1d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao#!/usr/bin/python 2d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao"""A glorified C pre-processor parser.""" 3d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 4d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport ctypes 5d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport logging 6d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport os 7d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport re 8d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport site 9d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport utils 10d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 11d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baotop = os.getenv('ANDROID_BUILD_TOP') 12d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoif top is None: 13d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao utils.panic('ANDROID_BUILD_TOP not set.\n') 14d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 15d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# Set up the env vars for libclang. 16d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baosite.addsitedir(os.path.join(top, 'external/clang/bindings/python')) 17d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 18d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoimport clang.cindex 19d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import conf 20d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import Cursor 21d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import CursorKind 22d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import SourceLocation 23d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import SourceRange 24d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import TokenGroup 25d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import TokenKind 26d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom clang.cindex import TranslationUnit 27d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 287592008030a67ebe0dbda20aa041d5c347170611Tao Bao# Set up LD_LIBRARY_PATH to include libclang.so, libLLVM.so, and etc. 297592008030a67ebe0dbda20aa041d5c347170611Tao Bao# Note that setting LD_LIBRARY_PATH with os.putenv() sometimes doesn't help. 307592008030a67ebe0dbda20aa041d5c347170611Tao Baoclang.cindex.Config.set_library_path(os.path.join(top, 'prebuilts/sdk/tools/linux/lib64')) 317592008030a67ebe0dbda20aa041d5c347170611Tao Bao 32d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom defaults import kCppUndefinedMacro 33d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom defaults import kernel_remove_config_macros 34d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baofrom defaults import kernel_token_replacements 35d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 36d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 37d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaodebugBlockParser = False 38d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaodebugCppExpr = False 39d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaodebugOptimIf01 = False 40d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 41d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao############################################################################### 42d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao############################################################################### 43d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 44d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### C P P T O K E N S ##### 45d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 46d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao############################################################################### 47d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao############################################################################### 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# the list of supported C-preprocessor tokens 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# plus a couple of C tokens as well 51d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokEOF = "\0" 52d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLN = "\n" 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokSTRINGIFY = "#" 54d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokCONCAT = "##" 55d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLOGICAND = "&&" 56d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLOGICOR = "||" 57d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokSHL = "<<" 58d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokSHR = ">>" 59d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokEQUAL = "==" 60d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokNEQUAL = "!=" 61d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLT = "<" 62d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLTE = "<=" 63d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokGT = ">" 64d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokGTE = ">=" 65d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokELLIPSIS = "..." 66d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokSPACE = " " 67d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokDEFINED = "defined" 68d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLPAREN = "(" 69d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokRPAREN = ")" 70d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokNOT = "!" 71d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokPLUS = "+" 72d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokMINUS = "-" 73d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokMULTIPLY = "*" 74d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokDIVIDE = "/" 75d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokMODULUS = "%" 76d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokBINAND = "&" 77d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokBINOR = "|" 78d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokBINXOR = "^" 79d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokCOMMA = "," 80d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokLBRACE = "{" 81d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokRBRACE = "}" 82d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokARROW = "->" 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokINCREMENT = "++" 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source ProjecttokDECREMENT = "--" 85d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokNUMBER = "<number>" 86d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokIDENT = "<ident>" 87d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaotokSTRING = "<string>" 88d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 89d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 90d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass Token(clang.cindex.Token): 91d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A class that represents one token after parsing. 92d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 93d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao It inherits the class in libclang, with an extra id property to hold the 94d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao new spelling of the token. The spelling property in the base class is 95d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao defined as read-only. New names after macro instantiation are saved in 96d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao their ids now. It also facilitates the renaming of directive optimizations 97d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao like replacing 'ifndef X' with 'if !defined(X)'. 98d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 99d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao It also overrides the cursor property of the base class. Because the one 100d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao in libclang always queries based on a single token, which usually doesn't 101d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao hold useful information. The cursor in this class can be set by calling 102d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao CppTokenizer.getTokensWithCursors(). Otherwise it returns the one in the 103d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao base class. 104d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 105d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 106d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, tu=None, group=None, int_data=None, ptr_data=None, 107d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursor=None): 108d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao clang.cindex.Token.__init__(self) 109d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._id = None 110d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tu = tu 111d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._group = group 112d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._cursor = cursor 113d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # self.int_data and self.ptr_data are from the base class. But 114d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # self.int_data doesn't accept a None value. 115d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if int_data is not None: 116d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.int_data = int_data 117d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.ptr_data = ptr_data 118d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 119d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @property 120d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def id(self): 121d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Name of the token.""" 122d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._id is None: 123d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.spelling 124d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao else: 125d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self._id 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 127d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @id.setter 128d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def id(self, new_id): 129d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Setting name of the token.""" 130d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._id = new_id 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 132d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @property 133d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def cursor(self): 134d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._cursor is None: 135d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._cursor = clang.cindex.Token.cursor 136d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self._cursor 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 138d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @cursor.setter 139d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def cursor(self, new_cursor): 140d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._cursor = new_cursor 1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __repr__(self): 143d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.id == 'defined': 144d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.id 145d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif self.kind == TokenKind.IDENTIFIER: 146d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return "(ident %s)" % self.id 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return self.id 1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __str__(self): 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return self.id 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 154d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass BadExpectedToken(Exception): 155d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """An exception that will be raised for unexpected tokens.""" 156d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao pass 157d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 158d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 159d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# The __contains__ function in libclang SourceRange class contains a bug. It 160d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# gives wrong result when dealing with single line range. 161d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# Bug filed with upstream: 162d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# http://llvm.org/bugs/show_bug.cgi?id=22243, http://reviews.llvm.org/D7277 163d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef SourceRange__contains__(self, other): 164d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Determine if a given location is inside the range.""" 165d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if not isinstance(other, SourceLocation): 166d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return False 167d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if other.file is None and self.start.file is None: 168d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao pass 169d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif (self.start.file.name != other.file.name or 170d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao other.file.name != self.end.file.name): 171d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # same file name 172d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return False 173d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # same file, in between lines 174d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.start.line < other.line < self.end.line: 175d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return True 176d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # same file, same line 177d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif self.start.line == other.line == self.end.line: 178d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.start.column <= other.column <= self.end.column: 179d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return True 180d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif self.start.line == other.line: 181d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # same file first line 182d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.start.column <= other.column: 183d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return True 184d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif other.line == self.end.line: 185d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # same file last line 186d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if other.column <= self.end.column: 187d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return True 188d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return False 189d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 190d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 191d7db594b8d1dab36b711bd887a9dd21675c87243Tao BaoSourceRange.__contains__ = SourceRange__contains__ 192d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 193d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 194d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 195d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 196d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 197d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### C P P T O K E N I Z E R ##### 198d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 199d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 200d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 201d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 202d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 203d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass CppTokenizer(object): 204d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A tokenizer that converts some input text into a list of tokens. 205d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 206d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao It calls libclang's tokenizer to get the parsed tokens. In addition, it 207d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao updates the cursor property in each token after parsing, by calling 208d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao getTokensWithCursors(). 209d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 210d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 211d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao clang_flags = ['-E', '-x', 'c'] 212d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao options = TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 214d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self): 215d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Initialize a new CppTokenizer object.""" 216d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._indexer = clang.cindex.Index.create() 217d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tu = None 218d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index = 0 219d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens = None 220d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 221d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def _getTokensWithCursors(self): 222d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Helper method to return all tokens with their cursors. 223d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 224d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao The cursor property in a clang Token doesn't provide enough 225d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao information. Because it is queried based on single token each time 226d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao without any context, i.e. via calling conf.lib.clang_annotateTokens() 227d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao with only one token given. So we often see 'INVALID_FILE' in one 228d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token's cursor. In this function it passes all the available tokens 229d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao to get more informative cursors. 230d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 231d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 232d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens_memory = ctypes.POINTER(clang.cindex.Token)() 233d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens_count = ctypes.c_uint() 234d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 235d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao conf.lib.clang_tokenize(self._tu, self._tu.cursor.extent, 236d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ctypes.byref(tokens_memory), 237d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ctypes.byref(tokens_count)) 238d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 239d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao count = int(tokens_count.value) 240d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 241d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # If we get no tokens, no memory was allocated. Be sure not to return 242d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # anything and potentially call a destructor on nothing. 243d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if count < 1: 244d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 246d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursors = (Cursor * count)() 247d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursors_memory = ctypes.cast(cursors, ctypes.POINTER(Cursor)) 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 249d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao conf.lib.clang_annotateTokens(self._tu, tokens_memory, count, 250d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursors_memory) 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 252d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens_array = ctypes.cast( 253d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens_memory, 254d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ctypes.POINTER(clang.cindex.Token * count)).contents 255d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token_group = TokenGroup(self._tu, tokens_memory, tokens_count) 2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 257d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens = [] 258d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for i in xrange(0, count): 259d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = Token(self._tu, token_group, 260d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao int_data=tokens_array[i].int_data, 261d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ptr_data=tokens_array[i].ptr_data, 262d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursor=cursors[i]) 263d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # We only want non-comment tokens. 264d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if token.kind != TokenKind.COMMENT: 265d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens.append(token) 266d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 267d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return tokens 268d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 269d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def parseString(self, lines): 270d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Parse a list of text lines into a BlockList object.""" 271d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao file_ = 'dummy.c' 272d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tu = self._indexer.parse(file_, self.clang_flags, 273d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao unsaved_files=[(file_, lines)], 274d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao options=self.options) 275d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens = self._getTokensWithCursors() 276d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 277d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def parseFile(self, file_): 278d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Parse a file into a BlockList object.""" 279d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tu = self._indexer.parse(file_, self.clang_flags, 280d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao options=self.options) 281d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens = self._getTokensWithCursors() 2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 283d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def nextToken(self): 284d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return next token from the list.""" 285d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index < len(self.tokens): 286d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = self.tokens[self._index] 287d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 288d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return t 2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 290d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 293d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass CppStringTokenizer(CppTokenizer): 294d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A CppTokenizer derived class that accepts a string of text as input.""" 2951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 296d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, line): 297d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao CppTokenizer.__init__(self) 298d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.parseString(line) 2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 301d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass CppFileTokenizer(CppTokenizer): 302d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A CppTokenizer derived class that accepts a file as input.""" 3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 304d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, file_): 3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project CppTokenizer.__init__(self) 306d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.parseFile(file_) 3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 309d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# Unit testing 310d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao# 311d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass CppTokenizerTester(object): 312d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A class used to test CppTokenizer classes.""" 3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 314d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, tokenizer=None): 315d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tokenizer = tokenizer 316d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._token = None 3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 318d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def setTokenizer(self, tokenizer): 319d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tokenizer = tokenizer 3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 321d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def expect(self, id): 322d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._token = self._tokenizer.nextToken() 323d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._token is None: 324d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokid = '' 3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 326d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokid = self._token.id 3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if tokid == id: 3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 329d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken("### BAD TOKEN: '%s' expecting '%s'" % ( 330d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokid, id)) 3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 332d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def expectToken(self, id, line, col): 3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.expect(id) 334d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._token.location.line != line: 335d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken( 336d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "### BAD LINENO: token '%s' got '%d' expecting '%d'" % ( 337d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao id, self._token.lineno, line)) 338d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._token.location.column != col: 339d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken("### BAD COLNO: '%d' expecting '%d'" % ( 340d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._token.colno, col)) 341d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 342d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def expectTokens(self, tokens): 343d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for id, line, col in tokens: 344d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.expectToken(id, line, col) 345d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 346d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def expectList(self, list_): 347d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for item in list_: 3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.expect(item) 3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 350d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 3511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_CppTokenizer(): 3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tester = CppTokenizerTester() 3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 354d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("#an/example && (01923_xy)")) 355d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectList(["#", "an", "/", "example", tokLOGICAND, tokLPAREN, 356d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "01923_xy", tokRPAREN]) 357d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 358d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("FOO(BAR) && defined(BAZ)")) 359d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectList(["FOO", tokLPAREN, "BAR", tokRPAREN, tokLOGICAND, 360d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "defined", tokLPAREN, "BAZ", tokRPAREN]) 361d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 362d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("/*\n#\n*/")) 363d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectList([]) 364d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 365d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("first\nsecond")) 366d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectList(["first", "second"]) 3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 368d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("first second\n third")) 369d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectTokens([("first", 1, 1), 370d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ("second", 1, 7), 371d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ("third", 2, 3)]) 372d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 373d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("boo /* what the\nhell */")) 374d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectTokens([("boo", 1, 1)]) 375d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 376d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.setTokenizer(CppStringTokenizer("an \\\n example")) 377d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tester.expectTokens([("an", 1, 1), 378d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ("example", 2, 2)]) 3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return True 3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 3811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 382d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 383d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 384d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 385d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### C P P E X P R E S S I O N S ##### 386d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 387d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 388d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 389d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 391d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass CppExpr(object): 392d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A class that models the condition of #if directives into an expr tree. 3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 394d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao Each node in the tree is of the form (op, arg) or (op, arg1, arg2) where 395d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "op" is a string describing the operation 396d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 397d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 398d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao unaries = ["!", "~"] 399d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao binaries = ["+", "-", "<", "<=", ">=", ">", "&&", "||", "*", "/", "%", 400d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "&", "|", "^", "<<", ">>", "==", "!=", "?", ":"] 4011198fd38645ff94bf48daae10f8b74903444badcElliott Hughes precedences = { 4021198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "?": 1, ":": 1, 4031198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "||": 2, 4041198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "&&": 3, 4051198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "|": 4, 4061198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "^": 5, 4071198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "&": 6, 4081198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "==": 7, "!=": 7, 4091198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "<": 8, "<=": 8, ">": 8, ">=": 8, 4101198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "<<": 9, ">>": 9, 4111198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "+": 10, "-": 10, 4121198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "*": 11, "/": 11, "%": 11, 4131198fd38645ff94bf48daae10f8b74903444badcElliott Hughes "!": 12, "~": 12 4141198fd38645ff94bf48daae10f8b74903444badcElliott Hughes } 4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __init__(self, tokens): 417d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Initialize a CppExpr. 'tokens' must be a CppToken list.""" 418d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens = tokens 419d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._num_tokens = len(tokens) 420d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index = 0 421d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if debugCppExpr: 4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project print "CppExpr: trying to parse %s" % repr(tokens) 42440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.expr = self.parseExpression(0) 4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if debugCppExpr: 42640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes print "CppExpr: got " + repr(self.expr) 427d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index != self._num_tokens: 428d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.throw(BadExpectedToken, "crap at end of input (%d != %d): %s" 429d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao % (self._index, self._num_tokens, repr(tokens))) 4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 43140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def throw(self, exception, msg): 432d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index < self._num_tokens: 433d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tok = self.tokens[self._index] 434d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print "%d:%d: %s" % (tok.location.line, tok.location.column, msg) 4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project print "EOF: %s" % msg 43740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes raise exception(msg) 4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 43940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def expectId(self, id): 440d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Check that a given token id is at the current position.""" 441d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = self.tokens[self._index] 442d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens or token.id != id: 443d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.throw(BadExpectedToken, 444d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "### expecting '%s' in expression, got '%s'" % ( 445d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao id, token.id)) 446d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 44740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 44840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def is_decimal(self): 449d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = self.tokens[self._index].id 450d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if token[-1] in "ULul": 451d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = token[:-1] 452d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao try: 453d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao val = int(token, 10) 454d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 455d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return ('int', val) 456d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao except ValueError: 457d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 459d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def is_octal(self): 460d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = self.tokens[self._index].id 461d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if token[-1] in "ULul": 462d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = token[:-1] 463d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if len(token) < 2 or token[0] != '0': 464d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 465d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao try: 466d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao val = int(token, 8) 467d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 468d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return ('oct', val) 469d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao except ValueError: 470d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 47140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 47240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def is_hexadecimal(self): 473d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = self.tokens[self._index].id 474d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if token[-1] in "ULul": 475d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao token = token[:-1] 476d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if len(token) < 3 or (token[:2] != '0x' and token[:2] != '0X'): 477d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 478d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao try: 479d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao val = int(token, 16) 480d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 481d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return ('hex', val) 482d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao except ValueError: 483d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 48440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 48540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def is_integer(self): 486d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.tokens[self._index].kind != TokenKind.LITERAL: 4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 48940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes c = self.is_hexadecimal() 490d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if c: 491d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return c 4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 493d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao c = self.is_octal() 494d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if c: 495d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return c 4961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 497d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao c = self.is_decimal() 498d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if c: 499d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return c 500d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 501d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return None 50240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 50340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def is_number(self): 504d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = self.tokens[self._index] 505d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if t.id == tokMINUS and self._index + 1 < self._num_tokens: 506d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 50740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes c = self.is_integer() 5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if c: 509d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao op, val = c 51040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return (op, -val) 511d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if t.id == tokPLUS and self._index + 1 < self._num_tokens: 512d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 51340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes c = self.is_integer() 514d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if c: 515d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return c 5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 51740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return self.is_integer() 5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 51940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def is_defined(self): 520d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = self.tokens[self._index] 5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if t.id != tokDEFINED: 5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 524d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # We have the defined keyword, check the rest. 525d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 526d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao used_parens = False 527d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if (self._index < self._num_tokens and 528d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens[self._index].id == tokLPAREN): 529d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao used_parens = True 530d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 531d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 532d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens: 533d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.throw(BadExpectedToken, 534d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "### 'defined' must be followed by macro name or left " 535d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "paren") 536d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 537d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = self.tokens[self._index] 538d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if t.kind != TokenKind.IDENTIFIER: 539d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.throw(BadExpectedToken, 540d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "### 'defined' must be followed by macro name") 541d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 542d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 543fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes if used_parens: 54440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.expectId(tokRPAREN) 5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 546d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return ("defined", t.id) 5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 54840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def is_call_or_ident(self): 549d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens: 5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 552d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = self.tokens[self._index] 553d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if t.kind != TokenKind.IDENTIFIER: 5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 556d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao name = t.id 5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 558d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 559d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if (self._index >= self._num_tokens or 560d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens[self._index].id != tokLPAREN): 56140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return ("ident", name) 5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 563d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao params = [] 564d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao depth = 1 565d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 566d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao j = self._index 567d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while self._index < self._num_tokens: 568d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao id = self.tokens[self._index].id 5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if id == tokLPAREN: 5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth += 1 5711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif depth == 1 and (id == tokCOMMA or id == tokRPAREN): 572d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao k = self._index 573d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao param = self.tokens[j:k] 57440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes params.append(param) 5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if id == tokRPAREN: 5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break 577d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao j = self._index + 1 5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif id == tokRPAREN: 5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth -= 1 580d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 582d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens: 5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 585d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 58640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return ("call", (name, params)) 5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 588d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Implements the "precedence climbing" algorithm from 589d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm. 590d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # The "classic" algorithm would be fine if we were using a tool to 591d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # generate the parser, but we're not. Dijkstra's "shunting yard" 592d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # algorithm hasn't been necessary yet. 5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 59440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def parseExpression(self, minPrecedence): 595d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens: 59640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return None 5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 59840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes node = self.parsePrimary() 599d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while (self.token() and self.isBinary(self.token()) and 600d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.precedence(self.token()) >= minPrecedence): 60140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes op = self.token() 60240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.nextToken() 60340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes rhs = self.parseExpression(self.precedence(op) + 1) 60440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes node = (op.id, node, rhs) 60540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 60640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return node 60740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 60840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def parsePrimary(self): 60940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes op = self.token() 61040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes if self.isUnary(op): 61140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.nextToken() 61240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return (op.id, self.parseExpression(self.precedence(op))) 61340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 61440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes primary = None 61540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes if op.id == tokLPAREN: 61640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.nextToken() 61740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes primary = self.parseExpression(0) 61840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.expectId(tokRPAREN) 6191198fd38645ff94bf48daae10f8b74903444badcElliott Hughes elif op.id == "?": 6201198fd38645ff94bf48daae10f8b74903444badcElliott Hughes self.nextToken() 6211198fd38645ff94bf48daae10f8b74903444badcElliott Hughes primary = self.parseExpression(0) 6221198fd38645ff94bf48daae10f8b74903444badcElliott Hughes self.expectId(":") 623d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif op.id == '+' or op.id == '-' or op.kind == TokenKind.LITERAL: 62440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes primary = self.is_number() 625d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Checking for 'defined' needs to come first now because 'defined' is 626d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # recognized as IDENTIFIER. 62740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes elif op.id == tokDEFINED: 62840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes primary = self.is_defined() 629d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif op.kind == TokenKind.IDENTIFIER: 630d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao primary = self.is_call_or_ident() 63140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes else: 632d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.throw(BadExpectedToken, 633d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "didn't expect to see a %s in factor" % ( 634d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens[self._index].id)) 635d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return primary 6361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 63740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def isBinary(self, token): 63840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return token.id in self.binaries 6391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 64040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def isUnary(self, token): 64140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return token.id in self.unaries 6421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 64340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def precedence(self, token): 64440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return self.precedences.get(token.id) 6451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 64640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def token(self): 647d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens: 6481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 649d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.tokens[self._index] 6501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 65140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def nextToken(self): 652d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._index += 1 653d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self._index >= self._num_tokens: 65440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return None 655d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.tokens[self._index] 6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 65740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def dump_node(self, e): 6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op = e[0] 6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line = "(" + op 6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "int": 6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " %d)" % e[1] 662d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif op == "oct": 663d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao line += " 0%o)" % e[1] 6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "hex": 6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " 0x%x)" % e[1] 6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "ident": 6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " %s)" % e[1] 6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "defined": 6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " %s)" % e[1] 6701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "call": 6711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project arg = e[1] 6721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " %s [" % arg[0] 6731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prefix = "" 6741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for param in arg[1]: 6751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project par = "" 6761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for tok in param: 6771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project par += str(tok) 6781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += "%s%s" % (prefix, par) 6791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project prefix = "," 6801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += "])" 6811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op in CppExpr.unaries: 6821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " %s)" % self.dump_node(e[1]) 6831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op in CppExpr.binaries: 6841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " %s %s)" % (self.dump_node(e[1]), self.dump_node(e[2])) 6851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 6861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project line += " ?%s)" % repr(e[1]) 6871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return line 6891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __repr__(self): 6911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return self.dump_node(self.expr) 6921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 69340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes def source_node(self, e): 6941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op = e[0] 6951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "int": 6961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "%d" % e[1] 6971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "hex": 6981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "0x%x" % e[1] 699d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if op == "oct": 700d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return "0%o" % e[1] 7011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "ident": 7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # XXX: should try to expand 7031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return e[1] 7041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "defined": 7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "defined(%s)" % e[1] 7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 707d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao prec = CppExpr.precedences.get(op, 1000) 708d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao arg = e[1] 7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op in CppExpr.unaries: 7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project arg_src = self.source_node(arg) 711d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao arg_op = arg[0] 712d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao arg_prec = CppExpr.precedences.get(arg_op, 1000) 7131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if arg_prec < prec: 7141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "!(" + arg_src + ")" 7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "!" + arg_src 7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op in CppExpr.binaries: 718d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao arg2 = e[2] 719d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao arg1_op = arg[0] 720d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao arg2_op = arg2[0] 7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project arg1_src = self.source_node(arg) 7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project arg2_src = self.source_node(arg2) 723d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if CppExpr.precedences.get(arg1_op, 1000) < prec: 7241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project arg1_src = "(%s)" % arg1_src 725d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if CppExpr.precedences.get(arg2_op, 1000) < prec: 7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project arg2_src = "(%s)" % arg2_src 7271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "%s %s %s" % (arg1_src, op, arg2_src) 7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return "???" 7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __str__(self): 7321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return self.source_node(self.expr) 7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 734d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @staticmethod 735d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def int_node(e): 736d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if e[0] in ["int", "oct", "hex"]: 7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return e[1] 7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def toInt(self): 7421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return self.int_node(self.expr) 7431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 744d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def optimize_node(self, e, macros=None): 745d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if macros is None: 746d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao macros = {} 7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op = e[0] 748d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "defined": 75040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes op, name = e 7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if macros.has_key(name): 7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if macros[name] == kCppUndefinedMacro: 7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 0) 7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 755d3e64a3f403918abf2cc3f9f0f9a2204a420ec96Elliott Hughes try: 756d3e64a3f403918abf2cc3f9f0f9a2204a420ec96Elliott Hughes value = int(macros[name]) 757d3e64a3f403918abf2cc3f9f0f9a2204a420ec96Elliott Hughes return ("int", value) 758d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao except ValueError: 759d3e64a3f403918abf2cc3f9f0f9a2204a420ec96Elliott Hughes return ("defined", macros[name]) 7601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if kernel_remove_config_macros and name.startswith("CONFIG_"): 7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 0) 7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 76440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return e 76540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 76640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes elif op == "ident": 76740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes op, name = e 76840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes if macros.has_key(name): 76940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes try: 77040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes value = int(macros[name]) 77140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes expanded = ("int", value) 772d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao except ValueError: 77340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes expanded = ("ident", macros[name]) 77440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return self.optimize_node(expanded, macros) 77540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return e 77640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "!": 7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op, v = e 7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project v = self.optimize_node(v, macros) 7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if v[0] == "int": 7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if v[1] == 0: 7821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 1) 7831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 7841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 0) 78540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return ('!', v) 7861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "&&": 7881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op, l, r = e 789d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao l = self.optimize_node(l, macros) 790d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao r = self.optimize_node(r, macros) 7911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project li = self.int_node(l) 7921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ri = self.int_node(r) 793d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if li is not None: 7941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if li == 0: 7951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 0) 7961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 7971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return r 798d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif ri is not None: 79940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes if ri == 0: 80040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return ("int", 0) 80140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes else: 80240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return l 80340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return (op, l, r) 8041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "||": 8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op, l, r = e 807d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao l = self.optimize_node(l, macros) 808d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao r = self.optimize_node(r, macros) 8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project li = self.int_node(l) 8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ri = self.int_node(r) 811d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if li is not None: 8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if li == 0: 8131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return r 8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 1) 816d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif ri is not None: 8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ri == 0: 8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return l 8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return ("int", 1) 82140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return (op, l, r) 8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 82340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes else: 82440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes return e 8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 826d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def optimize(self, macros=None): 827d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if macros is None: 828d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao macros = {} 82940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes self.expr = self.optimize_node(self.expr, macros) 8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_cpp_expr(expr, expected): 833d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao e = CppExpr(CppStringTokenizer(expr).tokens) 8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s1 = repr(e) 8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if s1 != expected: 836d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print ("[FAIL]: expression '%s' generates '%s', should be " 837d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "'%s'" % (expr, s1, expected)) 83840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes global failure_count 83940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes failure_count += 1 8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 841d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 842d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef test_cpp_expr_optim(expr, expected, macros=None): 843d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if macros is None: 844d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao macros = {} 845d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao e = CppExpr(CppStringTokenizer(expr).tokens) 8461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project e.optimize(macros) 8471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s1 = repr(e) 8481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if s1 != expected: 849d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print ("[FAIL]: optimized expression '%s' generates '%s' with " 850d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "macros %s, should be '%s'" % (expr, s1, macros, expected)) 85140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes global failure_count 85240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes failure_count += 1 8531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 854d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 8551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_cpp_expr_source(expr, expected): 856d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao e = CppExpr(CppStringTokenizer(expr).tokens) 8571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project s1 = str(e) 8581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if s1 != expected: 859d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print ("[FAIL]: source expression '%s' generates '%s', should " 860d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "be '%s'" % (expr, s1, expected)) 86140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes global failure_count 86240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes failure_count += 1 8631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 864d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 8651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_CppExpr(): 86640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("0", "(int 0)") 86740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("1", "(int 1)") 868d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("-5", "(int -5)") 869d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("+1", "(int 1)") 870d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("0U", "(int 0)") 871d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("015", "(oct 015)") 872d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("015l", "(oct 015)") 873d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("0x3e", "(hex 0x3e)") 87440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("(0)", "(int 0)") 87540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("1 && 1", "(&& (int 1) (int 1))") 87640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("1 && 0", "(&& (int 1) (int 0))") 87740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("EXAMPLE", "(ident EXAMPLE)") 87840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("EXAMPLE - 3", "(- (ident EXAMPLE) (int 3))") 87940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("defined(EXAMPLE)", "(defined EXAMPLE)") 88040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("defined ( EXAMPLE ) ", "(defined EXAMPLE)") 88140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr("!defined(EXAMPLE)", "(! (defined EXAMPLE))") 882d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("defined(ABC) || defined(BINGO)", 883d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(|| (defined ABC) (defined BINGO))") 884d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("FOO(BAR,5)", "(call FOO [BAR,5])") 885d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr("A == 1 || defined(B)", 886d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(|| (== (ident A) (int 1)) (defined B))") 88740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 88840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("0", "(int 0)") 88940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("1", "(int 1)") 89040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("1 && 1", "(int 1)") 891d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("1 && +1", "(int 1)") 892d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("0x1 && 01", "(oct 01)") 89340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("1 && 0", "(int 0)") 89440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("0 && 1", "(int 0)") 89540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("0 && 0", "(int 0)") 89640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("1 || 1", "(int 1)") 89740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("1 || 0", "(int 1)") 89840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("0 || 1", "(int 1)") 89940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("0 || 0", "(int 0)") 90040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("A", "(ident A)") 901d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("A", "(int 1)", {"A": 1}) 902d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("A || B", "(int 1)", {"A": 1}) 903d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("A || B", "(int 1)", {"B": 1}) 904d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("A && B", "(ident B)", {"A": 1}) 905d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("A && B", "(ident A)", {"B": 1}) 90640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("A && B", "(&& (ident A) (ident B))") 90740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("EXAMPLE", "(ident EXAMPLE)") 90840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("EXAMPLE - 3", "(- (ident EXAMPLE) (int 3))") 90940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("defined(EXAMPLE)", "(defined EXAMPLE)") 910d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(EXAMPLE)", "(defined XOWOE)", 911d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"EXAMPLE": "XOWOE"}) 912d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(EXAMPLE)", "(int 0)", 913d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"EXAMPLE": kCppUndefinedMacro}) 91440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_optim("!defined(EXAMPLE)", "(! (defined EXAMPLE))") 915d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("!defined(EXAMPLE)", "(! (defined XOWOE))", 916d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"EXAMPLE": "XOWOE"}) 917d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("!defined(EXAMPLE)", "(int 1)", 918d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"EXAMPLE": kCppUndefinedMacro}) 919d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) || defined(B)", 920d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(|| (defined A) (defined B))") 921d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) || defined(B)", "(int 1)", {"A": "1"}) 922d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) || defined(B)", "(int 1)", {"B": "1"}) 923d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) || defined(B)", "(defined A)", 924d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"B": kCppUndefinedMacro}) 925d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) || defined(B)", "(int 0)", 926d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"A": kCppUndefinedMacro, "B": kCppUndefinedMacro}) 927d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) && defined(B)", 928d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(&& (defined A) (defined B))") 929d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) && defined(B)", 930d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(defined B)", {"A": "1"}) 931d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) && defined(B)", 932d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(defined A)", {"B": "1"}) 933d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) && defined(B)", "(int 0)", 934d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"B": kCppUndefinedMacro}) 935d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("defined(A) && defined(B)", 936d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(int 0)", {"A": kCppUndefinedMacro}) 937d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim("A == 1 || defined(B)", 938d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(|| (== (ident A) (int 1)) (defined B))") 939d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_cpp_expr_optim( 940d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)", 941d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "(|| (! (defined __GLIBC__)) (< (ident __GLIBC__) (int 2)))", 942d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao {"__KERNEL__": kCppUndefinedMacro}) 94340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 94440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("0", "0") 94540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("1", "1") 94640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("1 && 1", "1 && 1") 94740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("1 && 0", "1 && 0") 94840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("0 && 1", "0 && 1") 94940596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("0 && 0", "0 && 0") 95040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("1 || 1", "1 || 1") 95140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("1 || 0", "1 || 0") 95240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("0 || 1", "0 || 1") 95340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("0 || 0", "0 || 0") 95440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("EXAMPLE", "EXAMPLE") 95540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("EXAMPLE - 3", "EXAMPLE - 3") 95640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("defined(EXAMPLE)", "defined(EXAMPLE)") 95740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("defined EXAMPLE", "defined(EXAMPLE)") 95840596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes test_cpp_expr_source("A == 1 || defined(B)", "A == 1 || defined(B)") 9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 961d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 962d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 963d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 964d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### C P P B L O C K ##### 965d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 966d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 967d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 970d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass Block(object): 971d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A class used to model a block of input source text. 972d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 973d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao There are two block types: 974d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao - directive blocks: contain the tokens of a single pre-processor 975d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao directive (e.g. #if) 976d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao - text blocks, contain the tokens of non-directive blocks 977d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 978d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao The cpp parser class below will transform an input source file into a list 979d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao of Block objects (grouped in a BlockList object for convenience) 980d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 981d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 982d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, tokens, directive=None, lineno=0, identifier=None): 983d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Initialize a new block, if 'directive' is None, it is a text block. 984d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 985d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao NOTE: This automatically converts '#ifdef MACRO' into 986d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '#if defined(MACRO)' and '#ifndef MACRO' into '#if !defined(MACRO)'. 987d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if directive == "ifdef": 9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tok = Token() 991d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tok.id = tokDEFINED 992d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens = [tok] + tokens 9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project directive = "if" 9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif directive == "ifndef": 9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tok1 = Token() 9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tok2 = Token() 998d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tok1.id = tokNOT 999d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tok2.id = tokDEFINED 1000d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens = [tok1, tok2] + tokens 10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project directive = "if" 10021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1003d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.tokens = tokens 10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.directive = directive 1005d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.define_id = identifier 10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if lineno > 0: 10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.lineno = lineno 10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 1009d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.lineno = self.tokens[0].location.line 10101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if self.isIf(): 1012d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.expr = CppExpr(self.tokens) 10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def isDirective(self): 1015d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return True iff this is a directive block.""" 1016d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.directive is not None 10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def isConditional(self): 1019d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return True iff this is a conditional directive block.""" 1020d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.directive in ["if", "ifdef", "ifndef", "else", "elif", 1021d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "endif"] 10221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def isDefine(self): 1024d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return the macro name in a #define directive, or None otherwise.""" 10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if self.directive != "define": 10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 1027d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.define_id 10281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 10291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def isIf(self): 1030d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return True iff this is an #if-like directive block.""" 1031d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.directive in ["if", "ifdef", "ifndef", "elif"] 10321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1033d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def isEndif(self): 1034d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return True iff this is an #endif directive block.""" 1035d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.directive == "endif" 10361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1037d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def isInclude(self): 1038d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Check whether this is a #include directive. 10391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1040d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao If true, returns the corresponding file name (with brackets or 1041d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao double-qoutes). None otherwise. 1042d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 10431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1044d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.directive != "include": 10451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return None 1046d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return ''.join([str(x) for x in self.tokens]) 10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1048d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @staticmethod 1049d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def format_blocks(tokens, indent=0): 1050d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return the formatted lines of strings with proper indentation.""" 1051d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = True 1052d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = [] 1053d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = '' 1054d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i = 0 1055d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while i < len(tokens): 1056d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = tokens[i] 1057d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if t.id == '{': 1058d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf += ' {' 1059d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(strip_space(buf)) 1060d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao indent += 2 1061d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = '' 1062d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = True 1063d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif t.id == '}': 1064d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao indent -= 2 1065d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if not newline: 1066d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(strip_space(buf)) 1067d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Look ahead to determine if it's the end of line. 1068d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if (i + 1 < len(tokens) and 1069d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (tokens[i+1].id == ';' or 1070d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens[i+1].id in ['else', '__attribute__', 1071d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '__attribute', '__packed'] or 1072d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens[i+1].kind == TokenKind.IDENTIFIER)): 1073d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = ' ' * indent + '}' 1074d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = False 1075d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao else: 1076d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(' ' * indent + '}') 1077d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = '' 1078d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = True 1079d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif t.id == ';': 1080d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(strip_space(buf) + ';') 1081d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = '' 1082d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = True 1083d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # We prefer a new line for each constant in enum. 1084d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif t.id == ',' and t.cursor.kind == CursorKind.ENUM_DECL: 1085d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(strip_space(buf) + ',') 1086d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = '' 1087d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = True 1088d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao else: 1089d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if newline: 1090d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf += ' ' * indent + str(t) 1091d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao else: 1092d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf += ' ' + str(t) 1093d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao newline = False 1094d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1095fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1096d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if buf: 1097d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(strip_space(buf)) 1098fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1099d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return result, indent 1100fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1101d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def writeWithWarning(self, out, warning, left_count, repeat_count, indent): 1102d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Dump the current block with warnings.""" 1103fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # removeWhiteSpace() will sometimes creates non-directive blocks 1104fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # without any tokens. These come from blocks that only contained 1105fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # empty lines and spaces. They should not be printed in the final 1106fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # output, and then should not be counted for this operation. 1107fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1108d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.directive is None and not self.tokens: 1109d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return left_count, indent 1110fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1111fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if self.directive: 1112d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao out.write(str(self) + '\n') 1113fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner left_count -= 1 1114fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if left_count == 0: 1115fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner out.write(warning) 1116fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner left_count = repeat_count 1117fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1118fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner else: 1119d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao lines, indent = self.format_blocks(self.tokens, indent) 1120d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for line in lines: 1121d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao out.write(line + '\n') 1122d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao left_count -= 1 1123d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if left_count == 0: 1124d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao out.write(warning) 1125d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao left_count = repeat_count 1126fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1127d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return left_count, indent 1128fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __repr__(self): 1130d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Generate the representation of a given block.""" 11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if self.directive: 11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = "#%s " % self.directive 11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if self.isIf(): 11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += repr(self.expr) 11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for tok in self.tokens: 11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += repr(tok) 11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = "" 11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for tok in self.tokens: 11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += repr(tok) 11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result 11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __str__(self): 1146d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Generate the string representation of a given block.""" 11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if self.directive: 1148d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # "#if" 11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if self.directive == "if": 11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # small optimization to re-generate #ifdef and #ifndef 11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project e = self.expr.expr 11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project op = e[0] 11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if op == "defined": 11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = "#ifdef %s" % e[1] 11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project elif op == "!" and e[1][0] == "defined": 11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = "#ifndef %s" % e[1][1] 11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = "#if " + str(self.expr) 1159d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1160d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # "#define" 1161d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif self.isDefine(): 1162d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = "#%s %s" % (self.directive, self.define_id) 1163d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.tokens: 1164d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result += " " 1165d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao expr = strip_space(' '.join([tok.id for tok in self.tokens])) 1166d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # remove the space between name and '(' in function call 1167d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result += re.sub(r'(\w+) \(', r'\1(', expr) 1168d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1169d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # "#error" 1170d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Concatenating tokens with a space separator, because they may 1171d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # not be quoted and broken into several tokens 1172d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif self.directive == "error": 1173d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = "#error %s" % ' '.join([tok.id for tok in self.tokens]) 1174d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = "#%s" % self.directive 1177d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if self.tokens: 11781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += " " 1179d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result += ''.join([tok.id for tok in self.tokens]) 11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 1181d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao lines, _ = self.format_blocks(self.tokens) 1182d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = '\n'.join(lines) 11831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result 11851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1186d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1187d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass BlockList(object): 1188d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A convenience class used to hold and process a list of blocks. 1189d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1190d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao It calls the cpp parser to get the blocks. 1191d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 1192d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1193d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, blocks): 11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.blocks = blocks 11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __len__(self): 11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return len(self.blocks) 11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1199d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __getitem__(self, n): 12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return self.blocks[n] 12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __repr__(self): 12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return repr(self.blocks) 12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def __str__(self): 1206d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = '\n'.join([str(b) for b in self.blocks]) 12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result 12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1209d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def dump(self): 1210d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Dump all the blocks in current BlockList.""" 1211d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print '##### BEGIN #####' 1212d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for i, b in enumerate(self.blocks): 1213d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print '### BLOCK %d ###' % i 1214d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print b 1215d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print '##### END #####' 1216d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1217d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def optimizeIf01(self): 1218d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Remove the code between #if 0 .. #endif in a BlockList.""" 12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.blocks = optimize_if01(self.blocks) 12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def optimizeMacros(self, macros): 1222d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Remove known defined and undefined macros from a BlockList.""" 12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for b in self.blocks: 12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if b.isIf(): 12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project b.expr.optimize(macros) 12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1227d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def removeMacroDefines(self, macros): 1228d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Remove known macro definitions from a BlockList.""" 1229d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self.blocks = remove_macro_defines(self.blocks, macros) 1230fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1231d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def optimizeAll(self, macros): 12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.optimizeMacros(macros) 12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.optimizeIf01() 12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project def findIncludes(self): 1237d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return the list of included files in a BlockList.""" 12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = [] 12391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for b in self.blocks: 12401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = b.isInclude() 12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if i: 12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result.append(i) 12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result 12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1245d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def write(self, out): 12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project out.write(str(self)) 12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1248d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def writeWithWarning(self, out, warning, repeat_count): 1249fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner left_count = repeat_count 1250d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao indent = 0 1251fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner for b in self.blocks: 1252d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao left_count, indent = b.writeWithWarning(out, warning, left_count, 1253d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao repeat_count, indent) 1254d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1255d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def removeVarsAndFuncs(self, knownStatics=None): 1256d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Remove variable and function declarations. 1257d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1258d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao All extern and static declarations corresponding to variable and 1259d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao function declarations are removed. We only accept typedefs and 1260d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao enum/structs/union declarations. 1261d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1262d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao However, we keep the definitions corresponding to the set of known 1263d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao static inline functions in the set 'knownStatics', which is useful 1264d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for optimized byteorder swap functions and stuff like that. 1265d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 1266d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1267d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # NOTE: It's also removing function-like macros, such as __SYSCALL(...) 1268d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # in uapi/asm-generic/unistd.h, or KEY_FIELD(...) in linux/bcache.h. 1269d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # It could be problematic when we have function-like macros but without 1270d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # '}' following them. It will skip all the tokens/blocks until seeing a 1271d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # '}' as the function end. Fortunately we don't have such cases in the 1272d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # current kernel headers. 1273fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # state = 0 => normal (i.e. LN + spaces) 1275fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # state = 1 => typedef/struct encountered, ends with ";" 1276fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # state = 2 => var declaration encountered, ends with ";" 1277fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # state = 3 => func declaration encountered, ends with "}" 1278d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1279d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if knownStatics is None: 1280d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao knownStatics = set() 1281d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao state = 0 1282d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao depth = 0 1283d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks2 = [] 1284fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner skipTokens = False 12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for b in self.blocks: 12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if b.isDirective(): 12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blocks2.append(b) 12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 1289d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao n = len(b.tokens) 1290d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i = 0 1291fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if skipTokens: 12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project first = n 1293fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner else: 1294fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner first = 0 12951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while i < n: 12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project tok = b.tokens[i] 1297fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner tokid = tok.id 1298fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # If we are not looking for the start of a new 1299fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # type/var/func, then skip over tokens until 1300fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # we find our terminator, managing the depth of 1301fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # accolades as we go. 1302fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if state > 0: 1303fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner terminator = False 1304fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if tokid == '{': 13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth += 1 1306fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner elif tokid == '}': 13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if depth > 0: 13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth -= 1 1309fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if (depth == 0) and (state == 3): 1310fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner terminator = True 1311fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner elif tokid == ';' and depth == 0: 1312fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner terminator = True 13131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1314fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if terminator: 1315fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # we found the terminator 13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project state = 0 1317fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if skipTokens: 1318fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner skipTokens = False 1319d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao first = i + 1 1320fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1321d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1322fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner continue 1323fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1324fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # Is it a new type definition, then start recording it 1325d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if tok.id in ['struct', 'typedef', 'enum', 'union', 1326d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '__extension__']: 1327fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner state = 1 1328d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1329fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner continue 1330fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1331fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # Is it a variable or function definition. If so, first 1332fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # try to determine which type it is, and also extract 1333fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # its name. 1334fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1335fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # We're going to parse the next tokens of the same block 1336fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # until we find a semi-column or a left parenthesis. 1337fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1338fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # The semi-column corresponds to a variable definition, 1339fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # the left-parenthesis to a function definition. 1340fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1341fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # We also assume that the var/func name is the last 1342fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # identifier before the terminator. 1343fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1344d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao j = i + 1 1345fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner ident = "" 1346fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner while j < n: 1347fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner tokid = b.tokens[j].id 1348fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if tokid == '(': # a function declaration 1349fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner state = 3 1350fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner break 1351d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif tokid == ';': # a variable declaration 1352fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner state = 2 1353fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner break 1354d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if b.tokens[j].kind == TokenKind.IDENTIFIER: 1355d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ident = b.tokens[j].id 1356fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner j += 1 13571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1358fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if j >= n: 1359fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # This can only happen when the declaration 1360fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # does not end on the current block (e.g. with 1361fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # a directive mixed inside it. 1362fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1363fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # We will treat it as malformed because 1364fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # it's very hard to recover from this case 1365fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # without making our parser much more 1366fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # complex. 1367fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # 1368d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("### skip unterminated static '%s'", 1369d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ident) 1370fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner break 1371fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1372fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if ident in knownStatics: 1373d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("### keep var/func '%s': %s", ident, 1374d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao repr(b.tokens[i:j])) 1375fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner else: 1376fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner # We're going to skip the tokens for this declaration 1377d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("### skip var/func '%s': %s", ident, 1378d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao repr(b.tokens[i:j])) 1379fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner if i > first: 1380d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks2.append(Block(b.tokens[first:i])) 1381fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner skipTokens = True 1382d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao first = n 1383fc2693110ee8a2ba22a445ad9855fbe9e118d439David 'Digit' Turner 1384d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 13851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if i > first: 1387d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # print "### final '%s'" % repr(b.tokens[first:i]) 1388d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks2.append(Block(b.tokens[first:i])) 13891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 13901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project self.blocks = blocks2 13911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1392d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def replaceTokens(self, replacements): 1393d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Replace tokens according to the given dict.""" 1394d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo for b in self.blocks: 1395fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes made_change = False 1396d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if b.isInclude() is None: 1397d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo for tok in b.tokens: 1398d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if tok.kind == TokenKind.IDENTIFIER: 1399d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if tok.id in replacements: 1400d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tok.id = replacements[tok.id] 1401fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes made_change = True 1402fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes 1403d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if b.isDefine() and b.define_id in replacements: 1404d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao b.define_id = replacements[b.define_id] 1405d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao made_change = True 1406d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1407fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes if made_change and b.isIf(): 1408fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes # Keep 'expr' in sync with 'tokens'. 1409fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes b.expr = CppExpr(b.tokens) 1410d32c8052fc2b2d3c5da344eb673df35d4a5bc052Martin Storsjo 14111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1412d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef strip_space(s): 1413d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Strip out redundant space in a given string.""" 1414d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1415d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # NOTE: It ought to be more clever to not destroy spaces in string tokens. 1416d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao replacements = {' . ': '.', 1417d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ' [': '[', 1418d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '[ ': '[', 1419d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ' ]': ']', 1420d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '( ': '(', 1421d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ' )': ')', 1422d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ' ,': ',', 1423d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '# ': '#', 1424d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ' ;': ';', 1425d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao '~ ': '~', 1426d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ' -> ': '->'} 1427d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = s 1428d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao for r in replacements: 1429d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = result.replace(r, replacements[r]) 1430d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1431d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Remove the space between function name and the parenthesis. 1432d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = re.sub(r'(\w+) \(', r'\1(', result) 1433d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return result 14341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 14351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1436d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baoclass BlockParser(object): 1437d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """A class that converts an input source file into a BlockList object.""" 14381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1439d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def __init__(self, tokzer=None): 1440d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Initialize a block parser. 14411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1442d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao The input source is provided through a Tokenizer object. 1443d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 1444d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._tokzer = tokzer 1445d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._parsed = False 14461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1447d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @property 1448d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def parsed(self): 1449d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self._parsed 14501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1451d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao @staticmethod 1452d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def _short_extent(extent): 1453d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return '%d:%d - %d:%d' % (extent.start.line, extent.start.column, 1454d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao extent.end.line, extent.end.column) 1455d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1456d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def getBlocks(self, tokzer=None): 1457d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return all the blocks parsed.""" 1458d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1459d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def consume_extent(i, tokens, extent=None, detect_change=False): 1460d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return tokens that belong to the given extent. 1461d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1462d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao It parses all the tokens that follow tokens[i], until getting out 1463d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao of the extent. When detect_change is True, it may terminate early 1464d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao when detecting preprocessing directives inside the extent. 1465d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """ 1466d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1467d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = [] 1468d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if extent is None: 1469d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao extent = tokens[i].cursor.extent 1470d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1471d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while i < len(tokens) and tokens[i].location in extent: 1472d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = tokens[i] 1473d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if debugBlockParser: 1474d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print ' ' * 2, t.id, t.kind, t.cursor.kind 1475d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if (detect_change and t.cursor.extent != extent and 1476d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t.cursor.kind == CursorKind.PREPROCESSING_DIRECTIVE): 1477d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao break 1478d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(t) 1479d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1480d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return (i, result) 1481d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1482d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def consume_line(i, tokens): 1483d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Return tokens that follow tokens[i] in the same line.""" 1484d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result = [] 1485d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao line = tokens[i].location.line 1486d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while i < len(tokens) and tokens[i].location.line == line: 1487d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if tokens[i].cursor.kind == CursorKind.PREPROCESSING_DIRECTIVE: 1488d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao break 1489d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao result.append(tokens[i]) 1490d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1491d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return (i, result) 1492d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1493d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if tokzer is None: 1494d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokzer = self._tokzer 1495d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens = tokzer.tokens 1496d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1497d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks = [] 1498d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = [] 1499d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i = 0 1500d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1501d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while i < len(tokens): 1502d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao t = tokens[i] 1503d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursor = t.cursor 1504d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1505d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if debugBlockParser: 1506d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print ("%d: Processing [%s], kind=[%s], cursor=[%s], " 1507d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "extent=[%s]" % (t.location.line, t.spelling, t.kind, 1508d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao cursor.kind, 1509d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._short_extent(cursor.extent))) 1510d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1511d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if cursor.kind == CursorKind.PREPROCESSING_DIRECTIVE: 1512d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if buf: 1513d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(buf)) 1514d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = [] 1515d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1516d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao j = i 1517d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if j + 1 >= len(tokens): 1518d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken("### BAD TOKEN at %s" % (t.location)) 1519d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao directive = tokens[j+1].id 1520d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1521d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if directive == 'define': 1522d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if i+2 >= len(tokens): 1523d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken("### BAD TOKEN at %s" % 1524d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (tokens[i].location)) 1525d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1526d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Skip '#' and 'define'. 1527d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao extent = tokens[i].cursor.extent 1528d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 2 1529d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao id = '' 1530d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # We need to separate the id from the remaining of 1531d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # the line, especially for the function-like macro. 1532d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if (i + 1 < len(tokens) and tokens[i+1].id == '(' and 1533d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (tokens[i].location.column + len(tokens[i].spelling) == 1534d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao tokens[i+1].location.column)): 1535d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao while i < len(tokens): 1536d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao id += tokens[i].id 1537d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if tokens[i].spelling == ')': 1538d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1539d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao break 1540d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1541d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao else: 1542d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao id += tokens[i].id 1543d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Advance to the next token that follows the macro id 1544d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i += 1 1545d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1546d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (i, ret) = consume_extent(i, tokens, extent=extent) 1547d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(ret, directive=directive, 1548d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao lineno=t.location.line, identifier=id)) 1549d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1550d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao else: 1551d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (i, ret) = consume_extent(i, tokens) 1552d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(ret[2:], directive=directive, 1553d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao lineno=t.location.line)) 1554d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1555d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif cursor.kind == CursorKind.INCLUSION_DIRECTIVE: 1556d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if buf: 1557d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(buf)) 1558d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = [] 1559d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao directive = tokens[i+1].id 1560d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (i, ret) = consume_extent(i, tokens) 15611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1562d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(ret[2:], directive=directive, 1563d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao lineno=t.location.line)) 15641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1565d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif cursor.kind == CursorKind.VAR_DECL: 1566d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if buf: 1567d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(buf)) 1568d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = [] 15691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1570d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (i, ret) = consume_extent(i, tokens, detect_change=True) 1571d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf += ret 15721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1573d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif cursor.kind == CursorKind.FUNCTION_DECL: 1574d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if buf: 1575d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(buf)) 1576d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf = [] 1577d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1578d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (i, ret) = consume_extent(i, tokens, detect_change=True) 1579d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf += ret 15801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 15811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project else: 1582d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao (i, ret) = consume_line(i, tokens) 1583d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao buf += ret 15841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1585d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if buf: 1586d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.append(Block(buf)) 15871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1588d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # _parsed=True indicates a successful parsing, although may result an 1589d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # empty BlockList. 1590d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao self._parsed = True 15911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1592d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return BlockList(blocks) 15931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1594d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def parse(self, tokzer): 1595d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.getBlocks(tokzer) 15961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1597d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao def parseFile(self, path): 1598d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao return self.getBlocks(CppFileTokenizer(path)) 15991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 16001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1601d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef test_block_parsing(lines, expected): 1602d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Helper method to test the correctness of BlockParser.parse.""" 1603d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks = BlockParser().parse(CppStringTokenizer('\n'.join(lines))) 16041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if len(blocks) != len(expected): 1605d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken("BlockParser.parse() returned '%s' expecting " 1606d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "'%s'" % (str(blocks), repr(expected))) 16071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for n in range(len(blocks)): 16081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if str(blocks[n]) != expected[n]: 1609d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao raise BadExpectedToken("BlockParser.parse()[%d] is '%s', " 1610d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "expecting '%s'" % (n, str(blocks[n]), 1611d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao expected[n])) 1612d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 16131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 16141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef test_BlockParser(): 1615d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_block_parsing(["#error hello"], ["#error hello"]) 1616d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_block_parsing(["foo", "", "bar"], ["foo bar"]) 1617d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1618d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # We currently cannot handle the following case with libclang properly. 1619d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # Fortunately it doesn't appear in current headers. 1620d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao # test_block_parsing(["foo", " # ", "bar"], ["foo", "bar"]) 1621d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1622d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao test_block_parsing(["foo", 1623d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao " # /* ahah */ if defined(__KERNEL__) /* more */", 1624d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "bar", "#endif"], 1625d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao ["foo", "#ifdef __KERNEL__", "bar", "#endif"]) 1626d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1627d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1628d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 1629d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 1630d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 1631d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### B L O C K L I S T O P T I M I Z A T I O N ##### 1632d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao##### ##### 1633d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 1634d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao################################################################################ 1635d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1636d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1637d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef remove_macro_defines(blocks, excludedMacros=None): 1638d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Remove macro definitions like #define <macroName> ....""" 1639d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if excludedMacros is None: 1640d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao excludedMacros = set() 16411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = [] 16421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for b in blocks: 16431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project macroName = b.isDefine() 1644d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if macroName is None or macroName not in excludedMacros: 16451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result.append(b) 16461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 16471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result 16481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1649d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1650d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef find_matching_endif(blocks, i): 1651d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Traverse the blocks to find out the matching #endif.""" 1652d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao n = len(blocks) 16531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth = 1 16541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while i < n: 16551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if blocks[i].isDirective(): 1656d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao dir_ = blocks[i].directive 1657d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if dir_ in ["if", "ifndef", "ifdef"]: 16581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth += 1 1659d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif depth == 1 and dir_ in ["else", "elif"]: 16601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return i 1661d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif dir_ == "endif": 16621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project depth -= 1 16631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if depth == 0: 16641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return i 16651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i += 1 16661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return i 16671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1668d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1669d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef optimize_if01(blocks): 1670d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Remove the code between #if 0 .. #endif in a list of CppBlocks.""" 16711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = 0 16721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project n = len(blocks) 16731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result = [] 16741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while i < n: 16751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project j = i 16761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project while j < n and not blocks[j].isIf(): 16771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project j += 1 16781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if j > i: 1679d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("appending lines %d to %d", blocks[i].lineno, 1680d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[j-1].lineno) 16811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += blocks[i:j] 16821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if j >= n: 16831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break 16841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project expr = blocks[j].expr 1685d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao r = expr.toInt() 1686d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if r is None: 16871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result.append(blocks[j]) 16881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = j + 1 16891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue 16901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 16911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if r == 0: 16921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # if 0 => skip everything until the corresponding #endif 1693d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao j = find_matching_endif(blocks, j + 1) 16941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if j >= n: 16951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # unterminated #if 0, finish here 16961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break 1697d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao dir_ = blocks[j].directive 1698d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if dir_ == "endif": 1699d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("remove 'if 0' .. 'endif' (lines %d to %d)", 1700d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[i].lineno, blocks[j].lineno) 17011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = j + 1 1702d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif dir_ == "else": 17031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # convert 'else' into 'if 1' 1704d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("convert 'if 0' .. 'else' into 'if 1' (lines %d " 1705d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao "to %d)", blocks[i].lineno, blocks[j-1].lineno) 17061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blocks[j].directive = "if" 1707d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[j].expr = CppExpr(CppStringTokenizer("1").tokens) 17081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = j 1709d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif dir_ == "elif": 17101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # convert 'elif' into 'if' 1711dc1fb7000adb77c647f70428fd6ce224e3938220Elliott Hughes logging.debug("convert 'if 0' .. 'elif' into 'if'") 17121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blocks[j].directive = "if" 17131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = j 17141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue 17151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 17161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # if 1 => find corresponding endif and remove/transform them 1717d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao k = find_matching_endif(blocks, j + 1) 17181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if k >= n: 17191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # unterminated #if 1, finish here 1720dc1fb7000adb77c647f70428fd6ce224e3938220Elliott Hughes logging.debug("unterminated 'if 1'") 17211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += blocks[j+1:k] 17221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break 17231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1724d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao dir_ = blocks[k].directive 1725d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao if dir_ == "endif": 1726d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("convert 'if 1' .. 'endif' (lines %d to %d)", 1727d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[j].lineno, blocks[k].lineno) 17281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += optimize_if01(blocks[j+1:k]) 1729d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao i = k + 1 1730d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif dir_ == "else": 17311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # convert 'else' into 'if 0' 1732d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("convert 'if 1' .. 'else' (lines %d to %d)", 1733d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[j].lineno, blocks[k].lineno) 17341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += optimize_if01(blocks[j+1:k]) 17351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project blocks[k].directive = "if" 1736d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[k].expr = CppExpr(CppStringTokenizer("0").tokens) 17371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = k 1738d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao elif dir_ == "elif": 17391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project # convert 'elif' into 'if 0' 1740d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao logging.debug("convert 'if 1' .. 'elif' (lines %d to %d)", 1741d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[j].lineno, blocks[k].lineno) 17421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project result += optimize_if01(blocks[j+1:k]) 1743d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks[k].expr = CppExpr(CppStringTokenizer("0").tokens) 17441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project i = k 17451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return result 17461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1747d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 1748d7db594b8d1dab36b711bd887a9dd21675c87243Tao Baodef test_optimizeAll(): 17491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project text = """\ 17501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 1 17511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_1 17521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 17531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 17541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BAD_2 17551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BAD_3 17561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 17571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 17581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 1 17591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_2 17601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 17611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BAD_4 17621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 17631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 17641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 17651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BAD_5 17661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else 17671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_3 17681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 17691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 177040596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#if defined(__KERNEL__) 177140596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#define BAD_KERNEL 177240596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#endif 177340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 177440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) 177540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#define X 177640596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#endif 177740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes 1778fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes#ifndef SIGRTMAX 1779fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes#define SIGRTMAX 123 1780fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes#endif /* SIGRTMAX */ 1781fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes 17821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0 17831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 1 17841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BAD_6 17851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif 17861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif\ 17871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project""" 17881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 17891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project expected = """\ 17901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_1 17911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_2 17921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GOOD_3 179340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#if !defined(__GLIBC__) || __GLIBC__ < 2 179440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#define X 179540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes#endif 1796fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes#ifndef __SIGRTMAX 1797fddbafdc0a63a1b4c5e9252719a913197a4eecfaElliott Hughes#define __SIGRTMAX 123 1798d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao#endif\ 17991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project""" 18001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1801d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao out = utils.StringOutput() 1802d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks = BlockParser().parse(CppStringTokenizer(text)) 1803d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.replaceTokens(kernel_token_replacements) 1804d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.optimizeAll({"__KERNEL__": kCppUndefinedMacro}) 1805d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao blocks.write(out) 18061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if out.get() != expected: 180740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes print "[FAIL]: macro optimization failed\n" 18081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project print "<<<< expecting '", 18091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project print expected, 1810d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao print "'\n>>>> result '", 18111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project print out.get(), 18121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project print "'\n----" 181340596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes global failure_count 181440596aa0054bcfa76148f55321bf4b979e2242beElliott Hughes failure_count += 1 18151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 18171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdef runUnitTests(): 1818d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao """Always run all unit tests for this program.""" 18191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project test_CppTokenizer() 18201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project test_CppExpr() 18211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project test_optimizeAll() 18221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project test_BlockParser() 18231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1824d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao 182540596aa0054bcfa76148f55321bf4b979e2242beElliott Hughesfailure_count = 0 182640596aa0054bcfa76148f55321bf4b979e2242beElliott HughesrunUnitTests() 182740596aa0054bcfa76148f55321bf4b979e2242beElliott Hughesif failure_count != 0: 1828d7db594b8d1dab36b711bd887a9dd21675c87243Tao Bao utils.panic("Unit tests failed in cpp.py.\n") 1829