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 3603 2008/10/10 05:46:45 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