home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / Languages / Python / python-14-src / Tools / scripts / h2py.py < prev    next >
Encoding:
Python Source  |  1997-01-17  |  4.8 KB  |  175 lines

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