SCons.cpp

Package SCons :: Module cpp |
[hide private]
[frames] | no frames]

# Source Code for Module SCons.cpp

      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 2725 2008/03/31 12:52:02 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.
    161 -def CPP_to_Python(s):
    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
    179 -class FunctionEvaluator:
    180      """
    181      Handles delayed evaluation of a #define function call.
    182      """
    183 -    def __init__(self, name, args, expansion):
    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
    198 -    def __call__(self, *values):
    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
    238 -class PreProcessor:
    239      """
    240      The main workhorse class for handling C pre-processing.
    241      """
    242 -    def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0):
    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
    279 -    def tupleize(self, contents):
    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
    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(string.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(self.cpp_namespace.has_key(t[1]))
    447
    448 -    def do_ifndef(self, t):
    449          """
    450          Default handling of a #ifndef line.
    451          """
    452          self._do_if_else_condition(not self.cpp_namespace.has_key(t[1]))
    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 = apply(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          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