7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 1) #!/usr/bin/env python3
4f19048fd0a00 (Thomas Gleixner 2019-05-27 08:55:14 +0200 2) # SPDX-License-Identifier: GPL-2.0-only
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 3)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 4) """Find Kconfig symbols that are referenced but not defined."""
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 5)
8e8e333179d6e (Valentin Rothberg 2017-01-18 13:08:19 +0100 6) # (c) 2014-2017 Valentin Rothberg <valentinrothberg@gmail.com>
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 7) # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 8) #
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 9)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 10)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 11) import argparse
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 12) import difflib
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 13) import os
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 14) import re
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 15) import signal
f175ba174ef3c (Valentin Rothberg 2016-08-27 10:59:07 +0200 16) import subprocess
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 17) import sys
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 18) from multiprocessing import Pool, cpu_count
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 19)
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 20)
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 21) # regex expressions
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 22) OPERATORS = r"&|\(|\)|\||\!"
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 23) SYMBOL = r"(?:\w*[A-Z0-9]\w*){2,}"
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 24) DEF = r"^\s*(?:menu){,1}config\s+(" + SYMBOL + r")\s*"
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 25) EXPR = r"(?:" + OPERATORS + r"|\s|" + SYMBOL + r")+"
0bd38ae355227 (Valentin Rothberg 2015-07-27 12:33:05 +0200 26) DEFAULT = r"default\s+.*?(?:if\s.+){,1}"
3b28f4f2c2c7f (Valentin Rothberg 2017-02-02 18:00:44 +0100 27) STMT = r"^\s*(?:if|select|imply|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 28) SOURCE_SYMBOL = r"(?:\W|\b)+[D]{,1}CONFIG_(" + SYMBOL + r")"
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 29)
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 30) # regex objects
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 31) REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$")
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 32) REGEX_SYMBOL = re.compile(r'(?!\B)' + SYMBOL + r'(?!\B)')
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 33) REGEX_SOURCE_SYMBOL = re.compile(SOURCE_SYMBOL)
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 34) REGEX_KCONFIG_DEF = re.compile(DEF)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 35) REGEX_KCONFIG_EXPR = re.compile(EXPR)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 36) REGEX_KCONFIG_STMT = re.compile(STMT)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 37) REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$")
0bd38ae355227 (Valentin Rothberg 2015-07-27 12:33:05 +0200 38) REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+")
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 39) REGEX_QUOTES = re.compile("(\"(.*?)\")")
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 40)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 41)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 42) def parse_options():
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 43) """The user interface of this module."""
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 44) usage = "Run this tool to detect Kconfig symbols that are referenced but " \
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 45) "not defined in Kconfig. If no option is specified, " \
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 46) "checkkconfigsymbols defaults to check your current tree. " \
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 47) "Please note that specifying commits will 'git reset --hard\' " \
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 48) "your current tree! You may save uncommitted changes to avoid " \
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 49) "losing data."
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 50)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 51) parser = argparse.ArgumentParser(description=usage)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 52)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 53) parser.add_argument('-c', '--commit', dest='commit', action='store',
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 54) default="",
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 55) help="check if the specified commit (hash) introduces "
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 56) "undefined Kconfig symbols")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 57)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 58) parser.add_argument('-d', '--diff', dest='diff', action='store',
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 59) default="",
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 60) help="diff undefined symbols between two commits "
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 61) "(e.g., -d commmit1..commit2)")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 62)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 63) parser.add_argument('-f', '--find', dest='find', action='store_true',
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 64) default=False,
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 65) help="find and show commits that may cause symbols to be "
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 66) "missing (required to run with --diff)")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 67)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 68) parser.add_argument('-i', '--ignore', dest='ignore', action='store',
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 69) default="",
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 70) help="ignore files matching this Python regex "
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 71) "(e.g., -i '.*defconfig')")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 72)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 73) parser.add_argument('-s', '--sim', dest='sim', action='store', default="",
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 74) help="print a list of max. 10 string-similar symbols")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 75)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 76) parser.add_argument('--force', dest='force', action='store_true',
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 77) default=False,
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 78) help="reset current Git tree even when it's dirty")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 79)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 80) parser.add_argument('--no-color', dest='color', action='store_false',
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 81) default=True,
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 82) help="don't print colored output (default when not "
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 83) "outputting to a terminal)")
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 84)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 85) args = parser.parse_args()
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 86)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 87) if args.commit and args.diff:
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 88) sys.exit("Please specify only one option at once.")
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 89)
0d18c19288601 (Valentin Rothberg 2016-10-27 14:34:57 +0200 90) if args.diff and not re.match(r"^[\w\-\.\^]+\.\.[\w\-\.\^]+$", args.diff):
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 91) sys.exit("Please specify valid input in the following format: "
38cbfe4fe8071 (Andreas Ziegler 2016-03-31 09:24:29 +0200 92) "\'commit1..commit2\'")
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 93)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 94) if args.commit or args.diff:
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 95) if not args.force and tree_is_dirty():
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 96) sys.exit("The current Git tree is dirty (see 'git status'). "
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 97) "Running this script may\ndelete important data since it "
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 98) "calls 'git reset --hard' for some performance\nreasons. "
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 99) " Please run this script in a clean Git tree or pass "
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 100) "'--force' if you\nwant to ignore this warning and "
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 101) "continue.")
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 102)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 103) if args.commit:
d62d5aed3354a (Ariel Marcovitch 2021-09-01 17:52:12 +0300 104) if args.commit.startswith('HEAD'):
d62d5aed3354a (Ariel Marcovitch 2021-09-01 17:52:12 +0300 105) sys.exit("The --commit option can't use the HEAD ref")
d62d5aed3354a (Ariel Marcovitch 2021-09-01 17:52:12 +0300 106)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 107) args.find = False
a42fa92ce77a9 (Valentin Rothberg 2015-06-01 16:00:19 +0200 108)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 109) if args.ignore:
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 110) try:
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 111) re.match(args.ignore, "this/is/just/a/test.c")
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 112) except:
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 113) sys.exit("Please specify a valid Python regex.")
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 114)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 115) return args
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 116)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 117)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 118) def main():
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 119) """Main function of this module."""
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 120) args = parse_options()
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 121)
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 122) global COLOR
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 123) COLOR = args.color and sys.stdout.isatty()
4c73c0882b34d (Andrew Donnellan 2016-07-05 17:47:37 +1000 124)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 125) if args.sim and not args.commit and not args.diff:
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 126) sims = find_sims(args.sim, args.ignore)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 127) if sims:
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 128) print("%s: %s" % (yel("Similar symbols"), ', '.join(sims)))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 129) else:
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 130) print("%s: no similar symbols found" % yel("Similar symbols"))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 131) sys.exit(0)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 132)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 133) # dictionary of (un)defined symbols
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 134) defined = {}
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 135) undefined = {}
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 136)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 137) if args.commit or args.diff:
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 138) head = get_head()
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 139)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 140) # get commit range
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 141) commit_a = None
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 142) commit_b = None
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 143) if args.commit:
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 144) commit_a = args.commit + "~"
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 145) commit_b = args.commit
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 146) elif args.diff:
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 147) split = args.diff.split("..")
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 148) commit_a = split[0]
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 149) commit_b = split[1]
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 150) undefined_a = {}
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 151) undefined_b = {}
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 152)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 153) # get undefined items before the commit
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 154) reset(commit_a)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 155) undefined_a, _ = check_symbols(args.ignore)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 156)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 157) # get undefined items for the commit
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 158) reset(commit_b)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 159) undefined_b, defined = check_symbols(args.ignore)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 160)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 161) # report cases that are present for the commit but not before
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 162) for symbol in sorted(undefined_b):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 163) # symbol has not been undefined before
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 164) if symbol not in undefined_a:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 165) files = sorted(undefined_b.get(symbol))
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 166) undefined[symbol] = files
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 167) # check if there are new files that reference the undefined symbol
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 168) else:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 169) files = sorted(undefined_b.get(symbol) -
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 170) undefined_a.get(symbol))
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 171) if files:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 172) undefined[symbol] = files
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 173)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 174) # reset to head
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 175) reset(head)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 176)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 177) # default to check the entire tree
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 178) else:
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 179) undefined, defined = check_symbols(args.ignore)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 180)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 181) # now print the output
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 182) for symbol in sorted(undefined):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 183) print(red(symbol))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 184)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 185) files = sorted(undefined.get(symbol))
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 186) print("%s: %s" % (yel("Referencing files"), ", ".join(files)))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 187)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 188) sims = find_sims(symbol, args.ignore, defined)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 189) sims_out = yel("Similar symbols")
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 190) if sims:
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 191) print("%s: %s" % (sims_out, ', '.join(sims)))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 192) else:
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 193) print("%s: %s" % (sims_out, "no similar symbols found"))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 194)
14390e31641e6 (Valentin Rothberg 2016-08-28 08:51:29 +0200 195) if args.find:
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 196) print("%s:" % yel("Commits changing symbol"))
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 197) commits = find_commits(symbol, args.diff)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 198) if commits:
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 199) for commit in commits:
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 200) commit = commit.split(" ", 1)
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 201) print("\t- %s (\"%s\")" % (yel(commit[0]), commit[1]))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 202) else:
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 203) print("\t- no commit found")
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 204) print() # new line
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 205)
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 206)
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 207) def reset(commit):
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 208) """Reset current git tree to %commit."""
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 209) execute(["git", "reset", "--hard", commit])
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 210)
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 211)
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 212) def yel(string):
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 213) """
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 214) Color %string yellow.
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 215) """
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 216) return "\033[33m%s\033[0m" % string if COLOR else string
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 217)
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 218)
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 219) def red(string):
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 220) """
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 221) Color %string red.
c745566306e36 (Valentin Rothberg 2015-06-01 16:00:20 +0200 222) """
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 223) return "\033[31m%s\033[0m" % string if COLOR else string
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 224)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 225)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 226) def execute(cmd):
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 227) """Execute %cmd and return stdout. Exit in case of error."""
f175ba174ef3c (Valentin Rothberg 2016-08-27 10:59:07 +0200 228) try:
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 229) stdout = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False)
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 230) stdout = stdout.decode(errors='replace')
f175ba174ef3c (Valentin Rothberg 2016-08-27 10:59:07 +0200 231) except subprocess.CalledProcessError as fail:
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 232) exit(fail)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 233) return stdout
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 234)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 235)
a42fa92ce77a9 (Valentin Rothberg 2015-06-01 16:00:19 +0200 236) def find_commits(symbol, diff):
a42fa92ce77a9 (Valentin Rothberg 2015-06-01 16:00:19 +0200 237) """Find commits changing %symbol in the given range of %diff."""
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 238) commits = execute(["git", "log", "--pretty=oneline",
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 239) "--abbrev-commit", "-G",
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 240) symbol, diff])
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 241) return [x for x in commits.split("\n") if x]
a42fa92ce77a9 (Valentin Rothberg 2015-06-01 16:00:19 +0200 242)
a42fa92ce77a9 (Valentin Rothberg 2015-06-01 16:00:19 +0200 243)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 244) def tree_is_dirty():
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 245) """Return true if the current working tree is dirty (i.e., if any file has
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 246) been added, deleted, modified, renamed or copied but not committed)."""
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 247) stdout = execute(["git", "status", "--porcelain"])
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 248) for line in stdout:
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 249) if re.findall(r"[URMADC]{1}", line[:2]):
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 250) return True
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 251) return False
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 252)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 253)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 254) def get_head():
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 255) """Return commit hash of current HEAD."""
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 256) stdout = execute(["git", "rev-parse", "HEAD"])
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 257) return stdout.strip('\n')
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 258)
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 259)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 260) def partition(lst, size):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 261) """Partition list @lst into eveni-sized lists of size @size."""
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 262) return [lst[i::size] for i in range(size)]
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 263)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 264)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 265) def init_worker():
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 266) """Set signal handler to ignore SIGINT."""
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 267) signal.signal(signal.SIGINT, signal.SIG_IGN)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 268)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 269)
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 270) def find_sims(symbol, ignore, defined=[]):
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 271) """Return a list of max. ten Kconfig symbols that are string-similar to
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 272) @symbol."""
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 273) if defined:
8e8e333179d6e (Valentin Rothberg 2017-01-18 13:08:19 +0100 274) return difflib.get_close_matches(symbol, set(defined), 10)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 275)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 276) pool = Pool(cpu_count(), init_worker)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 277) kfiles = []
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 278) for gitfile in get_files():
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 279) if REGEX_FILE_KCONFIG.match(gitfile):
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 280) kfiles.append(gitfile)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 281)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 282) arglist = []
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 283) for part in partition(kfiles, cpu_count()):
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 284) arglist.append((part, ignore))
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 285)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 286) for res in pool.map(parse_kconfig_files, arglist):
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 287) defined.extend(res[0])
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 288)
8e8e333179d6e (Valentin Rothberg 2017-01-18 13:08:19 +0100 289) return difflib.get_close_matches(symbol, set(defined), 10)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 290)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 291)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 292) def get_files():
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 293) """Return a list of all files in the current git directory."""
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 294) # use 'git ls-files' to get the worklist
2f9cc12bb34a4 (Valentin Rothberg 2016-08-28 08:51:32 +0200 295) stdout = execute(["git", "ls-files"])
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 296) if len(stdout) > 0 and stdout[-1] == "\n":
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 297) stdout = stdout[:-1]
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 298)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 299) files = []
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 300) for gitfile in stdout.rsplit("\n"):
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 301) if ".git" in gitfile or "ChangeLog" in gitfile or \
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 302) ".log" in gitfile or os.path.isdir(gitfile) or \
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 303) gitfile.startswith("tools/"):
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 304) continue
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 305) files.append(gitfile)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 306) return files
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 307)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 308)
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 309) def check_symbols(ignore):
b1a3f243485fa (Valentin Rothberg 2015-03-16 12:16:14 +0100 310) """Find undefined Kconfig symbols and return a dict with the symbol as key
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 311) and a list of referencing files as value. Files matching %ignore are not
cf132e4a8e070 (Valentin Rothberg 2015-04-29 16:58:27 +0200 312) checked for undefined symbols."""
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 313) pool = Pool(cpu_count(), init_worker)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 314) try:
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 315) return check_symbols_helper(pool, ignore)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 316) except KeyboardInterrupt:
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 317) pool.terminate()
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 318) pool.join()
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 319) sys.exit(1)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 320)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 321)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 322) def check_symbols_helper(pool, ignore):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 323) """Helper method for check_symbols(). Used to catch keyboard interrupts in
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 324) check_symbols() in order to properly terminate running worker processes."""
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 325) source_files = []
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 326) kconfig_files = []
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 327) defined_symbols = []
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 328) referenced_symbols = dict() # {file: [symbols]}
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 329)
1b2c841467515 (Valentin Rothberg 2015-11-26 14:17:15 +0100 330) for gitfile in get_files():
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 331) if REGEX_FILE_KCONFIG.match(gitfile):
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 332) kconfig_files.append(gitfile)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 333) else:
1439ebd2ce772 (Ariel Marcovitch 2021-08-22 22:22:01 +0300 334) if ignore and re.match(ignore, gitfile):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 335) continue
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 336) # add source files that do not match the ignore pattern
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 337) source_files.append(gitfile)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 338)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 339) # parse source files
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 340) arglist = partition(source_files, cpu_count())
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 341) for res in pool.map(parse_source_files, arglist):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 342) referenced_symbols.update(res)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 343)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 344) # parse kconfig files
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 345) arglist = []
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 346) for part in partition(kconfig_files, cpu_count()):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 347) arglist.append((part, ignore))
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 348) for res in pool.map(parse_kconfig_files, arglist):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 349) defined_symbols.extend(res[0])
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 350) referenced_symbols.update(res[1])
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 351) defined_symbols = set(defined_symbols)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 352)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 353) # inverse mapping of referenced_symbols to dict(symbol: [files])
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 354) inv_map = dict()
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 355) for _file, symbols in referenced_symbols.items():
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 356) for symbol in symbols:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 357) inv_map[symbol] = inv_map.get(symbol, set())
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 358) inv_map[symbol].add(_file)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 359) referenced_symbols = inv_map
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 360)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 361) undefined = {} # {symbol: [files]}
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 362) for symbol in sorted(referenced_symbols):
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 363) # filter some false positives
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 364) if symbol == "FOO" or symbol == "BAR" or \
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 365) symbol == "FOO_BAR" or symbol == "XXX":
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 366) continue
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 367) if symbol not in defined_symbols:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 368) if symbol.endswith("_MODULE"):
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 369) # avoid false positives for kernel modules
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 370) if symbol[:-len("_MODULE")] in defined_symbols:
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 371) continue
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 372) undefined[symbol] = referenced_symbols.get(symbol)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 373) return undefined, defined_symbols
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 374)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 375)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 376) def parse_source_files(source_files):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 377) """Parse each source file in @source_files and return dictionary with source
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 378) files as keys and lists of references Kconfig symbols as values."""
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 379) referenced_symbols = dict()
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 380) for sfile in source_files:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 381) referenced_symbols[sfile] = parse_source_file(sfile)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 382) return referenced_symbols
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 383)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 384)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 385) def parse_source_file(sfile):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 386) """Parse @sfile and return a list of referenced Kconfig symbols."""
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 387) lines = []
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 388) references = []
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 389)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 390) if not os.path.exists(sfile):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 391) return references
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 392)
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 393) with open(sfile, "r", encoding='utf-8', errors='replace') as stream:
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 394) lines = stream.readlines()
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 395)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 396) for line in lines:
36c79c7face54 (Valentin Rothberg 2016-08-28 08:51:30 +0200 397) if "CONFIG_" not in line:
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 398) continue
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 399) symbols = REGEX_SOURCE_SYMBOL.findall(line)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 400) for symbol in symbols:
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 401) if not REGEX_FILTER_SYMBOLS.search(symbol):
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 402) continue
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 403) references.append(symbol)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 404)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 405) return references
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 406)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 407)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 408) def get_symbols_in_line(line):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 409) """Return mentioned Kconfig symbols in @line."""
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 410) return REGEX_SYMBOL.findall(line)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 411)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 412)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 413) def parse_kconfig_files(args):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 414) """Parse kconfig files and return tuple of defined and references Kconfig
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 415) symbols. Note, @args is a tuple of a list of files and the @ignore
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 416) pattern."""
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 417) kconfig_files = args[0]
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 418) ignore = args[1]
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 419) defined_symbols = []
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 420) referenced_symbols = dict()
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 421)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 422) for kfile in kconfig_files:
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 423) defined, references = parse_kconfig_file(kfile)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 424) defined_symbols.extend(defined)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 425) if ignore and re.match(ignore, kfile):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 426) # do not collect references for files that match the ignore pattern
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 427) continue
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 428) referenced_symbols[kfile] = references
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 429) return (defined_symbols, referenced_symbols)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 430)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 431)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 432) def parse_kconfig_file(kfile):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 433) """Parse @kfile and update symbol definitions and references."""
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 434) lines = []
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 435) defined = []
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 436) references = []
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 437)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 438) if not os.path.exists(kfile):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 439) return defined, references
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 440)
7c5227af25a1b (Valentin Rothberg 2016-08-28 08:51:28 +0200 441) with open(kfile, "r", encoding='utf-8', errors='replace') as stream:
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 442) lines = stream.readlines()
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 443)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 444) for i in range(len(lines)):
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 445) line = lines[i]
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 446) line = line.strip('\n')
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 447) line = line.split("#")[0] # ignore comments
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 448)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 449) if REGEX_KCONFIG_DEF.match(line):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 450) symbol_def = REGEX_KCONFIG_DEF.findall(line)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 451) defined.append(symbol_def[0])
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 452) elif REGEX_KCONFIG_STMT.match(line):
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 453) line = REGEX_QUOTES.sub("", line)
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 454) symbols = get_symbols_in_line(line)
cc641d5529965 (Valentin Rothberg 2014-11-08 20:56:35 +0100 455) # multi-line statements
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 456) while line.endswith("\\"):
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 457) i += 1
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 458) line = lines[i]
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 459) line = line.strip('\n')
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 460) symbols.extend(get_symbols_in_line(line))
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 461) for symbol in set(symbols):
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 462) if REGEX_NUMERIC.match(symbol):
0bd38ae355227 (Valentin Rothberg 2015-07-27 12:33:05 +0200 463) # ignore numeric values
0bd38ae355227 (Valentin Rothberg 2015-07-27 12:33:05 +0200 464) continue
ef3f55438d95f (Valentin Rothberg 2016-08-28 08:51:31 +0200 465) references.append(symbol)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 466)
e2042a8a80ab5 (Valentin Rothberg 2015-10-15 10:37:47 +0200 467) return defined, references
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 468)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 469)
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 470) if __name__ == "__main__":
24fe1f03e4ef8 (Valentin Rothberg 2014-09-27 16:30:45 +0200 471) main()