1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
#
# Copyright (C) 2000 Stefan Seefeld
# Copyright (C) 2000 Stephen Davies
# All rights reserved.
# Licensed to the public under the terms of the GNU LGPL (>= 2),
# see the file COPYING for details.
#
from Synopsis.Processor import Processor, Parameter
from Synopsis import AST, Type, Util
import os.path, string, cPickle, urllib
class XRefCompiler(Processor):
"""This class compiles a set of text-based xref files from the C++ parser
into a cPickled data structure with a name index.
The format of the data structure is:
<pre>
(data, index) = cPickle.load()
data = dict<scoped targetname, target_data>
index = dict<name, list<scoped targetname>>
target_data = (definitions = list<target_info>,
func calls = list<target_info>,
references = list<target_info>)
target_info = (filename, int(line number), scoped context name)
</pre>
The scoped targetnames in the index are guaranteed to exist in the data
dictionary.
"""
prefix = Parameter('', 'where to look for xref files')
no_locals = Parameter(True, '')
def process(self, ast, **kwds):
self.set_parameters(kwds)
self.ast = self.merge_input(ast)
filenames = map(lambda x: x[0],
filter(lambda x: x[1].is_main(), ast.files().items()))
filenames = map(lambda x:os.path.join(self.prefix, x), filenames)
self.do_compile(filenames, self.output, self.no_locals)
return self.ast
def do_compile(self, input_files, output, no_locals):
if not output:
if self.verbose: print "XRefCompiler: no output given"
return
# Init data structures
data = {}
index = {}
file_data = (data, index)
# Read input files
for file in input_files:
if self.verbose: print "XRefCompiler: Reading",file
try:
f = open(file, 'rt')
except IOError, e:
if self.verbose: print "Error opening %s: %s. Skipping."%(file, e)
continue
lines = f.readlines()
f.close()
for line in lines:
target, file, line, scope, context = string.split(line)
target = tuple(map(intern, string.split(urllib.unquote(target), '\t')))
scope = map(intern, string.split(urllib.unquote(scope), '\t'))
line = int(line)
file = intern(file)
if no_locals:
bad = 0
for i in range(len(target)):
if len(target[i]) > 0 and target[i][0] == '`':
# Don't store local function variables
bad = 1
break
if bad: continue
for i in range(len(scope)):
if len(scope[i]) > 0 and scope[i][0] == '`':
# Function scope, truncate here
del scope[i+1:]
scope[i] = scope[i][1:]
break
scope = tuple(scope)
target_data = data.setdefault(target, [[],[],[]])
if context == 'DEF':
target_data[0].append( (file, line, scope) )
elif context == 'CALL':
target_data[1].append( (file, line, scope) )
elif context == 'REF':
target_data[2].append( (file, line, scope) )
else:
print "Warning: Unknown context:",context
# Sort the data
for target, target_data in data.items():
target_data[1].sort()
target_data[2].sort()
name = target[-1]
index.setdefault(name,[]).append(target)
# If it's a function name, also add without the parameters
paren = name.find('(')
if paren != -1:
index.setdefault(name[:paren],[]).append(target)
if self.verbose: print "XRefCompiler: Writing",output
f = open(output, 'wb')
cPickle.dump(file_data, f)
f.close()
|