Macroscope gets refactored in preparation for doing more with it.

This commit is contained in:
Eric S. Raymond 2007-04-06 03:10:35 +00:00
parent 7f08591791
commit a761acd429

View file

@ -5,58 +5,72 @@
# By Eric S. Raymond April 2007.
# (Yes, this *is* named after an ancient Piers Anthony novel.)
import os, time, re
import sys, os, time, re
print "Macroscope cross-reference report on %s" % time.ctime()
class macro_cross_reference:
def __init__(self, filelist):
self.gather_macro_definitions(filelist)
def gather_macro_definitions(self, filelist):
"Collect macro definitions from a specified filelist."
self.xref = {}
for filename in filelist:
dfp = open(filename)
for (n, line) in enumerate(dfp):
if line.startswith("#define"):
tokens = line.split()
name = tokens[1]
if name in self.xref:
print >>sys.stderr, "*** Warning: duplicate definition of %s from %s:%d at %s:%d\n" \
% (self.xref[name][0], self.xref[name][1], name, filename, n+1)
self.xref[name] = (filename, n+1, {})
dfp.close()
return self.xref
def check_macro_references(self, filelist):
"Decorate definitions with all references from a specified filelist."
for filename in filelist:
rfp = open(filename)
for (n, line) in enumerate(rfp):
if line[0] == "#" or "{" not in line:
continue
for name in self.xref:
if re.search("{" + name + r"\b", line):
namedict = self.xref[name][2]
if filename not in namedict:
namedict[filename] = []
namedict[filename].append(n+1)
rfp.close()
def dump(self):
"Report the crossreference."
for (name, (filename, n, references)) in self.xref.items():
print "Macro %s is defined at %s:%d, used in %d files:" % (name, filename, n, len(references))
for (file, linenumbers) in references.items():
print " %s: %s" % (file, `linenumbers`[1:-1])
print "# Macroscope reporting on %s" % time.ctime()
# This assumes we're being called from our source-tree location
datadir = os.path.join(*os.path.split(os.getcwd())[:-1])
print "Data directory is: %s" % datadir
# Get the names of all files in the data subdirectory.
# Chdir to there first so we can deal in relative pathnames.
datafiles = []
os.chdir(datadir)
definitions = map(lambda x: os.path.join("utils", x),
filter(lambda x: x.endswith(".cfg"),
os.listdir(os.path.join(datadir, "utils"))))
#print "Definition files: %s" % `definitions`[1:-1]
# Gather definition locations from the definition files
xref = {}
for filename in definitions:
dfp = open(os.path.join(datadir, filename))
for (n, line) in enumerate(dfp):
if line.startswith("#define"):
tokens = line.split()
name = tokens[1]
if name in xref:
print "*** Warning: duplicate definition of %s from %s:%d at %s:%d\n" \
% (xref[name][0], xref[name][1], name, filename, n+1)
xref[name] = (filename, n+1, {})
dfp.close()
# Get the names of the files we need to check
cfgfiles = []
os.path.walk(".",
lambda arg, dir, names: cfgfiles.extend(map(lambda x: os.path.join(dir,x), names)),
lambda arg, dir, names: datafiles.extend(map(lambda x: os.path.normpath(os.path.join(dir,x)), names)),
None)
cfgfiles = filter(lambda x: x.endswith(".cfg"), cfgfiles)
datafiles = filter(lambda x: ".svn" not in x, datafiles)
#print "Data files: %s" % `datafiles`[1:-1]
# Now build the cross-reference
for filename in cfgfiles:
rfp = open(filename)
for (n, line) in enumerate(rfp):
if line[0] == "#" or "{" not in line:
continue
for name in xref:
if re.search("{" + name + r"\b", line):
namedict = xref[name][2]
if filename not in namedict:
namedict[filename] = []
namedict[filename].append(n+1)
rfp.close()
# Get the names of all WML files.
cfgfiles = filter(lambda x: x.endswith(".cfg"), datafiles)
# Dump it.
for (name, (filename, n, references)) in xref.items():
print "Macro %s is defined at %s:%d, used in %d files:" % (name, filename, n, len(references))
for (file, linenumbers) in references.items():
print " %s: %s" % (file, `linenumbers`[1:-1])
# Get the names of all utility-macro definition files
utilsfiles = filter(lambda x: x.startswith("utils"), cfgfiles)
print "Definition files: %s" % `utilsfiles`[1:-1]
# Check definitions in the utils directory against references everywhere
xref = macro_cross_reference(utilsfiles)
xref.check_macro_references(cfgfiles)
xref.dump()