checkpatch.pl 66.3 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)
4
5
6
7
8
9
# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
# Licensed under the terms of the GNU GPL License version 2

use strict;

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

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

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

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

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

my $exit = 0;

if ($#ARGV < 0) {
52
	print "usage: $P [options] patchfile\n";
53
	print "version: $V\n";
54
55
56
57
58
59
60
61
62
	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";
63
64
65
	exit(1);
}

66
67
my $dbg_values = 0;
my $dbg_possible = 0;
68
my $dbg_type = 0;
69
my $dbg_attr = 0;
70
71
72
73
for my $key (keys %debug) {
	eval "\${dbg_$key} = '$debug{$key}';"
}

74
75
76
77
78
if ($terse) {
	$emacs = 1;
	$quiet++;
}

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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);
	}
97
98
}

99
100
101
102
103
104
105
106
107
108
109
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|
110
			__kprobes
111
112
113
114
115
		}x;
our $Attribute	= qr{
			const|
			__read_mostly|
			__kprobes|
116
117
118
			__(?:mem|cpu|dev|)(?:initdata|init)|
			____cacheline_aligned|
			____cacheline_aligned_in_smp|
119
120
			____cacheline_internodealigned_in_smp|
			__weak
121
		  }x;
122
our $Modifier;
123
124
125
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{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
our $Operators	= qr{
			<=|>=|==|!=|
			=>|->|<<|>>|<|>|!|~|
132
			&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
133
134
		  }x;

135
136
137
138
our $NonptrType;
our $Type;
our $Declare;

139
140
141
142
143
144
145
146
147
148
149
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;

150
151
152
153
154
our $typeTypedefs = qr{(?x:
	(?:__)?(?:u|s|be|le)(?:\d|\d\d)|
	atomic_t
)};

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

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

$chk_signoff = 0 if ($file);

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

215
216
217
				} elsif ($entry !~ m@/@) {
					push(@dep_functions, $entry);
				}
218
			}
219
220
221
222
		}
	}
}

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

exit($exit);

sub top_of_kernel_tree {
254
255
256
257
258
259
260
261
262
263
264
265
	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;
		}
266
	}
267
	return 1;
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
}

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;
}
290
sub copy_spacing {
291
	(my $res = shift) =~ tr/\t/ /c;
292
293
	return $res;
}
294

295
296
297
298
299
300
301
302
303
304
305
306
307
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));
}

308
309
310
311
312
313
314
315
316
317
318
my $sanitise_quote = '';

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

	if ($in_comment) {
		$sanitise_quote = '*/';
	} else {
		$sanitise_quote = '';
	}
}
319
320
321
322
323
324
sub sanitise_line {
	my ($line) = @_;

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

325
	my $qlen = 0;
326
327
	my $off = 0;
	my $c;
328

329
330
331
332
333
334
335
336
337
338
339
340
341
342
	# 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;
343
		}
344
		if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
345
346
347
348
			$sanitise_quote = '';
			substr($res, $off, 2, "$;$;");
			$off++;
			next;
349
		}
350
351
352
353
354
355
356

		# 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;
357
		}
358
359
360
361
		# Regular quotes.
		if ($c eq "'" || $c eq '"') {
			if ($sanitise_quote eq '') {
				$sanitise_quote = $c;
362

363
364
365
366
367
368
				substr($res, $off, 1, $c);
				next;
			} elsif ($sanitise_quote eq $c) {
				$sanitise_quote = '';
			}
		}
369

370
371
372
373
374
375
376
377
		#print "SQ:$sanitise_quote\n";
		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);
		}
378
379
380
	}

	# The pathname on a #include may be surrounded by '<' and '>'.
381
	if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
382
383
384
385
		my $clean = 'X' x length($1);
		$res =~ s@\<.*\>@<$clean>@;

	# The whole of a #error is a string.
386
	} elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
387
		my $clean = 'X' x length($1);
388
		$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
389
390
	}

391
392
393
	return $res;
}

394
395
396
397
398
399
sub ctx_statement_block {
	my ($linenr, $remain, $off) = @_;
	my $line = $linenr - 1;
	my $blk = '';
	my $soff = $off;
	my $coff = $off - 1;
400
	my $coff_set = 0;
401

402
403
	my $loff = 0;

404
405
	my $type = '';
	my $level = 0;
406
	my $p;
407
408
	my $c;
	my $len = 0;
409
410

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

436
		#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
437
438
439
440
441
442
		# Statement ends at the ';' or a close '}' at the
		# outermost level.
		if ($level == 0 && $c eq ';') {
			last;
		}

443
		# An else is really a conditional as long as its not else if
444
445
446
447
448
449
450
451
		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";
452
453
		}

454
455
456
457
458
459
460
461
462
463
		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;
464
465
				$coff_set = 1;
				#warn "CSB: mark coff<$coff>\n";
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
			}
		}
		if (($type eq '' || $type eq '{') && $c eq '{') {
			$level++;
			$type = '{';
		}
		if ($type eq '{' && $c eq '}') {
			$level--;
			$type = ($level != 0)? '{' : '';

			if ($level == 0) {
				last;
			}
		}
		$off++;
	}
482
	# We are truly at the end, so shuffle to the next line.
483
	if ($off == $len) {
484
		$loff = $len + 1;
485
486
487
		$line++;
		$remain--;
	}
488
489
490
491
492
493
494

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

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

495
	#print "coff<$coff> soff<$off> loff<$loff>\n";
496
497
498
499
500

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

501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
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;
	}
}

544
545
546
547
548
549
sub ctx_statement_full {
	my ($linenr, $remain, $off) = @_;
	my ($statement, $condition, $level);

	my (@chunks);

550
	# Grab the first conditional/block pair.
551
552
	($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
553
	#print "F: c<$condition> s<$statement> remain<$remain>\n";
554
555
556
557
558
559
560
	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.
561
562
563
	for (;;) {
		($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
564
		#print "C: c<$condition> s<$statement> remain<$remain>\n";
565
		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
566
567
		#print "C: push\n";
		push(@chunks, [ $condition, $statement ]);
568
569
570
	}

	return ($level, $linenr, @chunks);
571
572
}

573
sub ctx_block_get {
574
	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
575
576
577
578
579
580
581
	my $line;
	my $start = $linenr - 1;
	my $blk = '';
	my @o;
	my @c;
	my @res = ();

582
	my $level = 0;
583
584
585
586
587
	for ($line = $start; $remain > 0; $line++) {
		next if ($rawlines[$line] =~ /^-/);
		$remain--;

		$blk .= $rawlines[$line];
588
589
590
591
592
593
		foreach my $c (split(//, $rawlines[$line])) {
			##print "C<$c>L<$level><$open$close>O<$off>\n";
			if ($off > 0) {
				$off--;
				next;
			}
594

595
596
597
598
599
600
601
			if ($c eq $close && $level > 0) {
				$level--;
				last if ($level == 0);
			} elsif ($c eq $open) {
				$level++;
			}
		}
602

603
		if (!$outer || $level <= 1) {
604
			push(@res, $rawlines[$line]);
605
606
		}

607
		last if ($level == 0);
608
609
	}

610
	return ($level, @res);
611
612
613
614
}
sub ctx_block_outer {
	my ($linenr, $remain) = @_;

615
616
	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
	return @r;
617
618
619
620
}
sub ctx_block {
	my ($linenr, $remain) = @_;

621
622
	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
	return @r;
623
624
}
sub ctx_statement {
625
626
627
628
629
630
	my ($linenr, $remain, $off) = @_;

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

633
	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
634
}
635
636
637
638
639
sub ctx_statement_level {
	my ($linenr, $remain, $off) = @_;

	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
}
640
641
642
643
644

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

	# Catch a comment on the end of the line itself.
645
	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
646
647
648
649
650
651
652
	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++) {
653
654
		my $line = $rawlines[$linenr - 1];
		#warn "           $line\n";
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
		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);

677
	##print "LINE: $rawlines[$end_line - 1 ]\n";
678
679
680
681
682
	##print "CMMT: $cmt\n";

	return ($cmt ne '');
}

683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
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;
}

699
700
701
sub cat_vet {
	my ($vet) = @_;
	my ($res, $coded);
702

703
704
705
706
707
708
	$res = '';
	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
		$res .= $1;
		if ($2 ne '') {
			$coded = sprintf("^%c", unpack('C', $2) + 64);
			$res .= $coded;
709
710
		}
	}
711
	$res =~ s/$/\$/;
712

713
	return $res;
714
715
}

716
my $av_preprocessor = 0;
717
my $av_pending;
718
my @av_paren_type;
719
my $av_pend_colon;
720
721
722

sub annotate_reset {
	$av_preprocessor = 0;
723
724
	$av_pending = '_';
	@av_paren_type = ('E');
725
	$av_pend_colon = 'O';
726
727
}

728
729
sub annotate_values {
	my ($stream, $type) = @_;
730

731
	my $res;
732
	my $var = '_' x length($stream);
733
734
	my $cur = $stream;

735
	print "$stream\n" if ($dbg_values > 1);
736
737

	while (length($cur)) {
738
		@av_paren_type = ('E') if ($#av_paren_type < 0);
739
		print " <" . join('', @av_paren_type) .
740
				"> <$type> <$av_pending>" if ($dbg_values > 1);
741
		if ($cur =~ /^(\s+)/o) {
742
743
			print "WS($1)\n" if ($dbg_values > 1);
			if ($1 =~ /\n/ && $av_preprocessor) {
744
				$type = pop(@av_paren_type);
745
				$av_preprocessor = 0;
746
747
			}

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

752
753
754
755
		} elsif ($cur =~ /^($Modifier)\s*/) {
			print "MODIFIER($1)\n" if ($dbg_values > 1);
			$type = 'T';

756
		} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
757
			print "DEFINE($1,$2)\n" if ($dbg_values > 1);
758
			$av_preprocessor = 1;
759
760
761
762
763
764
			push(@av_paren_type, $type);
			if ($2 ne '') {
				$av_pending = 'N';
			}
			$type = 'E';

765
		} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
766
767
768
			print "UNDEF($1)\n" if ($dbg_values > 1);
			$av_preprocessor = 1;
			push(@av_paren_type, $type);
769

770
		} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
771
			print "PRE_START($1)\n" if ($dbg_values > 1);
772
			$av_preprocessor = 1;
773
774
775

			push(@av_paren_type, $type);
			push(@av_paren_type, $type);
776
			$type = 'E';
777

778
		} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
779
780
781
782
783
			print "PRE_RESTART($1)\n" if ($dbg_values > 1);
			$av_preprocessor = 1;

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

784
			$type = 'E';
785

786
		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
787
788
789
790
791
792
793
794
			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);
795
			$type = 'E';
796
797

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

800
801
802
803
804
		} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
			print "ATTR($1)\n" if ($dbg_values > 1);
			$av_pending = $type;
			$type = 'N';

805
		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
806
			print "SIZEOF($1)\n" if ($dbg_values > 1);
807
			if (defined $2) {
808
				$av_pending = 'V';
809
810
811
			}
			$type = 'N';

812
		} elsif ($cur =~ /^(if|while|for)\b/o) {
813
			print "COND($1)\n" if ($dbg_values > 1);
814
			$av_pending = 'E';
815
816
			$type = 'N';

817
818
819
820
821
		} elsif ($cur =~/^(case)/o) {
			print "CASE($1)\n" if ($dbg_values > 1);
			$av_pend_colon = 'C';
			$type = 'N';

822
		} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
823
			print "KEYWORD($1)\n" if ($dbg_values > 1);
824
825
826
			$type = 'N';

		} elsif ($cur =~ /^(\()/o) {
827
			print "PAREN('$1')\n" if ($dbg_values > 1);
828
829
			push(@av_paren_type, $av_pending);
			$av_pending = '_';
830
831
832
			$type = 'N';

		} elsif ($cur =~ /^(\))/o) {
833
834
835
			my $new_type = pop(@av_paren_type);
			if ($new_type ne '_') {
				$type = $new_type;
836
837
				print "PAREN('$1') -> $type\n"
							if ($dbg_values > 1);
838
			} else {
839
				print "PAREN('$1')\n" if ($dbg_values > 1);
840
841
			}

842
		} elsif ($cur =~ /^($Ident)\s*\(/o) {
843
			print "FUNC($1)\n" if ($dbg_values > 1);
844
			$type = 'V';
845
			$av_pending = 'V';
846

847
848
849
850
851
852
853
854
855
		} elsif ($cur =~ /^($Ident\s*):/) {
			if ($type eq 'E') {
				$av_pend_colon = 'L';
			} elsif ($type eq 'T') {
				$av_pend_colon = 'B';
			}
			print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
			$type = 'V';

856
		} elsif ($cur =~ /^($Ident|$Constant)/o) {
857
			print "IDENT($1)\n" if ($dbg_values > 1);
858
859
860
			$type = 'V';

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

864
		} elsif ($cur =~/^(;|{|})/) {
865
			print "END($1)\n" if ($dbg_values > 1);
866
			$type = 'E';
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
			$av_pend_colon = 'O';

		} 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';
883

884
		} elsif ($cur =~ /^(;|\[)/o) {
885
			print "CLOSE($1)\n" if ($dbg_values > 1);
886
887
			$type = 'N';

888
		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
889
890
891
892
893
894
895
896
897
898
899
900
			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';

901
		} elsif ($cur =~ /^($Operators)/o) {
902
			print "OP($1)\n" if ($dbg_values > 1);
903
904
905
906
907
			if ($1 ne '++' && $1 ne '--') {
				$type = 'N';
			}

		} elsif ($cur =~ /(^.)/o) {
908
			print "C($1)\n" if ($dbg_values > 1);
909
910
911
912
913
		}
		if (defined $1) {
			$cur = substr($cur, length($1));
			$res .= $type x length($1);
		}
914
	}
915

916
	return ($res, $var);
917
918
}

919
sub possible {
920
	my ($possible, $line) = @_;
921

922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
	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) {
938
939
940
941
942
943
944
		# 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;
945
946
947
948
			for my $modifier (split(' ', $possible)) {
				warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
				push(@modifierList, $modifier);
			}
949
950
951
952
953

		} else {
			warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
			push(@typeList, $possible);
		}
954
		build_types();
955
956
	} else {
		warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
957
958
959
	}
}

960
961
my $prefix = '';

962
sub report {
963
964
965
	if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
		return 0;
	}
966
967
968
969
	my $line = $prefix . $_[0];

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

970
	push(our @report, $line);
971
972

	return 1;
973
974
}
sub report_dump {
975
	our @report;
976
}
977
sub ERROR {
978
979
980
981
	if (report("ERROR: $_[0]\n")) {
		our $clean = 0;
		our $cnt_error++;
	}
982
983
}
sub WARN {
984
985
986
987
	if (report("WARNING: $_[0]\n")) {
		our $clean = 0;
		our $cnt_warn++;
	}
988
989
}
sub CHK {
990
	if ($check && report("CHECK: $_[0]\n")) {
991
992
993
		our $clean = 0;
		our $cnt_chk++;
	}
994
995
}

996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
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);
	}
}

1023
1024
1025
1026
1027
sub process {
	my $filename = shift;

	my $linenr=0;
	my $prevline="";
1028
	my $prevrawline="";
1029
	my $stashline="";
1030
	my $stashrawline="";
1031

1032
	my $length;
1033
1034
1035
1036
	my $indent;
	my $previndent=0;
	my $stashindent=0;

1037
	our $clean = 1;
1038
1039
1040
	my $signoff = 0;
	my $is_patch = 0;

1041
	our @report = ();
1042
1043
1044
1045
1046
	our $cnt_lines = 0;
	our $cnt_error = 0;
	our $cnt_warn = 0;
	our $cnt_chk = 0;

1047
1048
1049
1050
1051
1052
	# Trace the real file/line as we go.
	my $realfile = '';
	my $realline = 0;
	my $realcnt = 0;
	my $here = '';
	my $in_comment = 0;
1053
	my $comment_edge = 0;
1054
1055
	my $first_line = 0;

1056
1057
1058
	my $prev_values = 'E';

	# suppression flags
1059
	my %suppress_ifbraces;
1060
	my %suppress_whiletrailers;
1061

1062
	# Pre-scan the patch sanitizing the lines.
1063
	# Pre-scan the patch looking for any __setup documentation.
1064
	#
1065
1066
	my @setup_docs = ();
	my $setup_docs = 0;
1067
1068

	sanitise_line_reset();
1069
1070
	my $line;
	foreach my $rawline (@rawlines) {
1071
1072
		$linenr++;
		$line = $rawline;
1073

1074
		if ($rawline=~/^\+\+\+\s+(\S+)/) {
1075
1076
1077
1078
			$setup_docs = 0;
			if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
				$setup_docs = 1;
			}
1079
1080
1081
1082
1083
1084
1085
1086
1087
			#next;
		}
		if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
			$realline=$1-1;
			if (defined $2) {
				$realcnt=$3+1;
			} else {
				$realcnt=1+1;
			}
1088
			$in_comment = 0;
1089
1090
1091
1092
1093
1094

			# 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;
1095
1096
1097
1098
1099
1100
			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";
1101
1102
				last if (!defined $rawlines[$ln - 1]);
				($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
				last if (defined $edge);
			}
			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 &&
1113
			    $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
1114
1115
1116
1117
1118
1119
1120
			{
				$in_comment = 1;
			}

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

1121
		} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
1122
			# Standardise the strings and chars within the input to
1123
			# simplify matching -- only bother with positive lines.
1124
			$line = sanitise_line($rawline);
1125
		}
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
		push(@lines, $line);

		if ($realcnt > 1) {
			$realcnt-- if ($line =~ /^(?:\+| |$)/);
		} else {
			$realcnt = 0;
		}

		#print "==>$rawline\n";
		#print "-->$line\n";
1136
1137
1138
1139
1140
1141

		if ($setup_docs && $line =~ /^\+/) {
			push(@setup_docs, $line);
		}
	}

1142
1143
	$prefix = '';

1144
1145
	$realcnt = 0;
	$linenr = 0;
1146
1147
1148
	foreach my $line (@lines) {
		$linenr++;

1149
		my $rawline = $rawlines[$linenr - 1];
1150
		my $hunk_line = ($realcnt != 0);
1151

1152
#extract the line range in the file after the patch is applied
1153
		if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
1154
			$is_patch = 1;
1155
			$first_line = $linenr + 1;
1156
1157
1158
1159
1160
1161
			$realline=$1-1;
			if (defined $2) {
				$realcnt=$3+1;
			} else {
				$realcnt=1+1;
			}
1162
			annotate_reset();
1163
1164
			$prev_values = 'E';

1165
			%suppress_ifbraces = ();
1166
			%suppress_whiletrailers = ();
1167
1168
			next;

1169
1170
1171
# track the line number as we move through the hunk, note that
# new versions of GNU diff omit the leading space on completely
# blank context lines so we need to count that too.
1172
		} elsif ($line =~ /^( |\+|$)/) {
1173
			$realline++;
1174
			$realcnt-- if ($realcnt != 0);
1175

1176
			# Measure the line length and indent.
1177
			($length, $indent) = line_stats($rawline);
1178
1179
1180
1181

			# Track the previous line.
			($prevline, $stashline) = ($stashline, $line);
			($previndent, $stashindent) = ($stashindent, $indent);
1182
1183
			($prevrawline, $stashrawline) = ($stashrawline, $rawline);

1184
			#warn "line<$line>\n";
1185

1186
1187
		} elsif ($realcnt == 1) {
			$realcnt--;