diff options
Diffstat (limited to 'Tools/scripts/h2py.py')
-rwxr-xr-x | Tools/scripts/h2py.py | 80 |
1 files changed, 58 insertions, 22 deletions
diff --git a/Tools/scripts/h2py.py b/Tools/scripts/h2py.py index 3d7a851..db0dbd8 100755 --- a/Tools/scripts/h2py.py +++ b/Tools/scripts/h2py.py @@ -1,32 +1,43 @@ #! /usr/local/bin/python -# Read #define's from stdin and translate to Python code on stdout. -# Very primitive: non-#define's are ignored, as is anything that isn't -# valid Python as it stands. +# Read #define's and translate to Python code. +# Handle #include statements. +# Handle #define macros with one argument. +# Anything that isn't recognized or doesn't translate into valid +# Python is ignored. + +# Without filename arguments, acts as a filter. # If one or more filenames are given, output is written to corresponding # filenames in the local directory, translated to all uppercase, with # the extension replaced by ".py". + # By passing one or more options of the form "-i regular_expression" # you can specify additional strings to be ignored. This is useful # e.g. to ignore casts to u_long: simply specify "-i '(u_long)'". # XXX To do: # - turn trailing C comments into Python comments -# - turn C string quotes into Python comments # - turn C Boolean operators "&& || !" into Python "and or not" # - what to do about #if(def)? -# - what to do about #include? -# - what to do about macros with parameters? -# - reject definitions with semicolons in them +# - what to do about macros with multiple parameters? -import sys, regex, string, getopt, os +import sys, regex, regsub, string, getopt, os p_define = regex.compile('^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)[\t ]+') +p_macro = regex.compile( + '^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)(\([_a-zA-Z][_a-zA-Z0-9]*\))[\t ]+') + +p_include = regex.compile('^#[\t ]*include[\t ]+<\([a-zA-Z0-9_/\.]+\)') + p_comment = regex.compile('/\*\([^*]+\|\*+[^/]\)*\(\*+/\)?') ignores = [p_comment] +p_char = regex.compile("'\(\\\\.[^\\\\]*\|[^\\\\]\)'") + +filedict = {} + def main(): opts, args = getopt.getopt(sys.argv[1:], 'i:') for o, a in opts: @@ -47,40 +58,65 @@ def main(): outfile = outfile + '.py' outfp = open(outfile, 'w') outfp.write('# Generated by h2py from %s\n' % filename) + filedict = {} + if filename[:13] == '/usr/include/': + filedict[filename[13:]] = None process(fp, outfp) outfp.close() fp.close() -def process(fp, outfp): - env = {} +def process(fp, outfp, env = {}): lineno = 0 while 1: line = fp.readline() if not line: break lineno = lineno + 1 - # gobble up continuation lines - while line[-2:] == '\\\n': - nextline = fp.readline() - if not nextline: break - lineno = lineno + 1 - line = line + nextline n = p_define.match(line) if n >= 0: + # gobble up continuation lines + while line[-2:] == '\\\n': + nextline = fp.readline() + if not nextline: break + lineno = lineno + 1 + line = line + nextline name = p_define.group(1) body = line[n:] # replace ignored patterns by spaces for p in ignores: - while p.search(body) >= 0: - a, b = p.regs[0] - body = body[:a] + ' ' + body[b:] + body = regsub.gsub(p, ' ', body) + # replace char literals by ord(...) + body = regsub.gsub(p_char, 'ord(\\0)', body) stmt = '%s = %s\n' % (name, string.strip(body)) ok = 0 try: exec stmt in env - ok = 1 except: sys.stderr.write('Skipping: %s' % stmt) - if ok: + else: outfp.write(stmt) - + n =p_macro.match(line) + if n >= 0: + macro, arg = p_macro.group(1, 2) + body = line[n:] + for p in ignores: + body = regsub.gsub(p, ' ', body) + body = regsub.gsub(p_char, 'ord(\\0)', body) + stmt = 'def %s(%s): return %s\n' % (macro, arg, body) + try: + exec stmt in env + except: + sys.stderr.write('Skipping: %s' % stmt) + else: + outfp.write(stmt) + if p_include.match(line) >= 0: + regs = p_include.regs + a, b = regs[1] + filename = line[a:b] + if not filedict.has_key(filename): + filedict[filename] = None + outfp.write( + '\n# Included from %s\n' % filename) + inclfp = open('/usr/include/' + filename, 'r') + process(inclfp, outfp, env) main() + |