xref: /linux-6.15/scripts/checkpatch.pl (revision c2fdda0d)
10a920b5bSAndy Whitcroft#!/usr/bin/perl -w
20a920b5bSAndy Whitcroft# (c) 2001, Dave Jones. <[email protected]> (the file handling bit)
300df344fSAndy Whitcroft# (c) 2005, Joel Schopp <[email protected]> (the ugly bit)
40a920b5bSAndy Whitcroft# (c) 2007, Andy Whitcroft <[email protected]> (new conditions, test suite, etc)
50a920b5bSAndy Whitcroft# Licensed under the terms of the GNU GPL License version 2
60a920b5bSAndy Whitcroft
70a920b5bSAndy Whitcroftuse strict;
80a920b5bSAndy Whitcroft
90a920b5bSAndy Whitcroftmy $P = $0;
1000df344fSAndy Whitcroft$P =~ s@.*/@@g;
110a920b5bSAndy Whitcroft
12*c2fdda0dSAndy Whitcroftmy $V = '0.13';
130a920b5bSAndy Whitcroft
140a920b5bSAndy Whitcroftuse Getopt::Long qw(:config no_auto_abbrev);
150a920b5bSAndy Whitcroft
160a920b5bSAndy Whitcroftmy $quiet = 0;
170a920b5bSAndy Whitcroftmy $tree = 1;
180a920b5bSAndy Whitcroftmy $chk_signoff = 1;
190a920b5bSAndy Whitcroftmy $chk_patch = 1;
20653d4876SAndy Whitcroftmy $tst_type = 0;
216c72ffaaSAndy Whitcroftmy $emacs = 0;
228905a67cSAndy Whitcroftmy $terse = 0;
236c72ffaaSAndy Whitcroftmy $file = 0;
246c72ffaaSAndy Whitcroftmy $check = 0;
258905a67cSAndy Whitcroftmy $summary = 1;
268905a67cSAndy Whitcroftmy $mailback = 0;
276c72ffaaSAndy Whitcroftmy $root;
28*c2fdda0dSAndy Whitcroftmy %debug;
290a920b5bSAndy WhitcroftGetOptions(
306c72ffaaSAndy Whitcroft	'q|quiet+'	=> \$quiet,
310a920b5bSAndy Whitcroft	'tree!'		=> \$tree,
320a920b5bSAndy Whitcroft	'signoff!'	=> \$chk_signoff,
330a920b5bSAndy Whitcroft	'patch!'	=> \$chk_patch,
34653d4876SAndy Whitcroft	'test-type!'	=> \$tst_type,
356c72ffaaSAndy Whitcroft	'emacs!'	=> \$emacs,
368905a67cSAndy Whitcroft	'terse!'	=> \$terse,
376c72ffaaSAndy Whitcroft	'file!'		=> \$file,
386c72ffaaSAndy Whitcroft	'subjective!'	=> \$check,
396c72ffaaSAndy Whitcroft	'strict!'	=> \$check,
406c72ffaaSAndy Whitcroft	'root=s'	=> \$root,
418905a67cSAndy Whitcroft	'summary!'	=> \$summary,
428905a67cSAndy Whitcroft	'mailback!'	=> \$mailback,
43*c2fdda0dSAndy Whitcroft	'debug=s'	=> \%debug,
440a920b5bSAndy Whitcroft) or exit;
450a920b5bSAndy Whitcroft
460a920b5bSAndy Whitcroftmy $exit = 0;
470a920b5bSAndy Whitcroft
480a920b5bSAndy Whitcroftif ($#ARGV < 0) {
4900df344fSAndy Whitcroft	print "usage: $P [options] patchfile\n";
500a920b5bSAndy Whitcroft	print "version: $V\n";
510a920b5bSAndy Whitcroft	print "options: -q           => quiet\n";
520a920b5bSAndy Whitcroft	print "         --no-tree    => run without a kernel tree\n";
538905a67cSAndy Whitcroft	print "         --terse      => one line per report\n";
546c72ffaaSAndy Whitcroft	print "         --emacs      => emacs compile window format\n";
556c72ffaaSAndy Whitcroft	print "         --file       => check a source file\n";
566c72ffaaSAndy Whitcroft	print "         --strict     => enable more subjective tests\n";
576c72ffaaSAndy Whitcroft	print "         --root       => path to the kernel tree root\n";
580a920b5bSAndy Whitcroft	exit(1);
590a920b5bSAndy Whitcroft}
600a920b5bSAndy Whitcroft
61*c2fdda0dSAndy Whitcroftmy $dbg_values = 0;
62*c2fdda0dSAndy Whitcroftmy $dbg_possible = 0;
63*c2fdda0dSAndy Whitcroftfor my $key (keys %debug) {
64*c2fdda0dSAndy Whitcroft	eval "\${dbg_$key} = '$debug{$key}';"
65*c2fdda0dSAndy Whitcroft}
66*c2fdda0dSAndy Whitcroft
678905a67cSAndy Whitcroftif ($terse) {
688905a67cSAndy Whitcroft	$emacs = 1;
698905a67cSAndy Whitcroft	$quiet++;
708905a67cSAndy Whitcroft}
718905a67cSAndy Whitcroft
726c72ffaaSAndy Whitcroftif ($tree) {
736c72ffaaSAndy Whitcroft	if (defined $root) {
746c72ffaaSAndy Whitcroft		if (!top_of_kernel_tree($root)) {
756c72ffaaSAndy Whitcroft			die "$P: $root: --root does not point at a valid tree\n";
766c72ffaaSAndy Whitcroft		}
776c72ffaaSAndy Whitcroft	} else {
786c72ffaaSAndy Whitcroft		if (top_of_kernel_tree('.')) {
796c72ffaaSAndy Whitcroft			$root = '.';
806c72ffaaSAndy Whitcroft		} elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
816c72ffaaSAndy Whitcroft						top_of_kernel_tree($1)) {
826c72ffaaSAndy Whitcroft			$root = $1;
836c72ffaaSAndy Whitcroft		}
846c72ffaaSAndy Whitcroft	}
856c72ffaaSAndy Whitcroft
866c72ffaaSAndy Whitcroft	if (!defined $root) {
870a920b5bSAndy Whitcroft		print "Must be run from the top-level dir. of a kernel tree\n";
880a920b5bSAndy Whitcroft		exit(2);
890a920b5bSAndy Whitcroft	}
906c72ffaaSAndy Whitcroft}
916c72ffaaSAndy Whitcroft
926c72ffaaSAndy Whitcroftmy $emitted_corrupt = 0;
936c72ffaaSAndy Whitcroft
946c72ffaaSAndy Whitcroftour $Ident       = qr{[A-Za-z_][A-Za-z\d_]*};
956c72ffaaSAndy Whitcroftour $Storage	= qr{extern|static|asmlinkage};
966c72ffaaSAndy Whitcroftour $Sparse	= qr{
976c72ffaaSAndy Whitcroft			__user|
986c72ffaaSAndy Whitcroft			__kernel|
996c72ffaaSAndy Whitcroft			__force|
1006c72ffaaSAndy Whitcroft			__iomem|
1016c72ffaaSAndy Whitcroft			__must_check|
1026c72ffaaSAndy Whitcroft			__init_refok|
1036c72ffaaSAndy Whitcroft			__kprobes|
1046c72ffaaSAndy Whitcroft			fastcall
1056c72ffaaSAndy Whitcroft		}x;
1066c72ffaaSAndy Whitcroftour $Attribute	= qr{
1076c72ffaaSAndy Whitcroft			const|
1086c72ffaaSAndy Whitcroft			__read_mostly|
1096c72ffaaSAndy Whitcroft			__kprobes|
1106c72ffaaSAndy Whitcroft			__(?:mem|cpu|dev|)(?:initdata|init)
1116c72ffaaSAndy Whitcroft		  }x;
1126c72ffaaSAndy Whitcroftour $Inline	= qr{inline|__always_inline|noinline};
1136c72ffaaSAndy Whitcroftour $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};
1146c72ffaaSAndy Whitcroftour $Lval	= qr{$Ident(?:$Member)*};
1156c72ffaaSAndy Whitcroft
1166c72ffaaSAndy Whitcroftour $Constant	= qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
1176c72ffaaSAndy Whitcroftour $Assignment	= qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
1186c72ffaaSAndy Whitcroftour $Operators	= qr{
1196c72ffaaSAndy Whitcroft			<=|>=|==|!=|
1206c72ffaaSAndy Whitcroft			=>|->|<<|>>|<|>|!|~|
121*c2fdda0dSAndy Whitcroft			&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
1226c72ffaaSAndy Whitcroft		  }x;
1236c72ffaaSAndy Whitcroft
1248905a67cSAndy Whitcroftour $NonptrType;
1258905a67cSAndy Whitcroftour $Type;
1268905a67cSAndy Whitcroftour $Declare;
1278905a67cSAndy Whitcroft
1288905a67cSAndy Whitcroftour @typeList = (
1298905a67cSAndy Whitcroft	qr{void},
1308905a67cSAndy Whitcroft	qr{char},
1318905a67cSAndy Whitcroft	qr{short},
1328905a67cSAndy Whitcroft	qr{int},
1338905a67cSAndy Whitcroft	qr{long},
1348905a67cSAndy Whitcroft	qr{unsigned},
1358905a67cSAndy Whitcroft	qr{float},
1368905a67cSAndy Whitcroft	qr{double},
1378905a67cSAndy Whitcroft	qr{bool},
1388905a67cSAndy Whitcroft	qr{long\s+int},
1398905a67cSAndy Whitcroft	qr{long\s+long},
1408905a67cSAndy Whitcroft	qr{long\s+long\s+int},
1418905a67cSAndy Whitcroft	qr{(?:__)?(?:u|s|be|le)(?:8|16|32|64)},
1428905a67cSAndy Whitcroft	qr{struct\s+$Ident},
1438905a67cSAndy Whitcroft	qr{union\s+$Ident},
1448905a67cSAndy Whitcroft	qr{enum\s+$Ident},
1458905a67cSAndy Whitcroft	qr{${Ident}_t},
1468905a67cSAndy Whitcroft	qr{${Ident}_handler},
1478905a67cSAndy Whitcroft	qr{${Ident}_handler_fn},
1488905a67cSAndy Whitcroft);
1498905a67cSAndy Whitcroft
1508905a67cSAndy Whitcroftsub build_types {
1518905a67cSAndy Whitcroft	my $all = "(?:  \n" . join("|\n  ", @typeList) . "\n)";
1528905a67cSAndy Whitcroft	$NonptrType	= qr{
1538905a67cSAndy Whitcroft			\b
1548905a67cSAndy Whitcroft			(?:const\s+)?
1558905a67cSAndy Whitcroft			(?:unsigned\s+)?
1568905a67cSAndy Whitcroft			$all
1578905a67cSAndy Whitcroft			(?:\s+$Sparse|\s+const)*
1588905a67cSAndy Whitcroft			\b
1598905a67cSAndy Whitcroft		  }x;
1608905a67cSAndy Whitcroft	$Type	= qr{
1618905a67cSAndy Whitcroft			\b$NonptrType\b
1628905a67cSAndy Whitcroft			(?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
163*c2fdda0dSAndy Whitcroft			(?:\s+$Inline|\s+$Sparse|\s+$Attribute)*
1648905a67cSAndy Whitcroft		  }x;
1658905a67cSAndy Whitcroft	$Declare	= qr{(?:$Storage\s+)?$Type};
1668905a67cSAndy Whitcroft}
1678905a67cSAndy Whitcroftbuild_types();
1686c72ffaaSAndy Whitcroft
1696c72ffaaSAndy Whitcroft$chk_signoff = 0 if ($file);
1700a920b5bSAndy Whitcroft
1714a0df2efSAndy Whitcroftmy @dep_includes = ();
1724a0df2efSAndy Whitcroftmy @dep_functions = ();
1736c72ffaaSAndy Whitcroftmy $removal = "Documentation/feature-removal-schedule.txt";
1746c72ffaaSAndy Whitcroftif ($tree && -f "$root/$removal") {
1756c72ffaaSAndy Whitcroft	open(REMOVE, "<$root/$removal") ||
1766c72ffaaSAndy Whitcroft				die "$P: $removal: open failed - $!\n";
1770a920b5bSAndy Whitcroft	while (<REMOVE>) {
178f0a594c1SAndy Whitcroft		if (/^Check:\s+(.*\S)/) {
179f0a594c1SAndy Whitcroft			for my $entry (split(/[, ]+/, $1)) {
180f0a594c1SAndy Whitcroft				if ($entry =~ m@include/(.*)@) {
1814a0df2efSAndy Whitcroft					push(@dep_includes, $1);
1824a0df2efSAndy Whitcroft
183f0a594c1SAndy Whitcroft				} elsif ($entry !~ m@/@) {
184f0a594c1SAndy Whitcroft					push(@dep_functions, $entry);
185f0a594c1SAndy Whitcroft				}
1864a0df2efSAndy Whitcroft			}
1870a920b5bSAndy Whitcroft		}
1880a920b5bSAndy Whitcroft	}
1890a920b5bSAndy Whitcroft}
1900a920b5bSAndy Whitcroft
19100df344fSAndy Whitcroftmy @rawlines = ();
192*c2fdda0dSAndy Whitcroftmy @lines = ();
193*c2fdda0dSAndy Whitcroftmy $vname;
1946c72ffaaSAndy Whitcroftfor my $filename (@ARGV) {
1956c72ffaaSAndy Whitcroft	if ($file) {
1966c72ffaaSAndy Whitcroft		open(FILE, "diff -u /dev/null $filename|") ||
1976c72ffaaSAndy Whitcroft			die "$P: $filename: diff failed - $!\n";
1986c72ffaaSAndy Whitcroft	} else {
1996c72ffaaSAndy Whitcroft		open(FILE, "<$filename") ||
2006c72ffaaSAndy Whitcroft			die "$P: $filename: open failed - $!\n";
2016c72ffaaSAndy Whitcroft	}
202*c2fdda0dSAndy Whitcroft	if ($filename eq '-') {
203*c2fdda0dSAndy Whitcroft		$vname = 'Your patch';
204*c2fdda0dSAndy Whitcroft	} else {
205*c2fdda0dSAndy Whitcroft		$vname = $filename;
206*c2fdda0dSAndy Whitcroft	}
2076c72ffaaSAndy Whitcroft	while (<FILE>) {
2080a920b5bSAndy Whitcroft		chomp;
20900df344fSAndy Whitcroft		push(@rawlines, $_);
2106c72ffaaSAndy Whitcroft	}
2116c72ffaaSAndy Whitcroft	close(FILE);
212*c2fdda0dSAndy Whitcroft	if (!process($filename)) {
2130a920b5bSAndy Whitcroft		$exit = 1;
2140a920b5bSAndy Whitcroft	}
21500df344fSAndy Whitcroft	@rawlines = ();
2160a920b5bSAndy Whitcroft}
2170a920b5bSAndy Whitcroft
2180a920b5bSAndy Whitcroftexit($exit);
2190a920b5bSAndy Whitcroft
2200a920b5bSAndy Whitcroftsub top_of_kernel_tree {
2216c72ffaaSAndy Whitcroft	my ($root) = @_;
2226c72ffaaSAndy Whitcroft
2236c72ffaaSAndy Whitcroft	my @tree_check = (
2246c72ffaaSAndy Whitcroft		"COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
2256c72ffaaSAndy Whitcroft		"README", "Documentation", "arch", "include", "drivers",
2266c72ffaaSAndy Whitcroft		"fs", "init", "ipc", "kernel", "lib", "scripts",
2276c72ffaaSAndy Whitcroft	);
2286c72ffaaSAndy Whitcroft
2296c72ffaaSAndy Whitcroft	foreach my $check (@tree_check) {
2306c72ffaaSAndy Whitcroft		if (! -e $root . '/' . $check) {
2310a920b5bSAndy Whitcroft			return 0;
2320a920b5bSAndy Whitcroft		}
2336c72ffaaSAndy Whitcroft	}
2346c72ffaaSAndy Whitcroft	return 1;
2356c72ffaaSAndy Whitcroft}
2360a920b5bSAndy Whitcroft
2370a920b5bSAndy Whitcroftsub expand_tabs {
2380a920b5bSAndy Whitcroft	my ($str) = @_;
2390a920b5bSAndy Whitcroft
2400a920b5bSAndy Whitcroft	my $res = '';
2410a920b5bSAndy Whitcroft	my $n = 0;
2420a920b5bSAndy Whitcroft	for my $c (split(//, $str)) {
2430a920b5bSAndy Whitcroft		if ($c eq "\t") {
2440a920b5bSAndy Whitcroft			$res .= ' ';
2450a920b5bSAndy Whitcroft			$n++;
2460a920b5bSAndy Whitcroft			for (; ($n % 8) != 0; $n++) {
2470a920b5bSAndy Whitcroft				$res .= ' ';
2480a920b5bSAndy Whitcroft			}
2490a920b5bSAndy Whitcroft			next;
2500a920b5bSAndy Whitcroft		}
2510a920b5bSAndy Whitcroft		$res .= $c;
2520a920b5bSAndy Whitcroft		$n++;
2530a920b5bSAndy Whitcroft	}
2540a920b5bSAndy Whitcroft
2550a920b5bSAndy Whitcroft	return $res;
2560a920b5bSAndy Whitcroft}
2576c72ffaaSAndy Whitcroftsub copy_spacing {
2586c72ffaaSAndy Whitcroft	my ($str) = @_;
2596c72ffaaSAndy Whitcroft
2606c72ffaaSAndy Whitcroft	my $res = '';
2616c72ffaaSAndy Whitcroft	for my $c (split(//, $str)) {
2626c72ffaaSAndy Whitcroft		if ($c eq "\t") {
2636c72ffaaSAndy Whitcroft			$res .= $c;
2646c72ffaaSAndy Whitcroft		} else {
2656c72ffaaSAndy Whitcroft			$res .= ' ';
2666c72ffaaSAndy Whitcroft		}
2676c72ffaaSAndy Whitcroft	}
2686c72ffaaSAndy Whitcroft
2696c72ffaaSAndy Whitcroft	return $res;
2706c72ffaaSAndy Whitcroft}
2710a920b5bSAndy Whitcroft
2724a0df2efSAndy Whitcroftsub line_stats {
2734a0df2efSAndy Whitcroft	my ($line) = @_;
2744a0df2efSAndy Whitcroft
2754a0df2efSAndy Whitcroft	# Drop the diff line leader and expand tabs
2764a0df2efSAndy Whitcroft	$line =~ s/^.//;
2774a0df2efSAndy Whitcroft	$line = expand_tabs($line);
2784a0df2efSAndy Whitcroft
2794a0df2efSAndy Whitcroft	# Pick the indent from the front of the line.
2804a0df2efSAndy Whitcroft	my ($white) = ($line =~ /^(\s*)/);
2814a0df2efSAndy Whitcroft
2824a0df2efSAndy Whitcroft	return (length($line), length($white));
2834a0df2efSAndy Whitcroft}
2844a0df2efSAndy Whitcroft
28500df344fSAndy Whitcroftsub sanitise_line {
28600df344fSAndy Whitcroft	my ($line) = @_;
28700df344fSAndy Whitcroft
28800df344fSAndy Whitcroft	my $res = '';
28900df344fSAndy Whitcroft	my $l = '';
29000df344fSAndy Whitcroft
29100df344fSAndy Whitcroft	my $quote = '';
292*c2fdda0dSAndy Whitcroft	my $qlen = 0;
29300df344fSAndy Whitcroft
29400df344fSAndy Whitcroft	foreach my $c (split(//, $line)) {
295*c2fdda0dSAndy Whitcroft		# The second backslash of a pair is not a "quote".
296*c2fdda0dSAndy Whitcroft		if ($l eq "\\" && $c eq "\\") {
297*c2fdda0dSAndy Whitcroft			$c = 'X';
298*c2fdda0dSAndy Whitcroft		}
29900df344fSAndy Whitcroft		if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
30000df344fSAndy Whitcroft			if ($quote eq '') {
30100df344fSAndy Whitcroft				$quote = $c;
30200df344fSAndy Whitcroft				$res .= $c;
30300df344fSAndy Whitcroft				$l = $c;
304*c2fdda0dSAndy Whitcroft				$qlen = 0;
30500df344fSAndy Whitcroft				next;
30600df344fSAndy Whitcroft			} elsif ($quote eq $c) {
30700df344fSAndy Whitcroft				$quote = '';
30800df344fSAndy Whitcroft			}
30900df344fSAndy Whitcroft		}
310*c2fdda0dSAndy Whitcroft		if ($quote eq "'" && $qlen > 1) {
311*c2fdda0dSAndy Whitcroft			$quote = '';
312*c2fdda0dSAndy Whitcroft		}
31300df344fSAndy Whitcroft		if ($quote && $c ne "\t") {
31400df344fSAndy Whitcroft			$res .= "X";
315*c2fdda0dSAndy Whitcroft			$qlen++;
31600df344fSAndy Whitcroft		} else {
31700df344fSAndy Whitcroft			$res .= $c;
31800df344fSAndy Whitcroft		}
31900df344fSAndy Whitcroft
32000df344fSAndy Whitcroft		$l = $c;
32100df344fSAndy Whitcroft	}
32200df344fSAndy Whitcroft
323*c2fdda0dSAndy Whitcroft	# Clear out the comments.
324*c2fdda0dSAndy Whitcroft	while ($res =~ m@(/\*.*?\*/)@) {
325*c2fdda0dSAndy Whitcroft		substr($res, $-[1], $+[1] - $-[1]) = ' ' x ($+[1] - $-[1]);
326*c2fdda0dSAndy Whitcroft	}
327*c2fdda0dSAndy Whitcroft	if ($res =~ m@(/\*.*)@) {
328*c2fdda0dSAndy Whitcroft		substr($res, $-[1], $+[1] - $-[1]) = ' ' x ($+[1] - $-[1]);
329*c2fdda0dSAndy Whitcroft	}
330*c2fdda0dSAndy Whitcroft	if ($res =~ m@^.(.*\*/)@) {
331*c2fdda0dSAndy Whitcroft		substr($res, $-[1], $+[1] - $-[1]) = ' ' x ($+[1] - $-[1]);
332*c2fdda0dSAndy Whitcroft	}
333*c2fdda0dSAndy Whitcroft
334*c2fdda0dSAndy Whitcroft	# The pathname on a #include may be surrounded by '<' and '>'.
335*c2fdda0dSAndy Whitcroft	if ($res =~ /^.#\s*include\s+\<(.*)\>/) {
336*c2fdda0dSAndy Whitcroft		my $clean = 'X' x length($1);
337*c2fdda0dSAndy Whitcroft		$res =~ s@\<.*\>@<$clean>@;
338*c2fdda0dSAndy Whitcroft
339*c2fdda0dSAndy Whitcroft	# The whole of a #error is a string.
340*c2fdda0dSAndy Whitcroft	} elsif ($res =~ /^.#\s*(?:error|warning)\s+(.*)\b/) {
341*c2fdda0dSAndy Whitcroft		my $clean = 'X' x length($1);
342*c2fdda0dSAndy Whitcroft		$res =~ s@(#\s*(?:error|warning)\s+).*@$1$clean@;
343*c2fdda0dSAndy Whitcroft	}
344*c2fdda0dSAndy Whitcroft
34500df344fSAndy Whitcroft	return $res;
34600df344fSAndy Whitcroft}
34700df344fSAndy Whitcroft
3488905a67cSAndy Whitcroftsub ctx_statement_block {
3498905a67cSAndy Whitcroft	my ($linenr, $remain, $off) = @_;
3508905a67cSAndy Whitcroft	my $line = $linenr - 1;
3518905a67cSAndy Whitcroft	my $blk = '';
3528905a67cSAndy Whitcroft	my $soff = $off;
3538905a67cSAndy Whitcroft	my $coff = $off - 1;
3548905a67cSAndy Whitcroft
3558905a67cSAndy Whitcroft	my $type = '';
3568905a67cSAndy Whitcroft	my $level = 0;
3578905a67cSAndy Whitcroft	my $c;
3588905a67cSAndy Whitcroft	my $len = 0;
3598905a67cSAndy Whitcroft	while (1) {
3608905a67cSAndy Whitcroft		#warn "CSB: blk<$blk>\n";
3618905a67cSAndy Whitcroft		# If we are about to drop off the end, pull in more
3628905a67cSAndy Whitcroft		# context.
3638905a67cSAndy Whitcroft		if ($off >= $len) {
3648905a67cSAndy Whitcroft			for (; $remain > 0; $line++) {
365*c2fdda0dSAndy Whitcroft				next if ($lines[$line] =~ /^-/);
3668905a67cSAndy Whitcroft				$remain--;
367*c2fdda0dSAndy Whitcroft				$blk .= $lines[$line] . "\n";
3688905a67cSAndy Whitcroft				$len = length($blk);
3698905a67cSAndy Whitcroft				$line++;
3708905a67cSAndy Whitcroft				last;
3718905a67cSAndy Whitcroft			}
3728905a67cSAndy Whitcroft			# Bail if there is no further context.
3738905a67cSAndy Whitcroft			#warn "CSB: blk<$blk> off<$off> len<$len>\n";
3748905a67cSAndy Whitcroft			if ($off == $len) {
3758905a67cSAndy Whitcroft				last;
3768905a67cSAndy Whitcroft			}
3778905a67cSAndy Whitcroft		}
3788905a67cSAndy Whitcroft		$c = substr($blk, $off, 1);
3798905a67cSAndy Whitcroft
3808905a67cSAndy Whitcroft		#warn "CSB: c<$c> type<$type> level<$level>\n";
3818905a67cSAndy Whitcroft		# Statement ends at the ';' or a close '}' at the
3828905a67cSAndy Whitcroft		# outermost level.
3838905a67cSAndy Whitcroft		if ($level == 0 && $c eq ';') {
3848905a67cSAndy Whitcroft			last;
3858905a67cSAndy Whitcroft		}
3868905a67cSAndy Whitcroft
3878905a67cSAndy Whitcroft		if (($type eq '' || $type eq '(') && $c eq '(') {
3888905a67cSAndy Whitcroft			$level++;
3898905a67cSAndy Whitcroft			$type = '(';
3908905a67cSAndy Whitcroft		}
3918905a67cSAndy Whitcroft		if ($type eq '(' && $c eq ')') {
3928905a67cSAndy Whitcroft			$level--;
3938905a67cSAndy Whitcroft			$type = ($level != 0)? '(' : '';
3948905a67cSAndy Whitcroft
3958905a67cSAndy Whitcroft			if ($level == 0 && $coff < $soff) {
3968905a67cSAndy Whitcroft				$coff = $off;
3978905a67cSAndy Whitcroft			}
3988905a67cSAndy Whitcroft		}
3998905a67cSAndy Whitcroft		if (($type eq '' || $type eq '{') && $c eq '{') {
4008905a67cSAndy Whitcroft			$level++;
4018905a67cSAndy Whitcroft			$type = '{';
4028905a67cSAndy Whitcroft		}
4038905a67cSAndy Whitcroft		if ($type eq '{' && $c eq '}') {
4048905a67cSAndy Whitcroft			$level--;
4058905a67cSAndy Whitcroft			$type = ($level != 0)? '{' : '';
4068905a67cSAndy Whitcroft
4078905a67cSAndy Whitcroft			if ($level == 0) {
4088905a67cSAndy Whitcroft				last;
4098905a67cSAndy Whitcroft			}
4108905a67cSAndy Whitcroft		}
4118905a67cSAndy Whitcroft		$off++;
4128905a67cSAndy Whitcroft	}
4138905a67cSAndy Whitcroft
4148905a67cSAndy Whitcroft	my $statement = substr($blk, $soff, $off - $soff + 1);
4158905a67cSAndy Whitcroft	my $condition = substr($blk, $soff, $coff - $soff + 1);
4168905a67cSAndy Whitcroft
4178905a67cSAndy Whitcroft	#warn "STATEMENT<$statement>\n";
4188905a67cSAndy Whitcroft	#warn "CONDITION<$condition>\n";
4198905a67cSAndy Whitcroft
4208905a67cSAndy Whitcroft	return ($statement, $condition);
4218905a67cSAndy Whitcroft}
4228905a67cSAndy Whitcroft
4234a0df2efSAndy Whitcroftsub ctx_block_get {
424f0a594c1SAndy Whitcroft	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
4254a0df2efSAndy Whitcroft	my $line;
4264a0df2efSAndy Whitcroft	my $start = $linenr - 1;
4274a0df2efSAndy Whitcroft	my $blk = '';
4284a0df2efSAndy Whitcroft	my @o;
4294a0df2efSAndy Whitcroft	my @c;
4304a0df2efSAndy Whitcroft	my @res = ();
4314a0df2efSAndy Whitcroft
432f0a594c1SAndy Whitcroft	my $level = 0;
43300df344fSAndy Whitcroft	for ($line = $start; $remain > 0; $line++) {
43400df344fSAndy Whitcroft		next if ($rawlines[$line] =~ /^-/);
43500df344fSAndy Whitcroft		$remain--;
43600df344fSAndy Whitcroft
43700df344fSAndy Whitcroft		$blk .= $rawlines[$line];
438f0a594c1SAndy Whitcroft		foreach my $c (split(//, $rawlines[$line])) {
439f0a594c1SAndy Whitcroft			##print "C<$c>L<$level><$open$close>O<$off>\n";
440f0a594c1SAndy Whitcroft			if ($off > 0) {
441f0a594c1SAndy Whitcroft				$off--;
442f0a594c1SAndy Whitcroft				next;
443f0a594c1SAndy Whitcroft			}
4444a0df2efSAndy Whitcroft
445f0a594c1SAndy Whitcroft			if ($c eq $close && $level > 0) {
446f0a594c1SAndy Whitcroft				$level--;
447f0a594c1SAndy Whitcroft				last if ($level == 0);
448f0a594c1SAndy Whitcroft			} elsif ($c eq $open) {
449f0a594c1SAndy Whitcroft				$level++;
450f0a594c1SAndy Whitcroft			}
451f0a594c1SAndy Whitcroft		}
4524a0df2efSAndy Whitcroft
453f0a594c1SAndy Whitcroft		if (!$outer || $level <= 1) {
45400df344fSAndy Whitcroft			push(@res, $rawlines[$line]);
4554a0df2efSAndy Whitcroft		}
4564a0df2efSAndy Whitcroft
457f0a594c1SAndy Whitcroft		last if ($level == 0);
4584a0df2efSAndy Whitcroft	}
4594a0df2efSAndy Whitcroft
460f0a594c1SAndy Whitcroft	return ($level, @res);
4614a0df2efSAndy Whitcroft}
4624a0df2efSAndy Whitcroftsub ctx_block_outer {
4634a0df2efSAndy Whitcroft	my ($linenr, $remain) = @_;
4644a0df2efSAndy Whitcroft
465f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
466f0a594c1SAndy Whitcroft	return @r;
4674a0df2efSAndy Whitcroft}
4684a0df2efSAndy Whitcroftsub ctx_block {
4694a0df2efSAndy Whitcroft	my ($linenr, $remain) = @_;
4704a0df2efSAndy Whitcroft
471f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
472f0a594c1SAndy Whitcroft	return @r;
473653d4876SAndy Whitcroft}
474653d4876SAndy Whitcroftsub ctx_statement {
475f0a594c1SAndy Whitcroft	my ($linenr, $remain, $off) = @_;
476f0a594c1SAndy Whitcroft
477f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
478f0a594c1SAndy Whitcroft	return @r;
479f0a594c1SAndy Whitcroft}
480f0a594c1SAndy Whitcroftsub ctx_block_level {
481653d4876SAndy Whitcroft	my ($linenr, $remain) = @_;
482653d4876SAndy Whitcroft
483f0a594c1SAndy Whitcroft	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
4844a0df2efSAndy Whitcroft}
4859c0ca6f9SAndy Whitcroftsub ctx_statement_level {
4869c0ca6f9SAndy Whitcroft	my ($linenr, $remain, $off) = @_;
4879c0ca6f9SAndy Whitcroft
4889c0ca6f9SAndy Whitcroft	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
4899c0ca6f9SAndy Whitcroft}
4904a0df2efSAndy Whitcroft
4914a0df2efSAndy Whitcroftsub ctx_locate_comment {
4924a0df2efSAndy Whitcroft	my ($first_line, $end_line) = @_;
4934a0df2efSAndy Whitcroft
4944a0df2efSAndy Whitcroft	# Catch a comment on the end of the line itself.
49500df344fSAndy Whitcroft	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
4964a0df2efSAndy Whitcroft	return $current_comment if (defined $current_comment);
4974a0df2efSAndy Whitcroft
4984a0df2efSAndy Whitcroft	# Look through the context and try and figure out if there is a
4994a0df2efSAndy Whitcroft	# comment.
5004a0df2efSAndy Whitcroft	my $in_comment = 0;
5014a0df2efSAndy Whitcroft	$current_comment = '';
5024a0df2efSAndy Whitcroft	for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
50300df344fSAndy Whitcroft		my $line = $rawlines[$linenr - 1];
50400df344fSAndy Whitcroft		#warn "           $line\n";
5054a0df2efSAndy Whitcroft		if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
5064a0df2efSAndy Whitcroft			$in_comment = 1;
5074a0df2efSAndy Whitcroft		}
5084a0df2efSAndy Whitcroft		if ($line =~ m@/\*@) {
5094a0df2efSAndy Whitcroft			$in_comment = 1;
5104a0df2efSAndy Whitcroft		}
5114a0df2efSAndy Whitcroft		if (!$in_comment && $current_comment ne '') {
5124a0df2efSAndy Whitcroft			$current_comment = '';
5134a0df2efSAndy Whitcroft		}
5144a0df2efSAndy Whitcroft		$current_comment .= $line . "\n" if ($in_comment);
5154a0df2efSAndy Whitcroft		if ($line =~ m@\*/@) {
5164a0df2efSAndy Whitcroft			$in_comment = 0;
5174a0df2efSAndy Whitcroft		}
5184a0df2efSAndy Whitcroft	}
5194a0df2efSAndy Whitcroft
5204a0df2efSAndy Whitcroft	chomp($current_comment);
5214a0df2efSAndy Whitcroft	return($current_comment);
5224a0df2efSAndy Whitcroft}
5234a0df2efSAndy Whitcroftsub ctx_has_comment {
5244a0df2efSAndy Whitcroft	my ($first_line, $end_line) = @_;
5254a0df2efSAndy Whitcroft	my $cmt = ctx_locate_comment($first_line, $end_line);
5264a0df2efSAndy Whitcroft
52700df344fSAndy Whitcroft	##print "LINE: $rawlines[$end_line - 1 ]\n";
5284a0df2efSAndy Whitcroft	##print "CMMT: $cmt\n";
5294a0df2efSAndy Whitcroft
5304a0df2efSAndy Whitcroft	return ($cmt ne '');
5314a0df2efSAndy Whitcroft}
5324a0df2efSAndy Whitcroft
5330a920b5bSAndy Whitcroftsub cat_vet {
5340a920b5bSAndy Whitcroft	my ($vet) = @_;
5359c0ca6f9SAndy Whitcroft	my ($res, $coded);
5360a920b5bSAndy Whitcroft
5379c0ca6f9SAndy Whitcroft	$res = '';
5386c72ffaaSAndy Whitcroft	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
5396c72ffaaSAndy Whitcroft		$res .= $1;
5406c72ffaaSAndy Whitcroft		if ($2 ne '') {
5419c0ca6f9SAndy Whitcroft			$coded = sprintf("^%c", unpack('C', $2) + 64);
5426c72ffaaSAndy Whitcroft			$res .= $coded;
5436c72ffaaSAndy Whitcroft		}
5449c0ca6f9SAndy Whitcroft	}
5459c0ca6f9SAndy Whitcroft	$res =~ s/$/\$/;
5460a920b5bSAndy Whitcroft
5479c0ca6f9SAndy Whitcroft	return $res;
5480a920b5bSAndy Whitcroft}
5490a920b5bSAndy Whitcroft
550*c2fdda0dSAndy Whitcroftmy $av_preprocessor = 0;
551*c2fdda0dSAndy Whitcroftmy $av_paren = 0;
552*c2fdda0dSAndy Whitcroftmy @av_paren_type;
553*c2fdda0dSAndy Whitcroft
554*c2fdda0dSAndy Whitcroftsub annotate_reset {
555*c2fdda0dSAndy Whitcroft	$av_preprocessor = 0;
556*c2fdda0dSAndy Whitcroft	$av_paren = 0;
557*c2fdda0dSAndy Whitcroft	@av_paren_type = ();
558*c2fdda0dSAndy Whitcroft}
559*c2fdda0dSAndy Whitcroft
5606c72ffaaSAndy Whitcroftsub annotate_values {
5616c72ffaaSAndy Whitcroft	my ($stream, $type) = @_;
5626c72ffaaSAndy Whitcroft
5636c72ffaaSAndy Whitcroft	my $res;
5646c72ffaaSAndy Whitcroft	my $cur = $stream;
5656c72ffaaSAndy Whitcroft
566*c2fdda0dSAndy Whitcroft	print "$stream\n" if ($dbg_values > 1);
5676c72ffaaSAndy Whitcroft
5686c72ffaaSAndy Whitcroft	while (length($cur)) {
569*c2fdda0dSAndy Whitcroft		print " <$type> " if ($dbg_values > 1);
5706c72ffaaSAndy Whitcroft		if ($cur =~ /^(\s+)/o) {
571*c2fdda0dSAndy Whitcroft			print "WS($1)\n" if ($dbg_values > 1);
572*c2fdda0dSAndy Whitcroft			if ($1 =~ /\n/ && $av_preprocessor) {
573*c2fdda0dSAndy Whitcroft				$av_preprocessor = 0;
5746c72ffaaSAndy Whitcroft				$type = 'N';
5756c72ffaaSAndy Whitcroft			}
5766c72ffaaSAndy Whitcroft
5778905a67cSAndy Whitcroft		} elsif ($cur =~ /^($Type)/) {
578*c2fdda0dSAndy Whitcroft			print "DECLARE($1)\n" if ($dbg_values > 1);
5796c72ffaaSAndy Whitcroft			$type = 'T';
5806c72ffaaSAndy Whitcroft
5816c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
582*c2fdda0dSAndy Whitcroft			print "DEFINE($1)\n" if ($dbg_values > 1);
583*c2fdda0dSAndy Whitcroft			$av_preprocessor = 1;
584*c2fdda0dSAndy Whitcroft			$av_paren_type[$av_paren] = 'N';
5856c72ffaaSAndy Whitcroft
586*c2fdda0dSAndy Whitcroft		} elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if|else|elif|endif))/o) {
587*c2fdda0dSAndy Whitcroft			print "PRE($1)\n" if ($dbg_values > 1);
588*c2fdda0dSAndy Whitcroft			$av_preprocessor = 1;
5896c72ffaaSAndy Whitcroft			$type = 'N';
5906c72ffaaSAndy Whitcroft
5916c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(\\\n)/o) {
592*c2fdda0dSAndy Whitcroft			print "PRECONT($1)\n" if ($dbg_values > 1);
5936c72ffaaSAndy Whitcroft
5946c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
595*c2fdda0dSAndy Whitcroft			print "SIZEOF($1)\n" if ($dbg_values > 1);
5966c72ffaaSAndy Whitcroft			if (defined $2) {
597*c2fdda0dSAndy Whitcroft				$av_paren_type[$av_paren] = 'V';
5986c72ffaaSAndy Whitcroft			}
5996c72ffaaSAndy Whitcroft			$type = 'N';
6006c72ffaaSAndy Whitcroft
6018905a67cSAndy Whitcroft		} elsif ($cur =~ /^(if|while|typeof|for)\b/o) {
602*c2fdda0dSAndy Whitcroft			print "COND($1)\n" if ($dbg_values > 1);
603*c2fdda0dSAndy Whitcroft			$av_paren_type[$av_paren] = 'N';
6046c72ffaaSAndy Whitcroft			$type = 'N';
6056c72ffaaSAndy Whitcroft
6066c72ffaaSAndy Whitcroft		} elsif ($cur =~/^(return|case|else)/o) {
607*c2fdda0dSAndy Whitcroft			print "KEYWORD($1)\n" if ($dbg_values > 1);
6086c72ffaaSAndy Whitcroft			$type = 'N';
6096c72ffaaSAndy Whitcroft
6106c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(\()/o) {
611*c2fdda0dSAndy Whitcroft			print "PAREN('$1')\n" if ($dbg_values > 1);
612*c2fdda0dSAndy Whitcroft			$av_paren++;
6136c72ffaaSAndy Whitcroft			$type = 'N';
6146c72ffaaSAndy Whitcroft
6156c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(\))/o) {
616*c2fdda0dSAndy Whitcroft			$av_paren-- if ($av_paren > 0);
617*c2fdda0dSAndy Whitcroft			if (defined $av_paren_type[$av_paren]) {
618*c2fdda0dSAndy Whitcroft				$type = $av_paren_type[$av_paren];
619*c2fdda0dSAndy Whitcroft				undef $av_paren_type[$av_paren];
620*c2fdda0dSAndy Whitcroft				print "PAREN('$1') -> $type\n"
621*c2fdda0dSAndy Whitcroft							if ($dbg_values > 1);
6226c72ffaaSAndy Whitcroft			} else {
623*c2fdda0dSAndy Whitcroft				print "PAREN('$1')\n" if ($dbg_values > 1);
6246c72ffaaSAndy Whitcroft			}
6256c72ffaaSAndy Whitcroft
6266c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Ident)\(/o) {
627*c2fdda0dSAndy Whitcroft			print "FUNC($1)\n" if ($dbg_values > 1);
628*c2fdda0dSAndy Whitcroft			$av_paren_type[$av_paren] = 'V';
6296c72ffaaSAndy Whitcroft
6306c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Ident|$Constant)/o) {
631*c2fdda0dSAndy Whitcroft			print "IDENT($1)\n" if ($dbg_values > 1);
6326c72ffaaSAndy Whitcroft			$type = 'V';
6336c72ffaaSAndy Whitcroft
6346c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Assignment)/o) {
635*c2fdda0dSAndy Whitcroft			print "ASSIGN($1)\n" if ($dbg_values > 1);
6366c72ffaaSAndy Whitcroft			$type = 'N';
6376c72ffaaSAndy Whitcroft
6386c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^(;|{|}|\?|:|\[)/o) {
639*c2fdda0dSAndy Whitcroft			print "END($1)\n" if ($dbg_values > 1);
6406c72ffaaSAndy Whitcroft			$type = 'N';
6416c72ffaaSAndy Whitcroft
6426c72ffaaSAndy Whitcroft		} elsif ($cur =~ /^($Operators)/o) {
643*c2fdda0dSAndy Whitcroft			print "OP($1)\n" if ($dbg_values > 1);
6446c72ffaaSAndy Whitcroft			if ($1 ne '++' && $1 ne '--') {
6456c72ffaaSAndy Whitcroft				$type = 'N';
6466c72ffaaSAndy Whitcroft			}
6476c72ffaaSAndy Whitcroft
6486c72ffaaSAndy Whitcroft		} elsif ($cur =~ /(^.)/o) {
649*c2fdda0dSAndy Whitcroft			print "C($1)\n" if ($dbg_values > 1);
6506c72ffaaSAndy Whitcroft		}
6516c72ffaaSAndy Whitcroft		if (defined $1) {
6526c72ffaaSAndy Whitcroft			$cur = substr($cur, length($1));
6536c72ffaaSAndy Whitcroft			$res .= $type x length($1);
6546c72ffaaSAndy Whitcroft		}
6556c72ffaaSAndy Whitcroft	}
6566c72ffaaSAndy Whitcroft
6576c72ffaaSAndy Whitcroft	return $res;
6586c72ffaaSAndy Whitcroft}
6596c72ffaaSAndy Whitcroft
6608905a67cSAndy Whitcroftsub possible {
6618905a67cSAndy Whitcroft	my ($possible) = @_;
6628905a67cSAndy Whitcroft
6638905a67cSAndy Whitcroft	#print "CHECK<$possible>\n";
6648905a67cSAndy Whitcroft	if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
6658905a67cSAndy Whitcroft	    $possible ne 'goto' && $possible ne 'return' &&
6668905a67cSAndy Whitcroft	    $possible ne 'struct' && $possible ne 'enum' &&
6678905a67cSAndy Whitcroft	    $possible ne 'case' && $possible ne 'else' &&
6688905a67cSAndy Whitcroft	    $possible ne 'typedef') {
669*c2fdda0dSAndy Whitcroft		warn "POSSIBLE: $possible\n" if ($dbg_possible);
6708905a67cSAndy Whitcroft		push(@typeList, $possible);
6718905a67cSAndy Whitcroft		build_types();
6728905a67cSAndy Whitcroft	}
6738905a67cSAndy Whitcroft}
6748905a67cSAndy Whitcroft
6756c72ffaaSAndy Whitcroftmy $prefix = '';
6766c72ffaaSAndy Whitcroft
677f0a594c1SAndy Whitcroftmy @report = ();
678f0a594c1SAndy Whitcroftsub report {
6798905a67cSAndy Whitcroft	my $line = $prefix . $_[0];
6808905a67cSAndy Whitcroft
6818905a67cSAndy Whitcroft	$line = (split('\n', $line))[0] . "\n" if ($terse);
6828905a67cSAndy Whitcroft
6838905a67cSAndy Whitcroft	push(@report, $line);
684f0a594c1SAndy Whitcroft}
685f0a594c1SAndy Whitcroftsub report_dump {
686f0a594c1SAndy Whitcroft	@report;
687f0a594c1SAndy Whitcroft}
688de7d4f0eSAndy Whitcroftsub ERROR {
689f0a594c1SAndy Whitcroft	report("ERROR: $_[0]\n");
690de7d4f0eSAndy Whitcroft	our $clean = 0;
6916c72ffaaSAndy Whitcroft	our $cnt_error++;
692de7d4f0eSAndy Whitcroft}
693de7d4f0eSAndy Whitcroftsub WARN {
694f0a594c1SAndy Whitcroft	report("WARNING: $_[0]\n");
695de7d4f0eSAndy Whitcroft	our $clean = 0;
6966c72ffaaSAndy Whitcroft	our $cnt_warn++;
697de7d4f0eSAndy Whitcroft}
698de7d4f0eSAndy Whitcroftsub CHK {
6996c72ffaaSAndy Whitcroft	if ($check) {
700f0a594c1SAndy Whitcroft		report("CHECK: $_[0]\n");
701de7d4f0eSAndy Whitcroft		our $clean = 0;
7026c72ffaaSAndy Whitcroft		our $cnt_chk++;
7036c72ffaaSAndy Whitcroft	}
704de7d4f0eSAndy Whitcroft}
705de7d4f0eSAndy Whitcroft
7060a920b5bSAndy Whitcroftsub process {
7070a920b5bSAndy Whitcroft	my $filename = shift;
7080a920b5bSAndy Whitcroft
7090a920b5bSAndy Whitcroft	my $linenr=0;
7100a920b5bSAndy Whitcroft	my $prevline="";
711*c2fdda0dSAndy Whitcroft	my $prevrawline="";
7120a920b5bSAndy Whitcroft	my $stashline="";
713*c2fdda0dSAndy Whitcroft	my $stashrawline="";
7140a920b5bSAndy Whitcroft
7154a0df2efSAndy Whitcroft	my $length;
7160a920b5bSAndy Whitcroft	my $indent;
7170a920b5bSAndy Whitcroft	my $previndent=0;
7180a920b5bSAndy Whitcroft	my $stashindent=0;
7190a920b5bSAndy Whitcroft
720de7d4f0eSAndy Whitcroft	our $clean = 1;
7210a920b5bSAndy Whitcroft	my $signoff = 0;
7220a920b5bSAndy Whitcroft	my $is_patch = 0;
7230a920b5bSAndy Whitcroft
7246c72ffaaSAndy Whitcroft	our $cnt_lines = 0;
7256c72ffaaSAndy Whitcroft	our $cnt_error = 0;
7266c72ffaaSAndy Whitcroft	our $cnt_warn = 0;
7276c72ffaaSAndy Whitcroft	our $cnt_chk = 0;
7286c72ffaaSAndy Whitcroft
7290a920b5bSAndy Whitcroft	# Trace the real file/line as we go.
7300a920b5bSAndy Whitcroft	my $realfile = '';
7310a920b5bSAndy Whitcroft	my $realline = 0;
7320a920b5bSAndy Whitcroft	my $realcnt = 0;
7330a920b5bSAndy Whitcroft	my $here = '';
7340a920b5bSAndy Whitcroft	my $in_comment = 0;
735*c2fdda0dSAndy Whitcroft	my $comment_edge = 0;
7360a920b5bSAndy Whitcroft	my $first_line = 0;
7370a920b5bSAndy Whitcroft
7386c72ffaaSAndy Whitcroft	my $prev_values = 'N';
739653d4876SAndy Whitcroft
740*c2fdda0dSAndy Whitcroft	# Pre-scan the patch sanitizing the lines.
741de7d4f0eSAndy Whitcroft	# Pre-scan the patch looking for any __setup documentation.
742*c2fdda0dSAndy Whitcroft	#
743de7d4f0eSAndy Whitcroft	my @setup_docs = ();
744de7d4f0eSAndy Whitcroft	my $setup_docs = 0;
745*c2fdda0dSAndy Whitcroft	my $line;
746*c2fdda0dSAndy Whitcroft	foreach my $rawline (@rawlines) {
747*c2fdda0dSAndy Whitcroft		# Standardise the strings and chars within the input to
748*c2fdda0dSAndy Whitcroft		# simplify matching.
749*c2fdda0dSAndy Whitcroft		$line = sanitise_line($rawline);
750*c2fdda0dSAndy Whitcroft		push(@lines, $line);
751*c2fdda0dSAndy Whitcroft
752*c2fdda0dSAndy Whitcroft		##print "==>$rawline\n";
753*c2fdda0dSAndy Whitcroft		##print "-->$line\n";
754*c2fdda0dSAndy Whitcroft
755de7d4f0eSAndy Whitcroft		if ($line=~/^\+\+\+\s+(\S+)/) {
756de7d4f0eSAndy Whitcroft			$setup_docs = 0;
757de7d4f0eSAndy Whitcroft			if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
758de7d4f0eSAndy Whitcroft				$setup_docs = 1;
759de7d4f0eSAndy Whitcroft			}
760de7d4f0eSAndy Whitcroft			next;
761de7d4f0eSAndy Whitcroft		}
762de7d4f0eSAndy Whitcroft
763de7d4f0eSAndy Whitcroft		if ($setup_docs && $line =~ /^\+/) {
764de7d4f0eSAndy Whitcroft			push(@setup_docs, $line);
765de7d4f0eSAndy Whitcroft		}
766de7d4f0eSAndy Whitcroft	}
767de7d4f0eSAndy Whitcroft
7686c72ffaaSAndy Whitcroft	$prefix = '';
7696c72ffaaSAndy Whitcroft
7700a920b5bSAndy Whitcroft	foreach my $line (@lines) {
7710a920b5bSAndy Whitcroft		$linenr++;
7720a920b5bSAndy Whitcroft
773*c2fdda0dSAndy Whitcroft		my $rawline = $rawlines[$linenr - 1];
7746c72ffaaSAndy Whitcroft
7750a920b5bSAndy Whitcroft#extract the filename as it passes
7760a920b5bSAndy Whitcroft		if ($line=~/^\+\+\+\s+(\S+)/) {
7770a920b5bSAndy Whitcroft			$realfile=$1;
77800df344fSAndy Whitcroft			$realfile =~ s@^[^/]*/@@;
7790a920b5bSAndy Whitcroft			$in_comment = 0;
7800a920b5bSAndy Whitcroft			next;
7810a920b5bSAndy Whitcroft		}
7820a920b5bSAndy Whitcroft#extract the line range in the file after the patch is applied
7836c72ffaaSAndy Whitcroft		if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
7840a920b5bSAndy Whitcroft			$is_patch = 1;
7854a0df2efSAndy Whitcroft			$first_line = $linenr + 1;
7860a920b5bSAndy Whitcroft			$in_comment = 0;
7870a920b5bSAndy Whitcroft			$realline=$1-1;
7880a920b5bSAndy Whitcroft			if (defined $2) {
7890a920b5bSAndy Whitcroft				$realcnt=$3+1;
7900a920b5bSAndy Whitcroft			} else {
7910a920b5bSAndy Whitcroft				$realcnt=1+1;
7920a920b5bSAndy Whitcroft			}
793*c2fdda0dSAndy Whitcroft			annotate_reset();
7946c72ffaaSAndy Whitcroft			$prev_values = 'N';
7950a920b5bSAndy Whitcroft			next;
7960a920b5bSAndy Whitcroft		}
7970a920b5bSAndy Whitcroft
7984a0df2efSAndy Whitcroft# track the line number as we move through the hunk, note that
7994a0df2efSAndy Whitcroft# new versions of GNU diff omit the leading space on completely
8004a0df2efSAndy Whitcroft# blank context lines so we need to count that too.
8014a0df2efSAndy Whitcroft		if ($line =~ /^( |\+|$)/) {
8020a920b5bSAndy Whitcroft			$realline++;
803d8aaf121SAndy Whitcroft			$realcnt-- if ($realcnt != 0);
8040a920b5bSAndy Whitcroft
8058905a67cSAndy Whitcroft			# Guestimate if this is a continuing comment.  Run
8068905a67cSAndy Whitcroft			# the context looking for a comment "edge".  If this
8078905a67cSAndy Whitcroft			# edge is a close comment then we must be in a comment
8088905a67cSAndy Whitcroft			# at context start.
8098905a67cSAndy Whitcroft			if ($linenr == $first_line) {
8108905a67cSAndy Whitcroft				my $edge;
8118905a67cSAndy Whitcroft				for (my $ln = $first_line; $ln < ($linenr + $realcnt); $ln++) {
812*c2fdda0dSAndy Whitcroft					($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
8138905a67cSAndy Whitcroft					last if (defined $edge);
8148905a67cSAndy Whitcroft				}
8158905a67cSAndy Whitcroft				if (defined $edge && $edge eq '*/') {
8168905a67cSAndy Whitcroft					$in_comment = 1;
8178905a67cSAndy Whitcroft				}
8188905a67cSAndy Whitcroft			}
8198905a67cSAndy Whitcroft
8200a920b5bSAndy Whitcroft			# Guestimate if this is a continuing comment.  If this
8210a920b5bSAndy Whitcroft			# is the start of a diff block and this line starts
8220a920b5bSAndy Whitcroft			# ' *' then it is very likely a comment.
823*c2fdda0dSAndy Whitcroft			if ($linenr == $first_line and $rawline =~ m@^.\s* \*(?:\s|$)@) {
8240a920b5bSAndy Whitcroft				$in_comment = 1;
8250a920b5bSAndy Whitcroft			}
8268905a67cSAndy Whitcroft
8278905a67cSAndy Whitcroft			# Find the last comment edge on _this_ line.
828*c2fdda0dSAndy Whitcroft			$comment_edge = 0;
829*c2fdda0dSAndy Whitcroft			while (($rawline =~ m@(/\*|\*/)@g)) {
8308905a67cSAndy Whitcroft				if ($1 eq '/*') {
8310a920b5bSAndy Whitcroft					$in_comment = 1;
8328905a67cSAndy Whitcroft				} else {
8330a920b5bSAndy Whitcroft					$in_comment = 0;
8340a920b5bSAndy Whitcroft				}
835*c2fdda0dSAndy Whitcroft				$comment_edge = 1;
8368905a67cSAndy Whitcroft			}
8370a920b5bSAndy Whitcroft
8384a0df2efSAndy Whitcroft			# Measure the line length and indent.
839*c2fdda0dSAndy Whitcroft			($length, $indent) = line_stats($rawline);
8400a920b5bSAndy Whitcroft
8410a920b5bSAndy Whitcroft			# Track the previous line.
8420a920b5bSAndy Whitcroft			($prevline, $stashline) = ($stashline, $line);
8430a920b5bSAndy Whitcroft			($previndent, $stashindent) = ($stashindent, $indent);
844*c2fdda0dSAndy Whitcroft			($prevrawline, $stashrawline) = ($stashrawline, $rawline);
845*c2fdda0dSAndy Whitcroft
846*c2fdda0dSAndy Whitcroft			#warn "ic<$in_comment> ce<$comment_edge> line<$line>\n";
8476c72ffaaSAndy Whitcroft
848d8aaf121SAndy Whitcroft		} elsif ($realcnt == 1) {
849d8aaf121SAndy Whitcroft			$realcnt--;
8500a920b5bSAndy Whitcroft		}
8510a920b5bSAndy Whitcroft
8520a920b5bSAndy Whitcroft#make up the handle for any error we report on this line
8536c72ffaaSAndy Whitcroft		$here = "#$linenr: " if (!$file);
8546c72ffaaSAndy Whitcroft		$here = "#$realline: " if ($file);
855389834b6SRandy Dunlap		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
8560a920b5bSAndy Whitcroft
857*c2fdda0dSAndy Whitcroft		my $hereline = "$here\n$rawline\n";
858*c2fdda0dSAndy Whitcroft		my $herecurr = "$here\n$rawline\n";
859*c2fdda0dSAndy Whitcroft		my $hereprev = "$here\n$prevrawline\n$rawline\n";
8600a920b5bSAndy Whitcroft
8616c72ffaaSAndy Whitcroft		$prefix = "$filename:$realline: " if ($emacs && $file);
8626c72ffaaSAndy Whitcroft		$prefix = "$filename:$linenr: " if ($emacs && !$file);
8636c72ffaaSAndy Whitcroft		$cnt_lines++ if ($realcnt != 0);
8646c72ffaaSAndy Whitcroft
8650a920b5bSAndy Whitcroft#check the patch for a signoff:
866d8aaf121SAndy Whitcroft		if ($line =~ /^\s*signed-off-by:/i) {
8674a0df2efSAndy Whitcroft			# This is a signoff, if ugly, so do not double report.
8684a0df2efSAndy Whitcroft			$signoff++;
8690a920b5bSAndy Whitcroft			if (!($line =~ /^\s*Signed-off-by:/)) {
870de7d4f0eSAndy Whitcroft				WARN("Signed-off-by: is the preferred form\n" .
871de7d4f0eSAndy Whitcroft					$herecurr);
8720a920b5bSAndy Whitcroft			}
8730a920b5bSAndy Whitcroft			if ($line =~ /^\s*signed-off-by:\S/i) {
874de7d4f0eSAndy Whitcroft				WARN("need space after Signed-off-by:\n" .
875de7d4f0eSAndy Whitcroft					$herecurr);
8760a920b5bSAndy Whitcroft			}
8770a920b5bSAndy Whitcroft		}
8780a920b5bSAndy Whitcroft
87900df344fSAndy Whitcroft# Check for wrappage within a valid hunk of the file
8808905a67cSAndy Whitcroft		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
881de7d4f0eSAndy Whitcroft			ERROR("patch seems to be corrupt (line wrapped?)\n" .
8826c72ffaaSAndy Whitcroft				$herecurr) if (!$emitted_corrupt++);
883de7d4f0eSAndy Whitcroft		}
884de7d4f0eSAndy Whitcroft
885de7d4f0eSAndy Whitcroft# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
886de7d4f0eSAndy Whitcroft		if (($realfile =~ /^$/ || $line =~ /^\+/) &&
887*c2fdda0dSAndy Whitcroft		     !($rawline =~ m/^(
888de7d4f0eSAndy Whitcroft				[\x09\x0A\x0D\x20-\x7E]              # ASCII
889de7d4f0eSAndy Whitcroft				| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
890de7d4f0eSAndy Whitcroft				|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
891de7d4f0eSAndy Whitcroft				| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
892de7d4f0eSAndy Whitcroft				|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
893de7d4f0eSAndy Whitcroft				|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
894de7d4f0eSAndy Whitcroft				| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
895de7d4f0eSAndy Whitcroft				|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
896de7d4f0eSAndy Whitcroft				)*$/x )) {
897*c2fdda0dSAndy Whitcroft			ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $herecurr);
89800df344fSAndy Whitcroft		}
8990a920b5bSAndy Whitcroft
90000df344fSAndy Whitcroft#ignore lines being removed
90100df344fSAndy Whitcroft		if ($line=~/^-/) {next;}
90200df344fSAndy Whitcroft
90300df344fSAndy Whitcroft# check we are in a valid source file if not then ignore this hunk
90400df344fSAndy Whitcroft		next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
9050a920b5bSAndy Whitcroft
9060a920b5bSAndy Whitcroft#trailing whitespace
9079c0ca6f9SAndy Whitcroft		if ($line =~ /^\+.*\015/) {
908*c2fdda0dSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
9099c0ca6f9SAndy Whitcroft			ERROR("DOS line endings\n" . $herevet);
9109c0ca6f9SAndy Whitcroft
911*c2fdda0dSAndy Whitcroft		} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
912*c2fdda0dSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
913de7d4f0eSAndy Whitcroft			ERROR("trailing whitespace\n" . $herevet);
9140a920b5bSAndy Whitcroft		}
9150a920b5bSAndy Whitcroft#80 column limit
916*c2fdda0dSAndy Whitcroft		if ($line =~ /^\+/ && !($prevrawline=~/\/\*\*/) && $length > 80) {
917de7d4f0eSAndy Whitcroft			WARN("line over 80 characters\n" . $herecurr);
9180a920b5bSAndy Whitcroft		}
9190a920b5bSAndy Whitcroft
9208905a67cSAndy Whitcroft# check for adding lines without a newline.
9218905a67cSAndy Whitcroft		if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
9228905a67cSAndy Whitcroft			WARN("adding a line without newline at end of file\n" . $herecurr);
9238905a67cSAndy Whitcroft		}
9248905a67cSAndy Whitcroft
9250a920b5bSAndy Whitcroft# check we are in a valid source file *.[hc] if not then ignore this hunk
9260a920b5bSAndy Whitcroft		next if ($realfile !~ /\.[hc]$/);
9270a920b5bSAndy Whitcroft
9280a920b5bSAndy Whitcroft# at the beginning of a line any tabs must come first and anything
9290a920b5bSAndy Whitcroft# more than 8 must use tabs.
930*c2fdda0dSAndy Whitcroft		if ($rawline =~ /^\+\s* \t\s*\S/ ||
931*c2fdda0dSAndy Whitcroft		    $rawline =~ /^\+\s*        \s*/) {
932*c2fdda0dSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($rawline) . "\n";
933de7d4f0eSAndy Whitcroft			ERROR("use tabs not spaces\n" . $herevet);
9340a920b5bSAndy Whitcroft		}
9350a920b5bSAndy Whitcroft
936*c2fdda0dSAndy Whitcroft# check for RCS/CVS revision markers
937*c2fdda0dSAndy Whitcroft		if ($rawline =~ /\$(Revision|Log|Id)(?:\$|)/) {
938*c2fdda0dSAndy Whitcroft			WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
939*c2fdda0dSAndy Whitcroft		}
94022f2a2efSAndy Whitcroft
94122f2a2efSAndy Whitcroft# The rest of our checks refer specifically to C style
94222f2a2efSAndy Whitcroft# only apply those _outside_ comments.  Only skip
94322f2a2efSAndy Whitcroft# lines in the middle of comments.
94422f2a2efSAndy Whitcroft		next if (!$comment_edge && $in_comment);
94500df344fSAndy Whitcroft
9469c0ca6f9SAndy Whitcroft# Check for potential 'bare' types
947*c2fdda0dSAndy Whitcroft		if ($realcnt) {
948*c2fdda0dSAndy Whitcroft			# Ignore goto labels.
949*c2fdda0dSAndy Whitcroft			if ($line =~ /$Ident:\*$/) {
950*c2fdda0dSAndy Whitcroft
951*c2fdda0dSAndy Whitcroft			# Ignore functions being called
952*c2fdda0dSAndy Whitcroft			} elsif ($line =~ /^.\s*$Ident\s*\(/) {
953*c2fdda0dSAndy Whitcroft
9546c72ffaaSAndy Whitcroft			# definitions in global scope can only start with types
955*c2fdda0dSAndy Whitcroft			} elsif ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) {
9568905a67cSAndy Whitcroft				possible($1);
9578905a67cSAndy Whitcroft
9586c72ffaaSAndy Whitcroft			# declarations always start with types
959*c2fdda0dSAndy Whitcroft			} elsif ($prev_values eq 'N' && $line =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=)/) {
9608905a67cSAndy Whitcroft				possible($1);
961*c2fdda0dSAndy Whitcroft			}
9628905a67cSAndy Whitcroft
9636c72ffaaSAndy Whitcroft			# any (foo ... *) is a pointer cast, and foo is a type
964*c2fdda0dSAndy Whitcroft			while ($line =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) {
9658905a67cSAndy Whitcroft				possible($1);
9669c0ca6f9SAndy Whitcroft			}
9678905a67cSAndy Whitcroft
9688905a67cSAndy Whitcroft			# Check for any sort of function declaration.
9698905a67cSAndy Whitcroft			# int foo(something bar, other baz);
9708905a67cSAndy Whitcroft			# void (*store_gdt)(x86_descr_ptr *);
971*c2fdda0dSAndy Whitcroft			if ($prev_values eq 'N' && $line =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) {
9728905a67cSAndy Whitcroft				my ($name_len) = length($1);
9738905a67cSAndy Whitcroft				my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, $name_len);
9748905a67cSAndy Whitcroft				my $ctx = join("\n", @ctx);
9758905a67cSAndy Whitcroft
9768905a67cSAndy Whitcroft				$ctx =~ s/\n.//;
9778905a67cSAndy Whitcroft				substr($ctx, 0, $name_len + 1) = '';
9788905a67cSAndy Whitcroft				$ctx =~ s/\)[^\)]*$//;
9798905a67cSAndy Whitcroft				for my $arg (split(/\s*,\s*/, $ctx)) {
9808905a67cSAndy Whitcroft					if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/ || $arg =~ /^($Ident)$/) {
9818905a67cSAndy Whitcroft
9828905a67cSAndy Whitcroft						possible($1);
9838905a67cSAndy Whitcroft					}
9848905a67cSAndy Whitcroft				}
9858905a67cSAndy Whitcroft			}
9868905a67cSAndy Whitcroft
9879c0ca6f9SAndy Whitcroft		}
9889c0ca6f9SAndy Whitcroft
98900df344fSAndy Whitcroft#
99000df344fSAndy Whitcroft# Checks which may be anchored in the context.
99100df344fSAndy Whitcroft#
99200df344fSAndy Whitcroft
99300df344fSAndy Whitcroft# Check for switch () and associated case and default
99400df344fSAndy Whitcroft# statements should be at the same indent.
99500df344fSAndy Whitcroft		if ($line=~/\bswitch\s*\(.*\)/) {
99600df344fSAndy Whitcroft			my $err = '';
99700df344fSAndy Whitcroft			my $sep = '';
99800df344fSAndy Whitcroft			my @ctx = ctx_block_outer($linenr, $realcnt);
99900df344fSAndy Whitcroft			shift(@ctx);
100000df344fSAndy Whitcroft			for my $ctx (@ctx) {
100100df344fSAndy Whitcroft				my ($clen, $cindent) = line_stats($ctx);
100200df344fSAndy Whitcroft				if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
100300df344fSAndy Whitcroft							$indent != $cindent) {
100400df344fSAndy Whitcroft					$err .= "$sep$ctx\n";
100500df344fSAndy Whitcroft					$sep = '';
100600df344fSAndy Whitcroft				} else {
100700df344fSAndy Whitcroft					$sep = "[...]\n";
100800df344fSAndy Whitcroft				}
100900df344fSAndy Whitcroft			}
101000df344fSAndy Whitcroft			if ($err ne '') {
10119c0ca6f9SAndy Whitcroft				ERROR("switch and case should be at the same indent\n$hereline$err");
1012de7d4f0eSAndy Whitcroft			}
1013de7d4f0eSAndy Whitcroft		}
1014de7d4f0eSAndy Whitcroft
1015de7d4f0eSAndy Whitcroft# if/while/etc brace do not go on next line, unless defining a do while loop,
1016de7d4f0eSAndy Whitcroft# or if that brace on the next line is for something else
1017de7d4f0eSAndy Whitcroft		if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
10189c0ca6f9SAndy Whitcroft			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
1019de7d4f0eSAndy Whitcroft			my $ctx_ln = $linenr + $#ctx + 1;
1020de7d4f0eSAndy Whitcroft			my $ctx_cnt = $realcnt - $#ctx - 1;
1021de7d4f0eSAndy Whitcroft			my $ctx = join("\n", @ctx);
1022de7d4f0eSAndy Whitcroft
10239c0ca6f9SAndy Whitcroft			# Skip over any removed lines in the context following statement.
1024de7d4f0eSAndy Whitcroft			while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
1025de7d4f0eSAndy Whitcroft				$ctx_ln++;
1026de7d4f0eSAndy Whitcroft				$ctx_cnt--;
1027de7d4f0eSAndy Whitcroft			}
1028de7d4f0eSAndy Whitcroft			##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
1029de7d4f0eSAndy Whitcroft
1030de7d4f0eSAndy Whitcroft			if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
1031f0a594c1SAndy Whitcroft				ERROR("That open brace { should be on the previous line\n" .
1032de7d4f0eSAndy Whitcroft					"$here\n$ctx\n$lines[$ctx_ln - 1]");
103300df344fSAndy Whitcroft			}
10349c0ca6f9SAndy Whitcroft			if ($level == 0 && $ctx =~ /\)\s*\;\s*$/ && defined $lines[$ctx_ln - 1]) {
10359c0ca6f9SAndy Whitcroft				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
10369c0ca6f9SAndy Whitcroft				if ($nindent > $indent) {
10379c0ca6f9SAndy Whitcroft					WARN("Trailing semicolon indicates no statements, indent implies otherwise\n" .
10389c0ca6f9SAndy Whitcroft						"$here\n$ctx\n$lines[$ctx_ln - 1]");
10399c0ca6f9SAndy Whitcroft				}
10409c0ca6f9SAndy Whitcroft			}
104100df344fSAndy Whitcroft		}
104200df344fSAndy Whitcroft
10436c72ffaaSAndy Whitcroft		# Track the 'values' across context and added lines.
10446c72ffaaSAndy Whitcroft		my $opline = $line; $opline =~ s/^./ /;
10456c72ffaaSAndy Whitcroft		my $curr_values = annotate_values($opline . "\n", $prev_values);
10466c72ffaaSAndy Whitcroft		$curr_values = $prev_values . $curr_values;
1047*c2fdda0dSAndy Whitcroft		if ($dbg_values) {
1048*c2fdda0dSAndy Whitcroft			my $outline = $opline; $outline =~ s/\t/ /g;
1049*c2fdda0dSAndy Whitcroft			warn "--> .$outline\n";
1050*c2fdda0dSAndy Whitcroft			warn "--> $curr_values\n";
1051*c2fdda0dSAndy Whitcroft		}
10526c72ffaaSAndy Whitcroft		$prev_values = substr($curr_values, -1);
10536c72ffaaSAndy Whitcroft
105400df344fSAndy Whitcroft#ignore lines not being added
105500df344fSAndy Whitcroft		if ($line=~/^[^\+]/) {next;}
105600df344fSAndy Whitcroft
1057653d4876SAndy Whitcroft# TEST: allow direct testing of the type matcher.
1058653d4876SAndy Whitcroft		if ($tst_type && $line =~ /^.$Declare$/) {
1059de7d4f0eSAndy Whitcroft			ERROR("TEST: is type $Declare\n" . $herecurr);
1060653d4876SAndy Whitcroft			next;
1061653d4876SAndy Whitcroft		}
1062653d4876SAndy Whitcroft
1063f0a594c1SAndy Whitcroft# check for initialisation to aggregates open brace on the next line
1064f0a594c1SAndy Whitcroft		if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
1065f0a594c1SAndy Whitcroft		    $line =~ /^.\s*{/) {
1066f0a594c1SAndy Whitcroft			ERROR("That open brace { should be on the previous line\n" . $hereprev);
1067f0a594c1SAndy Whitcroft		}
1068f0a594c1SAndy Whitcroft
106900df344fSAndy Whitcroft#
107000df344fSAndy Whitcroft# Checks which are anchored on the added line.
107100df344fSAndy Whitcroft#
107200df344fSAndy Whitcroft
1073653d4876SAndy Whitcroft# check for malformed paths in #include statements (uses RAW line)
1074653d4876SAndy Whitcroft		if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) {
1075653d4876SAndy Whitcroft			my $path = $1;
1076653d4876SAndy Whitcroft			if ($path =~ m{//}) {
1077de7d4f0eSAndy Whitcroft				ERROR("malformed #include filename\n" .
1078de7d4f0eSAndy Whitcroft					$herecurr);
1079653d4876SAndy Whitcroft			}
1080653d4876SAndy Whitcroft		}
1081653d4876SAndy Whitcroft
108200df344fSAndy Whitcroft# no C99 // comments
108300df344fSAndy Whitcroft		if ($line =~ m{//}) {
1084de7d4f0eSAndy Whitcroft			ERROR("do not use C99 // comments\n" . $herecurr);
108500df344fSAndy Whitcroft		}
108600df344fSAndy Whitcroft		# Remove C99 comments.
10870a920b5bSAndy Whitcroft		$line =~ s@//.*@@;
10886c72ffaaSAndy Whitcroft		$opline =~ s@//.*@@;
10890a920b5bSAndy Whitcroft
10900a920b5bSAndy Whitcroft#EXPORT_SYMBOL should immediately follow its function closing }.
1091653d4876SAndy Whitcroft		if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
1092653d4876SAndy Whitcroft		    ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
1093653d4876SAndy Whitcroft			my $name = $1;
10940a920b5bSAndy Whitcroft			if (($prevline !~ /^}/) &&
10950a920b5bSAndy Whitcroft			   ($prevline !~ /^\+}/) &&
1096653d4876SAndy Whitcroft			   ($prevline !~ /^ }/) &&
109722f2a2efSAndy Whitcroft			   ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=)/)) {
1098de7d4f0eSAndy Whitcroft				WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
10990a920b5bSAndy Whitcroft			}
11000a920b5bSAndy Whitcroft		}
11010a920b5bSAndy Whitcroft
1102f0a594c1SAndy Whitcroft# check for external initialisers.
1103f0a594c1SAndy Whitcroft		if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL);/) {
1104f0a594c1SAndy Whitcroft			ERROR("do not initialise externals to 0 or NULL\n" .
1105f0a594c1SAndy Whitcroft				$herecurr);
1106f0a594c1SAndy Whitcroft		}
11070a920b5bSAndy Whitcroft# check for static initialisers.
1108f0a594c1SAndy Whitcroft		if ($line =~ /\s*static\s.*=\s*(0|NULL);/) {
1109de7d4f0eSAndy Whitcroft			ERROR("do not initialise statics to 0 or NULL\n" .
1110de7d4f0eSAndy Whitcroft				$herecurr);
11110a920b5bSAndy Whitcroft		}
11120a920b5bSAndy Whitcroft
1113653d4876SAndy Whitcroft# check for new typedefs, only function parameters and sparse annotations
1114653d4876SAndy Whitcroft# make sense.
1115653d4876SAndy Whitcroft		if ($line =~ /\btypedef\s/ &&
11169c0ca6f9SAndy Whitcroft		    $line !~ /\btypedef\s+$Type\s+\(\s*\*?$Ident\s*\)\s*\(/ &&
1117653d4876SAndy Whitcroft		    $line !~ /\b__bitwise(?:__|)\b/) {
1118de7d4f0eSAndy Whitcroft			WARN("do not add new typedefs\n" . $herecurr);
11190a920b5bSAndy Whitcroft		}
11200a920b5bSAndy Whitcroft
11210a920b5bSAndy Whitcroft# * goes on variable not on type
1122d8aaf121SAndy Whitcroft		if ($line =~ m{\($NonptrType(\*+)(?:\s+const)?\)}) {
1123de7d4f0eSAndy Whitcroft			ERROR("\"(foo$1)\" should be \"(foo $1)\"\n" .
1124de7d4f0eSAndy Whitcroft				$herecurr);
1125d8aaf121SAndy Whitcroft
1126d8aaf121SAndy Whitcroft		} elsif ($line =~ m{\($NonptrType\s+(\*+)(?!\s+const)\s+\)}) {
1127de7d4f0eSAndy Whitcroft			ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
1128de7d4f0eSAndy Whitcroft				$herecurr);
1129d8aaf121SAndy Whitcroft
11309c0ca6f9SAndy Whitcroft		} elsif ($line =~ m{$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
1131de7d4f0eSAndy Whitcroft			ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
1132de7d4f0eSAndy Whitcroft				$herecurr);
1133d8aaf121SAndy Whitcroft
11349c0ca6f9SAndy Whitcroft		} elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
1135de7d4f0eSAndy Whitcroft			ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
1136de7d4f0eSAndy Whitcroft				$herecurr);
11370a920b5bSAndy Whitcroft		}
11380a920b5bSAndy Whitcroft
11390a920b5bSAndy Whitcroft# # no BUG() or BUG_ON()
11400a920b5bSAndy Whitcroft# 		if ($line =~ /\b(BUG|BUG_ON)\b/) {
11410a920b5bSAndy Whitcroft# 			print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
11420a920b5bSAndy Whitcroft# 			print "$herecurr";
11430a920b5bSAndy Whitcroft# 			$clean = 0;
11440a920b5bSAndy Whitcroft# 		}
11450a920b5bSAndy Whitcroft
11468905a67cSAndy Whitcroft		if ($line =~ /\bLINUX_VERSION_CODE\b/) {
1147*c2fdda0dSAndy Whitcroft			WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
11488905a67cSAndy Whitcroft		}
11498905a67cSAndy Whitcroft
115000df344fSAndy Whitcroft# printk should use KERN_* levels.  Note that follow on printk's on the
115100df344fSAndy Whitcroft# same line do not need a level, so we use the current block context
115200df344fSAndy Whitcroft# to try and find and validate the current printk.  In summary the current
115300df344fSAndy Whitcroft# printk includes all preceeding printk's which have no newline on the end.
115400df344fSAndy Whitcroft# we assume the first bad printk is the one to report.
1155f0a594c1SAndy Whitcroft		if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
115600df344fSAndy Whitcroft			my $ok = 0;
115700df344fSAndy Whitcroft			for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
115800df344fSAndy Whitcroft				#print "CHECK<$lines[$ln - 1]\n";
115900df344fSAndy Whitcroft				# we have a preceeding printk if it ends
116000df344fSAndy Whitcroft				# with "\n" ignore it, else it is to blame
116100df344fSAndy Whitcroft				if ($lines[$ln - 1] =~ m{\bprintk\(}) {
116200df344fSAndy Whitcroft					if ($rawlines[$ln - 1] !~ m{\\n"}) {
116300df344fSAndy Whitcroft						$ok = 1;
116400df344fSAndy Whitcroft					}
116500df344fSAndy Whitcroft					last;
116600df344fSAndy Whitcroft				}
116700df344fSAndy Whitcroft			}
116800df344fSAndy Whitcroft			if ($ok == 0) {
1169de7d4f0eSAndy Whitcroft				WARN("printk() should include KERN_ facility level\n" . $herecurr);
11700a920b5bSAndy Whitcroft			}
117100df344fSAndy Whitcroft		}
11720a920b5bSAndy Whitcroft
1173653d4876SAndy Whitcroft# function brace can't be on same line, except for #defines of do while,
1174653d4876SAndy Whitcroft# or if closed on same line
1175*c2fdda0dSAndy Whitcroft		if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).*\s{/) and
11760a920b5bSAndy Whitcroft		    !($line=~/\#define.*do\s{/) and !($line=~/}/)) {
1177de7d4f0eSAndy Whitcroft			ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
11780a920b5bSAndy Whitcroft		}
1179653d4876SAndy Whitcroft
11808905a67cSAndy Whitcroft# open braces for enum, union and struct go on the same line.
11818905a67cSAndy Whitcroft		if ($line =~ /^.\s*{/ &&
11828905a67cSAndy Whitcroft		    $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
11838905a67cSAndy Whitcroft			ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
11848905a67cSAndy Whitcroft		}
11858905a67cSAndy Whitcroft
1186f0a594c1SAndy Whitcroft# check for spaces between functions and their parentheses.
11876c72ffaaSAndy Whitcroft		while ($line =~ /($Ident)\s+\(/g) {
1188*c2fdda0dSAndy Whitcroft			my $name = $1;
1189*c2fdda0dSAndy Whitcroft			my $ctx = substr($line, 0, $-[1]);
1190*c2fdda0dSAndy Whitcroft
1191*c2fdda0dSAndy Whitcroft			# Ignore those directives where spaces _are_ permitted.
1192*c2fdda0dSAndy Whitcroft			if ($name =~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright|case)$/) {
1193*c2fdda0dSAndy Whitcroft
1194*c2fdda0dSAndy Whitcroft			# cpp #define statements have non-optional spaces, ie
1195*c2fdda0dSAndy Whitcroft			# if there is a space between the name and the open
1196*c2fdda0dSAndy Whitcroft			# parenthesis it is simply not a parameter group.
1197*c2fdda0dSAndy Whitcroft			} elsif ($ctx =~ /^.\#\s*define\s*$/) {
1198*c2fdda0dSAndy Whitcroft
1199*c2fdda0dSAndy Whitcroft			# If this whole things ends with a type its most
1200*c2fdda0dSAndy Whitcroft			# likely a typedef for a function.
1201*c2fdda0dSAndy Whitcroft			} elsif ("$ctx$name" =~ /$Type$/) {
1202*c2fdda0dSAndy Whitcroft
1203*c2fdda0dSAndy Whitcroft			} else {
120422f2a2efSAndy Whitcroft				WARN("no space between function name and open parenthesis '('\n" . $herecurr);
1205f0a594c1SAndy Whitcroft			}
12066c72ffaaSAndy Whitcroft		}
1207653d4876SAndy Whitcroft# Check operator spacing.
12080a920b5bSAndy Whitcroft		if (!($line=~/\#\s*include/)) {
12099c0ca6f9SAndy Whitcroft			my $ops = qr{
12109c0ca6f9SAndy Whitcroft				<<=|>>=|<=|>=|==|!=|
12119c0ca6f9SAndy Whitcroft				\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
12129c0ca6f9SAndy Whitcroft				=>|->|<<|>>|<|>|=|!|~|
1213*c2fdda0dSAndy Whitcroft				&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
12149c0ca6f9SAndy Whitcroft			}x;
12159c0ca6f9SAndy Whitcroft			my @elements = split(/($ops|;)/, $opline);
121600df344fSAndy Whitcroft			my $off = 0;
12176c72ffaaSAndy Whitcroft
12186c72ffaaSAndy Whitcroft			my $blank = copy_spacing($opline);
12196c72ffaaSAndy Whitcroft
12200a920b5bSAndy Whitcroft			for (my $n = 0; $n < $#elements; $n += 2) {
12214a0df2efSAndy Whitcroft				$off += length($elements[$n]);
12224a0df2efSAndy Whitcroft
12234a0df2efSAndy Whitcroft				my $a = '';
12244a0df2efSAndy Whitcroft				$a = 'V' if ($elements[$n] ne '');
12254a0df2efSAndy Whitcroft				$a = 'W' if ($elements[$n] =~ /\s$/);
12264a0df2efSAndy Whitcroft				$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
12274a0df2efSAndy Whitcroft				$a = 'O' if ($elements[$n] eq '');
12284a0df2efSAndy Whitcroft				$a = 'E' if ($elements[$n] eq '' && $n == 0);
12294a0df2efSAndy Whitcroft
12300a920b5bSAndy Whitcroft				my $op = $elements[$n + 1];
12314a0df2efSAndy Whitcroft
12324a0df2efSAndy Whitcroft				my $c = '';
12330a920b5bSAndy Whitcroft				if (defined $elements[$n + 2]) {
12344a0df2efSAndy Whitcroft					$c = 'V' if ($elements[$n + 2] ne '');
12354a0df2efSAndy Whitcroft					$c = 'W' if ($elements[$n + 2] =~ /^\s/);
12364a0df2efSAndy Whitcroft					$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
12374a0df2efSAndy Whitcroft					$c = 'O' if ($elements[$n + 2] eq '');
123822f2a2efSAndy Whitcroft					$c = 'E' if ($elements[$n + 2] =~ /\s*\\$/);
12394a0df2efSAndy Whitcroft				} else {
12404a0df2efSAndy Whitcroft					$c = 'E';
12410a920b5bSAndy Whitcroft				}
12420a920b5bSAndy Whitcroft
124300df344fSAndy Whitcroft				# Pick up the preceeding and succeeding characters.
1244de7d4f0eSAndy Whitcroft				my $ca = substr($opline, 0, $off);
124500df344fSAndy Whitcroft				my $cc = '';
1246653d4876SAndy Whitcroft				if (length($opline) >= ($off + length($elements[$n + 1]))) {
1247d8aaf121SAndy Whitcroft					$cc = substr($opline, $off + length($elements[$n + 1]));
124800df344fSAndy Whitcroft				}
1249de7d4f0eSAndy Whitcroft				my $cb = "$ca$;$cc";
125000df344fSAndy Whitcroft
12514a0df2efSAndy Whitcroft				my $ctx = "${a}x${c}";
12524a0df2efSAndy Whitcroft
12534a0df2efSAndy Whitcroft				my $at = "(ctx:$ctx)";
12544a0df2efSAndy Whitcroft
12556c72ffaaSAndy Whitcroft				my $ptr = substr($blank, 0, $off) . "^";
1256de7d4f0eSAndy Whitcroft				my $hereptr = "$hereline$ptr\n";
12570a920b5bSAndy Whitcroft
12589c0ca6f9SAndy Whitcroft				# Classify operators into binary, unary, or
12599c0ca6f9SAndy Whitcroft				# definitions (* only) where they have more
12609c0ca6f9SAndy Whitcroft				# than one mode.
12616c72ffaaSAndy Whitcroft				my $op_type = substr($curr_values, $off + 1, 1);
12626c72ffaaSAndy Whitcroft				my $op_left = substr($curr_values, $off, 1);
12636c72ffaaSAndy Whitcroft				my $is_unary;
12646c72ffaaSAndy Whitcroft				if ($op_type eq 'T') {
12659c0ca6f9SAndy Whitcroft					$is_unary = 2;
12666c72ffaaSAndy Whitcroft				} elsif ($op_left eq 'V') {
12676c72ffaaSAndy Whitcroft					$is_unary = 0;
12686c72ffaaSAndy Whitcroft				} else {
12696c72ffaaSAndy Whitcroft					$is_unary = 1;
12709c0ca6f9SAndy Whitcroft				}
12719c0ca6f9SAndy Whitcroft				#if ($op eq '-' || $op eq '&' || $op eq '*') {
12726c72ffaaSAndy Whitcroft				#	print "UNARY: <$op_left$op_type $is_unary $a:$op:$c> <$ca:$op:$cc> <$unary_ctx>\n";
12739c0ca6f9SAndy Whitcroft				#}
12740a920b5bSAndy Whitcroft
1275d8aaf121SAndy Whitcroft				# ; should have either the end of line or a space or \ after it
1276d8aaf121SAndy Whitcroft				if ($op eq ';') {
1277de7d4f0eSAndy Whitcroft					if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ &&
1278de7d4f0eSAndy Whitcroft					    $cc !~ /^;/) {
1279de7d4f0eSAndy Whitcroft						ERROR("need space after that '$op' $at\n" . $hereptr);
1280d8aaf121SAndy Whitcroft					}
1281d8aaf121SAndy Whitcroft
1282d8aaf121SAndy Whitcroft				# // is a comment
1283d8aaf121SAndy Whitcroft				} elsif ($op eq '//') {
12840a920b5bSAndy Whitcroft
12850a920b5bSAndy Whitcroft				# -> should have no spaces
12860a920b5bSAndy Whitcroft				} elsif ($op eq '->') {
12874a0df2efSAndy Whitcroft					if ($ctx =~ /Wx.|.xW/) {
1288de7d4f0eSAndy Whitcroft						ERROR("no spaces around that '$op' $at\n" . $hereptr);
12890a920b5bSAndy Whitcroft					}
12900a920b5bSAndy Whitcroft
12910a920b5bSAndy Whitcroft				# , must have a space on the right.
12920a920b5bSAndy Whitcroft				} elsif ($op eq ',') {
1293d8aaf121SAndy Whitcroft					if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
1294de7d4f0eSAndy Whitcroft						ERROR("need space after that '$op' $at\n" . $hereptr);
12950a920b5bSAndy Whitcroft					}
12960a920b5bSAndy Whitcroft
12979c0ca6f9SAndy Whitcroft				# '*' as part of a type definition -- reported already.
12989c0ca6f9SAndy Whitcroft				} elsif ($op eq '*' && $is_unary == 2) {
12999c0ca6f9SAndy Whitcroft					#warn "'*' is part of type\n";
13009c0ca6f9SAndy Whitcroft
13019c0ca6f9SAndy Whitcroft				# unary operators should have a space before and
13029c0ca6f9SAndy Whitcroft				# none after.  May be left adjacent to another
13039c0ca6f9SAndy Whitcroft				# unary operator, or a cast
13049c0ca6f9SAndy Whitcroft				} elsif ($op eq '!' || $op eq '~' ||
13059c0ca6f9SAndy Whitcroft				         ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
13069c0ca6f9SAndy Whitcroft					if ($ctx !~ /[WEB]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
1307de7d4f0eSAndy Whitcroft						ERROR("need space before that '$op' $at\n" . $hereptr);
13080a920b5bSAndy Whitcroft					}
13094a0df2efSAndy Whitcroft					if ($ctx =~ /.xW/) {
1310de7d4f0eSAndy Whitcroft						ERROR("no space after that '$op' $at\n" . $hereptr);
13110a920b5bSAndy Whitcroft					}
13120a920b5bSAndy Whitcroft
13130a920b5bSAndy Whitcroft				# unary ++ and unary -- are allowed no space on one side.
13140a920b5bSAndy Whitcroft				} elsif ($op eq '++' or $op eq '--') {
1315d8aaf121SAndy Whitcroft					if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
1316de7d4f0eSAndy Whitcroft						ERROR("need space one side of that '$op' $at\n" . $hereptr);
13170a920b5bSAndy Whitcroft					}
1318d8aaf121SAndy Whitcroft					if ($ctx =~ /Wx./ && $cc =~ /^;/) {
1319de7d4f0eSAndy Whitcroft						ERROR("no space before that '$op' $at\n" . $hereptr);
1320653d4876SAndy Whitcroft					}
13210a920b5bSAndy Whitcroft
13220a920b5bSAndy Whitcroft				# << and >> may either have or not have spaces both sides
13239c0ca6f9SAndy Whitcroft				} elsif ($op eq '<<' or $op eq '>>' or
13249c0ca6f9SAndy Whitcroft					 $op eq '&' or $op eq '^' or $op eq '|' or
13259c0ca6f9SAndy Whitcroft					 $op eq '+' or $op eq '-' or
1326*c2fdda0dSAndy Whitcroft					 $op eq '*' or $op eq '/' or
1327*c2fdda0dSAndy Whitcroft					 $op eq '%')
13280a920b5bSAndy Whitcroft				{
13299c0ca6f9SAndy Whitcroft					if ($ctx !~ /VxV|WxW|VxE|WxE|VxO/) {
1330de7d4f0eSAndy Whitcroft						ERROR("need consistent spacing around '$op' $at\n" .
1331de7d4f0eSAndy Whitcroft							$hereptr);
13320a920b5bSAndy Whitcroft					}
13330a920b5bSAndy Whitcroft
13340a920b5bSAndy Whitcroft				# All the others need spaces both sides.
13354a0df2efSAndy Whitcroft				} elsif ($ctx !~ /[EW]x[WE]/) {
133622f2a2efSAndy Whitcroft					# Ignore email addresses <foo@bar>
133722f2a2efSAndy Whitcroft					if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
133822f2a2efSAndy Whitcroft					    !($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
1339de7d4f0eSAndy Whitcroft						ERROR("need spaces around that '$op' $at\n" . $hereptr);
13400a920b5bSAndy Whitcroft					}
134122f2a2efSAndy Whitcroft				}
13424a0df2efSAndy Whitcroft				$off += length($elements[$n + 1]);
13430a920b5bSAndy Whitcroft			}
13440a920b5bSAndy Whitcroft		}
13450a920b5bSAndy Whitcroft
1346f0a594c1SAndy Whitcroft# check for multiple assignments
1347f0a594c1SAndy Whitcroft		if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
13486c72ffaaSAndy Whitcroft			CHK("multiple assignments should be avoided\n" . $herecurr);
1349f0a594c1SAndy Whitcroft		}
1350f0a594c1SAndy Whitcroft
135122f2a2efSAndy Whitcroft## # check for multiple declarations, allowing for a function declaration
135222f2a2efSAndy Whitcroft## # continuation.
135322f2a2efSAndy Whitcroft## 		if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
135422f2a2efSAndy Whitcroft## 		    $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
135522f2a2efSAndy Whitcroft##
135622f2a2efSAndy Whitcroft## 			# Remove any bracketed sections to ensure we do not
135722f2a2efSAndy Whitcroft## 			# falsly report the parameters of functions.
135822f2a2efSAndy Whitcroft## 			my $ln = $line;
135922f2a2efSAndy Whitcroft## 			while ($ln =~ s/\([^\(\)]*\)//g) {
136022f2a2efSAndy Whitcroft## 			}
136122f2a2efSAndy Whitcroft## 			if ($ln =~ /,/) {
136222f2a2efSAndy Whitcroft## 				WARN("declaring multiple variables together should be avoided\n" . $herecurr);
136322f2a2efSAndy Whitcroft## 			}
136422f2a2efSAndy Whitcroft## 		}
1365f0a594c1SAndy Whitcroft
13660a920b5bSAndy Whitcroft#need space before brace following if, while, etc
136722f2a2efSAndy Whitcroft		if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
136822f2a2efSAndy Whitcroft		    $line =~ /do{/) {
1369de7d4f0eSAndy Whitcroft			ERROR("need a space before the open brace '{'\n" . $herecurr);
1370de7d4f0eSAndy Whitcroft		}
1371de7d4f0eSAndy Whitcroft
1372de7d4f0eSAndy Whitcroft# closing brace should have a space following it when it has anything
1373de7d4f0eSAndy Whitcroft# on the line
1374de7d4f0eSAndy Whitcroft		if ($line =~ /}(?!(?:,|;|\)))\S/) {
1375de7d4f0eSAndy Whitcroft			ERROR("need a space after that close brace '}'\n" . $herecurr);
13760a920b5bSAndy Whitcroft		}
13770a920b5bSAndy Whitcroft
137822f2a2efSAndy Whitcroft# check spacing on square brackets
137922f2a2efSAndy Whitcroft		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
138022f2a2efSAndy Whitcroft			ERROR("no space after that open square bracket '['\n" . $herecurr);
138122f2a2efSAndy Whitcroft		}
138222f2a2efSAndy Whitcroft		if ($line =~ /\s\]/) {
138322f2a2efSAndy Whitcroft			ERROR("no space before that close square bracket ']'\n" . $herecurr);
138422f2a2efSAndy Whitcroft		}
138522f2a2efSAndy Whitcroft
138622f2a2efSAndy Whitcroft# check spacing on paretheses
13879c0ca6f9SAndy Whitcroft		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
13889c0ca6f9SAndy Whitcroft		    $line !~ /for\s*\(\s+;/) {
138922f2a2efSAndy Whitcroft			ERROR("no space after that open parenthesis '('\n" . $herecurr);
139022f2a2efSAndy Whitcroft		}
13919c0ca6f9SAndy Whitcroft		if ($line =~ /\s\)/ && $line !~ /^.\s*\)/ &&
13929c0ca6f9SAndy Whitcroft		    $line !~ /for\s*\(.*;\s+\)/) {
139322f2a2efSAndy Whitcroft			ERROR("no space before that close parenthesis ')'\n" . $herecurr);
139422f2a2efSAndy Whitcroft		}
139522f2a2efSAndy Whitcroft
13960a920b5bSAndy Whitcroft#goto labels aren't indented, allow a single space however
13974a0df2efSAndy Whitcroft		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
13980a920b5bSAndy Whitcroft		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
1399de7d4f0eSAndy Whitcroft			WARN("labels should not be indented\n" . $herecurr);
14000a920b5bSAndy Whitcroft		}
14010a920b5bSAndy Whitcroft
14020a920b5bSAndy Whitcroft# Need a space before open parenthesis after if, while etc
14034a0df2efSAndy Whitcroft		if ($line=~/\b(if|while|for|switch)\(/) {
1404de7d4f0eSAndy Whitcroft			ERROR("need a space before the open parenthesis '('\n" . $herecurr);
14050a920b5bSAndy Whitcroft		}
14060a920b5bSAndy Whitcroft
14070a920b5bSAndy Whitcroft# Check for illegal assignment in if conditional.
14088905a67cSAndy Whitcroft		if ($line =~ /\bif\s*\(/) {
14098905a67cSAndy Whitcroft			my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
14108905a67cSAndy Whitcroft
14118905a67cSAndy Whitcroft			if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) {
1412*c2fdda0dSAndy Whitcroft				ERROR("do not use assignment in if condition\n" . $herecurr);
14138905a67cSAndy Whitcroft			}
14148905a67cSAndy Whitcroft
14158905a67cSAndy Whitcroft			# Find out what is on the end of the line after the
14168905a67cSAndy Whitcroft			# conditional.
14178905a67cSAndy Whitcroft			substr($s, 0, length($c)) = '';
14188905a67cSAndy Whitcroft			$s =~ s/\n.*//g;
14198905a67cSAndy Whitcroft
14208905a67cSAndy Whitcroft			if (length($c) && $s !~ /^\s*({|;|\/\*.*\*\/)?\s*\\*\s*$/) {
14218905a67cSAndy Whitcroft				ERROR("trailing statements should be on next line\n" . $herecurr);
14228905a67cSAndy Whitcroft			}
14238905a67cSAndy Whitcroft		}
14248905a67cSAndy Whitcroft
14258905a67cSAndy Whitcroft# if and else should not have general statements after it
14268905a67cSAndy Whitcroft		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ &&
14278905a67cSAndy Whitcroft		    $1 !~ /^\s*(?:\sif|{|\\|$)/) {
14288905a67cSAndy Whitcroft			ERROR("trailing statements should be on next line\n" . $herecurr);
14290a920b5bSAndy Whitcroft		}
14300a920b5bSAndy Whitcroft
14310a920b5bSAndy Whitcroft		# Check for }<nl>else {, these must be at the same
14320a920b5bSAndy Whitcroft		# indent level to be relevant to each other.
14330a920b5bSAndy Whitcroft		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
14340a920b5bSAndy Whitcroft						$previndent == $indent) {
1435de7d4f0eSAndy Whitcroft			ERROR("else should follow close brace '}'\n" . $hereprev);
14360a920b5bSAndy Whitcroft		}
14370a920b5bSAndy Whitcroft
1438*c2fdda0dSAndy Whitcroft		if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
1439*c2fdda0dSAndy Whitcroft						$previndent == $indent) {
1440*c2fdda0dSAndy Whitcroft			my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
1441*c2fdda0dSAndy Whitcroft
1442*c2fdda0dSAndy Whitcroft			# Find out what is on the end of the line after the
1443*c2fdda0dSAndy Whitcroft			# conditional.
1444*c2fdda0dSAndy Whitcroft			substr($s, 0, length($c)) = '';
1445*c2fdda0dSAndy Whitcroft			$s =~ s/\n.*//g;
1446*c2fdda0dSAndy Whitcroft
1447*c2fdda0dSAndy Whitcroft			if ($s =~ /^\s*;/) {
1448*c2fdda0dSAndy Whitcroft				ERROR("while should follow close brace '}'\n" . $hereprev);
1449*c2fdda0dSAndy Whitcroft			}
1450*c2fdda0dSAndy Whitcroft		}
1451*c2fdda0dSAndy Whitcroft
14520a920b5bSAndy Whitcroft#studly caps, commented out until figure out how to distinguish between use of existing and adding new
14530a920b5bSAndy Whitcroft#		if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
14540a920b5bSAndy Whitcroft#		    print "No studly caps, use _\n";
14550a920b5bSAndy Whitcroft#		    print "$herecurr";
14560a920b5bSAndy Whitcroft#		    $clean = 0;
14570a920b5bSAndy Whitcroft#		}
14580a920b5bSAndy Whitcroft
14590a920b5bSAndy Whitcroft#no spaces allowed after \ in define
14600a920b5bSAndy Whitcroft		if ($line=~/\#define.*\\\s$/) {
1461de7d4f0eSAndy Whitcroft			WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
14620a920b5bSAndy Whitcroft		}
14630a920b5bSAndy Whitcroft
1464653d4876SAndy Whitcroft#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
1465653d4876SAndy Whitcroft		if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
14666c72ffaaSAndy Whitcroft			my $checkfile = "$root/include/linux/$1.h";
14676c72ffaaSAndy Whitcroft			if (-f $checkfile && $1 ne 'irq.h') {
1468de7d4f0eSAndy Whitcroft				CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
1469de7d4f0eSAndy Whitcroft					$herecurr);
14700a920b5bSAndy Whitcroft			}
14710a920b5bSAndy Whitcroft		}
14720a920b5bSAndy Whitcroft
1473653d4876SAndy Whitcroft# multi-statement macros should be enclosed in a do while loop, grab the
1474653d4876SAndy Whitcroft# first statement and ensure its the whole macro if its not enclosed
1475653d4876SAndy Whitcroft# in a known goot container
14769c0ca6f9SAndy Whitcroft		if ($prevline =~ /\#define.*\\/ &&
14779c0ca6f9SAndy Whitcroft		   $prevline !~/(?:do\s+{|\(\{|\{)/ &&
14789c0ca6f9SAndy Whitcroft		   $line !~ /(?:do\s+{|\(\{|\{)/ &&
14799c0ca6f9SAndy Whitcroft		   $line !~ /^.\s*$Declare\s/) {
1480653d4876SAndy Whitcroft			# Grab the first statement, if that is the entire macro
1481653d4876SAndy Whitcroft			# its ok.  This may start either on the #define line
1482653d4876SAndy Whitcroft			# or the one below.
1483d8aaf121SAndy Whitcroft			my $ln = $linenr;
1484d8aaf121SAndy Whitcroft			my $cnt = $realcnt;
1485f0a594c1SAndy Whitcroft			my $off = 0;
1486653d4876SAndy Whitcroft
1487f0a594c1SAndy Whitcroft			# If the macro starts on the define line start
1488f0a594c1SAndy Whitcroft			# grabbing the statement after the identifier
1489f0a594c1SAndy Whitcroft			$prevline =~ m{^(.#\s*define\s*$Ident(?:\([^\)]*\))?\s*)(.*)\\\s*$};
1490f0a594c1SAndy Whitcroft			##print "1<$1> 2<$2>\n";
149122f2a2efSAndy Whitcroft			if (defined $2 && $2 ne '') {
1492f0a594c1SAndy Whitcroft				$off = length($1);
1493d8aaf121SAndy Whitcroft				$ln--;
1494d8aaf121SAndy Whitcroft				$cnt++;
14958905a67cSAndy Whitcroft				while ($lines[$ln - 1] =~ /^-/) {
14968905a67cSAndy Whitcroft					$ln--;
14978905a67cSAndy Whitcroft					$cnt++;
14988905a67cSAndy Whitcroft				}
1499d8aaf121SAndy Whitcroft			}
1500f0a594c1SAndy Whitcroft			my @ctx = ctx_statement($ln, $cnt, $off);
1501de7d4f0eSAndy Whitcroft			my $ctx_ln = $ln + $#ctx + 1;
1502de7d4f0eSAndy Whitcroft			my $ctx = join("\n", @ctx);
1503de7d4f0eSAndy Whitcroft
1504de7d4f0eSAndy Whitcroft			# Pull in any empty extension lines.
1505de7d4f0eSAndy Whitcroft			while ($ctx =~ /\\$/ &&
1506de7d4f0eSAndy Whitcroft			       $lines[$ctx_ln - 1] =~ /^.\s*(?:\\)?$/) {
1507de7d4f0eSAndy Whitcroft				$ctx .= $lines[$ctx_ln - 1];
1508de7d4f0eSAndy Whitcroft				$ctx_ln++;
1509de7d4f0eSAndy Whitcroft			}
1510d8aaf121SAndy Whitcroft
1511d8aaf121SAndy Whitcroft			if ($ctx =~ /\\$/) {
1512d8aaf121SAndy Whitcroft				if ($ctx =~ /;/) {
1513de7d4f0eSAndy Whitcroft					ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
1514d8aaf121SAndy Whitcroft				} else {
1515de7d4f0eSAndy Whitcroft					ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
1516d8aaf121SAndy Whitcroft				}
15170a920b5bSAndy Whitcroft			}
1518653d4876SAndy Whitcroft		}
15190a920b5bSAndy Whitcroft
1520f0a594c1SAndy Whitcroft# check for redundant bracing round if etc
1521f0a594c1SAndy Whitcroft		if ($line =~ /\b(if|while|for|else)\b/) {
1522f0a594c1SAndy Whitcroft			# Locate the end of the opening statement.
1523f0a594c1SAndy Whitcroft			my @control = ctx_statement($linenr, $realcnt, 0);
1524f0a594c1SAndy Whitcroft			my $nr = $linenr + (scalar(@control) - 1);
1525f0a594c1SAndy Whitcroft			my $cnt = $realcnt - (scalar(@control) - 1);
1526f0a594c1SAndy Whitcroft
1527f0a594c1SAndy Whitcroft			my $off = $realcnt - $cnt;
1528f0a594c1SAndy Whitcroft			#print "$off: line<$line>end<" . $lines[$nr - 1] . ">\n";
1529f0a594c1SAndy Whitcroft
1530f0a594c1SAndy Whitcroft			# If this is is a braced statement group check it
1531f0a594c1SAndy Whitcroft			if ($lines[$nr - 1] =~ /{\s*$/) {
1532f0a594c1SAndy Whitcroft				my ($lvl, @block) = ctx_block_level($nr, $cnt);
1533f0a594c1SAndy Whitcroft
15348905a67cSAndy Whitcroft				my $stmt = join("\n", @block);
15358905a67cSAndy Whitcroft				# Drop the diff line leader.
15368905a67cSAndy Whitcroft				$stmt =~ s/\n./\n/g;
15378905a67cSAndy Whitcroft				# Drop the code outside the block.
15388905a67cSAndy Whitcroft				$stmt =~ s/(^[^{]*){\s*//;
153922f2a2efSAndy Whitcroft				my $before = $1;
15408905a67cSAndy Whitcroft				$stmt =~ s/\s*}([^}]*$)//;
154122f2a2efSAndy Whitcroft				my $after = $1;
1542f0a594c1SAndy Whitcroft
1543f0a594c1SAndy Whitcroft				#print "block<" . join(' ', @block) . "><" . scalar(@block) . ">\n";
1544f0a594c1SAndy Whitcroft				#print "stmt<$stmt>\n\n";
1545f0a594c1SAndy Whitcroft
15468905a67cSAndy Whitcroft				# Count the newlines, if there is only one
15478905a67cSAndy Whitcroft				# then the block should not have {}'s.
15488905a67cSAndy Whitcroft				my @lines = ($stmt =~ /\n/g);
1549*c2fdda0dSAndy Whitcroft				my @statements = ($stmt =~ /;/g);
15508905a67cSAndy Whitcroft				#print "lines<" . scalar(@lines) . ">\n";
1551*c2fdda0dSAndy Whitcroft				#print "statements<" . scalar(@statements) . ">\n";
15528905a67cSAndy Whitcroft				if ($lvl == 0 && scalar(@lines) == 0 &&
1553*c2fdda0dSAndy Whitcroft				    scalar(@statements) < 2 &&
155422f2a2efSAndy Whitcroft				    $stmt !~ /{/ && $stmt !~ /\bif\b/ &&
155522f2a2efSAndy Whitcroft				    $before !~ /}/ && $after !~ /{/) {
1556f0a594c1SAndy Whitcroft				    	my $herectx = "$here\n" . join("\n", @control, @block[1 .. $#block]) . "\n";
1557f0a594c1SAndy Whitcroft				    	shift(@block);
155822f2a2efSAndy Whitcroft					WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
1559f0a594c1SAndy Whitcroft				}
1560f0a594c1SAndy Whitcroft			}
1561f0a594c1SAndy Whitcroft		}
1562f0a594c1SAndy Whitcroft
1563653d4876SAndy Whitcroft# don't include deprecated include files (uses RAW line)
15644a0df2efSAndy Whitcroft		for my $inc (@dep_includes) {
1565653d4876SAndy Whitcroft			if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
1566de7d4f0eSAndy Whitcroft				ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
15670a920b5bSAndy Whitcroft			}
15680a920b5bSAndy Whitcroft		}
15690a920b5bSAndy Whitcroft
15704a0df2efSAndy Whitcroft# don't use deprecated functions
15714a0df2efSAndy Whitcroft		for my $func (@dep_functions) {
157200df344fSAndy Whitcroft			if ($line =~ /\b$func\b/) {
1573de7d4f0eSAndy Whitcroft				ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
15744a0df2efSAndy Whitcroft			}
15754a0df2efSAndy Whitcroft		}
15764a0df2efSAndy Whitcroft
15774a0df2efSAndy Whitcroft# no volatiles please
15786c72ffaaSAndy Whitcroft		my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
15796c72ffaaSAndy Whitcroft		if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
1580de7d4f0eSAndy Whitcroft			WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
15814a0df2efSAndy Whitcroft		}
15824a0df2efSAndy Whitcroft
15839c0ca6f9SAndy Whitcroft# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
15849c0ca6f9SAndy Whitcroft		if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
15859c0ca6f9SAndy Whitcroft			ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
15869c0ca6f9SAndy Whitcroft		}
15879c0ca6f9SAndy Whitcroft
158800df344fSAndy Whitcroft# warn about #if 0
158900df344fSAndy Whitcroft		if ($line =~ /^.#\s*if\s+0\b/) {
1590de7d4f0eSAndy Whitcroft			CHK("if this code is redundant consider removing it\n" .
1591de7d4f0eSAndy Whitcroft				$herecurr);
15924a0df2efSAndy Whitcroft		}
15934a0df2efSAndy Whitcroft
1594f0a594c1SAndy Whitcroft# check for needless kfree() checks
1595f0a594c1SAndy Whitcroft		if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
1596f0a594c1SAndy Whitcroft			my $expr = $1;
1597f0a594c1SAndy Whitcroft			if ($line =~ /\bkfree\(\Q$expr\E\);/) {
1598f0a594c1SAndy Whitcroft				WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
1599f0a594c1SAndy Whitcroft			}
1600f0a594c1SAndy Whitcroft		}
1601f0a594c1SAndy Whitcroft
160200df344fSAndy Whitcroft# warn about #ifdefs in C files
160300df344fSAndy Whitcroft#		if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
160400df344fSAndy Whitcroft#			print "#ifdef in C files should be avoided\n";
160500df344fSAndy Whitcroft#			print "$herecurr";
160600df344fSAndy Whitcroft#			$clean = 0;
160700df344fSAndy Whitcroft#		}
160800df344fSAndy Whitcroft
160922f2a2efSAndy Whitcroft# warn about spacing in #ifdefs
161022f2a2efSAndy Whitcroft		if ($line =~ /^.#\s*(ifdef|ifndef|elif)\s\s+/) {
161122f2a2efSAndy Whitcroft			ERROR("exactly one space required after that #$1\n" . $herecurr);
161222f2a2efSAndy Whitcroft		}
161322f2a2efSAndy Whitcroft
16144a0df2efSAndy Whitcroft# check for spinlock_t definitions without a comment.
16154a0df2efSAndy Whitcroft		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
16164a0df2efSAndy Whitcroft			my $which = $1;
16174a0df2efSAndy Whitcroft			if (!ctx_has_comment($first_line, $linenr)) {
1618de7d4f0eSAndy Whitcroft				CHK("$1 definition without comment\n" . $herecurr);
16194a0df2efSAndy Whitcroft			}
16204a0df2efSAndy Whitcroft		}
16214a0df2efSAndy Whitcroft# check for memory barriers without a comment.
16224a0df2efSAndy Whitcroft		if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
16234a0df2efSAndy Whitcroft			if (!ctx_has_comment($first_line, $linenr)) {
1624de7d4f0eSAndy Whitcroft				CHK("memory barrier without comment\n" . $herecurr);
16254a0df2efSAndy Whitcroft			}
16264a0df2efSAndy Whitcroft		}
16274a0df2efSAndy Whitcroft# check of hardware specific defines
162822f2a2efSAndy Whitcroft		if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
1629de7d4f0eSAndy Whitcroft			CHK("architecture specific defines should be avoided\n" .  $herecurr);
16300a920b5bSAndy Whitcroft		}
1631653d4876SAndy Whitcroft
1632de7d4f0eSAndy Whitcroft# check the location of the inline attribute, that it is between
1633de7d4f0eSAndy Whitcroft# storage class and type.
16349c0ca6f9SAndy Whitcroft		if ($line =~ /\b$Type\s+$Inline\b/ ||
16359c0ca6f9SAndy Whitcroft		    $line =~ /\b$Inline\s+$Storage\b/) {
1636de7d4f0eSAndy Whitcroft			ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
1637de7d4f0eSAndy Whitcroft		}
1638de7d4f0eSAndy Whitcroft
16398905a67cSAndy Whitcroft# Check for __inline__ and __inline, prefer inline
16408905a67cSAndy Whitcroft		if ($line =~ /\b(__inline__|__inline)\b/) {
16418905a67cSAndy Whitcroft			WARN("plain inline is preferred over $1\n" . $herecurr);
16428905a67cSAndy Whitcroft		}
16438905a67cSAndy Whitcroft
1644de7d4f0eSAndy Whitcroft# check for new externs in .c files.
1645de7d4f0eSAndy Whitcroft		if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
1646de7d4f0eSAndy Whitcroft			WARN("externs should be avoided in .c files\n" .  $herecurr);
1647de7d4f0eSAndy Whitcroft		}
1648de7d4f0eSAndy Whitcroft
1649de7d4f0eSAndy Whitcroft# checks for new __setup's
1650de7d4f0eSAndy Whitcroft		if ($rawline =~ /\b__setup\("([^"]*)"/) {
1651de7d4f0eSAndy Whitcroft			my $name = $1;
1652de7d4f0eSAndy Whitcroft
1653de7d4f0eSAndy Whitcroft			if (!grep(/$name/, @setup_docs)) {
1654de7d4f0eSAndy Whitcroft				CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
1655de7d4f0eSAndy Whitcroft			}
1656653d4876SAndy Whitcroft		}
16579c0ca6f9SAndy Whitcroft
16589c0ca6f9SAndy Whitcroft# check for pointless casting of kmalloc return
16599c0ca6f9SAndy Whitcroft		if ($line =~ /\*\s*\)\s*k[czm]alloc\b/) {
16609c0ca6f9SAndy Whitcroft			WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
16619c0ca6f9SAndy Whitcroft		}
16620a920b5bSAndy Whitcroft	}
16630a920b5bSAndy Whitcroft
16648905a67cSAndy Whitcroft	# In mailback mode only produce a report in the negative, for
16658905a67cSAndy Whitcroft	# things that appear to be patches.
16668905a67cSAndy Whitcroft	if ($mailback && ($clean == 1 || !$is_patch)) {
16678905a67cSAndy Whitcroft		exit(0);
16688905a67cSAndy Whitcroft	}
16698905a67cSAndy Whitcroft
16708905a67cSAndy Whitcroft	# This is not a patch, and we are are in 'no-patch' mode so
16718905a67cSAndy Whitcroft	# just keep quiet.
16728905a67cSAndy Whitcroft	if (!$chk_patch && !$is_patch) {
16738905a67cSAndy Whitcroft		exit(0);
16748905a67cSAndy Whitcroft	}
16758905a67cSAndy Whitcroft
16768905a67cSAndy Whitcroft	if (!$is_patch) {
1677de7d4f0eSAndy Whitcroft		ERROR("Does not appear to be a unified-diff format patch\n");
16780a920b5bSAndy Whitcroft	}
16790a920b5bSAndy Whitcroft	if ($is_patch && $chk_signoff && $signoff == 0) {
1680de7d4f0eSAndy Whitcroft		ERROR("Missing Signed-off-by: line(s)\n");
16810a920b5bSAndy Whitcroft	}
16820a920b5bSAndy Whitcroft
1683f0a594c1SAndy Whitcroft	print report_dump();
16848905a67cSAndy Whitcroft	if ($summary) {
16856c72ffaaSAndy Whitcroft		print "total: $cnt_error errors, $cnt_warn warnings, " .
16866c72ffaaSAndy Whitcroft			(($check)? "$cnt_chk checks, " : "") .
16876c72ffaaSAndy Whitcroft			"$cnt_lines lines checked\n";
16888905a67cSAndy Whitcroft		print "\n" if ($quiet == 0);
16896c72ffaaSAndy Whitcroft	}
16908905a67cSAndy Whitcroft
16910a920b5bSAndy Whitcroft	if ($clean == 1 && $quiet == 0) {
1692*c2fdda0dSAndy Whitcroft		print "$vname has no obvious style problems and is ready for submission.\n"
16930a920b5bSAndy Whitcroft	}
16940a920b5bSAndy Whitcroft	if ($clean == 0 && $quiet == 0) {
1695*c2fdda0dSAndy Whitcroft		print "$vname has style problems, please review.  If any of these errors\n";
16960a920b5bSAndy Whitcroft		print "are false positives report them to the maintainer, see\n";
16970a920b5bSAndy Whitcroft		print "CHECKPATCH in MAINTAINERS.\n";
16980a920b5bSAndy Whitcroft	}
16990a920b5bSAndy Whitcroft	return $clean;
17000a920b5bSAndy Whitcroft}
1701