checkpatch.pl 72.3 KB
Newer Older
1
#!/usr/bin/perl -w
2
# (c) 2001, Dave Jones. (the file handling bit)
3
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
Andy Whitcroft's avatar
Andy Whitcroft committed
4
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
5
# (c) 2008,2009, 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.30';
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
my $help = 0;

sub help {
	my ($exitcode) = @_;

	print << "EOM";
Usage: $P [OPTION]... [FILE]...
Version: $V

Options:
  -q, --quiet                quiet
  --no-tree                  run without a kernel tree
  --no-signoff               do not check for 'Signed-off-by' line
  --patch                    treat FILE as patchfile (default)
  --emacs                    emacs compile window format
  --terse                    one line per report
  -f, --file                 treat FILE as regular source file
  --subjective, --strict     enable more subjective tests
  --root=PATH                PATH to the kernel tree root
  --no-summary               suppress the per-file summary
  --mailback                 only produce a report in case of warnings/errors
  --summary-file             include the filename in summary
  --debug KEY=[0|1]          turn on/off debugging of KEY, where KEY is one of
                             'values', 'possible', 'type', and 'attr' (default
                             is all off)
  --test-only=WORD           report only warnings/errors containing WORD
                             literally
  -h, --help, --version      display this help and exit

When FILE is - read standard input.
EOM

	exit($exitcode);
}

66
GetOptions(
67
	'q|quiet+'	=> \$quiet,
68
69
70
	'tree!'		=> \$tree,
	'signoff!'	=> \$chk_signoff,
	'patch!'	=> \$chk_patch,
71
	'emacs!'	=> \$emacs,
72
	'terse!'	=> \$terse,
73
	'f|file!'	=> \$file,
74
75
76
	'subjective!'	=> \$check,
	'strict!'	=> \$check,
	'root=s'	=> \$root,
77
78
	'summary!'	=> \$summary,
	'mailback!'	=> \$mailback,
79
80
	'summary-file!'	=> \$summary_file,

81
	'debug=s'	=> \%debug,
82
	'test-only=s'	=> \$tst_only,
83
84
85
86
87
	'h|help'	=> \$help,
	'version'	=> \$help
) or help(1);

help(0) if ($help);
88
89
90
91

my $exit = 0;

if ($#ARGV < 0) {
92
	print "$P: no input files\n";
93
94
95
	exit(1);
}

96
97
my $dbg_values = 0;
my $dbg_possible = 0;
98
my $dbg_type = 0;
99
my $dbg_attr = 0;
100
for my $key (keys %debug) {
101
102
103
	## no critic
	eval "\${dbg_$key} = '$debug{$key}';";
	die "$@" if ($@);
104
105
}

106
107
108
109
110
if ($terse) {
	$emacs = 1;
	$quiet++;
}

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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);
	}
129
130
}

131
132
my $emitted_corrupt = 0;

133
134
135
136
our $Ident	= qr{
			[A-Za-z_][A-Za-z\d_]*
			(?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
		}x;
137
138
139
140
141
142
143
144
our $Storage	= qr{extern|static|asmlinkage};
our $Sparse	= qr{
			__user|
			__kernel|
			__force|
			__iomem|
			__must_check|
			__init_refok|
145
146
			__kprobes|
			__ref
147
148
149
150
151
		}x;
our $Attribute	= qr{
			const|
			__read_mostly|
			__kprobes|
152
153
154
			__(?:mem|cpu|dev|)(?:initdata|init)|
			____cacheline_aligned|
			____cacheline_aligned_in_smp|
155
156
			____cacheline_internodealigned_in_smp|
			__weak
157
		  }x;
158
our $Modifier;
159
160
161
162
163
164
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{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
165
our $Compare    = qr{<=|>=|==|!=|<|>};
166
167
168
our $Operators	= qr{
			<=|>=|==|!=|
			=>|->|<<|>>|<|>|!|~|
169
			&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
170
171
		  }x;

172
173
174
175
our $NonptrType;
our $Type;
our $Declare;

176
177
178
179
180
181
182
183
184
185
186
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;

187
our $typeTypedefs = qr{(?x:
188
	(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
189
190
191
	atomic_t
)};

192
193
194
195
196
197
198
199
our $logFunctions = qr{(?x:
	printk|
	pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
	dev_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
	WARN|
	panic
)};

200
201
our @typeList = (
	qr{void},
202
203
204
205
206
207
208
	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},
209
210
211
212
213
214
215
216
217
218
219
	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},
);
220
221
222
our @modifierList = (
	qr{fastcall},
);
223
224

sub build_types {
225
226
	my $mods = "(?x:  \n" . join("|\n  ", @modifierList) . "\n)";
	my $all = "(?x:  \n" . join("|\n  ", @typeList) . "\n)";
227
	$Modifier	= qr{(?:$Attribute|$Sparse|$mods)};
228
	$NonptrType	= qr{
229
			(?:$Modifier\s+|const\s+)*
230
			(?:
231
				(?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
232
				(?:$typeTypedefs\b)|
233
				(?:${all}\b)
234
			)
235
			(?:\s+$Modifier|\s+const)*
236
237
		  }x;
	$Type	= qr{
238
			$NonptrType
239
			(?:[\s\*]+\s*const|[\s\*]+|(?:\s*\[\s*\])+)?
240
			(?:\s+$Inline|\s+$Modifier)*
241
242
243
244
		  }x;
	$Declare	= qr{(?:$Storage\s+)?$Type};
}
build_types();
245
246
247

$chk_signoff = 0 if ($file);

248
249
my @dep_includes = ();
my @dep_functions = ();
250
251
my $removal = "Documentation/feature-removal-schedule.txt";
if ($tree && -f "$root/$removal") {
252
	open(my $REMOVE, '<', "$root/$removal") ||
253
				die "$P: $removal: open failed - $!\n";
254
	while (<$REMOVE>) {
255
256
257
		if (/^Check:\s+(.*\S)/) {
			for my $entry (split(/[, ]+/, $1)) {
				if ($entry =~ m@include/(.*)@) {
258
259
					push(@dep_includes, $1);

260
261
262
				} elsif ($entry !~ m@/@) {
					push(@dep_functions, $entry);
				}
263
			}
264
265
		}
	}
266
	close($REMOVE);
267
268
}

269
my @rawlines = ();
270
271
my @lines = ();
my $vname;
272
for my $filename (@ARGV) {
273
	my $FILE;
274
	if ($file) {
275
		open($FILE, '-|', "diff -u /dev/null $filename") ||
276
			die "$P: $filename: diff failed - $!\n";
277
278
	} elsif ($filename eq '-') {
		open($FILE, '<&STDIN');
279
	} else {
280
		open($FILE, '<', "$filename") ||
281
			die "$P: $filename: open failed - $!\n";
282
	}
283
284
285
286
287
	if ($filename eq '-') {
		$vname = 'Your patch';
	} else {
		$vname = $filename;
	}
288
	while (<$FILE>) {
289
290
291
		chomp;
		push(@rawlines, $_);
	}
292
	close($FILE);
293
	if (!process($filename)) {
294
295
296
		$exit = 1;
	}
	@rawlines = ();
297
	@lines = ();
298
299
300
301
302
}

exit($exit);

sub top_of_kernel_tree {
303
304
305
306
307
308
309
310
311
312
313
314
	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;
		}
315
	}
316
	return 1;
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
}

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;
}
339
sub copy_spacing {
340
	(my $res = shift) =~ tr/\t/ /c;
341
342
	return $res;
}
343

344
345
346
347
348
349
350
351
352
353
354
355
356
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));
}

357
358
359
360
361
362
363
364
365
366
367
my $sanitise_quote = '';

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

	if ($in_comment) {
		$sanitise_quote = '*/';
	} else {
		$sanitise_quote = '';
	}
}
368
369
370
371
372
373
sub sanitise_line {
	my ($line) = @_;

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

374
	my $qlen = 0;
375
376
	my $off = 0;
	my $c;
377

378
379
380
381
382
383
384
385
386
387
388
389
390
391
	# 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;
392
		}
393
		if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
394
395
396
397
			$sanitise_quote = '';
			substr($res, $off, 2, "$;$;");
			$off++;
			next;
398
		}
399
400
401
402
403
404
405
		if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
			$sanitise_quote = '//';

			substr($res, $off, 2, $sanitise_quote);
			$off++;
			next;
		}
406
407
408
409
410
411
412

		# 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;
413
		}
414
415
416
417
		# Regular quotes.
		if ($c eq "'" || $c eq '"') {
			if ($sanitise_quote eq '') {
				$sanitise_quote = $c;
418

419
420
421
422
423
424
				substr($res, $off, 1, $c);
				next;
			} elsif ($sanitise_quote eq $c) {
				$sanitise_quote = '';
			}
		}
425

426
		#print "c<$c> SQ<$sanitise_quote>\n";
427
428
		if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
			substr($res, $off, 1, $;);
429
430
		} elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
			substr($res, $off, 1, $;);
431
432
433
434
435
		} elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
			substr($res, $off, 1, 'X');
		} else {
			substr($res, $off, 1, $c);
		}
436
437
	}

438
439
440
441
	if ($sanitise_quote eq '//') {
		$sanitise_quote = '';
	}

442
	# The pathname on a #include may be surrounded by '<' and '>'.
443
	if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
444
445
446
447
		my $clean = 'X' x length($1);
		$res =~ s@\<.*\>@<$clean>@;

	# The whole of a #error is a string.
448
	} elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
449
		my $clean = 'X' x length($1);
450
		$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
451
452
	}

453
454
455
	return $res;
}

456
457
458
459
460
461
sub ctx_statement_block {
	my ($linenr, $remain, $off) = @_;
	my $line = $linenr - 1;
	my $blk = '';
	my $soff = $off;
	my $coff = $off - 1;
462
	my $coff_set = 0;
463

464
465
	my $loff = 0;

466
467
	my $type = '';
	my $level = 0;
468
	my @stack = ();
469
	my $p;
470
471
	my $c;
	my $len = 0;
472
473

	my $remainder;
474
	while (1) {
475
476
		@stack = (['', 0]) if ($#stack == -1);

477
		#warn "CSB: blk<$blk> remain<$remain>\n";
478
479
480
481
		# If we are about to drop off the end, pull in more
		# context.
		if ($off >= $len) {
			for (; $remain > 0; $line++) {
482
				last if (!defined $lines[$line]);
483
				next if ($lines[$line] =~ /^-/);
484
				$remain--;
485
				$loff = $len;
486
				$blk .= $lines[$line] . "\n";
487
488
489
490
491
492
				$len = length($blk);
				$line++;
				last;
			}
			# Bail if there is no further context.
			#warn "CSB: blk<$blk> off<$off> len<$len>\n";
493
			if ($off >= $len) {
494
495
496
				last;
			}
		}
497
		$p = $c;
498
		$c = substr($blk, $off, 1);
499
		$remainder = substr($blk, $off);
500

501
		#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
502
503
504
505
506
507
508
509
510
511

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

512
513
514
515
516
517
		# Statement ends at the ';' or a close '}' at the
		# outermost level.
		if ($level == 0 && $c eq ';') {
			last;
		}

518
		# An else is really a conditional as long as its not else if
519
520
521
522
523
524
525
526
		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";
527
528
		}

529
530
531
532
533
534
535
536
537
538
		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;
539
540
				$coff_set = 1;
				#warn "CSB: mark coff<$coff>\n";
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
			}
		}
		if (($type eq '' || $type eq '{') && $c eq '{') {
			$level++;
			$type = '{';
		}
		if ($type eq '{' && $c eq '}') {
			$level--;
			$type = ($level != 0)? '{' : '';

			if ($level == 0) {
				last;
			}
		}
		$off++;
	}
557
	# We are truly at the end, so shuffle to the next line.
558
	if ($off == $len) {
559
		$loff = $len + 1;
560
561
562
		$line++;
		$remain--;
	}
563
564
565
566
567
568
569

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

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

570
	#print "coff<$coff> soff<$off> loff<$loff>\n";
571
572
573
574
575

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

576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
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;
	}
}

619
620
621
622
623
624
sub ctx_statement_full {
	my ($linenr, $remain, $off) = @_;
	my ($statement, $condition, $level);

	my (@chunks);

625
	# Grab the first conditional/block pair.
626
627
	($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
628
	#print "F: c<$condition> s<$statement> remain<$remain>\n";
629
630
631
632
633
634
635
	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.
636
637
638
	for (;;) {
		($statement, $condition, $linenr, $remain, $off, $level) =
				ctx_statement_block($linenr, $remain, $off);
639
		#print "C: c<$condition> s<$statement> remain<$remain>\n";
640
		last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
641
642
		#print "C: push\n";
		push(@chunks, [ $condition, $statement ]);
643
644
645
	}

	return ($level, $linenr, @chunks);
646
647
}

648
sub ctx_block_get {
649
	my ($linenr, $remain, $outer, $open, $close, $off) = @_;
650
651
652
653
654
655
656
	my $line;
	my $start = $linenr - 1;
	my $blk = '';
	my @o;
	my @c;
	my @res = ();

657
	my $level = 0;
658
	my @stack = ($level);
659
660
661
662
663
	for ($line = $start; $remain > 0; $line++) {
		next if ($rawlines[$line] =~ /^-/);
		$remain--;

		$blk .= $rawlines[$line];
664
665
666
667
668
669
670
671
672
673

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

674
675
676
677
678
679
		foreach my $c (split(//, $rawlines[$line])) {
			##print "C<$c>L<$level><$open$close>O<$off>\n";
			if ($off > 0) {
				$off--;
				next;
			}
680

681
682
683
684
685
686
687
			if ($c eq $close && $level > 0) {
				$level--;
				last if ($level == 0);
			} elsif ($c eq $open) {
				$level++;
			}
		}
688

689
		if (!$outer || $level <= 1) {
690
			push(@res, $rawlines[$line]);
691
692
		}

693
		last if ($level == 0);
694
695
	}

696
	return ($level, @res);
697
698
699
700
}
sub ctx_block_outer {
	my ($linenr, $remain) = @_;

701
702
	my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
	return @r;
703
704
705
706
}
sub ctx_block {
	my ($linenr, $remain) = @_;

707
708
	my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
	return @r;
709
710
}
sub ctx_statement {
711
712
713
714
715
716
	my ($linenr, $remain, $off) = @_;

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

719
	return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
720
}
721
722
723
724
725
sub ctx_statement_level {
	my ($linenr, $remain, $off) = @_;

	return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
}
726
727
728
729
730

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

	# Catch a comment on the end of the line itself.
731
	my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
732
733
734
735
736
737
738
	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++) {
739
740
		my $line = $rawlines[$linenr - 1];
		#warn "           $line\n";
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
		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);

763
	##print "LINE: $rawlines[$end_line - 1 ]\n";
764
765
766
767
768
	##print "CMMT: $cmt\n";

	return ($cmt ne '');
}

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
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;
}

785
786
787
sub cat_vet {
	my ($vet) = @_;
	my ($res, $coded);
788

789
790
791
792
793
794
	$res = '';
	while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
		$res .= $1;
		if ($2 ne '') {
			$coded = sprintf("^%c", unpack('C', $2) + 64);
			$res .= $coded;
795
796
		}
	}
797
	$res =~ s/$/\$/;
798

799
	return $res;
800
801
}

802
my $av_preprocessor = 0;
803
my $av_pending;
804
my @av_paren_type;
805
my $av_pend_colon;
806
807
808

sub annotate_reset {
	$av_preprocessor = 0;
809
810
	$av_pending = '_';
	@av_paren_type = ('E');
811
	$av_pend_colon = 'O';
812
813
}

814
815
sub annotate_values {
	my ($stream, $type) = @_;
816

817
	my $res;
818
	my $var = '_' x length($stream);
819
820
	my $cur = $stream;

821
	print "$stream\n" if ($dbg_values > 1);
822
823

	while (length($cur)) {
824
		@av_paren_type = ('E') if ($#av_paren_type < 0);
825
		print " <" . join('', @av_paren_type) .
826
				"> <$type> <$av_pending>" if ($dbg_values > 1);
827
		if ($cur =~ /^(\s+)/o) {
828
829
			print "WS($1)\n" if ($dbg_values > 1);
			if ($1 =~ /\n/ && $av_preprocessor) {
830
				$type = pop(@av_paren_type);
831
				$av_preprocessor = 0;
832
833
			}

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

838
839
840
841
		} elsif ($cur =~ /^($Modifier)\s*/) {
			print "MODIFIER($1)\n" if ($dbg_values > 1);
			$type = 'T';

842
		} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
843
			print "DEFINE($1,$2)\n" if ($dbg_values > 1);
844
			$av_preprocessor = 1;
845
846
847
848
849
850
			push(@av_paren_type, $type);
			if ($2 ne '') {
				$av_pending = 'N';
			}
			$type = 'E';

851
		} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
852
853
854
			print "UNDEF($1)\n" if ($dbg_values > 1);
			$av_preprocessor = 1;
			push(@av_paren_type, $type);
855

856
		} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
857
			print "PRE_START($1)\n" if ($dbg_values > 1);
858
			$av_preprocessor = 1;
859
860
861

			push(@av_paren_type, $type);
			push(@av_paren_type, $type);
862
			$type = 'E';
863

864
		} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
865
866
867
868
869
			print "PRE_RESTART($1)\n" if ($dbg_values > 1);
			$av_preprocessor = 1;

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

870
			$type = 'E';
871

872
		} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
873
874
875
876
877
878
879
880
			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);
881
			$type = 'E';
882
883

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

886
887
888
889
890
		} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
			print "ATTR($1)\n" if ($dbg_values > 1);
			$av_pending = $type;
			$type = 'N';

891
		} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
892
			print "SIZEOF($1)\n" if ($dbg_values > 1);
893
			if (defined $2) {
894
				$av_pending = 'V';
895
896
897
			}
			$type = 'N';

898
		} elsif ($cur =~ /^(if|while|for)\b/o) {
899
			print "COND($1)\n" if ($dbg_values > 1);
900
			$av_pending = 'E';
901
902
			$type = 'N';

903
904
905
906
907
		} elsif ($cur =~/^(case)/o) {
			print "CASE($1)\n" if ($dbg_values > 1);
			$av_pend_colon = 'C';
			$type = 'N';

908
		} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
909
			print "KEYWORD($1)\n" if ($dbg_values > 1);
910
911
912
			$type = 'N';

		} elsif ($cur =~ /^(\()/o) {
913
			print "PAREN('$1')\n" if ($dbg_values > 1);
914
915
			push(@av_paren_type, $av_pending);
			$av_pending = '_';
916
917
918
			$type = 'N';

		} elsif ($cur =~ /^(\))/o) {
919
920
921
			my $new_type = pop(@av_paren_type);
			if ($new_type ne '_') {
				$type = $new_type;
922
923
				print "PAREN('$1') -> $type\n"
							if ($dbg_values > 1);
924
			} else {
925
				print "PAREN('$1')\n" if ($dbg_values > 1);
926
927
			}

928
		} elsif ($cur =~ /^($Ident)\s*\(/o) {
929
			print "FUNC($1)\n" if ($dbg_values > 1);
930
			$type = 'V';
931
			$av_pending = 'V';
932

933
934
		} elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
			if (defined $2 && $type eq 'C' || $type eq 'T') {
935
				$av_pend_colon = 'B';
936
937
			} elsif ($type eq 'E') {
				$av_pend_colon = 'L';
938
939
940
941
			}
			print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
			$type = 'V';

942
		} elsif ($cur =~ /^($Ident|$Constant)/o) {
943
			print "IDENT($1)\n" if ($dbg_values > 1);
944
945
946
			$type = 'V';

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

950
		} elsif ($cur =~/^(;|{|})/) {
951
			print "END($1)\n" if ($dbg_values > 1);
952
			$type = 'E';
953
954
			$av_pend_colon = 'O';

955
956
957
958
		} elsif ($cur =~/^(,)/) {
			print "COMMA($1)\n" if ($dbg_values > 1);
			$type = 'C';

959
960
961
962
963
964
965
966
967
968
969
970
971
972
		} 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';
973

974
		} elsif ($cur =~ /^(\[)/o) {
975
			print "CLOSE($1)\n" if ($dbg_values > 1);
976
977
			$type = 'N';

978
		} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
979
980
981
982
983
984
985
986
987
988
989
990
			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';

991
		} elsif ($cur =~ /^($Operators)/o) {
992
			print "OP($1)\n" if ($dbg_values > 1);
993
994
995
996
997
			if ($1 ne '++' && $1 ne '--') {
				$type = 'N';
			}

		} elsif ($cur =~ /(^.)/o) {
998
			print "C($1)\n" if ($dbg_values > 1);
999
1000
1001
1002
1003
		}
		if (defined $1) {
			$cur = substr($cur, length($1));
			$res .= $type x length($1);
		}
1004
	}
1005

1006
	return ($res, $var);
1007
1008
}

1009
sub possible {
1010
	my ($possible, $line) = @_;
1011
	my $notPermitted = qr{(?:
1012
1013
1014
1015
		^(?:
			$Modifier|
			$Storage|
			$Type|
1016
1017
1018
			DEFINE_\S+
		)$|
		^(?:
1019
1020
1021
1022
1023
1024
			goto|
			return|
			case|
			else|
			asm|__asm__|
			do
1025
		)(?:\s|$)|
1026
		^(?:typedef|struct|enum)\b
1027
1028
1029
	    )}x;
	warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
	if ($possible !~ $notPermitted) {
1030
1031
1032
1033
1034
1035
1036
		# 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;
1037
			for my $modifier (split(' ', $possible)) {
1038
1039
1040
1041
				if ($modifier !~ $notPermitted) {
					warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
					push(@modifierList, $modifier);
				}
1042
			}
1043
1044
1045
1046
1047

		} else {
			warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
			push(@typeList, $possible);
		}
1048
		build_types();
1049
1050
	} else {
		warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
1051
1052
1053
	}
}

1054
1055
my $prefix = '';

1056
sub report {
1057
1058
1059
	if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
		return 0;
	}
1060
1061
1062
1063
	my $line = $prefix . $_[0];

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

1064
	push(our @report, $line);
1065
1066

	return 1;
1067
1068
}
sub report_dump {
1069
	our @report;
1070
}
1071
sub ERROR {
1072
1073
1074
1075
	if (report("ERROR: $_[0]\n")) {
		our $clean = 0;
		our $cnt_error++;
	}
1076
1077
}
sub WARN {
1078
1079
1080
1081
	if (report("WARNING: $_[0]\n")) {
		our $clean = 0;
		our $cnt_warn++;
	}
1082
1083
}
sub CHK {
1084
	if ($check && report("CHECK: $_[0]\n")) {
1085
1086
1087
		our $clean = 0;
		our $cnt_chk++;
	}
1088
1089
}

1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
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);
	}
}

1117
1118
1119
1120
1121
sub process {
	my $filename = shift;

	my $linenr=0;
	my $prevline="";
1122
	my $prevrawline="";
1123
	my $stashline="";
1124
	my $stashrawline="";
1125

1126
	my $length;
1127
1128
1129
1130
	my $indent;
	my $previndent=0;
	my $stashindent=0;

1131
	our $clean = 1;
1132
1133
1134
	my $signoff = 0;
	my $is_patch = 0;

1135
	our @report = ();
1136
1137
1138
1139
1140
	our $cnt_lines = 0;
	our $cnt_error = 0;
	our $cnt_warn = 0;
	our $cnt_chk = 0;

1141
1142
1143
1144
1145
1146
	# Trace the real file/line as we go.
	my $realfile = '';
	my $realline = 0;
	my $realcnt = 0;
	my $here = '';
	my $in_comment = 0;
1147
	my $comment_edge = 0;
1148
	my $first_line = 0;
1149
	my $p1_prefix = '';
1150

1151
1152
1153
	my $prev_values = 'E';

	# suppression flags
1154
	my %suppress_ifbraces;
1155
	my %suppress_whiletrailers;
1156
	my %suppress_export;
1157

1158
	# Pre-scan the patch sanitizing the lines.
1159
	# Pre-scan the patch looking for any __setup documentation.
1160
	#
1161
1162
	my @setup_docs = ();
	my $setup_docs = 0;