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