133 lines
2.8 KiB
Perl
Executable File
133 lines
2.8 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
my $srctree = shift @ARGV;
|
|
unless (defined $srctree) {
|
|
$srctree = `git rev-parse --show-toplevel 2>/dev/null`;
|
|
chomp $srctree;
|
|
my $msg = "Usage: $0 <srctree> [excludes file]\n";
|
|
$msg .= "Please provide <srctree>.";
|
|
$msg .= " Is it '$srctree'?" if $srctree;
|
|
$msg .= "\n";
|
|
die $msg;
|
|
}
|
|
my $kconfig_sym_check_excludes = defined $ARGV[0] ? $ARGV[0] : undef;
|
|
|
|
sub indent_depth {
|
|
my ($ws) = @_;
|
|
my $col = 0;
|
|
for my $c (split //, $ws) {
|
|
$col = $c eq "\t" ? int($col / 8) * 8 + 8 : $col + 1;
|
|
}
|
|
return $col;
|
|
}
|
|
|
|
my @files = `git -C \Q$srctree\E ls-files '*Kconfig*' 2>/dev/null`;
|
|
if (@files) {
|
|
chomp @files;
|
|
@files = map { "$srctree/$_" } @files;
|
|
} else {
|
|
@files = `find \Q$srctree\E -name '*Kconfig*'`;
|
|
chomp @files;
|
|
}
|
|
|
|
@files = grep { !m{/scripts/kconfig/tests/} } @files;
|
|
|
|
my %configs = ();
|
|
my %refs = ();
|
|
|
|
foreach my $file (@files) {
|
|
open F, $file or die "Cannot open $file: $!";
|
|
|
|
my $help = 0;
|
|
my $help_level;
|
|
my $level;
|
|
|
|
while (<F>) {
|
|
chomp;
|
|
|
|
while (/\\\s*$/) {
|
|
s/\\\s*$/ /;
|
|
my $cont = <F> // last;
|
|
chomp $cont;
|
|
$_ .= $cont;
|
|
}
|
|
|
|
next if /^\s*$/;
|
|
next if /^\s*#/;
|
|
|
|
/^(\s*)/;
|
|
$level = indent_depth($1);
|
|
|
|
if ($help && $level < $help_level) {
|
|
$help = 0;
|
|
}
|
|
|
|
next if ($help);
|
|
|
|
if (/^\s*(help|\-\-\-help\-\-\-)$/) {
|
|
$help = 1;
|
|
my $next;
|
|
while (defined($next = <F>)) {
|
|
last unless $next =~ /^\s*(?:#.*)?$/;
|
|
}
|
|
last unless defined $next;
|
|
$next =~ /^(\s*)/;
|
|
if (indent_depth($1) >= $level) {
|
|
$help_level = indent_depth($1);
|
|
} else {
|
|
$help = 0;
|
|
}
|
|
$_ = $next;
|
|
redo;
|
|
}
|
|
|
|
if (/^\s*(config|menuconfig)\s+([a-zA-Z0-9_]+)\s*(#.*)?$/) {
|
|
$configs{$2}++;
|
|
next;
|
|
}
|
|
|
|
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*$/) {
|
|
my $s = $2;
|
|
$s =~ s/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'//g;
|
|
$s =~ s/#.*//;
|
|
$s =~ s/\$\((?:[^()]*|\((?:[^()]*|\([^()]*\))*\))*\)//g;
|
|
$s =~ s/%%[^%]*%%//g;
|
|
my @syms = split /[^a-zA-Z0-9_]+/, $s;
|
|
map {
|
|
$refs{$_}++ if (/[a-zA-Z]/ && $_ ne "if" && $_ ne "y" && $_ ne "n" && $_ ne "m" && !/^0[xX][0-9a-fA-F]+$/);
|
|
} @syms
|
|
}
|
|
}
|
|
|
|
close F;
|
|
}
|
|
|
|
my %known_syms = ();
|
|
if (defined $kconfig_sym_check_excludes) {
|
|
my $file = $kconfig_sym_check_excludes;
|
|
open(F, "<", $file) or die "Cannot open $file: $!";
|
|
while (<F>) {
|
|
chomp;
|
|
next if /^\s*$/;
|
|
next if /^\s*#/;
|
|
$known_syms{$1}++ if (/^\s*([a-zA-Z0-9_]+)\s*(#.*)?$/);
|
|
}
|
|
}
|
|
|
|
my $ret = 0;
|
|
foreach my $k (sort keys %refs) {
|
|
next if (exists $configs{$k} || exists $known_syms{$k});
|
|
|
|
print "$k";
|
|
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");
|
|
print "\n";
|
|
|
|
$ret = 1;
|
|
}
|
|
|
|
exit $ret;
|