see Changelog
[mining-tools:carnarvon.git] / pycarnarvon / Functions.py
1 import os
2
3 class Function:
4
5     created_functions = {}
6     version_functions = {}
7
8     # select count(revision), revision, a.file_id, f.start_line, f.end_line 
9     # from annotates_2006_08_04 as a, functions as f 
10     # where a.line_id>f.start_line and a.line_id<f.end_line and a.file_id=f.file_id and f.function_id=1 
11     # group by revision;
12
13     def getCommandOutput(self, cmd):
14
15         pipe = os.popen(cmd)
16         output = pipe.readlines()
17         pipe.close()
18
19         return output
20
21     def getFunctions(self, filename):
22
23         filepath = filename
24         cmd = "exctags --c-kinds=f -x "+filepath
25         output_list = self.getCommandOutput(cmd)
26
27         header_lines = []
28         headers = []
29         names = []
30
31         for line in output_list:
32
33             tokens = line.split(' ')
34             # Remove empty tokens
35             non_empty = []
36             for t in tokens:
37                 if t != '':
38                     non_empty.append(t)
39
40             name = non_empty[0]
41             line = non_empty[2]
42             header = non_empty[4]
43
44             names.append(name)
45             header_lines.append(line)
46             headers.append(header)
47
48         return header_lines, headers, names
49
50     def searchForBeginAndEnd(self, header_line, filename):
51
52         filepath = filename
53         fileobj = open(filepath,'r')
54         content = fileobj.readlines()
55         fileobj.close()
56
57         header_line =int(header_line)
58
59         rest_of_file = content[header_line - 1:]
60         open_keys = 0
61         closed_keys = 0
62
63         current_line = header_line
64         starting_line = header_line
65         closing_line = header_line
66         code = ""
67
68         for line in rest_of_file:
69
70             # Let's count the open and closed keys per line
71             if line.find("{") != -1:
72                 open_keys += 1
73
74                 if 1 == open_keys:
75                     starting_line = current_line
76
77             if line.find("}") != -1:
78                 closed_keys += 1
79
80             # Once we have found the opening key, if the numer of
81             # open and closed is the same, the function end has been found
82             if open_keys >= 1:
83
84                 code += line
85
86                 if open_keys == closed_keys:
87                     closing_line = current_line
88                     break
89
90             current_line += 1
91
92         return starting_line, closing_line, code
93
94     def functions2sql(db):
95         count = 0
96         fkeys = Function.created_functions.keys()
97
98         for f in fkeys:
99             file_id = Function.created_functions[f][0]
100             fstart = Function.created_functions[f][1]
101             fend = Function.created_functions[f][2]
102             query = "INSERT INTO functions (function_id, file_id, start_line, end_line) "
103             query += " VALUES ('" + str(count) + "','"
104             query += str(file_id) + "','"
105             query += str(fstart) + "','"
106             query += str(fend) + "');"
107             count += 1
108
109             db.insertData(query)
110
111     def __init__(self, filename, file_id):
112
113         header_lines, headers, names = self.getFunctions(filename)
114         for i in range(len(header_lines)):
115             header_line = header_lines[i]
116             header = headers[i]
117             name = names[i]
118
119             begin_line, end_line, code = self.searchForBeginAndEnd(header_line, filename)
120             #print filename + "    -> Function "+ name + " " + str(begin_line) + " "  + str(end_line)
121             Function.created_functions[name] = [file_id, begin_line, end_line]
122
123     functions2sql = staticmethod(functions2sql)