mirror of
https://github.com/yasm/yasm
synced 2026-08-26 22:26:05 -04:00
192 lines
5.8 KiB
Python
Executable file
192 lines
5.8 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
"""
|
|
|
|
(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
|
|
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
|
|
|
|
|
|
|