Author: esr
Date: Sun Apr 8 00:30:54 2007
New Revision: 16681
URL: http://svn.gna.org/viewcvs/wesnoth?rev=16681&view=rev
Log:
Macroscope can now process multiple directories specified on the command line,
and so can be used for UMC.
I've added a Makefile to data/tools that invokes this in several ways
useful for performing sanity checks.
Added:
trunk/data/tools/Makefile
Modified:
trunk/data/tools/macroscope
Added: trunk/data/tools/Makefile
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/data/tools/Makefile?rev=16681&view=auto
==============================================================================
--- trunk/data/tools/Makefile (added)
+++ trunk/data/tools/Makefile Sun Apr 8 00:30:54 2007
@@ -1,0 +1,17 @@
+# Recipes for various sanity checks.
+
+utils-unused:
+ @echo "Report on unused utility macros"
+ cd ../..; data/tools/macroscope --crossreference --from data/utils
--refcount 0 data
+
+utils-macros:
+ @echo "Report on usage of utility macros"
+ cd ../..; data/tools/macroscope --crossreference --from data/utils data
+
+all-macros:
+ @echo "Report on usage of all macros"
+ cd ../..; data/tools/macroscope --crossreference data
+
+unresolved-macros:
+ @echo "Report on unresolved macro calls"
+ cd ../..; data/tools/macroscope --unresolved data
Modified: trunk/data/tools/macroscope
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/data/tools/macroscope?rev=16681&r1=16680&r2=16681&view=diff
==============================================================================
--- trunk/data/tools/macroscope (original)
+++ trunk/data/tools/macroscope Sun Apr 8 00:30:54 2007
@@ -7,34 +7,16 @@
import sys, os, time, re, getopt
-def allfiles(dir):
- "Get the names of all files under dir, ignoring .svn directories."
+def allfiles(dirpath):
+ "Get the names of all files under dirpath, ignoring .svn directories."
datafiles = []
- os.chdir(dir) # So we can deal in relative pathnames.
- os.path.walk(".",
- lambda arg, dir, names: datafiles.extend(map(lambda x:
os.path.normpath(os.path.join(dir,x)), names)),
- None)
- return filter(lambda x: ".svn" not in x, datafiles)
-
-def initialize(verbose):
- "Prepare for crosschecks."
- # This assumes we're being called from our source-tree location
- datadir = os.path.join(*os.path.split(os.getcwd())[:-1])
- if verbose:
- print "# Data directory is: %s" % datadir
-
- datafiles = allfiles(datadir)
- #print "Data files: %s" % `datafiles`[1:-1]
-
- # Get the names of all WML files.
- cfgfiles = filter(lambda x: x.endswith(".cfg"), datafiles)
-
- # Get the names of all utility-macro definition files
- utilsfiles = filter(lambda x: x.startswith("utils"), cfgfiles)
- if verbose:
- print "Definition files: %s" % `utilsfiles`[1:-1]
-
- return (datafiles, cfgfiles, utilsfiles)
+ for dir in dirpath:
+ os.path.walk(dir,
+ lambda arg, dir, names: datafiles.extend(map(lambda x:
os.path.normpath(os.path.join(dir,x)), names)),
+ None)
+ datafiles = filter(lambda x: ".svn" not in x, datafiles)
+ datafiles = filter(lambda x: not os.path.isdir(x), datafiles)
+ return datafiles
class reference:
"Describes a location by file and line."
@@ -48,11 +30,8 @@
return self.filebame
class macro_cross_reference:
- def __init__(self, fromlist, tolist):
- self.gather_macro_definitions(fromlist)
- self.check_macro_references(tolist)
- def gather_macro_definitions(self, filelist):
- "Collect macro definitions from a specified filelist."
+ def __init__(self, filelist):
+ # First, collect macro definitions from the specified filelist."
self.xref = {}
for filename in filelist:
dfp = open(filename)
@@ -62,16 +41,16 @@
name = tokens[1]
here = reference(filename, n+1)
if name in self.xref:
- print >>sys.stderr, "*** Warning: duplicate definition
of %s from %s, at %s\n" \
+ print >>sys.stderr, "*** Warning: duplicate definition
of %s from %s, at %s" \
% (name, self.xref[name][0], here)
self.xref[name] = (here, {})
dfp.close()
- return self.xref
- def check_macro_references(self, filelist):
- "Decorate definitions with all references from a specified filelist."
+ # Next, decorate definitions with all references from the filelist.
self.unresolved = []
formals = []
for filename in filelist:
+ if not filename.endswith(".cfg"):
+ continue
rfp = open(filename)
for (n, line) in enumerate(rfp):
if line.startswith("#define"):
@@ -106,7 +85,7 @@
print "Macro %s defined at %s is used in %d files:" % (name,
defloc, nrefs)
for (file, linenumbers) in references.items():
print " %s: %s" % (file, `linenumbers`[1:-1])
- def unrefdump(self):
+ def unresdump(self):
"Report dangling references."
if len(self.unresolved) == 0:
print "# No unresolved references"
@@ -116,57 +95,56 @@
print "%s at %s" % (name, reference)
if __name__ == "__main__":
- print "# Macroscope reporting on %s" % time.ctime()
+ def help():
+ sys.stderr.write("""\
+Usage: macroscope [options] sourcedirpath targetdirpath
+ Options may be any of these:
+ -h, --help Emit this help message
+ -b dir, --basedir=dir Set base directory for relative paths
+ -c, --crossreference Report target-to-source references
+ -u, --unresolved Report sourcepath macros unresolved in targetpath
+ -r ddd, --refcount=ddd Report only on macros w/refs in ddd files
+""")
+
# Process options
- (options, arguments) = getopt.getopt(sys.argv[1:], "mn:N:uv")
- verbose = False
+ (options, arguments) = getopt.getopt(sys.argv[1:], "cf:hr:u",
+ ['help',
+ 'crossreference', 'unresolved',
+ 'from=', 'refcount='])
+ crossreference = unresolved = False
+ from_restrict = None
+ refcount_restrict = None
for (switch, val) in options:
- if (switch == '-m'):
- print "# Checking macro definitions from anywhere"
- print "# against macro references from anywhere."
- print "# Output will list unused macros and undefined references."
- (datafiles, cfgfiles, utilsfiles) = initialize(verbose)
- xref = macro_cross_reference(cfgfiles, cfgfiles)
- print "# Unused macros:"
- xref.xrefdump(lambda n, d, r: len(r) == 0)
- xref.unrefdump()
+ if switch in ('-h', '--help'):
+ help()
sys.exit(0)
- elif (switch == '-n'):
- print "# Checking macro definitions in the utils directory"
- print "# against macro references from anywhere."
- c = int(val)
- print "# Output reports on util macros used in only %d file(s)."% c
- (datafiles, cfgfiles, utilsfiles) = initialize(verbose)
- xref = macro_cross_reference(utilsfiles, cfgfiles)
- xref.xrefdump(lambda n, d, r: len(r) == c)
- sys.exit(0)
- elif (switch == '-N'):
- print "# Checking macro definitions anywhere"
- print "# against macro references from anywhere."
- c = int(val)
- print "# Output reports on all macros used in only %d file(s)."% c
- (datafiles, cfgfiles, utilsfiles) = initialize(verbose)
- xref = macro_cross_reference(cfgfiles, cfgfiles)
- xref.xrefdump(lambda n, d, r: len(r) == c)
- sys.exit(0)
- elif (switch == '-u'):
- print "# Checking macro definitions in the utils directory"
- print "# against macro references from anywhere."
- print "# Output will be a full reference report."
- (datafiles, cfgfiles, utilsfiles) = initialize(verbose)
- xref = macro_cross_reference(utilsfiles, cfgfiles)
- xref.xrefdump()
- sys.exit(0)
- elif (switch == '-u'):
- verbose = True
- # We get here if user didn't pick a valid mode option
- print """
-Usage: macroscope [-v] {-m | -n | -N ddd | -u ddd}
- -m = Report unused macros and undefined references.
- -n ddd = Report on util macros used exactly a specified number of times
- -N ddd = Report on any macros used exactly a specified number of times
- -u = Full reference report on utils macros
- -v = set verbose mode, dumping some intermediate results
-"""
- sys.exit(1)
+ if switch in ('-f', '--from'):
+ from_restrict = val
+ elif switch in ('-c', '--crossreference'):
+ crossreference = True
+ elif switch in ('-u', '--unresolved'):
+ unresolved = True
+ elif switch in ('-r', '--refcount'):
+ refcount_restrict = 0
+ if len(arguments) != 1:
+ help()
+ sys.exit(1)
+ dirpath = arguments[0].split(";")
+ print "# Macroscope reporting on %s" % time.ctime()
+ print "# Working directory: %s" % os.getcwd()
+ print "# Directory path: %s" % dirpath
+ files = allfiles(dirpath)
+ if crossreference or unresolved:
+ xref = macro_cross_reference(allfiles(dirpath))
+ def predicate(name, defloc, references):
+ if from_restrict and not defloc.filename.startswith(from_restrict):
+ return False
+ if refcount_restrict!=None and len(references)!=refcount_restrict:
+ return False
+ return True
+ if crossreference:
+ xref.xrefdump(predicate)
+ if unresolved:
+ xref.unresdump()
+
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits