Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/build/checkstyle9.pl
39478 views
1
#!/usr/bin/env perl
2
# (c) 2001, Dave Jones. (the file handling bit)
3
# (c) 2005, Joel Schopp <[email protected]> (the ugly bit)
4
# (c) 2007,2008, Andy Whitcroft <[email protected]> (new conditions, test suite)
5
# (c) 2008-2010 Andy Whitcroft <[email protected]>
6
# Licensed under the terms of the GNU GPL License version 2
7
8
use strict;
9
use warnings;
10
use Term::ANSIColor qw(:constants);
11
12
my $P = $0;
13
$P =~ s@.*/@@g;
14
15
our $SrcFile = qr{\.(?:h|c|cpp|hpp|hh|cc|S|sh)$};
16
17
my $V = '0.31';
18
19
use Getopt::Long qw(:config no_auto_abbrev);
20
21
my $quiet = 0;
22
my $tree = 1;
23
my $chk_signoff = 1;
24
my $chk_patch = undef;
25
my $chk_branch = undef;
26
my $tst_only;
27
my $emacs = 0;
28
my $github = 0;
29
my $terse = 0;
30
my $file = undef;
31
my $color = "auto";
32
my $no_warnings = 0;
33
my $summary = 1;
34
my $mailback = 0;
35
my $summary_file = 0;
36
my $root;
37
my %debug;
38
my $help = 0;
39
40
sub help {
41
my ($exitcode) = @_;
42
43
print << "EOM";
44
Usage:
45
46
$P [OPTION]... [FILE]...
47
$P [OPTION]... [GIT-REV-LIST]
48
49
Version: $V
50
51
Options:
52
-q, --quiet quiet
53
--patch treat FILE as patchfile
54
--branch treat args as GIT revision list
55
--emacs emacs compile window format
56
--terse one line per report
57
-f, --file treat FILE as regular source file
58
--strict fail if only warnings are found
59
--no-summary suppress the per-file summary
60
--mailback only produce a report in case of warnings/errors
61
--summary-file include the filename in summary
62
--debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of
63
'values', 'possible', 'type', and 'attr' (default
64
is all off)
65
--test-only=WORD report only warnings/errors containing WORD
66
literally
67
--color[=WHEN] Use colors 'always', 'never', or only when output
68
is a terminal ('auto'). Default is 'auto'.
69
-h, --help, --version display this help and exit
70
71
When FILE is - read standard input.
72
EOM
73
74
exit($exitcode);
75
}
76
77
# Use at your own risk
78
print "\n", MAGENTA, "WARNING:", RESET, " This code is highly experimental ... likely isn't a great style(9) match yet\n\n";
79
80
# Perl's Getopt::Long allows options to take optional arguments after a space.
81
# Prevent --color by itself from consuming other arguments
82
foreach (@ARGV) {
83
if ($_ eq "--color" || $_ eq "-color") {
84
$_ = "--color=$color";
85
}
86
}
87
88
GetOptions(
89
'q|quiet+' => \$quiet,
90
'tree!' => \$tree,
91
'signoff!' => \$chk_signoff,
92
'patch!' => \$chk_patch,
93
'branch!' => \$chk_branch,
94
'emacs!' => \$emacs,
95
'github!' => \$github,
96
'terse!' => \$terse,
97
'f|file!' => \$file,
98
'strict!' => \$no_warnings,
99
'root=s' => \$root,
100
'summary!' => \$summary,
101
'mailback!' => \$mailback,
102
'summary-file!' => \$summary_file,
103
104
'debug=s' => \%debug,
105
'test-only=s' => \$tst_only,
106
'color=s' => \$color,
107
'no-color' => sub { $color = 'never'; },
108
'h|help' => \$help,
109
'version' => \$help
110
) or help(1);
111
112
help(0) if ($help);
113
114
my $exit = 0;
115
116
if ($#ARGV < 0) {
117
print "$P: no input files\n";
118
exit(1);
119
}
120
121
if (!defined $chk_branch && !defined $chk_patch && !defined $file) {
122
$chk_branch = $ARGV[0] =~ /.\.\./ ? 1 : 0;
123
$file = $ARGV[0] =~ /$SrcFile/ ? 1 : 0;
124
$chk_patch = $chk_branch || $file ? 0 : 1;
125
} elsif (!defined $chk_branch && !defined $chk_patch) {
126
if ($file) {
127
$chk_branch = $chk_patch = 0;
128
} else {
129
$chk_branch = $ARGV[0] =~ /.\.\./ ? 1 : 0;
130
$chk_patch = $chk_branch ? 0 : 1;
131
}
132
} elsif (!defined $chk_branch && !defined $file) {
133
if ($chk_patch) {
134
$chk_branch = $file = 0;
135
} else {
136
$chk_branch = $ARGV[0] =~ /.\.\./ ? 1 : 0;
137
$file = $chk_branch ? 0 : 1;
138
}
139
} elsif (!defined $chk_patch && !defined $file) {
140
if ($chk_branch) {
141
$chk_patch = $file = 0;
142
} else {
143
$file = $ARGV[0] =~ /$SrcFile/ ? 1 : 0;
144
$chk_patch = $file ? 0 : 1;
145
}
146
} elsif (!defined $chk_branch) {
147
$chk_branch = $chk_patch || $file ? 0 : 1;
148
} elsif (!defined $chk_patch) {
149
$chk_patch = $chk_branch || $file ? 0 : 1;
150
} elsif (!defined $file) {
151
$file = $chk_patch || $chk_branch ? 0 : 1;
152
}
153
154
if (($chk_patch && $chk_branch) ||
155
($chk_patch && $file) ||
156
($chk_branch && $file)) {
157
die "Only one of --file, --branch, --patch is permitted\n";
158
}
159
if (!$chk_patch && !$chk_branch && !$file) {
160
die "One of --file, --branch, --patch is required\n";
161
}
162
163
if ($color =~ /^always$/i) {
164
$color = 1;
165
} elsif ($color =~ /^never$/i) {
166
$color = 0;
167
} elsif ($color =~ /^auto$/i) {
168
$color = (-t STDOUT);
169
} else {
170
die "Invalid color mode: $color\n";
171
}
172
173
my $dbg_values = 0;
174
my $dbg_possible = 0;
175
my $dbg_adv_dcs = 0;
176
my $dbg_adv_checking = 0;
177
my $dbg_adv_apw = 0;
178
for my $key (keys %debug) {
179
## no critic
180
eval "\${dbg_$key} = '$debug{$key}';";
181
die "$@" if ($@);
182
}
183
184
my $rpt_cleaners = 0;
185
186
if ($terse) {
187
$emacs = 1;
188
$quiet++;
189
}
190
191
my $emitted_corrupt = 0;
192
193
our $Ident = qr{
194
[A-Za-z_][A-Za-z\d_]*
195
(?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
196
}x;
197
our $Storage = qr{extern|static|asmlinkage};
198
our $Sparse = qr{
199
__force
200
}x;
201
202
# Notes to $Attribute:
203
our $Attribute = qr{
204
const|
205
_*restrict|
206
volatile|
207
QEMU_NORETURN|
208
QEMU_WARN_UNUSED_RESULT|
209
QEMU_SENTINEL|
210
QEMU_PACKED|
211
GCC_FMT_ATTR
212
}x;
213
our $Modifier;
214
our $Inline = qr{inline};
215
our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
216
our $Lval = qr{$Ident(?:$Member)*};
217
218
our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
219
our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
220
our $Compare = qr{<=|>=|==|!=|<|>};
221
our $Operators = qr{
222
<=|>=|==|!=|
223
=>|->|<<|>>|<|>|!|~|
224
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
225
}x;
226
227
our $NonptrType;
228
our $Type;
229
our $Declare;
230
231
our $NON_ASCII_UTF8 = qr{
232
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
233
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
234
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
235
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
236
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
237
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
238
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
239
}x;
240
241
our $UTF8 = qr{
242
[\x09\x0A\x0D\x20-\x7E] # ASCII
243
| $NON_ASCII_UTF8
244
}x;
245
246
# some readers default to ISO-8859-1 when showing email source. detect
247
# when UTF-8 is incorrectly interpreted as ISO-8859-1 and reencoded back.
248
# False positives are possible but very unlikely.
249
our $UTF8_MOJIBAKE = qr{
250
\xC3[\x82-\x9F] \xC2[\x80-\xBF] # c2-df 80-bf
251
| \xC3\xA0 \xC2[\xA0-\xBF] \xC2[\x80-\xBF] # e0 a0-bf 80-bf
252
| \xC3[\xA1-\xAC\xAE\xAF] (?: \xC2[\x80-\xBF]){2} # e1-ec/ee/ef 80-bf 80-bf
253
| \xC3\xAD \xC2[\x80-\x9F] \xC2[\x80-\xBF] # ed 80-9f 80-bf
254
| \xC3\xB0 \xC2[\x90-\xBF] (?: \xC2[\x80-\xBF]){2} # f0 90-bf 80-bf 80-bf
255
| \xC3[\xB1-\xB3] (?: \xC2[\x80-\xBF]){3} # f1-f3 80-bf 80-bf 80-bf
256
| \xC3\xB4 \xC2[\x80-\x8F] (?: \xC2[\x80-\xBF]){2} # f4 80-b8 80-bf 80-bf
257
}x;
258
259
# There are still some false positives, but this catches most
260
# common cases.
261
our $typeTypedefs = qr{(?x:
262
(?![KMGTPE]iB) # IEC binary prefix (do not match)
263
[A-Z][A-Z\d_]*[a-z][A-Za-z\d_]* # camelcase
264
| [A-Z][A-Z\d_]*AIOCB # all uppercase
265
| [A-Z][A-Z\d_]*CPU # all uppercase
266
| QEMUBH # all uppercase
267
)};
268
269
our @typeList = (
270
qr{void},
271
qr{(?:unsigned\s+)?char},
272
qr{(?:unsigned\s+)?short},
273
qr{(?:unsigned\s+)?int},
274
qr{(?:unsigned\s+)?long},
275
qr{(?:unsigned\s+)?long\s+int},
276
qr{(?:unsigned\s+)?long\s+long},
277
qr{(?:unsigned\s+)?long\s+long\s+int},
278
qr{unsigned},
279
qr{float},
280
qr{double},
281
qr{bool},
282
qr{struct\s+$Ident},
283
qr{union\s+$Ident},
284
qr{enum\s+$Ident},
285
qr{${Ident}_t},
286
qr{${Ident}_handler},
287
qr{${Ident}_handler_fn},
288
qr{target_(?:u)?long},
289
qr{hwaddr},
290
);
291
292
# This can be modified by sub possible. Since it can be empty, be careful
293
# about regexes that always match, because they can cause infinite loops.
294
our @modifierList = (
295
);
296
297
sub build_types {
298
my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
299
if (@modifierList > 0) {
300
my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
301
$Modifier = qr{(?:$Attribute|$Sparse|$mods)};
302
} else {
303
$Modifier = qr{(?:$Attribute|$Sparse)};
304
}
305
$NonptrType = qr{
306
(?:$Modifier\s+|const\s+)*
307
(?:
308
(?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
309
(?:$typeTypedefs\b)|
310
(?:${all}\b)
311
)
312
(?:\s+$Modifier|\s+const)*
313
}x;
314
$Type = qr{
315
$NonptrType
316
(?:[\s\*]+\s*const|[\s\*]+|(?:\s*\[\s*\])+)?
317
(?:\s+$Inline|\s+$Modifier)*
318
}x;
319
$Declare = qr{(?:$Storage\s+)?$Type};
320
}
321
build_types();
322
323
$chk_signoff = 0 if ($file);
324
325
my @rawlines = ();
326
my @lines = ();
327
my $vname;
328
if ($chk_branch) {
329
my @patches;
330
my %git_commits = ();
331
my $HASH;
332
open($HASH, "-|", "git", "log", "--reverse", "--no-merges", "--format=%H %s", $ARGV[0]) ||
333
die "$P: git log --reverse --no-merges --format='%H %s' $ARGV[0] failed - $!\n";
334
335
for my $line (<$HASH>) {
336
$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
337
next if (!defined($1) || !defined($2));
338
my $sha1 = $1;
339
my $subject = $2;
340
push(@patches, $sha1);
341
$git_commits{$sha1} = $subject;
342
}
343
344
close $HASH;
345
346
die "$P: no revisions returned for revlist '$ARGV[0]'\n"
347
unless @patches;
348
349
my $i = 1;
350
my $num_patches = @patches;
351
for my $hash (@patches) {
352
my $FILE;
353
open($FILE, '-|', "git", "show", "--patch-with-stat", $hash) ||
354
die "$P: git show $hash - $!\n";
355
while (<$FILE>) {
356
chomp;
357
push(@rawlines, $_);
358
}
359
close($FILE);
360
$vname = substr($hash, 0, 12) . ' (' . $git_commits{$hash} . ')';
361
if ($num_patches > 1 && $quiet == 0) {
362
my $prefix = "$i/$num_patches";
363
$prefix = BLUE . BOLD . $prefix . RESET if $color;
364
print "$prefix Checking commit $vname\n";
365
$vname = "Patch $i/$num_patches";
366
} else {
367
$vname = "Commit " . $vname;
368
}
369
if (!process($hash)) {
370
$exit = 1;
371
print "\n" if ($num_patches > 1 && $quiet == 0);
372
}
373
@rawlines = ();
374
@lines = ();
375
$i++;
376
}
377
} else {
378
for my $filename (@ARGV) {
379
my $FILE;
380
if ($file) {
381
open($FILE, '-|', "diff -u /dev/null $filename") ||
382
die "$P: $filename: diff failed - $!\n";
383
} elsif ($filename eq '-') {
384
open($FILE, '<&STDIN');
385
} else {
386
open($FILE, '<', "$filename") ||
387
die "$P: $filename: open failed - $!\n";
388
}
389
if ($filename eq '-') {
390
$vname = 'Your patch';
391
} else {
392
$vname = $filename;
393
}
394
print "Checking $filename...\n" if @ARGV > 1 && $quiet == 0;
395
while (<$FILE>) {
396
chomp;
397
push(@rawlines, $_);
398
}
399
close($FILE);
400
if (!process($filename)) {
401
$exit = 1;
402
}
403
@rawlines = ();
404
@lines = ();
405
}
406
}
407
408
exit($exit);
409
410
sub top_of_kernel_tree {
411
my ($root) = @_;
412
413
my @tree_check = (
414
"Makefile.inc1", "README.md", "sys",
415
"usr.sbin"
416
);
417
418
foreach my $check (@tree_check) {
419
if (! -e $root . '/' . $check) {
420
return 0;
421
}
422
}
423
return 1;
424
}
425
426
sub expand_tabs {
427
my ($str) = @_;
428
429
my $res = '';
430
my $n = 0;
431
for my $c (split(//, $str)) {
432
if ($c eq "\t") {
433
$res .= ' ';
434
$n++;
435
for (; ($n % 8) != 0; $n++) {
436
$res .= ' ';
437
}
438
next;
439
}
440
$res .= $c;
441
$n++;
442
}
443
444
return $res;
445
}
446
sub copy_spacing {
447
(my $res = shift) =~ tr/\t/ /c;
448
return $res;
449
}
450
451
sub line_stats {
452
my ($line) = @_;
453
454
# Drop the diff line leader and expand tabs
455
$line =~ s/^.//;
456
$line = expand_tabs($line);
457
458
# Pick the indent from the front of the line.
459
my ($white) = ($line =~ /^(\s*)/);
460
461
return (length($line), length($white));
462
}
463
464
my $sanitise_quote = '';
465
466
sub sanitise_line_reset {
467
my ($in_comment) = @_;
468
469
if ($in_comment) {
470
$sanitise_quote = '*/';
471
} else {
472
$sanitise_quote = '';
473
}
474
}
475
sub sanitise_line {
476
my ($line) = @_;
477
478
my $res = '';
479
my $l = '';
480
481
my $qlen = 0;
482
my $off = 0;
483
my $c;
484
485
# Always copy over the diff marker.
486
$res = substr($line, 0, 1);
487
488
for ($off = 1; $off < length($line); $off++) {
489
$c = substr($line, $off, 1);
490
491
# Comments we are wacking completely including the begin
492
# and end, all to $;.
493
if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
494
$sanitise_quote = '*/';
495
496
substr($res, $off, 2, "$;$;");
497
$off++;
498
next;
499
}
500
if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
501
$sanitise_quote = '';
502
substr($res, $off, 2, "$;$;");
503
$off++;
504
next;
505
}
506
if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
507
$sanitise_quote = '//';
508
509
substr($res, $off, 2, $sanitise_quote);
510
$off++;
511
next;
512
}
513
514
# A \ in a string means ignore the next character.
515
if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
516
$c eq "\\") {
517
substr($res, $off, 2, 'XX');
518
$off++;
519
next;
520
}
521
# Regular quotes.
522
if ($c eq "'" || $c eq '"') {
523
if ($sanitise_quote eq '') {
524
$sanitise_quote = $c;
525
526
substr($res, $off, 1, $c);
527
next;
528
} elsif ($sanitise_quote eq $c) {
529
$sanitise_quote = '';
530
}
531
}
532
533
#print "c<$c> SQ<$sanitise_quote>\n";
534
if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
535
substr($res, $off, 1, $;);
536
} elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
537
substr($res, $off, 1, $;);
538
} elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
539
substr($res, $off, 1, 'X');
540
} else {
541
substr($res, $off, 1, $c);
542
}
543
}
544
545
if ($sanitise_quote eq '//') {
546
$sanitise_quote = '';
547
}
548
549
# The pathname on a #include may be surrounded by '<' and '>'.
550
if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
551
my $clean = 'X' x length($1);
552
$res =~ s@\<.*\>@<$clean>@;
553
554
# The whole of a #error is a string.
555
} elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
556
my $clean = 'X' x length($1);
557
$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
558
}
559
560
return $res;
561
}
562
563
sub ctx_statement_block {
564
my ($linenr, $remain, $off) = @_;
565
my $line = $linenr - 1;
566
my $blk = '';
567
my $soff = $off;
568
my $coff = $off - 1;
569
my $coff_set = 0;
570
571
my $loff = 0;
572
573
my $type = '';
574
my $level = 0;
575
my @stack = ();
576
my $p;
577
my $c;
578
my $len = 0;
579
580
my $remainder;
581
while (1) {
582
@stack = (['', 0]) if ($#stack == -1);
583
584
#warn "CSB: blk<$blk> remain<$remain>\n";
585
# If we are about to drop off the end, pull in more
586
# context.
587
if ($off >= $len) {
588
for (; $remain > 0; $line++) {
589
last if (!defined $lines[$line]);
590
next if ($lines[$line] =~ /^-/);
591
$remain--;
592
$loff = $len;
593
$blk .= $lines[$line] . "\n";
594
$len = length($blk);
595
$line++;
596
last;
597
}
598
# Bail if there is no further context.
599
#warn "CSB: blk<$blk> off<$off> len<$len>\n";
600
if ($off >= $len) {
601
last;
602
}
603
}
604
$p = $c;
605
$c = substr($blk, $off, 1);
606
$remainder = substr($blk, $off);
607
608
#warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
609
610
# Handle nested #if/#else.
611
if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
612
push(@stack, [ $type, $level ]);
613
} elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
614
($type, $level) = @{$stack[$#stack - 1]};
615
} elsif ($remainder =~ /^#\s*endif\b/) {
616
($type, $level) = @{pop(@stack)};
617
}
618
619
# Statement ends at the ';' or a close '}' at the
620
# outermost level.
621
if ($level == 0 && $c eq ';') {
622
last;
623
}
624
625
# An else is really a conditional as long as its not else if
626
if ($level == 0 && $coff_set == 0 &&
627
(!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
628
$remainder =~ /^(else)(?:\s|{)/ &&
629
$remainder !~ /^else\s+if\b/) {
630
$coff = $off + length($1) - 1;
631
$coff_set = 1;
632
#warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
633
#warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
634
}
635
636
if (($type eq '' || $type eq '(') && $c eq '(') {
637
$level++;
638
$type = '(';
639
}
640
if ($type eq '(' && $c eq ')') {
641
$level--;
642
$type = ($level != 0)? '(' : '';
643
644
if ($level == 0 && $coff < $soff) {
645
$coff = $off;
646
$coff_set = 1;
647
#warn "CSB: mark coff<$coff>\n";
648
}
649
}
650
if (($type eq '' || $type eq '{') && $c eq '{') {
651
$level++;
652
$type = '{';
653
}
654
if ($type eq '{' && $c eq '}') {
655
$level--;
656
$type = ($level != 0)? '{' : '';
657
658
if ($level == 0) {
659
if (substr($blk, $off + 1, 1) eq ';') {
660
$off++;
661
}
662
last;
663
}
664
}
665
$off++;
666
}
667
# We are truly at the end, so shuffle to the next line.
668
if ($off == $len) {
669
$loff = $len + 1;
670
$line++;
671
$remain--;
672
}
673
674
my $statement = substr($blk, $soff, $off - $soff + 1);
675
my $condition = substr($blk, $soff, $coff - $soff + 1);
676
677
#warn "STATEMENT<$statement>\n";
678
#warn "CONDITION<$condition>\n";
679
680
#print "coff<$coff> soff<$off> loff<$loff>\n";
681
682
return ($statement, $condition,
683
$line, $remain + 1, $off - $loff + 1, $level);
684
}
685
686
sub statement_lines {
687
my ($stmt) = @_;
688
689
# Strip the diff line prefixes and rip blank lines at start and end.
690
$stmt =~ s/(^|\n)./$1/g;
691
$stmt =~ s/^\s*//;
692
$stmt =~ s/\s*$//;
693
694
my @stmt_lines = ($stmt =~ /\n/g);
695
696
return $#stmt_lines + 2;
697
}
698
699
sub statement_rawlines {
700
my ($stmt) = @_;
701
702
my @stmt_lines = ($stmt =~ /\n/g);
703
704
return $#stmt_lines + 2;
705
}
706
707
sub statement_block_size {
708
my ($stmt) = @_;
709
710
$stmt =~ s/(^|\n)./$1/g;
711
$stmt =~ s/^\s*\{//;
712
$stmt =~ s/}\s*$//;
713
$stmt =~ s/^\s*//;
714
$stmt =~ s/\s*$//;
715
716
my @stmt_lines = ($stmt =~ /\n/g);
717
my @stmt_statements = ($stmt =~ /;/g);
718
719
my $stmt_lines = $#stmt_lines + 2;
720
my $stmt_statements = $#stmt_statements + 1;
721
722
if ($stmt_lines > $stmt_statements) {
723
return $stmt_lines;
724
} else {
725
return $stmt_statements;
726
}
727
}
728
729
sub ctx_statement_full {
730
my ($linenr, $remain, $off) = @_;
731
my ($statement, $condition, $level);
732
733
my (@chunks);
734
735
# Grab the first conditional/block pair.
736
($statement, $condition, $linenr, $remain, $off, $level) =
737
ctx_statement_block($linenr, $remain, $off);
738
#print "F: c<$condition> s<$statement> remain<$remain>\n";
739
push(@chunks, [ $condition, $statement ]);
740
if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
741
return ($level, $linenr, @chunks);
742
}
743
744
# Pull in the following conditional/block pairs and see if they
745
# could continue the statement.
746
for (;;) {
747
($statement, $condition, $linenr, $remain, $off, $level) =
748
ctx_statement_block($linenr, $remain, $off);
749
#print "C: c<$condition> s<$statement> remain<$remain>\n";
750
last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
751
#print "C: push\n";
752
push(@chunks, [ $condition, $statement ]);
753
}
754
755
return ($level, $linenr, @chunks);
756
}
757
758
sub ctx_block_get {
759
my ($linenr, $remain, $outer, $open, $close, $off) = @_;
760
my $line;
761
my $start = $linenr - 1;
762
my $blk = '';
763
my @o;
764
my @c;
765
my @res = ();
766
767
my $level = 0;
768
my @stack = ($level);
769
for ($line = $start; $remain > 0; $line++) {
770
next if ($rawlines[$line] =~ /^-/);
771
$remain--;
772
773
$blk .= $rawlines[$line];
774
775
# Handle nested #if/#else.
776
if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
777
push(@stack, $level);
778
} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
779
$level = $stack[$#stack - 1];
780
} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
781
$level = pop(@stack);
782
}
783
784
foreach my $c (split(//, $lines[$line])) {
785
##print "C<$c>L<$level><$open$close>O<$off>\n";
786
if ($off > 0) {
787
$off--;
788
next;
789
}
790
791
if ($c eq $close && $level > 0) {
792
$level--;
793
last if ($level == 0);
794
} elsif ($c eq $open) {
795
$level++;
796
}
797
}
798
799
if (!$outer || $level <= 1) {
800
push(@res, $rawlines[$line]);
801
}
802
803
last if ($level == 0);
804
}
805
806
return ($level, @res);
807
}
808
sub ctx_block_outer {
809
my ($linenr, $remain) = @_;
810
811
my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
812
return @r;
813
}
814
sub ctx_block {
815
my ($linenr, $remain) = @_;
816
817
my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
818
return @r;
819
}
820
sub ctx_statement {
821
my ($linenr, $remain, $off) = @_;
822
823
my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
824
return @r;
825
}
826
sub ctx_block_level {
827
my ($linenr, $remain) = @_;
828
829
return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
830
}
831
sub ctx_statement_level {
832
my ($linenr, $remain, $off) = @_;
833
834
return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
835
}
836
837
sub ctx_locate_comment {
838
my ($first_line, $end_line) = @_;
839
840
# Catch a comment on the end of the line itself.
841
my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
842
return $current_comment if (defined $current_comment);
843
844
# Look through the context and try and figure out if there is a
845
# comment.
846
my $in_comment = 0;
847
$current_comment = '';
848
for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
849
my $line = $rawlines[$linenr - 1];
850
#warn " $line\n";
851
if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
852
$in_comment = 1;
853
}
854
if ($line =~ m@/\*@) {
855
$in_comment = 1;
856
}
857
if (!$in_comment && $current_comment ne '') {
858
$current_comment = '';
859
}
860
$current_comment .= $line . "\n" if ($in_comment);
861
if ($line =~ m@\*/@) {
862
$in_comment = 0;
863
}
864
}
865
866
chomp($current_comment);
867
return($current_comment);
868
}
869
sub ctx_has_comment {
870
my ($first_line, $end_line) = @_;
871
my $cmt = ctx_locate_comment($first_line, $end_line);
872
873
##print "LINE: $rawlines[$end_line - 1 ]\n";
874
##print "CMMT: $cmt\n";
875
876
return ($cmt ne '');
877
}
878
879
sub raw_line {
880
my ($linenr, $cnt) = @_;
881
882
my $offset = $linenr - 1;
883
$cnt++;
884
885
my $line;
886
while ($cnt) {
887
$line = $rawlines[$offset++];
888
next if (defined($line) && $line =~ /^-/);
889
$cnt--;
890
}
891
892
return $line;
893
}
894
895
sub cat_vet {
896
my ($vet) = @_;
897
my ($res, $coded);
898
899
$res = '';
900
while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
901
$res .= $1;
902
if ($2 ne '') {
903
$coded = sprintf("^%c", unpack('C', $2) + 64);
904
$res .= $coded;
905
}
906
}
907
$res =~ s/$/\$/;
908
909
return $res;
910
}
911
912
my $av_preprocessor = 0;
913
my $av_pending;
914
my @av_paren_type;
915
my $av_pend_colon;
916
917
sub annotate_reset {
918
$av_preprocessor = 0;
919
$av_pending = '_';
920
@av_paren_type = ('E');
921
$av_pend_colon = 'O';
922
}
923
924
sub annotate_values {
925
my ($stream, $type) = @_;
926
927
my $res;
928
my $var = '_' x length($stream);
929
my $cur = $stream;
930
931
print "$stream\n" if ($dbg_values > 1);
932
933
while (length($cur)) {
934
@av_paren_type = ('E') if ($#av_paren_type < 0);
935
print " <" . join('', @av_paren_type) .
936
"> <$type> <$av_pending>" if ($dbg_values > 1);
937
if ($cur =~ /^(\s+)/o) {
938
print "WS($1)\n" if ($dbg_values > 1);
939
if ($1 =~ /\n/ && $av_preprocessor) {
940
$type = pop(@av_paren_type);
941
$av_preprocessor = 0;
942
}
943
944
} elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
945
print "CAST($1)\n" if ($dbg_values > 1);
946
push(@av_paren_type, $type);
947
$type = 'C';
948
949
} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
950
print "DECLARE($1)\n" if ($dbg_values > 1);
951
$type = 'T';
952
953
} elsif ($cur =~ /^($Modifier)\s*/) {
954
print "MODIFIER($1)\n" if ($dbg_values > 1);
955
$type = 'T';
956
957
} elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
958
print "DEFINE($1,$2)\n" if ($dbg_values > 1);
959
$av_preprocessor = 1;
960
push(@av_paren_type, $type);
961
if ($2 ne '') {
962
$av_pending = 'N';
963
}
964
$type = 'E';
965
966
} elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
967
print "UNDEF($1)\n" if ($dbg_values > 1);
968
$av_preprocessor = 1;
969
push(@av_paren_type, $type);
970
971
} elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
972
print "PRE_START($1)\n" if ($dbg_values > 1);
973
$av_preprocessor = 1;
974
975
push(@av_paren_type, $type);
976
push(@av_paren_type, $type);
977
$type = 'E';
978
979
} elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
980
print "PRE_RESTART($1)\n" if ($dbg_values > 1);
981
$av_preprocessor = 1;
982
983
push(@av_paren_type, $av_paren_type[$#av_paren_type]);
984
985
$type = 'E';
986
987
} elsif ($cur =~ /^(\#\s*(?:endif))/o) {
988
print "PRE_END($1)\n" if ($dbg_values > 1);
989
990
$av_preprocessor = 1;
991
992
# Assume all arms of the conditional end as this
993
# one does, and continue as if the #endif was not here.
994
pop(@av_paren_type);
995
push(@av_paren_type, $type);
996
$type = 'E';
997
998
} elsif ($cur =~ /^(\\\n)/o) {
999
print "PRECONT($1)\n" if ($dbg_values > 1);
1000
1001
} elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
1002
print "ATTR($1)\n" if ($dbg_values > 1);
1003
$av_pending = $type;
1004
$type = 'N';
1005
1006
} elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
1007
print "SIZEOF($1)\n" if ($dbg_values > 1);
1008
if (defined $2) {
1009
$av_pending = 'V';
1010
}
1011
$type = 'N';
1012
1013
} elsif ($cur =~ /^(if|while|for)\b/o) {
1014
print "COND($1)\n" if ($dbg_values > 1);
1015
$av_pending = 'E';
1016
$type = 'N';
1017
1018
} elsif ($cur =~/^(case)/o) {
1019
print "CASE($1)\n" if ($dbg_values > 1);
1020
$av_pend_colon = 'C';
1021
$type = 'N';
1022
1023
} elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
1024
print "KEYWORD($1)\n" if ($dbg_values > 1);
1025
$type = 'N';
1026
1027
} elsif ($cur =~ /^(\()/o) {
1028
print "PAREN('$1')\n" if ($dbg_values > 1);
1029
push(@av_paren_type, $av_pending);
1030
$av_pending = '_';
1031
$type = 'N';
1032
1033
} elsif ($cur =~ /^(\))/o) {
1034
my $new_type = pop(@av_paren_type);
1035
if ($new_type ne '_') {
1036
$type = $new_type;
1037
print "PAREN('$1') -> $type\n"
1038
if ($dbg_values > 1);
1039
} else {
1040
print "PAREN('$1')\n" if ($dbg_values > 1);
1041
}
1042
1043
} elsif ($cur =~ /^($Ident)\s*\(/o) {
1044
print "FUNC($1)\n" if ($dbg_values > 1);
1045
$type = 'V';
1046
$av_pending = 'V';
1047
1048
} elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
1049
if (defined $2 && $type eq 'C' || $type eq 'T') {
1050
$av_pend_colon = 'B';
1051
} elsif ($type eq 'E') {
1052
$av_pend_colon = 'L';
1053
}
1054
print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
1055
$type = 'V';
1056
1057
} elsif ($cur =~ /^($Ident|$Constant)/o) {
1058
print "IDENT($1)\n" if ($dbg_values > 1);
1059
$type = 'V';
1060
1061
} elsif ($cur =~ /^($Assignment)/o) {
1062
print "ASSIGN($1)\n" if ($dbg_values > 1);
1063
$type = 'N';
1064
1065
} elsif ($cur =~/^(;|{|})/) {
1066
print "END($1)\n" if ($dbg_values > 1);
1067
$type = 'E';
1068
$av_pend_colon = 'O';
1069
1070
} elsif ($cur =~/^(,)/) {
1071
print "COMMA($1)\n" if ($dbg_values > 1);
1072
$type = 'C';
1073
1074
} elsif ($cur =~ /^(\?)/o) {
1075
print "QUESTION($1)\n" if ($dbg_values > 1);
1076
$type = 'N';
1077
1078
} elsif ($cur =~ /^(:)/o) {
1079
print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
1080
1081
substr($var, length($res), 1, $av_pend_colon);
1082
if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
1083
$type = 'E';
1084
} else {
1085
$type = 'N';
1086
}
1087
$av_pend_colon = 'O';
1088
1089
} elsif ($cur =~ /^(\[)/o) {
1090
print "CLOSE($1)\n" if ($dbg_values > 1);
1091
$type = 'N';
1092
1093
} elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
1094
my $variant;
1095
1096
print "OPV($1)\n" if ($dbg_values > 1);
1097
if ($type eq 'V') {
1098
$variant = 'B';
1099
} else {
1100
$variant = 'U';
1101
}
1102
1103
substr($var, length($res), 1, $variant);
1104
$type = 'N';
1105
1106
} elsif ($cur =~ /^($Operators)/o) {
1107
print "OP($1)\n" if ($dbg_values > 1);
1108
if ($1 ne '++' && $1 ne '--') {
1109
$type = 'N';
1110
}
1111
1112
} elsif ($cur =~ /(^.)/o) {
1113
print "C($1)\n" if ($dbg_values > 1);
1114
}
1115
if (defined $1) {
1116
$cur = substr($cur, length($1));
1117
$res .= $type x length($1);
1118
}
1119
}
1120
1121
return ($res, $var);
1122
}
1123
1124
sub possible {
1125
my ($possible, $line) = @_;
1126
my $notPermitted = qr{(?:
1127
^(?:
1128
$Modifier|
1129
$Storage|
1130
$Type|
1131
DEFINE_\S+
1132
)$|
1133
^(?:
1134
goto|
1135
return|
1136
case|
1137
else|
1138
asm|__asm__|
1139
do
1140
)(?:\s|$)|
1141
^(?:typedef|struct|enum)\b|
1142
^\#
1143
)}x;
1144
warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
1145
if ($possible !~ $notPermitted) {
1146
# Check for modifiers.
1147
$possible =~ s/\s*$Storage\s*//g;
1148
$possible =~ s/\s*$Sparse\s*//g;
1149
if ($possible =~ /^\s*$/) {
1150
1151
} elsif ($possible =~ /\s/) {
1152
$possible =~ s/\s*(?:$Type|\#\#)\s*//g;
1153
for my $modifier (split(' ', $possible)) {
1154
if ($modifier !~ $notPermitted) {
1155
warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
1156
push(@modifierList, $modifier);
1157
}
1158
}
1159
1160
} else {
1161
warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
1162
push(@typeList, $possible);
1163
}
1164
build_types();
1165
} else {
1166
warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
1167
}
1168
}
1169
1170
my $prefix = '';
1171
1172
sub report {
1173
my ($level, $msg) = @_;
1174
if (defined $tst_only && $msg !~ /\Q$tst_only\E/) {
1175
return 0;
1176
}
1177
1178
my $output = '';
1179
my $do_color = $color && !$github;
1180
$output .= BOLD if $do_color;
1181
$output .= "::error " if $github && $level eq 'ERROR';
1182
$output .= "::warning " if $github && $level eq 'WARNING';
1183
$output .= $prefix;
1184
$output .= RED if $do_color && $level eq 'ERROR';
1185
$output .= MAGENTA if $do_color && $level eq 'WARNING';
1186
$output .= $level . ':' if !$github;
1187
$output .= RESET if $do_color;
1188
$output .= ' ' if (!$github);
1189
$output .= $msg . "\n";
1190
1191
$output = (split('\n', $output))[0] . "\n" if ($terse);
1192
1193
push(our @report, $output);
1194
1195
return 1;
1196
}
1197
sub report_dump {
1198
our @report;
1199
}
1200
sub ERROR {
1201
if (report("ERROR", $_[0])) {
1202
our $clean = 0;
1203
our $cnt_error++;
1204
}
1205
}
1206
sub WARN {
1207
if (report("WARNING", $_[0])) {
1208
our $clean = 0;
1209
our $cnt_warn++;
1210
}
1211
}
1212
1213
# According to tests/qtest/bios-tables-test.c: do not
1214
# change expected file in the same commit with adding test
1215
sub checkfilename {
1216
my ($name, $acpi_testexpected, $acpi_nontestexpected) = @_;
1217
1218
# Note: shell script that rebuilds the expected files is in the same
1219
# directory as files themselves.
1220
# Note: allowed diff list can be changed both when changing expected
1221
# files and when changing tests.
1222
if ($name =~ m#^tests/data/acpi/# and not $name =~ m#^\.sh$#) {
1223
$$acpi_testexpected = $name;
1224
} elsif ($name !~ m#^tests/qtest/bios-tables-test-allowed-diff.h$#) {
1225
$$acpi_nontestexpected = $name;
1226
}
1227
if (defined $$acpi_testexpected and defined $$acpi_nontestexpected) {
1228
ERROR("Do not add expected files together with tests, " .
1229
"follow instructions in " .
1230
"tests/qtest/bios-tables-test.c: both " .
1231
$$acpi_testexpected . " and " .
1232
$$acpi_nontestexpected . " found\n");
1233
}
1234
}
1235
1236
sub process {
1237
my $filename = shift;
1238
1239
my $linenr=0;
1240
my $prevline="";
1241
my $prevrawline="";
1242
my $stashline="";
1243
my $stashrawline="";
1244
1245
my $length;
1246
my $indent;
1247
my $previndent=0;
1248
my $stashindent=0;
1249
1250
our $clean = 1;
1251
my $signoff = 0;
1252
my $is_patch = 0;
1253
1254
my $in_header_lines = $file ? 0 : 1;
1255
my $in_commit_log = 0; #Scanning lines before patch
1256
my $non_utf8_charset = 0;
1257
1258
our @report = ();
1259
our $cnt_lines = 0;
1260
our $cnt_error = 0;
1261
our $cnt_warn = 0;
1262
our $cnt_chk = 0;
1263
1264
# Trace the real file/line as we go.
1265
my $realfile = '';
1266
my $realline = 0;
1267
my $realcnt = 0;
1268
my $here = '';
1269
my $in_comment = 0;
1270
my $comment_edge = 0;
1271
my $first_line = 0;
1272
my $p1_prefix = '';
1273
1274
my $prev_values = 'E';
1275
1276
# suppression flags
1277
my %suppress_ifbraces;
1278
my %suppress_whiletrailers;
1279
my %suppress_export;
1280
1281
my $acpi_testexpected;
1282
my $acpi_nontestexpected;
1283
1284
# Pre-scan the patch sanitizing the lines.
1285
1286
sanitise_line_reset();
1287
my $line;
1288
foreach my $rawline (@rawlines) {
1289
$linenr++;
1290
$line = $rawline;
1291
1292
if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
1293
$realline=$1-1;
1294
if (defined $2) {
1295
$realcnt=$3+1;
1296
} else {
1297
$realcnt=1+1;
1298
}
1299
$in_comment = 0;
1300
1301
# Guestimate if this is a continuing comment. Run
1302
# the context looking for a comment "edge". If this
1303
# edge is a close comment then we must be in a comment
1304
# at context start.
1305
my $edge;
1306
my $cnt = $realcnt;
1307
for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
1308
next if (defined $rawlines[$ln - 1] &&
1309
$rawlines[$ln - 1] =~ /^-/);
1310
$cnt--;
1311
#print "RAW<$rawlines[$ln - 1]>\n";
1312
last if (!defined $rawlines[$ln - 1]);
1313
if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
1314
$rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
1315
($edge) = $1;
1316
last;
1317
}
1318
}
1319
if (defined $edge && $edge eq '*/') {
1320
$in_comment = 1;
1321
}
1322
1323
# Guestimate if this is a continuing comment. If this
1324
# is the start of a diff block and this line starts
1325
# ' *' then it is very likely a comment.
1326
if (!defined $edge &&
1327
$rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
1328
{
1329
$in_comment = 1;
1330
}
1331
1332
##print "COMMENT:$in_comment edge<$edge> $rawline\n";
1333
sanitise_line_reset($in_comment);
1334
1335
} elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
1336
# Standardise the strings and chars within the input to
1337
# simplify matching -- only bother with positive lines.
1338
$line = sanitise_line($rawline);
1339
}
1340
push(@lines, $line);
1341
1342
if ($realcnt > 1) {
1343
$realcnt-- if ($line =~ /^(?:\+| |$)/);
1344
} else {
1345
$realcnt = 0;
1346
}
1347
1348
#print "==>$rawline\n";
1349
#print "-->$line\n";
1350
}
1351
1352
$prefix = '';
1353
1354
$realcnt = 0;
1355
$linenr = 0;
1356
foreach my $line (@lines) {
1357
$linenr++;
1358
1359
my $rawline = $rawlines[$linenr - 1];
1360
1361
#extract the line range in the file after the patch is applied
1362
if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
1363
$is_patch = 1;
1364
$first_line = $linenr + 1;
1365
$realline=$1-1;
1366
if (defined $2) {
1367
$realcnt=$3+1;
1368
} else {
1369
$realcnt=1+1;
1370
}
1371
annotate_reset();
1372
$prev_values = 'E';
1373
1374
%suppress_ifbraces = ();
1375
%suppress_whiletrailers = ();
1376
%suppress_export = ();
1377
next;
1378
1379
# track the line number as we move through the hunk, note that
1380
# new versions of GNU diff omit the leading space on completely
1381
# blank context lines so we need to count that too.
1382
} elsif ($line =~ /^( |\+|$)/) {
1383
$realline++;
1384
$realcnt-- if ($realcnt != 0);
1385
1386
# Measure the line length and indent.
1387
($length, $indent) = line_stats($rawline);
1388
1389
# Track the previous line.
1390
($prevline, $stashline) = ($stashline, $line);
1391
($previndent, $stashindent) = ($stashindent, $indent);
1392
($prevrawline, $stashrawline) = ($stashrawline, $rawline);
1393
1394
#warn "line<$line>\n";
1395
1396
} elsif ($realcnt == 1) {
1397
$realcnt--;
1398
}
1399
1400
my $hunk_line = ($realcnt != 0);
1401
1402
#make up the handle for any error we report on this line
1403
$prefix = "$filename:$realline: " if ($emacs && $file);
1404
$prefix = "$filename:$linenr: " if ($emacs && !$file);
1405
$prefix = "file=$filename,line=$realline:\:" if ($github && $file);
1406
$prefix = "file=$realfile,line=$realline:\:" if ($github && !$file);
1407
1408
$here = "#$linenr: " if (!$file);
1409
$here = "#$realline: " if ($file);
1410
1411
# extract the filename as it passes
1412
if ($line =~ /^diff --git.*?(\S+)$/) {
1413
$realfile = $1;
1414
$realfile =~ s@^([^/]*)/@@ if (!$file);
1415
checkfilename($realfile, \$acpi_testexpected, \$acpi_nontestexpected);
1416
} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
1417
$realfile = $1;
1418
$realfile =~ s@^([^/]*)/@@ if (!$file);
1419
checkfilename($realfile, \$acpi_testexpected, \$acpi_nontestexpected);
1420
1421
$p1_prefix = $1;
1422
if (!$file && $tree && $p1_prefix ne '' && defined $root &&
1423
-e "$root/$p1_prefix") {
1424
WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
1425
}
1426
1427
next;
1428
}
1429
1430
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
1431
1432
my $hereline = "$here\n$rawline\n";
1433
my $herecurr = "$here\n$rawline\n";
1434
my $hereprev = "$here\n$prevrawline\n$rawline\n";
1435
1436
$cnt_lines++ if ($realcnt != 0);
1437
1438
# Check for incorrect file permissions
1439
if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
1440
my $permhere = $here . "FILE: $realfile\n";
1441
if ($realfile =~ /(\bMakefile(?:\.objs)?|\.c|\.cc|\.cpp|\.h|\.hpp|\.mak|\.[sS])$/) {
1442
ERROR("do not set execute permissions for source files\n" . $permhere);
1443
}
1444
}
1445
1446
# Accept git diff extended headers as valid patches
1447
if ($line =~ /^(?:rename|copy) (?:from|to) [\w\/\.\-]+\s*$/) {
1448
$is_patch = 1;
1449
}
1450
1451
# Check for wrappage within a valid hunk of the file
1452
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
1453
ERROR("patch seems to be corrupt (line wrapped?)\n" .
1454
$herecurr) if (!$emitted_corrupt++);
1455
}
1456
1457
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
1458
if (($realfile =~ /^$/ || $line =~ /^\+/) &&
1459
$rawline !~ m/^$UTF8*$/) {
1460
my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
1461
1462
my $blank = copy_spacing($rawline);
1463
my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
1464
my $hereptr = "$hereline$ptr\n";
1465
1466
ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
1467
}
1468
1469
if ($rawline =~ m/$UTF8_MOJIBAKE/) {
1470
ERROR("Doubly-encoded UTF-8\n" . $herecurr);
1471
}
1472
# Check if it's the start of a commit log
1473
# (not a header line and we haven't seen the patch filename)
1474
if ($in_header_lines && $realfile =~ /^$/ &&
1475
!($rawline =~ /^\s+\S/ ||
1476
$rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
1477
$in_header_lines = 0;
1478
$in_commit_log = 1;
1479
}
1480
1481
# Check if there is UTF-8 in a commit log when a mail header has explicitly
1482
# declined it, i.e defined some charset where it is missing.
1483
if ($in_header_lines &&
1484
$rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
1485
$1 !~ /utf-8/i) {
1486
$non_utf8_charset = 1;
1487
}
1488
1489
if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
1490
$rawline =~ /$NON_ASCII_UTF8/) {
1491
WARN("8-bit UTF-8 used in possible commit log\n" . $herecurr);
1492
}
1493
1494
# ignore non-hunk lines and lines being removed
1495
next if (!$hunk_line || $line =~ /^-/);
1496
1497
#trailing whitespace
1498
if ($line =~ /^\+.*\015/) {
1499
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1500
ERROR("DOS line endings\n" . $herevet);
1501
1502
} elsif ($realfile =~ /^docs\/.+\.txt/ ||
1503
$realfile =~ /^docs\/.+\.md/) {
1504
if ($rawline =~ /^\+\s+$/ && $rawline !~ /^\+ {4}$/) {
1505
# TODO: properly check we're in a code block
1506
# (surrounding text is 4-column aligned)
1507
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1508
ERROR("code blocks in documentation should have " .
1509
"empty lines with exactly 4 columns of " .
1510
"whitespace\n" . $herevet);
1511
}
1512
} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
1513
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1514
ERROR("trailing whitespace\n" . $herevet);
1515
$rpt_cleaners = 1;
1516
}
1517
1518
# check we are in a valid source file if not then ignore this hunk
1519
next if ($realfile !~ /$SrcFile/);
1520
1521
#120 column limit; exempt URLs, if no other words on line
1522
if ($line =~ /^\+/ &&
1523
!($line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
1524
!($rawline =~ /^[^[:alnum:]]*https?:\S*$/) &&
1525
$length > 80 &&
1526
$realfile !~ /\/tests\//)
1527
{
1528
if ($length > 120) {
1529
ERROR("line over 120 characters\n" . $herecurr);
1530
} else {
1531
WARN("line over 80 characters\n" . $herecurr);
1532
}
1533
}
1534
1535
# check for spaces before a quoted newline
1536
if ($rawline =~ /^.*\".*\s\\n/) {
1537
ERROR("unnecessary whitespace before a quoted newline\n" . $herecurr);
1538
}
1539
1540
# check for adding lines without a newline.
1541
if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
1542
ERROR("adding a line without newline at end of file\n" . $herecurr);
1543
}
1544
1545
# check for RCS/CVS revision markers
1546
if ($rawline =~ /^\+.*\$(FreeBSD|Revision|Log|Id)(?:\$|\b)/) {
1547
ERROR("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
1548
}
1549
1550
# check we are in a valid C source file if not then ignore this hunk
1551
next if ($realfile !~ /\.(h|hpp|c|cpp|cc|hh)$/);
1552
1553
# Block comment styles
1554
1555
# Block comments use /* on a line of its own
1556
if ($rawline !~ m@^\+.*/\*.*\*/[ \t)}]*$@ && #inline /*...*/
1557
$rawline =~ m@^\+.*/\*[*-]?+[ \t]*[^ \t]@) { # /* or /** or /*- non-blank
1558
WARN("Block comments use a leading /* on a separate line\n" . $herecurr);
1559
}
1560
1561
# Block comments use * on subsequent lines
1562
if ($prevline =~ /$;[ \t]*$/ && #ends in comment
1563
$prevrawline =~ /^\+.*?\/\*/ && #starting /*
1564
$prevrawline !~ /\*\/[ \t]*$/ && #no trailing */
1565
$rawline =~ /^\+/ && #line is new
1566
$rawline !~ /^\+[ \t]*\*/) { #no leading *
1567
WARN("Block comments use * on subsequent lines\n" . $hereprev);
1568
}
1569
1570
# Block comments use */ on trailing lines
1571
if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */
1572
$rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/
1573
$rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/
1574
$rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */
1575
WARN("Block comments use a trailing */ on a separate line\n" . $herecurr);
1576
}
1577
1578
# Block comment * alignment
1579
if ($prevline =~ /$;[ \t]*$/ && #ends in comment
1580
$line =~ /^\+[ \t]*$;/ && #leading comment
1581
$rawline =~ /^\+[ \t]*\*/ && #leading *
1582
(($prevrawline =~ /^\+.*?\/\*/ && #leading /*
1583
$prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
1584
$prevrawline =~ /^\+[ \t]*\*/)) { #leading *
1585
my $oldindent;
1586
$prevrawline =~ m@^\+([ \t]*/?)\*@;
1587
if (defined($1)) {
1588
$oldindent = expand_tabs($1);
1589
} else {
1590
$prevrawline =~ m@^\+(.*/?)\*@;
1591
$oldindent = expand_tabs($1);
1592
}
1593
$rawline =~ m@^\+([ \t]*)\*@;
1594
my $newindent = $1;
1595
$newindent = expand_tabs($newindent);
1596
if (length($oldindent) ne length($newindent)) {
1597
WARN("Block comments should align the * on each line\n" . $hereprev);
1598
}
1599
}
1600
1601
# Check for potential 'bare' types
1602
my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
1603
$realline_next);
1604
if ($realcnt && $line =~ /.\s*\S/) {
1605
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
1606
ctx_statement_block($linenr, $realcnt, 0);
1607
$stat =~ s/\n./\n /g;
1608
$cond =~ s/\n./\n /g;
1609
1610
# Find the real next line.
1611
$realline_next = $line_nr_next;
1612
if (defined $realline_next &&
1613
(!defined $lines[$realline_next - 1] ||
1614
substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
1615
$realline_next++;
1616
}
1617
1618
my $s = $stat;
1619
$s =~ s/{.*$//s;
1620
1621
# Ignore goto labels.
1622
if ($s =~ /$Ident:\*$/s) {
1623
1624
# Ignore functions being called
1625
} elsif ($s =~ /^.\s*$Ident\s*\(/s) {
1626
1627
} elsif ($s =~ /^.\s*else\b/s) {
1628
1629
# declarations always start with types
1630
} elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
1631
my $type = $1;
1632
$type =~ s/\s+/ /g;
1633
possible($type, "A:" . $s);
1634
1635
# definitions in global scope can only start with types
1636
} elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
1637
possible($1, "B:" . $s);
1638
}
1639
1640
# any (foo ... *) is a pointer cast, and foo is a type
1641
while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
1642
possible($1, "C:" . $s);
1643
}
1644
1645
# Check for any sort of function declaration.
1646
# int foo(something bar, other baz);
1647
# void (*store_gdt)(x86_descr_ptr *);
1648
if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
1649
my ($name_len) = length($1);
1650
1651
my $ctx = $s;
1652
substr($ctx, 0, $name_len + 1, '');
1653
$ctx =~ s/\)[^\)]*$//;
1654
1655
for my $arg (split(/\s*,\s*/, $ctx)) {
1656
if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
1657
1658
possible($1, "D:" . $s);
1659
}
1660
}
1661
}
1662
1663
}
1664
1665
#
1666
# Checks which may be anchored in the context.
1667
#
1668
1669
# Check for switch () and associated case and default
1670
# statements should be at the same indent.
1671
if ($line=~/\bswitch\s*\(.*\)/) {
1672
my $err = '';
1673
my $sep = '';
1674
my @ctx = ctx_block_outer($linenr, $realcnt);
1675
shift(@ctx);
1676
for my $ctx (@ctx) {
1677
my ($clen, $cindent) = line_stats($ctx);
1678
if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
1679
$indent != $cindent) {
1680
$err .= "$sep$ctx\n";
1681
$sep = '';
1682
} else {
1683
$sep = "[...]\n";
1684
}
1685
}
1686
if ($err ne '') {
1687
ERROR("switch and case should be at the same indent\n$hereline$err");
1688
}
1689
}
1690
1691
# if/while/etc brace do not go on next line, unless defining a do while loop,
1692
# or if that brace on the next line is for something else
1693
if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
1694
my $pre_ctx = "$1$2";
1695
1696
my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
1697
my $ctx_cnt = $realcnt - $#ctx - 1;
1698
my $ctx = join("\n", @ctx);
1699
1700
my $ctx_ln = $linenr;
1701
my $ctx_skip = $realcnt;
1702
1703
while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
1704
defined $lines[$ctx_ln - 1] &&
1705
$lines[$ctx_ln - 1] =~ /^-/)) {
1706
##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
1707
$ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
1708
$ctx_ln++;
1709
}
1710
1711
#print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
1712
#print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
1713
1714
# The length of the "previous line" is checked against 80 because it
1715
# includes the + at the beginning of the line (if the actual line has
1716
# 79 or 80 characters, it is no longer possible to add a space and an
1717
# opening brace there)
1718
if ($#ctx == 0 && $ctx !~ /{\s*/ &&
1719
defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*\{/ &&
1720
defined($lines[$ctx_ln - 2]) && length($lines[$ctx_ln - 2]) < 80) {
1721
ERROR("that open brace { should be on the previous line\n" .
1722
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
1723
}
1724
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
1725
$ctx =~ /\)\s*\;\s*$/ &&
1726
defined $lines[$ctx_ln - 1])
1727
{
1728
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
1729
if ($nindent > $indent) {
1730
ERROR("trailing semicolon indicates no statements, indent implies otherwise\n" .
1731
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
1732
}
1733
}
1734
}
1735
1736
# 'do ... while (0/false)' only makes sense in macros, without trailing ';'
1737
if ($line =~ /while\s*\((0|false)\);/) {
1738
ERROR("suspicious ; after while (0)\n" . $herecurr);
1739
}
1740
1741
# Check superfluous trailing ';'
1742
if ($line =~ /;;$/) {
1743
ERROR("superfluous trailing semicolon\n" . $herecurr);
1744
}
1745
1746
# Check relative indent for conditionals and blocks.
1747
if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
1748
my ($s, $c) = ($stat, $cond);
1749
1750
substr($s, 0, length($c), '');
1751
1752
# Make sure we remove the line prefixes as we have
1753
# none on the first line, and are going to re-add them
1754
# where necessary.
1755
$s =~ s/\n./\n/gs;
1756
1757
# Find out how long the conditional actually is.
1758
my @newlines = ($c =~ /\n/gs);
1759
my $cond_lines = 1 + $#newlines;
1760
1761
# We want to check the first line inside the block
1762
# starting at the end of the conditional, so remove:
1763
# 1) any blank line termination
1764
# 2) any opening brace { on end of the line
1765
# 3) any do (...) {
1766
my $continuation = 0;
1767
my $check = 0;
1768
$s =~ s/^.*\bdo\b//;
1769
$s =~ s/^\s*\{//;
1770
if ($s =~ s/^\s*\\//) {
1771
$continuation = 1;
1772
}
1773
if ($s =~ s/^\s*?\n//) {
1774
$check = 1;
1775
$cond_lines++;
1776
}
1777
1778
# Also ignore a loop construct at the end of a
1779
# preprocessor statement.
1780
if (($prevline =~ /^.\s*#\s*define\s/ ||
1781
$prevline =~ /\\\s*$/) && $continuation == 0) {
1782
$check = 0;
1783
}
1784
1785
my $cond_ptr = -1;
1786
$continuation = 0;
1787
while ($cond_ptr != $cond_lines) {
1788
$cond_ptr = $cond_lines;
1789
1790
# If we see an #else/#elif then the code
1791
# is not linear.
1792
if ($s =~ /^\s*\#\s*(?:else|elif)/) {
1793
$check = 0;
1794
}
1795
1796
# Ignore:
1797
# 1) blank lines, they should be at 0,
1798
# 2) preprocessor lines, and
1799
# 3) labels.
1800
if ($continuation ||
1801
$s =~ /^\s*?\n/ ||
1802
$s =~ /^\s*#\s*?/ ||
1803
$s =~ /^\s*$Ident\s*:/) {
1804
$continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
1805
if ($s =~ s/^.*?\n//) {
1806
$cond_lines++;
1807
}
1808
}
1809
}
1810
1811
my (undef, $sindent) = line_stats("+" . $s);
1812
my $stat_real = raw_line($linenr, $cond_lines);
1813
1814
# Check if either of these lines are modified, else
1815
# this is not this patch's fault.
1816
if (!defined($stat_real) ||
1817
$stat !~ /^\+/ && $stat_real !~ /^\+/) {
1818
$check = 0;
1819
}
1820
if (defined($stat_real) && $cond_lines > 1) {
1821
$stat_real = "[...]\n$stat_real";
1822
}
1823
1824
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
1825
1826
if ($check && (($sindent % 4) != 0 ||
1827
($sindent <= $indent && $s ne ''))) {
1828
ERROR("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
1829
}
1830
}
1831
1832
# Track the 'values' across context and added lines.
1833
my $opline = $line; $opline =~ s/^./ /;
1834
my ($curr_values, $curr_vars) =
1835
annotate_values($opline . "\n", $prev_values);
1836
$curr_values = $prev_values . $curr_values;
1837
if ($dbg_values) {
1838
my $outline = $opline; $outline =~ s/\t/ /g;
1839
print "$linenr > .$outline\n";
1840
print "$linenr > $curr_values\n";
1841
print "$linenr > $curr_vars\n";
1842
}
1843
$prev_values = substr($curr_values, -1);
1844
1845
#ignore lines not being added
1846
if ($line=~/^[^\+]/) {next;}
1847
1848
# check for initialisation to aggregates open brace on the next line
1849
if ($line =~ /^.\s*\{/ &&
1850
$prevline =~ /(?:^|[^=])=\s*$/) {
1851
ERROR("that open brace { should be on the previous line\n" . $hereprev);
1852
}
1853
1854
#
1855
# Checks which are anchored on the added line.
1856
#
1857
1858
# check for malformed paths in #include statements (uses RAW line)
1859
if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
1860
my $path = $1;
1861
if ($path =~ m{//}) {
1862
ERROR("malformed #include filename\n" .
1863
$herecurr);
1864
}
1865
}
1866
1867
# Remove C99 comments.
1868
$line =~ s@//.*@@;
1869
$opline =~ s@//.*@@;
1870
1871
# * goes on variable not on type
1872
# (char*[ const])
1873
if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
1874
my ($from, $to) = ($1, $1);
1875
1876
# Should start with a space.
1877
$to =~ s/^(\S)/ $1/;
1878
# Should not end with a space.
1879
$to =~ s/\s+$//;
1880
# '*'s should not have spaces between.
1881
while ($to =~ s/\*\s+\*/\*\*/) {
1882
}
1883
1884
#print "from<$from> to<$to>\n";
1885
if ($from ne $to) {
1886
ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr);
1887
}
1888
} elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
1889
my ($from, $to, $ident) = ($1, $1, $2);
1890
1891
# Should start with a space.
1892
$to =~ s/^(\S)/ $1/;
1893
# Should not end with a space.
1894
$to =~ s/\s+$//;
1895
# '*'s should not have spaces between.
1896
while ($to =~ s/\*\s+\*/\*\*/) {
1897
}
1898
# Modifiers should have spaces.
1899
$to =~ s/(\b$Modifier$)/$1 /;
1900
1901
#print "from<$from> to<$to> ident<$ident>\n";
1902
if ($from ne $to && $ident !~ /^$Modifier$/) {
1903
ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr);
1904
}
1905
}
1906
1907
# function brace can't be on same line, except for #defines of do while,
1908
# or if closed on same line
1909
if (($line=~/$Type\s*$Ident\(.*\).*\s\{/) and
1910
!($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) {
1911
ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
1912
}
1913
1914
# missing space after union, struct or enum definition
1915
if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
1916
ERROR("missing space after $1 definition\n" . $herecurr);
1917
}
1918
1919
# check for spacing round square brackets; allowed:
1920
# 1. with a type on the left -- int [] a;
1921
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
1922
# 3. inside a curly brace -- = { [0...10] = 5 }
1923
# 4. after a comma -- [1] = 5, [2] = 6
1924
# 5. in a macro definition -- #define abc(x) [x] = y
1925
while ($line =~ /(.*?\s)\[/g) {
1926
my ($where, $prefix) = ($-[1], $1);
1927
if ($prefix !~ /$Type\s+$/ &&
1928
($where != 0 || $prefix !~ /^.\s+$/) &&
1929
$prefix !~ /\#\s*define[^(]*\([^)]*\)\s+$/ &&
1930
$prefix !~ /[,{:]\s+$/) {
1931
ERROR("space prohibited before open square bracket '['\n" . $herecurr);
1932
}
1933
}
1934
1935
# check for spaces between functions and their parentheses.
1936
while ($line =~ /($Ident)\s+\(/g) {
1937
my $name = $1;
1938
my $ctx_before = substr($line, 0, $-[1]);
1939
my $ctx = "$ctx_before$name";
1940
1941
# Ignore those directives where spaces _are_ permitted.
1942
if ($name =~ /^(?:
1943
if|for|while|switch|return|case|
1944
volatile|__volatile__|coroutine_fn|
1945
__attribute__|format|__extension__|
1946
asm|__asm__)$/x)
1947
{
1948
1949
# Ignore 'catch (...)' in C++
1950
} elsif ($name =~ /^catch$/ && $realfile =~ /\.(cpp|h|hpp|hh|cc)$/) {
1951
1952
# cpp #define statements have non-optional spaces, ie
1953
# if there is a space between the name and the open
1954
# parenthesis it is simply not a parameter group.
1955
} elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
1956
1957
# cpp #elif statement condition may start with a (
1958
} elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
1959
1960
# If this whole things ends with a type its most
1961
# likely a typedef for a function.
1962
} elsif ($ctx =~ /$Type$/) {
1963
1964
} else {
1965
ERROR("space prohibited between function name and open parenthesis '('\n" . $herecurr);
1966
}
1967
}
1968
# Check operator spacing.
1969
if (!($line=~/\#\s*include/)) {
1970
my $ops = qr{
1971
<<=|>>=|<=|>=|==|!=|
1972
\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
1973
=>|->|<<|>>|<|>|=|!|~|
1974
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
1975
\?|::|:
1976
}x;
1977
my @elements = split(/($ops|;)/, $opline);
1978
my $off = 0;
1979
1980
my $blank = copy_spacing($opline);
1981
1982
for (my $n = 0; $n < $#elements; $n += 2) {
1983
$off += length($elements[$n]);
1984
1985
# Pick up the preceding and succeeding characters.
1986
my $ca = substr($opline, 0, $off);
1987
my $cc = '';
1988
if (length($opline) >= ($off + length($elements[$n + 1]))) {
1989
$cc = substr($opline, $off + length($elements[$n + 1]));
1990
}
1991
my $cb = "$ca$;$cc";
1992
1993
my $a = '';
1994
$a = 'V' if ($elements[$n] ne '');
1995
$a = 'W' if ($elements[$n] =~ /\s$/);
1996
$a = 'C' if ($elements[$n] =~ /$;$/);
1997
$a = 'B' if ($elements[$n] =~ /(\[|\()$/);
1998
$a = 'O' if ($elements[$n] eq '');
1999
$a = 'E' if ($ca =~ /^\s*$/);
2000
2001
my $op = $elements[$n + 1];
2002
2003
my $c = '';
2004
if (defined $elements[$n + 2]) {
2005
$c = 'V' if ($elements[$n + 2] ne '');
2006
$c = 'W' if ($elements[$n + 2] =~ /^\s/);
2007
$c = 'C' if ($elements[$n + 2] =~ /^$;/);
2008
$c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
2009
$c = 'O' if ($elements[$n + 2] eq '');
2010
$c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
2011
} else {
2012
$c = 'E';
2013
}
2014
2015
my $ctx = "${a}x${c}";
2016
2017
my $at = "(ctx:$ctx)";
2018
2019
my $ptr = substr($blank, 0, $off) . "^";
2020
my $hereptr = "$hereline$ptr\n";
2021
2022
# Pull out the value of this operator.
2023
my $op_type = substr($curr_values, $off + 1, 1);
2024
2025
# Get the full operator variant.
2026
my $opv = $op . substr($curr_vars, $off, 1);
2027
2028
# Ignore operators passed as parameters.
2029
if ($op_type ne 'V' &&
2030
$ca =~ /\s$/ && $cc =~ /^\s*,/) {
2031
2032
# # Ignore comments
2033
# } elsif ($op =~ /^$;+$/) {
2034
2035
# ; should have either the end of line or a space or \ after it
2036
} elsif ($op eq ';') {
2037
if ($ctx !~ /.x[WEBC]/ &&
2038
$cc !~ /^\\/ && $cc !~ /^;/) {
2039
ERROR("space required after that '$op' $at\n" . $hereptr);
2040
}
2041
2042
# // is a comment
2043
} elsif ($op eq '//') {
2044
2045
# Ignore : used in class declaration in C++
2046
} elsif ($opv eq ':B' && $ctx =~ /Wx[WE]/ &&
2047
$line =~ /class/ && $realfile =~ /\.(cpp|h|hpp|hh|cc)$/) {
2048
2049
# No spaces for:
2050
# ->
2051
# : when part of a bitfield
2052
} elsif ($op eq '->' || $opv eq ':B') {
2053
if ($ctx =~ /Wx.|.xW/) {
2054
ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
2055
}
2056
2057
# , must have a space on the right.
2058
# not required when having a single },{ on one line
2059
} elsif ($op eq ',') {
2060
if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/ &&
2061
($elements[$n] . $elements[$n + 2]) !~ " *}\\{") {
2062
ERROR("space required after that '$op' $at\n" . $hereptr);
2063
}
2064
2065
# '*' as part of a type definition -- reported already.
2066
} elsif ($opv eq '*_') {
2067
#warn "'*' is part of type\n";
2068
2069
# unary operators should have a space before and
2070
# none after. May be left adjacent to another
2071
# unary operator, or a cast
2072
} elsif ($op eq '!' || $op eq '~' ||
2073
$opv eq '*U' || $opv eq '-U' ||
2074
$opv eq '&U' || $opv eq '&&U') {
2075
if ($op eq '~' && $ca =~ /::$/ && $realfile =~ /\.(cpp|h|hpp|cc|hh)$/) {
2076
# '~' used as a name of Destructor
2077
2078
} elsif ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
2079
ERROR("space required before that '$op' $at\n" . $hereptr);
2080
}
2081
if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
2082
# A unary '*' may be const
2083
2084
} elsif ($ctx =~ /.xW/) {
2085
ERROR("space prohibited after that '$op' $at\n" . $hereptr);
2086
}
2087
2088
# unary ++ and unary -- are allowed no space on one side.
2089
} elsif ($op eq '++' or $op eq '--') {
2090
if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
2091
ERROR("space required one side of that '$op' $at\n" . $hereptr);
2092
}
2093
if ($ctx =~ /Wx[BE]/ ||
2094
($ctx =~ /Wx./ && $cc =~ /^;/)) {
2095
ERROR("space prohibited before that '$op' $at\n" . $hereptr);
2096
}
2097
if ($ctx =~ /ExW/) {
2098
ERROR("space prohibited after that '$op' $at\n" . $hereptr);
2099
}
2100
2101
# A colon needs no spaces before when it is
2102
# terminating a case value or a label.
2103
} elsif ($opv eq ':C' || $opv eq ':L') {
2104
if ($ctx =~ /Wx./) {
2105
ERROR("space prohibited before that '$op' $at\n" . $hereptr);
2106
}
2107
2108
# All the others need spaces both sides.
2109
} elsif ($ctx !~ /[EWC]x[CWE]/) {
2110
my $ok = 0;
2111
2112
if ($realfile =~ /\.(cpp|h|hpp|cc|hh)$/) {
2113
# Ignore template arguments <...> in C++
2114
if (($op eq '<' || $op eq '>') && $line =~ /<.*>/) {
2115
$ok = 1;
2116
}
2117
2118
# Ignore :: in C++
2119
if ($op eq '::') {
2120
$ok = 1;
2121
}
2122
}
2123
2124
# Ignore email addresses <foo@bar>
2125
if (($op eq '<' &&
2126
$cc =~ /^\S+\@\S+>/) ||
2127
($op eq '>' &&
2128
$ca =~ /<\S+\@\S+$/))
2129
{
2130
$ok = 1;
2131
}
2132
2133
# Ignore ?:
2134
if (($opv eq ':O' && $ca =~ /\?$/) ||
2135
($op eq '?' && $cc =~ /^:/)) {
2136
$ok = 1;
2137
}
2138
2139
if ($ok == 0) {
2140
ERROR("spaces required around that '$op' $at\n" . $hereptr);
2141
}
2142
}
2143
$off += length($elements[$n + 1]);
2144
}
2145
}
2146
2147
#need space before brace following if, while, etc
2148
if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
2149
$line =~ /do\{/) {
2150
ERROR("space required before the open brace '{'\n" . $herecurr);
2151
}
2152
2153
# closing brace should have a space following it when it has anything
2154
# on the line
2155
if ($line =~ /}(?!(?:,|;|\)))\S/) {
2156
ERROR("space required after that close brace '}'\n" . $herecurr);
2157
}
2158
2159
# check spacing on square brackets
2160
if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
2161
ERROR("space prohibited after that open square bracket '['\n" . $herecurr);
2162
}
2163
if ($line =~ /\s\]/) {
2164
ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
2165
}
2166
2167
# check spacing on parentheses
2168
if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
2169
$line !~ /for\s*\(\s+;/) {
2170
ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
2171
}
2172
if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
2173
$line !~ /for\s*\(.*;\s+\)/ &&
2174
$line !~ /:\s+\)/) {
2175
ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
2176
}
2177
2178
if ($line =~ /^.\s*(Q(?:S?LIST|SIMPLEQ|TAILQ)_HEAD)\s*\(\s*[^,]/ &&
2179
$line !~ /^.typedef/) {
2180
ERROR("named $1 should be typedefed separately\n" . $herecurr);
2181
}
2182
2183
# Return needs parens
2184
if ($line =~ /^.\s*return [^(]/) {
2185
ERROR("parentheses required on return\n" . $herecurr);
2186
}
2187
2188
# Need a space before open parenthesis after if, while etc
2189
if ($line=~/\b(if|while|for|switch|return)\(/) {
2190
ERROR("space required before the open parenthesis '('\n" . $herecurr);
2191
}
2192
2193
# Check for illegal assignment in if conditional -- and check for trailing
2194
# statements after the conditional.
2195
if ($line =~ /do\s*(?!{)/) {
2196
my ($stat_next) = ctx_statement_block($line_nr_next,
2197
$remain_next, $off_next);
2198
$stat_next =~ s/\n./\n /g;
2199
##print "stat<$stat> stat_next<$stat_next>\n";
2200
2201
if ($stat_next =~ /^\s*while\b/) {
2202
# If the statement carries leading newlines,
2203
# then count those as offsets.
2204
my ($whitespace) =
2205
($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
2206
my $offset =
2207
statement_rawlines($whitespace) - 1;
2208
2209
$suppress_whiletrailers{$line_nr_next +
2210
$offset} = 1;
2211
}
2212
}
2213
if (!defined $suppress_whiletrailers{$linenr} &&
2214
$line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
2215
my ($s, $c) = ($stat, $cond);
2216
2217
# if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
2218
# ERROR("do not use assignment in if condition\n" . $herecurr);
2219
# }
2220
2221
# Find out what is on the end of the line after the
2222
# conditional.
2223
substr($s, 0, length($c), '');
2224
$s =~ s/\n.*//g;
2225
$s =~ s/$;//g; # Remove any comments
2226
if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
2227
$c !~ /}\s*while\s*/)
2228
{
2229
# Find out how long the conditional actually is.
2230
my @newlines = ($c =~ /\n/gs);
2231
my $cond_lines = 1 + $#newlines;
2232
my $stat_real = '';
2233
2234
$stat_real = raw_line($linenr, $cond_lines)
2235
. "\n" if ($cond_lines);
2236
if (defined($stat_real) && $cond_lines > 1) {
2237
$stat_real = "[...]\n$stat_real";
2238
}
2239
2240
ERROR("trailing statements should be on next line\n" . $herecurr . $stat_real);
2241
}
2242
}
2243
2244
# Check for bitwise tests written as boolean
2245
if ($line =~ /
2246
(?:
2247
(?:\[|\(|\&\&|\|\|)
2248
\s*0[xX][0-9]+\s*
2249
(?:\&\&|\|\|)
2250
|
2251
(?:\&\&|\|\|)
2252
\s*0[xX][0-9]+\s*
2253
(?:\&\&|\|\||\)|\])
2254
)/x)
2255
{
2256
ERROR("boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
2257
}
2258
2259
# if and else should not have general statements after it
2260
if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
2261
my $s = $1;
2262
$s =~ s/$;//g; # Remove any comments
2263
if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
2264
ERROR("trailing statements should be on next line\n" . $herecurr);
2265
}
2266
}
2267
# if should not continue a brace
2268
if ($line =~ /}\s*if\b/) {
2269
ERROR("trailing statements should be on next line\n" .
2270
$herecurr);
2271
}
2272
# case and default should not have general statements after them
2273
if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
2274
$line !~ /\G(?:
2275
(?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
2276
\s*return\s+
2277
)/xg)
2278
{
2279
ERROR("trailing statements should be on next line\n" . $herecurr);
2280
}
2281
2282
# Check for }<nl>else {, these must be at the same
2283
# indent level to be relevant to each other.
2284
if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
2285
$previndent == $indent) {
2286
ERROR("else should follow close brace '}'\n" . $hereprev);
2287
}
2288
2289
if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
2290
$previndent == $indent) {
2291
my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
2292
2293
# Find out what is on the end of the line after the
2294
# conditional.
2295
substr($s, 0, length($c), '');
2296
$s =~ s/\n.*//g;
2297
2298
if ($s =~ /^\s*;/) {
2299
ERROR("while should follow close brace '}'\n" . $hereprev);
2300
}
2301
}
2302
2303
#no spaces allowed after \ in define
2304
if ($line=~/\#\s*define.*\\\s$/) {
2305
ERROR("Whitespace after \\ makes next lines useless\n" . $herecurr);
2306
}
2307
2308
# multi-statement macros should be enclosed in a do while loop, grab the
2309
# first statement and ensure its the whole macro if its not enclosed
2310
# in a known good container
2311
if ($realfile !~ m@/vmlinux.lds.h$@ &&
2312
$line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
2313
my $ln = $linenr;
2314
my $cnt = $realcnt;
2315
my ($off, $dstat, $dcond, $rest);
2316
my $ctx = '';
2317
2318
my $args = defined($1);
2319
2320
# Find the end of the macro and limit our statement
2321
# search to that.
2322
while ($cnt > 0 && defined $lines[$ln - 1] &&
2323
$lines[$ln - 1] =~ /^(?:-|..*\\$)/)
2324
{
2325
$ctx .= $rawlines[$ln - 1] . "\n";
2326
$cnt-- if ($lines[$ln - 1] !~ /^-/);
2327
$ln++;
2328
}
2329
$ctx .= $rawlines[$ln - 1];
2330
2331
($dstat, $dcond, $ln, $cnt, $off) =
2332
ctx_statement_block($linenr, $ln - $linenr + 1, 0);
2333
#print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
2334
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
2335
2336
# Extract the remainder of the define (if any) and
2337
# rip off surrounding spaces, and trailing \'s.
2338
$rest = '';
2339
while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) {
2340
#print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n";
2341
if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
2342
$rest .= substr($lines[$ln - 1], $off) . "\n";
2343
$cnt--;
2344
}
2345
$ln++;
2346
$off = 0;
2347
}
2348
$rest =~ s/\\\n.//g;
2349
$rest =~ s/^\s*//s;
2350
$rest =~ s/\s*$//s;
2351
2352
# Clean up the original statement.
2353
if ($args) {
2354
substr($dstat, 0, length($dcond), '');
2355
} else {
2356
$dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
2357
}
2358
$dstat =~ s/$;//g;
2359
$dstat =~ s/\\\n.//g;
2360
$dstat =~ s/^\s*//s;
2361
$dstat =~ s/\s*$//s;
2362
2363
# Flatten any parentheses and braces
2364
while ($dstat =~ s/\([^\(\)]*\)/1/ ||
2365
$dstat =~ s/\{[^\{\}]*\}/1/ ||
2366
$dstat =~ s/\[[^\{\}]*\]/1/)
2367
{
2368
}
2369
2370
my $exceptions = qr{
2371
$Declare|
2372
module_param_named|
2373
MODULE_PARAM_DESC|
2374
DECLARE_PER_CPU|
2375
DEFINE_PER_CPU|
2376
__typeof__\(|
2377
union|
2378
struct|
2379
\.$Ident\s*=\s*|
2380
^\"|\"$
2381
}x;
2382
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
2383
if ($rest ne '' && $rest ne ',') {
2384
if ($rest !~ /while\s*\(/ &&
2385
$dstat !~ /$exceptions/)
2386
{
2387
ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
2388
}
2389
2390
} elsif ($ctx !~ /;/) {
2391
if ($dstat ne '' &&
2392
$dstat !~ /^(?:$Ident|-?$Constant)$/ &&
2393
$dstat !~ /$exceptions/ &&
2394
$dstat !~ /^\.$Ident\s*=/ &&
2395
$dstat =~ /$Operators/)
2396
{
2397
ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
2398
}
2399
}
2400
}
2401
2402
# check for missing bracing around if etc
2403
if ($line =~ /(^.*)\b(?:if|while|for)\b/ &&
2404
$line !~ /\#\s*if/) {
2405
my $allowed = 0;
2406
2407
# Check the pre-context.
2408
if ($line =~ /(\}.*?)$/) {
2409
my $pre = $1;
2410
2411
if ($line !~ /else/) {
2412
print "APW: ALLOWED: pre<$pre> line<$line>\n"
2413
if $dbg_adv_apw;
2414
$allowed = 1;
2415
}
2416
}
2417
my ($level, $endln, @chunks) =
2418
ctx_statement_full($linenr, $realcnt, 1);
2419
if ($dbg_adv_apw) {
2420
print "APW: chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
2421
print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"
2422
if $#chunks >= 1;
2423
}
2424
if ($#chunks >= 0 && $level == 0) {
2425
my $seen = 0;
2426
my $herectx = $here . "\n";
2427
my $ln = $linenr - 1;
2428
for my $chunk (@chunks) {
2429
my ($cond, $block) = @{$chunk};
2430
2431
# If the condition carries leading newlines, then count those as offsets.
2432
my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
2433
my $offset = statement_rawlines($whitespace) - 1;
2434
2435
#print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
2436
2437
# We have looked at and allowed this specific line.
2438
$suppress_ifbraces{$ln + $offset} = 1;
2439
2440
$herectx .= "$rawlines[$ln + $offset]\n[...]\n";
2441
$ln += statement_rawlines($block) - 1;
2442
2443
substr($block, 0, length($cond), '');
2444
2445
my $spaced_block = $block;
2446
$spaced_block =~ s/\n\+/ /g;
2447
2448
$seen++ if ($spaced_block =~ /^\s*\{/);
2449
2450
print "APW: cond<$cond> block<$block> allowed<$allowed>\n"
2451
if $dbg_adv_apw;
2452
if (statement_lines($cond) > 1) {
2453
print "APW: ALLOWED: cond<$cond>\n"
2454
if $dbg_adv_apw;
2455
$allowed = 1;
2456
}
2457
if ($block =~/\b(?:if|for|while)\b/) {
2458
print "APW: ALLOWED: block<$block>\n"
2459
if $dbg_adv_apw;
2460
$allowed = 1;
2461
}
2462
if (statement_block_size($block) > 1) {
2463
print "APW: ALLOWED: lines block<$block>\n"
2464
if $dbg_adv_apw;
2465
$allowed = 1;
2466
}
2467
}
2468
$allowed=1; # disable for now.
2469
if ($seen != ($#chunks + 1) && !$allowed) {
2470
ERROR("braces {} are necessary for all arms of this statement\n" . $herectx);
2471
}
2472
}
2473
}
2474
if (!defined $suppress_ifbraces{$linenr - 1} &&
2475
$line =~ /\b(if|while|for|else)\b/ &&
2476
$line !~ /\#\s*if/ &&
2477
$line !~ /\#\s*else/) {
2478
my $allowed = 0;
2479
2480
# Check the pre-context.
2481
if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
2482
my $pre = $1;
2483
2484
if ($line !~ /else/) {
2485
print "APW: ALLOWED: pre<$pre> line<$line>\n"
2486
if $dbg_adv_apw;
2487
$allowed = 1;
2488
}
2489
}
2490
2491
my ($level, $endln, @chunks) =
2492
ctx_statement_full($linenr, $realcnt, $-[0]);
2493
2494
# Check the condition.
2495
my ($cond, $block) = @{$chunks[0]};
2496
print "CHECKING<$linenr> cond<$cond> block<$block>\n"
2497
if $dbg_adv_checking;
2498
if (defined $cond) {
2499
substr($block, 0, length($cond), '');
2500
}
2501
if (statement_lines($cond) > 1) {
2502
print "APW: ALLOWED: cond<$cond>\n"
2503
if $dbg_adv_apw;
2504
$allowed = 1;
2505
}
2506
if ($block =~/\b(?:if|for|while)\b/) {
2507
print "APW: ALLOWED: block<$block>\n"
2508
if $dbg_adv_apw;
2509
$allowed = 1;
2510
}
2511
if (statement_block_size($block) > 1) {
2512
print "APW: ALLOWED: lines block<$block>\n"
2513
if $dbg_adv_apw;
2514
$allowed = 1;
2515
}
2516
# Check the post-context.
2517
if (defined $chunks[1]) {
2518
my ($cond, $block) = @{$chunks[1]};
2519
if (defined $cond) {
2520
substr($block, 0, length($cond), '');
2521
}
2522
if ($block =~ /^\s*\{/) {
2523
print "APW: ALLOWED: chunk-1 block<$block>\n"
2524
if $dbg_adv_apw;
2525
$allowed = 1;
2526
}
2527
}
2528
print "DCS: level=$level block<$block> allowed=$allowed\n"
2529
if $dbg_adv_dcs;
2530
if ($level == 0 && $block !~ /^\s*\{/ && !$allowed) {
2531
my $herectx = $here . "\n";;
2532
my $cnt = statement_rawlines($block);
2533
2534
for (my $n = 0; $n < $cnt; $n++) {
2535
$herectx .= raw_line($linenr, $n) . "\n";;
2536
}
2537
2538
WARN("braces {} are encouraged even for single statement blocks\n" . $herectx);
2539
}
2540
}
2541
2542
# warn about #if 0
2543
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
2544
ERROR("if this code is redundant consider removing it\n" .
2545
$herecurr);
2546
}
2547
2548
# Check that the storage class is at the beginning of a declaration
2549
if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
2550
ERROR("storage class should be at the beginning of the declaration\n" . $herecurr)
2551
}
2552
2553
# check the location of the inline attribute, that it is between
2554
# storage class and type.
2555
if ($line =~ /\b$Type\s+$Inline\b/ ||
2556
$line =~ /\b$Inline\s+$Storage\b/) {
2557
ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
2558
}
2559
2560
# check for sizeof(&)
2561
if ($line =~ /\bsizeof\s*\(\s*\&/) {
2562
ERROR("sizeof(& should be avoided\n" . $herecurr);
2563
}
2564
2565
# check for new externs in .c files.
2566
if ($realfile =~ /\.c$/ && defined $stat &&
2567
$stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
2568
{
2569
my $function_name = $1;
2570
my $paren_space = $2;
2571
2572
my $s = $stat;
2573
if (defined $cond) {
2574
substr($s, 0, length($cond), '');
2575
}
2576
if ($s =~ /^\s*;/ &&
2577
$function_name ne 'uninitialized_var')
2578
{
2579
ERROR("externs should be avoided in .c files\n" . $herecurr);
2580
}
2581
2582
if ($paren_space =~ /\n/) {
2583
ERROR("arguments for function declarations should follow identifier\n" . $herecurr);
2584
}
2585
2586
} elsif ($realfile =~ /\.c$/ && defined $stat &&
2587
$stat =~ /^.\s*extern\s+/)
2588
{
2589
ERROR("externs should be avoided in .c files\n" . $herecurr);
2590
}
2591
2592
# check for gcc specific __FUNCTION__
2593
if ($line =~ /__FUNCTION__/) {
2594
ERROR("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
2595
}
2596
2597
# recommend sigaction over signal for portability, when establishing a handler
2598
if ($line =~ /\bsignal\s*\(/ && !($line =~ /SIG_(?:IGN|DFL)/)) {
2599
ERROR("use sigaction to establish signal handlers; signal is not portable\n" . $herecurr);
2600
}
2601
2602
# format strings checks
2603
my $string;
2604
while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
2605
$string = substr($rawline, $-[1], $+[1] - $-[1]);
2606
$string =~ s/%%/__/g;
2607
# check for %L{u,d,i} in strings
2608
if ($string =~ /(?<!%)%L[udi]/) {
2609
ERROR("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
2610
}
2611
}
2612
2613
# Continue checking for error messages that contains newlines. This
2614
# check handles cases where string literals are spread over multiple lines.
2615
# Example:
2616
# error_report("Error msg line #1"
2617
# "Error msg line #2\n");
2618
my $quoted_newline_regex = qr{\+\s*\".*\\n.*\"};
2619
my $continued_str_literal = qr{\+\s*\".*\"};
2620
2621
if ($rawline =~ /$quoted_newline_regex/) {
2622
# Backtrack to first line that does not contain only a quoted literal
2623
# and assume that it is the start of the statement.
2624
my $i = $linenr - 2;
2625
2626
while (($i >= 0) & $rawlines[$i] =~ /$continued_str_literal/) {
2627
$i--;
2628
}
2629
}
2630
2631
}
2632
2633
# If we have no input at all, then there is nothing to report on
2634
# so just keep quiet.
2635
if ($#rawlines == -1) {
2636
return 1;
2637
}
2638
2639
# In mailback mode only produce a report in the negative, for
2640
# things that appear to be patches.
2641
if ($mailback && ($clean == 1 || !$is_patch)) {
2642
return 1;
2643
}
2644
2645
# This is not a patch, and we are are in 'no-patch' mode so
2646
# just keep quiet.
2647
if (!$chk_patch && !$is_patch) {
2648
return 1;
2649
}
2650
2651
if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
2652
ERROR("Does not appear to be a unified-diff format patch\n");
2653
}
2654
2655
print report_dump();
2656
if ($summary && !($clean == 1 && $quiet == 1)) {
2657
print "$filename " if ($summary_file);
2658
print "total: $cnt_error errors, $cnt_warn warnings, " .
2659
"$cnt_lines lines checked\n";
2660
print "\n" if ($quiet == 0);
2661
}
2662
2663
if ($quiet == 0) {
2664
# If there were whitespace errors which cleanpatch can fix
2665
# then suggest that.
2666
# if ($rpt_cleaners) {
2667
# print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
2668
# print " scripts/cleanfile\n\n";
2669
# }
2670
}
2671
2672
if ($clean == 1 && $quiet == 0) {
2673
print "$vname has no obvious style problems and is ready for submission.\n"
2674
}
2675
2676
return ($no_warnings ? $clean : $cnt_error == 0);
2677
}
2678
2679