diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/checkkconfigsymbols.py | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index f9440891d048..e9cc689033fe 100644 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py | |||
| @@ -1,36 +1,31 @@ | |||
| 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
| 2 | 2 | ||
| 3 | """Find Kconfig identifieres that are referenced but not defined.""" | 3 | """Find Kconfig identifiers that are referenced but not defined.""" |
| 4 | 4 | ||
| 5 | # Copyright (C) 2014 Valentin Rothberg <valentinrothberg@gmail.com> | 5 | # (c) 2014 Valentin Rothberg <valentinrothberg@gmail.com> |
| 6 | # Copyright (C) 2014 Stefan Hengelein <stefan.hengelein@fau.de> | 6 | # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de> |
| 7 | # | 7 | # |
| 8 | # This program is free software; you can redistribute it and/or modify it | 8 | # Licensed under the terms of the GNU GPL License version 2 |
| 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 | 9 | ||
| 17 | 10 | ||
| 18 | import os | 11 | import os |
| 19 | import re | 12 | import re |
| 20 | from subprocess import Popen, PIPE, STDOUT | 13 | from subprocess import Popen, PIPE, STDOUT |
| 21 | 14 | ||
| 22 | # REGEX EXPRESSIONS | 15 | |
| 16 | # regex expressions | ||
| 23 | OPERATORS = r"&|\(|\)|\||\!" | 17 | OPERATORS = r"&|\(|\)|\||\!" |
| 24 | FEATURE = r"\w*[A-Z]{1}\w*" | 18 | FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}" |
| 25 | CONFIG_DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*" | 19 | DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*" |
| 26 | EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+" | 20 | EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+" |
| 27 | STMT = r"^\s*(?:if|select|depends\s+on)\s+" + EXPR | 21 | STMT = r"^\s*(?:if|select|depends\s+on)\s+" + EXPR |
| 22 | SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")" | ||
| 28 | 23 | ||
| 29 | # REGEX OBJECTS | 24 | # regex objects |
| 30 | REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") | 25 | REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") |
| 31 | REGEX_FEATURE = re.compile(r"(" + FEATURE + r")") | 26 | REGEX_FEATURE = re.compile(r"(" + FEATURE + r")") |
| 32 | REGEX_SOURCE_FEATURE = re.compile(r"(?:D|\W|\b)+CONFIG_(" + FEATURE + r")") | 27 | REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) |
| 33 | REGEX_KCONFIG_DEF = re.compile(CONFIG_DEF) | 28 | REGEX_KCONFIG_DEF = re.compile(DEF) |
| 34 | REGEX_KCONFIG_EXPR = re.compile(EXPR) | 29 | REGEX_KCONFIG_EXPR = re.compile(EXPR) |
| 35 | REGEX_KCONFIG_STMT = re.compile(STMT) | 30 | REGEX_KCONFIG_STMT = re.compile(STMT) |
| 36 | REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") | 31 | REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") |
| @@ -42,7 +37,7 @@ def main(): | |||
| 42 | source_files = [] | 37 | source_files = [] |
| 43 | kconfig_files = [] | 38 | kconfig_files = [] |
| 44 | defined_features = set() | 39 | defined_features = set() |
| 45 | referenced_features = dict() | 40 | referenced_features = dict() # {feature: [files]} |
| 46 | 41 | ||
| 47 | # use 'git ls-files' to get the worklist | 42 | # use 'git ls-files' to get the worklist |
| 48 | pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True) | 43 | pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True) |
| @@ -52,12 +47,12 @@ def main(): | |||
| 52 | 47 | ||
| 53 | for gitfile in stdout.rsplit("\n"): | 48 | for gitfile in stdout.rsplit("\n"): |
| 54 | if ".git" in gitfile or "ChangeLog" in gitfile or \ | 49 | if ".git" in gitfile or "ChangeLog" in gitfile or \ |
| 55 | os.path.isdir(gitfile): | 50 | ".log" in gitfile or os.path.isdir(gitfile): |
| 56 | continue | 51 | continue |
| 57 | if REGEX_FILE_KCONFIG.match(gitfile): | 52 | if REGEX_FILE_KCONFIG.match(gitfile): |
| 58 | kconfig_files.append(gitfile) | 53 | kconfig_files.append(gitfile) |
| 59 | else: | 54 | else: |
| 60 | # All non-Kconfig files are checked for consistency | 55 | # all non-Kconfig files are checked for consistency |
| 61 | source_files.append(gitfile) | 56 | source_files.append(gitfile) |
| 62 | 57 | ||
| 63 | for sfile in source_files: | 58 | for sfile in source_files: |
| @@ -68,15 +63,17 @@ def main(): | |||
| 68 | 63 | ||
| 69 | print "Undefined symbol used\tFile list" | 64 | print "Undefined symbol used\tFile list" |
| 70 | for feature in sorted(referenced_features): | 65 | for feature in sorted(referenced_features): |
| 66 | # filter some false positives | ||
| 67 | if feature == "FOO" or feature == "BAR" or \ | ||
| 68 | feature == "FOO_BAR" or feature == "XXX": | ||
| 69 | continue | ||
| 71 | if feature not in defined_features: | 70 | if feature not in defined_features: |
| 72 | if feature.endswith("_MODULE"): | 71 | if feature.endswith("_MODULE"): |
| 73 | # Avoid false positives for kernel modules | 72 | # avoid false positives for kernel modules |
| 74 | if feature[:-len("_MODULE")] in defined_features: | 73 | if feature[:-len("_MODULE")] in defined_features: |
| 75 | continue | 74 | continue |
| 76 | if "FOO" in feature or "BAR" in feature: | ||
| 77 | continue | ||
| 78 | files = referenced_features.get(feature) | 75 | files = referenced_features.get(feature) |
| 79 | print "%s:\t%s" % (feature, ", ".join(files)) | 76 | print "%s\t%s" % (feature, ", ".join(files)) |
| 80 | 77 | ||
| 81 | 78 | ||
| 82 | def parse_source_file(sfile, referenced_features): | 79 | def parse_source_file(sfile, referenced_features): |
| @@ -92,9 +89,9 @@ def parse_source_file(sfile, referenced_features): | |||
| 92 | for feature in features: | 89 | for feature in features: |
| 93 | if not REGEX_FILTER_FEATURES.search(feature): | 90 | if not REGEX_FILTER_FEATURES.search(feature): |
| 94 | continue | 91 | continue |
| 95 | paths = referenced_features.get(feature, set()) | 92 | sfiles = referenced_features.get(feature, set()) |
| 96 | paths.add(sfile) | 93 | sfiles.add(sfile) |
| 97 | referenced_features[feature] = paths | 94 | referenced_features[feature] = sfiles |
| 98 | 95 | ||
| 99 | 96 | ||
| 100 | def get_features_in_line(line): | 97 | def get_features_in_line(line): |
| @@ -113,7 +110,7 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): | |||
| 113 | for i in range(len(lines)): | 110 | for i in range(len(lines)): |
| 114 | line = lines[i] | 111 | line = lines[i] |
| 115 | line = line.strip('\n') | 112 | line = line.strip('\n') |
| 116 | line = line.split("#")[0] # Ignore Kconfig comments | 113 | line = line.split("#")[0] # ignore comments |
| 117 | 114 | ||
| 118 | if REGEX_KCONFIG_DEF.match(line): | 115 | if REGEX_KCONFIG_DEF.match(line): |
| 119 | feature_def = REGEX_KCONFIG_DEF.findall(line) | 116 | feature_def = REGEX_KCONFIG_DEF.findall(line) |
| @@ -122,11 +119,11 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): | |||
| 122 | elif REGEX_KCONFIG_HELP.match(line): | 119 | elif REGEX_KCONFIG_HELP.match(line): |
| 123 | skip = True | 120 | skip = True |
| 124 | elif skip: | 121 | elif skip: |
| 125 | # Ignore content of help messages | 122 | # ignore content of help messages |
| 126 | pass | 123 | pass |
| 127 | elif REGEX_KCONFIG_STMT.match(line): | 124 | elif REGEX_KCONFIG_STMT.match(line): |
| 128 | features = get_features_in_line(line) | 125 | features = get_features_in_line(line) |
| 129 | # Multi-line statements | 126 | # multi-line statements |
| 130 | while line.endswith("\\"): | 127 | while line.endswith("\\"): |
| 131 | i += 1 | 128 | i += 1 |
| 132 | line = lines[i] | 129 | line = lines[i] |
