home *** CD-ROM | disk | FTP | other *** search
- #! /usr/bin/env python
-
- # 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 Boolean operators "&& || !" into Python "and or not"
- # - what to do about #if(def)?
- # - what to do about macros with multiple parameters?
-
- import sys, re, getopt, os
-
- p_define = re.compile('^[\t ]*#[\t ]*define[\t ]+([a-zA-Z0-9_]+)[\t ]+')
-
- p_macro = re.compile(
- '^[\t ]*#[\t ]*define[\t ]+'
- '([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+')
-
- p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([a-zA-Z0-9_/\.]+)')
-
- p_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?')
- p_cpp_comment = re.compile('//.*')
-
- ignores = [p_comment, p_cpp_comment]
-
- p_char = re.compile(r"'(\\.[^\\]*|[^\\])'")
-
- filedict = {}
- importable = {}
-
- try:
- searchdirs=os.environ['include'].split(';')
- except KeyError:
- try:
- searchdirs=os.environ['INCLUDE'].split(';')
- except KeyError:
- try:
- if sys.platform.find("beos") == 0:
- searchdirs=os.environ['BEINCLUDES'].split(';')
- else:
- raise KeyError
- except KeyError:
- searchdirs=['/usr/include']
-
- def main():
- global filedict
- opts, args = getopt.getopt(sys.argv[1:], 'i:')
- for o, a in opts:
- if o == '-i':
- ignores.append(re.compile(a))
- if not args:
- args = ['-']
- for filename in args:
- if filename == '-':
- sys.stdout.write('# Generated by h2py from stdin\n')
- process(sys.stdin, sys.stdout)
- else:
- fp = open(filename, 'r')
- outfile = os.path.basename(filename)
- i = outfile.rfind('.')
- if i > 0: outfile = outfile[:i]
- modname = outfile.upper()
- outfile = modname + '.py'
- outfp = open(outfile, 'w')
- outfp.write('# Generated by h2py from %s\n' % filename)
- filedict = {}
- for dir in searchdirs:
- if filename[:len(dir)] == dir:
- filedict[filename[len(dir)+1:]] = None # no '/' trailing
- importable[filename[len(dir)+1:]] = modname
- break
- process(fp, outfp)
- outfp.close()
- fp.close()
-
- def process(fp, outfp, env = {}):
- lineno = 0
- while 1:
- line = fp.readline()
- if not line: break
- lineno = lineno + 1
- match = p_define.match(line)
- if match:
- # gobble up continuation lines
- while line[-2:] == '\\\n':
- nextline = fp.readline()
- if not nextline: break
- lineno = lineno + 1
- line = line + nextline
- name = match.group(1)
- body = line[match.end():]
- # replace ignored patterns by spaces
- for p in ignores:
- body = p.sub(' ', body)
- # replace char literals by ord(...)
- body = p_char.sub('ord(\\0)', body)
- stmt = '%s = %s\n' % (name, body.strip())
- ok = 0
- try:
- exec stmt in env
- except:
- sys.stderr.write('Skipping: %s' % stmt)
- else:
- outfp.write(stmt)
- match = p_macro.match(line)
- if match:
- macro, arg = match.group(1, 2)
- body = line[match.end():]
- for p in ignores:
- body = p.sub(' ', body)
- body = p_char.sub('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)
- match = p_include.match(line)
- if match:
- regs = match.regs
- a, b = regs[1]
- filename = line[a:b]
- if importable.has_key(filename):
- outfp.write('from %s import *\n' % importable[filename])
- elif not filedict.has_key(filename):
- filedict[filename] = None
- inclfp = None
- for dir in searchdirs:
- try:
- inclfp = open(dir + '/' + filename)
- break
- except IOError:
- pass
- if inclfp:
- outfp.write(
- '\n# Included from %s\n' % filename)
- process(inclfp, outfp, env)
- else:
- sys.stderr.write('Warning - could not find file %s\n' %
- filename)
-
- main()
-