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