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