145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#!/usr/bin/env python
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org""" genpyx.py - parse c declarations
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org(c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com>
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgReleased under GNU LGPL license.
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgversion 0.xx
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgThis is a module of mixin classes for ir.py .
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgTowards the end of ir.py our global class definitions
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgare remapped to point to the class definitions in ir.py .
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgSo, for example, when we refer to Node we get ir.Node .
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org"""
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgimport sys
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfrom datetime import datetime
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# XX use this Context class instead of all those kw dicts !! XX
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Context(object):
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    " just a record (struct) "
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __init__( self, **kw ):
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for key, value in kw.items():
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            setattr( self, key, value )
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __getattr__( self, name ):
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return None # ?
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __getitem__( self, name ):
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return getattr(self, name)
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass OStream(object):
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def __init__( self, filename=None ):
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.filename = filename
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.tokens = []
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self._indent = 0
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def put( self, token="" ):
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert type(token) is str
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.tokens.append( token )
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def startln( self, token="" ):
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert type(token) is str
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.tokens.append( '    '*self._indent + token )
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def putln( self, ln="" ):
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert type(ln) is str
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.tokens.append( '    '*self._indent + ln + '\n')
4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def endln( self, token="" ):
4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert type(token) is str
4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self.tokens.append( token + '\n')
4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def indent( self ):
4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self._indent += 1
5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def dedent( self ):
5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self._indent -= 1
5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert self._indent >= 0, self._indent
5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def join( self ):
5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ''.join( self.tokens )
5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def close( self ):
5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s = ''.join( self.tokens )
5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        f = open( self.filename, 'w' )
5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        f.write(s)
5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#
6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org###############################################################################
6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#
6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Node(object):
6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tree structure
6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    _unique_id = 0
6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def get_unique_id(cls):
7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Node._unique_id += 1
7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return Node._unique_id
7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    get_unique_id = classmethod(get_unique_id)
7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# XX toks: use a tree of tokens: a list that can be push'ed and pop'ed XX
7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,**kw):
7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        """
7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            Build a list of tokens; return the joined tokens string
7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        """
7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if toks is None:
8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = []
8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for x in self:
8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if isinstance(x,Node):
8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                x.pyxstr(toks, indent, **kw)
8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else:
8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.insert(0,str(x)+' ')
8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s = ''.join(toks)
8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return s
8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#
9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#################################################
9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Named(object):
9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "has a .name property"
9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass BasicType(object):
9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "float double void char int"
9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Qualifier(object):
10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "register signed unsigned short long const volatile inline"
10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,**kw):
10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if toks is None:
10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = []
10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        x = self[0]
10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if x not in ( 'const','volatile','inline','register'): # ignore these
10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.insert(0,str(x)+' ')
10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s = ''.join(toks)
10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return s
11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass StorageClass(object):
11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "extern static auto"
11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,**kw):
11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ""
11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Ellipses(object):
11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "..."
11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass GCCBuiltin(BasicType):
12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "things with __builtin prefix"
12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Identifier(object):
12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,**kw):
12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if toks is None:
12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks=[]
13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.name:
13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append( self.name )
13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return " ".join(toks)
13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass TypeAlias(object):
13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org     typedefed things, eg. size_t
13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,cprefix="",**kw):
13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if toks is None:
14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = []
14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for x in self:
14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if isinstance(x,Node):
14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                x.pyxstr(toks, indent, cprefix=cprefix, **kw)
14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            else:
14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                s = str(x)+' '
14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if cprefix:
14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    s = cprefix+s
14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.insert(0,s)
14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        s = ''.join(toks)
15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return s
15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
15245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Function(object):
15345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
15445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
15545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks,indent=0,**kw):
15645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #print '%s.pyxstr(%s)'%(self,toks)
15745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        _toks=[]
15845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert len(self)
15945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        i=0
16045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while isinstance(self[i],Declarator):
16145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if not self[i].is_void():
16245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                _toks.append( self[i].pyxstr(indent=indent, **kw) )
16345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i=i+1
16445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        toks.append( '(%s)'% ', '.join(_toks) )
16545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while i<len(self):
16645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            self[i].pyxstr(toks, indent=indent, **kw)
16745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            i=i+1
16845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return " ".join(toks)
16945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
17045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Pointer(object):
17145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
17245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
17345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks,indent=0,**kw):
17445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert len(self)
17545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        node=self[0]
17645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        toks.insert(0,'*')
17745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if isinstance(node,Function):
17845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.insert(0,'(')
17945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append(')')
18045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif isinstance(node,Array):
18145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.insert(0,'(')
18245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append(')')
18345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return Node.pyxstr(self,toks,indent, **kw)
18445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
18545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Array(object):
18645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
18745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
18845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks,indent=0,**kw):
18945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.size is None:
19045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append('[]')
19145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
19245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            try:
19345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                int(self.size)
19445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append('[%s]'%self.size)
19545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            except:
19645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append('[]')
19745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return Node( *self[:-1] ).pyxstr( toks,indent, **kw )
19845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
19945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Tag(object):
20045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    " the tag of a Struct, Union or Enum "
20145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
20245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Taged(object):
20445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "Struct, Union or Enum "
20545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
20645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
20745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Compound(Taged):
20845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    "Struct or Union"
20945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,_toks=None,indent=0,cprefix="",shadow_name=True,**kw):
21045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if _toks is None:
21145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            _toks=[]
21245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        names = kw.get('names',{})
21345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        kw['names'] = names
21445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        tag_lookup = kw.get('tag_lookup')
21545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.tag:
21645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tag=self.tag.name
21745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
21845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tag = ''
21945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if isinstance(self,Struct):
22045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            descr = 'struct'
22145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        elif isinstance(self,Union):
22245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            descr = 'union'
22345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        _node = names.get(self.tag.name,None)
22445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ( _node is not None and _node.has_members() ) or \
22545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ( _node is not None and not self.has_members() ):
22645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            descr = '' # i am not defining myself here
22745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #print "Compound.pyxstr", tag
22845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #print self.deepstr()
22945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if descr:
23045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if cprefix and shadow_name:
23145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tag = '%s%s "%s"'%(cprefix,tag,tag)
23245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elif cprefix:
23345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tag = cprefix+tag
23445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = [ descr+' '+tag ] # struct foo
23545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if self.has_members():
23645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append(':\n')
23745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                for decl in self[1:]: # XX self.members
23845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    toks.append( decl.pyxstr(indent=indent+1, cprefix=cprefix, shadow_name=shadow_name, **kw)+"\n" ) # shadow_name = False ?
23945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #elif not tag_lookup.get( self.tag.name, self ).has_members():
24045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                # define empty struct here, it's the best we're gonna get
24145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #pass
24245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
24345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if cprefix: # and shadow_name:
24445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                tag = cprefix+tag
24545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = [ ' '+tag+' ' ] # foo
24645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while toks:
24745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            _toks.insert( 0, toks.pop() )
24845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return "".join( _toks )
24945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Struct(Compound):
25145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
25245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
25345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
25445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
25545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Union(Compound):
25645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
25745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
25845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
25945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
26145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Enum(Taged):
26245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
26345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
26445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,_toks=None,indent=0,cprefix="",shadow_name=True,**kw):
26545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if _toks is None:
26645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            _toks=[]
26745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        names = kw.get('names',{})
26845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        kw['names'] = names
26945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.tag:
27045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tag=self.tag.name
27145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
27245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            tag = ''
27345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        _node = names.get(self.tag.name,None)
27445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if ( _node is not None and _node.has_members() ) or \
27545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ( _node is not None and not self.has_members() ):
27645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            descr = '' # i am not defining myself here
27745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
27845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            descr = 'enum'
27945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if descr:
28045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #if not names.has_key(self.tag.name):
28145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = [ descr+' '+tag ] # enum foo
28245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append(':\n')
28345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            idents = [ ident for ident in self.members if ident.name not in names ]
28445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for ident in idents:
28545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if cprefix and shadow_name:
28645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ident = ident.clone()
28745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ident.name = '%s%s "%s"' % ( cprefix, ident.name, ident.name )
28845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #else: assert 0
28945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append( '    '+'    '*indent + ident.pyxstr(**kw)+"\n" )
29045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                names[ ident.name ] = ident
29145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if not idents:
29245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                # empty enum def'n !
29345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #assert 0 # should be handled by parents...
29445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append( '    '+'    '*indent + "pass\n" )
29545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        else:
29645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks = [ ' '+tag+' ' ] # foo
29745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        while toks:
29845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            _toks.insert( 0, toks.pop() )
29945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return "".join( _toks )
30045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
30145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Declarator(object):
30245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def is_pyxnative( self ):
30345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        # pyrex handles char* too
30445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        # but i don't know if we should make this the default
30545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        # sometimes we want to send a NULL, so ... XX
30645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self = self.cbasetype() # WARNING: cbasetype may be cached
30745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.is_void():
30845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return False
30945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.is_primative():
31045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return True
31145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.enum:
31245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            return True
31345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #pointer = None
31445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #if self.pointer:
31545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #pointer = self.pointer
31645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #elif self.array:
31745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #pointer = self.array
31845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #if pointer and pointer.spec:
31945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #spec = pointer.spec
32045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #if BasicType("char") in spec and not Qualifier("unsigned") in spec:
32145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                # char*, const char*
32245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ##print self.deepstr()
32345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #return True
32445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return False
32545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
32645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def _pyxstr( self, toks, indent, cprefix, use_cdef, shadow_name, **kw ):
32745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        " this is the common part of pyxstr that gets called from both Declarator and Typedef "
32845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        names = kw.get('names',{}) # what names have been defined ?
32945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        kw['names']=names
33045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for node in self.nodes(): # depth-first
33145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if isinstance(node,Taged):
33245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #print "Declarator.pyxstr", node.cstr()
33345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if not node.tag.name:
33445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    node.tag.name = "_anon_%s" % Node.get_unique_id()
33545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                _node = names.get(node.tag.name,None)
33645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #tag_lookup = kw.get('tag_lookup')
33745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #other = tag_lookup.get(node.tag.name, node)
33845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #if ((_node is None and (not isinstance(other,Compound) or not other.has_members()))
33945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #    or node.has_members()):
34045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if _node is None or node.has_members():
34145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    # either i am not defined at all, or this is my _real_ definition
34245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    # emit def'n of this node
34345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    #if isinstance(self,Typedef):
34445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                        #toks.append( '    '*indent + 'ctypedef ' + node.pyxstr(indent=indent, cprefix=cprefix, shadow_name=shadow_name, **kw).strip() )
34545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    #else:
34645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    toks.append( '    '*indent + 'cdef ' + node.pyxstr(indent=indent, cprefix=cprefix, shadow_name=shadow_name, **kw).strip() )
34745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    names[ node.tag.name ] = node
34845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            elif isinstance(node,GCCBuiltin) and node[0] not in names:
34945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #toks.append( '    '*indent + 'ctypedef long ' + node.pyxstr(indent=indent, **kw).strip() + ' # XX ??'    ) # XX ??
35045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append( '    '*indent + 'struct __unknown_builtin ' )
35145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                toks.append( '    '*indent + 'ctypedef __unknown_builtin ' + node.pyxstr(indent=indent, **kw).strip() )
35245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                names[ node[0] ] = node
35345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            for idx, child in enumerate(node):
35445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if type(child)==Array and not child.has_size():
35545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    # mutate this mystery array into a pointer XX method: Array.to_pointer()
35645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    node[idx] = Pointer()
35745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    node[idx].init_from( child ) # warning: shallow init
35845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    node[idx].pop() # pop the size element
35945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,cprefix="",use_cdef=True,shadow_name=True,**kw):
36145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        " note: i do not check if my name is already in 'names' "
36245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self = self.clone() # <----- NOTE
36345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        toks=[]
36445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        names = kw.get('names',{}) # what names have been defined ?
36545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        kw['names']=names
36645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self._pyxstr( toks, indent, cprefix, use_cdef, shadow_name, **kw )
36845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
36945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.name and not names.has_key( self.name ):
37045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            names[ self.name ] = self
37145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.identifier is not None:
37245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            comment = ""
37345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if self.name in python_kws:
37445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                comment = "#"
37545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if cprefix and use_cdef and shadow_name:
37645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                # When we are defining this guy, we refer to it using the pyrex shadow syntax.
37745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.name = '%s%s "%s" ' % ( cprefix, self.name, self.name )
37845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            cdef = 'cdef '
37945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if not use_cdef: cdef = '' # sometimes we don't want the cdef (eg. in a cast)
38045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            # this may need shadow_name=False:
38145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append( '    '*indent + comment + cdef + Node.pyxstr(self,indent=indent, cprefix=cprefix, **kw).strip() ) # + "(cprefix=%s)"%cprefix)
38245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #else: i am just a struct def (so i already did that) # huh ?? XX bad comment
38345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ' \n'.join(toks)
38445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
38545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxsym(self, ostream, names=None, tag_lookup=None, cprefix="", modname=None, cobjects=None):
38645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert self.name is not None, self.deepstr()
38745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream.putln( '# ' + self.cstr() )
38845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# This cdef is no good: it does not expose a python object
38945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# and we can't reliably set a global var
39045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #ostream.putln( 'cdef %s %s' % ( self.pyx_adaptor_decl(cobjects), self.name ) ) # _CObject
39145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #ostream.putln( '%s = %s()' % (self.name, self.pyx_adaptor_name(cobjects)) )
39245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #ostream.putln( '%s.p = <void*>&%s' % (self.name, cprefix+self.name) )
39345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ## expose a python object:
39445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #ostream.putln( '%s.%s = %s' % (modname,self.name, self.name) )
39545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream.putln( '%s = %s( addr = <long>&%s )' % (self.name, self.pyx_adaptor_name(cobjects), cprefix+self.name) )
39645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ostream
39745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
39945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Typedef(Declarator):
40045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,cprefix="",use_cdef=True,shadow_name=True,**kw): # shadow_name=True
40145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        " warning: i do not check if my name is already in 'names' "
40245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        assert shadow_name == True
40345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self = self.clone() # <----- NOTE
40445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        toks=[]
40545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        names = kw.get('names',{}) # what names have been defined ?
40645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        kw['names']=names
40745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
40845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #if self.tagged and not self.tagged.tag.name:
40945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ## "typedef struct {...} foo;" => "typedef struct foo {...} foo;"
41045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ## (to be emitted in the node loop below, and suppressed in the final toks.append)
41145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #self.tagged.tag = Tag( self.name ) # this is how pyrex does it: tag.name == self.name
41245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        # XX that doesn't work (the resulting c fails to compile) XX
41345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
41445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        self._pyxstr( toks, indent, cprefix, use_cdef, shadow_name, **kw )
41545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
41645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #print self.deepstr()
41745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.name and not names.has_key( self.name ):
41845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            names[ self.name ] = self
41945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if not (self.tagged and self.name == self.tagged.tag.name):
42045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            comment = ""
42145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if self.name in python_kws:
42245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                comment = "#"
42345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #if cprefix:
42445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                #  self.name = '%s%s "%s" ' % ( cprefix, self.name, self.name ) # XX pyrex can't do this
42545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if cprefix: # shadow_name=True
42645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                # My c-name gets this prefix. See also TypeAlias.pyxstr(): it also prepends the cprefix.
42745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                self.name = '%s%s "%s" ' % ( cprefix, self.name, self.name )
42845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            toks.append( '    '*indent + comment + 'ctypedef ' + Node.pyxstr(self,indent=indent, cprefix=cprefix, **kw).strip() )
42945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ' \n'.join(toks)
43045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
43145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
43245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass AbstractDeclarator(Declarator):
43345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """ used in Function; may lack an identifier """
43445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,**kw):
43545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.name in python_kws:
43645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            # Would be better to do this in __init__, but our subclass doesn't call our __init__.
43745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            self.name = '_' + self.name
43845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #return '    '*indent + Node.pyxstr(self,toks,indent, **kw).strip()
43945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return Node.pyxstr(self,toks,indent, **kw).strip()
44045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass FieldLength(object):
44345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
44445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
44545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks,indent,**kw):
44645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        pass
44745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
44945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass StructDeclarator(Declarator): # also used in Union
45045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
45145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
45245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyxstr(self,toks=None,indent=0,**kw):
45345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        comment = ""
45445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        if self.name in python_kws:
45545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            comment = "#"
45645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return '    '*indent + comment + Node.pyxstr(self,toks,indent, **kw).strip()
45745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
45845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass DeclarationSpecifiers(object):
45945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
46045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
46145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
46245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass TypeSpecifiers(DeclarationSpecifiers):
46445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
46545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
46645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
46745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
46845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Initializer(object):
46945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
47045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
47145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
47245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass Declaration(object):
47445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
47545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
47645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
47745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
47845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass ParameterDeclaration(Declaration):
47945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
48045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
48145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
48245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass StructDeclaration(Declaration):
48445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
48545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
48645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    pass
48745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
48845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass TransUnit(object):
48945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
49045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        Top level node.
49145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    """
49245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    def pyx_decls(self, filenames, modname, macros = {}, names = {}, func_cb=None, cprefix="", **kw):
49345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        # PART 1: emit extern declarations
49445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream = OStream()
49545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        now = datetime.today()
49645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream.putln( now.strftime('# Code generated by pyxelator on %x at %X') + '\n' )
49745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream.putln("# PART 1: extern declarations")
49845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for filename in filenames:
49945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ostream.putln( 'cdef extern from "%s":\n    pass\n' % filename )
50045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream.putln( 'cdef extern from *:' )
50145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        file = None # current file
50245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        for node in self:
50345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ostream.putln('')
50445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            ostream.putln('    # ' + node.cstr() )
50545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            assert node.marked
50645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            comment = False
50745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if node.name and node.name in names:
50845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                comment = True # redeclaration
50945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            #ostream.putln( node.deepstr( comment=True ) )
51045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            s = node.pyxstr(indent=1, names=names, tag_lookup = self.tag_lookup, cprefix=cprefix, **kw)
51145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org            if s.split():
51245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if comment:
51345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    s = "#"+s.replace( '\n', '\n#' ) + " # redeclaration "
51445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                if node.file != file:
51545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    file = node.file
51645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    #ostream.putln( 'cdef extern from "%s":' % file )
51745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                    ostream.putln( '    # "%s"' % file )
51845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org                ostream.putln( s )
51945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        ostream.putln('\n')
52045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        #s = '\n'.join(toks)
52145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org        return ostream.join()
52245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
52345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org# XX warn when we find a python keyword XX
52445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpython_kws = """
52545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgbreak continue del def except exec finally pass print raise
52645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgreturn try global assert lambda yield
52745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgfor while if elif else and in is not or import from """.split()
52845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgpython_kws = dict( zip( python_kws, (None,)*len(python_kws) ) )
52945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
53045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
531