1*4882a593Smuzhiyun#!/usr/bin/env perl 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# (c) 2001, Dave Jones. (the file handling bit) 5*4882a593Smuzhiyun# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) 6*4882a593Smuzhiyun# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) 7*4882a593Smuzhiyun# (c) 2008-2010 Andy Whitcroft <apw@canonical.com> 8*4882a593Smuzhiyun# (c) 2010-2018 Joe Perches <joe@perches.com> 9*4882a593Smuzhiyun 10*4882a593Smuzhiyunuse strict; 11*4882a593Smuzhiyunuse warnings; 12*4882a593Smuzhiyunuse POSIX; 13*4882a593Smuzhiyunuse File::Basename; 14*4882a593Smuzhiyunuse Cwd 'abs_path'; 15*4882a593Smuzhiyunuse Term::ANSIColor qw(:constants); 16*4882a593Smuzhiyunuse Encode qw(decode encode); 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunmy $P = $0; 19*4882a593Smuzhiyunmy $D = dirname(abs_path($P)); 20*4882a593Smuzhiyun 21*4882a593Smuzhiyunmy $V = '0.32'; 22*4882a593Smuzhiyun 23*4882a593Smuzhiyunuse Getopt::Long qw(:config no_auto_abbrev); 24*4882a593Smuzhiyun 25*4882a593Smuzhiyunmy $quiet = 0; 26*4882a593Smuzhiyunmy $tree = 1; 27*4882a593Smuzhiyunmy $chk_signoff = 1; 28*4882a593Smuzhiyunmy $chk_patch = 1; 29*4882a593Smuzhiyunmy $tst_only; 30*4882a593Smuzhiyunmy $emacs = 0; 31*4882a593Smuzhiyunmy $terse = 0; 32*4882a593Smuzhiyunmy $showfile = 0; 33*4882a593Smuzhiyunmy $file = 0; 34*4882a593Smuzhiyunmy $git = 0; 35*4882a593Smuzhiyunmy %git_commits = (); 36*4882a593Smuzhiyunmy $check = 0; 37*4882a593Smuzhiyunmy $check_orig = 0; 38*4882a593Smuzhiyunmy $summary = 1; 39*4882a593Smuzhiyunmy $mailback = 0; 40*4882a593Smuzhiyunmy $summary_file = 0; 41*4882a593Smuzhiyunmy $show_types = 0; 42*4882a593Smuzhiyunmy $list_types = 0; 43*4882a593Smuzhiyunmy $fix = 0; 44*4882a593Smuzhiyunmy $fix_inplace = 0; 45*4882a593Smuzhiyunmy $root; 46*4882a593Smuzhiyunmy $gitroot = $ENV{'GIT_DIR'}; 47*4882a593Smuzhiyun$gitroot = ".git" if !defined($gitroot); 48*4882a593Smuzhiyunmy %debug; 49*4882a593Smuzhiyunmy %camelcase = (); 50*4882a593Smuzhiyunmy %use_type = (); 51*4882a593Smuzhiyunmy @use = (); 52*4882a593Smuzhiyunmy %ignore_type = (); 53*4882a593Smuzhiyunmy @ignore = (); 54*4882a593Smuzhiyunmy $help = 0; 55*4882a593Smuzhiyunmy $configuration_file = ".checkpatch.conf"; 56*4882a593Smuzhiyunmy $max_line_length = 100; 57*4882a593Smuzhiyunmy $ignore_perl_version = 0; 58*4882a593Smuzhiyunmy $minimum_perl_version = 5.10.0; 59*4882a593Smuzhiyunmy $min_conf_desc_length = 4; 60*4882a593Smuzhiyunmy $spelling_file = "$D/spelling.txt"; 61*4882a593Smuzhiyunmy $codespell = 0; 62*4882a593Smuzhiyunmy $codespellfile = "/usr/share/codespell/dictionary.txt"; 63*4882a593Smuzhiyunmy $conststructsfile = "$D/const_structs.checkpatch"; 64*4882a593Smuzhiyunmy $typedefsfile; 65*4882a593Smuzhiyunmy $color = "auto"; 66*4882a593Smuzhiyunmy $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE 67*4882a593Smuzhiyun# git output parsing needs US English output, so first set backtick child process LANGUAGE 68*4882a593Smuzhiyunmy $git_command ='export LANGUAGE=en_US.UTF-8; git'; 69*4882a593Smuzhiyunmy $tabsize = 8; 70*4882a593Smuzhiyunmy ${CONFIG_} = "CONFIG_"; 71*4882a593Smuzhiyun 72*4882a593Smuzhiyunsub help { 73*4882a593Smuzhiyun my ($exitcode) = @_; 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun print << "EOM"; 76*4882a593SmuzhiyunUsage: $P [OPTION]... [FILE]... 77*4882a593SmuzhiyunVersion: $V 78*4882a593Smuzhiyun 79*4882a593SmuzhiyunOptions: 80*4882a593Smuzhiyun -q, --quiet quiet 81*4882a593Smuzhiyun --no-tree run without a kernel tree 82*4882a593Smuzhiyun --no-signoff do not check for 'Signed-off-by' line 83*4882a593Smuzhiyun --patch treat FILE as patchfile (default) 84*4882a593Smuzhiyun --emacs emacs compile window format 85*4882a593Smuzhiyun --terse one line per report 86*4882a593Smuzhiyun --showfile emit diffed file position, not input file position 87*4882a593Smuzhiyun -g, --git treat FILE as a single commit or git revision range 88*4882a593Smuzhiyun single git commit with: 89*4882a593Smuzhiyun <rev> 90*4882a593Smuzhiyun <rev>^ 91*4882a593Smuzhiyun <rev>~n 92*4882a593Smuzhiyun multiple git commits with: 93*4882a593Smuzhiyun <rev1>..<rev2> 94*4882a593Smuzhiyun <rev1>...<rev2> 95*4882a593Smuzhiyun <rev>-<count> 96*4882a593Smuzhiyun git merges are ignored 97*4882a593Smuzhiyun -f, --file treat FILE as regular source file 98*4882a593Smuzhiyun --subjective, --strict enable more subjective tests 99*4882a593Smuzhiyun --list-types list the possible message types 100*4882a593Smuzhiyun --types TYPE(,TYPE2...) show only these comma separated message types 101*4882a593Smuzhiyun --ignore TYPE(,TYPE2...) ignore various comma separated message types 102*4882a593Smuzhiyun --show-types show the specific message type in the output 103*4882a593Smuzhiyun --max-line-length=n set the maximum line length, (default $max_line_length) 104*4882a593Smuzhiyun if exceeded, warn on patches 105*4882a593Smuzhiyun requires --strict for use with --file 106*4882a593Smuzhiyun --min-conf-desc-length=n set the min description length, if shorter, warn 107*4882a593Smuzhiyun --tab-size=n set the number of spaces for tab (default $tabsize) 108*4882a593Smuzhiyun --root=PATH PATH to the kernel tree root 109*4882a593Smuzhiyun --no-summary suppress the per-file summary 110*4882a593Smuzhiyun --mailback only produce a report in case of warnings/errors 111*4882a593Smuzhiyun --summary-file include the filename in summary 112*4882a593Smuzhiyun --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of 113*4882a593Smuzhiyun 'values', 'possible', 'type', and 'attr' (default 114*4882a593Smuzhiyun is all off) 115*4882a593Smuzhiyun --test-only=WORD report only warnings/errors containing WORD 116*4882a593Smuzhiyun literally 117*4882a593Smuzhiyun --fix EXPERIMENTAL - may create horrible results 118*4882a593Smuzhiyun If correctable single-line errors exist, create 119*4882a593Smuzhiyun "<inputfile>.EXPERIMENTAL-checkpatch-fixes" 120*4882a593Smuzhiyun with potential errors corrected to the preferred 121*4882a593Smuzhiyun checkpatch style 122*4882a593Smuzhiyun --fix-inplace EXPERIMENTAL - may create horrible results 123*4882a593Smuzhiyun Is the same as --fix, but overwrites the input 124*4882a593Smuzhiyun file. It's your fault if there's no backup or git 125*4882a593Smuzhiyun --ignore-perl-version override checking of perl version. expect 126*4882a593Smuzhiyun runtime errors. 127*4882a593Smuzhiyun --codespell Use the codespell dictionary for spelling/typos 128*4882a593Smuzhiyun (default:/usr/share/codespell/dictionary.txt) 129*4882a593Smuzhiyun --codespellfile Use this codespell dictionary 130*4882a593Smuzhiyun --typedefsfile Read additional types from this file 131*4882a593Smuzhiyun --color[=WHEN] Use colors 'always', 'never', or only when output 132*4882a593Smuzhiyun is a terminal ('auto'). Default is 'auto'. 133*4882a593Smuzhiyun --kconfig-prefix=WORD use WORD as a prefix for Kconfig symbols (default 134*4882a593Smuzhiyun ${CONFIG_}) 135*4882a593Smuzhiyun -h, --help, --version display this help and exit 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunWhen FILE is - read standard input. 138*4882a593SmuzhiyunEOM 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun exit($exitcode); 141*4882a593Smuzhiyun} 142*4882a593Smuzhiyun 143*4882a593Smuzhiyunsub uniq { 144*4882a593Smuzhiyun my %seen; 145*4882a593Smuzhiyun return grep { !$seen{$_}++ } @_; 146*4882a593Smuzhiyun} 147*4882a593Smuzhiyun 148*4882a593Smuzhiyunsub list_types { 149*4882a593Smuzhiyun my ($exitcode) = @_; 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun my $count = 0; 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun local $/ = undef; 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun open(my $script, '<', abs_path($P)) or 156*4882a593Smuzhiyun die "$P: Can't read '$P' $!\n"; 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun my $text = <$script>; 159*4882a593Smuzhiyun close($script); 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun my @types = (); 162*4882a593Smuzhiyun # Also catch when type or level is passed through a variable 163*4882a593Smuzhiyun for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) { 164*4882a593Smuzhiyun push (@types, $_); 165*4882a593Smuzhiyun } 166*4882a593Smuzhiyun @types = sort(uniq(@types)); 167*4882a593Smuzhiyun print("#\tMessage type\n\n"); 168*4882a593Smuzhiyun foreach my $type (@types) { 169*4882a593Smuzhiyun print(++$count . "\t" . $type . "\n"); 170*4882a593Smuzhiyun } 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun exit($exitcode); 173*4882a593Smuzhiyun} 174*4882a593Smuzhiyun 175*4882a593Smuzhiyunmy $conf = which_conf($configuration_file); 176*4882a593Smuzhiyunif (-f $conf) { 177*4882a593Smuzhiyun my @conf_args; 178*4882a593Smuzhiyun open(my $conffile, '<', "$conf") 179*4882a593Smuzhiyun or warn "$P: Can't find a readable $configuration_file file $!\n"; 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun while (<$conffile>) { 182*4882a593Smuzhiyun my $line = $_; 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 185*4882a593Smuzhiyun $line =~ s/^\s*//g; 186*4882a593Smuzhiyun $line =~ s/\s+/ /g; 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 189*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun my @words = split(" ", $line); 192*4882a593Smuzhiyun foreach my $word (@words) { 193*4882a593Smuzhiyun last if ($word =~ m/^#/); 194*4882a593Smuzhiyun push (@conf_args, $word); 195*4882a593Smuzhiyun } 196*4882a593Smuzhiyun } 197*4882a593Smuzhiyun close($conffile); 198*4882a593Smuzhiyun unshift(@ARGV, @conf_args) if @conf_args; 199*4882a593Smuzhiyun} 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun# Perl's Getopt::Long allows options to take optional arguments after a space. 202*4882a593Smuzhiyun# Prevent --color by itself from consuming other arguments 203*4882a593Smuzhiyunforeach (@ARGV) { 204*4882a593Smuzhiyun if ($_ eq "--color" || $_ eq "-color") { 205*4882a593Smuzhiyun $_ = "--color=$color"; 206*4882a593Smuzhiyun } 207*4882a593Smuzhiyun} 208*4882a593Smuzhiyun 209*4882a593SmuzhiyunGetOptions( 210*4882a593Smuzhiyun 'q|quiet+' => \$quiet, 211*4882a593Smuzhiyun 'tree!' => \$tree, 212*4882a593Smuzhiyun 'signoff!' => \$chk_signoff, 213*4882a593Smuzhiyun 'patch!' => \$chk_patch, 214*4882a593Smuzhiyun 'emacs!' => \$emacs, 215*4882a593Smuzhiyun 'terse!' => \$terse, 216*4882a593Smuzhiyun 'showfile!' => \$showfile, 217*4882a593Smuzhiyun 'f|file!' => \$file, 218*4882a593Smuzhiyun 'g|git!' => \$git, 219*4882a593Smuzhiyun 'subjective!' => \$check, 220*4882a593Smuzhiyun 'strict!' => \$check, 221*4882a593Smuzhiyun 'ignore=s' => \@ignore, 222*4882a593Smuzhiyun 'types=s' => \@use, 223*4882a593Smuzhiyun 'show-types!' => \$show_types, 224*4882a593Smuzhiyun 'list-types!' => \$list_types, 225*4882a593Smuzhiyun 'max-line-length=i' => \$max_line_length, 226*4882a593Smuzhiyun 'min-conf-desc-length=i' => \$min_conf_desc_length, 227*4882a593Smuzhiyun 'tab-size=i' => \$tabsize, 228*4882a593Smuzhiyun 'root=s' => \$root, 229*4882a593Smuzhiyun 'summary!' => \$summary, 230*4882a593Smuzhiyun 'mailback!' => \$mailback, 231*4882a593Smuzhiyun 'summary-file!' => \$summary_file, 232*4882a593Smuzhiyun 'fix!' => \$fix, 233*4882a593Smuzhiyun 'fix-inplace!' => \$fix_inplace, 234*4882a593Smuzhiyun 'ignore-perl-version!' => \$ignore_perl_version, 235*4882a593Smuzhiyun 'debug=s' => \%debug, 236*4882a593Smuzhiyun 'test-only=s' => \$tst_only, 237*4882a593Smuzhiyun 'codespell!' => \$codespell, 238*4882a593Smuzhiyun 'codespellfile=s' => \$codespellfile, 239*4882a593Smuzhiyun 'typedefsfile=s' => \$typedefsfile, 240*4882a593Smuzhiyun 'color=s' => \$color, 241*4882a593Smuzhiyun 'no-color' => \$color, #keep old behaviors of -nocolor 242*4882a593Smuzhiyun 'nocolor' => \$color, #keep old behaviors of -nocolor 243*4882a593Smuzhiyun 'kconfig-prefix=s' => \${CONFIG_}, 244*4882a593Smuzhiyun 'h|help' => \$help, 245*4882a593Smuzhiyun 'version' => \$help 246*4882a593Smuzhiyun) or help(1); 247*4882a593Smuzhiyun 248*4882a593Smuzhiyunhelp(0) if ($help); 249*4882a593Smuzhiyun 250*4882a593Smuzhiyunlist_types(0) if ($list_types); 251*4882a593Smuzhiyun 252*4882a593Smuzhiyun$fix = 1 if ($fix_inplace); 253*4882a593Smuzhiyun$check_orig = $check; 254*4882a593Smuzhiyun 255*4882a593Smuzhiyundie "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix)); 256*4882a593Smuzhiyun 257*4882a593Smuzhiyunmy $exit = 0; 258*4882a593Smuzhiyun 259*4882a593Smuzhiyunmy $perl_version_ok = 1; 260*4882a593Smuzhiyunif ($^V && $^V lt $minimum_perl_version) { 261*4882a593Smuzhiyun $perl_version_ok = 0; 262*4882a593Smuzhiyun printf "$P: requires at least perl version %vd\n", $minimum_perl_version; 263*4882a593Smuzhiyun exit(1) if (!$ignore_perl_version); 264*4882a593Smuzhiyun} 265*4882a593Smuzhiyun 266*4882a593Smuzhiyun#if no filenames are given, push '-' to read patch from stdin 267*4882a593Smuzhiyunif ($#ARGV < 0) { 268*4882a593Smuzhiyun push(@ARGV, '-'); 269*4882a593Smuzhiyun} 270*4882a593Smuzhiyun 271*4882a593Smuzhiyunif ($color =~ /^[01]$/) { 272*4882a593Smuzhiyun $color = !$color; 273*4882a593Smuzhiyun} elsif ($color =~ /^always$/i) { 274*4882a593Smuzhiyun $color = 1; 275*4882a593Smuzhiyun} elsif ($color =~ /^never$/i) { 276*4882a593Smuzhiyun $color = 0; 277*4882a593Smuzhiyun} elsif ($color =~ /^auto$/i) { 278*4882a593Smuzhiyun $color = (-t STDOUT); 279*4882a593Smuzhiyun} else { 280*4882a593Smuzhiyun die "$P: Invalid color mode: $color\n"; 281*4882a593Smuzhiyun} 282*4882a593Smuzhiyun 283*4882a593Smuzhiyun# skip TAB size 1 to avoid additional checks on $tabsize - 1 284*4882a593Smuzhiyundie "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2); 285*4882a593Smuzhiyun 286*4882a593Smuzhiyunsub hash_save_array_words { 287*4882a593Smuzhiyun my ($hashRef, $arrayRef) = @_; 288*4882a593Smuzhiyun 289*4882a593Smuzhiyun my @array = split(/,/, join(',', @$arrayRef)); 290*4882a593Smuzhiyun foreach my $word (@array) { 291*4882a593Smuzhiyun $word =~ s/\s*\n?$//g; 292*4882a593Smuzhiyun $word =~ s/^\s*//g; 293*4882a593Smuzhiyun $word =~ s/\s+/ /g; 294*4882a593Smuzhiyun $word =~ tr/[a-z]/[A-Z]/; 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun next if ($word =~ m/^\s*#/); 297*4882a593Smuzhiyun next if ($word =~ m/^\s*$/); 298*4882a593Smuzhiyun 299*4882a593Smuzhiyun $hashRef->{$word}++; 300*4882a593Smuzhiyun } 301*4882a593Smuzhiyun} 302*4882a593Smuzhiyun 303*4882a593Smuzhiyunsub hash_show_words { 304*4882a593Smuzhiyun my ($hashRef, $prefix) = @_; 305*4882a593Smuzhiyun 306*4882a593Smuzhiyun if (keys %$hashRef) { 307*4882a593Smuzhiyun print "\nNOTE: $prefix message types:"; 308*4882a593Smuzhiyun foreach my $word (sort keys %$hashRef) { 309*4882a593Smuzhiyun print " $word"; 310*4882a593Smuzhiyun } 311*4882a593Smuzhiyun print "\n"; 312*4882a593Smuzhiyun } 313*4882a593Smuzhiyun} 314*4882a593Smuzhiyun 315*4882a593Smuzhiyunhash_save_array_words(\%ignore_type, \@ignore); 316*4882a593Smuzhiyunhash_save_array_words(\%use_type, \@use); 317*4882a593Smuzhiyun 318*4882a593Smuzhiyunmy $dbg_values = 0; 319*4882a593Smuzhiyunmy $dbg_possible = 0; 320*4882a593Smuzhiyunmy $dbg_type = 0; 321*4882a593Smuzhiyunmy $dbg_attr = 0; 322*4882a593Smuzhiyunfor my $key (keys %debug) { 323*4882a593Smuzhiyun ## no critic 324*4882a593Smuzhiyun eval "\${dbg_$key} = '$debug{$key}';"; 325*4882a593Smuzhiyun die "$@" if ($@); 326*4882a593Smuzhiyun} 327*4882a593Smuzhiyun 328*4882a593Smuzhiyunmy $rpt_cleaners = 0; 329*4882a593Smuzhiyun 330*4882a593Smuzhiyunif ($terse) { 331*4882a593Smuzhiyun $emacs = 1; 332*4882a593Smuzhiyun $quiet++; 333*4882a593Smuzhiyun} 334*4882a593Smuzhiyun 335*4882a593Smuzhiyunif ($tree) { 336*4882a593Smuzhiyun if (defined $root) { 337*4882a593Smuzhiyun if (!top_of_kernel_tree($root)) { 338*4882a593Smuzhiyun die "$P: $root: --root does not point at a valid tree\n"; 339*4882a593Smuzhiyun } 340*4882a593Smuzhiyun } else { 341*4882a593Smuzhiyun if (top_of_kernel_tree('.')) { 342*4882a593Smuzhiyun $root = '.'; 343*4882a593Smuzhiyun } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && 344*4882a593Smuzhiyun top_of_kernel_tree($1)) { 345*4882a593Smuzhiyun $root = $1; 346*4882a593Smuzhiyun } 347*4882a593Smuzhiyun } 348*4882a593Smuzhiyun 349*4882a593Smuzhiyun if (!defined $root) { 350*4882a593Smuzhiyun print "Must be run from the top-level dir. of a kernel tree\n"; 351*4882a593Smuzhiyun exit(2); 352*4882a593Smuzhiyun } 353*4882a593Smuzhiyun} 354*4882a593Smuzhiyun 355*4882a593Smuzhiyunmy $emitted_corrupt = 0; 356*4882a593Smuzhiyun 357*4882a593Smuzhiyunour $Ident = qr{ 358*4882a593Smuzhiyun [A-Za-z_][A-Za-z\d_]* 359*4882a593Smuzhiyun (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* 360*4882a593Smuzhiyun }x; 361*4882a593Smuzhiyunour $Storage = qr{extern|static|asmlinkage}; 362*4882a593Smuzhiyunour $Sparse = qr{ 363*4882a593Smuzhiyun __user| 364*4882a593Smuzhiyun __kernel| 365*4882a593Smuzhiyun __force| 366*4882a593Smuzhiyun __iomem| 367*4882a593Smuzhiyun __must_check| 368*4882a593Smuzhiyun __kprobes| 369*4882a593Smuzhiyun __ref| 370*4882a593Smuzhiyun __refconst| 371*4882a593Smuzhiyun __refdata| 372*4882a593Smuzhiyun __rcu| 373*4882a593Smuzhiyun __private 374*4882a593Smuzhiyun }x; 375*4882a593Smuzhiyunour $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; 376*4882a593Smuzhiyunour $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; 377*4882a593Smuzhiyunour $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; 378*4882a593Smuzhiyunour $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; 379*4882a593Smuzhiyunour $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; 380*4882a593Smuzhiyun 381*4882a593Smuzhiyun# Notes to $Attribute: 382*4882a593Smuzhiyun# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check 383*4882a593Smuzhiyunour $Attribute = qr{ 384*4882a593Smuzhiyun const| 385*4882a593Smuzhiyun __percpu| 386*4882a593Smuzhiyun __nocast| 387*4882a593Smuzhiyun __safe| 388*4882a593Smuzhiyun __bitwise| 389*4882a593Smuzhiyun __packed__| 390*4882a593Smuzhiyun __packed2__| 391*4882a593Smuzhiyun __naked| 392*4882a593Smuzhiyun __maybe_unused| 393*4882a593Smuzhiyun __always_unused| 394*4882a593Smuzhiyun __noreturn| 395*4882a593Smuzhiyun __used| 396*4882a593Smuzhiyun __cold| 397*4882a593Smuzhiyun __pure| 398*4882a593Smuzhiyun __noclone| 399*4882a593Smuzhiyun __deprecated| 400*4882a593Smuzhiyun __read_mostly| 401*4882a593Smuzhiyun __ro_after_init| 402*4882a593Smuzhiyun __kprobes| 403*4882a593Smuzhiyun $InitAttribute| 404*4882a593Smuzhiyun ____cacheline_aligned| 405*4882a593Smuzhiyun ____cacheline_aligned_in_smp| 406*4882a593Smuzhiyun ____cacheline_internodealigned_in_smp| 407*4882a593Smuzhiyun __weak 408*4882a593Smuzhiyun }x; 409*4882a593Smuzhiyunour $Modifier; 410*4882a593Smuzhiyunour $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; 411*4882a593Smuzhiyunour $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; 412*4882a593Smuzhiyunour $Lval = qr{$Ident(?:$Member)*}; 413*4882a593Smuzhiyun 414*4882a593Smuzhiyunour $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; 415*4882a593Smuzhiyunour $Binary = qr{(?i)0b[01]+$Int_type?}; 416*4882a593Smuzhiyunour $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; 417*4882a593Smuzhiyunour $Int = qr{[0-9]+$Int_type?}; 418*4882a593Smuzhiyunour $Octal = qr{0[0-7]+$Int_type?}; 419*4882a593Smuzhiyunour $String = qr{"[X\t]*"}; 420*4882a593Smuzhiyunour $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; 421*4882a593Smuzhiyunour $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; 422*4882a593Smuzhiyunour $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; 423*4882a593Smuzhiyunour $Float = qr{$Float_hex|$Float_dec|$Float_int}; 424*4882a593Smuzhiyunour $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; 425*4882a593Smuzhiyunour $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; 426*4882a593Smuzhiyunour $Compare = qr{<=|>=|==|!=|<|(?<!-)>}; 427*4882a593Smuzhiyunour $Arithmetic = qr{\+|-|\*|\/|%}; 428*4882a593Smuzhiyunour $Operators = qr{ 429*4882a593Smuzhiyun <=|>=|==|!=| 430*4882a593Smuzhiyun =>|->|<<|>>|<|>|!|~| 431*4882a593Smuzhiyun &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic 432*4882a593Smuzhiyun }x; 433*4882a593Smuzhiyun 434*4882a593Smuzhiyunour $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; 435*4882a593Smuzhiyun 436*4882a593Smuzhiyunour $BasicType; 437*4882a593Smuzhiyunour $NonptrType; 438*4882a593Smuzhiyunour $NonptrTypeMisordered; 439*4882a593Smuzhiyunour $NonptrTypeWithAttr; 440*4882a593Smuzhiyunour $Type; 441*4882a593Smuzhiyunour $TypeMisordered; 442*4882a593Smuzhiyunour $Declare; 443*4882a593Smuzhiyunour $DeclareMisordered; 444*4882a593Smuzhiyun 445*4882a593Smuzhiyunour $NON_ASCII_UTF8 = qr{ 446*4882a593Smuzhiyun [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte 447*4882a593Smuzhiyun | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs 448*4882a593Smuzhiyun | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte 449*4882a593Smuzhiyun | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates 450*4882a593Smuzhiyun | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 451*4882a593Smuzhiyun | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 452*4882a593Smuzhiyun | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 453*4882a593Smuzhiyun}x; 454*4882a593Smuzhiyun 455*4882a593Smuzhiyunour $UTF8 = qr{ 456*4882a593Smuzhiyun [\x09\x0A\x0D\x20-\x7E] # ASCII 457*4882a593Smuzhiyun | $NON_ASCII_UTF8 458*4882a593Smuzhiyun}x; 459*4882a593Smuzhiyun 460*4882a593Smuzhiyunour $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; 461*4882a593Smuzhiyunour $typeOtherOSTypedefs = qr{(?x: 462*4882a593Smuzhiyun u_(?:char|short|int|long) | # bsd 463*4882a593Smuzhiyun u(?:nchar|short|int|long) # sysv 464*4882a593Smuzhiyun)}; 465*4882a593Smuzhiyunour $typeKernelTypedefs = qr{(?x: 466*4882a593Smuzhiyun (?:__)?(?:u|s|be|le)(?:8|16|32|64)| 467*4882a593Smuzhiyun atomic_t 468*4882a593Smuzhiyun)}; 469*4882a593Smuzhiyunour $typeTypedefs = qr{(?x: 470*4882a593Smuzhiyun $typeC99Typedefs\b| 471*4882a593Smuzhiyun $typeOtherOSTypedefs\b| 472*4882a593Smuzhiyun $typeKernelTypedefs\b 473*4882a593Smuzhiyun)}; 474*4882a593Smuzhiyun 475*4882a593Smuzhiyunour $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; 476*4882a593Smuzhiyun 477*4882a593Smuzhiyunour $logFunctions = qr{(?x: 478*4882a593Smuzhiyun printk(?:_ratelimited|_once|_deferred_once|_deferred|)| 479*4882a593Smuzhiyun (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| 480*4882a593Smuzhiyun TP_printk| 481*4882a593Smuzhiyun WARN(?:_RATELIMIT|_ONCE|)| 482*4882a593Smuzhiyun panic| 483*4882a593Smuzhiyun MODULE_[A-Z_]+| 484*4882a593Smuzhiyun seq_vprintf|seq_printf|seq_puts 485*4882a593Smuzhiyun)}; 486*4882a593Smuzhiyun 487*4882a593Smuzhiyunour $allocFunctions = qr{(?x: 488*4882a593Smuzhiyun (?:(?:devm_)? 489*4882a593Smuzhiyun (?:kv|k|v)[czm]alloc(?:_node|_array)? | 490*4882a593Smuzhiyun kstrdup(?:_const)? | 491*4882a593Smuzhiyun kmemdup(?:_nul)?) | 492*4882a593Smuzhiyun (?:\w+)?alloc_skb(?:_ip_align)? | 493*4882a593Smuzhiyun # dev_alloc_skb/netdev_alloc_skb, et al 494*4882a593Smuzhiyun dma_alloc_coherent 495*4882a593Smuzhiyun)}; 496*4882a593Smuzhiyun 497*4882a593Smuzhiyunour $signature_tags = qr{(?xi: 498*4882a593Smuzhiyun Signed-off-by:| 499*4882a593Smuzhiyun Co-developed-by:| 500*4882a593Smuzhiyun Acked-by:| 501*4882a593Smuzhiyun Tested-by:| 502*4882a593Smuzhiyun Reviewed-by:| 503*4882a593Smuzhiyun Reported-by:| 504*4882a593Smuzhiyun Suggested-by:| 505*4882a593Smuzhiyun To:| 506*4882a593Smuzhiyun Cc: 507*4882a593Smuzhiyun)}; 508*4882a593Smuzhiyun 509*4882a593Smuzhiyunour @typeListMisordered = ( 510*4882a593Smuzhiyun qr{char\s+(?:un)?signed}, 511*4882a593Smuzhiyun qr{int\s+(?:(?:un)?signed\s+)?short\s}, 512*4882a593Smuzhiyun qr{int\s+short(?:\s+(?:un)?signed)}, 513*4882a593Smuzhiyun qr{short\s+int(?:\s+(?:un)?signed)}, 514*4882a593Smuzhiyun qr{(?:un)?signed\s+int\s+short}, 515*4882a593Smuzhiyun qr{short\s+(?:un)?signed}, 516*4882a593Smuzhiyun qr{long\s+int\s+(?:un)?signed}, 517*4882a593Smuzhiyun qr{int\s+long\s+(?:un)?signed}, 518*4882a593Smuzhiyun qr{long\s+(?:un)?signed\s+int}, 519*4882a593Smuzhiyun qr{int\s+(?:un)?signed\s+long}, 520*4882a593Smuzhiyun qr{int\s+(?:un)?signed}, 521*4882a593Smuzhiyun qr{int\s+long\s+long\s+(?:un)?signed}, 522*4882a593Smuzhiyun qr{long\s+long\s+int\s+(?:un)?signed}, 523*4882a593Smuzhiyun qr{long\s+long\s+(?:un)?signed\s+int}, 524*4882a593Smuzhiyun qr{long\s+long\s+(?:un)?signed}, 525*4882a593Smuzhiyun qr{long\s+(?:un)?signed}, 526*4882a593Smuzhiyun); 527*4882a593Smuzhiyun 528*4882a593Smuzhiyunour @typeList = ( 529*4882a593Smuzhiyun qr{void}, 530*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?char}, 531*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?short\s+int}, 532*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?short}, 533*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?int}, 534*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long\s+int}, 535*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, 536*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long\s+long}, 537*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long}, 538*4882a593Smuzhiyun qr{(?:un)?signed}, 539*4882a593Smuzhiyun qr{float}, 540*4882a593Smuzhiyun qr{double}, 541*4882a593Smuzhiyun qr{bool}, 542*4882a593Smuzhiyun qr{struct\s+$Ident}, 543*4882a593Smuzhiyun qr{union\s+$Ident}, 544*4882a593Smuzhiyun qr{enum\s+$Ident}, 545*4882a593Smuzhiyun qr{${Ident}_t}, 546*4882a593Smuzhiyun qr{${Ident}_handler}, 547*4882a593Smuzhiyun qr{${Ident}_handler_fn}, 548*4882a593Smuzhiyun @typeListMisordered, 549*4882a593Smuzhiyun); 550*4882a593Smuzhiyun 551*4882a593Smuzhiyunour $C90_int_types = qr{(?x: 552*4882a593Smuzhiyun long\s+long\s+int\s+(?:un)?signed| 553*4882a593Smuzhiyun long\s+long\s+(?:un)?signed\s+int| 554*4882a593Smuzhiyun long\s+long\s+(?:un)?signed| 555*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long\s+long\s+int| 556*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long\s+long| 557*4882a593Smuzhiyun int\s+long\s+long\s+(?:un)?signed| 558*4882a593Smuzhiyun int\s+(?:(?:un)?signed\s+)?long\s+long| 559*4882a593Smuzhiyun 560*4882a593Smuzhiyun long\s+int\s+(?:un)?signed| 561*4882a593Smuzhiyun long\s+(?:un)?signed\s+int| 562*4882a593Smuzhiyun long\s+(?:un)?signed| 563*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long\s+int| 564*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long| 565*4882a593Smuzhiyun int\s+long\s+(?:un)?signed| 566*4882a593Smuzhiyun int\s+(?:(?:un)?signed\s+)?long| 567*4882a593Smuzhiyun 568*4882a593Smuzhiyun int\s+(?:un)?signed| 569*4882a593Smuzhiyun (?:(?:un)?signed\s+)?int 570*4882a593Smuzhiyun)}; 571*4882a593Smuzhiyun 572*4882a593Smuzhiyunour @typeListFile = (); 573*4882a593Smuzhiyunour @typeListWithAttr = ( 574*4882a593Smuzhiyun @typeList, 575*4882a593Smuzhiyun qr{struct\s+$InitAttribute\s+$Ident}, 576*4882a593Smuzhiyun qr{union\s+$InitAttribute\s+$Ident}, 577*4882a593Smuzhiyun); 578*4882a593Smuzhiyun 579*4882a593Smuzhiyunour @modifierList = ( 580*4882a593Smuzhiyun qr{fastcall}, 581*4882a593Smuzhiyun); 582*4882a593Smuzhiyunour @modifierListFile = (); 583*4882a593Smuzhiyun 584*4882a593Smuzhiyunour @mode_permission_funcs = ( 585*4882a593Smuzhiyun ["module_param", 3], 586*4882a593Smuzhiyun ["module_param_(?:array|named|string)", 4], 587*4882a593Smuzhiyun ["module_param_array_named", 5], 588*4882a593Smuzhiyun ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], 589*4882a593Smuzhiyun ["proc_create(?:_data|)", 2], 590*4882a593Smuzhiyun ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2], 591*4882a593Smuzhiyun ["IIO_DEV_ATTR_[A-Z_]+", 1], 592*4882a593Smuzhiyun ["SENSOR_(?:DEVICE_|)ATTR_2", 2], 593*4882a593Smuzhiyun ["SENSOR_TEMPLATE(?:_2|)", 3], 594*4882a593Smuzhiyun ["__ATTR", 2], 595*4882a593Smuzhiyun); 596*4882a593Smuzhiyun 597*4882a593Smuzhiyunmy $word_pattern = '\b[A-Z]?[a-z]{2,}\b'; 598*4882a593Smuzhiyun 599*4882a593Smuzhiyun#Create a search pattern for all these functions to speed up a loop below 600*4882a593Smuzhiyunour $mode_perms_search = ""; 601*4882a593Smuzhiyunforeach my $entry (@mode_permission_funcs) { 602*4882a593Smuzhiyun $mode_perms_search .= '|' if ($mode_perms_search ne ""); 603*4882a593Smuzhiyun $mode_perms_search .= $entry->[0]; 604*4882a593Smuzhiyun} 605*4882a593Smuzhiyun$mode_perms_search = "(?:${mode_perms_search})"; 606*4882a593Smuzhiyun 607*4882a593Smuzhiyunour %deprecated_apis = ( 608*4882a593Smuzhiyun "synchronize_rcu_bh" => "synchronize_rcu", 609*4882a593Smuzhiyun "synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited", 610*4882a593Smuzhiyun "call_rcu_bh" => "call_rcu", 611*4882a593Smuzhiyun "rcu_barrier_bh" => "rcu_barrier", 612*4882a593Smuzhiyun "synchronize_sched" => "synchronize_rcu", 613*4882a593Smuzhiyun "synchronize_sched_expedited" => "synchronize_rcu_expedited", 614*4882a593Smuzhiyun "call_rcu_sched" => "call_rcu", 615*4882a593Smuzhiyun "rcu_barrier_sched" => "rcu_barrier", 616*4882a593Smuzhiyun "get_state_synchronize_sched" => "get_state_synchronize_rcu", 617*4882a593Smuzhiyun "cond_synchronize_sched" => "cond_synchronize_rcu", 618*4882a593Smuzhiyun); 619*4882a593Smuzhiyun 620*4882a593Smuzhiyun#Create a search pattern for all these strings to speed up a loop below 621*4882a593Smuzhiyunour $deprecated_apis_search = ""; 622*4882a593Smuzhiyunforeach my $entry (keys %deprecated_apis) { 623*4882a593Smuzhiyun $deprecated_apis_search .= '|' if ($deprecated_apis_search ne ""); 624*4882a593Smuzhiyun $deprecated_apis_search .= $entry; 625*4882a593Smuzhiyun} 626*4882a593Smuzhiyun$deprecated_apis_search = "(?:${deprecated_apis_search})"; 627*4882a593Smuzhiyun 628*4882a593Smuzhiyunour $mode_perms_world_writable = qr{ 629*4882a593Smuzhiyun S_IWUGO | 630*4882a593Smuzhiyun S_IWOTH | 631*4882a593Smuzhiyun S_IRWXUGO | 632*4882a593Smuzhiyun S_IALLUGO | 633*4882a593Smuzhiyun 0[0-7][0-7][2367] 634*4882a593Smuzhiyun}x; 635*4882a593Smuzhiyun 636*4882a593Smuzhiyunour %mode_permission_string_types = ( 637*4882a593Smuzhiyun "S_IRWXU" => 0700, 638*4882a593Smuzhiyun "S_IRUSR" => 0400, 639*4882a593Smuzhiyun "S_IWUSR" => 0200, 640*4882a593Smuzhiyun "S_IXUSR" => 0100, 641*4882a593Smuzhiyun "S_IRWXG" => 0070, 642*4882a593Smuzhiyun "S_IRGRP" => 0040, 643*4882a593Smuzhiyun "S_IWGRP" => 0020, 644*4882a593Smuzhiyun "S_IXGRP" => 0010, 645*4882a593Smuzhiyun "S_IRWXO" => 0007, 646*4882a593Smuzhiyun "S_IROTH" => 0004, 647*4882a593Smuzhiyun "S_IWOTH" => 0002, 648*4882a593Smuzhiyun "S_IXOTH" => 0001, 649*4882a593Smuzhiyun "S_IRWXUGO" => 0777, 650*4882a593Smuzhiyun "S_IRUGO" => 0444, 651*4882a593Smuzhiyun "S_IWUGO" => 0222, 652*4882a593Smuzhiyun "S_IXUGO" => 0111, 653*4882a593Smuzhiyun); 654*4882a593Smuzhiyun 655*4882a593Smuzhiyun#Create a search pattern for all these strings to speed up a loop below 656*4882a593Smuzhiyunour $mode_perms_string_search = ""; 657*4882a593Smuzhiyunforeach my $entry (keys %mode_permission_string_types) { 658*4882a593Smuzhiyun $mode_perms_string_search .= '|' if ($mode_perms_string_search ne ""); 659*4882a593Smuzhiyun $mode_perms_string_search .= $entry; 660*4882a593Smuzhiyun} 661*4882a593Smuzhiyunour $single_mode_perms_string_search = "(?:${mode_perms_string_search})"; 662*4882a593Smuzhiyunour $multi_mode_perms_string_search = qr{ 663*4882a593Smuzhiyun ${single_mode_perms_string_search} 664*4882a593Smuzhiyun (?:\s*\|\s*${single_mode_perms_string_search})* 665*4882a593Smuzhiyun}x; 666*4882a593Smuzhiyun 667*4882a593Smuzhiyunsub perms_to_octal { 668*4882a593Smuzhiyun my ($string) = @_; 669*4882a593Smuzhiyun 670*4882a593Smuzhiyun return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/); 671*4882a593Smuzhiyun 672*4882a593Smuzhiyun my $val = ""; 673*4882a593Smuzhiyun my $oval = ""; 674*4882a593Smuzhiyun my $to = 0; 675*4882a593Smuzhiyun my $curpos = 0; 676*4882a593Smuzhiyun my $lastpos = 0; 677*4882a593Smuzhiyun while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) { 678*4882a593Smuzhiyun $curpos = pos($string); 679*4882a593Smuzhiyun my $match = $2; 680*4882a593Smuzhiyun my $omatch = $1; 681*4882a593Smuzhiyun last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos)); 682*4882a593Smuzhiyun $lastpos = $curpos; 683*4882a593Smuzhiyun $to |= $mode_permission_string_types{$match}; 684*4882a593Smuzhiyun $val .= '\s*\|\s*' if ($val ne ""); 685*4882a593Smuzhiyun $val .= $match; 686*4882a593Smuzhiyun $oval .= $omatch; 687*4882a593Smuzhiyun } 688*4882a593Smuzhiyun $oval =~ s/^\s*\|\s*//; 689*4882a593Smuzhiyun $oval =~ s/\s*\|\s*$//; 690*4882a593Smuzhiyun return sprintf("%04o", $to); 691*4882a593Smuzhiyun} 692*4882a593Smuzhiyun 693*4882a593Smuzhiyunour $allowed_asm_includes = qr{(?x: 694*4882a593Smuzhiyun irq| 695*4882a593Smuzhiyun memory| 696*4882a593Smuzhiyun time| 697*4882a593Smuzhiyun reboot 698*4882a593Smuzhiyun)}; 699*4882a593Smuzhiyun# memory.h: ARM has a custom one 700*4882a593Smuzhiyun 701*4882a593Smuzhiyun# Load common spelling mistakes and build regular expression list. 702*4882a593Smuzhiyunmy $misspellings; 703*4882a593Smuzhiyunmy %spelling_fix; 704*4882a593Smuzhiyun 705*4882a593Smuzhiyunif (open(my $spelling, '<', $spelling_file)) { 706*4882a593Smuzhiyun while (<$spelling>) { 707*4882a593Smuzhiyun my $line = $_; 708*4882a593Smuzhiyun 709*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 710*4882a593Smuzhiyun $line =~ s/^\s*//g; 711*4882a593Smuzhiyun 712*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 713*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 714*4882a593Smuzhiyun 715*4882a593Smuzhiyun my ($suspect, $fix) = split(/\|\|/, $line); 716*4882a593Smuzhiyun 717*4882a593Smuzhiyun $spelling_fix{$suspect} = $fix; 718*4882a593Smuzhiyun } 719*4882a593Smuzhiyun close($spelling); 720*4882a593Smuzhiyun} else { 721*4882a593Smuzhiyun warn "No typos will be found - file '$spelling_file': $!\n"; 722*4882a593Smuzhiyun} 723*4882a593Smuzhiyun 724*4882a593Smuzhiyunif ($codespell) { 725*4882a593Smuzhiyun if (open(my $spelling, '<', $codespellfile)) { 726*4882a593Smuzhiyun while (<$spelling>) { 727*4882a593Smuzhiyun my $line = $_; 728*4882a593Smuzhiyun 729*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 730*4882a593Smuzhiyun $line =~ s/^\s*//g; 731*4882a593Smuzhiyun 732*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 733*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 734*4882a593Smuzhiyun next if ($line =~ m/, disabled/i); 735*4882a593Smuzhiyun 736*4882a593Smuzhiyun $line =~ s/,.*$//; 737*4882a593Smuzhiyun 738*4882a593Smuzhiyun my ($suspect, $fix) = split(/->/, $line); 739*4882a593Smuzhiyun 740*4882a593Smuzhiyun $spelling_fix{$suspect} = $fix; 741*4882a593Smuzhiyun } 742*4882a593Smuzhiyun close($spelling); 743*4882a593Smuzhiyun } else { 744*4882a593Smuzhiyun warn "No codespell typos will be found - file '$codespellfile': $!\n"; 745*4882a593Smuzhiyun } 746*4882a593Smuzhiyun} 747*4882a593Smuzhiyun 748*4882a593Smuzhiyun$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; 749*4882a593Smuzhiyun 750*4882a593Smuzhiyunsub read_words { 751*4882a593Smuzhiyun my ($wordsRef, $file) = @_; 752*4882a593Smuzhiyun 753*4882a593Smuzhiyun if (open(my $words, '<', $file)) { 754*4882a593Smuzhiyun while (<$words>) { 755*4882a593Smuzhiyun my $line = $_; 756*4882a593Smuzhiyun 757*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 758*4882a593Smuzhiyun $line =~ s/^\s*//g; 759*4882a593Smuzhiyun 760*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 761*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 762*4882a593Smuzhiyun if ($line =~ /\s/) { 763*4882a593Smuzhiyun print("$file: '$line' invalid - ignored\n"); 764*4882a593Smuzhiyun next; 765*4882a593Smuzhiyun } 766*4882a593Smuzhiyun 767*4882a593Smuzhiyun $$wordsRef .= '|' if (defined $$wordsRef); 768*4882a593Smuzhiyun $$wordsRef .= $line; 769*4882a593Smuzhiyun } 770*4882a593Smuzhiyun close($file); 771*4882a593Smuzhiyun return 1; 772*4882a593Smuzhiyun } 773*4882a593Smuzhiyun 774*4882a593Smuzhiyun return 0; 775*4882a593Smuzhiyun} 776*4882a593Smuzhiyun 777*4882a593Smuzhiyunmy $const_structs; 778*4882a593Smuzhiyunif (show_type("CONST_STRUCT")) { 779*4882a593Smuzhiyun read_words(\$const_structs, $conststructsfile) 780*4882a593Smuzhiyun or warn "No structs that should be const will be found - file '$conststructsfile': $!\n"; 781*4882a593Smuzhiyun} 782*4882a593Smuzhiyun 783*4882a593Smuzhiyunif (defined($typedefsfile)) { 784*4882a593Smuzhiyun my $typeOtherTypedefs; 785*4882a593Smuzhiyun read_words(\$typeOtherTypedefs, $typedefsfile) 786*4882a593Smuzhiyun or warn "No additional types will be considered - file '$typedefsfile': $!\n"; 787*4882a593Smuzhiyun $typeTypedefs .= '|' . $typeOtherTypedefs if (defined $typeOtherTypedefs); 788*4882a593Smuzhiyun} 789*4882a593Smuzhiyun 790*4882a593Smuzhiyunsub build_types { 791*4882a593Smuzhiyun my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; 792*4882a593Smuzhiyun my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; 793*4882a593Smuzhiyun my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; 794*4882a593Smuzhiyun my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; 795*4882a593Smuzhiyun $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; 796*4882a593Smuzhiyun $BasicType = qr{ 797*4882a593Smuzhiyun (?:$typeTypedefs\b)| 798*4882a593Smuzhiyun (?:${all}\b) 799*4882a593Smuzhiyun }x; 800*4882a593Smuzhiyun $NonptrType = qr{ 801*4882a593Smuzhiyun (?:$Modifier\s+|const\s+)* 802*4882a593Smuzhiyun (?: 803*4882a593Smuzhiyun (?:typeof|__typeof__)\s*\([^\)]*\)| 804*4882a593Smuzhiyun (?:$typeTypedefs\b)| 805*4882a593Smuzhiyun (?:${all}\b) 806*4882a593Smuzhiyun ) 807*4882a593Smuzhiyun (?:\s+$Modifier|\s+const)* 808*4882a593Smuzhiyun }x; 809*4882a593Smuzhiyun $NonptrTypeMisordered = qr{ 810*4882a593Smuzhiyun (?:$Modifier\s+|const\s+)* 811*4882a593Smuzhiyun (?: 812*4882a593Smuzhiyun (?:${Misordered}\b) 813*4882a593Smuzhiyun ) 814*4882a593Smuzhiyun (?:\s+$Modifier|\s+const)* 815*4882a593Smuzhiyun }x; 816*4882a593Smuzhiyun $NonptrTypeWithAttr = qr{ 817*4882a593Smuzhiyun (?:$Modifier\s+|const\s+)* 818*4882a593Smuzhiyun (?: 819*4882a593Smuzhiyun (?:typeof|__typeof__)\s*\([^\)]*\)| 820*4882a593Smuzhiyun (?:$typeTypedefs\b)| 821*4882a593Smuzhiyun (?:${allWithAttr}\b) 822*4882a593Smuzhiyun ) 823*4882a593Smuzhiyun (?:\s+$Modifier|\s+const)* 824*4882a593Smuzhiyun }x; 825*4882a593Smuzhiyun $Type = qr{ 826*4882a593Smuzhiyun $NonptrType 827*4882a593Smuzhiyun (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4} 828*4882a593Smuzhiyun (?:\s+$Inline|\s+$Modifier)* 829*4882a593Smuzhiyun }x; 830*4882a593Smuzhiyun $TypeMisordered = qr{ 831*4882a593Smuzhiyun $NonptrTypeMisordered 832*4882a593Smuzhiyun (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4} 833*4882a593Smuzhiyun (?:\s+$Inline|\s+$Modifier)* 834*4882a593Smuzhiyun }x; 835*4882a593Smuzhiyun $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; 836*4882a593Smuzhiyun $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; 837*4882a593Smuzhiyun} 838*4882a593Smuzhiyunbuild_types(); 839*4882a593Smuzhiyun 840*4882a593Smuzhiyunour $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; 841*4882a593Smuzhiyun 842*4882a593Smuzhiyun# Using $balanced_parens, $LvalOrFunc, or $FuncArg 843*4882a593Smuzhiyun# requires at least perl version v5.10.0 844*4882a593Smuzhiyun# Any use must be runtime checked with $^V 845*4882a593Smuzhiyun 846*4882a593Smuzhiyunour $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; 847*4882a593Smuzhiyunour $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; 848*4882a593Smuzhiyunour $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; 849*4882a593Smuzhiyun 850*4882a593Smuzhiyunour $declaration_macros = qr{(?x: 851*4882a593Smuzhiyun (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| 852*4882a593Smuzhiyun (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(| 853*4882a593Smuzhiyun (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\( 854*4882a593Smuzhiyun)}; 855*4882a593Smuzhiyun 856*4882a593Smuzhiyunsub deparenthesize { 857*4882a593Smuzhiyun my ($string) = @_; 858*4882a593Smuzhiyun return "" if (!defined($string)); 859*4882a593Smuzhiyun 860*4882a593Smuzhiyun while ($string =~ /^\s*\(.*\)\s*$/) { 861*4882a593Smuzhiyun $string =~ s@^\s*\(\s*@@; 862*4882a593Smuzhiyun $string =~ s@\s*\)\s*$@@; 863*4882a593Smuzhiyun } 864*4882a593Smuzhiyun 865*4882a593Smuzhiyun $string =~ s@\s+@ @g; 866*4882a593Smuzhiyun 867*4882a593Smuzhiyun return $string; 868*4882a593Smuzhiyun} 869*4882a593Smuzhiyun 870*4882a593Smuzhiyunsub seed_camelcase_file { 871*4882a593Smuzhiyun my ($file) = @_; 872*4882a593Smuzhiyun 873*4882a593Smuzhiyun return if (!(-f $file)); 874*4882a593Smuzhiyun 875*4882a593Smuzhiyun local $/; 876*4882a593Smuzhiyun 877*4882a593Smuzhiyun open(my $include_file, '<', "$file") 878*4882a593Smuzhiyun or warn "$P: Can't read '$file' $!\n"; 879*4882a593Smuzhiyun my $text = <$include_file>; 880*4882a593Smuzhiyun close($include_file); 881*4882a593Smuzhiyun 882*4882a593Smuzhiyun my @lines = split('\n', $text); 883*4882a593Smuzhiyun 884*4882a593Smuzhiyun foreach my $line (@lines) { 885*4882a593Smuzhiyun next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); 886*4882a593Smuzhiyun if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { 887*4882a593Smuzhiyun $camelcase{$1} = 1; 888*4882a593Smuzhiyun } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { 889*4882a593Smuzhiyun $camelcase{$1} = 1; 890*4882a593Smuzhiyun } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { 891*4882a593Smuzhiyun $camelcase{$1} = 1; 892*4882a593Smuzhiyun } 893*4882a593Smuzhiyun } 894*4882a593Smuzhiyun} 895*4882a593Smuzhiyun 896*4882a593Smuzhiyunour %maintained_status = (); 897*4882a593Smuzhiyun 898*4882a593Smuzhiyunsub is_maintained_obsolete { 899*4882a593Smuzhiyun my ($filename) = @_; 900*4882a593Smuzhiyun 901*4882a593Smuzhiyun return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl")); 902*4882a593Smuzhiyun 903*4882a593Smuzhiyun if (!exists($maintained_status{$filename})) { 904*4882a593Smuzhiyun $maintained_status{$filename} = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`; 905*4882a593Smuzhiyun } 906*4882a593Smuzhiyun 907*4882a593Smuzhiyun return $maintained_status{$filename} =~ /obsolete/i; 908*4882a593Smuzhiyun} 909*4882a593Smuzhiyun 910*4882a593Smuzhiyunsub is_SPDX_License_valid { 911*4882a593Smuzhiyun my ($license) = @_; 912*4882a593Smuzhiyun 913*4882a593Smuzhiyun return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot")); 914*4882a593Smuzhiyun 915*4882a593Smuzhiyun my $root_path = abs_path($root); 916*4882a593Smuzhiyun my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`; 917*4882a593Smuzhiyun return 0 if ($status ne ""); 918*4882a593Smuzhiyun return 1; 919*4882a593Smuzhiyun} 920*4882a593Smuzhiyun 921*4882a593Smuzhiyunmy $camelcase_seeded = 0; 922*4882a593Smuzhiyunsub seed_camelcase_includes { 923*4882a593Smuzhiyun return if ($camelcase_seeded); 924*4882a593Smuzhiyun 925*4882a593Smuzhiyun my $files; 926*4882a593Smuzhiyun my $camelcase_cache = ""; 927*4882a593Smuzhiyun my @include_files = (); 928*4882a593Smuzhiyun 929*4882a593Smuzhiyun $camelcase_seeded = 1; 930*4882a593Smuzhiyun 931*4882a593Smuzhiyun if (-e "$gitroot") { 932*4882a593Smuzhiyun my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`; 933*4882a593Smuzhiyun chomp $git_last_include_commit; 934*4882a593Smuzhiyun $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; 935*4882a593Smuzhiyun } else { 936*4882a593Smuzhiyun my $last_mod_date = 0; 937*4882a593Smuzhiyun $files = `find $root/include -name "*.h"`; 938*4882a593Smuzhiyun @include_files = split('\n', $files); 939*4882a593Smuzhiyun foreach my $file (@include_files) { 940*4882a593Smuzhiyun my $date = POSIX::strftime("%Y%m%d%H%M", 941*4882a593Smuzhiyun localtime((stat $file)[9])); 942*4882a593Smuzhiyun $last_mod_date = $date if ($last_mod_date < $date); 943*4882a593Smuzhiyun } 944*4882a593Smuzhiyun $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; 945*4882a593Smuzhiyun } 946*4882a593Smuzhiyun 947*4882a593Smuzhiyun if ($camelcase_cache ne "" && -f $camelcase_cache) { 948*4882a593Smuzhiyun open(my $camelcase_file, '<', "$camelcase_cache") 949*4882a593Smuzhiyun or warn "$P: Can't read '$camelcase_cache' $!\n"; 950*4882a593Smuzhiyun while (<$camelcase_file>) { 951*4882a593Smuzhiyun chomp; 952*4882a593Smuzhiyun $camelcase{$_} = 1; 953*4882a593Smuzhiyun } 954*4882a593Smuzhiyun close($camelcase_file); 955*4882a593Smuzhiyun 956*4882a593Smuzhiyun return; 957*4882a593Smuzhiyun } 958*4882a593Smuzhiyun 959*4882a593Smuzhiyun if (-e "$gitroot") { 960*4882a593Smuzhiyun $files = `${git_command} ls-files "include/*.h"`; 961*4882a593Smuzhiyun @include_files = split('\n', $files); 962*4882a593Smuzhiyun } 963*4882a593Smuzhiyun 964*4882a593Smuzhiyun foreach my $file (@include_files) { 965*4882a593Smuzhiyun seed_camelcase_file($file); 966*4882a593Smuzhiyun } 967*4882a593Smuzhiyun 968*4882a593Smuzhiyun if ($camelcase_cache ne "") { 969*4882a593Smuzhiyun unlink glob ".checkpatch-camelcase.*"; 970*4882a593Smuzhiyun open(my $camelcase_file, '>', "$camelcase_cache") 971*4882a593Smuzhiyun or warn "$P: Can't write '$camelcase_cache' $!\n"; 972*4882a593Smuzhiyun foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { 973*4882a593Smuzhiyun print $camelcase_file ("$_\n"); 974*4882a593Smuzhiyun } 975*4882a593Smuzhiyun close($camelcase_file); 976*4882a593Smuzhiyun } 977*4882a593Smuzhiyun} 978*4882a593Smuzhiyun 979*4882a593Smuzhiyunsub git_is_single_file { 980*4882a593Smuzhiyun my ($filename) = @_; 981*4882a593Smuzhiyun 982*4882a593Smuzhiyun return 0 if ((which("git") eq "") || !(-e "$gitroot")); 983*4882a593Smuzhiyun 984*4882a593Smuzhiyun my $output = `${git_command} ls-files -- $filename 2>/dev/null`; 985*4882a593Smuzhiyun my $count = $output =~ tr/\n//; 986*4882a593Smuzhiyun return $count eq 1 && $output =~ m{^${filename}$}; 987*4882a593Smuzhiyun} 988*4882a593Smuzhiyun 989*4882a593Smuzhiyunsub git_commit_info { 990*4882a593Smuzhiyun my ($commit, $id, $desc) = @_; 991*4882a593Smuzhiyun 992*4882a593Smuzhiyun return ($id, $desc) if ((which("git") eq "") || !(-e "$gitroot")); 993*4882a593Smuzhiyun 994*4882a593Smuzhiyun my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`; 995*4882a593Smuzhiyun $output =~ s/^\s*//gm; 996*4882a593Smuzhiyun my @lines = split("\n", $output); 997*4882a593Smuzhiyun 998*4882a593Smuzhiyun return ($id, $desc) if ($#lines < 0); 999*4882a593Smuzhiyun 1000*4882a593Smuzhiyun if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) { 1001*4882a593Smuzhiyun# Maybe one day convert this block of bash into something that returns 1002*4882a593Smuzhiyun# all matching commit ids, but it's very slow... 1003*4882a593Smuzhiyun# 1004*4882a593Smuzhiyun# echo "checking commits $1..." 1005*4882a593Smuzhiyun# git rev-list --remotes | grep -i "^$1" | 1006*4882a593Smuzhiyun# while read line ; do 1007*4882a593Smuzhiyun# git log --format='%H %s' -1 $line | 1008*4882a593Smuzhiyun# echo "commit $(cut -c 1-12,41-)" 1009*4882a593Smuzhiyun# done 1010*4882a593Smuzhiyun } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { 1011*4882a593Smuzhiyun $id = undef; 1012*4882a593Smuzhiyun } else { 1013*4882a593Smuzhiyun $id = substr($lines[0], 0, 12); 1014*4882a593Smuzhiyun $desc = substr($lines[0], 41); 1015*4882a593Smuzhiyun } 1016*4882a593Smuzhiyun 1017*4882a593Smuzhiyun return ($id, $desc); 1018*4882a593Smuzhiyun} 1019*4882a593Smuzhiyun 1020*4882a593Smuzhiyun$chk_signoff = 0 if ($file); 1021*4882a593Smuzhiyun 1022*4882a593Smuzhiyunmy @rawlines = (); 1023*4882a593Smuzhiyunmy @lines = (); 1024*4882a593Smuzhiyunmy @fixed = (); 1025*4882a593Smuzhiyunmy @fixed_inserted = (); 1026*4882a593Smuzhiyunmy @fixed_deleted = (); 1027*4882a593Smuzhiyunmy $fixlinenr = -1; 1028*4882a593Smuzhiyun 1029*4882a593Smuzhiyun# If input is git commits, extract all commits from the commit expressions. 1030*4882a593Smuzhiyun# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'. 1031*4882a593Smuzhiyundie "$P: No git repository found\n" if ($git && !-e "$gitroot"); 1032*4882a593Smuzhiyun 1033*4882a593Smuzhiyunif ($git) { 1034*4882a593Smuzhiyun my @commits = (); 1035*4882a593Smuzhiyun foreach my $commit_expr (@ARGV) { 1036*4882a593Smuzhiyun my $git_range; 1037*4882a593Smuzhiyun if ($commit_expr =~ m/^(.*)-(\d+)$/) { 1038*4882a593Smuzhiyun $git_range = "-$2 $1"; 1039*4882a593Smuzhiyun } elsif ($commit_expr =~ m/\.\./) { 1040*4882a593Smuzhiyun $git_range = "$commit_expr"; 1041*4882a593Smuzhiyun } else { 1042*4882a593Smuzhiyun $git_range = "-1 $commit_expr"; 1043*4882a593Smuzhiyun } 1044*4882a593Smuzhiyun my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`; 1045*4882a593Smuzhiyun foreach my $line (split(/\n/, $lines)) { 1046*4882a593Smuzhiyun $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/; 1047*4882a593Smuzhiyun next if (!defined($1) || !defined($2)); 1048*4882a593Smuzhiyun my $sha1 = $1; 1049*4882a593Smuzhiyun my $subject = $2; 1050*4882a593Smuzhiyun unshift(@commits, $sha1); 1051*4882a593Smuzhiyun $git_commits{$sha1} = $subject; 1052*4882a593Smuzhiyun } 1053*4882a593Smuzhiyun } 1054*4882a593Smuzhiyun die "$P: no git commits after extraction!\n" if (@commits == 0); 1055*4882a593Smuzhiyun @ARGV = @commits; 1056*4882a593Smuzhiyun} 1057*4882a593Smuzhiyun 1058*4882a593Smuzhiyunmy $vname; 1059*4882a593Smuzhiyun$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"}; 1060*4882a593Smuzhiyunfor my $filename (@ARGV) { 1061*4882a593Smuzhiyun my $FILE; 1062*4882a593Smuzhiyun my $is_git_file = git_is_single_file($filename); 1063*4882a593Smuzhiyun my $oldfile = $file; 1064*4882a593Smuzhiyun $file = 1 if ($is_git_file); 1065*4882a593Smuzhiyun if ($git) { 1066*4882a593Smuzhiyun open($FILE, '-|', "git format-patch -M --stdout -1 $filename") || 1067*4882a593Smuzhiyun die "$P: $filename: git format-patch failed - $!\n"; 1068*4882a593Smuzhiyun } elsif ($file) { 1069*4882a593Smuzhiyun open($FILE, '-|', "diff -u /dev/null $filename") || 1070*4882a593Smuzhiyun die "$P: $filename: diff failed - $!\n"; 1071*4882a593Smuzhiyun } elsif ($filename eq '-') { 1072*4882a593Smuzhiyun open($FILE, '<&STDIN'); 1073*4882a593Smuzhiyun } else { 1074*4882a593Smuzhiyun open($FILE, '<', "$filename") || 1075*4882a593Smuzhiyun die "$P: $filename: open failed - $!\n"; 1076*4882a593Smuzhiyun } 1077*4882a593Smuzhiyun if ($filename eq '-') { 1078*4882a593Smuzhiyun $vname = 'Your patch'; 1079*4882a593Smuzhiyun } elsif ($git) { 1080*4882a593Smuzhiyun $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")'; 1081*4882a593Smuzhiyun } else { 1082*4882a593Smuzhiyun $vname = $filename; 1083*4882a593Smuzhiyun } 1084*4882a593Smuzhiyun while (<$FILE>) { 1085*4882a593Smuzhiyun chomp; 1086*4882a593Smuzhiyun push(@rawlines, $_); 1087*4882a593Smuzhiyun $vname = qq("$1") if ($filename eq '-' && $_ =~ m/^Subject:\s+(.+)/i); 1088*4882a593Smuzhiyun } 1089*4882a593Smuzhiyun close($FILE); 1090*4882a593Smuzhiyun 1091*4882a593Smuzhiyun if ($#ARGV > 0 && $quiet == 0) { 1092*4882a593Smuzhiyun print '-' x length($vname) . "\n"; 1093*4882a593Smuzhiyun print "$vname\n"; 1094*4882a593Smuzhiyun print '-' x length($vname) . "\n"; 1095*4882a593Smuzhiyun } 1096*4882a593Smuzhiyun 1097*4882a593Smuzhiyun if (!process($filename)) { 1098*4882a593Smuzhiyun $exit = 1; 1099*4882a593Smuzhiyun } 1100*4882a593Smuzhiyun @rawlines = (); 1101*4882a593Smuzhiyun @lines = (); 1102*4882a593Smuzhiyun @fixed = (); 1103*4882a593Smuzhiyun @fixed_inserted = (); 1104*4882a593Smuzhiyun @fixed_deleted = (); 1105*4882a593Smuzhiyun $fixlinenr = -1; 1106*4882a593Smuzhiyun @modifierListFile = (); 1107*4882a593Smuzhiyun @typeListFile = (); 1108*4882a593Smuzhiyun build_types(); 1109*4882a593Smuzhiyun $file = $oldfile if ($is_git_file); 1110*4882a593Smuzhiyun} 1111*4882a593Smuzhiyun 1112*4882a593Smuzhiyunif (!$quiet) { 1113*4882a593Smuzhiyun hash_show_words(\%use_type, "Used"); 1114*4882a593Smuzhiyun hash_show_words(\%ignore_type, "Ignored"); 1115*4882a593Smuzhiyun 1116*4882a593Smuzhiyun if (!$perl_version_ok) { 1117*4882a593Smuzhiyun print << "EOM" 1118*4882a593Smuzhiyun 1119*4882a593SmuzhiyunNOTE: perl $^V is not modern enough to detect all possible issues. 1120*4882a593Smuzhiyun An upgrade to at least perl $minimum_perl_version is suggested. 1121*4882a593SmuzhiyunEOM 1122*4882a593Smuzhiyun } 1123*4882a593Smuzhiyun if ($exit) { 1124*4882a593Smuzhiyun print << "EOM" 1125*4882a593Smuzhiyun 1126*4882a593SmuzhiyunNOTE: If any of the errors are false positives, please report 1127*4882a593Smuzhiyun them to the maintainer, see CHECKPATCH in MAINTAINERS. 1128*4882a593SmuzhiyunEOM 1129*4882a593Smuzhiyun } 1130*4882a593Smuzhiyun} 1131*4882a593Smuzhiyun 1132*4882a593Smuzhiyunexit($exit); 1133*4882a593Smuzhiyun 1134*4882a593Smuzhiyunsub top_of_kernel_tree { 1135*4882a593Smuzhiyun my ($root) = @_; 1136*4882a593Smuzhiyun 1137*4882a593Smuzhiyun my @tree_check = ( 1138*4882a593Smuzhiyun "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", 1139*4882a593Smuzhiyun "README", "Documentation", "arch", "include", "drivers", 1140*4882a593Smuzhiyun "fs", "init", "ipc", "kernel", "lib", "scripts", 1141*4882a593Smuzhiyun ); 1142*4882a593Smuzhiyun 1143*4882a593Smuzhiyun foreach my $check (@tree_check) { 1144*4882a593Smuzhiyun if (! -e $root . '/' . $check) { 1145*4882a593Smuzhiyun return 0; 1146*4882a593Smuzhiyun } 1147*4882a593Smuzhiyun } 1148*4882a593Smuzhiyun return 1; 1149*4882a593Smuzhiyun} 1150*4882a593Smuzhiyun 1151*4882a593Smuzhiyunsub parse_email { 1152*4882a593Smuzhiyun my ($formatted_email) = @_; 1153*4882a593Smuzhiyun 1154*4882a593Smuzhiyun my $name = ""; 1155*4882a593Smuzhiyun my $name_comment = ""; 1156*4882a593Smuzhiyun my $address = ""; 1157*4882a593Smuzhiyun my $comment = ""; 1158*4882a593Smuzhiyun 1159*4882a593Smuzhiyun if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { 1160*4882a593Smuzhiyun $name = $1; 1161*4882a593Smuzhiyun $address = $2; 1162*4882a593Smuzhiyun $comment = $3 if defined $3; 1163*4882a593Smuzhiyun } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { 1164*4882a593Smuzhiyun $address = $1; 1165*4882a593Smuzhiyun $comment = $2 if defined $2; 1166*4882a593Smuzhiyun } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { 1167*4882a593Smuzhiyun $address = $1; 1168*4882a593Smuzhiyun $comment = $2 if defined $2; 1169*4882a593Smuzhiyun $formatted_email =~ s/\Q$address\E.*$//; 1170*4882a593Smuzhiyun $name = $formatted_email; 1171*4882a593Smuzhiyun $name = trim($name); 1172*4882a593Smuzhiyun $name =~ s/^\"|\"$//g; 1173*4882a593Smuzhiyun # If there's a name left after stripping spaces and 1174*4882a593Smuzhiyun # leading quotes, and the address doesn't have both 1175*4882a593Smuzhiyun # leading and trailing angle brackets, the address 1176*4882a593Smuzhiyun # is invalid. ie: 1177*4882a593Smuzhiyun # "joe smith joe@smith.com" bad 1178*4882a593Smuzhiyun # "joe smith <joe@smith.com" bad 1179*4882a593Smuzhiyun if ($name ne "" && $address !~ /^<[^>]+>$/) { 1180*4882a593Smuzhiyun $name = ""; 1181*4882a593Smuzhiyun $address = ""; 1182*4882a593Smuzhiyun $comment = ""; 1183*4882a593Smuzhiyun } 1184*4882a593Smuzhiyun } 1185*4882a593Smuzhiyun 1186*4882a593Smuzhiyun $comment = trim($comment); 1187*4882a593Smuzhiyun $name = trim($name); 1188*4882a593Smuzhiyun $name =~ s/^\"|\"$//g; 1189*4882a593Smuzhiyun if ($name =~ s/(\s*\([^\)]+\))\s*//) { 1190*4882a593Smuzhiyun $name_comment = trim($1); 1191*4882a593Smuzhiyun } 1192*4882a593Smuzhiyun $address = trim($address); 1193*4882a593Smuzhiyun $address =~ s/^\<|\>$//g; 1194*4882a593Smuzhiyun 1195*4882a593Smuzhiyun if ($name =~ /[^\w \-]/i) { ##has "must quote" chars 1196*4882a593Smuzhiyun $name =~ s/(?<!\\)"/\\"/g; ##escape quotes 1197*4882a593Smuzhiyun $name = "\"$name\""; 1198*4882a593Smuzhiyun } 1199*4882a593Smuzhiyun 1200*4882a593Smuzhiyun return ($name, $name_comment, $address, $comment); 1201*4882a593Smuzhiyun} 1202*4882a593Smuzhiyun 1203*4882a593Smuzhiyunsub format_email { 1204*4882a593Smuzhiyun my ($name, $name_comment, $address, $comment) = @_; 1205*4882a593Smuzhiyun 1206*4882a593Smuzhiyun my $formatted_email; 1207*4882a593Smuzhiyun 1208*4882a593Smuzhiyun $name_comment = trim($name_comment); 1209*4882a593Smuzhiyun $comment = trim($comment); 1210*4882a593Smuzhiyun $name = trim($name); 1211*4882a593Smuzhiyun $name =~ s/^\"|\"$//g; 1212*4882a593Smuzhiyun $address = trim($address); 1213*4882a593Smuzhiyun 1214*4882a593Smuzhiyun if ($name =~ /[^\w \-]/i) { ##has "must quote" chars 1215*4882a593Smuzhiyun $name =~ s/(?<!\\)"/\\"/g; ##escape quotes 1216*4882a593Smuzhiyun $name = "\"$name\""; 1217*4882a593Smuzhiyun } 1218*4882a593Smuzhiyun 1219*4882a593Smuzhiyun if ("$name" eq "") { 1220*4882a593Smuzhiyun $formatted_email = "$address"; 1221*4882a593Smuzhiyun } else { 1222*4882a593Smuzhiyun $formatted_email = "$name$name_comment <$address>"; 1223*4882a593Smuzhiyun } 1224*4882a593Smuzhiyun $formatted_email .= "$comment"; 1225*4882a593Smuzhiyun return $formatted_email; 1226*4882a593Smuzhiyun} 1227*4882a593Smuzhiyun 1228*4882a593Smuzhiyunsub reformat_email { 1229*4882a593Smuzhiyun my ($email) = @_; 1230*4882a593Smuzhiyun 1231*4882a593Smuzhiyun my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); 1232*4882a593Smuzhiyun return format_email($email_name, $name_comment, $email_address, $comment); 1233*4882a593Smuzhiyun} 1234*4882a593Smuzhiyun 1235*4882a593Smuzhiyunsub same_email_addresses { 1236*4882a593Smuzhiyun my ($email1, $email2, $match_comment) = @_; 1237*4882a593Smuzhiyun 1238*4882a593Smuzhiyun my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1); 1239*4882a593Smuzhiyun my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2); 1240*4882a593Smuzhiyun 1241*4882a593Smuzhiyun if ($match_comment != 1) { 1242*4882a593Smuzhiyun return $email1_name eq $email2_name && 1243*4882a593Smuzhiyun $email1_address eq $email2_address; 1244*4882a593Smuzhiyun } 1245*4882a593Smuzhiyun return $email1_name eq $email2_name && 1246*4882a593Smuzhiyun $email1_address eq $email2_address && 1247*4882a593Smuzhiyun $name1_comment eq $name2_comment && 1248*4882a593Smuzhiyun $comment1 eq $comment2; 1249*4882a593Smuzhiyun} 1250*4882a593Smuzhiyun 1251*4882a593Smuzhiyunsub which { 1252*4882a593Smuzhiyun my ($bin) = @_; 1253*4882a593Smuzhiyun 1254*4882a593Smuzhiyun foreach my $path (split(/:/, $ENV{PATH})) { 1255*4882a593Smuzhiyun if (-e "$path/$bin") { 1256*4882a593Smuzhiyun return "$path/$bin"; 1257*4882a593Smuzhiyun } 1258*4882a593Smuzhiyun } 1259*4882a593Smuzhiyun 1260*4882a593Smuzhiyun return ""; 1261*4882a593Smuzhiyun} 1262*4882a593Smuzhiyun 1263*4882a593Smuzhiyunsub which_conf { 1264*4882a593Smuzhiyun my ($conf) = @_; 1265*4882a593Smuzhiyun 1266*4882a593Smuzhiyun foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { 1267*4882a593Smuzhiyun if (-e "$path/$conf") { 1268*4882a593Smuzhiyun return "$path/$conf"; 1269*4882a593Smuzhiyun } 1270*4882a593Smuzhiyun } 1271*4882a593Smuzhiyun 1272*4882a593Smuzhiyun return ""; 1273*4882a593Smuzhiyun} 1274*4882a593Smuzhiyun 1275*4882a593Smuzhiyunsub expand_tabs { 1276*4882a593Smuzhiyun my ($str) = @_; 1277*4882a593Smuzhiyun 1278*4882a593Smuzhiyun my $res = ''; 1279*4882a593Smuzhiyun my $n = 0; 1280*4882a593Smuzhiyun for my $c (split(//, $str)) { 1281*4882a593Smuzhiyun if ($c eq "\t") { 1282*4882a593Smuzhiyun $res .= ' '; 1283*4882a593Smuzhiyun $n++; 1284*4882a593Smuzhiyun for (; ($n % $tabsize) != 0; $n++) { 1285*4882a593Smuzhiyun $res .= ' '; 1286*4882a593Smuzhiyun } 1287*4882a593Smuzhiyun next; 1288*4882a593Smuzhiyun } 1289*4882a593Smuzhiyun $res .= $c; 1290*4882a593Smuzhiyun $n++; 1291*4882a593Smuzhiyun } 1292*4882a593Smuzhiyun 1293*4882a593Smuzhiyun return $res; 1294*4882a593Smuzhiyun} 1295*4882a593Smuzhiyunsub copy_spacing { 1296*4882a593Smuzhiyun (my $res = shift) =~ tr/\t/ /c; 1297*4882a593Smuzhiyun return $res; 1298*4882a593Smuzhiyun} 1299*4882a593Smuzhiyun 1300*4882a593Smuzhiyunsub line_stats { 1301*4882a593Smuzhiyun my ($line) = @_; 1302*4882a593Smuzhiyun 1303*4882a593Smuzhiyun # Drop the diff line leader and expand tabs 1304*4882a593Smuzhiyun $line =~ s/^.//; 1305*4882a593Smuzhiyun $line = expand_tabs($line); 1306*4882a593Smuzhiyun 1307*4882a593Smuzhiyun # Pick the indent from the front of the line. 1308*4882a593Smuzhiyun my ($white) = ($line =~ /^(\s*)/); 1309*4882a593Smuzhiyun 1310*4882a593Smuzhiyun return (length($line), length($white)); 1311*4882a593Smuzhiyun} 1312*4882a593Smuzhiyun 1313*4882a593Smuzhiyunmy $sanitise_quote = ''; 1314*4882a593Smuzhiyun 1315*4882a593Smuzhiyunsub sanitise_line_reset { 1316*4882a593Smuzhiyun my ($in_comment) = @_; 1317*4882a593Smuzhiyun 1318*4882a593Smuzhiyun if ($in_comment) { 1319*4882a593Smuzhiyun $sanitise_quote = '*/'; 1320*4882a593Smuzhiyun } else { 1321*4882a593Smuzhiyun $sanitise_quote = ''; 1322*4882a593Smuzhiyun } 1323*4882a593Smuzhiyun} 1324*4882a593Smuzhiyunsub sanitise_line { 1325*4882a593Smuzhiyun my ($line) = @_; 1326*4882a593Smuzhiyun 1327*4882a593Smuzhiyun my $res = ''; 1328*4882a593Smuzhiyun my $l = ''; 1329*4882a593Smuzhiyun 1330*4882a593Smuzhiyun my $qlen = 0; 1331*4882a593Smuzhiyun my $off = 0; 1332*4882a593Smuzhiyun my $c; 1333*4882a593Smuzhiyun 1334*4882a593Smuzhiyun # Always copy over the diff marker. 1335*4882a593Smuzhiyun $res = substr($line, 0, 1); 1336*4882a593Smuzhiyun 1337*4882a593Smuzhiyun for ($off = 1; $off < length($line); $off++) { 1338*4882a593Smuzhiyun $c = substr($line, $off, 1); 1339*4882a593Smuzhiyun 1340*4882a593Smuzhiyun # Comments we are whacking completely including the begin 1341*4882a593Smuzhiyun # and end, all to $;. 1342*4882a593Smuzhiyun if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { 1343*4882a593Smuzhiyun $sanitise_quote = '*/'; 1344*4882a593Smuzhiyun 1345*4882a593Smuzhiyun substr($res, $off, 2, "$;$;"); 1346*4882a593Smuzhiyun $off++; 1347*4882a593Smuzhiyun next; 1348*4882a593Smuzhiyun } 1349*4882a593Smuzhiyun if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { 1350*4882a593Smuzhiyun $sanitise_quote = ''; 1351*4882a593Smuzhiyun substr($res, $off, 2, "$;$;"); 1352*4882a593Smuzhiyun $off++; 1353*4882a593Smuzhiyun next; 1354*4882a593Smuzhiyun } 1355*4882a593Smuzhiyun if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { 1356*4882a593Smuzhiyun $sanitise_quote = '//'; 1357*4882a593Smuzhiyun 1358*4882a593Smuzhiyun substr($res, $off, 2, $sanitise_quote); 1359*4882a593Smuzhiyun $off++; 1360*4882a593Smuzhiyun next; 1361*4882a593Smuzhiyun } 1362*4882a593Smuzhiyun 1363*4882a593Smuzhiyun # A \ in a string means ignore the next character. 1364*4882a593Smuzhiyun if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && 1365*4882a593Smuzhiyun $c eq "\\") { 1366*4882a593Smuzhiyun substr($res, $off, 2, 'XX'); 1367*4882a593Smuzhiyun $off++; 1368*4882a593Smuzhiyun next; 1369*4882a593Smuzhiyun } 1370*4882a593Smuzhiyun # Regular quotes. 1371*4882a593Smuzhiyun if ($c eq "'" || $c eq '"') { 1372*4882a593Smuzhiyun if ($sanitise_quote eq '') { 1373*4882a593Smuzhiyun $sanitise_quote = $c; 1374*4882a593Smuzhiyun 1375*4882a593Smuzhiyun substr($res, $off, 1, $c); 1376*4882a593Smuzhiyun next; 1377*4882a593Smuzhiyun } elsif ($sanitise_quote eq $c) { 1378*4882a593Smuzhiyun $sanitise_quote = ''; 1379*4882a593Smuzhiyun } 1380*4882a593Smuzhiyun } 1381*4882a593Smuzhiyun 1382*4882a593Smuzhiyun #print "c<$c> SQ<$sanitise_quote>\n"; 1383*4882a593Smuzhiyun if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { 1384*4882a593Smuzhiyun substr($res, $off, 1, $;); 1385*4882a593Smuzhiyun } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { 1386*4882a593Smuzhiyun substr($res, $off, 1, $;); 1387*4882a593Smuzhiyun } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { 1388*4882a593Smuzhiyun substr($res, $off, 1, 'X'); 1389*4882a593Smuzhiyun } else { 1390*4882a593Smuzhiyun substr($res, $off, 1, $c); 1391*4882a593Smuzhiyun } 1392*4882a593Smuzhiyun } 1393*4882a593Smuzhiyun 1394*4882a593Smuzhiyun if ($sanitise_quote eq '//') { 1395*4882a593Smuzhiyun $sanitise_quote = ''; 1396*4882a593Smuzhiyun } 1397*4882a593Smuzhiyun 1398*4882a593Smuzhiyun # The pathname on a #include may be surrounded by '<' and '>'. 1399*4882a593Smuzhiyun if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { 1400*4882a593Smuzhiyun my $clean = 'X' x length($1); 1401*4882a593Smuzhiyun $res =~ s@\<.*\>@<$clean>@; 1402*4882a593Smuzhiyun 1403*4882a593Smuzhiyun # The whole of a #error is a string. 1404*4882a593Smuzhiyun } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { 1405*4882a593Smuzhiyun my $clean = 'X' x length($1); 1406*4882a593Smuzhiyun $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; 1407*4882a593Smuzhiyun } 1408*4882a593Smuzhiyun 1409*4882a593Smuzhiyun if ($allow_c99_comments && $res =~ m@(//.*$)@) { 1410*4882a593Smuzhiyun my $match = $1; 1411*4882a593Smuzhiyun $res =~ s/\Q$match\E/"$;" x length($match)/e; 1412*4882a593Smuzhiyun } 1413*4882a593Smuzhiyun 1414*4882a593Smuzhiyun return $res; 1415*4882a593Smuzhiyun} 1416*4882a593Smuzhiyun 1417*4882a593Smuzhiyunsub get_quoted_string { 1418*4882a593Smuzhiyun my ($line, $rawline) = @_; 1419*4882a593Smuzhiyun 1420*4882a593Smuzhiyun return "" if (!defined($line) || !defined($rawline)); 1421*4882a593Smuzhiyun return "" if ($line !~ m/($String)/g); 1422*4882a593Smuzhiyun return substr($rawline, $-[0], $+[0] - $-[0]); 1423*4882a593Smuzhiyun} 1424*4882a593Smuzhiyun 1425*4882a593Smuzhiyunsub ctx_statement_block { 1426*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1427*4882a593Smuzhiyun my $line = $linenr - 1; 1428*4882a593Smuzhiyun my $blk = ''; 1429*4882a593Smuzhiyun my $soff = $off; 1430*4882a593Smuzhiyun my $coff = $off - 1; 1431*4882a593Smuzhiyun my $coff_set = 0; 1432*4882a593Smuzhiyun 1433*4882a593Smuzhiyun my $loff = 0; 1434*4882a593Smuzhiyun 1435*4882a593Smuzhiyun my $type = ''; 1436*4882a593Smuzhiyun my $level = 0; 1437*4882a593Smuzhiyun my @stack = (); 1438*4882a593Smuzhiyun my $p; 1439*4882a593Smuzhiyun my $c; 1440*4882a593Smuzhiyun my $len = 0; 1441*4882a593Smuzhiyun 1442*4882a593Smuzhiyun my $remainder; 1443*4882a593Smuzhiyun while (1) { 1444*4882a593Smuzhiyun @stack = (['', 0]) if ($#stack == -1); 1445*4882a593Smuzhiyun 1446*4882a593Smuzhiyun #warn "CSB: blk<$blk> remain<$remain>\n"; 1447*4882a593Smuzhiyun # If we are about to drop off the end, pull in more 1448*4882a593Smuzhiyun # context. 1449*4882a593Smuzhiyun if ($off >= $len) { 1450*4882a593Smuzhiyun for (; $remain > 0; $line++) { 1451*4882a593Smuzhiyun last if (!defined $lines[$line]); 1452*4882a593Smuzhiyun next if ($lines[$line] =~ /^-/); 1453*4882a593Smuzhiyun $remain--; 1454*4882a593Smuzhiyun $loff = $len; 1455*4882a593Smuzhiyun $blk .= $lines[$line] . "\n"; 1456*4882a593Smuzhiyun $len = length($blk); 1457*4882a593Smuzhiyun $line++; 1458*4882a593Smuzhiyun last; 1459*4882a593Smuzhiyun } 1460*4882a593Smuzhiyun # Bail if there is no further context. 1461*4882a593Smuzhiyun #warn "CSB: blk<$blk> off<$off> len<$len>\n"; 1462*4882a593Smuzhiyun if ($off >= $len) { 1463*4882a593Smuzhiyun last; 1464*4882a593Smuzhiyun } 1465*4882a593Smuzhiyun if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { 1466*4882a593Smuzhiyun $level++; 1467*4882a593Smuzhiyun $type = '#'; 1468*4882a593Smuzhiyun } 1469*4882a593Smuzhiyun } 1470*4882a593Smuzhiyun $p = $c; 1471*4882a593Smuzhiyun $c = substr($blk, $off, 1); 1472*4882a593Smuzhiyun $remainder = substr($blk, $off); 1473*4882a593Smuzhiyun 1474*4882a593Smuzhiyun #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; 1475*4882a593Smuzhiyun 1476*4882a593Smuzhiyun # Handle nested #if/#else. 1477*4882a593Smuzhiyun if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { 1478*4882a593Smuzhiyun push(@stack, [ $type, $level ]); 1479*4882a593Smuzhiyun } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { 1480*4882a593Smuzhiyun ($type, $level) = @{$stack[$#stack - 1]}; 1481*4882a593Smuzhiyun } elsif ($remainder =~ /^#\s*endif\b/) { 1482*4882a593Smuzhiyun ($type, $level) = @{pop(@stack)}; 1483*4882a593Smuzhiyun } 1484*4882a593Smuzhiyun 1485*4882a593Smuzhiyun # Statement ends at the ';' or a close '}' at the 1486*4882a593Smuzhiyun # outermost level. 1487*4882a593Smuzhiyun if ($level == 0 && $c eq ';') { 1488*4882a593Smuzhiyun last; 1489*4882a593Smuzhiyun } 1490*4882a593Smuzhiyun 1491*4882a593Smuzhiyun # An else is really a conditional as long as its not else if 1492*4882a593Smuzhiyun if ($level == 0 && $coff_set == 0 && 1493*4882a593Smuzhiyun (!defined($p) || $p =~ /(?:\s|\}|\+)/) && 1494*4882a593Smuzhiyun $remainder =~ /^(else)(?:\s|{)/ && 1495*4882a593Smuzhiyun $remainder !~ /^else\s+if\b/) { 1496*4882a593Smuzhiyun $coff = $off + length($1) - 1; 1497*4882a593Smuzhiyun $coff_set = 1; 1498*4882a593Smuzhiyun #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; 1499*4882a593Smuzhiyun #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; 1500*4882a593Smuzhiyun } 1501*4882a593Smuzhiyun 1502*4882a593Smuzhiyun if (($type eq '' || $type eq '(') && $c eq '(') { 1503*4882a593Smuzhiyun $level++; 1504*4882a593Smuzhiyun $type = '('; 1505*4882a593Smuzhiyun } 1506*4882a593Smuzhiyun if ($type eq '(' && $c eq ')') { 1507*4882a593Smuzhiyun $level--; 1508*4882a593Smuzhiyun $type = ($level != 0)? '(' : ''; 1509*4882a593Smuzhiyun 1510*4882a593Smuzhiyun if ($level == 0 && $coff < $soff) { 1511*4882a593Smuzhiyun $coff = $off; 1512*4882a593Smuzhiyun $coff_set = 1; 1513*4882a593Smuzhiyun #warn "CSB: mark coff<$coff>\n"; 1514*4882a593Smuzhiyun } 1515*4882a593Smuzhiyun } 1516*4882a593Smuzhiyun if (($type eq '' || $type eq '{') && $c eq '{') { 1517*4882a593Smuzhiyun $level++; 1518*4882a593Smuzhiyun $type = '{'; 1519*4882a593Smuzhiyun } 1520*4882a593Smuzhiyun if ($type eq '{' && $c eq '}') { 1521*4882a593Smuzhiyun $level--; 1522*4882a593Smuzhiyun $type = ($level != 0)? '{' : ''; 1523*4882a593Smuzhiyun 1524*4882a593Smuzhiyun if ($level == 0) { 1525*4882a593Smuzhiyun if (substr($blk, $off + 1, 1) eq ';') { 1526*4882a593Smuzhiyun $off++; 1527*4882a593Smuzhiyun } 1528*4882a593Smuzhiyun last; 1529*4882a593Smuzhiyun } 1530*4882a593Smuzhiyun } 1531*4882a593Smuzhiyun # Preprocessor commands end at the newline unless escaped. 1532*4882a593Smuzhiyun if ($type eq '#' && $c eq "\n" && $p ne "\\") { 1533*4882a593Smuzhiyun $level--; 1534*4882a593Smuzhiyun $type = ''; 1535*4882a593Smuzhiyun $off++; 1536*4882a593Smuzhiyun last; 1537*4882a593Smuzhiyun } 1538*4882a593Smuzhiyun $off++; 1539*4882a593Smuzhiyun } 1540*4882a593Smuzhiyun # We are truly at the end, so shuffle to the next line. 1541*4882a593Smuzhiyun if ($off == $len) { 1542*4882a593Smuzhiyun $loff = $len + 1; 1543*4882a593Smuzhiyun $line++; 1544*4882a593Smuzhiyun $remain--; 1545*4882a593Smuzhiyun } 1546*4882a593Smuzhiyun 1547*4882a593Smuzhiyun my $statement = substr($blk, $soff, $off - $soff + 1); 1548*4882a593Smuzhiyun my $condition = substr($blk, $soff, $coff - $soff + 1); 1549*4882a593Smuzhiyun 1550*4882a593Smuzhiyun #warn "STATEMENT<$statement>\n"; 1551*4882a593Smuzhiyun #warn "CONDITION<$condition>\n"; 1552*4882a593Smuzhiyun 1553*4882a593Smuzhiyun #print "coff<$coff> soff<$off> loff<$loff>\n"; 1554*4882a593Smuzhiyun 1555*4882a593Smuzhiyun return ($statement, $condition, 1556*4882a593Smuzhiyun $line, $remain + 1, $off - $loff + 1, $level); 1557*4882a593Smuzhiyun} 1558*4882a593Smuzhiyun 1559*4882a593Smuzhiyunsub statement_lines { 1560*4882a593Smuzhiyun my ($stmt) = @_; 1561*4882a593Smuzhiyun 1562*4882a593Smuzhiyun # Strip the diff line prefixes and rip blank lines at start and end. 1563*4882a593Smuzhiyun $stmt =~ s/(^|\n)./$1/g; 1564*4882a593Smuzhiyun $stmt =~ s/^\s*//; 1565*4882a593Smuzhiyun $stmt =~ s/\s*$//; 1566*4882a593Smuzhiyun 1567*4882a593Smuzhiyun my @stmt_lines = ($stmt =~ /\n/g); 1568*4882a593Smuzhiyun 1569*4882a593Smuzhiyun return $#stmt_lines + 2; 1570*4882a593Smuzhiyun} 1571*4882a593Smuzhiyun 1572*4882a593Smuzhiyunsub statement_rawlines { 1573*4882a593Smuzhiyun my ($stmt) = @_; 1574*4882a593Smuzhiyun 1575*4882a593Smuzhiyun my @stmt_lines = ($stmt =~ /\n/g); 1576*4882a593Smuzhiyun 1577*4882a593Smuzhiyun return $#stmt_lines + 2; 1578*4882a593Smuzhiyun} 1579*4882a593Smuzhiyun 1580*4882a593Smuzhiyunsub statement_block_size { 1581*4882a593Smuzhiyun my ($stmt) = @_; 1582*4882a593Smuzhiyun 1583*4882a593Smuzhiyun $stmt =~ s/(^|\n)./$1/g; 1584*4882a593Smuzhiyun $stmt =~ s/^\s*{//; 1585*4882a593Smuzhiyun $stmt =~ s/}\s*$//; 1586*4882a593Smuzhiyun $stmt =~ s/^\s*//; 1587*4882a593Smuzhiyun $stmt =~ s/\s*$//; 1588*4882a593Smuzhiyun 1589*4882a593Smuzhiyun my @stmt_lines = ($stmt =~ /\n/g); 1590*4882a593Smuzhiyun my @stmt_statements = ($stmt =~ /;/g); 1591*4882a593Smuzhiyun 1592*4882a593Smuzhiyun my $stmt_lines = $#stmt_lines + 2; 1593*4882a593Smuzhiyun my $stmt_statements = $#stmt_statements + 1; 1594*4882a593Smuzhiyun 1595*4882a593Smuzhiyun if ($stmt_lines > $stmt_statements) { 1596*4882a593Smuzhiyun return $stmt_lines; 1597*4882a593Smuzhiyun } else { 1598*4882a593Smuzhiyun return $stmt_statements; 1599*4882a593Smuzhiyun } 1600*4882a593Smuzhiyun} 1601*4882a593Smuzhiyun 1602*4882a593Smuzhiyunsub ctx_statement_full { 1603*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1604*4882a593Smuzhiyun my ($statement, $condition, $level); 1605*4882a593Smuzhiyun 1606*4882a593Smuzhiyun my (@chunks); 1607*4882a593Smuzhiyun 1608*4882a593Smuzhiyun # Grab the first conditional/block pair. 1609*4882a593Smuzhiyun ($statement, $condition, $linenr, $remain, $off, $level) = 1610*4882a593Smuzhiyun ctx_statement_block($linenr, $remain, $off); 1611*4882a593Smuzhiyun #print "F: c<$condition> s<$statement> remain<$remain>\n"; 1612*4882a593Smuzhiyun push(@chunks, [ $condition, $statement ]); 1613*4882a593Smuzhiyun if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { 1614*4882a593Smuzhiyun return ($level, $linenr, @chunks); 1615*4882a593Smuzhiyun } 1616*4882a593Smuzhiyun 1617*4882a593Smuzhiyun # Pull in the following conditional/block pairs and see if they 1618*4882a593Smuzhiyun # could continue the statement. 1619*4882a593Smuzhiyun for (;;) { 1620*4882a593Smuzhiyun ($statement, $condition, $linenr, $remain, $off, $level) = 1621*4882a593Smuzhiyun ctx_statement_block($linenr, $remain, $off); 1622*4882a593Smuzhiyun #print "C: c<$condition> s<$statement> remain<$remain>\n"; 1623*4882a593Smuzhiyun last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); 1624*4882a593Smuzhiyun #print "C: push\n"; 1625*4882a593Smuzhiyun push(@chunks, [ $condition, $statement ]); 1626*4882a593Smuzhiyun } 1627*4882a593Smuzhiyun 1628*4882a593Smuzhiyun return ($level, $linenr, @chunks); 1629*4882a593Smuzhiyun} 1630*4882a593Smuzhiyun 1631*4882a593Smuzhiyunsub ctx_block_get { 1632*4882a593Smuzhiyun my ($linenr, $remain, $outer, $open, $close, $off) = @_; 1633*4882a593Smuzhiyun my $line; 1634*4882a593Smuzhiyun my $start = $linenr - 1; 1635*4882a593Smuzhiyun my $blk = ''; 1636*4882a593Smuzhiyun my @o; 1637*4882a593Smuzhiyun my @c; 1638*4882a593Smuzhiyun my @res = (); 1639*4882a593Smuzhiyun 1640*4882a593Smuzhiyun my $level = 0; 1641*4882a593Smuzhiyun my @stack = ($level); 1642*4882a593Smuzhiyun for ($line = $start; $remain > 0; $line++) { 1643*4882a593Smuzhiyun next if ($rawlines[$line] =~ /^-/); 1644*4882a593Smuzhiyun $remain--; 1645*4882a593Smuzhiyun 1646*4882a593Smuzhiyun $blk .= $rawlines[$line]; 1647*4882a593Smuzhiyun 1648*4882a593Smuzhiyun # Handle nested #if/#else. 1649*4882a593Smuzhiyun if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { 1650*4882a593Smuzhiyun push(@stack, $level); 1651*4882a593Smuzhiyun } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { 1652*4882a593Smuzhiyun $level = $stack[$#stack - 1]; 1653*4882a593Smuzhiyun } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { 1654*4882a593Smuzhiyun $level = pop(@stack); 1655*4882a593Smuzhiyun } 1656*4882a593Smuzhiyun 1657*4882a593Smuzhiyun foreach my $c (split(//, $lines[$line])) { 1658*4882a593Smuzhiyun ##print "C<$c>L<$level><$open$close>O<$off>\n"; 1659*4882a593Smuzhiyun if ($off > 0) { 1660*4882a593Smuzhiyun $off--; 1661*4882a593Smuzhiyun next; 1662*4882a593Smuzhiyun } 1663*4882a593Smuzhiyun 1664*4882a593Smuzhiyun if ($c eq $close && $level > 0) { 1665*4882a593Smuzhiyun $level--; 1666*4882a593Smuzhiyun last if ($level == 0); 1667*4882a593Smuzhiyun } elsif ($c eq $open) { 1668*4882a593Smuzhiyun $level++; 1669*4882a593Smuzhiyun } 1670*4882a593Smuzhiyun } 1671*4882a593Smuzhiyun 1672*4882a593Smuzhiyun if (!$outer || $level <= 1) { 1673*4882a593Smuzhiyun push(@res, $rawlines[$line]); 1674*4882a593Smuzhiyun } 1675*4882a593Smuzhiyun 1676*4882a593Smuzhiyun last if ($level == 0); 1677*4882a593Smuzhiyun } 1678*4882a593Smuzhiyun 1679*4882a593Smuzhiyun return ($level, @res); 1680*4882a593Smuzhiyun} 1681*4882a593Smuzhiyunsub ctx_block_outer { 1682*4882a593Smuzhiyun my ($linenr, $remain) = @_; 1683*4882a593Smuzhiyun 1684*4882a593Smuzhiyun my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); 1685*4882a593Smuzhiyun return @r; 1686*4882a593Smuzhiyun} 1687*4882a593Smuzhiyunsub ctx_block { 1688*4882a593Smuzhiyun my ($linenr, $remain) = @_; 1689*4882a593Smuzhiyun 1690*4882a593Smuzhiyun my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); 1691*4882a593Smuzhiyun return @r; 1692*4882a593Smuzhiyun} 1693*4882a593Smuzhiyunsub ctx_statement { 1694*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1695*4882a593Smuzhiyun 1696*4882a593Smuzhiyun my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); 1697*4882a593Smuzhiyun return @r; 1698*4882a593Smuzhiyun} 1699*4882a593Smuzhiyunsub ctx_block_level { 1700*4882a593Smuzhiyun my ($linenr, $remain) = @_; 1701*4882a593Smuzhiyun 1702*4882a593Smuzhiyun return ctx_block_get($linenr, $remain, 0, '{', '}', 0); 1703*4882a593Smuzhiyun} 1704*4882a593Smuzhiyunsub ctx_statement_level { 1705*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1706*4882a593Smuzhiyun 1707*4882a593Smuzhiyun return ctx_block_get($linenr, $remain, 0, '(', ')', $off); 1708*4882a593Smuzhiyun} 1709*4882a593Smuzhiyun 1710*4882a593Smuzhiyunsub ctx_locate_comment { 1711*4882a593Smuzhiyun my ($first_line, $end_line) = @_; 1712*4882a593Smuzhiyun 1713*4882a593Smuzhiyun # If c99 comment on the current line, or the line before or after 1714*4882a593Smuzhiyun my ($current_comment) = ($rawlines[$end_line - 1] =~ m@^\+.*(//.*$)@); 1715*4882a593Smuzhiyun return $current_comment if (defined $current_comment); 1716*4882a593Smuzhiyun ($current_comment) = ($rawlines[$end_line - 2] =~ m@^[\+ ].*(//.*$)@); 1717*4882a593Smuzhiyun return $current_comment if (defined $current_comment); 1718*4882a593Smuzhiyun ($current_comment) = ($rawlines[$end_line] =~ m@^[\+ ].*(//.*$)@); 1719*4882a593Smuzhiyun return $current_comment if (defined $current_comment); 1720*4882a593Smuzhiyun 1721*4882a593Smuzhiyun # Catch a comment on the end of the line itself. 1722*4882a593Smuzhiyun ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); 1723*4882a593Smuzhiyun return $current_comment if (defined $current_comment); 1724*4882a593Smuzhiyun 1725*4882a593Smuzhiyun # Look through the context and try and figure out if there is a 1726*4882a593Smuzhiyun # comment. 1727*4882a593Smuzhiyun my $in_comment = 0; 1728*4882a593Smuzhiyun $current_comment = ''; 1729*4882a593Smuzhiyun for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { 1730*4882a593Smuzhiyun my $line = $rawlines[$linenr - 1]; 1731*4882a593Smuzhiyun #warn " $line\n"; 1732*4882a593Smuzhiyun if ($linenr == $first_line and $line =~ m@^.\s*\*@) { 1733*4882a593Smuzhiyun $in_comment = 1; 1734*4882a593Smuzhiyun } 1735*4882a593Smuzhiyun if ($line =~ m@/\*@) { 1736*4882a593Smuzhiyun $in_comment = 1; 1737*4882a593Smuzhiyun } 1738*4882a593Smuzhiyun if (!$in_comment && $current_comment ne '') { 1739*4882a593Smuzhiyun $current_comment = ''; 1740*4882a593Smuzhiyun } 1741*4882a593Smuzhiyun $current_comment .= $line . "\n" if ($in_comment); 1742*4882a593Smuzhiyun if ($line =~ m@\*/@) { 1743*4882a593Smuzhiyun $in_comment = 0; 1744*4882a593Smuzhiyun } 1745*4882a593Smuzhiyun } 1746*4882a593Smuzhiyun 1747*4882a593Smuzhiyun chomp($current_comment); 1748*4882a593Smuzhiyun return($current_comment); 1749*4882a593Smuzhiyun} 1750*4882a593Smuzhiyunsub ctx_has_comment { 1751*4882a593Smuzhiyun my ($first_line, $end_line) = @_; 1752*4882a593Smuzhiyun my $cmt = ctx_locate_comment($first_line, $end_line); 1753*4882a593Smuzhiyun 1754*4882a593Smuzhiyun ##print "LINE: $rawlines[$end_line - 1 ]\n"; 1755*4882a593Smuzhiyun ##print "CMMT: $cmt\n"; 1756*4882a593Smuzhiyun 1757*4882a593Smuzhiyun return ($cmt ne ''); 1758*4882a593Smuzhiyun} 1759*4882a593Smuzhiyun 1760*4882a593Smuzhiyunsub raw_line { 1761*4882a593Smuzhiyun my ($linenr, $cnt) = @_; 1762*4882a593Smuzhiyun 1763*4882a593Smuzhiyun my $offset = $linenr - 1; 1764*4882a593Smuzhiyun $cnt++; 1765*4882a593Smuzhiyun 1766*4882a593Smuzhiyun my $line; 1767*4882a593Smuzhiyun while ($cnt) { 1768*4882a593Smuzhiyun $line = $rawlines[$offset++]; 1769*4882a593Smuzhiyun next if (defined($line) && $line =~ /^-/); 1770*4882a593Smuzhiyun $cnt--; 1771*4882a593Smuzhiyun } 1772*4882a593Smuzhiyun 1773*4882a593Smuzhiyun return $line; 1774*4882a593Smuzhiyun} 1775*4882a593Smuzhiyun 1776*4882a593Smuzhiyunsub get_stat_real { 1777*4882a593Smuzhiyun my ($linenr, $lc) = @_; 1778*4882a593Smuzhiyun 1779*4882a593Smuzhiyun my $stat_real = raw_line($linenr, 0); 1780*4882a593Smuzhiyun for (my $count = $linenr + 1; $count <= $lc; $count++) { 1781*4882a593Smuzhiyun $stat_real = $stat_real . "\n" . raw_line($count, 0); 1782*4882a593Smuzhiyun } 1783*4882a593Smuzhiyun 1784*4882a593Smuzhiyun return $stat_real; 1785*4882a593Smuzhiyun} 1786*4882a593Smuzhiyun 1787*4882a593Smuzhiyunsub get_stat_here { 1788*4882a593Smuzhiyun my ($linenr, $cnt, $here) = @_; 1789*4882a593Smuzhiyun 1790*4882a593Smuzhiyun my $herectx = $here . "\n"; 1791*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 1792*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 1793*4882a593Smuzhiyun } 1794*4882a593Smuzhiyun 1795*4882a593Smuzhiyun return $herectx; 1796*4882a593Smuzhiyun} 1797*4882a593Smuzhiyun 1798*4882a593Smuzhiyunsub cat_vet { 1799*4882a593Smuzhiyun my ($vet) = @_; 1800*4882a593Smuzhiyun my ($res, $coded); 1801*4882a593Smuzhiyun 1802*4882a593Smuzhiyun $res = ''; 1803*4882a593Smuzhiyun while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { 1804*4882a593Smuzhiyun $res .= $1; 1805*4882a593Smuzhiyun if ($2 ne '') { 1806*4882a593Smuzhiyun $coded = sprintf("^%c", unpack('C', $2) + 64); 1807*4882a593Smuzhiyun $res .= $coded; 1808*4882a593Smuzhiyun } 1809*4882a593Smuzhiyun } 1810*4882a593Smuzhiyun $res =~ s/$/\$/; 1811*4882a593Smuzhiyun 1812*4882a593Smuzhiyun return $res; 1813*4882a593Smuzhiyun} 1814*4882a593Smuzhiyun 1815*4882a593Smuzhiyunmy $av_preprocessor = 0; 1816*4882a593Smuzhiyunmy $av_pending; 1817*4882a593Smuzhiyunmy @av_paren_type; 1818*4882a593Smuzhiyunmy $av_pend_colon; 1819*4882a593Smuzhiyun 1820*4882a593Smuzhiyunsub annotate_reset { 1821*4882a593Smuzhiyun $av_preprocessor = 0; 1822*4882a593Smuzhiyun $av_pending = '_'; 1823*4882a593Smuzhiyun @av_paren_type = ('E'); 1824*4882a593Smuzhiyun $av_pend_colon = 'O'; 1825*4882a593Smuzhiyun} 1826*4882a593Smuzhiyun 1827*4882a593Smuzhiyunsub annotate_values { 1828*4882a593Smuzhiyun my ($stream, $type) = @_; 1829*4882a593Smuzhiyun 1830*4882a593Smuzhiyun my $res; 1831*4882a593Smuzhiyun my $var = '_' x length($stream); 1832*4882a593Smuzhiyun my $cur = $stream; 1833*4882a593Smuzhiyun 1834*4882a593Smuzhiyun print "$stream\n" if ($dbg_values > 1); 1835*4882a593Smuzhiyun 1836*4882a593Smuzhiyun while (length($cur)) { 1837*4882a593Smuzhiyun @av_paren_type = ('E') if ($#av_paren_type < 0); 1838*4882a593Smuzhiyun print " <" . join('', @av_paren_type) . 1839*4882a593Smuzhiyun "> <$type> <$av_pending>" if ($dbg_values > 1); 1840*4882a593Smuzhiyun if ($cur =~ /^(\s+)/o) { 1841*4882a593Smuzhiyun print "WS($1)\n" if ($dbg_values > 1); 1842*4882a593Smuzhiyun if ($1 =~ /\n/ && $av_preprocessor) { 1843*4882a593Smuzhiyun $type = pop(@av_paren_type); 1844*4882a593Smuzhiyun $av_preprocessor = 0; 1845*4882a593Smuzhiyun } 1846*4882a593Smuzhiyun 1847*4882a593Smuzhiyun } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { 1848*4882a593Smuzhiyun print "CAST($1)\n" if ($dbg_values > 1); 1849*4882a593Smuzhiyun push(@av_paren_type, $type); 1850*4882a593Smuzhiyun $type = 'c'; 1851*4882a593Smuzhiyun 1852*4882a593Smuzhiyun } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { 1853*4882a593Smuzhiyun print "DECLARE($1)\n" if ($dbg_values > 1); 1854*4882a593Smuzhiyun $type = 'T'; 1855*4882a593Smuzhiyun 1856*4882a593Smuzhiyun } elsif ($cur =~ /^($Modifier)\s*/) { 1857*4882a593Smuzhiyun print "MODIFIER($1)\n" if ($dbg_values > 1); 1858*4882a593Smuzhiyun $type = 'T'; 1859*4882a593Smuzhiyun 1860*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { 1861*4882a593Smuzhiyun print "DEFINE($1,$2)\n" if ($dbg_values > 1); 1862*4882a593Smuzhiyun $av_preprocessor = 1; 1863*4882a593Smuzhiyun push(@av_paren_type, $type); 1864*4882a593Smuzhiyun if ($2 ne '') { 1865*4882a593Smuzhiyun $av_pending = 'N'; 1866*4882a593Smuzhiyun } 1867*4882a593Smuzhiyun $type = 'E'; 1868*4882a593Smuzhiyun 1869*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { 1870*4882a593Smuzhiyun print "UNDEF($1)\n" if ($dbg_values > 1); 1871*4882a593Smuzhiyun $av_preprocessor = 1; 1872*4882a593Smuzhiyun push(@av_paren_type, $type); 1873*4882a593Smuzhiyun 1874*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { 1875*4882a593Smuzhiyun print "PRE_START($1)\n" if ($dbg_values > 1); 1876*4882a593Smuzhiyun $av_preprocessor = 1; 1877*4882a593Smuzhiyun 1878*4882a593Smuzhiyun push(@av_paren_type, $type); 1879*4882a593Smuzhiyun push(@av_paren_type, $type); 1880*4882a593Smuzhiyun $type = 'E'; 1881*4882a593Smuzhiyun 1882*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { 1883*4882a593Smuzhiyun print "PRE_RESTART($1)\n" if ($dbg_values > 1); 1884*4882a593Smuzhiyun $av_preprocessor = 1; 1885*4882a593Smuzhiyun 1886*4882a593Smuzhiyun push(@av_paren_type, $av_paren_type[$#av_paren_type]); 1887*4882a593Smuzhiyun 1888*4882a593Smuzhiyun $type = 'E'; 1889*4882a593Smuzhiyun 1890*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:endif))/o) { 1891*4882a593Smuzhiyun print "PRE_END($1)\n" if ($dbg_values > 1); 1892*4882a593Smuzhiyun 1893*4882a593Smuzhiyun $av_preprocessor = 1; 1894*4882a593Smuzhiyun 1895*4882a593Smuzhiyun # Assume all arms of the conditional end as this 1896*4882a593Smuzhiyun # one does, and continue as if the #endif was not here. 1897*4882a593Smuzhiyun pop(@av_paren_type); 1898*4882a593Smuzhiyun push(@av_paren_type, $type); 1899*4882a593Smuzhiyun $type = 'E'; 1900*4882a593Smuzhiyun 1901*4882a593Smuzhiyun } elsif ($cur =~ /^(\\\n)/o) { 1902*4882a593Smuzhiyun print "PRECONT($1)\n" if ($dbg_values > 1); 1903*4882a593Smuzhiyun 1904*4882a593Smuzhiyun } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { 1905*4882a593Smuzhiyun print "ATTR($1)\n" if ($dbg_values > 1); 1906*4882a593Smuzhiyun $av_pending = $type; 1907*4882a593Smuzhiyun $type = 'N'; 1908*4882a593Smuzhiyun 1909*4882a593Smuzhiyun } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { 1910*4882a593Smuzhiyun print "SIZEOF($1)\n" if ($dbg_values > 1); 1911*4882a593Smuzhiyun if (defined $2) { 1912*4882a593Smuzhiyun $av_pending = 'V'; 1913*4882a593Smuzhiyun } 1914*4882a593Smuzhiyun $type = 'N'; 1915*4882a593Smuzhiyun 1916*4882a593Smuzhiyun } elsif ($cur =~ /^(if|while|for)\b/o) { 1917*4882a593Smuzhiyun print "COND($1)\n" if ($dbg_values > 1); 1918*4882a593Smuzhiyun $av_pending = 'E'; 1919*4882a593Smuzhiyun $type = 'N'; 1920*4882a593Smuzhiyun 1921*4882a593Smuzhiyun } elsif ($cur =~/^(case)/o) { 1922*4882a593Smuzhiyun print "CASE($1)\n" if ($dbg_values > 1); 1923*4882a593Smuzhiyun $av_pend_colon = 'C'; 1924*4882a593Smuzhiyun $type = 'N'; 1925*4882a593Smuzhiyun 1926*4882a593Smuzhiyun } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { 1927*4882a593Smuzhiyun print "KEYWORD($1)\n" if ($dbg_values > 1); 1928*4882a593Smuzhiyun $type = 'N'; 1929*4882a593Smuzhiyun 1930*4882a593Smuzhiyun } elsif ($cur =~ /^(\()/o) { 1931*4882a593Smuzhiyun print "PAREN('$1')\n" if ($dbg_values > 1); 1932*4882a593Smuzhiyun push(@av_paren_type, $av_pending); 1933*4882a593Smuzhiyun $av_pending = '_'; 1934*4882a593Smuzhiyun $type = 'N'; 1935*4882a593Smuzhiyun 1936*4882a593Smuzhiyun } elsif ($cur =~ /^(\))/o) { 1937*4882a593Smuzhiyun my $new_type = pop(@av_paren_type); 1938*4882a593Smuzhiyun if ($new_type ne '_') { 1939*4882a593Smuzhiyun $type = $new_type; 1940*4882a593Smuzhiyun print "PAREN('$1') -> $type\n" 1941*4882a593Smuzhiyun if ($dbg_values > 1); 1942*4882a593Smuzhiyun } else { 1943*4882a593Smuzhiyun print "PAREN('$1')\n" if ($dbg_values > 1); 1944*4882a593Smuzhiyun } 1945*4882a593Smuzhiyun 1946*4882a593Smuzhiyun } elsif ($cur =~ /^($Ident)\s*\(/o) { 1947*4882a593Smuzhiyun print "FUNC($1)\n" if ($dbg_values > 1); 1948*4882a593Smuzhiyun $type = 'V'; 1949*4882a593Smuzhiyun $av_pending = 'V'; 1950*4882a593Smuzhiyun 1951*4882a593Smuzhiyun } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { 1952*4882a593Smuzhiyun if (defined $2 && $type eq 'C' || $type eq 'T') { 1953*4882a593Smuzhiyun $av_pend_colon = 'B'; 1954*4882a593Smuzhiyun } elsif ($type eq 'E') { 1955*4882a593Smuzhiyun $av_pend_colon = 'L'; 1956*4882a593Smuzhiyun } 1957*4882a593Smuzhiyun print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); 1958*4882a593Smuzhiyun $type = 'V'; 1959*4882a593Smuzhiyun 1960*4882a593Smuzhiyun } elsif ($cur =~ /^($Ident|$Constant)/o) { 1961*4882a593Smuzhiyun print "IDENT($1)\n" if ($dbg_values > 1); 1962*4882a593Smuzhiyun $type = 'V'; 1963*4882a593Smuzhiyun 1964*4882a593Smuzhiyun } elsif ($cur =~ /^($Assignment)/o) { 1965*4882a593Smuzhiyun print "ASSIGN($1)\n" if ($dbg_values > 1); 1966*4882a593Smuzhiyun $type = 'N'; 1967*4882a593Smuzhiyun 1968*4882a593Smuzhiyun } elsif ($cur =~/^(;|{|})/) { 1969*4882a593Smuzhiyun print "END($1)\n" if ($dbg_values > 1); 1970*4882a593Smuzhiyun $type = 'E'; 1971*4882a593Smuzhiyun $av_pend_colon = 'O'; 1972*4882a593Smuzhiyun 1973*4882a593Smuzhiyun } elsif ($cur =~/^(,)/) { 1974*4882a593Smuzhiyun print "COMMA($1)\n" if ($dbg_values > 1); 1975*4882a593Smuzhiyun $type = 'C'; 1976*4882a593Smuzhiyun 1977*4882a593Smuzhiyun } elsif ($cur =~ /^(\?)/o) { 1978*4882a593Smuzhiyun print "QUESTION($1)\n" if ($dbg_values > 1); 1979*4882a593Smuzhiyun $type = 'N'; 1980*4882a593Smuzhiyun 1981*4882a593Smuzhiyun } elsif ($cur =~ /^(:)/o) { 1982*4882a593Smuzhiyun print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); 1983*4882a593Smuzhiyun 1984*4882a593Smuzhiyun substr($var, length($res), 1, $av_pend_colon); 1985*4882a593Smuzhiyun if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { 1986*4882a593Smuzhiyun $type = 'E'; 1987*4882a593Smuzhiyun } else { 1988*4882a593Smuzhiyun $type = 'N'; 1989*4882a593Smuzhiyun } 1990*4882a593Smuzhiyun $av_pend_colon = 'O'; 1991*4882a593Smuzhiyun 1992*4882a593Smuzhiyun } elsif ($cur =~ /^(\[)/o) { 1993*4882a593Smuzhiyun print "CLOSE($1)\n" if ($dbg_values > 1); 1994*4882a593Smuzhiyun $type = 'N'; 1995*4882a593Smuzhiyun 1996*4882a593Smuzhiyun } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { 1997*4882a593Smuzhiyun my $variant; 1998*4882a593Smuzhiyun 1999*4882a593Smuzhiyun print "OPV($1)\n" if ($dbg_values > 1); 2000*4882a593Smuzhiyun if ($type eq 'V') { 2001*4882a593Smuzhiyun $variant = 'B'; 2002*4882a593Smuzhiyun } else { 2003*4882a593Smuzhiyun $variant = 'U'; 2004*4882a593Smuzhiyun } 2005*4882a593Smuzhiyun 2006*4882a593Smuzhiyun substr($var, length($res), 1, $variant); 2007*4882a593Smuzhiyun $type = 'N'; 2008*4882a593Smuzhiyun 2009*4882a593Smuzhiyun } elsif ($cur =~ /^($Operators)/o) { 2010*4882a593Smuzhiyun print "OP($1)\n" if ($dbg_values > 1); 2011*4882a593Smuzhiyun if ($1 ne '++' && $1 ne '--') { 2012*4882a593Smuzhiyun $type = 'N'; 2013*4882a593Smuzhiyun } 2014*4882a593Smuzhiyun 2015*4882a593Smuzhiyun } elsif ($cur =~ /(^.)/o) { 2016*4882a593Smuzhiyun print "C($1)\n" if ($dbg_values > 1); 2017*4882a593Smuzhiyun } 2018*4882a593Smuzhiyun if (defined $1) { 2019*4882a593Smuzhiyun $cur = substr($cur, length($1)); 2020*4882a593Smuzhiyun $res .= $type x length($1); 2021*4882a593Smuzhiyun } 2022*4882a593Smuzhiyun } 2023*4882a593Smuzhiyun 2024*4882a593Smuzhiyun return ($res, $var); 2025*4882a593Smuzhiyun} 2026*4882a593Smuzhiyun 2027*4882a593Smuzhiyunsub possible { 2028*4882a593Smuzhiyun my ($possible, $line) = @_; 2029*4882a593Smuzhiyun my $notPermitted = qr{(?: 2030*4882a593Smuzhiyun ^(?: 2031*4882a593Smuzhiyun $Modifier| 2032*4882a593Smuzhiyun $Storage| 2033*4882a593Smuzhiyun $Type| 2034*4882a593Smuzhiyun DEFINE_\S+ 2035*4882a593Smuzhiyun )$| 2036*4882a593Smuzhiyun ^(?: 2037*4882a593Smuzhiyun goto| 2038*4882a593Smuzhiyun return| 2039*4882a593Smuzhiyun case| 2040*4882a593Smuzhiyun else| 2041*4882a593Smuzhiyun asm|__asm__| 2042*4882a593Smuzhiyun do| 2043*4882a593Smuzhiyun \#| 2044*4882a593Smuzhiyun \#\#| 2045*4882a593Smuzhiyun )(?:\s|$)| 2046*4882a593Smuzhiyun ^(?:typedef|struct|enum)\b 2047*4882a593Smuzhiyun )}x; 2048*4882a593Smuzhiyun warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); 2049*4882a593Smuzhiyun if ($possible !~ $notPermitted) { 2050*4882a593Smuzhiyun # Check for modifiers. 2051*4882a593Smuzhiyun $possible =~ s/\s*$Storage\s*//g; 2052*4882a593Smuzhiyun $possible =~ s/\s*$Sparse\s*//g; 2053*4882a593Smuzhiyun if ($possible =~ /^\s*$/) { 2054*4882a593Smuzhiyun 2055*4882a593Smuzhiyun } elsif ($possible =~ /\s/) { 2056*4882a593Smuzhiyun $possible =~ s/\s*$Type\s*//g; 2057*4882a593Smuzhiyun for my $modifier (split(' ', $possible)) { 2058*4882a593Smuzhiyun if ($modifier !~ $notPermitted) { 2059*4882a593Smuzhiyun warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); 2060*4882a593Smuzhiyun push(@modifierListFile, $modifier); 2061*4882a593Smuzhiyun } 2062*4882a593Smuzhiyun } 2063*4882a593Smuzhiyun 2064*4882a593Smuzhiyun } else { 2065*4882a593Smuzhiyun warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); 2066*4882a593Smuzhiyun push(@typeListFile, $possible); 2067*4882a593Smuzhiyun } 2068*4882a593Smuzhiyun build_types(); 2069*4882a593Smuzhiyun } else { 2070*4882a593Smuzhiyun warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); 2071*4882a593Smuzhiyun } 2072*4882a593Smuzhiyun} 2073*4882a593Smuzhiyun 2074*4882a593Smuzhiyunmy $prefix = ''; 2075*4882a593Smuzhiyun 2076*4882a593Smuzhiyunsub show_type { 2077*4882a593Smuzhiyun my ($type) = @_; 2078*4882a593Smuzhiyun 2079*4882a593Smuzhiyun $type =~ tr/[a-z]/[A-Z]/; 2080*4882a593Smuzhiyun 2081*4882a593Smuzhiyun return defined $use_type{$type} if (scalar keys %use_type > 0); 2082*4882a593Smuzhiyun 2083*4882a593Smuzhiyun return !defined $ignore_type{$type}; 2084*4882a593Smuzhiyun} 2085*4882a593Smuzhiyun 2086*4882a593Smuzhiyunsub report { 2087*4882a593Smuzhiyun my ($level, $type, $msg) = @_; 2088*4882a593Smuzhiyun 2089*4882a593Smuzhiyun if (!show_type($type) || 2090*4882a593Smuzhiyun (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { 2091*4882a593Smuzhiyun return 0; 2092*4882a593Smuzhiyun } 2093*4882a593Smuzhiyun my $output = ''; 2094*4882a593Smuzhiyun if ($color) { 2095*4882a593Smuzhiyun if ($level eq 'ERROR') { 2096*4882a593Smuzhiyun $output .= RED; 2097*4882a593Smuzhiyun } elsif ($level eq 'WARNING') { 2098*4882a593Smuzhiyun $output .= YELLOW; 2099*4882a593Smuzhiyun } else { 2100*4882a593Smuzhiyun $output .= GREEN; 2101*4882a593Smuzhiyun } 2102*4882a593Smuzhiyun } 2103*4882a593Smuzhiyun $output .= $prefix . $level . ':'; 2104*4882a593Smuzhiyun if ($show_types) { 2105*4882a593Smuzhiyun $output .= BLUE if ($color); 2106*4882a593Smuzhiyun $output .= "$type:"; 2107*4882a593Smuzhiyun } 2108*4882a593Smuzhiyun $output .= RESET if ($color); 2109*4882a593Smuzhiyun $output .= ' ' . $msg . "\n"; 2110*4882a593Smuzhiyun 2111*4882a593Smuzhiyun if ($showfile) { 2112*4882a593Smuzhiyun my @lines = split("\n", $output, -1); 2113*4882a593Smuzhiyun splice(@lines, 1, 1); 2114*4882a593Smuzhiyun $output = join("\n", @lines); 2115*4882a593Smuzhiyun } 2116*4882a593Smuzhiyun $output = (split('\n', $output))[0] . "\n" if ($terse); 2117*4882a593Smuzhiyun 2118*4882a593Smuzhiyun push(our @report, $output); 2119*4882a593Smuzhiyun 2120*4882a593Smuzhiyun return 1; 2121*4882a593Smuzhiyun} 2122*4882a593Smuzhiyun 2123*4882a593Smuzhiyunsub report_dump { 2124*4882a593Smuzhiyun our @report; 2125*4882a593Smuzhiyun} 2126*4882a593Smuzhiyun 2127*4882a593Smuzhiyunsub fixup_current_range { 2128*4882a593Smuzhiyun my ($lineRef, $offset, $length) = @_; 2129*4882a593Smuzhiyun 2130*4882a593Smuzhiyun if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { 2131*4882a593Smuzhiyun my $o = $1; 2132*4882a593Smuzhiyun my $l = $2; 2133*4882a593Smuzhiyun my $no = $o + $offset; 2134*4882a593Smuzhiyun my $nl = $l + $length; 2135*4882a593Smuzhiyun $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; 2136*4882a593Smuzhiyun } 2137*4882a593Smuzhiyun} 2138*4882a593Smuzhiyun 2139*4882a593Smuzhiyunsub fix_inserted_deleted_lines { 2140*4882a593Smuzhiyun my ($linesRef, $insertedRef, $deletedRef) = @_; 2141*4882a593Smuzhiyun 2142*4882a593Smuzhiyun my $range_last_linenr = 0; 2143*4882a593Smuzhiyun my $delta_offset = 0; 2144*4882a593Smuzhiyun 2145*4882a593Smuzhiyun my $old_linenr = 0; 2146*4882a593Smuzhiyun my $new_linenr = 0; 2147*4882a593Smuzhiyun 2148*4882a593Smuzhiyun my $next_insert = 0; 2149*4882a593Smuzhiyun my $next_delete = 0; 2150*4882a593Smuzhiyun 2151*4882a593Smuzhiyun my @lines = (); 2152*4882a593Smuzhiyun 2153*4882a593Smuzhiyun my $inserted = @{$insertedRef}[$next_insert++]; 2154*4882a593Smuzhiyun my $deleted = @{$deletedRef}[$next_delete++]; 2155*4882a593Smuzhiyun 2156*4882a593Smuzhiyun foreach my $old_line (@{$linesRef}) { 2157*4882a593Smuzhiyun my $save_line = 1; 2158*4882a593Smuzhiyun my $line = $old_line; #don't modify the array 2159*4882a593Smuzhiyun if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename 2160*4882a593Smuzhiyun $delta_offset = 0; 2161*4882a593Smuzhiyun } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk 2162*4882a593Smuzhiyun $range_last_linenr = $new_linenr; 2163*4882a593Smuzhiyun fixup_current_range(\$line, $delta_offset, 0); 2164*4882a593Smuzhiyun } 2165*4882a593Smuzhiyun 2166*4882a593Smuzhiyun while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { 2167*4882a593Smuzhiyun $deleted = @{$deletedRef}[$next_delete++]; 2168*4882a593Smuzhiyun $save_line = 0; 2169*4882a593Smuzhiyun fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); 2170*4882a593Smuzhiyun } 2171*4882a593Smuzhiyun 2172*4882a593Smuzhiyun while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { 2173*4882a593Smuzhiyun push(@lines, ${$inserted}{'LINE'}); 2174*4882a593Smuzhiyun $inserted = @{$insertedRef}[$next_insert++]; 2175*4882a593Smuzhiyun $new_linenr++; 2176*4882a593Smuzhiyun fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); 2177*4882a593Smuzhiyun } 2178*4882a593Smuzhiyun 2179*4882a593Smuzhiyun if ($save_line) { 2180*4882a593Smuzhiyun push(@lines, $line); 2181*4882a593Smuzhiyun $new_linenr++; 2182*4882a593Smuzhiyun } 2183*4882a593Smuzhiyun 2184*4882a593Smuzhiyun $old_linenr++; 2185*4882a593Smuzhiyun } 2186*4882a593Smuzhiyun 2187*4882a593Smuzhiyun return @lines; 2188*4882a593Smuzhiyun} 2189*4882a593Smuzhiyun 2190*4882a593Smuzhiyunsub fix_insert_line { 2191*4882a593Smuzhiyun my ($linenr, $line) = @_; 2192*4882a593Smuzhiyun 2193*4882a593Smuzhiyun my $inserted = { 2194*4882a593Smuzhiyun LINENR => $linenr, 2195*4882a593Smuzhiyun LINE => $line, 2196*4882a593Smuzhiyun }; 2197*4882a593Smuzhiyun push(@fixed_inserted, $inserted); 2198*4882a593Smuzhiyun} 2199*4882a593Smuzhiyun 2200*4882a593Smuzhiyunsub fix_delete_line { 2201*4882a593Smuzhiyun my ($linenr, $line) = @_; 2202*4882a593Smuzhiyun 2203*4882a593Smuzhiyun my $deleted = { 2204*4882a593Smuzhiyun LINENR => $linenr, 2205*4882a593Smuzhiyun LINE => $line, 2206*4882a593Smuzhiyun }; 2207*4882a593Smuzhiyun 2208*4882a593Smuzhiyun push(@fixed_deleted, $deleted); 2209*4882a593Smuzhiyun} 2210*4882a593Smuzhiyun 2211*4882a593Smuzhiyunsub ERROR { 2212*4882a593Smuzhiyun my ($type, $msg) = @_; 2213*4882a593Smuzhiyun 2214*4882a593Smuzhiyun if (report("ERROR", $type, $msg)) { 2215*4882a593Smuzhiyun our $clean = 0; 2216*4882a593Smuzhiyun our $cnt_error++; 2217*4882a593Smuzhiyun return 1; 2218*4882a593Smuzhiyun } 2219*4882a593Smuzhiyun return 0; 2220*4882a593Smuzhiyun} 2221*4882a593Smuzhiyunsub WARN { 2222*4882a593Smuzhiyun my ($type, $msg) = @_; 2223*4882a593Smuzhiyun 2224*4882a593Smuzhiyun if (report("WARNING", $type, $msg)) { 2225*4882a593Smuzhiyun our $clean = 0; 2226*4882a593Smuzhiyun our $cnt_warn++; 2227*4882a593Smuzhiyun return 1; 2228*4882a593Smuzhiyun } 2229*4882a593Smuzhiyun return 0; 2230*4882a593Smuzhiyun} 2231*4882a593Smuzhiyunsub CHK { 2232*4882a593Smuzhiyun my ($type, $msg) = @_; 2233*4882a593Smuzhiyun 2234*4882a593Smuzhiyun if ($check && report("CHECK", $type, $msg)) { 2235*4882a593Smuzhiyun our $clean = 0; 2236*4882a593Smuzhiyun our $cnt_chk++; 2237*4882a593Smuzhiyun return 1; 2238*4882a593Smuzhiyun } 2239*4882a593Smuzhiyun return 0; 2240*4882a593Smuzhiyun} 2241*4882a593Smuzhiyun 2242*4882a593Smuzhiyunsub check_absolute_file { 2243*4882a593Smuzhiyun my ($absolute, $herecurr) = @_; 2244*4882a593Smuzhiyun my $file = $absolute; 2245*4882a593Smuzhiyun 2246*4882a593Smuzhiyun ##print "absolute<$absolute>\n"; 2247*4882a593Smuzhiyun 2248*4882a593Smuzhiyun # See if any suffix of this path is a path within the tree. 2249*4882a593Smuzhiyun while ($file =~ s@^[^/]*/@@) { 2250*4882a593Smuzhiyun if (-f "$root/$file") { 2251*4882a593Smuzhiyun ##print "file<$file>\n"; 2252*4882a593Smuzhiyun last; 2253*4882a593Smuzhiyun } 2254*4882a593Smuzhiyun } 2255*4882a593Smuzhiyun if (! -f _) { 2256*4882a593Smuzhiyun return 0; 2257*4882a593Smuzhiyun } 2258*4882a593Smuzhiyun 2259*4882a593Smuzhiyun # It is, so see if the prefix is acceptable. 2260*4882a593Smuzhiyun my $prefix = $absolute; 2261*4882a593Smuzhiyun substr($prefix, -length($file)) = ''; 2262*4882a593Smuzhiyun 2263*4882a593Smuzhiyun ##print "prefix<$prefix>\n"; 2264*4882a593Smuzhiyun if ($prefix ne ".../") { 2265*4882a593Smuzhiyun WARN("USE_RELATIVE_PATH", 2266*4882a593Smuzhiyun "use relative pathname instead of absolute in changelog text\n" . $herecurr); 2267*4882a593Smuzhiyun } 2268*4882a593Smuzhiyun} 2269*4882a593Smuzhiyun 2270*4882a593Smuzhiyunsub trim { 2271*4882a593Smuzhiyun my ($string) = @_; 2272*4882a593Smuzhiyun 2273*4882a593Smuzhiyun $string =~ s/^\s+|\s+$//g; 2274*4882a593Smuzhiyun 2275*4882a593Smuzhiyun return $string; 2276*4882a593Smuzhiyun} 2277*4882a593Smuzhiyun 2278*4882a593Smuzhiyunsub ltrim { 2279*4882a593Smuzhiyun my ($string) = @_; 2280*4882a593Smuzhiyun 2281*4882a593Smuzhiyun $string =~ s/^\s+//; 2282*4882a593Smuzhiyun 2283*4882a593Smuzhiyun return $string; 2284*4882a593Smuzhiyun} 2285*4882a593Smuzhiyun 2286*4882a593Smuzhiyunsub rtrim { 2287*4882a593Smuzhiyun my ($string) = @_; 2288*4882a593Smuzhiyun 2289*4882a593Smuzhiyun $string =~ s/\s+$//; 2290*4882a593Smuzhiyun 2291*4882a593Smuzhiyun return $string; 2292*4882a593Smuzhiyun} 2293*4882a593Smuzhiyun 2294*4882a593Smuzhiyunsub string_find_replace { 2295*4882a593Smuzhiyun my ($string, $find, $replace) = @_; 2296*4882a593Smuzhiyun 2297*4882a593Smuzhiyun $string =~ s/$find/$replace/g; 2298*4882a593Smuzhiyun 2299*4882a593Smuzhiyun return $string; 2300*4882a593Smuzhiyun} 2301*4882a593Smuzhiyun 2302*4882a593Smuzhiyunsub tabify { 2303*4882a593Smuzhiyun my ($leading) = @_; 2304*4882a593Smuzhiyun 2305*4882a593Smuzhiyun my $source_indent = $tabsize; 2306*4882a593Smuzhiyun my $max_spaces_before_tab = $source_indent - 1; 2307*4882a593Smuzhiyun my $spaces_to_tab = " " x $source_indent; 2308*4882a593Smuzhiyun 2309*4882a593Smuzhiyun #convert leading spaces to tabs 2310*4882a593Smuzhiyun 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; 2311*4882a593Smuzhiyun #Remove spaces before a tab 2312*4882a593Smuzhiyun 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; 2313*4882a593Smuzhiyun 2314*4882a593Smuzhiyun return "$leading"; 2315*4882a593Smuzhiyun} 2316*4882a593Smuzhiyun 2317*4882a593Smuzhiyunsub pos_last_openparen { 2318*4882a593Smuzhiyun my ($line) = @_; 2319*4882a593Smuzhiyun 2320*4882a593Smuzhiyun my $pos = 0; 2321*4882a593Smuzhiyun 2322*4882a593Smuzhiyun my $opens = $line =~ tr/\(/\(/; 2323*4882a593Smuzhiyun my $closes = $line =~ tr/\)/\)/; 2324*4882a593Smuzhiyun 2325*4882a593Smuzhiyun my $last_openparen = 0; 2326*4882a593Smuzhiyun 2327*4882a593Smuzhiyun if (($opens == 0) || ($closes >= $opens)) { 2328*4882a593Smuzhiyun return -1; 2329*4882a593Smuzhiyun } 2330*4882a593Smuzhiyun 2331*4882a593Smuzhiyun my $len = length($line); 2332*4882a593Smuzhiyun 2333*4882a593Smuzhiyun for ($pos = 0; $pos < $len; $pos++) { 2334*4882a593Smuzhiyun my $string = substr($line, $pos); 2335*4882a593Smuzhiyun if ($string =~ /^($FuncArg|$balanced_parens)/) { 2336*4882a593Smuzhiyun $pos += length($1) - 1; 2337*4882a593Smuzhiyun } elsif (substr($line, $pos, 1) eq '(') { 2338*4882a593Smuzhiyun $last_openparen = $pos; 2339*4882a593Smuzhiyun } elsif (index($string, '(') == -1) { 2340*4882a593Smuzhiyun last; 2341*4882a593Smuzhiyun } 2342*4882a593Smuzhiyun } 2343*4882a593Smuzhiyun 2344*4882a593Smuzhiyun return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; 2345*4882a593Smuzhiyun} 2346*4882a593Smuzhiyun 2347*4882a593Smuzhiyunsub get_raw_comment { 2348*4882a593Smuzhiyun my ($line, $rawline) = @_; 2349*4882a593Smuzhiyun my $comment = ''; 2350*4882a593Smuzhiyun 2351*4882a593Smuzhiyun for my $i (0 .. (length($line) - 1)) { 2352*4882a593Smuzhiyun if (substr($line, $i, 1) eq "$;") { 2353*4882a593Smuzhiyun $comment .= substr($rawline, $i, 1); 2354*4882a593Smuzhiyun } 2355*4882a593Smuzhiyun } 2356*4882a593Smuzhiyun 2357*4882a593Smuzhiyun return $comment; 2358*4882a593Smuzhiyun} 2359*4882a593Smuzhiyun 2360*4882a593Smuzhiyunsub process { 2361*4882a593Smuzhiyun my $filename = shift; 2362*4882a593Smuzhiyun 2363*4882a593Smuzhiyun my $linenr=0; 2364*4882a593Smuzhiyun my $prevline=""; 2365*4882a593Smuzhiyun my $prevrawline=""; 2366*4882a593Smuzhiyun my $stashline=""; 2367*4882a593Smuzhiyun my $stashrawline=""; 2368*4882a593Smuzhiyun 2369*4882a593Smuzhiyun my $length; 2370*4882a593Smuzhiyun my $indent; 2371*4882a593Smuzhiyun my $previndent=0; 2372*4882a593Smuzhiyun my $stashindent=0; 2373*4882a593Smuzhiyun 2374*4882a593Smuzhiyun our $clean = 1; 2375*4882a593Smuzhiyun my $signoff = 0; 2376*4882a593Smuzhiyun my $author = ''; 2377*4882a593Smuzhiyun my $authorsignoff = 0; 2378*4882a593Smuzhiyun my $author_sob = ''; 2379*4882a593Smuzhiyun my $is_patch = 0; 2380*4882a593Smuzhiyun my $is_binding_patch = -1; 2381*4882a593Smuzhiyun my $in_header_lines = $file ? 0 : 1; 2382*4882a593Smuzhiyun my $in_commit_log = 0; #Scanning lines before patch 2383*4882a593Smuzhiyun my $has_patch_separator = 0; #Found a --- line 2384*4882a593Smuzhiyun my $has_commit_log = 0; #Encountered lines before patch 2385*4882a593Smuzhiyun my $commit_log_lines = 0; #Number of commit log lines 2386*4882a593Smuzhiyun my $commit_log_possible_stack_dump = 0; 2387*4882a593Smuzhiyun my $commit_log_long_line = 0; 2388*4882a593Smuzhiyun my $commit_log_has_diff = 0; 2389*4882a593Smuzhiyun my $reported_maintainer_file = 0; 2390*4882a593Smuzhiyun my $non_utf8_charset = 0; 2391*4882a593Smuzhiyun 2392*4882a593Smuzhiyun my $last_blank_line = 0; 2393*4882a593Smuzhiyun my $last_coalesced_string_linenr = -1; 2394*4882a593Smuzhiyun 2395*4882a593Smuzhiyun our @report = (); 2396*4882a593Smuzhiyun our $cnt_lines = 0; 2397*4882a593Smuzhiyun our $cnt_error = 0; 2398*4882a593Smuzhiyun our $cnt_warn = 0; 2399*4882a593Smuzhiyun our $cnt_chk = 0; 2400*4882a593Smuzhiyun 2401*4882a593Smuzhiyun # Trace the real file/line as we go. 2402*4882a593Smuzhiyun my $realfile = ''; 2403*4882a593Smuzhiyun my $realline = 0; 2404*4882a593Smuzhiyun my $realcnt = 0; 2405*4882a593Smuzhiyun my $here = ''; 2406*4882a593Smuzhiyun my $context_function; #undef'd unless there's a known function 2407*4882a593Smuzhiyun my $in_comment = 0; 2408*4882a593Smuzhiyun my $comment_edge = 0; 2409*4882a593Smuzhiyun my $first_line = 0; 2410*4882a593Smuzhiyun my $p1_prefix = ''; 2411*4882a593Smuzhiyun 2412*4882a593Smuzhiyun my $prev_values = 'E'; 2413*4882a593Smuzhiyun 2414*4882a593Smuzhiyun # suppression flags 2415*4882a593Smuzhiyun my %suppress_ifbraces; 2416*4882a593Smuzhiyun my %suppress_whiletrailers; 2417*4882a593Smuzhiyun my %suppress_export; 2418*4882a593Smuzhiyun my $suppress_statement = 0; 2419*4882a593Smuzhiyun 2420*4882a593Smuzhiyun my %signatures = (); 2421*4882a593Smuzhiyun 2422*4882a593Smuzhiyun # Pre-scan the patch sanitizing the lines. 2423*4882a593Smuzhiyun # Pre-scan the patch looking for any __setup documentation. 2424*4882a593Smuzhiyun # 2425*4882a593Smuzhiyun my @setup_docs = (); 2426*4882a593Smuzhiyun my $setup_docs = 0; 2427*4882a593Smuzhiyun 2428*4882a593Smuzhiyun my $camelcase_file_seeded = 0; 2429*4882a593Smuzhiyun 2430*4882a593Smuzhiyun my $checklicenseline = 1; 2431*4882a593Smuzhiyun 2432*4882a593Smuzhiyun sanitise_line_reset(); 2433*4882a593Smuzhiyun my $line; 2434*4882a593Smuzhiyun foreach my $rawline (@rawlines) { 2435*4882a593Smuzhiyun $linenr++; 2436*4882a593Smuzhiyun $line = $rawline; 2437*4882a593Smuzhiyun 2438*4882a593Smuzhiyun push(@fixed, $rawline) if ($fix); 2439*4882a593Smuzhiyun 2440*4882a593Smuzhiyun if ($rawline=~/^\+\+\+\s+(\S+)/) { 2441*4882a593Smuzhiyun $setup_docs = 0; 2442*4882a593Smuzhiyun if ($1 =~ m@Documentation/admin-guide/kernel-parameters.txt$@) { 2443*4882a593Smuzhiyun $setup_docs = 1; 2444*4882a593Smuzhiyun } 2445*4882a593Smuzhiyun #next; 2446*4882a593Smuzhiyun } 2447*4882a593Smuzhiyun if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { 2448*4882a593Smuzhiyun $realline=$1-1; 2449*4882a593Smuzhiyun if (defined $2) { 2450*4882a593Smuzhiyun $realcnt=$3+1; 2451*4882a593Smuzhiyun } else { 2452*4882a593Smuzhiyun $realcnt=1+1; 2453*4882a593Smuzhiyun } 2454*4882a593Smuzhiyun $in_comment = 0; 2455*4882a593Smuzhiyun 2456*4882a593Smuzhiyun # Guestimate if this is a continuing comment. Run 2457*4882a593Smuzhiyun # the context looking for a comment "edge". If this 2458*4882a593Smuzhiyun # edge is a close comment then we must be in a comment 2459*4882a593Smuzhiyun # at context start. 2460*4882a593Smuzhiyun my $edge; 2461*4882a593Smuzhiyun my $cnt = $realcnt; 2462*4882a593Smuzhiyun for (my $ln = $linenr + 1; $cnt > 0; $ln++) { 2463*4882a593Smuzhiyun next if (defined $rawlines[$ln - 1] && 2464*4882a593Smuzhiyun $rawlines[$ln - 1] =~ /^-/); 2465*4882a593Smuzhiyun $cnt--; 2466*4882a593Smuzhiyun #print "RAW<$rawlines[$ln - 1]>\n"; 2467*4882a593Smuzhiyun last if (!defined $rawlines[$ln - 1]); 2468*4882a593Smuzhiyun if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && 2469*4882a593Smuzhiyun $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { 2470*4882a593Smuzhiyun ($edge) = $1; 2471*4882a593Smuzhiyun last; 2472*4882a593Smuzhiyun } 2473*4882a593Smuzhiyun } 2474*4882a593Smuzhiyun if (defined $edge && $edge eq '*/') { 2475*4882a593Smuzhiyun $in_comment = 1; 2476*4882a593Smuzhiyun } 2477*4882a593Smuzhiyun 2478*4882a593Smuzhiyun # Guestimate if this is a continuing comment. If this 2479*4882a593Smuzhiyun # is the start of a diff block and this line starts 2480*4882a593Smuzhiyun # ' *' then it is very likely a comment. 2481*4882a593Smuzhiyun if (!defined $edge && 2482*4882a593Smuzhiyun $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) 2483*4882a593Smuzhiyun { 2484*4882a593Smuzhiyun $in_comment = 1; 2485*4882a593Smuzhiyun } 2486*4882a593Smuzhiyun 2487*4882a593Smuzhiyun ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; 2488*4882a593Smuzhiyun sanitise_line_reset($in_comment); 2489*4882a593Smuzhiyun 2490*4882a593Smuzhiyun } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { 2491*4882a593Smuzhiyun # Standardise the strings and chars within the input to 2492*4882a593Smuzhiyun # simplify matching -- only bother with positive lines. 2493*4882a593Smuzhiyun $line = sanitise_line($rawline); 2494*4882a593Smuzhiyun } 2495*4882a593Smuzhiyun push(@lines, $line); 2496*4882a593Smuzhiyun 2497*4882a593Smuzhiyun if ($realcnt > 1) { 2498*4882a593Smuzhiyun $realcnt-- if ($line =~ /^(?:\+| |$)/); 2499*4882a593Smuzhiyun } else { 2500*4882a593Smuzhiyun $realcnt = 0; 2501*4882a593Smuzhiyun } 2502*4882a593Smuzhiyun 2503*4882a593Smuzhiyun #print "==>$rawline\n"; 2504*4882a593Smuzhiyun #print "-->$line\n"; 2505*4882a593Smuzhiyun 2506*4882a593Smuzhiyun if ($setup_docs && $line =~ /^\+/) { 2507*4882a593Smuzhiyun push(@setup_docs, $line); 2508*4882a593Smuzhiyun } 2509*4882a593Smuzhiyun } 2510*4882a593Smuzhiyun 2511*4882a593Smuzhiyun $prefix = ''; 2512*4882a593Smuzhiyun 2513*4882a593Smuzhiyun $realcnt = 0; 2514*4882a593Smuzhiyun $linenr = 0; 2515*4882a593Smuzhiyun $fixlinenr = -1; 2516*4882a593Smuzhiyun foreach my $line (@lines) { 2517*4882a593Smuzhiyun $linenr++; 2518*4882a593Smuzhiyun $fixlinenr++; 2519*4882a593Smuzhiyun my $sline = $line; #copy of $line 2520*4882a593Smuzhiyun $sline =~ s/$;/ /g; #with comments as spaces 2521*4882a593Smuzhiyun 2522*4882a593Smuzhiyun my $rawline = $rawlines[$linenr - 1]; 2523*4882a593Smuzhiyun my $raw_comment = get_raw_comment($line, $rawline); 2524*4882a593Smuzhiyun 2525*4882a593Smuzhiyun# check if it's a mode change, rename or start of a patch 2526*4882a593Smuzhiyun if (!$in_commit_log && 2527*4882a593Smuzhiyun ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ || 2528*4882a593Smuzhiyun ($line =~ /^rename (?:from|to) \S+\s*$/ || 2529*4882a593Smuzhiyun $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) { 2530*4882a593Smuzhiyun $is_patch = 1; 2531*4882a593Smuzhiyun } 2532*4882a593Smuzhiyun 2533*4882a593Smuzhiyun#extract the line range in the file after the patch is applied 2534*4882a593Smuzhiyun if (!$in_commit_log && 2535*4882a593Smuzhiyun $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) { 2536*4882a593Smuzhiyun my $context = $4; 2537*4882a593Smuzhiyun $is_patch = 1; 2538*4882a593Smuzhiyun $first_line = $linenr + 1; 2539*4882a593Smuzhiyun $realline=$1-1; 2540*4882a593Smuzhiyun if (defined $2) { 2541*4882a593Smuzhiyun $realcnt=$3+1; 2542*4882a593Smuzhiyun } else { 2543*4882a593Smuzhiyun $realcnt=1+1; 2544*4882a593Smuzhiyun } 2545*4882a593Smuzhiyun annotate_reset(); 2546*4882a593Smuzhiyun $prev_values = 'E'; 2547*4882a593Smuzhiyun 2548*4882a593Smuzhiyun %suppress_ifbraces = (); 2549*4882a593Smuzhiyun %suppress_whiletrailers = (); 2550*4882a593Smuzhiyun %suppress_export = (); 2551*4882a593Smuzhiyun $suppress_statement = 0; 2552*4882a593Smuzhiyun if ($context =~ /\b(\w+)\s*\(/) { 2553*4882a593Smuzhiyun $context_function = $1; 2554*4882a593Smuzhiyun } else { 2555*4882a593Smuzhiyun undef $context_function; 2556*4882a593Smuzhiyun } 2557*4882a593Smuzhiyun next; 2558*4882a593Smuzhiyun 2559*4882a593Smuzhiyun# track the line number as we move through the hunk, note that 2560*4882a593Smuzhiyun# new versions of GNU diff omit the leading space on completely 2561*4882a593Smuzhiyun# blank context lines so we need to count that too. 2562*4882a593Smuzhiyun } elsif ($line =~ /^( |\+|$)/) { 2563*4882a593Smuzhiyun $realline++; 2564*4882a593Smuzhiyun $realcnt-- if ($realcnt != 0); 2565*4882a593Smuzhiyun 2566*4882a593Smuzhiyun # Measure the line length and indent. 2567*4882a593Smuzhiyun ($length, $indent) = line_stats($rawline); 2568*4882a593Smuzhiyun 2569*4882a593Smuzhiyun # Track the previous line. 2570*4882a593Smuzhiyun ($prevline, $stashline) = ($stashline, $line); 2571*4882a593Smuzhiyun ($previndent, $stashindent) = ($stashindent, $indent); 2572*4882a593Smuzhiyun ($prevrawline, $stashrawline) = ($stashrawline, $rawline); 2573*4882a593Smuzhiyun 2574*4882a593Smuzhiyun #warn "line<$line>\n"; 2575*4882a593Smuzhiyun 2576*4882a593Smuzhiyun } elsif ($realcnt == 1) { 2577*4882a593Smuzhiyun $realcnt--; 2578*4882a593Smuzhiyun } 2579*4882a593Smuzhiyun 2580*4882a593Smuzhiyun my $hunk_line = ($realcnt != 0); 2581*4882a593Smuzhiyun 2582*4882a593Smuzhiyun $here = "#$linenr: " if (!$file); 2583*4882a593Smuzhiyun $here = "#$realline: " if ($file); 2584*4882a593Smuzhiyun 2585*4882a593Smuzhiyun my $found_file = 0; 2586*4882a593Smuzhiyun # extract the filename as it passes 2587*4882a593Smuzhiyun if ($line =~ /^diff --git.*?(\S+)$/) { 2588*4882a593Smuzhiyun $realfile = $1; 2589*4882a593Smuzhiyun $realfile =~ s@^([^/]*)/@@ if (!$file); 2590*4882a593Smuzhiyun $in_commit_log = 0; 2591*4882a593Smuzhiyun $found_file = 1; 2592*4882a593Smuzhiyun } elsif ($line =~ /^\+\+\+\s+(\S+)/) { 2593*4882a593Smuzhiyun $realfile = $1; 2594*4882a593Smuzhiyun $realfile =~ s@^([^/]*)/@@ if (!$file); 2595*4882a593Smuzhiyun $in_commit_log = 0; 2596*4882a593Smuzhiyun 2597*4882a593Smuzhiyun $p1_prefix = $1; 2598*4882a593Smuzhiyun if (!$file && $tree && $p1_prefix ne '' && 2599*4882a593Smuzhiyun -e "$root/$p1_prefix") { 2600*4882a593Smuzhiyun WARN("PATCH_PREFIX", 2601*4882a593Smuzhiyun "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); 2602*4882a593Smuzhiyun } 2603*4882a593Smuzhiyun 2604*4882a593Smuzhiyun if ($realfile =~ m@^include/asm/@) { 2605*4882a593Smuzhiyun ERROR("MODIFIED_INCLUDE_ASM", 2606*4882a593Smuzhiyun "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); 2607*4882a593Smuzhiyun } 2608*4882a593Smuzhiyun $found_file = 1; 2609*4882a593Smuzhiyun } 2610*4882a593Smuzhiyun 2611*4882a593Smuzhiyun#make up the handle for any error we report on this line 2612*4882a593Smuzhiyun if ($showfile) { 2613*4882a593Smuzhiyun $prefix = "$realfile:$realline: " 2614*4882a593Smuzhiyun } elsif ($emacs) { 2615*4882a593Smuzhiyun if ($file) { 2616*4882a593Smuzhiyun $prefix = "$filename:$realline: "; 2617*4882a593Smuzhiyun } else { 2618*4882a593Smuzhiyun $prefix = "$filename:$linenr: "; 2619*4882a593Smuzhiyun } 2620*4882a593Smuzhiyun } 2621*4882a593Smuzhiyun 2622*4882a593Smuzhiyun if ($found_file) { 2623*4882a593Smuzhiyun if (is_maintained_obsolete($realfile)) { 2624*4882a593Smuzhiyun WARN("OBSOLETE", 2625*4882a593Smuzhiyun "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n"); 2626*4882a593Smuzhiyun } 2627*4882a593Smuzhiyun if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { 2628*4882a593Smuzhiyun $check = 1; 2629*4882a593Smuzhiyun } else { 2630*4882a593Smuzhiyun $check = $check_orig; 2631*4882a593Smuzhiyun } 2632*4882a593Smuzhiyun $checklicenseline = 1; 2633*4882a593Smuzhiyun 2634*4882a593Smuzhiyun if ($realfile !~ /^MAINTAINERS/) { 2635*4882a593Smuzhiyun my $last_binding_patch = $is_binding_patch; 2636*4882a593Smuzhiyun 2637*4882a593Smuzhiyun $is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@; 2638*4882a593Smuzhiyun 2639*4882a593Smuzhiyun if (($last_binding_patch != -1) && 2640*4882a593Smuzhiyun ($last_binding_patch ^ $is_binding_patch)) { 2641*4882a593Smuzhiyun WARN("DT_SPLIT_BINDING_PATCH", 2642*4882a593Smuzhiyun "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.rst\n"); 2643*4882a593Smuzhiyun } 2644*4882a593Smuzhiyun } 2645*4882a593Smuzhiyun 2646*4882a593Smuzhiyun next; 2647*4882a593Smuzhiyun } 2648*4882a593Smuzhiyun 2649*4882a593Smuzhiyun $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); 2650*4882a593Smuzhiyun 2651*4882a593Smuzhiyun my $hereline = "$here\n$rawline\n"; 2652*4882a593Smuzhiyun my $herecurr = "$here\n$rawline\n"; 2653*4882a593Smuzhiyun my $hereprev = "$here\n$prevrawline\n$rawline\n"; 2654*4882a593Smuzhiyun 2655*4882a593Smuzhiyun $cnt_lines++ if ($realcnt != 0); 2656*4882a593Smuzhiyun 2657*4882a593Smuzhiyun# Verify the existence of a commit log if appropriate 2658*4882a593Smuzhiyun# 2 is used because a $signature is counted in $commit_log_lines 2659*4882a593Smuzhiyun if ($in_commit_log) { 2660*4882a593Smuzhiyun if ($line !~ /^\s*$/) { 2661*4882a593Smuzhiyun $commit_log_lines++; #could be a $signature 2662*4882a593Smuzhiyun } 2663*4882a593Smuzhiyun } elsif ($has_commit_log && $commit_log_lines < 2) { 2664*4882a593Smuzhiyun WARN("COMMIT_MESSAGE", 2665*4882a593Smuzhiyun "Missing commit description - Add an appropriate one\n"); 2666*4882a593Smuzhiyun $commit_log_lines = 2; #warn only once 2667*4882a593Smuzhiyun } 2668*4882a593Smuzhiyun 2669*4882a593Smuzhiyun# Check if the commit log has what seems like a diff which can confuse patch 2670*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_has_diff && 2671*4882a593Smuzhiyun (($line =~ m@^\s+diff\b.*a/([\w/]+)@ && 2672*4882a593Smuzhiyun $line =~ m@^\s+diff\b.*a/[\w/]+\s+b/$1\b@) || 2673*4882a593Smuzhiyun $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || 2674*4882a593Smuzhiyun $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { 2675*4882a593Smuzhiyun ERROR("DIFF_IN_COMMIT_MSG", 2676*4882a593Smuzhiyun "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); 2677*4882a593Smuzhiyun $commit_log_has_diff = 1; 2678*4882a593Smuzhiyun } 2679*4882a593Smuzhiyun 2680*4882a593Smuzhiyun# Check for incorrect file permissions 2681*4882a593Smuzhiyun if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { 2682*4882a593Smuzhiyun my $permhere = $here . "FILE: $realfile\n"; 2683*4882a593Smuzhiyun if ($realfile !~ m@scripts/@ && 2684*4882a593Smuzhiyun $realfile !~ /\.(py|pl|awk|sh)$/) { 2685*4882a593Smuzhiyun ERROR("EXECUTE_PERMISSIONS", 2686*4882a593Smuzhiyun "do not set execute permissions for source files\n" . $permhere); 2687*4882a593Smuzhiyun } 2688*4882a593Smuzhiyun } 2689*4882a593Smuzhiyun 2690*4882a593Smuzhiyun# Check the patch for a From: 2691*4882a593Smuzhiyun if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) { 2692*4882a593Smuzhiyun $author = $1; 2693*4882a593Smuzhiyun my $curline = $linenr; 2694*4882a593Smuzhiyun while(defined($rawlines[$curline]) && ($rawlines[$curline++] =~ /^[ \t]\s*(.*)/)) { 2695*4882a593Smuzhiyun $author .= $1; 2696*4882a593Smuzhiyun } 2697*4882a593Smuzhiyun $author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i); 2698*4882a593Smuzhiyun $author =~ s/"//g; 2699*4882a593Smuzhiyun $author = reformat_email($author); 2700*4882a593Smuzhiyun } 2701*4882a593Smuzhiyun 2702*4882a593Smuzhiyun# Check the patch for a signoff: 2703*4882a593Smuzhiyun if ($line =~ /^\s*signed-off-by:\s*(.*)/i) { 2704*4882a593Smuzhiyun $signoff++; 2705*4882a593Smuzhiyun $in_commit_log = 0; 2706*4882a593Smuzhiyun if ($author ne '' && $authorsignoff != 1) { 2707*4882a593Smuzhiyun if (same_email_addresses($1, $author, 1)) { 2708*4882a593Smuzhiyun $authorsignoff = 1; 2709*4882a593Smuzhiyun } else { 2710*4882a593Smuzhiyun my $ctx = $1; 2711*4882a593Smuzhiyun my ($email_name, $email_comment, $email_address, $comment1) = parse_email($ctx); 2712*4882a593Smuzhiyun my ($author_name, $author_comment, $author_address, $comment2) = parse_email($author); 2713*4882a593Smuzhiyun 2714*4882a593Smuzhiyun if ($email_address eq $author_address && $email_name eq $author_name) { 2715*4882a593Smuzhiyun $author_sob = $ctx; 2716*4882a593Smuzhiyun $authorsignoff = 2; 2717*4882a593Smuzhiyun } elsif ($email_address eq $author_address) { 2718*4882a593Smuzhiyun $author_sob = $ctx; 2719*4882a593Smuzhiyun $authorsignoff = 3; 2720*4882a593Smuzhiyun } elsif ($email_name eq $author_name) { 2721*4882a593Smuzhiyun $author_sob = $ctx; 2722*4882a593Smuzhiyun $authorsignoff = 4; 2723*4882a593Smuzhiyun 2724*4882a593Smuzhiyun my $address1 = $email_address; 2725*4882a593Smuzhiyun my $address2 = $author_address; 2726*4882a593Smuzhiyun 2727*4882a593Smuzhiyun if ($address1 =~ /(\S+)\+\S+(\@.*)/) { 2728*4882a593Smuzhiyun $address1 = "$1$2"; 2729*4882a593Smuzhiyun } 2730*4882a593Smuzhiyun if ($address2 =~ /(\S+)\+\S+(\@.*)/) { 2731*4882a593Smuzhiyun $address2 = "$1$2"; 2732*4882a593Smuzhiyun } 2733*4882a593Smuzhiyun if ($address1 eq $address2) { 2734*4882a593Smuzhiyun $authorsignoff = 5; 2735*4882a593Smuzhiyun } 2736*4882a593Smuzhiyun } 2737*4882a593Smuzhiyun } 2738*4882a593Smuzhiyun } 2739*4882a593Smuzhiyun } 2740*4882a593Smuzhiyun 2741*4882a593Smuzhiyun# Check for patch separator 2742*4882a593Smuzhiyun if ($line =~ /^---$/) { 2743*4882a593Smuzhiyun $has_patch_separator = 1; 2744*4882a593Smuzhiyun $in_commit_log = 0; 2745*4882a593Smuzhiyun } 2746*4882a593Smuzhiyun 2747*4882a593Smuzhiyun# Check if MAINTAINERS is being updated. If so, there's probably no need to 2748*4882a593Smuzhiyun# emit the "does MAINTAINERS need updating?" message on file add/move/delete 2749*4882a593Smuzhiyun if ($line =~ /^\s*MAINTAINERS\s*\|/) { 2750*4882a593Smuzhiyun $reported_maintainer_file = 1; 2751*4882a593Smuzhiyun } 2752*4882a593Smuzhiyun 2753*4882a593Smuzhiyun# Check signature styles 2754*4882a593Smuzhiyun if (!$in_header_lines && 2755*4882a593Smuzhiyun $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { 2756*4882a593Smuzhiyun my $space_before = $1; 2757*4882a593Smuzhiyun my $sign_off = $2; 2758*4882a593Smuzhiyun my $space_after = $3; 2759*4882a593Smuzhiyun my $email = $4; 2760*4882a593Smuzhiyun my $ucfirst_sign_off = ucfirst(lc($sign_off)); 2761*4882a593Smuzhiyun 2762*4882a593Smuzhiyun if ($sign_off !~ /$signature_tags/) { 2763*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2764*4882a593Smuzhiyun "Non-standard signature: $sign_off\n" . $herecurr); 2765*4882a593Smuzhiyun } 2766*4882a593Smuzhiyun if (defined $space_before && $space_before ne "") { 2767*4882a593Smuzhiyun if (WARN("BAD_SIGN_OFF", 2768*4882a593Smuzhiyun "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && 2769*4882a593Smuzhiyun $fix) { 2770*4882a593Smuzhiyun $fixed[$fixlinenr] = 2771*4882a593Smuzhiyun "$ucfirst_sign_off $email"; 2772*4882a593Smuzhiyun } 2773*4882a593Smuzhiyun } 2774*4882a593Smuzhiyun if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { 2775*4882a593Smuzhiyun if (WARN("BAD_SIGN_OFF", 2776*4882a593Smuzhiyun "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && 2777*4882a593Smuzhiyun $fix) { 2778*4882a593Smuzhiyun $fixed[$fixlinenr] = 2779*4882a593Smuzhiyun "$ucfirst_sign_off $email"; 2780*4882a593Smuzhiyun } 2781*4882a593Smuzhiyun 2782*4882a593Smuzhiyun } 2783*4882a593Smuzhiyun if (!defined $space_after || $space_after ne " ") { 2784*4882a593Smuzhiyun if (WARN("BAD_SIGN_OFF", 2785*4882a593Smuzhiyun "Use a single space after $ucfirst_sign_off\n" . $herecurr) && 2786*4882a593Smuzhiyun $fix) { 2787*4882a593Smuzhiyun $fixed[$fixlinenr] = 2788*4882a593Smuzhiyun "$ucfirst_sign_off $email"; 2789*4882a593Smuzhiyun } 2790*4882a593Smuzhiyun } 2791*4882a593Smuzhiyun 2792*4882a593Smuzhiyun my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); 2793*4882a593Smuzhiyun my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment)); 2794*4882a593Smuzhiyun if ($suggested_email eq "") { 2795*4882a593Smuzhiyun ERROR("BAD_SIGN_OFF", 2796*4882a593Smuzhiyun "Unrecognized email address: '$email'\n" . $herecurr); 2797*4882a593Smuzhiyun } else { 2798*4882a593Smuzhiyun my $dequoted = $suggested_email; 2799*4882a593Smuzhiyun $dequoted =~ s/^"//; 2800*4882a593Smuzhiyun $dequoted =~ s/" </ </; 2801*4882a593Smuzhiyun # Don't force email to have quotes 2802*4882a593Smuzhiyun # Allow just an angle bracketed address 2803*4882a593Smuzhiyun if (!same_email_addresses($email, $suggested_email, 0)) { 2804*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2805*4882a593Smuzhiyun "email address '$email' might be better as '$suggested_email'\n" . $herecurr); 2806*4882a593Smuzhiyun } 2807*4882a593Smuzhiyun } 2808*4882a593Smuzhiyun 2809*4882a593Smuzhiyun# Check for duplicate signatures 2810*4882a593Smuzhiyun my $sig_nospace = $line; 2811*4882a593Smuzhiyun $sig_nospace =~ s/\s//g; 2812*4882a593Smuzhiyun $sig_nospace = lc($sig_nospace); 2813*4882a593Smuzhiyun if (defined $signatures{$sig_nospace}) { 2814*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2815*4882a593Smuzhiyun "Duplicate signature\n" . $herecurr); 2816*4882a593Smuzhiyun } else { 2817*4882a593Smuzhiyun $signatures{$sig_nospace} = 1; 2818*4882a593Smuzhiyun } 2819*4882a593Smuzhiyun 2820*4882a593Smuzhiyun# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email 2821*4882a593Smuzhiyun if ($sign_off =~ /^co-developed-by:$/i) { 2822*4882a593Smuzhiyun if ($email eq $author) { 2823*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2824*4882a593Smuzhiyun "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline); 2825*4882a593Smuzhiyun } 2826*4882a593Smuzhiyun if (!defined $lines[$linenr]) { 2827*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2828*4882a593Smuzhiyun "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline); 2829*4882a593Smuzhiyun } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) { 2830*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2831*4882a593Smuzhiyun "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); 2832*4882a593Smuzhiyun } elsif ($1 ne $email) { 2833*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2834*4882a593Smuzhiyun "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]); 2835*4882a593Smuzhiyun } 2836*4882a593Smuzhiyun } 2837*4882a593Smuzhiyun } 2838*4882a593Smuzhiyun 2839*4882a593Smuzhiyun# Check email subject for common tools that don't need to be mentioned 2840*4882a593Smuzhiyun if ($in_header_lines && 2841*4882a593Smuzhiyun $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { 2842*4882a593Smuzhiyun WARN("EMAIL_SUBJECT", 2843*4882a593Smuzhiyun "A patch subject line should describe the change not the tool that found it\n" . $herecurr); 2844*4882a593Smuzhiyun } 2845*4882a593Smuzhiyun 2846*4882a593Smuzhiyun# Check for Gerrit Change-Ids not in any patch context 2847*4882a593Smuzhiyun if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) { 2848*4882a593Smuzhiyun ERROR("GERRIT_CHANGE_ID", 2849*4882a593Smuzhiyun "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr); 2850*4882a593Smuzhiyun } 2851*4882a593Smuzhiyun 2852*4882a593Smuzhiyun# Check if the commit log is in a possible stack dump 2853*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_possible_stack_dump && 2854*4882a593Smuzhiyun ($line =~ /^\s*(?:WARNING:|BUG:)/ || 2855*4882a593Smuzhiyun $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || 2856*4882a593Smuzhiyun # timestamp 2857*4882a593Smuzhiyun $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) || 2858*4882a593Smuzhiyun $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ || 2859*4882a593Smuzhiyun $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) { 2860*4882a593Smuzhiyun # stack dump address styles 2861*4882a593Smuzhiyun $commit_log_possible_stack_dump = 1; 2862*4882a593Smuzhiyun } 2863*4882a593Smuzhiyun 2864*4882a593Smuzhiyun# Check for line lengths > 75 in commit log, warn once 2865*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_long_line && 2866*4882a593Smuzhiyun length($line) > 75 && 2867*4882a593Smuzhiyun !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || 2868*4882a593Smuzhiyun # file delta changes 2869*4882a593Smuzhiyun $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || 2870*4882a593Smuzhiyun # filename then : 2871*4882a593Smuzhiyun $line =~ /^\s*(?:Fixes:|Link:)/i || 2872*4882a593Smuzhiyun # A Fixes: or Link: line 2873*4882a593Smuzhiyun $commit_log_possible_stack_dump)) { 2874*4882a593Smuzhiyun WARN("COMMIT_LOG_LONG_LINE", 2875*4882a593Smuzhiyun "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); 2876*4882a593Smuzhiyun $commit_log_long_line = 1; 2877*4882a593Smuzhiyun } 2878*4882a593Smuzhiyun 2879*4882a593Smuzhiyun# Reset possible stack dump if a blank line is found 2880*4882a593Smuzhiyun if ($in_commit_log && $commit_log_possible_stack_dump && 2881*4882a593Smuzhiyun $line =~ /^\s*$/) { 2882*4882a593Smuzhiyun $commit_log_possible_stack_dump = 0; 2883*4882a593Smuzhiyun } 2884*4882a593Smuzhiyun 2885*4882a593Smuzhiyun# Check for git id commit length and improperly formed commit descriptions 2886*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_possible_stack_dump && 2887*4882a593Smuzhiyun $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i && 2888*4882a593Smuzhiyun $line !~ /^This reverts commit [0-9a-f]{7,40}/ && 2889*4882a593Smuzhiyun ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || 2890*4882a593Smuzhiyun ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i && 2891*4882a593Smuzhiyun $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && 2892*4882a593Smuzhiyun $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { 2893*4882a593Smuzhiyun my $init_char = "c"; 2894*4882a593Smuzhiyun my $orig_commit = ""; 2895*4882a593Smuzhiyun my $short = 1; 2896*4882a593Smuzhiyun my $long = 0; 2897*4882a593Smuzhiyun my $case = 1; 2898*4882a593Smuzhiyun my $space = 1; 2899*4882a593Smuzhiyun my $hasdesc = 0; 2900*4882a593Smuzhiyun my $hasparens = 0; 2901*4882a593Smuzhiyun my $id = '0123456789ab'; 2902*4882a593Smuzhiyun my $orig_desc = "commit description"; 2903*4882a593Smuzhiyun my $description = ""; 2904*4882a593Smuzhiyun 2905*4882a593Smuzhiyun if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { 2906*4882a593Smuzhiyun $init_char = $1; 2907*4882a593Smuzhiyun $orig_commit = lc($2); 2908*4882a593Smuzhiyun } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { 2909*4882a593Smuzhiyun $orig_commit = lc($1); 2910*4882a593Smuzhiyun } 2911*4882a593Smuzhiyun 2912*4882a593Smuzhiyun $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); 2913*4882a593Smuzhiyun $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); 2914*4882a593Smuzhiyun $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); 2915*4882a593Smuzhiyun $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); 2916*4882a593Smuzhiyun if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { 2917*4882a593Smuzhiyun $orig_desc = $1; 2918*4882a593Smuzhiyun $hasparens = 1; 2919*4882a593Smuzhiyun } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && 2920*4882a593Smuzhiyun defined $rawlines[$linenr] && 2921*4882a593Smuzhiyun $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { 2922*4882a593Smuzhiyun $orig_desc = $1; 2923*4882a593Smuzhiyun $hasparens = 1; 2924*4882a593Smuzhiyun } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && 2925*4882a593Smuzhiyun defined $rawlines[$linenr] && 2926*4882a593Smuzhiyun $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { 2927*4882a593Smuzhiyun $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; 2928*4882a593Smuzhiyun $orig_desc = $1; 2929*4882a593Smuzhiyun $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; 2930*4882a593Smuzhiyun $orig_desc .= " " . $1; 2931*4882a593Smuzhiyun $hasparens = 1; 2932*4882a593Smuzhiyun } 2933*4882a593Smuzhiyun 2934*4882a593Smuzhiyun ($id, $description) = git_commit_info($orig_commit, 2935*4882a593Smuzhiyun $id, $orig_desc); 2936*4882a593Smuzhiyun 2937*4882a593Smuzhiyun if (defined($id) && 2938*4882a593Smuzhiyun ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) { 2939*4882a593Smuzhiyun ERROR("GIT_COMMIT_ID", 2940*4882a593Smuzhiyun "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); 2941*4882a593Smuzhiyun } 2942*4882a593Smuzhiyun } 2943*4882a593Smuzhiyun 2944*4882a593Smuzhiyun# Check for added, moved or deleted files 2945*4882a593Smuzhiyun if (!$reported_maintainer_file && !$in_commit_log && 2946*4882a593Smuzhiyun ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || 2947*4882a593Smuzhiyun $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || 2948*4882a593Smuzhiyun ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && 2949*4882a593Smuzhiyun (defined($1) || defined($2))))) { 2950*4882a593Smuzhiyun $is_patch = 1; 2951*4882a593Smuzhiyun $reported_maintainer_file = 1; 2952*4882a593Smuzhiyun WARN("FILE_PATH_CHANGES", 2953*4882a593Smuzhiyun "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); 2954*4882a593Smuzhiyun } 2955*4882a593Smuzhiyun 2956*4882a593Smuzhiyun# Check for adding new DT bindings not in schema format 2957*4882a593Smuzhiyun if (!$in_commit_log && 2958*4882a593Smuzhiyun ($line =~ /^new file mode\s*\d+\s*$/) && 2959*4882a593Smuzhiyun ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) { 2960*4882a593Smuzhiyun WARN("DT_SCHEMA_BINDING_PATCH", 2961*4882a593Smuzhiyun "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n"); 2962*4882a593Smuzhiyun } 2963*4882a593Smuzhiyun 2964*4882a593Smuzhiyun# Check for wrappage within a valid hunk of the file 2965*4882a593Smuzhiyun if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { 2966*4882a593Smuzhiyun ERROR("CORRUPTED_PATCH", 2967*4882a593Smuzhiyun "patch seems to be corrupt (line wrapped?)\n" . 2968*4882a593Smuzhiyun $herecurr) if (!$emitted_corrupt++); 2969*4882a593Smuzhiyun } 2970*4882a593Smuzhiyun 2971*4882a593Smuzhiyun# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php 2972*4882a593Smuzhiyun if (($realfile =~ /^$/ || $line =~ /^\+/) && 2973*4882a593Smuzhiyun $rawline !~ m/^$UTF8*$/) { 2974*4882a593Smuzhiyun my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); 2975*4882a593Smuzhiyun 2976*4882a593Smuzhiyun my $blank = copy_spacing($rawline); 2977*4882a593Smuzhiyun my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; 2978*4882a593Smuzhiyun my $hereptr = "$hereline$ptr\n"; 2979*4882a593Smuzhiyun 2980*4882a593Smuzhiyun CHK("INVALID_UTF8", 2981*4882a593Smuzhiyun "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); 2982*4882a593Smuzhiyun } 2983*4882a593Smuzhiyun 2984*4882a593Smuzhiyun# Check if it's the start of a commit log 2985*4882a593Smuzhiyun# (not a header line and we haven't seen the patch filename) 2986*4882a593Smuzhiyun if ($in_header_lines && $realfile =~ /^$/ && 2987*4882a593Smuzhiyun !($rawline =~ /^\s+(?:\S|$)/ || 2988*4882a593Smuzhiyun $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) { 2989*4882a593Smuzhiyun $in_header_lines = 0; 2990*4882a593Smuzhiyun $in_commit_log = 1; 2991*4882a593Smuzhiyun $has_commit_log = 1; 2992*4882a593Smuzhiyun } 2993*4882a593Smuzhiyun 2994*4882a593Smuzhiyun# Check if there is UTF-8 in a commit log when a mail header has explicitly 2995*4882a593Smuzhiyun# declined it, i.e defined some charset where it is missing. 2996*4882a593Smuzhiyun if ($in_header_lines && 2997*4882a593Smuzhiyun $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && 2998*4882a593Smuzhiyun $1 !~ /utf-8/i) { 2999*4882a593Smuzhiyun $non_utf8_charset = 1; 3000*4882a593Smuzhiyun } 3001*4882a593Smuzhiyun 3002*4882a593Smuzhiyun if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && 3003*4882a593Smuzhiyun $rawline =~ /$NON_ASCII_UTF8/) { 3004*4882a593Smuzhiyun WARN("UTF8_BEFORE_PATCH", 3005*4882a593Smuzhiyun "8-bit UTF-8 used in possible commit log\n" . $herecurr); 3006*4882a593Smuzhiyun } 3007*4882a593Smuzhiyun 3008*4882a593Smuzhiyun# Check for absolute kernel paths in commit message 3009*4882a593Smuzhiyun if ($tree && $in_commit_log) { 3010*4882a593Smuzhiyun while ($line =~ m{(?:^|\s)(/\S*)}g) { 3011*4882a593Smuzhiyun my $file = $1; 3012*4882a593Smuzhiyun 3013*4882a593Smuzhiyun if ($file =~ m{^(.*?)(?::\d+)+:?$} && 3014*4882a593Smuzhiyun check_absolute_file($1, $herecurr)) { 3015*4882a593Smuzhiyun # 3016*4882a593Smuzhiyun } else { 3017*4882a593Smuzhiyun check_absolute_file($file, $herecurr); 3018*4882a593Smuzhiyun } 3019*4882a593Smuzhiyun } 3020*4882a593Smuzhiyun } 3021*4882a593Smuzhiyun 3022*4882a593Smuzhiyun# Check for various typo / spelling mistakes 3023*4882a593Smuzhiyun if (defined($misspellings) && 3024*4882a593Smuzhiyun ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { 3025*4882a593Smuzhiyun while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { 3026*4882a593Smuzhiyun my $typo = $1; 3027*4882a593Smuzhiyun my $typo_fix = $spelling_fix{lc($typo)}; 3028*4882a593Smuzhiyun $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); 3029*4882a593Smuzhiyun $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); 3030*4882a593Smuzhiyun my $msg_level = \&WARN; 3031*4882a593Smuzhiyun $msg_level = \&CHK if ($file); 3032*4882a593Smuzhiyun if (&{$msg_level}("TYPO_SPELLING", 3033*4882a593Smuzhiyun "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && 3034*4882a593Smuzhiyun $fix) { 3035*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; 3036*4882a593Smuzhiyun } 3037*4882a593Smuzhiyun } 3038*4882a593Smuzhiyun } 3039*4882a593Smuzhiyun 3040*4882a593Smuzhiyun# check for invalid commit id 3041*4882a593Smuzhiyun if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) { 3042*4882a593Smuzhiyun my $id; 3043*4882a593Smuzhiyun my $description; 3044*4882a593Smuzhiyun ($id, $description) = git_commit_info($2, undef, undef); 3045*4882a593Smuzhiyun if (!defined($id)) { 3046*4882a593Smuzhiyun WARN("UNKNOWN_COMMIT_ID", 3047*4882a593Smuzhiyun "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr); 3048*4882a593Smuzhiyun } 3049*4882a593Smuzhiyun } 3050*4882a593Smuzhiyun 3051*4882a593Smuzhiyun# check for repeated words separated by a single space 3052*4882a593Smuzhiyun if ($rawline =~ /^\+/ || $in_commit_log) { 3053*4882a593Smuzhiyun while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) { 3054*4882a593Smuzhiyun 3055*4882a593Smuzhiyun my $first = $1; 3056*4882a593Smuzhiyun my $second = $2; 3057*4882a593Smuzhiyun 3058*4882a593Smuzhiyun if ($first =~ /(?:struct|union|enum)/) { 3059*4882a593Smuzhiyun pos($rawline) += length($first) + length($second) + 1; 3060*4882a593Smuzhiyun next; 3061*4882a593Smuzhiyun } 3062*4882a593Smuzhiyun 3063*4882a593Smuzhiyun next if ($first ne $second); 3064*4882a593Smuzhiyun next if ($first eq 'long'); 3065*4882a593Smuzhiyun 3066*4882a593Smuzhiyun if (WARN("REPEATED_WORD", 3067*4882a593Smuzhiyun "Possible repeated word: '$first'\n" . $herecurr) && 3068*4882a593Smuzhiyun $fix) { 3069*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b$first $second\b/$first/; 3070*4882a593Smuzhiyun } 3071*4882a593Smuzhiyun } 3072*4882a593Smuzhiyun 3073*4882a593Smuzhiyun # if it's a repeated word on consecutive lines in a comment block 3074*4882a593Smuzhiyun if ($prevline =~ /$;+\s*$/ && 3075*4882a593Smuzhiyun $prevrawline =~ /($word_pattern)\s*$/) { 3076*4882a593Smuzhiyun my $last_word = $1; 3077*4882a593Smuzhiyun if ($rawline =~ /^\+\s*\*\s*$last_word /) { 3078*4882a593Smuzhiyun if (WARN("REPEATED_WORD", 3079*4882a593Smuzhiyun "Possible repeated word: '$last_word'\n" . $hereprev) && 3080*4882a593Smuzhiyun $fix) { 3081*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/; 3082*4882a593Smuzhiyun } 3083*4882a593Smuzhiyun } 3084*4882a593Smuzhiyun } 3085*4882a593Smuzhiyun } 3086*4882a593Smuzhiyun 3087*4882a593Smuzhiyun# ignore non-hunk lines and lines being removed 3088*4882a593Smuzhiyun next if (!$hunk_line || $line =~ /^-/); 3089*4882a593Smuzhiyun 3090*4882a593Smuzhiyun#trailing whitespace 3091*4882a593Smuzhiyun if ($line =~ /^\+.*\015/) { 3092*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3093*4882a593Smuzhiyun if (ERROR("DOS_LINE_ENDINGS", 3094*4882a593Smuzhiyun "DOS line endings\n" . $herevet) && 3095*4882a593Smuzhiyun $fix) { 3096*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/[\s\015]+$//; 3097*4882a593Smuzhiyun } 3098*4882a593Smuzhiyun } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { 3099*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3100*4882a593Smuzhiyun if (ERROR("TRAILING_WHITESPACE", 3101*4882a593Smuzhiyun "trailing whitespace\n" . $herevet) && 3102*4882a593Smuzhiyun $fix) { 3103*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s+$//; 3104*4882a593Smuzhiyun } 3105*4882a593Smuzhiyun 3106*4882a593Smuzhiyun $rpt_cleaners = 1; 3107*4882a593Smuzhiyun } 3108*4882a593Smuzhiyun 3109*4882a593Smuzhiyun# Check for FSF mailing addresses. 3110*4882a593Smuzhiyun if ($rawline =~ /\bwrite to the Free/i || 3111*4882a593Smuzhiyun $rawline =~ /\b675\s+Mass\s+Ave/i || 3112*4882a593Smuzhiyun $rawline =~ /\b59\s+Temple\s+Pl/i || 3113*4882a593Smuzhiyun $rawline =~ /\b51\s+Franklin\s+St/i) { 3114*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3115*4882a593Smuzhiyun my $msg_level = \&ERROR; 3116*4882a593Smuzhiyun $msg_level = \&CHK if ($file); 3117*4882a593Smuzhiyun &{$msg_level}("FSF_MAILING_ADDRESS", 3118*4882a593Smuzhiyun "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) 3119*4882a593Smuzhiyun } 3120*4882a593Smuzhiyun 3121*4882a593Smuzhiyun# check for Kconfig help text having a real description 3122*4882a593Smuzhiyun# Only applies when adding the entry originally, after that we do not have 3123*4882a593Smuzhiyun# sufficient context to determine whether it is indeed long enough. 3124*4882a593Smuzhiyun if ($realfile =~ /Kconfig/ && 3125*4882a593Smuzhiyun # 'choice' is usually the last thing on the line (though 3126*4882a593Smuzhiyun # Kconfig supports named choices), so use a word boundary 3127*4882a593Smuzhiyun # (\b) rather than a whitespace character (\s) 3128*4882a593Smuzhiyun $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) { 3129*4882a593Smuzhiyun my $length = 0; 3130*4882a593Smuzhiyun my $cnt = $realcnt; 3131*4882a593Smuzhiyun my $ln = $linenr + 1; 3132*4882a593Smuzhiyun my $f; 3133*4882a593Smuzhiyun my $is_start = 0; 3134*4882a593Smuzhiyun my $is_end = 0; 3135*4882a593Smuzhiyun for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { 3136*4882a593Smuzhiyun $f = $lines[$ln - 1]; 3137*4882a593Smuzhiyun $cnt-- if ($lines[$ln - 1] !~ /^-/); 3138*4882a593Smuzhiyun $is_end = $lines[$ln - 1] =~ /^\+/; 3139*4882a593Smuzhiyun 3140*4882a593Smuzhiyun next if ($f =~ /^-/); 3141*4882a593Smuzhiyun last if (!$file && $f =~ /^\@\@/); 3142*4882a593Smuzhiyun 3143*4882a593Smuzhiyun if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) { 3144*4882a593Smuzhiyun $is_start = 1; 3145*4882a593Smuzhiyun } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { 3146*4882a593Smuzhiyun $length = -1; 3147*4882a593Smuzhiyun } 3148*4882a593Smuzhiyun 3149*4882a593Smuzhiyun $f =~ s/^.//; 3150*4882a593Smuzhiyun $f =~ s/#.*//; 3151*4882a593Smuzhiyun $f =~ s/^\s+//; 3152*4882a593Smuzhiyun next if ($f =~ /^$/); 3153*4882a593Smuzhiyun 3154*4882a593Smuzhiyun # This only checks context lines in the patch 3155*4882a593Smuzhiyun # and so hopefully shouldn't trigger false 3156*4882a593Smuzhiyun # positives, even though some of these are 3157*4882a593Smuzhiyun # common words in help texts 3158*4882a593Smuzhiyun if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice| 3159*4882a593Smuzhiyun if|endif|menu|endmenu|source)\b/x) { 3160*4882a593Smuzhiyun $is_end = 1; 3161*4882a593Smuzhiyun last; 3162*4882a593Smuzhiyun } 3163*4882a593Smuzhiyun $length++; 3164*4882a593Smuzhiyun } 3165*4882a593Smuzhiyun if ($is_start && $is_end && $length < $min_conf_desc_length) { 3166*4882a593Smuzhiyun WARN("CONFIG_DESCRIPTION", 3167*4882a593Smuzhiyun "please write a paragraph that describes the config symbol fully\n" . $herecurr); 3168*4882a593Smuzhiyun } 3169*4882a593Smuzhiyun #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; 3170*4882a593Smuzhiyun } 3171*4882a593Smuzhiyun 3172*4882a593Smuzhiyun# check MAINTAINERS entries 3173*4882a593Smuzhiyun if ($realfile =~ /^MAINTAINERS$/) { 3174*4882a593Smuzhiyun# check MAINTAINERS entries for the right form 3175*4882a593Smuzhiyun if ($rawline =~ /^\+[A-Z]:/ && 3176*4882a593Smuzhiyun $rawline !~ /^\+[A-Z]:\t\S/) { 3177*4882a593Smuzhiyun if (WARN("MAINTAINERS_STYLE", 3178*4882a593Smuzhiyun "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) && 3179*4882a593Smuzhiyun $fix) { 3180*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/; 3181*4882a593Smuzhiyun } 3182*4882a593Smuzhiyun } 3183*4882a593Smuzhiyun# check MAINTAINERS entries for the right ordering too 3184*4882a593Smuzhiyun my $preferred_order = 'MRLSWQBCPTFXNK'; 3185*4882a593Smuzhiyun if ($rawline =~ /^\+[A-Z]:/ && 3186*4882a593Smuzhiyun $prevrawline =~ /^[\+ ][A-Z]:/) { 3187*4882a593Smuzhiyun $rawline =~ /^\+([A-Z]):\s*(.*)/; 3188*4882a593Smuzhiyun my $cur = $1; 3189*4882a593Smuzhiyun my $curval = $2; 3190*4882a593Smuzhiyun $prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/; 3191*4882a593Smuzhiyun my $prev = $1; 3192*4882a593Smuzhiyun my $prevval = $2; 3193*4882a593Smuzhiyun my $curindex = index($preferred_order, $cur); 3194*4882a593Smuzhiyun my $previndex = index($preferred_order, $prev); 3195*4882a593Smuzhiyun if ($curindex < 0) { 3196*4882a593Smuzhiyun WARN("MAINTAINERS_STYLE", 3197*4882a593Smuzhiyun "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr); 3198*4882a593Smuzhiyun } else { 3199*4882a593Smuzhiyun if ($previndex >= 0 && $curindex < $previndex) { 3200*4882a593Smuzhiyun WARN("MAINTAINERS_STYLE", 3201*4882a593Smuzhiyun "Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n" . $hereprev); 3202*4882a593Smuzhiyun } elsif ((($prev eq 'F' && $cur eq 'F') || 3203*4882a593Smuzhiyun ($prev eq 'X' && $cur eq 'X')) && 3204*4882a593Smuzhiyun ($prevval cmp $curval) > 0) { 3205*4882a593Smuzhiyun WARN("MAINTAINERS_STYLE", 3206*4882a593Smuzhiyun "Misordered MAINTAINERS entry - list file patterns in alphabetic order\n" . $hereprev); 3207*4882a593Smuzhiyun } 3208*4882a593Smuzhiyun } 3209*4882a593Smuzhiyun } 3210*4882a593Smuzhiyun } 3211*4882a593Smuzhiyun 3212*4882a593Smuzhiyun# discourage the use of boolean for type definition attributes of Kconfig options 3213*4882a593Smuzhiyun if ($realfile =~ /Kconfig/ && 3214*4882a593Smuzhiyun $line =~ /^\+\s*\bboolean\b/) { 3215*4882a593Smuzhiyun WARN("CONFIG_TYPE_BOOLEAN", 3216*4882a593Smuzhiyun "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); 3217*4882a593Smuzhiyun } 3218*4882a593Smuzhiyun 3219*4882a593Smuzhiyun if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && 3220*4882a593Smuzhiyun ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { 3221*4882a593Smuzhiyun my $flag = $1; 3222*4882a593Smuzhiyun my $replacement = { 3223*4882a593Smuzhiyun 'EXTRA_AFLAGS' => 'asflags-y', 3224*4882a593Smuzhiyun 'EXTRA_CFLAGS' => 'ccflags-y', 3225*4882a593Smuzhiyun 'EXTRA_CPPFLAGS' => 'cppflags-y', 3226*4882a593Smuzhiyun 'EXTRA_LDFLAGS' => 'ldflags-y', 3227*4882a593Smuzhiyun }; 3228*4882a593Smuzhiyun 3229*4882a593Smuzhiyun WARN("DEPRECATED_VARIABLE", 3230*4882a593Smuzhiyun "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); 3231*4882a593Smuzhiyun } 3232*4882a593Smuzhiyun 3233*4882a593Smuzhiyun# check for DT compatible documentation 3234*4882a593Smuzhiyun if (defined $root && 3235*4882a593Smuzhiyun (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || 3236*4882a593Smuzhiyun ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { 3237*4882a593Smuzhiyun 3238*4882a593Smuzhiyun my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; 3239*4882a593Smuzhiyun 3240*4882a593Smuzhiyun my $dt_path = $root . "/Documentation/devicetree/bindings/"; 3241*4882a593Smuzhiyun my $vp_file = $dt_path . "vendor-prefixes.yaml"; 3242*4882a593Smuzhiyun 3243*4882a593Smuzhiyun foreach my $compat (@compats) { 3244*4882a593Smuzhiyun my $compat2 = $compat; 3245*4882a593Smuzhiyun $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; 3246*4882a593Smuzhiyun my $compat3 = $compat; 3247*4882a593Smuzhiyun $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; 3248*4882a593Smuzhiyun `grep -Erq "$compat|$compat2|$compat3" $dt_path`; 3249*4882a593Smuzhiyun if ( $? >> 8 ) { 3250*4882a593Smuzhiyun WARN("UNDOCUMENTED_DT_STRING", 3251*4882a593Smuzhiyun "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); 3252*4882a593Smuzhiyun } 3253*4882a593Smuzhiyun 3254*4882a593Smuzhiyun next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; 3255*4882a593Smuzhiyun my $vendor = $1; 3256*4882a593Smuzhiyun `grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`; 3257*4882a593Smuzhiyun if ( $? >> 8 ) { 3258*4882a593Smuzhiyun WARN("UNDOCUMENTED_DT_STRING", 3259*4882a593Smuzhiyun "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); 3260*4882a593Smuzhiyun } 3261*4882a593Smuzhiyun } 3262*4882a593Smuzhiyun } 3263*4882a593Smuzhiyun 3264*4882a593Smuzhiyun# check for using SPDX license tag at beginning of files 3265*4882a593Smuzhiyun if ($realline == $checklicenseline) { 3266*4882a593Smuzhiyun if ($rawline =~ /^[ \+]\s*\#\!\s*\//) { 3267*4882a593Smuzhiyun $checklicenseline = 2; 3268*4882a593Smuzhiyun } elsif ($rawline =~ /^\+/) { 3269*4882a593Smuzhiyun my $comment = ""; 3270*4882a593Smuzhiyun if ($realfile =~ /\.(h|s|S)$/) { 3271*4882a593Smuzhiyun $comment = '/*'; 3272*4882a593Smuzhiyun } elsif ($realfile =~ /\.(c|dts|dtsi)$/) { 3273*4882a593Smuzhiyun $comment = '//'; 3274*4882a593Smuzhiyun } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) { 3275*4882a593Smuzhiyun $comment = '#'; 3276*4882a593Smuzhiyun } elsif ($realfile =~ /\.rst$/) { 3277*4882a593Smuzhiyun $comment = '..'; 3278*4882a593Smuzhiyun } 3279*4882a593Smuzhiyun 3280*4882a593Smuzhiyun# check SPDX comment style for .[chsS] files 3281*4882a593Smuzhiyun if ($realfile =~ /\.[chsS]$/ && 3282*4882a593Smuzhiyun $rawline =~ /SPDX-License-Identifier:/ && 3283*4882a593Smuzhiyun $rawline !~ m@^\+\s*\Q$comment\E\s*@) { 3284*4882a593Smuzhiyun WARN("SPDX_LICENSE_TAG", 3285*4882a593Smuzhiyun "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr); 3286*4882a593Smuzhiyun } 3287*4882a593Smuzhiyun 3288*4882a593Smuzhiyun if ($comment !~ /^$/ && 3289*4882a593Smuzhiyun $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) { 3290*4882a593Smuzhiyun WARN("SPDX_LICENSE_TAG", 3291*4882a593Smuzhiyun "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr); 3292*4882a593Smuzhiyun } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) { 3293*4882a593Smuzhiyun my $spdx_license = $1; 3294*4882a593Smuzhiyun if (!is_SPDX_License_valid($spdx_license)) { 3295*4882a593Smuzhiyun WARN("SPDX_LICENSE_TAG", 3296*4882a593Smuzhiyun "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr); 3297*4882a593Smuzhiyun } 3298*4882a593Smuzhiyun if ($realfile =~ m@^Documentation/devicetree/bindings/@ && 3299*4882a593Smuzhiyun not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) { 3300*4882a593Smuzhiyun my $msg_level = \&WARN; 3301*4882a593Smuzhiyun $msg_level = \&CHK if ($file); 3302*4882a593Smuzhiyun if (&{$msg_level}("SPDX_LICENSE_TAG", 3303*4882a593Smuzhiyun 3304*4882a593Smuzhiyun "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) && 3305*4882a593Smuzhiyun $fix) { 3306*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/; 3307*4882a593Smuzhiyun } 3308*4882a593Smuzhiyun } 3309*4882a593Smuzhiyun } 3310*4882a593Smuzhiyun } 3311*4882a593Smuzhiyun } 3312*4882a593Smuzhiyun 3313*4882a593Smuzhiyun# check for embedded filenames 3314*4882a593Smuzhiyun if ($rawline =~ /^\+.*\Q$realfile\E/) { 3315*4882a593Smuzhiyun WARN("EMBEDDED_FILENAME", 3316*4882a593Smuzhiyun "It's generally not useful to have the filename in the file\n" . $herecurr); 3317*4882a593Smuzhiyun } 3318*4882a593Smuzhiyun 3319*4882a593Smuzhiyun# check we are in a valid source file if not then ignore this hunk 3320*4882a593Smuzhiyun next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); 3321*4882a593Smuzhiyun 3322*4882a593Smuzhiyun# check for using SPDX-License-Identifier on the wrong line number 3323*4882a593Smuzhiyun if ($realline != $checklicenseline && 3324*4882a593Smuzhiyun $rawline =~ /\bSPDX-License-Identifier:/ && 3325*4882a593Smuzhiyun substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) { 3326*4882a593Smuzhiyun WARN("SPDX_LICENSE_TAG", 3327*4882a593Smuzhiyun "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr); 3328*4882a593Smuzhiyun } 3329*4882a593Smuzhiyun 3330*4882a593Smuzhiyun# line length limit (with some exclusions) 3331*4882a593Smuzhiyun# 3332*4882a593Smuzhiyun# There are a few types of lines that may extend beyond $max_line_length: 3333*4882a593Smuzhiyun# logging functions like pr_info that end in a string 3334*4882a593Smuzhiyun# lines with a single string 3335*4882a593Smuzhiyun# #defines that are a single string 3336*4882a593Smuzhiyun# lines with an RFC3986 like URL 3337*4882a593Smuzhiyun# 3338*4882a593Smuzhiyun# There are 3 different line length message types: 3339*4882a593Smuzhiyun# LONG_LINE_COMMENT a comment starts before but extends beyond $max_line_length 3340*4882a593Smuzhiyun# LONG_LINE_STRING a string starts before but extends beyond $max_line_length 3341*4882a593Smuzhiyun# LONG_LINE all other lines longer than $max_line_length 3342*4882a593Smuzhiyun# 3343*4882a593Smuzhiyun# if LONG_LINE is ignored, the other 2 types are also ignored 3344*4882a593Smuzhiyun# 3345*4882a593Smuzhiyun 3346*4882a593Smuzhiyun if ($line =~ /^\+/ && $length > $max_line_length) { 3347*4882a593Smuzhiyun my $msg_type = "LONG_LINE"; 3348*4882a593Smuzhiyun 3349*4882a593Smuzhiyun # Check the allowed long line types first 3350*4882a593Smuzhiyun 3351*4882a593Smuzhiyun # logging functions that end in a string that starts 3352*4882a593Smuzhiyun # before $max_line_length 3353*4882a593Smuzhiyun if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && 3354*4882a593Smuzhiyun length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { 3355*4882a593Smuzhiyun $msg_type = ""; 3356*4882a593Smuzhiyun 3357*4882a593Smuzhiyun # lines with only strings (w/ possible termination) 3358*4882a593Smuzhiyun # #defines with only strings 3359*4882a593Smuzhiyun } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || 3360*4882a593Smuzhiyun $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { 3361*4882a593Smuzhiyun $msg_type = ""; 3362*4882a593Smuzhiyun 3363*4882a593Smuzhiyun # More special cases 3364*4882a593Smuzhiyun } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ || 3365*4882a593Smuzhiyun $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) { 3366*4882a593Smuzhiyun $msg_type = ""; 3367*4882a593Smuzhiyun 3368*4882a593Smuzhiyun # URL ($rawline is used in case the URL is in a comment) 3369*4882a593Smuzhiyun } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) { 3370*4882a593Smuzhiyun $msg_type = ""; 3371*4882a593Smuzhiyun 3372*4882a593Smuzhiyun # Otherwise set the alternate message types 3373*4882a593Smuzhiyun 3374*4882a593Smuzhiyun # a comment starts before $max_line_length 3375*4882a593Smuzhiyun } elsif ($line =~ /($;[\s$;]*)$/ && 3376*4882a593Smuzhiyun length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { 3377*4882a593Smuzhiyun $msg_type = "LONG_LINE_COMMENT" 3378*4882a593Smuzhiyun 3379*4882a593Smuzhiyun # a quoted string starts before $max_line_length 3380*4882a593Smuzhiyun } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && 3381*4882a593Smuzhiyun length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { 3382*4882a593Smuzhiyun $msg_type = "LONG_LINE_STRING" 3383*4882a593Smuzhiyun } 3384*4882a593Smuzhiyun 3385*4882a593Smuzhiyun if ($msg_type ne "" && 3386*4882a593Smuzhiyun (show_type("LONG_LINE") || show_type($msg_type))) { 3387*4882a593Smuzhiyun my $msg_level = \&WARN; 3388*4882a593Smuzhiyun $msg_level = \&CHK if ($file); 3389*4882a593Smuzhiyun &{$msg_level}($msg_type, 3390*4882a593Smuzhiyun "line length of $length exceeds $max_line_length columns\n" . $herecurr); 3391*4882a593Smuzhiyun } 3392*4882a593Smuzhiyun } 3393*4882a593Smuzhiyun 3394*4882a593Smuzhiyun# check for adding lines without a newline. 3395*4882a593Smuzhiyun if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { 3396*4882a593Smuzhiyun WARN("MISSING_EOF_NEWLINE", 3397*4882a593Smuzhiyun "adding a line without newline at end of file\n" . $herecurr); 3398*4882a593Smuzhiyun } 3399*4882a593Smuzhiyun 3400*4882a593Smuzhiyun# check we are in a valid source file C or perl if not then ignore this hunk 3401*4882a593Smuzhiyun next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); 3402*4882a593Smuzhiyun 3403*4882a593Smuzhiyun# at the beginning of a line any tabs must come first and anything 3404*4882a593Smuzhiyun# more than $tabsize must use tabs. 3405*4882a593Smuzhiyun if ($rawline =~ /^\+\s* \t\s*\S/ || 3406*4882a593Smuzhiyun $rawline =~ /^\+\s* \s*/) { 3407*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3408*4882a593Smuzhiyun $rpt_cleaners = 1; 3409*4882a593Smuzhiyun if (ERROR("CODE_INDENT", 3410*4882a593Smuzhiyun "code indent should use tabs where possible\n" . $herevet) && 3411*4882a593Smuzhiyun $fix) { 3412*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; 3413*4882a593Smuzhiyun } 3414*4882a593Smuzhiyun } 3415*4882a593Smuzhiyun 3416*4882a593Smuzhiyun# check for space before tabs. 3417*4882a593Smuzhiyun if ($rawline =~ /^\+/ && $rawline =~ / \t/) { 3418*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3419*4882a593Smuzhiyun if (WARN("SPACE_BEFORE_TAB", 3420*4882a593Smuzhiyun "please, no space before tabs\n" . $herevet) && 3421*4882a593Smuzhiyun $fix) { 3422*4882a593Smuzhiyun while ($fixed[$fixlinenr] =~ 3423*4882a593Smuzhiyun s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {} 3424*4882a593Smuzhiyun while ($fixed[$fixlinenr] =~ 3425*4882a593Smuzhiyun s/(^\+.*) +\t/$1\t/) {} 3426*4882a593Smuzhiyun } 3427*4882a593Smuzhiyun } 3428*4882a593Smuzhiyun 3429*4882a593Smuzhiyun# check for assignments on the start of a line 3430*4882a593Smuzhiyun if ($sline =~ /^\+\s+($Assignment)[^=]/) { 3431*4882a593Smuzhiyun CHK("ASSIGNMENT_CONTINUATIONS", 3432*4882a593Smuzhiyun "Assignment operator '$1' should be on the previous line\n" . $hereprev); 3433*4882a593Smuzhiyun } 3434*4882a593Smuzhiyun 3435*4882a593Smuzhiyun# check for && or || at the start of a line 3436*4882a593Smuzhiyun if ($rawline =~ /^\+\s*(&&|\|\|)/) { 3437*4882a593Smuzhiyun CHK("LOGICAL_CONTINUATIONS", 3438*4882a593Smuzhiyun "Logical continuations should be on the previous line\n" . $hereprev); 3439*4882a593Smuzhiyun } 3440*4882a593Smuzhiyun 3441*4882a593Smuzhiyun# check indentation starts on a tab stop 3442*4882a593Smuzhiyun if ($perl_version_ok && 3443*4882a593Smuzhiyun $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) { 3444*4882a593Smuzhiyun my $indent = length($1); 3445*4882a593Smuzhiyun if ($indent % $tabsize) { 3446*4882a593Smuzhiyun if (WARN("TABSTOP", 3447*4882a593Smuzhiyun "Statements should start on a tabstop\n" . $herecurr) && 3448*4882a593Smuzhiyun $fix) { 3449*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e; 3450*4882a593Smuzhiyun } 3451*4882a593Smuzhiyun } 3452*4882a593Smuzhiyun } 3453*4882a593Smuzhiyun 3454*4882a593Smuzhiyun# check multi-line statement indentation matches previous line 3455*4882a593Smuzhiyun if ($perl_version_ok && 3456*4882a593Smuzhiyun $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { 3457*4882a593Smuzhiyun $prevline =~ /^\+(\t*)(.*)$/; 3458*4882a593Smuzhiyun my $oldindent = $1; 3459*4882a593Smuzhiyun my $rest = $2; 3460*4882a593Smuzhiyun 3461*4882a593Smuzhiyun my $pos = pos_last_openparen($rest); 3462*4882a593Smuzhiyun if ($pos >= 0) { 3463*4882a593Smuzhiyun $line =~ /^(\+| )([ \t]*)/; 3464*4882a593Smuzhiyun my $newindent = $2; 3465*4882a593Smuzhiyun 3466*4882a593Smuzhiyun my $goodtabindent = $oldindent . 3467*4882a593Smuzhiyun "\t" x ($pos / $tabsize) . 3468*4882a593Smuzhiyun " " x ($pos % $tabsize); 3469*4882a593Smuzhiyun my $goodspaceindent = $oldindent . " " x $pos; 3470*4882a593Smuzhiyun 3471*4882a593Smuzhiyun if ($newindent ne $goodtabindent && 3472*4882a593Smuzhiyun $newindent ne $goodspaceindent) { 3473*4882a593Smuzhiyun 3474*4882a593Smuzhiyun if (CHK("PARENTHESIS_ALIGNMENT", 3475*4882a593Smuzhiyun "Alignment should match open parenthesis\n" . $hereprev) && 3476*4882a593Smuzhiyun $fix && $line =~ /^\+/) { 3477*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3478*4882a593Smuzhiyun s/^\+[ \t]*/\+$goodtabindent/; 3479*4882a593Smuzhiyun } 3480*4882a593Smuzhiyun } 3481*4882a593Smuzhiyun } 3482*4882a593Smuzhiyun } 3483*4882a593Smuzhiyun 3484*4882a593Smuzhiyun# check for space after cast like "(int) foo" or "(struct foo) bar" 3485*4882a593Smuzhiyun# avoid checking a few false positives: 3486*4882a593Smuzhiyun# "sizeof(<type>)" or "__alignof__(<type>)" 3487*4882a593Smuzhiyun# function pointer declarations like "(*foo)(int) = bar;" 3488*4882a593Smuzhiyun# structure definitions like "(struct foo) { 0 };" 3489*4882a593Smuzhiyun# multiline macros that define functions 3490*4882a593Smuzhiyun# known attributes or the __attribute__ keyword 3491*4882a593Smuzhiyun if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && 3492*4882a593Smuzhiyun (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { 3493*4882a593Smuzhiyun if (CHK("SPACING", 3494*4882a593Smuzhiyun "No space is necessary after a cast\n" . $herecurr) && 3495*4882a593Smuzhiyun $fix) { 3496*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3497*4882a593Smuzhiyun s/(\(\s*$Type\s*\))[ \t]+/$1/; 3498*4882a593Smuzhiyun } 3499*4882a593Smuzhiyun } 3500*4882a593Smuzhiyun 3501*4882a593Smuzhiyun# Block comment styles 3502*4882a593Smuzhiyun# Networking with an initial /* 3503*4882a593Smuzhiyun if ($realfile =~ m@^(drivers/net/|net/)@ && 3504*4882a593Smuzhiyun $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && 3505*4882a593Smuzhiyun $rawline =~ /^\+[ \t]*\*/ && 3506*4882a593Smuzhiyun $realline > 3) { # Do not warn about the initial copyright comment block after SPDX-License-Identifier 3507*4882a593Smuzhiyun WARN("NETWORKING_BLOCK_COMMENT_STYLE", 3508*4882a593Smuzhiyun "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); 3509*4882a593Smuzhiyun } 3510*4882a593Smuzhiyun 3511*4882a593Smuzhiyun# Block comments use * on subsequent lines 3512*4882a593Smuzhiyun if ($prevline =~ /$;[ \t]*$/ && #ends in comment 3513*4882a593Smuzhiyun $prevrawline =~ /^\+.*?\/\*/ && #starting /* 3514*4882a593Smuzhiyun $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ 3515*4882a593Smuzhiyun $rawline =~ /^\+/ && #line is new 3516*4882a593Smuzhiyun $rawline !~ /^\+[ \t]*\*/) { #no leading * 3517*4882a593Smuzhiyun WARN("BLOCK_COMMENT_STYLE", 3518*4882a593Smuzhiyun "Block comments use * on subsequent lines\n" . $hereprev); 3519*4882a593Smuzhiyun } 3520*4882a593Smuzhiyun 3521*4882a593Smuzhiyun# Block comments use */ on trailing lines 3522*4882a593Smuzhiyun if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ 3523*4882a593Smuzhiyun $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ 3524*4882a593Smuzhiyun $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ 3525*4882a593Smuzhiyun $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ 3526*4882a593Smuzhiyun WARN("BLOCK_COMMENT_STYLE", 3527*4882a593Smuzhiyun "Block comments use a trailing */ on a separate line\n" . $herecurr); 3528*4882a593Smuzhiyun } 3529*4882a593Smuzhiyun 3530*4882a593Smuzhiyun# Block comment * alignment 3531*4882a593Smuzhiyun if ($prevline =~ /$;[ \t]*$/ && #ends in comment 3532*4882a593Smuzhiyun $line =~ /^\+[ \t]*$;/ && #leading comment 3533*4882a593Smuzhiyun $rawline =~ /^\+[ \t]*\*/ && #leading * 3534*4882a593Smuzhiyun (($prevrawline =~ /^\+.*?\/\*/ && #leading /* 3535*4882a593Smuzhiyun $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ 3536*4882a593Smuzhiyun $prevrawline =~ /^\+[ \t]*\*/)) { #leading * 3537*4882a593Smuzhiyun my $oldindent; 3538*4882a593Smuzhiyun $prevrawline =~ m@^\+([ \t]*/?)\*@; 3539*4882a593Smuzhiyun if (defined($1)) { 3540*4882a593Smuzhiyun $oldindent = expand_tabs($1); 3541*4882a593Smuzhiyun } else { 3542*4882a593Smuzhiyun $prevrawline =~ m@^\+(.*/?)\*@; 3543*4882a593Smuzhiyun $oldindent = expand_tabs($1); 3544*4882a593Smuzhiyun } 3545*4882a593Smuzhiyun $rawline =~ m@^\+([ \t]*)\*@; 3546*4882a593Smuzhiyun my $newindent = $1; 3547*4882a593Smuzhiyun $newindent = expand_tabs($newindent); 3548*4882a593Smuzhiyun if (length($oldindent) ne length($newindent)) { 3549*4882a593Smuzhiyun WARN("BLOCK_COMMENT_STYLE", 3550*4882a593Smuzhiyun "Block comments should align the * on each line\n" . $hereprev); 3551*4882a593Smuzhiyun } 3552*4882a593Smuzhiyun } 3553*4882a593Smuzhiyun 3554*4882a593Smuzhiyun# check for missing blank lines after struct/union declarations 3555*4882a593Smuzhiyun# with exceptions for various attributes and macros 3556*4882a593Smuzhiyun if ($prevline =~ /^[\+ ]};?\s*$/ && 3557*4882a593Smuzhiyun $line =~ /^\+/ && 3558*4882a593Smuzhiyun !($line =~ /^\+\s*$/ || 3559*4882a593Smuzhiyun $line =~ /^\+\s*EXPORT_SYMBOL/ || 3560*4882a593Smuzhiyun $line =~ /^\+\s*MODULE_/i || 3561*4882a593Smuzhiyun $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || 3562*4882a593Smuzhiyun $line =~ /^\+[a-z_]*init/ || 3563*4882a593Smuzhiyun $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || 3564*4882a593Smuzhiyun $line =~ /^\+\s*DECLARE/ || 3565*4882a593Smuzhiyun $line =~ /^\+\s*builtin_[\w_]*driver/ || 3566*4882a593Smuzhiyun $line =~ /^\+\s*__setup/)) { 3567*4882a593Smuzhiyun if (CHK("LINE_SPACING", 3568*4882a593Smuzhiyun "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && 3569*4882a593Smuzhiyun $fix) { 3570*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+"); 3571*4882a593Smuzhiyun } 3572*4882a593Smuzhiyun } 3573*4882a593Smuzhiyun 3574*4882a593Smuzhiyun# check for multiple consecutive blank lines 3575*4882a593Smuzhiyun if ($prevline =~ /^[\+ ]\s*$/ && 3576*4882a593Smuzhiyun $line =~ /^\+\s*$/ && 3577*4882a593Smuzhiyun $last_blank_line != ($linenr - 1)) { 3578*4882a593Smuzhiyun if (CHK("LINE_SPACING", 3579*4882a593Smuzhiyun "Please don't use multiple blank lines\n" . $hereprev) && 3580*4882a593Smuzhiyun $fix) { 3581*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 3582*4882a593Smuzhiyun } 3583*4882a593Smuzhiyun 3584*4882a593Smuzhiyun $last_blank_line = $linenr; 3585*4882a593Smuzhiyun } 3586*4882a593Smuzhiyun 3587*4882a593Smuzhiyun# check for missing blank lines after declarations 3588*4882a593Smuzhiyun if ($sline =~ /^\+\s+\S/ && #Not at char 1 3589*4882a593Smuzhiyun # actual declarations 3590*4882a593Smuzhiyun ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || 3591*4882a593Smuzhiyun # function pointer declarations 3592*4882a593Smuzhiyun $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || 3593*4882a593Smuzhiyun # foo bar; where foo is some local typedef or #define 3594*4882a593Smuzhiyun $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || 3595*4882a593Smuzhiyun # known declaration macros 3596*4882a593Smuzhiyun $prevline =~ /^\+\s+$declaration_macros/) && 3597*4882a593Smuzhiyun # for "else if" which can look like "$Ident $Ident" 3598*4882a593Smuzhiyun !($prevline =~ /^\+\s+$c90_Keywords\b/ || 3599*4882a593Smuzhiyun # other possible extensions of declaration lines 3600*4882a593Smuzhiyun $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || 3601*4882a593Smuzhiyun # not starting a section or a macro "\" extended line 3602*4882a593Smuzhiyun $prevline =~ /(?:\{\s*|\\)$/) && 3603*4882a593Smuzhiyun # looks like a declaration 3604*4882a593Smuzhiyun !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || 3605*4882a593Smuzhiyun # function pointer declarations 3606*4882a593Smuzhiyun $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || 3607*4882a593Smuzhiyun # foo bar; where foo is some local typedef or #define 3608*4882a593Smuzhiyun $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || 3609*4882a593Smuzhiyun # known declaration macros 3610*4882a593Smuzhiyun $sline =~ /^\+\s+$declaration_macros/ || 3611*4882a593Smuzhiyun # start of struct or union or enum 3612*4882a593Smuzhiyun $sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ || 3613*4882a593Smuzhiyun # start or end of block or continuation of declaration 3614*4882a593Smuzhiyun $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || 3615*4882a593Smuzhiyun # bitfield continuation 3616*4882a593Smuzhiyun $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || 3617*4882a593Smuzhiyun # other possible extensions of declaration lines 3618*4882a593Smuzhiyun $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && 3619*4882a593Smuzhiyun # indentation of previous and current line are the same 3620*4882a593Smuzhiyun (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { 3621*4882a593Smuzhiyun if (WARN("LINE_SPACING", 3622*4882a593Smuzhiyun "Missing a blank line after declarations\n" . $hereprev) && 3623*4882a593Smuzhiyun $fix) { 3624*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+"); 3625*4882a593Smuzhiyun } 3626*4882a593Smuzhiyun } 3627*4882a593Smuzhiyun 3628*4882a593Smuzhiyun# check for spaces at the beginning of a line. 3629*4882a593Smuzhiyun# Exceptions: 3630*4882a593Smuzhiyun# 1) within comments 3631*4882a593Smuzhiyun# 2) indented preprocessor commands 3632*4882a593Smuzhiyun# 3) hanging labels 3633*4882a593Smuzhiyun if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { 3634*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3635*4882a593Smuzhiyun if (WARN("LEADING_SPACE", 3636*4882a593Smuzhiyun "please, no spaces at the start of a line\n" . $herevet) && 3637*4882a593Smuzhiyun $fix) { 3638*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; 3639*4882a593Smuzhiyun } 3640*4882a593Smuzhiyun } 3641*4882a593Smuzhiyun 3642*4882a593Smuzhiyun# check we are in a valid C source file if not then ignore this hunk 3643*4882a593Smuzhiyun next if ($realfile !~ /\.(h|c)$/); 3644*4882a593Smuzhiyun 3645*4882a593Smuzhiyun# check for unusual line ending [ or ( 3646*4882a593Smuzhiyun if ($line =~ /^\+.*([\[\(])\s*$/) { 3647*4882a593Smuzhiyun CHK("OPEN_ENDED_LINE", 3648*4882a593Smuzhiyun "Lines should not end with a '$1'\n" . $herecurr); 3649*4882a593Smuzhiyun } 3650*4882a593Smuzhiyun 3651*4882a593Smuzhiyun# check if this appears to be the start function declaration, save the name 3652*4882a593Smuzhiyun if ($sline =~ /^\+\{\s*$/ && 3653*4882a593Smuzhiyun $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) { 3654*4882a593Smuzhiyun $context_function = $1; 3655*4882a593Smuzhiyun } 3656*4882a593Smuzhiyun 3657*4882a593Smuzhiyun# check if this appears to be the end of function declaration 3658*4882a593Smuzhiyun if ($sline =~ /^\+\}\s*$/) { 3659*4882a593Smuzhiyun undef $context_function; 3660*4882a593Smuzhiyun } 3661*4882a593Smuzhiyun 3662*4882a593Smuzhiyun# check indentation of any line with a bare else 3663*4882a593Smuzhiyun# (but not if it is a multiple line "if (foo) return bar; else return baz;") 3664*4882a593Smuzhiyun# if the previous line is a break or return and is indented 1 tab more... 3665*4882a593Smuzhiyun if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { 3666*4882a593Smuzhiyun my $tabs = length($1) + 1; 3667*4882a593Smuzhiyun if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || 3668*4882a593Smuzhiyun ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && 3669*4882a593Smuzhiyun defined $lines[$linenr] && 3670*4882a593Smuzhiyun $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { 3671*4882a593Smuzhiyun WARN("UNNECESSARY_ELSE", 3672*4882a593Smuzhiyun "else is not generally useful after a break or return\n" . $hereprev); 3673*4882a593Smuzhiyun } 3674*4882a593Smuzhiyun } 3675*4882a593Smuzhiyun 3676*4882a593Smuzhiyun# check indentation of a line with a break; 3677*4882a593Smuzhiyun# if the previous line is a goto or return and is indented the same # of tabs 3678*4882a593Smuzhiyun if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { 3679*4882a593Smuzhiyun my $tabs = $1; 3680*4882a593Smuzhiyun if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { 3681*4882a593Smuzhiyun WARN("UNNECESSARY_BREAK", 3682*4882a593Smuzhiyun "break is not useful after a goto or return\n" . $hereprev); 3683*4882a593Smuzhiyun } 3684*4882a593Smuzhiyun } 3685*4882a593Smuzhiyun 3686*4882a593Smuzhiyun# check for RCS/CVS revision markers 3687*4882a593Smuzhiyun if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { 3688*4882a593Smuzhiyun WARN("CVS_KEYWORD", 3689*4882a593Smuzhiyun "CVS style keyword markers, these will _not_ be updated\n". $herecurr); 3690*4882a593Smuzhiyun } 3691*4882a593Smuzhiyun 3692*4882a593Smuzhiyun# check for old HOTPLUG __dev<foo> section markings 3693*4882a593Smuzhiyun if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { 3694*4882a593Smuzhiyun WARN("HOTPLUG_SECTION", 3695*4882a593Smuzhiyun "Using $1 is unnecessary\n" . $herecurr); 3696*4882a593Smuzhiyun } 3697*4882a593Smuzhiyun 3698*4882a593Smuzhiyun# Check for potential 'bare' types 3699*4882a593Smuzhiyun my ($stat, $cond, $line_nr_next, $remain_next, $off_next, 3700*4882a593Smuzhiyun $realline_next); 3701*4882a593Smuzhiyun#print "LINE<$line>\n"; 3702*4882a593Smuzhiyun if ($linenr > $suppress_statement && 3703*4882a593Smuzhiyun $realcnt && $sline =~ /.\s*\S/) { 3704*4882a593Smuzhiyun ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 3705*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0); 3706*4882a593Smuzhiyun $stat =~ s/\n./\n /g; 3707*4882a593Smuzhiyun $cond =~ s/\n./\n /g; 3708*4882a593Smuzhiyun 3709*4882a593Smuzhiyun#print "linenr<$linenr> <$stat>\n"; 3710*4882a593Smuzhiyun # If this statement has no statement boundaries within 3711*4882a593Smuzhiyun # it there is no point in retrying a statement scan 3712*4882a593Smuzhiyun # until we hit end of it. 3713*4882a593Smuzhiyun my $frag = $stat; $frag =~ s/;+\s*$//; 3714*4882a593Smuzhiyun if ($frag !~ /(?:{|;)/) { 3715*4882a593Smuzhiyun#print "skip<$line_nr_next>\n"; 3716*4882a593Smuzhiyun $suppress_statement = $line_nr_next; 3717*4882a593Smuzhiyun } 3718*4882a593Smuzhiyun 3719*4882a593Smuzhiyun # Find the real next line. 3720*4882a593Smuzhiyun $realline_next = $line_nr_next; 3721*4882a593Smuzhiyun if (defined $realline_next && 3722*4882a593Smuzhiyun (!defined $lines[$realline_next - 1] || 3723*4882a593Smuzhiyun substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { 3724*4882a593Smuzhiyun $realline_next++; 3725*4882a593Smuzhiyun } 3726*4882a593Smuzhiyun 3727*4882a593Smuzhiyun my $s = $stat; 3728*4882a593Smuzhiyun $s =~ s/{.*$//s; 3729*4882a593Smuzhiyun 3730*4882a593Smuzhiyun # Ignore goto labels. 3731*4882a593Smuzhiyun if ($s =~ /$Ident:\*$/s) { 3732*4882a593Smuzhiyun 3733*4882a593Smuzhiyun # Ignore functions being called 3734*4882a593Smuzhiyun } elsif ($s =~ /^.\s*$Ident\s*\(/s) { 3735*4882a593Smuzhiyun 3736*4882a593Smuzhiyun } elsif ($s =~ /^.\s*else\b/s) { 3737*4882a593Smuzhiyun 3738*4882a593Smuzhiyun # declarations always start with types 3739*4882a593Smuzhiyun } 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) { 3740*4882a593Smuzhiyun my $type = $1; 3741*4882a593Smuzhiyun $type =~ s/\s+/ /g; 3742*4882a593Smuzhiyun possible($type, "A:" . $s); 3743*4882a593Smuzhiyun 3744*4882a593Smuzhiyun # definitions in global scope can only start with types 3745*4882a593Smuzhiyun } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { 3746*4882a593Smuzhiyun possible($1, "B:" . $s); 3747*4882a593Smuzhiyun } 3748*4882a593Smuzhiyun 3749*4882a593Smuzhiyun # any (foo ... *) is a pointer cast, and foo is a type 3750*4882a593Smuzhiyun while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { 3751*4882a593Smuzhiyun possible($1, "C:" . $s); 3752*4882a593Smuzhiyun } 3753*4882a593Smuzhiyun 3754*4882a593Smuzhiyun # Check for any sort of function declaration. 3755*4882a593Smuzhiyun # int foo(something bar, other baz); 3756*4882a593Smuzhiyun # void (*store_gdt)(x86_descr_ptr *); 3757*4882a593Smuzhiyun if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { 3758*4882a593Smuzhiyun my ($name_len) = length($1); 3759*4882a593Smuzhiyun 3760*4882a593Smuzhiyun my $ctx = $s; 3761*4882a593Smuzhiyun substr($ctx, 0, $name_len + 1, ''); 3762*4882a593Smuzhiyun $ctx =~ s/\)[^\)]*$//; 3763*4882a593Smuzhiyun 3764*4882a593Smuzhiyun for my $arg (split(/\s*,\s*/, $ctx)) { 3765*4882a593Smuzhiyun if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { 3766*4882a593Smuzhiyun 3767*4882a593Smuzhiyun possible($1, "D:" . $s); 3768*4882a593Smuzhiyun } 3769*4882a593Smuzhiyun } 3770*4882a593Smuzhiyun } 3771*4882a593Smuzhiyun 3772*4882a593Smuzhiyun } 3773*4882a593Smuzhiyun 3774*4882a593Smuzhiyun# 3775*4882a593Smuzhiyun# Checks which may be anchored in the context. 3776*4882a593Smuzhiyun# 3777*4882a593Smuzhiyun 3778*4882a593Smuzhiyun# Check for switch () and associated case and default 3779*4882a593Smuzhiyun# statements should be at the same indent. 3780*4882a593Smuzhiyun if ($line=~/\bswitch\s*\(.*\)/) { 3781*4882a593Smuzhiyun my $err = ''; 3782*4882a593Smuzhiyun my $sep = ''; 3783*4882a593Smuzhiyun my @ctx = ctx_block_outer($linenr, $realcnt); 3784*4882a593Smuzhiyun shift(@ctx); 3785*4882a593Smuzhiyun for my $ctx (@ctx) { 3786*4882a593Smuzhiyun my ($clen, $cindent) = line_stats($ctx); 3787*4882a593Smuzhiyun if ($ctx =~ /^\+\s*(case\s+|default:)/ && 3788*4882a593Smuzhiyun $indent != $cindent) { 3789*4882a593Smuzhiyun $err .= "$sep$ctx\n"; 3790*4882a593Smuzhiyun $sep = ''; 3791*4882a593Smuzhiyun } else { 3792*4882a593Smuzhiyun $sep = "[...]\n"; 3793*4882a593Smuzhiyun } 3794*4882a593Smuzhiyun } 3795*4882a593Smuzhiyun if ($err ne '') { 3796*4882a593Smuzhiyun ERROR("SWITCH_CASE_INDENT_LEVEL", 3797*4882a593Smuzhiyun "switch and case should be at the same indent\n$hereline$err"); 3798*4882a593Smuzhiyun } 3799*4882a593Smuzhiyun } 3800*4882a593Smuzhiyun 3801*4882a593Smuzhiyun# if/while/etc brace do not go on next line, unless defining a do while loop, 3802*4882a593Smuzhiyun# or if that brace on the next line is for something else 3803*4882a593Smuzhiyun if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { 3804*4882a593Smuzhiyun my $pre_ctx = "$1$2"; 3805*4882a593Smuzhiyun 3806*4882a593Smuzhiyun my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); 3807*4882a593Smuzhiyun 3808*4882a593Smuzhiyun if ($line =~ /^\+\t{6,}/) { 3809*4882a593Smuzhiyun WARN("DEEP_INDENTATION", 3810*4882a593Smuzhiyun "Too many leading tabs - consider code refactoring\n" . $herecurr); 3811*4882a593Smuzhiyun } 3812*4882a593Smuzhiyun 3813*4882a593Smuzhiyun my $ctx_cnt = $realcnt - $#ctx - 1; 3814*4882a593Smuzhiyun my $ctx = join("\n", @ctx); 3815*4882a593Smuzhiyun 3816*4882a593Smuzhiyun my $ctx_ln = $linenr; 3817*4882a593Smuzhiyun my $ctx_skip = $realcnt; 3818*4882a593Smuzhiyun 3819*4882a593Smuzhiyun while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && 3820*4882a593Smuzhiyun defined $lines[$ctx_ln - 1] && 3821*4882a593Smuzhiyun $lines[$ctx_ln - 1] =~ /^-/)) { 3822*4882a593Smuzhiyun ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; 3823*4882a593Smuzhiyun $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); 3824*4882a593Smuzhiyun $ctx_ln++; 3825*4882a593Smuzhiyun } 3826*4882a593Smuzhiyun 3827*4882a593Smuzhiyun #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; 3828*4882a593Smuzhiyun #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; 3829*4882a593Smuzhiyun 3830*4882a593Smuzhiyun if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { 3831*4882a593Smuzhiyun ERROR("OPEN_BRACE", 3832*4882a593Smuzhiyun "that open brace { should be on the previous line\n" . 3833*4882a593Smuzhiyun "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); 3834*4882a593Smuzhiyun } 3835*4882a593Smuzhiyun if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && 3836*4882a593Smuzhiyun $ctx =~ /\)\s*\;\s*$/ && 3837*4882a593Smuzhiyun defined $lines[$ctx_ln - 1]) 3838*4882a593Smuzhiyun { 3839*4882a593Smuzhiyun my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); 3840*4882a593Smuzhiyun if ($nindent > $indent) { 3841*4882a593Smuzhiyun WARN("TRAILING_SEMICOLON", 3842*4882a593Smuzhiyun "trailing semicolon indicates no statements, indent implies otherwise\n" . 3843*4882a593Smuzhiyun "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); 3844*4882a593Smuzhiyun } 3845*4882a593Smuzhiyun } 3846*4882a593Smuzhiyun } 3847*4882a593Smuzhiyun 3848*4882a593Smuzhiyun# Check relative indent for conditionals and blocks. 3849*4882a593Smuzhiyun if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { 3850*4882a593Smuzhiyun ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 3851*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0) 3852*4882a593Smuzhiyun if (!defined $stat); 3853*4882a593Smuzhiyun my ($s, $c) = ($stat, $cond); 3854*4882a593Smuzhiyun 3855*4882a593Smuzhiyun substr($s, 0, length($c), ''); 3856*4882a593Smuzhiyun 3857*4882a593Smuzhiyun # remove inline comments 3858*4882a593Smuzhiyun $s =~ s/$;/ /g; 3859*4882a593Smuzhiyun $c =~ s/$;/ /g; 3860*4882a593Smuzhiyun 3861*4882a593Smuzhiyun # Find out how long the conditional actually is. 3862*4882a593Smuzhiyun my @newlines = ($c =~ /\n/gs); 3863*4882a593Smuzhiyun my $cond_lines = 1 + $#newlines; 3864*4882a593Smuzhiyun 3865*4882a593Smuzhiyun # Make sure we remove the line prefixes as we have 3866*4882a593Smuzhiyun # none on the first line, and are going to readd them 3867*4882a593Smuzhiyun # where necessary. 3868*4882a593Smuzhiyun $s =~ s/\n./\n/gs; 3869*4882a593Smuzhiyun while ($s =~ /\n\s+\\\n/) { 3870*4882a593Smuzhiyun $cond_lines += $s =~ s/\n\s+\\\n/\n/g; 3871*4882a593Smuzhiyun } 3872*4882a593Smuzhiyun 3873*4882a593Smuzhiyun # We want to check the first line inside the block 3874*4882a593Smuzhiyun # starting at the end of the conditional, so remove: 3875*4882a593Smuzhiyun # 1) any blank line termination 3876*4882a593Smuzhiyun # 2) any opening brace { on end of the line 3877*4882a593Smuzhiyun # 3) any do (...) { 3878*4882a593Smuzhiyun my $continuation = 0; 3879*4882a593Smuzhiyun my $check = 0; 3880*4882a593Smuzhiyun $s =~ s/^.*\bdo\b//; 3881*4882a593Smuzhiyun $s =~ s/^\s*{//; 3882*4882a593Smuzhiyun if ($s =~ s/^\s*\\//) { 3883*4882a593Smuzhiyun $continuation = 1; 3884*4882a593Smuzhiyun } 3885*4882a593Smuzhiyun if ($s =~ s/^\s*?\n//) { 3886*4882a593Smuzhiyun $check = 1; 3887*4882a593Smuzhiyun $cond_lines++; 3888*4882a593Smuzhiyun } 3889*4882a593Smuzhiyun 3890*4882a593Smuzhiyun # Also ignore a loop construct at the end of a 3891*4882a593Smuzhiyun # preprocessor statement. 3892*4882a593Smuzhiyun if (($prevline =~ /^.\s*#\s*define\s/ || 3893*4882a593Smuzhiyun $prevline =~ /\\\s*$/) && $continuation == 0) { 3894*4882a593Smuzhiyun $check = 0; 3895*4882a593Smuzhiyun } 3896*4882a593Smuzhiyun 3897*4882a593Smuzhiyun my $cond_ptr = -1; 3898*4882a593Smuzhiyun $continuation = 0; 3899*4882a593Smuzhiyun while ($cond_ptr != $cond_lines) { 3900*4882a593Smuzhiyun $cond_ptr = $cond_lines; 3901*4882a593Smuzhiyun 3902*4882a593Smuzhiyun # If we see an #else/#elif then the code 3903*4882a593Smuzhiyun # is not linear. 3904*4882a593Smuzhiyun if ($s =~ /^\s*\#\s*(?:else|elif)/) { 3905*4882a593Smuzhiyun $check = 0; 3906*4882a593Smuzhiyun } 3907*4882a593Smuzhiyun 3908*4882a593Smuzhiyun # Ignore: 3909*4882a593Smuzhiyun # 1) blank lines, they should be at 0, 3910*4882a593Smuzhiyun # 2) preprocessor lines, and 3911*4882a593Smuzhiyun # 3) labels. 3912*4882a593Smuzhiyun if ($continuation || 3913*4882a593Smuzhiyun $s =~ /^\s*?\n/ || 3914*4882a593Smuzhiyun $s =~ /^\s*#\s*?/ || 3915*4882a593Smuzhiyun $s =~ /^\s*$Ident\s*:/) { 3916*4882a593Smuzhiyun $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; 3917*4882a593Smuzhiyun if ($s =~ s/^.*?\n//) { 3918*4882a593Smuzhiyun $cond_lines++; 3919*4882a593Smuzhiyun } 3920*4882a593Smuzhiyun } 3921*4882a593Smuzhiyun } 3922*4882a593Smuzhiyun 3923*4882a593Smuzhiyun my (undef, $sindent) = line_stats("+" . $s); 3924*4882a593Smuzhiyun my $stat_real = raw_line($linenr, $cond_lines); 3925*4882a593Smuzhiyun 3926*4882a593Smuzhiyun # Check if either of these lines are modified, else 3927*4882a593Smuzhiyun # this is not this patch's fault. 3928*4882a593Smuzhiyun if (!defined($stat_real) || 3929*4882a593Smuzhiyun $stat !~ /^\+/ && $stat_real !~ /^\+/) { 3930*4882a593Smuzhiyun $check = 0; 3931*4882a593Smuzhiyun } 3932*4882a593Smuzhiyun if (defined($stat_real) && $cond_lines > 1) { 3933*4882a593Smuzhiyun $stat_real = "[...]\n$stat_real"; 3934*4882a593Smuzhiyun } 3935*4882a593Smuzhiyun 3936*4882a593Smuzhiyun #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"; 3937*4882a593Smuzhiyun 3938*4882a593Smuzhiyun if ($check && $s ne '' && 3939*4882a593Smuzhiyun (($sindent % $tabsize) != 0 || 3940*4882a593Smuzhiyun ($sindent < $indent) || 3941*4882a593Smuzhiyun ($sindent == $indent && 3942*4882a593Smuzhiyun ($s !~ /^\s*(?:\}|\{|else\b)/)) || 3943*4882a593Smuzhiyun ($sindent > $indent + $tabsize))) { 3944*4882a593Smuzhiyun WARN("SUSPECT_CODE_INDENT", 3945*4882a593Smuzhiyun "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); 3946*4882a593Smuzhiyun } 3947*4882a593Smuzhiyun } 3948*4882a593Smuzhiyun 3949*4882a593Smuzhiyun # Track the 'values' across context and added lines. 3950*4882a593Smuzhiyun my $opline = $line; $opline =~ s/^./ /; 3951*4882a593Smuzhiyun my ($curr_values, $curr_vars) = 3952*4882a593Smuzhiyun annotate_values($opline . "\n", $prev_values); 3953*4882a593Smuzhiyun $curr_values = $prev_values . $curr_values; 3954*4882a593Smuzhiyun if ($dbg_values) { 3955*4882a593Smuzhiyun my $outline = $opline; $outline =~ s/\t/ /g; 3956*4882a593Smuzhiyun print "$linenr > .$outline\n"; 3957*4882a593Smuzhiyun print "$linenr > $curr_values\n"; 3958*4882a593Smuzhiyun print "$linenr > $curr_vars\n"; 3959*4882a593Smuzhiyun } 3960*4882a593Smuzhiyun $prev_values = substr($curr_values, -1); 3961*4882a593Smuzhiyun 3962*4882a593Smuzhiyun#ignore lines not being added 3963*4882a593Smuzhiyun next if ($line =~ /^[^\+]/); 3964*4882a593Smuzhiyun 3965*4882a593Smuzhiyun# check for self assignments used to avoid compiler warnings 3966*4882a593Smuzhiyun# e.g.: int foo = foo, *bar = NULL; 3967*4882a593Smuzhiyun# struct foo bar = *(&(bar)); 3968*4882a593Smuzhiyun if ($line =~ /^\+\s*(?:$Declare)?([A-Za-z_][A-Za-z\d_]*)\s*=/) { 3969*4882a593Smuzhiyun my $var = $1; 3970*4882a593Smuzhiyun if ($line =~ /^\+\s*(?:$Declare)?$var\s*=\s*(?:$var|\*\s*\(?\s*&\s*\(?\s*$var\s*\)?\s*\)?)\s*[;,]/) { 3971*4882a593Smuzhiyun WARN("SELF_ASSIGNMENT", 3972*4882a593Smuzhiyun "Do not use self-assignments to avoid compiler warnings\n" . $herecurr); 3973*4882a593Smuzhiyun } 3974*4882a593Smuzhiyun } 3975*4882a593Smuzhiyun 3976*4882a593Smuzhiyun# check for dereferences that span multiple lines 3977*4882a593Smuzhiyun if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ && 3978*4882a593Smuzhiyun $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) { 3979*4882a593Smuzhiyun $prevline =~ /($Lval\s*(?:\.|->))\s*$/; 3980*4882a593Smuzhiyun my $ref = $1; 3981*4882a593Smuzhiyun $line =~ /^.\s*($Lval)/; 3982*4882a593Smuzhiyun $ref .= $1; 3983*4882a593Smuzhiyun $ref =~ s/\s//g; 3984*4882a593Smuzhiyun WARN("MULTILINE_DEREFERENCE", 3985*4882a593Smuzhiyun "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev); 3986*4882a593Smuzhiyun } 3987*4882a593Smuzhiyun 3988*4882a593Smuzhiyun# check for declarations of signed or unsigned without int 3989*4882a593Smuzhiyun while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { 3990*4882a593Smuzhiyun my $type = $1; 3991*4882a593Smuzhiyun my $var = $2; 3992*4882a593Smuzhiyun $var = "" if (!defined $var); 3993*4882a593Smuzhiyun if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { 3994*4882a593Smuzhiyun my $sign = $1; 3995*4882a593Smuzhiyun my $pointer = $2; 3996*4882a593Smuzhiyun 3997*4882a593Smuzhiyun $pointer = "" if (!defined $pointer); 3998*4882a593Smuzhiyun 3999*4882a593Smuzhiyun if (WARN("UNSPECIFIED_INT", 4000*4882a593Smuzhiyun "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && 4001*4882a593Smuzhiyun $fix) { 4002*4882a593Smuzhiyun my $decl = trim($sign) . " int "; 4003*4882a593Smuzhiyun my $comp_pointer = $pointer; 4004*4882a593Smuzhiyun $comp_pointer =~ s/\s//g; 4005*4882a593Smuzhiyun $decl .= $comp_pointer; 4006*4882a593Smuzhiyun $decl = rtrim($decl) if ($var eq ""); 4007*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; 4008*4882a593Smuzhiyun } 4009*4882a593Smuzhiyun } 4010*4882a593Smuzhiyun } 4011*4882a593Smuzhiyun 4012*4882a593Smuzhiyun# TEST: allow direct testing of the type matcher. 4013*4882a593Smuzhiyun if ($dbg_type) { 4014*4882a593Smuzhiyun if ($line =~ /^.\s*$Declare\s*$/) { 4015*4882a593Smuzhiyun ERROR("TEST_TYPE", 4016*4882a593Smuzhiyun "TEST: is type\n" . $herecurr); 4017*4882a593Smuzhiyun } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { 4018*4882a593Smuzhiyun ERROR("TEST_NOT_TYPE", 4019*4882a593Smuzhiyun "TEST: is not type ($1 is)\n". $herecurr); 4020*4882a593Smuzhiyun } 4021*4882a593Smuzhiyun next; 4022*4882a593Smuzhiyun } 4023*4882a593Smuzhiyun# TEST: allow direct testing of the attribute matcher. 4024*4882a593Smuzhiyun if ($dbg_attr) { 4025*4882a593Smuzhiyun if ($line =~ /^.\s*$Modifier\s*$/) { 4026*4882a593Smuzhiyun ERROR("TEST_ATTR", 4027*4882a593Smuzhiyun "TEST: is attr\n" . $herecurr); 4028*4882a593Smuzhiyun } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { 4029*4882a593Smuzhiyun ERROR("TEST_NOT_ATTR", 4030*4882a593Smuzhiyun "TEST: is not attr ($1 is)\n". $herecurr); 4031*4882a593Smuzhiyun } 4032*4882a593Smuzhiyun next; 4033*4882a593Smuzhiyun } 4034*4882a593Smuzhiyun 4035*4882a593Smuzhiyun# check for initialisation to aggregates open brace on the next line 4036*4882a593Smuzhiyun if ($line =~ /^.\s*{/ && 4037*4882a593Smuzhiyun $prevline =~ /(?:^|[^=])=\s*$/) { 4038*4882a593Smuzhiyun if (ERROR("OPEN_BRACE", 4039*4882a593Smuzhiyun "that open brace { should be on the previous line\n" . $hereprev) && 4040*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 4041*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 4042*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 4043*4882a593Smuzhiyun my $fixedline = $prevrawline; 4044*4882a593Smuzhiyun $fixedline =~ s/\s*=\s*$/ = {/; 4045*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4046*4882a593Smuzhiyun $fixedline = $line; 4047*4882a593Smuzhiyun $fixedline =~ s/^(.\s*)\{\s*/$1/; 4048*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4049*4882a593Smuzhiyun } 4050*4882a593Smuzhiyun } 4051*4882a593Smuzhiyun 4052*4882a593Smuzhiyun# 4053*4882a593Smuzhiyun# Checks which are anchored on the added line. 4054*4882a593Smuzhiyun# 4055*4882a593Smuzhiyun 4056*4882a593Smuzhiyun# check for malformed paths in #include statements (uses RAW line) 4057*4882a593Smuzhiyun if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { 4058*4882a593Smuzhiyun my $path = $1; 4059*4882a593Smuzhiyun if ($path =~ m{//}) { 4060*4882a593Smuzhiyun ERROR("MALFORMED_INCLUDE", 4061*4882a593Smuzhiyun "malformed #include filename\n" . $herecurr); 4062*4882a593Smuzhiyun } 4063*4882a593Smuzhiyun if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { 4064*4882a593Smuzhiyun ERROR("UAPI_INCLUDE", 4065*4882a593Smuzhiyun "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); 4066*4882a593Smuzhiyun } 4067*4882a593Smuzhiyun } 4068*4882a593Smuzhiyun 4069*4882a593Smuzhiyun# no C99 // comments 4070*4882a593Smuzhiyun if ($line =~ m{//}) { 4071*4882a593Smuzhiyun if (ERROR("C99_COMMENTS", 4072*4882a593Smuzhiyun "do not use C99 // comments\n" . $herecurr) && 4073*4882a593Smuzhiyun $fix) { 4074*4882a593Smuzhiyun my $line = $fixed[$fixlinenr]; 4075*4882a593Smuzhiyun if ($line =~ /\/\/(.*)$/) { 4076*4882a593Smuzhiyun my $comment = trim($1); 4077*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; 4078*4882a593Smuzhiyun } 4079*4882a593Smuzhiyun } 4080*4882a593Smuzhiyun } 4081*4882a593Smuzhiyun # Remove C99 comments. 4082*4882a593Smuzhiyun $line =~ s@//.*@@; 4083*4882a593Smuzhiyun $opline =~ s@//.*@@; 4084*4882a593Smuzhiyun 4085*4882a593Smuzhiyun# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider 4086*4882a593Smuzhiyun# the whole statement. 4087*4882a593Smuzhiyun#print "APW <$lines[$realline_next - 1]>\n"; 4088*4882a593Smuzhiyun if (defined $realline_next && 4089*4882a593Smuzhiyun exists $lines[$realline_next - 1] && 4090*4882a593Smuzhiyun !defined $suppress_export{$realline_next} && 4091*4882a593Smuzhiyun ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || 4092*4882a593Smuzhiyun $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { 4093*4882a593Smuzhiyun # Handle definitions which produce identifiers with 4094*4882a593Smuzhiyun # a prefix: 4095*4882a593Smuzhiyun # XXX(foo); 4096*4882a593Smuzhiyun # EXPORT_SYMBOL(something_foo); 4097*4882a593Smuzhiyun my $name = $1; 4098*4882a593Smuzhiyun if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && 4099*4882a593Smuzhiyun $name =~ /^${Ident}_$2/) { 4100*4882a593Smuzhiyun#print "FOO C name<$name>\n"; 4101*4882a593Smuzhiyun $suppress_export{$realline_next} = 1; 4102*4882a593Smuzhiyun 4103*4882a593Smuzhiyun } elsif ($stat !~ /(?: 4104*4882a593Smuzhiyun \n.}\s*$| 4105*4882a593Smuzhiyun ^.DEFINE_$Ident\(\Q$name\E\)| 4106*4882a593Smuzhiyun ^.DECLARE_$Ident\(\Q$name\E\)| 4107*4882a593Smuzhiyun ^.LIST_HEAD\(\Q$name\E\)| 4108*4882a593Smuzhiyun ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| 4109*4882a593Smuzhiyun \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() 4110*4882a593Smuzhiyun )/x) { 4111*4882a593Smuzhiyun#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; 4112*4882a593Smuzhiyun $suppress_export{$realline_next} = 2; 4113*4882a593Smuzhiyun } else { 4114*4882a593Smuzhiyun $suppress_export{$realline_next} = 1; 4115*4882a593Smuzhiyun } 4116*4882a593Smuzhiyun } 4117*4882a593Smuzhiyun if (!defined $suppress_export{$linenr} && 4118*4882a593Smuzhiyun $prevline =~ /^.\s*$/ && 4119*4882a593Smuzhiyun ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || 4120*4882a593Smuzhiyun $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { 4121*4882a593Smuzhiyun#print "FOO B <$lines[$linenr - 1]>\n"; 4122*4882a593Smuzhiyun $suppress_export{$linenr} = 2; 4123*4882a593Smuzhiyun } 4124*4882a593Smuzhiyun if (defined $suppress_export{$linenr} && 4125*4882a593Smuzhiyun $suppress_export{$linenr} == 2) { 4126*4882a593Smuzhiyun WARN("EXPORT_SYMBOL", 4127*4882a593Smuzhiyun "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); 4128*4882a593Smuzhiyun } 4129*4882a593Smuzhiyun 4130*4882a593Smuzhiyun# check for global initialisers. 4131*4882a593Smuzhiyun if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { 4132*4882a593Smuzhiyun if (ERROR("GLOBAL_INITIALISERS", 4133*4882a593Smuzhiyun "do not initialise globals to $1\n" . $herecurr) && 4134*4882a593Smuzhiyun $fix) { 4135*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; 4136*4882a593Smuzhiyun } 4137*4882a593Smuzhiyun } 4138*4882a593Smuzhiyun# check for static initialisers. 4139*4882a593Smuzhiyun if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { 4140*4882a593Smuzhiyun if (ERROR("INITIALISED_STATIC", 4141*4882a593Smuzhiyun "do not initialise statics to $1\n" . 4142*4882a593Smuzhiyun $herecurr) && 4143*4882a593Smuzhiyun $fix) { 4144*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; 4145*4882a593Smuzhiyun } 4146*4882a593Smuzhiyun } 4147*4882a593Smuzhiyun 4148*4882a593Smuzhiyun# check for misordered declarations of char/short/int/long with signed/unsigned 4149*4882a593Smuzhiyun while ($sline =~ m{(\b$TypeMisordered\b)}g) { 4150*4882a593Smuzhiyun my $tmp = trim($1); 4151*4882a593Smuzhiyun WARN("MISORDERED_TYPE", 4152*4882a593Smuzhiyun "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); 4153*4882a593Smuzhiyun } 4154*4882a593Smuzhiyun 4155*4882a593Smuzhiyun# check for unnecessary <signed> int declarations of short/long/long long 4156*4882a593Smuzhiyun while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) { 4157*4882a593Smuzhiyun my $type = trim($1); 4158*4882a593Smuzhiyun next if ($type !~ /\bint\b/); 4159*4882a593Smuzhiyun next if ($type !~ /\b(?:short|long\s+long|long)\b/); 4160*4882a593Smuzhiyun my $new_type = $type; 4161*4882a593Smuzhiyun $new_type =~ s/\b\s*int\s*\b/ /; 4162*4882a593Smuzhiyun $new_type =~ s/\b\s*(?:un)?signed\b\s*/ /; 4163*4882a593Smuzhiyun $new_type =~ s/^const\s+//; 4164*4882a593Smuzhiyun $new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/); 4165*4882a593Smuzhiyun $new_type = "const $new_type" if ($type =~ /^const\b/); 4166*4882a593Smuzhiyun $new_type =~ s/\s+/ /g; 4167*4882a593Smuzhiyun $new_type = trim($new_type); 4168*4882a593Smuzhiyun if (WARN("UNNECESSARY_INT", 4169*4882a593Smuzhiyun "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) && 4170*4882a593Smuzhiyun $fix) { 4171*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/; 4172*4882a593Smuzhiyun } 4173*4882a593Smuzhiyun } 4174*4882a593Smuzhiyun 4175*4882a593Smuzhiyun# check for static const char * arrays. 4176*4882a593Smuzhiyun if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { 4177*4882a593Smuzhiyun WARN("STATIC_CONST_CHAR_ARRAY", 4178*4882a593Smuzhiyun "static const char * array should probably be static const char * const\n" . 4179*4882a593Smuzhiyun $herecurr); 4180*4882a593Smuzhiyun } 4181*4882a593Smuzhiyun 4182*4882a593Smuzhiyun# check for initialized const char arrays that should be static const 4183*4882a593Smuzhiyun if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) { 4184*4882a593Smuzhiyun if (WARN("STATIC_CONST_CHAR_ARRAY", 4185*4882a593Smuzhiyun "const array should probably be static const\n" . $herecurr) && 4186*4882a593Smuzhiyun $fix) { 4187*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/; 4188*4882a593Smuzhiyun } 4189*4882a593Smuzhiyun } 4190*4882a593Smuzhiyun 4191*4882a593Smuzhiyun# check for static char foo[] = "bar" declarations. 4192*4882a593Smuzhiyun if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { 4193*4882a593Smuzhiyun WARN("STATIC_CONST_CHAR_ARRAY", 4194*4882a593Smuzhiyun "static char array declaration should probably be static const char\n" . 4195*4882a593Smuzhiyun $herecurr); 4196*4882a593Smuzhiyun } 4197*4882a593Smuzhiyun 4198*4882a593Smuzhiyun# check for const <foo> const where <foo> is not a pointer or array type 4199*4882a593Smuzhiyun if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { 4200*4882a593Smuzhiyun my $found = $1; 4201*4882a593Smuzhiyun if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { 4202*4882a593Smuzhiyun WARN("CONST_CONST", 4203*4882a593Smuzhiyun "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); 4204*4882a593Smuzhiyun } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { 4205*4882a593Smuzhiyun WARN("CONST_CONST", 4206*4882a593Smuzhiyun "'const $found const' should probably be 'const $found'\n" . $herecurr); 4207*4882a593Smuzhiyun } 4208*4882a593Smuzhiyun } 4209*4882a593Smuzhiyun 4210*4882a593Smuzhiyun# check for non-global char *foo[] = {"bar", ...} declarations. 4211*4882a593Smuzhiyun if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { 4212*4882a593Smuzhiyun WARN("STATIC_CONST_CHAR_ARRAY", 4213*4882a593Smuzhiyun "char * array declaration might be better as static const\n" . 4214*4882a593Smuzhiyun $herecurr); 4215*4882a593Smuzhiyun } 4216*4882a593Smuzhiyun 4217*4882a593Smuzhiyun# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) 4218*4882a593Smuzhiyun if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { 4219*4882a593Smuzhiyun my $array = $1; 4220*4882a593Smuzhiyun if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) { 4221*4882a593Smuzhiyun my $array_div = $1; 4222*4882a593Smuzhiyun if (WARN("ARRAY_SIZE", 4223*4882a593Smuzhiyun "Prefer ARRAY_SIZE($array)\n" . $herecurr) && 4224*4882a593Smuzhiyun $fix) { 4225*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; 4226*4882a593Smuzhiyun } 4227*4882a593Smuzhiyun } 4228*4882a593Smuzhiyun } 4229*4882a593Smuzhiyun 4230*4882a593Smuzhiyun# check for function declarations without arguments like "int foo()" 4231*4882a593Smuzhiyun if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) { 4232*4882a593Smuzhiyun if (ERROR("FUNCTION_WITHOUT_ARGS", 4233*4882a593Smuzhiyun "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && 4234*4882a593Smuzhiyun $fix) { 4235*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; 4236*4882a593Smuzhiyun } 4237*4882a593Smuzhiyun } 4238*4882a593Smuzhiyun 4239*4882a593Smuzhiyun# check for new typedefs, only function parameters and sparse annotations 4240*4882a593Smuzhiyun# make sense. 4241*4882a593Smuzhiyun if ($line =~ /\btypedef\s/ && 4242*4882a593Smuzhiyun $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && 4243*4882a593Smuzhiyun $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && 4244*4882a593Smuzhiyun $line !~ /\b$typeTypedefs\b/ && 4245*4882a593Smuzhiyun $line !~ /\b__bitwise\b/) { 4246*4882a593Smuzhiyun WARN("NEW_TYPEDEFS", 4247*4882a593Smuzhiyun "do not add new typedefs\n" . $herecurr); 4248*4882a593Smuzhiyun } 4249*4882a593Smuzhiyun 4250*4882a593Smuzhiyun# * goes on variable not on type 4251*4882a593Smuzhiyun # (char*[ const]) 4252*4882a593Smuzhiyun while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { 4253*4882a593Smuzhiyun #print "AA<$1>\n"; 4254*4882a593Smuzhiyun my ($ident, $from, $to) = ($1, $2, $2); 4255*4882a593Smuzhiyun 4256*4882a593Smuzhiyun # Should start with a space. 4257*4882a593Smuzhiyun $to =~ s/^(\S)/ $1/; 4258*4882a593Smuzhiyun # Should not end with a space. 4259*4882a593Smuzhiyun $to =~ s/\s+$//; 4260*4882a593Smuzhiyun # '*'s should not have spaces between. 4261*4882a593Smuzhiyun while ($to =~ s/\*\s+\*/\*\*/) { 4262*4882a593Smuzhiyun } 4263*4882a593Smuzhiyun 4264*4882a593Smuzhiyun## print "1: from<$from> to<$to> ident<$ident>\n"; 4265*4882a593Smuzhiyun if ($from ne $to) { 4266*4882a593Smuzhiyun if (ERROR("POINTER_LOCATION", 4267*4882a593Smuzhiyun "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && 4268*4882a593Smuzhiyun $fix) { 4269*4882a593Smuzhiyun my $sub_from = $ident; 4270*4882a593Smuzhiyun my $sub_to = $ident; 4271*4882a593Smuzhiyun $sub_to =~ s/\Q$from\E/$to/; 4272*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4273*4882a593Smuzhiyun s@\Q$sub_from\E@$sub_to@; 4274*4882a593Smuzhiyun } 4275*4882a593Smuzhiyun } 4276*4882a593Smuzhiyun } 4277*4882a593Smuzhiyun while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { 4278*4882a593Smuzhiyun #print "BB<$1>\n"; 4279*4882a593Smuzhiyun my ($match, $from, $to, $ident) = ($1, $2, $2, $3); 4280*4882a593Smuzhiyun 4281*4882a593Smuzhiyun # Should start with a space. 4282*4882a593Smuzhiyun $to =~ s/^(\S)/ $1/; 4283*4882a593Smuzhiyun # Should not end with a space. 4284*4882a593Smuzhiyun $to =~ s/\s+$//; 4285*4882a593Smuzhiyun # '*'s should not have spaces between. 4286*4882a593Smuzhiyun while ($to =~ s/\*\s+\*/\*\*/) { 4287*4882a593Smuzhiyun } 4288*4882a593Smuzhiyun # Modifiers should have spaces. 4289*4882a593Smuzhiyun $to =~ s/(\b$Modifier$)/$1 /; 4290*4882a593Smuzhiyun 4291*4882a593Smuzhiyun## print "2: from<$from> to<$to> ident<$ident>\n"; 4292*4882a593Smuzhiyun if ($from ne $to && $ident !~ /^$Modifier$/) { 4293*4882a593Smuzhiyun if (ERROR("POINTER_LOCATION", 4294*4882a593Smuzhiyun "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && 4295*4882a593Smuzhiyun $fix) { 4296*4882a593Smuzhiyun 4297*4882a593Smuzhiyun my $sub_from = $match; 4298*4882a593Smuzhiyun my $sub_to = $match; 4299*4882a593Smuzhiyun $sub_to =~ s/\Q$from\E/$to/; 4300*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4301*4882a593Smuzhiyun s@\Q$sub_from\E@$sub_to@; 4302*4882a593Smuzhiyun } 4303*4882a593Smuzhiyun } 4304*4882a593Smuzhiyun } 4305*4882a593Smuzhiyun 4306*4882a593Smuzhiyun# avoid BUG() or BUG_ON() 4307*4882a593Smuzhiyun if ($line =~ /\b(?:BUG|BUG_ON)\b/) { 4308*4882a593Smuzhiyun my $msg_level = \&WARN; 4309*4882a593Smuzhiyun $msg_level = \&CHK if ($file); 4310*4882a593Smuzhiyun &{$msg_level}("AVOID_BUG", 4311*4882a593Smuzhiyun "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); 4312*4882a593Smuzhiyun } 4313*4882a593Smuzhiyun 4314*4882a593Smuzhiyun# avoid LINUX_VERSION_CODE 4315*4882a593Smuzhiyun if ($line =~ /\bLINUX_VERSION_CODE\b/) { 4316*4882a593Smuzhiyun WARN("LINUX_VERSION_CODE", 4317*4882a593Smuzhiyun "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); 4318*4882a593Smuzhiyun } 4319*4882a593Smuzhiyun 4320*4882a593Smuzhiyun# check for uses of printk_ratelimit 4321*4882a593Smuzhiyun if ($line =~ /\bprintk_ratelimit\s*\(/) { 4322*4882a593Smuzhiyun WARN("PRINTK_RATELIMITED", 4323*4882a593Smuzhiyun "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); 4324*4882a593Smuzhiyun } 4325*4882a593Smuzhiyun 4326*4882a593Smuzhiyun# printk should use KERN_* levels 4327*4882a593Smuzhiyun if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) { 4328*4882a593Smuzhiyun WARN("PRINTK_WITHOUT_KERN_LEVEL", 4329*4882a593Smuzhiyun "printk() should include KERN_<LEVEL> facility level\n" . $herecurr); 4330*4882a593Smuzhiyun } 4331*4882a593Smuzhiyun 4332*4882a593Smuzhiyun if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { 4333*4882a593Smuzhiyun my $orig = $1; 4334*4882a593Smuzhiyun my $level = lc($orig); 4335*4882a593Smuzhiyun $level = "warn" if ($level eq "warning"); 4336*4882a593Smuzhiyun my $level2 = $level; 4337*4882a593Smuzhiyun $level2 = "dbg" if ($level eq "debug"); 4338*4882a593Smuzhiyun WARN("PREFER_PR_LEVEL", 4339*4882a593Smuzhiyun "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); 4340*4882a593Smuzhiyun } 4341*4882a593Smuzhiyun 4342*4882a593Smuzhiyun if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { 4343*4882a593Smuzhiyun my $orig = $1; 4344*4882a593Smuzhiyun my $level = lc($orig); 4345*4882a593Smuzhiyun $level = "warn" if ($level eq "warning"); 4346*4882a593Smuzhiyun $level = "dbg" if ($level eq "debug"); 4347*4882a593Smuzhiyun WARN("PREFER_DEV_LEVEL", 4348*4882a593Smuzhiyun "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); 4349*4882a593Smuzhiyun } 4350*4882a593Smuzhiyun 4351*4882a593Smuzhiyun# trace_printk should not be used in production code. 4352*4882a593Smuzhiyun if ($line =~ /\b(trace_printk|trace_puts|ftrace_vprintk)\s*\(/) { 4353*4882a593Smuzhiyun WARN("TRACE_PRINTK", 4354*4882a593Smuzhiyun "Do not use $1() in production code (this can be ignored if built only with a debug config option)\n" . $herecurr); 4355*4882a593Smuzhiyun } 4356*4882a593Smuzhiyun 4357*4882a593Smuzhiyun# ENOSYS means "bad syscall nr" and nothing else. This will have a small 4358*4882a593Smuzhiyun# number of false positives, but assembly files are not checked, so at 4359*4882a593Smuzhiyun# least the arch entry code will not trigger this warning. 4360*4882a593Smuzhiyun if ($line =~ /\bENOSYS\b/) { 4361*4882a593Smuzhiyun WARN("ENOSYS", 4362*4882a593Smuzhiyun "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); 4363*4882a593Smuzhiyun } 4364*4882a593Smuzhiyun 4365*4882a593Smuzhiyun# ENOTSUPP is not a standard error code and should be avoided in new patches. 4366*4882a593Smuzhiyun# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP. 4367*4882a593Smuzhiyun# Similarly to ENOSYS warning a small number of false positives is expected. 4368*4882a593Smuzhiyun if (!$file && $line =~ /\bENOTSUPP\b/) { 4369*4882a593Smuzhiyun if (WARN("ENOTSUPP", 4370*4882a593Smuzhiyun "ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr) && 4371*4882a593Smuzhiyun $fix) { 4372*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bENOTSUPP\b/EOPNOTSUPP/; 4373*4882a593Smuzhiyun } 4374*4882a593Smuzhiyun } 4375*4882a593Smuzhiyun 4376*4882a593Smuzhiyun# function brace can't be on same line, except for #defines of do while, 4377*4882a593Smuzhiyun# or if closed on same line 4378*4882a593Smuzhiyun if ($perl_version_ok && 4379*4882a593Smuzhiyun $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ && 4380*4882a593Smuzhiyun $sline !~ /\#\s*define\b.*do\s*\{/ && 4381*4882a593Smuzhiyun $sline !~ /}/) { 4382*4882a593Smuzhiyun if (ERROR("OPEN_BRACE", 4383*4882a593Smuzhiyun "open brace '{' following function definitions go on the next line\n" . $herecurr) && 4384*4882a593Smuzhiyun $fix) { 4385*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 4386*4882a593Smuzhiyun my $fixed_line = $rawline; 4387*4882a593Smuzhiyun $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/; 4388*4882a593Smuzhiyun my $line1 = $1; 4389*4882a593Smuzhiyun my $line2 = $2; 4390*4882a593Smuzhiyun fix_insert_line($fixlinenr, ltrim($line1)); 4391*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+{"); 4392*4882a593Smuzhiyun if ($line2 !~ /^\s*$/) { 4393*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+\t" . trim($line2)); 4394*4882a593Smuzhiyun } 4395*4882a593Smuzhiyun } 4396*4882a593Smuzhiyun } 4397*4882a593Smuzhiyun 4398*4882a593Smuzhiyun# open braces for enum, union and struct go on the same line. 4399*4882a593Smuzhiyun if ($line =~ /^.\s*{/ && 4400*4882a593Smuzhiyun $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { 4401*4882a593Smuzhiyun if (ERROR("OPEN_BRACE", 4402*4882a593Smuzhiyun "open brace '{' following $1 go on the same line\n" . $hereprev) && 4403*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 4404*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 4405*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 4406*4882a593Smuzhiyun my $fixedline = rtrim($prevrawline) . " {"; 4407*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4408*4882a593Smuzhiyun $fixedline = $rawline; 4409*4882a593Smuzhiyun $fixedline =~ s/^(.\s*)\{\s*/$1\t/; 4410*4882a593Smuzhiyun if ($fixedline !~ /^\+\s*$/) { 4411*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4412*4882a593Smuzhiyun } 4413*4882a593Smuzhiyun } 4414*4882a593Smuzhiyun } 4415*4882a593Smuzhiyun 4416*4882a593Smuzhiyun# missing space after union, struct or enum definition 4417*4882a593Smuzhiyun if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { 4418*4882a593Smuzhiyun if (WARN("SPACING", 4419*4882a593Smuzhiyun "missing space after $1 definition\n" . $herecurr) && 4420*4882a593Smuzhiyun $fix) { 4421*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4422*4882a593Smuzhiyun s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; 4423*4882a593Smuzhiyun } 4424*4882a593Smuzhiyun } 4425*4882a593Smuzhiyun 4426*4882a593Smuzhiyun# Function pointer declarations 4427*4882a593Smuzhiyun# check spacing between type, funcptr, and args 4428*4882a593Smuzhiyun# canonical declaration is "type (*funcptr)(args...)" 4429*4882a593Smuzhiyun if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { 4430*4882a593Smuzhiyun my $declare = $1; 4431*4882a593Smuzhiyun my $pre_pointer_space = $2; 4432*4882a593Smuzhiyun my $post_pointer_space = $3; 4433*4882a593Smuzhiyun my $funcname = $4; 4434*4882a593Smuzhiyun my $post_funcname_space = $5; 4435*4882a593Smuzhiyun my $pre_args_space = $6; 4436*4882a593Smuzhiyun 4437*4882a593Smuzhiyun# the $Declare variable will capture all spaces after the type 4438*4882a593Smuzhiyun# so check it for a missing trailing missing space but pointer return types 4439*4882a593Smuzhiyun# don't need a space so don't warn for those. 4440*4882a593Smuzhiyun my $post_declare_space = ""; 4441*4882a593Smuzhiyun if ($declare =~ /(\s+)$/) { 4442*4882a593Smuzhiyun $post_declare_space = $1; 4443*4882a593Smuzhiyun $declare = rtrim($declare); 4444*4882a593Smuzhiyun } 4445*4882a593Smuzhiyun if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { 4446*4882a593Smuzhiyun WARN("SPACING", 4447*4882a593Smuzhiyun "missing space after return type\n" . $herecurr); 4448*4882a593Smuzhiyun $post_declare_space = " "; 4449*4882a593Smuzhiyun } 4450*4882a593Smuzhiyun 4451*4882a593Smuzhiyun# unnecessary space "type (*funcptr)(args...)" 4452*4882a593Smuzhiyun# This test is not currently implemented because these declarations are 4453*4882a593Smuzhiyun# equivalent to 4454*4882a593Smuzhiyun# int foo(int bar, ...) 4455*4882a593Smuzhiyun# and this is form shouldn't/doesn't generate a checkpatch warning. 4456*4882a593Smuzhiyun# 4457*4882a593Smuzhiyun# elsif ($declare =~ /\s{2,}$/) { 4458*4882a593Smuzhiyun# WARN("SPACING", 4459*4882a593Smuzhiyun# "Multiple spaces after return type\n" . $herecurr); 4460*4882a593Smuzhiyun# } 4461*4882a593Smuzhiyun 4462*4882a593Smuzhiyun# unnecessary space "type ( *funcptr)(args...)" 4463*4882a593Smuzhiyun if (defined $pre_pointer_space && 4464*4882a593Smuzhiyun $pre_pointer_space =~ /^\s/) { 4465*4882a593Smuzhiyun WARN("SPACING", 4466*4882a593Smuzhiyun "Unnecessary space after function pointer open parenthesis\n" . $herecurr); 4467*4882a593Smuzhiyun } 4468*4882a593Smuzhiyun 4469*4882a593Smuzhiyun# unnecessary space "type (* funcptr)(args...)" 4470*4882a593Smuzhiyun if (defined $post_pointer_space && 4471*4882a593Smuzhiyun $post_pointer_space =~ /^\s/) { 4472*4882a593Smuzhiyun WARN("SPACING", 4473*4882a593Smuzhiyun "Unnecessary space before function pointer name\n" . $herecurr); 4474*4882a593Smuzhiyun } 4475*4882a593Smuzhiyun 4476*4882a593Smuzhiyun# unnecessary space "type (*funcptr )(args...)" 4477*4882a593Smuzhiyun if (defined $post_funcname_space && 4478*4882a593Smuzhiyun $post_funcname_space =~ /^\s/) { 4479*4882a593Smuzhiyun WARN("SPACING", 4480*4882a593Smuzhiyun "Unnecessary space after function pointer name\n" . $herecurr); 4481*4882a593Smuzhiyun } 4482*4882a593Smuzhiyun 4483*4882a593Smuzhiyun# unnecessary space "type (*funcptr) (args...)" 4484*4882a593Smuzhiyun if (defined $pre_args_space && 4485*4882a593Smuzhiyun $pre_args_space =~ /^\s/) { 4486*4882a593Smuzhiyun WARN("SPACING", 4487*4882a593Smuzhiyun "Unnecessary space before function pointer arguments\n" . $herecurr); 4488*4882a593Smuzhiyun } 4489*4882a593Smuzhiyun 4490*4882a593Smuzhiyun if (show_type("SPACING") && $fix) { 4491*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4492*4882a593Smuzhiyun s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; 4493*4882a593Smuzhiyun } 4494*4882a593Smuzhiyun } 4495*4882a593Smuzhiyun 4496*4882a593Smuzhiyun# check for spacing round square brackets; allowed: 4497*4882a593Smuzhiyun# 1. with a type on the left -- int [] a; 4498*4882a593Smuzhiyun# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, 4499*4882a593Smuzhiyun# 3. inside a curly brace -- = { [0...10] = 5 } 4500*4882a593Smuzhiyun while ($line =~ /(.*?\s)\[/g) { 4501*4882a593Smuzhiyun my ($where, $prefix) = ($-[1], $1); 4502*4882a593Smuzhiyun if ($prefix !~ /$Type\s+$/ && 4503*4882a593Smuzhiyun ($where != 0 || $prefix !~ /^.\s+$/) && 4504*4882a593Smuzhiyun $prefix !~ /[{,:]\s+$/) { 4505*4882a593Smuzhiyun if (ERROR("BRACKET_SPACE", 4506*4882a593Smuzhiyun "space prohibited before open square bracket '['\n" . $herecurr) && 4507*4882a593Smuzhiyun $fix) { 4508*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4509*4882a593Smuzhiyun s/^(\+.*?)\s+\[/$1\[/; 4510*4882a593Smuzhiyun } 4511*4882a593Smuzhiyun } 4512*4882a593Smuzhiyun } 4513*4882a593Smuzhiyun 4514*4882a593Smuzhiyun# check for spaces between functions and their parentheses. 4515*4882a593Smuzhiyun while ($line =~ /($Ident)\s+\(/g) { 4516*4882a593Smuzhiyun my $name = $1; 4517*4882a593Smuzhiyun my $ctx_before = substr($line, 0, $-[1]); 4518*4882a593Smuzhiyun my $ctx = "$ctx_before$name"; 4519*4882a593Smuzhiyun 4520*4882a593Smuzhiyun # Ignore those directives where spaces _are_ permitted. 4521*4882a593Smuzhiyun if ($name =~ /^(?: 4522*4882a593Smuzhiyun if|for|while|switch|return|case| 4523*4882a593Smuzhiyun volatile|__volatile__| 4524*4882a593Smuzhiyun __attribute__|format|__extension__| 4525*4882a593Smuzhiyun asm|__asm__)$/x) 4526*4882a593Smuzhiyun { 4527*4882a593Smuzhiyun # cpp #define statements have non-optional spaces, ie 4528*4882a593Smuzhiyun # if there is a space between the name and the open 4529*4882a593Smuzhiyun # parenthesis it is simply not a parameter group. 4530*4882a593Smuzhiyun } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { 4531*4882a593Smuzhiyun 4532*4882a593Smuzhiyun # cpp #elif statement condition may start with a ( 4533*4882a593Smuzhiyun } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { 4534*4882a593Smuzhiyun 4535*4882a593Smuzhiyun # If this whole things ends with a type its most 4536*4882a593Smuzhiyun # likely a typedef for a function. 4537*4882a593Smuzhiyun } elsif ($ctx =~ /$Type$/) { 4538*4882a593Smuzhiyun 4539*4882a593Smuzhiyun } else { 4540*4882a593Smuzhiyun if (WARN("SPACING", 4541*4882a593Smuzhiyun "space prohibited between function name and open parenthesis '('\n" . $herecurr) && 4542*4882a593Smuzhiyun $fix) { 4543*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4544*4882a593Smuzhiyun s/\b$name\s+\(/$name\(/; 4545*4882a593Smuzhiyun } 4546*4882a593Smuzhiyun } 4547*4882a593Smuzhiyun } 4548*4882a593Smuzhiyun 4549*4882a593Smuzhiyun# Check operator spacing. 4550*4882a593Smuzhiyun if (!($line=~/\#\s*include/)) { 4551*4882a593Smuzhiyun my $fixed_line = ""; 4552*4882a593Smuzhiyun my $line_fixed = 0; 4553*4882a593Smuzhiyun 4554*4882a593Smuzhiyun my $ops = qr{ 4555*4882a593Smuzhiyun <<=|>>=|<=|>=|==|!=| 4556*4882a593Smuzhiyun \+=|-=|\*=|\/=|%=|\^=|\|=|&=| 4557*4882a593Smuzhiyun =>|->|<<|>>|<|>|=|!|~| 4558*4882a593Smuzhiyun &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| 4559*4882a593Smuzhiyun \?:|\?|: 4560*4882a593Smuzhiyun }x; 4561*4882a593Smuzhiyun my @elements = split(/($ops|;)/, $opline); 4562*4882a593Smuzhiyun 4563*4882a593Smuzhiyun## print("element count: <" . $#elements . ">\n"); 4564*4882a593Smuzhiyun## foreach my $el (@elements) { 4565*4882a593Smuzhiyun## print("el: <$el>\n"); 4566*4882a593Smuzhiyun## } 4567*4882a593Smuzhiyun 4568*4882a593Smuzhiyun my @fix_elements = (); 4569*4882a593Smuzhiyun my $off = 0; 4570*4882a593Smuzhiyun 4571*4882a593Smuzhiyun foreach my $el (@elements) { 4572*4882a593Smuzhiyun push(@fix_elements, substr($rawline, $off, length($el))); 4573*4882a593Smuzhiyun $off += length($el); 4574*4882a593Smuzhiyun } 4575*4882a593Smuzhiyun 4576*4882a593Smuzhiyun $off = 0; 4577*4882a593Smuzhiyun 4578*4882a593Smuzhiyun my $blank = copy_spacing($opline); 4579*4882a593Smuzhiyun my $last_after = -1; 4580*4882a593Smuzhiyun 4581*4882a593Smuzhiyun for (my $n = 0; $n < $#elements; $n += 2) { 4582*4882a593Smuzhiyun 4583*4882a593Smuzhiyun my $good = $fix_elements[$n] . $fix_elements[$n + 1]; 4584*4882a593Smuzhiyun 4585*4882a593Smuzhiyun## print("n: <$n> good: <$good>\n"); 4586*4882a593Smuzhiyun 4587*4882a593Smuzhiyun $off += length($elements[$n]); 4588*4882a593Smuzhiyun 4589*4882a593Smuzhiyun # Pick up the preceding and succeeding characters. 4590*4882a593Smuzhiyun my $ca = substr($opline, 0, $off); 4591*4882a593Smuzhiyun my $cc = ''; 4592*4882a593Smuzhiyun if (length($opline) >= ($off + length($elements[$n + 1]))) { 4593*4882a593Smuzhiyun $cc = substr($opline, $off + length($elements[$n + 1])); 4594*4882a593Smuzhiyun } 4595*4882a593Smuzhiyun my $cb = "$ca$;$cc"; 4596*4882a593Smuzhiyun 4597*4882a593Smuzhiyun my $a = ''; 4598*4882a593Smuzhiyun $a = 'V' if ($elements[$n] ne ''); 4599*4882a593Smuzhiyun $a = 'W' if ($elements[$n] =~ /\s$/); 4600*4882a593Smuzhiyun $a = 'C' if ($elements[$n] =~ /$;$/); 4601*4882a593Smuzhiyun $a = 'B' if ($elements[$n] =~ /(\[|\()$/); 4602*4882a593Smuzhiyun $a = 'O' if ($elements[$n] eq ''); 4603*4882a593Smuzhiyun $a = 'E' if ($ca =~ /^\s*$/); 4604*4882a593Smuzhiyun 4605*4882a593Smuzhiyun my $op = $elements[$n + 1]; 4606*4882a593Smuzhiyun 4607*4882a593Smuzhiyun my $c = ''; 4608*4882a593Smuzhiyun if (defined $elements[$n + 2]) { 4609*4882a593Smuzhiyun $c = 'V' if ($elements[$n + 2] ne ''); 4610*4882a593Smuzhiyun $c = 'W' if ($elements[$n + 2] =~ /^\s/); 4611*4882a593Smuzhiyun $c = 'C' if ($elements[$n + 2] =~ /^$;/); 4612*4882a593Smuzhiyun $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); 4613*4882a593Smuzhiyun $c = 'O' if ($elements[$n + 2] eq ''); 4614*4882a593Smuzhiyun $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); 4615*4882a593Smuzhiyun } else { 4616*4882a593Smuzhiyun $c = 'E'; 4617*4882a593Smuzhiyun } 4618*4882a593Smuzhiyun 4619*4882a593Smuzhiyun my $ctx = "${a}x${c}"; 4620*4882a593Smuzhiyun 4621*4882a593Smuzhiyun my $at = "(ctx:$ctx)"; 4622*4882a593Smuzhiyun 4623*4882a593Smuzhiyun my $ptr = substr($blank, 0, $off) . "^"; 4624*4882a593Smuzhiyun my $hereptr = "$hereline$ptr\n"; 4625*4882a593Smuzhiyun 4626*4882a593Smuzhiyun # Pull out the value of this operator. 4627*4882a593Smuzhiyun my $op_type = substr($curr_values, $off + 1, 1); 4628*4882a593Smuzhiyun 4629*4882a593Smuzhiyun # Get the full operator variant. 4630*4882a593Smuzhiyun my $opv = $op . substr($curr_vars, $off, 1); 4631*4882a593Smuzhiyun 4632*4882a593Smuzhiyun # Ignore operators passed as parameters. 4633*4882a593Smuzhiyun if ($op_type ne 'V' && 4634*4882a593Smuzhiyun $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { 4635*4882a593Smuzhiyun 4636*4882a593Smuzhiyun# # Ignore comments 4637*4882a593Smuzhiyun# } elsif ($op =~ /^$;+$/) { 4638*4882a593Smuzhiyun 4639*4882a593Smuzhiyun # ; should have either the end of line or a space or \ after it 4640*4882a593Smuzhiyun } elsif ($op eq ';') { 4641*4882a593Smuzhiyun if ($ctx !~ /.x[WEBC]/ && 4642*4882a593Smuzhiyun $cc !~ /^\\/ && $cc !~ /^;/) { 4643*4882a593Smuzhiyun if (ERROR("SPACING", 4644*4882a593Smuzhiyun "space required after that '$op' $at\n" . $hereptr)) { 4645*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; 4646*4882a593Smuzhiyun $line_fixed = 1; 4647*4882a593Smuzhiyun } 4648*4882a593Smuzhiyun } 4649*4882a593Smuzhiyun 4650*4882a593Smuzhiyun # // is a comment 4651*4882a593Smuzhiyun } elsif ($op eq '//') { 4652*4882a593Smuzhiyun 4653*4882a593Smuzhiyun # : when part of a bitfield 4654*4882a593Smuzhiyun } elsif ($opv eq ':B') { 4655*4882a593Smuzhiyun # skip the bitfield test for now 4656*4882a593Smuzhiyun 4657*4882a593Smuzhiyun # No spaces for: 4658*4882a593Smuzhiyun # -> 4659*4882a593Smuzhiyun } elsif ($op eq '->') { 4660*4882a593Smuzhiyun if ($ctx =~ /Wx.|.xW/) { 4661*4882a593Smuzhiyun if (ERROR("SPACING", 4662*4882a593Smuzhiyun "spaces prohibited around that '$op' $at\n" . $hereptr)) { 4663*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4664*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4665*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4666*4882a593Smuzhiyun } 4667*4882a593Smuzhiyun $line_fixed = 1; 4668*4882a593Smuzhiyun } 4669*4882a593Smuzhiyun } 4670*4882a593Smuzhiyun 4671*4882a593Smuzhiyun # , must not have a space before and must have a space on the right. 4672*4882a593Smuzhiyun } elsif ($op eq ',') { 4673*4882a593Smuzhiyun my $rtrim_before = 0; 4674*4882a593Smuzhiyun my $space_after = 0; 4675*4882a593Smuzhiyun if ($ctx =~ /Wx./) { 4676*4882a593Smuzhiyun if (ERROR("SPACING", 4677*4882a593Smuzhiyun "space prohibited before that '$op' $at\n" . $hereptr)) { 4678*4882a593Smuzhiyun $line_fixed = 1; 4679*4882a593Smuzhiyun $rtrim_before = 1; 4680*4882a593Smuzhiyun } 4681*4882a593Smuzhiyun } 4682*4882a593Smuzhiyun if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { 4683*4882a593Smuzhiyun if (ERROR("SPACING", 4684*4882a593Smuzhiyun "space required after that '$op' $at\n" . $hereptr)) { 4685*4882a593Smuzhiyun $line_fixed = 1; 4686*4882a593Smuzhiyun $last_after = $n; 4687*4882a593Smuzhiyun $space_after = 1; 4688*4882a593Smuzhiyun } 4689*4882a593Smuzhiyun } 4690*4882a593Smuzhiyun if ($rtrim_before || $space_after) { 4691*4882a593Smuzhiyun if ($rtrim_before) { 4692*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4693*4882a593Smuzhiyun } else { 4694*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); 4695*4882a593Smuzhiyun } 4696*4882a593Smuzhiyun if ($space_after) { 4697*4882a593Smuzhiyun $good .= " "; 4698*4882a593Smuzhiyun } 4699*4882a593Smuzhiyun } 4700*4882a593Smuzhiyun 4701*4882a593Smuzhiyun # '*' as part of a type definition -- reported already. 4702*4882a593Smuzhiyun } elsif ($opv eq '*_') { 4703*4882a593Smuzhiyun #warn "'*' is part of type\n"; 4704*4882a593Smuzhiyun 4705*4882a593Smuzhiyun # unary operators should have a space before and 4706*4882a593Smuzhiyun # none after. May be left adjacent to another 4707*4882a593Smuzhiyun # unary operator, or a cast 4708*4882a593Smuzhiyun } elsif ($op eq '!' || $op eq '~' || 4709*4882a593Smuzhiyun $opv eq '*U' || $opv eq '-U' || 4710*4882a593Smuzhiyun $opv eq '&U' || $opv eq '&&U') { 4711*4882a593Smuzhiyun if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { 4712*4882a593Smuzhiyun if (ERROR("SPACING", 4713*4882a593Smuzhiyun "space required before that '$op' $at\n" . $hereptr)) { 4714*4882a593Smuzhiyun if ($n != $last_after + 2) { 4715*4882a593Smuzhiyun $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); 4716*4882a593Smuzhiyun $line_fixed = 1; 4717*4882a593Smuzhiyun } 4718*4882a593Smuzhiyun } 4719*4882a593Smuzhiyun } 4720*4882a593Smuzhiyun if ($op eq '*' && $cc =~/\s*$Modifier\b/) { 4721*4882a593Smuzhiyun # A unary '*' may be const 4722*4882a593Smuzhiyun 4723*4882a593Smuzhiyun } elsif ($ctx =~ /.xW/) { 4724*4882a593Smuzhiyun if (ERROR("SPACING", 4725*4882a593Smuzhiyun "space prohibited after that '$op' $at\n" . $hereptr)) { 4726*4882a593Smuzhiyun $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); 4727*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4728*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4729*4882a593Smuzhiyun } 4730*4882a593Smuzhiyun $line_fixed = 1; 4731*4882a593Smuzhiyun } 4732*4882a593Smuzhiyun } 4733*4882a593Smuzhiyun 4734*4882a593Smuzhiyun # unary ++ and unary -- are allowed no space on one side. 4735*4882a593Smuzhiyun } elsif ($op eq '++' or $op eq '--') { 4736*4882a593Smuzhiyun if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { 4737*4882a593Smuzhiyun if (ERROR("SPACING", 4738*4882a593Smuzhiyun "space required one side of that '$op' $at\n" . $hereptr)) { 4739*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; 4740*4882a593Smuzhiyun $line_fixed = 1; 4741*4882a593Smuzhiyun } 4742*4882a593Smuzhiyun } 4743*4882a593Smuzhiyun if ($ctx =~ /Wx[BE]/ || 4744*4882a593Smuzhiyun ($ctx =~ /Wx./ && $cc =~ /^;/)) { 4745*4882a593Smuzhiyun if (ERROR("SPACING", 4746*4882a593Smuzhiyun "space prohibited before that '$op' $at\n" . $hereptr)) { 4747*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4748*4882a593Smuzhiyun $line_fixed = 1; 4749*4882a593Smuzhiyun } 4750*4882a593Smuzhiyun } 4751*4882a593Smuzhiyun if ($ctx =~ /ExW/) { 4752*4882a593Smuzhiyun if (ERROR("SPACING", 4753*4882a593Smuzhiyun "space prohibited after that '$op' $at\n" . $hereptr)) { 4754*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); 4755*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4756*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4757*4882a593Smuzhiyun } 4758*4882a593Smuzhiyun $line_fixed = 1; 4759*4882a593Smuzhiyun } 4760*4882a593Smuzhiyun } 4761*4882a593Smuzhiyun 4762*4882a593Smuzhiyun # << and >> may either have or not have spaces both sides 4763*4882a593Smuzhiyun } elsif ($op eq '<<' or $op eq '>>' or 4764*4882a593Smuzhiyun $op eq '&' or $op eq '^' or $op eq '|' or 4765*4882a593Smuzhiyun $op eq '+' or $op eq '-' or 4766*4882a593Smuzhiyun $op eq '*' or $op eq '/' or 4767*4882a593Smuzhiyun $op eq '%') 4768*4882a593Smuzhiyun { 4769*4882a593Smuzhiyun if ($check) { 4770*4882a593Smuzhiyun if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { 4771*4882a593Smuzhiyun if (CHK("SPACING", 4772*4882a593Smuzhiyun "spaces preferred around that '$op' $at\n" . $hereptr)) { 4773*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; 4774*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4775*4882a593Smuzhiyun $line_fixed = 1; 4776*4882a593Smuzhiyun } 4777*4882a593Smuzhiyun } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { 4778*4882a593Smuzhiyun if (CHK("SPACING", 4779*4882a593Smuzhiyun "space preferred before that '$op' $at\n" . $hereptr)) { 4780*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); 4781*4882a593Smuzhiyun $line_fixed = 1; 4782*4882a593Smuzhiyun } 4783*4882a593Smuzhiyun } 4784*4882a593Smuzhiyun } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { 4785*4882a593Smuzhiyun if (ERROR("SPACING", 4786*4882a593Smuzhiyun "need consistent spacing around '$op' $at\n" . $hereptr)) { 4787*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; 4788*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4789*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4790*4882a593Smuzhiyun } 4791*4882a593Smuzhiyun $line_fixed = 1; 4792*4882a593Smuzhiyun } 4793*4882a593Smuzhiyun } 4794*4882a593Smuzhiyun 4795*4882a593Smuzhiyun # A colon needs no spaces before when it is 4796*4882a593Smuzhiyun # terminating a case value or a label. 4797*4882a593Smuzhiyun } elsif ($opv eq ':C' || $opv eq ':L') { 4798*4882a593Smuzhiyun if ($ctx =~ /Wx./) { 4799*4882a593Smuzhiyun if (ERROR("SPACING", 4800*4882a593Smuzhiyun "space prohibited before that '$op' $at\n" . $hereptr)) { 4801*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4802*4882a593Smuzhiyun $line_fixed = 1; 4803*4882a593Smuzhiyun } 4804*4882a593Smuzhiyun } 4805*4882a593Smuzhiyun 4806*4882a593Smuzhiyun # All the others need spaces both sides. 4807*4882a593Smuzhiyun } elsif ($ctx !~ /[EWC]x[CWE]/) { 4808*4882a593Smuzhiyun my $ok = 0; 4809*4882a593Smuzhiyun 4810*4882a593Smuzhiyun # Ignore email addresses <foo@bar> 4811*4882a593Smuzhiyun if (($op eq '<' && 4812*4882a593Smuzhiyun $cc =~ /^\S+\@\S+>/) || 4813*4882a593Smuzhiyun ($op eq '>' && 4814*4882a593Smuzhiyun $ca =~ /<\S+\@\S+$/)) 4815*4882a593Smuzhiyun { 4816*4882a593Smuzhiyun $ok = 1; 4817*4882a593Smuzhiyun } 4818*4882a593Smuzhiyun 4819*4882a593Smuzhiyun # for asm volatile statements 4820*4882a593Smuzhiyun # ignore a colon with another 4821*4882a593Smuzhiyun # colon immediately before or after 4822*4882a593Smuzhiyun if (($op eq ':') && 4823*4882a593Smuzhiyun ($ca =~ /:$/ || $cc =~ /^:/)) { 4824*4882a593Smuzhiyun $ok = 1; 4825*4882a593Smuzhiyun } 4826*4882a593Smuzhiyun 4827*4882a593Smuzhiyun # messages are ERROR, but ?: are CHK 4828*4882a593Smuzhiyun if ($ok == 0) { 4829*4882a593Smuzhiyun my $msg_level = \&ERROR; 4830*4882a593Smuzhiyun $msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); 4831*4882a593Smuzhiyun 4832*4882a593Smuzhiyun if (&{$msg_level}("SPACING", 4833*4882a593Smuzhiyun "spaces required around that '$op' $at\n" . $hereptr)) { 4834*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; 4835*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4836*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4837*4882a593Smuzhiyun } 4838*4882a593Smuzhiyun $line_fixed = 1; 4839*4882a593Smuzhiyun } 4840*4882a593Smuzhiyun } 4841*4882a593Smuzhiyun } 4842*4882a593Smuzhiyun $off += length($elements[$n + 1]); 4843*4882a593Smuzhiyun 4844*4882a593Smuzhiyun## print("n: <$n> GOOD: <$good>\n"); 4845*4882a593Smuzhiyun 4846*4882a593Smuzhiyun $fixed_line = $fixed_line . $good; 4847*4882a593Smuzhiyun } 4848*4882a593Smuzhiyun 4849*4882a593Smuzhiyun if (($#elements % 2) == 0) { 4850*4882a593Smuzhiyun $fixed_line = $fixed_line . $fix_elements[$#elements]; 4851*4882a593Smuzhiyun } 4852*4882a593Smuzhiyun 4853*4882a593Smuzhiyun if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { 4854*4882a593Smuzhiyun $fixed[$fixlinenr] = $fixed_line; 4855*4882a593Smuzhiyun } 4856*4882a593Smuzhiyun 4857*4882a593Smuzhiyun 4858*4882a593Smuzhiyun } 4859*4882a593Smuzhiyun 4860*4882a593Smuzhiyun# check for whitespace before a non-naked semicolon 4861*4882a593Smuzhiyun if ($line =~ /^\+.*\S\s+;\s*$/) { 4862*4882a593Smuzhiyun if (WARN("SPACING", 4863*4882a593Smuzhiyun "space prohibited before semicolon\n" . $herecurr) && 4864*4882a593Smuzhiyun $fix) { 4865*4882a593Smuzhiyun 1 while $fixed[$fixlinenr] =~ 4866*4882a593Smuzhiyun s/^(\+.*\S)\s+;/$1;/; 4867*4882a593Smuzhiyun } 4868*4882a593Smuzhiyun } 4869*4882a593Smuzhiyun 4870*4882a593Smuzhiyun# check for multiple assignments 4871*4882a593Smuzhiyun if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { 4872*4882a593Smuzhiyun CHK("MULTIPLE_ASSIGNMENTS", 4873*4882a593Smuzhiyun "multiple assignments should be avoided\n" . $herecurr); 4874*4882a593Smuzhiyun } 4875*4882a593Smuzhiyun 4876*4882a593Smuzhiyun## # check for multiple declarations, allowing for a function declaration 4877*4882a593Smuzhiyun## # continuation. 4878*4882a593Smuzhiyun## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && 4879*4882a593Smuzhiyun## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { 4880*4882a593Smuzhiyun## 4881*4882a593Smuzhiyun## # Remove any bracketed sections to ensure we do not 4882*4882a593Smuzhiyun## # falsly report the parameters of functions. 4883*4882a593Smuzhiyun## my $ln = $line; 4884*4882a593Smuzhiyun## while ($ln =~ s/\([^\(\)]*\)//g) { 4885*4882a593Smuzhiyun## } 4886*4882a593Smuzhiyun## if ($ln =~ /,/) { 4887*4882a593Smuzhiyun## WARN("MULTIPLE_DECLARATION", 4888*4882a593Smuzhiyun## "declaring multiple variables together should be avoided\n" . $herecurr); 4889*4882a593Smuzhiyun## } 4890*4882a593Smuzhiyun## } 4891*4882a593Smuzhiyun 4892*4882a593Smuzhiyun#need space before brace following if, while, etc 4893*4882a593Smuzhiyun if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || 4894*4882a593Smuzhiyun $line =~ /\b(?:else|do)\{/) { 4895*4882a593Smuzhiyun if (ERROR("SPACING", 4896*4882a593Smuzhiyun "space required before the open brace '{'\n" . $herecurr) && 4897*4882a593Smuzhiyun $fix) { 4898*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/; 4899*4882a593Smuzhiyun } 4900*4882a593Smuzhiyun } 4901*4882a593Smuzhiyun 4902*4882a593Smuzhiyun## # check for blank lines before declarations 4903*4882a593Smuzhiyun## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && 4904*4882a593Smuzhiyun## $prevrawline =~ /^.\s*$/) { 4905*4882a593Smuzhiyun## WARN("SPACING", 4906*4882a593Smuzhiyun## "No blank lines before declarations\n" . $hereprev); 4907*4882a593Smuzhiyun## } 4908*4882a593Smuzhiyun## 4909*4882a593Smuzhiyun 4910*4882a593Smuzhiyun# closing brace should have a space following it when it has anything 4911*4882a593Smuzhiyun# on the line 4912*4882a593Smuzhiyun if ($line =~ /}(?!(?:,|;|\)|\}))\S/) { 4913*4882a593Smuzhiyun if (ERROR("SPACING", 4914*4882a593Smuzhiyun "space required after that close brace '}'\n" . $herecurr) && 4915*4882a593Smuzhiyun $fix) { 4916*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4917*4882a593Smuzhiyun s/}((?!(?:,|;|\)))\S)/} $1/; 4918*4882a593Smuzhiyun } 4919*4882a593Smuzhiyun } 4920*4882a593Smuzhiyun 4921*4882a593Smuzhiyun# check spacing on square brackets 4922*4882a593Smuzhiyun if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { 4923*4882a593Smuzhiyun if (ERROR("SPACING", 4924*4882a593Smuzhiyun "space prohibited after that open square bracket '['\n" . $herecurr) && 4925*4882a593Smuzhiyun $fix) { 4926*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4927*4882a593Smuzhiyun s/\[\s+/\[/; 4928*4882a593Smuzhiyun } 4929*4882a593Smuzhiyun } 4930*4882a593Smuzhiyun if ($line =~ /\s\]/) { 4931*4882a593Smuzhiyun if (ERROR("SPACING", 4932*4882a593Smuzhiyun "space prohibited before that close square bracket ']'\n" . $herecurr) && 4933*4882a593Smuzhiyun $fix) { 4934*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4935*4882a593Smuzhiyun s/\s+\]/\]/; 4936*4882a593Smuzhiyun } 4937*4882a593Smuzhiyun } 4938*4882a593Smuzhiyun 4939*4882a593Smuzhiyun# check spacing on parentheses 4940*4882a593Smuzhiyun if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && 4941*4882a593Smuzhiyun $line !~ /for\s*\(\s+;/) { 4942*4882a593Smuzhiyun if (ERROR("SPACING", 4943*4882a593Smuzhiyun "space prohibited after that open parenthesis '('\n" . $herecurr) && 4944*4882a593Smuzhiyun $fix) { 4945*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4946*4882a593Smuzhiyun s/\(\s+/\(/; 4947*4882a593Smuzhiyun } 4948*4882a593Smuzhiyun } 4949*4882a593Smuzhiyun if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && 4950*4882a593Smuzhiyun $line !~ /for\s*\(.*;\s+\)/ && 4951*4882a593Smuzhiyun $line !~ /:\s+\)/) { 4952*4882a593Smuzhiyun if (ERROR("SPACING", 4953*4882a593Smuzhiyun "space prohibited before that close parenthesis ')'\n" . $herecurr) && 4954*4882a593Smuzhiyun $fix) { 4955*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4956*4882a593Smuzhiyun s/\s+\)/\)/; 4957*4882a593Smuzhiyun } 4958*4882a593Smuzhiyun } 4959*4882a593Smuzhiyun 4960*4882a593Smuzhiyun# check unnecessary parentheses around addressof/dereference single $Lvals 4961*4882a593Smuzhiyun# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar 4962*4882a593Smuzhiyun 4963*4882a593Smuzhiyun while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { 4964*4882a593Smuzhiyun my $var = $1; 4965*4882a593Smuzhiyun if (CHK("UNNECESSARY_PARENTHESES", 4966*4882a593Smuzhiyun "Unnecessary parentheses around $var\n" . $herecurr) && 4967*4882a593Smuzhiyun $fix) { 4968*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; 4969*4882a593Smuzhiyun } 4970*4882a593Smuzhiyun } 4971*4882a593Smuzhiyun 4972*4882a593Smuzhiyun# check for unnecessary parentheses around function pointer uses 4973*4882a593Smuzhiyun# ie: (foo->bar)(); should be foo->bar(); 4974*4882a593Smuzhiyun# but not "if (foo->bar) (" to avoid some false positives 4975*4882a593Smuzhiyun if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { 4976*4882a593Smuzhiyun my $var = $2; 4977*4882a593Smuzhiyun if (CHK("UNNECESSARY_PARENTHESES", 4978*4882a593Smuzhiyun "Unnecessary parentheses around function pointer $var\n" . $herecurr) && 4979*4882a593Smuzhiyun $fix) { 4980*4882a593Smuzhiyun my $var2 = deparenthesize($var); 4981*4882a593Smuzhiyun $var2 =~ s/\s//g; 4982*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; 4983*4882a593Smuzhiyun } 4984*4882a593Smuzhiyun } 4985*4882a593Smuzhiyun 4986*4882a593Smuzhiyun# check for unnecessary parentheses around comparisons in if uses 4987*4882a593Smuzhiyun# when !drivers/staging or command-line uses --strict 4988*4882a593Smuzhiyun if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) && 4989*4882a593Smuzhiyun $perl_version_ok && defined($stat) && 4990*4882a593Smuzhiyun $stat =~ /(^.\s*if\s*($balanced_parens))/) { 4991*4882a593Smuzhiyun my $if_stat = $1; 4992*4882a593Smuzhiyun my $test = substr($2, 1, -1); 4993*4882a593Smuzhiyun my $herectx; 4994*4882a593Smuzhiyun while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) { 4995*4882a593Smuzhiyun my $match = $1; 4996*4882a593Smuzhiyun # avoid parentheses around potential macro args 4997*4882a593Smuzhiyun next if ($match =~ /^\s*\w+\s*$/); 4998*4882a593Smuzhiyun if (!defined($herectx)) { 4999*4882a593Smuzhiyun $herectx = $here . "\n"; 5000*4882a593Smuzhiyun my $cnt = statement_rawlines($if_stat); 5001*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 5002*4882a593Smuzhiyun my $rl = raw_line($linenr, $n); 5003*4882a593Smuzhiyun $herectx .= $rl . "\n"; 5004*4882a593Smuzhiyun last if $rl =~ /^[ \+].*\{/; 5005*4882a593Smuzhiyun } 5006*4882a593Smuzhiyun } 5007*4882a593Smuzhiyun CHK("UNNECESSARY_PARENTHESES", 5008*4882a593Smuzhiyun "Unnecessary parentheses around '$match'\n" . $herectx); 5009*4882a593Smuzhiyun } 5010*4882a593Smuzhiyun } 5011*4882a593Smuzhiyun 5012*4882a593Smuzhiyun#goto labels aren't indented, allow a single space however 5013*4882a593Smuzhiyun if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and 5014*4882a593Smuzhiyun !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { 5015*4882a593Smuzhiyun if (WARN("INDENTED_LABEL", 5016*4882a593Smuzhiyun "labels should not be indented\n" . $herecurr) && 5017*4882a593Smuzhiyun $fix) { 5018*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 5019*4882a593Smuzhiyun s/^(.)\s+/$1/; 5020*4882a593Smuzhiyun } 5021*4882a593Smuzhiyun } 5022*4882a593Smuzhiyun 5023*4882a593Smuzhiyun# check if a statement with a comma should be two statements like: 5024*4882a593Smuzhiyun# foo = bar(), /* comma should be semicolon */ 5025*4882a593Smuzhiyun# bar = baz(); 5026*4882a593Smuzhiyun if (defined($stat) && 5027*4882a593Smuzhiyun $stat =~ /^\+\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*,\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*;\s*$/) { 5028*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 5029*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 5030*4882a593Smuzhiyun WARN("SUSPECT_COMMA_SEMICOLON", 5031*4882a593Smuzhiyun "Possible comma where semicolon could be used\n" . $herectx); 5032*4882a593Smuzhiyun } 5033*4882a593Smuzhiyun 5034*4882a593Smuzhiyun# return is not a function 5035*4882a593Smuzhiyun if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { 5036*4882a593Smuzhiyun my $spacing = $1; 5037*4882a593Smuzhiyun if ($perl_version_ok && 5038*4882a593Smuzhiyun $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { 5039*4882a593Smuzhiyun my $value = $1; 5040*4882a593Smuzhiyun $value = deparenthesize($value); 5041*4882a593Smuzhiyun if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { 5042*4882a593Smuzhiyun ERROR("RETURN_PARENTHESES", 5043*4882a593Smuzhiyun "return is not a function, parentheses are not required\n" . $herecurr); 5044*4882a593Smuzhiyun } 5045*4882a593Smuzhiyun } elsif ($spacing !~ /\s+/) { 5046*4882a593Smuzhiyun ERROR("SPACING", 5047*4882a593Smuzhiyun "space required before the open parenthesis '('\n" . $herecurr); 5048*4882a593Smuzhiyun } 5049*4882a593Smuzhiyun } 5050*4882a593Smuzhiyun 5051*4882a593Smuzhiyun# unnecessary return in a void function 5052*4882a593Smuzhiyun# at end-of-function, with the previous line a single leading tab, then return; 5053*4882a593Smuzhiyun# and the line before that not a goto label target like "out:" 5054*4882a593Smuzhiyun if ($sline =~ /^[ \+]}\s*$/ && 5055*4882a593Smuzhiyun $prevline =~ /^\+\treturn\s*;\s*$/ && 5056*4882a593Smuzhiyun $linenr >= 3 && 5057*4882a593Smuzhiyun $lines[$linenr - 3] =~ /^[ +]/ && 5058*4882a593Smuzhiyun $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { 5059*4882a593Smuzhiyun WARN("RETURN_VOID", 5060*4882a593Smuzhiyun "void function return statements are not generally useful\n" . $hereprev); 5061*4882a593Smuzhiyun } 5062*4882a593Smuzhiyun 5063*4882a593Smuzhiyun# if statements using unnecessary parentheses - ie: if ((foo == bar)) 5064*4882a593Smuzhiyun if ($perl_version_ok && 5065*4882a593Smuzhiyun $line =~ /\bif\s*((?:\(\s*){2,})/) { 5066*4882a593Smuzhiyun my $openparens = $1; 5067*4882a593Smuzhiyun my $count = $openparens =~ tr@\(@\(@; 5068*4882a593Smuzhiyun my $msg = ""; 5069*4882a593Smuzhiyun if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { 5070*4882a593Smuzhiyun my $comp = $4; #Not $1 because of $LvalOrFunc 5071*4882a593Smuzhiyun $msg = " - maybe == should be = ?" if ($comp eq "=="); 5072*4882a593Smuzhiyun WARN("UNNECESSARY_PARENTHESES", 5073*4882a593Smuzhiyun "Unnecessary parentheses$msg\n" . $herecurr); 5074*4882a593Smuzhiyun } 5075*4882a593Smuzhiyun } 5076*4882a593Smuzhiyun 5077*4882a593Smuzhiyun# comparisons with a constant or upper case identifier on the left 5078*4882a593Smuzhiyun# avoid cases like "foo + BAR < baz" 5079*4882a593Smuzhiyun# only fix matches surrounded by parentheses to avoid incorrect 5080*4882a593Smuzhiyun# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" 5081*4882a593Smuzhiyun if ($perl_version_ok && 5082*4882a593Smuzhiyun $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { 5083*4882a593Smuzhiyun my $lead = $1; 5084*4882a593Smuzhiyun my $const = $2; 5085*4882a593Smuzhiyun my $comp = $3; 5086*4882a593Smuzhiyun my $to = $4; 5087*4882a593Smuzhiyun my $newcomp = $comp; 5088*4882a593Smuzhiyun if ($lead !~ /(?:$Operators|\.)\s*$/ && 5089*4882a593Smuzhiyun $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && 5090*4882a593Smuzhiyun WARN("CONSTANT_COMPARISON", 5091*4882a593Smuzhiyun "Comparisons should place the constant on the right side of the test\n" . $herecurr) && 5092*4882a593Smuzhiyun $fix) { 5093*4882a593Smuzhiyun if ($comp eq "<") { 5094*4882a593Smuzhiyun $newcomp = ">"; 5095*4882a593Smuzhiyun } elsif ($comp eq "<=") { 5096*4882a593Smuzhiyun $newcomp = ">="; 5097*4882a593Smuzhiyun } elsif ($comp eq ">") { 5098*4882a593Smuzhiyun $newcomp = "<"; 5099*4882a593Smuzhiyun } elsif ($comp eq ">=") { 5100*4882a593Smuzhiyun $newcomp = "<="; 5101*4882a593Smuzhiyun } 5102*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; 5103*4882a593Smuzhiyun } 5104*4882a593Smuzhiyun } 5105*4882a593Smuzhiyun 5106*4882a593Smuzhiyun# Return of what appears to be an errno should normally be negative 5107*4882a593Smuzhiyun if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { 5108*4882a593Smuzhiyun my $name = $1; 5109*4882a593Smuzhiyun if ($name ne 'EOF' && $name ne 'ERROR') { 5110*4882a593Smuzhiyun WARN("USE_NEGATIVE_ERRNO", 5111*4882a593Smuzhiyun "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); 5112*4882a593Smuzhiyun } 5113*4882a593Smuzhiyun } 5114*4882a593Smuzhiyun 5115*4882a593Smuzhiyun# Need a space before open parenthesis after if, while etc 5116*4882a593Smuzhiyun if ($line =~ /\b(if|while|for|switch)\(/) { 5117*4882a593Smuzhiyun if (ERROR("SPACING", 5118*4882a593Smuzhiyun "space required before the open parenthesis '('\n" . $herecurr) && 5119*4882a593Smuzhiyun $fix) { 5120*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 5121*4882a593Smuzhiyun s/\b(if|while|for|switch)\(/$1 \(/; 5122*4882a593Smuzhiyun } 5123*4882a593Smuzhiyun } 5124*4882a593Smuzhiyun 5125*4882a593Smuzhiyun# Check for illegal assignment in if conditional -- and check for trailing 5126*4882a593Smuzhiyun# statements after the conditional. 5127*4882a593Smuzhiyun if ($line =~ /do\s*(?!{)/) { 5128*4882a593Smuzhiyun ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 5129*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0) 5130*4882a593Smuzhiyun if (!defined $stat); 5131*4882a593Smuzhiyun my ($stat_next) = ctx_statement_block($line_nr_next, 5132*4882a593Smuzhiyun $remain_next, $off_next); 5133*4882a593Smuzhiyun $stat_next =~ s/\n./\n /g; 5134*4882a593Smuzhiyun ##print "stat<$stat> stat_next<$stat_next>\n"; 5135*4882a593Smuzhiyun 5136*4882a593Smuzhiyun if ($stat_next =~ /^\s*while\b/) { 5137*4882a593Smuzhiyun # If the statement carries leading newlines, 5138*4882a593Smuzhiyun # then count those as offsets. 5139*4882a593Smuzhiyun my ($whitespace) = 5140*4882a593Smuzhiyun ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); 5141*4882a593Smuzhiyun my $offset = 5142*4882a593Smuzhiyun statement_rawlines($whitespace) - 1; 5143*4882a593Smuzhiyun 5144*4882a593Smuzhiyun $suppress_whiletrailers{$line_nr_next + 5145*4882a593Smuzhiyun $offset} = 1; 5146*4882a593Smuzhiyun } 5147*4882a593Smuzhiyun } 5148*4882a593Smuzhiyun if (!defined $suppress_whiletrailers{$linenr} && 5149*4882a593Smuzhiyun defined($stat) && defined($cond) && 5150*4882a593Smuzhiyun $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { 5151*4882a593Smuzhiyun my ($s, $c) = ($stat, $cond); 5152*4882a593Smuzhiyun 5153*4882a593Smuzhiyun if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { 5154*4882a593Smuzhiyun if (ERROR("ASSIGN_IN_IF", 5155*4882a593Smuzhiyun "do not use assignment in if condition\n" . $herecurr) && 5156*4882a593Smuzhiyun $fix && $perl_version_ok) { 5157*4882a593Smuzhiyun if ($rawline =~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=\s*$LvalOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) { 5158*4882a593Smuzhiyun my $space = $1; 5159*4882a593Smuzhiyun my $not = $2; 5160*4882a593Smuzhiyun my $statement = $3; 5161*4882a593Smuzhiyun my $assigned = $4; 5162*4882a593Smuzhiyun my $test = $8; 5163*4882a593Smuzhiyun my $against = $9; 5164*4882a593Smuzhiyun my $brace = $15; 5165*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5166*4882a593Smuzhiyun fix_insert_line($fixlinenr, "$space$statement;"); 5167*4882a593Smuzhiyun my $newline = "${space}if ("; 5168*4882a593Smuzhiyun $newline .= '!' if defined($not); 5169*4882a593Smuzhiyun $newline .= '(' if (defined $not && defined($test) && defined($against)); 5170*4882a593Smuzhiyun $newline .= "$assigned"; 5171*4882a593Smuzhiyun $newline .= " $test $against" if (defined($test) && defined($against)); 5172*4882a593Smuzhiyun $newline .= ')' if (defined $not && defined($test) && defined($against)); 5173*4882a593Smuzhiyun $newline .= ')'; 5174*4882a593Smuzhiyun $newline .= " {" if (defined($brace)); 5175*4882a593Smuzhiyun fix_insert_line($fixlinenr + 1, $newline); 5176*4882a593Smuzhiyun } 5177*4882a593Smuzhiyun } 5178*4882a593Smuzhiyun } 5179*4882a593Smuzhiyun 5180*4882a593Smuzhiyun # Find out what is on the end of the line after the 5181*4882a593Smuzhiyun # conditional. 5182*4882a593Smuzhiyun substr($s, 0, length($c), ''); 5183*4882a593Smuzhiyun $s =~ s/\n.*//g; 5184*4882a593Smuzhiyun $s =~ s/$;//g; # Remove any comments 5185*4882a593Smuzhiyun if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && 5186*4882a593Smuzhiyun $c !~ /}\s*while\s*/) 5187*4882a593Smuzhiyun { 5188*4882a593Smuzhiyun # Find out how long the conditional actually is. 5189*4882a593Smuzhiyun my @newlines = ($c =~ /\n/gs); 5190*4882a593Smuzhiyun my $cond_lines = 1 + $#newlines; 5191*4882a593Smuzhiyun my $stat_real = ''; 5192*4882a593Smuzhiyun 5193*4882a593Smuzhiyun $stat_real = raw_line($linenr, $cond_lines) 5194*4882a593Smuzhiyun . "\n" if ($cond_lines); 5195*4882a593Smuzhiyun if (defined($stat_real) && $cond_lines > 1) { 5196*4882a593Smuzhiyun $stat_real = "[...]\n$stat_real"; 5197*4882a593Smuzhiyun } 5198*4882a593Smuzhiyun 5199*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 5200*4882a593Smuzhiyun "trailing statements should be on next line\n" . $herecurr . $stat_real); 5201*4882a593Smuzhiyun } 5202*4882a593Smuzhiyun } 5203*4882a593Smuzhiyun 5204*4882a593Smuzhiyun# Check for bitwise tests written as boolean 5205*4882a593Smuzhiyun if ($line =~ / 5206*4882a593Smuzhiyun (?: 5207*4882a593Smuzhiyun (?:\[|\(|\&\&|\|\|) 5208*4882a593Smuzhiyun \s*0[xX][0-9]+\s* 5209*4882a593Smuzhiyun (?:\&\&|\|\|) 5210*4882a593Smuzhiyun | 5211*4882a593Smuzhiyun (?:\&\&|\|\|) 5212*4882a593Smuzhiyun \s*0[xX][0-9]+\s* 5213*4882a593Smuzhiyun (?:\&\&|\|\||\)|\]) 5214*4882a593Smuzhiyun )/x) 5215*4882a593Smuzhiyun { 5216*4882a593Smuzhiyun WARN("HEXADECIMAL_BOOLEAN_TEST", 5217*4882a593Smuzhiyun "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); 5218*4882a593Smuzhiyun } 5219*4882a593Smuzhiyun 5220*4882a593Smuzhiyun# if and else should not have general statements after it 5221*4882a593Smuzhiyun if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { 5222*4882a593Smuzhiyun my $s = $1; 5223*4882a593Smuzhiyun $s =~ s/$;//g; # Remove any comments 5224*4882a593Smuzhiyun if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { 5225*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 5226*4882a593Smuzhiyun "trailing statements should be on next line\n" . $herecurr); 5227*4882a593Smuzhiyun } 5228*4882a593Smuzhiyun } 5229*4882a593Smuzhiyun# if should not continue a brace 5230*4882a593Smuzhiyun if ($line =~ /}\s*if\b/) { 5231*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 5232*4882a593Smuzhiyun "trailing statements should be on next line (or did you mean 'else if'?)\n" . 5233*4882a593Smuzhiyun $herecurr); 5234*4882a593Smuzhiyun } 5235*4882a593Smuzhiyun# case and default should not have general statements after them 5236*4882a593Smuzhiyun if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && 5237*4882a593Smuzhiyun $line !~ /\G(?: 5238*4882a593Smuzhiyun (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| 5239*4882a593Smuzhiyun \s*return\s+ 5240*4882a593Smuzhiyun )/xg) 5241*4882a593Smuzhiyun { 5242*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 5243*4882a593Smuzhiyun "trailing statements should be on next line\n" . $herecurr); 5244*4882a593Smuzhiyun } 5245*4882a593Smuzhiyun 5246*4882a593Smuzhiyun # Check for }<nl>else {, these must be at the same 5247*4882a593Smuzhiyun # indent level to be relevant to each other. 5248*4882a593Smuzhiyun if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && 5249*4882a593Smuzhiyun $previndent == $indent) { 5250*4882a593Smuzhiyun if (ERROR("ELSE_AFTER_BRACE", 5251*4882a593Smuzhiyun "else should follow close brace '}'\n" . $hereprev) && 5252*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 5253*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5254*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5255*4882a593Smuzhiyun my $fixedline = $prevrawline; 5256*4882a593Smuzhiyun $fixedline =~ s/}\s*$//; 5257*4882a593Smuzhiyun if ($fixedline !~ /^\+\s*$/) { 5258*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 5259*4882a593Smuzhiyun } 5260*4882a593Smuzhiyun $fixedline = $rawline; 5261*4882a593Smuzhiyun $fixedline =~ s/^(.\s*)else/$1} else/; 5262*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 5263*4882a593Smuzhiyun } 5264*4882a593Smuzhiyun } 5265*4882a593Smuzhiyun 5266*4882a593Smuzhiyun if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && 5267*4882a593Smuzhiyun $previndent == $indent) { 5268*4882a593Smuzhiyun my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); 5269*4882a593Smuzhiyun 5270*4882a593Smuzhiyun # Find out what is on the end of the line after the 5271*4882a593Smuzhiyun # conditional. 5272*4882a593Smuzhiyun substr($s, 0, length($c), ''); 5273*4882a593Smuzhiyun $s =~ s/\n.*//g; 5274*4882a593Smuzhiyun 5275*4882a593Smuzhiyun if ($s =~ /^\s*;/) { 5276*4882a593Smuzhiyun if (ERROR("WHILE_AFTER_BRACE", 5277*4882a593Smuzhiyun "while should follow close brace '}'\n" . $hereprev) && 5278*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 5279*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5280*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5281*4882a593Smuzhiyun my $fixedline = $prevrawline; 5282*4882a593Smuzhiyun my $trailing = $rawline; 5283*4882a593Smuzhiyun $trailing =~ s/^\+//; 5284*4882a593Smuzhiyun $trailing = trim($trailing); 5285*4882a593Smuzhiyun $fixedline =~ s/}\s*$/} $trailing/; 5286*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 5287*4882a593Smuzhiyun } 5288*4882a593Smuzhiyun } 5289*4882a593Smuzhiyun } 5290*4882a593Smuzhiyun 5291*4882a593Smuzhiyun#Specific variable tests 5292*4882a593Smuzhiyun while ($line =~ m{($Constant|$Lval)}g) { 5293*4882a593Smuzhiyun my $var = $1; 5294*4882a593Smuzhiyun 5295*4882a593Smuzhiyun#CamelCase 5296*4882a593Smuzhiyun if ($var !~ /^$Constant$/ && 5297*4882a593Smuzhiyun $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && 5298*4882a593Smuzhiyun#Ignore Page<foo> variants 5299*4882a593Smuzhiyun $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && 5300*4882a593Smuzhiyun#Ignore SI style variants like nS, mV and dB 5301*4882a593Smuzhiyun#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE) 5302*4882a593Smuzhiyun $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ && 5303*4882a593Smuzhiyun#Ignore some three character SI units explicitly, like MiB and KHz 5304*4882a593Smuzhiyun $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { 5305*4882a593Smuzhiyun while ($var =~ m{($Ident)}g) { 5306*4882a593Smuzhiyun my $word = $1; 5307*4882a593Smuzhiyun next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); 5308*4882a593Smuzhiyun if ($check) { 5309*4882a593Smuzhiyun seed_camelcase_includes(); 5310*4882a593Smuzhiyun if (!$file && !$camelcase_file_seeded) { 5311*4882a593Smuzhiyun seed_camelcase_file($realfile); 5312*4882a593Smuzhiyun $camelcase_file_seeded = 1; 5313*4882a593Smuzhiyun } 5314*4882a593Smuzhiyun } 5315*4882a593Smuzhiyun if (!defined $camelcase{$word}) { 5316*4882a593Smuzhiyun $camelcase{$word} = 1; 5317*4882a593Smuzhiyun CHK("CAMELCASE", 5318*4882a593Smuzhiyun "Avoid CamelCase: <$word>\n" . $herecurr); 5319*4882a593Smuzhiyun } 5320*4882a593Smuzhiyun } 5321*4882a593Smuzhiyun } 5322*4882a593Smuzhiyun } 5323*4882a593Smuzhiyun 5324*4882a593Smuzhiyun#no spaces allowed after \ in define 5325*4882a593Smuzhiyun if ($line =~ /\#\s*define.*\\\s+$/) { 5326*4882a593Smuzhiyun if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", 5327*4882a593Smuzhiyun "Whitespace after \\ makes next lines useless\n" . $herecurr) && 5328*4882a593Smuzhiyun $fix) { 5329*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s+$//; 5330*4882a593Smuzhiyun } 5331*4882a593Smuzhiyun } 5332*4882a593Smuzhiyun 5333*4882a593Smuzhiyun# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes 5334*4882a593Smuzhiyun# itself <asm/foo.h> (uses RAW line) 5335*4882a593Smuzhiyun if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { 5336*4882a593Smuzhiyun my $file = "$1.h"; 5337*4882a593Smuzhiyun my $checkfile = "include/linux/$file"; 5338*4882a593Smuzhiyun if (-f "$root/$checkfile" && 5339*4882a593Smuzhiyun $realfile ne $checkfile && 5340*4882a593Smuzhiyun $1 !~ /$allowed_asm_includes/) 5341*4882a593Smuzhiyun { 5342*4882a593Smuzhiyun my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; 5343*4882a593Smuzhiyun if ($asminclude > 0) { 5344*4882a593Smuzhiyun if ($realfile =~ m{^arch/}) { 5345*4882a593Smuzhiyun CHK("ARCH_INCLUDE_LINUX", 5346*4882a593Smuzhiyun "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); 5347*4882a593Smuzhiyun } else { 5348*4882a593Smuzhiyun WARN("INCLUDE_LINUX", 5349*4882a593Smuzhiyun "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); 5350*4882a593Smuzhiyun } 5351*4882a593Smuzhiyun } 5352*4882a593Smuzhiyun } 5353*4882a593Smuzhiyun } 5354*4882a593Smuzhiyun 5355*4882a593Smuzhiyun# multi-statement macros should be enclosed in a do while loop, grab the 5356*4882a593Smuzhiyun# first statement and ensure its the whole macro if its not enclosed 5357*4882a593Smuzhiyun# in a known good container 5358*4882a593Smuzhiyun if ($realfile !~ m@/vmlinux.lds.h$@ && 5359*4882a593Smuzhiyun $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { 5360*4882a593Smuzhiyun my $ln = $linenr; 5361*4882a593Smuzhiyun my $cnt = $realcnt; 5362*4882a593Smuzhiyun my ($off, $dstat, $dcond, $rest); 5363*4882a593Smuzhiyun my $ctx = ''; 5364*4882a593Smuzhiyun my $has_flow_statement = 0; 5365*4882a593Smuzhiyun my $has_arg_concat = 0; 5366*4882a593Smuzhiyun ($dstat, $dcond, $ln, $cnt, $off) = 5367*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0); 5368*4882a593Smuzhiyun $ctx = $dstat; 5369*4882a593Smuzhiyun #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; 5370*4882a593Smuzhiyun #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; 5371*4882a593Smuzhiyun 5372*4882a593Smuzhiyun $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); 5373*4882a593Smuzhiyun $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); 5374*4882a593Smuzhiyun 5375*4882a593Smuzhiyun $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//; 5376*4882a593Smuzhiyun my $define_args = $1; 5377*4882a593Smuzhiyun my $define_stmt = $dstat; 5378*4882a593Smuzhiyun my @def_args = (); 5379*4882a593Smuzhiyun 5380*4882a593Smuzhiyun if (defined $define_args && $define_args ne "") { 5381*4882a593Smuzhiyun $define_args = substr($define_args, 1, length($define_args) - 2); 5382*4882a593Smuzhiyun $define_args =~ s/\s*//g; 5383*4882a593Smuzhiyun $define_args =~ s/\\\+?//g; 5384*4882a593Smuzhiyun @def_args = split(",", $define_args); 5385*4882a593Smuzhiyun } 5386*4882a593Smuzhiyun 5387*4882a593Smuzhiyun $dstat =~ s/$;//g; 5388*4882a593Smuzhiyun $dstat =~ s/\\\n.//g; 5389*4882a593Smuzhiyun $dstat =~ s/^\s*//s; 5390*4882a593Smuzhiyun $dstat =~ s/\s*$//s; 5391*4882a593Smuzhiyun 5392*4882a593Smuzhiyun # Flatten any parentheses and braces 5393*4882a593Smuzhiyun while ($dstat =~ s/\([^\(\)]*\)/1u/ || 5394*4882a593Smuzhiyun $dstat =~ s/\{[^\{\}]*\}/1u/ || 5395*4882a593Smuzhiyun $dstat =~ s/.\[[^\[\]]*\]/1u/) 5396*4882a593Smuzhiyun { 5397*4882a593Smuzhiyun } 5398*4882a593Smuzhiyun 5399*4882a593Smuzhiyun # Flatten any obvious string concatenation. 5400*4882a593Smuzhiyun while ($dstat =~ s/($String)\s*$Ident/$1/ || 5401*4882a593Smuzhiyun $dstat =~ s/$Ident\s*($String)/$1/) 5402*4882a593Smuzhiyun { 5403*4882a593Smuzhiyun } 5404*4882a593Smuzhiyun 5405*4882a593Smuzhiyun # Make asm volatile uses seem like a generic function 5406*4882a593Smuzhiyun $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; 5407*4882a593Smuzhiyun 5408*4882a593Smuzhiyun my $exceptions = qr{ 5409*4882a593Smuzhiyun $Declare| 5410*4882a593Smuzhiyun module_param_named| 5411*4882a593Smuzhiyun MODULE_PARM_DESC| 5412*4882a593Smuzhiyun DECLARE_PER_CPU| 5413*4882a593Smuzhiyun DEFINE_PER_CPU| 5414*4882a593Smuzhiyun __typeof__\(| 5415*4882a593Smuzhiyun union| 5416*4882a593Smuzhiyun struct| 5417*4882a593Smuzhiyun \.$Ident\s*=\s*| 5418*4882a593Smuzhiyun ^\"|\"$| 5419*4882a593Smuzhiyun ^\[ 5420*4882a593Smuzhiyun }x; 5421*4882a593Smuzhiyun #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; 5422*4882a593Smuzhiyun 5423*4882a593Smuzhiyun $ctx =~ s/\n*$//; 5424*4882a593Smuzhiyun my $stmt_cnt = statement_rawlines($ctx); 5425*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $stmt_cnt, $here); 5426*4882a593Smuzhiyun 5427*4882a593Smuzhiyun if ($dstat ne '' && 5428*4882a593Smuzhiyun $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), 5429*4882a593Smuzhiyun $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); 5430*4882a593Smuzhiyun $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz 5431*4882a593Smuzhiyun $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants 5432*4882a593Smuzhiyun $dstat !~ /$exceptions/ && 5433*4882a593Smuzhiyun $dstat !~ /^\.$Ident\s*=/ && # .foo = 5434*4882a593Smuzhiyun $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo 5435*4882a593Smuzhiyun $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) 5436*4882a593Smuzhiyun $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...} 5437*4882a593Smuzhiyun $dstat !~ /^for\s*$Constant$/ && # for (...) 5438*4882a593Smuzhiyun $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() 5439*4882a593Smuzhiyun $dstat !~ /^do\s*{/ && # do {... 5440*4882a593Smuzhiyun $dstat !~ /^\(\{/ && # ({... 5441*4882a593Smuzhiyun $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) 5442*4882a593Smuzhiyun { 5443*4882a593Smuzhiyun if ($dstat =~ /^\s*if\b/) { 5444*4882a593Smuzhiyun ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", 5445*4882a593Smuzhiyun "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx"); 5446*4882a593Smuzhiyun } elsif ($dstat =~ /;/) { 5447*4882a593Smuzhiyun ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", 5448*4882a593Smuzhiyun "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); 5449*4882a593Smuzhiyun } else { 5450*4882a593Smuzhiyun ERROR("COMPLEX_MACRO", 5451*4882a593Smuzhiyun "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); 5452*4882a593Smuzhiyun } 5453*4882a593Smuzhiyun 5454*4882a593Smuzhiyun } 5455*4882a593Smuzhiyun 5456*4882a593Smuzhiyun # Make $define_stmt single line, comment-free, etc 5457*4882a593Smuzhiyun my @stmt_array = split('\n', $define_stmt); 5458*4882a593Smuzhiyun my $first = 1; 5459*4882a593Smuzhiyun $define_stmt = ""; 5460*4882a593Smuzhiyun foreach my $l (@stmt_array) { 5461*4882a593Smuzhiyun $l =~ s/\\$//; 5462*4882a593Smuzhiyun if ($first) { 5463*4882a593Smuzhiyun $define_stmt = $l; 5464*4882a593Smuzhiyun $first = 0; 5465*4882a593Smuzhiyun } elsif ($l =~ /^[\+ ]/) { 5466*4882a593Smuzhiyun $define_stmt .= substr($l, 1); 5467*4882a593Smuzhiyun } 5468*4882a593Smuzhiyun } 5469*4882a593Smuzhiyun $define_stmt =~ s/$;//g; 5470*4882a593Smuzhiyun $define_stmt =~ s/\s+/ /g; 5471*4882a593Smuzhiyun $define_stmt = trim($define_stmt); 5472*4882a593Smuzhiyun 5473*4882a593Smuzhiyun# check if any macro arguments are reused (ignore '...' and 'type') 5474*4882a593Smuzhiyun foreach my $arg (@def_args) { 5475*4882a593Smuzhiyun next if ($arg =~ /\.\.\./); 5476*4882a593Smuzhiyun next if ($arg =~ /^type$/i); 5477*4882a593Smuzhiyun my $tmp_stmt = $define_stmt; 5478*4882a593Smuzhiyun $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; 5479*4882a593Smuzhiyun $tmp_stmt =~ s/\#+\s*$arg\b//g; 5480*4882a593Smuzhiyun $tmp_stmt =~ s/\b$arg\s*\#\#//g; 5481*4882a593Smuzhiyun my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g; 5482*4882a593Smuzhiyun if ($use_cnt > 1) { 5483*4882a593Smuzhiyun CHK("MACRO_ARG_REUSE", 5484*4882a593Smuzhiyun "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx"); 5485*4882a593Smuzhiyun } 5486*4882a593Smuzhiyun# check if any macro arguments may have other precedence issues 5487*4882a593Smuzhiyun if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m && 5488*4882a593Smuzhiyun ((defined($1) && $1 ne ',') || 5489*4882a593Smuzhiyun (defined($2) && $2 ne ','))) { 5490*4882a593Smuzhiyun CHK("MACRO_ARG_PRECEDENCE", 5491*4882a593Smuzhiyun "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx"); 5492*4882a593Smuzhiyun } 5493*4882a593Smuzhiyun } 5494*4882a593Smuzhiyun 5495*4882a593Smuzhiyun# check for macros with flow control, but without ## concatenation 5496*4882a593Smuzhiyun# ## concatenation is commonly a macro that defines a function so ignore those 5497*4882a593Smuzhiyun if ($has_flow_statement && !$has_arg_concat) { 5498*4882a593Smuzhiyun my $cnt = statement_rawlines($ctx); 5499*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 5500*4882a593Smuzhiyun 5501*4882a593Smuzhiyun WARN("MACRO_WITH_FLOW_CONTROL", 5502*4882a593Smuzhiyun "Macros with flow control statements should be avoided\n" . "$herectx"); 5503*4882a593Smuzhiyun } 5504*4882a593Smuzhiyun 5505*4882a593Smuzhiyun# check for line continuations outside of #defines, preprocessor #, and asm 5506*4882a593Smuzhiyun 5507*4882a593Smuzhiyun } else { 5508*4882a593Smuzhiyun if ($prevline !~ /^..*\\$/ && 5509*4882a593Smuzhiyun $line !~ /^\+\s*\#.*\\$/ && # preprocessor 5510*4882a593Smuzhiyun $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm 5511*4882a593Smuzhiyun $line =~ /^\+.*\\$/) { 5512*4882a593Smuzhiyun WARN("LINE_CONTINUATIONS", 5513*4882a593Smuzhiyun "Avoid unnecessary line continuations\n" . $herecurr); 5514*4882a593Smuzhiyun } 5515*4882a593Smuzhiyun } 5516*4882a593Smuzhiyun 5517*4882a593Smuzhiyun# do {} while (0) macro tests: 5518*4882a593Smuzhiyun# single-statement macros do not need to be enclosed in do while (0) loop, 5519*4882a593Smuzhiyun# macro should not end with a semicolon 5520*4882a593Smuzhiyun if ($perl_version_ok && 5521*4882a593Smuzhiyun $realfile !~ m@/vmlinux.lds.h$@ && 5522*4882a593Smuzhiyun $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { 5523*4882a593Smuzhiyun my $ln = $linenr; 5524*4882a593Smuzhiyun my $cnt = $realcnt; 5525*4882a593Smuzhiyun my ($off, $dstat, $dcond, $rest); 5526*4882a593Smuzhiyun my $ctx = ''; 5527*4882a593Smuzhiyun ($dstat, $dcond, $ln, $cnt, $off) = 5528*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0); 5529*4882a593Smuzhiyun $ctx = $dstat; 5530*4882a593Smuzhiyun 5531*4882a593Smuzhiyun $dstat =~ s/\\\n.//g; 5532*4882a593Smuzhiyun $dstat =~ s/$;/ /g; 5533*4882a593Smuzhiyun 5534*4882a593Smuzhiyun if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { 5535*4882a593Smuzhiyun my $stmts = $2; 5536*4882a593Smuzhiyun my $semis = $3; 5537*4882a593Smuzhiyun 5538*4882a593Smuzhiyun $ctx =~ s/\n*$//; 5539*4882a593Smuzhiyun my $cnt = statement_rawlines($ctx); 5540*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 5541*4882a593Smuzhiyun 5542*4882a593Smuzhiyun if (($stmts =~ tr/;/;/) == 1 && 5543*4882a593Smuzhiyun $stmts !~ /^\s*(if|while|for|switch)\b/) { 5544*4882a593Smuzhiyun WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", 5545*4882a593Smuzhiyun "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); 5546*4882a593Smuzhiyun } 5547*4882a593Smuzhiyun if (defined $semis && $semis ne "") { 5548*4882a593Smuzhiyun WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", 5549*4882a593Smuzhiyun "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); 5550*4882a593Smuzhiyun } 5551*4882a593Smuzhiyun } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { 5552*4882a593Smuzhiyun $ctx =~ s/\n*$//; 5553*4882a593Smuzhiyun my $cnt = statement_rawlines($ctx); 5554*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 5555*4882a593Smuzhiyun 5556*4882a593Smuzhiyun WARN("TRAILING_SEMICOLON", 5557*4882a593Smuzhiyun "macros should not use a trailing semicolon\n" . "$herectx"); 5558*4882a593Smuzhiyun } 5559*4882a593Smuzhiyun } 5560*4882a593Smuzhiyun 5561*4882a593Smuzhiyun# check for redundant bracing round if etc 5562*4882a593Smuzhiyun if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { 5563*4882a593Smuzhiyun my ($level, $endln, @chunks) = 5564*4882a593Smuzhiyun ctx_statement_full($linenr, $realcnt, 1); 5565*4882a593Smuzhiyun #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; 5566*4882a593Smuzhiyun #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; 5567*4882a593Smuzhiyun if ($#chunks > 0 && $level == 0) { 5568*4882a593Smuzhiyun my @allowed = (); 5569*4882a593Smuzhiyun my $allow = 0; 5570*4882a593Smuzhiyun my $seen = 0; 5571*4882a593Smuzhiyun my $herectx = $here . "\n"; 5572*4882a593Smuzhiyun my $ln = $linenr - 1; 5573*4882a593Smuzhiyun for my $chunk (@chunks) { 5574*4882a593Smuzhiyun my ($cond, $block) = @{$chunk}; 5575*4882a593Smuzhiyun 5576*4882a593Smuzhiyun # If the condition carries leading newlines, then count those as offsets. 5577*4882a593Smuzhiyun my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); 5578*4882a593Smuzhiyun my $offset = statement_rawlines($whitespace) - 1; 5579*4882a593Smuzhiyun 5580*4882a593Smuzhiyun $allowed[$allow] = 0; 5581*4882a593Smuzhiyun #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; 5582*4882a593Smuzhiyun 5583*4882a593Smuzhiyun # We have looked at and allowed this specific line. 5584*4882a593Smuzhiyun $suppress_ifbraces{$ln + $offset} = 1; 5585*4882a593Smuzhiyun 5586*4882a593Smuzhiyun $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; 5587*4882a593Smuzhiyun $ln += statement_rawlines($block) - 1; 5588*4882a593Smuzhiyun 5589*4882a593Smuzhiyun substr($block, 0, length($cond), ''); 5590*4882a593Smuzhiyun 5591*4882a593Smuzhiyun $seen++ if ($block =~ /^\s*{/); 5592*4882a593Smuzhiyun 5593*4882a593Smuzhiyun #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; 5594*4882a593Smuzhiyun if (statement_lines($cond) > 1) { 5595*4882a593Smuzhiyun #print "APW: ALLOWED: cond<$cond>\n"; 5596*4882a593Smuzhiyun $allowed[$allow] = 1; 5597*4882a593Smuzhiyun } 5598*4882a593Smuzhiyun if ($block =~/\b(?:if|for|while)\b/) { 5599*4882a593Smuzhiyun #print "APW: ALLOWED: block<$block>\n"; 5600*4882a593Smuzhiyun $allowed[$allow] = 1; 5601*4882a593Smuzhiyun } 5602*4882a593Smuzhiyun if (statement_block_size($block) > 1) { 5603*4882a593Smuzhiyun #print "APW: ALLOWED: lines block<$block>\n"; 5604*4882a593Smuzhiyun $allowed[$allow] = 1; 5605*4882a593Smuzhiyun } 5606*4882a593Smuzhiyun $allow++; 5607*4882a593Smuzhiyun } 5608*4882a593Smuzhiyun if ($seen) { 5609*4882a593Smuzhiyun my $sum_allowed = 0; 5610*4882a593Smuzhiyun foreach (@allowed) { 5611*4882a593Smuzhiyun $sum_allowed += $_; 5612*4882a593Smuzhiyun } 5613*4882a593Smuzhiyun if ($sum_allowed == 0) { 5614*4882a593Smuzhiyun WARN("BRACES", 5615*4882a593Smuzhiyun "braces {} are not necessary for any arm of this statement\n" . $herectx); 5616*4882a593Smuzhiyun } elsif ($sum_allowed != $allow && 5617*4882a593Smuzhiyun $seen != $allow) { 5618*4882a593Smuzhiyun CHK("BRACES", 5619*4882a593Smuzhiyun "braces {} should be used on all arms of this statement\n" . $herectx); 5620*4882a593Smuzhiyun } 5621*4882a593Smuzhiyun } 5622*4882a593Smuzhiyun } 5623*4882a593Smuzhiyun } 5624*4882a593Smuzhiyun if (!defined $suppress_ifbraces{$linenr - 1} && 5625*4882a593Smuzhiyun $line =~ /\b(if|while|for|else)\b/) { 5626*4882a593Smuzhiyun my $allowed = 0; 5627*4882a593Smuzhiyun 5628*4882a593Smuzhiyun # Check the pre-context. 5629*4882a593Smuzhiyun if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { 5630*4882a593Smuzhiyun #print "APW: ALLOWED: pre<$1>\n"; 5631*4882a593Smuzhiyun $allowed = 1; 5632*4882a593Smuzhiyun } 5633*4882a593Smuzhiyun 5634*4882a593Smuzhiyun my ($level, $endln, @chunks) = 5635*4882a593Smuzhiyun ctx_statement_full($linenr, $realcnt, $-[0]); 5636*4882a593Smuzhiyun 5637*4882a593Smuzhiyun # Check the condition. 5638*4882a593Smuzhiyun my ($cond, $block) = @{$chunks[0]}; 5639*4882a593Smuzhiyun #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; 5640*4882a593Smuzhiyun if (defined $cond) { 5641*4882a593Smuzhiyun substr($block, 0, length($cond), ''); 5642*4882a593Smuzhiyun } 5643*4882a593Smuzhiyun if (statement_lines($cond) > 1) { 5644*4882a593Smuzhiyun #print "APW: ALLOWED: cond<$cond>\n"; 5645*4882a593Smuzhiyun $allowed = 1; 5646*4882a593Smuzhiyun } 5647*4882a593Smuzhiyun if ($block =~/\b(?:if|for|while)\b/) { 5648*4882a593Smuzhiyun #print "APW: ALLOWED: block<$block>\n"; 5649*4882a593Smuzhiyun $allowed = 1; 5650*4882a593Smuzhiyun } 5651*4882a593Smuzhiyun if (statement_block_size($block) > 1) { 5652*4882a593Smuzhiyun #print "APW: ALLOWED: lines block<$block>\n"; 5653*4882a593Smuzhiyun $allowed = 1; 5654*4882a593Smuzhiyun } 5655*4882a593Smuzhiyun # Check the post-context. 5656*4882a593Smuzhiyun if (defined $chunks[1]) { 5657*4882a593Smuzhiyun my ($cond, $block) = @{$chunks[1]}; 5658*4882a593Smuzhiyun if (defined $cond) { 5659*4882a593Smuzhiyun substr($block, 0, length($cond), ''); 5660*4882a593Smuzhiyun } 5661*4882a593Smuzhiyun if ($block =~ /^\s*\{/) { 5662*4882a593Smuzhiyun #print "APW: ALLOWED: chunk-1 block<$block>\n"; 5663*4882a593Smuzhiyun $allowed = 1; 5664*4882a593Smuzhiyun } 5665*4882a593Smuzhiyun } 5666*4882a593Smuzhiyun if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { 5667*4882a593Smuzhiyun my $cnt = statement_rawlines($block); 5668*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 5669*4882a593Smuzhiyun 5670*4882a593Smuzhiyun WARN("BRACES", 5671*4882a593Smuzhiyun "braces {} are not necessary for single statement blocks\n" . $herectx); 5672*4882a593Smuzhiyun } 5673*4882a593Smuzhiyun } 5674*4882a593Smuzhiyun 5675*4882a593Smuzhiyun# check for single line unbalanced braces 5676*4882a593Smuzhiyun if ($sline =~ /^.\s*\}\s*else\s*$/ || 5677*4882a593Smuzhiyun $sline =~ /^.\s*else\s*\{\s*$/) { 5678*4882a593Smuzhiyun CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr); 5679*4882a593Smuzhiyun } 5680*4882a593Smuzhiyun 5681*4882a593Smuzhiyun# check for unnecessary blank lines around braces 5682*4882a593Smuzhiyun if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { 5683*4882a593Smuzhiyun if (CHK("BRACES", 5684*4882a593Smuzhiyun "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && 5685*4882a593Smuzhiyun $fix && $prevrawline =~ /^\+/) { 5686*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5687*4882a593Smuzhiyun } 5688*4882a593Smuzhiyun } 5689*4882a593Smuzhiyun if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { 5690*4882a593Smuzhiyun if (CHK("BRACES", 5691*4882a593Smuzhiyun "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && 5692*4882a593Smuzhiyun $fix) { 5693*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5694*4882a593Smuzhiyun } 5695*4882a593Smuzhiyun } 5696*4882a593Smuzhiyun 5697*4882a593Smuzhiyun# no volatiles please 5698*4882a593Smuzhiyun my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; 5699*4882a593Smuzhiyun if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { 5700*4882a593Smuzhiyun WARN("VOLATILE", 5701*4882a593Smuzhiyun "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr); 5702*4882a593Smuzhiyun } 5703*4882a593Smuzhiyun 5704*4882a593Smuzhiyun# Check for user-visible strings broken across lines, which breaks the ability 5705*4882a593Smuzhiyun# to grep for the string. Make exceptions when the previous string ends in a 5706*4882a593Smuzhiyun# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' 5707*4882a593Smuzhiyun# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value 5708*4882a593Smuzhiyun if ($line =~ /^\+\s*$String/ && 5709*4882a593Smuzhiyun $prevline =~ /"\s*$/ && 5710*4882a593Smuzhiyun $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { 5711*4882a593Smuzhiyun if (WARN("SPLIT_STRING", 5712*4882a593Smuzhiyun "quoted string split across lines\n" . $hereprev) && 5713*4882a593Smuzhiyun $fix && 5714*4882a593Smuzhiyun $prevrawline =~ /^\+.*"\s*$/ && 5715*4882a593Smuzhiyun $last_coalesced_string_linenr != $linenr - 1) { 5716*4882a593Smuzhiyun my $extracted_string = get_quoted_string($line, $rawline); 5717*4882a593Smuzhiyun my $comma_close = ""; 5718*4882a593Smuzhiyun if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { 5719*4882a593Smuzhiyun $comma_close = $1; 5720*4882a593Smuzhiyun } 5721*4882a593Smuzhiyun 5722*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5723*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5724*4882a593Smuzhiyun my $fixedline = $prevrawline; 5725*4882a593Smuzhiyun $fixedline =~ s/"\s*$//; 5726*4882a593Smuzhiyun $fixedline .= substr($extracted_string, 1) . trim($comma_close); 5727*4882a593Smuzhiyun fix_insert_line($fixlinenr - 1, $fixedline); 5728*4882a593Smuzhiyun $fixedline = $rawline; 5729*4882a593Smuzhiyun $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; 5730*4882a593Smuzhiyun if ($fixedline !~ /\+\s*$/) { 5731*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 5732*4882a593Smuzhiyun } 5733*4882a593Smuzhiyun $last_coalesced_string_linenr = $linenr; 5734*4882a593Smuzhiyun } 5735*4882a593Smuzhiyun } 5736*4882a593Smuzhiyun 5737*4882a593Smuzhiyun# check for missing a space in a string concatenation 5738*4882a593Smuzhiyun if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { 5739*4882a593Smuzhiyun WARN('MISSING_SPACE', 5740*4882a593Smuzhiyun "break quoted strings at a space character\n" . $hereprev); 5741*4882a593Smuzhiyun } 5742*4882a593Smuzhiyun 5743*4882a593Smuzhiyun# check for an embedded function name in a string when the function is known 5744*4882a593Smuzhiyun# This does not work very well for -f --file checking as it depends on patch 5745*4882a593Smuzhiyun# context providing the function name or a single line form for in-file 5746*4882a593Smuzhiyun# function declarations 5747*4882a593Smuzhiyun if ($line =~ /^\+.*$String/ && 5748*4882a593Smuzhiyun defined($context_function) && 5749*4882a593Smuzhiyun get_quoted_string($line, $rawline) =~ /\b$context_function\b/ && 5750*4882a593Smuzhiyun length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) { 5751*4882a593Smuzhiyun WARN("EMBEDDED_FUNCTION_NAME", 5752*4882a593Smuzhiyun "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr); 5753*4882a593Smuzhiyun } 5754*4882a593Smuzhiyun 5755*4882a593Smuzhiyun# check for spaces before a quoted newline 5756*4882a593Smuzhiyun if ($rawline =~ /^.*\".*\s\\n/) { 5757*4882a593Smuzhiyun if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", 5758*4882a593Smuzhiyun "unnecessary whitespace before a quoted newline\n" . $herecurr) && 5759*4882a593Smuzhiyun $fix) { 5760*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; 5761*4882a593Smuzhiyun } 5762*4882a593Smuzhiyun 5763*4882a593Smuzhiyun } 5764*4882a593Smuzhiyun 5765*4882a593Smuzhiyun# concatenated string without spaces between elements 5766*4882a593Smuzhiyun if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) { 5767*4882a593Smuzhiyun if (CHK("CONCATENATED_STRING", 5768*4882a593Smuzhiyun "Concatenated strings should use spaces between elements\n" . $herecurr) && 5769*4882a593Smuzhiyun $fix) { 5770*4882a593Smuzhiyun while ($line =~ /($String)/g) { 5771*4882a593Smuzhiyun my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]); 5772*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/; 5773*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/; 5774*4882a593Smuzhiyun } 5775*4882a593Smuzhiyun } 5776*4882a593Smuzhiyun } 5777*4882a593Smuzhiyun 5778*4882a593Smuzhiyun# uncoalesced string fragments 5779*4882a593Smuzhiyun if ($line =~ /$String\s*"/) { 5780*4882a593Smuzhiyun if (WARN("STRING_FRAGMENTS", 5781*4882a593Smuzhiyun "Consecutive strings are generally better as a single string\n" . $herecurr) && 5782*4882a593Smuzhiyun $fix) { 5783*4882a593Smuzhiyun while ($line =~ /($String)(?=\s*")/g) { 5784*4882a593Smuzhiyun my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]); 5785*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e; 5786*4882a593Smuzhiyun } 5787*4882a593Smuzhiyun } 5788*4882a593Smuzhiyun } 5789*4882a593Smuzhiyun 5790*4882a593Smuzhiyun# check for non-standard and hex prefixed decimal printf formats 5791*4882a593Smuzhiyun my $show_L = 1; #don't show the same defect twice 5792*4882a593Smuzhiyun my $show_Z = 1; 5793*4882a593Smuzhiyun while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { 5794*4882a593Smuzhiyun my $string = substr($rawline, $-[1], $+[1] - $-[1]); 5795*4882a593Smuzhiyun $string =~ s/%%/__/g; 5796*4882a593Smuzhiyun # check for %L 5797*4882a593Smuzhiyun if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) { 5798*4882a593Smuzhiyun WARN("PRINTF_L", 5799*4882a593Smuzhiyun "\%L$1 is non-standard C, use %ll$1\n" . $herecurr); 5800*4882a593Smuzhiyun $show_L = 0; 5801*4882a593Smuzhiyun } 5802*4882a593Smuzhiyun # check for %Z 5803*4882a593Smuzhiyun if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) { 5804*4882a593Smuzhiyun WARN("PRINTF_Z", 5805*4882a593Smuzhiyun "%Z$1 is non-standard C, use %z$1\n" . $herecurr); 5806*4882a593Smuzhiyun $show_Z = 0; 5807*4882a593Smuzhiyun } 5808*4882a593Smuzhiyun # check for 0x<decimal> 5809*4882a593Smuzhiyun if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) { 5810*4882a593Smuzhiyun ERROR("PRINTF_0XDECIMAL", 5811*4882a593Smuzhiyun "Prefixing 0x with decimal output is defective\n" . $herecurr); 5812*4882a593Smuzhiyun } 5813*4882a593Smuzhiyun } 5814*4882a593Smuzhiyun 5815*4882a593Smuzhiyun# check for line continuations in quoted strings with odd counts of " 5816*4882a593Smuzhiyun if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) { 5817*4882a593Smuzhiyun WARN("LINE_CONTINUATIONS", 5818*4882a593Smuzhiyun "Avoid line continuations in quoted strings\n" . $herecurr); 5819*4882a593Smuzhiyun } 5820*4882a593Smuzhiyun 5821*4882a593Smuzhiyun# warn about #if 0 5822*4882a593Smuzhiyun if ($line =~ /^.\s*\#\s*if\s+0\b/) { 5823*4882a593Smuzhiyun WARN("IF_0", 5824*4882a593Smuzhiyun "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr); 5825*4882a593Smuzhiyun } 5826*4882a593Smuzhiyun 5827*4882a593Smuzhiyun# warn about #if 1 5828*4882a593Smuzhiyun if ($line =~ /^.\s*\#\s*if\s+1\b/) { 5829*4882a593Smuzhiyun WARN("IF_1", 5830*4882a593Smuzhiyun "Consider removing the #if 1 and its #endif\n" . $herecurr); 5831*4882a593Smuzhiyun } 5832*4882a593Smuzhiyun 5833*4882a593Smuzhiyun# check for needless "if (<foo>) fn(<foo>)" uses 5834*4882a593Smuzhiyun if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { 5835*4882a593Smuzhiyun my $tested = quotemeta($1); 5836*4882a593Smuzhiyun my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; 5837*4882a593Smuzhiyun if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { 5838*4882a593Smuzhiyun my $func = $1; 5839*4882a593Smuzhiyun if (WARN('NEEDLESS_IF', 5840*4882a593Smuzhiyun "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && 5841*4882a593Smuzhiyun $fix) { 5842*4882a593Smuzhiyun my $do_fix = 1; 5843*4882a593Smuzhiyun my $leading_tabs = ""; 5844*4882a593Smuzhiyun my $new_leading_tabs = ""; 5845*4882a593Smuzhiyun if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { 5846*4882a593Smuzhiyun $leading_tabs = $1; 5847*4882a593Smuzhiyun } else { 5848*4882a593Smuzhiyun $do_fix = 0; 5849*4882a593Smuzhiyun } 5850*4882a593Smuzhiyun if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { 5851*4882a593Smuzhiyun $new_leading_tabs = $1; 5852*4882a593Smuzhiyun if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { 5853*4882a593Smuzhiyun $do_fix = 0; 5854*4882a593Smuzhiyun } 5855*4882a593Smuzhiyun } else { 5856*4882a593Smuzhiyun $do_fix = 0; 5857*4882a593Smuzhiyun } 5858*4882a593Smuzhiyun if ($do_fix) { 5859*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5860*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; 5861*4882a593Smuzhiyun } 5862*4882a593Smuzhiyun } 5863*4882a593Smuzhiyun } 5864*4882a593Smuzhiyun } 5865*4882a593Smuzhiyun 5866*4882a593Smuzhiyun# check for unnecessary "Out of Memory" messages 5867*4882a593Smuzhiyun if ($line =~ /^\+.*\b$logFunctions\s*\(/ && 5868*4882a593Smuzhiyun $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && 5869*4882a593Smuzhiyun (defined $1 || defined $3) && 5870*4882a593Smuzhiyun $linenr > 3) { 5871*4882a593Smuzhiyun my $testval = $2; 5872*4882a593Smuzhiyun my $testline = $lines[$linenr - 3]; 5873*4882a593Smuzhiyun 5874*4882a593Smuzhiyun my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); 5875*4882a593Smuzhiyun# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); 5876*4882a593Smuzhiyun 5877*4882a593Smuzhiyun if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ && 5878*4882a593Smuzhiyun $s !~ /\b__GFP_NOWARN\b/ ) { 5879*4882a593Smuzhiyun WARN("OOM_MESSAGE", 5880*4882a593Smuzhiyun "Possible unnecessary 'out of memory' message\n" . $hereprev); 5881*4882a593Smuzhiyun } 5882*4882a593Smuzhiyun } 5883*4882a593Smuzhiyun 5884*4882a593Smuzhiyun# check for logging functions with KERN_<LEVEL> 5885*4882a593Smuzhiyun if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && 5886*4882a593Smuzhiyun $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { 5887*4882a593Smuzhiyun my $level = $1; 5888*4882a593Smuzhiyun if (WARN("UNNECESSARY_KERN_LEVEL", 5889*4882a593Smuzhiyun "Possible unnecessary $level\n" . $herecurr) && 5890*4882a593Smuzhiyun $fix) { 5891*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s*$level\s*//; 5892*4882a593Smuzhiyun } 5893*4882a593Smuzhiyun } 5894*4882a593Smuzhiyun 5895*4882a593Smuzhiyun# check for logging continuations 5896*4882a593Smuzhiyun if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) { 5897*4882a593Smuzhiyun WARN("LOGGING_CONTINUATION", 5898*4882a593Smuzhiyun "Avoid logging continuation uses where feasible\n" . $herecurr); 5899*4882a593Smuzhiyun } 5900*4882a593Smuzhiyun 5901*4882a593Smuzhiyun# check for mask then right shift without a parentheses 5902*4882a593Smuzhiyun if ($perl_version_ok && 5903*4882a593Smuzhiyun $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && 5904*4882a593Smuzhiyun $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so 5905*4882a593Smuzhiyun WARN("MASK_THEN_SHIFT", 5906*4882a593Smuzhiyun "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); 5907*4882a593Smuzhiyun } 5908*4882a593Smuzhiyun 5909*4882a593Smuzhiyun# check for pointer comparisons to NULL 5910*4882a593Smuzhiyun if ($perl_version_ok) { 5911*4882a593Smuzhiyun while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { 5912*4882a593Smuzhiyun my $val = $1; 5913*4882a593Smuzhiyun my $equal = "!"; 5914*4882a593Smuzhiyun $equal = "" if ($4 eq "!="); 5915*4882a593Smuzhiyun if (CHK("COMPARISON_TO_NULL", 5916*4882a593Smuzhiyun "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && 5917*4882a593Smuzhiyun $fix) { 5918*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; 5919*4882a593Smuzhiyun } 5920*4882a593Smuzhiyun } 5921*4882a593Smuzhiyun } 5922*4882a593Smuzhiyun 5923*4882a593Smuzhiyun# check for bad placement of section $InitAttribute (e.g.: __initdata) 5924*4882a593Smuzhiyun if ($line =~ /(\b$InitAttribute\b)/) { 5925*4882a593Smuzhiyun my $attr = $1; 5926*4882a593Smuzhiyun if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { 5927*4882a593Smuzhiyun my $ptr = $1; 5928*4882a593Smuzhiyun my $var = $2; 5929*4882a593Smuzhiyun if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && 5930*4882a593Smuzhiyun ERROR("MISPLACED_INIT", 5931*4882a593Smuzhiyun "$attr should be placed after $var\n" . $herecurr)) || 5932*4882a593Smuzhiyun ($ptr !~ /\b(union|struct)\s+$attr\b/ && 5933*4882a593Smuzhiyun WARN("MISPLACED_INIT", 5934*4882a593Smuzhiyun "$attr should be placed after $var\n" . $herecurr))) && 5935*4882a593Smuzhiyun $fix) { 5936*4882a593Smuzhiyun $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; 5937*4882a593Smuzhiyun } 5938*4882a593Smuzhiyun } 5939*4882a593Smuzhiyun } 5940*4882a593Smuzhiyun 5941*4882a593Smuzhiyun# check for $InitAttributeData (ie: __initdata) with const 5942*4882a593Smuzhiyun if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { 5943*4882a593Smuzhiyun my $attr = $1; 5944*4882a593Smuzhiyun $attr =~ /($InitAttributePrefix)(.*)/; 5945*4882a593Smuzhiyun my $attr_prefix = $1; 5946*4882a593Smuzhiyun my $attr_type = $2; 5947*4882a593Smuzhiyun if (ERROR("INIT_ATTRIBUTE", 5948*4882a593Smuzhiyun "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && 5949*4882a593Smuzhiyun $fix) { 5950*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 5951*4882a593Smuzhiyun s/$InitAttributeData/${attr_prefix}initconst/; 5952*4882a593Smuzhiyun } 5953*4882a593Smuzhiyun } 5954*4882a593Smuzhiyun 5955*4882a593Smuzhiyun# check for $InitAttributeConst (ie: __initconst) without const 5956*4882a593Smuzhiyun if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { 5957*4882a593Smuzhiyun my $attr = $1; 5958*4882a593Smuzhiyun if (ERROR("INIT_ATTRIBUTE", 5959*4882a593Smuzhiyun "Use of $attr requires a separate use of const\n" . $herecurr) && 5960*4882a593Smuzhiyun $fix) { 5961*4882a593Smuzhiyun my $lead = $fixed[$fixlinenr] =~ 5962*4882a593Smuzhiyun /(^\+\s*(?:static\s+))/; 5963*4882a593Smuzhiyun $lead = rtrim($1); 5964*4882a593Smuzhiyun $lead = "$lead " if ($lead !~ /^\+$/); 5965*4882a593Smuzhiyun $lead = "${lead}const "; 5966*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; 5967*4882a593Smuzhiyun } 5968*4882a593Smuzhiyun } 5969*4882a593Smuzhiyun 5970*4882a593Smuzhiyun# check for __read_mostly with const non-pointer (should just be const) 5971*4882a593Smuzhiyun if ($line =~ /\b__read_mostly\b/ && 5972*4882a593Smuzhiyun $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { 5973*4882a593Smuzhiyun if (ERROR("CONST_READ_MOSTLY", 5974*4882a593Smuzhiyun "Invalid use of __read_mostly with const type\n" . $herecurr) && 5975*4882a593Smuzhiyun $fix) { 5976*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; 5977*4882a593Smuzhiyun } 5978*4882a593Smuzhiyun } 5979*4882a593Smuzhiyun 5980*4882a593Smuzhiyun# don't use __constant_<foo> functions outside of include/uapi/ 5981*4882a593Smuzhiyun if ($realfile !~ m@^include/uapi/@ && 5982*4882a593Smuzhiyun $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { 5983*4882a593Smuzhiyun my $constant_func = $1; 5984*4882a593Smuzhiyun my $func = $constant_func; 5985*4882a593Smuzhiyun $func =~ s/^__constant_//; 5986*4882a593Smuzhiyun if (WARN("CONSTANT_CONVERSION", 5987*4882a593Smuzhiyun "$constant_func should be $func\n" . $herecurr) && 5988*4882a593Smuzhiyun $fix) { 5989*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; 5990*4882a593Smuzhiyun } 5991*4882a593Smuzhiyun } 5992*4882a593Smuzhiyun 5993*4882a593Smuzhiyun# prefer usleep_range over udelay 5994*4882a593Smuzhiyun if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { 5995*4882a593Smuzhiyun my $delay = $1; 5996*4882a593Smuzhiyun # ignore udelay's < 10, however 5997*4882a593Smuzhiyun if (! ($delay < 10) ) { 5998*4882a593Smuzhiyun CHK("USLEEP_RANGE", 5999*4882a593Smuzhiyun "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr); 6000*4882a593Smuzhiyun } 6001*4882a593Smuzhiyun if ($delay > 2000) { 6002*4882a593Smuzhiyun WARN("LONG_UDELAY", 6003*4882a593Smuzhiyun "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); 6004*4882a593Smuzhiyun } 6005*4882a593Smuzhiyun } 6006*4882a593Smuzhiyun 6007*4882a593Smuzhiyun# warn about unexpectedly long msleep's 6008*4882a593Smuzhiyun if ($line =~ /\bmsleep\s*\((\d+)\);/) { 6009*4882a593Smuzhiyun if ($1 < 20) { 6010*4882a593Smuzhiyun WARN("MSLEEP", 6011*4882a593Smuzhiyun "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr); 6012*4882a593Smuzhiyun } 6013*4882a593Smuzhiyun } 6014*4882a593Smuzhiyun 6015*4882a593Smuzhiyun# check for comparisons of jiffies 6016*4882a593Smuzhiyun if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { 6017*4882a593Smuzhiyun WARN("JIFFIES_COMPARISON", 6018*4882a593Smuzhiyun "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); 6019*4882a593Smuzhiyun } 6020*4882a593Smuzhiyun 6021*4882a593Smuzhiyun# check for comparisons of get_jiffies_64() 6022*4882a593Smuzhiyun if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { 6023*4882a593Smuzhiyun WARN("JIFFIES_COMPARISON", 6024*4882a593Smuzhiyun "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); 6025*4882a593Smuzhiyun } 6026*4882a593Smuzhiyun 6027*4882a593Smuzhiyun# warn about #ifdefs in C files 6028*4882a593Smuzhiyun# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { 6029*4882a593Smuzhiyun# print "#ifdef in C files should be avoided\n"; 6030*4882a593Smuzhiyun# print "$herecurr"; 6031*4882a593Smuzhiyun# $clean = 0; 6032*4882a593Smuzhiyun# } 6033*4882a593Smuzhiyun 6034*4882a593Smuzhiyun# warn about spacing in #ifdefs 6035*4882a593Smuzhiyun if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { 6036*4882a593Smuzhiyun if (ERROR("SPACING", 6037*4882a593Smuzhiyun "exactly one space required after that #$1\n" . $herecurr) && 6038*4882a593Smuzhiyun $fix) { 6039*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 6040*4882a593Smuzhiyun s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; 6041*4882a593Smuzhiyun } 6042*4882a593Smuzhiyun 6043*4882a593Smuzhiyun } 6044*4882a593Smuzhiyun 6045*4882a593Smuzhiyun# check for spinlock_t definitions without a comment. 6046*4882a593Smuzhiyun if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || 6047*4882a593Smuzhiyun $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { 6048*4882a593Smuzhiyun my $which = $1; 6049*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 6050*4882a593Smuzhiyun CHK("UNCOMMENTED_DEFINITION", 6051*4882a593Smuzhiyun "$1 definition without comment\n" . $herecurr); 6052*4882a593Smuzhiyun } 6053*4882a593Smuzhiyun } 6054*4882a593Smuzhiyun# check for memory barriers without a comment. 6055*4882a593Smuzhiyun 6056*4882a593Smuzhiyun my $barriers = qr{ 6057*4882a593Smuzhiyun mb| 6058*4882a593Smuzhiyun rmb| 6059*4882a593Smuzhiyun wmb 6060*4882a593Smuzhiyun }x; 6061*4882a593Smuzhiyun my $barrier_stems = qr{ 6062*4882a593Smuzhiyun mb__before_atomic| 6063*4882a593Smuzhiyun mb__after_atomic| 6064*4882a593Smuzhiyun store_release| 6065*4882a593Smuzhiyun load_acquire| 6066*4882a593Smuzhiyun store_mb| 6067*4882a593Smuzhiyun (?:$barriers) 6068*4882a593Smuzhiyun }x; 6069*4882a593Smuzhiyun my $all_barriers = qr{ 6070*4882a593Smuzhiyun (?:$barriers)| 6071*4882a593Smuzhiyun smp_(?:$barrier_stems)| 6072*4882a593Smuzhiyun virt_(?:$barrier_stems) 6073*4882a593Smuzhiyun }x; 6074*4882a593Smuzhiyun 6075*4882a593Smuzhiyun if ($line =~ /\b(?:$all_barriers)\s*\(/) { 6076*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 6077*4882a593Smuzhiyun WARN("MEMORY_BARRIER", 6078*4882a593Smuzhiyun "memory barrier without comment\n" . $herecurr); 6079*4882a593Smuzhiyun } 6080*4882a593Smuzhiyun } 6081*4882a593Smuzhiyun 6082*4882a593Smuzhiyun my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; 6083*4882a593Smuzhiyun 6084*4882a593Smuzhiyun if ($realfile !~ m@^include/asm-generic/@ && 6085*4882a593Smuzhiyun $realfile !~ m@/barrier\.h$@ && 6086*4882a593Smuzhiyun $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && 6087*4882a593Smuzhiyun $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { 6088*4882a593Smuzhiyun WARN("MEMORY_BARRIER", 6089*4882a593Smuzhiyun "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); 6090*4882a593Smuzhiyun } 6091*4882a593Smuzhiyun 6092*4882a593Smuzhiyun# check for waitqueue_active without a comment. 6093*4882a593Smuzhiyun if ($line =~ /\bwaitqueue_active\s*\(/) { 6094*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 6095*4882a593Smuzhiyun WARN("WAITQUEUE_ACTIVE", 6096*4882a593Smuzhiyun "waitqueue_active without comment\n" . $herecurr); 6097*4882a593Smuzhiyun } 6098*4882a593Smuzhiyun } 6099*4882a593Smuzhiyun 6100*4882a593Smuzhiyun# check for data_race without a comment. 6101*4882a593Smuzhiyun if ($line =~ /\bdata_race\s*\(/) { 6102*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 6103*4882a593Smuzhiyun WARN("DATA_RACE", 6104*4882a593Smuzhiyun "data_race without comment\n" . $herecurr); 6105*4882a593Smuzhiyun } 6106*4882a593Smuzhiyun } 6107*4882a593Smuzhiyun 6108*4882a593Smuzhiyun# check of hardware specific defines 6109*4882a593Smuzhiyun if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { 6110*4882a593Smuzhiyun CHK("ARCH_DEFINES", 6111*4882a593Smuzhiyun "architecture specific defines should be avoided\n" . $herecurr); 6112*4882a593Smuzhiyun } 6113*4882a593Smuzhiyun 6114*4882a593Smuzhiyun# check that the storage class is not after a type 6115*4882a593Smuzhiyun if ($line =~ /\b($Type)\s+($Storage)\b/) { 6116*4882a593Smuzhiyun WARN("STORAGE_CLASS", 6117*4882a593Smuzhiyun "storage class '$2' should be located before type '$1'\n" . $herecurr); 6118*4882a593Smuzhiyun } 6119*4882a593Smuzhiyun# Check that the storage class is at the beginning of a declaration 6120*4882a593Smuzhiyun if ($line =~ /\b$Storage\b/ && 6121*4882a593Smuzhiyun $line !~ /^.\s*$Storage/ && 6122*4882a593Smuzhiyun $line =~ /^.\s*(.+?)\$Storage\s/ && 6123*4882a593Smuzhiyun $1 !~ /[\,\)]\s*$/) { 6124*4882a593Smuzhiyun WARN("STORAGE_CLASS", 6125*4882a593Smuzhiyun "storage class should be at the beginning of the declaration\n" . $herecurr); 6126*4882a593Smuzhiyun } 6127*4882a593Smuzhiyun 6128*4882a593Smuzhiyun# check the location of the inline attribute, that it is between 6129*4882a593Smuzhiyun# storage class and type. 6130*4882a593Smuzhiyun if ($line =~ /\b$Type\s+$Inline\b/ || 6131*4882a593Smuzhiyun $line =~ /\b$Inline\s+$Storage\b/) { 6132*4882a593Smuzhiyun ERROR("INLINE_LOCATION", 6133*4882a593Smuzhiyun "inline keyword should sit between storage class and type\n" . $herecurr); 6134*4882a593Smuzhiyun } 6135*4882a593Smuzhiyun 6136*4882a593Smuzhiyun# Check for __inline__ and __inline, prefer inline 6137*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6138*4882a593Smuzhiyun $line =~ /\b(__inline__|__inline)\b/) { 6139*4882a593Smuzhiyun if (WARN("INLINE", 6140*4882a593Smuzhiyun "plain inline is preferred over $1\n" . $herecurr) && 6141*4882a593Smuzhiyun $fix) { 6142*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; 6143*4882a593Smuzhiyun 6144*4882a593Smuzhiyun } 6145*4882a593Smuzhiyun } 6146*4882a593Smuzhiyun 6147*4882a593Smuzhiyun# Check for __attribute__ packed, prefer __packed 6148*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6149*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { 6150*4882a593Smuzhiyun WARN("PREFER_PACKED", 6151*4882a593Smuzhiyun "__packed is preferred over __attribute__((packed))\n" . $herecurr); 6152*4882a593Smuzhiyun } 6153*4882a593Smuzhiyun 6154*4882a593Smuzhiyun# Check for __attribute__ aligned, prefer __aligned 6155*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6156*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { 6157*4882a593Smuzhiyun WARN("PREFER_ALIGNED", 6158*4882a593Smuzhiyun "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); 6159*4882a593Smuzhiyun } 6160*4882a593Smuzhiyun 6161*4882a593Smuzhiyun# Check for __attribute__ section, prefer __section 6162*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6163*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) { 6164*4882a593Smuzhiyun my $old = substr($rawline, $-[1], $+[1] - $-[1]); 6165*4882a593Smuzhiyun my $new = substr($old, 1, -1); 6166*4882a593Smuzhiyun if (WARN("PREFER_SECTION", 6167*4882a593Smuzhiyun "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) && 6168*4882a593Smuzhiyun $fix) { 6169*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/; 6170*4882a593Smuzhiyun } 6171*4882a593Smuzhiyun } 6172*4882a593Smuzhiyun 6173*4882a593Smuzhiyun# Check for __attribute__ format(printf, prefer __printf 6174*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6175*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { 6176*4882a593Smuzhiyun if (WARN("PREFER_PRINTF", 6177*4882a593Smuzhiyun "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && 6178*4882a593Smuzhiyun $fix) { 6179*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; 6180*4882a593Smuzhiyun 6181*4882a593Smuzhiyun } 6182*4882a593Smuzhiyun } 6183*4882a593Smuzhiyun 6184*4882a593Smuzhiyun# Check for __attribute__ format(scanf, prefer __scanf 6185*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6186*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { 6187*4882a593Smuzhiyun if (WARN("PREFER_SCANF", 6188*4882a593Smuzhiyun "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && 6189*4882a593Smuzhiyun $fix) { 6190*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; 6191*4882a593Smuzhiyun } 6192*4882a593Smuzhiyun } 6193*4882a593Smuzhiyun 6194*4882a593Smuzhiyun# Check for __attribute__ weak, or __weak declarations (may have link issues) 6195*4882a593Smuzhiyun if ($perl_version_ok && 6196*4882a593Smuzhiyun $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && 6197*4882a593Smuzhiyun ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || 6198*4882a593Smuzhiyun $line =~ /\b__weak\b/)) { 6199*4882a593Smuzhiyun ERROR("WEAK_DECLARATION", 6200*4882a593Smuzhiyun "Using weak declarations can have unintended link defects\n" . $herecurr); 6201*4882a593Smuzhiyun } 6202*4882a593Smuzhiyun 6203*4882a593Smuzhiyun# check for c99 types like uint8_t used outside of uapi/ and tools/ 6204*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 6205*4882a593Smuzhiyun $realfile !~ m@\btools/@ && 6206*4882a593Smuzhiyun $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { 6207*4882a593Smuzhiyun my $type = $1; 6208*4882a593Smuzhiyun if ($type =~ /\b($typeC99Typedefs)\b/) { 6209*4882a593Smuzhiyun $type = $1; 6210*4882a593Smuzhiyun my $kernel_type = 'u'; 6211*4882a593Smuzhiyun $kernel_type = 's' if ($type =~ /^_*[si]/); 6212*4882a593Smuzhiyun $type =~ /(\d+)/; 6213*4882a593Smuzhiyun $kernel_type .= $1; 6214*4882a593Smuzhiyun if (CHK("PREFER_KERNEL_TYPES", 6215*4882a593Smuzhiyun "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && 6216*4882a593Smuzhiyun $fix) { 6217*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; 6218*4882a593Smuzhiyun } 6219*4882a593Smuzhiyun } 6220*4882a593Smuzhiyun } 6221*4882a593Smuzhiyun 6222*4882a593Smuzhiyun# check for cast of C90 native int or longer types constants 6223*4882a593Smuzhiyun if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { 6224*4882a593Smuzhiyun my $cast = $1; 6225*4882a593Smuzhiyun my $const = $2; 6226*4882a593Smuzhiyun if (WARN("TYPECAST_INT_CONSTANT", 6227*4882a593Smuzhiyun "Unnecessary typecast of c90 int constant\n" . $herecurr) && 6228*4882a593Smuzhiyun $fix) { 6229*4882a593Smuzhiyun my $suffix = ""; 6230*4882a593Smuzhiyun my $newconst = $const; 6231*4882a593Smuzhiyun $newconst =~ s/${Int_type}$//; 6232*4882a593Smuzhiyun $suffix .= 'U' if ($cast =~ /\bunsigned\b/); 6233*4882a593Smuzhiyun if ($cast =~ /\blong\s+long\b/) { 6234*4882a593Smuzhiyun $suffix .= 'LL'; 6235*4882a593Smuzhiyun } elsif ($cast =~ /\blong\b/) { 6236*4882a593Smuzhiyun $suffix .= 'L'; 6237*4882a593Smuzhiyun } 6238*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; 6239*4882a593Smuzhiyun } 6240*4882a593Smuzhiyun } 6241*4882a593Smuzhiyun 6242*4882a593Smuzhiyun# check for sizeof(&) 6243*4882a593Smuzhiyun if ($line =~ /\bsizeof\s*\(\s*\&/) { 6244*4882a593Smuzhiyun WARN("SIZEOF_ADDRESS", 6245*4882a593Smuzhiyun "sizeof(& should be avoided\n" . $herecurr); 6246*4882a593Smuzhiyun } 6247*4882a593Smuzhiyun 6248*4882a593Smuzhiyun# check for sizeof without parenthesis 6249*4882a593Smuzhiyun if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { 6250*4882a593Smuzhiyun if (WARN("SIZEOF_PARENTHESIS", 6251*4882a593Smuzhiyun "sizeof $1 should be sizeof($1)\n" . $herecurr) && 6252*4882a593Smuzhiyun $fix) { 6253*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; 6254*4882a593Smuzhiyun } 6255*4882a593Smuzhiyun } 6256*4882a593Smuzhiyun 6257*4882a593Smuzhiyun# check for struct spinlock declarations 6258*4882a593Smuzhiyun if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { 6259*4882a593Smuzhiyun WARN("USE_SPINLOCK_T", 6260*4882a593Smuzhiyun "struct spinlock should be spinlock_t\n" . $herecurr); 6261*4882a593Smuzhiyun } 6262*4882a593Smuzhiyun 6263*4882a593Smuzhiyun# check for seq_printf uses that could be seq_puts 6264*4882a593Smuzhiyun if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { 6265*4882a593Smuzhiyun my $fmt = get_quoted_string($line, $rawline); 6266*4882a593Smuzhiyun $fmt =~ s/%%//g; 6267*4882a593Smuzhiyun if ($fmt !~ /%/) { 6268*4882a593Smuzhiyun if (WARN("PREFER_SEQ_PUTS", 6269*4882a593Smuzhiyun "Prefer seq_puts to seq_printf\n" . $herecurr) && 6270*4882a593Smuzhiyun $fix) { 6271*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; 6272*4882a593Smuzhiyun } 6273*4882a593Smuzhiyun } 6274*4882a593Smuzhiyun } 6275*4882a593Smuzhiyun 6276*4882a593Smuzhiyun# check for vsprintf extension %p<foo> misuses 6277*4882a593Smuzhiyun if ($perl_version_ok && 6278*4882a593Smuzhiyun defined $stat && 6279*4882a593Smuzhiyun $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s && 6280*4882a593Smuzhiyun $1 !~ /^_*volatile_*$/) { 6281*4882a593Smuzhiyun my $stat_real; 6282*4882a593Smuzhiyun 6283*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 6284*4882a593Smuzhiyun $lc = $lc + $linenr; 6285*4882a593Smuzhiyun for (my $count = $linenr; $count <= $lc; $count++) { 6286*4882a593Smuzhiyun my $specifier; 6287*4882a593Smuzhiyun my $extension; 6288*4882a593Smuzhiyun my $qualifier; 6289*4882a593Smuzhiyun my $bad_specifier = ""; 6290*4882a593Smuzhiyun my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0)); 6291*4882a593Smuzhiyun $fmt =~ s/%%//g; 6292*4882a593Smuzhiyun 6293*4882a593Smuzhiyun while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) { 6294*4882a593Smuzhiyun $specifier = $1; 6295*4882a593Smuzhiyun $extension = $2; 6296*4882a593Smuzhiyun $qualifier = $3; 6297*4882a593Smuzhiyun if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ || 6298*4882a593Smuzhiyun ($extension eq "f" && 6299*4882a593Smuzhiyun defined $qualifier && $qualifier !~ /^w/)) { 6300*4882a593Smuzhiyun $bad_specifier = $specifier; 6301*4882a593Smuzhiyun last; 6302*4882a593Smuzhiyun } 6303*4882a593Smuzhiyun if ($extension eq "x" && !defined($stat_real)) { 6304*4882a593Smuzhiyun if (!defined($stat_real)) { 6305*4882a593Smuzhiyun $stat_real = get_stat_real($linenr, $lc); 6306*4882a593Smuzhiyun } 6307*4882a593Smuzhiyun WARN("VSPRINTF_SPECIFIER_PX", 6308*4882a593Smuzhiyun "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"); 6309*4882a593Smuzhiyun } 6310*4882a593Smuzhiyun } 6311*4882a593Smuzhiyun if ($bad_specifier ne "") { 6312*4882a593Smuzhiyun my $stat_real = get_stat_real($linenr, $lc); 6313*4882a593Smuzhiyun my $ext_type = "Invalid"; 6314*4882a593Smuzhiyun my $use = ""; 6315*4882a593Smuzhiyun if ($bad_specifier =~ /p[Ff]/) { 6316*4882a593Smuzhiyun $use = " - use %pS instead"; 6317*4882a593Smuzhiyun $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/); 6318*4882a593Smuzhiyun } 6319*4882a593Smuzhiyun 6320*4882a593Smuzhiyun WARN("VSPRINTF_POINTER_EXTENSION", 6321*4882a593Smuzhiyun "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n"); 6322*4882a593Smuzhiyun } 6323*4882a593Smuzhiyun } 6324*4882a593Smuzhiyun } 6325*4882a593Smuzhiyun 6326*4882a593Smuzhiyun# Check for misused memsets 6327*4882a593Smuzhiyun if ($perl_version_ok && 6328*4882a593Smuzhiyun defined $stat && 6329*4882a593Smuzhiyun $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { 6330*4882a593Smuzhiyun 6331*4882a593Smuzhiyun my $ms_addr = $2; 6332*4882a593Smuzhiyun my $ms_val = $7; 6333*4882a593Smuzhiyun my $ms_size = $12; 6334*4882a593Smuzhiyun 6335*4882a593Smuzhiyun if ($ms_size =~ /^(0x|)0$/i) { 6336*4882a593Smuzhiyun ERROR("MEMSET", 6337*4882a593Smuzhiyun "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); 6338*4882a593Smuzhiyun } elsif ($ms_size =~ /^(0x|)1$/i) { 6339*4882a593Smuzhiyun WARN("MEMSET", 6340*4882a593Smuzhiyun "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); 6341*4882a593Smuzhiyun } 6342*4882a593Smuzhiyun } 6343*4882a593Smuzhiyun 6344*4882a593Smuzhiyun# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) 6345*4882a593Smuzhiyun# if ($perl_version_ok && 6346*4882a593Smuzhiyun# defined $stat && 6347*4882a593Smuzhiyun# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 6348*4882a593Smuzhiyun# if (WARN("PREFER_ETHER_ADDR_COPY", 6349*4882a593Smuzhiyun# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && 6350*4882a593Smuzhiyun# $fix) { 6351*4882a593Smuzhiyun# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; 6352*4882a593Smuzhiyun# } 6353*4882a593Smuzhiyun# } 6354*4882a593Smuzhiyun 6355*4882a593Smuzhiyun# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) 6356*4882a593Smuzhiyun# if ($perl_version_ok && 6357*4882a593Smuzhiyun# defined $stat && 6358*4882a593Smuzhiyun# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 6359*4882a593Smuzhiyun# WARN("PREFER_ETHER_ADDR_EQUAL", 6360*4882a593Smuzhiyun# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") 6361*4882a593Smuzhiyun# } 6362*4882a593Smuzhiyun 6363*4882a593Smuzhiyun# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr 6364*4882a593Smuzhiyun# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr 6365*4882a593Smuzhiyun# if ($perl_version_ok && 6366*4882a593Smuzhiyun# defined $stat && 6367*4882a593Smuzhiyun# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 6368*4882a593Smuzhiyun# 6369*4882a593Smuzhiyun# my $ms_val = $7; 6370*4882a593Smuzhiyun# 6371*4882a593Smuzhiyun# if ($ms_val =~ /^(?:0x|)0+$/i) { 6372*4882a593Smuzhiyun# if (WARN("PREFER_ETH_ZERO_ADDR", 6373*4882a593Smuzhiyun# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && 6374*4882a593Smuzhiyun# $fix) { 6375*4882a593Smuzhiyun# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; 6376*4882a593Smuzhiyun# } 6377*4882a593Smuzhiyun# } elsif ($ms_val =~ /^(?:0xff|255)$/i) { 6378*4882a593Smuzhiyun# if (WARN("PREFER_ETH_BROADCAST_ADDR", 6379*4882a593Smuzhiyun# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && 6380*4882a593Smuzhiyun# $fix) { 6381*4882a593Smuzhiyun# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; 6382*4882a593Smuzhiyun# } 6383*4882a593Smuzhiyun# } 6384*4882a593Smuzhiyun# } 6385*4882a593Smuzhiyun 6386*4882a593Smuzhiyun# typecasts on min/max could be min_t/max_t 6387*4882a593Smuzhiyun if ($perl_version_ok && 6388*4882a593Smuzhiyun defined $stat && 6389*4882a593Smuzhiyun $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { 6390*4882a593Smuzhiyun if (defined $2 || defined $7) { 6391*4882a593Smuzhiyun my $call = $1; 6392*4882a593Smuzhiyun my $cast1 = deparenthesize($2); 6393*4882a593Smuzhiyun my $arg1 = $3; 6394*4882a593Smuzhiyun my $cast2 = deparenthesize($7); 6395*4882a593Smuzhiyun my $arg2 = $8; 6396*4882a593Smuzhiyun my $cast; 6397*4882a593Smuzhiyun 6398*4882a593Smuzhiyun if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { 6399*4882a593Smuzhiyun $cast = "$cast1 or $cast2"; 6400*4882a593Smuzhiyun } elsif ($cast1 ne "") { 6401*4882a593Smuzhiyun $cast = $cast1; 6402*4882a593Smuzhiyun } else { 6403*4882a593Smuzhiyun $cast = $cast2; 6404*4882a593Smuzhiyun } 6405*4882a593Smuzhiyun WARN("MINMAX", 6406*4882a593Smuzhiyun "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); 6407*4882a593Smuzhiyun } 6408*4882a593Smuzhiyun } 6409*4882a593Smuzhiyun 6410*4882a593Smuzhiyun# check usleep_range arguments 6411*4882a593Smuzhiyun if ($perl_version_ok && 6412*4882a593Smuzhiyun defined $stat && 6413*4882a593Smuzhiyun $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { 6414*4882a593Smuzhiyun my $min = $1; 6415*4882a593Smuzhiyun my $max = $7; 6416*4882a593Smuzhiyun if ($min eq $max) { 6417*4882a593Smuzhiyun WARN("USLEEP_RANGE", 6418*4882a593Smuzhiyun "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n"); 6419*4882a593Smuzhiyun } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && 6420*4882a593Smuzhiyun $min > $max) { 6421*4882a593Smuzhiyun WARN("USLEEP_RANGE", 6422*4882a593Smuzhiyun "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n"); 6423*4882a593Smuzhiyun } 6424*4882a593Smuzhiyun } 6425*4882a593Smuzhiyun 6426*4882a593Smuzhiyun# check for naked sscanf 6427*4882a593Smuzhiyun if ($perl_version_ok && 6428*4882a593Smuzhiyun defined $stat && 6429*4882a593Smuzhiyun $line =~ /\bsscanf\b/ && 6430*4882a593Smuzhiyun ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && 6431*4882a593Smuzhiyun $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && 6432*4882a593Smuzhiyun $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { 6433*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 6434*4882a593Smuzhiyun $lc = $lc + $linenr; 6435*4882a593Smuzhiyun my $stat_real = get_stat_real($linenr, $lc); 6436*4882a593Smuzhiyun WARN("NAKED_SSCANF", 6437*4882a593Smuzhiyun "unchecked sscanf return value\n" . "$here\n$stat_real\n"); 6438*4882a593Smuzhiyun } 6439*4882a593Smuzhiyun 6440*4882a593Smuzhiyun# check for simple sscanf that should be kstrto<foo> 6441*4882a593Smuzhiyun if ($perl_version_ok && 6442*4882a593Smuzhiyun defined $stat && 6443*4882a593Smuzhiyun $line =~ /\bsscanf\b/) { 6444*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 6445*4882a593Smuzhiyun $lc = $lc + $linenr; 6446*4882a593Smuzhiyun my $stat_real = get_stat_real($linenr, $lc); 6447*4882a593Smuzhiyun if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { 6448*4882a593Smuzhiyun my $format = $6; 6449*4882a593Smuzhiyun my $count = $format =~ tr@%@%@; 6450*4882a593Smuzhiyun if ($count == 1 && 6451*4882a593Smuzhiyun $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { 6452*4882a593Smuzhiyun WARN("SSCANF_TO_KSTRTO", 6453*4882a593Smuzhiyun "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); 6454*4882a593Smuzhiyun } 6455*4882a593Smuzhiyun } 6456*4882a593Smuzhiyun } 6457*4882a593Smuzhiyun 6458*4882a593Smuzhiyun# check for new externs in .h files. 6459*4882a593Smuzhiyun if ($realfile =~ /\.h$/ && 6460*4882a593Smuzhiyun $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { 6461*4882a593Smuzhiyun if (CHK("AVOID_EXTERNS", 6462*4882a593Smuzhiyun "extern prototypes should be avoided in .h files\n" . $herecurr) && 6463*4882a593Smuzhiyun $fix) { 6464*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; 6465*4882a593Smuzhiyun } 6466*4882a593Smuzhiyun } 6467*4882a593Smuzhiyun 6468*4882a593Smuzhiyun# check for new externs in .c files. 6469*4882a593Smuzhiyun if ($realfile =~ /\.c$/ && defined $stat && 6470*4882a593Smuzhiyun $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) 6471*4882a593Smuzhiyun { 6472*4882a593Smuzhiyun my $function_name = $1; 6473*4882a593Smuzhiyun my $paren_space = $2; 6474*4882a593Smuzhiyun 6475*4882a593Smuzhiyun my $s = $stat; 6476*4882a593Smuzhiyun if (defined $cond) { 6477*4882a593Smuzhiyun substr($s, 0, length($cond), ''); 6478*4882a593Smuzhiyun } 6479*4882a593Smuzhiyun if ($s =~ /^\s*;/) 6480*4882a593Smuzhiyun { 6481*4882a593Smuzhiyun WARN("AVOID_EXTERNS", 6482*4882a593Smuzhiyun "externs should be avoided in .c files\n" . $herecurr); 6483*4882a593Smuzhiyun } 6484*4882a593Smuzhiyun 6485*4882a593Smuzhiyun if ($paren_space =~ /\n/) { 6486*4882a593Smuzhiyun WARN("FUNCTION_ARGUMENTS", 6487*4882a593Smuzhiyun "arguments for function declarations should follow identifier\n" . $herecurr); 6488*4882a593Smuzhiyun } 6489*4882a593Smuzhiyun 6490*4882a593Smuzhiyun } elsif ($realfile =~ /\.c$/ && defined $stat && 6491*4882a593Smuzhiyun $stat =~ /^.\s*extern\s+/) 6492*4882a593Smuzhiyun { 6493*4882a593Smuzhiyun WARN("AVOID_EXTERNS", 6494*4882a593Smuzhiyun "externs should be avoided in .c files\n" . $herecurr); 6495*4882a593Smuzhiyun } 6496*4882a593Smuzhiyun 6497*4882a593Smuzhiyun# check for function declarations that have arguments without identifier names 6498*4882a593Smuzhiyun if (defined $stat && 6499*4882a593Smuzhiyun $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s && 6500*4882a593Smuzhiyun $1 ne "void") { 6501*4882a593Smuzhiyun my $args = trim($1); 6502*4882a593Smuzhiyun while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) { 6503*4882a593Smuzhiyun my $arg = trim($1); 6504*4882a593Smuzhiyun if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) { 6505*4882a593Smuzhiyun WARN("FUNCTION_ARGUMENTS", 6506*4882a593Smuzhiyun "function definition argument '$arg' should also have an identifier name\n" . $herecurr); 6507*4882a593Smuzhiyun } 6508*4882a593Smuzhiyun } 6509*4882a593Smuzhiyun } 6510*4882a593Smuzhiyun 6511*4882a593Smuzhiyun# check for function definitions 6512*4882a593Smuzhiyun if ($perl_version_ok && 6513*4882a593Smuzhiyun defined $stat && 6514*4882a593Smuzhiyun $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) { 6515*4882a593Smuzhiyun $context_function = $1; 6516*4882a593Smuzhiyun 6517*4882a593Smuzhiyun# check for multiline function definition with misplaced open brace 6518*4882a593Smuzhiyun my $ok = 0; 6519*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 6520*4882a593Smuzhiyun my $herectx = $here . "\n"; 6521*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 6522*4882a593Smuzhiyun my $rl = raw_line($linenr, $n); 6523*4882a593Smuzhiyun $herectx .= $rl . "\n"; 6524*4882a593Smuzhiyun $ok = 1 if ($rl =~ /^[ \+]\{/); 6525*4882a593Smuzhiyun $ok = 1 if ($rl =~ /\{/ && $n == 0); 6526*4882a593Smuzhiyun last if $rl =~ /^[ \+].*\{/; 6527*4882a593Smuzhiyun } 6528*4882a593Smuzhiyun if (!$ok) { 6529*4882a593Smuzhiyun ERROR("OPEN_BRACE", 6530*4882a593Smuzhiyun "open brace '{' following function definitions go on the next line\n" . $herectx); 6531*4882a593Smuzhiyun } 6532*4882a593Smuzhiyun } 6533*4882a593Smuzhiyun 6534*4882a593Smuzhiyun# checks for new __setup's 6535*4882a593Smuzhiyun if ($rawline =~ /\b__setup\("([^"]*)"/) { 6536*4882a593Smuzhiyun my $name = $1; 6537*4882a593Smuzhiyun 6538*4882a593Smuzhiyun if (!grep(/$name/, @setup_docs)) { 6539*4882a593Smuzhiyun CHK("UNDOCUMENTED_SETUP", 6540*4882a593Smuzhiyun "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr); 6541*4882a593Smuzhiyun } 6542*4882a593Smuzhiyun } 6543*4882a593Smuzhiyun 6544*4882a593Smuzhiyun# check for pointless casting of alloc functions 6545*4882a593Smuzhiyun if ($line =~ /\*\s*\)\s*$allocFunctions\b/) { 6546*4882a593Smuzhiyun WARN("UNNECESSARY_CASTS", 6547*4882a593Smuzhiyun "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); 6548*4882a593Smuzhiyun } 6549*4882a593Smuzhiyun 6550*4882a593Smuzhiyun# alloc style 6551*4882a593Smuzhiyun# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) 6552*4882a593Smuzhiyun if ($perl_version_ok && 6553*4882a593Smuzhiyun $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { 6554*4882a593Smuzhiyun CHK("ALLOC_SIZEOF_STRUCT", 6555*4882a593Smuzhiyun "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); 6556*4882a593Smuzhiyun } 6557*4882a593Smuzhiyun 6558*4882a593Smuzhiyun# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc 6559*4882a593Smuzhiyun if ($perl_version_ok && 6560*4882a593Smuzhiyun defined $stat && 6561*4882a593Smuzhiyun $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { 6562*4882a593Smuzhiyun my $oldfunc = $3; 6563*4882a593Smuzhiyun my $a1 = $4; 6564*4882a593Smuzhiyun my $a2 = $10; 6565*4882a593Smuzhiyun my $newfunc = "kmalloc_array"; 6566*4882a593Smuzhiyun $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); 6567*4882a593Smuzhiyun my $r1 = $a1; 6568*4882a593Smuzhiyun my $r2 = $a2; 6569*4882a593Smuzhiyun if ($a1 =~ /^sizeof\s*\S/) { 6570*4882a593Smuzhiyun $r1 = $a2; 6571*4882a593Smuzhiyun $r2 = $a1; 6572*4882a593Smuzhiyun } 6573*4882a593Smuzhiyun if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && 6574*4882a593Smuzhiyun !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { 6575*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 6576*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 6577*4882a593Smuzhiyun 6578*4882a593Smuzhiyun if (WARN("ALLOC_WITH_MULTIPLY", 6579*4882a593Smuzhiyun "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) && 6580*4882a593Smuzhiyun $cnt == 1 && 6581*4882a593Smuzhiyun $fix) { 6582*4882a593Smuzhiyun $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; 6583*4882a593Smuzhiyun } 6584*4882a593Smuzhiyun } 6585*4882a593Smuzhiyun } 6586*4882a593Smuzhiyun 6587*4882a593Smuzhiyun# check for krealloc arg reuse 6588*4882a593Smuzhiyun if ($perl_version_ok && 6589*4882a593Smuzhiyun $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ && 6590*4882a593Smuzhiyun $1 eq $3) { 6591*4882a593Smuzhiyun WARN("KREALLOC_ARG_REUSE", 6592*4882a593Smuzhiyun "Reusing the krealloc arg is almost always a bug\n" . $herecurr); 6593*4882a593Smuzhiyun } 6594*4882a593Smuzhiyun 6595*4882a593Smuzhiyun# check for alloc argument mismatch 6596*4882a593Smuzhiyun if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { 6597*4882a593Smuzhiyun WARN("ALLOC_ARRAY_ARGS", 6598*4882a593Smuzhiyun "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); 6599*4882a593Smuzhiyun } 6600*4882a593Smuzhiyun 6601*4882a593Smuzhiyun# check for multiple semicolons 6602*4882a593Smuzhiyun if ($line =~ /;\s*;\s*$/) { 6603*4882a593Smuzhiyun if (WARN("ONE_SEMICOLON", 6604*4882a593Smuzhiyun "Statements terminations use 1 semicolon\n" . $herecurr) && 6605*4882a593Smuzhiyun $fix) { 6606*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; 6607*4882a593Smuzhiyun } 6608*4882a593Smuzhiyun } 6609*4882a593Smuzhiyun 6610*4882a593Smuzhiyun# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi 6611*4882a593Smuzhiyun if ($realfile !~ m@^include/uapi/@ && 6612*4882a593Smuzhiyun $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { 6613*4882a593Smuzhiyun my $ull = ""; 6614*4882a593Smuzhiyun $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); 6615*4882a593Smuzhiyun if (CHK("BIT_MACRO", 6616*4882a593Smuzhiyun "Prefer using the BIT$ull macro\n" . $herecurr) && 6617*4882a593Smuzhiyun $fix) { 6618*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; 6619*4882a593Smuzhiyun } 6620*4882a593Smuzhiyun } 6621*4882a593Smuzhiyun 6622*4882a593Smuzhiyun# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too) 6623*4882a593Smuzhiyun if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) { 6624*4882a593Smuzhiyun WARN("IS_ENABLED_CONFIG", 6625*4882a593Smuzhiyun "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); 6626*4882a593Smuzhiyun } 6627*4882a593Smuzhiyun 6628*4882a593Smuzhiyun# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE 6629*4882a593Smuzhiyun if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { 6630*4882a593Smuzhiyun my $config = $1; 6631*4882a593Smuzhiyun if (WARN("PREFER_IS_ENABLED", 6632*4882a593Smuzhiyun "Prefer IS_ENABLED(<FOO>) to ${CONFIG_}<FOO> || ${CONFIG_}<FOO>_MODULE\n" . $herecurr) && 6633*4882a593Smuzhiyun $fix) { 6634*4882a593Smuzhiyun $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)"; 6635*4882a593Smuzhiyun } 6636*4882a593Smuzhiyun } 6637*4882a593Smuzhiyun 6638*4882a593Smuzhiyun# check for /* fallthrough */ like comment, prefer fallthrough; 6639*4882a593Smuzhiyun my @fallthroughs = ( 6640*4882a593Smuzhiyun 'fallthrough', 6641*4882a593Smuzhiyun '@fallthrough@', 6642*4882a593Smuzhiyun 'lint -fallthrough[ \t]*', 6643*4882a593Smuzhiyun 'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)', 6644*4882a593Smuzhiyun '(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?', 6645*4882a593Smuzhiyun 'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?', 6646*4882a593Smuzhiyun 'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?', 6647*4882a593Smuzhiyun ); 6648*4882a593Smuzhiyun if ($raw_comment ne '') { 6649*4882a593Smuzhiyun foreach my $ft (@fallthroughs) { 6650*4882a593Smuzhiyun if ($raw_comment =~ /$ft/) { 6651*4882a593Smuzhiyun my $msg_level = \&WARN; 6652*4882a593Smuzhiyun $msg_level = \&CHK if ($file); 6653*4882a593Smuzhiyun &{$msg_level}("PREFER_FALLTHROUGH", 6654*4882a593Smuzhiyun "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr); 6655*4882a593Smuzhiyun last; 6656*4882a593Smuzhiyun } 6657*4882a593Smuzhiyun } 6658*4882a593Smuzhiyun } 6659*4882a593Smuzhiyun 6660*4882a593Smuzhiyun# check for switch/default statements without a break; 6661*4882a593Smuzhiyun if ($perl_version_ok && 6662*4882a593Smuzhiyun defined $stat && 6663*4882a593Smuzhiyun $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { 6664*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 6665*4882a593Smuzhiyun my $herectx = get_stat_here($linenr, $cnt, $here); 6666*4882a593Smuzhiyun 6667*4882a593Smuzhiyun WARN("DEFAULT_NO_BREAK", 6668*4882a593Smuzhiyun "switch default: should use break\n" . $herectx); 6669*4882a593Smuzhiyun } 6670*4882a593Smuzhiyun 6671*4882a593Smuzhiyun# check for gcc specific __FUNCTION__ 6672*4882a593Smuzhiyun if ($line =~ /\b__FUNCTION__\b/) { 6673*4882a593Smuzhiyun if (WARN("USE_FUNC", 6674*4882a593Smuzhiyun "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && 6675*4882a593Smuzhiyun $fix) { 6676*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; 6677*4882a593Smuzhiyun } 6678*4882a593Smuzhiyun } 6679*4882a593Smuzhiyun 6680*4882a593Smuzhiyun# check for uses of __DATE__, __TIME__, __TIMESTAMP__ 6681*4882a593Smuzhiyun while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { 6682*4882a593Smuzhiyun ERROR("DATE_TIME", 6683*4882a593Smuzhiyun "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); 6684*4882a593Smuzhiyun } 6685*4882a593Smuzhiyun 6686*4882a593Smuzhiyun# check for use of yield() 6687*4882a593Smuzhiyun if ($line =~ /\byield\s*\(\s*\)/) { 6688*4882a593Smuzhiyun WARN("YIELD", 6689*4882a593Smuzhiyun "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); 6690*4882a593Smuzhiyun } 6691*4882a593Smuzhiyun 6692*4882a593Smuzhiyun# check for comparisons against true and false 6693*4882a593Smuzhiyun if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { 6694*4882a593Smuzhiyun my $lead = $1; 6695*4882a593Smuzhiyun my $arg = $2; 6696*4882a593Smuzhiyun my $test = $3; 6697*4882a593Smuzhiyun my $otype = $4; 6698*4882a593Smuzhiyun my $trail = $5; 6699*4882a593Smuzhiyun my $op = "!"; 6700*4882a593Smuzhiyun 6701*4882a593Smuzhiyun ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); 6702*4882a593Smuzhiyun 6703*4882a593Smuzhiyun my $type = lc($otype); 6704*4882a593Smuzhiyun if ($type =~ /^(?:true|false)$/) { 6705*4882a593Smuzhiyun if (("$test" eq "==" && "$type" eq "true") || 6706*4882a593Smuzhiyun ("$test" eq "!=" && "$type" eq "false")) { 6707*4882a593Smuzhiyun $op = ""; 6708*4882a593Smuzhiyun } 6709*4882a593Smuzhiyun 6710*4882a593Smuzhiyun CHK("BOOL_COMPARISON", 6711*4882a593Smuzhiyun "Using comparison to $otype is error prone\n" . $herecurr); 6712*4882a593Smuzhiyun 6713*4882a593Smuzhiyun## maybe suggesting a correct construct would better 6714*4882a593Smuzhiyun## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); 6715*4882a593Smuzhiyun 6716*4882a593Smuzhiyun } 6717*4882a593Smuzhiyun } 6718*4882a593Smuzhiyun 6719*4882a593Smuzhiyun# check for semaphores initialized locked 6720*4882a593Smuzhiyun if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { 6721*4882a593Smuzhiyun WARN("CONSIDER_COMPLETION", 6722*4882a593Smuzhiyun "consider using a completion\n" . $herecurr); 6723*4882a593Smuzhiyun } 6724*4882a593Smuzhiyun 6725*4882a593Smuzhiyun# recommend kstrto* over simple_strto* and strict_strto* 6726*4882a593Smuzhiyun if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { 6727*4882a593Smuzhiyun WARN("CONSIDER_KSTRTO", 6728*4882a593Smuzhiyun "$1 is obsolete, use k$3 instead\n" . $herecurr); 6729*4882a593Smuzhiyun } 6730*4882a593Smuzhiyun 6731*4882a593Smuzhiyun# check for __initcall(), use device_initcall() explicitly or more appropriate function please 6732*4882a593Smuzhiyun if ($line =~ /^.\s*__initcall\s*\(/) { 6733*4882a593Smuzhiyun WARN("USE_DEVICE_INITCALL", 6734*4882a593Smuzhiyun "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); 6735*4882a593Smuzhiyun } 6736*4882a593Smuzhiyun 6737*4882a593Smuzhiyun# check for spin_is_locked(), suggest lockdep instead 6738*4882a593Smuzhiyun if ($line =~ /\bspin_is_locked\(/) { 6739*4882a593Smuzhiyun WARN("USE_LOCKDEP", 6740*4882a593Smuzhiyun "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr); 6741*4882a593Smuzhiyun } 6742*4882a593Smuzhiyun 6743*4882a593Smuzhiyun# check for deprecated apis 6744*4882a593Smuzhiyun if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) { 6745*4882a593Smuzhiyun my $deprecated_api = $1; 6746*4882a593Smuzhiyun my $new_api = $deprecated_apis{$deprecated_api}; 6747*4882a593Smuzhiyun WARN("DEPRECATED_API", 6748*4882a593Smuzhiyun "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr); 6749*4882a593Smuzhiyun } 6750*4882a593Smuzhiyun 6751*4882a593Smuzhiyun# check for various structs that are normally const (ops, kgdb, device_tree) 6752*4882a593Smuzhiyun# and avoid what seem like struct definitions 'struct foo {' 6753*4882a593Smuzhiyun if (defined($const_structs) && 6754*4882a593Smuzhiyun $line !~ /\bconst\b/ && 6755*4882a593Smuzhiyun $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) { 6756*4882a593Smuzhiyun WARN("CONST_STRUCT", 6757*4882a593Smuzhiyun "struct $1 should normally be const\n" . $herecurr); 6758*4882a593Smuzhiyun } 6759*4882a593Smuzhiyun 6760*4882a593Smuzhiyun# use of NR_CPUS is usually wrong 6761*4882a593Smuzhiyun# ignore definitions of NR_CPUS and usage to define arrays as likely right 6762*4882a593Smuzhiyun if ($line =~ /\bNR_CPUS\b/ && 6763*4882a593Smuzhiyun $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && 6764*4882a593Smuzhiyun $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && 6765*4882a593Smuzhiyun $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && 6766*4882a593Smuzhiyun $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && 6767*4882a593Smuzhiyun $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) 6768*4882a593Smuzhiyun { 6769*4882a593Smuzhiyun WARN("NR_CPUS", 6770*4882a593Smuzhiyun "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); 6771*4882a593Smuzhiyun } 6772*4882a593Smuzhiyun 6773*4882a593Smuzhiyun# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. 6774*4882a593Smuzhiyun if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { 6775*4882a593Smuzhiyun ERROR("DEFINE_ARCH_HAS", 6776*4882a593Smuzhiyun "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); 6777*4882a593Smuzhiyun } 6778*4882a593Smuzhiyun 6779*4882a593Smuzhiyun# likely/unlikely comparisons similar to "(likely(foo) > 0)" 6780*4882a593Smuzhiyun if ($perl_version_ok && 6781*4882a593Smuzhiyun $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { 6782*4882a593Smuzhiyun WARN("LIKELY_MISUSE", 6783*4882a593Smuzhiyun "Using $1 should generally have parentheses around the comparison\n" . $herecurr); 6784*4882a593Smuzhiyun } 6785*4882a593Smuzhiyun 6786*4882a593Smuzhiyun# nested likely/unlikely calls 6787*4882a593Smuzhiyun if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) { 6788*4882a593Smuzhiyun WARN("LIKELY_MISUSE", 6789*4882a593Smuzhiyun "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr); 6790*4882a593Smuzhiyun } 6791*4882a593Smuzhiyun 6792*4882a593Smuzhiyun# whine mightly about in_atomic 6793*4882a593Smuzhiyun if ($line =~ /\bin_atomic\s*\(/) { 6794*4882a593Smuzhiyun if ($realfile =~ m@^drivers/@) { 6795*4882a593Smuzhiyun ERROR("IN_ATOMIC", 6796*4882a593Smuzhiyun "do not use in_atomic in drivers\n" . $herecurr); 6797*4882a593Smuzhiyun } elsif ($realfile !~ m@^kernel/@) { 6798*4882a593Smuzhiyun WARN("IN_ATOMIC", 6799*4882a593Smuzhiyun "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); 6800*4882a593Smuzhiyun } 6801*4882a593Smuzhiyun } 6802*4882a593Smuzhiyun 6803*4882a593Smuzhiyun# check for mutex_trylock_recursive usage 6804*4882a593Smuzhiyun if ($line =~ /mutex_trylock_recursive/) { 6805*4882a593Smuzhiyun ERROR("LOCKING", 6806*4882a593Smuzhiyun "recursive locking is bad, do not use this ever.\n" . $herecurr); 6807*4882a593Smuzhiyun } 6808*4882a593Smuzhiyun 6809*4882a593Smuzhiyun# check for lockdep_set_novalidate_class 6810*4882a593Smuzhiyun if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || 6811*4882a593Smuzhiyun $line =~ /__lockdep_no_validate__\s*\)/ ) { 6812*4882a593Smuzhiyun if ($realfile !~ m@^kernel/lockdep@ && 6813*4882a593Smuzhiyun $realfile !~ m@^include/linux/lockdep@ && 6814*4882a593Smuzhiyun $realfile !~ m@^drivers/base/core@) { 6815*4882a593Smuzhiyun ERROR("LOCKDEP", 6816*4882a593Smuzhiyun "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); 6817*4882a593Smuzhiyun } 6818*4882a593Smuzhiyun } 6819*4882a593Smuzhiyun 6820*4882a593Smuzhiyun if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || 6821*4882a593Smuzhiyun $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { 6822*4882a593Smuzhiyun WARN("EXPORTED_WORLD_WRITABLE", 6823*4882a593Smuzhiyun "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); 6824*4882a593Smuzhiyun } 6825*4882a593Smuzhiyun 6826*4882a593Smuzhiyun# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO> 6827*4882a593Smuzhiyun# and whether or not function naming is typical and if 6828*4882a593Smuzhiyun# DEVICE_ATTR permissions uses are unusual too 6829*4882a593Smuzhiyun if ($perl_version_ok && 6830*4882a593Smuzhiyun defined $stat && 6831*4882a593Smuzhiyun $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*\)/) { 6832*4882a593Smuzhiyun my $var = $1; 6833*4882a593Smuzhiyun my $perms = $2; 6834*4882a593Smuzhiyun my $show = $3; 6835*4882a593Smuzhiyun my $store = $4; 6836*4882a593Smuzhiyun my $octal_perms = perms_to_octal($perms); 6837*4882a593Smuzhiyun if ($show =~ /^${var}_show$/ && 6838*4882a593Smuzhiyun $store =~ /^${var}_store$/ && 6839*4882a593Smuzhiyun $octal_perms eq "0644") { 6840*4882a593Smuzhiyun if (WARN("DEVICE_ATTR_RW", 6841*4882a593Smuzhiyun "Use DEVICE_ATTR_RW\n" . $herecurr) && 6842*4882a593Smuzhiyun $fix) { 6843*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/; 6844*4882a593Smuzhiyun } 6845*4882a593Smuzhiyun } elsif ($show =~ /^${var}_show$/ && 6846*4882a593Smuzhiyun $store =~ /^NULL$/ && 6847*4882a593Smuzhiyun $octal_perms eq "0444") { 6848*4882a593Smuzhiyun if (WARN("DEVICE_ATTR_RO", 6849*4882a593Smuzhiyun "Use DEVICE_ATTR_RO\n" . $herecurr) && 6850*4882a593Smuzhiyun $fix) { 6851*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/; 6852*4882a593Smuzhiyun } 6853*4882a593Smuzhiyun } elsif ($show =~ /^NULL$/ && 6854*4882a593Smuzhiyun $store =~ /^${var}_store$/ && 6855*4882a593Smuzhiyun $octal_perms eq "0200") { 6856*4882a593Smuzhiyun if (WARN("DEVICE_ATTR_WO", 6857*4882a593Smuzhiyun "Use DEVICE_ATTR_WO\n" . $herecurr) && 6858*4882a593Smuzhiyun $fix) { 6859*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/; 6860*4882a593Smuzhiyun } 6861*4882a593Smuzhiyun } elsif ($octal_perms eq "0644" || 6862*4882a593Smuzhiyun $octal_perms eq "0444" || 6863*4882a593Smuzhiyun $octal_perms eq "0200") { 6864*4882a593Smuzhiyun my $newshow = "$show"; 6865*4882a593Smuzhiyun $newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show"); 6866*4882a593Smuzhiyun my $newstore = $store; 6867*4882a593Smuzhiyun $newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store"); 6868*4882a593Smuzhiyun my $rename = ""; 6869*4882a593Smuzhiyun if ($show ne $newshow) { 6870*4882a593Smuzhiyun $rename .= " '$show' to '$newshow'"; 6871*4882a593Smuzhiyun } 6872*4882a593Smuzhiyun if ($store ne $newstore) { 6873*4882a593Smuzhiyun $rename .= " '$store' to '$newstore'"; 6874*4882a593Smuzhiyun } 6875*4882a593Smuzhiyun WARN("DEVICE_ATTR_FUNCTIONS", 6876*4882a593Smuzhiyun "Consider renaming function(s)$rename\n" . $herecurr); 6877*4882a593Smuzhiyun } else { 6878*4882a593Smuzhiyun WARN("DEVICE_ATTR_PERMS", 6879*4882a593Smuzhiyun "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr); 6880*4882a593Smuzhiyun } 6881*4882a593Smuzhiyun } 6882*4882a593Smuzhiyun 6883*4882a593Smuzhiyun# Mode permission misuses where it seems decimal should be octal 6884*4882a593Smuzhiyun# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop 6885*4882a593Smuzhiyun# o Ignore module_param*(...) uses with a decimal 0 permission as that has a 6886*4882a593Smuzhiyun# specific definition of not visible in sysfs. 6887*4882a593Smuzhiyun# o Ignore proc_create*(...) uses with a decimal 0 permission as that means 6888*4882a593Smuzhiyun# use the default permissions 6889*4882a593Smuzhiyun if ($perl_version_ok && 6890*4882a593Smuzhiyun defined $stat && 6891*4882a593Smuzhiyun $line =~ /$mode_perms_search/) { 6892*4882a593Smuzhiyun foreach my $entry (@mode_permission_funcs) { 6893*4882a593Smuzhiyun my $func = $entry->[0]; 6894*4882a593Smuzhiyun my $arg_pos = $entry->[1]; 6895*4882a593Smuzhiyun 6896*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 6897*4882a593Smuzhiyun $lc = $lc + $linenr; 6898*4882a593Smuzhiyun my $stat_real = get_stat_real($linenr, $lc); 6899*4882a593Smuzhiyun 6900*4882a593Smuzhiyun my $skip_args = ""; 6901*4882a593Smuzhiyun if ($arg_pos > 1) { 6902*4882a593Smuzhiyun $arg_pos--; 6903*4882a593Smuzhiyun $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; 6904*4882a593Smuzhiyun } 6905*4882a593Smuzhiyun my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]"; 6906*4882a593Smuzhiyun if ($stat =~ /$test/) { 6907*4882a593Smuzhiyun my $val = $1; 6908*4882a593Smuzhiyun $val = $6 if ($skip_args ne ""); 6909*4882a593Smuzhiyun if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") && 6910*4882a593Smuzhiyun (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || 6911*4882a593Smuzhiyun ($val =~ /^$Octal$/ && length($val) ne 4))) { 6912*4882a593Smuzhiyun ERROR("NON_OCTAL_PERMISSIONS", 6913*4882a593Smuzhiyun "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real); 6914*4882a593Smuzhiyun } 6915*4882a593Smuzhiyun if ($val =~ /^$Octal$/ && (oct($val) & 02)) { 6916*4882a593Smuzhiyun ERROR("EXPORTED_WORLD_WRITABLE", 6917*4882a593Smuzhiyun "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real); 6918*4882a593Smuzhiyun } 6919*4882a593Smuzhiyun } 6920*4882a593Smuzhiyun } 6921*4882a593Smuzhiyun } 6922*4882a593Smuzhiyun 6923*4882a593Smuzhiyun# check for uses of S_<PERMS> that could be octal for readability 6924*4882a593Smuzhiyun while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) { 6925*4882a593Smuzhiyun my $oval = $1; 6926*4882a593Smuzhiyun my $octal = perms_to_octal($oval); 6927*4882a593Smuzhiyun if (WARN("SYMBOLIC_PERMS", 6928*4882a593Smuzhiyun "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) && 6929*4882a593Smuzhiyun $fix) { 6930*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/; 6931*4882a593Smuzhiyun } 6932*4882a593Smuzhiyun } 6933*4882a593Smuzhiyun 6934*4882a593Smuzhiyun# validate content of MODULE_LICENSE against list from include/linux/module.h 6935*4882a593Smuzhiyun if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { 6936*4882a593Smuzhiyun my $extracted_string = get_quoted_string($line, $rawline); 6937*4882a593Smuzhiyun my $valid_licenses = qr{ 6938*4882a593Smuzhiyun GPL| 6939*4882a593Smuzhiyun GPL\ v2| 6940*4882a593Smuzhiyun GPL\ and\ additional\ rights| 6941*4882a593Smuzhiyun Dual\ BSD/GPL| 6942*4882a593Smuzhiyun Dual\ MIT/GPL| 6943*4882a593Smuzhiyun Dual\ MPL/GPL| 6944*4882a593Smuzhiyun Proprietary 6945*4882a593Smuzhiyun }x; 6946*4882a593Smuzhiyun if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { 6947*4882a593Smuzhiyun WARN("MODULE_LICENSE", 6948*4882a593Smuzhiyun "unknown module license " . $extracted_string . "\n" . $herecurr); 6949*4882a593Smuzhiyun } 6950*4882a593Smuzhiyun } 6951*4882a593Smuzhiyun 6952*4882a593Smuzhiyun# check for sysctl duplicate constants 6953*4882a593Smuzhiyun if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) { 6954*4882a593Smuzhiyun WARN("DUPLICATED_SYSCTL_CONST", 6955*4882a593Smuzhiyun "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr); 6956*4882a593Smuzhiyun } 6957*4882a593Smuzhiyun } 6958*4882a593Smuzhiyun 6959*4882a593Smuzhiyun # If we have no input at all, then there is nothing to report on 6960*4882a593Smuzhiyun # so just keep quiet. 6961*4882a593Smuzhiyun if ($#rawlines == -1) { 6962*4882a593Smuzhiyun exit(0); 6963*4882a593Smuzhiyun } 6964*4882a593Smuzhiyun 6965*4882a593Smuzhiyun # In mailback mode only produce a report in the negative, for 6966*4882a593Smuzhiyun # things that appear to be patches. 6967*4882a593Smuzhiyun if ($mailback && ($clean == 1 || !$is_patch)) { 6968*4882a593Smuzhiyun exit(0); 6969*4882a593Smuzhiyun } 6970*4882a593Smuzhiyun 6971*4882a593Smuzhiyun # This is not a patch, and we are are in 'no-patch' mode so 6972*4882a593Smuzhiyun # just keep quiet. 6973*4882a593Smuzhiyun if (!$chk_patch && !$is_patch) { 6974*4882a593Smuzhiyun exit(0); 6975*4882a593Smuzhiyun } 6976*4882a593Smuzhiyun 6977*4882a593Smuzhiyun if (!$is_patch && $filename !~ /cover-letter\.patch$/) { 6978*4882a593Smuzhiyun ERROR("NOT_UNIFIED_DIFF", 6979*4882a593Smuzhiyun "Does not appear to be a unified-diff format patch\n"); 6980*4882a593Smuzhiyun } 6981*4882a593Smuzhiyun if ($is_patch && $has_commit_log && $chk_signoff) { 6982*4882a593Smuzhiyun if ($signoff == 0) { 6983*4882a593Smuzhiyun ERROR("MISSING_SIGN_OFF", 6984*4882a593Smuzhiyun "Missing Signed-off-by: line(s)\n"); 6985*4882a593Smuzhiyun } elsif ($authorsignoff != 1) { 6986*4882a593Smuzhiyun # authorsignoff values: 6987*4882a593Smuzhiyun # 0 -> missing sign off 6988*4882a593Smuzhiyun # 1 -> sign off identical 6989*4882a593Smuzhiyun # 2 -> names and addresses match, comments mismatch 6990*4882a593Smuzhiyun # 3 -> addresses match, names different 6991*4882a593Smuzhiyun # 4 -> names match, addresses different 6992*4882a593Smuzhiyun # 5 -> names match, addresses excluding subaddress details (refer RFC 5233) match 6993*4882a593Smuzhiyun 6994*4882a593Smuzhiyun my $sob_msg = "'From: $author' != 'Signed-off-by: $author_sob'"; 6995*4882a593Smuzhiyun 6996*4882a593Smuzhiyun if ($authorsignoff == 0) { 6997*4882a593Smuzhiyun ERROR("NO_AUTHOR_SIGN_OFF", 6998*4882a593Smuzhiyun "Missing Signed-off-by: line by nominal patch author '$author'\n"); 6999*4882a593Smuzhiyun } elsif ($authorsignoff == 2) { 7000*4882a593Smuzhiyun CHK("FROM_SIGN_OFF_MISMATCH", 7001*4882a593Smuzhiyun "From:/Signed-off-by: email comments mismatch: $sob_msg\n"); 7002*4882a593Smuzhiyun } elsif ($authorsignoff == 3) { 7003*4882a593Smuzhiyun WARN("FROM_SIGN_OFF_MISMATCH", 7004*4882a593Smuzhiyun "From:/Signed-off-by: email name mismatch: $sob_msg\n"); 7005*4882a593Smuzhiyun } elsif ($authorsignoff == 4) { 7006*4882a593Smuzhiyun WARN("FROM_SIGN_OFF_MISMATCH", 7007*4882a593Smuzhiyun "From:/Signed-off-by: email address mismatch: $sob_msg\n"); 7008*4882a593Smuzhiyun } elsif ($authorsignoff == 5) { 7009*4882a593Smuzhiyun WARN("FROM_SIGN_OFF_MISMATCH", 7010*4882a593Smuzhiyun "From:/Signed-off-by: email subaddress mismatch: $sob_msg\n"); 7011*4882a593Smuzhiyun } 7012*4882a593Smuzhiyun } 7013*4882a593Smuzhiyun } 7014*4882a593Smuzhiyun 7015*4882a593Smuzhiyun print report_dump(); 7016*4882a593Smuzhiyun if ($summary && !($clean == 1 && $quiet == 1)) { 7017*4882a593Smuzhiyun print "$filename " if ($summary_file); 7018*4882a593Smuzhiyun print "total: $cnt_error errors, $cnt_warn warnings, " . 7019*4882a593Smuzhiyun (($check)? "$cnt_chk checks, " : "") . 7020*4882a593Smuzhiyun "$cnt_lines lines checked\n"; 7021*4882a593Smuzhiyun } 7022*4882a593Smuzhiyun 7023*4882a593Smuzhiyun if ($quiet == 0) { 7024*4882a593Smuzhiyun # If there were any defects found and not already fixing them 7025*4882a593Smuzhiyun if (!$clean and !$fix) { 7026*4882a593Smuzhiyun print << "EOM" 7027*4882a593Smuzhiyun 7028*4882a593SmuzhiyunNOTE: For some of the reported defects, checkpatch may be able to 7029*4882a593Smuzhiyun mechanically convert to the typical style using --fix or --fix-inplace. 7030*4882a593SmuzhiyunEOM 7031*4882a593Smuzhiyun } 7032*4882a593Smuzhiyun # If there were whitespace errors which cleanpatch can fix 7033*4882a593Smuzhiyun # then suggest that. 7034*4882a593Smuzhiyun if ($rpt_cleaners) { 7035*4882a593Smuzhiyun $rpt_cleaners = 0; 7036*4882a593Smuzhiyun print << "EOM" 7037*4882a593Smuzhiyun 7038*4882a593SmuzhiyunNOTE: Whitespace errors detected. 7039*4882a593Smuzhiyun You may wish to use scripts/cleanpatch or scripts/cleanfile 7040*4882a593SmuzhiyunEOM 7041*4882a593Smuzhiyun } 7042*4882a593Smuzhiyun } 7043*4882a593Smuzhiyun 7044*4882a593Smuzhiyun if ($clean == 0 && $fix && 7045*4882a593Smuzhiyun ("@rawlines" ne "@fixed" || 7046*4882a593Smuzhiyun $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { 7047*4882a593Smuzhiyun my $newfile = $filename; 7048*4882a593Smuzhiyun $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); 7049*4882a593Smuzhiyun my $linecount = 0; 7050*4882a593Smuzhiyun my $f; 7051*4882a593Smuzhiyun 7052*4882a593Smuzhiyun @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); 7053*4882a593Smuzhiyun 7054*4882a593Smuzhiyun open($f, '>', $newfile) 7055*4882a593Smuzhiyun or die "$P: Can't open $newfile for write\n"; 7056*4882a593Smuzhiyun foreach my $fixed_line (@fixed) { 7057*4882a593Smuzhiyun $linecount++; 7058*4882a593Smuzhiyun if ($file) { 7059*4882a593Smuzhiyun if ($linecount > 3) { 7060*4882a593Smuzhiyun $fixed_line =~ s/^\+//; 7061*4882a593Smuzhiyun print $f $fixed_line . "\n"; 7062*4882a593Smuzhiyun } 7063*4882a593Smuzhiyun } else { 7064*4882a593Smuzhiyun print $f $fixed_line . "\n"; 7065*4882a593Smuzhiyun } 7066*4882a593Smuzhiyun } 7067*4882a593Smuzhiyun close($f); 7068*4882a593Smuzhiyun 7069*4882a593Smuzhiyun if (!$quiet) { 7070*4882a593Smuzhiyun print << "EOM"; 7071*4882a593Smuzhiyun 7072*4882a593SmuzhiyunWrote EXPERIMENTAL --fix correction(s) to '$newfile' 7073*4882a593Smuzhiyun 7074*4882a593SmuzhiyunDo _NOT_ trust the results written to this file. 7075*4882a593SmuzhiyunDo _NOT_ submit these changes without inspecting them for correctness. 7076*4882a593Smuzhiyun 7077*4882a593SmuzhiyunThis EXPERIMENTAL file is simply a convenience to help rewrite patches. 7078*4882a593SmuzhiyunNo warranties, expressed or implied... 7079*4882a593SmuzhiyunEOM 7080*4882a593Smuzhiyun } 7081*4882a593Smuzhiyun } 7082*4882a593Smuzhiyun 7083*4882a593Smuzhiyun if ($quiet == 0) { 7084*4882a593Smuzhiyun print "\n"; 7085*4882a593Smuzhiyun if ($clean == 1) { 7086*4882a593Smuzhiyun print "$vname has no obvious style problems and is ready for submission.\n"; 7087*4882a593Smuzhiyun } else { 7088*4882a593Smuzhiyun print "$vname has style problems, please review.\n"; 7089*4882a593Smuzhiyun } 7090*4882a593Smuzhiyun } 7091*4882a593Smuzhiyun return $clean; 7092*4882a593Smuzhiyun} 7093