#!/usr/bin/python3 # # Copyright 2016-2024 The Khronos Group Inc. # # SPDX-License-Identifier: Apache-2.0 # Retroactively insert markup in show both 1.1 core features and KHR # extensions they were promoted from. # Usage: promote.py [-overwrite] [-out dir] [-suffix str] files # -overwrite updates in place (can be risky, make sure there are backups) # -out specifies directory to create output file in, default 'out' # -suffix specifies suffix to add to output files, default '' # files are asciidoc source files from the Vulkan spec to reflow. # For error and file-loading interfaces only import argparse, copy, os, pdb, re, string, sys from reflib import * from promoted import * global anchor anchor = 0 def anchorname(anchor): return 'promoted-' + str(anchor) def printanchor(fp): # Anchor index for navigation global anchor print('[[' + anchorname(anchor) + ']]', file=fp) print('This anchor:', anchorname(anchor), file=fp) print('<<' + anchorname(anchor+1) + ', OINK>>', file=fp) anchor = anchor + 1 # promote a core interface and include the extension it was promoted from # line - matching line with 1.1 interface # type - 'protos', 'structs', 'flags', 'enums' # name - interface name # extension - name of extension interface was promoted from # fp - output filename def promote(line, type, name, extension, fp): if type == 'protos': # printanchor(fp) print('ifdef::VK_VERSION_1_1[]', file=fp) print(line, file=fp, end='') print('endif::VK_VERSION_1_1[]', file=fp) print('', file=fp) print('ifdef::VK_VERSION_1_1+' + extension + '[or the equivalent command]', file=fp) print('', file=fp) print('ifdef::' + extension + '[]', file=fp) print('include::../api/' + type + '/' + name + 'KHR.adoc[]', file=fp) print('endif::' + extension + '[]', file=fp) del promoted[name] elif type == 'structs' or type == 'enums' or type == 'flags' or type == 'handles': # printanchor(fp) print(line, file=fp, end='') print('', file=fp) print('ifdef::' + extension + '[]', file=fp) print('or the equivalent', file=fp) print('', file=fp) print('include::../api/' + type + '/' + name + 'KHR.adoc[]', file=fp) print('endif::' + extension + '[]', file=fp) del promoted[name] else: logWarn('Unrecognized promoted type', type, 'for interface', name) print(line, file=fp, end='') def promoteFile(filename, args): logDiag('promote: filename', filename) lines = loadFile(filename) if (lines == None): return # Output file handle and promote object for this file. There are no race # conditions on overwriting the input, but it is not recommended unless # you have backing store such as git. if args.overwrite: outFilename = filename else: outFilename = args.outDir + '/' + os.path.basename(filename) + args.suffix try: fp = open(outFilename, 'w', encoding='utf8') True except: logWarn('Cannot open output file', filename, ':', sys.exc_info()[0]) return None lineno = 0 for line in lines: lineno = lineno + 1 matches = includePat.search(line) if matches != None: type = matches.group('type') name = matches.group('name') if name in promoted: extension = promoted[name]['extension'] if extension: # Promote core interface promote(line, type, name, promoted[name]['extension'], fp) continue # Fallthrough print(line, file=fp, end='') fp.close() def promoteAllAdocFiles(folder_to_promote, args): for root, subdirs, files in os.walk(folder_to_promote): for file in files: if file.endswith(".adoc"): file_path = os.path.join(root, file) promoteFile(file_path, args) for subdir in subdirs: sub_folder = os.path.join(root, subdir) print('Sub-folder = %s' % sub_folder) if not (subdir.lower() == "scripts") and not (subdir.lower() == "style"): print(' Parsing = %s' % sub_folder) promoteAllAdocFiles(sub_folder, args) else: print(' Skipping = %s' % sub_folder) # Patterns used to recognize interesting lines in an asciidoc source file. # These patterns are only compiled once. if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-diag', action='store', dest='diagFile', help='Set the diagnostic file') parser.add_argument('-warn', action='store', dest='warnFile', help='Set the warning file') parser.add_argument('-log', action='store', dest='logFile', help='Set the log file for both diagnostics and warnings') parser.add_argument('-overwrite', action='store_true', help='Overwrite input filenames instead of writing different output filenames') parser.add_argument('-out', action='store', dest='outDir', default='out', help='Set the output directory in which updated files are generated (default: out)') parser.add_argument('-suffix', action='store', dest='suffix', default='', help='Set the suffix added to updated file names (default: none)') parser.add_argument('files', metavar='filename', nargs='*', help='a filename to promote text in') parser.add_argument('--version', action='version', version='%(prog)s 1.0') args = parser.parse_args() setLogFile(True, True, args.logFile) setLogFile(True, False, args.diagFile) setLogFile(False, True, args.warnFile) if args.overwrite: logWarn('promote.py: will overwrite all input files') # If no files are specified, promote the entire specification chapters folder if len(args.files) == 0: folder_to_promote = os.getcwd() folder_to_promote += '/chapters' promoteAllAdocFiles(folder_to_promote, args) else: for file in args.files: promoteFile(file, args) print('At end, promoted interfaces remaining:') for key in promoted: if promoted[key]['extension'] != None: print('\t' + key)