xref: /linux-6.15/scripts/checkpatch.pl (revision 9c0ca6f9)
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*9c0ca6f9SAndy Whitcroftmy $V = '0.10';
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;
210a920b5bSAndy WhitcroftGetOptions(
220a920b5bSAndy Whitcroft	'q|quiet'	=> \$quiet,
230a920b5bSAndy Whitcroft	'tree!'		=> \$tree,
240a920b5bSAndy Whitcroft	'signoff!'	=> \$chk_signoff,
250a920b5bSAndy Whitcroft	'patch!'	=> \$chk_patch,
26653d4876SAndy Whitcroft	'test-type!'	=> \$tst_type,
270a920b5bSAndy Whitcroft) or exit;
280a920b5bSAndy Whitcroft
290a920b5bSAndy Whitcroftmy $exit = 0;
300a920b5bSAndy Whitcroft
310a920b5bSAndy Whitcroftif ($#ARGV < 0) {
3200df344fSAndy Whitcroft	print "usage: $P [options] patchfile\n";
330a920b5bSAndy Whitcroft	print "version: $V\n";
340a920b5bSAndy Whitcroft	print "options: -q           => quiet\n";
350a920b5bSAndy Whitcroft	print "         --no-tree    => run without a kernel tree\n";
360a920b5bSAndy Whitcroft	exit(1);
370a920b5bSAndy Whitcroft}
380a920b5bSAndy Whitcroft
390a920b5bSAndy Whitcroftif ($tree && !top_of_kernel_tree()) {
400a920b5bSAndy Whitcroft	print "Must be run from the top-level dir. of a kernel tree\n";
410a920b5bSAndy Whitcroft	exit(2);
420a920b5bSAndy Whitcroft}
430a920b5bSAndy Whitcroft
444a0df2efSAndy Whitcroftmy @dep_includes = ();
454a0df2efSAndy Whitcroftmy @dep_functions = ();
460a920b5bSAndy Whitcroftmy $removal = 'Documentation/feature-removal-schedule.txt';
470a920b5bSAndy Whitcroftif ($tree && -f $removal) {
480a920b5bSAndy Whitcroft	open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
490a920b5bSAndy Whitcroft	while (<REMOVE>) {
50f0a594c1SAndy Whitcroft		if (/^Check:\s+(.*\S)/) {
51f0a594c1SAndy Whitcroft			for my $entry (split(/[, ]+/, $1)) {
52f0a594c1SAndy Whitcroft				if ($entry =~ m@include/(.*)@) {
534a0df2efSAndy Whitcroft					push(@dep_includes, $1);
544a0df2efSAndy Whitcroft
55f0a594c1SAndy Whitcroft				} elsif ($entry !~ m@/@) {
56f0a594c1SAndy Whitcroft					push(@dep_functions, $entry);
57f0a594c1SAndy Whitcroft				}
584a0df2efSAndy Whitcroft			}
590a920b5bSAndy Whitcroft		}
600a920b5bSAndy Whitcroft	}
610a920b5bSAndy Whitcroft}
620a920b5bSAndy Whitcroft
6300df344fSAndy Whitcroftmy @rawlines = ();
640a920b5bSAndy Whitcroftwhile (<>) {
650a920b5bSAndy Whitcroft	chomp;
6600df344fSAndy Whitcroft	push(@rawlines, $_);
670a920b5bSAndy Whitcroft	if (eof(ARGV)) {
6800df344fSAndy Whitcroft		if (!process($ARGV, @rawlines)) {
690a920b5bSAndy Whitcroft			$exit = 1;
700a920b5bSAndy Whitcroft		}
7100df344fSAndy Whitcroft		@rawlines = ();
720a920b5bSAndy Whitcroft	}
730a920b5bSAndy Whitcroft}
740a920b5bSAndy Whitcroft
750a920b5bSAndy Whitcroftexit($exit);
760a920b5bSAndy Whitcroft
770a920b5bSAndy Whitcroftsub top_of_kernel_tree {
780a920b5bSAndy Whitcroft	if ((-f "COPYING") && (-f "CREDITS") && (-f "Kbuild") &&
790a920b5bSAndy Whitcroft	    (-f "MAINTAINERS") && (-f "Makefile") && (-f "README") &&
800a920b5bSAndy Whitcroft	    (-d "Documentation") && (-d "arch") && (-d "include") &&
810a920b5bSAndy Whitcroft	    (-d "drivers") && (-d "fs") && (-d "init") && (-d "ipc") &&
820a920b5bSAndy Whitcroft	    (-d "kernel") && (-d "lib") && (-d "scripts")) {
830a920b5bSAndy Whitcroft		return 1;
840a920b5bSAndy Whitcroft	}
850a920b5bSAndy Whitcroft	return 0;
860a920b5bSAndy Whitcroft}
870a920b5bSAndy Whitcroft
880a920b5bSAndy Whitcroftsub expand_tabs {
890a920b5bSAndy Whitcroft	my ($str) = @_;
900a920b5bSAndy Whitcroft
910a920b5bSAndy Whitcroft	my $res = '';
920a920b5bSAndy Whitcroft	my $n = 0;
930a920b5bSAndy Whitcroft	for my $c (split(//, $str)) {
940a920b5bSAndy Whitcroft		if ($c eq "\t") {
950a920b5bSAndy Whitcroft			$res .= ' ';
960a920b5bSAndy Whitcroft			$n++;
970a920b5bSAndy Whitcroft			for (; ($n % 8) != 0; $n++) {
980a920b5bSAndy Whitcroft				$res .= ' ';
990a920b5bSAndy Whitcroft			}
1000a920b5bSAndy Whitcroft			next;
1010a920b5bSAndy Whitcroft		}
1020a920b5bSAndy Whitcroft		$res .= $c;
1030a920b5bSAndy Whitcroft		$n++;
1040a920b5bSAndy Whitcroft	}
1050a920b5bSAndy Whitcroft
1060a920b5bSAndy Whitcroft	return $res;
1070a920b5bSAndy Whitcroft}
1080a920b5bSAndy Whitcroft
1094a0df2efSAndy Whitcroftsub line_stats {
1104a0df2efSAndy Whitcroft	my ($line) = @_;
1114a0df2efSAndy Whitcroft
1124a0df2efSAndy Whitcroft	# Drop the diff line leader and expand tabs
1134a0df2efSAndy Whitcroft	$line =~ s/^.//;
1144a0df2efSAndy Whitcroft	$line = expand_tabs($line);
1154a0df2efSAndy Whitcroft
1164a0df2efSAndy Whitcroft	# Pick the indent from the front of the line.
1174a0df2efSAndy Whitcroft	my ($white) = ($line =~ /^(\s*)/);
1184a0df2efSAndy Whitcroft
1194a0df2efSAndy Whitcroft	return (length($line), length($white));
1204a0df2efSAndy Whitcroft}
1214a0df2efSAndy Whitcroft
12200df344fSAndy Whitcroftsub sanitise_line {
12300df344fSAndy Whitcroft	my ($line) = @_;
12400df344fSAndy Whitcroft
12500df344fSAndy Whitcroft	my $res = '';
12600df344fSAndy Whitcroft	my $l = '';
12700df344fSAndy Whitcroft
12800df344fSAndy Whitcroft	my $quote = '';
12900df344fSAndy Whitcroft
13000df344fSAndy Whitcroft	foreach my $c (split(//, $line)) {
13100df344fSAndy Whitcroft		if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
13200df344fSAndy Whitcroft			if ($quote eq '') {
13300df344fSAndy Whitcroft				$quote = $c;
13400df344fSAndy Whitcroft				$res .= $c;
13500df344fSAndy Whitcroft				$l = $c;
13600df344fSAndy Whitcroft				next;
13700df344fSAndy Whitcroft			} elsif ($quote eq $c) {
13800df344fSAndy Whitcroft				$quote = '';
13900df344fSAndy Whitcroft			}
14000df344fSAndy Whitcroft		}
14100df344fSAndy Whitcroft		if ($quote && $c ne "\t") {
14200df344fSAndy Whitcroft			$res .= "X";
14300df344fSAndy Whitcroft		} else {
14400df344fSAndy Whitcroft			$res .= $c;
14500df344fSAndy Whitcroft		}
14600df344fSAndy Whitcroft
14700df344fSAndy Whitcroft		$l = $c;
14800df344fSAndy Whitcroft	}
14900df344fSAndy Whitcroft
15000df344fSAndy Whitcroft	return $res;
15100df344fSAndy Whitcroft}
15200df344fSAndy Whitcroft
1534a0df2efSAndy Whitcroftsub ctx_block_get {
154f0a594c1SAndy Whitcroft	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
1554a0df2efSAndy Whitcroft	my $line;
1564a0df2efSAndy Whitcroft	my $start = $linenr - 1;
1574a0df2efSAndy Whitcroft	my $blk = '';
1584a0df2efSAndy Whitcroft	my @o;
1594a0df2efSAndy Whitcroft	my @c;
1604a0df2efSAndy Whitcroft	my @res = ();
1614a0df2efSAndy Whitcroft
162f0a594c1SAndy Whitcroft	my $level = 0;
16300df344fSAndy Whitcroft	for ($line = $start; $remain > 0; $line++) {
16400df344fSAndy Whitcroft		next if ($rawlines[$line] =~ /^-/);
16500df344fSAndy Whitcroft		$remain--;
16600df344fSAndy Whitcroft
16700df344fSAndy Whitcroft		$blk .= $rawlines[$line];
168f0a594c1SAndy Whitcroft		foreach my $c (split(//, $rawlines[$line])) {
169f0a594c1SAndy Whitcroft			##print "C<$c>L<$level><$open$close>O<$off>\n";
170f0a594c1SAndy Whitcroft			if ($off > 0) {
171f0a594c1SAndy Whitcroft				$off--;
172f0a594c1SAndy Whitcroft				next;
173f0a594c1SAndy Whitcroft			}
1744a0df2efSAndy Whitcroft
175f0a594c1SAndy Whitcroft			if ($c eq $close && $level > 0) {
176f0a594c1SAndy Whitcroft				$level--;
177f0a594c1SAndy Whitcroft				last if ($level == 0);
178f0a594c1SAndy Whitcroft			} elsif ($c eq $open) {
179f0a594c1SAndy Whitcroft				$level++;
180f0a594c1SAndy Whitcroft			}
181f0a594c1SAndy Whitcroft		}
1824a0df2efSAndy Whitcroft
183f0a594c1SAndy Whitcroft		if (!$outer || $level <= 1) {
18400df344fSAndy Whitcroft			push(@res, $rawlines[$line]);
1854a0df2efSAndy Whitcroft		}
1864a0df2efSAndy Whitcroft
187f0a594c1SAndy Whitcroft		last if ($level == 0);
1884a0df2efSAndy Whitcroft	}
1894a0df2efSAndy Whitcroft
190f0a594c1SAndy Whitcroft	return ($level, @res);
1914a0df2efSAndy Whitcroft}
1924a0df2efSAndy Whitcroftsub ctx_block_outer {
1934a0df2efSAndy Whitcroft	my ($linenr, $remain) = @_;
1944a0df2efSAndy Whitcroft
195f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
196f0a594c1SAndy Whitcroft	return @r;
1974a0df2efSAndy Whitcroft}
1984a0df2efSAndy Whitcroftsub ctx_block {
1994a0df2efSAndy Whitcroft	my ($linenr, $remain) = @_;
2004a0df2efSAndy Whitcroft
201f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
202f0a594c1SAndy Whitcroft	return @r;
203653d4876SAndy Whitcroft}
204653d4876SAndy Whitcroftsub ctx_statement {
205f0a594c1SAndy Whitcroft	my ($linenr, $remain, $off) = @_;
206f0a594c1SAndy Whitcroft
207f0a594c1SAndy Whitcroft	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
208f0a594c1SAndy Whitcroft	return @r;
209f0a594c1SAndy Whitcroft}
210f0a594c1SAndy Whitcroftsub ctx_block_level {
211653d4876SAndy Whitcroft	my ($linenr, $remain) = @_;
212653d4876SAndy Whitcroft
213f0a594c1SAndy Whitcroft	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
2144a0df2efSAndy Whitcroft}
215*9c0ca6f9SAndy Whitcroftsub ctx_statement_level {
216*9c0ca6f9SAndy Whitcroft	my ($linenr, $remain, $off) = @_;
217*9c0ca6f9SAndy Whitcroft
218*9c0ca6f9SAndy Whitcroft	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
219*9c0ca6f9SAndy Whitcroft}
2204a0df2efSAndy Whitcroft
2214a0df2efSAndy Whitcroftsub ctx_locate_comment {
2224a0df2efSAndy Whitcroft	my ($first_line, $end_line) = @_;
2234a0df2efSAndy Whitcroft
2244a0df2efSAndy Whitcroft	# Catch a comment on the end of the line itself.
22500df344fSAndy Whitcroft	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
2264a0df2efSAndy Whitcroft	return $current_comment if (defined $current_comment);
2274a0df2efSAndy Whitcroft
2284a0df2efSAndy Whitcroft	# Look through the context and try and figure out if there is a
2294a0df2efSAndy Whitcroft	# comment.
2304a0df2efSAndy Whitcroft	my $in_comment = 0;
2314a0df2efSAndy Whitcroft	$current_comment = '';
2324a0df2efSAndy Whitcroft	for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
23300df344fSAndy Whitcroft		my $line = $rawlines[$linenr - 1];
23400df344fSAndy Whitcroft		#warn "           $line\n";
2354a0df2efSAndy Whitcroft		if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
2364a0df2efSAndy Whitcroft			$in_comment = 1;
2374a0df2efSAndy Whitcroft		}
2384a0df2efSAndy Whitcroft		if ($line =~ m@/\*@) {
2394a0df2efSAndy Whitcroft			$in_comment = 1;
2404a0df2efSAndy Whitcroft		}
2414a0df2efSAndy Whitcroft		if (!$in_comment && $current_comment ne '') {
2424a0df2efSAndy Whitcroft			$current_comment = '';
2434a0df2efSAndy Whitcroft		}
2444a0df2efSAndy Whitcroft		$current_comment .= $line . "\n" if ($in_comment);
2454a0df2efSAndy Whitcroft		if ($line =~ m@\*/@) {
2464a0df2efSAndy Whitcroft			$in_comment = 0;
2474a0df2efSAndy Whitcroft		}
2484a0df2efSAndy Whitcroft	}
2494a0df2efSAndy Whitcroft
2504a0df2efSAndy Whitcroft	chomp($current_comment);
2514a0df2efSAndy Whitcroft	return($current_comment);
2524a0df2efSAndy Whitcroft}
2534a0df2efSAndy Whitcroftsub ctx_has_comment {
2544a0df2efSAndy Whitcroft	my ($first_line, $end_line) = @_;
2554a0df2efSAndy Whitcroft	my $cmt = ctx_locate_comment($first_line, $end_line);
2564a0df2efSAndy Whitcroft
25700df344fSAndy Whitcroft	##print "LINE: $rawlines[$end_line - 1 ]\n";
2584a0df2efSAndy Whitcroft	##print "CMMT: $cmt\n";
2594a0df2efSAndy Whitcroft
2604a0df2efSAndy Whitcroft	return ($cmt ne '');
2614a0df2efSAndy Whitcroft}
2624a0df2efSAndy Whitcroft
263*9c0ca6f9SAndy Whitcroftsub ctx_expr_before {
264*9c0ca6f9SAndy Whitcroft	my ($line) = @_;
265*9c0ca6f9SAndy Whitcroft
266*9c0ca6f9SAndy Whitcroft	##print "CHECK<$line>\n";
267*9c0ca6f9SAndy Whitcroft
268*9c0ca6f9SAndy Whitcroft	my $pos = length($line) - 1;
269*9c0ca6f9SAndy Whitcroft	my $count = 0;
270*9c0ca6f9SAndy Whitcroft	my $c;
271*9c0ca6f9SAndy Whitcroft
272*9c0ca6f9SAndy Whitcroft	for (; $pos >= 0; $pos--) {
273*9c0ca6f9SAndy Whitcroft		$c = substr($line, $pos, 1);
274*9c0ca6f9SAndy Whitcroft		##print "CHECK: c<$c> count<$count>\n";
275*9c0ca6f9SAndy Whitcroft		if ($c eq ')') {
276*9c0ca6f9SAndy Whitcroft			$count++;
277*9c0ca6f9SAndy Whitcroft		} elsif ($c eq '(') {
278*9c0ca6f9SAndy Whitcroft			last if (--$count == 0);
279*9c0ca6f9SAndy Whitcroft		}
280*9c0ca6f9SAndy Whitcroft	}
281*9c0ca6f9SAndy Whitcroft
282*9c0ca6f9SAndy Whitcroft	##print "CHECK: result<" . substr($line, 0, $pos) . ">\n";
283*9c0ca6f9SAndy Whitcroft
284*9c0ca6f9SAndy Whitcroft	return substr($line, 0, $pos);
285*9c0ca6f9SAndy Whitcroft}
286*9c0ca6f9SAndy Whitcroft
2870a920b5bSAndy Whitcroftsub cat_vet {
2880a920b5bSAndy Whitcroft	my ($vet) = @_;
289*9c0ca6f9SAndy Whitcroft	my ($res, $coded);
2900a920b5bSAndy Whitcroft
291*9c0ca6f9SAndy Whitcroft	$res = '';
292*9c0ca6f9SAndy Whitcroft	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]])/g) {
293*9c0ca6f9SAndy Whitcroft		$coded = sprintf("^%c", unpack('C', $2) + 64);
294*9c0ca6f9SAndy Whitcroft		$res .= $1 . $coded;
295*9c0ca6f9SAndy Whitcroft	}
296*9c0ca6f9SAndy Whitcroft	$res =~ s/$/\$/;
2970a920b5bSAndy Whitcroft
298*9c0ca6f9SAndy Whitcroft	return $res;
2990a920b5bSAndy Whitcroft}
3000a920b5bSAndy Whitcroft
301f0a594c1SAndy Whitcroftmy @report = ();
302f0a594c1SAndy Whitcroftsub report {
303f0a594c1SAndy Whitcroft	push(@report, $_[0]);
304f0a594c1SAndy Whitcroft}
305f0a594c1SAndy Whitcroftsub report_dump {
306f0a594c1SAndy Whitcroft	@report;
307f0a594c1SAndy Whitcroft}
308de7d4f0eSAndy Whitcroftsub ERROR {
309f0a594c1SAndy Whitcroft	report("ERROR: $_[0]\n");
310de7d4f0eSAndy Whitcroft	our $clean = 0;
311de7d4f0eSAndy Whitcroft}
312de7d4f0eSAndy Whitcroftsub WARN {
313f0a594c1SAndy Whitcroft	report("WARNING: $_[0]\n");
314de7d4f0eSAndy Whitcroft	our $clean = 0;
315de7d4f0eSAndy Whitcroft}
316de7d4f0eSAndy Whitcroftsub CHK {
317f0a594c1SAndy Whitcroft	report("CHECK: $_[0]\n");
318de7d4f0eSAndy Whitcroft	our $clean = 0;
319de7d4f0eSAndy Whitcroft}
320de7d4f0eSAndy Whitcroft
3210a920b5bSAndy Whitcroftsub process {
3220a920b5bSAndy Whitcroft	my $filename = shift;
3230a920b5bSAndy Whitcroft	my @lines = @_;
3240a920b5bSAndy Whitcroft
3250a920b5bSAndy Whitcroft	my $linenr=0;
3260a920b5bSAndy Whitcroft	my $prevline="";
3270a920b5bSAndy Whitcroft	my $stashline="";
3280a920b5bSAndy Whitcroft
3294a0df2efSAndy Whitcroft	my $length;
3300a920b5bSAndy Whitcroft	my $indent;
3310a920b5bSAndy Whitcroft	my $previndent=0;
3320a920b5bSAndy Whitcroft	my $stashindent=0;
3330a920b5bSAndy Whitcroft
334de7d4f0eSAndy Whitcroft	our $clean = 1;
3350a920b5bSAndy Whitcroft	my $signoff = 0;
3360a920b5bSAndy Whitcroft	my $is_patch = 0;
3370a920b5bSAndy Whitcroft
3380a920b5bSAndy Whitcroft	# Trace the real file/line as we go.
3390a920b5bSAndy Whitcroft	my $realfile = '';
3400a920b5bSAndy Whitcroft	my $realline = 0;
3410a920b5bSAndy Whitcroft	my $realcnt = 0;
3420a920b5bSAndy Whitcroft	my $here = '';
3430a920b5bSAndy Whitcroft	my $in_comment = 0;
3440a920b5bSAndy Whitcroft	my $first_line = 0;
3450a920b5bSAndy Whitcroft
346d8aaf121SAndy Whitcroft	my $Ident	= qr{[A-Za-z\d_]+};
347*9c0ca6f9SAndy Whitcroft	my $Storage	= qr{extern|static|asmlinkage};
348*9c0ca6f9SAndy Whitcroft	my $Sparse	= qr{
349*9c0ca6f9SAndy Whitcroft				__user|
350*9c0ca6f9SAndy Whitcroft				__kernel|
351*9c0ca6f9SAndy Whitcroft				__force|
352*9c0ca6f9SAndy Whitcroft				__iomem|
353*9c0ca6f9SAndy Whitcroft				__must_check|
354*9c0ca6f9SAndy Whitcroft				__init_refok|
355*9c0ca6f9SAndy Whitcroft				fastcall
356*9c0ca6f9SAndy Whitcroft			}x;
357*9c0ca6f9SAndy Whitcroft	my $Inline	= qr{inline|__always_inline|noinline};
358d8aaf121SAndy Whitcroft	my $NonptrType	= qr{
359d8aaf121SAndy Whitcroft				\b
360d8aaf121SAndy Whitcroft				(?:const\s+)?
361d8aaf121SAndy Whitcroft				(?:unsigned\s+)?
362d8aaf121SAndy Whitcroft				(?:
363d8aaf121SAndy Whitcroft					void|
364d8aaf121SAndy Whitcroft					char|
365d8aaf121SAndy Whitcroft					short|
366d8aaf121SAndy Whitcroft					int|
367d8aaf121SAndy Whitcroft					long|
368d8aaf121SAndy Whitcroft					unsigned|
369d8aaf121SAndy Whitcroft					float|
370d8aaf121SAndy Whitcroft					double|
37122f2a2efSAndy Whitcroft					bool|
372d8aaf121SAndy Whitcroft					long\s+int|
373d8aaf121SAndy Whitcroft					long\s+long|
374d8aaf121SAndy Whitcroft					long\s+long\s+int|
375de7d4f0eSAndy Whitcroft					u8|u16|u32|u64|
376de7d4f0eSAndy Whitcroft					s8|s16|s32|s64|
377d8aaf121SAndy Whitcroft					struct\s+$Ident|
378d8aaf121SAndy Whitcroft					union\s+$Ident|
379de7d4f0eSAndy Whitcroft					enum\s+$Ident|
380d8aaf121SAndy Whitcroft					${Ident}_t
381d8aaf121SAndy Whitcroft				)
382d8aaf121SAndy Whitcroft				(?:\s+$Sparse)*
383d8aaf121SAndy Whitcroft				\b
384d8aaf121SAndy Whitcroft			  }x;
385d8aaf121SAndy Whitcroft	my $Type	= qr{
386d8aaf121SAndy Whitcroft				\b$NonptrType\b
38722f2a2efSAndy Whitcroft				(?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
38822f2a2efSAndy Whitcroft				(?:\s+$Sparse)*
389d8aaf121SAndy Whitcroft			  }x;
390d8aaf121SAndy Whitcroft	my $Declare	= qr{(?:$Storage\s+)?$Type};
391*9c0ca6f9SAndy Whitcroft	my $Attribute	= qr{
392*9c0ca6f9SAndy Whitcroft				const|
393*9c0ca6f9SAndy Whitcroft				__read_mostly|
394*9c0ca6f9SAndy Whitcroft				__(?:mem|cpu|dev|)(?:initdata|init)
395*9c0ca6f9SAndy Whitcroft			  }x;
396f0a594c1SAndy Whitcroft	my $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};
397f0a594c1SAndy Whitcroft	my $Lval	= qr{$Ident(?:$Member)*};
398653d4876SAndy Whitcroft
399*9c0ca6f9SAndy Whitcroft	# Possible bare types.
400*9c0ca6f9SAndy Whitcroft	my @bare = ();
401*9c0ca6f9SAndy Whitcroft	my $Bare = $NonptrType;
402*9c0ca6f9SAndy Whitcroft
403de7d4f0eSAndy Whitcroft	# Pre-scan the patch looking for any __setup documentation.
404de7d4f0eSAndy Whitcroft	my @setup_docs = ();
405de7d4f0eSAndy Whitcroft	my $setup_docs = 0;
406de7d4f0eSAndy Whitcroft	foreach my $line (@lines) {
407de7d4f0eSAndy Whitcroft		if ($line=~/^\+\+\+\s+(\S+)/) {
408de7d4f0eSAndy Whitcroft			$setup_docs = 0;
409de7d4f0eSAndy Whitcroft			if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
410de7d4f0eSAndy Whitcroft				$setup_docs = 1;
411de7d4f0eSAndy Whitcroft			}
412de7d4f0eSAndy Whitcroft			next;
413de7d4f0eSAndy Whitcroft		}
414de7d4f0eSAndy Whitcroft
415de7d4f0eSAndy Whitcroft		if ($setup_docs && $line =~ /^\+/) {
416de7d4f0eSAndy Whitcroft			push(@setup_docs, $line);
417de7d4f0eSAndy Whitcroft		}
418de7d4f0eSAndy Whitcroft	}
419de7d4f0eSAndy Whitcroft
4200a920b5bSAndy Whitcroft	foreach my $line (@lines) {
4210a920b5bSAndy Whitcroft		$linenr++;
4220a920b5bSAndy Whitcroft
423653d4876SAndy Whitcroft		my $rawline = $line;
424653d4876SAndy Whitcroft
4250a920b5bSAndy Whitcroft#extract the filename as it passes
4260a920b5bSAndy Whitcroft		if ($line=~/^\+\+\+\s+(\S+)/) {
4270a920b5bSAndy Whitcroft			$realfile=$1;
42800df344fSAndy Whitcroft			$realfile =~ s@^[^/]*/@@;
4290a920b5bSAndy Whitcroft			$in_comment = 0;
4300a920b5bSAndy Whitcroft			next;
4310a920b5bSAndy Whitcroft		}
4320a920b5bSAndy Whitcroft#extract the line range in the file after the patch is applied
4330a920b5bSAndy Whitcroft		if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
4340a920b5bSAndy Whitcroft			$is_patch = 1;
4354a0df2efSAndy Whitcroft			$first_line = $linenr + 1;
4360a920b5bSAndy Whitcroft			$in_comment = 0;
4370a920b5bSAndy Whitcroft			$realline=$1-1;
4380a920b5bSAndy Whitcroft			if (defined $2) {
4390a920b5bSAndy Whitcroft				$realcnt=$3+1;
4400a920b5bSAndy Whitcroft			} else {
4410a920b5bSAndy Whitcroft				$realcnt=1+1;
4420a920b5bSAndy Whitcroft			}
4430a920b5bSAndy Whitcroft			next;
4440a920b5bSAndy Whitcroft		}
4450a920b5bSAndy Whitcroft
4464a0df2efSAndy Whitcroft# track the line number as we move through the hunk, note that
4474a0df2efSAndy Whitcroft# new versions of GNU diff omit the leading space on completely
4484a0df2efSAndy Whitcroft# blank context lines so we need to count that too.
4494a0df2efSAndy Whitcroft		if ($line =~ /^( |\+|$)/) {
4500a920b5bSAndy Whitcroft			$realline++;
451d8aaf121SAndy Whitcroft			$realcnt-- if ($realcnt != 0);
4520a920b5bSAndy Whitcroft
4530a920b5bSAndy Whitcroft			# track any sort of multi-line comment.  Obviously if
4540a920b5bSAndy Whitcroft			# the added text or context do not include the whole
4550a920b5bSAndy Whitcroft			# comment we will not see it. Such is life.
4560a920b5bSAndy Whitcroft			#
4570a920b5bSAndy Whitcroft			# Guestimate if this is a continuing comment.  If this
4580a920b5bSAndy Whitcroft			# is the start of a diff block and this line starts
4590a920b5bSAndy Whitcroft			# ' *' then it is very likely a comment.
4604a0df2efSAndy Whitcroft			if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
4610a920b5bSAndy Whitcroft				$in_comment = 1;
4620a920b5bSAndy Whitcroft			}
4630a920b5bSAndy Whitcroft			if ($line =~ m@/\*@) {
4640a920b5bSAndy Whitcroft				$in_comment = 1;
4650a920b5bSAndy Whitcroft			}
4660a920b5bSAndy Whitcroft			if ($line =~ m@\*/@) {
4670a920b5bSAndy Whitcroft				$in_comment = 0;
4680a920b5bSAndy Whitcroft			}
4690a920b5bSAndy Whitcroft
4704a0df2efSAndy Whitcroft			# Measure the line length and indent.
4714a0df2efSAndy Whitcroft			($length, $indent) = line_stats($line);
4720a920b5bSAndy Whitcroft
4730a920b5bSAndy Whitcroft			# Track the previous line.
4740a920b5bSAndy Whitcroft			($prevline, $stashline) = ($stashline, $line);
4750a920b5bSAndy Whitcroft			($previndent, $stashindent) = ($stashindent, $indent);
476d8aaf121SAndy Whitcroft		} elsif ($realcnt == 1) {
477d8aaf121SAndy Whitcroft			$realcnt--;
4780a920b5bSAndy Whitcroft		}
4790a920b5bSAndy Whitcroft
4800a920b5bSAndy Whitcroft#make up the handle for any error we report on this line
481389834b6SRandy Dunlap		$here = "#$linenr: ";
482389834b6SRandy Dunlap		$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
4830a920b5bSAndy Whitcroft
48400df344fSAndy Whitcroft		my $hereline = "$here\n$line\n";
485de7d4f0eSAndy Whitcroft		my $herecurr = "$here\n$line\n";
486de7d4f0eSAndy Whitcroft		my $hereprev = "$here\n$prevline\n$line\n";
4870a920b5bSAndy Whitcroft
4880a920b5bSAndy Whitcroft#check the patch for a signoff:
489d8aaf121SAndy Whitcroft		if ($line =~ /^\s*signed-off-by:/i) {
4904a0df2efSAndy Whitcroft			# This is a signoff, if ugly, so do not double report.
4914a0df2efSAndy Whitcroft			$signoff++;
4920a920b5bSAndy Whitcroft			if (!($line =~ /^\s*Signed-off-by:/)) {
493de7d4f0eSAndy Whitcroft				WARN("Signed-off-by: is the preferred form\n" .
494de7d4f0eSAndy Whitcroft					$herecurr);
4950a920b5bSAndy Whitcroft			}
4960a920b5bSAndy Whitcroft			if ($line =~ /^\s*signed-off-by:\S/i) {
497de7d4f0eSAndy Whitcroft				WARN("need space after Signed-off-by:\n" .
498de7d4f0eSAndy Whitcroft					$herecurr);
4990a920b5bSAndy Whitcroft			}
5000a920b5bSAndy Whitcroft		}
5010a920b5bSAndy Whitcroft
50200df344fSAndy Whitcroft# Check for wrappage within a valid hunk of the file
50300df344fSAndy Whitcroft		if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
504de7d4f0eSAndy Whitcroft			ERROR("patch seems to be corrupt (line wrapped?)\n" .
505de7d4f0eSAndy Whitcroft				$herecurr);
506de7d4f0eSAndy Whitcroft		}
507de7d4f0eSAndy Whitcroft
508de7d4f0eSAndy Whitcroft# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
509de7d4f0eSAndy Whitcroft		if (($realfile =~ /^$/ || $line =~ /^\+/) &&
510de7d4f0eSAndy Whitcroft		     !($line =~ m/^(
511de7d4f0eSAndy Whitcroft				[\x09\x0A\x0D\x20-\x7E]              # ASCII
512de7d4f0eSAndy Whitcroft				| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
513de7d4f0eSAndy Whitcroft				|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
514de7d4f0eSAndy Whitcroft				| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
515de7d4f0eSAndy Whitcroft				|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
516de7d4f0eSAndy Whitcroft				|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
517de7d4f0eSAndy Whitcroft				| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
518de7d4f0eSAndy Whitcroft				|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
519de7d4f0eSAndy Whitcroft				)*$/x )) {
520de7d4f0eSAndy Whitcroft			ERROR("Invalid UTF-8\n" . $herecurr);
52100df344fSAndy Whitcroft		}
5220a920b5bSAndy Whitcroft
52300df344fSAndy Whitcroft#ignore lines being removed
52400df344fSAndy Whitcroft		if ($line=~/^-/) {next;}
52500df344fSAndy Whitcroft
52600df344fSAndy Whitcroft# check we are in a valid source file if not then ignore this hunk
52700df344fSAndy Whitcroft		next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
5280a920b5bSAndy Whitcroft
5290a920b5bSAndy Whitcroft#trailing whitespace
530*9c0ca6f9SAndy Whitcroft		if ($line =~ /^\+.*\015/) {
531*9c0ca6f9SAndy Whitcroft			my $herevet = "$here\n" . cat_vet($line) . "\n";
532*9c0ca6f9SAndy Whitcroft			ERROR("DOS line endings\n" . $herevet);
533*9c0ca6f9SAndy Whitcroft
534*9c0ca6f9SAndy Whitcroft		} elsif ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
535de7d4f0eSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($line) . "\n";
536de7d4f0eSAndy Whitcroft			ERROR("trailing whitespace\n" . $herevet);
5370a920b5bSAndy Whitcroft		}
5380a920b5bSAndy Whitcroft#80 column limit
53900df344fSAndy Whitcroft		if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
540de7d4f0eSAndy Whitcroft			WARN("line over 80 characters\n" . $herecurr);
5410a920b5bSAndy Whitcroft		}
5420a920b5bSAndy Whitcroft
5430a920b5bSAndy Whitcroft# check we are in a valid source file *.[hc] if not then ignore this hunk
5440a920b5bSAndy Whitcroft		next if ($realfile !~ /\.[hc]$/);
5450a920b5bSAndy Whitcroft
5460a920b5bSAndy Whitcroft# at the beginning of a line any tabs must come first and anything
5470a920b5bSAndy Whitcroft# more than 8 must use tabs.
5480a920b5bSAndy Whitcroft		if ($line=~/^\+\s* \t\s*\S/ or $line=~/^\+\s*        \s*/) {
549de7d4f0eSAndy Whitcroft			my $herevet = "$here\n" . cat_vet($line) . "\n";
550de7d4f0eSAndy Whitcroft			ERROR("use tabs not spaces\n" . $herevet);
5510a920b5bSAndy Whitcroft		}
5520a920b5bSAndy Whitcroft
5530a920b5bSAndy Whitcroft# Remove comments from the line before processing.
55422f2a2efSAndy Whitcroft		my $comment_edge = ($line =~ s@/\*.*\*/@@g) +
55522f2a2efSAndy Whitcroft				   ($line =~ s@/\*.*@@) +
55622f2a2efSAndy Whitcroft				   ($line =~ s@^(.).*\*/@$1@);
55722f2a2efSAndy Whitcroft
55822f2a2efSAndy Whitcroft# The rest of our checks refer specifically to C style
55922f2a2efSAndy Whitcroft# only apply those _outside_ comments.  Only skip
56022f2a2efSAndy Whitcroft# lines in the middle of comments.
56122f2a2efSAndy Whitcroft		next if (!$comment_edge && $in_comment);
56200df344fSAndy Whitcroft
563653d4876SAndy Whitcroft# Standardise the strings and chars within the input to simplify matching.
564653d4876SAndy Whitcroft		$line = sanitise_line($line);
565653d4876SAndy Whitcroft
566*9c0ca6f9SAndy Whitcroft# Check for potential 'bare' types
567*9c0ca6f9SAndy Whitcroft		if ($realcnt &&
568*9c0ca6f9SAndy Whitcroft		    $line !~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?$Type\b/ &&
569*9c0ca6f9SAndy Whitcroft		    $line !~ /$Ident:\s*$/ &&
570*9c0ca6f9SAndy Whitcroft		    $line !~ /^.\s*$Ident\s*\(/ &&
571*9c0ca6f9SAndy Whitcroft		    ($line =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?($Ident)\b/ ||
572*9c0ca6f9SAndy Whitcroft		     $line =~ /^.\s*(?:$Storage\s+)?($Ident)\b\s*\**\s*$Ident\s*(?:;|=)/)) {
573*9c0ca6f9SAndy Whitcroft			my $possible = $1;
574*9c0ca6f9SAndy Whitcroft			if ($possible !~ /^(?:$Storage|$Type|DEFINE_\S+)$/ &&
575*9c0ca6f9SAndy Whitcroft			    $possible ne 'goto' && $possible ne 'return' &&
576*9c0ca6f9SAndy Whitcroft			    $possible ne 'struct' && $possible ne 'enum' &&
577*9c0ca6f9SAndy Whitcroft			    $possible ne 'case' && $possible ne 'else' &&
578*9c0ca6f9SAndy Whitcroft			    $possible ne 'typedef') {
579*9c0ca6f9SAndy Whitcroft				#print "POSSIBLE<$possible>\n";
580*9c0ca6f9SAndy Whitcroft				push(@bare, $possible);
581*9c0ca6f9SAndy Whitcroft				my $bare = join("|", @bare);
582*9c0ca6f9SAndy Whitcroft				$Bare	= qr{
583*9c0ca6f9SAndy Whitcroft						\b(?:$bare)\b
584*9c0ca6f9SAndy Whitcroft						(?:\s*\*+\s*const|\s*\*+|(?:\s*\[\s*\])+)?
585*9c0ca6f9SAndy Whitcroft						(?:\s+$Sparse)*
586*9c0ca6f9SAndy Whitcroft					  }x;
587*9c0ca6f9SAndy Whitcroft			}
588*9c0ca6f9SAndy Whitcroft		}
589*9c0ca6f9SAndy Whitcroft
59000df344fSAndy Whitcroft#
59100df344fSAndy Whitcroft# Checks which may be anchored in the context.
59200df344fSAndy Whitcroft#
59300df344fSAndy Whitcroft
59400df344fSAndy Whitcroft# Check for switch () and associated case and default
59500df344fSAndy Whitcroft# statements should be at the same indent.
59600df344fSAndy Whitcroft		if ($line=~/\bswitch\s*\(.*\)/) {
59700df344fSAndy Whitcroft			my $err = '';
59800df344fSAndy Whitcroft			my $sep = '';
59900df344fSAndy Whitcroft			my @ctx = ctx_block_outer($linenr, $realcnt);
60000df344fSAndy Whitcroft			shift(@ctx);
60100df344fSAndy Whitcroft			for my $ctx (@ctx) {
60200df344fSAndy Whitcroft				my ($clen, $cindent) = line_stats($ctx);
60300df344fSAndy Whitcroft				if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
60400df344fSAndy Whitcroft							$indent != $cindent) {
60500df344fSAndy Whitcroft					$err .= "$sep$ctx\n";
60600df344fSAndy Whitcroft					$sep = '';
60700df344fSAndy Whitcroft				} else {
60800df344fSAndy Whitcroft					$sep = "[...]\n";
60900df344fSAndy Whitcroft				}
61000df344fSAndy Whitcroft			}
61100df344fSAndy Whitcroft			if ($err ne '') {
612*9c0ca6f9SAndy Whitcroft				ERROR("switch and case should be at the same indent\n$hereline$err");
613de7d4f0eSAndy Whitcroft			}
614de7d4f0eSAndy Whitcroft		}
615de7d4f0eSAndy Whitcroft
616de7d4f0eSAndy Whitcroft# if/while/etc brace do not go on next line, unless defining a do while loop,
617de7d4f0eSAndy Whitcroft# or if that brace on the next line is for something else
618de7d4f0eSAndy Whitcroft		if ($line =~ /\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.#/) {
619*9c0ca6f9SAndy Whitcroft			my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
620de7d4f0eSAndy Whitcroft			my $ctx_ln = $linenr + $#ctx + 1;
621de7d4f0eSAndy Whitcroft			my $ctx_cnt = $realcnt - $#ctx - 1;
622de7d4f0eSAndy Whitcroft			my $ctx = join("\n", @ctx);
623de7d4f0eSAndy Whitcroft
624*9c0ca6f9SAndy Whitcroft			# Skip over any removed lines in the context following statement.
625de7d4f0eSAndy Whitcroft			while ($ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^-/) {
626de7d4f0eSAndy Whitcroft				$ctx_ln++;
627de7d4f0eSAndy Whitcroft				$ctx_cnt--;
628de7d4f0eSAndy Whitcroft			}
629de7d4f0eSAndy Whitcroft			##warn "line<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>";
630de7d4f0eSAndy Whitcroft
631de7d4f0eSAndy Whitcroft			if ($ctx !~ /{\s*/ && $ctx_cnt > 0 && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
632f0a594c1SAndy Whitcroft				ERROR("That open brace { should be on the previous line\n" .
633de7d4f0eSAndy Whitcroft					"$here\n$ctx\n$lines[$ctx_ln - 1]");
63400df344fSAndy Whitcroft			}
635*9c0ca6f9SAndy Whitcroft			if ($level == 0 && $ctx =~ /\)\s*\;\s*$/ && defined $lines[$ctx_ln - 1]) {
636*9c0ca6f9SAndy Whitcroft				my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
637*9c0ca6f9SAndy Whitcroft				if ($nindent > $indent) {
638*9c0ca6f9SAndy Whitcroft					WARN("Trailing semicolon indicates no statements, indent implies otherwise\n" .
639*9c0ca6f9SAndy Whitcroft						"$here\n$ctx\n$lines[$ctx_ln - 1]");
640*9c0ca6f9SAndy Whitcroft				}
641*9c0ca6f9SAndy Whitcroft			}
64200df344fSAndy Whitcroft		}
64300df344fSAndy Whitcroft
64400df344fSAndy Whitcroft#ignore lines not being added
64500df344fSAndy Whitcroft		if ($line=~/^[^\+]/) {next;}
64600df344fSAndy Whitcroft
647653d4876SAndy Whitcroft# TEST: allow direct testing of the type matcher.
648653d4876SAndy Whitcroft		if ($tst_type && $line =~ /^.$Declare$/) {
649de7d4f0eSAndy Whitcroft			ERROR("TEST: is type $Declare\n" . $herecurr);
650653d4876SAndy Whitcroft			next;
651653d4876SAndy Whitcroft		}
652653d4876SAndy Whitcroft
653f0a594c1SAndy Whitcroft# check for initialisation to aggregates open brace on the next line
654f0a594c1SAndy Whitcroft		if ($prevline =~ /$Declare\s*$Ident\s*=\s*$/ &&
655f0a594c1SAndy Whitcroft		    $line =~ /^.\s*{/) {
656f0a594c1SAndy Whitcroft			ERROR("That open brace { should be on the previous line\n" . $hereprev);
657f0a594c1SAndy Whitcroft		}
658f0a594c1SAndy Whitcroft
65900df344fSAndy Whitcroft#
66000df344fSAndy Whitcroft# Checks which are anchored on the added line.
66100df344fSAndy Whitcroft#
66200df344fSAndy Whitcroft
663653d4876SAndy Whitcroft# check for malformed paths in #include statements (uses RAW line)
664653d4876SAndy Whitcroft		if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) {
665653d4876SAndy Whitcroft			my $path = $1;
666653d4876SAndy Whitcroft			if ($path =~ m{//}) {
667de7d4f0eSAndy Whitcroft				ERROR("malformed #include filename\n" .
668de7d4f0eSAndy Whitcroft					$herecurr);
669653d4876SAndy Whitcroft			}
670653d4876SAndy Whitcroft			# Sanitise this special form of string.
671653d4876SAndy Whitcroft			$path = 'X' x length($path);
672653d4876SAndy Whitcroft			$line =~ s{\<.*\>}{<$path>};
673653d4876SAndy Whitcroft		}
674653d4876SAndy Whitcroft
67500df344fSAndy Whitcroft# no C99 // comments
67600df344fSAndy Whitcroft		if ($line =~ m{//}) {
677de7d4f0eSAndy Whitcroft			ERROR("do not use C99 // comments\n" . $herecurr);
67800df344fSAndy Whitcroft		}
67900df344fSAndy Whitcroft		# Remove C99 comments.
6800a920b5bSAndy Whitcroft		$line =~ s@//.*@@;
6810a920b5bSAndy Whitcroft
6820a920b5bSAndy Whitcroft#EXPORT_SYMBOL should immediately follow its function closing }.
683653d4876SAndy Whitcroft		if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
684653d4876SAndy Whitcroft		    ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
685653d4876SAndy Whitcroft			my $name = $1;
6860a920b5bSAndy Whitcroft			if (($prevline !~ /^}/) &&
6870a920b5bSAndy Whitcroft			   ($prevline !~ /^\+}/) &&
688653d4876SAndy Whitcroft			   ($prevline !~ /^ }/) &&
68922f2a2efSAndy Whitcroft			   ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=)/)) {
690de7d4f0eSAndy Whitcroft				WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
6910a920b5bSAndy Whitcroft			}
6920a920b5bSAndy Whitcroft		}
6930a920b5bSAndy Whitcroft
694f0a594c1SAndy Whitcroft# check for external initialisers.
695f0a594c1SAndy Whitcroft		if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL);/) {
696f0a594c1SAndy Whitcroft			ERROR("do not initialise externals to 0 or NULL\n" .
697f0a594c1SAndy Whitcroft				$herecurr);
698f0a594c1SAndy Whitcroft		}
6990a920b5bSAndy Whitcroft# check for static initialisers.
700f0a594c1SAndy Whitcroft		if ($line =~ /\s*static\s.*=\s*(0|NULL);/) {
701de7d4f0eSAndy Whitcroft			ERROR("do not initialise statics to 0 or NULL\n" .
702de7d4f0eSAndy Whitcroft				$herecurr);
7030a920b5bSAndy Whitcroft		}
7040a920b5bSAndy Whitcroft
705653d4876SAndy Whitcroft# check for new typedefs, only function parameters and sparse annotations
706653d4876SAndy Whitcroft# make sense.
707653d4876SAndy Whitcroft		if ($line =~ /\btypedef\s/ &&
708*9c0ca6f9SAndy Whitcroft		    $line !~ /\btypedef\s+$Type\s+\(\s*\*?$Ident\s*\)\s*\(/ &&
709653d4876SAndy Whitcroft		    $line !~ /\b__bitwise(?:__|)\b/) {
710de7d4f0eSAndy Whitcroft			WARN("do not add new typedefs\n" . $herecurr);
7110a920b5bSAndy Whitcroft		}
7120a920b5bSAndy Whitcroft
7130a920b5bSAndy Whitcroft# * goes on variable not on type
714d8aaf121SAndy Whitcroft		if ($line =~ m{\($NonptrType(\*+)(?:\s+const)?\)}) {
715de7d4f0eSAndy Whitcroft			ERROR("\"(foo$1)\" should be \"(foo $1)\"\n" .
716de7d4f0eSAndy Whitcroft				$herecurr);
717d8aaf121SAndy Whitcroft
718d8aaf121SAndy Whitcroft		} elsif ($line =~ m{\($NonptrType\s+(\*+)(?!\s+const)\s+\)}) {
719de7d4f0eSAndy Whitcroft			ERROR("\"(foo $1 )\" should be \"(foo $1)\"\n" .
720de7d4f0eSAndy Whitcroft				$herecurr);
721d8aaf121SAndy Whitcroft
722*9c0ca6f9SAndy Whitcroft		} elsif ($line =~ m{$NonptrType(\*+)(?:\s+(?:$Attribute|$Sparse))?\s+[A-Za-z\d_]+}) {
723de7d4f0eSAndy Whitcroft			ERROR("\"foo$1 bar\" should be \"foo $1bar\"\n" .
724de7d4f0eSAndy Whitcroft				$herecurr);
725d8aaf121SAndy Whitcroft
726*9c0ca6f9SAndy Whitcroft		} elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+(?:$Attribute|$Sparse))\s+[A-Za-z\d_]+}) {
727de7d4f0eSAndy Whitcroft			ERROR("\"foo $1 bar\" should be \"foo $1bar\"\n" .
728de7d4f0eSAndy Whitcroft				$herecurr);
7290a920b5bSAndy Whitcroft		}
7300a920b5bSAndy Whitcroft
7310a920b5bSAndy Whitcroft# # no BUG() or BUG_ON()
7320a920b5bSAndy Whitcroft# 		if ($line =~ /\b(BUG|BUG_ON)\b/) {
7330a920b5bSAndy Whitcroft# 			print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
7340a920b5bSAndy Whitcroft# 			print "$herecurr";
7350a920b5bSAndy Whitcroft# 			$clean = 0;
7360a920b5bSAndy Whitcroft# 		}
7370a920b5bSAndy Whitcroft
73800df344fSAndy Whitcroft# printk should use KERN_* levels.  Note that follow on printk's on the
73900df344fSAndy Whitcroft# same line do not need a level, so we use the current block context
74000df344fSAndy Whitcroft# to try and find and validate the current printk.  In summary the current
74100df344fSAndy Whitcroft# printk includes all preceeding printk's which have no newline on the end.
74200df344fSAndy Whitcroft# we assume the first bad printk is the one to report.
743f0a594c1SAndy Whitcroft		if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
74400df344fSAndy Whitcroft			my $ok = 0;
74500df344fSAndy Whitcroft			for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
74600df344fSAndy Whitcroft				#print "CHECK<$lines[$ln - 1]\n";
74700df344fSAndy Whitcroft				# we have a preceeding printk if it ends
74800df344fSAndy Whitcroft				# with "\n" ignore it, else it is to blame
74900df344fSAndy Whitcroft				if ($lines[$ln - 1] =~ m{\bprintk\(}) {
75000df344fSAndy Whitcroft					if ($rawlines[$ln - 1] !~ m{\\n"}) {
75100df344fSAndy Whitcroft						$ok = 1;
75200df344fSAndy Whitcroft					}
75300df344fSAndy Whitcroft					last;
75400df344fSAndy Whitcroft				}
75500df344fSAndy Whitcroft			}
75600df344fSAndy Whitcroft			if ($ok == 0) {
757de7d4f0eSAndy Whitcroft				WARN("printk() should include KERN_ facility level\n" . $herecurr);
7580a920b5bSAndy Whitcroft			}
75900df344fSAndy Whitcroft		}
7600a920b5bSAndy Whitcroft
761653d4876SAndy Whitcroft# function brace can't be on same line, except for #defines of do while,
762653d4876SAndy Whitcroft# or if closed on same line
763d8aaf121SAndy Whitcroft		if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).* {/) and
7640a920b5bSAndy Whitcroft		    !($line=~/\#define.*do\s{/) and !($line=~/}/)) {
765de7d4f0eSAndy Whitcroft			ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
7660a920b5bSAndy Whitcroft		}
767653d4876SAndy Whitcroft
768f0a594c1SAndy Whitcroft# check for spaces between functions and their parentheses.
769f0a594c1SAndy Whitcroft		if ($line =~ /($Ident)\s+\(/ &&
77022f2a2efSAndy Whitcroft		    $1 !~ /^(?:if|for|while|switch|return|volatile|__volatile__|__attribute__|format|__extension__|Copyright)$/ &&
771f0a594c1SAndy Whitcroft		    $line !~ /$Type\s+\(/ && $line !~ /^.\#\s*define\b/) {
77222f2a2efSAndy Whitcroft			WARN("no space between function name and open parenthesis '('\n" . $herecurr);
773f0a594c1SAndy Whitcroft		}
774653d4876SAndy Whitcroft# Check operator spacing.
7754a0df2efSAndy Whitcroft		# Note we expand the line with the leading + as the real
7764a0df2efSAndy Whitcroft		# line will be displayed with the leading + and the tabs
7774a0df2efSAndy Whitcroft		# will therefore also expand that way.
7780a920b5bSAndy Whitcroft		my $opline = $line;
7794a0df2efSAndy Whitcroft		$opline = expand_tabs($opline);
7800a920b5bSAndy Whitcroft		$opline =~ s/^./ /;
7810a920b5bSAndy Whitcroft		if (!($line=~/\#\s*include/)) {
782*9c0ca6f9SAndy Whitcroft			my $ops = qr{
783*9c0ca6f9SAndy Whitcroft				<<=|>>=|<=|>=|==|!=|
784*9c0ca6f9SAndy Whitcroft				\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
785*9c0ca6f9SAndy Whitcroft				=>|->|<<|>>|<|>|=|!|~|
786*9c0ca6f9SAndy Whitcroft				&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/
787*9c0ca6f9SAndy Whitcroft			}x;
788*9c0ca6f9SAndy Whitcroft			my @elements = split(/($ops|;)/, $opline);
78900df344fSAndy Whitcroft			my $off = 0;
7900a920b5bSAndy Whitcroft			for (my $n = 0; $n < $#elements; $n += 2) {
7914a0df2efSAndy Whitcroft				$off += length($elements[$n]);
7924a0df2efSAndy Whitcroft
7934a0df2efSAndy Whitcroft				my $a = '';
7944a0df2efSAndy Whitcroft				$a = 'V' if ($elements[$n] ne '');
7954a0df2efSAndy Whitcroft				$a = 'W' if ($elements[$n] =~ /\s$/);
7964a0df2efSAndy Whitcroft				$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
7974a0df2efSAndy Whitcroft				$a = 'O' if ($elements[$n] eq '');
7984a0df2efSAndy Whitcroft				$a = 'E' if ($elements[$n] eq '' && $n == 0);
7994a0df2efSAndy Whitcroft
8000a920b5bSAndy Whitcroft				my $op = $elements[$n + 1];
8014a0df2efSAndy Whitcroft
8024a0df2efSAndy Whitcroft				my $c = '';
8030a920b5bSAndy Whitcroft				if (defined $elements[$n + 2]) {
8044a0df2efSAndy Whitcroft					$c = 'V' if ($elements[$n + 2] ne '');
8054a0df2efSAndy Whitcroft					$c = 'W' if ($elements[$n + 2] =~ /^\s/);
8064a0df2efSAndy Whitcroft					$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
8074a0df2efSAndy Whitcroft					$c = 'O' if ($elements[$n + 2] eq '');
80822f2a2efSAndy Whitcroft					$c = 'E' if ($elements[$n + 2] =~ /\s*\\$/);
8094a0df2efSAndy Whitcroft				} else {
8104a0df2efSAndy Whitcroft					$c = 'E';
8110a920b5bSAndy Whitcroft				}
8120a920b5bSAndy Whitcroft
81300df344fSAndy Whitcroft				# Pick up the preceeding and succeeding characters.
814de7d4f0eSAndy Whitcroft				my $ca = substr($opline, 0, $off);
81500df344fSAndy Whitcroft				my $cc = '';
816653d4876SAndy Whitcroft				if (length($opline) >= ($off + length($elements[$n + 1]))) {
817d8aaf121SAndy Whitcroft					$cc = substr($opline, $off + length($elements[$n + 1]));
81800df344fSAndy Whitcroft				}
819de7d4f0eSAndy Whitcroft				my $cb = "$ca$;$cc";
82000df344fSAndy Whitcroft
8214a0df2efSAndy Whitcroft				my $ctx = "${a}x${c}";
8224a0df2efSAndy Whitcroft
8234a0df2efSAndy Whitcroft				my $at = "(ctx:$ctx)";
8244a0df2efSAndy Whitcroft
8254a0df2efSAndy Whitcroft				my $ptr = (" " x $off) . "^";
826de7d4f0eSAndy Whitcroft				my $hereptr = "$hereline$ptr\n";
8270a920b5bSAndy Whitcroft
828*9c0ca6f9SAndy Whitcroft				# Classify operators into binary, unary, or
829*9c0ca6f9SAndy Whitcroft				# definitions (* only) where they have more
830*9c0ca6f9SAndy Whitcroft				# than one mode.
831*9c0ca6f9SAndy Whitcroft				my $unary_ctx = $prevline . $ca;
832*9c0ca6f9SAndy Whitcroft				$unary_ctx =~ s/^./ /;
833*9c0ca6f9SAndy Whitcroft				my $is_unary = 0;
834*9c0ca6f9SAndy Whitcroft				my $Unary = qr{
835*9c0ca6f9SAndy Whitcroft					(?:
836*9c0ca6f9SAndy Whitcroft						^|;|,|$ops|\(|\?|:|
837*9c0ca6f9SAndy Whitcroft						\(\s*$Type\s*\)|
838*9c0ca6f9SAndy Whitcroft						$Type|
839*9c0ca6f9SAndy Whitcroft						return|case|else|
840*9c0ca6f9SAndy Whitcroft						\{|\}|
841*9c0ca6f9SAndy Whitcroft						\[|
842*9c0ca6f9SAndy Whitcroft						^.\#\s*define\s+$Ident\s*(?:\([^\)]*\))?|
843*9c0ca6f9SAndy Whitcroft						^.\#\s*else|
844*9c0ca6f9SAndy Whitcroft						^.\#\s*endif|
845*9c0ca6f9SAndy Whitcroft						^.\#\s*(?:if|ifndef|ifdef)\b.*
846*9c0ca6f9SAndy Whitcroft					)\s*(?:|\\)\s*$
847*9c0ca6f9SAndy Whitcroft				}x;
848*9c0ca6f9SAndy Whitcroft				my $UnaryFalse = qr{
849*9c0ca6f9SAndy Whitcroft					sizeof\s*\(\s*$Type\s*\)\s*$
850*9c0ca6f9SAndy Whitcroft				}x;
851*9c0ca6f9SAndy Whitcroft				my $UnaryDefine = qr{
852*9c0ca6f9SAndy Whitcroft					 (?:$Type|$Bare)\s*|
853*9c0ca6f9SAndy Whitcroft					 (?:$Type|$Bare).*,\s*\**
854*9c0ca6f9SAndy Whitcroft				}x;
855*9c0ca6f9SAndy Whitcroft				if ($op eq '-' || $op eq '&' || $op eq '*') {
856*9c0ca6f9SAndy Whitcroft					# An operator is binary if the left hand
857*9c0ca6f9SAndy Whitcroft					# side is a value.  Pick out the known
858*9c0ca6f9SAndy Whitcroft					# non-values.
859*9c0ca6f9SAndy Whitcroft					if ($unary_ctx =~ /$Unary$/s &&
860*9c0ca6f9SAndy Whitcroft					    $unary_ctx !~ /$UnaryFalse$/s) {
861*9c0ca6f9SAndy Whitcroft						$is_unary = 1;
862*9c0ca6f9SAndy Whitcroft
863*9c0ca6f9SAndy Whitcroft					# Special handling for ')' check if this
864*9c0ca6f9SAndy Whitcroft					# brace represents a conditional, if so
865*9c0ca6f9SAndy Whitcroft					# we are unary.
866*9c0ca6f9SAndy Whitcroft					} elsif ($unary_ctx =~ /\)\s*$/) {
867*9c0ca6f9SAndy Whitcroft						my $before = ctx_expr_before($unary_ctx);
868*9c0ca6f9SAndy Whitcroft						if ($before =~ /(?:for|if|while)\s*$/) {
869*9c0ca6f9SAndy Whitcroft							$is_unary = 1;
870*9c0ca6f9SAndy Whitcroft						}
871*9c0ca6f9SAndy Whitcroft					}
872*9c0ca6f9SAndy Whitcroft
873*9c0ca6f9SAndy Whitcroft					# Check for type definition for of '*'.
874*9c0ca6f9SAndy Whitcroft					if ($op eq '*' && $unary_ctx =~ /$UnaryDefine$/) {
875*9c0ca6f9SAndy Whitcroft						$is_unary = 2;
876*9c0ca6f9SAndy Whitcroft					}
877*9c0ca6f9SAndy Whitcroft				}
878*9c0ca6f9SAndy Whitcroft
879*9c0ca6f9SAndy Whitcroft				#if ($op eq '-' || $op eq '&' || $op eq '*') {
880*9c0ca6f9SAndy Whitcroft				#	print "UNARY: <$is_unary $a:$op:$c> <$ca:$op:$cc> <$unary_ctx>\n";
881*9c0ca6f9SAndy Whitcroft				#}
8820a920b5bSAndy Whitcroft
883d8aaf121SAndy Whitcroft				# ; should have either the end of line or a space or \ after it
884d8aaf121SAndy Whitcroft				if ($op eq ';') {
885de7d4f0eSAndy Whitcroft					if ($ctx !~ /.x[WEB]/ && $cc !~ /^\\/ &&
886de7d4f0eSAndy Whitcroft					    $cc !~ /^;/) {
887de7d4f0eSAndy Whitcroft						ERROR("need space after that '$op' $at\n" . $hereptr);
888d8aaf121SAndy Whitcroft					}
889d8aaf121SAndy Whitcroft
890d8aaf121SAndy Whitcroft				# // is a comment
891d8aaf121SAndy Whitcroft				} elsif ($op eq '//') {
8920a920b5bSAndy Whitcroft
8930a920b5bSAndy Whitcroft				# -> should have no spaces
8940a920b5bSAndy Whitcroft				} elsif ($op eq '->') {
8954a0df2efSAndy Whitcroft					if ($ctx =~ /Wx.|.xW/) {
896de7d4f0eSAndy Whitcroft						ERROR("no spaces around that '$op' $at\n" . $hereptr);
8970a920b5bSAndy Whitcroft					}
8980a920b5bSAndy Whitcroft
8990a920b5bSAndy Whitcroft				# , must have a space on the right.
9000a920b5bSAndy Whitcroft				} elsif ($op eq ',') {
901d8aaf121SAndy Whitcroft					if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
902de7d4f0eSAndy Whitcroft						ERROR("need space after that '$op' $at\n" . $hereptr);
9030a920b5bSAndy Whitcroft					}
9040a920b5bSAndy Whitcroft
905*9c0ca6f9SAndy Whitcroft				# '*' as part of a type definition -- reported already.
906*9c0ca6f9SAndy Whitcroft				} elsif ($op eq '*' && $is_unary == 2) {
907*9c0ca6f9SAndy Whitcroft					#warn "'*' is part of type\n";
908*9c0ca6f9SAndy Whitcroft
909*9c0ca6f9SAndy Whitcroft				# unary operators should have a space before and
910*9c0ca6f9SAndy Whitcroft				# none after.  May be left adjacent to another
911*9c0ca6f9SAndy Whitcroft				# unary operator, or a cast
912*9c0ca6f9SAndy Whitcroft				} elsif ($op eq '!' || $op eq '~' ||
913*9c0ca6f9SAndy Whitcroft				         ($is_unary && ($op eq '*' || $op eq '-' || $op eq '&'))) {
914*9c0ca6f9SAndy Whitcroft					if ($ctx !~ /[WEB]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
915de7d4f0eSAndy Whitcroft						ERROR("need space before that '$op' $at\n" . $hereptr);
9160a920b5bSAndy Whitcroft					}
9174a0df2efSAndy Whitcroft					if ($ctx =~ /.xW/) {
918de7d4f0eSAndy Whitcroft						ERROR("no space after that '$op' $at\n" . $hereptr);
9190a920b5bSAndy Whitcroft					}
9200a920b5bSAndy Whitcroft
9210a920b5bSAndy Whitcroft				# unary ++ and unary -- are allowed no space on one side.
9220a920b5bSAndy Whitcroft				} elsif ($op eq '++' or $op eq '--') {
923d8aaf121SAndy Whitcroft					if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
924de7d4f0eSAndy Whitcroft						ERROR("need space one side of that '$op' $at\n" . $hereptr);
9250a920b5bSAndy Whitcroft					}
926d8aaf121SAndy Whitcroft					if ($ctx =~ /Wx./ && $cc =~ /^;/) {
927de7d4f0eSAndy Whitcroft						ERROR("no space before that '$op' $at\n" . $hereptr);
928653d4876SAndy Whitcroft					}
9290a920b5bSAndy Whitcroft
9300a920b5bSAndy Whitcroft				# << and >> may either have or not have spaces both sides
931*9c0ca6f9SAndy Whitcroft				} elsif ($op eq '<<' or $op eq '>>' or
932*9c0ca6f9SAndy Whitcroft					 $op eq '&' or $op eq '^' or $op eq '|' or
933*9c0ca6f9SAndy Whitcroft					 $op eq '+' or $op eq '-' or
934*9c0ca6f9SAndy Whitcroft					 $op eq '*' or $op eq '/')
9350a920b5bSAndy Whitcroft				{
936*9c0ca6f9SAndy Whitcroft					if ($ctx !~ /VxV|WxW|VxE|WxE|VxO/) {
937de7d4f0eSAndy Whitcroft						ERROR("need consistent spacing around '$op' $at\n" .
938de7d4f0eSAndy Whitcroft							$hereptr);
9390a920b5bSAndy Whitcroft					}
9400a920b5bSAndy Whitcroft
9410a920b5bSAndy Whitcroft				# All the others need spaces both sides.
9424a0df2efSAndy Whitcroft				} elsif ($ctx !~ /[EW]x[WE]/) {
94322f2a2efSAndy Whitcroft					# Ignore email addresses <foo@bar>
94422f2a2efSAndy Whitcroft					if (!($op eq '<' && $cb =~ /$;\S+\@\S+>/) &&
94522f2a2efSAndy Whitcroft					    !($op eq '>' && $cb =~ /<\S+\@\S+$;/)) {
946de7d4f0eSAndy Whitcroft						ERROR("need spaces around that '$op' $at\n" . $hereptr);
9470a920b5bSAndy Whitcroft					}
94822f2a2efSAndy Whitcroft				}
9494a0df2efSAndy Whitcroft				$off += length($elements[$n + 1]);
9500a920b5bSAndy Whitcroft			}
9510a920b5bSAndy Whitcroft		}
9520a920b5bSAndy Whitcroft
953f0a594c1SAndy Whitcroft# check for multiple assignments
954f0a594c1SAndy Whitcroft		if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
955f0a594c1SAndy Whitcroft			WARN("multiple assignments should be avoided\n" . $herecurr);
956f0a594c1SAndy Whitcroft		}
957f0a594c1SAndy Whitcroft
95822f2a2efSAndy Whitcroft## # check for multiple declarations, allowing for a function declaration
95922f2a2efSAndy Whitcroft## # continuation.
96022f2a2efSAndy Whitcroft## 		if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
96122f2a2efSAndy Whitcroft## 		    $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
96222f2a2efSAndy Whitcroft##
96322f2a2efSAndy Whitcroft## 			# Remove any bracketed sections to ensure we do not
96422f2a2efSAndy Whitcroft## 			# falsly report the parameters of functions.
96522f2a2efSAndy Whitcroft## 			my $ln = $line;
96622f2a2efSAndy Whitcroft## 			while ($ln =~ s/\([^\(\)]*\)//g) {
96722f2a2efSAndy Whitcroft## 			}
96822f2a2efSAndy Whitcroft## 			if ($ln =~ /,/) {
96922f2a2efSAndy Whitcroft## 				WARN("declaring multiple variables together should be avoided\n" . $herecurr);
97022f2a2efSAndy Whitcroft## 			}
97122f2a2efSAndy Whitcroft## 		}
972f0a594c1SAndy Whitcroft
9730a920b5bSAndy Whitcroft#need space before brace following if, while, etc
97422f2a2efSAndy Whitcroft		if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
97522f2a2efSAndy Whitcroft		    $line =~ /do{/) {
976de7d4f0eSAndy Whitcroft			ERROR("need a space before the open brace '{'\n" . $herecurr);
977de7d4f0eSAndy Whitcroft		}
978de7d4f0eSAndy Whitcroft
979de7d4f0eSAndy Whitcroft# closing brace should have a space following it when it has anything
980de7d4f0eSAndy Whitcroft# on the line
981de7d4f0eSAndy Whitcroft		if ($line =~ /}(?!(?:,|;|\)))\S/) {
982de7d4f0eSAndy Whitcroft			ERROR("need a space after that close brace '}'\n" . $herecurr);
9830a920b5bSAndy Whitcroft		}
9840a920b5bSAndy Whitcroft
98522f2a2efSAndy Whitcroft# check spacing on square brackets
98622f2a2efSAndy Whitcroft		if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
98722f2a2efSAndy Whitcroft			ERROR("no space after that open square bracket '['\n" . $herecurr);
98822f2a2efSAndy Whitcroft		}
98922f2a2efSAndy Whitcroft		if ($line =~ /\s\]/) {
99022f2a2efSAndy Whitcroft			ERROR("no space before that close square bracket ']'\n" . $herecurr);
99122f2a2efSAndy Whitcroft		}
99222f2a2efSAndy Whitcroft
99322f2a2efSAndy Whitcroft# check spacing on paretheses
994*9c0ca6f9SAndy Whitcroft		if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
995*9c0ca6f9SAndy Whitcroft		    $line !~ /for\s*\(\s+;/) {
99622f2a2efSAndy Whitcroft			ERROR("no space after that open parenthesis '('\n" . $herecurr);
99722f2a2efSAndy Whitcroft		}
998*9c0ca6f9SAndy Whitcroft		if ($line =~ /\s\)/ && $line !~ /^.\s*\)/ &&
999*9c0ca6f9SAndy Whitcroft		    $line !~ /for\s*\(.*;\s+\)/) {
100022f2a2efSAndy Whitcroft			ERROR("no space before that close parenthesis ')'\n" . $herecurr);
100122f2a2efSAndy Whitcroft		}
100222f2a2efSAndy Whitcroft
10030a920b5bSAndy Whitcroft#goto labels aren't indented, allow a single space however
10044a0df2efSAndy Whitcroft		if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
10050a920b5bSAndy Whitcroft		   !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
1006de7d4f0eSAndy Whitcroft			WARN("labels should not be indented\n" . $herecurr);
10070a920b5bSAndy Whitcroft		}
10080a920b5bSAndy Whitcroft
10090a920b5bSAndy Whitcroft# Need a space before open parenthesis after if, while etc
10104a0df2efSAndy Whitcroft		if ($line=~/\b(if|while|for|switch)\(/) {
1011de7d4f0eSAndy Whitcroft			ERROR("need a space before the open parenthesis '('\n" . $herecurr);
10120a920b5bSAndy Whitcroft		}
10130a920b5bSAndy Whitcroft
10140a920b5bSAndy Whitcroft# Check for illegal assignment in if conditional.
1015653d4876SAndy Whitcroft		if ($line=~/\bif\s*\(.*[^<>!=]=[^=].*\)/) {
101600df344fSAndy Whitcroft			#next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
1017de7d4f0eSAndy Whitcroft			ERROR("do not use assignment in if condition\n" . $herecurr);
10180a920b5bSAndy Whitcroft		}
10190a920b5bSAndy Whitcroft
10200a920b5bSAndy Whitcroft		# Check for }<nl>else {, these must be at the same
10210a920b5bSAndy Whitcroft		# indent level to be relevant to each other.
10220a920b5bSAndy Whitcroft		if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
10230a920b5bSAndy Whitcroft						$previndent == $indent) {
1024de7d4f0eSAndy Whitcroft			ERROR("else should follow close brace '}'\n" . $hereprev);
10250a920b5bSAndy Whitcroft		}
10260a920b5bSAndy Whitcroft
10270a920b5bSAndy Whitcroft#studly caps, commented out until figure out how to distinguish between use of existing and adding new
10280a920b5bSAndy Whitcroft#		if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
10290a920b5bSAndy Whitcroft#		    print "No studly caps, use _\n";
10300a920b5bSAndy Whitcroft#		    print "$herecurr";
10310a920b5bSAndy Whitcroft#		    $clean = 0;
10320a920b5bSAndy Whitcroft#		}
10330a920b5bSAndy Whitcroft
10340a920b5bSAndy Whitcroft#no spaces allowed after \ in define
10350a920b5bSAndy Whitcroft		if ($line=~/\#define.*\\\s$/) {
1036de7d4f0eSAndy Whitcroft			WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
10370a920b5bSAndy Whitcroft		}
10380a920b5bSAndy Whitcroft
1039653d4876SAndy Whitcroft#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
1040653d4876SAndy Whitcroft		if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
10410a920b5bSAndy Whitcroft			my $checkfile = "include/linux/$1.h";
10420a920b5bSAndy Whitcroft			if (-f $checkfile) {
1043de7d4f0eSAndy Whitcroft				CHK("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
1044de7d4f0eSAndy Whitcroft					$herecurr);
10450a920b5bSAndy Whitcroft			}
10460a920b5bSAndy Whitcroft		}
10470a920b5bSAndy Whitcroft
1048d8aaf121SAndy Whitcroft# if and else should not have general statements after it
1049d8aaf121SAndy Whitcroft		if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ &&
1050de7d4f0eSAndy Whitcroft		    $1 !~ /^\s*(?:\sif|{|\\|$)/) {
1051de7d4f0eSAndy Whitcroft			ERROR("trailing statements should be on next line\n" . $herecurr);
1052d8aaf121SAndy Whitcroft		}
1053d8aaf121SAndy Whitcroft
1054653d4876SAndy Whitcroft# multi-statement macros should be enclosed in a do while loop, grab the
1055653d4876SAndy Whitcroft# first statement and ensure its the whole macro if its not enclosed
1056653d4876SAndy Whitcroft# in a known goot container
1057*9c0ca6f9SAndy Whitcroft		if ($prevline =~ /\#define.*\\/ &&
1058*9c0ca6f9SAndy Whitcroft		   $prevline !~/(?:do\s+{|\(\{|\{)/ &&
1059*9c0ca6f9SAndy Whitcroft		   $line !~ /(?:do\s+{|\(\{|\{)/ &&
1060*9c0ca6f9SAndy Whitcroft		   $line !~ /^.\s*$Declare\s/) {
1061653d4876SAndy Whitcroft			# Grab the first statement, if that is the entire macro
1062653d4876SAndy Whitcroft			# its ok.  This may start either on the #define line
1063653d4876SAndy Whitcroft			# or the one below.
1064d8aaf121SAndy Whitcroft			my $ln = $linenr;
1065d8aaf121SAndy Whitcroft			my $cnt = $realcnt;
1066f0a594c1SAndy Whitcroft			my $off = 0;
1067653d4876SAndy Whitcroft
1068f0a594c1SAndy Whitcroft			# If the macro starts on the define line start
1069f0a594c1SAndy Whitcroft			# grabbing the statement after the identifier
1070f0a594c1SAndy Whitcroft			$prevline =~ m{^(.#\s*define\s*$Ident(?:\([^\)]*\))?\s*)(.*)\\\s*$};
1071f0a594c1SAndy Whitcroft			##print "1<$1> 2<$2>\n";
107222f2a2efSAndy Whitcroft			if (defined $2 && $2 ne '') {
1073f0a594c1SAndy Whitcroft				$off = length($1);
1074d8aaf121SAndy Whitcroft				$ln--;
1075d8aaf121SAndy Whitcroft				$cnt++;
1076d8aaf121SAndy Whitcroft			}
1077f0a594c1SAndy Whitcroft			my @ctx = ctx_statement($ln, $cnt, $off);
1078de7d4f0eSAndy Whitcroft			my $ctx_ln = $ln + $#ctx + 1;
1079de7d4f0eSAndy Whitcroft			my $ctx = join("\n", @ctx);
1080de7d4f0eSAndy Whitcroft
1081de7d4f0eSAndy Whitcroft			# Pull in any empty extension lines.
1082de7d4f0eSAndy Whitcroft			while ($ctx =~ /\\$/ &&
1083de7d4f0eSAndy Whitcroft			       $lines[$ctx_ln - 1] =~ /^.\s*(?:\\)?$/) {
1084de7d4f0eSAndy Whitcroft				$ctx .= $lines[$ctx_ln - 1];
1085de7d4f0eSAndy Whitcroft				$ctx_ln++;
1086de7d4f0eSAndy Whitcroft			}
1087d8aaf121SAndy Whitcroft
1088d8aaf121SAndy Whitcroft			if ($ctx =~ /\\$/) {
1089d8aaf121SAndy Whitcroft				if ($ctx =~ /;/) {
1090de7d4f0eSAndy Whitcroft					ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
1091d8aaf121SAndy Whitcroft				} else {
1092de7d4f0eSAndy Whitcroft					ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
1093d8aaf121SAndy Whitcroft				}
10940a920b5bSAndy Whitcroft			}
1095653d4876SAndy Whitcroft		}
10960a920b5bSAndy Whitcroft
1097f0a594c1SAndy Whitcroft# check for redundant bracing round if etc
1098f0a594c1SAndy Whitcroft		if ($line =~ /\b(if|while|for|else)\b/) {
1099f0a594c1SAndy Whitcroft			# Locate the end of the opening statement.
1100f0a594c1SAndy Whitcroft			my @control = ctx_statement($linenr, $realcnt, 0);
1101f0a594c1SAndy Whitcroft			my $nr = $linenr + (scalar(@control) - 1);
1102f0a594c1SAndy Whitcroft			my $cnt = $realcnt - (scalar(@control) - 1);
1103f0a594c1SAndy Whitcroft
1104f0a594c1SAndy Whitcroft			my $off = $realcnt - $cnt;
1105f0a594c1SAndy Whitcroft			#print "$off: line<$line>end<" . $lines[$nr - 1] . ">\n";
1106f0a594c1SAndy Whitcroft
1107f0a594c1SAndy Whitcroft			# If this is is a braced statement group check it
1108f0a594c1SAndy Whitcroft			if ($lines[$nr - 1] =~ /{\s*$/) {
1109f0a594c1SAndy Whitcroft				my ($lvl, @block) = ctx_block_level($nr, $cnt);
1110f0a594c1SAndy Whitcroft
1111f0a594c1SAndy Whitcroft				my $stmt = join(' ', @block);
111222f2a2efSAndy Whitcroft				$stmt =~ s/(^[^{]*){//;
111322f2a2efSAndy Whitcroft				my $before = $1;
111422f2a2efSAndy Whitcroft				$stmt =~ s/}([^}]*$)//;
111522f2a2efSAndy Whitcroft				my $after = $1;
1116f0a594c1SAndy Whitcroft
1117f0a594c1SAndy Whitcroft				#print "block<" . join(' ', @block) . "><" . scalar(@block) . ">\n";
1118f0a594c1SAndy Whitcroft				#print "stmt<$stmt>\n\n";
1119f0a594c1SAndy Whitcroft
1120f0a594c1SAndy Whitcroft				# Count the ;'s if there is fewer than two
1121f0a594c1SAndy Whitcroft				# then there can only be one statement,
1122f0a594c1SAndy Whitcroft				# if there is a brace inside we cannot
1123f0a594c1SAndy Whitcroft				# trivially detect if its one statement.
1124f0a594c1SAndy Whitcroft				# Also nested if's often require braces to
1125f0a594c1SAndy Whitcroft				# disambiguate the else binding so shhh there.
1126f0a594c1SAndy Whitcroft				my @semi = ($stmt =~ /;/g);
112722f2a2efSAndy Whitcroft				push(@semi, "/**/") if ($stmt =~ m@/\*@);
1128f0a594c1SAndy Whitcroft				##print "semi<" . scalar(@semi) . ">\n";
1129f0a594c1SAndy Whitcroft				if ($lvl == 0 && scalar(@semi) < 2 &&
113022f2a2efSAndy Whitcroft				    $stmt !~ /{/ && $stmt !~ /\bif\b/ &&
113122f2a2efSAndy Whitcroft				    $before !~ /}/ && $after !~ /{/) {
1132f0a594c1SAndy Whitcroft				    	my $herectx = "$here\n" . join("\n", @control, @block[1 .. $#block]) . "\n";
1133f0a594c1SAndy Whitcroft				    	shift(@block);
113422f2a2efSAndy Whitcroft					WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
1135f0a594c1SAndy Whitcroft				}
1136f0a594c1SAndy Whitcroft			}
1137f0a594c1SAndy Whitcroft		}
1138f0a594c1SAndy Whitcroft
1139653d4876SAndy Whitcroft# don't include deprecated include files (uses RAW line)
11404a0df2efSAndy Whitcroft		for my $inc (@dep_includes) {
1141653d4876SAndy Whitcroft			if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
1142de7d4f0eSAndy Whitcroft				ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
11430a920b5bSAndy Whitcroft			}
11440a920b5bSAndy Whitcroft		}
11450a920b5bSAndy Whitcroft
11464a0df2efSAndy Whitcroft# don't use deprecated functions
11474a0df2efSAndy Whitcroft		for my $func (@dep_functions) {
114800df344fSAndy Whitcroft			if ($line =~ /\b$func\b/) {
1149de7d4f0eSAndy Whitcroft				ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
11504a0df2efSAndy Whitcroft			}
11514a0df2efSAndy Whitcroft		}
11524a0df2efSAndy Whitcroft
11534a0df2efSAndy Whitcroft# no volatiles please
115400df344fSAndy Whitcroft		if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
1155de7d4f0eSAndy Whitcroft			WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
11564a0df2efSAndy Whitcroft		}
11574a0df2efSAndy Whitcroft
1158*9c0ca6f9SAndy Whitcroft# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
1159*9c0ca6f9SAndy Whitcroft		if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
1160*9c0ca6f9SAndy Whitcroft			ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
1161*9c0ca6f9SAndy Whitcroft		}
1162*9c0ca6f9SAndy Whitcroft
116300df344fSAndy Whitcroft# warn about #if 0
116400df344fSAndy Whitcroft		if ($line =~ /^.#\s*if\s+0\b/) {
1165de7d4f0eSAndy Whitcroft			CHK("if this code is redundant consider removing it\n" .
1166de7d4f0eSAndy Whitcroft				$herecurr);
11674a0df2efSAndy Whitcroft		}
11684a0df2efSAndy Whitcroft
1169f0a594c1SAndy Whitcroft# check for needless kfree() checks
1170f0a594c1SAndy Whitcroft		if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
1171f0a594c1SAndy Whitcroft			my $expr = $1;
1172f0a594c1SAndy Whitcroft			if ($line =~ /\bkfree\(\Q$expr\E\);/) {
1173f0a594c1SAndy Whitcroft				WARN("kfree(NULL) is safe this check is probabally not required\n" . $hereprev);
1174f0a594c1SAndy Whitcroft			}
1175f0a594c1SAndy Whitcroft		}
1176f0a594c1SAndy Whitcroft
117700df344fSAndy Whitcroft# warn about #ifdefs in C files
117800df344fSAndy Whitcroft#		if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
117900df344fSAndy Whitcroft#			print "#ifdef in C files should be avoided\n";
118000df344fSAndy Whitcroft#			print "$herecurr";
118100df344fSAndy Whitcroft#			$clean = 0;
118200df344fSAndy Whitcroft#		}
118300df344fSAndy Whitcroft
118422f2a2efSAndy Whitcroft# warn about spacing in #ifdefs
118522f2a2efSAndy Whitcroft		if ($line =~ /^.#\s*(ifdef|ifndef|elif)\s\s+/) {
118622f2a2efSAndy Whitcroft			ERROR("exactly one space required after that #$1\n" . $herecurr);
118722f2a2efSAndy Whitcroft		}
118822f2a2efSAndy Whitcroft
11894a0df2efSAndy Whitcroft# check for spinlock_t definitions without a comment.
11904a0df2efSAndy Whitcroft		if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
11914a0df2efSAndy Whitcroft			my $which = $1;
11924a0df2efSAndy Whitcroft			if (!ctx_has_comment($first_line, $linenr)) {
1193de7d4f0eSAndy Whitcroft				CHK("$1 definition without comment\n" . $herecurr);
11944a0df2efSAndy Whitcroft			}
11954a0df2efSAndy Whitcroft		}
11964a0df2efSAndy Whitcroft# check for memory barriers without a comment.
11974a0df2efSAndy Whitcroft		if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
11984a0df2efSAndy Whitcroft			if (!ctx_has_comment($first_line, $linenr)) {
1199de7d4f0eSAndy Whitcroft				CHK("memory barrier without comment\n" . $herecurr);
12004a0df2efSAndy Whitcroft			}
12014a0df2efSAndy Whitcroft		}
12024a0df2efSAndy Whitcroft# check of hardware specific defines
120322f2a2efSAndy Whitcroft		if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
1204de7d4f0eSAndy Whitcroft			CHK("architecture specific defines should be avoided\n" .  $herecurr);
12050a920b5bSAndy Whitcroft		}
1206653d4876SAndy Whitcroft
1207de7d4f0eSAndy Whitcroft# check the location of the inline attribute, that it is between
1208de7d4f0eSAndy Whitcroft# storage class and type.
1209*9c0ca6f9SAndy Whitcroft		if ($line =~ /\b$Type\s+$Inline\b/ ||
1210*9c0ca6f9SAndy Whitcroft		    $line =~ /\b$Inline\s+$Storage\b/) {
1211de7d4f0eSAndy Whitcroft			ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
1212de7d4f0eSAndy Whitcroft		}
1213de7d4f0eSAndy Whitcroft
1214de7d4f0eSAndy Whitcroft# check for new externs in .c files.
1215de7d4f0eSAndy Whitcroft		if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
1216de7d4f0eSAndy Whitcroft			WARN("externs should be avoided in .c files\n" .  $herecurr);
1217de7d4f0eSAndy Whitcroft		}
1218de7d4f0eSAndy Whitcroft
1219de7d4f0eSAndy Whitcroft# checks for new __setup's
1220de7d4f0eSAndy Whitcroft		if ($rawline =~ /\b__setup\("([^"]*)"/) {
1221de7d4f0eSAndy Whitcroft			my $name = $1;
1222de7d4f0eSAndy Whitcroft
1223de7d4f0eSAndy Whitcroft			if (!grep(/$name/, @setup_docs)) {
1224de7d4f0eSAndy Whitcroft				CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
1225de7d4f0eSAndy Whitcroft			}
1226653d4876SAndy Whitcroft		}
1227*9c0ca6f9SAndy Whitcroft
1228*9c0ca6f9SAndy Whitcroft# check for pointless casting of kmalloc return
1229*9c0ca6f9SAndy Whitcroft		if ($line =~ /\*\s*\)\s*k[czm]alloc\b/) {
1230*9c0ca6f9SAndy Whitcroft			WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
1231*9c0ca6f9SAndy Whitcroft		}
12320a920b5bSAndy Whitcroft	}
12330a920b5bSAndy Whitcroft
12340a920b5bSAndy Whitcroft	if ($chk_patch && !$is_patch) {
1235de7d4f0eSAndy Whitcroft		ERROR("Does not appear to be a unified-diff format patch\n");
12360a920b5bSAndy Whitcroft	}
12370a920b5bSAndy Whitcroft	if ($is_patch && $chk_signoff && $signoff == 0) {
1238de7d4f0eSAndy Whitcroft		ERROR("Missing Signed-off-by: line(s)\n");
12390a920b5bSAndy Whitcroft	}
12400a920b5bSAndy Whitcroft
1241f0a594c1SAndy Whitcroft	if ($clean == 0 && ($chk_patch || $is_patch)) {
1242f0a594c1SAndy Whitcroft		print report_dump();
1243f0a594c1SAndy Whitcroft	}
12440a920b5bSAndy Whitcroft	if ($clean == 1 && $quiet == 0) {
12450a920b5bSAndy Whitcroft		print "Your patch has no obvious style problems and is ready for submission.\n"
12460a920b5bSAndy Whitcroft	}
12470a920b5bSAndy Whitcroft	if ($clean == 0 && $quiet == 0) {
12480a920b5bSAndy Whitcroft		print "Your patch has style problems, please review.  If any of these errors\n";
12490a920b5bSAndy Whitcroft		print "are false positives report them to the maintainer, see\n";
12500a920b5bSAndy Whitcroft		print "CHECKPATCH in MAINTAINERS.\n";
12510a920b5bSAndy Whitcroft	}
12520a920b5bSAndy Whitcroft	return $clean;
12530a920b5bSAndy Whitcroft}
1254