Home | History | Annotate | Download | only in pyxelator
      1 #!/usr/bin/env python
      2 
      3 """ 
      4 
      5 (c) 2002, 2003, 2004, 2005 Simon Burton <simon (at] arrowtheory.com>
      6 Released under GNU LGPL license.
      7 
      8 version 0.xx
      9 
     10 """
     11 
     12 
     13 import sys
     14 import os
     15 
     16 import cparse
     17 import ir
     18 
     19 def 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 
     31 class 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 
    140 def file_exists(path):
    141     try:
    142         os.stat(path)
    143         return True
    144     except OSError:
    145         return False
    146 
    147 if sys.platform.count('darwin'):
    148     shared_ext = '.dylib'
    149 else:
    150     shared_ext = '.so'
    151 
    152 def 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