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

Source Code for Module SCons.cpp

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