Issue 2410: Fix crash when using one-character identifiers in C and C++ macros.
[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 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.
164 def CPP_to_Python(s):
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
182 class FunctionEvaluator:
183     """
184     Handles delayed evaluation of a #define function call.
185     """
186     def __init__(self, name, args, expansion):
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
201     def __call__(self, *values):
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
241 class PreProcessor:
242     """
243     The main workhorse class for handling C pre-processing.
244     """
245     def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0):
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
282     def tupleize(self, contents):
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
299     def __call__(self, file):
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
308     def process_contents(self, contents, fname=None):
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
330     def save(self):
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
338     def restore(self):
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
348     def do_nothing(self, t):
349         """
350         Null method for when we explicitly want the action for a
351         specific preprocessor directive to do nothing.
352         """
353         pass
354
355     def scons_current_file(self, t):
356         self.current_file = t[1]
357
358     def eval_expression(self, t):
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
370     def initialize_result(self, fname):
371         self.result = [fname]
372
373     def finalize_result(self, fname):
374         return self.result[1:]
375
376     def find_include_file(self, t):
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
390     def read_file(self, file):
391         return open(file).read()
392
393     # Start and stop processing include lines.
394
395     def start_handling_includes(self, t=None):
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
411     def stop_handling_includes(self, t=None):
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
429     def _do_if_else_condition(self, condition):
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             d['else'] = self.start_handling_includes
444
445     def do_ifdef(self, t):
446         """
447         Default handling of a #ifdef line.
448         """
449         self._do_if_else_condition(self.cpp_namespace.has_key(t[1]))
450
451     def do_ifndef(self, t):
452         """
453         Default handling of a #ifndef line.
454         """
455         self._do_if_else_condition(not self.cpp_namespace.has_key(t[1]))
456
457     def do_if(self, t):
458         """
459         Default handling of a #if line.
460         """
461         self._do_if_else_condition(self.eval_expression(t))
462
463     def do_elif(self, t):
464         """
465         Default handling of a #elif line.
466         """
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
472
473     def do_else(self, t):
474         """
475         Default handling of a #else line.
476         """
477         pass
478
479     def do_endif(self, t):
480         """
481         Default handling of a #endif line.
482         """
483         self.restore()
484
485     def do_define(self, t):
486         """
487         Default handling of a #define line.
488         """
489         _, name, args, expansion = t
490         try:
491             expansion = int(expansion)
492         except (TypeError, ValueError):
493             pass
494         if args:
495             evaluator = FunctionEvaluator(name, args[1:-1], expansion)
496             self.cpp_namespace[name] = evaluator
497         else:
498             self.cpp_namespace[name] = expansion
499
500     def do_undef(self, t):
501         """
502         Default handling of a #undef line.
503         """
504         try: del self.cpp_namespace[t[1]]
505         except KeyError: pass
506
507     def do_import(self, t):
508         """
509         Default handling of a #import line.
510         """
511         # XXX finish this -- maybe borrow/share logic from do_include()...?
512         pass
513
514     def do_include(self, t):
515         """
516         Default handling of a #include line.
517         """
518         t = self.resolve_include(t)
519         include_file = self.find_include_file(t)
520         if include_file:
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
528
529     # Date: Tue, 22 Nov 2005 20:26:09 -0500
530     # From: Stefan Seefeld <seefeld@sympatico.ca>
531     #
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.
540     #
541     # I have no idea in what context 'import' might be used.
542
543     # XXX is #include_next really the same as #include ?
544     do_include_next = do_include
545
546     # Utility methods for handling resolution of include files.
547
548     def resolve_include(self, t):
549         """Resolve a tuple-ized #include line.
550
551         This handles recursive expansion of values without "" or <>
552         surrounding the name until an initial " or < is found, to handle
553                 #include FILE
554         where FILE is a #define somewhere else.
555         """
556         s = t[1]
557         while not s[0] in '<"':
558             #print "s =", s
559             try:
560                 s = self.cpp_namespace[s]
561             except KeyError:
562                 m = function_name.search(s)
563                 s = self.cpp_namespace[m.group(1)]
564                 if callable(s):
565                     args = function_arg_separator.split(m.group(2))
566                     s = apply(s, args)
567             if not s:
568                 return None
569         return (t[0], s[0], s[1:-1])
570
571     def all_include(self, t):
572         """
573         """
574         self.result.append(self.resolve_include(t))
575
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
579     SCons scanner did).
580
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.
585     """
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
591
592 del __revision__
593
594 # Local Variables:
595 # tab-width:4
596 # indent-tabs-mode:nil
597 # End:
598 # vim: set expandtab tabstop=4 shiftwidth=4: