#!/usr/bin/env python """ (c) 2002, 2003, 2004, 2005 Simon Burton Released under GNU LGPL license. version 0.xx """ import sys import os import cparse import ir def callcmd(cmd): try: from subprocess import call try: retcode = call(cmd, shell=True) assert retcode == 0, "command failed: %s"%cmd except OSError, e: assert False, "command failed: %s"%e except ImportError: status = os.system( cmd ) assert status == 0, "command failed: %s"%cmd class WorkUnit(object): def __init__(self, files, modname, filename, std=False, strip=False, mark_cb=None, extradefs="", use_header=None, CC="gcc", CPP="gcc -E", CPPFLAGS=""): self.files = tuple(files) self.modname = modname self.filename = filename self.CPPFLAGS = CPPFLAGS self.CPP = CPP if CC == 'g++': self.CPPFLAGS += " -D__cplusplus" self.std = std self.strip = strip self.mark_cb = mark_cb self.node = None self.extradefs = extradefs self.CC = CC self.use_header = use_header def mkheader( self ): if self.use_header: return self.use_header tmpname = str(abs(hash( (self.files,self.CPPFLAGS) ))) name = '.tmp/%s' % tmpname ifile = open( name+'.h', "w" ) ifile.write( """ #define __attribute__(...) #define __const const #define __restrict #define __extension__ #define __asm__(...) #define __asm(...) #define __inline__ #define __inline """ ) for filename in self.files: if self.std: line = '#include <%s>\n'%filename else: line = '#include "%s"\n'%filename ifile.write( line ) print line, ifile.close() cmd = '%s %s %s > %s'%(self.CPP,name+'.h',self.CPPFLAGS,name+'.E') sys.stderr.write( "# %s\n" % cmd ) callcmd( cmd ) assert open(name+'.E').read().count('\n') > 10, "failed to run preprocessor" cmd = '%s -dM %s %s > %s'%(self.CPP,name+'.h',self.CPPFLAGS,name+'.dM') sys.stderr.write( "# %s\n" % cmd ) callcmd( cmd ) assert open(name+'.dM').read().count('\n') > 10, "failed to run preprocessor with -dM" return name def parse(self, verbose=False): sys.stderr.write( "# parse %s\n" % str(self.files) ) name = self.mkheader() # read macros f = open(name+'.dM') macros = {} for line in f.readlines(): if line: macro = line.split()[1] if macro.count('('): macro = macro[:macro.index('(')] macros[macro] = None #keys = macros.keys() #keys.sort() #for key in keys: #print key self.macros = macros # parse preprocessed code f = open(name+'.E') s = f.read() + self.extradefs self.node = cparse.TransUnit(verbose = verbose) sys.stderr.write( "# parsing %s lines\n" % s.count('\n') ) self.node.parse( s ) if self.strip: self.node.strip(self.files) def transform(self, verbose=False, test_parse=False, test_types=False): sys.stderr.write( "# processing...\n" ) self.node = ir.TransUnit( self.node ) self.node.transform(verbose, test_parse, test_types) #self.node[0].psource() if self.mark_cb is not None: self.node.mark(self.mark_cb,verbose=False) def output( self, func_cb = None ): sys.stderr.write( "# pyxstr...\n" ) decls = self.node.pyx_decls(self.files, self.modname, macros = self.macros, func_cb = func_cb, names={}, cprefix="" ) name = self.filename assert name.endswith(".pyx") pxi = name[:-3]+'pxi' file = open( pxi, "w" ) file.write(decls) sys.stderr.write( "# wrote %s, %d lines\n" % (pxi,decls.count('\n')) ) def pprint(self): for decl in self.node: #decl.psource() #cstr = decl.cstr() #cstr = cstr.replace( '\n', '\n# ' ) print #print '#', cstr print decl.deepstr() def file_exists(path): try: os.stat(path) return True except OSError: return False if sys.platform.count('darwin'): shared_ext = '.dylib' else: shared_ext = '.so' def get_syms(libs, libdirs): # XX write interface to objdump -t XX libnames = [] for lib in libs: for ext in shared_ext,'.a': libname = 'lib'+lib+ext for libdir in libdirs: path = libdir+'/'+libname if file_exists(path): libnames.append(path) break #else: #print "cannot find %s lib as %s in %s" % ( lib, libname, libdir ) print 'libnames:', libnames syms = {} accept = [ ' %s '%c for c in 'TVWBCDGRS' ] #f = open('syms.out','w') for libname in libnames: try: from subprocess import Popen, PIPE p = Popen(['nm', libname], bufsize=1, stdout=PIPE) fout = p.stdout except ImportError: fin, fout = os.popen2( 'nm %s' % libname ) for line in fout.readlines(): for acc in accept: if line.count(acc): left, right = line.split(acc) sym = right.strip() if sys.platform.count('darwin'): if sym[0] == '_': sym = sym[1:] # remove underscore prefix if sym.endswith('.eh'): sym = sym[:-len('.eh')] syms[sym] = None #f.write( '%s: %s %s\n' % (sym,line[:-1],libname) ) break return syms