Evaluate compat module transparently when SCons is instantiated
[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 import os
31 import re
32 import string
33
34 #
35 # First "subsystem" of regular expressions that we set up:
36 #
37 # Stuff to turn the C preprocessor directives in a file's contents into
38 # a list of tuples that we can process easily.
39 #
40
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.
45 cpp_lines_dict = {
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',)
49                         : '\s+(.+)',
50
51     # Fetch the rest of a #import/#include/#include_next line as one
52     # argument, with white space optional.
53     ('import', 'include', 'include_next',)
54                         : '\s*(.+)',
55
56     # We don't care what comes after a #else or #endif line.
57     ('else', 'endif',)  : '',
58
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*(.*)',
65
66     # Fetch the #undefed keyword from a #undef line.
67     ('undef',)          : '\s+([_A-Za-z][A-Za-z0-9_]+)',
68 }
69
70 # Create a table that maps each individual C preprocessor directive to
71 # the corresponding compiled regular expression that fetches the arguments
72 # we care about.
73 Table = {}
74 for op_list, expr in cpp_lines_dict.items():
75     e = re.compile(expr)
76     for op in op_list:
77         Table[op] = e
78 del e
79 del op
80 del op_list
81
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."
86 override = {
87     'if'                        : 'if(?!def)',
88 }
89 l = map(lambda x, o=override: o.get(x, x), Table.keys())
90
91
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, '|') + ')(.*)$'
98
99 # And last but not least, compile the expression.
100 CPP_Expression = re.compile(e, re.M)
101
102
103
104
105 #
106 # Second "subsystem" of regular expressions that we set up:
107 #
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().
110 #
111
112 # A dictionary that maps the C representation of Boolean operators
113 # to their Python equivalents.
114 CPP_to_Python_Ops_Dict = {
115     '!'         : ' not ',
116     '!='        : ' != ',
117     '&&'        : ' and ',
118     '||'        : ' or ',
119     '?'         : ' and ',
120     ':'         : ' or ',
121     '\r'        : '',
122 }
123
124 CPP_to_Python_Ops_Sub = lambda m, d=CPP_to_Python_Ops_Dict: d[m.group(0)]
125
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)))
134
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), '|')
138
139 # ...and compile the expression.
140 CPP_to_Python_Ops_Expression = re.compile(expr)
141
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")'],
147     ['/\*.*\*/',                ''],
148     ['/\*.*',                   ''],
149     ['//.*',                    ''],
150     ['(0x[0-9A-Fa-f]*)[UL]+',   '\\1L'],
151 ]
152
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])
157
158 # Wrap up all of the above into a handy function.
159 def CPP_to_Python(s):
160     """
161     Converts a C pre-processor expression into an equivalent
162     Python expression that can be evaluated.
163     """
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)
167     return s
168
169
170
171 del expr
172 del l
173 del override
174
175
176
177 class FunctionEvaluator:
178     """
179     Handles delayed evaluation of a #define function call.
180     """
181     def __init__(self, name, args, expansion):
182         """
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.
186         """
187         self.name = name
188         self.args = function_arg_separator.split(args)
189         try:
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.
194             pass
195         self.expansion = expansion
196     def __call__(self, *values):
197         """
198         Evaluates the expansion of a #define macro function called
199         with the specified values.
200         """
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
206         # the right values.
207         locals = {}
208         for k, v in zip(self.args, values):
209             locals[k] = v
210
211         parts = []
212         for s in self.expansion:
213             if not s in self.args:
214                 s = repr(s)
215             parts.append(s)
216         statement = string.join(parts, ' + ')
217
218         return eval(statement, globals(), locals)
219
220
221
222 # Find line continuations.
223 line_continuations = re.compile('\\\\\r?\n')
224
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+)\(([^)]*)\)')
229
230 # Split a string containing comma-separated function call arguments into
231 # the separate arguments.
232 function_arg_separator = re.compile(',\s*')
233
234
235
236 class PreProcessor:
237     """
238     The main workhorse class for handling C pre-processing.
239     """
240     def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0):
241         global Table
242
243         cpppath = tuple(cpppath)
244
245         self.searchpath = {
246             '"' :       (current,) + cpppath,
247             '<' :       cpppath + (current,),
248         }
249
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
254         # Python).
255         self.cpp_namespace = dict.copy()
256         self.cpp_namespace['__dict__'] = self.cpp_namespace
257
258         if all:
259            self.do_include = self.all_include
260
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.
268         d = {
269             'scons_current_file'    : self.scons_current_file
270         }
271         for op in Table.keys():
272             d[op] = getattr(self, 'do_' + op)
273         self.default_table = d
274
275     # Controlling methods.
276
277     def tupleize(self, contents):
278         """
279         Turns the contents of a file into a list of easily-processed
280         tuples describing the CPP lines in the file.
281
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.
286         """
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(),
292                     cpp_tuples)
293
294     def __call__(self, file):
295         """
296         Pre-processes a file.
297
298         This is the main public entry point.
299         """
300         self.current_file = file
301         return self.process_contents(self.read_file(file), file)
302
303     def process_contents(self, contents, fname=None):
304         """
305         Pre-processes a file contents.
306
307         This is the main internal entry point.
308         """
309         self.stack = []
310         self.dispatch_table = self.default_table.copy()
311         self.current_file = fname
312         self.tuples = self.tupleize(contents)
313
314         self.initialize_result(fname)
315         while self.tuples:
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).
319             #print t
320             self.dispatch_table[t[0]](t)
321         return self.finalize_result(fname)
322
323     # Dispatch table stack manipulation methods.
324
325     def save(self):
326         """
327         Pushes the current dispatch table on the stack and re-initializes
328         the current dispatch table to the default.
329         """
330         self.stack.append(self.dispatch_table)
331         self.dispatch_table = self.default_table.copy()
332
333     def restore(self):
334         """
335         Pops the previous dispatch table off the stack and makes it the
336         current one.
337         """
338         try: self.dispatch_table = self.stack.pop()
339         except IndexError: pass
340
341     # Utility methods.
342
343     def do_nothing(self, t):
344         """
345         Null method for when we explicitly want the action for a
346         specific preprocessor directive to do nothing.
347         """
348         pass
349
350     def scons_current_file(self, t):
351         self.current_file = t[1]
352
353     def eval_expression(self, t):
354         """
355         Evaluates a C preprocessor expression.
356
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.
360         """
361         t = CPP_to_Python(string.join(t[1:]))
362         try: return eval(t, self.cpp_namespace)
363         except (NameError, TypeError): return 0
364
365     def initialize_result(self, fname):
366         self.result = [fname]
367
368     def finalize_result(self, fname):
369         return self.result[1:]
370
371     def find_include_file(self, t):
372         """
373         Finds the #include file for a given preprocessor tuple.
374         """
375         fname = t[2]
376         for d in self.searchpath[t[1]]:
377             if d == os.curdir:
378                 f = fname
379             else:
380                 f = os.path.join(d, fname)
381             if os.path.isfile(f):
382                 return f
383         return None
384
385     def read_file(self, file):
386         return open(file).read()
387
388     # Start and stop processing include lines.
389
390     def start_handling_includes(self, t=None):
391         """
392         Causes the PreProcessor object to start processing #import,
393         #include and #include_next lines.
394
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
398         False.
399
400         """
401         d = self.dispatch_table
402         d['import'] = self.do_import
403         d['include'] =  self.do_include
404         d['include_next'] =  self.do_include
405
406     def stop_handling_includes(self, t=None):
407         """
408         Causes the PreProcessor object to stop processing #import,
409         #include and #include_next lines.
410
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.
414         """
415         d = self.dispatch_table
416         d['import'] = self.do_nothing
417         d['include'] =  self.do_nothing
418         d['include_next'] =  self.do_nothing
419
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.)
423
424     def _do_if_else_condition(self, condition):
425         """
426         Common logic for evaluating the conditions on #if, #ifdef and
427         #ifndef lines.
428         """
429         self.save()
430         d = self.dispatch_table
431         if condition:
432             self.start_handling_includes()
433             d['elif'] = self.stop_handling_includes
434             d['else'] = self.stop_handling_includes
435         else:
436             self.stop_handling_includes()
437             d['elif'] = self.do_elif
438             d['else'] = self.start_handling_includes
439
440     def do_ifdef(self, t):
441         """
442         Default handling of a #ifdef line.
443         """
444         self._do_if_else_condition(self.cpp_namespace.has_key(t[1]))
445
446     def do_ifndef(self, t):
447         """
448         Default handling of a #ifndef line.
449         """
450         self._do_if_else_condition(not self.cpp_namespace.has_key(t[1]))
451
452     def do_if(self, t):
453         """
454         Default handling of a #if line.
455         """
456         self._do_if_else_condition(self.eval_expression(t))
457
458     def do_elif(self, t):
459         """
460         Default handling of a #elif line.
461         """
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
467
468     def do_else(self, t):
469         """
470         Default handling of a #else line.
471         """
472         pass
473
474     def do_endif(self, t):
475         """
476         Default handling of a #endif line.
477         """
478         self.restore()
479
480     def do_define(self, t):
481         """
482         Default handling of a #define line.
483         """
484         _, name, args, expansion = t
485         try:
486             expansion = int(expansion)
487         except (TypeError, ValueError):
488             pass
489         if args:
490             evaluator = FunctionEvaluator(name, args[1:-1], expansion)
491             self.cpp_namespace[name] = evaluator
492         else:
493             self.cpp_namespace[name] = expansion
494
495     def do_undef(self, t):
496         """
497         Default handling of a #undef line.
498         """
499         try: del self.cpp_namespace[t[1]]
500         except KeyError: pass
501
502     def do_import(self, t):
503         """
504         Default handling of a #import line.
505         """
506         # XXX finish this -- maybe borrow/share logic from do_include()...?
507         pass
508
509     def do_include(self, t):
510         """
511         Default handling of a #include line.
512         """
513         t = self.resolve_include(t)
514         include_file = self.find_include_file(t)
515         if include_file:
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
523
524     # Date: Tue, 22 Nov 2005 20:26:09 -0500
525     # From: Stefan Seefeld <seefeld@sympatico.ca>
526     #
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.
535     #
536     # I have no idea in what context 'import' might be used.
537
538     # XXX is #include_next really the same as #include ?
539     do_include_next = do_include
540
541     # Utility methods for handling resolution of include files.
542
543     def resolve_include(self, t):
544         """Resolve a tuple-ized #include line.
545
546         This handles recursive expansion of values without "" or <>
547         surrounding the name until an initial " or < is found, to handle
548                 #include FILE
549         where FILE is a #define somewhere else.
550         """
551         s = t[1]
552         while not s[0] in '<"':
553             #print "s =", s
554             try:
555                 s = self.cpp_namespace[s]
556             except KeyError:
557                 m = function_name.search(s)
558                 s = self.cpp_namespace[m.group(1)]
559                 if callable(s):
560                     args = function_arg_separator.split(m.group(2))
561                     s = apply(s, args)
562             if not s:
563                 return None
564         return (t[0], s[0], s[1:-1])
565
566     def all_include(self, t):
567         """
568         """
569         self.result.append(self.resolve_include(t))
570
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
574     SCons scanner did).
575
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.
580     """
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
586
587 del __revision__