diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-21 12:42:58 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-21 12:42:58 -0400 |
| commit | 1fc149933fd49a5b0e7738dc0853dbfbac4ae0e1 (patch) | |
| tree | dfe99751c21aaf39e49765379d0b9b32114c757d /scripts | |
| parent | 41d5e08ea86af3359239d5a6f7021cdc61beaa49 (diff) | |
| parent | ea5505fabd3b59608750bfd3721d0f8bc5c8b0bb (diff) | |
Merge tag 'char-misc-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here's the big char/misc driver patchset for 4.1-rc1.
Lots of different driver subsystem updates here, nothing major, full
details are in the shortlog.
All of this has been in linux-next for a while"
* tag 'char-misc-4.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (133 commits)
mei: trace: remove unused TRACE_SYSTEM_STRING
DTS: ARM: OMAP3-N900: Add lis3lv02d support
Documentation: DT: lis302: update wakeup binding
lis3lv02d: DT: add wakeup unit 2 and wakeup threshold
lis3lv02d: DT: use s32 to support negative values
Drivers: hv: hv_balloon: correctly handle num_pages>INT_MAX case
Drivers: hv: hv_balloon: correctly handle val.freeram<num_pages case
mei: replace check for connection instead of transitioning
mei: use mei_cl_is_connected consistently
mei: fix mei_poll operation
hv_vmbus: Add gradually increased delay for retries in vmbus_post_msg()
Drivers: hv: hv_balloon: survive ballooning request with num_pages=0
Drivers: hv: hv_balloon: eliminate jumps in piecewiese linear floor function
Drivers: hv: hv_balloon: do not online pages in offline blocks
hv: remove the per-channel workqueue
hv: don't schedule new works in vmbus_onoffer()/vmbus_onoffer_rescind()
hv: run non-blocking message handlers in the dispatch tasklet
coresight: moving to new "hwtracing" directory
coresight-tmc: Adding a status interface to sysfs
coresight: remove the unnecessary configuration coresight-default-sink
...
Diffstat (limited to 'scripts')
| -rwxr-xr-x[-rw-r--r--] | scripts/checkkconfigsymbols.py | 147 |
1 files changed, 138 insertions, 9 deletions
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index e9cc689033fe..74086a583d8d 100644..100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
| 2 | 2 | ||
| 3 | """Find Kconfig identifiers that are referenced but not defined.""" | 3 | """Find Kconfig symbols that are referenced but not defined.""" |
| 4 | 4 | ||
| 5 | # (c) 2014 Valentin Rothberg <valentinrothberg@gmail.com> | 5 | # (c) 2014-2015 Valentin Rothberg <Valentin.Rothberg@lip6.fr> |
| 6 | # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de> | 6 | # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de> |
| 7 | # | 7 | # |
| 8 | # Licensed under the terms of the GNU GPL License version 2 | 8 | # Licensed under the terms of the GNU GPL License version 2 |
| @@ -10,7 +10,9 @@ | |||
| 10 | 10 | ||
| 11 | import os | 11 | import os |
| 12 | import re | 12 | import re |
| 13 | import sys | ||
| 13 | from subprocess import Popen, PIPE, STDOUT | 14 | from subprocess import Popen, PIPE, STDOUT |
| 15 | from optparse import OptionParser | ||
| 14 | 16 | ||
| 15 | 17 | ||
| 16 | # regex expressions | 18 | # regex expressions |
| @@ -32,22 +34,149 @@ REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") | |||
| 32 | REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") | 34 | REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") |
| 33 | 35 | ||
| 34 | 36 | ||
| 37 | def parse_options(): | ||
| 38 | """The user interface of this module.""" | ||
| 39 | usage = "%prog [options]\n\n" \ | ||
| 40 | "Run this tool to detect Kconfig symbols that are referenced but " \ | ||
| 41 | "not defined in\nKconfig. The output of this tool has the " \ | ||
| 42 | "format \'Undefined symbol\\tFile list\'\n\n" \ | ||
| 43 | "If no option is specified, %prog will default to check your\n" \ | ||
| 44 | "current tree. Please note that specifying commits will " \ | ||
| 45 | "\'git reset --hard\'\nyour current tree! You may save " \ | ||
| 46 | "uncommitted changes to avoid losing data." | ||
| 47 | |||
| 48 | parser = OptionParser(usage=usage) | ||
| 49 | |||
| 50 | parser.add_option('-c', '--commit', dest='commit', action='store', | ||
| 51 | default="", | ||
| 52 | help="Check if the specified commit (hash) introduces " | ||
| 53 | "undefined Kconfig symbols.") | ||
| 54 | |||
| 55 | parser.add_option('-d', '--diff', dest='diff', action='store', | ||
| 56 | default="", | ||
| 57 | help="Diff undefined symbols between two commits. The " | ||
| 58 | "input format bases on Git log's " | ||
| 59 | "\'commmit1..commit2\'.") | ||
| 60 | |||
| 61 | parser.add_option('', '--force', dest='force', action='store_true', | ||
| 62 | default=False, | ||
| 63 | help="Reset current Git tree even when it's dirty.") | ||
| 64 | |||
| 65 | (opts, _) = parser.parse_args() | ||
| 66 | |||
| 67 | if opts.commit and opts.diff: | ||
| 68 | sys.exit("Please specify only one option at once.") | ||
| 69 | |||
| 70 | if opts.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", opts.diff): | ||
| 71 | sys.exit("Please specify valid input in the following format: " | ||
| 72 | "\'commmit1..commit2\'") | ||
| 73 | |||
| 74 | if opts.commit or opts.diff: | ||
| 75 | if not opts.force and tree_is_dirty(): | ||
| 76 | sys.exit("The current Git tree is dirty (see 'git status'). " | ||
| 77 | "Running this script may\ndelete important data since it " | ||
| 78 | "calls 'git reset --hard' for some performance\nreasons. " | ||
| 79 | " Please run this script in a clean Git tree or pass " | ||
| 80 | "'--force' if you\nwant to ignore this warning and " | ||
| 81 | "continue.") | ||
| 82 | |||
| 83 | return opts | ||
| 84 | |||
| 85 | |||
| 35 | def main(): | 86 | def main(): |
| 36 | """Main function of this module.""" | 87 | """Main function of this module.""" |
| 88 | opts = parse_options() | ||
| 89 | |||
| 90 | if opts.commit or opts.diff: | ||
| 91 | head = get_head() | ||
| 92 | |||
| 93 | # get commit range | ||
| 94 | commit_a = None | ||
| 95 | commit_b = None | ||
| 96 | if opts.commit: | ||
| 97 | commit_a = opts.commit + "~" | ||
| 98 | commit_b = opts.commit | ||
| 99 | elif opts.diff: | ||
| 100 | split = opts.diff.split("..") | ||
| 101 | commit_a = split[0] | ||
| 102 | commit_b = split[1] | ||
| 103 | undefined_a = {} | ||
| 104 | undefined_b = {} | ||
| 105 | |||
| 106 | # get undefined items before the commit | ||
| 107 | execute("git reset --hard %s" % commit_a) | ||
| 108 | undefined_a = check_symbols() | ||
| 109 | |||
| 110 | # get undefined items for the commit | ||
| 111 | execute("git reset --hard %s" % commit_b) | ||
| 112 | undefined_b = check_symbols() | ||
| 113 | |||
| 114 | # report cases that are present for the commit but not before | ||
| 115 | for feature in sorted(undefined_b): | ||
| 116 | # feature has not been undefined before | ||
| 117 | if not feature in undefined_a: | ||
| 118 | files = sorted(undefined_b.get(feature)) | ||
| 119 | print "%s\t%s" % (feature, ", ".join(files)) | ||
| 120 | # check if there are new files that reference the undefined feature | ||
| 121 | else: | ||
| 122 | files = sorted(undefined_b.get(feature) - | ||
| 123 | undefined_a.get(feature)) | ||
| 124 | if files: | ||
| 125 | print "%s\t%s" % (feature, ", ".join(files)) | ||
| 126 | |||
| 127 | # reset to head | ||
| 128 | execute("git reset --hard %s" % head) | ||
| 129 | |||
| 130 | # default to check the entire tree | ||
| 131 | else: | ||
| 132 | undefined = check_symbols() | ||
| 133 | for feature in sorted(undefined): | ||
| 134 | files = sorted(undefined.get(feature)) | ||
| 135 | print "%s\t%s" % (feature, ", ".join(files)) | ||
| 136 | |||
| 137 | |||
| 138 | def execute(cmd): | ||
| 139 | """Execute %cmd and return stdout. Exit in case of error.""" | ||
| 140 | pop = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True) | ||
| 141 | (stdout, _) = pop.communicate() # wait until finished | ||
| 142 | if pop.returncode != 0: | ||
| 143 | sys.exit(stdout) | ||
| 144 | return stdout | ||
| 145 | |||
| 146 | |||
| 147 | def tree_is_dirty(): | ||
| 148 | """Return true if the current working tree is dirty (i.e., if any file has | ||
| 149 | been added, deleted, modified, renamed or copied but not committed).""" | ||
| 150 | stdout = execute("git status --porcelain") | ||
| 151 | for line in stdout: | ||
| 152 | if re.findall(r"[URMADC]{1}", line[:2]): | ||
| 153 | return True | ||
| 154 | return False | ||
| 155 | |||
| 156 | |||
| 157 | def get_head(): | ||
| 158 | """Return commit hash of current HEAD.""" | ||
| 159 | stdout = execute("git rev-parse HEAD") | ||
| 160 | return stdout.strip('\n') | ||
| 161 | |||
| 162 | |||
| 163 | def check_symbols(): | ||
| 164 | """Find undefined Kconfig symbols and return a dict with the symbol as key | ||
| 165 | and a list of referencing files as value.""" | ||
| 37 | source_files = [] | 166 | source_files = [] |
| 38 | kconfig_files = [] | 167 | kconfig_files = [] |
| 39 | defined_features = set() | 168 | defined_features = set() |
| 40 | referenced_features = dict() # {feature: [files]} | 169 | referenced_features = dict() # {feature: [files]} |
| 41 | 170 | ||
| 42 | # use 'git ls-files' to get the worklist | 171 | # use 'git ls-files' to get the worklist |
| 43 | pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True) | 172 | stdout = execute("git ls-files") |
| 44 | (stdout, _) = pop.communicate() # wait until finished | ||
| 45 | if len(stdout) > 0 and stdout[-1] == "\n": | 173 | if len(stdout) > 0 and stdout[-1] == "\n": |
| 46 | stdout = stdout[:-1] | 174 | stdout = stdout[:-1] |
| 47 | 175 | ||
| 48 | for gitfile in stdout.rsplit("\n"): | 176 | for gitfile in stdout.rsplit("\n"): |
| 49 | if ".git" in gitfile or "ChangeLog" in gitfile or \ | 177 | if ".git" in gitfile or "ChangeLog" in gitfile or \ |
| 50 | ".log" in gitfile or os.path.isdir(gitfile): | 178 | ".log" in gitfile or os.path.isdir(gitfile) or \ |
| 179 | gitfile.startswith("tools/"): | ||
| 51 | continue | 180 | continue |
| 52 | if REGEX_FILE_KCONFIG.match(gitfile): | 181 | if REGEX_FILE_KCONFIG.match(gitfile): |
| 53 | kconfig_files.append(gitfile) | 182 | kconfig_files.append(gitfile) |
| @@ -61,7 +190,7 @@ def main(): | |||
| 61 | for kfile in kconfig_files: | 190 | for kfile in kconfig_files: |
| 62 | parse_kconfig_file(kfile, defined_features, referenced_features) | 191 | parse_kconfig_file(kfile, defined_features, referenced_features) |
| 63 | 192 | ||
| 64 | print "Undefined symbol used\tFile list" | 193 | undefined = {} # {feature: [files]} |
| 65 | for feature in sorted(referenced_features): | 194 | for feature in sorted(referenced_features): |
| 66 | # filter some false positives | 195 | # filter some false positives |
| 67 | if feature == "FOO" or feature == "BAR" or \ | 196 | if feature == "FOO" or feature == "BAR" or \ |
| @@ -72,8 +201,8 @@ def main(): | |||
| 72 | # avoid false positives for kernel modules | 201 | # avoid false positives for kernel modules |
| 73 | if feature[:-len("_MODULE")] in defined_features: | 202 | if feature[:-len("_MODULE")] in defined_features: |
| 74 | continue | 203 | continue |
| 75 | files = referenced_features.get(feature) | 204 | undefined[feature] = referenced_features.get(feature) |
| 76 | print "%s\t%s" % (feature, ", ".join(files)) | 205 | return undefined |
| 77 | 206 | ||
| 78 | 207 | ||
| 79 | def parse_source_file(sfile, referenced_features): | 208 | def parse_source_file(sfile, referenced_features): |
