OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S
Cons Foundation |
| 3 # |
| 4 # Permission is hereby granted, free of charge, to any person obtaining |
| 5 # a copy of this software and associated documentation files (the |
| 6 # "Software"), to deal in the Software without restriction, including |
| 7 # without limitation the rights to use, copy, modify, merge, publish, |
| 8 # distribute, sublicense, and/or sell copies of the Software, and to |
| 9 # permit persons to whom the Software is furnished to do so, subject to |
| 10 # the following conditions: |
| 11 # |
| 12 # The above copyright notice and this permission notice shall be included |
| 13 # in all copies or substantial portions of the Software. |
| 14 # |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 22 # |
| 23 |
| 24 __revision__ = "src/engine/SCons/cpp.py 5134 2010/08/16 23:02:40 bdeegan" |
| 25 |
| 26 __doc__ = """ |
| 27 SCons C Pre-Processor module |
| 28 """ |
| 29 #TODO 2.3 and before has no sorted() |
| 30 import SCons.compat |
| 31 |
| 32 import os |
| 33 import re |
| 34 |
| 35 # |
| 36 # First "subsystem" of regular expressions that we set up: |
| 37 # |
| 38 # Stuff to turn the C preprocessor directives in a file's contents into |
| 39 # a list of tuples that we can process easily. |
| 40 # |
| 41 |
| 42 # A table of regular expressions that fetch the arguments from the rest of |
| 43 # a C preprocessor line. Different directives have different arguments |
| 44 # that we want to fetch, using the regular expressions to which the lists |
| 45 # of preprocessor directives map. |
| 46 cpp_lines_dict = { |
| 47 # Fetch the rest of a #if/#elif/#ifdef/#ifndef as one argument, |
| 48 # separated from the keyword by white space. |
| 49 ('if', 'elif', 'ifdef', 'ifndef',) |
| 50 : '\s+(.+)', |
| 51 |
| 52 # Fetch the rest of a #import/#include/#include_next line as one |
| 53 # argument, with white space optional. |
| 54 ('import', 'include', 'include_next',) |
| 55 : '\s*(.+)', |
| 56 |
| 57 # We don't care what comes after a #else or #endif line. |
| 58 ('else', 'endif',) : '', |
| 59 |
| 60 # Fetch three arguments from a #define line: |
| 61 # 1) The #defined keyword. |
| 62 # 2) The optional parentheses and arguments (if it's a function-like |
| 63 # macro, '' if it's not). |
| 64 # 3) The expansion value. |
| 65 ('define',) : '\s+([_A-Za-z][_A-Za-z0-9_]*)(\([^)]*\))?\s*(.*)', |
| 66 |
| 67 # Fetch the #undefed keyword from a #undef line. |
| 68 ('undef',) : '\s+([_A-Za-z][A-Za-z0-9_]*)', |
| 69 } |
| 70 |
| 71 # Create a table that maps each individual C preprocessor directive to |
| 72 # the corresponding compiled regular expression that fetches the arguments |
| 73 # we care about. |
| 74 Table = {} |
| 75 for op_list, expr in cpp_lines_dict.items(): |
| 76 e = re.compile(expr) |
| 77 for op in op_list: |
| 78 Table[op] = e |
| 79 del e |
| 80 del op |
| 81 del op_list |
| 82 |
| 83 # Create a list of the expressions we'll use to match all of the |
| 84 # preprocessor directives. These are the same as the directives |
| 85 # themselves *except* that we must use a negative lookahead assertion |
| 86 # when matching "if" so it doesn't match the "if" in "ifdef." |
| 87 override = { |
| 88 'if' : 'if(?!def)', |
| 89 } |
| 90 l = [override.get(x, x) for x in Table.keys()] |
| 91 |
| 92 |
| 93 # Turn the list of expressions into one big honkin' regular expression |
| 94 # that will match all the preprocessor lines at once. This will return |
| 95 # a list of tuples, one for each preprocessor line. The preprocessor |
| 96 # directive will be the first element in each tuple, and the rest of |
| 97 # the line will be the second element. |
| 98 e = '^\s*#\s*(' + '|'.join(l) + ')(.*)$' |
| 99 |
| 100 # And last but not least, compile the expression. |
| 101 CPP_Expression = re.compile(e, re.M) |
| 102 |
| 103 |
| 104 |
| 105 |
| 106 # |
| 107 # Second "subsystem" of regular expressions that we set up: |
| 108 # |
| 109 # Stuff to translate a C preprocessor expression (as found on a #if or |
| 110 # #elif line) into an equivalent Python expression that we can eval(). |
| 111 # |
| 112 |
| 113 # A dictionary that maps the C representation of Boolean operators |
| 114 # to their Python equivalents. |
| 115 CPP_to_Python_Ops_Dict = { |
| 116 '!' : ' not ', |
| 117 '!=' : ' != ', |
| 118 '&&' : ' and ', |
| 119 '||' : ' or ', |
| 120 '?' : ' and ', |
| 121 ':' : ' or ', |
| 122 '\r' : '', |
| 123 } |
| 124 |
| 125 CPP_to_Python_Ops_Sub = lambda m: CPP_to_Python_Ops_Dict[m.group(0)] |
| 126 |
| 127 # We have to sort the keys by length so that longer expressions |
| 128 # come *before* shorter expressions--in particular, "!=" must |
| 129 # come before "!" in the alternation. Without this, the Python |
| 130 # re module, as late as version 2.2.2, empirically matches the |
| 131 # "!" in "!=" first, instead of finding the longest match. |
| 132 # What's up with that? |
| 133 l = sorted(CPP_to_Python_Ops_Dict.keys(), key=lambda a: len(a), reverse=True) |
| 134 |
| 135 # Turn the list of keys into one regular expression that will allow us |
| 136 # to substitute all of the operators at once. |
| 137 expr = '|'.join(map(re.escape, l)) |
| 138 |
| 139 # ...and compile the expression. |
| 140 CPP_to_Python_Ops_Expression = re.compile(expr) |
| 141 |
| 142 # A separate list of expressions to be evaluated and substituted |
| 143 # sequentially, not all at once. |
| 144 CPP_to_Python_Eval_List = [ |
| 145 ['defined\s+(\w+)', '"\\1" in __dict__'], |
| 146 ['defined\s*\((\w+)\)', '"\\1" in __dict__'], |
| 147 ['/\*.*\*/', ''], |
| 148 ['/\*.*', ''], |
| 149 ['//.*', ''], |
| 150 ['(0x[0-9A-Fa-f]*)[UL]+', '\\1'], |
| 151 ] |
| 152 |
| 153 # Replace the string representations of the regular expressions in the |
| 154 # list with compiled versions. |
| 155 for l in CPP_to_Python_Eval_List: |
| 156 l[0] = re.compile(l[0]) |
| 157 |
| 158 # Wrap up all of the above into a handy function. |
| 159 def CPP_to_Python(s): |
| 160 """ |
| 161 Converts a C pre-processor expression into an equivalent |
| 162 Python expression that can be evaluated. |
| 163 """ |
| 164 s = CPP_to_Python_Ops_Expression.sub(CPP_to_Python_Ops_Sub, s) |
| 165 for expr, repl in CPP_to_Python_Eval_List: |
| 166 s = expr.sub(repl, s) |
| 167 return s |
| 168 |
| 169 |
| 170 |
| 171 del expr |
| 172 del l |
| 173 del override |
| 174 |
| 175 |
| 176 |
| 177 class FunctionEvaluator(object): |
| 178 """ |
| 179 Handles delayed evaluation of a #define function call. |
| 180 """ |
| 181 def __init__(self, name, args, expansion): |
| 182 """ |
| 183 Squirrels away the arguments and expansion value of a #define |
| 184 macro function for later evaluation when we must actually expand |
| 185 a value that uses it. |
| 186 """ |
| 187 self.name = name |
| 188 self.args = function_arg_separator.split(args) |
| 189 try: |
| 190 expansion = expansion.split('##') |
| 191 except AttributeError: |
| 192 pass |
| 193 self.expansion = expansion |
| 194 def __call__(self, *values): |
| 195 """ |
| 196 Evaluates the expansion of a #define macro function called |
| 197 with the specified values. |
| 198 """ |
| 199 if len(self.args) != len(values): |
| 200 raise ValueError("Incorrect number of arguments to `%s'" % self.name
) |
| 201 # Create a dictionary that maps the macro arguments to the |
| 202 # corresponding values in this "call." We'll use this when we |
| 203 # eval() the expansion so that arguments will get expanded to |
| 204 # the right values. |
| 205 locals = {} |
| 206 for k, v in zip(self.args, values): |
| 207 locals[k] = v |
| 208 |
| 209 parts = [] |
| 210 for s in self.expansion: |
| 211 if not s in self.args: |
| 212 s = repr(s) |
| 213 parts.append(s) |
| 214 statement = ' + '.join(parts) |
| 215 |
| 216 return eval(statement, globals(), locals) |
| 217 |
| 218 |
| 219 |
| 220 # Find line continuations. |
| 221 line_continuations = re.compile('\\\\\r?\n') |
| 222 |
| 223 # Search for a "function call" macro on an expansion. Returns the |
| 224 # two-tuple of the "function" name itself, and a string containing the |
| 225 # arguments within the call parentheses. |
| 226 function_name = re.compile('(\S+)\(([^)]*)\)') |
| 227 |
| 228 # Split a string containing comma-separated function call arguments into |
| 229 # the separate arguments. |
| 230 function_arg_separator = re.compile(',\s*') |
| 231 |
| 232 |
| 233 |
| 234 class PreProcessor(object): |
| 235 """ |
| 236 The main workhorse class for handling C pre-processing. |
| 237 """ |
| 238 def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0): |
| 239 global Table |
| 240 |
| 241 cpppath = tuple(cpppath) |
| 242 |
| 243 self.searchpath = { |
| 244 '"' : (current,) + cpppath, |
| 245 '<' : cpppath + (current,), |
| 246 } |
| 247 |
| 248 # Initialize our C preprocessor namespace for tracking the |
| 249 # values of #defined keywords. We use this namespace to look |
| 250 # for keywords on #ifdef/#ifndef lines, and to eval() the |
| 251 # expressions on #if/#elif lines (after massaging them from C to |
| 252 # Python). |
| 253 self.cpp_namespace = dict.copy() |
| 254 self.cpp_namespace['__dict__'] = self.cpp_namespace |
| 255 |
| 256 if all: |
| 257 self.do_include = self.all_include |
| 258 |
| 259 # For efficiency, a dispatch table maps each C preprocessor |
| 260 # directive (#if, #define, etc.) to the method that should be |
| 261 # called when we see it. We accomodate state changes (#if, |
| 262 # #ifdef, #ifndef) by pushing the current dispatch table on a |
| 263 # stack and changing what method gets called for each relevant |
| 264 # directive we might see next at this level (#else, #elif). |
| 265 # #endif will simply pop the stack. |
| 266 d = { |
| 267 'scons_current_file' : self.scons_current_file |
| 268 } |
| 269 for op in Table.keys(): |
| 270 d[op] = getattr(self, 'do_' + op) |
| 271 self.default_table = d |
| 272 |
| 273 # Controlling methods. |
| 274 |
| 275 def tupleize(self, contents): |
| 276 """ |
| 277 Turns the contents of a file into a list of easily-processed |
| 278 tuples describing the CPP lines in the file. |
| 279 |
| 280 The first element of each tuple is the line's preprocessor |
| 281 directive (#if, #include, #define, etc., minus the initial '#'). |
| 282 The remaining elements are specific to the type of directive, as |
| 283 pulled apart by the regular expression. |
| 284 """ |
| 285 global CPP_Expression, Table |
| 286 contents = line_continuations.sub('', contents) |
| 287 cpp_tuples = CPP_Expression.findall(contents) |
| 288 return [(m[0],) + Table[m[0]].match(m[1]).groups() for m in cpp_tuples] |
| 289 |
| 290 def __call__(self, file): |
| 291 """ |
| 292 Pre-processes a file. |
| 293 |
| 294 This is the main public entry point. |
| 295 """ |
| 296 self.current_file = file |
| 297 return self.process_contents(self.read_file(file), file) |
| 298 |
| 299 def process_contents(self, contents, fname=None): |
| 300 """ |
| 301 Pre-processes a file contents. |
| 302 |
| 303 This is the main internal entry point. |
| 304 """ |
| 305 self.stack = [] |
| 306 self.dispatch_table = self.default_table.copy() |
| 307 self.current_file = fname |
| 308 self.tuples = self.tupleize(contents) |
| 309 |
| 310 self.initialize_result(fname) |
| 311 while self.tuples: |
| 312 t = self.tuples.pop(0) |
| 313 # Uncomment to see the list of tuples being processed (e.g., |
| 314 # to validate the CPP lines are being translated correctly). |
| 315 #print t |
| 316 self.dispatch_table[t[0]](t) |
| 317 return self.finalize_result(fname) |
| 318 |
| 319 # Dispatch table stack manipulation methods. |
| 320 |
| 321 def save(self): |
| 322 """ |
| 323 Pushes the current dispatch table on the stack and re-initializes |
| 324 the current dispatch table to the default. |
| 325 """ |
| 326 self.stack.append(self.dispatch_table) |
| 327 self.dispatch_table = self.default_table.copy() |
| 328 |
| 329 def restore(self): |
| 330 """ |
| 331 Pops the previous dispatch table off the stack and makes it the |
| 332 current one. |
| 333 """ |
| 334 try: self.dispatch_table = self.stack.pop() |
| 335 except IndexError: pass |
| 336 |
| 337 # Utility methods. |
| 338 |
| 339 def do_nothing(self, t): |
| 340 """ |
| 341 Null method for when we explicitly want the action for a |
| 342 specific preprocessor directive to do nothing. |
| 343 """ |
| 344 pass |
| 345 |
| 346 def scons_current_file(self, t): |
| 347 self.current_file = t[1] |
| 348 |
| 349 def eval_expression(self, t): |
| 350 """ |
| 351 Evaluates a C preprocessor expression. |
| 352 |
| 353 This is done by converting it to a Python equivalent and |
| 354 eval()ing it in the C preprocessor namespace we use to |
| 355 track #define values. |
| 356 """ |
| 357 t = CPP_to_Python(' '.join(t[1:])) |
| 358 try: return eval(t, self.cpp_namespace) |
| 359 except (NameError, TypeError): return 0 |
| 360 |
| 361 def initialize_result(self, fname): |
| 362 self.result = [fname] |
| 363 |
| 364 def finalize_result(self, fname): |
| 365 return self.result[1:] |
| 366 |
| 367 def find_include_file(self, t): |
| 368 """ |
| 369 Finds the #include file for a given preprocessor tuple. |
| 370 """ |
| 371 fname = t[2] |
| 372 for d in self.searchpath[t[1]]: |
| 373 if d == os.curdir: |
| 374 f = fname |
| 375 else: |
| 376 f = os.path.join(d, fname) |
| 377 if os.path.isfile(f): |
| 378 return f |
| 379 return None |
| 380 |
| 381 def read_file(self, file): |
| 382 return open(file).read() |
| 383 |
| 384 # Start and stop processing include lines. |
| 385 |
| 386 def start_handling_includes(self, t=None): |
| 387 """ |
| 388 Causes the PreProcessor object to start processing #import, |
| 389 #include and #include_next lines. |
| 390 |
| 391 This method will be called when a #if, #ifdef, #ifndef or #elif |
| 392 evaluates True, or when we reach the #else in a #if, #ifdef, |
| 393 #ifndef or #elif block where a condition already evaluated |
| 394 False. |
| 395 |
| 396 """ |
| 397 d = self.dispatch_table |
| 398 d['import'] = self.do_import |
| 399 d['include'] = self.do_include |
| 400 d['include_next'] = self.do_include |
| 401 |
| 402 def stop_handling_includes(self, t=None): |
| 403 """ |
| 404 Causes the PreProcessor object to stop processing #import, |
| 405 #include and #include_next lines. |
| 406 |
| 407 This method will be called when a #if, #ifdef, #ifndef or #elif |
| 408 evaluates False, or when we reach the #else in a #if, #ifdef, |
| 409 #ifndef or #elif block where a condition already evaluated True. |
| 410 """ |
| 411 d = self.dispatch_table |
| 412 d['import'] = self.do_nothing |
| 413 d['include'] = self.do_nothing |
| 414 d['include_next'] = self.do_nothing |
| 415 |
| 416 # Default methods for handling all of the preprocessor directives. |
| 417 # (Note that what actually gets called for a given directive at any |
| 418 # point in time is really controlled by the dispatch_table.) |
| 419 |
| 420 def _do_if_else_condition(self, condition): |
| 421 """ |
| 422 Common logic for evaluating the conditions on #if, #ifdef and |
| 423 #ifndef lines. |
| 424 """ |
| 425 self.save() |
| 426 d = self.dispatch_table |
| 427 if condition: |
| 428 self.start_handling_includes() |
| 429 d['elif'] = self.stop_handling_includes |
| 430 d['else'] = self.stop_handling_includes |
| 431 else: |
| 432 self.stop_handling_includes() |
| 433 d['elif'] = self.do_elif |
| 434 d['else'] = self.start_handling_includes |
| 435 |
| 436 def do_ifdef(self, t): |
| 437 """ |
| 438 Default handling of a #ifdef line. |
| 439 """ |
| 440 self._do_if_else_condition(t[1] in self.cpp_namespace) |
| 441 |
| 442 def do_ifndef(self, t): |
| 443 """ |
| 444 Default handling of a #ifndef line. |
| 445 """ |
| 446 self._do_if_else_condition(t[1] not in self.cpp_namespace) |
| 447 |
| 448 def do_if(self, t): |
| 449 """ |
| 450 Default handling of a #if line. |
| 451 """ |
| 452 self._do_if_else_condition(self.eval_expression(t)) |
| 453 |
| 454 def do_elif(self, t): |
| 455 """ |
| 456 Default handling of a #elif line. |
| 457 """ |
| 458 d = self.dispatch_table |
| 459 if self.eval_expression(t): |
| 460 self.start_handling_includes() |
| 461 d['elif'] = self.stop_handling_includes |
| 462 d['else'] = self.stop_handling_includes |
| 463 |
| 464 def do_else(self, t): |
| 465 """ |
| 466 Default handling of a #else line. |
| 467 """ |
| 468 pass |
| 469 |
| 470 def do_endif(self, t): |
| 471 """ |
| 472 Default handling of a #endif line. |
| 473 """ |
| 474 self.restore() |
| 475 |
| 476 def do_define(self, t): |
| 477 """ |
| 478 Default handling of a #define line. |
| 479 """ |
| 480 _, name, args, expansion = t |
| 481 try: |
| 482 expansion = int(expansion) |
| 483 except (TypeError, ValueError): |
| 484 pass |
| 485 if args: |
| 486 evaluator = FunctionEvaluator(name, args[1:-1], expansion) |
| 487 self.cpp_namespace[name] = evaluator |
| 488 else: |
| 489 self.cpp_namespace[name] = expansion |
| 490 |
| 491 def do_undef(self, t): |
| 492 """ |
| 493 Default handling of a #undef line. |
| 494 """ |
| 495 try: del self.cpp_namespace[t[1]] |
| 496 except KeyError: pass |
| 497 |
| 498 def do_import(self, t): |
| 499 """ |
| 500 Default handling of a #import line. |
| 501 """ |
| 502 # XXX finish this -- maybe borrow/share logic from do_include()...? |
| 503 pass |
| 504 |
| 505 def do_include(self, t): |
| 506 """ |
| 507 Default handling of a #include line. |
| 508 """ |
| 509 t = self.resolve_include(t) |
| 510 include_file = self.find_include_file(t) |
| 511 if include_file: |
| 512 #print "include_file =", include_file |
| 513 self.result.append(include_file) |
| 514 contents = self.read_file(include_file) |
| 515 new_tuples = [('scons_current_file', include_file)] + \ |
| 516 self.tupleize(contents) + \ |
| 517 [('scons_current_file', self.current_file)] |
| 518 self.tuples[:] = new_tuples + self.tuples |
| 519 |
| 520 # Date: Tue, 22 Nov 2005 20:26:09 -0500 |
| 521 # From: Stefan Seefeld <seefeld@sympatico.ca> |
| 522 # |
| 523 # By the way, #include_next is not the same as #include. The difference |
| 524 # being that #include_next starts its search in the path following the |
| 525 # path that let to the including file. In other words, if your system |
| 526 # include paths are ['/foo', '/bar'], and you are looking at a header |
| 527 # '/foo/baz.h', it might issue an '#include_next <baz.h>' which would |
| 528 # correctly resolve to '/bar/baz.h' (if that exists), but *not* see |
| 529 # '/foo/baz.h' again. See http://www.delorie.com/gnu/docs/gcc/cpp_11.html |
| 530 # for more reasoning. |
| 531 # |
| 532 # I have no idea in what context 'import' might be used. |
| 533 |
| 534 # XXX is #include_next really the same as #include ? |
| 535 do_include_next = do_include |
| 536 |
| 537 # Utility methods for handling resolution of include files. |
| 538 |
| 539 def resolve_include(self, t): |
| 540 """Resolve a tuple-ized #include line. |
| 541 |
| 542 This handles recursive expansion of values without "" or <> |
| 543 surrounding the name until an initial " or < is found, to handle |
| 544 #include FILE |
| 545 where FILE is a #define somewhere else. |
| 546 """ |
| 547 s = t[1] |
| 548 while not s[0] in '<"': |
| 549 #print "s =", s |
| 550 try: |
| 551 s = self.cpp_namespace[s] |
| 552 except KeyError: |
| 553 m = function_name.search(s) |
| 554 s = self.cpp_namespace[m.group(1)] |
| 555 if callable(s): |
| 556 args = function_arg_separator.split(m.group(2)) |
| 557 s = s(*args) |
| 558 if not s: |
| 559 return None |
| 560 return (t[0], s[0], s[1:-1]) |
| 561 |
| 562 def all_include(self, t): |
| 563 """ |
| 564 """ |
| 565 self.result.append(self.resolve_include(t)) |
| 566 |
| 567 class DumbPreProcessor(PreProcessor): |
| 568 """A preprocessor that ignores all #if/#elif/#else/#endif directives |
| 569 and just reports back *all* of the #include files (like the classic |
| 570 SCons scanner did). |
| 571 |
| 572 This is functionally equivalent to using a regular expression to |
| 573 find all of the #include lines, only slower. It exists mainly as |
| 574 an example of how the main PreProcessor class can be sub-classed |
| 575 to tailor its behavior. |
| 576 """ |
| 577 def __init__(self, *args, **kw): |
| 578 PreProcessor.__init__(self, *args, **kw) |
| 579 d = self.default_table |
| 580 for func in ['if', 'elif', 'else', 'endif', 'ifdef', 'ifndef']: |
| 581 d[func] = d[func] = self.do_nothing |
| 582 |
| 583 del __revision__ |
| 584 |
| 585 # Local Variables: |
| 586 # tab-width:4 |
| 587 # indent-tabs-mode:nil |
| 588 # End: |
| 589 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |