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