Home | History | Annotate | Download | only in pyxelator
      1 #!/usr/bin/env python
      2 """ ir.py - parse c declarations
      3 
      4 (c) 2002, 2003, 2004, 2005 Simon Burton <simon (at] arrowtheory.com>
      5 Released under GNU LGPL license.
      6 
      7 version 0.xx
      8 
      9 """
     10 
     11 import sys
     12 #import cPickle as pickle
     13 import pickle
     14 
     15 #from lexer import Lexer
     16 from parse_core import Symbols #, Parser
     17 import node as node_module
     18 import cparse
     19 import genpyx
     20 
     21 class Node(genpyx.Node, node_module.Node):
     22     """
     23         tree structure
     24     """
     25     def __init__( self, *args, **kw ):
     26         node_module.Node.__init__( self, *args, **kw )
     27         self._marked = False
     28     def get_marked( self ):
     29         return self._marked
     30     def set_marked( self, marked ):
     31 #    if marked:
     32 #      print "MARK", self
     33         self._marked = marked
     34     marked = property( get_marked, set_marked )
     35 
     36 #  def __getstate__( self ):
     37 #    return self.__class__, tuple( [ item.__getstate__() for item in self ] )
     38 #  def __setstate__( self, state ):
     39 #    cls, states = state
     40 #    states = list(states)
     41 #    for idx, state in enumerate(states):
     42 #      items[idx] = items[idx].__setstate__( 
     43     def __getstate__(self):
     44         return str(self)
     45     def __setstate__(self, state):
     46         Node.__init__(self)
     47         self[:] = eval(state)
     48 
     49 #  _unique_id = 0
     50 #  def get_unique_id(cls):
     51 #    Node._unique_id += 1
     52 #    return Node._unique_id
     53 #  get_unique_id = classmethod(get_unique_id)
     54 
     55     def __hash__( self ):
     56         return hash( tuple([hash(type(self))]+[hash(item) for item in self]) )
     57 
     58     def clone(self):
     59         l = []
     60         for item in self:
     61             if isinstance(item,Node):
     62                 item = item.clone()
     63             l.append(item)
     64         return self.__class__(*l, **self.__dict__)
     65 
     66     def init_from( self, other ): # class method ?
     67         # Warning: shallow init
     68         self[:] = other
     69         self.__dict__.update( other.__dict__ )
     70         return self
     71 
     72 #  def is_struct(self):
     73 #    for x in self:
     74 #      if isinstance(x,Node):
     75 #        if x.is_struct():
     76 #          return 1
     77 #    return 0
     78 
     79 
     80     #def explain(self):
     81         #l = []
     82         #for x in self:
     83             #if isinstance(x,Node):
     84                 #l.append(x.explain())
     85             #else:
     86                 #l.append(str(x))
     87         #return string.join(l," ") 
     88             ##(self.__class__.__name__,string.join(l) )
     89 
     90     def psource(self):
     91         if hasattr(self,'lines'):
     92 #      print "# "+string.join(self.lines,"\n# ")+"\n"
     93             print "# "+"\n# ".join(self.lines)+"\n"
     94 
     95     def cstr(self,l=None):
     96         """
     97             Build a list of tokens; return the joined tokens string
     98         """
     99         if l is None:
    100             l = []
    101         for x in self:
    102             if isinstance(x,Node):
    103                 x.cstr(l)
    104             else:
    105                 l.insert(0,str(x)+' ')
    106         s = ''.join(l)
    107         return s
    108 
    109     def ctype(self): # anon_clone
    110         " return clone of self without identifiers "
    111         #print "%s.ctype()"%self
    112         l=[]
    113         for x in self:
    114             if isinstance(x,Node):
    115                 l.append(x.ctype())
    116             else:
    117                 l.append(x)
    118         #print "%s.__class__(*%s)"%(self,l)
    119         return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ?
    120 
    121     def cbasetype(self):
    122         " return ctype with all TypeAlias's replaced "
    123         # WARNING: we cache results (so do not mutate self!!)
    124         l=[]
    125         for x in self:
    126             if isinstance(x,Node):
    127                 l.append(x.cbasetype())
    128             else:
    129                 l.append(x)
    130         #print "%s.__class__(*%s)"%(self,l)
    131         return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ?
    132 
    133     def signature( self, tank=None ):
    134         if tank is None:
    135             tank = {}
    136         for node in self.nodes():
    137             if not tank.has_key( type(node) ):
    138                 tank[ type(node) ] = {}
    139                 type(node).tank = tank[type(node)]
    140             shape = tuple( [ type(_node).__name__ for _node in node ] )
    141             if not tank[type(node)].has_key(shape):
    142                 tank[type(node)][shape] = []
    143             tank[type(node)][shape].append( node )
    144         return tank
    145             
    146     def psig( self, tank=None ):
    147         if tank is None:
    148             tank = {}
    149         tank = self.signature(tank)
    150         for key in tank.keys():
    151             print key.__name__
    152             for shape in tank[key].keys():
    153                 print "  ", shape
    154 
    155 #
    156 #################################################
    157 
    158 class Named(genpyx.Named, Node):
    159     " has a .name property "
    160     def get_name(self):
    161         if self:
    162             assert type(self[0])==str
    163             return self[0]
    164         return None
    165     def set_name(self, name):
    166         if self:
    167             self[0] = name
    168         else:
    169             self.append(name)
    170     name = property(get_name,set_name)
    171 
    172 
    173 class BasicType(genpyx.BasicType, Named):
    174     "float double void char int"
    175     pass
    176 
    177 class Qualifier(genpyx.Qualifier, Named):
    178     "register signed unsigned short long const volatile inline"
    179     pass
    180 
    181 class StorageClass(genpyx.StorageClass, Named):
    182     "extern static auto"
    183     pass
    184 
    185 class Ellipses(genpyx.Ellipses, Named):
    186     "..."
    187     pass
    188 
    189 class GCCBuiltin(genpyx.GCCBuiltin, BasicType):
    190     "things with __builtin prefix"
    191     pass
    192 
    193 class Identifier(genpyx.Identifier, Named):
    194     """
    195         shape = +( str, +ConstExpr )
    196     """
    197     #def explain(self):
    198         #if len(self)==1:
    199             #return "%s"%self.name
    200         #else:
    201             #return "%s initialized to %s"%(self.name,
    202                 #Node(self[1]).explain()) # will handle Initializer
    203 
    204 #  def ctype(self):
    205 #    return self.__class__(*self[1:]) #.clone() ?
    206 
    207 #  def get_name(self):
    208 #    if self:
    209 #      return self[0]
    210 #  def set_name(self, name):
    211 #    if self:
    212 #      self[0] = name
    213 #    else:
    214 #      self.append(name)
    215 #  name = property(get_name,set_name)
    216 
    217     def cstr(self,l=None):
    218         if l is None:
    219             l=[]
    220         if len(self)>1:
    221             assert len(self)==2
    222             l.append( '%s = %s'%(self[0],self[1]) )
    223         elif len(self)==1:
    224             l.append( str(self[0]) )
    225         return " ".join(l)
    226 
    227 class TypeAlias(genpyx.TypeAlias, Named):
    228     """
    229      typedefed things, eg. size_t 
    230 
    231     """
    232     def cbasetype( self ):
    233         node = self.typedef.cbasetype().get_rest()
    234         return node
    235 
    236 class Function(genpyx.Function, Node):
    237     """
    238     """
    239     #def explain(self):
    240         #if len(self):
    241             #return "function (%s), returning"%\
    242                 #", ".join( map(lambda x:x.explain(),self) )
    243         #else:
    244             #return "function returning"
    245 
    246     def cstr(self,l):
    247         #print '%s.cstr(%s)'%(self,l)
    248         _l=[]
    249         assert len(self)
    250         i=0
    251         while isinstance(self[i],Declarator):
    252             _l.append( self[i].cstr() )
    253             i=i+1
    254         l.append( '(%s)'% ', '.join(_l) )
    255         while i<len(self):
    256             self[i].cstr(l)
    257             i=i+1
    258         return " ".join(l)
    259 
    260     def return_type(self):
    261         node = self[-1]
    262         #assert isinstance(node,DeclarationSpecifiers)
    263         return Declarator( Identifier(), node )
    264     ret = property(return_type)
    265 
    266     def get_args(self):
    267         args = [ arg for arg in self[:-1] if not arg.is_void() ]
    268         return args
    269     args = property(get_args)
    270 
    271     def arg_types(self):
    272         return [ AbstractDeclarator().init_from( arg.ctype() ) for arg in self[:-1]]
    273 
    274     def is_varargs(self):
    275         for node in self.nodes():
    276             if isinstance(node,Ellipses) or 'va_list' in node:
    277 #        print self, 'is_varargs'
    278                 return True
    279 #    print self, 'is_varargs'
    280         return False
    281 #    return fn.deepfind(Ellipses) or fn.deepfind('va_list')
    282 
    283     def ctype(self):
    284         return Function(*self.arg_types()+[self[-1]]) # XX self[-1].ctype
    285 
    286 
    287 class Pointer(genpyx.Pointer, Node):
    288     """
    289     """
    290     def get_spec(self):
    291         if type(self[0])==TypeSpecifiers: # isinstance ??
    292             return self[0]
    293     spec = property(get_spec)
    294 
    295     #def explain(self):
    296         #return "pointer to"
    297 
    298     def cstr(self,l):
    299         assert len(self)
    300         node=self[0]
    301         l.insert(0,'*')
    302         if isinstance(node,Function):
    303             l.insert(0,'(')
    304             l.append(')')
    305         elif isinstance(node,Array):
    306             l.insert(0,'(')
    307             l.append(')')
    308         return Node.cstr(self,l)
    309 
    310 class Array(genpyx.Array, Node):
    311     """
    312     """
    313     #def explain(self):
    314         #s=''
    315         #if len(self):
    316             #if type(self[0])==int:
    317                 #s='0 to %s '%(self[0]-1)
    318         #return "array %sof"%s
    319     def has_size(self):
    320         try:
    321             int(self.size)
    322             return True
    323         except:
    324             return False
    325 
    326     def get_size(self):
    327         if type(self[-1])==str:
    328             try: return int(self[-1])
    329             except: return self[-1]
    330         return self[-1] # None
    331     size = property(get_size)
    332 
    333     def get_spec(self):
    334         if type(self[0])==TypeSpecifiers: # isinstance ??
    335             return self[0]
    336     spec = property(get_spec)
    337 
    338     def to_pointer(self):
    339         node = Pointer()
    340         node.init_from( self.clone() )
    341         node.pop() # pop the size element
    342         return node
    343 
    344     def cstr(self,l):
    345         if self.size is None:
    346             l.append('[]')
    347         else:
    348             l.append('[%s]'%self.size)
    349         return Node( *self[:-1] ).cstr( l )
    350 
    351 class Tag(genpyx.Tag, Named):
    352     " the tag of a Struct, Union or Enum "
    353     pass
    354 
    355 class Taged(genpyx.Taged, Node):
    356     "Struct, Union or Enum "
    357     def get_tag(self):
    358         if len(self):
    359             tag = self[0]
    360             assert type(tag)==Tag # isinstance ??
    361         else:
    362             tag = None
    363         return tag
    364     def set_tag(self,tag):
    365         if len(self):
    366             self[0] = tag
    367         else:
    368             self.append(tag)
    369     tag = property( get_tag, set_tag )
    370     def has_members(self):
    371         return len(self)>1 # more than just a tag
    372     def get_members(self):
    373         return self[1:]
    374     members = property(get_members) # fields ?
    375 
    376     def ctype(self):
    377         if not self.tag.name:
    378             #print "# WARNING : anonymous struct " # OK i think
    379             return self.clone()
    380 #    self = self.clone()
    381 #    return self[:1] # just the tag
    382         return self.__class__( self.tag, **self.__dict__ ) # just the Tag
    383 #    return self.__class__( *self, **self.__dict__ )
    384 
    385     def cbasetype(self):
    386         return self.ctype() # is this enough ???
    387 #    return Node.cbasetype(self) # XX lookup my tag if i am empty ..?
    388 
    389 
    390 class Compound(genpyx.Compound, Taged):
    391     "Struct or Union"
    392 
    393     def cstr(self,_l=None):
    394         assert isinstance( self[0], Tag )
    395         tag=''
    396         if len(self[0]):
    397             tag=' '+self[0][0]
    398         if isinstance(self,Struct):
    399             l=[ 'struct%s '%tag ]
    400         elif isinstance(self,Union):
    401             l=[ 'union%s '%tag ]
    402         if len(self)>1:
    403             l.append(' { ')
    404             for decl in self[1:]:
    405                 l.append( decl.cstr()+"; " )
    406             l.append('} ')
    407         if _l is None:
    408             _l=[]
    409         while l:
    410             _l.insert( 0, l.pop() )
    411         # XX empty struct with no tag -> "struct" XX
    412         return "".join( _l )
    413 
    414     def ctype(self):
    415         tp = Taged.ctype(self)
    416         for i in range(1,len(tp)):
    417             tp[i] = StructDeclarator().init_from( tp[i] )
    418         return tp
    419 
    420 class Struct(genpyx.Struct, Compound):
    421     """
    422     """
    423     pass
    424 
    425 
    426 class Union(genpyx.Union, Compound):
    427     """
    428     """
    429     pass
    430 
    431 
    432 class Enum(genpyx.Enum, Taged):
    433     """
    434     """
    435     def cstr(self,_l=None):
    436         assert isinstance( self[0], Tag )
    437         tag=''
    438         if len(self[0]):
    439             tag=' '+self[0][0]
    440         l=[ 'enum%s '%tag ]
    441         if len(self)>1:
    442             l.append(' { ')
    443             for node in self[1:]:
    444                 l.append( node.cstr()+', ' )
    445             l.append('} ')
    446         if _l is None:
    447             _l=[]
    448         while l:
    449             _l.insert( 0, l.pop() )
    450         return ''.join( _l )
    451 
    452 class Declarator(genpyx.Declarator, Node):
    453     """
    454     """
    455 
    456     def __eq__(self,other):
    457         " unordered equality "
    458         # ordering sometimes gets lost when we do a cbasetype
    459         if not isinstance(other,Node):
    460             return False
    461         a, b = self[:], other[:]
    462         a.sort()
    463         b.sort()
    464         return a == b
    465 
    466     def __hash__( self ):
    467         hs = [hash(item) for item in self]
    468         hs.sort()
    469         return hash( tuple([hash(type(self))]+hs) )
    470 
    471     def transform(self):
    472         return
    473 
    474     def get_identifier(self):
    475         if len(self)>1:
    476             return self[0]
    477     def set_identifier(self, identifier):
    478         if len(self)>1:
    479             self[0] = identifier
    480         else:
    481             self.insert(0,identifier)
    482     identifier = property(get_identifier,set_identifier)
    483 
    484     def get_spec(self):
    485         spec = self[-1]
    486         if type(spec)==TypeSpecifiers: # isinstance ??
    487             return spec
    488     spec = property(get_spec)
    489 
    490     def get_type_alias(self):
    491         if self.spec:
    492             if isinstance(self.spec[0], TypeAlias):
    493                 return self.spec[0]
    494     type_alias = property(get_type_alias)
    495 
    496     def get_tagged(self):
    497         if self.spec:
    498             return self.spec.tagged # i am a tagged
    499     tagged = property(get_tagged)
    500 
    501     def get_compound(self):
    502         if self.spec:
    503             return self.spec.compound # i am a compound
    504     compound = property(get_compound)
    505 
    506     def get_struct(self):
    507         if self.spec:
    508             return self.spec.struct # i am a struct
    509     struct = property(get_struct)
    510 
    511     def get_union(self):
    512         if self.spec:
    513             return self.spec.union # i am a union
    514     union = property(get_union)
    515 
    516     def get_enum(self):
    517         if self.spec:
    518             return self.spec.enum # i am an enum
    519     enum = property(get_enum)
    520 
    521     def get_function(self):
    522         if len(self)>1 and type(self[1])==Function: # isinstance ??
    523             return self[1]
    524     function = property(get_function)
    525 
    526     def get_pointer(self):
    527         if len(self)>1 and type(self[1])==Pointer: # isinstance ??
    528             return self[1]
    529     pointer = property(get_pointer)
    530 
    531     def get_array(self):
    532         if len(self)>1 and type(self[1])==Array: # isinstance ??
    533             return self[1]
    534     array = property(get_array)
    535 
    536     def get_name(self):
    537         if self.identifier:
    538             return self.identifier.name
    539     def set_name(self, name):
    540         assert self.identifier is not None
    541         self.identifier.name = name
    542     name = property(get_name, set_name)
    543 
    544     def get_rest(self): # XX needs a better name
    545         if len(self)>1:
    546             return self[1]
    547         return self[0]
    548 
    549     def pointer_to( self ):
    550         " return Declarator pointing to self's type "
    551         decl = Declarator(Identifier(), Pointer(self.get_rest().clone()))
    552         return decl
    553 
    554     def deref( self ):
    555         " return (clone of) Declarator that self is pointing to "
    556         node = self.ctype() # clone
    557         pointer = node.pointer or node.array
    558         assert pointer, "cannot dereference non-pointer"
    559         node[1:2] = pointer
    560         return node
    561 
    562     def is_void(self):
    563         return self.spec and BasicType('void') in self.spec
    564 
    565     def is_pointer_to_fn(self):
    566         return self.pointer and self.deref().function
    567 
    568     def is_pointer_to_char(self):
    569 #    return self.ctype() == TransUnit("char *a;").transform()[0].ctype()
    570         node = self.pointer or self.array
    571         if node:
    572             spec = node.spec 
    573             if spec and BasicType('char') in spec and not BasicType('unsigned') in spec:
    574                 return True
    575         return False
    576 
    577     def is_callback(self):
    578         " i am a pointer to a function whose last arg is void* "
    579         if self.is_pointer_to_fn():
    580             fn = self.deref().function
    581             if fn.args:
    582                 arg = fn.args[-1]
    583                 if arg.pointer and arg.deref().is_void():
    584                     return True
    585 
    586     def is_complete( self, tag_lookup ):
    587         if self.tagged and self.tagged.tag.name in tag_lookup and not tag_lookup[self.tagged.tag.name].has_members():
    588             return False
    589         return True
    590 
    591     def is_primative( self ):
    592         "i am a char,short,int,float,double... "
    593         spec = self.cbasetype().spec
    594         return spec and spec.find(BasicType)
    595 
    596     def is_pyxnative( self ):
    597         # pyrex handles char* too
    598         # but i don't know if we should make this the default
    599         # sometimes we want to send a NULL, so ... XXX
    600         self = self.cbasetype()
    601         if self.is_void():
    602             return False
    603         if self.is_primative():
    604             return True
    605         if self.enum:
    606             return True
    607 #    pointer = None
    608 #    if self.pointer:
    609 #      pointer = self.pointer
    610 #    elif self.array:
    611 #      pointer = self.array
    612 #    if pointer and pointer.spec:
    613 #      spec = pointer.spec
    614 #      if BasicType("char") in spec and not Qualifier("unsigned") in spec:
    615 #        # char*, const char*
    616 ##        print self.deepstr()
    617 #        return True
    618         return False
    619 
    620     def cstr(self,l=None):
    621         return Node.cstr(self,l).strip()
    622 
    623     def ctype(self):
    624         decl=Declarator()
    625         decl.init_from( self.clone() )
    626         decl.identifier = Identifier()
    627         for i in range(1,len(decl)):
    628             decl[i]=decl[i].ctype()
    629         return decl
    630 
    631     def cbasetype(self):
    632         # WARNING: we cache results (so do not mutate self!!)
    633         try:
    634             # this cache improves performance by 50%
    635             return self.__cbasetype.clone()
    636         except AttributeError:
    637             pass
    638         decl = self.ctype() # gets rid of Identifier names
    639         for i, node in enumerate(decl):
    640             decl[i] = decl[i].cbasetype()
    641 #    return decl.get_rest()
    642 
    643         done = False
    644         while not done:
    645             done = True
    646             nodes = decl.deepfilter( TypeSpecifiers )
    647             for node in nodes:
    648                 if node.deepfind( TypeSpecifiers ) != node:
    649                     # this node has another TypeSpecifier;
    650                     decl.expose_node( node )
    651                     done = False
    652                     break # start again...
    653 
    654         # each TypeSpecifier needs to absorb primitive siblings (StorageClass, BasicType etc.)
    655         nodes = decl.deepfilter( TypeSpecifiers )
    656         for node in nodes:
    657             parent = decl.get_parent(node)
    658             i = 0
    659             while i < len(parent):
    660                 assert not type(parent[i]) in (TypeAlias, Enum, Struct, Union)
    661                 if type(parent[i]) in (StorageClass, BasicType, Qualifier):
    662                     node.append( parent.pop(i) )
    663                 else:
    664                     i = i + 1
    665 
    666         self.__cbasetype = decl.clone()
    667         return decl
    668 
    669     def invalidate(self):
    670         # flush cache, etc.
    671         try:
    672             del self.__cbasetype
    673         except AttributeError:
    674             pass
    675 
    676     def declare_str(self,name):
    677         " return c string declaring name with same type as self "
    678         tp = self.ctype()
    679         tp.name = name
    680         return tp.cstr()+";"
    681 
    682 class Typedef(genpyx.Typedef, Declarator):
    683     def cstr(self,l=None):
    684         return 'typedef ' + Declarator.cstr(self,l) #.strip()
    685 
    686 class AbstractDeclarator(genpyx.AbstractDeclarator, Declarator):
    687     """ used in Function; may lack an identifier """
    688 
    689     #def cstr(self,l=None):
    690         #return Node.cstr(self,l)
    691 
    692 #  def ctype(self):
    693 #    # _type_ ignores the name of our identifier
    694 #    return Node.ctype(self)
    695 
    696 class FieldLength(genpyx.FieldLength, Node):
    697     """
    698     """
    699     #def explain(self):
    700         #return ""
    701 
    702     def cstr(self,l):
    703         l.append(':%s'%self[0]) 
    704 
    705 class StructDeclarator(genpyx.StructDeclarator, Declarator): # also used in Union
    706     """
    707     """
    708     #def explain(self):
    709         #flen = self.find(FieldLength)
    710         #if flen is not None:
    711             #i = self.index(flen)
    712             #self.pop(i)
    713             #s = Declarator.explain(self)
    714             #self.insert(i,flen)
    715             #width = flen[0]
    716             #if width > 0:
    717                 #return s+" bitfield %s wide"%width
    718             #else:
    719                 #return s+" alignment bitfield"
    720         #else:
    721             #return Declarator.explain(self)
    722 #  def ctype(self):
    723 #    return self   
    724     def get_field_length(self):
    725         if len(self)>1 and isinstance( self[1], FieldLength ):
    726             return self[1]
    727     field_length = property(get_field_length)
    728 
    729 
    730 class DeclarationSpecifiers(genpyx.DeclarationSpecifiers, Node):
    731 #class TypeSpecifiers(Node):
    732     """
    733     """
    734     def __eq__(self,other):
    735         " unordered equality "
    736         if not isinstance(other,Node):
    737             return False
    738         a, b = self[:], other[:]
    739         a.sort()
    740         b.sort()
    741         return a == b
    742 
    743     def __hash__( self ):
    744         hs = [hash(item) for item in self]
    745         hs.sort()
    746         return hash( tuple([hash(type(self))]+hs) )
    747 
    748 #  def is_struct(self):
    749 #    return self.find(Struct) is not None
    750 
    751 
    752 class TypeSpecifiers(genpyx.TypeSpecifiers, DeclarationSpecifiers):
    753     """
    754     """
    755     def get_tagged(self):
    756         if self and isinstance(self[0],Taged):
    757             return self[0]
    758     tagged = property(get_tagged)
    759 
    760     def get_compound(self):
    761         if self and isinstance(self[0],Compound):
    762             return self[0]
    763     compound = property(get_compound)
    764 
    765     def get_struct(self):
    766         if self and isinstance(self[0],Struct):
    767             return self[0]
    768     struct = property(get_struct)
    769 
    770     def get_union(self):
    771         if self and isinstance(self[0],Union):
    772             return self[0]
    773     union = property(get_union)
    774 
    775     def get_enum(self):
    776         if self and isinstance(self[0],Enum):
    777             return self[0]
    778     enum = property(get_enum)
    779 
    780     def cbasetype(self):
    781         node = Node.cbasetype(self)
    782 #    node.expose( TypeSpecifiers )
    783 #    if node.deepfind(TypeSpecifiers) != node:
    784         return node
    785 
    786 class Initializer(genpyx.Initializer, Node):
    787     """
    788     """
    789     pass
    790 
    791 
    792 
    793 class Declaration(genpyx.Declaration, Node):
    794     """
    795     """
    796     def do_spec(self):
    797         " distribute DeclarationSpecifiers over each Declarator "
    798         spec=self[0]
    799         assert isinstance(spec,DeclarationSpecifiers), spec.deepstr()
    800         self.pop(0)
    801         for declarator in self:
    802             assert isinstance(declarator,Declarator)
    803             #if isinstance(declarator,DeclarationSpecifiers #huh?
    804             ##for node in spec:
    805                 ##declarator.append(node.clone())
    806             declarator.append(spec)
    807 
    808     def transform(self):
    809         # children go first 
    810         for node in self.nodes():
    811             if isinstance(node,Declaration):
    812                 node.do_spec()
    813             node.file = self.file # overkill ?
    814         self.expose(Declaration)
    815 
    816     #def explain(self):
    817         #return string.join([x.explain() for x in self],", ") 
    818         #return string.join(map(lambda x:x.explain(),self),", ") 
    819 
    820 
    821 class ParameterDeclaration(genpyx.ParameterDeclaration, Declaration):
    822     """
    823     """
    824     pass
    825 
    826 
    827 class StructDeclaration(genpyx.StructDeclaration, Declaration):
    828     """
    829     """
    830     pass
    831 
    832 
    833 class TransUnit(genpyx.TransUnit, Node):
    834     """
    835         Top level node.
    836     """
    837     def __init__( self, item ): # XX __init__ uses different signature ! XX
    838         if type(item)==str:
    839             node = cparse.TransUnit()
    840             node.parse(item)
    841         else:
    842             node = item
    843             assert isinstance( node, cparse.TransUnit ), str(node)
    844         Node.__init__(self)
    845         self[:] = [ self.convert(child) for child in node ]
    846         self.__dict__.update( node.__dict__ )
    847         assert "name" not in node.__dict__
    848 
    849         self.syms = {} # map identifier names to their Declarator's
    850         self.typedefs = {} # map names to Typedef's
    851         self.tag_lookup = {} # map struct, union, enum tags to Taged's
    852 
    853         # XX should call transform here XX
    854 
    855 #    print self.deepstr()
    856     def __getstate__( self ):
    857         nodes = tuple( [ repr(node) for node in self ] )
    858         typedefs = tuple( [ (key,repr(val)) for key,val in self.typedefs.items() ] )
    859         return nodes, typedefs
    860     def __setstate__( self, state ):
    861         Node.__init__(self)
    862         nodes, typedefs = state
    863         nodes = [ eval(node) for node in nodes ]
    864         self[:] = nodes
    865         typedefs = [ (key,eval(val)) for key,val in typedefs ]
    866         self.typedefs = dict(typedefs)
    867 
    868     def convert( self, node ):
    869 #    name = node.__class__.__name__
    870 #    cls = globals()[ name ]
    871         cls = cls_lookup[ type(node) ]
    872         _node = cls()
    873         for child in node:
    874             if isinstance(child, node_module.Node):
    875                 child = self.convert( child )
    876             else:
    877                 assert child is None or type(child) in (str, int), type(child)
    878             _node.append( child )
    879         _node.__dict__.update( node.__dict__ )
    880         return _node
    881 
    882     def strip(self,files):
    883         " leave only the declarations from <files> "
    884         i=0
    885         while i<len(self):
    886             if self[i].file in files:
    887                 i=i+1
    888             else:
    889                 self.pop(i)
    890 
    891     def mark(self,cb,verbose=False):
    892         " mark our child nodes such that cb(node).. mark dependants too. prune unmarked objects. "
    893         # mark the nodes:
    894         for node in self:
    895             node.marked = cb(self, node)
    896             if verbose and node.marked:
    897                 print '1:', node.cstr()
    898         # propagate dependancy:
    899         i=len(self)
    900         while i:
    901             i-=1 # we go backwards
    902             for node in self[i].nodes(): # bottom-up search
    903                 if verbose and self[i].marked and not node.marked:
    904                     print '2:', str(node), '<--', self[i].cstr()
    905                 node.marked = self[i].marked or node.marked
    906                 if type(node)==TypeAlias:
    907                     if verbose and node.marked and not node.typedef.marked:
    908                         print '3:', node.typedef.cstr(), '<--', node.cstr()
    909                     node.typedef.marked = node.typedef.marked or node.marked
    910                 if isinstance(node, Taged):
    911                     if node.tag.name in self.tag_lookup:
    912                         _node = self.tag_lookup[ node.tag.name ] # look-up the def'n
    913                         if verbose and node.marked and not _node.marked: 
    914                             print '4:', _node.cstr(), '<--', self[i].cstr()
    915 #            _node.marked = _node.marked or self[i].marked
    916                         _node.marked = _node.marked or node.marked
    917 #          else:
    918 #            # this guy has no tag
    919 #            print "lost tag:", self[i].cstr()
    920 
    921                  # XX struct defs acquire marks from members, but XX
    922                  # XX ordinary definitions do not                 XX
    923 #        if node.marked and not self[i].marked:
    924 #          # one of my descendants is marked
    925 #          if verbose:
    926 #            print '5:', self[i].cstr(), '<--', node.cstr()
    927 #          self[i].marked = True
    928 #    if verbose:
    929 #      for node in self:
    930 #        print '-'*79
    931 #        if node.enum:
    932 #          print str(node.marked) + ': ' + node.cstr()
    933         # prune:
    934         f = open(".tmp/pruned.txt","w")
    935         f.write("// This file autogenerated by '%s' .\n"%__file__)
    936         f.write("// List of functions pruned from parse tree, for various reasons.\n\n")
    937         i=0
    938         while i<len(self):
    939             if not self[i].marked:
    940                 if verbose: print 'pop:', self[i].cstr()
    941                 f.write( self[i].cstr() + "\n" )
    942                 self.pop(i)
    943 #      elif self[i].compound:
    944 #        # XXXX for now, rip out all struct members XXXX
    945 #        self[i].compound[1:] = [] # XX encapsulation
    946 #        i = i + 1
    947             else:
    948                 i = i + 1
    949         for key, value in self.syms.items():
    950             if not value.marked:
    951                 del self.syms[key]
    952         for key, value in self.typedefs.items():
    953             if not value.marked:
    954                 del self.typedefs[key]
    955         for key, value in self.tag_lookup.items():
    956             if not value.marked:
    957                 del self.tag_lookup[key]
    958 #    sys.exit(1)
    959 
    960     def assert_no_dups(self):
    961         check={}
    962         for node in self.nodes():
    963             assert not check.has_key(id(node))
    964             check[id(node)]=1
    965 
    966     def transform(self, verbose=False, test_parse=False, test_types=False ):
    967         i=0
    968         while i < len(self):
    969             if verbose: print "##"*25
    970             declaration=self[i]
    971 
    972             if verbose: declaration.psource()
    973             if verbose: print declaration.deepstr(),'\n'
    974             assert isinstance(declaration,Declaration)
    975             if verbose: print "# expose declarators from declaration"
    976 
    977             # STAGE 1
    978             declaration.transform()
    979 
    980             if verbose: print declaration.deepstr(),'\n'
    981             self[i:i+1] = declaration # expose declarators from declaration
    982 
    983             for j in range(len(declaration)):
    984                 declarator=self[i]
    985 
    986                 assert isinstance(declarator,Declarator)
    987                 if verbose: print "# declarator.transform()"
    988 
    989                 # STAGE 2
    990                 declarator.transform()
    991 
    992                 if verbose: print declarator.deepstr(),'\n'
    993                 if verbose: print "# self.visit_declarator(declarator)"
    994 
    995                 # STAGE 3
    996                 self[i] = declarator = self.visit_declarator(declarator)
    997 
    998                 # STAGE 4 
    999                 if declarator.name:
   1000                     if isinstance(declarator, Typedef):
   1001                         if verbose: print "# typedef %s" % declarator.name
   1002                         self.typedefs[ declarator.name ] = declarator
   1003                     else:
   1004                         if verbose: print "# sym %s" % declarator.name
   1005                         self.syms[ declarator.name ] = declarator
   1006 
   1007                 for node in declarator.nodes():
   1008                     if isinstance(node,Taged) and node.tag.name:
   1009                         assert type(node.tag.name)==str, node.deepstr()
   1010                         taged = self.tag_lookup.get( node.tag.name, None )
   1011                         if taged is None:
   1012                             if verbose: print "# tag lookup %s = %s" % (declarator.name, node.tag.name)
   1013                             self.tag_lookup[ node.tag.name ] = node
   1014                         elif not taged.has_members():
   1015                             # this is (maybe) the definition of this tag
   1016                             if verbose: print "# definition %s = %s" % (declarator.name, node.tag.name)
   1017                             self.tag_lookup[ node.tag.name ] = node 
   1018 
   1019                 # Annotate the TypeAlias's
   1020                 for node in declarator.deepfilter( TypeAlias ):
   1021                     name = node[0]
   1022                     assert type( name ) == str
   1023                     node.typedef = self.typedefs[ name ]
   1024 
   1025                 if verbose: print declarator.deepstr(),'\n'
   1026                 #print declarator.ctype().deepstr(),'\n'
   1027                 #assert declarator.clone() == declarator
   1028 
   1029                 ###################################################
   1030                 # TESTS:
   1031                 if test_parse:
   1032                     # test that parse of cstr gives same answer
   1033                     cstr = declarator.cstr()+';\n'
   1034                     if verbose: print '# '+cstr.replace('\n','\n# ')
   1035                     #print
   1036                     if isinstance(declarator,Typedef):
   1037                         name = declarator[0][0]
   1038                         assert type(name)==str
   1039                         self.lexer.rmtypedef( name )
   1040                     declaration = cparse.Declaration()
   1041                     self.lexer.lex( cstr )
   1042                     #print self.lexer.err_string()
   1043                     declaration.parse(  self.lexer, Symbols() ) # use new name-space
   1044                     #declaration.parse(  Lexer( cstr ), Symbols() )
   1045                     declaration = self.convert(declaration)
   1046                     declaration.transform()
   1047                     assert len(declaration)==1
   1048                     decl=declaration[0]
   1049                     decl.transform()
   1050                     decl = self.visit_declarator(decl)
   1051                     if decl!=declarator:
   1052                         if verbose: print "#???????????"
   1053                         if verbose: print decl.deepstr(),'\n\n'
   1054                         #if verbose: print declaration.deepstr(),'\n\n'
   1055                         #assert 0
   1056                     elif verbose: print '# OK\n'
   1057 
   1058                 if test_types:
   1059                     node = declarator.ctype()
   1060                     declare_str= node.declare_str("my_name")
   1061                     if verbose: print "# declarator.ctype() "
   1062                     if verbose: print node.deepstr(),"\n"
   1063                     if verbose: print "#",declare_str.replace('\n','\n# '), '\n'
   1064 
   1065                 i=i+1
   1066         return self
   1067 
   1068     def visit(self,node):
   1069         #print 'visit(%s)'%node
   1070         for _node in node:
   1071             if isinstance(_node,Declarator):
   1072                 _node = self.visit_declarator(_node) # XX replace _node
   1073             elif isinstance(_node,Node):
   1074                 _node = self.visit(_node) # XX replace _node
   1075         return node
   1076 
   1077     def visit_declarator(self,decl):
   1078         assert isinstance(decl,Declarator)
   1079 
   1080         # STAGE 3.a
   1081         tp = decl.deepfind(Typedef)
   1082         if tp is not None:
   1083             decl.deeprm(tp)
   1084             tp.init_from( decl ) # warning: shallow init
   1085             decl = tp
   1086 
   1087         # STAGE 3.b
   1088         i=len(decl)
   1089         # accumulate nodes (they become the children of decl)
   1090         children=[]
   1091         while i:
   1092             i=i-1
   1093             node=decl.pop(i)
   1094             if isinstance(node,Declarator):
   1095                 node = self.visit_declarator(node) # replace node
   1096             else:
   1097                 node = self.visit(node) # replace node
   1098             if isinstance(node,Pointer):
   1099                 node+=children
   1100                 children=[node]
   1101             elif isinstance(node,Function):
   1102                 node+=children
   1103                 children=[node]
   1104             elif isinstance(node,Array):
   1105                 while children:
   1106                     node.insert(0,children.pop())
   1107                 children=[node]
   1108                 # array size (if any) at end
   1109             #elif isinstance(node,Identifier):
   1110                 #node+=children
   1111                 #children=[node]
   1112             else:
   1113                 # accumulate
   1114                 children.insert(0,node)
   1115         decl[:]=children
   1116         return decl
   1117 
   1118     cstr = None
   1119     ctype = None
   1120     cbasetype = None
   1121 
   1122 
   1123 # remap the global class definitions in genpyx to
   1124 # point to the definitions in this module
   1125 gbl = globals()
   1126 for key, val in gbl.items():
   1127     if type(val)==type:
   1128         if issubclass(val,Node):
   1129             setattr( genpyx, key, val )
   1130 assert genpyx.Node == Node
   1131 
   1132 cls_lookup = {
   1133 #  Node : Node ,
   1134     cparse.BasicType : BasicType ,
   1135     cparse.Qualifier : Qualifier ,
   1136     cparse.StorageClass : StorageClass ,
   1137     cparse.Ellipses : Ellipses ,
   1138     cparse.GCCBuiltin : GCCBuiltin ,
   1139     cparse.Identifier : Identifier ,
   1140     cparse.TypeAlias : TypeAlias ,
   1141     cparse.Function : Function ,
   1142     cparse.Pointer : Pointer ,
   1143     cparse.Array : Array ,
   1144     cparse.Tag : Tag ,
   1145     cparse.Compound : Compound ,
   1146     cparse.Struct : Struct ,
   1147     cparse.Union : Union ,
   1148     cparse.Enum : Enum ,
   1149     cparse.Declarator : Declarator ,
   1150     cparse.Typedef : Typedef ,
   1151     cparse.AbstractDeclarator : AbstractDeclarator ,
   1152     cparse.FieldLength : FieldLength ,
   1153     cparse.StructDeclarator : StructDeclarator ,
   1154     cparse.DeclarationSpecifiers : TypeSpecifiers ,
   1155     cparse.TypeSpecifiers : TypeSpecifiers ,
   1156     cparse.Initializer : Initializer ,
   1157     cparse.Declaration : Declaration ,
   1158     cparse.ParameterDeclaration : ParameterDeclaration ,
   1159     cparse.StructDeclaration : StructDeclaration ,
   1160     cparse.TransUnit : TransUnit ,
   1161 }
   1162 
   1163 
   1164