xref: /OK3568_Linux_fs/kernel/scripts/checkpatch.pl (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env perl
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# (c) 2001, Dave Jones. (the file handling bit)
5*4882a593Smuzhiyun# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
6*4882a593Smuzhiyun# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
7*4882a593Smuzhiyun# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
8*4882a593Smuzhiyun# (c) 2010-2018 Joe Perches <joe@perches.com>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyunuse strict;
11*4882a593Smuzhiyunuse warnings;
12*4882a593Smuzhiyunuse POSIX;
13*4882a593Smuzhiyunuse File::Basename;
14*4882a593Smuzhiyunuse Cwd 'abs_path';
15*4882a593Smuzhiyunuse Term::ANSIColor qw(:constants);
16*4882a593Smuzhiyunuse Encode qw(decode encode);
17*4882a593Smuzhiyun
18*4882a593Smuzhiyunmy $P = $0;
19*4882a593Smuzhiyunmy $D = dirname(abs_path($P));
20*4882a593Smuzhiyun
21*4882a593Smuzhiyunmy $V = '0.32';
22*4882a593Smuzhiyun
23*4882a593Smuzhiyunuse Getopt::Long qw(:config no_auto_abbrev);
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunmy $quiet = 0;
26*4882a593Smuzhiyunmy $tree = 1;
27*4882a593Smuzhiyunmy $chk_signoff = 1;
28*4882a593Smuzhiyunmy $chk_patch = 1;
29*4882a593Smuzhiyunmy $tst_only;
30*4882a593Smuzhiyunmy $emacs = 0;
31*4882a593Smuzhiyunmy $terse = 0;
32*4882a593Smuzhiyunmy $showfile = 0;
33*4882a593Smuzhiyunmy $file = 0;
34*4882a593Smuzhiyunmy $git = 0;
35*4882a593Smuzhiyunmy %git_commits = ();
36*4882a593Smuzhiyunmy $check = 0;
37*4882a593Smuzhiyunmy $check_orig = 0;
38*4882a593Smuzhiyunmy $summary = 1;
39*4882a593Smuzhiyunmy $mailback = 0;
40*4882a593Smuzhiyunmy $summary_file = 0;
41*4882a593Smuzhiyunmy $show_types = 0;
42*4882a593Smuzhiyunmy $list_types = 0;
43*4882a593Smuzhiyunmy $fix = 0;
44*4882a593Smuzhiyunmy $fix_inplace = 0;
45*4882a593Smuzhiyunmy $root;
46*4882a593Smuzhiyunmy $gitroot = $ENV{'GIT_DIR'};
47*4882a593Smuzhiyun$gitroot = ".git" if !defined($gitroot);
48*4882a593Smuzhiyunmy %debug;
49*4882a593Smuzhiyunmy %camelcase = ();
50*4882a593Smuzhiyunmy %use_type = ();
51*4882a593Smuzhiyunmy @use = ();
52*4882a593Smuzhiyunmy %ignore_type = ();
53*4882a593Smuzhiyunmy @ignore = ();
54*4882a593Smuzhiyunmy $help = 0;
55*4882a593Smuzhiyunmy $configuration_file = ".checkpatch.conf";
56*4882a593Smuzhiyunmy $max_line_length = 100;
57*4882a593Smuzhiyunmy $ignore_perl_version = 0;
58*4882a593Smuzhiyunmy $minimum_perl_version = 5.10.0;
59*4882a593Smuzhiyunmy $min_conf_desc_length = 4;
60*4882a593Smuzhiyunmy $spelling_file = "$D/spelling.txt";
61*4882a593Smuzhiyunmy $codespell = 0;
62*4882a593Smuzhiyunmy $codespellfile = "/usr/share/codespell/dictionary.txt";
63*4882a593Smuzhiyunmy $conststructsfile = "$D/const_structs.checkpatch";
64*4882a593Smuzhiyunmy $typedefsfile;
65*4882a593Smuzhiyunmy $color = "auto";
66*4882a593Smuzhiyunmy $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
67*4882a593Smuzhiyun# git output parsing needs US English output, so first set backtick child process LANGUAGE
68*4882a593Smuzhiyunmy $git_command ='export LANGUAGE=en_US.UTF-8; git';
69*4882a593Smuzhiyunmy $tabsize = 8;
70*4882a593Smuzhiyunmy ${CONFIG_} = "CONFIG_";
71*4882a593Smuzhiyun
72*4882a593Smuzhiyunsub help {
73*4882a593Smuzhiyun	my ($exitcode) = @_;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun	print << "EOM";
76*4882a593SmuzhiyunUsage: $P [OPTION]... [FILE]...
77*4882a593SmuzhiyunVersion: $V
78*4882a593Smuzhiyun
79*4882a593SmuzhiyunOptions:
80*4882a593Smuzhiyun  -q, --quiet                quiet
81*4882a593Smuzhiyun  --no-tree                  run without a kernel tree
82*4882a593Smuzhiyun  --no-signoff               do not check for 'Signed-off-by' line
83*4882a593Smuzhiyun  --patch                    treat FILE as patchfile (default)
84*4882a593Smuzhiyun  --emacs                    emacs compile window format
85*4882a593Smuzhiyun  --terse                    one line per report
86*4882a593Smuzhiyun  --showfile                 emit diffed file position, not input file position
87*4882a593Smuzhiyun  -g, --git                  treat FILE as a single commit or git revision range
88*4882a593Smuzhiyun                             single git commit with:
89*4882a593Smuzhiyun                               <rev>
90*4882a593Smuzhiyun                               <rev>^
91*4882a593Smuzhiyun                               <rev>~n
92*4882a593Smuzhiyun                             multiple git commits with:
93*4882a593Smuzhiyun                               <rev1>..<rev2>
94*4882a593Smuzhiyun                               <rev1>...<rev2>
95*4882a593Smuzhiyun                               <rev>-<count>
96*4882a593Smuzhiyun                             git merges are ignored
97*4882a593Smuzhiyun  -f, --file                 treat FILE as regular source file
98*4882a593Smuzhiyun  --subjective, --strict     enable more subjective tests
99*4882a593Smuzhiyun  --list-types               list the possible message types
100*4882a593Smuzhiyun  --types TYPE(,TYPE2...)    show only these comma separated message types
101*4882a593Smuzhiyun  --ignore TYPE(,TYPE2...)   ignore various comma separated message types
102*4882a593Smuzhiyun  --show-types               show the specific message type in the output
103*4882a593Smuzhiyun  --max-line-length=n        set the maximum line length, (default $max_line_length)
104*4882a593Smuzhiyun                             if exceeded, warn on patches
105*4882a593Smuzhiyun                             requires --strict for use with --file
106*4882a593Smuzhiyun  --min-conf-desc-length=n   set the min description length, if shorter, warn
107*4882a593Smuzhiyun  --tab-size=n               set the number of spaces for tab (default $tabsize)
108*4882a593Smuzhiyun  --root=PATH                PATH to the kernel tree root
109*4882a593Smuzhiyun  --no-summary               suppress the per-file summary
110*4882a593Smuzhiyun  --mailback                 only produce a report in case of warnings/errors
111*4882a593Smuzhiyun  --summary-file             include the filename in summary
112*4882a593Smuzhiyun  --debug KEY=[0|1]          turn on/off debugging of KEY, where KEY is one of
113*4882a593Smuzhiyun                             'values', 'possible', 'type', and 'attr' (default
114*4882a593Smuzhiyun                             is all off)
115*4882a593Smuzhiyun  --test-only=WORD           report only warnings/errors containing WORD
116*4882a593Smuzhiyun                             literally
117*4882a593Smuzhiyun  --fix                      EXPERIMENTAL - may create horrible results
118*4882a593Smuzhiyun                             If correctable single-line errors exist, create
119*4882a593Smuzhiyun                             "<inputfile>.EXPERIMENTAL-checkpatch-fixes"
120*4882a593Smuzhiyun                             with potential errors corrected to the preferred
121*4882a593Smuzhiyun                             checkpatch style
122*4882a593Smuzhiyun  --fix-inplace              EXPERIMENTAL - may create horrible results
123*4882a593Smuzhiyun                             Is the same as --fix, but overwrites the input
124*4882a593Smuzhiyun                             file.  It's your fault if there's no backup or git
125*4882a593Smuzhiyun  --ignore-perl-version      override checking of perl version.  expect
126*4882a593Smuzhiyun                             runtime errors.
127*4882a593Smuzhiyun  --codespell                Use the codespell dictionary for spelling/typos
128*4882a593Smuzhiyun                             (default:/usr/share/codespell/dictionary.txt)
129*4882a593Smuzhiyun  --codespellfile            Use this codespell dictionary
130*4882a593Smuzhiyun  --typedefsfile             Read additional types from this file
131*4882a593Smuzhiyun  --color[=WHEN]             Use colors 'always', 'never', or only when output
132*4882a593Smuzhiyun                             is a terminal ('auto'). Default is 'auto'.
133*4882a593Smuzhiyun  --kconfig-prefix=WORD      use WORD as a prefix for Kconfig symbols (default
134*4882a593Smuzhiyun                             ${CONFIG_})
135*4882a593Smuzhiyun  -h, --help, --version      display this help and exit
136*4882a593Smuzhiyun
137*4882a593SmuzhiyunWhen FILE is - read standard input.
138*4882a593SmuzhiyunEOM
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun	exit($exitcode);
141*4882a593Smuzhiyun}
142*4882a593Smuzhiyun
143*4882a593Smuzhiyunsub uniq {
144*4882a593Smuzhiyun	my %seen;
145*4882a593Smuzhiyun	return grep { !$seen{$_}++ } @_;
146*4882a593Smuzhiyun}
147*4882a593Smuzhiyun
148*4882a593Smuzhiyunsub list_types {
149*4882a593Smuzhiyun	my ($exitcode) = @_;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun	my $count = 0;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun	local $/ = undef;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun	open(my $script, '<', abs_path($P)) or
156*4882a593Smuzhiyun	    die "$P: Can't read '$P' $!\n";
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun	my $text = <$script>;
159*4882a593Smuzhiyun	close($script);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun	my @types = ();
162*4882a593Smuzhiyun	# Also catch when type or level is passed through a variable
163*4882a593Smuzhiyun	for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
164*4882a593Smuzhiyun		push (@types, $_);
165*4882a593Smuzhiyun	}
166*4882a593Smuzhiyun	@types = sort(uniq(@types));
167*4882a593Smuzhiyun	print("#\tMessage type\n\n");
168*4882a593Smuzhiyun	foreach my $type (@types) {
169*4882a593Smuzhiyun		print(++$count . "\t" . $type . "\n");
170*4882a593Smuzhiyun	}
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun	exit($exitcode);
173*4882a593Smuzhiyun}
174*4882a593Smuzhiyun
175*4882a593Smuzhiyunmy $conf = which_conf($configuration_file);
176*4882a593Smuzhiyunif (-f $conf) {
177*4882a593Smuzhiyun	my @conf_args;
178*4882a593Smuzhiyun	open(my $conffile, '<', "$conf")
179*4882a593Smuzhiyun	    or warn "$P: Can't find a readable $configuration_file file $!\n";
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun	while (<$conffile>) {
182*4882a593Smuzhiyun		my $line = $_;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun		$line =~ s/\s*\n?$//g;
185*4882a593Smuzhiyun		$line =~ s/^\s*//g;
186*4882a593Smuzhiyun		$line =~ s/\s+/ /g;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun		next if ($line =~ m/^\s*#/);
189*4882a593Smuzhiyun		next if ($line =~ m/^\s*$/);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun		my @words = split(" ", $line);
192*4882a593Smuzhiyun		foreach my $word (@words) {
193*4882a593Smuzhiyun			last if ($word =~ m/^#/);
194*4882a593Smuzhiyun			push (@conf_args, $word);
195*4882a593Smuzhiyun		}
196*4882a593Smuzhiyun	}
197*4882a593Smuzhiyun	close($conffile);
198*4882a593Smuzhiyun	unshift(@ARGV, @conf_args) if @conf_args;
199*4882a593Smuzhiyun}
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun# Perl's Getopt::Long allows options to take optional arguments after a space.
202*4882a593Smuzhiyun# Prevent --color by itself from consuming other arguments
203*4882a593Smuzhiyunforeach (@ARGV) {
204*4882a593Smuzhiyun	if ($_ eq "--color" || $_ eq "-color") {
205*4882a593Smuzhiyun		$_ = "--color=$color";
206*4882a593Smuzhiyun	}
207*4882a593Smuzhiyun}
208*4882a593Smuzhiyun
209*4882a593SmuzhiyunGetOptions(
210*4882a593Smuzhiyun	'q|quiet+'	=> \$quiet,
211*4882a593Smuzhiyun	'tree!'		=> \$tree,
212*4882a593Smuzhiyun	'signoff!'	=> \$chk_signoff,
213*4882a593Smuzhiyun	'patch!'	=> \$chk_patch,
214*4882a593Smuzhiyun	'emacs!'	=> \$emacs,
215*4882a593Smuzhiyun	'terse!'	=> \$terse,
216*4882a593Smuzhiyun	'showfile!'	=> \$showfile,
217*4882a593Smuzhiyun	'f|file!'	=> \$file,
218*4882a593Smuzhiyun	'g|git!'	=> \$git,
219*4882a593Smuzhiyun	'subjective!'	=> \$check,
220*4882a593Smuzhiyun	'strict!'	=> \$check,
221*4882a593Smuzhiyun	'ignore=s'	=> \@ignore,
222*4882a593Smuzhiyun	'types=s'	=> \@use,
223*4882a593Smuzhiyun	'show-types!'	=> \$show_types,
224*4882a593Smuzhiyun	'list-types!'	=> \$list_types,
225*4882a593Smuzhiyun	'max-line-length=i' => \$max_line_length,
226*4882a593Smuzhiyun	'min-conf-desc-length=i' => \$min_conf_desc_length,
227*4882a593Smuzhiyun	'tab-size=i'	=> \$tabsize,
228*4882a593Smuzhiyun	'root=s'	=> \$root,
229*4882a593Smuzhiyun	'summary!'	=> \$summary,
230*4882a593Smuzhiyun	'mailback!'	=> \$mailback,
231*4882a593Smuzhiyun	'summary-file!'	=> \$summary_file,
232*4882a593Smuzhiyun	'fix!'		=> \$fix,
233*4882a593Smuzhiyun	'fix-inplace!'	=> \$fix_inplace,
234*4882a593Smuzhiyun	'ignore-perl-version!' => \$ignore_perl_version,
235*4882a593Smuzhiyun	'debug=s'	=> \%debug,
236*4882a593Smuzhiyun	'test-only=s'	=> \$tst_only,
237*4882a593Smuzhiyun	'codespell!'	=> \$codespell,
238*4882a593Smuzhiyun	'codespellfile=s'	=> \$codespellfile,
239*4882a593Smuzhiyun	'typedefsfile=s'	=> \$typedefsfile,
240*4882a593Smuzhiyun	'color=s'	=> \$color,
241*4882a593Smuzhiyun	'no-color'	=> \$color,	#keep old behaviors of -nocolor
242*4882a593Smuzhiyun	'nocolor'	=> \$color,	#keep old behaviors of -nocolor
243*4882a593Smuzhiyun	'kconfig-prefix=s'	=> \${CONFIG_},
244*4882a593Smuzhiyun	'h|help'	=> \$help,
245*4882a593Smuzhiyun	'version'	=> \$help
246*4882a593Smuzhiyun) or help(1);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyunhelp(0) if ($help);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyunlist_types(0) if ($list_types);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun$fix = 1 if ($fix_inplace);
253*4882a593Smuzhiyun$check_orig = $check;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyundie "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
256*4882a593Smuzhiyun
257*4882a593Smuzhiyunmy $exit = 0;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyunmy $perl_version_ok = 1;
260*4882a593Smuzhiyunif ($^V && $^V lt $minimum_perl_version) {
261*4882a593Smuzhiyun	$perl_version_ok = 0;
262*4882a593Smuzhiyun	printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
263*4882a593Smuzhiyun	exit(1) if (!$ignore_perl_version);
264*4882a593Smuzhiyun}
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun#if no filenames are given, push '-' to read patch from stdin
267*4882a593Smuzhiyunif ($#ARGV < 0) {
268*4882a593Smuzhiyun	push(@ARGV, '-');
269*4882a593Smuzhiyun}
270*4882a593Smuzhiyun
271*4882a593Smuzhiyunif ($color =~ /^[01]$/) {
272*4882a593Smuzhiyun	$color = !$color;
273*4882a593Smuzhiyun} elsif ($color =~ /^always$/i) {
274*4882a593Smuzhiyun	$color = 1;
275*4882a593Smuzhiyun} elsif ($color =~ /^never$/i) {
276*4882a593Smuzhiyun	$color = 0;
277*4882a593Smuzhiyun} elsif ($color =~ /^auto$/i) {
278*4882a593Smuzhiyun	$color = (-t STDOUT);
279*4882a593Smuzhiyun} else {
280*4882a593Smuzhiyun	die "$P: Invalid color mode: $color\n";
281*4882a593Smuzhiyun}
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun# skip TAB size 1 to avoid additional checks on $tabsize - 1
284*4882a593Smuzhiyundie "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyunsub hash_save_array_words {
287*4882a593Smuzhiyun	my ($hashRef, $arrayRef) = @_;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun	my @array = split(/,/, join(',', @$arrayRef));
290*4882a593Smuzhiyun	foreach my $word (@array) {
291*4882a593Smuzhiyun		$word =~ s/\s*\n?$//g;
292*4882a593Smuzhiyun		$word =~ s/^\s*//g;
293*4882a593Smuzhiyun		$word =~ s/\s+/ /g;
294*4882a593Smuzhiyun		$word =~ tr/[a-z]/[A-Z]/;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun		next if ($word =~ m/^\s*#/);
297*4882a593Smuzhiyun		next if ($word =~ m/^\s*$/);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun		$hashRef->{$word}++;
300*4882a593Smuzhiyun	}
301*4882a593Smuzhiyun}
302*4882a593Smuzhiyun
303*4882a593Smuzhiyunsub hash_show_words {
304*4882a593Smuzhiyun	my ($hashRef, $prefix) = @_;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun	if (keys %$hashRef) {
307*4882a593Smuzhiyun		print "\nNOTE: $prefix message types:";
308*4882a593Smuzhiyun		foreach my $word (sort keys %$hashRef) {
309*4882a593Smuzhiyun			print " $word";
310*4882a593Smuzhiyun		}
311*4882a593Smuzhiyun		print "\n";
312*4882a593Smuzhiyun	}
313*4882a593Smuzhiyun}
314*4882a593Smuzhiyun
315*4882a593Smuzhiyunhash_save_array_words(\%ignore_type, \@ignore);
316*4882a593Smuzhiyunhash_save_array_words(\%use_type, \@use);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyunmy $dbg_values = 0;
319*4882a593Smuzhiyunmy $dbg_possible = 0;
320*4882a593Smuzhiyunmy $dbg_type = 0;
321*4882a593Smuzhiyunmy $dbg_attr = 0;
322*4882a593Smuzhiyunfor my $key (keys %debug) {
323*4882a593Smuzhiyun	## no critic
324*4882a593Smuzhiyun	eval "\${dbg_$key} = '$debug{$key}';";
325*4882a593Smuzhiyun	die "$@" if ($@);
326*4882a593Smuzhiyun}
327*4882a593Smuzhiyun
328*4882a593Smuzhiyunmy $rpt_cleaners = 0;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyunif ($terse) {
331*4882a593Smuzhiyun	$emacs = 1;
332*4882a593Smuzhiyun	$quiet++;
333*4882a593Smuzhiyun}
334*4882a593Smuzhiyun
335*4882a593Smuzhiyunif ($tree) {
336*4882a593Smuzhiyun	if (defined $root) {
337*4882a593Smuzhiyun		if (!top_of_kernel_tree($root)) {
338*4882a593Smuzhiyun			die "$P: $root: --root does not point at a valid tree\n";
339*4882a593Smuzhiyun		}
340*4882a593Smuzhiyun	} else {
341*4882a593Smuzhiyun		if (top_of_kernel_tree('.')) {
342*4882a593Smuzhiyun			$root = '.';
343*4882a593Smuzhiyun		} elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
344*4882a593Smuzhiyun						top_of_kernel_tree($1)) {
345*4882a593Smuzhiyun			$root = $1;
346*4882a593Smuzhiyun		}
347*4882a593Smuzhiyun	}
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun	if (!defined $root) {
350*4882a593Smuzhiyun		print "Must be run from the top-level dir. of a kernel tree\n";
351*4882a593Smuzhiyun		exit(2);
352*4882a593Smuzhiyun	}
353*4882a593Smuzhiyun}
354*4882a593Smuzhiyun
355*4882a593Smuzhiyunmy $emitted_corrupt = 0;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyunour $Ident	= qr{
358*4882a593Smuzhiyun			[A-Za-z_][A-Za-z\d_]*
359*4882a593Smuzhiyun			(?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
360*4882a593Smuzhiyun		}x;
361*4882a593Smuzhiyunour $Storage	= qr{extern|static|asmlinkage};
362*4882a593Smuzhiyunour $Sparse	= qr{
363*4882a593Smuzhiyun			__user|
364*4882a593Smuzhiyun			__kernel|
365*4882a593Smuzhiyun			__force|
366*4882a593Smuzhiyun			__iomem|
367*4882a593Smuzhiyun			__must_check|
368*4882a593Smuzhiyun			__kprobes|
369*4882a593Smuzhiyun			__ref|
370*4882a593Smuzhiyun			__refconst|
371*4882a593Smuzhiyun			__refdata|
372*4882a593Smuzhiyun			__rcu|
373*4882a593Smuzhiyun			__private
374*4882a593Smuzhiyun		}x;
375*4882a593Smuzhiyunour $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
376*4882a593Smuzhiyunour $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
377*4882a593Smuzhiyunour $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)};
378*4882a593Smuzhiyunour $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)};
379*4882a593Smuzhiyunour $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit};
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun# Notes to $Attribute:
382*4882a593Smuzhiyun# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
383*4882a593Smuzhiyunour $Attribute	= qr{
384*4882a593Smuzhiyun			const|
385*4882a593Smuzhiyun			__percpu|
386*4882a593Smuzhiyun			__nocast|
387*4882a593Smuzhiyun			__safe|
388*4882a593Smuzhiyun			__bitwise|
389*4882a593Smuzhiyun			__packed__|
390*4882a593Smuzhiyun			__packed2__|
391*4882a593Smuzhiyun			__naked|
392*4882a593Smuzhiyun			__maybe_unused|
393*4882a593Smuzhiyun			__always_unused|
394*4882a593Smuzhiyun			__noreturn|
395*4882a593Smuzhiyun			__used|
396*4882a593Smuzhiyun			__cold|
397*4882a593Smuzhiyun			__pure|
398*4882a593Smuzhiyun			__noclone|
399*4882a593Smuzhiyun			__deprecated|
400*4882a593Smuzhiyun			__read_mostly|
401*4882a593Smuzhiyun			__ro_after_init|
402*4882a593Smuzhiyun			__kprobes|
403*4882a593Smuzhiyun			$InitAttribute|
404*4882a593Smuzhiyun			____cacheline_aligned|
405*4882a593Smuzhiyun			____cacheline_aligned_in_smp|
406*4882a593Smuzhiyun			____cacheline_internodealigned_in_smp|
407*4882a593Smuzhiyun			__weak
408*4882a593Smuzhiyun		  }x;
409*4882a593Smuzhiyunour $Modifier;
410*4882a593Smuzhiyunour $Inline	= qr{inline|__always_inline|noinline|__inline|__inline__};
411*4882a593Smuzhiyunour $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};
412*4882a593Smuzhiyunour $Lval	= qr{$Ident(?:$Member)*};
413*4882a593Smuzhiyun
414*4882a593Smuzhiyunour $Int_type	= qr{(?i)llu|ull|ll|lu|ul|l|u};
415*4882a593Smuzhiyunour $Binary	= qr{(?i)0b[01]+$Int_type?};
416*4882a593Smuzhiyunour $Hex	= qr{(?i)0x[0-9a-f]+$Int_type?};
417*4882a593Smuzhiyunour $Int	= qr{[0-9]+$Int_type?};
418*4882a593Smuzhiyunour $Octal	= qr{0[0-7]+$Int_type?};
419*4882a593Smuzhiyunour $String	= qr{"[X\t]*"};
420*4882a593Smuzhiyunour $Float_hex	= qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
421*4882a593Smuzhiyunour $Float_dec	= qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
422*4882a593Smuzhiyunour $Float_int	= qr{(?i)[0-9]+e-?[0-9]+[fl]?};
423*4882a593Smuzhiyunour $Float	= qr{$Float_hex|$Float_dec|$Float_int};
424*4882a593Smuzhiyunour $Constant	= qr{$Float|$Binary|$Octal|$Hex|$Int};
425*4882a593Smuzhiyunour $Assignment	= qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
426*4882a593Smuzhiyunour $Compare    = qr{<=|>=|==|!=|<|(?<!-)>};
427*4882a593Smuzhiyunour $Arithmetic = qr{\+|-|\*|\/|%};
428*4882a593Smuzhiyunour $Operators	= qr{
429*4882a593Smuzhiyun			<=|>=|==|!=|
430*4882a593Smuzhiyun			=>|->|<<|>>|<|>|!|~|
431*4882a593Smuzhiyun			&&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
432*4882a593Smuzhiyun		  }x;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyunour $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyunour $BasicType;
437*4882a593Smuzhiyunour $NonptrType;
438*4882a593Smuzhiyunour $NonptrTypeMisordered;
439*4882a593Smuzhiyunour $NonptrTypeWithAttr;
440*4882a593Smuzhiyunour $Type;
441*4882a593Smuzhiyunour $TypeMisordered;
442*4882a593Smuzhiyunour $Declare;
443*4882a593Smuzhiyunour $DeclareMisordered;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyunour $NON_ASCII_UTF8	= qr{
446*4882a593Smuzhiyun	[\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
447*4882a593Smuzhiyun	|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
448*4882a593Smuzhiyun	| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
449*4882a593Smuzhiyun	|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
450*4882a593Smuzhiyun	|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
451*4882a593Smuzhiyun	| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
452*4882a593Smuzhiyun	|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
453*4882a593Smuzhiyun}x;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyunour $UTF8	= qr{
456*4882a593Smuzhiyun	[\x09\x0A\x0D\x20-\x7E]              # ASCII
457*4882a593Smuzhiyun	| $NON_ASCII_UTF8
458*4882a593Smuzhiyun}x;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyunour $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t};
461*4882a593Smuzhiyunour $typeOtherOSTypedefs = qr{(?x:
462*4882a593Smuzhiyun	u_(?:char|short|int|long) |          # bsd
463*4882a593Smuzhiyun	u(?:nchar|short|int|long)            # sysv
464*4882a593Smuzhiyun)};
465*4882a593Smuzhiyunour $typeKernelTypedefs = qr{(?x:
466*4882a593Smuzhiyun	(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
467*4882a593Smuzhiyun	atomic_t
468*4882a593Smuzhiyun)};
469*4882a593Smuzhiyunour $typeTypedefs = qr{(?x:
470*4882a593Smuzhiyun	$typeC99Typedefs\b|
471*4882a593Smuzhiyun	$typeOtherOSTypedefs\b|
472*4882a593Smuzhiyun	$typeKernelTypedefs\b
473*4882a593Smuzhiyun)};
474*4882a593Smuzhiyun
475*4882a593Smuzhiyunour $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
476*4882a593Smuzhiyun
477*4882a593Smuzhiyunour $logFunctions = qr{(?x:
478*4882a593Smuzhiyun	printk(?:_ratelimited|_once|_deferred_once|_deferred|)|
479*4882a593Smuzhiyun	(?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
480*4882a593Smuzhiyun	TP_printk|
481*4882a593Smuzhiyun	WARN(?:_RATELIMIT|_ONCE|)|
482*4882a593Smuzhiyun	panic|
483*4882a593Smuzhiyun	MODULE_[A-Z_]+|
484*4882a593Smuzhiyun	seq_vprintf|seq_printf|seq_puts
485*4882a593Smuzhiyun)};
486*4882a593Smuzhiyun
487*4882a593Smuzhiyunour $allocFunctions = qr{(?x:
488*4882a593Smuzhiyun	(?:(?:devm_)?
489*4882a593Smuzhiyun		(?:kv|k|v)[czm]alloc(?:_node|_array)? |
490*4882a593Smuzhiyun		kstrdup(?:_const)? |
491*4882a593Smuzhiyun		kmemdup(?:_nul)?) |
492*4882a593Smuzhiyun	(?:\w+)?alloc_skb(?:_ip_align)? |
493*4882a593Smuzhiyun				# dev_alloc_skb/netdev_alloc_skb, et al
494*4882a593Smuzhiyun	dma_alloc_coherent
495*4882a593Smuzhiyun)};
496*4882a593Smuzhiyun
497*4882a593Smuzhiyunour $signature_tags = qr{(?xi:
498*4882a593Smuzhiyun	Signed-off-by:|
499*4882a593Smuzhiyun	Co-developed-by:|
500*4882a593Smuzhiyun	Acked-by:|
501*4882a593Smuzhiyun	Tested-by:|
502*4882a593Smuzhiyun	Reviewed-by:|
503*4882a593Smuzhiyun	Reported-by:|
504*4882a593Smuzhiyun	Suggested-by:|
505*4882a593Smuzhiyun	To:|
506*4882a593Smuzhiyun	Cc:
507*4882a593Smuzhiyun)};
508*4882a593Smuzhiyun
509*4882a593Smuzhiyunour @typeListMisordered = (
510*4882a593Smuzhiyun	qr{char\s+(?:un)?signed},
511*4882a593Smuzhiyun	qr{int\s+(?:(?:un)?signed\s+)?short\s},
512*4882a593Smuzhiyun	qr{int\s+short(?:\s+(?:un)?signed)},
513*4882a593Smuzhiyun	qr{short\s+int(?:\s+(?:un)?signed)},
514*4882a593Smuzhiyun	qr{(?:un)?signed\s+int\s+short},
515*4882a593Smuzhiyun	qr{short\s+(?:un)?signed},
516*4882a593Smuzhiyun	qr{long\s+int\s+(?:un)?signed},
517*4882a593Smuzhiyun	qr{int\s+long\s+(?:un)?signed},
518*4882a593Smuzhiyun	qr{long\s+(?:un)?signed\s+int},
519*4882a593Smuzhiyun	qr{int\s+(?:un)?signed\s+long},
520*4882a593Smuzhiyun	qr{int\s+(?:un)?signed},
521*4882a593Smuzhiyun	qr{int\s+long\s+long\s+(?:un)?signed},
522*4882a593Smuzhiyun	qr{long\s+long\s+int\s+(?:un)?signed},
523*4882a593Smuzhiyun	qr{long\s+long\s+(?:un)?signed\s+int},
524*4882a593Smuzhiyun	qr{long\s+long\s+(?:un)?signed},
525*4882a593Smuzhiyun	qr{long\s+(?:un)?signed},
526*4882a593Smuzhiyun);
527*4882a593Smuzhiyun
528*4882a593Smuzhiyunour @typeList = (
529*4882a593Smuzhiyun	qr{void},
530*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?char},
531*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?short\s+int},
532*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?short},
533*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?int},
534*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?long\s+int},
535*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?long\s+long\s+int},
536*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?long\s+long},
537*4882a593Smuzhiyun	qr{(?:(?:un)?signed\s+)?long},
538*4882a593Smuzhiyun	qr{(?:un)?signed},
539*4882a593Smuzhiyun	qr{float},
540*4882a593Smuzhiyun	qr{double},
541*4882a593Smuzhiyun	qr{bool},
542*4882a593Smuzhiyun	qr{struct\s+$Ident},
543*4882a593Smuzhiyun	qr{union\s+$Ident},
544*4882a593Smuzhiyun	qr{enum\s+$Ident},
545*4882a593Smuzhiyun	qr{${Ident}_t},
546*4882a593Smuzhiyun	qr{${Ident}_handler},
547*4882a593Smuzhiyun	qr{${Ident}_handler_fn},
548*4882a593Smuzhiyun	@typeListMisordered,
549*4882a593Smuzhiyun);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyunour $C90_int_types = qr{(?x:
552*4882a593Smuzhiyun	long\s+long\s+int\s+(?:un)?signed|
553*4882a593Smuzhiyun	long\s+long\s+(?:un)?signed\s+int|
554*4882a593Smuzhiyun	long\s+long\s+(?:un)?signed|
555*4882a593Smuzhiyun	(?:(?:un)?signed\s+)?long\s+long\s+int|
556*4882a593Smuzhiyun	(?:(?:un)?signed\s+)?long\s+long|
557*4882a593Smuzhiyun	int\s+long\s+long\s+(?:un)?signed|
558*4882a593Smuzhiyun	int\s+(?:(?:un)?signed\s+)?long\s+long|
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun	long\s+int\s+(?:un)?signed|
561*4882a593Smuzhiyun	long\s+(?:un)?signed\s+int|
562*4882a593Smuzhiyun	long\s+(?:un)?signed|
563*4882a593Smuzhiyun	(?:(?:un)?signed\s+)?long\s+int|
564*4882a593Smuzhiyun	(?:(?:un)?signed\s+)?long|
565*4882a593Smuzhiyun	int\s+long\s+(?:un)?signed|
566*4882a593Smuzhiyun	int\s+(?:(?:un)?signed\s+)?long|
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun	int\s+(?:un)?signed|
569*4882a593Smuzhiyun	(?:(?:un)?signed\s+)?int
570*4882a593Smuzhiyun)};
571*4882a593Smuzhiyun
572*4882a593Smuzhiyunour @typeListFile = ();
573*4882a593Smuzhiyunour @typeListWithAttr = (
574*4882a593Smuzhiyun	@typeList,
575*4882a593Smuzhiyun	qr{struct\s+$InitAttribute\s+$Ident},
576*4882a593Smuzhiyun	qr{union\s+$InitAttribute\s+$Ident},
577*4882a593Smuzhiyun);
578*4882a593Smuzhiyun
579*4882a593Smuzhiyunour @modifierList = (
580*4882a593Smuzhiyun	qr{fastcall},
581*4882a593Smuzhiyun);
582*4882a593Smuzhiyunour @modifierListFile = ();
583*4882a593Smuzhiyun
584*4882a593Smuzhiyunour @mode_permission_funcs = (
585*4882a593Smuzhiyun	["module_param", 3],
586*4882a593Smuzhiyun	["module_param_(?:array|named|string)", 4],
587*4882a593Smuzhiyun	["module_param_array_named", 5],
588*4882a593Smuzhiyun	["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
589*4882a593Smuzhiyun	["proc_create(?:_data|)", 2],
590*4882a593Smuzhiyun	["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
591*4882a593Smuzhiyun	["IIO_DEV_ATTR_[A-Z_]+", 1],
592*4882a593Smuzhiyun	["SENSOR_(?:DEVICE_|)ATTR_2", 2],
593*4882a593Smuzhiyun	["SENSOR_TEMPLATE(?:_2|)", 3],
594*4882a593Smuzhiyun	["__ATTR", 2],
595*4882a593Smuzhiyun);
596*4882a593Smuzhiyun
597*4882a593Smuzhiyunmy $word_pattern = '\b[A-Z]?[a-z]{2,}\b';
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun#Create a search pattern for all these functions to speed up a loop below
600*4882a593Smuzhiyunour $mode_perms_search = "";
601*4882a593Smuzhiyunforeach my $entry (@mode_permission_funcs) {
602*4882a593Smuzhiyun	$mode_perms_search .= '|' if ($mode_perms_search ne "");
603*4882a593Smuzhiyun	$mode_perms_search .= $entry->[0];
604*4882a593Smuzhiyun}
605*4882a593Smuzhiyun$mode_perms_search = "(?:${mode_perms_search})";
606*4882a593Smuzhiyun
607*4882a593Smuzhiyunour %deprecated_apis = (
608*4882a593Smuzhiyun	"synchronize_rcu_bh"			=> "synchronize_rcu",
609*4882a593Smuzhiyun	"synchronize_rcu_bh_expedited"		=> "synchronize_rcu_expedited",
610*4882a593Smuzhiyun	"call_rcu_bh"				=> "call_rcu",
611*4882a593Smuzhiyun	"rcu_barrier_bh"			=> "rcu_barrier",
612*4882a593Smuzhiyun	"synchronize_sched"			=> "synchronize_rcu",
613*4882a593Smuzhiyun	"synchronize_sched_expedited"		=> "synchronize_rcu_expedited",
614*4882a593Smuzhiyun	"call_rcu_sched"			=> "call_rcu",
615*4882a593Smuzhiyun	"rcu_barrier_sched"			=> "rcu_barrier",
616*4882a593Smuzhiyun	"get_state_synchronize_sched"		=> "get_state_synchronize_rcu",
617*4882a593Smuzhiyun	"cond_synchronize_sched"		=> "cond_synchronize_rcu",
618*4882a593Smuzhiyun);
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun#Create a search pattern for all these strings to speed up a loop below
621*4882a593Smuzhiyunour $deprecated_apis_search = "";
622*4882a593Smuzhiyunforeach my $entry (keys %deprecated_apis) {
623*4882a593Smuzhiyun	$deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
624*4882a593Smuzhiyun	$deprecated_apis_search .= $entry;
625*4882a593Smuzhiyun}
626*4882a593Smuzhiyun$deprecated_apis_search = "(?:${deprecated_apis_search})";
627*4882a593Smuzhiyun
628*4882a593Smuzhiyunour $mode_perms_world_writable = qr{
629*4882a593Smuzhiyun	S_IWUGO		|
630*4882a593Smuzhiyun	S_IWOTH		|
631*4882a593Smuzhiyun	S_IRWXUGO	|
632*4882a593Smuzhiyun	S_IALLUGO	|
633*4882a593Smuzhiyun	0[0-7][0-7][2367]
634*4882a593Smuzhiyun}x;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyunour %mode_permission_string_types = (
637*4882a593Smuzhiyun	"S_IRWXU" => 0700,
638*4882a593Smuzhiyun	"S_IRUSR" => 0400,
639*4882a593Smuzhiyun	"S_IWUSR" => 0200,
640*4882a593Smuzhiyun	"S_IXUSR" => 0100,
641*4882a593Smuzhiyun	"S_IRWXG" => 0070,
642*4882a593Smuzhiyun	"S_IRGRP" => 0040,
643*4882a593Smuzhiyun	"S_IWGRP" => 0020,
644*4882a593Smuzhiyun	"S_IXGRP" => 0010,
645*4882a593Smuzhiyun	"S_IRWXO" => 0007,
646*4882a593Smuzhiyun	"S_IROTH" => 0004,
647*4882a593Smuzhiyun	"S_IWOTH" => 0002,
648*4882a593Smuzhiyun	"S_IXOTH" => 0001,
649*4882a593Smuzhiyun	"S_IRWXUGO" => 0777,
650*4882a593Smuzhiyun	"S_IRUGO" => 0444,
651*4882a593Smuzhiyun	"S_IWUGO" => 0222,
652*4882a593Smuzhiyun	"S_IXUGO" => 0111,
653*4882a593Smuzhiyun);
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun#Create a search pattern for all these strings to speed up a loop below
656*4882a593Smuzhiyunour $mode_perms_string_search = "";
657*4882a593Smuzhiyunforeach my $entry (keys %mode_permission_string_types) {
658*4882a593Smuzhiyun	$mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
659*4882a593Smuzhiyun	$mode_perms_string_search .= $entry;
660*4882a593Smuzhiyun}
661*4882a593Smuzhiyunour $single_mode_perms_string_search = "(?:${mode_perms_string_search})";
662*4882a593Smuzhiyunour $multi_mode_perms_string_search = qr{
663*4882a593Smuzhiyun	${single_mode_perms_string_search}
664*4882a593Smuzhiyun	(?:\s*\|\s*${single_mode_perms_string_search})*
665*4882a593Smuzhiyun}x;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyunsub perms_to_octal {
668*4882a593Smuzhiyun	my ($string) = @_;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun	return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/);
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun	my $val = "";
673*4882a593Smuzhiyun	my $oval = "";
674*4882a593Smuzhiyun	my $to = 0;
675*4882a593Smuzhiyun	my $curpos = 0;
676*4882a593Smuzhiyun	my $lastpos = 0;
677*4882a593Smuzhiyun	while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
678*4882a593Smuzhiyun		$curpos = pos($string);
679*4882a593Smuzhiyun		my $match = $2;
680*4882a593Smuzhiyun		my $omatch = $1;
681*4882a593Smuzhiyun		last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
682*4882a593Smuzhiyun		$lastpos = $curpos;
683*4882a593Smuzhiyun		$to |= $mode_permission_string_types{$match};
684*4882a593Smuzhiyun		$val .= '\s*\|\s*' if ($val ne "");
685*4882a593Smuzhiyun		$val .= $match;
686*4882a593Smuzhiyun		$oval .= $omatch;
687*4882a593Smuzhiyun	}
688*4882a593Smuzhiyun	$oval =~ s/^\s*\|\s*//;
689*4882a593Smuzhiyun	$oval =~ s/\s*\|\s*$//;
690*4882a593Smuzhiyun	return sprintf("%04o", $to);
691*4882a593Smuzhiyun}
692*4882a593Smuzhiyun
693*4882a593Smuzhiyunour $allowed_asm_includes = qr{(?x:
694*4882a593Smuzhiyun	irq|
695*4882a593Smuzhiyun	memory|
696*4882a593Smuzhiyun	time|
697*4882a593Smuzhiyun	reboot
698*4882a593Smuzhiyun)};
699*4882a593Smuzhiyun# memory.h: ARM has a custom one
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun# Load common spelling mistakes and build regular expression list.
702*4882a593Smuzhiyunmy $misspellings;
703*4882a593Smuzhiyunmy %spelling_fix;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyunif (open(my $spelling, '<', $spelling_file)) {
706*4882a593Smuzhiyun	while (<$spelling>) {
707*4882a593Smuzhiyun		my $line = $_;
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun		$line =~ s/\s*\n?$//g;
710*4882a593Smuzhiyun		$line =~ s/^\s*//g;
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun		next if ($line =~ m/^\s*#/);
713*4882a593Smuzhiyun		next if ($line =~ m/^\s*$/);
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun		my ($suspect, $fix) = split(/\|\|/, $line);
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun		$spelling_fix{$suspect} = $fix;
718*4882a593Smuzhiyun	}
719*4882a593Smuzhiyun	close($spelling);
720*4882a593Smuzhiyun} else {
721*4882a593Smuzhiyun	warn "No typos will be found - file '$spelling_file': $!\n";
722*4882a593Smuzhiyun}
723*4882a593Smuzhiyun
724*4882a593Smuzhiyunif ($codespell) {
725*4882a593Smuzhiyun	if (open(my $spelling, '<', $codespellfile)) {
726*4882a593Smuzhiyun		while (<$spelling>) {
727*4882a593Smuzhiyun			my $line = $_;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun			$line =~ s/\s*\n?$//g;
730*4882a593Smuzhiyun			$line =~ s/^\s*//g;
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun			next if ($line =~ m/^\s*#/);
733*4882a593Smuzhiyun			next if ($line =~ m/^\s*$/);
734*4882a593Smuzhiyun			next if ($line =~ m/, disabled/i);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun			$line =~ s/,.*$//;
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun			my ($suspect, $fix) = split(/->/, $line);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun			$spelling_fix{$suspect} = $fix;
741*4882a593Smuzhiyun		}
742*4882a593Smuzhiyun		close($spelling);
743*4882a593Smuzhiyun	} else {
744*4882a593Smuzhiyun		warn "No codespell typos will be found - file '$codespellfile': $!\n";
745*4882a593Smuzhiyun	}
746*4882a593Smuzhiyun}
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyunsub read_words {
751*4882a593Smuzhiyun	my ($wordsRef, $file) = @_;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun	if (open(my $words, '<', $file)) {
754*4882a593Smuzhiyun		while (<$words>) {
755*4882a593Smuzhiyun			my $line = $_;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun			$line =~ s/\s*\n?$//g;
758*4882a593Smuzhiyun			$line =~ s/^\s*//g;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun			next if ($line =~ m/^\s*#/);
761*4882a593Smuzhiyun			next if ($line =~ m/^\s*$/);
762*4882a593Smuzhiyun			if ($line =~ /\s/) {
763*4882a593Smuzhiyun				print("$file: '$line' invalid - ignored\n");
764*4882a593Smuzhiyun				next;
765*4882a593Smuzhiyun			}
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun			$$wordsRef .= '|' if (defined $$wordsRef);
768*4882a593Smuzhiyun			$$wordsRef .= $line;
769*4882a593Smuzhiyun		}
770*4882a593Smuzhiyun		close($file);
771*4882a593Smuzhiyun		return 1;
772*4882a593Smuzhiyun	}
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun	return 0;
775*4882a593Smuzhiyun}
776*4882a593Smuzhiyun
777*4882a593Smuzhiyunmy $const_structs;
778*4882a593Smuzhiyunif (show_type("CONST_STRUCT")) {
779*4882a593Smuzhiyun	read_words(\$const_structs, $conststructsfile)
780*4882a593Smuzhiyun	    or warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
781*4882a593Smuzhiyun}
782*4882a593Smuzhiyun
783*4882a593Smuzhiyunif (defined($typedefsfile)) {
784*4882a593Smuzhiyun	my $typeOtherTypedefs;
785*4882a593Smuzhiyun	read_words(\$typeOtherTypedefs, $typedefsfile)
786*4882a593Smuzhiyun	    or warn "No additional types will be considered - file '$typedefsfile': $!\n";
787*4882a593Smuzhiyun	$typeTypedefs .= '|' . $typeOtherTypedefs if (defined $typeOtherTypedefs);
788*4882a593Smuzhiyun}
789*4882a593Smuzhiyun
790*4882a593Smuzhiyunsub build_types {
791*4882a593Smuzhiyun	my $mods = "(?x:  \n" . join("|\n  ", (@modifierList, @modifierListFile)) . "\n)";
792*4882a593Smuzhiyun	my $all = "(?x:  \n" . join("|\n  ", (@typeList, @typeListFile)) . "\n)";
793*4882a593Smuzhiyun	my $Misordered = "(?x:  \n" . join("|\n  ", @typeListMisordered) . "\n)";
794*4882a593Smuzhiyun	my $allWithAttr = "(?x:  \n" . join("|\n  ", @typeListWithAttr) . "\n)";
795*4882a593Smuzhiyun	$Modifier	= qr{(?:$Attribute|$Sparse|$mods)};
796*4882a593Smuzhiyun	$BasicType	= qr{
797*4882a593Smuzhiyun				(?:$typeTypedefs\b)|
798*4882a593Smuzhiyun				(?:${all}\b)
799*4882a593Smuzhiyun		}x;
800*4882a593Smuzhiyun	$NonptrType	= qr{
801*4882a593Smuzhiyun			(?:$Modifier\s+|const\s+)*
802*4882a593Smuzhiyun			(?:
803*4882a593Smuzhiyun				(?:typeof|__typeof__)\s*\([^\)]*\)|
804*4882a593Smuzhiyun				(?:$typeTypedefs\b)|
805*4882a593Smuzhiyun				(?:${all}\b)
806*4882a593Smuzhiyun			)
807*4882a593Smuzhiyun			(?:\s+$Modifier|\s+const)*
808*4882a593Smuzhiyun		  }x;
809*4882a593Smuzhiyun	$NonptrTypeMisordered	= qr{
810*4882a593Smuzhiyun			(?:$Modifier\s+|const\s+)*
811*4882a593Smuzhiyun			(?:
812*4882a593Smuzhiyun				(?:${Misordered}\b)
813*4882a593Smuzhiyun			)
814*4882a593Smuzhiyun			(?:\s+$Modifier|\s+const)*
815*4882a593Smuzhiyun		  }x;
816*4882a593Smuzhiyun	$NonptrTypeWithAttr	= qr{
817*4882a593Smuzhiyun			(?:$Modifier\s+|const\s+)*
818*4882a593Smuzhiyun			(?:
819*4882a593Smuzhiyun				(?:typeof|__typeof__)\s*\([^\)]*\)|
820*4882a593Smuzhiyun				(?:$typeTypedefs\b)|
821*4882a593Smuzhiyun				(?:${allWithAttr}\b)
822*4882a593Smuzhiyun			)
823*4882a593Smuzhiyun			(?:\s+$Modifier|\s+const)*
824*4882a593Smuzhiyun		  }x;
825*4882a593Smuzhiyun	$Type	= qr{
826*4882a593Smuzhiyun			$NonptrType
827*4882a593Smuzhiyun			(?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
828*4882a593Smuzhiyun			(?:\s+$Inline|\s+$Modifier)*
829*4882a593Smuzhiyun		  }x;
830*4882a593Smuzhiyun	$TypeMisordered	= qr{
831*4882a593Smuzhiyun			$NonptrTypeMisordered
832*4882a593Smuzhiyun			(?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
833*4882a593Smuzhiyun			(?:\s+$Inline|\s+$Modifier)*
834*4882a593Smuzhiyun		  }x;
835*4882a593Smuzhiyun	$Declare	= qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
836*4882a593Smuzhiyun	$DeclareMisordered	= qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered};
837*4882a593Smuzhiyun}
838*4882a593Smuzhiyunbuild_types();
839*4882a593Smuzhiyun
840*4882a593Smuzhiyunour $Typecast	= qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun# Using $balanced_parens, $LvalOrFunc, or $FuncArg
843*4882a593Smuzhiyun# requires at least perl version v5.10.0
844*4882a593Smuzhiyun# Any use must be runtime checked with $^V
845*4882a593Smuzhiyun
846*4882a593Smuzhiyunour $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
847*4882a593Smuzhiyunour $LvalOrFunc	= qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
848*4882a593Smuzhiyunour $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
849*4882a593Smuzhiyun
850*4882a593Smuzhiyunour $declaration_macros = qr{(?x:
851*4882a593Smuzhiyun	(?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
852*4882a593Smuzhiyun	(?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
853*4882a593Smuzhiyun	(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
854*4882a593Smuzhiyun)};
855*4882a593Smuzhiyun
856*4882a593Smuzhiyunsub deparenthesize {
857*4882a593Smuzhiyun	my ($string) = @_;
858*4882a593Smuzhiyun	return "" if (!defined($string));
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun	while ($string =~ /^\s*\(.*\)\s*$/) {
861*4882a593Smuzhiyun		$string =~ s@^\s*\(\s*@@;
862*4882a593Smuzhiyun		$string =~ s@\s*\)\s*$@@;
863*4882a593Smuzhiyun	}
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun	$string =~ s@\s+@ @g;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun	return $string;
868*4882a593Smuzhiyun}
869*4882a593Smuzhiyun
870*4882a593Smuzhiyunsub seed_camelcase_file {
871*4882a593Smuzhiyun	my ($file) = @_;
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun	return if (!(-f $file));
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun	local $/;
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun	open(my $include_file, '<', "$file")
878*4882a593Smuzhiyun	    or warn "$P: Can't read '$file' $!\n";
879*4882a593Smuzhiyun	my $text = <$include_file>;
880*4882a593Smuzhiyun	close($include_file);
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun	my @lines = split('\n', $text);
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun	foreach my $line (@lines) {
885*4882a593Smuzhiyun		next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/);
886*4882a593Smuzhiyun		if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) {
887*4882a593Smuzhiyun			$camelcase{$1} = 1;
888*4882a593Smuzhiyun		} elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) {
889*4882a593Smuzhiyun			$camelcase{$1} = 1;
890*4882a593Smuzhiyun		} elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) {
891*4882a593Smuzhiyun			$camelcase{$1} = 1;
892*4882a593Smuzhiyun		}
893*4882a593Smuzhiyun	}
894*4882a593Smuzhiyun}
895*4882a593Smuzhiyun
896*4882a593Smuzhiyunour %maintained_status = ();
897*4882a593Smuzhiyun
898*4882a593Smuzhiyunsub is_maintained_obsolete {
899*4882a593Smuzhiyun	my ($filename) = @_;
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun	return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun	if (!exists($maintained_status{$filename})) {
904*4882a593Smuzhiyun		$maintained_status{$filename} = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
905*4882a593Smuzhiyun	}
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun	return $maintained_status{$filename} =~ /obsolete/i;
908*4882a593Smuzhiyun}
909*4882a593Smuzhiyun
910*4882a593Smuzhiyunsub is_SPDX_License_valid {
911*4882a593Smuzhiyun	my ($license) = @_;
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun	return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot"));
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun	my $root_path = abs_path($root);
916*4882a593Smuzhiyun	my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
917*4882a593Smuzhiyun	return 0 if ($status ne "");
918*4882a593Smuzhiyun	return 1;
919*4882a593Smuzhiyun}
920*4882a593Smuzhiyun
921*4882a593Smuzhiyunmy $camelcase_seeded = 0;
922*4882a593Smuzhiyunsub seed_camelcase_includes {
923*4882a593Smuzhiyun	return if ($camelcase_seeded);
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun	my $files;
926*4882a593Smuzhiyun	my $camelcase_cache = "";
927*4882a593Smuzhiyun	my @include_files = ();
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun	$camelcase_seeded = 1;
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun	if (-e "$gitroot") {
932*4882a593Smuzhiyun		my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
933*4882a593Smuzhiyun		chomp $git_last_include_commit;
934*4882a593Smuzhiyun		$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
935*4882a593Smuzhiyun	} else {
936*4882a593Smuzhiyun		my $last_mod_date = 0;
937*4882a593Smuzhiyun		$files = `find $root/include -name "*.h"`;
938*4882a593Smuzhiyun		@include_files = split('\n', $files);
939*4882a593Smuzhiyun		foreach my $file (@include_files) {
940*4882a593Smuzhiyun			my $date = POSIX::strftime("%Y%m%d%H%M",
941*4882a593Smuzhiyun						   localtime((stat $file)[9]));
942*4882a593Smuzhiyun			$last_mod_date = $date if ($last_mod_date < $date);
943*4882a593Smuzhiyun		}
944*4882a593Smuzhiyun		$camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date";
945*4882a593Smuzhiyun	}
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun	if ($camelcase_cache ne "" && -f $camelcase_cache) {
948*4882a593Smuzhiyun		open(my $camelcase_file, '<', "$camelcase_cache")
949*4882a593Smuzhiyun		    or warn "$P: Can't read '$camelcase_cache' $!\n";
950*4882a593Smuzhiyun		while (<$camelcase_file>) {
951*4882a593Smuzhiyun			chomp;
952*4882a593Smuzhiyun			$camelcase{$_} = 1;
953*4882a593Smuzhiyun		}
954*4882a593Smuzhiyun		close($camelcase_file);
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun		return;
957*4882a593Smuzhiyun	}
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun	if (-e "$gitroot") {
960*4882a593Smuzhiyun		$files = `${git_command} ls-files "include/*.h"`;
961*4882a593Smuzhiyun		@include_files = split('\n', $files);
962*4882a593Smuzhiyun	}
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun	foreach my $file (@include_files) {
965*4882a593Smuzhiyun		seed_camelcase_file($file);
966*4882a593Smuzhiyun	}
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun	if ($camelcase_cache ne "") {
969*4882a593Smuzhiyun		unlink glob ".checkpatch-camelcase.*";
970*4882a593Smuzhiyun		open(my $camelcase_file, '>', "$camelcase_cache")
971*4882a593Smuzhiyun		    or warn "$P: Can't write '$camelcase_cache' $!\n";
972*4882a593Smuzhiyun		foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) {
973*4882a593Smuzhiyun			print $camelcase_file ("$_\n");
974*4882a593Smuzhiyun		}
975*4882a593Smuzhiyun		close($camelcase_file);
976*4882a593Smuzhiyun	}
977*4882a593Smuzhiyun}
978*4882a593Smuzhiyun
979*4882a593Smuzhiyunsub git_is_single_file {
980*4882a593Smuzhiyun	my ($filename) = @_;
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun	return 0 if ((which("git") eq "") || !(-e "$gitroot"));
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun	my $output = `${git_command} ls-files -- $filename 2>/dev/null`;
985*4882a593Smuzhiyun	my $count = $output =~ tr/\n//;
986*4882a593Smuzhiyun	return $count eq 1 && $output =~ m{^${filename}$};
987*4882a593Smuzhiyun}
988*4882a593Smuzhiyun
989*4882a593Smuzhiyunsub git_commit_info {
990*4882a593Smuzhiyun	my ($commit, $id, $desc) = @_;
991*4882a593Smuzhiyun
992*4882a593Smuzhiyun	return ($id, $desc) if ((which("git") eq "") || !(-e "$gitroot"));
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun	my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
995*4882a593Smuzhiyun	$output =~ s/^\s*//gm;
996*4882a593Smuzhiyun	my @lines = split("\n", $output);
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun	return ($id, $desc) if ($#lines < 0);
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun	if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
1001*4882a593Smuzhiyun# Maybe one day convert this block of bash into something that returns
1002*4882a593Smuzhiyun# all matching commit ids, but it's very slow...
1003*4882a593Smuzhiyun#
1004*4882a593Smuzhiyun#		echo "checking commits $1..."
1005*4882a593Smuzhiyun#		git rev-list --remotes | grep -i "^$1" |
1006*4882a593Smuzhiyun#		while read line ; do
1007*4882a593Smuzhiyun#		    git log --format='%H %s' -1 $line |
1008*4882a593Smuzhiyun#		    echo "commit $(cut -c 1-12,41-)"
1009*4882a593Smuzhiyun#		done
1010*4882a593Smuzhiyun	} elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
1011*4882a593Smuzhiyun		$id = undef;
1012*4882a593Smuzhiyun	} else {
1013*4882a593Smuzhiyun		$id = substr($lines[0], 0, 12);
1014*4882a593Smuzhiyun		$desc = substr($lines[0], 41);
1015*4882a593Smuzhiyun	}
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun	return ($id, $desc);
1018*4882a593Smuzhiyun}
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun$chk_signoff = 0 if ($file);
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyunmy @rawlines = ();
1023*4882a593Smuzhiyunmy @lines = ();
1024*4882a593Smuzhiyunmy @fixed = ();
1025*4882a593Smuzhiyunmy @fixed_inserted = ();
1026*4882a593Smuzhiyunmy @fixed_deleted = ();
1027*4882a593Smuzhiyunmy $fixlinenr = -1;
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun# If input is git commits, extract all commits from the commit expressions.
1030*4882a593Smuzhiyun# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
1031*4882a593Smuzhiyundie "$P: No git repository found\n" if ($git && !-e "$gitroot");
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyunif ($git) {
1034*4882a593Smuzhiyun	my @commits = ();
1035*4882a593Smuzhiyun	foreach my $commit_expr (@ARGV) {
1036*4882a593Smuzhiyun		my $git_range;
1037*4882a593Smuzhiyun		if ($commit_expr =~ m/^(.*)-(\d+)$/) {
1038*4882a593Smuzhiyun			$git_range = "-$2 $1";
1039*4882a593Smuzhiyun		} elsif ($commit_expr =~ m/\.\./) {
1040*4882a593Smuzhiyun			$git_range = "$commit_expr";
1041*4882a593Smuzhiyun		} else {
1042*4882a593Smuzhiyun			$git_range = "-1 $commit_expr";
1043*4882a593Smuzhiyun		}
1044*4882a593Smuzhiyun		my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
1045*4882a593Smuzhiyun		foreach my $line (split(/\n/, $lines)) {
1046*4882a593Smuzhiyun			$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
1047*4882a593Smuzhiyun			next if (!defined($1) || !defined($2));
1048*4882a593Smuzhiyun			my $sha1 = $1;
1049*4882a593Smuzhiyun			my $subject = $2;
1050*4882a593Smuzhiyun			unshift(@commits, $sha1);
1051*4882a593Smuzhiyun			$git_commits{$sha1} = $subject;
1052*4882a593Smuzhiyun		}
1053*4882a593Smuzhiyun	}
1054*4882a593Smuzhiyun	die "$P: no git commits after extraction!\n" if (@commits == 0);
1055*4882a593Smuzhiyun	@ARGV = @commits;
1056*4882a593Smuzhiyun}
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyunmy $vname;
1059*4882a593Smuzhiyun$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
1060*4882a593Smuzhiyunfor my $filename (@ARGV) {
1061*4882a593Smuzhiyun	my $FILE;
1062*4882a593Smuzhiyun	my $is_git_file = git_is_single_file($filename);
1063*4882a593Smuzhiyun	my $oldfile = $file;
1064*4882a593Smuzhiyun	$file = 1 if ($is_git_file);
1065*4882a593Smuzhiyun	if ($git) {
1066*4882a593Smuzhiyun		open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
1067*4882a593Smuzhiyun			die "$P: $filename: git format-patch failed - $!\n";
1068*4882a593Smuzhiyun	} elsif ($file) {
1069*4882a593Smuzhiyun		open($FILE, '-|', "diff -u /dev/null $filename") ||
1070*4882a593Smuzhiyun			die "$P: $filename: diff failed - $!\n";
1071*4882a593Smuzhiyun	} elsif ($filename eq '-') {
1072*4882a593Smuzhiyun		open($FILE, '<&STDIN');
1073*4882a593Smuzhiyun	} else {
1074*4882a593Smuzhiyun		open($FILE, '<', "$filename") ||
1075*4882a593Smuzhiyun			die "$P: $filename: open failed - $!\n";
1076*4882a593Smuzhiyun	}
1077*4882a593Smuzhiyun	if ($filename eq '-') {
1078*4882a593Smuzhiyun		$vname = 'Your patch';
1079*4882a593Smuzhiyun	} elsif ($git) {
1080*4882a593Smuzhiyun		$vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
1081*4882a593Smuzhiyun	} else {
1082*4882a593Smuzhiyun		$vname = $filename;
1083*4882a593Smuzhiyun	}
1084*4882a593Smuzhiyun	while (<$FILE>) {
1085*4882a593Smuzhiyun		chomp;
1086*4882a593Smuzhiyun		push(@rawlines, $_);
1087*4882a593Smuzhiyun		$vname = qq("$1") if ($filename eq '-' && $_ =~ m/^Subject:\s+(.+)/i);
1088*4882a593Smuzhiyun	}
1089*4882a593Smuzhiyun	close($FILE);
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun	if ($#ARGV > 0 && $quiet == 0) {
1092*4882a593Smuzhiyun		print '-' x length($vname) . "\n";
1093*4882a593Smuzhiyun		print "$vname\n";
1094*4882a593Smuzhiyun		print '-' x length($vname) . "\n";
1095*4882a593Smuzhiyun	}
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun	if (!process($filename)) {
1098*4882a593Smuzhiyun		$exit = 1;
1099*4882a593Smuzhiyun	}
1100*4882a593Smuzhiyun	@rawlines = ();
1101*4882a593Smuzhiyun	@lines = ();
1102*4882a593Smuzhiyun	@fixed = ();
1103*4882a593Smuzhiyun	@fixed_inserted = ();
1104*4882a593Smuzhiyun	@fixed_deleted = ();
1105*4882a593Smuzhiyun	$fixlinenr = -1;
1106*4882a593Smuzhiyun	@modifierListFile = ();
1107*4882a593Smuzhiyun	@typeListFile = ();
1108*4882a593Smuzhiyun	build_types();
1109*4882a593Smuzhiyun	$file = $oldfile if ($is_git_file);
1110*4882a593Smuzhiyun}
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyunif (!$quiet) {
1113*4882a593Smuzhiyun	hash_show_words(\%use_type, "Used");
1114*4882a593Smuzhiyun	hash_show_words(\%ignore_type, "Ignored");
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun	if (!$perl_version_ok) {
1117*4882a593Smuzhiyun		print << "EOM"
1118*4882a593Smuzhiyun
1119*4882a593SmuzhiyunNOTE: perl $^V is not modern enough to detect all possible issues.
1120*4882a593Smuzhiyun      An upgrade to at least perl $minimum_perl_version is suggested.
1121*4882a593SmuzhiyunEOM
1122*4882a593Smuzhiyun	}
1123*4882a593Smuzhiyun	if ($exit) {
1124*4882a593Smuzhiyun		print << "EOM"
1125*4882a593Smuzhiyun
1126*4882a593SmuzhiyunNOTE: If any of the errors are false positives, please report
1127*4882a593Smuzhiyun      them to the maintainer, see CHECKPATCH in MAINTAINERS.
1128*4882a593SmuzhiyunEOM
1129*4882a593Smuzhiyun	}
1130*4882a593Smuzhiyun}
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyunexit($exit);
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyunsub top_of_kernel_tree {
1135*4882a593Smuzhiyun	my ($root) = @_;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun	my @tree_check = (
1138*4882a593Smuzhiyun		"COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
1139*4882a593Smuzhiyun		"README", "Documentation", "arch", "include", "drivers",
1140*4882a593Smuzhiyun		"fs", "init", "ipc", "kernel", "lib", "scripts",
1141*4882a593Smuzhiyun	);
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun	foreach my $check (@tree_check) {
1144*4882a593Smuzhiyun		if (! -e $root . '/' . $check) {
1145*4882a593Smuzhiyun			return 0;
1146*4882a593Smuzhiyun		}
1147*4882a593Smuzhiyun	}
1148*4882a593Smuzhiyun	return 1;
1149*4882a593Smuzhiyun}
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyunsub parse_email {
1152*4882a593Smuzhiyun	my ($formatted_email) = @_;
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun	my $name = "";
1155*4882a593Smuzhiyun	my $name_comment = "";
1156*4882a593Smuzhiyun	my $address = "";
1157*4882a593Smuzhiyun	my $comment = "";
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun	if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) {
1160*4882a593Smuzhiyun		$name = $1;
1161*4882a593Smuzhiyun		$address = $2;
1162*4882a593Smuzhiyun		$comment = $3 if defined $3;
1163*4882a593Smuzhiyun	} elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) {
1164*4882a593Smuzhiyun		$address = $1;
1165*4882a593Smuzhiyun		$comment = $2 if defined $2;
1166*4882a593Smuzhiyun	} elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
1167*4882a593Smuzhiyun		$address = $1;
1168*4882a593Smuzhiyun		$comment = $2 if defined $2;
1169*4882a593Smuzhiyun		$formatted_email =~ s/\Q$address\E.*$//;
1170*4882a593Smuzhiyun		$name = $formatted_email;
1171*4882a593Smuzhiyun		$name = trim($name);
1172*4882a593Smuzhiyun		$name =~ s/^\"|\"$//g;
1173*4882a593Smuzhiyun		# If there's a name left after stripping spaces and
1174*4882a593Smuzhiyun		# leading quotes, and the address doesn't have both
1175*4882a593Smuzhiyun		# leading and trailing angle brackets, the address
1176*4882a593Smuzhiyun		# is invalid. ie:
1177*4882a593Smuzhiyun		#   "joe smith joe@smith.com" bad
1178*4882a593Smuzhiyun		#   "joe smith <joe@smith.com" bad
1179*4882a593Smuzhiyun		if ($name ne "" && $address !~ /^<[^>]+>$/) {
1180*4882a593Smuzhiyun			$name = "";
1181*4882a593Smuzhiyun			$address = "";
1182*4882a593Smuzhiyun			$comment = "";
1183*4882a593Smuzhiyun		}
1184*4882a593Smuzhiyun	}
1185*4882a593Smuzhiyun
1186*4882a593Smuzhiyun	$comment = trim($comment);
1187*4882a593Smuzhiyun	$name = trim($name);
1188*4882a593Smuzhiyun	$name =~ s/^\"|\"$//g;
1189*4882a593Smuzhiyun	if ($name =~ s/(\s*\([^\)]+\))\s*//) {
1190*4882a593Smuzhiyun		$name_comment = trim($1);
1191*4882a593Smuzhiyun	}
1192*4882a593Smuzhiyun	$address = trim($address);
1193*4882a593Smuzhiyun	$address =~ s/^\<|\>$//g;
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun	if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
1196*4882a593Smuzhiyun		$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
1197*4882a593Smuzhiyun		$name = "\"$name\"";
1198*4882a593Smuzhiyun	}
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun	return ($name, $name_comment, $address, $comment);
1201*4882a593Smuzhiyun}
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyunsub format_email {
1204*4882a593Smuzhiyun	my ($name, $name_comment, $address, $comment) = @_;
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun	my $formatted_email;
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun	$name_comment = trim($name_comment);
1209*4882a593Smuzhiyun	$comment = trim($comment);
1210*4882a593Smuzhiyun	$name = trim($name);
1211*4882a593Smuzhiyun	$name =~ s/^\"|\"$//g;
1212*4882a593Smuzhiyun	$address = trim($address);
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun	if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
1215*4882a593Smuzhiyun		$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
1216*4882a593Smuzhiyun		$name = "\"$name\"";
1217*4882a593Smuzhiyun	}
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun	if ("$name" eq "") {
1220*4882a593Smuzhiyun		$formatted_email = "$address";
1221*4882a593Smuzhiyun	} else {
1222*4882a593Smuzhiyun		$formatted_email = "$name$name_comment <$address>";
1223*4882a593Smuzhiyun	}
1224*4882a593Smuzhiyun	$formatted_email .= "$comment";
1225*4882a593Smuzhiyun	return $formatted_email;
1226*4882a593Smuzhiyun}
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyunsub reformat_email {
1229*4882a593Smuzhiyun	my ($email) = @_;
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun	my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
1232*4882a593Smuzhiyun	return format_email($email_name, $name_comment, $email_address, $comment);
1233*4882a593Smuzhiyun}
1234*4882a593Smuzhiyun
1235*4882a593Smuzhiyunsub same_email_addresses {
1236*4882a593Smuzhiyun	my ($email1, $email2, $match_comment) = @_;
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun	my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1);
1239*4882a593Smuzhiyun	my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2);
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun	if ($match_comment != 1) {
1242*4882a593Smuzhiyun		return $email1_name eq $email2_name &&
1243*4882a593Smuzhiyun		       $email1_address eq $email2_address;
1244*4882a593Smuzhiyun	}
1245*4882a593Smuzhiyun	return $email1_name eq $email2_name &&
1246*4882a593Smuzhiyun	       $email1_address eq $email2_address &&
1247*4882a593Smuzhiyun	       $name1_comment eq $name2_comment &&
1248*4882a593Smuzhiyun	       $comment1 eq $comment2;
1249*4882a593Smuzhiyun}
1250*4882a593Smuzhiyun
1251*4882a593Smuzhiyunsub which {
1252*4882a593Smuzhiyun	my ($bin) = @_;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun	foreach my $path (split(/:/, $ENV{PATH})) {
1255*4882a593Smuzhiyun		if (-e "$path/$bin") {
1256*4882a593Smuzhiyun			return "$path/$bin";
1257*4882a593Smuzhiyun		}
1258*4882a593Smuzhiyun	}
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun	return "";
1261*4882a593Smuzhiyun}
1262*4882a593Smuzhiyun
1263*4882a593Smuzhiyunsub which_conf {
1264*4882a593Smuzhiyun	my ($conf) = @_;
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun	foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
1267*4882a593Smuzhiyun		if (-e "$path/$conf") {
1268*4882a593Smuzhiyun			return "$path/$conf";
1269*4882a593Smuzhiyun		}
1270*4882a593Smuzhiyun	}
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun	return "";
1273*4882a593Smuzhiyun}
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyunsub expand_tabs {
1276*4882a593Smuzhiyun	my ($str) = @_;
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun	my $res = '';
1279*4882a593Smuzhiyun	my $n = 0;
1280*4882a593Smuzhiyun	for my $c (split(//, $str)) {
1281*4882a593Smuzhiyun		if ($c eq "\t") {
1282*4882a593Smuzhiyun			$res .= ' ';
1283*4882a593Smuzhiyun			$n++;
1284*4882a593Smuzhiyun			for (; ($n % $tabsize) != 0; $n++) {
1285*4882a593Smuzhiyun				$res .= ' ';
1286*4882a593Smuzhiyun			}
1287*4882a593Smuzhiyun			next;
1288*4882a593Smuzhiyun		}
1289*4882a593Smuzhiyun		$res .= $c;
1290*4882a593Smuzhiyun		$n++;
1291*4882a593Smuzhiyun	}
1292*4882a593Smuzhiyun
1293*4882a593Smuzhiyun	return $res;
1294*4882a593Smuzhiyun}
1295*4882a593Smuzhiyunsub copy_spacing {
1296*4882a593Smuzhiyun	(my $res = shift) =~ tr/\t/ /c;
1297*4882a593Smuzhiyun	return $res;
1298*4882a593Smuzhiyun}
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyunsub line_stats {
1301*4882a593Smuzhiyun	my ($line) = @_;
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun	# Drop the diff line leader and expand tabs
1304*4882a593Smuzhiyun	$line =~ s/^.//;
1305*4882a593Smuzhiyun	$line = expand_tabs($line);
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun	# Pick the indent from the front of the line.
1308*4882a593Smuzhiyun	my ($white) = ($line =~ /^(\s*)/);
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun	return (length($line), length($white));
1311*4882a593Smuzhiyun}
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyunmy $sanitise_quote = '';
1314*4882a593Smuzhiyun
1315*4882a593Smuzhiyunsub sanitise_line_reset {
1316*4882a593Smuzhiyun	my ($in_comment) = @_;
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun	if ($in_comment) {
1319*4882a593Smuzhiyun		$sanitise_quote = '*/';
1320*4882a593Smuzhiyun	} else {
1321*4882a593Smuzhiyun		$sanitise_quote = '';
1322*4882a593Smuzhiyun	}
1323*4882a593Smuzhiyun}
1324*4882a593Smuzhiyunsub sanitise_line {
1325*4882a593Smuzhiyun	my ($line) = @_;
1326*4882a593Smuzhiyun
1327*4882a593Smuzhiyun	my $res = '';
1328*4882a593Smuzhiyun	my $l = '';
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun	my $qlen = 0;
1331*4882a593Smuzhiyun	my $off = 0;
1332*4882a593Smuzhiyun	my $c;
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun	# Always copy over the diff marker.
1335*4882a593Smuzhiyun	$res = substr($line, 0, 1);
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun	for ($off = 1; $off < length($line); $off++) {
1338*4882a593Smuzhiyun		$c = substr($line, $off, 1);
1339*4882a593Smuzhiyun
1340*4882a593Smuzhiyun		# Comments we are whacking completely including the begin
1341*4882a593Smuzhiyun		# and end, all to $;.
1342*4882a593Smuzhiyun		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
1343*4882a593Smuzhiyun			$sanitise_quote = '*/';
1344*4882a593Smuzhiyun
1345*4882a593Smuzhiyun			substr($res, $off, 2, "$;$;");
1346*4882a593Smuzhiyun			$off++;
1347*4882a593Smuzhiyun			next;
1348*4882a593Smuzhiyun		}
1349*4882a593Smuzhiyun		if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
1350*4882a593Smuzhiyun			$sanitise_quote = '';
1351*4882a593Smuzhiyun			substr($res, $off, 2, "$;$;");
1352*4882a593Smuzhiyun			$off++;
1353*4882a593Smuzhiyun			next;
1354*4882a593Smuzhiyun		}
1355*4882a593Smuzhiyun		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
1356*4882a593Smuzhiyun			$sanitise_quote = '//';
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun			substr($res, $off, 2, $sanitise_quote);
1359*4882a593Smuzhiyun			$off++;
1360*4882a593Smuzhiyun			next;
1361*4882a593Smuzhiyun		}
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun		# A \ in a string means ignore the next character.
1364*4882a593Smuzhiyun		if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
1365*4882a593Smuzhiyun		    $c eq "\\") {
1366*4882a593Smuzhiyun			substr($res, $off, 2, 'XX');
1367*4882a593Smuzhiyun			$off++;
1368*4882a593Smuzhiyun			next;
1369*4882a593Smuzhiyun		}
1370*4882a593Smuzhiyun		# Regular quotes.
1371*4882a593Smuzhiyun		if ($c eq "'" || $c eq '"') {
1372*4882a593Smuzhiyun			if ($sanitise_quote eq '') {
1373*4882a593Smuzhiyun				$sanitise_quote = $c;
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun				substr($res, $off, 1, $c);
1376*4882a593Smuzhiyun				next;
1377*4882a593Smuzhiyun			} elsif ($sanitise_quote eq $c) {
1378*4882a593Smuzhiyun				$sanitise_quote = '';
1379*4882a593Smuzhiyun			}
1380*4882a593Smuzhiyun		}
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun		#print "c<$c> SQ<$sanitise_quote>\n";
1383*4882a593Smuzhiyun		if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
1384*4882a593Smuzhiyun			substr($res, $off, 1, $;);
1385*4882a593Smuzhiyun		} elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
1386*4882a593Smuzhiyun			substr($res, $off, 1, $;);
1387*4882a593Smuzhiyun		} elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
1388*4882a593Smuzhiyun			substr($res, $off, 1, 'X');
1389*4882a593Smuzhiyun		} else {
1390*4882a593Smuzhiyun			substr($res, $off, 1, $c);
1391*4882a593Smuzhiyun		}
1392*4882a593Smuzhiyun	}
1393*4882a593Smuzhiyun
1394*4882a593Smuzhiyun	if ($sanitise_quote eq '//') {
1395*4882a593Smuzhiyun		$sanitise_quote = '';
1396*4882a593Smuzhiyun	}
1397*4882a593Smuzhiyun
1398*4882a593Smuzhiyun	# The pathname on a #include may be surrounded by '<' and '>'.
1399*4882a593Smuzhiyun	if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
1400*4882a593Smuzhiyun		my $clean = 'X' x length($1);
1401*4882a593Smuzhiyun		$res =~ s@\<.*\>@<$clean>@;
1402*4882a593Smuzhiyun
1403*4882a593Smuzhiyun	# The whole of a #error is a string.
1404*4882a593Smuzhiyun	} elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
1405*4882a593Smuzhiyun		my $clean = 'X' x length($1);
1406*4882a593Smuzhiyun		$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
1407*4882a593Smuzhiyun	}
1408*4882a593Smuzhiyun
1409*4882a593Smuzhiyun	if ($allow_c99_comments && $res =~ m@(//.*$)@) {
1410*4882a593Smuzhiyun		my $match = $1;
1411*4882a593Smuzhiyun		$res =~ s/\Q$match\E/"$;" x length($match)/e;
1412*4882a593Smuzhiyun	}
1413*4882a593Smuzhiyun
1414*4882a593Smuzhiyun	return $res;
1415*4882a593Smuzhiyun}
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyunsub get_quoted_string {
1418*4882a593Smuzhiyun	my ($line, $rawline) = @_;
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun	return "" if (!defined($line) || !defined($rawline));
1421*4882a593Smuzhiyun	return "" if ($line !~ m/($String)/g);
1422*4882a593Smuzhiyun	return substr($rawline, $-[0], $+[0] - $-[0]);
1423*4882a593Smuzhiyun}
1424*4882a593Smuzhiyun
1425*4882a593Smuzhiyunsub ctx_statement_block {
1426*4882a593Smuzhiyun	my ($linenr, $remain, $off) = @_;
1427*4882a593Smuzhiyun	my $line = $linenr - 1;
1428*4882a593Smuzhiyun	my $blk = '';
1429*4882a593Smuzhiyun	my $soff = $off;
1430*4882a593Smuzhiyun	my $coff = $off - 1;
1431*4882a593Smuzhiyun	my $coff_set = 0;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun	my $loff = 0;
1434*4882a593Smuzhiyun
1435*4882a593Smuzhiyun	my $type = '';
1436*4882a593Smuzhiyun	my $level = 0;
1437*4882a593Smuzhiyun	my @stack = ();
1438*4882a593Smuzhiyun	my $p;
1439*4882a593Smuzhiyun	my $c;
1440*4882a593Smuzhiyun	my $len = 0;
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun	my $remainder;
1443*4882a593Smuzhiyun	while (1) {
1444*4882a593Smuzhiyun		@stack = (['', 0]) if ($#stack == -1);
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun		#warn "CSB: blk<$blk> remain<$remain>\n";
1447*4882a593Smuzhiyun		# If we are about to drop off the end, pull in more
1448*4882a593Smuzhiyun		# context.
1449*4882a593Smuzhiyun		if ($off >= $len) {
1450*4882a593Smuzhiyun			for (; $remain > 0; $line++) {
1451*4882a593Smuzhiyun				last if (!defined $lines[$line]);
1452*4882a593Smuzhiyun				next if ($lines[$line] =~ /^-/);
1453*4882a593Smuzhiyun				$remain--;
1454*4882a593Smuzhiyun				$loff = $len;
1455*4882a593Smuzhiyun				$blk .= $lines[$line] . "\n";
1456*4882a593Smuzhiyun				$len = length($blk);
1457*4882a593Smuzhiyun				$line++;
1458*4882a593Smuzhiyun				last;
1459*4882a593Smuzhiyun			}
1460*4882a593Smuzhiyun			# Bail if there is no further context.
1461*4882a593Smuzhiyun			#warn "CSB: blk<$blk> off<$off> len<$len>\n";
1462*4882a593Smuzhiyun			if ($off >= $len) {
1463*4882a593Smuzhiyun				last;
1464*4882a593Smuzhiyun			}
1465*4882a593Smuzhiyun			if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) {
1466*4882a593Smuzhiyun				$level++;
1467*4882a593Smuzhiyun				$type = '#';
1468*4882a593Smuzhiyun			}
1469*4882a593Smuzhiyun		}
1470*4882a593Smuzhiyun		$p = $c;
1471*4882a593Smuzhiyun		$c = substr($blk, $off, 1);
1472*4882a593Smuzhiyun		$remainder = substr($blk, $off);
1473*4882a593Smuzhiyun
1474*4882a593Smuzhiyun		#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun		# Handle nested #if/#else.
1477*4882a593Smuzhiyun		if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
1478*4882a593Smuzhiyun			push(@stack, [ $type, $level ]);
1479*4882a593Smuzhiyun		} elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
1480*4882a593Smuzhiyun			($type, $level) = @{$stack[$#stack - 1]};
1481*4882a593Smuzhiyun		} elsif ($remainder =~ /^#\s*endif\b/) {
1482*4882a593Smuzhiyun			($type, $level) = @{pop(@stack)};
1483*4882a593Smuzhiyun		}
1484*4882a593Smuzhiyun
1485*4882a593Smuzhiyun		# Statement ends at the ';' or a close '}' at the
1486*4882a593Smuzhiyun		# outermost level.
1487*4882a593Smuzhiyun		if ($level == 0 && $c eq ';') {
1488*4882a593Smuzhiyun			last;
1489*4882a593Smuzhiyun		}
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun		# An else is really a conditional as long as its not else if
1492*4882a593Smuzhiyun		if ($level == 0 && $coff_set == 0 &&
1493*4882a593Smuzhiyun				(!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
1494*4882a593Smuzhiyun				$remainder =~ /^(else)(?:\s|{)/ &&
1495*4882a593Smuzhiyun				$remainder !~ /^else\s+if\b/) {
1496*4882a593Smuzhiyun			$coff = $off + length($1) - 1;
1497*4882a593Smuzhiyun			$coff_set = 1;
1498*4882a593Smuzhiyun			#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
1499*4882a593Smuzhiyun			#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
1500*4882a593Smuzhiyun		}
1501*4882a593Smuzhiyun
1502*4882a593Smuzhiyun		if (($type eq '' || $type eq '(') && $c eq '(') {
1503*4882a593Smuzhiyun			$level++;
1504*4882a593Smuzhiyun			$type = '(';
1505*4882a593Smuzhiyun		}
1506*4882a593Smuzhiyun		if ($type eq '(' && $c eq ')') {
1507*4882a593Smuzhiyun			$level--;
1508*4882a593Smuzhiyun			$type = ($level != 0)? '(' : '';
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun			if ($level == 0 && $coff < $soff) {
1511*4882a593Smuzhiyun				$coff = $off;
1512*4882a593Smuzhiyun				$coff_set = 1;
1513*4882a593Smuzhiyun				#warn "CSB: mark coff<$coff>\n";
1514*4882a593Smuzhiyun			}
1515*4882a593Smuzhiyun		}
1516*4882a593Smuzhiyun		if (($type eq '' || $type eq '{') && $c eq '{') {
1517*4882a593Smuzhiyun			$level++;
1518*4882a593Smuzhiyun			$type = '{';
1519*4882a593Smuzhiyun		}
1520*4882a593Smuzhiyun		if ($type eq '{' && $c eq '}') {
1521*4882a593Smuzhiyun			$level--;
1522*4882a593Smuzhiyun			$type = ($level != 0)? '{' : '';
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun			if ($level == 0) {
1525*4882a593Smuzhiyun				if (substr($blk, $off + 1, 1) eq ';') {
1526*4882a593Smuzhiyun					$off++;
1527*4882a593Smuzhiyun				}
1528*4882a593Smuzhiyun				last;
1529*4882a593Smuzhiyun			}
1530*4882a593Smuzhiyun		}
1531*4882a593Smuzhiyun		# Preprocessor commands end at the newline unless escaped.
1532*4882a593Smuzhiyun		if ($type eq '#' && $c eq "\n" && $p ne "\\") {
1533*4882a593Smuzhiyun			$level--;
1534*4882a593Smuzhiyun			$type = '';
1535*4882a593Smuzhiyun			$off++;
1536*4882a593Smuzhiyun			last;
1537*4882a593Smuzhiyun		}
1538*4882a593Smuzhiyun		$off++;
1539*4882a593Smuzhiyun	}
1540*4882a593Smuzhiyun	# We are truly at the end, so shuffle to the next line.
1541*4882a593Smuzhiyun	if ($off == $len) {
1542*4882a593Smuzhiyun		$loff = $len + 1;
1543*4882a593Smuzhiyun		$line++;
1544*4882a593Smuzhiyun		$remain--;
1545*4882a593Smuzhiyun	}
1546*4882a593Smuzhiyun
1547*4882a593Smuzhiyun	my $statement = substr($blk, $soff, $off - $soff + 1);
1548*4882a593Smuzhiyun	my $condition = substr($blk, $soff, $coff - $soff + 1);
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun	#warn "STATEMENT<$statement>\n";
1551*4882a593Smuzhiyun	#warn "CONDITION<$condition>\n";
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun	#print "coff<$coff> soff<$off> loff<$loff>\n";
1554*4882a593Smuzhiyun
1555*4882a593Smuzhiyun	return ($statement, $condition,
1556*4882a593Smuzhiyun			$line, $remain + 1, $off - $loff + 1, $level);
1557*4882a593Smuzhiyun}
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyunsub statement_lines {
1560*4882a593Smuzhiyun	my ($stmt) = @_;
1561*4882a593Smuzhiyun
1562*4882a593Smuzhiyun	# Strip the diff line prefixes and rip blank lines at start and end.
1563*4882a593Smuzhiyun	$stmt =~ s/(^|\n)./$1/g;
1564*4882a593Smuzhiyun	$stmt =~ s/^\s*//;
1565*4882a593Smuzhiyun	$stmt =~ s/\s*$//;
1566*4882a593Smuzhiyun
1567*4882a593Smuzhiyun	my @stmt_lines = ($stmt =~ /\n/g);
1568*4882a593Smuzhiyun
1569*4882a593Smuzhiyun	return $#stmt_lines + 2;
1570*4882a593Smuzhiyun}
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyunsub statement_rawlines {
1573*4882a593Smuzhiyun	my ($stmt) = @_;
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun	my @stmt_lines = ($stmt =~ /\n/g);
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun	return $#stmt_lines + 2;
1578*4882a593Smuzhiyun}
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyunsub statement_block_size {
1581*4882a593Smuzhiyun	my ($stmt) = @_;
1582*4882a593Smuzhiyun
1583*4882a593Smuzhiyun	$stmt =~ s/(^|\n)./$1/g;
1584*4882a593Smuzhiyun	$stmt =~ s/^\s*{//;
1585*4882a593Smuzhiyun	$stmt =~ s/}\s*$//;
1586*4882a593Smuzhiyun	$stmt =~ s/^\s*//;
1587*4882a593Smuzhiyun	$stmt =~ s/\s*$//;
1588*4882a593Smuzhiyun
1589*4882a593Smuzhiyun	my @stmt_lines = ($stmt =~ /\n/g);
1590*4882a593Smuzhiyun	my @stmt_statements = ($stmt =~ /;/g);
1591*4882a593Smuzhiyun
1592*4882a593Smuzhiyun	my $stmt_lines = $#stmt_lines + 2;
1593*4882a593Smuzhiyun	my $stmt_statements = $#stmt_statements + 1;
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun	if ($stmt_lines > $stmt_statements) {
1596*4882a593Smuzhiyun		return $stmt_lines;
1597*4882a593Smuzhiyun	} else {
1598*4882a593Smuzhiyun		return $stmt_statements;
1599*4882a593Smuzhiyun	}
1600*4882a593Smuzhiyun}
1601*4882a593Smuzhiyun
1602*4882a593Smuzhiyunsub ctx_statement_full {
1603*4882a593Smuzhiyun	my ($linenr, $remain, $off) = @_;
1604*4882a593Smuzhiyun	my ($statement, $condition, $level);
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun	my (@chunks);
1607*4882a593Smuzhiyun
1608*4882a593Smuzhiyun	# Grab the first conditional/block pair.
1609*4882a593Smuzhiyun	($statement, $condition, $linenr, $remain, $off, $level) =
1610*4882a593Smuzhiyun				ctx_statement_block($linenr, $remain, $off);
1611*4882a593Smuzhiyun	#print "F: c<$condition> s<$statement> remain<$remain>\n";
1612*4882a593Smuzhiyun	push(@chunks, [ $condition, $statement ]);
1613*4882a593Smuzhiyun	if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
1614*4882a593Smuzhiyun		return ($level, $linenr, @chunks);
1615*4882a593Smuzhiyun	}
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun	# Pull in the following conditional/block pairs and see if they
1618*4882a593Smuzhiyun	# could continue the statement.
1619*4882a593Smuzhiyun	for (;;) {
1620*4882a593Smuzhiyun		($statement, $condition, $linenr, $remain, $off, $level) =
1621*4882a593Smuzhiyun				ctx_statement_block($linenr, $remain, $off);
1622*4882a593Smuzhiyun		#print "C: c<$condition> s<$statement> remain<$remain>\n";
1623*4882a593Smuzhiyun		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
1624*4882a593Smuzhiyun		#print "C: push\n";
1625*4882a593Smuzhiyun		push(@chunks, [ $condition, $statement ]);
1626*4882a593Smuzhiyun	}
1627*4882a593Smuzhiyun
1628*4882a593Smuzhiyun	return ($level, $linenr, @chunks);
1629*4882a593Smuzhiyun}
1630*4882a593Smuzhiyun
1631*4882a593Smuzhiyunsub ctx_block_get {
1632*4882a593Smuzhiyun	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
1633*4882a593Smuzhiyun	my $line;
1634*4882a593Smuzhiyun	my $start = $linenr - 1;
1635*4882a593Smuzhiyun	my $blk = '';
1636*4882a593Smuzhiyun	my @o;
1637*4882a593Smuzhiyun	my @c;
1638*4882a593Smuzhiyun	my @res = ();
1639*4882a593Smuzhiyun
1640*4882a593Smuzhiyun	my $level = 0;
1641*4882a593Smuzhiyun	my @stack = ($level);
1642*4882a593Smuzhiyun	for ($line = $start; $remain > 0; $line++) {
1643*4882a593Smuzhiyun		next if ($rawlines[$line] =~ /^-/);
1644*4882a593Smuzhiyun		$remain--;
1645*4882a593Smuzhiyun
1646*4882a593Smuzhiyun		$blk .= $rawlines[$line];
1647*4882a593Smuzhiyun
1648*4882a593Smuzhiyun		# Handle nested #if/#else.
1649*4882a593Smuzhiyun		if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
1650*4882a593Smuzhiyun			push(@stack, $level);
1651*4882a593Smuzhiyun		} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
1652*4882a593Smuzhiyun			$level = $stack[$#stack - 1];
1653*4882a593Smuzhiyun		} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
1654*4882a593Smuzhiyun			$level = pop(@stack);
1655*4882a593Smuzhiyun		}
1656*4882a593Smuzhiyun
1657*4882a593Smuzhiyun		foreach my $c (split(//, $lines[$line])) {
1658*4882a593Smuzhiyun			##print "C<$c>L<$level><$open$close>O<$off>\n";
1659*4882a593Smuzhiyun			if ($off > 0) {
1660*4882a593Smuzhiyun				$off--;
1661*4882a593Smuzhiyun				next;
1662*4882a593Smuzhiyun			}
1663*4882a593Smuzhiyun
1664*4882a593Smuzhiyun			if ($c eq $close && $level > 0) {
1665*4882a593Smuzhiyun				$level--;
1666*4882a593Smuzhiyun				last if ($level == 0);
1667*4882a593Smuzhiyun			} elsif ($c eq $open) {
1668*4882a593Smuzhiyun				$level++;
1669*4882a593Smuzhiyun			}
1670*4882a593Smuzhiyun		}
1671*4882a593Smuzhiyun
1672*4882a593Smuzhiyun		if (!$outer || $level <= 1) {
1673*4882a593Smuzhiyun			push(@res, $rawlines[$line]);
1674*4882a593Smuzhiyun		}
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun		last if ($level == 0);
1677*4882a593Smuzhiyun	}
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun	return ($level, @res);
1680*4882a593Smuzhiyun}
1681*4882a593Smuzhiyunsub ctx_block_outer {
1682*4882a593Smuzhiyun	my ($linenr, $remain) = @_;
1683*4882a593Smuzhiyun
1684*4882a593Smuzhiyun	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
1685*4882a593Smuzhiyun	return @r;
1686*4882a593Smuzhiyun}
1687*4882a593Smuzhiyunsub ctx_block {
1688*4882a593Smuzhiyun	my ($linenr, $remain) = @_;
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1691*4882a593Smuzhiyun	return @r;
1692*4882a593Smuzhiyun}
1693*4882a593Smuzhiyunsub ctx_statement {
1694*4882a593Smuzhiyun	my ($linenr, $remain, $off) = @_;
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1697*4882a593Smuzhiyun	return @r;
1698*4882a593Smuzhiyun}
1699*4882a593Smuzhiyunsub ctx_block_level {
1700*4882a593Smuzhiyun	my ($linenr, $remain) = @_;
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1703*4882a593Smuzhiyun}
1704*4882a593Smuzhiyunsub ctx_statement_level {
1705*4882a593Smuzhiyun	my ($linenr, $remain, $off) = @_;
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1708*4882a593Smuzhiyun}
1709*4882a593Smuzhiyun
1710*4882a593Smuzhiyunsub ctx_locate_comment {
1711*4882a593Smuzhiyun	my ($first_line, $end_line) = @_;
1712*4882a593Smuzhiyun
1713*4882a593Smuzhiyun	# If c99 comment on the current line, or the line before or after
1714*4882a593Smuzhiyun	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@^\+.*(//.*$)@);
1715*4882a593Smuzhiyun	return $current_comment if (defined $current_comment);
1716*4882a593Smuzhiyun	($current_comment) = ($rawlines[$end_line - 2] =~ m@^[\+ ].*(//.*$)@);
1717*4882a593Smuzhiyun	return $current_comment if (defined $current_comment);
1718*4882a593Smuzhiyun	($current_comment) = ($rawlines[$end_line] =~ m@^[\+ ].*(//.*$)@);
1719*4882a593Smuzhiyun	return $current_comment if (defined $current_comment);
1720*4882a593Smuzhiyun
1721*4882a593Smuzhiyun	# Catch a comment on the end of the line itself.
1722*4882a593Smuzhiyun	($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
1723*4882a593Smuzhiyun	return $current_comment if (defined $current_comment);
1724*4882a593Smuzhiyun
1725*4882a593Smuzhiyun	# Look through the context and try and figure out if there is a
1726*4882a593Smuzhiyun	# comment.
1727*4882a593Smuzhiyun	my $in_comment = 0;
1728*4882a593Smuzhiyun	$current_comment = '';
1729*4882a593Smuzhiyun	for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
1730*4882a593Smuzhiyun		my $line = $rawlines[$linenr - 1];
1731*4882a593Smuzhiyun		#warn "           $line\n";
1732*4882a593Smuzhiyun		if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
1733*4882a593Smuzhiyun			$in_comment = 1;
1734*4882a593Smuzhiyun		}
1735*4882a593Smuzhiyun		if ($line =~ m@/\*@) {
1736*4882a593Smuzhiyun			$in_comment = 1;
1737*4882a593Smuzhiyun		}
1738*4882a593Smuzhiyun		if (!$in_comment && $current_comment ne '') {
1739*4882a593Smuzhiyun			$current_comment = '';
1740*4882a593Smuzhiyun		}
1741*4882a593Smuzhiyun		$current_comment .= $line . "\n" if ($in_comment);
1742*4882a593Smuzhiyun		if ($line =~ m@\*/@) {
1743*4882a593Smuzhiyun			$in_comment = 0;
1744*4882a593Smuzhiyun		}
1745*4882a593Smuzhiyun	}
1746*4882a593Smuzhiyun
1747*4882a593Smuzhiyun	chomp($current_comment);
1748*4882a593Smuzhiyun	return($current_comment);
1749*4882a593Smuzhiyun}
1750*4882a593Smuzhiyunsub ctx_has_comment {
1751*4882a593Smuzhiyun	my ($first_line, $end_line) = @_;
1752*4882a593Smuzhiyun	my $cmt = ctx_locate_comment($first_line, $end_line);
1753*4882a593Smuzhiyun
1754*4882a593Smuzhiyun	##print "LINE: $rawlines[$end_line - 1 ]\n";
1755*4882a593Smuzhiyun	##print "CMMT: $cmt\n";
1756*4882a593Smuzhiyun
1757*4882a593Smuzhiyun	return ($cmt ne '');
1758*4882a593Smuzhiyun}
1759*4882a593Smuzhiyun
1760*4882a593Smuzhiyunsub raw_line {
1761*4882a593Smuzhiyun	my ($linenr, $cnt) = @_;
1762*4882a593Smuzhiyun
1763*4882a593Smuzhiyun	my $offset = $linenr - 1;
1764*4882a593Smuzhiyun	$cnt++;
1765*4882a593Smuzhiyun
1766*4882a593Smuzhiyun	my $line;
1767*4882a593Smuzhiyun	while ($cnt) {
1768*4882a593Smuzhiyun		$line = $rawlines[$offset++];
1769*4882a593Smuzhiyun		next if (defined($line) && $line =~ /^-/);
1770*4882a593Smuzhiyun		$cnt--;
1771*4882a593Smuzhiyun	}
1772*4882a593Smuzhiyun
1773*4882a593Smuzhiyun	return $line;
1774*4882a593Smuzhiyun}
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyunsub get_stat_real {
1777*4882a593Smuzhiyun	my ($linenr, $lc) = @_;
1778*4882a593Smuzhiyun
1779*4882a593Smuzhiyun	my $stat_real = raw_line($linenr, 0);
1780*4882a593Smuzhiyun	for (my $count = $linenr + 1; $count <= $lc; $count++) {
1781*4882a593Smuzhiyun		$stat_real = $stat_real . "\n" . raw_line($count, 0);
1782*4882a593Smuzhiyun	}
1783*4882a593Smuzhiyun
1784*4882a593Smuzhiyun	return $stat_real;
1785*4882a593Smuzhiyun}
1786*4882a593Smuzhiyun
1787*4882a593Smuzhiyunsub get_stat_here {
1788*4882a593Smuzhiyun	my ($linenr, $cnt, $here) = @_;
1789*4882a593Smuzhiyun
1790*4882a593Smuzhiyun	my $herectx = $here . "\n";
1791*4882a593Smuzhiyun	for (my $n = 0; $n < $cnt; $n++) {
1792*4882a593Smuzhiyun		$herectx .= raw_line($linenr, $n) . "\n";
1793*4882a593Smuzhiyun	}
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun	return $herectx;
1796*4882a593Smuzhiyun}
1797*4882a593Smuzhiyun
1798*4882a593Smuzhiyunsub cat_vet {
1799*4882a593Smuzhiyun	my ($vet) = @_;
1800*4882a593Smuzhiyun	my ($res, $coded);
1801*4882a593Smuzhiyun
1802*4882a593Smuzhiyun	$res = '';
1803*4882a593Smuzhiyun	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
1804*4882a593Smuzhiyun		$res .= $1;
1805*4882a593Smuzhiyun		if ($2 ne '') {
1806*4882a593Smuzhiyun			$coded = sprintf("^%c", unpack('C', $2) + 64);
1807*4882a593Smuzhiyun			$res .= $coded;
1808*4882a593Smuzhiyun		}
1809*4882a593Smuzhiyun	}
1810*4882a593Smuzhiyun	$res =~ s/$/\$/;
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun	return $res;
1813*4882a593Smuzhiyun}
1814*4882a593Smuzhiyun
1815*4882a593Smuzhiyunmy $av_preprocessor = 0;
1816*4882a593Smuzhiyunmy $av_pending;
1817*4882a593Smuzhiyunmy @av_paren_type;
1818*4882a593Smuzhiyunmy $av_pend_colon;
1819*4882a593Smuzhiyun
1820*4882a593Smuzhiyunsub annotate_reset {
1821*4882a593Smuzhiyun	$av_preprocessor = 0;
1822*4882a593Smuzhiyun	$av_pending = '_';
1823*4882a593Smuzhiyun	@av_paren_type = ('E');
1824*4882a593Smuzhiyun	$av_pend_colon = 'O';
1825*4882a593Smuzhiyun}
1826*4882a593Smuzhiyun
1827*4882a593Smuzhiyunsub annotate_values {
1828*4882a593Smuzhiyun	my ($stream, $type) = @_;
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun	my $res;
1831*4882a593Smuzhiyun	my $var = '_' x length($stream);
1832*4882a593Smuzhiyun	my $cur = $stream;
1833*4882a593Smuzhiyun
1834*4882a593Smuzhiyun	print "$stream\n" if ($dbg_values > 1);
1835*4882a593Smuzhiyun
1836*4882a593Smuzhiyun	while (length($cur)) {
1837*4882a593Smuzhiyun		@av_paren_type = ('E') if ($#av_paren_type < 0);
1838*4882a593Smuzhiyun		print " <" . join('', @av_paren_type) .
1839*4882a593Smuzhiyun				"> <$type> <$av_pending>" if ($dbg_values > 1);
1840*4882a593Smuzhiyun		if ($cur =~ /^(\s+)/o) {
1841*4882a593Smuzhiyun			print "WS($1)\n" if ($dbg_values > 1);
1842*4882a593Smuzhiyun			if ($1 =~ /\n/ && $av_preprocessor) {
1843*4882a593Smuzhiyun				$type = pop(@av_paren_type);
1844*4882a593Smuzhiyun				$av_preprocessor = 0;
1845*4882a593Smuzhiyun			}
1846*4882a593Smuzhiyun
1847*4882a593Smuzhiyun		} elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
1848*4882a593Smuzhiyun			print "CAST($1)\n" if ($dbg_values > 1);
1849*4882a593Smuzhiyun			push(@av_paren_type, $type);
1850*4882a593Smuzhiyun			$type = 'c';
1851*4882a593Smuzhiyun
1852*4882a593Smuzhiyun		} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
1853*4882a593Smuzhiyun			print "DECLARE($1)\n" if ($dbg_values > 1);
1854*4882a593Smuzhiyun			$type = 'T';
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun		} elsif ($cur =~ /^($Modifier)\s*/) {
1857*4882a593Smuzhiyun			print "MODIFIER($1)\n" if ($dbg_values > 1);
1858*4882a593Smuzhiyun			$type = 'T';
1859*4882a593Smuzhiyun
1860*4882a593Smuzhiyun		} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
1861*4882a593Smuzhiyun			print "DEFINE($1,$2)\n" if ($dbg_values > 1);
1862*4882a593Smuzhiyun			$av_preprocessor = 1;
1863*4882a593Smuzhiyun			push(@av_paren_type, $type);
1864*4882a593Smuzhiyun			if ($2 ne '') {
1865*4882a593Smuzhiyun				$av_pending = 'N';
1866*4882a593Smuzhiyun			}
1867*4882a593Smuzhiyun			$type = 'E';
1868*4882a593Smuzhiyun
1869*4882a593Smuzhiyun		} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
1870*4882a593Smuzhiyun			print "UNDEF($1)\n" if ($dbg_values > 1);
1871*4882a593Smuzhiyun			$av_preprocessor = 1;
1872*4882a593Smuzhiyun			push(@av_paren_type, $type);
1873*4882a593Smuzhiyun
1874*4882a593Smuzhiyun		} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
1875*4882a593Smuzhiyun			print "PRE_START($1)\n" if ($dbg_values > 1);
1876*4882a593Smuzhiyun			$av_preprocessor = 1;
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun			push(@av_paren_type, $type);
1879*4882a593Smuzhiyun			push(@av_paren_type, $type);
1880*4882a593Smuzhiyun			$type = 'E';
1881*4882a593Smuzhiyun
1882*4882a593Smuzhiyun		} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
1883*4882a593Smuzhiyun			print "PRE_RESTART($1)\n" if ($dbg_values > 1);
1884*4882a593Smuzhiyun			$av_preprocessor = 1;
1885*4882a593Smuzhiyun
1886*4882a593Smuzhiyun			push(@av_paren_type, $av_paren_type[$#av_paren_type]);
1887*4882a593Smuzhiyun
1888*4882a593Smuzhiyun			$type = 'E';
1889*4882a593Smuzhiyun
1890*4882a593Smuzhiyun		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
1891*4882a593Smuzhiyun			print "PRE_END($1)\n" if ($dbg_values > 1);
1892*4882a593Smuzhiyun
1893*4882a593Smuzhiyun			$av_preprocessor = 1;
1894*4882a593Smuzhiyun
1895*4882a593Smuzhiyun			# Assume all arms of the conditional end as this
1896*4882a593Smuzhiyun			# one does, and continue as if the #endif was not here.
1897*4882a593Smuzhiyun			pop(@av_paren_type);
1898*4882a593Smuzhiyun			push(@av_paren_type, $type);
1899*4882a593Smuzhiyun			$type = 'E';
1900*4882a593Smuzhiyun
1901*4882a593Smuzhiyun		} elsif ($cur =~ /^(\\\n)/o) {
1902*4882a593Smuzhiyun			print "PRECONT($1)\n" if ($dbg_values > 1);
1903*4882a593Smuzhiyun
1904*4882a593Smuzhiyun		} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
1905*4882a593Smuzhiyun			print "ATTR($1)\n" if ($dbg_values > 1);
1906*4882a593Smuzhiyun			$av_pending = $type;
1907*4882a593Smuzhiyun			$type = 'N';
1908*4882a593Smuzhiyun
1909*4882a593Smuzhiyun		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
1910*4882a593Smuzhiyun			print "SIZEOF($1)\n" if ($dbg_values > 1);
1911*4882a593Smuzhiyun			if (defined $2) {
1912*4882a593Smuzhiyun				$av_pending = 'V';
1913*4882a593Smuzhiyun			}
1914*4882a593Smuzhiyun			$type = 'N';
1915*4882a593Smuzhiyun
1916*4882a593Smuzhiyun		} elsif ($cur =~ /^(if|while|for)\b/o) {
1917*4882a593Smuzhiyun			print "COND($1)\n" if ($dbg_values > 1);
1918*4882a593Smuzhiyun			$av_pending = 'E';
1919*4882a593Smuzhiyun			$type = 'N';
1920*4882a593Smuzhiyun
1921*4882a593Smuzhiyun		} elsif ($cur =~/^(case)/o) {
1922*4882a593Smuzhiyun			print "CASE($1)\n" if ($dbg_values > 1);
1923*4882a593Smuzhiyun			$av_pend_colon = 'C';
1924*4882a593Smuzhiyun			$type = 'N';
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun		} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
1927*4882a593Smuzhiyun			print "KEYWORD($1)\n" if ($dbg_values > 1);
1928*4882a593Smuzhiyun			$type = 'N';
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun		} elsif ($cur =~ /^(\()/o) {
1931*4882a593Smuzhiyun			print "PAREN('$1')\n" if ($dbg_values > 1);
1932*4882a593Smuzhiyun			push(@av_paren_type, $av_pending);
1933*4882a593Smuzhiyun			$av_pending = '_';
1934*4882a593Smuzhiyun			$type = 'N';
1935*4882a593Smuzhiyun
1936*4882a593Smuzhiyun		} elsif ($cur =~ /^(\))/o) {
1937*4882a593Smuzhiyun			my $new_type = pop(@av_paren_type);
1938*4882a593Smuzhiyun			if ($new_type ne '_') {
1939*4882a593Smuzhiyun				$type = $new_type;
1940*4882a593Smuzhiyun				print "PAREN('$1') -> $type\n"
1941*4882a593Smuzhiyun							if ($dbg_values > 1);
1942*4882a593Smuzhiyun			} else {
1943*4882a593Smuzhiyun				print "PAREN('$1')\n" if ($dbg_values > 1);
1944*4882a593Smuzhiyun			}
1945*4882a593Smuzhiyun
1946*4882a593Smuzhiyun		} elsif ($cur =~ /^($Ident)\s*\(/o) {
1947*4882a593Smuzhiyun			print "FUNC($1)\n" if ($dbg_values > 1);
1948*4882a593Smuzhiyun			$type = 'V';
1949*4882a593Smuzhiyun			$av_pending = 'V';
1950*4882a593Smuzhiyun
1951*4882a593Smuzhiyun		} elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
1952*4882a593Smuzhiyun			if (defined $2 && $type eq 'C' || $type eq 'T') {
1953*4882a593Smuzhiyun				$av_pend_colon = 'B';
1954*4882a593Smuzhiyun			} elsif ($type eq 'E') {
1955*4882a593Smuzhiyun				$av_pend_colon = 'L';
1956*4882a593Smuzhiyun			}
1957*4882a593Smuzhiyun			print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
1958*4882a593Smuzhiyun			$type = 'V';
1959*4882a593Smuzhiyun
1960*4882a593Smuzhiyun		} elsif ($cur =~ /^($Ident|$Constant)/o) {
1961*4882a593Smuzhiyun			print "IDENT($1)\n" if ($dbg_values > 1);
1962*4882a593Smuzhiyun			$type = 'V';
1963*4882a593Smuzhiyun
1964*4882a593Smuzhiyun		} elsif ($cur =~ /^($Assignment)/o) {
1965*4882a593Smuzhiyun			print "ASSIGN($1)\n" if ($dbg_values > 1);
1966*4882a593Smuzhiyun			$type = 'N';
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun		} elsif ($cur =~/^(;|{|})/) {
1969*4882a593Smuzhiyun			print "END($1)\n" if ($dbg_values > 1);
1970*4882a593Smuzhiyun			$type = 'E';
1971*4882a593Smuzhiyun			$av_pend_colon = 'O';
1972*4882a593Smuzhiyun
1973*4882a593Smuzhiyun		} elsif ($cur =~/^(,)/) {
1974*4882a593Smuzhiyun			print "COMMA($1)\n" if ($dbg_values > 1);
1975*4882a593Smuzhiyun			$type = 'C';
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun		} elsif ($cur =~ /^(\?)/o) {
1978*4882a593Smuzhiyun			print "QUESTION($1)\n" if ($dbg_values > 1);
1979*4882a593Smuzhiyun			$type = 'N';
1980*4882a593Smuzhiyun
1981*4882a593Smuzhiyun		} elsif ($cur =~ /^(:)/o) {
1982*4882a593Smuzhiyun			print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
1983*4882a593Smuzhiyun
1984*4882a593Smuzhiyun			substr($var, length($res), 1, $av_pend_colon);
1985*4882a593Smuzhiyun			if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
1986*4882a593Smuzhiyun				$type = 'E';
1987*4882a593Smuzhiyun			} else {
1988*4882a593Smuzhiyun				$type = 'N';
1989*4882a593Smuzhiyun			}
1990*4882a593Smuzhiyun			$av_pend_colon = 'O';
1991*4882a593Smuzhiyun
1992*4882a593Smuzhiyun		} elsif ($cur =~ /^(\[)/o) {
1993*4882a593Smuzhiyun			print "CLOSE($1)\n" if ($dbg_values > 1);
1994*4882a593Smuzhiyun			$type = 'N';
1995*4882a593Smuzhiyun
1996*4882a593Smuzhiyun		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
1997*4882a593Smuzhiyun			my $variant;
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun			print "OPV($1)\n" if ($dbg_values > 1);
2000*4882a593Smuzhiyun			if ($type eq 'V') {
2001*4882a593Smuzhiyun				$variant = 'B';
2002*4882a593Smuzhiyun			} else {
2003*4882a593Smuzhiyun				$variant = 'U';
2004*4882a593Smuzhiyun			}
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyun			substr($var, length($res), 1, $variant);
2007*4882a593Smuzhiyun			$type = 'N';
2008*4882a593Smuzhiyun
2009*4882a593Smuzhiyun		} elsif ($cur =~ /^($Operators)/o) {
2010*4882a593Smuzhiyun			print "OP($1)\n" if ($dbg_values > 1);
2011*4882a593Smuzhiyun			if ($1 ne '++' && $1 ne '--') {
2012*4882a593Smuzhiyun				$type = 'N';
2013*4882a593Smuzhiyun			}
2014*4882a593Smuzhiyun
2015*4882a593Smuzhiyun		} elsif ($cur =~ /(^.)/o) {
2016*4882a593Smuzhiyun			print "C($1)\n" if ($dbg_values > 1);
2017*4882a593Smuzhiyun		}
2018*4882a593Smuzhiyun		if (defined $1) {
2019*4882a593Smuzhiyun			$cur = substr($cur, length($1));
2020*4882a593Smuzhiyun			$res .= $type x length($1);
2021*4882a593Smuzhiyun		}
2022*4882a593Smuzhiyun	}
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun	return ($res, $var);
2025*4882a593Smuzhiyun}
2026*4882a593Smuzhiyun
2027*4882a593Smuzhiyunsub possible {
2028*4882a593Smuzhiyun	my ($possible, $line) = @_;
2029*4882a593Smuzhiyun	my $notPermitted = qr{(?:
2030*4882a593Smuzhiyun		^(?:
2031*4882a593Smuzhiyun			$Modifier|
2032*4882a593Smuzhiyun			$Storage|
2033*4882a593Smuzhiyun			$Type|
2034*4882a593Smuzhiyun			DEFINE_\S+
2035*4882a593Smuzhiyun		)$|
2036*4882a593Smuzhiyun		^(?:
2037*4882a593Smuzhiyun			goto|
2038*4882a593Smuzhiyun			return|
2039*4882a593Smuzhiyun			case|
2040*4882a593Smuzhiyun			else|
2041*4882a593Smuzhiyun			asm|__asm__|
2042*4882a593Smuzhiyun			do|
2043*4882a593Smuzhiyun			\#|
2044*4882a593Smuzhiyun			\#\#|
2045*4882a593Smuzhiyun		)(?:\s|$)|
2046*4882a593Smuzhiyun		^(?:typedef|struct|enum)\b
2047*4882a593Smuzhiyun	    )}x;
2048*4882a593Smuzhiyun	warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
2049*4882a593Smuzhiyun	if ($possible !~ $notPermitted) {
2050*4882a593Smuzhiyun		# Check for modifiers.
2051*4882a593Smuzhiyun		$possible =~ s/\s*$Storage\s*//g;
2052*4882a593Smuzhiyun		$possible =~ s/\s*$Sparse\s*//g;
2053*4882a593Smuzhiyun		if ($possible =~ /^\s*$/) {
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun		} elsif ($possible =~ /\s/) {
2056*4882a593Smuzhiyun			$possible =~ s/\s*$Type\s*//g;
2057*4882a593Smuzhiyun			for my $modifier (split(' ', $possible)) {
2058*4882a593Smuzhiyun				if ($modifier !~ $notPermitted) {
2059*4882a593Smuzhiyun					warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
2060*4882a593Smuzhiyun					push(@modifierListFile, $modifier);
2061*4882a593Smuzhiyun				}
2062*4882a593Smuzhiyun			}
2063*4882a593Smuzhiyun
2064*4882a593Smuzhiyun		} else {
2065*4882a593Smuzhiyun			warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
2066*4882a593Smuzhiyun			push(@typeListFile, $possible);
2067*4882a593Smuzhiyun		}
2068*4882a593Smuzhiyun		build_types();
2069*4882a593Smuzhiyun	} else {
2070*4882a593Smuzhiyun		warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
2071*4882a593Smuzhiyun	}
2072*4882a593Smuzhiyun}
2073*4882a593Smuzhiyun
2074*4882a593Smuzhiyunmy $prefix = '';
2075*4882a593Smuzhiyun
2076*4882a593Smuzhiyunsub show_type {
2077*4882a593Smuzhiyun	my ($type) = @_;
2078*4882a593Smuzhiyun
2079*4882a593Smuzhiyun	$type =~ tr/[a-z]/[A-Z]/;
2080*4882a593Smuzhiyun
2081*4882a593Smuzhiyun	return defined $use_type{$type} if (scalar keys %use_type > 0);
2082*4882a593Smuzhiyun
2083*4882a593Smuzhiyun	return !defined $ignore_type{$type};
2084*4882a593Smuzhiyun}
2085*4882a593Smuzhiyun
2086*4882a593Smuzhiyunsub report {
2087*4882a593Smuzhiyun	my ($level, $type, $msg) = @_;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun	if (!show_type($type) ||
2090*4882a593Smuzhiyun	    (defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
2091*4882a593Smuzhiyun		return 0;
2092*4882a593Smuzhiyun	}
2093*4882a593Smuzhiyun	my $output = '';
2094*4882a593Smuzhiyun	if ($color) {
2095*4882a593Smuzhiyun		if ($level eq 'ERROR') {
2096*4882a593Smuzhiyun			$output .= RED;
2097*4882a593Smuzhiyun		} elsif ($level eq 'WARNING') {
2098*4882a593Smuzhiyun			$output .= YELLOW;
2099*4882a593Smuzhiyun		} else {
2100*4882a593Smuzhiyun			$output .= GREEN;
2101*4882a593Smuzhiyun		}
2102*4882a593Smuzhiyun	}
2103*4882a593Smuzhiyun	$output .= $prefix . $level . ':';
2104*4882a593Smuzhiyun	if ($show_types) {
2105*4882a593Smuzhiyun		$output .= BLUE if ($color);
2106*4882a593Smuzhiyun		$output .= "$type:";
2107*4882a593Smuzhiyun	}
2108*4882a593Smuzhiyun	$output .= RESET if ($color);
2109*4882a593Smuzhiyun	$output .= ' ' . $msg . "\n";
2110*4882a593Smuzhiyun
2111*4882a593Smuzhiyun	if ($showfile) {
2112*4882a593Smuzhiyun		my @lines = split("\n", $output, -1);
2113*4882a593Smuzhiyun		splice(@lines, 1, 1);
2114*4882a593Smuzhiyun		$output = join("\n", @lines);
2115*4882a593Smuzhiyun	}
2116*4882a593Smuzhiyun	$output = (split('\n', $output))[0] . "\n" if ($terse);
2117*4882a593Smuzhiyun
2118*4882a593Smuzhiyun	push(our @report, $output);
2119*4882a593Smuzhiyun
2120*4882a593Smuzhiyun	return 1;
2121*4882a593Smuzhiyun}
2122*4882a593Smuzhiyun
2123*4882a593Smuzhiyunsub report_dump {
2124*4882a593Smuzhiyun	our @report;
2125*4882a593Smuzhiyun}
2126*4882a593Smuzhiyun
2127*4882a593Smuzhiyunsub fixup_current_range {
2128*4882a593Smuzhiyun	my ($lineRef, $offset, $length) = @_;
2129*4882a593Smuzhiyun
2130*4882a593Smuzhiyun	if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) {
2131*4882a593Smuzhiyun		my $o = $1;
2132*4882a593Smuzhiyun		my $l = $2;
2133*4882a593Smuzhiyun		my $no = $o + $offset;
2134*4882a593Smuzhiyun		my $nl = $l + $length;
2135*4882a593Smuzhiyun		$$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/;
2136*4882a593Smuzhiyun	}
2137*4882a593Smuzhiyun}
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyunsub fix_inserted_deleted_lines {
2140*4882a593Smuzhiyun	my ($linesRef, $insertedRef, $deletedRef) = @_;
2141*4882a593Smuzhiyun
2142*4882a593Smuzhiyun	my $range_last_linenr = 0;
2143*4882a593Smuzhiyun	my $delta_offset = 0;
2144*4882a593Smuzhiyun
2145*4882a593Smuzhiyun	my $old_linenr = 0;
2146*4882a593Smuzhiyun	my $new_linenr = 0;
2147*4882a593Smuzhiyun
2148*4882a593Smuzhiyun	my $next_insert = 0;
2149*4882a593Smuzhiyun	my $next_delete = 0;
2150*4882a593Smuzhiyun
2151*4882a593Smuzhiyun	my @lines = ();
2152*4882a593Smuzhiyun
2153*4882a593Smuzhiyun	my $inserted = @{$insertedRef}[$next_insert++];
2154*4882a593Smuzhiyun	my $deleted = @{$deletedRef}[$next_delete++];
2155*4882a593Smuzhiyun
2156*4882a593Smuzhiyun	foreach my $old_line (@{$linesRef}) {
2157*4882a593Smuzhiyun		my $save_line = 1;
2158*4882a593Smuzhiyun		my $line = $old_line;	#don't modify the array
2159*4882a593Smuzhiyun		if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) {	#new filename
2160*4882a593Smuzhiyun			$delta_offset = 0;
2161*4882a593Smuzhiyun		} elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) {	#new hunk
2162*4882a593Smuzhiyun			$range_last_linenr = $new_linenr;
2163*4882a593Smuzhiyun			fixup_current_range(\$line, $delta_offset, 0);
2164*4882a593Smuzhiyun		}
2165*4882a593Smuzhiyun
2166*4882a593Smuzhiyun		while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) {
2167*4882a593Smuzhiyun			$deleted = @{$deletedRef}[$next_delete++];
2168*4882a593Smuzhiyun			$save_line = 0;
2169*4882a593Smuzhiyun			fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
2170*4882a593Smuzhiyun		}
2171*4882a593Smuzhiyun
2172*4882a593Smuzhiyun		while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) {
2173*4882a593Smuzhiyun			push(@lines, ${$inserted}{'LINE'});
2174*4882a593Smuzhiyun			$inserted = @{$insertedRef}[$next_insert++];
2175*4882a593Smuzhiyun			$new_linenr++;
2176*4882a593Smuzhiyun			fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
2177*4882a593Smuzhiyun		}
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun		if ($save_line) {
2180*4882a593Smuzhiyun			push(@lines, $line);
2181*4882a593Smuzhiyun			$new_linenr++;
2182*4882a593Smuzhiyun		}
2183*4882a593Smuzhiyun
2184*4882a593Smuzhiyun		$old_linenr++;
2185*4882a593Smuzhiyun	}
2186*4882a593Smuzhiyun
2187*4882a593Smuzhiyun	return @lines;
2188*4882a593Smuzhiyun}
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyunsub fix_insert_line {
2191*4882a593Smuzhiyun	my ($linenr, $line) = @_;
2192*4882a593Smuzhiyun
2193*4882a593Smuzhiyun	my $inserted = {
2194*4882a593Smuzhiyun		LINENR => $linenr,
2195*4882a593Smuzhiyun		LINE => $line,
2196*4882a593Smuzhiyun	};
2197*4882a593Smuzhiyun	push(@fixed_inserted, $inserted);
2198*4882a593Smuzhiyun}
2199*4882a593Smuzhiyun
2200*4882a593Smuzhiyunsub fix_delete_line {
2201*4882a593Smuzhiyun	my ($linenr, $line) = @_;
2202*4882a593Smuzhiyun
2203*4882a593Smuzhiyun	my $deleted = {
2204*4882a593Smuzhiyun		LINENR => $linenr,
2205*4882a593Smuzhiyun		LINE => $line,
2206*4882a593Smuzhiyun	};
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun	push(@fixed_deleted, $deleted);
2209*4882a593Smuzhiyun}
2210*4882a593Smuzhiyun
2211*4882a593Smuzhiyunsub ERROR {
2212*4882a593Smuzhiyun	my ($type, $msg) = @_;
2213*4882a593Smuzhiyun
2214*4882a593Smuzhiyun	if (report("ERROR", $type, $msg)) {
2215*4882a593Smuzhiyun		our $clean = 0;
2216*4882a593Smuzhiyun		our $cnt_error++;
2217*4882a593Smuzhiyun		return 1;
2218*4882a593Smuzhiyun	}
2219*4882a593Smuzhiyun	return 0;
2220*4882a593Smuzhiyun}
2221*4882a593Smuzhiyunsub WARN {
2222*4882a593Smuzhiyun	my ($type, $msg) = @_;
2223*4882a593Smuzhiyun
2224*4882a593Smuzhiyun	if (report("WARNING", $type, $msg)) {
2225*4882a593Smuzhiyun		our $clean = 0;
2226*4882a593Smuzhiyun		our $cnt_warn++;
2227*4882a593Smuzhiyun		return 1;
2228*4882a593Smuzhiyun	}
2229*4882a593Smuzhiyun	return 0;
2230*4882a593Smuzhiyun}
2231*4882a593Smuzhiyunsub CHK {
2232*4882a593Smuzhiyun	my ($type, $msg) = @_;
2233*4882a593Smuzhiyun
2234*4882a593Smuzhiyun	if ($check && report("CHECK", $type, $msg)) {
2235*4882a593Smuzhiyun		our $clean = 0;
2236*4882a593Smuzhiyun		our $cnt_chk++;
2237*4882a593Smuzhiyun		return 1;
2238*4882a593Smuzhiyun	}
2239*4882a593Smuzhiyun	return 0;
2240*4882a593Smuzhiyun}
2241*4882a593Smuzhiyun
2242*4882a593Smuzhiyunsub check_absolute_file {
2243*4882a593Smuzhiyun	my ($absolute, $herecurr) = @_;
2244*4882a593Smuzhiyun	my $file = $absolute;
2245*4882a593Smuzhiyun
2246*4882a593Smuzhiyun	##print "absolute<$absolute>\n";
2247*4882a593Smuzhiyun
2248*4882a593Smuzhiyun	# See if any suffix of this path is a path within the tree.
2249*4882a593Smuzhiyun	while ($file =~ s@^[^/]*/@@) {
2250*4882a593Smuzhiyun		if (-f "$root/$file") {
2251*4882a593Smuzhiyun			##print "file<$file>\n";
2252*4882a593Smuzhiyun			last;
2253*4882a593Smuzhiyun		}
2254*4882a593Smuzhiyun	}
2255*4882a593Smuzhiyun	if (! -f _)  {
2256*4882a593Smuzhiyun		return 0;
2257*4882a593Smuzhiyun	}
2258*4882a593Smuzhiyun
2259*4882a593Smuzhiyun	# It is, so see if the prefix is acceptable.
2260*4882a593Smuzhiyun	my $prefix = $absolute;
2261*4882a593Smuzhiyun	substr($prefix, -length($file)) = '';
2262*4882a593Smuzhiyun
2263*4882a593Smuzhiyun	##print "prefix<$prefix>\n";
2264*4882a593Smuzhiyun	if ($prefix ne ".../") {
2265*4882a593Smuzhiyun		WARN("USE_RELATIVE_PATH",
2266*4882a593Smuzhiyun		     "use relative pathname instead of absolute in changelog text\n" . $herecurr);
2267*4882a593Smuzhiyun	}
2268*4882a593Smuzhiyun}
2269*4882a593Smuzhiyun
2270*4882a593Smuzhiyunsub trim {
2271*4882a593Smuzhiyun	my ($string) = @_;
2272*4882a593Smuzhiyun
2273*4882a593Smuzhiyun	$string =~ s/^\s+|\s+$//g;
2274*4882a593Smuzhiyun
2275*4882a593Smuzhiyun	return $string;
2276*4882a593Smuzhiyun}
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyunsub ltrim {
2279*4882a593Smuzhiyun	my ($string) = @_;
2280*4882a593Smuzhiyun
2281*4882a593Smuzhiyun	$string =~ s/^\s+//;
2282*4882a593Smuzhiyun
2283*4882a593Smuzhiyun	return $string;
2284*4882a593Smuzhiyun}
2285*4882a593Smuzhiyun
2286*4882a593Smuzhiyunsub rtrim {
2287*4882a593Smuzhiyun	my ($string) = @_;
2288*4882a593Smuzhiyun
2289*4882a593Smuzhiyun	$string =~ s/\s+$//;
2290*4882a593Smuzhiyun
2291*4882a593Smuzhiyun	return $string;
2292*4882a593Smuzhiyun}
2293*4882a593Smuzhiyun
2294*4882a593Smuzhiyunsub string_find_replace {
2295*4882a593Smuzhiyun	my ($string, $find, $replace) = @_;
2296*4882a593Smuzhiyun
2297*4882a593Smuzhiyun	$string =~ s/$find/$replace/g;
2298*4882a593Smuzhiyun
2299*4882a593Smuzhiyun	return $string;
2300*4882a593Smuzhiyun}
2301*4882a593Smuzhiyun
2302*4882a593Smuzhiyunsub tabify {
2303*4882a593Smuzhiyun	my ($leading) = @_;
2304*4882a593Smuzhiyun
2305*4882a593Smuzhiyun	my $source_indent = $tabsize;
2306*4882a593Smuzhiyun	my $max_spaces_before_tab = $source_indent - 1;
2307*4882a593Smuzhiyun	my $spaces_to_tab = " " x $source_indent;
2308*4882a593Smuzhiyun
2309*4882a593Smuzhiyun	#convert leading spaces to tabs
2310*4882a593Smuzhiyun	1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
2311*4882a593Smuzhiyun	#Remove spaces before a tab
2312*4882a593Smuzhiyun	1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g;
2313*4882a593Smuzhiyun
2314*4882a593Smuzhiyun	return "$leading";
2315*4882a593Smuzhiyun}
2316*4882a593Smuzhiyun
2317*4882a593Smuzhiyunsub pos_last_openparen {
2318*4882a593Smuzhiyun	my ($line) = @_;
2319*4882a593Smuzhiyun
2320*4882a593Smuzhiyun	my $pos = 0;
2321*4882a593Smuzhiyun
2322*4882a593Smuzhiyun	my $opens = $line =~ tr/\(/\(/;
2323*4882a593Smuzhiyun	my $closes = $line =~ tr/\)/\)/;
2324*4882a593Smuzhiyun
2325*4882a593Smuzhiyun	my $last_openparen = 0;
2326*4882a593Smuzhiyun
2327*4882a593Smuzhiyun	if (($opens == 0) || ($closes >= $opens)) {
2328*4882a593Smuzhiyun		return -1;
2329*4882a593Smuzhiyun	}
2330*4882a593Smuzhiyun
2331*4882a593Smuzhiyun	my $len = length($line);
2332*4882a593Smuzhiyun
2333*4882a593Smuzhiyun	for ($pos = 0; $pos < $len; $pos++) {
2334*4882a593Smuzhiyun		my $string = substr($line, $pos);
2335*4882a593Smuzhiyun		if ($string =~ /^($FuncArg|$balanced_parens)/) {
2336*4882a593Smuzhiyun			$pos += length($1) - 1;
2337*4882a593Smuzhiyun		} elsif (substr($line, $pos, 1) eq '(') {
2338*4882a593Smuzhiyun			$last_openparen = $pos;
2339*4882a593Smuzhiyun		} elsif (index($string, '(') == -1) {
2340*4882a593Smuzhiyun			last;
2341*4882a593Smuzhiyun		}
2342*4882a593Smuzhiyun	}
2343*4882a593Smuzhiyun
2344*4882a593Smuzhiyun	return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
2345*4882a593Smuzhiyun}
2346*4882a593Smuzhiyun
2347*4882a593Smuzhiyunsub get_raw_comment {
2348*4882a593Smuzhiyun	my ($line, $rawline) = @_;
2349*4882a593Smuzhiyun	my $comment = '';
2350*4882a593Smuzhiyun
2351*4882a593Smuzhiyun	for my $i (0 .. (length($line) - 1)) {
2352*4882a593Smuzhiyun		if (substr($line, $i, 1) eq "$;") {
2353*4882a593Smuzhiyun			$comment .= substr($rawline, $i, 1);
2354*4882a593Smuzhiyun		}
2355*4882a593Smuzhiyun	}
2356*4882a593Smuzhiyun
2357*4882a593Smuzhiyun	return $comment;
2358*4882a593Smuzhiyun}
2359*4882a593Smuzhiyun
2360*4882a593Smuzhiyunsub process {
2361*4882a593Smuzhiyun	my $filename = shift;
2362*4882a593Smuzhiyun
2363*4882a593Smuzhiyun	my $linenr=0;
2364*4882a593Smuzhiyun	my $prevline="";
2365*4882a593Smuzhiyun	my $prevrawline="";
2366*4882a593Smuzhiyun	my $stashline="";
2367*4882a593Smuzhiyun	my $stashrawline="";
2368*4882a593Smuzhiyun
2369*4882a593Smuzhiyun	my $length;
2370*4882a593Smuzhiyun	my $indent;
2371*4882a593Smuzhiyun	my $previndent=0;
2372*4882a593Smuzhiyun	my $stashindent=0;
2373*4882a593Smuzhiyun
2374*4882a593Smuzhiyun	our $clean = 1;
2375*4882a593Smuzhiyun	my $signoff = 0;
2376*4882a593Smuzhiyun	my $author = '';
2377*4882a593Smuzhiyun	my $authorsignoff = 0;
2378*4882a593Smuzhiyun	my $author_sob = '';
2379*4882a593Smuzhiyun	my $is_patch = 0;
2380*4882a593Smuzhiyun	my $is_binding_patch = -1;
2381*4882a593Smuzhiyun	my $in_header_lines = $file ? 0 : 1;
2382*4882a593Smuzhiyun	my $in_commit_log = 0;		#Scanning lines before patch
2383*4882a593Smuzhiyun	my $has_patch_separator = 0;	#Found a --- line
2384*4882a593Smuzhiyun	my $has_commit_log = 0;		#Encountered lines before patch
2385*4882a593Smuzhiyun	my $commit_log_lines = 0;	#Number of commit log lines
2386*4882a593Smuzhiyun	my $commit_log_possible_stack_dump = 0;
2387*4882a593Smuzhiyun	my $commit_log_long_line = 0;
2388*4882a593Smuzhiyun	my $commit_log_has_diff = 0;
2389*4882a593Smuzhiyun	my $reported_maintainer_file = 0;
2390*4882a593Smuzhiyun	my $non_utf8_charset = 0;
2391*4882a593Smuzhiyun
2392*4882a593Smuzhiyun	my $last_blank_line = 0;
2393*4882a593Smuzhiyun	my $last_coalesced_string_linenr = -1;
2394*4882a593Smuzhiyun
2395*4882a593Smuzhiyun	our @report = ();
2396*4882a593Smuzhiyun	our $cnt_lines = 0;
2397*4882a593Smuzhiyun	our $cnt_error = 0;
2398*4882a593Smuzhiyun	our $cnt_warn = 0;
2399*4882a593Smuzhiyun	our $cnt_chk = 0;
2400*4882a593Smuzhiyun
2401*4882a593Smuzhiyun	# Trace the real file/line as we go.
2402*4882a593Smuzhiyun	my $realfile = '';
2403*4882a593Smuzhiyun	my $realline = 0;
2404*4882a593Smuzhiyun	my $realcnt = 0;
2405*4882a593Smuzhiyun	my $here = '';
2406*4882a593Smuzhiyun	my $context_function;		#undef'd unless there's a known function
2407*4882a593Smuzhiyun	my $in_comment = 0;
2408*4882a593Smuzhiyun	my $comment_edge = 0;
2409*4882a593Smuzhiyun	my $first_line = 0;
2410*4882a593Smuzhiyun	my $p1_prefix = '';
2411*4882a593Smuzhiyun
2412*4882a593Smuzhiyun	my $prev_values = 'E';
2413*4882a593Smuzhiyun
2414*4882a593Smuzhiyun	# suppression flags
2415*4882a593Smuzhiyun	my %suppress_ifbraces;
2416*4882a593Smuzhiyun	my %suppress_whiletrailers;
2417*4882a593Smuzhiyun	my %suppress_export;
2418*4882a593Smuzhiyun	my $suppress_statement = 0;
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun	my %signatures = ();
2421*4882a593Smuzhiyun
2422*4882a593Smuzhiyun	# Pre-scan the patch sanitizing the lines.
2423*4882a593Smuzhiyun	# Pre-scan the patch looking for any __setup documentation.
2424*4882a593Smuzhiyun	#
2425*4882a593Smuzhiyun	my @setup_docs = ();
2426*4882a593Smuzhiyun	my $setup_docs = 0;
2427*4882a593Smuzhiyun
2428*4882a593Smuzhiyun	my $camelcase_file_seeded = 0;
2429*4882a593Smuzhiyun
2430*4882a593Smuzhiyun	my $checklicenseline = 1;
2431*4882a593Smuzhiyun
2432*4882a593Smuzhiyun	sanitise_line_reset();
2433*4882a593Smuzhiyun	my $line;
2434*4882a593Smuzhiyun	foreach my $rawline (@rawlines) {
2435*4882a593Smuzhiyun		$linenr++;
2436*4882a593Smuzhiyun		$line = $rawline;
2437*4882a593Smuzhiyun
2438*4882a593Smuzhiyun		push(@fixed, $rawline) if ($fix);
2439*4882a593Smuzhiyun
2440*4882a593Smuzhiyun		if ($rawline=~/^\+\+\+\s+(\S+)/) {
2441*4882a593Smuzhiyun			$setup_docs = 0;
2442*4882a593Smuzhiyun			if ($1 =~ m@Documentation/admin-guide/kernel-parameters.txt$@) {
2443*4882a593Smuzhiyun				$setup_docs = 1;
2444*4882a593Smuzhiyun			}
2445*4882a593Smuzhiyun			#next;
2446*4882a593Smuzhiyun		}
2447*4882a593Smuzhiyun		if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
2448*4882a593Smuzhiyun			$realline=$1-1;
2449*4882a593Smuzhiyun			if (defined $2) {
2450*4882a593Smuzhiyun				$realcnt=$3+1;
2451*4882a593Smuzhiyun			} else {
2452*4882a593Smuzhiyun				$realcnt=1+1;
2453*4882a593Smuzhiyun			}
2454*4882a593Smuzhiyun			$in_comment = 0;
2455*4882a593Smuzhiyun
2456*4882a593Smuzhiyun			# Guestimate if this is a continuing comment.  Run
2457*4882a593Smuzhiyun			# the context looking for a comment "edge".  If this
2458*4882a593Smuzhiyun			# edge is a close comment then we must be in a comment
2459*4882a593Smuzhiyun			# at context start.
2460*4882a593Smuzhiyun			my $edge;
2461*4882a593Smuzhiyun			my $cnt = $realcnt;
2462*4882a593Smuzhiyun			for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
2463*4882a593Smuzhiyun				next if (defined $rawlines[$ln - 1] &&
2464*4882a593Smuzhiyun					 $rawlines[$ln - 1] =~ /^-/);
2465*4882a593Smuzhiyun				$cnt--;
2466*4882a593Smuzhiyun				#print "RAW<$rawlines[$ln - 1]>\n";
2467*4882a593Smuzhiyun				last if (!defined $rawlines[$ln - 1]);
2468*4882a593Smuzhiyun				if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
2469*4882a593Smuzhiyun				    $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
2470*4882a593Smuzhiyun					($edge) = $1;
2471*4882a593Smuzhiyun					last;
2472*4882a593Smuzhiyun				}
2473*4882a593Smuzhiyun			}
2474*4882a593Smuzhiyun			if (defined $edge && $edge eq '*/') {
2475*4882a593Smuzhiyun				$in_comment = 1;
2476*4882a593Smuzhiyun			}
2477*4882a593Smuzhiyun
2478*4882a593Smuzhiyun			# Guestimate if this is a continuing comment.  If this
2479*4882a593Smuzhiyun			# is the start of a diff block and this line starts
2480*4882a593Smuzhiyun			# ' *' then it is very likely a comment.
2481*4882a593Smuzhiyun			if (!defined $edge &&
2482*4882a593Smuzhiyun			    $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
2483*4882a593Smuzhiyun			{
2484*4882a593Smuzhiyun				$in_comment = 1;
2485*4882a593Smuzhiyun			}
2486*4882a593Smuzhiyun
2487*4882a593Smuzhiyun			##print "COMMENT:$in_comment edge<$edge> $rawline\n";
2488*4882a593Smuzhiyun			sanitise_line_reset($in_comment);
2489*4882a593Smuzhiyun
2490*4882a593Smuzhiyun		} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
2491*4882a593Smuzhiyun			# Standardise the strings and chars within the input to
2492*4882a593Smuzhiyun			# simplify matching -- only bother with positive lines.
2493*4882a593Smuzhiyun			$line = sanitise_line($rawline);
2494*4882a593Smuzhiyun		}
2495*4882a593Smuzhiyun		push(@lines, $line);
2496*4882a593Smuzhiyun
2497*4882a593Smuzhiyun		if ($realcnt > 1) {
2498*4882a593Smuzhiyun			$realcnt-- if ($line =~ /^(?:\+| |$)/);
2499*4882a593Smuzhiyun		} else {
2500*4882a593Smuzhiyun			$realcnt = 0;
2501*4882a593Smuzhiyun		}
2502*4882a593Smuzhiyun
2503*4882a593Smuzhiyun		#print "==>$rawline\n";
2504*4882a593Smuzhiyun		#print "-->$line\n";
2505*4882a593Smuzhiyun
2506*4882a593Smuzhiyun		if ($setup_docs && $line =~ /^\+/) {
2507*4882a593Smuzhiyun			push(@setup_docs, $line);
2508*4882a593Smuzhiyun		}
2509*4882a593Smuzhiyun	}
2510*4882a593Smuzhiyun
2511*4882a593Smuzhiyun	$prefix = '';
2512*4882a593Smuzhiyun
2513*4882a593Smuzhiyun	$realcnt = 0;
2514*4882a593Smuzhiyun	$linenr = 0;
2515*4882a593Smuzhiyun	$fixlinenr = -1;
2516*4882a593Smuzhiyun	foreach my $line (@lines) {
2517*4882a593Smuzhiyun		$linenr++;
2518*4882a593Smuzhiyun		$fixlinenr++;
2519*4882a593Smuzhiyun		my $sline = $line;	#copy of $line
2520*4882a593Smuzhiyun		$sline =~ s/$;/ /g;	#with comments as spaces
2521*4882a593Smuzhiyun
2522*4882a593Smuzhiyun		my $rawline = $rawlines[$linenr - 1];
2523*4882a593Smuzhiyun		my $raw_comment = get_raw_comment($line, $rawline);
2524*4882a593Smuzhiyun
2525*4882a593Smuzhiyun# check if it's a mode change, rename or start of a patch
2526*4882a593Smuzhiyun		if (!$in_commit_log &&
2527*4882a593Smuzhiyun		    ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ ||
2528*4882a593Smuzhiyun		    ($line =~ /^rename (?:from|to) \S+\s*$/ ||
2529*4882a593Smuzhiyun		     $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) {
2530*4882a593Smuzhiyun			$is_patch = 1;
2531*4882a593Smuzhiyun		}
2532*4882a593Smuzhiyun
2533*4882a593Smuzhiyun#extract the line range in the file after the patch is applied
2534*4882a593Smuzhiyun		if (!$in_commit_log &&
2535*4882a593Smuzhiyun		    $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
2536*4882a593Smuzhiyun			my $context = $4;
2537*4882a593Smuzhiyun			$is_patch = 1;
2538*4882a593Smuzhiyun			$first_line = $linenr + 1;
2539*4882a593Smuzhiyun			$realline=$1-1;
2540*4882a593Smuzhiyun			if (defined $2) {
2541*4882a593Smuzhiyun				$realcnt=$3+1;
2542*4882a593Smuzhiyun			} else {
2543*4882a593Smuzhiyun				$realcnt=1+1;
2544*4882a593Smuzhiyun			}
2545*4882a593Smuzhiyun			annotate_reset();
2546*4882a593Smuzhiyun			$prev_values = 'E';
2547*4882a593Smuzhiyun
2548*4882a593Smuzhiyun			%suppress_ifbraces = ();
2549*4882a593Smuzhiyun			%suppress_whiletrailers = ();
2550*4882a593Smuzhiyun			%suppress_export = ();
2551*4882a593Smuzhiyun			$suppress_statement = 0;
2552*4882a593Smuzhiyun			if ($context =~ /\b(\w+)\s*\(/) {
2553*4882a593Smuzhiyun				$context_function = $1;
2554*4882a593Smuzhiyun			} else {
2555*4882a593Smuzhiyun				undef $context_function;
2556*4882a593Smuzhiyun			}
2557*4882a593Smuzhiyun			next;
2558*4882a593Smuzhiyun
2559*4882a593Smuzhiyun# track the line number as we move through the hunk, note that
2560*4882a593Smuzhiyun# new versions of GNU diff omit the leading space on completely
2561*4882a593Smuzhiyun# blank context lines so we need to count that too.
2562*4882a593Smuzhiyun		} elsif ($line =~ /^( |\+|$)/) {
2563*4882a593Smuzhiyun			$realline++;
2564*4882a593Smuzhiyun			$realcnt-- if ($realcnt != 0);
2565*4882a593Smuzhiyun
2566*4882a593Smuzhiyun			# Measure the line length and indent.
2567*4882a593Smuzhiyun			($length, $indent) = line_stats($rawline);
2568*4882a593Smuzhiyun
2569*4882a593Smuzhiyun			# Track the previous line.
2570*4882a593Smuzhiyun			($prevline, $stashline) = ($stashline, $line);
2571*4882a593Smuzhiyun			($previndent, $stashindent) = ($stashindent, $indent);
2572*4882a593Smuzhiyun			($prevrawline, $stashrawline) = ($stashrawline, $rawline);
2573*4882a593Smuzhiyun
2574*4882a593Smuzhiyun			#warn "line<$line>\n";
2575*4882a593Smuzhiyun
2576*4882a593Smuzhiyun		} elsif ($realcnt == 1) {
2577*4882a593Smuzhiyun			$realcnt--;
2578*4882a593Smuzhiyun		}
2579*4882a593Smuzhiyun
2580*4882a593Smuzhiyun		my $hunk_line = ($realcnt != 0);
2581*4882a593Smuzhiyun
2582*4882a593Smuzhiyun		$here = "#$linenr: " if (!$file);
2583*4882a593Smuzhiyun		$here = "#$realline: " if ($file);
2584*4882a593Smuzhiyun
2585*4882a593Smuzhiyun		my $found_file = 0;
2586*4882a593Smuzhiyun		# extract the filename as it passes
2587*4882a593Smuzhiyun		if ($line =~ /^diff --git.*?(\S+)$/) {
2588*4882a593Smuzhiyun			$realfile = $1;
2589*4882a593Smuzhiyun			$realfile =~ s@^([^/]*)/@@ if (!$file);
2590*4882a593Smuzhiyun			$in_commit_log = 0;
2591*4882a593Smuzhiyun			$found_file = 1;
2592*4882a593Smuzhiyun		} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
2593*4882a593Smuzhiyun			$realfile = $1;
2594*4882a593Smuzhiyun			$realfile =~ s@^([^/]*)/@@ if (!$file);
2595*4882a593Smuzhiyun			$in_commit_log = 0;
2596*4882a593Smuzhiyun
2597*4882a593Smuzhiyun			$p1_prefix = $1;
2598*4882a593Smuzhiyun			if (!$file && $tree && $p1_prefix ne '' &&
2599*4882a593Smuzhiyun			    -e "$root/$p1_prefix") {
2600*4882a593Smuzhiyun				WARN("PATCH_PREFIX",
2601*4882a593Smuzhiyun				     "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
2602*4882a593Smuzhiyun			}
2603*4882a593Smuzhiyun
2604*4882a593Smuzhiyun			if ($realfile =~ m@^include/asm/@) {
2605*4882a593Smuzhiyun				ERROR("MODIFIED_INCLUDE_ASM",
2606*4882a593Smuzhiyun				      "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
2607*4882a593Smuzhiyun			}
2608*4882a593Smuzhiyun			$found_file = 1;
2609*4882a593Smuzhiyun		}
2610*4882a593Smuzhiyun
2611*4882a593Smuzhiyun#make up the handle for any error we report on this line
2612*4882a593Smuzhiyun		if ($showfile) {
2613*4882a593Smuzhiyun			$prefix = "$realfile:$realline: "
2614*4882a593Smuzhiyun		} elsif ($emacs) {
2615*4882a593Smuzhiyun			if ($file) {
2616*4882a593Smuzhiyun				$prefix = "$filename:$realline: ";
2617*4882a593Smuzhiyun			} else {
2618*4882a593Smuzhiyun				$prefix = "$filename:$linenr: ";
2619*4882a593Smuzhiyun			}
2620*4882a593Smuzhiyun		}
2621*4882a593Smuzhiyun
2622*4882a593Smuzhiyun		if ($found_file) {
2623*4882a593Smuzhiyun			if (is_maintained_obsolete($realfile)) {
2624*4882a593Smuzhiyun				WARN("OBSOLETE",
2625*4882a593Smuzhiyun				     "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy.  No unnecessary modifications please.\n");
2626*4882a593Smuzhiyun			}
2627*4882a593Smuzhiyun			if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) {
2628*4882a593Smuzhiyun				$check = 1;
2629*4882a593Smuzhiyun			} else {
2630*4882a593Smuzhiyun				$check = $check_orig;
2631*4882a593Smuzhiyun			}
2632*4882a593Smuzhiyun			$checklicenseline = 1;
2633*4882a593Smuzhiyun
2634*4882a593Smuzhiyun			if ($realfile !~ /^MAINTAINERS/) {
2635*4882a593Smuzhiyun				my $last_binding_patch = $is_binding_patch;
2636*4882a593Smuzhiyun
2637*4882a593Smuzhiyun				$is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@;
2638*4882a593Smuzhiyun
2639*4882a593Smuzhiyun				if (($last_binding_patch != -1) &&
2640*4882a593Smuzhiyun				    ($last_binding_patch ^ $is_binding_patch)) {
2641*4882a593Smuzhiyun					WARN("DT_SPLIT_BINDING_PATCH",
2642*4882a593Smuzhiyun					     "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.rst\n");
2643*4882a593Smuzhiyun				}
2644*4882a593Smuzhiyun			}
2645*4882a593Smuzhiyun
2646*4882a593Smuzhiyun			next;
2647*4882a593Smuzhiyun		}
2648*4882a593Smuzhiyun
2649*4882a593Smuzhiyun		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
2650*4882a593Smuzhiyun
2651*4882a593Smuzhiyun		my $hereline = "$here\n$rawline\n";
2652*4882a593Smuzhiyun		my $herecurr = "$here\n$rawline\n";
2653*4882a593Smuzhiyun		my $hereprev = "$here\n$prevrawline\n$rawline\n";
2654*4882a593Smuzhiyun
2655*4882a593Smuzhiyun		$cnt_lines++ if ($realcnt != 0);
2656*4882a593Smuzhiyun
2657*4882a593Smuzhiyun# Verify the existence of a commit log if appropriate
2658*4882a593Smuzhiyun# 2 is used because a $signature is counted in $commit_log_lines
2659*4882a593Smuzhiyun		if ($in_commit_log) {
2660*4882a593Smuzhiyun			if ($line !~ /^\s*$/) {
2661*4882a593Smuzhiyun				$commit_log_lines++;	#could be a $signature
2662*4882a593Smuzhiyun			}
2663*4882a593Smuzhiyun		} elsif ($has_commit_log && $commit_log_lines < 2) {
2664*4882a593Smuzhiyun			WARN("COMMIT_MESSAGE",
2665*4882a593Smuzhiyun			     "Missing commit description - Add an appropriate one\n");
2666*4882a593Smuzhiyun			$commit_log_lines = 2;	#warn only once
2667*4882a593Smuzhiyun		}
2668*4882a593Smuzhiyun
2669*4882a593Smuzhiyun# Check if the commit log has what seems like a diff which can confuse patch
2670*4882a593Smuzhiyun		if ($in_commit_log && !$commit_log_has_diff &&
2671*4882a593Smuzhiyun		    (($line =~ m@^\s+diff\b.*a/([\w/]+)@ &&
2672*4882a593Smuzhiyun		      $line =~ m@^\s+diff\b.*a/[\w/]+\s+b/$1\b@) ||
2673*4882a593Smuzhiyun		     $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ ||
2674*4882a593Smuzhiyun		     $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) {
2675*4882a593Smuzhiyun			ERROR("DIFF_IN_COMMIT_MSG",
2676*4882a593Smuzhiyun			      "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr);
2677*4882a593Smuzhiyun			$commit_log_has_diff = 1;
2678*4882a593Smuzhiyun		}
2679*4882a593Smuzhiyun
2680*4882a593Smuzhiyun# Check for incorrect file permissions
2681*4882a593Smuzhiyun		if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
2682*4882a593Smuzhiyun			my $permhere = $here . "FILE: $realfile\n";
2683*4882a593Smuzhiyun			if ($realfile !~ m@scripts/@ &&
2684*4882a593Smuzhiyun			    $realfile !~ /\.(py|pl|awk|sh)$/) {
2685*4882a593Smuzhiyun				ERROR("EXECUTE_PERMISSIONS",
2686*4882a593Smuzhiyun				      "do not set execute permissions for source files\n" . $permhere);
2687*4882a593Smuzhiyun			}
2688*4882a593Smuzhiyun		}
2689*4882a593Smuzhiyun
2690*4882a593Smuzhiyun# Check the patch for a From:
2691*4882a593Smuzhiyun		if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
2692*4882a593Smuzhiyun			$author = $1;
2693*4882a593Smuzhiyun			my $curline = $linenr;
2694*4882a593Smuzhiyun			while(defined($rawlines[$curline]) && ($rawlines[$curline++] =~ /^[ \t]\s*(.*)/)) {
2695*4882a593Smuzhiyun				$author .= $1;
2696*4882a593Smuzhiyun			}
2697*4882a593Smuzhiyun			$author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
2698*4882a593Smuzhiyun			$author =~ s/"//g;
2699*4882a593Smuzhiyun			$author = reformat_email($author);
2700*4882a593Smuzhiyun		}
2701*4882a593Smuzhiyun
2702*4882a593Smuzhiyun# Check the patch for a signoff:
2703*4882a593Smuzhiyun		if ($line =~ /^\s*signed-off-by:\s*(.*)/i) {
2704*4882a593Smuzhiyun			$signoff++;
2705*4882a593Smuzhiyun			$in_commit_log = 0;
2706*4882a593Smuzhiyun			if ($author ne ''  && $authorsignoff != 1) {
2707*4882a593Smuzhiyun				if (same_email_addresses($1, $author, 1)) {
2708*4882a593Smuzhiyun					$authorsignoff = 1;
2709*4882a593Smuzhiyun				} else {
2710*4882a593Smuzhiyun					my $ctx = $1;
2711*4882a593Smuzhiyun					my ($email_name, $email_comment, $email_address, $comment1) = parse_email($ctx);
2712*4882a593Smuzhiyun					my ($author_name, $author_comment, $author_address, $comment2) = parse_email($author);
2713*4882a593Smuzhiyun
2714*4882a593Smuzhiyun					if ($email_address eq $author_address && $email_name eq $author_name) {
2715*4882a593Smuzhiyun						$author_sob = $ctx;
2716*4882a593Smuzhiyun						$authorsignoff = 2;
2717*4882a593Smuzhiyun					} elsif ($email_address eq $author_address) {
2718*4882a593Smuzhiyun						$author_sob = $ctx;
2719*4882a593Smuzhiyun						$authorsignoff = 3;
2720*4882a593Smuzhiyun					} elsif ($email_name eq $author_name) {
2721*4882a593Smuzhiyun						$author_sob = $ctx;
2722*4882a593Smuzhiyun						$authorsignoff = 4;
2723*4882a593Smuzhiyun
2724*4882a593Smuzhiyun						my $address1 = $email_address;
2725*4882a593Smuzhiyun						my $address2 = $author_address;
2726*4882a593Smuzhiyun
2727*4882a593Smuzhiyun						if ($address1 =~ /(\S+)\+\S+(\@.*)/) {
2728*4882a593Smuzhiyun							$address1 = "$1$2";
2729*4882a593Smuzhiyun						}
2730*4882a593Smuzhiyun						if ($address2 =~ /(\S+)\+\S+(\@.*)/) {
2731*4882a593Smuzhiyun							$address2 = "$1$2";
2732*4882a593Smuzhiyun						}
2733*4882a593Smuzhiyun						if ($address1 eq $address2) {
2734*4882a593Smuzhiyun							$authorsignoff = 5;
2735*4882a593Smuzhiyun						}
2736*4882a593Smuzhiyun					}
2737*4882a593Smuzhiyun				}
2738*4882a593Smuzhiyun			}
2739*4882a593Smuzhiyun		}
2740*4882a593Smuzhiyun
2741*4882a593Smuzhiyun# Check for patch separator
2742*4882a593Smuzhiyun		if ($line =~ /^---$/) {
2743*4882a593Smuzhiyun			$has_patch_separator = 1;
2744*4882a593Smuzhiyun			$in_commit_log = 0;
2745*4882a593Smuzhiyun		}
2746*4882a593Smuzhiyun
2747*4882a593Smuzhiyun# Check if MAINTAINERS is being updated.  If so, there's probably no need to
2748*4882a593Smuzhiyun# emit the "does MAINTAINERS need updating?" message on file add/move/delete
2749*4882a593Smuzhiyun		if ($line =~ /^\s*MAINTAINERS\s*\|/) {
2750*4882a593Smuzhiyun			$reported_maintainer_file = 1;
2751*4882a593Smuzhiyun		}
2752*4882a593Smuzhiyun
2753*4882a593Smuzhiyun# Check signature styles
2754*4882a593Smuzhiyun		if (!$in_header_lines &&
2755*4882a593Smuzhiyun		    $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
2756*4882a593Smuzhiyun			my $space_before = $1;
2757*4882a593Smuzhiyun			my $sign_off = $2;
2758*4882a593Smuzhiyun			my $space_after = $3;
2759*4882a593Smuzhiyun			my $email = $4;
2760*4882a593Smuzhiyun			my $ucfirst_sign_off = ucfirst(lc($sign_off));
2761*4882a593Smuzhiyun
2762*4882a593Smuzhiyun			if ($sign_off !~ /$signature_tags/) {
2763*4882a593Smuzhiyun				WARN("BAD_SIGN_OFF",
2764*4882a593Smuzhiyun				     "Non-standard signature: $sign_off\n" . $herecurr);
2765*4882a593Smuzhiyun			}
2766*4882a593Smuzhiyun			if (defined $space_before && $space_before ne "") {
2767*4882a593Smuzhiyun				if (WARN("BAD_SIGN_OFF",
2768*4882a593Smuzhiyun					 "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
2769*4882a593Smuzhiyun				    $fix) {
2770*4882a593Smuzhiyun					$fixed[$fixlinenr] =
2771*4882a593Smuzhiyun					    "$ucfirst_sign_off $email";
2772*4882a593Smuzhiyun				}
2773*4882a593Smuzhiyun			}
2774*4882a593Smuzhiyun			if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
2775*4882a593Smuzhiyun				if (WARN("BAD_SIGN_OFF",
2776*4882a593Smuzhiyun					 "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
2777*4882a593Smuzhiyun				    $fix) {
2778*4882a593Smuzhiyun					$fixed[$fixlinenr] =
2779*4882a593Smuzhiyun					    "$ucfirst_sign_off $email";
2780*4882a593Smuzhiyun				}
2781*4882a593Smuzhiyun
2782*4882a593Smuzhiyun			}
2783*4882a593Smuzhiyun			if (!defined $space_after || $space_after ne " ") {
2784*4882a593Smuzhiyun				if (WARN("BAD_SIGN_OFF",
2785*4882a593Smuzhiyun					 "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
2786*4882a593Smuzhiyun				    $fix) {
2787*4882a593Smuzhiyun					$fixed[$fixlinenr] =
2788*4882a593Smuzhiyun					    "$ucfirst_sign_off $email";
2789*4882a593Smuzhiyun				}
2790*4882a593Smuzhiyun			}
2791*4882a593Smuzhiyun
2792*4882a593Smuzhiyun			my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
2793*4882a593Smuzhiyun			my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment));
2794*4882a593Smuzhiyun			if ($suggested_email eq "") {
2795*4882a593Smuzhiyun				ERROR("BAD_SIGN_OFF",
2796*4882a593Smuzhiyun				      "Unrecognized email address: '$email'\n" . $herecurr);
2797*4882a593Smuzhiyun			} else {
2798*4882a593Smuzhiyun				my $dequoted = $suggested_email;
2799*4882a593Smuzhiyun				$dequoted =~ s/^"//;
2800*4882a593Smuzhiyun				$dequoted =~ s/" </ </;
2801*4882a593Smuzhiyun				# Don't force email to have quotes
2802*4882a593Smuzhiyun				# Allow just an angle bracketed address
2803*4882a593Smuzhiyun				if (!same_email_addresses($email, $suggested_email, 0)) {
2804*4882a593Smuzhiyun					WARN("BAD_SIGN_OFF",
2805*4882a593Smuzhiyun					     "email address '$email' might be better as '$suggested_email'\n" . $herecurr);
2806*4882a593Smuzhiyun				}
2807*4882a593Smuzhiyun			}
2808*4882a593Smuzhiyun
2809*4882a593Smuzhiyun# Check for duplicate signatures
2810*4882a593Smuzhiyun			my $sig_nospace = $line;
2811*4882a593Smuzhiyun			$sig_nospace =~ s/\s//g;
2812*4882a593Smuzhiyun			$sig_nospace = lc($sig_nospace);
2813*4882a593Smuzhiyun			if (defined $signatures{$sig_nospace}) {
2814*4882a593Smuzhiyun				WARN("BAD_SIGN_OFF",
2815*4882a593Smuzhiyun				     "Duplicate signature\n" . $herecurr);
2816*4882a593Smuzhiyun			} else {
2817*4882a593Smuzhiyun				$signatures{$sig_nospace} = 1;
2818*4882a593Smuzhiyun			}
2819*4882a593Smuzhiyun
2820*4882a593Smuzhiyun# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
2821*4882a593Smuzhiyun			if ($sign_off =~ /^co-developed-by:$/i) {
2822*4882a593Smuzhiyun				if ($email eq $author) {
2823*4882a593Smuzhiyun					WARN("BAD_SIGN_OFF",
2824*4882a593Smuzhiyun					      "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
2825*4882a593Smuzhiyun				}
2826*4882a593Smuzhiyun				if (!defined $lines[$linenr]) {
2827*4882a593Smuzhiyun					WARN("BAD_SIGN_OFF",
2828*4882a593Smuzhiyun                                             "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
2829*4882a593Smuzhiyun				} elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
2830*4882a593Smuzhiyun					WARN("BAD_SIGN_OFF",
2831*4882a593Smuzhiyun					     "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
2832*4882a593Smuzhiyun				} elsif ($1 ne $email) {
2833*4882a593Smuzhiyun					WARN("BAD_SIGN_OFF",
2834*4882a593Smuzhiyun					     "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
2835*4882a593Smuzhiyun				}
2836*4882a593Smuzhiyun			}
2837*4882a593Smuzhiyun		}
2838*4882a593Smuzhiyun
2839*4882a593Smuzhiyun# Check email subject for common tools that don't need to be mentioned
2840*4882a593Smuzhiyun		if ($in_header_lines &&
2841*4882a593Smuzhiyun		    $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) {
2842*4882a593Smuzhiyun			WARN("EMAIL_SUBJECT",
2843*4882a593Smuzhiyun			     "A patch subject line should describe the change not the tool that found it\n" . $herecurr);
2844*4882a593Smuzhiyun		}
2845*4882a593Smuzhiyun
2846*4882a593Smuzhiyun# Check for Gerrit Change-Ids not in any patch context
2847*4882a593Smuzhiyun		if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
2848*4882a593Smuzhiyun			ERROR("GERRIT_CHANGE_ID",
2849*4882a593Smuzhiyun			      "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
2850*4882a593Smuzhiyun		}
2851*4882a593Smuzhiyun
2852*4882a593Smuzhiyun# Check if the commit log is in a possible stack dump
2853*4882a593Smuzhiyun		if ($in_commit_log && !$commit_log_possible_stack_dump &&
2854*4882a593Smuzhiyun		    ($line =~ /^\s*(?:WARNING:|BUG:)/ ||
2855*4882a593Smuzhiyun		     $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
2856*4882a593Smuzhiyun					# timestamp
2857*4882a593Smuzhiyun		     $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
2858*4882a593Smuzhiyun		     $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
2859*4882a593Smuzhiyun		     $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
2860*4882a593Smuzhiyun					# stack dump address styles
2861*4882a593Smuzhiyun			$commit_log_possible_stack_dump = 1;
2862*4882a593Smuzhiyun		}
2863*4882a593Smuzhiyun
2864*4882a593Smuzhiyun# Check for line lengths > 75 in commit log, warn once
2865*4882a593Smuzhiyun		if ($in_commit_log && !$commit_log_long_line &&
2866*4882a593Smuzhiyun		    length($line) > 75 &&
2867*4882a593Smuzhiyun		    !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
2868*4882a593Smuzhiyun					# file delta changes
2869*4882a593Smuzhiyun		      $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
2870*4882a593Smuzhiyun					# filename then :
2871*4882a593Smuzhiyun		      $line =~ /^\s*(?:Fixes:|Link:)/i ||
2872*4882a593Smuzhiyun					# A Fixes: or Link: line
2873*4882a593Smuzhiyun		      $commit_log_possible_stack_dump)) {
2874*4882a593Smuzhiyun			WARN("COMMIT_LOG_LONG_LINE",
2875*4882a593Smuzhiyun			     "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
2876*4882a593Smuzhiyun			$commit_log_long_line = 1;
2877*4882a593Smuzhiyun		}
2878*4882a593Smuzhiyun
2879*4882a593Smuzhiyun# Reset possible stack dump if a blank line is found
2880*4882a593Smuzhiyun		if ($in_commit_log && $commit_log_possible_stack_dump &&
2881*4882a593Smuzhiyun		    $line =~ /^\s*$/) {
2882*4882a593Smuzhiyun			$commit_log_possible_stack_dump = 0;
2883*4882a593Smuzhiyun		}
2884*4882a593Smuzhiyun
2885*4882a593Smuzhiyun# Check for git id commit length and improperly formed commit descriptions
2886*4882a593Smuzhiyun		if ($in_commit_log && !$commit_log_possible_stack_dump &&
2887*4882a593Smuzhiyun		    $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
2888*4882a593Smuzhiyun		    $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
2889*4882a593Smuzhiyun		    ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
2890*4882a593Smuzhiyun		     ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
2891*4882a593Smuzhiyun		      $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
2892*4882a593Smuzhiyun		      $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
2893*4882a593Smuzhiyun			my $init_char = "c";
2894*4882a593Smuzhiyun			my $orig_commit = "";
2895*4882a593Smuzhiyun			my $short = 1;
2896*4882a593Smuzhiyun			my $long = 0;
2897*4882a593Smuzhiyun			my $case = 1;
2898*4882a593Smuzhiyun			my $space = 1;
2899*4882a593Smuzhiyun			my $hasdesc = 0;
2900*4882a593Smuzhiyun			my $hasparens = 0;
2901*4882a593Smuzhiyun			my $id = '0123456789ab';
2902*4882a593Smuzhiyun			my $orig_desc = "commit description";
2903*4882a593Smuzhiyun			my $description = "";
2904*4882a593Smuzhiyun
2905*4882a593Smuzhiyun			if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
2906*4882a593Smuzhiyun				$init_char = $1;
2907*4882a593Smuzhiyun				$orig_commit = lc($2);
2908*4882a593Smuzhiyun			} elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) {
2909*4882a593Smuzhiyun				$orig_commit = lc($1);
2910*4882a593Smuzhiyun			}
2911*4882a593Smuzhiyun
2912*4882a593Smuzhiyun			$short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i);
2913*4882a593Smuzhiyun			$long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i);
2914*4882a593Smuzhiyun			$space = 0 if ($line =~ /\bcommit [0-9a-f]/i);
2915*4882a593Smuzhiyun			$case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
2916*4882a593Smuzhiyun			if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) {
2917*4882a593Smuzhiyun				$orig_desc = $1;
2918*4882a593Smuzhiyun				$hasparens = 1;
2919*4882a593Smuzhiyun			} elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i &&
2920*4882a593Smuzhiyun				 defined $rawlines[$linenr] &&
2921*4882a593Smuzhiyun				 $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) {
2922*4882a593Smuzhiyun				$orig_desc = $1;
2923*4882a593Smuzhiyun				$hasparens = 1;
2924*4882a593Smuzhiyun			} elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i &&
2925*4882a593Smuzhiyun				 defined $rawlines[$linenr] &&
2926*4882a593Smuzhiyun				 $rawlines[$linenr] =~ /^\s*[^"]+"\)/) {
2927*4882a593Smuzhiyun				$line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i;
2928*4882a593Smuzhiyun				$orig_desc = $1;
2929*4882a593Smuzhiyun				$rawlines[$linenr] =~ /^\s*([^"]+)"\)/;
2930*4882a593Smuzhiyun				$orig_desc .= " " . $1;
2931*4882a593Smuzhiyun				$hasparens = 1;
2932*4882a593Smuzhiyun			}
2933*4882a593Smuzhiyun
2934*4882a593Smuzhiyun			($id, $description) = git_commit_info($orig_commit,
2935*4882a593Smuzhiyun							      $id, $orig_desc);
2936*4882a593Smuzhiyun
2937*4882a593Smuzhiyun			if (defined($id) &&
2938*4882a593Smuzhiyun			   ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) {
2939*4882a593Smuzhiyun				ERROR("GIT_COMMIT_ID",
2940*4882a593Smuzhiyun				      "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr);
2941*4882a593Smuzhiyun			}
2942*4882a593Smuzhiyun		}
2943*4882a593Smuzhiyun
2944*4882a593Smuzhiyun# Check for added, moved or deleted files
2945*4882a593Smuzhiyun		if (!$reported_maintainer_file && !$in_commit_log &&
2946*4882a593Smuzhiyun		    ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
2947*4882a593Smuzhiyun		     $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
2948*4882a593Smuzhiyun		     ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
2949*4882a593Smuzhiyun		      (defined($1) || defined($2))))) {
2950*4882a593Smuzhiyun			$is_patch = 1;
2951*4882a593Smuzhiyun			$reported_maintainer_file = 1;
2952*4882a593Smuzhiyun			WARN("FILE_PATH_CHANGES",
2953*4882a593Smuzhiyun			     "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
2954*4882a593Smuzhiyun		}
2955*4882a593Smuzhiyun
2956*4882a593Smuzhiyun# Check for adding new DT bindings not in schema format
2957*4882a593Smuzhiyun		if (!$in_commit_log &&
2958*4882a593Smuzhiyun		    ($line =~ /^new file mode\s*\d+\s*$/) &&
2959*4882a593Smuzhiyun		    ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
2960*4882a593Smuzhiyun			WARN("DT_SCHEMA_BINDING_PATCH",
2961*4882a593Smuzhiyun			     "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n");
2962*4882a593Smuzhiyun		}
2963*4882a593Smuzhiyun
2964*4882a593Smuzhiyun# Check for wrappage within a valid hunk of the file
2965*4882a593Smuzhiyun		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
2966*4882a593Smuzhiyun			ERROR("CORRUPTED_PATCH",
2967*4882a593Smuzhiyun			      "patch seems to be corrupt (line wrapped?)\n" .
2968*4882a593Smuzhiyun				$herecurr) if (!$emitted_corrupt++);
2969*4882a593Smuzhiyun		}
2970*4882a593Smuzhiyun
2971*4882a593Smuzhiyun# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
2972*4882a593Smuzhiyun		if (($realfile =~ /^$/ || $line =~ /^\+/) &&
2973*4882a593Smuzhiyun		    $rawline !~ m/^$UTF8*$/) {
2974*4882a593Smuzhiyun			my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
2975*4882a593Smuzhiyun
2976*4882a593Smuzhiyun			my $blank = copy_spacing($rawline);
2977*4882a593Smuzhiyun			my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
2978*4882a593Smuzhiyun			my $hereptr = "$hereline$ptr\n";
2979*4882a593Smuzhiyun
2980*4882a593Smuzhiyun			CHK("INVALID_UTF8",
2981*4882a593Smuzhiyun			    "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
2982*4882a593Smuzhiyun		}
2983*4882a593Smuzhiyun
2984*4882a593Smuzhiyun# Check if it's the start of a commit log
2985*4882a593Smuzhiyun# (not a header line and we haven't seen the patch filename)
2986*4882a593Smuzhiyun		if ($in_header_lines && $realfile =~ /^$/ &&
2987*4882a593Smuzhiyun		    !($rawline =~ /^\s+(?:\S|$)/ ||
2988*4882a593Smuzhiyun		      $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) {
2989*4882a593Smuzhiyun			$in_header_lines = 0;
2990*4882a593Smuzhiyun			$in_commit_log = 1;
2991*4882a593Smuzhiyun			$has_commit_log = 1;
2992*4882a593Smuzhiyun		}
2993*4882a593Smuzhiyun
2994*4882a593Smuzhiyun# Check if there is UTF-8 in a commit log when a mail header has explicitly
2995*4882a593Smuzhiyun# declined it, i.e defined some charset where it is missing.
2996*4882a593Smuzhiyun		if ($in_header_lines &&
2997*4882a593Smuzhiyun		    $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
2998*4882a593Smuzhiyun		    $1 !~ /utf-8/i) {
2999*4882a593Smuzhiyun			$non_utf8_charset = 1;
3000*4882a593Smuzhiyun		}
3001*4882a593Smuzhiyun
3002*4882a593Smuzhiyun		if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
3003*4882a593Smuzhiyun		    $rawline =~ /$NON_ASCII_UTF8/) {
3004*4882a593Smuzhiyun			WARN("UTF8_BEFORE_PATCH",
3005*4882a593Smuzhiyun			    "8-bit UTF-8 used in possible commit log\n" . $herecurr);
3006*4882a593Smuzhiyun		}
3007*4882a593Smuzhiyun
3008*4882a593Smuzhiyun# Check for absolute kernel paths in commit message
3009*4882a593Smuzhiyun		if ($tree && $in_commit_log) {
3010*4882a593Smuzhiyun			while ($line =~ m{(?:^|\s)(/\S*)}g) {
3011*4882a593Smuzhiyun				my $file = $1;
3012*4882a593Smuzhiyun
3013*4882a593Smuzhiyun				if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
3014*4882a593Smuzhiyun				    check_absolute_file($1, $herecurr)) {
3015*4882a593Smuzhiyun					#
3016*4882a593Smuzhiyun				} else {
3017*4882a593Smuzhiyun					check_absolute_file($file, $herecurr);
3018*4882a593Smuzhiyun				}
3019*4882a593Smuzhiyun			}
3020*4882a593Smuzhiyun		}
3021*4882a593Smuzhiyun
3022*4882a593Smuzhiyun# Check for various typo / spelling mistakes
3023*4882a593Smuzhiyun		if (defined($misspellings) &&
3024*4882a593Smuzhiyun		    ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
3025*4882a593Smuzhiyun			while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
3026*4882a593Smuzhiyun				my $typo = $1;
3027*4882a593Smuzhiyun				my $typo_fix = $spelling_fix{lc($typo)};
3028*4882a593Smuzhiyun				$typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
3029*4882a593Smuzhiyun				$typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
3030*4882a593Smuzhiyun				my $msg_level = \&WARN;
3031*4882a593Smuzhiyun				$msg_level = \&CHK if ($file);
3032*4882a593Smuzhiyun				if (&{$msg_level}("TYPO_SPELLING",
3033*4882a593Smuzhiyun						  "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
3034*4882a593Smuzhiyun				    $fix) {
3035*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
3036*4882a593Smuzhiyun				}
3037*4882a593Smuzhiyun			}
3038*4882a593Smuzhiyun		}
3039*4882a593Smuzhiyun
3040*4882a593Smuzhiyun# check for invalid commit id
3041*4882a593Smuzhiyun		if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
3042*4882a593Smuzhiyun			my $id;
3043*4882a593Smuzhiyun			my $description;
3044*4882a593Smuzhiyun			($id, $description) = git_commit_info($2, undef, undef);
3045*4882a593Smuzhiyun			if (!defined($id)) {
3046*4882a593Smuzhiyun				WARN("UNKNOWN_COMMIT_ID",
3047*4882a593Smuzhiyun				     "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
3048*4882a593Smuzhiyun			}
3049*4882a593Smuzhiyun		}
3050*4882a593Smuzhiyun
3051*4882a593Smuzhiyun# check for repeated words separated by a single space
3052*4882a593Smuzhiyun		if ($rawline =~ /^\+/ || $in_commit_log) {
3053*4882a593Smuzhiyun			while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) {
3054*4882a593Smuzhiyun
3055*4882a593Smuzhiyun				my $first = $1;
3056*4882a593Smuzhiyun				my $second = $2;
3057*4882a593Smuzhiyun
3058*4882a593Smuzhiyun				if ($first =~ /(?:struct|union|enum)/) {
3059*4882a593Smuzhiyun					pos($rawline) += length($first) + length($second) + 1;
3060*4882a593Smuzhiyun					next;
3061*4882a593Smuzhiyun				}
3062*4882a593Smuzhiyun
3063*4882a593Smuzhiyun				next if ($first ne $second);
3064*4882a593Smuzhiyun				next if ($first eq 'long');
3065*4882a593Smuzhiyun
3066*4882a593Smuzhiyun				if (WARN("REPEATED_WORD",
3067*4882a593Smuzhiyun					 "Possible repeated word: '$first'\n" . $herecurr) &&
3068*4882a593Smuzhiyun				    $fix) {
3069*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\b$first $second\b/$first/;
3070*4882a593Smuzhiyun				}
3071*4882a593Smuzhiyun			}
3072*4882a593Smuzhiyun
3073*4882a593Smuzhiyun			# if it's a repeated word on consecutive lines in a comment block
3074*4882a593Smuzhiyun			if ($prevline =~ /$;+\s*$/ &&
3075*4882a593Smuzhiyun			    $prevrawline =~ /($word_pattern)\s*$/) {
3076*4882a593Smuzhiyun				my $last_word = $1;
3077*4882a593Smuzhiyun				if ($rawline =~ /^\+\s*\*\s*$last_word /) {
3078*4882a593Smuzhiyun					if (WARN("REPEATED_WORD",
3079*4882a593Smuzhiyun						 "Possible repeated word: '$last_word'\n" . $hereprev) &&
3080*4882a593Smuzhiyun					    $fix) {
3081*4882a593Smuzhiyun						$fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/;
3082*4882a593Smuzhiyun					}
3083*4882a593Smuzhiyun				}
3084*4882a593Smuzhiyun			}
3085*4882a593Smuzhiyun		}
3086*4882a593Smuzhiyun
3087*4882a593Smuzhiyun# ignore non-hunk lines and lines being removed
3088*4882a593Smuzhiyun		next if (!$hunk_line || $line =~ /^-/);
3089*4882a593Smuzhiyun
3090*4882a593Smuzhiyun#trailing whitespace
3091*4882a593Smuzhiyun		if ($line =~ /^\+.*\015/) {
3092*4882a593Smuzhiyun			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3093*4882a593Smuzhiyun			if (ERROR("DOS_LINE_ENDINGS",
3094*4882a593Smuzhiyun				  "DOS line endings\n" . $herevet) &&
3095*4882a593Smuzhiyun			    $fix) {
3096*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/[\s\015]+$//;
3097*4882a593Smuzhiyun			}
3098*4882a593Smuzhiyun		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
3099*4882a593Smuzhiyun			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3100*4882a593Smuzhiyun			if (ERROR("TRAILING_WHITESPACE",
3101*4882a593Smuzhiyun				  "trailing whitespace\n" . $herevet) &&
3102*4882a593Smuzhiyun			    $fix) {
3103*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\s+$//;
3104*4882a593Smuzhiyun			}
3105*4882a593Smuzhiyun
3106*4882a593Smuzhiyun			$rpt_cleaners = 1;
3107*4882a593Smuzhiyun		}
3108*4882a593Smuzhiyun
3109*4882a593Smuzhiyun# Check for FSF mailing addresses.
3110*4882a593Smuzhiyun		if ($rawline =~ /\bwrite to the Free/i ||
3111*4882a593Smuzhiyun		    $rawline =~ /\b675\s+Mass\s+Ave/i ||
3112*4882a593Smuzhiyun		    $rawline =~ /\b59\s+Temple\s+Pl/i ||
3113*4882a593Smuzhiyun		    $rawline =~ /\b51\s+Franklin\s+St/i) {
3114*4882a593Smuzhiyun			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3115*4882a593Smuzhiyun			my $msg_level = \&ERROR;
3116*4882a593Smuzhiyun			$msg_level = \&CHK if ($file);
3117*4882a593Smuzhiyun			&{$msg_level}("FSF_MAILING_ADDRESS",
3118*4882a593Smuzhiyun				      "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
3119*4882a593Smuzhiyun		}
3120*4882a593Smuzhiyun
3121*4882a593Smuzhiyun# check for Kconfig help text having a real description
3122*4882a593Smuzhiyun# Only applies when adding the entry originally, after that we do not have
3123*4882a593Smuzhiyun# sufficient context to determine whether it is indeed long enough.
3124*4882a593Smuzhiyun		if ($realfile =~ /Kconfig/ &&
3125*4882a593Smuzhiyun		    # 'choice' is usually the last thing on the line (though
3126*4882a593Smuzhiyun		    # Kconfig supports named choices), so use a word boundary
3127*4882a593Smuzhiyun		    # (\b) rather than a whitespace character (\s)
3128*4882a593Smuzhiyun		    $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
3129*4882a593Smuzhiyun			my $length = 0;
3130*4882a593Smuzhiyun			my $cnt = $realcnt;
3131*4882a593Smuzhiyun			my $ln = $linenr + 1;
3132*4882a593Smuzhiyun			my $f;
3133*4882a593Smuzhiyun			my $is_start = 0;
3134*4882a593Smuzhiyun			my $is_end = 0;
3135*4882a593Smuzhiyun			for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
3136*4882a593Smuzhiyun				$f = $lines[$ln - 1];
3137*4882a593Smuzhiyun				$cnt-- if ($lines[$ln - 1] !~ /^-/);
3138*4882a593Smuzhiyun				$is_end = $lines[$ln - 1] =~ /^\+/;
3139*4882a593Smuzhiyun
3140*4882a593Smuzhiyun				next if ($f =~ /^-/);
3141*4882a593Smuzhiyun				last if (!$file && $f =~ /^\@\@/);
3142*4882a593Smuzhiyun
3143*4882a593Smuzhiyun				if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
3144*4882a593Smuzhiyun					$is_start = 1;
3145*4882a593Smuzhiyun				} elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
3146*4882a593Smuzhiyun					$length = -1;
3147*4882a593Smuzhiyun				}
3148*4882a593Smuzhiyun
3149*4882a593Smuzhiyun				$f =~ s/^.//;
3150*4882a593Smuzhiyun				$f =~ s/#.*//;
3151*4882a593Smuzhiyun				$f =~ s/^\s+//;
3152*4882a593Smuzhiyun				next if ($f =~ /^$/);
3153*4882a593Smuzhiyun
3154*4882a593Smuzhiyun				# This only checks context lines in the patch
3155*4882a593Smuzhiyun				# and so hopefully shouldn't trigger false
3156*4882a593Smuzhiyun				# positives, even though some of these are
3157*4882a593Smuzhiyun				# common words in help texts
3158*4882a593Smuzhiyun				if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
3159*4882a593Smuzhiyun						  if|endif|menu|endmenu|source)\b/x) {
3160*4882a593Smuzhiyun					$is_end = 1;
3161*4882a593Smuzhiyun					last;
3162*4882a593Smuzhiyun				}
3163*4882a593Smuzhiyun				$length++;
3164*4882a593Smuzhiyun			}
3165*4882a593Smuzhiyun			if ($is_start && $is_end && $length < $min_conf_desc_length) {
3166*4882a593Smuzhiyun				WARN("CONFIG_DESCRIPTION",
3167*4882a593Smuzhiyun				     "please write a paragraph that describes the config symbol fully\n" . $herecurr);
3168*4882a593Smuzhiyun			}
3169*4882a593Smuzhiyun			#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
3170*4882a593Smuzhiyun		}
3171*4882a593Smuzhiyun
3172*4882a593Smuzhiyun# check MAINTAINERS entries
3173*4882a593Smuzhiyun		if ($realfile =~ /^MAINTAINERS$/) {
3174*4882a593Smuzhiyun# check MAINTAINERS entries for the right form
3175*4882a593Smuzhiyun			if ($rawline =~ /^\+[A-Z]:/ &&
3176*4882a593Smuzhiyun			    $rawline !~ /^\+[A-Z]:\t\S/) {
3177*4882a593Smuzhiyun				if (WARN("MAINTAINERS_STYLE",
3178*4882a593Smuzhiyun					 "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) &&
3179*4882a593Smuzhiyun				    $fix) {
3180*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
3181*4882a593Smuzhiyun				}
3182*4882a593Smuzhiyun			}
3183*4882a593Smuzhiyun# check MAINTAINERS entries for the right ordering too
3184*4882a593Smuzhiyun			my $preferred_order = 'MRLSWQBCPTFXNK';
3185*4882a593Smuzhiyun			if ($rawline =~ /^\+[A-Z]:/ &&
3186*4882a593Smuzhiyun			    $prevrawline =~ /^[\+ ][A-Z]:/) {
3187*4882a593Smuzhiyun				$rawline =~ /^\+([A-Z]):\s*(.*)/;
3188*4882a593Smuzhiyun				my $cur = $1;
3189*4882a593Smuzhiyun				my $curval = $2;
3190*4882a593Smuzhiyun				$prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/;
3191*4882a593Smuzhiyun				my $prev = $1;
3192*4882a593Smuzhiyun				my $prevval = $2;
3193*4882a593Smuzhiyun				my $curindex = index($preferred_order, $cur);
3194*4882a593Smuzhiyun				my $previndex = index($preferred_order, $prev);
3195*4882a593Smuzhiyun				if ($curindex < 0) {
3196*4882a593Smuzhiyun					WARN("MAINTAINERS_STYLE",
3197*4882a593Smuzhiyun					     "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr);
3198*4882a593Smuzhiyun				} else {
3199*4882a593Smuzhiyun					if ($previndex >= 0 && $curindex < $previndex) {
3200*4882a593Smuzhiyun						WARN("MAINTAINERS_STYLE",
3201*4882a593Smuzhiyun						     "Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n" . $hereprev);
3202*4882a593Smuzhiyun					} elsif ((($prev eq 'F' && $cur eq 'F') ||
3203*4882a593Smuzhiyun						  ($prev eq 'X' && $cur eq 'X')) &&
3204*4882a593Smuzhiyun						 ($prevval cmp $curval) > 0) {
3205*4882a593Smuzhiyun						WARN("MAINTAINERS_STYLE",
3206*4882a593Smuzhiyun						     "Misordered MAINTAINERS entry - list file patterns in alphabetic order\n" . $hereprev);
3207*4882a593Smuzhiyun					}
3208*4882a593Smuzhiyun				}
3209*4882a593Smuzhiyun			}
3210*4882a593Smuzhiyun		}
3211*4882a593Smuzhiyun
3212*4882a593Smuzhiyun# discourage the use of boolean for type definition attributes of Kconfig options
3213*4882a593Smuzhiyun		if ($realfile =~ /Kconfig/ &&
3214*4882a593Smuzhiyun		    $line =~ /^\+\s*\bboolean\b/) {
3215*4882a593Smuzhiyun			WARN("CONFIG_TYPE_BOOLEAN",
3216*4882a593Smuzhiyun			     "Use of boolean is deprecated, please use bool instead.\n" . $herecurr);
3217*4882a593Smuzhiyun		}
3218*4882a593Smuzhiyun
3219*4882a593Smuzhiyun		if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
3220*4882a593Smuzhiyun		    ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
3221*4882a593Smuzhiyun			my $flag = $1;
3222*4882a593Smuzhiyun			my $replacement = {
3223*4882a593Smuzhiyun				'EXTRA_AFLAGS' =>   'asflags-y',
3224*4882a593Smuzhiyun				'EXTRA_CFLAGS' =>   'ccflags-y',
3225*4882a593Smuzhiyun				'EXTRA_CPPFLAGS' => 'cppflags-y',
3226*4882a593Smuzhiyun				'EXTRA_LDFLAGS' =>  'ldflags-y',
3227*4882a593Smuzhiyun			};
3228*4882a593Smuzhiyun
3229*4882a593Smuzhiyun			WARN("DEPRECATED_VARIABLE",
3230*4882a593Smuzhiyun			     "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
3231*4882a593Smuzhiyun		}
3232*4882a593Smuzhiyun
3233*4882a593Smuzhiyun# check for DT compatible documentation
3234*4882a593Smuzhiyun		if (defined $root &&
3235*4882a593Smuzhiyun			(($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
3236*4882a593Smuzhiyun			 ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) {
3237*4882a593Smuzhiyun
3238*4882a593Smuzhiyun			my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
3239*4882a593Smuzhiyun
3240*4882a593Smuzhiyun			my $dt_path = $root . "/Documentation/devicetree/bindings/";
3241*4882a593Smuzhiyun			my $vp_file = $dt_path . "vendor-prefixes.yaml";
3242*4882a593Smuzhiyun
3243*4882a593Smuzhiyun			foreach my $compat (@compats) {
3244*4882a593Smuzhiyun				my $compat2 = $compat;
3245*4882a593Smuzhiyun				$compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/;
3246*4882a593Smuzhiyun				my $compat3 = $compat;
3247*4882a593Smuzhiyun				$compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/;
3248*4882a593Smuzhiyun				`grep -Erq "$compat|$compat2|$compat3" $dt_path`;
3249*4882a593Smuzhiyun				if ( $? >> 8 ) {
3250*4882a593Smuzhiyun					WARN("UNDOCUMENTED_DT_STRING",
3251*4882a593Smuzhiyun					     "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
3252*4882a593Smuzhiyun				}
3253*4882a593Smuzhiyun
3254*4882a593Smuzhiyun				next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
3255*4882a593Smuzhiyun				my $vendor = $1;
3256*4882a593Smuzhiyun				`grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`;
3257*4882a593Smuzhiyun				if ( $? >> 8 ) {
3258*4882a593Smuzhiyun					WARN("UNDOCUMENTED_DT_STRING",
3259*4882a593Smuzhiyun					     "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
3260*4882a593Smuzhiyun				}
3261*4882a593Smuzhiyun			}
3262*4882a593Smuzhiyun		}
3263*4882a593Smuzhiyun
3264*4882a593Smuzhiyun# check for using SPDX license tag at beginning of files
3265*4882a593Smuzhiyun		if ($realline == $checklicenseline) {
3266*4882a593Smuzhiyun			if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
3267*4882a593Smuzhiyun				$checklicenseline = 2;
3268*4882a593Smuzhiyun			} elsif ($rawline =~ /^\+/) {
3269*4882a593Smuzhiyun				my $comment = "";
3270*4882a593Smuzhiyun				if ($realfile =~ /\.(h|s|S)$/) {
3271*4882a593Smuzhiyun					$comment = '/*';
3272*4882a593Smuzhiyun				} elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
3273*4882a593Smuzhiyun					$comment = '//';
3274*4882a593Smuzhiyun				} elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
3275*4882a593Smuzhiyun					$comment = '#';
3276*4882a593Smuzhiyun				} elsif ($realfile =~ /\.rst$/) {
3277*4882a593Smuzhiyun					$comment = '..';
3278*4882a593Smuzhiyun				}
3279*4882a593Smuzhiyun
3280*4882a593Smuzhiyun# check SPDX comment style for .[chsS] files
3281*4882a593Smuzhiyun				if ($realfile =~ /\.[chsS]$/ &&
3282*4882a593Smuzhiyun				    $rawline =~ /SPDX-License-Identifier:/ &&
3283*4882a593Smuzhiyun				    $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
3284*4882a593Smuzhiyun					WARN("SPDX_LICENSE_TAG",
3285*4882a593Smuzhiyun					     "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
3286*4882a593Smuzhiyun				}
3287*4882a593Smuzhiyun
3288*4882a593Smuzhiyun				if ($comment !~ /^$/ &&
3289*4882a593Smuzhiyun				    $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
3290*4882a593Smuzhiyun					WARN("SPDX_LICENSE_TAG",
3291*4882a593Smuzhiyun					     "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
3292*4882a593Smuzhiyun				} elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
3293*4882a593Smuzhiyun					my $spdx_license = $1;
3294*4882a593Smuzhiyun					if (!is_SPDX_License_valid($spdx_license)) {
3295*4882a593Smuzhiyun						WARN("SPDX_LICENSE_TAG",
3296*4882a593Smuzhiyun						     "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
3297*4882a593Smuzhiyun					}
3298*4882a593Smuzhiyun					if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
3299*4882a593Smuzhiyun					    not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
3300*4882a593Smuzhiyun						my $msg_level = \&WARN;
3301*4882a593Smuzhiyun						$msg_level = \&CHK if ($file);
3302*4882a593Smuzhiyun						if (&{$msg_level}("SPDX_LICENSE_TAG",
3303*4882a593Smuzhiyun
3304*4882a593Smuzhiyun								  "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) &&
3305*4882a593Smuzhiyun						    $fix) {
3306*4882a593Smuzhiyun							$fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
3307*4882a593Smuzhiyun						}
3308*4882a593Smuzhiyun					}
3309*4882a593Smuzhiyun				}
3310*4882a593Smuzhiyun			}
3311*4882a593Smuzhiyun		}
3312*4882a593Smuzhiyun
3313*4882a593Smuzhiyun# check for embedded filenames
3314*4882a593Smuzhiyun		if ($rawline =~ /^\+.*\Q$realfile\E/) {
3315*4882a593Smuzhiyun			WARN("EMBEDDED_FILENAME",
3316*4882a593Smuzhiyun			     "It's generally not useful to have the filename in the file\n" . $herecurr);
3317*4882a593Smuzhiyun		}
3318*4882a593Smuzhiyun
3319*4882a593Smuzhiyun# check we are in a valid source file if not then ignore this hunk
3320*4882a593Smuzhiyun		next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
3321*4882a593Smuzhiyun
3322*4882a593Smuzhiyun# check for using SPDX-License-Identifier on the wrong line number
3323*4882a593Smuzhiyun		if ($realline != $checklicenseline &&
3324*4882a593Smuzhiyun		    $rawline =~ /\bSPDX-License-Identifier:/ &&
3325*4882a593Smuzhiyun		    substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
3326*4882a593Smuzhiyun			WARN("SPDX_LICENSE_TAG",
3327*4882a593Smuzhiyun			     "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
3328*4882a593Smuzhiyun		}
3329*4882a593Smuzhiyun
3330*4882a593Smuzhiyun# line length limit (with some exclusions)
3331*4882a593Smuzhiyun#
3332*4882a593Smuzhiyun# There are a few types of lines that may extend beyond $max_line_length:
3333*4882a593Smuzhiyun#	logging functions like pr_info that end in a string
3334*4882a593Smuzhiyun#	lines with a single string
3335*4882a593Smuzhiyun#	#defines that are a single string
3336*4882a593Smuzhiyun#	lines with an RFC3986 like URL
3337*4882a593Smuzhiyun#
3338*4882a593Smuzhiyun# There are 3 different line length message types:
3339*4882a593Smuzhiyun# LONG_LINE_COMMENT	a comment starts before but extends beyond $max_line_length
3340*4882a593Smuzhiyun# LONG_LINE_STRING	a string starts before but extends beyond $max_line_length
3341*4882a593Smuzhiyun# LONG_LINE		all other lines longer than $max_line_length
3342*4882a593Smuzhiyun#
3343*4882a593Smuzhiyun# if LONG_LINE is ignored, the other 2 types are also ignored
3344*4882a593Smuzhiyun#
3345*4882a593Smuzhiyun
3346*4882a593Smuzhiyun		if ($line =~ /^\+/ && $length > $max_line_length) {
3347*4882a593Smuzhiyun			my $msg_type = "LONG_LINE";
3348*4882a593Smuzhiyun
3349*4882a593Smuzhiyun			# Check the allowed long line types first
3350*4882a593Smuzhiyun
3351*4882a593Smuzhiyun			# logging functions that end in a string that starts
3352*4882a593Smuzhiyun			# before $max_line_length
3353*4882a593Smuzhiyun			if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ &&
3354*4882a593Smuzhiyun			    length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3355*4882a593Smuzhiyun				$msg_type = "";
3356*4882a593Smuzhiyun
3357*4882a593Smuzhiyun			# lines with only strings (w/ possible termination)
3358*4882a593Smuzhiyun			# #defines with only strings
3359*4882a593Smuzhiyun			} elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
3360*4882a593Smuzhiyun				 $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
3361*4882a593Smuzhiyun				$msg_type = "";
3362*4882a593Smuzhiyun
3363*4882a593Smuzhiyun			# More special cases
3364*4882a593Smuzhiyun			} elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ ||
3365*4882a593Smuzhiyun				 $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) {
3366*4882a593Smuzhiyun				$msg_type = "";
3367*4882a593Smuzhiyun
3368*4882a593Smuzhiyun			# URL ($rawline is used in case the URL is in a comment)
3369*4882a593Smuzhiyun			} elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) {
3370*4882a593Smuzhiyun				$msg_type = "";
3371*4882a593Smuzhiyun
3372*4882a593Smuzhiyun			# Otherwise set the alternate message types
3373*4882a593Smuzhiyun
3374*4882a593Smuzhiyun			# a comment starts before $max_line_length
3375*4882a593Smuzhiyun			} elsif ($line =~ /($;[\s$;]*)$/ &&
3376*4882a593Smuzhiyun				 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3377*4882a593Smuzhiyun				$msg_type = "LONG_LINE_COMMENT"
3378*4882a593Smuzhiyun
3379*4882a593Smuzhiyun			# a quoted string starts before $max_line_length
3380*4882a593Smuzhiyun			} elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ &&
3381*4882a593Smuzhiyun				 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3382*4882a593Smuzhiyun				$msg_type = "LONG_LINE_STRING"
3383*4882a593Smuzhiyun			}
3384*4882a593Smuzhiyun
3385*4882a593Smuzhiyun			if ($msg_type ne "" &&
3386*4882a593Smuzhiyun			    (show_type("LONG_LINE") || show_type($msg_type))) {
3387*4882a593Smuzhiyun				my $msg_level = \&WARN;
3388*4882a593Smuzhiyun				$msg_level = \&CHK if ($file);
3389*4882a593Smuzhiyun				&{$msg_level}($msg_type,
3390*4882a593Smuzhiyun					      "line length of $length exceeds $max_line_length columns\n" . $herecurr);
3391*4882a593Smuzhiyun			}
3392*4882a593Smuzhiyun		}
3393*4882a593Smuzhiyun
3394*4882a593Smuzhiyun# check for adding lines without a newline.
3395*4882a593Smuzhiyun		if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
3396*4882a593Smuzhiyun			WARN("MISSING_EOF_NEWLINE",
3397*4882a593Smuzhiyun			     "adding a line without newline at end of file\n" . $herecurr);
3398*4882a593Smuzhiyun		}
3399*4882a593Smuzhiyun
3400*4882a593Smuzhiyun# check we are in a valid source file C or perl if not then ignore this hunk
3401*4882a593Smuzhiyun		next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
3402*4882a593Smuzhiyun
3403*4882a593Smuzhiyun# at the beginning of a line any tabs must come first and anything
3404*4882a593Smuzhiyun# more than $tabsize must use tabs.
3405*4882a593Smuzhiyun		if ($rawline =~ /^\+\s* \t\s*\S/ ||
3406*4882a593Smuzhiyun		    $rawline =~ /^\+\s*        \s*/) {
3407*4882a593Smuzhiyun			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3408*4882a593Smuzhiyun			$rpt_cleaners = 1;
3409*4882a593Smuzhiyun			if (ERROR("CODE_INDENT",
3410*4882a593Smuzhiyun				  "code indent should use tabs where possible\n" . $herevet) &&
3411*4882a593Smuzhiyun			    $fix) {
3412*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
3413*4882a593Smuzhiyun			}
3414*4882a593Smuzhiyun		}
3415*4882a593Smuzhiyun
3416*4882a593Smuzhiyun# check for space before tabs.
3417*4882a593Smuzhiyun		if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
3418*4882a593Smuzhiyun			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3419*4882a593Smuzhiyun			if (WARN("SPACE_BEFORE_TAB",
3420*4882a593Smuzhiyun				"please, no space before tabs\n" . $herevet) &&
3421*4882a593Smuzhiyun			    $fix) {
3422*4882a593Smuzhiyun				while ($fixed[$fixlinenr] =~
3423*4882a593Smuzhiyun					   s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {}
3424*4882a593Smuzhiyun				while ($fixed[$fixlinenr] =~
3425*4882a593Smuzhiyun					   s/(^\+.*) +\t/$1\t/) {}
3426*4882a593Smuzhiyun			}
3427*4882a593Smuzhiyun		}
3428*4882a593Smuzhiyun
3429*4882a593Smuzhiyun# check for assignments on the start of a line
3430*4882a593Smuzhiyun		if ($sline =~ /^\+\s+($Assignment)[^=]/) {
3431*4882a593Smuzhiyun			CHK("ASSIGNMENT_CONTINUATIONS",
3432*4882a593Smuzhiyun			    "Assignment operator '$1' should be on the previous line\n" . $hereprev);
3433*4882a593Smuzhiyun		}
3434*4882a593Smuzhiyun
3435*4882a593Smuzhiyun# check for && or || at the start of a line
3436*4882a593Smuzhiyun		if ($rawline =~ /^\+\s*(&&|\|\|)/) {
3437*4882a593Smuzhiyun			CHK("LOGICAL_CONTINUATIONS",
3438*4882a593Smuzhiyun			    "Logical continuations should be on the previous line\n" . $hereprev);
3439*4882a593Smuzhiyun		}
3440*4882a593Smuzhiyun
3441*4882a593Smuzhiyun# check indentation starts on a tab stop
3442*4882a593Smuzhiyun		if ($perl_version_ok &&
3443*4882a593Smuzhiyun		    $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
3444*4882a593Smuzhiyun			my $indent = length($1);
3445*4882a593Smuzhiyun			if ($indent % $tabsize) {
3446*4882a593Smuzhiyun				if (WARN("TABSTOP",
3447*4882a593Smuzhiyun					 "Statements should start on a tabstop\n" . $herecurr) &&
3448*4882a593Smuzhiyun				    $fix) {
3449*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e;
3450*4882a593Smuzhiyun				}
3451*4882a593Smuzhiyun			}
3452*4882a593Smuzhiyun		}
3453*4882a593Smuzhiyun
3454*4882a593Smuzhiyun# check multi-line statement indentation matches previous line
3455*4882a593Smuzhiyun		if ($perl_version_ok &&
3456*4882a593Smuzhiyun		    $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
3457*4882a593Smuzhiyun			$prevline =~ /^\+(\t*)(.*)$/;
3458*4882a593Smuzhiyun			my $oldindent = $1;
3459*4882a593Smuzhiyun			my $rest = $2;
3460*4882a593Smuzhiyun
3461*4882a593Smuzhiyun			my $pos = pos_last_openparen($rest);
3462*4882a593Smuzhiyun			if ($pos >= 0) {
3463*4882a593Smuzhiyun				$line =~ /^(\+| )([ \t]*)/;
3464*4882a593Smuzhiyun				my $newindent = $2;
3465*4882a593Smuzhiyun
3466*4882a593Smuzhiyun				my $goodtabindent = $oldindent .
3467*4882a593Smuzhiyun					"\t" x ($pos / $tabsize) .
3468*4882a593Smuzhiyun					" "  x ($pos % $tabsize);
3469*4882a593Smuzhiyun				my $goodspaceindent = $oldindent . " "  x $pos;
3470*4882a593Smuzhiyun
3471*4882a593Smuzhiyun				if ($newindent ne $goodtabindent &&
3472*4882a593Smuzhiyun				    $newindent ne $goodspaceindent) {
3473*4882a593Smuzhiyun
3474*4882a593Smuzhiyun					if (CHK("PARENTHESIS_ALIGNMENT",
3475*4882a593Smuzhiyun						"Alignment should match open parenthesis\n" . $hereprev) &&
3476*4882a593Smuzhiyun					    $fix && $line =~ /^\+/) {
3477*4882a593Smuzhiyun						$fixed[$fixlinenr] =~
3478*4882a593Smuzhiyun						    s/^\+[ \t]*/\+$goodtabindent/;
3479*4882a593Smuzhiyun					}
3480*4882a593Smuzhiyun				}
3481*4882a593Smuzhiyun			}
3482*4882a593Smuzhiyun		}
3483*4882a593Smuzhiyun
3484*4882a593Smuzhiyun# check for space after cast like "(int) foo" or "(struct foo) bar"
3485*4882a593Smuzhiyun# avoid checking a few false positives:
3486*4882a593Smuzhiyun#   "sizeof(<type>)" or "__alignof__(<type>)"
3487*4882a593Smuzhiyun#   function pointer declarations like "(*foo)(int) = bar;"
3488*4882a593Smuzhiyun#   structure definitions like "(struct foo) { 0 };"
3489*4882a593Smuzhiyun#   multiline macros that define functions
3490*4882a593Smuzhiyun#   known attributes or the __attribute__ keyword
3491*4882a593Smuzhiyun		if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ &&
3492*4882a593Smuzhiyun		    (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) {
3493*4882a593Smuzhiyun			if (CHK("SPACING",
3494*4882a593Smuzhiyun				"No space is necessary after a cast\n" . $herecurr) &&
3495*4882a593Smuzhiyun			    $fix) {
3496*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
3497*4882a593Smuzhiyun				    s/(\(\s*$Type\s*\))[ \t]+/$1/;
3498*4882a593Smuzhiyun			}
3499*4882a593Smuzhiyun		}
3500*4882a593Smuzhiyun
3501*4882a593Smuzhiyun# Block comment styles
3502*4882a593Smuzhiyun# Networking with an initial /*
3503*4882a593Smuzhiyun		if ($realfile =~ m@^(drivers/net/|net/)@ &&
3504*4882a593Smuzhiyun		    $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
3505*4882a593Smuzhiyun		    $rawline =~ /^\+[ \t]*\*/ &&
3506*4882a593Smuzhiyun		    $realline > 3) { # Do not warn about the initial copyright comment block after SPDX-License-Identifier
3507*4882a593Smuzhiyun			WARN("NETWORKING_BLOCK_COMMENT_STYLE",
3508*4882a593Smuzhiyun			     "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
3509*4882a593Smuzhiyun		}
3510*4882a593Smuzhiyun
3511*4882a593Smuzhiyun# Block comments use * on subsequent lines
3512*4882a593Smuzhiyun		if ($prevline =~ /$;[ \t]*$/ &&			#ends in comment
3513*4882a593Smuzhiyun		    $prevrawline =~ /^\+.*?\/\*/ &&		#starting /*
3514*4882a593Smuzhiyun		    $prevrawline !~ /\*\/[ \t]*$/ &&		#no trailing */
3515*4882a593Smuzhiyun		    $rawline =~ /^\+/ &&			#line is new
3516*4882a593Smuzhiyun		    $rawline !~ /^\+[ \t]*\*/) {		#no leading *
3517*4882a593Smuzhiyun			WARN("BLOCK_COMMENT_STYLE",
3518*4882a593Smuzhiyun			     "Block comments use * on subsequent lines\n" . $hereprev);
3519*4882a593Smuzhiyun		}
3520*4882a593Smuzhiyun
3521*4882a593Smuzhiyun# Block comments use */ on trailing lines
3522*4882a593Smuzhiyun		if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&	#trailing */
3523*4882a593Smuzhiyun		    $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&	#inline /*...*/
3524*4882a593Smuzhiyun		    $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&	#trailing **/
3525*4882a593Smuzhiyun		    $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {	#non blank */
3526*4882a593Smuzhiyun			WARN("BLOCK_COMMENT_STYLE",
3527*4882a593Smuzhiyun			     "Block comments use a trailing */ on a separate line\n" . $herecurr);
3528*4882a593Smuzhiyun		}
3529*4882a593Smuzhiyun
3530*4882a593Smuzhiyun# Block comment * alignment
3531*4882a593Smuzhiyun		if ($prevline =~ /$;[ \t]*$/ &&			#ends in comment
3532*4882a593Smuzhiyun		    $line =~ /^\+[ \t]*$;/ &&			#leading comment
3533*4882a593Smuzhiyun		    $rawline =~ /^\+[ \t]*\*/ &&		#leading *
3534*4882a593Smuzhiyun		    (($prevrawline =~ /^\+.*?\/\*/ &&		#leading /*
3535*4882a593Smuzhiyun		      $prevrawline !~ /\*\/[ \t]*$/) ||		#no trailing */
3536*4882a593Smuzhiyun		     $prevrawline =~ /^\+[ \t]*\*/)) {		#leading *
3537*4882a593Smuzhiyun			my $oldindent;
3538*4882a593Smuzhiyun			$prevrawline =~ m@^\+([ \t]*/?)\*@;
3539*4882a593Smuzhiyun			if (defined($1)) {
3540*4882a593Smuzhiyun				$oldindent = expand_tabs($1);
3541*4882a593Smuzhiyun			} else {
3542*4882a593Smuzhiyun				$prevrawline =~ m@^\+(.*/?)\*@;
3543*4882a593Smuzhiyun				$oldindent = expand_tabs($1);
3544*4882a593Smuzhiyun			}
3545*4882a593Smuzhiyun			$rawline =~ m@^\+([ \t]*)\*@;
3546*4882a593Smuzhiyun			my $newindent = $1;
3547*4882a593Smuzhiyun			$newindent = expand_tabs($newindent);
3548*4882a593Smuzhiyun			if (length($oldindent) ne length($newindent)) {
3549*4882a593Smuzhiyun				WARN("BLOCK_COMMENT_STYLE",
3550*4882a593Smuzhiyun				     "Block comments should align the * on each line\n" . $hereprev);
3551*4882a593Smuzhiyun			}
3552*4882a593Smuzhiyun		}
3553*4882a593Smuzhiyun
3554*4882a593Smuzhiyun# check for missing blank lines after struct/union declarations
3555*4882a593Smuzhiyun# with exceptions for various attributes and macros
3556*4882a593Smuzhiyun		if ($prevline =~ /^[\+ ]};?\s*$/ &&
3557*4882a593Smuzhiyun		    $line =~ /^\+/ &&
3558*4882a593Smuzhiyun		    !($line =~ /^\+\s*$/ ||
3559*4882a593Smuzhiyun		      $line =~ /^\+\s*EXPORT_SYMBOL/ ||
3560*4882a593Smuzhiyun		      $line =~ /^\+\s*MODULE_/i ||
3561*4882a593Smuzhiyun		      $line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
3562*4882a593Smuzhiyun		      $line =~ /^\+[a-z_]*init/ ||
3563*4882a593Smuzhiyun		      $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
3564*4882a593Smuzhiyun		      $line =~ /^\+\s*DECLARE/ ||
3565*4882a593Smuzhiyun		      $line =~ /^\+\s*builtin_[\w_]*driver/ ||
3566*4882a593Smuzhiyun		      $line =~ /^\+\s*__setup/)) {
3567*4882a593Smuzhiyun			if (CHK("LINE_SPACING",
3568*4882a593Smuzhiyun				"Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
3569*4882a593Smuzhiyun			    $fix) {
3570*4882a593Smuzhiyun				fix_insert_line($fixlinenr, "\+");
3571*4882a593Smuzhiyun			}
3572*4882a593Smuzhiyun		}
3573*4882a593Smuzhiyun
3574*4882a593Smuzhiyun# check for multiple consecutive blank lines
3575*4882a593Smuzhiyun		if ($prevline =~ /^[\+ ]\s*$/ &&
3576*4882a593Smuzhiyun		    $line =~ /^\+\s*$/ &&
3577*4882a593Smuzhiyun		    $last_blank_line != ($linenr - 1)) {
3578*4882a593Smuzhiyun			if (CHK("LINE_SPACING",
3579*4882a593Smuzhiyun				"Please don't use multiple blank lines\n" . $hereprev) &&
3580*4882a593Smuzhiyun			    $fix) {
3581*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
3582*4882a593Smuzhiyun			}
3583*4882a593Smuzhiyun
3584*4882a593Smuzhiyun			$last_blank_line = $linenr;
3585*4882a593Smuzhiyun		}
3586*4882a593Smuzhiyun
3587*4882a593Smuzhiyun# check for missing blank lines after declarations
3588*4882a593Smuzhiyun		if ($sline =~ /^\+\s+\S/ &&			#Not at char 1
3589*4882a593Smuzhiyun			# actual declarations
3590*4882a593Smuzhiyun		    ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
3591*4882a593Smuzhiyun			# function pointer declarations
3592*4882a593Smuzhiyun		     $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
3593*4882a593Smuzhiyun			# foo bar; where foo is some local typedef or #define
3594*4882a593Smuzhiyun		     $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
3595*4882a593Smuzhiyun			# known declaration macros
3596*4882a593Smuzhiyun		     $prevline =~ /^\+\s+$declaration_macros/) &&
3597*4882a593Smuzhiyun			# for "else if" which can look like "$Ident $Ident"
3598*4882a593Smuzhiyun		    !($prevline =~ /^\+\s+$c90_Keywords\b/ ||
3599*4882a593Smuzhiyun			# other possible extensions of declaration lines
3600*4882a593Smuzhiyun		      $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
3601*4882a593Smuzhiyun			# not starting a section or a macro "\" extended line
3602*4882a593Smuzhiyun		      $prevline =~ /(?:\{\s*|\\)$/) &&
3603*4882a593Smuzhiyun			# looks like a declaration
3604*4882a593Smuzhiyun		    !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
3605*4882a593Smuzhiyun			# function pointer declarations
3606*4882a593Smuzhiyun		      $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
3607*4882a593Smuzhiyun			# foo bar; where foo is some local typedef or #define
3608*4882a593Smuzhiyun		      $sline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
3609*4882a593Smuzhiyun			# known declaration macros
3610*4882a593Smuzhiyun		      $sline =~ /^\+\s+$declaration_macros/ ||
3611*4882a593Smuzhiyun			# start of struct or union or enum
3612*4882a593Smuzhiyun		      $sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
3613*4882a593Smuzhiyun			# start or end of block or continuation of declaration
3614*4882a593Smuzhiyun		      $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
3615*4882a593Smuzhiyun			# bitfield continuation
3616*4882a593Smuzhiyun		      $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
3617*4882a593Smuzhiyun			# other possible extensions of declaration lines
3618*4882a593Smuzhiyun		      $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
3619*4882a593Smuzhiyun			# indentation of previous and current line are the same
3620*4882a593Smuzhiyun		    (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
3621*4882a593Smuzhiyun			if (WARN("LINE_SPACING",
3622*4882a593Smuzhiyun				 "Missing a blank line after declarations\n" . $hereprev) &&
3623*4882a593Smuzhiyun			    $fix) {
3624*4882a593Smuzhiyun				fix_insert_line($fixlinenr, "\+");
3625*4882a593Smuzhiyun			}
3626*4882a593Smuzhiyun		}
3627*4882a593Smuzhiyun
3628*4882a593Smuzhiyun# check for spaces at the beginning of a line.
3629*4882a593Smuzhiyun# Exceptions:
3630*4882a593Smuzhiyun#  1) within comments
3631*4882a593Smuzhiyun#  2) indented preprocessor commands
3632*4882a593Smuzhiyun#  3) hanging labels
3633*4882a593Smuzhiyun		if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/)  {
3634*4882a593Smuzhiyun			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3635*4882a593Smuzhiyun			if (WARN("LEADING_SPACE",
3636*4882a593Smuzhiyun				 "please, no spaces at the start of a line\n" . $herevet) &&
3637*4882a593Smuzhiyun			    $fix) {
3638*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
3639*4882a593Smuzhiyun			}
3640*4882a593Smuzhiyun		}
3641*4882a593Smuzhiyun
3642*4882a593Smuzhiyun# check we are in a valid C source file if not then ignore this hunk
3643*4882a593Smuzhiyun		next if ($realfile !~ /\.(h|c)$/);
3644*4882a593Smuzhiyun
3645*4882a593Smuzhiyun# check for unusual line ending [ or (
3646*4882a593Smuzhiyun		if ($line =~ /^\+.*([\[\(])\s*$/) {
3647*4882a593Smuzhiyun			CHK("OPEN_ENDED_LINE",
3648*4882a593Smuzhiyun			    "Lines should not end with a '$1'\n" . $herecurr);
3649*4882a593Smuzhiyun		}
3650*4882a593Smuzhiyun
3651*4882a593Smuzhiyun# check if this appears to be the start function declaration, save the name
3652*4882a593Smuzhiyun		if ($sline =~ /^\+\{\s*$/ &&
3653*4882a593Smuzhiyun		    $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
3654*4882a593Smuzhiyun			$context_function = $1;
3655*4882a593Smuzhiyun		}
3656*4882a593Smuzhiyun
3657*4882a593Smuzhiyun# check if this appears to be the end of function declaration
3658*4882a593Smuzhiyun		if ($sline =~ /^\+\}\s*$/) {
3659*4882a593Smuzhiyun			undef $context_function;
3660*4882a593Smuzhiyun		}
3661*4882a593Smuzhiyun
3662*4882a593Smuzhiyun# check indentation of any line with a bare else
3663*4882a593Smuzhiyun# (but not if it is a multiple line "if (foo) return bar; else return baz;")
3664*4882a593Smuzhiyun# if the previous line is a break or return and is indented 1 tab more...
3665*4882a593Smuzhiyun		if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) {
3666*4882a593Smuzhiyun			my $tabs = length($1) + 1;
3667*4882a593Smuzhiyun			if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ ||
3668*4882a593Smuzhiyun			    ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ &&
3669*4882a593Smuzhiyun			     defined $lines[$linenr] &&
3670*4882a593Smuzhiyun			     $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) {
3671*4882a593Smuzhiyun				WARN("UNNECESSARY_ELSE",
3672*4882a593Smuzhiyun				     "else is not generally useful after a break or return\n" . $hereprev);
3673*4882a593Smuzhiyun			}
3674*4882a593Smuzhiyun		}
3675*4882a593Smuzhiyun
3676*4882a593Smuzhiyun# check indentation of a line with a break;
3677*4882a593Smuzhiyun# if the previous line is a goto or return and is indented the same # of tabs
3678*4882a593Smuzhiyun		if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
3679*4882a593Smuzhiyun			my $tabs = $1;
3680*4882a593Smuzhiyun			if ($prevline =~ /^\+$tabs(?:goto|return)\b/) {
3681*4882a593Smuzhiyun				WARN("UNNECESSARY_BREAK",
3682*4882a593Smuzhiyun				     "break is not useful after a goto or return\n" . $hereprev);
3683*4882a593Smuzhiyun			}
3684*4882a593Smuzhiyun		}
3685*4882a593Smuzhiyun
3686*4882a593Smuzhiyun# check for RCS/CVS revision markers
3687*4882a593Smuzhiyun		if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
3688*4882a593Smuzhiyun			WARN("CVS_KEYWORD",
3689*4882a593Smuzhiyun			     "CVS style keyword markers, these will _not_ be updated\n". $herecurr);
3690*4882a593Smuzhiyun		}
3691*4882a593Smuzhiyun
3692*4882a593Smuzhiyun# check for old HOTPLUG __dev<foo> section markings
3693*4882a593Smuzhiyun		if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) {
3694*4882a593Smuzhiyun			WARN("HOTPLUG_SECTION",
3695*4882a593Smuzhiyun			     "Using $1 is unnecessary\n" . $herecurr);
3696*4882a593Smuzhiyun		}
3697*4882a593Smuzhiyun
3698*4882a593Smuzhiyun# Check for potential 'bare' types
3699*4882a593Smuzhiyun		my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
3700*4882a593Smuzhiyun		    $realline_next);
3701*4882a593Smuzhiyun#print "LINE<$line>\n";
3702*4882a593Smuzhiyun		if ($linenr > $suppress_statement &&
3703*4882a593Smuzhiyun		    $realcnt && $sline =~ /.\s*\S/) {
3704*4882a593Smuzhiyun			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
3705*4882a593Smuzhiyun				ctx_statement_block($linenr, $realcnt, 0);
3706*4882a593Smuzhiyun			$stat =~ s/\n./\n /g;
3707*4882a593Smuzhiyun			$cond =~ s/\n./\n /g;
3708*4882a593Smuzhiyun
3709*4882a593Smuzhiyun#print "linenr<$linenr> <$stat>\n";
3710*4882a593Smuzhiyun			# If this statement has no statement boundaries within
3711*4882a593Smuzhiyun			# it there is no point in retrying a statement scan
3712*4882a593Smuzhiyun			# until we hit end of it.
3713*4882a593Smuzhiyun			my $frag = $stat; $frag =~ s/;+\s*$//;
3714*4882a593Smuzhiyun			if ($frag !~ /(?:{|;)/) {
3715*4882a593Smuzhiyun#print "skip<$line_nr_next>\n";
3716*4882a593Smuzhiyun				$suppress_statement = $line_nr_next;
3717*4882a593Smuzhiyun			}
3718*4882a593Smuzhiyun
3719*4882a593Smuzhiyun			# Find the real next line.
3720*4882a593Smuzhiyun			$realline_next = $line_nr_next;
3721*4882a593Smuzhiyun			if (defined $realline_next &&
3722*4882a593Smuzhiyun			    (!defined $lines[$realline_next - 1] ||
3723*4882a593Smuzhiyun			     substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
3724*4882a593Smuzhiyun				$realline_next++;
3725*4882a593Smuzhiyun			}
3726*4882a593Smuzhiyun
3727*4882a593Smuzhiyun			my $s = $stat;
3728*4882a593Smuzhiyun			$s =~ s/{.*$//s;
3729*4882a593Smuzhiyun
3730*4882a593Smuzhiyun			# Ignore goto labels.
3731*4882a593Smuzhiyun			if ($s =~ /$Ident:\*$/s) {
3732*4882a593Smuzhiyun
3733*4882a593Smuzhiyun			# Ignore functions being called
3734*4882a593Smuzhiyun			} elsif ($s =~ /^.\s*$Ident\s*\(/s) {
3735*4882a593Smuzhiyun
3736*4882a593Smuzhiyun			} elsif ($s =~ /^.\s*else\b/s) {
3737*4882a593Smuzhiyun
3738*4882a593Smuzhiyun			# declarations always start with types
3739*4882a593Smuzhiyun			} elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
3740*4882a593Smuzhiyun				my $type = $1;
3741*4882a593Smuzhiyun				$type =~ s/\s+/ /g;
3742*4882a593Smuzhiyun				possible($type, "A:" . $s);
3743*4882a593Smuzhiyun
3744*4882a593Smuzhiyun			# definitions in global scope can only start with types
3745*4882a593Smuzhiyun			} elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
3746*4882a593Smuzhiyun				possible($1, "B:" . $s);
3747*4882a593Smuzhiyun			}
3748*4882a593Smuzhiyun
3749*4882a593Smuzhiyun			# any (foo ... *) is a pointer cast, and foo is a type
3750*4882a593Smuzhiyun			while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
3751*4882a593Smuzhiyun				possible($1, "C:" . $s);
3752*4882a593Smuzhiyun			}
3753*4882a593Smuzhiyun
3754*4882a593Smuzhiyun			# Check for any sort of function declaration.
3755*4882a593Smuzhiyun			# int foo(something bar, other baz);
3756*4882a593Smuzhiyun			# void (*store_gdt)(x86_descr_ptr *);
3757*4882a593Smuzhiyun			if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
3758*4882a593Smuzhiyun				my ($name_len) = length($1);
3759*4882a593Smuzhiyun
3760*4882a593Smuzhiyun				my $ctx = $s;
3761*4882a593Smuzhiyun				substr($ctx, 0, $name_len + 1, '');
3762*4882a593Smuzhiyun				$ctx =~ s/\)[^\)]*$//;
3763*4882a593Smuzhiyun
3764*4882a593Smuzhiyun				for my $arg (split(/\s*,\s*/, $ctx)) {
3765*4882a593Smuzhiyun					if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
3766*4882a593Smuzhiyun
3767*4882a593Smuzhiyun						possible($1, "D:" . $s);
3768*4882a593Smuzhiyun					}
3769*4882a593Smuzhiyun				}
3770*4882a593Smuzhiyun			}
3771*4882a593Smuzhiyun
3772*4882a593Smuzhiyun		}
3773*4882a593Smuzhiyun
3774*4882a593Smuzhiyun#
3775*4882a593Smuzhiyun# Checks which may be anchored in the context.
3776*4882a593Smuzhiyun#
3777*4882a593Smuzhiyun
3778*4882a593Smuzhiyun# Check for switch () and associated case and default
3779*4882a593Smuzhiyun# statements should be at the same indent.
3780*4882a593Smuzhiyun		if ($line=~/\bswitch\s*\(.*\)/) {
3781*4882a593Smuzhiyun			my $err = '';
3782*4882a593Smuzhiyun			my $sep = '';
3783*4882a593Smuzhiyun			my @ctx = ctx_block_outer($linenr, $realcnt);
3784*4882a593Smuzhiyun			shift(@ctx);
3785*4882a593Smuzhiyun			for my $ctx (@ctx) {
3786*4882a593Smuzhiyun				my ($clen, $cindent) = line_stats($ctx);
3787*4882a593Smuzhiyun				if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
3788*4882a593Smuzhiyun							$indent != $cindent) {
3789*4882a593Smuzhiyun					$err .= "$sep$ctx\n";
3790*4882a593Smuzhiyun					$sep = '';
3791*4882a593Smuzhiyun				} else {
3792*4882a593Smuzhiyun					$sep = "[...]\n";
3793*4882a593Smuzhiyun				}
3794*4882a593Smuzhiyun			}
3795*4882a593Smuzhiyun			if ($err ne '') {
3796*4882a593Smuzhiyun				ERROR("SWITCH_CASE_INDENT_LEVEL",
3797*4882a593Smuzhiyun				      "switch and case should be at the same indent\n$hereline$err");
3798*4882a593Smuzhiyun			}
3799*4882a593Smuzhiyun		}
3800*4882a593Smuzhiyun
3801*4882a593Smuzhiyun# if/while/etc brace do not go on next line, unless defining a do while loop,
3802*4882a593Smuzhiyun# or if that brace on the next line is for something else
3803*4882a593Smuzhiyun		if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
3804*4882a593Smuzhiyun			my $pre_ctx = "$1$2";
3805*4882a593Smuzhiyun
3806*4882a593Smuzhiyun			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
3807*4882a593Smuzhiyun
3808*4882a593Smuzhiyun			if ($line =~ /^\+\t{6,}/) {
3809*4882a593Smuzhiyun				WARN("DEEP_INDENTATION",
3810*4882a593Smuzhiyun				     "Too many leading tabs - consider code refactoring\n" . $herecurr);
3811*4882a593Smuzhiyun			}
3812*4882a593Smuzhiyun
3813*4882a593Smuzhiyun			my $ctx_cnt = $realcnt - $#ctx - 1;
3814*4882a593Smuzhiyun			my $ctx = join("\n", @ctx);
3815*4882a593Smuzhiyun
3816*4882a593Smuzhiyun			my $ctx_ln = $linenr;
3817*4882a593Smuzhiyun			my $ctx_skip = $realcnt;
3818*4882a593Smuzhiyun
3819*4882a593Smuzhiyun			while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
3820*4882a593Smuzhiyun					defined $lines[$ctx_ln - 1] &&
3821*4882a593Smuzhiyun					$lines[$ctx_ln - 1] =~ /^-/)) {
3822*4882a593Smuzhiyun				##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
3823*4882a593Smuzhiyun				$ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
3824*4882a593Smuzhiyun				$ctx_ln++;
3825*4882a593Smuzhiyun			}
3826*4882a593Smuzhiyun
3827*4882a593Smuzhiyun			#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
3828*4882a593Smuzhiyun			#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
3829*4882a593Smuzhiyun
3830*4882a593Smuzhiyun			if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
3831*4882a593Smuzhiyun				ERROR("OPEN_BRACE",
3832*4882a593Smuzhiyun				      "that open brace { should be on the previous line\n" .
3833*4882a593Smuzhiyun					"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
3834*4882a593Smuzhiyun			}
3835*4882a593Smuzhiyun			if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
3836*4882a593Smuzhiyun			    $ctx =~ /\)\s*\;\s*$/ &&
3837*4882a593Smuzhiyun			    defined $lines[$ctx_ln - 1])
3838*4882a593Smuzhiyun			{
3839*4882a593Smuzhiyun				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
3840*4882a593Smuzhiyun				if ($nindent > $indent) {
3841*4882a593Smuzhiyun					WARN("TRAILING_SEMICOLON",
3842*4882a593Smuzhiyun					     "trailing semicolon indicates no statements, indent implies otherwise\n" .
3843*4882a593Smuzhiyun						"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
3844*4882a593Smuzhiyun				}
3845*4882a593Smuzhiyun			}
3846*4882a593Smuzhiyun		}
3847*4882a593Smuzhiyun
3848*4882a593Smuzhiyun# Check relative indent for conditionals and blocks.
3849*4882a593Smuzhiyun		if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
3850*4882a593Smuzhiyun			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
3851*4882a593Smuzhiyun				ctx_statement_block($linenr, $realcnt, 0)
3852*4882a593Smuzhiyun					if (!defined $stat);
3853*4882a593Smuzhiyun			my ($s, $c) = ($stat, $cond);
3854*4882a593Smuzhiyun
3855*4882a593Smuzhiyun			substr($s, 0, length($c), '');
3856*4882a593Smuzhiyun
3857*4882a593Smuzhiyun			# remove inline comments
3858*4882a593Smuzhiyun			$s =~ s/$;/ /g;
3859*4882a593Smuzhiyun			$c =~ s/$;/ /g;
3860*4882a593Smuzhiyun
3861*4882a593Smuzhiyun			# Find out how long the conditional actually is.
3862*4882a593Smuzhiyun			my @newlines = ($c =~ /\n/gs);
3863*4882a593Smuzhiyun			my $cond_lines = 1 + $#newlines;
3864*4882a593Smuzhiyun
3865*4882a593Smuzhiyun			# Make sure we remove the line prefixes as we have
3866*4882a593Smuzhiyun			# none on the first line, and are going to readd them
3867*4882a593Smuzhiyun			# where necessary.
3868*4882a593Smuzhiyun			$s =~ s/\n./\n/gs;
3869*4882a593Smuzhiyun			while ($s =~ /\n\s+\\\n/) {
3870*4882a593Smuzhiyun				$cond_lines += $s =~ s/\n\s+\\\n/\n/g;
3871*4882a593Smuzhiyun			}
3872*4882a593Smuzhiyun
3873*4882a593Smuzhiyun			# We want to check the first line inside the block
3874*4882a593Smuzhiyun			# starting at the end of the conditional, so remove:
3875*4882a593Smuzhiyun			#  1) any blank line termination
3876*4882a593Smuzhiyun			#  2) any opening brace { on end of the line
3877*4882a593Smuzhiyun			#  3) any do (...) {
3878*4882a593Smuzhiyun			my $continuation = 0;
3879*4882a593Smuzhiyun			my $check = 0;
3880*4882a593Smuzhiyun			$s =~ s/^.*\bdo\b//;
3881*4882a593Smuzhiyun			$s =~ s/^\s*{//;
3882*4882a593Smuzhiyun			if ($s =~ s/^\s*\\//) {
3883*4882a593Smuzhiyun				$continuation = 1;
3884*4882a593Smuzhiyun			}
3885*4882a593Smuzhiyun			if ($s =~ s/^\s*?\n//) {
3886*4882a593Smuzhiyun				$check = 1;
3887*4882a593Smuzhiyun				$cond_lines++;
3888*4882a593Smuzhiyun			}
3889*4882a593Smuzhiyun
3890*4882a593Smuzhiyun			# Also ignore a loop construct at the end of a
3891*4882a593Smuzhiyun			# preprocessor statement.
3892*4882a593Smuzhiyun			if (($prevline =~ /^.\s*#\s*define\s/ ||
3893*4882a593Smuzhiyun			    $prevline =~ /\\\s*$/) && $continuation == 0) {
3894*4882a593Smuzhiyun				$check = 0;
3895*4882a593Smuzhiyun			}
3896*4882a593Smuzhiyun
3897*4882a593Smuzhiyun			my $cond_ptr = -1;
3898*4882a593Smuzhiyun			$continuation = 0;
3899*4882a593Smuzhiyun			while ($cond_ptr != $cond_lines) {
3900*4882a593Smuzhiyun				$cond_ptr = $cond_lines;
3901*4882a593Smuzhiyun
3902*4882a593Smuzhiyun				# If we see an #else/#elif then the code
3903*4882a593Smuzhiyun				# is not linear.
3904*4882a593Smuzhiyun				if ($s =~ /^\s*\#\s*(?:else|elif)/) {
3905*4882a593Smuzhiyun					$check = 0;
3906*4882a593Smuzhiyun				}
3907*4882a593Smuzhiyun
3908*4882a593Smuzhiyun				# Ignore:
3909*4882a593Smuzhiyun				#  1) blank lines, they should be at 0,
3910*4882a593Smuzhiyun				#  2) preprocessor lines, and
3911*4882a593Smuzhiyun				#  3) labels.
3912*4882a593Smuzhiyun				if ($continuation ||
3913*4882a593Smuzhiyun				    $s =~ /^\s*?\n/ ||
3914*4882a593Smuzhiyun				    $s =~ /^\s*#\s*?/ ||
3915*4882a593Smuzhiyun				    $s =~ /^\s*$Ident\s*:/) {
3916*4882a593Smuzhiyun					$continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
3917*4882a593Smuzhiyun					if ($s =~ s/^.*?\n//) {
3918*4882a593Smuzhiyun						$cond_lines++;
3919*4882a593Smuzhiyun					}
3920*4882a593Smuzhiyun				}
3921*4882a593Smuzhiyun			}
3922*4882a593Smuzhiyun
3923*4882a593Smuzhiyun			my (undef, $sindent) = line_stats("+" . $s);
3924*4882a593Smuzhiyun			my $stat_real = raw_line($linenr, $cond_lines);
3925*4882a593Smuzhiyun
3926*4882a593Smuzhiyun			# Check if either of these lines are modified, else
3927*4882a593Smuzhiyun			# this is not this patch's fault.
3928*4882a593Smuzhiyun			if (!defined($stat_real) ||
3929*4882a593Smuzhiyun			    $stat !~ /^\+/ && $stat_real !~ /^\+/) {
3930*4882a593Smuzhiyun				$check = 0;
3931*4882a593Smuzhiyun			}
3932*4882a593Smuzhiyun			if (defined($stat_real) && $cond_lines > 1) {
3933*4882a593Smuzhiyun				$stat_real = "[...]\n$stat_real";
3934*4882a593Smuzhiyun			}
3935*4882a593Smuzhiyun
3936*4882a593Smuzhiyun			#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
3937*4882a593Smuzhiyun
3938*4882a593Smuzhiyun			if ($check && $s ne '' &&
3939*4882a593Smuzhiyun			    (($sindent % $tabsize) != 0 ||
3940*4882a593Smuzhiyun			     ($sindent < $indent) ||
3941*4882a593Smuzhiyun			     ($sindent == $indent &&
3942*4882a593Smuzhiyun			      ($s !~ /^\s*(?:\}|\{|else\b)/)) ||
3943*4882a593Smuzhiyun			     ($sindent > $indent + $tabsize))) {
3944*4882a593Smuzhiyun				WARN("SUSPECT_CODE_INDENT",
3945*4882a593Smuzhiyun				     "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
3946*4882a593Smuzhiyun			}
3947*4882a593Smuzhiyun		}
3948*4882a593Smuzhiyun
3949*4882a593Smuzhiyun		# Track the 'values' across context and added lines.
3950*4882a593Smuzhiyun		my $opline = $line; $opline =~ s/^./ /;
3951*4882a593Smuzhiyun		my ($curr_values, $curr_vars) =
3952*4882a593Smuzhiyun				annotate_values($opline . "\n", $prev_values);
3953*4882a593Smuzhiyun		$curr_values = $prev_values . $curr_values;
3954*4882a593Smuzhiyun		if ($dbg_values) {
3955*4882a593Smuzhiyun			my $outline = $opline; $outline =~ s/\t/ /g;
3956*4882a593Smuzhiyun			print "$linenr > .$outline\n";
3957*4882a593Smuzhiyun			print "$linenr > $curr_values\n";
3958*4882a593Smuzhiyun			print "$linenr >  $curr_vars\n";
3959*4882a593Smuzhiyun		}
3960*4882a593Smuzhiyun		$prev_values = substr($curr_values, -1);
3961*4882a593Smuzhiyun
3962*4882a593Smuzhiyun#ignore lines not being added
3963*4882a593Smuzhiyun		next if ($line =~ /^[^\+]/);
3964*4882a593Smuzhiyun
3965*4882a593Smuzhiyun# check for self assignments used to avoid compiler warnings
3966*4882a593Smuzhiyun# e.g.:	int foo = foo, *bar = NULL;
3967*4882a593Smuzhiyun#	struct foo bar = *(&(bar));
3968*4882a593Smuzhiyun		if ($line =~ /^\+\s*(?:$Declare)?([A-Za-z_][A-Za-z\d_]*)\s*=/) {
3969*4882a593Smuzhiyun			my $var = $1;
3970*4882a593Smuzhiyun			if ($line =~ /^\+\s*(?:$Declare)?$var\s*=\s*(?:$var|\*\s*\(?\s*&\s*\(?\s*$var\s*\)?\s*\)?)\s*[;,]/) {
3971*4882a593Smuzhiyun				WARN("SELF_ASSIGNMENT",
3972*4882a593Smuzhiyun				     "Do not use self-assignments to avoid compiler warnings\n" . $herecurr);
3973*4882a593Smuzhiyun			}
3974*4882a593Smuzhiyun		}
3975*4882a593Smuzhiyun
3976*4882a593Smuzhiyun# check for dereferences that span multiple lines
3977*4882a593Smuzhiyun		if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ &&
3978*4882a593Smuzhiyun		    $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) {
3979*4882a593Smuzhiyun			$prevline =~ /($Lval\s*(?:\.|->))\s*$/;
3980*4882a593Smuzhiyun			my $ref = $1;
3981*4882a593Smuzhiyun			$line =~ /^.\s*($Lval)/;
3982*4882a593Smuzhiyun			$ref .= $1;
3983*4882a593Smuzhiyun			$ref =~ s/\s//g;
3984*4882a593Smuzhiyun			WARN("MULTILINE_DEREFERENCE",
3985*4882a593Smuzhiyun			     "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev);
3986*4882a593Smuzhiyun		}
3987*4882a593Smuzhiyun
3988*4882a593Smuzhiyun# check for declarations of signed or unsigned without int
3989*4882a593Smuzhiyun		while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
3990*4882a593Smuzhiyun			my $type = $1;
3991*4882a593Smuzhiyun			my $var = $2;
3992*4882a593Smuzhiyun			$var = "" if (!defined $var);
3993*4882a593Smuzhiyun			if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
3994*4882a593Smuzhiyun				my $sign = $1;
3995*4882a593Smuzhiyun				my $pointer = $2;
3996*4882a593Smuzhiyun
3997*4882a593Smuzhiyun				$pointer = "" if (!defined $pointer);
3998*4882a593Smuzhiyun
3999*4882a593Smuzhiyun				if (WARN("UNSPECIFIED_INT",
4000*4882a593Smuzhiyun					 "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) &&
4001*4882a593Smuzhiyun				    $fix) {
4002*4882a593Smuzhiyun					my $decl = trim($sign) . " int ";
4003*4882a593Smuzhiyun					my $comp_pointer = $pointer;
4004*4882a593Smuzhiyun					$comp_pointer =~ s/\s//g;
4005*4882a593Smuzhiyun					$decl .= $comp_pointer;
4006*4882a593Smuzhiyun					$decl = rtrim($decl) if ($var eq "");
4007*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
4008*4882a593Smuzhiyun				}
4009*4882a593Smuzhiyun			}
4010*4882a593Smuzhiyun		}
4011*4882a593Smuzhiyun
4012*4882a593Smuzhiyun# TEST: allow direct testing of the type matcher.
4013*4882a593Smuzhiyun		if ($dbg_type) {
4014*4882a593Smuzhiyun			if ($line =~ /^.\s*$Declare\s*$/) {
4015*4882a593Smuzhiyun				ERROR("TEST_TYPE",
4016*4882a593Smuzhiyun				      "TEST: is type\n" . $herecurr);
4017*4882a593Smuzhiyun			} elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
4018*4882a593Smuzhiyun				ERROR("TEST_NOT_TYPE",
4019*4882a593Smuzhiyun				      "TEST: is not type ($1 is)\n". $herecurr);
4020*4882a593Smuzhiyun			}
4021*4882a593Smuzhiyun			next;
4022*4882a593Smuzhiyun		}
4023*4882a593Smuzhiyun# TEST: allow direct testing of the attribute matcher.
4024*4882a593Smuzhiyun		if ($dbg_attr) {
4025*4882a593Smuzhiyun			if ($line =~ /^.\s*$Modifier\s*$/) {
4026*4882a593Smuzhiyun				ERROR("TEST_ATTR",
4027*4882a593Smuzhiyun				      "TEST: is attr\n" . $herecurr);
4028*4882a593Smuzhiyun			} elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
4029*4882a593Smuzhiyun				ERROR("TEST_NOT_ATTR",
4030*4882a593Smuzhiyun				      "TEST: is not attr ($1 is)\n". $herecurr);
4031*4882a593Smuzhiyun			}
4032*4882a593Smuzhiyun			next;
4033*4882a593Smuzhiyun		}
4034*4882a593Smuzhiyun
4035*4882a593Smuzhiyun# check for initialisation to aggregates open brace on the next line
4036*4882a593Smuzhiyun		if ($line =~ /^.\s*{/ &&
4037*4882a593Smuzhiyun		    $prevline =~ /(?:^|[^=])=\s*$/) {
4038*4882a593Smuzhiyun			if (ERROR("OPEN_BRACE",
4039*4882a593Smuzhiyun				  "that open brace { should be on the previous line\n" . $hereprev) &&
4040*4882a593Smuzhiyun			    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
4041*4882a593Smuzhiyun				fix_delete_line($fixlinenr - 1, $prevrawline);
4042*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
4043*4882a593Smuzhiyun				my $fixedline = $prevrawline;
4044*4882a593Smuzhiyun				$fixedline =~ s/\s*=\s*$/ = {/;
4045*4882a593Smuzhiyun				fix_insert_line($fixlinenr, $fixedline);
4046*4882a593Smuzhiyun				$fixedline = $line;
4047*4882a593Smuzhiyun				$fixedline =~ s/^(.\s*)\{\s*/$1/;
4048*4882a593Smuzhiyun				fix_insert_line($fixlinenr, $fixedline);
4049*4882a593Smuzhiyun			}
4050*4882a593Smuzhiyun		}
4051*4882a593Smuzhiyun
4052*4882a593Smuzhiyun#
4053*4882a593Smuzhiyun# Checks which are anchored on the added line.
4054*4882a593Smuzhiyun#
4055*4882a593Smuzhiyun
4056*4882a593Smuzhiyun# check for malformed paths in #include statements (uses RAW line)
4057*4882a593Smuzhiyun		if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
4058*4882a593Smuzhiyun			my $path = $1;
4059*4882a593Smuzhiyun			if ($path =~ m{//}) {
4060*4882a593Smuzhiyun				ERROR("MALFORMED_INCLUDE",
4061*4882a593Smuzhiyun				      "malformed #include filename\n" . $herecurr);
4062*4882a593Smuzhiyun			}
4063*4882a593Smuzhiyun			if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) {
4064*4882a593Smuzhiyun				ERROR("UAPI_INCLUDE",
4065*4882a593Smuzhiyun				      "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr);
4066*4882a593Smuzhiyun			}
4067*4882a593Smuzhiyun		}
4068*4882a593Smuzhiyun
4069*4882a593Smuzhiyun# no C99 // comments
4070*4882a593Smuzhiyun		if ($line =~ m{//}) {
4071*4882a593Smuzhiyun			if (ERROR("C99_COMMENTS",
4072*4882a593Smuzhiyun				  "do not use C99 // comments\n" . $herecurr) &&
4073*4882a593Smuzhiyun			    $fix) {
4074*4882a593Smuzhiyun				my $line = $fixed[$fixlinenr];
4075*4882a593Smuzhiyun				if ($line =~ /\/\/(.*)$/) {
4076*4882a593Smuzhiyun					my $comment = trim($1);
4077*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@;
4078*4882a593Smuzhiyun				}
4079*4882a593Smuzhiyun			}
4080*4882a593Smuzhiyun		}
4081*4882a593Smuzhiyun		# Remove C99 comments.
4082*4882a593Smuzhiyun		$line =~ s@//.*@@;
4083*4882a593Smuzhiyun		$opline =~ s@//.*@@;
4084*4882a593Smuzhiyun
4085*4882a593Smuzhiyun# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
4086*4882a593Smuzhiyun# the whole statement.
4087*4882a593Smuzhiyun#print "APW <$lines[$realline_next - 1]>\n";
4088*4882a593Smuzhiyun		if (defined $realline_next &&
4089*4882a593Smuzhiyun		    exists $lines[$realline_next - 1] &&
4090*4882a593Smuzhiyun		    !defined $suppress_export{$realline_next} &&
4091*4882a593Smuzhiyun		    ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
4092*4882a593Smuzhiyun		     $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
4093*4882a593Smuzhiyun			# Handle definitions which produce identifiers with
4094*4882a593Smuzhiyun			# a prefix:
4095*4882a593Smuzhiyun			#   XXX(foo);
4096*4882a593Smuzhiyun			#   EXPORT_SYMBOL(something_foo);
4097*4882a593Smuzhiyun			my $name = $1;
4098*4882a593Smuzhiyun			if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
4099*4882a593Smuzhiyun			    $name =~ /^${Ident}_$2/) {
4100*4882a593Smuzhiyun#print "FOO C name<$name>\n";
4101*4882a593Smuzhiyun				$suppress_export{$realline_next} = 1;
4102*4882a593Smuzhiyun
4103*4882a593Smuzhiyun			} elsif ($stat !~ /(?:
4104*4882a593Smuzhiyun				\n.}\s*$|
4105*4882a593Smuzhiyun				^.DEFINE_$Ident\(\Q$name\E\)|
4106*4882a593Smuzhiyun				^.DECLARE_$Ident\(\Q$name\E\)|
4107*4882a593Smuzhiyun				^.LIST_HEAD\(\Q$name\E\)|
4108*4882a593Smuzhiyun				^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
4109*4882a593Smuzhiyun				\b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
4110*4882a593Smuzhiyun			    )/x) {
4111*4882a593Smuzhiyun#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
4112*4882a593Smuzhiyun				$suppress_export{$realline_next} = 2;
4113*4882a593Smuzhiyun			} else {
4114*4882a593Smuzhiyun				$suppress_export{$realline_next} = 1;
4115*4882a593Smuzhiyun			}
4116*4882a593Smuzhiyun		}
4117*4882a593Smuzhiyun		if (!defined $suppress_export{$linenr} &&
4118*4882a593Smuzhiyun		    $prevline =~ /^.\s*$/ &&
4119*4882a593Smuzhiyun		    ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
4120*4882a593Smuzhiyun		     $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
4121*4882a593Smuzhiyun#print "FOO B <$lines[$linenr - 1]>\n";
4122*4882a593Smuzhiyun			$suppress_export{$linenr} = 2;
4123*4882a593Smuzhiyun		}
4124*4882a593Smuzhiyun		if (defined $suppress_export{$linenr} &&
4125*4882a593Smuzhiyun		    $suppress_export{$linenr} == 2) {
4126*4882a593Smuzhiyun			WARN("EXPORT_SYMBOL",
4127*4882a593Smuzhiyun			     "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
4128*4882a593Smuzhiyun		}
4129*4882a593Smuzhiyun
4130*4882a593Smuzhiyun# check for global initialisers.
4131*4882a593Smuzhiyun		if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) {
4132*4882a593Smuzhiyun			if (ERROR("GLOBAL_INITIALISERS",
4133*4882a593Smuzhiyun				  "do not initialise globals to $1\n" . $herecurr) &&
4134*4882a593Smuzhiyun			    $fix) {
4135*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/;
4136*4882a593Smuzhiyun			}
4137*4882a593Smuzhiyun		}
4138*4882a593Smuzhiyun# check for static initialisers.
4139*4882a593Smuzhiyun		if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) {
4140*4882a593Smuzhiyun			if (ERROR("INITIALISED_STATIC",
4141*4882a593Smuzhiyun				  "do not initialise statics to $1\n" .
4142*4882a593Smuzhiyun				      $herecurr) &&
4143*4882a593Smuzhiyun			    $fix) {
4144*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/;
4145*4882a593Smuzhiyun			}
4146*4882a593Smuzhiyun		}
4147*4882a593Smuzhiyun
4148*4882a593Smuzhiyun# check for misordered declarations of char/short/int/long with signed/unsigned
4149*4882a593Smuzhiyun		while ($sline =~ m{(\b$TypeMisordered\b)}g) {
4150*4882a593Smuzhiyun			my $tmp = trim($1);
4151*4882a593Smuzhiyun			WARN("MISORDERED_TYPE",
4152*4882a593Smuzhiyun			     "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
4153*4882a593Smuzhiyun		}
4154*4882a593Smuzhiyun
4155*4882a593Smuzhiyun# check for unnecessary <signed> int declarations of short/long/long long
4156*4882a593Smuzhiyun		while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
4157*4882a593Smuzhiyun			my $type = trim($1);
4158*4882a593Smuzhiyun			next if ($type !~ /\bint\b/);
4159*4882a593Smuzhiyun			next if ($type !~ /\b(?:short|long\s+long|long)\b/);
4160*4882a593Smuzhiyun			my $new_type = $type;
4161*4882a593Smuzhiyun			$new_type =~ s/\b\s*int\s*\b/ /;
4162*4882a593Smuzhiyun			$new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
4163*4882a593Smuzhiyun			$new_type =~ s/^const\s+//;
4164*4882a593Smuzhiyun			$new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
4165*4882a593Smuzhiyun			$new_type = "const $new_type" if ($type =~ /^const\b/);
4166*4882a593Smuzhiyun			$new_type =~ s/\s+/ /g;
4167*4882a593Smuzhiyun			$new_type = trim($new_type);
4168*4882a593Smuzhiyun			if (WARN("UNNECESSARY_INT",
4169*4882a593Smuzhiyun				 "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) &&
4170*4882a593Smuzhiyun			    $fix) {
4171*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
4172*4882a593Smuzhiyun			}
4173*4882a593Smuzhiyun		}
4174*4882a593Smuzhiyun
4175*4882a593Smuzhiyun# check for static const char * arrays.
4176*4882a593Smuzhiyun		if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
4177*4882a593Smuzhiyun			WARN("STATIC_CONST_CHAR_ARRAY",
4178*4882a593Smuzhiyun			     "static const char * array should probably be static const char * const\n" .
4179*4882a593Smuzhiyun				$herecurr);
4180*4882a593Smuzhiyun		}
4181*4882a593Smuzhiyun
4182*4882a593Smuzhiyun# check for initialized const char arrays that should be static const
4183*4882a593Smuzhiyun		if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
4184*4882a593Smuzhiyun			if (WARN("STATIC_CONST_CHAR_ARRAY",
4185*4882a593Smuzhiyun				 "const array should probably be static const\n" . $herecurr) &&
4186*4882a593Smuzhiyun			    $fix) {
4187*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
4188*4882a593Smuzhiyun			}
4189*4882a593Smuzhiyun		}
4190*4882a593Smuzhiyun
4191*4882a593Smuzhiyun# check for static char foo[] = "bar" declarations.
4192*4882a593Smuzhiyun		if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
4193*4882a593Smuzhiyun			WARN("STATIC_CONST_CHAR_ARRAY",
4194*4882a593Smuzhiyun			     "static char array declaration should probably be static const char\n" .
4195*4882a593Smuzhiyun				$herecurr);
4196*4882a593Smuzhiyun		}
4197*4882a593Smuzhiyun
4198*4882a593Smuzhiyun# check for const <foo> const where <foo> is not a pointer or array type
4199*4882a593Smuzhiyun		if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
4200*4882a593Smuzhiyun			my $found = $1;
4201*4882a593Smuzhiyun			if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) {
4202*4882a593Smuzhiyun				WARN("CONST_CONST",
4203*4882a593Smuzhiyun				     "'const $found const *' should probably be 'const $found * const'\n" . $herecurr);
4204*4882a593Smuzhiyun			} elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) {
4205*4882a593Smuzhiyun				WARN("CONST_CONST",
4206*4882a593Smuzhiyun				     "'const $found const' should probably be 'const $found'\n" . $herecurr);
4207*4882a593Smuzhiyun			}
4208*4882a593Smuzhiyun		}
4209*4882a593Smuzhiyun
4210*4882a593Smuzhiyun# check for non-global char *foo[] = {"bar", ...} declarations.
4211*4882a593Smuzhiyun		if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
4212*4882a593Smuzhiyun			WARN("STATIC_CONST_CHAR_ARRAY",
4213*4882a593Smuzhiyun			     "char * array declaration might be better as static const\n" .
4214*4882a593Smuzhiyun				$herecurr);
4215*4882a593Smuzhiyun               }
4216*4882a593Smuzhiyun
4217*4882a593Smuzhiyun# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
4218*4882a593Smuzhiyun		if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
4219*4882a593Smuzhiyun			my $array = $1;
4220*4882a593Smuzhiyun			if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) {
4221*4882a593Smuzhiyun				my $array_div = $1;
4222*4882a593Smuzhiyun				if (WARN("ARRAY_SIZE",
4223*4882a593Smuzhiyun					 "Prefer ARRAY_SIZE($array)\n" . $herecurr) &&
4224*4882a593Smuzhiyun				    $fix) {
4225*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/;
4226*4882a593Smuzhiyun				}
4227*4882a593Smuzhiyun			}
4228*4882a593Smuzhiyun		}
4229*4882a593Smuzhiyun
4230*4882a593Smuzhiyun# check for function declarations without arguments like "int foo()"
4231*4882a593Smuzhiyun		if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
4232*4882a593Smuzhiyun			if (ERROR("FUNCTION_WITHOUT_ARGS",
4233*4882a593Smuzhiyun				  "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
4234*4882a593Smuzhiyun			    $fix) {
4235*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
4236*4882a593Smuzhiyun			}
4237*4882a593Smuzhiyun		}
4238*4882a593Smuzhiyun
4239*4882a593Smuzhiyun# check for new typedefs, only function parameters and sparse annotations
4240*4882a593Smuzhiyun# make sense.
4241*4882a593Smuzhiyun		if ($line =~ /\btypedef\s/ &&
4242*4882a593Smuzhiyun		    $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
4243*4882a593Smuzhiyun		    $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
4244*4882a593Smuzhiyun		    $line !~ /\b$typeTypedefs\b/ &&
4245*4882a593Smuzhiyun		    $line !~ /\b__bitwise\b/) {
4246*4882a593Smuzhiyun			WARN("NEW_TYPEDEFS",
4247*4882a593Smuzhiyun			     "do not add new typedefs\n" . $herecurr);
4248*4882a593Smuzhiyun		}
4249*4882a593Smuzhiyun
4250*4882a593Smuzhiyun# * goes on variable not on type
4251*4882a593Smuzhiyun		# (char*[ const])
4252*4882a593Smuzhiyun		while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) {
4253*4882a593Smuzhiyun			#print "AA<$1>\n";
4254*4882a593Smuzhiyun			my ($ident, $from, $to) = ($1, $2, $2);
4255*4882a593Smuzhiyun
4256*4882a593Smuzhiyun			# Should start with a space.
4257*4882a593Smuzhiyun			$to =~ s/^(\S)/ $1/;
4258*4882a593Smuzhiyun			# Should not end with a space.
4259*4882a593Smuzhiyun			$to =~ s/\s+$//;
4260*4882a593Smuzhiyun			# '*'s should not have spaces between.
4261*4882a593Smuzhiyun			while ($to =~ s/\*\s+\*/\*\*/) {
4262*4882a593Smuzhiyun			}
4263*4882a593Smuzhiyun
4264*4882a593Smuzhiyun##			print "1: from<$from> to<$to> ident<$ident>\n";
4265*4882a593Smuzhiyun			if ($from ne $to) {
4266*4882a593Smuzhiyun				if (ERROR("POINTER_LOCATION",
4267*4882a593Smuzhiyun					  "\"(foo$from)\" should be \"(foo$to)\"\n" .  $herecurr) &&
4268*4882a593Smuzhiyun				    $fix) {
4269*4882a593Smuzhiyun					my $sub_from = $ident;
4270*4882a593Smuzhiyun					my $sub_to = $ident;
4271*4882a593Smuzhiyun					$sub_to =~ s/\Q$from\E/$to/;
4272*4882a593Smuzhiyun					$fixed[$fixlinenr] =~
4273*4882a593Smuzhiyun					    s@\Q$sub_from\E@$sub_to@;
4274*4882a593Smuzhiyun				}
4275*4882a593Smuzhiyun			}
4276*4882a593Smuzhiyun		}
4277*4882a593Smuzhiyun		while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) {
4278*4882a593Smuzhiyun			#print "BB<$1>\n";
4279*4882a593Smuzhiyun			my ($match, $from, $to, $ident) = ($1, $2, $2, $3);
4280*4882a593Smuzhiyun
4281*4882a593Smuzhiyun			# Should start with a space.
4282*4882a593Smuzhiyun			$to =~ s/^(\S)/ $1/;
4283*4882a593Smuzhiyun			# Should not end with a space.
4284*4882a593Smuzhiyun			$to =~ s/\s+$//;
4285*4882a593Smuzhiyun			# '*'s should not have spaces between.
4286*4882a593Smuzhiyun			while ($to =~ s/\*\s+\*/\*\*/) {
4287*4882a593Smuzhiyun			}
4288*4882a593Smuzhiyun			# Modifiers should have spaces.
4289*4882a593Smuzhiyun			$to =~ s/(\b$Modifier$)/$1 /;
4290*4882a593Smuzhiyun
4291*4882a593Smuzhiyun##			print "2: from<$from> to<$to> ident<$ident>\n";
4292*4882a593Smuzhiyun			if ($from ne $to && $ident !~ /^$Modifier$/) {
4293*4882a593Smuzhiyun				if (ERROR("POINTER_LOCATION",
4294*4882a593Smuzhiyun					  "\"foo${from}bar\" should be \"foo${to}bar\"\n" .  $herecurr) &&
4295*4882a593Smuzhiyun				    $fix) {
4296*4882a593Smuzhiyun
4297*4882a593Smuzhiyun					my $sub_from = $match;
4298*4882a593Smuzhiyun					my $sub_to = $match;
4299*4882a593Smuzhiyun					$sub_to =~ s/\Q$from\E/$to/;
4300*4882a593Smuzhiyun					$fixed[$fixlinenr] =~
4301*4882a593Smuzhiyun					    s@\Q$sub_from\E@$sub_to@;
4302*4882a593Smuzhiyun				}
4303*4882a593Smuzhiyun			}
4304*4882a593Smuzhiyun		}
4305*4882a593Smuzhiyun
4306*4882a593Smuzhiyun# avoid BUG() or BUG_ON()
4307*4882a593Smuzhiyun		if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
4308*4882a593Smuzhiyun			my $msg_level = \&WARN;
4309*4882a593Smuzhiyun			$msg_level = \&CHK if ($file);
4310*4882a593Smuzhiyun			&{$msg_level}("AVOID_BUG",
4311*4882a593Smuzhiyun				      "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
4312*4882a593Smuzhiyun		}
4313*4882a593Smuzhiyun
4314*4882a593Smuzhiyun# avoid LINUX_VERSION_CODE
4315*4882a593Smuzhiyun		if ($line =~ /\bLINUX_VERSION_CODE\b/) {
4316*4882a593Smuzhiyun			WARN("LINUX_VERSION_CODE",
4317*4882a593Smuzhiyun			     "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
4318*4882a593Smuzhiyun		}
4319*4882a593Smuzhiyun
4320*4882a593Smuzhiyun# check for uses of printk_ratelimit
4321*4882a593Smuzhiyun		if ($line =~ /\bprintk_ratelimit\s*\(/) {
4322*4882a593Smuzhiyun			WARN("PRINTK_RATELIMITED",
4323*4882a593Smuzhiyun			     "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
4324*4882a593Smuzhiyun		}
4325*4882a593Smuzhiyun
4326*4882a593Smuzhiyun# printk should use KERN_* levels
4327*4882a593Smuzhiyun		if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) {
4328*4882a593Smuzhiyun			WARN("PRINTK_WITHOUT_KERN_LEVEL",
4329*4882a593Smuzhiyun			     "printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
4330*4882a593Smuzhiyun		}
4331*4882a593Smuzhiyun
4332*4882a593Smuzhiyun		if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
4333*4882a593Smuzhiyun			my $orig = $1;
4334*4882a593Smuzhiyun			my $level = lc($orig);
4335*4882a593Smuzhiyun			$level = "warn" if ($level eq "warning");
4336*4882a593Smuzhiyun			my $level2 = $level;
4337*4882a593Smuzhiyun			$level2 = "dbg" if ($level eq "debug");
4338*4882a593Smuzhiyun			WARN("PREFER_PR_LEVEL",
4339*4882a593Smuzhiyun			     "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
4340*4882a593Smuzhiyun		}
4341*4882a593Smuzhiyun
4342*4882a593Smuzhiyun		if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
4343*4882a593Smuzhiyun			my $orig = $1;
4344*4882a593Smuzhiyun			my $level = lc($orig);
4345*4882a593Smuzhiyun			$level = "warn" if ($level eq "warning");
4346*4882a593Smuzhiyun			$level = "dbg" if ($level eq "debug");
4347*4882a593Smuzhiyun			WARN("PREFER_DEV_LEVEL",
4348*4882a593Smuzhiyun			     "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr);
4349*4882a593Smuzhiyun		}
4350*4882a593Smuzhiyun
4351*4882a593Smuzhiyun# trace_printk should not be used in production code.
4352*4882a593Smuzhiyun		if ($line =~ /\b(trace_printk|trace_puts|ftrace_vprintk)\s*\(/) {
4353*4882a593Smuzhiyun			WARN("TRACE_PRINTK",
4354*4882a593Smuzhiyun			     "Do not use $1() in production code (this can be ignored if built only with a debug config option)\n" . $herecurr);
4355*4882a593Smuzhiyun		}
4356*4882a593Smuzhiyun
4357*4882a593Smuzhiyun# ENOSYS means "bad syscall nr" and nothing else.  This will have a small
4358*4882a593Smuzhiyun# number of false positives, but assembly files are not checked, so at
4359*4882a593Smuzhiyun# least the arch entry code will not trigger this warning.
4360*4882a593Smuzhiyun		if ($line =~ /\bENOSYS\b/) {
4361*4882a593Smuzhiyun			WARN("ENOSYS",
4362*4882a593Smuzhiyun			     "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr);
4363*4882a593Smuzhiyun		}
4364*4882a593Smuzhiyun
4365*4882a593Smuzhiyun# ENOTSUPP is not a standard error code and should be avoided in new patches.
4366*4882a593Smuzhiyun# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP.
4367*4882a593Smuzhiyun# Similarly to ENOSYS warning a small number of false positives is expected.
4368*4882a593Smuzhiyun		if (!$file && $line =~ /\bENOTSUPP\b/) {
4369*4882a593Smuzhiyun			if (WARN("ENOTSUPP",
4370*4882a593Smuzhiyun				 "ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr) &&
4371*4882a593Smuzhiyun			    $fix) {
4372*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\bENOTSUPP\b/EOPNOTSUPP/;
4373*4882a593Smuzhiyun			}
4374*4882a593Smuzhiyun		}
4375*4882a593Smuzhiyun
4376*4882a593Smuzhiyun# function brace can't be on same line, except for #defines of do while,
4377*4882a593Smuzhiyun# or if closed on same line
4378*4882a593Smuzhiyun		if ($perl_version_ok &&
4379*4882a593Smuzhiyun		    $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
4380*4882a593Smuzhiyun		    $sline !~ /\#\s*define\b.*do\s*\{/ &&
4381*4882a593Smuzhiyun		    $sline !~ /}/) {
4382*4882a593Smuzhiyun			if (ERROR("OPEN_BRACE",
4383*4882a593Smuzhiyun				  "open brace '{' following function definitions go on the next line\n" . $herecurr) &&
4384*4882a593Smuzhiyun			    $fix) {
4385*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
4386*4882a593Smuzhiyun				my $fixed_line = $rawline;
4387*4882a593Smuzhiyun				$fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/;
4388*4882a593Smuzhiyun				my $line1 = $1;
4389*4882a593Smuzhiyun				my $line2 = $2;
4390*4882a593Smuzhiyun				fix_insert_line($fixlinenr, ltrim($line1));
4391*4882a593Smuzhiyun				fix_insert_line($fixlinenr, "\+{");
4392*4882a593Smuzhiyun				if ($line2 !~ /^\s*$/) {
4393*4882a593Smuzhiyun					fix_insert_line($fixlinenr, "\+\t" . trim($line2));
4394*4882a593Smuzhiyun				}
4395*4882a593Smuzhiyun			}
4396*4882a593Smuzhiyun		}
4397*4882a593Smuzhiyun
4398*4882a593Smuzhiyun# open braces for enum, union and struct go on the same line.
4399*4882a593Smuzhiyun		if ($line =~ /^.\s*{/ &&
4400*4882a593Smuzhiyun		    $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
4401*4882a593Smuzhiyun			if (ERROR("OPEN_BRACE",
4402*4882a593Smuzhiyun				  "open brace '{' following $1 go on the same line\n" . $hereprev) &&
4403*4882a593Smuzhiyun			    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
4404*4882a593Smuzhiyun				fix_delete_line($fixlinenr - 1, $prevrawline);
4405*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
4406*4882a593Smuzhiyun				my $fixedline = rtrim($prevrawline) . " {";
4407*4882a593Smuzhiyun				fix_insert_line($fixlinenr, $fixedline);
4408*4882a593Smuzhiyun				$fixedline = $rawline;
4409*4882a593Smuzhiyun				$fixedline =~ s/^(.\s*)\{\s*/$1\t/;
4410*4882a593Smuzhiyun				if ($fixedline !~ /^\+\s*$/) {
4411*4882a593Smuzhiyun					fix_insert_line($fixlinenr, $fixedline);
4412*4882a593Smuzhiyun				}
4413*4882a593Smuzhiyun			}
4414*4882a593Smuzhiyun		}
4415*4882a593Smuzhiyun
4416*4882a593Smuzhiyun# missing space after union, struct or enum definition
4417*4882a593Smuzhiyun		if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) {
4418*4882a593Smuzhiyun			if (WARN("SPACING",
4419*4882a593Smuzhiyun				 "missing space after $1 definition\n" . $herecurr) &&
4420*4882a593Smuzhiyun			    $fix) {
4421*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4422*4882a593Smuzhiyun				    s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
4423*4882a593Smuzhiyun			}
4424*4882a593Smuzhiyun		}
4425*4882a593Smuzhiyun
4426*4882a593Smuzhiyun# Function pointer declarations
4427*4882a593Smuzhiyun# check spacing between type, funcptr, and args
4428*4882a593Smuzhiyun# canonical declaration is "type (*funcptr)(args...)"
4429*4882a593Smuzhiyun		if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) {
4430*4882a593Smuzhiyun			my $declare = $1;
4431*4882a593Smuzhiyun			my $pre_pointer_space = $2;
4432*4882a593Smuzhiyun			my $post_pointer_space = $3;
4433*4882a593Smuzhiyun			my $funcname = $4;
4434*4882a593Smuzhiyun			my $post_funcname_space = $5;
4435*4882a593Smuzhiyun			my $pre_args_space = $6;
4436*4882a593Smuzhiyun
4437*4882a593Smuzhiyun# the $Declare variable will capture all spaces after the type
4438*4882a593Smuzhiyun# so check it for a missing trailing missing space but pointer return types
4439*4882a593Smuzhiyun# don't need a space so don't warn for those.
4440*4882a593Smuzhiyun			my $post_declare_space = "";
4441*4882a593Smuzhiyun			if ($declare =~ /(\s+)$/) {
4442*4882a593Smuzhiyun				$post_declare_space = $1;
4443*4882a593Smuzhiyun				$declare = rtrim($declare);
4444*4882a593Smuzhiyun			}
4445*4882a593Smuzhiyun			if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) {
4446*4882a593Smuzhiyun				WARN("SPACING",
4447*4882a593Smuzhiyun				     "missing space after return type\n" . $herecurr);
4448*4882a593Smuzhiyun				$post_declare_space = " ";
4449*4882a593Smuzhiyun			}
4450*4882a593Smuzhiyun
4451*4882a593Smuzhiyun# unnecessary space "type  (*funcptr)(args...)"
4452*4882a593Smuzhiyun# This test is not currently implemented because these declarations are
4453*4882a593Smuzhiyun# equivalent to
4454*4882a593Smuzhiyun#	int  foo(int bar, ...)
4455*4882a593Smuzhiyun# and this is form shouldn't/doesn't generate a checkpatch warning.
4456*4882a593Smuzhiyun#
4457*4882a593Smuzhiyun#			elsif ($declare =~ /\s{2,}$/) {
4458*4882a593Smuzhiyun#				WARN("SPACING",
4459*4882a593Smuzhiyun#				     "Multiple spaces after return type\n" . $herecurr);
4460*4882a593Smuzhiyun#			}
4461*4882a593Smuzhiyun
4462*4882a593Smuzhiyun# unnecessary space "type ( *funcptr)(args...)"
4463*4882a593Smuzhiyun			if (defined $pre_pointer_space &&
4464*4882a593Smuzhiyun			    $pre_pointer_space =~ /^\s/) {
4465*4882a593Smuzhiyun				WARN("SPACING",
4466*4882a593Smuzhiyun				     "Unnecessary space after function pointer open parenthesis\n" . $herecurr);
4467*4882a593Smuzhiyun			}
4468*4882a593Smuzhiyun
4469*4882a593Smuzhiyun# unnecessary space "type (* funcptr)(args...)"
4470*4882a593Smuzhiyun			if (defined $post_pointer_space &&
4471*4882a593Smuzhiyun			    $post_pointer_space =~ /^\s/) {
4472*4882a593Smuzhiyun				WARN("SPACING",
4473*4882a593Smuzhiyun				     "Unnecessary space before function pointer name\n" . $herecurr);
4474*4882a593Smuzhiyun			}
4475*4882a593Smuzhiyun
4476*4882a593Smuzhiyun# unnecessary space "type (*funcptr )(args...)"
4477*4882a593Smuzhiyun			if (defined $post_funcname_space &&
4478*4882a593Smuzhiyun			    $post_funcname_space =~ /^\s/) {
4479*4882a593Smuzhiyun				WARN("SPACING",
4480*4882a593Smuzhiyun				     "Unnecessary space after function pointer name\n" . $herecurr);
4481*4882a593Smuzhiyun			}
4482*4882a593Smuzhiyun
4483*4882a593Smuzhiyun# unnecessary space "type (*funcptr) (args...)"
4484*4882a593Smuzhiyun			if (defined $pre_args_space &&
4485*4882a593Smuzhiyun			    $pre_args_space =~ /^\s/) {
4486*4882a593Smuzhiyun				WARN("SPACING",
4487*4882a593Smuzhiyun				     "Unnecessary space before function pointer arguments\n" . $herecurr);
4488*4882a593Smuzhiyun			}
4489*4882a593Smuzhiyun
4490*4882a593Smuzhiyun			if (show_type("SPACING") && $fix) {
4491*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4492*4882a593Smuzhiyun				    s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex;
4493*4882a593Smuzhiyun			}
4494*4882a593Smuzhiyun		}
4495*4882a593Smuzhiyun
4496*4882a593Smuzhiyun# check for spacing round square brackets; allowed:
4497*4882a593Smuzhiyun#  1. with a type on the left -- int [] a;
4498*4882a593Smuzhiyun#  2. at the beginning of a line for slice initialisers -- [0...10] = 5,
4499*4882a593Smuzhiyun#  3. inside a curly brace -- = { [0...10] = 5 }
4500*4882a593Smuzhiyun		while ($line =~ /(.*?\s)\[/g) {
4501*4882a593Smuzhiyun			my ($where, $prefix) = ($-[1], $1);
4502*4882a593Smuzhiyun			if ($prefix !~ /$Type\s+$/ &&
4503*4882a593Smuzhiyun			    ($where != 0 || $prefix !~ /^.\s+$/) &&
4504*4882a593Smuzhiyun			    $prefix !~ /[{,:]\s+$/) {
4505*4882a593Smuzhiyun				if (ERROR("BRACKET_SPACE",
4506*4882a593Smuzhiyun					  "space prohibited before open square bracket '['\n" . $herecurr) &&
4507*4882a593Smuzhiyun				    $fix) {
4508*4882a593Smuzhiyun				    $fixed[$fixlinenr] =~
4509*4882a593Smuzhiyun					s/^(\+.*?)\s+\[/$1\[/;
4510*4882a593Smuzhiyun				}
4511*4882a593Smuzhiyun			}
4512*4882a593Smuzhiyun		}
4513*4882a593Smuzhiyun
4514*4882a593Smuzhiyun# check for spaces between functions and their parentheses.
4515*4882a593Smuzhiyun		while ($line =~ /($Ident)\s+\(/g) {
4516*4882a593Smuzhiyun			my $name = $1;
4517*4882a593Smuzhiyun			my $ctx_before = substr($line, 0, $-[1]);
4518*4882a593Smuzhiyun			my $ctx = "$ctx_before$name";
4519*4882a593Smuzhiyun
4520*4882a593Smuzhiyun			# Ignore those directives where spaces _are_ permitted.
4521*4882a593Smuzhiyun			if ($name =~ /^(?:
4522*4882a593Smuzhiyun				if|for|while|switch|return|case|
4523*4882a593Smuzhiyun				volatile|__volatile__|
4524*4882a593Smuzhiyun				__attribute__|format|__extension__|
4525*4882a593Smuzhiyun				asm|__asm__)$/x)
4526*4882a593Smuzhiyun			{
4527*4882a593Smuzhiyun			# cpp #define statements have non-optional spaces, ie
4528*4882a593Smuzhiyun			# if there is a space between the name and the open
4529*4882a593Smuzhiyun			# parenthesis it is simply not a parameter group.
4530*4882a593Smuzhiyun			} elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
4531*4882a593Smuzhiyun
4532*4882a593Smuzhiyun			# cpp #elif statement condition may start with a (
4533*4882a593Smuzhiyun			} elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
4534*4882a593Smuzhiyun
4535*4882a593Smuzhiyun			# If this whole things ends with a type its most
4536*4882a593Smuzhiyun			# likely a typedef for a function.
4537*4882a593Smuzhiyun			} elsif ($ctx =~ /$Type$/) {
4538*4882a593Smuzhiyun
4539*4882a593Smuzhiyun			} else {
4540*4882a593Smuzhiyun				if (WARN("SPACING",
4541*4882a593Smuzhiyun					 "space prohibited between function name and open parenthesis '('\n" . $herecurr) &&
4542*4882a593Smuzhiyun					     $fix) {
4543*4882a593Smuzhiyun					$fixed[$fixlinenr] =~
4544*4882a593Smuzhiyun					    s/\b$name\s+\(/$name\(/;
4545*4882a593Smuzhiyun				}
4546*4882a593Smuzhiyun			}
4547*4882a593Smuzhiyun		}
4548*4882a593Smuzhiyun
4549*4882a593Smuzhiyun# Check operator spacing.
4550*4882a593Smuzhiyun		if (!($line=~/\#\s*include/)) {
4551*4882a593Smuzhiyun			my $fixed_line = "";
4552*4882a593Smuzhiyun			my $line_fixed = 0;
4553*4882a593Smuzhiyun
4554*4882a593Smuzhiyun			my $ops = qr{
4555*4882a593Smuzhiyun				<<=|>>=|<=|>=|==|!=|
4556*4882a593Smuzhiyun				\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
4557*4882a593Smuzhiyun				=>|->|<<|>>|<|>|=|!|~|
4558*4882a593Smuzhiyun				&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
4559*4882a593Smuzhiyun				\?:|\?|:
4560*4882a593Smuzhiyun			}x;
4561*4882a593Smuzhiyun			my @elements = split(/($ops|;)/, $opline);
4562*4882a593Smuzhiyun
4563*4882a593Smuzhiyun##			print("element count: <" . $#elements . ">\n");
4564*4882a593Smuzhiyun##			foreach my $el (@elements) {
4565*4882a593Smuzhiyun##				print("el: <$el>\n");
4566*4882a593Smuzhiyun##			}
4567*4882a593Smuzhiyun
4568*4882a593Smuzhiyun			my @fix_elements = ();
4569*4882a593Smuzhiyun			my $off = 0;
4570*4882a593Smuzhiyun
4571*4882a593Smuzhiyun			foreach my $el (@elements) {
4572*4882a593Smuzhiyun				push(@fix_elements, substr($rawline, $off, length($el)));
4573*4882a593Smuzhiyun				$off += length($el);
4574*4882a593Smuzhiyun			}
4575*4882a593Smuzhiyun
4576*4882a593Smuzhiyun			$off = 0;
4577*4882a593Smuzhiyun
4578*4882a593Smuzhiyun			my $blank = copy_spacing($opline);
4579*4882a593Smuzhiyun			my $last_after = -1;
4580*4882a593Smuzhiyun
4581*4882a593Smuzhiyun			for (my $n = 0; $n < $#elements; $n += 2) {
4582*4882a593Smuzhiyun
4583*4882a593Smuzhiyun				my $good = $fix_elements[$n] . $fix_elements[$n + 1];
4584*4882a593Smuzhiyun
4585*4882a593Smuzhiyun##				print("n: <$n> good: <$good>\n");
4586*4882a593Smuzhiyun
4587*4882a593Smuzhiyun				$off += length($elements[$n]);
4588*4882a593Smuzhiyun
4589*4882a593Smuzhiyun				# Pick up the preceding and succeeding characters.
4590*4882a593Smuzhiyun				my $ca = substr($opline, 0, $off);
4591*4882a593Smuzhiyun				my $cc = '';
4592*4882a593Smuzhiyun				if (length($opline) >= ($off + length($elements[$n + 1]))) {
4593*4882a593Smuzhiyun					$cc = substr($opline, $off + length($elements[$n + 1]));
4594*4882a593Smuzhiyun				}
4595*4882a593Smuzhiyun				my $cb = "$ca$;$cc";
4596*4882a593Smuzhiyun
4597*4882a593Smuzhiyun				my $a = '';
4598*4882a593Smuzhiyun				$a = 'V' if ($elements[$n] ne '');
4599*4882a593Smuzhiyun				$a = 'W' if ($elements[$n] =~ /\s$/);
4600*4882a593Smuzhiyun				$a = 'C' if ($elements[$n] =~ /$;$/);
4601*4882a593Smuzhiyun				$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
4602*4882a593Smuzhiyun				$a = 'O' if ($elements[$n] eq '');
4603*4882a593Smuzhiyun				$a = 'E' if ($ca =~ /^\s*$/);
4604*4882a593Smuzhiyun
4605*4882a593Smuzhiyun				my $op = $elements[$n + 1];
4606*4882a593Smuzhiyun
4607*4882a593Smuzhiyun				my $c = '';
4608*4882a593Smuzhiyun				if (defined $elements[$n + 2]) {
4609*4882a593Smuzhiyun					$c = 'V' if ($elements[$n + 2] ne '');
4610*4882a593Smuzhiyun					$c = 'W' if ($elements[$n + 2] =~ /^\s/);
4611*4882a593Smuzhiyun					$c = 'C' if ($elements[$n + 2] =~ /^$;/);
4612*4882a593Smuzhiyun					$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
4613*4882a593Smuzhiyun					$c = 'O' if ($elements[$n + 2] eq '');
4614*4882a593Smuzhiyun					$c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
4615*4882a593Smuzhiyun				} else {
4616*4882a593Smuzhiyun					$c = 'E';
4617*4882a593Smuzhiyun				}
4618*4882a593Smuzhiyun
4619*4882a593Smuzhiyun				my $ctx = "${a}x${c}";
4620*4882a593Smuzhiyun
4621*4882a593Smuzhiyun				my $at = "(ctx:$ctx)";
4622*4882a593Smuzhiyun
4623*4882a593Smuzhiyun				my $ptr = substr($blank, 0, $off) . "^";
4624*4882a593Smuzhiyun				my $hereptr = "$hereline$ptr\n";
4625*4882a593Smuzhiyun
4626*4882a593Smuzhiyun				# Pull out the value of this operator.
4627*4882a593Smuzhiyun				my $op_type = substr($curr_values, $off + 1, 1);
4628*4882a593Smuzhiyun
4629*4882a593Smuzhiyun				# Get the full operator variant.
4630*4882a593Smuzhiyun				my $opv = $op . substr($curr_vars, $off, 1);
4631*4882a593Smuzhiyun
4632*4882a593Smuzhiyun				# Ignore operators passed as parameters.
4633*4882a593Smuzhiyun				if ($op_type ne 'V' &&
4634*4882a593Smuzhiyun				    $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) {
4635*4882a593Smuzhiyun
4636*4882a593Smuzhiyun#				# Ignore comments
4637*4882a593Smuzhiyun#				} elsif ($op =~ /^$;+$/) {
4638*4882a593Smuzhiyun
4639*4882a593Smuzhiyun				# ; should have either the end of line or a space or \ after it
4640*4882a593Smuzhiyun				} elsif ($op eq ';') {
4641*4882a593Smuzhiyun					if ($ctx !~ /.x[WEBC]/ &&
4642*4882a593Smuzhiyun					    $cc !~ /^\\/ && $cc !~ /^;/) {
4643*4882a593Smuzhiyun						if (ERROR("SPACING",
4644*4882a593Smuzhiyun							  "space required after that '$op' $at\n" . $hereptr)) {
4645*4882a593Smuzhiyun							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
4646*4882a593Smuzhiyun							$line_fixed = 1;
4647*4882a593Smuzhiyun						}
4648*4882a593Smuzhiyun					}
4649*4882a593Smuzhiyun
4650*4882a593Smuzhiyun				# // is a comment
4651*4882a593Smuzhiyun				} elsif ($op eq '//') {
4652*4882a593Smuzhiyun
4653*4882a593Smuzhiyun				#   :   when part of a bitfield
4654*4882a593Smuzhiyun				} elsif ($opv eq ':B') {
4655*4882a593Smuzhiyun					# skip the bitfield test for now
4656*4882a593Smuzhiyun
4657*4882a593Smuzhiyun				# No spaces for:
4658*4882a593Smuzhiyun				#   ->
4659*4882a593Smuzhiyun				} elsif ($op eq '->') {
4660*4882a593Smuzhiyun					if ($ctx =~ /Wx.|.xW/) {
4661*4882a593Smuzhiyun						if (ERROR("SPACING",
4662*4882a593Smuzhiyun							  "spaces prohibited around that '$op' $at\n" . $hereptr)) {
4663*4882a593Smuzhiyun							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4664*4882a593Smuzhiyun							if (defined $fix_elements[$n + 2]) {
4665*4882a593Smuzhiyun								$fix_elements[$n + 2] =~ s/^\s+//;
4666*4882a593Smuzhiyun							}
4667*4882a593Smuzhiyun							$line_fixed = 1;
4668*4882a593Smuzhiyun						}
4669*4882a593Smuzhiyun					}
4670*4882a593Smuzhiyun
4671*4882a593Smuzhiyun				# , must not have a space before and must have a space on the right.
4672*4882a593Smuzhiyun				} elsif ($op eq ',') {
4673*4882a593Smuzhiyun					my $rtrim_before = 0;
4674*4882a593Smuzhiyun					my $space_after = 0;
4675*4882a593Smuzhiyun					if ($ctx =~ /Wx./) {
4676*4882a593Smuzhiyun						if (ERROR("SPACING",
4677*4882a593Smuzhiyun							  "space prohibited before that '$op' $at\n" . $hereptr)) {
4678*4882a593Smuzhiyun							$line_fixed = 1;
4679*4882a593Smuzhiyun							$rtrim_before = 1;
4680*4882a593Smuzhiyun						}
4681*4882a593Smuzhiyun					}
4682*4882a593Smuzhiyun					if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
4683*4882a593Smuzhiyun						if (ERROR("SPACING",
4684*4882a593Smuzhiyun							  "space required after that '$op' $at\n" . $hereptr)) {
4685*4882a593Smuzhiyun							$line_fixed = 1;
4686*4882a593Smuzhiyun							$last_after = $n;
4687*4882a593Smuzhiyun							$space_after = 1;
4688*4882a593Smuzhiyun						}
4689*4882a593Smuzhiyun					}
4690*4882a593Smuzhiyun					if ($rtrim_before || $space_after) {
4691*4882a593Smuzhiyun						if ($rtrim_before) {
4692*4882a593Smuzhiyun							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4693*4882a593Smuzhiyun						} else {
4694*4882a593Smuzhiyun							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
4695*4882a593Smuzhiyun						}
4696*4882a593Smuzhiyun						if ($space_after) {
4697*4882a593Smuzhiyun							$good .= " ";
4698*4882a593Smuzhiyun						}
4699*4882a593Smuzhiyun					}
4700*4882a593Smuzhiyun
4701*4882a593Smuzhiyun				# '*' as part of a type definition -- reported already.
4702*4882a593Smuzhiyun				} elsif ($opv eq '*_') {
4703*4882a593Smuzhiyun					#warn "'*' is part of type\n";
4704*4882a593Smuzhiyun
4705*4882a593Smuzhiyun				# unary operators should have a space before and
4706*4882a593Smuzhiyun				# none after.  May be left adjacent to another
4707*4882a593Smuzhiyun				# unary operator, or a cast
4708*4882a593Smuzhiyun				} elsif ($op eq '!' || $op eq '~' ||
4709*4882a593Smuzhiyun					 $opv eq '*U' || $opv eq '-U' ||
4710*4882a593Smuzhiyun					 $opv eq '&U' || $opv eq '&&U') {
4711*4882a593Smuzhiyun					if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
4712*4882a593Smuzhiyun						if (ERROR("SPACING",
4713*4882a593Smuzhiyun							  "space required before that '$op' $at\n" . $hereptr)) {
4714*4882a593Smuzhiyun							if ($n != $last_after + 2) {
4715*4882a593Smuzhiyun								$good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]);
4716*4882a593Smuzhiyun								$line_fixed = 1;
4717*4882a593Smuzhiyun							}
4718*4882a593Smuzhiyun						}
4719*4882a593Smuzhiyun					}
4720*4882a593Smuzhiyun					if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
4721*4882a593Smuzhiyun						# A unary '*' may be const
4722*4882a593Smuzhiyun
4723*4882a593Smuzhiyun					} elsif ($ctx =~ /.xW/) {
4724*4882a593Smuzhiyun						if (ERROR("SPACING",
4725*4882a593Smuzhiyun							  "space prohibited after that '$op' $at\n" . $hereptr)) {
4726*4882a593Smuzhiyun							$good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]);
4727*4882a593Smuzhiyun							if (defined $fix_elements[$n + 2]) {
4728*4882a593Smuzhiyun								$fix_elements[$n + 2] =~ s/^\s+//;
4729*4882a593Smuzhiyun							}
4730*4882a593Smuzhiyun							$line_fixed = 1;
4731*4882a593Smuzhiyun						}
4732*4882a593Smuzhiyun					}
4733*4882a593Smuzhiyun
4734*4882a593Smuzhiyun				# unary ++ and unary -- are allowed no space on one side.
4735*4882a593Smuzhiyun				} elsif ($op eq '++' or $op eq '--') {
4736*4882a593Smuzhiyun					if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
4737*4882a593Smuzhiyun						if (ERROR("SPACING",
4738*4882a593Smuzhiyun							  "space required one side of that '$op' $at\n" . $hereptr)) {
4739*4882a593Smuzhiyun							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
4740*4882a593Smuzhiyun							$line_fixed = 1;
4741*4882a593Smuzhiyun						}
4742*4882a593Smuzhiyun					}
4743*4882a593Smuzhiyun					if ($ctx =~ /Wx[BE]/ ||
4744*4882a593Smuzhiyun					    ($ctx =~ /Wx./ && $cc =~ /^;/)) {
4745*4882a593Smuzhiyun						if (ERROR("SPACING",
4746*4882a593Smuzhiyun							  "space prohibited before that '$op' $at\n" . $hereptr)) {
4747*4882a593Smuzhiyun							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4748*4882a593Smuzhiyun							$line_fixed = 1;
4749*4882a593Smuzhiyun						}
4750*4882a593Smuzhiyun					}
4751*4882a593Smuzhiyun					if ($ctx =~ /ExW/) {
4752*4882a593Smuzhiyun						if (ERROR("SPACING",
4753*4882a593Smuzhiyun							  "space prohibited after that '$op' $at\n" . $hereptr)) {
4754*4882a593Smuzhiyun							$good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
4755*4882a593Smuzhiyun							if (defined $fix_elements[$n + 2]) {
4756*4882a593Smuzhiyun								$fix_elements[$n + 2] =~ s/^\s+//;
4757*4882a593Smuzhiyun							}
4758*4882a593Smuzhiyun							$line_fixed = 1;
4759*4882a593Smuzhiyun						}
4760*4882a593Smuzhiyun					}
4761*4882a593Smuzhiyun
4762*4882a593Smuzhiyun				# << and >> may either have or not have spaces both sides
4763*4882a593Smuzhiyun				} elsif ($op eq '<<' or $op eq '>>' or
4764*4882a593Smuzhiyun					 $op eq '&' or $op eq '^' or $op eq '|' or
4765*4882a593Smuzhiyun					 $op eq '+' or $op eq '-' or
4766*4882a593Smuzhiyun					 $op eq '*' or $op eq '/' or
4767*4882a593Smuzhiyun					 $op eq '%')
4768*4882a593Smuzhiyun				{
4769*4882a593Smuzhiyun					if ($check) {
4770*4882a593Smuzhiyun						if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) {
4771*4882a593Smuzhiyun							if (CHK("SPACING",
4772*4882a593Smuzhiyun								"spaces preferred around that '$op' $at\n" . $hereptr)) {
4773*4882a593Smuzhiyun								$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4774*4882a593Smuzhiyun								$fix_elements[$n + 2] =~ s/^\s+//;
4775*4882a593Smuzhiyun								$line_fixed = 1;
4776*4882a593Smuzhiyun							}
4777*4882a593Smuzhiyun						} elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) {
4778*4882a593Smuzhiyun							if (CHK("SPACING",
4779*4882a593Smuzhiyun								"space preferred before that '$op' $at\n" . $hereptr)) {
4780*4882a593Smuzhiyun								$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]);
4781*4882a593Smuzhiyun								$line_fixed = 1;
4782*4882a593Smuzhiyun							}
4783*4882a593Smuzhiyun						}
4784*4882a593Smuzhiyun					} elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
4785*4882a593Smuzhiyun						if (ERROR("SPACING",
4786*4882a593Smuzhiyun							  "need consistent spacing around '$op' $at\n" . $hereptr)) {
4787*4882a593Smuzhiyun							$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4788*4882a593Smuzhiyun							if (defined $fix_elements[$n + 2]) {
4789*4882a593Smuzhiyun								$fix_elements[$n + 2] =~ s/^\s+//;
4790*4882a593Smuzhiyun							}
4791*4882a593Smuzhiyun							$line_fixed = 1;
4792*4882a593Smuzhiyun						}
4793*4882a593Smuzhiyun					}
4794*4882a593Smuzhiyun
4795*4882a593Smuzhiyun				# A colon needs no spaces before when it is
4796*4882a593Smuzhiyun				# terminating a case value or a label.
4797*4882a593Smuzhiyun				} elsif ($opv eq ':C' || $opv eq ':L') {
4798*4882a593Smuzhiyun					if ($ctx =~ /Wx./) {
4799*4882a593Smuzhiyun						if (ERROR("SPACING",
4800*4882a593Smuzhiyun							  "space prohibited before that '$op' $at\n" . $hereptr)) {
4801*4882a593Smuzhiyun							$good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4802*4882a593Smuzhiyun							$line_fixed = 1;
4803*4882a593Smuzhiyun						}
4804*4882a593Smuzhiyun					}
4805*4882a593Smuzhiyun
4806*4882a593Smuzhiyun				# All the others need spaces both sides.
4807*4882a593Smuzhiyun				} elsif ($ctx !~ /[EWC]x[CWE]/) {
4808*4882a593Smuzhiyun					my $ok = 0;
4809*4882a593Smuzhiyun
4810*4882a593Smuzhiyun					# Ignore email addresses <foo@bar>
4811*4882a593Smuzhiyun					if (($op eq '<' &&
4812*4882a593Smuzhiyun					     $cc =~ /^\S+\@\S+>/) ||
4813*4882a593Smuzhiyun					    ($op eq '>' &&
4814*4882a593Smuzhiyun					     $ca =~ /<\S+\@\S+$/))
4815*4882a593Smuzhiyun					{
4816*4882a593Smuzhiyun						$ok = 1;
4817*4882a593Smuzhiyun					}
4818*4882a593Smuzhiyun
4819*4882a593Smuzhiyun					# for asm volatile statements
4820*4882a593Smuzhiyun					# ignore a colon with another
4821*4882a593Smuzhiyun					# colon immediately before or after
4822*4882a593Smuzhiyun					if (($op eq ':') &&
4823*4882a593Smuzhiyun					    ($ca =~ /:$/ || $cc =~ /^:/)) {
4824*4882a593Smuzhiyun						$ok = 1;
4825*4882a593Smuzhiyun					}
4826*4882a593Smuzhiyun
4827*4882a593Smuzhiyun					# messages are ERROR, but ?: are CHK
4828*4882a593Smuzhiyun					if ($ok == 0) {
4829*4882a593Smuzhiyun						my $msg_level = \&ERROR;
4830*4882a593Smuzhiyun						$msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
4831*4882a593Smuzhiyun
4832*4882a593Smuzhiyun						if (&{$msg_level}("SPACING",
4833*4882a593Smuzhiyun								  "spaces required around that '$op' $at\n" . $hereptr)) {
4834*4882a593Smuzhiyun							$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4835*4882a593Smuzhiyun							if (defined $fix_elements[$n + 2]) {
4836*4882a593Smuzhiyun								$fix_elements[$n + 2] =~ s/^\s+//;
4837*4882a593Smuzhiyun							}
4838*4882a593Smuzhiyun							$line_fixed = 1;
4839*4882a593Smuzhiyun						}
4840*4882a593Smuzhiyun					}
4841*4882a593Smuzhiyun				}
4842*4882a593Smuzhiyun				$off += length($elements[$n + 1]);
4843*4882a593Smuzhiyun
4844*4882a593Smuzhiyun##				print("n: <$n> GOOD: <$good>\n");
4845*4882a593Smuzhiyun
4846*4882a593Smuzhiyun				$fixed_line = $fixed_line . $good;
4847*4882a593Smuzhiyun			}
4848*4882a593Smuzhiyun
4849*4882a593Smuzhiyun			if (($#elements % 2) == 0) {
4850*4882a593Smuzhiyun				$fixed_line = $fixed_line . $fix_elements[$#elements];
4851*4882a593Smuzhiyun			}
4852*4882a593Smuzhiyun
4853*4882a593Smuzhiyun			if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) {
4854*4882a593Smuzhiyun				$fixed[$fixlinenr] = $fixed_line;
4855*4882a593Smuzhiyun			}
4856*4882a593Smuzhiyun
4857*4882a593Smuzhiyun
4858*4882a593Smuzhiyun		}
4859*4882a593Smuzhiyun
4860*4882a593Smuzhiyun# check for whitespace before a non-naked semicolon
4861*4882a593Smuzhiyun		if ($line =~ /^\+.*\S\s+;\s*$/) {
4862*4882a593Smuzhiyun			if (WARN("SPACING",
4863*4882a593Smuzhiyun				 "space prohibited before semicolon\n" . $herecurr) &&
4864*4882a593Smuzhiyun			    $fix) {
4865*4882a593Smuzhiyun				1 while $fixed[$fixlinenr] =~
4866*4882a593Smuzhiyun				    s/^(\+.*\S)\s+;/$1;/;
4867*4882a593Smuzhiyun			}
4868*4882a593Smuzhiyun		}
4869*4882a593Smuzhiyun
4870*4882a593Smuzhiyun# check for multiple assignments
4871*4882a593Smuzhiyun		if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
4872*4882a593Smuzhiyun			CHK("MULTIPLE_ASSIGNMENTS",
4873*4882a593Smuzhiyun			    "multiple assignments should be avoided\n" . $herecurr);
4874*4882a593Smuzhiyun		}
4875*4882a593Smuzhiyun
4876*4882a593Smuzhiyun## # check for multiple declarations, allowing for a function declaration
4877*4882a593Smuzhiyun## # continuation.
4878*4882a593Smuzhiyun## 		if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
4879*4882a593Smuzhiyun## 		    $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
4880*4882a593Smuzhiyun##
4881*4882a593Smuzhiyun## 			# Remove any bracketed sections to ensure we do not
4882*4882a593Smuzhiyun## 			# falsly report the parameters of functions.
4883*4882a593Smuzhiyun## 			my $ln = $line;
4884*4882a593Smuzhiyun## 			while ($ln =~ s/\([^\(\)]*\)//g) {
4885*4882a593Smuzhiyun## 			}
4886*4882a593Smuzhiyun## 			if ($ln =~ /,/) {
4887*4882a593Smuzhiyun## 				WARN("MULTIPLE_DECLARATION",
4888*4882a593Smuzhiyun##				     "declaring multiple variables together should be avoided\n" . $herecurr);
4889*4882a593Smuzhiyun## 			}
4890*4882a593Smuzhiyun## 		}
4891*4882a593Smuzhiyun
4892*4882a593Smuzhiyun#need space before brace following if, while, etc
4893*4882a593Smuzhiyun		if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
4894*4882a593Smuzhiyun		    $line =~ /\b(?:else|do)\{/) {
4895*4882a593Smuzhiyun			if (ERROR("SPACING",
4896*4882a593Smuzhiyun				  "space required before the open brace '{'\n" . $herecurr) &&
4897*4882a593Smuzhiyun			    $fix) {
4898*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
4899*4882a593Smuzhiyun			}
4900*4882a593Smuzhiyun		}
4901*4882a593Smuzhiyun
4902*4882a593Smuzhiyun## # check for blank lines before declarations
4903*4882a593Smuzhiyun##		if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ &&
4904*4882a593Smuzhiyun##		    $prevrawline =~ /^.\s*$/) {
4905*4882a593Smuzhiyun##			WARN("SPACING",
4906*4882a593Smuzhiyun##			     "No blank lines before declarations\n" . $hereprev);
4907*4882a593Smuzhiyun##		}
4908*4882a593Smuzhiyun##
4909*4882a593Smuzhiyun
4910*4882a593Smuzhiyun# closing brace should have a space following it when it has anything
4911*4882a593Smuzhiyun# on the line
4912*4882a593Smuzhiyun		if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
4913*4882a593Smuzhiyun			if (ERROR("SPACING",
4914*4882a593Smuzhiyun				  "space required after that close brace '}'\n" . $herecurr) &&
4915*4882a593Smuzhiyun			    $fix) {
4916*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4917*4882a593Smuzhiyun				    s/}((?!(?:,|;|\)))\S)/} $1/;
4918*4882a593Smuzhiyun			}
4919*4882a593Smuzhiyun		}
4920*4882a593Smuzhiyun
4921*4882a593Smuzhiyun# check spacing on square brackets
4922*4882a593Smuzhiyun		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
4923*4882a593Smuzhiyun			if (ERROR("SPACING",
4924*4882a593Smuzhiyun				  "space prohibited after that open square bracket '['\n" . $herecurr) &&
4925*4882a593Smuzhiyun			    $fix) {
4926*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4927*4882a593Smuzhiyun				    s/\[\s+/\[/;
4928*4882a593Smuzhiyun			}
4929*4882a593Smuzhiyun		}
4930*4882a593Smuzhiyun		if ($line =~ /\s\]/) {
4931*4882a593Smuzhiyun			if (ERROR("SPACING",
4932*4882a593Smuzhiyun				  "space prohibited before that close square bracket ']'\n" . $herecurr) &&
4933*4882a593Smuzhiyun			    $fix) {
4934*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4935*4882a593Smuzhiyun				    s/\s+\]/\]/;
4936*4882a593Smuzhiyun			}
4937*4882a593Smuzhiyun		}
4938*4882a593Smuzhiyun
4939*4882a593Smuzhiyun# check spacing on parentheses
4940*4882a593Smuzhiyun		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
4941*4882a593Smuzhiyun		    $line !~ /for\s*\(\s+;/) {
4942*4882a593Smuzhiyun			if (ERROR("SPACING",
4943*4882a593Smuzhiyun				  "space prohibited after that open parenthesis '('\n" . $herecurr) &&
4944*4882a593Smuzhiyun			    $fix) {
4945*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4946*4882a593Smuzhiyun				    s/\(\s+/\(/;
4947*4882a593Smuzhiyun			}
4948*4882a593Smuzhiyun		}
4949*4882a593Smuzhiyun		if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
4950*4882a593Smuzhiyun		    $line !~ /for\s*\(.*;\s+\)/ &&
4951*4882a593Smuzhiyun		    $line !~ /:\s+\)/) {
4952*4882a593Smuzhiyun			if (ERROR("SPACING",
4953*4882a593Smuzhiyun				  "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
4954*4882a593Smuzhiyun			    $fix) {
4955*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
4956*4882a593Smuzhiyun				    s/\s+\)/\)/;
4957*4882a593Smuzhiyun			}
4958*4882a593Smuzhiyun		}
4959*4882a593Smuzhiyun
4960*4882a593Smuzhiyun# check unnecessary parentheses around addressof/dereference single $Lvals
4961*4882a593Smuzhiyun# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar
4962*4882a593Smuzhiyun
4963*4882a593Smuzhiyun		while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) {
4964*4882a593Smuzhiyun			my $var = $1;
4965*4882a593Smuzhiyun			if (CHK("UNNECESSARY_PARENTHESES",
4966*4882a593Smuzhiyun				"Unnecessary parentheses around $var\n" . $herecurr) &&
4967*4882a593Smuzhiyun			    $fix) {
4968*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/;
4969*4882a593Smuzhiyun			}
4970*4882a593Smuzhiyun		}
4971*4882a593Smuzhiyun
4972*4882a593Smuzhiyun# check for unnecessary parentheses around function pointer uses
4973*4882a593Smuzhiyun# ie: (foo->bar)(); should be foo->bar();
4974*4882a593Smuzhiyun# but not "if (foo->bar) (" to avoid some false positives
4975*4882a593Smuzhiyun		if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) {
4976*4882a593Smuzhiyun			my $var = $2;
4977*4882a593Smuzhiyun			if (CHK("UNNECESSARY_PARENTHESES",
4978*4882a593Smuzhiyun				"Unnecessary parentheses around function pointer $var\n" . $herecurr) &&
4979*4882a593Smuzhiyun			    $fix) {
4980*4882a593Smuzhiyun				my $var2 = deparenthesize($var);
4981*4882a593Smuzhiyun				$var2 =~ s/\s//g;
4982*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\Q$var\E/$var2/;
4983*4882a593Smuzhiyun			}
4984*4882a593Smuzhiyun		}
4985*4882a593Smuzhiyun
4986*4882a593Smuzhiyun# check for unnecessary parentheses around comparisons in if uses
4987*4882a593Smuzhiyun# when !drivers/staging or command-line uses --strict
4988*4882a593Smuzhiyun		if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
4989*4882a593Smuzhiyun		    $perl_version_ok && defined($stat) &&
4990*4882a593Smuzhiyun		    $stat =~ /(^.\s*if\s*($balanced_parens))/) {
4991*4882a593Smuzhiyun			my $if_stat = $1;
4992*4882a593Smuzhiyun			my $test = substr($2, 1, -1);
4993*4882a593Smuzhiyun			my $herectx;
4994*4882a593Smuzhiyun			while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) {
4995*4882a593Smuzhiyun				my $match = $1;
4996*4882a593Smuzhiyun				# avoid parentheses around potential macro args
4997*4882a593Smuzhiyun				next if ($match =~ /^\s*\w+\s*$/);
4998*4882a593Smuzhiyun				if (!defined($herectx)) {
4999*4882a593Smuzhiyun					$herectx = $here . "\n";
5000*4882a593Smuzhiyun					my $cnt = statement_rawlines($if_stat);
5001*4882a593Smuzhiyun					for (my $n = 0; $n < $cnt; $n++) {
5002*4882a593Smuzhiyun						my $rl = raw_line($linenr, $n);
5003*4882a593Smuzhiyun						$herectx .=  $rl . "\n";
5004*4882a593Smuzhiyun						last if $rl =~ /^[ \+].*\{/;
5005*4882a593Smuzhiyun					}
5006*4882a593Smuzhiyun				}
5007*4882a593Smuzhiyun				CHK("UNNECESSARY_PARENTHESES",
5008*4882a593Smuzhiyun				    "Unnecessary parentheses around '$match'\n" . $herectx);
5009*4882a593Smuzhiyun			}
5010*4882a593Smuzhiyun		}
5011*4882a593Smuzhiyun
5012*4882a593Smuzhiyun#goto labels aren't indented, allow a single space however
5013*4882a593Smuzhiyun		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
5014*4882a593Smuzhiyun		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
5015*4882a593Smuzhiyun			if (WARN("INDENTED_LABEL",
5016*4882a593Smuzhiyun				 "labels should not be indented\n" . $herecurr) &&
5017*4882a593Smuzhiyun			    $fix) {
5018*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
5019*4882a593Smuzhiyun				    s/^(.)\s+/$1/;
5020*4882a593Smuzhiyun			}
5021*4882a593Smuzhiyun		}
5022*4882a593Smuzhiyun
5023*4882a593Smuzhiyun# check if a statement with a comma should be two statements like:
5024*4882a593Smuzhiyun#	foo = bar(),	/* comma should be semicolon */
5025*4882a593Smuzhiyun#	bar = baz();
5026*4882a593Smuzhiyun		if (defined($stat) &&
5027*4882a593Smuzhiyun		    $stat =~ /^\+\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*,\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*;\s*$/) {
5028*4882a593Smuzhiyun			my $cnt = statement_rawlines($stat);
5029*4882a593Smuzhiyun			my $herectx = get_stat_here($linenr, $cnt, $here);
5030*4882a593Smuzhiyun			WARN("SUSPECT_COMMA_SEMICOLON",
5031*4882a593Smuzhiyun			     "Possible comma where semicolon could be used\n" . $herectx);
5032*4882a593Smuzhiyun		}
5033*4882a593Smuzhiyun
5034*4882a593Smuzhiyun# return is not a function
5035*4882a593Smuzhiyun		if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
5036*4882a593Smuzhiyun			my $spacing = $1;
5037*4882a593Smuzhiyun			if ($perl_version_ok &&
5038*4882a593Smuzhiyun			    $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
5039*4882a593Smuzhiyun				my $value = $1;
5040*4882a593Smuzhiyun				$value = deparenthesize($value);
5041*4882a593Smuzhiyun				if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
5042*4882a593Smuzhiyun					ERROR("RETURN_PARENTHESES",
5043*4882a593Smuzhiyun					      "return is not a function, parentheses are not required\n" . $herecurr);
5044*4882a593Smuzhiyun				}
5045*4882a593Smuzhiyun			} elsif ($spacing !~ /\s+/) {
5046*4882a593Smuzhiyun				ERROR("SPACING",
5047*4882a593Smuzhiyun				      "space required before the open parenthesis '('\n" . $herecurr);
5048*4882a593Smuzhiyun			}
5049*4882a593Smuzhiyun		}
5050*4882a593Smuzhiyun
5051*4882a593Smuzhiyun# unnecessary return in a void function
5052*4882a593Smuzhiyun# at end-of-function, with the previous line a single leading tab, then return;
5053*4882a593Smuzhiyun# and the line before that not a goto label target like "out:"
5054*4882a593Smuzhiyun		if ($sline =~ /^[ \+]}\s*$/ &&
5055*4882a593Smuzhiyun		    $prevline =~ /^\+\treturn\s*;\s*$/ &&
5056*4882a593Smuzhiyun		    $linenr >= 3 &&
5057*4882a593Smuzhiyun		    $lines[$linenr - 3] =~ /^[ +]/ &&
5058*4882a593Smuzhiyun		    $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) {
5059*4882a593Smuzhiyun			WARN("RETURN_VOID",
5060*4882a593Smuzhiyun			     "void function return statements are not generally useful\n" . $hereprev);
5061*4882a593Smuzhiyun               }
5062*4882a593Smuzhiyun
5063*4882a593Smuzhiyun# if statements using unnecessary parentheses - ie: if ((foo == bar))
5064*4882a593Smuzhiyun		if ($perl_version_ok &&
5065*4882a593Smuzhiyun		    $line =~ /\bif\s*((?:\(\s*){2,})/) {
5066*4882a593Smuzhiyun			my $openparens = $1;
5067*4882a593Smuzhiyun			my $count = $openparens =~ tr@\(@\(@;
5068*4882a593Smuzhiyun			my $msg = "";
5069*4882a593Smuzhiyun			if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
5070*4882a593Smuzhiyun				my $comp = $4;	#Not $1 because of $LvalOrFunc
5071*4882a593Smuzhiyun				$msg = " - maybe == should be = ?" if ($comp eq "==");
5072*4882a593Smuzhiyun				WARN("UNNECESSARY_PARENTHESES",
5073*4882a593Smuzhiyun				     "Unnecessary parentheses$msg\n" . $herecurr);
5074*4882a593Smuzhiyun			}
5075*4882a593Smuzhiyun		}
5076*4882a593Smuzhiyun
5077*4882a593Smuzhiyun# comparisons with a constant or upper case identifier on the left
5078*4882a593Smuzhiyun#	avoid cases like "foo + BAR < baz"
5079*4882a593Smuzhiyun#	only fix matches surrounded by parentheses to avoid incorrect
5080*4882a593Smuzhiyun#	conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
5081*4882a593Smuzhiyun		if ($perl_version_ok &&
5082*4882a593Smuzhiyun		    $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
5083*4882a593Smuzhiyun			my $lead = $1;
5084*4882a593Smuzhiyun			my $const = $2;
5085*4882a593Smuzhiyun			my $comp = $3;
5086*4882a593Smuzhiyun			my $to = $4;
5087*4882a593Smuzhiyun			my $newcomp = $comp;
5088*4882a593Smuzhiyun			if ($lead !~ /(?:$Operators|\.)\s*$/ &&
5089*4882a593Smuzhiyun			    $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
5090*4882a593Smuzhiyun			    WARN("CONSTANT_COMPARISON",
5091*4882a593Smuzhiyun				 "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
5092*4882a593Smuzhiyun			    $fix) {
5093*4882a593Smuzhiyun				if ($comp eq "<") {
5094*4882a593Smuzhiyun					$newcomp = ">";
5095*4882a593Smuzhiyun				} elsif ($comp eq "<=") {
5096*4882a593Smuzhiyun					$newcomp = ">=";
5097*4882a593Smuzhiyun				} elsif ($comp eq ">") {
5098*4882a593Smuzhiyun					$newcomp = "<";
5099*4882a593Smuzhiyun				} elsif ($comp eq ">=") {
5100*4882a593Smuzhiyun					$newcomp = "<=";
5101*4882a593Smuzhiyun				}
5102*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/;
5103*4882a593Smuzhiyun			}
5104*4882a593Smuzhiyun		}
5105*4882a593Smuzhiyun
5106*4882a593Smuzhiyun# Return of what appears to be an errno should normally be negative
5107*4882a593Smuzhiyun		if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
5108*4882a593Smuzhiyun			my $name = $1;
5109*4882a593Smuzhiyun			if ($name ne 'EOF' && $name ne 'ERROR') {
5110*4882a593Smuzhiyun				WARN("USE_NEGATIVE_ERRNO",
5111*4882a593Smuzhiyun				     "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
5112*4882a593Smuzhiyun			}
5113*4882a593Smuzhiyun		}
5114*4882a593Smuzhiyun
5115*4882a593Smuzhiyun# Need a space before open parenthesis after if, while etc
5116*4882a593Smuzhiyun		if ($line =~ /\b(if|while|for|switch)\(/) {
5117*4882a593Smuzhiyun			if (ERROR("SPACING",
5118*4882a593Smuzhiyun				  "space required before the open parenthesis '('\n" . $herecurr) &&
5119*4882a593Smuzhiyun			    $fix) {
5120*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
5121*4882a593Smuzhiyun				    s/\b(if|while|for|switch)\(/$1 \(/;
5122*4882a593Smuzhiyun			}
5123*4882a593Smuzhiyun		}
5124*4882a593Smuzhiyun
5125*4882a593Smuzhiyun# Check for illegal assignment in if conditional -- and check for trailing
5126*4882a593Smuzhiyun# statements after the conditional.
5127*4882a593Smuzhiyun		if ($line =~ /do\s*(?!{)/) {
5128*4882a593Smuzhiyun			($stat, $cond, $line_nr_next, $remain_next, $off_next) =
5129*4882a593Smuzhiyun				ctx_statement_block($linenr, $realcnt, 0)
5130*4882a593Smuzhiyun					if (!defined $stat);
5131*4882a593Smuzhiyun			my ($stat_next) = ctx_statement_block($line_nr_next,
5132*4882a593Smuzhiyun						$remain_next, $off_next);
5133*4882a593Smuzhiyun			$stat_next =~ s/\n./\n /g;
5134*4882a593Smuzhiyun			##print "stat<$stat> stat_next<$stat_next>\n";
5135*4882a593Smuzhiyun
5136*4882a593Smuzhiyun			if ($stat_next =~ /^\s*while\b/) {
5137*4882a593Smuzhiyun				# If the statement carries leading newlines,
5138*4882a593Smuzhiyun				# then count those as offsets.
5139*4882a593Smuzhiyun				my ($whitespace) =
5140*4882a593Smuzhiyun					($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
5141*4882a593Smuzhiyun				my $offset =
5142*4882a593Smuzhiyun					statement_rawlines($whitespace) - 1;
5143*4882a593Smuzhiyun
5144*4882a593Smuzhiyun				$suppress_whiletrailers{$line_nr_next +
5145*4882a593Smuzhiyun								$offset} = 1;
5146*4882a593Smuzhiyun			}
5147*4882a593Smuzhiyun		}
5148*4882a593Smuzhiyun		if (!defined $suppress_whiletrailers{$linenr} &&
5149*4882a593Smuzhiyun		    defined($stat) && defined($cond) &&
5150*4882a593Smuzhiyun		    $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
5151*4882a593Smuzhiyun			my ($s, $c) = ($stat, $cond);
5152*4882a593Smuzhiyun
5153*4882a593Smuzhiyun			if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
5154*4882a593Smuzhiyun				if (ERROR("ASSIGN_IN_IF",
5155*4882a593Smuzhiyun					  "do not use assignment in if condition\n" . $herecurr) &&
5156*4882a593Smuzhiyun				    $fix && $perl_version_ok) {
5157*4882a593Smuzhiyun					if ($rawline =~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=\s*$LvalOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) {
5158*4882a593Smuzhiyun						my $space = $1;
5159*4882a593Smuzhiyun						my $not = $2;
5160*4882a593Smuzhiyun						my $statement = $3;
5161*4882a593Smuzhiyun						my $assigned = $4;
5162*4882a593Smuzhiyun						my $test = $8;
5163*4882a593Smuzhiyun						my $against = $9;
5164*4882a593Smuzhiyun						my $brace = $15;
5165*4882a593Smuzhiyun						fix_delete_line($fixlinenr, $rawline);
5166*4882a593Smuzhiyun						fix_insert_line($fixlinenr, "$space$statement;");
5167*4882a593Smuzhiyun						my $newline = "${space}if (";
5168*4882a593Smuzhiyun						$newline .= '!' if defined($not);
5169*4882a593Smuzhiyun						$newline .= '(' if (defined $not && defined($test) && defined($against));
5170*4882a593Smuzhiyun						$newline .= "$assigned";
5171*4882a593Smuzhiyun						$newline .= " $test $against" if (defined($test) && defined($against));
5172*4882a593Smuzhiyun						$newline .= ')' if (defined $not && defined($test) && defined($against));
5173*4882a593Smuzhiyun						$newline .= ')';
5174*4882a593Smuzhiyun						$newline .= " {" if (defined($brace));
5175*4882a593Smuzhiyun						fix_insert_line($fixlinenr + 1, $newline);
5176*4882a593Smuzhiyun					}
5177*4882a593Smuzhiyun				}
5178*4882a593Smuzhiyun			}
5179*4882a593Smuzhiyun
5180*4882a593Smuzhiyun			# Find out what is on the end of the line after the
5181*4882a593Smuzhiyun			# conditional.
5182*4882a593Smuzhiyun			substr($s, 0, length($c), '');
5183*4882a593Smuzhiyun			$s =~ s/\n.*//g;
5184*4882a593Smuzhiyun			$s =~ s/$;//g;	# Remove any comments
5185*4882a593Smuzhiyun			if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
5186*4882a593Smuzhiyun			    $c !~ /}\s*while\s*/)
5187*4882a593Smuzhiyun			{
5188*4882a593Smuzhiyun				# Find out how long the conditional actually is.
5189*4882a593Smuzhiyun				my @newlines = ($c =~ /\n/gs);
5190*4882a593Smuzhiyun				my $cond_lines = 1 + $#newlines;
5191*4882a593Smuzhiyun				my $stat_real = '';
5192*4882a593Smuzhiyun
5193*4882a593Smuzhiyun				$stat_real = raw_line($linenr, $cond_lines)
5194*4882a593Smuzhiyun							. "\n" if ($cond_lines);
5195*4882a593Smuzhiyun				if (defined($stat_real) && $cond_lines > 1) {
5196*4882a593Smuzhiyun					$stat_real = "[...]\n$stat_real";
5197*4882a593Smuzhiyun				}
5198*4882a593Smuzhiyun
5199*4882a593Smuzhiyun				ERROR("TRAILING_STATEMENTS",
5200*4882a593Smuzhiyun				      "trailing statements should be on next line\n" . $herecurr . $stat_real);
5201*4882a593Smuzhiyun			}
5202*4882a593Smuzhiyun		}
5203*4882a593Smuzhiyun
5204*4882a593Smuzhiyun# Check for bitwise tests written as boolean
5205*4882a593Smuzhiyun		if ($line =~ /
5206*4882a593Smuzhiyun			(?:
5207*4882a593Smuzhiyun				(?:\[|\(|\&\&|\|\|)
5208*4882a593Smuzhiyun				\s*0[xX][0-9]+\s*
5209*4882a593Smuzhiyun				(?:\&\&|\|\|)
5210*4882a593Smuzhiyun			|
5211*4882a593Smuzhiyun				(?:\&\&|\|\|)
5212*4882a593Smuzhiyun				\s*0[xX][0-9]+\s*
5213*4882a593Smuzhiyun				(?:\&\&|\|\||\)|\])
5214*4882a593Smuzhiyun			)/x)
5215*4882a593Smuzhiyun		{
5216*4882a593Smuzhiyun			WARN("HEXADECIMAL_BOOLEAN_TEST",
5217*4882a593Smuzhiyun			     "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
5218*4882a593Smuzhiyun		}
5219*4882a593Smuzhiyun
5220*4882a593Smuzhiyun# if and else should not have general statements after it
5221*4882a593Smuzhiyun		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
5222*4882a593Smuzhiyun			my $s = $1;
5223*4882a593Smuzhiyun			$s =~ s/$;//g;	# Remove any comments
5224*4882a593Smuzhiyun			if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
5225*4882a593Smuzhiyun				ERROR("TRAILING_STATEMENTS",
5226*4882a593Smuzhiyun				      "trailing statements should be on next line\n" . $herecurr);
5227*4882a593Smuzhiyun			}
5228*4882a593Smuzhiyun		}
5229*4882a593Smuzhiyun# if should not continue a brace
5230*4882a593Smuzhiyun		if ($line =~ /}\s*if\b/) {
5231*4882a593Smuzhiyun			ERROR("TRAILING_STATEMENTS",
5232*4882a593Smuzhiyun			      "trailing statements should be on next line (or did you mean 'else if'?)\n" .
5233*4882a593Smuzhiyun				$herecurr);
5234*4882a593Smuzhiyun		}
5235*4882a593Smuzhiyun# case and default should not have general statements after them
5236*4882a593Smuzhiyun		if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
5237*4882a593Smuzhiyun		    $line !~ /\G(?:
5238*4882a593Smuzhiyun			(?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
5239*4882a593Smuzhiyun			\s*return\s+
5240*4882a593Smuzhiyun		    )/xg)
5241*4882a593Smuzhiyun		{
5242*4882a593Smuzhiyun			ERROR("TRAILING_STATEMENTS",
5243*4882a593Smuzhiyun			      "trailing statements should be on next line\n" . $herecurr);
5244*4882a593Smuzhiyun		}
5245*4882a593Smuzhiyun
5246*4882a593Smuzhiyun		# Check for }<nl>else {, these must be at the same
5247*4882a593Smuzhiyun		# indent level to be relevant to each other.
5248*4882a593Smuzhiyun		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
5249*4882a593Smuzhiyun		    $previndent == $indent) {
5250*4882a593Smuzhiyun			if (ERROR("ELSE_AFTER_BRACE",
5251*4882a593Smuzhiyun				  "else should follow close brace '}'\n" . $hereprev) &&
5252*4882a593Smuzhiyun			    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
5253*4882a593Smuzhiyun				fix_delete_line($fixlinenr - 1, $prevrawline);
5254*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
5255*4882a593Smuzhiyun				my $fixedline = $prevrawline;
5256*4882a593Smuzhiyun				$fixedline =~ s/}\s*$//;
5257*4882a593Smuzhiyun				if ($fixedline !~ /^\+\s*$/) {
5258*4882a593Smuzhiyun					fix_insert_line($fixlinenr, $fixedline);
5259*4882a593Smuzhiyun				}
5260*4882a593Smuzhiyun				$fixedline = $rawline;
5261*4882a593Smuzhiyun				$fixedline =~ s/^(.\s*)else/$1} else/;
5262*4882a593Smuzhiyun				fix_insert_line($fixlinenr, $fixedline);
5263*4882a593Smuzhiyun			}
5264*4882a593Smuzhiyun		}
5265*4882a593Smuzhiyun
5266*4882a593Smuzhiyun		if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
5267*4882a593Smuzhiyun		    $previndent == $indent) {
5268*4882a593Smuzhiyun			my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
5269*4882a593Smuzhiyun
5270*4882a593Smuzhiyun			# Find out what is on the end of the line after the
5271*4882a593Smuzhiyun			# conditional.
5272*4882a593Smuzhiyun			substr($s, 0, length($c), '');
5273*4882a593Smuzhiyun			$s =~ s/\n.*//g;
5274*4882a593Smuzhiyun
5275*4882a593Smuzhiyun			if ($s =~ /^\s*;/) {
5276*4882a593Smuzhiyun				if (ERROR("WHILE_AFTER_BRACE",
5277*4882a593Smuzhiyun					  "while should follow close brace '}'\n" . $hereprev) &&
5278*4882a593Smuzhiyun				    $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
5279*4882a593Smuzhiyun					fix_delete_line($fixlinenr - 1, $prevrawline);
5280*4882a593Smuzhiyun					fix_delete_line($fixlinenr, $rawline);
5281*4882a593Smuzhiyun					my $fixedline = $prevrawline;
5282*4882a593Smuzhiyun					my $trailing = $rawline;
5283*4882a593Smuzhiyun					$trailing =~ s/^\+//;
5284*4882a593Smuzhiyun					$trailing = trim($trailing);
5285*4882a593Smuzhiyun					$fixedline =~ s/}\s*$/} $trailing/;
5286*4882a593Smuzhiyun					fix_insert_line($fixlinenr, $fixedline);
5287*4882a593Smuzhiyun				}
5288*4882a593Smuzhiyun			}
5289*4882a593Smuzhiyun		}
5290*4882a593Smuzhiyun
5291*4882a593Smuzhiyun#Specific variable tests
5292*4882a593Smuzhiyun		while ($line =~ m{($Constant|$Lval)}g) {
5293*4882a593Smuzhiyun			my $var = $1;
5294*4882a593Smuzhiyun
5295*4882a593Smuzhiyun#CamelCase
5296*4882a593Smuzhiyun			if ($var !~ /^$Constant$/ &&
5297*4882a593Smuzhiyun			    $var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
5298*4882a593Smuzhiyun#Ignore Page<foo> variants
5299*4882a593Smuzhiyun			    $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
5300*4882a593Smuzhiyun#Ignore SI style variants like nS, mV and dB
5301*4882a593Smuzhiyun#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
5302*4882a593Smuzhiyun			    $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
5303*4882a593Smuzhiyun#Ignore some three character SI units explicitly, like MiB and KHz
5304*4882a593Smuzhiyun			    $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
5305*4882a593Smuzhiyun				while ($var =~ m{($Ident)}g) {
5306*4882a593Smuzhiyun					my $word = $1;
5307*4882a593Smuzhiyun					next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
5308*4882a593Smuzhiyun					if ($check) {
5309*4882a593Smuzhiyun						seed_camelcase_includes();
5310*4882a593Smuzhiyun						if (!$file && !$camelcase_file_seeded) {
5311*4882a593Smuzhiyun							seed_camelcase_file($realfile);
5312*4882a593Smuzhiyun							$camelcase_file_seeded = 1;
5313*4882a593Smuzhiyun						}
5314*4882a593Smuzhiyun					}
5315*4882a593Smuzhiyun					if (!defined $camelcase{$word}) {
5316*4882a593Smuzhiyun						$camelcase{$word} = 1;
5317*4882a593Smuzhiyun						CHK("CAMELCASE",
5318*4882a593Smuzhiyun						    "Avoid CamelCase: <$word>\n" . $herecurr);
5319*4882a593Smuzhiyun					}
5320*4882a593Smuzhiyun				}
5321*4882a593Smuzhiyun			}
5322*4882a593Smuzhiyun		}
5323*4882a593Smuzhiyun
5324*4882a593Smuzhiyun#no spaces allowed after \ in define
5325*4882a593Smuzhiyun		if ($line =~ /\#\s*define.*\\\s+$/) {
5326*4882a593Smuzhiyun			if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
5327*4882a593Smuzhiyun				 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
5328*4882a593Smuzhiyun			    $fix) {
5329*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\s+$//;
5330*4882a593Smuzhiyun			}
5331*4882a593Smuzhiyun		}
5332*4882a593Smuzhiyun
5333*4882a593Smuzhiyun# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes
5334*4882a593Smuzhiyun# itself <asm/foo.h> (uses RAW line)
5335*4882a593Smuzhiyun		if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
5336*4882a593Smuzhiyun			my $file = "$1.h";
5337*4882a593Smuzhiyun			my $checkfile = "include/linux/$file";
5338*4882a593Smuzhiyun			if (-f "$root/$checkfile" &&
5339*4882a593Smuzhiyun			    $realfile ne $checkfile &&
5340*4882a593Smuzhiyun			    $1 !~ /$allowed_asm_includes/)
5341*4882a593Smuzhiyun			{
5342*4882a593Smuzhiyun				my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`;
5343*4882a593Smuzhiyun				if ($asminclude > 0) {
5344*4882a593Smuzhiyun					if ($realfile =~ m{^arch/}) {
5345*4882a593Smuzhiyun						CHK("ARCH_INCLUDE_LINUX",
5346*4882a593Smuzhiyun						    "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5347*4882a593Smuzhiyun					} else {
5348*4882a593Smuzhiyun						WARN("INCLUDE_LINUX",
5349*4882a593Smuzhiyun						     "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5350*4882a593Smuzhiyun					}
5351*4882a593Smuzhiyun				}
5352*4882a593Smuzhiyun			}
5353*4882a593Smuzhiyun		}
5354*4882a593Smuzhiyun
5355*4882a593Smuzhiyun# multi-statement macros should be enclosed in a do while loop, grab the
5356*4882a593Smuzhiyun# first statement and ensure its the whole macro if its not enclosed
5357*4882a593Smuzhiyun# in a known good container
5358*4882a593Smuzhiyun		if ($realfile !~ m@/vmlinux.lds.h$@ &&
5359*4882a593Smuzhiyun		    $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
5360*4882a593Smuzhiyun			my $ln = $linenr;
5361*4882a593Smuzhiyun			my $cnt = $realcnt;
5362*4882a593Smuzhiyun			my ($off, $dstat, $dcond, $rest);
5363*4882a593Smuzhiyun			my $ctx = '';
5364*4882a593Smuzhiyun			my $has_flow_statement = 0;
5365*4882a593Smuzhiyun			my $has_arg_concat = 0;
5366*4882a593Smuzhiyun			($dstat, $dcond, $ln, $cnt, $off) =
5367*4882a593Smuzhiyun				ctx_statement_block($linenr, $realcnt, 0);
5368*4882a593Smuzhiyun			$ctx = $dstat;
5369*4882a593Smuzhiyun			#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
5370*4882a593Smuzhiyun			#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
5371*4882a593Smuzhiyun
5372*4882a593Smuzhiyun			$has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
5373*4882a593Smuzhiyun			$has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
5374*4882a593Smuzhiyun
5375*4882a593Smuzhiyun			$dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
5376*4882a593Smuzhiyun			my $define_args = $1;
5377*4882a593Smuzhiyun			my $define_stmt = $dstat;
5378*4882a593Smuzhiyun			my @def_args = ();
5379*4882a593Smuzhiyun
5380*4882a593Smuzhiyun			if (defined $define_args && $define_args ne "") {
5381*4882a593Smuzhiyun				$define_args = substr($define_args, 1, length($define_args) - 2);
5382*4882a593Smuzhiyun				$define_args =~ s/\s*//g;
5383*4882a593Smuzhiyun				$define_args =~ s/\\\+?//g;
5384*4882a593Smuzhiyun				@def_args = split(",", $define_args);
5385*4882a593Smuzhiyun			}
5386*4882a593Smuzhiyun
5387*4882a593Smuzhiyun			$dstat =~ s/$;//g;
5388*4882a593Smuzhiyun			$dstat =~ s/\\\n.//g;
5389*4882a593Smuzhiyun			$dstat =~ s/^\s*//s;
5390*4882a593Smuzhiyun			$dstat =~ s/\s*$//s;
5391*4882a593Smuzhiyun
5392*4882a593Smuzhiyun			# Flatten any parentheses and braces
5393*4882a593Smuzhiyun			while ($dstat =~ s/\([^\(\)]*\)/1u/ ||
5394*4882a593Smuzhiyun			       $dstat =~ s/\{[^\{\}]*\}/1u/ ||
5395*4882a593Smuzhiyun			       $dstat =~ s/.\[[^\[\]]*\]/1u/)
5396*4882a593Smuzhiyun			{
5397*4882a593Smuzhiyun			}
5398*4882a593Smuzhiyun
5399*4882a593Smuzhiyun			# Flatten any obvious string concatenation.
5400*4882a593Smuzhiyun			while ($dstat =~ s/($String)\s*$Ident/$1/ ||
5401*4882a593Smuzhiyun			       $dstat =~ s/$Ident\s*($String)/$1/)
5402*4882a593Smuzhiyun			{
5403*4882a593Smuzhiyun			}
5404*4882a593Smuzhiyun
5405*4882a593Smuzhiyun			# Make asm volatile uses seem like a generic function
5406*4882a593Smuzhiyun			$dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
5407*4882a593Smuzhiyun
5408*4882a593Smuzhiyun			my $exceptions = qr{
5409*4882a593Smuzhiyun				$Declare|
5410*4882a593Smuzhiyun				module_param_named|
5411*4882a593Smuzhiyun				MODULE_PARM_DESC|
5412*4882a593Smuzhiyun				DECLARE_PER_CPU|
5413*4882a593Smuzhiyun				DEFINE_PER_CPU|
5414*4882a593Smuzhiyun				__typeof__\(|
5415*4882a593Smuzhiyun				union|
5416*4882a593Smuzhiyun				struct|
5417*4882a593Smuzhiyun				\.$Ident\s*=\s*|
5418*4882a593Smuzhiyun				^\"|\"$|
5419*4882a593Smuzhiyun				^\[
5420*4882a593Smuzhiyun			}x;
5421*4882a593Smuzhiyun			#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
5422*4882a593Smuzhiyun
5423*4882a593Smuzhiyun			$ctx =~ s/\n*$//;
5424*4882a593Smuzhiyun			my $stmt_cnt = statement_rawlines($ctx);
5425*4882a593Smuzhiyun			my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
5426*4882a593Smuzhiyun
5427*4882a593Smuzhiyun			if ($dstat ne '' &&
5428*4882a593Smuzhiyun			    $dstat !~ /^(?:$Ident|-?$Constant),$/ &&			# 10, // foo(),
5429*4882a593Smuzhiyun			    $dstat !~ /^(?:$Ident|-?$Constant);$/ &&			# foo();
5430*4882a593Smuzhiyun			    $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ &&		# 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
5431*4882a593Smuzhiyun			    $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ &&			# character constants
5432*4882a593Smuzhiyun			    $dstat !~ /$exceptions/ &&
5433*4882a593Smuzhiyun			    $dstat !~ /^\.$Ident\s*=/ &&				# .foo =
5434*4882a593Smuzhiyun			    $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ &&		# stringification #foo
5435*4882a593Smuzhiyun			    $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ &&	# do {...} while (...); // do {...} while (...)
5436*4882a593Smuzhiyun			    $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ &&		# while (...) {...}
5437*4882a593Smuzhiyun			    $dstat !~ /^for\s*$Constant$/ &&				# for (...)
5438*4882a593Smuzhiyun			    $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ &&	# for (...) bar()
5439*4882a593Smuzhiyun			    $dstat !~ /^do\s*{/ &&					# do {...
5440*4882a593Smuzhiyun			    $dstat !~ /^\(\{/ &&						# ({...
5441*4882a593Smuzhiyun			    $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
5442*4882a593Smuzhiyun			{
5443*4882a593Smuzhiyun				if ($dstat =~ /^\s*if\b/) {
5444*4882a593Smuzhiyun					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
5445*4882a593Smuzhiyun					      "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
5446*4882a593Smuzhiyun				} elsif ($dstat =~ /;/) {
5447*4882a593Smuzhiyun					ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
5448*4882a593Smuzhiyun					      "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
5449*4882a593Smuzhiyun				} else {
5450*4882a593Smuzhiyun					ERROR("COMPLEX_MACRO",
5451*4882a593Smuzhiyun					      "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
5452*4882a593Smuzhiyun				}
5453*4882a593Smuzhiyun
5454*4882a593Smuzhiyun			}
5455*4882a593Smuzhiyun
5456*4882a593Smuzhiyun			# Make $define_stmt single line, comment-free, etc
5457*4882a593Smuzhiyun			my @stmt_array = split('\n', $define_stmt);
5458*4882a593Smuzhiyun			my $first = 1;
5459*4882a593Smuzhiyun			$define_stmt = "";
5460*4882a593Smuzhiyun			foreach my $l (@stmt_array) {
5461*4882a593Smuzhiyun				$l =~ s/\\$//;
5462*4882a593Smuzhiyun				if ($first) {
5463*4882a593Smuzhiyun					$define_stmt = $l;
5464*4882a593Smuzhiyun					$first = 0;
5465*4882a593Smuzhiyun				} elsif ($l =~ /^[\+ ]/) {
5466*4882a593Smuzhiyun					$define_stmt .= substr($l, 1);
5467*4882a593Smuzhiyun				}
5468*4882a593Smuzhiyun			}
5469*4882a593Smuzhiyun			$define_stmt =~ s/$;//g;
5470*4882a593Smuzhiyun			$define_stmt =~ s/\s+/ /g;
5471*4882a593Smuzhiyun			$define_stmt = trim($define_stmt);
5472*4882a593Smuzhiyun
5473*4882a593Smuzhiyun# check if any macro arguments are reused (ignore '...' and 'type')
5474*4882a593Smuzhiyun			foreach my $arg (@def_args) {
5475*4882a593Smuzhiyun			        next if ($arg =~ /\.\.\./);
5476*4882a593Smuzhiyun			        next if ($arg =~ /^type$/i);
5477*4882a593Smuzhiyun				my $tmp_stmt = $define_stmt;
5478*4882a593Smuzhiyun				$tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
5479*4882a593Smuzhiyun				$tmp_stmt =~ s/\#+\s*$arg\b//g;
5480*4882a593Smuzhiyun				$tmp_stmt =~ s/\b$arg\s*\#\#//g;
5481*4882a593Smuzhiyun				my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
5482*4882a593Smuzhiyun				if ($use_cnt > 1) {
5483*4882a593Smuzhiyun					CHK("MACRO_ARG_REUSE",
5484*4882a593Smuzhiyun					    "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
5485*4882a593Smuzhiyun				    }
5486*4882a593Smuzhiyun# check if any macro arguments may have other precedence issues
5487*4882a593Smuzhiyun				if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
5488*4882a593Smuzhiyun				    ((defined($1) && $1 ne ',') ||
5489*4882a593Smuzhiyun				     (defined($2) && $2 ne ','))) {
5490*4882a593Smuzhiyun					CHK("MACRO_ARG_PRECEDENCE",
5491*4882a593Smuzhiyun					    "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
5492*4882a593Smuzhiyun				}
5493*4882a593Smuzhiyun			}
5494*4882a593Smuzhiyun
5495*4882a593Smuzhiyun# check for macros with flow control, but without ## concatenation
5496*4882a593Smuzhiyun# ## concatenation is commonly a macro that defines a function so ignore those
5497*4882a593Smuzhiyun			if ($has_flow_statement && !$has_arg_concat) {
5498*4882a593Smuzhiyun				my $cnt = statement_rawlines($ctx);
5499*4882a593Smuzhiyun				my $herectx = get_stat_here($linenr, $cnt, $here);
5500*4882a593Smuzhiyun
5501*4882a593Smuzhiyun				WARN("MACRO_WITH_FLOW_CONTROL",
5502*4882a593Smuzhiyun				     "Macros with flow control statements should be avoided\n" . "$herectx");
5503*4882a593Smuzhiyun			}
5504*4882a593Smuzhiyun
5505*4882a593Smuzhiyun# check for line continuations outside of #defines, preprocessor #, and asm
5506*4882a593Smuzhiyun
5507*4882a593Smuzhiyun		} else {
5508*4882a593Smuzhiyun			if ($prevline !~ /^..*\\$/ &&
5509*4882a593Smuzhiyun			    $line !~ /^\+\s*\#.*\\$/ &&		# preprocessor
5510*4882a593Smuzhiyun			    $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ &&	# asm
5511*4882a593Smuzhiyun			    $line =~ /^\+.*\\$/) {
5512*4882a593Smuzhiyun				WARN("LINE_CONTINUATIONS",
5513*4882a593Smuzhiyun				     "Avoid unnecessary line continuations\n" . $herecurr);
5514*4882a593Smuzhiyun			}
5515*4882a593Smuzhiyun		}
5516*4882a593Smuzhiyun
5517*4882a593Smuzhiyun# do {} while (0) macro tests:
5518*4882a593Smuzhiyun# single-statement macros do not need to be enclosed in do while (0) loop,
5519*4882a593Smuzhiyun# macro should not end with a semicolon
5520*4882a593Smuzhiyun		if ($perl_version_ok &&
5521*4882a593Smuzhiyun		    $realfile !~ m@/vmlinux.lds.h$@ &&
5522*4882a593Smuzhiyun		    $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
5523*4882a593Smuzhiyun			my $ln = $linenr;
5524*4882a593Smuzhiyun			my $cnt = $realcnt;
5525*4882a593Smuzhiyun			my ($off, $dstat, $dcond, $rest);
5526*4882a593Smuzhiyun			my $ctx = '';
5527*4882a593Smuzhiyun			($dstat, $dcond, $ln, $cnt, $off) =
5528*4882a593Smuzhiyun				ctx_statement_block($linenr, $realcnt, 0);
5529*4882a593Smuzhiyun			$ctx = $dstat;
5530*4882a593Smuzhiyun
5531*4882a593Smuzhiyun			$dstat =~ s/\\\n.//g;
5532*4882a593Smuzhiyun			$dstat =~ s/$;/ /g;
5533*4882a593Smuzhiyun
5534*4882a593Smuzhiyun			if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {
5535*4882a593Smuzhiyun				my $stmts = $2;
5536*4882a593Smuzhiyun				my $semis = $3;
5537*4882a593Smuzhiyun
5538*4882a593Smuzhiyun				$ctx =~ s/\n*$//;
5539*4882a593Smuzhiyun				my $cnt = statement_rawlines($ctx);
5540*4882a593Smuzhiyun				my $herectx = get_stat_here($linenr, $cnt, $here);
5541*4882a593Smuzhiyun
5542*4882a593Smuzhiyun				if (($stmts =~ tr/;/;/) == 1 &&
5543*4882a593Smuzhiyun				    $stmts !~ /^\s*(if|while|for|switch)\b/) {
5544*4882a593Smuzhiyun					WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",
5545*4882a593Smuzhiyun					     "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");
5546*4882a593Smuzhiyun				}
5547*4882a593Smuzhiyun				if (defined $semis && $semis ne "") {
5548*4882a593Smuzhiyun					WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
5549*4882a593Smuzhiyun					     "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
5550*4882a593Smuzhiyun				}
5551*4882a593Smuzhiyun			} elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
5552*4882a593Smuzhiyun				$ctx =~ s/\n*$//;
5553*4882a593Smuzhiyun				my $cnt = statement_rawlines($ctx);
5554*4882a593Smuzhiyun				my $herectx = get_stat_here($linenr, $cnt, $here);
5555*4882a593Smuzhiyun
5556*4882a593Smuzhiyun				WARN("TRAILING_SEMICOLON",
5557*4882a593Smuzhiyun				     "macros should not use a trailing semicolon\n" . "$herectx");
5558*4882a593Smuzhiyun			}
5559*4882a593Smuzhiyun		}
5560*4882a593Smuzhiyun
5561*4882a593Smuzhiyun# check for redundant bracing round if etc
5562*4882a593Smuzhiyun		if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
5563*4882a593Smuzhiyun			my ($level, $endln, @chunks) =
5564*4882a593Smuzhiyun				ctx_statement_full($linenr, $realcnt, 1);
5565*4882a593Smuzhiyun			#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
5566*4882a593Smuzhiyun			#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
5567*4882a593Smuzhiyun			if ($#chunks > 0 && $level == 0) {
5568*4882a593Smuzhiyun				my @allowed = ();
5569*4882a593Smuzhiyun				my $allow = 0;
5570*4882a593Smuzhiyun				my $seen = 0;
5571*4882a593Smuzhiyun				my $herectx = $here . "\n";
5572*4882a593Smuzhiyun				my $ln = $linenr - 1;
5573*4882a593Smuzhiyun				for my $chunk (@chunks) {
5574*4882a593Smuzhiyun					my ($cond, $block) = @{$chunk};
5575*4882a593Smuzhiyun
5576*4882a593Smuzhiyun					# If the condition carries leading newlines, then count those as offsets.
5577*4882a593Smuzhiyun					my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
5578*4882a593Smuzhiyun					my $offset = statement_rawlines($whitespace) - 1;
5579*4882a593Smuzhiyun
5580*4882a593Smuzhiyun					$allowed[$allow] = 0;
5581*4882a593Smuzhiyun					#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
5582*4882a593Smuzhiyun
5583*4882a593Smuzhiyun					# We have looked at and allowed this specific line.
5584*4882a593Smuzhiyun					$suppress_ifbraces{$ln + $offset} = 1;
5585*4882a593Smuzhiyun
5586*4882a593Smuzhiyun					$herectx .= "$rawlines[$ln + $offset]\n[...]\n";
5587*4882a593Smuzhiyun					$ln += statement_rawlines($block) - 1;
5588*4882a593Smuzhiyun
5589*4882a593Smuzhiyun					substr($block, 0, length($cond), '');
5590*4882a593Smuzhiyun
5591*4882a593Smuzhiyun					$seen++ if ($block =~ /^\s*{/);
5592*4882a593Smuzhiyun
5593*4882a593Smuzhiyun					#print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
5594*4882a593Smuzhiyun					if (statement_lines($cond) > 1) {
5595*4882a593Smuzhiyun						#print "APW: ALLOWED: cond<$cond>\n";
5596*4882a593Smuzhiyun						$allowed[$allow] = 1;
5597*4882a593Smuzhiyun					}
5598*4882a593Smuzhiyun					if ($block =~/\b(?:if|for|while)\b/) {
5599*4882a593Smuzhiyun						#print "APW: ALLOWED: block<$block>\n";
5600*4882a593Smuzhiyun						$allowed[$allow] = 1;
5601*4882a593Smuzhiyun					}
5602*4882a593Smuzhiyun					if (statement_block_size($block) > 1) {
5603*4882a593Smuzhiyun						#print "APW: ALLOWED: lines block<$block>\n";
5604*4882a593Smuzhiyun						$allowed[$allow] = 1;
5605*4882a593Smuzhiyun					}
5606*4882a593Smuzhiyun					$allow++;
5607*4882a593Smuzhiyun				}
5608*4882a593Smuzhiyun				if ($seen) {
5609*4882a593Smuzhiyun					my $sum_allowed = 0;
5610*4882a593Smuzhiyun					foreach (@allowed) {
5611*4882a593Smuzhiyun						$sum_allowed += $_;
5612*4882a593Smuzhiyun					}
5613*4882a593Smuzhiyun					if ($sum_allowed == 0) {
5614*4882a593Smuzhiyun						WARN("BRACES",
5615*4882a593Smuzhiyun						     "braces {} are not necessary for any arm of this statement\n" . $herectx);
5616*4882a593Smuzhiyun					} elsif ($sum_allowed != $allow &&
5617*4882a593Smuzhiyun						 $seen != $allow) {
5618*4882a593Smuzhiyun						CHK("BRACES",
5619*4882a593Smuzhiyun						    "braces {} should be used on all arms of this statement\n" . $herectx);
5620*4882a593Smuzhiyun					}
5621*4882a593Smuzhiyun				}
5622*4882a593Smuzhiyun			}
5623*4882a593Smuzhiyun		}
5624*4882a593Smuzhiyun		if (!defined $suppress_ifbraces{$linenr - 1} &&
5625*4882a593Smuzhiyun					$line =~ /\b(if|while|for|else)\b/) {
5626*4882a593Smuzhiyun			my $allowed = 0;
5627*4882a593Smuzhiyun
5628*4882a593Smuzhiyun			# Check the pre-context.
5629*4882a593Smuzhiyun			if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
5630*4882a593Smuzhiyun				#print "APW: ALLOWED: pre<$1>\n";
5631*4882a593Smuzhiyun				$allowed = 1;
5632*4882a593Smuzhiyun			}
5633*4882a593Smuzhiyun
5634*4882a593Smuzhiyun			my ($level, $endln, @chunks) =
5635*4882a593Smuzhiyun				ctx_statement_full($linenr, $realcnt, $-[0]);
5636*4882a593Smuzhiyun
5637*4882a593Smuzhiyun			# Check the condition.
5638*4882a593Smuzhiyun			my ($cond, $block) = @{$chunks[0]};
5639*4882a593Smuzhiyun			#print "CHECKING<$linenr> cond<$cond> block<$block>\n";
5640*4882a593Smuzhiyun			if (defined $cond) {
5641*4882a593Smuzhiyun				substr($block, 0, length($cond), '');
5642*4882a593Smuzhiyun			}
5643*4882a593Smuzhiyun			if (statement_lines($cond) > 1) {
5644*4882a593Smuzhiyun				#print "APW: ALLOWED: cond<$cond>\n";
5645*4882a593Smuzhiyun				$allowed = 1;
5646*4882a593Smuzhiyun			}
5647*4882a593Smuzhiyun			if ($block =~/\b(?:if|for|while)\b/) {
5648*4882a593Smuzhiyun				#print "APW: ALLOWED: block<$block>\n";
5649*4882a593Smuzhiyun				$allowed = 1;
5650*4882a593Smuzhiyun			}
5651*4882a593Smuzhiyun			if (statement_block_size($block) > 1) {
5652*4882a593Smuzhiyun				#print "APW: ALLOWED: lines block<$block>\n";
5653*4882a593Smuzhiyun				$allowed = 1;
5654*4882a593Smuzhiyun			}
5655*4882a593Smuzhiyun			# Check the post-context.
5656*4882a593Smuzhiyun			if (defined $chunks[1]) {
5657*4882a593Smuzhiyun				my ($cond, $block) = @{$chunks[1]};
5658*4882a593Smuzhiyun				if (defined $cond) {
5659*4882a593Smuzhiyun					substr($block, 0, length($cond), '');
5660*4882a593Smuzhiyun				}
5661*4882a593Smuzhiyun				if ($block =~ /^\s*\{/) {
5662*4882a593Smuzhiyun					#print "APW: ALLOWED: chunk-1 block<$block>\n";
5663*4882a593Smuzhiyun					$allowed = 1;
5664*4882a593Smuzhiyun				}
5665*4882a593Smuzhiyun			}
5666*4882a593Smuzhiyun			if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
5667*4882a593Smuzhiyun				my $cnt = statement_rawlines($block);
5668*4882a593Smuzhiyun				my $herectx = get_stat_here($linenr, $cnt, $here);
5669*4882a593Smuzhiyun
5670*4882a593Smuzhiyun				WARN("BRACES",
5671*4882a593Smuzhiyun				     "braces {} are not necessary for single statement blocks\n" . $herectx);
5672*4882a593Smuzhiyun			}
5673*4882a593Smuzhiyun		}
5674*4882a593Smuzhiyun
5675*4882a593Smuzhiyun# check for single line unbalanced braces
5676*4882a593Smuzhiyun		if ($sline =~ /^.\s*\}\s*else\s*$/ ||
5677*4882a593Smuzhiyun		    $sline =~ /^.\s*else\s*\{\s*$/) {
5678*4882a593Smuzhiyun			CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);
5679*4882a593Smuzhiyun		}
5680*4882a593Smuzhiyun
5681*4882a593Smuzhiyun# check for unnecessary blank lines around braces
5682*4882a593Smuzhiyun		if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
5683*4882a593Smuzhiyun			if (CHK("BRACES",
5684*4882a593Smuzhiyun				"Blank lines aren't necessary before a close brace '}'\n" . $hereprev) &&
5685*4882a593Smuzhiyun			    $fix && $prevrawline =~ /^\+/) {
5686*4882a593Smuzhiyun				fix_delete_line($fixlinenr - 1, $prevrawline);
5687*4882a593Smuzhiyun			}
5688*4882a593Smuzhiyun		}
5689*4882a593Smuzhiyun		if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) {
5690*4882a593Smuzhiyun			if (CHK("BRACES",
5691*4882a593Smuzhiyun				"Blank lines aren't necessary after an open brace '{'\n" . $hereprev) &&
5692*4882a593Smuzhiyun			    $fix) {
5693*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
5694*4882a593Smuzhiyun			}
5695*4882a593Smuzhiyun		}
5696*4882a593Smuzhiyun
5697*4882a593Smuzhiyun# no volatiles please
5698*4882a593Smuzhiyun		my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
5699*4882a593Smuzhiyun		if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
5700*4882a593Smuzhiyun			WARN("VOLATILE",
5701*4882a593Smuzhiyun			     "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);
5702*4882a593Smuzhiyun		}
5703*4882a593Smuzhiyun
5704*4882a593Smuzhiyun# Check for user-visible strings broken across lines, which breaks the ability
5705*4882a593Smuzhiyun# to grep for the string.  Make exceptions when the previous string ends in a
5706*4882a593Smuzhiyun# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
5707*4882a593Smuzhiyun# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
5708*4882a593Smuzhiyun		if ($line =~ /^\+\s*$String/ &&
5709*4882a593Smuzhiyun		    $prevline =~ /"\s*$/ &&
5710*4882a593Smuzhiyun		    $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
5711*4882a593Smuzhiyun			if (WARN("SPLIT_STRING",
5712*4882a593Smuzhiyun				 "quoted string split across lines\n" . $hereprev) &&
5713*4882a593Smuzhiyun				     $fix &&
5714*4882a593Smuzhiyun				     $prevrawline =~ /^\+.*"\s*$/ &&
5715*4882a593Smuzhiyun				     $last_coalesced_string_linenr != $linenr - 1) {
5716*4882a593Smuzhiyun				my $extracted_string = get_quoted_string($line, $rawline);
5717*4882a593Smuzhiyun				my $comma_close = "";
5718*4882a593Smuzhiyun				if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) {
5719*4882a593Smuzhiyun					$comma_close = $1;
5720*4882a593Smuzhiyun				}
5721*4882a593Smuzhiyun
5722*4882a593Smuzhiyun				fix_delete_line($fixlinenr - 1, $prevrawline);
5723*4882a593Smuzhiyun				fix_delete_line($fixlinenr, $rawline);
5724*4882a593Smuzhiyun				my $fixedline = $prevrawline;
5725*4882a593Smuzhiyun				$fixedline =~ s/"\s*$//;
5726*4882a593Smuzhiyun				$fixedline .= substr($extracted_string, 1) . trim($comma_close);
5727*4882a593Smuzhiyun				fix_insert_line($fixlinenr - 1, $fixedline);
5728*4882a593Smuzhiyun				$fixedline = $rawline;
5729*4882a593Smuzhiyun				$fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//;
5730*4882a593Smuzhiyun				if ($fixedline !~ /\+\s*$/) {
5731*4882a593Smuzhiyun					fix_insert_line($fixlinenr, $fixedline);
5732*4882a593Smuzhiyun				}
5733*4882a593Smuzhiyun				$last_coalesced_string_linenr = $linenr;
5734*4882a593Smuzhiyun			}
5735*4882a593Smuzhiyun		}
5736*4882a593Smuzhiyun
5737*4882a593Smuzhiyun# check for missing a space in a string concatenation
5738*4882a593Smuzhiyun		if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {
5739*4882a593Smuzhiyun			WARN('MISSING_SPACE',
5740*4882a593Smuzhiyun			     "break quoted strings at a space character\n" . $hereprev);
5741*4882a593Smuzhiyun		}
5742*4882a593Smuzhiyun
5743*4882a593Smuzhiyun# check for an embedded function name in a string when the function is known
5744*4882a593Smuzhiyun# This does not work very well for -f --file checking as it depends on patch
5745*4882a593Smuzhiyun# context providing the function name or a single line form for in-file
5746*4882a593Smuzhiyun# function declarations
5747*4882a593Smuzhiyun		if ($line =~ /^\+.*$String/ &&
5748*4882a593Smuzhiyun		    defined($context_function) &&
5749*4882a593Smuzhiyun		    get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&
5750*4882a593Smuzhiyun		    length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {
5751*4882a593Smuzhiyun			WARN("EMBEDDED_FUNCTION_NAME",
5752*4882a593Smuzhiyun			     "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
5753*4882a593Smuzhiyun		}
5754*4882a593Smuzhiyun
5755*4882a593Smuzhiyun# check for spaces before a quoted newline
5756*4882a593Smuzhiyun		if ($rawline =~ /^.*\".*\s\\n/) {
5757*4882a593Smuzhiyun			if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
5758*4882a593Smuzhiyun				 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
5759*4882a593Smuzhiyun			    $fix) {
5760*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
5761*4882a593Smuzhiyun			}
5762*4882a593Smuzhiyun
5763*4882a593Smuzhiyun		}
5764*4882a593Smuzhiyun
5765*4882a593Smuzhiyun# concatenated string without spaces between elements
5766*4882a593Smuzhiyun		if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
5767*4882a593Smuzhiyun			if (CHK("CONCATENATED_STRING",
5768*4882a593Smuzhiyun				"Concatenated strings should use spaces between elements\n" . $herecurr) &&
5769*4882a593Smuzhiyun			    $fix) {
5770*4882a593Smuzhiyun				while ($line =~ /($String)/g) {
5771*4882a593Smuzhiyun					my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
5772*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
5773*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
5774*4882a593Smuzhiyun				}
5775*4882a593Smuzhiyun			}
5776*4882a593Smuzhiyun		}
5777*4882a593Smuzhiyun
5778*4882a593Smuzhiyun# uncoalesced string fragments
5779*4882a593Smuzhiyun		if ($line =~ /$String\s*"/) {
5780*4882a593Smuzhiyun			if (WARN("STRING_FRAGMENTS",
5781*4882a593Smuzhiyun				 "Consecutive strings are generally better as a single string\n" . $herecurr) &&
5782*4882a593Smuzhiyun			    $fix) {
5783*4882a593Smuzhiyun				while ($line =~ /($String)(?=\s*")/g) {
5784*4882a593Smuzhiyun					my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
5785*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
5786*4882a593Smuzhiyun				}
5787*4882a593Smuzhiyun			}
5788*4882a593Smuzhiyun		}
5789*4882a593Smuzhiyun
5790*4882a593Smuzhiyun# check for non-standard and hex prefixed decimal printf formats
5791*4882a593Smuzhiyun		my $show_L = 1;	#don't show the same defect twice
5792*4882a593Smuzhiyun		my $show_Z = 1;
5793*4882a593Smuzhiyun		while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
5794*4882a593Smuzhiyun			my $string = substr($rawline, $-[1], $+[1] - $-[1]);
5795*4882a593Smuzhiyun			$string =~ s/%%/__/g;
5796*4882a593Smuzhiyun			# check for %L
5797*4882a593Smuzhiyun			if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) {
5798*4882a593Smuzhiyun				WARN("PRINTF_L",
5799*4882a593Smuzhiyun				     "\%L$1 is non-standard C, use %ll$1\n" . $herecurr);
5800*4882a593Smuzhiyun				$show_L = 0;
5801*4882a593Smuzhiyun			}
5802*4882a593Smuzhiyun			# check for %Z
5803*4882a593Smuzhiyun			if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) {
5804*4882a593Smuzhiyun				WARN("PRINTF_Z",
5805*4882a593Smuzhiyun				     "%Z$1 is non-standard C, use %z$1\n" . $herecurr);
5806*4882a593Smuzhiyun				$show_Z = 0;
5807*4882a593Smuzhiyun			}
5808*4882a593Smuzhiyun			# check for 0x<decimal>
5809*4882a593Smuzhiyun			if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) {
5810*4882a593Smuzhiyun				ERROR("PRINTF_0XDECIMAL",
5811*4882a593Smuzhiyun				      "Prefixing 0x with decimal output is defective\n" . $herecurr);
5812*4882a593Smuzhiyun			}
5813*4882a593Smuzhiyun		}
5814*4882a593Smuzhiyun
5815*4882a593Smuzhiyun# check for line continuations in quoted strings with odd counts of "
5816*4882a593Smuzhiyun		if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {
5817*4882a593Smuzhiyun			WARN("LINE_CONTINUATIONS",
5818*4882a593Smuzhiyun			     "Avoid line continuations in quoted strings\n" . $herecurr);
5819*4882a593Smuzhiyun		}
5820*4882a593Smuzhiyun
5821*4882a593Smuzhiyun# warn about #if 0
5822*4882a593Smuzhiyun		if ($line =~ /^.\s*\#\s*if\s+0\b/) {
5823*4882a593Smuzhiyun			WARN("IF_0",
5824*4882a593Smuzhiyun			     "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
5825*4882a593Smuzhiyun		}
5826*4882a593Smuzhiyun
5827*4882a593Smuzhiyun# warn about #if 1
5828*4882a593Smuzhiyun		if ($line =~ /^.\s*\#\s*if\s+1\b/) {
5829*4882a593Smuzhiyun			WARN("IF_1",
5830*4882a593Smuzhiyun			     "Consider removing the #if 1 and its #endif\n" . $herecurr);
5831*4882a593Smuzhiyun		}
5832*4882a593Smuzhiyun
5833*4882a593Smuzhiyun# check for needless "if (<foo>) fn(<foo>)" uses
5834*4882a593Smuzhiyun		if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {
5835*4882a593Smuzhiyun			my $tested = quotemeta($1);
5836*4882a593Smuzhiyun			my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;';
5837*4882a593Smuzhiyun			if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) {
5838*4882a593Smuzhiyun				my $func = $1;
5839*4882a593Smuzhiyun				if (WARN('NEEDLESS_IF',
5840*4882a593Smuzhiyun					 "$func(NULL) is safe and this check is probably not required\n" . $hereprev) &&
5841*4882a593Smuzhiyun				    $fix) {
5842*4882a593Smuzhiyun					my $do_fix = 1;
5843*4882a593Smuzhiyun					my $leading_tabs = "";
5844*4882a593Smuzhiyun					my $new_leading_tabs = "";
5845*4882a593Smuzhiyun					if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) {
5846*4882a593Smuzhiyun						$leading_tabs = $1;
5847*4882a593Smuzhiyun					} else {
5848*4882a593Smuzhiyun						$do_fix = 0;
5849*4882a593Smuzhiyun					}
5850*4882a593Smuzhiyun					if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) {
5851*4882a593Smuzhiyun						$new_leading_tabs = $1;
5852*4882a593Smuzhiyun						if (length($leading_tabs) + 1 ne length($new_leading_tabs)) {
5853*4882a593Smuzhiyun							$do_fix = 0;
5854*4882a593Smuzhiyun						}
5855*4882a593Smuzhiyun					} else {
5856*4882a593Smuzhiyun						$do_fix = 0;
5857*4882a593Smuzhiyun					}
5858*4882a593Smuzhiyun					if ($do_fix) {
5859*4882a593Smuzhiyun						fix_delete_line($fixlinenr - 1, $prevrawline);
5860*4882a593Smuzhiyun						$fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/;
5861*4882a593Smuzhiyun					}
5862*4882a593Smuzhiyun				}
5863*4882a593Smuzhiyun			}
5864*4882a593Smuzhiyun		}
5865*4882a593Smuzhiyun
5866*4882a593Smuzhiyun# check for unnecessary "Out of Memory" messages
5867*4882a593Smuzhiyun		if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
5868*4882a593Smuzhiyun		    $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
5869*4882a593Smuzhiyun		    (defined $1 || defined $3) &&
5870*4882a593Smuzhiyun		    $linenr > 3) {
5871*4882a593Smuzhiyun			my $testval = $2;
5872*4882a593Smuzhiyun			my $testline = $lines[$linenr - 3];
5873*4882a593Smuzhiyun
5874*4882a593Smuzhiyun			my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
5875*4882a593Smuzhiyun#			print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
5876*4882a593Smuzhiyun
5877*4882a593Smuzhiyun			if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
5878*4882a593Smuzhiyun			    $s !~ /\b__GFP_NOWARN\b/ ) {
5879*4882a593Smuzhiyun				WARN("OOM_MESSAGE",
5880*4882a593Smuzhiyun				     "Possible unnecessary 'out of memory' message\n" . $hereprev);
5881*4882a593Smuzhiyun			}
5882*4882a593Smuzhiyun		}
5883*4882a593Smuzhiyun
5884*4882a593Smuzhiyun# check for logging functions with KERN_<LEVEL>
5885*4882a593Smuzhiyun		if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ &&
5886*4882a593Smuzhiyun		    $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) {
5887*4882a593Smuzhiyun			my $level = $1;
5888*4882a593Smuzhiyun			if (WARN("UNNECESSARY_KERN_LEVEL",
5889*4882a593Smuzhiyun				 "Possible unnecessary $level\n" . $herecurr) &&
5890*4882a593Smuzhiyun			    $fix) {
5891*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\s*$level\s*//;
5892*4882a593Smuzhiyun			}
5893*4882a593Smuzhiyun		}
5894*4882a593Smuzhiyun
5895*4882a593Smuzhiyun# check for logging continuations
5896*4882a593Smuzhiyun		if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) {
5897*4882a593Smuzhiyun			WARN("LOGGING_CONTINUATION",
5898*4882a593Smuzhiyun			     "Avoid logging continuation uses where feasible\n" . $herecurr);
5899*4882a593Smuzhiyun		}
5900*4882a593Smuzhiyun
5901*4882a593Smuzhiyun# check for mask then right shift without a parentheses
5902*4882a593Smuzhiyun		if ($perl_version_ok &&
5903*4882a593Smuzhiyun		    $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
5904*4882a593Smuzhiyun		    $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
5905*4882a593Smuzhiyun			WARN("MASK_THEN_SHIFT",
5906*4882a593Smuzhiyun			     "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr);
5907*4882a593Smuzhiyun		}
5908*4882a593Smuzhiyun
5909*4882a593Smuzhiyun# check for pointer comparisons to NULL
5910*4882a593Smuzhiyun		if ($perl_version_ok) {
5911*4882a593Smuzhiyun			while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
5912*4882a593Smuzhiyun				my $val = $1;
5913*4882a593Smuzhiyun				my $equal = "!";
5914*4882a593Smuzhiyun				$equal = "" if ($4 eq "!=");
5915*4882a593Smuzhiyun				if (CHK("COMPARISON_TO_NULL",
5916*4882a593Smuzhiyun					"Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) &&
5917*4882a593Smuzhiyun					    $fix) {
5918*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/;
5919*4882a593Smuzhiyun				}
5920*4882a593Smuzhiyun			}
5921*4882a593Smuzhiyun		}
5922*4882a593Smuzhiyun
5923*4882a593Smuzhiyun# check for bad placement of section $InitAttribute (e.g.: __initdata)
5924*4882a593Smuzhiyun		if ($line =~ /(\b$InitAttribute\b)/) {
5925*4882a593Smuzhiyun			my $attr = $1;
5926*4882a593Smuzhiyun			if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) {
5927*4882a593Smuzhiyun				my $ptr = $1;
5928*4882a593Smuzhiyun				my $var = $2;
5929*4882a593Smuzhiyun				if ((($ptr =~ /\b(union|struct)\s+$attr\b/ &&
5930*4882a593Smuzhiyun				      ERROR("MISPLACED_INIT",
5931*4882a593Smuzhiyun					    "$attr should be placed after $var\n" . $herecurr)) ||
5932*4882a593Smuzhiyun				     ($ptr !~ /\b(union|struct)\s+$attr\b/ &&
5933*4882a593Smuzhiyun				      WARN("MISPLACED_INIT",
5934*4882a593Smuzhiyun					   "$attr should be placed after $var\n" . $herecurr))) &&
5935*4882a593Smuzhiyun				    $fix) {
5936*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e;
5937*4882a593Smuzhiyun				}
5938*4882a593Smuzhiyun			}
5939*4882a593Smuzhiyun		}
5940*4882a593Smuzhiyun
5941*4882a593Smuzhiyun# check for $InitAttributeData (ie: __initdata) with const
5942*4882a593Smuzhiyun		if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
5943*4882a593Smuzhiyun			my $attr = $1;
5944*4882a593Smuzhiyun			$attr =~ /($InitAttributePrefix)(.*)/;
5945*4882a593Smuzhiyun			my $attr_prefix = $1;
5946*4882a593Smuzhiyun			my $attr_type = $2;
5947*4882a593Smuzhiyun			if (ERROR("INIT_ATTRIBUTE",
5948*4882a593Smuzhiyun				  "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
5949*4882a593Smuzhiyun			    $fix) {
5950*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
5951*4882a593Smuzhiyun				    s/$InitAttributeData/${attr_prefix}initconst/;
5952*4882a593Smuzhiyun			}
5953*4882a593Smuzhiyun		}
5954*4882a593Smuzhiyun
5955*4882a593Smuzhiyun# check for $InitAttributeConst (ie: __initconst) without const
5956*4882a593Smuzhiyun		if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
5957*4882a593Smuzhiyun			my $attr = $1;
5958*4882a593Smuzhiyun			if (ERROR("INIT_ATTRIBUTE",
5959*4882a593Smuzhiyun				  "Use of $attr requires a separate use of const\n" . $herecurr) &&
5960*4882a593Smuzhiyun			    $fix) {
5961*4882a593Smuzhiyun				my $lead = $fixed[$fixlinenr] =~
5962*4882a593Smuzhiyun				    /(^\+\s*(?:static\s+))/;
5963*4882a593Smuzhiyun				$lead = rtrim($1);
5964*4882a593Smuzhiyun				$lead = "$lead " if ($lead !~ /^\+$/);
5965*4882a593Smuzhiyun				$lead = "${lead}const ";
5966*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/;
5967*4882a593Smuzhiyun			}
5968*4882a593Smuzhiyun		}
5969*4882a593Smuzhiyun
5970*4882a593Smuzhiyun# check for __read_mostly with const non-pointer (should just be const)
5971*4882a593Smuzhiyun		if ($line =~ /\b__read_mostly\b/ &&
5972*4882a593Smuzhiyun		    $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) {
5973*4882a593Smuzhiyun			if (ERROR("CONST_READ_MOSTLY",
5974*4882a593Smuzhiyun				  "Invalid use of __read_mostly with const type\n" . $herecurr) &&
5975*4882a593Smuzhiyun			    $fix) {
5976*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\s+__read_mostly\b//;
5977*4882a593Smuzhiyun			}
5978*4882a593Smuzhiyun		}
5979*4882a593Smuzhiyun
5980*4882a593Smuzhiyun# don't use __constant_<foo> functions outside of include/uapi/
5981*4882a593Smuzhiyun		if ($realfile !~ m@^include/uapi/@ &&
5982*4882a593Smuzhiyun		    $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
5983*4882a593Smuzhiyun			my $constant_func = $1;
5984*4882a593Smuzhiyun			my $func = $constant_func;
5985*4882a593Smuzhiyun			$func =~ s/^__constant_//;
5986*4882a593Smuzhiyun			if (WARN("CONSTANT_CONVERSION",
5987*4882a593Smuzhiyun				 "$constant_func should be $func\n" . $herecurr) &&
5988*4882a593Smuzhiyun			    $fix) {
5989*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
5990*4882a593Smuzhiyun			}
5991*4882a593Smuzhiyun		}
5992*4882a593Smuzhiyun
5993*4882a593Smuzhiyun# prefer usleep_range over udelay
5994*4882a593Smuzhiyun		if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
5995*4882a593Smuzhiyun			my $delay = $1;
5996*4882a593Smuzhiyun			# ignore udelay's < 10, however
5997*4882a593Smuzhiyun			if (! ($delay < 10) ) {
5998*4882a593Smuzhiyun				CHK("USLEEP_RANGE",
5999*4882a593Smuzhiyun				    "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
6000*4882a593Smuzhiyun			}
6001*4882a593Smuzhiyun			if ($delay > 2000) {
6002*4882a593Smuzhiyun				WARN("LONG_UDELAY",
6003*4882a593Smuzhiyun				     "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
6004*4882a593Smuzhiyun			}
6005*4882a593Smuzhiyun		}
6006*4882a593Smuzhiyun
6007*4882a593Smuzhiyun# warn about unexpectedly long msleep's
6008*4882a593Smuzhiyun		if ($line =~ /\bmsleep\s*\((\d+)\);/) {
6009*4882a593Smuzhiyun			if ($1 < 20) {
6010*4882a593Smuzhiyun				WARN("MSLEEP",
6011*4882a593Smuzhiyun				     "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
6012*4882a593Smuzhiyun			}
6013*4882a593Smuzhiyun		}
6014*4882a593Smuzhiyun
6015*4882a593Smuzhiyun# check for comparisons of jiffies
6016*4882a593Smuzhiyun		if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
6017*4882a593Smuzhiyun			WARN("JIFFIES_COMPARISON",
6018*4882a593Smuzhiyun			     "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
6019*4882a593Smuzhiyun		}
6020*4882a593Smuzhiyun
6021*4882a593Smuzhiyun# check for comparisons of get_jiffies_64()
6022*4882a593Smuzhiyun		if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
6023*4882a593Smuzhiyun			WARN("JIFFIES_COMPARISON",
6024*4882a593Smuzhiyun			     "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
6025*4882a593Smuzhiyun		}
6026*4882a593Smuzhiyun
6027*4882a593Smuzhiyun# warn about #ifdefs in C files
6028*4882a593Smuzhiyun#		if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
6029*4882a593Smuzhiyun#			print "#ifdef in C files should be avoided\n";
6030*4882a593Smuzhiyun#			print "$herecurr";
6031*4882a593Smuzhiyun#			$clean = 0;
6032*4882a593Smuzhiyun#		}
6033*4882a593Smuzhiyun
6034*4882a593Smuzhiyun# warn about spacing in #ifdefs
6035*4882a593Smuzhiyun		if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
6036*4882a593Smuzhiyun			if (ERROR("SPACING",
6037*4882a593Smuzhiyun				  "exactly one space required after that #$1\n" . $herecurr) &&
6038*4882a593Smuzhiyun			    $fix) {
6039*4882a593Smuzhiyun				$fixed[$fixlinenr] =~
6040*4882a593Smuzhiyun				    s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
6041*4882a593Smuzhiyun			}
6042*4882a593Smuzhiyun
6043*4882a593Smuzhiyun		}
6044*4882a593Smuzhiyun
6045*4882a593Smuzhiyun# check for spinlock_t definitions without a comment.
6046*4882a593Smuzhiyun		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
6047*4882a593Smuzhiyun		    $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
6048*4882a593Smuzhiyun			my $which = $1;
6049*4882a593Smuzhiyun			if (!ctx_has_comment($first_line, $linenr)) {
6050*4882a593Smuzhiyun				CHK("UNCOMMENTED_DEFINITION",
6051*4882a593Smuzhiyun				    "$1 definition without comment\n" . $herecurr);
6052*4882a593Smuzhiyun			}
6053*4882a593Smuzhiyun		}
6054*4882a593Smuzhiyun# check for memory barriers without a comment.
6055*4882a593Smuzhiyun
6056*4882a593Smuzhiyun		my $barriers = qr{
6057*4882a593Smuzhiyun			mb|
6058*4882a593Smuzhiyun			rmb|
6059*4882a593Smuzhiyun			wmb
6060*4882a593Smuzhiyun		}x;
6061*4882a593Smuzhiyun		my $barrier_stems = qr{
6062*4882a593Smuzhiyun			mb__before_atomic|
6063*4882a593Smuzhiyun			mb__after_atomic|
6064*4882a593Smuzhiyun			store_release|
6065*4882a593Smuzhiyun			load_acquire|
6066*4882a593Smuzhiyun			store_mb|
6067*4882a593Smuzhiyun			(?:$barriers)
6068*4882a593Smuzhiyun		}x;
6069*4882a593Smuzhiyun		my $all_barriers = qr{
6070*4882a593Smuzhiyun			(?:$barriers)|
6071*4882a593Smuzhiyun			smp_(?:$barrier_stems)|
6072*4882a593Smuzhiyun			virt_(?:$barrier_stems)
6073*4882a593Smuzhiyun		}x;
6074*4882a593Smuzhiyun
6075*4882a593Smuzhiyun		if ($line =~ /\b(?:$all_barriers)\s*\(/) {
6076*4882a593Smuzhiyun			if (!ctx_has_comment($first_line, $linenr)) {
6077*4882a593Smuzhiyun				WARN("MEMORY_BARRIER",
6078*4882a593Smuzhiyun				     "memory barrier without comment\n" . $herecurr);
6079*4882a593Smuzhiyun			}
6080*4882a593Smuzhiyun		}
6081*4882a593Smuzhiyun
6082*4882a593Smuzhiyun		my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x;
6083*4882a593Smuzhiyun
6084*4882a593Smuzhiyun		if ($realfile !~ m@^include/asm-generic/@ &&
6085*4882a593Smuzhiyun		    $realfile !~ m@/barrier\.h$@ &&
6086*4882a593Smuzhiyun		    $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&
6087*4882a593Smuzhiyun		    $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {
6088*4882a593Smuzhiyun			WARN("MEMORY_BARRIER",
6089*4882a593Smuzhiyun			     "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr);
6090*4882a593Smuzhiyun		}
6091*4882a593Smuzhiyun
6092*4882a593Smuzhiyun# check for waitqueue_active without a comment.
6093*4882a593Smuzhiyun		if ($line =~ /\bwaitqueue_active\s*\(/) {
6094*4882a593Smuzhiyun			if (!ctx_has_comment($first_line, $linenr)) {
6095*4882a593Smuzhiyun				WARN("WAITQUEUE_ACTIVE",
6096*4882a593Smuzhiyun				     "waitqueue_active without comment\n" . $herecurr);
6097*4882a593Smuzhiyun			}
6098*4882a593Smuzhiyun		}
6099*4882a593Smuzhiyun
6100*4882a593Smuzhiyun# check for data_race without a comment.
6101*4882a593Smuzhiyun		if ($line =~ /\bdata_race\s*\(/) {
6102*4882a593Smuzhiyun			if (!ctx_has_comment($first_line, $linenr)) {
6103*4882a593Smuzhiyun				WARN("DATA_RACE",
6104*4882a593Smuzhiyun				     "data_race without comment\n" . $herecurr);
6105*4882a593Smuzhiyun			}
6106*4882a593Smuzhiyun		}
6107*4882a593Smuzhiyun
6108*4882a593Smuzhiyun# check of hardware specific defines
6109*4882a593Smuzhiyun		if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
6110*4882a593Smuzhiyun			CHK("ARCH_DEFINES",
6111*4882a593Smuzhiyun			    "architecture specific defines should be avoided\n" .  $herecurr);
6112*4882a593Smuzhiyun		}
6113*4882a593Smuzhiyun
6114*4882a593Smuzhiyun# check that the storage class is not after a type
6115*4882a593Smuzhiyun		if ($line =~ /\b($Type)\s+($Storage)\b/) {
6116*4882a593Smuzhiyun			WARN("STORAGE_CLASS",
6117*4882a593Smuzhiyun			     "storage class '$2' should be located before type '$1'\n" . $herecurr);
6118*4882a593Smuzhiyun		}
6119*4882a593Smuzhiyun# Check that the storage class is at the beginning of a declaration
6120*4882a593Smuzhiyun		if ($line =~ /\b$Storage\b/ &&
6121*4882a593Smuzhiyun		    $line !~ /^.\s*$Storage/ &&
6122*4882a593Smuzhiyun		    $line =~ /^.\s*(.+?)\$Storage\s/ &&
6123*4882a593Smuzhiyun		    $1 !~ /[\,\)]\s*$/) {
6124*4882a593Smuzhiyun			WARN("STORAGE_CLASS",
6125*4882a593Smuzhiyun			     "storage class should be at the beginning of the declaration\n" . $herecurr);
6126*4882a593Smuzhiyun		}
6127*4882a593Smuzhiyun
6128*4882a593Smuzhiyun# check the location of the inline attribute, that it is between
6129*4882a593Smuzhiyun# storage class and type.
6130*4882a593Smuzhiyun		if ($line =~ /\b$Type\s+$Inline\b/ ||
6131*4882a593Smuzhiyun		    $line =~ /\b$Inline\s+$Storage\b/) {
6132*4882a593Smuzhiyun			ERROR("INLINE_LOCATION",
6133*4882a593Smuzhiyun			      "inline keyword should sit between storage class and type\n" . $herecurr);
6134*4882a593Smuzhiyun		}
6135*4882a593Smuzhiyun
6136*4882a593Smuzhiyun# Check for __inline__ and __inline, prefer inline
6137*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6138*4882a593Smuzhiyun		    $line =~ /\b(__inline__|__inline)\b/) {
6139*4882a593Smuzhiyun			if (WARN("INLINE",
6140*4882a593Smuzhiyun				 "plain inline is preferred over $1\n" . $herecurr) &&
6141*4882a593Smuzhiyun			    $fix) {
6142*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/;
6143*4882a593Smuzhiyun
6144*4882a593Smuzhiyun			}
6145*4882a593Smuzhiyun		}
6146*4882a593Smuzhiyun
6147*4882a593Smuzhiyun# Check for __attribute__ packed, prefer __packed
6148*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6149*4882a593Smuzhiyun		    $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
6150*4882a593Smuzhiyun			WARN("PREFER_PACKED",
6151*4882a593Smuzhiyun			     "__packed is preferred over __attribute__((packed))\n" . $herecurr);
6152*4882a593Smuzhiyun		}
6153*4882a593Smuzhiyun
6154*4882a593Smuzhiyun# Check for __attribute__ aligned, prefer __aligned
6155*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6156*4882a593Smuzhiyun		    $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
6157*4882a593Smuzhiyun			WARN("PREFER_ALIGNED",
6158*4882a593Smuzhiyun			     "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
6159*4882a593Smuzhiyun		}
6160*4882a593Smuzhiyun
6161*4882a593Smuzhiyun# Check for __attribute__ section, prefer __section
6162*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6163*4882a593Smuzhiyun		    $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
6164*4882a593Smuzhiyun			my $old = substr($rawline, $-[1], $+[1] - $-[1]);
6165*4882a593Smuzhiyun			my $new = substr($old, 1, -1);
6166*4882a593Smuzhiyun			if (WARN("PREFER_SECTION",
6167*4882a593Smuzhiyun				 "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
6168*4882a593Smuzhiyun			    $fix) {
6169*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
6170*4882a593Smuzhiyun			}
6171*4882a593Smuzhiyun		}
6172*4882a593Smuzhiyun
6173*4882a593Smuzhiyun# Check for __attribute__ format(printf, prefer __printf
6174*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6175*4882a593Smuzhiyun		    $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
6176*4882a593Smuzhiyun			if (WARN("PREFER_PRINTF",
6177*4882a593Smuzhiyun				 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
6178*4882a593Smuzhiyun			    $fix) {
6179*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
6180*4882a593Smuzhiyun
6181*4882a593Smuzhiyun			}
6182*4882a593Smuzhiyun		}
6183*4882a593Smuzhiyun
6184*4882a593Smuzhiyun# Check for __attribute__ format(scanf, prefer __scanf
6185*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6186*4882a593Smuzhiyun		    $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
6187*4882a593Smuzhiyun			if (WARN("PREFER_SCANF",
6188*4882a593Smuzhiyun				 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
6189*4882a593Smuzhiyun			    $fix) {
6190*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
6191*4882a593Smuzhiyun			}
6192*4882a593Smuzhiyun		}
6193*4882a593Smuzhiyun
6194*4882a593Smuzhiyun# Check for __attribute__ weak, or __weak declarations (may have link issues)
6195*4882a593Smuzhiyun		if ($perl_version_ok &&
6196*4882a593Smuzhiyun		    $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
6197*4882a593Smuzhiyun		    ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
6198*4882a593Smuzhiyun		     $line =~ /\b__weak\b/)) {
6199*4882a593Smuzhiyun			ERROR("WEAK_DECLARATION",
6200*4882a593Smuzhiyun			      "Using weak declarations can have unintended link defects\n" . $herecurr);
6201*4882a593Smuzhiyun		}
6202*4882a593Smuzhiyun
6203*4882a593Smuzhiyun# check for c99 types like uint8_t used outside of uapi/ and tools/
6204*4882a593Smuzhiyun		if ($realfile !~ m@\binclude/uapi/@ &&
6205*4882a593Smuzhiyun		    $realfile !~ m@\btools/@ &&
6206*4882a593Smuzhiyun		    $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {
6207*4882a593Smuzhiyun			my $type = $1;
6208*4882a593Smuzhiyun			if ($type =~ /\b($typeC99Typedefs)\b/) {
6209*4882a593Smuzhiyun				$type = $1;
6210*4882a593Smuzhiyun				my $kernel_type = 'u';
6211*4882a593Smuzhiyun				$kernel_type = 's' if ($type =~ /^_*[si]/);
6212*4882a593Smuzhiyun				$type =~ /(\d+)/;
6213*4882a593Smuzhiyun				$kernel_type .= $1;
6214*4882a593Smuzhiyun				if (CHK("PREFER_KERNEL_TYPES",
6215*4882a593Smuzhiyun					"Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) &&
6216*4882a593Smuzhiyun				    $fix) {
6217*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/;
6218*4882a593Smuzhiyun				}
6219*4882a593Smuzhiyun			}
6220*4882a593Smuzhiyun		}
6221*4882a593Smuzhiyun
6222*4882a593Smuzhiyun# check for cast of C90 native int or longer types constants
6223*4882a593Smuzhiyun		if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {
6224*4882a593Smuzhiyun			my $cast = $1;
6225*4882a593Smuzhiyun			my $const = $2;
6226*4882a593Smuzhiyun			if (WARN("TYPECAST_INT_CONSTANT",
6227*4882a593Smuzhiyun				 "Unnecessary typecast of c90 int constant\n" . $herecurr) &&
6228*4882a593Smuzhiyun			    $fix) {
6229*4882a593Smuzhiyun				my $suffix = "";
6230*4882a593Smuzhiyun				my $newconst = $const;
6231*4882a593Smuzhiyun				$newconst =~ s/${Int_type}$//;
6232*4882a593Smuzhiyun				$suffix .= 'U' if ($cast =~ /\bunsigned\b/);
6233*4882a593Smuzhiyun				if ($cast =~ /\blong\s+long\b/) {
6234*4882a593Smuzhiyun					$suffix .= 'LL';
6235*4882a593Smuzhiyun				} elsif ($cast =~ /\blong\b/) {
6236*4882a593Smuzhiyun					$suffix .= 'L';
6237*4882a593Smuzhiyun				}
6238*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;
6239*4882a593Smuzhiyun			}
6240*4882a593Smuzhiyun		}
6241*4882a593Smuzhiyun
6242*4882a593Smuzhiyun# check for sizeof(&)
6243*4882a593Smuzhiyun		if ($line =~ /\bsizeof\s*\(\s*\&/) {
6244*4882a593Smuzhiyun			WARN("SIZEOF_ADDRESS",
6245*4882a593Smuzhiyun			     "sizeof(& should be avoided\n" . $herecurr);
6246*4882a593Smuzhiyun		}
6247*4882a593Smuzhiyun
6248*4882a593Smuzhiyun# check for sizeof without parenthesis
6249*4882a593Smuzhiyun		if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
6250*4882a593Smuzhiyun			if (WARN("SIZEOF_PARENTHESIS",
6251*4882a593Smuzhiyun				 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
6252*4882a593Smuzhiyun			    $fix) {
6253*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
6254*4882a593Smuzhiyun			}
6255*4882a593Smuzhiyun		}
6256*4882a593Smuzhiyun
6257*4882a593Smuzhiyun# check for struct spinlock declarations
6258*4882a593Smuzhiyun		if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) {
6259*4882a593Smuzhiyun			WARN("USE_SPINLOCK_T",
6260*4882a593Smuzhiyun			     "struct spinlock should be spinlock_t\n" . $herecurr);
6261*4882a593Smuzhiyun		}
6262*4882a593Smuzhiyun
6263*4882a593Smuzhiyun# check for seq_printf uses that could be seq_puts
6264*4882a593Smuzhiyun		if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
6265*4882a593Smuzhiyun			my $fmt = get_quoted_string($line, $rawline);
6266*4882a593Smuzhiyun			$fmt =~ s/%%//g;
6267*4882a593Smuzhiyun			if ($fmt !~ /%/) {
6268*4882a593Smuzhiyun				if (WARN("PREFER_SEQ_PUTS",
6269*4882a593Smuzhiyun					 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
6270*4882a593Smuzhiyun				    $fix) {
6271*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;
6272*4882a593Smuzhiyun				}
6273*4882a593Smuzhiyun			}
6274*4882a593Smuzhiyun		}
6275*4882a593Smuzhiyun
6276*4882a593Smuzhiyun# check for vsprintf extension %p<foo> misuses
6277*4882a593Smuzhiyun		if ($perl_version_ok &&
6278*4882a593Smuzhiyun		    defined $stat &&
6279*4882a593Smuzhiyun		    $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
6280*4882a593Smuzhiyun		    $1 !~ /^_*volatile_*$/) {
6281*4882a593Smuzhiyun			my $stat_real;
6282*4882a593Smuzhiyun
6283*4882a593Smuzhiyun			my $lc = $stat =~ tr@\n@@;
6284*4882a593Smuzhiyun			$lc = $lc + $linenr;
6285*4882a593Smuzhiyun		        for (my $count = $linenr; $count <= $lc; $count++) {
6286*4882a593Smuzhiyun				my $specifier;
6287*4882a593Smuzhiyun				my $extension;
6288*4882a593Smuzhiyun				my $qualifier;
6289*4882a593Smuzhiyun				my $bad_specifier = "";
6290*4882a593Smuzhiyun				my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
6291*4882a593Smuzhiyun				$fmt =~ s/%%//g;
6292*4882a593Smuzhiyun
6293*4882a593Smuzhiyun				while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {
6294*4882a593Smuzhiyun					$specifier = $1;
6295*4882a593Smuzhiyun					$extension = $2;
6296*4882a593Smuzhiyun					$qualifier = $3;
6297*4882a593Smuzhiyun					if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
6298*4882a593Smuzhiyun					    ($extension eq "f" &&
6299*4882a593Smuzhiyun					     defined $qualifier && $qualifier !~ /^w/)) {
6300*4882a593Smuzhiyun						$bad_specifier = $specifier;
6301*4882a593Smuzhiyun						last;
6302*4882a593Smuzhiyun					}
6303*4882a593Smuzhiyun					if ($extension eq "x" && !defined($stat_real)) {
6304*4882a593Smuzhiyun						if (!defined($stat_real)) {
6305*4882a593Smuzhiyun							$stat_real = get_stat_real($linenr, $lc);
6306*4882a593Smuzhiyun						}
6307*4882a593Smuzhiyun						WARN("VSPRINTF_SPECIFIER_PX",
6308*4882a593Smuzhiyun						     "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n");
6309*4882a593Smuzhiyun					}
6310*4882a593Smuzhiyun				}
6311*4882a593Smuzhiyun				if ($bad_specifier ne "") {
6312*4882a593Smuzhiyun					my $stat_real = get_stat_real($linenr, $lc);
6313*4882a593Smuzhiyun					my $ext_type = "Invalid";
6314*4882a593Smuzhiyun					my $use = "";
6315*4882a593Smuzhiyun					if ($bad_specifier =~ /p[Ff]/) {
6316*4882a593Smuzhiyun						$use = " - use %pS instead";
6317*4882a593Smuzhiyun						$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
6318*4882a593Smuzhiyun					}
6319*4882a593Smuzhiyun
6320*4882a593Smuzhiyun					WARN("VSPRINTF_POINTER_EXTENSION",
6321*4882a593Smuzhiyun					     "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
6322*4882a593Smuzhiyun				}
6323*4882a593Smuzhiyun			}
6324*4882a593Smuzhiyun		}
6325*4882a593Smuzhiyun
6326*4882a593Smuzhiyun# Check for misused memsets
6327*4882a593Smuzhiyun		if ($perl_version_ok &&
6328*4882a593Smuzhiyun		    defined $stat &&
6329*4882a593Smuzhiyun		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
6330*4882a593Smuzhiyun
6331*4882a593Smuzhiyun			my $ms_addr = $2;
6332*4882a593Smuzhiyun			my $ms_val = $7;
6333*4882a593Smuzhiyun			my $ms_size = $12;
6334*4882a593Smuzhiyun
6335*4882a593Smuzhiyun			if ($ms_size =~ /^(0x|)0$/i) {
6336*4882a593Smuzhiyun				ERROR("MEMSET",
6337*4882a593Smuzhiyun				      "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n");
6338*4882a593Smuzhiyun			} elsif ($ms_size =~ /^(0x|)1$/i) {
6339*4882a593Smuzhiyun				WARN("MEMSET",
6340*4882a593Smuzhiyun				     "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n");
6341*4882a593Smuzhiyun			}
6342*4882a593Smuzhiyun		}
6343*4882a593Smuzhiyun
6344*4882a593Smuzhiyun# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
6345*4882a593Smuzhiyun#		if ($perl_version_ok &&
6346*4882a593Smuzhiyun#		    defined $stat &&
6347*4882a593Smuzhiyun#		    $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6348*4882a593Smuzhiyun#			if (WARN("PREFER_ETHER_ADDR_COPY",
6349*4882a593Smuzhiyun#				 "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
6350*4882a593Smuzhiyun#			    $fix) {
6351*4882a593Smuzhiyun#				$fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
6352*4882a593Smuzhiyun#			}
6353*4882a593Smuzhiyun#		}
6354*4882a593Smuzhiyun
6355*4882a593Smuzhiyun# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
6356*4882a593Smuzhiyun#		if ($perl_version_ok &&
6357*4882a593Smuzhiyun#		    defined $stat &&
6358*4882a593Smuzhiyun#		    $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6359*4882a593Smuzhiyun#			WARN("PREFER_ETHER_ADDR_EQUAL",
6360*4882a593Smuzhiyun#			     "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
6361*4882a593Smuzhiyun#		}
6362*4882a593Smuzhiyun
6363*4882a593Smuzhiyun# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
6364*4882a593Smuzhiyun# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
6365*4882a593Smuzhiyun#		if ($perl_version_ok &&
6366*4882a593Smuzhiyun#		    defined $stat &&
6367*4882a593Smuzhiyun#		    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6368*4882a593Smuzhiyun#
6369*4882a593Smuzhiyun#			my $ms_val = $7;
6370*4882a593Smuzhiyun#
6371*4882a593Smuzhiyun#			if ($ms_val =~ /^(?:0x|)0+$/i) {
6372*4882a593Smuzhiyun#				if (WARN("PREFER_ETH_ZERO_ADDR",
6373*4882a593Smuzhiyun#					 "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
6374*4882a593Smuzhiyun#				    $fix) {
6375*4882a593Smuzhiyun#					$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
6376*4882a593Smuzhiyun#				}
6377*4882a593Smuzhiyun#			} elsif ($ms_val =~ /^(?:0xff|255)$/i) {
6378*4882a593Smuzhiyun#				if (WARN("PREFER_ETH_BROADCAST_ADDR",
6379*4882a593Smuzhiyun#					 "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
6380*4882a593Smuzhiyun#				    $fix) {
6381*4882a593Smuzhiyun#					$fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
6382*4882a593Smuzhiyun#				}
6383*4882a593Smuzhiyun#			}
6384*4882a593Smuzhiyun#		}
6385*4882a593Smuzhiyun
6386*4882a593Smuzhiyun# typecasts on min/max could be min_t/max_t
6387*4882a593Smuzhiyun		if ($perl_version_ok &&
6388*4882a593Smuzhiyun		    defined $stat &&
6389*4882a593Smuzhiyun		    $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
6390*4882a593Smuzhiyun			if (defined $2 || defined $7) {
6391*4882a593Smuzhiyun				my $call = $1;
6392*4882a593Smuzhiyun				my $cast1 = deparenthesize($2);
6393*4882a593Smuzhiyun				my $arg1 = $3;
6394*4882a593Smuzhiyun				my $cast2 = deparenthesize($7);
6395*4882a593Smuzhiyun				my $arg2 = $8;
6396*4882a593Smuzhiyun				my $cast;
6397*4882a593Smuzhiyun
6398*4882a593Smuzhiyun				if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) {
6399*4882a593Smuzhiyun					$cast = "$cast1 or $cast2";
6400*4882a593Smuzhiyun				} elsif ($cast1 ne "") {
6401*4882a593Smuzhiyun					$cast = $cast1;
6402*4882a593Smuzhiyun				} else {
6403*4882a593Smuzhiyun					$cast = $cast2;
6404*4882a593Smuzhiyun				}
6405*4882a593Smuzhiyun				WARN("MINMAX",
6406*4882a593Smuzhiyun				     "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n");
6407*4882a593Smuzhiyun			}
6408*4882a593Smuzhiyun		}
6409*4882a593Smuzhiyun
6410*4882a593Smuzhiyun# check usleep_range arguments
6411*4882a593Smuzhiyun		if ($perl_version_ok &&
6412*4882a593Smuzhiyun		    defined $stat &&
6413*4882a593Smuzhiyun		    $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
6414*4882a593Smuzhiyun			my $min = $1;
6415*4882a593Smuzhiyun			my $max = $7;
6416*4882a593Smuzhiyun			if ($min eq $max) {
6417*4882a593Smuzhiyun				WARN("USLEEP_RANGE",
6418*4882a593Smuzhiyun				     "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
6419*4882a593Smuzhiyun			} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
6420*4882a593Smuzhiyun				 $min > $max) {
6421*4882a593Smuzhiyun				WARN("USLEEP_RANGE",
6422*4882a593Smuzhiyun				     "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
6423*4882a593Smuzhiyun			}
6424*4882a593Smuzhiyun		}
6425*4882a593Smuzhiyun
6426*4882a593Smuzhiyun# check for naked sscanf
6427*4882a593Smuzhiyun		if ($perl_version_ok &&
6428*4882a593Smuzhiyun		    defined $stat &&
6429*4882a593Smuzhiyun		    $line =~ /\bsscanf\b/ &&
6430*4882a593Smuzhiyun		    ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
6431*4882a593Smuzhiyun		     $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
6432*4882a593Smuzhiyun		     $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
6433*4882a593Smuzhiyun			my $lc = $stat =~ tr@\n@@;
6434*4882a593Smuzhiyun			$lc = $lc + $linenr;
6435*4882a593Smuzhiyun			my $stat_real = get_stat_real($linenr, $lc);
6436*4882a593Smuzhiyun			WARN("NAKED_SSCANF",
6437*4882a593Smuzhiyun			     "unchecked sscanf return value\n" . "$here\n$stat_real\n");
6438*4882a593Smuzhiyun		}
6439*4882a593Smuzhiyun
6440*4882a593Smuzhiyun# check for simple sscanf that should be kstrto<foo>
6441*4882a593Smuzhiyun		if ($perl_version_ok &&
6442*4882a593Smuzhiyun		    defined $stat &&
6443*4882a593Smuzhiyun		    $line =~ /\bsscanf\b/) {
6444*4882a593Smuzhiyun			my $lc = $stat =~ tr@\n@@;
6445*4882a593Smuzhiyun			$lc = $lc + $linenr;
6446*4882a593Smuzhiyun			my $stat_real = get_stat_real($linenr, $lc);
6447*4882a593Smuzhiyun			if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
6448*4882a593Smuzhiyun				my $format = $6;
6449*4882a593Smuzhiyun				my $count = $format =~ tr@%@%@;
6450*4882a593Smuzhiyun				if ($count == 1 &&
6451*4882a593Smuzhiyun				    $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {
6452*4882a593Smuzhiyun					WARN("SSCANF_TO_KSTRTO",
6453*4882a593Smuzhiyun					     "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n");
6454*4882a593Smuzhiyun				}
6455*4882a593Smuzhiyun			}
6456*4882a593Smuzhiyun		}
6457*4882a593Smuzhiyun
6458*4882a593Smuzhiyun# check for new externs in .h files.
6459*4882a593Smuzhiyun		if ($realfile =~ /\.h$/ &&
6460*4882a593Smuzhiyun		    $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
6461*4882a593Smuzhiyun			if (CHK("AVOID_EXTERNS",
6462*4882a593Smuzhiyun				"extern prototypes should be avoided in .h files\n" . $herecurr) &&
6463*4882a593Smuzhiyun			    $fix) {
6464*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
6465*4882a593Smuzhiyun			}
6466*4882a593Smuzhiyun		}
6467*4882a593Smuzhiyun
6468*4882a593Smuzhiyun# check for new externs in .c files.
6469*4882a593Smuzhiyun		if ($realfile =~ /\.c$/ && defined $stat &&
6470*4882a593Smuzhiyun		    $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
6471*4882a593Smuzhiyun		{
6472*4882a593Smuzhiyun			my $function_name = $1;
6473*4882a593Smuzhiyun			my $paren_space = $2;
6474*4882a593Smuzhiyun
6475*4882a593Smuzhiyun			my $s = $stat;
6476*4882a593Smuzhiyun			if (defined $cond) {
6477*4882a593Smuzhiyun				substr($s, 0, length($cond), '');
6478*4882a593Smuzhiyun			}
6479*4882a593Smuzhiyun			if ($s =~ /^\s*;/)
6480*4882a593Smuzhiyun			{
6481*4882a593Smuzhiyun				WARN("AVOID_EXTERNS",
6482*4882a593Smuzhiyun				     "externs should be avoided in .c files\n" .  $herecurr);
6483*4882a593Smuzhiyun			}
6484*4882a593Smuzhiyun
6485*4882a593Smuzhiyun			if ($paren_space =~ /\n/) {
6486*4882a593Smuzhiyun				WARN("FUNCTION_ARGUMENTS",
6487*4882a593Smuzhiyun				     "arguments for function declarations should follow identifier\n" . $herecurr);
6488*4882a593Smuzhiyun			}
6489*4882a593Smuzhiyun
6490*4882a593Smuzhiyun		} elsif ($realfile =~ /\.c$/ && defined $stat &&
6491*4882a593Smuzhiyun		    $stat =~ /^.\s*extern\s+/)
6492*4882a593Smuzhiyun		{
6493*4882a593Smuzhiyun			WARN("AVOID_EXTERNS",
6494*4882a593Smuzhiyun			     "externs should be avoided in .c files\n" .  $herecurr);
6495*4882a593Smuzhiyun		}
6496*4882a593Smuzhiyun
6497*4882a593Smuzhiyun# check for function declarations that have arguments without identifier names
6498*4882a593Smuzhiyun		if (defined $stat &&
6499*4882a593Smuzhiyun		    $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
6500*4882a593Smuzhiyun		    $1 ne "void") {
6501*4882a593Smuzhiyun			my $args = trim($1);
6502*4882a593Smuzhiyun			while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
6503*4882a593Smuzhiyun				my $arg = trim($1);
6504*4882a593Smuzhiyun				if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
6505*4882a593Smuzhiyun					WARN("FUNCTION_ARGUMENTS",
6506*4882a593Smuzhiyun					     "function definition argument '$arg' should also have an identifier name\n" . $herecurr);
6507*4882a593Smuzhiyun				}
6508*4882a593Smuzhiyun			}
6509*4882a593Smuzhiyun		}
6510*4882a593Smuzhiyun
6511*4882a593Smuzhiyun# check for function definitions
6512*4882a593Smuzhiyun		if ($perl_version_ok &&
6513*4882a593Smuzhiyun		    defined $stat &&
6514*4882a593Smuzhiyun		    $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
6515*4882a593Smuzhiyun			$context_function = $1;
6516*4882a593Smuzhiyun
6517*4882a593Smuzhiyun# check for multiline function definition with misplaced open brace
6518*4882a593Smuzhiyun			my $ok = 0;
6519*4882a593Smuzhiyun			my $cnt = statement_rawlines($stat);
6520*4882a593Smuzhiyun			my $herectx = $here . "\n";
6521*4882a593Smuzhiyun			for (my $n = 0; $n < $cnt; $n++) {
6522*4882a593Smuzhiyun				my $rl = raw_line($linenr, $n);
6523*4882a593Smuzhiyun				$herectx .=  $rl . "\n";
6524*4882a593Smuzhiyun				$ok = 1 if ($rl =~ /^[ \+]\{/);
6525*4882a593Smuzhiyun				$ok = 1 if ($rl =~ /\{/ && $n == 0);
6526*4882a593Smuzhiyun				last if $rl =~ /^[ \+].*\{/;
6527*4882a593Smuzhiyun			}
6528*4882a593Smuzhiyun			if (!$ok) {
6529*4882a593Smuzhiyun				ERROR("OPEN_BRACE",
6530*4882a593Smuzhiyun				      "open brace '{' following function definitions go on the next line\n" . $herectx);
6531*4882a593Smuzhiyun			}
6532*4882a593Smuzhiyun		}
6533*4882a593Smuzhiyun
6534*4882a593Smuzhiyun# checks for new __setup's
6535*4882a593Smuzhiyun		if ($rawline =~ /\b__setup\("([^"]*)"/) {
6536*4882a593Smuzhiyun			my $name = $1;
6537*4882a593Smuzhiyun
6538*4882a593Smuzhiyun			if (!grep(/$name/, @setup_docs)) {
6539*4882a593Smuzhiyun				CHK("UNDOCUMENTED_SETUP",
6540*4882a593Smuzhiyun				    "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);
6541*4882a593Smuzhiyun			}
6542*4882a593Smuzhiyun		}
6543*4882a593Smuzhiyun
6544*4882a593Smuzhiyun# check for pointless casting of alloc functions
6545*4882a593Smuzhiyun		if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
6546*4882a593Smuzhiyun			WARN("UNNECESSARY_CASTS",
6547*4882a593Smuzhiyun			     "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
6548*4882a593Smuzhiyun		}
6549*4882a593Smuzhiyun
6550*4882a593Smuzhiyun# alloc style
6551*4882a593Smuzhiyun# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
6552*4882a593Smuzhiyun		if ($perl_version_ok &&
6553*4882a593Smuzhiyun		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
6554*4882a593Smuzhiyun			CHK("ALLOC_SIZEOF_STRUCT",
6555*4882a593Smuzhiyun			    "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
6556*4882a593Smuzhiyun		}
6557*4882a593Smuzhiyun
6558*4882a593Smuzhiyun# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
6559*4882a593Smuzhiyun		if ($perl_version_ok &&
6560*4882a593Smuzhiyun		    defined $stat &&
6561*4882a593Smuzhiyun		    $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
6562*4882a593Smuzhiyun			my $oldfunc = $3;
6563*4882a593Smuzhiyun			my $a1 = $4;
6564*4882a593Smuzhiyun			my $a2 = $10;
6565*4882a593Smuzhiyun			my $newfunc = "kmalloc_array";
6566*4882a593Smuzhiyun			$newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
6567*4882a593Smuzhiyun			my $r1 = $a1;
6568*4882a593Smuzhiyun			my $r2 = $a2;
6569*4882a593Smuzhiyun			if ($a1 =~ /^sizeof\s*\S/) {
6570*4882a593Smuzhiyun				$r1 = $a2;
6571*4882a593Smuzhiyun				$r2 = $a1;
6572*4882a593Smuzhiyun			}
6573*4882a593Smuzhiyun			if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
6574*4882a593Smuzhiyun			    !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
6575*4882a593Smuzhiyun				my $cnt = statement_rawlines($stat);
6576*4882a593Smuzhiyun				my $herectx = get_stat_here($linenr, $cnt, $here);
6577*4882a593Smuzhiyun
6578*4882a593Smuzhiyun				if (WARN("ALLOC_WITH_MULTIPLY",
6579*4882a593Smuzhiyun					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
6580*4882a593Smuzhiyun				    $cnt == 1 &&
6581*4882a593Smuzhiyun				    $fix) {
6582*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
6583*4882a593Smuzhiyun				}
6584*4882a593Smuzhiyun			}
6585*4882a593Smuzhiyun		}
6586*4882a593Smuzhiyun
6587*4882a593Smuzhiyun# check for krealloc arg reuse
6588*4882a593Smuzhiyun		if ($perl_version_ok &&
6589*4882a593Smuzhiyun		    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
6590*4882a593Smuzhiyun		    $1 eq $3) {
6591*4882a593Smuzhiyun			WARN("KREALLOC_ARG_REUSE",
6592*4882a593Smuzhiyun			     "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
6593*4882a593Smuzhiyun		}
6594*4882a593Smuzhiyun
6595*4882a593Smuzhiyun# check for alloc argument mismatch
6596*4882a593Smuzhiyun		if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) {
6597*4882a593Smuzhiyun			WARN("ALLOC_ARRAY_ARGS",
6598*4882a593Smuzhiyun			     "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
6599*4882a593Smuzhiyun		}
6600*4882a593Smuzhiyun
6601*4882a593Smuzhiyun# check for multiple semicolons
6602*4882a593Smuzhiyun		if ($line =~ /;\s*;\s*$/) {
6603*4882a593Smuzhiyun			if (WARN("ONE_SEMICOLON",
6604*4882a593Smuzhiyun				 "Statements terminations use 1 semicolon\n" . $herecurr) &&
6605*4882a593Smuzhiyun			    $fix) {
6606*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
6607*4882a593Smuzhiyun			}
6608*4882a593Smuzhiyun		}
6609*4882a593Smuzhiyun
6610*4882a593Smuzhiyun# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
6611*4882a593Smuzhiyun		if ($realfile !~ m@^include/uapi/@ &&
6612*4882a593Smuzhiyun		    $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
6613*4882a593Smuzhiyun			my $ull = "";
6614*4882a593Smuzhiyun			$ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
6615*4882a593Smuzhiyun			if (CHK("BIT_MACRO",
6616*4882a593Smuzhiyun				"Prefer using the BIT$ull macro\n" . $herecurr) &&
6617*4882a593Smuzhiyun			    $fix) {
6618*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/;
6619*4882a593Smuzhiyun			}
6620*4882a593Smuzhiyun		}
6621*4882a593Smuzhiyun
6622*4882a593Smuzhiyun# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
6623*4882a593Smuzhiyun		if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) {
6624*4882a593Smuzhiyun			WARN("IS_ENABLED_CONFIG",
6625*4882a593Smuzhiyun			     "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr);
6626*4882a593Smuzhiyun		}
6627*4882a593Smuzhiyun
6628*4882a593Smuzhiyun# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
6629*4882a593Smuzhiyun		if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
6630*4882a593Smuzhiyun			my $config = $1;
6631*4882a593Smuzhiyun			if (WARN("PREFER_IS_ENABLED",
6632*4882a593Smuzhiyun				 "Prefer IS_ENABLED(<FOO>) to ${CONFIG_}<FOO> || ${CONFIG_}<FOO>_MODULE\n" . $herecurr) &&
6633*4882a593Smuzhiyun			    $fix) {
6634*4882a593Smuzhiyun				$fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
6635*4882a593Smuzhiyun			}
6636*4882a593Smuzhiyun		}
6637*4882a593Smuzhiyun
6638*4882a593Smuzhiyun# check for /* fallthrough */ like comment, prefer fallthrough;
6639*4882a593Smuzhiyun		my @fallthroughs = (
6640*4882a593Smuzhiyun			'fallthrough',
6641*4882a593Smuzhiyun			'@fallthrough@',
6642*4882a593Smuzhiyun			'lint -fallthrough[ \t]*',
6643*4882a593Smuzhiyun			'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',
6644*4882a593Smuzhiyun			'(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',
6645*4882a593Smuzhiyun			'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
6646*4882a593Smuzhiyun			'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
6647*4882a593Smuzhiyun		    );
6648*4882a593Smuzhiyun		if ($raw_comment ne '') {
6649*4882a593Smuzhiyun			foreach my $ft (@fallthroughs) {
6650*4882a593Smuzhiyun				if ($raw_comment =~ /$ft/) {
6651*4882a593Smuzhiyun					my $msg_level = \&WARN;
6652*4882a593Smuzhiyun					$msg_level = \&CHK if ($file);
6653*4882a593Smuzhiyun					&{$msg_level}("PREFER_FALLTHROUGH",
6654*4882a593Smuzhiyun						      "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr);
6655*4882a593Smuzhiyun					last;
6656*4882a593Smuzhiyun				}
6657*4882a593Smuzhiyun			}
6658*4882a593Smuzhiyun		}
6659*4882a593Smuzhiyun
6660*4882a593Smuzhiyun# check for switch/default statements without a break;
6661*4882a593Smuzhiyun		if ($perl_version_ok &&
6662*4882a593Smuzhiyun		    defined $stat &&
6663*4882a593Smuzhiyun		    $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
6664*4882a593Smuzhiyun			my $cnt = statement_rawlines($stat);
6665*4882a593Smuzhiyun			my $herectx = get_stat_here($linenr, $cnt, $here);
6666*4882a593Smuzhiyun
6667*4882a593Smuzhiyun			WARN("DEFAULT_NO_BREAK",
6668*4882a593Smuzhiyun			     "switch default: should use break\n" . $herectx);
6669*4882a593Smuzhiyun		}
6670*4882a593Smuzhiyun
6671*4882a593Smuzhiyun# check for gcc specific __FUNCTION__
6672*4882a593Smuzhiyun		if ($line =~ /\b__FUNCTION__\b/) {
6673*4882a593Smuzhiyun			if (WARN("USE_FUNC",
6674*4882a593Smuzhiyun				 "__func__ should be used instead of gcc specific __FUNCTION__\n"  . $herecurr) &&
6675*4882a593Smuzhiyun			    $fix) {
6676*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
6677*4882a593Smuzhiyun			}
6678*4882a593Smuzhiyun		}
6679*4882a593Smuzhiyun
6680*4882a593Smuzhiyun# check for uses of __DATE__, __TIME__, __TIMESTAMP__
6681*4882a593Smuzhiyun		while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) {
6682*4882a593Smuzhiyun			ERROR("DATE_TIME",
6683*4882a593Smuzhiyun			      "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr);
6684*4882a593Smuzhiyun		}
6685*4882a593Smuzhiyun
6686*4882a593Smuzhiyun# check for use of yield()
6687*4882a593Smuzhiyun		if ($line =~ /\byield\s*\(\s*\)/) {
6688*4882a593Smuzhiyun			WARN("YIELD",
6689*4882a593Smuzhiyun			     "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n"  . $herecurr);
6690*4882a593Smuzhiyun		}
6691*4882a593Smuzhiyun
6692*4882a593Smuzhiyun# check for comparisons against true and false
6693*4882a593Smuzhiyun		if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {
6694*4882a593Smuzhiyun			my $lead = $1;
6695*4882a593Smuzhiyun			my $arg = $2;
6696*4882a593Smuzhiyun			my $test = $3;
6697*4882a593Smuzhiyun			my $otype = $4;
6698*4882a593Smuzhiyun			my $trail = $5;
6699*4882a593Smuzhiyun			my $op = "!";
6700*4882a593Smuzhiyun
6701*4882a593Smuzhiyun			($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i);
6702*4882a593Smuzhiyun
6703*4882a593Smuzhiyun			my $type = lc($otype);
6704*4882a593Smuzhiyun			if ($type =~ /^(?:true|false)$/) {
6705*4882a593Smuzhiyun				if (("$test" eq "==" && "$type" eq "true") ||
6706*4882a593Smuzhiyun				    ("$test" eq "!=" && "$type" eq "false")) {
6707*4882a593Smuzhiyun					$op = "";
6708*4882a593Smuzhiyun				}
6709*4882a593Smuzhiyun
6710*4882a593Smuzhiyun				CHK("BOOL_COMPARISON",
6711*4882a593Smuzhiyun				    "Using comparison to $otype is error prone\n" . $herecurr);
6712*4882a593Smuzhiyun
6713*4882a593Smuzhiyun## maybe suggesting a correct construct would better
6714*4882a593Smuzhiyun##				    "Using comparison to $otype is error prone.  Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr);
6715*4882a593Smuzhiyun
6716*4882a593Smuzhiyun			}
6717*4882a593Smuzhiyun		}
6718*4882a593Smuzhiyun
6719*4882a593Smuzhiyun# check for semaphores initialized locked
6720*4882a593Smuzhiyun		if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
6721*4882a593Smuzhiyun			WARN("CONSIDER_COMPLETION",
6722*4882a593Smuzhiyun			     "consider using a completion\n" . $herecurr);
6723*4882a593Smuzhiyun		}
6724*4882a593Smuzhiyun
6725*4882a593Smuzhiyun# recommend kstrto* over simple_strto* and strict_strto*
6726*4882a593Smuzhiyun		if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
6727*4882a593Smuzhiyun			WARN("CONSIDER_KSTRTO",
6728*4882a593Smuzhiyun			     "$1 is obsolete, use k$3 instead\n" . $herecurr);
6729*4882a593Smuzhiyun		}
6730*4882a593Smuzhiyun
6731*4882a593Smuzhiyun# check for __initcall(), use device_initcall() explicitly or more appropriate function please
6732*4882a593Smuzhiyun		if ($line =~ /^.\s*__initcall\s*\(/) {
6733*4882a593Smuzhiyun			WARN("USE_DEVICE_INITCALL",
6734*4882a593Smuzhiyun			     "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
6735*4882a593Smuzhiyun		}
6736*4882a593Smuzhiyun
6737*4882a593Smuzhiyun# check for spin_is_locked(), suggest lockdep instead
6738*4882a593Smuzhiyun		if ($line =~ /\bspin_is_locked\(/) {
6739*4882a593Smuzhiyun			WARN("USE_LOCKDEP",
6740*4882a593Smuzhiyun			     "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
6741*4882a593Smuzhiyun		}
6742*4882a593Smuzhiyun
6743*4882a593Smuzhiyun# check for deprecated apis
6744*4882a593Smuzhiyun		if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
6745*4882a593Smuzhiyun			my $deprecated_api = $1;
6746*4882a593Smuzhiyun			my $new_api = $deprecated_apis{$deprecated_api};
6747*4882a593Smuzhiyun			WARN("DEPRECATED_API",
6748*4882a593Smuzhiyun			     "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
6749*4882a593Smuzhiyun		}
6750*4882a593Smuzhiyun
6751*4882a593Smuzhiyun# check for various structs that are normally const (ops, kgdb, device_tree)
6752*4882a593Smuzhiyun# and avoid what seem like struct definitions 'struct foo {'
6753*4882a593Smuzhiyun		if (defined($const_structs) &&
6754*4882a593Smuzhiyun		    $line !~ /\bconst\b/ &&
6755*4882a593Smuzhiyun		    $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
6756*4882a593Smuzhiyun			WARN("CONST_STRUCT",
6757*4882a593Smuzhiyun			     "struct $1 should normally be const\n" . $herecurr);
6758*4882a593Smuzhiyun		}
6759*4882a593Smuzhiyun
6760*4882a593Smuzhiyun# use of NR_CPUS is usually wrong
6761*4882a593Smuzhiyun# ignore definitions of NR_CPUS and usage to define arrays as likely right
6762*4882a593Smuzhiyun		if ($line =~ /\bNR_CPUS\b/ &&
6763*4882a593Smuzhiyun		    $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
6764*4882a593Smuzhiyun		    $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
6765*4882a593Smuzhiyun		    $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
6766*4882a593Smuzhiyun		    $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
6767*4882a593Smuzhiyun		    $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
6768*4882a593Smuzhiyun		{
6769*4882a593Smuzhiyun			WARN("NR_CPUS",
6770*4882a593Smuzhiyun			     "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
6771*4882a593Smuzhiyun		}
6772*4882a593Smuzhiyun
6773*4882a593Smuzhiyun# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
6774*4882a593Smuzhiyun		if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
6775*4882a593Smuzhiyun			ERROR("DEFINE_ARCH_HAS",
6776*4882a593Smuzhiyun			      "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
6777*4882a593Smuzhiyun		}
6778*4882a593Smuzhiyun
6779*4882a593Smuzhiyun# likely/unlikely comparisons similar to "(likely(foo) > 0)"
6780*4882a593Smuzhiyun		if ($perl_version_ok &&
6781*4882a593Smuzhiyun		    $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
6782*4882a593Smuzhiyun			WARN("LIKELY_MISUSE",
6783*4882a593Smuzhiyun			     "Using $1 should generally have parentheses around the comparison\n" . $herecurr);
6784*4882a593Smuzhiyun		}
6785*4882a593Smuzhiyun
6786*4882a593Smuzhiyun# nested likely/unlikely calls
6787*4882a593Smuzhiyun		if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
6788*4882a593Smuzhiyun			WARN("LIKELY_MISUSE",
6789*4882a593Smuzhiyun			     "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
6790*4882a593Smuzhiyun		}
6791*4882a593Smuzhiyun
6792*4882a593Smuzhiyun# whine mightly about in_atomic
6793*4882a593Smuzhiyun		if ($line =~ /\bin_atomic\s*\(/) {
6794*4882a593Smuzhiyun			if ($realfile =~ m@^drivers/@) {
6795*4882a593Smuzhiyun				ERROR("IN_ATOMIC",
6796*4882a593Smuzhiyun				      "do not use in_atomic in drivers\n" . $herecurr);
6797*4882a593Smuzhiyun			} elsif ($realfile !~ m@^kernel/@) {
6798*4882a593Smuzhiyun				WARN("IN_ATOMIC",
6799*4882a593Smuzhiyun				     "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
6800*4882a593Smuzhiyun			}
6801*4882a593Smuzhiyun		}
6802*4882a593Smuzhiyun
6803*4882a593Smuzhiyun# check for mutex_trylock_recursive usage
6804*4882a593Smuzhiyun		if ($line =~ /mutex_trylock_recursive/) {
6805*4882a593Smuzhiyun			ERROR("LOCKING",
6806*4882a593Smuzhiyun			      "recursive locking is bad, do not use this ever.\n" . $herecurr);
6807*4882a593Smuzhiyun		}
6808*4882a593Smuzhiyun
6809*4882a593Smuzhiyun# check for lockdep_set_novalidate_class
6810*4882a593Smuzhiyun		if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
6811*4882a593Smuzhiyun		    $line =~ /__lockdep_no_validate__\s*\)/ ) {
6812*4882a593Smuzhiyun			if ($realfile !~ m@^kernel/lockdep@ &&
6813*4882a593Smuzhiyun			    $realfile !~ m@^include/linux/lockdep@ &&
6814*4882a593Smuzhiyun			    $realfile !~ m@^drivers/base/core@) {
6815*4882a593Smuzhiyun				ERROR("LOCKDEP",
6816*4882a593Smuzhiyun				      "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
6817*4882a593Smuzhiyun			}
6818*4882a593Smuzhiyun		}
6819*4882a593Smuzhiyun
6820*4882a593Smuzhiyun		if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ ||
6821*4882a593Smuzhiyun		    $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) {
6822*4882a593Smuzhiyun			WARN("EXPORTED_WORLD_WRITABLE",
6823*4882a593Smuzhiyun			     "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
6824*4882a593Smuzhiyun		}
6825*4882a593Smuzhiyun
6826*4882a593Smuzhiyun# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
6827*4882a593Smuzhiyun# and whether or not function naming is typical and if
6828*4882a593Smuzhiyun# DEVICE_ATTR permissions uses are unusual too
6829*4882a593Smuzhiyun		if ($perl_version_ok &&
6830*4882a593Smuzhiyun		    defined $stat &&
6831*4882a593Smuzhiyun		    $stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
6832*4882a593Smuzhiyun			my $var = $1;
6833*4882a593Smuzhiyun			my $perms = $2;
6834*4882a593Smuzhiyun			my $show = $3;
6835*4882a593Smuzhiyun			my $store = $4;
6836*4882a593Smuzhiyun			my $octal_perms = perms_to_octal($perms);
6837*4882a593Smuzhiyun			if ($show =~ /^${var}_show$/ &&
6838*4882a593Smuzhiyun			    $store =~ /^${var}_store$/ &&
6839*4882a593Smuzhiyun			    $octal_perms eq "0644") {
6840*4882a593Smuzhiyun				if (WARN("DEVICE_ATTR_RW",
6841*4882a593Smuzhiyun					 "Use DEVICE_ATTR_RW\n" . $herecurr) &&
6842*4882a593Smuzhiyun				    $fix) {
6843*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
6844*4882a593Smuzhiyun				}
6845*4882a593Smuzhiyun			} elsif ($show =~ /^${var}_show$/ &&
6846*4882a593Smuzhiyun				 $store =~ /^NULL$/ &&
6847*4882a593Smuzhiyun				 $octal_perms eq "0444") {
6848*4882a593Smuzhiyun				if (WARN("DEVICE_ATTR_RO",
6849*4882a593Smuzhiyun					 "Use DEVICE_ATTR_RO\n" . $herecurr) &&
6850*4882a593Smuzhiyun				    $fix) {
6851*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
6852*4882a593Smuzhiyun				}
6853*4882a593Smuzhiyun			} elsif ($show =~ /^NULL$/ &&
6854*4882a593Smuzhiyun				 $store =~ /^${var}_store$/ &&
6855*4882a593Smuzhiyun				 $octal_perms eq "0200") {
6856*4882a593Smuzhiyun				if (WARN("DEVICE_ATTR_WO",
6857*4882a593Smuzhiyun					 "Use DEVICE_ATTR_WO\n" . $herecurr) &&
6858*4882a593Smuzhiyun				    $fix) {
6859*4882a593Smuzhiyun					$fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
6860*4882a593Smuzhiyun				}
6861*4882a593Smuzhiyun			} elsif ($octal_perms eq "0644" ||
6862*4882a593Smuzhiyun				 $octal_perms eq "0444" ||
6863*4882a593Smuzhiyun				 $octal_perms eq "0200") {
6864*4882a593Smuzhiyun				my $newshow = "$show";
6865*4882a593Smuzhiyun				$newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
6866*4882a593Smuzhiyun				my $newstore = $store;
6867*4882a593Smuzhiyun				$newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
6868*4882a593Smuzhiyun				my $rename = "";
6869*4882a593Smuzhiyun				if ($show ne $newshow) {
6870*4882a593Smuzhiyun					$rename .= " '$show' to '$newshow'";
6871*4882a593Smuzhiyun				}
6872*4882a593Smuzhiyun				if ($store ne $newstore) {
6873*4882a593Smuzhiyun					$rename .= " '$store' to '$newstore'";
6874*4882a593Smuzhiyun				}
6875*4882a593Smuzhiyun				WARN("DEVICE_ATTR_FUNCTIONS",
6876*4882a593Smuzhiyun				     "Consider renaming function(s)$rename\n" . $herecurr);
6877*4882a593Smuzhiyun			} else {
6878*4882a593Smuzhiyun				WARN("DEVICE_ATTR_PERMS",
6879*4882a593Smuzhiyun				     "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr);
6880*4882a593Smuzhiyun			}
6881*4882a593Smuzhiyun		}
6882*4882a593Smuzhiyun
6883*4882a593Smuzhiyun# Mode permission misuses where it seems decimal should be octal
6884*4882a593Smuzhiyun# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
6885*4882a593Smuzhiyun# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
6886*4882a593Smuzhiyun#   specific definition of not visible in sysfs.
6887*4882a593Smuzhiyun# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
6888*4882a593Smuzhiyun#   use the default permissions
6889*4882a593Smuzhiyun		if ($perl_version_ok &&
6890*4882a593Smuzhiyun		    defined $stat &&
6891*4882a593Smuzhiyun		    $line =~ /$mode_perms_search/) {
6892*4882a593Smuzhiyun			foreach my $entry (@mode_permission_funcs) {
6893*4882a593Smuzhiyun				my $func = $entry->[0];
6894*4882a593Smuzhiyun				my $arg_pos = $entry->[1];
6895*4882a593Smuzhiyun
6896*4882a593Smuzhiyun				my $lc = $stat =~ tr@\n@@;
6897*4882a593Smuzhiyun				$lc = $lc + $linenr;
6898*4882a593Smuzhiyun				my $stat_real = get_stat_real($linenr, $lc);
6899*4882a593Smuzhiyun
6900*4882a593Smuzhiyun				my $skip_args = "";
6901*4882a593Smuzhiyun				if ($arg_pos > 1) {
6902*4882a593Smuzhiyun					$arg_pos--;
6903*4882a593Smuzhiyun					$skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
6904*4882a593Smuzhiyun				}
6905*4882a593Smuzhiyun				my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
6906*4882a593Smuzhiyun				if ($stat =~ /$test/) {
6907*4882a593Smuzhiyun					my $val = $1;
6908*4882a593Smuzhiyun					$val = $6 if ($skip_args ne "");
6909*4882a593Smuzhiyun					if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
6910*4882a593Smuzhiyun					    (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
6911*4882a593Smuzhiyun					     ($val =~ /^$Octal$/ && length($val) ne 4))) {
6912*4882a593Smuzhiyun						ERROR("NON_OCTAL_PERMISSIONS",
6913*4882a593Smuzhiyun						      "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
6914*4882a593Smuzhiyun					}
6915*4882a593Smuzhiyun					if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
6916*4882a593Smuzhiyun						ERROR("EXPORTED_WORLD_WRITABLE",
6917*4882a593Smuzhiyun						      "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
6918*4882a593Smuzhiyun					}
6919*4882a593Smuzhiyun				}
6920*4882a593Smuzhiyun			}
6921*4882a593Smuzhiyun		}
6922*4882a593Smuzhiyun
6923*4882a593Smuzhiyun# check for uses of S_<PERMS> that could be octal for readability
6924*4882a593Smuzhiyun		while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
6925*4882a593Smuzhiyun			my $oval = $1;
6926*4882a593Smuzhiyun			my $octal = perms_to_octal($oval);
6927*4882a593Smuzhiyun			if (WARN("SYMBOLIC_PERMS",
6928*4882a593Smuzhiyun				 "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
6929*4882a593Smuzhiyun			    $fix) {
6930*4882a593Smuzhiyun				$fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
6931*4882a593Smuzhiyun			}
6932*4882a593Smuzhiyun		}
6933*4882a593Smuzhiyun
6934*4882a593Smuzhiyun# validate content of MODULE_LICENSE against list from include/linux/module.h
6935*4882a593Smuzhiyun		if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
6936*4882a593Smuzhiyun			my $extracted_string = get_quoted_string($line, $rawline);
6937*4882a593Smuzhiyun			my $valid_licenses = qr{
6938*4882a593Smuzhiyun						GPL|
6939*4882a593Smuzhiyun						GPL\ v2|
6940*4882a593Smuzhiyun						GPL\ and\ additional\ rights|
6941*4882a593Smuzhiyun						Dual\ BSD/GPL|
6942*4882a593Smuzhiyun						Dual\ MIT/GPL|
6943*4882a593Smuzhiyun						Dual\ MPL/GPL|
6944*4882a593Smuzhiyun						Proprietary
6945*4882a593Smuzhiyun					}x;
6946*4882a593Smuzhiyun			if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) {
6947*4882a593Smuzhiyun				WARN("MODULE_LICENSE",
6948*4882a593Smuzhiyun				     "unknown module license " . $extracted_string . "\n" . $herecurr);
6949*4882a593Smuzhiyun			}
6950*4882a593Smuzhiyun		}
6951*4882a593Smuzhiyun
6952*4882a593Smuzhiyun# check for sysctl duplicate constants
6953*4882a593Smuzhiyun		if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
6954*4882a593Smuzhiyun			WARN("DUPLICATED_SYSCTL_CONST",
6955*4882a593Smuzhiyun				"duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
6956*4882a593Smuzhiyun		}
6957*4882a593Smuzhiyun	}
6958*4882a593Smuzhiyun
6959*4882a593Smuzhiyun	# If we have no input at all, then there is nothing to report on
6960*4882a593Smuzhiyun	# so just keep quiet.
6961*4882a593Smuzhiyun	if ($#rawlines == -1) {
6962*4882a593Smuzhiyun		exit(0);
6963*4882a593Smuzhiyun	}
6964*4882a593Smuzhiyun
6965*4882a593Smuzhiyun	# In mailback mode only produce a report in the negative, for
6966*4882a593Smuzhiyun	# things that appear to be patches.
6967*4882a593Smuzhiyun	if ($mailback && ($clean == 1 || !$is_patch)) {
6968*4882a593Smuzhiyun		exit(0);
6969*4882a593Smuzhiyun	}
6970*4882a593Smuzhiyun
6971*4882a593Smuzhiyun	# This is not a patch, and we are are in 'no-patch' mode so
6972*4882a593Smuzhiyun	# just keep quiet.
6973*4882a593Smuzhiyun	if (!$chk_patch && !$is_patch) {
6974*4882a593Smuzhiyun		exit(0);
6975*4882a593Smuzhiyun	}
6976*4882a593Smuzhiyun
6977*4882a593Smuzhiyun	if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
6978*4882a593Smuzhiyun		ERROR("NOT_UNIFIED_DIFF",
6979*4882a593Smuzhiyun		      "Does not appear to be a unified-diff format patch\n");
6980*4882a593Smuzhiyun	}
6981*4882a593Smuzhiyun	if ($is_patch && $has_commit_log && $chk_signoff) {
6982*4882a593Smuzhiyun		if ($signoff == 0) {
6983*4882a593Smuzhiyun			ERROR("MISSING_SIGN_OFF",
6984*4882a593Smuzhiyun			      "Missing Signed-off-by: line(s)\n");
6985*4882a593Smuzhiyun		} elsif ($authorsignoff != 1) {
6986*4882a593Smuzhiyun			# authorsignoff values:
6987*4882a593Smuzhiyun			# 0 -> missing sign off
6988*4882a593Smuzhiyun			# 1 -> sign off identical
6989*4882a593Smuzhiyun			# 2 -> names and addresses match, comments mismatch
6990*4882a593Smuzhiyun			# 3 -> addresses match, names different
6991*4882a593Smuzhiyun			# 4 -> names match, addresses different
6992*4882a593Smuzhiyun			# 5 -> names match, addresses excluding subaddress details (refer RFC 5233) match
6993*4882a593Smuzhiyun
6994*4882a593Smuzhiyun			my $sob_msg = "'From: $author' != 'Signed-off-by: $author_sob'";
6995*4882a593Smuzhiyun
6996*4882a593Smuzhiyun			if ($authorsignoff == 0) {
6997*4882a593Smuzhiyun				ERROR("NO_AUTHOR_SIGN_OFF",
6998*4882a593Smuzhiyun				      "Missing Signed-off-by: line by nominal patch author '$author'\n");
6999*4882a593Smuzhiyun			} elsif ($authorsignoff == 2) {
7000*4882a593Smuzhiyun				CHK("FROM_SIGN_OFF_MISMATCH",
7001*4882a593Smuzhiyun				    "From:/Signed-off-by: email comments mismatch: $sob_msg\n");
7002*4882a593Smuzhiyun			} elsif ($authorsignoff == 3) {
7003*4882a593Smuzhiyun				WARN("FROM_SIGN_OFF_MISMATCH",
7004*4882a593Smuzhiyun				     "From:/Signed-off-by: email name mismatch: $sob_msg\n");
7005*4882a593Smuzhiyun			} elsif ($authorsignoff == 4) {
7006*4882a593Smuzhiyun				WARN("FROM_SIGN_OFF_MISMATCH",
7007*4882a593Smuzhiyun				     "From:/Signed-off-by: email address mismatch: $sob_msg\n");
7008*4882a593Smuzhiyun			} elsif ($authorsignoff == 5) {
7009*4882a593Smuzhiyun				WARN("FROM_SIGN_OFF_MISMATCH",
7010*4882a593Smuzhiyun				     "From:/Signed-off-by: email subaddress mismatch: $sob_msg\n");
7011*4882a593Smuzhiyun			}
7012*4882a593Smuzhiyun		}
7013*4882a593Smuzhiyun	}
7014*4882a593Smuzhiyun
7015*4882a593Smuzhiyun	print report_dump();
7016*4882a593Smuzhiyun	if ($summary && !($clean == 1 && $quiet == 1)) {
7017*4882a593Smuzhiyun		print "$filename " if ($summary_file);
7018*4882a593Smuzhiyun		print "total: $cnt_error errors, $cnt_warn warnings, " .
7019*4882a593Smuzhiyun			(($check)? "$cnt_chk checks, " : "") .
7020*4882a593Smuzhiyun			"$cnt_lines lines checked\n";
7021*4882a593Smuzhiyun	}
7022*4882a593Smuzhiyun
7023*4882a593Smuzhiyun	if ($quiet == 0) {
7024*4882a593Smuzhiyun		# If there were any defects found and not already fixing them
7025*4882a593Smuzhiyun		if (!$clean and !$fix) {
7026*4882a593Smuzhiyun			print << "EOM"
7027*4882a593Smuzhiyun
7028*4882a593SmuzhiyunNOTE: For some of the reported defects, checkpatch may be able to
7029*4882a593Smuzhiyun      mechanically convert to the typical style using --fix or --fix-inplace.
7030*4882a593SmuzhiyunEOM
7031*4882a593Smuzhiyun		}
7032*4882a593Smuzhiyun		# If there were whitespace errors which cleanpatch can fix
7033*4882a593Smuzhiyun		# then suggest that.
7034*4882a593Smuzhiyun		if ($rpt_cleaners) {
7035*4882a593Smuzhiyun			$rpt_cleaners = 0;
7036*4882a593Smuzhiyun			print << "EOM"
7037*4882a593Smuzhiyun
7038*4882a593SmuzhiyunNOTE: Whitespace errors detected.
7039*4882a593Smuzhiyun      You may wish to use scripts/cleanpatch or scripts/cleanfile
7040*4882a593SmuzhiyunEOM
7041*4882a593Smuzhiyun		}
7042*4882a593Smuzhiyun	}
7043*4882a593Smuzhiyun
7044*4882a593Smuzhiyun	if ($clean == 0 && $fix &&
7045*4882a593Smuzhiyun	    ("@rawlines" ne "@fixed" ||
7046*4882a593Smuzhiyun	     $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
7047*4882a593Smuzhiyun		my $newfile = $filename;
7048*4882a593Smuzhiyun		$newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
7049*4882a593Smuzhiyun		my $linecount = 0;
7050*4882a593Smuzhiyun		my $f;
7051*4882a593Smuzhiyun
7052*4882a593Smuzhiyun		@fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
7053*4882a593Smuzhiyun
7054*4882a593Smuzhiyun		open($f, '>', $newfile)
7055*4882a593Smuzhiyun		    or die "$P: Can't open $newfile for write\n";
7056*4882a593Smuzhiyun		foreach my $fixed_line (@fixed) {
7057*4882a593Smuzhiyun			$linecount++;
7058*4882a593Smuzhiyun			if ($file) {
7059*4882a593Smuzhiyun				if ($linecount > 3) {
7060*4882a593Smuzhiyun					$fixed_line =~ s/^\+//;
7061*4882a593Smuzhiyun					print $f $fixed_line . "\n";
7062*4882a593Smuzhiyun				}
7063*4882a593Smuzhiyun			} else {
7064*4882a593Smuzhiyun				print $f $fixed_line . "\n";
7065*4882a593Smuzhiyun			}
7066*4882a593Smuzhiyun		}
7067*4882a593Smuzhiyun		close($f);
7068*4882a593Smuzhiyun
7069*4882a593Smuzhiyun		if (!$quiet) {
7070*4882a593Smuzhiyun			print << "EOM";
7071*4882a593Smuzhiyun
7072*4882a593SmuzhiyunWrote EXPERIMENTAL --fix correction(s) to '$newfile'
7073*4882a593Smuzhiyun
7074*4882a593SmuzhiyunDo _NOT_ trust the results written to this file.
7075*4882a593SmuzhiyunDo _NOT_ submit these changes without inspecting them for correctness.
7076*4882a593Smuzhiyun
7077*4882a593SmuzhiyunThis EXPERIMENTAL file is simply a convenience to help rewrite patches.
7078*4882a593SmuzhiyunNo warranties, expressed or implied...
7079*4882a593SmuzhiyunEOM
7080*4882a593Smuzhiyun		}
7081*4882a593Smuzhiyun	}
7082*4882a593Smuzhiyun
7083*4882a593Smuzhiyun	if ($quiet == 0) {
7084*4882a593Smuzhiyun		print "\n";
7085*4882a593Smuzhiyun		if ($clean == 1) {
7086*4882a593Smuzhiyun			print "$vname has no obvious style problems and is ready for submission.\n";
7087*4882a593Smuzhiyun		} else {
7088*4882a593Smuzhiyun			print "$vname has style problems, please review.\n";
7089*4882a593Smuzhiyun		}
7090*4882a593Smuzhiyun	}
7091*4882a593Smuzhiyun	return $clean;
7092*4882a593Smuzhiyun}
7093