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