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