1#!/usr/bin/env python 2# 3# Check trace components in FreeType 2 source. 4# Author: suzuki toshiya, 2009, 2013 5# 6# This code is explicitly into the public domain. 7 8 9import sys 10import os 11import re 12 13SRC_FILE_LIST = [] 14USED_COMPONENT = {} 15KNOWN_COMPONENT = {} 16 17SRC_FILE_DIRS = [ "src" ] 18TRACE_DEF_FILES = [ "include/internal/fttrace.h" ] 19 20 21# -------------------------------------------------------------- 22# Parse command line options 23# 24 25for i in range( 1, len( sys.argv ) ): 26 if sys.argv[i].startswith( "--help" ): 27 print "Usage: %s [option]" % sys.argv[0] 28 print "Search used-but-defined and defined-but-not-used trace_XXX macros" 29 print "" 30 print " --help:" 31 print " Show this help" 32 print "" 33 print " --src-dirs=dir1:dir2:..." 34 print " Specify the directories of C source files to be checked" 35 print " Default is %s" % ":".join( SRC_FILE_DIRS ) 36 print "" 37 print " --def-files=file1:file2:..." 38 print " Specify the header files including FT_TRACE_DEF()" 39 print " Default is %s" % ":".join( TRACE_DEF_FILES ) 40 print "" 41 exit(0) 42 if sys.argv[i].startswith( "--src-dirs=" ): 43 SRC_FILE_DIRS = sys.argv[i].replace( "--src-dirs=", "", 1 ).split( ":" ) 44 elif sys.argv[i].startswith( "--def-files=" ): 45 TRACE_DEF_FILES = sys.argv[i].replace( "--def-files=", "", 1 ).split( ":" ) 46 47 48# -------------------------------------------------------------- 49# Scan C source and header files using trace macros. 50# 51 52c_pathname_pat = re.compile( '^.*\.[ch]$', re.IGNORECASE ) 53trace_use_pat = re.compile( '^[ \t]*#define[ \t]+FT_COMPONENT[ \t]+trace_' ) 54 55for d in SRC_FILE_DIRS: 56 for ( p, dlst, flst ) in os.walk( d ): 57 for f in flst: 58 if c_pathname_pat.match( f ) != None: 59 src_pathname = os.path.join( p, f ) 60 61 line_num = 0 62 for src_line in open( src_pathname, 'r' ): 63 line_num = line_num + 1 64 src_line = src_line.strip() 65 if trace_use_pat.match( src_line ) != None: 66 component_name = trace_use_pat.sub( '', src_line ) 67 if component_name in USED_COMPONENT: 68 USED_COMPONENT[component_name].append( "%s:%d" % ( src_pathname, line_num ) ) 69 else: 70 USED_COMPONENT[component_name] = [ "%s:%d" % ( src_pathname, line_num ) ] 71 72 73# -------------------------------------------------------------- 74# Scan header file(s) defining trace macros. 75# 76 77trace_def_pat_opn = re.compile( '^.*FT_TRACE_DEF[ \t]*\([ \t]*' ) 78trace_def_pat_cls = re.compile( '[ \t\)].*$' ) 79 80for f in TRACE_DEF_FILES: 81 line_num = 0 82 for hdr_line in open( f, 'r' ): 83 line_num = line_num + 1 84 hdr_line = hdr_line.strip() 85 if trace_def_pat_opn.match( hdr_line ) != None: 86 component_name = trace_def_pat_opn.sub( '', hdr_line ) 87 component_name = trace_def_pat_cls.sub( '', component_name ) 88 if component_name in KNOWN_COMPONENT: 89 print "trace component %s is defined twice, see %s and fttrace.h:%d" % \ 90 ( component_name, KNOWN_COMPONENT[component_name], line_num ) 91 else: 92 KNOWN_COMPONENT[component_name] = "%s:%d" % \ 93 ( os.path.basename( f ), line_num ) 94 95 96# -------------------------------------------------------------- 97# Compare the used and defined trace macros. 98# 99 100print "# Trace component used in the implementations but not defined in fttrace.h." 101cmpnt = USED_COMPONENT.keys() 102cmpnt.sort() 103for c in cmpnt: 104 if c not in KNOWN_COMPONENT: 105 print "Trace component %s (used in %s) is not defined." % ( c, ", ".join( USED_COMPONENT[c] ) ) 106 107print "# Trace component is defined but not used in the implementations." 108cmpnt = KNOWN_COMPONENT.keys() 109cmpnt.sort() 110for c in cmpnt: 111 if c not in USED_COMPONENT: 112 if c != "any": 113 print "Trace component %s (defined in %s) is not used." % ( c, KNOWN_COMPONENT[c] ) 114 115