Examples - h2py.py
Jump to navigation
Jump to search
Transliterate C Include Files into Python Code
#!/usr/bin/env python # # $Id:$ # #------------------------------------------------------------------------------- """ 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 os, re, sys, getopt #------------------------------------------------------------------------------- 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 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) #------------------------------------------------------------------------------- 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() #------------------------------------------------------------------------------- if __name__ == "__main__": main(sys.argv[1:]) #-------------------------------------------------------------------------------
For example: Convert /usr/include/sys/fcntl.h
$ cat fcntlh.py # Generated by h2py from /usr/include/sys/fcntl.h _FOPEN = (-1) _FREAD = 0x0001 _FWRITE = 0x0002 _FAPPEND = 0x0008 _FMARK = 0x0010 _FDEFER = 0x0020 _FASYNC = 0x0040 _FSHLOCK = 0x0080 _FEXLOCK = 0x0100 _FCREAT = 0x0200 _FTRUNC = 0x0400 _FEXCL = 0x0800 _FNBIO = 0x1000 _FSYNC = 0x2000 _FNONBLOCK = 0x4000 _FNDELAY = _FNONBLOCK _FNOCTTY = 0x8000 O_RDONLY = 0 O_WRONLY = 1 O_RDWR = 2 O_APPEND = _FAPPEND O_CREAT = _FCREAT O_TRUNC = _FTRUNC O_EXCL = _FEXCL O_NONBLOCK = _FNONBLOCK O_NOCTTY = _FNOCTTY _FBINARY = 0x10000 _FTEXT = 0x20000 _FNOINHERIT = 0x40000 O_BINARY = _FBINARY O_TEXT = _FTEXT O_NOINHERIT = _FNOINHERIT _O_RDONLY = O_RDONLY _O_WRONLY = O_WRONLY _O_RDWR = O_RDWR _O_APPEND = O_APPEND _O_CREAT = O_CREAT _O_TRUNC = O_TRUNC _O_EXCL = O_EXCL _O_TEXT = O_TEXT _O_BINARY = O_BINARY _O_RAW = O_BINARY _O_NOINHERIT = O_NOINHERIT O_SYNC = _FSYNC FAPPEND = _FAPPEND FSYNC = _FSYNC FASYNC = _FASYNC FNBIO = _FNBIO FNONBIO = _FNONBLOCK FNDELAY = _FNDELAY FREAD = _FREAD FWRITE = _FWRITE FMARK = _FMARK FDEFER = _FDEFER FSHLOCK = _FSHLOCK FEXLOCK = _FEXLOCK FOPEN = _FOPEN FCREAT = _FCREAT FTRUNC = _FTRUNC FEXCL = _FEXCL FNOCTTY = _FNOCTTY FD_CLOEXEC = 1 F_DUPFD = 0 F_GETFD = 1 F_SETFD = 2 F_GETFL = 3 F_SETFL = 4 F_GETOWN = 5 F_SETOWN = 6 F_GETLK = 7 F_SETLK = 8 F_SETLKW = 9 F_RGETLK = 10 F_RSETLK = 11 F_CNVT = 12 F_RSETLKW = 13 F_RDLCK = 1 F_WRLCK = 2 F_UNLCK = 3 F_UNLKSYS = 4 # Included from sys/types.h # Included from sys/stat.h _S_IFMT = 0170000 _S_IFDIR = 0040000 _S_IFCHR = 0020000 _S_IFIFO = 0010000 _S_IFREG = 0100000 _S_IREAD = 0000400 _S_IWRITE = 0000200 _S_IEXEC = 0000100 S_IFMT = _S_IFMT S_IFDIR = _S_IFDIR S_IFCHR = _S_IFCHR S_IFREG = _S_IFREG S_IREAD = _S_IREAD S_IWRITE = _S_IWRITE S_IEXEC = _S_IEXEC