1#!/usr/bin/python3 2# 3# Copyright 2016-2022 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 * 13import argparse, copy, io, os, pdb, re, string, sys 14 15def prefix(depth): 16 return ' ' * depth 17 18openPat = re.compile('^\[open,(?P<attribs>refpage=.*)\]') 19ifdefPat = re.compile('^if(n|)def::(?P<condition>.*)\[(?P<text>.*)\]') 20endifPat = re.compile('^endif::(?P<condition>.*)\[\]') 21 22# Look for imbalanced block delimiters and conditionals 23# specFile - filename to examine 24def findBalance(specFile): 25 file = loadFile(specFile) 26 if file == None: 27 return 28 29 # blocks[] is a stack of nesting constructs, each of which is 30 # [ '--', line, None ] for a -- delimiter on line 31 # [ 'ifdef', line, condition] for an ifdef or ifndef on line 32 blocks = [] 33 34 line = 1 35 36 for str in file: 37 blockDepth = len(blocks) 38 if blockDepth > 0: 39 thisBlock = blocks[blockDepth-1] 40 blockType = thisBlock[0] 41 blockLine = thisBlock[1] 42 blockCondition = thisBlock[2] 43 else: 44 thisBlock = None 45 blockType = None 46 blockLine = None 47 blockCondition = None 48 49 if str.rstrip() == '--': 50 if (blockDepth > 0 and blockType == '--'): 51 print(prefix(blockDepth - 1) + 52 'Closing -- block opened @', blockLine, 53 '-> new block depth =', blockDepth - 1) 54 blocks.pop() 55 else: 56 print(prefix(blockDepth) + 57 'Opening -- block @', line, 58 '-> new block depth:', blockDepth + 1) 59 blocks.append([ '--', line, None ]) 60 line = line + 1 61 continue 62 63 matches = beginPat.search(str) 64 if matches != None: 65 # print('Matched [open pattern @', line, ':', str.rstrip()) 66 line = line + 1 67 continue 68 69 matches = ifdefPat.search(str) 70 if matches != None: 71 condition = matches.group('condition') 72 text = matches.group('text') 73 74 if text != '': 75 print('Matched self-closing if(n)def pattern @', line, 76 'condition:', condition, 'text:', text) 77 else: 78 print(prefix(blockDepth) + 79 'Opening if(n)def block @', line, 80 '-> new block depth =', blockDepth + 1, 81 'condition:', condition) 82 blocks.append([ 'ifdef', line, condition ]) 83 84 line = line + 1 85 continue 86 87 matches = endifPat.search(str) 88 if matches != None: 89 condition = matches.group('condition') 90 91 if (blockDepth > 0): 92 if blockType == 'ifdef': 93 # Try closing an ifdef/ifndef block 94 if blockCondition != condition: 95 print('** WARNING:', specFile, 96 'endif @', blockLine, 97 'block depth:', blockDepth, 98 'condition', condition, 99 'does not match ifdef/ifndef @', 100 blockLine, 'condition', blockCondition) 101 102 print(prefix(blockDepth - 1) + 103 'Closing endif block @', line, 104 '-> new block depth =', blockDepth - 1) 105 blocks.pop() 106 elif blockType == '--': 107 # An overlap! 108 print('** ERROR:', specFile, 'endif @', line, 109 'block depth:', blockDepth, 110 'overlaps -- block start @', blockLine) 111 else: 112 # Should never get here 113 print('** ERROR:', specFile, 114 'block depth:', blockDepth, 115 'unknown open block type:', blockType) 116 else: 117 # Unlikely error condition from bad markup 118 print('** ERROR:', specFile, 119 'block depth:', blockDepth, 120 'endif @', line, 'with no matching open block') 121 122 line = line + 1 123 continue 124 125 line = line + 1 126 127 blockDepth = len(blocks) 128 if blockDepth > 0: 129 print('** ERROR:', specFile, 'still in open block at EOF:', 130 'block depth =', blockDepth, 131 'block type:', blocks[blockDepth-1][0]) 132 133if __name__ == '__main__': 134 global genDict 135 genDict = {} 136 137 parser = argparse.ArgumentParser() 138 139 parser.add_argument('-diag', action='store', dest='diagFile', 140 help='Set the diagnostic file') 141 parser.add_argument('-warn', action='store', dest='warnFile', 142 help='Set the warning file') 143 parser.add_argument('-log', action='store', dest='logFile', 144 help='Set the log file for both diagnostics and warnings') 145 parser.add_argument('files', metavar='filename', nargs='*', 146 help='a filename to extract ref pages from') 147 parser.add_argument('--version', action='version', version='%(prog)s 1.0') 148 149 results = parser.parse_args() 150 151 setLogFile(True, True, results.logFile) 152 setLogFile(True, False, results.diagFile) 153 setLogFile(False, True, results.warnFile) 154 155 skipped = set() 156 for file in results.files: 157 findBalance(file) 158 159 if len(skipped) > 0: 160 print('Files containing skipped feature blocks:') 161 for file in sorted(skipped): 162 print('\t' + file) 163