home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / programacao / pythonwin / python.exe / H2PY.PY < prev    next >
Encoding:
Python Source  |  2002-11-23  |  5.8 KB  |  175 lines

  1. #! /usr/bin/env python
  2.  
  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.
  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".
  13.  
  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)'".
  17.  
  18. # XXX To do:
  19. # - turn trailing C comments into Python comments
  20. # - turn C Boolean operators "&& || !" into Python "and or not"
  21. # - what to do about #if(def)?
  22. # - what to do about macros with multiple parameters?
  23.  
  24. import sys, re, getopt, os
  25.  
  26. p_define = re.compile('^[\t ]*#[\t ]*define[\t ]+([a-zA-Z0-9_]+)[\t ]+')
  27.  
  28. p_macro = re.compile(
  29.   '^[\t ]*#[\t ]*define[\t ]+'
  30.   '([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+')
  31.  
  32. p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([a-zA-Z0-9_/\.]+)')
  33.  
  34. p_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?')
  35. p_cpp_comment = re.compile('//.*')
  36.  
  37. ignores = [p_comment, p_cpp_comment]
  38.  
  39. p_char = re.compile(r"'(\\.[^\\]*|[^\\])'")
  40.  
  41. p_hex = re.compile(r"0x([0-9a-fA-F]+)L?")
  42.  
  43. filedict = {}
  44. importable = {}
  45.  
  46. try:
  47.     searchdirs=os.environ['include'].split(';')
  48. except KeyError:
  49.     try:
  50.         searchdirs=os.environ['INCLUDE'].split(';')
  51.     except KeyError:
  52.         try:
  53.             if  sys.platform.find("beos") == 0:
  54.                 searchdirs=os.environ['BEINCLUDES'].split(';')
  55.             elif sys.platform.startswith("atheos"):
  56.                 searchdirs=os.environ['C_INCLUDE_PATH'].split(':')
  57.             else:
  58.                 raise KeyError
  59.         except KeyError:
  60.             searchdirs=['/usr/include']
  61.  
  62. def main():
  63.     global filedict
  64.     opts, args = getopt.getopt(sys.argv[1:], 'i:')
  65.     for o, a in opts:
  66.         if o == '-i':
  67.             ignores.append(re.compile(a))
  68.     if not args:
  69.         args = ['-']
  70.     for filename in args:
  71.         if filename == '-':
  72.             sys.stdout.write('# Generated by h2py from stdin\n')
  73.             process(sys.stdin, sys.stdout)
  74.         else:
  75.             fp = open(filename, 'r')
  76.             outfile = os.path.basename(filename)
  77.             i = outfile.rfind('.')
  78.             if i > 0: outfile = outfile[:i]
  79.             modname = outfile.upper()
  80.             outfile = modname + '.py'
  81.             outfp = open(outfile, 'w')
  82.             outfp.write('# Generated by h2py from %s\n' % filename)
  83.             filedict = {}
  84.             for dir in searchdirs:
  85.                 if filename[:len(dir)] == dir:
  86.                     filedict[filename[len(dir)+1:]] = None  # no '/' trailing
  87.                     importable[filename[len(dir)+1:]] = modname
  88.                     break
  89.             process(fp, outfp)
  90.             outfp.close()
  91.             fp.close()
  92.  
  93. def pytify(body):
  94.     # replace ignored patterns by spaces
  95.     for p in ignores:
  96.         body = p.sub(' ', body)
  97.     # replace char literals by ord(...)
  98.     body = p_char.sub('ord(\\0)', body)
  99.     # Compute negative hexadecimal constants
  100.     start = 0
  101.     UMAX = 2*(sys.maxint+1)
  102.     while 1:
  103.         m = p_hex.search(body, start)
  104.         if not m: break
  105.         s,e = m.span()
  106.         val = long(body[slice(*m.span(1))], 16)
  107.         if val > sys.maxint:
  108.             val -= UMAX
  109.             body = body[:s] + "(" + str(val) + ")" + body[e:]
  110.         start = s + 1
  111.     return body
  112.  
  113. def process(fp, outfp, env = {}):
  114.     lineno = 0
  115.     while 1:
  116.         line = fp.readline()
  117.         if not line: break
  118.         lineno = lineno + 1
  119.         match = p_define.match(line)
  120.         if match:
  121.             # gobble up continuation lines
  122.             while line[-2:] == '\\\n':
  123.                 nextline = fp.readline()
  124.                 if not nextline: break
  125.                 lineno = lineno + 1
  126.                 line = line + nextline
  127.             name = match.group(1)
  128.             body = line[match.end():]
  129.             body = pytify(body)
  130.             ok = 0
  131.             stmt = '%s = %s\n' % (name, body.strip())
  132.             try:
  133.                 exec stmt in env
  134.             except:
  135.                 sys.stderr.write('Skipping: %s' % stmt)
  136.             else:
  137.                 outfp.write(stmt)
  138.         match = p_macro.match(line)
  139.         if match:
  140.             macro, arg = match.group(1, 2)
  141.             body = line[match.end():]
  142.             body = pytify(body)
  143.             stmt = 'def %s(%s): return %s\n' % (macro, arg, body)
  144.             try:
  145.                 exec stmt in env
  146.             except:
  147.                 sys.stderr.write('Skipping: %s' % stmt)
  148.             else:
  149.                 outfp.write(stmt)
  150.         match = p_include.match(line)
  151.         if match:
  152.             regs = match.regs
  153.             a, b = regs[1]
  154.             filename = line[a:b]
  155.             if importable.has_key(filename):
  156.                 outfp.write('from %s import *\n' % importable[filename])
  157.             elif not filedict.has_key(filename):
  158.                 filedict[filename] = None
  159.                 inclfp = None
  160.                 for dir in searchdirs:
  161.                     try:
  162.                         inclfp = open(dir + '/' + filename)
  163.                         break
  164.                     except IOError:
  165.                         pass
  166.                 if inclfp:
  167.                     outfp.write(
  168.                             '\n# Included from %s\n' % filename)
  169.                     process(inclfp, outfp, env)
  170.                 else:
  171.                     sys.stderr.write('Warning - could not find file %s\n' %
  172.                                      filename)
  173.  
  174. main()
  175.