1*4882a593Smuzhiyun#!/usr/bin/env perl 2*4882a593Smuzhiyun# (c) 2001, Dave Jones. (the file handling bit) 3*4882a593Smuzhiyun# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) 4*4882a593Smuzhiyun# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) 5*4882a593Smuzhiyun# (c) 2008-2010 Andy Whitcroft <apw@canonical.com> 6*4882a593Smuzhiyun# Licensed under the terms of the GNU GPL License version 2 7*4882a593Smuzhiyun 8*4882a593Smuzhiyunuse strict; 9*4882a593Smuzhiyunuse warnings; 10*4882a593Smuzhiyunuse POSIX; 11*4882a593Smuzhiyunuse File::Basename; 12*4882a593Smuzhiyunuse Cwd 'abs_path'; 13*4882a593Smuzhiyunuse Term::ANSIColor qw(:constants); 14*4882a593Smuzhiyun 15*4882a593Smuzhiyunmy $P = $0; 16*4882a593Smuzhiyunmy $D = dirname(abs_path($P)); 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunmy $V = '0.32'; 19*4882a593Smuzhiyun 20*4882a593Smuzhiyunuse Getopt::Long qw(:config no_auto_abbrev); 21*4882a593Smuzhiyun 22*4882a593Smuzhiyunmy $quiet = 0; 23*4882a593Smuzhiyunmy $tree = 1; 24*4882a593Smuzhiyunmy $chk_signoff = 1; 25*4882a593Smuzhiyunmy $chk_patch = 1; 26*4882a593Smuzhiyunmy $tst_only; 27*4882a593Smuzhiyunmy $emacs = 0; 28*4882a593Smuzhiyunmy $terse = 0; 29*4882a593Smuzhiyunmy $showfile = 0; 30*4882a593Smuzhiyunmy $file = 0; 31*4882a593Smuzhiyunmy $git = 0; 32*4882a593Smuzhiyunmy %git_commits = (); 33*4882a593Smuzhiyunmy $check = 0; 34*4882a593Smuzhiyunmy $check_orig = 0; 35*4882a593Smuzhiyunmy $summary = 1; 36*4882a593Smuzhiyunmy $mailback = 0; 37*4882a593Smuzhiyunmy $summary_file = 0; 38*4882a593Smuzhiyunmy $show_types = 0; 39*4882a593Smuzhiyunmy $list_types = 0; 40*4882a593Smuzhiyunmy $fix = 0; 41*4882a593Smuzhiyunmy $fix_inplace = 0; 42*4882a593Smuzhiyunmy $root; 43*4882a593Smuzhiyunmy %debug; 44*4882a593Smuzhiyunmy %camelcase = (); 45*4882a593Smuzhiyunmy %use_type = (); 46*4882a593Smuzhiyunmy @use = (); 47*4882a593Smuzhiyunmy %ignore_type = (); 48*4882a593Smuzhiyunmy @ignore = (); 49*4882a593Smuzhiyunmy $help = 0; 50*4882a593Smuzhiyunmy $configuration_file = ".checkpatch.conf"; 51*4882a593Smuzhiyunmy $max_line_length = 80; 52*4882a593Smuzhiyunmy $ignore_perl_version = 0; 53*4882a593Smuzhiyunmy $minimum_perl_version = 5.10.0; 54*4882a593Smuzhiyunmy $min_conf_desc_length = 4; 55*4882a593Smuzhiyunmy $spelling_file = "$D/spelling.txt"; 56*4882a593Smuzhiyunmy $codespell = 0; 57*4882a593Smuzhiyunmy $codespellfile = "/usr/share/codespell/dictionary.txt"; 58*4882a593Smuzhiyunmy $conststructsfile = "$D/const_structs.checkpatch"; 59*4882a593Smuzhiyunmy $typedefsfile = ""; 60*4882a593Smuzhiyunmy $color = "auto"; 61*4882a593Smuzhiyunmy $allow_c99_comments = 1; 62*4882a593Smuzhiyun 63*4882a593Smuzhiyunsub help { 64*4882a593Smuzhiyun my ($exitcode) = @_; 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun print << "EOM"; 67*4882a593SmuzhiyunUsage: $P [OPTION]... [FILE]... 68*4882a593SmuzhiyunVersion: $V 69*4882a593Smuzhiyun 70*4882a593SmuzhiyunOptions: 71*4882a593Smuzhiyun -q, --quiet quiet 72*4882a593Smuzhiyun --no-tree run without a kernel tree 73*4882a593Smuzhiyun --no-signoff do not check for 'Signed-off-by' line 74*4882a593Smuzhiyun --patch treat FILE as patchfile (default) 75*4882a593Smuzhiyun --emacs emacs compile window format 76*4882a593Smuzhiyun --terse one line per report 77*4882a593Smuzhiyun --showfile emit diffed file position, not input file position 78*4882a593Smuzhiyun -g, --git treat FILE as a single commit or git revision range 79*4882a593Smuzhiyun single git commit with: 80*4882a593Smuzhiyun <rev> 81*4882a593Smuzhiyun <rev>^ 82*4882a593Smuzhiyun <rev>~n 83*4882a593Smuzhiyun multiple git commits with: 84*4882a593Smuzhiyun <rev1>..<rev2> 85*4882a593Smuzhiyun <rev1>...<rev2> 86*4882a593Smuzhiyun <rev>-<count> 87*4882a593Smuzhiyun git merges are ignored 88*4882a593Smuzhiyun -f, --file treat FILE as regular source file 89*4882a593Smuzhiyun --subjective, --strict enable more subjective tests 90*4882a593Smuzhiyun --list-types list the possible message types 91*4882a593Smuzhiyun --types TYPE(,TYPE2...) show only these comma separated message types 92*4882a593Smuzhiyun --ignore TYPE(,TYPE2...) ignore various comma separated message types 93*4882a593Smuzhiyun --show-types show the specific message type in the output 94*4882a593Smuzhiyun --max-line-length=n set the maximum line length, if exceeded, warn 95*4882a593Smuzhiyun --min-conf-desc-length=n set the min description length, if shorter, warn 96*4882a593Smuzhiyun --root=PATH PATH to the kernel tree root 97*4882a593Smuzhiyun --no-summary suppress the per-file summary 98*4882a593Smuzhiyun --mailback only produce a report in case of warnings/errors 99*4882a593Smuzhiyun --summary-file include the filename in summary 100*4882a593Smuzhiyun --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of 101*4882a593Smuzhiyun 'values', 'possible', 'type', and 'attr' (default 102*4882a593Smuzhiyun is all off) 103*4882a593Smuzhiyun --test-only=WORD report only warnings/errors containing WORD 104*4882a593Smuzhiyun literally 105*4882a593Smuzhiyun --fix EXPERIMENTAL - may create horrible results 106*4882a593Smuzhiyun If correctable single-line errors exist, create 107*4882a593Smuzhiyun "<inputfile>.EXPERIMENTAL-checkpatch-fixes" 108*4882a593Smuzhiyun with potential errors corrected to the preferred 109*4882a593Smuzhiyun checkpatch style 110*4882a593Smuzhiyun --fix-inplace EXPERIMENTAL - may create horrible results 111*4882a593Smuzhiyun Is the same as --fix, but overwrites the input 112*4882a593Smuzhiyun file. It's your fault if there's no backup or git 113*4882a593Smuzhiyun --ignore-perl-version override checking of perl version. expect 114*4882a593Smuzhiyun runtime errors. 115*4882a593Smuzhiyun --codespell Use the codespell dictionary for spelling/typos 116*4882a593Smuzhiyun (default:/usr/share/codespell/dictionary.txt) 117*4882a593Smuzhiyun --codespellfile Use this codespell dictionary 118*4882a593Smuzhiyun --typedefsfile Read additional types from this file 119*4882a593Smuzhiyun --color[=WHEN] Use colors 'always', 'never', or only when output 120*4882a593Smuzhiyun is a terminal ('auto'). Default is 'auto'. 121*4882a593Smuzhiyun -h, --help, --version display this help and exit 122*4882a593Smuzhiyun 123*4882a593SmuzhiyunWhen FILE is - read standard input. 124*4882a593SmuzhiyunEOM 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun exit($exitcode); 127*4882a593Smuzhiyun} 128*4882a593Smuzhiyun 129*4882a593Smuzhiyunsub uniq { 130*4882a593Smuzhiyun my %seen; 131*4882a593Smuzhiyun return grep { !$seen{$_}++ } @_; 132*4882a593Smuzhiyun} 133*4882a593Smuzhiyun 134*4882a593Smuzhiyunsub list_types { 135*4882a593Smuzhiyun my ($exitcode) = @_; 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun my $count = 0; 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun local $/ = undef; 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun open(my $script, '<', abs_path($P)) or 142*4882a593Smuzhiyun die "$P: Can't read '$P' $!\n"; 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun my $text = <$script>; 145*4882a593Smuzhiyun close($script); 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun my @types = (); 148*4882a593Smuzhiyun for ($text =~ /\b(?:(?:CHK|WARN|ERROR)\s*\(\s*"([^"]+)")/g) { 149*4882a593Smuzhiyun push (@types, $_); 150*4882a593Smuzhiyun } 151*4882a593Smuzhiyun @types = sort(uniq(@types)); 152*4882a593Smuzhiyun print("#\tMessage type\n\n"); 153*4882a593Smuzhiyun foreach my $type (@types) { 154*4882a593Smuzhiyun print(++$count . "\t" . $type . "\n"); 155*4882a593Smuzhiyun } 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun exit($exitcode); 158*4882a593Smuzhiyun} 159*4882a593Smuzhiyun 160*4882a593Smuzhiyunmy $conf = which_conf($configuration_file); 161*4882a593Smuzhiyunif (-f $conf) { 162*4882a593Smuzhiyun my @conf_args; 163*4882a593Smuzhiyun open(my $conffile, '<', "$conf") 164*4882a593Smuzhiyun or warn "$P: Can't find a readable $configuration_file file $!\n"; 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun while (<$conffile>) { 167*4882a593Smuzhiyun my $line = $_; 168*4882a593Smuzhiyun 169*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 170*4882a593Smuzhiyun $line =~ s/^\s*//g; 171*4882a593Smuzhiyun $line =~ s/\s+/ /g; 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 174*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun my @words = split(" ", $line); 177*4882a593Smuzhiyun foreach my $word (@words) { 178*4882a593Smuzhiyun last if ($word =~ m/^#/); 179*4882a593Smuzhiyun push (@conf_args, $word); 180*4882a593Smuzhiyun } 181*4882a593Smuzhiyun } 182*4882a593Smuzhiyun close($conffile); 183*4882a593Smuzhiyun unshift(@ARGV, @conf_args) if @conf_args; 184*4882a593Smuzhiyun} 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun# Perl's Getopt::Long allows options to take optional arguments after a space. 187*4882a593Smuzhiyun# Prevent --color by itself from consuming other arguments 188*4882a593Smuzhiyunforeach (@ARGV) { 189*4882a593Smuzhiyun if ($_ eq "--color" || $_ eq "-color") { 190*4882a593Smuzhiyun $_ = "--color=$color"; 191*4882a593Smuzhiyun } 192*4882a593Smuzhiyun} 193*4882a593Smuzhiyun 194*4882a593SmuzhiyunGetOptions( 195*4882a593Smuzhiyun 'q|quiet+' => \$quiet, 196*4882a593Smuzhiyun 'tree!' => \$tree, 197*4882a593Smuzhiyun 'signoff!' => \$chk_signoff, 198*4882a593Smuzhiyun 'patch!' => \$chk_patch, 199*4882a593Smuzhiyun 'emacs!' => \$emacs, 200*4882a593Smuzhiyun 'terse!' => \$terse, 201*4882a593Smuzhiyun 'showfile!' => \$showfile, 202*4882a593Smuzhiyun 'f|file!' => \$file, 203*4882a593Smuzhiyun 'g|git!' => \$git, 204*4882a593Smuzhiyun 'subjective!' => \$check, 205*4882a593Smuzhiyun 'strict!' => \$check, 206*4882a593Smuzhiyun 'ignore=s' => \@ignore, 207*4882a593Smuzhiyun 'types=s' => \@use, 208*4882a593Smuzhiyun 'show-types!' => \$show_types, 209*4882a593Smuzhiyun 'list-types!' => \$list_types, 210*4882a593Smuzhiyun 'max-line-length=i' => \$max_line_length, 211*4882a593Smuzhiyun 'min-conf-desc-length=i' => \$min_conf_desc_length, 212*4882a593Smuzhiyun 'root=s' => \$root, 213*4882a593Smuzhiyun 'summary!' => \$summary, 214*4882a593Smuzhiyun 'mailback!' => \$mailback, 215*4882a593Smuzhiyun 'summary-file!' => \$summary_file, 216*4882a593Smuzhiyun 'fix!' => \$fix, 217*4882a593Smuzhiyun 'fix-inplace!' => \$fix_inplace, 218*4882a593Smuzhiyun 'ignore-perl-version!' => \$ignore_perl_version, 219*4882a593Smuzhiyun 'debug=s' => \%debug, 220*4882a593Smuzhiyun 'test-only=s' => \$tst_only, 221*4882a593Smuzhiyun 'codespell!' => \$codespell, 222*4882a593Smuzhiyun 'codespellfile=s' => \$codespellfile, 223*4882a593Smuzhiyun 'typedefsfile=s' => \$typedefsfile, 224*4882a593Smuzhiyun 'color=s' => \$color, 225*4882a593Smuzhiyun 'no-color' => \$color, #keep old behaviors of -nocolor 226*4882a593Smuzhiyun 'nocolor' => \$color, #keep old behaviors of -nocolor 227*4882a593Smuzhiyun 'h|help' => \$help, 228*4882a593Smuzhiyun 'version' => \$help 229*4882a593Smuzhiyun) or help(1); 230*4882a593Smuzhiyun 231*4882a593Smuzhiyunhelp(0) if ($help); 232*4882a593Smuzhiyun 233*4882a593Smuzhiyunlist_types(0) if ($list_types); 234*4882a593Smuzhiyun 235*4882a593Smuzhiyun$fix = 1 if ($fix_inplace); 236*4882a593Smuzhiyun$check_orig = $check; 237*4882a593Smuzhiyun 238*4882a593Smuzhiyunmy $exit = 0; 239*4882a593Smuzhiyun 240*4882a593Smuzhiyunif ($^V && $^V lt $minimum_perl_version) { 241*4882a593Smuzhiyun printf "$P: requires at least perl version %vd\n", $minimum_perl_version; 242*4882a593Smuzhiyun if (!$ignore_perl_version) { 243*4882a593Smuzhiyun exit(1); 244*4882a593Smuzhiyun } 245*4882a593Smuzhiyun} 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun#if no filenames are given, push '-' to read patch from stdin 248*4882a593Smuzhiyunif ($#ARGV < 0) { 249*4882a593Smuzhiyun push(@ARGV, '-'); 250*4882a593Smuzhiyun} 251*4882a593Smuzhiyun 252*4882a593Smuzhiyunif ($color =~ /^[01]$/) { 253*4882a593Smuzhiyun $color = !$color; 254*4882a593Smuzhiyun} elsif ($color =~ /^always$/i) { 255*4882a593Smuzhiyun $color = 1; 256*4882a593Smuzhiyun} elsif ($color =~ /^never$/i) { 257*4882a593Smuzhiyun $color = 0; 258*4882a593Smuzhiyun} elsif ($color =~ /^auto$/i) { 259*4882a593Smuzhiyun $color = (-t STDOUT); 260*4882a593Smuzhiyun} else { 261*4882a593Smuzhiyun die "Invalid color mode: $color\n"; 262*4882a593Smuzhiyun} 263*4882a593Smuzhiyun 264*4882a593Smuzhiyunsub hash_save_array_words { 265*4882a593Smuzhiyun my ($hashRef, $arrayRef) = @_; 266*4882a593Smuzhiyun 267*4882a593Smuzhiyun my @array = split(/,/, join(',', @$arrayRef)); 268*4882a593Smuzhiyun foreach my $word (@array) { 269*4882a593Smuzhiyun $word =~ s/\s*\n?$//g; 270*4882a593Smuzhiyun $word =~ s/^\s*//g; 271*4882a593Smuzhiyun $word =~ s/\s+/ /g; 272*4882a593Smuzhiyun $word =~ tr/[a-z]/[A-Z]/; 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun next if ($word =~ m/^\s*#/); 275*4882a593Smuzhiyun next if ($word =~ m/^\s*$/); 276*4882a593Smuzhiyun 277*4882a593Smuzhiyun $hashRef->{$word}++; 278*4882a593Smuzhiyun } 279*4882a593Smuzhiyun} 280*4882a593Smuzhiyun 281*4882a593Smuzhiyunsub hash_show_words { 282*4882a593Smuzhiyun my ($hashRef, $prefix) = @_; 283*4882a593Smuzhiyun 284*4882a593Smuzhiyun if (keys %$hashRef) { 285*4882a593Smuzhiyun print "\nNOTE: $prefix message types:"; 286*4882a593Smuzhiyun foreach my $word (sort keys %$hashRef) { 287*4882a593Smuzhiyun print " $word"; 288*4882a593Smuzhiyun } 289*4882a593Smuzhiyun print "\n"; 290*4882a593Smuzhiyun } 291*4882a593Smuzhiyun} 292*4882a593Smuzhiyun 293*4882a593Smuzhiyunhash_save_array_words(\%ignore_type, \@ignore); 294*4882a593Smuzhiyunhash_save_array_words(\%use_type, \@use); 295*4882a593Smuzhiyun 296*4882a593Smuzhiyunmy $dbg_values = 0; 297*4882a593Smuzhiyunmy $dbg_possible = 0; 298*4882a593Smuzhiyunmy $dbg_type = 0; 299*4882a593Smuzhiyunmy $dbg_attr = 0; 300*4882a593Smuzhiyunfor my $key (keys %debug) { 301*4882a593Smuzhiyun ## no critic 302*4882a593Smuzhiyun eval "\${dbg_$key} = '$debug{$key}';"; 303*4882a593Smuzhiyun die "$@" if ($@); 304*4882a593Smuzhiyun} 305*4882a593Smuzhiyun 306*4882a593Smuzhiyunmy $rpt_cleaners = 0; 307*4882a593Smuzhiyun 308*4882a593Smuzhiyunif ($terse) { 309*4882a593Smuzhiyun $emacs = 1; 310*4882a593Smuzhiyun $quiet++; 311*4882a593Smuzhiyun} 312*4882a593Smuzhiyun 313*4882a593Smuzhiyunif ($tree) { 314*4882a593Smuzhiyun if (defined $root) { 315*4882a593Smuzhiyun if (!top_of_kernel_tree($root)) { 316*4882a593Smuzhiyun die "$P: $root: --root does not point at a valid tree\n"; 317*4882a593Smuzhiyun } 318*4882a593Smuzhiyun } else { 319*4882a593Smuzhiyun if (top_of_kernel_tree('.')) { 320*4882a593Smuzhiyun $root = '.'; 321*4882a593Smuzhiyun } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && 322*4882a593Smuzhiyun top_of_kernel_tree($1)) { 323*4882a593Smuzhiyun $root = $1; 324*4882a593Smuzhiyun } 325*4882a593Smuzhiyun } 326*4882a593Smuzhiyun 327*4882a593Smuzhiyun if (!defined $root) { 328*4882a593Smuzhiyun print "Must be run from the top-level dir. of a kernel tree\n"; 329*4882a593Smuzhiyun exit(2); 330*4882a593Smuzhiyun } 331*4882a593Smuzhiyun} 332*4882a593Smuzhiyun 333*4882a593Smuzhiyunmy $emitted_corrupt = 0; 334*4882a593Smuzhiyun 335*4882a593Smuzhiyunour $Ident = qr{ 336*4882a593Smuzhiyun [A-Za-z_][A-Za-z\d_]* 337*4882a593Smuzhiyun (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* 338*4882a593Smuzhiyun }x; 339*4882a593Smuzhiyunour $Storage = qr{extern|static|asmlinkage}; 340*4882a593Smuzhiyunour $Sparse = qr{ 341*4882a593Smuzhiyun __user| 342*4882a593Smuzhiyun __kernel| 343*4882a593Smuzhiyun __force| 344*4882a593Smuzhiyun __iomem| 345*4882a593Smuzhiyun __must_check| 346*4882a593Smuzhiyun __init_refok| 347*4882a593Smuzhiyun __kprobes| 348*4882a593Smuzhiyun __ref| 349*4882a593Smuzhiyun __rcu| 350*4882a593Smuzhiyun __private 351*4882a593Smuzhiyun }x; 352*4882a593Smuzhiyunour $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; 353*4882a593Smuzhiyunour $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; 354*4882a593Smuzhiyunour $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)}; 355*4882a593Smuzhiyunour $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)}; 356*4882a593Smuzhiyunour $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit}; 357*4882a593Smuzhiyun 358*4882a593Smuzhiyun# Notes to $Attribute: 359*4882a593Smuzhiyun# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check 360*4882a593Smuzhiyunour $Attribute = qr{ 361*4882a593Smuzhiyun const| 362*4882a593Smuzhiyun __percpu| 363*4882a593Smuzhiyun __nocast| 364*4882a593Smuzhiyun __safe| 365*4882a593Smuzhiyun __bitwise| 366*4882a593Smuzhiyun __packed__| 367*4882a593Smuzhiyun __packed2__| 368*4882a593Smuzhiyun __naked| 369*4882a593Smuzhiyun __maybe_unused| 370*4882a593Smuzhiyun __always_unused| 371*4882a593Smuzhiyun __noreturn| 372*4882a593Smuzhiyun __used| 373*4882a593Smuzhiyun __cold| 374*4882a593Smuzhiyun __pure| 375*4882a593Smuzhiyun __noclone| 376*4882a593Smuzhiyun __deprecated| 377*4882a593Smuzhiyun __read_mostly| 378*4882a593Smuzhiyun __kprobes| 379*4882a593Smuzhiyun $InitAttribute| 380*4882a593Smuzhiyun ____cacheline_aligned| 381*4882a593Smuzhiyun ____cacheline_aligned_in_smp| 382*4882a593Smuzhiyun ____cacheline_internodealigned_in_smp| 383*4882a593Smuzhiyun __weak 384*4882a593Smuzhiyun }x; 385*4882a593Smuzhiyunour $Modifier; 386*4882a593Smuzhiyunour $Inline = qr{inline|__always_inline|noinline|__inline|__inline__}; 387*4882a593Smuzhiyunour $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; 388*4882a593Smuzhiyunour $Lval = qr{$Ident(?:$Member)*}; 389*4882a593Smuzhiyun 390*4882a593Smuzhiyunour $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u}; 391*4882a593Smuzhiyunour $Binary = qr{(?i)0b[01]+$Int_type?}; 392*4882a593Smuzhiyunour $Hex = qr{(?i)0x[0-9a-f]+$Int_type?}; 393*4882a593Smuzhiyunour $Int = qr{[0-9]+$Int_type?}; 394*4882a593Smuzhiyunour $Octal = qr{0[0-7]+$Int_type?}; 395*4882a593Smuzhiyunour $String = qr{(?:\bL)?"[X\t]*"}; 396*4882a593Smuzhiyunour $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?}; 397*4882a593Smuzhiyunour $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?}; 398*4882a593Smuzhiyunour $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?}; 399*4882a593Smuzhiyunour $Float = qr{$Float_hex|$Float_dec|$Float_int}; 400*4882a593Smuzhiyunour $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int}; 401*4882a593Smuzhiyunour $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=}; 402*4882a593Smuzhiyunour $Compare = qr{<=|>=|==|!=|<|(?<!-)>}; 403*4882a593Smuzhiyunour $Arithmetic = qr{\+|-|\*|\/|%}; 404*4882a593Smuzhiyunour $Operators = qr{ 405*4882a593Smuzhiyun <=|>=|==|!=| 406*4882a593Smuzhiyun =>|->|<<|>>|<|>|!|~| 407*4882a593Smuzhiyun &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic 408*4882a593Smuzhiyun }x; 409*4882a593Smuzhiyun 410*4882a593Smuzhiyunour $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; 411*4882a593Smuzhiyun 412*4882a593Smuzhiyunour $BasicType; 413*4882a593Smuzhiyunour $NonptrType; 414*4882a593Smuzhiyunour $NonptrTypeMisordered; 415*4882a593Smuzhiyunour $NonptrTypeWithAttr; 416*4882a593Smuzhiyunour $Type; 417*4882a593Smuzhiyunour $TypeMisordered; 418*4882a593Smuzhiyunour $Declare; 419*4882a593Smuzhiyunour $DeclareMisordered; 420*4882a593Smuzhiyun 421*4882a593Smuzhiyunour $NON_ASCII_UTF8 = qr{ 422*4882a593Smuzhiyun [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte 423*4882a593Smuzhiyun | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs 424*4882a593Smuzhiyun | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte 425*4882a593Smuzhiyun | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates 426*4882a593Smuzhiyun | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 427*4882a593Smuzhiyun | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 428*4882a593Smuzhiyun | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 429*4882a593Smuzhiyun}x; 430*4882a593Smuzhiyun 431*4882a593Smuzhiyunour $UTF8 = qr{ 432*4882a593Smuzhiyun [\x09\x0A\x0D\x20-\x7E] # ASCII 433*4882a593Smuzhiyun | $NON_ASCII_UTF8 434*4882a593Smuzhiyun}x; 435*4882a593Smuzhiyun 436*4882a593Smuzhiyunour $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t}; 437*4882a593Smuzhiyunour $typeOtherOSTypedefs = qr{(?x: 438*4882a593Smuzhiyun u_(?:char|short|int|long) | # bsd 439*4882a593Smuzhiyun u(?:nchar|short|int|long) # sysv 440*4882a593Smuzhiyun)}; 441*4882a593Smuzhiyunour $typeKernelTypedefs = qr{(?x: 442*4882a593Smuzhiyun (?:__)?(?:u|s|be|le)(?:8|16|32|64)| 443*4882a593Smuzhiyun atomic_t 444*4882a593Smuzhiyun)}; 445*4882a593Smuzhiyunour $typeTypedefs = qr{(?x: 446*4882a593Smuzhiyun $typeC99Typedefs\b| 447*4882a593Smuzhiyun $typeOtherOSTypedefs\b| 448*4882a593Smuzhiyun $typeKernelTypedefs\b 449*4882a593Smuzhiyun)}; 450*4882a593Smuzhiyun 451*4882a593Smuzhiyunour $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b}; 452*4882a593Smuzhiyun 453*4882a593Smuzhiyunour $logFunctions = qr{(?x: 454*4882a593Smuzhiyun printk(?:_ratelimited|_once|_deferred_once|_deferred|)| 455*4882a593Smuzhiyun (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| 456*4882a593Smuzhiyun WARN(?:_RATELIMIT|_ONCE|)| 457*4882a593Smuzhiyun panic| 458*4882a593Smuzhiyun MODULE_[A-Z_]+| 459*4882a593Smuzhiyun seq_vprintf|seq_printf|seq_puts 460*4882a593Smuzhiyun)}; 461*4882a593Smuzhiyun 462*4882a593Smuzhiyunour $signature_tags = qr{(?xi: 463*4882a593Smuzhiyun Signed-off-by:| 464*4882a593Smuzhiyun Acked-by:| 465*4882a593Smuzhiyun Tested-by:| 466*4882a593Smuzhiyun Reviewed-by:| 467*4882a593Smuzhiyun Reported-by:| 468*4882a593Smuzhiyun Suggested-by:| 469*4882a593Smuzhiyun To:| 470*4882a593Smuzhiyun Cc: 471*4882a593Smuzhiyun)}; 472*4882a593Smuzhiyun 473*4882a593Smuzhiyunour @typeListMisordered = ( 474*4882a593Smuzhiyun qr{char\s+(?:un)?signed}, 475*4882a593Smuzhiyun qr{int\s+(?:(?:un)?signed\s+)?short\s}, 476*4882a593Smuzhiyun qr{int\s+short(?:\s+(?:un)?signed)}, 477*4882a593Smuzhiyun qr{short\s+int(?:\s+(?:un)?signed)}, 478*4882a593Smuzhiyun qr{(?:un)?signed\s+int\s+short}, 479*4882a593Smuzhiyun qr{short\s+(?:un)?signed}, 480*4882a593Smuzhiyun qr{long\s+int\s+(?:un)?signed}, 481*4882a593Smuzhiyun qr{int\s+long\s+(?:un)?signed}, 482*4882a593Smuzhiyun qr{long\s+(?:un)?signed\s+int}, 483*4882a593Smuzhiyun qr{int\s+(?:un)?signed\s+long}, 484*4882a593Smuzhiyun qr{int\s+(?:un)?signed}, 485*4882a593Smuzhiyun qr{int\s+long\s+long\s+(?:un)?signed}, 486*4882a593Smuzhiyun qr{long\s+long\s+int\s+(?:un)?signed}, 487*4882a593Smuzhiyun qr{long\s+long\s+(?:un)?signed\s+int}, 488*4882a593Smuzhiyun qr{long\s+long\s+(?:un)?signed}, 489*4882a593Smuzhiyun qr{long\s+(?:un)?signed}, 490*4882a593Smuzhiyun); 491*4882a593Smuzhiyun 492*4882a593Smuzhiyunour @typeList = ( 493*4882a593Smuzhiyun qr{void}, 494*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?char}, 495*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?short\s+int}, 496*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?short}, 497*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?int}, 498*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long\s+int}, 499*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long\s+long\s+int}, 500*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long\s+long}, 501*4882a593Smuzhiyun qr{(?:(?:un)?signed\s+)?long}, 502*4882a593Smuzhiyun qr{(?:un)?signed}, 503*4882a593Smuzhiyun qr{float}, 504*4882a593Smuzhiyun qr{double}, 505*4882a593Smuzhiyun qr{bool}, 506*4882a593Smuzhiyun qr{struct\s+$Ident}, 507*4882a593Smuzhiyun qr{union\s+$Ident}, 508*4882a593Smuzhiyun qr{enum\s+$Ident}, 509*4882a593Smuzhiyun qr{${Ident}_t}, 510*4882a593Smuzhiyun qr{${Ident}_handler}, 511*4882a593Smuzhiyun qr{${Ident}_handler_fn}, 512*4882a593Smuzhiyun @typeListMisordered, 513*4882a593Smuzhiyun); 514*4882a593Smuzhiyun 515*4882a593Smuzhiyunour $C90_int_types = qr{(?x: 516*4882a593Smuzhiyun long\s+long\s+int\s+(?:un)?signed| 517*4882a593Smuzhiyun long\s+long\s+(?:un)?signed\s+int| 518*4882a593Smuzhiyun long\s+long\s+(?:un)?signed| 519*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long\s+long\s+int| 520*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long\s+long| 521*4882a593Smuzhiyun int\s+long\s+long\s+(?:un)?signed| 522*4882a593Smuzhiyun int\s+(?:(?:un)?signed\s+)?long\s+long| 523*4882a593Smuzhiyun 524*4882a593Smuzhiyun long\s+int\s+(?:un)?signed| 525*4882a593Smuzhiyun long\s+(?:un)?signed\s+int| 526*4882a593Smuzhiyun long\s+(?:un)?signed| 527*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long\s+int| 528*4882a593Smuzhiyun (?:(?:un)?signed\s+)?long| 529*4882a593Smuzhiyun int\s+long\s+(?:un)?signed| 530*4882a593Smuzhiyun int\s+(?:(?:un)?signed\s+)?long| 531*4882a593Smuzhiyun 532*4882a593Smuzhiyun int\s+(?:un)?signed| 533*4882a593Smuzhiyun (?:(?:un)?signed\s+)?int 534*4882a593Smuzhiyun)}; 535*4882a593Smuzhiyun 536*4882a593Smuzhiyunour @typeListFile = (); 537*4882a593Smuzhiyunour @typeListWithAttr = ( 538*4882a593Smuzhiyun @typeList, 539*4882a593Smuzhiyun qr{struct\s+$InitAttribute\s+$Ident}, 540*4882a593Smuzhiyun qr{union\s+$InitAttribute\s+$Ident}, 541*4882a593Smuzhiyun); 542*4882a593Smuzhiyun 543*4882a593Smuzhiyunour @modifierList = ( 544*4882a593Smuzhiyun qr{fastcall}, 545*4882a593Smuzhiyun); 546*4882a593Smuzhiyunour @modifierListFile = (); 547*4882a593Smuzhiyun 548*4882a593Smuzhiyunour @mode_permission_funcs = ( 549*4882a593Smuzhiyun ["module_param", 3], 550*4882a593Smuzhiyun ["module_param_(?:array|named|string)", 4], 551*4882a593Smuzhiyun ["module_param_array_named", 5], 552*4882a593Smuzhiyun ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], 553*4882a593Smuzhiyun ["proc_create(?:_data|)", 2], 554*4882a593Smuzhiyun ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2], 555*4882a593Smuzhiyun ["IIO_DEV_ATTR_[A-Z_]+", 1], 556*4882a593Smuzhiyun ["SENSOR_(?:DEVICE_|)ATTR_2", 2], 557*4882a593Smuzhiyun ["SENSOR_TEMPLATE(?:_2|)", 3], 558*4882a593Smuzhiyun ["__ATTR", 2], 559*4882a593Smuzhiyun); 560*4882a593Smuzhiyun 561*4882a593Smuzhiyun#Create a search pattern for all these functions to speed up a loop below 562*4882a593Smuzhiyunour $mode_perms_search = ""; 563*4882a593Smuzhiyunforeach my $entry (@mode_permission_funcs) { 564*4882a593Smuzhiyun $mode_perms_search .= '|' if ($mode_perms_search ne ""); 565*4882a593Smuzhiyun $mode_perms_search .= $entry->[0]; 566*4882a593Smuzhiyun} 567*4882a593Smuzhiyun 568*4882a593Smuzhiyunour $mode_perms_world_writable = qr{ 569*4882a593Smuzhiyun S_IWUGO | 570*4882a593Smuzhiyun S_IWOTH | 571*4882a593Smuzhiyun S_IRWXUGO | 572*4882a593Smuzhiyun S_IALLUGO | 573*4882a593Smuzhiyun 0[0-7][0-7][2367] 574*4882a593Smuzhiyun}x; 575*4882a593Smuzhiyun 576*4882a593Smuzhiyunour %mode_permission_string_types = ( 577*4882a593Smuzhiyun "S_IRWXU" => 0700, 578*4882a593Smuzhiyun "S_IRUSR" => 0400, 579*4882a593Smuzhiyun "S_IWUSR" => 0200, 580*4882a593Smuzhiyun "S_IXUSR" => 0100, 581*4882a593Smuzhiyun "S_IRWXG" => 0070, 582*4882a593Smuzhiyun "S_IRGRP" => 0040, 583*4882a593Smuzhiyun "S_IWGRP" => 0020, 584*4882a593Smuzhiyun "S_IXGRP" => 0010, 585*4882a593Smuzhiyun "S_IRWXO" => 0007, 586*4882a593Smuzhiyun "S_IROTH" => 0004, 587*4882a593Smuzhiyun "S_IWOTH" => 0002, 588*4882a593Smuzhiyun "S_IXOTH" => 0001, 589*4882a593Smuzhiyun "S_IRWXUGO" => 0777, 590*4882a593Smuzhiyun "S_IRUGO" => 0444, 591*4882a593Smuzhiyun "S_IWUGO" => 0222, 592*4882a593Smuzhiyun "S_IXUGO" => 0111, 593*4882a593Smuzhiyun); 594*4882a593Smuzhiyun 595*4882a593Smuzhiyun#Create a search pattern for all these strings to speed up a loop below 596*4882a593Smuzhiyunour $mode_perms_string_search = ""; 597*4882a593Smuzhiyunforeach my $entry (keys %mode_permission_string_types) { 598*4882a593Smuzhiyun $mode_perms_string_search .= '|' if ($mode_perms_string_search ne ""); 599*4882a593Smuzhiyun $mode_perms_string_search .= $entry; 600*4882a593Smuzhiyun} 601*4882a593Smuzhiyun 602*4882a593Smuzhiyunour $allowed_asm_includes = qr{(?x: 603*4882a593Smuzhiyun irq| 604*4882a593Smuzhiyun memory| 605*4882a593Smuzhiyun time| 606*4882a593Smuzhiyun reboot 607*4882a593Smuzhiyun)}; 608*4882a593Smuzhiyun# memory.h: ARM has a custom one 609*4882a593Smuzhiyun 610*4882a593Smuzhiyun# Load common spelling mistakes and build regular expression list. 611*4882a593Smuzhiyunmy $misspellings; 612*4882a593Smuzhiyunmy %spelling_fix; 613*4882a593Smuzhiyun 614*4882a593Smuzhiyunif (open(my $spelling, '<', $spelling_file)) { 615*4882a593Smuzhiyun while (<$spelling>) { 616*4882a593Smuzhiyun my $line = $_; 617*4882a593Smuzhiyun 618*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 619*4882a593Smuzhiyun $line =~ s/^\s*//g; 620*4882a593Smuzhiyun 621*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 622*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 623*4882a593Smuzhiyun 624*4882a593Smuzhiyun my ($suspect, $fix) = split(/\|\|/, $line); 625*4882a593Smuzhiyun 626*4882a593Smuzhiyun $spelling_fix{$suspect} = $fix; 627*4882a593Smuzhiyun } 628*4882a593Smuzhiyun close($spelling); 629*4882a593Smuzhiyun} else { 630*4882a593Smuzhiyun warn "No typos will be found - file '$spelling_file': $!\n"; 631*4882a593Smuzhiyun} 632*4882a593Smuzhiyun 633*4882a593Smuzhiyunif ($codespell) { 634*4882a593Smuzhiyun if (open(my $spelling, '<', $codespellfile)) { 635*4882a593Smuzhiyun while (<$spelling>) { 636*4882a593Smuzhiyun my $line = $_; 637*4882a593Smuzhiyun 638*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 639*4882a593Smuzhiyun $line =~ s/^\s*//g; 640*4882a593Smuzhiyun 641*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 642*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 643*4882a593Smuzhiyun next if ($line =~ m/, disabled/i); 644*4882a593Smuzhiyun 645*4882a593Smuzhiyun $line =~ s/,.*$//; 646*4882a593Smuzhiyun 647*4882a593Smuzhiyun my ($suspect, $fix) = split(/->/, $line); 648*4882a593Smuzhiyun 649*4882a593Smuzhiyun $spelling_fix{$suspect} = $fix; 650*4882a593Smuzhiyun } 651*4882a593Smuzhiyun close($spelling); 652*4882a593Smuzhiyun } else { 653*4882a593Smuzhiyun warn "No codespell typos will be found - file '$codespellfile': $!\n"; 654*4882a593Smuzhiyun } 655*4882a593Smuzhiyun} 656*4882a593Smuzhiyun 657*4882a593Smuzhiyun$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; 658*4882a593Smuzhiyun 659*4882a593Smuzhiyunsub read_words { 660*4882a593Smuzhiyun my ($wordsRef, $file) = @_; 661*4882a593Smuzhiyun 662*4882a593Smuzhiyun if (open(my $words, '<', $file)) { 663*4882a593Smuzhiyun while (<$words>) { 664*4882a593Smuzhiyun my $line = $_; 665*4882a593Smuzhiyun 666*4882a593Smuzhiyun $line =~ s/\s*\n?$//g; 667*4882a593Smuzhiyun $line =~ s/^\s*//g; 668*4882a593Smuzhiyun 669*4882a593Smuzhiyun next if ($line =~ m/^\s*#/); 670*4882a593Smuzhiyun next if ($line =~ m/^\s*$/); 671*4882a593Smuzhiyun if ($line =~ /\s/) { 672*4882a593Smuzhiyun print("$file: '$line' invalid - ignored\n"); 673*4882a593Smuzhiyun next; 674*4882a593Smuzhiyun } 675*4882a593Smuzhiyun 676*4882a593Smuzhiyun $$wordsRef .= '|' if ($$wordsRef ne ""); 677*4882a593Smuzhiyun $$wordsRef .= $line; 678*4882a593Smuzhiyun } 679*4882a593Smuzhiyun close($file); 680*4882a593Smuzhiyun return 1; 681*4882a593Smuzhiyun } 682*4882a593Smuzhiyun 683*4882a593Smuzhiyun return 0; 684*4882a593Smuzhiyun} 685*4882a593Smuzhiyun 686*4882a593Smuzhiyunmy $const_structs = ""; 687*4882a593Smuzhiyunread_words(\$const_structs, $conststructsfile) 688*4882a593Smuzhiyun or warn "No structs that should be const will be found - file '$conststructsfile': $!\n"; 689*4882a593Smuzhiyun 690*4882a593Smuzhiyunmy $typeOtherTypedefs = ""; 691*4882a593Smuzhiyunif (length($typedefsfile)) { 692*4882a593Smuzhiyun read_words(\$typeOtherTypedefs, $typedefsfile) 693*4882a593Smuzhiyun or warn "No additional types will be considered - file '$typedefsfile': $!\n"; 694*4882a593Smuzhiyun} 695*4882a593Smuzhiyun$typeTypedefs .= '|' . $typeOtherTypedefs if ($typeOtherTypedefs ne ""); 696*4882a593Smuzhiyun 697*4882a593Smuzhiyunsub build_types { 698*4882a593Smuzhiyun my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; 699*4882a593Smuzhiyun my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; 700*4882a593Smuzhiyun my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)"; 701*4882a593Smuzhiyun my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)"; 702*4882a593Smuzhiyun $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; 703*4882a593Smuzhiyun $BasicType = qr{ 704*4882a593Smuzhiyun (?:$typeTypedefs\b)| 705*4882a593Smuzhiyun (?:${all}\b) 706*4882a593Smuzhiyun }x; 707*4882a593Smuzhiyun $NonptrType = qr{ 708*4882a593Smuzhiyun (?:$Modifier\s+|const\s+)* 709*4882a593Smuzhiyun (?: 710*4882a593Smuzhiyun (?:typeof|__typeof__)\s*\([^\)]*\)| 711*4882a593Smuzhiyun (?:$typeTypedefs\b)| 712*4882a593Smuzhiyun (?:${all}\b) 713*4882a593Smuzhiyun ) 714*4882a593Smuzhiyun (?:\s+$Modifier|\s+const)* 715*4882a593Smuzhiyun }x; 716*4882a593Smuzhiyun $NonptrTypeMisordered = qr{ 717*4882a593Smuzhiyun (?:$Modifier\s+|const\s+)* 718*4882a593Smuzhiyun (?: 719*4882a593Smuzhiyun (?:${Misordered}\b) 720*4882a593Smuzhiyun ) 721*4882a593Smuzhiyun (?:\s+$Modifier|\s+const)* 722*4882a593Smuzhiyun }x; 723*4882a593Smuzhiyun $NonptrTypeWithAttr = qr{ 724*4882a593Smuzhiyun (?:$Modifier\s+|const\s+)* 725*4882a593Smuzhiyun (?: 726*4882a593Smuzhiyun (?:typeof|__typeof__)\s*\([^\)]*\)| 727*4882a593Smuzhiyun (?:$typeTypedefs\b)| 728*4882a593Smuzhiyun (?:${allWithAttr}\b) 729*4882a593Smuzhiyun ) 730*4882a593Smuzhiyun (?:\s+$Modifier|\s+const)* 731*4882a593Smuzhiyun }x; 732*4882a593Smuzhiyun $Type = qr{ 733*4882a593Smuzhiyun $NonptrType 734*4882a593Smuzhiyun (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? 735*4882a593Smuzhiyun (?:\s+$Inline|\s+$Modifier)* 736*4882a593Smuzhiyun }x; 737*4882a593Smuzhiyun $TypeMisordered = qr{ 738*4882a593Smuzhiyun $NonptrTypeMisordered 739*4882a593Smuzhiyun (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)? 740*4882a593Smuzhiyun (?:\s+$Inline|\s+$Modifier)* 741*4882a593Smuzhiyun }x; 742*4882a593Smuzhiyun $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type}; 743*4882a593Smuzhiyun $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered}; 744*4882a593Smuzhiyun} 745*4882a593Smuzhiyunbuild_types(); 746*4882a593Smuzhiyun 747*4882a593Smuzhiyunour $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; 748*4882a593Smuzhiyun 749*4882a593Smuzhiyun# Using $balanced_parens, $LvalOrFunc, or $FuncArg 750*4882a593Smuzhiyun# requires at least perl version v5.10.0 751*4882a593Smuzhiyun# Any use must be runtime checked with $^V 752*4882a593Smuzhiyun 753*4882a593Smuzhiyunour $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; 754*4882a593Smuzhiyunour $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*}; 755*4882a593Smuzhiyunour $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)}; 756*4882a593Smuzhiyun 757*4882a593Smuzhiyunour $declaration_macros = qr{(?x: 758*4882a593Smuzhiyun (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(| 759*4882a593Smuzhiyun (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(| 760*4882a593Smuzhiyun (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\( 761*4882a593Smuzhiyun)}; 762*4882a593Smuzhiyun 763*4882a593Smuzhiyunsub deparenthesize { 764*4882a593Smuzhiyun my ($string) = @_; 765*4882a593Smuzhiyun return "" if (!defined($string)); 766*4882a593Smuzhiyun 767*4882a593Smuzhiyun while ($string =~ /^\s*\(.*\)\s*$/) { 768*4882a593Smuzhiyun $string =~ s@^\s*\(\s*@@; 769*4882a593Smuzhiyun $string =~ s@\s*\)\s*$@@; 770*4882a593Smuzhiyun } 771*4882a593Smuzhiyun 772*4882a593Smuzhiyun $string =~ s@\s+@ @g; 773*4882a593Smuzhiyun 774*4882a593Smuzhiyun return $string; 775*4882a593Smuzhiyun} 776*4882a593Smuzhiyun 777*4882a593Smuzhiyunsub seed_camelcase_file { 778*4882a593Smuzhiyun my ($file) = @_; 779*4882a593Smuzhiyun 780*4882a593Smuzhiyun return if (!(-f $file)); 781*4882a593Smuzhiyun 782*4882a593Smuzhiyun local $/; 783*4882a593Smuzhiyun 784*4882a593Smuzhiyun open(my $include_file, '<', "$file") 785*4882a593Smuzhiyun or warn "$P: Can't read '$file' $!\n"; 786*4882a593Smuzhiyun my $text = <$include_file>; 787*4882a593Smuzhiyun close($include_file); 788*4882a593Smuzhiyun 789*4882a593Smuzhiyun my @lines = split('\n', $text); 790*4882a593Smuzhiyun 791*4882a593Smuzhiyun foreach my $line (@lines) { 792*4882a593Smuzhiyun next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/); 793*4882a593Smuzhiyun if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) { 794*4882a593Smuzhiyun $camelcase{$1} = 1; 795*4882a593Smuzhiyun } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) { 796*4882a593Smuzhiyun $camelcase{$1} = 1; 797*4882a593Smuzhiyun } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) { 798*4882a593Smuzhiyun $camelcase{$1} = 1; 799*4882a593Smuzhiyun } 800*4882a593Smuzhiyun } 801*4882a593Smuzhiyun} 802*4882a593Smuzhiyun 803*4882a593Smuzhiyunsub is_maintained_obsolete { 804*4882a593Smuzhiyun my ($filename) = @_; 805*4882a593Smuzhiyun 806*4882a593Smuzhiyun return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl")); 807*4882a593Smuzhiyun 808*4882a593Smuzhiyun my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`; 809*4882a593Smuzhiyun 810*4882a593Smuzhiyun return $status =~ /obsolete/i; 811*4882a593Smuzhiyun} 812*4882a593Smuzhiyun 813*4882a593Smuzhiyunmy $camelcase_seeded = 0; 814*4882a593Smuzhiyunsub seed_camelcase_includes { 815*4882a593Smuzhiyun return if ($camelcase_seeded); 816*4882a593Smuzhiyun 817*4882a593Smuzhiyun my $files; 818*4882a593Smuzhiyun my $camelcase_cache = ""; 819*4882a593Smuzhiyun my @include_files = (); 820*4882a593Smuzhiyun 821*4882a593Smuzhiyun $camelcase_seeded = 1; 822*4882a593Smuzhiyun 823*4882a593Smuzhiyun if (-e ".git") { 824*4882a593Smuzhiyun my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`; 825*4882a593Smuzhiyun chomp $git_last_include_commit; 826*4882a593Smuzhiyun $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; 827*4882a593Smuzhiyun } else { 828*4882a593Smuzhiyun my $last_mod_date = 0; 829*4882a593Smuzhiyun $files = `find $root/include -name "*.h"`; 830*4882a593Smuzhiyun @include_files = split('\n', $files); 831*4882a593Smuzhiyun foreach my $file (@include_files) { 832*4882a593Smuzhiyun my $date = POSIX::strftime("%Y%m%d%H%M", 833*4882a593Smuzhiyun localtime((stat $file)[9])); 834*4882a593Smuzhiyun $last_mod_date = $date if ($last_mod_date < $date); 835*4882a593Smuzhiyun } 836*4882a593Smuzhiyun $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date"; 837*4882a593Smuzhiyun } 838*4882a593Smuzhiyun 839*4882a593Smuzhiyun if ($camelcase_cache ne "" && -f $camelcase_cache) { 840*4882a593Smuzhiyun open(my $camelcase_file, '<', "$camelcase_cache") 841*4882a593Smuzhiyun or warn "$P: Can't read '$camelcase_cache' $!\n"; 842*4882a593Smuzhiyun while (<$camelcase_file>) { 843*4882a593Smuzhiyun chomp; 844*4882a593Smuzhiyun $camelcase{$_} = 1; 845*4882a593Smuzhiyun } 846*4882a593Smuzhiyun close($camelcase_file); 847*4882a593Smuzhiyun 848*4882a593Smuzhiyun return; 849*4882a593Smuzhiyun } 850*4882a593Smuzhiyun 851*4882a593Smuzhiyun if (-e ".git") { 852*4882a593Smuzhiyun $files = `git ls-files "include/*.h"`; 853*4882a593Smuzhiyun @include_files = split('\n', $files); 854*4882a593Smuzhiyun } 855*4882a593Smuzhiyun 856*4882a593Smuzhiyun foreach my $file (@include_files) { 857*4882a593Smuzhiyun seed_camelcase_file($file); 858*4882a593Smuzhiyun } 859*4882a593Smuzhiyun 860*4882a593Smuzhiyun if ($camelcase_cache ne "") { 861*4882a593Smuzhiyun unlink glob ".checkpatch-camelcase.*"; 862*4882a593Smuzhiyun open(my $camelcase_file, '>', "$camelcase_cache") 863*4882a593Smuzhiyun or warn "$P: Can't write '$camelcase_cache' $!\n"; 864*4882a593Smuzhiyun foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) { 865*4882a593Smuzhiyun print $camelcase_file ("$_\n"); 866*4882a593Smuzhiyun } 867*4882a593Smuzhiyun close($camelcase_file); 868*4882a593Smuzhiyun } 869*4882a593Smuzhiyun} 870*4882a593Smuzhiyun 871*4882a593Smuzhiyunsub git_commit_info { 872*4882a593Smuzhiyun my ($commit, $id, $desc) = @_; 873*4882a593Smuzhiyun 874*4882a593Smuzhiyun return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); 875*4882a593Smuzhiyun 876*4882a593Smuzhiyun my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`; 877*4882a593Smuzhiyun $output =~ s/^\s*//gm; 878*4882a593Smuzhiyun my @lines = split("\n", $output); 879*4882a593Smuzhiyun 880*4882a593Smuzhiyun return ($id, $desc) if ($#lines < 0); 881*4882a593Smuzhiyun 882*4882a593Smuzhiyun if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) { 883*4882a593Smuzhiyun# Maybe one day convert this block of bash into something that returns 884*4882a593Smuzhiyun# all matching commit ids, but it's very slow... 885*4882a593Smuzhiyun# 886*4882a593Smuzhiyun# echo "checking commits $1..." 887*4882a593Smuzhiyun# git rev-list --remotes | grep -i "^$1" | 888*4882a593Smuzhiyun# while read line ; do 889*4882a593Smuzhiyun# git log --format='%H %s' -1 $line | 890*4882a593Smuzhiyun# echo "commit $(cut -c 1-12,41-)" 891*4882a593Smuzhiyun# done 892*4882a593Smuzhiyun } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) { 893*4882a593Smuzhiyun $id = undef; 894*4882a593Smuzhiyun } else { 895*4882a593Smuzhiyun $id = substr($lines[0], 0, 12); 896*4882a593Smuzhiyun $desc = substr($lines[0], 41); 897*4882a593Smuzhiyun } 898*4882a593Smuzhiyun 899*4882a593Smuzhiyun return ($id, $desc); 900*4882a593Smuzhiyun} 901*4882a593Smuzhiyun 902*4882a593Smuzhiyun$chk_signoff = 0 if ($file); 903*4882a593Smuzhiyun 904*4882a593Smuzhiyunmy @rawlines = (); 905*4882a593Smuzhiyunmy @lines = (); 906*4882a593Smuzhiyunmy @fixed = (); 907*4882a593Smuzhiyunmy @fixed_inserted = (); 908*4882a593Smuzhiyunmy @fixed_deleted = (); 909*4882a593Smuzhiyunmy $fixlinenr = -1; 910*4882a593Smuzhiyun 911*4882a593Smuzhiyun# If input is git commits, extract all commits from the commit expressions. 912*4882a593Smuzhiyun# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'. 913*4882a593Smuzhiyundie "$P: No git repository found\n" if ($git && !-e ".git"); 914*4882a593Smuzhiyun 915*4882a593Smuzhiyunif ($git) { 916*4882a593Smuzhiyun my @commits = (); 917*4882a593Smuzhiyun foreach my $commit_expr (@ARGV) { 918*4882a593Smuzhiyun my $git_range; 919*4882a593Smuzhiyun if ($commit_expr =~ m/^(.*)-(\d+)$/) { 920*4882a593Smuzhiyun $git_range = "-$2 $1"; 921*4882a593Smuzhiyun } elsif ($commit_expr =~ m/\.\./) { 922*4882a593Smuzhiyun $git_range = "$commit_expr"; 923*4882a593Smuzhiyun } else { 924*4882a593Smuzhiyun $git_range = "-1 $commit_expr"; 925*4882a593Smuzhiyun } 926*4882a593Smuzhiyun my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`; 927*4882a593Smuzhiyun foreach my $line (split(/\n/, $lines)) { 928*4882a593Smuzhiyun $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/; 929*4882a593Smuzhiyun next if (!defined($1) || !defined($2)); 930*4882a593Smuzhiyun my $sha1 = $1; 931*4882a593Smuzhiyun my $subject = $2; 932*4882a593Smuzhiyun unshift(@commits, $sha1); 933*4882a593Smuzhiyun $git_commits{$sha1} = $subject; 934*4882a593Smuzhiyun } 935*4882a593Smuzhiyun } 936*4882a593Smuzhiyun die "$P: no git commits after extraction!\n" if (@commits == 0); 937*4882a593Smuzhiyun @ARGV = @commits; 938*4882a593Smuzhiyun} 939*4882a593Smuzhiyun 940*4882a593Smuzhiyunmy $vname; 941*4882a593Smuzhiyunfor my $filename (@ARGV) { 942*4882a593Smuzhiyun my $FILE; 943*4882a593Smuzhiyun if ($git) { 944*4882a593Smuzhiyun open($FILE, '-|', "git format-patch -M --stdout -1 $filename") || 945*4882a593Smuzhiyun die "$P: $filename: git format-patch failed - $!\n"; 946*4882a593Smuzhiyun } elsif ($file) { 947*4882a593Smuzhiyun open($FILE, '-|', "diff -u /dev/null $filename") || 948*4882a593Smuzhiyun die "$P: $filename: diff failed - $!\n"; 949*4882a593Smuzhiyun } elsif ($filename eq '-') { 950*4882a593Smuzhiyun open($FILE, '<&STDIN'); 951*4882a593Smuzhiyun } else { 952*4882a593Smuzhiyun open($FILE, '<', "$filename") || 953*4882a593Smuzhiyun die "$P: $filename: open failed - $!\n"; 954*4882a593Smuzhiyun } 955*4882a593Smuzhiyun if ($filename eq '-') { 956*4882a593Smuzhiyun $vname = 'Your patch'; 957*4882a593Smuzhiyun } elsif ($git) { 958*4882a593Smuzhiyun $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")'; 959*4882a593Smuzhiyun } else { 960*4882a593Smuzhiyun $vname = $filename; 961*4882a593Smuzhiyun } 962*4882a593Smuzhiyun while (<$FILE>) { 963*4882a593Smuzhiyun chomp; 964*4882a593Smuzhiyun push(@rawlines, $_); 965*4882a593Smuzhiyun } 966*4882a593Smuzhiyun close($FILE); 967*4882a593Smuzhiyun 968*4882a593Smuzhiyun if ($#ARGV > 0 && $quiet == 0) { 969*4882a593Smuzhiyun print '-' x length($vname) . "\n"; 970*4882a593Smuzhiyun print "$vname\n"; 971*4882a593Smuzhiyun print '-' x length($vname) . "\n"; 972*4882a593Smuzhiyun } 973*4882a593Smuzhiyun 974*4882a593Smuzhiyun if (!process($filename)) { 975*4882a593Smuzhiyun $exit = 1; 976*4882a593Smuzhiyun } 977*4882a593Smuzhiyun @rawlines = (); 978*4882a593Smuzhiyun @lines = (); 979*4882a593Smuzhiyun @fixed = (); 980*4882a593Smuzhiyun @fixed_inserted = (); 981*4882a593Smuzhiyun @fixed_deleted = (); 982*4882a593Smuzhiyun $fixlinenr = -1; 983*4882a593Smuzhiyun @modifierListFile = (); 984*4882a593Smuzhiyun @typeListFile = (); 985*4882a593Smuzhiyun build_types(); 986*4882a593Smuzhiyun} 987*4882a593Smuzhiyun 988*4882a593Smuzhiyunif (!$quiet) { 989*4882a593Smuzhiyun hash_show_words(\%use_type, "Used"); 990*4882a593Smuzhiyun hash_show_words(\%ignore_type, "Ignored"); 991*4882a593Smuzhiyun 992*4882a593Smuzhiyun if ($^V lt 5.10.0) { 993*4882a593Smuzhiyun print << "EOM" 994*4882a593Smuzhiyun 995*4882a593SmuzhiyunNOTE: perl $^V is not modern enough to detect all possible issues. 996*4882a593Smuzhiyun An upgrade to at least perl v5.10.0 is suggested. 997*4882a593SmuzhiyunEOM 998*4882a593Smuzhiyun } 999*4882a593Smuzhiyun if ($exit) { 1000*4882a593Smuzhiyun print << "EOM" 1001*4882a593Smuzhiyun 1002*4882a593SmuzhiyunNOTE: If any of the errors are false positives, please report 1003*4882a593Smuzhiyun them to the maintainer, see CHECKPATCH in MAINTAINERS. 1004*4882a593SmuzhiyunEOM 1005*4882a593Smuzhiyun } 1006*4882a593Smuzhiyun} 1007*4882a593Smuzhiyun 1008*4882a593Smuzhiyunexit($exit); 1009*4882a593Smuzhiyun 1010*4882a593Smuzhiyunsub top_of_kernel_tree { 1011*4882a593Smuzhiyun my ($root) = @_; 1012*4882a593Smuzhiyun 1013*4882a593Smuzhiyun my @tree_check = ( 1014*4882a593Smuzhiyun "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", 1015*4882a593Smuzhiyun "README", "Documentation", "arch", "include", "drivers", 1016*4882a593Smuzhiyun "fs", "init", "ipc", "kernel", "lib", "scripts", 1017*4882a593Smuzhiyun ); 1018*4882a593Smuzhiyun 1019*4882a593Smuzhiyun foreach my $check (@tree_check) { 1020*4882a593Smuzhiyun if (! -e $root . '/' . $check) { 1021*4882a593Smuzhiyun return 0; 1022*4882a593Smuzhiyun } 1023*4882a593Smuzhiyun } 1024*4882a593Smuzhiyun return 1; 1025*4882a593Smuzhiyun} 1026*4882a593Smuzhiyun 1027*4882a593Smuzhiyunsub parse_email { 1028*4882a593Smuzhiyun my ($formatted_email) = @_; 1029*4882a593Smuzhiyun 1030*4882a593Smuzhiyun my $name = ""; 1031*4882a593Smuzhiyun my $address = ""; 1032*4882a593Smuzhiyun my $comment = ""; 1033*4882a593Smuzhiyun 1034*4882a593Smuzhiyun if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { 1035*4882a593Smuzhiyun $name = $1; 1036*4882a593Smuzhiyun $address = $2; 1037*4882a593Smuzhiyun $comment = $3 if defined $3; 1038*4882a593Smuzhiyun } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { 1039*4882a593Smuzhiyun $address = $1; 1040*4882a593Smuzhiyun $comment = $2 if defined $2; 1041*4882a593Smuzhiyun } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { 1042*4882a593Smuzhiyun $address = $1; 1043*4882a593Smuzhiyun $comment = $2 if defined $2; 1044*4882a593Smuzhiyun $formatted_email =~ s/$address.*$//; 1045*4882a593Smuzhiyun $name = $formatted_email; 1046*4882a593Smuzhiyun $name = trim($name); 1047*4882a593Smuzhiyun $name =~ s/^\"|\"$//g; 1048*4882a593Smuzhiyun # If there's a name left after stripping spaces and 1049*4882a593Smuzhiyun # leading quotes, and the address doesn't have both 1050*4882a593Smuzhiyun # leading and trailing angle brackets, the address 1051*4882a593Smuzhiyun # is invalid. ie: 1052*4882a593Smuzhiyun # "joe smith joe@smith.com" bad 1053*4882a593Smuzhiyun # "joe smith <joe@smith.com" bad 1054*4882a593Smuzhiyun if ($name ne "" && $address !~ /^<[^>]+>$/) { 1055*4882a593Smuzhiyun $name = ""; 1056*4882a593Smuzhiyun $address = ""; 1057*4882a593Smuzhiyun $comment = ""; 1058*4882a593Smuzhiyun } 1059*4882a593Smuzhiyun } 1060*4882a593Smuzhiyun 1061*4882a593Smuzhiyun $name = trim($name); 1062*4882a593Smuzhiyun $name =~ s/^\"|\"$//g; 1063*4882a593Smuzhiyun $address = trim($address); 1064*4882a593Smuzhiyun $address =~ s/^\<|\>$//g; 1065*4882a593Smuzhiyun 1066*4882a593Smuzhiyun if ($name =~ /[^\w \-]/i) { ##has "must quote" chars 1067*4882a593Smuzhiyun $name =~ s/(?<!\\)"/\\"/g; ##escape quotes 1068*4882a593Smuzhiyun $name = "\"$name\""; 1069*4882a593Smuzhiyun } 1070*4882a593Smuzhiyun 1071*4882a593Smuzhiyun return ($name, $address, $comment); 1072*4882a593Smuzhiyun} 1073*4882a593Smuzhiyun 1074*4882a593Smuzhiyunsub format_email { 1075*4882a593Smuzhiyun my ($name, $address) = @_; 1076*4882a593Smuzhiyun 1077*4882a593Smuzhiyun my $formatted_email; 1078*4882a593Smuzhiyun 1079*4882a593Smuzhiyun $name = trim($name); 1080*4882a593Smuzhiyun $name =~ s/^\"|\"$//g; 1081*4882a593Smuzhiyun $address = trim($address); 1082*4882a593Smuzhiyun 1083*4882a593Smuzhiyun if ($name =~ /[^\w \-]/i) { ##has "must quote" chars 1084*4882a593Smuzhiyun $name =~ s/(?<!\\)"/\\"/g; ##escape quotes 1085*4882a593Smuzhiyun $name = "\"$name\""; 1086*4882a593Smuzhiyun } 1087*4882a593Smuzhiyun 1088*4882a593Smuzhiyun if ("$name" eq "") { 1089*4882a593Smuzhiyun $formatted_email = "$address"; 1090*4882a593Smuzhiyun } else { 1091*4882a593Smuzhiyun $formatted_email = "$name <$address>"; 1092*4882a593Smuzhiyun } 1093*4882a593Smuzhiyun 1094*4882a593Smuzhiyun return $formatted_email; 1095*4882a593Smuzhiyun} 1096*4882a593Smuzhiyun 1097*4882a593Smuzhiyunsub which { 1098*4882a593Smuzhiyun my ($bin) = @_; 1099*4882a593Smuzhiyun 1100*4882a593Smuzhiyun foreach my $path (split(/:/, $ENV{PATH})) { 1101*4882a593Smuzhiyun if (-e "$path/$bin") { 1102*4882a593Smuzhiyun return "$path/$bin"; 1103*4882a593Smuzhiyun } 1104*4882a593Smuzhiyun } 1105*4882a593Smuzhiyun 1106*4882a593Smuzhiyun return ""; 1107*4882a593Smuzhiyun} 1108*4882a593Smuzhiyun 1109*4882a593Smuzhiyunsub which_conf { 1110*4882a593Smuzhiyun my ($conf) = @_; 1111*4882a593Smuzhiyun 1112*4882a593Smuzhiyun foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { 1113*4882a593Smuzhiyun if (-e "$path/$conf") { 1114*4882a593Smuzhiyun return "$path/$conf"; 1115*4882a593Smuzhiyun } 1116*4882a593Smuzhiyun } 1117*4882a593Smuzhiyun 1118*4882a593Smuzhiyun return ""; 1119*4882a593Smuzhiyun} 1120*4882a593Smuzhiyun 1121*4882a593Smuzhiyunsub expand_tabs { 1122*4882a593Smuzhiyun my ($str) = @_; 1123*4882a593Smuzhiyun 1124*4882a593Smuzhiyun my $res = ''; 1125*4882a593Smuzhiyun my $n = 0; 1126*4882a593Smuzhiyun for my $c (split(//, $str)) { 1127*4882a593Smuzhiyun if ($c eq "\t") { 1128*4882a593Smuzhiyun $res .= ' '; 1129*4882a593Smuzhiyun $n++; 1130*4882a593Smuzhiyun for (; ($n % 8) != 0; $n++) { 1131*4882a593Smuzhiyun $res .= ' '; 1132*4882a593Smuzhiyun } 1133*4882a593Smuzhiyun next; 1134*4882a593Smuzhiyun } 1135*4882a593Smuzhiyun $res .= $c; 1136*4882a593Smuzhiyun $n++; 1137*4882a593Smuzhiyun } 1138*4882a593Smuzhiyun 1139*4882a593Smuzhiyun return $res; 1140*4882a593Smuzhiyun} 1141*4882a593Smuzhiyunsub copy_spacing { 1142*4882a593Smuzhiyun (my $res = shift) =~ tr/\t/ /c; 1143*4882a593Smuzhiyun return $res; 1144*4882a593Smuzhiyun} 1145*4882a593Smuzhiyun 1146*4882a593Smuzhiyunsub line_stats { 1147*4882a593Smuzhiyun my ($line) = @_; 1148*4882a593Smuzhiyun 1149*4882a593Smuzhiyun # Drop the diff line leader and expand tabs 1150*4882a593Smuzhiyun $line =~ s/^.//; 1151*4882a593Smuzhiyun $line = expand_tabs($line); 1152*4882a593Smuzhiyun 1153*4882a593Smuzhiyun # Pick the indent from the front of the line. 1154*4882a593Smuzhiyun my ($white) = ($line =~ /^(\s*)/); 1155*4882a593Smuzhiyun 1156*4882a593Smuzhiyun return (length($line), length($white)); 1157*4882a593Smuzhiyun} 1158*4882a593Smuzhiyun 1159*4882a593Smuzhiyunmy $sanitise_quote = ''; 1160*4882a593Smuzhiyun 1161*4882a593Smuzhiyunsub sanitise_line_reset { 1162*4882a593Smuzhiyun my ($in_comment) = @_; 1163*4882a593Smuzhiyun 1164*4882a593Smuzhiyun if ($in_comment) { 1165*4882a593Smuzhiyun $sanitise_quote = '*/'; 1166*4882a593Smuzhiyun } else { 1167*4882a593Smuzhiyun $sanitise_quote = ''; 1168*4882a593Smuzhiyun } 1169*4882a593Smuzhiyun} 1170*4882a593Smuzhiyunsub sanitise_line { 1171*4882a593Smuzhiyun my ($line) = @_; 1172*4882a593Smuzhiyun 1173*4882a593Smuzhiyun my $res = ''; 1174*4882a593Smuzhiyun my $l = ''; 1175*4882a593Smuzhiyun 1176*4882a593Smuzhiyun my $qlen = 0; 1177*4882a593Smuzhiyun my $off = 0; 1178*4882a593Smuzhiyun my $c; 1179*4882a593Smuzhiyun 1180*4882a593Smuzhiyun # Always copy over the diff marker. 1181*4882a593Smuzhiyun $res = substr($line, 0, 1); 1182*4882a593Smuzhiyun 1183*4882a593Smuzhiyun for ($off = 1; $off < length($line); $off++) { 1184*4882a593Smuzhiyun $c = substr($line, $off, 1); 1185*4882a593Smuzhiyun 1186*4882a593Smuzhiyun # Comments we are wacking completly including the begin 1187*4882a593Smuzhiyun # and end, all to $;. 1188*4882a593Smuzhiyun if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') { 1189*4882a593Smuzhiyun $sanitise_quote = '*/'; 1190*4882a593Smuzhiyun 1191*4882a593Smuzhiyun substr($res, $off, 2, "$;$;"); 1192*4882a593Smuzhiyun $off++; 1193*4882a593Smuzhiyun next; 1194*4882a593Smuzhiyun } 1195*4882a593Smuzhiyun if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') { 1196*4882a593Smuzhiyun $sanitise_quote = ''; 1197*4882a593Smuzhiyun substr($res, $off, 2, "$;$;"); 1198*4882a593Smuzhiyun $off++; 1199*4882a593Smuzhiyun next; 1200*4882a593Smuzhiyun } 1201*4882a593Smuzhiyun if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') { 1202*4882a593Smuzhiyun $sanitise_quote = '//'; 1203*4882a593Smuzhiyun 1204*4882a593Smuzhiyun substr($res, $off, 2, $sanitise_quote); 1205*4882a593Smuzhiyun $off++; 1206*4882a593Smuzhiyun next; 1207*4882a593Smuzhiyun } 1208*4882a593Smuzhiyun 1209*4882a593Smuzhiyun # A \ in a string means ignore the next character. 1210*4882a593Smuzhiyun if (($sanitise_quote eq "'" || $sanitise_quote eq '"') && 1211*4882a593Smuzhiyun $c eq "\\") { 1212*4882a593Smuzhiyun substr($res, $off, 2, 'XX'); 1213*4882a593Smuzhiyun $off++; 1214*4882a593Smuzhiyun next; 1215*4882a593Smuzhiyun } 1216*4882a593Smuzhiyun # Regular quotes. 1217*4882a593Smuzhiyun if ($c eq "'" || $c eq '"') { 1218*4882a593Smuzhiyun if ($sanitise_quote eq '') { 1219*4882a593Smuzhiyun $sanitise_quote = $c; 1220*4882a593Smuzhiyun 1221*4882a593Smuzhiyun substr($res, $off, 1, $c); 1222*4882a593Smuzhiyun next; 1223*4882a593Smuzhiyun } elsif ($sanitise_quote eq $c) { 1224*4882a593Smuzhiyun $sanitise_quote = ''; 1225*4882a593Smuzhiyun } 1226*4882a593Smuzhiyun } 1227*4882a593Smuzhiyun 1228*4882a593Smuzhiyun #print "c<$c> SQ<$sanitise_quote>\n"; 1229*4882a593Smuzhiyun if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") { 1230*4882a593Smuzhiyun substr($res, $off, 1, $;); 1231*4882a593Smuzhiyun } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") { 1232*4882a593Smuzhiyun substr($res, $off, 1, $;); 1233*4882a593Smuzhiyun } elsif ($off != 0 && $sanitise_quote && $c ne "\t") { 1234*4882a593Smuzhiyun substr($res, $off, 1, 'X'); 1235*4882a593Smuzhiyun } else { 1236*4882a593Smuzhiyun substr($res, $off, 1, $c); 1237*4882a593Smuzhiyun } 1238*4882a593Smuzhiyun } 1239*4882a593Smuzhiyun 1240*4882a593Smuzhiyun if ($sanitise_quote eq '//') { 1241*4882a593Smuzhiyun $sanitise_quote = ''; 1242*4882a593Smuzhiyun } 1243*4882a593Smuzhiyun 1244*4882a593Smuzhiyun # The pathname on a #include may be surrounded by '<' and '>'. 1245*4882a593Smuzhiyun if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) { 1246*4882a593Smuzhiyun my $clean = 'X' x length($1); 1247*4882a593Smuzhiyun $res =~ s@\<.*\>@<$clean>@; 1248*4882a593Smuzhiyun 1249*4882a593Smuzhiyun # The whole of a #error is a string. 1250*4882a593Smuzhiyun } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) { 1251*4882a593Smuzhiyun my $clean = 'X' x length($1); 1252*4882a593Smuzhiyun $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@; 1253*4882a593Smuzhiyun } 1254*4882a593Smuzhiyun 1255*4882a593Smuzhiyun if ($allow_c99_comments && $res =~ m@(//.*$)@) { 1256*4882a593Smuzhiyun my $match = $1; 1257*4882a593Smuzhiyun $res =~ s/\Q$match\E/"$;" x length($match)/e; 1258*4882a593Smuzhiyun } 1259*4882a593Smuzhiyun 1260*4882a593Smuzhiyun return $res; 1261*4882a593Smuzhiyun} 1262*4882a593Smuzhiyun 1263*4882a593Smuzhiyunsub get_quoted_string { 1264*4882a593Smuzhiyun my ($line, $rawline) = @_; 1265*4882a593Smuzhiyun 1266*4882a593Smuzhiyun return "" if ($line !~ m/($String)/g); 1267*4882a593Smuzhiyun return substr($rawline, $-[0], $+[0] - $-[0]); 1268*4882a593Smuzhiyun} 1269*4882a593Smuzhiyun 1270*4882a593Smuzhiyunsub ctx_statement_block { 1271*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1272*4882a593Smuzhiyun my $line = $linenr - 1; 1273*4882a593Smuzhiyun my $blk = ''; 1274*4882a593Smuzhiyun my $soff = $off; 1275*4882a593Smuzhiyun my $coff = $off - 1; 1276*4882a593Smuzhiyun my $coff_set = 0; 1277*4882a593Smuzhiyun 1278*4882a593Smuzhiyun my $loff = 0; 1279*4882a593Smuzhiyun 1280*4882a593Smuzhiyun my $type = ''; 1281*4882a593Smuzhiyun my $level = 0; 1282*4882a593Smuzhiyun my @stack = (); 1283*4882a593Smuzhiyun my $p; 1284*4882a593Smuzhiyun my $c; 1285*4882a593Smuzhiyun my $len = 0; 1286*4882a593Smuzhiyun 1287*4882a593Smuzhiyun my $remainder; 1288*4882a593Smuzhiyun while (1) { 1289*4882a593Smuzhiyun @stack = (['', 0]) if ($#stack == -1); 1290*4882a593Smuzhiyun 1291*4882a593Smuzhiyun #warn "CSB: blk<$blk> remain<$remain>\n"; 1292*4882a593Smuzhiyun # If we are about to drop off the end, pull in more 1293*4882a593Smuzhiyun # context. 1294*4882a593Smuzhiyun if ($off >= $len) { 1295*4882a593Smuzhiyun for (; $remain > 0; $line++) { 1296*4882a593Smuzhiyun last if (!defined $lines[$line]); 1297*4882a593Smuzhiyun next if ($lines[$line] =~ /^-/); 1298*4882a593Smuzhiyun $remain--; 1299*4882a593Smuzhiyun $loff = $len; 1300*4882a593Smuzhiyun $blk .= $lines[$line] . "\n"; 1301*4882a593Smuzhiyun $len = length($blk); 1302*4882a593Smuzhiyun $line++; 1303*4882a593Smuzhiyun last; 1304*4882a593Smuzhiyun } 1305*4882a593Smuzhiyun # Bail if there is no further context. 1306*4882a593Smuzhiyun #warn "CSB: blk<$blk> off<$off> len<$len>\n"; 1307*4882a593Smuzhiyun if ($off >= $len) { 1308*4882a593Smuzhiyun last; 1309*4882a593Smuzhiyun } 1310*4882a593Smuzhiyun if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) { 1311*4882a593Smuzhiyun $level++; 1312*4882a593Smuzhiyun $type = '#'; 1313*4882a593Smuzhiyun } 1314*4882a593Smuzhiyun } 1315*4882a593Smuzhiyun $p = $c; 1316*4882a593Smuzhiyun $c = substr($blk, $off, 1); 1317*4882a593Smuzhiyun $remainder = substr($blk, $off); 1318*4882a593Smuzhiyun 1319*4882a593Smuzhiyun #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n"; 1320*4882a593Smuzhiyun 1321*4882a593Smuzhiyun # Handle nested #if/#else. 1322*4882a593Smuzhiyun if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) { 1323*4882a593Smuzhiyun push(@stack, [ $type, $level ]); 1324*4882a593Smuzhiyun } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) { 1325*4882a593Smuzhiyun ($type, $level) = @{$stack[$#stack - 1]}; 1326*4882a593Smuzhiyun } elsif ($remainder =~ /^#\s*endif\b/) { 1327*4882a593Smuzhiyun ($type, $level) = @{pop(@stack)}; 1328*4882a593Smuzhiyun } 1329*4882a593Smuzhiyun 1330*4882a593Smuzhiyun # Statement ends at the ';' or a close '}' at the 1331*4882a593Smuzhiyun # outermost level. 1332*4882a593Smuzhiyun if ($level == 0 && $c eq ';') { 1333*4882a593Smuzhiyun last; 1334*4882a593Smuzhiyun } 1335*4882a593Smuzhiyun 1336*4882a593Smuzhiyun # An else is really a conditional as long as its not else if 1337*4882a593Smuzhiyun if ($level == 0 && $coff_set == 0 && 1338*4882a593Smuzhiyun (!defined($p) || $p =~ /(?:\s|\}|\+)/) && 1339*4882a593Smuzhiyun $remainder =~ /^(else)(?:\s|{)/ && 1340*4882a593Smuzhiyun $remainder !~ /^else\s+if\b/) { 1341*4882a593Smuzhiyun $coff = $off + length($1) - 1; 1342*4882a593Smuzhiyun $coff_set = 1; 1343*4882a593Smuzhiyun #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n"; 1344*4882a593Smuzhiyun #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n"; 1345*4882a593Smuzhiyun } 1346*4882a593Smuzhiyun 1347*4882a593Smuzhiyun if (($type eq '' || $type eq '(') && $c eq '(') { 1348*4882a593Smuzhiyun $level++; 1349*4882a593Smuzhiyun $type = '('; 1350*4882a593Smuzhiyun } 1351*4882a593Smuzhiyun if ($type eq '(' && $c eq ')') { 1352*4882a593Smuzhiyun $level--; 1353*4882a593Smuzhiyun $type = ($level != 0)? '(' : ''; 1354*4882a593Smuzhiyun 1355*4882a593Smuzhiyun if ($level == 0 && $coff < $soff) { 1356*4882a593Smuzhiyun $coff = $off; 1357*4882a593Smuzhiyun $coff_set = 1; 1358*4882a593Smuzhiyun #warn "CSB: mark coff<$coff>\n"; 1359*4882a593Smuzhiyun } 1360*4882a593Smuzhiyun } 1361*4882a593Smuzhiyun if (($type eq '' || $type eq '{') && $c eq '{') { 1362*4882a593Smuzhiyun $level++; 1363*4882a593Smuzhiyun $type = '{'; 1364*4882a593Smuzhiyun } 1365*4882a593Smuzhiyun if ($type eq '{' && $c eq '}') { 1366*4882a593Smuzhiyun $level--; 1367*4882a593Smuzhiyun $type = ($level != 0)? '{' : ''; 1368*4882a593Smuzhiyun 1369*4882a593Smuzhiyun if ($level == 0) { 1370*4882a593Smuzhiyun if (substr($blk, $off + 1, 1) eq ';') { 1371*4882a593Smuzhiyun $off++; 1372*4882a593Smuzhiyun } 1373*4882a593Smuzhiyun last; 1374*4882a593Smuzhiyun } 1375*4882a593Smuzhiyun } 1376*4882a593Smuzhiyun # Preprocessor commands end at the newline unless escaped. 1377*4882a593Smuzhiyun if ($type eq '#' && $c eq "\n" && $p ne "\\") { 1378*4882a593Smuzhiyun $level--; 1379*4882a593Smuzhiyun $type = ''; 1380*4882a593Smuzhiyun $off++; 1381*4882a593Smuzhiyun last; 1382*4882a593Smuzhiyun } 1383*4882a593Smuzhiyun $off++; 1384*4882a593Smuzhiyun } 1385*4882a593Smuzhiyun # We are truly at the end, so shuffle to the next line. 1386*4882a593Smuzhiyun if ($off == $len) { 1387*4882a593Smuzhiyun $loff = $len + 1; 1388*4882a593Smuzhiyun $line++; 1389*4882a593Smuzhiyun $remain--; 1390*4882a593Smuzhiyun } 1391*4882a593Smuzhiyun 1392*4882a593Smuzhiyun my $statement = substr($blk, $soff, $off - $soff + 1); 1393*4882a593Smuzhiyun my $condition = substr($blk, $soff, $coff - $soff + 1); 1394*4882a593Smuzhiyun 1395*4882a593Smuzhiyun #warn "STATEMENT<$statement>\n"; 1396*4882a593Smuzhiyun #warn "CONDITION<$condition>\n"; 1397*4882a593Smuzhiyun 1398*4882a593Smuzhiyun #print "coff<$coff> soff<$off> loff<$loff>\n"; 1399*4882a593Smuzhiyun 1400*4882a593Smuzhiyun return ($statement, $condition, 1401*4882a593Smuzhiyun $line, $remain + 1, $off - $loff + 1, $level); 1402*4882a593Smuzhiyun} 1403*4882a593Smuzhiyun 1404*4882a593Smuzhiyunsub statement_lines { 1405*4882a593Smuzhiyun my ($stmt) = @_; 1406*4882a593Smuzhiyun 1407*4882a593Smuzhiyun # Strip the diff line prefixes and rip blank lines at start and end. 1408*4882a593Smuzhiyun $stmt =~ s/(^|\n)./$1/g; 1409*4882a593Smuzhiyun $stmt =~ s/^\s*//; 1410*4882a593Smuzhiyun $stmt =~ s/\s*$//; 1411*4882a593Smuzhiyun 1412*4882a593Smuzhiyun my @stmt_lines = ($stmt =~ /\n/g); 1413*4882a593Smuzhiyun 1414*4882a593Smuzhiyun return $#stmt_lines + 2; 1415*4882a593Smuzhiyun} 1416*4882a593Smuzhiyun 1417*4882a593Smuzhiyunsub statement_rawlines { 1418*4882a593Smuzhiyun my ($stmt) = @_; 1419*4882a593Smuzhiyun 1420*4882a593Smuzhiyun my @stmt_lines = ($stmt =~ /\n/g); 1421*4882a593Smuzhiyun 1422*4882a593Smuzhiyun return $#stmt_lines + 2; 1423*4882a593Smuzhiyun} 1424*4882a593Smuzhiyun 1425*4882a593Smuzhiyunsub statement_block_size { 1426*4882a593Smuzhiyun my ($stmt) = @_; 1427*4882a593Smuzhiyun 1428*4882a593Smuzhiyun $stmt =~ s/(^|\n)./$1/g; 1429*4882a593Smuzhiyun $stmt =~ s/^\s*{//; 1430*4882a593Smuzhiyun $stmt =~ s/}\s*$//; 1431*4882a593Smuzhiyun $stmt =~ s/^\s*//; 1432*4882a593Smuzhiyun $stmt =~ s/\s*$//; 1433*4882a593Smuzhiyun 1434*4882a593Smuzhiyun my @stmt_lines = ($stmt =~ /\n/g); 1435*4882a593Smuzhiyun my @stmt_statements = ($stmt =~ /;/g); 1436*4882a593Smuzhiyun 1437*4882a593Smuzhiyun my $stmt_lines = $#stmt_lines + 2; 1438*4882a593Smuzhiyun my $stmt_statements = $#stmt_statements + 1; 1439*4882a593Smuzhiyun 1440*4882a593Smuzhiyun if ($stmt_lines > $stmt_statements) { 1441*4882a593Smuzhiyun return $stmt_lines; 1442*4882a593Smuzhiyun } else { 1443*4882a593Smuzhiyun return $stmt_statements; 1444*4882a593Smuzhiyun } 1445*4882a593Smuzhiyun} 1446*4882a593Smuzhiyun 1447*4882a593Smuzhiyunsub ctx_statement_full { 1448*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1449*4882a593Smuzhiyun my ($statement, $condition, $level); 1450*4882a593Smuzhiyun 1451*4882a593Smuzhiyun my (@chunks); 1452*4882a593Smuzhiyun 1453*4882a593Smuzhiyun # Grab the first conditional/block pair. 1454*4882a593Smuzhiyun ($statement, $condition, $linenr, $remain, $off, $level) = 1455*4882a593Smuzhiyun ctx_statement_block($linenr, $remain, $off); 1456*4882a593Smuzhiyun #print "F: c<$condition> s<$statement> remain<$remain>\n"; 1457*4882a593Smuzhiyun push(@chunks, [ $condition, $statement ]); 1458*4882a593Smuzhiyun if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) { 1459*4882a593Smuzhiyun return ($level, $linenr, @chunks); 1460*4882a593Smuzhiyun } 1461*4882a593Smuzhiyun 1462*4882a593Smuzhiyun # Pull in the following conditional/block pairs and see if they 1463*4882a593Smuzhiyun # could continue the statement. 1464*4882a593Smuzhiyun for (;;) { 1465*4882a593Smuzhiyun ($statement, $condition, $linenr, $remain, $off, $level) = 1466*4882a593Smuzhiyun ctx_statement_block($linenr, $remain, $off); 1467*4882a593Smuzhiyun #print "C: c<$condition> s<$statement> remain<$remain>\n"; 1468*4882a593Smuzhiyun last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s)); 1469*4882a593Smuzhiyun #print "C: push\n"; 1470*4882a593Smuzhiyun push(@chunks, [ $condition, $statement ]); 1471*4882a593Smuzhiyun } 1472*4882a593Smuzhiyun 1473*4882a593Smuzhiyun return ($level, $linenr, @chunks); 1474*4882a593Smuzhiyun} 1475*4882a593Smuzhiyun 1476*4882a593Smuzhiyunsub ctx_block_get { 1477*4882a593Smuzhiyun my ($linenr, $remain, $outer, $open, $close, $off) = @_; 1478*4882a593Smuzhiyun my $line; 1479*4882a593Smuzhiyun my $start = $linenr - 1; 1480*4882a593Smuzhiyun my $blk = ''; 1481*4882a593Smuzhiyun my @o; 1482*4882a593Smuzhiyun my @c; 1483*4882a593Smuzhiyun my @res = (); 1484*4882a593Smuzhiyun 1485*4882a593Smuzhiyun my $level = 0; 1486*4882a593Smuzhiyun my @stack = ($level); 1487*4882a593Smuzhiyun for ($line = $start; $remain > 0; $line++) { 1488*4882a593Smuzhiyun next if ($rawlines[$line] =~ /^-/); 1489*4882a593Smuzhiyun $remain--; 1490*4882a593Smuzhiyun 1491*4882a593Smuzhiyun $blk .= $rawlines[$line]; 1492*4882a593Smuzhiyun 1493*4882a593Smuzhiyun # Handle nested #if/#else. 1494*4882a593Smuzhiyun if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) { 1495*4882a593Smuzhiyun push(@stack, $level); 1496*4882a593Smuzhiyun } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) { 1497*4882a593Smuzhiyun $level = $stack[$#stack - 1]; 1498*4882a593Smuzhiyun } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) { 1499*4882a593Smuzhiyun $level = pop(@stack); 1500*4882a593Smuzhiyun } 1501*4882a593Smuzhiyun 1502*4882a593Smuzhiyun foreach my $c (split(//, $lines[$line])) { 1503*4882a593Smuzhiyun ##print "C<$c>L<$level><$open$close>O<$off>\n"; 1504*4882a593Smuzhiyun if ($off > 0) { 1505*4882a593Smuzhiyun $off--; 1506*4882a593Smuzhiyun next; 1507*4882a593Smuzhiyun } 1508*4882a593Smuzhiyun 1509*4882a593Smuzhiyun if ($c eq $close && $level > 0) { 1510*4882a593Smuzhiyun $level--; 1511*4882a593Smuzhiyun last if ($level == 0); 1512*4882a593Smuzhiyun } elsif ($c eq $open) { 1513*4882a593Smuzhiyun $level++; 1514*4882a593Smuzhiyun } 1515*4882a593Smuzhiyun } 1516*4882a593Smuzhiyun 1517*4882a593Smuzhiyun if (!$outer || $level <= 1) { 1518*4882a593Smuzhiyun push(@res, $rawlines[$line]); 1519*4882a593Smuzhiyun } 1520*4882a593Smuzhiyun 1521*4882a593Smuzhiyun last if ($level == 0); 1522*4882a593Smuzhiyun } 1523*4882a593Smuzhiyun 1524*4882a593Smuzhiyun return ($level, @res); 1525*4882a593Smuzhiyun} 1526*4882a593Smuzhiyunsub ctx_block_outer { 1527*4882a593Smuzhiyun my ($linenr, $remain) = @_; 1528*4882a593Smuzhiyun 1529*4882a593Smuzhiyun my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0); 1530*4882a593Smuzhiyun return @r; 1531*4882a593Smuzhiyun} 1532*4882a593Smuzhiyunsub ctx_block { 1533*4882a593Smuzhiyun my ($linenr, $remain) = @_; 1534*4882a593Smuzhiyun 1535*4882a593Smuzhiyun my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0); 1536*4882a593Smuzhiyun return @r; 1537*4882a593Smuzhiyun} 1538*4882a593Smuzhiyunsub ctx_statement { 1539*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1540*4882a593Smuzhiyun 1541*4882a593Smuzhiyun my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off); 1542*4882a593Smuzhiyun return @r; 1543*4882a593Smuzhiyun} 1544*4882a593Smuzhiyunsub ctx_block_level { 1545*4882a593Smuzhiyun my ($linenr, $remain) = @_; 1546*4882a593Smuzhiyun 1547*4882a593Smuzhiyun return ctx_block_get($linenr, $remain, 0, '{', '}', 0); 1548*4882a593Smuzhiyun} 1549*4882a593Smuzhiyunsub ctx_statement_level { 1550*4882a593Smuzhiyun my ($linenr, $remain, $off) = @_; 1551*4882a593Smuzhiyun 1552*4882a593Smuzhiyun return ctx_block_get($linenr, $remain, 0, '(', ')', $off); 1553*4882a593Smuzhiyun} 1554*4882a593Smuzhiyun 1555*4882a593Smuzhiyunsub ctx_locate_comment { 1556*4882a593Smuzhiyun my ($first_line, $end_line) = @_; 1557*4882a593Smuzhiyun 1558*4882a593Smuzhiyun # Catch a comment on the end of the line itself. 1559*4882a593Smuzhiyun my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@); 1560*4882a593Smuzhiyun return $current_comment if (defined $current_comment); 1561*4882a593Smuzhiyun 1562*4882a593Smuzhiyun # Look through the context and try and figure out if there is a 1563*4882a593Smuzhiyun # comment. 1564*4882a593Smuzhiyun my $in_comment = 0; 1565*4882a593Smuzhiyun $current_comment = ''; 1566*4882a593Smuzhiyun for (my $linenr = $first_line; $linenr < $end_line; $linenr++) { 1567*4882a593Smuzhiyun my $line = $rawlines[$linenr - 1]; 1568*4882a593Smuzhiyun #warn " $line\n"; 1569*4882a593Smuzhiyun if ($linenr == $first_line and $line =~ m@^.\s*\*@) { 1570*4882a593Smuzhiyun $in_comment = 1; 1571*4882a593Smuzhiyun } 1572*4882a593Smuzhiyun if ($line =~ m@/\*@) { 1573*4882a593Smuzhiyun $in_comment = 1; 1574*4882a593Smuzhiyun } 1575*4882a593Smuzhiyun if (!$in_comment && $current_comment ne '') { 1576*4882a593Smuzhiyun $current_comment = ''; 1577*4882a593Smuzhiyun } 1578*4882a593Smuzhiyun $current_comment .= $line . "\n" if ($in_comment); 1579*4882a593Smuzhiyun if ($line =~ m@\*/@) { 1580*4882a593Smuzhiyun $in_comment = 0; 1581*4882a593Smuzhiyun } 1582*4882a593Smuzhiyun } 1583*4882a593Smuzhiyun 1584*4882a593Smuzhiyun chomp($current_comment); 1585*4882a593Smuzhiyun return($current_comment); 1586*4882a593Smuzhiyun} 1587*4882a593Smuzhiyunsub ctx_has_comment { 1588*4882a593Smuzhiyun my ($first_line, $end_line) = @_; 1589*4882a593Smuzhiyun my $cmt = ctx_locate_comment($first_line, $end_line); 1590*4882a593Smuzhiyun 1591*4882a593Smuzhiyun ##print "LINE: $rawlines[$end_line - 1 ]\n"; 1592*4882a593Smuzhiyun ##print "CMMT: $cmt\n"; 1593*4882a593Smuzhiyun 1594*4882a593Smuzhiyun return ($cmt ne ''); 1595*4882a593Smuzhiyun} 1596*4882a593Smuzhiyun 1597*4882a593Smuzhiyunsub raw_line { 1598*4882a593Smuzhiyun my ($linenr, $cnt) = @_; 1599*4882a593Smuzhiyun 1600*4882a593Smuzhiyun my $offset = $linenr - 1; 1601*4882a593Smuzhiyun $cnt++; 1602*4882a593Smuzhiyun 1603*4882a593Smuzhiyun my $line; 1604*4882a593Smuzhiyun while ($cnt) { 1605*4882a593Smuzhiyun $line = $rawlines[$offset++]; 1606*4882a593Smuzhiyun next if (defined($line) && $line =~ /^-/); 1607*4882a593Smuzhiyun $cnt--; 1608*4882a593Smuzhiyun } 1609*4882a593Smuzhiyun 1610*4882a593Smuzhiyun return $line; 1611*4882a593Smuzhiyun} 1612*4882a593Smuzhiyun 1613*4882a593Smuzhiyunsub cat_vet { 1614*4882a593Smuzhiyun my ($vet) = @_; 1615*4882a593Smuzhiyun my ($res, $coded); 1616*4882a593Smuzhiyun 1617*4882a593Smuzhiyun $res = ''; 1618*4882a593Smuzhiyun while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) { 1619*4882a593Smuzhiyun $res .= $1; 1620*4882a593Smuzhiyun if ($2 ne '') { 1621*4882a593Smuzhiyun $coded = sprintf("^%c", unpack('C', $2) + 64); 1622*4882a593Smuzhiyun $res .= $coded; 1623*4882a593Smuzhiyun } 1624*4882a593Smuzhiyun } 1625*4882a593Smuzhiyun $res =~ s/$/\$/; 1626*4882a593Smuzhiyun 1627*4882a593Smuzhiyun return $res; 1628*4882a593Smuzhiyun} 1629*4882a593Smuzhiyun 1630*4882a593Smuzhiyunmy $av_preprocessor = 0; 1631*4882a593Smuzhiyunmy $av_pending; 1632*4882a593Smuzhiyunmy @av_paren_type; 1633*4882a593Smuzhiyunmy $av_pend_colon; 1634*4882a593Smuzhiyun 1635*4882a593Smuzhiyunsub annotate_reset { 1636*4882a593Smuzhiyun $av_preprocessor = 0; 1637*4882a593Smuzhiyun $av_pending = '_'; 1638*4882a593Smuzhiyun @av_paren_type = ('E'); 1639*4882a593Smuzhiyun $av_pend_colon = 'O'; 1640*4882a593Smuzhiyun} 1641*4882a593Smuzhiyun 1642*4882a593Smuzhiyunsub annotate_values { 1643*4882a593Smuzhiyun my ($stream, $type) = @_; 1644*4882a593Smuzhiyun 1645*4882a593Smuzhiyun my $res; 1646*4882a593Smuzhiyun my $var = '_' x length($stream); 1647*4882a593Smuzhiyun my $cur = $stream; 1648*4882a593Smuzhiyun 1649*4882a593Smuzhiyun print "$stream\n" if ($dbg_values > 1); 1650*4882a593Smuzhiyun 1651*4882a593Smuzhiyun while (length($cur)) { 1652*4882a593Smuzhiyun @av_paren_type = ('E') if ($#av_paren_type < 0); 1653*4882a593Smuzhiyun print " <" . join('', @av_paren_type) . 1654*4882a593Smuzhiyun "> <$type> <$av_pending>" if ($dbg_values > 1); 1655*4882a593Smuzhiyun if ($cur =~ /^(\s+)/o) { 1656*4882a593Smuzhiyun print "WS($1)\n" if ($dbg_values > 1); 1657*4882a593Smuzhiyun if ($1 =~ /\n/ && $av_preprocessor) { 1658*4882a593Smuzhiyun $type = pop(@av_paren_type); 1659*4882a593Smuzhiyun $av_preprocessor = 0; 1660*4882a593Smuzhiyun } 1661*4882a593Smuzhiyun 1662*4882a593Smuzhiyun } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') { 1663*4882a593Smuzhiyun print "CAST($1)\n" if ($dbg_values > 1); 1664*4882a593Smuzhiyun push(@av_paren_type, $type); 1665*4882a593Smuzhiyun $type = 'c'; 1666*4882a593Smuzhiyun 1667*4882a593Smuzhiyun } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) { 1668*4882a593Smuzhiyun print "DECLARE($1)\n" if ($dbg_values > 1); 1669*4882a593Smuzhiyun $type = 'T'; 1670*4882a593Smuzhiyun 1671*4882a593Smuzhiyun } elsif ($cur =~ /^($Modifier)\s*/) { 1672*4882a593Smuzhiyun print "MODIFIER($1)\n" if ($dbg_values > 1); 1673*4882a593Smuzhiyun $type = 'T'; 1674*4882a593Smuzhiyun 1675*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) { 1676*4882a593Smuzhiyun print "DEFINE($1,$2)\n" if ($dbg_values > 1); 1677*4882a593Smuzhiyun $av_preprocessor = 1; 1678*4882a593Smuzhiyun push(@av_paren_type, $type); 1679*4882a593Smuzhiyun if ($2 ne '') { 1680*4882a593Smuzhiyun $av_pending = 'N'; 1681*4882a593Smuzhiyun } 1682*4882a593Smuzhiyun $type = 'E'; 1683*4882a593Smuzhiyun 1684*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) { 1685*4882a593Smuzhiyun print "UNDEF($1)\n" if ($dbg_values > 1); 1686*4882a593Smuzhiyun $av_preprocessor = 1; 1687*4882a593Smuzhiyun push(@av_paren_type, $type); 1688*4882a593Smuzhiyun 1689*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) { 1690*4882a593Smuzhiyun print "PRE_START($1)\n" if ($dbg_values > 1); 1691*4882a593Smuzhiyun $av_preprocessor = 1; 1692*4882a593Smuzhiyun 1693*4882a593Smuzhiyun push(@av_paren_type, $type); 1694*4882a593Smuzhiyun push(@av_paren_type, $type); 1695*4882a593Smuzhiyun $type = 'E'; 1696*4882a593Smuzhiyun 1697*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) { 1698*4882a593Smuzhiyun print "PRE_RESTART($1)\n" if ($dbg_values > 1); 1699*4882a593Smuzhiyun $av_preprocessor = 1; 1700*4882a593Smuzhiyun 1701*4882a593Smuzhiyun push(@av_paren_type, $av_paren_type[$#av_paren_type]); 1702*4882a593Smuzhiyun 1703*4882a593Smuzhiyun $type = 'E'; 1704*4882a593Smuzhiyun 1705*4882a593Smuzhiyun } elsif ($cur =~ /^(\#\s*(?:endif))/o) { 1706*4882a593Smuzhiyun print "PRE_END($1)\n" if ($dbg_values > 1); 1707*4882a593Smuzhiyun 1708*4882a593Smuzhiyun $av_preprocessor = 1; 1709*4882a593Smuzhiyun 1710*4882a593Smuzhiyun # Assume all arms of the conditional end as this 1711*4882a593Smuzhiyun # one does, and continue as if the #endif was not here. 1712*4882a593Smuzhiyun pop(@av_paren_type); 1713*4882a593Smuzhiyun push(@av_paren_type, $type); 1714*4882a593Smuzhiyun $type = 'E'; 1715*4882a593Smuzhiyun 1716*4882a593Smuzhiyun } elsif ($cur =~ /^(\\\n)/o) { 1717*4882a593Smuzhiyun print "PRECONT($1)\n" if ($dbg_values > 1); 1718*4882a593Smuzhiyun 1719*4882a593Smuzhiyun } elsif ($cur =~ /^(__attribute__)\s*\(?/o) { 1720*4882a593Smuzhiyun print "ATTR($1)\n" if ($dbg_values > 1); 1721*4882a593Smuzhiyun $av_pending = $type; 1722*4882a593Smuzhiyun $type = 'N'; 1723*4882a593Smuzhiyun 1724*4882a593Smuzhiyun } elsif ($cur =~ /^(sizeof)\s*(\()?/o) { 1725*4882a593Smuzhiyun print "SIZEOF($1)\n" if ($dbg_values > 1); 1726*4882a593Smuzhiyun if (defined $2) { 1727*4882a593Smuzhiyun $av_pending = 'V'; 1728*4882a593Smuzhiyun } 1729*4882a593Smuzhiyun $type = 'N'; 1730*4882a593Smuzhiyun 1731*4882a593Smuzhiyun } elsif ($cur =~ /^(if|while|for)\b/o) { 1732*4882a593Smuzhiyun print "COND($1)\n" if ($dbg_values > 1); 1733*4882a593Smuzhiyun $av_pending = 'E'; 1734*4882a593Smuzhiyun $type = 'N'; 1735*4882a593Smuzhiyun 1736*4882a593Smuzhiyun } elsif ($cur =~/^(case)/o) { 1737*4882a593Smuzhiyun print "CASE($1)\n" if ($dbg_values > 1); 1738*4882a593Smuzhiyun $av_pend_colon = 'C'; 1739*4882a593Smuzhiyun $type = 'N'; 1740*4882a593Smuzhiyun 1741*4882a593Smuzhiyun } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) { 1742*4882a593Smuzhiyun print "KEYWORD($1)\n" if ($dbg_values > 1); 1743*4882a593Smuzhiyun $type = 'N'; 1744*4882a593Smuzhiyun 1745*4882a593Smuzhiyun } elsif ($cur =~ /^(\()/o) { 1746*4882a593Smuzhiyun print "PAREN('$1')\n" if ($dbg_values > 1); 1747*4882a593Smuzhiyun push(@av_paren_type, $av_pending); 1748*4882a593Smuzhiyun $av_pending = '_'; 1749*4882a593Smuzhiyun $type = 'N'; 1750*4882a593Smuzhiyun 1751*4882a593Smuzhiyun } elsif ($cur =~ /^(\))/o) { 1752*4882a593Smuzhiyun my $new_type = pop(@av_paren_type); 1753*4882a593Smuzhiyun if ($new_type ne '_') { 1754*4882a593Smuzhiyun $type = $new_type; 1755*4882a593Smuzhiyun print "PAREN('$1') -> $type\n" 1756*4882a593Smuzhiyun if ($dbg_values > 1); 1757*4882a593Smuzhiyun } else { 1758*4882a593Smuzhiyun print "PAREN('$1')\n" if ($dbg_values > 1); 1759*4882a593Smuzhiyun } 1760*4882a593Smuzhiyun 1761*4882a593Smuzhiyun } elsif ($cur =~ /^($Ident)\s*\(/o) { 1762*4882a593Smuzhiyun print "FUNC($1)\n" if ($dbg_values > 1); 1763*4882a593Smuzhiyun $type = 'V'; 1764*4882a593Smuzhiyun $av_pending = 'V'; 1765*4882a593Smuzhiyun 1766*4882a593Smuzhiyun } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) { 1767*4882a593Smuzhiyun if (defined $2 && $type eq 'C' || $type eq 'T') { 1768*4882a593Smuzhiyun $av_pend_colon = 'B'; 1769*4882a593Smuzhiyun } elsif ($type eq 'E') { 1770*4882a593Smuzhiyun $av_pend_colon = 'L'; 1771*4882a593Smuzhiyun } 1772*4882a593Smuzhiyun print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1); 1773*4882a593Smuzhiyun $type = 'V'; 1774*4882a593Smuzhiyun 1775*4882a593Smuzhiyun } elsif ($cur =~ /^($Ident|$Constant)/o) { 1776*4882a593Smuzhiyun print "IDENT($1)\n" if ($dbg_values > 1); 1777*4882a593Smuzhiyun $type = 'V'; 1778*4882a593Smuzhiyun 1779*4882a593Smuzhiyun } elsif ($cur =~ /^($Assignment)/o) { 1780*4882a593Smuzhiyun print "ASSIGN($1)\n" if ($dbg_values > 1); 1781*4882a593Smuzhiyun $type = 'N'; 1782*4882a593Smuzhiyun 1783*4882a593Smuzhiyun } elsif ($cur =~/^(;|{|})/) { 1784*4882a593Smuzhiyun print "END($1)\n" if ($dbg_values > 1); 1785*4882a593Smuzhiyun $type = 'E'; 1786*4882a593Smuzhiyun $av_pend_colon = 'O'; 1787*4882a593Smuzhiyun 1788*4882a593Smuzhiyun } elsif ($cur =~/^(,)/) { 1789*4882a593Smuzhiyun print "COMMA($1)\n" if ($dbg_values > 1); 1790*4882a593Smuzhiyun $type = 'C'; 1791*4882a593Smuzhiyun 1792*4882a593Smuzhiyun } elsif ($cur =~ /^(\?)/o) { 1793*4882a593Smuzhiyun print "QUESTION($1)\n" if ($dbg_values > 1); 1794*4882a593Smuzhiyun $type = 'N'; 1795*4882a593Smuzhiyun 1796*4882a593Smuzhiyun } elsif ($cur =~ /^(:)/o) { 1797*4882a593Smuzhiyun print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1); 1798*4882a593Smuzhiyun 1799*4882a593Smuzhiyun substr($var, length($res), 1, $av_pend_colon); 1800*4882a593Smuzhiyun if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') { 1801*4882a593Smuzhiyun $type = 'E'; 1802*4882a593Smuzhiyun } else { 1803*4882a593Smuzhiyun $type = 'N'; 1804*4882a593Smuzhiyun } 1805*4882a593Smuzhiyun $av_pend_colon = 'O'; 1806*4882a593Smuzhiyun 1807*4882a593Smuzhiyun } elsif ($cur =~ /^(\[)/o) { 1808*4882a593Smuzhiyun print "CLOSE($1)\n" if ($dbg_values > 1); 1809*4882a593Smuzhiyun $type = 'N'; 1810*4882a593Smuzhiyun 1811*4882a593Smuzhiyun } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) { 1812*4882a593Smuzhiyun my $variant; 1813*4882a593Smuzhiyun 1814*4882a593Smuzhiyun print "OPV($1)\n" if ($dbg_values > 1); 1815*4882a593Smuzhiyun if ($type eq 'V') { 1816*4882a593Smuzhiyun $variant = 'B'; 1817*4882a593Smuzhiyun } else { 1818*4882a593Smuzhiyun $variant = 'U'; 1819*4882a593Smuzhiyun } 1820*4882a593Smuzhiyun 1821*4882a593Smuzhiyun substr($var, length($res), 1, $variant); 1822*4882a593Smuzhiyun $type = 'N'; 1823*4882a593Smuzhiyun 1824*4882a593Smuzhiyun } elsif ($cur =~ /^($Operators)/o) { 1825*4882a593Smuzhiyun print "OP($1)\n" if ($dbg_values > 1); 1826*4882a593Smuzhiyun if ($1 ne '++' && $1 ne '--') { 1827*4882a593Smuzhiyun $type = 'N'; 1828*4882a593Smuzhiyun } 1829*4882a593Smuzhiyun 1830*4882a593Smuzhiyun } elsif ($cur =~ /(^.)/o) { 1831*4882a593Smuzhiyun print "C($1)\n" if ($dbg_values > 1); 1832*4882a593Smuzhiyun } 1833*4882a593Smuzhiyun if (defined $1) { 1834*4882a593Smuzhiyun $cur = substr($cur, length($1)); 1835*4882a593Smuzhiyun $res .= $type x length($1); 1836*4882a593Smuzhiyun } 1837*4882a593Smuzhiyun } 1838*4882a593Smuzhiyun 1839*4882a593Smuzhiyun return ($res, $var); 1840*4882a593Smuzhiyun} 1841*4882a593Smuzhiyun 1842*4882a593Smuzhiyunsub possible { 1843*4882a593Smuzhiyun my ($possible, $line) = @_; 1844*4882a593Smuzhiyun my $notPermitted = qr{(?: 1845*4882a593Smuzhiyun ^(?: 1846*4882a593Smuzhiyun $Modifier| 1847*4882a593Smuzhiyun $Storage| 1848*4882a593Smuzhiyun $Type| 1849*4882a593Smuzhiyun DEFINE_\S+ 1850*4882a593Smuzhiyun )$| 1851*4882a593Smuzhiyun ^(?: 1852*4882a593Smuzhiyun goto| 1853*4882a593Smuzhiyun return| 1854*4882a593Smuzhiyun case| 1855*4882a593Smuzhiyun else| 1856*4882a593Smuzhiyun asm|__asm__| 1857*4882a593Smuzhiyun do| 1858*4882a593Smuzhiyun \#| 1859*4882a593Smuzhiyun \#\#| 1860*4882a593Smuzhiyun )(?:\s|$)| 1861*4882a593Smuzhiyun ^(?:typedef|struct|enum)\b 1862*4882a593Smuzhiyun )}x; 1863*4882a593Smuzhiyun warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2); 1864*4882a593Smuzhiyun if ($possible !~ $notPermitted) { 1865*4882a593Smuzhiyun # Check for modifiers. 1866*4882a593Smuzhiyun $possible =~ s/\s*$Storage\s*//g; 1867*4882a593Smuzhiyun $possible =~ s/\s*$Sparse\s*//g; 1868*4882a593Smuzhiyun if ($possible =~ /^\s*$/) { 1869*4882a593Smuzhiyun 1870*4882a593Smuzhiyun } elsif ($possible =~ /\s/) { 1871*4882a593Smuzhiyun $possible =~ s/\s*$Type\s*//g; 1872*4882a593Smuzhiyun for my $modifier (split(' ', $possible)) { 1873*4882a593Smuzhiyun if ($modifier !~ $notPermitted) { 1874*4882a593Smuzhiyun warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible); 1875*4882a593Smuzhiyun push(@modifierListFile, $modifier); 1876*4882a593Smuzhiyun } 1877*4882a593Smuzhiyun } 1878*4882a593Smuzhiyun 1879*4882a593Smuzhiyun } else { 1880*4882a593Smuzhiyun warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible); 1881*4882a593Smuzhiyun push(@typeListFile, $possible); 1882*4882a593Smuzhiyun } 1883*4882a593Smuzhiyun build_types(); 1884*4882a593Smuzhiyun } else { 1885*4882a593Smuzhiyun warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1); 1886*4882a593Smuzhiyun } 1887*4882a593Smuzhiyun} 1888*4882a593Smuzhiyun 1889*4882a593Smuzhiyunmy $prefix = ''; 1890*4882a593Smuzhiyun 1891*4882a593Smuzhiyunsub show_type { 1892*4882a593Smuzhiyun my ($type) = @_; 1893*4882a593Smuzhiyun 1894*4882a593Smuzhiyun $type =~ tr/[a-z]/[A-Z]/; 1895*4882a593Smuzhiyun 1896*4882a593Smuzhiyun return defined $use_type{$type} if (scalar keys %use_type > 0); 1897*4882a593Smuzhiyun 1898*4882a593Smuzhiyun return !defined $ignore_type{$type}; 1899*4882a593Smuzhiyun} 1900*4882a593Smuzhiyun 1901*4882a593Smuzhiyunsub report { 1902*4882a593Smuzhiyun my ($level, $type, $msg) = @_; 1903*4882a593Smuzhiyun 1904*4882a593Smuzhiyun if (!show_type($type) || 1905*4882a593Smuzhiyun (defined $tst_only && $msg !~ /\Q$tst_only\E/)) { 1906*4882a593Smuzhiyun return 0; 1907*4882a593Smuzhiyun } 1908*4882a593Smuzhiyun my $output = ''; 1909*4882a593Smuzhiyun if ($color) { 1910*4882a593Smuzhiyun if ($level eq 'ERROR') { 1911*4882a593Smuzhiyun $output .= RED; 1912*4882a593Smuzhiyun } elsif ($level eq 'WARNING') { 1913*4882a593Smuzhiyun $output .= YELLOW; 1914*4882a593Smuzhiyun } else { 1915*4882a593Smuzhiyun $output .= GREEN; 1916*4882a593Smuzhiyun } 1917*4882a593Smuzhiyun } 1918*4882a593Smuzhiyun $output .= $prefix . $level . ':'; 1919*4882a593Smuzhiyun if ($show_types) { 1920*4882a593Smuzhiyun $output .= BLUE if ($color); 1921*4882a593Smuzhiyun $output .= "$type:"; 1922*4882a593Smuzhiyun } 1923*4882a593Smuzhiyun $output .= RESET if ($color); 1924*4882a593Smuzhiyun $output .= ' ' . $msg . "\n"; 1925*4882a593Smuzhiyun 1926*4882a593Smuzhiyun if ($showfile) { 1927*4882a593Smuzhiyun my @lines = split("\n", $output, -1); 1928*4882a593Smuzhiyun splice(@lines, 1, 1); 1929*4882a593Smuzhiyun $output = join("\n", @lines); 1930*4882a593Smuzhiyun } 1931*4882a593Smuzhiyun $output = (split('\n', $output))[0] . "\n" if ($terse); 1932*4882a593Smuzhiyun 1933*4882a593Smuzhiyun push(our @report, $output); 1934*4882a593Smuzhiyun 1935*4882a593Smuzhiyun return 1; 1936*4882a593Smuzhiyun} 1937*4882a593Smuzhiyun 1938*4882a593Smuzhiyunsub report_dump { 1939*4882a593Smuzhiyun our @report; 1940*4882a593Smuzhiyun} 1941*4882a593Smuzhiyun 1942*4882a593Smuzhiyunsub fixup_current_range { 1943*4882a593Smuzhiyun my ($lineRef, $offset, $length) = @_; 1944*4882a593Smuzhiyun 1945*4882a593Smuzhiyun if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) { 1946*4882a593Smuzhiyun my $o = $1; 1947*4882a593Smuzhiyun my $l = $2; 1948*4882a593Smuzhiyun my $no = $o + $offset; 1949*4882a593Smuzhiyun my $nl = $l + $length; 1950*4882a593Smuzhiyun $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/; 1951*4882a593Smuzhiyun } 1952*4882a593Smuzhiyun} 1953*4882a593Smuzhiyun 1954*4882a593Smuzhiyunsub fix_inserted_deleted_lines { 1955*4882a593Smuzhiyun my ($linesRef, $insertedRef, $deletedRef) = @_; 1956*4882a593Smuzhiyun 1957*4882a593Smuzhiyun my $range_last_linenr = 0; 1958*4882a593Smuzhiyun my $delta_offset = 0; 1959*4882a593Smuzhiyun 1960*4882a593Smuzhiyun my $old_linenr = 0; 1961*4882a593Smuzhiyun my $new_linenr = 0; 1962*4882a593Smuzhiyun 1963*4882a593Smuzhiyun my $next_insert = 0; 1964*4882a593Smuzhiyun my $next_delete = 0; 1965*4882a593Smuzhiyun 1966*4882a593Smuzhiyun my @lines = (); 1967*4882a593Smuzhiyun 1968*4882a593Smuzhiyun my $inserted = @{$insertedRef}[$next_insert++]; 1969*4882a593Smuzhiyun my $deleted = @{$deletedRef}[$next_delete++]; 1970*4882a593Smuzhiyun 1971*4882a593Smuzhiyun foreach my $old_line (@{$linesRef}) { 1972*4882a593Smuzhiyun my $save_line = 1; 1973*4882a593Smuzhiyun my $line = $old_line; #don't modify the array 1974*4882a593Smuzhiyun if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename 1975*4882a593Smuzhiyun $delta_offset = 0; 1976*4882a593Smuzhiyun } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk 1977*4882a593Smuzhiyun $range_last_linenr = $new_linenr; 1978*4882a593Smuzhiyun fixup_current_range(\$line, $delta_offset, 0); 1979*4882a593Smuzhiyun } 1980*4882a593Smuzhiyun 1981*4882a593Smuzhiyun while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) { 1982*4882a593Smuzhiyun $deleted = @{$deletedRef}[$next_delete++]; 1983*4882a593Smuzhiyun $save_line = 0; 1984*4882a593Smuzhiyun fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1); 1985*4882a593Smuzhiyun } 1986*4882a593Smuzhiyun 1987*4882a593Smuzhiyun while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) { 1988*4882a593Smuzhiyun push(@lines, ${$inserted}{'LINE'}); 1989*4882a593Smuzhiyun $inserted = @{$insertedRef}[$next_insert++]; 1990*4882a593Smuzhiyun $new_linenr++; 1991*4882a593Smuzhiyun fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1); 1992*4882a593Smuzhiyun } 1993*4882a593Smuzhiyun 1994*4882a593Smuzhiyun if ($save_line) { 1995*4882a593Smuzhiyun push(@lines, $line); 1996*4882a593Smuzhiyun $new_linenr++; 1997*4882a593Smuzhiyun } 1998*4882a593Smuzhiyun 1999*4882a593Smuzhiyun $old_linenr++; 2000*4882a593Smuzhiyun } 2001*4882a593Smuzhiyun 2002*4882a593Smuzhiyun return @lines; 2003*4882a593Smuzhiyun} 2004*4882a593Smuzhiyun 2005*4882a593Smuzhiyunsub fix_insert_line { 2006*4882a593Smuzhiyun my ($linenr, $line) = @_; 2007*4882a593Smuzhiyun 2008*4882a593Smuzhiyun my $inserted = { 2009*4882a593Smuzhiyun LINENR => $linenr, 2010*4882a593Smuzhiyun LINE => $line, 2011*4882a593Smuzhiyun }; 2012*4882a593Smuzhiyun push(@fixed_inserted, $inserted); 2013*4882a593Smuzhiyun} 2014*4882a593Smuzhiyun 2015*4882a593Smuzhiyunsub fix_delete_line { 2016*4882a593Smuzhiyun my ($linenr, $line) = @_; 2017*4882a593Smuzhiyun 2018*4882a593Smuzhiyun my $deleted = { 2019*4882a593Smuzhiyun LINENR => $linenr, 2020*4882a593Smuzhiyun LINE => $line, 2021*4882a593Smuzhiyun }; 2022*4882a593Smuzhiyun 2023*4882a593Smuzhiyun push(@fixed_deleted, $deleted); 2024*4882a593Smuzhiyun} 2025*4882a593Smuzhiyun 2026*4882a593Smuzhiyunsub ERROR { 2027*4882a593Smuzhiyun my ($type, $msg) = @_; 2028*4882a593Smuzhiyun 2029*4882a593Smuzhiyun if (report("ERROR", $type, $msg)) { 2030*4882a593Smuzhiyun our $clean = 0; 2031*4882a593Smuzhiyun our $cnt_error++; 2032*4882a593Smuzhiyun return 1; 2033*4882a593Smuzhiyun } 2034*4882a593Smuzhiyun return 0; 2035*4882a593Smuzhiyun} 2036*4882a593Smuzhiyunsub WARN { 2037*4882a593Smuzhiyun my ($type, $msg) = @_; 2038*4882a593Smuzhiyun 2039*4882a593Smuzhiyun if (report("WARNING", $type, $msg)) { 2040*4882a593Smuzhiyun our $clean = 0; 2041*4882a593Smuzhiyun our $cnt_warn++; 2042*4882a593Smuzhiyun return 1; 2043*4882a593Smuzhiyun } 2044*4882a593Smuzhiyun return 0; 2045*4882a593Smuzhiyun} 2046*4882a593Smuzhiyunsub CHK { 2047*4882a593Smuzhiyun my ($type, $msg) = @_; 2048*4882a593Smuzhiyun 2049*4882a593Smuzhiyun if ($check && report("CHECK", $type, $msg)) { 2050*4882a593Smuzhiyun our $clean = 0; 2051*4882a593Smuzhiyun our $cnt_chk++; 2052*4882a593Smuzhiyun return 1; 2053*4882a593Smuzhiyun } 2054*4882a593Smuzhiyun return 0; 2055*4882a593Smuzhiyun} 2056*4882a593Smuzhiyun 2057*4882a593Smuzhiyunsub check_absolute_file { 2058*4882a593Smuzhiyun my ($absolute, $herecurr) = @_; 2059*4882a593Smuzhiyun my $file = $absolute; 2060*4882a593Smuzhiyun 2061*4882a593Smuzhiyun ##print "absolute<$absolute>\n"; 2062*4882a593Smuzhiyun 2063*4882a593Smuzhiyun # See if any suffix of this path is a path within the tree. 2064*4882a593Smuzhiyun while ($file =~ s@^[^/]*/@@) { 2065*4882a593Smuzhiyun if (-f "$root/$file") { 2066*4882a593Smuzhiyun ##print "file<$file>\n"; 2067*4882a593Smuzhiyun last; 2068*4882a593Smuzhiyun } 2069*4882a593Smuzhiyun } 2070*4882a593Smuzhiyun if (! -f _) { 2071*4882a593Smuzhiyun return 0; 2072*4882a593Smuzhiyun } 2073*4882a593Smuzhiyun 2074*4882a593Smuzhiyun # It is, so see if the prefix is acceptable. 2075*4882a593Smuzhiyun my $prefix = $absolute; 2076*4882a593Smuzhiyun substr($prefix, -length($file)) = ''; 2077*4882a593Smuzhiyun 2078*4882a593Smuzhiyun ##print "prefix<$prefix>\n"; 2079*4882a593Smuzhiyun if ($prefix ne ".../") { 2080*4882a593Smuzhiyun WARN("USE_RELATIVE_PATH", 2081*4882a593Smuzhiyun "use relative pathname instead of absolute in changelog text\n" . $herecurr); 2082*4882a593Smuzhiyun } 2083*4882a593Smuzhiyun} 2084*4882a593Smuzhiyun 2085*4882a593Smuzhiyunsub trim { 2086*4882a593Smuzhiyun my ($string) = @_; 2087*4882a593Smuzhiyun 2088*4882a593Smuzhiyun $string =~ s/^\s+|\s+$//g; 2089*4882a593Smuzhiyun 2090*4882a593Smuzhiyun return $string; 2091*4882a593Smuzhiyun} 2092*4882a593Smuzhiyun 2093*4882a593Smuzhiyunsub ltrim { 2094*4882a593Smuzhiyun my ($string) = @_; 2095*4882a593Smuzhiyun 2096*4882a593Smuzhiyun $string =~ s/^\s+//; 2097*4882a593Smuzhiyun 2098*4882a593Smuzhiyun return $string; 2099*4882a593Smuzhiyun} 2100*4882a593Smuzhiyun 2101*4882a593Smuzhiyunsub rtrim { 2102*4882a593Smuzhiyun my ($string) = @_; 2103*4882a593Smuzhiyun 2104*4882a593Smuzhiyun $string =~ s/\s+$//; 2105*4882a593Smuzhiyun 2106*4882a593Smuzhiyun return $string; 2107*4882a593Smuzhiyun} 2108*4882a593Smuzhiyun 2109*4882a593Smuzhiyunsub string_find_replace { 2110*4882a593Smuzhiyun my ($string, $find, $replace) = @_; 2111*4882a593Smuzhiyun 2112*4882a593Smuzhiyun $string =~ s/$find/$replace/g; 2113*4882a593Smuzhiyun 2114*4882a593Smuzhiyun return $string; 2115*4882a593Smuzhiyun} 2116*4882a593Smuzhiyun 2117*4882a593Smuzhiyunsub tabify { 2118*4882a593Smuzhiyun my ($leading) = @_; 2119*4882a593Smuzhiyun 2120*4882a593Smuzhiyun my $source_indent = 8; 2121*4882a593Smuzhiyun my $max_spaces_before_tab = $source_indent - 1; 2122*4882a593Smuzhiyun my $spaces_to_tab = " " x $source_indent; 2123*4882a593Smuzhiyun 2124*4882a593Smuzhiyun #convert leading spaces to tabs 2125*4882a593Smuzhiyun 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g; 2126*4882a593Smuzhiyun #Remove spaces before a tab 2127*4882a593Smuzhiyun 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g; 2128*4882a593Smuzhiyun 2129*4882a593Smuzhiyun return "$leading"; 2130*4882a593Smuzhiyun} 2131*4882a593Smuzhiyun 2132*4882a593Smuzhiyunsub pos_last_openparen { 2133*4882a593Smuzhiyun my ($line) = @_; 2134*4882a593Smuzhiyun 2135*4882a593Smuzhiyun my $pos = 0; 2136*4882a593Smuzhiyun 2137*4882a593Smuzhiyun my $opens = $line =~ tr/\(/\(/; 2138*4882a593Smuzhiyun my $closes = $line =~ tr/\)/\)/; 2139*4882a593Smuzhiyun 2140*4882a593Smuzhiyun my $last_openparen = 0; 2141*4882a593Smuzhiyun 2142*4882a593Smuzhiyun if (($opens == 0) || ($closes >= $opens)) { 2143*4882a593Smuzhiyun return -1; 2144*4882a593Smuzhiyun } 2145*4882a593Smuzhiyun 2146*4882a593Smuzhiyun my $len = length($line); 2147*4882a593Smuzhiyun 2148*4882a593Smuzhiyun for ($pos = 0; $pos < $len; $pos++) { 2149*4882a593Smuzhiyun my $string = substr($line, $pos); 2150*4882a593Smuzhiyun if ($string =~ /^($FuncArg|$balanced_parens)/) { 2151*4882a593Smuzhiyun $pos += length($1) - 1; 2152*4882a593Smuzhiyun } elsif (substr($line, $pos, 1) eq '(') { 2153*4882a593Smuzhiyun $last_openparen = $pos; 2154*4882a593Smuzhiyun } elsif (index($string, '(') == -1) { 2155*4882a593Smuzhiyun last; 2156*4882a593Smuzhiyun } 2157*4882a593Smuzhiyun } 2158*4882a593Smuzhiyun 2159*4882a593Smuzhiyun return length(expand_tabs(substr($line, 0, $last_openparen))) + 1; 2160*4882a593Smuzhiyun} 2161*4882a593Smuzhiyun 2162*4882a593Smuzhiyunsub process { 2163*4882a593Smuzhiyun my $filename = shift; 2164*4882a593Smuzhiyun 2165*4882a593Smuzhiyun my $linenr=0; 2166*4882a593Smuzhiyun my $prevline=""; 2167*4882a593Smuzhiyun my $prevrawline=""; 2168*4882a593Smuzhiyun my $stashline=""; 2169*4882a593Smuzhiyun my $stashrawline=""; 2170*4882a593Smuzhiyun 2171*4882a593Smuzhiyun my $length; 2172*4882a593Smuzhiyun my $indent; 2173*4882a593Smuzhiyun my $previndent=0; 2174*4882a593Smuzhiyun my $stashindent=0; 2175*4882a593Smuzhiyun 2176*4882a593Smuzhiyun our $clean = 1; 2177*4882a593Smuzhiyun my $signoff = 0; 2178*4882a593Smuzhiyun my $is_patch = 0; 2179*4882a593Smuzhiyun my $in_header_lines = $file ? 0 : 1; 2180*4882a593Smuzhiyun my $in_commit_log = 0; #Scanning lines before patch 2181*4882a593Smuzhiyun my $has_commit_log = 0; #Encountered lines before patch 2182*4882a593Smuzhiyun my $commit_log_possible_stack_dump = 0; 2183*4882a593Smuzhiyun my $commit_log_long_line = 0; 2184*4882a593Smuzhiyun my $commit_log_has_diff = 0; 2185*4882a593Smuzhiyun my $reported_maintainer_file = 0; 2186*4882a593Smuzhiyun my $non_utf8_charset = 0; 2187*4882a593Smuzhiyun 2188*4882a593Smuzhiyun my $last_blank_line = 0; 2189*4882a593Smuzhiyun my $last_coalesced_string_linenr = -1; 2190*4882a593Smuzhiyun 2191*4882a593Smuzhiyun our @report = (); 2192*4882a593Smuzhiyun our $cnt_lines = 0; 2193*4882a593Smuzhiyun our $cnt_error = 0; 2194*4882a593Smuzhiyun our $cnt_warn = 0; 2195*4882a593Smuzhiyun our $cnt_chk = 0; 2196*4882a593Smuzhiyun 2197*4882a593Smuzhiyun # Trace the real file/line as we go. 2198*4882a593Smuzhiyun my $realfile = ''; 2199*4882a593Smuzhiyun my $realline = 0; 2200*4882a593Smuzhiyun my $realcnt = 0; 2201*4882a593Smuzhiyun my $here = ''; 2202*4882a593Smuzhiyun my $context_function; #undef'd unless there's a known function 2203*4882a593Smuzhiyun my $in_comment = 0; 2204*4882a593Smuzhiyun my $comment_edge = 0; 2205*4882a593Smuzhiyun my $first_line = 0; 2206*4882a593Smuzhiyun my $p1_prefix = ''; 2207*4882a593Smuzhiyun 2208*4882a593Smuzhiyun my $prev_values = 'E'; 2209*4882a593Smuzhiyun 2210*4882a593Smuzhiyun # suppression flags 2211*4882a593Smuzhiyun my %suppress_ifbraces; 2212*4882a593Smuzhiyun my %suppress_whiletrailers; 2213*4882a593Smuzhiyun my %suppress_export; 2214*4882a593Smuzhiyun my $suppress_statement = 0; 2215*4882a593Smuzhiyun 2216*4882a593Smuzhiyun my %signatures = (); 2217*4882a593Smuzhiyun 2218*4882a593Smuzhiyun # Pre-scan the patch sanitizing the lines. 2219*4882a593Smuzhiyun # Pre-scan the patch looking for any __setup documentation. 2220*4882a593Smuzhiyun # 2221*4882a593Smuzhiyun my @setup_docs = (); 2222*4882a593Smuzhiyun my $setup_docs = 0; 2223*4882a593Smuzhiyun 2224*4882a593Smuzhiyun my $camelcase_file_seeded = 0; 2225*4882a593Smuzhiyun 2226*4882a593Smuzhiyun sanitise_line_reset(); 2227*4882a593Smuzhiyun my $line; 2228*4882a593Smuzhiyun foreach my $rawline (@rawlines) { 2229*4882a593Smuzhiyun $linenr++; 2230*4882a593Smuzhiyun $line = $rawline; 2231*4882a593Smuzhiyun 2232*4882a593Smuzhiyun push(@fixed, $rawline) if ($fix); 2233*4882a593Smuzhiyun 2234*4882a593Smuzhiyun if ($rawline=~/^\+\+\+\s+(\S+)/) { 2235*4882a593Smuzhiyun $setup_docs = 0; 2236*4882a593Smuzhiyun if ($1 =~ m@Documentation/admin-guide/kernel-parameters.rst$@) { 2237*4882a593Smuzhiyun $setup_docs = 1; 2238*4882a593Smuzhiyun } 2239*4882a593Smuzhiyun #next; 2240*4882a593Smuzhiyun } 2241*4882a593Smuzhiyun if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) { 2242*4882a593Smuzhiyun $realline=$1-1; 2243*4882a593Smuzhiyun if (defined $2) { 2244*4882a593Smuzhiyun $realcnt=$3+1; 2245*4882a593Smuzhiyun } else { 2246*4882a593Smuzhiyun $realcnt=1+1; 2247*4882a593Smuzhiyun } 2248*4882a593Smuzhiyun $in_comment = 0; 2249*4882a593Smuzhiyun 2250*4882a593Smuzhiyun # Guestimate if this is a continuing comment. Run 2251*4882a593Smuzhiyun # the context looking for a comment "edge". If this 2252*4882a593Smuzhiyun # edge is a close comment then we must be in a comment 2253*4882a593Smuzhiyun # at context start. 2254*4882a593Smuzhiyun my $edge; 2255*4882a593Smuzhiyun my $cnt = $realcnt; 2256*4882a593Smuzhiyun for (my $ln = $linenr + 1; $cnt > 0; $ln++) { 2257*4882a593Smuzhiyun next if (defined $rawlines[$ln - 1] && 2258*4882a593Smuzhiyun $rawlines[$ln - 1] =~ /^-/); 2259*4882a593Smuzhiyun $cnt--; 2260*4882a593Smuzhiyun #print "RAW<$rawlines[$ln - 1]>\n"; 2261*4882a593Smuzhiyun last if (!defined $rawlines[$ln - 1]); 2262*4882a593Smuzhiyun if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ && 2263*4882a593Smuzhiyun $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) { 2264*4882a593Smuzhiyun ($edge) = $1; 2265*4882a593Smuzhiyun last; 2266*4882a593Smuzhiyun } 2267*4882a593Smuzhiyun } 2268*4882a593Smuzhiyun if (defined $edge && $edge eq '*/') { 2269*4882a593Smuzhiyun $in_comment = 1; 2270*4882a593Smuzhiyun } 2271*4882a593Smuzhiyun 2272*4882a593Smuzhiyun # Guestimate if this is a continuing comment. If this 2273*4882a593Smuzhiyun # is the start of a diff block and this line starts 2274*4882a593Smuzhiyun # ' *' then it is very likely a comment. 2275*4882a593Smuzhiyun if (!defined $edge && 2276*4882a593Smuzhiyun $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@) 2277*4882a593Smuzhiyun { 2278*4882a593Smuzhiyun $in_comment = 1; 2279*4882a593Smuzhiyun } 2280*4882a593Smuzhiyun 2281*4882a593Smuzhiyun ##print "COMMENT:$in_comment edge<$edge> $rawline\n"; 2282*4882a593Smuzhiyun sanitise_line_reset($in_comment); 2283*4882a593Smuzhiyun 2284*4882a593Smuzhiyun } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) { 2285*4882a593Smuzhiyun # Standardise the strings and chars within the input to 2286*4882a593Smuzhiyun # simplify matching -- only bother with positive lines. 2287*4882a593Smuzhiyun $line = sanitise_line($rawline); 2288*4882a593Smuzhiyun } 2289*4882a593Smuzhiyun push(@lines, $line); 2290*4882a593Smuzhiyun 2291*4882a593Smuzhiyun if ($realcnt > 1) { 2292*4882a593Smuzhiyun $realcnt-- if ($line =~ /^(?:\+| |$)/); 2293*4882a593Smuzhiyun } else { 2294*4882a593Smuzhiyun $realcnt = 0; 2295*4882a593Smuzhiyun } 2296*4882a593Smuzhiyun 2297*4882a593Smuzhiyun #print "==>$rawline\n"; 2298*4882a593Smuzhiyun #print "-->$line\n"; 2299*4882a593Smuzhiyun 2300*4882a593Smuzhiyun if ($setup_docs && $line =~ /^\+/) { 2301*4882a593Smuzhiyun push(@setup_docs, $line); 2302*4882a593Smuzhiyun } 2303*4882a593Smuzhiyun } 2304*4882a593Smuzhiyun 2305*4882a593Smuzhiyun $prefix = ''; 2306*4882a593Smuzhiyun 2307*4882a593Smuzhiyun $realcnt = 0; 2308*4882a593Smuzhiyun $linenr = 0; 2309*4882a593Smuzhiyun $fixlinenr = -1; 2310*4882a593Smuzhiyun foreach my $line (@lines) { 2311*4882a593Smuzhiyun $linenr++; 2312*4882a593Smuzhiyun $fixlinenr++; 2313*4882a593Smuzhiyun my $sline = $line; #copy of $line 2314*4882a593Smuzhiyun $sline =~ s/$;/ /g; #with comments as spaces 2315*4882a593Smuzhiyun 2316*4882a593Smuzhiyun my $rawline = $rawlines[$linenr - 1]; 2317*4882a593Smuzhiyun 2318*4882a593Smuzhiyun#extract the line range in the file after the patch is applied 2319*4882a593Smuzhiyun if (!$in_commit_log && 2320*4882a593Smuzhiyun $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) { 2321*4882a593Smuzhiyun my $context = $4; 2322*4882a593Smuzhiyun $is_patch = 1; 2323*4882a593Smuzhiyun $first_line = $linenr + 1; 2324*4882a593Smuzhiyun $realline=$1-1; 2325*4882a593Smuzhiyun if (defined $2) { 2326*4882a593Smuzhiyun $realcnt=$3+1; 2327*4882a593Smuzhiyun } else { 2328*4882a593Smuzhiyun $realcnt=1+1; 2329*4882a593Smuzhiyun } 2330*4882a593Smuzhiyun annotate_reset(); 2331*4882a593Smuzhiyun $prev_values = 'E'; 2332*4882a593Smuzhiyun 2333*4882a593Smuzhiyun %suppress_ifbraces = (); 2334*4882a593Smuzhiyun %suppress_whiletrailers = (); 2335*4882a593Smuzhiyun %suppress_export = (); 2336*4882a593Smuzhiyun $suppress_statement = 0; 2337*4882a593Smuzhiyun if ($context =~ /\b(\w+)\s*\(/) { 2338*4882a593Smuzhiyun $context_function = $1; 2339*4882a593Smuzhiyun } else { 2340*4882a593Smuzhiyun undef $context_function; 2341*4882a593Smuzhiyun } 2342*4882a593Smuzhiyun next; 2343*4882a593Smuzhiyun 2344*4882a593Smuzhiyun# track the line number as we move through the hunk, note that 2345*4882a593Smuzhiyun# new versions of GNU diff omit the leading space on completely 2346*4882a593Smuzhiyun# blank context lines so we need to count that too. 2347*4882a593Smuzhiyun } elsif ($line =~ /^( |\+|$)/) { 2348*4882a593Smuzhiyun $realline++; 2349*4882a593Smuzhiyun $realcnt-- if ($realcnt != 0); 2350*4882a593Smuzhiyun 2351*4882a593Smuzhiyun # Measure the line length and indent. 2352*4882a593Smuzhiyun ($length, $indent) = line_stats($rawline); 2353*4882a593Smuzhiyun 2354*4882a593Smuzhiyun # Track the previous line. 2355*4882a593Smuzhiyun ($prevline, $stashline) = ($stashline, $line); 2356*4882a593Smuzhiyun ($previndent, $stashindent) = ($stashindent, $indent); 2357*4882a593Smuzhiyun ($prevrawline, $stashrawline) = ($stashrawline, $rawline); 2358*4882a593Smuzhiyun 2359*4882a593Smuzhiyun #warn "line<$line>\n"; 2360*4882a593Smuzhiyun 2361*4882a593Smuzhiyun } elsif ($realcnt == 1) { 2362*4882a593Smuzhiyun $realcnt--; 2363*4882a593Smuzhiyun } 2364*4882a593Smuzhiyun 2365*4882a593Smuzhiyun my $hunk_line = ($realcnt != 0); 2366*4882a593Smuzhiyun 2367*4882a593Smuzhiyun $here = "#$linenr: " if (!$file); 2368*4882a593Smuzhiyun $here = "#$realline: " if ($file); 2369*4882a593Smuzhiyun 2370*4882a593Smuzhiyun my $found_file = 0; 2371*4882a593Smuzhiyun # extract the filename as it passes 2372*4882a593Smuzhiyun if ($line =~ /^diff --git.*?(\S+)$/) { 2373*4882a593Smuzhiyun $realfile = $1; 2374*4882a593Smuzhiyun $realfile =~ s@^([^/]*)/@@ if (!$file); 2375*4882a593Smuzhiyun $in_commit_log = 0; 2376*4882a593Smuzhiyun $found_file = 1; 2377*4882a593Smuzhiyun } elsif ($line =~ /^\+\+\+\s+(\S+)/) { 2378*4882a593Smuzhiyun $realfile = $1; 2379*4882a593Smuzhiyun $realfile =~ s@^([^/]*)/@@ if (!$file); 2380*4882a593Smuzhiyun $in_commit_log = 0; 2381*4882a593Smuzhiyun 2382*4882a593Smuzhiyun $p1_prefix = $1; 2383*4882a593Smuzhiyun if (!$file && $tree && $p1_prefix ne '' && 2384*4882a593Smuzhiyun -e "$root/$p1_prefix") { 2385*4882a593Smuzhiyun WARN("PATCH_PREFIX", 2386*4882a593Smuzhiyun "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n"); 2387*4882a593Smuzhiyun } 2388*4882a593Smuzhiyun 2389*4882a593Smuzhiyun if ($realfile =~ m@^include/asm/@) { 2390*4882a593Smuzhiyun ERROR("MODIFIED_INCLUDE_ASM", 2391*4882a593Smuzhiyun "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n"); 2392*4882a593Smuzhiyun } 2393*4882a593Smuzhiyun $found_file = 1; 2394*4882a593Smuzhiyun } 2395*4882a593Smuzhiyun 2396*4882a593Smuzhiyun#make up the handle for any error we report on this line 2397*4882a593Smuzhiyun if ($showfile) { 2398*4882a593Smuzhiyun $prefix = "$realfile:$realline: " 2399*4882a593Smuzhiyun } elsif ($emacs) { 2400*4882a593Smuzhiyun if ($file) { 2401*4882a593Smuzhiyun $prefix = "$filename:$realline: "; 2402*4882a593Smuzhiyun } else { 2403*4882a593Smuzhiyun $prefix = "$filename:$linenr: "; 2404*4882a593Smuzhiyun } 2405*4882a593Smuzhiyun } 2406*4882a593Smuzhiyun 2407*4882a593Smuzhiyun if ($found_file) { 2408*4882a593Smuzhiyun if (is_maintained_obsolete($realfile)) { 2409*4882a593Smuzhiyun WARN("OBSOLETE", 2410*4882a593Smuzhiyun "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n"); 2411*4882a593Smuzhiyun } 2412*4882a593Smuzhiyun if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { 2413*4882a593Smuzhiyun $check = 1; 2414*4882a593Smuzhiyun } else { 2415*4882a593Smuzhiyun $check = $check_orig; 2416*4882a593Smuzhiyun } 2417*4882a593Smuzhiyun next; 2418*4882a593Smuzhiyun } 2419*4882a593Smuzhiyun 2420*4882a593Smuzhiyun $here .= "FILE: $realfile:$realline:" if ($realcnt != 0); 2421*4882a593Smuzhiyun 2422*4882a593Smuzhiyun my $hereline = "$here\n$rawline\n"; 2423*4882a593Smuzhiyun my $herecurr = "$here\n$rawline\n"; 2424*4882a593Smuzhiyun my $hereprev = "$here\n$prevrawline\n$rawline\n"; 2425*4882a593Smuzhiyun 2426*4882a593Smuzhiyun $cnt_lines++ if ($realcnt != 0); 2427*4882a593Smuzhiyun 2428*4882a593Smuzhiyun# Check if the commit log has what seems like a diff which can confuse patch 2429*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_has_diff && 2430*4882a593Smuzhiyun (($line =~ m@^\s+diff\b.*a/[\w/]+@ && 2431*4882a593Smuzhiyun $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) || 2432*4882a593Smuzhiyun $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ || 2433*4882a593Smuzhiyun $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) { 2434*4882a593Smuzhiyun ERROR("DIFF_IN_COMMIT_MSG", 2435*4882a593Smuzhiyun "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr); 2436*4882a593Smuzhiyun $commit_log_has_diff = 1; 2437*4882a593Smuzhiyun } 2438*4882a593Smuzhiyun 2439*4882a593Smuzhiyun# Check for incorrect file permissions 2440*4882a593Smuzhiyun if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) { 2441*4882a593Smuzhiyun my $permhere = $here . "FILE: $realfile\n"; 2442*4882a593Smuzhiyun if ($realfile !~ m@scripts/@ && 2443*4882a593Smuzhiyun $realfile !~ /\.(py|pl|awk|sh)$/) { 2444*4882a593Smuzhiyun ERROR("EXECUTE_PERMISSIONS", 2445*4882a593Smuzhiyun "do not set execute permissions for source files\n" . $permhere); 2446*4882a593Smuzhiyun } 2447*4882a593Smuzhiyun } 2448*4882a593Smuzhiyun 2449*4882a593Smuzhiyun# Check the patch for a signoff: 2450*4882a593Smuzhiyun if ($line =~ /^\s*signed-off-by:/i) { 2451*4882a593Smuzhiyun $signoff++; 2452*4882a593Smuzhiyun $in_commit_log = 0; 2453*4882a593Smuzhiyun } 2454*4882a593Smuzhiyun 2455*4882a593Smuzhiyun# Check if MAINTAINERS is being updated. If so, there's probably no need to 2456*4882a593Smuzhiyun# emit the "does MAINTAINERS need updating?" message on file add/move/delete 2457*4882a593Smuzhiyun if ($line =~ /^\s*MAINTAINERS\s*\|/) { 2458*4882a593Smuzhiyun $reported_maintainer_file = 1; 2459*4882a593Smuzhiyun } 2460*4882a593Smuzhiyun 2461*4882a593Smuzhiyun# Check signature styles 2462*4882a593Smuzhiyun if (!$in_header_lines && 2463*4882a593Smuzhiyun $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) { 2464*4882a593Smuzhiyun my $space_before = $1; 2465*4882a593Smuzhiyun my $sign_off = $2; 2466*4882a593Smuzhiyun my $space_after = $3; 2467*4882a593Smuzhiyun my $email = $4; 2468*4882a593Smuzhiyun my $ucfirst_sign_off = ucfirst(lc($sign_off)); 2469*4882a593Smuzhiyun 2470*4882a593Smuzhiyun if ($sign_off !~ /$signature_tags/) { 2471*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2472*4882a593Smuzhiyun "Non-standard signature: $sign_off\n" . $herecurr); 2473*4882a593Smuzhiyun } 2474*4882a593Smuzhiyun if (defined $space_before && $space_before ne "") { 2475*4882a593Smuzhiyun if (WARN("BAD_SIGN_OFF", 2476*4882a593Smuzhiyun "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) && 2477*4882a593Smuzhiyun $fix) { 2478*4882a593Smuzhiyun $fixed[$fixlinenr] = 2479*4882a593Smuzhiyun "$ucfirst_sign_off $email"; 2480*4882a593Smuzhiyun } 2481*4882a593Smuzhiyun } 2482*4882a593Smuzhiyun if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) { 2483*4882a593Smuzhiyun if (WARN("BAD_SIGN_OFF", 2484*4882a593Smuzhiyun "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) && 2485*4882a593Smuzhiyun $fix) { 2486*4882a593Smuzhiyun $fixed[$fixlinenr] = 2487*4882a593Smuzhiyun "$ucfirst_sign_off $email"; 2488*4882a593Smuzhiyun } 2489*4882a593Smuzhiyun 2490*4882a593Smuzhiyun } 2491*4882a593Smuzhiyun if (!defined $space_after || $space_after ne " ") { 2492*4882a593Smuzhiyun if (WARN("BAD_SIGN_OFF", 2493*4882a593Smuzhiyun "Use a single space after $ucfirst_sign_off\n" . $herecurr) && 2494*4882a593Smuzhiyun $fix) { 2495*4882a593Smuzhiyun $fixed[$fixlinenr] = 2496*4882a593Smuzhiyun "$ucfirst_sign_off $email"; 2497*4882a593Smuzhiyun } 2498*4882a593Smuzhiyun } 2499*4882a593Smuzhiyun 2500*4882a593Smuzhiyun my ($email_name, $email_address, $comment) = parse_email($email); 2501*4882a593Smuzhiyun my $suggested_email = format_email(($email_name, $email_address)); 2502*4882a593Smuzhiyun if ($suggested_email eq "") { 2503*4882a593Smuzhiyun ERROR("BAD_SIGN_OFF", 2504*4882a593Smuzhiyun "Unrecognized email address: '$email'\n" . $herecurr); 2505*4882a593Smuzhiyun } else { 2506*4882a593Smuzhiyun my $dequoted = $suggested_email; 2507*4882a593Smuzhiyun $dequoted =~ s/^"//; 2508*4882a593Smuzhiyun $dequoted =~ s/" </ </; 2509*4882a593Smuzhiyun # Don't force email to have quotes 2510*4882a593Smuzhiyun # Allow just an angle bracketed address 2511*4882a593Smuzhiyun if ("$dequoted$comment" ne $email && 2512*4882a593Smuzhiyun "<$email_address>$comment" ne $email && 2513*4882a593Smuzhiyun "$suggested_email$comment" ne $email) { 2514*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2515*4882a593Smuzhiyun "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr); 2516*4882a593Smuzhiyun } 2517*4882a593Smuzhiyun } 2518*4882a593Smuzhiyun 2519*4882a593Smuzhiyun# Check for duplicate signatures 2520*4882a593Smuzhiyun my $sig_nospace = $line; 2521*4882a593Smuzhiyun $sig_nospace =~ s/\s//g; 2522*4882a593Smuzhiyun $sig_nospace = lc($sig_nospace); 2523*4882a593Smuzhiyun if (defined $signatures{$sig_nospace}) { 2524*4882a593Smuzhiyun WARN("BAD_SIGN_OFF", 2525*4882a593Smuzhiyun "Duplicate signature\n" . $herecurr); 2526*4882a593Smuzhiyun } else { 2527*4882a593Smuzhiyun $signatures{$sig_nospace} = 1; 2528*4882a593Smuzhiyun } 2529*4882a593Smuzhiyun } 2530*4882a593Smuzhiyun 2531*4882a593Smuzhiyun# Check email subject for common tools that don't need to be mentioned 2532*4882a593Smuzhiyun if ($in_header_lines && 2533*4882a593Smuzhiyun $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) { 2534*4882a593Smuzhiyun WARN("EMAIL_SUBJECT", 2535*4882a593Smuzhiyun "A patch subject line should describe the change not the tool that found it\n" . $herecurr); 2536*4882a593Smuzhiyun } 2537*4882a593Smuzhiyun 2538*4882a593Smuzhiyun# Check for old stable address 2539*4882a593Smuzhiyun if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) { 2540*4882a593Smuzhiyun ERROR("STABLE_ADDRESS", 2541*4882a593Smuzhiyun "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr); 2542*4882a593Smuzhiyun } 2543*4882a593Smuzhiyun 2544*4882a593Smuzhiyun# Check for unwanted Gerrit info 2545*4882a593Smuzhiyun if ($in_commit_log && $line =~ /^\s*change-id:/i) { 2546*4882a593Smuzhiyun ERROR("GERRIT_CHANGE_ID", 2547*4882a593Smuzhiyun "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr); 2548*4882a593Smuzhiyun } 2549*4882a593Smuzhiyun 2550*4882a593Smuzhiyun# Check if the commit log is in a possible stack dump 2551*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_possible_stack_dump && 2552*4882a593Smuzhiyun ($line =~ /^\s*(?:WARNING:|BUG:)/ || 2553*4882a593Smuzhiyun $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ || 2554*4882a593Smuzhiyun # timestamp 2555*4882a593Smuzhiyun $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) { 2556*4882a593Smuzhiyun # stack dump address 2557*4882a593Smuzhiyun $commit_log_possible_stack_dump = 1; 2558*4882a593Smuzhiyun } 2559*4882a593Smuzhiyun 2560*4882a593Smuzhiyun# Check for line lengths > 75 in commit log, warn once 2561*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_long_line && 2562*4882a593Smuzhiyun length($line) > 75 && 2563*4882a593Smuzhiyun !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ || 2564*4882a593Smuzhiyun # file delta changes 2565*4882a593Smuzhiyun $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ || 2566*4882a593Smuzhiyun # filename then : 2567*4882a593Smuzhiyun $line =~ /^\s*(?:Fixes:|Link:)/i || 2568*4882a593Smuzhiyun # A Fixes: or Link: line 2569*4882a593Smuzhiyun $commit_log_possible_stack_dump)) { 2570*4882a593Smuzhiyun WARN("COMMIT_LOG_LONG_LINE", 2571*4882a593Smuzhiyun "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr); 2572*4882a593Smuzhiyun $commit_log_long_line = 1; 2573*4882a593Smuzhiyun } 2574*4882a593Smuzhiyun 2575*4882a593Smuzhiyun# Reset possible stack dump if a blank line is found 2576*4882a593Smuzhiyun if ($in_commit_log && $commit_log_possible_stack_dump && 2577*4882a593Smuzhiyun $line =~ /^\s*$/) { 2578*4882a593Smuzhiyun $commit_log_possible_stack_dump = 0; 2579*4882a593Smuzhiyun } 2580*4882a593Smuzhiyun 2581*4882a593Smuzhiyun# Check for git id commit length and improperly formed commit descriptions 2582*4882a593Smuzhiyun if ($in_commit_log && !$commit_log_possible_stack_dump && 2583*4882a593Smuzhiyun $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i && 2584*4882a593Smuzhiyun $line !~ /^This reverts commit [0-9a-f]{7,40}/ && 2585*4882a593Smuzhiyun ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i || 2586*4882a593Smuzhiyun ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i && 2587*4882a593Smuzhiyun $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i && 2588*4882a593Smuzhiyun $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) { 2589*4882a593Smuzhiyun my $init_char = "c"; 2590*4882a593Smuzhiyun my $orig_commit = ""; 2591*4882a593Smuzhiyun my $short = 1; 2592*4882a593Smuzhiyun my $long = 0; 2593*4882a593Smuzhiyun my $case = 1; 2594*4882a593Smuzhiyun my $space = 1; 2595*4882a593Smuzhiyun my $hasdesc = 0; 2596*4882a593Smuzhiyun my $hasparens = 0; 2597*4882a593Smuzhiyun my $id = '0123456789ab'; 2598*4882a593Smuzhiyun my $orig_desc = "commit description"; 2599*4882a593Smuzhiyun my $description = ""; 2600*4882a593Smuzhiyun 2601*4882a593Smuzhiyun if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) { 2602*4882a593Smuzhiyun $init_char = $1; 2603*4882a593Smuzhiyun $orig_commit = lc($2); 2604*4882a593Smuzhiyun } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) { 2605*4882a593Smuzhiyun $orig_commit = lc($1); 2606*4882a593Smuzhiyun } 2607*4882a593Smuzhiyun 2608*4882a593Smuzhiyun $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i); 2609*4882a593Smuzhiyun $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i); 2610*4882a593Smuzhiyun $space = 0 if ($line =~ /\bcommit [0-9a-f]/i); 2611*4882a593Smuzhiyun $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/); 2612*4882a593Smuzhiyun if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) { 2613*4882a593Smuzhiyun $orig_desc = $1; 2614*4882a593Smuzhiyun $hasparens = 1; 2615*4882a593Smuzhiyun } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i && 2616*4882a593Smuzhiyun defined $rawlines[$linenr] && 2617*4882a593Smuzhiyun $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) { 2618*4882a593Smuzhiyun $orig_desc = $1; 2619*4882a593Smuzhiyun $hasparens = 1; 2620*4882a593Smuzhiyun } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i && 2621*4882a593Smuzhiyun defined $rawlines[$linenr] && 2622*4882a593Smuzhiyun $rawlines[$linenr] =~ /^\s*[^"]+"\)/) { 2623*4882a593Smuzhiyun $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i; 2624*4882a593Smuzhiyun $orig_desc = $1; 2625*4882a593Smuzhiyun $rawlines[$linenr] =~ /^\s*([^"]+)"\)/; 2626*4882a593Smuzhiyun $orig_desc .= " " . $1; 2627*4882a593Smuzhiyun $hasparens = 1; 2628*4882a593Smuzhiyun } 2629*4882a593Smuzhiyun 2630*4882a593Smuzhiyun ($id, $description) = git_commit_info($orig_commit, 2631*4882a593Smuzhiyun $id, $orig_desc); 2632*4882a593Smuzhiyun 2633*4882a593Smuzhiyun if (defined($id) && 2634*4882a593Smuzhiyun ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) { 2635*4882a593Smuzhiyun ERROR("GIT_COMMIT_ID", 2636*4882a593Smuzhiyun "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr); 2637*4882a593Smuzhiyun } 2638*4882a593Smuzhiyun } 2639*4882a593Smuzhiyun 2640*4882a593Smuzhiyun# Check for added, moved or deleted files 2641*4882a593Smuzhiyun if (!$reported_maintainer_file && !$in_commit_log && 2642*4882a593Smuzhiyun ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || 2643*4882a593Smuzhiyun $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || 2644*4882a593Smuzhiyun ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && 2645*4882a593Smuzhiyun (defined($1) || defined($2))))) { 2646*4882a593Smuzhiyun $is_patch = 1; 2647*4882a593Smuzhiyun $reported_maintainer_file = 1; 2648*4882a593Smuzhiyun WARN("FILE_PATH_CHANGES", 2649*4882a593Smuzhiyun "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); 2650*4882a593Smuzhiyun } 2651*4882a593Smuzhiyun 2652*4882a593Smuzhiyun# Check for wrappage within a valid hunk of the file 2653*4882a593Smuzhiyun if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { 2654*4882a593Smuzhiyun ERROR("CORRUPTED_PATCH", 2655*4882a593Smuzhiyun "patch seems to be corrupt (line wrapped?)\n" . 2656*4882a593Smuzhiyun $herecurr) if (!$emitted_corrupt++); 2657*4882a593Smuzhiyun } 2658*4882a593Smuzhiyun 2659*4882a593Smuzhiyun# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php 2660*4882a593Smuzhiyun if (($realfile =~ /^$/ || $line =~ /^\+/) && 2661*4882a593Smuzhiyun $rawline !~ m/^$UTF8*$/) { 2662*4882a593Smuzhiyun my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/); 2663*4882a593Smuzhiyun 2664*4882a593Smuzhiyun my $blank = copy_spacing($rawline); 2665*4882a593Smuzhiyun my $ptr = substr($blank, 0, length($utf8_prefix)) . "^"; 2666*4882a593Smuzhiyun my $hereptr = "$hereline$ptr\n"; 2667*4882a593Smuzhiyun 2668*4882a593Smuzhiyun CHK("INVALID_UTF8", 2669*4882a593Smuzhiyun "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); 2670*4882a593Smuzhiyun } 2671*4882a593Smuzhiyun 2672*4882a593Smuzhiyun# Check if it's the start of a commit log 2673*4882a593Smuzhiyun# (not a header line and we haven't seen the patch filename) 2674*4882a593Smuzhiyun if ($in_header_lines && $realfile =~ /^$/ && 2675*4882a593Smuzhiyun !($rawline =~ /^\s+(?:\S|$)/ || 2676*4882a593Smuzhiyun $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) { 2677*4882a593Smuzhiyun $in_header_lines = 0; 2678*4882a593Smuzhiyun $in_commit_log = 1; 2679*4882a593Smuzhiyun $has_commit_log = 1; 2680*4882a593Smuzhiyun } 2681*4882a593Smuzhiyun 2682*4882a593Smuzhiyun# Check if there is UTF-8 in a commit log when a mail header has explicitly 2683*4882a593Smuzhiyun# declined it, i.e defined some charset where it is missing. 2684*4882a593Smuzhiyun if ($in_header_lines && 2685*4882a593Smuzhiyun $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && 2686*4882a593Smuzhiyun $1 !~ /utf-8/i) { 2687*4882a593Smuzhiyun $non_utf8_charset = 1; 2688*4882a593Smuzhiyun } 2689*4882a593Smuzhiyun 2690*4882a593Smuzhiyun if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && 2691*4882a593Smuzhiyun $rawline =~ /$NON_ASCII_UTF8/) { 2692*4882a593Smuzhiyun WARN("UTF8_BEFORE_PATCH", 2693*4882a593Smuzhiyun "8-bit UTF-8 used in possible commit log\n" . $herecurr); 2694*4882a593Smuzhiyun } 2695*4882a593Smuzhiyun 2696*4882a593Smuzhiyun# Check for absolute kernel paths in commit message 2697*4882a593Smuzhiyun if ($tree && $in_commit_log) { 2698*4882a593Smuzhiyun while ($line =~ m{(?:^|\s)(/\S*)}g) { 2699*4882a593Smuzhiyun my $file = $1; 2700*4882a593Smuzhiyun 2701*4882a593Smuzhiyun if ($file =~ m{^(.*?)(?::\d+)+:?$} && 2702*4882a593Smuzhiyun check_absolute_file($1, $herecurr)) { 2703*4882a593Smuzhiyun # 2704*4882a593Smuzhiyun } else { 2705*4882a593Smuzhiyun check_absolute_file($file, $herecurr); 2706*4882a593Smuzhiyun } 2707*4882a593Smuzhiyun } 2708*4882a593Smuzhiyun } 2709*4882a593Smuzhiyun 2710*4882a593Smuzhiyun# Check for various typo / spelling mistakes 2711*4882a593Smuzhiyun if (defined($misspellings) && 2712*4882a593Smuzhiyun ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) { 2713*4882a593Smuzhiyun while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) { 2714*4882a593Smuzhiyun my $typo = $1; 2715*4882a593Smuzhiyun my $typo_fix = $spelling_fix{lc($typo)}; 2716*4882a593Smuzhiyun $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/); 2717*4882a593Smuzhiyun $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/); 2718*4882a593Smuzhiyun my $msg_type = \&WARN; 2719*4882a593Smuzhiyun $msg_type = \&CHK if ($file); 2720*4882a593Smuzhiyun if (&{$msg_type}("TYPO_SPELLING", 2721*4882a593Smuzhiyun "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) && 2722*4882a593Smuzhiyun $fix) { 2723*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/; 2724*4882a593Smuzhiyun } 2725*4882a593Smuzhiyun } 2726*4882a593Smuzhiyun } 2727*4882a593Smuzhiyun 2728*4882a593Smuzhiyun# ignore non-hunk lines and lines being removed 2729*4882a593Smuzhiyun next if (!$hunk_line || $line =~ /^-/); 2730*4882a593Smuzhiyun 2731*4882a593Smuzhiyun#trailing whitespace 2732*4882a593Smuzhiyun if ($line =~ /^\+.*\015/) { 2733*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 2734*4882a593Smuzhiyun if (ERROR("DOS_LINE_ENDINGS", 2735*4882a593Smuzhiyun "DOS line endings\n" . $herevet) && 2736*4882a593Smuzhiyun $fix) { 2737*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/[\s\015]+$//; 2738*4882a593Smuzhiyun } 2739*4882a593Smuzhiyun } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) { 2740*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 2741*4882a593Smuzhiyun if (ERROR("TRAILING_WHITESPACE", 2742*4882a593Smuzhiyun "trailing whitespace\n" . $herevet) && 2743*4882a593Smuzhiyun $fix) { 2744*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s+$//; 2745*4882a593Smuzhiyun } 2746*4882a593Smuzhiyun 2747*4882a593Smuzhiyun $rpt_cleaners = 1; 2748*4882a593Smuzhiyun } 2749*4882a593Smuzhiyun 2750*4882a593Smuzhiyun# Check for FSF mailing addresses. 2751*4882a593Smuzhiyun if ($rawline =~ /\bwrite to the Free/i || 2752*4882a593Smuzhiyun $rawline =~ /\b675\s+Mass\s+Ave/i || 2753*4882a593Smuzhiyun $rawline =~ /\b59\s+Temple\s+Pl/i || 2754*4882a593Smuzhiyun $rawline =~ /\b51\s+Franklin\s+St/i) { 2755*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 2756*4882a593Smuzhiyun my $msg_type = \&ERROR; 2757*4882a593Smuzhiyun $msg_type = \&CHK if ($file); 2758*4882a593Smuzhiyun &{$msg_type}("FSF_MAILING_ADDRESS", 2759*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) 2760*4882a593Smuzhiyun } 2761*4882a593Smuzhiyun 2762*4882a593Smuzhiyun# check for Kconfig help text having a real description 2763*4882a593Smuzhiyun# Only applies when adding the entry originally, after that we do not have 2764*4882a593Smuzhiyun# sufficient context to determine whether it is indeed long enough. 2765*4882a593Smuzhiyun if ($realfile =~ /Kconfig/ && 2766*4882a593Smuzhiyun $line =~ /^\+\s*config\s+/) { 2767*4882a593Smuzhiyun my $length = 0; 2768*4882a593Smuzhiyun my $cnt = $realcnt; 2769*4882a593Smuzhiyun my $ln = $linenr + 1; 2770*4882a593Smuzhiyun my $f; 2771*4882a593Smuzhiyun my $is_start = 0; 2772*4882a593Smuzhiyun my $is_end = 0; 2773*4882a593Smuzhiyun for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) { 2774*4882a593Smuzhiyun $f = $lines[$ln - 1]; 2775*4882a593Smuzhiyun $cnt-- if ($lines[$ln - 1] !~ /^-/); 2776*4882a593Smuzhiyun $is_end = $lines[$ln - 1] =~ /^\+/; 2777*4882a593Smuzhiyun 2778*4882a593Smuzhiyun next if ($f =~ /^-/); 2779*4882a593Smuzhiyun last if (!$file && $f =~ /^\@\@/); 2780*4882a593Smuzhiyun 2781*4882a593Smuzhiyun if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) { 2782*4882a593Smuzhiyun $is_start = 1; 2783*4882a593Smuzhiyun } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) { 2784*4882a593Smuzhiyun $length = -1; 2785*4882a593Smuzhiyun } 2786*4882a593Smuzhiyun 2787*4882a593Smuzhiyun $f =~ s/^.//; 2788*4882a593Smuzhiyun $f =~ s/#.*//; 2789*4882a593Smuzhiyun $f =~ s/^\s+//; 2790*4882a593Smuzhiyun next if ($f =~ /^$/); 2791*4882a593Smuzhiyun if ($f =~ /^\s*config\s/) { 2792*4882a593Smuzhiyun $is_end = 1; 2793*4882a593Smuzhiyun last; 2794*4882a593Smuzhiyun } 2795*4882a593Smuzhiyun $length++; 2796*4882a593Smuzhiyun } 2797*4882a593Smuzhiyun if ($is_start && $is_end && $length < $min_conf_desc_length) { 2798*4882a593Smuzhiyun WARN("CONFIG_DESCRIPTION", 2799*4882a593Smuzhiyun "please write a paragraph that describes the config symbol fully\n" . $herecurr); 2800*4882a593Smuzhiyun } 2801*4882a593Smuzhiyun #print "is_start<$is_start> is_end<$is_end> length<$length>\n"; 2802*4882a593Smuzhiyun } 2803*4882a593Smuzhiyun 2804*4882a593Smuzhiyun# check for MAINTAINERS entries that don't have the right form 2805*4882a593Smuzhiyun if ($realfile =~ /^MAINTAINERS$/ && 2806*4882a593Smuzhiyun $rawline =~ /^\+[A-Z]:/ && 2807*4882a593Smuzhiyun $rawline !~ /^\+[A-Z]:\t\S/) { 2808*4882a593Smuzhiyun if (WARN("MAINTAINERS_STYLE", 2809*4882a593Smuzhiyun "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) && 2810*4882a593Smuzhiyun $fix) { 2811*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/; 2812*4882a593Smuzhiyun } 2813*4882a593Smuzhiyun } 2814*4882a593Smuzhiyun 2815*4882a593Smuzhiyun# discourage the use of boolean for type definition attributes of Kconfig options 2816*4882a593Smuzhiyun if ($realfile =~ /Kconfig/ && 2817*4882a593Smuzhiyun $line =~ /^\+\s*\bboolean\b/) { 2818*4882a593Smuzhiyun WARN("CONFIG_TYPE_BOOLEAN", 2819*4882a593Smuzhiyun "Use of boolean is deprecated, please use bool instead.\n" . $herecurr); 2820*4882a593Smuzhiyun } 2821*4882a593Smuzhiyun 2822*4882a593Smuzhiyun if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) && 2823*4882a593Smuzhiyun ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) { 2824*4882a593Smuzhiyun my $flag = $1; 2825*4882a593Smuzhiyun my $replacement = { 2826*4882a593Smuzhiyun 'EXTRA_AFLAGS' => 'asflags-y', 2827*4882a593Smuzhiyun 'EXTRA_CFLAGS' => 'ccflags-y', 2828*4882a593Smuzhiyun 'EXTRA_CPPFLAGS' => 'cppflags-y', 2829*4882a593Smuzhiyun 'EXTRA_LDFLAGS' => 'ldflags-y', 2830*4882a593Smuzhiyun }; 2831*4882a593Smuzhiyun 2832*4882a593Smuzhiyun WARN("DEPRECATED_VARIABLE", 2833*4882a593Smuzhiyun "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag}); 2834*4882a593Smuzhiyun } 2835*4882a593Smuzhiyun 2836*4882a593Smuzhiyun# check for DT compatible documentation 2837*4882a593Smuzhiyun if (defined $root && 2838*4882a593Smuzhiyun (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) || 2839*4882a593Smuzhiyun ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) { 2840*4882a593Smuzhiyun 2841*4882a593Smuzhiyun my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g; 2842*4882a593Smuzhiyun 2843*4882a593Smuzhiyun my $dt_path = $root . "/Documentation/devicetree/bindings/"; 2844*4882a593Smuzhiyun my $vp_file = $dt_path . "vendor-prefixes.txt"; 2845*4882a593Smuzhiyun 2846*4882a593Smuzhiyun foreach my $compat (@compats) { 2847*4882a593Smuzhiyun my $compat2 = $compat; 2848*4882a593Smuzhiyun $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/; 2849*4882a593Smuzhiyun my $compat3 = $compat; 2850*4882a593Smuzhiyun $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/; 2851*4882a593Smuzhiyun `grep -Erq "$compat|$compat2|$compat3" $dt_path`; 2852*4882a593Smuzhiyun if ( $? >> 8 ) { 2853*4882a593Smuzhiyun WARN("UNDOCUMENTED_DT_STRING", 2854*4882a593Smuzhiyun "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr); 2855*4882a593Smuzhiyun } 2856*4882a593Smuzhiyun 2857*4882a593Smuzhiyun next if $compat !~ /^([a-zA-Z0-9\-]+)\,/; 2858*4882a593Smuzhiyun my $vendor = $1; 2859*4882a593Smuzhiyun `grep -Eq "^$vendor\\b" $vp_file`; 2860*4882a593Smuzhiyun if ( $? >> 8 ) { 2861*4882a593Smuzhiyun WARN("UNDOCUMENTED_DT_STRING", 2862*4882a593Smuzhiyun "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr); 2863*4882a593Smuzhiyun } 2864*4882a593Smuzhiyun } 2865*4882a593Smuzhiyun } 2866*4882a593Smuzhiyun 2867*4882a593Smuzhiyun# check we are in a valid source file if not then ignore this hunk 2868*4882a593Smuzhiyun next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); 2869*4882a593Smuzhiyun 2870*4882a593Smuzhiyun# line length limit (with some exclusions) 2871*4882a593Smuzhiyun# 2872*4882a593Smuzhiyun# There are a few types of lines that may extend beyond $max_line_length: 2873*4882a593Smuzhiyun# logging functions like pr_info that end in a string 2874*4882a593Smuzhiyun# lines with a single string 2875*4882a593Smuzhiyun# #defines that are a single string 2876*4882a593Smuzhiyun# 2877*4882a593Smuzhiyun# There are 3 different line length message types: 2878*4882a593Smuzhiyun# LONG_LINE_COMMENT a comment starts before but extends beyond $max_linelength 2879*4882a593Smuzhiyun# LONG_LINE_STRING a string starts before but extends beyond $max_line_length 2880*4882a593Smuzhiyun# LONG_LINE all other lines longer than $max_line_length 2881*4882a593Smuzhiyun# 2882*4882a593Smuzhiyun# if LONG_LINE is ignored, the other 2 types are also ignored 2883*4882a593Smuzhiyun# 2884*4882a593Smuzhiyun 2885*4882a593Smuzhiyun if ($line =~ /^\+/ && $length > $max_line_length) { 2886*4882a593Smuzhiyun my $msg_type = "LONG_LINE"; 2887*4882a593Smuzhiyun 2888*4882a593Smuzhiyun # Check the allowed long line types first 2889*4882a593Smuzhiyun 2890*4882a593Smuzhiyun # logging functions that end in a string that starts 2891*4882a593Smuzhiyun # before $max_line_length 2892*4882a593Smuzhiyun if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ && 2893*4882a593Smuzhiyun length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { 2894*4882a593Smuzhiyun $msg_type = ""; 2895*4882a593Smuzhiyun 2896*4882a593Smuzhiyun # lines with only strings (w/ possible termination) 2897*4882a593Smuzhiyun # #defines with only strings 2898*4882a593Smuzhiyun } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ || 2899*4882a593Smuzhiyun $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) { 2900*4882a593Smuzhiyun $msg_type = ""; 2901*4882a593Smuzhiyun 2902*4882a593Smuzhiyun # EFI_GUID is another special case 2903*4882a593Smuzhiyun } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/) { 2904*4882a593Smuzhiyun $msg_type = ""; 2905*4882a593Smuzhiyun 2906*4882a593Smuzhiyun # Otherwise set the alternate message types 2907*4882a593Smuzhiyun 2908*4882a593Smuzhiyun # a comment starts before $max_line_length 2909*4882a593Smuzhiyun } elsif ($line =~ /($;[\s$;]*)$/ && 2910*4882a593Smuzhiyun length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { 2911*4882a593Smuzhiyun $msg_type = "LONG_LINE_COMMENT" 2912*4882a593Smuzhiyun 2913*4882a593Smuzhiyun # a quoted string starts before $max_line_length 2914*4882a593Smuzhiyun } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ && 2915*4882a593Smuzhiyun length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) { 2916*4882a593Smuzhiyun $msg_type = "LONG_LINE_STRING" 2917*4882a593Smuzhiyun } 2918*4882a593Smuzhiyun 2919*4882a593Smuzhiyun if ($msg_type ne "" && 2920*4882a593Smuzhiyun (show_type("LONG_LINE") || show_type($msg_type))) { 2921*4882a593Smuzhiyun WARN($msg_type, 2922*4882a593Smuzhiyun "line over $max_line_length characters\n" . $herecurr); 2923*4882a593Smuzhiyun } 2924*4882a593Smuzhiyun } 2925*4882a593Smuzhiyun 2926*4882a593Smuzhiyun# check for adding lines without a newline. 2927*4882a593Smuzhiyun if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) { 2928*4882a593Smuzhiyun WARN("MISSING_EOF_NEWLINE", 2929*4882a593Smuzhiyun "adding a line without newline at end of file\n" . $herecurr); 2930*4882a593Smuzhiyun } 2931*4882a593Smuzhiyun 2932*4882a593Smuzhiyun# Blackfin: use hi/lo macros 2933*4882a593Smuzhiyun if ($realfile =~ m@arch/blackfin/.*\.S$@) { 2934*4882a593Smuzhiyun if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) { 2935*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($line) . "\n"; 2936*4882a593Smuzhiyun ERROR("LO_MACRO", 2937*4882a593Smuzhiyun "use the LO() macro, not (... & 0xFFFF)\n" . $herevet); 2938*4882a593Smuzhiyun } 2939*4882a593Smuzhiyun if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) { 2940*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($line) . "\n"; 2941*4882a593Smuzhiyun ERROR("HI_MACRO", 2942*4882a593Smuzhiyun "use the HI() macro, not (... >> 16)\n" . $herevet); 2943*4882a593Smuzhiyun } 2944*4882a593Smuzhiyun } 2945*4882a593Smuzhiyun 2946*4882a593Smuzhiyun# check we are in a valid source file C or perl if not then ignore this hunk 2947*4882a593Smuzhiyun next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/); 2948*4882a593Smuzhiyun 2949*4882a593Smuzhiyun# at the beginning of a line any tabs must come first and anything 2950*4882a593Smuzhiyun# more than 8 must use tabs. 2951*4882a593Smuzhiyun if ($rawline =~ /^\+\s* \t\s*\S/ || 2952*4882a593Smuzhiyun $rawline =~ /^\+\s* \s*/) { 2953*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 2954*4882a593Smuzhiyun $rpt_cleaners = 1; 2955*4882a593Smuzhiyun if (ERROR("CODE_INDENT", 2956*4882a593Smuzhiyun "code indent should use tabs where possible\n" . $herevet) && 2957*4882a593Smuzhiyun $fix) { 2958*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; 2959*4882a593Smuzhiyun } 2960*4882a593Smuzhiyun } 2961*4882a593Smuzhiyun 2962*4882a593Smuzhiyun# check for space before tabs. 2963*4882a593Smuzhiyun if ($rawline =~ /^\+/ && $rawline =~ / \t/) { 2964*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 2965*4882a593Smuzhiyun if (WARN("SPACE_BEFORE_TAB", 2966*4882a593Smuzhiyun "please, no space before tabs\n" . $herevet) && 2967*4882a593Smuzhiyun $fix) { 2968*4882a593Smuzhiyun while ($fixed[$fixlinenr] =~ 2969*4882a593Smuzhiyun s/(^\+.*) {8,8}\t/$1\t\t/) {} 2970*4882a593Smuzhiyun while ($fixed[$fixlinenr] =~ 2971*4882a593Smuzhiyun s/(^\+.*) +\t/$1\t/) {} 2972*4882a593Smuzhiyun } 2973*4882a593Smuzhiyun } 2974*4882a593Smuzhiyun 2975*4882a593Smuzhiyun# check for && or || at the start of a line 2976*4882a593Smuzhiyun if ($rawline =~ /^\+\s*(&&|\|\|)/) { 2977*4882a593Smuzhiyun CHK("LOGICAL_CONTINUATIONS", 2978*4882a593Smuzhiyun "Logical continuations should be on the previous line\n" . $hereprev); 2979*4882a593Smuzhiyun } 2980*4882a593Smuzhiyun 2981*4882a593Smuzhiyun# check indentation starts on a tab stop 2982*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 2983*4882a593Smuzhiyun $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$))/) { 2984*4882a593Smuzhiyun my $indent = length($1); 2985*4882a593Smuzhiyun if ($indent % 8) { 2986*4882a593Smuzhiyun if (WARN("TABSTOP", 2987*4882a593Smuzhiyun "Statements should start on a tabstop\n" . $herecurr) && 2988*4882a593Smuzhiyun $fix) { 2989*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e; 2990*4882a593Smuzhiyun } 2991*4882a593Smuzhiyun } 2992*4882a593Smuzhiyun } 2993*4882a593Smuzhiyun 2994*4882a593Smuzhiyun# check multi-line statement indentation matches previous line 2995*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 2996*4882a593Smuzhiyun $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) { 2997*4882a593Smuzhiyun $prevline =~ /^\+(\t*)(.*)$/; 2998*4882a593Smuzhiyun my $oldindent = $1; 2999*4882a593Smuzhiyun my $rest = $2; 3000*4882a593Smuzhiyun 3001*4882a593Smuzhiyun my $pos = pos_last_openparen($rest); 3002*4882a593Smuzhiyun if ($pos >= 0) { 3003*4882a593Smuzhiyun $line =~ /^(\+| )([ \t]*)/; 3004*4882a593Smuzhiyun my $newindent = $2; 3005*4882a593Smuzhiyun 3006*4882a593Smuzhiyun my $goodtabindent = $oldindent . 3007*4882a593Smuzhiyun "\t" x ($pos / 8) . 3008*4882a593Smuzhiyun " " x ($pos % 8); 3009*4882a593Smuzhiyun my $goodspaceindent = $oldindent . " " x $pos; 3010*4882a593Smuzhiyun 3011*4882a593Smuzhiyun if ($newindent ne $goodtabindent && 3012*4882a593Smuzhiyun $newindent ne $goodspaceindent) { 3013*4882a593Smuzhiyun 3014*4882a593Smuzhiyun if (CHK("PARENTHESIS_ALIGNMENT", 3015*4882a593Smuzhiyun "Alignment should match open parenthesis\n" . $hereprev) && 3016*4882a593Smuzhiyun $fix && $line =~ /^\+/) { 3017*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3018*4882a593Smuzhiyun s/^\+[ \t]*/\+$goodtabindent/; 3019*4882a593Smuzhiyun } 3020*4882a593Smuzhiyun } 3021*4882a593Smuzhiyun } 3022*4882a593Smuzhiyun } 3023*4882a593Smuzhiyun 3024*4882a593Smuzhiyun# check for space after cast like "(int) foo" or "(struct foo) bar" 3025*4882a593Smuzhiyun# avoid checking a few false positives: 3026*4882a593Smuzhiyun# "sizeof(<type>)" or "__alignof__(<type>)" 3027*4882a593Smuzhiyun# function pointer declarations like "(*foo)(int) = bar;" 3028*4882a593Smuzhiyun# structure definitions like "(struct foo) { 0 };" 3029*4882a593Smuzhiyun# multiline macros that define functions 3030*4882a593Smuzhiyun# known attributes or the __attribute__ keyword 3031*4882a593Smuzhiyun if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ && 3032*4882a593Smuzhiyun (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) { 3033*4882a593Smuzhiyun if (CHK("SPACING", 3034*4882a593Smuzhiyun "No space is necessary after a cast\n" . $herecurr) && 3035*4882a593Smuzhiyun $fix) { 3036*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3037*4882a593Smuzhiyun s/(\(\s*$Type\s*\))[ \t]+/$1/; 3038*4882a593Smuzhiyun } 3039*4882a593Smuzhiyun } 3040*4882a593Smuzhiyun 3041*4882a593Smuzhiyun# Block comment styles 3042*4882a593Smuzhiyun# Networking with an initial /* 3043*4882a593Smuzhiyun if ($realfile =~ m@^(drivers/net/|net/)@ && 3044*4882a593Smuzhiyun $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && 3045*4882a593Smuzhiyun $rawline =~ /^\+[ \t]*\*/ && 3046*4882a593Smuzhiyun $realline > 2) { 3047*4882a593Smuzhiyun WARN("NETWORKING_BLOCK_COMMENT_STYLE", 3048*4882a593Smuzhiyun "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); 3049*4882a593Smuzhiyun } 3050*4882a593Smuzhiyun 3051*4882a593Smuzhiyun# Block comments use * on subsequent lines 3052*4882a593Smuzhiyun if ($prevline =~ /$;[ \t]*$/ && #ends in comment 3053*4882a593Smuzhiyun $prevrawline =~ /^\+.*?\/\*/ && #starting /* 3054*4882a593Smuzhiyun $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */ 3055*4882a593Smuzhiyun $rawline =~ /^\+/ && #line is new 3056*4882a593Smuzhiyun $rawline !~ /^\+[ \t]*\*/) { #no leading * 3057*4882a593Smuzhiyun WARN("BLOCK_COMMENT_STYLE", 3058*4882a593Smuzhiyun "Block comments use * on subsequent lines\n" . $hereprev); 3059*4882a593Smuzhiyun } 3060*4882a593Smuzhiyun 3061*4882a593Smuzhiyun# Block comments use */ on trailing lines 3062*4882a593Smuzhiyun if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ 3063*4882a593Smuzhiyun $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ 3064*4882a593Smuzhiyun $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ 3065*4882a593Smuzhiyun $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ 3066*4882a593Smuzhiyun WARN("BLOCK_COMMENT_STYLE", 3067*4882a593Smuzhiyun "Block comments use a trailing */ on a separate line\n" . $herecurr); 3068*4882a593Smuzhiyun } 3069*4882a593Smuzhiyun 3070*4882a593Smuzhiyun# Block comment * alignment 3071*4882a593Smuzhiyun if ($prevline =~ /$;[ \t]*$/ && #ends in comment 3072*4882a593Smuzhiyun $line =~ /^\+[ \t]*$;/ && #leading comment 3073*4882a593Smuzhiyun $rawline =~ /^\+[ \t]*\*/ && #leading * 3074*4882a593Smuzhiyun (($prevrawline =~ /^\+.*?\/\*/ && #leading /* 3075*4882a593Smuzhiyun $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ 3076*4882a593Smuzhiyun $prevrawline =~ /^\+[ \t]*\*/)) { #leading * 3077*4882a593Smuzhiyun my $oldindent; 3078*4882a593Smuzhiyun $prevrawline =~ m@^\+([ \t]*/?)\*@; 3079*4882a593Smuzhiyun if (defined($1)) { 3080*4882a593Smuzhiyun $oldindent = expand_tabs($1); 3081*4882a593Smuzhiyun } else { 3082*4882a593Smuzhiyun $prevrawline =~ m@^\+(.*/?)\*@; 3083*4882a593Smuzhiyun $oldindent = expand_tabs($1); 3084*4882a593Smuzhiyun } 3085*4882a593Smuzhiyun $rawline =~ m@^\+([ \t]*)\*@; 3086*4882a593Smuzhiyun my $newindent = $1; 3087*4882a593Smuzhiyun $newindent = expand_tabs($newindent); 3088*4882a593Smuzhiyun if (length($oldindent) ne length($newindent)) { 3089*4882a593Smuzhiyun WARN("BLOCK_COMMENT_STYLE", 3090*4882a593Smuzhiyun "Block comments should align the * on each line\n" . $hereprev); 3091*4882a593Smuzhiyun } 3092*4882a593Smuzhiyun } 3093*4882a593Smuzhiyun 3094*4882a593Smuzhiyun# check for missing blank lines after struct/union declarations 3095*4882a593Smuzhiyun# with exceptions for various attributes and macros 3096*4882a593Smuzhiyun if ($prevline =~ /^[\+ ]};?\s*$/ && 3097*4882a593Smuzhiyun $line =~ /^\+/ && 3098*4882a593Smuzhiyun !($line =~ /^\+\s*$/ || 3099*4882a593Smuzhiyun $line =~ /^\+\s*EXPORT_SYMBOL/ || 3100*4882a593Smuzhiyun $line =~ /^\+\s*MODULE_/i || 3101*4882a593Smuzhiyun $line =~ /^\+\s*\#\s*(?:end|elif|else)/ || 3102*4882a593Smuzhiyun $line =~ /^\+[a-z_]*init/ || 3103*4882a593Smuzhiyun $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ || 3104*4882a593Smuzhiyun $line =~ /^\+\s*DECLARE/ || 3105*4882a593Smuzhiyun $line =~ /^\+\s*__setup/)) { 3106*4882a593Smuzhiyun if (CHK("LINE_SPACING", 3107*4882a593Smuzhiyun "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) && 3108*4882a593Smuzhiyun $fix) { 3109*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+"); 3110*4882a593Smuzhiyun } 3111*4882a593Smuzhiyun } 3112*4882a593Smuzhiyun 3113*4882a593Smuzhiyun# check for multiple consecutive blank lines 3114*4882a593Smuzhiyun if ($prevline =~ /^[\+ ]\s*$/ && 3115*4882a593Smuzhiyun $line =~ /^\+\s*$/ && 3116*4882a593Smuzhiyun $last_blank_line != ($linenr - 1)) { 3117*4882a593Smuzhiyun if (CHK("LINE_SPACING", 3118*4882a593Smuzhiyun "Please don't use multiple blank lines\n" . $hereprev) && 3119*4882a593Smuzhiyun $fix) { 3120*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 3121*4882a593Smuzhiyun } 3122*4882a593Smuzhiyun 3123*4882a593Smuzhiyun $last_blank_line = $linenr; 3124*4882a593Smuzhiyun } 3125*4882a593Smuzhiyun 3126*4882a593Smuzhiyun# check for missing blank lines after declarations 3127*4882a593Smuzhiyun if ($sline =~ /^\+\s+\S/ && #Not at char 1 3128*4882a593Smuzhiyun # actual declarations 3129*4882a593Smuzhiyun ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || 3130*4882a593Smuzhiyun # function pointer declarations 3131*4882a593Smuzhiyun $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || 3132*4882a593Smuzhiyun # foo bar; where foo is some local typedef or #define 3133*4882a593Smuzhiyun $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || 3134*4882a593Smuzhiyun # known declaration macros 3135*4882a593Smuzhiyun $prevline =~ /^\+\s+$declaration_macros/) && 3136*4882a593Smuzhiyun # for "else if" which can look like "$Ident $Ident" 3137*4882a593Smuzhiyun !($prevline =~ /^\+\s+$c90_Keywords\b/ || 3138*4882a593Smuzhiyun # other possible extensions of declaration lines 3139*4882a593Smuzhiyun $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ || 3140*4882a593Smuzhiyun # not starting a section or a macro "\" extended line 3141*4882a593Smuzhiyun $prevline =~ /(?:\{\s*|\\)$/) && 3142*4882a593Smuzhiyun # looks like a declaration 3143*4882a593Smuzhiyun !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ || 3144*4882a593Smuzhiyun # function pointer declarations 3145*4882a593Smuzhiyun $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ || 3146*4882a593Smuzhiyun # foo bar; where foo is some local typedef or #define 3147*4882a593Smuzhiyun $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ || 3148*4882a593Smuzhiyun # known declaration macros 3149*4882a593Smuzhiyun $sline =~ /^\+\s+$declaration_macros/ || 3150*4882a593Smuzhiyun # start of struct or union or enum 3151*4882a593Smuzhiyun $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ || 3152*4882a593Smuzhiyun # start or end of block or continuation of declaration 3153*4882a593Smuzhiyun $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ || 3154*4882a593Smuzhiyun # bitfield continuation 3155*4882a593Smuzhiyun $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ || 3156*4882a593Smuzhiyun # other possible extensions of declaration lines 3157*4882a593Smuzhiyun $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) && 3158*4882a593Smuzhiyun # indentation of previous and current line are the same 3159*4882a593Smuzhiyun (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) { 3160*4882a593Smuzhiyun if (WARN("LINE_SPACING", 3161*4882a593Smuzhiyun "Missing a blank line after declarations\n" . $hereprev) && 3162*4882a593Smuzhiyun $fix) { 3163*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+"); 3164*4882a593Smuzhiyun } 3165*4882a593Smuzhiyun } 3166*4882a593Smuzhiyun 3167*4882a593Smuzhiyun# check for spaces at the beginning of a line. 3168*4882a593Smuzhiyun# Exceptions: 3169*4882a593Smuzhiyun# 1) within comments 3170*4882a593Smuzhiyun# 2) indented preprocessor commands 3171*4882a593Smuzhiyun# 3) hanging labels 3172*4882a593Smuzhiyun if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/) { 3173*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($rawline) . "\n"; 3174*4882a593Smuzhiyun if (WARN("LEADING_SPACE", 3175*4882a593Smuzhiyun "please, no spaces at the start of a line\n" . $herevet) && 3176*4882a593Smuzhiyun $fix) { 3177*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e; 3178*4882a593Smuzhiyun } 3179*4882a593Smuzhiyun } 3180*4882a593Smuzhiyun 3181*4882a593Smuzhiyun# check we are in a valid C source file if not then ignore this hunk 3182*4882a593Smuzhiyun next if ($realfile !~ /\.(h|c)$/); 3183*4882a593Smuzhiyun 3184*4882a593Smuzhiyun# check if this appears to be the start function declaration, save the name 3185*4882a593Smuzhiyun if ($sline =~ /^\+\{\s*$/ && 3186*4882a593Smuzhiyun $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) { 3187*4882a593Smuzhiyun $context_function = $1; 3188*4882a593Smuzhiyun } 3189*4882a593Smuzhiyun 3190*4882a593Smuzhiyun# check if this appears to be the end of function declaration 3191*4882a593Smuzhiyun if ($sline =~ /^\+\}\s*$/) { 3192*4882a593Smuzhiyun undef $context_function; 3193*4882a593Smuzhiyun } 3194*4882a593Smuzhiyun 3195*4882a593Smuzhiyun# check indentation of any line with a bare else 3196*4882a593Smuzhiyun# (but not if it is a multiple line "if (foo) return bar; else return baz;") 3197*4882a593Smuzhiyun# if the previous line is a break or return and is indented 1 tab more... 3198*4882a593Smuzhiyun if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) { 3199*4882a593Smuzhiyun my $tabs = length($1) + 1; 3200*4882a593Smuzhiyun if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ || 3201*4882a593Smuzhiyun ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ && 3202*4882a593Smuzhiyun defined $lines[$linenr] && 3203*4882a593Smuzhiyun $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) { 3204*4882a593Smuzhiyun WARN("UNNECESSARY_ELSE", 3205*4882a593Smuzhiyun "else is not generally useful after a break or return\n" . $hereprev); 3206*4882a593Smuzhiyun } 3207*4882a593Smuzhiyun } 3208*4882a593Smuzhiyun 3209*4882a593Smuzhiyun# check indentation of a line with a break; 3210*4882a593Smuzhiyun# if the previous line is a goto or return and is indented the same # of tabs 3211*4882a593Smuzhiyun if ($sline =~ /^\+([\t]+)break\s*;\s*$/) { 3212*4882a593Smuzhiyun my $tabs = $1; 3213*4882a593Smuzhiyun if ($prevline =~ /^\+$tabs(?:goto|return)\b/) { 3214*4882a593Smuzhiyun WARN("UNNECESSARY_BREAK", 3215*4882a593Smuzhiyun "break is not useful after a goto or return\n" . $hereprev); 3216*4882a593Smuzhiyun } 3217*4882a593Smuzhiyun } 3218*4882a593Smuzhiyun 3219*4882a593Smuzhiyun# check for RCS/CVS revision markers 3220*4882a593Smuzhiyun if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) { 3221*4882a593Smuzhiyun WARN("CVS_KEYWORD", 3222*4882a593Smuzhiyun "CVS style keyword markers, these will _not_ be updated\n". $herecurr); 3223*4882a593Smuzhiyun } 3224*4882a593Smuzhiyun 3225*4882a593Smuzhiyun# Blackfin: don't use __builtin_bfin_[cs]sync 3226*4882a593Smuzhiyun if ($line =~ /__builtin_bfin_csync/) { 3227*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($line) . "\n"; 3228*4882a593Smuzhiyun ERROR("CSYNC", 3229*4882a593Smuzhiyun "use the CSYNC() macro in asm/blackfin.h\n" . $herevet); 3230*4882a593Smuzhiyun } 3231*4882a593Smuzhiyun if ($line =~ /__builtin_bfin_ssync/) { 3232*4882a593Smuzhiyun my $herevet = "$here\n" . cat_vet($line) . "\n"; 3233*4882a593Smuzhiyun ERROR("SSYNC", 3234*4882a593Smuzhiyun "use the SSYNC() macro in asm/blackfin.h\n" . $herevet); 3235*4882a593Smuzhiyun } 3236*4882a593Smuzhiyun 3237*4882a593Smuzhiyun# check for old HOTPLUG __dev<foo> section markings 3238*4882a593Smuzhiyun if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) { 3239*4882a593Smuzhiyun WARN("HOTPLUG_SECTION", 3240*4882a593Smuzhiyun "Using $1 is unnecessary\n" . $herecurr); 3241*4882a593Smuzhiyun } 3242*4882a593Smuzhiyun 3243*4882a593Smuzhiyun# Check for potential 'bare' types 3244*4882a593Smuzhiyun my ($stat, $cond, $line_nr_next, $remain_next, $off_next, 3245*4882a593Smuzhiyun $realline_next); 3246*4882a593Smuzhiyun#print "LINE<$line>\n"; 3247*4882a593Smuzhiyun if ($linenr > $suppress_statement && 3248*4882a593Smuzhiyun $realcnt && $sline =~ /.\s*\S/) { 3249*4882a593Smuzhiyun ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 3250*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0); 3251*4882a593Smuzhiyun $stat =~ s/\n./\n /g; 3252*4882a593Smuzhiyun $cond =~ s/\n./\n /g; 3253*4882a593Smuzhiyun 3254*4882a593Smuzhiyun#print "linenr<$linenr> <$stat>\n"; 3255*4882a593Smuzhiyun # If this statement has no statement boundaries within 3256*4882a593Smuzhiyun # it there is no point in retrying a statement scan 3257*4882a593Smuzhiyun # until we hit end of it. 3258*4882a593Smuzhiyun my $frag = $stat; $frag =~ s/;+\s*$//; 3259*4882a593Smuzhiyun if ($frag !~ /(?:{|;)/) { 3260*4882a593Smuzhiyun#print "skip<$line_nr_next>\n"; 3261*4882a593Smuzhiyun $suppress_statement = $line_nr_next; 3262*4882a593Smuzhiyun } 3263*4882a593Smuzhiyun 3264*4882a593Smuzhiyun # Find the real next line. 3265*4882a593Smuzhiyun $realline_next = $line_nr_next; 3266*4882a593Smuzhiyun if (defined $realline_next && 3267*4882a593Smuzhiyun (!defined $lines[$realline_next - 1] || 3268*4882a593Smuzhiyun substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) { 3269*4882a593Smuzhiyun $realline_next++; 3270*4882a593Smuzhiyun } 3271*4882a593Smuzhiyun 3272*4882a593Smuzhiyun my $s = $stat; 3273*4882a593Smuzhiyun $s =~ s/{.*$//s; 3274*4882a593Smuzhiyun 3275*4882a593Smuzhiyun # Ignore goto labels. 3276*4882a593Smuzhiyun if ($s =~ /$Ident:\*$/s) { 3277*4882a593Smuzhiyun 3278*4882a593Smuzhiyun # Ignore functions being called 3279*4882a593Smuzhiyun } elsif ($s =~ /^.\s*$Ident\s*\(/s) { 3280*4882a593Smuzhiyun 3281*4882a593Smuzhiyun } elsif ($s =~ /^.\s*else\b/s) { 3282*4882a593Smuzhiyun 3283*4882a593Smuzhiyun # declarations always start with types 3284*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) { 3285*4882a593Smuzhiyun my $type = $1; 3286*4882a593Smuzhiyun $type =~ s/\s+/ /g; 3287*4882a593Smuzhiyun possible($type, "A:" . $s); 3288*4882a593Smuzhiyun 3289*4882a593Smuzhiyun # definitions in global scope can only start with types 3290*4882a593Smuzhiyun } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) { 3291*4882a593Smuzhiyun possible($1, "B:" . $s); 3292*4882a593Smuzhiyun } 3293*4882a593Smuzhiyun 3294*4882a593Smuzhiyun # any (foo ... *) is a pointer cast, and foo is a type 3295*4882a593Smuzhiyun while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) { 3296*4882a593Smuzhiyun possible($1, "C:" . $s); 3297*4882a593Smuzhiyun } 3298*4882a593Smuzhiyun 3299*4882a593Smuzhiyun # Check for any sort of function declaration. 3300*4882a593Smuzhiyun # int foo(something bar, other baz); 3301*4882a593Smuzhiyun # void (*store_gdt)(x86_descr_ptr *); 3302*4882a593Smuzhiyun if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) { 3303*4882a593Smuzhiyun my ($name_len) = length($1); 3304*4882a593Smuzhiyun 3305*4882a593Smuzhiyun my $ctx = $s; 3306*4882a593Smuzhiyun substr($ctx, 0, $name_len + 1, ''); 3307*4882a593Smuzhiyun $ctx =~ s/\)[^\)]*$//; 3308*4882a593Smuzhiyun 3309*4882a593Smuzhiyun for my $arg (split(/\s*,\s*/, $ctx)) { 3310*4882a593Smuzhiyun if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) { 3311*4882a593Smuzhiyun 3312*4882a593Smuzhiyun possible($1, "D:" . $s); 3313*4882a593Smuzhiyun } 3314*4882a593Smuzhiyun } 3315*4882a593Smuzhiyun } 3316*4882a593Smuzhiyun 3317*4882a593Smuzhiyun } 3318*4882a593Smuzhiyun 3319*4882a593Smuzhiyun# 3320*4882a593Smuzhiyun# Checks which may be anchored in the context. 3321*4882a593Smuzhiyun# 3322*4882a593Smuzhiyun 3323*4882a593Smuzhiyun# Check for switch () and associated case and default 3324*4882a593Smuzhiyun# statements should be at the same indent. 3325*4882a593Smuzhiyun if ($line=~/\bswitch\s*\(.*\)/) { 3326*4882a593Smuzhiyun my $err = ''; 3327*4882a593Smuzhiyun my $sep = ''; 3328*4882a593Smuzhiyun my @ctx = ctx_block_outer($linenr, $realcnt); 3329*4882a593Smuzhiyun shift(@ctx); 3330*4882a593Smuzhiyun for my $ctx (@ctx) { 3331*4882a593Smuzhiyun my ($clen, $cindent) = line_stats($ctx); 3332*4882a593Smuzhiyun if ($ctx =~ /^\+\s*(case\s+|default:)/ && 3333*4882a593Smuzhiyun $indent != $cindent) { 3334*4882a593Smuzhiyun $err .= "$sep$ctx\n"; 3335*4882a593Smuzhiyun $sep = ''; 3336*4882a593Smuzhiyun } else { 3337*4882a593Smuzhiyun $sep = "[...]\n"; 3338*4882a593Smuzhiyun } 3339*4882a593Smuzhiyun } 3340*4882a593Smuzhiyun if ($err ne '') { 3341*4882a593Smuzhiyun ERROR("SWITCH_CASE_INDENT_LEVEL", 3342*4882a593Smuzhiyun "switch and case should be at the same indent\n$hereline$err"); 3343*4882a593Smuzhiyun } 3344*4882a593Smuzhiyun } 3345*4882a593Smuzhiyun 3346*4882a593Smuzhiyun# if/while/etc brace do not go on next line, unless defining a do while loop, 3347*4882a593Smuzhiyun# or if that brace on the next line is for something else 3348*4882a593Smuzhiyun if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) { 3349*4882a593Smuzhiyun my $pre_ctx = "$1$2"; 3350*4882a593Smuzhiyun 3351*4882a593Smuzhiyun my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0); 3352*4882a593Smuzhiyun 3353*4882a593Smuzhiyun if ($line =~ /^\+\t{6,}/) { 3354*4882a593Smuzhiyun WARN("DEEP_INDENTATION", 3355*4882a593Smuzhiyun "Too many leading tabs - consider code refactoring\n" . $herecurr); 3356*4882a593Smuzhiyun } 3357*4882a593Smuzhiyun 3358*4882a593Smuzhiyun my $ctx_cnt = $realcnt - $#ctx - 1; 3359*4882a593Smuzhiyun my $ctx = join("\n", @ctx); 3360*4882a593Smuzhiyun 3361*4882a593Smuzhiyun my $ctx_ln = $linenr; 3362*4882a593Smuzhiyun my $ctx_skip = $realcnt; 3363*4882a593Smuzhiyun 3364*4882a593Smuzhiyun while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt && 3365*4882a593Smuzhiyun defined $lines[$ctx_ln - 1] && 3366*4882a593Smuzhiyun $lines[$ctx_ln - 1] =~ /^-/)) { 3367*4882a593Smuzhiyun ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n"; 3368*4882a593Smuzhiyun $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/); 3369*4882a593Smuzhiyun $ctx_ln++; 3370*4882a593Smuzhiyun } 3371*4882a593Smuzhiyun 3372*4882a593Smuzhiyun #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n"; 3373*4882a593Smuzhiyun #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n"; 3374*4882a593Smuzhiyun 3375*4882a593Smuzhiyun if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) { 3376*4882a593Smuzhiyun ERROR("OPEN_BRACE", 3377*4882a593Smuzhiyun "that open brace { should be on the previous line\n" . 3378*4882a593Smuzhiyun "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); 3379*4882a593Smuzhiyun } 3380*4882a593Smuzhiyun if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ && 3381*4882a593Smuzhiyun $ctx =~ /\)\s*\;\s*$/ && 3382*4882a593Smuzhiyun defined $lines[$ctx_ln - 1]) 3383*4882a593Smuzhiyun { 3384*4882a593Smuzhiyun my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]); 3385*4882a593Smuzhiyun if ($nindent > $indent) { 3386*4882a593Smuzhiyun WARN("TRAILING_SEMICOLON", 3387*4882a593Smuzhiyun "trailing semicolon indicates no statements, indent implies otherwise\n" . 3388*4882a593Smuzhiyun "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n"); 3389*4882a593Smuzhiyun } 3390*4882a593Smuzhiyun } 3391*4882a593Smuzhiyun } 3392*4882a593Smuzhiyun 3393*4882a593Smuzhiyun# Check relative indent for conditionals and blocks. 3394*4882a593Smuzhiyun if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) { 3395*4882a593Smuzhiyun ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 3396*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0) 3397*4882a593Smuzhiyun if (!defined $stat); 3398*4882a593Smuzhiyun my ($s, $c) = ($stat, $cond); 3399*4882a593Smuzhiyun 3400*4882a593Smuzhiyun substr($s, 0, length($c), ''); 3401*4882a593Smuzhiyun 3402*4882a593Smuzhiyun # remove inline comments 3403*4882a593Smuzhiyun $s =~ s/$;/ /g; 3404*4882a593Smuzhiyun $c =~ s/$;/ /g; 3405*4882a593Smuzhiyun 3406*4882a593Smuzhiyun # Find out how long the conditional actually is. 3407*4882a593Smuzhiyun my @newlines = ($c =~ /\n/gs); 3408*4882a593Smuzhiyun my $cond_lines = 1 + $#newlines; 3409*4882a593Smuzhiyun 3410*4882a593Smuzhiyun # Make sure we remove the line prefixes as we have 3411*4882a593Smuzhiyun # none on the first line, and are going to readd them 3412*4882a593Smuzhiyun # where necessary. 3413*4882a593Smuzhiyun $s =~ s/\n./\n/gs; 3414*4882a593Smuzhiyun while ($s =~ /\n\s+\\\n/) { 3415*4882a593Smuzhiyun $cond_lines += $s =~ s/\n\s+\\\n/\n/g; 3416*4882a593Smuzhiyun } 3417*4882a593Smuzhiyun 3418*4882a593Smuzhiyun # We want to check the first line inside the block 3419*4882a593Smuzhiyun # starting at the end of the conditional, so remove: 3420*4882a593Smuzhiyun # 1) any blank line termination 3421*4882a593Smuzhiyun # 2) any opening brace { on end of the line 3422*4882a593Smuzhiyun # 3) any do (...) { 3423*4882a593Smuzhiyun my $continuation = 0; 3424*4882a593Smuzhiyun my $check = 0; 3425*4882a593Smuzhiyun $s =~ s/^.*\bdo\b//; 3426*4882a593Smuzhiyun $s =~ s/^\s*{//; 3427*4882a593Smuzhiyun if ($s =~ s/^\s*\\//) { 3428*4882a593Smuzhiyun $continuation = 1; 3429*4882a593Smuzhiyun } 3430*4882a593Smuzhiyun if ($s =~ s/^\s*?\n//) { 3431*4882a593Smuzhiyun $check = 1; 3432*4882a593Smuzhiyun $cond_lines++; 3433*4882a593Smuzhiyun } 3434*4882a593Smuzhiyun 3435*4882a593Smuzhiyun # Also ignore a loop construct at the end of a 3436*4882a593Smuzhiyun # preprocessor statement. 3437*4882a593Smuzhiyun if (($prevline =~ /^.\s*#\s*define\s/ || 3438*4882a593Smuzhiyun $prevline =~ /\\\s*$/) && $continuation == 0) { 3439*4882a593Smuzhiyun $check = 0; 3440*4882a593Smuzhiyun } 3441*4882a593Smuzhiyun 3442*4882a593Smuzhiyun my $cond_ptr = -1; 3443*4882a593Smuzhiyun $continuation = 0; 3444*4882a593Smuzhiyun while ($cond_ptr != $cond_lines) { 3445*4882a593Smuzhiyun $cond_ptr = $cond_lines; 3446*4882a593Smuzhiyun 3447*4882a593Smuzhiyun # If we see an #else/#elif then the code 3448*4882a593Smuzhiyun # is not linear. 3449*4882a593Smuzhiyun if ($s =~ /^\s*\#\s*(?:else|elif)/) { 3450*4882a593Smuzhiyun $check = 0; 3451*4882a593Smuzhiyun } 3452*4882a593Smuzhiyun 3453*4882a593Smuzhiyun # Ignore: 3454*4882a593Smuzhiyun # 1) blank lines, they should be at 0, 3455*4882a593Smuzhiyun # 2) preprocessor lines, and 3456*4882a593Smuzhiyun # 3) labels. 3457*4882a593Smuzhiyun if ($continuation || 3458*4882a593Smuzhiyun $s =~ /^\s*?\n/ || 3459*4882a593Smuzhiyun $s =~ /^\s*#\s*?/ || 3460*4882a593Smuzhiyun $s =~ /^\s*$Ident\s*:/) { 3461*4882a593Smuzhiyun $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0; 3462*4882a593Smuzhiyun if ($s =~ s/^.*?\n//) { 3463*4882a593Smuzhiyun $cond_lines++; 3464*4882a593Smuzhiyun } 3465*4882a593Smuzhiyun } 3466*4882a593Smuzhiyun } 3467*4882a593Smuzhiyun 3468*4882a593Smuzhiyun my (undef, $sindent) = line_stats("+" . $s); 3469*4882a593Smuzhiyun my $stat_real = raw_line($linenr, $cond_lines); 3470*4882a593Smuzhiyun 3471*4882a593Smuzhiyun # Check if either of these lines are modified, else 3472*4882a593Smuzhiyun # this is not this patch's fault. 3473*4882a593Smuzhiyun if (!defined($stat_real) || 3474*4882a593Smuzhiyun $stat !~ /^\+/ && $stat_real !~ /^\+/) { 3475*4882a593Smuzhiyun $check = 0; 3476*4882a593Smuzhiyun } 3477*4882a593Smuzhiyun if (defined($stat_real) && $cond_lines > 1) { 3478*4882a593Smuzhiyun $stat_real = "[...]\n$stat_real"; 3479*4882a593Smuzhiyun } 3480*4882a593Smuzhiyun 3481*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"; 3482*4882a593Smuzhiyun 3483*4882a593Smuzhiyun if ($check && $s ne '' && 3484*4882a593Smuzhiyun (($sindent % 8) != 0 || 3485*4882a593Smuzhiyun ($sindent < $indent) || 3486*4882a593Smuzhiyun ($sindent == $indent && 3487*4882a593Smuzhiyun ($s !~ /^\s*(?:\}|\{|else\b)/)) || 3488*4882a593Smuzhiyun ($sindent > $indent + 8))) { 3489*4882a593Smuzhiyun WARN("SUSPECT_CODE_INDENT", 3490*4882a593Smuzhiyun "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n"); 3491*4882a593Smuzhiyun } 3492*4882a593Smuzhiyun } 3493*4882a593Smuzhiyun 3494*4882a593Smuzhiyun # Track the 'values' across context and added lines. 3495*4882a593Smuzhiyun my $opline = $line; $opline =~ s/^./ /; 3496*4882a593Smuzhiyun my ($curr_values, $curr_vars) = 3497*4882a593Smuzhiyun annotate_values($opline . "\n", $prev_values); 3498*4882a593Smuzhiyun $curr_values = $prev_values . $curr_values; 3499*4882a593Smuzhiyun if ($dbg_values) { 3500*4882a593Smuzhiyun my $outline = $opline; $outline =~ s/\t/ /g; 3501*4882a593Smuzhiyun print "$linenr > .$outline\n"; 3502*4882a593Smuzhiyun print "$linenr > $curr_values\n"; 3503*4882a593Smuzhiyun print "$linenr > $curr_vars\n"; 3504*4882a593Smuzhiyun } 3505*4882a593Smuzhiyun $prev_values = substr($curr_values, -1); 3506*4882a593Smuzhiyun 3507*4882a593Smuzhiyun#ignore lines not being added 3508*4882a593Smuzhiyun next if ($line =~ /^[^\+]/); 3509*4882a593Smuzhiyun 3510*4882a593Smuzhiyun# check for dereferences that span multiple lines 3511*4882a593Smuzhiyun if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ && 3512*4882a593Smuzhiyun $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) { 3513*4882a593Smuzhiyun $prevline =~ /($Lval\s*(?:\.|->))\s*$/; 3514*4882a593Smuzhiyun my $ref = $1; 3515*4882a593Smuzhiyun $line =~ /^.\s*($Lval)/; 3516*4882a593Smuzhiyun $ref .= $1; 3517*4882a593Smuzhiyun $ref =~ s/\s//g; 3518*4882a593Smuzhiyun WARN("MULTILINE_DEREFERENCE", 3519*4882a593Smuzhiyun "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev); 3520*4882a593Smuzhiyun } 3521*4882a593Smuzhiyun 3522*4882a593Smuzhiyun# check for declarations of signed or unsigned without int 3523*4882a593Smuzhiyun while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { 3524*4882a593Smuzhiyun my $type = $1; 3525*4882a593Smuzhiyun my $var = $2; 3526*4882a593Smuzhiyun $var = "" if (!defined $var); 3527*4882a593Smuzhiyun if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { 3528*4882a593Smuzhiyun my $sign = $1; 3529*4882a593Smuzhiyun my $pointer = $2; 3530*4882a593Smuzhiyun 3531*4882a593Smuzhiyun $pointer = "" if (!defined $pointer); 3532*4882a593Smuzhiyun 3533*4882a593Smuzhiyun if (WARN("UNSPECIFIED_INT", 3534*4882a593Smuzhiyun "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && 3535*4882a593Smuzhiyun $fix) { 3536*4882a593Smuzhiyun my $decl = trim($sign) . " int "; 3537*4882a593Smuzhiyun my $comp_pointer = $pointer; 3538*4882a593Smuzhiyun $comp_pointer =~ s/\s//g; 3539*4882a593Smuzhiyun $decl .= $comp_pointer; 3540*4882a593Smuzhiyun $decl = rtrim($decl) if ($var eq ""); 3541*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; 3542*4882a593Smuzhiyun } 3543*4882a593Smuzhiyun } 3544*4882a593Smuzhiyun } 3545*4882a593Smuzhiyun 3546*4882a593Smuzhiyun# TEST: allow direct testing of the type matcher. 3547*4882a593Smuzhiyun if ($dbg_type) { 3548*4882a593Smuzhiyun if ($line =~ /^.\s*$Declare\s*$/) { 3549*4882a593Smuzhiyun ERROR("TEST_TYPE", 3550*4882a593Smuzhiyun "TEST: is type\n" . $herecurr); 3551*4882a593Smuzhiyun } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) { 3552*4882a593Smuzhiyun ERROR("TEST_NOT_TYPE", 3553*4882a593Smuzhiyun "TEST: is not type ($1 is)\n". $herecurr); 3554*4882a593Smuzhiyun } 3555*4882a593Smuzhiyun next; 3556*4882a593Smuzhiyun } 3557*4882a593Smuzhiyun# TEST: allow direct testing of the attribute matcher. 3558*4882a593Smuzhiyun if ($dbg_attr) { 3559*4882a593Smuzhiyun if ($line =~ /^.\s*$Modifier\s*$/) { 3560*4882a593Smuzhiyun ERROR("TEST_ATTR", 3561*4882a593Smuzhiyun "TEST: is attr\n" . $herecurr); 3562*4882a593Smuzhiyun } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) { 3563*4882a593Smuzhiyun ERROR("TEST_NOT_ATTR", 3564*4882a593Smuzhiyun "TEST: is not attr ($1 is)\n". $herecurr); 3565*4882a593Smuzhiyun } 3566*4882a593Smuzhiyun next; 3567*4882a593Smuzhiyun } 3568*4882a593Smuzhiyun 3569*4882a593Smuzhiyun# check for initialisation to aggregates open brace on the next line 3570*4882a593Smuzhiyun if ($line =~ /^.\s*{/ && 3571*4882a593Smuzhiyun $prevline =~ /(?:^|[^=])=\s*$/) { 3572*4882a593Smuzhiyun if (ERROR("OPEN_BRACE", 3573*4882a593Smuzhiyun "that open brace { should be on the previous line\n" . $hereprev) && 3574*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 3575*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 3576*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 3577*4882a593Smuzhiyun my $fixedline = $prevrawline; 3578*4882a593Smuzhiyun $fixedline =~ s/\s*=\s*$/ = {/; 3579*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 3580*4882a593Smuzhiyun $fixedline = $line; 3581*4882a593Smuzhiyun $fixedline =~ s/^(.\s*)\{\s*/$1/; 3582*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 3583*4882a593Smuzhiyun } 3584*4882a593Smuzhiyun } 3585*4882a593Smuzhiyun 3586*4882a593Smuzhiyun# 3587*4882a593Smuzhiyun# Checks which are anchored on the added line. 3588*4882a593Smuzhiyun# 3589*4882a593Smuzhiyun 3590*4882a593Smuzhiyun# check for malformed paths in #include statements (uses RAW line) 3591*4882a593Smuzhiyun if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) { 3592*4882a593Smuzhiyun my $path = $1; 3593*4882a593Smuzhiyun if ($path =~ m{//}) { 3594*4882a593Smuzhiyun ERROR("MALFORMED_INCLUDE", 3595*4882a593Smuzhiyun "malformed #include filename\n" . $herecurr); 3596*4882a593Smuzhiyun } 3597*4882a593Smuzhiyun if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) { 3598*4882a593Smuzhiyun ERROR("UAPI_INCLUDE", 3599*4882a593Smuzhiyun "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr); 3600*4882a593Smuzhiyun } 3601*4882a593Smuzhiyun } 3602*4882a593Smuzhiyun 3603*4882a593Smuzhiyun# no C99 // comments 3604*4882a593Smuzhiyun if ($line =~ m{//}) { 3605*4882a593Smuzhiyun if (ERROR("C99_COMMENTS", 3606*4882a593Smuzhiyun "do not use C99 // comments\n" . $herecurr) && 3607*4882a593Smuzhiyun $fix) { 3608*4882a593Smuzhiyun my $line = $fixed[$fixlinenr]; 3609*4882a593Smuzhiyun if ($line =~ /\/\/(.*)$/) { 3610*4882a593Smuzhiyun my $comment = trim($1); 3611*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@; 3612*4882a593Smuzhiyun } 3613*4882a593Smuzhiyun } 3614*4882a593Smuzhiyun } 3615*4882a593Smuzhiyun # Remove C99 comments. 3616*4882a593Smuzhiyun $line =~ s@//.*@@; 3617*4882a593Smuzhiyun $opline =~ s@//.*@@; 3618*4882a593Smuzhiyun 3619*4882a593Smuzhiyun# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider 3620*4882a593Smuzhiyun# the whole statement. 3621*4882a593Smuzhiyun#print "APW <$lines[$realline_next - 1]>\n"; 3622*4882a593Smuzhiyun if (defined $realline_next && 3623*4882a593Smuzhiyun exists $lines[$realline_next - 1] && 3624*4882a593Smuzhiyun !defined $suppress_export{$realline_next} && 3625*4882a593Smuzhiyun ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ || 3626*4882a593Smuzhiyun $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { 3627*4882a593Smuzhiyun # Handle definitions which produce identifiers with 3628*4882a593Smuzhiyun # a prefix: 3629*4882a593Smuzhiyun # XXX(foo); 3630*4882a593Smuzhiyun # EXPORT_SYMBOL(something_foo); 3631*4882a593Smuzhiyun my $name = $1; 3632*4882a593Smuzhiyun if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ && 3633*4882a593Smuzhiyun $name =~ /^${Ident}_$2/) { 3634*4882a593Smuzhiyun#print "FOO C name<$name>\n"; 3635*4882a593Smuzhiyun $suppress_export{$realline_next} = 1; 3636*4882a593Smuzhiyun 3637*4882a593Smuzhiyun } elsif ($stat !~ /(?: 3638*4882a593Smuzhiyun \n.}\s*$| 3639*4882a593Smuzhiyun ^.DEFINE_$Ident\(\Q$name\E\)| 3640*4882a593Smuzhiyun ^.DECLARE_$Ident\(\Q$name\E\)| 3641*4882a593Smuzhiyun ^.LIST_HEAD\(\Q$name\E\)| 3642*4882a593Smuzhiyun ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(| 3643*4882a593Smuzhiyun \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\() 3644*4882a593Smuzhiyun )/x) { 3645*4882a593Smuzhiyun#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n"; 3646*4882a593Smuzhiyun $suppress_export{$realline_next} = 2; 3647*4882a593Smuzhiyun } else { 3648*4882a593Smuzhiyun $suppress_export{$realline_next} = 1; 3649*4882a593Smuzhiyun } 3650*4882a593Smuzhiyun } 3651*4882a593Smuzhiyun if (!defined $suppress_export{$linenr} && 3652*4882a593Smuzhiyun $prevline =~ /^.\s*$/ && 3653*4882a593Smuzhiyun ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ || 3654*4882a593Smuzhiyun $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) { 3655*4882a593Smuzhiyun#print "FOO B <$lines[$linenr - 1]>\n"; 3656*4882a593Smuzhiyun $suppress_export{$linenr} = 2; 3657*4882a593Smuzhiyun } 3658*4882a593Smuzhiyun if (defined $suppress_export{$linenr} && 3659*4882a593Smuzhiyun $suppress_export{$linenr} == 2) { 3660*4882a593Smuzhiyun WARN("EXPORT_SYMBOL", 3661*4882a593Smuzhiyun "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr); 3662*4882a593Smuzhiyun } 3663*4882a593Smuzhiyun 3664*4882a593Smuzhiyun# check for global initialisers. 3665*4882a593Smuzhiyun if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) { 3666*4882a593Smuzhiyun if (ERROR("GLOBAL_INITIALISERS", 3667*4882a593Smuzhiyun "do not initialise globals to $1\n" . $herecurr) && 3668*4882a593Smuzhiyun $fix) { 3669*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/; 3670*4882a593Smuzhiyun } 3671*4882a593Smuzhiyun } 3672*4882a593Smuzhiyun# check for static initialisers. 3673*4882a593Smuzhiyun if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) { 3674*4882a593Smuzhiyun if (ERROR("INITIALISED_STATIC", 3675*4882a593Smuzhiyun "do not initialise statics to $1\n" . 3676*4882a593Smuzhiyun $herecurr) && 3677*4882a593Smuzhiyun $fix) { 3678*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/; 3679*4882a593Smuzhiyun } 3680*4882a593Smuzhiyun } 3681*4882a593Smuzhiyun 3682*4882a593Smuzhiyun# check for misordered declarations of char/short/int/long with signed/unsigned 3683*4882a593Smuzhiyun while ($sline =~ m{(\b$TypeMisordered\b)}g) { 3684*4882a593Smuzhiyun my $tmp = trim($1); 3685*4882a593Smuzhiyun WARN("MISORDERED_TYPE", 3686*4882a593Smuzhiyun "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr); 3687*4882a593Smuzhiyun } 3688*4882a593Smuzhiyun 3689*4882a593Smuzhiyun# check for static const char * arrays. 3690*4882a593Smuzhiyun if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) { 3691*4882a593Smuzhiyun WARN("STATIC_CONST_CHAR_ARRAY", 3692*4882a593Smuzhiyun "static const char * array should probably be static const char * const\n" . 3693*4882a593Smuzhiyun $herecurr); 3694*4882a593Smuzhiyun } 3695*4882a593Smuzhiyun 3696*4882a593Smuzhiyun# check for static char foo[] = "bar" declarations. 3697*4882a593Smuzhiyun if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) { 3698*4882a593Smuzhiyun WARN("STATIC_CONST_CHAR_ARRAY", 3699*4882a593Smuzhiyun "static char array declaration should probably be static const char\n" . 3700*4882a593Smuzhiyun $herecurr); 3701*4882a593Smuzhiyun } 3702*4882a593Smuzhiyun 3703*4882a593Smuzhiyun# check for const <foo> const where <foo> is not a pointer or array type 3704*4882a593Smuzhiyun if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) { 3705*4882a593Smuzhiyun my $found = $1; 3706*4882a593Smuzhiyun if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) { 3707*4882a593Smuzhiyun WARN("CONST_CONST", 3708*4882a593Smuzhiyun "'const $found const *' should probably be 'const $found * const'\n" . $herecurr); 3709*4882a593Smuzhiyun } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) { 3710*4882a593Smuzhiyun WARN("CONST_CONST", 3711*4882a593Smuzhiyun "'const $found const' should probably be 'const $found'\n" . $herecurr); 3712*4882a593Smuzhiyun } 3713*4882a593Smuzhiyun } 3714*4882a593Smuzhiyun 3715*4882a593Smuzhiyun# check for non-global char *foo[] = {"bar", ...} declarations. 3716*4882a593Smuzhiyun if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) { 3717*4882a593Smuzhiyun WARN("STATIC_CONST_CHAR_ARRAY", 3718*4882a593Smuzhiyun "char * array declaration might be better as static const\n" . 3719*4882a593Smuzhiyun $herecurr); 3720*4882a593Smuzhiyun } 3721*4882a593Smuzhiyun 3722*4882a593Smuzhiyun# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo) 3723*4882a593Smuzhiyun if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) { 3724*4882a593Smuzhiyun my $array = $1; 3725*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*\))@) { 3726*4882a593Smuzhiyun my $array_div = $1; 3727*4882a593Smuzhiyun if (WARN("ARRAY_SIZE", 3728*4882a593Smuzhiyun "Prefer ARRAY_SIZE($array)\n" . $herecurr) && 3729*4882a593Smuzhiyun $fix) { 3730*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/; 3731*4882a593Smuzhiyun } 3732*4882a593Smuzhiyun } 3733*4882a593Smuzhiyun } 3734*4882a593Smuzhiyun 3735*4882a593Smuzhiyun# check for function declarations without arguments like "int foo()" 3736*4882a593Smuzhiyun if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) { 3737*4882a593Smuzhiyun if (ERROR("FUNCTION_WITHOUT_ARGS", 3738*4882a593Smuzhiyun "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) && 3739*4882a593Smuzhiyun $fix) { 3740*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/; 3741*4882a593Smuzhiyun } 3742*4882a593Smuzhiyun } 3743*4882a593Smuzhiyun 3744*4882a593Smuzhiyun# check for new typedefs, only function parameters and sparse annotations 3745*4882a593Smuzhiyun# make sense. 3746*4882a593Smuzhiyun if ($line =~ /\btypedef\s/ && 3747*4882a593Smuzhiyun $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && 3748*4882a593Smuzhiyun $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && 3749*4882a593Smuzhiyun $line !~ /\b$typeTypedefs\b/ && 3750*4882a593Smuzhiyun $line !~ /\b__bitwise\b/) { 3751*4882a593Smuzhiyun WARN("NEW_TYPEDEFS", 3752*4882a593Smuzhiyun "do not add new typedefs\n" . $herecurr); 3753*4882a593Smuzhiyun } 3754*4882a593Smuzhiyun 3755*4882a593Smuzhiyun# * goes on variable not on type 3756*4882a593Smuzhiyun # (char*[ const]) 3757*4882a593Smuzhiyun while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) { 3758*4882a593Smuzhiyun #print "AA<$1>\n"; 3759*4882a593Smuzhiyun my ($ident, $from, $to) = ($1, $2, $2); 3760*4882a593Smuzhiyun 3761*4882a593Smuzhiyun # Should start with a space. 3762*4882a593Smuzhiyun $to =~ s/^(\S)/ $1/; 3763*4882a593Smuzhiyun # Should not end with a space. 3764*4882a593Smuzhiyun $to =~ s/\s+$//; 3765*4882a593Smuzhiyun # '*'s should not have spaces between. 3766*4882a593Smuzhiyun while ($to =~ s/\*\s+\*/\*\*/) { 3767*4882a593Smuzhiyun } 3768*4882a593Smuzhiyun 3769*4882a593Smuzhiyun## print "1: from<$from> to<$to> ident<$ident>\n"; 3770*4882a593Smuzhiyun if ($from ne $to) { 3771*4882a593Smuzhiyun if (ERROR("POINTER_LOCATION", 3772*4882a593Smuzhiyun "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) && 3773*4882a593Smuzhiyun $fix) { 3774*4882a593Smuzhiyun my $sub_from = $ident; 3775*4882a593Smuzhiyun my $sub_to = $ident; 3776*4882a593Smuzhiyun $sub_to =~ s/\Q$from\E/$to/; 3777*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3778*4882a593Smuzhiyun s@\Q$sub_from\E@$sub_to@; 3779*4882a593Smuzhiyun } 3780*4882a593Smuzhiyun } 3781*4882a593Smuzhiyun } 3782*4882a593Smuzhiyun while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) { 3783*4882a593Smuzhiyun #print "BB<$1>\n"; 3784*4882a593Smuzhiyun my ($match, $from, $to, $ident) = ($1, $2, $2, $3); 3785*4882a593Smuzhiyun 3786*4882a593Smuzhiyun # Should start with a space. 3787*4882a593Smuzhiyun $to =~ s/^(\S)/ $1/; 3788*4882a593Smuzhiyun # Should not end with a space. 3789*4882a593Smuzhiyun $to =~ s/\s+$//; 3790*4882a593Smuzhiyun # '*'s should not have spaces between. 3791*4882a593Smuzhiyun while ($to =~ s/\*\s+\*/\*\*/) { 3792*4882a593Smuzhiyun } 3793*4882a593Smuzhiyun # Modifiers should have spaces. 3794*4882a593Smuzhiyun $to =~ s/(\b$Modifier$)/$1 /; 3795*4882a593Smuzhiyun 3796*4882a593Smuzhiyun## print "2: from<$from> to<$to> ident<$ident>\n"; 3797*4882a593Smuzhiyun if ($from ne $to && $ident !~ /^$Modifier$/) { 3798*4882a593Smuzhiyun if (ERROR("POINTER_LOCATION", 3799*4882a593Smuzhiyun "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) && 3800*4882a593Smuzhiyun $fix) { 3801*4882a593Smuzhiyun 3802*4882a593Smuzhiyun my $sub_from = $match; 3803*4882a593Smuzhiyun my $sub_to = $match; 3804*4882a593Smuzhiyun $sub_to =~ s/\Q$from\E/$to/; 3805*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3806*4882a593Smuzhiyun s@\Q$sub_from\E@$sub_to@; 3807*4882a593Smuzhiyun } 3808*4882a593Smuzhiyun } 3809*4882a593Smuzhiyun } 3810*4882a593Smuzhiyun 3811*4882a593Smuzhiyun# avoid BUG() or BUG_ON() 3812*4882a593Smuzhiyun if ($line =~ /\b(?:BUG|BUG_ON)\b/) { 3813*4882a593Smuzhiyun my $msg_type = \&WARN; 3814*4882a593Smuzhiyun $msg_type = \&CHK if ($file); 3815*4882a593Smuzhiyun &{$msg_type}("AVOID_BUG", 3816*4882a593Smuzhiyun "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr); 3817*4882a593Smuzhiyun } 3818*4882a593Smuzhiyun 3819*4882a593Smuzhiyun# avoid LINUX_VERSION_CODE 3820*4882a593Smuzhiyun if ($line =~ /\bLINUX_VERSION_CODE\b/) { 3821*4882a593Smuzhiyun WARN("LINUX_VERSION_CODE", 3822*4882a593Smuzhiyun "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr); 3823*4882a593Smuzhiyun } 3824*4882a593Smuzhiyun 3825*4882a593Smuzhiyun# check for uses of printk_ratelimit 3826*4882a593Smuzhiyun if ($line =~ /\bprintk_ratelimit\s*\(/) { 3827*4882a593Smuzhiyun WARN("PRINTK_RATELIMITED", 3828*4882a593Smuzhiyun "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr); 3829*4882a593Smuzhiyun } 3830*4882a593Smuzhiyun 3831*4882a593Smuzhiyun# printk should use KERN_* levels. Note that follow on printk's on the 3832*4882a593Smuzhiyun# same line do not need a level, so we use the current block context 3833*4882a593Smuzhiyun# to try and find and validate the current printk. In summary the current 3834*4882a593Smuzhiyun# printk includes all preceding printk's which have no newline on the end. 3835*4882a593Smuzhiyun# we assume the first bad printk is the one to report. 3836*4882a593Smuzhiyun if ($line =~ /\bprintk\((?!KERN_)\s*"/) { 3837*4882a593Smuzhiyun my $ok = 0; 3838*4882a593Smuzhiyun for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) { 3839*4882a593Smuzhiyun #print "CHECK<$lines[$ln - 1]\n"; 3840*4882a593Smuzhiyun # we have a preceding printk if it ends 3841*4882a593Smuzhiyun # with "\n" ignore it, else it is to blame 3842*4882a593Smuzhiyun if ($lines[$ln - 1] =~ m{\bprintk\(}) { 3843*4882a593Smuzhiyun if ($rawlines[$ln - 1] !~ m{\\n"}) { 3844*4882a593Smuzhiyun $ok = 1; 3845*4882a593Smuzhiyun } 3846*4882a593Smuzhiyun last; 3847*4882a593Smuzhiyun } 3848*4882a593Smuzhiyun } 3849*4882a593Smuzhiyun if ($ok == 0) { 3850*4882a593Smuzhiyun WARN("PRINTK_WITHOUT_KERN_LEVEL", 3851*4882a593Smuzhiyun "printk() should include KERN_ facility level\n" . $herecurr); 3852*4882a593Smuzhiyun } 3853*4882a593Smuzhiyun } 3854*4882a593Smuzhiyun 3855*4882a593Smuzhiyun if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) { 3856*4882a593Smuzhiyun my $orig = $1; 3857*4882a593Smuzhiyun my $level = lc($orig); 3858*4882a593Smuzhiyun $level = "warn" if ($level eq "warning"); 3859*4882a593Smuzhiyun my $level2 = $level; 3860*4882a593Smuzhiyun $level2 = "dbg" if ($level eq "debug"); 3861*4882a593Smuzhiyun WARN("PREFER_PR_LEVEL", 3862*4882a593Smuzhiyun "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr); 3863*4882a593Smuzhiyun } 3864*4882a593Smuzhiyun 3865*4882a593Smuzhiyun if ($line =~ /\bpr_warning\s*\(/) { 3866*4882a593Smuzhiyun if (WARN("PREFER_PR_LEVEL", 3867*4882a593Smuzhiyun "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) && 3868*4882a593Smuzhiyun $fix) { 3869*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3870*4882a593Smuzhiyun s/\bpr_warning\b/pr_warn/; 3871*4882a593Smuzhiyun } 3872*4882a593Smuzhiyun } 3873*4882a593Smuzhiyun 3874*4882a593Smuzhiyun if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) { 3875*4882a593Smuzhiyun my $orig = $1; 3876*4882a593Smuzhiyun my $level = lc($orig); 3877*4882a593Smuzhiyun $level = "warn" if ($level eq "warning"); 3878*4882a593Smuzhiyun $level = "dbg" if ($level eq "debug"); 3879*4882a593Smuzhiyun WARN("PREFER_DEV_LEVEL", 3880*4882a593Smuzhiyun "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); 3881*4882a593Smuzhiyun } 3882*4882a593Smuzhiyun 3883*4882a593Smuzhiyun# ENOSYS means "bad syscall nr" and nothing else. This will have a small 3884*4882a593Smuzhiyun# number of false positives, but assembly files are not checked, so at 3885*4882a593Smuzhiyun# least the arch entry code will not trigger this warning. 3886*4882a593Smuzhiyun if ($line =~ /\bENOSYS\b/) { 3887*4882a593Smuzhiyun WARN("ENOSYS", 3888*4882a593Smuzhiyun "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr); 3889*4882a593Smuzhiyun } 3890*4882a593Smuzhiyun 3891*4882a593Smuzhiyun# function brace can't be on same line, except for #defines of do while, 3892*4882a593Smuzhiyun# or if closed on same line 3893*4882a593Smuzhiyun if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and 3894*4882a593Smuzhiyun !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) { 3895*4882a593Smuzhiyun if (ERROR("OPEN_BRACE", 3896*4882a593Smuzhiyun "open brace '{' following function declarations go on the next line\n" . $herecurr) && 3897*4882a593Smuzhiyun $fix) { 3898*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 3899*4882a593Smuzhiyun my $fixed_line = $rawline; 3900*4882a593Smuzhiyun $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; 3901*4882a593Smuzhiyun my $line1 = $1; 3902*4882a593Smuzhiyun my $line2 = $2; 3903*4882a593Smuzhiyun fix_insert_line($fixlinenr, ltrim($line1)); 3904*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+{"); 3905*4882a593Smuzhiyun if ($line2 !~ /^\s*$/) { 3906*4882a593Smuzhiyun fix_insert_line($fixlinenr, "\+\t" . trim($line2)); 3907*4882a593Smuzhiyun } 3908*4882a593Smuzhiyun } 3909*4882a593Smuzhiyun } 3910*4882a593Smuzhiyun 3911*4882a593Smuzhiyun# open braces for enum, union and struct go on the same line. 3912*4882a593Smuzhiyun if ($line =~ /^.\s*{/ && 3913*4882a593Smuzhiyun $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) { 3914*4882a593Smuzhiyun if (ERROR("OPEN_BRACE", 3915*4882a593Smuzhiyun "open brace '{' following $1 go on the same line\n" . $hereprev) && 3916*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 3917*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 3918*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 3919*4882a593Smuzhiyun my $fixedline = rtrim($prevrawline) . " {"; 3920*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 3921*4882a593Smuzhiyun $fixedline = $rawline; 3922*4882a593Smuzhiyun $fixedline =~ s/^(.\s*)\{\s*/$1\t/; 3923*4882a593Smuzhiyun if ($fixedline !~ /^\+\s*$/) { 3924*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 3925*4882a593Smuzhiyun } 3926*4882a593Smuzhiyun } 3927*4882a593Smuzhiyun } 3928*4882a593Smuzhiyun 3929*4882a593Smuzhiyun# missing space after union, struct or enum definition 3930*4882a593Smuzhiyun if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) { 3931*4882a593Smuzhiyun if (WARN("SPACING", 3932*4882a593Smuzhiyun "missing space after $1 definition\n" . $herecurr) && 3933*4882a593Smuzhiyun $fix) { 3934*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 3935*4882a593Smuzhiyun s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/; 3936*4882a593Smuzhiyun } 3937*4882a593Smuzhiyun } 3938*4882a593Smuzhiyun 3939*4882a593Smuzhiyun# Function pointer declarations 3940*4882a593Smuzhiyun# check spacing between type, funcptr, and args 3941*4882a593Smuzhiyun# canonical declaration is "type (*funcptr)(args...)" 3942*4882a593Smuzhiyun if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) { 3943*4882a593Smuzhiyun my $declare = $1; 3944*4882a593Smuzhiyun my $pre_pointer_space = $2; 3945*4882a593Smuzhiyun my $post_pointer_space = $3; 3946*4882a593Smuzhiyun my $funcname = $4; 3947*4882a593Smuzhiyun my $post_funcname_space = $5; 3948*4882a593Smuzhiyun my $pre_args_space = $6; 3949*4882a593Smuzhiyun 3950*4882a593Smuzhiyun# the $Declare variable will capture all spaces after the type 3951*4882a593Smuzhiyun# so check it for a missing trailing missing space but pointer return types 3952*4882a593Smuzhiyun# don't need a space so don't warn for those. 3953*4882a593Smuzhiyun my $post_declare_space = ""; 3954*4882a593Smuzhiyun if ($declare =~ /(\s+)$/) { 3955*4882a593Smuzhiyun $post_declare_space = $1; 3956*4882a593Smuzhiyun $declare = rtrim($declare); 3957*4882a593Smuzhiyun } 3958*4882a593Smuzhiyun if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) { 3959*4882a593Smuzhiyun WARN("SPACING", 3960*4882a593Smuzhiyun "missing space after return type\n" . $herecurr); 3961*4882a593Smuzhiyun $post_declare_space = " "; 3962*4882a593Smuzhiyun } 3963*4882a593Smuzhiyun 3964*4882a593Smuzhiyun# unnecessary space "type (*funcptr)(args...)" 3965*4882a593Smuzhiyun# This test is not currently implemented because these declarations are 3966*4882a593Smuzhiyun# equivalent to 3967*4882a593Smuzhiyun# int foo(int bar, ...) 3968*4882a593Smuzhiyun# and this is form shouldn't/doesn't generate a checkpatch warning. 3969*4882a593Smuzhiyun# 3970*4882a593Smuzhiyun# elsif ($declare =~ /\s{2,}$/) { 3971*4882a593Smuzhiyun# WARN("SPACING", 3972*4882a593Smuzhiyun# "Multiple spaces after return type\n" . $herecurr); 3973*4882a593Smuzhiyun# } 3974*4882a593Smuzhiyun 3975*4882a593Smuzhiyun# unnecessary space "type ( *funcptr)(args...)" 3976*4882a593Smuzhiyun if (defined $pre_pointer_space && 3977*4882a593Smuzhiyun $pre_pointer_space =~ /^\s/) { 3978*4882a593Smuzhiyun WARN("SPACING", 3979*4882a593Smuzhiyun "Unnecessary space after function pointer open parenthesis\n" . $herecurr); 3980*4882a593Smuzhiyun } 3981*4882a593Smuzhiyun 3982*4882a593Smuzhiyun# unnecessary space "type (* funcptr)(args...)" 3983*4882a593Smuzhiyun if (defined $post_pointer_space && 3984*4882a593Smuzhiyun $post_pointer_space =~ /^\s/) { 3985*4882a593Smuzhiyun WARN("SPACING", 3986*4882a593Smuzhiyun "Unnecessary space before function pointer name\n" . $herecurr); 3987*4882a593Smuzhiyun } 3988*4882a593Smuzhiyun 3989*4882a593Smuzhiyun# unnecessary space "type (*funcptr )(args...)" 3990*4882a593Smuzhiyun if (defined $post_funcname_space && 3991*4882a593Smuzhiyun $post_funcname_space =~ /^\s/) { 3992*4882a593Smuzhiyun WARN("SPACING", 3993*4882a593Smuzhiyun "Unnecessary space after function pointer name\n" . $herecurr); 3994*4882a593Smuzhiyun } 3995*4882a593Smuzhiyun 3996*4882a593Smuzhiyun# unnecessary space "type (*funcptr) (args...)" 3997*4882a593Smuzhiyun if (defined $pre_args_space && 3998*4882a593Smuzhiyun $pre_args_space =~ /^\s/) { 3999*4882a593Smuzhiyun WARN("SPACING", 4000*4882a593Smuzhiyun "Unnecessary space before function pointer arguments\n" . $herecurr); 4001*4882a593Smuzhiyun } 4002*4882a593Smuzhiyun 4003*4882a593Smuzhiyun if (show_type("SPACING") && $fix) { 4004*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4005*4882a593Smuzhiyun s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex; 4006*4882a593Smuzhiyun } 4007*4882a593Smuzhiyun } 4008*4882a593Smuzhiyun 4009*4882a593Smuzhiyun# check for spacing round square brackets; allowed: 4010*4882a593Smuzhiyun# 1. with a type on the left -- int [] a; 4011*4882a593Smuzhiyun# 2. at the beginning of a line for slice initialisers -- [0...10] = 5, 4012*4882a593Smuzhiyun# 3. inside a curly brace -- = { [0...10] = 5 } 4013*4882a593Smuzhiyun while ($line =~ /(.*?\s)\[/g) { 4014*4882a593Smuzhiyun my ($where, $prefix) = ($-[1], $1); 4015*4882a593Smuzhiyun if ($prefix !~ /$Type\s+$/ && 4016*4882a593Smuzhiyun ($where != 0 || $prefix !~ /^.\s+$/) && 4017*4882a593Smuzhiyun $prefix !~ /[{,]\s+$/) { 4018*4882a593Smuzhiyun if (ERROR("BRACKET_SPACE", 4019*4882a593Smuzhiyun "space prohibited before open square bracket '['\n" . $herecurr) && 4020*4882a593Smuzhiyun $fix) { 4021*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4022*4882a593Smuzhiyun s/^(\+.*?)\s+\[/$1\[/; 4023*4882a593Smuzhiyun } 4024*4882a593Smuzhiyun } 4025*4882a593Smuzhiyun } 4026*4882a593Smuzhiyun 4027*4882a593Smuzhiyun# check for spaces between functions and their parentheses. 4028*4882a593Smuzhiyun while ($line =~ /($Ident)\s+\(/g) { 4029*4882a593Smuzhiyun my $name = $1; 4030*4882a593Smuzhiyun my $ctx_before = substr($line, 0, $-[1]); 4031*4882a593Smuzhiyun my $ctx = "$ctx_before$name"; 4032*4882a593Smuzhiyun 4033*4882a593Smuzhiyun # Ignore those directives where spaces _are_ permitted. 4034*4882a593Smuzhiyun if ($name =~ /^(?: 4035*4882a593Smuzhiyun if|for|while|switch|return|case| 4036*4882a593Smuzhiyun volatile|__volatile__| 4037*4882a593Smuzhiyun __attribute__|format|__extension__| 4038*4882a593Smuzhiyun asm|__asm__)$/x) 4039*4882a593Smuzhiyun { 4040*4882a593Smuzhiyun # cpp #define statements have non-optional spaces, ie 4041*4882a593Smuzhiyun # if there is a space between the name and the open 4042*4882a593Smuzhiyun # parenthesis it is simply not a parameter group. 4043*4882a593Smuzhiyun } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) { 4044*4882a593Smuzhiyun 4045*4882a593Smuzhiyun # cpp #elif statement condition may start with a ( 4046*4882a593Smuzhiyun } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) { 4047*4882a593Smuzhiyun 4048*4882a593Smuzhiyun # If this whole things ends with a type its most 4049*4882a593Smuzhiyun # likely a typedef for a function. 4050*4882a593Smuzhiyun } elsif ($ctx =~ /$Type$/) { 4051*4882a593Smuzhiyun 4052*4882a593Smuzhiyun } else { 4053*4882a593Smuzhiyun if (WARN("SPACING", 4054*4882a593Smuzhiyun "space prohibited between function name and open parenthesis '('\n" . $herecurr) && 4055*4882a593Smuzhiyun $fix) { 4056*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4057*4882a593Smuzhiyun s/\b$name\s+\(/$name\(/; 4058*4882a593Smuzhiyun } 4059*4882a593Smuzhiyun } 4060*4882a593Smuzhiyun } 4061*4882a593Smuzhiyun 4062*4882a593Smuzhiyun# Check operator spacing. 4063*4882a593Smuzhiyun if (!($line=~/\#\s*include/)) { 4064*4882a593Smuzhiyun my $fixed_line = ""; 4065*4882a593Smuzhiyun my $line_fixed = 0; 4066*4882a593Smuzhiyun 4067*4882a593Smuzhiyun my $ops = qr{ 4068*4882a593Smuzhiyun <<=|>>=|<=|>=|==|!=| 4069*4882a593Smuzhiyun \+=|-=|\*=|\/=|%=|\^=|\|=|&=| 4070*4882a593Smuzhiyun =>|->|<<|>>|<|>|=|!|~| 4071*4882a593Smuzhiyun &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%| 4072*4882a593Smuzhiyun \?:|\?|: 4073*4882a593Smuzhiyun }x; 4074*4882a593Smuzhiyun my @elements = split(/($ops|;)/, $opline); 4075*4882a593Smuzhiyun 4076*4882a593Smuzhiyun## print("element count: <" . $#elements . ">\n"); 4077*4882a593Smuzhiyun## foreach my $el (@elements) { 4078*4882a593Smuzhiyun## print("el: <$el>\n"); 4079*4882a593Smuzhiyun## } 4080*4882a593Smuzhiyun 4081*4882a593Smuzhiyun my @fix_elements = (); 4082*4882a593Smuzhiyun my $off = 0; 4083*4882a593Smuzhiyun 4084*4882a593Smuzhiyun foreach my $el (@elements) { 4085*4882a593Smuzhiyun push(@fix_elements, substr($rawline, $off, length($el))); 4086*4882a593Smuzhiyun $off += length($el); 4087*4882a593Smuzhiyun } 4088*4882a593Smuzhiyun 4089*4882a593Smuzhiyun $off = 0; 4090*4882a593Smuzhiyun 4091*4882a593Smuzhiyun my $blank = copy_spacing($opline); 4092*4882a593Smuzhiyun my $last_after = -1; 4093*4882a593Smuzhiyun 4094*4882a593Smuzhiyun for (my $n = 0; $n < $#elements; $n += 2) { 4095*4882a593Smuzhiyun 4096*4882a593Smuzhiyun my $good = $fix_elements[$n] . $fix_elements[$n + 1]; 4097*4882a593Smuzhiyun 4098*4882a593Smuzhiyun## print("n: <$n> good: <$good>\n"); 4099*4882a593Smuzhiyun 4100*4882a593Smuzhiyun $off += length($elements[$n]); 4101*4882a593Smuzhiyun 4102*4882a593Smuzhiyun # Pick up the preceding and succeeding characters. 4103*4882a593Smuzhiyun my $ca = substr($opline, 0, $off); 4104*4882a593Smuzhiyun my $cc = ''; 4105*4882a593Smuzhiyun if (length($opline) >= ($off + length($elements[$n + 1]))) { 4106*4882a593Smuzhiyun $cc = substr($opline, $off + length($elements[$n + 1])); 4107*4882a593Smuzhiyun } 4108*4882a593Smuzhiyun my $cb = "$ca$;$cc"; 4109*4882a593Smuzhiyun 4110*4882a593Smuzhiyun my $a = ''; 4111*4882a593Smuzhiyun $a = 'V' if ($elements[$n] ne ''); 4112*4882a593Smuzhiyun $a = 'W' if ($elements[$n] =~ /\s$/); 4113*4882a593Smuzhiyun $a = 'C' if ($elements[$n] =~ /$;$/); 4114*4882a593Smuzhiyun $a = 'B' if ($elements[$n] =~ /(\[|\()$/); 4115*4882a593Smuzhiyun $a = 'O' if ($elements[$n] eq ''); 4116*4882a593Smuzhiyun $a = 'E' if ($ca =~ /^\s*$/); 4117*4882a593Smuzhiyun 4118*4882a593Smuzhiyun my $op = $elements[$n + 1]; 4119*4882a593Smuzhiyun 4120*4882a593Smuzhiyun my $c = ''; 4121*4882a593Smuzhiyun if (defined $elements[$n + 2]) { 4122*4882a593Smuzhiyun $c = 'V' if ($elements[$n + 2] ne ''); 4123*4882a593Smuzhiyun $c = 'W' if ($elements[$n + 2] =~ /^\s/); 4124*4882a593Smuzhiyun $c = 'C' if ($elements[$n + 2] =~ /^$;/); 4125*4882a593Smuzhiyun $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/); 4126*4882a593Smuzhiyun $c = 'O' if ($elements[$n + 2] eq ''); 4127*4882a593Smuzhiyun $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/); 4128*4882a593Smuzhiyun } else { 4129*4882a593Smuzhiyun $c = 'E'; 4130*4882a593Smuzhiyun } 4131*4882a593Smuzhiyun 4132*4882a593Smuzhiyun my $ctx = "${a}x${c}"; 4133*4882a593Smuzhiyun 4134*4882a593Smuzhiyun my $at = "(ctx:$ctx)"; 4135*4882a593Smuzhiyun 4136*4882a593Smuzhiyun my $ptr = substr($blank, 0, $off) . "^"; 4137*4882a593Smuzhiyun my $hereptr = "$hereline$ptr\n"; 4138*4882a593Smuzhiyun 4139*4882a593Smuzhiyun # Pull out the value of this operator. 4140*4882a593Smuzhiyun my $op_type = substr($curr_values, $off + 1, 1); 4141*4882a593Smuzhiyun 4142*4882a593Smuzhiyun # Get the full operator variant. 4143*4882a593Smuzhiyun my $opv = $op . substr($curr_vars, $off, 1); 4144*4882a593Smuzhiyun 4145*4882a593Smuzhiyun # Ignore operators passed as parameters. 4146*4882a593Smuzhiyun if ($op_type ne 'V' && 4147*4882a593Smuzhiyun $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) { 4148*4882a593Smuzhiyun 4149*4882a593Smuzhiyun# # Ignore comments 4150*4882a593Smuzhiyun# } elsif ($op =~ /^$;+$/) { 4151*4882a593Smuzhiyun 4152*4882a593Smuzhiyun # ; should have either the end of line or a space or \ after it 4153*4882a593Smuzhiyun } elsif ($op eq ';') { 4154*4882a593Smuzhiyun if ($ctx !~ /.x[WEBC]/ && 4155*4882a593Smuzhiyun $cc !~ /^\\/ && $cc !~ /^;/) { 4156*4882a593Smuzhiyun if (ERROR("SPACING", 4157*4882a593Smuzhiyun "space required after that '$op' $at\n" . $hereptr)) { 4158*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; 4159*4882a593Smuzhiyun $line_fixed = 1; 4160*4882a593Smuzhiyun } 4161*4882a593Smuzhiyun } 4162*4882a593Smuzhiyun 4163*4882a593Smuzhiyun # // is a comment 4164*4882a593Smuzhiyun } elsif ($op eq '//') { 4165*4882a593Smuzhiyun 4166*4882a593Smuzhiyun # : when part of a bitfield 4167*4882a593Smuzhiyun } elsif ($opv eq ':B') { 4168*4882a593Smuzhiyun # skip the bitfield test for now 4169*4882a593Smuzhiyun 4170*4882a593Smuzhiyun # No spaces for: 4171*4882a593Smuzhiyun # -> 4172*4882a593Smuzhiyun } elsif ($op eq '->') { 4173*4882a593Smuzhiyun if ($ctx =~ /Wx.|.xW/) { 4174*4882a593Smuzhiyun if (ERROR("SPACING", 4175*4882a593Smuzhiyun "spaces prohibited around that '$op' $at\n" . $hereptr)) { 4176*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4177*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4178*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4179*4882a593Smuzhiyun } 4180*4882a593Smuzhiyun $line_fixed = 1; 4181*4882a593Smuzhiyun } 4182*4882a593Smuzhiyun } 4183*4882a593Smuzhiyun 4184*4882a593Smuzhiyun # , must not have a space before and must have a space on the right. 4185*4882a593Smuzhiyun } elsif ($op eq ',') { 4186*4882a593Smuzhiyun my $rtrim_before = 0; 4187*4882a593Smuzhiyun my $space_after = 0; 4188*4882a593Smuzhiyun if ($ctx =~ /Wx./) { 4189*4882a593Smuzhiyun if (ERROR("SPACING", 4190*4882a593Smuzhiyun "space prohibited before that '$op' $at\n" . $hereptr)) { 4191*4882a593Smuzhiyun $line_fixed = 1; 4192*4882a593Smuzhiyun $rtrim_before = 1; 4193*4882a593Smuzhiyun } 4194*4882a593Smuzhiyun } 4195*4882a593Smuzhiyun if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) { 4196*4882a593Smuzhiyun if (ERROR("SPACING", 4197*4882a593Smuzhiyun "space required after that '$op' $at\n" . $hereptr)) { 4198*4882a593Smuzhiyun $line_fixed = 1; 4199*4882a593Smuzhiyun $last_after = $n; 4200*4882a593Smuzhiyun $space_after = 1; 4201*4882a593Smuzhiyun } 4202*4882a593Smuzhiyun } 4203*4882a593Smuzhiyun if ($rtrim_before || $space_after) { 4204*4882a593Smuzhiyun if ($rtrim_before) { 4205*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4206*4882a593Smuzhiyun } else { 4207*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); 4208*4882a593Smuzhiyun } 4209*4882a593Smuzhiyun if ($space_after) { 4210*4882a593Smuzhiyun $good .= " "; 4211*4882a593Smuzhiyun } 4212*4882a593Smuzhiyun } 4213*4882a593Smuzhiyun 4214*4882a593Smuzhiyun # '*' as part of a type definition -- reported already. 4215*4882a593Smuzhiyun } elsif ($opv eq '*_') { 4216*4882a593Smuzhiyun #warn "'*' is part of type\n"; 4217*4882a593Smuzhiyun 4218*4882a593Smuzhiyun # unary operators should have a space before and 4219*4882a593Smuzhiyun # none after. May be left adjacent to another 4220*4882a593Smuzhiyun # unary operator, or a cast 4221*4882a593Smuzhiyun } elsif ($op eq '!' || $op eq '~' || 4222*4882a593Smuzhiyun $opv eq '*U' || $opv eq '-U' || 4223*4882a593Smuzhiyun $opv eq '&U' || $opv eq '&&U') { 4224*4882a593Smuzhiyun if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) { 4225*4882a593Smuzhiyun if (ERROR("SPACING", 4226*4882a593Smuzhiyun "space required before that '$op' $at\n" . $hereptr)) { 4227*4882a593Smuzhiyun if ($n != $last_after + 2) { 4228*4882a593Smuzhiyun $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]); 4229*4882a593Smuzhiyun $line_fixed = 1; 4230*4882a593Smuzhiyun } 4231*4882a593Smuzhiyun } 4232*4882a593Smuzhiyun } 4233*4882a593Smuzhiyun if ($op eq '*' && $cc =~/\s*$Modifier\b/) { 4234*4882a593Smuzhiyun # A unary '*' may be const 4235*4882a593Smuzhiyun 4236*4882a593Smuzhiyun } elsif ($ctx =~ /.xW/) { 4237*4882a593Smuzhiyun if (ERROR("SPACING", 4238*4882a593Smuzhiyun "space prohibited after that '$op' $at\n" . $hereptr)) { 4239*4882a593Smuzhiyun $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]); 4240*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4241*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4242*4882a593Smuzhiyun } 4243*4882a593Smuzhiyun $line_fixed = 1; 4244*4882a593Smuzhiyun } 4245*4882a593Smuzhiyun } 4246*4882a593Smuzhiyun 4247*4882a593Smuzhiyun # unary ++ and unary -- are allowed no space on one side. 4248*4882a593Smuzhiyun } elsif ($op eq '++' or $op eq '--') { 4249*4882a593Smuzhiyun if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) { 4250*4882a593Smuzhiyun if (ERROR("SPACING", 4251*4882a593Smuzhiyun "space required one side of that '$op' $at\n" . $hereptr)) { 4252*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " "; 4253*4882a593Smuzhiyun $line_fixed = 1; 4254*4882a593Smuzhiyun } 4255*4882a593Smuzhiyun } 4256*4882a593Smuzhiyun if ($ctx =~ /Wx[BE]/ || 4257*4882a593Smuzhiyun ($ctx =~ /Wx./ && $cc =~ /^;/)) { 4258*4882a593Smuzhiyun if (ERROR("SPACING", 4259*4882a593Smuzhiyun "space prohibited before that '$op' $at\n" . $hereptr)) { 4260*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4261*4882a593Smuzhiyun $line_fixed = 1; 4262*4882a593Smuzhiyun } 4263*4882a593Smuzhiyun } 4264*4882a593Smuzhiyun if ($ctx =~ /ExW/) { 4265*4882a593Smuzhiyun if (ERROR("SPACING", 4266*4882a593Smuzhiyun "space prohibited after that '$op' $at\n" . $hereptr)) { 4267*4882a593Smuzhiyun $good = $fix_elements[$n] . trim($fix_elements[$n + 1]); 4268*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4269*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4270*4882a593Smuzhiyun } 4271*4882a593Smuzhiyun $line_fixed = 1; 4272*4882a593Smuzhiyun } 4273*4882a593Smuzhiyun } 4274*4882a593Smuzhiyun 4275*4882a593Smuzhiyun # << and >> may either have or not have spaces both sides 4276*4882a593Smuzhiyun } elsif ($op eq '<<' or $op eq '>>' or 4277*4882a593Smuzhiyun $op eq '&' or $op eq '^' or $op eq '|' or 4278*4882a593Smuzhiyun $op eq '+' or $op eq '-' or 4279*4882a593Smuzhiyun $op eq '*' or $op eq '/' or 4280*4882a593Smuzhiyun $op eq '%') 4281*4882a593Smuzhiyun { 4282*4882a593Smuzhiyun if ($check) { 4283*4882a593Smuzhiyun if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) { 4284*4882a593Smuzhiyun if (CHK("SPACING", 4285*4882a593Smuzhiyun "spaces preferred around that '$op' $at\n" . $hereptr)) { 4286*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; 4287*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4288*4882a593Smuzhiyun $line_fixed = 1; 4289*4882a593Smuzhiyun } 4290*4882a593Smuzhiyun } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) { 4291*4882a593Smuzhiyun if (CHK("SPACING", 4292*4882a593Smuzhiyun "space preferred before that '$op' $at\n" . $hereptr)) { 4293*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]); 4294*4882a593Smuzhiyun $line_fixed = 1; 4295*4882a593Smuzhiyun } 4296*4882a593Smuzhiyun } 4297*4882a593Smuzhiyun } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) { 4298*4882a593Smuzhiyun if (ERROR("SPACING", 4299*4882a593Smuzhiyun "need consistent spacing around '$op' $at\n" . $hereptr)) { 4300*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; 4301*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4302*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4303*4882a593Smuzhiyun } 4304*4882a593Smuzhiyun $line_fixed = 1; 4305*4882a593Smuzhiyun } 4306*4882a593Smuzhiyun } 4307*4882a593Smuzhiyun 4308*4882a593Smuzhiyun # A colon needs no spaces before when it is 4309*4882a593Smuzhiyun # terminating a case value or a label. 4310*4882a593Smuzhiyun } elsif ($opv eq ':C' || $opv eq ':L') { 4311*4882a593Smuzhiyun if ($ctx =~ /Wx./) { 4312*4882a593Smuzhiyun if (ERROR("SPACING", 4313*4882a593Smuzhiyun "space prohibited before that '$op' $at\n" . $hereptr)) { 4314*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]); 4315*4882a593Smuzhiyun $line_fixed = 1; 4316*4882a593Smuzhiyun } 4317*4882a593Smuzhiyun } 4318*4882a593Smuzhiyun 4319*4882a593Smuzhiyun # All the others need spaces both sides. 4320*4882a593Smuzhiyun } elsif ($ctx !~ /[EWC]x[CWE]/) { 4321*4882a593Smuzhiyun my $ok = 0; 4322*4882a593Smuzhiyun 4323*4882a593Smuzhiyun # Ignore email addresses <foo@bar> 4324*4882a593Smuzhiyun if (($op eq '<' && 4325*4882a593Smuzhiyun $cc =~ /^\S+\@\S+>/) || 4326*4882a593Smuzhiyun ($op eq '>' && 4327*4882a593Smuzhiyun $ca =~ /<\S+\@\S+$/)) 4328*4882a593Smuzhiyun { 4329*4882a593Smuzhiyun $ok = 1; 4330*4882a593Smuzhiyun } 4331*4882a593Smuzhiyun 4332*4882a593Smuzhiyun # for asm volatile statements 4333*4882a593Smuzhiyun # ignore a colon with another 4334*4882a593Smuzhiyun # colon immediately before or after 4335*4882a593Smuzhiyun if (($op eq ':') && 4336*4882a593Smuzhiyun ($ca =~ /:$/ || $cc =~ /^:/)) { 4337*4882a593Smuzhiyun $ok = 1; 4338*4882a593Smuzhiyun } 4339*4882a593Smuzhiyun 4340*4882a593Smuzhiyun # messages are ERROR, but ?: are CHK 4341*4882a593Smuzhiyun if ($ok == 0) { 4342*4882a593Smuzhiyun my $msg_type = \&ERROR; 4343*4882a593Smuzhiyun $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/); 4344*4882a593Smuzhiyun 4345*4882a593Smuzhiyun if (&{$msg_type}("SPACING", 4346*4882a593Smuzhiyun "spaces required around that '$op' $at\n" . $hereptr)) { 4347*4882a593Smuzhiyun $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " "; 4348*4882a593Smuzhiyun if (defined $fix_elements[$n + 2]) { 4349*4882a593Smuzhiyun $fix_elements[$n + 2] =~ s/^\s+//; 4350*4882a593Smuzhiyun } 4351*4882a593Smuzhiyun $line_fixed = 1; 4352*4882a593Smuzhiyun } 4353*4882a593Smuzhiyun } 4354*4882a593Smuzhiyun } 4355*4882a593Smuzhiyun $off += length($elements[$n + 1]); 4356*4882a593Smuzhiyun 4357*4882a593Smuzhiyun## print("n: <$n> GOOD: <$good>\n"); 4358*4882a593Smuzhiyun 4359*4882a593Smuzhiyun $fixed_line = $fixed_line . $good; 4360*4882a593Smuzhiyun } 4361*4882a593Smuzhiyun 4362*4882a593Smuzhiyun if (($#elements % 2) == 0) { 4363*4882a593Smuzhiyun $fixed_line = $fixed_line . $fix_elements[$#elements]; 4364*4882a593Smuzhiyun } 4365*4882a593Smuzhiyun 4366*4882a593Smuzhiyun if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) { 4367*4882a593Smuzhiyun $fixed[$fixlinenr] = $fixed_line; 4368*4882a593Smuzhiyun } 4369*4882a593Smuzhiyun 4370*4882a593Smuzhiyun 4371*4882a593Smuzhiyun } 4372*4882a593Smuzhiyun 4373*4882a593Smuzhiyun# check for whitespace before a non-naked semicolon 4374*4882a593Smuzhiyun if ($line =~ /^\+.*\S\s+;\s*$/) { 4375*4882a593Smuzhiyun if (WARN("SPACING", 4376*4882a593Smuzhiyun "space prohibited before semicolon\n" . $herecurr) && 4377*4882a593Smuzhiyun $fix) { 4378*4882a593Smuzhiyun 1 while $fixed[$fixlinenr] =~ 4379*4882a593Smuzhiyun s/^(\+.*\S)\s+;/$1;/; 4380*4882a593Smuzhiyun } 4381*4882a593Smuzhiyun } 4382*4882a593Smuzhiyun 4383*4882a593Smuzhiyun# check for multiple assignments 4384*4882a593Smuzhiyun if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) { 4385*4882a593Smuzhiyun CHK("MULTIPLE_ASSIGNMENTS", 4386*4882a593Smuzhiyun "multiple assignments should be avoided\n" . $herecurr); 4387*4882a593Smuzhiyun } 4388*4882a593Smuzhiyun 4389*4882a593Smuzhiyun## # check for multiple declarations, allowing for a function declaration 4390*4882a593Smuzhiyun## # continuation. 4391*4882a593Smuzhiyun## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ && 4392*4882a593Smuzhiyun## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) { 4393*4882a593Smuzhiyun## 4394*4882a593Smuzhiyun## # Remove any bracketed sections to ensure we do not 4395*4882a593Smuzhiyun## # falsly report the parameters of functions. 4396*4882a593Smuzhiyun## my $ln = $line; 4397*4882a593Smuzhiyun## while ($ln =~ s/\([^\(\)]*\)//g) { 4398*4882a593Smuzhiyun## } 4399*4882a593Smuzhiyun## if ($ln =~ /,/) { 4400*4882a593Smuzhiyun## WARN("MULTIPLE_DECLARATION", 4401*4882a593Smuzhiyun## "declaring multiple variables together should be avoided\n" . $herecurr); 4402*4882a593Smuzhiyun## } 4403*4882a593Smuzhiyun## } 4404*4882a593Smuzhiyun 4405*4882a593Smuzhiyun#need space before brace following if, while, etc 4406*4882a593Smuzhiyun if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || 4407*4882a593Smuzhiyun $line =~ /do\{/) { 4408*4882a593Smuzhiyun if (ERROR("SPACING", 4409*4882a593Smuzhiyun "space required before the open brace '{'\n" . $herecurr) && 4410*4882a593Smuzhiyun $fix) { 4411*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/; 4412*4882a593Smuzhiyun } 4413*4882a593Smuzhiyun } 4414*4882a593Smuzhiyun 4415*4882a593Smuzhiyun## # check for blank lines before declarations 4416*4882a593Smuzhiyun## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ && 4417*4882a593Smuzhiyun## $prevrawline =~ /^.\s*$/) { 4418*4882a593Smuzhiyun## WARN("SPACING", 4419*4882a593Smuzhiyun## "No blank lines before declarations\n" . $hereprev); 4420*4882a593Smuzhiyun## } 4421*4882a593Smuzhiyun## 4422*4882a593Smuzhiyun 4423*4882a593Smuzhiyun# closing brace should have a space following it when it has anything 4424*4882a593Smuzhiyun# on the line 4425*4882a593Smuzhiyun if ($line =~ /}(?!(?:,|;|\)))\S/) { 4426*4882a593Smuzhiyun if (ERROR("SPACING", 4427*4882a593Smuzhiyun "space required after that close brace '}'\n" . $herecurr) && 4428*4882a593Smuzhiyun $fix) { 4429*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4430*4882a593Smuzhiyun s/}((?!(?:,|;|\)))\S)/} $1/; 4431*4882a593Smuzhiyun } 4432*4882a593Smuzhiyun } 4433*4882a593Smuzhiyun 4434*4882a593Smuzhiyun# check spacing on square brackets 4435*4882a593Smuzhiyun if ($line =~ /\[\s/ && $line !~ /\[\s*$/) { 4436*4882a593Smuzhiyun if (ERROR("SPACING", 4437*4882a593Smuzhiyun "space prohibited after that open square bracket '['\n" . $herecurr) && 4438*4882a593Smuzhiyun $fix) { 4439*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4440*4882a593Smuzhiyun s/\[\s+/\[/; 4441*4882a593Smuzhiyun } 4442*4882a593Smuzhiyun } 4443*4882a593Smuzhiyun if ($line =~ /\s\]/) { 4444*4882a593Smuzhiyun if (ERROR("SPACING", 4445*4882a593Smuzhiyun "space prohibited before that close square bracket ']'\n" . $herecurr) && 4446*4882a593Smuzhiyun $fix) { 4447*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4448*4882a593Smuzhiyun s/\s+\]/\]/; 4449*4882a593Smuzhiyun } 4450*4882a593Smuzhiyun } 4451*4882a593Smuzhiyun 4452*4882a593Smuzhiyun# check spacing on parentheses 4453*4882a593Smuzhiyun if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ && 4454*4882a593Smuzhiyun $line !~ /for\s*\(\s+;/) { 4455*4882a593Smuzhiyun if (ERROR("SPACING", 4456*4882a593Smuzhiyun "space prohibited after that open parenthesis '('\n" . $herecurr) && 4457*4882a593Smuzhiyun $fix) { 4458*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4459*4882a593Smuzhiyun s/\(\s+/\(/; 4460*4882a593Smuzhiyun } 4461*4882a593Smuzhiyun } 4462*4882a593Smuzhiyun if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ && 4463*4882a593Smuzhiyun $line !~ /for\s*\(.*;\s+\)/ && 4464*4882a593Smuzhiyun $line !~ /:\s+\)/) { 4465*4882a593Smuzhiyun if (ERROR("SPACING", 4466*4882a593Smuzhiyun "space prohibited before that close parenthesis ')'\n" . $herecurr) && 4467*4882a593Smuzhiyun $fix) { 4468*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4469*4882a593Smuzhiyun s/\s+\)/\)/; 4470*4882a593Smuzhiyun } 4471*4882a593Smuzhiyun } 4472*4882a593Smuzhiyun 4473*4882a593Smuzhiyun# check unnecessary parentheses around addressof/dereference single $Lvals 4474*4882a593Smuzhiyun# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar 4475*4882a593Smuzhiyun 4476*4882a593Smuzhiyun while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) { 4477*4882a593Smuzhiyun my $var = $1; 4478*4882a593Smuzhiyun if (CHK("UNNECESSARY_PARENTHESES", 4479*4882a593Smuzhiyun "Unnecessary parentheses around $var\n" . $herecurr) && 4480*4882a593Smuzhiyun $fix) { 4481*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/; 4482*4882a593Smuzhiyun } 4483*4882a593Smuzhiyun } 4484*4882a593Smuzhiyun 4485*4882a593Smuzhiyun# check for unnecessary parentheses around function pointer uses 4486*4882a593Smuzhiyun# ie: (foo->bar)(); should be foo->bar(); 4487*4882a593Smuzhiyun# but not "if (foo->bar) (" to avoid some false positives 4488*4882a593Smuzhiyun if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) { 4489*4882a593Smuzhiyun my $var = $2; 4490*4882a593Smuzhiyun if (CHK("UNNECESSARY_PARENTHESES", 4491*4882a593Smuzhiyun "Unnecessary parentheses around function pointer $var\n" . $herecurr) && 4492*4882a593Smuzhiyun $fix) { 4493*4882a593Smuzhiyun my $var2 = deparenthesize($var); 4494*4882a593Smuzhiyun $var2 =~ s/\s//g; 4495*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/; 4496*4882a593Smuzhiyun } 4497*4882a593Smuzhiyun } 4498*4882a593Smuzhiyun 4499*4882a593Smuzhiyun#goto labels aren't indented, allow a single space however 4500*4882a593Smuzhiyun if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and 4501*4882a593Smuzhiyun !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { 4502*4882a593Smuzhiyun if (WARN("INDENTED_LABEL", 4503*4882a593Smuzhiyun "labels should not be indented\n" . $herecurr) && 4504*4882a593Smuzhiyun $fix) { 4505*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4506*4882a593Smuzhiyun s/^(.)\s+/$1/; 4507*4882a593Smuzhiyun } 4508*4882a593Smuzhiyun } 4509*4882a593Smuzhiyun 4510*4882a593Smuzhiyun# return is not a function 4511*4882a593Smuzhiyun if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { 4512*4882a593Smuzhiyun my $spacing = $1; 4513*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 4514*4882a593Smuzhiyun $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) { 4515*4882a593Smuzhiyun my $value = $1; 4516*4882a593Smuzhiyun $value = deparenthesize($value); 4517*4882a593Smuzhiyun if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) { 4518*4882a593Smuzhiyun ERROR("RETURN_PARENTHESES", 4519*4882a593Smuzhiyun "return is not a function, parentheses are not required\n" . $herecurr); 4520*4882a593Smuzhiyun } 4521*4882a593Smuzhiyun } elsif ($spacing !~ /\s+/) { 4522*4882a593Smuzhiyun ERROR("SPACING", 4523*4882a593Smuzhiyun "space required before the open parenthesis '('\n" . $herecurr); 4524*4882a593Smuzhiyun } 4525*4882a593Smuzhiyun } 4526*4882a593Smuzhiyun 4527*4882a593Smuzhiyun# unnecessary return in a void function 4528*4882a593Smuzhiyun# at end-of-function, with the previous line a single leading tab, then return; 4529*4882a593Smuzhiyun# and the line before that not a goto label target like "out:" 4530*4882a593Smuzhiyun if ($sline =~ /^[ \+]}\s*$/ && 4531*4882a593Smuzhiyun $prevline =~ /^\+\treturn\s*;\s*$/ && 4532*4882a593Smuzhiyun $linenr >= 3 && 4533*4882a593Smuzhiyun $lines[$linenr - 3] =~ /^[ +]/ && 4534*4882a593Smuzhiyun $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) { 4535*4882a593Smuzhiyun WARN("RETURN_VOID", 4536*4882a593Smuzhiyun "void function return statements are not generally useful\n" . $hereprev); 4537*4882a593Smuzhiyun } 4538*4882a593Smuzhiyun 4539*4882a593Smuzhiyun# if statements using unnecessary parentheses - ie: if ((foo == bar)) 4540*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 4541*4882a593Smuzhiyun $line =~ /\bif\s*((?:\(\s*){2,})/) { 4542*4882a593Smuzhiyun my $openparens = $1; 4543*4882a593Smuzhiyun my $count = $openparens =~ tr@\(@\(@; 4544*4882a593Smuzhiyun my $msg = ""; 4545*4882a593Smuzhiyun if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) { 4546*4882a593Smuzhiyun my $comp = $4; #Not $1 because of $LvalOrFunc 4547*4882a593Smuzhiyun $msg = " - maybe == should be = ?" if ($comp eq "=="); 4548*4882a593Smuzhiyun WARN("UNNECESSARY_PARENTHESES", 4549*4882a593Smuzhiyun "Unnecessary parentheses$msg\n" . $herecurr); 4550*4882a593Smuzhiyun } 4551*4882a593Smuzhiyun } 4552*4882a593Smuzhiyun 4553*4882a593Smuzhiyun# comparisons with a constant or upper case identifier on the left 4554*4882a593Smuzhiyun# avoid cases like "foo + BAR < baz" 4555*4882a593Smuzhiyun# only fix matches surrounded by parentheses to avoid incorrect 4556*4882a593Smuzhiyun# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5" 4557*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 4558*4882a593Smuzhiyun $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) { 4559*4882a593Smuzhiyun my $lead = $1; 4560*4882a593Smuzhiyun my $const = $2; 4561*4882a593Smuzhiyun my $comp = $3; 4562*4882a593Smuzhiyun my $to = $4; 4563*4882a593Smuzhiyun my $newcomp = $comp; 4564*4882a593Smuzhiyun if ($lead !~ /(?:$Operators|\.)\s*$/ && 4565*4882a593Smuzhiyun $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ && 4566*4882a593Smuzhiyun WARN("CONSTANT_COMPARISON", 4567*4882a593Smuzhiyun "Comparisons should place the constant on the right side of the test\n" . $herecurr) && 4568*4882a593Smuzhiyun $fix) { 4569*4882a593Smuzhiyun if ($comp eq "<") { 4570*4882a593Smuzhiyun $newcomp = ">"; 4571*4882a593Smuzhiyun } elsif ($comp eq "<=") { 4572*4882a593Smuzhiyun $newcomp = ">="; 4573*4882a593Smuzhiyun } elsif ($comp eq ">") { 4574*4882a593Smuzhiyun $newcomp = "<"; 4575*4882a593Smuzhiyun } elsif ($comp eq ">=") { 4576*4882a593Smuzhiyun $newcomp = "<="; 4577*4882a593Smuzhiyun } 4578*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/; 4579*4882a593Smuzhiyun } 4580*4882a593Smuzhiyun } 4581*4882a593Smuzhiyun 4582*4882a593Smuzhiyun# Return of what appears to be an errno should normally be negative 4583*4882a593Smuzhiyun if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { 4584*4882a593Smuzhiyun my $name = $1; 4585*4882a593Smuzhiyun if ($name ne 'EOF' && $name ne 'ERROR') { 4586*4882a593Smuzhiyun WARN("USE_NEGATIVE_ERRNO", 4587*4882a593Smuzhiyun "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); 4588*4882a593Smuzhiyun } 4589*4882a593Smuzhiyun } 4590*4882a593Smuzhiyun 4591*4882a593Smuzhiyun# Need a space before open parenthesis after if, while etc 4592*4882a593Smuzhiyun if ($line =~ /\b(if|while|for|switch)\(/) { 4593*4882a593Smuzhiyun if (ERROR("SPACING", 4594*4882a593Smuzhiyun "space required before the open parenthesis '('\n" . $herecurr) && 4595*4882a593Smuzhiyun $fix) { 4596*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4597*4882a593Smuzhiyun s/\b(if|while|for|switch)\(/$1 \(/; 4598*4882a593Smuzhiyun } 4599*4882a593Smuzhiyun } 4600*4882a593Smuzhiyun 4601*4882a593Smuzhiyun# Check for illegal assignment in if conditional -- and check for trailing 4602*4882a593Smuzhiyun# statements after the conditional. 4603*4882a593Smuzhiyun if ($line =~ /do\s*(?!{)/) { 4604*4882a593Smuzhiyun ($stat, $cond, $line_nr_next, $remain_next, $off_next) = 4605*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0) 4606*4882a593Smuzhiyun if (!defined $stat); 4607*4882a593Smuzhiyun my ($stat_next) = ctx_statement_block($line_nr_next, 4608*4882a593Smuzhiyun $remain_next, $off_next); 4609*4882a593Smuzhiyun $stat_next =~ s/\n./\n /g; 4610*4882a593Smuzhiyun ##print "stat<$stat> stat_next<$stat_next>\n"; 4611*4882a593Smuzhiyun 4612*4882a593Smuzhiyun if ($stat_next =~ /^\s*while\b/) { 4613*4882a593Smuzhiyun # If the statement carries leading newlines, 4614*4882a593Smuzhiyun # then count those as offsets. 4615*4882a593Smuzhiyun my ($whitespace) = 4616*4882a593Smuzhiyun ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s); 4617*4882a593Smuzhiyun my $offset = 4618*4882a593Smuzhiyun statement_rawlines($whitespace) - 1; 4619*4882a593Smuzhiyun 4620*4882a593Smuzhiyun $suppress_whiletrailers{$line_nr_next + 4621*4882a593Smuzhiyun $offset} = 1; 4622*4882a593Smuzhiyun } 4623*4882a593Smuzhiyun } 4624*4882a593Smuzhiyun if (!defined $suppress_whiletrailers{$linenr} && 4625*4882a593Smuzhiyun defined($stat) && defined($cond) && 4626*4882a593Smuzhiyun $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) { 4627*4882a593Smuzhiyun my ($s, $c) = ($stat, $cond); 4628*4882a593Smuzhiyun 4629*4882a593Smuzhiyun if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) { 4630*4882a593Smuzhiyun ERROR("ASSIGN_IN_IF", 4631*4882a593Smuzhiyun "do not use assignment in if condition\n" . $herecurr); 4632*4882a593Smuzhiyun } 4633*4882a593Smuzhiyun 4634*4882a593Smuzhiyun # Find out what is on the end of the line after the 4635*4882a593Smuzhiyun # conditional. 4636*4882a593Smuzhiyun substr($s, 0, length($c), ''); 4637*4882a593Smuzhiyun $s =~ s/\n.*//g; 4638*4882a593Smuzhiyun $s =~ s/$;//g; # Remove any comments 4639*4882a593Smuzhiyun if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ && 4640*4882a593Smuzhiyun $c !~ /}\s*while\s*/) 4641*4882a593Smuzhiyun { 4642*4882a593Smuzhiyun # Find out how long the conditional actually is. 4643*4882a593Smuzhiyun my @newlines = ($c =~ /\n/gs); 4644*4882a593Smuzhiyun my $cond_lines = 1 + $#newlines; 4645*4882a593Smuzhiyun my $stat_real = ''; 4646*4882a593Smuzhiyun 4647*4882a593Smuzhiyun $stat_real = raw_line($linenr, $cond_lines) 4648*4882a593Smuzhiyun . "\n" if ($cond_lines); 4649*4882a593Smuzhiyun if (defined($stat_real) && $cond_lines > 1) { 4650*4882a593Smuzhiyun $stat_real = "[...]\n$stat_real"; 4651*4882a593Smuzhiyun } 4652*4882a593Smuzhiyun 4653*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 4654*4882a593Smuzhiyun "trailing statements should be on next line\n" . $herecurr . $stat_real); 4655*4882a593Smuzhiyun } 4656*4882a593Smuzhiyun } 4657*4882a593Smuzhiyun 4658*4882a593Smuzhiyun# Check for bitwise tests written as boolean 4659*4882a593Smuzhiyun if ($line =~ / 4660*4882a593Smuzhiyun (?: 4661*4882a593Smuzhiyun (?:\[|\(|\&\&|\|\|) 4662*4882a593Smuzhiyun \s*0[xX][0-9]+\s* 4663*4882a593Smuzhiyun (?:\&\&|\|\|) 4664*4882a593Smuzhiyun | 4665*4882a593Smuzhiyun (?:\&\&|\|\|) 4666*4882a593Smuzhiyun \s*0[xX][0-9]+\s* 4667*4882a593Smuzhiyun (?:\&\&|\|\||\)|\]) 4668*4882a593Smuzhiyun )/x) 4669*4882a593Smuzhiyun { 4670*4882a593Smuzhiyun WARN("HEXADECIMAL_BOOLEAN_TEST", 4671*4882a593Smuzhiyun "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr); 4672*4882a593Smuzhiyun } 4673*4882a593Smuzhiyun 4674*4882a593Smuzhiyun# if and else should not have general statements after it 4675*4882a593Smuzhiyun if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) { 4676*4882a593Smuzhiyun my $s = $1; 4677*4882a593Smuzhiyun $s =~ s/$;//g; # Remove any comments 4678*4882a593Smuzhiyun if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) { 4679*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 4680*4882a593Smuzhiyun "trailing statements should be on next line\n" . $herecurr); 4681*4882a593Smuzhiyun } 4682*4882a593Smuzhiyun } 4683*4882a593Smuzhiyun# if should not continue a brace 4684*4882a593Smuzhiyun if ($line =~ /}\s*if\b/) { 4685*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 4686*4882a593Smuzhiyun "trailing statements should be on next line (or did you mean 'else if'?)\n" . 4687*4882a593Smuzhiyun $herecurr); 4688*4882a593Smuzhiyun } 4689*4882a593Smuzhiyun# case and default should not have general statements after them 4690*4882a593Smuzhiyun if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g && 4691*4882a593Smuzhiyun $line !~ /\G(?: 4692*4882a593Smuzhiyun (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$| 4693*4882a593Smuzhiyun \s*return\s+ 4694*4882a593Smuzhiyun )/xg) 4695*4882a593Smuzhiyun { 4696*4882a593Smuzhiyun ERROR("TRAILING_STATEMENTS", 4697*4882a593Smuzhiyun "trailing statements should be on next line\n" . $herecurr); 4698*4882a593Smuzhiyun } 4699*4882a593Smuzhiyun 4700*4882a593Smuzhiyun # Check for }<nl>else {, these must be at the same 4701*4882a593Smuzhiyun # indent level to be relevant to each other. 4702*4882a593Smuzhiyun if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ && 4703*4882a593Smuzhiyun $previndent == $indent) { 4704*4882a593Smuzhiyun if (ERROR("ELSE_AFTER_BRACE", 4705*4882a593Smuzhiyun "else should follow close brace '}'\n" . $hereprev) && 4706*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 4707*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 4708*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 4709*4882a593Smuzhiyun my $fixedline = $prevrawline; 4710*4882a593Smuzhiyun $fixedline =~ s/}\s*$//; 4711*4882a593Smuzhiyun if ($fixedline !~ /^\+\s*$/) { 4712*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4713*4882a593Smuzhiyun } 4714*4882a593Smuzhiyun $fixedline = $rawline; 4715*4882a593Smuzhiyun $fixedline =~ s/^(.\s*)else/$1} else/; 4716*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4717*4882a593Smuzhiyun } 4718*4882a593Smuzhiyun } 4719*4882a593Smuzhiyun 4720*4882a593Smuzhiyun if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ && 4721*4882a593Smuzhiyun $previndent == $indent) { 4722*4882a593Smuzhiyun my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0); 4723*4882a593Smuzhiyun 4724*4882a593Smuzhiyun # Find out what is on the end of the line after the 4725*4882a593Smuzhiyun # conditional. 4726*4882a593Smuzhiyun substr($s, 0, length($c), ''); 4727*4882a593Smuzhiyun $s =~ s/\n.*//g; 4728*4882a593Smuzhiyun 4729*4882a593Smuzhiyun if ($s =~ /^\s*;/) { 4730*4882a593Smuzhiyun if (ERROR("WHILE_AFTER_BRACE", 4731*4882a593Smuzhiyun "while should follow close brace '}'\n" . $hereprev) && 4732*4882a593Smuzhiyun $fix && $prevline =~ /^\+/ && $line =~ /^\+/) { 4733*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 4734*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 4735*4882a593Smuzhiyun my $fixedline = $prevrawline; 4736*4882a593Smuzhiyun my $trailing = $rawline; 4737*4882a593Smuzhiyun $trailing =~ s/^\+//; 4738*4882a593Smuzhiyun $trailing = trim($trailing); 4739*4882a593Smuzhiyun $fixedline =~ s/}\s*$/} $trailing/; 4740*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 4741*4882a593Smuzhiyun } 4742*4882a593Smuzhiyun } 4743*4882a593Smuzhiyun } 4744*4882a593Smuzhiyun 4745*4882a593Smuzhiyun#Specific variable tests 4746*4882a593Smuzhiyun while ($line =~ m{($Constant|$Lval)}g) { 4747*4882a593Smuzhiyun my $var = $1; 4748*4882a593Smuzhiyun 4749*4882a593Smuzhiyun#gcc binary extension 4750*4882a593Smuzhiyun if ($var =~ /^$Binary$/) { 4751*4882a593Smuzhiyun if (WARN("GCC_BINARY_CONSTANT", 4752*4882a593Smuzhiyun "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) && 4753*4882a593Smuzhiyun $fix) { 4754*4882a593Smuzhiyun my $hexval = sprintf("0x%x", oct($var)); 4755*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 4756*4882a593Smuzhiyun s/\b$var\b/$hexval/; 4757*4882a593Smuzhiyun } 4758*4882a593Smuzhiyun } 4759*4882a593Smuzhiyun 4760*4882a593Smuzhiyun#CamelCase 4761*4882a593Smuzhiyun if ($var !~ /^$Constant$/ && 4762*4882a593Smuzhiyun $var =~ /[A-Z][a-z]|[a-z][A-Z]/ && 4763*4882a593Smuzhiyun#Ignore Page<foo> variants 4764*4882a593Smuzhiyun $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ && 4765*4882a593Smuzhiyun#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show) 4766*4882a593Smuzhiyun $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ && 4767*4882a593Smuzhiyun#Ignore some three character SI units explicitly, like MiB and KHz 4768*4882a593Smuzhiyun $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) { 4769*4882a593Smuzhiyun while ($var =~ m{($Ident)}g) { 4770*4882a593Smuzhiyun my $word = $1; 4771*4882a593Smuzhiyun next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/); 4772*4882a593Smuzhiyun if ($check) { 4773*4882a593Smuzhiyun seed_camelcase_includes(); 4774*4882a593Smuzhiyun if (!$file && !$camelcase_file_seeded) { 4775*4882a593Smuzhiyun seed_camelcase_file($realfile); 4776*4882a593Smuzhiyun $camelcase_file_seeded = 1; 4777*4882a593Smuzhiyun } 4778*4882a593Smuzhiyun } 4779*4882a593Smuzhiyun if (!defined $camelcase{$word}) { 4780*4882a593Smuzhiyun $camelcase{$word} = 1; 4781*4882a593Smuzhiyun CHK("CAMELCASE", 4782*4882a593Smuzhiyun "Avoid CamelCase: <$word>\n" . $herecurr); 4783*4882a593Smuzhiyun } 4784*4882a593Smuzhiyun } 4785*4882a593Smuzhiyun } 4786*4882a593Smuzhiyun } 4787*4882a593Smuzhiyun 4788*4882a593Smuzhiyun#no spaces allowed after \ in define 4789*4882a593Smuzhiyun if ($line =~ /\#\s*define.*\\\s+$/) { 4790*4882a593Smuzhiyun if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION", 4791*4882a593Smuzhiyun "Whitespace after \\ makes next lines useless\n" . $herecurr) && 4792*4882a593Smuzhiyun $fix) { 4793*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s+$//; 4794*4882a593Smuzhiyun } 4795*4882a593Smuzhiyun } 4796*4882a593Smuzhiyun 4797*4882a593Smuzhiyun# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes 4798*4882a593Smuzhiyun# itself <asm/foo.h> (uses RAW line) 4799*4882a593Smuzhiyun if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) { 4800*4882a593Smuzhiyun my $file = "$1.h"; 4801*4882a593Smuzhiyun my $checkfile = "include/linux/$file"; 4802*4882a593Smuzhiyun if (-f "$root/$checkfile" && 4803*4882a593Smuzhiyun $realfile ne $checkfile && 4804*4882a593Smuzhiyun $1 !~ /$allowed_asm_includes/) 4805*4882a593Smuzhiyun { 4806*4882a593Smuzhiyun my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`; 4807*4882a593Smuzhiyun if ($asminclude > 0) { 4808*4882a593Smuzhiyun if ($realfile =~ m{^arch/}) { 4809*4882a593Smuzhiyun CHK("ARCH_INCLUDE_LINUX", 4810*4882a593Smuzhiyun "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr); 4811*4882a593Smuzhiyun } else { 4812*4882a593Smuzhiyun WARN("INCLUDE_LINUX", 4813*4882a593Smuzhiyun "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr); 4814*4882a593Smuzhiyun } 4815*4882a593Smuzhiyun } 4816*4882a593Smuzhiyun } 4817*4882a593Smuzhiyun } 4818*4882a593Smuzhiyun 4819*4882a593Smuzhiyun# multi-statement macros should be enclosed in a do while loop, grab the 4820*4882a593Smuzhiyun# first statement and ensure its the whole macro if its not enclosed 4821*4882a593Smuzhiyun# in a known good container 4822*4882a593Smuzhiyun if ($realfile !~ m@/vmlinux.lds.h$@ && 4823*4882a593Smuzhiyun $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { 4824*4882a593Smuzhiyun my $ln = $linenr; 4825*4882a593Smuzhiyun my $cnt = $realcnt; 4826*4882a593Smuzhiyun my ($off, $dstat, $dcond, $rest); 4827*4882a593Smuzhiyun my $ctx = ''; 4828*4882a593Smuzhiyun my $has_flow_statement = 0; 4829*4882a593Smuzhiyun my $has_arg_concat = 0; 4830*4882a593Smuzhiyun ($dstat, $dcond, $ln, $cnt, $off) = 4831*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0); 4832*4882a593Smuzhiyun $ctx = $dstat; 4833*4882a593Smuzhiyun #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n"; 4834*4882a593Smuzhiyun #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; 4835*4882a593Smuzhiyun 4836*4882a593Smuzhiyun $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); 4837*4882a593Smuzhiyun $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); 4838*4882a593Smuzhiyun 4839*4882a593Smuzhiyun $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//; 4840*4882a593Smuzhiyun my $define_args = $1; 4841*4882a593Smuzhiyun my $define_stmt = $dstat; 4842*4882a593Smuzhiyun my @def_args = (); 4843*4882a593Smuzhiyun 4844*4882a593Smuzhiyun if (defined $define_args && $define_args ne "") { 4845*4882a593Smuzhiyun $define_args = substr($define_args, 1, length($define_args) - 2); 4846*4882a593Smuzhiyun $define_args =~ s/\s*//g; 4847*4882a593Smuzhiyun @def_args = split(",", $define_args); 4848*4882a593Smuzhiyun } 4849*4882a593Smuzhiyun 4850*4882a593Smuzhiyun $dstat =~ s/$;//g; 4851*4882a593Smuzhiyun $dstat =~ s/\\\n.//g; 4852*4882a593Smuzhiyun $dstat =~ s/^\s*//s; 4853*4882a593Smuzhiyun $dstat =~ s/\s*$//s; 4854*4882a593Smuzhiyun 4855*4882a593Smuzhiyun # Flatten any parentheses and braces 4856*4882a593Smuzhiyun while ($dstat =~ s/\([^\(\)]*\)/1/ || 4857*4882a593Smuzhiyun $dstat =~ s/\{[^\{\}]*\}/1/ || 4858*4882a593Smuzhiyun $dstat =~ s/.\[[^\[\]]*\]/1/) 4859*4882a593Smuzhiyun { 4860*4882a593Smuzhiyun } 4861*4882a593Smuzhiyun 4862*4882a593Smuzhiyun # Flatten any obvious string concatentation. 4863*4882a593Smuzhiyun while ($dstat =~ s/($String)\s*$Ident/$1/ || 4864*4882a593Smuzhiyun $dstat =~ s/$Ident\s*($String)/$1/) 4865*4882a593Smuzhiyun { 4866*4882a593Smuzhiyun } 4867*4882a593Smuzhiyun 4868*4882a593Smuzhiyun # Make asm volatile uses seem like a generic function 4869*4882a593Smuzhiyun $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; 4870*4882a593Smuzhiyun 4871*4882a593Smuzhiyun my $exceptions = qr{ 4872*4882a593Smuzhiyun $Declare| 4873*4882a593Smuzhiyun module_param_named| 4874*4882a593Smuzhiyun MODULE_PARM_DESC| 4875*4882a593Smuzhiyun DECLARE_PER_CPU| 4876*4882a593Smuzhiyun DEFINE_PER_CPU| 4877*4882a593Smuzhiyun __typeof__\(| 4878*4882a593Smuzhiyun union| 4879*4882a593Smuzhiyun struct| 4880*4882a593Smuzhiyun \.$Ident\s*=\s*| 4881*4882a593Smuzhiyun ^\"|\"$| 4882*4882a593Smuzhiyun ^\[ 4883*4882a593Smuzhiyun }x; 4884*4882a593Smuzhiyun #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; 4885*4882a593Smuzhiyun 4886*4882a593Smuzhiyun $ctx =~ s/\n*$//; 4887*4882a593Smuzhiyun my $herectx = $here . "\n"; 4888*4882a593Smuzhiyun my $stmt_cnt = statement_rawlines($ctx); 4889*4882a593Smuzhiyun 4890*4882a593Smuzhiyun for (my $n = 0; $n < $stmt_cnt; $n++) { 4891*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 4892*4882a593Smuzhiyun } 4893*4882a593Smuzhiyun 4894*4882a593Smuzhiyun if ($dstat ne '' && 4895*4882a593Smuzhiyun $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), 4896*4882a593Smuzhiyun $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); 4897*4882a593Smuzhiyun $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz 4898*4882a593Smuzhiyun $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants 4899*4882a593Smuzhiyun $dstat !~ /$exceptions/ && 4900*4882a593Smuzhiyun $dstat !~ /^\.$Ident\s*=/ && # .foo = 4901*4882a593Smuzhiyun $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo 4902*4882a593Smuzhiyun $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) 4903*4882a593Smuzhiyun $dstat !~ /^for\s*$Constant$/ && # for (...) 4904*4882a593Smuzhiyun $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() 4905*4882a593Smuzhiyun $dstat !~ /^do\s*{/ && # do {... 4906*4882a593Smuzhiyun $dstat !~ /^\(\{/ && # ({... 4907*4882a593Smuzhiyun $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) 4908*4882a593Smuzhiyun { 4909*4882a593Smuzhiyun if ($dstat =~ /^\s*if\b/) { 4910*4882a593Smuzhiyun ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", 4911*4882a593Smuzhiyun "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx"); 4912*4882a593Smuzhiyun } elsif ($dstat =~ /;/) { 4913*4882a593Smuzhiyun ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", 4914*4882a593Smuzhiyun "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); 4915*4882a593Smuzhiyun } else { 4916*4882a593Smuzhiyun ERROR("COMPLEX_MACRO", 4917*4882a593Smuzhiyun "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); 4918*4882a593Smuzhiyun } 4919*4882a593Smuzhiyun 4920*4882a593Smuzhiyun } 4921*4882a593Smuzhiyun 4922*4882a593Smuzhiyun # Make $define_stmt single line, comment-free, etc 4923*4882a593Smuzhiyun my @stmt_array = split('\n', $define_stmt); 4924*4882a593Smuzhiyun my $first = 1; 4925*4882a593Smuzhiyun $define_stmt = ""; 4926*4882a593Smuzhiyun foreach my $l (@stmt_array) { 4927*4882a593Smuzhiyun $l =~ s/\\$//; 4928*4882a593Smuzhiyun if ($first) { 4929*4882a593Smuzhiyun $define_stmt = $l; 4930*4882a593Smuzhiyun $first = 0; 4931*4882a593Smuzhiyun } elsif ($l =~ /^[\+ ]/) { 4932*4882a593Smuzhiyun $define_stmt .= substr($l, 1); 4933*4882a593Smuzhiyun } 4934*4882a593Smuzhiyun } 4935*4882a593Smuzhiyun $define_stmt =~ s/$;//g; 4936*4882a593Smuzhiyun $define_stmt =~ s/\s+/ /g; 4937*4882a593Smuzhiyun $define_stmt = trim($define_stmt); 4938*4882a593Smuzhiyun 4939*4882a593Smuzhiyun# check if any macro arguments are reused (ignore '...' and 'type') 4940*4882a593Smuzhiyun foreach my $arg (@def_args) { 4941*4882a593Smuzhiyun next if ($arg =~ /\.\.\./); 4942*4882a593Smuzhiyun next if ($arg =~ /^type$/i); 4943*4882a593Smuzhiyun my $tmp_stmt = $define_stmt; 4944*4882a593Smuzhiyun $tmp_stmt =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; 4945*4882a593Smuzhiyun $tmp_stmt =~ s/\#+\s*$arg\b//g; 4946*4882a593Smuzhiyun $tmp_stmt =~ s/\b$arg\s*\#\#//g; 4947*4882a593Smuzhiyun my $use_cnt = $tmp_stmt =~ s/\b$arg\b//g; 4948*4882a593Smuzhiyun if ($use_cnt > 1) { 4949*4882a593Smuzhiyun CHK("MACRO_ARG_REUSE", 4950*4882a593Smuzhiyun "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx"); 4951*4882a593Smuzhiyun } 4952*4882a593Smuzhiyun# check if any macro arguments may have other precedence issues 4953*4882a593Smuzhiyun if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m && 4954*4882a593Smuzhiyun ((defined($1) && $1 ne ',') || 4955*4882a593Smuzhiyun (defined($2) && $2 ne ','))) { 4956*4882a593Smuzhiyun CHK("MACRO_ARG_PRECEDENCE", 4957*4882a593Smuzhiyun "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx"); 4958*4882a593Smuzhiyun } 4959*4882a593Smuzhiyun } 4960*4882a593Smuzhiyun 4961*4882a593Smuzhiyun# check for macros with flow control, but without ## concatenation 4962*4882a593Smuzhiyun# ## concatenation is commonly a macro that defines a function so ignore those 4963*4882a593Smuzhiyun if ($has_flow_statement && !$has_arg_concat) { 4964*4882a593Smuzhiyun my $herectx = $here . "\n"; 4965*4882a593Smuzhiyun my $cnt = statement_rawlines($ctx); 4966*4882a593Smuzhiyun 4967*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 4968*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 4969*4882a593Smuzhiyun } 4970*4882a593Smuzhiyun WARN("MACRO_WITH_FLOW_CONTROL", 4971*4882a593Smuzhiyun "Macros with flow control statements should be avoided\n" . "$herectx"); 4972*4882a593Smuzhiyun } 4973*4882a593Smuzhiyun 4974*4882a593Smuzhiyun# check for line continuations outside of #defines, preprocessor #, and asm 4975*4882a593Smuzhiyun 4976*4882a593Smuzhiyun } else { 4977*4882a593Smuzhiyun if ($prevline !~ /^..*\\$/ && 4978*4882a593Smuzhiyun $line !~ /^\+\s*\#.*\\$/ && # preprocessor 4979*4882a593Smuzhiyun $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm 4980*4882a593Smuzhiyun $line =~ /^\+.*\\$/) { 4981*4882a593Smuzhiyun WARN("LINE_CONTINUATIONS", 4982*4882a593Smuzhiyun "Avoid unnecessary line continuations\n" . $herecurr); 4983*4882a593Smuzhiyun } 4984*4882a593Smuzhiyun } 4985*4882a593Smuzhiyun 4986*4882a593Smuzhiyun# do {} while (0) macro tests: 4987*4882a593Smuzhiyun# single-statement macros do not need to be enclosed in do while (0) loop, 4988*4882a593Smuzhiyun# macro should not end with a semicolon 4989*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 4990*4882a593Smuzhiyun $realfile !~ m@/vmlinux.lds.h$@ && 4991*4882a593Smuzhiyun $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) { 4992*4882a593Smuzhiyun my $ln = $linenr; 4993*4882a593Smuzhiyun my $cnt = $realcnt; 4994*4882a593Smuzhiyun my ($off, $dstat, $dcond, $rest); 4995*4882a593Smuzhiyun my $ctx = ''; 4996*4882a593Smuzhiyun ($dstat, $dcond, $ln, $cnt, $off) = 4997*4882a593Smuzhiyun ctx_statement_block($linenr, $realcnt, 0); 4998*4882a593Smuzhiyun $ctx = $dstat; 4999*4882a593Smuzhiyun 5000*4882a593Smuzhiyun $dstat =~ s/\\\n.//g; 5001*4882a593Smuzhiyun $dstat =~ s/$;/ /g; 5002*4882a593Smuzhiyun 5003*4882a593Smuzhiyun if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) { 5004*4882a593Smuzhiyun my $stmts = $2; 5005*4882a593Smuzhiyun my $semis = $3; 5006*4882a593Smuzhiyun 5007*4882a593Smuzhiyun $ctx =~ s/\n*$//; 5008*4882a593Smuzhiyun my $cnt = statement_rawlines($ctx); 5009*4882a593Smuzhiyun my $herectx = $here . "\n"; 5010*4882a593Smuzhiyun 5011*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 5012*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 5013*4882a593Smuzhiyun } 5014*4882a593Smuzhiyun 5015*4882a593Smuzhiyun if (($stmts =~ tr/;/;/) == 1 && 5016*4882a593Smuzhiyun $stmts !~ /^\s*(if|while|for|switch)\b/) { 5017*4882a593Smuzhiyun WARN("SINGLE_STATEMENT_DO_WHILE_MACRO", 5018*4882a593Smuzhiyun "Single statement macros should not use a do {} while (0) loop\n" . "$herectx"); 5019*4882a593Smuzhiyun } 5020*4882a593Smuzhiyun if (defined $semis && $semis ne "") { 5021*4882a593Smuzhiyun WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON", 5022*4882a593Smuzhiyun "do {} while (0) macros should not be semicolon terminated\n" . "$herectx"); 5023*4882a593Smuzhiyun } 5024*4882a593Smuzhiyun } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) { 5025*4882a593Smuzhiyun $ctx =~ s/\n*$//; 5026*4882a593Smuzhiyun my $cnt = statement_rawlines($ctx); 5027*4882a593Smuzhiyun my $herectx = $here . "\n"; 5028*4882a593Smuzhiyun 5029*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 5030*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 5031*4882a593Smuzhiyun } 5032*4882a593Smuzhiyun 5033*4882a593Smuzhiyun WARN("TRAILING_SEMICOLON", 5034*4882a593Smuzhiyun "macros should not use a trailing semicolon\n" . "$herectx"); 5035*4882a593Smuzhiyun } 5036*4882a593Smuzhiyun } 5037*4882a593Smuzhiyun 5038*4882a593Smuzhiyun# make sure symbols are always wrapped with VMLINUX_SYMBOL() ... 5039*4882a593Smuzhiyun# all assignments may have only one of the following with an assignment: 5040*4882a593Smuzhiyun# . 5041*4882a593Smuzhiyun# ALIGN(...) 5042*4882a593Smuzhiyun# VMLINUX_SYMBOL(...) 5043*4882a593Smuzhiyun if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) { 5044*4882a593Smuzhiyun WARN("MISSING_VMLINUX_SYMBOL", 5045*4882a593Smuzhiyun "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr); 5046*4882a593Smuzhiyun } 5047*4882a593Smuzhiyun 5048*4882a593Smuzhiyun# check for redundant bracing round if etc 5049*4882a593Smuzhiyun if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) { 5050*4882a593Smuzhiyun my ($level, $endln, @chunks) = 5051*4882a593Smuzhiyun ctx_statement_full($linenr, $realcnt, 1); 5052*4882a593Smuzhiyun #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n"; 5053*4882a593Smuzhiyun #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"; 5054*4882a593Smuzhiyun if ($#chunks > 0 && $level == 0) { 5055*4882a593Smuzhiyun my @allowed = (); 5056*4882a593Smuzhiyun my $allow = 0; 5057*4882a593Smuzhiyun my $seen = 0; 5058*4882a593Smuzhiyun my $herectx = $here . "\n"; 5059*4882a593Smuzhiyun my $ln = $linenr - 1; 5060*4882a593Smuzhiyun for my $chunk (@chunks) { 5061*4882a593Smuzhiyun my ($cond, $block) = @{$chunk}; 5062*4882a593Smuzhiyun 5063*4882a593Smuzhiyun # If the condition carries leading newlines, then count those as offsets. 5064*4882a593Smuzhiyun my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s); 5065*4882a593Smuzhiyun my $offset = statement_rawlines($whitespace) - 1; 5066*4882a593Smuzhiyun 5067*4882a593Smuzhiyun $allowed[$allow] = 0; 5068*4882a593Smuzhiyun #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n"; 5069*4882a593Smuzhiyun 5070*4882a593Smuzhiyun # We have looked at and allowed this specific line. 5071*4882a593Smuzhiyun $suppress_ifbraces{$ln + $offset} = 1; 5072*4882a593Smuzhiyun 5073*4882a593Smuzhiyun $herectx .= "$rawlines[$ln + $offset]\n[...]\n"; 5074*4882a593Smuzhiyun $ln += statement_rawlines($block) - 1; 5075*4882a593Smuzhiyun 5076*4882a593Smuzhiyun substr($block, 0, length($cond), ''); 5077*4882a593Smuzhiyun 5078*4882a593Smuzhiyun $seen++ if ($block =~ /^\s*{/); 5079*4882a593Smuzhiyun 5080*4882a593Smuzhiyun #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n"; 5081*4882a593Smuzhiyun if (statement_lines($cond) > 1) { 5082*4882a593Smuzhiyun #print "APW: ALLOWED: cond<$cond>\n"; 5083*4882a593Smuzhiyun $allowed[$allow] = 1; 5084*4882a593Smuzhiyun } 5085*4882a593Smuzhiyun if ($block =~/\b(?:if|for|while)\b/) { 5086*4882a593Smuzhiyun #print "APW: ALLOWED: block<$block>\n"; 5087*4882a593Smuzhiyun $allowed[$allow] = 1; 5088*4882a593Smuzhiyun } 5089*4882a593Smuzhiyun if (statement_block_size($block) > 1) { 5090*4882a593Smuzhiyun #print "APW: ALLOWED: lines block<$block>\n"; 5091*4882a593Smuzhiyun $allowed[$allow] = 1; 5092*4882a593Smuzhiyun } 5093*4882a593Smuzhiyun $allow++; 5094*4882a593Smuzhiyun } 5095*4882a593Smuzhiyun if ($seen) { 5096*4882a593Smuzhiyun my $sum_allowed = 0; 5097*4882a593Smuzhiyun foreach (@allowed) { 5098*4882a593Smuzhiyun $sum_allowed += $_; 5099*4882a593Smuzhiyun } 5100*4882a593Smuzhiyun if ($sum_allowed == 0) { 5101*4882a593Smuzhiyun WARN("BRACES", 5102*4882a593Smuzhiyun "braces {} are not necessary for any arm of this statement\n" . $herectx); 5103*4882a593Smuzhiyun } elsif ($sum_allowed != $allow && 5104*4882a593Smuzhiyun $seen != $allow) { 5105*4882a593Smuzhiyun CHK("BRACES", 5106*4882a593Smuzhiyun "braces {} should be used on all arms of this statement\n" . $herectx); 5107*4882a593Smuzhiyun } 5108*4882a593Smuzhiyun } 5109*4882a593Smuzhiyun } 5110*4882a593Smuzhiyun } 5111*4882a593Smuzhiyun if (!defined $suppress_ifbraces{$linenr - 1} && 5112*4882a593Smuzhiyun $line =~ /\b(if|while|for|else)\b/) { 5113*4882a593Smuzhiyun my $allowed = 0; 5114*4882a593Smuzhiyun 5115*4882a593Smuzhiyun # Check the pre-context. 5116*4882a593Smuzhiyun if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) { 5117*4882a593Smuzhiyun #print "APW: ALLOWED: pre<$1>\n"; 5118*4882a593Smuzhiyun $allowed = 1; 5119*4882a593Smuzhiyun } 5120*4882a593Smuzhiyun 5121*4882a593Smuzhiyun my ($level, $endln, @chunks) = 5122*4882a593Smuzhiyun ctx_statement_full($linenr, $realcnt, $-[0]); 5123*4882a593Smuzhiyun 5124*4882a593Smuzhiyun # Check the condition. 5125*4882a593Smuzhiyun my ($cond, $block) = @{$chunks[0]}; 5126*4882a593Smuzhiyun #print "CHECKING<$linenr> cond<$cond> block<$block>\n"; 5127*4882a593Smuzhiyun if (defined $cond) { 5128*4882a593Smuzhiyun substr($block, 0, length($cond), ''); 5129*4882a593Smuzhiyun } 5130*4882a593Smuzhiyun if (statement_lines($cond) > 1) { 5131*4882a593Smuzhiyun #print "APW: ALLOWED: cond<$cond>\n"; 5132*4882a593Smuzhiyun $allowed = 1; 5133*4882a593Smuzhiyun } 5134*4882a593Smuzhiyun if ($block =~/\b(?:if|for|while)\b/) { 5135*4882a593Smuzhiyun #print "APW: ALLOWED: block<$block>\n"; 5136*4882a593Smuzhiyun $allowed = 1; 5137*4882a593Smuzhiyun } 5138*4882a593Smuzhiyun if (statement_block_size($block) > 1) { 5139*4882a593Smuzhiyun #print "APW: ALLOWED: lines block<$block>\n"; 5140*4882a593Smuzhiyun $allowed = 1; 5141*4882a593Smuzhiyun } 5142*4882a593Smuzhiyun # Check the post-context. 5143*4882a593Smuzhiyun if (defined $chunks[1]) { 5144*4882a593Smuzhiyun my ($cond, $block) = @{$chunks[1]}; 5145*4882a593Smuzhiyun if (defined $cond) { 5146*4882a593Smuzhiyun substr($block, 0, length($cond), ''); 5147*4882a593Smuzhiyun } 5148*4882a593Smuzhiyun if ($block =~ /^\s*\{/) { 5149*4882a593Smuzhiyun #print "APW: ALLOWED: chunk-1 block<$block>\n"; 5150*4882a593Smuzhiyun $allowed = 1; 5151*4882a593Smuzhiyun } 5152*4882a593Smuzhiyun } 5153*4882a593Smuzhiyun if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) { 5154*4882a593Smuzhiyun my $herectx = $here . "\n"; 5155*4882a593Smuzhiyun my $cnt = statement_rawlines($block); 5156*4882a593Smuzhiyun 5157*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 5158*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 5159*4882a593Smuzhiyun } 5160*4882a593Smuzhiyun 5161*4882a593Smuzhiyun WARN("BRACES", 5162*4882a593Smuzhiyun "braces {} are not necessary for single statement blocks\n" . $herectx); 5163*4882a593Smuzhiyun } 5164*4882a593Smuzhiyun } 5165*4882a593Smuzhiyun 5166*4882a593Smuzhiyun# check for single line unbalanced braces 5167*4882a593Smuzhiyun if ($sline =~ /^.\s*\}\s*else\s*$/ || 5168*4882a593Smuzhiyun $sline =~ /^.\s*else\s*\{\s*$/) { 5169*4882a593Smuzhiyun CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr); 5170*4882a593Smuzhiyun } 5171*4882a593Smuzhiyun 5172*4882a593Smuzhiyun# check for unnecessary blank lines around braces 5173*4882a593Smuzhiyun if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) { 5174*4882a593Smuzhiyun if (CHK("BRACES", 5175*4882a593Smuzhiyun "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) && 5176*4882a593Smuzhiyun $fix && $prevrawline =~ /^\+/) { 5177*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5178*4882a593Smuzhiyun } 5179*4882a593Smuzhiyun } 5180*4882a593Smuzhiyun if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) { 5181*4882a593Smuzhiyun if (CHK("BRACES", 5182*4882a593Smuzhiyun "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) && 5183*4882a593Smuzhiyun $fix) { 5184*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5185*4882a593Smuzhiyun } 5186*4882a593Smuzhiyun } 5187*4882a593Smuzhiyun 5188*4882a593Smuzhiyun# no volatiles please 5189*4882a593Smuzhiyun my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b}; 5190*4882a593Smuzhiyun if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) { 5191*4882a593Smuzhiyun WARN("VOLATILE", 5192*4882a593Smuzhiyun "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr); 5193*4882a593Smuzhiyun } 5194*4882a593Smuzhiyun 5195*4882a593Smuzhiyun# Check for user-visible strings broken across lines, which breaks the ability 5196*4882a593Smuzhiyun# to grep for the string. Make exceptions when the previous string ends in a 5197*4882a593Smuzhiyun# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{' 5198*4882a593Smuzhiyun# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value 5199*4882a593Smuzhiyun if ($line =~ /^\+\s*$String/ && 5200*4882a593Smuzhiyun $prevline =~ /"\s*$/ && 5201*4882a593Smuzhiyun $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) { 5202*4882a593Smuzhiyun if (WARN("SPLIT_STRING", 5203*4882a593Smuzhiyun "quoted string split across lines\n" . $hereprev) && 5204*4882a593Smuzhiyun $fix && 5205*4882a593Smuzhiyun $prevrawline =~ /^\+.*"\s*$/ && 5206*4882a593Smuzhiyun $last_coalesced_string_linenr != $linenr - 1) { 5207*4882a593Smuzhiyun my $extracted_string = get_quoted_string($line, $rawline); 5208*4882a593Smuzhiyun my $comma_close = ""; 5209*4882a593Smuzhiyun if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) { 5210*4882a593Smuzhiyun $comma_close = $1; 5211*4882a593Smuzhiyun } 5212*4882a593Smuzhiyun 5213*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5214*4882a593Smuzhiyun fix_delete_line($fixlinenr, $rawline); 5215*4882a593Smuzhiyun my $fixedline = $prevrawline; 5216*4882a593Smuzhiyun $fixedline =~ s/"\s*$//; 5217*4882a593Smuzhiyun $fixedline .= substr($extracted_string, 1) . trim($comma_close); 5218*4882a593Smuzhiyun fix_insert_line($fixlinenr - 1, $fixedline); 5219*4882a593Smuzhiyun $fixedline = $rawline; 5220*4882a593Smuzhiyun $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//; 5221*4882a593Smuzhiyun if ($fixedline !~ /\+\s*$/) { 5222*4882a593Smuzhiyun fix_insert_line($fixlinenr, $fixedline); 5223*4882a593Smuzhiyun } 5224*4882a593Smuzhiyun $last_coalesced_string_linenr = $linenr; 5225*4882a593Smuzhiyun } 5226*4882a593Smuzhiyun } 5227*4882a593Smuzhiyun 5228*4882a593Smuzhiyun# check for missing a space in a string concatenation 5229*4882a593Smuzhiyun if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) { 5230*4882a593Smuzhiyun WARN('MISSING_SPACE', 5231*4882a593Smuzhiyun "break quoted strings at a space character\n" . $hereprev); 5232*4882a593Smuzhiyun } 5233*4882a593Smuzhiyun 5234*4882a593Smuzhiyun# check for an embedded function name in a string when the function is known 5235*4882a593Smuzhiyun# This does not work very well for -f --file checking as it depends on patch 5236*4882a593Smuzhiyun# context providing the function name or a single line form for in-file 5237*4882a593Smuzhiyun# function declarations 5238*4882a593Smuzhiyun if ($line =~ /^\+.*$String/ && 5239*4882a593Smuzhiyun defined($context_function) && 5240*4882a593Smuzhiyun get_quoted_string($line, $rawline) =~ /\b$context_function\b/ && 5241*4882a593Smuzhiyun length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) { 5242*4882a593Smuzhiyun WARN("EMBEDDED_FUNCTION_NAME", 5243*4882a593Smuzhiyun "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr); 5244*4882a593Smuzhiyun } 5245*4882a593Smuzhiyun 5246*4882a593Smuzhiyun# check for spaces before a quoted newline 5247*4882a593Smuzhiyun if ($rawline =~ /^.*\".*\s\\n/) { 5248*4882a593Smuzhiyun if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE", 5249*4882a593Smuzhiyun "unnecessary whitespace before a quoted newline\n" . $herecurr) && 5250*4882a593Smuzhiyun $fix) { 5251*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/; 5252*4882a593Smuzhiyun } 5253*4882a593Smuzhiyun 5254*4882a593Smuzhiyun } 5255*4882a593Smuzhiyun 5256*4882a593Smuzhiyun# concatenated string without spaces between elements 5257*4882a593Smuzhiyun if ($line =~ /$String[A-Z_]/ || 5258*4882a593Smuzhiyun ($line =~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^L$/)) { 5259*4882a593Smuzhiyun CHK("CONCATENATED_STRING", 5260*4882a593Smuzhiyun "Concatenated strings should use spaces between elements\n" . $herecurr); 5261*4882a593Smuzhiyun } 5262*4882a593Smuzhiyun 5263*4882a593Smuzhiyun# uncoalesced string fragments 5264*4882a593Smuzhiyun if ($line =~ /$String\s*L?"/) { 5265*4882a593Smuzhiyun WARN("STRING_FRAGMENTS", 5266*4882a593Smuzhiyun "Consecutive strings are generally better as a single string\n" . $herecurr); 5267*4882a593Smuzhiyun } 5268*4882a593Smuzhiyun 5269*4882a593Smuzhiyun# check for non-standard and hex prefixed decimal printf formats 5270*4882a593Smuzhiyun my $show_L = 1; #don't show the same defect twice 5271*4882a593Smuzhiyun my $show_Z = 1; 5272*4882a593Smuzhiyun while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) { 5273*4882a593Smuzhiyun my $string = substr($rawline, $-[1], $+[1] - $-[1]); 5274*4882a593Smuzhiyun $string =~ s/%%/__/g; 5275*4882a593Smuzhiyun # check for %L 5276*4882a593Smuzhiyun if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) { 5277*4882a593Smuzhiyun WARN("PRINTF_L", 5278*4882a593Smuzhiyun "\%L$1 is non-standard C, use %ll$1\n" . $herecurr); 5279*4882a593Smuzhiyun $show_L = 0; 5280*4882a593Smuzhiyun } 5281*4882a593Smuzhiyun # check for %Z 5282*4882a593Smuzhiyun if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) { 5283*4882a593Smuzhiyun WARN("PRINTF_Z", 5284*4882a593Smuzhiyun "%Z$1 is non-standard C, use %z$1\n" . $herecurr); 5285*4882a593Smuzhiyun $show_Z = 0; 5286*4882a593Smuzhiyun } 5287*4882a593Smuzhiyun # check for 0x<decimal> 5288*4882a593Smuzhiyun if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) { 5289*4882a593Smuzhiyun ERROR("PRINTF_0XDECIMAL", 5290*4882a593Smuzhiyun "Prefixing 0x with decimal output is defective\n" . $herecurr); 5291*4882a593Smuzhiyun } 5292*4882a593Smuzhiyun } 5293*4882a593Smuzhiyun 5294*4882a593Smuzhiyun# check for line continuations in quoted strings with odd counts of " 5295*4882a593Smuzhiyun if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) { 5296*4882a593Smuzhiyun WARN("LINE_CONTINUATIONS", 5297*4882a593Smuzhiyun "Avoid line continuations in quoted strings\n" . $herecurr); 5298*4882a593Smuzhiyun } 5299*4882a593Smuzhiyun 5300*4882a593Smuzhiyun# warn about #if 0 5301*4882a593Smuzhiyun if ($line =~ /^.\s*\#\s*if\s+0\b/) { 5302*4882a593Smuzhiyun CHK("REDUNDANT_CODE", 5303*4882a593Smuzhiyun "if this code is redundant consider removing it\n" . 5304*4882a593Smuzhiyun $herecurr); 5305*4882a593Smuzhiyun } 5306*4882a593Smuzhiyun 5307*4882a593Smuzhiyun# check for needless "if (<foo>) fn(<foo>)" uses 5308*4882a593Smuzhiyun if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) { 5309*4882a593Smuzhiyun my $tested = quotemeta($1); 5310*4882a593Smuzhiyun my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;'; 5311*4882a593Smuzhiyun if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) { 5312*4882a593Smuzhiyun my $func = $1; 5313*4882a593Smuzhiyun if (WARN('NEEDLESS_IF', 5314*4882a593Smuzhiyun "$func(NULL) is safe and this check is probably not required\n" . $hereprev) && 5315*4882a593Smuzhiyun $fix) { 5316*4882a593Smuzhiyun my $do_fix = 1; 5317*4882a593Smuzhiyun my $leading_tabs = ""; 5318*4882a593Smuzhiyun my $new_leading_tabs = ""; 5319*4882a593Smuzhiyun if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) { 5320*4882a593Smuzhiyun $leading_tabs = $1; 5321*4882a593Smuzhiyun } else { 5322*4882a593Smuzhiyun $do_fix = 0; 5323*4882a593Smuzhiyun } 5324*4882a593Smuzhiyun if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) { 5325*4882a593Smuzhiyun $new_leading_tabs = $1; 5326*4882a593Smuzhiyun if (length($leading_tabs) + 1 ne length($new_leading_tabs)) { 5327*4882a593Smuzhiyun $do_fix = 0; 5328*4882a593Smuzhiyun } 5329*4882a593Smuzhiyun } else { 5330*4882a593Smuzhiyun $do_fix = 0; 5331*4882a593Smuzhiyun } 5332*4882a593Smuzhiyun if ($do_fix) { 5333*4882a593Smuzhiyun fix_delete_line($fixlinenr - 1, $prevrawline); 5334*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/; 5335*4882a593Smuzhiyun } 5336*4882a593Smuzhiyun } 5337*4882a593Smuzhiyun } 5338*4882a593Smuzhiyun } 5339*4882a593Smuzhiyun 5340*4882a593Smuzhiyun# check for unnecessary "Out of Memory" messages 5341*4882a593Smuzhiyun if ($line =~ /^\+.*\b$logFunctions\s*\(/ && 5342*4882a593Smuzhiyun $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ && 5343*4882a593Smuzhiyun (defined $1 || defined $3) && 5344*4882a593Smuzhiyun $linenr > 3) { 5345*4882a593Smuzhiyun my $testval = $2; 5346*4882a593Smuzhiyun my $testline = $lines[$linenr - 3]; 5347*4882a593Smuzhiyun 5348*4882a593Smuzhiyun my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0); 5349*4882a593Smuzhiyun# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n"); 5350*4882a593Smuzhiyun 5351*4882a593Smuzhiyun if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|kmemdup|(?:dev_)?alloc_skb)/) { 5352*4882a593Smuzhiyun WARN("OOM_MESSAGE", 5353*4882a593Smuzhiyun "Possible unnecessary 'out of memory' message\n" . $hereprev); 5354*4882a593Smuzhiyun } 5355*4882a593Smuzhiyun } 5356*4882a593Smuzhiyun 5357*4882a593Smuzhiyun# check for logging functions with KERN_<LEVEL> 5358*4882a593Smuzhiyun if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ && 5359*4882a593Smuzhiyun $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) { 5360*4882a593Smuzhiyun my $level = $1; 5361*4882a593Smuzhiyun if (WARN("UNNECESSARY_KERN_LEVEL", 5362*4882a593Smuzhiyun "Possible unnecessary $level\n" . $herecurr) && 5363*4882a593Smuzhiyun $fix) { 5364*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s*$level\s*//; 5365*4882a593Smuzhiyun } 5366*4882a593Smuzhiyun } 5367*4882a593Smuzhiyun 5368*4882a593Smuzhiyun# check for logging continuations 5369*4882a593Smuzhiyun if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) { 5370*4882a593Smuzhiyun WARN("LOGGING_CONTINUATION", 5371*4882a593Smuzhiyun "Avoid logging continuation uses where feasible\n" . $herecurr); 5372*4882a593Smuzhiyun } 5373*4882a593Smuzhiyun 5374*4882a593Smuzhiyun# check for mask then right shift without a parentheses 5375*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5376*4882a593Smuzhiyun $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ && 5377*4882a593Smuzhiyun $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so 5378*4882a593Smuzhiyun WARN("MASK_THEN_SHIFT", 5379*4882a593Smuzhiyun "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr); 5380*4882a593Smuzhiyun } 5381*4882a593Smuzhiyun 5382*4882a593Smuzhiyun# check for pointer comparisons to NULL 5383*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0) { 5384*4882a593Smuzhiyun while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) { 5385*4882a593Smuzhiyun my $val = $1; 5386*4882a593Smuzhiyun my $equal = "!"; 5387*4882a593Smuzhiyun $equal = "" if ($4 eq "!="); 5388*4882a593Smuzhiyun if (CHK("COMPARISON_TO_NULL", 5389*4882a593Smuzhiyun "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) && 5390*4882a593Smuzhiyun $fix) { 5391*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/; 5392*4882a593Smuzhiyun } 5393*4882a593Smuzhiyun } 5394*4882a593Smuzhiyun } 5395*4882a593Smuzhiyun 5396*4882a593Smuzhiyun# check for bad placement of section $InitAttribute (e.g.: __initdata) 5397*4882a593Smuzhiyun if ($line =~ /(\b$InitAttribute\b)/) { 5398*4882a593Smuzhiyun my $attr = $1; 5399*4882a593Smuzhiyun if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) { 5400*4882a593Smuzhiyun my $ptr = $1; 5401*4882a593Smuzhiyun my $var = $2; 5402*4882a593Smuzhiyun if ((($ptr =~ /\b(union|struct)\s+$attr\b/ && 5403*4882a593Smuzhiyun ERROR("MISPLACED_INIT", 5404*4882a593Smuzhiyun "$attr should be placed after $var\n" . $herecurr)) || 5405*4882a593Smuzhiyun ($ptr !~ /\b(union|struct)\s+$attr\b/ && 5406*4882a593Smuzhiyun WARN("MISPLACED_INIT", 5407*4882a593Smuzhiyun "$attr should be placed after $var\n" . $herecurr))) && 5408*4882a593Smuzhiyun $fix) { 5409*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; 5410*4882a593Smuzhiyun } 5411*4882a593Smuzhiyun } 5412*4882a593Smuzhiyun } 5413*4882a593Smuzhiyun 5414*4882a593Smuzhiyun# check for $InitAttributeData (ie: __initdata) with const 5415*4882a593Smuzhiyun if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) { 5416*4882a593Smuzhiyun my $attr = $1; 5417*4882a593Smuzhiyun $attr =~ /($InitAttributePrefix)(.*)/; 5418*4882a593Smuzhiyun my $attr_prefix = $1; 5419*4882a593Smuzhiyun my $attr_type = $2; 5420*4882a593Smuzhiyun if (ERROR("INIT_ATTRIBUTE", 5421*4882a593Smuzhiyun "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) && 5422*4882a593Smuzhiyun $fix) { 5423*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 5424*4882a593Smuzhiyun s/$InitAttributeData/${attr_prefix}initconst/; 5425*4882a593Smuzhiyun } 5426*4882a593Smuzhiyun } 5427*4882a593Smuzhiyun 5428*4882a593Smuzhiyun# check for $InitAttributeConst (ie: __initconst) without const 5429*4882a593Smuzhiyun if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) { 5430*4882a593Smuzhiyun my $attr = $1; 5431*4882a593Smuzhiyun if (ERROR("INIT_ATTRIBUTE", 5432*4882a593Smuzhiyun "Use of $attr requires a separate use of const\n" . $herecurr) && 5433*4882a593Smuzhiyun $fix) { 5434*4882a593Smuzhiyun my $lead = $fixed[$fixlinenr] =~ 5435*4882a593Smuzhiyun /(^\+\s*(?:static\s+))/; 5436*4882a593Smuzhiyun $lead = rtrim($1); 5437*4882a593Smuzhiyun $lead = "$lead " if ($lead !~ /^\+$/); 5438*4882a593Smuzhiyun $lead = "${lead}const "; 5439*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/; 5440*4882a593Smuzhiyun } 5441*4882a593Smuzhiyun } 5442*4882a593Smuzhiyun 5443*4882a593Smuzhiyun# check for __read_mostly with const non-pointer (should just be const) 5444*4882a593Smuzhiyun if ($line =~ /\b__read_mostly\b/ && 5445*4882a593Smuzhiyun $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) { 5446*4882a593Smuzhiyun if (ERROR("CONST_READ_MOSTLY", 5447*4882a593Smuzhiyun "Invalid use of __read_mostly with const type\n" . $herecurr) && 5448*4882a593Smuzhiyun $fix) { 5449*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//; 5450*4882a593Smuzhiyun } 5451*4882a593Smuzhiyun } 5452*4882a593Smuzhiyun 5453*4882a593Smuzhiyun# don't use __constant_<foo> functions outside of include/uapi/ 5454*4882a593Smuzhiyun if ($realfile !~ m@^include/uapi/@ && 5455*4882a593Smuzhiyun $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) { 5456*4882a593Smuzhiyun my $constant_func = $1; 5457*4882a593Smuzhiyun my $func = $constant_func; 5458*4882a593Smuzhiyun $func =~ s/^__constant_//; 5459*4882a593Smuzhiyun if (WARN("CONSTANT_CONVERSION", 5460*4882a593Smuzhiyun "$constant_func should be $func\n" . $herecurr) && 5461*4882a593Smuzhiyun $fix) { 5462*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g; 5463*4882a593Smuzhiyun } 5464*4882a593Smuzhiyun } 5465*4882a593Smuzhiyun 5466*4882a593Smuzhiyun# prefer usleep_range over udelay 5467*4882a593Smuzhiyun if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) { 5468*4882a593Smuzhiyun my $delay = $1; 5469*4882a593Smuzhiyun # ignore udelay's < 10, however 5470*4882a593Smuzhiyun if (! ($delay < 10) ) { 5471*4882a593Smuzhiyun CHK("USLEEP_RANGE", 5472*4882a593Smuzhiyun "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr); 5473*4882a593Smuzhiyun } 5474*4882a593Smuzhiyun if ($delay > 2000) { 5475*4882a593Smuzhiyun WARN("LONG_UDELAY", 5476*4882a593Smuzhiyun "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr); 5477*4882a593Smuzhiyun } 5478*4882a593Smuzhiyun } 5479*4882a593Smuzhiyun 5480*4882a593Smuzhiyun# warn about unexpectedly long msleep's 5481*4882a593Smuzhiyun if ($line =~ /\bmsleep\s*\((\d+)\);/) { 5482*4882a593Smuzhiyun if ($1 < 20) { 5483*4882a593Smuzhiyun WARN("MSLEEP", 5484*4882a593Smuzhiyun "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr); 5485*4882a593Smuzhiyun } 5486*4882a593Smuzhiyun } 5487*4882a593Smuzhiyun 5488*4882a593Smuzhiyun# check for comparisons of jiffies 5489*4882a593Smuzhiyun if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) { 5490*4882a593Smuzhiyun WARN("JIFFIES_COMPARISON", 5491*4882a593Smuzhiyun "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr); 5492*4882a593Smuzhiyun } 5493*4882a593Smuzhiyun 5494*4882a593Smuzhiyun# check for comparisons of get_jiffies_64() 5495*4882a593Smuzhiyun if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) { 5496*4882a593Smuzhiyun WARN("JIFFIES_COMPARISON", 5497*4882a593Smuzhiyun "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr); 5498*4882a593Smuzhiyun } 5499*4882a593Smuzhiyun 5500*4882a593Smuzhiyun# warn about #ifdefs in C files 5501*4882a593Smuzhiyun# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) { 5502*4882a593Smuzhiyun# print "#ifdef in C files should be avoided\n"; 5503*4882a593Smuzhiyun# print "$herecurr"; 5504*4882a593Smuzhiyun# $clean = 0; 5505*4882a593Smuzhiyun# } 5506*4882a593Smuzhiyun 5507*4882a593Smuzhiyun# warn about spacing in #ifdefs 5508*4882a593Smuzhiyun if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) { 5509*4882a593Smuzhiyun if (ERROR("SPACING", 5510*4882a593Smuzhiyun "exactly one space required after that #$1\n" . $herecurr) && 5511*4882a593Smuzhiyun $fix) { 5512*4882a593Smuzhiyun $fixed[$fixlinenr] =~ 5513*4882a593Smuzhiyun s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /; 5514*4882a593Smuzhiyun } 5515*4882a593Smuzhiyun 5516*4882a593Smuzhiyun } 5517*4882a593Smuzhiyun 5518*4882a593Smuzhiyun# check for spinlock_t definitions without a comment. 5519*4882a593Smuzhiyun if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ || 5520*4882a593Smuzhiyun $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) { 5521*4882a593Smuzhiyun my $which = $1; 5522*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 5523*4882a593Smuzhiyun CHK("UNCOMMENTED_DEFINITION", 5524*4882a593Smuzhiyun "$1 definition without comment\n" . $herecurr); 5525*4882a593Smuzhiyun } 5526*4882a593Smuzhiyun } 5527*4882a593Smuzhiyun# check for memory barriers without a comment. 5528*4882a593Smuzhiyun 5529*4882a593Smuzhiyun my $barriers = qr{ 5530*4882a593Smuzhiyun mb| 5531*4882a593Smuzhiyun rmb| 5532*4882a593Smuzhiyun wmb| 5533*4882a593Smuzhiyun read_barrier_depends 5534*4882a593Smuzhiyun }x; 5535*4882a593Smuzhiyun my $barrier_stems = qr{ 5536*4882a593Smuzhiyun mb__before_atomic| 5537*4882a593Smuzhiyun mb__after_atomic| 5538*4882a593Smuzhiyun store_release| 5539*4882a593Smuzhiyun load_acquire| 5540*4882a593Smuzhiyun store_mb| 5541*4882a593Smuzhiyun (?:$barriers) 5542*4882a593Smuzhiyun }x; 5543*4882a593Smuzhiyun my $all_barriers = qr{ 5544*4882a593Smuzhiyun (?:$barriers)| 5545*4882a593Smuzhiyun smp_(?:$barrier_stems)| 5546*4882a593Smuzhiyun virt_(?:$barrier_stems) 5547*4882a593Smuzhiyun }x; 5548*4882a593Smuzhiyun 5549*4882a593Smuzhiyun if ($line =~ /\b(?:$all_barriers)\s*\(/) { 5550*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 5551*4882a593Smuzhiyun WARN("MEMORY_BARRIER", 5552*4882a593Smuzhiyun "memory barrier without comment\n" . $herecurr); 5553*4882a593Smuzhiyun } 5554*4882a593Smuzhiyun } 5555*4882a593Smuzhiyun 5556*4882a593Smuzhiyun my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; 5557*4882a593Smuzhiyun 5558*4882a593Smuzhiyun if ($realfile !~ m@^include/asm-generic/@ && 5559*4882a593Smuzhiyun $realfile !~ m@/barrier\.h$@ && 5560*4882a593Smuzhiyun $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && 5561*4882a593Smuzhiyun $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { 5562*4882a593Smuzhiyun WARN("MEMORY_BARRIER", 5563*4882a593Smuzhiyun "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); 5564*4882a593Smuzhiyun } 5565*4882a593Smuzhiyun 5566*4882a593Smuzhiyun# check for waitqueue_active without a comment. 5567*4882a593Smuzhiyun if ($line =~ /\bwaitqueue_active\s*\(/) { 5568*4882a593Smuzhiyun if (!ctx_has_comment($first_line, $linenr)) { 5569*4882a593Smuzhiyun WARN("WAITQUEUE_ACTIVE", 5570*4882a593Smuzhiyun "waitqueue_active without comment\n" . $herecurr); 5571*4882a593Smuzhiyun } 5572*4882a593Smuzhiyun } 5573*4882a593Smuzhiyun 5574*4882a593Smuzhiyun# check of hardware specific defines 5575*4882a593Smuzhiyun if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) { 5576*4882a593Smuzhiyun CHK("ARCH_DEFINES", 5577*4882a593Smuzhiyun "architecture specific defines should be avoided\n" . $herecurr); 5578*4882a593Smuzhiyun } 5579*4882a593Smuzhiyun 5580*4882a593Smuzhiyun# check that the storage class is not after a type 5581*4882a593Smuzhiyun if ($line =~ /\b($Type)\s+($Storage)\b/) { 5582*4882a593Smuzhiyun WARN("STORAGE_CLASS", 5583*4882a593Smuzhiyun "storage class '$2' should be located before type '$1'\n" . $herecurr); 5584*4882a593Smuzhiyun } 5585*4882a593Smuzhiyun# Check that the storage class is at the beginning of a declaration 5586*4882a593Smuzhiyun if ($line =~ /\b$Storage\b/ && 5587*4882a593Smuzhiyun $line !~ /^.\s*$Storage/ && 5588*4882a593Smuzhiyun $line =~ /^.\s*(.+?)\$Storage\s/ && 5589*4882a593Smuzhiyun $1 !~ /[\,\)]\s*$/) { 5590*4882a593Smuzhiyun WARN("STORAGE_CLASS", 5591*4882a593Smuzhiyun "storage class should be at the beginning of the declaration\n" . $herecurr); 5592*4882a593Smuzhiyun } 5593*4882a593Smuzhiyun 5594*4882a593Smuzhiyun# check the location of the inline attribute, that it is between 5595*4882a593Smuzhiyun# storage class and type. 5596*4882a593Smuzhiyun if ($line =~ /\b$Type\s+$Inline\b/ || 5597*4882a593Smuzhiyun $line =~ /\b$Inline\s+$Storage\b/) { 5598*4882a593Smuzhiyun ERROR("INLINE_LOCATION", 5599*4882a593Smuzhiyun "inline keyword should sit between storage class and type\n" . $herecurr); 5600*4882a593Smuzhiyun } 5601*4882a593Smuzhiyun 5602*4882a593Smuzhiyun# Check for __inline__ and __inline, prefer inline 5603*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5604*4882a593Smuzhiyun $line =~ /\b(__inline__|__inline)\b/) { 5605*4882a593Smuzhiyun if (WARN("INLINE", 5606*4882a593Smuzhiyun "plain inline is preferred over $1\n" . $herecurr) && 5607*4882a593Smuzhiyun $fix) { 5608*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/; 5609*4882a593Smuzhiyun 5610*4882a593Smuzhiyun } 5611*4882a593Smuzhiyun } 5612*4882a593Smuzhiyun 5613*4882a593Smuzhiyun# Check for __attribute__ packed, prefer __packed 5614*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5615*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) { 5616*4882a593Smuzhiyun WARN("PREFER_PACKED", 5617*4882a593Smuzhiyun "__packed is preferred over __attribute__((packed))\n" . $herecurr); 5618*4882a593Smuzhiyun } 5619*4882a593Smuzhiyun 5620*4882a593Smuzhiyun# Check for new packed members, warn to use care 5621*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5622*4882a593Smuzhiyun $line =~ /\b(__attribute__\s*\(\s*\(.*\bpacked|__packed)\b/) { 5623*4882a593Smuzhiyun WARN("NEW_PACKED", 5624*4882a593Smuzhiyun "Adding new packed members is to be done with care\n" . $herecurr); 5625*4882a593Smuzhiyun } 5626*4882a593Smuzhiyun 5627*4882a593Smuzhiyun# Check for __attribute__ aligned, prefer __aligned 5628*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5629*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) { 5630*4882a593Smuzhiyun WARN("PREFER_ALIGNED", 5631*4882a593Smuzhiyun "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr); 5632*4882a593Smuzhiyun } 5633*4882a593Smuzhiyun 5634*4882a593Smuzhiyun# Check for __attribute__ format(printf, prefer __printf 5635*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5636*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) { 5637*4882a593Smuzhiyun if (WARN("PREFER_PRINTF", 5638*4882a593Smuzhiyun "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) && 5639*4882a593Smuzhiyun $fix) { 5640*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex; 5641*4882a593Smuzhiyun 5642*4882a593Smuzhiyun } 5643*4882a593Smuzhiyun } 5644*4882a593Smuzhiyun 5645*4882a593Smuzhiyun# Check for __attribute__ format(scanf, prefer __scanf 5646*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5647*4882a593Smuzhiyun $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) { 5648*4882a593Smuzhiyun if (WARN("PREFER_SCANF", 5649*4882a593Smuzhiyun "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) && 5650*4882a593Smuzhiyun $fix) { 5651*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex; 5652*4882a593Smuzhiyun } 5653*4882a593Smuzhiyun } 5654*4882a593Smuzhiyun 5655*4882a593Smuzhiyun# Check for __attribute__ weak, or __weak declarations (may have link issues) 5656*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5657*4882a593Smuzhiyun $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ && 5658*4882a593Smuzhiyun ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ || 5659*4882a593Smuzhiyun $line =~ /\b__weak\b/)) { 5660*4882a593Smuzhiyun ERROR("WEAK_DECLARATION", 5661*4882a593Smuzhiyun "Using weak declarations can have unintended link defects\n" . $herecurr); 5662*4882a593Smuzhiyun } 5663*4882a593Smuzhiyun 5664*4882a593Smuzhiyun# check for c99 types like uint8_t used outside of uapi/ and tools/ 5665*4882a593Smuzhiyun if ($realfile !~ m@\binclude/uapi/@ && 5666*4882a593Smuzhiyun $realfile !~ m@\btools/@ && 5667*4882a593Smuzhiyun $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) { 5668*4882a593Smuzhiyun my $type = $1; 5669*4882a593Smuzhiyun if ($type =~ /\b($typeC99Typedefs)\b/) { 5670*4882a593Smuzhiyun $type = $1; 5671*4882a593Smuzhiyun my $kernel_type = 'u'; 5672*4882a593Smuzhiyun $kernel_type = 's' if ($type =~ /^_*[si]/); 5673*4882a593Smuzhiyun $type =~ /(\d+)/; 5674*4882a593Smuzhiyun $kernel_type .= $1; 5675*4882a593Smuzhiyun if (CHK("PREFER_KERNEL_TYPES", 5676*4882a593Smuzhiyun "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) && 5677*4882a593Smuzhiyun $fix) { 5678*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/; 5679*4882a593Smuzhiyun } 5680*4882a593Smuzhiyun } 5681*4882a593Smuzhiyun } 5682*4882a593Smuzhiyun 5683*4882a593Smuzhiyun# check for cast of C90 native int or longer types constants 5684*4882a593Smuzhiyun if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { 5685*4882a593Smuzhiyun my $cast = $1; 5686*4882a593Smuzhiyun my $const = $2; 5687*4882a593Smuzhiyun if (WARN("TYPECAST_INT_CONSTANT", 5688*4882a593Smuzhiyun "Unnecessary typecast of c90 int constant\n" . $herecurr) && 5689*4882a593Smuzhiyun $fix) { 5690*4882a593Smuzhiyun my $suffix = ""; 5691*4882a593Smuzhiyun my $newconst = $const; 5692*4882a593Smuzhiyun $newconst =~ s/${Int_type}$//; 5693*4882a593Smuzhiyun $suffix .= 'U' if ($cast =~ /\bunsigned\b/); 5694*4882a593Smuzhiyun if ($cast =~ /\blong\s+long\b/) { 5695*4882a593Smuzhiyun $suffix .= 'LL'; 5696*4882a593Smuzhiyun } elsif ($cast =~ /\blong\b/) { 5697*4882a593Smuzhiyun $suffix .= 'L'; 5698*4882a593Smuzhiyun } 5699*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; 5700*4882a593Smuzhiyun } 5701*4882a593Smuzhiyun } 5702*4882a593Smuzhiyun 5703*4882a593Smuzhiyun# check for sizeof(&) 5704*4882a593Smuzhiyun if ($line =~ /\bsizeof\s*\(\s*\&/) { 5705*4882a593Smuzhiyun WARN("SIZEOF_ADDRESS", 5706*4882a593Smuzhiyun "sizeof(& should be avoided\n" . $herecurr); 5707*4882a593Smuzhiyun } 5708*4882a593Smuzhiyun 5709*4882a593Smuzhiyun# check for sizeof without parenthesis 5710*4882a593Smuzhiyun if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) { 5711*4882a593Smuzhiyun if (WARN("SIZEOF_PARENTHESIS", 5712*4882a593Smuzhiyun "sizeof $1 should be sizeof($1)\n" . $herecurr) && 5713*4882a593Smuzhiyun $fix) { 5714*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex; 5715*4882a593Smuzhiyun } 5716*4882a593Smuzhiyun } 5717*4882a593Smuzhiyun 5718*4882a593Smuzhiyun# check for struct spinlock declarations 5719*4882a593Smuzhiyun if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) { 5720*4882a593Smuzhiyun WARN("USE_SPINLOCK_T", 5721*4882a593Smuzhiyun "struct spinlock should be spinlock_t\n" . $herecurr); 5722*4882a593Smuzhiyun } 5723*4882a593Smuzhiyun 5724*4882a593Smuzhiyun# check for seq_printf uses that could be seq_puts 5725*4882a593Smuzhiyun if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) { 5726*4882a593Smuzhiyun my $fmt = get_quoted_string($line, $rawline); 5727*4882a593Smuzhiyun $fmt =~ s/%%//g; 5728*4882a593Smuzhiyun if ($fmt !~ /%/) { 5729*4882a593Smuzhiyun if (WARN("PREFER_SEQ_PUTS", 5730*4882a593Smuzhiyun "Prefer seq_puts to seq_printf\n" . $herecurr) && 5731*4882a593Smuzhiyun $fix) { 5732*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/; 5733*4882a593Smuzhiyun } 5734*4882a593Smuzhiyun } 5735*4882a593Smuzhiyun } 5736*4882a593Smuzhiyun 5737*4882a593Smuzhiyun # check for vsprintf extension %p<foo> misuses 5738*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5739*4882a593Smuzhiyun defined $stat && 5740*4882a593Smuzhiyun $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s && 5741*4882a593Smuzhiyun $1 !~ /^_*volatile_*$/) { 5742*4882a593Smuzhiyun my $bad_extension = ""; 5743*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 5744*4882a593Smuzhiyun $lc = $lc + $linenr; 5745*4882a593Smuzhiyun for (my $count = $linenr; $count <= $lc; $count++) { 5746*4882a593Smuzhiyun my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0)); 5747*4882a593Smuzhiyun $fmt =~ s/%%//g; 5748*4882a593Smuzhiyun if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGNO]).)/) { 5749*4882a593Smuzhiyun $bad_extension = $1; 5750*4882a593Smuzhiyun last; 5751*4882a593Smuzhiyun } 5752*4882a593Smuzhiyun } 5753*4882a593Smuzhiyun if ($bad_extension ne "") { 5754*4882a593Smuzhiyun my $stat_real = raw_line($linenr, 0); 5755*4882a593Smuzhiyun for (my $count = $linenr + 1; $count <= $lc; $count++) { 5756*4882a593Smuzhiyun $stat_real = $stat_real . "\n" . raw_line($count, 0); 5757*4882a593Smuzhiyun } 5758*4882a593Smuzhiyun WARN("VSPRINTF_POINTER_EXTENSION", 5759*4882a593Smuzhiyun "Invalid vsprintf pointer extension '$bad_extension'\n" . "$here\n$stat_real\n"); 5760*4882a593Smuzhiyun } 5761*4882a593Smuzhiyun } 5762*4882a593Smuzhiyun 5763*4882a593Smuzhiyun# Check for misused memsets 5764*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5765*4882a593Smuzhiyun defined $stat && 5766*4882a593Smuzhiyun $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) { 5767*4882a593Smuzhiyun 5768*4882a593Smuzhiyun my $ms_addr = $2; 5769*4882a593Smuzhiyun my $ms_val = $7; 5770*4882a593Smuzhiyun my $ms_size = $12; 5771*4882a593Smuzhiyun 5772*4882a593Smuzhiyun if ($ms_size =~ /^(0x|)0$/i) { 5773*4882a593Smuzhiyun ERROR("MEMSET", 5774*4882a593Smuzhiyun "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n"); 5775*4882a593Smuzhiyun } elsif ($ms_size =~ /^(0x|)1$/i) { 5776*4882a593Smuzhiyun WARN("MEMSET", 5777*4882a593Smuzhiyun "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n"); 5778*4882a593Smuzhiyun } 5779*4882a593Smuzhiyun } 5780*4882a593Smuzhiyun 5781*4882a593Smuzhiyun# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) 5782*4882a593Smuzhiyun# if ($^V && $^V ge 5.10.0 && 5783*4882a593Smuzhiyun# defined $stat && 5784*4882a593Smuzhiyun# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 5785*4882a593Smuzhiyun# if (WARN("PREFER_ETHER_ADDR_COPY", 5786*4882a593Smuzhiyun# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && 5787*4882a593Smuzhiyun# $fix) { 5788*4882a593Smuzhiyun# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; 5789*4882a593Smuzhiyun# } 5790*4882a593Smuzhiyun# } 5791*4882a593Smuzhiyun 5792*4882a593Smuzhiyun# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) 5793*4882a593Smuzhiyun# if ($^V && $^V ge 5.10.0 && 5794*4882a593Smuzhiyun# defined $stat && 5795*4882a593Smuzhiyun# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 5796*4882a593Smuzhiyun# WARN("PREFER_ETHER_ADDR_EQUAL", 5797*4882a593Smuzhiyun# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") 5798*4882a593Smuzhiyun# } 5799*4882a593Smuzhiyun 5800*4882a593Smuzhiyun# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr 5801*4882a593Smuzhiyun# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr 5802*4882a593Smuzhiyun# if ($^V && $^V ge 5.10.0 && 5803*4882a593Smuzhiyun# defined $stat && 5804*4882a593Smuzhiyun# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { 5805*4882a593Smuzhiyun# 5806*4882a593Smuzhiyun# my $ms_val = $7; 5807*4882a593Smuzhiyun# 5808*4882a593Smuzhiyun# if ($ms_val =~ /^(?:0x|)0+$/i) { 5809*4882a593Smuzhiyun# if (WARN("PREFER_ETH_ZERO_ADDR", 5810*4882a593Smuzhiyun# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && 5811*4882a593Smuzhiyun# $fix) { 5812*4882a593Smuzhiyun# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; 5813*4882a593Smuzhiyun# } 5814*4882a593Smuzhiyun# } elsif ($ms_val =~ /^(?:0xff|255)$/i) { 5815*4882a593Smuzhiyun# if (WARN("PREFER_ETH_BROADCAST_ADDR", 5816*4882a593Smuzhiyun# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && 5817*4882a593Smuzhiyun# $fix) { 5818*4882a593Smuzhiyun# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; 5819*4882a593Smuzhiyun# } 5820*4882a593Smuzhiyun# } 5821*4882a593Smuzhiyun# } 5822*4882a593Smuzhiyun 5823*4882a593Smuzhiyun# typecasts on min/max could be min_t/max_t 5824*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5825*4882a593Smuzhiyun defined $stat && 5826*4882a593Smuzhiyun $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) { 5827*4882a593Smuzhiyun if (defined $2 || defined $7) { 5828*4882a593Smuzhiyun my $call = $1; 5829*4882a593Smuzhiyun my $cast1 = deparenthesize($2); 5830*4882a593Smuzhiyun my $arg1 = $3; 5831*4882a593Smuzhiyun my $cast2 = deparenthesize($7); 5832*4882a593Smuzhiyun my $arg2 = $8; 5833*4882a593Smuzhiyun my $cast; 5834*4882a593Smuzhiyun 5835*4882a593Smuzhiyun if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) { 5836*4882a593Smuzhiyun $cast = "$cast1 or $cast2"; 5837*4882a593Smuzhiyun } elsif ($cast1 ne "") { 5838*4882a593Smuzhiyun $cast = $cast1; 5839*4882a593Smuzhiyun } else { 5840*4882a593Smuzhiyun $cast = $cast2; 5841*4882a593Smuzhiyun } 5842*4882a593Smuzhiyun WARN("MINMAX", 5843*4882a593Smuzhiyun "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n"); 5844*4882a593Smuzhiyun } 5845*4882a593Smuzhiyun } 5846*4882a593Smuzhiyun 5847*4882a593Smuzhiyun# check usleep_range arguments 5848*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5849*4882a593Smuzhiyun defined $stat && 5850*4882a593Smuzhiyun $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) { 5851*4882a593Smuzhiyun my $min = $1; 5852*4882a593Smuzhiyun my $max = $7; 5853*4882a593Smuzhiyun if ($min eq $max) { 5854*4882a593Smuzhiyun WARN("USLEEP_RANGE", 5855*4882a593Smuzhiyun "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); 5856*4882a593Smuzhiyun } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ && 5857*4882a593Smuzhiyun $min > $max) { 5858*4882a593Smuzhiyun WARN("USLEEP_RANGE", 5859*4882a593Smuzhiyun "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n"); 5860*4882a593Smuzhiyun } 5861*4882a593Smuzhiyun } 5862*4882a593Smuzhiyun 5863*4882a593Smuzhiyun# check for naked sscanf 5864*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5865*4882a593Smuzhiyun defined $stat && 5866*4882a593Smuzhiyun $line =~ /\bsscanf\b/ && 5867*4882a593Smuzhiyun ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ && 5868*4882a593Smuzhiyun $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ && 5869*4882a593Smuzhiyun $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) { 5870*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 5871*4882a593Smuzhiyun $lc = $lc + $linenr; 5872*4882a593Smuzhiyun my $stat_real = raw_line($linenr, 0); 5873*4882a593Smuzhiyun for (my $count = $linenr + 1; $count <= $lc; $count++) { 5874*4882a593Smuzhiyun $stat_real = $stat_real . "\n" . raw_line($count, 0); 5875*4882a593Smuzhiyun } 5876*4882a593Smuzhiyun WARN("NAKED_SSCANF", 5877*4882a593Smuzhiyun "unchecked sscanf return value\n" . "$here\n$stat_real\n"); 5878*4882a593Smuzhiyun } 5879*4882a593Smuzhiyun 5880*4882a593Smuzhiyun# check for simple sscanf that should be kstrto<foo> 5881*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5882*4882a593Smuzhiyun defined $stat && 5883*4882a593Smuzhiyun $line =~ /\bsscanf\b/) { 5884*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 5885*4882a593Smuzhiyun $lc = $lc + $linenr; 5886*4882a593Smuzhiyun my $stat_real = raw_line($linenr, 0); 5887*4882a593Smuzhiyun for (my $count = $linenr + 1; $count <= $lc; $count++) { 5888*4882a593Smuzhiyun $stat_real = $stat_real . "\n" . raw_line($count, 0); 5889*4882a593Smuzhiyun } 5890*4882a593Smuzhiyun if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) { 5891*4882a593Smuzhiyun my $format = $6; 5892*4882a593Smuzhiyun my $count = $format =~ tr@%@%@; 5893*4882a593Smuzhiyun if ($count == 1 && 5894*4882a593Smuzhiyun $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) { 5895*4882a593Smuzhiyun WARN("SSCANF_TO_KSTRTO", 5896*4882a593Smuzhiyun "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n"); 5897*4882a593Smuzhiyun } 5898*4882a593Smuzhiyun } 5899*4882a593Smuzhiyun } 5900*4882a593Smuzhiyun 5901*4882a593Smuzhiyun# check for new externs in .h files. 5902*4882a593Smuzhiyun if ($realfile =~ /\.h$/ && 5903*4882a593Smuzhiyun $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) { 5904*4882a593Smuzhiyun if (CHK("AVOID_EXTERNS", 5905*4882a593Smuzhiyun "extern prototypes should be avoided in .h files\n" . $herecurr) && 5906*4882a593Smuzhiyun $fix) { 5907*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/; 5908*4882a593Smuzhiyun } 5909*4882a593Smuzhiyun } 5910*4882a593Smuzhiyun 5911*4882a593Smuzhiyun# check for new externs in .c files. 5912*4882a593Smuzhiyun if ($realfile =~ /\.c$/ && defined $stat && 5913*4882a593Smuzhiyun $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s) 5914*4882a593Smuzhiyun { 5915*4882a593Smuzhiyun my $function_name = $1; 5916*4882a593Smuzhiyun my $paren_space = $2; 5917*4882a593Smuzhiyun 5918*4882a593Smuzhiyun my $s = $stat; 5919*4882a593Smuzhiyun if (defined $cond) { 5920*4882a593Smuzhiyun substr($s, 0, length($cond), ''); 5921*4882a593Smuzhiyun } 5922*4882a593Smuzhiyun if ($s =~ /^\s*;/ && 5923*4882a593Smuzhiyun $function_name ne 'uninitialized_var') 5924*4882a593Smuzhiyun { 5925*4882a593Smuzhiyun WARN("AVOID_EXTERNS", 5926*4882a593Smuzhiyun "externs should be avoided in .c files\n" . $herecurr); 5927*4882a593Smuzhiyun } 5928*4882a593Smuzhiyun 5929*4882a593Smuzhiyun if ($paren_space =~ /\n/) { 5930*4882a593Smuzhiyun WARN("FUNCTION_ARGUMENTS", 5931*4882a593Smuzhiyun "arguments for function declarations should follow identifier\n" . $herecurr); 5932*4882a593Smuzhiyun } 5933*4882a593Smuzhiyun 5934*4882a593Smuzhiyun } elsif ($realfile =~ /\.c$/ && defined $stat && 5935*4882a593Smuzhiyun $stat =~ /^.\s*extern\s+/) 5936*4882a593Smuzhiyun { 5937*4882a593Smuzhiyun WARN("AVOID_EXTERNS", 5938*4882a593Smuzhiyun "externs should be avoided in .c files\n" . $herecurr); 5939*4882a593Smuzhiyun } 5940*4882a593Smuzhiyun 5941*4882a593Smuzhiyun# check for function declarations that have arguments without identifier names 5942*4882a593Smuzhiyun if (defined $stat && 5943*4882a593Smuzhiyun $stat =~ /^.\s*(?:extern\s+)?$Type\s*$Ident\s*\(\s*([^{]+)\s*\)\s*;/s && 5944*4882a593Smuzhiyun $1 ne "void") { 5945*4882a593Smuzhiyun my $args = trim($1); 5946*4882a593Smuzhiyun while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) { 5947*4882a593Smuzhiyun my $arg = trim($1); 5948*4882a593Smuzhiyun if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) { 5949*4882a593Smuzhiyun WARN("FUNCTION_ARGUMENTS", 5950*4882a593Smuzhiyun "function definition argument '$arg' should also have an identifier name\n" . $herecurr); 5951*4882a593Smuzhiyun } 5952*4882a593Smuzhiyun } 5953*4882a593Smuzhiyun } 5954*4882a593Smuzhiyun 5955*4882a593Smuzhiyun# check for function definitions 5956*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5957*4882a593Smuzhiyun defined $stat && 5958*4882a593Smuzhiyun $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) { 5959*4882a593Smuzhiyun $context_function = $1; 5960*4882a593Smuzhiyun 5961*4882a593Smuzhiyun# check for multiline function definition with misplaced open brace 5962*4882a593Smuzhiyun my $ok = 0; 5963*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 5964*4882a593Smuzhiyun my $herectx = $here . "\n"; 5965*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 5966*4882a593Smuzhiyun my $rl = raw_line($linenr, $n); 5967*4882a593Smuzhiyun $herectx .= $rl . "\n"; 5968*4882a593Smuzhiyun $ok = 1 if ($rl =~ /^[ \+]\{/); 5969*4882a593Smuzhiyun $ok = 1 if ($rl =~ /\{/ && $n == 0); 5970*4882a593Smuzhiyun last if $rl =~ /^[ \+].*\{/; 5971*4882a593Smuzhiyun } 5972*4882a593Smuzhiyun if (!$ok) { 5973*4882a593Smuzhiyun ERROR("OPEN_BRACE", 5974*4882a593Smuzhiyun "open brace '{' following function definitions go on the next line\n" . $herectx); 5975*4882a593Smuzhiyun } 5976*4882a593Smuzhiyun } 5977*4882a593Smuzhiyun 5978*4882a593Smuzhiyun# checks for new __setup's 5979*4882a593Smuzhiyun if ($rawline =~ /\b__setup\("([^"]*)"/) { 5980*4882a593Smuzhiyun my $name = $1; 5981*4882a593Smuzhiyun 5982*4882a593Smuzhiyun if (!grep(/$name/, @setup_docs)) { 5983*4882a593Smuzhiyun CHK("UNDOCUMENTED_SETUP", 5984*4882a593Smuzhiyun "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.rst\n" . $herecurr); 5985*4882a593Smuzhiyun } 5986*4882a593Smuzhiyun } 5987*4882a593Smuzhiyun 5988*4882a593Smuzhiyun# check for pointless casting of kmalloc return 5989*4882a593Smuzhiyun if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) { 5990*4882a593Smuzhiyun WARN("UNNECESSARY_CASTS", 5991*4882a593Smuzhiyun "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr); 5992*4882a593Smuzhiyun } 5993*4882a593Smuzhiyun 5994*4882a593Smuzhiyun# alloc style 5995*4882a593Smuzhiyun# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...) 5996*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 5997*4882a593Smuzhiyun $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) { 5998*4882a593Smuzhiyun CHK("ALLOC_SIZEOF_STRUCT", 5999*4882a593Smuzhiyun "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); 6000*4882a593Smuzhiyun } 6001*4882a593Smuzhiyun 6002*4882a593Smuzhiyun# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc 6003*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 6004*4882a593Smuzhiyun defined $stat && 6005*4882a593Smuzhiyun $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { 6006*4882a593Smuzhiyun my $oldfunc = $3; 6007*4882a593Smuzhiyun my $a1 = $4; 6008*4882a593Smuzhiyun my $a2 = $10; 6009*4882a593Smuzhiyun my $newfunc = "kmalloc_array"; 6010*4882a593Smuzhiyun $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); 6011*4882a593Smuzhiyun my $r1 = $a1; 6012*4882a593Smuzhiyun my $r2 = $a2; 6013*4882a593Smuzhiyun if ($a1 =~ /^sizeof\s*\S/) { 6014*4882a593Smuzhiyun $r1 = $a2; 6015*4882a593Smuzhiyun $r2 = $a1; 6016*4882a593Smuzhiyun } 6017*4882a593Smuzhiyun if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ && 6018*4882a593Smuzhiyun !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) { 6019*4882a593Smuzhiyun my $ctx = ''; 6020*4882a593Smuzhiyun my $herectx = $here . "\n"; 6021*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 6022*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 6023*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 6024*4882a593Smuzhiyun } 6025*4882a593Smuzhiyun if (WARN("ALLOC_WITH_MULTIPLY", 6026*4882a593Smuzhiyun "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) && 6027*4882a593Smuzhiyun $cnt == 1 && 6028*4882a593Smuzhiyun $fix) { 6029*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; 6030*4882a593Smuzhiyun } 6031*4882a593Smuzhiyun } 6032*4882a593Smuzhiyun } 6033*4882a593Smuzhiyun 6034*4882a593Smuzhiyun# check for krealloc arg reuse 6035*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 6036*4882a593Smuzhiyun $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) { 6037*4882a593Smuzhiyun WARN("KREALLOC_ARG_REUSE", 6038*4882a593Smuzhiyun "Reusing the krealloc arg is almost always a bug\n" . $herecurr); 6039*4882a593Smuzhiyun } 6040*4882a593Smuzhiyun 6041*4882a593Smuzhiyun# check for alloc argument mismatch 6042*4882a593Smuzhiyun if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) { 6043*4882a593Smuzhiyun WARN("ALLOC_ARRAY_ARGS", 6044*4882a593Smuzhiyun "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr); 6045*4882a593Smuzhiyun } 6046*4882a593Smuzhiyun 6047*4882a593Smuzhiyun# check for multiple semicolons 6048*4882a593Smuzhiyun if ($line =~ /;\s*;\s*$/) { 6049*4882a593Smuzhiyun if (WARN("ONE_SEMICOLON", 6050*4882a593Smuzhiyun "Statements terminations use 1 semicolon\n" . $herecurr) && 6051*4882a593Smuzhiyun $fix) { 6052*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g; 6053*4882a593Smuzhiyun } 6054*4882a593Smuzhiyun } 6055*4882a593Smuzhiyun 6056*4882a593Smuzhiyun# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi 6057*4882a593Smuzhiyun if ($realfile !~ m@^include/uapi/@ && 6058*4882a593Smuzhiyun $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) { 6059*4882a593Smuzhiyun my $ull = ""; 6060*4882a593Smuzhiyun $ull = "_ULL" if (defined($1) && $1 =~ /ll/i); 6061*4882a593Smuzhiyun if (CHK("BIT_MACRO", 6062*4882a593Smuzhiyun "Prefer using the BIT$ull macro\n" . $herecurr) && 6063*4882a593Smuzhiyun $fix) { 6064*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/; 6065*4882a593Smuzhiyun } 6066*4882a593Smuzhiyun } 6067*4882a593Smuzhiyun 6068*4882a593Smuzhiyun# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE 6069*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*$/) { 6070*4882a593Smuzhiyun my $config = $1; 6071*4882a593Smuzhiyun if (WARN("PREFER_IS_ENABLED", 6072*4882a593Smuzhiyun "Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) && 6073*4882a593Smuzhiyun $fix) { 6074*4882a593Smuzhiyun $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)"; 6075*4882a593Smuzhiyun } 6076*4882a593Smuzhiyun } 6077*4882a593Smuzhiyun 6078*4882a593Smuzhiyun# check for case / default statements not preceded by break/fallthrough/switch 6079*4882a593Smuzhiyun if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) { 6080*4882a593Smuzhiyun my $has_break = 0; 6081*4882a593Smuzhiyun my $has_statement = 0; 6082*4882a593Smuzhiyun my $count = 0; 6083*4882a593Smuzhiyun my $prevline = $linenr; 6084*4882a593Smuzhiyun while ($prevline > 1 && ($file || $count < 3) && !$has_break) { 6085*4882a593Smuzhiyun $prevline--; 6086*4882a593Smuzhiyun my $rline = $rawlines[$prevline - 1]; 6087*4882a593Smuzhiyun my $fline = $lines[$prevline - 1]; 6088*4882a593Smuzhiyun last if ($fline =~ /^\@\@/); 6089*4882a593Smuzhiyun next if ($fline =~ /^\-/); 6090*4882a593Smuzhiyun next if ($fline =~ /^.(?:\s*(?:case\s+(?:$Ident|$Constant)[\s$;]*|default):[\s$;]*)*$/); 6091*4882a593Smuzhiyun $has_break = 1 if ($rline =~ /fall[\s_-]*(through|thru)/i); 6092*4882a593Smuzhiyun next if ($fline =~ /^.[\s$;]*$/); 6093*4882a593Smuzhiyun $has_statement = 1; 6094*4882a593Smuzhiyun $count++; 6095*4882a593Smuzhiyun $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/); 6096*4882a593Smuzhiyun } 6097*4882a593Smuzhiyun if (!$has_break && $has_statement) { 6098*4882a593Smuzhiyun WARN("MISSING_BREAK", 6099*4882a593Smuzhiyun "Possible switch case/default not preceded by break or fallthrough comment\n" . $herecurr); 6100*4882a593Smuzhiyun } 6101*4882a593Smuzhiyun } 6102*4882a593Smuzhiyun 6103*4882a593Smuzhiyun# check for switch/default statements without a break; 6104*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 6105*4882a593Smuzhiyun defined $stat && 6106*4882a593Smuzhiyun $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) { 6107*4882a593Smuzhiyun my $ctx = ''; 6108*4882a593Smuzhiyun my $herectx = $here . "\n"; 6109*4882a593Smuzhiyun my $cnt = statement_rawlines($stat); 6110*4882a593Smuzhiyun for (my $n = 0; $n < $cnt; $n++) { 6111*4882a593Smuzhiyun $herectx .= raw_line($linenr, $n) . "\n"; 6112*4882a593Smuzhiyun } 6113*4882a593Smuzhiyun WARN("DEFAULT_NO_BREAK", 6114*4882a593Smuzhiyun "switch default: should use break\n" . $herectx); 6115*4882a593Smuzhiyun } 6116*4882a593Smuzhiyun 6117*4882a593Smuzhiyun# check for gcc specific __FUNCTION__ 6118*4882a593Smuzhiyun if ($line =~ /\b__FUNCTION__\b/) { 6119*4882a593Smuzhiyun if (WARN("USE_FUNC", 6120*4882a593Smuzhiyun "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) && 6121*4882a593Smuzhiyun $fix) { 6122*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g; 6123*4882a593Smuzhiyun } 6124*4882a593Smuzhiyun } 6125*4882a593Smuzhiyun 6126*4882a593Smuzhiyun# check for uses of __DATE__, __TIME__, __TIMESTAMP__ 6127*4882a593Smuzhiyun while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) { 6128*4882a593Smuzhiyun ERROR("DATE_TIME", 6129*4882a593Smuzhiyun "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr); 6130*4882a593Smuzhiyun } 6131*4882a593Smuzhiyun 6132*4882a593Smuzhiyun# check for use of yield() 6133*4882a593Smuzhiyun if ($line =~ /\byield\s*\(\s*\)/) { 6134*4882a593Smuzhiyun WARN("YIELD", 6135*4882a593Smuzhiyun "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr); 6136*4882a593Smuzhiyun } 6137*4882a593Smuzhiyun 6138*4882a593Smuzhiyun# check for comparisons against true and false 6139*4882a593Smuzhiyun if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) { 6140*4882a593Smuzhiyun my $lead = $1; 6141*4882a593Smuzhiyun my $arg = $2; 6142*4882a593Smuzhiyun my $test = $3; 6143*4882a593Smuzhiyun my $otype = $4; 6144*4882a593Smuzhiyun my $trail = $5; 6145*4882a593Smuzhiyun my $op = "!"; 6146*4882a593Smuzhiyun 6147*4882a593Smuzhiyun ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i); 6148*4882a593Smuzhiyun 6149*4882a593Smuzhiyun my $type = lc($otype); 6150*4882a593Smuzhiyun if ($type =~ /^(?:true|false)$/) { 6151*4882a593Smuzhiyun if (("$test" eq "==" && "$type" eq "true") || 6152*4882a593Smuzhiyun ("$test" eq "!=" && "$type" eq "false")) { 6153*4882a593Smuzhiyun $op = ""; 6154*4882a593Smuzhiyun } 6155*4882a593Smuzhiyun 6156*4882a593Smuzhiyun CHK("BOOL_COMPARISON", 6157*4882a593Smuzhiyun "Using comparison to $otype is error prone\n" . $herecurr); 6158*4882a593Smuzhiyun 6159*4882a593Smuzhiyun## maybe suggesting a correct construct would better 6160*4882a593Smuzhiyun## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr); 6161*4882a593Smuzhiyun 6162*4882a593Smuzhiyun } 6163*4882a593Smuzhiyun } 6164*4882a593Smuzhiyun 6165*4882a593Smuzhiyun# check for semaphores initialized locked 6166*4882a593Smuzhiyun if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) { 6167*4882a593Smuzhiyun WARN("CONSIDER_COMPLETION", 6168*4882a593Smuzhiyun "consider using a completion\n" . $herecurr); 6169*4882a593Smuzhiyun } 6170*4882a593Smuzhiyun 6171*4882a593Smuzhiyun# recommend kstrto* over simple_strto* and strict_strto* 6172*4882a593Smuzhiyun if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) { 6173*4882a593Smuzhiyun WARN("CONSIDER_KSTRTO", 6174*4882a593Smuzhiyun "$1 is obsolete, use k$3 instead\n" . $herecurr); 6175*4882a593Smuzhiyun } 6176*4882a593Smuzhiyun 6177*4882a593Smuzhiyun# check for __initcall(), use device_initcall() explicitly or more appropriate function please 6178*4882a593Smuzhiyun if ($line =~ /^.\s*__initcall\s*\(/) { 6179*4882a593Smuzhiyun WARN("USE_DEVICE_INITCALL", 6180*4882a593Smuzhiyun "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr); 6181*4882a593Smuzhiyun } 6182*4882a593Smuzhiyun 6183*4882a593Smuzhiyun# check for various structs that are normally const (ops, kgdb, device_tree) 6184*4882a593Smuzhiyun# and avoid what seem like struct definitions 'struct foo {' 6185*4882a593Smuzhiyun if ($line !~ /\bconst\b/ && 6186*4882a593Smuzhiyun $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) { 6187*4882a593Smuzhiyun WARN("CONST_STRUCT", 6188*4882a593Smuzhiyun "struct $1 should normally be const\n" . $herecurr); 6189*4882a593Smuzhiyun } 6190*4882a593Smuzhiyun 6191*4882a593Smuzhiyun# use of NR_CPUS is usually wrong 6192*4882a593Smuzhiyun# ignore definitions of NR_CPUS and usage to define arrays as likely right 6193*4882a593Smuzhiyun if ($line =~ /\bNR_CPUS\b/ && 6194*4882a593Smuzhiyun $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ && 6195*4882a593Smuzhiyun $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ && 6196*4882a593Smuzhiyun $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ && 6197*4882a593Smuzhiyun $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ && 6198*4882a593Smuzhiyun $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/) 6199*4882a593Smuzhiyun { 6200*4882a593Smuzhiyun WARN("NR_CPUS", 6201*4882a593Smuzhiyun "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr); 6202*4882a593Smuzhiyun } 6203*4882a593Smuzhiyun 6204*4882a593Smuzhiyun# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong. 6205*4882a593Smuzhiyun if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) { 6206*4882a593Smuzhiyun ERROR("DEFINE_ARCH_HAS", 6207*4882a593Smuzhiyun "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr); 6208*4882a593Smuzhiyun } 6209*4882a593Smuzhiyun 6210*4882a593Smuzhiyun# likely/unlikely comparisons similar to "(likely(foo) > 0)" 6211*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 6212*4882a593Smuzhiyun $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) { 6213*4882a593Smuzhiyun WARN("LIKELY_MISUSE", 6214*4882a593Smuzhiyun "Using $1 should generally have parentheses around the comparison\n" . $herecurr); 6215*4882a593Smuzhiyun } 6216*4882a593Smuzhiyun 6217*4882a593Smuzhiyun# whine mightly about in_atomic 6218*4882a593Smuzhiyun if ($line =~ /\bin_atomic\s*\(/) { 6219*4882a593Smuzhiyun if ($realfile =~ m@^drivers/@) { 6220*4882a593Smuzhiyun ERROR("IN_ATOMIC", 6221*4882a593Smuzhiyun "do not use in_atomic in drivers\n" . $herecurr); 6222*4882a593Smuzhiyun } elsif ($realfile !~ m@^kernel/@) { 6223*4882a593Smuzhiyun WARN("IN_ATOMIC", 6224*4882a593Smuzhiyun "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr); 6225*4882a593Smuzhiyun } 6226*4882a593Smuzhiyun } 6227*4882a593Smuzhiyun 6228*4882a593Smuzhiyun# whine about ACCESS_ONCE 6229*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 6230*4882a593Smuzhiyun $line =~ /\bACCESS_ONCE\s*$balanced_parens\s*(=(?!=))?\s*($FuncArg)?/) { 6231*4882a593Smuzhiyun my $par = $1; 6232*4882a593Smuzhiyun my $eq = $2; 6233*4882a593Smuzhiyun my $fun = $3; 6234*4882a593Smuzhiyun $par =~ s/^\(\s*(.*)\s*\)$/$1/; 6235*4882a593Smuzhiyun if (defined($eq)) { 6236*4882a593Smuzhiyun if (WARN("PREFER_WRITE_ONCE", 6237*4882a593Smuzhiyun "Prefer WRITE_ONCE(<FOO>, <BAR>) over ACCESS_ONCE(<FOO>) = <BAR>\n" . $herecurr) && 6238*4882a593Smuzhiyun $fix) { 6239*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)\s*$eq\s*\Q$fun\E/WRITE_ONCE($par, $fun)/; 6240*4882a593Smuzhiyun } 6241*4882a593Smuzhiyun } else { 6242*4882a593Smuzhiyun if (WARN("PREFER_READ_ONCE", 6243*4882a593Smuzhiyun "Prefer READ_ONCE(<FOO>) over ACCESS_ONCE(<FOO>)\n" . $herecurr) && 6244*4882a593Smuzhiyun $fix) { 6245*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/\bACCESS_ONCE\s*\(\s*\Q$par\E\s*\)/READ_ONCE($par)/; 6246*4882a593Smuzhiyun } 6247*4882a593Smuzhiyun } 6248*4882a593Smuzhiyun } 6249*4882a593Smuzhiyun 6250*4882a593Smuzhiyun# check for mutex_trylock_recursive usage 6251*4882a593Smuzhiyun if ($line =~ /mutex_trylock_recursive/) { 6252*4882a593Smuzhiyun ERROR("LOCKING", 6253*4882a593Smuzhiyun "recursive locking is bad, do not use this ever.\n" . $herecurr); 6254*4882a593Smuzhiyun } 6255*4882a593Smuzhiyun 6256*4882a593Smuzhiyun# check for lockdep_set_novalidate_class 6257*4882a593Smuzhiyun if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ || 6258*4882a593Smuzhiyun $line =~ /__lockdep_no_validate__\s*\)/ ) { 6259*4882a593Smuzhiyun if ($realfile !~ m@^kernel/lockdep@ && 6260*4882a593Smuzhiyun $realfile !~ m@^include/linux/lockdep@ && 6261*4882a593Smuzhiyun $realfile !~ m@^drivers/base/core@) { 6262*4882a593Smuzhiyun ERROR("LOCKDEP", 6263*4882a593Smuzhiyun "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr); 6264*4882a593Smuzhiyun } 6265*4882a593Smuzhiyun } 6266*4882a593Smuzhiyun 6267*4882a593Smuzhiyun if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ || 6268*4882a593Smuzhiyun $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) { 6269*4882a593Smuzhiyun WARN("EXPORTED_WORLD_WRITABLE", 6270*4882a593Smuzhiyun "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); 6271*4882a593Smuzhiyun } 6272*4882a593Smuzhiyun 6273*4882a593Smuzhiyun# Mode permission misuses where it seems decimal should be octal 6274*4882a593Smuzhiyun# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop 6275*4882a593Smuzhiyun if ($^V && $^V ge 5.10.0 && 6276*4882a593Smuzhiyun defined $stat && 6277*4882a593Smuzhiyun $line =~ /$mode_perms_search/) { 6278*4882a593Smuzhiyun foreach my $entry (@mode_permission_funcs) { 6279*4882a593Smuzhiyun my $func = $entry->[0]; 6280*4882a593Smuzhiyun my $arg_pos = $entry->[1]; 6281*4882a593Smuzhiyun 6282*4882a593Smuzhiyun my $lc = $stat =~ tr@\n@@; 6283*4882a593Smuzhiyun $lc = $lc + $linenr; 6284*4882a593Smuzhiyun my $stat_real = raw_line($linenr, 0); 6285*4882a593Smuzhiyun for (my $count = $linenr + 1; $count <= $lc; $count++) { 6286*4882a593Smuzhiyun $stat_real = $stat_real . "\n" . raw_line($count, 0); 6287*4882a593Smuzhiyun } 6288*4882a593Smuzhiyun 6289*4882a593Smuzhiyun my $skip_args = ""; 6290*4882a593Smuzhiyun if ($arg_pos > 1) { 6291*4882a593Smuzhiyun $arg_pos--; 6292*4882a593Smuzhiyun $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; 6293*4882a593Smuzhiyun } 6294*4882a593Smuzhiyun my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]"; 6295*4882a593Smuzhiyun if ($stat =~ /$test/) { 6296*4882a593Smuzhiyun my $val = $1; 6297*4882a593Smuzhiyun $val = $6 if ($skip_args ne ""); 6298*4882a593Smuzhiyun if (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || 6299*4882a593Smuzhiyun ($val =~ /^$Octal$/ && length($val) ne 4)) { 6300*4882a593Smuzhiyun ERROR("NON_OCTAL_PERMISSIONS", 6301*4882a593Smuzhiyun "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real); 6302*4882a593Smuzhiyun } 6303*4882a593Smuzhiyun if ($val =~ /^$Octal$/ && (oct($val) & 02)) { 6304*4882a593Smuzhiyun ERROR("EXPORTED_WORLD_WRITABLE", 6305*4882a593Smuzhiyun "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real); 6306*4882a593Smuzhiyun } 6307*4882a593Smuzhiyun } 6308*4882a593Smuzhiyun } 6309*4882a593Smuzhiyun } 6310*4882a593Smuzhiyun 6311*4882a593Smuzhiyun# check for uses of S_<PERMS> that could be octal for readability 6312*4882a593Smuzhiyun if ($line =~ /\b$mode_perms_string_search\b/) { 6313*4882a593Smuzhiyun my $val = ""; 6314*4882a593Smuzhiyun my $oval = ""; 6315*4882a593Smuzhiyun my $to = 0; 6316*4882a593Smuzhiyun my $curpos = 0; 6317*4882a593Smuzhiyun my $lastpos = 0; 6318*4882a593Smuzhiyun while ($line =~ /\b(($mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) { 6319*4882a593Smuzhiyun $curpos = pos($line); 6320*4882a593Smuzhiyun my $match = $2; 6321*4882a593Smuzhiyun my $omatch = $1; 6322*4882a593Smuzhiyun last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos)); 6323*4882a593Smuzhiyun $lastpos = $curpos; 6324*4882a593Smuzhiyun $to |= $mode_permission_string_types{$match}; 6325*4882a593Smuzhiyun $val .= '\s*\|\s*' if ($val ne ""); 6326*4882a593Smuzhiyun $val .= $match; 6327*4882a593Smuzhiyun $oval .= $omatch; 6328*4882a593Smuzhiyun } 6329*4882a593Smuzhiyun $oval =~ s/^\s*\|\s*//; 6330*4882a593Smuzhiyun $oval =~ s/\s*\|\s*$//; 6331*4882a593Smuzhiyun my $octal = sprintf("%04o", $to); 6332*4882a593Smuzhiyun if (WARN("SYMBOLIC_PERMS", 6333*4882a593Smuzhiyun "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) && 6334*4882a593Smuzhiyun $fix) { 6335*4882a593Smuzhiyun $fixed[$fixlinenr] =~ s/$val/$octal/; 6336*4882a593Smuzhiyun } 6337*4882a593Smuzhiyun } 6338*4882a593Smuzhiyun 6339*4882a593Smuzhiyun# validate content of MODULE_LICENSE against list from include/linux/module.h 6340*4882a593Smuzhiyun if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { 6341*4882a593Smuzhiyun my $extracted_string = get_quoted_string($line, $rawline); 6342*4882a593Smuzhiyun my $valid_licenses = qr{ 6343*4882a593Smuzhiyun GPL| 6344*4882a593Smuzhiyun GPL\ v2| 6345*4882a593Smuzhiyun GPL\ and\ additional\ rights| 6346*4882a593Smuzhiyun Dual\ BSD/GPL| 6347*4882a593Smuzhiyun Dual\ MIT/GPL| 6348*4882a593Smuzhiyun Dual\ MPL/GPL| 6349*4882a593Smuzhiyun Proprietary 6350*4882a593Smuzhiyun }x; 6351*4882a593Smuzhiyun if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) { 6352*4882a593Smuzhiyun WARN("MODULE_LICENSE", 6353*4882a593Smuzhiyun "unknown module license " . $extracted_string . "\n" . $herecurr); 6354*4882a593Smuzhiyun } 6355*4882a593Smuzhiyun } 6356*4882a593Smuzhiyun } 6357*4882a593Smuzhiyun 6358*4882a593Smuzhiyun # If we have no input at all, then there is nothing to report on 6359*4882a593Smuzhiyun # so just keep quiet. 6360*4882a593Smuzhiyun if ($#rawlines == -1) { 6361*4882a593Smuzhiyun exit(0); 6362*4882a593Smuzhiyun } 6363*4882a593Smuzhiyun 6364*4882a593Smuzhiyun # In mailback mode only produce a report in the negative, for 6365*4882a593Smuzhiyun # things that appear to be patches. 6366*4882a593Smuzhiyun if ($mailback && ($clean == 1 || !$is_patch)) { 6367*4882a593Smuzhiyun exit(0); 6368*4882a593Smuzhiyun } 6369*4882a593Smuzhiyun 6370*4882a593Smuzhiyun # This is not a patch, and we are are in 'no-patch' mode so 6371*4882a593Smuzhiyun # just keep quiet. 6372*4882a593Smuzhiyun if (!$chk_patch && !$is_patch) { 6373*4882a593Smuzhiyun exit(0); 6374*4882a593Smuzhiyun } 6375*4882a593Smuzhiyun 6376*4882a593Smuzhiyun if (!$is_patch && $file !~ /cover-letter\.patch$/) { 6377*4882a593Smuzhiyun ERROR("NOT_UNIFIED_DIFF", 6378*4882a593Smuzhiyun "Does not appear to be a unified-diff format patch\n"); 6379*4882a593Smuzhiyun } 6380*4882a593Smuzhiyun if ($is_patch && $has_commit_log && $chk_signoff && $signoff == 0) { 6381*4882a593Smuzhiyun ERROR("MISSING_SIGN_OFF", 6382*4882a593Smuzhiyun "Missing Signed-off-by: line(s)\n"); 6383*4882a593Smuzhiyun } 6384*4882a593Smuzhiyun 6385*4882a593Smuzhiyun print report_dump(); 6386*4882a593Smuzhiyun if ($summary && !($clean == 1 && $quiet == 1)) { 6387*4882a593Smuzhiyun print "$filename " if ($summary_file); 6388*4882a593Smuzhiyun print "total: $cnt_error errors, $cnt_warn warnings, " . 6389*4882a593Smuzhiyun (($check)? "$cnt_chk checks, " : "") . 6390*4882a593Smuzhiyun "$cnt_lines lines checked\n"; 6391*4882a593Smuzhiyun } 6392*4882a593Smuzhiyun 6393*4882a593Smuzhiyun if ($quiet == 0) { 6394*4882a593Smuzhiyun # If there were any defects found and not already fixing them 6395*4882a593Smuzhiyun if (!$clean and !$fix) { 6396*4882a593Smuzhiyun print << "EOM" 6397*4882a593Smuzhiyun 6398*4882a593SmuzhiyunNOTE: For some of the reported defects, checkpatch may be able to 6399*4882a593Smuzhiyun mechanically convert to the typical style using --fix or --fix-inplace. 6400*4882a593SmuzhiyunEOM 6401*4882a593Smuzhiyun } 6402*4882a593Smuzhiyun # If there were whitespace errors which cleanpatch can fix 6403*4882a593Smuzhiyun # then suggest that. 6404*4882a593Smuzhiyun if ($rpt_cleaners) { 6405*4882a593Smuzhiyun $rpt_cleaners = 0; 6406*4882a593Smuzhiyun print << "EOM" 6407*4882a593Smuzhiyun 6408*4882a593SmuzhiyunNOTE: Whitespace errors detected. 6409*4882a593Smuzhiyun You may wish to use scripts/cleanpatch or scripts/cleanfile 6410*4882a593SmuzhiyunEOM 6411*4882a593Smuzhiyun } 6412*4882a593Smuzhiyun } 6413*4882a593Smuzhiyun 6414*4882a593Smuzhiyun if ($clean == 0 && $fix && 6415*4882a593Smuzhiyun ("@rawlines" ne "@fixed" || 6416*4882a593Smuzhiyun $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) { 6417*4882a593Smuzhiyun my $newfile = $filename; 6418*4882a593Smuzhiyun $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace); 6419*4882a593Smuzhiyun my $linecount = 0; 6420*4882a593Smuzhiyun my $f; 6421*4882a593Smuzhiyun 6422*4882a593Smuzhiyun @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted); 6423*4882a593Smuzhiyun 6424*4882a593Smuzhiyun open($f, '>', $newfile) 6425*4882a593Smuzhiyun or die "$P: Can't open $newfile for write\n"; 6426*4882a593Smuzhiyun foreach my $fixed_line (@fixed) { 6427*4882a593Smuzhiyun $linecount++; 6428*4882a593Smuzhiyun if ($file) { 6429*4882a593Smuzhiyun if ($linecount > 3) { 6430*4882a593Smuzhiyun $fixed_line =~ s/^\+//; 6431*4882a593Smuzhiyun print $f $fixed_line . "\n"; 6432*4882a593Smuzhiyun } 6433*4882a593Smuzhiyun } else { 6434*4882a593Smuzhiyun print $f $fixed_line . "\n"; 6435*4882a593Smuzhiyun } 6436*4882a593Smuzhiyun } 6437*4882a593Smuzhiyun close($f); 6438*4882a593Smuzhiyun 6439*4882a593Smuzhiyun if (!$quiet) { 6440*4882a593Smuzhiyun print << "EOM"; 6441*4882a593Smuzhiyun 6442*4882a593SmuzhiyunWrote EXPERIMENTAL --fix correction(s) to '$newfile' 6443*4882a593Smuzhiyun 6444*4882a593SmuzhiyunDo _NOT_ trust the results written to this file. 6445*4882a593SmuzhiyunDo _NOT_ submit these changes without inspecting them for correctness. 6446*4882a593Smuzhiyun 6447*4882a593SmuzhiyunThis EXPERIMENTAL file is simply a convenience to help rewrite patches. 6448*4882a593SmuzhiyunNo warranties, expressed or implied... 6449*4882a593SmuzhiyunEOM 6450*4882a593Smuzhiyun } 6451*4882a593Smuzhiyun } 6452*4882a593Smuzhiyun 6453*4882a593Smuzhiyun if ($quiet == 0) { 6454*4882a593Smuzhiyun print "\n"; 6455*4882a593Smuzhiyun if ($clean == 1) { 6456*4882a593Smuzhiyun print "$vname has no obvious style problems and is ready for submission.\n"; 6457*4882a593Smuzhiyun } else { 6458*4882a593Smuzhiyun print "$vname has style problems, please review.\n"; 6459*4882a593Smuzhiyun } 6460*4882a593Smuzhiyun } 6461*4882a593Smuzhiyun return $clean; 6462*4882a593Smuzhiyun} 6463