| 
									
										
										
										
											2010-03-11 22:53:45 +00:00
										 |  |  | #! /usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | # 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. | 
					
						
							| 
									
										
										
										
											1994-05-03 14:37:30 +00:00
										 |  |  | # 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". | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-05-17 09:05:54 +00:00
										 |  |  | # 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)'". | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # 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)? | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | # - what to do about macros with multiple parameters? | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | import sys, re, getopt, os | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | p_define = re.compile('^[\t ]*#[\t ]*define[\t ]+([a-zA-Z0-9_]+)[\t ]+') | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | p_macro = re.compile( | 
					
						
							| 
									
										
										
										
											1996-08-22 23:12:23 +00:00
										 |  |  |   '^[\t ]*#[\t ]*define[\t ]+' | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |   '([a-zA-Z0-9_]+)\(([_a-zA-Z][_a-zA-Z0-9]*)\)[\t ]+') | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | p_include = re.compile('^[\t ]*#[\t ]*include[\t ]+<([a-zA-Z0-9_/\.]+)') | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | p_comment = re.compile(r'/\*([^*]+|\*+[^/])*(\*+/)?') | 
					
						
							|  |  |  | p_cpp_comment = re.compile('//.*') | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-08-14 20:14:29 +00:00
										 |  |  | ignores = [p_comment, p_cpp_comment] | 
					
						
							| 
									
										
										
										
											1994-05-17 09:05:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | p_char = re.compile(r"'(\\.[^\\]*|[^\\])'") | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  | p_hex = re.compile(r"0x([0-9a-fA-F]+)L?") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | filedict = {} | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  | importable = {} | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-01-17 17:01:40 +00:00
										 |  |  | try: | 
					
						
							| 
									
										
										
										
											2001-12-06 03:24:30 +00:00
										 |  |  |     searchdirs=os.environ['include'].split(';') | 
					
						
							| 
									
										
										
										
											1995-01-17 17:01:40 +00:00
										 |  |  | except KeyError: | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2001-12-06 03:24:30 +00:00
										 |  |  |         searchdirs=os.environ['INCLUDE'].split(';') | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     except KeyError: | 
					
						
							| 
									
										
										
										
											2009-10-24 20:11:21 +00:00
										 |  |  |         searchdirs=['/usr/include'] | 
					
						
							| 
									
										
										
										
											1995-01-17 17:01:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     global filedict | 
					
						
							|  |  |  |     opts, args = getopt.getopt(sys.argv[1:], 'i:') | 
					
						
							|  |  |  |     for o, a in opts: | 
					
						
							|  |  |  |         if o == '-i': | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |             ignores.append(re.compile(a)) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     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) | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |             i = outfile.rfind('.') | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             if i > 0: outfile = outfile[:i] | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |             modname = outfile.upper() | 
					
						
							|  |  |  |             outfile = modname + '.py' | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             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 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |                     importable[filename[len(dir)+1:]] = modname | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |                     break | 
					
						
							|  |  |  |             process(fp, outfp) | 
					
						
							|  |  |  |             outfp.close() | 
					
						
							|  |  |  |             fp.close() | 
					
						
							| 
									
										
										
										
											1992-03-02 16:20:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  | def pytify(body): | 
					
						
							|  |  |  |     # 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) | 
					
						
							|  |  |  |     # Compute negative hexadecimal constants | 
					
						
							|  |  |  |     start = 0 | 
					
						
							| 
									
										
										
										
											2007-12-04 23:02:19 +00:00
										 |  |  |     UMAX = 2*(sys.maxsize+1) | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  |     while 1: | 
					
						
							|  |  |  |         m = p_hex.search(body, start) | 
					
						
							|  |  |  |         if not m: break | 
					
						
							|  |  |  |         s,e = m.span() | 
					
						
							| 
									
										
										
										
											2008-05-16 15:23:30 +00:00
										 |  |  |         val = int(body[slice(*m.span(1))], 16) | 
					
						
							| 
									
										
										
										
											2007-12-04 23:02:19 +00:00
										 |  |  |         if val > sys.maxsize: | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  |             val -= UMAX | 
					
						
							|  |  |  |             body = body[:s] + "(" + str(val) + ")" + body[e:] | 
					
						
							|  |  |  |         start = s + 1 | 
					
						
							|  |  |  |     return body | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | def process(fp, outfp, env = {}): | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     lineno = 0 | 
					
						
							|  |  |  |     while 1: | 
					
						
							|  |  |  |         line = fp.readline() | 
					
						
							|  |  |  |         if not line: break | 
					
						
							|  |  |  |         lineno = lineno + 1 | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |         match = p_define.match(line) | 
					
						
							|  |  |  |         if match: | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             # gobble up continuation lines | 
					
						
							|  |  |  |             while line[-2:] == '\\\n': | 
					
						
							|  |  |  |                 nextline = fp.readline() | 
					
						
							|  |  |  |                 if not nextline: break | 
					
						
							|  |  |  |                 lineno = lineno + 1 | 
					
						
							|  |  |  |                 line = line + nextline | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |             name = match.group(1) | 
					
						
							|  |  |  |             body = line[match.end():] | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  |             body = pytify(body) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             ok = 0 | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  |             stmt = '%s = %s\n' % (name, body.strip()) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2006-09-06 06:51:57 +00:00
										 |  |  |                 exec(stmt, env) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             except: | 
					
						
							|  |  |  |                 sys.stderr.write('Skipping: %s' % stmt) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 outfp.write(stmt) | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |         match = p_macro.match(line) | 
					
						
							|  |  |  |         if match: | 
					
						
							|  |  |  |             macro, arg = match.group(1, 2) | 
					
						
							|  |  |  |             body = line[match.end():] | 
					
						
							| 
									
										
										
										
											2002-11-23 12:08:10 +00:00
										 |  |  |             body = pytify(body) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             stmt = 'def %s(%s): return %s\n' % (macro, arg, body) | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2006-09-06 06:51:57 +00:00
										 |  |  |                 exec(stmt, env) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             except: | 
					
						
							|  |  |  |                 sys.stderr.write('Skipping: %s' % stmt) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 outfp.write(stmt) | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |         match = p_include.match(line) | 
					
						
							|  |  |  |         if match: | 
					
						
							|  |  |  |             regs = match.regs | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             a, b = regs[1] | 
					
						
							|  |  |  |             filename = line[a:b] | 
					
						
							| 
									
										
										
										
											2008-05-16 15:23:30 +00:00
										 |  |  |             if filename in importable: | 
					
						
							| 
									
										
										
										
											2001-08-09 12:32:10 +00:00
										 |  |  |                 outfp.write('from %s import *\n' % importable[filename]) | 
					
						
							| 
									
										
										
										
											2008-05-16 15:23:30 +00:00
										 |  |  |             elif filename not in filedict: | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |                 filedict[filename] = None | 
					
						
							|  |  |  |                 inclfp = None | 
					
						
							|  |  |  |                 for dir in searchdirs: | 
					
						
							|  |  |  |                     try: | 
					
						
							| 
									
										
										
										
											2001-08-09 12:24:38 +00:00
										 |  |  |                         inclfp = open(dir + '/' + filename) | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |                         break | 
					
						
							|  |  |  |                     except IOError: | 
					
						
							|  |  |  |                         pass | 
					
						
							|  |  |  |                 if inclfp: | 
					
						
							|  |  |  |                     outfp.write( | 
					
						
							|  |  |  |                             '\n# Included from %s\n' % filename) | 
					
						
							|  |  |  |                     process(inclfp, outfp, env) | 
					
						
							|  |  |  |                 else: | 
					
						
							| 
									
										
										
										
											2001-12-06 03:28:17 +00:00
										 |  |  |                     sys.stderr.write('Warning - could not find file %s\n' % | 
					
						
							|  |  |  |                                      filename) | 
					
						
							| 
									
										
										
										
											1994-10-03 16:45:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-09 17:27:55 +00:00
										 |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     main() |