Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Linker/XRefCompiler.py
    1| # $Id: XRefCompiler.py,v 1.4 2002/12/09 04:00:59 chalky Exp $
    2| #
    3| # This file is a part of Synopsis.
    4| # Copyright (C) 2000, 2001 Stefan Seefeld
    5| # Copyright (C) 2000, 2001 Stephen Davies
    6| #
    7| # Synopsis is free software; you can redistribute it and/or modify it
    8| # under the terms of the GNU General Public License as published by
    9| # the Free Software Foundation; either version 2 of the License, or
   10| # (at your option) any later version.
   11| #
   12| # This program is distributed in the hope that it will be useful,
   13| # but WITHOUT ANY WARRANTY; without even the implied warranty of
   14| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15| # General Public License for more details.
   16| #
   17| # You should have received a copy of the GNU General Public License
   18| # along with this program; if not, write to the Free Software
   19| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   20| # 02111-1307, USA.
   21| #
   22| # $Log: XRefCompiler.py,v $
   23| # Revision 1.4  2002/12/09 04:00:59  chalky
   24| # Added multiple file support to parsers, changed AST datastructure to handle
   25| # new information, added a demo to demo/C++. AST Declarations now have a
   26| # reference to a SourceFile (which includes a filename) instead of a filename.
   27| #
   28| # Revision 1.3  2002/11/03 06:08:56  chalky
   29| # Tolerate file not found errors
   30| #
   31| # Revision 1.2  2002/10/29 12:43:25  chalky
   32| # Added no_locals support which is on by default, and strips local variables
   33| # from cross reference tables
   34| #
   35| # Revision 1.1  2002/10/29 07:34:29  chalky
   36| # New linker module, compiles xref files into data structure
   37| #
   38| #
   39| 
   40| import string, cPickle, urllib
   41| 
   42| from Synopsis.Core import AST, Type, Util
   43| 
   44| from Linker import config, Operation
   45| 
   46| def do_compile(input_files, output_file, no_locals):
   47|     # Init data structures
   48|     data = {}
   49|     index = {}
   50|     file_data = (data, index)
   51| 
   52|     # Read input files
   53|     for file in input_files:
   54|         if config.verbose: print "XRefCompiler: Reading",file
   55|         try:
   56|             f = open(file, 'rt')
   57|         except IOError, e:
   58|             print "Error opening %s: %s"%(file, e)
   59|             continue
   60| 
   61|         lines = f.readlines()
   62|         f.close()
   63| 
   64|         for line in lines:
   65|             target, file, line, scope, context = string.split(line)
   66|             target = tuple(map(intern, string.split(urllib.unquote(target), '\t')))
   67|             scope = map(intern, string.split(urllib.unquote(scope), '\t'))
   68|             line = int(line)
   69|             file = intern(file)
   70| 
   71|             if no_locals:
   72|         bad = 0
   73|                for i in range(len(target)):
   74|                    if len(target[i]) > 0 and target[i][0] == '`':
   75|                       # Don't store local function variables
   76|                bad = 1
   77|         break
   78|                if bad: continue
   79| 
   80|             for i in range(len(scope)):
   81|                if len(scope[i]) > 0 and scope[i][0] == '`':
   82|                    # Function scope, truncate here
   83|                    del scope[i+1:]
   84|                    scope[i] = scope[i][1:]
   85|                break
   86|             scope = tuple(scope)
   87|         
   88|             target_data = data.setdefault(target, [[],[],[]])
   89|             if context == 'DEF':
   90|                target_data[0].append( (file, line, scope) )
   91|             elif context == 'CALL':
   92|                target_data[1].append( (file, line, scope) )
   93|             elif context == 'REF':
   94|                target_data[2].append( (file, line, scope) )
   95|          else:
   96|                print "Warning: Unknown context:",context
   97| 
   98|     # Sort the data
   99|     for target, target_data in data.items():
  100|         target_data[1].sort()
  101|         target_data[2].sort()
  102| 
  103|         name = target[-1]
  104|         index.setdefault(name,[]).append(target)
  105|         # If it's a function name, also add without the parameters
  106|         paren = name.find('(')
  107|         if paren != -1:
  108|             index.setdefault(name[:paren],[]).append(target)
  109|         
  110|     if config.verbose: print "XRefCompiler: Writing",output_file
  111|     f = open(output_file, 'wb')
  112|     cPickle.dump(file_data, f)
  113|     f.close()
  114|  
  115| class XRefCompiler(Operation):
  116|     """This class compiles a set of text-based xref files from the C++ parser
  117|     into a cPickled data structure with a name index.
  118|     
  119|     The format of the data structure is:
  120|     <pre>
  121|      (data, index) = cPickle.load()
  122|      data = dict<scoped targetname, target_data>
  123|      index = dict<name, list<scoped targetname>>
  124|      target_data = (definitions = list<target_info>,
  125|                    func calls = list<target_info>,
  126|                    references = list<target_info>)
  127|      target_info = (filename, int(line number), scoped context name)
  128|     </pre>
  129|     The scoped targetnames in the index are guaranteed to exist in the data
  130|     dictionary.
  131|     """
  132|     def __init__(self):
  133|         self.__xref_path = './%s-xref'
  134|         self.__xref_file = 'compiled.xref'
  135|         self.__no_locals = 1
  136|         if hasattr(config.obj, 'XRefCompiler'):
  137|             obj = config.obj.XRefCompiler
  138|             if hasattr(obj, 'xref_path'):
  139|                self.__xref_path = obj.xref_path
  140|             if hasattr(obj, 'xref_file'):
  141|                self.__xref_file = obj.xref_file
  142|             if hasattr(obj, 'no_locals'):
  143|                self.__no_locals = obj.no_locals
  144|     def execute(self, ast):
  145|         filenames = map(lambda x: x[0], 
  146|             filter(lambda x: x[1].is_main(), 
  147|                ast.files().items()))
  148|         filenames = map(lambda x:self.__xref_path%x, filenames)
  149|         do_compile(filenames, self.__xref_file, self.__no_locals)
  150| 
  151| linkerOperation = XRefCompiler