5ccc00e14ac6123cddcc231f309398dee7f0b51b
[scons.git] / src / engine / SCons / cpp.py
1 #
2 # __COPYRIGHT__
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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
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
38 #
39 # First "subsystem" of regular expressions that we set up:
40 #
41 # Stuff to turn the C preprocessor directives in a file's contents into
42 # a list of tuples that we can process easily.
43 #
44
45 # A table of regular expressions that fetch the arguments from the rest of
46 # a C preprocessor line.  Different directives have different arguments
47 # that we want to fetch, using the regular expressions to which the lists
48 # of preprocessor directives map.
49 cpp_lines_dict = {
50     # Fetch the rest of a #if/#elif/#ifdef/#ifndef as one argument,
51     # separated from the keyword by white space.
52     ('if', 'elif', 'ifdef', 'ifndef',)
53                         : '\s+(.+)',
54
55     # Fetch the rest of a #import/#include/#include_next line as one
56     # argument, with white space optional.
57     ('import', 'include', 'include_next',)
58                         : '\s*(.+)',
59
60     # We don't care what comes after a #else or #endif line.
61     ('else', 'endif',)  : '',
62
63     # Fetch three arguments from a #define line:
64     #   1) The #defined keyword.
65     #   2) The optional parentheses and arguments (if it's a function-like
66     #      macro, '' if it's not).
67     #   3) The expansion value.
68     ('define',)         : '\s+([_A-Za-z][_A-Za-z0-9_]*)(\([^)]*\))?\s*(.*)',
69
70     # Fetch the #undefed keyword from a #undef line.
71     ('undef',)          : '\s+([_A-Za-z][A-Za-z0-9_]*)',
72 }
73
74 # Create a table that maps each individual C preprocessor directive to
75 # the corresponding compiled regular expression that fetches the arguments
76 # we care about.
77 Table = {}
78 for op_list, expr in cpp_lines_dict.items():
79     e = re.compile(expr)
80     for op in op_list:
81         Table[op] = e
82 del e
83 del op
84 del op_list
85
86 # Create a list of the expressions we'll use to match all of the
87 # preprocessor directives.  These are the same as the directives
88 # themselves *except* that we must use a negative lookahead assertion
89 # when matching "if" so it doesn't match the "if" in "ifdef."
90 override = {
91     'if'                        : 'if(?!def)',
92 }
93 l = [override.get(x, x) for x in Table.keys()]
94
95
96 # Turn the list of expressions into one big honkin' regular expression
97 # that will match all the preprocessor lines at once.  This will return
98 # a list of tuples, one for each preprocessor line.  The preprocessor
99 # directive will be the first element in each tuple, and the rest of
100 # the line will be the second element.
101 e = '^\s*#\s*(' + '|'.join(l) + ')(.*)$'
102
103 # And last but not least, compile the expression.
104 CPP_Expression = re.compile(e, re.M)
105
106
107
108
109 #
110 # Second "subsystem" of regular expressions that we set up:
111 #
112 # Stuff to translate a C preprocessor expression (as found on a #if or
113 # #elif line) into an equivalent Python expression that we can eval().
114 #
115
116 # A dictionary that maps the C representation of Boolean operators
117 # to their Python equivalents.
118 CPP_to_Python_Ops_Dict = {
119     '!'         : ' not ',
120     '!='        : ' != ',
121     '&&'        : ' and ',
122     '||'        : ' or ',
123     '?'         : ' and ',
124     ':'         : ' or ',
125     '\r'        : '',
126 }
127
128 CPP_to_Python_Ops_Sub = lambda m: CPP_to_Python_Ops_Dict[m.group(0)]
129
130 # We have to sort the keys by length so that longer expressions
131 # come *before* shorter expressions--in particular, "!=" must
132 # come before "!" in the alternation.  Without this, the Python
133 # re module, as late as version 2.2.2, empirically matches the
134 # "!" in "!=" first, instead of finding the longest match.
135 # What's up with that?
136 l = CPP_to_Python_Ops_Dict.keys()
137 l.sort(lambda a, b: cmp(len(b), len(a)))
138
139 # Turn the list of keys into one regular expression that will allow us
140 # to substitute all of the operators at once.
141 expr = '|'.join(map(re.escape, l))
142
143 # ...and compile the expression.
144 CPP_to_Python_Ops_Expression = re.compile(expr)
145
146 # A separate list of expressions to be evaluated and substituted
147 # sequentially, not all at once.
148 CPP_to_Python_Eval_List = [
149     ['defined\s+(\w+)',         '"\\1" in __dict__'],
150     ['defined\s*\((\w+)\)',     '"\\1" in __dict__'],
151     ['/\*.*\*/',                ''],
152     ['/\*.*',                   ''],
153     ['//.*',                    ''],
154     ['(0x[0-9A-Fa-f]*)[UL]+',   '\\1'],
155 ]
156
157 # Replace the string representations of the regular expressions in the
158 # list with compiled versions.
159 for l in CPP_to_Python_Eval_List:
160     l[0] = re.compile(l[0])
161
162 # Wrap up all of the above into a handy function.
163 def CPP_to_Python(s):
164     """
165     Converts a C pre-processor expression into an equivalent
166     Python expression that can be evaluated.
167     """
168     s = CPP_to_Python_Ops_Expression.sub(CPP_to_Python_Ops_Sub, s)
169     for expr, repl in CPP_to_Python_Eval_List:
170         s = expr.sub(repl, s)
171     return s
172
173
174
175 del expr
176 del l
177 del override
178
179
180
181 class FunctionEvaluator:
182     """
183     Handles delayed evaluation of a #define function call.
184     """
185     def __init__(self, name, args, expansion):
186         """
187         Squirrels away the arguments and expansion value of a #define
188         macro function for later evaluation when we must actually expand
189         a value that uses it.
190         """
191         self.name = name
192         self.args = function_arg_separator.split(args)
193         try:
194             expansion = expansion.split('##')
195         except (AttributeError, TypeError):
196             # Python 1.5 throws TypeError if "expansion" isn't a string,
197             # later versions throw AttributeError.
198             pass
199         self.expansion = expansion
200     def __call__(self, *values):
201         """
202         Evaluates the expansion of a #define macro function called
203         with the specified values.
204         """
205         if len(self.args) != len(values):
206             raise ValueError, "Incorrect number of arguments to `%s'" % self.name
207         # Create a dictionary that maps the macro arguments to the
208         # corresponding values in this "call."  We'll use this when we
209         # eval() the expansion so that arguments will get expanded to
210         # the right values.
211         locals = {}
212         for k, v in zip(self.args, values):
213             locals[k] = v
214
215         parts = []
216         for s in self.expansion:
217             if not s in self.args:
218                 s = repr(s)
219             parts.append(s)
220         statement = ' + '.join(parts)
221
222         return eval(statement, globals(), locals)
223
224
225
226 # Find line continuations.
227 line_continuations = re.compile('\\\\\r?\n')
228
229 # Search for a "function call" macro on an expansion.  Returns the
230 # two-tuple of the "function" name itself, and a string containing the
231 # arguments within the call parentheses.
232 function_name = re.compile('(\S+)\(([^)]*)\)')
233
234 # Split a string containing comma-separated function call arguments into
235 # the separate arguments.
236 function_arg_separator = re.compile(',\s*')
237
238
239
240 class PreProcessor:
241     """
242     The main workhorse class for handling C pre-processing.
243     """
244     def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0):
245         global Table
246
247         cpppath = tuple(cpppath)
248
249         self.searchpath = {
250             '"' :       (current,) + cpppath,
251             '<' :       cpppath + (current,),
252         }
253
254         # Initialize our C preprocessor namespace for tracking the
255         # values of #defined keywords.  We use this namespace to look
256         # for keywords on #ifdef/#ifndef lines, and to eval() the
257         # expressions on #if/#elif lines (after massaging them from C to
258         # Python).
259         self.cpp_namespace = dict.copy()
260         self.cpp_namespace['__dict__'] = self.cpp_namespace
261
262         if all:
263            self.do_include = self.all_include
264
265         # For efficiency, a dispatch table maps each C preprocessor
266         # directive (#if, #define, etc.) to the method that should be
267         # called when we see it.  We accomodate state changes (#if,
268         # #ifdef, #ifndef) by pushing the current dispatch table on a
269         # stack and changing what method gets called for each relevant
270         # directive we might see next at this level (#else, #elif).
271         # #endif will simply pop the stack.
272         d = {
273             'scons_current_file'    : self.scons_current_file
274         }
275         for op in Table.keys():
276             d[op] = getattr(self, 'do_' + op)
277         self.default_table = d
278
279     # Controlling methods.
280
281     def tupleize(self, contents):
282         """
283         Turns the contents of a file into a list of easily-processed
284         tuples describing the CPP lines in the file.
285
286         The first element of each tuple is the line's preprocessor
287         directive (#if, #include, #define, etc., minus the initial '#').
288         The remaining elements are specific to the type of directive, as
289         pulled apart by the regular expression.
290         """
291         global CPP_Expression, Table
292         contents = line_continuations.sub('', contents)
293         cpp_tuples = CPP_Expression.findall(contents)
294         return  [(m[0],) + Table[m[0]].match(m[1]).groups() for m in cpp_tuples]
295
296     def __call__(self, file):
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
305     def process_contents(self, contents, fname=None):
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
327     def save(self):
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
335     def restore(self):
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
345     def do_nothing(self, t):
346         """
347         Null method for when we explicitly want the action for a
348         specific preprocessor directive to do nothing.
349         """
350         pass
351
352     def scons_current_file(self, t):
353         self.current_file = t[1]
354
355     def eval_expression(self, t):
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(' '.join(t[1:]))
364         try: return eval(t, self.cpp_namespace)
365         except (NameError, TypeError): return 0
366
367     def initialize_result(self, fname):
368         self.result = [fname]
369
370     def finalize_result(self, fname):
371         return self.result[1:]
372
373     def find_include_file(self, t):
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
387     def read_file(self, file):
388         return open(file).read()
389
390     # Start and stop processing include lines.
391
392     def start_handling_includes(self, t=None):
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
408     def stop_handling_includes(self, t=None):
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
426     def _do_if_else_condition(self, condition):
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
442     def do_ifdef(self, t):
443         """
444         Default handling of a #ifdef line.
445         """
446         self._do_if_else_condition(t[1] in self.cpp_namespace)
447
448     def do_ifndef(self, t):
449         """
450         Default handling of a #ifndef line.
451         """
452         self._do_if_else_condition(t[1] not in self.cpp_namespace)
453
454     def do_if(self, t):
455         """
456         Default handling of a #if line.
457         """
458         self._do_if_else_condition(self.eval_expression(t))
459
460     def do_elif(self, t):
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
470     def do_else(self, t):
471         """
472         Default handling of a #else line.
473         """
474         pass
475
476     def do_endif(self, t):
477         """
478         Default handling of a #endif line.
479         """
480         self.restore()
481
482     def do_define(self, t):
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
497     def do_undef(self, t):
498         """
499         Default handling of a #undef line.
500         """
501         try: del self.cpp_namespace[t[1]]
502         except KeyError: pass
503
504     def do_import(self, t):
505         """
506         Default handling of a #import line.
507         """
508         # XXX finish this -- maybe borrow/share logic from do_include()...?
509         pass
510
511     def do_include(self, t):
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 <seefeld@sympatico.ca>
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
545     def resolve_include(self, t):
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 = s(*args)
564             if not s:
565                 return None
566         return (t[0], s[0], s[1:-1])
567
568     def all_include(self, t):
569         """
570         """
571         self.result.append(self.resolve_include(t))
572
573 class DumbPreProcessor(PreProcessor):
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     """
583     def __init__(self, *args, **kw):
584         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
591 # Local Variables:
592 # tab-width:4
593 # indent-tabs-mode:nil
594 # End:
595 # vim: set expandtab tabstop=4 shiftwidth=4: