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