elf: limit the number of argc/envc
[akaros.git] / scripts / checkpatch.pl
1 #!/usr/bin/env perl
2 # SPDX-License-Identifier: GPL-2.0
3 #
4 # (c) 2001, Dave Jones. (the file handling bit)
5 # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
6 # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
7 # (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
8 # (c) 2010-2018 Joe Perches <joe@perches.com>
9 #
10 # Modifications for Akaros:
11 #   Copyright (c) 2015 Google Inc
12 #   Barret Rhoden <brho@cs.berkeley.edu>
13 #
14 # - Added a tab_length parameter, set it to 8
15 # - Set tree = 0, since we do not have a Linux kernel tree
16 # - No KERN_ checks for printk
17 # - ENOSYS can be used in more places
18 # - Block comments do not need to end on a trailing line
19 # - Can use spaces for aligning (more than tab_length spaces) and thus also at
20 # the beginning of a line
21 # - Can indent cases once more than its switch
22 # - Casting pointers can be (struct foo*) or (struct foo *)
23 # - Don't prod about updating MAINTAINERS
24 # - Allow C99 comments
25 # - Allow Gerrit change-ids
26 # - Don't check for the SPDX header
27
28 use strict;
29 use warnings;
30 use POSIX;
31 use File::Basename;
32 use Cwd 'abs_path';
33 use Term::ANSIColor qw(:constants);
34
35 my $P = $0;
36 my $D = dirname(abs_path($P));
37
38 my $V = '0.32';
39
40 use Getopt::Long qw(:config no_auto_abbrev);
41
42 my $quiet = 0;
43 my $tree = 0;
44 my $chk_signoff = 1;
45 my $chk_patch = 1;
46 my $tst_only;
47 my $emacs = 0;
48 my $terse = 0;
49 my $showfile = 0;
50 my $file = 0;
51 my $git = 0;
52 my %git_commits = ();
53 my $check = 0;
54 my $check_orig = 0;
55 my $summary = 1;
56 my $mailback = 0;
57 my $summary_file = 0;
58 my $show_types = 0;
59 my $list_types = 0;
60 my $fix = 0;
61 my $fix_inplace = 0;
62 my $root;
63 my %debug;
64 my %camelcase = ();
65 my %use_type = ();
66 my @use = ();
67 my %ignore_type = ();
68 my @ignore = ();
69 my $help = 0;
70 my $configuration_file = ".checkpatch.conf";
71 my $max_line_length = 80;
72 my $ignore_perl_version = 0;
73 my $minimum_perl_version = 5.10.0;
74 my $min_conf_desc_length = 4;
75 my $spelling_file = "$D/spelling.txt";
76 my $codespell = 0;
77 my $codespellfile = "/usr/share/codespell/dictionary.txt";
78 my $conststructsfile = "$D/const_structs.checkpatch";
79 my $typedefsfile = "";
80 my $color = "auto";
81 my $allow_c99_comments = 1;
82 my $tab_length = 8;
83
84 sub help {
85         my ($exitcode) = @_;
86
87         print << "EOM";
88 Usage: $P [OPTION]... [FILE]...
89 Version: $V
90
91 Options:
92   -q, --quiet                quiet
93   --no-tree                  run without a kernel tree
94   --no-signoff               do not check for 'Signed-off-by' line
95   --patch                    treat FILE as patchfile (default)
96   --emacs                    emacs compile window format
97   --terse                    one line per report
98   --showfile                 emit diffed file position, not input file position
99   -g, --git                  treat FILE as a single commit or git revision range
100                              single git commit with:
101                                <rev>
102                                <rev>^
103                                <rev>~n
104                              multiple git commits with:
105                                <rev1>..<rev2>
106                                <rev1>...<rev2>
107                                <rev>-<count>
108                              git merges are ignored
109   -f, --file                 treat FILE as regular source file
110   --subjective, --strict     enable more subjective tests
111   --list-types               list the possible message types
112   --types TYPE(,TYPE2...)    show only these comma separated message types
113   --ignore TYPE(,TYPE2...)   ignore various comma separated message types
114   --show-types               show the specific message type in the output
115   --max-line-length=n        set the maximum line length, if exceeded, warn
116   --min-conf-desc-length=n   set the min description length, if shorter, warn
117   --root=PATH                PATH to the kernel tree root
118   --no-summary               suppress the per-file summary
119   --mailback                 only produce a report in case of warnings/errors
120   --summary-file             include the filename in summary
121   --debug KEY=[0|1]          turn on/off debugging of KEY, where KEY is one of
122                              'values', 'possible', 'type', and 'attr' (default
123                              is all off)
124   --test-only=WORD           report only warnings/errors containing WORD
125                              literally
126   --fix                      EXPERIMENTAL - may create horrible results
127                              If correctable single-line errors exist, create
128                              "<inputfile>.EXPERIMENTAL-checkpatch-fixes"
129                              with potential errors corrected to the preferred
130                              checkpatch style
131   --fix-inplace              EXPERIMENTAL - may create horrible results
132                              Is the same as --fix, but overwrites the input
133                              file.  It's your fault if there's no backup or git
134   --ignore-perl-version      override checking of perl version.  expect
135                              runtime errors.
136   --codespell                Use the codespell dictionary for spelling/typos
137                              (default:/usr/share/codespell/dictionary.txt)
138   --codespellfile            Use this codespell dictionary
139   --typedefsfile             Read additional types from this file
140   --color[=WHEN]             Use colors 'always', 'never', or only when output
141                              is a terminal ('auto'). Default is 'auto'.
142   -h, --help, --version      display this help and exit
143
144 When FILE is - read standard input.
145 EOM
146
147         exit($exitcode);
148 }
149
150 sub uniq {
151         my %seen;
152         return grep { !$seen{$_}++ } @_;
153 }
154
155 sub list_types {
156         my ($exitcode) = @_;
157
158         my $count = 0;
159
160         local $/ = undef;
161
162         open(my $script, '<', abs_path($P)) or
163             die "$P: Can't read '$P' $!\n";
164
165         my $text = <$script>;
166         close($script);
167
168         my @types = ();
169         # Also catch when type or level is passed through a variable
170         for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
171                 push (@types, $_);
172         }
173         @types = sort(uniq(@types));
174         print("#\tMessage type\n\n");
175         foreach my $type (@types) {
176                 print(++$count . "\t" . $type . "\n");
177         }
178
179         exit($exitcode);
180 }
181
182 my $conf = which_conf($configuration_file);
183 if (-f $conf) {
184         my @conf_args;
185         open(my $conffile, '<', "$conf")
186             or warn "$P: Can't find a readable $configuration_file file $!\n";
187
188         while (<$conffile>) {
189                 my $line = $_;
190
191                 $line =~ s/\s*\n?$//g;
192                 $line =~ s/^\s*//g;
193                 $line =~ s/\s+/ /g;
194
195                 next if ($line =~ m/^\s*#/);
196                 next if ($line =~ m/^\s*$/);
197
198                 my @words = split(" ", $line);
199                 foreach my $word (@words) {
200                         last if ($word =~ m/^#/);
201                         push (@conf_args, $word);
202                 }
203         }
204         close($conffile);
205         unshift(@ARGV, @conf_args) if @conf_args;
206 }
207
208 # Perl's Getopt::Long allows options to take optional arguments after a space.
209 # Prevent --color by itself from consuming other arguments
210 foreach (@ARGV) {
211         if ($_ eq "--color" || $_ eq "-color") {
212                 $_ = "--color=$color";
213         }
214 }
215
216 GetOptions(
217         'q|quiet+'      => \$quiet,
218         'tree!'         => \$tree,
219         'signoff!'      => \$chk_signoff,
220         'patch!'        => \$chk_patch,
221         'emacs!'        => \$emacs,
222         'terse!'        => \$terse,
223         'showfile!'     => \$showfile,
224         'f|file!'       => \$file,
225         'g|git!'        => \$git,
226         'subjective!'   => \$check,
227         'strict!'       => \$check,
228         'ignore=s'      => \@ignore,
229         'types=s'       => \@use,
230         'show-types!'   => \$show_types,
231         'list-types!'   => \$list_types,
232         'max-line-length=i' => \$max_line_length,
233         'min-conf-desc-length=i' => \$min_conf_desc_length,
234         'root=s'        => \$root,
235         'summary!'      => \$summary,
236         'mailback!'     => \$mailback,
237         'summary-file!' => \$summary_file,
238         'fix!'          => \$fix,
239         'fix-inplace!'  => \$fix_inplace,
240         'ignore-perl-version!' => \$ignore_perl_version,
241         'debug=s'       => \%debug,
242         'test-only=s'   => \$tst_only,
243         'codespell!'    => \$codespell,
244         'codespellfile=s'       => \$codespellfile,
245         'typedefsfile=s'        => \$typedefsfile,
246         'color=s'       => \$color,
247         'no-color'      => \$color,     #keep old behaviors of -nocolor
248         'nocolor'       => \$color,     #keep old behaviors of -nocolor
249         'h|help'        => \$help,
250         'version'       => \$help
251 ) or help(1);
252
253 help(0) if ($help);
254
255 list_types(0) if ($list_types);
256
257 $fix = 1 if ($fix_inplace);
258 $check_orig = $check;
259
260 my $exit = 0;
261
262 if ($^V && $^V lt $minimum_perl_version) {
263         printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
264         if (!$ignore_perl_version) {
265                 exit(1);
266         }
267 }
268
269 #if no filenames are given, push '-' to read patch from stdin
270 if ($#ARGV < 0) {
271         push(@ARGV, '-');
272 }
273
274 if ($color =~ /^[01]$/) {
275         $color = !$color;
276 } elsif ($color =~ /^always$/i) {
277         $color = 1;
278 } elsif ($color =~ /^never$/i) {
279         $color = 0;
280 } elsif ($color =~ /^auto$/i) {
281         $color = (-t STDOUT);
282 } else {
283         die "Invalid color mode: $color\n";
284 }
285
286 sub hash_save_array_words {
287         my ($hashRef, $arrayRef) = @_;
288
289         my @array = split(/,/, join(',', @$arrayRef));
290         foreach my $word (@array) {
291                 $word =~ s/\s*\n?$//g;
292                 $word =~ s/^\s*//g;
293                 $word =~ s/\s+/ /g;
294                 $word =~ tr/[a-z]/[A-Z]/;
295
296                 next if ($word =~ m/^\s*#/);
297                 next if ($word =~ m/^\s*$/);
298
299                 $hashRef->{$word}++;
300         }
301 }
302
303 sub hash_show_words {
304         my ($hashRef, $prefix) = @_;
305
306         if (keys %$hashRef) {
307                 print "\nNOTE: $prefix message types:";
308                 foreach my $word (sort keys %$hashRef) {
309                         print " $word";
310                 }
311                 print "\n";
312         }
313 }
314
315 hash_save_array_words(\%ignore_type, \@ignore);
316 hash_save_array_words(\%use_type, \@use);
317
318 my $dbg_values = 0;
319 my $dbg_possible = 0;
320 my $dbg_type = 0;
321 my $dbg_attr = 0;
322 for my $key (keys %debug) {
323         ## no critic
324         eval "\${dbg_$key} = '$debug{$key}';";
325         die "$@" if ($@);
326 }
327
328 my $rpt_cleaners = 0;
329
330 if ($terse) {
331         $emacs = 1;
332         $quiet++;
333 }
334
335 if ($tree) {
336         if (defined $root) {
337                 if (!top_of_kernel_tree($root)) {
338                         die "$P: $root: --root does not point at a valid tree\n";
339                 }
340         } else {
341                 if (top_of_kernel_tree('.')) {
342                         $root = '.';
343                 } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
344                                                 top_of_kernel_tree($1)) {
345                         $root = $1;
346                 }
347         }
348
349         if (!defined $root) {
350                 print "Must be run from the top-level dir. of a kernel tree\n";
351                 exit(2);
352         }
353 }
354
355 my $emitted_corrupt = 0;
356
357 our $Ident      = qr{
358                         [A-Za-z_][A-Za-z\d_]*
359                         (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
360                 }x;
361 our $Storage    = qr{extern|static|asmlinkage};
362 our $Sparse     = qr{
363                         __user|
364                         __kernel|
365                         __force|
366                         __iomem|
367                         __must_check|
368                         __init_refok|
369                         __kprobes|
370                         __ref|
371                         __rcu|
372                         __private
373                 }x;
374 our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
375 our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
376 our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)};
377 our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)};
378 our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit};
379
380 # Notes to $Attribute:
381 # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
382 our $Attribute  = qr{
383                         const|
384                         __percpu|
385                         __nocast|
386                         __safe|
387                         __bitwise|
388                         __packed__|
389                         __packed2__|
390                         __naked|
391                         __maybe_unused|
392                         __always_unused|
393                         __noreturn|
394                         __used|
395                         __cold|
396                         __pure|
397                         __noclone|
398                         __deprecated|
399                         __read_mostly|
400                         __kprobes|
401                         $InitAttribute|
402                         ____cacheline_aligned|
403                         ____cacheline_aligned_in_smp|
404                         ____cacheline_internodealigned_in_smp|
405                         __weak
406                   }x;
407 our $Modifier;
408 our $Inline     = qr{inline|__always_inline|noinline|__inline|__inline__};
409 our $Member     = qr{->$Ident|\.$Ident|\[[^]]*\]};
410 our $Lval       = qr{$Ident(?:$Member)*};
411
412 our $Int_type   = qr{(?i)llu|ull|ll|lu|ul|l|u};
413 our $Binary     = qr{(?i)0b[01]+$Int_type?};
414 our $Hex        = qr{(?i)0x[0-9a-f]+$Int_type?};
415 our $Int        = qr{[0-9]+$Int_type?};
416 our $Octal      = qr{0[0-7]+$Int_type?};
417 our $String     = qr{"[X\t]*"};
418 our $Float_hex  = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
419 our $Float_dec  = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
420 our $Float_int  = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
421 our $Float      = qr{$Float_hex|$Float_dec|$Float_int};
422 our $Constant   = qr{$Float|$Binary|$Octal|$Hex|$Int};
423 our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
424 our $Compare    = qr{<=|>=|==|!=|<|(?<!-)>};
425 our $Arithmetic = qr{\+|-|\*|\/|%};
426 our $Operators  = qr{
427                         <=|>=|==|!=|
428                         =>|->|<<|>>|<|>|!|~|
429                         &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
430                   }x;
431
432 our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
433
434 our $BasicType;
435 our $NonptrType;
436 our $NonptrTypeMisordered;
437 our $NonptrTypeWithAttr;
438 our $Type;
439 our $TypeMisordered;
440 our $Declare;
441 our $DeclareMisordered;
442
443 our $NON_ASCII_UTF8     = qr{
444         [\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
445         |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
446         | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
447         |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
448         |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
449         | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
450         |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
451 }x;
452
453 our $UTF8       = qr{
454         [\x09\x0A\x0D\x20-\x7E]              # ASCII
455         | $NON_ASCII_UTF8
456 }x;
457
458 our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t};
459 our $typeOtherOSTypedefs = qr{(?x:
460         u_(?:char|short|int|long) |          # bsd
461         u(?:nchar|short|int|long)            # sysv
462 )};
463 our $typeKernelTypedefs = qr{(?x:
464         (?:__)?(?:u|s|be|le)(?:8|16|32|64)|
465         atomic_t
466 )};
467 our $typeTypedefs = qr{(?x:
468         $typeC99Typedefs\b|
469         $typeOtherOSTypedefs\b|
470         $typeKernelTypedefs\b
471 )};
472
473 our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
474
475 our $logFunctions = qr{(?x:
476         printk(?:_ratelimited|_once|_deferred_once|_deferred|)|
477         (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
478         TP_printk|
479         WARN(?:_RATELIMIT|_ONCE|)|
480         panic|
481         MODULE_[A-Z_]+|
482         seq_vprintf|seq_printf|seq_puts
483 )};
484
485 our $signature_tags = qr{(?xi:
486         Signed-off-by:|
487         Acked-by:|
488         Tested-by:|
489         Reviewed-by:|
490         Reported-by:|
491         Suggested-by:|
492         To:|
493         Cc:
494 )};
495
496 our @typeListMisordered = (
497         qr{char\s+(?:un)?signed},
498         qr{int\s+(?:(?:un)?signed\s+)?short\s},
499         qr{int\s+short(?:\s+(?:un)?signed)},
500         qr{short\s+int(?:\s+(?:un)?signed)},
501         qr{(?:un)?signed\s+int\s+short},
502         qr{short\s+(?:un)?signed},
503         qr{long\s+int\s+(?:un)?signed},
504         qr{int\s+long\s+(?:un)?signed},
505         qr{long\s+(?:un)?signed\s+int},
506         qr{int\s+(?:un)?signed\s+long},
507         qr{int\s+(?:un)?signed},
508         qr{int\s+long\s+long\s+(?:un)?signed},
509         qr{long\s+long\s+int\s+(?:un)?signed},
510         qr{long\s+long\s+(?:un)?signed\s+int},
511         qr{long\s+long\s+(?:un)?signed},
512         qr{long\s+(?:un)?signed},
513 );
514
515 our @typeList = (
516         qr{void},
517         qr{(?:(?:un)?signed\s+)?char},
518         qr{(?:(?:un)?signed\s+)?short\s+int},
519         qr{(?:(?:un)?signed\s+)?short},
520         qr{(?:(?:un)?signed\s+)?int},
521         qr{(?:(?:un)?signed\s+)?long\s+int},
522         qr{(?:(?:un)?signed\s+)?long\s+long\s+int},
523         qr{(?:(?:un)?signed\s+)?long\s+long},
524         qr{(?:(?:un)?signed\s+)?long},
525         qr{(?:un)?signed},
526         qr{float},
527         qr{double},
528         qr{bool},
529         qr{struct\s+$Ident},
530         qr{union\s+$Ident},
531         qr{enum\s+$Ident},
532         qr{${Ident}_t},
533         qr{${Ident}_handler},
534         qr{${Ident}_handler_fn},
535         @typeListMisordered,
536 );
537
538 our $C90_int_types = qr{(?x:
539         long\s+long\s+int\s+(?:un)?signed|
540         long\s+long\s+(?:un)?signed\s+int|
541         long\s+long\s+(?:un)?signed|
542         (?:(?:un)?signed\s+)?long\s+long\s+int|
543         (?:(?:un)?signed\s+)?long\s+long|
544         int\s+long\s+long\s+(?:un)?signed|
545         int\s+(?:(?:un)?signed\s+)?long\s+long|
546
547         long\s+int\s+(?:un)?signed|
548         long\s+(?:un)?signed\s+int|
549         long\s+(?:un)?signed|
550         (?:(?:un)?signed\s+)?long\s+int|
551         (?:(?:un)?signed\s+)?long|
552         int\s+long\s+(?:un)?signed|
553         int\s+(?:(?:un)?signed\s+)?long|
554
555         int\s+(?:un)?signed|
556         (?:(?:un)?signed\s+)?int
557 )};
558
559 our @typeListFile = ();
560 our @typeListWithAttr = (
561         @typeList,
562         qr{struct\s+$InitAttribute\s+$Ident},
563         qr{union\s+$InitAttribute\s+$Ident},
564 );
565
566 our @modifierList = (
567         qr{fastcall},
568 );
569 our @modifierListFile = ();
570
571 our @mode_permission_funcs = (
572         ["module_param", 3],
573         ["module_param_(?:array|named|string)", 4],
574         ["module_param_array_named", 5],
575         ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
576         ["proc_create(?:_data|)", 2],
577         ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
578         ["IIO_DEV_ATTR_[A-Z_]+", 1],
579         ["SENSOR_(?:DEVICE_|)ATTR_2", 2],
580         ["SENSOR_TEMPLATE(?:_2|)", 3],
581         ["__ATTR", 2],
582 );
583
584 #Create a search pattern for all these functions to speed up a loop below
585 our $mode_perms_search = "";
586 foreach my $entry (@mode_permission_funcs) {
587         $mode_perms_search .= '|' if ($mode_perms_search ne "");
588         $mode_perms_search .= $entry->[0];
589 }
590 $mode_perms_search = "(?:${mode_perms_search})";
591
592 our $mode_perms_world_writable = qr{
593         S_IWUGO         |
594         S_IWOTH         |
595         S_IRWXUGO       |
596         S_IALLUGO       |
597         0[0-7][0-7][2367]
598 }x;
599
600 our %mode_permission_string_types = (
601         "S_IRWXU" => 0700,
602         "S_IRUSR" => 0400,
603         "S_IWUSR" => 0200,
604         "S_IXUSR" => 0100,
605         "S_IRWXG" => 0070,
606         "S_IRGRP" => 0040,
607         "S_IWGRP" => 0020,
608         "S_IXGRP" => 0010,
609         "S_IRWXO" => 0007,
610         "S_IROTH" => 0004,
611         "S_IWOTH" => 0002,
612         "S_IXOTH" => 0001,
613         "S_IRWXUGO" => 0777,
614         "S_IRUGO" => 0444,
615         "S_IWUGO" => 0222,
616         "S_IXUGO" => 0111,
617 );
618
619 #Create a search pattern for all these strings to speed up a loop below
620 our $mode_perms_string_search = "";
621 foreach my $entry (keys %mode_permission_string_types) {
622         $mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
623         $mode_perms_string_search .= $entry;
624 }
625 our $single_mode_perms_string_search = "(?:${mode_perms_string_search})";
626 our $multi_mode_perms_string_search = qr{
627         ${single_mode_perms_string_search}
628         (?:\s*\|\s*${single_mode_perms_string_search})*
629 }x;
630
631 sub perms_to_octal {
632         my ($string) = @_;
633
634         return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/);
635
636         my $val = "";
637         my $oval = "";
638         my $to = 0;
639         my $curpos = 0;
640         my $lastpos = 0;
641         while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
642                 $curpos = pos($string);
643                 my $match = $2;
644                 my $omatch = $1;
645                 last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
646                 $lastpos = $curpos;
647                 $to |= $mode_permission_string_types{$match};
648                 $val .= '\s*\|\s*' if ($val ne "");
649                 $val .= $match;
650                 $oval .= $omatch;
651         }
652         $oval =~ s/^\s*\|\s*//;
653         $oval =~ s/\s*\|\s*$//;
654         return sprintf("%04o", $to);
655 }
656
657 our $allowed_asm_includes = qr{(?x:
658         irq|
659         memory|
660         time|
661         reboot
662 )};
663 # memory.h: ARM has a custom one
664
665 # Load common spelling mistakes and build regular expression list.
666 my $misspellings;
667 my %spelling_fix;
668
669 if (open(my $spelling, '<', $spelling_file)) {
670         while (<$spelling>) {
671                 my $line = $_;
672
673                 $line =~ s/\s*\n?$//g;
674                 $line =~ s/^\s*//g;
675
676                 next if ($line =~ m/^\s*#/);
677                 next if ($line =~ m/^\s*$/);
678
679                 my ($suspect, $fix) = split(/\|\|/, $line);
680
681                 $spelling_fix{$suspect} = $fix;
682         }
683         close($spelling);
684 } else {
685         warn "No typos will be found - file '$spelling_file': $!\n";
686 }
687
688 if ($codespell) {
689         if (open(my $spelling, '<', $codespellfile)) {
690                 while (<$spelling>) {
691                         my $line = $_;
692
693                         $line =~ s/\s*\n?$//g;
694                         $line =~ s/^\s*//g;
695
696                         next if ($line =~ m/^\s*#/);
697                         next if ($line =~ m/^\s*$/);
698                         next if ($line =~ m/, disabled/i);
699
700                         $line =~ s/,.*$//;
701
702                         my ($suspect, $fix) = split(/->/, $line);
703
704                         $spelling_fix{$suspect} = $fix;
705                 }
706                 close($spelling);
707         } else {
708                 warn "No codespell typos will be found - file '$codespellfile': $!\n";
709         }
710 }
711
712 $misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
713
714 sub read_words {
715         my ($wordsRef, $file) = @_;
716
717         if (open(my $words, '<', $file)) {
718                 while (<$words>) {
719                         my $line = $_;
720
721                         $line =~ s/\s*\n?$//g;
722                         $line =~ s/^\s*//g;
723
724                         next if ($line =~ m/^\s*#/);
725                         next if ($line =~ m/^\s*$/);
726                         if ($line =~ /\s/) {
727                                 print("$file: '$line' invalid - ignored\n");
728                                 next;
729                         }
730
731                         $$wordsRef .= '|' if ($$wordsRef ne "");
732                         $$wordsRef .= $line;
733                 }
734                 close($file);
735                 return 1;
736         }
737
738         return 0;
739 }
740
741 my $const_structs = "";
742 read_words(\$const_structs, $conststructsfile)
743     or warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
744
745 my $typeOtherTypedefs = "";
746 if (length($typedefsfile)) {
747         read_words(\$typeOtherTypedefs, $typedefsfile)
748             or warn "No additional types will be considered - file '$typedefsfile': $!\n";
749 }
750 $typeTypedefs .= '|' . $typeOtherTypedefs if ($typeOtherTypedefs ne "");
751
752 sub build_types {
753         my $mods = "(?x:  \n" . join("|\n  ", (@modifierList, @modifierListFile)) . "\n)";
754         my $all = "(?x:  \n" . join("|\n  ", (@typeList, @typeListFile)) . "\n)";
755         my $Misordered = "(?x:  \n" . join("|\n  ", @typeListMisordered) . "\n)";
756         my $allWithAttr = "(?x:  \n" . join("|\n  ", @typeListWithAttr) . "\n)";
757         $Modifier       = qr{(?:$Attribute|$Sparse|$mods)};
758         $BasicType      = qr{
759                                 (?:$typeTypedefs\b)|
760                                 (?:${all}\b)
761                 }x;
762         $NonptrType     = qr{
763                         (?:$Modifier\s+|const\s+)*
764                         (?:
765                                 (?:typeof|__typeof__)\s*\([^\)]*\)|
766                                 (?:$typeTypedefs\b)|
767                                 (?:${all}\b)
768                         )
769                         (?:\s+$Modifier|\s+const)*
770                   }x;
771         $NonptrTypeMisordered   = qr{
772                         (?:$Modifier\s+|const\s+)*
773                         (?:
774                                 (?:${Misordered}\b)
775                         )
776                         (?:\s+$Modifier|\s+const)*
777                   }x;
778         $NonptrTypeWithAttr     = qr{
779                         (?:$Modifier\s+|const\s+)*
780                         (?:
781                                 (?:typeof|__typeof__)\s*\([^\)]*\)|
782                                 (?:$typeTypedefs\b)|
783                                 (?:${allWithAttr}\b)
784                         )
785                         (?:\s+$Modifier|\s+const)*
786                   }x;
787         $Type   = qr{
788                         $NonptrType
789                         (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
790                         (?:\s+$Inline|\s+$Modifier)*
791                   }x;
792         $TypeMisordered = qr{
793                         $NonptrTypeMisordered
794                         (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
795                         (?:\s+$Inline|\s+$Modifier)*
796                   }x;
797         $Declare        = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
798         $DeclareMisordered      = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered};
799 }
800 build_types();
801
802 our $Typecast   = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
803
804 # Using $balanced_parens, $LvalOrFunc, or $FuncArg
805 # requires at least perl version v5.10.0
806 # Any use must be runtime checked with $^V
807
808 our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
809 our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
810 our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
811
812 our $declaration_macros = qr{(?x:
813         (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
814         (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
815         (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(|
816         (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
817 )};
818
819 sub deparenthesize {
820         my ($string) = @_;
821         return "" if (!defined($string));
822
823         while ($string =~ /^\s*\(.*\)\s*$/) {
824                 $string =~ s@^\s*\(\s*@@;
825                 $string =~ s@\s*\)\s*$@@;
826         }
827
828         $string =~ s@\s+@ @g;
829
830         return $string;
831 }
832
833 sub seed_camelcase_file {
834         my ($file) = @_;
835
836         return if (!(-f $file));
837
838         local $/;
839
840         open(my $include_file, '<', "$file")
841             or warn "$P: Can't read '$file' $!\n";
842         my $text = <$include_file>;
843         close($include_file);
844
845         my @lines = split('\n', $text);
846
847         foreach my $line (@lines) {
848                 next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/);
849                 if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) {
850                         $camelcase{$1} = 1;
851                 } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) {
852                         $camelcase{$1} = 1;
853                 } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) {
854                         $camelcase{$1} = 1;
855                 }
856         }
857 }
858
859 sub is_maintained_obsolete {
860         my ($filename) = @_;
861
862         return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
863
864         my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
865
866         return $status =~ /obsolete/i;
867 }
868
869 my $camelcase_seeded = 0;
870 sub seed_camelcase_includes {
871         return if ($camelcase_seeded);
872
873         my $files;
874         my $camelcase_cache = "";
875         my @include_files = ();
876
877         $camelcase_seeded = 1;
878
879         if (-e ".git") {
880                 my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
881                 chomp $git_last_include_commit;
882                 $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
883         } else {
884                 my $last_mod_date = 0;
885                 $files = `find $root/include -name "*.h"`;
886                 @include_files = split('\n', $files);
887                 foreach my $file (@include_files) {
888                         my $date = POSIX::strftime("%Y%m%d%H%M",
889                                                    localtime((stat $file)[9]));
890                         $last_mod_date = $date if ($last_mod_date < $date);
891                 }
892                 $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date";
893         }
894
895         if ($camelcase_cache ne "" && -f $camelcase_cache) {
896                 open(my $camelcase_file, '<', "$camelcase_cache")
897                     or warn "$P: Can't read '$camelcase_cache' $!\n";
898                 while (<$camelcase_file>) {
899                         chomp;
900                         $camelcase{$_} = 1;
901                 }
902                 close($camelcase_file);
903
904                 return;
905         }
906
907         if (-e ".git") {
908                 $files = `git ls-files "include/*.h"`;
909                 @include_files = split('\n', $files);
910         }
911
912         foreach my $file (@include_files) {
913                 seed_camelcase_file($file);
914         }
915
916         if ($camelcase_cache ne "") {
917                 unlink glob ".checkpatch-camelcase.*";
918                 open(my $camelcase_file, '>', "$camelcase_cache")
919                     or warn "$P: Can't write '$camelcase_cache' $!\n";
920                 foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) {
921                         print $camelcase_file ("$_\n");
922                 }
923                 close($camelcase_file);
924         }
925 }
926
927 sub git_commit_info {
928         my ($commit, $id, $desc) = @_;
929
930         return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
931
932         my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
933         $output =~ s/^\s*//gm;
934         my @lines = split("\n", $output);
935
936         return ($id, $desc) if ($#lines < 0);
937
938         if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
939 # Maybe one day convert this block of bash into something that returns
940 # all matching commit ids, but it's very slow...
941 #
942 #               echo "checking commits $1..."
943 #               git rev-list --remotes | grep -i "^$1" |
944 #               while read line ; do
945 #                   git log --format='%H %s' -1 $line |
946 #                   echo "commit $(cut -c 1-12,41-)"
947 #               done
948         } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
949                 $id = undef;
950         } else {
951                 $id = substr($lines[0], 0, 12);
952                 $desc = substr($lines[0], 41);
953         }
954
955         return ($id, $desc);
956 }
957
958 $chk_signoff = 0 if ($file);
959
960 my @rawlines = ();
961 my @lines = ();
962 my @fixed = ();
963 my @fixed_inserted = ();
964 my @fixed_deleted = ();
965 my $fixlinenr = -1;
966
967 # If input is git commits, extract all commits from the commit expressions.
968 # For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
969 die "$P: No git repository found\n" if ($git && !-e ".git");
970
971 if ($git) {
972         my @commits = ();
973         foreach my $commit_expr (@ARGV) {
974                 my $git_range;
975                 if ($commit_expr =~ m/^(.*)-(\d+)$/) {
976                         $git_range = "-$2 $1";
977                 } elsif ($commit_expr =~ m/\.\./) {
978                         $git_range = "$commit_expr";
979                 } else {
980                         $git_range = "-1 $commit_expr";
981                 }
982                 my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
983                 foreach my $line (split(/\n/, $lines)) {
984                         $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
985                         next if (!defined($1) || !defined($2));
986                         my $sha1 = $1;
987                         my $subject = $2;
988                         unshift(@commits, $sha1);
989                         $git_commits{$sha1} = $subject;
990                 }
991         }
992         die "$P: no git commits after extraction!\n" if (@commits == 0);
993         @ARGV = @commits;
994 }
995
996 my $vname;
997 for my $filename (@ARGV) {
998         my $FILE;
999         if ($git) {
1000                 open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
1001                         die "$P: $filename: git format-patch failed - $!\n";
1002         } elsif ($file) {
1003                 open($FILE, '-|', "diff -u /dev/null $filename") ||
1004                         die "$P: $filename: diff failed - $!\n";
1005         } elsif ($filename eq '-') {
1006                 open($FILE, '<&STDIN');
1007         } else {
1008                 open($FILE, '<', "$filename") ||
1009                         die "$P: $filename: open failed - $!\n";
1010         }
1011         if ($filename eq '-') {
1012                 $vname = 'Your patch';
1013         } elsif ($git) {
1014                 $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
1015         } else {
1016                 $vname = $filename;
1017         }
1018         while (<$FILE>) {
1019                 chomp;
1020                 push(@rawlines, $_);
1021         }
1022         close($FILE);
1023
1024         if ($#ARGV > 0 && $quiet == 0) {
1025                 print '-' x length($vname) . "\n";
1026                 print "$vname\n";
1027                 print '-' x length($vname) . "\n";
1028         }
1029
1030         if (!process($filename)) {
1031                 $exit = 1;
1032         }
1033         @rawlines = ();
1034         @lines = ();
1035         @fixed = ();
1036         @fixed_inserted = ();
1037         @fixed_deleted = ();
1038         $fixlinenr = -1;
1039         @modifierListFile = ();
1040         @typeListFile = ();
1041         build_types();
1042 }
1043
1044 if (!$quiet) {
1045         hash_show_words(\%use_type, "Used");
1046         hash_show_words(\%ignore_type, "Ignored");
1047
1048         if ($^V lt 5.10.0) {
1049                 print << "EOM"
1050
1051 NOTE: perl $^V is not modern enough to detect all possible issues.
1052       An upgrade to at least perl v5.10.0 is suggested.
1053 EOM
1054         }
1055         if ($exit) {
1056                 print << "EOM"
1057
1058 NOTE: If any of the errors are false positives, please report
1059       them to the maintainer, see CHECKPATCH in MAINTAINERS.
1060 EOM
1061         }
1062 }
1063
1064 exit($exit);
1065
1066 sub top_of_kernel_tree {
1067         my ($root) = @_;
1068
1069         my @tree_check = (
1070                 "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
1071                 "README", "Documentation", "arch", "include", "drivers",
1072                 "fs", "init", "ipc", "kernel", "lib", "scripts",
1073         );
1074
1075         foreach my $check (@tree_check) {
1076                 if (! -e $root . '/' . $check) {
1077                         return 0;
1078                 }
1079         }
1080         return 1;
1081 }
1082
1083 sub parse_email {
1084         my ($formatted_email) = @_;
1085
1086         my $name = "";
1087         my $address = "";
1088         my $comment = "";
1089
1090         if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) {
1091                 $name = $1;
1092                 $address = $2;
1093                 $comment = $3 if defined $3;
1094         } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) {
1095                 $address = $1;
1096                 $comment = $2 if defined $2;
1097         } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
1098                 $address = $1;
1099                 $comment = $2 if defined $2;
1100                 $formatted_email =~ s/\Q$address\E.*$//;
1101                 $name = $formatted_email;
1102                 $name = trim($name);
1103                 $name =~ s/^\"|\"$//g;
1104                 # If there's a name left after stripping spaces and
1105                 # leading quotes, and the address doesn't have both
1106                 # leading and trailing angle brackets, the address
1107                 # is invalid. ie:
1108                 #   "joe smith joe@smith.com" bad
1109                 #   "joe smith <joe@smith.com" bad
1110                 if ($name ne "" && $address !~ /^<[^>]+>$/) {
1111                         $name = "";
1112                         $address = "";
1113                         $comment = "";
1114                 }
1115         }
1116
1117         $name = trim($name);
1118         $name =~ s/^\"|\"$//g;
1119         $address = trim($address);
1120         $address =~ s/^\<|\>$//g;
1121
1122         if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
1123                 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
1124                 $name = "\"$name\"";
1125         }
1126
1127         return ($name, $address, $comment);
1128 }
1129
1130 sub format_email {
1131         my ($name, $address) = @_;
1132
1133         my $formatted_email;
1134
1135         $name = trim($name);
1136         $name =~ s/^\"|\"$//g;
1137         $address = trim($address);
1138
1139         if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
1140                 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
1141                 $name = "\"$name\"";
1142         }
1143
1144         if ("$name" eq "") {
1145                 $formatted_email = "$address";
1146         } else {
1147                 $formatted_email = "$name <$address>";
1148         }
1149
1150         return $formatted_email;
1151 }
1152
1153 sub which {
1154         my ($bin) = @_;
1155
1156         foreach my $path (split(/:/, $ENV{PATH})) {
1157                 if (-e "$path/$bin") {
1158                         return "$path/$bin";
1159                 }
1160         }
1161
1162         return "";
1163 }
1164
1165 sub which_conf {
1166         my ($conf) = @_;
1167
1168         foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
1169                 if (-e "$path/$conf") {
1170                         return "$path/$conf";
1171                 }
1172         }
1173
1174         return "";
1175 }
1176
1177 sub expand_tabs {
1178         my ($str) = @_;
1179
1180         my $res = '';
1181         my $n = 0;
1182         for my $c (split(//, $str)) {
1183                 if ($c eq "\t") {
1184                         $res .= ' ';
1185                         $n++;
1186                         for (; ($n % $tab_length) != 0; $n++) {
1187                                 $res .= ' ';
1188                         }
1189                         next;
1190                 }
1191                 $res .= $c;
1192                 $n++;
1193         }
1194
1195         return $res;
1196 }
1197 sub copy_spacing {
1198         (my $res = shift) =~ tr/\t/ /c;
1199         return $res;
1200 }
1201
1202 sub line_stats {
1203         my ($line) = @_;
1204
1205         # Drop the diff line leader and expand tabs
1206         $line =~ s/^.//;
1207         $line = expand_tabs($line);
1208
1209         # Pick the indent from the front of the line.
1210         my ($white) = ($line =~ /^(\s*)/);
1211
1212         return (length($line), length($white));
1213 }
1214
1215 my $sanitise_quote = '';
1216
1217 sub sanitise_line_reset {
1218         my ($in_comment) = @_;
1219
1220         if ($in_comment) {
1221                 $sanitise_quote = '*/';
1222         } else {
1223                 $sanitise_quote = '';
1224         }
1225 }
1226 sub sanitise_line {
1227         my ($line) = @_;
1228
1229         my $res = '';
1230         my $l = '';
1231
1232         my $qlen = 0;
1233         my $off = 0;
1234         my $c;
1235
1236         # Always copy over the diff marker.
1237         $res = substr($line, 0, 1);
1238
1239         for ($off = 1; $off < length($line); $off++) {
1240                 $c = substr($line, $off, 1);
1241
1242                 # Comments we are whacking completely including the begin
1243                 # and end, all to $;.
1244                 if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
1245                         $sanitise_quote = '*/';
1246
1247                         substr($res, $off, 2, "$;$;");
1248                         $off++;
1249                         next;
1250                 }
1251                 if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
1252                         $sanitise_quote = '';
1253                         substr($res, $off, 2, "$;$;");
1254                         $off++;
1255                         next;
1256                 }
1257                 if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
1258                         $sanitise_quote = '//';
1259
1260                         substr($res, $off, 2, $sanitise_quote);
1261                         $off++;
1262                         next;
1263                 }
1264
1265                 # A \ in a string means ignore the next character.
1266                 if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
1267                     $c eq "\\") {
1268                         substr($res, $off, 2, 'XX');
1269                         $off++;
1270                         next;
1271                 }
1272                 # Regular quotes.
1273                 if ($c eq "'" || $c eq '"') {
1274                         if ($sanitise_quote eq '') {
1275                                 $sanitise_quote = $c;
1276
1277                                 substr($res, $off, 1, $c);
1278                                 next;
1279                         } elsif ($sanitise_quote eq $c) {
1280                                 $sanitise_quote = '';
1281                         }
1282                 }
1283
1284                 #print "c<$c> SQ<$sanitise_quote>\n";
1285                 if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
1286                         substr($res, $off, 1, $;);
1287                 } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
1288                         substr($res, $off, 1, $;);
1289                 } elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
1290                         substr($res, $off, 1, 'X');
1291                 } else {
1292                         substr($res, $off, 1, $c);
1293                 }
1294         }
1295
1296         if ($sanitise_quote eq '//') {
1297                 $sanitise_quote = '';
1298         }
1299
1300         # The pathname on a #include may be surrounded by '<' and '>'.
1301         if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
1302                 my $clean = 'X' x length($1);
1303                 $res =~ s@\<.*\>@<$clean>@;
1304
1305         # The whole of a #error is a string.
1306         } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
1307                 my $clean = 'X' x length($1);
1308                 $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
1309         }
1310
1311         if ($allow_c99_comments && $res =~ m@(//.*$)@) {
1312                 my $match = $1;
1313                 $res =~ s/\Q$match\E/"$;" x length($match)/e;
1314         }
1315
1316         return $res;
1317 }
1318
1319 sub get_quoted_string {
1320         my ($line, $rawline) = @_;
1321
1322         return "" if (!defined($line) || !defined($rawline));
1323         return "" if ($line !~ m/($String)/g);
1324         return substr($rawline, $-[0], $+[0] - $-[0]);
1325 }
1326
1327 sub ctx_statement_block {
1328         my ($linenr, $remain, $off) = @_;
1329         my $line = $linenr - 1;
1330         my $blk = '';
1331         my $soff = $off;
1332         my $coff = $off - 1;
1333         my $coff_set = 0;
1334
1335         my $loff = 0;
1336
1337         my $type = '';
1338         my $level = 0;
1339         my @stack = ();
1340         my $p;
1341         my $c;
1342         my $len = 0;
1343
1344         my $remainder;
1345         while (1) {
1346                 @stack = (['', 0]) if ($#stack == -1);
1347
1348                 #warn "CSB: blk<$blk> remain<$remain>\n";
1349                 # If we are about to drop off the end, pull in more
1350                 # context.
1351                 if ($off >= $len) {
1352                         for (; $remain > 0; $line++) {
1353                                 last if (!defined $lines[$line]);
1354                                 next if ($lines[$line] =~ /^-/);
1355                                 $remain--;
1356                                 $loff = $len;
1357                                 $blk .= $lines[$line] . "\n";
1358                                 $len = length($blk);
1359                                 $line++;
1360                                 last;
1361                         }
1362                         # Bail if there is no further context.
1363                         #warn "CSB: blk<$blk> off<$off> len<$len>\n";
1364                         if ($off >= $len) {
1365                                 last;
1366                         }
1367                         if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) {
1368                                 $level++;
1369                                 $type = '#';
1370                         }
1371                 }
1372                 $p = $c;
1373                 $c = substr($blk, $off, 1);
1374                 $remainder = substr($blk, $off);
1375
1376                 #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
1377
1378                 # Handle nested #if/#else.
1379                 if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
1380                         push(@stack, [ $type, $level ]);
1381                 } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
1382                         ($type, $level) = @{$stack[$#stack - 1]};
1383                 } elsif ($remainder =~ /^#\s*endif\b/) {
1384                         ($type, $level) = @{pop(@stack)};
1385                 }
1386
1387                 # Statement ends at the ';' or a close '}' at the
1388                 # outermost level.
1389                 if ($level == 0 && $c eq ';') {
1390                         last;
1391                 }
1392
1393                 # An else is really a conditional as long as its not else if
1394                 if ($level == 0 && $coff_set == 0 &&
1395                                 (!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
1396                                 $remainder =~ /^(else)(?:\s|{)/ &&
1397                                 $remainder !~ /^else\s+if\b/) {
1398                         $coff = $off + length($1) - 1;
1399                         $coff_set = 1;
1400                         #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
1401                         #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
1402                 }
1403
1404                 if (($type eq '' || $type eq '(') && $c eq '(') {
1405                         $level++;
1406                         $type = '(';
1407                 }
1408                 if ($type eq '(' && $c eq ')') {
1409                         $level--;
1410                         $type = ($level != 0)? '(' : '';
1411
1412                         if ($level == 0 && $coff < $soff) {
1413                                 $coff = $off;
1414                                 $coff_set = 1;
1415                                 #warn "CSB: mark coff<$coff>\n";
1416                         }
1417                 }
1418                 if (($type eq '' || $type eq '{') && $c eq '{') {
1419                         $level++;
1420                         $type = '{';
1421                 }
1422                 if ($type eq '{' && $c eq '}') {
1423                         $level--;
1424                         $type = ($level != 0)? '{' : '';
1425
1426                         if ($level == 0) {
1427                                 if (substr($blk, $off + 1, 1) eq ';') {
1428                                         $off++;
1429                                 }
1430                                 last;
1431                         }
1432                 }
1433                 # Preprocessor commands end at the newline unless escaped.
1434                 if ($type eq '#' && $c eq "\n" && $p ne "\\") {
1435                         $level--;
1436                         $type = '';
1437                         $off++;
1438                         last;
1439                 }
1440                 $off++;
1441         }
1442         # We are truly at the end, so shuffle to the next line.
1443         if ($off == $len) {
1444                 $loff = $len + 1;
1445                 $line++;
1446                 $remain--;
1447         }
1448
1449         my $statement = substr($blk, $soff, $off - $soff + 1);
1450         my $condition = substr($blk, $soff, $coff - $soff + 1);
1451
1452         #warn "STATEMENT<$statement>\n";
1453         #warn "CONDITION<$condition>\n";
1454
1455         #print "coff<$coff> soff<$off> loff<$loff>\n";
1456
1457         return ($statement, $condition,
1458                         $line, $remain + 1, $off - $loff + 1, $level);
1459 }
1460
1461 sub statement_lines {
1462         my ($stmt) = @_;
1463
1464         # Strip the diff line prefixes and rip blank lines at start and end.
1465         $stmt =~ s/(^|\n)./$1/g;
1466         $stmt =~ s/^\s*//;
1467         $stmt =~ s/\s*$//;
1468
1469         my @stmt_lines = ($stmt =~ /\n/g);
1470
1471         return $#stmt_lines + 2;
1472 }
1473
1474 sub statement_rawlines {
1475         my ($stmt) = @_;
1476
1477         my @stmt_lines = ($stmt =~ /\n/g);
1478
1479         return $#stmt_lines + 2;
1480 }
1481
1482 sub statement_block_size {
1483         my ($stmt) = @_;
1484
1485         $stmt =~ s/(^|\n)./$1/g;
1486         $stmt =~ s/^\s*{//;
1487         $stmt =~ s/}\s*$//;
1488         $stmt =~ s/^\s*//;
1489         $stmt =~ s/\s*$//;
1490
1491         my @stmt_lines = ($stmt =~ /\n/g);
1492         my @stmt_statements = ($stmt =~ /;/g);
1493
1494         my $stmt_lines = $#stmt_lines + 2;
1495         my $stmt_statements = $#stmt_statements + 1;
1496
1497         if ($stmt_lines > $stmt_statements) {
1498                 return $stmt_lines;
1499         } else {
1500                 return $stmt_statements;
1501         }
1502 }
1503
1504 sub ctx_statement_full {
1505         my ($linenr, $remain, $off) = @_;
1506         my ($statement, $condition, $level);
1507
1508         my (@chunks);
1509
1510         # Grab the first conditional/block pair.
1511         ($statement, $condition, $linenr, $remain, $off, $level) =
1512                                 ctx_statement_block($linenr, $remain, $off);
1513         #print "F: c<$condition> s<$statement> remain<$remain>\n";
1514         push(@chunks, [ $condition, $statement ]);
1515         if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
1516                 return ($level, $linenr, @chunks);
1517         }
1518
1519         # Pull in the following conditional/block pairs and see if they
1520         # could continue the statement.
1521         for (;;) {
1522                 ($statement, $condition, $linenr, $remain, $off, $level) =
1523                                 ctx_statement_block($linenr, $remain, $off);
1524                 #print "C: c<$condition> s<$statement> remain<$remain>\n";
1525                 last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
1526                 #print "C: push\n";
1527                 push(@chunks, [ $condition, $statement ]);
1528         }
1529
1530         return ($level, $linenr, @chunks);
1531 }
1532
1533 sub ctx_block_get {
1534         my ($linenr, $remain, $outer, $open, $close, $off) = @_;
1535         my $line;
1536         my $start = $linenr - 1;
1537         my $blk = '';
1538         my @o;
1539         my @c;
1540         my @res = ();
1541
1542         my $level = 0;
1543         my @stack = ($level);
1544         for ($line = $start; $remain > 0; $line++) {
1545                 next if ($rawlines[$line] =~ /^-/);
1546                 $remain--;
1547
1548                 $blk .= $rawlines[$line];
1549
1550                 # Handle nested #if/#else.
1551                 if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
1552                         push(@stack, $level);
1553                 } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
1554                         $level = $stack[$#stack - 1];
1555                 } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
1556                         $level = pop(@stack);
1557                 }
1558
1559                 foreach my $c (split(//, $lines[$line])) {
1560                         ##print "C<$c>L<$level><$open$close>O<$off>\n";
1561                         if ($off > 0) {
1562                                 $off--;
1563                                 next;
1564                         }
1565
1566                         if ($c eq $close && $level > 0) {
1567                                 $level--;
1568                                 last if ($level == 0);
1569                         } elsif ($c eq $open) {
1570                                 $level++;
1571                         }
1572                 }
1573
1574                 if (!$outer || $level <= 1) {
1575                         push(@res, $rawlines[$line]);
1576                 }
1577
1578                 last if ($level == 0);
1579         }
1580
1581         return ($level, @res);
1582 }
1583 sub ctx_block_outer {
1584         my ($linenr, $remain) = @_;
1585
1586         my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
1587         return @r;
1588 }
1589 sub ctx_block {
1590         my ($linenr, $remain) = @_;
1591
1592         my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1593         return @r;
1594 }
1595 sub ctx_statement {
1596         my ($linenr, $remain, $off) = @_;
1597
1598         my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1599         return @r;
1600 }
1601 sub ctx_block_level {
1602         my ($linenr, $remain) = @_;
1603
1604         return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1605 }
1606 sub ctx_statement_level {
1607         my ($linenr, $remain, $off) = @_;
1608
1609         return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1610 }
1611
1612 sub ctx_locate_comment {
1613         my ($first_line, $end_line) = @_;
1614
1615         # Catch a comment on the end of the line itself.
1616         my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
1617         return $current_comment if (defined $current_comment);
1618
1619         # Look through the context and try and figure out if there is a
1620         # comment.
1621         my $in_comment = 0;
1622         $current_comment = '';
1623         for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
1624                 my $line = $rawlines[$linenr - 1];
1625                 #warn "           $line\n";
1626                 if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
1627                         $in_comment = 1;
1628                 }
1629                 if ($line =~ m@/\*@) {
1630                         $in_comment = 1;
1631                 }
1632                 if (!$in_comment && $current_comment ne '') {
1633                         $current_comment = '';
1634                 }
1635                 $current_comment .= $line . "\n" if ($in_comment);
1636                 if ($line =~ m@\*/@) {
1637                         $in_comment = 0;
1638                 }
1639         }
1640
1641         chomp($current_comment);
1642         return($current_comment);
1643 }
1644 sub ctx_has_comment {
1645         my ($first_line, $end_line) = @_;
1646         my $cmt = ctx_locate_comment($first_line, $end_line);
1647
1648         ##print "LINE: $rawlines[$end_line - 1 ]\n";
1649         ##print "CMMT: $cmt\n";
1650
1651         return ($cmt ne '');
1652 }
1653
1654 sub raw_line {
1655         my ($linenr, $cnt) = @_;
1656
1657         my $offset = $linenr - 1;
1658         $cnt++;
1659
1660         my $line;
1661         while ($cnt) {
1662                 $line = $rawlines[$offset++];
1663                 next if (defined($line) && $line =~ /^-/);
1664                 $cnt--;
1665         }
1666
1667         return $line;
1668 }
1669
1670 sub get_stat_real {
1671         my ($linenr, $lc) = @_;
1672
1673         my $stat_real = raw_line($linenr, 0);
1674         for (my $count = $linenr + 1; $count <= $lc; $count++) {
1675                 $stat_real = $stat_real . "\n" . raw_line($count, 0);
1676         }
1677
1678         return $stat_real;
1679 }
1680
1681 sub get_stat_here {
1682         my ($linenr, $cnt, $here) = @_;
1683
1684         my $herectx = $here . "\n";
1685         for (my $n = 0; $n < $cnt; $n++) {
1686                 $herectx .= raw_line($linenr, $n) . "\n";
1687         }
1688
1689         return $herectx;
1690 }
1691
1692 sub cat_vet {
1693         my ($vet) = @_;
1694         my ($res, $coded);
1695
1696         $res = '';
1697         while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
1698                 $res .= $1;
1699                 if ($2 ne '') {
1700                         $coded = sprintf("^%c", unpack('C', $2) + 64);
1701                         $res .= $coded;
1702                 }
1703         }
1704         $res =~ s/$/\$/;
1705
1706         return $res;
1707 }
1708
1709 my $av_preprocessor = 0;
1710 my $av_pending;
1711 my @av_paren_type;
1712 my $av_pend_colon;
1713
1714 sub annotate_reset {
1715         $av_preprocessor = 0;
1716         $av_pending = '_';
1717         @av_paren_type = ('E');
1718         $av_pend_colon = 'O';
1719 }
1720
1721 sub annotate_values {
1722         my ($stream, $type) = @_;
1723
1724         my $res;
1725         my $var = '_' x length($stream);
1726         my $cur = $stream;
1727
1728         print "$stream\n" if ($dbg_values > 1);
1729
1730         while (length($cur)) {
1731                 @av_paren_type = ('E') if ($#av_paren_type < 0);
1732                 print " <" . join('', @av_paren_type) .
1733                                 "> <$type> <$av_pending>" if ($dbg_values > 1);
1734                 if ($cur =~ /^(\s+)/o) {
1735                         print "WS($1)\n" if ($dbg_values > 1);
1736                         if ($1 =~ /\n/ && $av_preprocessor) {
1737                                 $type = pop(@av_paren_type);
1738                                 $av_preprocessor = 0;
1739                         }
1740
1741                 } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
1742                         print "CAST($1)\n" if ($dbg_values > 1);
1743                         push(@av_paren_type, $type);
1744                         $type = 'c';
1745
1746                 } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
1747                         print "DECLARE($1)\n" if ($dbg_values > 1);
1748                         $type = 'T';
1749
1750                 } elsif ($cur =~ /^($Modifier)\s*/) {
1751                         print "MODIFIER($1)\n" if ($dbg_values > 1);
1752                         $type = 'T';
1753
1754                 } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
1755                         print "DEFINE($1,$2)\n" if ($dbg_values > 1);
1756                         $av_preprocessor = 1;
1757                         push(@av_paren_type, $type);
1758                         if ($2 ne '') {
1759                                 $av_pending = 'N';
1760                         }
1761                         $type = 'E';
1762
1763                 } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
1764                         print "UNDEF($1)\n" if ($dbg_values > 1);
1765                         $av_preprocessor = 1;
1766                         push(@av_paren_type, $type);
1767
1768                 } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
1769                         print "PRE_START($1)\n" if ($dbg_values > 1);
1770                         $av_preprocessor = 1;
1771
1772                         push(@av_paren_type, $type);
1773                         push(@av_paren_type, $type);
1774                         $type = 'E';
1775
1776                 } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
1777                         print "PRE_RESTART($1)\n" if ($dbg_values > 1);
1778                         $av_preprocessor = 1;
1779
1780                         push(@av_paren_type, $av_paren_type[$#av_paren_type]);
1781
1782                         $type = 'E';
1783
1784                 } elsif ($cur =~ /^(\#\s*(?:endif))/o) {
1785                         print "PRE_END($1)\n" if ($dbg_values > 1);
1786
1787                         $av_preprocessor = 1;
1788
1789                         # Assume all arms of the conditional end as this
1790                         # one does, and continue as if the #endif was not here.
1791                         pop(@av_paren_type);
1792                         push(@av_paren_type, $type);
1793                         $type = 'E';
1794
1795                 } elsif ($cur =~ /^(\\\n)/o) {
1796                         print "PRECONT($1)\n" if ($dbg_values > 1);
1797
1798                 } elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
1799                         print "ATTR($1)\n" if ($dbg_values > 1);
1800                         $av_pending = $type;
1801                         $type = 'N';
1802
1803                 } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
1804                         print "SIZEOF($1)\n" if ($dbg_values > 1);
1805                         if (defined $2) {
1806                                 $av_pending = 'V';
1807                         }
1808                         $type = 'N';
1809
1810                 } elsif ($cur =~ /^(if|while|for)\b/o) {
1811                         print "COND($1)\n" if ($dbg_values > 1);
1812                         $av_pending = 'E';
1813                         $type = 'N';
1814
1815                 } elsif ($cur =~/^(case)/o) {
1816                         print "CASE($1)\n" if ($dbg_values > 1);
1817                         $av_pend_colon = 'C';
1818                         $type = 'N';
1819
1820                 } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
1821                         print "KEYWORD($1)\n" if ($dbg_values > 1);
1822                         $type = 'N';
1823
1824                 } elsif ($cur =~ /^(\()/o) {
1825                         print "PAREN('$1')\n" if ($dbg_values > 1);
1826                         push(@av_paren_type, $av_pending);
1827                         $av_pending = '_';
1828                         $type = 'N';
1829
1830                 } elsif ($cur =~ /^(\))/o) {
1831                         my $new_type = pop(@av_paren_type);
1832                         if ($new_type ne '_') {
1833                                 $type = $new_type;
1834                                 print "PAREN('$1') -> $type\n"
1835                                                         if ($dbg_values > 1);
1836                         } else {
1837                                 print "PAREN('$1')\n" if ($dbg_values > 1);
1838                         }
1839
1840                 } elsif ($cur =~ /^($Ident)\s*\(/o) {
1841                         print "FUNC($1)\n" if ($dbg_values > 1);
1842                         $type = 'V';
1843                         $av_pending = 'V';
1844
1845                 } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
1846                         if (defined $2 && $type eq 'C' || $type eq 'T') {
1847                                 $av_pend_colon = 'B';
1848                         } elsif ($type eq 'E') {
1849                                 $av_pend_colon = 'L';
1850                         }
1851                         print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
1852                         $type = 'V';
1853
1854                 } elsif ($cur =~ /^($Ident|$Constant)/o) {
1855                         print "IDENT($1)\n" if ($dbg_values > 1);
1856                         $type = 'V';
1857
1858                 } elsif ($cur =~ /^($Assignment)/o) {
1859                         print "ASSIGN($1)\n" if ($dbg_values > 1);
1860                         $type = 'N';
1861
1862                 } elsif ($cur =~/^(;|{|})/) {
1863                         print "END($1)\n" if ($dbg_values > 1);
1864                         $type = 'E';
1865                         $av_pend_colon = 'O';
1866
1867                 } elsif ($cur =~/^(,)/) {
1868                         print "COMMA($1)\n" if ($dbg_values > 1);
1869                         $type = 'C';
1870
1871                 } elsif ($cur =~ /^(\?)/o) {
1872                         print "QUESTION($1)\n" if ($dbg_values > 1);
1873                         $type = 'N';
1874
1875                 } elsif ($cur =~ /^(:)/o) {
1876                         print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
1877
1878                         substr($var, length($res), 1, $av_pend_colon);
1879                         if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
1880                                 $type = 'E';
1881                         } else {
1882                                 $type = 'N';
1883                         }
1884                         $av_pend_colon = 'O';
1885
1886                 } elsif ($cur =~ /^(\[)/o) {
1887                         print "CLOSE($1)\n" if ($dbg_values > 1);
1888                         $type = 'N';
1889
1890                 } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
1891                         my $variant;
1892
1893                         print "OPV($1)\n" if ($dbg_values > 1);
1894                         if ($type eq 'V') {
1895                                 $variant = 'B';
1896                         } else {
1897                                 $variant = 'U';
1898                         }
1899
1900                         substr($var, length($res), 1, $variant);
1901                         $type = 'N';
1902
1903                 } elsif ($cur =~ /^($Operators)/o) {
1904                         print "OP($1)\n" if ($dbg_values > 1);
1905                         if ($1 ne '++' && $1 ne '--') {
1906                                 $type = 'N';
1907                         }
1908
1909                 } elsif ($cur =~ /(^.)/o) {
1910                         print "C($1)\n" if ($dbg_values > 1);
1911                 }
1912                 if (defined $1) {
1913                         $cur = substr($cur, length($1));
1914                         $res .= $type x length($1);
1915                 }
1916         }
1917
1918         return ($res, $var);
1919 }
1920
1921 sub possible {
1922         my ($possible, $line) = @_;
1923         my $notPermitted = qr{(?:
1924                 ^(?:
1925                         $Modifier|
1926                         $Storage|
1927                         $Type|
1928                         DEFINE_\S+
1929                 )$|
1930                 ^(?:
1931                         goto|
1932                         return|
1933                         case|
1934                         else|
1935                         asm|__asm__|
1936                         do|
1937                         \#|
1938                         \#\#|
1939                 )(?:\s|$)|
1940                 ^(?:typedef|struct|enum)\b
1941             )}x;
1942         warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
1943         if ($possible !~ $notPermitted) {
1944                 # Check for modifiers.
1945                 $possible =~ s/\s*$Storage\s*//g;
1946                 $possible =~ s/\s*$Sparse\s*//g;
1947                 if ($possible =~ /^\s*$/) {
1948
1949                 } elsif ($possible =~ /\s/) {
1950                         $possible =~ s/\s*$Type\s*//g;
1951                         for my $modifier (split(' ', $possible)) {
1952                                 if ($modifier !~ $notPermitted) {
1953                                         warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
1954                                         push(@modifierListFile, $modifier);
1955                                 }
1956                         }
1957
1958                 } else {
1959                         warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
1960                         push(@typeListFile, $possible);
1961                 }
1962                 build_types();
1963         } else {
1964                 warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
1965         }
1966 }
1967
1968 my $prefix = '';
1969
1970 sub show_type {
1971         my ($type) = @_;
1972
1973         $type =~ tr/[a-z]/[A-Z]/;
1974
1975         return defined $use_type{$type} if (scalar keys %use_type > 0);
1976
1977         return !defined $ignore_type{$type};
1978 }
1979
1980 sub report {
1981         my ($level, $type, $msg) = @_;
1982
1983         if (!show_type($type) ||
1984             (defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
1985                 return 0;
1986         }
1987         my $output = '';
1988         if ($color) {
1989                 if ($level eq 'ERROR') {
1990                         $output .= RED;
1991                 } elsif ($level eq 'WARNING') {
1992                         $output .= YELLOW;
1993                 } else {
1994                         $output .= GREEN;
1995                 }
1996         }
1997         $output .= $prefix . $level . ':';
1998         if ($show_types) {
1999                 $output .= BLUE if ($color);
2000                 $output .= "$type:";
2001         }
2002         $output .= RESET if ($color);
2003         $output .= ' ' . $msg . "\n";
2004
2005         if ($showfile) {
2006                 my @lines = split("\n", $output, -1);
2007                 splice(@lines, 1, 1);
2008                 $output = join("\n", @lines);
2009         }
2010         $output = (split('\n', $output))[0] . "\n" if ($terse);
2011
2012         push(our @report, $output);
2013
2014         return 1;
2015 }
2016
2017 sub report_dump {
2018         our @report;
2019 }
2020
2021 sub fixup_current_range {
2022         my ($lineRef, $offset, $length) = @_;
2023
2024         if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) {
2025                 my $o = $1;
2026                 my $l = $2;
2027                 my $no = $o + $offset;
2028                 my $nl = $l + $length;
2029                 $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/;
2030         }
2031 }
2032
2033 sub fix_inserted_deleted_lines {
2034         my ($linesRef, $insertedRef, $deletedRef) = @_;
2035
2036         my $range_last_linenr = 0;
2037         my $delta_offset = 0;
2038
2039         my $old_linenr = 0;
2040         my $new_linenr = 0;
2041
2042         my $next_insert = 0;
2043         my $next_delete = 0;
2044
2045         my @lines = ();
2046
2047         my $inserted = @{$insertedRef}[$next_insert++];
2048         my $deleted = @{$deletedRef}[$next_delete++];
2049
2050         foreach my $old_line (@{$linesRef}) {
2051                 my $save_line = 1;
2052                 my $line = $old_line;   #don't modify the array
2053                 if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) {      #new filename
2054                         $delta_offset = 0;
2055                 } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) {    #new hunk
2056                         $range_last_linenr = $new_linenr;
2057                         fixup_current_range(\$line, $delta_offset, 0);
2058                 }
2059
2060                 while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) {
2061                         $deleted = @{$deletedRef}[$next_delete++];
2062                         $save_line = 0;
2063                         fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
2064                 }
2065
2066                 while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) {
2067                         push(@lines, ${$inserted}{'LINE'});
2068                         $inserted = @{$insertedRef}[$next_insert++];
2069                         $new_linenr++;
2070                         fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
2071                 }
2072
2073                 if ($save_line) {
2074                         push(@lines, $line);
2075                         $new_linenr++;
2076                 }
2077
2078                 $old_linenr++;
2079         }
2080
2081         return @lines;
2082 }
2083
2084 sub fix_insert_line {
2085         my ($linenr, $line) = @_;
2086
2087         my $inserted = {
2088                 LINENR => $linenr,
2089                 LINE => $line,
2090         };
2091         push(@fixed_inserted, $inserted);
2092 }
2093
2094 sub fix_delete_line {
2095         my ($linenr, $line) = @_;
2096
2097         my $deleted = {
2098                 LINENR => $linenr,
2099                 LINE => $line,
2100         };
2101
2102         push(@fixed_deleted, $deleted);
2103 }
2104
2105 sub ERROR {
2106         my ($type, $msg) = @_;
2107
2108         if (report("ERROR", $type, $msg)) {
2109                 our $clean = 0;
2110                 our $cnt_error++;
2111                 return 1;
2112         }
2113         return 0;
2114 }
2115 sub WARN {
2116         my ($type, $msg) = @_;
2117
2118         if (report("WARNING", $type, $msg)) {
2119                 our $clean = 0;
2120                 our $cnt_warn++;
2121                 return 1;
2122         }
2123         return 0;
2124 }
2125 sub CHK {
2126         my ($type, $msg) = @_;
2127
2128         if ($check && report("CHECK", $type, $msg)) {
2129                 our $clean = 0;
2130                 our $cnt_chk++;
2131                 return 1;
2132         }
2133         return 0;
2134 }
2135
2136 sub check_absolute_file {
2137         my ($absolute, $herecurr) = @_;
2138         my $file = $absolute;
2139
2140         ##print "absolute<$absolute>\n";
2141
2142         # See if any suffix of this path is a path within the tree.
2143         while ($file =~ s@^[^/]*/@@) {
2144                 if (-f "$root/$file") {
2145                         ##print "file<$file>\n";
2146                         last;
2147                 }
2148         }
2149         if (! -f _)  {
2150                 return 0;
2151         }
2152
2153         # It is, so see if the prefix is acceptable.
2154         my $prefix = $absolute;
2155         substr($prefix, -length($file)) = '';
2156
2157         ##print "prefix<$prefix>\n";
2158         if ($prefix ne ".../") {
2159                 WARN("USE_RELATIVE_PATH",
2160                      "use relative pathname instead of absolute in changelog text\n" . $herecurr);
2161         }
2162 }
2163
2164 sub trim {
2165         my ($string) = @_;
2166
2167         $string =~ s/^\s+|\s+$//g;
2168
2169         return $string;
2170 }
2171
2172 sub ltrim {
2173         my ($string) = @_;
2174
2175         $string =~ s/^\s+//;
2176
2177         return $string;
2178 }
2179
2180 sub rtrim {
2181         my ($string) = @_;
2182
2183         $string =~ s/\s+$//;
2184
2185         return $string;
2186 }
2187
2188 sub string_find_replace {
2189         my ($string, $find, $replace) = @_;
2190
2191         $string =~ s/$find/$replace/g;
2192
2193         return $string;
2194 }
2195
2196 sub tabify {
2197         my ($leading) = @_;
2198
2199         my $source_indent = $tab_length;
2200         my $max_spaces_before_tab = $source_indent - 1;
2201         my $spaces_to_tab = " " x $source_indent;
2202
2203         #convert leading spaces to tabs
2204         1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
2205         #Remove spaces before a tab
2206         1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g;
2207
2208         return "$leading";
2209 }
2210
2211 sub pos_last_openparen {
2212         my ($line) = @_;
2213
2214         my $pos = 0;
2215
2216         my $opens = $line =~ tr/\(/\(/;
2217         my $closes = $line =~ tr/\)/\)/;
2218
2219         my $last_openparen = 0;
2220
2221         if (($opens == 0) || ($closes >= $opens)) {
2222                 return -1;
2223         }
2224
2225         my $len = length($line);
2226
2227         for ($pos = 0; $pos < $len; $pos++) {
2228                 my $string = substr($line, $pos);
2229                 if ($string =~ /^($FuncArg|$balanced_parens)/) {
2230                         $pos += length($1) - 1;
2231                 } elsif (substr($line, $pos, 1) eq '(') {
2232                         $last_openparen = $pos;
2233                 } elsif (index($string, '(') == -1) {
2234                         last;
2235                 }
2236         }
2237
2238         return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
2239 }
2240
2241 sub process {
2242         my $filename = shift;
2243
2244         my $linenr=0;
2245         my $prevline="";
2246         my $prevrawline="";
2247         my $stashline="";
2248         my $stashrawline="";
2249
2250         my $length;
2251         my $indent;
2252         my $previndent=0;
2253         my $stashindent=0;
2254
2255         our $clean = 1;
2256         my $signoff = 0;
2257         my $is_patch = 0;
2258         my $in_header_lines = $file ? 0 : 1;
2259         my $in_commit_log = 0;          #Scanning lines before patch
2260         my $has_commit_log = 0;         #Encountered lines before patch
2261         my $commit_log_possible_stack_dump = 0;
2262         my $commit_log_long_line = 0;
2263         my $commit_log_has_diff = 0;
2264         my $reported_maintainer_file = 0;
2265         my $non_utf8_charset = 0;
2266
2267         my $last_blank_line = 0;
2268         my $last_coalesced_string_linenr = -1;
2269
2270         our @report = ();
2271         our $cnt_lines = 0;
2272         our $cnt_error = 0;
2273         our $cnt_warn = 0;
2274         our $cnt_chk = 0;
2275
2276         # Trace the real file/line as we go.
2277         my $realfile = '';
2278         my $realline = 0;
2279         my $realcnt = 0;
2280         my $here = '';
2281         my $context_function;           #undef'd unless there's a known function
2282         my $in_comment = 0;
2283         my $comment_edge = 0;
2284         my $first_line = 0;
2285         my $p1_prefix = '';
2286
2287         my $prev_values = 'E';
2288
2289         # suppression flags
2290         my %suppress_ifbraces;
2291         my %suppress_whiletrailers;
2292         my %suppress_export;
2293         my $suppress_statement = 0;
2294
2295         my %signatures = ();
2296
2297         # Pre-scan the patch sanitizing the lines.
2298         # Pre-scan the patch looking for any __setup documentation.
2299         #
2300         my @setup_docs = ();
2301         my $setup_docs = 0;
2302
2303         my $camelcase_file_seeded = 0;
2304
2305         my $checklicenseline = 1;
2306
2307         sanitise_line_reset();
2308         my $line;
2309         foreach my $rawline (@rawlines) {
2310                 $linenr++;
2311                 $line = $rawline;
2312
2313                 push(@fixed, $rawline) if ($fix);
2314
2315                 if ($rawline=~/^\+\+\+\s+(\S+)/) {
2316                         $setup_docs = 0;
2317                         if ($1 =~ m@Documentation/admin-guide/kernel-parameters.rst$@) {
2318                                 $setup_docs = 1;
2319                         }
2320                         #next;
2321                 }
2322                 if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
2323                         $realline=$1-1;
2324                         if (defined $2) {
2325                                 $realcnt=$3+1;
2326                         } else {
2327                                 $realcnt=1+1;
2328                         }
2329                         $in_comment = 0;
2330
2331                         # Guestimate if this is a continuing comment.  Run
2332                         # the context looking for a comment "edge".  If this
2333                         # edge is a close comment then we must be in a comment
2334                         # at context start.
2335                         my $edge;
2336                         my $cnt = $realcnt;
2337                         for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
2338                                 next if (defined $rawlines[$ln - 1] &&
2339                                          $rawlines[$ln - 1] =~ /^-/);
2340                                 $cnt--;
2341                                 #print "RAW<$rawlines[$ln - 1]>\n";
2342                                 last if (!defined $rawlines[$ln - 1]);
2343                                 if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
2344                                     $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
2345                                         ($edge) = $1;
2346                                         last;
2347                                 }
2348                         }
2349                         if (defined $edge && $edge eq '*/') {
2350                                 $in_comment = 1;
2351                         }
2352
2353                         # Guestimate if this is a continuing comment.  If this
2354                         # is the start of a diff block and this line starts
2355                         # ' *' then it is very likely a comment.
2356                         if (!defined $edge &&
2357                             $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
2358                         {
2359                                 $in_comment = 1;
2360                         }
2361
2362                         ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
2363                         sanitise_line_reset($in_comment);
2364
2365                 } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
2366                         # Standardise the strings and chars within the input to
2367                         # simplify matching -- only bother with positive lines.
2368                         $line = sanitise_line($rawline);
2369                 }
2370                 push(@lines, $line);
2371
2372                 if ($realcnt > 1) {
2373                         $realcnt-- if ($line =~ /^(?:\+| |$)/);
2374                 } else {
2375                         $realcnt = 0;
2376                 }
2377
2378                 #print "==>$rawline\n";
2379                 #print "-->$line\n";
2380
2381                 if ($setup_docs && $line =~ /^\+/) {
2382                         push(@setup_docs, $line);
2383                 }
2384         }
2385
2386         $prefix = '';
2387
2388         $realcnt = 0;
2389         $linenr = 0;
2390         $fixlinenr = -1;
2391         foreach my $line (@lines) {
2392                 $linenr++;
2393                 $fixlinenr++;
2394                 my $sline = $line;      #copy of $line
2395                 $sline =~ s/$;/ /g;     #with comments as spaces
2396
2397                 my $rawline = $rawlines[$linenr - 1];
2398
2399 # check if it's a mode change, rename or start of a patch
2400                 if (!$in_commit_log &&
2401                     ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ ||
2402                     ($line =~ /^rename (?:from|to) \S+\s*$/ ||
2403                      $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) {
2404                         $is_patch = 1;
2405                 }
2406
2407 #extract the line range in the file after the patch is applied
2408                 if (!$in_commit_log &&
2409                     $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
2410                         my $context = $4;
2411                         $is_patch = 1;
2412                         $first_line = $linenr + 1;
2413                         $realline=$1-1;
2414                         if (defined $2) {
2415                                 $realcnt=$3+1;
2416                         } else {
2417                                 $realcnt=1+1;
2418                         }
2419                         annotate_reset();
2420                         $prev_values = 'E';
2421
2422                         %suppress_ifbraces = ();
2423                         %suppress_whiletrailers = ();
2424                         %suppress_export = ();
2425                         $suppress_statement = 0;
2426                         if ($context =~ /\b(\w+)\s*\(/) {
2427                                 $context_function = $1;
2428                         } else {
2429                                 undef $context_function;
2430                         }
2431                         next;
2432
2433 # track the line number as we move through the hunk, note that
2434 # new versions of GNU diff omit the leading space on completely
2435 # blank context lines so we need to count that too.
2436                 } elsif ($line =~ /^( |\+|$)/) {
2437                         $realline++;
2438                         $realcnt-- if ($realcnt != 0);
2439
2440                         # Measure the line length and indent.
2441                         ($length, $indent) = line_stats($rawline);
2442
2443                         # Track the previous line.
2444                         ($prevline, $stashline) = ($stashline, $line);
2445                         ($previndent, $stashindent) = ($stashindent, $indent);
2446                         ($prevrawline, $stashrawline) = ($stashrawline, $rawline);
2447
2448                         #warn "line<$line>\n";
2449
2450                 } elsif ($realcnt == 1) {
2451                         $realcnt--;
2452                 }
2453
2454                 my $hunk_line = ($realcnt != 0);
2455
2456                 $here = "#$linenr: " if (!$file);
2457                 $here = "#$realline: " if ($file);
2458
2459                 my $found_file = 0;
2460                 # extract the filename as it passes
2461                 if ($line =~ /^diff --git.*?(\S+)$/) {
2462                         $realfile = $1;
2463                         $realfile =~ s@^([^/]*)/@@ if (!$file);
2464                         $in_commit_log = 0;
2465                         $found_file = 1;
2466                 } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
2467                         $realfile = $1;
2468                         $realfile =~ s@^([^/]*)/@@ if (!$file);
2469                         $in_commit_log = 0;
2470
2471                         $p1_prefix = $1;
2472                         if (!$file && $tree && $p1_prefix ne '' &&
2473                             -e "$root/$p1_prefix") {
2474                                 WARN("PATCH_PREFIX",
2475                                      "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
2476                         }
2477
2478                         if ($realfile =~ m@^include/asm/@) {
2479                                 ERROR("MODIFIED_INCLUDE_ASM",
2480                                       "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
2481                         }
2482                         $found_file = 1;
2483                 }
2484
2485 #make up the handle for any error we report on this line
2486                 if ($showfile) {
2487                         $prefix = "$realfile:$realline: "
2488                 } elsif ($emacs) {
2489                         if ($file) {
2490                                 $prefix = "$filename:$realline: ";
2491                         } else {
2492                                 $prefix = "$filename:$linenr: ";
2493                         }
2494                 }
2495
2496                 if ($found_file) {
2497                         if (is_maintained_obsolete($realfile)) {
2498                                 WARN("OBSOLETE",
2499                                      "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy.  No unnecessary modifications please.\n");
2500                         }
2501                         if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) {
2502                                 $check = 1;
2503                         } else {
2504                                 $check = $check_orig;
2505                         }
2506                         $checklicenseline = 1;
2507                         next;
2508                 }
2509
2510                 $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
2511
2512                 my $hereline = "$here\n$rawline\n";
2513                 my $herecurr = "$here\n$rawline\n";
2514                 my $hereprev = "$here\n$prevrawline\n$rawline\n";
2515
2516                 $cnt_lines++ if ($realcnt != 0);
2517
2518 # Check if the commit log has what seems like a diff which can confuse patch
2519                 if ($in_commit_log && !$commit_log_has_diff &&
2520                     (($line =~ m@^\s+diff\b.*a/[\w/]+@ &&
2521                       $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) ||
2522                      $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ ||
2523                      $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) {
2524                         ERROR("DIFF_IN_COMMIT_MSG",
2525                               "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr);
2526                         $commit_log_has_diff = 1;
2527                 }
2528
2529 # Check for incorrect file permissions
2530                 if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
2531                         my $permhere = $here . "FILE: $realfile\n";
2532                         if ($realfile !~ m@scripts/@ &&
2533                             $realfile !~ /\.(py|pl|awk|sh)$/) {
2534                                 ERROR("EXECUTE_PERMISSIONS",
2535                                       "do not set execute permissions for source files\n" . $permhere);
2536                         }
2537                 }
2538
2539 # Check the patch for a signoff:
2540                 if ($line =~ /^\s*signed-off-by:/i) {
2541                         $signoff++;
2542                         $in_commit_log = 0;
2543                 }
2544
2545 # Check if MAINTAINERS is being updated.  If so, there's probably no need to
2546 # emit the "does MAINTAINERS need updating?" message on file add/move/delete
2547                 if ($line =~ /^\s*MAINTAINERS\s*\|/) {
2548                         $reported_maintainer_file = 1;
2549                 }
2550
2551 # Check signature styles
2552                 if (!$in_header_lines &&
2553                     $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
2554                         my $space_before = $1;
2555                         my $sign_off = $2;
2556                         my $space_after = $3;
2557                         my $email = $4;
2558                         my $ucfirst_sign_off = ucfirst(lc($sign_off));
2559
2560                         if ($sign_off !~ /$signature_tags/) {
2561                                 WARN("BAD_SIGN_OFF",
2562                                      "Non-standard signature: $sign_off\n" . $herecurr);
2563                         }
2564                         if (defined $space_before && $space_before ne "") {
2565                                 if (WARN("BAD_SIGN_OFF",
2566                                          "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
2567                                     $fix) {
2568                                         $fixed[$fixlinenr] =
2569                                             "$ucfirst_sign_off $email";
2570                                 }
2571                         }
2572                         if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
2573                                 if (WARN("BAD_SIGN_OFF",
2574                                          "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
2575                                     $fix) {
2576                                         $fixed[$fixlinenr] =
2577                                             "$ucfirst_sign_off $email";
2578                                 }
2579
2580                         }
2581                         if (!defined $space_after || $space_after ne " ") {
2582                                 if (WARN("BAD_SIGN_OFF",
2583                                          "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
2584                                     $fix) {
2585                                         $fixed[$fixlinenr] =
2586                                             "$ucfirst_sign_off $email";
2587                                 }
2588                         }
2589
2590                         my ($email_name, $email_address, $comment) = parse_email($email);
2591                         my $suggested_email = format_email(($email_name, $email_address));
2592                         if ($suggested_email eq "") {
2593                                 ERROR("BAD_SIGN_OFF",
2594                                       "Unrecognized email address: '$email'\n" . $herecurr);
2595                         } else {
2596                                 my $dequoted = $suggested_email;
2597                                 $dequoted =~ s/^"//;
2598                                 $dequoted =~ s/" </ </;
2599                                 # Don't force email to have quotes
2600                                 # Allow just an angle bracketed address
2601                                 if ("$dequoted$comment" ne $email &&
2602                                     "<$email_address>$comment" ne $email &&
2603                                     "$suggested_email$comment" ne $email) {
2604                                         WARN("BAD_SIGN_OFF",
2605                                              "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
2606                                 }
2607                         }
2608
2609 # Check for duplicate signatures
2610                         my $sig_nospace = $line;
2611                         $sig_nospace =~ s/\s//g;
2612                         $sig_nospace = lc($sig_nospace);
2613                         if (defined $signatures{$sig_nospace}) {
2614                                 WARN("BAD_SIGN_OFF",
2615                                      "Duplicate signature\n" . $herecurr);
2616                         } else {
2617                                 $signatures{$sig_nospace} = 1;
2618                         }
2619                 }
2620
2621 # Check email subject for common tools that don't need to be mentioned
2622                 if ($in_header_lines &&
2623                     $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) {
2624                         WARN("EMAIL_SUBJECT",
2625                              "A patch subject line should describe the change not the tool that found it\n" . $herecurr);
2626                 }
2627
2628 ## Check for unwanted Gerrit info
2629 #               if ($in_commit_log && $line =~ /^\s*change-id:/i) {
2630 #                       ERROR("GERRIT_CHANGE_ID",
2631 #                             "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
2632 #               }
2633
2634 # Check if the commit log is in a possible stack dump
2635                 if ($in_commit_log && !$commit_log_possible_stack_dump &&
2636                     ($line =~ /^\s*(?:WARNING:|BUG:)/ ||
2637                      $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
2638                                         # timestamp
2639                      $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
2640                                         # stack dump address
2641                         $commit_log_possible_stack_dump = 1;
2642                 }
2643
2644 # Check for line lengths > 75 in commit log, warn once
2645                 if ($in_commit_log && !$commit_log_long_line &&
2646                     length($line) > 75 &&
2647                     !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
2648                                         # file delta changes
2649                       $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
2650                                         # filename then :
2651                       $line =~ /^\s*(?:Fixes:|Link:)/i ||
2652                                         # A Fixes: or Link: line
2653                       $commit_log_possible_stack_dump)) {
2654                         WARN("COMMIT_LOG_LONG_LINE",
2655                              "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
2656                         $commit_log_long_line = 1;
2657                 }
2658
2659 # Reset possible stack dump if a blank line is found
2660                 if ($in_commit_log && $commit_log_possible_stack_dump &&
2661                     $line =~ /^\s*$/) {
2662                         $commit_log_possible_stack_dump = 0;
2663                 }
2664
2665 # Check for git id commit length and improperly formed commit descriptions
2666                 if ($in_commit_log && !$commit_log_possible_stack_dump &&
2667                     $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i &&
2668                     $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
2669                     ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
2670                      ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
2671                       $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
2672                       $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
2673                         my $init_char = "c";
2674                         my $orig_commit = "";
2675                         my $short = 1;
2676                         my $long = 0;
2677                         my $case = 1;
2678                         my $space = 1;
2679                         my $hasdesc = 0;
2680                         my $hasparens = 0;
2681                         my $id = '0123456789ab';
2682                         my $orig_desc = "commit description";
2683                         my $description = "";
2684
2685                         if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
2686                                 $init_char = $1;
2687                                 $orig_commit = lc($2);
2688                         } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) {
2689                                 $orig_commit = lc($1);
2690                         }
2691
2692                         $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i);
2693                         $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i);
2694                         $space = 0 if ($line =~ /\bcommit [0-9a-f]/i);
2695                         $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
2696                         if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) {
2697                                 $orig_desc = $1;
2698                                 $hasparens = 1;
2699                         } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i &&
2700                                  defined $rawlines[$linenr] &&
2701                                  $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) {
2702                                 $orig_desc = $1;
2703                                 $hasparens = 1;
2704                         } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i &&
2705                                  defined $rawlines[$linenr] &&
2706                                  $rawlines[$linenr] =~ /^\s*[^"]+"\)/) {
2707                                 $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i;
2708                                 $orig_desc = $1;
2709                                 $rawlines[$linenr] =~ /^\s*([^"]+)"\)/;
2710                                 $orig_desc .= " " . $1;
2711                                 $hasparens = 1;
2712                         }
2713
2714                         ($id, $description) = git_commit_info($orig_commit,
2715                                                               $id, $orig_desc);
2716
2717                         if (defined($id) &&
2718                            ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) {
2719                                 ERROR("GIT_COMMIT_ID",
2720                                       "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr);
2721                         }
2722                 }
2723
2724 ## Check for added, moved or deleted files
2725 #               if (!$reported_maintainer_file && !$in_commit_log &&
2726 #                   ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
2727 #                    $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
2728 #                    ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
2729 #                     (defined($1) || defined($2))))) {
2730 #                       $is_patch = 1;
2731 #                       $reported_maintainer_file = 1;
2732 #                       WARN("FILE_PATH_CHANGES",
2733 #                            "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
2734 #               }
2735
2736 # Check for wrappage within a valid hunk of the file
2737                 if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
2738                         ERROR("CORRUPTED_PATCH",
2739                               "patch seems to be corrupt (line wrapped?)\n" .
2740                                 $herecurr) if (!$emitted_corrupt++);
2741                 }
2742
2743 # UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
2744                 if (($realfile =~ /^$/ || $line =~ /^\+/) &&
2745                     $rawline !~ m/^$UTF8*$/) {
2746                         my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
2747
2748                         my $blank = copy_spacing($rawline);
2749                         my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
2750                         my $hereptr = "$hereline$ptr\n";
2751
2752                         CHK("INVALID_UTF8",
2753                             "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
2754                 }
2755
2756 # Check if it's the start of a commit log
2757 # (not a header line and we haven't seen the patch filename)
2758                 if ($in_header_lines && $realfile =~ /^$/ &&
2759                     !($rawline =~ /^\s+(?:\S|$)/ ||
2760                       $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) {
2761                         $in_header_lines = 0;
2762                         $in_commit_log = 1;
2763                         $has_commit_log = 1;
2764                 }
2765
2766 # Check if there is UTF-8 in a commit log when a mail header has explicitly
2767 # declined it, i.e defined some charset where it is missing.
2768                 if ($in_header_lines &&
2769                     $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
2770                     $1 !~ /utf-8/i) {
2771                         $non_utf8_charset = 1;
2772                 }
2773
2774                 if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
2775                     $rawline =~ /$NON_ASCII_UTF8/) {
2776                         WARN("UTF8_BEFORE_PATCH",
2777                             "8-bit UTF-8 used in possible commit log\n" . $herecurr);
2778                 }
2779
2780 # Check for absolute kernel paths in commit message
2781                 if ($tree && $in_commit_log) {
2782                         while ($line =~ m{(?:^|\s)(/\S*)}g) {
2783                                 my $file = $1;
2784
2785                                 if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
2786                                     check_absolute_file($1, $herecurr)) {
2787                                         #
2788                                 } else {
2789                                         check_absolute_file($file, $herecurr);
2790                                 }
2791                         }
2792                 }
2793
2794 # Check for various typo / spelling mistakes
2795                 if (defined($misspellings) &&
2796                     ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
2797                         while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
2798                                 my $typo = $1;
2799                                 my $typo_fix = $spelling_fix{lc($typo)};
2800                                 $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
2801                                 $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
2802                                 my $msg_level = \&WARN;
2803                                 $msg_level = \&CHK if ($file);
2804                                 if (&{$msg_level}("TYPO_SPELLING",
2805                                                   "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
2806                                     $fix) {
2807                                         $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
2808                                 }
2809                         }
2810                 }
2811
2812 # ignore non-hunk lines and lines being removed
2813                 next if (!$hunk_line || $line =~ /^-/);
2814
2815 #trailing whitespace
2816                 if ($line =~ /^\+.*\015/) {
2817                         my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2818                         if (ERROR("DOS_LINE_ENDINGS",
2819                                   "DOS line endings\n" . $herevet) &&
2820                             $fix) {
2821                                 $fixed[$fixlinenr] =~ s/[\s\015]+$//;
2822                         }
2823                 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
2824                         my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2825                         if (ERROR("TRAILING_WHITESPACE",
2826                                   "trailing whitespace\n" . $herevet) &&
2827                             $fix) {
2828                                 $fixed[$fixlinenr] =~ s/\s+$//;
2829                         }
2830
2831                         $rpt_cleaners = 1;
2832                 }
2833
2834 # Check for FSF mailing addresses.
2835                 if ($rawline =~ /\bwrite to the Free/i ||
2836                     $rawline =~ /\b675\s+Mass\s+Ave/i ||
2837                     $rawline =~ /\b59\s+Temple\s+Pl/i ||
2838                     $rawline =~ /\b51\s+Franklin\s+St/i) {
2839                         my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2840                         my $msg_level = \&ERROR;
2841                         $msg_level = \&CHK if ($file);
2842                         &{$msg_level}("FSF_MAILING_ADDRESS",
2843                                       "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
2844                 }
2845
2846 # check for Kconfig help text having a real description
2847 # Only applies when adding the entry originally, after that we do not have
2848 # sufficient context to determine whether it is indeed long enough.
2849                 if ($realfile =~ /Kconfig/ &&
2850                     # 'choice' is usually the last thing on the line (though
2851                     # Kconfig supports named choices), so use a word boundary
2852                     # (\b) rather than a whitespace character (\s)
2853                     $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
2854                         my $length = 0;
2855                         my $cnt = $realcnt;
2856                         my $ln = $linenr + 1;
2857                         my $f;
2858                         my $is_start = 0;
2859                         my $is_end = 0;
2860                         for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
2861                                 $f = $lines[$ln - 1];
2862                                 $cnt-- if ($lines[$ln - 1] !~ /^-/);
2863                                 $is_end = $lines[$ln - 1] =~ /^\+/;
2864
2865                                 next if ($f =~ /^-/);
2866                                 last if (!$file && $f =~ /^\@\@/);
2867
2868                                 if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
2869                                         $is_start = 1;
2870                                 } elsif ($lines[$ln - 1] =~ /^\+\s*(?:help|---help---)\s*$/) {
2871                                         if ($lines[$ln - 1] =~ "---help---") {
2872                                                 WARN("CONFIG_DESCRIPTION",
2873                                                      "prefer 'help' over '---help---' for new help texts\n" . $herecurr);
2874                                         }
2875                                         $length = -1;
2876                                 }
2877
2878                                 $f =~ s/^.//;
2879                                 $f =~ s/#.*//;
2880                                 $f =~ s/^\s+//;
2881                                 next if ($f =~ /^$/);
2882
2883                                 # This only checks context lines in the patch
2884                                 # and so hopefully shouldn't trigger false
2885                                 # positives, even though some of these are
2886                                 # common words in help texts
2887                                 if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
2888                                                   if|endif|menu|endmenu|source)\b/x) {
2889                                         $is_end = 1;
2890                                         last;
2891                                 }
2892                                 $length++;
2893                         }
2894                         if ($is_start && $is_end && $length < $min_conf_desc_length) {
2895                                 WARN("CONFIG_DESCRIPTION",
2896                                      "please write a paragraph that describes the config symbol fully\n" . $herecurr);
2897                         }
2898                         #print "is_start<$is_start> is_end<$is_end> length<$length>\n";
2899                 }
2900
2901 # check for MAINTAINERS entries that don't have the right form
2902                 if ($realfile =~ /^MAINTAINERS$/ &&
2903                     $rawline =~ /^\+[A-Z]:/ &&
2904                     $rawline !~ /^\+[A-Z]:\t\S/) {
2905                         if (WARN("MAINTAINERS_STYLE",
2906                                  "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) &&
2907                             $fix) {
2908                                 $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
2909                         }
2910                 }
2911
2912 # discourage the use of boolean for type definition attributes of Kconfig options
2913                 if ($realfile =~ /Kconfig/ &&
2914                     $line =~ /^\+\s*\bboolean\b/) {
2915                         WARN("CONFIG_TYPE_BOOLEAN",
2916                              "Use of boolean is deprecated, please use bool instead.\n" . $herecurr);
2917                 }
2918
2919                 if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
2920                     ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
2921                         my $flag = $1;
2922                         my $replacement = {
2923                                 'EXTRA_AFLAGS' =>   'asflags-y',
2924                                 'EXTRA_CFLAGS' =>   'ccflags-y',
2925                                 'EXTRA_CPPFLAGS' => 'cppflags-y',
2926                                 'EXTRA_LDFLAGS' =>  'ldflags-y',
2927                         };
2928
2929                         WARN("DEPRECATED_VARIABLE",
2930                              "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
2931                 }
2932
2933 # check for DT compatible documentation
2934                 if (defined $root &&
2935                         (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
2936                          ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) {
2937
2938                         my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
2939
2940                         my $dt_path = $root . "/Documentation/devicetree/bindings/";
2941                         my $vp_file = $dt_path . "vendor-prefixes.txt";
2942
2943                         foreach my $compat (@compats) {
2944                                 my $compat2 = $compat;
2945                                 $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/;
2946                                 my $compat3 = $compat;
2947                                 $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/;
2948                                 `grep -Erq "$compat|$compat2|$compat3" $dt_path`;
2949                                 if ( $? >> 8 ) {
2950                                         WARN("UNDOCUMENTED_DT_STRING",
2951                                              "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
2952                                 }
2953
2954                                 next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
2955                                 my $vendor = $1;
2956                                 `grep -Eq "^$vendor\\b" $vp_file`;
2957                                 if ( $? >> 8 ) {
2958                                         WARN("UNDOCUMENTED_DT_STRING",
2959                                              "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
2960                                 }
2961                         }
2962                 }
2963
2964 ## check for using SPDX license tag at beginning of files
2965 #               if ($realline == $checklicenseline) {
2966 #                       if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
2967 #                               $checklicenseline = 2;
2968 #                       } elsif ($rawline =~ /^\+/) {
2969 #                               my $comment = "";
2970 #                               if ($realfile =~ /\.(h|s|S)$/) {
2971 #                                       $comment = '/*';
2972 #                               } elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
2973 #                                       $comment = '//';
2974 #                               } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc)$/) {
2975 #                                       $comment = '#';
2976 #                               } elsif ($realfile =~ /\.rst$/) {
2977 #                                       $comment = '..';
2978 #                               }
2979 #
2980 #                               if ($comment !~ /^$/ &&
2981 #                                   $rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
2982 #                                       WARN("SPDX_LICENSE_TAG",
2983 #                                            "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
2984 #                               }
2985 #                       }
2986 #               }
2987
2988 # check we are in a valid source file if not then ignore this hunk
2989                 next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
2990
2991 # line length limit (with some exclusions)
2992 #
2993 # There are a few types of lines that may extend beyond $max_line_length:
2994 #       logging functions like pr_info that end in a string
2995 #       lines with a single string
2996 #       #defines that are a single string
2997 #       lines with an RFC3986 like URL
2998 #
2999 # There are 3 different line length message types:
3000 # LONG_LINE_COMMENT     a comment starts before but extends beyond $max_line_length
3001 # LONG_LINE_STRING      a string starts before but extends beyond $max_line_length
3002 # LONG_LINE             all other lines longer than $max_line_length
3003 #
3004 # if LONG_LINE is ignored, the other 2 types are also ignored
3005 #
3006
3007                 if ($line =~ /^\+/ && $length > $max_line_length) {
3008                         my $msg_type = "LONG_LINE";
3009
3010                         # Check the allowed long line types first
3011
3012                         # logging functions that end in a string that starts
3013                         # before $max_line_length
3014                         if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ &&
3015                             length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3016                                 $msg_type = "";
3017
3018                         # lines with only strings (w/ possible termination)
3019                         # #defines with only strings
3020                         } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
3021                                  $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
3022                                 $msg_type = "";
3023
3024                         # More special cases
3025                         } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ ||
3026                                  $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) {
3027                                 $msg_type = "";
3028
3029                         # URL ($rawline is used in case the URL is in a comment)
3030                         } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) {
3031                                 $msg_type = "";
3032
3033                         # Otherwise set the alternate message types
3034
3035                         # a comment starts before $max_line_length
3036                         } elsif ($line =~ /($;[\s$;]*)$/ &&
3037                                  length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3038                                 $msg_type = "LONG_LINE_COMMENT"
3039
3040                         # a quoted string starts before $max_line_length
3041                         } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ &&
3042                                  length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3043                                 $msg_type = "LONG_LINE_STRING"
3044                         }
3045
3046                         if ($msg_type ne "" &&
3047                             (show_type("LONG_LINE") || show_type($msg_type))) {
3048                                 WARN($msg_type,
3049                                      "line over $max_line_length characters\n" . $herecurr);
3050                         }
3051                 }
3052
3053 # check for adding lines without a newline.
3054                 if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
3055                         WARN("MISSING_EOF_NEWLINE",
3056                              "adding a line without newline at end of file\n" . $herecurr);
3057                 }
3058
3059 # check we are in a valid source file C or perl if not then ignore this hunk
3060                 next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
3061
3062 ## at the beginning of a line any tabs must come first and anything
3063 ## more than tab_length must use tabs.
3064 #               if ($rawline =~ /^\+\s* \t\s*\S/ ||
3065 #                   $rawline =~ /^\+\s*    \s*/) {
3066 #                       my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3067 #                       $rpt_cleaners = 1;
3068 #                       if (ERROR("CODE_INDENT",
3069 #                                 "code indent should use tabs where possible\n" . $herevet) &&
3070 #                           $fix) {
3071 #                               $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
3072 #                       }
3073 #               }
3074
3075 # check for space before tabs.
3076                 if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
3077                         my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3078                         if (WARN("SPACE_BEFORE_TAB",
3079                                 "please, no space before tabs\n" . $herevet) &&
3080                             $fix) {
3081                                 while ($fixed[$fixlinenr] =~
3082                                            s/(^\+.*) {$tab_length,$tab_length}\t/$1\t\t/) {}
3083                                 while ($fixed[$fixlinenr] =~
3084                                            s/(^\+.*) +\t/$1\t/) {}
3085                         }
3086                 }
3087
3088 # check for assignments on the start of a line
3089                 if ($sline =~ /^\+\s+($Assignment)[^=]/) {
3090                         CHK("ASSIGNMENT_CONTINUATIONS",
3091                             "Assignment operator '$1' should be on the previous line\n" . $hereprev);
3092                 }
3093
3094 # check for && or || at the start of a line
3095                 if ($rawline =~ /^\+\s*(&&|\|\|)/) {
3096                         CHK("LOGICAL_CONTINUATIONS",
3097                             "Logical continuations should be on the previous line\n" . $hereprev);
3098                 }
3099
3100 # check indentation starts on a tab stop
3101                 if ($^V && $^V ge 5.10.0 &&
3102                     $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
3103                         my $indent = length($1);
3104                         if ($indent % 8) {
3105                                 if (WARN("TABSTOP",
3106                                          "Statements should start on a tabstop\n" . $herecurr) &&
3107                                     $fix) {
3108                                         $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
3109                                 }
3110                         }
3111                 }
3112
3113 # check multi-line statement indentation matches previous line
3114                 if ($^V && $^V ge 5.10.0 &&
3115                     $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
3116                         $prevline =~ /^\+(\t*)(.*)$/;
3117                         my $oldindent = $1;
3118                         my $rest = $2;
3119
3120                         my $pos = pos_last_openparen($rest);
3121                         if ($pos >= 0) {
3122                                 $line =~ /^(\+| )([ \t]*)/;
3123                                 my $newindent = $2;
3124
3125                                 my $goodtabindent = $oldindent .
3126                                         "\t" x ($pos / $tab_length) .
3127                                         " "  x ($pos % $tab_length);
3128                                 my $goodspaceindent = $oldindent . " "  x $pos;
3129
3130                                 if ($newindent ne $goodtabindent &&
3131                                     $newindent ne $goodspaceindent) {
3132
3133                                         if (CHK("PARENTHESIS_ALIGNMENT",
3134                                                 "Alignment should match open parenthesis\n" . $hereprev) &&
3135                                             $fix && $line =~ /^\+/) {
3136                                                 $fixed[$fixlinenr] =~
3137                                                     s/^\+[ \t]*/\+$goodtabindent/;
3138                                         }
3139                                 }
3140                         }
3141                 }
3142
3143 # check for space after cast like "(int) foo" or "(struct foo) bar"
3144 # avoid checking a few false positives:
3145 #   "sizeof(<type>)" or "__alignof__(<type>)"
3146 #   function pointer declarations like "(*foo)(int) = bar;"
3147 #   structure definitions like "(struct foo) { 0 };"
3148 #   multiline macros that define functions
3149 #   known attributes or the __attribute__ keyword
3150                 if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ &&
3151                     (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) {
3152                         if (CHK("SPACING",
3153                                 "No space is necessary after a cast\n" . $herecurr) &&
3154                             $fix) {
3155                                 $fixed[$fixlinenr] =~
3156                                     s/(\(\s*$Type\s*\))[ \t]+/$1/;
3157                         }
3158                 }
3159
3160 # Block comment styles
3161 # Networking with an initial /*
3162                 if ($realfile =~ m@^(driv