| Home | Trees | Indices | Help |
|
|---|
|
|
1 #
2 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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 3795 2008/11/25 22:04:43 scons"
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.
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
183 """
184 Handles delayed evaluation of a #define function call.
185 """
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
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
242 """
243 The main workhorse class for handling C pre-processing.
244 """
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
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
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
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
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
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
349 """
350 Null method for when we explicitly want the action for a
351 specific preprocessor directive to do nothing.
352 """
353 pass
354
357
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
371 self.result = [fname]
372
374 return self.result[1:]
375
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
392
393 # Start and stop processing include lines.
394
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
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
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