| 1 | |
| 2 | |
| 3 |
|
| 4 | use warnings;
|
| 5 | use strict;
|
| 6 |
|
| 7 | my $srctree = shift @ARGV;
|
| 8 | unless (defined $srctree) {
|
| 9 | $srctree = `git rev-parse --show-toplevel 2>/dev/null`;
|
| 10 | chomp $srctree;
|
| 11 | my $msg = "Usage: $0 <srctree> [excludes file]\n";
|
| 12 | $msg .= "Please provide <srctree>.";
|
| 13 | $msg .= " Is it '$srctree'?" if $srctree;
|
| 14 | $msg .= "\n";
|
| 15 | die $msg;
|
| 16 | }
|
| 17 | my $kconfig_sym_check_excludes = defined $ARGV[0] ? $ARGV[0] : undef;
|
| 18 |
|
| 19 | sub indent_depth {
|
| 20 | my ($ws) = @_;
|
| 21 | my $col = 0;
|
| 22 | for my $c (split //, $ws) {
|
| 23 | $col = $c eq "\t" ? int($col / 8) * 8 + 8 : $col + 1;
|
| 24 | }
|
| 25 | return $col;
|
| 26 | }
|
| 27 |
|
| 28 | my @files = `git -C \Q$srctree\E ls-files '*Kconfig*' 2>/dev/null`;
|
| 29 | if (@files) {
|
| 30 | chomp @files;
|
| 31 | @files = map { "$srctree/$_" } @files;
|
| 32 | } else {
|
| 33 | @files = `find \Q$srctree\E -name '*Kconfig*'`;
|
| 34 | chomp @files;
|
| 35 | }
|
| 36 |
|
| 37 | @files = grep { !m{/scripts/kconfig/tests/} } @files;
|
| 38 |
|
| 39 | my %configs = ();
|
| 40 | my %refs = ();
|
| 41 |
|
| 42 | foreach my $file (@files) {
|
| 43 | open F, $file or die "Cannot open $file: $!";
|
| 44 |
|
| 45 | my $help = 0;
|
| 46 | my $help_level;
|
| 47 | my $level;
|
| 48 |
|
| 49 | while (<F>) {
|
| 50 | chomp;
|
| 51 |
|
| 52 | while (/\\\s*$/) {
|
| 53 | s/\\\s*$/ /;
|
| 54 | my $cont = <F> // last;
|
| 55 | chomp $cont;
|
| 56 | $_ .= $cont;
|
| 57 | }
|
| 58 |
|
| 59 | next if /^\s*$/;
|
| 60 | next if /^\s*#/;
|
| 61 |
|
| 62 | /^(\s*)/;
|
| 63 | $level = indent_depth($1);
|
| 64 |
|
| 65 | if ($help && $level < $help_level) {
|
| 66 | $help = 0;
|
| 67 | }
|
| 68 |
|
| 69 | next if ($help);
|
| 70 |
|
| 71 | if (/^\s*(help|\-\-\-help\-\-\-)$/) {
|
| 72 | $help = 1;
|
| 73 | my $next;
|
| 74 | while (defined($next = <F>)) {
|
| 75 | last unless $next =~ /^\s*(?:#.*)?$/;
|
| 76 | }
|
| 77 | last unless defined $next;
|
| 78 | $next =~ /^(\s*)/;
|
| 79 | if (indent_depth($1) >= $level) {
|
| 80 | $help_level = indent_depth($1);
|
| 81 | } else {
|
| 82 | $help = 0;
|
| 83 | }
|
| 84 | $_ = $next;
|
| 85 | redo;
|
| 86 | }
|
| 87 |
|
| 88 | if (/^\s*(config|menuconfig)\s+([a-zA-Z0-9_]+)\s*(#.*)?$/) {
|
| 89 | $configs{$2}++;
|
| 90 | next;
|
| 91 | }
|
| 92 |
|
| 93 | if (/^\s*(default|def_bool|def_tristate|select|depends\s+on|imply|visible\s+if|range|if|bool|tristate|int|hex|string|prompt)\s+(.+)\s*$/) {
|
| 94 | my $s = $2;
|
| 95 | $s =~ s/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'//g;
|
| 96 | $s =~ s/#.*//;
|
| 97 | $s =~ s/\$\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\)//g;
|
| 98 | $s =~ s/%%[^%]*%%//g;
|
| 99 | my @syms = split /[^a-zA-Z0-9_]+/, $s;
|
| 100 | map {
|
| 101 | $refs{$_}++ if (/[a-zA-Z]/ && $_ ne "if" && $_ ne "y" && $_ ne "n" && $_ ne "m" && !/^0[xX][0-9a-fA-F]+$/);
|
| 102 | } @syms
|
| 103 | }
|
| 104 | }
|
| 105 |
|
| 106 | close F;
|
| 107 | }
|
| 108 |
|
| 109 | my %known_syms = ();
|
| 110 | if (defined $kconfig_sym_check_excludes) {
|
| 111 | my $file = $kconfig_sym_check_excludes;
|
| 112 | open(F, "<", $file) or die "Cannot open $file: $!";
|
| 113 | while (<F>) {
|
| 114 | chomp;
|
| 115 | next if /^\s*$/;
|
| 116 | next if /^\s*#/;
|
| 117 | $known_syms{$1}++ if (/^\s*([a-zA-Z0-9_]+)\s*(#.*)?$/);
|
| 118 | }
|
| 119 | }
|
| 120 |
|
| 121 | my $ret = 0;
|
| 122 | foreach my $k (sort keys %refs) {
|
| 123 | next if (exists $configs{$k} || exists $known_syms{$k});
|
| 124 |
|
| 125 | print "$k";
|
| 126 | print " - warning: '$k' is probably not what you want; Kconfig tristate literals are always lowercase ('n', 'y', 'm')" if ($k eq "N" || $k eq "Y" || $k eq "M");
|
| 127 | print "\n";
|
| 128 |
|
| 129 | $ret = 1;
|
| 130 | }
|
| 131 |
|
| 132 | exit $ret;
|