xref: /linux-6.15/scripts/checkpatch.pl (revision 86cffecd)
1cb77f0d6SKamil Rytarowski#!/usr/bin/env perl
2882ea1d6SJoe Perches# SPDX-License-Identifier: GPL-2.0
3882ea1d6SJoe Perches#
4dbf004d7SDave Jones# (c) 2001, Dave Jones. (the file handling bit)
500df344fSAndy Whitcroft# (c) 2005, Joel Schopp <[email protected]> (the ugly bit)
62a5a2c25SAndy Whitcroft# (c) 2007,2008, Andy Whitcroft <[email protected]> (new conditions, test suite)
7015830beSAndy Whitcroft# (c) 2008-2010 Andy Whitcroft <[email protected]>
8882ea1d6SJoe Perches# (c) 2010-2018 Joe Perches <[email protected]>
90a920b5bSAndy Whitcroft
100a920b5bSAndy Whitcroftuse strict;
11cb77f0d6SKamil Rytarowskiuse warnings;
12c707a81dSJoe Perchesuse POSIX;
1336061e38SJoe Perchesuse File::Basename;
1436061e38SJoe Perchesuse Cwd 'abs_path';
1557230297SJoe Perchesuse Term::ANSIColor qw(:constants);
16cd261496SGeert Uytterhoevenuse Encode qw(decode encode);
170a920b5bSAndy Whitcroft
180a920b5bSAndy Whitcroftmy $P = $0;
1936061e38SJoe Perchesmy $D = dirname(abs_path($P));
200a920b5bSAndy Whitcroft
21000d1cc1SJoe Perchesmy $V = '0.32';
220a920b5bSAndy Whitcroft
230a920b5bSAndy Whitcroftuse Getopt::Long qw(:config no_auto_abbrev);
240a920b5bSAndy Whitcroft
250a920b5bSAndy Whitcroftmy $quiet = 0;
2652178ce0SDwaipayan Raymy $verbose = 0;
2752178ce0SDwaipayan Raymy %verbose_messages = ();
2852178ce0SDwaipayan Raymy %verbose_emitted = ();
290a920b5bSAndy Whitcroftmy $tree = 1;
300a920b5bSAndy Whitcroftmy $chk_signoff = 1;
310a920b5bSAndy Whitcroftmy $chk_patch = 1;
32773647a0SAndy Whitcroftmy $tst_only;
336c72ffaaSAndy Whitcroftmy $emacs = 0;
348905a67cSAndy Whitcroftmy $terse = 0;
3534d8815fSJoe Perchesmy $showfile = 0;
366c72ffaaSAndy Whitcroftmy $file = 0;
374a593c34SDu, Changbinmy $git = 0;
380dea9f1eSJoe Perchesmy %git_commits = ();
396c72ffaaSAndy Whitcroftmy $check = 0;
402ac73b4fSJoe Perchesmy $check_orig = 0;
418905a67cSAndy Whitcroftmy $summary = 1;
428905a67cSAndy Whitcroftmy $mailback = 0;
4313214adfSAndy Whitcroftmy $summary_file = 0;
44000d1cc1SJoe Perchesmy $show_types = 0;
453beb42ecSJoe Perchesmy $list_types = 0;
463705ce5bSJoe Perchesmy $fix = 0;
479624b8d6SJoe Perchesmy $fix_inplace = 0;
486c72ffaaSAndy Whitcroftmy $root;
490f7f635bSJoe Perchesmy $gitroot = $ENV{'GIT_DIR'};
500f7f635bSJoe Perches$gitroot = ".git" if !defined($gitroot);
51c2fdda0dSAndy Whitcroftmy %debug;
523445686aSJoe Perchesmy %camelcase = ();
5391bfe484SJoe Perchesmy %use_type = ();
5491bfe484SJoe Perchesmy @use = ();
5591bfe484SJoe Perchesmy %ignore_type = ();
56000d1cc1SJoe Perchesmy @ignore = ();
5777f5b10aSHannes Edermy $help = 0;
58000d1cc1SJoe Perchesmy $configuration_file = ".checkpatch.conf";
59bdc48fa1SJoe Perchesmy $max_line_length = 100;
60d62a201fSDave Hansenmy $ignore_perl_version = 0;
61d62a201fSDave Hansenmy $minimum_perl_version = 5.10.0;
6256193274SVadim Bendeburymy $min_conf_desc_length = 4;
6366b47b4aSKees Cookmy $spelling_file = "$D/spelling.txt";
64ebfd7d62SJoe Perchesmy $codespell = 0;
65f1a63678SMaxim Uvarovmy $codespellfile = "/usr/share/codespell/dictionary.txt";
66bf1fa1daSJoe Perchesmy $conststructsfile = "$D/const_structs.checkpatch";
6752178ce0SDwaipayan Raymy $docsfile = "$D/../Documentation/dev-tools/checkpatch.rst";
68ced69da1SQuentin Monnetmy $typedefsfile;
69737c0767SJohn Brooksmy $color = "auto";
7098005e8cSVadim Bendeburymy $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
71dbbf869dSJoe Perches# git output parsing needs US English output, so first set backtick child process LANGUAGE
72dbbf869dSJoe Perchesmy $git_command ='export LANGUAGE=en_US.UTF-8; git';
73713a09deSAntonio Borneomy $tabsize = 8;
743e89ad85SJerome Forissiermy ${CONFIG_} = "CONFIG_";
7577f5b10aSHannes Eder
7677f5b10aSHannes Edersub help {
7777f5b10aSHannes Eder	my ($exitcode) = @_;
7877f5b10aSHannes Eder
7977f5b10aSHannes Eder	print << "EOM";
8077f5b10aSHannes EderUsage: $P [OPTION]... [FILE]...
8177f5b10aSHannes EderVersion: $V
8277f5b10aSHannes Eder
8377f5b10aSHannes EderOptions:
8477f5b10aSHannes Eder  -q, --quiet                quiet
8552178ce0SDwaipayan Ray  -v, --verbose              verbose mode
8677f5b10aSHannes Eder  --no-tree                  run without a kernel tree
8777f5b10aSHannes Eder  --no-signoff               do not check for 'Signed-off-by' line
8877f5b10aSHannes Eder  --patch                    treat FILE as patchfile (default)
8977f5b10aSHannes Eder  --emacs                    emacs compile window format
9077f5b10aSHannes Eder  --terse                    one line per report
9134d8815fSJoe Perches  --showfile                 emit diffed file position, not input file position
924a593c34SDu, Changbin  -g, --git                  treat FILE as a single commit or git revision range
934a593c34SDu, Changbin                             single git commit with:
944a593c34SDu, Changbin                               <rev>
954a593c34SDu, Changbin                               <rev>^
964a593c34SDu, Changbin                               <rev>~n
974a593c34SDu, Changbin                             multiple git commits with:
984a593c34SDu, Changbin                               <rev1>..<rev2>
994a593c34SDu, Changbin                               <rev1>...<rev2>
1004a593c34SDu, Changbin                               <rev>-<count>
1014a593c34SDu, Changbin                             git merges are ignored
10277f5b10aSHannes Eder  -f, --file                 treat FILE as regular source file
10377f5b10aSHannes Eder  --subjective, --strict     enable more subjective tests
1043beb42ecSJoe Perches  --list-types               list the possible message types
10591bfe484SJoe Perches  --types TYPE(,TYPE2...)    show only these comma separated message types
106000d1cc1SJoe Perches  --ignore TYPE(,TYPE2...)   ignore various comma separated message types
1073beb42ecSJoe Perches  --show-types               show the specific message type in the output
108bdc48fa1SJoe Perches  --max-line-length=n        set the maximum line length, (default $max_line_length)
109bdc48fa1SJoe Perches                             if exceeded, warn on patches
110bdc48fa1SJoe Perches                             requires --strict for use with --file
11156193274SVadim Bendebury  --min-conf-desc-length=n   set the min description length, if shorter, warn
112bdc48fa1SJoe Perches  --tab-size=n               set the number of spaces for tab (default $tabsize)
11377f5b10aSHannes Eder  --root=PATH                PATH to the kernel tree root
11477f5b10aSHannes Eder  --no-summary               suppress the per-file summary
11577f5b10aSHannes Eder  --mailback                 only produce a report in case of warnings/errors
11677f5b10aSHannes Eder  --summary-file             include the filename in summary
11777f5b10aSHannes Eder  --debug KEY=[0|1]          turn on/off debugging of KEY, where KEY is one of
11877f5b10aSHannes Eder                             'values', 'possible', 'type', and 'attr' (default
11977f5b10aSHannes Eder                             is all off)
12077f5b10aSHannes Eder  --test-only=WORD           report only warnings/errors containing WORD
12177f5b10aSHannes Eder                             literally
1223705ce5bSJoe Perches  --fix                      EXPERIMENTAL - may create horrible results
1233705ce5bSJoe Perches                             If correctable single-line errors exist, create
1243705ce5bSJoe Perches                             "<inputfile>.EXPERIMENTAL-checkpatch-fixes"
1253705ce5bSJoe Perches                             with potential errors corrected to the preferred
1263705ce5bSJoe Perches                             checkpatch style
1279624b8d6SJoe Perches  --fix-inplace              EXPERIMENTAL - may create horrible results
1289624b8d6SJoe Perches                             Is the same as --fix, but overwrites the input
1299624b8d6SJoe Perches                             file.  It's your fault if there's no backup or git
130d62a201fSDave Hansen  --ignore-perl-version      override checking of perl version.  expect
131d62a201fSDave Hansen                             runtime errors.
132ebfd7d62SJoe Perches  --codespell                Use the codespell dictionary for spelling/typos
133f1a63678SMaxim Uvarov                             (default:/usr/share/codespell/dictionary.txt)
134ebfd7d62SJoe Perches  --codespellfile            Use this codespell dictionary
13575ad8c57SJerome Forissier  --typedefsfile             Read additional types from this file
136737c0767SJohn Brooks  --color[=WHEN]             Use colors 'always', 'never', or only when output
137737c0767SJohn Brooks                             is a terminal ('auto'). Default is 'auto'.
1383e89ad85SJerome Forissier  --kconfig-prefix=WORD      use WORD as a prefix for Kconfig symbols (default
1393e89ad85SJerome Forissier                             ${CONFIG_})
14077f5b10aSHannes Eder  -h, --help, --version      display this help and exit
14177f5b10aSHannes Eder
14277f5b10aSHannes EderWhen FILE is - read standard input.
14377f5b10aSHannes EderEOM
14477f5b10aSHannes Eder
14577f5b10aSHannes Eder	exit($exitcode);
14677f5b10aSHannes Eder}
14777f5b10aSHannes Eder
1483beb42ecSJoe Perchessub uniq {
1493beb42ecSJoe Perches	my %seen;
1503beb42ecSJoe Perches	return grep { !$seen{$_}++ } @_;
1513beb42ecSJoe Perches}
1523beb42ecSJoe Perches
1533beb42ecSJoe Perchessub list_types {
1543beb42ecSJoe Perches	my ($exitcode) = @_;
1553beb42ecSJoe Perches
1563beb42ecSJoe Perches	my $count = 0;
1573beb42ecSJoe Perches
1583beb42ecSJoe Perches	local $/ = undef;
1593beb42ecSJoe Perches
1603beb42ecSJoe Perches	open(my $script, '<', abs_path($P)) or
1613beb42ecSJoe Perches	    die "$P: Can't read '$P' $!\n";
1623beb42ecSJoe Perches
1633beb42ecSJoe Perches	my $text = <$script>;
1643beb42ecSJoe Perches	close($script);
1653beb42ecSJoe Perches
16652178ce0SDwaipayan Ray	my %types = ();
1670547fa58SJean Delvare	# Also catch when type or level is passed through a variable
16852178ce0SDwaipayan Ray	while ($text =~ /(?:(\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
16952178ce0SDwaipayan Ray		if (defined($1)) {
17052178ce0SDwaipayan Ray			if (exists($types{$2})) {
17152178ce0SDwaipayan Ray				$types{$2} .= ",$1" if ($types{$2} ne $1);
17252178ce0SDwaipayan Ray			} else {
17352178ce0SDwaipayan Ray				$types{$2} = $1;
1743beb42ecSJoe Perches			}
17552178ce0SDwaipayan Ray		} else {
17652178ce0SDwaipayan Ray			$types{$2} = "UNDETERMINED";
17752178ce0SDwaipayan Ray		}
17852178ce0SDwaipayan Ray	}
17952178ce0SDwaipayan Ray
1803beb42ecSJoe Perches	print("#\tMessage type\n\n");
18152178ce0SDwaipayan Ray	if ($color) {
18252178ce0SDwaipayan Ray		print(" ( Color coding: ");
18352178ce0SDwaipayan Ray		print(RED . "ERROR" . RESET);
18452178ce0SDwaipayan Ray		print(" | ");
18552178ce0SDwaipayan Ray		print(YELLOW . "WARNING" . RESET);
18652178ce0SDwaipayan Ray		print(" | ");
18752178ce0SDwaipayan Ray		print(GREEN . "CHECK" . RESET);
18852178ce0SDwaipayan Ray		print(" | ");
18952178ce0SDwaipayan Ray		print("Multiple levels / Undetermined");
19052178ce0SDwaipayan Ray		print(" )\n\n");
19152178ce0SDwaipayan Ray	}
19252178ce0SDwaipayan Ray
19352178ce0SDwaipayan Ray	foreach my $type (sort keys %types) {
19452178ce0SDwaipayan Ray		my $orig_type = $type;
19552178ce0SDwaipayan Ray		if ($color) {
19652178ce0SDwaipayan Ray			my $level = $types{$type};
19752178ce0SDwaipayan Ray			if ($level eq "ERROR") {
19852178ce0SDwaipayan Ray				$type = RED . $type . RESET;
19952178ce0SDwaipayan Ray			} elsif ($level eq "WARN") {
20052178ce0SDwaipayan Ray				$type = YELLOW . $type . RESET;
20152178ce0SDwaipayan Ray			} elsif ($level eq "CHK") {
20252178ce0SDwaipayan Ray				$type = GREEN . $type . RESET;
20352178ce0SDwaipayan Ray			}
20452178ce0SDwaipayan Ray		}
2053beb42ecSJoe Perches		print(++$count . "\t" . $type . "\n");
20652178ce0SDwaipayan Ray		if ($verbose && exists($verbose_messages{$orig_type})) {
20752178ce0SDwaipayan Ray			my $message = $verbose_messages{$orig_type};
20852178ce0SDwaipayan Ray			$message =~ s/\n/\n\t/g;
20952178ce0SDwaipayan Ray			print("\t" . $message . "\n\n");
21052178ce0SDwaipayan Ray		}
2113beb42ecSJoe Perches	}
2123beb42ecSJoe Perches
2133beb42ecSJoe Perches	exit($exitcode);
2143beb42ecSJoe Perches}
2153beb42ecSJoe Perches
216000d1cc1SJoe Perchesmy $conf = which_conf($configuration_file);
217000d1cc1SJoe Perchesif (-f $conf) {
218000d1cc1SJoe Perches	my @conf_args;
219000d1cc1SJoe Perches	open(my $conffile, '<', "$conf")
220000d1cc1SJoe Perches	    or warn "$P: Can't find a readable $configuration_file file $!\n";
221000d1cc1SJoe Perches
222000d1cc1SJoe Perches	while (<$conffile>) {
223000d1cc1SJoe Perches		my $line = $_;
224000d1cc1SJoe Perches
225000d1cc1SJoe Perches		$line =~ s/\s*\n?$//g;
226000d1cc1SJoe Perches		$line =~ s/^\s*//g;
227000d1cc1SJoe Perches		$line =~ s/\s+/ /g;
228000d1cc1SJoe Perches
229000d1cc1SJoe Perches		next if ($line =~ m/^\s*#/);
230000d1cc1SJoe Perches		next if ($line =~ m/^\s*$/);
231000d1cc1SJoe Perches
232000d1cc1SJoe Perches		my @words = split(" ", $line);
233000d1cc1SJoe Perches		foreach my $word (@words) {
234000d1cc1SJoe Perches			last if ($word =~ m/^#/);
235000d1cc1SJoe Perches			push (@conf_args, $word);
236000d1cc1SJoe Perches		}
237000d1cc1SJoe Perches	}
238000d1cc1SJoe Perches	close($conffile);
239000d1cc1SJoe Perches	unshift(@ARGV, @conf_args) if @conf_args;
240000d1cc1SJoe Perches}
241000d1cc1SJoe Perches
24252178ce0SDwaipayan Raysub load_docs {
24352178ce0SDwaipayan Ray	open(my $docs, '<', "$docsfile")
24452178ce0SDwaipayan Ray	    or warn "$P: Can't read the documentation file $docsfile $!\n";
24552178ce0SDwaipayan Ray
24652178ce0SDwaipayan Ray	my $type = '';
24752178ce0SDwaipayan Ray	my $desc = '';
24852178ce0SDwaipayan Ray	my $in_desc = 0;
24952178ce0SDwaipayan Ray
25052178ce0SDwaipayan Ray	while (<$docs>) {
25152178ce0SDwaipayan Ray		chomp;
25252178ce0SDwaipayan Ray		my $line = $_;
25352178ce0SDwaipayan Ray		$line =~ s/\s+$//;
25452178ce0SDwaipayan Ray
25552178ce0SDwaipayan Ray		if ($line =~ /^\s*\*\*(.+)\*\*$/) {
25652178ce0SDwaipayan Ray			if ($desc ne '') {
25752178ce0SDwaipayan Ray				$verbose_messages{$type} = trim($desc);
25852178ce0SDwaipayan Ray			}
25952178ce0SDwaipayan Ray			$type = $1;
26052178ce0SDwaipayan Ray			$desc = '';
26152178ce0SDwaipayan Ray			$in_desc = 1;
26252178ce0SDwaipayan Ray		} elsif ($in_desc) {
26352178ce0SDwaipayan Ray			if ($line =~ /^(?:\s{4,}|$)/) {
26452178ce0SDwaipayan Ray				$line =~ s/^\s{4}//;
26552178ce0SDwaipayan Ray				$desc .= $line;
26652178ce0SDwaipayan Ray				$desc .= "\n";
26752178ce0SDwaipayan Ray			} else {
26852178ce0SDwaipayan Ray				$verbose_messages{$type} = trim($desc);
26952178ce0SDwaipayan Ray				$type = '';
27052178ce0SDwaipayan Ray				$desc = '';
27152178ce0SDwaipayan Ray				$in_desc = 0;
27252178ce0SDwaipayan Ray			}
27352178ce0SDwaipayan Ray		}
27452178ce0SDwaipayan Ray	}
27552178ce0SDwaipayan Ray
27652178ce0SDwaipayan Ray	if ($desc ne '') {
27752178ce0SDwaipayan Ray		$verbose_messages{$type} = trim($desc);
27852178ce0SDwaipayan Ray	}
27952178ce0SDwaipayan Ray	close($docs);
28052178ce0SDwaipayan Ray}
28152178ce0SDwaipayan Ray
282737c0767SJohn Brooks# Perl's Getopt::Long allows options to take optional arguments after a space.
283737c0767SJohn Brooks# Prevent --color by itself from consuming other arguments
284737c0767SJohn Brooksforeach (@ARGV) {
285737c0767SJohn Brooks	if ($_ eq "--color" || $_ eq "-color") {
286737c0767SJohn Brooks		$_ = "--color=$color";
287737c0767SJohn Brooks	}
288737c0767SJohn Brooks}
289737c0767SJohn Brooks
2900a920b5bSAndy WhitcroftGetOptions(
2916c72ffaaSAndy Whitcroft	'q|quiet+'	=> \$quiet,
29252178ce0SDwaipayan Ray	'v|verbose!'	=> \$verbose,
2930a920b5bSAndy Whitcroft	'tree!'		=> \$tree,
2940a920b5bSAndy Whitcroft	'signoff!'	=> \$chk_signoff,
2950a920b5bSAndy Whitcroft	'patch!'	=> \$chk_patch,
2966c72ffaaSAndy Whitcroft	'emacs!'	=> \$emacs,
2978905a67cSAndy Whitcroft	'terse!'	=> \$terse,
29834d8815fSJoe Perches	'showfile!'	=> \$showfile,
29977f5b10aSHannes Eder	'f|file!'	=> \$file,
3004a593c34SDu, Changbin	'g|git!'	=> \$git,
3016c72ffaaSAndy Whitcroft	'subjective!'	=> \$check,
3026c72ffaaSAndy Whitcroft	'strict!'	=> \$check,
303000d1cc1SJoe Perches	'ignore=s'	=> \@ignore,
30491bfe484SJoe Perches	'types=s'	=> \@use,
305000d1cc1SJoe Perches	'show-types!'	=> \$show_types,
3063beb42ecSJoe Perches	'list-types!'	=> \$list_types,
3076cd7f386SJoe Perches	'max-line-length=i' => \$max_line_length,
30856193274SVadim Bendebury	'min-conf-desc-length=i' => \$min_conf_desc_length,
309713a09deSAntonio Borneo	'tab-size=i'	=> \$tabsize,
3106c72ffaaSAndy Whitcroft	'root=s'	=> \$root,
3118905a67cSAndy Whitcroft	'summary!'	=> \$summary,
3128905a67cSAndy Whitcroft	'mailback!'	=> \$mailback,
31313214adfSAndy Whitcroft	'summary-file!'	=> \$summary_file,
3143705ce5bSJoe Perches	'fix!'		=> \$fix,
3159624b8d6SJoe Perches	'fix-inplace!'	=> \$fix_inplace,
316d62a201fSDave Hansen	'ignore-perl-version!' => \$ignore_perl_version,
317c2fdda0dSAndy Whitcroft	'debug=s'	=> \%debug,
318773647a0SAndy Whitcroft	'test-only=s'	=> \$tst_only,
319ebfd7d62SJoe Perches	'codespell!'	=> \$codespell,
320ebfd7d62SJoe Perches	'codespellfile=s'	=> \$codespellfile,
32175ad8c57SJerome Forissier	'typedefsfile=s'	=> \$typedefsfile,
322737c0767SJohn Brooks	'color=s'	=> \$color,
323737c0767SJohn Brooks	'no-color'	=> \$color,	#keep old behaviors of -nocolor
324737c0767SJohn Brooks	'nocolor'	=> \$color,	#keep old behaviors of -nocolor
3253e89ad85SJerome Forissier	'kconfig-prefix=s'	=> \${CONFIG_},
32677f5b10aSHannes Eder	'h|help'	=> \$help,
32777f5b10aSHannes Eder	'version'	=> \$help
32877f5b10aSHannes Eder) or help(1);
32977f5b10aSHannes Eder
33077f5b10aSHannes Ederhelp(0) if ($help);
3310a920b5bSAndy Whitcroft
33252178ce0SDwaipayan Raydie "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
33352178ce0SDwaipayan Raydie "$P: --verbose cannot be used with --terse\n" if ($verbose && $terse);
33452178ce0SDwaipayan Ray
33552178ce0SDwaipayan Rayif ($color =~ /^[01]$/) {
33652178ce0SDwaipayan Ray	$color = !$color;
33752178ce0SDwaipayan Ray} elsif ($color =~ /^always$/i) {
33852178ce0SDwaipayan Ray	$color = 1;
33952178ce0SDwaipayan Ray} elsif ($color =~ /^never$/i) {
34052178ce0SDwaipayan Ray	$color = 0;
34152178ce0SDwaipayan Ray} elsif ($color =~ /^auto$/i) {
34252178ce0SDwaipayan Ray	$color = (-t STDOUT);
34352178ce0SDwaipayan Ray} else {
34452178ce0SDwaipayan Ray	die "$P: Invalid color mode: $color\n";
34552178ce0SDwaipayan Ray}
34652178ce0SDwaipayan Ray
34752178ce0SDwaipayan Rayload_docs() if ($verbose);
3483beb42ecSJoe Percheslist_types(0) if ($list_types);
3493beb42ecSJoe Perches
3509624b8d6SJoe Perches$fix = 1 if ($fix_inplace);
3512ac73b4fSJoe Perches$check_orig = $check;
3529624b8d6SJoe Perches
3530a920b5bSAndy Whitcroftmy $exit = 0;
3540a920b5bSAndy Whitcroft
3555b57980dSJoe Perchesmy $perl_version_ok = 1;
356d62a201fSDave Hansenif ($^V && $^V lt $minimum_perl_version) {
3575b57980dSJoe Perches	$perl_version_ok = 0;
358d62a201fSDave Hansen	printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
3595b57980dSJoe Perches	exit(1) if (!$ignore_perl_version);
360d62a201fSDave Hansen}
361d62a201fSDave Hansen
36245107ff6SAllen Hubbe#if no filenames are given, push '-' to read patch from stdin
3630a920b5bSAndy Whitcroftif ($#ARGV < 0) {
36445107ff6SAllen Hubbe	push(@ARGV, '-');
3650a920b5bSAndy Whitcroft}
3660a920b5bSAndy Whitcroft
367713a09deSAntonio Borneo# skip TAB size 1 to avoid additional checks on $tabsize - 1
36832f30ca9SJoe Perchesdie "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2);
369713a09deSAntonio Borneo
37091bfe484SJoe Perchessub hash_save_array_words {
37191bfe484SJoe Perches	my ($hashRef, $arrayRef) = @_;
37291bfe484SJoe Perches
37391bfe484SJoe Perches	my @array = split(/,/, join(',', @$arrayRef));
37491bfe484SJoe Perches	foreach my $word (@array) {
375000d1cc1SJoe Perches		$word =~ s/\s*\n?$//g;
376000d1cc1SJoe Perches		$word =~ s/^\s*//g;
377000d1cc1SJoe Perches		$word =~ s/\s+/ /g;
378000d1cc1SJoe Perches		$word =~ tr/[a-z]/[A-Z]/;
379000d1cc1SJoe Perches
380000d1cc1SJoe Perches		next if ($word =~ m/^\s*#/);
381000d1cc1SJoe Perches		next if ($word =~ m/^\s*$/);
382000d1cc1SJoe Perches
38391bfe484SJoe Perches		$hashRef->{$word}++;
384000d1cc1SJoe Perches	}
38591bfe484SJoe Perches}
38691bfe484SJoe Perches
38791bfe484SJoe Perchessub hash_show_words {
38891bfe484SJoe Perches	my ($hashRef, $prefix) = @_;
38991bfe484SJoe Perches
3903c816e49SJoe Perches	if (keys %$hashRef) {
391d8469f16SJoe Perches		print "\nNOTE: $prefix message types:";
39258cb3cf6SJoe Perches		foreach my $word (sort keys %$hashRef) {
39391bfe484SJoe Perches			print " $word";
39491bfe484SJoe Perches		}
395d8469f16SJoe Perches		print "\n";
39691bfe484SJoe Perches	}
39791bfe484SJoe Perches}
39891bfe484SJoe Perches
39991bfe484SJoe Percheshash_save_array_words(\%ignore_type, \@ignore);
40091bfe484SJoe Percheshash_save_array_words(\%use_type, \@use);
401000d1cc1SJoe Perches
402c2fdda0dSAndy Whitcroftmy $dbg_values = 0;
403c2fdda0dSAndy Whitcroftmy $dbg_possible = 0;
4047429c690SAndy Whitcroftmy $dbg_type = 0;
405a1ef277eSAndy Whitcroftmy $dbg_attr = 0;
406c2fdda0dSAndy Whitcroftfor my $key (keys %debug) {
40721caa13cSAndy Whitcroft	## no critic
40821caa13cSAndy Whitcroft	eval "\${dbg_$key} = '$debug{$key}';";
40921caa13cSAndy Whitcroft	die "$@" if ($@);
410c2fdda0dSAndy Whitcroft}
411c2fdda0dSAndy Whitcroft
412d2c0a235SAndy Whitcroftmy $rpt_cleaners = 0;
413d2c0a235SAndy Whitcroft
4148905a67cSAndy Whitcroftif ($terse) {
4158905a67cSAndy Whitcroft	$emacs = 1;
4168905a67cSAndy Whitcroft	$quiet++;
4178905a67cSAndy Whitcroft}
4188905a67cSAndy Whitcroft
4196c72ffaaSAndy Whitcroftif ($tree) {
4206c72ffaaSAndy Whitcroft	if (defined $root) {
4216c72ffaaSAndy Whitcroft		if (!top_of_kernel_tree($root)) {
4226c72ffaaSAndy Whitcroft			die "$P: $root: --root does not point at a valid tree\n";
4236c72ffaaSAndy Whitcroft		}
4246c72ffaaSAndy Whitcroft	} else {
4256c72ffaaSAndy Whitcroft		if (top_of_kernel_tree('.')) {
4266c72ffaaSAndy Whitcroft			$root = '.';
4276c72ffaaSAndy Whitcroft		} elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
4286c72ffaaSAndy Whitcroft						top_of_kernel_tree($1)) {
4296c72ffaaSAndy Whitcroft			$root = $1;
4306c72ffaaSAndy Whitcroft		}
4316c72ffaaSAndy Whitcroft	}
4326c72ffaaSAndy Whitcroft
4336c72ffaaSAndy Whitcroft	if (!defined $root) {
4340a920b5bSAndy Whitcroft		print "Must be run from the top-level dir. of a kernel tree\n";
4350a920b5bSAndy Whitcroft		exit(2);
4360a920b5bSAndy Whitcroft	}
4376c72ffaaSAndy Whitcroft}
4386c72ffaaSAndy Whitcroft
4396c72ffaaSAndy Whitcroftmy $emitted_corrupt = 0;
4406c72ffaaSAndy Whitcroft
4412ceb532bSAndy Whitcroftour $Ident	= qr{
4422ceb532bSAndy Whitcroft			[A-Za-z_][A-Za-z\d_]*
4432ceb532bSAndy Whitcroft			(?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
4442ceb532bSAndy Whitcroft		}x;
4456c72ffaaSAndy Whitcroftour $Storage	= qr{extern|static|asmlinkage};
4466c72ffaaSAndy Whitcroftour $Sparse	= qr{
4476c72ffaaSAndy Whitcroft			__user|
4486c72ffaaSAndy Whitcroft			__kernel|
4496c72ffaaSAndy Whitcroft			__force|
4506c72ffaaSAndy Whitcroft			__iomem|
4516c72ffaaSAndy Whitcroft			__must_check|
452417495edSAndy Whitcroft			__kprobes|
453165e72a6SSven Eckelmann			__ref|
45433aa4597SGeert Uytterhoeven			__refconst|
45533aa4597SGeert Uytterhoeven			__refdata|
456ad315455SBoqun Feng			__rcu|
457ad315455SBoqun Feng			__private
4586c72ffaaSAndy Whitcroft		}x;
459e970b884SJoe Perchesour $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
460e970b884SJoe Perchesour $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
461e970b884SJoe Perchesour $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)};
462e970b884SJoe Perchesour $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)};
463e970b884SJoe Perchesour $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit};
4648716de38SJoe Perches
46552131292SWolfram Sang# Notes to $Attribute:
46652131292SWolfram Sang# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
4676c72ffaaSAndy Whitcroftour $Attribute	= qr{
4686c72ffaaSAndy Whitcroft			const|
469b5e8736aSJoe Perches			volatile|
47003f1df7dSJoe Perches			__percpu|
47103f1df7dSJoe Perches			__nocast|
47203f1df7dSJoe Perches			__safe|
47346d832f5SMichael S. Tsirkin			__bitwise|
47403f1df7dSJoe Perches			__packed__|
47503f1df7dSJoe Perches			__packed2__|
47603f1df7dSJoe Perches			__naked|
47703f1df7dSJoe Perches			__maybe_unused|
47803f1df7dSJoe Perches			__always_unused|
47903f1df7dSJoe Perches			__noreturn|
48003f1df7dSJoe Perches			__used|
48103f1df7dSJoe Perches			__cold|
482e23ef1f3SJoe Perches			__pure|
48303f1df7dSJoe Perches			__noclone|
48403f1df7dSJoe Perches			__deprecated|
4856c72ffaaSAndy Whitcroft			__read_mostly|
486c5967e98SJoe Perches			__ro_after_init|
4876c72ffaaSAndy Whitcroft			__kprobes|
4888716de38SJoe Perches			$InitAttribute|
48924e1d81aSAndy Whitcroft			____cacheline_aligned|
49024e1d81aSAndy Whitcroft			____cacheline_aligned_in_smp|
4915fe3af11SAndy Whitcroft			____cacheline_internodealigned_in_smp|
492*86cffecdSKees Cook			__weak|
493*86cffecdSKees Cook			__alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\)
4946c72ffaaSAndy Whitcroft		  }x;
495c45dcabdSAndy Whitcroftour $Modifier;
49691cb5195SJoe Perchesour $Inline	= qr{inline|__always_inline|noinline|__inline|__inline__};
4976c72ffaaSAndy Whitcroftour $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};
4986c72ffaaSAndy Whitcroftour $Lval	= qr{$Ident(?:$Member)*};
4996c72ffaaSAndy Whitcroft
50095e2c602SJoe Perchesour $Int_type	= qr{(?i)llu|ull|ll|lu|ul|l|u};
50195e2c602SJoe Perchesour $Binary	= qr{(?i)0b[01]+$Int_type?};
50295e2c602SJoe Perchesour $Hex	= qr{(?i)0x[0-9a-f]+$Int_type?};
50395e2c602SJoe Perchesour $Int	= qr{[0-9]+$Int_type?};
5042435880fSJoe Perchesour $Octal	= qr{0[0-7]+$Int_type?};
505d2af5aa6SJoe Perchesour $String	= qr{(?:\b[Lu])?"[X\t]*"};
506326b1ffcSJoe Perchesour $Float_hex	= qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
507326b1ffcSJoe Perchesour $Float_dec	= qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
508326b1ffcSJoe Perchesour $Float_int	= qr{(?i)[0-9]+e-?[0-9]+[fl]?};
50974349bccSJoe Perchesour $Float	= qr{$Float_hex|$Float_dec|$Float_int};
5102435880fSJoe Perchesour $Constant	= qr{$Float|$Binary|$Octal|$Hex|$Int};
511326b1ffcSJoe Perchesour $Assignment	= qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
512447432f3SJoe Perchesour $Compare    = qr{<=|>=|==|!=|<|(?<!-)>};
51323f780c9SJoe Perchesour $Arithmetic = qr{\+|-|\*|\/|%};
5146c72ffaaSAndy Whitcroftour $Operators	= qr{
5156c72ffaaSAndy Whitcroft			<=|>=|==|!=|
5166c72ffaaSAndy Whitcroft			=>|->|<<|>>|<|>|!|~|
51723f780c9SJoe Perches			&&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
5186c72ffaaSAndy Whitcroft		  }x;
5196c72ffaaSAndy Whitcroft
52091cb5195SJoe Perchesour $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
52191cb5195SJoe Perches
522ab7e23f3SJoe Perchesour $BasicType;
5238905a67cSAndy Whitcroftour $NonptrType;
5241813087dSJoe Perchesour $NonptrTypeMisordered;
5258716de38SJoe Perchesour $NonptrTypeWithAttr;
5268905a67cSAndy Whitcroftour $Type;
5271813087dSJoe Perchesour $TypeMisordered;
5288905a67cSAndy Whitcroftour $Declare;
5291813087dSJoe Perchesour $DeclareMisordered;
5308905a67cSAndy Whitcroft
53115662b3eSJoe Perchesour $NON_ASCII_UTF8	= qr{
53215662b3eSJoe Perches	[\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
533171ae1a4SAndy Whitcroft	|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
534171ae1a4SAndy Whitcroft	| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
535171ae1a4SAndy Whitcroft	|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
536171ae1a4SAndy Whitcroft	|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
537171ae1a4SAndy Whitcroft	| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
538171ae1a4SAndy Whitcroft	|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
539171ae1a4SAndy Whitcroft}x;
540171ae1a4SAndy Whitcroft
54115662b3eSJoe Perchesour $UTF8	= qr{
54215662b3eSJoe Perches	[\x09\x0A\x0D\x20-\x7E]              # ASCII
54315662b3eSJoe Perches	| $NON_ASCII_UTF8
54415662b3eSJoe Perches}x;
54515662b3eSJoe Perches
546e6176fa4SJoe Perchesour $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t};
547021158b4SJoe Perchesour $typeOtherOSTypedefs = qr{(?x:
548021158b4SJoe Perches	u_(?:char|short|int|long) |          # bsd
549021158b4SJoe Perches	u(?:nchar|short|int|long)            # sysv
550021158b4SJoe Perches)};
551e6176fa4SJoe Perchesour $typeKernelTypedefs = qr{(?x:
552fb9e9096SAndy Whitcroft	(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
5538ed22cadSAndy Whitcroft	atomic_t
5548ed22cadSAndy Whitcroft)};
555e6176fa4SJoe Perchesour $typeTypedefs = qr{(?x:
556e6176fa4SJoe Perches	$typeC99Typedefs\b|
557e6176fa4SJoe Perches	$typeOtherOSTypedefs\b|
558e6176fa4SJoe Perches	$typeKernelTypedefs\b
559e6176fa4SJoe Perches)};
5608ed22cadSAndy Whitcroft
5616d32f7a3SJoe Perchesour $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
5626d32f7a3SJoe Perches
563691e669bSJoe Perchesour $logFunctions = qr{(?x:
564758d7aadSMiles Chen	printk(?:_ratelimited|_once|_deferred_once|_deferred|)|
5657d0b6594SJacob Keller	(?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
56687bd499aSJoe Perches	TP_printk|
5676e60c02eSJoe Perches	WARN(?:_RATELIMIT|_ONCE|)|
568b0531722SJoe Perches	panic|
56906668727SJoe Perches	MODULE_[A-Z_]+|
57006668727SJoe Perches	seq_vprintf|seq_printf|seq_puts
571691e669bSJoe Perches)};
572691e669bSJoe Perches
573e29a70f1SJoe Perchesour $allocFunctions = qr{(?x:
574e29a70f1SJoe Perches	(?:(?:devm_)?
57558f02267SJoe Perches		(?:kv|k|v)[czm]alloc(?:_array)?(?:_node)? |
576e29a70f1SJoe Perches		kstrdup(?:_const)? |
577e29a70f1SJoe Perches		kmemdup(?:_nul)?) |
578461e1565SChristophe JAILLET	(?:\w+)?alloc_skb(?:_ip_align)? |
579e29a70f1SJoe Perches				# dev_alloc_skb/netdev_alloc_skb, et al
580e29a70f1SJoe Perches	dma_alloc_coherent
581e29a70f1SJoe Perches)};
582e29a70f1SJoe Perches
58320112475SJoe Perchesour $signature_tags = qr{(?xi:
58420112475SJoe Perches	Signed-off-by:|
585d499480cSJorge Ramirez-Ortiz	Co-developed-by:|
58620112475SJoe Perches	Acked-by:|
58720112475SJoe Perches	Tested-by:|
58820112475SJoe Perches	Reviewed-by:|
58920112475SJoe Perches	Reported-by:|
5908543ae12SMugunthan V N	Suggested-by:|
59120112475SJoe Perches	To:|
59220112475SJoe Perches	Cc:
59320112475SJoe Perches)};
59420112475SJoe Perches
595adb2da82SJoe Perchesour $tracing_logging_tags = qr{(?xi:
596adb2da82SJoe Perches	[=-]*> |
597adb2da82SJoe Perches	<[=-]* |
598adb2da82SJoe Perches	\[ |
599adb2da82SJoe Perches	\] |
600adb2da82SJoe Perches	start |
601adb2da82SJoe Perches	called |
602adb2da82SJoe Perches	entered |
603adb2da82SJoe Perches	entry |
604adb2da82SJoe Perches	enter |
605adb2da82SJoe Perches	in |
606adb2da82SJoe Perches	inside |
607adb2da82SJoe Perches	here |
608adb2da82SJoe Perches	begin |
609adb2da82SJoe Perches	exit |
610adb2da82SJoe Perches	end |
611adb2da82SJoe Perches	done |
612adb2da82SJoe Perches	leave |
613adb2da82SJoe Perches	completed |
614adb2da82SJoe Perches	out |
615adb2da82SJoe Perches	return |
616adb2da82SJoe Perches	[\.\!:\s]*
617adb2da82SJoe Perches)};
618adb2da82SJoe Perches
619831242abSAditya Srivastavasub edit_distance_min {
620831242abSAditya Srivastava	my (@arr) = @_;
621831242abSAditya Srivastava	my $len = scalar @arr;
622831242abSAditya Srivastava	if ((scalar @arr) < 1) {
623831242abSAditya Srivastava		# if underflow, return
624831242abSAditya Srivastava		return;
625831242abSAditya Srivastava	}
626831242abSAditya Srivastava	my $min = $arr[0];
627831242abSAditya Srivastava	for my $i (0 .. ($len-1)) {
628831242abSAditya Srivastava		if ($arr[$i] < $min) {
629831242abSAditya Srivastava			$min = $arr[$i];
630831242abSAditya Srivastava		}
631831242abSAditya Srivastava	}
632831242abSAditya Srivastava	return $min;
633831242abSAditya Srivastava}
634831242abSAditya Srivastava
635831242abSAditya Srivastavasub get_edit_distance {
636831242abSAditya Srivastava	my ($str1, $str2) = @_;
637831242abSAditya Srivastava	$str1 = lc($str1);
638831242abSAditya Srivastava	$str2 = lc($str2);
639831242abSAditya Srivastava	$str1 =~ s/-//g;
640831242abSAditya Srivastava	$str2 =~ s/-//g;
641831242abSAditya Srivastava	my $len1 = length($str1);
642831242abSAditya Srivastava	my $len2 = length($str2);
643831242abSAditya Srivastava	# two dimensional array storing minimum edit distance
644831242abSAditya Srivastava	my @distance;
645831242abSAditya Srivastava	for my $i (0 .. $len1) {
646831242abSAditya Srivastava		for my $j (0 .. $len2) {
647831242abSAditya Srivastava			if ($i == 0) {
648831242abSAditya Srivastava				$distance[$i][$j] = $j;
649831242abSAditya Srivastava			} elsif ($j == 0) {
650831242abSAditya Srivastava				$distance[$i][$j] = $i;
651831242abSAditya Srivastava			} elsif (substr($str1, $i-1, 1) eq substr($str2, $j-1, 1)) {
652831242abSAditya Srivastava				$distance[$i][$j] = $distance[$i - 1][$j - 1];
653831242abSAditya Srivastava			} else {
654831242abSAditya Srivastava				my $dist1 = $distance[$i][$j - 1]; #insert distance
655831242abSAditya Srivastava				my $dist2 = $distance[$i - 1][$j]; # remove
656831242abSAditya Srivastava				my $dist3 = $distance[$i - 1][$j - 1]; #replace
657831242abSAditya Srivastava				$distance[$i][$j] = 1 + edit_distance_min($dist1, $dist2, $dist3);
658831242abSAditya Srivastava			}
659831242abSAditya Srivastava		}
660831242abSAditya Srivastava	}
661831242abSAditya Srivastava	return $distance[$len1][$len2];
662831242abSAditya Srivastava}
663831242abSAditya Srivastava
664831242abSAditya Srivastavasub find_standard_signature {
665831242abSAditya Srivastava	my ($sign_off) = @_;
666831242abSAditya Srivastava	my @standard_signature_tags = (
667831242abSAditya Srivastava		'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:',
668831242abSAditya Srivastava		'Reviewed-by:', 'Reported-by:', 'Suggested-by:'
669831242abSAditya Srivastava	);
670831242abSAditya Srivastava	foreach my $signature (@standard_signature_tags) {
671831242abSAditya Srivastava		return $signature if (get_edit_distance($sign_off, $signature) <= 2);
672831242abSAditya Srivastava	}
673831242abSAditya Srivastava
674831242abSAditya Srivastava	return "";
675831242abSAditya Srivastava}
676831242abSAditya Srivastava
6771813087dSJoe Perchesour @typeListMisordered = (
6781813087dSJoe Perches	qr{char\s+(?:un)?signed},
6791813087dSJoe Perches	qr{int\s+(?:(?:un)?signed\s+)?short\s},
6801813087dSJoe Perches	qr{int\s+short(?:\s+(?:un)?signed)},
6811813087dSJoe Perches	qr{short\s+int(?:\s+(?:un)?signed)},
6821813087dSJoe Perches	qr{(?:un)?signed\s+int\s+short},
6831813087dSJoe Perches	qr{short\s+(?:un)?signed},
6841813087dSJoe Perches	qr{long\s+int\s+(?:un)?signed},
6851813087dSJoe Perches	qr{int\s+long\s+(?:un)?signed},
6861813087dSJoe Perches	qr{long\s+(?:un)?signed\s+int},
6871813087dSJoe Perches	qr{int\s+(?:un)?signed\s+long},
6881813087dSJoe Perches	qr{int\s+(?:un)?signed},
6891813087dSJoe Perches	qr{int\s+long\s+long\s+(?:un)?signed},
6901813087dSJoe Perches	qr{long\s+long\s+int\s+(?:un)?signed},
6911813087dSJoe Perches	qr{long\s+long\s+(?:un)?signed\s+int},
6921813087dSJoe Perches	qr{long\s+long\s+(?:un)?signed},
6931813087dSJoe Perches	qr{long\s+(?:un)?signed},
6941813087dSJoe Perches);
6951813087dSJoe Perches
6968905a67cSAndy Whitcroftour @typeList = (
6978905a67cSAndy Whitcroft	qr{void},
6980c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?char},
6990c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?short\s+int},
7000c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?short},
7010c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?int},
7020c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?long\s+int},
7030c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?long\s+long\s+int},
7040c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?long\s+long},
7050c773d9dSJoe Perches	qr{(?:(?:un)?signed\s+)?long},
7060c773d9dSJoe Perches	qr{(?:un)?signed},
7078905a67cSAndy Whitcroft	qr{float},
7088905a67cSAndy Whitcroft	qr{double},
7098905a67cSAndy Whitcroft	qr{bool},
7108905a67cSAndy Whitcroft	qr{struct\s+$Ident},
7118905a67cSAndy Whitcroft	qr{union\s+$Ident},
7128905a67cSAndy Whitcroft	qr{enum\s+$Ident},
7138905a67cSAndy Whitcroft	qr{${Ident}_t},
7148905a67cSAndy Whitcroft	qr{${Ident}_handler},
7158905a67cSAndy Whitcroft	qr{${Ident}_handler_fn},
7161813087dSJoe Perches	@typeListMisordered,
7178905a67cSAndy Whitcroft);
718938224b5SJoe Perches
719938224b5SJoe Perchesour $C90_int_types = qr{(?x:
720938224b5SJoe Perches	long\s+long\s+int\s+(?:un)?signed|
721938224b5SJoe Perches	long\s+long\s+(?:un)?signed\s+int|
722938224b5SJoe Perches	long\s+long\s+(?:un)?signed|
723938224b5SJoe Perches	(?:(?:un)?signed\s+)?long\s+long\s+int|
724938224b5SJoe Perches	(?:(?:un)?signed\s+)?long\s+long|
725938224b5SJoe Perches	int\s+long\s+long\s+(?:un)?signed|
726938224b5SJoe Perches	int\s+(?:(?:un)?signed\s+)?long\s+long|
727938224b5SJoe Perches
728938224b5SJoe Perches	long\s+int\s+(?:un)?signed|
729938224b5SJoe Perches	long\s+(?:un)?signed\s+int|
730938224b5SJoe Perches	long\s+(?:un)?signed|
731938224b5SJoe Perches	(?:(?:un)?signed\s+)?long\s+int|
732938224b5SJoe Perches	(?:(?:un)?signed\s+)?long|
733938224b5SJoe Perches	int\s+long\s+(?:un)?signed|
734938224b5SJoe Perches	int\s+(?:(?:un)?signed\s+)?long|
735938224b5SJoe Perches
736938224b5SJoe Perches	int\s+(?:un)?signed|
737938224b5SJoe Perches	(?:(?:un)?signed\s+)?int
738938224b5SJoe Perches)};
739938224b5SJoe Perches
740485ff23eSAlex Dowadour @typeListFile = ();
7418716de38SJoe Perchesour @typeListWithAttr = (
7428716de38SJoe Perches	@typeList,
7438716de38SJoe Perches	qr{struct\s+$InitAttribute\s+$Ident},
7448716de38SJoe Perches	qr{union\s+$InitAttribute\s+$Ident},
7458716de38SJoe Perches);
7468716de38SJoe Perches
747c45dcabdSAndy Whitcroftour @modifierList = (
748c45dcabdSAndy Whitcroft	qr{fastcall},
749c45dcabdSAndy Whitcroft);
750485ff23eSAlex Dowadour @modifierListFile = ();
7518905a67cSAndy Whitcroft
7522435880fSJoe Perchesour @mode_permission_funcs = (
7532435880fSJoe Perches	["module_param", 3],
7542435880fSJoe Perches	["module_param_(?:array|named|string)", 4],
7552435880fSJoe Perches	["module_param_array_named", 5],
7562435880fSJoe Perches	["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
7572435880fSJoe Perches	["proc_create(?:_data|)", 2],
758459cf0aeSJoe Perches	["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
759459cf0aeSJoe Perches	["IIO_DEV_ATTR_[A-Z_]+", 1],
760459cf0aeSJoe Perches	["SENSOR_(?:DEVICE_|)ATTR_2", 2],
761459cf0aeSJoe Perches	["SENSOR_TEMPLATE(?:_2|)", 3],
762459cf0aeSJoe Perches	["__ATTR", 2],
7632435880fSJoe Perches);
7642435880fSJoe Perches
7651a3dcf2eSJoe Perchesmy $word_pattern = '\b[A-Z]?[a-z]{2,}\b';
7661a3dcf2eSJoe Perches
767515a235eSJoe Perches#Create a search pattern for all these functions to speed up a loop below
768515a235eSJoe Perchesour $mode_perms_search = "";
769515a235eSJoe Perchesforeach my $entry (@mode_permission_funcs) {
770515a235eSJoe Perches	$mode_perms_search .= '|' if ($mode_perms_search ne "");
771515a235eSJoe Perches	$mode_perms_search .= $entry->[0];
772515a235eSJoe Perches}
77300180468SJoe Perches$mode_perms_search = "(?:${mode_perms_search})";
774515a235eSJoe Perches
7759189c7e7SJoe Perchesour %deprecated_apis = (
7769189c7e7SJoe Perches	"synchronize_rcu_bh"			=> "synchronize_rcu",
7779189c7e7SJoe Perches	"synchronize_rcu_bh_expedited"		=> "synchronize_rcu_expedited",
7789189c7e7SJoe Perches	"call_rcu_bh"				=> "call_rcu",
7799189c7e7SJoe Perches	"rcu_barrier_bh"			=> "rcu_barrier",
7809189c7e7SJoe Perches	"synchronize_sched"			=> "synchronize_rcu",
7819189c7e7SJoe Perches	"synchronize_sched_expedited"		=> "synchronize_rcu_expedited",
7829189c7e7SJoe Perches	"call_rcu_sched"			=> "call_rcu",
7839189c7e7SJoe Perches	"rcu_barrier_sched"			=> "rcu_barrier",
7849189c7e7SJoe Perches	"get_state_synchronize_sched"		=> "get_state_synchronize_rcu",
7859189c7e7SJoe Perches	"cond_synchronize_sched"		=> "cond_synchronize_rcu",
7869189c7e7SJoe Perches);
7879189c7e7SJoe Perches
7889189c7e7SJoe Perches#Create a search pattern for all these strings to speed up a loop below
7899189c7e7SJoe Perchesour $deprecated_apis_search = "";
7909189c7e7SJoe Perchesforeach my $entry (keys %deprecated_apis) {
7919189c7e7SJoe Perches	$deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
7929189c7e7SJoe Perches	$deprecated_apis_search .= $entry;
7939189c7e7SJoe Perches}
7949189c7e7SJoe Perches$deprecated_apis_search = "(?:${deprecated_apis_search})";
7959189c7e7SJoe Perches
796b392c64fSJoe Perchesour $mode_perms_world_writable = qr{
797b392c64fSJoe Perches	S_IWUGO		|
798b392c64fSJoe Perches	S_IWOTH		|
799b392c64fSJoe Perches	S_IRWXUGO	|
800b392c64fSJoe Perches	S_IALLUGO	|
801b392c64fSJoe Perches	0[0-7][0-7][2367]
802b392c64fSJoe Perches}x;
803b392c64fSJoe Perches
804f90774e1SJoe Perchesour %mode_permission_string_types = (
805f90774e1SJoe Perches	"S_IRWXU" => 0700,
806f90774e1SJoe Perches	"S_IRUSR" => 0400,
807f90774e1SJoe Perches	"S_IWUSR" => 0200,
808f90774e1SJoe Perches	"S_IXUSR" => 0100,
809f90774e1SJoe Perches	"S_IRWXG" => 0070,
810f90774e1SJoe Perches	"S_IRGRP" => 0040,
811f90774e1SJoe Perches	"S_IWGRP" => 0020,
812f90774e1SJoe Perches	"S_IXGRP" => 0010,
813f90774e1SJoe Perches	"S_IRWXO" => 0007,
814f90774e1SJoe Perches	"S_IROTH" => 0004,
815f90774e1SJoe Perches	"S_IWOTH" => 0002,
816f90774e1SJoe Perches	"S_IXOTH" => 0001,
817f90774e1SJoe Perches	"S_IRWXUGO" => 0777,
818f90774e1SJoe Perches	"S_IRUGO" => 0444,
819f90774e1SJoe Perches	"S_IWUGO" => 0222,
820f90774e1SJoe Perches	"S_IXUGO" => 0111,
821f90774e1SJoe Perches);
822f90774e1SJoe Perches
823f90774e1SJoe Perches#Create a search pattern for all these strings to speed up a loop below
824f90774e1SJoe Perchesour $mode_perms_string_search = "";
825f90774e1SJoe Perchesforeach my $entry (keys %mode_permission_string_types) {
826f90774e1SJoe Perches	$mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
827f90774e1SJoe Perches	$mode_perms_string_search .= $entry;
828f90774e1SJoe Perches}
82900180468SJoe Perchesour $single_mode_perms_string_search = "(?:${mode_perms_string_search})";
83000180468SJoe Perchesour $multi_mode_perms_string_search = qr{
83100180468SJoe Perches	${single_mode_perms_string_search}
83200180468SJoe Perches	(?:\s*\|\s*${single_mode_perms_string_search})*
83300180468SJoe Perches}x;
83400180468SJoe Perches
83500180468SJoe Perchessub perms_to_octal {
83600180468SJoe Perches	my ($string) = @_;
83700180468SJoe Perches
83800180468SJoe Perches	return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/);
83900180468SJoe Perches
84000180468SJoe Perches	my $val = "";
84100180468SJoe Perches	my $oval = "";
84200180468SJoe Perches	my $to = 0;
84300180468SJoe Perches	my $curpos = 0;
84400180468SJoe Perches	my $lastpos = 0;
84500180468SJoe Perches	while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
84600180468SJoe Perches		$curpos = pos($string);
84700180468SJoe Perches		my $match = $2;
84800180468SJoe Perches		my $omatch = $1;
84900180468SJoe Perches		last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
85000180468SJoe Perches		$lastpos = $curpos;
85100180468SJoe Perches		$to |= $mode_permission_string_types{$match};
85200180468SJoe Perches		$val .= '\s*\|\s*' if ($val ne "");
85300180468SJoe Perches		$val .= $match;
85400180468SJoe Perches		$oval .= $omatch;
85500180468SJoe Perches	}
85600180468SJoe Perches	$oval =~ s/^\s*\|\s*//;
85700180468SJoe Perches	$oval =~ s/\s*\|\s*$//;
85800180468SJoe Perches	return sprintf("%04o", $to);
85900180468SJoe Perches}
860f90774e1SJoe Perches
8617840a94cSWolfram Sangour $allowed_asm_includes = qr{(?x:
8627840a94cSWolfram Sang	irq|
863cdcee686SSergey Ryazanov	memory|
864cdcee686SSergey Ryazanov	time|
865cdcee686SSergey Ryazanov	reboot
8667840a94cSWolfram Sang)};
8677840a94cSWolfram Sang# memory.h: ARM has a custom one
8687840a94cSWolfram Sang
86966b47b4aSKees Cook# Load common spelling mistakes and build regular expression list.
87066b47b4aSKees Cookmy $misspellings;
87166b47b4aSKees Cookmy %spelling_fix;
87236061e38SJoe Perches
87336061e38SJoe Perchesif (open(my $spelling, '<', $spelling_file)) {
87466b47b4aSKees Cook	while (<$spelling>) {
87566b47b4aSKees Cook		my $line = $_;
87666b47b4aSKees Cook
87766b47b4aSKees Cook		$line =~ s/\s*\n?$//g;
87866b47b4aSKees Cook		$line =~ s/^\s*//g;
87966b47b4aSKees Cook
88066b47b4aSKees Cook		next if ($line =~ m/^\s*#/);
88166b47b4aSKees Cook		next if ($line =~ m/^\s*$/);
88266b47b4aSKees Cook
88366b47b4aSKees Cook		my ($suspect, $fix) = split(/\|\|/, $line);
88466b47b4aSKees Cook
88566b47b4aSKees Cook		$spelling_fix{$suspect} = $fix;
88666b47b4aSKees Cook	}
88766b47b4aSKees Cook	close($spelling);
88836061e38SJoe Perches} else {
88936061e38SJoe Perches	warn "No typos will be found - file '$spelling_file': $!\n";
89036061e38SJoe Perches}
89166b47b4aSKees Cook
892ebfd7d62SJoe Perchesif ($codespell) {
893ebfd7d62SJoe Perches	if (open(my $spelling, '<', $codespellfile)) {
894ebfd7d62SJoe Perches		while (<$spelling>) {
895ebfd7d62SJoe Perches			my $line = $_;
896ebfd7d62SJoe Perches
897ebfd7d62SJoe Perches			$line =~ s/\s*\n?$//g;
898ebfd7d62SJoe Perches			$line =~ s/^\s*//g;
899ebfd7d62SJoe Perches
900ebfd7d62SJoe Perches			next if ($line =~ m/^\s*#/);
901ebfd7d62SJoe Perches			next if ($line =~ m/^\s*$/);
902ebfd7d62SJoe Perches			next if ($line =~ m/, disabled/i);
903ebfd7d62SJoe Perches
904ebfd7d62SJoe Perches			$line =~ s/,.*$//;
905ebfd7d62SJoe Perches
906ebfd7d62SJoe Perches			my ($suspect, $fix) = split(/->/, $line);
907ebfd7d62SJoe Perches
908ebfd7d62SJoe Perches			$spelling_fix{$suspect} = $fix;
909ebfd7d62SJoe Perches		}
910ebfd7d62SJoe Perches		close($spelling);
911ebfd7d62SJoe Perches	} else {
912ebfd7d62SJoe Perches		warn "No codespell typos will be found - file '$codespellfile': $!\n";
913ebfd7d62SJoe Perches	}
914ebfd7d62SJoe Perches}
915ebfd7d62SJoe Perches
916ebfd7d62SJoe Perches$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
917ebfd7d62SJoe Perches
91875ad8c57SJerome Forissiersub read_words {
91975ad8c57SJerome Forissier	my ($wordsRef, $file) = @_;
92075ad8c57SJerome Forissier
92175ad8c57SJerome Forissier	if (open(my $words, '<', $file)) {
92275ad8c57SJerome Forissier		while (<$words>) {
923bf1fa1daSJoe Perches			my $line = $_;
924bf1fa1daSJoe Perches
925bf1fa1daSJoe Perches			$line =~ s/\s*\n?$//g;
926bf1fa1daSJoe Perches			$line =~ s/^\s*//g;
927bf1fa1daSJoe Perches
928bf1fa1daSJoe Perches			next if ($line =~ m/^\s*#/);
929bf1fa1daSJoe Perches			next if ($line =~ m/^\s*$/);
930bf1fa1daSJoe Perches			if ($line =~ /\s/) {
93175ad8c57SJerome Forissier				print("$file: '$line' invalid - ignored\n");
932bf1fa1daSJoe Perches				next;
933bf1fa1daSJoe Perches			}
934bf1fa1daSJoe Perches
935ced69da1SQuentin Monnet			$$wordsRef .= '|' if (defined $$wordsRef);
93675ad8c57SJerome Forissier			$$wordsRef .= $line;
937bf1fa1daSJoe Perches		}
93875ad8c57SJerome Forissier		close($file);
93975ad8c57SJerome Forissier		return 1;
940bf1fa1daSJoe Perches	}
941bf1fa1daSJoe Perches
94275ad8c57SJerome Forissier	return 0;
94375ad8c57SJerome Forissier}
94475ad8c57SJerome Forissier
945ced69da1SQuentin Monnetmy $const_structs;
946ced69da1SQuentin Monnetif (show_type("CONST_STRUCT")) {
94775ad8c57SJerome Forissier	read_words(\$const_structs, $conststructsfile)
94875ad8c57SJerome Forissier	    or warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
949ced69da1SQuentin Monnet}
95075ad8c57SJerome Forissier
951ced69da1SQuentin Monnetif (defined($typedefsfile)) {
952ced69da1SQuentin Monnet	my $typeOtherTypedefs;
95375ad8c57SJerome Forissier	read_words(\$typeOtherTypedefs, $typedefsfile)
95475ad8c57SJerome Forissier	    or warn "No additional types will be considered - file '$typedefsfile': $!\n";
955ced69da1SQuentin Monnet	$typeTypedefs .= '|' . $typeOtherTypedefs if (defined $typeOtherTypedefs);
95675ad8c57SJerome Forissier}
95775ad8c57SJerome Forissier
9588905a67cSAndy Whitcroftsub build_types {
959485ff23eSAlex Dowad	my $mods = "(?x:  \n" . join("|\n  ", (@modifierList, @modifierListFile)) . "\n)";
960485ff23eSAlex Dowad	my $all = "(?x:  \n" . join("|\n  ", (@typeList, @typeListFile)) . "\n)";
9611813087dSJoe Perches	my $Misordered = "(?x:  \n" . join("|\n  ", @typeListMisordered) . "\n)";
9628716de38SJoe Perches	my $allWithAttr = "(?x:  \n" . join("|\n  ", @typeListWithAttr) . "\n)";
963c8cb2ca3SAndy Whitcroft	$Modifier	= qr{(?:$Attribute|$Sparse|$mods)};
964ab7e23f3SJoe Perches	$BasicType	= qr{
965ab7e23f3SJoe Perches				(?:$typeTypedefs\b)|
966ab7e23f3SJoe Perches				(?:${all}\b)
967ab7e23f3SJoe Perches		}x;
9688905a67cSAndy Whitcroft	$NonptrType	= qr{
969d2172eb5SAndy Whitcroft			(?:$Modifier\s+|const\s+)*
970cf655043SAndy Whitcroft			(?:
9716b48db24SAndy Whitcroft				(?:typeof|__typeof__)\s*\([^\)]*\)|
9728ed22cadSAndy Whitcroft				(?:$typeTypedefs\b)|
973c45dcabdSAndy Whitcroft				(?:${all}\b)
974cf655043SAndy Whitcroft			)
975c8cb2ca3SAndy Whitcroft			(?:\s+$Modifier|\s+const)*
9768905a67cSAndy Whitcroft		  }x;
9771813087dSJoe Perches	$NonptrTypeMisordered	= qr{
9781813087dSJoe Perches			(?:$Modifier\s+|const\s+)*
9791813087dSJoe Perches			(?:
9801813087dSJoe Perches				(?:${Misordered}\b)
9811813087dSJoe Perches			)
9821813087dSJoe Perches			(?:\s+$Modifier|\s+const)*
9831813087dSJoe Perches		  }x;
9848716de38SJoe Perches	$NonptrTypeWithAttr	= qr{
9858716de38SJoe Perches			(?:$Modifier\s+|const\s+)*
9868716de38SJoe Perches			(?:
9878716de38SJoe Perches				(?:typeof|__typeof__)\s*\([^\)]*\)|
9888716de38SJoe Perches				(?:$typeTypedefs\b)|
9898716de38SJoe Perches				(?:${allWithAttr}\b)
9908716de38SJoe Perches			)
9918716de38SJoe Perches			(?:\s+$Modifier|\s+const)*
9928716de38SJoe Perches		  }x;
9938905a67cSAndy Whitcroft	$Type	= qr{
994c45dcabdSAndy Whitcroft			$NonptrType
9957b18496cSAntonio Borneo			(?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
996c8cb2ca3SAndy Whitcroft			(?:\s+$Inline|\s+$Modifier)*
9978905a67cSAndy Whitcroft		  }x;
9981813087dSJoe Perches	$TypeMisordered	= qr{
9991813087dSJoe Perches			$NonptrTypeMisordered
10007b18496cSAntonio Borneo			(?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
10011813087dSJoe Perches			(?:\s+$Inline|\s+$Modifier)*
10021813087dSJoe Perches		  }x;
100391cb5195SJoe Perches	$Declare	= qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
10041813087dSJoe Perches	$DeclareMisordered	= qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered};
10058905a67cSAndy Whitcroft}
10068905a67cSAndy Whitcroftbuild_types();
10076c72ffaaSAndy Whitcroft
10087d2367afSJoe Perchesour $Typecast	= qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
1009d1fe9c09SJoe Perches
1010d1fe9c09SJoe Perches# Using $balanced_parens, $LvalOrFunc, or $FuncArg
1011d1fe9c09SJoe Perches# requires at least perl version v5.10.0
1012d1fe9c09SJoe Perches# Any use must be runtime checked with $^V
1013d1fe9c09SJoe Perches
1014d1fe9c09SJoe Perchesour $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
10152435880fSJoe Perchesour $LvalOrFunc	= qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
1016c0a5c898SJoe Perchesour $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
10177d2367afSJoe Perches
1018f8422308SJoe Perchesour $declaration_macros = qr{(?x:
10193e838b6cSJoe Perches	(?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
1020fe658f94SSteffen Maier	(?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
10213d102fc0SGilad Ben-Yossef	(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
1022f8422308SJoe Perches)};
1023f8422308SJoe Perches
10248d0325ccSAditya Srivastavaour %allow_repeated_words = (
10258d0325ccSAditya Srivastava	add => '',
10268d0325ccSAditya Srivastava	added => '',
10278d0325ccSAditya Srivastava	bad => '',
10288d0325ccSAditya Srivastava	be => '',
10298d0325ccSAditya Srivastava);
10308d0325ccSAditya Srivastava
10317d2367afSJoe Perchessub deparenthesize {
10327d2367afSJoe Perches	my ($string) = @_;
10337d2367afSJoe Perches	return "" if (!defined($string));
10345b9553abSJoe Perches
10355b9553abSJoe Perches	while ($string =~ /^\s*\(.*\)\s*$/) {
10365b9553abSJoe Perches		$string =~ s@^\s*\(\s*@@;
10375b9553abSJoe Perches		$string =~ s@\s*\)\s*$@@;
10385b9553abSJoe Perches	}
10395b9553abSJoe Perches
10407d2367afSJoe Perches	$string =~ s@\s+@ @g;
10415b9553abSJoe Perches
10427d2367afSJoe Perches	return $string;
10437d2367afSJoe Perches}
10447d2367afSJoe Perches
10453445686aSJoe Perchessub seed_camelcase_file {
10463445686aSJoe Perches	my ($file) = @_;
10473445686aSJoe Perches
10483445686aSJoe Perches	return if (!(-f $file));
10493445686aSJoe Perches
10503445686aSJoe Perches	local $/;
10513445686aSJoe Perches
10523445686aSJoe Perches	open(my $include_file, '<', "$file")
10533445686aSJoe Perches	    or warn "$P: Can't read '$file' $!\n";
10543445686aSJoe Perches	my $text = <$include_file>;
10553445686aSJoe Perches	close($include_file);
10563445686aSJoe Perches
10573445686aSJoe Perches	my @lines = split('\n', $text);
10583445686aSJoe Perches
10593445686aSJoe Perches	foreach my $line (@lines) {
10603445686aSJoe Perches		next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/);
10613445686aSJoe Perches		if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) {
10623445686aSJoe Perches			$camelcase{$1} = 1;
106311ea516aSJoe Perches		} elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) {
106411ea516aSJoe Perches			$camelcase{$1} = 1;
106511ea516aSJoe Perches		} elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) {
10663445686aSJoe Perches			$camelcase{$1} = 1;
10673445686aSJoe Perches		}
10683445686aSJoe Perches	}
10693445686aSJoe Perches}
10703445686aSJoe Perches
1071cd28b119SJoe Perchesour %maintained_status = ();
1072cd28b119SJoe Perches
107385b0ee18SJoe Perchessub is_maintained_obsolete {
107485b0ee18SJoe Perches	my ($filename) = @_;
107585b0ee18SJoe Perches
1076f2c19c2fSJerome Forissier	return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
107785b0ee18SJoe Perches
1078cd28b119SJoe Perches	if (!exists($maintained_status{$filename})) {
1079cd28b119SJoe Perches		$maintained_status{$filename} = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
1080cd28b119SJoe Perches	}
108185b0ee18SJoe Perches
1082cd28b119SJoe Perches	return $maintained_status{$filename} =~ /obsolete/i;
108385b0ee18SJoe Perches}
108485b0ee18SJoe Perches
10853b6e8ac9SJoe Perchessub is_SPDX_License_valid {
10863b6e8ac9SJoe Perches	my ($license) = @_;
10873b6e8ac9SJoe Perches
1088f9363b31SGuenter Roeck	return 1 if (!$tree || which("python3") eq "" || !(-x "$root/scripts/spdxcheck.py") || !(-e "$gitroot"));
10893b6e8ac9SJoe Perches
109056294112SJoe Perches	my $root_path = abs_path($root);
1091f9363b31SGuenter Roeck	my $status = `cd "$root_path"; echo "$license" | scripts/spdxcheck.py -`;
10923b6e8ac9SJoe Perches	return 0 if ($status ne "");
10933b6e8ac9SJoe Perches	return 1;
10943b6e8ac9SJoe Perches}
10953b6e8ac9SJoe Perches
10963445686aSJoe Perchesmy $camelcase_seeded = 0;
10973445686aSJoe Perchessub seed_camelcase_includes {
10983445686aSJoe Perches	return if ($camelcase_seeded);
10993445686aSJoe Perches
11003445686aSJoe Perches	my $files;
1101c707a81dSJoe Perches	my $camelcase_cache = "";
1102c707a81dSJoe Perches	my @include_files = ();
1103c707a81dSJoe Perches
1104c707a81dSJoe Perches	$camelcase_seeded = 1;
1105351b2a1fSJoe Perches
11060f7f635bSJoe Perches	if (-e "$gitroot") {
1107dbbf869dSJoe Perches		my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
1108351b2a1fSJoe Perches		chomp $git_last_include_commit;
1109c707a81dSJoe Perches		$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
1110c707a81dSJoe Perches	} else {
1111c707a81dSJoe Perches		my $last_mod_date = 0;
1112c707a81dSJoe Perches		$files = `find $root/include -name "*.h"`;
1113c707a81dSJoe Perches		@include_files = split('\n', $files);
1114c707a81dSJoe Perches		foreach my $file (@include_files) {
1115c707a81dSJoe Perches			my $date = POSIX::strftime("%Y%m%d%H%M",
1116c707a81dSJoe Perches						   localtime((stat $file)[9]));
1117c707a81dSJoe Perches			$last_mod_date = $date if ($last_mod_date < $date);
1118c707a81dSJoe Perches		}
1119c707a81dSJoe Perches		$camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date";
1120c707a81dSJoe Perches	}
1121c707a81dSJoe Perches
1122c707a81dSJoe Perches	if ($camelcase_cache ne "" && -f $camelcase_cache) {
1123c707a81dSJoe Perches		open(my $camelcase_file, '<', "$camelcase_cache")
1124c707a81dSJoe Perches		    or warn "$P: Can't read '$camelcase_cache' $!\n";
1125351b2a1fSJoe Perches		while (<$camelcase_file>) {
1126351b2a1fSJoe Perches			chomp;
1127351b2a1fSJoe Perches			$camelcase{$_} = 1;
1128351b2a1fSJoe Perches		}
1129351b2a1fSJoe Perches		close($camelcase_file);
1130351b2a1fSJoe Perches
1131351b2a1fSJoe Perches		return;
1132351b2a1fSJoe Perches	}
1133c707a81dSJoe Perches
11340f7f635bSJoe Perches	if (-e "$gitroot") {
1135dbbf869dSJoe Perches		$files = `${git_command} ls-files "include/*.h"`;
1136c707a81dSJoe Perches		@include_files = split('\n', $files);
11373445686aSJoe Perches	}
1138c707a81dSJoe Perches
11393445686aSJoe Perches	foreach my $file (@include_files) {
11403445686aSJoe Perches		seed_camelcase_file($file);
11413445686aSJoe Perches	}
1142351b2a1fSJoe Perches
1143c707a81dSJoe Perches	if ($camelcase_cache ne "") {
1144351b2a1fSJoe Perches		unlink glob ".checkpatch-camelcase.*";
1145c707a81dSJoe Perches		open(my $camelcase_file, '>', "$camelcase_cache")
1146c707a81dSJoe Perches		    or warn "$P: Can't write '$camelcase_cache' $!\n";
1147351b2a1fSJoe Perches		foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) {
1148351b2a1fSJoe Perches			print $camelcase_file ("$_\n");
1149351b2a1fSJoe Perches		}
1150351b2a1fSJoe Perches		close($camelcase_file);
1151351b2a1fSJoe Perches	}
11523445686aSJoe Perches}
11533445686aSJoe Perches
1154f5f61325SJoe Perchessub git_is_single_file {
1155f5f61325SJoe Perches	my ($filename) = @_;
1156f5f61325SJoe Perches
1157f5f61325SJoe Perches	return 0 if ((which("git") eq "") || !(-e "$gitroot"));
1158f5f61325SJoe Perches
1159f5f61325SJoe Perches	my $output = `${git_command} ls-files -- $filename 2>/dev/null`;
1160f5f61325SJoe Perches	my $count = $output =~ tr/\n//;
1161f5f61325SJoe Perches	return $count eq 1 && $output =~ m{^${filename}$};
1162f5f61325SJoe Perches}
1163f5f61325SJoe Perches
1164d311cd44SJoe Perchessub git_commit_info {
1165d311cd44SJoe Perches	my ($commit, $id, $desc) = @_;
1166d311cd44SJoe Perches
11670f7f635bSJoe Perches	return ($id, $desc) if ((which("git") eq "") || !(-e "$gitroot"));
1168d311cd44SJoe Perches
1169dbbf869dSJoe Perches	my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
1170d311cd44SJoe Perches	$output =~ s/^\s*//gm;
1171d311cd44SJoe Perches	my @lines = split("\n", $output);
1172d311cd44SJoe Perches
11730d7835fcSJoe Perches	return ($id, $desc) if ($#lines < 0);
11740d7835fcSJoe Perches
11755a7f4455SSean Christopherson	if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
1176d311cd44SJoe Perches# Maybe one day convert this block of bash into something that returns
1177d311cd44SJoe Perches# all matching commit ids, but it's very slow...
1178d311cd44SJoe Perches#
1179d311cd44SJoe Perches#		echo "checking commits $1..."
1180d311cd44SJoe Perches#		git rev-list --remotes | grep -i "^$1" |
1181d311cd44SJoe Perches#		while read line ; do
1182d311cd44SJoe Perches#		    git log --format='%H %s' -1 $line |
1183d311cd44SJoe Perches#		    echo "commit $(cut -c 1-12,41-)"
1184d311cd44SJoe Perches#		done
11854ce9f970SJoe Perches	} elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./ ||
11864ce9f970SJoe Perches		 $lines[0] =~ /^fatal: bad object $commit/) {
1187948b133aSHeinrich Schuchardt		$id = undef;
1188d311cd44SJoe Perches	} else {
1189d311cd44SJoe Perches		$id = substr($lines[0], 0, 12);
1190d311cd44SJoe Perches		$desc = substr($lines[0], 41);
1191d311cd44SJoe Perches	}
1192d311cd44SJoe Perches
1193d311cd44SJoe Perches	return ($id, $desc);
1194d311cd44SJoe Perches}
1195d311cd44SJoe Perches
11966c72ffaaSAndy Whitcroft$chk_signoff = 0 if ($file);
11970a920b5bSAndy Whitcroft
119800df344fSAndy Whitcroftmy @rawlines = ();
1199c2fdda0dSAndy Whitcroftmy @lines = ();
12003705ce5bSJoe Perchesmy @fixed = ();
1201d752fcc8SJoe Perchesmy @fixed_inserted = ();
1202d752fcc8SJoe Perchesmy @fixed_deleted = ();
1203194f66fcSJoe Perchesmy $fixlinenr = -1;
1204194f66fcSJoe Perches
12054a593c34SDu, Changbin# If input is git commits, extract all commits from the commit expressions.
12064a593c34SDu, Changbin# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
12070f7f635bSJoe Perchesdie "$P: No git repository found\n" if ($git && !-e "$gitroot");
12084a593c34SDu, Changbin
12094a593c34SDu, Changbinif ($git) {
12104a593c34SDu, Changbin	my @commits = ();
12110dea9f1eSJoe Perches	foreach my $commit_expr (@ARGV) {
12124a593c34SDu, Changbin		my $git_range;
121328898fd1SJoe Perches		if ($commit_expr =~ m/^(.*)-(\d+)$/) {
121428898fd1SJoe Perches			$git_range = "-$2 $1";
12154a593c34SDu, Changbin		} elsif ($commit_expr =~ m/\.\./) {
12164a593c34SDu, Changbin			$git_range = "$commit_expr";
12174a593c34SDu, Changbin		} else {
12180dea9f1eSJoe Perches			$git_range = "-1 $commit_expr";
12190dea9f1eSJoe Perches		}
1220dbbf869dSJoe Perches		my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
12210dea9f1eSJoe Perches		foreach my $line (split(/\n/, $lines)) {
122228898fd1SJoe Perches			$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
122328898fd1SJoe Perches			next if (!defined($1) || !defined($2));
12240dea9f1eSJoe Perches			my $sha1 = $1;
12250dea9f1eSJoe Perches			my $subject = $2;
12260dea9f1eSJoe Perches			unshift(@commits, $sha1);
12270dea9f1eSJoe Perches			$git_commits{$sha1} = $subject;
12284a593c34SDu, Changbin		}
12294a593c34SDu, Changbin	}
12304a593c34SDu, Changbin	die "$P: no git commits after extraction!\n" if (@commits == 0);
12314a593c34SDu, Changbin	@ARGV = @commits;
12324a593c34SDu, Changbin}
12334a593c34SDu, Changbin
1234c2fdda0dSAndy Whitcroftmy $vname;
123598005e8cSVadim Bendebury$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
12366c72ffaaSAndy Whitcroftfor my $filename (@ARGV) {
123721caa13cSAndy Whitcroft	my $FILE;
1238f5f61325SJoe Perches	my $is_git_file = git_is_single_file($filename);
1239f5f61325SJoe Perches	my $oldfile = $file;
1240f5f61325SJoe Perches	$file = 1 if ($is_git_file);
12414a593c34SDu, Changbin	if ($git) {
12424a593c34SDu, Changbin		open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
12434a593c34SDu, Changbin			die "$P: $filename: git format-patch failed - $!\n";
12444a593c34SDu, Changbin	} elsif ($file) {
124521caa13cSAndy Whitcroft		open($FILE, '-|', "diff -u /dev/null $filename") ||
12466c72ffaaSAndy Whitcroft			die "$P: $filename: diff failed - $!\n";
124721caa13cSAndy Whitcroft	} elsif ($filename eq '-') {
124821caa13cSAndy Whitcroft		open($FILE, '<&STDIN');
12496c72ffaaSAndy Whitcroft	} else {
125021caa13cSAndy Whitcroft		open($FILE, '<', "$filename") ||
12516c72ffaaSAndy Whitcroft			die "$P: $filename: open failed - $!\n";
12526c72ffaaSAndy Whitcroft	}
1253c2fdda0dSAndy Whitcroft	if ($filename eq '-') {
1254c2fdda0dSAndy Whitcroft		$vname = 'Your patch';
12554a593c34SDu, Changbin	} elsif ($git) {
12560dea9f1eSJoe Perches		$vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
1257c2fdda0dSAndy Whitcroft	} else {
1258c2fdda0dSAndy Whitcroft		$vname = $filename;
1259c2fdda0dSAndy Whitcroft	}
126021caa13cSAndy Whitcroft	while (<$FILE>) {
12610a920b5bSAndy Whitcroft		chomp;
126200df344fSAndy Whitcroft		push(@rawlines, $_);
1263c7f574d0SGeert Uytterhoeven		$vname = qq("$1") if ($filename eq '-' && $_ =~ m/^Subject:\s+(.+)/i);
12646c72ffaaSAndy Whitcroft	}
126521caa13cSAndy Whitcroft	close($FILE);
1266d8469f16SJoe Perches
1267d8469f16SJoe Perches	if ($#ARGV > 0 && $quiet == 0) {
1268d8469f16SJoe Perches		print '-' x length($vname) . "\n";
1269d8469f16SJoe Perches		print "$vname\n";
1270d8469f16SJoe Perches		print '-' x length($vname) . "\n";
1271d8469f16SJoe Perches	}
1272d8469f16SJoe Perches
1273c2fdda0dSAndy Whitcroft	if (!process($filename)) {
12740a920b5bSAndy Whitcroft		$exit = 1;
12750a920b5bSAndy Whitcroft	}
127600df344fSAndy Whitcroft	@rawlines = ();
127713214adfSAndy Whitcroft	@lines = ();
12783705ce5bSJoe Perches	@fixed = ();
1279d752fcc8SJoe Perches	@fixed_inserted = ();
1280d752fcc8SJoe Perches	@fixed_deleted = ();
1281194f66fcSJoe Perches	$fixlinenr = -1;
1282485ff23eSAlex Dowad	@modifierListFile = ();
1283485ff23eSAlex Dowad	@typeListFile = ();
1284485ff23eSAlex Dowad	build_types();
1285f5f61325SJoe Perches	$file = $oldfile if ($is_git_file);
12860a920b5bSAndy Whitcroft}
12870a920b5bSAndy Whitcroft
1288d8469f16SJoe Perchesif (!$quiet) {
12893c816e49SJoe Perches	hash_show_words(\%use_type, "Used");
12903c816e49SJoe Perches	hash_show_words(\%ignore_type, "Ignored");
12913c816e49SJoe Perches
12925b57980dSJoe Perches	if (!$perl_version_ok) {
1293d8469f16SJoe Perches		print << "EOM"
1294d8469f16SJoe Perches
1295d8469f16SJoe PerchesNOTE: perl $^V is not modern enough to detect all possible issues.
12965b57980dSJoe Perches      An upgrade to at least perl $minimum_perl_version is suggested.
1297d8469f16SJoe PerchesEOM
1298d8469f16SJoe Perches	}
1299d8469f16SJoe Perches	if ($exit) {
1300d8469f16SJoe Perches		print << "EOM"
1301d8469f16SJoe Perches
1302d8469f16SJoe PerchesNOTE: If any of the errors are false positives, please report
1303d8469f16SJoe Perches      them to the maintainer, see CHECKPATCH in MAINTAINERS.
1304d8469f16SJoe PerchesEOM
1305d8469f16SJoe Perches	}
1306d8469f16SJoe Perches}
1307d8469f16SJoe Perches
13080a920b5bSAndy Whitcroftexit($exit);
13090a920b5bSAndy Whitcroft
13100a920b5bSAndy Whitcroftsub top_of_kernel_tree {
13116c72ffaaSAndy Whitcroft	my ($root) = @_;
13126c72ffaaSAndy Whitcroft
13136c72ffaaSAndy Whitcroft	my @tree_check = (
13146c72ffaaSAndy Whitcroft		"COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
13156c72ffaaSAndy Whitcroft		"README", "Documentation", "arch", "include", "drivers",
13166c72ffaaSAndy Whitcroft		"fs", "init", "ipc", "kernel", "lib", "scripts",
13176c72ffaaSAndy Whitcroft	);
13186c72ffaaSAndy Whitcroft
13196c72ffaaSAndy Whitcroft	foreach my $check (@tree_check) {
13206c72ffaaSAndy Whitcroft		if (! -e $root . '/' . $check) {
13210a920b5bSAndy Whitcroft			return 0;
13220a920b5bSAndy Whitcroft		}
13236c72ffaaSAndy Whitcroft	}
13246c72ffaaSAndy Whitcroft	return 1;
13256c72ffaaSAndy Whitcroft}
13260a920b5bSAndy Whitcroft
132720112475SJoe Perchessub parse_email {
132820112475SJoe Perches	my ($formatted_email) = @_;
132920112475SJoe Perches
133020112475SJoe Perches	my $name = "";
1331fccaebf0SDwaipayan Ray	my $quoted = "";
1332dfa05c28SJoe Perches	my $name_comment = "";
133320112475SJoe Perches	my $address = "";
133420112475SJoe Perches	my $comment = "";
133520112475SJoe Perches
133620112475SJoe Perches	if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) {
133720112475SJoe Perches		$name = $1;
133820112475SJoe Perches		$address = $2;
133920112475SJoe Perches		$comment = $3 if defined $3;
134020112475SJoe Perches	} elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) {
134120112475SJoe Perches		$address = $1;
134220112475SJoe Perches		$comment = $2 if defined $2;
134320112475SJoe Perches	} elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
134420112475SJoe Perches		$address = $1;
134520112475SJoe Perches		$comment = $2 if defined $2;
134685e12066SJoe Perches		$formatted_email =~ s/\Q$address\E.*$//;
134720112475SJoe Perches		$name = $formatted_email;
13483705ce5bSJoe Perches		$name = trim($name);
134920112475SJoe Perches		$name =~ s/^\"|\"$//g;
135020112475SJoe Perches		# If there's a name left after stripping spaces and
135120112475SJoe Perches		# leading quotes, and the address doesn't have both
135220112475SJoe Perches		# leading and trailing angle brackets, the address
135320112475SJoe Perches		# is invalid. ie:
135420112475SJoe Perches		#   "joe smith [email protected]" bad
135520112475SJoe Perches		#   "joe smith <[email protected]" bad
135620112475SJoe Perches		if ($name ne "" && $address !~ /^<[^>]+>$/) {
135720112475SJoe Perches			$name = "";
135820112475SJoe Perches			$address = "";
135920112475SJoe Perches			$comment = "";
136020112475SJoe Perches		}
136120112475SJoe Perches	}
136220112475SJoe Perches
1363fccaebf0SDwaipayan Ray	# Extract comments from names excluding quoted parts
1364fccaebf0SDwaipayan Ray	# "John D. (Doe)" - Do not extract
1365fccaebf0SDwaipayan Ray	if ($name =~ s/\"(.+)\"//) {
1366fccaebf0SDwaipayan Ray		$quoted = $1;
1367dfa05c28SJoe Perches	}
1368fccaebf0SDwaipayan Ray	while ($name =~ s/\s*($balanced_parens)\s*/ /) {
1369fccaebf0SDwaipayan Ray		$name_comment .= trim($1);
1370fccaebf0SDwaipayan Ray	}
1371fccaebf0SDwaipayan Ray	$name =~ s/^[ \"]+|[ \"]+$//g;
1372fccaebf0SDwaipayan Ray	$name = trim("$quoted $name");
1373fccaebf0SDwaipayan Ray
13743705ce5bSJoe Perches	$address = trim($address);
137520112475SJoe Perches	$address =~ s/^\<|\>$//g;
1376fccaebf0SDwaipayan Ray	$comment = trim($comment);
137720112475SJoe Perches
137820112475SJoe Perches	if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
137920112475SJoe Perches		$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
138020112475SJoe Perches		$name = "\"$name\"";
138120112475SJoe Perches	}
138220112475SJoe Perches
1383dfa05c28SJoe Perches	return ($name, $name_comment, $address, $comment);
138420112475SJoe Perches}
138520112475SJoe Perches
138620112475SJoe Perchessub format_email {
138748ca2d8aSDwaipayan Ray	my ($name, $name_comment, $address, $comment) = @_;
138820112475SJoe Perches
138920112475SJoe Perches	my $formatted_email;
139020112475SJoe Perches
1391fccaebf0SDwaipayan Ray	$name =~ s/^[ \"]+|[ \"]+$//g;
13923705ce5bSJoe Perches	$address = trim($address);
1393fccaebf0SDwaipayan Ray	$address =~ s/(?:\.|\,|\")+$//; ##trailing commas, dots or quotes
139420112475SJoe Perches
139520112475SJoe Perches	if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
139620112475SJoe Perches		$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
139720112475SJoe Perches		$name = "\"$name\"";
139820112475SJoe Perches	}
139920112475SJoe Perches
1400fccaebf0SDwaipayan Ray	$name_comment = trim($name_comment);
1401fccaebf0SDwaipayan Ray	$name_comment = " $name_comment" if ($name_comment ne "");
1402fccaebf0SDwaipayan Ray	$comment = trim($comment);
1403fccaebf0SDwaipayan Ray	$comment = " $comment" if ($comment ne "");
1404fccaebf0SDwaipayan Ray
140520112475SJoe Perches	if ("$name" eq "") {
140620112475SJoe Perches		$formatted_email = "$address";
140720112475SJoe Perches	} else {
140848ca2d8aSDwaipayan Ray		$formatted_email = "$name$name_comment <$address>";
140920112475SJoe Perches	}
141048ca2d8aSDwaipayan Ray	$formatted_email .= "$comment";
141120112475SJoe Perches	return $formatted_email;
141220112475SJoe Perches}
141320112475SJoe Perches
1414dfa05c28SJoe Perchessub reformat_email {
1415dfa05c28SJoe Perches	my ($email) = @_;
1416dfa05c28SJoe Perches
1417dfa05c28SJoe Perches	my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
141848ca2d8aSDwaipayan Ray	return format_email($email_name, $name_comment, $email_address, $comment);
1419dfa05c28SJoe Perches}
1420dfa05c28SJoe Perches
1421dfa05c28SJoe Perchessub same_email_addresses {
1422fccaebf0SDwaipayan Ray	my ($email1, $email2) = @_;
1423dfa05c28SJoe Perches
1424dfa05c28SJoe Perches	my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1);
1425dfa05c28SJoe Perches	my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2);
1426dfa05c28SJoe Perches
142748ca2d8aSDwaipayan Ray	return $email1_name eq $email2_name &&
142848ca2d8aSDwaipayan Ray	       $email1_address eq $email2_address &&
142948ca2d8aSDwaipayan Ray	       $name1_comment eq $name2_comment &&
143048ca2d8aSDwaipayan Ray	       $comment1 eq $comment2;
143148ca2d8aSDwaipayan Ray}
1432dfa05c28SJoe Perches
1433d311cd44SJoe Perchessub which {
1434d311cd44SJoe Perches	my ($bin) = @_;
1435d311cd44SJoe Perches
1436d311cd44SJoe Perches	foreach my $path (split(/:/, $ENV{PATH})) {
1437d311cd44SJoe Perches		if (-e "$path/$bin") {
1438d311cd44SJoe Perches			return "$path/$bin";
1439d311cd44SJoe Perches		}
1440d311cd44SJoe Perches	}
1441d311cd44SJoe Perches
1442d311cd44SJoe Perches	return "";
1443d311cd44SJoe Perches}
1444d311cd44SJoe Perches
1445000d1cc1SJoe Perchessub which_conf {
1446000d1cc1SJoe Perches	my ($conf) = @_;
1447000d1cc1SJoe Perches
1448000d1cc1SJoe Perches	foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
1449000d1cc1SJoe Perches		if (-e "$path/$conf") {
1450000d1cc1SJoe Perches			return "$path/$conf";
1451000d1cc1SJoe Perches		}
1452000d1cc1SJoe Perches	}
1453000d1cc1SJoe Perches
1454000d1cc1SJoe Perches	return "";
1455000d1cc1SJoe Perches}
1456000d1cc1SJoe Perches
14570a920b5bSAndy Whitcroftsub expand_tabs {
14580a920b5bSAndy Whitcroft	my ($str) = @_;
14590a920b5bSAndy Whitcroft
14600a920b5bSAndy Whitcroft	my $res = '';
14610a920b5bSAndy Whitcroft	my $n = 0;
14620a920b5bSAndy Whitcroft	for my $c (split(//, $str)) {
14630a920b5bSAndy Whitcroft		if ($c eq "\t") {
14640a920b5bSAndy Whitcroft			$res .= ' ';
14650a920b5bSAndy Whitcroft			$n++;
1466713a09deSAntonio Borneo			for (; ($n % $tabsize) != 0; $n++) {
14670a920b5bSAndy Whitcroft				$res .= ' ';
14680a920b5bSAndy Whitcroft			}
14690a920b5bSAndy Whitcroft			next;
14700a920b5bSAndy Whitcroft		}
14710a920b5bSAndy Whitcroft		$res .= $c;
14720a920b5bSAndy Whitcroft		$n++;
14730a920b5bSAndy Whitcroft	}
14740a920b5bSAndy Whitcroft
14750a920b5bSAndy Whitcroft	return $res;
14760a920b5bSAndy Whitcroft}
14776c72ffaaSAndy Whitcroftsub copy_spacing {
1478773647a0SAndy Whitcroft	(my $res = shift) =~ tr/\t/ /c;
14796c72ffaaSAndy Whitcroft	return $res;
14806c72ffaaSAndy Whitcroft}
14810a920b5bSAndy Whitcroft
14824a0df2efSAndy Whitcroftsub line_stats {
14834a0df2efSAndy Whitcroft	my ($line) = @_;
14844a0df2efSAndy Whitcroft
14854a0df2efSAndy Whitcroft	# Drop the diff line leader and expand tabs
14864a0df2efSAndy Whitcroft	$line =~ s/^.//;
14874a0df2efSAndy Whitcroft	$line = expand_tabs($line);
14884a0df2efSAndy Whitcroft
14894a0df2efSAndy Whitcroft	# Pick the indent from the front of the line.
14904a0df2efSAndy Whitcroft	my ($white) = ($line =~ /^(\s*)/);
14914a0df2efSAndy Whitcroft
14924a0df2efSAndy Whitcroft	return (length($line), length($white));
14934a0df2efSAndy Whitcroft}
14944a0df2efSAndy Whitcroft
1495773647a0SAndy Whitcroftmy $sanitise_quote = '';
1496773647a0SAndy Whitcroft
1497773647a0SAndy Whitcroftsub sanitise_line_reset {
1498773647a0SAndy Whitcroft	my ($in_comment) = @_;
1499773647a0SAndy Whitcroft
1500773647a0SAndy Whitcroft	if ($in_comment) {
1501773647a0SAndy Whitcroft		$sanitise_quote = '*/';
1502773647a0SAndy Whitcroft	} else {
1503773647a0SAndy Whitcroft		$sanitise_quote = '';
1504773647a0SAndy Whitcroft	}
1505773647a0SAndy Whitcroft}
150600df344fSAndy Whitcroftsub sanitise_line {
150700df344fSAndy Whitcroft	my ($line) = @_;
150800df344fSAndy Whitcroft
150900df344fSAndy Whitcroft	my $res = '';
151000df344fSAndy Whitcroft	my $l = '';
151100df344fSAndy Whitcroft
1512c2fdda0dSAndy Whitcroft	my $qlen = 0;
1513773647a0SAndy Whitcroft	my $off = 0;
1514773647a0SAndy Whitcroft	my $c;
151500df344fSAndy Whitcroft
1516773647a0SAndy Whitcroft	# Always copy over the diff marker.
1517773647a0SAndy Whitcroft	$res = substr($line, 0, 1);
1518773647a0SAndy Whitcroft
1519773647a0SAndy Whitcroft	for ($off = 1; $off < length($line); $off++) {
1520773647a0SAndy Whitcroft		$c = substr($line, $off, 1);
1521773647a0SAndy Whitcroft
15228d2e11b2SClaudio Fontana		# Comments we are whacking completely including the begin
1523773647a0SAndy Whitcroft		# and end, all to $;.
1524773647a0SAndy Whitcroft		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
1525773647a0SAndy Whitcroft			$sanitise_quote = '*/';
1526773647a0SAndy Whitcroft
1527773647a0SAndy Whitcroft			substr($res, $off, 2, "$;$;");
1528773647a0SAndy Whitcroft			$off++;
152900df344fSAndy Whitcroft			next;
1530773647a0SAndy Whitcroft		}
153181bc0e02SAndy Whitcroft		if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
1532773647a0SAndy Whitcroft			$sanitise_quote = '';
1533773647a0SAndy Whitcroft			substr($res, $off, 2, "$;$;");
1534773647a0SAndy Whitcroft			$off++;
1535773647a0SAndy Whitcroft			next;
1536773647a0SAndy Whitcroft		}
1537113f04a8SDaniel Walker		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
1538113f04a8SDaniel Walker			$sanitise_quote = '//';
1539113f04a8SDaniel Walker
1540113f04a8SDaniel Walker			substr($res, $off, 2, $sanitise_quote);
1541113f04a8SDaniel Walker			$off++;
1542113f04a8SDaniel Walker			next;
1543113f04a8SDaniel Walker		}
1544773647a0SAndy Whitcroft
1545773647a0SAndy Whitcroft		# A \ in a string means ignore the next character.
1546773647a0SAndy Whitcroft		if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
1547773647a0SAndy Whitcroft		    $c eq "\\") {
1548773647a0SAndy Whitcroft			substr($res, $off, 2, 'XX');
1549773647a0SAndy Whitcroft			$off++;
1550773647a0SAndy Whitcroft			next;
1551773647a0SAndy Whitcroft		}
1552773647a0SAndy Whitcroft		# Regular quotes.
1553773647a0SAndy Whitcroft		if ($c eq "'" || $c eq '"') {
1554773647a0SAndy Whitcroft			if ($sanitise_quote eq '') {
1555773647a0SAndy Whitcroft				$sanitise_quote = $c;
1556773647a0SAndy Whitcroft
1557773647a0SAndy Whitcroft				substr($res, $off, 1, $c);
1558773647a0SAndy Whitcroft				next;
1559773647a0SAndy Whitcroft			} elsif ($sanitise_quote eq $c) {
1560773647a0SAndy Whitcroft				$sanitise_quote = '';
156100df344fSAndy Whitcroft			}
156200df344fSAndy Whitcroft		}
1563773647a0SAndy Whitcroft
1564fae17daeSAndy Whitcroft		#print "c<$c> SQ<$sanitise_quote>\n";
1565773647a0SAndy Whitcroft		if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
1566773647a0SAndy Whitcroft			substr($res, $off, 1, $;);
1567113f04a8SDaniel Walker		} elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
1568113f04a8SDaniel Walker			substr($res, $off, 1, $;);
1569773647a0SAndy Whitcroft		} elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
1570773647a0SAndy Whitcroft			substr($res, $off, 1, 'X');
157100df344fSAndy Whitcroft		} else {
1572773647a0SAndy Whitcroft			substr($res, $off, 1, $c);
157300df344fSAndy Whitcroft		}
1574c2fdda0dSAndy Whitcroft	}
1575c2fdda0dSAndy Whitcroft
1576113f04a8SDaniel Walker	if ($sanitise_quote eq '//') {
1577113f04a8SDaniel Walker		$sanitise_quote = '';
1578113f04a8SDaniel Walker	}
1579113f04a8SDaniel Walker
1580c2fdda0dSAndy Whitcroft	# The pathname on a #include may be surrounded by '<' and '>'.
1581c45dcabdSAndy Whitcroft	if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
1582c2fdda0dSAndy Whitcroft		my $clean = 'X' x length($1);
1583c2fdda0dSAndy Whitcroft		$res =~ s@\<.*\>@<$clean>@;
1584c2fdda0dSAndy Whitcroft
1585c2fdda0dSAndy Whitcroft	# The whole of a #error is a string.
1586c45dcabdSAndy Whitcroft	} elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
1587c2fdda0dSAndy Whitcroft		my $clean = 'X' x length($1);
1588c45dcabdSAndy Whitcroft		$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
1589c2fdda0dSAndy Whitcroft	}
1590c2fdda0dSAndy Whitcroft
1591dadf680dSJoe Perches	if ($allow_c99_comments && $res =~ m@(//.*$)@) {
1592dadf680dSJoe Perches		my $match = $1;
1593dadf680dSJoe Perches		$res =~ s/\Q$match\E/"$;" x length($match)/e;
1594dadf680dSJoe Perches	}
1595dadf680dSJoe Perches
159600df344fSAndy Whitcroft	return $res;
159700df344fSAndy Whitcroft}
159800df344fSAndy Whitcroft
1599a6962d72SJoe Perchessub get_quoted_string {
1600a6962d72SJoe Perches	my ($line, $rawline) = @_;
1601a6962d72SJoe Perches
1602478b1799SJoe Perches	return "" if (!defined($line) || !defined($rawline));
160333acb54aSJoe Perches	return "" if ($line !~ m/($String)/g);
1604a6962d72SJoe Perches	return substr($rawline, $-[0], $+[0] - $-[0]);
1605a6962d72SJoe Perches}
1606a6962d72SJoe Perches
16078905a67cSAndy Whitcroftsub ctx_statement_block {
16088905a67cSAndy Whitcroft	my ($linenr, $remain, $off) = @_;
16098905a67cSAndy Whitcroft	my $line = $linenr - 1;
16108905a67cSAndy Whitcroft	my $blk = '';
16118905a67cSAndy Whitcroft	my $soff = $off;
16128905a67cSAndy Whitcroft	my $coff = $off - 1;
1613773647a0SAndy Whitcroft	my $coff_set = 0;
16148905a67cSAndy Whitcroft
161513214adfSAndy Whitcroft	my $loff = 0;
161613214adfSAndy Whitcroft
16178905a67cSAndy Whitcroft	my $type = '';
16188905a67cSAndy Whitcroft	my $level = 0;
1619a2750645SAndy Whitcroft	my @stack = ();
1620cf655043SAndy Whitcroft	my $p;
16218905a67cSAndy Whitcroft	my $c;
16228905a67cSAndy Whitcroft	my $len = 0;
162313214adfSAndy Whitcroft
162413214adfSAndy Whitcroft	my $remainder;
16258905a67cSAndy Whitcroft	while (1) {
1626a2750645SAndy Whitcroft		@stack = (['', 0]) if ($#stack == -1);
1627a2750645SAndy Whitcroft
1628773647a0SAndy Whitcroft		#warn "CSB: blk<$blk> remain<$remain>\n";
16298905a67cSAndy Whitcroft		# If we are about to drop off the end, pull in more
16308905a67cSAndy Whitcroft		# context.
16318905a67cSAndy Whitcroft		if ($off >= $len) {
16328905a67cSAndy Whitcroft			for (; $remain > 0; $line++) {
1633dea33496SAndy Whitcroft				last if (!defined $lines[$line]);
1634c2fdda0dSAndy Whitcroft				next if ($lines[$line] =~ /^-/);
16358905a67cSAndy Whitcroft				$remain--;
163613214adfSAndy Whitcroft				$loff = $len;
1637c2fdda0dSAndy Whitcroft				$blk .= $lines[$line] . "\n";
16388905a67cSAndy Whitcroft				$len = length($blk);
16398905a67cSAndy Whitcroft				$line++;
16408905a67cSAndy Whitcroft				last;
16418905a67cSAndy Whitcroft			}
16428905a67cSAndy Whitcroft			# Bail if there is no further context.
16438905a67cSAndy Whitcroft			#warn "CSB: blk<$blk> off<$off> len<$len>\n";
164413214adfSAndy Whitcroft			if ($off >= $len) {
16458905a67cSAndy Whitcroft				last;
16468905a67cSAndy Whitcroft			}
1647f74bd194SAndy Whitcroft			if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) {
1648f74bd194SAndy Whitcroft				$level++;
1649f74bd194SAndy Whitcroft				$type = '#';
1650f74bd194SAndy Whitcroft			}
16518905a67cSAndy Whitcroft		}
1652cf655043SAndy Whitcroft		$p = $c;
16538905a67cSAndy Whitcroft		$c = substr($blk, $off, 1);
165413214adfSAndy Whitcroft		$remainder = substr($blk, $off);
16558905a67cSAndy Whitcroft
1656773647a0SAndy Whitcroft		#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
16574635f4fbSAndy Whitcroft
16584635f4fbSAndy Whitcroft		# Handle nested #if/#else.
16594635f4fbSAndy Whitcroft		if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
16604635f4fbSAndy Whitcroft			push(@stack, [ $type, $level ]);
16614635f4fbSAndy Whitcroft		} elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
16624635f4fbSAndy Whitcroft			($type, $level) = @{$stack[$#stack - 1]};
16634635f4fbSAndy Whitcroft		} elsif ($remainder =~ /^#\s*endif\b/) {
16644635f4fbSAndy Whitcroft			($type, $level) = @{pop(@stack)};
16654635f4fbSAndy Whitcroft		}
16664635f4fbSAndy Whitcroft
16678905a67cSAndy Whitcroft		# Statement ends at the ';' or a close '}' at the
16688905a67cSAndy Whitcroft		# outermost level.
16698905a67cSAndy Whitcroft		if ($level == 0 && $c eq ';') {
16708905a67cSAndy Whitcroft			last;
16718905a67cSAndy Whitcroft		}
16728905a67cSAndy Whitcroft
167313214adfSAndy Whitcroft		# An else is really a conditional as long as its not else if
1674773647a0SAndy Whitcroft		if ($level == 0 && $coff_set == 0 &&
1675773647a0SAndy Whitcroft				(!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
1676773647a0SAndy Whitcroft				$remainder =~ /^(else)(?:\s|{)/ &&
1677773647a0SAndy Whitcroft				$remainder !~ /^else\s+if\b/) {
1678773647a0SAndy Whitcroft			$coff = $off + length($1) - 1;
1679773647a0SAndy Whitcroft			$coff_set = 1;
1680773647a0SAndy Whitcroft			#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
1681773647a0SAndy Whitcroft			#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
168213214adfSAndy Whitcroft		}
168313214adfSAndy Whitcroft
16848905a67cSAndy Whitcroft		if (($type eq '' || $type eq '(') && $c eq '(') {
16858905a67cSAndy Whitcroft			$level++;
16868905a67cSAndy Whitcroft			$type = '(';
16878905a67cSAndy Whitcroft		}
16888905a67cSAndy Whitcroft		if ($type eq '(' && $c eq ')') {
16898905a67cSAndy Whitcroft			$level--;
16908905a67cSAndy Whitcroft			$type = ($level != 0)? '(' : '';
16918905a67cSAndy Whitcroft
16928905a67cSAndy Whitcroft			if ($level == 0 && $coff < $soff) {
16938905a67cSAndy Whitcroft				$coff = $off;
1694773647a0SAndy Whitcroft				$coff_set = 1;
1695773647a0SAndy Whitcroft				#warn "CSB: mark coff<$coff>\n";
16968905a67cSAndy Whitcroft			}
16978905a67cSAndy Whitcroft		}
16988905a67cSAndy Whitcroft		if (($type eq '' || $type eq '{') && $c eq '{') {
16998905a67cSAndy Whitcroft			$level++;
17008905a67cSAndy Whitcroft			$type = '{';
17018905a67cSAndy Whitcroft		}
17028905a67cSAndy Whitcroft		if ($type eq '{' && $c eq '}') {
17038905a67cSAndy Whitcroft			$level--;
17048905a67cSAndy Whitcroft			$type = ($level != 0)? '{' : '';
17058905a67cSAndy Whitcroft
17068905a67cSAndy Whitcroft			if ($level == 0) {
1707b998e001SPatrick Pannuto				if (substr($blk, $off + 1, 1) eq ';') {
1708b998e001SPatrick Pannuto					$off++;
1709b998e001SPatrick Pannuto				}
17108905a67cSAndy Whitcroft				last;
17118905a67cSAndy Whitcroft			}
17128905a67cSAndy Whitcroft		}
1713f74bd194SAndy Whitcroft		# Preprocessor commands end at the newline unless escaped.
1714f74bd194SAndy Whitcroft		if ($type eq '#' && $c eq "\n" && $p ne "\\") {
1715f74bd194SAndy Whitcroft			$level--;
1716f74bd194SAndy Whitcroft			$type = '';
1717f74bd194SAndy Whitcroft			$off++;
1718f74bd194SAndy Whitcroft			last;
1719f74bd194SAndy Whitcroft		}
17208905a67cSAndy Whitcroft		$off++;
17218905a67cSAndy Whitcroft	}
1722a3bb97a7SAndy Whitcroft	# We are truly at the end, so shuffle to the next line.
172313214adfSAndy Whitcroft	if ($off == $len) {
1724a3bb97a7SAndy Whitcroft		$loff = $len + 1;
172513214adfSAndy Whitcroft		$line++;
172613214adfSAndy Whitcroft		$remain--;
172713214adfSAndy Whitcroft	}
17288905a67cSAndy Whitcroft
17298905a67cSAndy Whitcroft	my $statement = substr($blk, $soff, $off - $soff + 1);
17308905a67cSAndy Whitcroft	my $condition = substr($blk, $soff, $coff - $soff + 1);
17318905a67cSAndy Whitcroft
17328905a67cSAndy Whitcroft	#warn "STATEMENT<$statement>\n";
17338905a67cSAndy Whitcroft	#warn "CONDITION<$condition>\n";
17348905a67cSAndy Whitcroft
1735773647a0SAndy Whitcroft	#print "coff<$coff> soff<$off> loff<$loff>\n";
173613214adfSAndy Whitcroft
173713214adfSAndy Whitcroft	return ($statement, $condition,
173813214adfSAndy Whitcroft			$line, $remain + 1, $off - $loff + 1, $level);
173913214adfSAndy Whitcroft}
174013214adfSAndy Whitcroft
1741cf655043SAndy Whitcroftsub statement_lines {
1742cf655043SAndy Whitcroft	my ($stmt) = @_;
1743cf655043SAndy Whitcroft
1744cf655043SAndy Whitcroft	# Strip the diff line prefixes and rip blank lines at start and end.
1745cf655043SAndy Whitcroft	$stmt =~ s/(^|\n)./$1/g;
1746cf655043SAndy Whitcroft	$stmt =~ s/^\s*//;
1747cf655043SAndy Whitcroft	$stmt =~ s/\s*$//;
1748cf655043SAndy Whitcroft
1749cf655043SAndy Whitcroft	my @stmt_lines = ($stmt =~ /\n/g);
1750cf655043SAndy Whitcroft
1751cf655043SAndy Whitcroft	return $#stmt_lines + 2;
1752cf655043SAndy Whitcroft}
1753cf655043SAndy Whitcroft
1754cf655043SAndy Whitcroftsub statement_rawlines {
1755cf655043SAndy Whitcroft	my ($stmt) = @_;
1756cf655043SAndy Whitcroft
1757cf655043SAndy Whitcroft	my @stmt_lines = ($stmt =~ /\n/g);
1758cf655043SAndy Whitcroft
1759cf655043SAndy Whitcroft	return $#stmt_lines + 2;
1760cf655043SAndy Whitcroft}
1761cf655043SAndy Whitcroft
1762cf655043SAndy Whitcroftsub statement_block_size {
1763cf655043SAndy Whitcroft	my ($stmt) = @_;
1764cf655043SAndy Whitcroft
1765cf655043SAndy Whitcroft	$stmt =~ s/(^|\n)./$1/g;
1766cf655043SAndy Whitcroft	$stmt =~ s/^\s*{//;
1767cf655043SAndy Whitcroft	$stmt =~ s/}\s*$//;
1768cf655043SAndy Whitcroft	$stmt =~ s/^\s*//;
1769cf655043SAndy Whitcroft	$stmt =~ s/\s*$//;
1770cf655043SAndy Whitcroft
1771cf655043SAndy Whitcroft	my @stmt_lines = ($stmt =~ /\n/g);
1772cf655043SAndy Whitcroft	my @stmt_statements = ($stmt =~ /;/g);
1773cf655043SAndy Whitcroft
1774cf655043SAndy Whitcroft	my $stmt_lines = $#stmt_lines + 2;
1775cf655043SAndy Whitcroft	my $stmt_statements = $#stmt_statements + 1;
1776cf655043SAndy Whitcroft
1777cf655043SAndy Whitcroft	if ($stmt_lines > $stmt_statements) {
1778cf655043SAndy Whitcroft		return $stmt_lines;
1779cf655043SAndy Whitcroft	} else {
1780cf655043SAndy Whitcroft		return $stmt_statements;
1781cf655043SAndy Whitcroft	}
1782cf655043SAndy Whitcroft}
1783cf655043SAndy Whitcroft
178413214adfSAndy Whitcroftsub ctx_statement_full {
178513214adfSAndy Whitcroft	my ($linenr, $remain, $off) = @_;
178613214adfSAndy Whitcroft	my ($statement, $condition, $level);
178713214adfSAndy Whitcroft
178813214adfSAndy Whitcroft	my (@chunks);
178913214adfSAndy Whitcroft
1790cf655043SAndy Whitcroft	# Grab the first conditional/block pair.
179113214adfSAndy Whitcroft	($statement, $condition, $linenr, $remain, $off, $level) =
179213214adfSAndy Whitcroft				ctx_statement_block($linenr, $remain, $off);
1793773647a0SAndy Whitcroft	#print "F: c<$condition> s<$statement> remain<$remain>\n";
179413214adfSAndy Whitcroft	push(@chunks, [ $condition, $statement ]);
1795cf655043SAndy Whitcroft	if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
1796cf655043SAndy Whitcroft		return ($level, $linenr, @chunks);
1797cf655043SAndy Whitcroft	}
1798cf655043SAndy Whitcroft
1799cf655043SAndy Whitcroft	# Pull in the following conditional/block pairs and see if they
1800cf655043SAndy Whitcroft	# could continue the statement.
1801cf655043SAndy Whitcroft	for (;;) {
180213214adfSAndy Whitcroft		($statement, $condition, $linenr, $remain, $off, $level) =
180313214adfSAndy Whitcroft				ctx_statement_block($linenr, $remain, $off);
1804cf655043SAndy Whitcroft		#print "C: c<$condition> s<$statement> remain<$remain>\n";
1805773647a0SAndy Whitcroft		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
1806cf655043SAndy Whitcroft		#print "C: push\n";
1807cf655043SAndy Whitcroft		push(@chunks, [ $condition, $statement ]);
180813214adfSAndy Whitcroft	}
180913214adfSAndy Whitcroft
181013214adfSAndy Whitcroft	return ($level, $linenr, @chunks);
18118905a67cSAndy Whitcroft}
18128905a67cSAndy Whitcroft
18134a0df2efSAndy Whitcroftsub ctx_block_get {
1814f0a594c1SAndy Whitcroft	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
18154a0df2efSAndy Whitcroft	my $line;
18164a0df2efSAndy Whitcroft	my $start = $linenr - 1;
18174a0df2efSAndy Whitcroft	my $blk = '';
18184a0df2efSAndy Whitcroft	my @o;
18194a0df2efSAndy Whitcroft	my @c;
18204a0df2efSAndy Whitcroft	my @res = ();
18214a0df2efSAndy Whitcroft
1822f0a594c1SAndy Whitcroft	my $level = 0;
18234635f4fbSAndy Whitcroft	my @stack = ($level);
182400df344fSAndy Whitcroft	for ($line = $start; $remain > 0; $line++) {
182500df344fSAndy Whitcroft		next if ($rawlines[$line] =~ /^-/);
182600df344fSAndy Whitcroft		$remain--;
182700df344fSAndy Whitcroft
182800df344fSAndy Whitcroft		$blk .= $rawlines[$line];
18294635f4fbSAndy Whitcroft
18304635f4fbSAndy Whitcroft		# Handle nested #if/#else.
183101464f30SAndy Whitcroft		if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
18324635f4fbSAndy Whitcroft			push(@stack, $level);
183301464f30SAndy Whitcroft		} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
18344635f4fbSAndy Whitcroft			$level = $stack[$#stack - 1];
183501464f30SAndy Whitcroft		} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
18364635f4fbSAndy Whitcroft			$level = pop(@stack);
18374635f4fbSAndy Whitcroft		}
18384635f4fbSAndy Whitcroft
183901464f30SAndy Whitcroft		foreach my $c (split(//, $lines[$line])) {
1840f0a594c1SAndy Whitcroft			##print "C<$c>L<$level><$open$close>O<$off>\n";
1841f0a594c1SAndy Whitcroft			if ($off > 0) {
1842f0a594c1SAndy Whitcroft				$off--;
1843f0a594c1SAndy Whitcroft				next;
1844f0a594c1SAndy Whitcroft			}
18454a0df2efSAndy Whitcroft
1846f0a594c1SAndy Whitcroft			if ($c eq $close && $level > 0) {
1847f0a594c1SAndy Whitcroft				$level--;
1848f0a594c1SAndy Whitcroft				last if ($level == 0);
1849f0a594c1SAndy Whitcroft			} elsif ($c eq $open) {
1850f0a594c1SAndy Whitcroft				$level++;
1851f0a594c1SAndy Whitcroft			}
1852f0a594c1SAndy Whitcroft		}
18534a0df2efSAndy Whitcroft
1854f0a594c1SAndy Whitcroft		if (!$outer || $level <= 1) {
185500df344fSAndy Whitcroft			push(@res, $rawlines[$line]);
18564a0df2efSAndy Whitcroft		}
18574a0df2efSAndy Whitcroft
1858f0a594c1SAndy Whitcroft		last if ($level == 0);
18594a0df2efSAndy Whitcroft	}
18604a0df2efSAndy Whitcroft
1861f0a594c1SAndy Whitcroft	return ($level, @res);
18624a0df2efSAndy Whitcroft}
18634a0df2efSAndy Whitcroftsub ctx_block_outer {
18644a0df2efSAndy Whitcroft	my ($linenr, $remain) = @_;
18654a0df2efSAndy Whitcroft
1866f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
1867f0a594c1SAndy Whitcroft	return @r;
18684a0df2efSAndy Whitcroft}
18694a0df2efSAndy Whitcroftsub ctx_block {
18704a0df2efSAndy Whitcroft	my ($linenr, $remain) = @_;
18714a0df2efSAndy Whitcroft
1872f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1873f0a594c1SAndy Whitcroft	return @r;
1874653d4876SAndy Whitcroft}
1875653d4876SAndy Whitcroftsub ctx_statement {
1876f0a594c1SAndy Whitcroft	my ($linenr, $remain, $off) = @_;
1877f0a594c1SAndy Whitcroft
1878f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1879f0a594c1SAndy Whitcroft	return @r;
1880f0a594c1SAndy Whitcroft}
1881f0a594c1SAndy Whitcroftsub ctx_block_level {
1882653d4876SAndy Whitcroft	my ($linenr, $remain) = @_;
1883653d4876SAndy Whitcroft
1884f0a594c1SAndy Whitcroft	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
18854a0df2efSAndy Whitcroft}
18869c0ca6f9SAndy Whitcroftsub ctx_statement_level {
18879c0ca6f9SAndy Whitcroft	my ($linenr, $remain, $off) = @_;
18889c0ca6f9SAndy Whitcroft
18899c0ca6f9SAndy Whitcroft	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
18909c0ca6f9SAndy Whitcroft}
18914a0df2efSAndy Whitcroft
18924a0df2efSAndy Whitcroftsub ctx_locate_comment {
18934a0df2efSAndy Whitcroft	my ($first_line, $end_line) = @_;
18944a0df2efSAndy Whitcroft
1895a55ee0ccSJoe Perches	# If c99 comment on the current line, or the line before or after
1896a55ee0ccSJoe Perches	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@^\+.*(//.*$)@);
1897a55ee0ccSJoe Perches	return $current_comment if (defined $current_comment);
1898a55ee0ccSJoe Perches	($current_comment) = ($rawlines[$end_line - 2] =~ m@^[\+ ].*(//.*$)@);
1899a55ee0ccSJoe Perches	return $current_comment if (defined $current_comment);
1900a55ee0ccSJoe Perches	($current_comment) = ($rawlines[$end_line] =~ m@^[\+ ].*(//.*$)@);
1901a55ee0ccSJoe Perches	return $current_comment if (defined $current_comment);
1902a55ee0ccSJoe Perches
19034a0df2efSAndy Whitcroft	# Catch a comment on the end of the line itself.
1904a55ee0ccSJoe Perches	($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
19054a0df2efSAndy Whitcroft	return $current_comment if (defined $current_comment);
19064a0df2efSAndy Whitcroft
19074a0df2efSAndy Whitcroft	# Look through the context and try and figure out if there is a
19084a0df2efSAndy Whitcroft	# comment.
19094a0df2efSAndy Whitcroft	my $in_comment = 0;
19104a0df2efSAndy Whitcroft	$current_comment = '';
19114a0df2efSAndy Whitcroft	for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
191200df344fSAndy Whitcroft		my $line = $rawlines[$linenr - 1];
191300df344fSAndy Whitcroft		#warn "           $line\n";
19144a0df2efSAndy Whitcroft		if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
19154a0df2efSAndy Whitcroft			$in_comment = 1;
19164a0df2efSAndy Whitcroft		}
19174a0df2efSAndy Whitcroft		if ($line =~ m@/\*@) {
19184a0df2efSAndy Whitcroft			$in_comment = 1;
19194a0df2efSAndy Whitcroft		}
19204a0df2efSAndy Whitcroft		if (!$in_comment && $current_comment ne '') {
19214a0df2efSAndy Whitcroft			$current_comment = '';
19224a0df2efSAndy Whitcroft		}
19234a0df2efSAndy Whitcroft		$current_comment .= $line . "\n" if ($in_comment);
19244a0df2efSAndy Whitcroft		if ($line =~ m@\*/@) {
19254a0df2efSAndy Whitcroft			$in_comment = 0;
19264a0df2efSAndy Whitcroft		}
19274a0df2efSAndy Whitcroft	}
19284a0df2efSAndy Whitcroft
19294a0df2efSAndy Whitcroft	chomp($current_comment);
19304a0df2efSAndy Whitcroft	return($current_comment);
19314a0df2efSAndy Whitcroft}
19324a0df2efSAndy Whitcroftsub ctx_has_comment {
19334a0df2efSAndy Whitcroft	my ($first_line, $end_line) = @_;
19344a0df2efSAndy Whitcroft	my $cmt = ctx_locate_comment($first_line, $end_line);
19354a0df2efSAndy Whitcroft
193600df344fSAndy Whitcroft	##print "LINE: $rawlines[$end_line - 1 ]\n";
19374a0df2efSAndy Whitcroft	##print "CMMT: $cmt\n";
19384a0df2efSAndy Whitcroft
19394a0df2efSAndy Whitcroft	return ($cmt ne '');
19404a0df2efSAndy Whitcroft}
19414a0df2efSAndy Whitcroft
19424d001e4dSAndy Whitcroftsub raw_line {
19434d001e4dSAndy Whitcroft	my ($linenr, $cnt) = @_;
19444d001e4dSAndy Whitcroft
19454d001e4dSAndy Whitcroft	my $offset = $linenr - 1;
19464d001e4dSAndy Whitcroft	$cnt++;
19474d001e4dSAndy Whitcroft
19484d001e4dSAndy Whitcroft	my $line;
19494d001e4dSAndy Whitcroft	while ($cnt) {
19504d001e4dSAndy Whitcroft		$line = $rawlines[$offset++];
19514d001e4dSAndy Whitcroft		next if (defined($line) && $line =~ /^-/);
19524d001e4dSAndy Whitcroft		$cnt--;
19534d001e4dSAndy Whitcroft	}
19544d001e4dSAndy Whitcroft
19554d001e4dSAndy Whitcroft	return $line;
19564d001e4dSAndy Whitcroft}
19574d001e4dSAndy Whitcroft
19582a9f9d85STobin C. Hardingsub get_stat_real {
19592a9f9d85STobin C. Harding	my ($linenr, $lc) = @_;
19602a9f9d85STobin C. Harding
19612a9f9d85STobin C. Harding	my $stat_real = raw_line($linenr, 0);
19622a9f9d85STobin C. Harding	for (my $count = $linenr + 1; $count <= $lc; $count++) {
19632a9f9d85STobin C. Harding		$stat_real = $stat_real . "\n" . raw_line($count, 0);
19642a9f9d85STobin C. Harding	}
19652a9f9d85STobin C. Harding
19662a9f9d85STobin C. Harding	return $stat_real;
19672a9f9d85STobin C. Harding}
19682a9f9d85STobin C. Harding
1969e3d95a2aSTobin C. Hardingsub get_stat_here {
1970e3d95a2aSTobin C. Harding	my ($linenr, $cnt, $here) = @_;
1971e3d95a2aSTobin C. Harding
1972e3d95a2aSTobin C. Harding	my $herectx = $here . "\n";
1973e3d95a2aSTobin C. Harding	for (my $n = 0; $n < $cnt; $n++) {
1974e3d95a2aSTobin C. Harding		$herectx .= raw_line($linenr, $n) . "\n";
1975e3d95a2aSTobin C. Harding	}
1976e3d95a2aSTobin C. Harding
1977e3d95a2aSTobin C. Harding	return $herectx;
1978e3d95a2aSTobin C. Harding}
1979e3d95a2aSTobin C. Harding
19800a920b5bSAndy Whitcroftsub cat_vet {
19810a920b5bSAndy Whitcroft	my ($vet) = @_;
19829c0ca6f9SAndy Whitcroft	my ($res, $coded);
19830a920b5bSAndy Whitcroft
19849c0ca6f9SAndy Whitcroft	$res = '';
19856c72ffaaSAndy Whitcroft	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
19866c72ffaaSAndy Whitcroft		$res .= $1;
19876c72ffaaSAndy Whitcroft		if ($2 ne '') {
19889c0ca6f9SAndy Whitcroft			$coded = sprintf("^%c", unpack('C', $2) + 64);
19896c72ffaaSAndy Whitcroft			$res .= $coded;
19906c72ffaaSAndy Whitcroft		}
19919c0ca6f9SAndy Whitcroft	}
19929c0ca6f9SAndy Whitcroft	$res =~ s/$/\$/;
19930a920b5bSAndy Whitcroft
19949c0ca6f9SAndy Whitcroft	return $res;
19950a920b5bSAndy Whitcroft}
19960a920b5bSAndy Whitcroft
1997c2fdda0dSAndy Whitcroftmy $av_preprocessor = 0;
1998cf655043SAndy Whitcroftmy $av_pending;
1999c2fdda0dSAndy Whitcroftmy @av_paren_type;
20001f65f947SAndy Whitcroftmy $av_pend_colon;
2001c2fdda0dSAndy Whitcroft
2002c2fdda0dSAndy Whitcroftsub annotate_reset {
2003c2fdda0dSAndy Whitcroft	$av_preprocessor = 0;
2004cf655043SAndy Whitcroft	$av_pending = '_';
2005cf655043SAndy Whitcroft	@av_paren_type = ('E');
20061f65f947SAndy Whitcroft	$av_pend_colon = 'O';
2007c2fdda0dSAndy Whitcroft}
2008c2fdda0dSAndy Whitcroft
20096c72ffaaSAndy Whitcroftsub annotate_values {
20106c72ffaaSAndy Whitcroft	my ($stream, $type) = @_;
20116c72ffaaSAndy Whitcroft
20126c72ffaaSAndy Whitcroft	my $res;
20131f65f947SAndy Whitcroft	my $var = '_' x length($stream);
20146c72ffaaSAndy Whitcroft	my $cur = $stream;
20156c72ffaaSAndy Whitcroft
2016c2fdda0dSAndy Whitcroft	print "$stream\n" if ($dbg_values > 1);
20176c72ffaaSAndy Whitcroft
20186c72ffaaSAndy Whitcroft	while (length($cur)) {
2019773647a0SAndy Whitcroft		@av_paren_type = ('E') if ($#av_paren_type < 0);
2020cf655043SAndy Whitcroft		print " <" . join('', @av_paren_type) .
2021171ae1a4SAndy Whitcroft				"> <$type> <$av_pending>" if ($dbg_values > 1);
20226c72ffaaSAndy Whitcroft		if ($cur =~ /^(\s+)/o) {
2023c2fdda0dSAndy Whitcroft			print "WS($1)\n" if ($dbg_values > 1);
2024c2fdda0dSAndy Whitcroft			if ($1 =~ /\n/ && $av_preprocessor) {
2025cf655043SAndy Whitcroft				$type = pop(@av_paren_type);
2026c2fdda0dSAndy Whitcroft				$av_preprocessor = 0;
20276c72ffaaSAndy Whitcroft			}
20286c72ffaaSAndy Whitcroft
2029c023e473SFlorian Mickler		} elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
20309446ef56SAndy Whitcroft			print "CAST($1)\n" if ($dbg_values > 1);
20319446ef56SAndy Whitcroft			push(@av_paren_type, $type);
2032addcdceaSAndy Whitcroft			$type = 'c';
20339446ef56SAndy Whitcroft
2034e91b6e26SAndy Whitcroft		} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
2035c2fdda0dSAndy Whitcroft			print "DECLARE($1)\n" if ($dbg_values > 1);
20366c72ffaaSAndy Whitcroft			$type = 'T';
20376c72ffaaSAndy Whitcroft
2038389a2fe5SAndy Whitcroft		} elsif ($cur =~ /^($Modifier)\s*/) {
2039389a2fe5SAndy Whitcroft			print "MODIFIER($1)\n" if ($dbg_values > 1);
2040389a2fe5SAndy Whitcroft			$type = 'T';
2041389a2fe5SAndy Whitcroft
2042c45dcabdSAndy Whitcroft		} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
2043171ae1a4SAndy Whitcroft			print "DEFINE($1,$2)\n" if ($dbg_values > 1);
2044c2fdda0dSAndy Whitcroft			$av_preprocessor = 1;
2045171ae1a4SAndy Whitcroft			push(@av_paren_type, $type);
2046171ae1a4SAndy Whitcroft			if ($2 ne '') {
2047cf655043SAndy Whitcroft				$av_pending = 'N';
2048171ae1a4SAndy Whitcroft			}
2049171ae1a4SAndy Whitcroft			$type = 'E';
2050171ae1a4SAndy Whitcroft
2051c45dcabdSAndy Whitcroft		} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
2052171ae1a4SAndy Whitcroft			print "UNDEF($1)\n" if ($dbg_values > 1);
2053171ae1a4SAndy Whitcroft			$av_preprocessor = 1;
2054171ae1a4SAndy Whitcroft			push(@av_paren_type, $type);
20556c72ffaaSAndy Whitcroft
2056c45dcabdSAndy Whitcroft		} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
2057cf655043SAndy Whitcroft			print "PRE_START($1)\n" if ($dbg_values > 1);
2058c2fdda0dSAndy Whitcroft			$av_preprocessor = 1;
2059cf655043SAndy Whitcroft
2060cf655043SAndy Whitcroft			push(@av_paren_type, $type);
2061cf655043SAndy Whitcroft			push(@av_paren_type, $type);
2062171ae1a4SAndy Whitcroft			$type = 'E';
2063cf655043SAndy Whitcroft
2064c45dcabdSAndy Whitcroft		} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
2065cf655043SAndy Whitcroft			print "PRE_RESTART($1)\n" if ($dbg_values > 1);
2066cf655043SAndy Whitcroft			$av_preprocessor = 1;
2067cf655043SAndy Whitcroft
2068cf655043SAndy Whitcroft			push(@av_paren_type, $av_paren_type[$#av_paren_type]);
2069cf655043SAndy Whitcroft
2070171ae1a4SAndy Whitcroft			$type = 'E';
2071cf655043SAndy Whitcroft
2072c45dcabdSAndy Whitcroft		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
2073cf655043SAndy Whitcroft			print "PRE_END($1)\n" if ($dbg_values > 1);
2074cf655043SAndy Whitcroft
2075cf655043SAndy Whitcroft			$av_preprocessor = 1;
2076cf655043SAndy Whitcroft
2077cf655043SAndy Whitcroft			# Assume all arms of the conditional end as this
2078cf655043SAndy Whitcroft			# one does, and continue as if the #endif was not here.
2079cf655043SAndy Whitcroft			pop(@av_paren_type);
2080cf655043SAndy Whitcroft			push(@av_paren_type, $type);
2081171ae1a4SAndy Whitcroft			$type = 'E';
20826c72ffaaSAndy Whitcroft
20836c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(\\\n)/o) {
2084c2fdda0dSAndy Whitcroft			print "PRECONT($1)\n" if ($dbg_values > 1);
20856c72ffaaSAndy Whitcroft
2086171ae1a4SAndy Whitcroft		} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
2087171ae1a4SAndy Whitcroft			print "ATTR($1)\n" if ($dbg_values > 1);
2088171ae1a4SAndy Whitcroft			$av_pending = $type;
2089171ae1a4SAndy Whitcroft			$type = 'N';
2090171ae1a4SAndy Whitcroft
20916c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
2092c2fdda0dSAndy Whitcroft			print "SIZEOF($1)\n" if ($dbg_values > 1);
20936c72ffaaSAndy Whitcroft			if (defined $2) {
2094cf655043SAndy Whitcroft				$av_pending = 'V';
20956c72ffaaSAndy Whitcroft			}
20966c72ffaaSAndy Whitcroft			$type = 'N';
20976c72ffaaSAndy Whitcroft
209814b111c1SAndy Whitcroft		} elsif ($cur =~ /^(if|while|for)\b/o) {
2099c2fdda0dSAndy Whitcroft			print "COND($1)\n" if ($dbg_values > 1);
210014b111c1SAndy Whitcroft			$av_pending = 'E';
21016c72ffaaSAndy Whitcroft			$type = 'N';
21026c72ffaaSAndy Whitcroft
21031f65f947SAndy Whitcroft		} elsif ($cur =~/^(case)/o) {
21041f65f947SAndy Whitcroft			print "CASE($1)\n" if ($dbg_values > 1);
21051f65f947SAndy Whitcroft			$av_pend_colon = 'C';
21061f65f947SAndy Whitcroft			$type = 'N';
21071f65f947SAndy Whitcroft
210814b111c1SAndy Whitcroft		} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
2109c2fdda0dSAndy Whitcroft			print "KEYWORD($1)\n" if ($dbg_values > 1);
21106c72ffaaSAndy Whitcroft			$type = 'N';
21116c72ffaaSAndy Whitcroft
21126c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(\()/o) {
2113c2fdda0dSAndy Whitcroft			print "PAREN('$1')\n" if ($dbg_values > 1);
2114cf655043SAndy Whitcroft			push(@av_paren_type, $av_pending);
2115cf655043SAndy Whitcroft			$av_pending = '_';
21166c72ffaaSAndy Whitcroft			$type = 'N';
21176c72ffaaSAndy Whitcroft
21186c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(\))/o) {
2119cf655043SAndy Whitcroft			my $new_type = pop(@av_paren_type);
2120cf655043SAndy Whitcroft			if ($new_type ne '_') {
2121cf655043SAndy Whitcroft				$type = $new_type;
2122c2fdda0dSAndy Whitcroft				print "PAREN('$1') -> $type\n"
2123c2fdda0dSAndy Whitcroft							if ($dbg_values > 1);
21246c72ffaaSAndy Whitcroft			} else {
2125c2fdda0dSAndy Whitcroft				print "PAREN('$1')\n" if ($dbg_values > 1);
21266c72ffaaSAndy Whitcroft			}
21276c72ffaaSAndy Whitcroft
2128c8cb2ca3SAndy Whitcroft		} elsif ($cur =~ /^($Ident)\s*\(/o) {
2129c2fdda0dSAndy Whitcroft			print "FUNC($1)\n" if ($dbg_values > 1);
2130c8cb2ca3SAndy Whitcroft			$type = 'V';
2131cf655043SAndy Whitcroft			$av_pending = 'V';
21326c72ffaaSAndy Whitcroft
21338e761b04SAndy Whitcroft		} elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
21348e761b04SAndy Whitcroft			if (defined $2 && $type eq 'C' || $type eq 'T') {
21351f65f947SAndy Whitcroft				$av_pend_colon = 'B';
21368e761b04SAndy Whitcroft			} elsif ($type eq 'E') {
21378e761b04SAndy Whitcroft				$av_pend_colon = 'L';
21381f65f947SAndy Whitcroft			}
21391f65f947SAndy Whitcroft			print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
21401f65f947SAndy Whitcroft			$type = 'V';
21411f65f947SAndy Whitcroft
21426c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Ident|$Constant)/o) {
2143c2fdda0dSAndy Whitcroft			print "IDENT($1)\n" if ($dbg_values > 1);
21446c72ffaaSAndy Whitcroft			$type = 'V';
21456c72ffaaSAndy Whitcroft
21466c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Assignment)/o) {
2147c2fdda0dSAndy Whitcroft			print "ASSIGN($1)\n" if ($dbg_values > 1);
21486c72ffaaSAndy Whitcroft			$type = 'N';
21496c72ffaaSAndy Whitcroft
2150cf655043SAndy Whitcroft		} elsif ($cur =~/^(;|{|})/) {
2151c2fdda0dSAndy Whitcroft			print "END($1)\n" if ($dbg_values > 1);
215213214adfSAndy Whitcroft			$type = 'E';
21531f65f947SAndy Whitcroft			$av_pend_colon = 'O';
215413214adfSAndy Whitcroft
21558e761b04SAndy Whitcroft		} elsif ($cur =~/^(,)/) {
21568e761b04SAndy Whitcroft			print "COMMA($1)\n" if ($dbg_values > 1);
21578e761b04SAndy Whitcroft			$type = 'C';
21588e761b04SAndy Whitcroft
21591f65f947SAndy Whitcroft		} elsif ($cur =~ /^(\?)/o) {
21601f65f947SAndy Whitcroft			print "QUESTION($1)\n" if ($dbg_values > 1);
21611f65f947SAndy Whitcroft			$type = 'N';
21621f65f947SAndy Whitcroft
21631f65f947SAndy Whitcroft		} elsif ($cur =~ /^(:)/o) {
21641f65f947SAndy Whitcroft			print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
21651f65f947SAndy Whitcroft
21661f65f947SAndy Whitcroft			substr($var, length($res), 1, $av_pend_colon);
21671f65f947SAndy Whitcroft			if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
21681f65f947SAndy Whitcroft				$type = 'E';
21691f65f947SAndy Whitcroft			} else {
21701f65f947SAndy Whitcroft				$type = 'N';
21711f65f947SAndy Whitcroft			}
21721f65f947SAndy Whitcroft			$av_pend_colon = 'O';
21731f65f947SAndy Whitcroft
21748e761b04SAndy Whitcroft		} elsif ($cur =~ /^(\[)/o) {
217513214adfSAndy Whitcroft			print "CLOSE($1)\n" if ($dbg_values > 1);
21766c72ffaaSAndy Whitcroft			$type = 'N';
21776c72ffaaSAndy Whitcroft
21780d413866SAndy Whitcroft		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
217974048ed8SAndy Whitcroft			my $variant;
218074048ed8SAndy Whitcroft
218174048ed8SAndy Whitcroft			print "OPV($1)\n" if ($dbg_values > 1);
218274048ed8SAndy Whitcroft			if ($type eq 'V') {
218374048ed8SAndy Whitcroft				$variant = 'B';
218474048ed8SAndy Whitcroft			} else {
218574048ed8SAndy Whitcroft				$variant = 'U';
218674048ed8SAndy Whitcroft			}
218774048ed8SAndy Whitcroft
218874048ed8SAndy Whitcroft			substr($var, length($res), 1, $variant);
218974048ed8SAndy Whitcroft			$type = 'N';
219074048ed8SAndy Whitcroft
21916c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Operators)/o) {
2192c2fdda0dSAndy Whitcroft			print "OP($1)\n" if ($dbg_values > 1);
21936c72ffaaSAndy Whitcroft			if ($1 ne '++' && $1 ne '--') {
21946c72ffaaSAndy Whitcroft				$type = 'N';
21956c72ffaaSAndy Whitcroft			}
21966c72ffaaSAndy Whitcroft
21976c72ffaaSAndy Whitcroft		} elsif ($cur =~ /(^.)/o) {
2198c2fdda0dSAndy Whitcroft			print "C($1)\n" if ($dbg_values > 1);
21996c72ffaaSAndy Whitcroft		}
22006c72ffaaSAndy Whitcroft		if (defined $1) {
22016c72ffaaSAndy Whitcroft			$cur = substr($cur, length($1));
22026c72ffaaSAndy Whitcroft			$res .= $type x length($1);
22036c72ffaaSAndy Whitcroft		}
22046c72ffaaSAndy Whitcroft	}
22056c72ffaaSAndy Whitcroft
22061f65f947SAndy Whitcroft	return ($res, $var);
22076c72ffaaSAndy Whitcroft}
22086c72ffaaSAndy Whitcroft
22098905a67cSAndy Whitcroftsub possible {
221013214adfSAndy Whitcroft	my ($possible, $line) = @_;
22119a974fdbSAndy Whitcroft	my $notPermitted = qr{(?:
22120776e594SAndy Whitcroft		^(?:
22130776e594SAndy Whitcroft			$Modifier|
22140776e594SAndy Whitcroft			$Storage|
22150776e594SAndy Whitcroft			$Type|
22169a974fdbSAndy Whitcroft			DEFINE_\S+
22179a974fdbSAndy Whitcroft		)$|
22189a974fdbSAndy Whitcroft		^(?:
22190776e594SAndy Whitcroft			goto|
22200776e594SAndy Whitcroft			return|
22210776e594SAndy Whitcroft			case|
22220776e594SAndy Whitcroft			else|
22230776e594SAndy Whitcroft			asm|__asm__|
222489a88353SAndy Whitcroft			do|
222589a88353SAndy Whitcroft			\#|
222689a88353SAndy Whitcroft			\#\#|
22279a974fdbSAndy Whitcroft		)(?:\s|$)|
22280776e594SAndy Whitcroft		^(?:typedef|struct|enum)\b
22299a974fdbSAndy Whitcroft	    )}x;
22309a974fdbSAndy Whitcroft	warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
22319a974fdbSAndy Whitcroft	if ($possible !~ $notPermitted) {
2232c45dcabdSAndy Whitcroft		# Check for modifiers.
2233c45dcabdSAndy Whitcroft		$possible =~ s/\s*$Storage\s*//g;
2234c45dcabdSAndy Whitcroft		$possible =~ s/\s*$Sparse\s*//g;
2235c45dcabdSAndy Whitcroft		if ($possible =~ /^\s*$/) {
2236c45dcabdSAndy Whitcroft
2237c45dcabdSAndy Whitcroft		} elsif ($possible =~ /\s/) {
2238c45dcabdSAndy Whitcroft			$possible =~ s/\s*$Type\s*//g;
2239d2506586SAndy Whitcroft			for my $modifier (split(' ', $possible)) {
22409a974fdbSAndy Whitcroft				if ($modifier !~ $notPermitted) {
2241d2506586SAndy Whitcroft					warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
2242485ff23eSAlex Dowad					push(@modifierListFile, $modifier);
2243d2506586SAndy Whitcroft				}
22449a974fdbSAndy Whitcroft			}
2245c45dcabdSAndy Whitcroft
2246c45dcabdSAndy Whitcroft		} else {
224713214adfSAndy Whitcroft			warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
2248485ff23eSAlex Dowad			push(@typeListFile, $possible);
2249c45dcabdSAndy Whitcroft		}
22508905a67cSAndy Whitcroft		build_types();
22510776e594SAndy Whitcroft	} else {
22520776e594SAndy Whitcroft		warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
22538905a67cSAndy Whitcroft	}
22548905a67cSAndy Whitcroft}
22558905a67cSAndy Whitcroft
22566c72ffaaSAndy Whitcroftmy $prefix = '';
22576c72ffaaSAndy Whitcroft
2258000d1cc1SJoe Perchessub show_type {
2259cbec18afSJoe Perches	my ($type) = @_;
226091bfe484SJoe Perches
2261522b837cSAlexey Dobriyan	$type =~ tr/[a-z]/[A-Z]/;
2262522b837cSAlexey Dobriyan
2263cbec18afSJoe Perches	return defined $use_type{$type} if (scalar keys %use_type > 0);
2264cbec18afSJoe Perches
2265cbec18afSJoe Perches	return !defined $ignore_type{$type};
2266000d1cc1SJoe Perches}
2267000d1cc1SJoe Perches
2268f0a594c1SAndy Whitcroftsub report {
2269cbec18afSJoe Perches	my ($level, $type, $msg) = @_;
2270cbec18afSJoe Perches
2271cbec18afSJoe Perches	if (!show_type($type) ||
2272cbec18afSJoe Perches	    (defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
2273773647a0SAndy Whitcroft		return 0;
2274773647a0SAndy Whitcroft	}
227557230297SJoe Perches	my $output = '';
2276737c0767SJohn Brooks	if ($color) {
227757230297SJoe Perches		if ($level eq 'ERROR') {
227857230297SJoe Perches			$output .= RED;
227957230297SJoe Perches		} elsif ($level eq 'WARNING') {
228057230297SJoe Perches			$output .= YELLOW;
2281000d1cc1SJoe Perches		} else {
228257230297SJoe Perches			$output .= GREEN;
2283000d1cc1SJoe Perches		}
228457230297SJoe Perches	}
228557230297SJoe Perches	$output .= $prefix . $level . ':';
228657230297SJoe Perches	if ($show_types) {
2287737c0767SJohn Brooks		$output .= BLUE if ($color);
228857230297SJoe Perches		$output .= "$type:";
228957230297SJoe Perches	}
2290737c0767SJohn Brooks	$output .= RESET if ($color);
229157230297SJoe Perches	$output .= ' ' . $msg . "\n";
229234d8815fSJoe Perches
229334d8815fSJoe Perches	if ($showfile) {
229434d8815fSJoe Perches		my @lines = split("\n", $output, -1);
229534d8815fSJoe Perches		splice(@lines, 1, 1);
229634d8815fSJoe Perches		$output = join("\n", @lines);
229734d8815fSJoe Perches	}
229852178ce0SDwaipayan Ray
229952178ce0SDwaipayan Ray	if ($terse) {
230052178ce0SDwaipayan Ray		$output = (split('\n', $output))[0] . "\n";
230152178ce0SDwaipayan Ray	}
230252178ce0SDwaipayan Ray
230352178ce0SDwaipayan Ray	if ($verbose && exists($verbose_messages{$type}) &&
230452178ce0SDwaipayan Ray	    !exists($verbose_emitted{$type})) {
230552178ce0SDwaipayan Ray		$output .= $verbose_messages{$type} . "\n\n";
230652178ce0SDwaipayan Ray		$verbose_emitted{$type} = 1;
230752178ce0SDwaipayan Ray	}
23088905a67cSAndy Whitcroft
230957230297SJoe Perches	push(our @report, $output);
2310773647a0SAndy Whitcroft
2311773647a0SAndy Whitcroft	return 1;
2312f0a594c1SAndy Whitcroft}
2313cbec18afSJoe Perches
2314f0a594c1SAndy Whitcroftsub report_dump {
231513214adfSAndy Whitcroft	our @report;
2316f0a594c1SAndy Whitcroft}
2317000d1cc1SJoe Perches
2318d752fcc8SJoe Perchessub fixup_current_range {
2319d752fcc8SJoe Perches	my ($lineRef, $offset, $length) = @_;
2320d752fcc8SJoe Perches
2321d752fcc8SJoe Perches	if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) {
2322d752fcc8SJoe Perches		my $o = $1;
2323d752fcc8SJoe Perches		my $l = $2;
2324d752fcc8SJoe Perches		my $no = $o + $offset;
2325d752fcc8SJoe Perches		my $nl = $l + $length;
2326d752fcc8SJoe Perches		$$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/;
2327d752fcc8SJoe Perches	}
2328d752fcc8SJoe Perches}
2329d752fcc8SJoe Perches
2330d752fcc8SJoe Perchessub fix_inserted_deleted_lines {
2331d752fcc8SJoe Perches	my ($linesRef, $insertedRef, $deletedRef) = @_;
2332d752fcc8SJoe Perches
2333d752fcc8SJoe Perches	my $range_last_linenr = 0;
2334d752fcc8SJoe Perches	my $delta_offset = 0;
2335d752fcc8SJoe Perches
2336d752fcc8SJoe Perches	my $old_linenr = 0;
2337d752fcc8SJoe Perches	my $new_linenr = 0;
2338d752fcc8SJoe Perches
2339d752fcc8SJoe Perches	my $next_insert = 0;
2340d752fcc8SJoe Perches	my $next_delete = 0;
2341d752fcc8SJoe Perches
2342d752fcc8SJoe Perches	my @lines = ();
2343d752fcc8SJoe Perches
2344d752fcc8SJoe Perches	my $inserted = @{$insertedRef}[$next_insert++];
2345d752fcc8SJoe Perches	my $deleted = @{$deletedRef}[$next_delete++];
2346d752fcc8SJoe Perches
2347d752fcc8SJoe Perches	foreach my $old_line (@{$linesRef}) {
2348d752fcc8SJoe Perches		my $save_line = 1;
2349d752fcc8SJoe Perches		my $line = $old_line;	#don't modify the array
2350323b267fSJoe Perches		if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) {	#new filename
2351d752fcc8SJoe Perches			$delta_offset = 0;
2352d752fcc8SJoe Perches		} elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) {	#new hunk
2353d752fcc8SJoe Perches			$range_last_linenr = $new_linenr;
2354d752fcc8SJoe Perches			fixup_current_range(\$line, $delta_offset, 0);
2355d752fcc8SJoe Perches		}
2356d752fcc8SJoe Perches
2357d752fcc8SJoe Perches		while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) {
2358d752fcc8SJoe Perches			$deleted = @{$deletedRef}[$next_delete++];
2359d752fcc8SJoe Perches			$save_line = 0;
2360d752fcc8SJoe Perches			fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
2361d752fcc8SJoe Perches		}
2362d752fcc8SJoe Perches
2363d752fcc8SJoe Perches		while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) {
2364d752fcc8SJoe Perches			push(@lines, ${$inserted}{'LINE'});
2365d752fcc8SJoe Perches			$inserted = @{$insertedRef}[$next_insert++];
2366d752fcc8SJoe Perches			$new_linenr++;
2367d752fcc8SJoe Perches			fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
2368d752fcc8SJoe Perches		}
2369d752fcc8SJoe Perches
2370d752fcc8SJoe Perches		if ($save_line) {
2371d752fcc8SJoe Perches			push(@lines, $line);
2372d752fcc8SJoe Perches			$new_linenr++;
2373d752fcc8SJoe Perches		}
2374d752fcc8SJoe Perches
2375d752fcc8SJoe Perches		$old_linenr++;
2376d752fcc8SJoe Perches	}
2377d752fcc8SJoe Perches
2378d752fcc8SJoe Perches	return @lines;
2379d752fcc8SJoe Perches}
2380d752fcc8SJoe Perches
2381f2d7e4d4SJoe Perchessub fix_insert_line {
2382f2d7e4d4SJoe Perches	my ($linenr, $line) = @_;
2383f2d7e4d4SJoe Perches
2384f2d7e4d4SJoe Perches	my $inserted = {
2385f2d7e4d4SJoe Perches		LINENR => $linenr,
2386f2d7e4d4SJoe Perches		LINE => $line,
2387f2d7e4d4SJoe Perches	};
2388f2d7e4d4SJoe Perches	push(@fixed_inserted, $inserted);
2389f2d7e4d4SJoe Perches}
2390f2d7e4d4SJoe Perches
2391f2d7e4d4SJoe Perchessub fix_delete_line {
2392f2d7e4d4SJoe Perches	my ($linenr, $line) = @_;
2393f2d7e4d4SJoe Perches
2394f2d7e4d4SJoe Perches	my $deleted = {
2395f2d7e4d4SJoe Perches		LINENR => $linenr,
2396f2d7e4d4SJoe Perches		LINE => $line,
2397f2d7e4d4SJoe Perches	};
2398f2d7e4d4SJoe Perches
2399f2d7e4d4SJoe Perches	push(@fixed_deleted, $deleted);
2400f2d7e4d4SJoe Perches}
2401f2d7e4d4SJoe Perches
2402de7d4f0eSAndy Whitcroftsub ERROR {
2403cbec18afSJoe Perches	my ($type, $msg) = @_;
2404cbec18afSJoe Perches
2405cbec18afSJoe Perches	if (report("ERROR", $type, $msg)) {
2406de7d4f0eSAndy Whitcroft		our $clean = 0;
24076c72ffaaSAndy Whitcroft		our $cnt_error++;
24083705ce5bSJoe Perches		return 1;
2409de7d4f0eSAndy Whitcroft	}
24103705ce5bSJoe Perches	return 0;
2411773647a0SAndy Whitcroft}
2412de7d4f0eSAndy Whitcroftsub WARN {
2413cbec18afSJoe Perches	my ($type, $msg) = @_;
2414cbec18afSJoe Perches
2415cbec18afSJoe Perches	if (report("WARNING", $type, $msg)) {
2416de7d4f0eSAndy Whitcroft		our $clean = 0;
24176c72ffaaSAndy Whitcroft		our $cnt_warn++;
24183705ce5bSJoe Perches		return 1;
2419de7d4f0eSAndy Whitcroft	}
24203705ce5bSJoe Perches	return 0;
2421773647a0SAndy Whitcroft}
2422de7d4f0eSAndy Whitcroftsub CHK {
2423cbec18afSJoe Perches	my ($type, $msg) = @_;
2424cbec18afSJoe Perches
2425cbec18afSJoe Perches	if ($check && report("CHECK", $type, $msg)) {
2426de7d4f0eSAndy Whitcroft		our $clean = 0;
24276c72ffaaSAndy Whitcroft		our $cnt_chk++;
24283705ce5bSJoe Perches		return 1;
24296c72ffaaSAndy Whitcroft	}
24303705ce5bSJoe Perches	return 0;
2431de7d4f0eSAndy Whitcroft}
2432de7d4f0eSAndy Whitcroft
24336ecd9674SAndy Whitcroftsub check_absolute_file {
24346ecd9674SAndy Whitcroft	my ($absolute, $herecurr) = @_;
24356ecd9674SAndy Whitcroft	my $file = $absolute;
24366ecd9674SAndy Whitcroft
24376ecd9674SAndy Whitcroft	##print "absolute<$absolute>\n";
24386ecd9674SAndy Whitcroft
24396ecd9674SAndy Whitcroft	# See if any suffix of this path is a path within the tree.
24406ecd9674SAndy Whitcroft	while ($file =~ s@^[^/]*/@@) {
24416ecd9674SAndy Whitcroft		if (-f "$root/$file") {
24426ecd9674SAndy Whitcroft			##print "file<$file>\n";
24436ecd9674SAndy Whitcroft			last;
24446ecd9674SAndy Whitcroft		}
24456ecd9674SAndy Whitcroft	}
24466ecd9674SAndy Whitcroft	if (! -f _)  {
24476ecd9674SAndy Whitcroft		return 0;
24486ecd9674SAndy Whitcroft	}
24496ecd9674SAndy Whitcroft
24506ecd9674SAndy Whitcroft	# It is, so see if the prefix is acceptable.
24516ecd9674SAndy Whitcroft	my $prefix = $absolute;
24526ecd9674SAndy Whitcroft	substr($prefix, -length($file)) = '';
24536ecd9674SAndy Whitcroft
24546ecd9674SAndy Whitcroft	##print "prefix<$prefix>\n";
24556ecd9674SAndy Whitcroft	if ($prefix ne ".../") {
2456000d1cc1SJoe Perches		WARN("USE_RELATIVE_PATH",
2457000d1cc1SJoe Perches		     "use relative pathname instead of absolute in changelog text\n" . $herecurr);
24586ecd9674SAndy Whitcroft	}
24596ecd9674SAndy Whitcroft}
24606ecd9674SAndy Whitcroft
24613705ce5bSJoe Perchessub trim {
24623705ce5bSJoe Perches	my ($string) = @_;
24633705ce5bSJoe Perches
2464b34c648bSJoe Perches	$string =~ s/^\s+|\s+$//g;
2465b34c648bSJoe Perches
2466b34c648bSJoe Perches	return $string;
2467b34c648bSJoe Perches}
2468b34c648bSJoe Perches
2469b34c648bSJoe Perchessub ltrim {
2470b34c648bSJoe Perches	my ($string) = @_;
2471b34c648bSJoe Perches
2472b34c648bSJoe Perches	$string =~ s/^\s+//;
2473b34c648bSJoe Perches
2474b34c648bSJoe Perches	return $string;
2475b34c648bSJoe Perches}
2476b34c648bSJoe Perches
2477b34c648bSJoe Perchessub rtrim {
2478b34c648bSJoe Perches	my ($string) = @_;
2479b34c648bSJoe Perches
2480b34c648bSJoe Perches	$string =~ s/\s+$//;
24813705ce5bSJoe Perches
24823705ce5bSJoe Perches	return $string;
24833705ce5bSJoe Perches}
24843705ce5bSJoe Perches
248552ea8506SJoe Perchessub string_find_replace {
248652ea8506SJoe Perches	my ($string, $find, $replace) = @_;
248752ea8506SJoe Perches
248852ea8506SJoe Perches	$string =~ s/$find/$replace/g;
248952ea8506SJoe Perches
249052ea8506SJoe Perches	return $string;
249152ea8506SJoe Perches}
249252ea8506SJoe Perches
24933705ce5bSJoe Perchessub tabify {
24943705ce5bSJoe Perches	my ($leading) = @_;
24953705ce5bSJoe Perches
2496713a09deSAntonio Borneo	my $source_indent = $tabsize;
24973705ce5bSJoe Perches	my $max_spaces_before_tab = $source_indent - 1;
24983705ce5bSJoe Perches	my $spaces_to_tab = " " x $source_indent;
24993705ce5bSJoe Perches
25003705ce5bSJoe Perches	#convert leading spaces to tabs
25013705ce5bSJoe Perches	1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
25023705ce5bSJoe Perches	#Remove spaces before a tab
25033705ce5bSJoe Perches	1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g;
25043705ce5bSJoe Perches
25053705ce5bSJoe Perches	return "$leading";
25063705ce5bSJoe Perches}
25073705ce5bSJoe Perches
2508d1fe9c09SJoe Perchessub pos_last_openparen {
2509d1fe9c09SJoe Perches	my ($line) = @_;
2510d1fe9c09SJoe Perches
2511d1fe9c09SJoe Perches	my $pos = 0;
2512d1fe9c09SJoe Perches
2513d1fe9c09SJoe Perches	my $opens = $line =~ tr/\(/\(/;
2514d1fe9c09SJoe Perches	my $closes = $line =~ tr/\)/\)/;
2515d1fe9c09SJoe Perches
2516d1fe9c09SJoe Perches	my $last_openparen = 0;
2517d1fe9c09SJoe Perches
2518d1fe9c09SJoe Perches	if (($opens == 0) || ($closes >= $opens)) {
2519d1fe9c09SJoe Perches		return -1;
2520d1fe9c09SJoe Perches	}
2521d1fe9c09SJoe Perches
2522d1fe9c09SJoe Perches	my $len = length($line);
2523d1fe9c09SJoe Perches
2524d1fe9c09SJoe Perches	for ($pos = 0; $pos < $len; $pos++) {
2525d1fe9c09SJoe Perches		my $string = substr($line, $pos);
2526d1fe9c09SJoe Perches		if ($string =~ /^($FuncArg|$balanced_parens)/) {
2527d1fe9c09SJoe Perches			$pos += length($1) - 1;
2528d1fe9c09SJoe Perches		} elsif (substr($line, $pos, 1) eq '(') {
2529d1fe9c09SJoe Perches			$last_openparen = $pos;
2530d1fe9c09SJoe Perches		} elsif (index($string, '(') == -1) {
2531d1fe9c09SJoe Perches			last;
2532d1fe9c09SJoe Perches		}
2533d1fe9c09SJoe Perches	}
2534d1fe9c09SJoe Perches
253591cb5195SJoe Perches	return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
2536d1fe9c09SJoe Perches}
2537d1fe9c09SJoe Perches
2538f36d3eb8SJoe Perchessub get_raw_comment {
2539f36d3eb8SJoe Perches	my ($line, $rawline) = @_;
2540f36d3eb8SJoe Perches	my $comment = '';
2541f36d3eb8SJoe Perches
2542f36d3eb8SJoe Perches	for my $i (0 .. (length($line) - 1)) {
2543f36d3eb8SJoe Perches		if (substr($line, $i, 1) eq "$;") {
2544f36d3eb8SJoe Perches			$comment .= substr($rawline, $i, 1);
2545f36d3eb8SJoe Perches		}
2546f36d3eb8SJoe Perches	}
2547f36d3eb8SJoe Perches
2548f36d3eb8SJoe Perches	return $comment;
2549f36d3eb8SJoe Perches}
2550f36d3eb8SJoe Perches
25515b8f82e1SSong Liusub exclude_global_initialisers {
25525b8f82e1SSong Liu	my ($realfile) = @_;
25535b8f82e1SSong Liu
25545b8f82e1SSong Liu	# Do not check for BPF programs (tools/testing/selftests/bpf/progs/*.c, samples/bpf/*_kern.c, *.bpf.c).
25555b8f82e1SSong Liu	return $realfile =~ m@^tools/testing/selftests/bpf/progs/.*\.c$@ ||
25565b8f82e1SSong Liu		$realfile =~ m@^samples/bpf/.*_kern\.c$@ ||
25575b8f82e1SSong Liu		$realfile =~ m@/bpf/.*\.bpf\.c$@;
25585b8f82e1SSong Liu}
25595b8f82e1SSong Liu
25600a920b5bSAndy Whitcroftsub process {
25610a920b5bSAndy Whitcroft	my $filename = shift;
25620a920b5bSAndy Whitcroft
25630a920b5bSAndy Whitcroft	my $linenr=0;
25640a920b5bSAndy Whitcroft	my $prevline="";
2565c2fdda0dSAndy Whitcroft	my $prevrawline="";
25660a920b5bSAndy Whitcroft	my $stashline="";
2567c2fdda0dSAndy Whitcroft	my $stashrawline="";
25680a920b5bSAndy Whitcroft
25694a0df2efSAndy Whitcroft	my $length;
25700a920b5bSAndy Whitcroft	my $indent;
25710a920b5bSAndy Whitcroft	my $previndent=0;
25720a920b5bSAndy Whitcroft	my $stashindent=0;
25730a920b5bSAndy Whitcroft
2574de7d4f0eSAndy Whitcroft	our $clean = 1;
25750a920b5bSAndy Whitcroft	my $signoff = 0;
2576cd261496SGeert Uytterhoeven	my $author = '';
2577cd261496SGeert Uytterhoeven	my $authorsignoff = 0;
257848ca2d8aSDwaipayan Ray	my $author_sob = '';
25790a920b5bSAndy Whitcroft	my $is_patch = 0;
2580133712a2SRob Herring	my $is_binding_patch = -1;
258129ee1b0cSJoe Perches	my $in_header_lines = $file ? 0 : 1;
258215662b3eSJoe Perches	my $in_commit_log = 0;		#Scanning lines before patch
258344d303ebSJoe Perches	my $has_patch_separator = 0;	#Found a --- line
2584ed43c4e5SAllen Hubbe	my $has_commit_log = 0;		#Encountered lines before patch
2585490b292cSJoe Perches	my $commit_log_lines = 0;	#Number of commit log lines
2586bf4daf12SJoe Perches	my $commit_log_possible_stack_dump = 0;
25872a076f40SJoe Perches	my $commit_log_long_line = 0;
2588e518e9a5SJoe Perches	my $commit_log_has_diff = 0;
258913f1937eSJoe Perches	my $reported_maintainer_file = 0;
2590fa64205dSPasi Savanainen	my $non_utf8_charset = 0;
2591fa64205dSPasi Savanainen
25924ce9f970SJoe Perches	my $last_git_commit_id_linenr = -1;
25934ce9f970SJoe Perches
2594365dd4eaSJoe Perches	my $last_blank_line = 0;
25955e4f6ba5SJoe Perches	my $last_coalesced_string_linenr = -1;
2596365dd4eaSJoe Perches
259713214adfSAndy Whitcroft	our @report = ();
25986c72ffaaSAndy Whitcroft	our $cnt_lines = 0;
25996c72ffaaSAndy Whitcroft	our $cnt_error = 0;
26006c72ffaaSAndy Whitcroft	our $cnt_warn = 0;
26016c72ffaaSAndy Whitcroft	our $cnt_chk = 0;
26026c72ffaaSAndy Whitcroft
26030a920b5bSAndy Whitcroft	# Trace the real file/line as we go.
26040a920b5bSAndy Whitcroft	my $realfile = '';
26050a920b5bSAndy Whitcroft	my $realline = 0;
26060a920b5bSAndy Whitcroft	my $realcnt = 0;
26070a920b5bSAndy Whitcroft	my $here = '';
260877cb8546SJoe Perches	my $context_function;		#undef'd unless there's a known function
26090a920b5bSAndy Whitcroft	my $in_comment = 0;
2610c2fdda0dSAndy Whitcroft	my $comment_edge = 0;
26110a920b5bSAndy Whitcroft	my $first_line = 0;
26121e855726SWolfram Sang	my $p1_prefix = '';
26130a920b5bSAndy Whitcroft
261413214adfSAndy Whitcroft	my $prev_values = 'E';
261513214adfSAndy Whitcroft
261613214adfSAndy Whitcroft	# suppression flags
2617773647a0SAndy Whitcroft	my %suppress_ifbraces;
2618170d3a22SAndy Whitcroft	my %suppress_whiletrailers;
26192b474a1aSAndy Whitcroft	my %suppress_export;
26203e469cdcSAndy Whitcroft	my $suppress_statement = 0;
2621653d4876SAndy Whitcroft
26227e51f197SJoe Perches	my %signatures = ();
2623323c1260SJoe Perches
2624c2fdda0dSAndy Whitcroft	# Pre-scan the patch sanitizing the lines.
2625de7d4f0eSAndy Whitcroft	# Pre-scan the patch looking for any __setup documentation.
2626c2fdda0dSAndy Whitcroft	#
2627de7d4f0eSAndy Whitcroft	my @setup_docs = ();
2628de7d4f0eSAndy Whitcroft	my $setup_docs = 0;
2629773647a0SAndy Whitcroft
2630d8b07710SJoe Perches	my $camelcase_file_seeded = 0;
2631d8b07710SJoe Perches
26329f3a8992SRob Herring	my $checklicenseline = 1;
26339f3a8992SRob Herring
2634773647a0SAndy Whitcroft	sanitise_line_reset();
2635c2fdda0dSAndy Whitcroft	my $line;
2636c2fdda0dSAndy Whitcroft	foreach my $rawline (@rawlines) {
2637773647a0SAndy Whitcroft		$linenr++;
2638773647a0SAndy Whitcroft		$line = $rawline;
2639c2fdda0dSAndy Whitcroft
26403705ce5bSJoe Perches		push(@fixed, $rawline) if ($fix);
26413705ce5bSJoe Perches
2642773647a0SAndy Whitcroft		if ($rawline=~/^\+\+\+\s+(\S+)/) {
2643de7d4f0eSAndy Whitcroft			$setup_docs = 0;
26442581ac7cSTim Froidcoeur			if ($1 =~ m@Documentation/admin-guide/kernel-parameters.txt$@) {
2645de7d4f0eSAndy Whitcroft				$setup_docs = 1;
2646de7d4f0eSAndy Whitcroft			}
2647773647a0SAndy Whitcroft			#next;
2648de7d4f0eSAndy Whitcroft		}
264974fd4f34SJoe Perches		if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
2650773647a0SAndy Whitcroft			$realline=$1-1;
2651773647a0SAndy Whitcroft			if (defined $2) {
2652773647a0SAndy Whitcroft				$realcnt=$3+1;
2653773647a0SAndy Whitcroft			} else {
2654773647a0SAndy Whitcroft				$realcnt=1+1;
2655773647a0SAndy Whitcroft			}
2656c45dcabdSAndy Whitcroft			$in_comment = 0;
2657773647a0SAndy Whitcroft
2658773647a0SAndy Whitcroft			# Guestimate if this is a continuing comment.  Run
2659773647a0SAndy Whitcroft			# the context looking for a comment "edge".  If this
2660773647a0SAndy Whitcroft			# edge is a close comment then we must be in a comment
2661773647a0SAndy Whitcroft			# at context start.
2662773647a0SAndy Whitcroft			my $edge;
266301fa9147SAndy Whitcroft			my $cnt = $realcnt;
266401fa9147SAndy Whitcroft			for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
266501fa9147SAndy Whitcroft				next if (defined $rawlines[$ln - 1] &&
266601fa9147SAndy Whitcroft					 $rawlines[$ln - 1] =~ /^-/);
266701fa9147SAndy Whitcroft				$cnt--;
266801fa9147SAndy Whitcroft				#print "RAW<$rawlines[$ln - 1]>\n";
2669721c1cb6SAndy Whitcroft				last if (!defined $rawlines[$ln - 1]);
2670fae17daeSAndy Whitcroft				if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
2671fae17daeSAndy Whitcroft				    $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
2672fae17daeSAndy Whitcroft					($edge) = $1;
2673fae17daeSAndy Whitcroft					last;
2674fae17daeSAndy Whitcroft				}
2675773647a0SAndy Whitcroft			}
2676773647a0SAndy Whitcroft			if (defined $edge && $edge eq '*/') {
2677773647a0SAndy Whitcroft				$in_comment = 1;
2678773647a0SAndy Whitcroft			}
2679773647a0SAndy Whitcroft
2680773647a0SAndy Whitcroft			# Guestimate if this is a continuing comment.  If this
2681773647a0SAndy Whitcroft			# is the start of a diff block and this line starts
2682773647a0SAndy Whitcroft			# ' *' then it is very likely a comment.
2683773647a0SAndy Whitcroft			if (!defined $edge &&
268483242e0cSAndy Whitcroft			    $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
2685773647a0SAndy Whitcroft			{
2686773647a0SAndy Whitcroft				$in_comment = 1;
2687773647a0SAndy Whitcroft			}
2688773647a0SAndy Whitcroft
2689773647a0SAndy Whitcroft			##print "COMMENT:$in_comment edge<$edge> $rawline\n";
2690773647a0SAndy Whitcroft			sanitise_line_reset($in_comment);
2691773647a0SAndy Whitcroft
2692171ae1a4SAndy Whitcroft		} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
2693773647a0SAndy Whitcroft			# Standardise the strings and chars within the input to
2694171ae1a4SAndy Whitcroft			# simplify matching -- only bother with positive lines.
2695773647a0SAndy Whitcroft			$line = sanitise_line($rawline);
2696773647a0SAndy Whitcroft		}
2697773647a0SAndy Whitcroft		push(@lines, $line);
2698773647a0SAndy Whitcroft
2699773647a0SAndy Whitcroft		if ($realcnt > 1) {
2700773647a0SAndy Whitcroft			$realcnt-- if ($line =~ /^(?:\+| |$)/);
2701773647a0SAndy Whitcroft		} else {
2702773647a0SAndy Whitcroft			$realcnt = 0;
2703773647a0SAndy Whitcroft		}
2704773647a0SAndy Whitcroft
2705773647a0SAndy Whitcroft		#print "==>$rawline\n";
2706773647a0SAndy Whitcroft		#print "-->$line\n";
2707de7d4f0eSAndy Whitcroft
2708de7d4f0eSAndy Whitcroft		if ($setup_docs && $line =~ /^\+/) {
2709de7d4f0eSAndy Whitcroft			push(@setup_docs, $line);
2710de7d4f0eSAndy Whitcroft		}
2711de7d4f0eSAndy Whitcroft	}
2712de7d4f0eSAndy Whitcroft
27136c72ffaaSAndy Whitcroft	$prefix = '';
27146c72ffaaSAndy Whitcroft
2715773647a0SAndy Whitcroft	$realcnt = 0;
2716773647a0SAndy Whitcroft	$linenr = 0;
2717194f66fcSJoe Perches	$fixlinenr = -1;
27180a920b5bSAndy Whitcroft	foreach my $line (@lines) {
27190a920b5bSAndy Whitcroft		$linenr++;
2720194f66fcSJoe Perches		$fixlinenr++;
27211b5539b1SJoe Perches		my $sline = $line;	#copy of $line
27221b5539b1SJoe Perches		$sline =~ s/$;/ /g;	#with comments as spaces
27230a920b5bSAndy Whitcroft
2724c2fdda0dSAndy Whitcroft		my $rawline = $rawlines[$linenr - 1];
2725f36d3eb8SJoe Perches		my $raw_comment = get_raw_comment($line, $rawline);
27266c72ffaaSAndy Whitcroft
272712c253abSJoe Perches# check if it's a mode change, rename or start of a patch
272812c253abSJoe Perches		if (!$in_commit_log &&
272912c253abSJoe Perches		    ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ ||
273012c253abSJoe Perches		    ($line =~ /^rename (?:from|to) \S+\s*$/ ||
273112c253abSJoe Perches		     $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) {
273212c253abSJoe Perches			$is_patch = 1;
273312c253abSJoe Perches		}
273412c253abSJoe Perches
27350a920b5bSAndy Whitcroft#extract the line range in the file after the patch is applied
2736e518e9a5SJoe Perches		if (!$in_commit_log &&
273774fd4f34SJoe Perches		    $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
273874fd4f34SJoe Perches			my $context = $4;
27390a920b5bSAndy Whitcroft			$is_patch = 1;
27404a0df2efSAndy Whitcroft			$first_line = $linenr + 1;
27410a920b5bSAndy Whitcroft			$realline=$1-1;
27420a920b5bSAndy Whitcroft			if (defined $2) {
27430a920b5bSAndy Whitcroft				$realcnt=$3+1;
27440a920b5bSAndy Whitcroft			} else {
27450a920b5bSAndy Whitcroft				$realcnt=1+1;
27460a920b5bSAndy Whitcroft			}
2747c2fdda0dSAndy Whitcroft			annotate_reset();
274813214adfSAndy Whitcroft			$prev_values = 'E';
274913214adfSAndy Whitcroft
2750773647a0SAndy Whitcroft			%suppress_ifbraces = ();
2751170d3a22SAndy Whitcroft			%suppress_whiletrailers = ();
27522b474a1aSAndy Whitcroft			%suppress_export = ();
27533e469cdcSAndy Whitcroft			$suppress_statement = 0;
275474fd4f34SJoe Perches			if ($context =~ /\b(\w+)\s*\(/) {
275574fd4f34SJoe Perches				$context_function = $1;
275674fd4f34SJoe Perches			} else {
275774fd4f34SJoe Perches				undef $context_function;
275874fd4f34SJoe Perches			}
27590a920b5bSAndy Whitcroft			next;
27600a920b5bSAndy Whitcroft
27614a0df2efSAndy Whitcroft# track the line number as we move through the hunk, note that
27624a0df2efSAndy Whitcroft# new versions of GNU diff omit the leading space on completely
27634a0df2efSAndy Whitcroft# blank context lines so we need to count that too.
2764773647a0SAndy Whitcroft		} elsif ($line =~ /^( |\+|$)/) {
27650a920b5bSAndy Whitcroft			$realline++;
2766d8aaf121SAndy Whitcroft			$realcnt-- if ($realcnt != 0);
27670a920b5bSAndy Whitcroft
27684a0df2efSAndy Whitcroft			# Measure the line length and indent.
2769c2fdda0dSAndy Whitcroft			($length, $indent) = line_stats($rawline);
27700a920b5bSAndy Whitcroft
27710a920b5bSAndy Whitcroft			# Track the previous line.
27720a920b5bSAndy Whitcroft			($prevline, $stashline) = ($stashline, $line);
27730a920b5bSAndy Whitcroft			($previndent, $stashindent) = ($stashindent, $indent);
2774c2fdda0dSAndy Whitcroft			($prevrawline, $stashrawline) = ($stashrawline, $rawline);
2775c2fdda0dSAndy Whitcroft
2776773647a0SAndy Whitcroft			#warn "line<$line>\n";
27776c72ffaaSAndy Whitcroft
2778d8aaf121SAndy Whitcroft		} elsif ($realcnt == 1) {
2779d8aaf121SAndy Whitcroft			$realcnt--;
27800a920b5bSAndy Whitcroft		}
27810a920b5bSAndy Whitcroft
2782cc77cdcaSAndy Whitcroft		my $hunk_line = ($realcnt != 0);
2783cc77cdcaSAndy Whitcroft
27846c72ffaaSAndy Whitcroft		$here = "#$linenr: " if (!$file);
27856c72ffaaSAndy Whitcroft		$here = "#$realline: " if ($file);
2786773647a0SAndy Whitcroft
27872ac73b4fSJoe Perches		my $found_file = 0;
2788773647a0SAndy Whitcroft		# extract the filename as it passes
27893bf9a009SRabin Vincent		if ($line =~ /^diff --git.*?(\S+)$/) {
27903bf9a009SRabin Vincent			$realfile = $1;
27912b7ab453SJoe Perches			$realfile =~ s@^([^/]*)/@@ if (!$file);
2792270c49a0SJoe Perches			$in_commit_log = 0;
27932ac73b4fSJoe Perches			$found_file = 1;
27943bf9a009SRabin Vincent		} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
2795773647a0SAndy Whitcroft			$realfile = $1;
27962b7ab453SJoe Perches			$realfile =~ s@^([^/]*)/@@ if (!$file);
2797270c49a0SJoe Perches			$in_commit_log = 0;
27981e855726SWolfram Sang
27991e855726SWolfram Sang			$p1_prefix = $1;
2800e2f7aa4bSAndy Whitcroft			if (!$file && $tree && $p1_prefix ne '' &&
2801e2f7aa4bSAndy Whitcroft			    -e "$root/$p1_prefix") {
2802000d1cc1SJoe Perches				WARN("PATCH_PREFIX",
2803000d1cc1SJoe Perches				     "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
28041e855726SWolfram Sang			}
2805773647a0SAndy Whitcroft
2806c1ab3326SAndy Whitcroft			if ($realfile =~ m@^include/asm/@) {
2807000d1cc1SJoe Perches				ERROR("MODIFIED_INCLUDE_ASM",
2808000d1cc1SJoe Perches				      "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
2809773647a0SAndy Whitcroft			}
28102ac73b4fSJoe Perches			$found_file = 1;
28112ac73b4fSJoe Perches		}
28122ac73b4fSJoe Perches
281334d8815fSJoe Perches#make up the handle for any error we report on this line
281434d8815fSJoe Perches		if ($showfile) {
281534d8815fSJoe Perches			$prefix = "$realfile:$realline: "
281634d8815fSJoe Perches		} elsif ($emacs) {
28177d3a9f67SJoe Perches			if ($file) {
28187d3a9f67SJoe Perches				$prefix = "$filename:$realline: ";
28197d3a9f67SJoe Perches			} else {
282034d8815fSJoe Perches				$prefix = "$filename:$linenr: ";
282134d8815fSJoe Perches			}
28227d3a9f67SJoe Perches		}
282334d8815fSJoe Perches
28242ac73b4fSJoe Perches		if ($found_file) {
282585b0ee18SJoe Perches			if (is_maintained_obsolete($realfile)) {
282685b0ee18SJoe Perches				WARN("OBSOLETE",
282785b0ee18SJoe Perches				     "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy.  No unnecessary modifications please.\n");
282885b0ee18SJoe Perches			}
28297bd7e483SJoe Perches			if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) {
28302ac73b4fSJoe Perches				$check = 1;
28312ac73b4fSJoe Perches			} else {
28322ac73b4fSJoe Perches				$check = $check_orig;
28332ac73b4fSJoe Perches			}
28349f3a8992SRob Herring			$checklicenseline = 1;
2835133712a2SRob Herring
2836133712a2SRob Herring			if ($realfile !~ /^MAINTAINERS/) {
2837133712a2SRob Herring				my $last_binding_patch = $is_binding_patch;
2838133712a2SRob Herring
2839133712a2SRob Herring				$is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@;
2840133712a2SRob Herring
2841133712a2SRob Herring				if (($last_binding_patch != -1) &&
2842133712a2SRob Herring				    ($last_binding_patch ^ $is_binding_patch)) {
2843133712a2SRob Herring					WARN("DT_SPLIT_BINDING_PATCH",
2844858e6845SMauro Carvalho Chehab					     "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.rst\n");
2845133712a2SRob Herring				}
2846133712a2SRob Herring			}
2847133712a2SRob Herring
2848773647a0SAndy Whitcroft			next;
2849773647a0SAndy Whitcroft		}
2850773647a0SAndy Whitcroft
2851389834b6SRandy Dunlap		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
28520a920b5bSAndy Whitcroft
2853c2fdda0dSAndy Whitcroft		my $hereline = "$here\n$rawline\n";
2854c2fdda0dSAndy Whitcroft		my $herecurr = "$here\n$rawline\n";
2855c2fdda0dSAndy Whitcroft		my $hereprev = "$here\n$prevrawline\n$rawline\n";
28560a920b5bSAndy Whitcroft
28576c72ffaaSAndy Whitcroft		$cnt_lines++ if ($realcnt != 0);
28586c72ffaaSAndy Whitcroft
2859490b292cSJoe Perches# Verify the existence of a commit log if appropriate
2860490b292cSJoe Perches# 2 is used because a $signature is counted in $commit_log_lines
2861490b292cSJoe Perches		if ($in_commit_log) {
2862490b292cSJoe Perches			if ($line !~ /^\s*$/) {
2863490b292cSJoe Perches				$commit_log_lines++;	#could be a $signature
2864490b292cSJoe Perches			}
2865490b292cSJoe Perches		} elsif ($has_commit_log && $commit_log_lines < 2) {
2866490b292cSJoe Perches			WARN("COMMIT_MESSAGE",
2867490b292cSJoe Perches			     "Missing commit description - Add an appropriate one\n");
2868490b292cSJoe Perches			$commit_log_lines = 2;	#warn only once
2869490b292cSJoe Perches		}
2870490b292cSJoe Perches
2871e518e9a5SJoe Perches# Check if the commit log has what seems like a diff which can confuse patch
2872e518e9a5SJoe Perches		if ($in_commit_log && !$commit_log_has_diff &&
287313e45417SMrinal Pandey		    (($line =~ m@^\s+diff\b.*a/([\w/]+)@ &&
287413e45417SMrinal Pandey		      $line =~ m@^\s+diff\b.*a/[\w/]+\s+b/$1\b@) ||
2875e518e9a5SJoe Perches		     $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ ||
2876e518e9a5SJoe Perches		     $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) {
2877e518e9a5SJoe Perches			ERROR("DIFF_IN_COMMIT_MSG",
2878e518e9a5SJoe Perches			      "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr);
2879e518e9a5SJoe Perches			$commit_log_has_diff = 1;
2880e518e9a5SJoe Perches		}
2881e518e9a5SJoe Perches
28823bf9a009SRabin Vincent# Check for incorrect file permissions
28833bf9a009SRabin Vincent		if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
28843bf9a009SRabin Vincent			my $permhere = $here . "FILE: $realfile\n";
288504db4d25SJoe Perches			if ($realfile !~ m@scripts/@ &&
288604db4d25SJoe Perches			    $realfile !~ /\.(py|pl|awk|sh)$/) {
2887000d1cc1SJoe Perches				ERROR("EXECUTE_PERMISSIONS",
2888000d1cc1SJoe Perches				      "do not set execute permissions for source files\n" . $permhere);
28893bf9a009SRabin Vincent			}
28903bf9a009SRabin Vincent		}
28913bf9a009SRabin Vincent
2892cd261496SGeert Uytterhoeven# Check the patch for a From:
2893cd261496SGeert Uytterhoeven		if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
2894cd261496SGeert Uytterhoeven			$author = $1;
2895e7f929f3SDwaipayan Ray			my $curline = $linenr;
2896e7f929f3SDwaipayan Ray			while(defined($rawlines[$curline]) && ($rawlines[$curline++] =~ /^[ \t]\s*(.*)/)) {
2897e7f929f3SDwaipayan Ray				$author .= $1;
2898e7f929f3SDwaipayan Ray			}
2899cd261496SGeert Uytterhoeven			$author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
2900cd261496SGeert Uytterhoeven			$author =~ s/"//g;
2901dfa05c28SJoe Perches			$author = reformat_email($author);
2902cd261496SGeert Uytterhoeven		}
2903cd261496SGeert Uytterhoeven
290420112475SJoe Perches# Check the patch for a signoff:
2905dfa05c28SJoe Perches		if ($line =~ /^\s*signed-off-by:\s*(.*)/i) {
29064a0df2efSAndy Whitcroft			$signoff++;
290715662b3eSJoe Perches			$in_commit_log = 0;
290848ca2d8aSDwaipayan Ray			if ($author ne ''  && $authorsignoff != 1) {
2909fccaebf0SDwaipayan Ray				if (same_email_addresses($1, $author)) {
2910cd261496SGeert Uytterhoeven					$authorsignoff = 1;
291148ca2d8aSDwaipayan Ray				} else {
291248ca2d8aSDwaipayan Ray					my $ctx = $1;
291348ca2d8aSDwaipayan Ray					my ($email_name, $email_comment, $email_address, $comment1) = parse_email($ctx);
291448ca2d8aSDwaipayan Ray					my ($author_name, $author_comment, $author_address, $comment2) = parse_email($author);
291548ca2d8aSDwaipayan Ray
2916046fc741SMimi Zohar					if (lc $email_address eq lc $author_address && $email_name eq $author_name) {
291748ca2d8aSDwaipayan Ray						$author_sob = $ctx;
291848ca2d8aSDwaipayan Ray						$authorsignoff = 2;
2919046fc741SMimi Zohar					} elsif (lc $email_address eq lc $author_address) {
292048ca2d8aSDwaipayan Ray						$author_sob = $ctx;
292148ca2d8aSDwaipayan Ray						$authorsignoff = 3;
292248ca2d8aSDwaipayan Ray					} elsif ($email_name eq $author_name) {
292348ca2d8aSDwaipayan Ray						$author_sob = $ctx;
292448ca2d8aSDwaipayan Ray						$authorsignoff = 4;
292548ca2d8aSDwaipayan Ray
292648ca2d8aSDwaipayan Ray						my $address1 = $email_address;
292748ca2d8aSDwaipayan Ray						my $address2 = $author_address;
292848ca2d8aSDwaipayan Ray
292948ca2d8aSDwaipayan Ray						if ($address1 =~ /(\S+)\+\S+(\@.*)/) {
293048ca2d8aSDwaipayan Ray							$address1 = "$1$2";
293148ca2d8aSDwaipayan Ray						}
293248ca2d8aSDwaipayan Ray						if ($address2 =~ /(\S+)\+\S+(\@.*)/) {
293348ca2d8aSDwaipayan Ray							$address2 = "$1$2";
293448ca2d8aSDwaipayan Ray						}
293548ca2d8aSDwaipayan Ray						if ($address1 eq $address2) {
293648ca2d8aSDwaipayan Ray							$authorsignoff = 5;
293748ca2d8aSDwaipayan Ray						}
293848ca2d8aSDwaipayan Ray					}
2939cd261496SGeert Uytterhoeven				}
2940cd261496SGeert Uytterhoeven			}
29410a920b5bSAndy Whitcroft		}
294220112475SJoe Perches
294344d303ebSJoe Perches# Check for patch separator
294444d303ebSJoe Perches		if ($line =~ /^---$/) {
294544d303ebSJoe Perches			$has_patch_separator = 1;
294644d303ebSJoe Perches			$in_commit_log = 0;
294744d303ebSJoe Perches		}
294844d303ebSJoe Perches
2949e0d975b1SJoe Perches# Check if MAINTAINERS is being updated.  If so, there's probably no need to
2950e0d975b1SJoe Perches# emit the "does MAINTAINERS need updating?" message on file add/move/delete
2951e0d975b1SJoe Perches		if ($line =~ /^\s*MAINTAINERS\s*\|/) {
2952e0d975b1SJoe Perches			$reported_maintainer_file = 1;
2953e0d975b1SJoe Perches		}
2954e0d975b1SJoe Perches
295520112475SJoe Perches# Check signature styles
2956270c49a0SJoe Perches		if (!$in_header_lines &&
2957ce0338dfSJoe Perches		    $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
295820112475SJoe Perches			my $space_before = $1;
295920112475SJoe Perches			my $sign_off = $2;
296020112475SJoe Perches			my $space_after = $3;
296120112475SJoe Perches			my $email = $4;
296220112475SJoe Perches			my $ucfirst_sign_off = ucfirst(lc($sign_off));
296320112475SJoe Perches
2964ce0338dfSJoe Perches			if ($sign_off !~ /$signature_tags/) {
2965831242abSAditya Srivastava				my $suggested_signature = find_standard_signature($sign_off);
2966831242abSAditya Srivastava				if ($suggested_signature eq "") {
2967ce0338dfSJoe Perches					WARN("BAD_SIGN_OFF",
2968ce0338dfSJoe Perches					     "Non-standard signature: $sign_off\n" . $herecurr);
2969831242abSAditya Srivastava				} else {
2970831242abSAditya Srivastava					if (WARN("BAD_SIGN_OFF",
2971831242abSAditya Srivastava						 "Non-standard signature: '$sign_off' - perhaps '$suggested_signature'?\n" . $herecurr) &&
2972831242abSAditya Srivastava					    $fix) {
2973831242abSAditya Srivastava						$fixed[$fixlinenr] =~ s/$sign_off/$suggested_signature/;
2974831242abSAditya Srivastava					}
2975831242abSAditya Srivastava				}
2976ce0338dfSJoe Perches			}
297720112475SJoe Perches			if (defined $space_before && $space_before ne "") {
29783705ce5bSJoe Perches				if (WARN("BAD_SIGN_OFF",
29793705ce5bSJoe Perches					 "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
29803705ce5bSJoe Perches				    $fix) {
2981194f66fcSJoe Perches					$fixed[$fixlinenr] =
29823705ce5bSJoe Perches					    "$ucfirst_sign_off $email";
29833705ce5bSJoe Perches				}
298420112475SJoe Perches			}
298520112475SJoe Perches			if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
29863705ce5bSJoe Perches				if (WARN("BAD_SIGN_OFF",
29873705ce5bSJoe Perches					 "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
29883705ce5bSJoe Perches				    $fix) {
2989194f66fcSJoe Perches					$fixed[$fixlinenr] =
29903705ce5bSJoe Perches					    "$ucfirst_sign_off $email";
29913705ce5bSJoe Perches				}
29923705ce5bSJoe Perches
299320112475SJoe Perches			}
299420112475SJoe Perches			if (!defined $space_after || $space_after ne " ") {
29953705ce5bSJoe Perches				if (WARN("BAD_SIGN_OFF",
29963705ce5bSJoe Perches					 "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
29973705ce5bSJoe Perches				    $fix) {
2998194f66fcSJoe Perches					$fixed[$fixlinenr] =
29993705ce5bSJoe Perches					    "$ucfirst_sign_off $email";
30003705ce5bSJoe Perches				}
300120112475SJoe Perches			}
300220112475SJoe Perches
3003dfa05c28SJoe Perches			my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
300448ca2d8aSDwaipayan Ray			my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment));
300520112475SJoe Perches			if ($suggested_email eq "") {
3006000d1cc1SJoe Perches				ERROR("BAD_SIGN_OFF",
3007000d1cc1SJoe Perches				      "Unrecognized email address: '$email'\n" . $herecurr);
300820112475SJoe Perches			} else {
300920112475SJoe Perches				my $dequoted = $suggested_email;
301020112475SJoe Perches				$dequoted =~ s/^"//;
301120112475SJoe Perches				$dequoted =~ s/" </ </;
301220112475SJoe Perches				# Don't force email to have quotes
301320112475SJoe Perches				# Allow just an angle bracketed address
3014fccaebf0SDwaipayan Ray				if (!same_email_addresses($email, $suggested_email)) {
3015fccaebf0SDwaipayan Ray					if (WARN("BAD_SIGN_OFF",
3016fccaebf0SDwaipayan Ray						 "email address '$email' might be better as '$suggested_email'\n" . $herecurr) &&
3017fccaebf0SDwaipayan Ray					    $fix) {
3018fccaebf0SDwaipayan Ray						$fixed[$fixlinenr] =~ s/\Q$email\E/$suggested_email/;
3019fccaebf0SDwaipayan Ray					}
3020fccaebf0SDwaipayan Ray				}
3021fccaebf0SDwaipayan Ray
3022fccaebf0SDwaipayan Ray				# Address part shouldn't have comments
3023fccaebf0SDwaipayan Ray				my $stripped_address = $email_address;
3024fccaebf0SDwaipayan Ray				$stripped_address =~ s/\([^\(\)]*\)//g;
3025fccaebf0SDwaipayan Ray				if ($email_address ne $stripped_address) {
3026fccaebf0SDwaipayan Ray					if (WARN("BAD_SIGN_OFF",
3027fccaebf0SDwaipayan Ray						 "address part of email should not have comments: '$email_address'\n" . $herecurr) &&
3028fccaebf0SDwaipayan Ray					    $fix) {
3029fccaebf0SDwaipayan Ray						$fixed[$fixlinenr] =~ s/\Q$email_address\E/$stripped_address/;
3030fccaebf0SDwaipayan Ray					}
3031fccaebf0SDwaipayan Ray				}
3032fccaebf0SDwaipayan Ray
3033fccaebf0SDwaipayan Ray				# Only one name comment should be allowed
3034fccaebf0SDwaipayan Ray				my $comment_count = () = $name_comment =~ /\([^\)]+\)/g;
3035fccaebf0SDwaipayan Ray				if ($comment_count > 1) {
3036000d1cc1SJoe Perches					WARN("BAD_SIGN_OFF",
3037fccaebf0SDwaipayan Ray					     "Use a single name comment in email: '$email'\n" . $herecurr);
3038fccaebf0SDwaipayan Ray				}
3039fccaebf0SDwaipayan Ray
3040fccaebf0SDwaipayan Ray
3041fccaebf0SDwaipayan Ray				# [email protected] or [email protected] shouldn't
3042e73d2715SDwaipayan Ray				# have an email name. In addition comments should strictly
3043fccaebf0SDwaipayan Ray				# begin with a #
3044fccaebf0SDwaipayan Ray				if ($email =~ /^.*stable\@(?:vger\.)?kernel\.org/i) {
3045fccaebf0SDwaipayan Ray					if (($comment ne "" && $comment !~ /^#.+/) ||
3046fccaebf0SDwaipayan Ray					    ($email_name ne "")) {
3047fccaebf0SDwaipayan Ray						my $cur_name = $email_name;
3048fccaebf0SDwaipayan Ray						my $new_comment = $comment;
3049fccaebf0SDwaipayan Ray						$cur_name =~ s/[a-zA-Z\s\-\"]+//g;
3050fccaebf0SDwaipayan Ray
3051fccaebf0SDwaipayan Ray						# Remove brackets enclosing comment text
3052fccaebf0SDwaipayan Ray						# and # from start of comments to get comment text
3053fccaebf0SDwaipayan Ray						$new_comment =~ s/^\((.*)\)$/$1/;
3054fccaebf0SDwaipayan Ray						$new_comment =~ s/^\[(.*)\]$/$1/;
3055fccaebf0SDwaipayan Ray						$new_comment =~ s/^[\s\#]+|\s+$//g;
3056fccaebf0SDwaipayan Ray
3057fccaebf0SDwaipayan Ray						$new_comment = trim("$new_comment $cur_name") if ($cur_name ne $new_comment);
3058fccaebf0SDwaipayan Ray						$new_comment = " # $new_comment" if ($new_comment ne "");
3059fccaebf0SDwaipayan Ray						my $new_email = "$email_address$new_comment";
3060fccaebf0SDwaipayan Ray
3061fccaebf0SDwaipayan Ray						if (WARN("BAD_STABLE_ADDRESS_STYLE",
3062fccaebf0SDwaipayan Ray							 "Invalid email format for stable: '$email', prefer '$new_email'\n" . $herecurr) &&
3063fccaebf0SDwaipayan Ray						    $fix) {
3064fccaebf0SDwaipayan Ray							$fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
3065fccaebf0SDwaipayan Ray						}
3066fccaebf0SDwaipayan Ray					}
3067fccaebf0SDwaipayan Ray				} elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) {
3068fccaebf0SDwaipayan Ray					my $new_comment = $comment;
3069fccaebf0SDwaipayan Ray
3070fccaebf0SDwaipayan Ray					# Extract comment text from within brackets or
3071fccaebf0SDwaipayan Ray					# c89 style /*...*/ comments
3072fccaebf0SDwaipayan Ray					$new_comment =~ s/^\[(.*)\]$/$1/;
3073fccaebf0SDwaipayan Ray					$new_comment =~ s/^\/\*(.*)\*\/$/$1/;
3074fccaebf0SDwaipayan Ray
3075fccaebf0SDwaipayan Ray					$new_comment = trim($new_comment);
3076fccaebf0SDwaipayan Ray					$new_comment =~ s/^[^\w]$//; # Single lettered comment with non word character is usually a typo
3077fccaebf0SDwaipayan Ray					$new_comment = "($new_comment)" if ($new_comment ne "");
3078fccaebf0SDwaipayan Ray					my $new_email = format_email($email_name, $name_comment, $email_address, $new_comment);
3079fccaebf0SDwaipayan Ray
3080fccaebf0SDwaipayan Ray					if (WARN("BAD_SIGN_OFF",
3081fccaebf0SDwaipayan Ray						 "Unexpected content after email: '$email', should be: '$new_email'\n" . $herecurr) &&
3082fccaebf0SDwaipayan Ray					    $fix) {
3083fccaebf0SDwaipayan Ray						$fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
3084fccaebf0SDwaipayan Ray					}
308520112475SJoe Perches				}
30860a920b5bSAndy Whitcroft			}
30877e51f197SJoe Perches
30887e51f197SJoe Perches# Check for duplicate signatures
30897e51f197SJoe Perches			my $sig_nospace = $line;
30907e51f197SJoe Perches			$sig_nospace =~ s/\s//g;
30917e51f197SJoe Perches			$sig_nospace = lc($sig_nospace);
30927e51f197SJoe Perches			if (defined $signatures{$sig_nospace}) {
30937e51f197SJoe Perches				WARN("BAD_SIGN_OFF",
30947e51f197SJoe Perches				     "Duplicate signature\n" . $herecurr);
30957e51f197SJoe Perches			} else {
30967e51f197SJoe Perches				$signatures{$sig_nospace} = 1;
30977e51f197SJoe Perches			}
30986c5d24eeSSean Christopherson
30996c5d24eeSSean Christopherson# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
31006c5d24eeSSean Christopherson			if ($sign_off =~ /^co-developed-by:$/i) {
31016c5d24eeSSean Christopherson				if ($email eq $author) {
31026c5d24eeSSean Christopherson					WARN("BAD_SIGN_OFF",
31036c5d24eeSSean Christopherson					      "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
31046c5d24eeSSean Christopherson				}
31056c5d24eeSSean Christopherson				if (!defined $lines[$linenr]) {
31066c5d24eeSSean Christopherson					WARN("BAD_SIGN_OFF",
31076c5d24eeSSean Christopherson					     "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
31086c5d24eeSSean Christopherson				} elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
31096c5d24eeSSean Christopherson					WARN("BAD_SIGN_OFF",
31106c5d24eeSSean Christopherson					     "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
31116c5d24eeSSean Christopherson				} elsif ($1 ne $email) {
31126c5d24eeSSean Christopherson					WARN("BAD_SIGN_OFF",
31136c5d24eeSSean Christopherson					     "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
31146c5d24eeSSean Christopherson				}
31156c5d24eeSSean Christopherson			}
31160a920b5bSAndy Whitcroft		}
31170a920b5bSAndy Whitcroft
3118a2fe16b9SJoe Perches# Check email subject for common tools that don't need to be mentioned
3119a2fe16b9SJoe Perches		if ($in_header_lines &&
3120a2fe16b9SJoe Perches		    $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) {
3121a2fe16b9SJoe Perches			WARN("EMAIL_SUBJECT",
3122a2fe16b9SJoe Perches			     "A patch subject line should describe the change not the tool that found it\n" . $herecurr);
3123a2fe16b9SJoe Perches		}
3124a2fe16b9SJoe Perches
312544d303ebSJoe Perches# Check for Gerrit Change-Ids not in any patch context
312644d303ebSJoe Perches		if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
31277580c5b9SAditya Srivastava			if (ERROR("GERRIT_CHANGE_ID",
31287580c5b9SAditya Srivastava			          "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr) &&
31297580c5b9SAditya Srivastava			    $fix) {
31307580c5b9SAditya Srivastava				fix_delete_line($fixlinenr, $rawline);
31317580c5b9SAditya Srivastava			}
31327ebd05efSChristopher Covington		}
31337ebd05efSChristopher Covington
3134369c8dd3SJoe Perches# Check if the commit log is in a possible stack dump
3135369c8dd3SJoe Perches		if ($in_commit_log && !$commit_log_possible_stack_dump &&
3136369c8dd3SJoe Perches		    ($line =~ /^\s*(?:WARNING:|BUG:)/ ||
3137369c8dd3SJoe Perches		     $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
3138369c8dd3SJoe Perches					# timestamp
3139634cffccSJoe Perches		     $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
3140634cffccSJoe Perches		     $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
3141634cffccSJoe Perches		     $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
3142634cffccSJoe Perches					# stack dump address styles
3143369c8dd3SJoe Perches			$commit_log_possible_stack_dump = 1;
3144369c8dd3SJoe Perches		}
3145369c8dd3SJoe Perches
31462a076f40SJoe Perches# Check for line lengths > 75 in commit log, warn once
31472a076f40SJoe Perches		if ($in_commit_log && !$commit_log_long_line &&
3148bf4daf12SJoe Perches		    length($line) > 75 &&
3149bf4daf12SJoe Perches		    !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
3150bf4daf12SJoe Perches					# file delta changes
3151bf4daf12SJoe Perches		      $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
3152bf4daf12SJoe Perches					# filename then :
315327b379afSAditya Srivastava		      $line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
315427b379afSAditya Srivastava					# A Fixes: or Link: line or signature tag line
3155bf4daf12SJoe Perches		      $commit_log_possible_stack_dump)) {
31562a076f40SJoe Perches			WARN("COMMIT_LOG_LONG_LINE",
31572a076f40SJoe Perches			     "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
31582a076f40SJoe Perches			$commit_log_long_line = 1;
31592a076f40SJoe Perches		}
31602a076f40SJoe Perches
3161bf4daf12SJoe Perches# Reset possible stack dump if a blank line is found
3162bf4daf12SJoe Perches		if ($in_commit_log && $commit_log_possible_stack_dump &&
3163bf4daf12SJoe Perches		    $line =~ /^\s*$/) {
3164bf4daf12SJoe Perches			$commit_log_possible_stack_dump = 0;
3165bf4daf12SJoe Perches		}
3166bf4daf12SJoe Perches
3167084a617aSDwaipayan Ray# Check for lines starting with a #
3168084a617aSDwaipayan Ray		if ($in_commit_log && $line =~ /^#/) {
3169084a617aSDwaipayan Ray			if (WARN("COMMIT_COMMENT_SYMBOL",
3170084a617aSDwaipayan Ray				 "Commit log lines starting with '#' are dropped by git as comments\n" . $herecurr) &&
3171084a617aSDwaipayan Ray			    $fix) {
3172084a617aSDwaipayan Ray				$fixed[$fixlinenr] =~ s/^/ /;
3173084a617aSDwaipayan Ray			}
3174084a617aSDwaipayan Ray		}
3175084a617aSDwaipayan Ray
31760d7835fcSJoe Perches# Check for git id commit length and improperly formed commit descriptions
31774ce9f970SJoe Perches# A correctly formed commit description is:
31784ce9f970SJoe Perches#    commit <SHA-1 hash length 12+ chars> ("Complete commit subject")
31794ce9f970SJoe Perches# with the commit subject '("' prefix and '")' suffix
31804ce9f970SJoe Perches# This is a fairly compilicated block as it tests for what appears to be
31814ce9f970SJoe Perches# bare SHA-1 hash with  minimum length of 5.  It also avoids several types of
31824ce9f970SJoe Perches# possible SHA-1 matches.
31834ce9f970SJoe Perches# A commit match can span multiple lines so this block attempts to find a
31844ce9f970SJoe Perches# complete typical commit on a maximum of 3 lines
31854ce9f970SJoe Perches		if ($perl_version_ok &&
31864ce9f970SJoe Perches		    $in_commit_log && !$commit_log_possible_stack_dump &&
3187a8972573SJohn Hubbard		    $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
3188e882dbfcSWei Wang		    $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
31894ce9f970SJoe Perches		    (($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
31904ce9f970SJoe Perches		      ($line =~ /\bcommit\s*$/i && defined($rawlines[$linenr]) && $rawlines[$linenr] =~ /^\s*[0-9a-f]{5,}\b/i)) ||
3191aab38f51SJoe Perches		     ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
3192369c8dd3SJoe Perches		      $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
3193bf4daf12SJoe Perches		      $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
3194fe043ea1SJoe Perches			my $init_char = "c";
3195fe043ea1SJoe Perches			my $orig_commit = "";
31960d7835fcSJoe Perches			my $short = 1;
31970d7835fcSJoe Perches			my $long = 0;
31980d7835fcSJoe Perches			my $case = 1;
31990d7835fcSJoe Perches			my $space = 1;
32000d7835fcSJoe Perches			my $id = '0123456789ab';
32010d7835fcSJoe Perches			my $orig_desc = "commit description";
32020d7835fcSJoe Perches			my $description = "";
32034ce9f970SJoe Perches			my $herectx = $herecurr;
32044ce9f970SJoe Perches			my $has_parens = 0;
32054ce9f970SJoe Perches			my $has_quotes = 0;
32060d7835fcSJoe Perches
32074ce9f970SJoe Perches			my $input = $line;
32084ce9f970SJoe Perches			if ($line =~ /(?:\bcommit\s+[0-9a-f]{5,}|\bcommit\s*$)/i) {
32094ce9f970SJoe Perches				for (my $n = 0; $n < 2; $n++) {
32104ce9f970SJoe Perches					if ($input =~ /\bcommit\s+[0-9a-f]{5,}\s*($balanced_parens)/i) {
32114ce9f970SJoe Perches						$orig_desc = $1;
32124ce9f970SJoe Perches						$has_parens = 1;
32134ce9f970SJoe Perches						# Always strip leading/trailing parens then double quotes if existing
32144ce9f970SJoe Perches						$orig_desc = substr($orig_desc, 1, -1);
32154ce9f970SJoe Perches						if ($orig_desc =~ /^".*"$/) {
32164ce9f970SJoe Perches							$orig_desc = substr($orig_desc, 1, -1);
32174ce9f970SJoe Perches							$has_quotes = 1;
32184ce9f970SJoe Perches						}
32194ce9f970SJoe Perches						last;
32204ce9f970SJoe Perches					}
32214ce9f970SJoe Perches					last if ($#lines < $linenr + $n);
32224ce9f970SJoe Perches					$input .= " " . trim($rawlines[$linenr + $n]);
32234ce9f970SJoe Perches					$herectx .= "$rawlines[$linenr + $n]\n";
32244ce9f970SJoe Perches				}
32254ce9f970SJoe Perches				$herectx = $herecurr if (!$has_parens);
3226fe043ea1SJoe Perches			}
3227fe043ea1SJoe Perches
32284ce9f970SJoe Perches			if ($input =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
32294ce9f970SJoe Perches				$init_char = $1;
32304ce9f970SJoe Perches				$orig_commit = lc($2);
32314ce9f970SJoe Perches				$short = 0 if ($input =~ /\bcommit\s+[0-9a-f]{12,40}/i);
32324ce9f970SJoe Perches				$long = 1 if ($input =~ /\bcommit\s+[0-9a-f]{41,}/i);
32334ce9f970SJoe Perches				$space = 0 if ($input =~ /\bcommit [0-9a-f]/i);
32344ce9f970SJoe Perches				$case = 0 if ($input =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
32354ce9f970SJoe Perches			} elsif ($input =~ /\b([0-9a-f]{12,40})\b/i) {
32364ce9f970SJoe Perches				$orig_commit = lc($1);
32370d7835fcSJoe Perches			}
32380d7835fcSJoe Perches
32390d7835fcSJoe Perches			($id, $description) = git_commit_info($orig_commit,
32400d7835fcSJoe Perches							      $id, $orig_desc);
32410d7835fcSJoe Perches
3242948b133aSHeinrich Schuchardt			if (defined($id) &&
32434ce9f970SJoe Perches			    ($short || $long || $space || $case || ($orig_desc ne $description) || !$has_quotes) &&
32444ce9f970SJoe Perches			    $last_git_commit_id_linenr != $linenr - 1) {
3245d311cd44SJoe Perches				ERROR("GIT_COMMIT_ID",
32464ce9f970SJoe Perches				      "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herectx);
32470d7835fcSJoe Perches			}
32484ce9f970SJoe Perches			#don't report the next line if this line ends in commit and the sha1 hash is the next line
32494ce9f970SJoe Perches			$last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i);
3250d311cd44SJoe Perches		}
3251d311cd44SJoe Perches
325213f1937eSJoe Perches# Check for added, moved or deleted files
325313f1937eSJoe Perches		if (!$reported_maintainer_file && !$in_commit_log &&
325413f1937eSJoe Perches		    ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
325513f1937eSJoe Perches		     $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
325613f1937eSJoe Perches		     ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
325713f1937eSJoe Perches		      (defined($1) || defined($2))))) {
3258a82603a8SAndrew Jeffery			$is_patch = 1;
325913f1937eSJoe Perches			$reported_maintainer_file = 1;
326013f1937eSJoe Perches			WARN("FILE_PATH_CHANGES",
326113f1937eSJoe Perches			     "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
326213f1937eSJoe Perches		}
326313f1937eSJoe Perches
3264e400edb1SRob Herring# Check for adding new DT bindings not in schema format
3265e400edb1SRob Herring		if (!$in_commit_log &&
3266e400edb1SRob Herring		    ($line =~ /^new file mode\s*\d+\s*$/) &&
3267e400edb1SRob Herring		    ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
3268e400edb1SRob Herring			WARN("DT_SCHEMA_BINDING_PATCH",
326956ddc4cdSMauro Carvalho Chehab			     "DT bindings should be in DT schema format. See: Documentation/devicetree/bindings/writing-schema.rst\n");
3270e400edb1SRob Herring		}
3271e400edb1SRob Herring
327200df344fSAndy Whitcroft# Check for wrappage within a valid hunk of the file
32738905a67cSAndy Whitcroft		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
3274000d1cc1SJoe Perches			ERROR("CORRUPTED_PATCH",
3275000d1cc1SJoe Perches			      "patch seems to be corrupt (line wrapped?)\n" .
32766c72ffaaSAndy Whitcroft				$herecurr) if (!$emitted_corrupt++);
3277de7d4f0eSAndy Whitcroft		}
3278de7d4f0eSAndy Whitcroft
3279de7d4f0eSAndy Whitcroft# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
3280de7d4f0eSAndy Whitcroft		if (($realfile =~ /^$/ || $line =~ /^\+/) &&
3281171ae1a4SAndy Whitcroft		    $rawline !~ m/^$UTF8*$/) {
3282171ae1a4SAndy Whitcroft			my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
3283171ae1a4SAndy Whitcroft
3284171ae1a4SAndy Whitcroft			my $blank = copy_spacing($rawline);
3285171ae1a4SAndy Whitcroft			my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
3286171ae1a4SAndy Whitcroft			my $hereptr = "$hereline$ptr\n";
3287171ae1a4SAndy Whitcroft
328834d99219SJoe Perches			CHK("INVALID_UTF8",
3289000d1cc1SJoe Perches			    "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
329000df344fSAndy Whitcroft		}
32910a920b5bSAndy Whitcroft
329215662b3eSJoe Perches# Check if it's the start of a commit log
329315662b3eSJoe Perches# (not a header line and we haven't seen the patch filename)
329415662b3eSJoe Perches		if ($in_header_lines && $realfile =~ /^$/ &&
3295eb3a58deSJoe Perches		    !($rawline =~ /^\s+(?:\S|$)/ ||
3296eb3a58deSJoe Perches		      $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) {
329715662b3eSJoe Perches			$in_header_lines = 0;
329815662b3eSJoe Perches			$in_commit_log = 1;
3299ed43c4e5SAllen Hubbe			$has_commit_log = 1;
330015662b3eSJoe Perches		}
330115662b3eSJoe Perches
3302fa64205dSPasi Savanainen# Check if there is UTF-8 in a commit log when a mail header has explicitly
3303fa64205dSPasi Savanainen# declined it, i.e defined some charset where it is missing.
3304fa64205dSPasi Savanainen		if ($in_header_lines &&
3305fa64205dSPasi Savanainen		    $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
3306fa64205dSPasi Savanainen		    $1 !~ /utf-8/i) {
3307fa64205dSPasi Savanainen			$non_utf8_charset = 1;
3308fa64205dSPasi Savanainen		}
3309fa64205dSPasi Savanainen
3310fa64205dSPasi Savanainen		if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
331115662b3eSJoe Perches		    $rawline =~ /$NON_ASCII_UTF8/) {
3312fa64205dSPasi Savanainen			WARN("UTF8_BEFORE_PATCH",
331315662b3eSJoe Perches			    "8-bit UTF-8 used in possible commit log\n" . $herecurr);
331415662b3eSJoe Perches		}
331515662b3eSJoe Perches
3316d6430f71SJoe Perches# Check for absolute kernel paths in commit message
3317d6430f71SJoe Perches		if ($tree && $in_commit_log) {
3318d6430f71SJoe Perches			while ($line =~ m{(?:^|\s)(/\S*)}g) {
3319d6430f71SJoe Perches				my $file = $1;
3320d6430f71SJoe Perches
3321d6430f71SJoe Perches				if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
3322d6430f71SJoe Perches				    check_absolute_file($1, $herecurr)) {
3323d6430f71SJoe Perches					#
3324d6430f71SJoe Perches				} else {
3325d6430f71SJoe Perches					check_absolute_file($file, $herecurr);
3326d6430f71SJoe Perches				}
3327d6430f71SJoe Perches			}
3328d6430f71SJoe Perches		}
3329d6430f71SJoe Perches
333066b47b4aSKees Cook# Check for various typo / spelling mistakes
333166d7a382SJoe Perches		if (defined($misspellings) &&
333266d7a382SJoe Perches		    ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
33337da07c31SDwaipayan Ray			while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {
333466b47b4aSKees Cook				my $typo = $1;
33357da07c31SDwaipayan Ray				my $blank = copy_spacing($rawline);
33367da07c31SDwaipayan Ray				my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);
33377da07c31SDwaipayan Ray				my $hereptr = "$hereline$ptr\n";
333866b47b4aSKees Cook				my $typo_fix = $spelling_fix{lc($typo)};
333966b47b4aSKees Cook				$typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
334066b47b4aSKees Cook				$typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
33410675a8fbSJean Delvare				my $msg_level = \&WARN;
33420675a8fbSJean Delvare				$msg_level = \&CHK if ($file);
33430675a8fbSJean Delvare				if (&{$msg_level}("TYPO_SPELLING",
33447da07c31SDwaipayan Ray						  "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $hereptr) &&
334566b47b4aSKees Cook				    $fix) {
334666b47b4aSKees Cook					$fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
334766b47b4aSKees Cook				}
334866b47b4aSKees Cook			}
334966b47b4aSKees Cook		}
335066b47b4aSKees Cook
3351a8dd86bfSMatteo Croce# check for invalid commit id
3352a8dd86bfSMatteo Croce		if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
3353a8dd86bfSMatteo Croce			my $id;
3354a8dd86bfSMatteo Croce			my $description;
3355a8dd86bfSMatteo Croce			($id, $description) = git_commit_info($2, undef, undef);
3356a8dd86bfSMatteo Croce			if (!defined($id)) {
3357a8dd86bfSMatteo Croce				WARN("UNKNOWN_COMMIT_ID",
3358a8dd86bfSMatteo Croce				     "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
3359a8dd86bfSMatteo Croce			}
3360a8dd86bfSMatteo Croce		}
3361a8dd86bfSMatteo Croce
3362310cd06bSJoe Perches# check for repeated words separated by a single space
33638d0325ccSAditya Srivastava# avoid false positive from list command eg, '-rw-r--r-- 1 root root'
33648d0325ccSAditya Srivastava		if (($rawline =~ /^\+/ || $in_commit_log) &&
33658d0325ccSAditya Srivastava		    $rawline !~ /[bcCdDlMnpPs\?-][rwxsStT-]{9}/) {
33661db81a68SDwaipayan Ray			pos($rawline) = 1 if (!$in_commit_log);
3367310cd06bSJoe Perches			while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) {
3368310cd06bSJoe Perches
3369310cd06bSJoe Perches				my $first = $1;
3370310cd06bSJoe Perches				my $second = $2;
33711db81a68SDwaipayan Ray				my $start_pos = $-[1];
33721db81a68SDwaipayan Ray				my $end_pos = $+[2];
3373310cd06bSJoe Perches				if ($first =~ /(?:struct|union|enum)/) {
3374310cd06bSJoe Perches					pos($rawline) += length($first) + length($second) + 1;
3375310cd06bSJoe Perches					next;
3376310cd06bSJoe Perches				}
3377310cd06bSJoe Perches
33781db81a68SDwaipayan Ray				next if (lc($first) ne lc($second));
3379310cd06bSJoe Perches				next if ($first eq 'long');
3380310cd06bSJoe Perches
33811db81a68SDwaipayan Ray				# check for character before and after the word matches
33821db81a68SDwaipayan Ray				my $start_char = '';
33831db81a68SDwaipayan Ray				my $end_char = '';
33841db81a68SDwaipayan Ray				$start_char = substr($rawline, $start_pos - 1, 1) if ($start_pos > ($in_commit_log ? 0 : 1));
33851db81a68SDwaipayan Ray				$end_char = substr($rawline, $end_pos, 1) if ($end_pos < length($rawline));
33861db81a68SDwaipayan Ray
33871db81a68SDwaipayan Ray				next if ($start_char =~ /^\S$/);
33881db81a68SDwaipayan Ray				next if (index(" \t.,;?!", $end_char) == -1);
33891db81a68SDwaipayan Ray
33908d0325ccSAditya Srivastava				# avoid repeating hex occurrences like 'ff ff fe 09 ...'
33918d0325ccSAditya Srivastava				if ($first =~ /\b[0-9a-f]{2,}\b/i) {
33928d0325ccSAditya Srivastava					next if (!exists($allow_repeated_words{lc($first)}));
33938d0325ccSAditya Srivastava				}
33948d0325ccSAditya Srivastava
3395310cd06bSJoe Perches				if (WARN("REPEATED_WORD",
3396310cd06bSJoe Perches					 "Possible repeated word: '$first'\n" . $herecurr) &&
3397310cd06bSJoe Perches				    $fix) {
3398310cd06bSJoe Perches					$fixed[$fixlinenr] =~ s/\b$first $second\b/$first/;
3399310cd06bSJoe Perches				}
3400310cd06bSJoe Perches			}
3401310cd06bSJoe Perches
3402310cd06bSJoe Perches			# if it's a repeated word on consecutive lines in a comment block
3403310cd06bSJoe Perches			if ($prevline =~ /$;+\s*$/ &&
3404310cd06bSJoe Perches			    $prevrawline =~ /($word_pattern)\s*$/) {
3405310cd06bSJoe Perches				my $last_word = $1;
3406310cd06bSJoe Perches				if ($rawline =~ /^\+\s*\*\s*$last_word /) {
3407310cd06bSJoe Perches					if (WARN("REPEATED_WORD",
3408310cd06bSJoe Perches						 "Possible repeated word: '$last_word'\n" . $hereprev) &&
3409310cd06bSJoe Perches					    $fix) {
3410310cd06bSJoe Perches						$fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/;
3411310cd06bSJoe Perches					}
3412310cd06bSJoe Perches				}
3413310cd06bSJoe Perches			}
3414310cd06bSJoe Perches		}
3415310cd06bSJoe Perches
341630670854SAndy Whitcroft# ignore non-hunk lines and lines being removed
341730670854SAndy Whitcroft		next if (!$hunk_line || $line =~ /^-/);
341800df344fSAndy Whitcroft
34190a920b5bSAndy Whitcroft#trailing whitespace
34209c0ca6f9SAndy Whitcroft		if ($line =~ /^\+.*\015/) {
3421c2fdda0dSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3422d5e616fcSJoe Perches			if (ERROR("DOS_LINE_ENDINGS",
3423d5e616fcSJoe Perches				  "DOS line endings\n" . $herevet) &&
3424d5e616fcSJoe Perches			    $fix) {
3425194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/[\s\015]+$//;
3426d5e616fcSJoe Perches			}
3427c2fdda0dSAndy Whitcroft		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
3428c2fdda0dSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
34293705ce5bSJoe Perches			if (ERROR("TRAILING_WHITESPACE",
34303705ce5bSJoe Perches				  "trailing whitespace\n" . $herevet) &&
34313705ce5bSJoe Perches			    $fix) {
3432194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/\s+$//;
34333705ce5bSJoe Perches			}
34343705ce5bSJoe Perches
3435d2c0a235SAndy Whitcroft			$rpt_cleaners = 1;
34360a920b5bSAndy Whitcroft		}
34375368df20SAndy Whitcroft
34384783f894SJosh Triplett# Check for FSF mailing addresses.
3439109d8cb2SAlexander Duyck		if ($rawline =~ /\bwrite to the Free/i ||
34401bde561eSMatthew Wilcox		    $rawline =~ /\b675\s+Mass\s+Ave/i ||
34413e2232f2SJoe Perches		    $rawline =~ /\b59\s+Temple\s+Pl/i ||
34423e2232f2SJoe Perches		    $rawline =~ /\b51\s+Franklin\s+St/i) {
34434783f894SJosh Triplett			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
34440675a8fbSJean Delvare			my $msg_level = \&ERROR;
34450675a8fbSJean Delvare			$msg_level = \&CHK if ($file);
34460675a8fbSJean Delvare			&{$msg_level}("FSF_MAILING_ADDRESS",
34474783f894SJosh Triplett				      "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)
34484783f894SJosh Triplett		}
34494783f894SJosh Triplett
34503354957aSAndi Kleen# check for Kconfig help text having a real description
34519fe287d7SAndy Whitcroft# Only applies when adding the entry originally, after that we do not have
34529fe287d7SAndy Whitcroft# sufficient context to determine whether it is indeed long enough.
34533354957aSAndi Kleen		if ($realfile =~ /Kconfig/ &&
3454678ae162SUlf Magnusson		    # 'choice' is usually the last thing on the line (though
3455678ae162SUlf Magnusson		    # Kconfig supports named choices), so use a word boundary
3456678ae162SUlf Magnusson		    # (\b) rather than a whitespace character (\s)
3457678ae162SUlf Magnusson		    $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
34583354957aSAndi Kleen			my $length = 0;
34599fe287d7SAndy Whitcroft			my $cnt = $realcnt;
34609fe287d7SAndy Whitcroft			my $ln = $linenr + 1;
34619fe287d7SAndy Whitcroft			my $f;
3462a1385803SAndy Whitcroft			my $is_start = 0;
34639fe287d7SAndy Whitcroft			my $is_end = 0;
3464a1385803SAndy Whitcroft			for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
34659fe287d7SAndy Whitcroft				$f = $lines[$ln - 1];
34669fe287d7SAndy Whitcroft				$cnt-- if ($lines[$ln - 1] !~ /^-/);
34679fe287d7SAndy Whitcroft				$is_end = $lines[$ln - 1] =~ /^\+/;
34689fe287d7SAndy Whitcroft
34699fe287d7SAndy Whitcroft				next if ($f =~ /^-/);
34708d73e0e7SJoe Perches				last if (!$file && $f =~ /^\@\@/);
3471a1385803SAndy Whitcroft
347286adf1a0SUlf Magnusson				if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
3473a1385803SAndy Whitcroft					$is_start = 1;
347422a4ac02SMasahiro Yamada				} elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
3475a1385803SAndy Whitcroft					$length = -1;
3476a1385803SAndy Whitcroft				}
3477a1385803SAndy Whitcroft
34789fe287d7SAndy Whitcroft				$f =~ s/^.//;
34793354957aSAndi Kleen				$f =~ s/#.*//;
34803354957aSAndi Kleen				$f =~ s/^\s+//;
34813354957aSAndi Kleen				next if ($f =~ /^$/);
3482678ae162SUlf Magnusson
3483678ae162SUlf Magnusson				# This only checks context lines in the patch
3484678ae162SUlf Magnusson				# and so hopefully shouldn't trigger false
3485678ae162SUlf Magnusson				# positives, even though some of these are
3486678ae162SUlf Magnusson				# common words in help texts
3487678ae162SUlf Magnusson				if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
3488678ae162SUlf Magnusson						  if|endif|menu|endmenu|source)\b/x) {
34899fe287d7SAndy Whitcroft					$is_end = 1;
34909fe287d7SAndy Whitcroft					last;
34919fe287d7SAndy Whitcroft				}
34923354957aSAndi Kleen				$length++;
34933354957aSAndi Kleen			}
349456193274SVadim Bendebury			if ($is_start && $is_end && $length < $min_conf_desc_length) {
3495000d1cc1SJoe Perches				WARN("CONFIG_DESCRIPTION",
349656193274SVadim Bendebury				     "please write a paragraph that describes the config symbol fully\n" . $herecurr);
349756193274SVadim Bendebury			}
3498a1385803SAndy Whitcroft			#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
34993354957aSAndi Kleen		}
35003354957aSAndi Kleen
35017ccf41a8SJoe Perches# check MAINTAINERS entries
35027ccf41a8SJoe Perches		if ($realfile =~ /^MAINTAINERS$/) {
35037ccf41a8SJoe Perches# check MAINTAINERS entries for the right form
35047ccf41a8SJoe Perches			if ($rawline =~ /^\+[A-Z]:/ &&
3505628f91a2SJoe Perches			    $rawline !~ /^\+[A-Z]:\t\S/) {
3506628f91a2SJoe Perches				if (WARN("MAINTAINERS_STYLE",
3507628f91a2SJoe Perches					 "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) &&
3508628f91a2SJoe Perches				    $fix) {
3509628f91a2SJoe Perches					$fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
3510628f91a2SJoe Perches				}
3511628f91a2SJoe Perches			}
35127ccf41a8SJoe Perches# check MAINTAINERS entries for the right ordering too
35137ccf41a8SJoe Perches			my $preferred_order = 'MRLSWQBCPTFXNK';
35147ccf41a8SJoe Perches			if ($rawline =~ /^\+[A-Z]:/ &&
35157ccf41a8SJoe Perches			    $prevrawline =~ /^[\+ ][A-Z]:/) {
35167ccf41a8SJoe Perches				$rawline =~ /^\+([A-Z]):\s*(.*)/;
35177ccf41a8SJoe Perches				my $cur = $1;
35187ccf41a8SJoe Perches				my $curval = $2;
35197ccf41a8SJoe Perches				$prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/;
35207ccf41a8SJoe Perches				my $prev = $1;
35217ccf41a8SJoe Perches				my $prevval = $2;
35227ccf41a8SJoe Perches				my $curindex = index($preferred_order, $cur);
35237ccf41a8SJoe Perches				my $previndex = index($preferred_order, $prev);
35247ccf41a8SJoe Perches				if ($curindex < 0) {
35257ccf41a8SJoe Perches					WARN("MAINTAINERS_STYLE",
35267ccf41a8SJoe Perches					     "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr);
35277ccf41a8SJoe Perches				} else {
35287ccf41a8SJoe Perches					if ($previndex >= 0 && $curindex < $previndex) {
35297ccf41a8SJoe Perches						WARN("MAINTAINERS_STYLE",
35307ccf41a8SJoe Perches						     "Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n" . $hereprev);
35317ccf41a8SJoe Perches					} elsif ((($prev eq 'F' && $cur eq 'F') ||
35327ccf41a8SJoe Perches						  ($prev eq 'X' && $cur eq 'X')) &&
35337ccf41a8SJoe Perches						 ($prevval cmp $curval) > 0) {
35347ccf41a8SJoe Perches						WARN("MAINTAINERS_STYLE",
35357ccf41a8SJoe Perches						     "Misordered MAINTAINERS entry - list file patterns in alphabetic order\n" . $hereprev);
35367ccf41a8SJoe Perches					}
35377ccf41a8SJoe Perches				}
35387ccf41a8SJoe Perches			}
35397ccf41a8SJoe Perches		}
3540628f91a2SJoe Perches
3541c68e5878SArnaud Lacombe		if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
3542c68e5878SArnaud Lacombe		    ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
3543c68e5878SArnaud Lacombe			my $flag = $1;
3544c68e5878SArnaud Lacombe			my $replacement = {
3545c68e5878SArnaud Lacombe				'EXTRA_AFLAGS' =>   'asflags-y',
3546c68e5878SArnaud Lacombe				'EXTRA_CFLAGS' =>   'ccflags-y',
3547c68e5878SArnaud Lacombe				'EXTRA_CPPFLAGS' => 'cppflags-y',
3548c68e5878SArnaud Lacombe				'EXTRA_LDFLAGS' =>  'ldflags-y',
3549c68e5878SArnaud Lacombe			};
3550c68e5878SArnaud Lacombe
3551c68e5878SArnaud Lacombe			WARN("DEPRECATED_VARIABLE",
3552c68e5878SArnaud Lacombe			     "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
3553c68e5878SArnaud Lacombe		}
3554c68e5878SArnaud Lacombe
3555bff5da43SRob Herring# check for DT compatible documentation
35567dd05b38SFlorian Vaussard		if (defined $root &&
35577dd05b38SFlorian Vaussard			(($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
35587dd05b38SFlorian Vaussard			 ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) {
35597dd05b38SFlorian Vaussard
3560bff5da43SRob Herring			my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
3561bff5da43SRob Herring
3562cc93319bSFlorian Vaussard			my $dt_path = $root . "/Documentation/devicetree/bindings/";
3563852d095dSRob Herring			my $vp_file = $dt_path . "vendor-prefixes.yaml";
3564cc93319bSFlorian Vaussard
3565bff5da43SRob Herring			foreach my $compat (@compats) {
3566bff5da43SRob Herring				my $compat2 = $compat;
3567185d566bSRob Herring				$compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/;
3568185d566bSRob Herring				my $compat3 = $compat;
3569185d566bSRob Herring				$compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/;
3570185d566bSRob Herring				`grep -Erq "$compat|$compat2|$compat3" $dt_path`;
3571bff5da43SRob Herring				if ( $? >> 8 ) {
3572bff5da43SRob Herring					WARN("UNDOCUMENTED_DT_STRING",
3573bff5da43SRob Herring					     "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
3574bff5da43SRob Herring				}
3575bff5da43SRob Herring
35764fbf32a6SFlorian Vaussard				next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
35774fbf32a6SFlorian Vaussard				my $vendor = $1;
3578852d095dSRob Herring				`grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`;
3579bff5da43SRob Herring				if ( $? >> 8 ) {
3580bff5da43SRob Herring					WARN("UNDOCUMENTED_DT_STRING",
3581cc93319bSFlorian Vaussard					     "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
3582bff5da43SRob Herring				}
3583bff5da43SRob Herring			}
3584bff5da43SRob Herring		}
3585bff5da43SRob Herring
35869f3a8992SRob Herring# check for using SPDX license tag at beginning of files
35879f3a8992SRob Herring		if ($realline == $checklicenseline) {
35889f3a8992SRob Herring			if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
35899f3a8992SRob Herring				$checklicenseline = 2;
35909f3a8992SRob Herring			} elsif ($rawline =~ /^\+/) {
35919f3a8992SRob Herring				my $comment = "";
35929f3a8992SRob Herring				if ($realfile =~ /\.(h|s|S)$/) {
35939f3a8992SRob Herring					$comment = '/*';
35949f3a8992SRob Herring				} elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
35959f3a8992SRob Herring					$comment = '//';
3596c8df0ab6SLubomir Rintel				} elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
35979f3a8992SRob Herring					$comment = '#';
35989f3a8992SRob Herring				} elsif ($realfile =~ /\.rst$/) {
35999f3a8992SRob Herring					$comment = '..';
36009f3a8992SRob Herring				}
36019f3a8992SRob Herring
3602fdf13693SJoe Perches# check SPDX comment style for .[chsS] files
3603fdf13693SJoe Perches				if ($realfile =~ /\.[chsS]$/ &&
3604fdf13693SJoe Perches				    $rawline =~ /SPDX-License-Identifier:/ &&
3605ffbce897SJoe Perches				    $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
3606fdf13693SJoe Perches					WARN("SPDX_LICENSE_TAG",
3607fdf13693SJoe Perches					     "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
3608fdf13693SJoe Perches				}
3609fdf13693SJoe Perches
36109f3a8992SRob Herring				if ($comment !~ /^$/ &&
3611ffbce897SJoe Perches				    $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
36129f3a8992SRob Herring					WARN("SPDX_LICENSE_TAG",
36139f3a8992SRob Herring					     "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
36143b6e8ac9SJoe Perches				} elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
36153b6e8ac9SJoe Perches					my $spdx_license = $1;
36163b6e8ac9SJoe Perches					if (!is_SPDX_License_valid($spdx_license)) {
36173b6e8ac9SJoe Perches						WARN("SPDX_LICENSE_TAG",
36183b6e8ac9SJoe Perches						     "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
36193b6e8ac9SJoe Perches					}
362050c92900SLubomir Rintel					if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
362150c92900SLubomir Rintel					    not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
362250c92900SLubomir Rintel						my $msg_level = \&WARN;
362350c92900SLubomir Rintel						$msg_level = \&CHK if ($file);
362450c92900SLubomir Rintel						if (&{$msg_level}("SPDX_LICENSE_TAG",
362550c92900SLubomir Rintel
362650c92900SLubomir Rintel								  "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) &&
362750c92900SLubomir Rintel						    $fix) {
362850c92900SLubomir Rintel							$fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
362950c92900SLubomir Rintel						}
363050c92900SLubomir Rintel					}
36319f3a8992SRob Herring				}
36329f3a8992SRob Herring			}
36339f3a8992SRob Herring		}
36349f3a8992SRob Herring
3635a0154cdbSJoe Perches# check for embedded filenames
3636a0154cdbSJoe Perches		if ($rawline =~ /^\+.*\Q$realfile\E/) {
3637a0154cdbSJoe Perches			WARN("EMBEDDED_FILENAME",
3638a0154cdbSJoe Perches			     "It's generally not useful to have the filename in the file\n" . $herecurr);
3639a0154cdbSJoe Perches		}
3640a0154cdbSJoe Perches
36415368df20SAndy Whitcroft# check we are in a valid source file if not then ignore this hunk
3642d6430f71SJoe Perches		next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
36435368df20SAndy Whitcroft
3644a8da38a9SJoe Perches# check for using SPDX-License-Identifier on the wrong line number
3645a8da38a9SJoe Perches		if ($realline != $checklicenseline &&
3646a8da38a9SJoe Perches		    $rawline =~ /\bSPDX-License-Identifier:/ &&
3647a8da38a9SJoe Perches		    substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
3648a8da38a9SJoe Perches			WARN("SPDX_LICENSE_TAG",
3649a8da38a9SJoe Perches			     "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
3650a8da38a9SJoe Perches		}
3651a8da38a9SJoe Perches
365247e0c88bSJoe Perches# line length limit (with some exclusions)
365347e0c88bSJoe Perches#
365447e0c88bSJoe Perches# There are a few types of lines that may extend beyond $max_line_length:
365547e0c88bSJoe Perches#	logging functions like pr_info that end in a string
365647e0c88bSJoe Perches#	lines with a single string
365747e0c88bSJoe Perches#	#defines that are a single string
36582e4bbbc5SAndreas Brauchli#	lines with an RFC3986 like URL
365947e0c88bSJoe Perches#
366047e0c88bSJoe Perches# There are 3 different line length message types:
3661ab1ecabfSJean Delvare# LONG_LINE_COMMENT	a comment starts before but extends beyond $max_line_length
366247e0c88bSJoe Perches# LONG_LINE_STRING	a string starts before but extends beyond $max_line_length
366347e0c88bSJoe Perches# LONG_LINE		all other lines longer than $max_line_length
366447e0c88bSJoe Perches#
366547e0c88bSJoe Perches# if LONG_LINE is ignored, the other 2 types are also ignored
366647e0c88bSJoe Perches#
366747e0c88bSJoe Perches
3668b4749e96SJoe Perches		if ($line =~ /^\+/ && $length > $max_line_length) {
366947e0c88bSJoe Perches			my $msg_type = "LONG_LINE";
367047e0c88bSJoe Perches
367147e0c88bSJoe Perches			# Check the allowed long line types first
367247e0c88bSJoe Perches
367347e0c88bSJoe Perches			# logging functions that end in a string that starts
367447e0c88bSJoe Perches			# before $max_line_length
367547e0c88bSJoe Perches			if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ &&
367647e0c88bSJoe Perches			    length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
367747e0c88bSJoe Perches				$msg_type = "";
367847e0c88bSJoe Perches
367947e0c88bSJoe Perches			# lines with only strings (w/ possible termination)
368047e0c88bSJoe Perches			# #defines with only strings
368147e0c88bSJoe Perches			} elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
368247e0c88bSJoe Perches				 $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
368347e0c88bSJoe Perches				$msg_type = "";
368447e0c88bSJoe Perches
3685cc147506SJoe Perches			# More special cases
3686cc147506SJoe Perches			} elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ ||
3687cc147506SJoe Perches				 $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) {
3688d560a5f8SJoe Perches				$msg_type = "";
3689d560a5f8SJoe Perches
36902e4bbbc5SAndreas Brauchli			# URL ($rawline is used in case the URL is in a comment)
36912e4bbbc5SAndreas Brauchli			} elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) {
36922e4bbbc5SAndreas Brauchli				$msg_type = "";
36932e4bbbc5SAndreas Brauchli
369447e0c88bSJoe Perches			# Otherwise set the alternate message types
369547e0c88bSJoe Perches
369647e0c88bSJoe Perches			# a comment starts before $max_line_length
369747e0c88bSJoe Perches			} elsif ($line =~ /($;[\s$;]*)$/ &&
369847e0c88bSJoe Perches				 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
369947e0c88bSJoe Perches				$msg_type = "LONG_LINE_COMMENT"
370047e0c88bSJoe Perches
370147e0c88bSJoe Perches			# a quoted string starts before $max_line_length
370247e0c88bSJoe Perches			} elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ &&
370347e0c88bSJoe Perches				 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
370447e0c88bSJoe Perches				$msg_type = "LONG_LINE_STRING"
370547e0c88bSJoe Perches			}
370647e0c88bSJoe Perches
370747e0c88bSJoe Perches			if ($msg_type ne "" &&
370847e0c88bSJoe Perches			    (show_type("LONG_LINE") || show_type($msg_type))) {
3709bdc48fa1SJoe Perches				my $msg_level = \&WARN;
3710bdc48fa1SJoe Perches				$msg_level = \&CHK if ($file);
3711bdc48fa1SJoe Perches				&{$msg_level}($msg_type,
3712bdc48fa1SJoe Perches					      "line length of $length exceeds $max_line_length columns\n" . $herecurr);
37130a920b5bSAndy Whitcroft			}
371447e0c88bSJoe Perches		}
37150a920b5bSAndy Whitcroft
37168905a67cSAndy Whitcroft# check for adding lines without a newline.
37178905a67cSAndy Whitcroft		if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
371847ca69b8STom Rix			if (WARN("MISSING_EOF_NEWLINE",
371947ca69b8STom Rix			         "adding a line without newline at end of file\n" . $herecurr) &&
372047ca69b8STom Rix			    $fix) {
372147ca69b8STom Rix				fix_delete_line($fixlinenr+1, "No newline at end of file");
372247ca69b8STom Rix			}
37238905a67cSAndy Whitcroft		}
37248905a67cSAndy Whitcroft
3725de93245cSAditya Srivastava# check for .L prefix local symbols in .S files
3726de93245cSAditya Srivastava		if ($realfile =~ /\.S$/ &&
3727de93245cSAditya Srivastava		    $line =~ /^\+\s*(?:[A-Z]+_)?SYM_[A-Z]+_(?:START|END)(?:_[A-Z_]+)?\s*\(\s*\.L/) {
3728de93245cSAditya Srivastava			WARN("AVOID_L_PREFIX",
3729de93245cSAditya Srivastava			     "Avoid using '.L' prefixed local symbol names for denoting a range of code via 'SYM_*_START/END' annotations; see Documentation/asm-annotations.rst\n" . $herecurr);
3730de93245cSAditya Srivastava		}
3731de93245cSAditya Srivastava
3732b9ea10d6SAndy Whitcroft# check we are in a valid source file C or perl if not then ignore this hunk
3733de4c924cSGeert Uytterhoeven		next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
37340a920b5bSAndy Whitcroft
37350a920b5bSAndy Whitcroft# at the beginning of a line any tabs must come first and anything
3736713a09deSAntonio Borneo# more than $tabsize must use tabs.
3737c2fdda0dSAndy Whitcroft		if ($rawline =~ /^\+\s* \t\s*\S/ ||
3738c2fdda0dSAndy Whitcroft		    $rawline =~ /^\+\s*        \s*/) {
3739c2fdda0dSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3740d2c0a235SAndy Whitcroft			$rpt_cleaners = 1;
37413705ce5bSJoe Perches			if (ERROR("CODE_INDENT",
37423705ce5bSJoe Perches				  "code indent should use tabs where possible\n" . $herevet) &&
37433705ce5bSJoe Perches			    $fix) {
3744194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
37453705ce5bSJoe Perches			}
37460a920b5bSAndy Whitcroft		}
37470a920b5bSAndy Whitcroft
374808e44365SAlberto Panizzo# check for space before tabs.
374908e44365SAlberto Panizzo		if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
375008e44365SAlberto Panizzo			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
37513705ce5bSJoe Perches			if (WARN("SPACE_BEFORE_TAB",
37523705ce5bSJoe Perches				"please, no space before tabs\n" . $herevet) &&
37533705ce5bSJoe Perches			    $fix) {
3754194f66fcSJoe Perches				while ($fixed[$fixlinenr] =~
3755713a09deSAntonio Borneo					   s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {}
3756194f66fcSJoe Perches				while ($fixed[$fixlinenr] =~
3757c76f4cb3SJoe Perches					   s/(^\+.*) +\t/$1\t/) {}
37583705ce5bSJoe Perches			}
375908e44365SAlberto Panizzo		}
376008e44365SAlberto Panizzo
37616a487211SJoe Perches# check for assignments on the start of a line
37626a487211SJoe Perches		if ($sline =~ /^\+\s+($Assignment)[^=]/) {
3763da7355abSAditya Srivastava			my $operator = $1;
3764da7355abSAditya Srivastava			if (CHK("ASSIGNMENT_CONTINUATIONS",
3765da7355abSAditya Srivastava				"Assignment operator '$1' should be on the previous line\n" . $hereprev) &&
3766da7355abSAditya Srivastava			    $fix && $prevrawline =~ /^\+/) {
3767da7355abSAditya Srivastava				# add assignment operator to the previous line, remove from current line
3768da7355abSAditya Srivastava				$fixed[$fixlinenr - 1] .= " $operator";
3769da7355abSAditya Srivastava				$fixed[$fixlinenr] =~ s/\Q$operator\E\s*//;
3770da7355abSAditya Srivastava			}
37716a487211SJoe Perches		}
37726a487211SJoe Perches
3773d1fe9c09SJoe Perches# check for && or || at the start of a line
3774d1fe9c09SJoe Perches		if ($rawline =~ /^\+\s*(&&|\|\|)/) {
37758e08f076SAditya Srivastava			my $operator = $1;
37768e08f076SAditya Srivastava			if (CHK("LOGICAL_CONTINUATIONS",
37778e08f076SAditya Srivastava				"Logical continuations should be on the previous line\n" . $hereprev) &&
37788e08f076SAditya Srivastava			    $fix && $prevrawline =~ /^\+/) {
37798e08f076SAditya Srivastava				# insert logical operator at last non-comment, non-whitepsace char on previous line
37808e08f076SAditya Srivastava				$prevline =~ /[\s$;]*$/;
37818e08f076SAditya Srivastava				my $line_end = substr($prevrawline, $-[0]);
37828e08f076SAditya Srivastava				$fixed[$fixlinenr - 1] =~ s/\Q$line_end\E$/ $operator$line_end/;
37838e08f076SAditya Srivastava				$fixed[$fixlinenr] =~ s/\Q$operator\E\s*//;
37848e08f076SAditya Srivastava			}
3785d1fe9c09SJoe Perches		}
3786d1fe9c09SJoe Perches
3787a91e8994SJoe Perches# check indentation starts on a tab stop
37885b57980dSJoe Perches		if ($perl_version_ok &&
3789bd49111fSJoe Perches		    $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
3790a91e8994SJoe Perches			my $indent = length($1);
3791713a09deSAntonio Borneo			if ($indent % $tabsize) {
3792a91e8994SJoe Perches				if (WARN("TABSTOP",
3793a91e8994SJoe Perches					 "Statements should start on a tabstop\n" . $herecurr) &&
3794a91e8994SJoe Perches				    $fix) {
3795713a09deSAntonio Borneo					$fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e;
3796a91e8994SJoe Perches				}
3797a91e8994SJoe Perches			}
3798a91e8994SJoe Perches		}
3799a91e8994SJoe Perches
3800d1fe9c09SJoe Perches# check multi-line statement indentation matches previous line
38015b57980dSJoe Perches		if ($perl_version_ok &&
3802fd71f632SJoe Perches		    $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
3803d1fe9c09SJoe Perches			$prevline =~ /^\+(\t*)(.*)$/;
3804d1fe9c09SJoe Perches			my $oldindent = $1;
3805d1fe9c09SJoe Perches			my $rest = $2;
3806d1fe9c09SJoe Perches
3807d1fe9c09SJoe Perches			my $pos = pos_last_openparen($rest);
3808d1fe9c09SJoe Perches			if ($pos >= 0) {
3809b34a26f3SJoe Perches				$line =~ /^(\+| )([ \t]*)/;
3810b34a26f3SJoe Perches				my $newindent = $2;
3811d1fe9c09SJoe Perches
3812d1fe9c09SJoe Perches				my $goodtabindent = $oldindent .
3813713a09deSAntonio Borneo					"\t" x ($pos / $tabsize) .
3814713a09deSAntonio Borneo					" "  x ($pos % $tabsize);
3815d1fe9c09SJoe Perches				my $goodspaceindent = $oldindent . " "  x $pos;
3816d1fe9c09SJoe Perches
3817d1fe9c09SJoe Perches				if ($newindent ne $goodtabindent &&
3818d1fe9c09SJoe Perches				    $newindent ne $goodspaceindent) {
38193705ce5bSJoe Perches
38203705ce5bSJoe Perches					if (CHK("PARENTHESIS_ALIGNMENT",
38213705ce5bSJoe Perches						"Alignment should match open parenthesis\n" . $hereprev) &&
38223705ce5bSJoe Perches					    $fix && $line =~ /^\+/) {
3823194f66fcSJoe Perches						$fixed[$fixlinenr] =~
38243705ce5bSJoe Perches						    s/^\+[ \t]*/\+$goodtabindent/;
38253705ce5bSJoe Perches					}
3826d1fe9c09SJoe Perches				}
3827d1fe9c09SJoe Perches			}
3828d1fe9c09SJoe Perches		}
3829d1fe9c09SJoe Perches
38306ab3a970SJoe Perches# check for space after cast like "(int) foo" or "(struct foo) bar"
38316ab3a970SJoe Perches# avoid checking a few false positives:
38326ab3a970SJoe Perches#   "sizeof(<type>)" or "__alignof__(<type>)"
38336ab3a970SJoe Perches#   function pointer declarations like "(*foo)(int) = bar;"
38346ab3a970SJoe Perches#   structure definitions like "(struct foo) { 0 };"
38356ab3a970SJoe Perches#   multiline macros that define functions
38366ab3a970SJoe Perches#   known attributes or the __attribute__ keyword
38376ab3a970SJoe Perches		if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ &&
38386ab3a970SJoe Perches		    (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) {
38393705ce5bSJoe Perches			if (CHK("SPACING",
3840f27c95dbSJoe Perches				"No space is necessary after a cast\n" . $herecurr) &&
38413705ce5bSJoe Perches			    $fix) {
3842194f66fcSJoe Perches				$fixed[$fixlinenr] =~
3843f27c95dbSJoe Perches				    s/(\(\s*$Type\s*\))[ \t]+/$1/;
38443705ce5bSJoe Perches			}
3845aad4f614SJoe Perches		}
3846aad4f614SJoe Perches
384786406b1cSJoe Perches# Block comment styles
384886406b1cSJoe Perches# Networking with an initial /*
384905880600SJoe Perches		if ($realfile =~ m@^(drivers/net/|net/)@ &&
3850fdb4bcd6SJoe Perches		    $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
385185ad978cSJoe Perches		    $rawline =~ /^\+[ \t]*\*/ &&
3852c70735c2SŁukasz Stelmach		    $realline > 3) { # Do not warn about the initial copyright comment block after SPDX-License-Identifier
385305880600SJoe Perches			WARN("NETWORKING_BLOCK_COMMENT_STYLE",
385405880600SJoe Perches			     "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
385505880600SJoe Perches		}
385605880600SJoe Perches
385786406b1cSJoe Perches# Block comments use * on subsequent lines
385886406b1cSJoe Perches		if ($prevline =~ /$;[ \t]*$/ &&			#ends in comment
385986406b1cSJoe Perches		    $prevrawline =~ /^\+.*?\/\*/ &&		#starting /*
3860a605e32eSJoe Perches		    $prevrawline !~ /\*\/[ \t]*$/ &&		#no trailing */
386161135e96SJoe Perches		    $rawline =~ /^\+/ &&			#line is new
3862a605e32eSJoe Perches		    $rawline !~ /^\+[ \t]*\*/) {		#no leading *
386386406b1cSJoe Perches			WARN("BLOCK_COMMENT_STYLE",
386486406b1cSJoe Perches			     "Block comments use * on subsequent lines\n" . $hereprev);
3865a605e32eSJoe Perches		}
3866a605e32eSJoe Perches
386786406b1cSJoe Perches# Block comments use */ on trailing lines
386886406b1cSJoe Perches		if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&	#trailing */
3869c24f9f19SJoe Perches		    $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&	#inline /*...*/
3870c24f9f19SJoe Perches		    $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&	#trailing **/
3871c24f9f19SJoe Perches		    $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {	#non blank */
387286406b1cSJoe Perches			WARN("BLOCK_COMMENT_STYLE",
387386406b1cSJoe Perches			     "Block comments use a trailing */ on a separate line\n" . $herecurr);
387405880600SJoe Perches		}
387505880600SJoe Perches
387608eb9b80SJoe Perches# Block comment * alignment
387708eb9b80SJoe Perches		if ($prevline =~ /$;[ \t]*$/ &&			#ends in comment
3878af207524SJoe Perches		    $line =~ /^\+[ \t]*$;/ &&			#leading comment
3879af207524SJoe Perches		    $rawline =~ /^\+[ \t]*\*/ &&		#leading *
3880af207524SJoe Perches		    (($prevrawline =~ /^\+.*?\/\*/ &&		#leading /*
388108eb9b80SJoe Perches		      $prevrawline !~ /\*\/[ \t]*$/) ||		#no trailing */
3882af207524SJoe Perches		     $prevrawline =~ /^\+[ \t]*\*/)) {		#leading *
3883af207524SJoe Perches			my $oldindent;
388408eb9b80SJoe Perches			$prevrawline =~ m@^\+([ \t]*/?)\*@;
3885af207524SJoe Perches			if (defined($1)) {
3886af207524SJoe Perches				$oldindent = expand_tabs($1);
3887af207524SJoe Perches			} else {
3888af207524SJoe Perches				$prevrawline =~ m@^\+(.*/?)\*@;
3889af207524SJoe Perches				$oldindent = expand_tabs($1);
3890af207524SJoe Perches			}
389108eb9b80SJoe Perches			$rawline =~ m@^\+([ \t]*)\*@;
389208eb9b80SJoe Perches			my $newindent = $1;
389308eb9b80SJoe Perches			$newindent = expand_tabs($newindent);
3894af207524SJoe Perches			if (length($oldindent) ne length($newindent)) {
389508eb9b80SJoe Perches				WARN("BLOCK_COMMENT_STYLE",
389608eb9b80SJoe Perches				     "Block comments should align the * on each line\n" . $hereprev);
389708eb9b80SJoe Perches			}
389808eb9b80SJoe Perches		}
389908eb9b80SJoe Perches
39007f619191SJoe Perches# check for missing blank lines after struct/union declarations
39017f619191SJoe Perches# with exceptions for various attributes and macros
39027f619191SJoe Perches		if ($prevline =~ /^[\+ ]};?\s*$/ &&
39037f619191SJoe Perches		    $line =~ /^\+/ &&
39047f619191SJoe Perches		    !($line =~ /^\+\s*$/ ||
39057f619191SJoe Perches		      $line =~ /^\+\s*EXPORT_SYMBOL/ ||
39067f619191SJoe Perches		      $line =~ /^\+\s*MODULE_/i ||
39077f619191SJoe Perches		      $line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
39087f619191SJoe Perches		      $line =~ /^\+[a-z_]*init/ ||
39097f619191SJoe Perches		      $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
39107f619191SJoe Perches		      $line =~ /^\+\s*DECLARE/ ||
39110bc989ffSMasahiro Yamada		      $line =~ /^\+\s*builtin_[\w_]*driver/ ||
39127f619191SJoe Perches		      $line =~ /^\+\s*__setup/)) {
3913d752fcc8SJoe Perches			if (CHK("LINE_SPACING",
3914d752fcc8SJoe Perches				"Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
3915d752fcc8SJoe Perches			    $fix) {
3916f2d7e4d4SJoe Perches				fix_insert_line($fixlinenr, "\+");
3917d752fcc8SJoe Perches			}
39187f619191SJoe Perches		}
39197f619191SJoe Perches
3920365dd4eaSJoe Perches# check for multiple consecutive blank lines
3921365dd4eaSJoe Perches		if ($prevline =~ /^[\+ ]\s*$/ &&
3922365dd4eaSJoe Perches		    $line =~ /^\+\s*$/ &&
3923365dd4eaSJoe Perches		    $last_blank_line != ($linenr - 1)) {
3924d752fcc8SJoe Perches			if (CHK("LINE_SPACING",
3925d752fcc8SJoe Perches				"Please don't use multiple blank lines\n" . $hereprev) &&
3926d752fcc8SJoe Perches			    $fix) {
3927f2d7e4d4SJoe Perches				fix_delete_line($fixlinenr, $rawline);
3928d752fcc8SJoe Perches			}
3929d752fcc8SJoe Perches
3930365dd4eaSJoe Perches			$last_blank_line = $linenr;
3931365dd4eaSJoe Perches		}
3932365dd4eaSJoe Perches
39333b617e3bSJoe Perches# check for missing blank lines after declarations
3934b5e8736aSJoe Perches# (declarations must have the same indentation and not be at the start of line)
3935b5e8736aSJoe Perches		if (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/) {
3936b5e8736aSJoe Perches			# use temporaries
3937b5e8736aSJoe Perches			my $sl = $sline;
3938b5e8736aSJoe Perches			my $pl = $prevline;
3939b5e8736aSJoe Perches			# remove $Attribute/$Sparse uses to simplify comparisons
3940b5e8736aSJoe Perches			$sl =~ s/\b(?:$Attribute|$Sparse)\b//g;
3941b5e8736aSJoe Perches			$pl =~ s/\b(?:$Attribute|$Sparse)\b//g;
3942b5e8736aSJoe Perches			if (($pl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
39435a4e1fd3SJoe Perches			# function pointer declarations
3944b5e8736aSJoe Perches			     $pl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
39453f7bac03SJoe Perches			# foo bar; where foo is some local typedef or #define
3946b5e8736aSJoe Perches			     $pl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
39473f7bac03SJoe Perches			# known declaration macros
3948b5e8736aSJoe Perches			     $pl =~ /^\+\s+$declaration_macros/) &&
39493f7bac03SJoe Perches			# for "else if" which can look like "$Ident $Ident"
3950b5e8736aSJoe Perches			    !($pl =~ /^\+\s+$c90_Keywords\b/ ||
39513f7bac03SJoe Perches			# other possible extensions of declaration lines
3952b5e8736aSJoe Perches			      $pl =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
39533f7bac03SJoe Perches			# not starting a section or a macro "\" extended line
3954b5e8736aSJoe Perches			      $pl =~ /(?:\{\s*|\\)$/) &&
39553f7bac03SJoe Perches			# looks like a declaration
3956b5e8736aSJoe Perches			    !($sl =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
39575a4e1fd3SJoe Perches			# function pointer declarations
3958b5e8736aSJoe Perches			      $sl =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
39593f7bac03SJoe Perches			# foo bar; where foo is some local typedef or #define
3960b5e8736aSJoe Perches			      $sl =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
39613f7bac03SJoe Perches			# known declaration macros
3962b5e8736aSJoe Perches			      $sl =~ /^\+\s+$declaration_macros/ ||
39633f7bac03SJoe Perches			# start of struct or union or enum
3964b5e8736aSJoe Perches			      $sl =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
39653f7bac03SJoe Perches			# start or end of block or continuation of declaration
3966b5e8736aSJoe Perches			      $sl =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
39673f7bac03SJoe Perches			# bitfield continuation
3968b5e8736aSJoe Perches			      $sl =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
39693f7bac03SJoe Perches			# other possible extensions of declaration lines
3970b5e8736aSJoe Perches			      $sl =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/)) {
3971d752fcc8SJoe Perches				if (WARN("LINE_SPACING",
3972d752fcc8SJoe Perches					 "Missing a blank line after declarations\n" . $hereprev) &&
3973d752fcc8SJoe Perches				    $fix) {
3974f2d7e4d4SJoe Perches					fix_insert_line($fixlinenr, "\+");
3975d752fcc8SJoe Perches				}
39763b617e3bSJoe Perches			}
3977b5e8736aSJoe Perches		}
39783b617e3bSJoe Perches
39795f7ddae6SRaffaele Recalcati# check for spaces at the beginning of a line.
39806b4c5bebSAndy Whitcroft# Exceptions:
39816b4c5bebSAndy Whitcroft#  1) within comments
39826b4c5bebSAndy Whitcroft#  2) indented preprocessor commands
39836b4c5bebSAndy Whitcroft#  3) hanging labels
39843705ce5bSJoe Perches		if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/)  {
39855f7ddae6SRaffaele Recalcati			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
39863705ce5bSJoe Perches			if (WARN("LEADING_SPACE",
39873705ce5bSJoe Perches				 "please, no spaces at the start of a line\n" . $herevet) &&
39883705ce5bSJoe Perches			    $fix) {
3989194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
39903705ce5bSJoe Perches			}
39915f7ddae6SRaffaele Recalcati		}
39925f7ddae6SRaffaele Recalcati
3993b9ea10d6SAndy Whitcroft# check we are in a valid C source file if not then ignore this hunk
3994b9ea10d6SAndy Whitcroft		next if ($realfile !~ /\.(h|c)$/);
3995b9ea10d6SAndy Whitcroft
39965751a24eSJoe Perches# check for unusual line ending [ or (
39975751a24eSJoe Perches		if ($line =~ /^\+.*([\[\(])\s*$/) {
39985751a24eSJoe Perches			CHK("OPEN_ENDED_LINE",
39995751a24eSJoe Perches			    "Lines should not end with a '$1'\n" . $herecurr);
40005751a24eSJoe Perches		}
40015751a24eSJoe Perches
40024dbed76fSJoe Perches# check if this appears to be the start function declaration, save the name
40034dbed76fSJoe Perches		if ($sline =~ /^\+\{\s*$/ &&
40044dbed76fSJoe Perches		    $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
40054dbed76fSJoe Perches			$context_function = $1;
40064dbed76fSJoe Perches		}
40074dbed76fSJoe Perches
40084dbed76fSJoe Perches# check if this appears to be the end of function declaration
40094dbed76fSJoe Perches		if ($sline =~ /^\+\}\s*$/) {
40104dbed76fSJoe Perches			undef $context_function;
40114dbed76fSJoe Perches		}
40124dbed76fSJoe Perches
4013032a4c0fSJoe Perches# check indentation of any line with a bare else
4014840080a0SJoe Perches# (but not if it is a multiple line "if (foo) return bar; else return baz;")
4015032a4c0fSJoe Perches# if the previous line is a break or return and is indented 1 tab more...
4016032a4c0fSJoe Perches		if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) {
4017032a4c0fSJoe Perches			my $tabs = length($1) + 1;
4018840080a0SJoe Perches			if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ ||
4019840080a0SJoe Perches			    ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ &&
4020840080a0SJoe Perches			     defined $lines[$linenr] &&
4021840080a0SJoe Perches			     $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) {
4022032a4c0fSJoe Perches				WARN("UNNECESSARY_ELSE",
4023032a4c0fSJoe Perches				     "else is not generally useful after a break or return\n" . $hereprev);
4024032a4c0fSJoe Perches			}
4025032a4c0fSJoe Perches		}
4026032a4c0fSJoe Perches
4027c00df19aSJoe Perches# check indentation of a line with a break;
4028dc58bc55SJoe Perches# if the previous line is a goto, return or break
4029dc58bc55SJoe Perches# and is indented the same # of tabs
4030c00df19aSJoe Perches		if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
4031c00df19aSJoe Perches			my $tabs = $1;
4032dc58bc55SJoe Perches			if ($prevline =~ /^\+$tabs(goto|return|break)\b/) {
4033dc58bc55SJoe Perches				if (WARN("UNNECESSARY_BREAK",
4034dc58bc55SJoe Perches					 "break is not useful after a $1\n" . $hereprev) &&
4035dc58bc55SJoe Perches				    $fix) {
4036dc58bc55SJoe Perches					fix_delete_line($fixlinenr, $rawline);
4037dc58bc55SJoe Perches				}
4038c00df19aSJoe Perches			}
4039c00df19aSJoe Perches		}
4040c00df19aSJoe Perches
4041c2fdda0dSAndy Whitcroft# check for RCS/CVS revision markers
4042cf655043SAndy Whitcroft		if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
4043000d1cc1SJoe Perches			WARN("CVS_KEYWORD",
4044000d1cc1SJoe Perches			     "CVS style keyword markers, these will _not_ be updated\n". $herecurr);
4045c2fdda0dSAndy Whitcroft		}
404622f2a2efSAndy Whitcroft
404756e77d70SJoe Perches# check for old HOTPLUG __dev<foo> section markings
404856e77d70SJoe Perches		if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) {
404956e77d70SJoe Perches			WARN("HOTPLUG_SECTION",
405056e77d70SJoe Perches			     "Using $1 is unnecessary\n" . $herecurr);
405156e77d70SJoe Perches		}
405256e77d70SJoe Perches
40539c0ca6f9SAndy Whitcroft# Check for potential 'bare' types
40542b474a1aSAndy Whitcroft		my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
40552b474a1aSAndy Whitcroft		    $realline_next);
40563e469cdcSAndy Whitcroft#print "LINE<$line>\n";
4057ca819864SJoe Perches		if ($linenr > $suppress_statement &&
40581b5539b1SJoe Perches		    $realcnt && $sline =~ /.\s*\S/) {
4059170d3a22SAndy Whitcroft			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
4060f5fe35ddSAndy Whitcroft				ctx_statement_block($linenr, $realcnt, 0);
4061171ae1a4SAndy Whitcroft			$stat =~ s/\n./\n /g;
4062171ae1a4SAndy Whitcroft			$cond =~ s/\n./\n /g;
4063171ae1a4SAndy Whitcroft
40643e469cdcSAndy Whitcroft#print "linenr<$linenr> <$stat>\n";
40653e469cdcSAndy Whitcroft			# If this statement has no statement boundaries within
40663e469cdcSAndy Whitcroft			# it there is no point in retrying a statement scan
40673e469cdcSAndy Whitcroft			# until we hit end of it.
40683e469cdcSAndy Whitcroft			my $frag = $stat; $frag =~ s/;+\s*$//;
40693e469cdcSAndy Whitcroft			if ($frag !~ /(?:{|;)/) {
40703e469cdcSAndy Whitcroft#print "skip<$line_nr_next>\n";
40713e469cdcSAndy Whitcroft				$suppress_statement = $line_nr_next;
40723e469cdcSAndy Whitcroft			}
4073f74bd194SAndy Whitcroft
40742b474a1aSAndy Whitcroft			# Find the real next line.
40752b474a1aSAndy Whitcroft			$realline_next = $line_nr_next;
40762b474a1aSAndy Whitcroft			if (defined $realline_next &&
40772b474a1aSAndy Whitcroft			    (!defined $lines[$realline_next - 1] ||
40782b474a1aSAndy Whitcroft			     substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
40792b474a1aSAndy Whitcroft				$realline_next++;
40802b474a1aSAndy Whitcroft			}
40812b474a1aSAndy Whitcroft
4082171ae1a4SAndy Whitcroft			my $s = $stat;
4083171ae1a4SAndy Whitcroft			$s =~ s/{.*$//s;
4084cf655043SAndy Whitcroft
4085c2fdda0dSAndy Whitcroft			# Ignore goto labels.
4086171ae1a4SAndy Whitcroft			if ($s =~ /$Ident:\*$/s) {
4087c2fdda0dSAndy Whitcroft
4088c2fdda0dSAndy Whitcroft			# Ignore functions being called
4089171ae1a4SAndy Whitcroft			} elsif ($s =~ /^.\s*$Ident\s*\(/s) {
4090c2fdda0dSAndy Whitcroft
4091463f2864SAndy Whitcroft			} elsif ($s =~ /^.\s*else\b/s) {
4092463f2864SAndy Whitcroft
4093c45dcabdSAndy Whitcroft			# declarations always start with types
4094d2506586SAndy Whitcroft			} 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) {
4095c45dcabdSAndy Whitcroft				my $type = $1;
4096c45dcabdSAndy Whitcroft				$type =~ s/\s+/ /g;
4097c45dcabdSAndy Whitcroft				possible($type, "A:" . $s);
4098c45dcabdSAndy Whitcroft
40996c72ffaaSAndy Whitcroft			# definitions in global scope can only start with types
4100a6a84062SAndy Whitcroft			} elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
4101c45dcabdSAndy Whitcroft				possible($1, "B:" . $s);
4102c2fdda0dSAndy Whitcroft			}
41038905a67cSAndy Whitcroft
41046c72ffaaSAndy Whitcroft			# any (foo ... *) is a pointer cast, and foo is a type
410565863862SAndy Whitcroft			while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
4106c45dcabdSAndy Whitcroft				possible($1, "C:" . $s);
41079c0ca6f9SAndy Whitcroft			}
41088905a67cSAndy Whitcroft
41098905a67cSAndy Whitcroft			# Check for any sort of function declaration.
41108905a67cSAndy Whitcroft			# int foo(something bar, other baz);
41118905a67cSAndy Whitcroft			# void (*store_gdt)(x86_descr_ptr *);
4112171ae1a4SAndy Whitcroft			if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
41138905a67cSAndy Whitcroft				my ($name_len) = length($1);
41148905a67cSAndy Whitcroft
4115cf655043SAndy Whitcroft				my $ctx = $s;
4116773647a0SAndy Whitcroft				substr($ctx, 0, $name_len + 1, '');
41178905a67cSAndy Whitcroft				$ctx =~ s/\)[^\)]*$//;
4118cf655043SAndy Whitcroft
41198905a67cSAndy Whitcroft				for my $arg (split(/\s*,\s*/, $ctx)) {
4120c45dcabdSAndy Whitcroft					if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
41218905a67cSAndy Whitcroft
4122c45dcabdSAndy Whitcroft						possible($1, "D:" . $s);
41238905a67cSAndy Whitcroft					}
41248905a67cSAndy Whitcroft				}
41258905a67cSAndy Whitcroft			}
41268905a67cSAndy Whitcroft
41279c0ca6f9SAndy Whitcroft		}
41289c0ca6f9SAndy Whitcroft
412900df344fSAndy Whitcroft#
413000df344fSAndy Whitcroft# Checks which may be anchored in the context.
413100df344fSAndy Whitcroft#
413200df344fSAndy Whitcroft
413300df344fSAndy Whitcroft# Check for switch () and associated case and default
413400df344fSAndy Whitcroft# statements should be at the same indent.
413500df344fSAndy Whitcroft		if ($line=~/\bswitch\s*\(.*\)/) {
413600df344fSAndy Whitcroft			my $err = '';
413700df344fSAndy Whitcroft			my $sep = '';
413800df344fSAndy Whitcroft			my @ctx = ctx_block_outer($linenr, $realcnt);
413900df344fSAndy Whitcroft			shift(@ctx);
414000df344fSAndy Whitcroft			for my $ctx (@ctx) {
414100df344fSAndy Whitcroft				my ($clen, $cindent) = line_stats($ctx);
414200df344fSAndy Whitcroft				if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
414300df344fSAndy Whitcroft							$indent != $cindent) {
414400df344fSAndy Whitcroft					$err .= "$sep$ctx\n";
414500df344fSAndy Whitcroft					$sep = '';
414600df344fSAndy Whitcroft				} else {
414700df344fSAndy Whitcroft					$sep = "[...]\n";
414800df344fSAndy Whitcroft				}
414900df344fSAndy Whitcroft			}
415000df344fSAndy Whitcroft			if ($err ne '') {
4151000d1cc1SJoe Perches				ERROR("SWITCH_CASE_INDENT_LEVEL",
4152000d1cc1SJoe Perches				      "switch and case should be at the same indent\n$hereline$err");
4153de7d4f0eSAndy Whitcroft			}
4154de7d4f0eSAndy Whitcroft		}
4155de7d4f0eSAndy Whitcroft
4156de7d4f0eSAndy Whitcroft# if/while/etc brace do not go on next line, unless defining a do while loop,
4157de7d4f0eSAndy Whitcroft# or if that brace on the next line is for something else
41580fe3dc2bSJoe Perches		if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
4159773647a0SAndy Whitcroft			my $pre_ctx = "$1$2";
4160773647a0SAndy Whitcroft
41619c0ca6f9SAndy Whitcroft			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
41628eef05ddSJoe Perches
41638eef05ddSJoe Perches			if ($line =~ /^\+\t{6,}/) {
41648eef05ddSJoe Perches				WARN("DEEP_INDENTATION",
41658eef05ddSJoe Perches				     "Too many leading tabs - consider code refactoring\n" . $herecurr);
41668eef05ddSJoe Perches			}
41678eef05ddSJoe Perches
4168de7d4f0eSAndy Whitcroft			my $ctx_cnt = $realcnt - $#ctx - 1;
4169de7d4f0eSAndy Whitcroft			my $ctx = join("\n", @ctx);
4170de7d4f0eSAndy Whitcroft
4171548596d5SAndy Whitcroft			my $ctx_ln = $linenr;
4172548596d5SAndy Whitcroft			my $ctx_skip = $realcnt;
4173de7d4f0eSAndy Whitcroft
4174548596d5SAndy Whitcroft			while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
4175548596d5SAndy Whitcroft					defined $lines[$ctx_ln - 1] &&
4176548596d5SAndy Whitcroft					$lines[$ctx_ln - 1] =~ /^-/)) {
4177548596d5SAndy Whitcroft				##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
4178548596d5SAndy Whitcroft				$ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
4179773647a0SAndy Whitcroft				$ctx_ln++;
4180773647a0SAndy Whitcroft			}
4181548596d5SAndy Whitcroft
418253210168SAndy Whitcroft			#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
418353210168SAndy Whitcroft			#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
4184773647a0SAndy Whitcroft
4185773647a0SAndy Whitcroft			if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
4186000d1cc1SJoe Perches				ERROR("OPEN_BRACE",
4187000d1cc1SJoe Perches				      "that open brace { should be on the previous line\n" .
418801464f30SAndy Whitcroft					"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
418900df344fSAndy Whitcroft			}
4190773647a0SAndy Whitcroft			if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
4191773647a0SAndy Whitcroft			    $ctx =~ /\)\s*\;\s*$/ &&
4192773647a0SAndy Whitcroft			    defined $lines[$ctx_ln - 1])
4193773647a0SAndy Whitcroft			{
41949c0ca6f9SAndy Whitcroft				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
41959c0ca6f9SAndy Whitcroft				if ($nindent > $indent) {
4196000d1cc1SJoe Perches					WARN("TRAILING_SEMICOLON",
4197000d1cc1SJoe Perches					     "trailing semicolon indicates no statements, indent implies otherwise\n" .
419801464f30SAndy Whitcroft						"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
41999c0ca6f9SAndy Whitcroft				}
42009c0ca6f9SAndy Whitcroft			}
420100df344fSAndy Whitcroft		}
420200df344fSAndy Whitcroft
42034d001e4dSAndy Whitcroft# Check relative indent for conditionals and blocks.
4204f6950a73SJoe Perches		if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
42053e469cdcSAndy Whitcroft			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
42063e469cdcSAndy Whitcroft				ctx_statement_block($linenr, $realcnt, 0)
42073e469cdcSAndy Whitcroft					if (!defined $stat);
42084d001e4dSAndy Whitcroft			my ($s, $c) = ($stat, $cond);
42094d001e4dSAndy Whitcroft
42104d001e4dSAndy Whitcroft			substr($s, 0, length($c), '');
42114d001e4dSAndy Whitcroft
42129f5af480SJoe Perches			# remove inline comments
42139f5af480SJoe Perches			$s =~ s/$;/ /g;
42149f5af480SJoe Perches			$c =~ s/$;/ /g;
42154d001e4dSAndy Whitcroft
42164d001e4dSAndy Whitcroft			# Find out how long the conditional actually is.
42176f779c18SAndy Whitcroft			my @newlines = ($c =~ /\n/gs);
42186f779c18SAndy Whitcroft			my $cond_lines = 1 + $#newlines;
42194d001e4dSAndy Whitcroft
42209f5af480SJoe Perches			# Make sure we remove the line prefixes as we have
42219f5af480SJoe Perches			# none on the first line, and are going to readd them
42229f5af480SJoe Perches			# where necessary.
42239f5af480SJoe Perches			$s =~ s/\n./\n/gs;
42249f5af480SJoe Perches			while ($s =~ /\n\s+\\\n/) {
42259f5af480SJoe Perches				$cond_lines += $s =~ s/\n\s+\\\n/\n/g;
42269f5af480SJoe Perches			}
42279f5af480SJoe Perches
42284d001e4dSAndy Whitcroft			# We want to check the first line inside the block
42294d001e4dSAndy Whitcroft			# starting at the end of the conditional, so remove:
42304d001e4dSAndy Whitcroft			#  1) any blank line termination
42314d001e4dSAndy Whitcroft			#  2) any opening brace { on end of the line
42324d001e4dSAndy Whitcroft			#  3) any do (...) {
42334d001e4dSAndy Whitcroft			my $continuation = 0;
42344d001e4dSAndy Whitcroft			my $check = 0;
42354d001e4dSAndy Whitcroft			$s =~ s/^.*\bdo\b//;
42364d001e4dSAndy Whitcroft			$s =~ s/^\s*{//;
42374d001e4dSAndy Whitcroft			if ($s =~ s/^\s*\\//) {
42384d001e4dSAndy Whitcroft				$continuation = 1;
42394d001e4dSAndy Whitcroft			}
42409bd49efeSAndy Whitcroft			if ($s =~ s/^\s*?\n//) {
42414d001e4dSAndy Whitcroft				$check = 1;
42424d001e4dSAndy Whitcroft				$cond_lines++;
42434d001e4dSAndy Whitcroft			}
42444d001e4dSAndy Whitcroft
42454d001e4dSAndy Whitcroft			# Also ignore a loop construct at the end of a
42464d001e4dSAndy Whitcroft			# preprocessor statement.
42474d001e4dSAndy Whitcroft			if (($prevline =~ /^.\s*#\s*define\s/ ||
42484d001e4dSAndy Whitcroft			    $prevline =~ /\\\s*$/) && $continuation == 0) {
42494d001e4dSAndy Whitcroft				$check = 0;
42504d001e4dSAndy Whitcroft			}
42514d001e4dSAndy Whitcroft
42529bd49efeSAndy Whitcroft			my $cond_ptr = -1;
4253740504c6SAndy Whitcroft			$continuation = 0;
42549bd49efeSAndy Whitcroft			while ($cond_ptr != $cond_lines) {
42559bd49efeSAndy Whitcroft				$cond_ptr = $cond_lines;
42564d001e4dSAndy Whitcroft
4257f16fa28fSAndy Whitcroft				# If we see an #else/#elif then the code
4258f16fa28fSAndy Whitcroft				# is not linear.
4259f16fa28fSAndy Whitcroft				if ($s =~ /^\s*\#\s*(?:else|elif)/) {
4260f16fa28fSAndy Whitcroft					$check = 0;
4261f16fa28fSAndy Whitcroft				}
4262f16fa28fSAndy Whitcroft
42639bd49efeSAndy Whitcroft				# Ignore:
42649bd49efeSAndy Whitcroft				#  1) blank lines, they should be at 0,
42659bd49efeSAndy Whitcroft				#  2) preprocessor lines, and
42669bd49efeSAndy Whitcroft				#  3) labels.
4267740504c6SAndy Whitcroft				if ($continuation ||
4268740504c6SAndy Whitcroft				    $s =~ /^\s*?\n/ ||
42699bd49efeSAndy Whitcroft				    $s =~ /^\s*#\s*?/ ||
42709bd49efeSAndy Whitcroft				    $s =~ /^\s*$Ident\s*:/) {
4271740504c6SAndy Whitcroft					$continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
427230dad6ebSAndy Whitcroft					if ($s =~ s/^.*?\n//) {
42739bd49efeSAndy Whitcroft						$cond_lines++;
42749bd49efeSAndy Whitcroft					}
42754d001e4dSAndy Whitcroft				}
427630dad6ebSAndy Whitcroft			}
42774d001e4dSAndy Whitcroft
42784d001e4dSAndy Whitcroft			my (undef, $sindent) = line_stats("+" . $s);
42794d001e4dSAndy Whitcroft			my $stat_real = raw_line($linenr, $cond_lines);
42804d001e4dSAndy Whitcroft
42814d001e4dSAndy Whitcroft			# Check if either of these lines are modified, else
42824d001e4dSAndy Whitcroft			# this is not this patch's fault.
42834d001e4dSAndy Whitcroft			if (!defined($stat_real) ||
42844d001e4dSAndy Whitcroft			    $stat !~ /^\+/ && $stat_real !~ /^\+/) {
42854d001e4dSAndy Whitcroft				$check = 0;
42864d001e4dSAndy Whitcroft			}
42874d001e4dSAndy Whitcroft			if (defined($stat_real) && $cond_lines > 1) {
42884d001e4dSAndy Whitcroft				$stat_real = "[...]\n$stat_real";
42894d001e4dSAndy Whitcroft			}
42904d001e4dSAndy Whitcroft
42919bd49efeSAndy Whitcroft			#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";
42924d001e4dSAndy Whitcroft
42939f5af480SJoe Perches			if ($check && $s ne '' &&
4294713a09deSAntonio Borneo			    (($sindent % $tabsize) != 0 ||
42959f5af480SJoe Perches			     ($sindent < $indent) ||
4296f6950a73SJoe Perches			     ($sindent == $indent &&
4297f6950a73SJoe Perches			      ($s !~ /^\s*(?:\}|\{|else\b)/)) ||
4298713a09deSAntonio Borneo			     ($sindent > $indent + $tabsize))) {
4299000d1cc1SJoe Perches				WARN("SUSPECT_CODE_INDENT",
4300000d1cc1SJoe Perches				     "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
43014d001e4dSAndy Whitcroft			}
43024d001e4dSAndy Whitcroft		}
43034d001e4dSAndy Whitcroft
43046c72ffaaSAndy Whitcroft		# Track the 'values' across context and added lines.
43056c72ffaaSAndy Whitcroft		my $opline = $line; $opline =~ s/^./ /;
43061f65f947SAndy Whitcroft		my ($curr_values, $curr_vars) =
43071f65f947SAndy Whitcroft				annotate_values($opline . "\n", $prev_values);
43086c72ffaaSAndy Whitcroft		$curr_values = $prev_values . $curr_values;
4309c2fdda0dSAndy Whitcroft		if ($dbg_values) {
4310c2fdda0dSAndy Whitcroft			my $outline = $opline; $outline =~ s/\t/ /g;
4311cf655043SAndy Whitcroft			print "$linenr > .$outline\n";
4312cf655043SAndy Whitcroft			print "$linenr > $curr_values\n";
43131f65f947SAndy Whitcroft			print "$linenr >  $curr_vars\n";
4314c2fdda0dSAndy Whitcroft		}
43156c72ffaaSAndy Whitcroft		$prev_values = substr($curr_values, -1);
43166c72ffaaSAndy Whitcroft
431700df344fSAndy Whitcroft#ignore lines not being added
43183705ce5bSJoe Perches		next if ($line =~ /^[^\+]/);
431900df344fSAndy Whitcroft
432099ca38c2SJoe Perches# check for self assignments used to avoid compiler warnings
432199ca38c2SJoe Perches# e.g.:	int foo = foo, *bar = NULL;
432299ca38c2SJoe Perches#	struct foo bar = *(&(bar));
432399ca38c2SJoe Perches		if ($line =~ /^\+\s*(?:$Declare)?([A-Za-z_][A-Za-z\d_]*)\s*=/) {
432499ca38c2SJoe Perches			my $var = $1;
432599ca38c2SJoe Perches			if ($line =~ /^\+\s*(?:$Declare)?$var\s*=\s*(?:$var|\*\s*\(?\s*&\s*\(?\s*$var\s*\)?\s*\)?)\s*[;,]/) {
432699ca38c2SJoe Perches				WARN("SELF_ASSIGNMENT",
432799ca38c2SJoe Perches				     "Do not use self-assignments to avoid compiler warnings\n" . $herecurr);
432899ca38c2SJoe Perches			}
432999ca38c2SJoe Perches		}
433099ca38c2SJoe Perches
433111ca40a0SJoe Perches# check for dereferences that span multiple lines
433211ca40a0SJoe Perches		if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ &&
433311ca40a0SJoe Perches		    $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) {
433411ca40a0SJoe Perches			$prevline =~ /($Lval\s*(?:\.|->))\s*$/;
433511ca40a0SJoe Perches			my $ref = $1;
433611ca40a0SJoe Perches			$line =~ /^.\s*($Lval)/;
433711ca40a0SJoe Perches			$ref .= $1;
433811ca40a0SJoe Perches			$ref =~ s/\s//g;
433911ca40a0SJoe Perches			WARN("MULTILINE_DEREFERENCE",
434011ca40a0SJoe Perches			     "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev);
434111ca40a0SJoe Perches		}
434211ca40a0SJoe Perches
4343a1ce18e4SJoe Perches# check for declarations of signed or unsigned without int
4344c8447115SJoe Perches		while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
4345a1ce18e4SJoe Perches			my $type = $1;
4346a1ce18e4SJoe Perches			my $var = $2;
4347207a8e84SJoe Perches			$var = "" if (!defined $var);
4348207a8e84SJoe Perches			if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
4349a1ce18e4SJoe Perches				my $sign = $1;
4350a1ce18e4SJoe Perches				my $pointer = $2;
4351a1ce18e4SJoe Perches
4352a1ce18e4SJoe Perches				$pointer = "" if (!defined $pointer);
4353a1ce18e4SJoe Perches
4354a1ce18e4SJoe Perches				if (WARN("UNSPECIFIED_INT",
4355a1ce18e4SJoe Perches					 "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) &&
4356a1ce18e4SJoe Perches				    $fix) {
4357a1ce18e4SJoe Perches					my $decl = trim($sign) . " int ";
4358207a8e84SJoe Perches					my $comp_pointer = $pointer;
4359207a8e84SJoe Perches					$comp_pointer =~ s/\s//g;
4360207a8e84SJoe Perches					$decl .= $comp_pointer;
4361207a8e84SJoe Perches					$decl = rtrim($decl) if ($var eq "");
4362207a8e84SJoe Perches					$fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
4363a1ce18e4SJoe Perches				}
4364a1ce18e4SJoe Perches			}
4365a1ce18e4SJoe Perches		}
4366a1ce18e4SJoe Perches
4367653d4876SAndy Whitcroft# TEST: allow direct testing of the type matcher.
43687429c690SAndy Whitcroft		if ($dbg_type) {
43697429c690SAndy Whitcroft			if ($line =~ /^.\s*$Declare\s*$/) {
4370000d1cc1SJoe Perches				ERROR("TEST_TYPE",
4371000d1cc1SJoe Perches				      "TEST: is type\n" . $herecurr);
43727429c690SAndy Whitcroft			} elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
4373000d1cc1SJoe Perches				ERROR("TEST_NOT_TYPE",
4374000d1cc1SJoe Perches				      "TEST: is not type ($1 is)\n". $herecurr);
43757429c690SAndy Whitcroft			}
4376653d4876SAndy Whitcroft			next;
4377653d4876SAndy Whitcroft		}
4378a1ef277eSAndy Whitcroft# TEST: allow direct testing of the attribute matcher.
4379a1ef277eSAndy Whitcroft		if ($dbg_attr) {
43809360b0e5SAndy Whitcroft			if ($line =~ /^.\s*$Modifier\s*$/) {
4381000d1cc1SJoe Perches				ERROR("TEST_ATTR",
4382000d1cc1SJoe Perches				      "TEST: is attr\n" . $herecurr);
43839360b0e5SAndy Whitcroft			} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
4384000d1cc1SJoe Perches				ERROR("TEST_NOT_ATTR",
4385000d1cc1SJoe Perches				      "TEST: is not attr ($1 is)\n". $herecurr);
4386a1ef277eSAndy Whitcroft			}
4387a1ef277eSAndy Whitcroft			next;
4388a1ef277eSAndy Whitcroft		}
4389653d4876SAndy Whitcroft
4390f0a594c1SAndy Whitcroft# check for initialisation to aggregates open brace on the next line
439199423c20SAndy Whitcroft		if ($line =~ /^.\s*{/ &&
439299423c20SAndy Whitcroft		    $prevline =~ /(?:^|[^=])=\s*$/) {
4393d752fcc8SJoe Perches			if (ERROR("OPEN_BRACE",
4394d752fcc8SJoe Perches				  "that open brace { should be on the previous line\n" . $hereprev) &&
4395f2d7e4d4SJoe Perches			    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
4396f2d7e4d4SJoe Perches				fix_delete_line($fixlinenr - 1, $prevrawline);
4397f2d7e4d4SJoe Perches				fix_delete_line($fixlinenr, $rawline);
4398d752fcc8SJoe Perches				my $fixedline = $prevrawline;
4399d752fcc8SJoe Perches				$fixedline =~ s/\s*=\s*$/ = {/;
4400f2d7e4d4SJoe Perches				fix_insert_line($fixlinenr, $fixedline);
4401d752fcc8SJoe Perches				$fixedline = $line;
44028d81ae05SCyril Bur				$fixedline =~ s/^(.\s*)\{\s*/$1/;
4403f2d7e4d4SJoe Perches				fix_insert_line($fixlinenr, $fixedline);
4404d752fcc8SJoe Perches			}
4405f0a594c1SAndy Whitcroft		}
4406f0a594c1SAndy Whitcroft
440700df344fSAndy Whitcroft#
440800df344fSAndy Whitcroft# Checks which are anchored on the added line.
440900df344fSAndy Whitcroft#
441000df344fSAndy Whitcroft
4411653d4876SAndy Whitcroft# check for malformed paths in #include statements (uses RAW line)
4412c45dcabdSAndy Whitcroft		if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
4413653d4876SAndy Whitcroft			my $path = $1;
4414653d4876SAndy Whitcroft			if ($path =~ m{//}) {
4415000d1cc1SJoe Perches				ERROR("MALFORMED_INCLUDE",
4416495e9d84SJoe Perches				      "malformed #include filename\n" . $herecurr);
4417495e9d84SJoe Perches			}
4418495e9d84SJoe Perches			if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) {
4419495e9d84SJoe Perches				ERROR("UAPI_INCLUDE",
4420495e9d84SJoe Perches				      "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr);
4421653d4876SAndy Whitcroft			}
4422653d4876SAndy Whitcroft		}
4423653d4876SAndy Whitcroft
442400df344fSAndy Whitcroft# no C99 // comments
442500df344fSAndy Whitcroft		if ($line =~ m{//}) {
44263705ce5bSJoe Perches			if (ERROR("C99_COMMENTS",
44273705ce5bSJoe Perches				  "do not use C99 // comments\n" . $herecurr) &&
44283705ce5bSJoe Perches			    $fix) {
4429194f66fcSJoe Perches				my $line = $fixed[$fixlinenr];
44303705ce5bSJoe Perches				if ($line =~ /\/\/(.*)$/) {
44313705ce5bSJoe Perches					my $comment = trim($1);
4432194f66fcSJoe Perches					$fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@;
44333705ce5bSJoe Perches				}
44343705ce5bSJoe Perches			}
443500df344fSAndy Whitcroft		}
443600df344fSAndy Whitcroft		# Remove C99 comments.
44370a920b5bSAndy Whitcroft		$line =~ s@//.*@@;
44386c72ffaaSAndy Whitcroft		$opline =~ s@//.*@@;
44390a920b5bSAndy Whitcroft
44402b474a1aSAndy Whitcroft# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
44412b474a1aSAndy Whitcroft# the whole statement.
44422b474a1aSAndy Whitcroft#print "APW <$lines[$realline_next - 1]>\n";
44432b474a1aSAndy Whitcroft		if (defined $realline_next &&
44442b474a1aSAndy Whitcroft		    exists $lines[$realline_next - 1] &&
44452b474a1aSAndy Whitcroft		    !defined $suppress_export{$realline_next} &&
444636794822SChristoph Hellwig		    ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
44473cbf62dfSAndy Whitcroft			# Handle definitions which produce identifiers with
44483cbf62dfSAndy Whitcroft			# a prefix:
44493cbf62dfSAndy Whitcroft			#   XXX(foo);
44503cbf62dfSAndy Whitcroft			#   EXPORT_SYMBOL(something_foo);
4451653d4876SAndy Whitcroft			my $name = $1;
445287a53877SAndy Whitcroft			if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
44533cbf62dfSAndy Whitcroft			    $name =~ /^${Ident}_$2/) {
44543cbf62dfSAndy Whitcroft#print "FOO C name<$name>\n";
44553cbf62dfSAndy Whitcroft				$suppress_export{$realline_next} = 1;
44563cbf62dfSAndy Whitcroft
44573cbf62dfSAndy Whitcroft			} elsif ($stat !~ /(?:
44582b474a1aSAndy Whitcroft				\n.}\s*$|
445948012058SAndy Whitcroft				^.DEFINE_$Ident\(\Q$name\E\)|
446048012058SAndy Whitcroft				^.DECLARE_$Ident\(\Q$name\E\)|
446148012058SAndy Whitcroft				^.LIST_HEAD\(\Q$name\E\)|
44622b474a1aSAndy Whitcroft				^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
44632b474a1aSAndy Whitcroft				\b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
446448012058SAndy Whitcroft			    )/x) {
44652b474a1aSAndy Whitcroft#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
44662b474a1aSAndy Whitcroft				$suppress_export{$realline_next} = 2;
44672b474a1aSAndy Whitcroft			} else {
44682b474a1aSAndy Whitcroft				$suppress_export{$realline_next} = 1;
44690a920b5bSAndy Whitcroft			}
44700a920b5bSAndy Whitcroft		}
44712b474a1aSAndy Whitcroft		if (!defined $suppress_export{$linenr} &&
44722b474a1aSAndy Whitcroft		    $prevline =~ /^.\s*$/ &&
447336794822SChristoph Hellwig		    ($line =~ /EXPORT_SYMBOL.*\((.*)\)/)) {
44742b474a1aSAndy Whitcroft#print "FOO B <$lines[$linenr - 1]>\n";
44752b474a1aSAndy Whitcroft			$suppress_export{$linenr} = 2;
44762b474a1aSAndy Whitcroft		}
44772b474a1aSAndy Whitcroft		if (defined $suppress_export{$linenr} &&
44782b474a1aSAndy Whitcroft		    $suppress_export{$linenr} == 2) {
4479000d1cc1SJoe Perches			WARN("EXPORT_SYMBOL",
4480000d1cc1SJoe Perches			     "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
44812b474a1aSAndy Whitcroft		}
44820a920b5bSAndy Whitcroft
44835150bda4SJoe Eloff# check for global initialisers.
44845b8f82e1SSong Liu		if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/ &&
44855b8f82e1SSong Liu		    !exclude_global_initialisers($realfile)) {
4486d5e616fcSJoe Perches			if (ERROR("GLOBAL_INITIALISERS",
44876d32f7a3SJoe Perches				  "do not initialise globals to $1\n" . $herecurr) &&
4488d5e616fcSJoe Perches			    $fix) {
44896d32f7a3SJoe Perches				$fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/;
4490d5e616fcSJoe Perches			}
4491f0a594c1SAndy Whitcroft		}
44920a920b5bSAndy Whitcroft# check for static initialisers.
44936d32f7a3SJoe Perches		if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) {
4494d5e616fcSJoe Perches			if (ERROR("INITIALISED_STATIC",
44956d32f7a3SJoe Perches				  "do not initialise statics to $1\n" .
4496d5e616fcSJoe Perches				      $herecurr) &&
4497d5e616fcSJoe Perches			    $fix) {
44986d32f7a3SJoe Perches				$fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/;
4499d5e616fcSJoe Perches			}
45000a920b5bSAndy Whitcroft		}
45010a920b5bSAndy Whitcroft
45021813087dSJoe Perches# check for misordered declarations of char/short/int/long with signed/unsigned
45031813087dSJoe Perches		while ($sline =~ m{(\b$TypeMisordered\b)}g) {
45041813087dSJoe Perches			my $tmp = trim($1);
45051813087dSJoe Perches			WARN("MISORDERED_TYPE",
45061813087dSJoe Perches			     "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
45071813087dSJoe Perches		}
45081813087dSJoe Perches
4509809e082eSJoe Perches# check for unnecessary <signed> int declarations of short/long/long long
4510809e082eSJoe Perches		while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
4511809e082eSJoe Perches			my $type = trim($1);
4512809e082eSJoe Perches			next if ($type !~ /\bint\b/);
4513809e082eSJoe Perches			next if ($type !~ /\b(?:short|long\s+long|long)\b/);
4514809e082eSJoe Perches			my $new_type = $type;
4515809e082eSJoe Perches			$new_type =~ s/\b\s*int\s*\b/ /;
4516809e082eSJoe Perches			$new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
4517809e082eSJoe Perches			$new_type =~ s/^const\s+//;
4518809e082eSJoe Perches			$new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
4519809e082eSJoe Perches			$new_type = "const $new_type" if ($type =~ /^const\b/);
4520809e082eSJoe Perches			$new_type =~ s/\s+/ /g;
4521809e082eSJoe Perches			$new_type = trim($new_type);
4522809e082eSJoe Perches			if (WARN("UNNECESSARY_INT",
4523809e082eSJoe Perches				 "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) &&
4524809e082eSJoe Perches			    $fix) {
4525809e082eSJoe Perches				$fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
4526809e082eSJoe Perches			}
4527809e082eSJoe Perches		}
4528809e082eSJoe Perches
4529cb710ecaSJoe Perches# check for static const char * arrays.
4530cb710ecaSJoe Perches		if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
4531000d1cc1SJoe Perches			WARN("STATIC_CONST_CHAR_ARRAY",
4532000d1cc1SJoe Perches			     "static const char * array should probably be static const char * const\n" .
4533cb710ecaSJoe Perches				$herecurr);
4534cb710ecaSJoe Perches		}
4535cb710ecaSJoe Perches
453677b8c0a8SJoe Perches# check for initialized const char arrays that should be static const
453777b8c0a8SJoe Perches		if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
453877b8c0a8SJoe Perches			if (WARN("STATIC_CONST_CHAR_ARRAY",
453977b8c0a8SJoe Perches				 "const array should probably be static const\n" . $herecurr) &&
454077b8c0a8SJoe Perches			    $fix) {
454177b8c0a8SJoe Perches				$fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
454277b8c0a8SJoe Perches			}
454377b8c0a8SJoe Perches		}
454477b8c0a8SJoe Perches
4545cb710ecaSJoe Perches# check for static char foo[] = "bar" declarations.
4546cb710ecaSJoe Perches		if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
4547000d1cc1SJoe Perches			WARN("STATIC_CONST_CHAR_ARRAY",
4548000d1cc1SJoe Perches			     "static char array declaration should probably be static const char\n" .
4549cb710ecaSJoe Perches				$herecurr);
4550cb710ecaSJoe Perches		}
4551cb710ecaSJoe Perches
4552ab7e23f3SJoe Perches# check for const <foo> const where <foo> is not a pointer or array type
4553ab7e23f3SJoe Perches		if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
4554ab7e23f3SJoe Perches			my $found = $1;
4555ab7e23f3SJoe Perches			if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) {
4556ab7e23f3SJoe Perches				WARN("CONST_CONST",
4557ab7e23f3SJoe Perches				     "'const $found const *' should probably be 'const $found * const'\n" . $herecurr);
4558ab7e23f3SJoe Perches			} elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) {
4559ab7e23f3SJoe Perches				WARN("CONST_CONST",
4560ab7e23f3SJoe Perches				     "'const $found const' should probably be 'const $found'\n" . $herecurr);
4561ab7e23f3SJoe Perches			}
4562ab7e23f3SJoe Perches		}
4563ab7e23f3SJoe Perches
456473169765SJoe Perches# check for const static or static <non ptr type> const declarations
456573169765SJoe Perches# prefer 'static const <foo>' over 'const static <foo>' and 'static <foo> const'
456673169765SJoe Perches		if ($sline =~ /^\+\s*const\s+static\s+($Type)\b/ ||
456773169765SJoe Perches		    $sline =~ /^\+\s*static\s+($BasicType)\s+const\b/) {
456873169765SJoe Perches			if (WARN("STATIC_CONST",
456973169765SJoe Perches				 "Move const after static - use 'static const $1'\n" . $herecurr) &&
457073169765SJoe Perches			    $fix) {
457173169765SJoe Perches				$fixed[$fixlinenr] =~ s/\bconst\s+static\b/static const/;
457273169765SJoe Perches				$fixed[$fixlinenr] =~ s/\bstatic\s+($BasicType)\s+const\b/static const $1/;
457373169765SJoe Perches			}
457473169765SJoe Perches		}
457573169765SJoe Perches
45769b0fa60dSJoe Perches# check for non-global char *foo[] = {"bar", ...} declarations.
45779b0fa60dSJoe Perches		if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
45789b0fa60dSJoe Perches			WARN("STATIC_CONST_CHAR_ARRAY",
45799b0fa60dSJoe Perches			     "char * array declaration might be better as static const\n" .
45809b0fa60dSJoe Perches				$herecurr);
45819b0fa60dSJoe Perches		}
45829b0fa60dSJoe Perches
4583b598b670SJoe Perches# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
4584b598b670SJoe Perches		if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
4585b598b670SJoe Perches			my $array = $1;
4586b598b670SJoe Perches			if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) {
4587b598b670SJoe Perches				my $array_div = $1;
4588b598b670SJoe Perches				if (WARN("ARRAY_SIZE",
4589b598b670SJoe Perches					 "Prefer ARRAY_SIZE($array)\n" . $herecurr) &&
4590b598b670SJoe Perches				    $fix) {
4591b598b670SJoe Perches					$fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/;
4592b598b670SJoe Perches				}
4593b598b670SJoe Perches			}
4594b598b670SJoe Perches		}
4595b598b670SJoe Perches
4596b36190c5SJoe Perches# check for function declarations without arguments like "int foo()"
459716b7f3c8SJoe Perches		if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
4598b36190c5SJoe Perches			if (ERROR("FUNCTION_WITHOUT_ARGS",
4599b36190c5SJoe Perches				  "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
4600b36190c5SJoe Perches			    $fix) {
4601194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
4602b36190c5SJoe Perches			}
4603b36190c5SJoe Perches		}
4604b36190c5SJoe Perches
4605653d4876SAndy Whitcroft# check for new typedefs, only function parameters and sparse annotations
4606653d4876SAndy Whitcroft# make sense.
4607653d4876SAndy Whitcroft		if ($line =~ /\btypedef\s/ &&
46088054576dSAndy Whitcroft		    $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
4609c45dcabdSAndy Whitcroft		    $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
46108ed22cadSAndy Whitcroft		    $line !~ /\b$typeTypedefs\b/ &&
461146d832f5SMichael S. Tsirkin		    $line !~ /\b__bitwise\b/) {
4612000d1cc1SJoe Perches			WARN("NEW_TYPEDEFS",
4613000d1cc1SJoe Perches			     "do not add new typedefs\n" . $herecurr);
46140a920b5bSAndy Whitcroft		}
46150a920b5bSAndy Whitcroft
46160a920b5bSAndy Whitcroft# * goes on variable not on type
461765863862SAndy Whitcroft		# (char*[ const])
4618bfcb2cc7SAndy Whitcroft		while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) {
4619bfcb2cc7SAndy Whitcroft			#print "AA<$1>\n";
46203705ce5bSJoe Perches			my ($ident, $from, $to) = ($1, $2, $2);
4621d8aaf121SAndy Whitcroft
462265863862SAndy Whitcroft			# Should start with a space.
462365863862SAndy Whitcroft			$to =~ s/^(\S)/ $1/;
462465863862SAndy Whitcroft			# Should not end with a space.
462565863862SAndy Whitcroft			$to =~ s/\s+$//;
462665863862SAndy Whitcroft			# '*'s should not have spaces between.
4627f9a0b3d1SAndy Whitcroft			while ($to =~ s/\*\s+\*/\*\*/) {
462865863862SAndy Whitcroft			}
4629d8aaf121SAndy Whitcroft
46303705ce5bSJoe Perches##			print "1: from<$from> to<$to> ident<$ident>\n";
463165863862SAndy Whitcroft			if ($from ne $to) {
46323705ce5bSJoe Perches				if (ERROR("POINTER_LOCATION",
46333705ce5bSJoe Perches					  "\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr) &&
46343705ce5bSJoe Perches				    $fix) {
46353705ce5bSJoe Perches					my $sub_from = $ident;
46363705ce5bSJoe Perches					my $sub_to = $ident;
46373705ce5bSJoe Perches					$sub_to =~ s/\Q$from\E/$to/;
4638194f66fcSJoe Perches					$fixed[$fixlinenr] =~
46393705ce5bSJoe Perches					    s@\Q$sub_from\E@$sub_to@;
46403705ce5bSJoe Perches				}
464165863862SAndy Whitcroft			}
4642bfcb2cc7SAndy Whitcroft		}
4643bfcb2cc7SAndy Whitcroft		while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) {
4644bfcb2cc7SAndy Whitcroft			#print "BB<$1>\n";
46453705ce5bSJoe Perches			my ($match, $from, $to, $ident) = ($1, $2, $2, $3);
4646d8aaf121SAndy Whitcroft
464765863862SAndy Whitcroft			# Should start with a space.
464865863862SAndy Whitcroft			$to =~ s/^(\S)/ $1/;
464965863862SAndy Whitcroft			# Should not end with a space.
465065863862SAndy Whitcroft			$to =~ s/\s+$//;
465165863862SAndy Whitcroft			# '*'s should not have spaces between.
4652f9a0b3d1SAndy Whitcroft			while ($to =~ s/\*\s+\*/\*\*/) {
465365863862SAndy Whitcroft			}
465465863862SAndy Whitcroft			# Modifiers should have spaces.
465565863862SAndy Whitcroft			$to =~ s/(\b$Modifier$)/$1 /;
465665863862SAndy Whitcroft
46573705ce5bSJoe Perches##			print "2: from<$from> to<$to> ident<$ident>\n";
4658667026e7SAndy Whitcroft			if ($from ne $to && $ident !~ /^$Modifier$/) {
46593705ce5bSJoe Perches				if (ERROR("POINTER_LOCATION",
46603705ce5bSJoe Perches					  "\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr) &&
46613705ce5bSJoe Perches				    $fix) {
46623705ce5bSJoe Perches
46633705ce5bSJoe Perches					my $sub_from = $match;
46643705ce5bSJoe Perches					my $sub_to = $match;
46653705ce5bSJoe Perches					$sub_to =~ s/\Q$from\E/$to/;
4666194f66fcSJoe Perches					$fixed[$fixlinenr] =~
46673705ce5bSJoe Perches					    s@\Q$sub_from\E@$sub_to@;
46683705ce5bSJoe Perches				}
466965863862SAndy Whitcroft			}
46700a920b5bSAndy Whitcroft		}
46710a920b5bSAndy Whitcroft
46729d3e3c70SJoe Perches# avoid BUG() or BUG_ON()
46739d3e3c70SJoe Perches		if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
46740675a8fbSJean Delvare			my $msg_level = \&WARN;
46750675a8fbSJean Delvare			$msg_level = \&CHK if ($file);
46760675a8fbSJean Delvare			&{$msg_level}("AVOID_BUG",
46779d3e3c70SJoe Perches				      "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
46789d3e3c70SJoe Perches		}
46790a920b5bSAndy Whitcroft
46809d3e3c70SJoe Perches# avoid LINUX_VERSION_CODE
46818905a67cSAndy Whitcroft		if ($line =~ /\bLINUX_VERSION_CODE\b/) {
4682000d1cc1SJoe Perches			WARN("LINUX_VERSION_CODE",
4683000d1cc1SJoe Perches			     "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
46848905a67cSAndy Whitcroft		}
46858905a67cSAndy Whitcroft
468617441227SJoe Perches# check for uses of printk_ratelimit
468717441227SJoe Perches		if ($line =~ /\bprintk_ratelimit\s*\(/) {
4688000d1cc1SJoe Perches			WARN("PRINTK_RATELIMITED",
4689000d1cc1SJoe Perches			     "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
469017441227SJoe Perches		}
469117441227SJoe Perches
4692eeef5733SJoe Perches# printk should use KERN_* levels
4693eeef5733SJoe Perches		if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) {
4694000d1cc1SJoe Perches			WARN("PRINTK_WITHOUT_KERN_LEVEL",
4695eeef5733SJoe Perches			     "printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
469600df344fSAndy Whitcroft		}
46970a920b5bSAndy Whitcroft
4698f5eea3b0SJoe Perches# prefer variants of (subsystem|netdev|dev|pr)_<level> to printk(KERN_<LEVEL>
4699f5eea3b0SJoe Perches		if ($line =~ /\b(printk(_once|_ratelimited)?)\s*\(\s*KERN_([A-Z]+)/) {
4700f5eea3b0SJoe Perches			my $printk = $1;
4701f5eea3b0SJoe Perches			my $modifier = $2;
4702f5eea3b0SJoe Perches			my $orig = $3;
4703f5eea3b0SJoe Perches			$modifier = "" if (!defined($modifier));
4704243f3803SJoe Perches			my $level = lc($orig);
4705243f3803SJoe Perches			$level = "warn" if ($level eq "warning");
47068f26b837SJoe Perches			my $level2 = $level;
47078f26b837SJoe Perches			$level2 = "dbg" if ($level eq "debug");
4708f5eea3b0SJoe Perches			$level .= $modifier;
4709f5eea3b0SJoe Perches			$level2 .= $modifier;
4710243f3803SJoe Perches			WARN("PREFER_PR_LEVEL",
4711f5eea3b0SJoe Perches			     "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(...  to $printk(KERN_$orig ...\n" . $herecurr);
4712243f3803SJoe Perches		}
4713243f3803SJoe Perches
4714f5eea3b0SJoe Perches# prefer dev_<level> to dev_printk(KERN_<LEVEL>
4715dc139313SJoe Perches		if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
4716dc139313SJoe Perches			my $orig = $1;
4717dc139313SJoe Perches			my $level = lc($orig);
4718dc139313SJoe Perches			$level = "warn" if ($level eq "warning");
4719dc139313SJoe Perches			$level = "dbg" if ($level eq "debug");
4720dc139313SJoe Perches			WARN("PREFER_DEV_LEVEL",
4721dc139313SJoe Perches			     "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr);
4722dc139313SJoe Perches		}
4723dc139313SJoe Perches
47248020b253SNicolas Boichat# trace_printk should not be used in production code.
47258020b253SNicolas Boichat		if ($line =~ /\b(trace_printk|trace_puts|ftrace_vprintk)\s*\(/) {
47268020b253SNicolas Boichat			WARN("TRACE_PRINTK",
47278020b253SNicolas Boichat			     "Do not use $1() in production code (this can be ignored if built only with a debug config option)\n" . $herecurr);
47288020b253SNicolas Boichat		}
47298020b253SNicolas Boichat
473091c9afafSAndy Lutomirski# ENOSYS means "bad syscall nr" and nothing else.  This will have a small
473191c9afafSAndy Lutomirski# number of false positives, but assembly files are not checked, so at
473291c9afafSAndy Lutomirski# least the arch entry code will not trigger this warning.
473391c9afafSAndy Lutomirski		if ($line =~ /\bENOSYS\b/) {
473491c9afafSAndy Lutomirski			WARN("ENOSYS",
473591c9afafSAndy Lutomirski			     "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr);
473691c9afafSAndy Lutomirski		}
473791c9afafSAndy Lutomirski
47386b9ea5ffSJakub Kicinski# ENOTSUPP is not a standard error code and should be avoided in new patches.
47396b9ea5ffSJakub Kicinski# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP.
47406b9ea5ffSJakub Kicinski# Similarly to ENOSYS warning a small number of false positives is expected.
47416b9ea5ffSJakub Kicinski		if (!$file && $line =~ /\bENOTSUPP\b/) {
47426b9ea5ffSJakub Kicinski			if (WARN("ENOTSUPP",
47436b9ea5ffSJakub Kicinski				 "ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr) &&
47446b9ea5ffSJakub Kicinski			    $fix) {
47456b9ea5ffSJakub Kicinski				$fixed[$fixlinenr] =~ s/\bENOTSUPP\b/EOPNOTSUPP/;
47466b9ea5ffSJakub Kicinski			}
47476b9ea5ffSJakub Kicinski		}
47486b9ea5ffSJakub Kicinski
4749653d4876SAndy Whitcroft# function brace can't be on same line, except for #defines of do while,
4750653d4876SAndy Whitcroft# or if closed on same line
47515b57980dSJoe Perches		if ($perl_version_ok &&
47522d453e3bSJoe Perches		    $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
47532d453e3bSJoe Perches		    $sline !~ /\#\s*define\b.*do\s*\{/ &&
47542d453e3bSJoe Perches		    $sline !~ /}/) {
47558d182478SJoe Perches			if (ERROR("OPEN_BRACE",
47562d453e3bSJoe Perches				  "open brace '{' following function definitions go on the next line\n" . $herecurr) &&
47578d182478SJoe Perches			    $fix) {
47588d182478SJoe Perches				fix_delete_line($fixlinenr, $rawline);
47598d182478SJoe Perches				my $fixed_line = $rawline;
476003f49351SDwaipayan Ray				$fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/;
47618d182478SJoe Perches				my $line1 = $1;
47628d182478SJoe Perches				my $line2 = $2;
47638d182478SJoe Perches				fix_insert_line($fixlinenr, ltrim($line1));
47648d182478SJoe Perches				fix_insert_line($fixlinenr, "\+{");
47658d182478SJoe Perches				if ($line2 !~ /^\s*$/) {
47668d182478SJoe Perches					fix_insert_line($fixlinenr, "\+\t" . trim($line2));
47678d182478SJoe Perches				}
47688d182478SJoe Perches			}
47690a920b5bSAndy Whitcroft		}
4770653d4876SAndy Whitcroft
47718905a67cSAndy Whitcroft# open braces for enum, union and struct go on the same line.
47728905a67cSAndy Whitcroft		if ($line =~ /^.\s*{/ &&
47738905a67cSAndy Whitcroft		    $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
47748d182478SJoe Perches			if (ERROR("OPEN_BRACE",
47758d182478SJoe Perches				  "open brace '{' following $1 go on the same line\n" . $hereprev) &&
47768d182478SJoe Perches			    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
47778d182478SJoe Perches				fix_delete_line($fixlinenr - 1, $prevrawline);
47788d182478SJoe Perches				fix_delete_line($fixlinenr, $rawline);
47798d182478SJoe Perches				my $fixedline = rtrim($prevrawline) . " {";
47808d182478SJoe Perches				fix_insert_line($fixlinenr, $fixedline);
47818d182478SJoe Perches				$fixedline = $rawline;
47828d81ae05SCyril Bur				$fixedline =~ s/^(.\s*)\{\s*/$1\t/;
47838d182478SJoe Perches				if ($fixedline !~ /^\+\s*$/) {
47848d182478SJoe Perches					fix_insert_line($fixlinenr, $fixedline);
47858d182478SJoe Perches				}
47868d182478SJoe Perches			}
47878905a67cSAndy Whitcroft		}
47888905a67cSAndy Whitcroft
47890c73b4ebSAndy Whitcroft# missing space after union, struct or enum definition
47903705ce5bSJoe Perches		if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) {
47913705ce5bSJoe Perches			if (WARN("SPACING",
47923705ce5bSJoe Perches				 "missing space after $1 definition\n" . $herecurr) &&
47933705ce5bSJoe Perches			    $fix) {
4794194f66fcSJoe Perches				$fixed[$fixlinenr] =~
47953705ce5bSJoe Perches				    s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
47963705ce5bSJoe Perches			}
47970c73b4ebSAndy Whitcroft		}
47980c73b4ebSAndy Whitcroft
479931070b5dSJoe Perches# Function pointer declarations
480031070b5dSJoe Perches# check spacing between type, funcptr, and args
480131070b5dSJoe Perches# canonical declaration is "type (*funcptr)(args...)"
480291f72e9cSJoe Perches		if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) {
480331070b5dSJoe Perches			my $declare = $1;
480431070b5dSJoe Perches			my $pre_pointer_space = $2;
480531070b5dSJoe Perches			my $post_pointer_space = $3;
480631070b5dSJoe Perches			my $funcname = $4;
480731070b5dSJoe Perches			my $post_funcname_space = $5;
480831070b5dSJoe Perches			my $pre_args_space = $6;
480931070b5dSJoe Perches
481091f72e9cSJoe Perches# the $Declare variable will capture all spaces after the type
481191f72e9cSJoe Perches# so check it for a missing trailing missing space but pointer return types
481291f72e9cSJoe Perches# don't need a space so don't warn for those.
481391f72e9cSJoe Perches			my $post_declare_space = "";
481491f72e9cSJoe Perches			if ($declare =~ /(\s+)$/) {
481591f72e9cSJoe Perches				$post_declare_space = $1;
481691f72e9cSJoe Perches				$declare = rtrim($declare);
481791f72e9cSJoe Perches			}
481891f72e9cSJoe Perches			if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) {
481931070b5dSJoe Perches				WARN("SPACING",
482031070b5dSJoe Perches				     "missing space after return type\n" . $herecurr);
482191f72e9cSJoe Perches				$post_declare_space = " ";
482231070b5dSJoe Perches			}
482331070b5dSJoe Perches
482431070b5dSJoe Perches# unnecessary space "type  (*funcptr)(args...)"
482591f72e9cSJoe Perches# This test is not currently implemented because these declarations are
482691f72e9cSJoe Perches# equivalent to
482791f72e9cSJoe Perches#	int  foo(int bar, ...)
482891f72e9cSJoe Perches# and this is form shouldn't/doesn't generate a checkpatch warning.
482991f72e9cSJoe Perches#
483091f72e9cSJoe Perches#			elsif ($declare =~ /\s{2,}$/) {
483191f72e9cSJoe Perches#				WARN("SPACING",
483291f72e9cSJoe Perches#				     "Multiple spaces after return type\n" . $herecurr);
483391f72e9cSJoe Perches#			}
483431070b5dSJoe Perches
483531070b5dSJoe Perches# unnecessary space "type ( *funcptr)(args...)"
483631070b5dSJoe Perches			if (defined $pre_pointer_space &&
483731070b5dSJoe Perches			    $pre_pointer_space =~ /^\s/) {
483831070b5dSJoe Perches				WARN("SPACING",
483931070b5dSJoe Perches				     "Unnecessary space after function pointer open parenthesis\n" . $herecurr);
484031070b5dSJoe Perches			}
484131070b5dSJoe Perches
484231070b5dSJoe Perches# unnecessary space "type (* funcptr)(args...)"
484331070b5dSJoe Perches			if (defined $post_pointer_space &&
484431070b5dSJoe Perches			    $post_pointer_space =~ /^\s/) {
484531070b5dSJoe Perches				WARN("SPACING",
484631070b5dSJoe Perches				     "Unnecessary space before function pointer name\n" . $herecurr);
484731070b5dSJoe Perches			}
484831070b5dSJoe Perches
484931070b5dSJoe Perches# unnecessary space "type (*funcptr )(args...)"
485031070b5dSJoe Perches			if (defined $post_funcname_space &&
485131070b5dSJoe Perches			    $post_funcname_space =~ /^\s/) {
485231070b5dSJoe Perches				WARN("SPACING",
485331070b5dSJoe Perches				     "Unnecessary space after function pointer name\n" . $herecurr);
485431070b5dSJoe Perches			}
485531070b5dSJoe Perches
485631070b5dSJoe Perches# unnecessary space "type (*funcptr) (args...)"
485731070b5dSJoe Perches			if (defined $pre_args_space &&
485831070b5dSJoe Perches			    $pre_args_space =~ /^\s/) {
485931070b5dSJoe Perches				WARN("SPACING",
486031070b5dSJoe Perches				     "Unnecessary space before function pointer arguments\n" . $herecurr);
486131070b5dSJoe Perches			}
486231070b5dSJoe Perches
486331070b5dSJoe Perches			if (show_type("SPACING") && $fix) {
4864194f66fcSJoe Perches				$fixed[$fixlinenr] =~
486591f72e9cSJoe Perches				    s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex;
486631070b5dSJoe Perches			}
486731070b5dSJoe Perches		}
486831070b5dSJoe Perches
48698d31cfceSAndy Whitcroft# check for spacing round square brackets; allowed:
48708d31cfceSAndy Whitcroft#  1. with a type on the left -- int [] a;
4871fe2a7dbcSAndy Whitcroft#  2. at the beginning of a line for slice initialisers -- [0...10] = 5,
4872fe2a7dbcSAndy Whitcroft#  3. inside a curly brace -- = { [0...10] = 5 }
48738d31cfceSAndy Whitcroft		while ($line =~ /(.*?\s)\[/g) {
48748d31cfceSAndy Whitcroft			my ($where, $prefix) = ($-[1], $1);
48758d31cfceSAndy Whitcroft			if ($prefix !~ /$Type\s+$/ &&
4876fe2a7dbcSAndy Whitcroft			    ($where != 0 || $prefix !~ /^.\s+$/) &&
487738dca988SHeinrich Schuchardt			    $prefix !~ /[{,:]\s+$/) {
48783705ce5bSJoe Perches				if (ERROR("BRACKET_SPACE",
48793705ce5bSJoe Perches					  "space prohibited before open square bracket '['\n" . $herecurr) &&
48803705ce5bSJoe Perches				    $fix) {
4881194f66fcSJoe Perches				    $fixed[$fixlinenr] =~
48823705ce5bSJoe Perches					s/^(\+.*?)\s+\[/$1\[/;
48833705ce5bSJoe Perches				}
48848d31cfceSAndy Whitcroft			}
48858d31cfceSAndy Whitcroft		}
48868d31cfceSAndy Whitcroft
4887f0a594c1SAndy Whitcroft# check for spaces between functions and their parentheses.
48886c72ffaaSAndy Whitcroft		while ($line =~ /($Ident)\s+\(/g) {
4889c2fdda0dSAndy Whitcroft			my $name = $1;
4890773647a0SAndy Whitcroft			my $ctx_before = substr($line, 0, $-[1]);
4891773647a0SAndy Whitcroft			my $ctx = "$ctx_before$name";
4892c2fdda0dSAndy Whitcroft
4893c2fdda0dSAndy Whitcroft			# Ignore those directives where spaces _are_ permitted.
4894773647a0SAndy Whitcroft			if ($name =~ /^(?:
4895773647a0SAndy Whitcroft				if|for|while|switch|return|case|
4896773647a0SAndy Whitcroft				volatile|__volatile__|
4897773647a0SAndy Whitcroft				__attribute__|format|__extension__|
4898773647a0SAndy Whitcroft				asm|__asm__)$/x)
4899773647a0SAndy Whitcroft			{
4900c2fdda0dSAndy Whitcroft			# cpp #define statements have non-optional spaces, ie
4901c2fdda0dSAndy Whitcroft			# if there is a space between the name and the open
4902c2fdda0dSAndy Whitcroft			# parenthesis it is simply not a parameter group.
4903c45dcabdSAndy Whitcroft			} elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
4904773647a0SAndy Whitcroft
4905773647a0SAndy Whitcroft			# cpp #elif statement condition may start with a (
4906c45dcabdSAndy Whitcroft			} elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
4907c2fdda0dSAndy Whitcroft
4908c2fdda0dSAndy Whitcroft			# If this whole things ends with a type its most
4909c2fdda0dSAndy Whitcroft			# likely a typedef for a function.
4910773647a0SAndy Whitcroft			} elsif ($ctx =~ /$Type$/) {
4911c2fdda0dSAndy Whitcroft
4912c2fdda0dSAndy Whitcroft			} else {
49133705ce5bSJoe Perches				if (WARN("SPACING",
49143705ce5bSJoe Perches					 "space prohibited between function name and open parenthesis '('\n" . $herecurr) &&
49153705ce5bSJoe Perches					     $fix) {
4916194f66fcSJoe Perches					$fixed[$fixlinenr] =~
49173705ce5bSJoe Perches					    s/\b$name\s+\(/$name\(/;
49183705ce5bSJoe Perches				}
4919f0a594c1SAndy Whitcroft			}
49206c72ffaaSAndy Whitcroft		}
49219a4cad4eSEric Nelson
4922653d4876SAndy Whitcroft# Check operator spacing.
49230a920b5bSAndy Whitcroft		if (!($line=~/\#\s*include/)) {
49243705ce5bSJoe Perches			my $fixed_line = "";
49253705ce5bSJoe Perches			my $line_fixed = 0;
49263705ce5bSJoe Perches
49279c0ca6f9SAndy Whitcroft			my $ops = qr{
49289c0ca6f9SAndy Whitcroft				<<=|>>=|<=|>=|==|!=|
49299c0ca6f9SAndy Whitcroft				\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
49309c0ca6f9SAndy Whitcroft				=>|->|<<|>>|<|>|=|!|~|
49311f65f947SAndy Whitcroft				&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
493284731623SJoe Perches				\?:|\?|:
49339c0ca6f9SAndy Whitcroft			}x;
4934cf655043SAndy Whitcroft			my @elements = split(/($ops|;)/, $opline);
49353705ce5bSJoe Perches
49363705ce5bSJoe Perches##			print("element count: <" . $#elements . ">\n");
49373705ce5bSJoe Perches##			foreach my $el (@elements) {
49383705ce5bSJoe Perches##				print("el: <$el>\n");
49393705ce5bSJoe Perches##			}
49403705ce5bSJoe Perches
49413705ce5bSJoe Perches			my @fix_elements = ();
494200df344fSAndy Whitcroft			my $off = 0;
49436c72ffaaSAndy Whitcroft
49443705ce5bSJoe Perches			foreach my $el (@elements) {
49453705ce5bSJoe Perches				push(@fix_elements, substr($rawline, $off, length($el)));
49463705ce5bSJoe Perches				$off += length($el);
49473705ce5bSJoe Perches			}
49483705ce5bSJoe Perches
49493705ce5bSJoe Perches			$off = 0;
49503705ce5bSJoe Perches
49516c72ffaaSAndy Whitcroft			my $blank = copy_spacing($opline);
4952b34c648bSJoe Perches			my $last_after = -1;
49536c72ffaaSAndy Whitcroft
49540a920b5bSAndy Whitcroft			for (my $n = 0; $n < $#elements; $n += 2) {
49553705ce5bSJoe Perches
49563705ce5bSJoe Perches				my $good = $fix_elements[$n] . $fix_elements[$n + 1];
49573705ce5bSJoe Perches
49583705ce5bSJoe Perches##				print("n: <$n> good: <$good>\n");
49593705ce5bSJoe Perches
49604a0df2efSAndy Whitcroft				$off += length($elements[$n]);
49614a0df2efSAndy Whitcroft
496225985edcSLucas De Marchi				# Pick up the preceding and succeeding characters.
4963773647a0SAndy Whitcroft				my $ca = substr($opline, 0, $off);
4964773647a0SAndy Whitcroft				my $cc = '';
4965773647a0SAndy Whitcroft				if (length($opline) >= ($off + length($elements[$n + 1]))) {
4966773647a0SAndy Whitcroft					$cc = substr($opline, $off + length($elements[$n + 1]));
4967773647a0SAndy Whitcroft				}
4968773647a0SAndy Whitcroft				my $cb = "$ca$;$cc";
4969773647a0SAndy Whitcroft
49704a0df2efSAndy Whitcroft				my $a = '';
49714a0df2efSAndy Whitcroft				$a = 'V' if ($elements[$n] ne '');
49724a0df2efSAndy Whitcroft				$a = 'W' if ($elements[$n] =~ /\s$/);
4973cf655043SAndy Whitcroft				$a = 'C' if ($elements[$n] =~ /$;$/);
49744a0df2efSAndy Whitcroft				$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
49754a0df2efSAndy Whitcroft				$a = 'O' if ($elements[$n] eq '');
4976773647a0SAndy Whitcroft				$a = 'E' if ($ca =~ /^\s*$/);
49774a0df2efSAndy Whitcroft
49780a920b5bSAndy Whitcroft				my $op = $elements[$n + 1];
49794a0df2efSAndy Whitcroft
49804a0df2efSAndy Whitcroft				my $c = '';
49810a920b5bSAndy Whitcroft				if (defined $elements[$n + 2]) {
49824a0df2efSAndy Whitcroft					$c = 'V' if ($elements[$n + 2] ne '');
49834a0df2efSAndy Whitcroft					$c = 'W' if ($elements[$n + 2] =~ /^\s/);
4984cf655043SAndy Whitcroft					$c = 'C' if ($elements[$n + 2] =~ /^$;/);
49854a0df2efSAndy Whitcroft					$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
49864a0df2efSAndy Whitcroft					$c = 'O' if ($elements[$n + 2] eq '');
49878b1b3378SAndy Whitcroft					$c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
49884a0df2efSAndy Whitcroft				} else {
49894a0df2efSAndy Whitcroft					$c = 'E';
49900a920b5bSAndy Whitcroft				}
49910a920b5bSAndy Whitcroft
49924a0df2efSAndy Whitcroft				my $ctx = "${a}x${c}";
49934a0df2efSAndy Whitcroft
49944a0df2efSAndy Whitcroft				my $at = "(ctx:$ctx)";
49954a0df2efSAndy Whitcroft
49966c72ffaaSAndy Whitcroft				my $ptr = substr($blank, 0, $off) . "^";
4997de7d4f0eSAndy Whitcroft				my $hereptr = "$hereline$ptr\n";
49980a920b5bSAndy Whitcroft
499974048ed8SAndy Whitcroft				# Pull out the value of this operator.
50006c72ffaaSAndy Whitcroft				my $op_type = substr($curr_values, $off + 1, 1);
50010a920b5bSAndy Whitcroft
50021f65f947SAndy Whitcroft				# Get the full operator variant.
50031f65f947SAndy Whitcroft				my $opv = $op . substr($curr_vars, $off, 1);
50041f65f947SAndy Whitcroft
500513214adfSAndy Whitcroft				# Ignore operators passed as parameters.
500613214adfSAndy Whitcroft				if ($op_type ne 'V' &&
5007d7fe8065SSam Bobroff				    $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) {
500813214adfSAndy Whitcroft
5009cf655043SAndy Whitcroft#				# Ignore comments
5010cf655043SAndy Whitcroft#				} elsif ($op =~ /^$;+$/) {
501113214adfSAndy Whitcroft
5012d8aaf121SAndy Whitcroft				# ; should have either the end of line or a space or \ after it
501313214adfSAndy Whitcroft				} elsif ($op eq ';') {
5014cf655043SAndy Whitcroft					if ($ctx !~ /.x[WEBC]/ &&
5015cf655043SAndy Whitcroft					    $cc !~ /^\\/ && $cc !~ /^;/) {
50163705ce5bSJoe Perches						if (ERROR("SPACING",
50173705ce5bSJoe Perches							  "space required after that '$op' $at\n" . $hereptr)) {
5018b34c648bSJoe Perches							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
50193705ce5bSJoe Perches							$line_fixed = 1;
50203705ce5bSJoe Perches						}
5021d8aaf121SAndy Whitcroft					}
5022d8aaf121SAndy Whitcroft
5023d8aaf121SAndy Whitcroft				# // is a comment
5024d8aaf121SAndy Whitcroft				} elsif ($op eq '//') {
50250a920b5bSAndy Whitcroft
5026b00e4814SJoe Perches				#   :   when part of a bitfield
5027b00e4814SJoe Perches				} elsif ($opv eq ':B') {
5028b00e4814SJoe Perches					# skip the bitfield test for now
5029b00e4814SJoe Perches
50301f65f947SAndy Whitcroft				# No spaces for:
50311f65f947SAndy Whitcroft				#   ->
5032b00e4814SJoe Perches				} elsif ($op eq '->') {
50334a0df2efSAndy Whitcroft					if ($ctx =~ /Wx.|.xW/) {
50343705ce5bSJoe Perches						if (ERROR("SPACING",
50353705ce5bSJoe Perches							  "spaces prohibited around that '$op' $at\n" . $hereptr)) {
5036b34c648bSJoe Perches							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
50373705ce5bSJoe Perches							if (defined $fix_elements[$n + 2]) {
50383705ce5bSJoe Perches								$fix_elements[$n + 2] =~ s/^\s+//;
50393705ce5bSJoe Perches							}
5040b34c648bSJoe Perches							$line_fixed = 1;
50413705ce5bSJoe Perches						}
50420a920b5bSAndy Whitcroft					}
50430a920b5bSAndy Whitcroft
50442381097bSJoe Perches				# , must not have a space before and must have a space on the right.
50450a920b5bSAndy Whitcroft				} elsif ($op eq ',') {
50462381097bSJoe Perches					my $rtrim_before = 0;
50472381097bSJoe Perches					my $space_after = 0;
50482381097bSJoe Perches					if ($ctx =~ /Wx./) {
50492381097bSJoe Perches						if (ERROR("SPACING",
50502381097bSJoe Perches							  "space prohibited before that '$op' $at\n" . $hereptr)) {
50512381097bSJoe Perches							$line_fixed = 1;
50522381097bSJoe Perches							$rtrim_before = 1;
50532381097bSJoe Perches						}
50542381097bSJoe Perches					}
5055cf655043SAndy Whitcroft					if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
50563705ce5bSJoe Perches						if (ERROR("SPACING",
50573705ce5bSJoe Perches							  "space required after that '$op' $at\n" . $hereptr)) {
50583705ce5bSJoe Perches							$line_fixed = 1;
5059b34c648bSJoe Perches							$last_after = $n;
50602381097bSJoe Perches							$space_after = 1;
50612381097bSJoe Perches						}
50622381097bSJoe Perches					}
50632381097bSJoe Perches					if ($rtrim_before || $space_after) {
50642381097bSJoe Perches						if ($rtrim_before) {
50652381097bSJoe Perches							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
50662381097bSJoe Perches						} else {
50672381097bSJoe Perches							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
50682381097bSJoe Perches						}
50692381097bSJoe Perches						if ($space_after) {
50702381097bSJoe Perches							$good .= " ";
50713705ce5bSJoe Perches						}
50720a920b5bSAndy Whitcroft					}
50730a920b5bSAndy Whitcroft
50749c0ca6f9SAndy Whitcroft				# '*' as part of a type definition -- reported already.
507574048ed8SAndy Whitcroft				} elsif ($opv eq '*_') {
50769c0ca6f9SAndy Whitcroft					#warn "'*' is part of type\n";
50779c0ca6f9SAndy Whitcroft
50789c0ca6f9SAndy Whitcroft				# unary operators should have a space before and
50799c0ca6f9SAndy Whitcroft				# none after.  May be left adjacent to another
50809c0ca6f9SAndy Whitcroft				# unary operator, or a cast
50819c0ca6f9SAndy Whitcroft				} elsif ($op eq '!' || $op eq '~' ||
508274048ed8SAndy Whitcroft					 $opv eq '*U' || $opv eq '-U' ||
50830d413866SAndy Whitcroft					 $opv eq '&U' || $opv eq '&&U') {
5084cf655043SAndy Whitcroft					if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
50853705ce5bSJoe Perches						if (ERROR("SPACING",
50863705ce5bSJoe Perches							  "space required before that '$op' $at\n" . $hereptr)) {
5087b34c648bSJoe Perches							if ($n != $last_after + 2) {
5088b34c648bSJoe Perches								$good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]);
50893705ce5bSJoe Perches								$line_fixed = 1;
50903705ce5bSJoe Perches							}
50910a920b5bSAndy Whitcroft						}
5092b34c648bSJoe Perches					}
5093a3340b35SAndy Whitcroft					if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
5094171ae1a4SAndy Whitcroft						# A unary '*' may be const
5095171ae1a4SAndy Whitcroft
5096171ae1a4SAndy Whitcroft					} elsif ($ctx =~ /.xW/) {
50973705ce5bSJoe Perches						if (ERROR("SPACING",
50983705ce5bSJoe Perches							  "space prohibited after that '$op' $at\n" . $hereptr)) {
5099b34c648bSJoe Perches							$good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]);
51003705ce5bSJoe Perches							if (defined $fix_elements[$n + 2]) {
51013705ce5bSJoe Perches								$fix_elements[$n + 2] =~ s/^\s+//;
51023705ce5bSJoe Perches							}
5103b34c648bSJoe Perches							$line_fixed = 1;
51043705ce5bSJoe Perches						}
51050a920b5bSAndy Whitcroft					}
51060a920b5bSAndy Whitcroft
51070a920b5bSAndy Whitcroft				# unary ++ and unary -- are allowed no space on one side.
51080a920b5bSAndy Whitcroft				} elsif ($op eq '++' or $op eq '--') {
5109773647a0SAndy Whitcroft					if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
51103705ce5bSJoe Perches						if (ERROR("SPACING",
51113705ce5bSJoe Perches							  "space required one side of that '$op' $at\n" . $hereptr)) {
5112b34c648bSJoe Perches							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
51133705ce5bSJoe Perches							$line_fixed = 1;
51143705ce5bSJoe Perches						}
51150a920b5bSAndy Whitcroft					}
5116773647a0SAndy Whitcroft					if ($ctx =~ /Wx[BE]/ ||
5117773647a0SAndy Whitcroft					    ($ctx =~ /Wx./ && $cc =~ /^;/)) {
51183705ce5bSJoe Perches						if (ERROR("SPACING",
51193705ce5bSJoe Perches							  "space prohibited before that '$op' $at\n" . $hereptr)) {
5120b34c648bSJoe Perches							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
51213705ce5bSJoe Perches							$line_fixed = 1;
51223705ce5bSJoe Perches						}
5123653d4876SAndy Whitcroft					}
5124773647a0SAndy Whitcroft					if ($ctx =~ /ExW/) {
51253705ce5bSJoe Perches						if (ERROR("SPACING",
51263705ce5bSJoe Perches							  "space prohibited after that '$op' $at\n" . $hereptr)) {
5127b34c648bSJoe Perches							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
51283705ce5bSJoe Perches							if (defined $fix_elements[$n + 2]) {
51293705ce5bSJoe Perches								$fix_elements[$n + 2] =~ s/^\s+//;
5130773647a0SAndy Whitcroft							}
5131b34c648bSJoe Perches							$line_fixed = 1;
51323705ce5bSJoe Perches						}
51333705ce5bSJoe Perches					}
51340a920b5bSAndy Whitcroft
51350a920b5bSAndy Whitcroft				# << and >> may either have or not have spaces both sides
51369c0ca6f9SAndy Whitcroft				} elsif ($op eq '<<' or $op eq '>>' or
51379c0ca6f9SAndy Whitcroft					 $op eq '&' or $op eq '^' or $op eq '|' or
51389c0ca6f9SAndy Whitcroft					 $op eq '+' or $op eq '-' or
5139c2fdda0dSAndy Whitcroft					 $op eq '*' or $op eq '/' or
5140c2fdda0dSAndy Whitcroft					 $op eq '%')
51410a920b5bSAndy Whitcroft				{
5142d2e025f3SJoe Perches					if ($check) {
5143d2e025f3SJoe Perches						if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) {
5144d2e025f3SJoe Perches							if (CHK("SPACING",
5145d2e025f3SJoe Perches								"spaces preferred around that '$op' $at\n" . $hereptr)) {
5146d2e025f3SJoe Perches								$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
5147d2e025f3SJoe Perches								$fix_elements[$n + 2] =~ s/^\s+//;
5148d2e025f3SJoe Perches								$line_fixed = 1;
5149d2e025f3SJoe Perches							}
5150d2e025f3SJoe Perches						} elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) {
5151d2e025f3SJoe Perches							if (CHK("SPACING",
5152d2e025f3SJoe Perches								"space preferred before that '$op' $at\n" . $hereptr)) {
5153d2e025f3SJoe Perches								$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]);
5154d2e025f3SJoe Perches								$line_fixed = 1;
5155d2e025f3SJoe Perches							}
5156d2e025f3SJoe Perches						}
5157d2e025f3SJoe Perches					} elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
51583705ce5bSJoe Perches						if (ERROR("SPACING",
51593705ce5bSJoe Perches							  "need consistent spacing around '$op' $at\n" . $hereptr)) {
5160b34c648bSJoe Perches							$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
5161b34c648bSJoe Perches							if (defined $fix_elements[$n + 2]) {
5162b34c648bSJoe Perches								$fix_elements[$n + 2] =~ s/^\s+//;
5163b34c648bSJoe Perches							}
51643705ce5bSJoe Perches							$line_fixed = 1;
51653705ce5bSJoe Perches						}
51660a920b5bSAndy Whitcroft					}
51670a920b5bSAndy Whitcroft
51681f65f947SAndy Whitcroft				# A colon needs no spaces before when it is
51691f65f947SAndy Whitcroft				# terminating a case value or a label.
51701f65f947SAndy Whitcroft				} elsif ($opv eq ':C' || $opv eq ':L') {
5171263afd39SChris Down					if ($ctx =~ /Wx./ and $realfile !~ m@.*\.lds\.h$@) {
51723705ce5bSJoe Perches						if (ERROR("SPACING",
51733705ce5bSJoe Perches							  "space prohibited before that '$op' $at\n" . $hereptr)) {
5174b34c648bSJoe Perches							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
51753705ce5bSJoe Perches							$line_fixed = 1;
51763705ce5bSJoe Perches						}
51771f65f947SAndy Whitcroft					}
51781f65f947SAndy Whitcroft
51790a920b5bSAndy Whitcroft				# All the others need spaces both sides.
5180cf655043SAndy Whitcroft				} elsif ($ctx !~ /[EWC]x[CWE]/) {
51811f65f947SAndy Whitcroft					my $ok = 0;
51821f65f947SAndy Whitcroft
518322f2a2efSAndy Whitcroft					# Ignore email addresses <foo@bar>
51841f65f947SAndy Whitcroft					if (($op eq '<' &&
51851f65f947SAndy Whitcroft					     $cc =~ /^\S+\@\S+>/) ||
51861f65f947SAndy Whitcroft					    ($op eq '>' &&
51871f65f947SAndy Whitcroft					     $ca =~ /<\S+\@\S+$/))
51881f65f947SAndy Whitcroft					{
51891f65f947SAndy Whitcroft						$ok = 1;
51901f65f947SAndy Whitcroft					}
51911f65f947SAndy Whitcroft
5192e0df7e1fSJoe Perches					# for asm volatile statements
5193e0df7e1fSJoe Perches					# ignore a colon with another
5194e0df7e1fSJoe Perches					# colon immediately before or after
5195e0df7e1fSJoe Perches					if (($op eq ':') &&
5196e0df7e1fSJoe Perches					    ($ca =~ /:$/ || $cc =~ /^:/)) {
5197e0df7e1fSJoe Perches						$ok = 1;
5198e0df7e1fSJoe Perches					}
5199e0df7e1fSJoe Perches
520084731623SJoe Perches					# messages are ERROR, but ?: are CHK
52011f65f947SAndy Whitcroft					if ($ok == 0) {
52020675a8fbSJean Delvare						my $msg_level = \&ERROR;
52030675a8fbSJean Delvare						$msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
520484731623SJoe Perches
52050675a8fbSJean Delvare						if (&{$msg_level}("SPACING",
52063705ce5bSJoe Perches								  "spaces required around that '$op' $at\n" . $hereptr)) {
5207b34c648bSJoe Perches							$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
5208b34c648bSJoe Perches							if (defined $fix_elements[$n + 2]) {
5209b34c648bSJoe Perches								$fix_elements[$n + 2] =~ s/^\s+//;
5210b34c648bSJoe Perches							}
52113705ce5bSJoe Perches							$line_fixed = 1;
52123705ce5bSJoe Perches						}
52130a920b5bSAndy Whitcroft					}
521422f2a2efSAndy Whitcroft				}
52154a0df2efSAndy Whitcroft				$off += length($elements[$n + 1]);
52163705ce5bSJoe Perches
52173705ce5bSJoe Perches##				print("n: <$n> GOOD: <$good>\n");
52183705ce5bSJoe Perches
52193705ce5bSJoe Perches				$fixed_line = $fixed_line . $good;
52200a920b5bSAndy Whitcroft			}
52213705ce5bSJoe Perches
52223705ce5bSJoe Perches			if (($#elements % 2) == 0) {
52233705ce5bSJoe Perches				$fixed_line = $fixed_line . $fix_elements[$#elements];
52243705ce5bSJoe Perches			}
52253705ce5bSJoe Perches
5226194f66fcSJoe Perches			if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) {
5227194f66fcSJoe Perches				$fixed[$fixlinenr] = $fixed_line;
52283705ce5bSJoe Perches			}
52293705ce5bSJoe Perches
52303705ce5bSJoe Perches
52310a920b5bSAndy Whitcroft		}
52320a920b5bSAndy Whitcroft
5233786b6326SJoe Perches# check for whitespace before a non-naked semicolon
5234d2e248e7SJoe Perches		if ($line =~ /^\+.*\S\s+;\s*$/) {
5235786b6326SJoe Perches			if (WARN("SPACING",
5236786b6326SJoe Perches				 "space prohibited before semicolon\n" . $herecurr) &&
5237786b6326SJoe Perches			    $fix) {
5238194f66fcSJoe Perches				1 while $fixed[$fixlinenr] =~
5239786b6326SJoe Perches				    s/^(\+.*\S)\s+;/$1;/;
5240786b6326SJoe Perches			}
5241786b6326SJoe Perches		}
5242786b6326SJoe Perches
5243f0a594c1SAndy Whitcroft# check for multiple assignments
5244f0a594c1SAndy Whitcroft		if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
5245000d1cc1SJoe Perches			CHK("MULTIPLE_ASSIGNMENTS",
5246000d1cc1SJoe Perches			    "multiple assignments should be avoided\n" . $herecurr);
5247f0a594c1SAndy Whitcroft		}
5248f0a594c1SAndy Whitcroft
524922f2a2efSAndy Whitcroft## # check for multiple declarations, allowing for a function declaration
525022f2a2efSAndy Whitcroft## # continuation.
525122f2a2efSAndy Whitcroft## 		if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
525222f2a2efSAndy Whitcroft## 		    $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
525322f2a2efSAndy Whitcroft##
525422f2a2efSAndy Whitcroft## 			# Remove any bracketed sections to ensure we do not
5255e73d2715SDwaipayan Ray## 			# falsely report the parameters of functions.
525622f2a2efSAndy Whitcroft## 			my $ln = $line;
525722f2a2efSAndy Whitcroft## 			while ($ln =~ s/\([^\(\)]*\)//g) {
525822f2a2efSAndy Whitcroft## 			}
525922f2a2efSAndy Whitcroft## 			if ($ln =~ /,/) {
5260000d1cc1SJoe Perches## 				WARN("MULTIPLE_DECLARATION",
5261000d1cc1SJoe Perches##				     "declaring multiple variables together should be avoided\n" . $herecurr);
526222f2a2efSAndy Whitcroft## 			}
526322f2a2efSAndy Whitcroft## 		}
5264f0a594c1SAndy Whitcroft
52650a920b5bSAndy Whitcroft#need space before brace following if, while, etc
52666b8c69e4SGeyslan G. Bem		if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
52676ad724e2SMichal Zylowski		    $line =~ /\b(?:else|do)\{/) {
52683705ce5bSJoe Perches			if (ERROR("SPACING",
52693705ce5bSJoe Perches				  "space required before the open brace '{'\n" . $herecurr) &&
52703705ce5bSJoe Perches			    $fix) {
52716ad724e2SMichal Zylowski				$fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
52723705ce5bSJoe Perches			}
5273de7d4f0eSAndy Whitcroft		}
5274de7d4f0eSAndy Whitcroft
5275c4a62ef9SJoe Perches## # check for blank lines before declarations
5276c4a62ef9SJoe Perches##		if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ &&
5277c4a62ef9SJoe Perches##		    $prevrawline =~ /^.\s*$/) {
5278c4a62ef9SJoe Perches##			WARN("SPACING",
5279c4a62ef9SJoe Perches##			     "No blank lines before declarations\n" . $hereprev);
5280c4a62ef9SJoe Perches##		}
5281c4a62ef9SJoe Perches##
5282c4a62ef9SJoe Perches
5283de7d4f0eSAndy Whitcroft# closing brace should have a space following it when it has anything
5284de7d4f0eSAndy Whitcroft# on the line
528594fb9845SJoe Perches		if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
5286d5e616fcSJoe Perches			if (ERROR("SPACING",
5287d5e616fcSJoe Perches				  "space required after that close brace '}'\n" . $herecurr) &&
5288d5e616fcSJoe Perches			    $fix) {
5289194f66fcSJoe Perches				$fixed[$fixlinenr] =~
5290d5e616fcSJoe Perches				    s/}((?!(?:,|;|\)))\S)/} $1/;
5291d5e616fcSJoe Perches			}
52920a920b5bSAndy Whitcroft		}
52930a920b5bSAndy Whitcroft
529422f2a2efSAndy Whitcroft# check spacing on square brackets
529522f2a2efSAndy Whitcroft		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
52963705ce5bSJoe Perches			if (ERROR("SPACING",
52973705ce5bSJoe Perches				  "space prohibited after that open square bracket '['\n" . $herecurr) &&
52983705ce5bSJoe Perches			    $fix) {
5299194f66fcSJoe Perches				$fixed[$fixlinenr] =~
53003705ce5bSJoe Perches				    s/\[\s+/\[/;
53013705ce5bSJoe Perches			}
530222f2a2efSAndy Whitcroft		}
530322f2a2efSAndy Whitcroft		if ($line =~ /\s\]/) {
53043705ce5bSJoe Perches			if (ERROR("SPACING",
53053705ce5bSJoe Perches				  "space prohibited before that close square bracket ']'\n" . $herecurr) &&
53063705ce5bSJoe Perches			    $fix) {
5307194f66fcSJoe Perches				$fixed[$fixlinenr] =~
53083705ce5bSJoe Perches				    s/\s+\]/\]/;
53093705ce5bSJoe Perches			}
531022f2a2efSAndy Whitcroft		}
531122f2a2efSAndy Whitcroft
5312c45dcabdSAndy Whitcroft# check spacing on parentheses
53139c0ca6f9SAndy Whitcroft		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
53149c0ca6f9SAndy Whitcroft		    $line !~ /for\s*\(\s+;/) {
53153705ce5bSJoe Perches			if (ERROR("SPACING",
53163705ce5bSJoe Perches				  "space prohibited after that open parenthesis '('\n" . $herecurr) &&
53173705ce5bSJoe Perches			    $fix) {
5318194f66fcSJoe Perches				$fixed[$fixlinenr] =~
53193705ce5bSJoe Perches				    s/\(\s+/\(/;
53203705ce5bSJoe Perches			}
532122f2a2efSAndy Whitcroft		}
532213214adfSAndy Whitcroft		if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
5323c45dcabdSAndy Whitcroft		    $line !~ /for\s*\(.*;\s+\)/ &&
5324c45dcabdSAndy Whitcroft		    $line !~ /:\s+\)/) {
53253705ce5bSJoe Perches			if (ERROR("SPACING",
53263705ce5bSJoe Perches				  "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
53273705ce5bSJoe Perches			    $fix) {
5328194f66fcSJoe Perches				$fixed[$fixlinenr] =~
53293705ce5bSJoe Perches				    s/\s+\)/\)/;
53303705ce5bSJoe Perches			}
533122f2a2efSAndy Whitcroft		}
533222f2a2efSAndy Whitcroft
5333e2826fd0SJoe Perches# check unnecessary parentheses around addressof/dereference single $Lvals
5334e2826fd0SJoe Perches# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar
5335e2826fd0SJoe Perches
5336e2826fd0SJoe Perches		while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) {
5337ea4acbb1SJoe Perches			my $var = $1;
5338ea4acbb1SJoe Perches			if (CHK("UNNECESSARY_PARENTHESES",
5339ea4acbb1SJoe Perches				"Unnecessary parentheses around $var\n" . $herecurr) &&
5340ea4acbb1SJoe Perches			    $fix) {
5341ea4acbb1SJoe Perches				$fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/;
5342ea4acbb1SJoe Perches			}
5343ea4acbb1SJoe Perches		}
5344ea4acbb1SJoe Perches
5345ea4acbb1SJoe Perches# check for unnecessary parentheses around function pointer uses
5346ea4acbb1SJoe Perches# ie: (foo->bar)(); should be foo->bar();
5347ea4acbb1SJoe Perches# but not "if (foo->bar) (" to avoid some false positives
5348ea4acbb1SJoe Perches		if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) {
5349ea4acbb1SJoe Perches			my $var = $2;
5350ea4acbb1SJoe Perches			if (CHK("UNNECESSARY_PARENTHESES",
5351ea4acbb1SJoe Perches				"Unnecessary parentheses around function pointer $var\n" . $herecurr) &&
5352ea4acbb1SJoe Perches			    $fix) {
5353ea4acbb1SJoe Perches				my $var2 = deparenthesize($var);
5354ea4acbb1SJoe Perches				$var2 =~ s/\s//g;
5355ea4acbb1SJoe Perches				$fixed[$fixlinenr] =~ s/\Q$var\E/$var2/;
5356ea4acbb1SJoe Perches			}
5357e2826fd0SJoe Perches		}
5358e2826fd0SJoe Perches
535963b7c73eSJoe Perches# check for unnecessary parentheses around comparisons in if uses
5360a032aa4cSJoe Perches# when !drivers/staging or command-line uses --strict
5361a032aa4cSJoe Perches		if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
53625b57980dSJoe Perches		    $perl_version_ok && defined($stat) &&
536363b7c73eSJoe Perches		    $stat =~ /(^.\s*if\s*($balanced_parens))/) {
536463b7c73eSJoe Perches			my $if_stat = $1;
536563b7c73eSJoe Perches			my $test = substr($2, 1, -1);
536663b7c73eSJoe Perches			my $herectx;
536763b7c73eSJoe Perches			while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) {
536863b7c73eSJoe Perches				my $match = $1;
536963b7c73eSJoe Perches				# avoid parentheses around potential macro args
537063b7c73eSJoe Perches				next if ($match =~ /^\s*\w+\s*$/);
537163b7c73eSJoe Perches				if (!defined($herectx)) {
537263b7c73eSJoe Perches					$herectx = $here . "\n";
537363b7c73eSJoe Perches					my $cnt = statement_rawlines($if_stat);
537463b7c73eSJoe Perches					for (my $n = 0; $n < $cnt; $n++) {
537563b7c73eSJoe Perches						my $rl = raw_line($linenr, $n);
537663b7c73eSJoe Perches						$herectx .=  $rl . "\n";
537763b7c73eSJoe Perches						last if $rl =~ /^[ \+].*\{/;
537863b7c73eSJoe Perches					}
537963b7c73eSJoe Perches				}
538063b7c73eSJoe Perches				CHK("UNNECESSARY_PARENTHESES",
538163b7c73eSJoe Perches				    "Unnecessary parentheses around '$match'\n" . $herectx);
538263b7c73eSJoe Perches			}
538363b7c73eSJoe Perches		}
538463b7c73eSJoe Perches
538569078651SJoe Perches# check that goto labels aren't indented (allow a single space indentation)
538669078651SJoe Perches# and ignore bitfield definitions like foo:1
538769078651SJoe Perches# Strictly, labels can have whitespace after the identifier and before the :
538869078651SJoe Perches# but this is not allowed here as many ?: uses would appear to be labels
538969078651SJoe Perches		if ($sline =~ /^.\s+[A-Za-z_][A-Za-z\d_]*:(?!\s*\d+)/ &&
539069078651SJoe Perches		    $sline !~ /^. [A-Za-z\d_][A-Za-z\d_]*:/ &&
539169078651SJoe Perches		    $sline !~ /^.\s+default:/) {
53923705ce5bSJoe Perches			if (WARN("INDENTED_LABEL",
53933705ce5bSJoe Perches				 "labels should not be indented\n" . $herecurr) &&
53943705ce5bSJoe Perches			    $fix) {
5395194f66fcSJoe Perches				$fixed[$fixlinenr] =~
53963705ce5bSJoe Perches				    s/^(.)\s+/$1/;
53973705ce5bSJoe Perches			}
53980a920b5bSAndy Whitcroft		}
53990a920b5bSAndy Whitcroft
540040873abaSJoe Perches# check if a statement with a comma should be two statements like:
540140873abaSJoe Perches#	foo = bar(),	/* comma should be semicolon */
540240873abaSJoe Perches#	bar = baz();
540340873abaSJoe Perches		if (defined($stat) &&
540440873abaSJoe Perches		    $stat =~ /^\+\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*,\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*;\s*$/) {
540540873abaSJoe Perches			my $cnt = statement_rawlines($stat);
540640873abaSJoe Perches			my $herectx = get_stat_here($linenr, $cnt, $here);
540740873abaSJoe Perches			WARN("SUSPECT_COMMA_SEMICOLON",
540840873abaSJoe Perches			     "Possible comma where semicolon could be used\n" . $herectx);
540940873abaSJoe Perches		}
541040873abaSJoe Perches
54115b9553abSJoe Perches# return is not a function
5412507e5141SJoe Perches		if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
5413c45dcabdSAndy Whitcroft			my $spacing = $1;
54145b57980dSJoe Perches			if ($perl_version_ok &&
54155b9553abSJoe Perches			    $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
54165b9553abSJoe Perches				my $value = $1;
54175b9553abSJoe Perches				$value = deparenthesize($value);
54185b9553abSJoe Perches				if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
5419000d1cc1SJoe Perches					ERROR("RETURN_PARENTHESES",
5420000d1cc1SJoe Perches					      "return is not a function, parentheses are not required\n" . $herecurr);
54215b9553abSJoe Perches				}
5422c45dcabdSAndy Whitcroft			} elsif ($spacing !~ /\s+/) {
5423000d1cc1SJoe Perches				ERROR("SPACING",
5424000d1cc1SJoe Perches				      "space required before the open parenthesis '('\n" . $herecurr);
5425c45dcabdSAndy Whitcroft			}
5426c45dcabdSAndy Whitcroft		}
5427507e5141SJoe Perches
5428b43ae21bSJoe Perches# unnecessary return in a void function
5429b43ae21bSJoe Perches# at end-of-function, with the previous line a single leading tab, then return;
5430b43ae21bSJoe Perches# and the line before that not a goto label target like "out:"
5431b43ae21bSJoe Perches		if ($sline =~ /^[ \+]}\s*$/ &&
5432b43ae21bSJoe Perches		    $prevline =~ /^\+\treturn\s*;\s*$/ &&
5433b43ae21bSJoe Perches		    $linenr >= 3 &&
5434b43ae21bSJoe Perches		    $lines[$linenr - 3] =~ /^[ +]/ &&
5435b43ae21bSJoe Perches		    $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) {
54369819cf25SJoe Perches			WARN("RETURN_VOID",
5437b43ae21bSJoe Perches			     "void function return statements are not generally useful\n" . $hereprev);
54389819cf25SJoe Perches		}
54399819cf25SJoe Perches
5440189248d8SJoe Perches# if statements using unnecessary parentheses - ie: if ((foo == bar))
54415b57980dSJoe Perches		if ($perl_version_ok &&
5442189248d8SJoe Perches		    $line =~ /\bif\s*((?:\(\s*){2,})/) {
5443189248d8SJoe Perches			my $openparens = $1;
5444189248d8SJoe Perches			my $count = $openparens =~ tr@\(@\(@;
5445189248d8SJoe Perches			my $msg = "";
5446189248d8SJoe Perches			if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
5447189248d8SJoe Perches				my $comp = $4;	#Not $1 because of $LvalOrFunc
5448189248d8SJoe Perches				$msg = " - maybe == should be = ?" if ($comp eq "==");
5449189248d8SJoe Perches				WARN("UNNECESSARY_PARENTHESES",
5450189248d8SJoe Perches				     "Unnecessary parentheses$msg\n" . $herecurr);
5451189248d8SJoe Perches			}
5452189248d8SJoe Perches		}
5453189248d8SJoe Perches
5454c5595fa2SJoe Perches# comparisons with a constant or upper case identifier on the left
5455c5595fa2SJoe Perches#	avoid cases like "foo + BAR < baz"
5456c5595fa2SJoe Perches#	only fix matches surrounded by parentheses to avoid incorrect
5457c5595fa2SJoe Perches#	conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
54585b57980dSJoe Perches		if ($perl_version_ok &&
5459c5595fa2SJoe Perches		    $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
5460c5595fa2SJoe Perches			my $lead = $1;
5461c5595fa2SJoe Perches			my $const = $2;
5462c5595fa2SJoe Perches			my $comp = $3;
5463c5595fa2SJoe Perches			my $to = $4;
5464c5595fa2SJoe Perches			my $newcomp = $comp;
5465f39e1769SJoe Perches			if ($lead !~ /(?:$Operators|\.)\s*$/ &&
5466c5595fa2SJoe Perches			    $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
5467c5595fa2SJoe Perches			    WARN("CONSTANT_COMPARISON",
5468c5595fa2SJoe Perches				 "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
5469c5595fa2SJoe Perches			    $fix) {
5470c5595fa2SJoe Perches				if ($comp eq "<") {
5471c5595fa2SJoe Perches					$newcomp = ">";
5472c5595fa2SJoe Perches				} elsif ($comp eq "<=") {
5473c5595fa2SJoe Perches					$newcomp = ">=";
5474c5595fa2SJoe Perches				} elsif ($comp eq ">") {
5475c5595fa2SJoe Perches					$newcomp = "<";
5476c5595fa2SJoe Perches				} elsif ($comp eq ">=") {
5477c5595fa2SJoe Perches					$newcomp = "<=";
5478c5595fa2SJoe Perches				}
5479c5595fa2SJoe Perches				$fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/;
5480c5595fa2SJoe Perches			}
5481c5595fa2SJoe Perches		}
5482c5595fa2SJoe Perches
5483f34e4a4fSJoe Perches# Return of what appears to be an errno should normally be negative
5484f34e4a4fSJoe Perches		if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
548553a3c448SAndy Whitcroft			my $name = $1;
548646b85bf9SGuenter Roeck			if ($name ne 'EOF' && $name ne 'ERROR' && $name !~ /^EPOLL/) {
5487000d1cc1SJoe Perches				WARN("USE_NEGATIVE_ERRNO",
5488f34e4a4fSJoe Perches				     "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
548953a3c448SAndy Whitcroft			}
549053a3c448SAndy Whitcroft		}
5491c45dcabdSAndy Whitcroft
54920a920b5bSAndy Whitcroft# Need a space before open parenthesis after if, while etc
54934a0df2efSAndy Whitcroft		if ($line =~ /\b(if|while|for|switch)\(/) {
54943705ce5bSJoe Perches			if (ERROR("SPACING",
54953705ce5bSJoe Perches				  "space required before the open parenthesis '('\n" . $herecurr) &&
54963705ce5bSJoe Perches			    $fix) {
5497194f66fcSJoe Perches				$fixed[$fixlinenr] =~
54983705ce5bSJoe Perches				    s/\b(if|while|for|switch)\(/$1 \(/;
54993705ce5bSJoe Perches			}
55000a920b5bSAndy Whitcroft		}
55010a920b5bSAndy Whitcroft
5502f5fe35ddSAndy Whitcroft# Check for illegal assignment in if conditional -- and check for trailing
5503f5fe35ddSAndy Whitcroft# statements after the conditional.
5504170d3a22SAndy Whitcroft		if ($line =~ /do\s*(?!{)/) {
55053e469cdcSAndy Whitcroft			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
55063e469cdcSAndy Whitcroft				ctx_statement_block($linenr, $realcnt, 0)
55073e469cdcSAndy Whitcroft					if (!defined $stat);
5508170d3a22SAndy Whitcroft			my ($stat_next) = ctx_statement_block($line_nr_next,
5509170d3a22SAndy Whitcroft						$remain_next, $off_next);
5510170d3a22SAndy Whitcroft			$stat_next =~ s/\n./\n /g;
5511170d3a22SAndy Whitcroft			##print "stat<$stat> stat_next<$stat_next>\n";
5512170d3a22SAndy Whitcroft
5513170d3a22SAndy Whitcroft			if ($stat_next =~ /^\s*while\b/) {
5514170d3a22SAndy Whitcroft				# If the statement carries leading newlines,
5515170d3a22SAndy Whitcroft				# then count those as offsets.
5516170d3a22SAndy Whitcroft				my ($whitespace) =
5517170d3a22SAndy Whitcroft					($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
5518170d3a22SAndy Whitcroft				my $offset =
5519170d3a22SAndy Whitcroft					statement_rawlines($whitespace) - 1;
5520170d3a22SAndy Whitcroft
5521170d3a22SAndy Whitcroft				$suppress_whiletrailers{$line_nr_next +
5522170d3a22SAndy Whitcroft								$offset} = 1;
5523170d3a22SAndy Whitcroft			}
5524170d3a22SAndy Whitcroft		}
5525170d3a22SAndy Whitcroft		if (!defined $suppress_whiletrailers{$linenr} &&
5526c11230f4SJoe Perches		    defined($stat) && defined($cond) &&
5527170d3a22SAndy Whitcroft		    $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
5528171ae1a4SAndy Whitcroft			my ($s, $c) = ($stat, $cond);
55298905a67cSAndy Whitcroft
5530b53c8e10SAndy Whitcroft			if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
553165b64b3bSJoe Perches				if (ERROR("ASSIGN_IN_IF",
553265b64b3bSJoe Perches					  "do not use assignment in if condition\n" . $herecurr) &&
553365b64b3bSJoe Perches				    $fix && $perl_version_ok) {
553465b64b3bSJoe Perches					if ($rawline =~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=\s*$LvalOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) {
553565b64b3bSJoe Perches						my $space = $1;
553665b64b3bSJoe Perches						my $not = $2;
553765b64b3bSJoe Perches						my $statement = $3;
553865b64b3bSJoe Perches						my $assigned = $4;
553965b64b3bSJoe Perches						my $test = $8;
554065b64b3bSJoe Perches						my $against = $9;
554165b64b3bSJoe Perches						my $brace = $15;
554265b64b3bSJoe Perches						fix_delete_line($fixlinenr, $rawline);
554365b64b3bSJoe Perches						fix_insert_line($fixlinenr, "$space$statement;");
554465b64b3bSJoe Perches						my $newline = "${space}if (";
554565b64b3bSJoe Perches						$newline .= '!' if defined($not);
554665b64b3bSJoe Perches						$newline .= '(' if (defined $not && defined($test) && defined($against));
554765b64b3bSJoe Perches						$newline .= "$assigned";
554865b64b3bSJoe Perches						$newline .= " $test $against" if (defined($test) && defined($against));
554965b64b3bSJoe Perches						$newline .= ')' if (defined $not && defined($test) && defined($against));
555065b64b3bSJoe Perches						$newline .= ')';
555165b64b3bSJoe Perches						$newline .= " {" if (defined($brace));
555265b64b3bSJoe Perches						fix_insert_line($fixlinenr + 1, $newline);
555365b64b3bSJoe Perches					}
555465b64b3bSJoe Perches				}
55558905a67cSAndy Whitcroft			}
55568905a67cSAndy Whitcroft
55578905a67cSAndy Whitcroft			# Find out what is on the end of the line after the
55588905a67cSAndy Whitcroft			# conditional.
5559773647a0SAndy Whitcroft			substr($s, 0, length($c), '');
55608905a67cSAndy Whitcroft			$s =~ s/\n.*//g;
556113214adfSAndy Whitcroft			$s =~ s/$;//g;	# Remove any comments
556253210168SAndy Whitcroft			if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
556353210168SAndy Whitcroft			    $c !~ /}\s*while\s*/)
5564773647a0SAndy Whitcroft			{
5565bb44ad39SAndy Whitcroft				# Find out how long the conditional actually is.
5566bb44ad39SAndy Whitcroft				my @newlines = ($c =~ /\n/gs);
5567bb44ad39SAndy Whitcroft				my $cond_lines = 1 + $#newlines;
556842bdf74cSHidetoshi Seto				my $stat_real = '';
5569bb44ad39SAndy Whitcroft
557042bdf74cSHidetoshi Seto				$stat_real = raw_line($linenr, $cond_lines)
557142bdf74cSHidetoshi Seto							. "\n" if ($cond_lines);
5572bb44ad39SAndy Whitcroft				if (defined($stat_real) && $cond_lines > 1) {
5573bb44ad39SAndy Whitcroft					$stat_real = "[...]\n$stat_real";
5574bb44ad39SAndy Whitcroft				}
5575bb44ad39SAndy Whitcroft
5576000d1cc1SJoe Perches				ERROR("TRAILING_STATEMENTS",
5577000d1cc1SJoe Perches				      "trailing statements should be on next line\n" . $herecurr . $stat_real);
55788905a67cSAndy Whitcroft			}
55798905a67cSAndy Whitcroft		}
55808905a67cSAndy Whitcroft
558113214adfSAndy Whitcroft# Check for bitwise tests written as boolean
558213214adfSAndy Whitcroft		if ($line =~ /
558313214adfSAndy Whitcroft			(?:
558413214adfSAndy Whitcroft				(?:\[|\(|\&\&|\|\|)
558513214adfSAndy Whitcroft				\s*0[xX][0-9]+\s*
558613214adfSAndy Whitcroft				(?:\&\&|\|\|)
558713214adfSAndy Whitcroft			|
558813214adfSAndy Whitcroft				(?:\&\&|\|\|)
558913214adfSAndy Whitcroft				\s*0[xX][0-9]+\s*
559013214adfSAndy Whitcroft				(?:\&\&|\|\||\)|\])
559113214adfSAndy Whitcroft			)/x)
559213214adfSAndy Whitcroft		{
5593000d1cc1SJoe Perches			WARN("HEXADECIMAL_BOOLEAN_TEST",
5594000d1cc1SJoe Perches			     "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
559513214adfSAndy Whitcroft		}
559613214adfSAndy Whitcroft
55978905a67cSAndy Whitcroft# if and else should not have general statements after it
559813214adfSAndy Whitcroft		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
559913214adfSAndy Whitcroft			my $s = $1;
560013214adfSAndy Whitcroft			$s =~ s/$;//g;	# Remove any comments
560113214adfSAndy Whitcroft			if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
5602000d1cc1SJoe Perches				ERROR("TRAILING_STATEMENTS",
5603000d1cc1SJoe Perches				      "trailing statements should be on next line\n" . $herecurr);
56040a920b5bSAndy Whitcroft			}
560513214adfSAndy Whitcroft		}
560639667782SAndy Whitcroft# if should not continue a brace
560739667782SAndy Whitcroft		if ($line =~ /}\s*if\b/) {
5608000d1cc1SJoe Perches			ERROR("TRAILING_STATEMENTS",
5609048b123fSRasmus Villemoes			      "trailing statements should be on next line (or did you mean 'else if'?)\n" .
561039667782SAndy Whitcroft				$herecurr);
561139667782SAndy Whitcroft		}
5612a1080bf8SAndy Whitcroft# case and default should not have general statements after them
5613a1080bf8SAndy Whitcroft		if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
5614a1080bf8SAndy Whitcroft		    $line !~ /\G(?:
56153fef12d6SAndy Whitcroft			(?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
5616a1080bf8SAndy Whitcroft			\s*return\s+
5617a1080bf8SAndy Whitcroft		    )/xg)
5618a1080bf8SAndy Whitcroft		{
5619000d1cc1SJoe Perches			ERROR("TRAILING_STATEMENTS",
5620000d1cc1SJoe Perches			      "trailing statements should be on next line\n" . $herecurr);
5621a1080bf8SAndy Whitcroft		}
56220a920b5bSAndy Whitcroft
56230a920b5bSAndy Whitcroft		# Check for }<nl>else {, these must be at the same
56240a920b5bSAndy Whitcroft		# indent level to be relevant to each other.
56258b8856f4SJoe Perches		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
56260a920b5bSAndy Whitcroft		    $previndent == $indent) {
56278b8856f4SJoe Perches			if (ERROR("ELSE_AFTER_BRACE",
56288b8856f4SJoe Perches				  "else should follow close brace '}'\n" . $hereprev) &&
56298b8856f4SJoe Perches			    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
56308b8856f4SJoe Perches				fix_delete_line($fixlinenr - 1, $prevrawline);
56318b8856f4SJoe Perches				fix_delete_line($fixlinenr, $rawline);
56328b8856f4SJoe Perches				my $fixedline = $prevrawline;
56338b8856f4SJoe Perches				$fixedline =~ s/}\s*$//;
56348b8856f4SJoe Perches				if ($fixedline !~ /^\+\s*$/) {
56358b8856f4SJoe Perches					fix_insert_line($fixlinenr, $fixedline);
56368b8856f4SJoe Perches				}
56378b8856f4SJoe Perches				$fixedline = $rawline;
56388b8856f4SJoe Perches				$fixedline =~ s/^(.\s*)else/$1} else/;
56398b8856f4SJoe Perches				fix_insert_line($fixlinenr, $fixedline);
56408b8856f4SJoe Perches			}
56410a920b5bSAndy Whitcroft		}
56420a920b5bSAndy Whitcroft
56438b8856f4SJoe Perches		if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
5644c2fdda0dSAndy Whitcroft		    $previndent == $indent) {
5645c2fdda0dSAndy Whitcroft			my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
5646c2fdda0dSAndy Whitcroft
5647c2fdda0dSAndy Whitcroft			# Find out what is on the end of the line after the
5648c2fdda0dSAndy Whitcroft			# conditional.
5649773647a0SAndy Whitcroft			substr($s, 0, length($c), '');
5650c2fdda0dSAndy Whitcroft			$s =~ s/\n.*//g;
5651c2fdda0dSAndy Whitcroft
5652c2fdda0dSAndy Whitcroft			if ($s =~ /^\s*;/) {
56538b8856f4SJoe Perches				if (ERROR("WHILE_AFTER_BRACE",
56548b8856f4SJoe Perches					  "while should follow close brace '}'\n" . $hereprev) &&
56558b8856f4SJoe Perches				    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
56568b8856f4SJoe Perches					fix_delete_line($fixlinenr - 1, $prevrawline);
56578b8856f4SJoe Perches					fix_delete_line($fixlinenr, $rawline);
56588b8856f4SJoe Perches					my $fixedline = $prevrawline;
56598b8856f4SJoe Perches					my $trailing = $rawline;
56608b8856f4SJoe Perches					$trailing =~ s/^\+//;
56618b8856f4SJoe Perches					$trailing = trim($trailing);
56628b8856f4SJoe Perches					$fixedline =~ s/}\s*$/} $trailing/;
56638b8856f4SJoe Perches					fix_insert_line($fixlinenr, $fixedline);
56648b8856f4SJoe Perches				}
5665c2fdda0dSAndy Whitcroft			}
5666c2fdda0dSAndy Whitcroft		}
5667c2fdda0dSAndy Whitcroft
566895e2c602SJoe Perches#Specific variable tests
5669323c1260SJoe Perches		while ($line =~ m{($Constant|$Lval)}g) {
5670323c1260SJoe Perches			my $var = $1;
567195e2c602SJoe Perches
567295e2c602SJoe Perches#CamelCase
5673807bd26cSJoe Perches			if ($var !~ /^$Constant$/ &&
5674be79794bSJoe Perches			    $var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
56754104a206SŁukasz Stelmach#Ignore some autogenerated defines and enum values
56764104a206SŁukasz Stelmach			    $var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
567722735ce8SJoe Perches#Ignore Page<foo> variants
5678807bd26cSJoe Perches			    $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
5679d439e6a5SJoe Perches#Ignore SI style variants like nS, mV and dB
5680d439e6a5SJoe Perches#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
5681d439e6a5SJoe Perches			    $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
5682f5123576SJulius Werner#Ignore some three character SI units explicitly, like MiB and KHz
5683f5123576SJulius Werner			    $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
56847e781f67SJoe Perches				while ($var =~ m{($Ident)}g) {
56857e781f67SJoe Perches					my $word = $1;
56867e781f67SJoe Perches					next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
5687d8b07710SJoe Perches					if ($check) {
5688d8b07710SJoe Perches						seed_camelcase_includes();
5689d8b07710SJoe Perches						if (!$file && !$camelcase_file_seeded) {
5690d8b07710SJoe Perches							seed_camelcase_file($realfile);
5691d8b07710SJoe Perches							$camelcase_file_seeded = 1;
5692d8b07710SJoe Perches						}
5693d8b07710SJoe Perches					}
56947e781f67SJoe Perches					if (!defined $camelcase{$word}) {
56957e781f67SJoe Perches						$camelcase{$word} = 1;
5696be79794bSJoe Perches						CHK("CAMELCASE",
56977e781f67SJoe Perches						    "Avoid CamelCase: <$word>\n" . $herecurr);
56987e781f67SJoe Perches					}
5699323c1260SJoe Perches				}
5700323c1260SJoe Perches			}
57013445686aSJoe Perches		}
57020a920b5bSAndy Whitcroft
57030a920b5bSAndy Whitcroft#no spaces allowed after \ in define
5704d5e616fcSJoe Perches		if ($line =~ /\#\s*define.*\\\s+$/) {
5705d5e616fcSJoe Perches			if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
5706d5e616fcSJoe Perches				 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
5707d5e616fcSJoe Perches			    $fix) {
5708194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/\s+$//;
5709d5e616fcSJoe Perches			}
57100a920b5bSAndy Whitcroft		}
57110a920b5bSAndy Whitcroft
57120e212e0aSFabian Frederick# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes
57130e212e0aSFabian Frederick# itself <asm/foo.h> (uses RAW line)
5714c45dcabdSAndy Whitcroft		if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
5715e09dec48SAndy Whitcroft			my $file = "$1.h";
5716e09dec48SAndy Whitcroft			my $checkfile = "include/linux/$file";
5717e09dec48SAndy Whitcroft			if (-f "$root/$checkfile" &&
5718e09dec48SAndy Whitcroft			    $realfile ne $checkfile &&
57197840a94cSWolfram Sang			    $1 !~ /$allowed_asm_includes/)
5720c45dcabdSAndy Whitcroft			{
57210e212e0aSFabian Frederick				my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`;
57220e212e0aSFabian Frederick				if ($asminclude > 0) {
5723e09dec48SAndy Whitcroft					if ($realfile =~ m{^arch/}) {
5724000d1cc1SJoe Perches						CHK("ARCH_INCLUDE_LINUX",
5725000d1cc1SJoe Perches						    "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5726e09dec48SAndy Whitcroft					} else {
5727000d1cc1SJoe Perches						WARN("INCLUDE_LINUX",
5728000d1cc1SJoe Perches						     "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5729e09dec48SAndy Whitcroft					}
57300a920b5bSAndy Whitcroft				}
57310a920b5bSAndy Whitcroft			}
57320e212e0aSFabian Frederick		}
57330a920b5bSAndy Whitcroft
5734653d4876SAndy Whitcroft# multi-statement macros should be enclosed in a do while loop, grab the
5735653d4876SAndy Whitcroft# first statement and ensure its the whole macro if its not enclosed
5736cf655043SAndy Whitcroft# in a known good container
5737b8f96a31SAndy Whitcroft		if ($realfile !~ m@/vmlinux.lds.h$@ &&
5738b8f96a31SAndy Whitcroft		    $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
5739d8aaf121SAndy Whitcroft			my $ln = $linenr;
5740d8aaf121SAndy Whitcroft			my $cnt = $realcnt;
5741c45dcabdSAndy Whitcroft			my ($off, $dstat, $dcond, $rest);
5742c45dcabdSAndy Whitcroft			my $ctx = '';
574308a2843eSJoe Perches			my $has_flow_statement = 0;
574408a2843eSJoe Perches			my $has_arg_concat = 0;
5745c45dcabdSAndy Whitcroft			($dstat, $dcond, $ln, $cnt, $off) =
5746f74bd194SAndy Whitcroft				ctx_statement_block($linenr, $realcnt, 0);
5747f74bd194SAndy Whitcroft			$ctx = $dstat;
5748c45dcabdSAndy Whitcroft			#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
5749a3bb97a7SAndy Whitcroft			#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
5750c45dcabdSAndy Whitcroft
575108a2843eSJoe Perches			$has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
575262e15a6dSJoe Perches			$has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
575308a2843eSJoe Perches
5754f59b64bfSJoe Perches			$dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
5755f59b64bfSJoe Perches			my $define_args = $1;
5756f59b64bfSJoe Perches			my $define_stmt = $dstat;
5757f59b64bfSJoe Perches			my @def_args = ();
5758f59b64bfSJoe Perches
5759f59b64bfSJoe Perches			if (defined $define_args && $define_args ne "") {
5760f59b64bfSJoe Perches				$define_args = substr($define_args, 1, length($define_args) - 2);
5761f59b64bfSJoe Perches				$define_args =~ s/\s*//g;
57628c8c45cfSJoe Perches				$define_args =~ s/\\\+?//g;
5763f59b64bfSJoe Perches				@def_args = split(",", $define_args);
5764f59b64bfSJoe Perches			}
5765f59b64bfSJoe Perches
5766292f1a9bSAndy Whitcroft			$dstat =~ s/$;//g;
5767c45dcabdSAndy Whitcroft			$dstat =~ s/\\\n.//g;
5768c45dcabdSAndy Whitcroft			$dstat =~ s/^\s*//s;
5769c45dcabdSAndy Whitcroft			$dstat =~ s/\s*$//s;
5770c45dcabdSAndy Whitcroft
5771c45dcabdSAndy Whitcroft			# Flatten any parentheses and braces
57722e44e803SDwaipayan Ray			while ($dstat =~ s/\([^\(\)]*\)/1u/ ||
57732e44e803SDwaipayan Ray			       $dstat =~ s/\{[^\{\}]*\}/1u/ ||
57742e44e803SDwaipayan Ray			       $dstat =~ s/.\[[^\[\]]*\]/1u/)
5775bf30d6edSAndy Whitcroft			{
5776c45dcabdSAndy Whitcroft			}
5777c45dcabdSAndy Whitcroft
5778342d3d2fSAntonio Borneo			# Flatten any obvious string concatenation.
577933acb54aSJoe Perches			while ($dstat =~ s/($String)\s*$Ident/$1/ ||
578033acb54aSJoe Perches			       $dstat =~ s/$Ident\s*($String)/$1/)
5781e45bab8eSAndy Whitcroft			{
5782e45bab8eSAndy Whitcroft			}
5783e45bab8eSAndy Whitcroft
578442e15293SJoe Perches			# Make asm volatile uses seem like a generic function
578542e15293SJoe Perches			$dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
578642e15293SJoe Perches
5787c45dcabdSAndy Whitcroft			my $exceptions = qr{
5788c45dcabdSAndy Whitcroft				$Declare|
5789c45dcabdSAndy Whitcroft				module_param_named|
5790a0a0a7a9SKees Cook				MODULE_PARM_DESC|
5791c45dcabdSAndy Whitcroft				DECLARE_PER_CPU|
5792c45dcabdSAndy Whitcroft				DEFINE_PER_CPU|
5793383099fdSAndy Whitcroft				__typeof__\(|
579422fd2d3eSStefani Seibold				union|
579522fd2d3eSStefani Seibold				struct|
5796ea71a0a0SAndy Whitcroft				\.$Ident\s*=\s*|
57976b10df42SVladimir Zapolskiy				^\"|\"$|
57986b10df42SVladimir Zapolskiy				^\[
5799c45dcabdSAndy Whitcroft			}x;
58005eaa20b9SAndy Whitcroft			#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
5801f59b64bfSJoe Perches
5802f59b64bfSJoe Perches			$ctx =~ s/\n*$//;
5803f59b64bfSJoe Perches			my $stmt_cnt = statement_rawlines($ctx);
5804e3d95a2aSTobin C. Harding			my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
5805f59b64bfSJoe Perches
5806f74bd194SAndy Whitcroft			if ($dstat ne '' &&
5807f74bd194SAndy Whitcroft			    $dstat !~ /^(?:$Ident|-?$Constant),$/ &&			# 10, // foo(),
5808f74bd194SAndy Whitcroft			    $dstat !~ /^(?:$Ident|-?$Constant);$/ &&			# foo();
58093cc4b1c3SJoe Perches			    $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ &&		# 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
5810356fd398SJoe Perches			    $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ &&			# character constants
5811f74bd194SAndy Whitcroft			    $dstat !~ /$exceptions/ &&
5812f74bd194SAndy Whitcroft			    $dstat !~ /^\.$Ident\s*=/ &&				# .foo =
5813e942e2c3SJoe Perches			    $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ &&		# stringification #foo
581472f115f9SAndy Whitcroft			    $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ &&	# do {...} while (...); // do {...} while (...)
58152e44e803SDwaipayan Ray			    $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ &&		# while (...) {...}
5816f74bd194SAndy Whitcroft			    $dstat !~ /^for\s*$Constant$/ &&				# for (...)
5817f74bd194SAndy Whitcroft			    $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ &&	# for (...) bar()
5818f74bd194SAndy Whitcroft			    $dstat !~ /^do\s*{/ &&					# do {...
58194e5d56bdSEddie Kovsky			    $dstat !~ /^\(\{/ &&						# ({...
5820f95a7e6aSJoe Perches			    $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
5821c45dcabdSAndy Whitcroft			{
5822e795556aSJoe Perches				if ($dstat =~ /^\s*if\b/) {
5823e795556aSJoe Perches					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
5824e795556aSJoe Perches					      "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
5825e795556aSJoe Perches				} elsif ($dstat =~ /;/) {
5826f74bd194SAndy Whitcroft					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
5827f74bd194SAndy Whitcroft					      "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
5828f74bd194SAndy Whitcroft				} else {
5829000d1cc1SJoe Perches					ERROR("COMPLEX_MACRO",
5830388982b5SAndrew Morton					      "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
5831d8aaf121SAndy Whitcroft				}
5832f59b64bfSJoe Perches
5833f59b64bfSJoe Perches			}
58345207649bSJoe Perches
58355207649bSJoe Perches			# Make $define_stmt single line, comment-free, etc
58365207649bSJoe Perches			my @stmt_array = split('\n', $define_stmt);
58375207649bSJoe Perches			my $first = 1;
58385207649bSJoe Perches			$define_stmt = "";
58395207649bSJoe Perches			foreach my $l (@stmt_array) {
58405207649bSJoe Perches				$l =~ s/\\$//;
58415207649bSJoe Perches				if ($first) {
58425207649bSJoe Perches					$define_stmt = $l;
58435207649bSJoe Perches					$first = 0;
58445207649bSJoe Perches				} elsif ($l =~ /^[\+ ]/) {
58455207649bSJoe Perches					$define_stmt .= substr($l, 1);
58465207649bSJoe Perches				}
58475207649bSJoe Perches			}
58485207649bSJoe Perches			$define_stmt =~ s/$;//g;
58495207649bSJoe Perches			$define_stmt =~ s/\s+/ /g;
58505207649bSJoe Perches			$define_stmt = trim($define_stmt);
58515207649bSJoe Perches
5852f59b64bfSJoe Perches# check if any macro arguments are reused (ignore '...' and 'type')
5853f59b64bfSJoe Perches			foreach my $arg (@def_args) {
5854f59b64bfSJoe Perches			        next if ($arg =~ /\.\.\./);
58559192d41aSJoe Perches			        next if ($arg =~ /^type$/i);
58567fe528a2SJoe Perches				my $tmp_stmt = $define_stmt;
58577b844345SVincent Mailhol				$tmp_stmt =~ s/\b(__must_be_array|offsetof|sizeof|sizeof_field|__stringify|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
58587fe528a2SJoe Perches				$tmp_stmt =~ s/\#+\s*$arg\b//g;
58597fe528a2SJoe Perches				$tmp_stmt =~ s/\b$arg\s*\#\#//g;
5860d41362edSJoe Perches				my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
5861f59b64bfSJoe Perches				if ($use_cnt > 1) {
5862f59b64bfSJoe Perches					CHK("MACRO_ARG_REUSE",
5863f59b64bfSJoe Perches					    "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
5864f59b64bfSJoe Perches				    }
58659192d41aSJoe Perches# check if any macro arguments may have other precedence issues
58667fe528a2SJoe Perches				if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
58679192d41aSJoe Perches				    ((defined($1) && $1 ne ',') ||
58689192d41aSJoe Perches				     (defined($2) && $2 ne ','))) {
58699192d41aSJoe Perches					CHK("MACRO_ARG_PRECEDENCE",
58709192d41aSJoe Perches					    "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
58719192d41aSJoe Perches				}
58720a920b5bSAndy Whitcroft			}
58735023d347SJoe Perches
587408a2843eSJoe Perches# check for macros with flow control, but without ## concatenation
587508a2843eSJoe Perches# ## concatenation is commonly a macro that defines a function so ignore those
587608a2843eSJoe Perches			if ($has_flow_statement && !$has_arg_concat) {
587708a2843eSJoe Perches				my $cnt = statement_rawlines($ctx);
5878e3d95a2aSTobin C. Harding				my $herectx = get_stat_here($linenr, $cnt, $here);
587908a2843eSJoe Perches
588008a2843eSJoe Perches				WARN("MACRO_WITH_FLOW_CONTROL",
588108a2843eSJoe Perches				     "Macros with flow control statements should be avoided\n" . "$herectx");
588208a2843eSJoe Perches			}
588308a2843eSJoe Perches
5884481eb486SJoe Perches# check for line continuations outside of #defines, preprocessor #, and asm
58855023d347SJoe Perches
58865023d347SJoe Perches		} else {
58875023d347SJoe Perches			if ($prevline !~ /^..*\\$/ &&
5888481eb486SJoe Perches			    $line !~ /^\+\s*\#.*\\$/ &&		# preprocessor
5889481eb486SJoe Perches			    $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ &&	# asm
58905023d347SJoe Perches			    $line =~ /^\+.*\\$/) {
58915023d347SJoe Perches				WARN("LINE_CONTINUATIONS",
58925023d347SJoe Perches				     "Avoid unnecessary line continuations\n" . $herecurr);
58935023d347SJoe Perches			}
5894653d4876SAndy Whitcroft		}
58950a920b5bSAndy Whitcroft
5896b13edf7fSJoe Perches# do {} while (0) macro tests:
5897b13edf7fSJoe Perches# single-statement macros do not need to be enclosed in do while (0) loop,
5898b13edf7fSJoe Perches# macro should not end with a semicolon
58995b57980dSJoe Perches		if ($perl_version_ok &&
5900b13edf7fSJoe Perches		    $realfile !~ m@/vmlinux.lds.h$@ &&
5901b13edf7fSJoe Perches		    $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
5902b13edf7fSJoe Perches			my $ln = $linenr;
5903b13edf7fSJoe Perches			my $cnt = $realcnt;
5904b13edf7fSJoe Perches			my ($off, $dstat, $dcond, $rest);
5905b13edf7fSJoe Perches			my $ctx = '';
5906b13edf7fSJoe Perches			($dstat, $dcond, $ln, $cnt, $off) =
5907b13edf7fSJoe Perches				ctx_statement_block($linenr, $realcnt, 0);
5908b13edf7fSJoe Perches			$ctx = $dstat;
5909b13edf7fSJoe Perches
5910b13edf7fSJoe Perches			$dstat =~ s/\\\n.//g;
59111b36b201SJoe Perches			$dstat =~ s/$;/ /g;
5912b13edf7fSJoe Perches
5913b13edf7fSJoe Perches			if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {
5914b13edf7fSJoe Perches				my $stmts = $2;
5915b13edf7fSJoe Perches				my $semis = $3;
5916b13edf7fSJoe Perches
5917b13edf7fSJoe Perches				$ctx =~ s/\n*$//;
5918b13edf7fSJoe Perches				my $cnt = statement_rawlines($ctx);
5919e3d95a2aSTobin C. Harding				my $herectx = get_stat_here($linenr, $cnt, $here);
5920b13edf7fSJoe Perches
5921ac8e97f8SJoe Perches				if (($stmts =~ tr/;/;/) == 1 &&
5922ac8e97f8SJoe Perches				    $stmts !~ /^\s*(if|while|for|switch)\b/) {
5923b13edf7fSJoe Perches					WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",
5924b13edf7fSJoe Perches					     "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");
5925b13edf7fSJoe Perches				}
5926b13edf7fSJoe Perches				if (defined $semis && $semis ne "") {
5927b13edf7fSJoe Perches					WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
5928b13edf7fSJoe Perches					     "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
5929b13edf7fSJoe Perches				}
5930f5ef95b1SJoe Perches			} elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
5931f5ef95b1SJoe Perches				$ctx =~ s/\n*$//;
5932f5ef95b1SJoe Perches				my $cnt = statement_rawlines($ctx);
5933e3d95a2aSTobin C. Harding				my $herectx = get_stat_here($linenr, $cnt, $here);
5934f5ef95b1SJoe Perches
5935f5ef95b1SJoe Perches				WARN("TRAILING_SEMICOLON",
5936f5ef95b1SJoe Perches				     "macros should not use a trailing semicolon\n" . "$herectx");
5937b13edf7fSJoe Perches			}
5938b13edf7fSJoe Perches		}
5939b13edf7fSJoe Perches
5940f0a594c1SAndy Whitcroft# check for redundant bracing round if etc
594113214adfSAndy Whitcroft		if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
594213214adfSAndy Whitcroft			my ($level, $endln, @chunks) =
5943cf655043SAndy Whitcroft				ctx_statement_full($linenr, $realcnt, 1);
594413214adfSAndy Whitcroft			#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
5945cf655043SAndy Whitcroft			#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
5946cf655043SAndy Whitcroft			if ($#chunks > 0 && $level == 0) {
5947aad4f614SJoe Perches				my @allowed = ();
5948aad4f614SJoe Perches				my $allow = 0;
594913214adfSAndy Whitcroft				my $seen = 0;
5950773647a0SAndy Whitcroft				my $herectx = $here . "\n";
5951cf655043SAndy Whitcroft				my $ln = $linenr - 1;
595213214adfSAndy Whitcroft				for my $chunk (@chunks) {
595313214adfSAndy Whitcroft					my ($cond, $block) = @{$chunk};
595413214adfSAndy Whitcroft
5955773647a0SAndy Whitcroft					# If the condition carries leading newlines, then count those as offsets.
5956773647a0SAndy Whitcroft					my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
5957773647a0SAndy Whitcroft					my $offset = statement_rawlines($whitespace) - 1;
5958773647a0SAndy Whitcroft
5959aad4f614SJoe Perches					$allowed[$allow] = 0;
5960773647a0SAndy Whitcroft					#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
5961773647a0SAndy Whitcroft
5962773647a0SAndy Whitcroft					# We have looked at and allowed this specific line.
5963773647a0SAndy Whitcroft					$suppress_ifbraces{$ln + $offset} = 1;
5964773647a0SAndy Whitcroft
5965773647a0SAndy Whitcroft					$herectx .= "$rawlines[$ln + $offset]\n[...]\n";
5966cf655043SAndy Whitcroft					$ln += statement_rawlines($block) - 1;
5967cf655043SAndy Whitcroft
5968773647a0SAndy Whitcroft					substr($block, 0, length($cond), '');
596913214adfSAndy Whitcroft
597013214adfSAndy Whitcroft					$seen++ if ($block =~ /^\s*{/);
597113214adfSAndy Whitcroft
5972aad4f614SJoe Perches					#print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
5973cf655043SAndy Whitcroft					if (statement_lines($cond) > 1) {
5974cf655043SAndy Whitcroft						#print "APW: ALLOWED: cond<$cond>\n";
5975aad4f614SJoe Perches						$allowed[$allow] = 1;
597613214adfSAndy Whitcroft					}
597713214adfSAndy Whitcroft					if ($block =~/\b(?:if|for|while)\b/) {
5978cf655043SAndy Whitcroft						#print "APW: ALLOWED: block<$block>\n";
5979aad4f614SJoe Perches						$allowed[$allow] = 1;
598013214adfSAndy Whitcroft					}
5981cf655043SAndy Whitcroft					if (statement_block_size($block) > 1) {
5982cf655043SAndy Whitcroft						#print "APW: ALLOWED: lines block<$block>\n";
5983aad4f614SJoe Perches						$allowed[$allow] = 1;
598413214adfSAndy Whitcroft					}
5985aad4f614SJoe Perches					$allow++;
598613214adfSAndy Whitcroft				}
5987aad4f614SJoe Perches				if ($seen) {
5988aad4f614SJoe Perches					my $sum_allowed = 0;
5989aad4f614SJoe Perches					foreach (@allowed) {
5990aad4f614SJoe Perches						$sum_allowed += $_;
5991aad4f614SJoe Perches					}
5992aad4f614SJoe Perches					if ($sum_allowed == 0) {
5993000d1cc1SJoe Perches						WARN("BRACES",
5994000d1cc1SJoe Perches						     "braces {} are not necessary for any arm of this statement\n" . $herectx);
5995aad4f614SJoe Perches					} elsif ($sum_allowed != $allow &&
5996aad4f614SJoe Perches						 $seen != $allow) {
5997aad4f614SJoe Perches						CHK("BRACES",
5998aad4f614SJoe Perches						    "braces {} should be used on all arms of this statement\n" . $herectx);
5999aad4f614SJoe Perches					}
600013214adfSAndy Whitcroft				}
600113214adfSAndy Whitcroft			}
600213214adfSAndy Whitcroft		}
6003773647a0SAndy Whitcroft		if (!defined $suppress_ifbraces{$linenr - 1} &&
600413214adfSAndy Whitcroft					$line =~ /\b(if|while|for|else)\b/) {
6005cf655043SAndy Whitcroft			my $allowed = 0;
6006f0a594c1SAndy Whitcroft
6007cf655043SAndy Whitcroft			# Check the pre-context.
6008cf655043SAndy Whitcroft			if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
6009cf655043SAndy Whitcroft				#print "APW: ALLOWED: pre<$1>\n";
6010cf655043SAndy Whitcroft				$allowed = 1;
6011f0a594c1SAndy Whitcroft			}
6012773647a0SAndy Whitcroft
6013773647a0SAndy Whitcroft			my ($level, $endln, @chunks) =
6014773647a0SAndy Whitcroft				ctx_statement_full($linenr, $realcnt, $-[0]);
6015773647a0SAndy Whitcroft
6016cf655043SAndy Whitcroft			# Check the condition.
6017cf655043SAndy Whitcroft			my ($cond, $block) = @{$chunks[0]};
6018773647a0SAndy Whitcroft			#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
6019cf655043SAndy Whitcroft			if (defined $cond) {
6020773647a0SAndy Whitcroft				substr($block, 0, length($cond), '');
6021cf655043SAndy Whitcroft			}
6022cf655043SAndy Whitcroft			if (statement_lines($cond) > 1) {
6023cf655043SAndy Whitcroft				#print "APW: ALLOWED: cond<$cond>\n";
6024cf655043SAndy Whitcroft				$allowed = 1;
6025cf655043SAndy Whitcroft			}
6026cf655043SAndy Whitcroft			if ($block =~/\b(?:if|for|while)\b/) {
6027cf655043SAndy Whitcroft				#print "APW: ALLOWED: block<$block>\n";
6028cf655043SAndy Whitcroft				$allowed = 1;
6029cf655043SAndy Whitcroft			}
6030cf655043SAndy Whitcroft			if (statement_block_size($block) > 1) {
6031cf655043SAndy Whitcroft				#print "APW: ALLOWED: lines block<$block>\n";
6032cf655043SAndy Whitcroft				$allowed = 1;
6033cf655043SAndy Whitcroft			}
6034cf655043SAndy Whitcroft			# Check the post-context.
6035cf655043SAndy Whitcroft			if (defined $chunks[1]) {
6036cf655043SAndy Whitcroft				my ($cond, $block) = @{$chunks[1]};
6037cf655043SAndy Whitcroft				if (defined $cond) {
6038773647a0SAndy Whitcroft					substr($block, 0, length($cond), '');
6039cf655043SAndy Whitcroft				}
6040cf655043SAndy Whitcroft				if ($block =~ /^\s*\{/) {
6041cf655043SAndy Whitcroft					#print "APW: ALLOWED: chunk-1 block<$block>\n";
6042cf655043SAndy Whitcroft					$allowed = 1;
6043cf655043SAndy Whitcroft				}
6044cf655043SAndy Whitcroft			}
6045cf655043SAndy Whitcroft			if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
6046f055663cSAndy Whitcroft				my $cnt = statement_rawlines($block);
6047e3d95a2aSTobin C. Harding				my $herectx = get_stat_here($linenr, $cnt, $here);
6048cf655043SAndy Whitcroft
6049000d1cc1SJoe Perches				WARN("BRACES",
6050000d1cc1SJoe Perches				     "braces {} are not necessary for single statement blocks\n" . $herectx);
6051f0a594c1SAndy Whitcroft			}
6052f0a594c1SAndy Whitcroft		}
6053f0a594c1SAndy Whitcroft
6054e4c5babdSJoe Perches# check for single line unbalanced braces
605595330473SSven Eckelmann		if ($sline =~ /^.\s*\}\s*else\s*$/ ||
605695330473SSven Eckelmann		    $sline =~ /^.\s*else\s*\{\s*$/) {
6057e4c5babdSJoe Perches			CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);
6058e4c5babdSJoe Perches		}
6059e4c5babdSJoe Perches
60600979ae66SJoe Perches# check for unnecessary blank lines around braces
606177b9a53aSJoe Perches		if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
6062f8e58219SJoe Perches			if (CHK("BRACES",
6063f8e58219SJoe Perches				"Blank lines aren't necessary before a close brace '}'\n" . $hereprev) &&
6064f8e58219SJoe Perches			    $fix && $prevrawline =~ /^\+/) {
6065f8e58219SJoe Perches				fix_delete_line($fixlinenr - 1, $prevrawline);
6066f8e58219SJoe Perches			}
60670979ae66SJoe Perches		}
606877b9a53aSJoe Perches		if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) {
6069f8e58219SJoe Perches			if (CHK("BRACES",
6070f8e58219SJoe Perches				"Blank lines aren't necessary after an open brace '{'\n" . $hereprev) &&
6071f8e58219SJoe Perches			    $fix) {
6072f8e58219SJoe Perches				fix_delete_line($fixlinenr, $rawline);
6073f8e58219SJoe Perches			}
60740979ae66SJoe Perches		}
60750979ae66SJoe Perches
60764a0df2efSAndy Whitcroft# no volatiles please
60776c72ffaaSAndy Whitcroft		my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
60786c72ffaaSAndy Whitcroft		if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
6079000d1cc1SJoe Perches			WARN("VOLATILE",
60808c27ceffSMauro Carvalho Chehab			     "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);
60814a0df2efSAndy Whitcroft		}
60824a0df2efSAndy Whitcroft
60835e4f6ba5SJoe Perches# Check for user-visible strings broken across lines, which breaks the ability
60845e4f6ba5SJoe Perches# to grep for the string.  Make exceptions when the previous string ends in a
60855e4f6ba5SJoe Perches# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
60865e4f6ba5SJoe Perches# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
608733acb54aSJoe Perches		if ($line =~ /^\+\s*$String/ &&
60885e4f6ba5SJoe Perches		    $prevline =~ /"\s*$/ &&
60895e4f6ba5SJoe Perches		    $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
60905e4f6ba5SJoe Perches			if (WARN("SPLIT_STRING",
60915e4f6ba5SJoe Perches				 "quoted string split across lines\n" . $hereprev) &&
60925e4f6ba5SJoe Perches				     $fix &&
60935e4f6ba5SJoe Perches				     $prevrawline =~ /^\+.*"\s*$/ &&
60945e4f6ba5SJoe Perches				     $last_coalesced_string_linenr != $linenr - 1) {
60955e4f6ba5SJoe Perches				my $extracted_string = get_quoted_string($line, $rawline);
60965e4f6ba5SJoe Perches				my $comma_close = "";
60975e4f6ba5SJoe Perches				if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) {
60985e4f6ba5SJoe Perches					$comma_close = $1;
60995e4f6ba5SJoe Perches				}
61005e4f6ba5SJoe Perches
61015e4f6ba5SJoe Perches				fix_delete_line($fixlinenr - 1, $prevrawline);
61025e4f6ba5SJoe Perches				fix_delete_line($fixlinenr, $rawline);
61035e4f6ba5SJoe Perches				my $fixedline = $prevrawline;
61045e4f6ba5SJoe Perches				$fixedline =~ s/"\s*$//;
61055e4f6ba5SJoe Perches				$fixedline .= substr($extracted_string, 1) . trim($comma_close);
61065e4f6ba5SJoe Perches				fix_insert_line($fixlinenr - 1, $fixedline);
61075e4f6ba5SJoe Perches				$fixedline = $rawline;
61085e4f6ba5SJoe Perches				$fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//;
61095e4f6ba5SJoe Perches				if ($fixedline !~ /\+\s*$/) {
61105e4f6ba5SJoe Perches					fix_insert_line($fixlinenr, $fixedline);
61115e4f6ba5SJoe Perches				}
61125e4f6ba5SJoe Perches				$last_coalesced_string_linenr = $linenr;
61135e4f6ba5SJoe Perches			}
61145e4f6ba5SJoe Perches		}
61155e4f6ba5SJoe Perches
61165e4f6ba5SJoe Perches# check for missing a space in a string concatenation
61175e4f6ba5SJoe Perches		if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {
61185e4f6ba5SJoe Perches			WARN('MISSING_SPACE',
61195e4f6ba5SJoe Perches			     "break quoted strings at a space character\n" . $hereprev);
61205e4f6ba5SJoe Perches		}
61215e4f6ba5SJoe Perches
612277cb8546SJoe Perches# check for an embedded function name in a string when the function is known
6123e4b7d309SJoe Perches# This does not work very well for -f --file checking as it depends on patch
6124e4b7d309SJoe Perches# context providing the function name or a single line form for in-file
6125e4b7d309SJoe Perches# function declarations
612677cb8546SJoe Perches		if ($line =~ /^\+.*$String/ &&
612777cb8546SJoe Perches		    defined($context_function) &&
6128e4b7d309SJoe Perches		    get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&
6129e4b7d309SJoe Perches		    length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {
613077cb8546SJoe Perches			WARN("EMBEDDED_FUNCTION_NAME",
6131e4b7d309SJoe Perches			     "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
613277cb8546SJoe Perches		}
613377cb8546SJoe Perches
6134adb2da82SJoe Perches# check for unnecessary function tracing like uses
6135adb2da82SJoe Perches# This does not use $logFunctions because there are many instances like
6136adb2da82SJoe Perches# 'dprintk(FOO, "%s()\n", __func__);' which do not match $logFunctions
6137adb2da82SJoe Perches		if ($rawline =~ /^\+.*\([^"]*"$tracing_logging_tags{0,3}%s(?:\s*\(\s*\)\s*)?$tracing_logging_tags{0,3}(?:\\n)?"\s*,\s*__func__\s*\)\s*;/) {
6138adb2da82SJoe Perches			if (WARN("TRACING_LOGGING",
6139adb2da82SJoe Perches				 "Unnecessary ftrace-like logging - prefer using ftrace\n" . $herecurr) &&
6140adb2da82SJoe Perches			    $fix) {
6141adb2da82SJoe Perches                                fix_delete_line($fixlinenr, $rawline);
6142adb2da82SJoe Perches			}
6143adb2da82SJoe Perches		}
6144adb2da82SJoe Perches
61455e4f6ba5SJoe Perches# check for spaces before a quoted newline
61465e4f6ba5SJoe Perches		if ($rawline =~ /^.*\".*\s\\n/) {
61475e4f6ba5SJoe Perches			if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
61485e4f6ba5SJoe Perches				 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
61495e4f6ba5SJoe Perches			    $fix) {
61505e4f6ba5SJoe Perches				$fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
61515e4f6ba5SJoe Perches			}
61525e4f6ba5SJoe Perches
61535e4f6ba5SJoe Perches		}
61545e4f6ba5SJoe Perches
6155f17dba4fSJoe Perches# concatenated string without spaces between elements
6156d2af5aa6SJoe Perches		if ($line =~ /$String[A-Z_]/ ||
6157d2af5aa6SJoe Perches		    ($line =~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^[Lu]$/)) {
615879682c0cSJoe Perches			if (CHK("CONCATENATED_STRING",
615979682c0cSJoe Perches				"Concatenated strings should use spaces between elements\n" . $herecurr) &&
616079682c0cSJoe Perches			    $fix) {
616179682c0cSJoe Perches				while ($line =~ /($String)/g) {
616279682c0cSJoe Perches					my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
616379682c0cSJoe Perches					$fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
616479682c0cSJoe Perches					$fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
616579682c0cSJoe Perches				}
616679682c0cSJoe Perches			}
6167f17dba4fSJoe Perches		}
6168f17dba4fSJoe Perches
616990ad30e5SJoe Perches# uncoalesced string fragments
6170d2af5aa6SJoe Perches		if ($line =~ /$String\s*[Lu]?"/) {
617179682c0cSJoe Perches			if (WARN("STRING_FRAGMENTS",
617279682c0cSJoe Perches				 "Consecutive strings are generally better as a single string\n" . $herecurr) &&
617379682c0cSJoe Perches			    $fix) {
617479682c0cSJoe Perches				while ($line =~ /($String)(?=\s*")/g) {
617579682c0cSJoe Perches					my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
617679682c0cSJoe Perches					$fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
617779682c0cSJoe Perches				}
617879682c0cSJoe Perches			}
617990ad30e5SJoe Perches		}
618090ad30e5SJoe Perches
6181522b837cSAlexey Dobriyan# check for non-standard and hex prefixed decimal printf formats
6182522b837cSAlexey Dobriyan		my $show_L = 1;	#don't show the same defect twice
6183522b837cSAlexey Dobriyan		my $show_Z = 1;
61845e4f6ba5SJoe Perches		while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
6185522b837cSAlexey Dobriyan			my $string = substr($rawline, $-[1], $+[1] - $-[1]);
61865e4f6ba5SJoe Perches			$string =~ s/%%/__/g;
6187522b837cSAlexey Dobriyan			# check for %L
6188522b837cSAlexey Dobriyan			if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) {
61895e4f6ba5SJoe Perches				WARN("PRINTF_L",
6190522b837cSAlexey Dobriyan				     "\%L$1 is non-standard C, use %ll$1\n" . $herecurr);
6191522b837cSAlexey Dobriyan				$show_L = 0;
61925e4f6ba5SJoe Perches			}
6193522b837cSAlexey Dobriyan			# check for %Z
6194522b837cSAlexey Dobriyan			if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) {
6195522b837cSAlexey Dobriyan				WARN("PRINTF_Z",
6196522b837cSAlexey Dobriyan				     "%Z$1 is non-standard C, use %z$1\n" . $herecurr);
6197522b837cSAlexey Dobriyan				$show_Z = 0;
6198522b837cSAlexey Dobriyan			}
6199522b837cSAlexey Dobriyan			# check for 0x<decimal>
6200522b837cSAlexey Dobriyan			if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) {
6201522b837cSAlexey Dobriyan				ERROR("PRINTF_0XDECIMAL",
62026e300757SJoe Perches				      "Prefixing 0x with decimal output is defective\n" . $herecurr);
62036e300757SJoe Perches			}
62045e4f6ba5SJoe Perches		}
62055e4f6ba5SJoe Perches
62065e4f6ba5SJoe Perches# check for line continuations in quoted strings with odd counts of "
62073f7f335dSJoe Perches		if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {
62085e4f6ba5SJoe Perches			WARN("LINE_CONTINUATIONS",
62095e4f6ba5SJoe Perches			     "Avoid line continuations in quoted strings\n" . $herecurr);
62105e4f6ba5SJoe Perches		}
62115e4f6ba5SJoe Perches
621200df344fSAndy Whitcroft# warn about #if 0
6213c45dcabdSAndy Whitcroft		if ($line =~ /^.\s*\#\s*if\s+0\b/) {
621460f89010SPrakruthi Deepak Heragu			WARN("IF_0",
621560f89010SPrakruthi Deepak Heragu			     "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
621660f89010SPrakruthi Deepak Heragu		}
621760f89010SPrakruthi Deepak Heragu
621860f89010SPrakruthi Deepak Heragu# warn about #if 1
621960f89010SPrakruthi Deepak Heragu		if ($line =~ /^.\s*\#\s*if\s+1\b/) {
622060f89010SPrakruthi Deepak Heragu			WARN("IF_1",
622160f89010SPrakruthi Deepak Heragu			     "Consider removing the #if 1 and its #endif\n" . $herecurr);
62224a0df2efSAndy Whitcroft		}
62234a0df2efSAndy Whitcroft
622403df4b51SAndy Whitcroft# check for needless "if (<foo>) fn(<foo>)" uses
622503df4b51SAndy Whitcroft		if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {
6226100425deSJoe Perches			my $tested = quotemeta($1);
6227100425deSJoe Perches			my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;';
6228100425deSJoe Perches			if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) {
6229100425deSJoe Perches				my $func = $1;
6230100425deSJoe Perches				if (WARN('NEEDLESS_IF',
6231100425deSJoe Perches					 "$func(NULL) is safe and this check is probably not required\n" . $hereprev) &&
6232100425deSJoe Perches				    $fix) {
6233100425deSJoe Perches					my $do_fix = 1;
6234100425deSJoe Perches					my $leading_tabs = "";
6235100425deSJoe Perches					my $new_leading_tabs = "";
6236100425deSJoe Perches					if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) {
6237100425deSJoe Perches						$leading_tabs = $1;
6238100425deSJoe Perches					} else {
6239100425deSJoe Perches						$do_fix = 0;
6240100425deSJoe Perches					}
6241100425deSJoe Perches					if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) {
6242100425deSJoe Perches						$new_leading_tabs = $1;
6243100425deSJoe Perches						if (length($leading_tabs) + 1 ne length($new_leading_tabs)) {
6244100425deSJoe Perches							$do_fix = 0;
6245100425deSJoe Perches						}
6246100425deSJoe Perches					} else {
6247100425deSJoe Perches						$do_fix = 0;
6248100425deSJoe Perches					}
6249100425deSJoe Perches					if ($do_fix) {
6250100425deSJoe Perches						fix_delete_line($fixlinenr - 1, $prevrawline);
6251100425deSJoe Perches						$fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/;
6252100425deSJoe Perches					}
6253100425deSJoe Perches				}
62544c432a8fSGreg Kroah-Hartman			}
62554c432a8fSGreg Kroah-Hartman		}
6256f0a594c1SAndy Whitcroft
6257ebfdc409SJoe Perches# check for unnecessary "Out of Memory" messages
6258ebfdc409SJoe Perches		if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
6259ebfdc409SJoe Perches		    $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
6260ebfdc409SJoe Perches		    (defined $1 || defined $3) &&
6261ebfdc409SJoe Perches		    $linenr > 3) {
6262ebfdc409SJoe Perches			my $testval = $2;
6263ebfdc409SJoe Perches			my $testline = $lines[$linenr - 3];
6264ebfdc409SJoe Perches
6265ebfdc409SJoe Perches			my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
6266ebfdc409SJoe Perches#			print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
6267ebfdc409SJoe Perches
6268e29a70f1SJoe Perches			if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
6269e29a70f1SJoe Perches			    $s !~ /\b__GFP_NOWARN\b/ ) {
6270ebfdc409SJoe Perches				WARN("OOM_MESSAGE",
6271ebfdc409SJoe Perches				     "Possible unnecessary 'out of memory' message\n" . $hereprev);
6272ebfdc409SJoe Perches			}
6273ebfdc409SJoe Perches		}
6274ebfdc409SJoe Perches
6275f78d98f6SJoe Perches# check for logging functions with KERN_<LEVEL>
6276dcaf1123SPaolo Bonzini		if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ &&
6277f78d98f6SJoe Perches		    $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) {
6278f78d98f6SJoe Perches			my $level = $1;
6279f78d98f6SJoe Perches			if (WARN("UNNECESSARY_KERN_LEVEL",
6280f78d98f6SJoe Perches				 "Possible unnecessary $level\n" . $herecurr) &&
6281f78d98f6SJoe Perches			    $fix) {
6282f78d98f6SJoe Perches				$fixed[$fixlinenr] =~ s/\s*$level\s*//;
6283f78d98f6SJoe Perches			}
6284f78d98f6SJoe Perches		}
6285f78d98f6SJoe Perches
628645c55e92SJoe Perches# check for logging continuations
628745c55e92SJoe Perches		if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) {
628845c55e92SJoe Perches			WARN("LOGGING_CONTINUATION",
628945c55e92SJoe Perches			     "Avoid logging continuation uses where feasible\n" . $herecurr);
629045c55e92SJoe Perches		}
629145c55e92SJoe Perches
629270eb2275SDwaipayan Ray# check for unnecessary use of %h[xudi] and %hh[xudi] in logging functions
629370eb2275SDwaipayan Ray		if (defined $stat &&
629470eb2275SDwaipayan Ray		    $line =~ /\b$logFunctions\s*\(/ &&
629570eb2275SDwaipayan Ray		    index($stat, '"') >= 0) {
629670eb2275SDwaipayan Ray			my $lc = $stat =~ tr@\n@@;
629770eb2275SDwaipayan Ray			$lc = $lc + $linenr;
629870eb2275SDwaipayan Ray			my $stat_real = get_stat_real($linenr, $lc);
629970eb2275SDwaipayan Ray			pos($stat_real) = index($stat_real, '"');
630070eb2275SDwaipayan Ray			while ($stat_real =~ /[^\"%]*(%[\#\d\.\*\-]*(h+)[idux])/g) {
630170eb2275SDwaipayan Ray				my $pspec = $1;
630270eb2275SDwaipayan Ray				my $h = $2;
630370eb2275SDwaipayan Ray				my $lineoff = substr($stat_real, 0, $-[1]) =~ tr@\n@@;
630470eb2275SDwaipayan Ray				if (WARN("UNNECESSARY_MODIFIER",
630570eb2275SDwaipayan Ray					 "Integer promotion: Using '$h' in '$pspec' is unnecessary\n" . "$here\n$stat_real\n") &&
630670eb2275SDwaipayan Ray				    $fix && $fixed[$fixlinenr + $lineoff] =~ /^\+/) {
630770eb2275SDwaipayan Ray					my $nspec = $pspec;
630870eb2275SDwaipayan Ray					$nspec =~ s/h//g;
630970eb2275SDwaipayan Ray					$fixed[$fixlinenr + $lineoff] =~ s/\Q$pspec\E/$nspec/;
631070eb2275SDwaipayan Ray				}
631170eb2275SDwaipayan Ray			}
631270eb2275SDwaipayan Ray		}
631370eb2275SDwaipayan Ray
6314abb08a53SJoe Perches# check for mask then right shift without a parentheses
63155b57980dSJoe Perches		if ($perl_version_ok &&
6316abb08a53SJoe Perches		    $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
6317abb08a53SJoe Perches		    $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
6318abb08a53SJoe Perches			WARN("MASK_THEN_SHIFT",
6319abb08a53SJoe Perches			     "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr);
6320abb08a53SJoe Perches		}
6321abb08a53SJoe Perches
6322b75ac618SJoe Perches# check for pointer comparisons to NULL
63235b57980dSJoe Perches		if ($perl_version_ok) {
6324b75ac618SJoe Perches			while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
6325b75ac618SJoe Perches				my $val = $1;
6326b75ac618SJoe Perches				my $equal = "!";
6327b75ac618SJoe Perches				$equal = "" if ($4 eq "!=");
6328b75ac618SJoe Perches				if (CHK("COMPARISON_TO_NULL",
6329b75ac618SJoe Perches					"Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) &&
6330b75ac618SJoe Perches					    $fix) {
6331b75ac618SJoe Perches					$fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/;
6332b75ac618SJoe Perches				}
6333b75ac618SJoe Perches			}
6334b75ac618SJoe Perches		}
6335b75ac618SJoe Perches
63368716de38SJoe Perches# check for bad placement of section $InitAttribute (e.g.: __initdata)
63378716de38SJoe Perches		if ($line =~ /(\b$InitAttribute\b)/) {
63388716de38SJoe Perches			my $attr = $1;
63398716de38SJoe Perches			if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) {
63408716de38SJoe Perches				my $ptr = $1;
63418716de38SJoe Perches				my $var = $2;
63428716de38SJoe Perches				if ((($ptr =~ /\b(union|struct)\s+$attr\b/ &&
63438716de38SJoe Perches				      ERROR("MISPLACED_INIT",
63448716de38SJoe Perches					    "$attr should be placed after $var\n" . $herecurr)) ||
63458716de38SJoe Perches				     ($ptr !~ /\b(union|struct)\s+$attr\b/ &&
63468716de38SJoe Perches				      WARN("MISPLACED_INIT",
63478716de38SJoe Perches					   "$attr should be placed after $var\n" . $herecurr))) &&
63488716de38SJoe Perches				    $fix) {
6349194f66fcSJoe Perches					$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;
63508716de38SJoe Perches				}
63518716de38SJoe Perches			}
63528716de38SJoe Perches		}
63538716de38SJoe Perches
6354e970b884SJoe Perches# check for $InitAttributeData (ie: __initdata) with const
6355e970b884SJoe Perches		if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
6356e970b884SJoe Perches			my $attr = $1;
6357e970b884SJoe Perches			$attr =~ /($InitAttributePrefix)(.*)/;
6358e970b884SJoe Perches			my $attr_prefix = $1;
6359e970b884SJoe Perches			my $attr_type = $2;
6360e970b884SJoe Perches			if (ERROR("INIT_ATTRIBUTE",
6361e970b884SJoe Perches				  "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
6362e970b884SJoe Perches			    $fix) {
6363194f66fcSJoe Perches				$fixed[$fixlinenr] =~
6364e970b884SJoe Perches				    s/$InitAttributeData/${attr_prefix}initconst/;
6365e970b884SJoe Perches			}
6366e970b884SJoe Perches		}
6367e970b884SJoe Perches
6368e970b884SJoe Perches# check for $InitAttributeConst (ie: __initconst) without const
6369e970b884SJoe Perches		if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
6370e970b884SJoe Perches			my $attr = $1;
6371e970b884SJoe Perches			if (ERROR("INIT_ATTRIBUTE",
6372e970b884SJoe Perches				  "Use of $attr requires a separate use of const\n" . $herecurr) &&
6373e970b884SJoe Perches			    $fix) {
6374194f66fcSJoe Perches				my $lead = $fixed[$fixlinenr] =~
6375e970b884SJoe Perches				    /(^\+\s*(?:static\s+))/;
6376e970b884SJoe Perches				$lead = rtrim($1);
6377e970b884SJoe Perches				$lead = "$lead " if ($lead !~ /^\+$/);
6378e970b884SJoe Perches				$lead = "${lead}const ";
6379194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/;
6380e970b884SJoe Perches			}
6381e970b884SJoe Perches		}
6382e970b884SJoe Perches
6383c17893c7SJoe Perches# check for __read_mostly with const non-pointer (should just be const)
6384c17893c7SJoe Perches		if ($line =~ /\b__read_mostly\b/ &&
6385c17893c7SJoe Perches		    $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) {
6386c17893c7SJoe Perches			if (ERROR("CONST_READ_MOSTLY",
6387c17893c7SJoe Perches				  "Invalid use of __read_mostly with const type\n" . $herecurr) &&
6388c17893c7SJoe Perches			    $fix) {
6389c17893c7SJoe Perches				$fixed[$fixlinenr] =~ s/\s+__read_mostly\b//;
6390c17893c7SJoe Perches			}
6391c17893c7SJoe Perches		}
6392c17893c7SJoe Perches
6393fbdb8138SJoe Perches# don't use __constant_<foo> functions outside of include/uapi/
6394fbdb8138SJoe Perches		if ($realfile !~ m@^include/uapi/@ &&
6395fbdb8138SJoe Perches		    $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
6396fbdb8138SJoe Perches			my $constant_func = $1;
6397fbdb8138SJoe Perches			my $func = $constant_func;
6398fbdb8138SJoe Perches			$func =~ s/^__constant_//;
6399fbdb8138SJoe Perches			if (WARN("CONSTANT_CONVERSION",
6400fbdb8138SJoe Perches				 "$constant_func should be $func\n" . $herecurr) &&
6401fbdb8138SJoe Perches			    $fix) {
6402194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
6403fbdb8138SJoe Perches			}
6404fbdb8138SJoe Perches		}
6405fbdb8138SJoe Perches
64061a15a250SPatrick Pannuto# prefer usleep_range over udelay
640737581c28SBruce Allan		if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
640843c1d77cSJoe Perches			my $delay = $1;
64091a15a250SPatrick Pannuto			# ignore udelay's < 10, however
641043c1d77cSJoe Perches			if (! ($delay < 10) ) {
6411000d1cc1SJoe Perches				CHK("USLEEP_RANGE",
6412458f69efSMauro Carvalho Chehab				    "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
641343c1d77cSJoe Perches			}
641443c1d77cSJoe Perches			if ($delay > 2000) {
641543c1d77cSJoe Perches				WARN("LONG_UDELAY",
641643c1d77cSJoe Perches				     "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
64171a15a250SPatrick Pannuto			}
64181a15a250SPatrick Pannuto		}
64191a15a250SPatrick Pannuto
642009ef8725SPatrick Pannuto# warn about unexpectedly long msleep's
642109ef8725SPatrick Pannuto		if ($line =~ /\bmsleep\s*\((\d+)\);/) {
642209ef8725SPatrick Pannuto			if ($1 < 20) {
6423000d1cc1SJoe Perches				WARN("MSLEEP",
6424458f69efSMauro Carvalho Chehab				     "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
642509ef8725SPatrick Pannuto			}
642609ef8725SPatrick Pannuto		}
642709ef8725SPatrick Pannuto
642836ec1939SJoe Perches# check for comparisons of jiffies
642936ec1939SJoe Perches		if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
643036ec1939SJoe Perches			WARN("JIFFIES_COMPARISON",
643136ec1939SJoe Perches			     "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
643236ec1939SJoe Perches		}
643336ec1939SJoe Perches
64349d7a34a5SJoe Perches# check for comparisons of get_jiffies_64()
64359d7a34a5SJoe Perches		if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
64369d7a34a5SJoe Perches			WARN("JIFFIES_COMPARISON",
64379d7a34a5SJoe Perches			     "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
64389d7a34a5SJoe Perches		}
64399d7a34a5SJoe Perches
644000df344fSAndy Whitcroft# warn about #ifdefs in C files
6441c45dcabdSAndy Whitcroft#		if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
644200df344fSAndy Whitcroft#			print "#ifdef in C files should be avoided\n";
644300df344fSAndy Whitcroft#			print "$herecurr";
644400df344fSAndy Whitcroft#			$clean = 0;
644500df344fSAndy Whitcroft#		}
644600df344fSAndy Whitcroft
644722f2a2efSAndy Whitcroft# warn about spacing in #ifdefs
6448c45dcabdSAndy Whitcroft		if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
64493705ce5bSJoe Perches			if (ERROR("SPACING",
64503705ce5bSJoe Perches				  "exactly one space required after that #$1\n" . $herecurr) &&
64513705ce5bSJoe Perches			    $fix) {
6452194f66fcSJoe Perches				$fixed[$fixlinenr] =~
64533705ce5bSJoe Perches				    s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
64543705ce5bSJoe Perches			}
64553705ce5bSJoe Perches
645622f2a2efSAndy Whitcroft		}
645722f2a2efSAndy Whitcroft
64584a0df2efSAndy Whitcroft# check for spinlock_t definitions without a comment.
6459171ae1a4SAndy Whitcroft		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
6460171ae1a4SAndy Whitcroft		    $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
64614a0df2efSAndy Whitcroft			my $which = $1;
64624a0df2efSAndy Whitcroft			if (!ctx_has_comment($first_line, $linenr)) {
6463000d1cc1SJoe Perches				CHK("UNCOMMENTED_DEFINITION",
6464000d1cc1SJoe Perches				    "$1 definition without comment\n" . $herecurr);
64654a0df2efSAndy Whitcroft			}
64664a0df2efSAndy Whitcroft		}
64674a0df2efSAndy Whitcroft# check for memory barriers without a comment.
6468402c2553SMichael S. Tsirkin
6469402c2553SMichael S. Tsirkin		my $barriers = qr{
6470402c2553SMichael S. Tsirkin			mb|
6471402c2553SMichael S. Tsirkin			rmb|
6472ad83ec6cSWill Deacon			wmb
6473402c2553SMichael S. Tsirkin		}x;
6474402c2553SMichael S. Tsirkin		my $barrier_stems = qr{
6475402c2553SMichael S. Tsirkin			mb__before_atomic|
6476402c2553SMichael S. Tsirkin			mb__after_atomic|
6477402c2553SMichael S. Tsirkin			store_release|
6478402c2553SMichael S. Tsirkin			load_acquire|
6479402c2553SMichael S. Tsirkin			store_mb|
6480402c2553SMichael S. Tsirkin			(?:$barriers)
6481402c2553SMichael S. Tsirkin		}x;
6482402c2553SMichael S. Tsirkin		my $all_barriers = qr{
6483402c2553SMichael S. Tsirkin			(?:$barriers)|
648443e361f2SMichael S. Tsirkin			smp_(?:$barrier_stems)|
648543e361f2SMichael S. Tsirkin			virt_(?:$barrier_stems)
6486402c2553SMichael S. Tsirkin		}x;
6487402c2553SMichael S. Tsirkin
6488402c2553SMichael S. Tsirkin		if ($line =~ /\b(?:$all_barriers)\s*\(/) {
64894a0df2efSAndy Whitcroft			if (!ctx_has_comment($first_line, $linenr)) {
6490c1fd7bb9SJoe Perches				WARN("MEMORY_BARRIER",
6491000d1cc1SJoe Perches				     "memory barrier without comment\n" . $herecurr);
64924a0df2efSAndy Whitcroft			}
64934a0df2efSAndy Whitcroft		}
64943ad81779SPaul E. McKenney
6495f4073b0fSMichael S. Tsirkin		my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x;
6496f4073b0fSMichael S. Tsirkin
6497f4073b0fSMichael S. Tsirkin		if ($realfile !~ m@^include/asm-generic/@ &&
6498f4073b0fSMichael S. Tsirkin		    $realfile !~ m@/barrier\.h$@ &&
6499f4073b0fSMichael S. Tsirkin		    $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&
6500f4073b0fSMichael S. Tsirkin		    $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {
6501f4073b0fSMichael S. Tsirkin			WARN("MEMORY_BARRIER",
6502f4073b0fSMichael S. Tsirkin			     "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr);
6503f4073b0fSMichael S. Tsirkin		}
6504f4073b0fSMichael S. Tsirkin
6505cb426e99SJoe Perches# check for waitqueue_active without a comment.
6506cb426e99SJoe Perches		if ($line =~ /\bwaitqueue_active\s*\(/) {
6507cb426e99SJoe Perches			if (!ctx_has_comment($first_line, $linenr)) {
6508cb426e99SJoe Perches				WARN("WAITQUEUE_ACTIVE",
6509cb426e99SJoe Perches				     "waitqueue_active without comment\n" . $herecurr);
6510cb426e99SJoe Perches			}
6511cb426e99SJoe Perches		}
65123ad81779SPaul E. McKenney
65135099a722SMarco Elver# check for data_race without a comment.
65145099a722SMarco Elver		if ($line =~ /\bdata_race\s*\(/) {
65155099a722SMarco Elver			if (!ctx_has_comment($first_line, $linenr)) {
65165099a722SMarco Elver				WARN("DATA_RACE",
65175099a722SMarco Elver				     "data_race without comment\n" . $herecurr);
65185099a722SMarco Elver			}
65195099a722SMarco Elver		}
65205099a722SMarco Elver
65214a0df2efSAndy Whitcroft# check of hardware specific defines
6522c45dcabdSAndy Whitcroft		if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
6523000d1cc1SJoe Perches			CHK("ARCH_DEFINES",
6524000d1cc1SJoe Perches			    "architecture specific defines should be avoided\n" .  $herecurr);
65250a920b5bSAndy Whitcroft		}
6526653d4876SAndy Whitcroft
6527596ed45bSJoe Perches# check that the storage class is not after a type
6528596ed45bSJoe Perches		if ($line =~ /\b($Type)\s+($Storage)\b/) {
6529000d1cc1SJoe Perches			WARN("STORAGE_CLASS",
6530596ed45bSJoe Perches			     "storage class '$2' should be located before type '$1'\n" . $herecurr);
6531596ed45bSJoe Perches		}
6532596ed45bSJoe Perches# Check that the storage class is at the beginning of a declaration
6533596ed45bSJoe Perches		if ($line =~ /\b$Storage\b/ &&
6534596ed45bSJoe Perches		    $line !~ /^.\s*$Storage/ &&
6535596ed45bSJoe Perches		    $line =~ /^.\s*(.+?)\$Storage\s/ &&
6536596ed45bSJoe Perches		    $1 !~ /[\,\)]\s*$/) {
6537596ed45bSJoe Perches			WARN("STORAGE_CLASS",
6538596ed45bSJoe Perches			     "storage class should be at the beginning of the declaration\n" . $herecurr);
6539d4977c78STobias Klauser		}
6540d4977c78STobias Klauser
6541de7d4f0eSAndy Whitcroft# check the location of the inline attribute, that it is between
6542de7d4f0eSAndy Whitcroft# storage class and type.
65439c0ca6f9SAndy Whitcroft		if ($line =~ /\b$Type\s+$Inline\b/ ||
65449c0ca6f9SAndy Whitcroft		    $line =~ /\b$Inline\s+$Storage\b/) {
6545000d1cc1SJoe Perches			ERROR("INLINE_LOCATION",
6546000d1cc1SJoe Perches			      "inline keyword should sit between storage class and type\n" . $herecurr);
6547de7d4f0eSAndy Whitcroft		}
6548de7d4f0eSAndy Whitcroft
65498905a67cSAndy Whitcroft# Check for __inline__ and __inline, prefer inline
65502b7ab453SJoe Perches		if ($realfile !~ m@\binclude/uapi/@ &&
65512b7ab453SJoe Perches		    $line =~ /\b(__inline__|__inline)\b/) {
6552d5e616fcSJoe Perches			if (WARN("INLINE",
6553d5e616fcSJoe Perches				 "plain inline is preferred over $1\n" . $herecurr) &&
6554d5e616fcSJoe Perches			    $fix) {
6555194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/;
6556d5e616fcSJoe Perches
6557d5e616fcSJoe Perches			}
65588905a67cSAndy Whitcroft		}
65598905a67cSAndy Whitcroft
65607ebe1d17SDwaipayan Ray# Check for compiler attributes
65612b7ab453SJoe Perches		if ($realfile !~ m@\binclude/uapi/@ &&
65627ebe1d17SDwaipayan Ray		    $rawline =~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) {
65637ebe1d17SDwaipayan Ray			my $attr = $1;
65647ebe1d17SDwaipayan Ray			$attr =~ s/\s*\(\s*(.*)\)\s*/$1/;
65657ebe1d17SDwaipayan Ray
65667ebe1d17SDwaipayan Ray			my %attr_list = (
65670830aab0SJoe Perches				"alias"				=> "__alias",
65687ebe1d17SDwaipayan Ray				"aligned"			=> "__aligned",
65697ebe1d17SDwaipayan Ray				"always_inline"			=> "__always_inline",
65707ebe1d17SDwaipayan Ray				"assume_aligned"		=> "__assume_aligned",
65717ebe1d17SDwaipayan Ray				"cold"				=> "__cold",
65727ebe1d17SDwaipayan Ray				"const"				=> "__attribute_const__",
65737ebe1d17SDwaipayan Ray				"copy"				=> "__copy",
65747ebe1d17SDwaipayan Ray				"designated_init"		=> "__designated_init",
65757ebe1d17SDwaipayan Ray				"externally_visible"		=> "__visible",
65767ebe1d17SDwaipayan Ray				"format"			=> "printf|scanf",
65777ebe1d17SDwaipayan Ray				"gnu_inline"			=> "__gnu_inline",
65787ebe1d17SDwaipayan Ray				"malloc"			=> "__malloc",
65797ebe1d17SDwaipayan Ray				"mode"				=> "__mode",
65807ebe1d17SDwaipayan Ray				"no_caller_saved_registers"	=> "__no_caller_saved_registers",
65817ebe1d17SDwaipayan Ray				"noclone"			=> "__noclone",
65827ebe1d17SDwaipayan Ray				"noinline"			=> "noinline",
65837ebe1d17SDwaipayan Ray				"nonstring"			=> "__nonstring",
65847ebe1d17SDwaipayan Ray				"noreturn"			=> "__noreturn",
65857ebe1d17SDwaipayan Ray				"packed"			=> "__packed",
65867ebe1d17SDwaipayan Ray				"pure"				=> "__pure",
6587339f29d9SJoe Perches				"section"			=> "__section",
65880830aab0SJoe Perches				"used"				=> "__used",
65890830aab0SJoe Perches				"weak"				=> "__weak"
65907ebe1d17SDwaipayan Ray			);
65917ebe1d17SDwaipayan Ray
65927ebe1d17SDwaipayan Ray			while ($attr =~ /\s*(\w+)\s*(${balanced_parens})?/g) {
6593339f29d9SJoe Perches				my $orig_attr = $1;
65947ebe1d17SDwaipayan Ray				my $params = '';
65957ebe1d17SDwaipayan Ray				$params = $2 if defined($2);
6596339f29d9SJoe Perches				my $curr_attr = $orig_attr;
65977ebe1d17SDwaipayan Ray				$curr_attr =~ s/^[\s_]+|[\s_]+$//g;
65987ebe1d17SDwaipayan Ray				if (exists($attr_list{$curr_attr})) {
6599339f29d9SJoe Perches					my $new = $attr_list{$curr_attr};
66007ebe1d17SDwaipayan Ray					if ($curr_attr eq "format" && $params) {
66017ebe1d17SDwaipayan Ray						$params =~ /^\s*\(\s*(\w+)\s*,\s*(.*)/;
6602339f29d9SJoe Perches						$new = "__$1\($2";
66037ebe1d17SDwaipayan Ray					} else {
6604339f29d9SJoe Perches						$new = "$new$params";
66057ebe1d17SDwaipayan Ray					}
66067ebe1d17SDwaipayan Ray					if (WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",
6607339f29d9SJoe Perches						 "Prefer $new over __attribute__(($orig_attr$params))\n" . $herecurr) &&
66087ebe1d17SDwaipayan Ray					    $fix) {
6609339f29d9SJoe Perches						my $remove = "\Q$orig_attr\E" . '\s*' . "\Q$params\E" . '(?:\s*,\s*)?';
6610339f29d9SJoe Perches						$fixed[$fixlinenr] =~ s/$remove//;
6611339f29d9SJoe Perches						$fixed[$fixlinenr] =~ s/\b__attribute__/$new __attribute__/;
6612339f29d9SJoe Perches						$fixed[$fixlinenr] =~ s/\}\Q$new\E/} $new/;
6613339f29d9SJoe Perches						$fixed[$fixlinenr] =~ s/ __attribute__\s*\(\s*\(\s*\)\s*\)//;
66147ebe1d17SDwaipayan Ray					}
661539b7e287SJoe Perches				}
6616462811d9SJoe Perches			}
6617462811d9SJoe Perches
66187ebe1d17SDwaipayan Ray			# Check for __attribute__ unused, prefer __always_unused or __maybe_unused
66197ebe1d17SDwaipayan Ray			if ($attr =~ /^_*unused/) {
66207ebe1d17SDwaipayan Ray				WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",
66217ebe1d17SDwaipayan Ray				     "__always_unused or __maybe_unused is preferred over __attribute__((__unused__))\n" . $herecurr);
6622d5e616fcSJoe Perches			}
66236061d949SJoe Perches		}
66246061d949SJoe Perches
6625619a908aSJoe Perches# Check for __attribute__ weak, or __weak declarations (may have link issues)
66265b57980dSJoe Perches		if ($perl_version_ok &&
6627619a908aSJoe Perches		    $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
6628619a908aSJoe Perches		    ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
6629619a908aSJoe Perches		     $line =~ /\b__weak\b/)) {
6630619a908aSJoe Perches			ERROR("WEAK_DECLARATION",
6631619a908aSJoe Perches			      "Using weak declarations can have unintended link defects\n" . $herecurr);
6632619a908aSJoe Perches		}
6633619a908aSJoe Perches
6634fd39f904STomas Winkler# check for c99 types like uint8_t used outside of uapi/ and tools/
6635e6176fa4SJoe Perches		if ($realfile !~ m@\binclude/uapi/@ &&
6636fd39f904STomas Winkler		    $realfile !~ m@\btools/@ &&
6637e6176fa4SJoe Perches		    $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {
6638e6176fa4SJoe Perches			my $type = $1;
6639e6176fa4SJoe Perches			if ($type =~ /\b($typeC99Typedefs)\b/) {
6640e6176fa4SJoe Perches				$type = $1;
6641e6176fa4SJoe Perches				my $kernel_type = 'u';
6642e6176fa4SJoe Perches				$kernel_type = 's' if ($type =~ /^_*[si]/);
6643e6176fa4SJoe Perches				$type =~ /(\d+)/;
6644e6176fa4SJoe Perches				$kernel_type .= $1;
6645e6176fa4SJoe Perches				if (CHK("PREFER_KERNEL_TYPES",
6646e6176fa4SJoe Perches					"Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) &&
6647e6176fa4SJoe Perches				    $fix) {
6648e6176fa4SJoe Perches					$fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/;
6649e6176fa4SJoe Perches				}
6650e6176fa4SJoe Perches			}
6651e6176fa4SJoe Perches		}
6652e6176fa4SJoe Perches
6653938224b5SJoe Perches# check for cast of C90 native int or longer types constants
6654938224b5SJoe Perches		if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {
6655938224b5SJoe Perches			my $cast = $1;
6656938224b5SJoe Perches			my $const = $2;
6657938224b5SJoe Perches			my $suffix = "";
6658938224b5SJoe Perches			my $newconst = $const;
6659938224b5SJoe Perches			$newconst =~ s/${Int_type}$//;
6660938224b5SJoe Perches			$suffix .= 'U' if ($cast =~ /\bunsigned\b/);
6661938224b5SJoe Perches			if ($cast =~ /\blong\s+long\b/) {
6662938224b5SJoe Perches			    $suffix .= 'LL';
6663938224b5SJoe Perches			} elsif ($cast =~ /\blong\b/) {
6664938224b5SJoe Perches			    $suffix .= 'L';
6665938224b5SJoe Perches			}
66660972b8bfSJoe Perches			if (WARN("TYPECAST_INT_CONSTANT",
66670972b8bfSJoe Perches				 "Unnecessary typecast of c90 int constant - '$cast$const' could be '$const$suffix'\n" . $herecurr) &&
66680972b8bfSJoe Perches			    $fix) {
6669938224b5SJoe Perches				$fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;
6670938224b5SJoe Perches			}
6671938224b5SJoe Perches		}
6672938224b5SJoe Perches
66738f53a9b8SJoe Perches# check for sizeof(&)
66748f53a9b8SJoe Perches		if ($line =~ /\bsizeof\s*\(\s*\&/) {
6675000d1cc1SJoe Perches			WARN("SIZEOF_ADDRESS",
6676000d1cc1SJoe Perches			     "sizeof(& should be avoided\n" . $herecurr);
66778f53a9b8SJoe Perches		}
66788f53a9b8SJoe Perches
667966c80b60SJoe Perches# check for sizeof without parenthesis
668066c80b60SJoe Perches		if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
6681d5e616fcSJoe Perches			if (WARN("SIZEOF_PARENTHESIS",
6682d5e616fcSJoe Perches				 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
6683d5e616fcSJoe Perches			    $fix) {
6684194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
6685d5e616fcSJoe Perches			}
668666c80b60SJoe Perches		}
668766c80b60SJoe Perches
668888982feaSJoe Perches# check for struct spinlock declarations
668988982feaSJoe Perches		if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) {
669088982feaSJoe Perches			WARN("USE_SPINLOCK_T",
669188982feaSJoe Perches			     "struct spinlock should be spinlock_t\n" . $herecurr);
669288982feaSJoe Perches		}
669388982feaSJoe Perches
6694a6962d72SJoe Perches# check for seq_printf uses that could be seq_puts
669506668727SJoe Perches		if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
6696a6962d72SJoe Perches			my $fmt = get_quoted_string($line, $rawline);
6697caac1d5fSHeba Aamer			$fmt =~ s/%%//g;
6698caac1d5fSHeba Aamer			if ($fmt !~ /%/) {
6699d5e616fcSJoe Perches				if (WARN("PREFER_SEQ_PUTS",
6700d5e616fcSJoe Perches					 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
6701d5e616fcSJoe Perches				    $fix) {
6702194f66fcSJoe Perches					$fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;
6703d5e616fcSJoe Perches				}
6704a6962d72SJoe Perches			}
6705a6962d72SJoe Perches		}
6706a6962d72SJoe Perches
67070b523769SJoe Perches# check for vsprintf extension %p<foo> misuses
67085b57980dSJoe Perches		if ($perl_version_ok &&
67090b523769SJoe Perches		    defined $stat &&
67100b523769SJoe Perches		    $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
67110b523769SJoe Perches		    $1 !~ /^_*volatile_*$/) {
6712e3c6bc95STobin C. Harding			my $stat_real;
6713e3c6bc95STobin C. Harding
67140b523769SJoe Perches			my $lc = $stat =~ tr@\n@@;
67150b523769SJoe Perches			$lc = $lc + $linenr;
67160b523769SJoe Perches		        for (my $count = $linenr; $count <= $lc; $count++) {
6717ffe07513SJoe Perches				my $specifier;
6718ffe07513SJoe Perches				my $extension;
67193bd32d6aSSakari Ailus				my $qualifier;
6720ffe07513SJoe Perches				my $bad_specifier = "";
67210b523769SJoe Perches				my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
67220b523769SJoe Perches				$fmt =~ s/%%//g;
6723e3c6bc95STobin C. Harding
67243bd32d6aSSakari Ailus				while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {
6725e3c6bc95STobin C. Harding					$specifier = $1;
6726e3c6bc95STobin C. Harding					$extension = $2;
67273bd32d6aSSakari Ailus					$qualifier = $3;
6728af612e43SSakari Ailus					if ($extension !~ /[4SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
67293bd32d6aSSakari Ailus					    ($extension eq "f" &&
6730af612e43SSakari Ailus					     defined $qualifier && $qualifier !~ /^w/) ||
6731af612e43SSakari Ailus					    ($extension eq "4" &&
6732af612e43SSakari Ailus					     defined $qualifier && $qualifier !~ /^cc/)) {
6733e3c6bc95STobin C. Harding						$bad_specifier = $specifier;
67340b523769SJoe Perches						last;
67350b523769SJoe Perches					}
6736e3c6bc95STobin C. Harding					if ($extension eq "x" && !defined($stat_real)) {
6737e3c6bc95STobin C. Harding						if (!defined($stat_real)) {
6738e3c6bc95STobin C. Harding							$stat_real = get_stat_real($linenr, $lc);
67390b523769SJoe Perches						}
6740e3c6bc95STobin C. Harding						WARN("VSPRINTF_SPECIFIER_PX",
6741e3c6bc95STobin C. Harding						     "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n");
6742e3c6bc95STobin C. Harding					}
6743e3c6bc95STobin C. Harding				}
6744e3c6bc95STobin C. Harding				if ($bad_specifier ne "") {
67452a9f9d85STobin C. Harding					my $stat_real = get_stat_real($linenr, $lc);
67461df7338aSSergey Senozhatsky					my $ext_type = "Invalid";
67471df7338aSSergey Senozhatsky					my $use = "";
6748e3c6bc95STobin C. Harding					if ($bad_specifier =~ /p[Ff]/) {
67491df7338aSSergey Senozhatsky						$use = " - use %pS instead";
6750e3c6bc95STobin C. Harding						$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
67511df7338aSSergey Senozhatsky					}
67522a9f9d85STobin C. Harding
67530b523769SJoe Perches					WARN("VSPRINTF_POINTER_EXTENSION",
6754e3c6bc95STobin C. Harding					     "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
6755e3c6bc95STobin C. Harding				}
67560b523769SJoe Perches			}
67570b523769SJoe Perches		}
67580b523769SJoe Perches
6759554e165cSAndy Whitcroft# Check for misused memsets
67605b57980dSJoe Perches		if ($perl_version_ok &&
6761d1fe9c09SJoe Perches		    defined $stat &&
67629e20a853SMateusz Kulikowski		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
6763554e165cSAndy Whitcroft
6764d7c76ba7SJoe Perches			my $ms_addr = $2;
6765d1fe9c09SJoe Perches			my $ms_val = $7;
6766d1fe9c09SJoe Perches			my $ms_size = $12;
6767d7c76ba7SJoe Perches
6768554e165cSAndy Whitcroft			if ($ms_size =~ /^(0x|)0$/i) {
6769554e165cSAndy Whitcroft				ERROR("MEMSET",
6770d7c76ba7SJoe Perches				      "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n");
6771554e165cSAndy Whitcroft			} elsif ($ms_size =~ /^(0x|)1$/i) {
6772554e165cSAndy Whitcroft				WARN("MEMSET",
6773d7c76ba7SJoe Perches				     "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n");
6774d7c76ba7SJoe Perches			}
6775d7c76ba7SJoe Perches		}
6776d7c76ba7SJoe Perches
677798a9bba5SJoe Perches# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
67785b57980dSJoe Perches#		if ($perl_version_ok &&
6779f333195dSJoe Perches#		    defined $stat &&
6780f333195dSJoe Perches#		    $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6781f333195dSJoe Perches#			if (WARN("PREFER_ETHER_ADDR_COPY",
6782f333195dSJoe Perches#				 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
6783f333195dSJoe Perches#			    $fix) {
6784f333195dSJoe Perches#				$fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
6785f333195dSJoe Perches#			}
6786f333195dSJoe Perches#		}
678798a9bba5SJoe Perches
6788b6117d17SMateusz Kulikowski# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
67895b57980dSJoe Perches#		if ($perl_version_ok &&
6790f333195dSJoe Perches#		    defined $stat &&
6791f333195dSJoe Perches#		    $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6792f333195dSJoe Perches#			WARN("PREFER_ETHER_ADDR_EQUAL",
6793f333195dSJoe Perches#			     "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
6794f333195dSJoe Perches#		}
6795b6117d17SMateusz Kulikowski
67968617cd09SMateusz Kulikowski# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
67978617cd09SMateusz Kulikowski# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
67985b57980dSJoe Perches#		if ($perl_version_ok &&
6799f333195dSJoe Perches#		    defined $stat &&
6800f333195dSJoe Perches#		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6801f333195dSJoe Perches#
6802f333195dSJoe Perches#			my $ms_val = $7;
6803f333195dSJoe Perches#
6804f333195dSJoe Perches#			if ($ms_val =~ /^(?:0x|)0+$/i) {
6805f333195dSJoe Perches#				if (WARN("PREFER_ETH_ZERO_ADDR",
6806f333195dSJoe Perches#					 "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
6807f333195dSJoe Perches#				    $fix) {
6808f333195dSJoe Perches#					$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
6809f333195dSJoe Perches#				}
6810f333195dSJoe Perches#			} elsif ($ms_val =~ /^(?:0xff|255)$/i) {
6811f333195dSJoe Perches#				if (WARN("PREFER_ETH_BROADCAST_ADDR",
6812f333195dSJoe Perches#					 "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
6813f333195dSJoe Perches#				    $fix) {
6814f333195dSJoe Perches#					$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
6815f333195dSJoe Perches#				}
6816f333195dSJoe Perches#			}
6817f333195dSJoe Perches#		}
68188617cd09SMateusz Kulikowski
68195dbdb2d8SJoe Perches# strlcpy uses that should likely be strscpy
68205dbdb2d8SJoe Perches		if ($line =~ /\bstrlcpy\s*\(/) {
68215dbdb2d8SJoe Perches			WARN("STRLCPY",
68225dbdb2d8SJoe Perches			     "Prefer strscpy over strlcpy - see: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw\@mail.gmail.com/\n" . $herecurr);
68235dbdb2d8SJoe Perches		}
68245dbdb2d8SJoe Perches
6825d7c76ba7SJoe Perches# typecasts on min/max could be min_t/max_t
68265b57980dSJoe Perches		if ($perl_version_ok &&
6827d1fe9c09SJoe Perches		    defined $stat &&
6828d7c76ba7SJoe Perches		    $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
6829d1fe9c09SJoe Perches			if (defined $2 || defined $7) {
6830d7c76ba7SJoe Perches				my $call = $1;
6831d7c76ba7SJoe Perches				my $cast1 = deparenthesize($2);
6832d7c76ba7SJoe Perches				my $arg1 = $3;
6833d1fe9c09SJoe Perches				my $cast2 = deparenthesize($7);
6834d1fe9c09SJoe Perches				my $arg2 = $8;
6835d7c76ba7SJoe Perches				my $cast;
6836d7c76ba7SJoe Perches
6837d1fe9c09SJoe Perches				if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) {
6838d7c76ba7SJoe Perches					$cast = "$cast1 or $cast2";
6839d7c76ba7SJoe Perches				} elsif ($cast1 ne "") {
6840d7c76ba7SJoe Perches					$cast = $cast1;
6841d7c76ba7SJoe Perches				} else {
6842d7c76ba7SJoe Perches					$cast = $cast2;
6843d7c76ba7SJoe Perches				}
6844d7c76ba7SJoe Perches				WARN("MINMAX",
6845d7c76ba7SJoe Perches				     "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n");
6846554e165cSAndy Whitcroft			}
6847554e165cSAndy Whitcroft		}
6848554e165cSAndy Whitcroft
68494a273195SJoe Perches# check usleep_range arguments
68505b57980dSJoe Perches		if ($perl_version_ok &&
68514a273195SJoe Perches		    defined $stat &&
68524a273195SJoe Perches		    $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
68534a273195SJoe Perches			my $min = $1;
68544a273195SJoe Perches			my $max = $7;
68554a273195SJoe Perches			if ($min eq $max) {
68564a273195SJoe Perches				WARN("USLEEP_RANGE",
6857458f69efSMauro Carvalho Chehab				     "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
68584a273195SJoe Perches			} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
68594a273195SJoe Perches				 $min > $max) {
68604a273195SJoe Perches				WARN("USLEEP_RANGE",
6861458f69efSMauro Carvalho Chehab				     "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
68624a273195SJoe Perches			}
68634a273195SJoe Perches		}
68644a273195SJoe Perches
6865823b794cSJoe Perches# check for naked sscanf
68665b57980dSJoe Perches		if ($perl_version_ok &&
6867823b794cSJoe Perches		    defined $stat &&
68686c8bd707SJoe Perches		    $line =~ /\bsscanf\b/ &&
6869823b794cSJoe Perches		    ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
6870823b794cSJoe Perches		     $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
6871823b794cSJoe Perches		     $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
6872823b794cSJoe Perches			my $lc = $stat =~ tr@\n@@;
6873823b794cSJoe Perches			$lc = $lc + $linenr;
68742a9f9d85STobin C. Harding			my $stat_real = get_stat_real($linenr, $lc);
6875823b794cSJoe Perches			WARN("NAKED_SSCANF",
6876823b794cSJoe Perches			     "unchecked sscanf return value\n" . "$here\n$stat_real\n");
6877823b794cSJoe Perches		}
6878823b794cSJoe Perches
6879afc819abSJoe Perches# check for simple sscanf that should be kstrto<foo>
68805b57980dSJoe Perches		if ($perl_version_ok &&
6881afc819abSJoe Perches		    defined $stat &&
6882afc819abSJoe Perches		    $line =~ /\bsscanf\b/) {
6883afc819abSJoe Perches			my $lc = $stat =~ tr@\n@@;
6884afc819abSJoe Perches			$lc = $lc + $linenr;
68852a9f9d85STobin C. Harding			my $stat_real = get_stat_real($linenr, $lc);
6886afc819abSJoe Perches			if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
6887afc819abSJoe Perches				my $format = $6;
6888afc819abSJoe Perches				my $count = $format =~ tr@%@%@;
6889afc819abSJoe Perches				if ($count == 1 &&
6890afc819abSJoe Perches				    $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {
6891afc819abSJoe Perches					WARN("SSCANF_TO_KSTRTO",
6892afc819abSJoe Perches					     "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n");
6893afc819abSJoe Perches				}
6894afc819abSJoe Perches			}
6895afc819abSJoe Perches		}
6896afc819abSJoe Perches
689770dc8a48SJoe Perches# check for new externs in .h files.
689870dc8a48SJoe Perches		if ($realfile =~ /\.h$/ &&
689970dc8a48SJoe Perches		    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
6900d1d85780SJoe Perches			if (CHK("AVOID_EXTERNS",
690170dc8a48SJoe Perches				"extern prototypes should be avoided in .h files\n" . $herecurr) &&
690270dc8a48SJoe Perches			    $fix) {
6903194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
690470dc8a48SJoe Perches			}
690570dc8a48SJoe Perches		}
690670dc8a48SJoe Perches
6907de7d4f0eSAndy Whitcroft# check for new externs in .c files.
6908171ae1a4SAndy Whitcroft		if ($realfile =~ /\.c$/ && defined $stat &&
6909c45dcabdSAndy Whitcroft		    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
6910171ae1a4SAndy Whitcroft		{
6911c45dcabdSAndy Whitcroft			my $function_name = $1;
6912c45dcabdSAndy Whitcroft			my $paren_space = $2;
6913171ae1a4SAndy Whitcroft
6914171ae1a4SAndy Whitcroft			my $s = $stat;
6915171ae1a4SAndy Whitcroft			if (defined $cond) {
6916171ae1a4SAndy Whitcroft				substr($s, 0, length($cond), '');
6917171ae1a4SAndy Whitcroft			}
6918d8b44b58SKees Cook			if ($s =~ /^\s*;/)
6919c45dcabdSAndy Whitcroft			{
6920000d1cc1SJoe Perches				WARN("AVOID_EXTERNS",
6921000d1cc1SJoe Perches				     "externs should be avoided in .c files\n" .  $herecurr);
6922de7d4f0eSAndy Whitcroft			}
6923de7d4f0eSAndy Whitcroft
6924171ae1a4SAndy Whitcroft			if ($paren_space =~ /\n/) {
6925000d1cc1SJoe Perches				WARN("FUNCTION_ARGUMENTS",
6926000d1cc1SJoe Perches				     "arguments for function declarations should follow identifier\n" . $herecurr);
6927171ae1a4SAndy Whitcroft			}
69289c9ba34eSAndy Whitcroft
69299c9ba34eSAndy Whitcroft		} elsif ($realfile =~ /\.c$/ && defined $stat &&
69309c9ba34eSAndy Whitcroft		    $stat =~ /^.\s*extern\s+/)
69319c9ba34eSAndy Whitcroft		{
6932000d1cc1SJoe Perches			WARN("AVOID_EXTERNS",
6933000d1cc1SJoe Perches			     "externs should be avoided in .c files\n" .  $herecurr);
6934171ae1a4SAndy Whitcroft		}
6935171ae1a4SAndy Whitcroft
6936a0ad7596SJoe Perches# check for function declarations that have arguments without identifier names
6937a0ad7596SJoe Perches		if (defined $stat &&
6938d8b44b58SKees Cook		    $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
6939d8b44b58SKees Cook		    $1 ne "void") {
6940d8b44b58SKees Cook			my $args = trim($1);
6941ca0d8929SJoe Perches			while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
6942ca0d8929SJoe Perches				my $arg = trim($1);
6943d8b44b58SKees Cook				if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
6944ca0d8929SJoe Perches					WARN("FUNCTION_ARGUMENTS",
6945ca0d8929SJoe Perches					     "function definition argument '$arg' should also have an identifier name\n" . $herecurr);
6946ca0d8929SJoe Perches				}
6947ca0d8929SJoe Perches			}
6948ca0d8929SJoe Perches		}
6949ca0d8929SJoe Perches
6950a0ad7596SJoe Perches# check for function definitions
69515b57980dSJoe Perches		if ($perl_version_ok &&
6952a0ad7596SJoe Perches		    defined $stat &&
6953a0ad7596SJoe Perches		    $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
6954a0ad7596SJoe Perches			$context_function = $1;
6955a0ad7596SJoe Perches
6956a0ad7596SJoe Perches# check for multiline function definition with misplaced open brace
6957a0ad7596SJoe Perches			my $ok = 0;
6958a0ad7596SJoe Perches			my $cnt = statement_rawlines($stat);
6959a0ad7596SJoe Perches			my $herectx = $here . "\n";
6960a0ad7596SJoe Perches			for (my $n = 0; $n < $cnt; $n++) {
6961a0ad7596SJoe Perches				my $rl = raw_line($linenr, $n);
6962a0ad7596SJoe Perches				$herectx .=  $rl . "\n";
6963a0ad7596SJoe Perches				$ok = 1 if ($rl =~ /^[ \+]\{/);
6964a0ad7596SJoe Perches				$ok = 1 if ($rl =~ /\{/ && $n == 0);
6965a0ad7596SJoe Perches				last if $rl =~ /^[ \+].*\{/;
6966a0ad7596SJoe Perches			}
6967a0ad7596SJoe Perches			if (!$ok) {
6968a0ad7596SJoe Perches				ERROR("OPEN_BRACE",
6969a0ad7596SJoe Perches				      "open brace '{' following function definitions go on the next line\n" . $herectx);
6970a0ad7596SJoe Perches			}
6971a0ad7596SJoe Perches		}
6972a0ad7596SJoe Perches
6973de7d4f0eSAndy Whitcroft# checks for new __setup's
6974de7d4f0eSAndy Whitcroft		if ($rawline =~ /\b__setup\("([^"]*)"/) {
6975de7d4f0eSAndy Whitcroft			my $name = $1;
6976de7d4f0eSAndy Whitcroft
6977de7d4f0eSAndy Whitcroft			if (!grep(/$name/, @setup_docs)) {
6978000d1cc1SJoe Perches				CHK("UNDOCUMENTED_SETUP",
69792581ac7cSTim Froidcoeur				    "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);
6980de7d4f0eSAndy Whitcroft			}
6981653d4876SAndy Whitcroft		}
69829c0ca6f9SAndy Whitcroft
6983e29a70f1SJoe Perches# check for pointless casting of alloc functions
6984e29a70f1SJoe Perches		if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
6985000d1cc1SJoe Perches			WARN("UNNECESSARY_CASTS",
6986000d1cc1SJoe Perches			     "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
69879c0ca6f9SAndy Whitcroft		}
698813214adfSAndy Whitcroft
6989a640d25cSJoe Perches# alloc style
6990a640d25cSJoe Perches# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
69915b57980dSJoe Perches		if ($perl_version_ok &&
6992e29a70f1SJoe Perches		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
6993a640d25cSJoe Perches			CHK("ALLOC_SIZEOF_STRUCT",
6994a640d25cSJoe Perches			    "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
6995a640d25cSJoe Perches		}
6996a640d25cSJoe Perches
699760a55369SJoe Perches# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
69985b57980dSJoe Perches		if ($perl_version_ok &&
69991b4a2ed4SJoe Perches		    defined $stat &&
70001b4a2ed4SJoe Perches		    $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
700160a55369SJoe Perches			my $oldfunc = $3;
700260a55369SJoe Perches			my $a1 = $4;
700360a55369SJoe Perches			my $a2 = $10;
700460a55369SJoe Perches			my $newfunc = "kmalloc_array";
700560a55369SJoe Perches			$newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
700660a55369SJoe Perches			my $r1 = $a1;
700760a55369SJoe Perches			my $r2 = $a2;
700860a55369SJoe Perches			if ($a1 =~ /^sizeof\s*\S/) {
700960a55369SJoe Perches				$r1 = $a2;
701060a55369SJoe Perches				$r2 = $a1;
701160a55369SJoe Perches			}
7012e367455aSJoe Perches			if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
7013e367455aSJoe Perches			    !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
70141b4a2ed4SJoe Perches				my $cnt = statement_rawlines($stat);
7015e3d95a2aSTobin C. Harding				my $herectx = get_stat_here($linenr, $cnt, $here);
7016e3d95a2aSTobin C. Harding
7017e367455aSJoe Perches				if (WARN("ALLOC_WITH_MULTIPLY",
70181b4a2ed4SJoe Perches					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
70191b4a2ed4SJoe Perches				    $cnt == 1 &&
7020e367455aSJoe Perches				    $fix) {
7021194f66fcSJoe Perches					$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;
702260a55369SJoe Perches				}
702360a55369SJoe Perches			}
702460a55369SJoe Perches		}
702560a55369SJoe Perches
7026972fdea2SJoe Perches# check for krealloc arg reuse
70275b57980dSJoe Perches		if ($perl_version_ok &&
70284cab63ceSJoe Perches		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
70294cab63ceSJoe Perches		    $1 eq $3) {
7030972fdea2SJoe Perches			WARN("KREALLOC_ARG_REUSE",
7031972fdea2SJoe Perches			     "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
7032972fdea2SJoe Perches		}
7033972fdea2SJoe Perches
70345ce59ae0SJoe Perches# check for alloc argument mismatch
70357e6cdd7fSChristophe JAILLET		if ($line =~ /\b((?:devm_)?(?:kcalloc|kmalloc_array))\s*\(\s*sizeof\b/) {
70365ce59ae0SJoe Perches			WARN("ALLOC_ARRAY_ARGS",
70375ce59ae0SJoe Perches			     "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
70385ce59ae0SJoe Perches		}
70395ce59ae0SJoe Perches
7040caf2a54fSJoe Perches# check for multiple semicolons
7041caf2a54fSJoe Perches		if ($line =~ /;\s*;\s*$/) {
7042d5e616fcSJoe Perches			if (WARN("ONE_SEMICOLON",
7043d5e616fcSJoe Perches				 "Statements terminations use 1 semicolon\n" . $herecurr) &&
7044d5e616fcSJoe Perches			    $fix) {
7045194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
7046d5e616fcSJoe Perches			}
7047d1e2ad07SJoe Perches		}
7048d1e2ad07SJoe Perches
7049cec3aaa5STomas Winkler# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
7050cec3aaa5STomas Winkler		if ($realfile !~ m@^include/uapi/@ &&
7051cec3aaa5STomas Winkler		    $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
70520ab90191SJoe Perches			my $ull = "";
70530ab90191SJoe Perches			$ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
70540ab90191SJoe Perches			if (CHK("BIT_MACRO",
70550ab90191SJoe Perches				"Prefer using the BIT$ull macro\n" . $herecurr) &&
70560ab90191SJoe Perches			    $fix) {
70570ab90191SJoe Perches				$fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/;
70580ab90191SJoe Perches			}
70590ab90191SJoe Perches		}
70600ab90191SJoe Perches
706150161266SJoe Perches# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
70623e89ad85SJerome Forissier		if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) {
706350161266SJoe Perches			WARN("IS_ENABLED_CONFIG",
70643e89ad85SJerome Forissier			     "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr);
706550161266SJoe Perches		}
706650161266SJoe Perches
70672d632745SJoe Perches# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
70683e89ad85SJerome Forissier		if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
70692d632745SJoe Perches			my $config = $1;
70702d632745SJoe Perches			if (WARN("PREFER_IS_ENABLED",
70713e89ad85SJerome Forissier				 "Prefer IS_ENABLED(<FOO>) to ${CONFIG_}<FOO> || ${CONFIG_}<FOO>_MODULE\n" . $herecurr) &&
70722d632745SJoe Perches			    $fix) {
70732d632745SJoe Perches				$fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
70742d632745SJoe Perches			}
70752d632745SJoe Perches		}
70762d632745SJoe Perches
7077f36d3eb8SJoe Perches# check for /* fallthrough */ like comment, prefer fallthrough;
7078f36d3eb8SJoe Perches		my @fallthroughs = (
7079f36d3eb8SJoe Perches			'fallthrough',
7080f36d3eb8SJoe Perches			'@fallthrough@',
7081f36d3eb8SJoe Perches			'lint -fallthrough[ \t]*',
7082f36d3eb8SJoe Perches			'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',
7083f36d3eb8SJoe Perches			'(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',
7084f36d3eb8SJoe Perches			'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
7085f36d3eb8SJoe Perches			'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
7086f36d3eb8SJoe Perches		    );
7087f36d3eb8SJoe Perches		if ($raw_comment ne '') {
7088f36d3eb8SJoe Perches			foreach my $ft (@fallthroughs) {
7089f36d3eb8SJoe Perches				if ($raw_comment =~ /$ft/) {
7090f36d3eb8SJoe Perches					my $msg_level = \&WARN;
7091f36d3eb8SJoe Perches					$msg_level = \&CHK if ($file);
7092f36d3eb8SJoe Perches					&{$msg_level}("PREFER_FALLTHROUGH",
7093f36d3eb8SJoe Perches						      "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr);
7094f36d3eb8SJoe Perches					last;
7095f36d3eb8SJoe Perches				}
7096f36d3eb8SJoe Perches			}
7097f36d3eb8SJoe Perches		}
7098f36d3eb8SJoe Perches
7099d1e2ad07SJoe Perches# check for switch/default statements without a break;
71005b57980dSJoe Perches		if ($perl_version_ok &&
7101d1e2ad07SJoe Perches		    defined $stat &&
7102d1e2ad07SJoe Perches		    $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
7103d1e2ad07SJoe Perches			my $cnt = statement_rawlines($stat);
7104e3d95a2aSTobin C. Harding			my $herectx = get_stat_here($linenr, $cnt, $here);
7105e3d95a2aSTobin C. Harding
7106d1e2ad07SJoe Perches			WARN("DEFAULT_NO_BREAK",
7107d1e2ad07SJoe Perches			     "switch default: should use break\n" . $herectx);
7108caf2a54fSJoe Perches		}
7109caf2a54fSJoe Perches
711013214adfSAndy Whitcroft# check for gcc specific __FUNCTION__
7111d5e616fcSJoe Perches		if ($line =~ /\b__FUNCTION__\b/) {
7112d5e616fcSJoe Perches			if (WARN("USE_FUNC",
7113d5e616fcSJoe Perches				 "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr) &&
7114d5e616fcSJoe Perches			    $fix) {
7115194f66fcSJoe Perches				$fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
7116d5e616fcSJoe Perches			}
711713214adfSAndy Whitcroft		}
7118773647a0SAndy Whitcroft
711962ec818fSJoe Perches# check for uses of __DATE__, __TIME__, __TIMESTAMP__
712062ec818fSJoe Perches		while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) {
712162ec818fSJoe Perches			ERROR("DATE_TIME",
712262ec818fSJoe Perches			      "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr);
712362ec818fSJoe Perches		}
712462ec818fSJoe Perches
71252c92488aSJoe Perches# check for use of yield()
71262c92488aSJoe Perches		if ($line =~ /\byield\s*\(\s*\)/) {
71272c92488aSJoe Perches			WARN("YIELD",
71282c92488aSJoe Perches			     "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n"  . $herecurr);
71292c92488aSJoe Perches		}
71302c92488aSJoe Perches
7131179f8f40SJoe Perches# check for comparisons against true and false
7132179f8f40SJoe Perches		if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {
7133179f8f40SJoe Perches			my $lead = $1;
7134179f8f40SJoe Perches			my $arg = $2;
7135179f8f40SJoe Perches			my $test = $3;
7136179f8f40SJoe Perches			my $otype = $4;
7137179f8f40SJoe Perches			my $trail = $5;
7138179f8f40SJoe Perches			my $op = "!";
7139179f8f40SJoe Perches
7140179f8f40SJoe Perches			($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i);
7141179f8f40SJoe Perches
7142179f8f40SJoe Perches			my $type = lc($otype);
7143179f8f40SJoe Perches			if ($type =~ /^(?:true|false)$/) {
7144179f8f40SJoe Perches				if (("$test" eq "==" && "$type" eq "true") ||
7145179f8f40SJoe Perches				    ("$test" eq "!=" && "$type" eq "false")) {
7146179f8f40SJoe Perches					$op = "";
7147179f8f40SJoe Perches				}
7148179f8f40SJoe Perches
7149179f8f40SJoe Perches				CHK("BOOL_COMPARISON",
7150179f8f40SJoe Perches				    "Using comparison to $otype is error prone\n" . $herecurr);
7151179f8f40SJoe Perches
7152179f8f40SJoe Perches## maybe suggesting a correct construct would better
7153179f8f40SJoe Perches##				    "Using comparison to $otype is error prone.  Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr);
7154179f8f40SJoe Perches
7155179f8f40SJoe Perches			}
7156179f8f40SJoe Perches		}
7157179f8f40SJoe Perches
71584882720bSThomas Gleixner# check for semaphores initialized locked
71594882720bSThomas Gleixner		if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
7160000d1cc1SJoe Perches			WARN("CONSIDER_COMPLETION",
7161000d1cc1SJoe Perches			     "consider using a completion\n" . $herecurr);
7162773647a0SAndy Whitcroft		}
71636712d858SJoe Perches
716467d0a075SJoe Perches# recommend kstrto* over simple_strto* and strict_strto*
716567d0a075SJoe Perches		if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
7166000d1cc1SJoe Perches			WARN("CONSIDER_KSTRTO",
716767d0a075SJoe Perches			     "$1 is obsolete, use k$3 instead\n" . $herecurr);
7168773647a0SAndy Whitcroft		}
71696712d858SJoe Perches
7170ae3ccc46SFabian Frederick# check for __initcall(), use device_initcall() explicitly or more appropriate function please
7171f3db6639SMichael Ellerman		if ($line =~ /^.\s*__initcall\s*\(/) {
7172000d1cc1SJoe Perches			WARN("USE_DEVICE_INITCALL",
7173ae3ccc46SFabian Frederick			     "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
7174f3db6639SMichael Ellerman		}
71756712d858SJoe Perches
71763d709ab5SPaul E. McKenney# check for spin_is_locked(), suggest lockdep instead
71773d709ab5SPaul E. McKenney		if ($line =~ /\bspin_is_locked\(/) {
71783d709ab5SPaul E. McKenney			WARN("USE_LOCKDEP",
71793d709ab5SPaul E. McKenney			     "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
71803d709ab5SPaul E. McKenney		}
71813d709ab5SPaul E. McKenney
71829189c7e7SJoe Perches# check for deprecated apis
71839189c7e7SJoe Perches		if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
71849189c7e7SJoe Perches			my $deprecated_api = $1;
71859189c7e7SJoe Perches			my $new_api = $deprecated_apis{$deprecated_api};
71869189c7e7SJoe Perches			WARN("DEPRECATED_API",
71879189c7e7SJoe Perches			     "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
71889189c7e7SJoe Perches		}
71899189c7e7SJoe Perches
71900f3c5aabSJoe Perches# check for various structs that are normally const (ops, kgdb, device_tree)
7191d9190e4eSJoe Perches# and avoid what seem like struct definitions 'struct foo {'
7192ced69da1SQuentin Monnet		if (defined($const_structs) &&
7193ced69da1SQuentin Monnet		    $line !~ /\bconst\b/ &&
7194d9190e4eSJoe Perches		    $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
7195000d1cc1SJoe Perches			WARN("CONST_STRUCT",
7196d9190e4eSJoe Perches			     "struct $1 should normally be const\n" . $herecurr);
71972b6db5cbSAndy Whitcroft		}
7198773647a0SAndy Whitcroft
7199773647a0SAndy Whitcroft# use of NR_CPUS is usually wrong
7200773647a0SAndy Whitcroft# ignore definitions of NR_CPUS and usage to define arrays as likely right
720135cdcbfcSPeng Wang# ignore designated initializers using NR_CPUS
7202773647a0SAndy Whitcroft		if ($line =~ /\bNR_CPUS\b/ &&
7203c45dcabdSAndy Whitcroft		    $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
7204c45dcabdSAndy Whitcroft		    $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
7205171ae1a4SAndy Whitcroft		    $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
7206171ae1a4SAndy Whitcroft		    $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
720735cdcbfcSPeng Wang		    $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/ &&
720835cdcbfcSPeng Wang		    $line !~ /^.\s*\.\w+\s*=\s*.*\bNR_CPUS\b/)
7209773647a0SAndy Whitcroft		{
7210000d1cc1SJoe Perches			WARN("NR_CPUS",
7211000d1cc1SJoe Perches			     "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
7212773647a0SAndy Whitcroft		}
72139c9ba34eSAndy Whitcroft
721452ea8506SJoe Perches# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
721552ea8506SJoe Perches		if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
721652ea8506SJoe Perches			ERROR("DEFINE_ARCH_HAS",
721752ea8506SJoe Perches			      "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
721852ea8506SJoe Perches		}
721952ea8506SJoe Perches
7220acd9362cSJoe Perches# likely/unlikely comparisons similar to "(likely(foo) > 0)"
72215b57980dSJoe Perches		if ($perl_version_ok &&
7222acd9362cSJoe Perches		    $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
7223acd9362cSJoe Perches			WARN("LIKELY_MISUSE",
7224acd9362cSJoe Perches			     "Using $1 should generally have parentheses around the comparison\n" . $herecurr);
7225acd9362cSJoe Perches		}
7226acd9362cSJoe Perches
7227fbe74541SJoe Perches# return sysfs_emit(foo, fmt, ...) fmt without newline
7228fbe74541SJoe Perches		if ($line =~ /\breturn\s+sysfs_emit\s*\(\s*$FuncArg\s*,\s*($String)/ &&
7229fbe74541SJoe Perches		    substr($rawline, $-[6], $+[6] - $-[6]) !~ /\\n"$/) {
7230fbe74541SJoe Perches			my $offset = $+[6] - 1;
7231fbe74541SJoe Perches			if (WARN("SYSFS_EMIT",
7232fbe74541SJoe Perches				 "return sysfs_emit(...) formats should include a terminating newline\n" . $herecurr) &&
7233fbe74541SJoe Perches			    $fix) {
7234fbe74541SJoe Perches				substr($fixed[$fixlinenr], $offset, 0) = '\\n';
7235fbe74541SJoe Perches			}
7236fbe74541SJoe Perches		}
7237fbe74541SJoe Perches
7238de3f186fSDenis Efremov# nested likely/unlikely calls
7239de3f186fSDenis Efremov		if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
7240de3f186fSDenis Efremov			WARN("LIKELY_MISUSE",
7241de3f186fSDenis Efremov			     "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
7242de3f186fSDenis Efremov		}
7243de3f186fSDenis Efremov
7244691d77b6SAndy Whitcroft# whine mightly about in_atomic
7245691d77b6SAndy Whitcroft		if ($line =~ /\bin_atomic\s*\(/) {
7246691d77b6SAndy Whitcroft			if ($realfile =~ m@^drivers/@) {
7247000d1cc1SJoe Perches				ERROR("IN_ATOMIC",
7248000d1cc1SJoe Perches				      "do not use in_atomic in drivers\n" . $herecurr);
7249f4a87736SAndy Whitcroft			} elsif ($realfile !~ m@^kernel/@) {
7250000d1cc1SJoe Perches				WARN("IN_ATOMIC",
7251000d1cc1SJoe Perches				     "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
7252691d77b6SAndy Whitcroft			}
7253691d77b6SAndy Whitcroft		}
72541704f47bSPeter Zijlstra
72551704f47bSPeter Zijlstra# check for lockdep_set_novalidate_class
72561704f47bSPeter Zijlstra		if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
72571704f47bSPeter Zijlstra		    $line =~ /__lockdep_no_validate__\s*\)/ ) {
72581704f47bSPeter Zijlstra			if ($realfile !~ m@^kernel/lockdep@ &&
72591704f47bSPeter Zijlstra			    $realfile !~ m@^include/linux/lockdep@ &&
72601704f47bSPeter Zijlstra			    $realfile !~ m@^drivers/base/core@) {
7261000d1cc1SJoe Perches				ERROR("LOCKDEP",
7262000d1cc1SJoe Perches				      "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
72631704f47bSPeter Zijlstra			}
72641704f47bSPeter Zijlstra		}
726588f8831cSDave Jones
7266b392c64fSJoe Perches		if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ ||
7267b392c64fSJoe Perches		    $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) {
7268000d1cc1SJoe Perches			WARN("EXPORTED_WORLD_WRITABLE",
7269000d1cc1SJoe Perches			     "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
727088f8831cSDave Jones		}
72712435880fSJoe Perches
727200180468SJoe Perches# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
727300180468SJoe Perches# and whether or not function naming is typical and if
727400180468SJoe Perches# DEVICE_ATTR permissions uses are unusual too
72755b57980dSJoe Perches		if ($perl_version_ok &&
727600180468SJoe Perches		    defined $stat &&
727700180468SJoe Perches		    $stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
727800180468SJoe Perches			my $var = $1;
727900180468SJoe Perches			my $perms = $2;
728000180468SJoe Perches			my $show = $3;
728100180468SJoe Perches			my $store = $4;
728200180468SJoe Perches			my $octal_perms = perms_to_octal($perms);
728300180468SJoe Perches			if ($show =~ /^${var}_show$/ &&
728400180468SJoe Perches			    $store =~ /^${var}_store$/ &&
728500180468SJoe Perches			    $octal_perms eq "0644") {
728600180468SJoe Perches				if (WARN("DEVICE_ATTR_RW",
728700180468SJoe Perches					 "Use DEVICE_ATTR_RW\n" . $herecurr) &&
728800180468SJoe Perches				    $fix) {
728900180468SJoe Perches					$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
729000180468SJoe Perches				}
729100180468SJoe Perches			} elsif ($show =~ /^${var}_show$/ &&
729200180468SJoe Perches				 $store =~ /^NULL$/ &&
729300180468SJoe Perches				 $octal_perms eq "0444") {
729400180468SJoe Perches				if (WARN("DEVICE_ATTR_RO",
729500180468SJoe Perches					 "Use DEVICE_ATTR_RO\n" . $herecurr) &&
729600180468SJoe Perches				    $fix) {
729700180468SJoe Perches					$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
729800180468SJoe Perches				}
729900180468SJoe Perches			} elsif ($show =~ /^NULL$/ &&
730000180468SJoe Perches				 $store =~ /^${var}_store$/ &&
730100180468SJoe Perches				 $octal_perms eq "0200") {
730200180468SJoe Perches				if (WARN("DEVICE_ATTR_WO",
730300180468SJoe Perches					 "Use DEVICE_ATTR_WO\n" . $herecurr) &&
730400180468SJoe Perches				    $fix) {
730500180468SJoe Perches					$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
730600180468SJoe Perches				}
730700180468SJoe Perches			} elsif ($octal_perms eq "0644" ||
730800180468SJoe Perches				 $octal_perms eq "0444" ||
730900180468SJoe Perches				 $octal_perms eq "0200") {
731000180468SJoe Perches				my $newshow = "$show";
731100180468SJoe Perches				$newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
731200180468SJoe Perches				my $newstore = $store;
731300180468SJoe Perches				$newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
731400180468SJoe Perches				my $rename = "";
731500180468SJoe Perches				if ($show ne $newshow) {
731600180468SJoe Perches					$rename .= " '$show' to '$newshow'";
731700180468SJoe Perches				}
731800180468SJoe Perches				if ($store ne $newstore) {
731900180468SJoe Perches					$rename .= " '$store' to '$newstore'";
732000180468SJoe Perches				}
732100180468SJoe Perches				WARN("DEVICE_ATTR_FUNCTIONS",
732200180468SJoe Perches				     "Consider renaming function(s)$rename\n" . $herecurr);
732300180468SJoe Perches			} else {
732400180468SJoe Perches				WARN("DEVICE_ATTR_PERMS",
732500180468SJoe Perches				     "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr);
732600180468SJoe Perches			}
732700180468SJoe Perches		}
732800180468SJoe Perches
7329515a235eSJoe Perches# Mode permission misuses where it seems decimal should be octal
7330515a235eSJoe Perches# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
733173121534SJoe Perches# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
733273121534SJoe Perches#   specific definition of not visible in sysfs.
733373121534SJoe Perches# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
733473121534SJoe Perches#   use the default permissions
73355b57980dSJoe Perches		if ($perl_version_ok &&
7336459cf0aeSJoe Perches		    defined $stat &&
7337515a235eSJoe Perches		    $line =~ /$mode_perms_search/) {
73382435880fSJoe Perches			foreach my $entry (@mode_permission_funcs) {
73392435880fSJoe Perches				my $func = $entry->[0];
73402435880fSJoe Perches				my $arg_pos = $entry->[1];
73412435880fSJoe Perches
7342459cf0aeSJoe Perches				my $lc = $stat =~ tr@\n@@;
7343459cf0aeSJoe Perches				$lc = $lc + $linenr;
73442a9f9d85STobin C. Harding				my $stat_real = get_stat_real($linenr, $lc);
7345459cf0aeSJoe Perches
73462435880fSJoe Perches				my $skip_args = "";
73472435880fSJoe Perches				if ($arg_pos > 1) {
73482435880fSJoe Perches					$arg_pos--;
73492435880fSJoe Perches					$skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
73502435880fSJoe Perches				}
7351f90774e1SJoe Perches				my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
7352459cf0aeSJoe Perches				if ($stat =~ /$test/) {
73532435880fSJoe Perches					my $val = $1;
73542435880fSJoe Perches					$val = $6 if ($skip_args ne "");
735573121534SJoe Perches					if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
735673121534SJoe Perches					    (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
735773121534SJoe Perches					     ($val =~ /^$Octal$/ && length($val) ne 4))) {
73582435880fSJoe Perches						ERROR("NON_OCTAL_PERMISSIONS",
7359459cf0aeSJoe Perches						      "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
7360f90774e1SJoe Perches					}
7361f90774e1SJoe Perches					if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
7362c0a5c898SJoe Perches						ERROR("EXPORTED_WORLD_WRITABLE",
7363459cf0aeSJoe Perches						      "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
73642435880fSJoe Perches					}
7365459cf0aeSJoe Perches				}
7366459cf0aeSJoe Perches			}
7367459cf0aeSJoe Perches		}
7368459cf0aeSJoe Perches
7369459cf0aeSJoe Perches# check for uses of S_<PERMS> that could be octal for readability
7370bc22d9a7SJoe Perches		while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
737100180468SJoe Perches			my $oval = $1;
737200180468SJoe Perches			my $octal = perms_to_octal($oval);
7373f90774e1SJoe Perches			if (WARN("SYMBOLIC_PERMS",
7374459cf0aeSJoe Perches				 "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
7375f90774e1SJoe Perches			    $fix) {
737600180468SJoe Perches				$fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
73772435880fSJoe Perches			}
737813214adfSAndy Whitcroft		}
73795a6d20ceSBjorn Andersson
73805a6d20ceSBjorn Andersson# validate content of MODULE_LICENSE against list from include/linux/module.h
73815a6d20ceSBjorn Andersson		if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
73825a6d20ceSBjorn Andersson			my $extracted_string = get_quoted_string($line, $rawline);
73835a6d20ceSBjorn Andersson			my $valid_licenses = qr{
73845a6d20ceSBjorn Andersson						GPL|
73855a6d20ceSBjorn Andersson						GPL\ v2|
73865a6d20ceSBjorn Andersson						GPL\ and\ additional\ rights|
73875a6d20ceSBjorn Andersson						Dual\ BSD/GPL|
73885a6d20ceSBjorn Andersson						Dual\ MIT/GPL|
73895a6d20ceSBjorn Andersson						Dual\ MPL/GPL|
73905a6d20ceSBjorn Andersson						Proprietary
73915a6d20ceSBjorn Andersson					}x;
73925a6d20ceSBjorn Andersson			if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) {
73935a6d20ceSBjorn Andersson				WARN("MODULE_LICENSE",
73945a6d20ceSBjorn Andersson				     "unknown module license " . $extracted_string . "\n" . $herecurr);
73955a6d20ceSBjorn Andersson			}
73965a6d20ceSBjorn Andersson		}
73976a8d76cbSMatteo Croce
73986a8d76cbSMatteo Croce# check for sysctl duplicate constants
73996a8d76cbSMatteo Croce		if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
74006a8d76cbSMatteo Croce			WARN("DUPLICATED_SYSCTL_CONST",
74016a8d76cbSMatteo Croce				"duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
74026a8d76cbSMatteo Croce		}
7403515a235eSJoe Perches	}
740413214adfSAndy Whitcroft
740513214adfSAndy Whitcroft	# If we have no input at all, then there is nothing to report on
740613214adfSAndy Whitcroft	# so just keep quiet.
740713214adfSAndy Whitcroft	if ($#rawlines == -1) {
740813214adfSAndy Whitcroft		exit(0);
74090a920b5bSAndy Whitcroft	}
74100a920b5bSAndy Whitcroft
74118905a67cSAndy Whitcroft	# In mailback mode only produce a report in the negative, for
74128905a67cSAndy Whitcroft	# things that appear to be patches.
74138905a67cSAndy Whitcroft	if ($mailback && ($clean == 1 || !$is_patch)) {
74148905a67cSAndy Whitcroft		exit(0);
74158905a67cSAndy Whitcroft	}
74168905a67cSAndy Whitcroft
7417e73d2715SDwaipayan Ray	# This is not a patch, and we are in 'no-patch' mode so
74188905a67cSAndy Whitcroft	# just keep quiet.
74198905a67cSAndy Whitcroft	if (!$chk_patch && !$is_patch) {
74208905a67cSAndy Whitcroft		exit(0);
74218905a67cSAndy Whitcroft	}
74228905a67cSAndy Whitcroft
7423a08ffbefSStafford Horne	if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
7424000d1cc1SJoe Perches		ERROR("NOT_UNIFIED_DIFF",
7425000d1cc1SJoe Perches		      "Does not appear to be a unified-diff format patch\n");
74260a920b5bSAndy Whitcroft	}
7427cd261496SGeert Uytterhoeven	if ($is_patch && $has_commit_log && $chk_signoff) {
7428cd261496SGeert Uytterhoeven		if ($signoff == 0) {
7429000d1cc1SJoe Perches			ERROR("MISSING_SIGN_OFF",
7430000d1cc1SJoe Perches			      "Missing Signed-off-by: line(s)\n");
743148ca2d8aSDwaipayan Ray		} elsif ($authorsignoff != 1) {
743248ca2d8aSDwaipayan Ray			# authorsignoff values:
743348ca2d8aSDwaipayan Ray			# 0 -> missing sign off
743448ca2d8aSDwaipayan Ray			# 1 -> sign off identical
743548ca2d8aSDwaipayan Ray			# 2 -> names and addresses match, comments mismatch
743648ca2d8aSDwaipayan Ray			# 3 -> addresses match, names different
743748ca2d8aSDwaipayan Ray			# 4 -> names match, addresses different
743848ca2d8aSDwaipayan Ray			# 5 -> names match, addresses excluding subaddress details (refer RFC 5233) match
743948ca2d8aSDwaipayan Ray
744048ca2d8aSDwaipayan Ray			my $sob_msg = "'From: $author' != 'Signed-off-by: $author_sob'";
744148ca2d8aSDwaipayan Ray
744248ca2d8aSDwaipayan Ray			if ($authorsignoff == 0) {
744348ca2d8aSDwaipayan Ray				ERROR("NO_AUTHOR_SIGN_OFF",
7444cd261496SGeert Uytterhoeven				      "Missing Signed-off-by: line by nominal patch author '$author'\n");
744548ca2d8aSDwaipayan Ray			} elsif ($authorsignoff == 2) {
744648ca2d8aSDwaipayan Ray				CHK("FROM_SIGN_OFF_MISMATCH",
744748ca2d8aSDwaipayan Ray				    "From:/Signed-off-by: email comments mismatch: $sob_msg\n");
744848ca2d8aSDwaipayan Ray			} elsif ($authorsignoff == 3) {
744948ca2d8aSDwaipayan Ray				WARN("FROM_SIGN_OFF_MISMATCH",
745048ca2d8aSDwaipayan Ray				     "From:/Signed-off-by: email name mismatch: $sob_msg\n");
745148ca2d8aSDwaipayan Ray			} elsif ($authorsignoff == 4) {
745248ca2d8aSDwaipayan Ray				WARN("FROM_SIGN_OFF_MISMATCH",
745348ca2d8aSDwaipayan Ray				     "From:/Signed-off-by: email address mismatch: $sob_msg\n");
745448ca2d8aSDwaipayan Ray			} elsif ($authorsignoff == 5) {
745548ca2d8aSDwaipayan Ray				WARN("FROM_SIGN_OFF_MISMATCH",
745648ca2d8aSDwaipayan Ray				     "From:/Signed-off-by: email subaddress mismatch: $sob_msg\n");
745748ca2d8aSDwaipayan Ray			}
7458cd261496SGeert Uytterhoeven		}
74590a920b5bSAndy Whitcroft	}
74600a920b5bSAndy Whitcroft
7461f0a594c1SAndy Whitcroft	print report_dump();
746213214adfSAndy Whitcroft	if ($summary && !($clean == 1 && $quiet == 1)) {
746313214adfSAndy Whitcroft		print "$filename " if ($summary_file);
74646c72ffaaSAndy Whitcroft		print "total: $cnt_error errors, $cnt_warn warnings, " .
74656c72ffaaSAndy Whitcroft			(($check)? "$cnt_chk checks, " : "") .
74666c72ffaaSAndy Whitcroft			"$cnt_lines lines checked\n";
74676c72ffaaSAndy Whitcroft	}
74688905a67cSAndy Whitcroft
7469d2c0a235SAndy Whitcroft	if ($quiet == 0) {
7470ef212196SJoe Perches		# If there were any defects found and not already fixing them
7471ef212196SJoe Perches		if (!$clean and !$fix) {
7472ef212196SJoe Perches			print << "EOM"
7473ef212196SJoe Perches
7474ef212196SJoe PerchesNOTE: For some of the reported defects, checkpatch may be able to
7475ef212196SJoe Perches      mechanically convert to the typical style using --fix or --fix-inplace.
7476ef212196SJoe PerchesEOM
7477ef212196SJoe Perches		}
7478d2c0a235SAndy Whitcroft		# If there were whitespace errors which cleanpatch can fix
7479d2c0a235SAndy Whitcroft		# then suggest that.
7480d2c0a235SAndy Whitcroft		if ($rpt_cleaners) {
7481b0781216SMike Frysinger			$rpt_cleaners = 0;
7482d8469f16SJoe Perches			print << "EOM"
7483d8469f16SJoe Perches
7484d8469f16SJoe PerchesNOTE: Whitespace errors detected.
7485d8469f16SJoe Perches      You may wish to use scripts/cleanpatch or scripts/cleanfile
7486d8469f16SJoe PerchesEOM
7487d2c0a235SAndy Whitcroft		}
7488d2c0a235SAndy Whitcroft	}
7489d2c0a235SAndy Whitcroft
7490d752fcc8SJoe Perches	if ($clean == 0 && $fix &&
7491d752fcc8SJoe Perches	    ("@rawlines" ne "@fixed" ||
7492d752fcc8SJoe Perches	     $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
74939624b8d6SJoe Perches		my $newfile = $filename;
74949624b8d6SJoe Perches		$newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
74953705ce5bSJoe Perches		my $linecount = 0;
74963705ce5bSJoe Perches		my $f;
74973705ce5bSJoe Perches
7498d752fcc8SJoe Perches		@fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
7499d752fcc8SJoe Perches
75003705ce5bSJoe Perches		open($f, '>', $newfile)
75013705ce5bSJoe Perches		    or die "$P: Can't open $newfile for write\n";
75023705ce5bSJoe Perches		foreach my $fixed_line (@fixed) {
75033705ce5bSJoe Perches			$linecount++;
75043705ce5bSJoe Perches			if ($file) {
75053705ce5bSJoe Perches				if ($linecount > 3) {
75063705ce5bSJoe Perches					$fixed_line =~ s/^\+//;
75073705ce5bSJoe Perches					print $f $fixed_line . "\n";
75083705ce5bSJoe Perches				}
75093705ce5bSJoe Perches			} else {
75103705ce5bSJoe Perches				print $f $fixed_line . "\n";
75113705ce5bSJoe Perches			}
75123705ce5bSJoe Perches		}
75133705ce5bSJoe Perches		close($f);
75143705ce5bSJoe Perches
75153705ce5bSJoe Perches		if (!$quiet) {
75163705ce5bSJoe Perches			print << "EOM";
7517d8469f16SJoe Perches
75183705ce5bSJoe PerchesWrote EXPERIMENTAL --fix correction(s) to '$newfile'
75193705ce5bSJoe Perches
75203705ce5bSJoe PerchesDo _NOT_ trust the results written to this file.
75213705ce5bSJoe PerchesDo _NOT_ submit these changes without inspecting them for correctness.
75223705ce5bSJoe Perches
75233705ce5bSJoe PerchesThis EXPERIMENTAL file is simply a convenience to help rewrite patches.
75243705ce5bSJoe PerchesNo warranties, expressed or implied...
75253705ce5bSJoe PerchesEOM
75263705ce5bSJoe Perches		}
75273705ce5bSJoe Perches	}
75283705ce5bSJoe Perches
7529d8469f16SJoe Perches	if ($quiet == 0) {
7530d8469f16SJoe Perches		print "\n";
7531d8469f16SJoe Perches		if ($clean == 1) {
7532d8469f16SJoe Perches			print "$vname has no obvious style problems and is ready for submission.\n";
7533d8469f16SJoe Perches		} else {
7534d8469f16SJoe Perches			print "$vname has style problems, please review.\n";
75350a920b5bSAndy Whitcroft		}
75360a920b5bSAndy Whitcroft	}
75370a920b5bSAndy Whitcroft	return $clean;
75380a920b5bSAndy Whitcroft}
7539