#!/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 [excludes file]\n"; $msg .= "Please provide ."; $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 () { chomp; while (/\\\s*$/) { s/\\\s*$/ /; my $cont = // 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 = )) { 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 () { 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;