1#!/usr/bin/python3 2# 3# Copyright 2016-2023 The Khronos Group Inc. 4# 5# SPDX-License-Identifier: Apache-2.0 6 7# fixupRef.py - replace old // refBegin .. // refEnd syntax with new 8# open block syntax 9# 10# Usage: fixupRef.py [-outdir path] [-overwrite] files 11 12from reflib import * 13from vkapi import * 14import argparse, copy, io, os, pdb, re, string, sys 15 16# Return 'None' for None, the string otherwise 17def noneStr(str): 18 if str == None: 19 return '(None)' 20 else: 21 return str 22 23# Escape single quotes in a string for asciidoc 24def escapeQuote(str): 25 return str.replace("'", "\'") 26 27# Start a refpage open block 28def openBlock(pi, fp): 29 if pi.refs != '': 30 print("[open,refpage='" + pi.name + 31 "',desc='" + pi.desc + 32 "',type='" + pi.type + 33 "',xrefs='" + pi.refs + "']", 34 file=fp) 35 else: 36 print("[open,refpage='" + pi.name + 37 "',desc='" + pi.desc + 38 "',type='" + pi.type + "']", 39 file=fp) 40 print('--', file=fp) 41 42# End a refpage open block 43def closeBlock(pi, fp): 44 print('--', file=fp) 45 # Just for finding block ends while debugging 46 # print("// end [open,refpage='" + pi.name + "']", file=fp) 47 48# Replace old // refBegin .. // refEnd references in an asciidoc 49# file with open blocks, per # ??? . 50# specFile - filename to extract from 51# outDir - output directory to write updated file to, if not overwritten 52# overwrite - True if the file should be overwritten in place 53# skipped - set of filenames containing commands which were not 54# rewritten with open blocks (e.g. enums). Updated in place. 55def replaceRef(specFile, outDir, overwrite = False, skipped = set()): 56 file = loadFile(specFile) 57 if file == None: 58 return 59 60 # Save the path to this file for later use in rewriting relative includes 61 specDir = os.path.dirname(os.path.abspath(specFile)) 62 63 pageMap = findRefs(file) 64 logDiag(specFile + ': found', len(pageMap.keys()), 'potential pages') 65 66 sys.stderr.flush() 67 68 # Fix up references in pageMap 69 fixupRefs(pageMap, specFile, file) 70 71 # Map the page info dictionary into a dictionary of actions 72 # keyed by line number they are performed on/after: 73 # 'action' : 'begin' or 'end'. What to do on a refBegin or refEnd line 74 # 'replace': True if this line needs to be replaced 75 # 'name' : Name of the ref page being defined 76 # 'desc' : One-line description of the ref page being defined 77 # 'type' : Type of the ref page being defined, 'structs', 'protos', etc. 78 # 'refs' : Space-separated string of cross-referenced pages 79 80 actions = { } 81 82 for name in pageMap.keys(): 83 pi = pageMap[name] 84 85 # Cleanup parameters for output 86 pi.name = noneStr(pi.name) 87 pi.desc = escapeQuote(noneStr(pi.desc)) 88 89 if pi.extractPage: 90 if (file[pi.begin][0:11] == '// refBegin'): 91 # Replace line 92 actions[pi.begin] = { 93 'action' : 'begin', 94 'replace' : True, 95 'pageinfo' : pi 96 } 97 else: 98 # Insert line 99 actions[pi.begin] = { 100 'action' : 'begin', 101 'replace' : False, 102 'pageinfo' : pi 103 } 104 105 if (file[pi.end][0:9] == '// refEnd'): 106 # Replace line 107 actions[pi.end] = { 108 'action' : 'end', 109 'replace' : True, 110 'pageinfo' : pi 111 } 112 else: 113 # Insert line 114 actions[pi.end] = { 115 'action' : 'end', 116 'replace' : False, 117 'pageinfo' : pi 118 } 119 else: 120 logWarn('Skipping replacement for', pi.name, 'at', specFile, 121 'line', pi.begin) 122 print('Skipping replacement for', pi.name, 'at', specFile, 123 'line', pi.begin) 124 printPageInfo(pi, file) 125 skipped.add(specFile) 126 127 if overwrite: 128 pageName = specFile 129 else: 130 pageName = outDir + '/' + os.path.basename(specFile) 131 132 fp = open(pageName, 'w', encoding='utf-8') 133 134 line = 0 135 for text in file: 136 if line in actions.keys(): 137 action = actions[line]['action'] 138 replace = actions[line]['replace'] 139 pi = actions[line]['pageinfo'] 140 141 logDiag('ACTION:', action, 'REPLACE:', replace, 'at line', line) 142 logDiag('PageInfo of action:') 143 printPageInfo(pi, file) 144 145 if action == 'begin': 146 openBlock(pi, fp) 147 if not replace: 148 print(text, file=fp, end='') 149 elif action == 'end': 150 if not replace: 151 print(text, file=fp, end='') 152 closeBlock(pi, fp) 153 else: 154 print('ERROR: unrecognized action:', action, 'in', 155 specFile, 'at line', line) 156 print(text, file=fp, end='') 157 else: 158 print(text, file=fp, end='') 159 line = line + 1 160 161 fp.close() 162 163 #for line in sorted(actions.keys()): 164 # action = actions[line] 165 # print('action at line', line, '\t', 166 # action[0], action[1], action[2]) 167 168if __name__ == '__main__': 169 global genDict 170 genDict = {} 171 172 parser = argparse.ArgumentParser() 173 174 parser.add_argument('-diag', action='store', dest='diagFile', 175 help='Set the diagnostic file') 176 parser.add_argument('-warn', action='store', dest='warnFile', 177 help='Set the warning file') 178 parser.add_argument('-log', action='store', dest='logFile', 179 help='Set the log file for both diagnostics and warnings') 180 parser.add_argument('-outdir', action='store', dest='outDir', 181 default='out', 182 help='Set the base directory in which pages are generated') 183 parser.add_argument('-overwrite', action='store_true', 184 help='Overwrite input filenames instead of writing different output filenames') 185 parser.add_argument('files', metavar='filename', nargs='*', 186 help='a filename to extract ref pages from') 187 parser.add_argument('--version', action='version', version='%(prog)s 1.0') 188 189 results = parser.parse_args() 190 191 setLogFile(True, True, results.logFile) 192 setLogFile(True, False, results.diagFile) 193 setLogFile(False, True, results.warnFile) 194 195 skipped = set() 196 for file in results.files: 197 replaceRef(file, results.outDir, results.overwrite, skipped) 198 199 if len(skipped) > 0: 200 print('Files containing skipped feature blocks:') 201 for file in sorted(skipped): 202 print('\t' + file) 203