ยปCore Development>Code coverage>Tools/scripts/h2py.py

Python code coverage for Tools/scripts/h2py.py

#countcontent
1n/a#! /usr/bin/env python3
2n/a
3n/a# Read #define's and translate to Python code.
4n/a# Handle #include statements.
5n/a# Handle #define macros with one argument.
6n/a# Anything that isn't recognized or doesn't translate into valid
7n/a# Python is ignored.
8n/a
9n/a# Without filename arguments, acts as a filter.
10n/a# If one or more filenames are given, output is written to corresponding
11n/a# filenames in the local directory, translated to all uppercase, with
12n/a# the extension replaced by ".py".
13n/a
14n/a# By passing one or more options of the form "-i regular_expression"
15n/a# you can specify additional strings to be ignored. This is useful
16n/a# e.g. to ignore casts to u_long: simply specify "-i '(u_long)'".
17n/a
18n/a# XXX To do:
19n/a# - turn trailing C comments into Python comments
20n/a# - turn C Boolean operators "&& || !" into Python "and or not"
21n/a# - what to do about #if(def)?
22n/a# - what to do about macros with multiple parameters?
23n/a
24n/aimport sys, re, getopt, os
25n/a
26n/ap_define = re.compile(r'^[\t ]*#[\t ]*define[\t ]+([a-zA-Z0-9_]+)[\t ]+')
27n/a
28n/ap_macro = re.compile(
29n/a r'^[\t ]*#[\t ]*define[\t ]+'
30n/a r'([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+')
31n/a
32n/ap_include = re.compile(r'^[\t ]*#[\t ]*include[\t ]+<([^>\n]+)>')
33n/a
34n/ap_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?')
35n/ap_cpp_comment = re.compile('//.*')
36n/a
37n/aignores = [p_comment, p_cpp_comment]
38n/a
39n/ap_char = re.compile(r"'(\\.[^\\]*|[^\\])'")
40n/a
41n/ap_hex = re.compile(r"0x([0-9a-fA-F]+)L?")
42n/a
43n/afiledict = {}
44n/aimportable = {}
45n/a
46n/atry:
47n/a searchdirs=os.environ['include'].split(';')
48n/aexcept KeyError:
49n/a try:
50n/a searchdirs=os.environ['INCLUDE'].split(';')
51n/a except KeyError:
52n/a searchdirs=['/usr/include']
53n/a try:
54n/a searchdirs.insert(0, os.path.join('/usr/include',
55n/a os.environ['MULTIARCH']))
56n/a except KeyError:
57n/a pass
58n/a
59n/adef main():
60n/a global filedict
61n/a opts, args = getopt.getopt(sys.argv[1:], 'i:')
62n/a for o, a in opts:
63n/a if o == '-i':
64n/a ignores.append(re.compile(a))
65n/a if not args:
66n/a args = ['-']
67n/a for filename in args:
68n/a if filename == '-':
69n/a sys.stdout.write('# Generated by h2py from stdin\n')
70n/a process(sys.stdin, sys.stdout)
71n/a else:
72n/a fp = open(filename, 'r')
73n/a outfile = os.path.basename(filename)
74n/a i = outfile.rfind('.')
75n/a if i > 0: outfile = outfile[:i]
76n/a modname = outfile.upper()
77n/a outfile = modname + '.py'
78n/a outfp = open(outfile, 'w')
79n/a outfp.write('# Generated by h2py from %s\n' % filename)
80n/a filedict = {}
81n/a for dir in searchdirs:
82n/a if filename[:len(dir)] == dir:
83n/a filedict[filename[len(dir)+1:]] = None # no '/' trailing
84n/a importable[filename[len(dir)+1:]] = modname
85n/a break
86n/a process(fp, outfp)
87n/a outfp.close()
88n/a fp.close()
89n/a
90n/adef pytify(body):
91n/a # replace ignored patterns by spaces
92n/a for p in ignores:
93n/a body = p.sub(' ', body)
94n/a # replace char literals by ord(...)
95n/a body = p_char.sub("ord('\\1')", body)
96n/a # Compute negative hexadecimal constants
97n/a start = 0
98n/a UMAX = 2*(sys.maxsize+1)
99n/a while 1:
100n/a m = p_hex.search(body, start)
101n/a if not m: break
102n/a s,e = m.span()
103n/a val = int(body[slice(*m.span(1))], 16)
104n/a if val > sys.maxsize:
105n/a val -= UMAX
106n/a body = body[:s] + "(" + str(val) + ")" + body[e:]
107n/a start = s + 1
108n/a return body
109n/a
110n/adef process(fp, outfp, env = {}):
111n/a lineno = 0
112n/a while 1:
113n/a line = fp.readline()
114n/a if not line: break
115n/a lineno = lineno + 1
116n/a match = p_define.match(line)
117n/a if match:
118n/a # gobble up continuation lines
119n/a while line[-2:] == '\\\n':
120n/a nextline = fp.readline()
121n/a if not nextline: break
122n/a lineno = lineno + 1
123n/a line = line + nextline
124n/a name = match.group(1)
125n/a body = line[match.end():]
126n/a body = pytify(body)
127n/a ok = 0
128n/a stmt = '%s = %s\n' % (name, body.strip())
129n/a try:
130n/a exec(stmt, env)
131n/a except:
132n/a sys.stderr.write('Skipping: %s' % stmt)
133n/a else:
134n/a outfp.write(stmt)
135n/a match = p_macro.match(line)
136n/a if match:
137n/a macro, arg = match.group(1, 2)
138n/a body = line[match.end():]
139n/a body = pytify(body)
140n/a stmt = 'def %s(%s): return %s\n' % (macro, arg, body)
141n/a try:
142n/a exec(stmt, env)
143n/a except:
144n/a sys.stderr.write('Skipping: %s' % stmt)
145n/a else:
146n/a outfp.write(stmt)
147n/a match = p_include.match(line)
148n/a if match:
149n/a regs = match.regs
150n/a a, b = regs[1]
151n/a filename = line[a:b]
152n/a if filename in importable:
153n/a outfp.write('from %s import *\n' % importable[filename])
154n/a elif filename not in filedict:
155n/a filedict[filename] = None
156n/a inclfp = None
157n/a for dir in searchdirs:
158n/a try:
159n/a inclfp = open(dir + '/' + filename)
160n/a break
161n/a except IOError:
162n/a pass
163n/a if inclfp:
164n/a outfp.write(
165n/a '\n# Included from %s\n' % filename)
166n/a process(inclfp, outfp, env)
167n/a else:
168n/a sys.stderr.write('Warning - could not find file %s\n' %
169n/a filename)
170n/a
171n/aif __name__ == '__main__':
172n/a main()