11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# a glorified C pre-processor parser
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectimport sys, re, string
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfrom utils import *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfrom defaults import *
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectdebugTokens             = False
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectdebugDirectiveTokenizer = False
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectdebugLineParsing        = False
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectdebugCppExpr            = False
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectdebugOptimIf01          = False
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####           C P P   T O K E N S                                             #####
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# the list of supported C-preprocessor tokens
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# plus a couple of C tokens as well
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokEOF       = "\0"
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLN        = "\n"
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokSTRINGIFY = "#"
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokCONCAT    = "##"
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLOGICAND  = "&&"
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLOGICOR   = "||"
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokSHL       = "<<"
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokSHR       = ">>"
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokEQUAL     = "=="
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokNEQUAL    = "!="
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLT        = "<"
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLTE       = "<="
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokGT        = ">"
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokGTE       = ">="
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokELLIPSIS  = "..."
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokSPACE     = " "
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokDEFINED   = "defined"
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLPAREN    = "("
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokRPAREN    = ")"
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokNOT       = "!"
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokPLUS      = "+"
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokMINUS     = "-"
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokMULTIPLY  = "*"
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokDIVIDE    = "/"
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokMODULUS   = "%"
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokBINAND    = "&"
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokBINOR     = "|"
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokBINXOR    = "^"
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokCOMMA     = ","
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokLBRACE    = "{"
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokRBRACE    = "}"
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokARROW     = "->"
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokINCREMENT = "++"
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokDECREMENT = "--"
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokNUMBER    = "<number>"
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokIDENT     = "<ident>"
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokSTRING    = "<string>"
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass Token:
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a simple class to hold information about a given token.
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       each token has a position in the source code, as well as
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       an 'id' and a 'value'. the id is a string that identifies
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       the token's class, while the value is the string of the
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       original token itself.
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       for example, the tokenizer concatenates a series of spaces
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       and tabs as a single tokSPACE id, whose value if the original
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       spaces+tabs sequence."""
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self):
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.id     = None
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.value  = None
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.lineno = 0
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.colno  = 0
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def set(self,id,val=None):
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.id = id
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if val:
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.value = val
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.value = id
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def copyFrom(self,src):
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.id     = src.id
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.value  = src.value
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.lineno = src.lineno
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.colno  = src.colno
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokIDENT:
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "(ident %s)" % self.value
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokNUMBER:
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "(number %s)" % self.value
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokSTRING:
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "(string '%s')" % self.value
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokLN:
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "<LN>"
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokEOF:
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "<EOF>"
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokSPACE and self.value == "\\":
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # this corresponds to a trailing \ that was transformed into a tokSPACE
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "<\\>"
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.id
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokIDENT:
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.value
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokNUMBER:
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.value
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokSTRING:
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.value
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokEOF:
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "<EOF>"
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.id == tokSPACE:
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if self.value == "\\":  # trailing \
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return "\\\n"
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return self.value
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.id
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass BadExpectedToken(Exception):
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,msg):
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print msg
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####          C P P   T O K E N   C U R S O R                                  #####
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass TokenCursor:
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a small class to iterate over a list of Token objects"""
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,tokens):
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tokens = tokens
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.n      = 0
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.count  = len(tokens)
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def set(self,n):
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """set the current position"""
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if n < 0:
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            n = 0
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if n > self.count:
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            n = self.count
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.n = n
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def peekId(self):
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """retrieve the id of the current token"""
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (self.n >= self.count):
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.tokens[self.n].id
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def peek(self):
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """retrieve the current token. does not change position"""
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (self.n >= self.count):
1621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.tokens[self.n]
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skip(self):
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """increase current token position"""
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (self.n < self.count):
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.n += 1
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skipSpaces(self):
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """skip over all space tokens, this includes tokSPACE and tokLN"""
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while 1:
1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok = self.peekId()
1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if tok != tokSPACE and tok != tokLN:
1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break
1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.skip()
1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skipIfId(self,id):
1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """skip an optional token"""
1801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.peekId() == id:
1811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.skip()
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expectId(self,id):
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """raise an exception if the current token hasn't a given id.
1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           otherwise skip over it"""
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        tok = self.peek()
1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if tok.id != id:
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            raise BadExpectedToken, "%d:%d: '%s' expected, received '%s'" % (tok.lineno, tok.colno, id, tok.id)
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.skip()
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def remain(self):
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return the list of remaining tokens"""
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.tokens[self.n:]
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####           C P P   T O K E N I Z E R                                       #####
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# list of long symbols, i.e. those that take more than one characters
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjectcppLongSymbols = [ tokCONCAT, tokLOGICAND, tokLOGICOR, tokSHL, tokSHR, tokELLIPSIS, tokEQUAL,\
2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                   tokNEQUAL, tokLTE, tokGTE, tokARROW, tokINCREMENT, tokDECREMENT ]
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppTokenizer:
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """an abstract class used to convert some input text into a list
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       of tokens. real implementations follow and differ in the format
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       of the input text only"""
2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self):
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """initialize a new CppTokenizer object"""
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.eof  = False  # end of file reached ?
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.text = None   # content of current line, with final \n stripped
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.line = 0      # number of current line
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.pos  = 0      # current character position in current line
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.len  = 0      # length of current line text
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.held = Token()
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def setLineText(self,line):
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """set the content of the (next) current line. should be called
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           by fillLineText() in derived classes"""
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.text = line
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.len  = len(line)
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.pos  = 0
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def fillLineText(self):
2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """refresh the content of 'line' with a new line of input"""
2311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # to be overriden
2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.eof = True
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def markPos(self,tok):
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """mark the position of the current token in the source file"""
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.eof or self.pos > self.len:
2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok.lineno = self.line + 1
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok.colno  = 0
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok.lineno = self.line
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok.colno  = self.pos
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def peekChar(self):
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return the current token under the cursor without moving it"""
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.eof:
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return tokEOF
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.pos > self.len:
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.pos   = 0
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.line += 1
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.fillLineText()
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if self.eof:
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tokEOF
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.pos == self.len:
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return tokLN
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.text[self.pos]
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def peekNChar(self,n):
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """try to peek the next n chars on the same line"""
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.pos + n > self.len:
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.text[self.pos:self.pos+n]
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skipChar(self):
2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """increment the token cursor position"""
2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not self.eof:
2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.pos += 1
2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skipNChars(self,n):
2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.pos + n <= self.len:
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.pos += n
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while n > 0:
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                n -= 1
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def nextChar(self):
2801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """retrieve the token at the current cursor position, then skip it"""
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = self.peekChar()
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.skipChar()
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return  result
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def getEscape(self):
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # try to get all characters after a backslash (\)
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = self.nextChar()
2881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if result == "0":
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # octal number ?
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            num = self.peekNChar(3)
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if num != None:
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                isOctal = True
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for d in num:
2941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if not d in "01234567":
2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        isOctal = False
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        break
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if isOctal:
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result += num
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    self.skipNChars(3)
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif result == "x" or result == "X":
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # hex number ?
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            num = self.peekNChar(2)
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if num != None:
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                isHex = True
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for d in num:
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if not d in "012345678abcdefABCDEF":
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        isHex = False
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        break
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if isHex:
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result += num
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    self.skipNChars(2)
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif result == "u" or result == "U":
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # unicode char ?
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            num = self.peekNChar(4)
3151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if num != None:
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                isHex = True
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for d in num:
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if not d in "012345678abcdefABCDEF":
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        isHex = False
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        break
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if isHex:
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result += num
3231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    self.skipNChars(4)
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def nextRealToken(self,tok):
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return next CPP token, used internally by nextToken()"""
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.nextChar()
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c == tokEOF or c == tokLN:
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return tok.set(c)
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c == '/':
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c = self.peekChar()
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c == '/':   # C++ comment line
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while 1:
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    c = self.nextChar()
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if c == tokEOF or c == tokLN:
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        break
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tok.set(tokLN)
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c == '*':   # C comment start
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
3441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                value = "/*"
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                prev_c = None
3461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while 1:
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    c = self.nextChar()
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if c == tokEOF:
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        #print "## EOF after '%s'" % value
3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        return tok.set(tokEOF,value)
3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if c == '/' and prev_c == '*':
3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        break
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    prev_c = c
3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    value += c
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                value += "/"
3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                #print "## COMMENT: '%s'" % value
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tok.set(tokSPACE,value)
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c = '/'
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c.isspace():
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while 1:
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c2 = self.peekChar()
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if c2 == tokLN or not c2.isspace():
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c += c2
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return tok.set(tokSPACE,c)
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c == '\\':
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if debugTokens:
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                print "nextRealToken: \\ found, next token is '%s'" % repr(self.peekChar())
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if self.peekChar() == tokLN:   # trailing \
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # eat the tokLN
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # we replace a trailing \ by a tokSPACE whose value is
3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # simply "\\". this allows us to detect them later when
3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # needed.
3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tok.set(tokSPACE,"\\")
3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # treat as a single token here ?
3821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c +=self.getEscape()
3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tok.set(c)
3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c == "'":  # chars
3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c2 = self.nextChar()
3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c += c2
3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c2 == '\\':
3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c += self.getEscape()
3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while 1:
3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c2 = self.nextChar()
3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if c2 == tokEOF:
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c += c2
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if c2 == "'":
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return tok.set(tokSTRING, c)
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c == '"':  # strings
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            quote = 0
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while 1:
4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c2  = self.nextChar()
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if c2 == tokEOF:
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return tok.set(tokSTRING,c)
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c += c2
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if not quote:
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if c2 == '"':
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        return tok.set(tokSTRING,c)
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if c2 == "\\":
4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        quote = 1
4141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    quote = 0
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c >= "0" and c <= "9":  # integers ?
4181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while 1:
4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c2 = self.peekChar()
4201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if c2 == tokLN or (not c2.isalnum() and c2 != "_"):
4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c += c2
4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
4241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return tok.set(tokNUMBER,c)
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c.isalnum() or c == "_":  # identifiers ?
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while 1:
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c2 = self.peekChar()
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if c2 == tokLN or (not c2.isalnum() and c2 != "_"):
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                c += c2
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.skipChar()
4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c == tokDEFINED:
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tok.set(tokDEFINED)
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return tok.set(tokIDENT,c)
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # check special symbols
4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for sk in cppLongSymbols:
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c == sk[0]:
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                sklen = len(sk[1:])
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if self.pos + sklen <= self.len and \
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                   self.text[self.pos:self.pos+sklen] == sk[1:]:
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    self.pos += sklen
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return tok.set(sk)
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return tok.set(c)
4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def nextToken(self,tok):
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return the next token from the input text. this function
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           really updates 'tok', and does not return a new one"""
4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.markPos(tok)
4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.nextRealToken(tok)
4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def getToken(self):
4561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        tok = Token()
4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.nextToken(tok)
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if debugTokens:
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "getTokens: %s" % repr(tok)
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return tok
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def toTokenList(self):
4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """convert the input text of a CppTokenizer into a direct
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           list of token objects. tokEOF is stripped from the result"""
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = []
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while 1:
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok = Token()
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.nextToken(tok)
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if tok.id == tokEOF:
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result.append(tok)
4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppLineTokenizer(CppTokenizer):
4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a CppTokenizer derived class that accepts a single line of text as input"""
4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,line,lineno=1):
4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        CppTokenizer.__init__(self)
4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.line = lineno
4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.setLineText(line)
4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppLinesTokenizer(CppTokenizer):
4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a CppTokenizer derived class that accepts a list of texdt lines as input.
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       the lines must not have a trailing \n"""
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,lines=[],lineno=1):
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """initialize a CppLinesTokenizer. you can later add lines using addLines()"""
4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        CppTokenizer.__init__(self)
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.line  = lineno
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.lines = lines
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.index = 0
4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.count = len(lines)
4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.count > 0:
4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.fillLineText()
4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.eof = True
4971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def addLine(self,line):
4991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """add a line to a CppLinesTokenizer. this can be done after tokenization
5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           happens"""
5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.count == 0:
5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.setLineText(line)
5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.index = 1
5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.lines.append(line)
5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.count += 1
5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.eof    = False
5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def fillLineText(self):
5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.index < self.count:
5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.setLineText(self.lines[self.index])
5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.index += 1
5121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.eof = True
5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppFileTokenizer(CppTokenizer):
5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,file,lineno=1):
5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        CppTokenizer.__init__(self)
5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.file = file
5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.line = lineno
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def fillLineText(self):
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        line = self.file.readline()
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if len(line) > 0:
5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if line[-1] == '\n':
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                line = line[:-1]
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if len(line) > 0 and line[-1] == "\r":
5281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                line = line[:-1]
5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.setLineText(line)
5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.eof = True
5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# Unit testing
5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#
5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppTokenizerTester:
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class used to test CppTokenizer classes"""
5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,tokenizer=None):
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tokenizer = tokenizer
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.token     = Token()
5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def setTokenizer(self,tokenizer):
5421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tokenizer = tokenizer
5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expect(self,id):
5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tokenizer.nextToken(self.token)
5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        tokid = self.token.id
5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if tokid == id:
5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return
5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.token.value == id and (tokid == tokIDENT or tokid == tokNUMBER):
5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return
5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        raise BadExpectedToken, "###  BAD TOKEN: '%s' expecting '%s'" % (self.token.id,id)
5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expectToken(self,id,line,col):
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.expect(id)
5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.token.lineno != line:
5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            raise BadExpectedToken, "###  BAD LINENO: token '%s' got '%d' expecting '%d'" % (id,self.token.lineno,line)
5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.token.colno != col:
5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            raise BadExpectedToken, "###  BAD COLNO: '%d' expecting '%d'" % (self.token.colno,col)
5591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expectTokenVal(self,id,value,line,col):
5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.expectToken(id,line,col)
5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.token.value != value:
5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            raise BadExpectedToken, "###  BAD VALUE: '%s' expecting '%s'" % (self.token.value,value)
5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expectList(self,list):
5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for item in list:
5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.expect(item)
5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_CppTokenizer():
5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "running CppTokenizer tests"
5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester = CppTokenizerTester()
5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLineTokenizer("#an/example  && (01923_xy)") )
5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectList( ["#", "an", "/", "example", tokSPACE, tokLOGICAND, tokSPACE, tokLPAREN, "01923_xy", \
5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                       tokRPAREN, tokLN, tokEOF] )
5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLineTokenizer("FOO(BAR) && defined(BAZ)") )
5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectList( ["FOO", tokLPAREN, "BAR", tokRPAREN, tokSPACE, tokLOGICAND, tokSPACE,
5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        tokDEFINED, tokLPAREN, "BAZ", tokRPAREN, tokLN, tokEOF] )
5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLinesTokenizer( ["/*", "#", "*/"] ) )
5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectList( [ tokSPACE, tokLN, tokEOF ] )
5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLinesTokenizer( ["first", "second"] ) )
5851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectList( [ "first", tokLN, "second", tokLN, tokEOF ] )
5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLinesTokenizer( ["first second", "  third"] ) )
5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( "first", 1, 0 )
5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( tokSPACE, 1, 5 )
5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( "second", 1, 6 )
5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( tokLN, 1, 12 )
5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( tokSPACE, 2, 0 )
5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( "third", 2, 2 )
5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLinesTokenizer( [ "boo /* what the", "hell */" ] ) )
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectList( [ "boo", tokSPACE ] )
5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectTokenVal( tokSPACE, "/* what the\nhell */", 1, 4 )
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectList( [ tokLN, tokEOF ] )
5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.setTokenizer( CppLinesTokenizer( [ "an \\", " example" ] ) )
6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( "an", 1, 0 )
6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( tokSPACE, 1, 2 )
6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectTokenVal( tokSPACE, "\\", 1, 3 )
6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( tokSPACE, 2, 0 )
6051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( "example", 2, 1 )
6061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    tester.expectToken( tokLN, 2, 8 )
6071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return True
6091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####           C P P   E X P R E S S I O N S                                   #####
6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# Cpp expressions are modeled by tuples of the form (op,arg) or (op,arg1,arg2), etc..
6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# op is an "operator" string
6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass Expr:
6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class used to model a CPP expression"""
6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opInteger   = "int"
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opIdent     = "ident"
6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opCall      = "call"
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opDefined   = "defined"
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opTest      = "?"
6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opLogicNot  = "!"
6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opNot       = "~"
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opNeg       = "[-]"
6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opUnaryPlus = "[+]"
6331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opAdd = "+"
6341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opSub = "-"
6351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opMul = "*"
6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opDiv = "/"
6371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opMod = "%"
6381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opAnd = "&"
6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opOr  = "|"
6401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opXor = "^"
6411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opLogicAnd = "&&"
6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opLogicOr  = "||"
6431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opEqual = "=="
6441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opNotEqual = "!="
6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opLess = "<"
6461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opLessEq = "<="
6471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opGreater = ">"
6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opGreaterEq = ">="
6491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opShl = "<<"
6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    opShr = ">>"
6511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    unaries  = [ opLogicNot, opNot, opNeg, opUnaryPlus ]
6531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    binaries = [ opAdd, opSub, opMul, opDiv, opMod, opAnd, opOr, opXor, opLogicAnd, opLogicOr,
6541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                 opEqual, opNotEqual, opLess, opLessEq, opGreater, opGreaterEq ]
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    precedences = {
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opTest: 0,
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opLogicOr:  1,
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opLogicNot: 2,
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opOr : 3,
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opXor: 4,
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opAnd: 5,
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opEqual: 6, opNotEqual: 6,
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opLess:7, opLessEq:7, opGreater:7, opGreaterEq:7,
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opShl:8, opShr:8,
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opAdd:9, opSub:9,
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opMul:10, opDiv:10, opMod:10,
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opLogicNot:11,
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    opNot: 12,
6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    }
6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,op):
6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.op = op
6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(%s)" % self.op
6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "operator(%s)" % self.op
6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def precedence(self):
6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return the precedence of a given operator"""
6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return Expr.precedences.get(self.op, 1000)
6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isUnary(self):
6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.op in Expr.unaries
6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isBinary(self):
6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.op in Expr.binaries
6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isDefined(self):
6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.op is opDefined
6931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def toInt(self):
6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return the integer value of a given expression. only valid for integer expressions
6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           will return None otherwise"""
6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
6991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass IntExpr(Expr):
7001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,value):
7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        Expr.__init__(self,opInteger)
7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.arg   = value
7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(int %s)" % self.arg
7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
7081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.arg
7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def toInt(self):
7111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        s = self.arg  # string value
7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # get rid of U or L suffixes
7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while len(s) > 0 and s[-1] in "LUlu":
7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            s = s[:-1]
7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return string.atoi(s)
7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass IdentExpr(Expr):
7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,name):
7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        Expr.__init__(self,opIdent)
7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.name = name
7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(ident %s)" % self.name
7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.name
7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CallExpr(Expr):
7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,funcname,params):
7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        Expr.__init__(self,opCall)
7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.funcname = funcname
7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.params   = params
7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
7351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = "(call %s [" % self.funcname
7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        comma  = ""
7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for param in self.params:
7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += "%s%s" % (comma, repr(param))
7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            comma   = ","
7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result += "])"
7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
7421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = "%s(" % self.funcname
7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        comma = ""
7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for param in self.params:
7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += "%s%s" % (comma, str(param))
7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            comma = ","
7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result += ")"
7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass TestExpr(Expr):
7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,cond,iftrue,iffalse):
7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        Expr.__init__(self,opTest)
7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.cond    = cond
7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.iftrue  = iftrue
7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.iffalse = iffalse
7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(?: %s %s %s)" % (repr(self.cond),repr(self.iftrue),repr(self.iffalse))
7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(%s) ? (%s) : (%s)" % (self.cond, self.iftrue, self.iffalse)
7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass SingleArgExpr(Expr):
7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,op,arg):
7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        Expr.__init__(self,op)
7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.arg = arg
7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(%s %s)" % (self.op, repr(self.arg))
7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass DefinedExpr(SingleArgExpr):
7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,op,macroname):
7761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        SingleArgExpr.__init__(self.opDefined,macroname)
7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "defined(%s)" % self.arg
7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass UnaryExpr(SingleArgExpr):
7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,op,arg,opstr=None):
7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        SingleArgExpr.__init__(self,op,arg)
7851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not opstr:
7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            opstr = op
7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.opstr = opstr
7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
7901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg_s     = str(self.arg)
7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg_prec  = self.arg.precedence()
7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self_prec = self.precedence()
7931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if arg_prec < self_prec:
7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "%s(%s)" % (self.opstr,arg_s)
7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "%s%s" % (self.opstr, arg_s)
7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass TwoArgExpr(Expr):
7991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,op,arg1,arg2):
8001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        Expr.__init__(self,op)
8011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.arg1 = arg1
8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.arg2 = arg2
8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "(%s %s %s)" % (self.op, repr(self.arg1), repr(self.arg2))
8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass BinaryExpr(TwoArgExpr):
8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,op,arg1,arg2,opstr=None):
8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        TwoArgExpr.__init__(self,op,arg1,arg2)
8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not opstr:
8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            opstr = op
8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.opstr = opstr
8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg1_s    = str(self.arg1)
8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg2_s    = str(self.arg2)
8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg1_prec = self.arg1.precedence()
8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg2_prec = self.arg2.precedence()
8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self_prec = self.precedence()
8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = ""
8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if arg1_prec < self_prec:
8231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += "(%s)" % arg1_s
8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += arg1_s
8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result += " %s " % self.opstr
8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if arg2_prec < self_prec:
8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += "(%s)" % arg2_s
8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += arg2_s
8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####           C P P   E X P R E S S I O N   P A R S E R                       #####
8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
8421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
8431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass ExprParser:
8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class used to convert a list of tokens into a cpp Expr object"""
8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    re_octal   = re.compile(r"\s*\(0[0-7]+\).*")
8491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    re_decimal = re.compile(r"\s*\(\d+[ulUL]*\).*")
8501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    re_hexadecimal = re.compile(r"\s*\(0[xX][0-9a-fA-F]*\).*")
8511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,tokens):
8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tok = tokens
8541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.n   = len(self.tok)
8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.i   = 0
8561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def mark(self):
8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.i
8591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def release(self,pos):
8611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.i = pos
8621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def peekId(self):
8641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.i < self.n:
8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.tok[self.i].id
8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def peek(self):
8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.i < self.n:
8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.tok[self.i]
8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skip(self):
8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.i < self.n:
8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.i += 1
8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skipOptional(self,id):
8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.i < self.n and self.tok[self.i].id == id:
8791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.i += 1
8801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skipSpaces(self):
8821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i   = self.i
8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        n   = self.n
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        tok = self.tok
8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while i < n and (tok[i] == tokSPACE or tok[i] == tokLN):
8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i += 1
8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.i = i
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    # all the isXXX functions returns a (expr,nextpos) pair if a match is found
8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    # or None if not
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_integer(self):
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        id = self.tok[self.i].id
8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c  = id[0]
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c < '0' or c > '9':
8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        m = ExprParser.re_octal.match(id)
8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if m:
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (IntExpr(id), m.end(1))
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        m = ExprParser.re_decimal.match(id)
9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if m:
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (IntExpr(id), m.end(1))
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        m = ExprParser.re_hexadecimal(id)
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if m:
9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (IntExpr(id), m.end(1))
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_defined(self):
9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        id = self.tok[self.i].id
9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if id != "defined":
9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        pos = self.mark()
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        use_paren = 0
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.peekId() == tokLPAREN:
9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.skip()
9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            use_paren = 1
9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.peekId() != tokIDENT:
9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw( BadExpectedToken, "identifier expected")
9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        macroname = self.peek().value
9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.skip()
9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if use_paren:
9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.skipSpaces()
9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if self.peekId() != tokRPAREN:
9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.throw( BadExpectedToken, "missing right-paren after 'defined' directive")
9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.skip()
9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.i
9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return (DefinedExpr(macroname),i+1)
9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_call_or_ident(self):
9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        pass
9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def parse(self, i):
9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####           C P P   E X P R E S S I O N S                                   #####
9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppInvalidExpression(Exception):
9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """an exception raised when an invalid/unsupported cpp expression is detected"""
9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    pass
9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass CppExpr:
9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class that models the condition of #if directives into
9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        an expression tree. each node in the tree is of the form (op,arg) or (op,arg1,arg2)
9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        where "op" is a string describing the operation"""
9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    unaries  = [ "!", "~" ]
9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    binaries = [ "+", "-", "<", "<=", ">=", ">", "&&", "||", "*", "/", "%", "&", "|", "^", "<<", ">>", "==", "!=" ]
9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    precedences = { "||": 1,
9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    "&&": 2,
9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "|": 3,
9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "^": 4,
9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "&": 5,
9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "==":6, "!=":6,
9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "<":7, "<=":7, ">":7, ">=":7,
9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "<<":8, ">>":8,
9711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "+":9, "-":9,
9721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "*":10, "/":10, "%":10,
9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     "!":11, "~":12
9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                     }
9751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self, tokens):
9771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """initialize a CppExpr. 'tokens' must be a CppToken list"""
9781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tok  = tokens
9791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.n    = len(tokens)
9801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if debugCppExpr:
9811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "CppExpr: trying to parse %s" % repr(tokens)
9821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        expr      = self.is_expr(0)
9831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if debugCppExpr:
9841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "CppExpr: got " + repr(expr)
9851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.expr = expr[0]
9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    re_cpp_constant = re.compile(r"((\d|\w|_)+)")
9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def throw(self,exception,i,msg):
9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i < self.n:
9911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok = self.tok[i]
9921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "%d:%d: %s" % (tok.lineno,tok.colno,msg)
9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "EOF: %s" % msg
9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        raise exception
9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def skip_spaces(self,i):
9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """skip spaces in input token list"""
9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while i < self.n:
10001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            t = self.tok[i]
10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if t.id != tokSPACE and t.id != tokLN:
10021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break
10031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i += 1
10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return i
10051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expectId(self,i,id):
10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """check that a given token id is at the current position, then skip over it"""
10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
10091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n or self.tok[i].id != id:
10101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw(BadExpectedToken,i,"### expecting '%s' in expression, got '%s'" % (id, self.tok[i].id))
10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return i+1
10121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def expectIdent(self,i):
10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
10151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n or self.tok[i].id != tokIDENT:
10161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw(BadExpectedToken,i,"### expecting identifier in expression, got '%s'" % (id, self.tok[i].id))
10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return i+1
10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    # the is_xxxxx function returns either None or a pair (e,nextpos)
10201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    # where 'e' is an expression tuple (e.g. (op,arg)) and 'nextpos' is
10211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    # the corresponding next position in the input token list
10221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    #
10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_decimal(self,i):
10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        v = self.tok[i].value[:]
10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while len(v) > 0 and v[-1] in "ULul":
10271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            v = v[:-1]
10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for digit in v:
10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if not digit.isdigit():
10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return None
10311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # for an integer expression tuple, the argument
10331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # is simply the value as an integer
10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        val = string.atoi(v)
10351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return ("int", val), i+1
10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_hexadecimal(self,i):
10381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        v = self.tok[i].value[:]
10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while len(v) > 0 and v[-1] in "ULul":
10401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            v = v[:-1]
10411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if len(v) > 2 and (v[0:2] == "0x" or v[0:2] == "0X"):
10421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for digit in v[2:]:
10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if not digit in "0123456789abcdefABCDEF":
10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return None
10451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # for an hex expression tuple, the argument
10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # is the value as an integer
10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            val = int(v[2:], 16)
10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return ("hex", val), i+1
10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_integer(self,i):
10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.tok[i].id != tokNUMBER:
10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.is_decimal(i)
10581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c: return c
10591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.is_hexadecimal(i)
10611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c: return c
10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_number(self,i):
10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id == tokMINUS and i+1 < self.n:
10681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c = self.is_integer(i+1)
10691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c:
10701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                e, i2 = c
10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                op, val  = e
10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return (op, -val), i2
10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id == tokPLUS and i+1 < self.n:
10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c = self.is_integer(i+1)
10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if c: return c
10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.is_integer(i)
10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_alnum(self,i):
10811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """test wether a given token is alpha-numeric"""
10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n:
10841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        m = CppExpr.re_cpp_constant.match(t.id)
10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if m:
10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            #print "... alnum '%s'" % m.group(1)
10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            r = m.group(1)
10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return ("ident", r), i+1
10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_defined(self,i):
10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id != tokDEFINED:
10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # we have the defined keyword, check the rest
10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i+1)
11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        use_parens = 0
11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i < self.n and self.tok[i].id == tokLPAREN:
11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            use_parens = 1
11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i = self.skip_spaces(i+1)
11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n:
11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw(CppConstantExpected,i,"### 'defined' must be followed  by macro name or left paren")
11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id != tokIDENT:
11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw(CppConstantExpected,i,"### 'defined' must be followed by macro name")
11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i += 1
11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if use_parens:
11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i = self.expectId(i,tokRPAREN)
11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return ("defined",t.value), i
11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_call_or_ident(self,i):
11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n:
11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id != tokIDENT:
11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        name = t.value
11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i+1)
11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n or self.tok[i].id != tokLPAREN:
11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return ("ident", name), i
11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        params    = []
11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        depth     = 1
11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i += 1
11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        j  = i
11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while i < self.n:
11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            id = self.tok[i].id
11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if id == tokLPAREN:
11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                depth += 1
11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif depth == 1 and (id == tokCOMMA or id == tokRPAREN):
11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while j < i and self.tok[j].id == tokSPACE:
11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    j += 1
11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                k = i
11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while k > j and self.tok[k-1].id == tokSPACE:
11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    k -= 1
11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                param = self.tok[j:k]
11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                params.append( param )
11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if id == tokRPAREN:
11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                j = i+1
11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif id == tokRPAREN:
11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                depth -= 1
11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i += 1
11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n:
11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return ("call", (name, params)), i+1
11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_token(self,i,token):
11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n or self.tok[i].id != token:
11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return token, i+1
11671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_value(self,i):
11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id == tokSTRING:
11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return ("string", t.value), i+1
11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.is_number(i)
11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c: return c
11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.is_defined(i)
11781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c: return c
11791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.is_call_or_ident(i)
11811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if c: return c
11821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n or self.tok[i].id != tokLPAREN:
11851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
11861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        popcount = 1
11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i2       = i+1
11891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while i2 < self.n:
11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            t = self.tok[i2]
11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if t.id == tokLPAREN:
11921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                popcount += 1
11931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif t.id == tokRPAREN:
11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                popcount -= 1
11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if popcount == 0:
11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    break
11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i2 += 1
11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if popcount != 0:
12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw(CppInvalidExpression, i, "expression missing closing parenthesis")
12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if debugCppExpr:
12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            print "CppExpr: trying to parse sub-expression %s" % repr(self.tok[i+1:i2])
12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        oldcount   = self.n
12051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.n     = i2
12061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c          = self.is_expr(i+1)
12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.n     = oldcount
12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not c:
12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.throw(CppInvalidExpression, i, "invalid expression within parenthesis")
12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        e, i = c
12121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return e, i2+1
12131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_unary(self,i):
12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n:
12171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i]
12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id in CppExpr.unaries:
12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c = self.is_unary(i+1)
12221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if not c:
12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.throw(CppInvalidExpression, i, "%s operator must be followed by value" % t.id)
12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            e, i = c
12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (t.id, e), i
12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.is_value(i)
12281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_binary(self,i):
12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i = self.skip_spaces(i)
12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i >= self.n:
12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        c = self.is_unary(i)
12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if not c:
12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
12371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        e1, i2 = c
12391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i2 = self.skip_spaces(i2)
12401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if i2 >= self.n:
12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return c
12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        t = self.tok[i2]
12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if t.id in CppExpr.binaries:
12451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            c = self.is_binary(i2+1)
12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if not c:
12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                self.throw(CppInvalidExpression, i,"### %s operator must be followed by value" % t.id )
12481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            e2, i3 = c
12491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (t.id, e1, e2), i3
12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return None
12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_expr(self,i):
12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.is_binary(i)
12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def dump_node(self,e):
12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        op = e[0]
12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        line = "(" + op
12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "int":
12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " %d)" % e[1]
12611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "hex":
12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " 0x%x)" % e[1]
12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "ident":
12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " %s)" % e[1]
12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "defined":
12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " %s)" % e[1]
12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "call":
12681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg = e[1]
12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " %s [" % arg[0]
12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            prefix = ""
12711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for param in arg[1]:
12721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                par = ""
12731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for tok in param:
12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    par += str(tok)
12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                line += "%s%s" % (prefix, par)
12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                prefix = ","
12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += "])"
12781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op in CppExpr.unaries:
12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " %s)" % self.dump_node(e[1])
12801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op in CppExpr.binaries:
12811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " %s %s)" % (self.dump_node(e[1]), self.dump_node(e[2]))
12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
12831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            line += " ?%s)" % repr(e[1])
12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return line
12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.dump_node(self.expr)
12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def source_node(self,e):
12911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        op = e[0]
12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "int":
12931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "%d" % e[1]
12941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "hex":
12951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "0x%x" % e[1]
12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "ident":
12971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # XXX: should try to expand
12981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return e[1]
12991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "defined":
13001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "defined(%s)" % e[1]
13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        prec = CppExpr.precedences.get(op,1000)
13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        arg  = e[1]
13041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op in CppExpr.unaries:
13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg_src = self.source_node(arg)
13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg_op  = arg[0]
13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg_prec = CppExpr.precedences.get(arg[0],1000)
13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if arg_prec < prec:
13091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return "!(" + arg_src + ")"
13101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
13111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return "!" + arg_src
13121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op in CppExpr.binaries:
13131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg2     = e[2]
13141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg1_op  = arg[0]
13151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg2_op  = arg2[0]
13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg1_src = self.source_node(arg)
13171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            arg2_src = self.source_node(arg2)
13181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if CppExpr.precedences.get(arg1_op,1000) < prec:
13191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                arg1_src = "(%s)" % arg1_src
13201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if CppExpr.precedences.get(arg2_op,1000) < prec:
13211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                arg2_src = "(%s)" % arg2_src
13221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return "%s %s %s" % (arg1_src, op, arg2_src)
13241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return "???"
13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
13271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.source_node(self.expr)
13281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def int_node(self,e):
13301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if e[0] == "int":
13311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return e[1]
13321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif e[1] == "hex":
13331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return int(e[1],16)
13341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
13351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
13361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def toInt(self):
13381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.int_node(self.expr)
13391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def optimize_node(self,e,macros={}):
13411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        op = e[0]
13421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "defined":
13431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            name = e[1]
13441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if macros.has_key(name):
13451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if macros[name] == kCppUndefinedMacro:
13461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 0)
13471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
13481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 1)
13491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if kernel_remove_config_macros and name.startswith("CONFIG_"):
13511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return ("int", 0)
13521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "!":
13541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            op, v = e
13551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            v = self.optimize_node(v, macros)
13561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if v[0] == "int":
13571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if v[1] == 0:
13581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 1)
13591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
13601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 0)
13611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "&&":
13631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            op, l, r = e
13641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            l  = self.optimize_node(l, macros)
13651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            r  = self.optimize_node(r, macros)
13661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            li = self.int_node(l)
13671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            ri = self.int_node(r)
13681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if li != None:
13691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if li == 0:
13701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 0)
13711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
13721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return r
13731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "||":
13751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            op, l, r = e
13761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            l  = self.optimize_node(l, macros)
13771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            r  = self.optimize_node(r, macros)
13781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            li = self.int_node(l)
13791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            ri = self.int_node(r)
13801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if li != None:
13811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if li == 0:
13821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return r
13831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
13841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 1)
13851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif ri != None:
13861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if ri == 0:
13871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return l
13881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
13891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 1)
13901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return e
13911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def optimize(self,macros={}):
13931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.expr = self.optimize_node(self.expr,macros)
13941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def removePrefixedNode(self,e,prefix,names):
13961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        op = e[0]
13971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "defined":
13981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            name = e[1]
13991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if name.startswith(prefix):
14001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if names.has_key[name] and names[name] == "y":
14011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 1)
14021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
14031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return ("int", 0)
14041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op in CppExpr.unaries:
14061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            op, v = e
14071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            v = self.removePrefixedNode(v,prefix,names)
14081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (op, v)
14091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op in CppExpr.binaries:
14101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            op, v1, v2 = e
14111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            v1 = self.removePrefixedNode(v1,prefix,names)
14121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            v2 = self.removePrefixedNode(v2,prefix,names)
14131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (op, v1, v2)
14141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif op == "call":
14151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            func, params = e[1]
14161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            params2 = []
14171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for param in params:
14181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                params2.append( self.removePrefixedNode(param,prefix,names) )
14191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return (op, (func, params2))
14201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return e
14221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def removePrefixed(self,prefix,names={}):
14241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.expr = self.removePrefixedNode(self.expr,prefix,names)
14251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_equal_node(self,e1,e2):
14271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if e1[0] != e2[0] or len(e1) != len(e2):
14281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return False
14291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        op = e1[0]
14311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if op == "int" or op == "hex" or op == "!" or op == "defined":
14321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return e1[0] == e2[0]
14331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.is_equal_node(e1[1],e2[1]) and self.is_equal_node(e1[2],e2[2])
14351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def is_equal(self,other):
14371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.is_equal_node(self.expr,other.expr)
14381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_cpp_expr(expr, expected):
14401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    e = CppExpr( CppLineTokenizer( expr ).toTokenList() )
14411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    #print repr(e.expr)
14421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    s1 = repr(e)
14431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if s1 != expected:
14441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "KO: expression '%s' generates '%s', should be '%s'" % (expr, s1, expected)
14451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else:
14461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #print "OK: expression '%s'" % expr
14471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        pass
14481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_cpp_expr_optim(expr, expected, macros={}):
14501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    e = CppExpr( CppLineTokenizer( expr ).toTokenList() )
14511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    e.optimize(macros)
14521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    s1 = repr(e)
14541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if s1 != expected:
14551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "KO: optimized expression '%s' generates '%s', should be '%s'" % (expr, s1, expected)
14561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else:
14571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #print "OK: optmized expression '%s'" % expr
14581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        pass
14591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_cpp_expr_source(expr, expected):
14611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    e = CppExpr( CppLineTokenizer( expr ).toTokenList() )
14621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    s1 = str(e)
14631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if s1 != expected:
14641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "KO: source expression '%s' generates '%s', should be '%s'" % (expr, s1, expected)
14651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    else:
14661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #print "OK: source expression '%s'" % expr
14671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        pass
14681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_CppExpr():
14701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "testing CppExpr"
14711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "0", "(int 0)" )
14721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "1", "(int 1)" )
14731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "1 && 1", "(&& (int 1) (int 1))" )
14741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "1 && 0", "(&& (int 1) (int 0))" )
14751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "EXAMPLE", "(ident EXAMPLE)" )
14761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "EXAMPLE - 3", "(- (ident EXAMPLE) (int 3))" )
14771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "defined(EXAMPLE)", "(defined EXAMPLE)" )
14781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "!defined(EXAMPLE)", "(! (defined EXAMPLE))" )
14791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "defined(ABC) || defined(BINGO)", "(|| (defined ABC) (defined BINGO))" )
14801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr( "FOO(BAR)", "(call FOO [BAR])" )
14811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "0", "(int 0)" )
14831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "1", "(int 1)" )
14841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "1 && 1", "(int 1)" )
14851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "1 && 0", "(int 0)" )
14861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "0 && 1", "(int 0)" )
14871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "0 && 0", "(int 0)" )
14881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "1 || 1", "(int 1)" )
14891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "1 || 0", "(int 1)" )
14901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "0 || 1", "(int 1)" )
14911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "0 || 0", "(int 0)" )
14921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "EXAMPLE", "(ident EXAMPLE)" )
14931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "EXAMPLE - 3", "(- (ident EXAMPLE) (int 3))" )
14941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(EXAMPLE)", "(defined EXAMPLE)" )
14951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(EXAMPLE)", "(int 1)", { "EXAMPLE": "XOWOE" } )
14961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(EXAMPLE)", "(int 0)", { "EXAMPLE": kCppUndefinedMacro} )
14971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "!defined(EXAMPLE)", "(! (defined EXAMPLE))" )
14981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "!defined(EXAMPLE)", "(int 0)", { "EXAMPLE" : "XOWOE" } )
14991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "!defined(EXAMPLE)", "(int 1)", { "EXAMPLE" : kCppUndefinedMacro } )
15001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(ABC) || defined(BINGO)", "(|| (defined ABC) (defined BINGO))" )
15011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(ABC) || defined(BINGO)", "(int 1)", { "ABC" : "1" } )
15021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(ABC) || defined(BINGO)", "(int 1)", { "BINGO" : "1" } )
15031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(ABC) || defined(BINGO)", "(defined ABC)", { "BINGO" : kCppUndefinedMacro } )
15041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_optim( "defined(ABC) || defined(BINGO)", "(int 0)", { "ABC" : kCppUndefinedMacro, "BINGO" : kCppUndefinedMacro } )
15051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "0", "0" )
15071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "1", "1" )
15081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "1 && 1", "1 && 1" )
15091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "1 && 0", "1 && 0" )
15101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "0 && 1", "0 && 1" )
15111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "0 && 0", "0 && 0" )
15121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "1 || 1", "1 || 1" )
15131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "1 || 0", "1 || 0" )
15141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "0 || 1", "0 || 1" )
15151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "0 || 0", "0 || 0" )
15161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "EXAMPLE", "EXAMPLE" )
15171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "EXAMPLE - 3", "EXAMPLE - 3" )
15181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "defined(EXAMPLE)", "defined(EXAMPLE)" )
15191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_cpp_expr_source( "defined EXAMPLE", "defined(EXAMPLE)" )
15201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
15231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
15241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
15251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####          C P P   B L O C K                                                #####
15261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
15271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
15281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
15291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass Block:
15311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class used to model a block of input source text. there are two block types:
1532fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        - directive blocks: contain the tokens of a single pre-processor directive (e.g. #if)
15331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        - text blocks, contain the tokens of non-directive blocks
15341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       the cpp parser class below will transform an input source file into a list of Block
15361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       objects (grouped in a BlockList object for convenience)"""
15371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,tokens,directive=None,lineno=0):
15391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """initialize a new block, if 'directive' is None, this is a text block
15401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           NOTE: this automatically converts '#ifdef MACRO' into '#if defined(MACRO)'
15411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                 and '#ifndef MACRO' into '#if !defined(MACRO)'"""
15421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if directive == "ifdef":
15431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok = Token()
15441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok.set(tokDEFINED)
15451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tokens = [ tok ] + tokens
15461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            directive = "if"
15471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif directive == "ifndef":
15491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok1 = Token()
15501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok2 = Token()
15511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok1.set(tokNOT)
15521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok2.set(tokDEFINED)
15531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tokens = [ tok1, tok2 ] + tokens
15541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            directive = "if"
15551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tokens    = tokens
15571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.directive = directive
15581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if lineno > 0:
15591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.lineno = lineno
15601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
15611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.lineno = self.tokens[0].lineno
15621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.isIf():
15641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            self.expr = CppExpr( self.tokens )
15651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isDirective(self):
15671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """returns True iff this is a directive block"""
15681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.directive != None
15691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isConditional(self):
15711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """returns True iff this is a conditional directive block"""
15721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.directive in ["if","ifdef","ifndef","else","elif","endif"]
15731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isDefine(self):
15751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """returns the macro name in a #define directive, or None otherwise"""
15761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.directive != "define":
15771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
15781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.tokens[0].value
15801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isIf(self):
15821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """returns True iff this is an #if-like directive block"""
15831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.directive in ["if","ifdef","ifndef","elif"]
15841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def isInclude(self):
15861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """checks wether this is a #include directive. if true, then returns the
15871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           corresponding file name (with brackets or double-qoutes). None otherwise"""
15881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.directive != "include":
15891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
15901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        #print "iii " + repr(self.tokens)
15921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.tokens[0].id == tokSTRING:
15931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # a double-quote include, that's easy
15941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return self.tokens[0].value
15951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # we only want the bracket part, not any comments or junk after it
15971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.tokens[0].id == "<":
15981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i   = 0
15991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok = self.tokens
16001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            n   = len(tok)
16011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            while i < n and tok[i].id != ">":
16021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                i += 1
16031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
16041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if i >= n:
16051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return None
16061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
16071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return string.join([ str(x) for x in tok[:i+1] ],"")
16081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
16091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
16101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            return None
16111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1612fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    def removeWhiteSpace(self):
1613fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # Remove trailing whitespace and empty lines
1614fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # All whitespace is also contracted to a single space
1615fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if self.directive != None:
1616fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            return
1617fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1618fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        tokens = []
1619fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        line   = 0     # index of line start
1620fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        space  = -1    # index of first space, or -1
1621fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        ii = 0
1622fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        nn = len(self.tokens)
1623fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        while ii < nn:
1624fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            tok = self.tokens[ii]
1625fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1626fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # If we find a space, record its position if this is the first
1627fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # one the line start or the previous character. Don't append
1628fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # anything to tokens array yet though.
1629fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            if tok.id == tokSPACE:
1630fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                if space < 0:
1631fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    space = ii
1632fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                ii += 1
1633fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                continue
1634fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1635fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # If this is a line space, ignore the spaces we found previously
1636fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # on the line, and remove empty lines.
1637fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            if tok.id == tokLN:
1638fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                old_line  = line
1639fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                old_space = space
1640fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                #print "N line=%d space=%d ii=%d" % (line, space, ii)
1641fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                ii   += 1
1642fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                line  = ii
1643fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                space = -1
1644fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                if old_space == old_line:  # line only contains spaces
1645fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    #print "-s"
1646fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    continue
1647fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                if ii-1 == old_line:  # line is empty
1648fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    #print "-e"
1649fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    continue
1650fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                tokens.append(tok)
1651fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                continue
1652fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1653fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # Other token, append any space range if any, converting each
1654fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            # one to a single space character, then append the token.
1655fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            if space >= 0:
1656fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                jj = space
1657fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                space = -1
1658fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                while jj < ii:
1659fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    tok2 = self.tokens[jj]
1660fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    tok2.value = " "
1661fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    tokens.append(tok2)
1662fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    jj += 1
1663fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1664fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            tokens.append(tok)
1665fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            ii += 1
1666fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1667fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        self.tokens = tokens
1668fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1669fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    def writeWithWarning(self,out,warning,left_count,repeat_count):
1670fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # removeWhiteSpace() will sometimes creates non-directive blocks
1671fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # without any tokens. These come from blocks that only contained
1672fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # empty lines and spaces. They should not be printed in the final
1673fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # output, and then should not be counted for this operation.
1674fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        #
1675fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if not self.directive and self.tokens == []:
1676fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            return left_count
1677fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1678fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        if self.directive:
1679c95eb57405d3d2f0e6cfab313aa74b1bad280452Elliott Hughes            out.write(str(self).rstrip() + "\n")
1680fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            left_count -= 1
1681fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            if left_count == 0:
1682fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                out.write(warning)
1683fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                left_count = repeat_count
1684fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1685fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        else:
1686fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            for tok in self.tokens:
1687fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                out.write(str(tok))
1688fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                if tok.id == tokLN:
1689fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    left_count -= 1
1690fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if left_count == 0:
1691fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        out.write(warning)
1692fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        left_count = repeat_count
1693fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1694fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        return left_count
1695fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1696fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
16971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
16981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """generate the representation of a given block"""
16991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.directive:
17001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result = "#%s " % self.directive
17011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if self.isIf():
17021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                result += repr(self.expr)
17031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
17041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for tok in self.tokens:
17051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result += repr(tok)
17061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
17071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result = ""
17081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for tok in self.tokens:
17091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                result += repr(tok)
17101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
17121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
17141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """generate the string representation of a given block"""
17151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if self.directive:
17161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if self.directive == "if":
17171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # small optimization to re-generate #ifdef and #ifndef
17181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                e = self.expr.expr
17191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                op = e[0]
17201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if op == "defined":
17211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result = "#ifdef %s" % e[1]
17221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                elif op == "!" and e[1][0] == "defined":
17231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result = "#ifndef %s" % e[1][1]
17241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                else:
17251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result = "#if " + str(self.expr)
17261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
17271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                result = "#%s" % self.directive
17281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if len(self.tokens):
17291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result += " "
17301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                for tok in self.tokens:
17311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    result += str(tok)
17321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        else:
17331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result = ""
17341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for tok in self.tokens:
17351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                result += str(tok)
17361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
17381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass BlockList:
17401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a convenience class used to hold and process a list of blocks returned by
17411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project       the cpp parser"""
17421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,blocks):
17431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.blocks = blocks
17441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __len__(self):
17461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return len(self.blocks)
17471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __getitem__(self,n):
17491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.blocks[n]
17501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __repr__(self):
17521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return repr(self.blocks)
17531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __str__(self):
17551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = ""
17561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for b in self.blocks:
17571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += str(b)
17581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if b.isDirective():
1759c95eb57405d3d2f0e6cfab313aa74b1bad280452Elliott Hughes                result = result.rstrip() + '\n'
17601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
17611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def  optimizeIf01(self):
17631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """remove the code between #if 0 .. #endif in a BlockList"""
17641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.blocks = optimize_if01(self.blocks)
17651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def optimizeMacros(self, macros):
17671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """remove known defined and undefined macros from a BlockList"""
17681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for b in self.blocks:
17691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if b.isIf():
17701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                b.expr.optimize(macros)
17711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def removeMacroDefines(self,macros):
17731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """remove known macro definitions from a BlockList"""
17741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.blocks = remove_macro_defines(self.blocks,macros)
17751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def removePrefixed(self,prefix,names):
17771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for b in self.blocks:
17781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if b.isIf():
17791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                b.expr.removePrefixed(prefix,names)
17801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1781fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    def removeWhiteSpace(self):
1782fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        for b in self.blocks:
1783fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            b.removeWhiteSpace()
1784fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
17851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def optimizeAll(self,macros):
17861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.optimizeMacros(macros)
17871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.optimizeIf01()
17881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return
17891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def findIncludes(self):
17911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """return the list of included files in a BlockList"""
17921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = []
17931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for b in self.blocks:
17941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i = b.isInclude()
17951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if i:
17961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                result.append(i)
17971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
17981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
17991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
18001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
18011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def write(self,out):
18021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        out.write(str(self))
18031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1804fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner    def writeWithWarning(self,out,warning,repeat_count):
1805fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        left_count = repeat_count
1806fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        for b in self.blocks:
1807fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner            left_count = b.writeWithWarning(out,warning,left_count,repeat_count)
1808fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
18091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def removeComments(self):
18101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for b in self.blocks:
18111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            for tok in b.tokens:
18121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if tok.id == tokSPACE:
18131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    tok.value = " "
18141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
18151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def removeVarsAndFuncs(self,knownStatics=set()):
18161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """remove all extern and static declarations corresponding
18171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           to variable and function declarations. we only accept typedefs
18181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           and enum/structs/union declarations.
18191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
18201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           however, we keep the definitions corresponding to the set
18211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           of known static inline functions in the set 'knownStatics',
18221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           which is useful for optimized byteorder swap functions and
18231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           stuff like that.
18241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           """
18251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # state = 0 => normal (i.e. LN + spaces)
1826fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # state = 1 => typedef/struct encountered, ends with ";"
1827fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # state = 2 => var declaration encountered, ends with ";"
1828fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        # state = 3 => func declaration encountered, ends with "}"
18291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        state      = 0
18301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        depth      = 0
18311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        blocks2    = []
1832fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner        skipTokens = False
18331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        for b in self.blocks:
18341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if b.isDirective():
18351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                blocks2.append(b)
18361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
18371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                n     = len(b.tokens)
18381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                i     = 0
1839fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                if skipTokens:
18401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    first = n
1841fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                else:
1842fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    first = 0
18431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                while i < n:
18441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    tok = b.tokens[i]
1845fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    tokid = tok.id
1846fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # If we are not looking for the start of a new
1847fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # type/var/func, then skip over tokens until
1848fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # we find our terminator, managing the depth of
1849fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # accolades as we go.
1850fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if state > 0:
1851fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        terminator = False
1852fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        if tokid == '{':
18531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                            depth += 1
1854fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        elif tokid == '}':
18551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                            if depth > 0:
18561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                depth -= 1
1857fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            if (depth == 0) and (state == 3):
1858fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                                terminator = True
1859fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        elif tokid == ';' and depth == 0:
1860fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            terminator = True
18611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1862fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        if terminator:
1863fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            # we found the terminator
18641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                            state = 0
1865fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            if skipTokens:
1866fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                                skipTokens = False
1867fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                                first = i+1
1868fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1869fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        i = i+1
1870fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        continue
1871fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1872fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # We are looking for the start of a new type/func/var
1873fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # ignore whitespace
1874fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if tokid in [tokLN, tokSPACE]:
1875fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        i = i+1
1876fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        continue
1877fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1878fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # Is it a new type definition, then start recording it
1879fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if tok.value in [ 'struct', 'typedef', 'enum', 'union', '__extension__' ]:
1880fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        #print "$$$ keep type declr" + repr(b.tokens[i:])
1881fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        state = 1
1882fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        i     = i+1
1883fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        continue
1884fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1885fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # Is it a variable or function definition. If so, first
1886fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # try to determine which type it is, and also extract
1887fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # its name.
1888fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    #
1889fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # We're going to parse the next tokens of the same block
1890fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # until we find a semi-column or a left parenthesis.
1891fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    #
1892fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # The semi-column corresponds to a variable definition,
1893fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # the left-parenthesis to a function definition.
1894fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    #
1895fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # We also assume that the var/func name is the last
1896fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    # identifier before the terminator.
1897fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    #
1898fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    j = i+1
1899fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    ident = ""
1900fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    while j < n:
1901fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        tokid = b.tokens[j].id
1902fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        if tokid == '(':  # a function declaration
1903fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            state = 3
1904fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            break
1905fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        elif tokid == ';': # a variable declaration
1906fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            state = 2
1907fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            break
1908fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        if tokid == tokIDENT:
1909fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            ident = b.tokens[j].value
1910fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        j += 1
19111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1912fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if j >= n:
1913fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # This can only happen when the declaration
1914fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # does not end on the current block (e.g. with
1915fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # a directive mixed inside it.
1916fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        #
1917fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # We will treat it as malformed because
1918fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # it's very hard to recover from this case
1919fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # without making our parser much more
1920fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # complex.
1921fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        #
1922fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        #print "### skip unterminated static '%s'" % ident
1923fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        break
1924fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1925fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    if ident in knownStatics:
1926fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        #print "### keep var/func '%s': %s" % (ident,repr(b.tokens[i:j]))
1927fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        pass
1928fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    else:
1929fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        # We're going to skip the tokens for this declaration
1930fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        #print "### skip variable /func'%s': %s" % (ident,repr(b.tokens[i:j]))
1931fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        if i > first:
1932fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                            blocks2.append( Block(b.tokens[first:i]))
1933fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        skipTokens = True
1934fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                        first      = n
1935fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner
1936fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner                    i = i+1
19371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if i > first:
19391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    #print "### final '%s'" % repr(b.tokens[first:i])
19401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    blocks2.append( Block(b.tokens[first:i]) )
19411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.blocks = blocks2
19431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def insertDisclaimer(self,disclaimer="/* auto-generated file, DO NOT EDIT */"):
19451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """insert your standard issue disclaimer that this is an
19461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           auto-generated file, etc.."""
19471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        tokens = CppLineTokenizer( disclaimer ).toTokenList()
19481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        tokens = tokens[:-1]  # remove trailing tokLN
19491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.blocks = [ Block(tokens) ] + self.blocks
19501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1951d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo    def replaceTokens(self,replacements=dict()):
1952d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo        """replace tokens according to the given dict
1953d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo           """
1954d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo        for b in self.blocks:
1955d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo            if not b.isDirective():
1956d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo                for tok in b.tokens:
1957d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo                    if tok.id == tokIDENT:
1958d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo                        if tok.value in replacements:
1959d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo                            tok.value = replacements[tok.value]
1960d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo
19611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectclass BlockParser:
19621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """a class used to convert an input source file into a BlockList object"""
19631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def __init__(self,tokzer=None):
19651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """initialize a block parser. the input source is provided through a Tokenizer
19661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           object"""
19671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.reset(tokzer)
19681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def reset(self,tokzer):
19701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.state  = 1
19711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        self.tokzer = tokzer
19721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def getBlocks(self,tokzer=None):
19741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """tokenize and parse the input source, return a BlockList object
19751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project           NOTE: empty and line-numbering directives are ignored and removed
19761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                 from the result. as a consequence, it is possible to have
19771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                 two successive text blocks in the result"""
19781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # state 0 => in source code
19791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # state 1 => in source code, after a LN
19801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # state 2 => in source code, after LN then some space
19811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        state   = 1
19821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        lastLN  = 0
19831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        current = []
19841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        blocks  = []
19851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if tokzer == None:
19871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tokzer = self.tokzer
19881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while 1:
19901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            tok = tokzer.getToken()
19911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if tok.id == tokEOF:
19921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break
19931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if tok.id == tokLN:
19951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                state    = 1
19961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                current.append(tok)
19971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                lastLN   = len(current)
19981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
19991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif tok.id == tokSPACE:
20001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if state == 1:
20011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    state = 2
20021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                current.append(tok)
20031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif tok.id == "#":
20051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if state > 0:
20061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    # this is the start of a directive
20071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if lastLN > 0:
20091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        # record previous tokens as text block
20101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        block   = Block(current[:lastLN])
20111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        blocks.append(block)
20121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        lastLN  = 0
20131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    current = []
20151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    # skip spaces after the #
20171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    while 1:
20181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        tok = tokzer.getToken()
20191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        if tok.id != tokSPACE:
20201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                            break
20211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    if tok.id != tokIDENT:
20231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        # empty or line-numbering, ignore it
20241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        if tok.id != tokLN and tok.id != tokEOF:
20251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                            while 1:
20261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                tok = tokzer.getToken()
20271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                if tok.id == tokLN or tok.id == tokEOF:
20281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                                    break
20291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        continue
20301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    directive = tok.value
20321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    lineno    = tok.lineno
20331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    # skip spaces
20351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    tok = tokzer.getToken()
20361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    while tok.id == tokSPACE:
20371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        tok = tokzer.getToken()
20381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    # then record tokens until LN
20401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    dirtokens = []
20411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    while tok.id != tokLN and tok.id != tokEOF:
20421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        dirtokens.append(tok)
20431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                        tok = tokzer.getToken()
20441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    block = Block(dirtokens,directive,lineno)
20461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    blocks.append(block)
20471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    state   = 1
20481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            else:
20501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                state = 0
20511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                current.append(tok)
20521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if len(current) > 0:
20541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            block = Block(current)
20551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            blocks.append(block)
20561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return BlockList(blocks)
20581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def parse(self,tokzer):
20601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.getBlocks( tokzer )
20611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def parseLines(self,lines):
20631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """parse a list of text lines into a BlockList object"""
20641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return self.getBlocks( CppLinesTokenizer(lines) )
20651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    def parseFile(self,path):
20671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        """parse a file into a BlockList object"""
20681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        file = open(path, "rt")
20691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        result = self.getBlocks( CppFileTokenizer(file) )
20701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        file.close()
20711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return result
20721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_block_parsing(lines,expected):
20751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    blocks = BlockParser().parse( CppLinesTokenizer(lines) )
20761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if len(blocks) != len(expected):
20771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        raise BadExpectedToken, "parser.buildBlocks returned '%s' expecting '%s'" \
20781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project              % (str(blocks), repr(expected))
20791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for n in range(len(blocks)):
20801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if str(blocks[n]) != expected[n]:
20811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            raise BadExpectedToken, "parser.buildBlocks()[%d] is '%s', expecting '%s'" \
20821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                  % (n, str(blocks[n]), expected[n])
20831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    #for block in blocks:
20841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    #    print block
20851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_BlockParser():
20871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_block_parsing(["#error hello"],["#error hello"])
20881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_block_parsing([ "foo", "", "bar" ], [ "foo\n\nbar\n" ])
20891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_block_parsing([ "foo", "  #  ", "bar" ], [ "foo\n","bar\n" ])
20901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_block_parsing(\
20911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        [ "foo", "   #  ", "  #  /* ahah */ if defined(__KERNEL__) ", "bar", "#endif" ],
20921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        [ "foo\n", "#ifdef __KERNEL__", "bar\n", "#endif" ] )
20931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
20951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
20961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
20971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
20981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####        B L O C K   L I S T   O P T I M I Z A T I O N                      #####
20991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
21001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
21011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
21021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef  remove_macro_defines( blocks, excludedMacros=set() ):
21041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """remove macro definitions like #define <macroName>  ...."""
21051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    result = []
21061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    for b in blocks:
21071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        macroName = b.isDefine()
21081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if macroName == None or not macroName in excludedMacros:
21091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result.append(b)
21101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return result
21121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef  find_matching_endif( blocks, i ):
21141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    n     = len(blocks)
21151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    depth = 1
21161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    while i < n:
21171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if blocks[i].isDirective():
21181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            dir = blocks[i].directive
21191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if dir in [ "if", "ifndef", "ifdef" ]:
21201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                depth += 1
21211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif depth == 1 and dir in [ "else", "elif" ]:
21221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                return i
21231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif dir == "endif":
21241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                depth -= 1
21251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                if depth == 0:
21261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                    return i
21271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        i += 1
21281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return i
21291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef  optimize_if01( blocks ):
21311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """remove the code between #if 0 .. #endif in a list of CppBlocks"""
21321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    i = 0
21331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    n = len(blocks)
21341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    result = []
21351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    while i < n:
21361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        j = i
21371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        while j < n and not blocks[j].isIf():
21381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            j += 1
21391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if j > i:
21401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D2("appending lines %d to %d" % (blocks[i].lineno, blocks[j-1].lineno))
21411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += blocks[i:j]
21421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if j >= n:
21431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break
21441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        expr = blocks[j].expr
21451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        r    = expr.toInt()
21461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if r == None:
21471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result.append(blocks[j])
21481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i = j + 1
21491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            continue
21501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if r == 0:
21521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # if 0 => skip everything until the corresponding #endif
21531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            j = find_matching_endif( blocks, j+1 )
21541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if j >= n:
21551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # unterminated #if 0, finish here
21561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                break
21571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            dir = blocks[j].directive
21581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if dir == "endif":
21591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                D2("remove 'if 0' .. 'endif' (lines %d to %d)" % (blocks[i].lineno, blocks[j].lineno))
21601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                i = j + 1
21611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif dir == "else":
21621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # convert 'else' into 'if 1'
21631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                D2("convert 'if 0' .. 'else' into 'if 1' (lines %d to %d)" % (blocks[i].lineno, blocks[j-1].lineno))
21641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                blocks[j].directive = "if"
21651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                blocks[j].expr      = CppExpr( CppLineTokenizer("1").toTokenList() )
21661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                i = j
21671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            elif dir == "elif":
21681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                # convert 'elif' into 'if'
21691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                D2("convert 'if 0' .. 'elif' into 'if'")
21701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                blocks[j].directive = "if"
21711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project                i = j
21721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            continue
21731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        # if 1 => find corresponding endif and remove/transform them
21751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        k = find_matching_endif( blocks, j+1 )
21761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if k >= n:
21771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # unterminated #if 1, finish here
21781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D2("unterminated 'if 1'")
21791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += blocks[j+1:k]
21801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            break
21811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        dir = blocks[k].directive
21831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if dir == "endif":
21841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D2("convert 'if 1' .. 'endif' (lines %d to %d)"  % (blocks[j].lineno, blocks[k].lineno))
21851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += optimize_if01(blocks[j+1:k])
21861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i       = k+1
21871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif dir == "else":
21881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # convert 'else' into 'if 0'
21891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D2("convert 'if 1' .. 'else' (lines %d to %d)"  % (blocks[j].lineno, blocks[k].lineno))
21901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += optimize_if01(blocks[j+1:k])
21911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            blocks[k].directive = "if"
21921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            blocks[k].expr      = CppExpr( CppLineTokenizer("0").toTokenList() )
21931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i = k
21941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        elif dir == "elif":
21951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            # convert 'elif' into 'if 0'
21961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            D2("convert 'if 1' .. 'elif' (lines %d to %d)" % (blocks[j].lineno, blocks[k].lineno))
21971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            result += optimize_if01(blocks[j+1:k])
21981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            blocks[k].expr      = CppExpr( CppLineTokenizer("0").toTokenList() )
21991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            i = k
22001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    return result
22011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef  test_optimizeAll():
22031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    text = """\
22041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 1
22051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  GOOD_1
22061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
22071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0
22081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  BAD_2
22091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  BAD_3
22101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
22111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 1
22131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  GOOD_2
22141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
22151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  BAD_4
22161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
22171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0
22191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  BAD_5
22201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
22211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  GOOD_3
22221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
22231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0
22251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 1
22261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define  BAD_6
22271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
22281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif\
22291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project"""
22301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    expected = """\
22321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_1
22331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_2
22351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_3
22371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project"""
22391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "running test_BlockList.optimizeAll"
22411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    out = StringOutput()
22421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    lines = string.split(text, '\n')
22431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    list = BlockParser().parse( CppLinesTokenizer(lines) )
22441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    #D_setlevel(2)
22451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    list.optimizeAll( {"__KERNEL__":kCppUndefinedMacro} )
22461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    #print repr(list)
22471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    list.write(out)
22481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    if out.get() != expected:
22491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "KO: macro optimization failed\n"
22501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "<<<< expecting '",
22511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print expected,
22521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "'\n>>>> result '"
22531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print out.get(),
22541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        print "'\n----"
22551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
22581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
22591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
22601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
22611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####                                                                           #####
22621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
22631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#####################################################################################
22641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef runUnitTests():
22661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    """run all unit tests for this program"""
22671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "running unit tests"
22681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_CppTokenizer()
22691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_CppExpr()
22701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_optimizeAll()
22711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    test_BlockParser()
22721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    print "OK"
22731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
22741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectif __name__ == "__main__":
22751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    runUnitTests()
2276