checkpatch.pl 68.6 KB
Newer Older
1
#!/usr/bin/perl -w
Dave Jones's avatar
Dave Jones committed
2
# (c) 2001, Dave Jones. <davej@redhat.com> (the file handling bit)
3
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
Andy Whitcroft's avatar
Andy Whitcroft committed
4
5
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
# (c) 2008, Andy Whitcroft <apw@canonical.com>
6
7
8
9
10
# Licensed under the terms of the GNU GPL License version 2

use strict;

my $P = $0;
11
$P =~ s@.*/@@g;
12

Andy Whitcroft's avatar
Andy Whitcroft committed
13
my $V = '0.26';
14
15
16
17
18
19
20

use Getopt::Long qw(:config no_auto_abbrev);

my $quiet = 0;
my $tree = 1;
my $chk_signoff = 1;
my $chk_patch = 1;
21
my $tst_only;
22
my $emacs = 0;
23
my $terse = 0;
24
25
my $file = 0;
my $check = 0;
26
27
my $summary = 1;
my $mailback = 0;
28
my $summary_file = 0;
29
my $root;
30
my %debug;
31
GetOptions(
32
	'q|quiet+'	=> \$quiet,
33
34
35
	'tree!'		=> \$tree,
	'signoff!'	=> \$chk_signoff,
	'patch!'	=> \$chk_patch,
36
	'emacs!'	=> \$emacs,
37
	'terse!'	=> \$terse,
38
39
40
41
	'file!'		=> \$file,
	'subjective!'	=> \$check,
	'strict!'	=> \$check,
	'root=s'	=> \$root,
42
43
	'summary!'	=> \$summary,
	'mailback!'	=> \$mailback,
44
45
	'summary-file!'	=> \$summary_file,

46
	'debug=s'	=> \%debug,
47
	'test-only=s'	=> \$tst_only,
48
49
50
51
52
) or exit;

my $exit = 0;

if ($#ARGV < 0) {
53
	print "usage: $P [options] patchfile\n";
54
	print "version: $V\n";
55
56
57
58
59
60
61
62
63
	print "options: -q               => quiet\n";
	print "         --no-tree        => run without a kernel tree\n";
	print "         --terse          => one line per report\n";
	print "         --emacs          => emacs compile window format\n";
	print "         --file           => check a source file\n";
	print "         --strict         => enable more subjective tests\n";
	print "         --root           => path to the kernel tree root\n";
	print "         --no-summary     => suppress the per-file summary\n";
	print "         --summary-file   => include the filename in summary\n";
64
65
66
	exit(1);
}

67
68
my $dbg_values = 0;
my $dbg_possible = 0;
69
my $dbg_type = 0;
70
my $dbg_attr = 0;
71
for my $key (keys %debug) {
72
73
74
	## no critic
	eval "\${dbg_$key} = '$debug{$key}';";
	die "$@" if ($@);
75
76
}

77
78
79
80
81
if ($terse) {
	$emacs = 1;
	$quiet++;
}

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
if ($tree) {
	if (defined $root) {
		if (!top_of_kernel_tree($root)) {
			die "$P: $root: --root does not point at a valid tree\n";
		}
	} else {
		if (top_of_kernel_tree('.')) {
			$root = '.';
		} elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
						top_of_kernel_tree($1)) {
			$root = $1;
		}
	}

	if (!defined $root) {
		print "Must be run from the top-level dir. of a kernel tree\n";
		exit(2);
	}
100
101
}

102
103
104
105
106
107
108
109
110
111
112
my $emitted_corrupt = 0;

our $Ident       = qr{[A-Za-z_][A-Za-z\d_]*};
our $Storage	= qr{extern|static|asmlinkage};
our $Sparse	= qr{
			__user|
			__kernel|
			__force|
			__iomem|
			__must_check|
			__init_refok|
113
			__kprobes
114
115
116
117
118
		}x;
our $Attribute	= qr{
			const|
			__read_mostly|
			__kprobes|
119
120
121
			__(?:mem|cpu|dev|)(?:initdata|init)|
			____cacheline_aligned|
			____cacheline_aligned_in_smp|
122
123
			____cacheline_internodealigned_in_smp|
			__weak
124
		  }x;
125
our $Modifier;
126
127
128
129
130
131
our $Inline	= qr{inline|__always_inline|noinline};
our $Member	= qr{->$Ident|\.$Ident|\[[^]]*\]};
our $Lval	= qr{$Ident(?:$Member)*};

our $Constant	= qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
our $Assignment	= qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
132
our $Compare    = qr{<=|>=|==|!=|<|>};
133
134
135
our $Operators	= qr{
			<=|>=|==|!=|
			=>|->|<<|>>|<|>|!|~|
136
			&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
137
138
		  }x;

139
140
141
142
our $NonptrType;
our $Type;
our $Declare;

143
144
145
146
147
148
149
150
151
152
153
our $UTF8	= qr {
	[\x09\x0A\x0D\x20-\x7E]              # ASCII
	| [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
	|  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
	| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
	|  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
	|  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
	| [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
	|  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
}x;

154
155
156
157
158
our $typeTypedefs = qr{(?x:
	(?:__)?(?:u|s|be|le)(?:\d|\d\d)|
	atomic_t
)};

159
160
our @typeList = (
	qr{void},
161
162
163
164
165
166
167
	qr{(?:unsigned\s+)?char},
	qr{(?:unsigned\s+)?short},
	qr{(?:unsigned\s+)?int},
	qr{(?:unsigned\s+)?long},
	qr{(?:unsigned\s+)?long\s+int},
	qr{(?:unsigned\s+)?long\s+long},
	qr{(?:unsigned\s+)?long\s+long\s+int},
168
169
170
171
172
173
174
175
176
177
178
	qr{unsigned},
	qr{float},
	qr{double},
	qr{bool},
	qr{struct\s+$Ident},
	qr{union\s+$Ident},
	qr{enum\s+$Ident},
	qr{${Ident}_t},
	qr{${Ident}_handler},
	qr{${Ident}_handler_fn},
);
179
180
181
our @modifierList = (
	qr{fastcall},
);
182
183

sub build_types {
184
185
	my $mods = "(?x:  \n" . join("|\n  ", @modifierList) . "\n)";
	my $all = "(?x:  \n" . join("|\n  ", @typeList) . "\n)";
186
	$Modifier	= qr{(?:$Attribute|$Sparse|$mods)};
187
	$NonptrType	= qr{
188
			(?:$Modifier\s+|const\s+)*
189
			(?:
190
				(?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
191
				(?:$typeTypedefs\b)|
192
				(?:${all}\b)
193
			)
194
			(?:\s+$Modifier|\s+const)*
195
196
		  }x;
	$Type	= qr{
197
			$NonptrType
198
			(?:[\s\*]+\s*const|[\s\*]+|(?:\s*\[\s*\])+)?
199
			(?:\s+$Inline|\s+$Modifier)*
200
201
202
203
		  }x;
	$Declare	= qr{(?:$Storage\s+)?$Type};
}
build_types();
204
205
206

$chk_signoff = 0 if ($file);

207
208
my @dep_includes = ();
my @dep_functions = ();
209
210
my $removal = "Documentation/feature-removal-schedule.txt";
if ($tree && -f "$root/$removal") {
211
	open(my $REMOVE, '<', "$root/$removal") ||
212
				die "$P: $removal: open failed - $!\n";
213
	while (<$REMOVE>) {
214
215
216
		if (/^Check:\s+(.*\S)/) {
			for my $entry (split(/[, ]+/, $1)) {
				if ($entry =~ m@include/(.*)@) {
217
218
					push(@dep_includes, $1);

219
220
221
				} elsif ($entry !~ m@/@) {
					push(@dep_functions, $entry);
				}
222
			}
223
224
		}
	}
225
	close($REMOVE);
226
227
}

228
my @rawlines = ();
229
230
my @lines = ();
my $vname;
231
for my $filename (@ARGV) {
232
	my $FILE;
233
	if ($file) {
234
		open($FILE, '-|', "diff -u /dev/null $filename") ||
235
			die "$P: $filename: diff failed - $!\n";
236
237
	} elsif ($filename eq '-') {
		open($FILE, '<&STDIN');
238
	} else {
239
		open($FILE, '<', "$filename") ||
240
			die "$P: $filename: open failed - $!\n";
241
	}
242
243
244
245
246
	if ($filename eq '-') {
		$vname = 'Your patch';
	} else {
		$vname = $filename;
	}
247
	while (<$FILE>) {
248
249
250
		chomp;
		push(@rawlines, $_);
	}
251
	close($FILE);
252
	if (!process($filename)) {
253
254
255
		$exit = 1;
	}
	@rawlines = ();
256
	@lines = ();
257
258
259
260
261
}

exit($exit);

sub top_of_kernel_tree {
262
263
264
265
266
267
268
269
270
271
272
273
	my ($root) = @_;

	my @tree_check = (
		"COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
		"README", "Documentation", "arch", "include", "drivers",
		"fs", "init", "ipc", "kernel", "lib", "scripts",
	);

	foreach my $check (@tree_check) {
		if (! -e $root . '/' . $check) {
			return 0;
		}
274
	}
275
	return 1;
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
}

sub expand_tabs {
	my ($str) = @_;

	my $res = '';
	my $n = 0;
	for my $c (split(//, $str)) {
		if ($c eq "\t") {
			$res .= ' ';
			$n++;
			for (; ($n % 8) != 0; $n++) {
				$res .= ' ';
			}
			next;
		}
		$res .= $c;
		$n++;
	}

	return $res;
}
298
sub copy_spacing {
299
	(my $res = shift) =~ tr/\t/ /c;
300
301
	return $res;
}
302

303
304
305
306
307
308
309
310
311
312
313
314
315
sub line_stats {
	my ($line) = @_;

	# Drop the diff line leader and expand tabs
	$line =~ s/^.//;
	$line = expand_tabs($line);

	# Pick the indent from the front of the line.
	my ($white) = ($line =~ /^(\s*)/);

	return (length($line), length($white));
}

316
317
318
319
320
321
322
323
324
325
326
my $sanitise_quote = '';

sub sanitise_line_reset {
	my ($in_comment) = @_;

	if ($in_comment) {
		$sanitise_quote = '*/';
	} else {
		$sanitise_quote = '';
	}
}
327
328
329
330
331
332
sub sanitise_line {
	my ($line) = @_;

	my $res = '';
	my $l = '';

333
	my $qlen = 0;
334
335
	my $off = 0;
	my $c;
336

337
338
339
340
341
342
343
344
345
346
347
348
349
350
	# Always copy over the diff marker.
	$res = substr($line, 0, 1);

	for ($off = 1; $off < length($line); $off++) {
		$c = substr($line, $off, 1);

		# Comments we are wacking completly including the begin
		# and end, all to $;.
		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
			$sanitise_quote = '*/';

			substr($res, $off, 2, "$;$;");
			$off++;
			next;
351
		}
352
		if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
353
354
355
356
			$sanitise_quote = '';
			substr($res, $off, 2, "$;$;");
			$off++;
			next;
357
		}
358
359
360
361
362
363
364

		# A \ in a string means ignore the next character.
		if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
		    $c eq "\\") {
			substr($res, $off, 2, 'XX');
			$off++;
			next;
365
		}
366
367
368
369
		# Regular quotes.
		if ($c eq "'" || $c eq '"') {
			if ($sanitise_quote eq '') {
				$sanitise_quote = $c;
370

371
372
373
374
375
376
				substr($res, $off, 1, $c);
				next;
			} elsif ($sanitise_quote eq $c) {
				$sanitise_quote = '';
			}
		}
377

378
		#print "c<$c> SQ<$sanitise_quote>\n";
379
380
381
382
383
384
385
		if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
			substr($res, $off, 1, $;);
		} elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
			substr($res, $off, 1, 'X');
		} else {
			substr($res, $off, 1, $c);
		}
386
387
388
	}

	# The pathname on a #include may be surrounded by '<' and '>'.
389
	if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
390
391
392
393
		my $clean = 'X' x length($1);
		$res =~ s@\<.*\>@<$clean>@;

	# The whole of a #error is a string.
394
	} elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
395
		my $clean = 'X' x length($1);
396
		$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
397
398
	}

399
400
401
	return $res;
}

402
403
404
405
406
407
sub ctx_statement_block {
	my ($linenr, $remain, $off) = @_;
	my $line = $linenr - 1;
	my $blk = '';
	my $soff = $off;
	my $coff = $off - 1;
408
	my $coff_set = 0;
409

410
411
	my $loff = 0;

412
413
	my $type = '';
	my $level = 0;
414
	my @stack = ([$type, $level]);
415
	my $p;
416
417
	my $c;
	my $len = 0;
418
419

	my $remainder;
420
	while (1) {
421
		#warn "CSB: blk<$blk> remain<$remain>\n";
422
423
424
425
		# If we are about to drop off the end, pull in more
		# context.
		if ($off >= $len) {
			for (; $remain > 0; $line++) {
426
				last if (!defined $lines[$line]);
427
				next if ($lines[$line] =~ /^-/);
428
				$remain--;
429
				$loff = $len;
430
				$blk .= $lines[$line] . "\n";
431
432
433
434
435
436
				$len = length($blk);
				$line++;
				last;
			}
			# Bail if there is no further context.
			#warn "CSB: blk<$blk> off<$off> len<$len>\n";
437
			if ($off >= $len) {
438
439
440
				last;
			}
		}
441
		$p = $c;
442
		$c = substr($blk, $off, 1);
443
		$remainder = substr($blk, $off);
444

445
		#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
446
447
448
449
450
451
452
453
454
455

		# Handle nested #if/#else.
		if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
			push(@stack, [ $type, $level ]);
		} elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
			($type, $level) = @{$stack[$#stack - 1]};
		} elsif ($remainder =~ /^#\s*endif\b/) {
			($type, $level) = @{pop(@stack)};
		}

456
457
458
459
460
461
		# Statement ends at the ';' or a close '}' at the
		# outermost level.
		if ($level == 0 && $c eq ';') {
			last;
		}

462
		# An else is really a conditional as long as its not else if
463
464
465
466
467
468
469
470
		if ($level == 0 && $coff_set == 0 &&
				(!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
				$remainder =~ /^(else)(?:\s|{)/ &&
				$remainder !~ /^else\s+if\b/) {
			$coff = $off + length($1) - 1;
			$coff_set = 1;
			#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
			#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
471
472
		}

473
474
475
476
477
478
479
480
481
482
		if (($type eq '' || $type eq '(') && $c eq '(') {
			$level++;
			$type = '(';
		}
		if ($type eq '(' && $c eq ')') {
			$level--;
			$type = ($level != 0)? '(' : '';

			if ($level == 0 && $coff < $soff) {
				$coff = $off;
483
484
				$coff_set = 1;
				#warn "CSB: mark coff<$coff>\n";
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
			}
		}
		if (($type eq '' || $type eq '{') && $c eq '{') {
			$level++;
			$type = '{';
		}
		if ($type eq '{' && $c eq '}') {
			$level--;
			$type = ($level != 0)? '{' : '';

			if ($level == 0) {
				last;
			}
		}
		$off++;
	}
501
	# We are truly at the end, so shuffle to the next line.
502
	if ($off == $len) {
503
		$loff = $len + 1;
504
505
506
		$line++;
		$remain--;
	}
507
508
509
510
511
512
513

	my $statement = substr($blk, $soff, $off - $soff + 1);
	my $condition = substr($blk, $soff, $coff - $soff + 1);

	#warn "STATEMENT<$statement>\n";
	#warn "CONDITION<$condition>\n";

514
	#print "coff<$coff> soff<$off> loff<$loff>\n";
515
516
517
518
519

	return ($statement, $condition,
			$line, $remain + 1, $off - $loff + 1, $level);
}

520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
sub statement_lines {
	my ($stmt) = @_;

	# Strip the diff line prefixes and rip blank lines at start and end.
	$stmt =~ s/(^|\n)./$1/g;
	$stmt =~ s/^\s*//;
	$stmt =~ s/\s*$//;

	my @stmt_lines = ($stmt =~ /\n/g);

	return $#stmt_lines + 2;
}

sub statement_rawlines {
	my ($stmt) = @_;

	my @stmt_lines = ($stmt =~ /\n/g);

	return $#stmt_lines + 2;
}

sub statement_block_size {
	my ($stmt) = @_;

	$stmt =~ s/(^|\n)./$1/g;
	$stmt =~ s/^\s*{//;
	$stmt =~ s/}\s*$//;
	$stmt =~ s/^\s*//;
	$stmt =~ s/\s*$//;

	my @stmt_lines = ($stmt =~ /\n/g);
	my @stmt_statements = ($stmt =~ /;/g);

	my $stmt_lines = $#stmt_lines + 2;
	my $stmt_statements = $#stmt_statements + 1;

	if ($stmt_lines > $stmt_statements) {
		return $stmt_lines;
	} else {
		return $stmt_statements;
	}
}

563
564
565
566
567
568
sub ctx_statement_full {
	my ($linenr, $remain, $off) = @_;
	my ($statement, $condition, $level);

	my (@chunks);

569
	# Grab the first conditional/block pair.
570
571
	($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
572
	#print "F: c<$condition> s<$statement> remain<$remain>\n";
573
574
575
576
577
578
579
	push(@chunks, [ $condition, $statement ]);
	if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
		return ($level, $linenr, @chunks);
	}

	# Pull in the following conditional/block pairs and see if they
	# could continue the statement.
580
581
582
	for (;;) {
		($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
583
		#print "C: c<$condition> s<$statement> remain<$remain>\n";
584
		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
585
586
		#print "C: push\n";
		push(@chunks, [ $condition, $statement ]);
587
588
589
	}

	return ($level, $linenr, @chunks);
590
591
}

592
sub ctx_block_get {
593
	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
594
595
596
597
598
599
600
	my $line;
	my $start = $linenr - 1;
	my $blk = '';
	my @o;
	my @c;
	my @res = ();

601
	my $level = 0;
602
	my @stack = ($level);
603
604
605
606
607
	for ($line = $start; $remain > 0; $line++) {
		next if ($rawlines[$line] =~ /^-/);
		$remain--;

		$blk .= $rawlines[$line];
608
609
610
611
612
613
614
615
616
617

		# Handle nested #if/#else.
		if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
			push(@stack, $level);
		} elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
			$level = $stack[$#stack - 1];
		} elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
			$level = pop(@stack);
		}

618
619
620
621
622
623
		foreach my $c (split(//, $rawlines[$line])) {
			##print "C<$c>L<$level><$open$close>O<$off>\n";
			if ($off > 0) {
				$off--;
				next;
			}
624

625
626
627
628
629
630
631
			if ($c eq $close && $level > 0) {
				$level--;
				last if ($level == 0);
			} elsif ($c eq $open) {
				$level++;
			}
		}
632

633
		if (!$outer || $level <= 1) {
634
			push(@res, $rawlines[$line]);
635
636
		}

637
		last if ($level == 0);
638
639
	}

640
	return ($level, @res);
641
642
643
644
}
sub ctx_block_outer {
	my ($linenr, $remain) = @_;

645
646
	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
	return @r;
647
648
649
650
}
sub ctx_block {
	my ($linenr, $remain) = @_;

651
652
	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
	return @r;
653
654
}
sub ctx_statement {
655
656
657
658
659
660
	my ($linenr, $remain, $off) = @_;

	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
	return @r;
}
sub ctx_block_level {
661
662
	my ($linenr, $remain) = @_;

663
	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
664
}
665
666
667
668
669
sub ctx_statement_level {
	my ($linenr, $remain, $off) = @_;

	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
}
670
671
672
673
674

sub ctx_locate_comment {
	my ($first_line, $end_line) = @_;

	# Catch a comment on the end of the line itself.
675
	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
676
677
678
679
680
681
682
	return $current_comment if (defined $current_comment);

	# Look through the context and try and figure out if there is a
	# comment.
	my $in_comment = 0;
	$current_comment = '';
	for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
683
684
		my $line = $rawlines[$linenr - 1];
		#warn "           $line\n";
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
		if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
			$in_comment = 1;
		}
		if ($line =~ m@/\*@) {
			$in_comment = 1;
		}
		if (!$in_comment && $current_comment ne '') {
			$current_comment = '';
		}
		$current_comment .= $line . "\n" if ($in_comment);
		if ($line =~ m@\*/@) {
			$in_comment = 0;
		}
	}

	chomp($current_comment);
	return($current_comment);
}
sub ctx_has_comment {
	my ($first_line, $end_line) = @_;
	my $cmt = ctx_locate_comment($first_line, $end_line);

707
	##print "LINE: $rawlines[$end_line - 1 ]\n";
708
709
710
711
712
	##print "CMMT: $cmt\n";

	return ($cmt ne '');
}

713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
sub raw_line {
	my ($linenr, $cnt) = @_;

	my $offset = $linenr - 1;
	$cnt++;

	my $line;
	while ($cnt) {
		$line = $rawlines[$offset++];
		next if (defined($line) && $line =~ /^-/);
		$cnt--;
	}

	return $line;
}

729
730
731
sub cat_vet {
	my ($vet) = @_;
	my ($res, $coded);
732

733
734
735
736
737
738
	$res = '';
	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
		$res .= $1;
		if ($2 ne '') {
			$coded = sprintf("^%c", unpack('C', $2) + 64);
			$res .= $coded;
739
740
		}
	}
741
	$res =~ s/$/\$/;
742

743
	return $res;
744
745
}

746
my $av_preprocessor = 0;
747
my $av_pending;
748
my @av_paren_type;
749
my $av_pend_colon;
750
751
752

sub annotate_reset {
	$av_preprocessor = 0;
753
754
	$av_pending = '_';
	@av_paren_type = ('E');
755
	$av_pend_colon = 'O';
756
757
}

758
759
sub annotate_values {
	my ($stream, $type) = @_;
760

761
	my $res;
762
	my $var = '_' x length($stream);
763
764
	my $cur = $stream;

765
	print "$stream\n" if ($dbg_values > 1);
766
767

	while (length($cur)) {
768
		@av_paren_type = ('E') if ($#av_paren_type < 0);
769
		print " <" . join('', @av_paren_type) .
770
				"> <$type> <$av_pending>" if ($dbg_values > 1);
771
		if ($cur =~ /^(\s+)/o) {
772
773
			print "WS($1)\n" if ($dbg_values > 1);
			if ($1 =~ /\n/ && $av_preprocessor) {
774
				$type = pop(@av_paren_type);
775
				$av_preprocessor = 0;
776
777
			}

778
		} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
779
			print "DECLARE($1)\n" if ($dbg_values > 1);
780
781
			$type = 'T';

782
783
784
785
		} elsif ($cur =~ /^($Modifier)\s*/) {
			print "MODIFIER($1)\n" if ($dbg_values > 1);
			$type = 'T';

786
		} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
787
			print "DEFINE($1,$2)\n" if ($dbg_values > 1);
788
			$av_preprocessor = 1;
789
790
791
792
793
794
			push(@av_paren_type, $type);
			if ($2 ne '') {
				$av_pending = 'N';
			}
			$type = 'E';

795
		} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
796
797
798
			print "UNDEF($1)\n" if ($dbg_values > 1);
			$av_preprocessor = 1;
			push(@av_paren_type, $type);
799

800
		} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
801
			print "PRE_START($1)\n" if ($dbg_values > 1);
802
			$av_preprocessor = 1;
803
804
805

			push(@av_paren_type, $type);
			push(@av_paren_type, $type);
806
			$type = 'E';
807

808
		} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
809
810
811
812
813
			print "PRE_RESTART($1)\n" if ($dbg_values > 1);
			$av_preprocessor = 1;

			push(@av_paren_type, $av_paren_type[$#av_paren_type]);

814
			$type = 'E';
815

816
		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
817
818
819
820
821
822
823
824
			print "PRE_END($1)\n" if ($dbg_values > 1);

			$av_preprocessor = 1;

			# Assume all arms of the conditional end as this
			# one does, and continue as if the #endif was not here.
			pop(@av_paren_type);
			push(@av_paren_type, $type);
825
			$type = 'E';
826
827

		} elsif ($cur =~ /^(\\\n)/o) {
828
			print "PRECONT($1)\n" if ($dbg_values > 1);
829

830
831
832
833
834
		} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
			print "ATTR($1)\n" if ($dbg_values > 1);
			$av_pending = $type;
			$type = 'N';

835
		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
836
			print "SIZEOF($1)\n" if ($dbg_values > 1);
837
			if (defined $2) {
838
				$av_pending = 'V';
839
840
841
			}
			$type = 'N';

842
		} elsif ($cur =~ /^(if|while|for)\b/o) {
843
			print "COND($1)\n" if ($dbg_values > 1);
844
			$av_pending = 'E';
845
846
			$type = 'N';

847
848
849
850
851
		} elsif ($cur =~/^(case)/o) {
			print "CASE($1)\n" if ($dbg_values > 1);
			$av_pend_colon = 'C';
			$type = 'N';

852
		} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
853
			print "KEYWORD($1)\n" if ($dbg_values > 1);
854
855
856
			$type = 'N';

		} elsif ($cur =~ /^(\()/o) {
857
			print "PAREN('$1')\n" if ($dbg_values > 1);
858
859
			push(@av_paren_type, $av_pending);
			$av_pending = '_';
860
861
862
			$type = 'N';

		} elsif ($cur =~ /^(\))/o) {
863
864
865
			my $new_type = pop(@av_paren_type);
			if ($new_type ne '_') {
				$type = $new_type;
866
867
				print "PAREN('$1') -> $type\n"
							if ($dbg_values > 1);
868
			} else {
869
				print "PAREN('$1')\n" if ($dbg_values > 1);
870
871
			}

872
		} elsif ($cur =~ /^($Ident)\s*\(/o) {
873
			print "FUNC($1)\n" if ($dbg_values > 1);
874
			$type = 'V';
875
			$av_pending = 'V';
876

877
878
		} elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
			if (defined $2 && $type eq 'C' || $type eq 'T') {
879
				$av_pend_colon = 'B';
880
881
			} elsif ($type eq 'E') {
				$av_pend_colon = 'L';
882
883
884
885
			}
			print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
			$type = 'V';

886
		} elsif ($cur =~ /^($Ident|$Constant)/o) {
887
			print "IDENT($1)\n" if ($dbg_values > 1);
888
889
890
			$type = 'V';

		} elsif ($cur =~ /^($Assignment)/o) {
891
			print "ASSIGN($1)\n" if ($dbg_values > 1);
892
893
			$type = 'N';

894
		} elsif ($cur =~/^(;|{|})/) {
895
			print "END($1)\n" if ($dbg_values > 1);
896
			$type = 'E';
897
898
			$av_pend_colon = 'O';

899
900
901
902
		} elsif ($cur =~/^(,)/) {
			print "COMMA($1)\n" if ($dbg_values > 1);
			$type = 'C';

903
904
905
906
907
908
909
910
911
912
913
914
915
916
		} elsif ($cur =~ /^(\?)/o) {
			print "QUESTION($1)\n" if ($dbg_values > 1);
			$type = 'N';

		} elsif ($cur =~ /^(:)/o) {
			print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);

			substr($var, length($res), 1, $av_pend_colon);
			if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
				$type = 'E';
			} else {
				$type = 'N';
			}
			$av_pend_colon = 'O';
917

918
		} elsif ($cur =~ /^(\[)/o) {
919
			print "CLOSE($1)\n" if ($dbg_values > 1);
920
921
			$type = 'N';

922
		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
923
924
925
926
927
928
929
930
931
932
933
934
			my $variant;

			print "OPV($1)\n" if ($dbg_values > 1);
			if ($type eq 'V') {
				$variant = 'B';
			} else {
				$variant = 'U';
			}

			substr($var, length($res), 1, $variant);
			$type = 'N';

935
		} elsif ($cur =~ /^($Operators)/o) {
936
			print "OP($1)\n" if ($dbg_values > 1);
937
938
939
940
941
			if ($1 ne '++' && $1 ne '--') {
				$type = 'N';
			}

		} elsif ($cur =~ /(^.)/o) {
942
			print "C($1)\n" if ($dbg_values > 1);
943
944
945
946
947
		}
		if (defined $1) {
			$cur = substr($cur, length($1));
			$res .= $type x length($1);
		}
948
	}
949

950
	return ($res, $var);
951
952
}

953
sub possible {
954
	my ($possible, $line) = @_;
955

956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
	print "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
	if ($possible !~ /(?:
		^(?:
			$Modifier|
			$Storage|
			$Type|
			DEFINE_\S+|
			goto|
			return|
			case|
			else|
			asm|__asm__|
			do
		)$|
		^(?:typedef|struct|enum)\b
	    )/x) {
972
973
974
975
976
977
978
		# Check for modifiers.
		$possible =~ s/\s*$Storage\s*//g;
		$possible =~ s/\s*$Sparse\s*//g;
		if ($possible =~ /^\s*$/) {

		} elsif ($possible =~ /\s/) {
			$possible =~ s/\s*$Type\s*//g;
979
980
981
982
			for my $modifier (split(' ', $possible)) {
				warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
				push(@modifierList, $modifier);
			}
983
984
985
986
987

		} else {
			warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
			push(@typeList, $possible);
		}
988
		build_types();
989
990
	} else {
		warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
991
992
993
	}
}

994
995
my $prefix = '';

996
sub report {
997
998
999
	if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
		return 0;
	}
1000
1001
1002
1003
	my $line = $prefix . $_[0];

	$line = (split('\n', $line))[0] . "\n" if ($terse);

1004
	push(our @report, $line);
1005
1006

	return 1;
1007
1008
}
sub report_dump {
1009
	our @report;
1010
}
1011
sub ERROR {
1012
1013
1014
1015
	if (report("ERROR: $_[0]\n")) {
		our $clean = 0;
		our $cnt_error++;
	}
1016
1017
}
sub WARN {
1018
1019
1020
1021
	if (report("WARNING: $_[0]\n")) {
		our $clean = 0;
		our $cnt_warn++;
	}
1022
1023
}
sub CHK {
1024
	if ($check && report("CHECK: $_[0]\n")) {
1025
1026
1027
		our $clean = 0;
		our $cnt_chk++;
	}
1028
1029
}

1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
sub check_absolute_file {
	my ($absolute, $herecurr) = @_;
	my $file = $absolute;

	##print "absolute<$absolute>\n";

	# See if any suffix of this path is a path within the tree.
	while ($file =~ s@^[^/]*/@@) {
		if (-f "$root/$file") {
			##print "file<$file>\n";
			last;
		}
	}
	if (! -f _)  {
		return 0;
	}

	# It is, so see if the prefix is acceptable.
	my $prefix = $absolute;
	substr($prefix, -length($file)) = '';

	##print "prefix<$prefix>\n";
	if ($prefix ne ".../") {
		WARN("use relative pathname instead of absolute in changelog text\n" . $herecurr);
	}
}

1057
1058
1059
1060
1061
sub process {
	my $filename = shift;

	my $linenr=0;
	my $prevline="";
1062
	my $prevrawline="";
1063
	my $stashline="";
1064
	my $stashrawline="";
1065

1066
	my $length;
1067
1068
1069
1070
	my $indent;
	my $previndent=0;
	my $stashindent=0;

1071
	our $clean = 1;
1072
1073
1074
	my $signoff = 0;
	my $is_patch = 0;

1075
	our @report = ();
1076
1077
1078
1079
1080
	our $cnt_lines = 0;
	our $cnt_error = 0;
	our $cnt_warn = 0;
	our $cnt_chk = 0;

1081
1082
1083
1084
1085
1086
	# Trace the real file/line as we go.
	my $realfile = '';
	my $realline = 0;
	my $realcnt = 0;
	my $here = '';
	my $in_comment = 0;
1087
	my $comment_edge = 0;
1088
	my $first_line = 0;
1089
	my $p1_prefix = '';
1090

1091
1092
1093
	my $prev_values = 'E';

	# suppression flags
1094
	my %suppress_ifbraces;
1095
	my %suppress_whiletrailers;
1096

1097
	# Pre-scan the patch sanitizing the lines.
1098
	# Pre-scan the patch looking for any __setup documentation.
1099
	#
1100
1101
	my @setup_docs = ();
	my $setup_docs = 0;
1102
1103

	sanitise_line_reset();
1104
1105
	my $line;
	foreach my $rawline (@rawlines) {
1106
1107
		$linenr++;
		$line = $rawline;
1108

1109
		if ($rawline=~/^\+\+\+\s+(\S+)/) {
1110
1111
1112
1113
			$setup_docs = 0;
			if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
				$setup_docs = 1;
			}
1114
1115
1116
1117
1118
1119
1120
1121
1122
			#next;
		}
		if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
			$realline=$1-1;
			if (defined $2) {
				$realcnt=$3+1;
			} else {
				$realcnt=1+1;
			}
1123
			$in_comment = 0;
1124
1125
1126
1127
1128
1129

			# Guestimate if this is a continuing comment.  Run
			# the context looking for a comment "edge".  If this
			# edge is a close comment then we must be in a comment
			# at context start.
			my $edge;
1130
1131
1132
1133
1134
1135
			my $cnt = $realcnt;
			for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
				next if (defined $rawlines[$ln - 1] &&
					 $rawlines[$ln - 1] =~ /^-/);
				$cnt--;
				#print "RAW<$rawlines[$ln - 1]>\n";
1136
				last if (!defined $rawlines[$ln - 1]);
1137
1138
1139
1140
1141
				if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
				    $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
					($edge) = $1;
					last;
				}
1142
1143
1144
1145
1146
1147
1148
1149
1150
			}
			if (defined $edge && $edge eq '*/') {
				$in_comment = 1;
			}

			# Guestimate if this is a continuing comment.  If this
			# is the start of a diff block and this line starts
			# ' *' then it is very likely a comment.
			if (!defined $edge &&
1151
			    $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
1152
1153
1154
1155
1156
1157
1158
			{
				$in_comment = 1;
			}

			##print "COMMENT:$in_comment edge<$edge> $rawline\n";
			sanitise_line_reset($in_comment);

1159
		} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
1160
			# Standardise the strings and chars within the input to
1161
			# simplify matching -- only bother with positive lines.
1162
			$line = sanitise_line($rawline);
1163
		}
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
		push(@lines,