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.27';
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 = ();
415
	my $p;
416
417
	my $c;
	my $len = 0;
418
419

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	my (@chunks);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return ($cmt ne '');
}

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

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

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

745
	return $res;
746
747
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

816
			$type = 'E';
817

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

996
997
my $prefix = '';

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

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

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

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

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

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

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

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

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

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

1093
1094
1095
	my $prev_values = 'E';

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

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

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

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

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

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

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