Add xref to populate an sqlite database with a program cross-reference
This commit is contained in:
192
site_ansto/xref.py
Executable file
192
site_ansto/xref.py
Executable file
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/python
|
||||
# vim: tabstop=8 softtabstop=4 shiftwidth=4 nocindent smartindent
|
||||
import os, sys
|
||||
import sqlite3
|
||||
|
||||
def setup_database():
|
||||
"""Create a database to hold the data"""
|
||||
global conn
|
||||
global curs
|
||||
if os.path.exists("xref.sqlite"):
|
||||
os.remove("xref.sqlite")
|
||||
conn = sqlite3.connect("xref.sqlite")
|
||||
curs = conn.cursor()
|
||||
curs.execute("CREATE TABLE libtab (name TEXT)")
|
||||
curs.execute("CREATE TABLE objtab (name TEXT, lib_id INTEGER)")
|
||||
curs.execute("CREATE INDEX objidx ON objtab ( name )")
|
||||
curs.execute("CREATE TABLE symtab (name TEXT, usage CHAR, obj_id INTEGER)")
|
||||
curs.execute("CREATE INDEX symidx ON symtab ( name )")
|
||||
curs.execute("CREATE VIEW defs AS SELECT DISTINCT s.name sym, s.obj_id mod FROM symtab s WHERE s.usage != 'U'");
|
||||
curs.execute("CREATE VIEW refs AS SELECT DISTINCT s.name sym, s.obj_id mod FROM symtab s WHERE s.usage = 'U'");
|
||||
curs.execute("""CREATE VIEW v AS SELECT distinct a.name from_name, b.name to_name
|
||||
FROM defs, refs, objtab a, objtab b
|
||||
WHERE refs.mod = a.rowid and refs.sym = defs.sym and defs.mod = b.rowid and refs.mod != defs.mod
|
||||
""")
|
||||
curs.execute("""CREATE VIEW vnum AS SELECT distinct a.name from_name, b.name to_name, defs.sym sym
|
||||
FROM defs, refs, objtab a, objtab b
|
||||
WHERE refs.mod = a.rowid and refs.sym = defs.sym and defs.mod = b.rowid and refs.mod != defs.mod
|
||||
""")
|
||||
|
||||
def get_one_object(arg):
|
||||
line = arg.strip()
|
||||
line = os.path.realpath(os.path.abspath(line))
|
||||
if line.endswith(".a"):
|
||||
head, tail = os.path.split(line)
|
||||
if libraries.has_key(tail):
|
||||
if head in libraries[tail]:
|
||||
print "Skipping duplicate library:", line
|
||||
else:
|
||||
libraries[tail].append(head)
|
||||
else:
|
||||
libraries[tail] = [head]
|
||||
elif line.endswith(".o"):
|
||||
head, tail = os.path.split(line)
|
||||
if objects.has_key(tail):
|
||||
if head in objects[tail]:
|
||||
print "Skipping duplicate object:", line
|
||||
else:
|
||||
objects[tail].append(head)
|
||||
else:
|
||||
objects[tail] = [head]
|
||||
else:
|
||||
print "Unknown file type:", line
|
||||
|
||||
|
||||
def get_objects(arg):
|
||||
"""Get all .a and .o files into libraries and objects"""
|
||||
global libraries
|
||||
global objects
|
||||
if os.path.isfile(arg):
|
||||
get_one_object(arg)
|
||||
return
|
||||
if os.path.isdir(arg):
|
||||
lines = os.popen("find -H " + arg + " -name *.a -o -name *.o")
|
||||
for line in lines:
|
||||
get_one_object(line)
|
||||
else:
|
||||
print "Unrecognised argument:", arg
|
||||
|
||||
def report_duplicates():
|
||||
"""report all duplicate libraries and objects"""
|
||||
global libraries
|
||||
global objects
|
||||
for lib in libraries.keys():
|
||||
if len(libraries[lib]) > 1:
|
||||
print "Duplicate Library:", str(len(libraries[lib])), lib, libraries[lib]
|
||||
for obj in objects.keys():
|
||||
if len(objects[obj]) > 1:
|
||||
print "Duplicate Object:", str(len(objects[obj])), obj, objects[obj]
|
||||
|
||||
def process_library(path, lib):
|
||||
global dict_fm
|
||||
global dict_sm
|
||||
global dict_sf
|
||||
arg = os.path.join(path, lib)
|
||||
print 'lib -> ', arg
|
||||
curs.execute("insert into libtab values (:1)", (arg,))
|
||||
lib_id = curs.lastrowid
|
||||
conn.commit()
|
||||
for line in os.popen('nm ' + arg):
|
||||
while len(line) > 0 and (line[-1] in (' ', '\n', '\r')):
|
||||
line = line[0:-1]
|
||||
if len(line) > 0:
|
||||
if line[-1] == ':':
|
||||
file = line[0:-1]
|
||||
file_path = os.path.join(path, file)
|
||||
curs.execute("insert into objtab values (:1, :2)", (file_path, lib_id))
|
||||
obj_id = curs.lastrowid
|
||||
dict_fm[os.path.split(file)[1]] = os.path.split(arg)[1]
|
||||
remove_object(path, file)
|
||||
elif len(line) > 10:
|
||||
value = line[0:8]
|
||||
tag = line[9:10]
|
||||
name = line[11:]
|
||||
if tag in ("B", "D", "G", "R", "S", "T", "U"):
|
||||
curs.execute("insert into symtab values (:1, :2, :3)", (name, tag, obj_id))
|
||||
if not tag == 'U':
|
||||
dict_sf[name] = os.path.split(file)[1]
|
||||
dict_sm[name] = os.path.split(arg)[1]
|
||||
conn.commit()
|
||||
|
||||
def process_libraries():
|
||||
for lib in libraries.keys():
|
||||
for path in libraries[lib]:
|
||||
process_library(path, lib)
|
||||
|
||||
def process_object(path, obj):
|
||||
global dict_sf
|
||||
arg = os.path.join(path, obj)
|
||||
print 'obj -> ', arg
|
||||
file = arg
|
||||
curs.execute("insert into objtab values (:1, :2)", (file, 0))
|
||||
obj_id = curs.lastrowid
|
||||
conn.commit()
|
||||
for line in os.popen('nm ' + arg):
|
||||
while len(line) > 0 and (line[-1] in (' ', '\n', '\r')):
|
||||
line = line[0:-1]
|
||||
if len(line) > 10:
|
||||
value = line[0:8]
|
||||
tag = line[9:10]
|
||||
name = line[11:]
|
||||
if tag in ("B", "D", "G", "R", "S", "T", "U"):
|
||||
curs.execute("insert into symtab values (:1, :2, :3)", (name, tag, obj_id))
|
||||
if not tag == 'U':
|
||||
dict_sf[name] = os.path.split(file)[1]
|
||||
conn.commit()
|
||||
|
||||
def remove_object(path, file):
|
||||
if objects.has_key(file):
|
||||
del objects[file]
|
||||
# if len(objects[file]) == 1 and objects[file][0] == path:
|
||||
# del objects[file]
|
||||
# elif path in objects[file]:
|
||||
# del objects[file][objects[file].index(path)]
|
||||
|
||||
def process_objects():
|
||||
for obj in objects.keys():
|
||||
for path in objects[obj]:
|
||||
process_object(path, obj)
|
||||
|
||||
|
||||
args = sys.argv
|
||||
progname = args[0]
|
||||
del args[0]
|
||||
print 'prog ->', progname
|
||||
print 'args ->', args
|
||||
|
||||
setup_database()
|
||||
|
||||
libraries = {}
|
||||
objects = {}
|
||||
dict_sf = {}
|
||||
dict_sm = {}
|
||||
dict_fm = {}
|
||||
|
||||
for arg in args:
|
||||
get_objects(arg)
|
||||
report_duplicates()
|
||||
|
||||
print "Libraries:", libraries
|
||||
|
||||
process_libraries()
|
||||
|
||||
print "Objects:", objects
|
||||
|
||||
process_objects()
|
||||
|
||||
conn.commit()
|
||||
|
||||
#graph = {}
|
||||
#build_graph()
|
||||
#plot_modules()
|
||||
|
||||
#print "dict_sf = ", dict_sf
|
||||
#print "dict_sm = ", dict_sm
|
||||
#print "dict_fm = ", dict_fm
|
||||
|
||||
|
||||
if dict_sf.has_key("main"):
|
||||
print "main is in file", dict_sf["main"]
|
||||
if dict_sm.has_key("main"):
|
||||
print "main is in library", dict_sm["main"]
|
||||
|
||||
Reference in New Issue
Block a user