File: XRefCompiler.py

package info (click to toggle)
synopsis 0.8.0-5
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 10,112 kB
  • ctags: 12,996
  • sloc: cpp: 34,254; ansic: 33,620; python: 10,975; sh: 7,261; xml: 6,369; makefile: 773; asm: 445
file content (119 lines) | stat: -rw-r--r-- 3,933 bytes parent folder | download | duplicates (2)
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()