Package SCons :: Module cpp
[hide private]
[frames] | no frames]

Source Code for Module SCons.cpp

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