Commit 313d4f4ca675ca751bfa8b74fd3728fc81671883

suzuki toshiya 2009-07-13T00:01:57

Add a script to check the undefined and unused trace macros.

diff --git a/ChangeLog b/ChangeLog
index 53d474d..be8815c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2009-07-12  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
+	Add a script to check the undefined and unused trace macros.
+
+	* src/tools/chktrcmp.py: A script to check trace_XXXX macros
+	that are used in C source but undefined in fttrace.h, or
+	defined in fttrace.h but unused in C sources.  See
+	http://lists.gnu.org/archive/html/freetype-devel/2009-07/msg00013.html.
+	* docs/DEBUG: Mention on chktrcmp.py.
+	* docs/release: Ditto.
+
 2009-07-09  Werner Lemberg  <wl@gnu.org>
 
 	[ftraster] Make it compile again with -D_STANDALONE_.
diff --git a/docs/DEBUG b/docs/DEBUG
index 1fccc21..3d6acd3 100644
--- a/docs/DEBUG
+++ b/docs/DEBUG
@@ -92,7 +92,10 @@ its code:
 
     The  value  of  the  FT_COMPONENT  macro  is  an  enumeration  named
     trace_XXXX where XXXX  is one of the component  names defined in the
-    internal file `freetype/internal/fttrace.h'.
+    internal file `freetype/internal/fttrace.h'.  If you modify FreeType
+    source  and insert  new trace_XXXX macro,  you  must register  it in
+    fttrace.h. If you insert or remove many trace macros,  you can check
+    the undefined or the unused trace macro by src/tools/chktrcmp.py.
 
     Each  such component  is assigned  a `debug  level', ranging  from 0
     to  7,  through  the  use  of  the  FT2_DEBUG  environment  variable
@@ -186,7 +189,7 @@ behaviour of FreeType at runtime.
 
 ------------------------------------------------------------------------
 
-Copyright 2002, 2003, 2004, 2005 by
+Copyright 2002, 2003, 2004, 2005, 2009 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part  of the  FreeType  project, and  may  only be  used,
diff --git a/docs/release b/docs/release
index e93f430..c6a535b 100644
--- a/docs/release
+++ b/docs/release
@@ -33,6 +33,8 @@ How to prepare a new release
 
 . Test C++ compilation for ft2demos too.
 
+. Run src/tools/chktrcmp.py and check no undefined trace_XXXX macros.
+
 . Tag the CVS (freetype2, ft2demos).
 
   TODO: Tag the home page CVS on savannah.nongnu.org.
@@ -153,7 +155,7 @@ How to prepare a new release
 
 ----------------------------------------------------------------------
 
-Copyright 2003, 2005, 2006, 2007 by
+Copyright 2003, 2005, 2006, 2007, 2009 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/src/tools/chktrcmp.py b/src/tools/chktrcmp.py
new file mode 100755
index 0000000..d0f342e
--- /dev/null
+++ b/src/tools/chktrcmp.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Check trace components in FreeType 2 source.
+# Author: suzuki toshiya, 2009
+#
+# This code is explicitly into the public domain.
+
+
+import sys
+import os
+import re
+
+SRC_FILE_LIST   = []
+USED_COMPONENT  = {}
+KNOWN_COMPONENT = {}
+
+SRC_FILE_DIRS   = [ "src" ]
+TRACE_DEF_FILES = [ "include/freetype/internal/fttrace.h" ]
+
+
+# --------------------------------------------------------------
+# Parse command line options
+#
+
+for i in range( 1, len( sys.argv ) ):
+  if sys.argv[i].startswith( "--help" ):
+    print "Usage: %s [option]" % sys.argv[0]
+    print "Search used-but-defined and defined-but-not-used trace_XXX macros"
+    print ""
+    print "  --help:"
+    print "        Show this help"
+    print ""
+    print "  --src-dirs=dir1:dir2:..."
+    print "        Specify the directories of C source files to be checked"
+    print "        Default is %s" % ":".join( SRC_FILE_DIRS )
+    print ""
+    print "  --def-files=file1:file2:..."
+    print "        Specify the header files including FT_TRACE_DEF()"
+    print "        Default is %s" % ":".join( TRACE_DEF_FILES )
+    print ""
+    exit(0)
+  if sys.argv[i].startswith( "--src-dirs=" ):
+    SRC_FILE_DIRS = sys.argv[i].replace( "--src-dirs=", "", 1 ).split( ":" )
+  elif sys.argv[i].startswith( "--def-files=" ):
+    TRACE_DEF_FILES = sys.argv[i].replace( "--def-files=", "", 1 ).split( ":" )
+
+
+# --------------------------------------------------------------
+# Scan C source and header files using trace macros.
+#
+
+c_pathname_pat = re.compile( '^.*\.[ch]$', re.IGNORECASE )
+trace_use_pat  = re.compile( '^[ \t]*#define[ \t]+FT_COMPONENT[ \t]+trace_' )
+
+for d in SRC_FILE_DIRS:
+  for ( p, dlst, flst ) in os.walk( d ):
+    for f in flst:
+      if c_pathname_pat.match( f ) != None:
+        src_pathname = os.path.join( p, f )
+
+        line_num = 0
+        for src_line in open( src_pathname, 'r' ):
+          line_num = line_num + 1
+          src_line = src_line.strip()
+          if trace_use_pat.match( src_line ) != None:
+            component_name = trace_use_pat.sub( '', src_line )
+            if component_name in USED_COMPONENT:
+              USED_COMPONENT[component_name].append( "%s:%d" % ( src_pathname, line_num ) )
+            else:
+              USED_COMPONENT[component_name] = [ "%s:%d" % ( src_pathname, line_num ) ]
+
+
+# --------------------------------------------------------------
+# Scan header file(s) defining trace macros.
+#
+
+trace_def_pat_opn = re.compile( '^.*FT_TRACE_DEF[ \t]*\([ \t]*' )
+trace_def_pat_cls = re.compile( '[ \t\)].*$' )
+
+for f in TRACE_DEF_FILES:
+  line_num = 0
+  for hdr_line in open( f, 'r' ):
+    line_num = line_num + 1
+    hdr_line = hdr_line.strip()
+    if trace_def_pat_opn.match( hdr_line ) != None:
+      component_name = trace_def_pat_opn.sub( '', hdr_line )
+      component_name = trace_def_pat_cls.sub( '', component_name )
+      if component_name in KNOWN_COMPONENT:
+        print "trace component %s is defined twice, see %s and fttrace.h:%d" % \
+          ( component_name, KNOWN_COMPONENT[component_name], line_num )
+      else:
+        KNOWN_COMPONENT[component_name] = "%s:%d" % \
+          ( os.path.basename( f ), line_num )
+
+
+# --------------------------------------------------------------
+# Compare the used and defined trace macros.
+#
+
+print "# Trace component used in the implementations but not defined in fttrace.h."
+cmpnt = USED_COMPONENT.keys()
+cmpnt.sort()
+for c in cmpnt:
+  if c not in KNOWN_COMPONENT:
+    print "Trace component %s (used in %s) is not defined." % ( c, ", ".join( USED_COMPONENT[c] ) )
+
+print "# Trace component is defined but not used in the implementations."
+cmpnt = KNOWN_COMPONENT.keys()
+cmpnt.sort()
+for c in cmpnt:
+  if c not in USED_COMPONENT:
+    if c != "any":
+      print "Trace component %s (defined in %s) is not used." % ( c, KNOWN_COMPONENT[c] )
+