checkpatch.pl 68.9 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.28';
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
114
			__kprobes|
			__ref
115
116
117
118
119
		}x;
our $Attribute	= qr{
			const|
			__read_mostly|
			__kprobes|
120
121
122
			__(?:mem|cpu|dev|)(?:initdata|init)|
			____cacheline_aligned|
			____cacheline_aligned_in_smp|
123
124
			____cacheline_internodealigned_in_smp|
			__weak
125
		  }x;
126
our $Modifier;
127
128
129
130
131
132
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{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
133
our $Compare    = qr{<=|>=|==|!=|<|>};
134
135
136
our $Operators	= qr{
			<=|>=|==|!=|
			=>|->|<<|>>|<|>|!|~|
137
			&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
138
139
		  }x;

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

144
145
146
147
148
149
150
151
152
153
154
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;

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

160
161
our @typeList = (
	qr{void},
162
163
164
165
166
167
168
	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},
169
170
171
172
173
174
175
176
177
178
179
	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},
);
180
181
182
our @modifierList = (
	qr{fastcall},
);
183
184

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

$chk_signoff = 0 if ($file);

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

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

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

exit($exit);

sub top_of_kernel_tree {
263
264
265
266
267
268
269
270
271
272
273
274
	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;
		}
275
	}
276
	return 1;
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
}

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;
}
299
sub copy_spacing {
300
	(my $res = shift) =~ tr/\t/ /c;
301
302
	return $res;
}
303

304
305
306
307
308
309
310
311
312
313
314
315
316
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));
}

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

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

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

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

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

338
339
340
341
342
343
344
345
346
347
348
349
350
351
	# 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;
352
		}
353
		if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
354
355
356
357
			$sanitise_quote = '';
			substr($res, $off, 2, "$;$;");
			$off++;
			next;
358
		}
359
360
361
362
363
364
365

		# 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;
366
		}
367
368
369
370
		# Regular quotes.
		if ($c eq "'" || $c eq '"') {
			if ($sanitise_quote eq '') {
				$sanitise_quote = $c;
371

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

379
		#print "c<$c> SQ<$sanitise_quote>\n";
380
381
382
383
384
385
386
		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);
		}
387
388
389
	}

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

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

400
401
402
	return $res;
}

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

411
412
	my $loff = 0;

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

	my $remainder;
421
	while (1) {
422
423
		@stack = (['', 0]) if ($#stack == -1);

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

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

		# 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)};
		}

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

465
		# An else is really a conditional as long as its not else if
466
467
468
469
470
471
472
473
		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";
474
475
		}

476
477
478
479
480
481
482
483
484
485
		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;
486
487
				$coff_set = 1;
				#warn "CSB: mark coff<$coff>\n";
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
			}
		}
		if (($type eq '' || $type eq '{') && $c eq '{') {
			$level++;
			$type = '{';
		}
		if ($type eq '{' && $c eq '}') {
			$level--;
			$type = ($level != 0)? '{' : '';

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

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

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

517
	#print "coff<$coff> soff<$off> loff<$loff>\n";
518
519
520
521
522

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

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
563
564
565
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;
	}
}

566
567
568
569
570
571
sub ctx_statement_full {
	my ($linenr, $remain, $off) = @_;
	my ($statement, $condition, $level);

	my (@chunks);

572
	# Grab the first conditional/block pair.
573
574
	($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
575
	#print "F: c<$condition> s<$statement> remain<$remain>\n";
576
577
578
579
580
581
582
	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.
583
584
585
	for (;;) {
		($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
586
		#print "C: c<$condition> s<$statement> remain<$remain>\n";
587
		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
588
589
		#print "C: push\n";
		push(@chunks, [ $condition, $statement ]);
590
591
592
	}

	return ($level, $linenr, @chunks);
593
594
}

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

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

		$blk .= $rawlines[$line];
611
612
613
614
615
616
617
618
619
620

		# 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);
		}

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

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

636
		if (!$outer || $level <= 1) {
637
			push(@res, $rawlines[$line]);
638
639
		}

640
		last if ($level == 0);
641
642
	}

643
	return ($level, @res);
644
645
646
647
}
sub ctx_block_outer {
	my ($linenr, $remain) = @_;

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

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

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

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

	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
}
673
674
675
676
677

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

	# Catch a comment on the end of the line itself.
678
	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
679
680
681
682
683
684
685
	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++) {
686
687
		my $line = $rawlines[$linenr - 1];
		#warn "           $line\n";
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
		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);

710
	##print "LINE: $rawlines[$end_line - 1 ]\n";
711
712
713
714
715
	##print "CMMT: $cmt\n";

	return ($cmt ne '');
}

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
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;
}

732
733
734
sub cat_vet {
	my ($vet) = @_;
	my ($res, $coded);
735

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

746
	return $res;
747
748
}

749
my $av_preprocessor = 0;
750
my $av_pending;
751
my @av_paren_type;
752
my $av_pend_colon;
753
754
755

sub annotate_reset {
	$av_preprocessor = 0;
756
757
	$av_pending = '_';
	@av_paren_type = ('E');
758
	$av_pend_colon = 'O';
759
760
}

761
762
sub annotate_values {
	my ($stream, $type) = @_;
763

764
	my $res;
765
	my $var = '_' x length($stream);
766
767
	my $cur = $stream;

768
	print "$stream\n" if ($dbg_values > 1);
769
770

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

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

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

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

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

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

			push(@av_paren_type, $type);
			push(@av_paren_type, $type);
809
			$type = 'E';
810

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

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

817
			$type = 'E';
818

819
		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
820
821
822
823
824
825
826
827
			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);
828
			$type = 'E';
829
830

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

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

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

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

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

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

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

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

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

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

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

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

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

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

906
907
908
909
910
911
912
913
914
915
916
917
918
919
		} 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';
920

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

925
		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
926
927
928
929
930
931
932
933
934
935
936
937
			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';

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

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

953
	return ($res, $var);
954
955
}

956
sub possible {
957
	my ($possible, $line) = @_;
958

959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
	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) {
975
976
977
978
979
980
981
		# 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;
982
983
984
985
			for my $modifier (split(' ', $possible)) {
				warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
				push(@modifierList, $modifier);
			}
986
987
988
989
990

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

997
998
my $prefix = '';

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

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

1007
	push(our @report, $line);
1008
1009

	return 1;
1010
1011
}
sub report_dump {
1012
	our @report;
1013
}
1014
sub ERROR {
1015
1016
1017
1018
	if (report("ERROR: $_[0]\n")) {
		our $clean = 0;
		our $cnt_error++;
	}
1019
1020
}
sub WARN {
1021
1022
1023
1024
	if (report("WARNING: $_[0]\n")) {
		our $clean = 0;
		our $cnt_warn++;
	}
1025
1026
}
sub CHK {
1027
	if ($check && report("CHECK: $_[0]\n")) {
1028
1029
1030
		our $clean = 0;
		our $cnt_chk++;
	}
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
1057
1058
1059
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);
	}
}

1060
1061
1062
1063
1064
sub process {
	my $filename = shift;

	my $linenr=0;
	my $prevline="";
1065
	my $prevrawline="";
1066
	my $stashline="";
1067
	my $stashrawline="";
1068

1069
	my $length;
1070
1071
1072
1073
	my $indent;
	my $previndent=0;
	my $stashindent=0;

1074
	our $clean = 1;
1075
1076
1077
	my $signoff = 0;
	my $is_patch = 0;

1078
	our @report = ();
1079
1080
1081
1082
1083
	our $cnt_lines = 0;
	our $cnt_error = 0;
	our $cnt_warn = 0;
	our $cnt_chk = 0;

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

1094
1095
1096
	my $prev_values = 'E';

	# suppression flags
1097
	my %suppress_ifbraces;
1098
	my %suppress_whiletrailers;
1099

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

	sanitise_line_reset();
1107
1108
	my $line;
	foreach my $rawline (@rawlines) {
1109
1110
		$linenr++;
		$line = $rawline;
1111

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

			# 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;
1133
1134
1135
1136
1137
1138
			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";
1139
				last if (!defined $rawlines[$ln - 1]);
1140
1141
1142
1143
1144
				if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
				    $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
					($edge) = $1;
					last;
				}
1145
1146
1147
1148
1149
1150
1151
1152
1153
			}
			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 &&
1154
			    $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
1155
1156
1157
1158
1159
1160
1161
			{
				$in_comment = 1;
			}

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

1162
		} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
1163
			# Standardise the strings and chars within the input to
1164
			# simplify matching -- only bother with positive lines.
1165
			$line = sanitise_line($rawline);
1166
		}