-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsdiff.py
More file actions
127 lines (108 loc) · 3.14 KB
/
sdiff.py
File metadata and controls
127 lines (108 loc) · 3.14 KB
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
120
121
122
123
124
125
# -*- coding: utf-8 -*-
# Semantic diff between C header files
# ------------------------------------
#
# This tool parses two sets of C header files to locate all
# declarations: variables, functions, defines, macros, and
# typedefs. It produces in output:
# - Symbols defined in one set and not the other
# - Symbols with a different definition in both sets
#
# All the parsing is done using `ctags`.
#
import os
import sys
import glob
class Symbol:
'''
Parse the output of:
ctags-universal --kinds-c=+pLl --fields=Sk -f- filename.h
and store it as named fields.
Useful to store a list of symbols found in a file to compare it against
another list of symbols to find diffs.
'''
def __init__(self, line):
toks=[x.strip() for x in line.split('\t')]
self.name=toks[0]
self.file=toks[1]
self.type=toks[3]
self.sig=None
if len(toks)>4:
self.sig = toks[4][10:]
self.found=0
def __str__(self):
s='[%s][%s][%s]' % (self.file, self.type, self.name)
if self.sig:
s+='%s' % self.sig
return s
def __repr__(self):
return self.__str__()
def __eq__(self, other):
return self.name==other.name and \
self.type==other.type and \
self.sig==other.sig
def compare(self, other):
eq=0
if self.name!=other.name:
eq+=1
if self.type!=other.type:
eq+=1
if self.sig!=other.sig:
eq+=1
return eq
def tagfile(filename):
syms=[]
p=os.popen('ctags-universal --kinds-c=+pLl --fields=Sk -f- '+filename, 'r')
for line in p.readlines():
s=Symbol(line)
syms.append(s)
p.close()
return syms
def tagdir(dirname):
symbols=[]
candidates=glob.glob(dirname+'/*.h')
candidates.sort()
for c in candidates:
symbols.extend(tagfile(c))
return symbols
def tag(name):
if not os.path.exists(name):
print('error: cannot find '+name)
return None
if os.path.isdir(name):
return tagdir(name)
if os.path.isfile(name):
return tagfile(name)
return None
if __name__=="__main__":
verbose=False
if '-v' in sys.argv:
verbose=True
sys.argv.remove('-v')
if len(sys.argv)!=3:
print(f'''
use: {sys.argv[0]} reference candidate
reference and candidate can either be a single
header file, or a directory containing header files.
No recursive sub-directory search is performed.
''')
raise SystemExit
# Parse reference headers
ref=tag(sys.argv[1])
print('-- reference: %d symbols' % len(ref))
if verbose:
for s in ref: print(s)
# Parse candidate headers
cand=tag(sys.argv[2])
print('-- candidate: %d symbols' % len(cand))
if verbose:
for s in cand: print(s)
# Loop on all symbols defined in ref
for s_ref in ref:
for s_can in cand:
if s_ref==s_can:
s_ref.found+=1
print(f'-- {sys.argv[1]} symbols missing or different in {sys.argv[2]}')
for s_ref in ref:
if s_ref.found<1:
print('\t', s_ref)