blob: cfa9c02ead1642db9cf3d74e5c76ae8034f12ef1 [file] [log] [blame]
#!/usr/bin/env python
""" ir.py - parse c declarations
(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
Released under GNU LGPL license.
version 0.xx
"""
import sys
#import cPickle as pickle
import pickle
#from lexer import Lexer
from parse_core import Symbols #, Parser
import node as node_module
import cparse
import genpyx
class Node(genpyx.Node, node_module.Node):
"""
tree structure
"""
def __init__( self, *args, **kw ):
node_module.Node.__init__( self, *args, **kw )
self._marked = False
def get_marked( self ):
return self._marked
def set_marked( self, marked ):
# if marked:
# print "MARK", self
self._marked = marked
marked = property( get_marked, set_marked )
# def __getstate__( self ):
# return self.__class__, tuple( [ item.__getstate__() for item in self ] )
# def __setstate__( self, state ):
# cls, states = state
# states = list(states)
# for idx, state in enumerate(states):
# items[idx] = items[idx].__setstate__(
def __getstate__(self):
return str(self)
def __setstate__(self, state):
Node.__init__(self)
self[:] = eval(state)
# _unique_id = 0
# def get_unique_id(cls):
# Node._unique_id += 1
# return Node._unique_id
# get_unique_id = classmethod(get_unique_id)
def __hash__( self ):
return hash( tuple([hash(type(self))]+[hash(item) for item in self]) )
def clone(self):
l = []
for item in self:
if isinstance(item,Node):
item = item.clone()
l.append(item)
return self.__class__(*l, **self.__dict__)
def init_from( self, other ): # class method ?
# Warning: shallow init
self[:] = other
self.__dict__.update( other.__dict__ )
return self
# def is_struct(self):
# for x in self:
# if isinstance(x,Node):
# if x.is_struct():
# return 1
# return 0
#def explain(self):
#l = []
#for x in self:
#if isinstance(x,Node):
#l.append(x.explain())
#else:
#l.append(str(x))
#return string.join(l," ")
##(self.__class__.__name__,string.join(l) )
def psource(self):
if hasattr(self,'lines'):
# print "# "+string.join(self.lines,"\n# ")+"\n"
print "# "+"\n# ".join(self.lines)+"\n"
def cstr(self,l=None):
"""
Build a list of tokens; return the joined tokens string
"""
if l is None:
l = []
for x in self:
if isinstance(x,Node):
x.cstr(l)
else:
l.insert(0,str(x)+' ')
s = ''.join(l)
return s
def ctype(self): # anon_clone
" return clone of self without identifiers "
#print "%s.ctype()"%self
l=[]
for x in self:
if isinstance(x,Node):
l.append(x.ctype())
else:
l.append(x)
#print "%s.__class__(*%s)"%(self,l)
return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ?
def cbasetype(self):
" return ctype with all TypeAlias's replaced "
# WARNING: we cache results (so do not mutate self!!)
l=[]
for x in self:
if isinstance(x,Node):
l.append(x.cbasetype())
else:
l.append(x)
#print "%s.__class__(*%s)"%(self,l)
return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ?
def signature( self, tank=None ):
if tank is None:
tank = {}
for node in self.nodes():
if not tank.has_key( type(node) ):
tank[ type(node) ] = {}
type(node).tank = tank[type(node)]
shape = tuple( [ type(_node).__name__ for _node in node ] )
if not tank[type(node)].has_key(shape):
tank[type(node)][shape] = []
tank[type(node)][shape].append( node )
return tank
def psig( self, tank=None ):
if tank is None:
tank = {}
tank = self.signature(tank)
for key in tank.keys():
print key.__name__
for shape in tank[key].keys():
print " ", shape
#
#################################################
class Named(genpyx.Named, Node):
" has a .name property "
def get_name(self):
if self:
assert type(self[0])==str
return self[0]
return None
def set_name(self, name):
if self:
self[0] = name
else:
self.append(name)
name = property(get_name,set_name)
class BasicType(genpyx.BasicType, Named):
"float double void char int"
pass
class Qualifier(genpyx.Qualifier, Named):
"register signed unsigned short long const volatile inline"
pass
class StorageClass(genpyx.StorageClass, Named):
"extern static auto"
pass
class Ellipses(genpyx.Ellipses, Named):
"..."
pass
class GCCBuiltin(genpyx.GCCBuiltin, BasicType):
"things with __builtin prefix"
pass
class Identifier(genpyx.Identifier, Named):
"""
shape = +( str, +ConstExpr )
"""
#def explain(self):
#if len(self)==1:
#return "%s"%self.name
#else:
#return "%s initialized to %s"%(self.name,
#Node(self[1]).explain()) # will handle Initializer
# def ctype(self):
# return self.__class__(*self[1:]) #.clone() ?
# def get_name(self):
# if self:
# return self[0]
# def set_name(self, name):
# if self:
# self[0] = name
# else:
# self.append(name)
# name = property(get_name,set_name)
def cstr(self,l=None):
if l is None:
l=[]
if len(self)>1:
assert len(self)==2
l.append( '%s = %s'%(self[0],self[1]) )
elif len(self)==1:
l.append( str(self[0]) )
return " ".join(l)
class TypeAlias(genpyx.TypeAlias, Named):
"""
typedefed things, eg. size_t
"""
def cbasetype( self ):
node = self.typedef.cbasetype().get_rest()
return node
class Function(genpyx.Function, Node):
"""
"""
#def explain(self):
#if len(self):
#return "function (%s), returning"%\
#", ".join( map(lambda x:x.explain(),self) )
#else:
#return "function returning"
def cstr(self,l):
#print '%s.cstr(%s)'%(self,l)
_l=[]
assert len(self)
i=0
while isinstance(self[i],Declarator):
_l.append( self[i].cstr() )
i=i+1
l.append( '(%s)'% ', '.join(_l) )
while i<len(self):
self[i].cstr(l)
i=i+1
return " ".join(l)
def return_type(self):
node = self[-1]
#assert isinstance(node,DeclarationSpecifiers)
return Declarator( Identifier(), node )
ret = property(return_type)
def get_args(self):
args = [ arg for arg in self[:-1] if not arg.is_void() ]
return args
args = property(get_args)
def arg_types(self):
return [ AbstractDeclarator().init_from( arg.ctype() ) for arg in self[:-1]]
def is_varargs(self):
for node in self.nodes():
if isinstance(node,Ellipses) or 'va_list' in node:
# print self, 'is_varargs'
return True
# print self, 'is_varargs'
return False
# return fn.deepfind(Ellipses) or fn.deepfind('va_list')
def ctype(self):
return Function(*self.arg_types()+[self[-1]]) # XX self[-1].ctype
class Pointer(genpyx.Pointer, Node):
"""
"""
def get_spec(self):
if type(self[0])==TypeSpecifiers: # isinstance ??
return self[0]
spec = property(get_spec)
#def explain(self):
#return "pointer to"
def cstr(self,l):
assert len(self)
node=self[0]
l.insert(0,'*')
if isinstance(node,Function):
l.insert(0,'(')
l.append(')')
elif isinstance(node,Array):
l.insert(0,'(')
l.append(')')
return Node.cstr(self,l)
class Array(genpyx.Array, Node):
"""
"""
#def explain(self):
#s=''
#if len(self):
#if type(self[0])==int:
#s='0 to %s '%(self[0]-1)
#return "array %sof"%s
def has_size(self):
try:
int(self.size)
return True
except:
return False
def get_size(self):
if type(self[-1])==str:
try: return int(self[-1])
except: return self[-1]
return self[-1] # None
size = property(get_size)
def get_spec(self):
if type(self[0])==TypeSpecifiers: # isinstance ??
return self[0]
spec = property(get_spec)
def to_pointer(self):
node = Pointer()
node.init_from( self.clone() )
node.pop() # pop the size element
return node
def cstr(self,l):
if self.size is None:
l.append('[]')
else:
l.append('[%s]'%self.size)
return Node( *self[:-1] ).cstr( l )
class Tag(genpyx.Tag, Named):
" the tag of a Struct, Union or Enum "
pass
class Taged(genpyx.Taged, Node):
"Struct, Union or Enum "
def get_tag(self):
if len(self):
tag = self[0]
assert type(tag)==Tag # isinstance ??
else:
tag = None
return tag
def set_tag(self,tag):
if len(self):
self[0] = tag
else:
self.append(tag)
tag = property( get_tag, set_tag )
def has_members(self):
return len(self)>1 # more than just a tag
def get_members(self):
return self[1:]
members = property(get_members) # fields ?
def ctype(self):
if not self.tag.name:
#print "# WARNING : anonymous struct " # OK i think
return self.clone()
# self = self.clone()
# return self[:1] # just the tag
return self.__class__( self.tag, **self.__dict__ ) # just the Tag
# return self.__class__( *self, **self.__dict__ )
def cbasetype(self):
return self.ctype() # is this enough ???
# return Node.cbasetype(self) # XX lookup my tag if i am empty ..?
class Compound(genpyx.Compound, Taged):
"Struct or Union"
def cstr(self,_l=None):
assert isinstance( self[0], Tag )
tag=''
if len(self[0]):
tag=' '+self[0][0]
if isinstance(self,Struct):
l=[ 'struct%s '%tag ]
elif isinstance(self,Union):
l=[ 'union%s '%tag ]
if len(self)>1:
l.append(' { ')
for decl in self[1:]:
l.append( decl.cstr()+"; " )
l.append('} ')
if _l is None:
_l=[]
while l:
_l.insert( 0, l.pop() )
# XX empty struct with no tag -> "struct" XX
return "".join( _l )
def ctype(self):
tp = Taged.ctype(self)
for i in range(1,len(tp)):
tp[i] = StructDeclarator().init_from( tp[i] )
return tp
class Struct(genpyx.Struct, Compound):
"""
"""
pass
class Union(genpyx.Union, Compound):
"""
"""
pass
class Enum(genpyx.Enum, Taged):
"""
"""
def cstr(self,_l=None):
assert isinstance( self[0], Tag )
tag=''
if len(self[0]):
tag=' '+self[0][0]
l=[ 'enum%s '%tag ]
if len(self)>1:
l.append(' { ')
for node in self[1:]:
l.append( node.cstr()+', ' )
l.append('} ')
if _l is None:
_l=[]
while l:
_l.insert( 0, l.pop() )
return ''.join( _l )
class Declarator(genpyx.Declarator, Node):
"""
"""
def __eq__(self,other):
" unordered equality "
# ordering sometimes gets lost when we do a cbasetype
if not isinstance(other,Node):
return False
a, b = self[:], other[:]
a.sort()
b.sort()
return a == b
def __hash__( self ):
hs = [hash(item) for item in self]
hs.sort()
return hash( tuple([hash(type(self))]+hs) )
def transform(self):
return
def get_identifier(self):
if len(self)>1:
return self[0]
def set_identifier(self, identifier):
if len(self)>1:
self[0] = identifier
else:
self.insert(0,identifier)
identifier = property(get_identifier,set_identifier)
def get_spec(self):
spec = self[-1]
if type(spec)==TypeSpecifiers: # isinstance ??
return spec
spec = property(get_spec)
def get_type_alias(self):
if self.spec:
if isinstance(self.spec[0], TypeAlias):
return self.spec[0]
type_alias = property(get_type_alias)
def get_tagged(self):
if self.spec:
return self.spec.tagged # i am a tagged
tagged = property(get_tagged)
def get_compound(self):
if self.spec:
return self.spec.compound # i am a compound
compound = property(get_compound)
def get_struct(self):
if self.spec:
return self.spec.struct # i am a struct
struct = property(get_struct)
def get_union(self):
if self.spec:
return self.spec.union # i am a union
union = property(get_union)
def get_enum(self):
if self.spec:
return self.spec.enum # i am an enum
enum = property(get_enum)
def get_function(self):
if len(self)>1 and type(self[1])==Function: # isinstance ??
return self[1]
function = property(get_function)
def get_pointer(self):
if len(self)>1 and type(self[1])==Pointer: # isinstance ??
return self[1]
pointer = property(get_pointer)
def get_array(self):
if len(self)>1 and type(self[1])==Array: # isinstance ??
return self[1]
array = property(get_array)
def get_name(self):
if self.identifier:
return self.identifier.name
def set_name(self, name):
assert self.identifier is not None
self.identifier.name = name
name = property(get_name, set_name)
def get_rest(self): # XX needs a better name
if len(self)>1:
return self[1]
return self[0]
def pointer_to( self ):
" return Declarator pointing to self's type "
decl = Declarator(Identifier(), Pointer(self.get_rest().clone()))
return decl
def deref( self ):
" return (clone of) Declarator that self is pointing to "
node = self.ctype() # clone
pointer = node.pointer or node.array
assert pointer, "cannot dereference non-pointer"
node[1:2] = pointer
return node
def is_void(self):
return self.spec and BasicType('void') in self.spec
def is_pointer_to_fn(self):
return self.pointer and self.deref().function
def is_pointer_to_char(self):
# return self.ctype() == TransUnit("char *a;").transform()[0].ctype()
node = self.pointer or self.array
if node:
spec = node.spec
if spec and BasicType('char') in spec and not BasicType('unsigned') in spec:
return True
return False
def is_callback(self):
" i am a pointer to a function whose last arg is void* "
if self.is_pointer_to_fn():
fn = self.deref().function
if fn.args:
arg = fn.args[-1]
if arg.pointer and arg.deref().is_void():
return True
def is_complete( self, tag_lookup ):
if self.tagged and self.tagged.tag.name in tag_lookup and not tag_lookup[self.tagged.tag.name].has_members():
return False
return True
def is_primative( self ):
"i am a char,short,int,float,double... "
spec = self.cbasetype().spec
return spec and spec.find(BasicType)
def is_pyxnative( self ):
# pyrex handles char* too
# but i don't know if we should make this the default
# sometimes we want to send a NULL, so ... XXX
self = self.cbasetype()
if self.is_void():
return False
if self.is_primative():
return True
if self.enum:
return True
# pointer = None
# if self.pointer:
# pointer = self.pointer
# elif self.array:
# pointer = self.array
# if pointer and pointer.spec:
# spec = pointer.spec
# if BasicType("char") in spec and not Qualifier("unsigned") in spec:
# # char*, const char*
## print self.deepstr()
# return True
return False
def cstr(self,l=None):
return Node.cstr(self,l).strip()
def ctype(self):
decl=Declarator()
decl.init_from( self.clone() )
decl.identifier = Identifier()
for i in range(1,len(decl)):
decl[i]=decl[i].ctype()
return decl
def cbasetype(self):
# WARNING: we cache results (so do not mutate self!!)
try:
# this cache improves performance by 50%
return self.__cbasetype.clone()
except AttributeError:
pass
decl = self.ctype() # gets rid of Identifier names
for i, node in enumerate(decl):
decl[i] = decl[i].cbasetype()
# return decl.get_rest()
done = False
while not done:
done = True
nodes = decl.deepfilter( TypeSpecifiers )
for node in nodes:
if node.deepfind( TypeSpecifiers ) != node:
# this node has another TypeSpecifier;
decl.expose_node( node )
done = False
break # start again...
# each TypeSpecifier needs to absorb primitive siblings (StorageClass, BasicType etc.)
nodes = decl.deepfilter( TypeSpecifiers )
for node in nodes:
parent = decl.get_parent(node)
i = 0
while i < len(parent):
assert not type(parent[i]) in (TypeAlias, Enum, Struct, Union)
if type(parent[i]) in (StorageClass, BasicType, Qualifier):
node.append( parent.pop(i) )
else:
i = i + 1
self.__cbasetype = decl.clone()
return decl
def invalidate(self):
# flush cache, etc.
try:
del self.__cbasetype
except AttributeError:
pass
def declare_str(self,name):
" return c string declaring name with same type as self "
tp = self.ctype()
tp.name = name
return tp.cstr()+";"
class Typedef(genpyx.Typedef, Declarator):
def cstr(self,l=None):
return 'typedef ' + Declarator.cstr(self,l) #.strip()
class AbstractDeclarator(genpyx.AbstractDeclarator, Declarator):
""" used in Function; may lack an identifier """
#def cstr(self,l=None):
#return Node.cstr(self,l)
# def ctype(self):
# # _type_ ignores the name of our identifier
# return Node.ctype(self)
class FieldLength(genpyx.FieldLength, Node):
"""
"""
#def explain(self):
#return ""
def cstr(self,l):
l.append(':%s'%self[0])
class StructDeclarator(genpyx.StructDeclarator, Declarator): # also used in Union
"""
"""
#def explain(self):
#flen = self.find(FieldLength)
#if flen is not None:
#i = self.index(flen)
#self.pop(i)
#s = Declarator.explain(self)
#self.insert(i,flen)
#width = flen[0]
#if width > 0:
#return s+" bitfield %s wide"%width
#else:
#return s+" alignment bitfield"
#else:
#return Declarator.explain(self)
# def ctype(self):
# return self
def get_field_length(self):
if len(self)>1 and isinstance( self[1], FieldLength ):
return self[1]
field_length = property(get_field_length)
class DeclarationSpecifiers(genpyx.DeclarationSpecifiers, Node):
#class TypeSpecifiers(Node):
"""
"""
def __eq__(self,other):
" unordered equality "
if not isinstance(other,Node):
return False
a, b = self[:], other[:]
a.sort()
b.sort()
return a == b
def __hash__( self ):
hs = [hash(item) for item in self]
hs.sort()
return hash( tuple([hash(type(self))]+hs) )
# def is_struct(self):
# return self.find(Struct) is not None
class TypeSpecifiers(genpyx.TypeSpecifiers, DeclarationSpecifiers):
"""
"""
def get_tagged(self):
if self and isinstance(self[0],Taged):
return self[0]
tagged = property(get_tagged)
def get_compound(self):
if self and isinstance(self[0],Compound):
return self[0]
compound = property(get_compound)
def get_struct(self):
if self and isinstance(self[0],Struct):
return self[0]
struct = property(get_struct)
def get_union(self):
if self and isinstance(self[0],Union):
return self[0]
union = property(get_union)
def get_enum(self):
if self and isinstance(self[0],Enum):
return self[0]
enum = property(get_enum)
def cbasetype(self):
node = Node.cbasetype(self)
# node.expose( TypeSpecifiers )
# if node.deepfind(TypeSpecifiers) != node:
return node
class Initializer(genpyx.Initializer, Node):
"""
"""
pass
class Declaration(genpyx.Declaration, Node):
"""
"""
def do_spec(self):
" distribute DeclarationSpecifiers over each Declarator "
spec=self[0]
assert isinstance(spec,DeclarationSpecifiers), spec.deepstr()
self.pop(0)
for declarator in self:
assert isinstance(declarator,Declarator)
#if isinstance(declarator,DeclarationSpecifiers #huh?
##for node in spec:
##declarator.append(node.clone())
declarator.append(spec)
def transform(self):
# children go first
for node in self.nodes():
if isinstance(node,Declaration):
node.do_spec()
node.file = self.file # overkill ?
self.expose(Declaration)
#def explain(self):
#return string.join([x.explain() for x in self],", ")
#return string.join(map(lambda x:x.explain(),self),", ")
class ParameterDeclaration(genpyx.ParameterDeclaration, Declaration):
"""
"""
pass
class StructDeclaration(genpyx.StructDeclaration, Declaration):
"""
"""
pass
class TransUnit(genpyx.TransUnit, Node):
"""
Top level node.
"""
def __init__( self, item ): # XX __init__ uses different signature ! XX
if type(item)==str:
node = cparse.TransUnit()
node.parse(item)
else:
node = item
assert isinstance( node, cparse.TransUnit ), str(node)
Node.__init__(self)
self[:] = [ self.convert(child) for child in node ]
self.__dict__.update( node.__dict__ )
assert "name" not in node.__dict__
self.syms = {} # map identifier names to their Declarator's
self.typedefs = {} # map names to Typedef's
self.tag_lookup = {} # map struct, union, enum tags to Taged's
# XX should call transform here XX
# print self.deepstr()
def __getstate__( self ):
nodes = tuple( [ repr(node) for node in self ] )
typedefs = tuple( [ (key,repr(val)) for key,val in self.typedefs.items() ] )
return nodes, typedefs
def __setstate__( self, state ):
Node.__init__(self)
nodes, typedefs = state
nodes = [ eval(node) for node in nodes ]
self[:] = nodes
typedefs = [ (key,eval(val)) for key,val in typedefs ]
self.typedefs = dict(typedefs)
def convert( self, node ):
# name = node.__class__.__name__
# cls = globals()[ name ]
cls = cls_lookup[ type(node) ]
_node = cls()
for child in node:
if isinstance(child, node_module.Node):
child = self.convert( child )
else:
assert child is None or type(child) in (str, int), type(child)
_node.append( child )
_node.__dict__.update( node.__dict__ )
return _node
def strip(self,files):
" leave only the declarations from <files> "
i=0
while i<len(self):
if self[i].file in files:
i=i+1
else:
self.pop(i)
def mark(self,cb,verbose=False):
" mark our child nodes such that cb(node).. mark dependants too. prune unmarked objects. "
# mark the nodes:
for node in self:
node.marked = cb(self, node)
if verbose and node.marked:
print '1:', node.cstr()
# propagate dependancy:
i=len(self)
while i:
i-=1 # we go backwards
for node in self[i].nodes(): # bottom-up search
if verbose and self[i].marked and not node.marked:
print '2:', str(node), '<--', self[i].cstr()
node.marked = self[i].marked or node.marked
if type(node)==TypeAlias:
if verbose and node.marked and not node.typedef.marked:
print '3:', node.typedef.cstr(), '<--', node.cstr()
node.typedef.marked = node.typedef.marked or node.marked
if isinstance(node, Taged):
if node.tag.name in self.tag_lookup:
_node = self.tag_lookup[ node.tag.name ] # look-up the def'n
if verbose and node.marked and not _node.marked:
print '4:', _node.cstr(), '<--', self[i].cstr()
# _node.marked = _node.marked or self[i].marked
_node.marked = _node.marked or node.marked
# else:
# # this guy has no tag
# print "lost tag:", self[i].cstr()
# XX struct defs acquire marks from members, but XX
# XX ordinary definitions do not XX
# if node.marked and not self[i].marked:
# # one of my descendants is marked
# if verbose:
# print '5:', self[i].cstr(), '<--', node.cstr()
# self[i].marked = True
# if verbose:
# for node in self:
# print '-'*79
# if node.enum:
# print str(node.marked) + ': ' + node.cstr()
# prune:
f = open(".tmp/pruned.txt","w")
f.write("// This file autogenerated by '%s' .\n"%__file__)
f.write("// List of functions pruned from parse tree, for various reasons.\n\n")
i=0
while i<len(self):
if not self[i].marked:
if verbose: print 'pop:', self[i].cstr()
f.write( self[i].cstr() + "\n" )
self.pop(i)
# elif self[i].compound:
# # XXXX for now, rip out all struct members XXXX
# self[i].compound[1:] = [] # XX encapsulation
# i = i + 1
else:
i = i + 1
for key, value in self.syms.items():
if not value.marked:
del self.syms[key]
for key, value in self.typedefs.items():
if not value.marked:
del self.typedefs[key]
for key, value in self.tag_lookup.items():
if not value.marked:
del self.tag_lookup[key]
# sys.exit(1)
def assert_no_dups(self):
check={}
for node in self.nodes():
assert not check.has_key(id(node))
check[id(node)]=1
def transform(self, verbose=False, test_parse=False, test_types=False ):
i=0
while i < len(self):
if verbose: print "##"*25
declaration=self[i]
if verbose: declaration.psource()
if verbose: print declaration.deepstr(),'\n'
assert isinstance(declaration,Declaration)
if verbose: print "# expose declarators from declaration"
# STAGE 1
declaration.transform()
if verbose: print declaration.deepstr(),'\n'
self[i:i+1] = declaration # expose declarators from declaration
for j in range(len(declaration)):
declarator=self[i]
assert isinstance(declarator,Declarator)
if verbose: print "# declarator.transform()"
# STAGE 2
declarator.transform()
if verbose: print declarator.deepstr(),'\n'
if verbose: print "# self.visit_declarator(declarator)"
# STAGE 3
self[i] = declarator = self.visit_declarator(declarator)
# STAGE 4
if declarator.name:
if isinstance(declarator, Typedef):
if verbose: print "# typedef %s" % declarator.name
self.typedefs[ declarator.name ] = declarator
else:
if verbose: print "# sym %s" % declarator.name
self.syms[ declarator.name ] = declarator
for node in declarator.nodes():
if isinstance(node,Taged) and node.tag.name:
assert type(node.tag.name)==str, node.deepstr()
taged = self.tag_lookup.get( node.tag.name, None )
if taged is None:
if verbose: print "# tag lookup %s = %s" % (declarator.name, node.tag.name)
self.tag_lookup[ node.tag.name ] = node
elif not taged.has_members():
# this is (maybe) the definition of this tag
if verbose: print "# definition %s = %s" % (declarator.name, node.tag.name)
self.tag_lookup[ node.tag.name ] = node
# Annotate the TypeAlias's
for node in declarator.deepfilter( TypeAlias ):
name = node[0]
assert type( name ) == str
node.typedef = self.typedefs[ name ]
if verbose: print declarator.deepstr(),'\n'
#print declarator.ctype().deepstr(),'\n'
#assert declarator.clone() == declarator
###################################################
# TESTS:
if test_parse:
# test that parse of cstr gives same answer
cstr = declarator.cstr()+';\n'
if verbose: print '# '+cstr.replace('\n','\n# ')
#print
if isinstance(declarator,Typedef):
name = declarator[0][0]
assert type(name)==str
self.lexer.rmtypedef( name )
declaration = cparse.Declaration()
self.lexer.lex( cstr )
#print self.lexer.err_string()
declaration.parse( self.lexer, Symbols() ) # use new name-space
#declaration.parse( Lexer( cstr ), Symbols() )
declaration = self.convert(declaration)
declaration.transform()
assert len(declaration)==1
decl=declaration[0]
decl.transform()
decl = self.visit_declarator(decl)
if decl!=declarator:
if verbose: print "#???????????"
if verbose: print decl.deepstr(),'\n\n'
#if verbose: print declaration.deepstr(),'\n\n'
#assert 0
elif verbose: print '# OK\n'
if test_types:
node = declarator.ctype()
declare_str= node.declare_str("my_name")
if verbose: print "# declarator.ctype() "
if verbose: print node.deepstr(),"\n"
if verbose: print "#",declare_str.replace('\n','\n# '), '\n'
i=i+1
return self
def visit(self,node):
#print 'visit(%s)'%node
for _node in node:
if isinstance(_node,Declarator):
_node = self.visit_declarator(_node) # XX replace _node
elif isinstance(_node,Node):
_node = self.visit(_node) # XX replace _node
return node
def visit_declarator(self,decl):
assert isinstance(decl,Declarator)
# STAGE 3.a
tp = decl.deepfind(Typedef)
if tp is not None:
decl.deeprm(tp)
tp.init_from( decl ) # warning: shallow init
decl = tp
# STAGE 3.b
i=len(decl)
# accumulate nodes (they become the children of decl)
children=[]
while i:
i=i-1
node=decl.pop(i)
if isinstance(node,Declarator):
node = self.visit_declarator(node) # replace node
else:
node = self.visit(node) # replace node
if isinstance(node,Pointer):
node+=children
children=[node]
elif isinstance(node,Function):
node+=children
children=[node]
elif isinstance(node,Array):
while children:
node.insert(0,children.pop())
children=[node]
# array size (if any) at end
#elif isinstance(node,Identifier):
#node+=children
#children=[node]
else:
# accumulate
children.insert(0,node)
decl[:]=children
return decl
cstr = None
ctype = None
cbasetype = None
# remap the global class definitions in genpyx to
# point to the definitions in this module
gbl = globals()
for key, val in gbl.items():
if type(val)==type:
if issubclass(val,Node):
setattr( genpyx, key, val )
assert genpyx.Node == Node
cls_lookup = {
# Node : Node ,
cparse.BasicType : BasicType ,
cparse.Qualifier : Qualifier ,
cparse.StorageClass : StorageClass ,
cparse.Ellipses : Ellipses ,
cparse.GCCBuiltin : GCCBuiltin ,
cparse.Identifier : Identifier ,
cparse.TypeAlias : TypeAlias ,
cparse.Function : Function ,
cparse.Pointer : Pointer ,
cparse.Array : Array ,
cparse.Tag : Tag ,
cparse.Compound : Compound ,
cparse.Struct : Struct ,
cparse.Union : Union ,
cparse.Enum : Enum ,
cparse.Declarator : Declarator ,
cparse.Typedef : Typedef ,
cparse.AbstractDeclarator : AbstractDeclarator ,
cparse.FieldLength : FieldLength ,
cparse.StructDeclarator : StructDeclarator ,
cparse.DeclarationSpecifiers : TypeSpecifiers ,
cparse.TypeSpecifiers : TypeSpecifiers ,
cparse.Initializer : Initializer ,
cparse.Declaration : Declaration ,
cparse.ParameterDeclaration : ParameterDeclaration ,
cparse.StructDeclaration : StructDeclaration ,
cparse.TransUnit : TransUnit ,
}