ARM: removing support for etb/etm in "arch/arm/kernel/"
[linux-2.6-block.git] / scripts / checkkconfigsymbols.py
CommitLineData
24fe1f03
VR
1#!/usr/bin/env python
2
3"""Find Kconfig identifieres that are referenced but not defined."""
4
5# Copyright (C) 2014 Valentin Rothberg <valentinrothberg@gmail.com>
6# Copyright (C) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
7#
8# This program is free software; you can redistribute it and/or modify it
9# under the terms and conditions of the GNU General Public License,
10# version 2, as published by the Free Software Foundation.
11#
12# This program is distributed in the hope it will be useful, but WITHOUT
13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15# more details.
16
17
18import os
19import re
20from subprocess import Popen, PIPE, STDOUT
21
22# REGEX EXPRESSIONS
23OPERATORS = r"&|\(|\)|\||\!"
24FEATURE = r"\w*[A-Z]{1}\w*"
25CONFIG_DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*"
26EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+"
27STMT = r"^\s*(?:if|select|depends\s+on)\s+" + EXPR
28
29# REGEX OBJECTS
30REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$")
31REGEX_FEATURE = re.compile(r"(" + FEATURE + r")")
32REGEX_SOURCE_FEATURE = re.compile(r"(?:D|\W|\b)+CONFIG_(" + FEATURE + r")")
33REGEX_KCONFIG_DEF = re.compile(CONFIG_DEF)
34REGEX_KCONFIG_EXPR = re.compile(EXPR)
35REGEX_KCONFIG_STMT = re.compile(STMT)
36REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
37REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$")
38
39
40def main():
41 """Main function of this module."""
42 source_files = []
43 kconfig_files = []
44 defined_features = set()
45 referenced_features = dict()
46
47 # use 'git ls-files' to get the worklist
48 pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True)
49 (stdout, _) = pop.communicate() # wait until finished
50 if len(stdout) > 0 and stdout[-1] == "\n":
51 stdout = stdout[:-1]
52
53 for gitfile in stdout.rsplit("\n"):
54 if ".git" in gitfile or "ChangeLog" in gitfile or \
55 os.path.isdir(gitfile):
56 continue
57 if REGEX_FILE_KCONFIG.match(gitfile):
58 kconfig_files.append(gitfile)
59 else:
60 # All non-Kconfig files are checked for consistency
61 source_files.append(gitfile)
62
63 for sfile in source_files:
64 parse_source_file(sfile, referenced_features)
65
66 for kfile in kconfig_files:
67 parse_kconfig_file(kfile, defined_features, referenced_features)
68
69 print "Undefined symbol used\tFile list"
70 for feature in sorted(referenced_features):
71 if feature not in defined_features:
72 if feature.endswith("_MODULE"):
73 # Avoid false positives for kernel modules
74 if feature[:-len("_MODULE")] in defined_features:
75 continue
76 if "FOO" in feature or "BAR" in feature:
77 continue
78 files = referenced_features.get(feature)
79 print "%s:\t%s" % (feature, ", ".join(files))
80
81
82def parse_source_file(sfile, referenced_features):
83 """Parse @sfile for referenced Kconfig features."""
84 lines = []
85 with open(sfile, "r") as stream:
86 lines = stream.readlines()
87
88 for line in lines:
89 if not "CONFIG_" in line:
90 continue
91 features = REGEX_SOURCE_FEATURE.findall(line)
92 for feature in features:
93 if not REGEX_FILTER_FEATURES.search(feature):
94 continue
95 paths = referenced_features.get(feature, set())
96 paths.add(sfile)
97 referenced_features[feature] = paths
98
99
100def get_features_in_line(line):
101 """Return mentioned Kconfig features in @line."""
102 return REGEX_FEATURE.findall(line)
103
104
105def parse_kconfig_file(kfile, defined_features, referenced_features):
106 """Parse @kfile and update feature definitions and references."""
107 lines = []
108 skip = False
109
110 with open(kfile, "r") as stream:
111 lines = stream.readlines()
112
113 for i in range(len(lines)):
114 line = lines[i]
115 line = line.strip('\n')
116 line = line.split("#")[0] # Ignore Kconfig comments
117
118 if REGEX_KCONFIG_DEF.match(line):
119 feature_def = REGEX_KCONFIG_DEF.findall(line)
120 defined_features.add(feature_def[0])
121 skip = False
122 elif REGEX_KCONFIG_HELP.match(line):
123 skip = True
124 elif skip:
125 # Ignore content of help messages
126 pass
127 elif REGEX_KCONFIG_STMT.match(line):
128 features = get_features_in_line(line)
129 # Multi-line statements
130 while line.endswith("\\"):
131 i += 1
132 line = lines[i]
133 line = line.strip('\n')
134 features.extend(get_features_in_line(line))
135 for feature in set(features):
136 paths = referenced_features.get(feature, set())
137 paths.add(kfile)
138 referenced_features[feature] = paths
139
140
141if __name__ == "__main__":
142 main()