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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
27 SCons C Pre-Processor module
35 # First "subsystem" of regular expressions that we set up:
37 # Stuff to turn the C preprocessor directives in a file's contents into
38 # a list of tuples that we can process easily.
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.
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',)
51 # Fetch the rest of a #import/#include/#include_next line as one
52 # argument, with white space optional.
53 ('import', 'include', 'include_next',)
56 # We don't care what comes after a #else or #endif line.
57 ('else', 'endif',) : '',
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*(.*)',
66 # Fetch the #undefed keyword from a #undef line.
67 ('undef',) : '\s+([_A-Za-z][A-Za-z0-9_]+)',
70 # Create a table that maps each individual C preprocessor directive to
71 # the corresponding compiled regular expression that fetches the arguments
74 for op_list, expr in cpp_lines_dict.items():
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."
89 l = map(lambda x, o=override: o.get(x, x), Table.keys())
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*(' + string.join(l, '|') + ')(.*)$'
99 # And last but not least, compile the expression.
100 CPP_Expression = re.compile(e, re.M)
106 # Second "subsystem" of regular expressions that we set up:
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().
112 # A dictionary that maps the C representation of Boolean operators
113 # to their Python equivalents.
114 CPP_to_Python_Ops_Dict = {
124 CPP_to_Python_Ops_Sub = lambda m, d=CPP_to_Python_Ops_Dict: d[m.group(0)]
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 = CPP_to_Python_Ops_Dict.keys()
133 l.sort(lambda a, b: cmp(len(b), len(a)))
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 = string.join(map(re.escape, l), '|')
139 # ...and compile the expression.
140 CPP_to_Python_Ops_Expression = re.compile(expr)
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+)', '__dict__.has_key("\\1")'],
146 ['defined\s*\((\w+)\)', '__dict__.has_key("\\1")'],
150 ['(0x[0-9A-Fa-f]*)[UL]+', '\\1L'],
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])
158 # Wrap up all of the above into a handy function.
159 def CPP_to_Python(s):
161 Converts a C pre-processor expression into an equivalent
162 Python expression that can be evaluated.
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)
177 class FunctionEvaluator:
179 Handles delayed evaluation of a #define function call.
181 def __init__(self, name, args, expansion):
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.
188 self.args = function_arg_separator.split(args)
190 expansion = string.split(expansion, '##')
191 except (AttributeError, TypeError):
192 # Python 1.5 throws TypeError if "expansion" isn't a string,
193 # later versions throw AttributeError.
195 self.expansion = expansion
196 def __call__(self, *values):
198 Evaluates the expansion of a #define macro function called
199 with the specified values.
201 if len(self.args) != len(values):
202 raise ValueError, "Incorrect number of arguments to `%s'" % self.name
203 # Create a dictionary that maps the macro arguments to the
204 # corresponding values in this "call." We'll use this when we
205 # eval() the expansion so that arguments will get expanded to
208 for k, v in zip(self.args, values):
212 for s in self.expansion:
213 if not s in self.args:
216 statement = string.join(parts, ' + ')
218 return eval(statement, globals(), locals)
222 # Find line continuations.
223 line_continuations = re.compile('\\\\\r?\n')
225 # Search for a "function call" macro on an expansion. Returns the
226 # two-tuple of the "function" name itself, and a string containing the
227 # arguments within the call parentheses.
228 function_name = re.compile('(\S+)\(([^)]*)\)')
230 # Split a string containing comma-separated function call arguments into
231 # the separate arguments.
232 function_arg_separator = re.compile(',\s*')
238 The main workhorse class for handling C pre-processing.
240 def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0):
243 cpppath = tuple(cpppath)
246 '"' : (current,) + cpppath,
247 '<' : cpppath + (current,),
250 # Initialize our C preprocessor namespace for tracking the
251 # values of #defined keywords. We use this namespace to look
252 # for keywords on #ifdef/#ifndef lines, and to eval() the
253 # expressions on #if/#elif lines (after massaging them from C to
255 self.cpp_namespace = dict.copy()
256 self.cpp_namespace['__dict__'] = self.cpp_namespace
259 self.do_include = self.all_include
261 # For efficiency, a dispatch table maps each C preprocessor
262 # directive (#if, #define, etc.) to the method that should be
263 # called when we see it. We accomodate state changes (#if,
264 # #ifdef, #ifndef) by pushing the current dispatch table on a
265 # stack and changing what method gets called for each relevant
266 # directive we might see next at this level (#else, #elif).
267 # #endif will simply pop the stack.
269 'scons_current_file' : self.scons_current_file
271 for op in Table.keys():
272 d[op] = getattr(self, 'do_' + op)
273 self.default_table = d
275 # Controlling methods.
277 def tupleize(self, contents):
279 Turns the contents of a file into a list of easily-processed
280 tuples describing the CPP lines in the file.
282 The first element of each tuple is the line's preprocessor
283 directive (#if, #include, #define, etc., minus the initial '#').
284 The remaining elements are specific to the type of directive, as
285 pulled apart by the regular expression.
287 global CPP_Expression, Table
288 contents = line_continuations.sub('', contents)
289 cpp_tuples = CPP_Expression.findall(contents)
290 return map(lambda m, t=Table:
291 (m[0],) + t[m[0]].match(m[1]).groups(),
294 def __call__(self, file):
296 Pre-processes a file.
298 This is the main public entry point.
300 self.current_file = file
301 return self.process_contents(self.read_file(file), file)
303 def process_contents(self, contents, fname=None):
305 Pre-processes a file contents.
307 This is the main internal entry point.
310 self.dispatch_table = self.default_table.copy()
311 self.current_file = fname
312 self.tuples = self.tupleize(contents)
314 self.initialize_result(fname)
316 t = self.tuples.pop(0)
317 # Uncomment to see the list of tuples being processed (e.g.,
318 # to validate the CPP lines are being translated correctly).
320 self.dispatch_table[t[0]](t)
321 return self.finalize_result(fname)
323 # Dispatch table stack manipulation methods.
327 Pushes the current dispatch table on the stack and re-initializes
328 the current dispatch table to the default.
330 self.stack.append(self.dispatch_table)
331 self.dispatch_table = self.default_table.copy()
335 Pops the previous dispatch table off the stack and makes it the
338 try: self.dispatch_table = self.stack.pop()
339 except IndexError: pass
343 def do_nothing(self, t):
345 Null method for when we explicitly want the action for a
346 specific preprocessor directive to do nothing.
350 def scons_current_file(self, t):
351 self.current_file = t[1]
353 def eval_expression(self, t):
355 Evaluates a C preprocessor expression.
357 This is done by converting it to a Python equivalent and
358 eval()ing it in the C preprocessor namespace we use to
359 track #define values.
361 t = CPP_to_Python(string.join(t[1:]))
362 try: return eval(t, self.cpp_namespace)
363 except (NameError, TypeError): return 0
365 def initialize_result(self, fname):
366 self.result = [fname]
368 def finalize_result(self, fname):
369 return self.result[1:]
371 def find_include_file(self, t):
373 Finds the #include file for a given preprocessor tuple.
376 for d in self.searchpath[t[1]]:
380 f = os.path.join(d, fname)
381 if os.path.isfile(f):
385 def read_file(self, file):
386 return open(file).read()
388 # Start and stop processing include lines.
390 def start_handling_includes(self, t=None):
392 Causes the PreProcessor object to start processing #import,
393 #include and #include_next lines.
395 This method will be called when a #if, #ifdef, #ifndef or #elif
396 evaluates True, or when we reach the #else in a #if, #ifdef,
397 #ifndef or #elif block where a condition already evaluated
401 d = self.dispatch_table
402 d['import'] = self.do_import
403 d['include'] = self.do_include
404 d['include_next'] = self.do_include
406 def stop_handling_includes(self, t=None):
408 Causes the PreProcessor object to stop processing #import,
409 #include and #include_next lines.
411 This method will be called when a #if, #ifdef, #ifndef or #elif
412 evaluates False, or when we reach the #else in a #if, #ifdef,
413 #ifndef or #elif block where a condition already evaluated True.
415 d = self.dispatch_table
416 d['import'] = self.do_nothing
417 d['include'] = self.do_nothing
418 d['include_next'] = self.do_nothing
420 # Default methods for handling all of the preprocessor directives.
421 # (Note that what actually gets called for a given directive at any
422 # point in time is really controlled by the dispatch_table.)
424 def _do_if_else_condition(self, condition):
426 Common logic for evaluating the conditions on #if, #ifdef and
430 d = self.dispatch_table
432 self.start_handling_includes()
433 d['elif'] = self.stop_handling_includes
434 d['else'] = self.stop_handling_includes
436 self.stop_handling_includes()
437 d['elif'] = self.do_elif
438 d['else'] = self.start_handling_includes
440 def do_ifdef(self, t):
442 Default handling of a #ifdef line.
444 self._do_if_else_condition(self.cpp_namespace.has_key(t[1]))
446 def do_ifndef(self, t):
448 Default handling of a #ifndef line.
450 self._do_if_else_condition(not self.cpp_namespace.has_key(t[1]))
454 Default handling of a #if line.
456 self._do_if_else_condition(self.eval_expression(t))
458 def do_elif(self, t):
460 Default handling of a #elif line.
462 d = self.dispatch_table
463 if self.eval_expression(t):
464 self.start_handling_includes()
465 d['elif'] = self.stop_handling_includes
466 d['else'] = self.stop_handling_includes
468 def do_else(self, t):
470 Default handling of a #else line.
474 def do_endif(self, t):
476 Default handling of a #endif line.
480 def do_define(self, t):
482 Default handling of a #define line.
484 _, name, args, expansion = t
486 expansion = int(expansion)
487 except (TypeError, ValueError):
490 evaluator = FunctionEvaluator(name, args[1:-1], expansion)
491 self.cpp_namespace[name] = evaluator
493 self.cpp_namespace[name] = expansion
495 def do_undef(self, t):
497 Default handling of a #undef line.
499 try: del self.cpp_namespace[t[1]]
500 except KeyError: pass
502 def do_import(self, t):
504 Default handling of a #import line.
506 # XXX finish this -- maybe borrow/share logic from do_include()...?
509 def do_include(self, t):
511 Default handling of a #include line.
513 t = self.resolve_include(t)
514 include_file = self.find_include_file(t)
516 #print "include_file =", include_file
517 self.result.append(include_file)
518 contents = self.read_file(include_file)
519 new_tuples = [('scons_current_file', include_file)] + \
520 self.tupleize(contents) + \
521 [('scons_current_file', self.current_file)]
522 self.tuples[:] = new_tuples + self.tuples
524 # Date: Tue, 22 Nov 2005 20:26:09 -0500
525 # From: Stefan Seefeld <seefeld@sympatico.ca>
527 # By the way, #include_next is not the same as #include. The difference
528 # being that #include_next starts its search in the path following the
529 # path that let to the including file. In other words, if your system
530 # include paths are ['/foo', '/bar'], and you are looking at a header
531 # '/foo/baz.h', it might issue an '#include_next <baz.h>' which would
532 # correctly resolve to '/bar/baz.h' (if that exists), but *not* see
533 # '/foo/baz.h' again. See http://www.delorie.com/gnu/docs/gcc/cpp_11.html
534 # for more reasoning.
536 # I have no idea in what context 'import' might be used.
538 # XXX is #include_next really the same as #include ?
539 do_include_next = do_include
541 # Utility methods for handling resolution of include files.
543 def resolve_include(self, t):
544 """Resolve a tuple-ized #include line.
546 This handles recursive expansion of values without "" or <>
547 surrounding the name until an initial " or < is found, to handle
549 where FILE is a #define somewhere else.
552 while not s[0] in '<"':
555 s = self.cpp_namespace[s]
557 m = function_name.search(s)
558 s = self.cpp_namespace[m.group(1)]
560 args = function_arg_separator.split(m.group(2))
564 return (t[0], s[0], s[1:-1])
566 def all_include(self, t):
569 self.result.append(self.resolve_include(t))
571 class DumbPreProcessor(PreProcessor):
572 """A preprocessor that ignores all #if/#elif/#else/#endif directives
573 and just reports back *all* of the #include files (like the classic
576 This is functionally equivalent to using a regular expression to
577 find all of the #include lines, only slower. It exists mainly as
578 an example of how the main PreProcessor class can be sub-classed
579 to tailor its behavior.
581 def __init__(self, *args, **kw):
582 apply(PreProcessor.__init__, (self,)+args, kw)
583 d = self.default_table
584 for func in ['if', 'elif', 'else', 'endif', 'ifdef', 'ifndef']:
585 d[func] = d[func] = self.do_nothing