Guido van Rossum | 41ffccb | 1993-04-01 20:50:35 +0000 | [diff] [blame] | 1 | #! /usr/local/bin/python |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 2 | |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 3 | # Read #define's and translate to Python code. |
| 4 | # Handle #include statements. |
| 5 | # Handle #define macros with one argument. |
| 6 | # Anything that isn't recognized or doesn't translate into valid |
| 7 | # Python is ignored. |
| 8 | |
| 9 | # Without filename arguments, acts as a filter. |
Guido van Rossum | 09336f9 | 1994-05-03 14:37:30 +0000 | [diff] [blame] | 10 | # If one or more filenames are given, output is written to corresponding |
| 11 | # filenames in the local directory, translated to all uppercase, with |
| 12 | # the extension replaced by ".py". |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 13 | |
Guido van Rossum | 01f5f62 | 1994-05-17 09:05:54 +0000 | [diff] [blame] | 14 | # By passing one or more options of the form "-i regular_expression" |
| 15 | # you can specify additional strings to be ignored. This is useful |
| 16 | # e.g. to ignore casts to u_long: simply specify "-i '(u_long)'". |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 17 | |
| 18 | # XXX To do: |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 19 | # - turn trailing C comments into Python comments |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 20 | # - turn C Boolean operators "&& || !" into Python "and or not" |
| 21 | # - what to do about #if(def)? |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 22 | # - what to do about macros with multiple parameters? |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 23 | |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 24 | import sys, regex, regsub, string, getopt, os |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 25 | |
| 26 | p_define = regex.compile('^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)[\t ]+') |
| 27 | |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 28 | p_macro = regex.compile( |
| 29 | '^#[\t ]*define[\t ]+\([a-zA-Z0-9_]+\)(\([_a-zA-Z][_a-zA-Z0-9]*\))[\t ]+') |
| 30 | |
| 31 | p_include = regex.compile('^#[\t ]*include[\t ]+<\([a-zA-Z0-9_/\.]+\)') |
| 32 | |
Guido van Rossum | 047979e | 1992-06-05 15:13:53 +0000 | [diff] [blame] | 33 | p_comment = regex.compile('/\*\([^*]+\|\*+[^/]\)*\(\*+/\)?') |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 34 | |
Guido van Rossum | 01f5f62 | 1994-05-17 09:05:54 +0000 | [diff] [blame] | 35 | ignores = [p_comment] |
| 36 | |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 37 | p_char = regex.compile("'\(\\\\.[^\\\\]*\|[^\\\\]\)'") |
| 38 | |
| 39 | filedict = {} |
| 40 | |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 41 | def main(): |
Guido van Rossum | 01f5f62 | 1994-05-17 09:05:54 +0000 | [diff] [blame] | 42 | opts, args = getopt.getopt(sys.argv[1:], 'i:') |
| 43 | for o, a in opts: |
| 44 | if o == '-i': |
| 45 | ignores.append(regex.compile(a)) |
Guido van Rossum | 09336f9 | 1994-05-03 14:37:30 +0000 | [diff] [blame] | 46 | if not args: |
| 47 | args = ['-'] |
| 48 | for filename in args: |
| 49 | if filename == '-': |
| 50 | sys.stdout.write('# Generated by h2py from stdin\n') |
| 51 | process(sys.stdin, sys.stdout) |
| 52 | else: |
| 53 | fp = open(filename, 'r') |
| 54 | outfile = os.path.basename(filename) |
| 55 | i = string.rfind(outfile, '.') |
| 56 | if i > 0: outfile = outfile[:i] |
| 57 | outfile = string.upper(outfile) |
| 58 | outfile = outfile + '.py' |
| 59 | outfp = open(outfile, 'w') |
| 60 | outfp.write('# Generated by h2py from %s\n' % filename) |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 61 | filedict = {} |
| 62 | if filename[:13] == '/usr/include/': |
| 63 | filedict[filename[13:]] = None |
Guido van Rossum | 09336f9 | 1994-05-03 14:37:30 +0000 | [diff] [blame] | 64 | process(fp, outfp) |
| 65 | outfp.close() |
| 66 | fp.close() |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 67 | |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 68 | def process(fp, outfp, env = {}): |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 69 | lineno = 0 |
| 70 | while 1: |
| 71 | line = fp.readline() |
| 72 | if not line: break |
| 73 | lineno = lineno + 1 |
Guido van Rossum | 01f5f62 | 1994-05-17 09:05:54 +0000 | [diff] [blame] | 74 | n = p_define.match(line) |
| 75 | if n >= 0: |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 76 | # gobble up continuation lines |
| 77 | while line[-2:] == '\\\n': |
| 78 | nextline = fp.readline() |
| 79 | if not nextline: break |
| 80 | lineno = lineno + 1 |
| 81 | line = line + nextline |
Guido van Rossum | 01f5f62 | 1994-05-17 09:05:54 +0000 | [diff] [blame] | 82 | name = p_define.group(1) |
| 83 | body = line[n:] |
| 84 | # replace ignored patterns by spaces |
| 85 | for p in ignores: |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 86 | body = regsub.gsub(p, ' ', body) |
| 87 | # replace char literals by ord(...) |
| 88 | body = regsub.gsub(p_char, 'ord(\\0)', body) |
Guido van Rossum | 09336f9 | 1994-05-03 14:37:30 +0000 | [diff] [blame] | 89 | stmt = '%s = %s\n' % (name, string.strip(body)) |
| 90 | ok = 0 |
| 91 | try: |
| 92 | exec stmt in env |
Guido van Rossum | 09336f9 | 1994-05-03 14:37:30 +0000 | [diff] [blame] | 93 | except: |
| 94 | sys.stderr.write('Skipping: %s' % stmt) |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 95 | else: |
Guido van Rossum | 09336f9 | 1994-05-03 14:37:30 +0000 | [diff] [blame] | 96 | outfp.write(stmt) |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 97 | n =p_macro.match(line) |
| 98 | if n >= 0: |
| 99 | macro, arg = p_macro.group(1, 2) |
| 100 | body = line[n:] |
| 101 | for p in ignores: |
| 102 | body = regsub.gsub(p, ' ', body) |
| 103 | body = regsub.gsub(p_char, 'ord(\\0)', body) |
| 104 | stmt = 'def %s(%s): return %s\n' % (macro, arg, body) |
| 105 | try: |
| 106 | exec stmt in env |
| 107 | except: |
| 108 | sys.stderr.write('Skipping: %s' % stmt) |
| 109 | else: |
| 110 | outfp.write(stmt) |
| 111 | if p_include.match(line) >= 0: |
| 112 | regs = p_include.regs |
| 113 | a, b = regs[1] |
| 114 | filename = line[a:b] |
| 115 | if not filedict.has_key(filename): |
| 116 | filedict[filename] = None |
| 117 | outfp.write( |
| 118 | '\n# Included from %s\n' % filename) |
| 119 | inclfp = open('/usr/include/' + filename, 'r') |
| 120 | process(inclfp, outfp, env) |
Guido van Rossum | 2ba9f30 | 1992-03-02 16:20:32 +0000 | [diff] [blame] | 121 | main() |
Guido van Rossum | 07c9645 | 1994-10-03 16:45:35 +0000 | [diff] [blame^] | 122 | |