2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
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:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
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.
24 __revision__ = "src/engine/SCons/cpp.py 3842 2008/12/20 22:59:52 scons"
27 SCons C Pre-Processor module
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.
40 # First "subsystem" of regular expressions that we set up:
42 # Stuff to turn the C preprocessor directives in a file's contents into
43 # a list of tuples that we can process easily.
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.
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',)
56 # Fetch the rest of a #import/#include/#include_next line as one
57 # argument, with white space optional.
58 ('import', 'include', 'include_next',)
61 # We don't care what comes after a #else or #endif line.
62 ('else', 'endif',) : '',
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*(.*)',
71 # Fetch the #undefed keyword from a #undef line.
72 ('undef',) : '\s+([_A-Za-z][A-Za-z0-9_]+)',
75 # Create a table that maps each individual C preprocessor directive to
76 # the corresponding compiled regular expression that fetches the arguments
79 for op_list, expr in cpp_lines_dict.items():
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."
94 l = map(lambda x, o=override: o.get(x, x), Table.keys())
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, '|') + ')(.*)$'
104 # And last but not least, compile the expression.
105 CPP_Expression = re.compile(e, re.M)
111 # Second "subsystem" of regular expressions that we set up:
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().
117 # A dictionary that maps the C representation of Boolean operators
118 # to their Python equivalents.
119 CPP_to_Python_Ops_Dict = {
129 CPP_to_Python_Ops_Sub = lambda m, d=CPP_to_Python_Ops_Dict: d[m.group(0)]
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)))
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), '|')
144 # ...and compile the expression.
145 CPP_to_Python_Ops_Expression = re.compile(expr)
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")'],
155 ['(0x[0-9A-Fa-f]*)[UL]+', '\\1L'],
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])
163 # Wrap up all of the above into a handy function.
164 def CPP_to_Python(s):
166 Converts a C pre-processor expression into an equivalent
167 Python expression that can be evaluated.
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)
182 class FunctionEvaluator:
184 Handles delayed evaluation of a #define function call.
186 def __init__(self, name, args, expansion):
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.
193 self.args = function_arg_separator.split(args)
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.
200 self.expansion = expansion
201 def __call__(self, *values):
203 Evaluates the expansion of a #define macro function called
204 with the specified values.
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
213 for k, v in zip(self.args, values):
217 for s in self.expansion:
218 if not s in self.args:
221 statement = string.join(parts, ' + ')
223 return eval(statement, globals(), locals)
227 # Find line continuations.
228 line_continuations = re.compile('\\\\\r?\n')
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+)\(([^)]*)\)')
235 # Split a string containing comma-separated function call arguments into
236 # the separate arguments.
237 function_arg_separator = re.compile(',\s*')
243 The main workhorse class for handling C pre-processing.
245 def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0):
248 cpppath = tuple(cpppath)
251 '"' : (current,) + cpppath,
252 '<' : cpppath + (current,),
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
260 self.cpp_namespace = dict.copy()
261 self.cpp_namespace['__dict__'] = self.cpp_namespace
264 self.do_include = self.all_include
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.
274 'scons_current_file' : self.scons_current_file
276 for op in Table.keys():
277 d[op] = getattr(self, 'do_' + op)
278 self.default_table = d
280 # Controlling methods.
282 def tupleize(self, contents):
284 Turns the contents of a file into a list of easily-processed
285 tuples describing the CPP lines in the file.
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.
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(),
299 def __call__(self, file):
301 Pre-processes a file.
303 This is the main public entry point.
305 self.current_file = file
306 return self.process_contents(self.read_file(file), file)
308 def process_contents(self, contents, fname=None):
310 Pre-processes a file contents.
312 This is the main internal entry point.
315 self.dispatch_table = self.default_table.copy()
316 self.current_file = fname
317 self.tuples = self.tupleize(contents)
319 self.initialize_result(fname)
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).
325 self.dispatch_table[t[0]](t)
326 return self.finalize_result(fname)
328 # Dispatch table stack manipulation methods.
332 Pushes the current dispatch table on the stack and re-initializes
333 the current dispatch table to the default.
335 self.stack.append(self.dispatch_table)
336 self.dispatch_table = self.default_table.copy()
340 Pops the previous dispatch table off the stack and makes it the
343 try: self.dispatch_table = self.stack.pop()
344 except IndexError: pass
348 def do_nothing(self, t):
350 Null method for when we explicitly want the action for a
351 specific preprocessor directive to do nothing.
355 def scons_current_file(self, t):
356 self.current_file = t[1]
358 def eval_expression(self, t):
360 Evaluates a C preprocessor expression.
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.
366 t = CPP_to_Python(string.join(t[1:]))
367 try: return eval(t, self.cpp_namespace)
368 except (NameError, TypeError): return 0
370 def initialize_result(self, fname):
371 self.result = [fname]
373 def finalize_result(self, fname):
374 return self.result[1:]
376 def find_include_file(self, t):
378 Finds the #include file for a given preprocessor tuple.
381 for d in self.searchpath[t[1]]:
385 f = os.path.join(d, fname)
386 if os.path.isfile(f):
390 def read_file(self, file):
391 return open(file).read()
393 # Start and stop processing include lines.
395 def start_handling_includes(self, t=None):
397 Causes the PreProcessor object to start processing #import,
398 #include and #include_next lines.
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
406 d = self.dispatch_table
407 d['import'] = self.do_import
408 d['include'] = self.do_include
409 d['include_next'] = self.do_include
411 def stop_handling_includes(self, t=None):
413 Causes the PreProcessor object to stop processing #import,
414 #include and #include_next lines.
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.
420 d = self.dispatch_table
421 d['import'] = self.do_nothing
422 d['include'] = self.do_nothing
423 d['include_next'] = self.do_nothing
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.)
429 def _do_if_else_condition(self, condition):
431 Common logic for evaluating the conditions on #if, #ifdef and
435 d = self.dispatch_table
437 self.start_handling_includes()
438 d['elif'] = self.stop_handling_includes
439 d['else'] = self.stop_handling_includes
441 self.stop_handling_includes()
442 d['elif'] = self.do_elif
443 d['else'] = self.start_handling_includes
445 def do_ifdef(self, t):
447 Default handling of a #ifdef line.
449 self._do_if_else_condition(self.cpp_namespace.has_key(t[1]))
451 def do_ifndef(self, t):
453 Default handling of a #ifndef line.
455 self._do_if_else_condition(not self.cpp_namespace.has_key(t[1]))
459 Default handling of a #if line.
461 self._do_if_else_condition(self.eval_expression(t))
463 def do_elif(self, t):
465 Default handling of a #elif line.
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
473 def do_else(self, t):
475 Default handling of a #else line.
479 def do_endif(self, t):
481 Default handling of a #endif line.
485 def do_define(self, t):
487 Default handling of a #define line.
489 _, name, args, expansion = t
491 expansion = int(expansion)
492 except (TypeError, ValueError):
495 evaluator = FunctionEvaluator(name, args[1:-1], expansion)
496 self.cpp_namespace[name] = evaluator
498 self.cpp_namespace[name] = expansion
500 def do_undef(self, t):
502 Default handling of a #undef line.
504 try: del self.cpp_namespace[t[1]]
505 except KeyError: pass
507 def do_import(self, t):
509 Default handling of a #import line.
511 # XXX finish this -- maybe borrow/share logic from do_include()...?
514 def do_include(self, t):
516 Default handling of a #include line.
518 t = self.resolve_include(t)
519 include_file = self.find_include_file(t)
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
529 # Date: Tue, 22 Nov 2005 20:26:09 -0500
530 # From: Stefan Seefeld <seefeld@sympatico.ca>
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.
541 # I have no idea in what context 'import' might be used.
543 # XXX is #include_next really the same as #include ?
544 do_include_next = do_include
546 # Utility methods for handling resolution of include files.
548 def resolve_include(self, t):
549 """Resolve a tuple-ized #include line.
551 This handles recursive expansion of values without "" or <>
552 surrounding the name until an initial " or < is found, to handle
554 where FILE is a #define somewhere else.
557 while not s[0] in '<"':
560 s = self.cpp_namespace[s]
562 m = function_name.search(s)
563 s = self.cpp_namespace[m.group(1)]
565 args = function_arg_separator.split(m.group(2))
569 return (t[0], s[0], s[1:-1])
571 def all_include(self, t):
574 self.result.append(self.resolve_include(t))
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
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.
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