1#!/usr/bin/env python 2 3""" 4 5(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com> 6Released under GNU LGPL license. 7 8version 0.xx 9 10""" 11 12 13import sys 14import os 15 16import cparse 17import ir 18 19def callcmd(cmd): 20 try: 21 from subprocess import call 22 try: 23 retcode = call(cmd, shell=True) 24 assert retcode == 0, "command failed: %s"%cmd 25 except OSError, e: 26 assert False, "command failed: %s"%e 27 except ImportError: 28 status = os.system( cmd ) 29 assert status == 0, "command failed: %s"%cmd 30 31class WorkUnit(object): 32 def __init__(self, files, modname, filename, 33 std=False, strip=False, mark_cb=None, 34 extradefs="", use_header=None, CC="gcc", CPP="gcc -E", 35 CPPFLAGS=""): 36 self.files = tuple(files) 37 self.modname = modname 38 self.filename = filename 39 self.CPPFLAGS = CPPFLAGS 40 self.CPP = CPP 41 if CC == 'g++': 42 self.CPPFLAGS += " -D__cplusplus" 43 self.std = std 44 self.strip = strip 45 self.mark_cb = mark_cb 46 self.node = None 47 self.extradefs = extradefs 48 self.CC = CC 49 self.use_header = use_header 50 51 def mkheader( self ): 52 if self.use_header: 53 return self.use_header 54 tmpname = str(abs(hash( (self.files,self.CPPFLAGS) ))) 55 name = '.tmp/%s' % tmpname 56 ifile = open( name+'.h', "w" ) 57 ifile.write( """ 58#define __attribute__(...) 59#define __const const 60#define __restrict 61#define __extension__ 62#define __asm__(...) 63#define __asm(...) 64#define __inline__ 65#define __inline 66""" ) 67 for filename in self.files: 68 if self.std: 69 line = '#include <%s>\n'%filename 70 else: 71 line = '#include "%s"\n'%filename 72 ifile.write( line ) 73 print line, 74 ifile.close() 75 cmd = '%s %s %s > %s'%(self.CPP,name+'.h',self.CPPFLAGS,name+'.E') 76 sys.stderr.write( "# %s\n" % cmd ) 77 callcmd( cmd ) 78 assert open(name+'.E').read().count('\n') > 10, "failed to run preprocessor" 79 cmd = '%s -dM %s %s > %s'%(self.CPP,name+'.h',self.CPPFLAGS,name+'.dM') 80 sys.stderr.write( "# %s\n" % cmd ) 81 callcmd( cmd ) 82 assert open(name+'.dM').read().count('\n') > 10, "failed to run preprocessor with -dM" 83 return name 84 85 def parse(self, verbose=False): 86 sys.stderr.write( "# parse %s\n" % str(self.files) ) 87 name = self.mkheader() 88 # read macros 89 f = open(name+'.dM') 90 macros = {} 91 for line in f.readlines(): 92 if line: 93 macro = line.split()[1] 94 if macro.count('('): 95 macro = macro[:macro.index('(')] 96 macros[macro] = None 97 #keys = macros.keys() 98 #keys.sort() 99 #for key in keys: 100 #print key 101 self.macros = macros 102 # parse preprocessed code 103 f = open(name+'.E') 104 s = f.read() + self.extradefs 105 self.node = cparse.TransUnit(verbose = verbose) 106 sys.stderr.write( "# parsing %s lines\n" % s.count('\n') ) 107 self.node.parse( s ) 108 if self.strip: 109 self.node.strip(self.files) 110 111 def transform(self, verbose=False, test_parse=False, test_types=False): 112 sys.stderr.write( "# processing...\n" ) 113 self.node = ir.TransUnit( self.node ) 114 self.node.transform(verbose, test_parse, test_types) 115 #self.node[0].psource() 116 if self.mark_cb is not None: 117 self.node.mark(self.mark_cb,verbose=False) 118 119 def output( self, func_cb = None ): 120 sys.stderr.write( "# pyxstr...\n" ) 121 decls = self.node.pyx_decls(self.files, self.modname, macros = self.macros, func_cb = func_cb, names={}, cprefix="" ) 122 123 name = self.filename 124 assert name.endswith(".pyx") 125 126 pxi = name[:-3]+'pxi' 127 file = open( pxi, "w" ) 128 file.write(decls) 129 sys.stderr.write( "# wrote %s, %d lines\n" % (pxi,decls.count('\n')) ) 130 131 def pprint(self): 132 for decl in self.node: 133 #decl.psource() 134 #cstr = decl.cstr() 135 #cstr = cstr.replace( '\n', '\n# ' ) 136 print 137 #print '#', cstr 138 print decl.deepstr() 139 140def file_exists(path): 141 try: 142 os.stat(path) 143 return True 144 except OSError: 145 return False 146 147if sys.platform.count('darwin'): 148 shared_ext = '.dylib' 149else: 150 shared_ext = '.so' 151 152def get_syms(libs, libdirs): 153 # XX write interface to objdump -t XX 154 libnames = [] 155 for lib in libs: 156 for ext in shared_ext,'.a': 157 libname = 'lib'+lib+ext 158 for libdir in libdirs: 159 path = libdir+'/'+libname 160 if file_exists(path): 161 libnames.append(path) 162 break 163 #else: 164 #print "cannot find %s lib as %s in %s" % ( lib, libname, libdir ) 165 print 'libnames:', libnames 166 syms = {} 167 accept = [ ' %s '%c for c in 'TVWBCDGRS' ] 168 #f = open('syms.out','w') 169 for libname in libnames: 170 try: 171 from subprocess import Popen, PIPE 172 p = Popen(['nm', libname], bufsize=1, stdout=PIPE) 173 fout = p.stdout 174 except ImportError: 175 fin, fout = os.popen2( 'nm %s' % libname ) 176 for line in fout.readlines(): 177 for acc in accept: 178 if line.count(acc): 179 left, right = line.split(acc) 180 sym = right.strip() 181 if sys.platform.count('darwin'): 182 if sym[0] == '_': 183 sym = sym[1:] # remove underscore prefix 184 if sym.endswith('.eh'): 185 sym = sym[:-len('.eh')] 186 syms[sym] = None 187 #f.write( '%s: %s %s\n' % (sym,line[:-1],libname) ) 188 break 189 return syms 190 191 192 193