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