• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2#
3# Copyright (c) 2016-2018 The Khronos Group Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Retroactively insert markup in show both 1.1 core features and KHR
18# extensions they were promoted from.
19
20# Usage: promote.py [-overwrite] [-out dir] [-suffix str] files
21#   -overwrite updates in place (can be risky, make sure there are backups)
22#   -out specifies directory to create output file in, default 'out'
23#   -suffix specifies suffix to add to output files, default ''
24#   files are asciidoc source files from the Vulkan spec to reflow.
25
26# For error and file-loading interfaces only
27import argparse, copy, os, pdb, re, string, sys
28from reflib import *
29from promoted import *
30
31global anchor
32anchor = 0
33
34def anchorname(anchor):
35    return 'promoted-' + str(anchor)
36
37def printanchor(fp):
38    # Anchor index for navigation
39    global anchor
40
41    print('[[' + anchorname(anchor) + ']]', file=fp)
42    print('This anchor:', anchorname(anchor), file=fp)
43    print('<<' + anchorname(anchor+1) + ', OINK>>', file=fp)
44    anchor = anchor + 1
45
46# promote a core interface and include the extension it was promoted from
47#   line - matching line with 1.1 interface
48#   type - 'protos', 'structs', 'flags', 'enums'
49#   name - interface name
50#   extension - name of extension interface was promoted from
51#   fp - output filename
52def promote(line, type, name, extension, fp):
53    if type == 'protos':
54        # printanchor(fp)
55        print('ifdef::VK_VERSION_1_1[]', file=fp)
56        print(line, file=fp, end='')
57        print('endif::VK_VERSION_1_1[]', file=fp)
58        print('', file=fp)
59        print('ifdef::VK_VERSION_1_1+' + extension +
60              '[or the equivalent command]', file=fp)
61        print('', file=fp)
62        print('ifdef::' + extension + '[]', file=fp)
63        print('include::../api/' + type + '/' + name + 'KHR.txt[]', file=fp)
64        print('endif::' + extension + '[]', file=fp)
65        del promoted[name]
66    elif type == 'structs' or type == 'enums' or type == 'flags' or type == 'handles':
67        # printanchor(fp)
68        print(line, file=fp, end='')
69        print('', file=fp)
70        print('ifdef::' + extension + '[]', file=fp)
71        print('or the equivalent', file=fp)
72        print('', file=fp)
73        print('include::../api/' + type + '/' + name + 'KHR.txt[]', file=fp)
74        print('endif::' + extension + '[]', file=fp)
75        del promoted[name]
76    else:
77        logWarn('Unrecognized promoted type', type, 'for interface', name)
78        print(line, file=fp, end='')
79
80
81def promoteFile(filename, args):
82    logDiag('promote: filename', filename)
83
84    lines = loadFile(filename)
85    if (lines == None):
86        return
87
88    # Output file handle and promote object for this file. There are no race
89    # conditions on overwriting the input, but it's not recommended unless
90    # you have backing store such as git.
91
92    if args.overwrite:
93        outFilename = filename
94    else:
95        outFilename = args.outDir + '/' + os.path.basename(filename) + args.suffix
96
97    try:
98        fp = open(outFilename, 'w', encoding='utf8')
99        True
100    except:
101        logWarn('Cannot open output file', filename, ':', sys.exc_info()[0])
102        return None
103
104    lineno = 0
105    for line in lines:
106        lineno = lineno + 1
107
108        matches = includePat.search(line)
109        if matches != None:
110            type = matches.group('type')
111            name = matches.group('name')
112            if name in promoted:
113                extension = promoted[name]['extension']
114                if extension:
115                    # Promote core interface
116                    promote(line, type, name, promoted[name]['extension'], fp)
117                    continue
118        # Fallthrough
119        print(line, file=fp, end='')
120
121    fp.close()
122
123def promoteAllAdocFiles(folder_to_promote, args):
124    for root, subdirs, files in os.walk(folder_to_promote):
125        for file in files:
126            if file.endswith(".txt"):
127                file_path = os.path.join(root, file)
128                promoteFile(file_path, args)
129        for subdir in subdirs:
130            sub_folder = os.path.join(root, subdir)
131            print('Sub-folder = %s' % sub_folder)
132            if not (subdir.lower() == "scripts") and not (subdir.lower() == "style"):
133                print('   Parsing = %s' % sub_folder)
134                promoteAllAdocFiles(sub_folder, args)
135            else:
136                print('   Skipping = %s' % sub_folder)
137
138# Patterns used to recognize interesting lines in an asciidoc source file.
139# These patterns are only compiled once.
140
141if __name__ == '__main__':
142    parser = argparse.ArgumentParser()
143
144    parser.add_argument('-diag', action='store', dest='diagFile',
145                        help='Set the diagnostic file')
146    parser.add_argument('-warn', action='store', dest='warnFile',
147                        help='Set the warning file')
148    parser.add_argument('-log', action='store', dest='logFile',
149                        help='Set the log file for both diagnostics and warnings')
150    parser.add_argument('-overwrite', action='store_true',
151                        help='Overwrite input filenames instead of writing different output filenames')
152    parser.add_argument('-out', action='store', dest='outDir',
153                        default='out',
154                        help='Set the output directory in which updated files are generated (default: out)')
155    parser.add_argument('-suffix', action='store', dest='suffix',
156                        default='',
157                        help='Set the suffix added to updated file names (default: none)')
158    parser.add_argument('files', metavar='filename', nargs='*',
159                        help='a filename to promote text in')
160    parser.add_argument('--version', action='version', version='%(prog)s 1.0')
161
162    args = parser.parse_args()
163
164    setLogFile(True,  True, args.logFile)
165    setLogFile(True, False, args.diagFile)
166    setLogFile(False, True, args.warnFile)
167
168    if args.overwrite:
169        logWarn('promote.py: will overwrite all input files')
170
171    # If no files are specified, promote the entire specification chapters folder
172    if len(args.files) == 0:
173        folder_to_promote = os.getcwd()
174        folder_to_promote += '/chapters'
175        promoteAllAdocFiles(folder_to_promote, args)
176    else:
177        for file in args.files:
178            promoteFile(file, args)
179
180    print('At end, promoted interfaces remaining:')
181    for key in promoted:
182        if promoted[key]['extension'] != None:
183            print('\t' + key)
184