2017-05-07 23:25:26 +02:00
# ! / usr / bin / env perl
2018-06-07 17:04:33 -07:00
# SPDX - License - Identifier : GPL - 2.0
#
2010-01-12 16:59:52 -05:00
# ( c ) 2001 , Dave Jones . ( the file handling bit )
2007-06-08 13:47:06 -07:00
# ( c ) 2005 , Joel Schopp < jschopp@austin . ibm . com > ( the ugly bit )
2009-01-06 14:41:23 -08:00
# ( c ) 2007 , 2008 , Andy Whitcroft < apw@uk . ibm . com > ( new conditions , test suite )
2010-10-26 14:23:17 -07:00
# ( c ) 2008 - 2010 Andy Whitcroft < apw@canonical . com >
2018-06-07 17:04:33 -07:00
# ( c ) 2010 - 2018 Joe Perches < joe@perches . com >
2007-06-01 00:46:48 -07:00
use strict ;
2017-05-07 23:25:26 +02:00
use warnings ;
2013-07-08 16:00:43 -07:00
use POSIX ;
2014-12-10 15:51:43 -08:00
use File :: Basename ;
use Cwd 'abs_path' ;
2015-06-25 15:03:03 -07:00
use Term :: ANSIColor qw ( :constants );
2018-08-21 21:57:40 -07:00
use Encode qw ( decode encode );
2007-06-01 00:46:48 -07:00
my $ P = $ 0 ;
2014-12-10 15:51:43 -08:00
my $ D = dirname ( abs_path ( $ P ));
2007-06-01 00:46:48 -07:00
2011-07-25 17:13:25 -07:00
my $ V = '0.32' ;
2007-06-01 00:46:48 -07:00
use Getopt :: Long qw ( :config no_auto_abbrev );
my $ quiet = 0 ;
my $ tree = 1 ;
my $ chk_signoff = 1 ;
my $ chk_patch = 1 ;
2008-03-28 14:15:58 -07:00
my $ tst_only ;
2007-10-18 03:05:08 -07:00
my $ emacs = 0 ;
2007-11-28 16:21:06 -08:00
my $ terse = 0 ;
2015-06-25 15:03:05 -07:00
my $ showfile = 0 ;
2007-10-18 03:05:08 -07:00
my $ file = 0 ;
2016-05-20 17:04:16 -07:00
my $ git = 0 ;
2016-05-20 17:04:19 -07:00
my %git_commits = ();
2007-10-18 03:05:08 -07:00
my $ check = 0 ;
2014-06-04 16:12:05 -07:00
my $ check_orig = 0 ;
2007-11-28 16:21:06 -08:00
my $ summary = 1 ;
my $ mailback = 0 ;
2008-02-08 04:22:03 -08:00
my $ summary_file = 0 ;
2011-07-25 17:13:25 -07:00
my $ show_types = 0 ;
2016-05-20 17:04:14 -07:00
my $ list_types = 0 ;
2013-07-03 15:05:31 -07:00
my $ fix = 0 ;
2014-01-23 15:54:44 -08:00
my $ fix_inplace = 0 ;
2007-10-18 03:05:08 -07:00
my $ root ;
2020-10-24 16:59:04 -07:00
my $ gitroot = $ ENV { 'GIT_DIR' };
$ gitroot = ".git" if ! defined ( $ gitroot );
2008-02-08 04:20:54 -08:00
my %debug;
2013-07-03 15:05:34 -07:00
my %camelcase = ();
2013-09-11 14:23:59 -07:00
my %use_type = ();
my @use = ();
my %ignore_type = ();
2011-07-25 17:13:25 -07:00
my @ignore = ();
2009-09-21 17:04:37 -07:00
my $ help = 0 ;
2011-07-25 17:13:25 -07:00
my $ configuration_file = ".checkpatch.conf" ;
2020-05-29 16:12:21 -07:00
my $ max_line_length = 100 ;
2013-09-11 14:23:56 -07:00
my $ ignore_perl_version = 0 ;
my $ minimum_perl_version = 5.10.0 ;
2014-10-13 15:51:48 -07:00
my $ min_conf_desc_length = 4 ;
2014-10-13 15:51:57 -07:00
my $ spelling_file = "$D/spelling.txt" ;
2015-04-16 12:44:14 -07:00
my $ codespell = 0 ;
2015-06-25 15:03:08 -07:00
my $ codespellfile = "/usr/share/codespell/dictionary.txt" ;
2016-10-11 13:51:56 -07:00
my $ conststructsfile = "$D/const_structs.checkpatch" ;
2020-08-11 18:35:13 -07:00
my $ typedefsfile ;
2017-07-10 15:52:24 -07:00
my $ color = "auto" ;
2019-03-07 16:28:38 -08:00
my $ allow_c99_comments = 1 ; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
2019-09-25 16:46:52 -07:00
# git output parsing needs US English output , so first set backtick child process LANGUAGE
my $ git_command ='export LANGUAGE=en_US.UTF-8; git' ;
2020-04-06 20:11:07 -07:00
my $ tabsize = 8 ;
2020-10-15 20:11:49 -07:00
my $ { CONFIG_ } = "CONFIG_" ;
2009-09-21 17:04:37 -07:00
sub help {
my ( $ exitcode ) = @ _ ;
print << "EOM" ;
Usage : $ P [ OPTION ]... [ FILE ]...
Version : $ V
Options :
- q , --quiet quiet
--no - tree run without a kernel tree
--no - signoff do not check for 'Signed-off-by' line
--patch treat FILE as patchfile ( default )
--emacs emacs compile window format
--terse one line per report
2015-06-25 15:03:05 -07:00
--showfile emit diffed file position , not input file position
2016-05-20 17:04:16 -07:00
- g , --git treat FILE as a single commit or git revision range
single git commit with :
< rev >
< rev>^
< rev>~n
multiple git commits with :
< rev1>..<rev2 >
< rev1>...<rev2 >
< rev>-<count >
git merges are ignored
2009-09-21 17:04:37 -07:00
- f , --file treat FILE as regular source file
--subjective , --strict enable more subjective tests
2016-05-20 17:04:14 -07:00
--list - types list the possible message types
2013-09-11 14:23:59 -07:00
--types TYPE (, TYPE2 ...) show only these comma separated message types
2011-07-25 17:13:25 -07:00
--ignore TYPE (, TYPE2 ...) ignore various comma separated message types
2016-05-20 17:04:14 -07:00
--show - types show the specific message type in the output
2020-05-29 16:12:21 -07:00
--max - line - length = n set the maximum line length , ( default $ max_line_length )
if exceeded , warn on patches
requires --strict for use with --file
2014-10-13 15:51:48 -07:00
--min - conf - desc - length = n set the min description length , if shorter , warn
2020-05-29 16:12:21 -07:00
--tab - size = n set the number of spaces for tab ( default $ tabsize )
2009-09-21 17:04:37 -07:00
--root = PATH PATH to the kernel tree root
--no - summary suppress the per - file summary
--mailback only produce a report in case of warnings / errors
--summary - file include the filename in summary
--debug KEY = [ 0 | 1 ] turn on / off debugging of KEY , where KEY is one of
'values' , 'possible' , 'type' , and 'attr' ( default
is all off )
--test - only = WORD report only warnings / errors containing WORD
literally
2013-07-03 15:05:31 -07:00
--fix EXPERIMENTAL - may create horrible results
If correctable single - line errors exist , create
"<inputfile>.EXPERIMENTAL-checkpatch-fixes"
with potential errors corrected to the preferred
checkpatch style
2014-01-23 15:54:44 -08:00
--fix - inplace EXPERIMENTAL - may create horrible results
Is the same as --fix , but overwrites the input
file . It 's your fault if there's no backup or git
2013-09-11 14:23:56 -07:00
--ignore - perl - version override checking of perl version . expect
runtime errors .
2015-04-16 12:44:14 -07:00
--codespell Use the codespell dictionary for spelling / typos
2015-06-25 15:03:08 -07:00
( default : / usr / share / codespell / dictionary . txt )
2015-04-16 12:44:14 -07:00
--codespellfile Use this codespell dictionary
2017-05-08 15:56:00 -07:00
--typedefsfile Read additional types from this file
2017-07-10 15:52:24 -07:00
--color [ = WHEN ] Use colors 'always' , 'never' , or only when output
is a terminal ( 'auto' ). Default is 'auto' .
2020-10-15 20:11:49 -07:00
--kconfig - prefix = WORD use WORD as a prefix for Kconfig symbols ( default
$ { CONFIG_ })
2009-09-21 17:04:37 -07:00
- h , --help , --version display this help and exit
When FILE is - read standard input .
EOM
exit ( $ exitcode );
}
2016-05-20 17:04:14 -07:00
sub uniq {
my %seen;
return grep { ! $ seen { $ _ } ++ } @ _ ;
}
sub list_types {
my ( $ exitcode ) = @ _ ;
my $ count = 0 ;
local $ / = undef ;
open ( my $ script , '<' , abs_path ( $ P )) or
die "$P: Can't read '$P' $!\n" ;
my $ text = < $ script> ;
close ( $ script );
my @types = ();
2017-09-08 16:16:11 -07:00
# Also catch when type or level is passed through a variable
for ( $ text =~ / ( ?: ( ?:\bCHK | \bWARN | \bERROR | &\ { \ $ msg_level }) \s*\ (| \ $ msg_type\s*= ) \s* "([^" ] + ) "/g) {
2016-05-20 17:04:14 -07:00
push (@types, $_);
}
@types = sort(uniq(@types));
print(" #\tMessage type\n\n ");
foreach my $type (@types) {
print(++$count . " \t " . $type . " \n ");
}
exit($exitcode);
}
2011-07-25 17:13:25 -07:00
my $conf = which_conf($configuration_file);
if (-f $conf) {
my @conf_args;
open(my $conffile, '<', " $ conf ")
or warn " $ P : Can 't find a readable $configuration_file file $!\n";
while (<$conffile>) {
my $line = $_;
$line =~ s/\s*\n?$//g;
$line =~ s/^\s*//g;
$line =~ s/\s+/ /g;
next if ($line =~ m/^\s*#/);
next if ($line =~ m/^\s*$/);
my @words = split(" ", $line);
foreach my $word (@words) {
last if ($word =~ m/^#/);
push (@conf_args, $word);
}
}
close($conffile);
unshift(@ARGV, @conf_args) if @conf_args;
}
2017-07-10 15:52:24 -07:00
# Perl's Getopt :: Long allows options to take optional arguments after a space .
# Prevent --color by itself from consuming other arguments
foreach ( @ ARGV ) {
if ( $ _ eq "--color" || $ _ eq "-color" ) {
$ _ = "--color=$color" ;
}
}
2007-06-01 00:46:48 -07:00
GetOptions (
2007-10-18 03:05:08 -07:00
'q|quiet+' => \ $ quiet ,
2007-06-01 00:46:48 -07:00
'tree!' => \ $ tree ,
'signoff!' => \ $ chk_signoff ,
'patch!' => \ $ chk_patch ,
2007-10-18 03:05:08 -07:00
'emacs!' => \ $ emacs ,
2007-11-28 16:21:06 -08:00
'terse!' => \ $ terse ,
2015-06-25 15:03:05 -07:00
'showfile!' => \ $ showfile ,
2009-09-21 17:04:37 -07:00
'f|file!' => \ $ file ,
2016-05-20 17:04:16 -07:00
'g|git!' => \ $ git ,
2007-10-18 03:05:08 -07:00
'subjective!' => \ $ check ,
'strict!' => \ $ check ,
2011-07-25 17:13:25 -07:00
'ignore=s' => \@ignore ,
2013-09-11 14:23:59 -07:00
'types=s' => \@use ,
2011-07-25 17:13:25 -07:00
'show-types!' => \ $ show_types ,
2016-05-20 17:04:14 -07:00
'list-types!' => \ $ list_types ,
2012-12-17 16:01:54 -08:00
'max-line-length=i' => \ $ max_line_length ,
2014-10-13 15:51:48 -07:00
'min-conf-desc-length=i' => \ $ min_conf_desc_length ,
2020-04-06 20:11:07 -07:00
'tab-size=i' => \ $ tabsize ,
2007-10-18 03:05:08 -07:00
'root=s' => \ $ root ,
2007-11-28 16:21:06 -08:00
'summary!' => \ $ summary ,
'mailback!' => \ $ mailback ,
2008-02-08 04:22:03 -08:00
'summary-file!' => \ $ summary_file ,
2013-07-03 15:05:31 -07:00
'fix!' => \ $ fix ,
2014-01-23 15:54:44 -08:00
'fix-inplace!' => \ $ fix_inplace ,
2013-09-11 14:23:56 -07:00
'ignore-perl-version!' => \ $ ignore_perl_version ,
2008-02-08 04:20:54 -08:00
'debug=s' => \ %debug,
2008-03-28 14:15:58 -07:00
'test-only=s' => \ $ tst_only ,
2015-04-16 12:44:14 -07:00
'codespell!' => \ $ codespell ,
'codespellfile=s' => \ $ codespellfile ,
2017-05-08 15:56:00 -07:00
'typedefsfile=s' => \ $ typedefsfile ,
2017-07-10 15:52:24 -07:00
'color=s' => \ $ color ,
'no-color' => \ $ color , #keep old behaviors of - nocolor
'nocolor' => \ $ color , #keep old behaviors of - nocolor
2020-10-15 20:11:49 -07:00
'kconfig-prefix=s' => \ $ { CONFIG_ },
2009-09-21 17:04:37 -07:00
'h|help' => \ $ help ,
'version' => \ $ help
) or help ( 1 );
help ( 0 ) if ( $ help );
2007-06-01 00:46:48 -07:00
2016-05-20 17:04:14 -07:00
list_types ( 0 ) if ( $ list_types );
2014-01-23 15:54:44 -08:00
$ fix = 1 if ( $ fix_inplace );
2014-06-04 16:12:05 -07:00
$ check_orig = $ check ;
2014-01-23 15:54:44 -08:00
2020-06-04 16:50:40 -07:00
die "$P: --git cannot be used with --file or --fix\n" if ( $ git && ( $ file || $ fix ));
2007-06-01 00:46:48 -07:00
my $ exit = 0 ;
2018-08-21 21:57:33 -07:00
my $ perl_version_ok = 1 ;
2013-09-11 14:23:56 -07:00
if ( $ ^ V && $ ^ V lt $ minimum_perl_version ) {
2018-08-21 21:57:33 -07:00
$ perl_version_ok = 0 ;
2013-09-11 14:23:56 -07:00
printf "$P: requires at least perl version %vd\n" , $ minimum_perl_version ;
2018-08-21 21:57:33 -07:00
exit ( 1 ) if (! $ ignore_perl_version );
2013-09-11 14:23:56 -07:00
}
2016-08-02 14:04:47 -07:00
#if no filenames are given , push '-' to read patch from stdin
2007-06-01 00:46:48 -07:00
if ( $ # ARGV < 0 ) {
2016-08-02 14:04:47 -07:00
push ( @ ARGV , '-' );
2007-06-01 00:46:48 -07:00
}
2017-07-10 15:52:24 -07:00
if ( $ color =~ /^ [ 01 ] $ / ) {
$ color = ! $ color ;
} elsif ( $ color =~ /^always$ / i ) {
$ color = 1 ;
} elsif ( $ color =~ /^never$ / i ) {
$ color = 0 ;
} elsif ( $ color =~ /^auto$ / i ) {
$ color = ( - t STDOUT );
} else {
2020-06-04 16:50:40 -07:00
die "$P: Invalid color mode: $color\n" ;
2017-07-10 15:52:24 -07:00
}
2020-04-06 20:11:07 -07:00
# skip TAB size 1 to avoid additional checks on $ tabsize - 1
2020-06-04 16:50:40 -07:00
die "$P: Invalid TAB size: $tabsize\n" if ( $ tabsize < 2 );
2020-04-06 20:11:07 -07:00
2013-09-11 14:23:59 -07:00
sub hash_save_array_words {
my ( $ hashRef , $ arrayRef ) = @ _ ;
2011-07-25 17:13:25 -07:00
2013-09-11 14:23:59 -07:00
my @array = split ( / , / , join ( ',' , @ $ arrayRef ));
foreach my $ word ( @array ) {
$ word =~ s/\s*\n? $ // g ;
$ word =~ s/^\s*//g ;
$ word =~ s/\s+/ / g ;
$ word =~ tr / [ a - z ] / [ A - Z ] / ;
2011-07-25 17:13:25 -07:00
2013-09-11 14:23:59 -07:00
next if ( $ word =~ m/^\s*#/ );
next if ( $ word =~ m/^\s* $ / );
$ hashRef-> { $ word } ++ ;
}
2011-07-25 17:13:25 -07:00
}
2013-09-11 14:23:59 -07:00
sub hash_show_words {
my ( $ hashRef , $ prefix ) = @ _ ;
2015-06-25 15:03:29 -07:00
if ( keys %$hashRef) {
2015-06-25 15:03:00 -07:00
print "\nNOTE: $prefix message types:" ;
2013-09-11 14:24:04 -07:00
foreach my $ word ( sort keys %$hashRef) {
2013-09-11 14:23:59 -07:00
print " $word" ;
}
2015-06-25 15:03:00 -07:00
print "\n" ;
2013-09-11 14:23:59 -07:00
}
}
hash_save_array_words ( \ %ignore_type, \@ignore);
hash_save_array_words ( \ %use_type, \@use);
2008-02-08 04:20:54 -08:00
my $ dbg_values = 0 ;
my $ dbg_possible = 0 ;
2008-07-23 21:29:06 -07:00
my $ dbg_type = 0 ;
2008-10-15 22:02:17 -07:00
my $ dbg_attr = 0 ;
2008-02-08 04:20:54 -08:00
for my $ key ( keys %debug) {
2009-01-06 14:41:30 -08:00
## no critic
eval " \ $ { dbg_$key } = '$debug{$key}' ; ";
die " $ @ " if ($@);
2008-02-08 04:20:54 -08:00
}
2010-10-26 14:23:12 -07:00
my $rpt_cleaners = 0;
2007-11-28 16:21:06 -08:00
if ($terse) {
$emacs = 1;
$quiet++;
}
2007-10-18 03:05:08 -07:00
if ($tree) {
if (defined $root) {
if (!top_of_kernel_tree($root)) {
die " $ P : $ root : --root does not point at a valid tree\n ";
}
} else {
if (top_of_kernel_tree('.')) {
$root = '.';
} elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
top_of_kernel_tree($1)) {
$root = $1;
}
}
if (!defined $root) {
print " Must be run from the top - level dir . of a kernel tree\n " ;
exit ( 2 );
}
2007-06-01 00:46:48 -07:00
}
2007-10-18 03:05:08 -07:00
my $ emitted_corrupt = 0 ;
2009-10-26 16:50:14 -07:00
our $ Ident = qr {
[ A - Za - z_ ][ A - Za - z\d_ ] *
( ?:\s*\#\#\s * [ A - Za - z_ ][ A - Za - z\d_ ] * ) *
} x ;
2007-10-18 03:05:08 -07:00
our $ Storage = qr { extern | static | asmlinkage };
our $ Sparse = qr {
__ user |
__ kernel |
__ force |
__ iomem |
__ must_check |
2009-02-27 14:03:08 -08:00
__ kprobes |
2011-07-25 17:13:23 -07:00
__ ref |
2018-08-21 21:57:36 -07:00
__ refconst |
__ refdata |
2015-12-29 12:18:46 +08:00
__ rcu |
__ private
2007-10-18 03:05:08 -07:00
} x ;
2013-11-12 15:10:10 -08:00
our $ InitAttributePrefix = qr { __ ( ?:mem | cpu | dev | net_ |)};
our $ InitAttributeData = qr { $ InitAttributePrefix ( ?:initdata\b )};
our $ InitAttributeConst = qr { $ InitAttributePrefix ( ?:initconst\b )};
our $ InitAttributeInit = qr { $ InitAttributePrefix ( ?:init\b )};
our $ InitAttribute = qr { $ InitAttributeData | $ InitAttributeConst | $ InitAttributeInit };
2013-09-11 14:24:05 -07:00
2010-03-05 13:43:51 -08:00
# Notes to $ Attribute :
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
2007-10-18 03:05:08 -07:00
our $ Attribute = qr {
const |
2021-02-25 17:21:40 -08:00
volatile |
2010-10-26 14:23:16 -07:00
__ percpu |
__ nocast |
__ safe |
2016-12-11 06:29:58 +02:00
__ bitwise |
2010-10-26 14:23:16 -07:00
__ packed__ |
__ packed2__ |
__ naked |
__ maybe_unused |
__ always_unused |
__ noreturn |
__ used |
__ cold |
2015-02-13 14:38:24 -08:00
__ pure |
2010-10-26 14:23:16 -07:00
__ noclone |
__ deprecated |
2007-10-18 03:05:08 -07:00
__ read_mostly |
2018-09-04 15:46:20 -07:00
__ ro_after_init |
2007-10-18 03:05:08 -07:00
__ kprobes |
2013-09-11 14:24:05 -07:00
$ InitAttribute |
2008-10-15 22:02:18 -07:00
____ cacheline_aligned |
____ cacheline_aligned_in_smp |
2009-01-06 14:41:18 -08:00
____ cacheline_internodealigned_in_smp |
__ weak
2007-10-18 03:05:08 -07:00
} x ;
2008-06-05 22:46:01 -07:00
our $ Modifier ;
2014-04-03 14:49:32 -07:00
our $ Inline = qr { inline | __ always_inline | noinline | __ inline | __ inline__ };
2007-10-18 03:05:08 -07:00
our $ Member = qr { -> $ Ident | \. $ Ident | \ [[ ^ ]] *\ ]};
our $ Lval = qr { $ Ident ( ?: $ Member ) * };
2013-07-03 15:05:20 -07:00
our $ Int_type = qr {( ?i ) llu | ull | ll | lu | ul | l | u };
our $ Binary = qr {( ?i ) 0 b [ 01 ] + $ Int_type ? };
our $ Hex = qr {( ?i ) 0 x [ 0 - 9 a - f ] + $ Int_type ? };
our $ Int = qr {[ 0 - 9 ] + $ Int_type ? };
2014-04-03 14:49:13 -07:00
our $ Octal = qr { 0 [ 0 - 7 ] + $ Int_type ? };
2015-02-13 14:38:21 -08:00
our $ String = qr { "[X\t]*" };
2013-02-04 14:28:51 -08:00
our $ Float_hex = qr {( ?i ) 0 x [ 0 - 9 a - f ] + p-? [ 0 - 9 ] + [ fl ] ? };
our $ Float_dec = qr {( ?i )( ?: [ 0 - 9 ] +\. [ 0 - 9 ] * |[ 0 - 9 ] *\. [ 0 - 9 ] + )( ?:e-? [ 0 - 9 ] + ) ? [ fl ] ? };
our $ Float_int = qr {( ?i )[ 0 - 9 ] + e-? [ 0 - 9 ] + [ fl ] ? };
2012-12-17 16:02:05 -08:00
our $ Float = qr { $ Float_hex | $ Float_dec | $ Float_int };
2014-04-03 14:49:13 -07:00
our $ Constant = qr { $ Float | $ Binary | $ Octal | $ Hex | $ Int };
2013-02-04 14:28:51 -08:00
our $ Assignment = qr { \*\= | /= | %=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
2014-04-03 14:49:17 -07:00
our $ Compare = qr { <= | >= | == |! = | < |( ?< ! - ) > };
2013-07-03 15:05:31 -07:00
our $ Arithmetic = qr { \+ | - | \* | \/ | %};
2007-10-18 03:05:08 -07:00
our $ Operators = qr {
<= | >= | == |! = |
=> | -> | << | >> | < | > |!| ~ |
2013-07-03 15:05:31 -07:00
&& | \ | \ ||,| \^ | \+\+ | -- | & | \ || $ Arithmetic
2007-10-18 03:05:08 -07:00
} x ;
2014-04-03 14:49:32 -07:00
our $ c90_Keywords = qr { do | for | while | if | else | return | goto | continue | switch | default | case | break } x ;
2015-04-16 12:44:22 -07:00
our $ BasicType ;
2007-11-28 16:21:06 -08:00
our $ NonptrType ;
2014-08-06 16:11:22 -07:00
our $ NonptrTypeMisordered ;
2013-09-11 14:24:05 -07:00
our $ NonptrTypeWithAttr ;
2007-11-28 16:21:06 -08:00
our $ Type ;
2014-08-06 16:11:22 -07:00
our $ TypeMisordered ;
2007-11-28 16:21:06 -08:00
our $ Declare ;
2014-08-06 16:11:22 -07:00
our $ DeclareMisordered ;
2007-11-28 16:21:06 -08:00
2011-10-31 17:13:12 -07:00
our $ NON_ASCII_UTF8 = qr {
[ \xC2-\xDF ][ \x80-\xBF ] # non - overlong 2 - byte
2008-04-29 00:59:32 -07:00
| \xE0 [ \xA0-\xBF ][ \x80-\xBF ] # excluding overlongs
| [ \xE1-\xEC\xEE\xEF ][ \x80-\xBF ]{ 2 } # straight 3 - byte
| \xED [ \x80-\x9F ][ \x80-\xBF ] # excluding surrogates
| \xF0 [ \x90-\xBF ][ \x80-\xBF ]{ 2 } # planes 1 - 3
| [ \xF1-\xF3 ][ \x80-\xBF ]{ 3 } # planes 4 - 15
| \xF4 [ \x80-\x8F ][ \x80-\xBF ]{ 2 } # plane 16
} x ;
2011-10-31 17:13:12 -07:00
our $ UTF8 = qr {
[ \x09\x0A\x0D\x20-\x7E ] # ASCII
| $ NON_ASCII_UTF8
} x ;
2015-06-25 15:02:49 -07:00
our $ typeC99Typedefs = qr {( ?: __ ) ? ( ?: [ us ] _ ? ) ?int_? ( ?: 8 | 16 | 32 | 64 ) _ t };
2015-02-13 14:38:43 -08:00
our $ typeOtherOSTypedefs = qr {( ? x :
u_ ( ?:char | short | int | long ) | # bsd
u ( ?:nchar | short | int | long ) # sysv
)};
2015-06-25 15:02:49 -07:00
our $ typeKernelTypedefs = qr {( ? x :
2009-09-21 17:04:38 -07:00
( ?: __ ) ? ( ?:u | s | be | le )( ?: 8 | 16 | 32 | 64 )|
2008-10-15 22:02:32 -07:00
atomic_t
)};
2015-06-25 15:02:49 -07:00
our $ typeTypedefs = qr {( ? x :
$ typeC99Typedefs\b |
$ typeOtherOSTypedefs\b |
$ typeKernelTypedefs\b
)};
2008-10-15 22:02:32 -07:00
2015-11-06 16:31:37 -08:00
our $ zero_initializer = qr {( ?: ( ?: 0 [ xX ]) ? 0 + $ Int_type ? | NULL | false ) \b };
2010-03-05 13:43:51 -08:00
our $ logFunctions = qr {( ? x :
2017-02-24 15:01:34 -08:00
printk ( ?: _ ratelimited | _ once | _ deferred_once | _ deferred |)|
2013-07-03 15:05:35 -07:00
( ?: [ a - z0 - 9 ] + _ ){ 1 , 2 }( ?:printk | emerg | alert | crit | err | warning | warn | notice | info | debug | dbg | vdbg | devel | cont | WARN )( ?: _ ratelimited | _ once |)|
2017-11-17 15:28:48 -08:00
TP_printk |
2011-07-25 17:13:27 -07:00
WARN ( ?: _ RATELIMIT | _ ONCE |)|
2011-05-24 17:13:40 -07:00
panic |
2013-11-12 15:10:07 -08:00
MODULE_ [ A - Z_ ] + |
seq_vprintf | seq_printf | seq_puts
2010-03-05 13:43:51 -08:00
)};
2019-03-07 16:28:35 -08:00
our $ allocFunctions = qr {( ? x :
( ?: ( ?:devm_ ) ?
2021-02-25 17:22:01 -08:00
( ?:kv | k | v )[ czm ] alloc ( ?: _ array ) ? ( ?: _ node ) ? |
2019-03-07 16:28:35 -08:00
kstrdup ( ?: _ const ) ? |
kmemdup ( ?: _ nul ) ? ) |
2020-04-20 18:13:58 -07:00
( ?:\w+ ) ? alloc_skb ( ?: _ ip_align ) ? |
2019-03-07 16:28:35 -08:00
# dev_alloc_skb / netdev_alloc_skb , et al
dma_alloc_coherent
)};
2011-07-25 17:13:23 -07:00
our $ signature_tags = qr {( ? xi :
Signed - off - by :|
2019-01-03 15:29:12 -08:00
Co - developed - by :|
2011-07-25 17:13:23 -07:00
Acked - by :|
Tested - by :|
Reviewed - by :|
Reported - by :|
2013-04-29 16:18:17 -07:00
Suggested - by :|
2011-07-25 17:13:23 -07:00
To : |
Cc :
)};
2021-02-25 17:21:50 -08:00
our $ tracing_logging_tags = qr {( ? xi :
[ =- ] *> |
< [ =- ] * |
\ [ |
\ ] |
start |
called |
entered |
entry |
enter |
in |
inside |
here |
begin |
exit |
end |
done |
leave |
completed |
out |
return |
[ \.\ ! :\s ] *
)};
2020-12-15 20:45:12 -08:00
sub edit_distance_min {
my ( @arr ) = @ _ ;
my $ len = scalar @arr ;
if (( scalar @arr ) < 1 ) {
# if underflow , return
return ;
}
my $ min = $ arr [ 0 ];
for my $ i ( 0 .. ( $ len - 1 )) {
if ( $ arr [ $ i ] < $ min ) {
$ min = $ arr [ $ i ];
}
}
return $ min ;
}
sub get_edit_distance {
my ( $ str1 , $ str2 ) = @ _ ;
$ str1 = lc ( $ str1 );
$ str2 = lc ( $ str2 );
$ str1 =~ s/-//g ;
$ str2 =~ s/-//g ;
my $ len1 = length ( $ str1 );
my $ len2 = length ( $ str2 );
# two dimensional array storing minimum edit distance
my @distance ;
for my $ i ( 0 .. $ len1 ) {
for my $ j ( 0 .. $ len2 ) {
if ( $ i == 0 ) {
$ distance [ $ i ][ $ j ] = $ j ;
} elsif ( $ j == 0 ) {
$ distance [ $ i ][ $ j ] = $ i ;
} elsif ( substr ( $ str1 , $ i - 1 , 1 ) eq substr ( $ str2 , $ j - 1 , 1 )) {
$ distance [ $ i ][ $ j ] = $ distance [ $ i - 1 ][ $ j - 1 ];
} else {
my $ dist1 = $ distance [ $ i ][ $ j - 1 ]; #insert distance
my $ dist2 = $ distance [ $ i - 1 ][ $ j ]; # remove
my $ dist3 = $ distance [ $ i - 1 ][ $ j - 1 ]; #replace
$ distance [ $ i ][ $ j ] = 1 + edit_distance_min ( $ dist1 , $ dist2 , $ dist3 );
}
}
}
return $ distance [ $ len1 ][ $ len2 ];
}
sub find_standard_signature {
my ( $ sign_off ) = @ _ ;
my @standard_signature_tags = (
'Signed-off-by:' , 'Co-developed-by:' , 'Acked-by:' , 'Tested-by:' ,
'Reviewed-by:' , 'Reported-by:' , 'Suggested-by:'
);
foreach my $ signature ( @standard_signature_tags ) {
return $ signature if ( get_edit_distance ( $ sign_off , $ signature ) <= 2 );
}
return "" ;
}
2014-08-06 16:11:22 -07:00
our @typeListMisordered = (
qr { char\s+ ( ?:un ) ?signed },
qr { int\s+ ( ?: ( ?:un ) ?signed\s+ ) ?short\s },
qr { int\s + short ( ?:\s+ ( ?:un ) ?signed )},
qr { short\s + int ( ?:\s+ ( ?:un ) ?signed )},
qr {( ?:un ) ?signed\s + int\s + short },
qr { short\s+ ( ?:un ) ?signed },
qr { long\s + int\s+ ( ?:un ) ?signed },
qr { int\s + long\s+ ( ?:un ) ?signed },
qr { long\s+ ( ?:un ) ?signed\s + int },
qr { int\s+ ( ?:un ) ?signed\s + long },
qr { int\s+ ( ?:un ) ?signed },
qr { int\s + long\s + long\s+ ( ?:un ) ?signed },
qr { long\s + long\s + int\s+ ( ?:un ) ?signed },
qr { long\s + long\s+ ( ?:un ) ?signed\s + int },
qr { long\s + long\s+ ( ?:un ) ?signed },
qr { long\s+ ( ?:un ) ?signed },
);
2007-11-28 16:21:06 -08:00
our @typeList = (
qr { void },
2014-08-06 16:11:20 -07:00
qr {( ?: ( ?:un ) ?signed\s+ ) ?char },
qr {( ?: ( ?:un ) ?signed\s+ ) ?short\s + int },
qr {( ?: ( ?:un ) ?signed\s+ ) ?short },
qr {( ?: ( ?:un ) ?signed\s+ ) ?int },
qr {( ?: ( ?:un ) ?signed\s+ ) ?long\s + int },
qr {( ?: ( ?:un ) ?signed\s+ ) ?long\s + long\s + int },
qr {( ?: ( ?:un ) ?signed\s+ ) ?long\s + long },
qr {( ?: ( ?:un ) ?signed\s+ ) ?long },
qr {( ?:un ) ?signed },
2007-11-28 16:21:06 -08:00
qr { float },
qr { double },
qr { bool },
qr { struct\s+ $ Ident },
qr { union\s+ $ Ident },
qr { enum\s+ $ Ident },
qr { $ { Ident } _ t },
qr { $ { Ident } _ handler },
qr { $ { Ident } _ handler_fn },
2014-08-06 16:11:22 -07:00
@typeListMisordered ,
2007-11-28 16:21:06 -08:00
);
2016-01-20 14:59:15 -08:00
our $ C90_int_types = qr {( ? x :
long\s + long\s + int\s+ ( ?:un ) ?signed |
long\s + long\s+ ( ?:un ) ?signed\s + int |
long\s + long\s+ ( ?:un ) ?signed |
( ?: ( ?:un ) ?signed\s+ ) ?long\s + long\s + int |
( ?: ( ?:un ) ?signed\s+ ) ?long\s + long |
int\s + long\s + long\s+ ( ?:un ) ?signed |
int\s+ ( ?: ( ?:un ) ?signed\s+ ) ?long\s + long |
long\s + int\s+ ( ?:un ) ?signed |
long\s+ ( ?:un ) ?signed\s + int |
long\s+ ( ?:un ) ?signed |
( ?: ( ?:un ) ?signed\s+ ) ?long\s + int |
( ?: ( ?:un ) ?signed\s+ ) ?long |
int\s + long\s+ ( ?:un ) ?signed |
int\s+ ( ?: ( ?:un ) ?signed\s+ ) ?long |
int\s+ ( ?:un ) ?signed |
( ?: ( ?:un ) ?signed\s+ ) ?int
)};
2015-06-25 15:02:52 -07:00
our @typeListFile = ();
2013-09-11 14:24:05 -07:00
our @typeListWithAttr = (
@typeList ,
qr { struct\s+ $ InitAttribute \s+ $ Ident },
qr { union\s+ $ InitAttribute \s+ $ Ident },
);
2008-06-05 22:46:01 -07:00
our @modifierList = (
qr { fastcall },
);
2015-06-25 15:02:52 -07:00
our @modifierListFile = ();
2007-11-28 16:21:06 -08:00
2014-04-03 14:49:13 -07:00
our @mode_permission_funcs = (
[ "module_param" , 3 ],
[ "module_param_(?:array|named|string)" , 4 ],
[ "module_param_array_named" , 5 ],
[ "debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)" , 2 ],
[ "proc_create(?:_data|)" , 2 ],
2016-10-11 13:52:19 -07:00
[ "(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR" , 2 ],
[ "IIO_DEV_ATTR_[A-Z_]+" , 1 ],
[ "SENSOR_(?:DEVICE_|)ATTR_2" , 2 ],
[ "SENSOR_TEMPLATE(?:_2|)" , 3 ],
[ "__ATTR" , 2 ],
2014-04-03 14:49:13 -07:00
);
2020-08-11 18:35:16 -07:00
my $ word_pattern = '\b[A-Z]?[a-z]{2,}\b' ;
2014-04-03 14:49:24 -07:00
# Create a search pattern for all these functions to speed up a loop below
our $ mode_perms_search = "" ;
foreach my $ entry ( @mode_permission_funcs ) {
$ mode_perms_search . = '|' if ( $ mode_perms_search ne "" );
$ mode_perms_search . = $ entry-> [ 0 ];
}
2018-02-06 15:38:55 -08:00
$ mode_perms_search = "(?:${mode_perms_search})" ;
2014-04-03 14:49:24 -07:00
2018-09-07 15:26:18 -07:00
our %deprecated_apis = (
"synchronize_rcu_bh" => "synchronize_rcu" ,
"synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited" ,
"call_rcu_bh" => "call_rcu" ,
"rcu_barrier_bh" => "rcu_barrier" ,
"synchronize_sched" => "synchronize_rcu" ,
"synchronize_sched_expedited" => "synchronize_rcu_expedited" ,
"call_rcu_sched" => "call_rcu" ,
"rcu_barrier_sched" => "rcu_barrier" ,
"get_state_synchronize_sched" => "get_state_synchronize_rcu" ,
"cond_synchronize_sched" => "cond_synchronize_rcu" ,
);
# Create a search pattern for all these strings to speed up a loop below
our $ deprecated_apis_search = "" ;
foreach my $ entry ( keys %deprecated_apis) {
$ deprecated_apis_search . = '|' if ( $ deprecated_apis_search ne "" );
$ deprecated_apis_search . = $ entry ;
}
$ deprecated_apis_search = "(?:${deprecated_apis_search})" ;
2015-04-16 12:44:16 -07:00
our $ mode_perms_world_writable = qr {
S_IWUGO |
S_IWOTH |
S_IRWXUGO |
S_IALLUGO |
0 [ 0 - 7 ][ 0 - 7 ][ 2367 ]
} x ;
2016-10-11 13:51:47 -07:00
our %mode_permission_string_types = (
"S_IRWXU" => 0700 ,
"S_IRUSR" => 0400 ,
"S_IWUSR" => 0200 ,
"S_IXUSR" => 0100 ,
"S_IRWXG" => 0070 ,
"S_IRGRP" => 0040 ,
"S_IWGRP" => 0020 ,
"S_IXGRP" => 0010 ,
"S_IRWXO" => 0007 ,
"S_IROTH" => 0004 ,
"S_IWOTH" => 0002 ,
"S_IXOTH" => 0001 ,
"S_IRWXUGO" => 0777 ,
"S_IRUGO" => 0444 ,
"S_IWUGO" => 0222 ,
"S_IXUGO" => 0111 ,
);
# Create a search pattern for all these strings to speed up a loop below
our $ mode_perms_string_search = "" ;
foreach my $ entry ( keys %mode_permission_string_types) {
$ mode_perms_string_search . = '|' if ( $ mode_perms_string_search ne "" );
$ mode_perms_string_search . = $ entry ;
}
2018-02-06 15:38:55 -08:00
our $ single_mode_perms_string_search = "(?:${mode_perms_string_search})" ;
our $ multi_mode_perms_string_search = qr {
$ { single_mode_perms_string_search }
( ?:\s*\ | \s* $ { single_mode_perms_string_search }) *
} x ;
sub perms_to_octal {
my ( $ string ) = @ _ ;
return trim ( $ string ) if ( $ string =~ /^\s * 0 [ 0 - 7 ]{ 3 , 3 } \s* $ / );
my $ val = "" ;
my $ oval = "" ;
my $ to = 0 ;
my $ curpos = 0 ;
my $ lastpos = 0 ;
while ( $ string =~ /\ b (( $ single_mode_perms_string_search ) \ b ( ?:\s*\ | \s* ) ?\s* ) / g ) {
$ curpos = pos ( $ string );
my $ match = $ 2 ;
my $ omatch = $ 1 ;
last if ( $ lastpos > 0 && ( $ curpos - length ( $ omatch ) ! = $ lastpos ));
$ lastpos = $ curpos ;
$ to | = $ mode_permission_string_types { $ match };
$ val . = '\s*\|\s*' if ( $ val ne "" );
$ val . = $ match ;
$ oval . = $ omatch ;
}
$ oval =~ s/^\s*\ | \s*// ;
$ oval =~ s/\s*\ | \s* $ // ;
return sprintf ( "%04o" , $ to );
}
2016-10-11 13:51:47 -07:00
2010-08-09 17:20:57 -07:00
our $ allowed_asm_includes = qr {( ? x :
irq |
2014-10-13 15:51:44 -07:00
memory |
time |
reboot
2010-08-09 17:20:57 -07:00
)};
# memory . h : ARM has a custom one
2014-10-13 15:51:57 -07:00
# Load common spelling mistakes and build regular expression list .
my $ misspellings ;
my %spelling_fix;
2014-12-10 15:51:43 -08:00
if ( open ( my $ spelling , '<' , $ spelling_file )) {
while ( < $ spelling> ) {
my $ line = $ _ ;
2014-10-13 15:51:57 -07:00
2014-12-10 15:51:43 -08:00
$ line =~ s/\s*\n? $ // g ;
$ line =~ s/^\s*//g ;
2014-10-13 15:51:57 -07:00
2014-12-10 15:51:43 -08:00
next if ( $ line =~ m/^\s*#/ );
next if ( $ line =~ m/^\s* $ / );
2014-10-13 15:51:57 -07:00
2014-12-10 15:51:43 -08:00
my ( $ suspect , $ fix ) = split ( /\ | \ | / , $ line );
$ spelling_fix { $ suspect } = $ fix ;
}
close ( $ spelling );
} else {
warn "No typos will be found - file '$spelling_file': $!\n" ;
2014-10-13 15:51:57 -07:00
}
2015-04-16 12:44:14 -07:00
if ( $ codespell ) {
if ( open ( my $ spelling , '<' , $ codespellfile )) {
while ( < $ spelling> ) {
my $ line = $ _ ;
$ line =~ s/\s*\n? $ // g ;
$ line =~ s/^\s*//g ;
next if ( $ line =~ m/^\s*#/ );
next if ( $ line =~ m/^\s* $ / );
next if ( $ line =~ m/ , disabled / i );
$ line =~ s/ ,. * $ // ;
my ( $ suspect , $ fix ) = split ( /->/ , $ line );
$ spelling_fix { $ suspect } = $ fix ;
}
close ( $ spelling );
} else {
warn "No codespell typos will be found - file '$codespellfile': $!\n" ;
}
}
$ misspellings = join ( "|" , sort keys %spelling_fix) if keys %spelling_fix;
2017-05-08 15:56:00 -07:00
sub read_words {
my ( $ wordsRef , $ file ) = @ _ ;
2016-10-11 13:51:56 -07:00
2017-05-08 15:56:00 -07:00
if ( open ( my $ words , '<' , $ file )) {
while ( < $ words> ) {
my $ line = $ _ ;
2016-10-11 13:51:56 -07:00
2017-05-08 15:56:00 -07:00
$ line =~ s/\s*\n? $ // g ;
$ line =~ s/^\s*//g ;
next if ( $ line =~ m/^\s*#/ );
next if ( $ line =~ m/^\s* $ / );
if ( $ line =~ /\s/ ) {
print ( "$file: '$line' invalid - ignored\n" );
next ;
}
2020-08-11 18:35:13 -07:00
$$ wordsRef . = '|' if ( defined $$ wordsRef );
2017-05-08 15:56:00 -07:00
$$ wordsRef . = $ line ;
2016-10-11 13:51:56 -07:00
}
2017-05-08 15:56:00 -07:00
close ( $ file );
return 1 ;
2016-10-11 13:51:56 -07:00
}
2017-05-08 15:56:00 -07:00
return 0 ;
2016-10-11 13:51:56 -07:00
}
2020-08-11 18:35:13 -07:00
my $ const_structs ;
if ( show_type ( "CONST_STRUCT" )) {
read_words ( \ $ const_structs , $ conststructsfile )
or warn "No structs that should be const will be found - file '$conststructsfile': $!\n" ;
}
2017-05-08 15:56:00 -07:00
2020-08-11 18:35:13 -07:00
if ( defined ( $ typedefsfile )) {
my $ typeOtherTypedefs ;
2017-05-08 15:56:00 -07:00
read_words ( \ $ typeOtherTypedefs , $ typedefsfile )
or warn "No additional types will be considered - file '$typedefsfile': $!\n" ;
2020-08-11 18:35:13 -07:00
$ typeTypedefs . = '|' . $ typeOtherTypedefs if ( defined $ typeOtherTypedefs );
2017-05-08 15:56:00 -07:00
}
2007-11-28 16:21:06 -08:00
sub build_types {
2015-06-25 15:02:52 -07:00
my $ mods = "(?x: \n" . join ( "|\n " , ( @modifierList , @modifierListFile )) . "\n)" ;
my $ all = "(?x: \n" . join ( "|\n " , ( @typeList , @typeListFile )) . "\n)" ;
2014-08-06 16:11:22 -07:00
my $ Misordered = "(?x: \n" . join ( "|\n " , @typeListMisordered ) . "\n)" ;
2013-09-11 14:24:05 -07:00
my $ allWithAttr = "(?x: \n" . join ( "|\n " , @typeListWithAttr ) . "\n)" ;
2008-07-23 21:28:57 -07:00
$ Modifier = qr {( ?: $ Attribute | $ Sparse | $ mods )};
2015-04-16 12:44:22 -07:00
$ BasicType = qr {
( ?: $ typeTypedefs\b )|
( ?: $ { all } \b )
} x ;
2007-11-28 16:21:06 -08:00
$ NonptrType = qr {
2008-07-23 21:29:07 -07:00
( ?: $ Modifier \s+ | const\s+ ) *
2008-03-04 14:28:20 -08:00
( ?:
2012-01-10 15:10:13 -08:00
( ?:typeof | __ typeof__ ) \s*\ ([ ^\ )] *\ )|
2008-10-15 22:02:32 -07:00
( ?: $ typeTypedefs\b )|
2008-06-05 22:46:01 -07:00
( ?: $ { all } \b )
2008-03-04 14:28:20 -08:00
)
2008-07-23 21:28:57 -07:00
( ?:\s+ $ Modifier | \s + const ) *
2007-11-28 16:21:06 -08:00
} x ;
2014-08-06 16:11:22 -07:00
$ NonptrTypeMisordered = qr {
( ?: $ Modifier \s+ | const\s+ ) *
( ?:
( ?: $ { Misordered } \b )
)
( ?:\s+ $ Modifier | \s + const ) *
} x ;
2013-09-11 14:24:05 -07:00
$ NonptrTypeWithAttr = qr {
( ?: $ Modifier \s+ | const\s+ ) *
( ?:
( ?:typeof | __ typeof__ ) \s*\ ([ ^\ )] *\ )|
( ?: $ typeTypedefs\b )|
( ?: $ { allWithAttr } \b )
)
( ?:\s+ $ Modifier | \s + const ) *
} x ;
2007-11-28 16:21:06 -08:00
$ Type = qr {
2008-06-05 22:46:01 -07:00
$ NonptrType
2020-04-06 20:11:04 -07:00
( ?: ( ?:\s | \* | \ [ \ ]) +\s * const |( ?:\s | \*\s* ( ?:const\s* ) ? | \ [ \ ]) + |( ?:\s*\ [ \s*\ ]) + ){ 0 , 4 }
2008-07-23 21:28:57 -07:00
( ?:\s+ $ Inline | \s+ $ Modifier ) *
2007-11-28 16:21:06 -08:00
} x ;
2014-08-06 16:11:22 -07:00
$ TypeMisordered = qr {
$ NonptrTypeMisordered
2020-04-06 20:11:04 -07:00
( ?: ( ?:\s | \* | \ [ \ ]) +\s * const |( ?:\s | \*\s* ( ?:const\s* ) ? | \ [ \ ]) + |( ?:\s*\ [ \s*\ ]) + ){ 0 , 4 }
2014-08-06 16:11:22 -07:00
( ?:\s+ $ Inline | \s+ $ Modifier ) *
} x ;
2014-04-03 14:49:32 -07:00
$ Declare = qr {( ?: $ Storage \s+ ( ?: $ Inline \s+ ) ? ) ? $ Type };
2014-08-06 16:11:22 -07:00
$ DeclareMisordered = qr {( ?: $ Storage \s+ ( ?: $ Inline \s+ ) ? ) ? $ TypeMisordered };
2007-11-28 16:21:06 -08:00
}
build_types ();
2007-10-18 03:05:08 -07:00
2011-07-25 17:13:22 -07:00
our $ Typecast = qr { \s* ( \ ( \s* $ NonptrType \s*\ )){ 0 , 1 } \s* };
2012-03-23 15:02:16 -07:00
# Using $ balanced_parens , $ LvalOrFunc , or $ FuncArg
# requires at least perl version v5 .10.0
# Any use must be runtime checked with $ ^ V
our $ balanced_parens = qr/ ( \ (( ?: [ ^\ ( \ )] ++ |( ?- 1 )) *\ )) / ;
2014-04-03 14:49:13 -07:00
our $ LvalOrFunc = qr {(( ?: [ \&\* ] \s* ) ? $ Lval ) \s* ( $ balanced_parens { 0 , 1 }) \s* };
2015-02-13 14:38:21 -08:00
our $ FuncArg = qr { $ Typecast { 0 , 1 }( $ LvalOrFunc | $ Constant | $ String )};
2011-07-25 17:13:22 -07:00
2014-08-06 16:11:31 -07:00
our $ declaration_macros = qr {( ? x :
2015-09-09 15:37:33 -07:00
( ?: $ Storage \s+ ) ? ( ?: [ A - Z_ ][ A - Z0 - 9 ] * _ ){ 0 , 2 }( ?: DEFINE | DECLARE )( ?: _ [ A - Z0 - 9 ] + ){ 1 , 6 } \s*\ (|
2017-07-10 15:52:10 -07:00
( ?: $ Storage \s+ ) ? [ HLP ] ? LIST_HEAD \s*\ (|
2018-04-10 16:33:17 -07:00
( ?: SKCIPHER_REQUEST | SHASH_DESC | AHASH_REQUEST ) _ ON_STACK \s*\ (
2014-08-06 16:11:31 -07:00
)};
2020-12-15 20:44:24 -08:00
our %allow_repeated_words = (
add => '' ,
added => '' ,
bad => '' ,
be => '' ,
);
2011-07-25 17:13:22 -07:00
sub deparenthesize {
my ( $ string ) = @ _ ;
return "" if (! defined ( $ string ));
2014-04-03 14:49:21 -07:00
while ( $ string =~ /^\s*\ (. *\ ) \s* $ / ) {
$ string =~ s@^\s*\ ( \s*@@ ;
$ string =~ s@\s*\ ) \s* $ @@ ;
}
2011-07-25 17:13:22 -07:00
$ string =~ s@\s+@ @g ;
2014-04-03 14:49:21 -07:00
2011-07-25 17:13:22 -07:00
return $ string ;
}
2013-07-03 15:05:34 -07:00
sub seed_camelcase_file {
my ( $ file ) = @ _ ;
return if (!( - f $ file ));
local $ / ;
open ( my $ include_file , '<' , "$file" )
or warn "$P: Can't read '$file' $!\n" ;
my $ text = < $ include_file> ;
close ( $ include_file );
my @lines = split ( '\n' , $ text );
foreach my $ line ( @lines ) {
next if ( $ line ! ~ / ( ?: [ A - Z ][ a - z ]|[ a - z ][ A - Z ]) / );
if ( $ line =~ /^ [ \t ] * ( ?:# [ \t ] * define | typedef\s+ $ Type ) \s+ ( \w* ( ?: [ A - Z ][ a - z ]|[ a - z ][ A - Z ]) \w* ) / ) {
$ camelcase { $ 1 } = 1 ;
2013-11-12 15:10:08 -08:00
} elsif ( $ line =~ /^\s* $ Declare \s+ ( \w* ( ?: [ A - Z ][ a - z ]|[ a - z ][ A - Z ]) \w* ) \s * [ \ ( \ [,;] / ) {
$ camelcase { $ 1 } = 1 ;
} elsif ( $ line =~ /^\s* ( ?:union | struct | enum ) \s+ ( \w* ( ?: [ A - Z ][ a - z ]|[ a - z ][ A - Z ]) \w* ) \s * [; \ {] / ) {
2013-07-03 15:05:34 -07:00
$ camelcase { $ 1 } = 1 ;
}
}
}
2019-12-04 16:52:09 -08:00
our %maintained_status = ();
2016-10-11 13:51:44 -07:00
sub is_maintained_obsolete {
my ( $ filename ) = @ _ ;
2016-12-12 16:46:23 -08:00
return 0 if (! $ tree || !( - e "$root/scripts/get_maintainer.pl" ));
2016-10-11 13:51:44 -07:00
2019-12-04 16:52:09 -08:00
if (! exists ( $ maintained_status { $ filename })) {
$ maintained_status { $ filename } = ` perl $ root / scripts / get_maintainer . pl --status --nom --nol --nogit --nogit - fallback - f $ filename 2 >& 1 ` ;
}
2016-10-11 13:51:44 -07:00
2019-12-04 16:52:09 -08:00
return $ maintained_status { $ filename } =~ / obsolete / i ;
2016-10-11 13:51:44 -07:00
}
2018-08-21 21:57:47 -07:00
sub is_SPDX_License_valid {
my ( $ license ) = @ _ ;
2020-10-24 16:59:04 -07:00
return 1 if (! $ tree || which ( "python" ) eq "" || !( - e "$root/scripts/spdxcheck.py" ) || !( - e "$gitroot" ));
2018-08-21 21:57:47 -07:00
2018-08-21 21:58:04 -07:00
my $ root_path = abs_path ( $ root );
my $ status = ` cd "$root_path" ; echo "$license" | python scripts / spdxcheck . py - ` ;
2018-08-21 21:57:47 -07:00
return 0 if ( $ status ne "" );
return 1 ;
}
2013-07-03 15:05:34 -07:00
my $ camelcase_seeded = 0 ;
sub seed_camelcase_includes {
return if ( $ camelcase_seeded );
my $ files ;
2013-07-08 16:00:43 -07:00
my $ camelcase_cache = "" ;
my @include_files = ();
$ camelcase_seeded = 1 ;
2013-07-03 15:05:36 -07:00
2020-10-24 16:59:04 -07:00
if ( - e "$gitroot" ) {
2019-09-25 16:46:52 -07:00
my $ git_last_include_commit = `$ { git_command } log --no - merges --pretty = format : "%h%n" - 1 -- include ` ;
2013-07-03 15:05:36 -07:00
chomp $ git_last_include_commit ;
2013-07-08 16:00:43 -07:00
$ camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit" ;
2013-07-03 15:05:34 -07:00
} else {
2013-07-08 16:00:43 -07:00
my $ last_mod_date = 0 ;
2013-07-03 15:05:34 -07:00
$ files = ` find $ root / include - name "*.h" ` ;
2013-07-08 16:00:43 -07:00
@include_files = split ( '\n' , $ files );
foreach my $ file ( @include_files ) {
my $ date = POSIX :: strftime ( "%Y%m%d%H%M" ,
localtime (( stat $ file )[ 9 ]));
$ last_mod_date = $ date if ( $ last_mod_date < $ date );
}
$ camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date" ;
2013-07-03 15:05:34 -07:00
}
2013-07-08 16:00:43 -07:00
if ( $ camelcase_cache ne "" && - f $ camelcase_cache ) {
open ( my $ camelcase_file , '<' , "$camelcase_cache" )
or warn "$P: Can't read '$camelcase_cache' $!\n" ;
while ( < $ camelcase_file> ) {
chomp ;
$ camelcase { $ _ } = 1 ;
}
close ( $ camelcase_file );
return ;
}
2020-10-24 16:59:04 -07:00
if ( - e "$gitroot" ) {
2019-09-25 16:46:52 -07:00
$ files = `$ { git_command } ls - files "include/*.h" ` ;
2013-07-08 16:00:43 -07:00
@include_files = split ( '\n' , $ files );
}
2013-07-03 15:05:34 -07:00
foreach my $ file ( @include_files ) {
seed_camelcase_file ( $ file );
}
2013-07-03 15:05:36 -07:00
2013-07-08 16:00:43 -07:00
if ( $ camelcase_cache ne "" ) {
2013-07-03 15:05:36 -07:00
unlink glob ".checkpatch-camelcase.*" ;
2013-07-08 16:00:43 -07:00
open ( my $ camelcase_file , '>' , "$camelcase_cache" )
or warn "$P: Can't write '$camelcase_cache' $!\n" ;
2013-07-03 15:05:36 -07:00
foreach ( sort { lc ( $ a ) cmp lc ( $ b ) } keys ( %camelcase)) {
print $ camelcase_file ( "$_\n" );
}
close ( $ camelcase_file );
}
2013-07-03 15:05:34 -07:00
}
2020-10-15 20:12:12 -07:00
sub git_is_single_file {
my ( $ filename ) = @ _ ;
return 0 if (( which ( "git" ) eq "" ) || !( - e "$gitroot" ));
my $ output = `$ { git_command } ls - files -- $ filename 2 >/dev / null ` ;
my $ count = $ output =~ tr/\n// ;
return $ count eq 1 && $ output =~ m { ^ $ { filename } $ };
}
2014-08-06 16:10:57 -07:00
sub git_commit_info {
my ( $ commit , $ id , $ desc ) = @ _ ;
2020-10-24 16:59:04 -07:00
return ( $ id , $ desc ) if (( which ( "git" ) eq "" ) || !( - e "$gitroot" ));
2014-08-06 16:10:57 -07:00
2019-09-25 16:46:52 -07:00
my $ output = `$ { git_command } log --no - color --format='%H %s' - 1 $ commit 2 >& 1 ` ;
2014-08-06 16:10:57 -07:00
$ output =~ s/^\s*//gm ;
my @lines = split ( "\n" , $ output );
2015-02-13 14:38:35 -08:00
return ( $ id , $ desc ) if ( $ #lines < 0 );
2019-09-25 16:46:49 -07:00
if ( $ lines [ 0 ] =~ /^ error : short SHA1 $ commit is ambiguous/ ) {
2014-08-06 16:10:57 -07:00
# Maybe one day convert this block of bash into something that returns
# all matching commit ids , but it's very slow...
#
# echo "checking commits $1..."
# git rev-list --remotes | grep -i "^$1" |
# while read line ; do
# git log --format=' %H %s' -1 $line |
# echo "commit $(cut -c 1-12,41-)"
# done
} elsif ( $ lines [ 0 ] =~ /^ fatal : ambiguous argument '$commit': unknown revision or path not in the working tree\./ ) {
2017-07-10 15:52:16 -07:00
$ id = undef ;
2014-08-06 16:10:57 -07:00
} else {
$ id = substr ( $ lines [ 0 ], 0 , 12 );
$ desc = substr ( $ lines [ 0 ], 41 );
}
return ( $ id , $ desc );
}
2007-10-18 03:05:08 -07:00
$ chk_signoff = 0 if ( $ file );
2007-06-08 13:47:06 -07:00
my @rawlines = ();
2008-02-08 04:20:54 -08:00
my @lines = ();
2013-07-03 15:05:31 -07:00
my @fixed = ();
2014-08-06 16:11:05 -07:00
my @fixed_inserted = ();
my @fixed_deleted = ();
2014-08-06 16:11:03 -07:00
my $ fixlinenr = - 1 ;
2016-05-20 17:04:16 -07:00
# If input is git commits , extract all commits from the commit expressions .
# For example , HEAD - 3 means we need check 'HEAD, HEAD~1, HEAD~2' .
2020-10-24 16:59:04 -07:00
die "$P: No git repository found\n" if ( $ git && ! - e "$gitroot" );
2016-05-20 17:04:16 -07:00
if ( $ git ) {
my @commits = ();
2016-05-20 17:04:19 -07:00
foreach my $ commit_expr ( @ ARGV ) {
2016-05-20 17:04:16 -07:00
my $ git_range ;
2016-05-20 17:04:22 -07:00
if ( $ commit_expr =~ m/^ (. * ) - ( \d+ ) $ / ) {
$ git_range = "-$2 $1" ;
2016-05-20 17:04:16 -07:00
} elsif ( $ commit_expr =~ m/\.\./ ) {
$ git_range = "$commit_expr" ;
} else {
2016-05-20 17:04:19 -07:00
$ git_range = "-1 $commit_expr" ;
}
2019-09-25 16:46:52 -07:00
my $ lines = `$ { git_command } log --no - color --no - merges --pretty = format : '%H %s' $ git_range ` ;
2016-05-20 17:04:19 -07:00
foreach my $ line ( split ( /\n/ , $ lines )) {
2016-05-20 17:04:22 -07:00
$ line =~ /^ ([ 0 - 9 a - fA - F ]{ 40 , 40 }) (. * ) $ / ;
next if (! defined ( $ 1 ) || ! defined ( $ 2 ));
2016-05-20 17:04:19 -07:00
my $ sha1 = $ 1 ;
my $ subject = $ 2 ;
unshift ( @commits , $ sha1 );
$ git_commits { $ sha1 } = $ subject ;
2016-05-20 17:04:16 -07:00
}
}
die "$P: no git commits after extraction!\n" if ( @commits == 0 );
@ ARGV = @commits ;
}
2008-02-08 04:20:54 -08:00
my $ vname ;
2019-03-07 16:28:38 -08:00
$ allow_c99_comments = ! defined $ ignore_type { "C99_COMMENT_TOLERANCE" };
2007-10-18 03:05:08 -07:00
for my $ filename ( @ ARGV ) {
2009-01-06 14:41:30 -08:00
my $ FILE ;
2020-10-15 20:12:12 -07:00
my $ is_git_file = git_is_single_file ( $ filename );
my $ oldfile = $ file ;
$ file = 1 if ( $ is_git_file );
2016-05-20 17:04:16 -07:00
if ( $ git ) {
open ( $ FILE , '-|' , "git format-patch -M --stdout -1 $filename" ) ||
die "$P: $filename: git format-patch failed - $!\n" ;
} elsif ( $ file ) {
2009-01-06 14:41:30 -08:00
open ( $ FILE , '-|' , "diff -u /dev/null $filename" ) ||
2007-10-18 03:05:08 -07:00
die "$P: $filename: diff failed - $!\n" ;
2009-01-06 14:41:30 -08:00
} elsif ( $ filename eq '-' ) {
open ( $ FILE , '<&STDIN' );
2007-10-18 03:05:08 -07:00
} else {
2009-01-06 14:41:30 -08:00
open ( $ FILE , '<' , "$filename" ) ||
2007-10-18 03:05:08 -07:00
die "$P: $filename: open failed - $!\n" ;
2007-06-01 00:46:48 -07:00
}
2008-02-08 04:20:54 -08:00
if ( $ filename eq '-' ) {
$ vname = 'Your patch' ;
2016-05-20 17:04:16 -07:00
} elsif ( $ git ) {
2016-05-20 17:04:19 -07:00
$ vname = "Commit " . substr ( $ filename , 0 , 12 ) . ' ("' . $ git_commits { $ filename } . '")' ;
2008-02-08 04:20:54 -08:00
} else {
$ vname = $ filename ;
}
2009-01-06 14:41:30 -08:00
while ( < $ FILE > ) {
2007-10-18 03:05:08 -07:00
chomp ;
push ( @rawlines , $ _ );
2020-06-04 16:50:43 -07:00
$ vname = qq ( "$1" ) if ( $ filename eq '-' && $ _ =~ m/^ Subject :\s+ (. + ) / i );
2007-10-18 03:05:08 -07:00
}
2009-01-06 14:41:30 -08:00
close ( $ FILE );
2015-06-25 15:03:00 -07:00
if ( $ # ARGV > 0 && $ quiet == 0 ) {
print '-' x length ( $ vname ) . "\n" ;
print "$vname\n" ;
print '-' x length ( $ vname ) . "\n" ;
}
2008-02-08 04:20:54 -08:00
if (! process ( $ filename )) {
2007-10-18 03:05:08 -07:00
$ exit = 1 ;
}
@rawlines = ();
2008-02-08 04:22:03 -08:00
@lines = ();
2013-07-03 15:05:31 -07:00
@fixed = ();
2014-08-06 16:11:05 -07:00
@fixed_inserted = ();
@fixed_deleted = ();
2014-08-06 16:11:03 -07:00
$ fixlinenr = - 1 ;
2015-06-25 15:02:52 -07:00
@modifierListFile = ();
@typeListFile = ();
build_types ();
2020-10-15 20:12:12 -07:00
$ file = $ oldfile if ( $ is_git_file );
2007-06-01 00:46:48 -07:00
}
2015-06-25 15:03:00 -07:00
if (! $ quiet ) {
2015-06-25 15:03:29 -07:00
hash_show_words ( \ %use_type, "Used");
hash_show_words ( \ %ignore_type, "Ignored");
2018-08-21 21:57:33 -07:00
if (! $ perl_version_ok ) {
2015-06-25 15:03:00 -07:00
print << "EOM"
NOTE : perl $ ^ V is not modern enough to detect all possible issues .
2018-08-21 21:57:33 -07:00
An upgrade to at least perl $ minimum_perl_version is suggested .
2015-06-25 15:03:00 -07:00
EOM
}
if ( $ exit ) {
print << "EOM"
NOTE : If any of the errors are false positives , please report
them to the maintainer , see CHECKPATCH in MAINTAINERS .
EOM
}
}
2007-06-01 00:46:48 -07:00
exit ( $ exit );
sub top_of_kernel_tree {
2007-10-18 03:05:08 -07:00
my ( $ root ) = @ _ ;
my @tree_check = (
"COPYING" , "CREDITS" , "Kbuild" , "MAINTAINERS" , "Makefile" ,
"README" , "Documentation" , "arch" , "include" , "drivers" ,
"fs" , "init" , "ipc" , "kernel" , "lib" , "scripts" ,
);
foreach my $ check ( @tree_check ) {
if (! - e $ root . '/' . $ check ) {
return 0 ;
}
2007-06-01 00:46:48 -07:00
}
2007-10-18 03:05:08 -07:00
return 1 ;
2012-10-04 17:13:32 -07:00
}
2007-06-01 00:46:48 -07:00
2011-07-25 17:13:23 -07:00
sub parse_email {
my ( $ formatted_email ) = @ _ ;
my $ name = "" ;
2020-12-15 20:44:53 -08:00
my $ quoted = "" ;
2020-04-06 20:10:48 -07:00
my $ name_comment = "" ;
2011-07-25 17:13:23 -07:00
my $ address = "" ;
my $ comment = "" ;
if ( $ formatted_email =~ /^ (. * ) < ( \ S +\@\ S + ) > (. * ) $ / ) {
$ name = $ 1 ;
$ address = $ 2 ;
$ comment = $ 3 if defined $ 3 ;
} elsif ( $ formatted_email =~ /^\s*< ( \ S +\@\ S + ) > (. * ) $ / ) {
$ address = $ 1 ;
$ comment = $ 2 if defined $ 2 ;
} elsif ( $ formatted_email =~ / ( \ S +\@\ S + )(. * ) $ / ) {
$ address = $ 1 ;
$ comment = $ 2 if defined $ 2 ;
2018-04-10 16:33:09 -07:00
$ formatted_email =~ s/\ Q $ address\ E . * $ // ;
2011-07-25 17:13:23 -07:00
$ name = $ formatted_email ;
2013-07-03 15:05:31 -07:00
$ name = trim ( $ name );
2011-07-25 17:13:23 -07:00
$ name =~ s/^\ "|\"$//g;
# If there's a name left after stripping spaces and
# leading quotes, and the address doesn't have both
# leading and trailing angle brackets, the address
# is invalid. ie:
# " joe smith joe@smith . com " bad
# " joe smith < joe@smith . com " bad
if ($name ne "" && $address !~ /^<[^>]+>$/) {
$name = "";
$address = "";
$comment = "";
}
}
2020-12-15 20:44:53 -08:00
# Extract comments from names excluding quoted parts
# " John D . ( Doe ) " - Do not extract
if ($name =~ s/\"(.+)\"//) {
$quoted = $1;
2020-04-06 20:10:48 -07:00
}
2020-12-15 20:44:53 -08:00
while ($name =~ s/\s*($balanced_parens)\s*/ /) {
$name_comment .= trim($1);
}
$name =~ s/^[ \"]+|[ \"]+$//g;
$name = trim(" $ quoted $ name " );
2013-07-03 15:05:31 -07:00
$ address = trim ( $ address );
2011-07-25 17:13:23 -07:00
$ address =~ s/^\< | \> $ // g ;
2020-12-15 20:44:53 -08:00
$ comment = trim ( $ comment );
2011-07-25 17:13:23 -07:00
if ( $ name =~ / [ ^\w \- ] / i ) { ##has "must quote" chars
$ name =~ s/ ( ?< ! \\ ) " /\\ "/g; ##escape quotes
$name = " \ "$name\"" ;
}
2020-04-06 20:10:48 -07:00
return ( $ name , $ name_comment , $ address , $ comment );
2011-07-25 17:13:23 -07:00
}
sub format_email {
2020-10-15 20:12:28 -07:00
my ( $ name , $ name_comment , $ address , $ comment ) = @ _ ;
2011-07-25 17:13:23 -07:00
my $ formatted_email ;
2020-12-15 20:44:53 -08:00
$ name =~ s/^ [ \ " ] + |[ \ " ] + $ // g ;
2013-07-03 15:05:31 -07:00
$ address = trim ( $ address );
2020-12-15 20:44:53 -08:00
$ address =~ s/ ( ?:\. | \ ,| \ " ) + $ // ; ##trailing commas , dots or quotes
2011-07-25 17:13:23 -07:00
if ( $ name =~ / [ ^\w \- ] / i ) { ##has "must quote" chars
$ name =~ s/ ( ?< ! \\ ) " /\\ "/g; ##escape quotes
$name = " \ "$name\"" ;
}
2020-12-15 20:44:53 -08:00
$ name_comment = trim ( $ name_comment );
$ name_comment = " $name_comment" if ( $ name_comment ne "" );
$ comment = trim ( $ comment );
$ comment = " $comment" if ( $ comment ne "" );
2011-07-25 17:13:23 -07:00
if ( "$name" eq "" ) {
$ formatted_email = "$address" ;
} else {
2020-10-15 20:12:28 -07:00
$ formatted_email = "$name$name_comment <$address>" ;
2011-07-25 17:13:23 -07:00
}
2020-10-15 20:12:28 -07:00
$ formatted_email . = "$comment" ;
2011-07-25 17:13:23 -07:00
return $ formatted_email ;
}
2020-04-06 20:10:48 -07:00
sub reformat_email {
my ( $ email ) = @ _ ;
my ( $ email_name , $ name_comment , $ email_address , $ comment ) = parse_email ( $ email );
2020-10-15 20:12:28 -07:00
return format_email ( $ email_name , $ name_comment , $ email_address , $ comment );
2020-04-06 20:10:48 -07:00
}
sub same_email_addresses {
2020-12-15 20:44:53 -08:00
my ( $ email1 , $ email2 ) = @ _ ;
2020-04-06 20:10:48 -07:00
my ( $ email1_name , $ name1_comment , $ email1_address , $ comment1 ) = parse_email ( $ email1 );
my ( $ email2_name , $ name2_comment , $ email2_address , $ comment2 ) = parse_email ( $ email2 );
return $ email1_name eq $ email2_name &&
2020-10-15 20:12:28 -07:00
$ email1_address eq $ email2_address &&
$ name1_comment eq $ name2_comment &&
$ comment1 eq $ comment2 ;
2020-04-06 20:10:48 -07:00
}
2014-08-06 16:10:57 -07:00
sub which {
2014-08-06 16:11:10 -07:00
my ( $ bin ) = @ _ ;
2014-08-06 16:10:57 -07:00
2014-08-06 16:11:10 -07:00
foreach my $ path ( split ( /:/ , $ ENV { PATH })) {
if ( - e "$path/$bin" ) {
return "$path/$bin" ;
}
2014-08-06 16:10:57 -07:00
}
2014-08-06 16:11:10 -07:00
return "" ;
2014-08-06 16:10:57 -07:00
}
2011-07-25 17:13:25 -07:00
sub which_conf {
my ( $ conf ) = @ _ ;
foreach my $ path ( split ( /:/ , ".:$ENV{HOME}:.scripts" )) {
if ( - e "$path/$conf" ) {
return "$path/$conf" ;
}
}
return "" ;
}
2007-06-01 00:46:48 -07:00
sub expand_tabs {
my ( $ str ) = @ _ ;
my $ res = '' ;
my $ n = 0 ;
for my $ c ( split ( // , $ str )) {
if ( $ c eq "\t" ) {
$ res . = ' ' ;
$ n++ ;
2020-04-06 20:11:07 -07:00
for (; ( $ n % $tabsize) != 0; $n++) {
2007-06-01 00:46:48 -07:00
$ res . = ' ' ;
}
next ;
}
$ res . = $ c ;
$ n++ ;
}
return $ res ;
}
2007-10-18 03:05:08 -07:00
sub copy_spacing {
2008-03-28 14:15:58 -07:00
( my $ res = shift ) =~ tr/\t / / c ;
2007-10-18 03:05:08 -07:00
return $ res ;
}
2007-06-01 00:46:48 -07:00
2007-06-08 13:46:39 -07:00
sub line_stats {
my ( $ line ) = @ _ ;
# Drop the diff line leader and expand tabs
$ line =~ s/^.// ;
$ line = expand_tabs ( $ line );
# Pick the indent from the front of the line .
my ( $ white ) = ( $ line =~ /^ ( \s* ) / );
return ( length ( $ line ), length ( $ white ));
}
2008-03-28 14:15:58 -07:00
my $ sanitise_quote = '' ;
sub sanitise_line_reset {
my ( $ in_comment ) = @ _ ;
if ( $ in_comment ) {
$ sanitise_quote = '*/' ;
} else {
$ sanitise_quote = '' ;
}
}
2007-06-08 13:47:06 -07:00
sub sanitise_line {
my ( $ line ) = @ _ ;
my $ res = '' ;
my $ l = '' ;
2008-02-08 04:20:54 -08:00
my $ qlen = 0 ;
2008-03-28 14:15:58 -07:00
my $ off = 0 ;
my $ c ;
2007-06-08 13:47:06 -07:00
2008-03-28 14:15:58 -07:00
# Always copy over the diff marker .
$ res = substr ( $ line , 0 , 1 );
for ( $ off = 1 ; $ off < length ( $ line ); $ off++ ) {
$ c = substr ( $ line , $ off , 1 );
2018-04-10 16:33:42 -07:00
# Comments we are whacking completely including the begin
2008-03-28 14:15:58 -07:00
# and end , all to $ ;.
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '/*' ) {
$ sanitise_quote = '*/' ;
substr ( $ res , $ off , 2 , "$;$;" );
$ off++ ;
next ;
2008-02-08 04:20:54 -08:00
}
2008-10-15 22:02:26 -07:00
if ( $ sanitise_quote eq '*/' && substr ( $ line , $ off , 2 ) eq '*/' ) {
2008-03-28 14:15:58 -07:00
$ sanitise_quote = '' ;
substr ( $ res , $ off , 2 , "$;$;" );
$ off++ ;
next ;
}
2009-09-21 17:04:35 -07:00
if ( $ sanitise_quote eq '' && substr ( $ line , $ off , 2 ) eq '//' ) {
$ sanitise_quote = '//' ;
substr ( $ res , $ off , 2 , $ sanitise_quote );
$ off++ ;
next ;
}
2008-03-28 14:15:58 -07:00
# A \ in a string means ignore the next character .
if (( $ sanitise_quote eq "'" || $ sanitise_quote eq '"' ) &&
$ c eq " \\ ") {
substr($res, $off, 2, 'XX');
$off++;
next;
}
# Regular quotes.
if ($c eq " '" || $c eq ' "') {
if ($sanitise_quote eq '') {
$sanitise_quote = $c;
substr($res, $off, 1, $c);
2007-06-08 13:47:06 -07:00
next;
2008-03-28 14:15:58 -07:00
} elsif ($sanitise_quote eq $c) {
$sanitise_quote = '';
2007-06-08 13:47:06 -07:00
}
}
2008-03-28 14:15:58 -07:00
2009-01-06 14:41:20 -08:00
#print " c< $ c > SQ < $ sanitise_quote>\n ";
2008-03-28 14:15:58 -07:00
if ($off != 0 && $sanitise_quote eq '*/' && $c ne " \t ") {
substr($res, $off, 1, $;);
2009-09-21 17:04:35 -07:00
} elsif ($off != 0 && $sanitise_quote eq '//' && $c ne " \t ") {
substr($res, $off, 1, $;);
2008-03-28 14:15:58 -07:00
} elsif ($off != 0 && $sanitise_quote && $c ne " \t " ) {
substr ( $ res , $ off , 1 , 'X' );
2007-06-08 13:47:06 -07:00
} else {
2008-03-28 14:15:58 -07:00
substr ( $ res , $ off , 1 , $ c );
2007-06-08 13:47:06 -07:00
}
2008-02-08 04:20:54 -08:00
}
2009-09-21 17:04:35 -07:00
if ( $ sanitise_quote eq '//' ) {
$ sanitise_quote = '' ;
}
2008-02-08 04:20:54 -08:00
# The pathname on a #include may be surrounded by '<' and '>' .
2008-06-05 22:46:01 -07:00
if ( $ res =~ /^.\s*\#\s * include\s+\< (. * ) \>/ ) {
2008-02-08 04:20:54 -08:00
my $ clean = 'X' x length ( $ 1 );
$ res =~ s@\<.*\>@< $ clean>@ ;
# The whole of a #error is a string .
2008-06-05 22:46:01 -07:00
} elsif ( $ res =~ /^.\s*\#\s* ( ?:error | warning ) \s+ (. * ) \b/ ) {
2008-02-08 04:20:54 -08:00
my $ clean = 'X' x length ( $ 1 );
2008-06-05 22:46:01 -07:00
$ res =~ s@ ( \#\s* ( ?:error | warning ) \s+ ). *@ $ 1 $ clean@ ;
2008-02-08 04:20:54 -08:00
}
2016-08-02 14:04:33 -07:00
if ( $ allow_c99_comments && $ res =~ m@ ( //.* $ ) @ ) {
my $ match = $ 1 ;
$ res =~ s/\ Q $ match\ E / "$;" x length ( $ match ) / e ;
}
2007-06-08 13:47:06 -07:00
return $ res ;
}
2013-04-29 16:18:13 -07:00
sub get_quoted_string {
my ( $ line , $ rawline ) = @ _ ;
2018-04-10 16:33:34 -07:00
return "" if (! defined ( $ line ) || ! defined ( $ rawline ));
2015-06-25 15:02:54 -07:00
return "" if ( $ line ! ~ m/ ( $ String ) / g );
2013-04-29 16:18:13 -07:00
return substr ( $ rawline , $ - [ 0 ], $ + [ 0 ] - $ - [ 0 ]);
}
2007-11-28 16:21:06 -08:00
sub ctx_statement_block {
my ( $ linenr , $ remain , $ off ) = @ _ ;
my $ line = $ linenr - 1 ;
my $ blk = '' ;
my $ soff = $ off ;
my $ coff = $ off - 1 ;
2008-03-28 14:15:58 -07:00
my $ coff_set = 0 ;
2007-11-28 16:21:06 -08:00
2008-02-08 04:22:03 -08:00
my $ loff = 0 ;
2007-11-28 16:21:06 -08:00
my $ type = '' ;
my $ level = 0 ;
2009-01-15 13:51:04 -08:00
my @stack = ();
2008-03-04 14:28:20 -08:00
my $ p ;
2007-11-28 16:21:06 -08:00
my $ c ;
my $ len = 0 ;
2008-02-08 04:22:03 -08:00
my $ remainder ;
2007-11-28 16:21:06 -08:00
while ( 1 ) {
2009-01-15 13:51:04 -08:00
@stack = ([ '' , 0 ]) if ( $ #stack == - 1 );
2008-03-28 14:15:58 -07:00
#warn "CSB: blk<$blk> remain<$remain>\n" ;
2007-11-28 16:21:06 -08:00
# If we are about to drop off the end , pull in more
# context .
if ( $ off >= $ len ) {
for (; $ remain > 0 ; $ line++ ) {
2008-10-15 22:02:25 -07:00
last if (! defined $ lines [ $ line ]);
2008-02-08 04:20:54 -08:00
next if ( $ lines [ $ line ] =~ /^-/ );
2007-11-28 16:21:06 -08:00
$ remain-- ;
2008-02-08 04:22:03 -08:00
$ loff = $ len ;
2008-02-08 04:20:54 -08:00
$ blk . = $ lines [ $ line ] . "\n" ;
2007-11-28 16:21:06 -08:00
$ len = length ( $ blk );
$ line++ ;
last ;
}
# Bail if there is no further context .
#warn "CSB: blk<$blk> off<$off> len<$len>\n" ;
2008-02-08 04:22:03 -08:00
if ( $ off >= $ len ) {
2007-11-28 16:21:06 -08:00
last ;
}
2012-01-10 15:09:54 -08:00
if ( $ level == 0 && substr ( $ blk , $ off ) =~ /^.\s*#\s * define/ ) {
$ level++ ;
$ type = '#' ;
}
2007-11-28 16:21:06 -08:00
}
2008-03-04 14:28:20 -08:00
$ p = $ c ;
2007-11-28 16:21:06 -08:00
$ c = substr ( $ blk , $ off , 1 );
2008-02-08 04:22:03 -08:00
$ remainder = substr ( $ blk , $ off );
2007-11-28 16:21:06 -08:00
2008-03-28 14:15:58 -07:00
#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n" ;
2009-01-06 14:41:27 -08:00
# Handle nested #if/#else .
if ( $ remainder =~ /^#\s* ( ?:ifndef | ifdef | if ) \s/ ) {
push ( @stack , [ $ type , $ level ]);
} elsif ( $ remainder =~ /^#\s* ( ?:else | elif ) \b/ ) {
( $ type , $ level ) = @ { $ stack [ $ #stack - 1 ]};
} elsif ( $ remainder =~ /^#\s * endif\b/ ) {
( $ type , $ level ) = @ { pop ( @stack )};
}
2007-11-28 16:21:06 -08:00
# Statement ends at the ';' or a close '}' at the
# outermost level .
if ( $ level == 0 && $ c eq ';' ) {
last ;
}
2008-02-08 04:22:03 -08:00
# An else is really a conditional as long as its not else if
2008-03-28 14:15:58 -07:00
if ( $ level == 0 && $ coff_set == 0 &&
(! defined ( $ p ) || $ p =~ / ( ?:\s | \ }| \+ ) / ) &&
$ remainder =~ /^ ( else )( ?:\s |{) / &&
$ remainder ! ~ /^else\s + if\b/ ) {
$ coff = $ off + length ( $ 1 ) - 1 ;
$ coff_set = 1 ;
#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n" ;
#warn "[" . substr ( $ blk , $ soff , $ coff - $ soff + 1 ) . "]\n" ;
2008-02-08 04:22:03 -08:00
}
2007-11-28 16:21:06 -08:00
if (( $ type eq '' || $ type eq '(' ) && $ c eq '(' ) {
$ level++ ;
$ type = '(' ;
}
if ( $ type eq '(' && $ c eq ')' ) {
$ level-- ;
$ type = ( $ level ! = 0 ) ? '(' : '' ;
if ( $ level == 0 && $ coff < $ soff ) {
$ coff = $ off ;
2008-03-28 14:15:58 -07:00
$ coff_set = 1 ;
#warn "CSB: mark coff<$coff>\n" ;
2007-11-28 16:21:06 -08:00
}
}
if (( $ type eq '' || $ type eq '{' ) && $ c eq '{' ) {
$ level++ ;
$ type = '{' ;
}
if ( $ type eq '{' && $ c eq '}' ) {
$ level-- ;
$ type = ( $ level ! = 0 ) ? '{' : '' ;
if ( $ level == 0 ) {
2010-08-09 17:21:03 -07:00
if ( substr ( $ blk , $ off + 1 , 1 ) eq ';' ) {
$ off++ ;
}
2007-11-28 16:21:06 -08:00
last ;
}
}
2012-01-10 15:09:54 -08:00
# Preprocessor commands end at the newline unless escaped .
if ( $ type eq '#' && $ c eq "\n" && $ p ne " \\ ") {
$level--;
$type = '';
$off++;
last;
}
2007-11-28 16:21:06 -08:00
$off++;
}
2008-07-23 21:29:00 -07:00
# We are truly at the end, so shuffle to the next line.
2008-02-08 04:22:03 -08:00
if ($off == $len) {
2008-07-23 21:29:00 -07:00
$loff = $len + 1;
2008-02-08 04:22:03 -08:00
$line++;
$remain--;
}
2007-11-28 16:21:06 -08:00
my $statement = substr($blk, $soff, $off - $soff + 1);
my $condition = substr($blk, $soff, $coff - $soff + 1);
#warn " STATEMENT < $ statement>\n ";
#warn " CONDITION < $ condition>\n ";
2008-03-28 14:15:58 -07:00
#print " coff< $ coff > soff< $ off > loff< $ loff>\n ";
2008-02-08 04:22:03 -08:00
return ($statement, $condition,
$line, $remain + 1, $off - $loff + 1, $level);
}
2008-03-04 14:28:20 -08:00
sub statement_lines {
my ($stmt) = @_;
# Strip the diff line prefixes and rip blank lines at start and end.
$stmt =~ s/(^|\n)./$1/g;
$stmt =~ s/^\s*//;
$stmt =~ s/\s*$//;
my @stmt_lines = ($stmt =~ /\n/g);
return $#stmt_lines + 2;
}
sub statement_rawlines {
my ($stmt) = @_;
my @stmt_lines = ($stmt =~ /\n/g);
return $#stmt_lines + 2;
}
sub statement_block_size {
my ($stmt) = @_;
$stmt =~ s/(^|\n)./$1/g;
$stmt =~ s/^\s*{//;
$stmt =~ s/}\s*$//;
$stmt =~ s/^\s*//;
$stmt =~ s/\s*$//;
my @stmt_lines = ($stmt =~ /\n/g);
my @stmt_statements = ($stmt =~ /;/g);
my $stmt_lines = $#stmt_lines + 2;
my $stmt_statements = $#stmt_statements + 1;
if ($stmt_lines > $stmt_statements) {
return $stmt_lines;
} else {
return $stmt_statements;
}
}
2008-02-08 04:22:03 -08:00
sub ctx_statement_full {
my ($linenr, $remain, $off) = @_;
my ($statement, $condition, $level);
my (@chunks);
2008-03-04 14:28:20 -08:00
# Grab the first conditional/block pair.
2008-02-08 04:22:03 -08:00
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
2008-03-28 14:15:58 -07:00
#print " F : c< $ condition > s< $ statement > remain< $ remain>\n ";
2008-03-04 14:28:20 -08:00
push(@chunks, [ $condition, $statement ]);
if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
return ($level, $linenr, @chunks);
}
# Pull in the following conditional/block pairs and see if they
# could continue the statement.
2008-02-08 04:22:03 -08:00
for (;;) {
($statement, $condition, $linenr, $remain, $off, $level) =
ctx_statement_block($linenr, $remain, $off);
2008-03-04 14:28:20 -08:00
#print " C : c< $ condition > s< $ statement > remain< $ remain>\n ";
2008-03-28 14:15:58 -07:00
last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
2008-03-04 14:28:20 -08:00
#print " C : push\n ";
push(@chunks, [ $condition, $statement ]);
2008-02-08 04:22:03 -08:00
}
return ($level, $linenr, @chunks);
2007-11-28 16:21:06 -08:00
}
2007-06-08 13:46:39 -07:00
sub ctx_block_get {
2007-07-19 01:48:34 -07:00
my ($linenr, $remain, $outer, $open, $close, $off) = @_;
2007-06-08 13:46:39 -07:00
my $line;
my $start = $linenr - 1;
my $blk = '';
my @o;
my @c;
my @res = ();
2007-07-19 01:48:34 -07:00
my $level = 0;
2009-01-06 14:41:27 -08:00
my @stack = ($level);
2007-06-08 13:47:06 -07:00
for ($line = $start; $remain > 0; $line++) {
next if ($rawlines[$line] =~ /^-/);
$remain--;
$blk .= $rawlines[$line];
2009-01-06 14:41:27 -08:00
# Handle nested #if/#else.
2010-10-26 14:23:19 -07:00
if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
2009-01-06 14:41:27 -08:00
push(@stack, $level);
2010-10-26 14:23:19 -07:00
} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
2009-01-06 14:41:27 -08:00
$level = $stack[$#stack - 1];
2010-10-26 14:23:19 -07:00
} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
2009-01-06 14:41:27 -08:00
$level = pop(@stack);
}
2010-10-26 14:23:19 -07:00
foreach my $c (split(//, $lines[$line])) {
2007-07-19 01:48:34 -07:00
##print " C < $ c > L < $ level>< $ open$close > O < $ off>\n " ;
if ( $ off > 0 ) {
$ off-- ;
next ;
}
2007-06-08 13:46:39 -07:00
2007-07-19 01:48:34 -07:00
if ( $ c eq $ close && $ level > 0 ) {
$ level-- ;
last if ( $ level == 0 );
} elsif ( $ c eq $ open ) {
$ level++ ;
}
}
2007-06-08 13:46:39 -07:00
2007-07-19 01:48:34 -07:00
if (! $ outer || $ level <= 1 ) {
2007-06-08 13:47:06 -07:00
push ( @res , $ rawlines [ $ line ]);
2007-06-08 13:46:39 -07:00
}
2007-07-19 01:48:34 -07:00
last if ( $ level == 0 );
2007-06-08 13:46:39 -07:00
}
2007-07-19 01:48:34 -07:00
return ( $ level , @res );
2007-06-08 13:46:39 -07:00
}
sub ctx_block_outer {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 01:48:34 -07:00
my ( $ level , @r ) = ctx_block_get ( $ linenr , $ remain , 1 , '{' , '}' , 0 );
return @r ;
2007-06-08 13:46:39 -07:00
}
sub ctx_block {
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 01:48:34 -07:00
my ( $ level , @r ) = ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 );
return @r ;
2007-06-23 17:16:34 -07:00
}
sub ctx_statement {
2007-07-19 01:48:34 -07:00
my ( $ linenr , $ remain , $ off ) = @ _ ;
my ( $ level , @r ) = ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off );
return @r ;
}
sub ctx_block_level {
2007-06-23 17:16:34 -07:00
my ( $ linenr , $ remain ) = @ _ ;
2007-07-19 01:48:34 -07:00
return ctx_block_get ( $ linenr , $ remain , 0 , '{' , '}' , 0 );
2007-06-08 13:46:39 -07:00
}
2007-10-16 23:29:38 -07:00
sub ctx_statement_level {
my ( $ linenr , $ remain , $ off ) = @ _ ;
return ctx_block_get ( $ linenr , $ remain , 0 , '(' , ')' , $ off );
}
2007-06-08 13:46:39 -07:00
sub ctx_locate_comment {
my ( $ first_line , $ end_line ) = @ _ ;
2020-06-04 16:50:36 -07:00
# If c99 comment on the current line , or the line before or after
my ( $ current_comment ) = ( $ rawlines [ $ end_line - 1 ] =~ m@^\+.* ( //.* $ ) @ );
return $ current_comment if ( defined $ current_comment );
( $ current_comment ) = ( $ rawlines [ $ end_line - 2 ] =~ m@^ [ \+ ]. * ( //.* $ ) @ );
return $ current_comment if ( defined $ current_comment );
( $ current_comment ) = ( $ rawlines [ $ end_line ] =~ m@^ [ \+ ]. * ( //.* $ ) @ );
return $ current_comment if ( defined $ current_comment );
2007-06-08 13:46:39 -07:00
# Catch a comment on the end of the line itself .
2020-06-04 16:50:36 -07:00
( $ current_comment ) = ( $ rawlines [ $ end_line - 1 ] =~ m@.* ( /\*.*\*/ ) \s* ( ?:\\\s* ) ? $ @ );
2007-06-08 13:46:39 -07:00
return $ current_comment if ( defined $ current_comment );
# Look through the context and try and figure out if there is a
# comment .
my $ in_comment = 0 ;
$ current_comment = '' ;
for ( my $ linenr = $ first_line ; $ linenr < $ end_line ; $ linenr++ ) {
2007-06-08 13:47:06 -07:00
my $ line = $ rawlines [ $ linenr - 1 ];
#warn " $line\n" ;
2007-06-08 13:46:39 -07:00
if ( $ linenr == $ first_line and $ line =~ m@^.\s*\*@ ) {
$ in_comment = 1 ;
}
if ( $ line =~ m@/\*@ ) {
$ in_comment = 1 ;
}
if (! $ in_comment && $ current_comment ne '' ) {
$ current_comment = '' ;
}
$ current_comment . = $ line . "\n" if ( $ in_comment );
if ( $ line =~ m@\*/@ ) {
$ in_comment = 0 ;
}
}
chomp ( $ current_comment );
return ( $ current_comment );
}
sub ctx_has_comment {
my ( $ first_line , $ end_line ) = @ _ ;
my $ cmt = ctx_locate_comment ( $ first_line , $ end_line );
2007-06-08 13:47:06 -07:00
##print "LINE: $rawlines[$end_line - 1 ]\n" ;
2007-06-08 13:46:39 -07:00
##print "CMMT: $cmt\n" ;
return ( $ cmt ne '' );
}
2008-10-15 22:02:21 -07:00
sub raw_line {
my ( $ linenr , $ cnt ) = @ _ ;
my $ offset = $ linenr - 1 ;
$ cnt++ ;
my $ line ;
while ( $ cnt ) {
$ line = $ rawlines [ $ offset++ ];
next if ( defined ( $ line ) && $ line =~ /^-/ );
$ cnt-- ;
}
return $ line ;
}
2018-04-10 16:33:20 -07:00
sub get_stat_real {
my ( $ linenr , $ lc ) = @ _ ;
my $ stat_real = raw_line ( $ linenr , 0 );
for ( my $ count = $ linenr + 1 ; $ count <= $ lc ; $ count++ ) {
$ stat_real = $ stat_real . "\n" . raw_line ( $ count , 0 );
}
return $ stat_real ;
}
2018-04-10 16:33:27 -07:00
sub get_stat_here {
my ( $ linenr , $ cnt , $ here ) = @ _ ;
my $ herectx = $ here . "\n" ;
for ( my $ n = 0 ; $ n < $ cnt ; $ n++ ) {
$ herectx . = raw_line ( $ linenr , $ n ) . "\n" ;
}
return $ herectx ;
}
2007-06-01 00:46:48 -07:00
sub cat_vet {
my ( $ vet ) = @ _ ;
2007-10-16 23:29:38 -07:00
my ( $ res , $ coded );
2007-06-01 00:46:48 -07:00
2007-10-16 23:29:38 -07:00
$ res = '' ;
2007-10-18 03:05:08 -07:00
while ( $ vet =~ / ([ ^ [ : cntrl :]] * )([[ : cntrl :]]| $ ) / g ) {
$ res . = $ 1 ;
if ( $ 2 ne '' ) {
$ coded = sprintf ( "^%c" , unpack ( 'C' , $ 2 ) + 64 );
$ res . = $ coded ;
}
2007-10-16 23:29:38 -07:00
}
$ res =~ s/ $ /\ $ / ;
2007-06-01 00:46:48 -07:00
2007-10-16 23:29:38 -07:00
return $ res ;
2007-06-01 00:46:48 -07:00
}
2008-02-08 04:20:54 -08:00
my $ av_preprocessor = 0 ;
2008-03-04 14:28:20 -08:00
my $ av_pending ;
2008-02-08 04:20:54 -08:00
my @av_paren_type ;
2008-07-23 21:29:10 -07:00
my $ av_pend_colon ;
2008-02-08 04:20:54 -08:00
sub annotate_reset {
$ av_preprocessor = 0 ;
2008-03-04 14:28:20 -08:00
$ av_pending = '_' ;
@av_paren_type = ( 'E' );
2008-07-23 21:29:10 -07:00
$ av_pend_colon = 'O' ;
2008-02-08 04:20:54 -08:00
}
2007-10-18 03:05:08 -07:00
sub annotate_values {
my ( $ stream , $ type ) = @ _ ;
my $ res ;
2008-07-23 21:29:10 -07:00
my $ var = '_' x length ( $ stream );
2007-10-18 03:05:08 -07:00
my $ cur = $ stream ;
2008-02-08 04:20:54 -08:00
print "$stream\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
while ( length ( $ cur )) {
2008-03-28 14:15:58 -07:00
@av_paren_type = ( 'E' ) if ( $ #av_paren_type < 0 );
2008-03-04 14:28:20 -08:00
print " <" . join ( '' , @av_paren_type ) .
2008-04-29 00:59:32 -07:00
"> <$type> <$av_pending>" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
if ( $ cur =~ /^ ( \s+ ) / o ) {
2008-02-08 04:20:54 -08:00
print "WS($1)\n" if ( $ dbg_values > 1 );
if ( $ 1 =~ /\n / && $ av_preprocessor ) {
2008-03-04 14:28:20 -08:00
$ type = pop ( @av_paren_type );
2008-02-08 04:20:54 -08:00
$ av_preprocessor = 0 ;
2007-10-18 03:05:08 -07:00
}
2011-01-12 16:59:58 -08:00
} elsif ( $ cur =~ /^ ( \ ( \s* $ Type \s* ) \ ) / && $ av_pending eq '_' ) {
2010-10-26 14:23:13 -07:00
print "CAST($1)\n" if ( $ dbg_values > 1 );
push ( @av_paren_type , $ type );
2012-01-10 15:10:11 -08:00
$ type = 'c' ;
2010-10-26 14:23:13 -07:00
2010-10-26 14:23:11 -07:00
} elsif ( $ cur =~ /^ ( $ Type ) \s* ( ?: $ Ident |,| \ )| \ (| \s* $ ) / ) {
2008-02-08 04:20:54 -08:00
print "DECLARE($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
$ type = 'T' ;
2008-07-23 21:29:05 -07:00
} elsif ( $ cur =~ /^ ( $ Modifier ) \s*/ ) {
print "MODIFIER($1)\n" if ( $ dbg_values > 1 );
$ type = 'T' ;
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\s * define\s* $ Ident )( \ ( ? ) / o ) {
2008-04-29 00:59:32 -07:00
print "DEFINE($1,$2)\n" if ( $ dbg_values > 1 );
2008-02-08 04:20:54 -08:00
$ av_preprocessor = 1 ;
2008-04-29 00:59:32 -07:00
push ( @av_paren_type , $ type );
if ( $ 2 ne '' ) {
$ av_pending = 'N' ;
}
$ type = 'E' ;
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\s* ( ?:undef\s* $ Ident | include\b )) / o ) {
2008-04-29 00:59:32 -07:00
print "UNDEF($1)\n" if ( $ dbg_values > 1 );
$ av_preprocessor = 1 ;
push ( @av_paren_type , $ type );
2007-10-18 03:05:08 -07:00
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\s* ( ?:ifdef | ifndef | if )) / o ) {
2008-03-04 14:28:20 -08:00
print "PRE_START($1)\n" if ( $ dbg_values > 1 );
2008-02-08 04:20:54 -08:00
$ av_preprocessor = 1 ;
2008-03-04 14:28:20 -08:00
push ( @av_paren_type , $ type );
push ( @av_paren_type , $ type );
2008-04-29 00:59:32 -07:00
$ type = 'E' ;
2008-03-04 14:28:20 -08:00
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\s* ( ?:else | elif )) / o ) {
2008-03-04 14:28:20 -08:00
print "PRE_RESTART($1)\n" if ( $ dbg_values > 1 );
$ av_preprocessor = 1 ;
push ( @av_paren_type , $ av_paren_type [ $ #av_paren_type ]);
2008-04-29 00:59:32 -07:00
$ type = 'E' ;
2008-03-04 14:28:20 -08:00
2008-06-05 22:46:01 -07:00
} elsif ( $ cur =~ /^ ( \#\s* ( ?:endif )) / o ) {
2008-03-04 14:28:20 -08:00
print "PRE_END($1)\n" if ( $ dbg_values > 1 );
$ av_preprocessor = 1 ;
# Assume all arms of the conditional end as this
# one does , and continue as if the #endif was not here .
pop ( @av_paren_type );
push ( @av_paren_type , $ type );
2008-04-29 00:59:32 -07:00
$ type = 'E' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( \\\n ) / o ) {
2008-02-08 04:20:54 -08:00
print "PRECONT($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
2008-04-29 00:59:32 -07:00
} elsif ( $ cur =~ /^ ( __ attribute__ ) \s*\ ( ?/o ) {
print "ATTR($1)\n" if ( $ dbg_values > 1 );
$ av_pending = $ type ;
$ type = 'N' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( sizeof ) \s* ( \ () ?/o ) {
2008-02-08 04:20:54 -08:00
print "SIZEOF($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
if ( defined $ 2 ) {
2008-03-04 14:28:20 -08:00
$ av_pending = 'V' ;
2007-10-18 03:05:08 -07:00
}
$ type = 'N' ;
2008-10-15 22:02:16 -07:00
} elsif ( $ cur =~ /^ ( if | while | for ) \b / o ) {
2008-02-08 04:20:54 -08:00
print "COND($1)\n" if ( $ dbg_values > 1 );
2008-10-15 22:02:16 -07:00
$ av_pending = 'E' ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
2008-07-23 21:29:10 -07:00
} elsif ( $ cur =~/^ ( case ) / o ) {
print "CASE($1)\n" if ( $ dbg_values > 1 );
$ av_pend_colon = 'C' ;
$ type = 'N' ;
2008-10-15 22:02:16 -07:00
} elsif ( $ cur =~/^ ( return | else | goto | typeof | __ typeof__ ) \b / o ) {
2008-02-08 04:20:54 -08:00
print "KEYWORD($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
} elsif ( $ cur =~ /^ ( \ () / o ) {
2008-02-08 04:20:54 -08:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 );
2008-03-04 14:28:20 -08:00
push ( @av_paren_type , $ av_pending );
$ av_pending = '_' ;
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
} elsif ( $ cur =~ /^ ( \ )) / o ) {
2008-03-04 14:28:20 -08:00
my $ new_type = pop ( @av_paren_type );
if ( $ new_type ne '_' ) {
$ type = $ new_type ;
2008-02-08 04:20:54 -08:00
print "PAREN('$1') -> $type\n"
if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
} else {
2008-02-08 04:20:54 -08:00
print "PAREN('$1')\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
}
2008-07-23 21:28:57 -07:00
} elsif ( $ cur =~ /^ ( $ Ident ) \s*\ ( / o ) {
2008-02-08 04:20:54 -08:00
print "FUNC($1)\n" if ( $ dbg_values > 1 );
2008-07-23 21:28:57 -07:00
$ type = 'V' ;
2008-03-04 14:28:20 -08:00
$ av_pending = 'V' ;
2007-10-18 03:05:08 -07:00
2009-01-06 14:41:19 -08:00
} elsif ( $ cur =~ /^ ( $ Ident \s* ) : ( ?:\s*\d+\s* (,| = |;)) ?/ ) {
if ( defined $ 2 && $ type eq 'C' || $ type eq 'T' ) {
2008-07-23 21:29:10 -07:00
$ av_pend_colon = 'B' ;
2009-01-06 14:41:19 -08:00
} elsif ( $ type eq 'E' ) {
$ av_pend_colon = 'L' ;
2008-07-23 21:29:10 -07:00
}
print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ( $ dbg_values > 1 );
$ type = 'V' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( $ Ident | $ Constant ) / o ) {
2008-02-08 04:20:54 -08:00
print "IDENT($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
$ type = 'V' ;
} elsif ( $ cur =~ /^ ( $ Assignment ) / o ) {
2008-02-08 04:20:54 -08:00
print "ASSIGN($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
2008-03-04 14:28:20 -08:00
} elsif ( $ cur =~/^ (;|{|}) / ) {
2008-02-08 04:20:54 -08:00
print "END($1)\n" if ( $ dbg_values > 1 );
2008-02-08 04:22:03 -08:00
$ type = 'E' ;
2008-07-23 21:29:10 -07:00
$ av_pend_colon = 'O' ;
2008-02-08 04:22:03 -08:00
2009-01-06 14:41:19 -08:00
} elsif ( $ cur =~/^ (,) / ) {
print "COMMA($1)\n" if ( $ dbg_values > 1 );
$ type = 'C' ;
2008-07-23 21:29:10 -07:00
} elsif ( $ cur =~ /^ ( \? ) / o ) {
print "QUESTION($1)\n" if ( $ dbg_values > 1 );
$ type = 'N' ;
} elsif ( $ cur =~ /^ ( : ) / o ) {
print "COLON($1,$av_pend_colon)\n" if ( $ dbg_values > 1 );
substr ( $ var , length ( $ res ), 1 , $ av_pend_colon );
if ( $ av_pend_colon eq 'C' || $ av_pend_colon eq 'L' ) {
$ type = 'E' ;
} else {
$ type = 'N' ;
}
$ av_pend_colon = 'O' ;
2009-01-06 14:41:19 -08:00
} elsif ( $ cur =~ /^ ( \ [) / o ) {
2008-02-08 04:22:03 -08:00
print "CLOSE($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
$ type = 'N' ;
2008-10-15 22:02:16 -07:00
} elsif ( $ cur =~ /^ ( - ( ? ![ -> ])| \+ ( ? ! \+ )| \* | \&\& | \& ) / o ) {
2008-07-23 21:29:10 -07:00
my $ variant ;
print "OPV($1)\n" if ( $ dbg_values > 1 );
if ( $ type eq 'V' ) {
$ variant = 'B' ;
} else {
$ variant = 'U' ;
}
substr ( $ var , length ( $ res ), 1 , $ variant );
$ type = 'N' ;
2007-10-18 03:05:08 -07:00
} elsif ( $ cur =~ /^ ( $ Operators ) / o ) {
2008-02-08 04:20:54 -08:00
print "OP($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
if ( $ 1 ne '++' && $ 1 ne '--' ) {
$ type = 'N' ;
}
} elsif ( $ cur =~ / ( ^. ) / o ) {
2008-02-08 04:20:54 -08:00
print "C($1)\n" if ( $ dbg_values > 1 );
2007-10-18 03:05:08 -07:00
}
if ( defined $ 1 ) {
$ cur = substr ( $ cur , length ( $ 1 ));
$ res . = $ type x length ( $ 1 );
}
}
2008-07-23 21:29:10 -07:00
return ( $ res , $ var );
2007-10-18 03:05:08 -07:00
}
2007-11-28 16:21:06 -08:00
sub possible {
2008-02-08 04:22:03 -08:00
my ( $ possible , $ line ) = @ _ ;
2009-10-26 16:50:12 -07:00
my $ notPermitted = qr {( ?:
2008-10-15 22:02:29 -07:00
^ ( ?:
$ Modifier |
$ Storage |
$ Type |
2009-10-26 16:50:12 -07:00
DEFINE_ \ S +
) $ |
^ ( ?:
2008-10-15 22:02:29 -07:00
goto |
return |
case |
else |
asm | __ asm__ |
2012-01-10 15:10:00 -08:00
do |
\# |
\#\# |
2009-10-26 16:50:12 -07:00
)( ?:\s | $ )|
2008-10-15 22:02:29 -07:00
^ ( ?:typedef | struct | enum ) \b
2009-10-26 16:50:12 -07:00
)} x ;
warn "CHECK<$possible> ($line)\n" if ( $ dbg_possible > 2 );
if ( $ possible ! ~ $ notPermitted ) {
2008-06-05 22:46:01 -07:00
# Check for modifiers .
$ possible =~ s/\s* $ Storage \s*//g ;
$ possible =~ s/\s* $ Sparse \s*//g ;
if ( $ possible =~ /^\s* $ / ) {
} elsif ( $ possible =~ /\s/ ) {
$ possible =~ s/\s* $ Type \s*//g ;
2008-07-23 21:29:09 -07:00
for my $ modifier ( split ( ' ' , $ possible )) {
2009-10-26 16:50:12 -07:00
if ( $ modifier ! ~ $ notPermitted ) {
warn "MODIFIER: $modifier ($possible) ($line)\n" if ( $ dbg_possible );
2015-06-25 15:02:52 -07:00
push ( @modifierListFile , $ modifier );
2009-10-26 16:50:12 -07:00
}
2008-07-23 21:29:09 -07:00
}
2008-06-05 22:46:01 -07:00
} else {
warn "POSSIBLE: $possible ($line)\n" if ( $ dbg_possible );
2015-06-25 15:02:52 -07:00
push ( @typeListFile , $ possible );
2008-06-05 22:46:01 -07:00
}
2007-11-28 16:21:06 -08:00
build_types ();
2008-10-15 22:02:29 -07:00
} else {
warn "NOTPOSS: $possible ($line)\n" if ( $ dbg_possible > 1 );
2007-11-28 16:21:06 -08:00
}
}
2007-10-18 03:05:08 -07:00
my $ prefix = '' ;
2011-07-25 17:13:25 -07:00
sub show_type {
2014-04-03 14:49:19 -07:00
my ( $ type ) = @ _ ;
2013-09-11 14:23:59 -07:00
2017-02-27 14:30:05 -08:00
$ type =~ tr / [ a - z ] / [ A - Z ] / ;
2014-04-03 14:49:19 -07:00
return defined $ use_type { $ type } if ( scalar keys %use_type > 0);
return ! defined $ ignore_type { $ type };
2011-07-25 17:13:25 -07:00
}
2007-07-19 01:48:34 -07:00
sub report {
2014-04-03 14:49:19 -07:00
my ( $ level , $ type , $ msg ) = @ _ ;
if (! show_type ( $ type ) ||
( defined $ tst_only && $ msg ! ~ /\ Q $ tst_only\ E / )) {
2008-03-28 14:15:58 -07:00
return 0 ;
}
2015-06-25 15:03:03 -07:00
my $ output = '' ;
2017-07-10 15:52:24 -07:00
if ( $ color ) {
2015-06-25 15:03:03 -07:00
if ( $ level eq 'ERROR' ) {
$ output . = RED ;
} elsif ( $ level eq 'WARNING' ) {
$ output . = YELLOW ;
} else {
$ output . = GREEN ;
}
2011-07-25 17:13:25 -07:00
}
2015-06-25 15:03:03 -07:00
$ output . = $ prefix . $ level . ':' ;
if ( $ show_types ) {
2017-07-10 15:52:24 -07:00
$ output . = BLUE if ( $ color );
2015-06-25 15:03:03 -07:00
$ output . = "$type:" ;
}
2017-07-10 15:52:24 -07:00
$ output . = RESET if ( $ color );
2015-06-25 15:03:03 -07:00
$ output . = ' ' . $ msg . "\n" ;
2015-06-25 15:03:05 -07:00
if ( $ showfile ) {
my @lines = split ( "\n" , $ output , - 1 );
splice ( @lines , 1 , 1 );
$ output = join ( "\n" , @lines );
}
2015-06-25 15:03:03 -07:00
$ output = ( split ( '\n' , $ output ))[ 0 ] . "\n" if ( $ terse );
2007-11-28 16:21:06 -08:00
2015-06-25 15:03:03 -07:00
push ( our @report , $ output );
2008-03-28 14:15:58 -07:00
return 1 ;
2007-07-19 01:48:34 -07:00
}
2014-04-03 14:49:19 -07:00
2007-07-19 01:48:34 -07:00
sub report_dump {
2008-02-08 04:22:03 -08:00
our @report ;
2007-07-19 01:48:34 -07:00
}
2011-07-25 17:13:25 -07:00
2014-08-06 16:11:05 -07:00
sub fixup_current_range {
my ( $ lineRef , $ offset , $ length ) = @ _ ;
if ( $$ lineRef =~ /^\@\@ -\d+ , \d + \+ ( \d+ ),( \d+ ) \@\@/ ) {
my $ o = $ 1 ;
my $ l = $ 2 ;
my $ no = $ o + $ offset ;
my $ nl = $ l + $ length ;
$$ lineRef =~ s/\+ $ o , $ l \@\@/\+ $ no , $ nl \@\@/ ;
}
}
sub fix_inserted_deleted_lines {
my ( $ linesRef , $ insertedRef , $ deletedRef ) = @ _ ;
my $ range_last_linenr = 0 ;
my $ delta_offset = 0 ;
my $ old_linenr = 0 ;
my $ new_linenr = 0 ;
my $ next_insert = 0 ;
my $ next_delete = 0 ;
my @lines = ();
my $ inserted = @ { $ insertedRef }[ $ next_insert++ ];
my $ deleted = @ { $ deletedRef }[ $ next_delete++ ];
foreach my $ old_line ( @ { $ linesRef }) {
my $ save_line = 1 ;
my $ line = $ old_line ; #don't modify the array
2015-04-16 12:44:50 -07:00
if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename
2014-08-06 16:11:05 -07:00
$delta_offset = 0;
} elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk
$range_last_linenr = $new_linenr;
fixup_current_range(\$line, $delta_offset, 0);
}
while (defined($deleted) && ${$deleted}{' LINENR '} == $old_linenr) {
$deleted = @{$deletedRef}[$next_delete++];
$save_line = 0;
fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
}
while (defined($inserted) && ${$inserted}{' LINENR '} == $old_linenr) {
push(@lines, ${$inserted}{' LINE '});
$inserted = @{$insertedRef}[$next_insert++];
$new_linenr++;
fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
}
if ($save_line) {
push(@lines, $line);
$new_linenr++;
}
$old_linenr++;
}
return @lines;
}
2014-08-06 16:11:07 -07:00
sub fix_insert_line {
my ($linenr, $line) = @_;
my $inserted = {
LINENR => $linenr,
LINE => $line,
};
push(@fixed_inserted, $inserted);
}
sub fix_delete_line {
my ($linenr, $line) = @_;
my $deleted = {
LINENR => $linenr,
LINE => $line,
};
push(@fixed_deleted, $deleted);
}
2007-07-15 23:37:22 -07:00
sub ERROR {
2014-04-03 14:49:19 -07:00
my ($type, $msg) = @_;
if (report("ERROR", $type, $msg)) {
2008-03-28 14:15:58 -07:00
our $clean = 0;
our $cnt_error++;
2013-07-03 15:05:31 -07:00
return 1;
2008-03-28 14:15:58 -07:00
}
2013-07-03 15:05:31 -07:00
return 0;
2007-07-15 23:37:22 -07:00
}
sub WARN {
2014-04-03 14:49:19 -07:00
my ($type, $msg) = @_;
if (report("WARNING", $type, $msg)) {
2008-03-28 14:15:58 -07:00
our $clean = 0;
our $cnt_warn++;
2013-07-03 15:05:31 -07:00
return 1;
2008-03-28 14:15:58 -07:00
}
2013-07-03 15:05:31 -07:00
return 0;
2007-07-15 23:37:22 -07:00
}
sub CHK {
2014-04-03 14:49:19 -07:00
my ($type, $msg) = @_;
if ($check && report("CHECK", $type, $msg)) {
2007-10-18 03:05:08 -07:00
our $clean = 0;
our $cnt_chk++;
2013-07-03 15:05:31 -07:00
return 1;
2007-10-18 03:05:08 -07:00
}
2013-07-03 15:05:31 -07:00
return 0;
2007-07-15 23:37:22 -07:00
}
2008-10-15 22:02:21 -07:00
sub check_absolute_file {
my ($absolute, $herecurr) = @_;
my $file = $absolute;
##print "absolute<$absolute>\n";
# See if any suffix of this path is a path within the tree.
while ($file =~ s@^[^/]*/@@) {
if (-f "$root/$file") {
##print "file<$file>\n";
last;
}
}
if (! -f _) {
return 0;
}
# It is, so see if the prefix is acceptable.
my $prefix = $absolute;
substr($prefix, -length($file)) = '';
##print "prefix<$prefix>\n";
if ($prefix ne ".../") {
2011-07-25 17:13:25 -07:00
WARN("USE_RELATIVE_PATH",
"use relative pathname instead of absolute in changelog text\n" . $herecurr);
2008-10-15 22:02:21 -07:00
}
}
2013-07-03 15:05:31 -07:00
sub trim {
my ($string) = @_;
2013-09-11 14:24:01 -07:00
$string =~ s/^\s+|\s+$//g;
return $string;
}
sub ltrim {
my ($string) = @_;
$string =~ s/^\s+//;
return $string;
}
sub rtrim {
my ($string) = @_;
$string =~ s/\s+$//;
2013-07-03 15:05:31 -07:00
return $string;
}
2013-11-12 15:10:09 -08:00
sub string_find_replace {
my ($string, $find, $replace) = @_;
$string =~ s/$find/$replace/g;
return $string;
}
2013-07-03 15:05:31 -07:00
sub tabify {
my ($leading) = @_;
2020-04-06 20:11:07 -07:00
my $source_indent = $tabsize;
2013-07-03 15:05:31 -07:00
my $max_spaces_before_tab = $source_indent - 1;
my $spaces_to_tab = " " x $source_indent;
#convert leading spaces to tabs
1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
#Remove spaces before a tab
1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g;
return "$leading";
}
2012-03-23 15:02:16 -07:00
sub pos_last_openparen {
my ($line) = @_;
my $pos = 0;
my $opens = $line =~ tr/\(/\(/;
my $closes = $line =~ tr/\)/\)/;
my $last_openparen = 0;
if (($opens == 0) || ($closes >= $opens)) {
return -1;
}
my $len = length($line);
for ($pos = 0; $pos < $len; $pos++) {
my $string = substr($line, $pos);
if ($string =~ /^($FuncArg|$balanced_parens)/) {
$pos += length($1) - 1;
} elsif (substr($line, $pos, 1) eq ' ( ') {
$last_openparen = $pos;
} elsif (index($string, ' ( ') == -1) {
last;
}
}
2014-04-03 14:49:32 -07:00
return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
2012-03-23 15:02:16 -07:00
}
2020-04-06 20:10:58 -07:00
sub get_raw_comment {
my ($line, $rawline) = @_;
my $comment = '';
for my $i (0 .. (length($line) - 1)) {
if (substr($line, $i, 1) eq "$;") {
$comment .= substr($rawline, $i, 1);
}
}
return $comment;
}
2007-06-01 00:46:48 -07:00
sub process {
my $filename = shift;
my $linenr=0;
my $prevline="";
2008-02-08 04:20:54 -08:00
my $prevrawline="";
2007-06-01 00:46:48 -07:00
my $stashline="";
2008-02-08 04:20:54 -08:00
my $stashrawline="";
2007-06-01 00:46:48 -07:00
2007-06-08 13:46:39 -07:00
my $length;
2007-06-01 00:46:48 -07:00
my $indent;
my $previndent=0;
my $stashindent=0;
2007-07-15 23:37:22 -07:00
our $clean = 1;
2007-06-01 00:46:48 -07:00
my $signoff = 0;
2018-08-21 21:57:40 -07:00
my $author = '';
my $authorsignoff = 0;
2020-10-15 20:12:28 -07:00
my $author_sob = '';
2007-06-01 00:46:48 -07:00
my $is_patch = 0;
2018-08-21 21:58:16 -07:00
my $is_binding_patch = -1;
2014-08-06 16:10:35 -07:00
my $in_header_lines = $file ? 0 : 1;
2011-10-31 17:13:12 -07:00
my $in_commit_log = 0; #Scanning lines before patch
2020-04-06 20:11:10 -07:00
my $has_patch_separator = 0; #Found a --- line
2016-08-02 14:04:45 -07:00
my $has_commit_log = 0; #Encountered lines before patch
2018-08-21 21:58:01 -07:00
my $commit_log_lines = 0; #Number of commit log lines
2017-02-24 15:01:28 -08:00
my $commit_log_possible_stack_dump = 0;
2015-04-16 12:44:28 -07:00
my $commit_log_long_line = 0;
2015-06-25 15:03:27 -07:00
my $commit_log_has_diff = 0;
2014-08-06 16:10:59 -07:00
my $reported_maintainer_file = 0;
2012-10-04 17:13:29 -07:00
my $non_utf8_charset = 0;
2014-08-06 16:10:42 -07:00
my $last_blank_line = 0;
2014-12-10 15:52:05 -08:00
my $last_coalesced_string_linenr = -1;
2014-08-06 16:10:42 -07:00
2008-02-08 04:22:03 -08:00
our @report = ();
2007-10-18 03:05:08 -07:00
our $cnt_lines = 0;
our $cnt_error = 0;
our $cnt_warn = 0;
our $cnt_chk = 0;
2007-06-01 00:46:48 -07:00
# Trace the real file/line as we go.
my $realfile = '';
my $realline = 0;
my $realcnt = 0;
my $here = '';
2017-02-24 15:01:28 -08:00
my $context_function; #undef'd unless there's a known function
2007-06-01 00:46:48 -07:00
my $in_comment = 0;
2008-02-08 04:20:54 -08:00
my $comment_edge = 0;
2007-06-01 00:46:48 -07:00
my $first_line = 0;
2009-01-06 14:41:24 -08:00
my $p1_prefix = '';
2007-06-01 00:46:48 -07:00
2008-02-08 04:22:03 -08:00
my $prev_values = ' E ';
# suppression flags
2008-03-28 14:15:58 -07:00
my %suppress_ifbraces;
2008-10-15 22:02:30 -07:00
my %suppress_whiletrailers;
2009-10-26 16:50:16 -07:00
my %suppress_export;
2012-01-10 15:10:01 -08:00
my $suppress_statement = 0;
2007-06-23 17:16:34 -07:00
2013-09-11 14:23:57 -07:00
my %signatures = ();
2012-12-17 16:02:07 -08:00
2008-02-08 04:20:54 -08:00
# Pre-scan the patch sanitizing the lines.
2007-07-15 23:37:22 -07:00
# Pre-scan the patch looking for any __setup documentation.
2008-02-08 04:20:54 -08:00
#
2007-07-15 23:37:22 -07:00
my @setup_docs = ();
my $setup_docs = 0;
2008-03-28 14:15:58 -07:00
2013-11-12 15:10:06 -08:00
my $camelcase_file_seeded = 0;
2018-04-10 16:33:13 -07:00
my $checklicenseline = 1;
2008-03-28 14:15:58 -07:00
sanitise_line_reset();
2008-02-08 04:20:54 -08:00
my $line;
foreach my $rawline (@rawlines) {
2008-03-28 14:15:58 -07:00
$linenr++;
$line = $rawline;
2008-02-08 04:20:54 -08:00
2013-07-03 15:05:31 -07:00
push(@fixed, $rawline) if ($fix);
2008-03-28 14:15:58 -07:00
if ($rawline=~/^\+\+\+\s+(\S+)/) {
2007-07-15 23:37:22 -07:00
$setup_docs = 0;
2020-06-10 18:41:38 -07:00
if ($1 =~ m@Documentation/admin-guide/kernel-parameters.txt$@) {
2007-07-15 23:37:22 -07:00
$setup_docs = 1;
}
2008-03-28 14:15:58 -07:00
#next;
2007-07-15 23:37:22 -07:00
}
2017-05-08 15:56:02 -07:00
if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
2008-03-28 14:15:58 -07:00
$realline=$1-1;
if (defined $2) {
$realcnt=$3+1;
} else {
$realcnt=1+1;
}
2008-06-05 22:46:01 -07:00
$in_comment = 0;
2008-03-28 14:15:58 -07:00
# Guestimate if this is a continuing comment. Run
# the context looking for a comment "edge". If this
# edge is a close comment then we must be in a comment
# at context start.
my $edge;
2008-10-15 22:02:19 -07:00
my $cnt = $realcnt;
for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
next if (defined $rawlines[$ln - 1] &&
$rawlines[$ln - 1] =~ /^-/);
$cnt--;
#print "RAW<$rawlines[$ln - 1]>\n";
2009-01-06 14:41:16 -08:00
last if (!defined $rawlines[$ln - 1]);
2009-01-06 14:41:20 -08:00
if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
$rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
($edge) = $1;
last;
}
2008-03-28 14:15:58 -07:00
}
if (defined $edge && $edge eq '*/') {
$in_comment = 1;
}
# Guestimate if this is a continuing comment. If this
# is the start of a diff block and this line starts
# ' *' then it is very likely a comment.
if (!defined $edge &&
2009-01-06 14:41:17 -08:00
$rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
2008-03-28 14:15:58 -07:00
{
$in_comment = 1;
}
##print "COMMENT:$in_comment edge<$edge> $rawline\n";
sanitise_line_reset($in_comment);
2008-04-29 00:59:32 -07:00
} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
2008-03-28 14:15:58 -07:00
# Standardise the strings and chars within the input to
2008-04-29 00:59:32 -07:00
# simplify matching -- only bother with positive lines.
2008-03-28 14:15:58 -07:00
$line = sanitise_line($rawline);
}
push(@lines, $line);
if ($realcnt > 1) {
$realcnt-- if ($line =~ /^(?:\+| |$)/);
} else {
$realcnt = 0;
}
#print "==>$rawline\n";
#print "-->$line\n";
2007-07-15 23:37:22 -07:00
if ($setup_docs && $line =~ /^\+/) {
push(@setup_docs, $line);
}
}
2007-10-18 03:05:08 -07:00
$prefix = '';
2008-03-28 14:15:58 -07:00
$realcnt = 0;
$linenr = 0;
2014-08-06 16:11:03 -07:00
$fixlinenr = -1;
2007-06-01 00:46:48 -07:00
foreach my $line (@lines) {
$linenr++;
2014-08-06 16:11:03 -07:00
$fixlinenr++;
2013-09-11 14:24:03 -07:00
my $sline = $line; #copy of $line
$sline =~ s/$;/ /g; #with comments as spaces
2007-06-01 00:46:48 -07:00
2008-02-08 04:20:54 -08:00
my $rawline = $rawlines[$linenr - 1];
2020-04-06 20:10:58 -07:00
my $raw_comment = get_raw_comment($line, $rawline);
2007-10-18 03:05:08 -07:00
2018-06-07 17:10:58 -07:00
# check if it's a mode change , rename or start of a patch
if (! $ in_commit_log &&
( $ line =~ /^ mode change [ 0 - 7 ] + => [ 0 - 7 ] + \ S +\s* $ / ||
( $ line =~ /^ rename ( ?:from | to ) \ S +\s* $ / ||
$ line =~ /^diff --git a\/ [ \w\/\.\ _ \- ] + b\/\ S +\s* $ / ))) {
$ is_patch = 1 ;
}
2007-06-01 00:46:48 -07:00
#extract the line range in the file after the patch is applied
2015-06-25 15:03:27 -07:00
if (! $ in_commit_log &&
2017-05-08 15:56:02 -07:00
$ line =~ /^\@\@ -\d+ ( ?: , \d+ ) ? \+ ( \d+ )(,( \d+ )) ? \@\@ (. * ) / ) {
my $ context = $ 4 ;
2007-06-01 00:46:48 -07:00
$ is_patch = 1 ;
2007-06-08 13:46:39 -07:00
$ first_line = $ linenr + 1 ;
2007-06-01 00:46:48 -07:00
$ realline= $ 1 - 1 ;
if ( defined $ 2 ) {
$ realcnt= $ 3 + 1 ;
} else {
$ realcnt = 1 + 1 ;
}
2008-02-08 04:20:54 -08:00
annotate_reset ();
2008-02-08 04:22:03 -08:00
$ prev_values = 'E' ;
2008-03-28 14:15:58 -07:00
%suppress_ifbraces = ();
2008-10-15 22:02:30 -07:00
%suppress_whiletrailers = ();
2009-10-26 16:50:16 -07:00
%suppress_export = ();
2012-01-10 15:10:01 -08:00
$ suppress_statement = 0 ;
2017-05-08 15:56:02 -07:00
if ( $ context =~ /\ b ( \w+ ) \s*\ ( / ) {
$ context_function = $ 1 ;
} else {
undef $ context_function ;
}
2007-06-01 00:46:48 -07:00
next ;
2007-06-08 13:46:39 -07:00
# track the line number as we move through the hunk , note that
# new versions of GNU diff omit the leading space on completely
# blank context lines so we need to count that too .
2008-03-28 14:15:58 -07:00
} elsif ( $ line =~ /^ ( | \+ | $ ) / ) {
2007-06-01 00:46:48 -07:00
$ realline++ ;
2007-06-23 17:16:44 -07:00
$ realcnt-- if ( $ realcnt ! = 0 );
2007-06-01 00:46:48 -07:00
2007-06-08 13:46:39 -07:00
# Measure the line length and indent .
2008-02-08 04:20:54 -08:00
( $ length , $ indent ) = line_stats ( $ rawline );
2007-06-01 00:46:48 -07:00
# Track the previous line .
( $ prevline , $ stashline ) = ( $ stashline , $ line );
( $ previndent , $ stashindent ) = ( $ stashindent , $ indent );
2008-02-08 04:20:54 -08:00
( $ prevrawline , $ stashrawline ) = ( $ stashrawline , $ rawline );
2008-03-28 14:15:58 -07:00
#warn "line<$line>\n" ;
2007-10-18 03:05:08 -07:00
2007-06-23 17:16:44 -07:00
} elsif ( $ realcnt == 1 ) {
$ realcnt-- ;
2007-06-01 00:46:48 -07:00
}
2009-10-26 16:50:13 -07:00
my $ hunk_line = ( $ realcnt ! = 0 );
2007-10-18 03:05:08 -07:00
$ here = "#$linenr: " if (! $ file );
$ here = "#$realline: " if ( $ file );
2008-03-28 14:15:58 -07:00
2014-06-04 16:12:05 -07:00
my $ found_file = 0 ;
2008-03-28 14:15:58 -07:00
# extract the filename as it passes
2010-10-26 14:23:16 -07:00
if ( $ line =~ /^diff --git . *? ( \ S + ) $ / ) {
$ realfile = $ 1 ;
2013-11-12 15:10:14 -08:00
$ realfile =~ s@^ ([ ^/ ] * ) /@@ if (! $ file );
2012-01-10 15:09:50 -08:00
$ in_commit_log = 0 ;
2014-06-04 16:12:05 -07:00
$ found_file = 1 ;
2010-10-26 14:23:16 -07:00
} elsif ( $ line =~ /^\+\+\+\s+ ( \ S + ) / ) {
2008-03-28 14:15:58 -07:00
$ realfile = $ 1 ;
2013-11-12 15:10:14 -08:00
$ realfile =~ s@^ ([ ^/ ] * ) /@@ if (! $ file );
2012-01-10 15:09:50 -08:00
$ in_commit_log = 0 ;
2009-01-06 14:41:24 -08:00
$ p1_prefix = $ 1 ;
2009-02-27 14:03:06 -08:00
if (! $ file && $ tree && $ p1_prefix ne '' &&
- e "$root/$p1_prefix" ) {
2011-07-25 17:13:25 -07:00
WARN ( "PATCH_PREFIX" ,
"patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n" );
2009-01-06 14:41:24 -08:00
}
2008-03-28 14:15:58 -07:00
2008-10-15 22:02:20 -07:00
if ( $ realfile =~ m@^include / asm/@ ) {
2011-07-25 17:13:25 -07:00
ERROR ( "MODIFIED_INCLUDE_ASM" ,
"do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n" );
2008-03-28 14:15:58 -07:00
}
2014-06-04 16:12:05 -07:00
$ found_file = 1 ;
}
2015-06-25 15:03:05 -07:00
#make up the handle for any error we report on this line
if ( $ showfile ) {
$ prefix = "$realfile:$realline: "
} elsif ( $ emacs ) {
2015-09-09 15:37:39 -07:00
if ( $ file ) {
$ prefix = "$filename:$realline: " ;
} else {
$ prefix = "$filename:$linenr: " ;
}
2015-06-25 15:03:05 -07:00
}
2014-06-04 16:12:05 -07:00
if ( $ found_file ) {
2016-10-11 13:51:44 -07:00
if ( is_maintained_obsolete ( $ realfile )) {
WARN ( "OBSOLETE" ,
"$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n" );
}
2015-09-09 15:37:44 -07:00
if ( $ realfile =~ m@^ ( ?:drivers / net/ | net/ | drivers / staging/ ) @ ) {
2014-06-04 16:12:05 -07:00
$ check = 1 ;
} else {
$ check = $ check_orig ;
}
2018-04-10 16:33:13 -07:00
$ checklicenseline = 1 ;
2018-08-21 21:58:16 -07:00
if ( $ realfile ! ~ /^ MAINTAINERS / ) {
my $ last_binding_patch = $ is_binding_patch ;
$ is_binding_patch = () = $ realfile =~ m@^ ( ?: Documentation / devicetree/ | include / dt - bindings/ ) @ ;
if (( $ last_binding_patch ! = - 1 ) &&
( $ last_binding_patch ^ $ is_binding_patch )) {
WARN ( "DT_SPLIT_BINDING_PATCH" ,
2020-04-15 16:45:25 +02:00
"DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.rst\n" );
2018-08-21 21:58:16 -07:00
}
}
2008-03-28 14:15:58 -07:00
next ;
}
2007-06-08 13:47:03 -07:00
$ here . = "FILE: $realfile:$realline:" if ( $ realcnt ! = 0 );
2007-06-01 00:46:48 -07:00
2008-02-08 04:20:54 -08:00
my $ hereline = "$here\n$rawline\n" ;
my $ herecurr = "$here\n$rawline\n" ;
my $ hereprev = "$here\n$prevrawline\n$rawline\n" ;
2007-06-01 00:46:48 -07:00
2007-10-18 03:05:08 -07:00
$ cnt_lines++ if ( $ realcnt ! = 0 );
2018-08-21 21:58:01 -07:00
# Verify the existence of a commit log if appropriate
# 2 is used because a $ signature is counted in $ commit_log_lines
if ( $ in_commit_log ) {
if ( $ line ! ~ /^\s* $ / ) {
$ commit_log_lines++ ; #could be a $ signature
}
} elsif ( $ has_commit_log && $ commit_log_lines < 2 ) {
WARN ( "COMMIT_MESSAGE" ,
"Missing commit description - Add an appropriate one\n" );
$ commit_log_lines = 2 ; #warn only once
}
2015-06-25 15:03:27 -07:00
# Check if the commit log has what seems like a diff which can confuse patch
if ( $ in_commit_log && ! $ commit_log_has_diff &&
2020-09-04 16:35:52 -07:00
(( $ line =~ m@^\s + diff\b . * a/ ([ \w/ ] + ) @ &&
$ line =~ m@^\s + diff\b . * a / [ \w/ ] +\s + b/ $ 1 \b@ ) ||
2015-06-25 15:03:27 -07:00
$ line =~ m@^\s* ( ?:\-\-\-\s + a/ | \+\+\+\s + b/ ) @ ||
$ line =~ m/^\s*\@\@ \-\d+ , \d + \+\d+ , \d + \@\@/ )) {
ERROR ( "DIFF_IN_COMMIT_MSG" ,
"Avoid using diff content in the commit message - patch(1) might not work\n" . $ herecurr );
$ commit_log_has_diff = 1 ;
}
2010-10-26 14:23:16 -07:00
# Check for incorrect file permissions
if ( $ line =~ /^ new ( file ) ?mode . * [ 7531 ] \d { 0 , 2 } $ / ) {
my $ permhere = $ here . "FILE: $realfile\n" ;
2013-04-29 16:18:14 -07:00
if ( $ realfile ! ~ m@scripts/@ &&
$ realfile ! ~ /\. ( py | pl | awk | sh ) $ / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "EXECUTE_PERMISSIONS" ,
"do not set execute permissions for source files\n" . $ permhere );
2010-10-26 14:23:16 -07:00
}
}
2018-08-21 21:57:40 -07:00
# Check the patch for a From :
if ( decode ( "MIME-Header" , $ line ) =~ /^ From :\s* (. * ) / ) {
$ author = $ 1 ;
2020-10-15 20:12:15 -07:00
my $ curline = $ linenr ;
while ( defined ( $ rawlines [ $ curline ]) && ( $ rawlines [ $ curline++ ] =~ /^ [ \t ] \s* (. * ) / )) {
$ author . = $ 1 ;
}
2018-08-21 21:57:40 -07:00
$ author = encode ( "utf8" , $ author ) if ( $ line =~ /=\?utf - 8 \?/i );
$ author =~ s/ " // g ;
2020-04-06 20:10:48 -07:00
$ author = reformat_email ( $ author );
2018-08-21 21:57:40 -07:00
}
2011-07-25 17:13:23 -07:00
# Check the patch for a signoff :
2020-04-06 20:10:48 -07:00
if ( $ line =~ /^\s * signed - off - by : \s* (. * ) / i ) {
2007-06-08 13:46:39 -07:00
$ signoff++ ;
2011-10-31 17:13:12 -07:00
$ in_commit_log = 0 ;
2020-10-15 20:12:28 -07:00
if ( $ author ne '' && $ authorsignoff ! = 1 ) {
2020-12-15 20:44:53 -08:00
if ( same_email_addresses ( $ 1 , $ author )) {
2020-04-06 20:10:48 -07:00
$ authorsignoff = 1 ;
2020-10-15 20:12:28 -07:00
} else {
my $ ctx = $ 1 ;
my ( $ email_name , $ email_comment , $ email_address , $ comment1 ) = parse_email ( $ ctx );
my ( $ author_name , $ author_comment , $ author_address , $ comment2 ) = parse_email ( $ author );
if ( $ email_address eq $ author_address && $ email_name eq $ author_name ) {
$ author_sob = $ ctx ;
$ authorsignoff = 2 ;
} elsif ( $ email_address eq $ author_address ) {
$ author_sob = $ ctx ;
$ authorsignoff = 3 ;
} elsif ( $ email_name eq $ author_name ) {
$ author_sob = $ ctx ;
$ authorsignoff = 4 ;
my $ address1 = $ email_address ;
my $ address2 = $ author_address ;
if ( $ address1 =~ / ( \ S + ) \+\ S + ( \@.* ) / ) {
$ address1 = "$1$2" ;
}
if ( $ address2 =~ / ( \ S + ) \+\ S + ( \@.* ) / ) {
$ address2 = "$1$2" ;
}
if ( $ address1 eq $ address2 ) {
$ authorsignoff = 5 ;
}
}
2018-08-21 21:57:40 -07:00
}
}
2011-07-25 17:13:23 -07:00
}
2020-04-06 20:11:10 -07:00
# Check for patch separator
if ( $ line =~ /^--- $ / ) {
$ has_patch_separator = 1 ;
$ in_commit_log = 0 ;
}
2014-12-10 15:51:49 -08:00
# Check if MAINTAINERS is being updated . If so , there's probably no need to
# emit the "does MAINTAINERS need updating?" message on file add/move/delete
if ($line =~ /^\s*MAINTAINERS\s*\|/) {
$reported_maintainer_file = 1;
}
2011-07-25 17:13:23 -07:00
# Check signature styles
2012-01-10 15:09:50 -08:00
if (!$in_header_lines &&
2012-07-30 14:41:18 -07:00
$line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
2011-07-25 17:13:23 -07:00
my $space_before = $1;
my $sign_off = $2;
my $space_after = $3;
my $email = $4;
my $ucfirst_sign_off = ucfirst(lc($sign_off));
2012-07-30 14:41:18 -07:00
if ($sign_off !~ /$signature_tags/) {
2020-12-15 20:45:12 -08:00
my $suggested_signature = find_standard_signature($sign_off);
if ($suggested_signature eq "") {
WARN("BAD_SIGN_OFF",
"Non-standard signature: $sign_off\n" . $herecurr);
} else {
if (WARN("BAD_SIGN_OFF",
"Non-standard signature: ' $ sign_off' - perhaps ' $ suggested_signature'?\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/$sign_off/$suggested_signature/;
}
}
2012-07-30 14:41:18 -07:00
}
2011-07-25 17:13:23 -07:00
if (defined $space_before && $space_before ne "") {
2013-07-03 15:05:31 -07:00
if (WARN("BAD_SIGN_OFF",
"Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =
2013-07-03 15:05:31 -07:00
"$ucfirst_sign_off $email";
}
2007-06-01 00:46:48 -07:00
}
2011-07-25 17:13:23 -07:00
if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
2013-07-03 15:05:31 -07:00
if (WARN("BAD_SIGN_OFF",
"' $ ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =
2013-07-03 15:05:31 -07:00
"$ucfirst_sign_off $email";
}
2011-07-25 17:13:23 -07:00
}
if (!defined $space_after || $space_after ne " ") {
2013-07-03 15:05:31 -07:00
if (WARN("BAD_SIGN_OFF",
"Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =
2013-07-03 15:05:31 -07:00
"$ucfirst_sign_off $email";
}
2011-07-25 17:13:23 -07:00
}
2020-04-06 20:10:48 -07:00
my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
2020-10-15 20:12:28 -07:00
my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment));
2011-07-25 17:13:23 -07:00
if ($suggested_email eq "") {
2011-07-25 17:13:25 -07:00
ERROR("BAD_SIGN_OFF",
"Unrecognized email address: ' $ email'\n" . $herecurr);
2011-07-25 17:13:23 -07:00
} else {
my $dequoted = $suggested_email;
$dequoted =~ s/^"//;
$dequoted =~ s/" </ </;
# Don't force email to have quotes
# Allow just an angle bracketed address
2020-12-15 20:44:53 -08:00
if (! same_email_addresses ( $ email , $ suggested_email )) {
if ( WARN ( "BAD_SIGN_OFF" ,
"email address '$email' might be better as '$suggested_email'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\ Q $ email\ E / $ suggested_email/ ;
}
}
# Address part shouldn't have comments
my $stripped_address = $email_address;
$stripped_address =~ s/\([^\(\)]*\)//g;
if ($email_address ne $stripped_address) {
if (WARN("BAD_SIGN_OFF",
"address part of email should not have comments: ' $ email_address'\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\Q$email_address\E/$stripped_address/;
}
}
# Only one name comment should be allowed
my $comment_count = () = $name_comment =~ /\([^\)]+\)/g;
if ($comment_count > 1) {
2011-07-25 17:13:25 -07:00
WARN("BAD_SIGN_OFF",
2020-12-15 20:44:53 -08:00
"Use a single name comment in email: ' $ email'\n" . $herecurr);
}
# stable@vger.kernel.org or stable@kernel.org shouldn't
2020-12-15 20:44:56 -08:00
# have an email name . In addition comments should strictly
2020-12-15 20:44:53 -08:00
# begin with a #
if ( $ email =~ /^.*stable\@ ( ?:vger\. ) ?kernel\.org / i ) {
if (( $ comment ne "" && $ comment ! ~ /^#.+/ ) ||
( $ email_name ne "" )) {
my $ cur_name = $ email_name ;
my $ new_comment = $ comment ;
$ cur_name =~ s / [ a - zA - Z \s\-\ " ] +//g ;
# Remove brackets enclosing comment text
# and # from start of comments to get comment text
$ new_comment =~ s/^\ ((. * ) \ ) $ / $ 1 / ;
$ new_comment =~ s/^\ [(. * ) \ ] $ / $ 1 / ;
$ new_comment =~ s/^ [ \s\# ] + | \s+ $ // g ;
$ new_comment = trim ( "$new_comment $cur_name" ) if ( $ cur_name ne $ new_comment );
$ new_comment = " # $new_comment" if ( $ new_comment ne "" );
my $ new_email = "$email_address$new_comment" ;
if ( WARN ( "BAD_STABLE_ADDRESS_STYLE" ,
"Invalid email format for stable: '$email', prefer '$new_email'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\ Q $ email\ E / $ new_email/ ;
}
}
} elsif ( $ comment ne "" && $ comment ! ~ /^ ( ?:#.+ | \ (. +\ )) $ / ) {
my $ new_comment = $ comment ;
# Extract comment text from within brackets or
# c89 style /*...*/ comments
$ new_comment =~ s/^\ [(. * ) \ ] $ / $ 1 / ;
$ new_comment =~ s/^\/\* (. * ) \*\/ $ / $ 1 / ;
$ new_comment = trim ( $ new_comment );
$ new_comment =~ s/^ [ ^\w ] $ // ; # Single lettered comment with non word character is usually a typo
$ new_comment = "($new_comment)" if ( $ new_comment ne "" );
my $ new_email = format_email ( $ email_name , $ name_comment , $ email_address , $ new_comment );
if ( WARN ( "BAD_SIGN_OFF" ,
"Unexpected content after email: '$email', should be: '$new_email'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\ Q $ email\ E / $ new_email/ ;
}
2011-07-25 17:13:23 -07:00
}
2007-06-01 00:46:48 -07:00
}
2013-09-11 14:23:57 -07:00
# Check for duplicate signatures
my $ sig_nospace = $ line ;
$ sig_nospace =~ s/\s // g ;
$ sig_nospace = lc ( $ sig_nospace );
if ( defined $ signatures { $ sig_nospace }) {
WARN ( "BAD_SIGN_OFF" ,
"Duplicate signature\n" . $ herecurr );
} else {
$ signatures { $ sig_nospace } = 1 ;
}
2019-03-22 14:11:37 -07:00
# Check Co - developed - by : immediately followed by Signed - off - by : with same name and email
if ( $ sign_off =~ /^co - developed - by : $ / i ) {
if ( $ email eq $ author ) {
WARN ( "BAD_SIGN_OFF" ,
"Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $ rawline );
}
if (! defined $ lines [ $ linenr ]) {
WARN ( "BAD_SIGN_OFF" ,
2021-02-25 17:21:47 -08:00
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $ rawline );
2019-03-22 14:11:37 -07:00
} elsif ( $ rawlines [ $ linenr ] ! ~ /^\s * signed - off - by : \s* (. * ) / i ) {
WARN ( "BAD_SIGN_OFF" ,
"Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $ rawline . "\n" . $ rawlines [ $ linenr ]);
} elsif ( $ 1 ne $ email ) {
WARN ( "BAD_SIGN_OFF" ,
"Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $ rawline . "\n" . $ rawlines [ $ linenr ]);
}
}
2007-06-01 00:46:48 -07:00
}
2015-02-13 14:39:02 -08:00
# Check email subject for common tools that don't need to be mentioned
if ($in_header_lines &&
$line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) {
WARN("EMAIL_SUBJECT",
"A patch subject line should describe the change not the tool that found it\n" . $herecurr);
}
2020-04-06 20:11:10 -07:00
# Check for Gerrit Change-Ids not in any patch context
if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
2020-12-15 20:44:47 -08:00
if (ERROR("GERRIT_CHANGE_ID",
"Remove Gerrit Change-Id's before submitting upstream\n " . $ herecurr ) &&
$ fix ) {
2021-02-25 17:21:47 -08:00
fix_delete_line ( $ fixlinenr , $ rawline );
}
2014-04-03 14:49:31 -07:00
}
2015-11-06 16:31:34 -08:00
# Check if the commit log is in a possible stack dump
if ( $ in_commit_log && ! $ commit_log_possible_stack_dump &&
( $ line =~ /^\s* ( ?: WARNING : | BUG : ) / ||
$ line =~ /^\s*\ [ \s*\d+\.\d { 6 , 6 } \s*\ ] / ||
# timestamp
2019-09-25 16:46:32 -07:00
$ line =~ /^\s*\ [ \< [ 0 - 9 a - fA - F ]{ 8 ,} \>\ ] / ) ||
$ line =~ /^ ( ?:\s+\w+:\s + [ 0 - 9 a - fA - F ] + ){ 3 , 3 } / ||
$ line =~ /^\s*\#\d+\s*\ [[ 0 - 9 a - fA - F ] +\ ] \s*\w + at [ 0 - 9 a - fA - F ] +/ ) {
# stack dump address styles
2015-11-06 16:31:34 -08:00
$ commit_log_possible_stack_dump = 1 ;
}
2015-04-16 12:44:28 -07:00
# Check for line lengths > 75 in commit log , warn once
if ( $ in_commit_log && ! $ commit_log_long_line &&
2015-11-06 16:31:34 -08:00
length ( $ line ) > 75 &&
!( $ line =~ /^\s * [ a - zA - Z0 - 9 _ \/\. ] +\s+\ | \s+\d+/ ||
# file delta changes
$ line =~ /^\s* ( ?: [ \w\.\- ] +\/ ) ++ [ \w\.\- ] +:/ ||
# filename then :
2020-12-15 20:44:59 -08:00
$ line =~ /^\s* ( ?: Fixes : | Link : | $ signature_tags ) / i ||
# A Fixes : or Link : line or signature tag line
2015-11-06 16:31:34 -08:00
$ commit_log_possible_stack_dump )) {
2015-04-16 12:44:28 -07:00
WARN ( "COMMIT_LOG_LONG_LINE" ,
"Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $ herecurr );
$ commit_log_long_line = 1 ;
}
2015-09-09 15:37:50 -07:00
# Reset possible stack dump if a blank line is found
2015-11-06 16:31:34 -08:00
if ( $ in_commit_log && $ commit_log_possible_stack_dump &&
$ line =~ /^\s* $ / ) {
$ commit_log_possible_stack_dump = 0 ;
}
2015-09-09 15:37:50 -07:00
2020-12-15 20:45:18 -08:00
# Check for lines starting with a #
if ( $ in_commit_log && $ line =~ /^#/ ) {
if ( WARN ( "COMMIT_COMMENT_SYMBOL" ,
"Commit log lines starting with '#' are dropped by git as comments\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/^/ / ;
}
}
2015-02-13 14:38:35 -08:00
# Check for git id commit length and improperly formed commit descriptions
2015-11-06 16:31:34 -08:00
if ( $ in_commit_log && ! $ commit_log_possible_stack_dump &&
2020-04-06 20:10:55 -07:00
$ line ! ~ /^\s* ( ?: Link | Patchwork | http | https | BugLink | base - commit ) :/i &&
2017-05-08 15:55:54 -07:00
$ line ! ~ /^ This reverts commit [ 0 - 9 a - f ]{ 7 , 40 } / &&
2015-09-09 15:37:25 -07:00
( $ line =~ /\bcommit\s + [ 0 - 9 a - f ]{ 5 ,} \b / i ||
2016-08-02 14:04:36 -07:00
( $ line =~ / ( ?:\s | ^ )[ 0 - 9 a - f ]{ 12 , 40 }( ?: [ \s " '\(\[]|$)/i &&
2015-11-06 16:31:34 -08:00
$line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
$line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
2015-09-09 15:37:25 -07:00
my $init_char = "c";
my $orig_commit = "";
2015-02-13 14:38:35 -08:00
my $short = 1;
my $long = 0;
my $case = 1;
my $space = 1;
my $hasdesc = 0;
2015-02-13 14:39:00 -08:00
my $hasparens = 0;
2015-02-13 14:38:35 -08:00
my $id = ' 0123456789 ab';
my $orig_desc = "commit description";
my $description = "";
2015-09-09 15:37:25 -07:00
if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
$init_char = $1;
$orig_commit = lc($2);
} elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) {
$orig_commit = lc($1);
}
2015-02-13 14:38:35 -08:00
$short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i);
$long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i);
$space = 0 if ($line =~ /\bcommit [0-9a-f]/i);
$case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) {
$orig_desc = $1;
2015-02-13 14:39:00 -08:00
$hasparens = 1;
2015-02-13 14:38:35 -08:00
} elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i &&
defined $rawlines[$linenr] &&
$rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) {
$orig_desc = $1;
2015-02-13 14:39:00 -08:00
$hasparens = 1;
2015-02-13 14:38:41 -08:00
} elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i &&
defined $rawlines[$linenr] &&
$rawlines[$linenr] =~ /^\s*[^"]+"\)/) {
$line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i;
$orig_desc = $1;
$rawlines[$linenr] =~ /^\s*([^"]+)"\)/;
$orig_desc .= " " . $1;
2015-02-13 14:39:00 -08:00
$hasparens = 1;
2015-02-13 14:38:35 -08:00
}
($id, $description) = git_commit_info($orig_commit,
$id, $orig_desc);
2017-07-10 15:52:16 -07:00
if (defined($id) &&
($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) {
2015-02-13 14:38:35 -08:00
ERROR("GIT_COMMIT_ID",
"Please use git commit description style 'commit < 12 + chars of sha1 > ( \ "<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $ herecurr );
}
2014-08-06 16:10:57 -07:00
}
2014-08-06 16:10:59 -07:00
# Check for added , moved or deleted files
if (! $ reported_maintainer_file && ! $ in_commit_log &&
( $ line =~ /^ ( ?:new | deleted ) file mode\s*\d+\s* $ / ||
$ line =~ /^ rename ( ?:from | to ) [ \w\/\.\- ] +\s* $ / ||
( $ line =~ /\ { \s* ([ \w\/\.\- ] * ) \s*\=\>\s* ([ \w\/\.\- ] * ) \s*\ } / &&
( defined ( $ 1 ) || defined ( $ 2 ))))) {
2016-12-12 16:46:37 -08:00
$ is_patch = 1 ;
2014-08-06 16:10:59 -07:00
$ reported_maintainer_file = 1 ;
WARN ( "FILE_PATH_CHANGES" ,
"added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $ herecurr );
}
2019-09-12 15:18:20 +01:00
# Check for adding new DT bindings not in schema format
if (! $ in_commit_log &&
( $ line =~ /^new file mode\s*\d+\s* $ / ) &&
( $ realfile =~ m@^ Documentation / devicetree / bindings/.*\.txt$@ )) {
WARN ( "DT_SCHEMA_BINDING_PATCH" ,
"DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n" );
}
2007-06-08 13:47:06 -07:00
# Check for wrappage within a valid hunk of the file
2007-11-28 16:21:06 -08:00
if ( $ realcnt ! = 0 && $ line ! ~ m { ^ ( ?:\+ | - | | \\ No newline | $ )}) {
2011-07-25 17:13:25 -07:00
ERROR ( "CORRUPTED_PATCH" ,
"patch seems to be corrupt (line wrapped?)\n" .
2007-10-18 03:05:08 -07:00
$ herecurr ) if (! $ emitted_corrupt++ );
2007-07-15 23:37:22 -07:00
}
# UTF - 8 regex found at http : // www . w3 . org / International / questions / qa - forms - utf - 8. en . php
if (( $ realfile =~ /^ $ / || $ line =~ /^\+/ ) &&
2008-04-29 00:59:32 -07:00
$ rawline ! ~ m/^ $ UTF8 * $ / ) {
my ( $ utf8_prefix ) = ( $ rawline =~ /^ ( $ UTF8 * ) / );
my $ blank = copy_spacing ( $ rawline );
my $ ptr = substr ( $ blank , 0 , length ( $ utf8_prefix )) . "^" ;
my $ hereptr = "$hereline$ptr\n" ;
2011-07-25 17:13:26 -07:00
CHK ( "INVALID_UTF8" ,
"Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $ hereptr );
2007-06-08 13:47:06 -07:00
}
2007-06-01 00:46:48 -07:00
2011-10-31 17:13:12 -07:00
# Check if it's the start of a commit log
# (not a header line and we haven't seen the patch filename )
if ( $ in_header_lines && $ realfile =~ /^ $ / &&
2017-05-08 15:55:42 -07:00
!( $ rawline =~ /^\s+ ( ?:\ S | $ ) / ||
$ rawline =~ /^ ( ?:commit\b | from\b |[ \w- ] +: ) / i )) {
2011-10-31 17:13:12 -07:00
$ in_header_lines = 0 ;
$ in_commit_log = 1 ;
2016-08-02 14:04:45 -07:00
$ has_commit_log = 1 ;
2011-10-31 17:13:12 -07:00
}
2012-10-04 17:13:29 -07:00
# Check if there is UTF - 8 in a commit log when a mail header has explicitly
# declined it , i . e defined some charset where it is missing .
if ( $ in_header_lines &&
$ rawline =~ /^ Content - Type :.+charset= "(.+)" . * $ / &&
$ 1 ! ~ / utf - 8 / i ) {
$ non_utf8_charset = 1 ;
}
if ( $ in_commit_log && $ non_utf8_charset && $ realfile =~ /^ $ / &&
2011-10-31 17:13:12 -07:00
$ rawline =~ / $ NON_ASCII_UTF8 / ) {
2012-10-04 17:13:29 -07:00
WARN ( "UTF8_BEFORE_PATCH" ,
2011-10-31 17:13:12 -07:00
"8-bit UTF-8 used in possible commit log\n" . $ herecurr );
}
2016-12-12 16:46:28 -08:00
# Check for absolute kernel paths in commit message
if ( $ tree && $ in_commit_log ) {
while ( $ line =~ m {( ?:^ | \s )( /\ S * )} g ) {
my $ file = $ 1 ;
if ( $ file =~ m { ^ (. *? )( ?::\d+ ) +:? $ } &&
check_absolute_file ( $ 1 , $ herecurr )) {
#
} else {
check_absolute_file ( $ file , $ herecurr );
}
}
}
2014-10-13 15:51:57 -07:00
# Check for various typo / spelling mistakes
2015-04-16 12:44:08 -07:00
if ( defined ( $ misspellings ) &&
( $ in_commit_log || $ line =~ /^ ( ?:\+ | Subject : ) / i )) {
2020-12-15 20:45:21 -08:00
while ( $ rawline =~ / ( ?:^ |[ ^\w\-'`])($misspellings)(?:[^\w\-' ` ]| $ ) / gi ) {
2014-10-13 15:51:57 -07:00
my $ typo = $ 1 ;
2020-12-15 20:45:21 -08:00
my $ blank = copy_spacing ( $ rawline );
my $ ptr = substr ( $ blank , 0 , $ - [ 1 ]) . "^" x length ( $ typo );
my $ hereptr = "$hereline$ptr\n" ;
2014-10-13 15:51:57 -07:00
my $ typo_fix = $ spelling_fix { lc ( $ typo )};
$ typo_fix = ucfirst ( $ typo_fix ) if ( $ typo =~ /^ [ A - Z ] / );
$ typo_fix = uc ( $ typo_fix ) if ( $ typo =~ /^ [ A - Z ] + $ / );
2017-09-08 16:16:07 -07:00
my $ msg_level = \& WARN ;
$ msg_level = \& CHK if ( $ file );
if ( & { $ msg_level }( "TYPO_SPELLING" ,
2020-12-15 20:45:21 -08:00
"'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $ hereptr ) &&
2014-10-13 15:51:57 -07:00
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/ ( ^ |[ ^ A - Za - z@ ])( $ typo )( $ |[ ^ A - Za - z@ ]) / $ 1 $ typo_fix$3/ ;
}
}
}
2019-09-25 16:46:38 -07:00
# check for invalid commit id
if ( $ in_commit_log && $ line =~ / ( ^ fixes :| \bcommit ) \s+ ([ 0 - 9 a - f ]{ 6 , 40 }) \b / i ) {
my $ id ;
my $ description ;
( $ id , $ description ) = git_commit_info ( $ 2 , undef , undef );
if (! defined ( $ id )) {
WARN ( "UNKNOWN_COMMIT_ID" ,
"Unknown commit id '$2', maybe rebased or not pulled?\n" . $ herecurr );
}
}
2020-10-15 20:11:52 -07:00
# check for repeated words separated by a single space
2020-12-15 20:44:24 -08:00
# avoid false positive from list command eg , '-rw-r--r-- 1 root root'
if (( $ rawline =~ /^\+/ || $ in_commit_log ) &&
$ rawline ! ~ / [ bcCdDlMnpPs\?- ][ rwxsStT- ]{ 9 } / ) {
2020-12-15 20:44:20 -08:00
pos ( $ rawline ) = 1 if (! $ in_commit_log );
2020-10-15 20:11:52 -07:00
while ( $ rawline =~ /\ b ( $ word_pattern ) ( ?= ( $ word_pattern )) / g ) {
my $ first = $ 1 ;
my $ second = $ 2 ;
2020-12-15 20:44:20 -08:00
my $ start_pos = $ - [ 1 ];
my $ end_pos = $ + [ 2 ];
2020-10-15 20:11:52 -07:00
if ( $ first =~ / ( ?:struct | union | enum ) / ) {
pos ( $ rawline ) += length ( $ first ) + length ( $ second ) + 1 ;
next ;
}
2020-12-15 20:44:20 -08:00
next if ( lc ( $ first ) ne lc ( $ second ));
2020-10-15 20:11:52 -07:00
next if ( $ first eq 'long' );
2020-12-15 20:44:20 -08:00
# check for character before and after the word matches
my $ start_char = '' ;
my $ end_char = '' ;
$ start_char = substr ( $ rawline , $ start_pos - 1 , 1 ) if ( $ start_pos > ( $ in_commit_log ? 0 : 1 ));
$ end_char = substr ( $ rawline , $ end_pos , 1 ) if ( $ end_pos < length ( $ rawline ));
next if ( $ start_char =~ /^\ S $ / );
next if ( index ( " \t.,;?!" , $ end_char ) == - 1 );
2021-02-25 17:21:47 -08:00
# avoid repeating hex occurrences like 'ff ff fe 09 ...'
if ( $ first =~ /\b [ 0 - 9 a - f ]{ 2 ,} \b / i ) {
next if (! exists ( $ allow_repeated_words { lc ( $ first )}));
}
2020-12-15 20:44:24 -08:00
2020-10-15 20:11:52 -07:00
if ( WARN ( "REPEATED_WORD" ,
"Possible repeated word: '$first'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\b$first $ second\b/ $ first/ ;
}
}
# if it's a repeated word on consecutive lines in a comment block
if ($prevline =~ /$;+\s*$/ &&
$prevrawline =~ /($word_pattern)\s*$/) {
my $last_word = $1;
if ($rawline =~ /^\+\s*\*\s*$last_word /) {
if (WARN("REPEATED_WORD",
"Possible repeated word: ' $ last_word'\n" . $hereprev) &&
$fix) {
$fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/;
}
}
}
}
2008-10-15 22:02:28 -07:00
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
2007-06-08 13:47:06 -07:00
2007-06-01 00:46:48 -07:00
#trailing whitespace
2007-10-16 23:29:38 -07:00
if ($line =~ /^\+.*\015/) {
2008-02-08 04:20:54 -08:00
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2013-09-11 14:23:54 -07:00
if (ERROR("DOS_LINE_ENDINGS",
"DOS line endings\n" . $herevet) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/[\s\015]+$//;
2013-09-11 14:23:54 -07:00
}
2008-02-08 04:20:54 -08:00
} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2013-07-03 15:05:31 -07:00
if (ERROR("TRAILING_WHITESPACE",
"trailing whitespace\n" . $herevet) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/\s+$//;
2013-07-03 15:05:31 -07:00
}
2010-10-26 14:23:12 -07:00
$rpt_cleaners = 1;
2007-06-01 00:46:48 -07:00
}
2008-10-15 22:02:27 -07:00
2013-11-12 15:10:12 -08:00
# Check for FSF mailing addresses.
2014-01-23 15:54:50 -08:00
if ($rawline =~ /\bwrite to the Free/i ||
2017-02-24 15:01:38 -08:00
$rawline =~ /\b675\s+Mass\s+Ave/i ||
2014-01-23 15:54:48 -08:00
$rawline =~ /\b59\s+Temple\s+Pl/i ||
$rawline =~ /\b51\s+Franklin\s+St/i) {
2013-11-12 15:10:12 -08:00
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2017-09-08 16:16:07 -07:00
my $msg_level = \&ERROR;
$msg_level = \&CHK if ($file);
&{$msg_level}("FSF_MAILING_ADDRESS",
"Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice . The FSF has changed addresses in the past , and may do so again . Linux already includes a copy of the GPL . \n " . $ herevet )
2013-11-12 15:10:12 -08:00
}
2010-05-24 14:33:29 -07:00
# check for Kconfig help text having a real description
2010-10-26 14:23:15 -07:00
# Only applies when adding the entry originally , after that we do not have
# sufficient context to determine whether it is indeed long enough .
2010-05-24 14:33:29 -07:00
if ( $ realfile =~ / Kconfig / &&
2018-02-16 21:22:54 +01:00
# 'choice' is usually the last thing on the line ( though
# Kconfig supports named choices ), so use a word boundary
# ( \b ) rather than a whitespace character ( \s )
$ line =~ /^\+\s* ( ?:config | menuconfig | choice ) \b/ ) {
2010-05-24 14:33:29 -07:00
my $ length = 0 ;
2010-10-26 14:23:15 -07:00
my $ cnt = $ realcnt ;
my $ ln = $ linenr + 1 ;
my $ f ;
2012-01-10 15:10:03 -08:00
my $ is_start = 0 ;
2010-10-26 14:23:15 -07:00
my $ is_end = 0 ;
2012-01-10 15:10:03 -08:00
for (; $ cnt > 0 && defined $ lines [ $ ln - 1 ]; $ ln++ ) {
2010-10-26 14:23:15 -07:00
$ f = $ lines [ $ ln - 1 ];
$ cnt-- if ( $ lines [ $ ln - 1 ] ! ~ /^-/ );
$ is_end = $ lines [ $ ln - 1 ] =~ /^\+/ ;
next if ( $ f =~ /^-/ );
2014-08-06 16:10:46 -07:00
last if (! $ file && $ f =~ /^\@\@/ );
2012-01-10 15:10:03 -08:00
2018-02-16 21:22:53 +01:00
if ( $ lines [ $ ln - 1 ] =~ /^\+\s* ( ?:bool | tristate | prompt ) \s * [ " ']/) {
2012-01-10 15:10:03 -08:00
$is_start = 1;
2020-06-17 12:02:20 +09:00
} elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
2012-01-10 15:10:03 -08:00
$length = -1;
}
2010-10-26 14:23:15 -07:00
$f =~ s/^.//;
2010-05-24 14:33:29 -07:00
$f =~ s/#.*//;
$f =~ s/^\s+//;
next if ($f =~ /^$/);
2018-02-16 21:22:54 +01:00
# This only checks context lines in the patch
# and so hopefully shouldn't trigger false
# positives , even though some of these are
# common words in help texts
if ( $ f =~ /^\s* ( ?:config | menuconfig | choice | endchoice |
if | endif | menu | endmenu | source ) \b / x ) {
2010-10-26 14:23:15 -07:00
$ is_end = 1 ;
last ;
}
2010-05-24 14:33:29 -07:00
$ length++ ;
}
2014-10-13 15:51:48 -07:00
if ( $ is_start && $ is_end && $ length < $ min_conf_desc_length ) {
WARN ( "CONFIG_DESCRIPTION" ,
"please write a paragraph that describes the config symbol fully\n" . $ herecurr );
}
2012-01-10 15:10:03 -08:00
#print "is_start<$is_start> is_end<$is_end> length<$length>\n" ;
2010-05-24 14:33:29 -07:00
}
2020-06-04 16:50:33 -07:00
# check MAINTAINERS entries
if ( $ realfile =~ /^ MAINTAINERS $ / ) {
# check MAINTAINERS entries for the right form
if ( $ rawline =~ /^\+ [ A - Z ] :/ &&
$ rawline ! ~ /^\+ [ A - Z ] :\t\ S / ) {
if ( WARN ( "MAINTAINERS_STYLE" ,
"MAINTAINERS entries use one tab after TYPE:\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/^ ( \+ [ A - Z ]) :\s*/ $ 1 :\t/ ;
}
}
# check MAINTAINERS entries for the right ordering too
my $ preferred_order = 'MRLSWQBCPTFXNK' ;
if ( $ rawline =~ /^\+ [ A - Z ] :/ &&
$ prevrawline =~ /^ [ \+ ][ A - Z ] :/ ) {
$ rawline =~ /^\+ ([ A - Z ]) :\s* (. * ) / ;
my $ cur = $ 1 ;
my $ curval = $ 2 ;
$ prevrawline =~ /^ [ \+ ]([ A - Z ]) :\s* (. * ) / ;
my $ prev = $ 1 ;
my $ prevval = $ 2 ;
my $ curindex = index ( $ preferred_order , $ cur );
my $ previndex = index ( $ preferred_order , $ prev );
if ( $ curindex < 0 ) {
WARN ( "MAINTAINERS_STYLE" ,
"Unknown MAINTAINERS entry type: '$cur'\n" . $ herecurr );
} else {
if ( $ previndex >= 0 && $ curindex < $ previndex ) {
WARN ( "MAINTAINERS_STYLE" ,
"Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n" . $ hereprev );
} elsif ((( $ prev eq 'F' && $ cur eq 'F' ) ||
( $ prev eq 'X' && $ cur eq 'X' )) &&
( $ prevval cmp $ curval ) > 0 ) {
WARN ( "MAINTAINERS_STYLE" ,
"Misordered MAINTAINERS entry - list file patterns in alphabetic order\n" . $ hereprev );
}
}
2017-07-10 15:52:07 -07:00
}
}
2011-08-15 01:07:14 -04:00
if (( $ realfile =~ / Makefile . */ || $ realfile =~ / Kbuild . */ ) &&
( $ line =~ /\+ ( EXTRA_ [ A - Z ] + FLAGS ). */ )) {
my $ flag = $ 1 ;
my $ replacement = {
'EXTRA_AFLAGS' => 'asflags-y' ,
'EXTRA_CFLAGS' => 'ccflags-y' ,
'EXTRA_CPPFLAGS' => 'cppflags-y' ,
'EXTRA_LDFLAGS' => 'ldflags-y' ,
};
WARN ( "DEPRECATED_VARIABLE" ,
" Use of $ flag is deprecated , please use \ `$ replacement-> { $ flag } instead . \n " . $ herecurr ) if ( $ replacement-> { $ flag });
}
2014-01-23 15:54:51 -08:00
# check for DT compatible documentation
2014-04-03 14:49:26 -07:00
if ( defined $ root &&
(( $ realfile =~ /\.dtsi? $ / && $ line =~ /^\+\s * compatible\s*=\s*\ " / ) ||
( $ realfile =~ /\. [ ch ] $ / && $ line =~ /^\+.*\.compatible\s*=\s*\ " / ))) {
2014-01-23 15:54:51 -08:00
my @compats = $ rawline =~ /\ " ([ a - zA - Z0 - 9 \-\ , \.\+ _ ] + ) \ "/g;
2014-04-03 14:49:27 -07:00
my $dt_path = $root . " / Documentation / devicetree / bindings/ ";
2019-05-22 09:55:34 -05:00
my $vp_file = $dt_path . " vendor - prefixes . yaml " ;
2014-04-03 14:49:27 -07:00
2014-01-23 15:54:51 -08:00
foreach my $ compat ( @compats ) {
my $ compat2 = $ compat ;
2014-06-04 16:12:03 -07:00
$ compat2 =~ s/\ ,[ a - zA - Z0 - 9 ] *\-/\ , <\.\*>\-/ ;
my $ compat3 = $ compat ;
$ compat3 =~ s/\ ,([ a - z ] * )[ 0 - 9 ] *\-/\ , $ 1 <\.\*>\-/ ;
` grep - Erq "$compat|$compat2|$compat3" $ dt_path ` ;
2014-01-23 15:54:51 -08:00
if ( $ ? >> 8 ) {
WARN ( "UNDOCUMENTED_DT_STRING" ,
"DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $ herecurr );
}
2014-04-03 14:49:25 -07:00
next if $ compat ! ~ /^ ([ a - zA - Z0 - 9 \- ] + ) \ , / ;
my $ vendor = $ 1 ;
2019-05-22 09:55:34 -05:00
` grep - Eq " \\ " \\^\ Q $ vendor\ E , \\.\\*\\ ":" $ vp_file ` ;
2014-01-23 15:54:51 -08:00
if ( $ ? >> 8 ) {
WARN ( "UNDOCUMENTED_DT_STRING" ,
2014-04-03 14:49:27 -07:00
"DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $ herecurr );
2014-01-23 15:54:51 -08:00
}
}
}
2018-04-10 16:33:13 -07:00
# check for using SPDX license tag at beginning of files
if ( $ realline == $ checklicenseline ) {
if ( $ rawline =~ /^ [ \+ ] \s*\#\ ! \s*\// ) {
$ checklicenseline = 2 ;
} elsif ( $ rawline =~ /^\+/ ) {
my $ comment = "" ;
if ( $ realfile =~ /\. ( h | s | S ) $ / ) {
$ comment = '/*' ;
} elsif ( $ realfile =~ /\. ( c | dts | dtsi ) $ / ) {
$ comment = '//' ;
2020-04-06 20:10:51 -07:00
} elsif (( $ checklicenseline == 2 ) || $ realfile =~ /\. ( sh | pl | py | awk | tc | yaml ) $ / ) {
2018-04-10 16:33:13 -07:00
$ comment = '#' ;
} elsif ( $ realfile =~ /\.rst$/ ) {
$ comment = '..' ;
}
2019-03-07 16:28:32 -08:00
# check SPDX comment style for .[ chsS ] files
if ( $ realfile =~ /\. [ chsS ] $ / &&
$ rawline =~ / SPDX - License - Identifier :/ &&
2019-09-25 16:46:35 -07:00
$ rawline ! ~ m@^\+\s*\ Q $ comment\ E \s*@ ) {
2019-03-07 16:28:32 -08:00
WARN ( "SPDX_LICENSE_TAG" ,
"Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $ herecurr );
}
2018-04-10 16:33:13 -07:00
if ( $ comment ! ~ /^ $ / &&
2019-09-25 16:46:35 -07:00
$ rawline ! ~ m@^\+\ Q $ comment\ E SPDX - License - Identifier : @ ) {
WARN ( "SPDX_LICENSE_TAG" ,
"Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $ herecurr );
2018-08-21 21:57:47 -07:00
} elsif ( $ rawline =~ / ( SPDX - License - Identifier : . * ) / ) {
2019-09-25 16:46:35 -07:00
my $ spdx_license = $ 1 ;
if (! is_SPDX_License_valid ( $ spdx_license )) {
WARN ( "SPDX_LICENSE_TAG" ,
"'$spdx_license' is not supported in LICENSES/...\n" . $ herecurr );
}
2020-04-06 20:11:13 -07:00
if ( $ realfile =~ m@^ Documentation / devicetree / bindings/@ &&
not $ spdx_license =~ / GPL - 2 \. 0. * BSD - 2 - Clause / ) {
my $ msg_level = \& WARN ;
$ msg_level = \& CHK if ( $ file );
if ( & { $ msg_level }( "SPDX_LICENSE_TAG" ,
"DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s / SPDX - License - Identifier : . */ SPDX - License - Identifier : ( GPL - 2.0 - only OR BSD - 2 - Clause ) / ;
}
}
2018-04-10 16:33:13 -07:00
}
}
}
2020-10-15 20:12:19 -07:00
# check for embedded filenames
if ( $ rawline =~ /^\+.*\ Q $ realfile\ E / ) {
WARN ( "EMBEDDED_FILENAME" ,
"It's generally not useful to have the filename in the file\n" . $ herecurr );
}
2008-10-15 22:02:27 -07:00
# check we are in a valid source file if not then ignore this hunk
2016-12-12 16:46:28 -08:00
next if ( $ realfile ! ~ /\. ( h | c | s | S | sh | dtsi | dts ) $ / );
2008-10-15 22:02:27 -07:00
2019-03-07 16:28:42 -08:00
# check for using SPDX - License - Identifier on the wrong line number
if ( $ realline ! = $ checklicenseline &&
$ rawline =~ /\bSPDX - License - Identifier :/ &&
substr ( $ line , @- , @+ - @- ) eq "$;" x ( @+ - @- )) {
WARN ( "SPDX_LICENSE_TAG" ,
"Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $ herecurr );
}
2015-06-25 15:02:57 -07:00
# line length limit ( with some exclusions )
#
# There are a few types of lines that may extend beyond $ max_line_length:
# logging functions like pr_info that end in a string
# lines with a single string
# #defines that are a single string
2018-02-06 15:38:45 -08:00
# lines with an RFC3986 like URL
2015-06-25 15:02:57 -07:00
#
# There are 3 different line length message types :
2017-09-08 16:16:04 -07:00
# LONG_LINE_COMMENT a comment starts before but extends beyond $ max_line_length
2015-06-25 15:02:57 -07:00
# LONG_LINE_STRING a string starts before but extends beyond $ max_line_length
# LONG_LINE all other lines longer than $ max_line_length
#
# if LONG_LINE is ignored , the other 2 types are also ignored
#
2015-07-17 16:24:01 -07:00
if ( $ line =~ /^\+/ && $ length > $ max_line_length ) {
2015-06-25 15:02:57 -07:00
my $ msg_type = "LONG_LINE" ;
# Check the allowed long line types first
# logging functions that end in a string that starts
# before $ max_line_length
if ( $ line =~ /^\+\s* $ logFunctions\s*\ ( \s* ( ?: ( ?: KERN_ \ S +\s* |[ ^ " ] * )) ? ( $ String \s* ( ?: |,| \ ) \s* ;) \s* ) $ / &&
length ( expand_tabs ( substr ( $ line , 1 , length ( $ line ) - length ( $ 1 ) - 1 ))) <= $ max_line_length ) {
$ msg_type = "" ;
# lines with only strings ( w / possible termination )
# #defines with only strings
} elsif ( $ line =~ /^\+\s* $ String \s* ( ?:\s* |,| \ ) \s* ;) \s* $ / ||
$ line =~ /^\+\s*#\s * define\s+\w+\s+ $ String $ / ) {
$ msg_type = "" ;
2017-11-17 15:28:44 -08:00
# More special cases
} elsif ( $ line =~ /^\+.*\bEFI_GUID\s*\ ( / ||
$ line =~ /^\+\s* ( ?:\w+ ) ?\s * DEFINE_PER_CPU / ) {
2016-08-02 14:04:31 -07:00
$ msg_type = "" ;
2018-02-06 15:38:45 -08:00
# URL ( $ rawline is used in case the URL is in a comment )
} elsif ( $ rawline =~ /^\+.*\b [ a - z ][ \w\.\+\- ] *:\/\/\ S +/i ) {
$ msg_type = "" ;
2015-06-25 15:02:57 -07:00
# Otherwise set the alternate message types
# a comment starts before $ max_line_length
} elsif ( $ line =~ / ( $ ;[ \s$ ;] * ) $ / &&
length ( expand_tabs ( substr ( $ line , 1 , length ( $ line ) - length ( $ 1 ) - 1 ))) <= $ max_line_length ) {
$ msg_type = "LONG_LINE_COMMENT"
# a quoted string starts before $ max_line_length
} elsif ( $ sline =~ /\s* ( $ String ( ?:\s* ( ?:\\ |, \s* | \ ) \s* ; \s* )) ? ) $ / &&
length ( expand_tabs ( substr ( $ line , 1 , length ( $ line ) - length ( $ 1 ) - 1 ))) <= $ max_line_length ) {
$ msg_type = "LONG_LINE_STRING"
}
if ( $ msg_type ne "" &&
( show_type ( "LONG_LINE" ) || show_type ( $ msg_type ))) {
2020-05-29 16:12:21 -07:00
my $ msg_level = \& WARN ;
$ msg_level = \& CHK if ( $ file );
& { $ msg_level }( $ msg_type ,
"line length of $length exceeds $max_line_length columns\n" . $ herecurr );
2015-06-25 15:02:57 -07:00
}
2007-06-01 00:46:48 -07:00
}
2007-11-28 16:21:06 -08:00
# check for adding lines without a newline .
if ( $ line =~ /^\+/ && defined $ lines [ $ linenr ] && $ lines [ $ linenr ] =~ /^\\ No newline at end of file/ ) {
2020-12-15 20:44:40 -08:00
if ( WARN ( "MISSING_EOF_NEWLINE" ,
"adding a line without newline at end of file\n" . $ herecurr ) &&
$ fix ) {
fix_delete_line ( $ fixlinenr + 1 , "No newline at end of file" );
}
2007-11-28 16:21:06 -08:00
}
2021-02-25 17:21:57 -08:00
# check for . L prefix local symbols in . S files
if ( $ realfile =~ /\. S $ / &&
$ line =~ /^\+\s* ( ?: [ A - Z ] + _ ) ? SYM_ [ A - Z ] + _ ( ?: START | END )( ?: _ [ A - Z_ ] + ) ?\s*\ ( \s*\. L / ) {
WARN ( "AVOID_L_PREFIX" ,
"Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/asm-annotations.rst\n" . $ herecurr );
}
2008-10-15 22:02:24 -07:00
# check we are in a valid source file C or perl if not then ignore this hunk
2014-10-13 15:51:46 -07:00
next if ( $ realfile ! ~ /\. ( h | c | pl | dtsi | dts ) $ / );
2007-06-01 00:46:48 -07:00
# at the beginning of a line any tabs must come first and anything
2020-04-06 20:11:07 -07:00
# more than $ tabsize must use tabs .
2008-02-08 04:20:54 -08:00
if ( $ rawline =~ /^\+\s * \t\s*\ S / ||
$ rawline =~ /^\+\s * \s*/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2010-10-26 14:23:12 -07:00
$ rpt_cleaners = 1 ;
2013-07-03 15:05:31 -07:00
if ( ERROR ( "CODE_INDENT" ,
"code indent should use tabs where possible\n" . $ herevet ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/^\+ ([ \t ] + ) / " \+ " . tabify ( $ 1 ) / e ;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2010-03-05 13:43:54 -08:00
# check for space before tabs .
if ( $ rawline =~ /^\+/ && $ rawline =~ / \t/ ) {
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2013-07-03 15:05:31 -07:00
if ( WARN ( "SPACE_BEFORE_TAB" ,
"please, no space before tabs\n" . $ herevet ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
while ( $ fixed [ $ fixlinenr ] =~
2020-04-06 20:11:07 -07:00
s/ ( ^\+.* ) { $ tabsize , $ tabsize } \t/ $ 1 \t\t/ ) {}
2014-08-06 16:11:03 -07:00
while ( $ fixed [ $ fixlinenr ] =~
2014-01-23 15:54:46 -08:00
s/ ( ^\+.* ) +\t/ $ 1 \t/ ) {}
2013-07-03 15:05:31 -07:00
}
2010-03-05 13:43:54 -08:00
}
2018-04-10 16:34:04 -07:00
# check for assignments on the start of a line
if ( $ sline =~ /^\+\s+ ( $ Assignment )[ ^= ] / ) {
2020-12-15 20:45:06 -08:00
my $ operator = $ 1 ;
if ( CHK ( "ASSIGNMENT_CONTINUATIONS" ,
"Assignment operator '$1' should be on the previous line\n" . $ hereprev ) &&
$ fix && $ prevrawline =~ /^\+/ ) {
# add assignment operator to the previous line , remove from current line
$ fixed [ $ fixlinenr - 1 ] . = " $operator" ;
$ fixed [ $ fixlinenr ] =~ s/\ Q $ operator\ E \s*// ;
}
2018-04-10 16:34:04 -07:00
}
2010-03-05 13:43:54 -08:00
2012-03-23 15:02:16 -07:00
# check for && or || at the start of a line
if ( $ rawline =~ /^\+\s* ( && | \ | \ |) / ) {
2020-12-15 20:45:09 -08:00
my $ operator = $ 1 ;
if ( CHK ( "LOGICAL_CONTINUATIONS" ,
"Logical continuations should be on the previous line\n" . $ hereprev ) &&
$ fix && $ prevrawline =~ /^\+/ ) {
# insert logical operator at last non - comment , non - whitepsace char on previous line
$ prevline =~ / [ \s$ ;] * $ / ;
my $ line_end = substr ( $ prevrawline , $ - [ 0 ]);
$ fixed [ $ fixlinenr - 1 ] =~ s/\ Q $ line_end\ E $ / $ operator$line_end/ ;
$ fixed [ $ fixlinenr ] =~ s/\ Q $ operator\ E \s*// ;
}
2012-03-23 15:02:16 -07:00
}
2016-05-20 17:04:05 -07:00
# check indentation starts on a tab stop
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2018-02-06 15:39:06 -08:00
$ sline =~ /^\+\t+ ( + )( ?: $ c90_Keywords\b | \ { \s* $ | \ } \s* ( ?:else\b | while\b | \s* $ )| $ Declare \s* $ Ident \s * [; = ]) / ) {
2016-05-20 17:04:05 -07:00
my $ indent = length ( $ 1 );
2020-04-06 20:11:07 -07:00
if ( $ indent % $tabsize) {
2016-05-20 17:04:05 -07:00
if ( WARN ( "TABSTOP" ,
"Statements should start on a tabstop\n" . $ herecurr ) &&
$ fix ) {
2020-04-06 20:11:07 -07:00
$ fixed [ $ fixlinenr ] =~ s@ ( ^\+\t+ ) +@ $ 1 . "\t" x ( $ indent/ $ tabsize ) @e ;
2016-05-20 17:04:05 -07:00
}
}
}
2012-03-23 15:02:16 -07:00
# check multi - line statement indentation matches previous line
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2017-07-10 15:52:30 -07:00
$ prevline =~ /^\+ ([ \t ] * )(( ?: $ c90_Keywords ( ?:\s + if ) \s* )|( ?: $ Declare \s* ) ? ( ?: $ Ident | \ ( \s*\*\s* $ Ident \s*\ )) \s* |( ?:\*\s* ) * $ Lval \s*=\s* $ Ident \s* ) \ (. * ( \&\& | \ | \ ||,) \s* $ / ) {
2012-03-23 15:02:16 -07:00
$ prevline =~ /^\+ ( \t* )(. * ) $ / ;
my $ oldindent = $ 1 ;
my $ rest = $ 2 ;
my $ pos = pos_last_openparen ( $ rest );
if ( $ pos >= 0 ) {
2012-07-30 14:41:16 -07:00
$ line =~ /^ ( \+ | )([ \t ] * ) / ;
my $ newindent = $ 2 ;
2012-03-23 15:02:16 -07:00
my $ goodtabindent = $ oldindent .
2020-04-06 20:11:07 -07:00
"\t" x ( $ pos / $ tabsize ) .
" " x ( $ pos % $tabsize);
2012-03-23 15:02:16 -07:00
my $ goodspaceindent = $ oldindent . " " x $ pos ;
if ( $ newindent ne $ goodtabindent &&
$ newindent ne $ goodspaceindent ) {
2013-07-03 15:05:31 -07:00
if ( CHK ( "PARENTHESIS_ALIGNMENT" ,
"Alignment should match open parenthesis\n" . $ hereprev ) &&
$ fix && $ line =~ /^\+/ ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/^\+ [ \t ] */\+ $ goodtabindent/ ;
}
2012-03-23 15:02:16 -07:00
}
}
}
2015-04-16 12:44:05 -07:00
# check for space after cast like "(int) foo" or "(struct foo) bar"
# avoid checking a few false positives :
# "sizeof(<type>)" or "__alignof__(<type>)"
# function pointer declarations like "(*foo)(int) = bar;"
# structure definitions like "(struct foo) { 0 };"
# multiline macros that define functions
# known attributes or the __ attribute__ keyword
if ( $ line =~ /^\+ (. * ) \ ( \s* $ Type \s*\ )([ \t ] ++ )(( ? ![ = {]| \\ $ | $ Attribute | __ attribute__ )) / &&
(! defined ( $ 1 ) || $ 1 ! ~ /\ b ( ?:sizeof | __ alignof__ ) \s* $ / )) {
2013-07-03 15:05:31 -07:00
if ( CHK ( "SPACING" ,
2014-08-06 16:10:52 -07:00
"No space is necessary after a cast\n" . $ herecurr ) &&
2013-07-03 15:05:31 -07:00
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2014-08-06 16:10:52 -07:00
s/ ( \ ( \s* $ Type \s*\ ))[ \t ] +/ $ 1 / ;
2013-07-03 15:05:31 -07:00
}
2012-03-23 15:02:19 -07:00
}
2015-09-09 15:37:41 -07:00
# Block comment styles
# Networking with an initial /*
2012-10-04 17:13:35 -07:00
if ($realfile =~ m@^(drivers/net/|net/)@ &&
2013-07-03 15:05:23 -07:00
$prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
2014-04-03 14:49:20 -07:00
$rawline =~ /^\+[ \t]*\*/ &&
2020-10-15 20:12:25 -07:00
$ realline > 3 ) { # Do not warn about the initial copyright comment block after SPDX - License - Identifier
2012-10-04 17:13:35 -07:00
WARN ( "NETWORKING_BLOCK_COMMENT_STYLE" ,
"networking block comments don't use an empty /* line, use /* Comment...\n" . $ hereprev );
}
2015-09-09 15:37:41 -07:00
# Block comments use * on subsequent lines
if ( $ prevline =~ / $ ;[ \t ] * $ / && #ends in comment
$ prevrawline =~ /^\+.*?\/\*/ && #starting /*
2013-07-03 15:05:24 -07:00
$prevrawline !~ /\*\/[ \t]*$/ && #no trailing */
2013-09-11 14:23:59 -07:00
$ rawline =~ /^\+/ && #line is new
2013-07-03 15:05:24 -07:00
$ rawline ! ~ /^\+ [ \t ] *\*/ ) { #no leading *
2015-09-09 15:37:41 -07:00
WARN ( "BLOCK_COMMENT_STYLE" ,
"Block comments use * on subsequent lines\n" . $ hereprev );
2013-07-03 15:05:24 -07:00
}
2015-09-09 15:37:41 -07:00
# Block comments use */ on trailing lines
if ( $ rawline ! ~ m@^\+ [ \t ] *\*/ [ \t ] * $ @ && #trailing */
2012-11-08 15:53:29 -08:00
$ rawline ! ~ m@^\+.*/\*.*\*/ [ \t ] * $ @ && #inline /*...*/
$ rawline ! ~ m@^\+.*\* { 2 ,} / [ \t ] * $ @ && #trailing **/
$ rawline =~ m@^\+ [ \t ] *.+\*\/ [ \t ] * $ @ ) { #non blank */
2015-09-09 15:37:41 -07:00
WARN ( "BLOCK_COMMENT_STYLE" ,
"Block comments use a trailing */ on a separate line\n" . $ herecurr );
2012-10-04 17:13:35 -07:00
}
2016-10-11 13:51:50 -07:00
# Block comment * alignment
if ( $ prevline =~ / $ ;[ \t ] * $ / && #ends in comment
2016-10-11 13:52:05 -07:00
$ line =~ /^\+ [ \t ] * $ ; / && #leading comment
$ rawline =~ /^\+ [ \t ] *\*/ && #leading *
(( $ prevrawline =~ /^\+.*?\/\*/ && #leading /*
2016-10-11 13:51:50 -07:00
$prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
2016-10-11 13:52:05 -07:00
$ prevrawline =~ /^\+ [ \t ] *\*/ )) { #leading *
my $ oldindent ;
2016-10-11 13:51:50 -07:00
$ prevrawline =~ m@^\+ ([ \t ] */? ) \*@ ;
2016-10-11 13:52:05 -07:00
if ( defined ( $ 1 )) {
$ oldindent = expand_tabs ( $ 1 );
} else {
$ prevrawline =~ m@^\+ (. */? ) \*@ ;
$ oldindent = expand_tabs ( $ 1 );
}
2016-10-11 13:51:50 -07:00
$ rawline =~ m@^\+ ([ \t ] * ) \*@ ;
my $ newindent = $ 1 ;
$ newindent = expand_tabs ( $ newindent );
2016-10-11 13:52:05 -07:00
if ( length ( $ oldindent ) ne length ( $ newindent )) {
2016-10-11 13:51:50 -07:00
WARN ( "BLOCK_COMMENT_STYLE" ,
"Block comments should align the * on each line\n" . $ hereprev );
}
}
2014-08-06 16:10:39 -07:00
# check for missing blank lines after struct / union declarations
# with exceptions for various attributes and macros
if ( $ prevline =~ /^ [ \+ ]}; ?\s* $ / &&
$ line =~ /^\+/ &&
!( $ line =~ /^\+\s* $ / ||
$ line =~ /^\+\s * EXPORT_SYMBOL / ||
$ line =~ /^\+\s * MODULE_ / i ||
$ line =~ /^\+\s*\#\s* ( ?:end | elif | else ) / ||
$ line =~ /^\+ [ a - z_ ] * init / ||
$ line =~ /^\+\s* ( ?:static\s+ ) ? [ A - Z_ ] * ATTR / ||
$ line =~ /^\+\s * DECLARE / ||
2017-11-17 15:28:55 -08:00
$ line =~ /^\+\s * builtin_ [ \w_ ] * driver / ||
2014-08-06 16:10:39 -07:00
$ line =~ /^\+\s* __ setup/ )) {
2014-08-06 16:11:05 -07:00
if ( CHK ( "LINE_SPACING" ,
"Please use a blank line after function/struct/union/enum declarations\n" . $ hereprev ) &&
$ fix ) {
2014-08-06 16:11:07 -07:00
fix_insert_line ( $ fixlinenr , " \+ " );
2014-08-06 16:11:05 -07:00
}
2014-08-06 16:10:39 -07:00
}
2014-08-06 16:10:42 -07:00
# check for multiple consecutive blank lines
if ( $ prevline =~ /^ [ \+ ] \s* $ / &&
$ line =~ /^\+\s* $ / &&
$ last_blank_line ! = ( $ linenr - 1 )) {
2014-08-06 16:11:05 -07:00
if ( CHK ( "LINE_SPACING" ,
"Please don't use multiple blank lines\n" . $ hereprev ) &&
$ fix ) {
2014-08-06 16:11:07 -07:00
fix_delete_line ( $ fixlinenr , $ rawline );
2014-08-06 16:11:05 -07:00
}
2014-08-06 16:10:42 -07:00
$ last_blank_line = $ linenr ;
}
2014-04-03 14:49:28 -07:00
# check for missing blank lines after declarations
2021-02-25 17:21:40 -08:00
# ( declarations must have the same indentation and not be at the start of line )
if (( $ prevline =~ /\+ ( \s+ ) \ S / ) && $ sline =~ /^\+ $ 1 \ S / ) {
# use temporaries
my $ sl = $ sline ;
my $ pl = $ prevline ;
# remove $ Attribute / $ Sparse uses to simplify comparisons
$ sl =~ s/\ b ( ?: $ Attribute | $ Sparse ) \b // g ;
$ pl =~ s/\ b ( ?: $ Attribute | $ Sparse ) \b // g ;
if (( $ pl =~ /^\+\s+ $ Declare \s* $ Ident \s * [ = ,; :\ [] / ||
2014-08-06 16:10:33 -07:00
# function pointer declarations
2021-02-25 17:21:40 -08:00
$ pl =~ /^\+\s+ $ Declare \s*\ ( \s*\*\s* $ Ident \s*\ ) \s * [ = ,; :\ [ \ (] / ||
2014-06-04 16:12:04 -07:00
# foo bar ; where foo is some local typedef or #define
2021-02-25 17:21:40 -08:00
$ pl =~ /^\+\s+ $ Ident ( ?:\s+ | \s*\*\s* ) $ Ident \s * [ = ,; \ [] / ||
2014-06-04 16:12:04 -07:00
# known declaration macros
2021-02-25 17:21:40 -08:00
$ pl =~ /^\+\s+ $ declaration_macros/ ) &&
2014-06-04 16:12:04 -07:00
# for "else if" which can look like "$Ident $Ident"
2021-02-25 17:21:40 -08:00
!( $ pl =~ /^\+\s+ $ c90_Keywords\b / ||
2014-06-04 16:12:04 -07:00
# other possible extensions of declaration lines
2021-02-25 17:21:40 -08:00
$ pl =~ / ( ?: $ Compare | $ Assignment | $ Operators ) \s* $ / ||
2014-06-04 16:12:04 -07:00
# not starting a section or a macro " \ " extended line
2021-02-25 17:21:40 -08:00
$ pl =~ / ( ?:\ { \s* | \\ ) $ / ) &&
2014-06-04 16:12:04 -07:00
# looks like a declaration
2021-02-25 17:21:40 -08:00
!( $ sl =~ /^\+\s+ $ Declare \s* $ Ident \s * [ = ,; :\ [] / ||
2014-08-06 16:10:33 -07:00
# function pointer declarations
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+ $ Declare \s*\ ( \s*\*\s* $ Ident \s*\ ) \s * [ = ,; :\ [ \ (] / ||
2014-06-04 16:12:04 -07:00
# foo bar ; where foo is some local typedef or #define
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+ $ Ident ( ?:\s+ | \s*\*\s* ) $ Ident \s * [ = ,; \ [] / ||
2014-06-04 16:12:04 -07:00
# known declaration macros
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+ $ declaration_macros / ||
2014-06-04 16:12:04 -07:00
# start of struct or union or enum
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+ ( ?:static\s+ ) ? ( ?:const\s+ ) ? ( ?:union | struct | enum | typedef ) \b / ||
2014-06-04 16:12:04 -07:00
# start or end of block or continuation of declaration
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+ ( ?: $ |[ \ { \ } \.\#\ " \?\:\ ( \ []) / ||
2014-06-04 16:12:04 -07:00
# bitfield continuation
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+ $ Ident \s*:\s*\d+\s * [,;] / ||
2014-06-04 16:12:04 -07:00
# other possible extensions of declaration lines
2021-02-25 17:21:40 -08:00
$ sl =~ /^\+\s+\ ( ?\s* ( ?: $ Compare | $ Assignment | $ Operators ) / )) {
if ( WARN ( "LINE_SPACING" ,
"Missing a blank line after declarations\n" . $ hereprev ) &&
$ fix ) {
fix_insert_line ( $ fixlinenr , " \+ " );
}
2014-08-06 16:11:05 -07:00
}
2014-04-03 14:49:28 -07:00
}
2010-08-09 17:20:59 -07:00
# check for spaces at the beginning of a line .
2010-10-26 14:23:11 -07:00
# Exceptions :
# 1 ) within comments
# 2 ) indented preprocessor commands
# 3 ) hanging labels
2013-07-03 15:05:31 -07:00
if ( $ rawline =~ /^\+ / && $ line ! ~ /^\+ * ( ?: $ ;| # | $ Ident : ) / ) {
2010-08-09 17:20:59 -07:00
my $ herevet = "$here\n" . cat_vet ( $ rawline ) . "\n" ;
2013-07-03 15:05:31 -07:00
if ( WARN ( "LEADING_SPACE" ,
"please, no spaces at the start of a line\n" . $ herevet ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/^\+ ([ \t ] + ) / " \+ " . tabify ( $ 1 ) / e ;
2013-07-03 15:05:31 -07:00
}
2010-08-09 17:20:59 -07:00
}
2008-10-15 22:02:24 -07:00
# check we are in a valid C source file if not then ignore this hunk
next if ( $ realfile ! ~ /\. ( h | c ) $ / );
2017-11-17 15:28:52 -08:00
# check for unusual line ending [ or (
if ( $ line =~ /^\+.* ([ \ [ \ (]) \s* $ / ) {
CHK ( "OPEN_ENDED_LINE" ,
"Lines should not end with a '$1'\n" . $ herecurr );
}
2017-05-08 15:55:39 -07:00
# check if this appears to be the start function declaration , save the name
if ( $ sline =~ /^\+\ { \s* $ / &&
$ prevline =~ /^\+ ( ?: ( ?: ( ?: $ Storage | $ Inline ) \s* ) *\s* $ Type \s* ) ? ( $ Ident ) \ ( / ) {
$ context_function = $ 1 ;
}
# check if this appears to be the end of function declaration
if ( $ sline =~ /^\+\ } \s* $ / ) {
undef $ context_function ;
}
2014-08-06 16:10:29 -07:00
# check indentation of any line with a bare else
2014-10-13 15:51:59 -07:00
# ( but not if it is a multiple line "if (foo) return bar; else return baz;" )
2014-08-06 16:10:29 -07:00
# if the previous line is a break or return and is indented 1 tab more ...
if ( $ sline =~ /^\+ ([ \t ] + )( ?: }[ \t ] * ) ? else ( ?: [ \t ] * {) ?\s* $ / ) {
my $ tabs = length ( $ 1 ) + 1 ;
2014-10-13 15:51:59 -07:00
if ( $ prevline =~ /^\+\t { $ tabs , $ tabs } break\b / ||
( $ prevline =~ /^\+\t { $ tabs , $ tabs } return\b / &&
defined $ lines [ $ linenr ] &&
$ lines [ $ linenr ] ! ~ /^ [ \+ ] \t { $ tabs , $ tabs } return/ )) {
2014-08-06 16:10:29 -07:00
WARN ( "UNNECESSARY_ELSE" ,
"else is not generally useful after a break or return\n" . $ hereprev );
}
}
2014-08-06 16:11:01 -07:00
# check indentation of a line with a break ;
2020-12-15 20:44:33 -08:00
# if the previous line is a goto , return or break
# and is indented the same # of tabs
2014-08-06 16:11:01 -07:00
if ( $ sline =~ /^\+ ([ \t ] + ) break\s* ; \s* $ / ) {
my $ tabs = $ 1 ;
2020-12-15 20:44:33 -08:00
if ( $ prevline =~ /^\+ $ tabs ( goto | return | break ) \b/ ) {
if ( WARN ( "UNNECESSARY_BREAK" ,
"break is not useful after a $1\n" . $ hereprev ) &&
$ fix ) {
fix_delete_line ( $ fixlinenr , $ rawline );
}
2014-08-06 16:11:01 -07:00
}
}
2008-02-08 04:20:54 -08:00
# check for RCS / CVS revision markers
2008-03-04 14:28:20 -08:00
if ( $ rawline =~ /^\+.*\ $ ( Revision | Log | Id )( ?:\ $ |) / ) {
2011-07-25 17:13:25 -07:00
WARN ( "CVS_KEYWORD" ,
"CVS style keyword markers, these will _not_ be updated\n" . $ herecurr );
2008-02-08 04:20:54 -08:00
}
2007-08-10 13:01:03 -07:00
2013-02-21 16:44:14 -08:00
# check for old HOTPLUG __ dev < foo > section markings
if ( $ line =~ /\ b ( __ dev ( init | exit )( data | const |)) \b/ ) {
WARN ( "HOTPLUG_SECTION" ,
"Using $1 is unnecessary\n" . $ herecurr );
}
2007-10-16 23:29:38 -07:00
# Check for potential 'bare' types
2009-10-26 16:50:16 -07:00
my ( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ,
$ realline_next );
2012-01-10 15:10:01 -08:00
#print "LINE<$line>\n" ;
2017-07-10 15:52:13 -07:00
if ( $ linenr > $ suppress_statement &&
2013-09-11 14:24:03 -07:00
$ realcnt && $ sline =~ /.\s*\ S / ) {
2008-10-15 22:02:30 -07:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
2008-07-23 21:29:03 -07:00
ctx_statement_block ( $ linenr , $ realcnt , 0 );
2008-04-29 00:59:32 -07:00
$ stat =~ s/\n . /\n / g ;
$ cond =~ s/\n . /\n / g ;
2012-01-10 15:10:01 -08:00
#print "linenr<$linenr> <$stat>\n" ;
# If this statement has no statement boundaries within
# it there is no point in retrying a statement scan
# until we hit end of it .
my $ frag = $ stat ; $ frag =~ s/ ; +\s* $ // ;
if ( $ frag ! ~ / ( ?: {|;) / ) {
#print "skip<$line_nr_next>\n" ;
$ suppress_statement = $ line_nr_next ;
}
2012-01-10 15:09:54 -08:00
2009-10-26 16:50:16 -07:00
# Find the real next line .
$ realline_next = $ line_nr_next ;
if ( defined $ realline_next &&
(! defined $ lines [ $ realline_next - 1 ] ||
substr ( $ lines [ $ realline_next - 1 ], $ off_next ) =~ /^\s* $ / )) {
$ realline_next++ ;
}
2008-04-29 00:59:32 -07:00
my $ s = $ stat ;
$ s =~ s/ {. * $ // s ;
2008-03-04 14:28:20 -08:00
2008-02-08 04:20:54 -08:00
# Ignore goto labels .
2008-04-29 00:59:32 -07:00
if ( $ s =~ / $ Ident :\* $ / s ) {
2008-02-08 04:20:54 -08:00
# Ignore functions being called
2008-04-29 00:59:32 -07:00
} elsif ( $ s =~ /^.\s* $ Ident \s*\ ( / s ) {
2008-02-08 04:20:54 -08:00
2009-09-21 17:04:34 -07:00
} elsif ( $ s =~ /^.\s * else\b / s ) {
2008-06-05 22:46:01 -07:00
# declarations always start with types
2008-07-23 21:29:09 -07:00
} elsif ( $ prev_values eq 'E' && $ s =~ /^.\s* ( ?: $ Storage \s+ ) ? ( ?: $ Inline \s+ ) ? ( ?:const\s+ ) ? (( ?:\s* $ Ident ) +? ) \ b ( ?:\s+ $ Sparse ) ?\s*\**\s* ( ?: $ Ident | \ ( \* [ ^\ )] *\ ))( ?:\s* $ Modifier ) ?\s* ( ?: ;| = |,| \ () / s ) {
2008-06-05 22:46:01 -07:00
my $ type = $ 1 ;
$ type =~ s/\s+/ / g ;
possible ( $ type , "A:" . $ s );
2007-11-28 16:21:06 -08:00
# definitions in global scope can only start with types
2008-10-15 22:02:30 -07:00
} elsif ( $ s =~ /^. ( ?: $ Storage \s+ ) ? ( ?: $ Inline \s+ ) ? ( ?:const\s+ ) ? ( $ Ident ) \b\s* ( ? ! : ) / s ) {
2008-06-05 22:46:01 -07:00
possible ( $ 1 , "B:" . $ s );
2008-02-08 04:20:54 -08:00
}
2007-11-28 16:21:06 -08:00
# any ( foo ... * ) is a pointer cast , and foo is a type
2009-01-06 14:41:21 -08:00
while ( $ s =~ /\ (( $ Ident )( ?:\s+ $ Sparse ) * [ \s\* ] +\s*\ ) / sg ) {
2008-06-05 22:46:01 -07:00
possible ( $ 1 , "C:" . $ s );
2007-10-16 23:29:38 -07:00
}
2007-11-28 16:21:06 -08:00
# Check for any sort of function declaration .
# int foo ( something bar , other baz );
# void ( * store_gdt )( x86_descr_ptr * );
2008-04-29 00:59:32 -07:00
if ( $ prev_values eq 'E' && $ s =~ /^ (.( ?:typedef\s* ) ? ( ?: ( ?: $ Storage | $ Inline ) \s* ) *\s* $ Type \s* ( ?:\b$Ident | \ ( \*\s* $ Ident \ )) \s* ) \ ( / s ) {
2007-11-28 16:21:06 -08:00
my ( $ name_len ) = length ( $ 1 );
2008-03-04 14:28:20 -08:00
my $ ctx = $ s ;
2008-03-28 14:15:58 -07:00
substr ( $ ctx , 0 , $ name_len + 1 , '' );
2007-11-28 16:21:06 -08:00
$ ctx =~ s/\ )[ ^\ )] * $ // ;
2008-03-04 14:28:20 -08:00
2007-11-28 16:21:06 -08:00
for my $ arg ( split ( /\s* , \s*/ , $ ctx )) {
2008-06-05 22:46:01 -07:00
if ( $ arg =~ /^ ( ?:const\s+ ) ? ( $ Ident )( ?:\s+ $ Sparse ) *\s*\**\s* ( :?\b$Ident ) ? $ / s || $ arg =~ /^ ( $ Ident ) $ / s ) {
2007-11-28 16:21:06 -08:00
2008-06-05 22:46:01 -07:00
possible ( $ 1 , "D:" . $ s );
2007-11-28 16:21:06 -08:00
}
}
}
2007-10-16 23:29:38 -07:00
}
2007-06-23 17:16:34 -07:00
#
# Checks which may be anchored in the context .
#
# Check for switch () and associated case and default
# statements should be at the same indent .
2007-06-08 13:47:06 -07:00
if ( $ line=~/\bswitch\s*\ (. *\ ) / ) {
my $ err = '' ;
my $ sep = '' ;
my @ctx = ctx_block_outer ( $ linenr , $ realcnt );
shift ( @ctx );
for my $ ctx ( @ctx ) {
my ( $ clen , $ cindent ) = line_stats ( $ ctx );
if ( $ ctx =~ /^\+\s* ( case\s+ | default :) / &&
$ indent ! = $ cindent ) {
$ err . = "$sep$ctx\n" ;
$ sep = '' ;
} else {
$ sep = "[...]\n" ;
}
}
if ( $ err ne '' ) {
2011-07-25 17:13:25 -07:00
ERROR ( "SWITCH_CASE_INDENT_LEVEL" ,
"switch and case should be at the same indent\n$hereline$err" );
2007-07-15 23:37:22 -07:00
}
}
# if / while / etc brace do not go on next line , unless defining a do while loop ,
# or if that brace on the next line is for something else
2014-08-06 16:11:16 -07:00
if ( $ line =~ / (. * ) \ b (( ?:if | while | for | switch |( ?: [ a - z_ ] + |) for_each [ a - z_ ] + ) \s*\ (| do\b | else\b ) / && $ line ! ~ /^.\s*\#/ ) {
2008-03-28 14:15:58 -07:00
my $ pre_ctx = "$1$2" ;
2007-10-16 23:29:38 -07:00
my ( $ level , @ctx ) = ctx_statement_level ( $ linenr , $ realcnt , 0 );
2012-02-03 15:20:39 -08:00
if ( $ line =~ /^\+\t { 6 ,} / ) {
WARN ( "DEEP_INDENTATION" ,
"Too many leading tabs - consider code refactoring\n" . $ herecurr );
}
2007-07-15 23:37:22 -07:00
my $ ctx_cnt = $ realcnt - $ #ctx - 1 ;
my $ ctx = join ( "\n" , @ctx );
2008-07-23 21:29:01 -07:00
my $ ctx_ln = $ linenr ;
my $ ctx_skip = $ realcnt ;
2007-07-15 23:37:22 -07:00
2008-07-23 21:29:01 -07:00
while ( $ ctx_skip > $ ctx_cnt || ( $ ctx_skip == $ ctx_cnt &&
defined $ lines [ $ ctx_ln - 1 ] &&
$ lines [ $ ctx_ln - 1 ] =~ /^-/ )) {
##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n" ;
$ ctx_skip-- if (! defined $ lines [ $ ctx_ln - 1 ] || $ lines [ $ ctx_ln - 1 ] ! ~ /^-/ );
2008-03-28 14:15:58 -07:00
$ ctx_ln++ ;
}
2008-07-23 21:29:01 -07:00
2008-07-23 21:29:03 -07:00
#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n" ;
#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n" ;
2008-03-28 14:15:58 -07:00
2014-08-06 16:11:05 -07:00
if ( $ ctx ! ~ / { \s*/ && defined ( $ lines [ $ ctx_ln - 1 ]) && $ lines [ $ ctx_ln - 1 ] =~ /^\+\s* { / ) {
2011-07-25 17:13:25 -07:00
ERROR ( "OPEN_BRACE" ,
"that open brace { should be on the previous line\n" .
2010-10-26 14:23:19 -07:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n" );
2007-06-08 13:47:06 -07:00
}
2008-03-28 14:15:58 -07:00
if ( $ level == 0 && $ pre_ctx ! ~ / } \s * while\s*\ ( $ / &&
$ ctx =~ /\ ) \s*\ ; \s* $ / &&
defined $ lines [ $ ctx_ln - 1 ])
{
2007-10-16 23:29:38 -07:00
my ( $ nlength , $ nindent ) = line_stats ( $ lines [ $ ctx_ln - 1 ]);
if ( $ nindent > $ indent ) {
2011-07-25 17:13:25 -07:00
WARN ( "TRAILING_SEMICOLON" ,
"trailing semicolon indicates no statements, indent implies otherwise\n" .
2010-10-26 14:23:19 -07:00
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n" );
2007-10-16 23:29:38 -07:00
}
}
2007-06-08 13:47:06 -07:00
}
2008-10-15 22:02:21 -07:00
# Check relative indent for conditionals and blocks .
2017-05-08 15:56:05 -07:00
if ( $ line =~ /\ b ( ?: ( ?:if | while | for |( ?: [ a - z_ ] + |) for_each [ a - z_ ] + ) \s*\ (|( ?:do | else ) \b ) / && $ line ! ~ /^.\s*#/ && $ line ! ~ /\ } \s * while\s*/ ) {
2012-01-10 15:10:01 -08:00
( $ stat , $ cond , $ line_nr_next , $ remain_next , $ off_next ) =
ctx_statement_block ( $ linenr , $ realcnt , 0 )
if (! defined $ stat );
2008-10-15 22:02:21 -07:00
my ( $ s , $ c ) = ( $ stat , $ cond );
substr ( $ s , 0 , length ( $ c ), '' );
2015-09-09 15:37:30 -07:00
# remove inline comments
$ s =~ s/ $ ; / / g ;
$ c =~ s/ $ ; / / g ;
2008-10-15 22:02:21 -07:00
# Find out how long the conditional actually is .
2008-10-15 22:02:27 -07:00
my @newlines = ( $ c =~ /\n / gs );
my $ cond_lines = 1 + $ #newlines ;
2008-10-15 22:02:21 -07:00
2015-09-09 15:37:30 -07:00
# Make sure we remove the line prefixes as we have
# none on the first line , and are going to readd them
# where necessary .
$ s =~ s/\n . /\n / gs ;
while ( $ s =~ /\n\s+\\\n/ ) {
$ cond_lines += $ s =~ s/\n\s+\\\n/\n / g ;
}
2008-10-15 22:02:21 -07:00
# We want to check the first line inside the block
# starting at the end of the conditional , so remove :
# 1 ) any blank line termination
# 2 ) any opening brace { on end of the line
# 3 ) any do (...) {
my $ continuation = 0 ;
my $ check = 0 ;
$ s =~ s/^.*\bdo\b// ;
$ s =~ s/^\s* { // ;
if ( $ s =~ s/^\s*\\// ) {
$ continuation = 1 ;
}
2008-10-15 22:02:22 -07:00
if ( $ s =~ s/^\s*?\n// ) {
2008-10-15 22:02:21 -07:00
$ check = 1 ;
$ cond_lines++ ;
}
# Also ignore a loop construct at the end of a
# preprocessor statement .
if (( $ prevline =~ /^.\s*#\s * define\s / ||
$ prevline =~ /\\\s* $ / ) && $ continuation == 0 ) {
$ check = 0 ;
}
2008-10-15 22:02:22 -07:00
my $ cond_ptr = - 1 ;
2008-10-15 22:02:35 -07:00
$ continuation = 0 ;
2008-10-15 22:02:22 -07:00
while ( $ cond_ptr ! = $ cond_lines ) {
$ cond_ptr = $ cond_lines ;
2008-10-15 22:02:21 -07:00
2008-10-15 22:02:32 -07:00
# If we see an #else/#elif then the code
# is not linear .
if ( $ s =~ /^\s*\#\s* ( ?:else | elif ) / ) {
$ check = 0 ;
}
2008-10-15 22:02:22 -07:00
# Ignore :
# 1 ) blank lines , they should be at 0 ,
# 2 ) preprocessor lines , and
# 3 ) labels .
2008-10-15 22:02:35 -07:00
if ( $ continuation ||
$ s =~ /^\s*?\n / ||
2008-10-15 22:02:22 -07:00
$ s =~ /^\s*#\s*?/ ||
$ s =~ /^\s* $ Ident \s*:/ ) {
2008-10-15 22:02:35 -07:00
$ continuation = ( $ s =~ /^.*?\\\n/ ) ? 1 : 0 ;
2009-09-21 17:04:36 -07:00
if ( $ s =~ s/^.*?\n// ) {
$ cond_lines++ ;
}
2008-10-15 22:02:22 -07:00
}
2008-10-15 22:02:21 -07:00
}
my ( undef , $ sindent ) = line_stats ( "+" . $ s );
my $ stat_real = raw_line ( $ linenr , $ cond_lines );
# Check if either of these lines are modified , else
# this is not this patch's fault.
if (!defined($stat_real) ||
$stat !~ /^\+/ && $stat_real !~ /^\+/) {
$check = 0;
}
if (defined($stat_real) && $cond_lines > 1) {
$stat_real = "[...]\n$stat_real";
}
2008-10-15 22:02:22 -07:00
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
2008-10-15 22:02:21 -07:00
2015-09-09 15:37:30 -07:00
if ($check && $s ne '' &&
2020-04-06 20:11:07 -07:00
(($sindent % $tabsize) != 0 ||
2015-09-09 15:37:30 -07:00
($sindent < $indent) ||
2017-05-08 15:56:05 -07:00
($sindent == $indent &&
($s !~ /^\s*(?:\}|\{|else\b)/)) ||
2020-04-06 20:11:07 -07:00
($sindent > $indent + $tabsize))) {
2011-07-25 17:13:25 -07:00
WARN("SUSPECT_CODE_INDENT",
"suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
2008-10-15 22:02:21 -07:00
}
}
2007-10-18 03:05:08 -07:00
# Track the 'values' across context and added lines.
my $opline = $line; $opline =~ s/^./ /;
2008-07-23 21:29:10 -07:00
my ($curr_values, $curr_vars) =
annotate_values($opline . "\n", $prev_values);
2007-10-18 03:05:08 -07:00
$curr_values = $prev_values . $curr_values;
2008-02-08 04:20:54 -08:00
if ($dbg_values) {
my $outline = $opline; $outline =~ s/\t/ /g;
2008-03-04 14:28:20 -08:00
print "$linenr > .$outline\n";
print "$linenr > $curr_values\n";
2008-07-23 21:29:10 -07:00
print "$linenr > $curr_vars\n";
2008-02-08 04:20:54 -08:00
}
2007-10-18 03:05:08 -07:00
$prev_values = substr($curr_values, -1);
2007-06-08 13:47:06 -07:00
#ignore lines not being added
2013-07-03 15:05:31 -07:00
next if ($line =~ /^[^\+]/);
2007-06-08 13:47:06 -07:00
2020-10-15 20:12:09 -07:00
# check for self assignments used to avoid compiler warnings
# e.g.: int foo = foo, *bar = NULL;
# struct foo bar = *(&(bar));
if ($line =~ /^\+\s*(?:$Declare)?([A-Za-z_][A-Za-z\d_]*)\s*=/) {
my $var = $1;
if ($line =~ /^\+\s*(?:$Declare)?$var\s*=\s*(?:$var|\*\s*\(?\s*&\s*\(?\s*$var\s*\)?\s*\)?)\s*[;,]/) {
WARN("SELF_ASSIGNMENT",
"Do not use self-assignments to avoid compiler warnings\n" . $herecurr);
}
}
2016-12-12 16:46:31 -08:00
# check for dereferences that span multiple lines
if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ &&
$line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) {
$prevline =~ /($Lval\s*(?:\.|->))\s*$/;
my $ref = $1;
$line =~ /^.\s*($Lval)/;
$ref .= $1;
$ref =~ s/\s//g;
WARN("MULTILINE_DEREFERENCE",
"Avoid multiple line dereference - prefer ' $ ref'\n" . $hereprev);
}
2016-03-15 14:58:03 -07:00
# check for declarations of signed or unsigned without int
2016-08-02 14:04:42 -07:00
while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
2016-03-15 14:58:03 -07:00
my $type = $1;
my $var = $2;
2016-03-15 14:58:06 -07:00
$var = "" if (!defined $var);
if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
2016-03-15 14:58:03 -07:00
my $sign = $1;
my $pointer = $2;
$pointer = "" if (!defined $pointer);
if (WARN("UNSPECIFIED_INT",
"Prefer ' " . trim($sign) . " int " . rtrim($pointer) . " ' to bare use of ' $ sign " . rtrim($pointer) . " '\n" . $herecurr) &&
$fix) {
my $decl = trim($sign) . " int ";
2016-03-15 14:58:06 -07:00
my $comp_pointer = $pointer;
$comp_pointer =~ s/\s//g;
$decl .= $comp_pointer;
$decl = rtrim($decl) if ($var eq "");
$fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
2016-03-15 14:58:03 -07:00
}
}
}
2007-06-23 17:16:34 -07:00
# TEST: allow direct testing of the type matcher.
2008-07-23 21:29:06 -07:00
if ($dbg_type) {
if ($line =~ /^.\s*$Declare\s*$/) {
2011-07-25 17:13:25 -07:00
ERROR("TEST_TYPE",
"TEST: is type\n" . $herecurr);
2008-07-23 21:29:06 -07:00
} elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
2011-07-25 17:13:25 -07:00
ERROR("TEST_NOT_TYPE",
"TEST: is not type ($1 is)\n". $herecurr);
2008-07-23 21:29:06 -07:00
}
2007-06-23 17:16:34 -07:00
next;
}
2008-10-15 22:02:17 -07:00
# TEST: allow direct testing of the attribute matcher.
if ($dbg_attr) {
2009-02-27 14:03:08 -08:00
if ($line =~ /^.\s*$Modifier\s*$/) {
2011-07-25 17:13:25 -07:00
ERROR("TEST_ATTR",
"TEST: is attr\n" . $herecurr);
2009-02-27 14:03:08 -08:00
} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
2011-07-25 17:13:25 -07:00
ERROR("TEST_NOT_ATTR",
"TEST: is not attr ($1 is)\n". $herecurr);
2008-10-15 22:02:17 -07:00
}
next;
}
2007-06-23 17:16:34 -07:00
2007-07-19 01:48:34 -07:00
# check for initialisation to aggregates open brace on the next line
2009-10-26 16:50:15 -07:00
if ($line =~ /^.\s*{/ &&
$prevline =~ /(?:^|[^=])=\s*$/) {
2014-08-06 16:11:05 -07:00
if (ERROR("OPEN_BRACE",
"that open brace { should be on the previous line\n" . $hereprev) &&
2014-08-06 16:11:07 -07:00
$fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
fix_delete_line($fixlinenr - 1, $prevrawline);
fix_delete_line($fixlinenr, $rawline);
2014-08-06 16:11:05 -07:00
my $fixedline = $prevrawline;
$fixedline =~ s/\s*=\s*$/ = {/;
2014-08-06 16:11:07 -07:00
fix_insert_line($fixlinenr, $fixedline);
2014-08-06 16:11:05 -07:00
$fixedline = $line;
2017-07-10 15:52:21 -07:00
$fixedline =~ s/^(.\s*)\{\s*/$1/;
2014-08-06 16:11:07 -07:00
fix_insert_line($fixlinenr, $fixedline);
2014-08-06 16:11:05 -07:00
}
2007-07-19 01:48:34 -07:00
}
2007-06-23 17:16:34 -07:00
#
# Checks which are anchored on the added line.
#
# check for malformed paths in #include statements (uses RAW line)
2008-06-05 22:46:01 -07:00
if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
2007-06-23 17:16:34 -07:00
my $path = $1;
if ($path =~ m{//}) {
2011-07-25 17:13:25 -07:00
ERROR("MALFORMED_INCLUDE",
2012-12-20 15:05:37 -08:00
"malformed #include filename\n" . $herecurr);
}
if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) {
ERROR("UAPI_INCLUDE",
"No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr);
2007-06-23 17:16:34 -07:00
}
}
2007-06-08 13:47:06 -07:00
# no C99 // comments
if ($line =~ m{//}) {
2013-07-03 15:05:31 -07:00
if (ERROR("C99_COMMENTS",
"do not use C99 // comments\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
my $line = $fixed[$fixlinenr];
2013-07-03 15:05:31 -07:00
if ($line =~ /\/\/(.*)$/) {
my $comment = trim($1);
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@;
2013-07-03 15:05:31 -07:00
}
}
2007-06-08 13:47:06 -07:00
}
# Remove C99 comments.
2007-06-01 00:46:48 -07:00
$line =~ s@//.*@@;
2007-10-18 03:05:08 -07:00
$opline =~ s@//.*@@;
2007-06-01 00:46:48 -07:00
2009-10-26 16:50:16 -07:00
# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
# the whole statement.
#print "APW <$lines[$realline_next - 1]>\n";
if (defined $realline_next &&
exists $lines[$realline_next - 1] &&
!defined $suppress_export{$realline_next} &&
2021-02-02 13:13:34 +01:00
($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
2010-10-26 14:23:18 -07:00
# Handle definitions which produce identifiers with
# a prefix:
# XXX(foo);
# EXPORT_SYMBOL(something_foo);
2007-06-23 17:16:34 -07:00
my $name = $1;
2012-01-10 15:10:04 -08:00
if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
2010-10-26 14:23:18 -07:00
$name =~ /^${Ident}_$2/) {
#print "FOO C name<$name>\n";
$suppress_export{$realline_next} = 1;
} elsif ($stat !~ /(?:
2009-10-26 16:50:16 -07:00
\n.}\s*$|
2008-10-15 22:02:34 -07:00
^.DEFINE_$Ident\(\Q$name\E\)|
^.DECLARE_$Ident\(\Q$name\E\)|
^.LIST_HEAD\(\Q$name\E\)|
2009-10-26 16:50:16 -07:00
^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
\b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
2008-10-15 22:02:34 -07:00
)/x) {
2009-10-26 16:50:16 -07:00
#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
$suppress_export{$realline_next} = 2;
} else {
$suppress_export{$realline_next} = 1;
2007-06-01 00:46:48 -07:00
}
}
2009-10-26 16:50:16 -07:00
if (!defined $suppress_export{$linenr} &&
$prevline =~ /^.\s*$/ &&
2021-02-02 13:13:34 +01:00
($line =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
2009-10-26 16:50:16 -07:00
#print "FOO B <$lines[$linenr - 1]>\n";
$suppress_export{$linenr} = 2;
}
if (defined $suppress_export{$linenr} &&
$suppress_export{$linenr} == 2) {
2011-07-25 17:13:25 -07:00
WARN("EXPORT_SYMBOL",
"EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
2009-10-26 16:50:16 -07:00
}
2007-06-01 00:46:48 -07:00
2010-08-09 17:21:00 -07:00
# check for global initialisers.
2015-11-06 16:31:37 -08:00
if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) {
2013-09-11 14:23:54 -07:00
if (ERROR("GLOBAL_INITIALISERS",
2015-11-06 16:31:37 -08:00
"do not initialise globals to $1\n" . $herecurr) &&
2013-09-11 14:23:54 -07:00
$fix) {
2015-11-06 16:31:37 -08:00
$fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/;
2013-09-11 14:23:54 -07:00
}
2007-07-19 01:48:34 -07:00
}
2007-06-23 17:16:34 -07:00
# check for static initialisers.
2015-11-06 16:31:37 -08:00
if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) {
2013-09-11 14:23:54 -07:00
if (ERROR("INITIALISED_STATIC",
2015-11-06 16:31:37 -08:00
"do not initialise statics to $1\n" .
2013-09-11 14:23:54 -07:00
$herecurr) &&
$fix) {
2015-11-06 16:31:37 -08:00
$fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/;
2013-09-11 14:23:54 -07:00
}
2007-06-01 00:46:48 -07:00
}
2014-08-06 16:11:22 -07:00
# check for misordered declarations of char/short/int/long with signed/unsigned
while ($sline =~ m{(\b$TypeMisordered\b)}g) {
my $tmp = trim($1);
WARN("MISORDERED_TYPE",
"type ' $ tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
}
2018-08-21 21:58:12 -07:00
# check for unnecessary <signed> int declarations of short/long/long long
while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
my $type = trim($1);
next if ($type !~ /\bint\b/);
next if ($type !~ /\b(?:short|long\s+long|long)\b/);
my $new_type = $type;
$new_type =~ s/\b\s*int\s*\b/ /;
$new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
$new_type =~ s/^const\s+//;
$new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
$new_type = "const $new_type" if ($type =~ /^const\b/);
$new_type =~ s/\s+/ /g;
$new_type = trim($new_type);
if (WARN("UNNECESSARY_INT",
"Prefer ' $ new_type' over ' $ type' as the int is unnecessary\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
}
}
2010-10-26 14:23:20 -07:00
# check for static const char * arrays.
if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
2011-07-25 17:13:25 -07:00
WARN("STATIC_CONST_CHAR_ARRAY",
"static const char * array should probably be static const char * const\n" .
2010-10-26 14:23:20 -07:00
$herecurr);
2019-01-03 15:26:59 -08:00
}
# check for initialized const char arrays that should be static const
if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
if (WARN("STATIC_CONST_CHAR_ARRAY",
"const array should probably be static const\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
}
}
2010-10-26 14:23:20 -07:00
# check for static char foo[] = "bar" declarations.
if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
2011-07-25 17:13:25 -07:00
WARN("STATIC_CONST_CHAR_ARRAY",
"static char array declaration should probably be static const char\n" .
2010-10-26 14:23:20 -07:00
$herecurr);
2019-01-03 15:26:59 -08:00
}
2010-10-26 14:23:20 -07:00
2015-04-16 12:44:22 -07:00
# check for const <foo> const where <foo> is not a pointer or array type
if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
my $found = $1;
if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) {
WARN("CONST_CONST",
"'const $ found const *' should probably be 'const $ found * const'\n" . $herecurr);
} elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) {
WARN("CONST_CONST",
"'const $ found const' should probably be 'const $ found'\n" . $herecurr);
}
}
2020-12-15 20:44:30 -08:00
# check for const static or static <non ptr type> const declarations
# prefer 'static const < foo>' over 'const static < foo>' and 'static < foo > const'
if ($sline =~ /^\+\s*const\s+static\s+($Type)\b/ ||
$sline =~ /^\+\s*static\s+($BasicType)\s+const\b/) {
if (WARN("STATIC_CONST",
"Move const after static - use 'static const $ 1 '\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\bconst\s+static\b/static const/;
$fixed[$fixlinenr] =~ s/\bstatic\s+($BasicType)\s+const\b/static const $1/;
}
}
2014-04-03 14:49:18 -07:00
# check for non-global char *foo[] = {"bar", ...} declarations.
if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"char * array declaration might be better as static const\n" .
$herecurr);
2021-02-25 17:21:47 -08:00
}
2014-04-03 14:49:18 -07:00
2015-04-16 12:44:36 -07:00
# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
my $array = $1;
if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) {
my $array_div = $1;
if (WARN("ARRAY_SIZE",
"Prefer ARRAY_SIZE($array)\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/;
}
}
}
2014-01-27 17:07:18 -08:00
# check for function declarations without arguments like "int foo()"
2020-04-06 20:11:17 -07:00
if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
2014-01-27 17:07:18 -08:00
if (ERROR("FUNCTION_WITHOUT_ARGS",
"Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
2014-01-27 17:07:18 -08:00
}
}
2007-06-23 17:16:34 -07:00
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
2009-01-06 14:41:26 -08:00
$line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
2008-06-05 22:46:01 -07:00
$line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
2008-10-15 22:02:32 -07:00
$line !~ /\b$typeTypedefs\b/ &&
2016-12-11 06:29:58 +02:00
$line !~ /\b__bitwise\b/) {
2011-07-25 17:13:25 -07:00
WARN("NEW_TYPEDEFS",
"do not add new typedefs\n" . $herecurr);
2007-06-01 00:46:48 -07:00
}
# * goes on variable not on type
2009-01-06 14:41:21 -08:00
# (char*[ const])
2012-01-10 15:10:15 -08:00
while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) {
#print "AA<$1>\n";
2013-07-03 15:05:31 -07:00
my ($ident, $from, $to) = ($1, $2, $2);
2007-06-23 17:16:44 -07:00
2009-01-06 14:41:21 -08:00
# Should start with a space.
$to =~ s/^(\S)/ $1/;
# Should not end with a space.
$to =~ s/\s+$//;
# '*'s should not have spaces between.
2009-01-15 13:51:05 -08:00
while ($to =~ s/\*\s+\*/\*\*/) {
2009-01-06 14:41:21 -08:00
}
2007-06-23 17:16:44 -07:00
2013-07-03 15:05:31 -07:00
## print "1: from<$from> to<$to> ident<$ident>\n";
2009-01-06 14:41:21 -08:00
if ($from ne $to) {
2013-07-03 15:05:31 -07:00
if (ERROR("POINTER_LOCATION",
"\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) &&
$fix) {
my $sub_from = $ident;
my $sub_to = $ident;
$sub_to =~ s/\Q$from\E/$to/;
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~
2013-07-03 15:05:31 -07:00
s@\Q$sub_from\E@$sub_to@;
}
2009-01-06 14:41:21 -08:00
}
2012-01-10 15:10:15 -08:00
}
while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) {
#print "BB<$1>\n";
2013-07-03 15:05:31 -07:00
my ($match, $from, $to, $ident) = ($1, $2, $2, $3);
2007-06-23 17:16:44 -07:00
2009-01-06 14:41:21 -08:00
# Should start with a space.
$to =~ s/^(\S)/ $1/;
# Should not end with a space.
$to =~ s/\s+$//;
# '*'s should not have spaces between.
2009-01-15 13:51:05 -08:00
while ($to =~ s/\*\s+\*/\*\*/) {
2009-01-06 14:41:21 -08:00
}
# Modifiers should have spaces.
$to =~ s/(\b$Modifier$)/$1 /;
2013-07-03 15:05:31 -07:00
## print "2: from<$from> to<$to> ident<$ident>\n";
2009-02-27 14:03:08 -08:00
if ($from ne $to && $ident !~ /^$Modifier$/) {
2013-07-03 15:05:31 -07:00
if (ERROR("POINTER_LOCATION",
"\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) &&
$fix) {
my $sub_from = $match;
my $sub_to = $match;
$sub_to =~ s/\Q$from\E/$to/;
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~
2013-07-03 15:05:31 -07:00
s@\Q$sub_from\E@$sub_to@;
}
2009-01-06 14:41:21 -08:00
}
2007-06-01 00:46:48 -07:00
}
2015-09-09 15:37:27 -07:00
# avoid BUG() or BUG_ON()
if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
2017-09-08 16:16:07 -07:00
my $msg_level = \&WARN;
$msg_level = \&CHK if ($file);
&{$msg_level}("AVOID_BUG",
"Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
2015-09-09 15:37:27 -07:00
}
2007-06-01 00:46:48 -07:00
2015-09-09 15:37:27 -07:00
# avoid LINUX_VERSION_CODE
2007-11-28 16:21:06 -08:00
if ($line =~ /\bLINUX_VERSION_CODE\b/) {
2011-07-25 17:13:25 -07:00
WARN("LINUX_VERSION_CODE",
"LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
2007-11-28 16:21:06 -08:00
}
2011-06-15 15:08:17 -07:00
# check for uses of printk_ratelimit
if ($line =~ /\bprintk_ratelimit\s*\(/) {
2011-07-25 17:13:25 -07:00
WARN("PRINTK_RATELIMITED",
2015-02-13 14:38:54 -08:00
"Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
2011-06-15 15:08:17 -07:00
}
2017-11-17 15:28:41 -08:00
# printk should use KERN_* levels
if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) {
WARN("PRINTK_WITHOUT_KERN_LEVEL",
"printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
2007-06-01 00:46:48 -07:00
}
2020-12-15 20:45:24 -08:00
# prefer variants of (subsystem|netdev|dev|pr)_<level> to printk(KERN_<LEVEL>
if ($line =~ /\b(printk(_once|_ratelimited)?)\s*\(\s*KERN_([A-Z]+)/) {
my $printk = $1;
my $modifier = $2;
my $orig = $3;
$modifier = "" if (!defined($modifier));
2012-05-31 16:26:09 -07:00
my $level = lc($orig);
$level = "warn" if ($level eq "warning");
2012-10-04 17:13:32 -07:00
my $level2 = $level;
$level2 = "dbg" if ($level eq "debug");
2020-12-15 20:45:24 -08:00
$level .= $modifier;
$level2 .= $modifier;
2012-05-31 16:26:09 -07:00
WARN("PREFER_PR_LEVEL",
2020-12-15 20:45:24 -08:00
"Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to $printk(KERN_$orig ...\n" . $herecurr);
2012-05-31 16:26:09 -07:00
}
2020-12-15 20:45:24 -08:00
# prefer dev_<level> to dev_printk(KERN_<LEVEL>
2013-02-21 16:44:13 -08:00
if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
my $orig = $1;
my $level = lc($orig);
$level = "warn" if ($level eq "warning");
$level = "dbg" if ($level eq "debug");
WARN("PREFER_DEV_LEVEL",
"Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr);
}
2020-10-15 20:12:02 -07:00
# trace_printk should not be used in production code.
if ($line =~ /\b(trace_printk|trace_puts|ftrace_vprintk)\s*\(/) {
WARN("TRACE_PRINTK",
"Do not use $1() in production code (this can be ignored if built only with a debug config option)\n" . $herecurr);
}
2015-04-16 12:44:44 -07:00
# ENOSYS means "bad syscall nr" and nothing else. This will have a small
# number of false positives, but assembly files are not checked, so at
# least the arch entry code will not trigger this warning.
if ($line =~ /\bENOSYS\b/) {
WARN("ENOSYS",
"ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr);
}
2020-05-11 10:08:07 -07:00
# ENOTSUPP is not a standard error code and should be avoided in new patches.
# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP.
# Similarly to ENOSYS warning a small number of false positives is expected.
if (!$file && $line =~ /\bENOTSUPP\b/) {
if (WARN("ENOTSUPP",
"ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\bENOTSUPP\b/EOPNOTSUPP/;
}
}
2007-06-23 17:16:34 -07:00
# function brace can't be on same line , except for #defines of do while ,
# or if closed on same line
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2018-02-06 15:39:09 -08:00
$ sline =~ / $ Type \s* $ Ident \s* $ balanced_parens\s*\ { / &&
$ sline ! ~ /\#\s * define\b . * do\s*\ { / &&
$ sline ! ~ / } / ) {
2014-08-06 16:11:12 -07:00
if ( ERROR ( "OPEN_BRACE" ,
2018-02-06 15:39:09 -08:00
"open brace '{' following function definitions go on the next line\n" . $ herecurr ) &&
2014-08-06 16:11:12 -07:00
$ fix ) {
fix_delete_line ( $ fixlinenr , $ rawline );
my $ fixed_line = $ rawline ;
2020-12-15 20:45:02 -08:00
$ fixed_line =~ / ( ^..* $ Type \s* $ Ident \ (. *\ ) \s* ) \ {(. * ) $ / ;
2014-08-06 16:11:12 -07:00
my $ line1 = $ 1 ;
my $ line2 = $ 2 ;
fix_insert_line ( $ fixlinenr , ltrim ( $ line1 ));
fix_insert_line ( $ fixlinenr , " \+ { ");
if ($line2 !~ /^\s*$/) {
fix_insert_line($fixlinenr, " \+\t " . trim($line2));
}
}
2007-06-01 00:46:48 -07:00
}
2007-06-23 17:16:34 -07:00
2007-11-28 16:21:06 -08:00
# open braces for enum, union and struct go on the same line.
if ($line =~ /^.\s*{/ &&
$prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
2014-08-06 16:11:12 -07:00
if (ERROR(" OPEN_BRACE ",
" open brace '{' following $ 1 go on the same line\n " . $ hereprev ) &&
$ fix && $ prevline =~ /^\+/ && $ line =~ /^\+/ ) {
fix_delete_line ( $ fixlinenr - 1 , $ prevrawline );
fix_delete_line ( $ fixlinenr , $ rawline );
my $ fixedline = rtrim ( $ prevrawline ) . " {" ;
fix_insert_line ( $ fixlinenr , $ fixedline );
$ fixedline = $ rawline ;
2017-07-10 15:52:21 -07:00
$ fixedline =~ s/^ (. \s* ) \ { \s*/ $ 1 \t/ ;
2014-08-06 16:11:12 -07:00
if ( $ fixedline ! ~ /^\+\s* $ / ) {
fix_insert_line ( $ fixlinenr , $ fixedline );
}
}
2007-11-28 16:21:06 -08:00
}
2010-10-26 14:23:15 -07:00
# missing space after union , struct or enum definition
2013-07-03 15:05:31 -07:00
if ( $ line =~ /^.\s* ( ?:typedef\s+ ) ? ( enum | union | struct )( ?:\s+ $ Ident ){ 1 , 2 }[ =\ {] / ) {
if ( WARN ( "SPACING" ,
"missing space after $1 definition\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/^ (. \s* ( ?:typedef\s+ ) ? ( ?:enum | union | struct )( ?:\s+ $ Ident ){ 1 , 2 })([ =\ {]) / $ 1 $ 2 / ;
}
2010-10-26 14:23:15 -07:00
}
2014-01-23 15:54:49 -08:00
# Function pointer declarations
# check spacing between type , funcptr , and args
# canonical declaration is "type (*funcptr)(args...)"
2014-04-03 14:49:12 -07:00
if ( $ line =~ /^.\s* ( $ Declare ) \ (( \s* ) \* ( \s* )( $ Ident )( \s* ) \ )( \s* ) \ ( / ) {
2014-01-23 15:54:49 -08:00
my $ declare = $ 1 ;
my $ pre_pointer_space = $ 2 ;
my $ post_pointer_space = $ 3 ;
my $ funcname = $ 4 ;
my $ post_funcname_space = $ 5 ;
my $ pre_args_space = $ 6 ;
2014-04-03 14:49:12 -07:00
# the $ Declare variable will capture all spaces after the type
# so check it for a missing trailing missing space but pointer return types
# don't need a space so don't warn for those .
my $ post_declare_space = "" ;
if ( $ declare =~ / ( \s+ ) $ / ) {
$ post_declare_space = $ 1 ;
$ declare = rtrim ( $ declare );
}
if ( $ declare ! ~ /\* $ / && $ post_declare_space =~ /^ $ / ) {
2014-01-23 15:54:49 -08:00
WARN ( "SPACING" ,
"missing space after return type\n" . $ herecurr );
2014-04-03 14:49:12 -07:00
$ post_declare_space = " " ;
2014-01-23 15:54:49 -08:00
}
# unnecessary space "type (*funcptr)(args...)"
2014-04-03 14:49:12 -07:00
# This test is not currently implemented because these declarations are
# equivalent to
# int foo ( int bar , ...)
# and this is form shouldn't/doesn't generate a checkpatch warning .
#
# elsif ( $ declare =~ /\s { 2 ,} $ / ) {
# WARN ( "SPACING" ,
# "Multiple spaces after return type\n" . $ herecurr );
# }
2014-01-23 15:54:49 -08:00
# unnecessary space "type ( *funcptr)(args...)"
if ( defined $ pre_pointer_space &&
$ pre_pointer_space =~ /^\s/ ) {
WARN ( "SPACING" ,
"Unnecessary space after function pointer open parenthesis\n" . $ herecurr );
}
# unnecessary space "type (* funcptr)(args...)"
if ( defined $ post_pointer_space &&
$ post_pointer_space =~ /^\s/ ) {
WARN ( "SPACING" ,
"Unnecessary space before function pointer name\n" . $ herecurr );
}
# unnecessary space "type (*funcptr )(args...)"
if ( defined $ post_funcname_space &&
$ post_funcname_space =~ /^\s/ ) {
WARN ( "SPACING" ,
"Unnecessary space after function pointer name\n" . $ herecurr );
}
# unnecessary space "type (*funcptr) (args...)"
if ( defined $ pre_args_space &&
$ pre_args_space =~ /^\s/ ) {
WARN ( "SPACING" ,
"Unnecessary space before function pointer arguments\n" . $ herecurr );
}
if ( show_type ( "SPACING" ) && $ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2014-04-03 14:49:12 -07:00
s/^ (. \s* ) $ Declare \s*\ ( \s*\*\s* $ Ident \s*\ ) \s*\ ( / $ 1 . $ declare . $ post_declare_space . '(*' . $ funcname . ')(' / ex ;
2014-01-23 15:54:49 -08:00
}
}
2008-07-23 21:29:02 -07:00
# check for spacing round square brackets ; allowed :
# 1. with a type on the left -- int [] a ;
2008-10-15 22:02:15 -07:00
# 2. at the beginning of a line for slice initialisers -- [ 0. . .10 ] = 5 ,
# 3. inside a curly brace -- = { [ 0. . .10 ] = 5 }
2008-07-23 21:29:02 -07:00
while ( $ line =~ / (. *?\s ) \ [ / g ) {
my ( $ where , $ prefix ) = ( $ - [ 1 ], $ 1 );
if ( $ prefix ! ~ / $ Type \s+ $ / &&
2008-10-15 22:02:15 -07:00
( $ where ! = 0 || $ prefix ! ~ /^.\s+ $ / ) &&
2018-04-10 16:34:14 -07:00
$ prefix ! ~ / [{, : ] \s+ $ / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "BRACKET_SPACE" ,
"space prohibited before open square bracket '['\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/^ ( \+.*? ) \s+\ [ / $ 1 \ [ / ;
}
2008-07-23 21:29:02 -07:00
}
}
2007-07-19 01:48:34 -07:00
# check for spaces between functions and their parentheses .
2007-10-18 03:05:08 -07:00
while ( $ line =~ / ( $ Ident ) \s+\ ( / g ) {
2008-02-08 04:20:54 -08:00
my $ name = $ 1 ;
2008-03-28 14:15:58 -07:00
my $ ctx_before = substr ( $ line , 0 , $ - [ 1 ]);
my $ ctx = "$ctx_before$name" ;
2008-02-08 04:20:54 -08:00
# Ignore those directives where spaces _ are_ permitted .
2008-03-28 14:15:58 -07:00
if ( $ name =~ /^ ( ?:
if | for | while | switch | return | case |
volatile | __ volatile__ |
__ attribute__ | format | __ extension__ |
asm | __ asm__ ) $ / x )
{
2008-02-08 04:20:54 -08:00
# cpp #define statements have non - optional spaces , ie
# if there is a space between the name and the open
# parenthesis it is simply not a parameter group .
2008-06-05 22:46:01 -07:00
} elsif ( $ ctx_before =~ /^.\s*\#\s * define\s* $ / ) {
2008-03-28 14:15:58 -07:00
# cpp #elif statement condition may start with a (
2008-06-05 22:46:01 -07:00
} elsif ( $ ctx =~ /^.\s*\#\s * elif\s* $ / ) {
2008-02-08 04:20:54 -08:00
# If this whole things ends with a type its most
# likely a typedef for a function .
2008-03-28 14:15:58 -07:00
} elsif ( $ ctx =~ / $ Type $ / ) {
2008-02-08 04:20:54 -08:00
} else {
2013-07-03 15:05:31 -07:00
if ( WARN ( "SPACING" ,
"space prohibited between function name and open parenthesis '('\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/\b$name\s+\ ( / $ name\ ( / ;
}
2007-10-18 03:05:08 -07:00
}
2007-07-19 01:48:34 -07:00
}
2012-05-31 16:26:09 -07:00
2007-06-23 17:16:34 -07:00
# Check operator spacing .
2007-06-01 00:46:48 -07:00
if (!( $ line=~/\#\s * include/ )) {
2013-07-03 15:05:31 -07:00
my $ fixed_line = "" ;
my $ line_fixed = 0 ;
2007-10-16 23:29:38 -07:00
my $ ops = qr {
<<= | >>= | <= | >= | == |! = |
\+= | -= | \*= | \/= | %=|\^=|\|=|&=|
=> | -> | << | >> | < | > | = |!| ~ |
2008-07-23 21:29:10 -07:00
&& | \ | \ ||,| \^ | \+\+ | -- | & | \ || \+ | - | \* | \/ | %|
2013-11-12 15:10:05 -08:00
\?: | \? | :
2007-10-16 23:29:38 -07:00
} x ;
2008-03-04 14:28:20 -08:00
my @elements = split ( / ( $ ops |;) / , $ opline );
2013-07-03 15:05:31 -07:00
## print ( "element count: <" . $ #elements . ">\n" );
## foreach my $ el ( @elements ) {
## print ( "el: <$el>\n" );
## }
my @fix_elements = ();
2007-06-08 13:47:06 -07:00
my $ off = 0 ;
2007-10-18 03:05:08 -07:00
2013-07-03 15:05:31 -07:00
foreach my $ el ( @elements ) {
push ( @fix_elements , substr ( $ rawline , $ off , length ( $ el )));
$ off += length ( $ el );
}
$ off = 0 ;
2007-10-18 03:05:08 -07:00
my $ blank = copy_spacing ( $ opline );
2013-09-11 14:24:01 -07:00
my $ last_after = - 1 ;
2007-10-18 03:05:08 -07:00
2007-06-01 00:46:48 -07:00
for ( my $ n = 0 ; $ n < $ #elements ; $ n += 2 ) {
2013-07-03 15:05:31 -07:00
my $ good = $ fix_elements [ $ n ] . $ fix_elements [ $ n + 1 ];
## print ( "n: <$n> good: <$good>\n" );
2007-06-08 13:46:39 -07:00
$ off += length ( $ elements [ $ n ]);
2011-03-30 22:57:33 -03:00
# Pick up the preceding and succeeding characters .
2008-03-28 14:15:58 -07:00
my $ ca = substr ( $ opline , 0 , $ off );
my $ cc = '' ;
if ( length ( $ opline ) >= ( $ off + length ( $ elements [ $ n + 1 ]))) {
$ cc = substr ( $ opline , $ off + length ( $ elements [ $ n + 1 ]));
}
my $ cb = "$ca$;$cc" ;
2007-06-08 13:46:39 -07:00
my $ a = '' ;
$ a = 'V' if ( $ elements [ $ n ] ne '' );
$ a = 'W' if ( $ elements [ $ n ] =~ /\s$/ );
2008-03-04 14:28:20 -08:00
$ a = 'C' if ( $ elements [ $ n ] =~ / $ ; $ / );
2007-06-08 13:46:39 -07:00
$ a = 'B' if ( $ elements [ $ n ] =~ / ( \ [| \ () $ / );
$ a = 'O' if ( $ elements [ $ n ] eq '' );
2008-03-28 14:15:58 -07:00
$ a = 'E' if ( $ ca =~ /^\s* $ / );
2007-06-08 13:46:39 -07:00
2007-06-01 00:46:48 -07:00
my $ op = $ elements [ $ n + 1 ];
2007-06-08 13:46:39 -07:00
my $ c = '' ;
2007-06-01 00:46:48 -07:00
if ( defined $ elements [ $ n + 2 ]) {
2007-06-08 13:46:39 -07:00
$ c = 'V' if ( $ elements [ $ n + 2 ] ne '' );
$ c = 'W' if ( $ elements [ $ n + 2 ] =~ /^\s/ );
2008-03-04 14:28:20 -08:00
$ c = 'C' if ( $ elements [ $ n + 2 ] =~ /^ $ ; / );
2007-06-08 13:46:39 -07:00
$ c = 'B' if ( $ elements [ $ n + 2 ] =~ /^ ( \ )| \ ]|;) / );
$ c = 'O' if ( $ elements [ $ n + 2 ] eq '' );
2009-01-06 14:41:27 -08:00
$ c = 'E' if ( $ elements [ $ n + 2 ] =~ /^\s*\\ $ / );
2007-06-08 13:46:39 -07:00
} else {
$ c = 'E' ;
2007-06-01 00:46:48 -07:00
}
2007-06-08 13:46:39 -07:00
my $ ctx = "${a}x${c}" ;
my $ at = "(ctx:$ctx)" ;
2007-10-18 03:05:08 -07:00
my $ ptr = substr ( $ blank , 0 , $ off ) . "^" ;
2007-07-15 23:37:22 -07:00
my $ hereptr = "$hereline$ptr\n" ;
2007-06-01 00:46:48 -07:00
2008-07-23 21:29:10 -07:00
# Pull out the value of this operator .
2007-10-18 03:05:08 -07:00
my $ op_type = substr ( $ curr_values , $ off + 1 , 1 );
2007-06-01 00:46:48 -07:00
2008-07-23 21:29:10 -07:00
# Get the full operator variant .
my $ opv = $ op . substr ( $ curr_vars , $ off , 1 );
2008-02-08 04:22:03 -08:00
# Ignore operators passed as parameters .
if ( $ op_type ne 'V' &&
2015-04-16 12:44:39 -07:00
$ ca =~ /\s$ / && $ cc =~ /^\s * [, \ )] / ) {
2008-02-08 04:22:03 -08:00
2008-03-04 14:28:20 -08:00
# # Ignore comments
# } elsif ( $ op =~ /^ $ ; + $ / ) {
2008-02-08 04:22:03 -08:00
2007-06-23 17:16:44 -07:00
# ; should have either the end of line or a space or \ after it
2008-02-08 04:22:03 -08:00
} elsif ( $ op eq ';' ) {
2008-03-04 14:28:20 -08:00
if ( $ ctx ! ~ /.x [ WEBC ] / &&
$ cc ! ~ /^\\/ && $ cc ! ~ /^ ; / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space required after that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = $ fix_elements [ $ n ] . trim ( $ fix_elements [ $ n + 1 ]) . " " ;
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-06-23 17:16:44 -07:00
}
# // is a comment
} elsif ( $ op eq '//' ) {
2007-06-01 00:46:48 -07:00
2014-04-03 14:49:33 -07:00
# : when part of a bitfield
} elsif ( $ opv eq ':B' ) {
# skip the bitfield test for now
2008-07-23 21:29:10 -07:00
# No spaces for :
# ->
2014-04-03 14:49:33 -07:00
} elsif ( $ op eq '->' ) {
2007-06-08 13:46:39 -07:00
if ( $ ctx =~ / Wx .|. xW/ ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"spaces prohibited around that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ]) . trim ( $ fix_elements [ $ n + 1 ]);
2013-07-03 15:05:31 -07:00
if ( defined $ fix_elements [ $ n + 2 ]) {
$ fix_elements [ $ n + 2 ] =~ s/^\s+// ;
}
2013-09-11 14:24:01 -07:00
$ line_fixed = 1 ;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2014-12-10 15:51:32 -08:00
# , must not have a space before and must have a space on the right .
2007-06-01 00:46:48 -07:00
} elsif ( $ op eq ',' ) {
2014-12-10 15:51:32 -08:00
my $ rtrim_before = 0 ;
my $ space_after = 0 ;
if ( $ ctx =~ / Wx . / ) {
if ( ERROR ( "SPACING" ,
"space prohibited before that '$op' $at\n" . $ hereptr )) {
$ line_fixed = 1 ;
$ rtrim_before = 1 ;
}
}
2008-03-04 14:28:20 -08:00
if ( $ ctx ! ~ /.x [ WEC ] / && $ cc ! ~ /^ } / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space required after that '$op' $at\n" . $ hereptr )) {
$ line_fixed = 1 ;
2013-09-11 14:24:01 -07:00
$ last_after = $ n ;
2014-12-10 15:51:32 -08:00
$ space_after = 1 ;
}
}
if ( $ rtrim_before || $ space_after ) {
if ( $ rtrim_before ) {
$ good = rtrim ( $ fix_elements [ $ n ]) . trim ( $ fix_elements [ $ n + 1 ]);
} else {
$ good = $ fix_elements [ $ n ] . trim ( $ fix_elements [ $ n + 1 ]);
}
if ( $ space_after ) {
$ good . = " " ;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2007-10-16 23:29:38 -07:00
# '*' as part of a type definition -- reported already .
2008-07-23 21:29:10 -07:00
} elsif ( $ opv eq '*_' ) {
2007-10-16 23:29:38 -07:00
#warn "'*' is part of type\n" ;
# unary operators should have a space before and
# none after . May be left adjacent to another
# unary operator , or a cast
} elsif ( $ op eq '!' || $ op eq '~' ||
2008-07-23 21:29:10 -07:00
$ opv eq '*U' || $ opv eq '-U' ||
2008-10-15 22:02:16 -07:00
$ opv eq '&U' || $ opv eq '&&U' ) {
2008-03-04 14:28:20 -08:00
if ( $ ctx ! ~ / [ WEBC ] x . / && $ ca ! ~ / ( ?:\ )|!| ~ | \* | - | \& | \ || \+\+ | \-\- | \ {) $ / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space required before that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
if ( $ n ! = $ last_after + 2 ) {
$ good = $ fix_elements [ $ n ] . " " . ltrim ( $ fix_elements [ $ n + 1 ]);
$ line_fixed = 1 ;
}
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2009-02-27 14:03:07 -08:00
if ( $ op eq '*' && $ cc =~/\s* $ Modifier \b/ ) {
2008-04-29 00:59:32 -07:00
# A unary '*' may be const
} elsif ( $ ctx =~ /.xW/ ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited after that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = $ fix_elements [ $ n ] . rtrim ( $ fix_elements [ $ n + 1 ]);
2013-07-03 15:05:31 -07:00
if ( defined $ fix_elements [ $ n + 2 ]) {
$ fix_elements [ $ n + 2 ] =~ s/^\s+// ;
}
2013-09-11 14:24:01 -07:00
$ line_fixed = 1 ;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
# unary ++ and unary -- are allowed no space on one side .
} elsif ( $ op eq '++' or $ op eq '--' ) {
2008-03-28 14:15:58 -07:00
if ( $ ctx ! ~ / [ WEOBC ] x [ ^ W ] / && $ ctx ! ~ / [ ^ W ] x [ WOBEC ] / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space required one side of that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = $ fix_elements [ $ n ] . trim ( $ fix_elements [ $ n + 1 ]) . " " ;
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-06-01 00:46:48 -07:00
}
2008-03-28 14:15:58 -07:00
if ( $ ctx =~ / Wx [ BE ] / ||
( $ ctx =~ / Wx . / && $ cc =~ /^ ; / )) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ]) . trim ( $ fix_elements [ $ n + 1 ]);
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-06-23 17:16:34 -07:00
}
2008-03-28 14:15:58 -07:00
if ( $ ctx =~ / ExW / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited after that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = $ fix_elements [ $ n ] . trim ( $ fix_elements [ $ n + 1 ]);
2013-07-03 15:05:31 -07:00
if ( defined $ fix_elements [ $ n + 2 ]) {
$ fix_elements [ $ n + 2 ] =~ s/^\s+// ;
}
2013-09-11 14:24:01 -07:00
$ line_fixed = 1 ;
2013-07-03 15:05:31 -07:00
}
2008-03-28 14:15:58 -07:00
}
2007-06-01 00:46:48 -07:00
# << and >> may either have or not have spaces both sides
2007-10-16 23:29:38 -07:00
} elsif ( $ op eq '<<' or $ op eq '>>' or
$ op eq '&' or $ op eq '^' or $ op eq '|' or
$ op eq '+' or $ op eq '-' or
2008-02-08 04:20:54 -08:00
$ op eq '*' or $ op eq '/' or
$ op eq '%' )
2007-06-01 00:46:48 -07:00
{
2015-02-13 14:38:57 -08:00
if ( $ check ) {
if ( defined $ fix_elements [ $ n + 2 ] && $ ctx ! ~ / [ EW ] x [ EW ] / ) {
if ( CHK ( "SPACING" ,
"spaces preferred around that '$op' $at\n" . $ hereptr )) {
$ good = rtrim ( $ fix_elements [ $ n ]) . " " . trim ( $ fix_elements [ $ n + 1 ]) . " " ;
$ fix_elements [ $ n + 2 ] =~ s/^\s+// ;
$ line_fixed = 1 ;
}
} elsif (! defined $ fix_elements [ $ n + 2 ] && $ ctx ! ~ / Wx [ OE ] / ) {
if ( CHK ( "SPACING" ,
"space preferred before that '$op' $at\n" . $ hereptr )) {
$ good = rtrim ( $ fix_elements [ $ n ]) . " " . trim ( $ fix_elements [ $ n + 1 ]);
$ line_fixed = 1 ;
}
}
} elsif ( $ ctx =~ / Wx [ ^ WCE ]|[ ^ WCE ] xW/ ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"need consistent spacing around '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ]) . " " . trim ( $ fix_elements [ $ n + 1 ]) . " " ;
if ( defined $ fix_elements [ $ n + 2 ]) {
$ fix_elements [ $ n + 2 ] =~ s/^\s+// ;
}
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-06-01 00:46:48 -07:00
}
2008-07-23 21:29:10 -07:00
# A colon needs no spaces before when it is
# terminating a case value or a label .
} elsif ( $ opv eq ':C' || $ opv eq ':L' ) {
if ( $ ctx =~ / Wx . / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ]) . trim ( $ fix_elements [ $ n + 1 ]);
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2008-07-23 21:29:10 -07:00
}
2007-06-01 00:46:48 -07:00
# All the others need spaces both sides .
2008-03-04 14:28:20 -08:00
} elsif ( $ ctx ! ~ / [ EWC ] x [ CWE ] / ) {
2008-07-23 21:29:10 -07:00
my $ ok = 0 ;
2007-08-10 13:01:03 -07:00
# Ignore email addresses < foo@bar >
2008-07-23 21:29:10 -07:00
if (( $ op eq '<' &&
$ cc =~ /^\ S +\@\ S +>/ ) ||
( $ op eq '>' &&
$ ca =~ /<\ S +\@\ S + $ / ))
{
2020-04-06 20:11:01 -07:00
$ ok = 1 ;
2008-07-23 21:29:10 -07:00
}
2015-04-16 12:44:53 -07:00
# for asm volatile statements
# ignore a colon with another
# colon immediately before or after
if (( $ op eq ':' ) &&
( $ ca =~ /: $ / || $ cc =~ /^:/ )) {
$ ok = 1 ;
}
2013-11-12 15:10:05 -08:00
# messages are ERROR , but ?: are CHK
2008-07-23 21:29:10 -07:00
if ( $ ok == 0 ) {
2017-09-08 16:16:07 -07:00
my $ msg_level = \& ERROR ;
$ msg_level = \& CHK if (( $ op eq '?:' || $ op eq '?' || $ op eq ':' ) && $ ctx =~ / VxV / );
2013-11-12 15:10:05 -08:00
2017-09-08 16:16:07 -07:00
if ( & { $ msg_level }( "SPACING" ,
"spaces required around that '$op' $at\n" . $ hereptr )) {
2013-09-11 14:24:01 -07:00
$ good = rtrim ( $ fix_elements [ $ n ]) . " " . trim ( $ fix_elements [ $ n + 1 ]) . " " ;
if ( defined $ fix_elements [ $ n + 2 ]) {
$ fix_elements [ $ n + 2 ] =~ s/^\s+// ;
}
2013-07-03 15:05:31 -07:00
$ line_fixed = 1 ;
}
2007-08-10 13:01:03 -07:00
}
2007-06-01 00:46:48 -07:00
}
2007-06-08 13:46:39 -07:00
$ off += length ( $ elements [ $ n + 1 ]);
2013-07-03 15:05:31 -07:00
## print ( "n: <$n> GOOD: <$good>\n" );
$ fixed_line = $ fixed_line . $ good ;
2007-06-01 00:46:48 -07:00
}
2013-07-03 15:05:31 -07:00
if (( $ #elements % 2) == 0) {
$ fixed_line = $ fixed_line . $ fix_elements [ $ #elements ];
}
2014-08-06 16:11:03 -07:00
if ( $ fix && $ line_fixed && $ fixed_line ne $ fixed [ $ fixlinenr ]) {
$ fixed [ $ fixlinenr ] = $ fixed_line ;
2013-07-03 15:05:31 -07:00
}
2007-06-01 00:46:48 -07:00
}
2013-07-03 15:05:32 -07:00
# check for whitespace before a non - naked semicolon
2014-01-23 15:54:41 -08:00
if ( $ line =~ /^\+.*\ S \s+ ; \s* $ / ) {
2013-07-03 15:05:32 -07:00
if ( WARN ( "SPACING" ,
"space prohibited before semicolon\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
1 while $ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:32 -07:00
s/^ ( \+.*\ S ) \s+ ; / $ 1 ; / ;
}
}
2007-07-19 01:48:34 -07:00
# check for multiple assignments
if ( $ line =~ /^.\s* $ Lval \s*=\s* $ Lval \s*= ( ? ! = ) / ) {
2011-07-25 17:13:25 -07:00
CHK ( "MULTIPLE_ASSIGNMENTS" ,
"multiple assignments should be avoided\n" . $ herecurr );
2007-07-19 01:48:34 -07:00
}
2007-08-10 13:01:03 -07:00
## # check for multiple declarations , allowing for a function declaration
## # continuation .
## if ( $ line =~ /^.\s* $ Type \s+ $ Ident ( ?:\s*= [ ^ ,{] * ) ?\s* , \s* $ Ident . */ &&
## $ line ! ~ /^.\s* $ Type \s+ $ Ident ( ?:\s*= [ ^ ,{] * ) ?\s* , \s* $ Type \s* $ Ident . */ ) {
##
## # Remove any bracketed sections to ensure we do not
2020-12-15 20:44:56 -08:00
## # falsely report the parameters of functions .
2007-08-10 13:01:03 -07:00
## my $ ln = $ line ;
## while ( $ ln =~ s/\ ([ ^\ ( \ )] *\ ) // g ) {
## }
## if ( $ ln =~ / , / ) {
2011-07-25 17:13:25 -07:00
## WARN ( "MULTIPLE_DECLARATION" ,
## "declaring multiple variables together should be avoided\n" . $ herecurr );
2007-08-10 13:01:03 -07:00
## }
## }
2007-07-19 01:48:34 -07:00
2007-06-01 00:46:48 -07:00
#need space before brace following if , while , etc
2016-03-15 14:58:09 -07:00
if (( $ line =~ /\ (. *\ ) \ { / && $ line ! ~ /\ ( $ Type \ ) \ { / ) ||
2018-08-21 21:58:08 -07:00
$ line =~ /\ b ( ?:else | do ) \ { / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space required before the open brace '{'\n" . $ herecurr ) &&
$ fix ) {
2018-08-21 21:58:08 -07:00
$ fixed [ $ fixlinenr ] =~ s/^ ( \+.* ( ?:do | else | \ ))) \ { / $ 1 { / ;
2013-07-03 15:05:31 -07:00
}
2007-07-15 23:37:22 -07:00
}
2013-07-03 15:05:28 -07:00
## # check for blank lines before declarations
## if ( $ line =~ /^.\t+ $ Type \s+ $ Ident ( ?:\s*=.* ) ? ; / &&
## $ prevrawline =~ /^.\s* $ / ) {
## WARN ( "SPACING" ,
## "No blank lines before declarations\n" . $ hereprev );
## }
##
2007-07-15 23:37:22 -07:00
# closing brace should have a space following it when it has anything
# on the line
2019-09-25 16:46:47 -07:00
if ( $ line =~ / }( ? !( ?: ,|;| \ )| \ })) \ S / ) {
2013-09-11 14:23:54 -07:00
if ( ERROR ( "SPACING" ,
"space required after that close brace '}'\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-09-11 14:23:54 -07:00
s/ }(( ? !( ?: ,|;| \ ))) \ S ) / } $ 1 / ;
}
2007-06-01 00:46:48 -07:00
}
2007-08-10 13:01:03 -07:00
# check spacing on square brackets
if ( $ line =~ /\ [ \s / && $ line ! ~ /\ [ \s* $ / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited after that open square bracket '['\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/\ [ \s+/\ [ / ;
}
2007-08-10 13:01:03 -07:00
}
if ( $ line =~ /\s\ ] / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that close square bracket ']'\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/\s+\ ] /\ ] / ;
}
2007-08-10 13:01:03 -07:00
}
2008-06-05 22:46:01 -07:00
# check spacing on parentheses
2007-10-16 23:29:38 -07:00
if ( $ line =~ /\ ( \s / && $ line ! ~ /\ ( \s* ( ?:\\ ) ? $ / &&
$ line ! ~ / for\s*\ ( \s+ ; / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited after that open parenthesis '('\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/\ ( \s+/\ ( / ;
}
2007-08-10 13:01:03 -07:00
}
2008-02-08 04:22:03 -08:00
if ( $ line =~ / ( \s+ ) \ ) / && $ line ! ~ /^.\s*\ ) / &&
2008-06-05 22:46:01 -07:00
$ line ! ~ / for\s*\ (. * ; \s+\ ) / &&
$ line ! ~ /:\s+\ ) / ) {
2013-07-03 15:05:31 -07:00
if ( ERROR ( "SPACING" ,
"space prohibited before that close parenthesis ')'\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~
2013-07-03 15:05:31 -07:00
s/\s+\ ) /\ ) / ;
}
2007-08-10 13:01:03 -07:00
}
2014-08-06 16:10:48 -07:00
# check unnecessary parentheses around addressof / dereference single $ Lvals
# ie : & ( foo->bar ) should be &foo->bar and * ( foo->bar ) should be * foo->bar
while ( $ line =~ / ( ?: [ ^& ] &\s* | \* ) \ ( \s* ( $ Ident \s* ( ?: $ Member \s* ) + ) \s*\ ) / g ) {
2014-12-10 15:51:51 -08:00
my $ var = $ 1 ;
if ( CHK ( "UNNECESSARY_PARENTHESES" ,
"Unnecessary parentheses around $var\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\ ( \s*\ Q $ var\ E \s*\ ) / $ var/ ;
}
}
# check for unnecessary parentheses around function pointer uses
# ie : ( foo->bar )(); should be foo-> bar ();
# but not "if (foo->bar) (" to avoid some false positives
if ( $ line =~ / ( \bif\s* |)( \ ( \s* $ Ident \s* ( ?: $ Member \s* ) +\ ))[ \t ] *\ ( / && $ 1 ! ~ /^if/ ) {
my $ var = $ 2 ;
if ( CHK ( "UNNECESSARY_PARENTHESES" ,
"Unnecessary parentheses around function pointer $var\n" . $ herecurr ) &&
$ fix ) {
my $ var2 = deparenthesize ( $ var );
$ var2 =~ s/\s // g ;
$ fixed [ $ fixlinenr ] =~ s/\ Q $ var\ E / $ var2/ ;
}
}
2014-08-06 16:10:48 -07:00
2017-09-08 16:16:01 -07:00
# check for unnecessary parentheses around comparisons in if uses
2018-02-06 15:39:03 -08:00
# when ! drivers / staging or command - line uses --strict
if (( $ realfile ! ~ m@^ ( ?:drivers / staging/ ) @ || $ check_orig ) &&
2018-08-21 21:57:33 -07:00
$ perl_version_ok && defined ( $ stat ) &&
2017-09-08 16:16:01 -07:00
$ stat =~ / ( ^.\s * if\s* ( $ balanced_parens )) / ) {
my $ if_stat = $ 1 ;
my $ test = substr ( $ 2 , 1 , - 1 );
my $ herectx ;
while ( $ test =~ / ( ?:^ |[ ^\w\&\ ! \~ ]) +\s*\ ( \s* ([ \&\ ! \~ ] ?\s* $ Lval \s* ( ?: $ Compare \s* $ FuncArg ) ? ) \s*\ ) / g ) {
my $ match = $ 1 ;
# avoid parentheses around potential macro args
next if ( $ match =~ /^\s*\w+\s* $ / );
if (! defined ( $ herectx )) {
$ herectx = $ here . "\n" ;
my $ cnt = statement_rawlines ( $ if_stat );
for ( my $ n = 0 ; $ n < $ cnt ; $ n++ ) {
my $ rl = raw_line ( $ linenr , $ n );
$ herectx . = $ rl . "\n" ;
last if $ rl =~ /^ [ \+ ]. *\ { / ;
}
}
CHK ( "UNNECESSARY_PARENTHESES" ,
"Unnecessary parentheses around '$match'\n" . $ herectx );
}
}
2007-06-01 00:46:48 -07:00
#goto labels aren't indented, allow a single space however
2007-06-08 13:46:39 -07:00
if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
2007-06-01 00:46:48 -07:00
!($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
2013-07-03 15:05:31 -07:00
if (WARN("INDENTED_LABEL",
"labels should not be indented\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~
2013-07-03 15:05:31 -07:00
s/^(.)\s+/$1/;
}
2007-06-01 00:46:48 -07:00
}
2020-10-15 20:11:56 -07:00
# check if a statement with a comma should be two statements like:
# foo = bar(), /* comma should be semicolon */
# bar = baz();
if (defined($stat) &&
$stat =~ /^\+\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*,\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*;\s*$/) {
my $cnt = statement_rawlines($stat);
my $herectx = get_stat_here($linenr, $cnt, $here);
WARN("SUSPECT_COMMA_SEMICOLON",
"Possible comma where semicolon could be used\n" . $herectx);
}
2014-04-03 14:49:21 -07:00
# return is not a function
2013-11-12 15:10:13 -08:00
if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
2008-06-05 22:46:01 -07:00
my $spacing = $1;
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2014-04-03 14:49:21 -07:00
$stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
my $value = $1;
$value = deparenthesize($value);
if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
ERROR("RETURN_PARENTHESES",
"return is not a function, parentheses are not required\n" . $herecurr);
}
2008-06-05 22:46:01 -07:00
} elsif ($spacing !~ /\s+/) {
2011-07-25 17:13:25 -07:00
ERROR("SPACING",
"space required before the open parenthesis ' ( '\n" . $herecurr);
2008-06-05 22:46:01 -07:00
}
}
2013-11-12 15:10:13 -08:00
2014-06-23 13:22:07 -07:00
# unnecessary return in a void function
# at end-of-function, with the previous line a single leading tab, then return;
# and the line before that not a goto label target like "out:"
if ($sline =~ /^[ \+]}\s*$/ &&
$prevline =~ /^\+\treturn\s*;\s*$/ &&
$linenr >= 3 &&
$lines[$linenr - 3] =~ /^[ +]/ &&
$lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) {
2014-06-04 16:12:09 -07:00
WARN("RETURN_VOID",
2014-06-23 13:22:07 -07:00
"void function return statements are not generally useful\n" . $hereprev);
2021-02-25 17:21:47 -08:00
}
2014-06-04 16:12:09 -07:00
2014-01-23 15:54:47 -08:00
# if statements using unnecessary parentheses - ie: if ((foo == bar))
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2014-01-23 15:54:47 -08:00
$line =~ /\bif\s*((?:\(\s*){2,})/) {
my $openparens = $1;
my $count = $openparens =~ tr@\(@\(@;
my $msg = "";
if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
my $comp = $4; #Not $1 because of $LvalOrFunc
$msg = " - maybe == should be = ?" if ($comp eq "==");
WARN("UNNECESSARY_PARENTHESES",
"Unnecessary parentheses$msg\n" . $herecurr);
}
}
2015-09-09 15:37:58 -07:00
# comparisons with a constant or upper case identifier on the left
# avoid cases like "foo + BAR < baz"
# only fix matches surrounded by parentheses to avoid incorrect
# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2015-09-09 15:37:58 -07:00
$line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
my $lead = $1;
my $const = $2;
my $comp = $3;
my $to = $4;
my $newcomp = $comp;
2016-05-20 17:04:02 -07:00
if ($lead !~ /(?:$Operators|\.)\s*$/ &&
2015-09-09 15:37:58 -07:00
$to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
WARN("CONSTANT_COMPARISON",
"Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
$fix) {
if ($comp eq "<") {
$newcomp = ">";
} elsif ($comp eq "<=") {
$newcomp = ">=";
} elsif ($comp eq ">") {
$newcomp = "<";
} elsif ($comp eq ">=") {
$newcomp = "<=";
}
$fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/;
}
}
2015-04-16 12:44:19 -07:00
# Return of what appears to be an errno should normally be negative
if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
2010-10-26 14:23:14 -07:00
my $name = $1;
if ($name ne ' EOF ' && $name ne ' ERROR ') {
2011-07-25 17:13:25 -07:00
WARN("USE_NEGATIVE_ERRNO",
2015-04-16 12:44:19 -07:00
"return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
2010-10-26 14:23:14 -07:00
}
}
2008-06-05 22:46:01 -07:00
2007-06-01 00:46:48 -07:00
# Need a space before open parenthesis after if, while etc
2013-07-03 15:05:31 -07:00
if ($line =~ /\b(if|while|for|switch)\(/) {
if (ERROR("SPACING",
"space required before the open parenthesis ' ( '\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~
2013-07-03 15:05:31 -07:00
s/\b(if|while|for|switch)\(/$1 \(/;
}
2007-06-01 00:46:48 -07:00
}
2008-07-23 21:29:03 -07:00
# Check for illegal assignment in if conditional -- and check for trailing
# statements after the conditional.
2008-10-15 22:02:30 -07:00
if ($line =~ /do\s*(?!{)/) {
2012-01-10 15:10:01 -08:00
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
ctx_statement_block($linenr, $realcnt, 0)
if (!defined $stat);
2008-10-15 22:02:30 -07:00
my ($stat_next) = ctx_statement_block($line_nr_next,
$remain_next, $off_next);
$stat_next =~ s/\n./\n /g;
##print "stat<$stat> stat_next<$stat_next>\n";
if ($stat_next =~ /^\s*while\b/) {
# If the statement carries leading newlines,
# then count those as offsets.
my ($whitespace) =
($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
my $offset =
statement_rawlines($whitespace) - 1;
$suppress_whiletrailers{$line_nr_next +
$offset} = 1;
}
}
if (!defined $suppress_whiletrailers{$linenr} &&
2013-11-21 14:31:57 -08:00
defined($stat) && defined($cond) &&
2008-10-15 22:02:30 -07:00
$line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
2008-04-29 00:59:32 -07:00
my ($s, $c) = ($stat, $cond);
2007-11-28 16:21:06 -08:00
2009-01-06 14:41:29 -08:00
if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
2020-08-11 18:35:10 -07:00
if (ERROR("ASSIGN_IN_IF",
"do not use assignment in if condition\n" . $herecurr) &&
$fix && $perl_version_ok) {
if ($rawline =~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=\s*$LvalOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) {
my $space = $1;
my $not = $2;
my $statement = $3;
my $assigned = $4;
my $test = $8;
my $against = $9;
my $brace = $15;
fix_delete_line($fixlinenr, $rawline);
fix_insert_line($fixlinenr, "$space$statement;");
my $newline = "${space}if (";
$newline .= ' ! ' if defined($not);
$newline .= ' ( ' if (defined $not && defined($test) && defined($against));
$newline .= "$assigned";
$newline .= " $test $against" if (defined($test) && defined($against));
$newline .= ' ) ' if (defined $not && defined($test) && defined($against));
$newline .= ' ) ';
$newline .= " {" if (defined($brace));
fix_insert_line($fixlinenr + 1, $newline);
}
}
2007-11-28 16:21:06 -08:00
}
# Find out what is on the end of the line after the
# conditional.
2008-03-28 14:15:58 -07:00
substr($s, 0, length($c), '');
2007-11-28 16:21:06 -08:00
$s =~ s/\n.*//g;
2020-04-06 20:11:01 -07:00
$s =~ s/$;//g; # Remove any comments
2008-07-23 21:29:03 -07:00
if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
$c !~ /}\s*while\s*/)
2008-03-28 14:15:58 -07:00
{
2008-10-15 22:02:34 -07:00
# Find out how long the conditional actually is.
my @newlines = ($c =~ /\n/gs);
my $cond_lines = 1 + $#newlines;
2010-03-05 13:43:50 -08:00
my $stat_real = '';
2008-10-15 22:02:34 -07:00
2010-03-05 13:43:50 -08:00
$stat_real = raw_line($linenr, $cond_lines)
. "\n" if ($cond_lines);
2008-10-15 22:02:34 -07:00
if (defined($stat_real) && $cond_lines > 1) {
$stat_real = "[...]\n$stat_real";
}
2011-07-25 17:13:25 -07:00
ERROR("TRAILING_STATEMENTS",
"trailing statements should be on next line\n" . $herecurr . $stat_real);
2007-11-28 16:21:06 -08:00
}
}
2008-02-08 04:22:03 -08:00
# Check for bitwise tests written as boolean
if ($line =~ /
(?:
(?:\[|\(|\&\&|\|\|)
\s*0[xX][0-9]+\s*
(?:\&\&|\|\|)
|
(?:\&\&|\|\|)
\s*0[xX][0-9]+\s*
(?:\&\&|\|\||\)|\])
)/x)
{
2011-07-25 17:13:25 -07:00
WARN("HEXADECIMAL_BOOLEAN_TEST",
"boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
2008-02-08 04:22:03 -08:00
}
2007-11-28 16:21:06 -08:00
# if and else should not have general statements after it
2008-02-08 04:22:03 -08:00
if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
my $s = $1;
2020-04-06 20:11:01 -07:00
$s =~ s/$;//g; # Remove any comments
2008-02-08 04:22:03 -08:00
if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
2011-07-25 17:13:25 -07:00
ERROR("TRAILING_STATEMENTS",
"trailing statements should be on next line\n" . $herecurr);
2008-02-08 04:22:03 -08:00
}
2007-06-01 00:46:48 -07:00
}
2009-01-15 13:51:06 -08:00
# if should not continue a brace
if ($line =~ /}\s*if\b/) {
2011-07-25 17:13:25 -07:00
ERROR("TRAILING_STATEMENTS",
2014-08-06 16:10:37 -07:00
"trailing statements should be on next line (or did you mean 'else if'?)\n" .
2009-01-15 13:51:06 -08:00
$herecurr);
}
2008-10-15 22:02:25 -07:00
# case and default should not have general statements after them
if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
$line !~ /\G(?:
2008-10-15 22:02:36 -07:00
(?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
2008-10-15 22:02:25 -07:00
\s*return\s+
)/xg)
{
2011-07-25 17:13:25 -07:00
ERROR("TRAILING_STATEMENTS",
"trailing statements should be on next line\n" . $herecurr);
2008-10-15 22:02:25 -07:00
}
2007-06-01 00:46:48 -07:00
# Check for }<nl>else {, these must be at the same
# indent level to be relevant to each other.
2014-08-06 16:11:14 -07:00
if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
$previndent == $indent) {
if (ERROR("ELSE_AFTER_BRACE",
"else should follow close brace ' } '\n" . $hereprev) &&
$fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
fix_delete_line($fixlinenr - 1, $prevrawline);
fix_delete_line($fixlinenr, $rawline);
my $fixedline = $prevrawline;
$fixedline =~ s/}\s*$//;
if ($fixedline !~ /^\+\s*$/) {
fix_insert_line($fixlinenr, $fixedline);
}
$fixedline = $rawline;
$fixedline =~ s/^(.\s*)else/$1} else/;
fix_insert_line($fixlinenr, $fixedline);
}
2007-06-01 00:46:48 -07:00
}
2014-08-06 16:11:14 -07:00
if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
$previndent == $indent) {
2008-02-08 04:20:54 -08:00
my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
# Find out what is on the end of the line after the
# conditional.
2008-03-28 14:15:58 -07:00
substr($s, 0, length($c), '');
2008-02-08 04:20:54 -08:00
$s =~ s/\n.*//g;
if ($s =~ /^\s*;/) {
2014-08-06 16:11:14 -07:00
if (ERROR("WHILE_AFTER_BRACE",
"while should follow close brace ' } '\n" . $hereprev) &&
$fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
fix_delete_line($fixlinenr - 1, $prevrawline);
fix_delete_line($fixlinenr, $rawline);
my $fixedline = $prevrawline;
my $trailing = $rawline;
$trailing =~ s/^\+//;
$trailing = trim($trailing);
$fixedline =~ s/}\s*$/} $trailing/;
fix_insert_line($fixlinenr, $fixedline);
}
2008-02-08 04:20:54 -08:00
}
}
2013-07-03 15:05:20 -07:00
#Specific variable tests
2012-12-17 16:02:07 -08:00
while ($line =~ m{($Constant|$Lval)}g) {
my $var = $1;
2013-07-03 15:05:20 -07:00
#CamelCase
2013-07-03 15:05:22 -07:00
if ($var !~ /^$Constant$/ &&
2013-07-03 15:05:20 -07:00
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
2020-12-15 20:44:27 -08:00
#Ignore some autogenerated defines and enum values
$var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
2013-07-03 15:05:33 -07:00
#Ignore Page<foo> variants
2013-07-03 15:05:22 -07:00
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
2019-12-04 16:52:06 -08:00
#Ignore SI style variants like nS, mV and dB
#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
$var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
2014-12-10 15:51:54 -08:00
#Ignore some three character SI units explicitly, like MiB and KHz
$var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
2013-09-11 14:23:55 -07:00
while ($var =~ m{($Ident)}g) {
my $word = $1;
next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
2013-11-12 15:10:06 -08:00
if ($check) {
seed_camelcase_includes();
if (!$file && !$camelcase_file_seeded) {
seed_camelcase_file($realfile);
$camelcase_file_seeded = 1;
}
}
2013-09-11 14:23:55 -07:00
if (!defined $camelcase{$word}) {
$camelcase{$word} = 1;
CHK("CAMELCASE",
"Avoid CamelCase: <$word>\n" . $herecurr);
}
2013-07-03 15:05:34 -07:00
}
2012-12-17 16:02:07 -08:00
}
}
2007-06-01 00:46:48 -07:00
#no spaces allowed after \ in define
2013-09-11 14:23:54 -07:00
if ($line =~ /\#\s*define.*\\\s+$/) {
if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
"Whitespace after \\ makes next lines useless\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/\s+$//;
2013-09-11 14:23:54 -07:00
}
2007-06-01 00:46:48 -07:00
}
2015-04-16 12:44:25 -07:00
# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes
# itself <asm/foo.h> (uses RAW line)
2008-06-05 22:46:01 -07:00
if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
2008-10-15 22:02:20 -07:00
my $file = "$1.h";
my $checkfile = "include/linux/$file";
if (-f "$root/$checkfile" &&
$realfile ne $checkfile &&
2010-08-09 17:20:57 -07:00
$1 !~ /$allowed_asm_includes/)
2008-06-05 22:46:01 -07:00
{
2015-04-16 12:44:25 -07:00
my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`;
if ($asminclude > 0) {
if ($realfile =~ m{^arch/}) {
CHK("ARCH_INCLUDE_LINUX",
"Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
} else {
WARN("INCLUDE_LINUX",
"Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
}
2008-10-15 22:02:20 -07:00
}
2007-06-01 00:46:48 -07:00
}
}
2007-06-23 17:16:34 -07:00
# multi-statement macros should be enclosed in a do while loop, grab the
# first statement and ensure its the whole macro if its not enclosed
2008-03-04 14:28:20 -08:00
# in a known good container
2008-07-23 21:29:07 -07:00
if ($realfile !~ m@/vmlinux.lds.h$@ &&
$line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
2007-06-23 17:16:44 -07:00
my $ln = $linenr;
my $cnt = $realcnt;
2008-06-05 22:46:01 -07:00
my ($off, $dstat, $dcond, $rest);
my $ctx = '';
2014-10-13 15:51:55 -07:00
my $has_flow_statement = 0;
my $has_arg_concat = 0;
2008-06-05 22:46:01 -07:00
($dstat, $dcond, $ln, $cnt, $off) =
2012-01-10 15:09:54 -08:00
ctx_statement_block($linenr, $realcnt, 0);
$ctx = $dstat;
2008-06-05 22:46:01 -07:00
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
2008-07-23 21:29:00 -07:00
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
2008-06-05 22:46:01 -07:00
2014-10-13 15:51:55 -07:00
$has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
2016-01-20 14:59:18 -08:00
$has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
2014-10-13 15:51:55 -07:00
2016-10-11 13:52:08 -07:00
$dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
my $define_args = $1;
my $define_stmt = $dstat;
my @def_args = ();
if (defined $define_args && $define_args ne "") {
$define_args = substr($define_args, 1, length($define_args) - 2);
$define_args =~ s/\s*//g;
2018-08-21 21:57:43 -07:00
$define_args =~ s/\\\+?//g;
2016-10-11 13:52:08 -07:00
@def_args = split(",", $define_args);
}
2008-07-23 21:29:11 -07:00
$dstat =~ s/$;//g;
2008-06-05 22:46:01 -07:00
$dstat =~ s/\\\n.//g;
$dstat =~ s/^\s*//s;
$dstat =~ s/\s*$//s;
# Flatten any parentheses and braces
2020-10-15 20:12:22 -07:00
while ($dstat =~ s/\([^\(\)]*\)/1u/ ||
$dstat =~ s/\{[^\{\}]*\}/1u/ ||
$dstat =~ s/.\[[^\[\]]*\]/1u/)
2008-10-15 22:02:33 -07:00
{
2007-07-15 23:37:22 -07:00
}
2007-06-23 17:16:44 -07:00
2020-04-06 20:11:01 -07:00
# Flatten any obvious string concatenation.
2015-06-25 15:02:54 -07:00
while ($dstat =~ s/($String)\s*$Ident/$1/ ||
$dstat =~ s/$Ident\s*($String)/$1/)
2012-03-23 15:02:18 -07:00
{
}
2016-03-15 14:58:01 -07:00
# Make asm volatile uses seem like a generic function
$dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
2008-06-05 22:46:01 -07:00
my $exceptions = qr{
$Declare|
module_param_named|
2012-10-04 17:13:38 -07:00
MODULE_PARM_DESC|
2008-06-05 22:46:01 -07:00
DECLARE_PER_CPU|
DEFINE_PER_CPU|
2009-01-06 14:41:18 -08:00
__typeof__\(|
2010-03-05 13:43:52 -08:00
union|
struct|
2009-09-21 17:04:38 -07:00
\.$Ident\s*=\s*|
2016-01-20 14:59:21 -08:00
^\"|\"$|
^\[
2008-06-05 22:46:01 -07:00
}x;
2010-10-26 14:23:18 -07:00
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
2016-10-11 13:52:08 -07:00
$ctx =~ s/\n*$//;
my $stmt_cnt = statement_rawlines($ctx);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
2016-10-11 13:52:08 -07:00
2012-01-10 15:09:54 -08:00
if ($dstat ne '' &&
$dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
$dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
2013-07-03 15:05:27 -07:00
$dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
2014-08-06 16:10:31 -07:00
$dstat !~ /^' X '$/ && $dstat !~ /^' XX '$/ && # character constants
2012-01-10 15:09:54 -08:00
$dstat !~ /$exceptions/ &&
$dstat !~ /^\.$Ident\s*=/ && # .foo =
2013-04-17 15:58:26 -07:00
$dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
2012-01-10 15:10:06 -08:00
$dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
2020-10-15 20:12:22 -07:00
$dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...}
2012-01-10 15:09:54 -08:00
$dstat !~ /^for\s*$Constant$/ && # for (...)
$dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
$dstat !~ /^do\s*{/ && # do {...
2015-09-09 15:37:52 -07:00
$dstat !~ /^\(\{/ && # ({...
2013-09-11 14:24:00 -07:00
$ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
2012-01-10 15:09:54 -08:00
{
2017-05-08 15:55:48 -07:00
if ($dstat =~ /^\s*if\b/) {
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
"Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
} elsif ($dstat =~ /;/) {
2012-01-10 15:09:54 -08:00
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
} else {
2011-07-25 17:13:25 -07:00
ERROR("COMPLEX_MACRO",
2014-10-13 15:51:40 -07:00
"Macros with complex values should be enclosed in parentheses\n" . "$herectx");
2007-06-23 17:16:44 -07:00
}
2016-10-11 13:52:08 -07:00
}
2016-10-11 13:52:14 -07:00
# Make $define_stmt single line, comment-free, etc
my @stmt_array = split('\n', $define_stmt);
my $first = 1;
$define_stmt = "";
foreach my $l (@stmt_array) {
$l =~ s/\\$//;
if ($first) {
$define_stmt = $l;
$first = 0;
} elsif ($l =~ /^[\+ ]/) {
$define_stmt .= substr($l, 1);
}
}
$define_stmt =~ s/$;//g;
$define_stmt =~ s/\s+/ /g;
$define_stmt = trim($define_stmt);
2016-10-11 13:52:08 -07:00
# check if any macro arguments are reused (ignore ' ... ' and 'type')
foreach my $arg (@def_args) {
next if ($arg =~ /\.\.\./);
2016-10-11 13:52:11 -07:00
next if ($arg =~ /^type$/i);
2017-07-10 15:52:27 -07:00
my $tmp_stmt = $define_stmt;
2019-09-25 16:46:41 -07:00
$tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
2017-07-10 15:52:27 -07:00
$tmp_stmt =~ s/\#+\s*$arg\b//g;
$tmp_stmt =~ s/\b$arg\s*\#\#//g;
2018-05-25 14:48:04 -07:00
my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
2016-10-11 13:52:08 -07:00
if ($use_cnt > 1) {
CHK("MACRO_ARG_REUSE",
"Macro argument reuse ' $ arg' - possible side-effects?\n" . "$herectx");
2016-10-11 13:52:11 -07:00
}
# check if any macro arguments may have other precedence issues
2017-07-10 15:52:27 -07:00
if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
2016-10-11 13:52:11 -07:00
((defined($1) && $1 ne ' , ') ||
(defined($2) && $2 ne ' , '))) {
CHK("MACRO_ARG_PRECEDENCE",
"Macro argument ' $ arg' may be better as ' ( $ arg ) ' to avoid precedence issues\n" . "$herectx");
2016-10-11 13:52:08 -07:00
}
2007-06-23 17:16:34 -07:00
}
2012-12-17 16:01:47 -08:00
2014-10-13 15:51:55 -07:00
# check for macros with flow control, but without ## concatenation
# ## concatenation is commonly a macro that defines a function so ignore those
if ($has_flow_statement && !$has_arg_concat) {
my $cnt = statement_rawlines($ctx);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $cnt, $here);
2014-10-13 15:51:55 -07:00
WARN("MACRO_WITH_FLOW_CONTROL",
"Macros with flow control statements should be avoided\n" . "$herectx");
}
2012-12-17 16:01:56 -08:00
# check for line continuations outside of #defines, preprocessor #, and asm
2012-12-17 16:01:47 -08:00
} else {
if ($prevline !~ /^..*\\$/ &&
2012-12-17 16:01:56 -08:00
$line !~ /^\+\s*\#.*\\$/ && # preprocessor
$line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm
2012-12-17 16:01:47 -08:00
$line =~ /^\+.*\\$/) {
WARN("LINE_CONTINUATIONS",
"Avoid unnecessary line continuations\n" . $herecurr);
}
2007-06-01 00:46:48 -07:00
}
2012-07-30 14:41:24 -07:00
# do {} while (0) macro tests:
# single-statement macros do not need to be enclosed in do while (0) loop,
# macro should not end with a semicolon
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2012-07-30 14:41:24 -07:00
$realfile !~ m@/vmlinux.lds.h$@ &&
$line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
my $ln = $linenr;
my $cnt = $realcnt;
my ($off, $dstat, $dcond, $rest);
my $ctx = '';
($dstat, $dcond, $ln, $cnt, $off) =
ctx_statement_block($linenr, $realcnt, 0);
$ctx = $dstat;
$dstat =~ s/\\\n.//g;
2015-02-13 14:38:32 -08:00
$dstat =~ s/$;/ /g;
2012-07-30 14:41:24 -07:00
if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {
my $stmts = $2;
my $semis = $3;
$ctx =~ s/\n*$//;
my $cnt = statement_rawlines($ctx);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $cnt, $here);
2012-07-30 14:41:24 -07:00
2012-08-21 16:15:53 -07:00
if (($stmts =~ tr/;/;/) == 1 &&
$stmts !~ /^\s*(if|while|for|switch)\b/) {
2012-07-30 14:41:24 -07:00
WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",
"Single statement macros should not use a do {} while (0) loop\n" . "$herectx");
}
if (defined $semis && $semis ne "") {
WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
"do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
}
2014-06-04 16:12:06 -07:00
} elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
$ctx =~ s/\n*$//;
my $cnt = statement_rawlines($ctx);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $cnt, $here);
2014-06-04 16:12:06 -07:00
WARN("TRAILING_SEMICOLON",
"macros should not use a trailing semicolon\n" . "$herectx");
2012-07-30 14:41:24 -07:00
}
}
2007-07-19 01:48:34 -07:00
# check for redundant bracing round if etc
2008-02-08 04:22:03 -08:00
if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
my ($level, $endln, @chunks) =
2008-03-04 14:28:20 -08:00
ctx_statement_full($linenr, $realcnt, 1);
2008-02-08 04:22:03 -08:00
#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
2008-03-04 14:28:20 -08:00
#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
if ($#chunks > 0 && $level == 0) {
2012-03-23 15:02:19 -07:00
my @allowed = ();
my $allow = 0;
2008-02-08 04:22:03 -08:00
my $seen = 0;
2008-03-28 14:15:58 -07:00
my $herectx = $here . "\n";
2008-03-04 14:28:20 -08:00
my $ln = $linenr - 1;
2008-02-08 04:22:03 -08:00
for my $chunk (@chunks) {
my ($cond, $block) = @{$chunk};
2008-03-28 14:15:58 -07:00
# If the condition carries leading newlines, then count those as offsets.
my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
my $offset = statement_rawlines($whitespace) - 1;
2012-03-23 15:02:19 -07:00
$allowed[$allow] = 0;
2008-03-28 14:15:58 -07:00
#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
# We have looked at and allowed this specific line.
$suppress_ifbraces{$ln + $offset} = 1;
$herectx .= "$rawlines[$ln + $offset]\n[...]\n";
2008-03-04 14:28:20 -08:00
$ln += statement_rawlines($block) - 1;
2008-03-28 14:15:58 -07:00
substr($block, 0, length($cond), '');
2008-02-08 04:22:03 -08:00
$seen++ if ($block =~ /^\s*{/);
2012-03-23 15:02:19 -07:00
#print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
2008-03-04 14:28:20 -08:00
if (statement_lines($cond) > 1) {
#print "APW: ALLOWED: cond<$cond>\n";
2012-03-23 15:02:19 -07:00
$allowed[$allow] = 1;
2008-02-08 04:22:03 -08:00
}
if ($block =~/\b(?:if|for|while)\b/) {
2008-03-04 14:28:20 -08:00
#print "APW: ALLOWED: block<$block>\n";
2012-03-23 15:02:19 -07:00
$allowed[$allow] = 1;
2008-02-08 04:22:03 -08:00
}
2008-03-04 14:28:20 -08:00
if (statement_block_size($block) > 1) {
#print "APW: ALLOWED: lines block<$block>\n";
2012-03-23 15:02:19 -07:00
$allowed[$allow] = 1;
2008-02-08 04:22:03 -08:00
}
2012-03-23 15:02:19 -07:00
$allow++;
2008-02-08 04:22:03 -08:00
}
2012-03-23 15:02:19 -07:00
if ($seen) {
my $sum_allowed = 0;
foreach (@allowed) {
$sum_allowed += $_;
}
if ($sum_allowed == 0) {
WARN("BRACES",
"braces {} are not necessary for any arm of this statement\n" . $herectx);
} elsif ($sum_allowed != $allow &&
$seen != $allow) {
CHK("BRACES",
"braces {} should be used on all arms of this statement\n" . $herectx);
}
2008-02-08 04:22:03 -08:00
}
}
}
2008-03-28 14:15:58 -07:00
if (!defined $suppress_ifbraces{$linenr - 1} &&
2008-02-08 04:22:03 -08:00
$line =~ /\b(if|while|for|else)\b/) {
2008-03-04 14:28:20 -08:00
my $allowed = 0;
2007-07-19 01:48:34 -07:00
2008-03-04 14:28:20 -08:00
# Check the pre-context.
if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
#print "APW: ALLOWED: pre<$1>\n";
$allowed = 1;
}
2008-03-28 14:15:58 -07:00
my ($level, $endln, @chunks) =
ctx_statement_full($linenr, $realcnt, $-[0]);
2008-03-04 14:28:20 -08:00
# Check the condition.
my ($cond, $block) = @{$chunks[0]};
2008-03-28 14:15:58 -07:00
#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
2008-03-04 14:28:20 -08:00
if (defined $cond) {
2008-03-28 14:15:58 -07:00
substr($block, 0, length($cond), '');
2008-03-04 14:28:20 -08:00
}
if (statement_lines($cond) > 1) {
#print "APW: ALLOWED: cond<$cond>\n";
$allowed = 1;
}
if ($block =~/\b(?:if|for|while)\b/) {
#print "APW: ALLOWED: block<$block>\n";
$allowed = 1;
}
if (statement_block_size($block) > 1) {
#print "APW: ALLOWED: lines block<$block>\n";
$allowed = 1;
}
# Check the post-context.
if (defined $chunks[1]) {
my ($cond, $block) = @{$chunks[1]};
if (defined $cond) {
2008-03-28 14:15:58 -07:00
substr($block, 0, length($cond), '');
2007-07-19 01:48:34 -07:00
}
2008-03-04 14:28:20 -08:00
if ($block =~ /^\s*\{/) {
#print "APW: ALLOWED: chunk-1 block<$block>\n";
$allowed = 1;
}
}
if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
2008-10-15 22:02:23 -07:00
my $cnt = statement_rawlines($block);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $cnt, $here);
2008-03-04 14:28:20 -08:00
2011-07-25 17:13:25 -07:00
WARN("BRACES",
"braces {} are not necessary for single statement blocks\n" . $herectx);
2007-07-19 01:48:34 -07:00
}
}
2017-02-24 15:01:41 -08:00
# check for single line unbalanced braces
2017-02-24 15:01:43 -08:00
if ($sline =~ /^.\s*\}\s*else\s*$/ ||
$sline =~ /^.\s*else\s*\{\s*$/) {
2017-02-24 15:01:41 -08:00
CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);
}
2012-12-17 16:01:59 -08:00
# check for unnecessary blank lines around braces
2013-07-03 15:05:29 -07:00
if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
2015-02-13 14:38:46 -08:00
if (CHK("BRACES",
"Blank lines aren't necessary before a close brace '}'\n " . $ hereprev ) &&
$ fix && $ prevrawline =~ /^\+/ ) {
fix_delete_line ( $ fixlinenr - 1 , $ prevrawline );
}
2012-12-17 16:01:59 -08:00
}
2013-07-03 15:05:29 -07:00
if (( $ rawline =~ /^.\s* $ / && $ prevline =~ /^..* { \s* $ / )) {
2015-02-13 14:38:46 -08:00
if ( CHK ( "BRACES" ,
"Blank lines aren't necessary after an open brace '{'\n" . $ hereprev ) &&
$ fix ) {
fix_delete_line ( $ fixlinenr , $ rawline );
}
2012-12-17 16:01:59 -08:00
}
2007-06-08 13:46:39 -07:00
# no volatiles please
2007-10-18 03:05:08 -07:00
my $ asm_volatile = qr { \ b ( __ asm__ | asm ) \s+ ( __ volatile__ | volatile ) \b };
if ( $ line =~ /\bvolatile\b / && $ line ! ~ / $ asm_volatile/ ) {
2011-07-25 17:13:25 -07:00
WARN ( "VOLATILE" ,
2016-10-18 10:12:27 -02:00
"Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $ herecurr );
2007-06-08 13:46:39 -07:00
}
2014-12-10 15:52:05 -08:00
# Check for user - visible strings broken across lines , which breaks the ability
# to grep for the string . Make exceptions when the previous string ends in a
# newline ( multiple lines in one string constant ) or '\t' , '\r' , ';' , or '{'
# ( common in inline assembly ) or is a octal \ 123 or hexadecimal \xaf value
2015-06-25 15:02:54 -07:00
if ( $ line =~ /^\+\s* $ String / &&
2014-12-10 15:52:05 -08:00
$ prevline =~ / " \s* $ / &&
$ prevrawline ! ~ / ( ?:\\ ( ?: [ ntr ]|[ 0 - 7 ]{ 1 , 3 }| x [ 0 - 9 a - fA - F ]{ 1 , 2 })|; \s* | \ { \s* ) "\s*$/) {
if (WARN(" SPLIT_STRING ",
" quoted string split across lines\n " . $ hereprev ) &&
$ fix &&
$ prevrawline =~ /^\+.* "\s*$/ &&
$last_coalesced_string_linenr != $linenr - 1) {
my $extracted_string = get_quoted_string($line, $rawline);
my $comma_close = " " ;
if ( $ rawline =~ /\ Q $ extracted_string\ E ( \s*\ ) \s* ; \s* $ | \s* , \s* ) / ) {
$ comma_close = $ 1 ;
}
fix_delete_line ( $ fixlinenr - 1 , $ prevrawline );
fix_delete_line ( $ fixlinenr , $ rawline );
my $ fixedline = $ prevrawline ;
$ fixedline =~ s/ " \s* $ // ;
$ fixedline . = substr ( $ extracted_string , 1 ) . trim ( $ comma_close );
fix_insert_line ( $ fixlinenr - 1 , $ fixedline );
$ fixedline = $ rawline ;
$ fixedline =~ s/\ Q $ extracted_string\ E \ Q $ comma_close\ E // ;
if ( $ fixedline ! ~ /\+\s* $ / ) {
fix_insert_line ( $ fixlinenr , $ fixedline );
}
$ last_coalesced_string_linenr = $ linenr ;
}
}
# check for missing a space in a string concatenation
if ( $ prevrawline =~ / [ ^\\ ] \w "$ / && $ rawline =~ /^\+ [ \t ] + " \w/ ) {
WARN ( 'MISSING_SPACE' ,
"break quoted strings at a space character\n" . $ hereprev );
}
2017-05-08 15:55:51 -07:00
# check for an embedded function name in a string when the function is known
# This does not work very well for - f --file checking as it depends on patch
# context providing the function name or a single line form for in - file
# function declarations
2017-02-24 15:01:28 -08:00
if ( $ line =~ /^\+.* $ String / &&
defined ( $ context_function ) &&
2017-05-08 15:55:51 -07:00
get_quoted_string ( $ line , $ rawline ) =~ /\b$context_function\b / &&
length ( get_quoted_string ( $ line , $ rawline )) ! = ( length ( $ context_function ) + 2 )) {
2017-02-24 15:01:28 -08:00
WARN ( "EMBEDDED_FUNCTION_NAME" ,
2017-05-08 15:55:51 -07:00
"Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $ herecurr );
2017-02-24 15:01:28 -08:00
}
2021-02-25 17:21:50 -08:00
# check for unnecessary function tracing like uses
# This does not use $ logFunctions because there are many instances like
# 'dprintk(FOO, "%s()\n", __func__);' which do not match $ logFunctions
if ( $ rawline =~ /^\+.*\ ([ ^ "]*" $ tracing_logging_tags { 0 , 3 } %s(?:\s*\(\s*\)\s*)?$tracing_logging_tags{0,3}(?:\\n)?"\s*,\s*__func__\s*\)\s*;/) {
if ( WARN ( "TRACING_LOGGING" ,
"Unnecessary ftrace-like logging - prefer using ftrace\n" . $ herecurr ) &&
$ fix ) {
fix_delete_line ( $ fixlinenr , $ rawline );
}
}
2014-12-10 15:52:05 -08:00
# check for spaces before a quoted newline
if ( $ rawline =~ /^.*\ " . *\s\\n/ ) {
if ( WARN ( "QUOTED_WHITESPACE_BEFORE_NEWLINE" ,
"unnecessary whitespace before a quoted newline\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/^ ( \+.*\ " . * ) \s+\\n/ $ 1 \\n/ ;
}
}
2014-10-13 15:51:51 -07:00
# concatenated string without spaces between elements
2018-08-21 21:57:29 -07:00
if ( $ line =~ / $ String [ A - Za - z0 - 9 _ ] / || $ line =~ / [ A - Za - z0 - 9 _ ] $ String / ) {
if ( CHK ( "CONCATENATED_STRING" ,
"Concatenated strings should use spaces between elements\n" . $ herecurr ) &&
$ fix ) {
while ( $ line =~ / ( $ String ) / g ) {
my $ extracted_string = substr ( $ rawline , $ - [ 0 ], $ + [ 0 ] - $ - [ 0 ]);
$ fixed [ $ fixlinenr ] =~ s/\ Q $ extracted_string\ E ([ A - Za - z0 - 9 _ ]) / $ extracted_string $ 1 / ;
$ fixed [ $ fixlinenr ] =~ s/ ([ A - Za - z0 - 9 _ ]) \ Q $ extracted_string\ E / $ 1 $ extracted_string/ ;
}
}
2014-10-13 15:51:51 -07:00
}
2014-12-10 15:51:59 -08:00
# uncoalesced string fragments
2015-06-25 15:02:54 -07:00
if ( $ line =~ / $ String \s* "/) {
2018-08-21 21:57:29 -07:00
if (WARN(" STRING_FRAGMENTS ",
" Consecutive strings are generally better as a single string\n " . $herecurr) &&
$fix) {
while ($line =~ /($String)(?=\s*" ) / g ) {
my $ extracted_string = substr ( $ rawline , $ - [ 0 ], $ + [ 0 ] - $ - [ 0 ]);
$ fixed [ $ fixlinenr ] =~ s/\ Q $ extracted_string\ E \s* "/substr($extracted_string, 0, -1)/e;
}
}
2014-12-10 15:51:59 -08:00
}
2017-02-27 14:30:05 -08:00
# check for non-standard and hex prefixed decimal printf formats
my $show_L = 1; #don't show the same defect twice
my $show_Z = 1;
2014-12-10 15:52:05 -08:00
while ($line =~ /(?:^|" )([ X \t ] * )( ?: " | $ ) / g ) {
2017-02-27 14:30:05 -08:00
my $ string = substr ( $ rawline , $ - [ 1 ], $ + [ 1 ] - $ - [ 1 ]);
2014-12-10 15:52:05 -08:00
$ string =~ s/ %%/__/g;
2017-02-27 14:30:05 -08:00
# check for %L
if ( $ show_L && $ string =~ / %[\*\d\.\$]*L([diouxX])/) {
2014-12-10 15:52:05 -08:00
WARN ( "PRINTF_L" ,
2017-02-27 14:30:05 -08:00
" \ %L$1 is non-standard C, use %ll$1\n" . $herecurr);
$ show_L = 0 ;
2014-12-10 15:52:05 -08:00
}
2017-02-27 14:30:05 -08:00
# check for %Z
if ( $ show_Z && $ string =~ / %[\*\d\.\$]*Z([diouxX])/) {
WARN ( "PRINTF_Z" ,
"%Z$1 is non-standard C, use %z$1\n" . $ herecurr );
$ show_Z = 0 ;
}
# check for 0 x < decimal >
if ( $ string =~ / 0 x %[\*\d\.\$\Llzth]*[diou]/) {
ERROR ( "PRINTF_0XDECIMAL" ,
2015-09-09 15:37:47 -07:00
"Prefixing 0x with decimal output is defective\n" . $ herecurr );
}
2014-12-10 15:52:05 -08:00
}
# check for line continuations in quoted strings with odd counts of "
2018-02-06 15:38:52 -08:00
if ( $ rawline =~ /\\ $ / && $ sline =~ tr/ "/" / % 2) {
2014-12-10 15:52:05 -08:00
WARN ( "LINE_CONTINUATIONS" ,
"Avoid line continuations in quoted strings\n" . $ herecurr );
}
2007-06-08 13:47:06 -07:00
# warn about #if 0
2008-06-05 22:46:01 -07:00
if ( $ line =~ /^.\s*\#\s * if\s + 0 \b/ ) {
2018-08-21 21:57:57 -07:00
WARN ( "IF_0" ,
"Consider removing the code enclosed by this #if 0 and its #endif\n" . $ herecurr );
}
# warn about #if 1
if ( $ line =~ /^.\s*\#\s * if\s + 1 \b/ ) {
WARN ( "IF_1" ,
"Consider removing the #if 1 and its #endif\n" . $ herecurr );
2007-06-08 13:46:39 -07:00
}
2012-12-17 16:01:52 -08:00
# check for needless "if (<foo>) fn(<foo>)" uses
if ( $ prevline =~ /\bif\s*\ ( \s* ( $ Lval ) \s*\ ) / ) {
2015-09-09 15:37:36 -07:00
my $ tested = quotemeta ( $ 1 );
my $ expr = '\s*\(\s*' . $ tested . '\s*\)\s*;' ;
if ( $ line =~ /\ b ( kfree | usb_free_urb | debugfs_remove ( ?: _ recursive ) ? |( ?:kmem_cache | mempool | dma_pool ) _ destroy ) $ expr/ ) {
my $ func = $ 1 ;
if ( WARN ( 'NEEDLESS_IF' ,
"$func(NULL) is safe and this check is probably not required\n" . $ hereprev ) &&
$ fix ) {
my $ do_fix = 1 ;
my $ leading_tabs = "" ;
my $ new_leading_tabs = "" ;
if ( $ lines [ $ linenr - 2 ] =~ /^\+ ( \t* ) if\s*\ ( \s* $ tested\s*\ ) \s* $ / ) {
$ leading_tabs = $ 1 ;
} else {
$ do_fix = 0 ;
}
if ( $ lines [ $ linenr - 1 ] =~ /^\+ ( \t+ ) $ func\s*\ ( \s* $ tested\s*\ ) \s* ; \s* $ / ) {
$ new_leading_tabs = $ 1 ;
if ( length ( $ leading_tabs ) + 1 ne length ( $ new_leading_tabs )) {
$ do_fix = 0 ;
}
} else {
$ do_fix = 0 ;
}
if ( $ do_fix ) {
fix_delete_line ( $ fixlinenr - 1 , $ prevrawline );
$ fixed [ $ fixlinenr ] =~ s/^\+ $ new_leading_tabs/\+ $ leading_tabs/ ;
}
}
2008-07-23 21:29:04 -07:00
}
}
2007-07-19 01:48:34 -07:00
2014-08-06 16:10:27 -07:00
# check for unnecessary "Out of Memory" messages
if ( $ line =~ /^\+.*\b$logFunctions\s*\ ( / &&
$ prevline =~ /^ [ \+ ] \s * if\s*\ ( \s* ( \ ! \s* | NULL \s*==\s* ) ? ( $ Lval )( \s*==\s * NULL \s* ) ?\s*\ ) / &&
( defined $ 1 || defined $ 3 ) &&
$ linenr > 3 ) {
my $ testval = $ 2 ;
my $ testline = $ lines [ $ linenr - 3 ];
my ( $ s , $ c ) = ctx_statement_block ( $ linenr - 3 , $ realcnt , 0 );
# print ( "line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n" );
2019-03-07 16:28:35 -08:00
if ( $ s =~ / ( ?:^ | \n )[ \+ ] \s* ( ?: $ Type \s* ) ?\ Q $ testval\ E \s*=\s* ( ?:\ ([ ^\ )] *\ ) \s* ) ?\s* $ allocFunctions\s*\ ( / &&
$ s ! ~ /\b__GFP_NOWARN\b / ) {
2014-08-06 16:10:27 -07:00
WARN ( "OOM_MESSAGE" ,
"Possible unnecessary 'out of memory' message\n" . $ hereprev );
}
}
2014-10-13 15:52:01 -07:00
# check for logging functions with KERN_ < LEVEL >
2015-02-13 14:38:26 -08:00
if ( $ line ! ~ / printk ( ?: _ ratelimited | _ once ) ?\s*\ ( / &&
2014-10-13 15:52:01 -07:00
$ line =~ /\b$logFunctions\s*\ (. *\ b ( KERN_ [ A - Z ] + ) \b/ ) {
my $ level = $ 1 ;
if ( WARN ( "UNNECESSARY_KERN_LEVEL" ,
"Possible unnecessary $level\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\s* $ level\s*// ;
}
}
2017-02-24 15:01:31 -08:00
# check for logging continuations
if ( $ line =~ /\bprintk\s*\ ( \s * KERN_CONT \b | \bpr_cont\s*\ ( / ) {
WARN ( "LOGGING_CONTINUATION" ,
"Avoid logging continuation uses where feasible\n" . $ herecurr );
}
2020-12-15 20:45:15 -08:00
# check for unnecessary use of %h[xudi] and %hh[xudi] in logging functions
if ( defined $ stat &&
$ line =~ /\b$logFunctions\s*\ ( / &&
index ( $ stat , '"' ) >= 0 ) {
my $ lc = $ stat =~ tr@\n@@ ;
$ lc = $ lc + $ linenr ;
my $ stat_real = get_stat_real ( $ linenr , $ lc );
pos ( $ stat_real ) = index ( $ stat_real , '"' );
while ( $ stat_real =~ / [ ^\ " %]*(%[\#\d\.\*\-]*(h+)[idux])/g) {
my $ pspec = $ 1 ;
my $ h = $ 2 ;
my $ lineoff = substr ( $ stat_real , 0 , $ - [ 1 ]) =~ tr@\n@@ ;
if ( WARN ( "UNNECESSARY_MODIFIER" ,
"Integer promotion: Using '$h' in '$pspec' is unnecessary\n" . "$here\n$stat_real\n" ) &&
$ fix && $ fixed [ $ fixlinenr + $ lineoff ] =~ /^\+/ ) {
my $ nspec = $ pspec ;
$ nspec =~ s / h // g ;
$ fixed [ $ fixlinenr + $ lineoff ] =~ s/\ Q $ pspec\ E / $ nspec/ ;
}
}
}
2014-12-10 15:51:46 -08:00
# check for mask then right shift without a parentheses
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2014-12-10 15:51:46 -08:00
$ line =~ / $ LvalOrFunc \s*\&\s* ( $ LvalOrFunc ) \s*>>/ &&
$ 4 ! ~ /^\&/ ) { # $ LvalOrFunc may be &foo , ignore if so
WARN ( "MASK_THEN_SHIFT" ,
"Possible precedence defect with mask then right shift - may need parentheses\n" . $ herecurr );
}
2014-12-10 15:52:02 -08:00
# check for pointer comparisons to NULL
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok ) {
2014-12-10 15:52:02 -08:00
while ( $ line =~ /\b$LvalOrFunc\s* ( == | \ ! = ) \s * NULL \b / g ) {
my $ val = $ 1 ;
my $ equal = "!" ;
$ equal = "" if ( $ 4 eq "!=" );
if ( CHK ( "COMPARISON_TO_NULL" ,
"Comparison to NULL could be written \"${equal}${val}\"\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\b\ Q $ val\ E \s* ( ?:== | \ ! = ) \s * NULL \b/ $ equal$val/ ;
}
}
}
2013-09-11 14:24:05 -07:00
# check for bad placement of section $ InitAttribute ( e . g . : __ initdata )
if ( $ line =~ / ( \b$InitAttribute\b ) / ) {
my $ attr = $ 1 ;
if ( $ line =~ /^\+\s * static\s+ ( ?:const\s+ ) ? ( ?: $ attr\s+ ) ? ( $ NonptrTypeWithAttr ) \s+ ( ?: $ attr\s+ ) ? ( $ Ident ( ?:\ [[ ^ ]] *\ ]) ? ) \s * [ = ;] / ) {
my $ ptr = $ 1 ;
my $ var = $ 2 ;
if ((( $ ptr =~ /\ b ( union | struct ) \s+ $ attr\b / &&
ERROR ( "MISPLACED_INIT" ,
"$attr should be placed after $var\n" . $ herecurr )) ||
( $ ptr ! ~ /\ b ( union | struct ) \s+ $ attr\b / &&
WARN ( "MISPLACED_INIT" ,
"$attr should be placed after $var\n" . $ herecurr ))) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/ ( \bstatic\s+ ( ?:const\s+ ) ? )( ?: $ attr\s+ ) ? ( $ NonptrTypeWithAttr ) \s+ ( ?: $ attr\s+ ) ? ( $ Ident ( ?:\ [[ ^ ]] *\ ]) ? ) \s* ([ = ;]) \s*/ "$1" . trim ( string_find_replace ( $ 2 , " \\s* $ attr\\s* ", " ")) . " " . trim(string_find_replace($3, " \\s* $ attr\\s* ", "")) . " $ attr " . (" $ 4 " eq " ; " ? " ; " : " = ")/e;
2013-09-11 14:24:05 -07:00
}
}
}
2013-11-12 15:10:10 -08:00
# check for $InitAttributeData (ie: __initdata) with const
if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
my $attr = $1;
$attr =~ /($InitAttributePrefix)(.*)/;
my $attr_prefix = $1;
my $attr_type = $2;
if (ERROR(" INIT_ATTRIBUTE ",
" Use of const init definition must use $ { attr_prefix } initconst\n " . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~
2013-11-12 15:10:10 -08:00
s/$InitAttributeData/${attr_prefix}initconst/;
}
}
# check for $InitAttributeConst (ie: __initconst) without const
if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
my $attr = $1;
if (ERROR(" INIT_ATTRIBUTE ",
" Use of $ attr requires a separate use of const\n " . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
my $ lead = $ fixed [ $ fixlinenr ] =~
2013-11-12 15:10:10 -08:00
/ ( ^\+\s* ( ?:static\s+ )) / ;
$ lead = rtrim ( $ 1 );
$ lead = "$lead " if ( $ lead ! ~ /^\+ $ / );
$ lead = "${lead}const " ;
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/ ( ^\+\s* ( ?:static\s+ )) / $ lead/ ;
2013-11-12 15:10:10 -08:00
}
}
2015-04-16 12:44:42 -07:00
# check for __ read_mostly with const non - pointer ( should just be const )
if ( $ line =~ /\b__read_mostly\b / &&
$ line =~ / ( $ Type ) \s* $ Ident / && $ 1 ! ~ /\*\s* $ / && $ 1 =~ /\bconst\b/ ) {
if ( ERROR ( "CONST_READ_MOSTLY" ,
"Invalid use of __read_mostly with const type\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\s+ __ read_mostly\b// ;
}
}
2014-04-03 14:49:14 -07:00
# don't use __constant_<foo> functions outside of include/uapi/
if ($realfile !~ m@^include/uapi/@ &&
$line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
my $constant_func = $1;
my $func = $constant_func;
$func =~ s/^__constant_//;
if (WARN("CONSTANT_CONVERSION",
"$constant_func should be $func\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
2014-04-03 14:49:14 -07:00
}
}
2010-08-09 17:21:01 -07:00
# prefer usleep_range over udelay
2013-02-21 16:44:19 -08:00
if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
2014-04-03 14:49:11 -07:00
my $delay = $1;
2010-08-09 17:21:01 -07:00
# ignore udelay's < 10 , however
2014-04-03 14:49:11 -07:00
if (! ( $ delay < 10 ) ) {
2011-07-25 17:13:25 -07:00
CHK ( "USLEEP_RANGE" ,
2019-06-12 14:53:00 -03:00
"usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $ herecurr );
2014-04-03 14:49:11 -07:00
}
if ( $ delay > 2000 ) {
WARN ( "LONG_UDELAY" ,
"long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $ herecurr );
2010-08-09 17:21:01 -07:00
}
}
2010-08-09 17:21:02 -07:00
# warn about unexpectedly long msleep's
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
2011-07-25 17:13:25 -07:00
WARN("MSLEEP",
2019-06-12 14:53:00 -03:00
"msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
2010-08-09 17:21:02 -07:00
}
}
2013-07-03 15:05:25 -07:00
# check for comparisons of jiffies
if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
WARN("JIFFIES_COMPARISON",
"Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
}
2013-07-03 15:05:26 -07:00
# check for comparisons of get_jiffies_64()
if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
WARN("JIFFIES_COMPARISON",
"Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
}
2007-06-08 13:47:06 -07:00
# warn about #ifdefs in C files
2008-06-05 22:46:01 -07:00
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
2007-06-08 13:47:06 -07:00
# print "#ifdef in C files should be avoided\n";
# print "$herecurr";
# $clean = 0;
# }
2007-08-10 13:01:03 -07:00
# warn about spacing in #ifdefs
2008-06-05 22:46:01 -07:00
if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
2013-07-03 15:05:31 -07:00
if (ERROR("SPACING",
"exactly one space required after that #$1\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~
2013-07-03 15:05:31 -07:00
s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
}
2007-08-10 13:01:03 -07:00
}
2007-06-08 13:46:39 -07:00
# check for spinlock_t definitions without a comment.
2008-04-29 00:59:32 -07:00
if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
$line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
2007-06-08 13:46:39 -07:00
my $which = $1;
if (!ctx_has_comment($first_line, $linenr)) {
2011-07-25 17:13:25 -07:00
CHK("UNCOMMENTED_DEFINITION",
"$1 definition without comment\n" . $herecurr);
2007-06-08 13:46:39 -07:00
}
}
# check for memory barriers without a comment.
2016-01-04 09:39:01 +02:00
my $barriers = qr{
mb|
rmb|
2019-11-07 14:49:00 +00:00
wmb
2016-01-04 09:39:01 +02:00
}x;
my $barrier_stems = qr{
mb__before_atomic|
mb__after_atomic|
store_release|
load_acquire|
store_mb|
(?:$barriers)
}x;
my $all_barriers = qr{
(?:$barriers)|
2016-01-04 10:00:10 +02:00
smp_(?:$barrier_stems)|
virt_(?:$barrier_stems)
2016-01-04 09:39:01 +02:00
}x;
if ($line =~ /\b(?:$all_barriers)\s*\(/) {
2007-06-08 13:46:39 -07:00
if (!ctx_has_comment($first_line, $linenr)) {
2013-11-12 15:10:11 -08:00
WARN("MEMORY_BARRIER",
"memory barrier without comment\n" . $herecurr);
2007-06-08 13:46:39 -07:00
}
}
2015-07-02 11:55:40 -07:00
2016-01-04 09:54:51 +02:00
my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x;
if ($realfile !~ m@^include/asm-generic/@ &&
$realfile !~ m@/barrier\.h$@ &&
$line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&
$line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {
WARN("MEMORY_BARRIER",
"__smp memory barriers shouldn't be used outside barrier . h and asm - generic\n " . $ herecurr );
}
2015-06-25 15:02:46 -07:00
# check for waitqueue_active without a comment .
if ( $ line =~ /\bwaitqueue_active\s*\ ( / ) {
if (! ctx_has_comment ( $ first_line , $ linenr )) {
WARN ( "WAITQUEUE_ACTIVE" ,
"waitqueue_active without comment\n" . $ herecurr );
}
}
2015-07-02 11:55:40 -07:00
2020-04-01 12:17:14 +02:00
# check for data_race without a comment .
if ( $ line =~ /\bdata_race\s*\ ( / ) {
if (! ctx_has_comment ( $ first_line , $ linenr )) {
WARN ( "DATA_RACE" ,
"data_race without comment\n" . $ herecurr );
}
}
2007-06-08 13:46:39 -07:00
# check of hardware specific defines
2008-06-05 22:46:01 -07:00
if ( $ line =~ m@^.\s*\#\s * if . *\ b ( __ i386__ | __ powerpc64__ | __ sun__ | __ s390x__ ) \b@ && $ realfile ! ~ m@include / asm-@ ) {
2011-07-25 17:13:25 -07:00
CHK ( "ARCH_DEFINES" ,
"architecture specific defines should be avoided\n" . $ herecurr );
2007-06-01 00:46:48 -07:00
}
2007-06-23 17:16:34 -07:00
2017-07-12 14:37:02 -07:00
# check that the storage class is not after a type
if ( $ line =~ /\ b ( $ Type ) \s+ ( $ Storage ) \b/ ) {
2011-07-25 17:13:25 -07:00
WARN ( "STORAGE_CLASS" ,
2017-07-12 14:37:02 -07:00
"storage class '$2' should be located before type '$1'\n" . $ herecurr );
}
# Check that the storage class is at the beginning of a declaration
if ( $ line =~ /\b$Storage\b / &&
$ line ! ~ /^.\s* $ Storage / &&
$ line =~ /^.\s* (. +? ) \ $ Storage \s / &&
$ 1 ! ~ / [ \ , \ )] \s* $ / ) {
WARN ( "STORAGE_CLASS" ,
"storage class should be at the beginning of the declaration\n" . $ herecurr );
2010-05-24 14:33:30 -07:00
}
2007-07-15 23:37:22 -07:00
# check the location of the inline attribute , that it is between
# storage class and type .
2007-10-16 23:29:38 -07:00
if ( $ line =~ /\b$Type\s+ $ Inline \b / ||
$ line =~ /\b$Inline\s+ $ Storage \b/ ) {
2011-07-25 17:13:25 -07:00
ERROR ( "INLINE_LOCATION" ,
"inline keyword should sit between storage class and type\n" . $ herecurr );
2007-07-15 23:37:22 -07:00
}
2007-11-28 16:21:06 -08:00
# Check for __ inline__ and __ inline , prefer inline
2013-11-12 15:10:14 -08:00
if ( $ realfile ! ~ m@\binclude / uapi/@ &&
$ line =~ /\ b ( __ inline__ | __ inline ) \b/ ) {
2013-09-11 14:23:54 -07:00
if ( WARN ( "INLINE" ,
"plain inline is preferred over $1\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/\ b ( __ inline__ | __ inline ) \b / inline/ ;
2013-09-11 14:23:54 -07:00
}
2007-11-28 16:21:06 -08:00
}
2020-12-15 20:44:36 -08:00
# Check for compiler attributes
2013-11-12 15:10:14 -08:00
if ( $ realfile ! ~ m@\binclude / uapi/@ &&
2020-12-15 20:44:36 -08:00
$ rawline =~ /\b__attribute__\s*\ ( \s* ( $ balanced_parens ) \s*\ ) / ) {
my $ attr = $ 1 ;
$ attr =~ s/\s*\ ( \s* (. * ) \ ) \s*/ $ 1 / ;
2011-01-12 17:00:00 -08:00
2020-12-15 20:44:36 -08:00
my %attr_list = (
2020-12-15 20:44:50 -08:00
"alias" => "__alias" ,
2020-12-15 20:44:36 -08:00
"aligned" => "__aligned" ,
"always_inline" => "__always_inline" ,
"assume_aligned" => "__assume_aligned" ,
"cold" => "__cold" ,
"const" => "__attribute_const__" ,
"copy" => "__copy" ,
"designated_init" => "__designated_init" ,
"externally_visible" => "__visible" ,
"format" => "printf|scanf" ,
"gnu_inline" => "__gnu_inline" ,
"malloc" => "__malloc" ,
"mode" => "__mode" ,
"no_caller_saved_registers" => "__no_caller_saved_registers" ,
"noclone" => "__noclone" ,
"noinline" => "noinline" ,
"nonstring" => "__nonstring" ,
"noreturn" => "__noreturn" ,
"packed" => "__packed" ,
"pure" => "__pure" ,
2020-12-15 20:44:43 -08:00
"section" => "__section" ,
2020-12-15 20:44:50 -08:00
"used" => "__used" ,
"weak" => "__weak"
2020-12-15 20:44:36 -08:00
);
2011-07-25 17:13:24 -07:00
2020-12-15 20:44:36 -08:00
while ( $ attr =~ /\s* ( \w+ ) \s* ( $ { balanced_parens }) ?/g ) {
2020-12-15 20:44:43 -08:00
my $ orig_attr = $ 1 ;
2020-12-15 20:44:36 -08:00
my $ params = '' ;
$ params = $ 2 if defined ( $ 2 );
2020-12-15 20:44:43 -08:00
my $ curr_attr = $ orig_attr ;
2020-12-15 20:44:36 -08:00
$ curr_attr =~ s/^ [ \s_ ] + |[ \s_ ] + $ // g ;
if ( exists ( $ attr_list { $ curr_attr })) {
2020-12-15 20:44:43 -08:00
my $ new = $ attr_list { $ curr_attr };
2020-12-15 20:44:36 -08:00
if ( $ curr_attr eq "format" && $ params ) {
$ params =~ /^\s*\ ( \s* ( \w+ ) \s* , \s* (. * ) / ;
2020-12-15 20:44:43 -08:00
$ new = " __ $ 1 \ ( $ 2 ";
2020-12-15 20:44:36 -08:00
} else {
2020-12-15 20:44:43 -08:00
$new = " $ new$params ";
}
if (WARN(" PREFER_DEFINED_ATTRIBUTE_MACRO ",
" Prefer $ new over __ attribute__ (( $ orig_attr$params )) \n " . $herecurr) &&
$fix) {
my $remove = " \ Q $ orig_attr\ E " . '\s*' . " \ Q $ params\ E " . '(?:\s*,\s*)?' ;
$ fixed [ $ fixlinenr ] =~ s/ $ remove// ;
$ fixed [ $ fixlinenr ] =~ s/\b__attribute__/ $ new __ attribute__/ ;
$ fixed [ $ fixlinenr ] =~ s/\ } \ Q $ new\ E / } $ new/ ;
$ fixed [ $ fixlinenr ] =~ s / __ attribute__\s*\ ( \s*\ ( \s*\ ) \s*\ ) // ;
2020-12-15 20:44:36 -08:00
}
}
}
# Check for __ attribute__ unused , prefer __ always_unused or __ maybe_unused
if ( $ attr =~ /^ _ * unused/ ) {
WARN ( "PREFER_DEFINED_ATTRIBUTE_MACRO" ,
"__always_unused or __maybe_unused is preferred over __attribute__((__unused__))\n" . $ herecurr );
2013-09-11 14:23:54 -07:00
}
2012-03-23 15:02:16 -07:00
}
2014-12-10 15:51:35 -08:00
# Check for __ attribute__ weak , or __ weak declarations ( may have link issues )
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2014-12-10 15:51:35 -08:00
$ line =~ / ( ?: $ Declare | $ DeclareMisordered ) \s* $ Ident \s* $ balanced_parens\s* ( ?: $ Attribute ) ?\s* ; / &&
( $ line =~ /\b__attribute__\s*\ ( \s*\ (. *\bweak\b / ||
$ line =~ /\b__weak\b/ )) {
ERROR ( "WEAK_DECLARATION" ,
"Using weak declarations can have unintended link defects\n" . $ herecurr );
}
2016-12-12 16:46:34 -08:00
# check for c99 types like uint8_t used outside of uapi / and tools /
2015-06-25 15:02:49 -07:00
if ( $ realfile ! ~ m@\binclude / uapi/@ &&
2016-12-12 16:46:34 -08:00
$ realfile ! ~ m@\btools/@ &&
2015-06-25 15:02:49 -07:00
$ line =~ /\ b ( $ Declare ) \s* $ Ident \s * [ = ;, \ [] / ) {
my $ type = $ 1 ;
if ( $ type =~ /\ b ( $ typeC99Typedefs ) \b/ ) {
$ type = $ 1 ;
my $ kernel_type = 'u' ;
$ kernel_type = 's' if ( $ type =~ /^ _ * [ si ] / );
$ type =~ / ( \d+ ) / ;
$ kernel_type . = $ 1 ;
if ( CHK ( "PREFER_KERNEL_TYPES" ,
"Prefer kernel type '$kernel_type' over '$type'\n" . $ herecurr ) &&
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\b$type\b/ $ kernel_type/ ;
}
}
}
2016-01-20 14:59:15 -08:00
# check for cast of C90 native int or longer types constants
if ( $ line =~ / ( \ ( \s* $ C90_int_types \s*\ ) \s* )( $ Constant ) \b/ ) {
my $ cast = $ 1 ;
my $ const = $ 2 ;
2021-02-25 17:21:54 -08:00
my $ suffix = "" ;
my $ newconst = $ const ;
$ newconst =~ s/ $ { Int_type } $ // ;
$ suffix . = 'U' if ( $ cast =~ /\bunsigned\b/ );
if ( $ cast =~ /\blong\s + long\b/ ) {
$ suffix . = 'LL' ;
} elsif ( $ cast =~ /\blong\b/ ) {
$ suffix . = 'L' ;
}
2016-01-20 14:59:15 -08:00
if ( WARN ( "TYPECAST_INT_CONSTANT" ,
2021-02-25 17:21:54 -08:00
"Unnecessary typecast of c90 int constant - '$cast$const' could be '$const$suffix'\n" . $ herecurr ) &&
2016-01-20 14:59:15 -08:00
$ fix ) {
$ fixed [ $ fixlinenr ] =~ s/\ Q $ cast\ E $ const\b/ $ newconst$suffix/ ;
}
}
2010-03-05 13:43:48 -08:00
# check for sizeof ( & )
if ( $ line =~ /\bsizeof\s*\ ( \s*\&/ ) {
2011-07-25 17:13:25 -07:00
WARN ( "SIZEOF_ADDRESS" ,
"sizeof(& should be avoided\n" . $ herecurr );
2010-03-05 13:43:48 -08:00
}
2012-07-30 14:41:22 -07:00
# check for sizeof without parenthesis
if ( $ line =~ /\bsizeof\s+ (( ?:\*\s* |) $ Lval | $ Type ( ?:\s+ $ Lval |)) / ) {
2013-09-11 14:23:54 -07:00
if ( WARN ( "SIZEOF_PARENTHESIS" ,
"sizeof $1 should be sizeof($1)\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/\bsizeof\s+ (( ?:\*\s* |) $ Lval | $ Type ( ?:\s+ $ Lval |)) / "sizeof(" . trim ( $ 1 ) . ")" / ex ;
2013-09-11 14:23:54 -07:00
}
2012-07-30 14:41:22 -07:00
}
2012-12-17 16:02:00 -08:00
# check for struct spinlock declarations
if ( $ line =~ /^.\s*\bstruct\s + spinlock\s+\w+\s* ; / ) {
WARN ( "USE_SPINLOCK_T" ,
"struct spinlock should be spinlock_t\n" . $ herecurr );
}
2013-04-29 16:18:13 -07:00
# check for seq_printf uses that could be seq_puts
2013-11-12 15:10:07 -08:00
if ( $ sline =~ /\bseq_printf\s*\ (. * " \s*\ ) \s* ; \s* $ / ) {
2013-04-29 16:18:13 -07:00
my $ fmt = get_quoted_string ( $ line , $ rawline );
2015-02-13 14:38:49 -08:00
$ fmt =~ s/ %%//g;
if ( $ fmt ! ~ / %/) {
2013-09-11 14:23:54 -07:00
if ( WARN ( "PREFER_SEQ_PUTS" ,
"Prefer seq_puts to seq_printf\n" . $ herecurr ) &&
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/\bseq_printf\b / seq_puts/ ;
2013-09-11 14:23:54 -07:00
}
2013-04-29 16:18:13 -07:00
}
}
2018-04-10 16:33:34 -07:00
# check for vsprintf extension %p<foo> misuses
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2017-05-08 15:55:36 -07:00
defined $ stat &&
$ stat =~ /^\+ ( ? ![ ^\ {] *\ { \s* ). *\ b ( \w+ ) \s*\ (. * $ String \s* , / s &&
$ 1 ! ~ /^ _ * volatile_* $ / ) {
2018-04-10 16:33:31 -07:00
my $ stat_real ;
2017-05-08 15:55:36 -07:00
my $ lc = $ stat =~ tr@\n@@ ;
$ lc = $ lc + $ linenr ;
for ( my $ count = $ linenr ; $ count <= $ lc ; $ count++ ) {
2018-07-13 16:59:23 -07:00
my $ specifier ;
my $ extension ;
2019-10-03 15:32:18 +03:00
my $ qualifier ;
2018-07-13 16:59:23 -07:00
my $ bad_specifier = "" ;
2017-05-08 15:55:36 -07:00
my $ fmt = get_quoted_string ( $ lines [ $ count - 1 ], raw_line ( $ count , 0 ));
$ fmt =~ s/ %%//g;
2018-04-10 16:33:20 -07:00
2019-10-03 15:32:18 +03:00
while ( $ fmt =~ / ( \ %[\*\d\.]*p(\w)(\w*))/g) {
2018-04-10 16:33:31 -07:00
$ specifier = $ 1 ;
$ extension = $ 2 ;
2019-10-03 15:32:18 +03:00
$ qualifier = $ 3 ;
2019-11-26 19:45:12 -08:00
if ( $ extension ! ~ / [ SsBKRraEehMmIiUDdgVCbGNOxtf ] / ||
2019-10-03 15:32:18 +03:00
( $ extension eq "f" &&
defined $ qualifier && $ qualifier ! ~ /^w/ )) {
2018-04-10 16:33:31 -07:00
$ bad_specifier = $ specifier ;
last ;
}
if ( $ extension eq "x" && ! defined ( $ stat_real )) {
if (! defined ( $ stat_real )) {
$ stat_real = get_stat_real ( $ linenr , $ lc );
}
WARN ( "VSPRINTF_SPECIFIER_PX" ,
" Using vsprintf specifier '\%px' potentially exposes the kernel memory layout , if you don't really need the address please consider using '\ %p'.\n" . "$here\n$stat_real\n");
}
}
if ( $ bad_specifier ne "" ) {
my $ stat_real = get_stat_real ( $ linenr , $ lc );
my $ ext_type = "Invalid" ;
my $ use = "" ;
if ( $ bad_specifier =~ / p [ Ff ] / ) {
$ use = " - use %pS instead" ;
$ use =~ s / pS / ps / if ( $ bad_specifier =~ / pf/ );
}
WARN ( "VSPRINTF_POINTER_EXTENSION" ,
"$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n" );
}
2017-05-08 15:55:36 -07:00
}
}
2012-01-10 15:09:57 -08:00
# Check for misused memsets
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2012-03-23 15:02:16 -07:00
defined $ stat &&
2015-06-25 15:03:16 -07:00
$ stat =~ /^\+ ( ?:.*? ) \bmemset\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s*\ , \s* $ FuncArg \s*\ ) / ) {
2012-01-10 15:09:58 -08:00
my $ ms_addr = $ 2 ;
2012-03-23 15:02:16 -07:00
my $ ms_val = $ 7 ;
my $ ms_size = $ 12 ;
2012-01-10 15:09:57 -08:00
if ( $ ms_size =~ /^ ( 0 x |) 0 $ / i ) {
ERROR ( "MEMSET" ,
2012-01-10 15:09:58 -08:00
"memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n" );
2012-01-10 15:09:57 -08:00
} elsif ( $ ms_size =~ /^ ( 0 x |) 1 $ / i ) {
WARN ( "MEMSET" ,
2012-01-10 15:09:58 -08:00
"single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n" );
}
}
2014-01-23 15:54:52 -08:00
# Check for memcpy ( foo , bar , ETH_ALEN ) that could be ether_addr_copy ( foo , bar )
2018-08-21 21:57:33 -07:00
# if ( $ perl_version_ok &&
2016-10-11 13:51:53 -07:00
# defined $ stat &&
# $ stat =~ /^\+ ( ?:.*? ) \bmemcpy\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s*\ , \s * ETH_ALEN \s*\ ) / ) {
# if ( WARN ( "PREFER_ETHER_ADDR_COPY" ,
# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n" ) &&
# $ fix ) {
# $ fixed [ $ fixlinenr ] =~ s/\bmemcpy\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s*\ , \s * ETH_ALEN \s*\ ) / ether_addr_copy ( $ 2 , $ 7 ) / ;
# }
# }
2014-01-23 15:54:52 -08:00
2015-06-25 15:03:13 -07:00
# Check for memcmp ( foo , bar , ETH_ALEN ) that could be ether_addr_equal* ( foo , bar )
2018-08-21 21:57:33 -07:00
# if ( $ perl_version_ok &&
2016-10-11 13:51:53 -07:00
# defined $ stat &&
# $ stat =~ /^\+ ( ?:.*? ) \bmemcmp\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s*\ , \s * ETH_ALEN \s*\ ) / ) {
# WARN ( "PREFER_ETHER_ADDR_EQUAL" ,
# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n" )
# }
2015-06-25 15:03:13 -07:00
2015-06-25 15:03:19 -07:00
# check for memset ( foo , 0x0 , ETH_ALEN ) that could be eth_zero_addr
# check for memset ( foo , 0xFF , ETH_ALEN ) that could be eth_broadcast_addr
2018-08-21 21:57:33 -07:00
# if ( $ perl_version_ok &&
2016-10-11 13:51:53 -07:00
# defined $ stat &&
# $ stat =~ /^\+ ( ?:.*? ) \bmemset\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s*\ , \s * ETH_ALEN \s*\ ) / ) {
#
# my $ ms_val = $ 7 ;
#
# if ( $ ms_val =~ /^ ( ?: 0 x |) 0 + $ / i ) {
# if ( WARN ( "PREFER_ETH_ZERO_ADDR" ,
# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n" ) &&
# $ fix ) {
# $ fixed [ $ fixlinenr ] =~ s/\bmemset\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s* , \s * ETH_ALEN \s*\ ) / eth_zero_addr ( $ 2 ) / ;
# }
# } elsif ( $ ms_val =~ /^ ( ?: 0xff | 255 ) $ / i ) {
# if ( WARN ( "PREFER_ETH_BROADCAST_ADDR" ,
# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n" ) &&
# $ fix ) {
# $ fixed [ $ fixlinenr ] =~ s/\bmemset\s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s* , \s * ETH_ALEN \s*\ ) / eth_broadcast_addr ( $ 2 ) / ;
# }
# }
# }
2015-06-25 15:03:19 -07:00
2020-12-29 15:14:31 -08:00
# strlcpy uses that should likely be strscpy
if ( $ line =~ /\bstrlcpy\s*\ ( / ) {
WARN ( "STRLCPY" ,
" Prefer strscpy over strlcpy - see : https : // lore . kernel . org / r / CAHk -=wgfRnXz0W3D37d01q3JFkr_i_uTL = V6A6G1oUZcprmknw \@mail . gmail . com/\n " . $ herecurr );
}
2012-01-10 15:09:58 -08:00
# typecasts on min / max could be min_t / max_t
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2012-03-23 15:02:16 -07:00
defined $ stat &&
2012-01-10 15:09:58 -08:00
$ stat =~ /^\+ ( ?:.*? ) \ b ( min | max ) \s*\ ( \s* $ FuncArg \s* , \s* $ FuncArg \s*\ ) / ) {
2012-03-23 15:02:16 -07:00
if ( defined $ 2 || defined $ 7 ) {
2012-01-10 15:09:58 -08:00
my $ call = $ 1 ;
my $ cast1 = deparenthesize ( $ 2 );
my $ arg1 = $ 3 ;
2012-03-23 15:02:16 -07:00
my $ cast2 = deparenthesize ( $ 7 );
my $ arg2 = $ 8 ;
2012-01-10 15:09:58 -08:00
my $ cast ;
2012-03-23 15:02:16 -07:00
if ( $ cast1 ne "" && $ cast2 ne "" && $ cast1 ne $ cast2 ) {
2012-01-10 15:09:58 -08:00
$ cast = "$cast1 or $cast2" ;
} elsif ( $ cast1 ne "" ) {
$ cast = $ cast1 ;
} else {
$ cast = $ cast2 ;
}
WARN ( "MINMAX" ,
"$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n" );
2012-01-10 15:09:57 -08:00
}
}
2012-07-30 14:41:20 -07:00
# check usleep_range arguments
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2012-07-30 14:41:20 -07:00
defined $ stat &&
$ stat =~ /^\+ ( ?:.*? ) \busleep_range\s*\ ( \s* ( $ FuncArg ) \s* , \s* ( $ FuncArg ) \s*\ ) / ) {
my $ min = $ 1 ;
my $ max = $ 7 ;
if ( $ min eq $ max ) {
WARN ( "USLEEP_RANGE" ,
2019-06-12 14:53:00 -03:00
"usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n" );
2012-07-30 14:41:20 -07:00
} elsif ( $ min =~ /^\d+ $ / && $ max =~ /^\d+ $ / &&
$ min > $ max ) {
WARN ( "USLEEP_RANGE" ,
2019-06-12 14:53:00 -03:00
"usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n" );
2012-07-30 14:41:20 -07:00
}
}
2013-11-12 15:10:15 -08:00
# check for naked sscanf
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2013-11-12 15:10:15 -08:00
defined $ stat &&
2014-04-03 14:49:16 -07:00
$ line =~ /\bsscanf\b / &&
2013-11-12 15:10:15 -08:00
( $ stat ! ~ / $ Ident \s*=\s * sscanf\s* $ balanced_parens / &&
$ stat ! ~ /\bsscanf\s* $ balanced_parens\s* ( ?: $ Compare ) / &&
$ stat ! ~ / ( ?: $ Compare ) \s*\bsscanf\s* $ balanced_parens/ )) {
my $ lc = $ stat =~ tr@\n@@ ;
$ lc = $ lc + $ linenr ;
2018-04-10 16:33:20 -07:00
my $ stat_real = get_stat_real ( $ linenr , $ lc );
2013-11-12 15:10:15 -08:00
WARN ( "NAKED_SSCANF" ,
"unchecked sscanf return value\n" . "$here\n$stat_real\n" );
}
2014-06-04 16:12:08 -07:00
# check for simple sscanf that should be kstrto < foo >
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2014-06-04 16:12:08 -07:00
defined $ stat &&
$ line =~ /\bsscanf\b/ ) {
my $ lc = $ stat =~ tr@\n@@ ;
$ lc = $ lc + $ linenr ;
2018-04-10 16:33:20 -07:00
my $ stat_real = get_stat_real ( $ linenr , $ lc );
2014-06-04 16:12:08 -07:00
if ( $ stat_real =~ /\bsscanf\b\s*\ ( \s* $ FuncArg \s* , \s* ( "[^" ] + ")/) {
my $format = $6;
my $count = $format =~ tr@%@%@;
if ($count == 1 &&
$format =~ /^" \ %(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {
WARN ( "SSCANF_TO_KSTRTO" ,
"Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n" );
}
}
}
2013-09-11 14:23:58 -07:00
# check for new externs in . h files .
if ( $ realfile =~ /\.h$ / &&
$ line =~ /^\+\s* ( extern\s+ ) $ Type \s* $ Ident \s*\ ( / s ) {
2013-09-24 15:27:46 -07:00
if ( CHK ( "AVOID_EXTERNS" ,
"extern prototypes should be avoided in .h files\n" . $ herecurr ) &&
2013-09-11 14:23:58 -07:00
$ fix ) {
2014-08-06 16:11:03 -07:00
$ fixed [ $ fixlinenr ] =~ s/ (. * ) \bextern\b\s* (. * ) / $ 1 $ 2 / ;
2013-09-11 14:23:58 -07:00
}
}
2007-07-15 23:37:22 -07:00
# check for new externs in . c files .
2008-04-29 00:59:32 -07:00
if ( $ realfile =~ /\.c$ / && defined $ stat &&
2008-06-05 22:46:01 -07:00
$ stat =~ /^.\s* ( ?:extern\s+ ) ? $ Type \s+ ( $ Ident )( \s* ) \ ( / s )
2008-04-29 00:59:32 -07:00
{
2008-06-05 22:46:01 -07:00
my $ function_name = $ 1 ;
my $ paren_space = $ 2 ;
2008-04-29 00:59:32 -07:00
my $ s = $ stat ;
if ( defined $ cond ) {
substr ( $ s , 0 , length ( $ cond ), '' );
}
2020-06-03 14:18:09 -07:00
if ( $ s =~ /^\s* ; / )
2008-06-05 22:46:01 -07:00
{
2011-07-25 17:13:25 -07:00
WARN ( "AVOID_EXTERNS" ,
"externs should be avoided in .c files\n" . $ herecurr );
2008-04-29 00:59:32 -07:00
}
if ( $ paren_space =~ /\n/ ) {
2011-07-25 17:13:25 -07:00
WARN ( "FUNCTION_ARGUMENTS" ,
"arguments for function declarations should follow identifier\n" . $ herecurr );
2008-04-29 00:59:32 -07:00
}
2008-04-29 00:59:33 -07:00
} elsif ( $ realfile =~ /\.c$ / && defined $ stat &&
$ stat =~ /^.\s * extern\s+/ )
{
2011-07-25 17:13:25 -07:00
WARN ( "AVOID_EXTERNS" ,
"externs should be avoided in .c files\n" . $ herecurr );
2007-07-15 23:37:22 -07:00
}
2017-07-10 15:52:19 -07:00
# check for function declarations that have arguments without identifier names
if ( defined $ stat &&
2020-06-03 14:18:09 -07:00
$ stat =~ /^.\s* ( ?:extern\s+ ) ? $ Type \s* ( ?: $ Ident | \ ( \s*\*\s* $ Ident \s*\ )) \s*\ ( \s* ([ ^ {] + ) \s*\ ) \s* ; / s &&
$ 1 ne "void" ) {
my $ args = trim ( $ 1 );
2016-10-11 13:52:16 -07:00
while ( $ args =~ m/\s* ( $ Type \s* ( ?: $ Ident | \ ( \s*\*\s* $ Ident ?\s*\ ) \s* $ balanced_parens ) ? ) / g ) {
my $ arg = trim ( $ 1 );
2020-06-03 14:18:09 -07:00
if ( $ arg =~ /^ $ Type $ / && $ arg ! ~ / enum\s+ $ Ident $ / ) {
2016-10-11 13:52:16 -07:00
WARN ( "FUNCTION_ARGUMENTS" ,
"function definition argument '$arg' should also have an identifier name\n" . $ herecurr );
}
}
}
2017-07-10 15:52:19 -07:00
# check for function definitions
2018-08-21 21:57:33 -07:00
if ( $ perl_version_ok &&
2017-07-10 15:52:19 -07:00
defined $ stat &&
$ stat =~ /^.\s* ( ?: $ Storage \s+ ) ? $ Type \s* ( $ Ident ) \s* $ balanced_parens\s* { / s ) {
$ context_function = $ 1 ;
# check for multiline function definition with misplaced open brace
my $ ok = 0 ;
my $ cnt = statement_rawlines ( $ stat );
my $ herectx = $ here . "\n" ;
for ( my $ n = 0 ; $ n < $ cnt ; $ n++ ) {
my $ rl = raw_line ( $ linenr , $ n );
$ herectx . = $ rl . "\n" ;
$ ok = 1 if ( $ rl =~ /^ [ \+ ] \ { / );
$ ok = 1 if ( $ rl =~ /\ { / && $ n == 0 );
last if $ rl =~ /^ [ \+ ]. *\ { / ;
}
if (! $ ok ) {
ERROR ( "OPEN_BRACE" ,
"open brace '{' following function definitions go on the next line\n" . $ herectx );
}
}
2007-07-15 23:37:22 -07:00
# checks for new __ setup's
if ($rawline =~ /\b__setup\("([^"]*)"/) {
my $name = $1;
if (!grep(/$name/, @setup_docs)) {
2011-07-25 17:13:25 -07:00
CHK("UNDOCUMENTED_SETUP",
2020-06-10 18:41:38 -07:00
"__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);
2007-07-15 23:37:22 -07:00
}
2007-06-23 17:16:34 -07:00
}
2007-10-16 23:29:38 -07:00
2019-03-07 16:28:35 -08:00
# check for pointless casting of alloc functions
if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
2011-07-25 17:13:25 -07:00
WARN("UNNECESSARY_CASTS",
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
2007-10-16 23:29:38 -07:00
}
2008-02-08 04:22:03 -08:00
2013-07-03 15:05:21 -07:00
# alloc style
# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2019-03-07 16:28:35 -08:00
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
2013-07-03 15:05:21 -07:00
CHK("ALLOC_SIZEOF_STRUCT",
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
2014-06-04 16:12:07 -07:00
# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2017-05-08 15:55:57 -07:00
defined $stat &&
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
2014-06-04 16:12:07 -07:00
my $oldfunc = $3;
my $a1 = $4;
my $a2 = $10;
my $newfunc = "kmalloc_array";
$newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
2014-08-06 16:10:55 -07:00
my $r1 = $a1;
my $r2 = $a2;
if ($a1 =~ /^sizeof\s*\S/) {
$r1 = $a2;
$r2 = $a1;
}
if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
!($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
2017-05-08 15:55:57 -07:00
my $cnt = statement_rawlines($stat);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $cnt, $here);
2014-06-04 16:12:07 -07:00
if (WARN("ALLOC_WITH_MULTIPLY",
2017-05-08 15:55:57 -07:00
"Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
$cnt == 1 &&
2014-06-04 16:12:07 -07:00
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ' , ' . trim($r2)/e;
2014-06-04 16:12:07 -07:00
}
}
}
2013-04-29 16:18:12 -07:00
# check for krealloc arg reuse
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2018-08-21 21:57:50 -07:00
$line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
$1 eq $3) {
2013-04-29 16:18:12 -07:00
WARN("KREALLOC_ARG_REUSE",
"Reusing the krealloc arg is almost always a bug\n" . $herecurr);
}
2013-02-21 16:44:18 -08:00
# check for alloc argument mismatch
if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) {
WARN("ALLOC_ARRAY_ARGS",
"$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
}
2011-01-12 16:59:56 -08:00
# check for multiple semicolons
if ($line =~ /;\s*;\s*$/) {
2013-09-11 14:23:54 -07:00
if (WARN("ONE_SEMICOLON",
"Statements terminations use 1 semicolon\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
2013-09-11 14:23:54 -07:00
}
2012-12-17 16:02:01 -08:00
}
2016-08-02 14:04:39 -07:00
# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
if ($realfile !~ m@^include/uapi/@ &&
$line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
2014-12-10 15:51:57 -08:00
my $ull = "";
$ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
if (CHK("BIT_MACRO",
"Prefer using the BIT$ull macro\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/;
}
}
2020-08-11 18:35:07 -07:00
# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
2020-10-15 20:11:49 -07:00
if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) {
2020-08-11 18:35:07 -07:00
WARN("IS_ENABLED_CONFIG",
2020-10-15 20:11:49 -07:00
"IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr);
2020-08-11 18:35:07 -07:00
}
2016-05-20 17:04:00 -07:00
# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
2020-10-15 20:11:49 -07:00
if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
2016-05-20 17:04:00 -07:00
my $config = $1;
if (WARN("PREFER_IS_ENABLED",
2020-10-15 20:11:49 -07:00
"Prefer IS_ENABLED(<FOO>) to ${CONFIG_}<FOO> || ${CONFIG_}<FOO>_MODULE\n" . $herecurr) &&
2016-05-20 17:04:00 -07:00
$fix) {
$fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
}
}
2020-04-06 20:10:58 -07:00
# check for /* fallthrough */ like comment, prefer fallthrough;
my @fallthroughs = (
'fallthrough',
'@fallthrough@',
'lint - fallthrough [ \t ] *',
' intentional ( ?:ly ) ? [ \t ] * fall ( ?: ( ?:s | | - )[ Tt ]| t ) hr ( ?:ough | u | ew ) ',
' ( ?:else , ?\s* ) ? FALL ( ?: S | | - ) ? THR ( ?: OUGH | U | EW )[ \t .!] * ( ?:- [ ^\n\r ] * ) ?',
' Fall ( ?: ( ?:s | | - )[ Tt ]| t ) hr ( ?:ough | u | ew )[ \t .!] * ( ?:- [ ^\n\r ] * ) ?',
' fall ( ?:s | | - ) ? thr ( ?:ough | u | ew )[ \t .!] * ( ?:- [ ^\n\r ] * ) ?',
);
if ($raw_comment ne '') {
foreach my $ft (@fallthroughs) {
if ($raw_comment =~ /$ft/) {
my $msg_level = \&WARN;
$msg_level = \&CHK if ($file);
&{$msg_level}("PREFER_FALLTHROUGH",
"Prefer 'fallthrough ; ' over fallthrough comment\n" . $herecurr);
last;
}
}
}
2012-12-17 16:02:01 -08:00
# check for switch/default statements without a break;
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2012-12-17 16:02:01 -08:00
defined $stat &&
$stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
my $cnt = statement_rawlines($stat);
2018-04-10 16:33:27 -07:00
my $herectx = get_stat_here($linenr, $cnt, $here);
2012-12-17 16:02:01 -08:00
WARN("DEFAULT_NO_BREAK",
"switch default: should use break\n" . $herectx);
2011-01-12 16:59:56 -08:00
}
2008-02-08 04:22:03 -08:00
# check for gcc specific __FUNCTION__
2013-09-11 14:23:54 -07:00
if ($line =~ /\b__FUNCTION__\b/) {
if (WARN("USE_FUNC",
"__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) &&
$fix) {
2014-08-06 16:11:03 -07:00
$fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
2013-09-11 14:23:54 -07:00
}
2008-02-08 04:22:03 -08:00
}
2008-03-28 14:15:58 -07:00
2015-02-13 14:38:18 -08:00
# check for uses of __DATE__, __TIME__, __TIMESTAMP__
while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) {
ERROR("DATE_TIME",
"Use of the ' $ 1 ' macro makes the build non-deterministic\n" . $herecurr);
}
2012-03-23 15:02:20 -07:00
# check for use of yield()
if ($line =~ /\byield\s*\(\s*\)/) {
WARN("YIELD",
"Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr);
}
2013-07-03 15:05:30 -07:00
# check for comparisons against true and false
if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {
my $lead = $1;
my $arg = $2;
my $test = $3;
my $otype = $4;
my $trail = $5;
my $op = "!";
($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i);
my $type = lc($otype);
if ($type =~ /^(?:true|false)$/) {
if (("$test" eq "==" && "$type" eq "true") ||
("$test" eq "!=" && "$type" eq "false")) {
$op = "";
}
CHK("BOOL_COMPARISON",
"Using comparison to $otype is error prone\n" . $herecurr);
## maybe suggesting a correct construct would better
## "Using comparison to $otype is error prone. Perhaps use ' $ { lead } $ { op } $ { arg } $ { trail } '\n" . $herecurr);
}
}
2010-09-07 14:34:01 +00:00
# check for semaphores initialized locked
if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
2011-07-25 17:13:25 -07:00
WARN("CONSIDER_COMPLETION",
"consider using a completion\n" . $herecurr);
2008-03-28 14:15:58 -07:00
}
2012-03-23 15:02:20 -07:00
2011-10-31 17:13:10 -07:00
# recommend kstrto* over simple_strto* and strict_strto*
if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
2011-07-25 17:13:25 -07:00
WARN("CONSIDER_KSTRTO",
2011-10-31 17:13:10 -07:00
"$1 is obsolete, use k$3 instead\n" . $herecurr);
2008-03-28 14:15:58 -07:00
}
2012-03-23 15:02:20 -07:00
2014-06-04 16:12:10 -07:00
# check for __initcall(), use device_initcall() explicitly or more appropriate function please
2008-07-23 21:28:57 -07:00
if ($line =~ /^.\s*__initcall\s*\(/) {
2011-07-25 17:13:25 -07:00
WARN("USE_DEVICE_INITCALL",
2014-06-04 16:12:10 -07:00
"please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
2008-07-23 21:28:57 -07:00
}
2012-03-23 15:02:20 -07:00
2018-11-11 10:49:10 -08:00
# check for spin_is_locked(), suggest lockdep instead
if ($line =~ /\bspin_is_locked\(/) {
WARN("USE_LOCKDEP",
"Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
}
2018-09-07 15:26:18 -07:00
# check for deprecated apis
if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
my $deprecated_api = $1;
my $new_api = $deprecated_apis{$deprecated_api};
WARN("DEPRECATED_API",
"Deprecated use of ' $ deprecated_api', prefer ' $ new_api' instead\n" . $herecurr);
}
2015-02-13 14:39:05 -08:00
# check for various structs that are normally const (ops, kgdb, device_tree)
2017-05-08 15:55:45 -07:00
# and avoid what seem like struct definitions 'struct foo { '
2020-08-11 18:35:13 -07:00
if (defined($const_structs) &&
$line !~ /\bconst\b/ &&
2017-05-08 15:55:45 -07:00
$line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
2011-07-25 17:13:25 -07:00
WARN("CONST_STRUCT",
2017-05-08 15:55:45 -07:00
"struct $1 should normally be const\n" . $herecurr);
2009-01-06 14:41:29 -08:00
}
2008-03-28 14:15:58 -07:00
# use of NR_CPUS is usually wrong
# ignore definitions of NR_CPUS and usage to define arrays as likely right
2021-02-25 17:21:44 -08:00
# ignore designated initializers using NR_CPUS
2008-03-28 14:15:58 -07:00
if ($line =~ /\bNR_CPUS\b/ &&
2008-06-05 22:46:01 -07:00
$line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
$line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
2008-04-29 00:59:32 -07:00
$line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
$line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
2021-02-25 17:21:44 -08:00
$line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ &&
$line !~ /^.\s*\.\w+\s*=\s*.*\bNR_CPUS\b/)
2008-03-28 14:15:58 -07:00
{
2011-07-25 17:13:25 -07:00
WARN("NR_CPUS",
"usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
2008-03-28 14:15:58 -07:00
}
2008-04-29 00:59:33 -07:00
2013-11-12 15:10:09 -08:00
# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
ERROR("DEFINE_ARCH_HAS",
"#define of ' $ 1 ' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
}
2015-02-13 14:38:38 -08:00
# likely/unlikely comparisons similar to "(likely(foo) > 0)"
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2015-02-13 14:38:38 -08:00
$line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
WARN("LIKELY_MISUSE",
"Using $1 should generally have parentheses around the comparison\n" . $herecurr);
}
2019-09-25 16:49:25 -07:00
# nested likely/unlikely calls
if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
WARN("LIKELY_MISUSE",
"nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
}
2009-01-06 14:41:16 -08:00
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
2011-07-25 17:13:25 -07:00
ERROR("IN_ATOMIC",
"do not use in_atomic in drivers\n" . $herecurr);
2009-02-27 14:03:05 -08:00
} elsif ($realfile !~ m@^kernel/@) {
2011-07-25 17:13:25 -07:00
WARN("IN_ATOMIC",
"use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
2009-01-06 14:41:16 -08:00
}
}
2010-03-19 01:37:42 +01:00
# check for lockdep_set_novalidate_class
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
if ($realfile !~ m@^kernel/lockdep@ &&
$realfile !~ m@^include/linux/lockdep@ &&
$realfile !~ m@^drivers/base/core@) {
2011-07-25 17:13:25 -07:00
ERROR("LOCKDEP",
"lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
2010-03-19 01:37:42 +01:00
}
}
2011-01-12 16:59:59 -08:00
2015-04-16 12:44:16 -07:00
if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ ||
$line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) {
2011-07-25 17:13:25 -07:00
WARN("EXPORTED_WORLD_WRITABLE",
"Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
2011-01-12 16:59:59 -08:00
}
2014-04-03 14:49:13 -07:00
2018-02-06 15:38:55 -08:00
# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
# and whether or not function naming is typical and if
# DEVICE_ATTR permissions uses are unusual too
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2018-02-06 15:38:55 -08:00
defined $stat &&
$stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
my $var = $1;
my $perms = $2;
my $show = $3;
my $store = $4;
my $octal_perms = perms_to_octal($perms);
if ($show =~ /^${var}_show$/ &&
$store =~ /^${var}_store$/ &&
$octal_perms eq "0644") {
if (WARN("DEVICE_ATTR_RW",
"Use DEVICE_ATTR_RW\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
}
} elsif ($show =~ /^${var}_show$/ &&
$store =~ /^NULL$/ &&
$octal_perms eq "0444") {
if (WARN("DEVICE_ATTR_RO",
"Use DEVICE_ATTR_RO\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
}
} elsif ($show =~ /^NULL$/ &&
$store =~ /^${var}_store$/ &&
$octal_perms eq "0200") {
if (WARN("DEVICE_ATTR_WO",
"Use DEVICE_ATTR_WO\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
}
} elsif ($octal_perms eq "0644" ||
$octal_perms eq "0444" ||
$octal_perms eq "0200") {
my $newshow = "$show";
$newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
my $newstore = $store;
$newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
my $rename = "";
if ($show ne $newshow) {
$rename .= " ' $ show' to ' $ newshow'";
}
if ($store ne $newstore) {
$rename .= " ' $ store' to ' $ newstore'";
}
WARN("DEVICE_ATTR_FUNCTIONS",
"Consider renaming function(s)$rename\n" . $herecurr);
} else {
WARN("DEVICE_ATTR_PERMS",
"DEVICE_ATTR unusual permissions ' $ perms' used\n" . $herecurr);
}
}
2014-04-03 14:49:24 -07:00
# Mode permission misuses where it seems decimal should be octal
# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
2018-02-06 15:38:49 -08:00
# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
# specific definition of not visible in sysfs.
# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
# use the default permissions
2018-08-21 21:57:33 -07:00
if ($perl_version_ok &&
2016-10-11 13:52:19 -07:00
defined $stat &&
2014-04-03 14:49:24 -07:00
$line =~ /$mode_perms_search/) {
foreach my $entry (@mode_permission_funcs) {
my $func = $entry->[0];
my $arg_pos = $entry->[1];
2014-04-03 14:49:13 -07:00
2016-10-11 13:52:19 -07:00
my $lc = $stat =~ tr@\n@@;
$lc = $lc + $linenr;
2018-04-10 16:33:20 -07:00
my $stat_real = get_stat_real($linenr, $lc);
2016-10-11 13:52:19 -07:00
2014-04-03 14:49:24 -07:00
my $skip_args = "";
if ($arg_pos > 1) {
$arg_pos--;
$skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
}
2016-10-11 13:51:47 -07:00
my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
2016-10-11 13:52:19 -07:00
if ($stat =~ /$test/) {
2014-04-03 14:49:24 -07:00
my $val = $1;
$val = $6 if ($skip_args ne "");
2018-02-06 15:38:49 -08:00
if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
(($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
($val =~ /^$Octal$/ && length($val) ne 4))) {
2014-04-03 14:49:24 -07:00
ERROR("NON_OCTAL_PERMISSIONS",
2016-10-11 13:52:19 -07:00
"Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
2016-10-11 13:51:47 -07:00
}
if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
2015-02-13 14:38:21 -08:00
ERROR("EXPORTED_WORLD_WRITABLE",
2016-10-11 13:52:19 -07:00
"Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
2016-10-11 13:51:47 -07:00
}
2014-04-03 14:49:13 -07:00
}
}
}
2015-06-25 15:03:24 -07:00
2016-10-11 13:52:19 -07:00
# check for uses of S_<PERMS> that could be octal for readability
2018-04-10 16:33:53 -07:00
while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
2018-02-06 15:38:55 -08:00
my $oval = $1;
my $octal = perms_to_octal($oval);
2016-10-11 13:52:19 -07:00
if (WARN("SYMBOLIC_PERMS",
"Symbolic permissions ' $ oval' are not preferred. Consider using octal permissions ' $ octal'.\n" . $herecurr) &&
$fix) {
2018-02-06 15:38:55 -08:00
$fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
2016-10-11 13:52:19 -07:00
}
}
2015-06-25 15:03:24 -07:00
# validate content of MODULE_LICENSE against list from include/linux/module.h
if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
my $extracted_string = get_quoted_string($line, $rawline);
my $valid_licenses = qr{
GPL|
GPL\ v2|
GPL\ and\ additional\ rights|
Dual\ BSD/GPL|
Dual\ MIT/GPL|
Dual\ MPL/GPL|
Proprietary
}x;
if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) {
WARN("MODULE_LICENSE",
"unknown module license " . $extracted_string . "\n" . $herecurr);
}
}
2019-07-16 16:27:48 -07:00
# check for sysctl duplicate constants
if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
WARN("DUPLICATED_SYSCTL_CONST",
"duplicated sysctl range checking value ' $ 1 ', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
}
2008-02-08 04:22:03 -08:00
}
# If we have no input at all, then there is nothing to report on
# so just keep quiet.
if ($#rawlines == -1) {
exit(0);
2007-06-01 00:46:48 -07:00
}
2007-11-28 16:21:06 -08:00
# In mailback mode only produce a report in the negative, for
# things that appear to be patches.
if ($mailback && ($clean == 1 || !$is_patch)) {
exit(0);
}
2020-12-15 20:44:56 -08:00
# This is not a patch, and we are in 'no - patch' mode so
2007-11-28 16:21:06 -08:00
# just keep quiet.
if (!$chk_patch && !$is_patch) {
exit(0);
}
2017-10-03 16:16:51 -07:00
if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
2011-07-25 17:13:25 -07:00
ERROR("NOT_UNIFIED_DIFF",
"Does not appear to be a unified-diff format patch\n");
2007-06-01 00:46:48 -07:00
}
2018-08-21 21:57:40 -07:00
if ($is_patch && $has_commit_log && $chk_signoff) {
if ($signoff == 0) {
ERROR("MISSING_SIGN_OFF",
"Missing Signed-off-by: line(s)\n");
2020-10-15 20:12:28 -07:00
} elsif ($authorsignoff != 1) {
# authorsignoff values:
# 0 -> missing sign off
# 1 -> sign off identical
# 2 -> names and addresses match, comments mismatch
# 3 -> addresses match, names different
# 4 -> names match, addresses different
# 5 -> names match, addresses excluding subaddress details (refer RFC 5233) match
my $sob_msg = "' From : $ author' != ' Signed - off - by : $ author_sob'";
if ($authorsignoff == 0) {
ERROR("NO_AUTHOR_SIGN_OFF",
"Missing Signed-off-by: line by nominal patch author ' $ author'\n");
} elsif ($authorsignoff == 2) {
CHK("FROM_SIGN_OFF_MISMATCH",
"From:/Signed-off-by: email comments mismatch: $sob_msg\n");
} elsif ($authorsignoff == 3) {
WARN("FROM_SIGN_OFF_MISMATCH",
"From:/Signed-off-by: email name mismatch: $sob_msg\n");
} elsif ($authorsignoff == 4) {
WARN("FROM_SIGN_OFF_MISMATCH",
"From:/Signed-off-by: email address mismatch: $sob_msg\n");
} elsif ($authorsignoff == 5) {
WARN("FROM_SIGN_OFF_MISMATCH",
"From:/Signed-off-by: email subaddress mismatch: $sob_msg\n");
}
2018-08-21 21:57:40 -07:00
}
2007-06-01 00:46:48 -07:00
}
2007-11-28 16:21:06 -08:00
print report_dump();
2008-02-08 04:22:03 -08:00
if ($summary && !($clean == 1 && $quiet == 1)) {
print "$filename " if ($summary_file);
2007-11-28 16:21:06 -08:00
print "total: $cnt_error errors, $cnt_warn warnings, " .
(($check)? "$cnt_chk checks, " : "") .
"$cnt_lines lines checked\n";
2007-07-19 01:48:34 -07:00
}
2007-11-28 16:21:06 -08:00
2010-10-26 14:23:12 -07:00
if ($quiet == 0) {
2016-05-20 17:04:11 -07:00
# If there were any defects found and not already fixing them
if (!$clean and !$fix) {
print << "EOM"
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
EOM
}
2010-10-26 14:23:12 -07:00
# If there were whitespace errors which cleanpatch can fix
# then suggest that.
if ($rpt_cleaners) {
2011-03-22 16:34:43 -07:00
$rpt_cleaners = 0;
2015-06-25 15:03:00 -07:00
print << "EOM"
NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile
EOM
2010-10-26 14:23:12 -07:00
}
}
2014-08-06 16:11:05 -07:00
if ($clean == 0 && $fix &&
("@rawlines" ne "@fixed" ||
$#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
2014-01-23 15:54:44 -08:00
my $newfile = $filename;
$newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
2013-07-03 15:05:31 -07:00
my $linecount = 0;
my $f;
2014-08-06 16:11:05 -07:00
@fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
2013-07-03 15:05:31 -07:00
open($f, '>', $newfile)
or die "$P: Can't open $ newfile for write\n " ;
foreach my $ fixed_line ( @fixed ) {
$ linecount++ ;
if ( $ file ) {
if ( $ linecount > 3 ) {
$ fixed_line =~ s/^\+// ;
2014-08-06 16:11:05 -07:00
print $ f $ fixed_line . "\n" ;
2013-07-03 15:05:31 -07:00
}
} else {
print $ f $ fixed_line . "\n" ;
}
}
close ( $ f );
if (! $ quiet ) {
print << "EOM" ;
2015-06-25 15:03:00 -07:00
2013-07-03 15:05:31 -07:00
Wrote EXPERIMENTAL --fix correction ( s ) to '$newfile'
Do _ NOT_ trust the results written to this file .
Do _ NOT_ submit these changes without inspecting them for correctness .
This EXPERIMENTAL file is simply a convenience to help rewrite patches .
No warranties , expressed or implied ...
EOM
}
}
2015-06-25 15:03:00 -07:00
if ( $ quiet == 0 ) {
print "\n" ;
if ( $ clean == 1 ) {
print "$vname has no obvious style problems and is ready for submission.\n" ;
} else {
print "$vname has style problems, please review.\n" ;
}
2007-06-01 00:46:48 -07:00
}
return $ clean ;
}