blob: c0688e6274182d151e3557f1ff435d4735ca328b [file] [log] [blame]
Anas Nashif1eb244c2017-10-01 17:06:36 -04001#!/usr/bin/env perl
Peter Bigot5b10fac2020-03-26 11:16:33 -05002# SPDX-License-Identifier: GPL-2.0
3#
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004# (c) 2001, Dave Jones. (the file handling bit)
5# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
6# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
7# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
Peter Bigot5b10fac2020-03-26 11:16:33 -05008# (c) 2010-2018 Joe Perches <joe@perches.com>
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07009
10use strict;
Anas Nashif1eb244c2017-10-01 17:06:36 -040011use warnings;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070012use POSIX;
Anas Nashifcbfb62c2015-10-14 06:08:54 -040013use File::Basename;
14use Cwd 'abs_path';
15use Term::ANSIColor qw(:constants);
Peter Bigot5b10fac2020-03-26 11:16:33 -050016use Encode qw(decode encode);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070017
18my $P = $0;
Anas Nashifcbfb62c2015-10-14 06:08:54 -040019my $D = dirname(abs_path($P));
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070020
21my $V = '0.32';
22
23use Getopt::Long qw(:config no_auto_abbrev);
24
25my $quiet = 0;
26my $tree = 1;
27my $chk_signoff = 1;
28my $chk_patch = 1;
29my $tst_only;
30my $emacs = 0;
31my $terse = 0;
Anas Nashifcbfb62c2015-10-14 06:08:54 -040032my $showfile = 0;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070033my $file = 0;
Anas Nashif0f3d5472016-11-07 15:57:57 -050034my $git = 0;
35my %git_commits = ();
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070036my $check = 0;
37my $check_orig = 0;
38my $summary = 1;
39my $mailback = 0;
40my $summary_file = 0;
41my $show_types = 0;
Anas Nashif0f3d5472016-11-07 15:57:57 -050042my $list_types = 0;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070043my $fix = 0;
44my $fix_inplace = 0;
45my $root;
46my %debug;
47my %camelcase = ();
48my %use_type = ();
49my @use = ();
50my %ignore_type = ();
51my @ignore = ();
Anas Nashif0f3d5472016-11-07 15:57:57 -050052my @exclude = ();
Anas Nashif1eb244c2017-10-01 17:06:36 -040053my $help = 0;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070054my $configuration_file = ".checkpatch.conf";
55my $max_line_length = 80;
56my $ignore_perl_version = 0;
57my $minimum_perl_version = 5.10.0;
58my $min_conf_desc_length = 4;
59my $spelling_file = "$D/spelling.txt";
Anas Nashifcbfb62c2015-10-14 06:08:54 -040060my $codespell = 0;
61my $codespellfile = "/usr/share/codespell/dictionary.txt";
Anas Nashif0f3d5472016-11-07 15:57:57 -050062my $conststructsfile = "$D/const_structs.checkpatch";
Peter A. Bigote49e3c82020-08-10 10:37:32 -050063my $typedefsfile;
Anas Nashif1eb244c2017-10-01 17:06:36 -040064my $color = "auto";
Anas Nashifda871292017-04-21 08:52:01 -040065my $allow_c99_comments = 0;
Peter Bigot5b10fac2020-03-26 11:16:33 -050066# git output parsing needs US English output, so first set backtick child process LANGUAGE
67my $git_command ='export LANGUAGE=en_US.UTF-8; git';
Peter A. Bigote49e3c82020-08-10 10:37:32 -050068my $tabsize = 8;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070069
70sub help {
71 my ($exitcode) = @_;
72
73 print << "EOM";
74Usage: $P [OPTION]... [FILE]...
75Version: $V
76
77Options:
78 -q, --quiet quiet
79 --no-tree run without a kernel tree
80 --no-signoff do not check for 'Signed-off-by' line
81 --patch treat FILE as patchfile (default)
82 --emacs emacs compile window format
83 --terse one line per report
Anas Nashifcbfb62c2015-10-14 06:08:54 -040084 --showfile emit diffed file position, not input file position
Anas Nashif0f3d5472016-11-07 15:57:57 -050085 -g, --git treat FILE as a single commit or git revision range
86 single git commit with:
87 <rev>
88 <rev>^
89 <rev>~n
90 multiple git commits with:
91 <rev1>..<rev2>
92 <rev1>...<rev2>
93 <rev>-<count>
94 git merges are ignored
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070095 -f, --file treat FILE as regular source file
96 --subjective, --strict enable more subjective tests
Anas Nashif0f3d5472016-11-07 15:57:57 -050097 --list-types list the possible message types
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -070098 --types TYPE(,TYPE2...) show only these comma separated message types
99 --ignore TYPE(,TYPE2...) ignore various comma separated message types
Håkon Øye Amundsen325e3502022-12-01 13:43:04 +0100100 --exclude DIR (--exclude DIR2...) exclude directories
Anas Nashif1eb244c2017-10-01 17:06:36 -0400101 --show-types show the specific message type in the output
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500102 --max-line-length=n set the maximum line length, (default $max_line_length)
103 if exceeded, warn on patches
104 requires --strict for use with --file
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700105 --min-conf-desc-length=n set the min description length, if shorter, warn
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500106 --tab-size=n set the number of spaces for tab (default $tabsize)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700107 --root=PATH PATH to the kernel tree root
108 --no-summary suppress the per-file summary
109 --mailback only produce a report in case of warnings/errors
110 --summary-file include the filename in summary
111 --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of
112 'values', 'possible', 'type', and 'attr' (default
113 is all off)
114 --test-only=WORD report only warnings/errors containing WORD
115 literally
116 --fix EXPERIMENTAL - may create horrible results
117 If correctable single-line errors exist, create
118 "<inputfile>.EXPERIMENTAL-checkpatch-fixes"
119 with potential errors corrected to the preferred
120 checkpatch style
121 --fix-inplace EXPERIMENTAL - may create horrible results
122 Is the same as --fix, but overwrites the input
123 file. It's your fault if there's no backup or git
124 --ignore-perl-version override checking of perl version. expect
125 runtime errors.
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400126 --codespell Use the codespell dictionary for spelling/typos
127 (default:/usr/share/codespell/dictionary.txt)
128 --codespellfile Use this codespell dictionary
Anas Nashif1eb244c2017-10-01 17:06:36 -0400129 --typedefsfile Read additional types from this file
130 --color[=WHEN] Use colors 'always', 'never', or only when output
131 is a terminal ('auto'). Default is 'auto'.
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700132 -h, --help, --version display this help and exit
133
134When FILE is - read standard input.
135EOM
136
137 exit($exitcode);
138}
139
Anas Nashif0f3d5472016-11-07 15:57:57 -0500140sub uniq {
141 my %seen;
142 return grep { !$seen{$_}++ } @_;
143}
144
145sub list_types {
146 my ($exitcode) = @_;
147
148 my $count = 0;
149
150 local $/ = undef;
151
152 open(my $script, '<', abs_path($P)) or
153 die "$P: Can't read '$P' $!\n";
154
155 my $text = <$script>;
156 close($script);
157
158 my @types = ();
Anas Nashif1eb244c2017-10-01 17:06:36 -0400159 # Also catch when type or level is passed through a variable
160 for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
Anas Nashif0f3d5472016-11-07 15:57:57 -0500161 push (@types, $_);
162 }
163 @types = sort(uniq(@types));
164 print("#\tMessage type\n\n");
165 foreach my $type (@types) {
166 print(++$count . "\t" . $type . "\n");
167 }
168
169 exit($exitcode);
170}
171
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700172my $conf = which_conf($configuration_file);
173if (-f $conf) {
174 my @conf_args;
175 open(my $conffile, '<', "$conf")
176 or warn "$P: Can't find a readable $configuration_file file $!\n";
177
178 while (<$conffile>) {
179 my $line = $_;
180
181 $line =~ s/\s*\n?$//g;
182 $line =~ s/^\s*//g;
183 $line =~ s/\s+/ /g;
184
185 next if ($line =~ m/^\s*#/);
186 next if ($line =~ m/^\s*$/);
187
188 my @words = split(" ", $line);
189 foreach my $word (@words) {
190 last if ($word =~ m/^#/);
191 push (@conf_args, $word);
192 }
193 }
194 close($conffile);
195 unshift(@ARGV, @conf_args) if @conf_args;
196}
197
Anas Nashif1eb244c2017-10-01 17:06:36 -0400198# Perl's Getopt::Long allows options to take optional arguments after a space.
199# Prevent --color by itself from consuming other arguments
200foreach (@ARGV) {
201 if ($_ eq "--color" || $_ eq "-color") {
202 $_ = "--color=$color";
203 }
204}
205
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700206GetOptions(
207 'q|quiet+' => \$quiet,
208 'tree!' => \$tree,
209 'signoff!' => \$chk_signoff,
210 'patch!' => \$chk_patch,
211 'emacs!' => \$emacs,
212 'terse!' => \$terse,
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400213 'showfile!' => \$showfile,
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700214 'f|file!' => \$file,
Anas Nashif0f3d5472016-11-07 15:57:57 -0500215 'g|git!' => \$git,
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700216 'subjective!' => \$check,
217 'strict!' => \$check,
218 'ignore=s' => \@ignore,
Anas Nashif1eb244c2017-10-01 17:06:36 -0400219 'exclude=s' => \@exclude,
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700220 'types=s' => \@use,
221 'show-types!' => \$show_types,
Anas Nashif0f3d5472016-11-07 15:57:57 -0500222 'list-types!' => \$list_types,
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700223 'max-line-length=i' => \$max_line_length,
224 'min-conf-desc-length=i' => \$min_conf_desc_length,
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500225 'tab-size=i' => \$tabsize,
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700226 'root=s' => \$root,
227 'summary!' => \$summary,
228 'mailback!' => \$mailback,
229 'summary-file!' => \$summary_file,
230 'fix!' => \$fix,
231 'fix-inplace!' => \$fix_inplace,
232 'ignore-perl-version!' => \$ignore_perl_version,
233 'debug=s' => \%debug,
234 'test-only=s' => \$tst_only,
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400235 'codespell!' => \$codespell,
236 'codespellfile=s' => \$codespellfile,
Anas Nashif1eb244c2017-10-01 17:06:36 -0400237 'typedefsfile=s' => \$typedefsfile,
238 'color=s' => \$color,
239 'no-color' => \$color, #keep old behaviors of -nocolor
240 'nocolor' => \$color, #keep old behaviors of -nocolor
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700241 'h|help' => \$help,
242 'version' => \$help
243) or help(1);
244
245help(0) if ($help);
246
Anas Nashif0f3d5472016-11-07 15:57:57 -0500247list_types(0) if ($list_types);
248
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700249$fix = 1 if ($fix_inplace);
250$check_orig = $check;
251
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500252die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
253
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700254my $exit = 0;
255
Peter Bigot5b10fac2020-03-26 11:16:33 -0500256my $perl_version_ok = 1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700257if ($^V && $^V lt $minimum_perl_version) {
Peter Bigot5b10fac2020-03-26 11:16:33 -0500258 $perl_version_ok = 0;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700259 printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
Peter Bigot5b10fac2020-03-26 11:16:33 -0500260 exit(1) if (!$ignore_perl_version);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700261}
262
Anas Nashif0f3d5472016-11-07 15:57:57 -0500263#if no filenames are given, push '-' to read patch from stdin
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700264if ($#ARGV < 0) {
Anas Nashif0f3d5472016-11-07 15:57:57 -0500265 push(@ARGV, '-');
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700266}
267
Anas Nashif1eb244c2017-10-01 17:06:36 -0400268if ($color =~ /^[01]$/) {
269 $color = !$color;
270} elsif ($color =~ /^always$/i) {
271 $color = 1;
272} elsif ($color =~ /^never$/i) {
273 $color = 0;
274} elsif ($color =~ /^auto$/i) {
275 $color = (-t STDOUT);
276} else {
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500277 die "$P: Invalid color mode: $color\n";
Anas Nashif1eb244c2017-10-01 17:06:36 -0400278}
279
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500280# skip TAB size 1 to avoid additional checks on $tabsize - 1
281die "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2);
282
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700283sub hash_save_array_words {
284 my ($hashRef, $arrayRef) = @_;
285
286 my @array = split(/,/, join(',', @$arrayRef));
287 foreach my $word (@array) {
288 $word =~ s/\s*\n?$//g;
289 $word =~ s/^\s*//g;
290 $word =~ s/\s+/ /g;
291 $word =~ tr/[a-z]/[A-Z]/;
292
293 next if ($word =~ m/^\s*#/);
294 next if ($word =~ m/^\s*$/);
295
296 $hashRef->{$word}++;
297 }
298}
299
300sub hash_show_words {
301 my ($hashRef, $prefix) = @_;
302
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400303 if (keys %$hashRef) {
304 print "\nNOTE: $prefix message types:";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700305 foreach my $word (sort keys %$hashRef) {
306 print " $word";
307 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400308 print "\n";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700309 }
310}
311
312hash_save_array_words(\%ignore_type, \@ignore);
313hash_save_array_words(\%use_type, \@use);
314
315my $dbg_values = 0;
316my $dbg_possible = 0;
317my $dbg_type = 0;
318my $dbg_attr = 0;
319for my $key (keys %debug) {
320 ## no critic
321 eval "\${dbg_$key} = '$debug{$key}';";
322 die "$@" if ($@);
323}
324
325my $rpt_cleaners = 0;
326
327if ($terse) {
328 $emacs = 1;
329 $quiet++;
330}
331
332if ($tree) {
333 if (defined $root) {
334 if (!top_of_kernel_tree($root)) {
335 die "$P: $root: --root does not point at a valid tree\n";
336 }
337 } else {
338 if (top_of_kernel_tree('.')) {
339 $root = '.';
340 } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
341 top_of_kernel_tree($1)) {
342 $root = $1;
343 }
344 }
345
346 if (!defined $root) {
347 print "Must be run from the top-level dir. of a kernel tree\n";
348 exit(2);
349 }
350}
351
352my $emitted_corrupt = 0;
353
354our $Ident = qr{
355 [A-Za-z_][A-Za-z\d_]*
356 (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
357 }x;
358our $Storage = qr{extern|static|asmlinkage};
359our $Sparse = qr{
360 __user|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700361 __force|
362 __iomem|
363 __must_check|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700364 __kprobes|
365 __ref|
Peter Bigot5b10fac2020-03-26 11:16:33 -0500366 __refconst|
367 __refdata|
Anas Nashif0f3d5472016-11-07 15:57:57 -0500368 __rcu|
369 __private
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700370 }x;
371our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
372our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
373our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)};
374our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)};
375our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit};
376
377# Notes to $Attribute:
378# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
379our $Attribute = qr{
380 const|
381 __percpu|
382 __nocast|
383 __safe|
Anas Nashif1eb244c2017-10-01 17:06:36 -0400384 __bitwise|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700385 __packed__|
386 __packed2__|
387 __naked|
388 __maybe_unused|
389 __always_unused|
390 __noreturn|
391 __used|
Yong Cong Sinecb2df02023-11-24 11:15:53 +0800392 __unused|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700393 __cold|
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400394 __pure|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700395 __noclone|
396 __deprecated|
397 __read_mostly|
Peter Bigot5b10fac2020-03-26 11:16:33 -0500398 __ro_after_init|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700399 __kprobes|
400 $InitAttribute|
401 ____cacheline_aligned|
402 ____cacheline_aligned_in_smp|
403 ____cacheline_internodealigned_in_smp|
Andrew Boiefa94ee72017-09-28 16:54:35 -0700404 __weak|
Flavio Ceoline86ec972019-12-03 13:49:54 -0800405 __syscall
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700406 }x;
407our $Modifier;
408our $Inline = qr{inline|__always_inline|noinline|__inline|__inline__};
409our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
410our $Lval = qr{$Ident(?:$Member)*};
411
412our $Int_type = qr{(?i)llu|ull|ll|lu|ul|l|u};
413our $Binary = qr{(?i)0b[01]+$Int_type?};
414our $Hex = qr{(?i)0x[0-9a-f]+$Int_type?};
415our $Int = qr{[0-9]+$Int_type?};
416our $Octal = qr{0[0-7]+$Int_type?};
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400417our $String = qr{"[X\t]*"};
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700418our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
419our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
420our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
421our $Float = qr{$Float_hex|$Float_dec|$Float_int};
422our $Constant = qr{$Float|$Binary|$Octal|$Hex|$Int};
423our $Assignment = qr{\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=};
424our $Compare = qr{<=|>=|==|!=|<|(?<!-)>};
425our $Arithmetic = qr{\+|-|\*|\/|%};
426our $Operators = qr{
427 <=|>=|==|!=|
428 =>|->|<<|>>|<|>|!|~|
429 &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
430 }x;
431
432our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
433
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400434our $BasicType;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700435our $NonptrType;
436our $NonptrTypeMisordered;
437our $NonptrTypeWithAttr;
438our $Type;
439our $TypeMisordered;
440our $Declare;
441our $DeclareMisordered;
442
443our $NON_ASCII_UTF8 = qr{
444 [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
445 | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
446 | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
447 | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
448 | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
449 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
450 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
451}x;
452
453our $UTF8 = qr{
454 [\x09\x0A\x0D\x20-\x7E] # ASCII
455 | $NON_ASCII_UTF8
456}x;
457
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400458our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t};
459our $typeOtherOSTypedefs = qr{(?x:
460 u_(?:char|short|int|long) | # bsd
461 u(?:nchar|short|int|long) # sysv
462)};
463our $typeKernelTypedefs = qr{(?x:
Kumar Gala93da8dc2020-06-02 12:38:11 -0500464 (?:__)?(?:u|s|be|le)(?:8|16|32|64)|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700465 atomic_t
466)};
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400467our $typeTypedefs = qr{(?x:
468 $typeC99Typedefs\b|
469 $typeOtherOSTypedefs\b|
470 $typeKernelTypedefs\b
471)};
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700472
Anas Nashif76b09132016-02-20 13:53:35 -0500473our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
474
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700475our $logFunctions = qr{(?x:
Anas Nashif1eb244c2017-10-01 17:06:36 -0400476 printk(?:_ratelimited|_once|_deferred_once|_deferred|)|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700477 (?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
Peter Bigot5b10fac2020-03-26 11:16:33 -0500478 TP_printk|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700479 WARN(?:_RATELIMIT|_ONCE|)|
480 panic|
481 MODULE_[A-Z_]+|
482 seq_vprintf|seq_printf|seq_puts
483)};
484
Peter Bigot5b10fac2020-03-26 11:16:33 -0500485our $allocFunctions = qr{(?x:
486 (?:(?:devm_)?
487 (?:kv|k|v)[czm]alloc(?:_node|_array)? |
488 kstrdup(?:_const)? |
489 kmemdup(?:_nul)?) |
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500490 (?:\w+)?alloc_skb(?:_ip_align)? |
Peter Bigot5b10fac2020-03-26 11:16:33 -0500491 # dev_alloc_skb/netdev_alloc_skb, et al
492 dma_alloc_coherent
493)};
494
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700495our $signature_tags = qr{(?xi:
496 Signed-off-by:|
Bartosz Bilasfc88ddf2022-04-19 21:20:49 +0200497 Co-authored-by:|
Peter Bigot5b10fac2020-03-26 11:16:33 -0500498 Co-developed-by:|
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700499 Acked-by:|
500 Tested-by:|
501 Reviewed-by:|
502 Reported-by:|
503 Suggested-by:|
504 To:|
505 Cc:
506)};
507
508our @typeListMisordered = (
509 qr{char\s+(?:un)?signed},
510 qr{int\s+(?:(?:un)?signed\s+)?short\s},
511 qr{int\s+short(?:\s+(?:un)?signed)},
512 qr{short\s+int(?:\s+(?:un)?signed)},
513 qr{(?:un)?signed\s+int\s+short},
514 qr{short\s+(?:un)?signed},
515 qr{long\s+int\s+(?:un)?signed},
516 qr{int\s+long\s+(?:un)?signed},
517 qr{long\s+(?:un)?signed\s+int},
518 qr{int\s+(?:un)?signed\s+long},
519 qr{int\s+(?:un)?signed},
520 qr{int\s+long\s+long\s+(?:un)?signed},
521 qr{long\s+long\s+int\s+(?:un)?signed},
522 qr{long\s+long\s+(?:un)?signed\s+int},
523 qr{long\s+long\s+(?:un)?signed},
524 qr{long\s+(?:un)?signed},
525);
526
527our @typeList = (
528 qr{void},
529 qr{(?:(?:un)?signed\s+)?char},
530 qr{(?:(?:un)?signed\s+)?short\s+int},
531 qr{(?:(?:un)?signed\s+)?short},
532 qr{(?:(?:un)?signed\s+)?int},
533 qr{(?:(?:un)?signed\s+)?long\s+int},
534 qr{(?:(?:un)?signed\s+)?long\s+long\s+int},
535 qr{(?:(?:un)?signed\s+)?long\s+long},
536 qr{(?:(?:un)?signed\s+)?long},
537 qr{(?:un)?signed},
538 qr{float},
539 qr{double},
540 qr{bool},
541 qr{struct\s+$Ident},
542 qr{union\s+$Ident},
543 qr{enum\s+$Ident},
544 qr{${Ident}_t},
545 qr{${Ident}_handler},
546 qr{${Ident}_handler_fn},
547 @typeListMisordered,
548);
Anas Nashif76b09132016-02-20 13:53:35 -0500549
550our $C90_int_types = qr{(?x:
551 long\s+long\s+int\s+(?:un)?signed|
552 long\s+long\s+(?:un)?signed\s+int|
553 long\s+long\s+(?:un)?signed|
554 (?:(?:un)?signed\s+)?long\s+long\s+int|
555 (?:(?:un)?signed\s+)?long\s+long|
556 int\s+long\s+long\s+(?:un)?signed|
557 int\s+(?:(?:un)?signed\s+)?long\s+long|
558
559 long\s+int\s+(?:un)?signed|
560 long\s+(?:un)?signed\s+int|
561 long\s+(?:un)?signed|
562 (?:(?:un)?signed\s+)?long\s+int|
563 (?:(?:un)?signed\s+)?long|
564 int\s+long\s+(?:un)?signed|
565 int\s+(?:(?:un)?signed\s+)?long|
566
567 int\s+(?:un)?signed|
568 (?:(?:un)?signed\s+)?int
569)};
570
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400571our @typeListFile = ();
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700572our @typeListWithAttr = (
573 @typeList,
574 qr{struct\s+$InitAttribute\s+$Ident},
575 qr{union\s+$InitAttribute\s+$Ident},
576);
577
578our @modifierList = (
579 qr{fastcall},
580);
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400581our @modifierListFile = ();
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700582
583our @mode_permission_funcs = (
584 ["module_param", 3],
585 ["module_param_(?:array|named|string)", 4],
586 ["module_param_array_named", 5],
587 ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
588 ["proc_create(?:_data|)", 2],
Anas Nashif0f3d5472016-11-07 15:57:57 -0500589 ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
590 ["IIO_DEV_ATTR_[A-Z_]+", 1],
591 ["SENSOR_(?:DEVICE_|)ATTR_2", 2],
592 ["SENSOR_TEMPLATE(?:_2|)", 3],
593 ["__ATTR", 2],
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700594);
595
Keith Packardb021dec2023-07-17 14:45:26 -0700596our $api_defines = qr{(?x:
597 _ATFILE_SOURCE|
598 _BSD_SOURCE|
Keith Packard3d94c832023-07-18 14:55:41 -0700599 _DEFAULT_SOURCE|
Keith Packardb021dec2023-07-17 14:45:26 -0700600 _GNU_SOURCE|
601 _ISOC11_SOURCE|
602 _ISOC99_SOURCE|
Keith Packardb021dec2023-07-17 14:45:26 -0700603 _POSIX_SOURCE|
604 _SVID_SOURCE|
Keith Packard3d94c832023-07-18 14:55:41 -0700605 _XOPEN_SOURCE_EXTENDED
Keith Packardb021dec2023-07-17 14:45:26 -0700606)};
607
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500608my $word_pattern = '\b[A-Z]?[a-z]{2,}\b';
609
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700610#Create a search pattern for all these functions to speed up a loop below
611our $mode_perms_search = "";
612foreach my $entry (@mode_permission_funcs) {
613 $mode_perms_search .= '|' if ($mode_perms_search ne "");
614 $mode_perms_search .= $entry->[0];
615}
Peter Bigot5b10fac2020-03-26 11:16:33 -0500616$mode_perms_search = "(?:${mode_perms_search})";
617
618our %deprecated_apis = (
619 "synchronize_rcu_bh" => "synchronize_rcu",
620 "synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited",
621 "call_rcu_bh" => "call_rcu",
622 "rcu_barrier_bh" => "rcu_barrier",
623 "synchronize_sched" => "synchronize_rcu",
624 "synchronize_sched_expedited" => "synchronize_rcu_expedited",
625 "call_rcu_sched" => "call_rcu",
626 "rcu_barrier_sched" => "rcu_barrier",
627 "get_state_synchronize_sched" => "get_state_synchronize_rcu",
628 "cond_synchronize_sched" => "cond_synchronize_rcu",
629);
630
631#Create a search pattern for all these strings to speed up a loop below
632our $deprecated_apis_search = "";
633foreach my $entry (keys %deprecated_apis) {
634 $deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
635 $deprecated_apis_search .= $entry;
636}
637$deprecated_apis_search = "(?:${deprecated_apis_search})";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700638
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400639our $mode_perms_world_writable = qr{
640 S_IWUGO |
641 S_IWOTH |
642 S_IRWXUGO |
643 S_IALLUGO |
644 0[0-7][0-7][2367]
645}x;
646
Anas Nashif0f3d5472016-11-07 15:57:57 -0500647our %mode_permission_string_types = (
648 "S_IRWXU" => 0700,
649 "S_IRUSR" => 0400,
650 "S_IWUSR" => 0200,
651 "S_IXUSR" => 0100,
652 "S_IRWXG" => 0070,
653 "S_IRGRP" => 0040,
654 "S_IWGRP" => 0020,
655 "S_IXGRP" => 0010,
656 "S_IRWXO" => 0007,
657 "S_IROTH" => 0004,
658 "S_IWOTH" => 0002,
659 "S_IXOTH" => 0001,
660 "S_IRWXUGO" => 0777,
661 "S_IRUGO" => 0444,
662 "S_IWUGO" => 0222,
663 "S_IXUGO" => 0111,
664);
665
666#Create a search pattern for all these strings to speed up a loop below
667our $mode_perms_string_search = "";
668foreach my $entry (keys %mode_permission_string_types) {
669 $mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
670 $mode_perms_string_search .= $entry;
671}
Peter Bigot5b10fac2020-03-26 11:16:33 -0500672our $single_mode_perms_string_search = "(?:${mode_perms_string_search})";
673our $multi_mode_perms_string_search = qr{
674 ${single_mode_perms_string_search}
675 (?:\s*\|\s*${single_mode_perms_string_search})*
676}x;
677
678sub perms_to_octal {
679 my ($string) = @_;
680
681 return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/);
682
683 my $val = "";
684 my $oval = "";
685 my $to = 0;
686 my $curpos = 0;
687 my $lastpos = 0;
688 while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
689 $curpos = pos($string);
690 my $match = $2;
691 my $omatch = $1;
692 last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
693 $lastpos = $curpos;
694 $to |= $mode_permission_string_types{$match};
695 $val .= '\s*\|\s*' if ($val ne "");
696 $val .= $match;
697 $oval .= $omatch;
698 }
699 $oval =~ s/^\s*\|\s*//;
700 $oval =~ s/\s*\|\s*$//;
701 return sprintf("%04o", $to);
702}
Anas Nashif0f3d5472016-11-07 15:57:57 -0500703
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700704our $allowed_asm_includes = qr{(?x:
705 irq|
706 memory|
707 time|
708 reboot
709)};
710# memory.h: ARM has a custom one
711
712# Load common spelling mistakes and build regular expression list.
713my $misspellings;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700714my %spelling_fix;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700715
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400716if (open(my $spelling, '<', $spelling_file)) {
717 while (<$spelling>) {
718 my $line = $_;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700719
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400720 $line =~ s/\s*\n?$//g;
721 $line =~ s/^\s*//g;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700722
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400723 next if ($line =~ m/^\s*#/);
724 next if ($line =~ m/^\s*$/);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700725
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400726 my ($suspect, $fix) = split(/\|\|/, $line);
727
728 $spelling_fix{$suspect} = $fix;
729 }
730 close($spelling);
731} else {
732 warn "No typos will be found - file '$spelling_file': $!\n";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700733}
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400734
735if ($codespell) {
736 if (open(my $spelling, '<', $codespellfile)) {
737 while (<$spelling>) {
738 my $line = $_;
739
740 $line =~ s/\s*\n?$//g;
741 $line =~ s/^\s*//g;
742
743 next if ($line =~ m/^\s*#/);
744 next if ($line =~ m/^\s*$/);
745 next if ($line =~ m/, disabled/i);
746
747 $line =~ s/,.*$//;
748
749 my ($suspect, $fix) = split(/->/, $line);
750
751 $spelling_fix{$suspect} = $fix;
752 }
753 close($spelling);
754 } else {
755 warn "No codespell typos will be found - file '$codespellfile': $!\n";
756 }
757}
758
759$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700760
Anas Nashif1eb244c2017-10-01 17:06:36 -0400761sub read_words {
762 my ($wordsRef, $file) = @_;
Anas Nashif0f3d5472016-11-07 15:57:57 -0500763
Anas Nashif1eb244c2017-10-01 17:06:36 -0400764 if (open(my $words, '<', $file)) {
765 while (<$words>) {
766 my $line = $_;
Anas Nashif0f3d5472016-11-07 15:57:57 -0500767
Anas Nashif1eb244c2017-10-01 17:06:36 -0400768 $line =~ s/\s*\n?$//g;
769 $line =~ s/^\s*//g;
770
771 next if ($line =~ m/^\s*#/);
772 next if ($line =~ m/^\s*$/);
773 if ($line =~ /\s/) {
774 print("$file: '$line' invalid - ignored\n");
775 next;
776 }
777
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500778 $$wordsRef .= '|' if (defined $$wordsRef);
Anas Nashif1eb244c2017-10-01 17:06:36 -0400779 $$wordsRef .= $line;
Anas Nashif0f3d5472016-11-07 15:57:57 -0500780 }
Anas Nashif1eb244c2017-10-01 17:06:36 -0400781 close($file);
782 return 1;
Anas Nashif0f3d5472016-11-07 15:57:57 -0500783 }
Anas Nashif1eb244c2017-10-01 17:06:36 -0400784
785 return 0;
Anas Nashif0f3d5472016-11-07 15:57:57 -0500786}
787
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500788my $const_structs;
789#if (show_type("CONST_STRUCT")) {
790# read_words(\$const_structs, $conststructsfile)
791# or warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
792#}
Anas Nashif1eb244c2017-10-01 17:06:36 -0400793
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500794if (defined($typedefsfile)) {
795 my $typeOtherTypedefs;
Anas Nashif1eb244c2017-10-01 17:06:36 -0400796 read_words(\$typeOtherTypedefs, $typedefsfile)
797 or warn "No additional types will be considered - file '$typedefsfile': $!\n";
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500798 $typeTypedefs .= '|' . $typeOtherTypedefs if (defined $typeOtherTypedefs);
Anas Nashif1eb244c2017-10-01 17:06:36 -0400799}
Anas Nashif1eb244c2017-10-01 17:06:36 -0400800
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700801sub build_types {
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400802 my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)";
803 my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700804 my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)";
805 my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)";
806 $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400807 $BasicType = qr{
808 (?:$typeTypedefs\b)|
809 (?:${all}\b)
810 }x;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700811 $NonptrType = qr{
812 (?:$Modifier\s+|const\s+)*
813 (?:
814 (?:typeof|__typeof__)\s*\([^\)]*\)|
815 (?:$typeTypedefs\b)|
816 (?:${all}\b)
817 )
818 (?:\s+$Modifier|\s+const)*
819 }x;
820 $NonptrTypeMisordered = qr{
821 (?:$Modifier\s+|const\s+)*
822 (?:
823 (?:${Misordered}\b)
824 )
825 (?:\s+$Modifier|\s+const)*
826 }x;
827 $NonptrTypeWithAttr = qr{
828 (?:$Modifier\s+|const\s+)*
829 (?:
830 (?:typeof|__typeof__)\s*\([^\)]*\)|
831 (?:$typeTypedefs\b)|
832 (?:${allWithAttr}\b)
833 )
834 (?:\s+$Modifier|\s+const)*
835 }x;
836 $Type = qr{
837 $NonptrType
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500838 (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700839 (?:\s+$Inline|\s+$Modifier)*
840 }x;
841 $TypeMisordered = qr{
842 $NonptrTypeMisordered
Peter A. Bigote49e3c82020-08-10 10:37:32 -0500843 (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700844 (?:\s+$Inline|\s+$Modifier)*
845 }x;
846 $Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
847 $DeclareMisordered = qr{(?:$Storage\s+(?:$Inline\s+)?)?$TypeMisordered};
848}
849build_types();
850
851our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*};
852
853# Using $balanced_parens, $LvalOrFunc, or $FuncArg
854# requires at least perl version v5.10.0
855# Any use must be runtime checked with $^V
856
857our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;
858our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400859our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700860
861our $declaration_macros = qr{(?x:
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400862 (?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
Anas Nashif1eb244c2017-10-01 17:06:36 -0400863 (?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
Peter Bigot5b10fac2020-03-26 11:16:33 -0500864 (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700865)};
866
867sub deparenthesize {
868 my ($string) = @_;
869 return "" if (!defined($string));
870
871 while ($string =~ /^\s*\(.*\)\s*$/) {
872 $string =~ s@^\s*\(\s*@@;
873 $string =~ s@\s*\)\s*$@@;
874 }
875
876 $string =~ s@\s+@ @g;
877
878 return $string;
879}
880
881sub seed_camelcase_file {
882 my ($file) = @_;
883
884 return if (!(-f $file));
885
886 local $/;
887
888 open(my $include_file, '<', "$file")
889 or warn "$P: Can't read '$file' $!\n";
890 my $text = <$include_file>;
891 close($include_file);
892
893 my @lines = split('\n', $text);
894
895 foreach my $line (@lines) {
896 next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/);
897 if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) {
898 $camelcase{$1} = 1;
899 } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) {
900 $camelcase{$1} = 1;
901 } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) {
902 $camelcase{$1} = 1;
903 }
904 }
905}
906
Peter Bigot5b10fac2020-03-26 11:16:33 -0500907our %maintained_status = ();
908
Anas Nashif1eb244c2017-10-01 17:06:36 -0400909sub is_maintained_obsolete {
910 my ($filename) = @_;
911
912 return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
913
Peter Bigot5b10fac2020-03-26 11:16:33 -0500914 if (!exists($maintained_status{$filename})) {
915 $maintained_status{$filename} = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
916 }
Anas Nashif1eb244c2017-10-01 17:06:36 -0400917
Peter Bigot5b10fac2020-03-26 11:16:33 -0500918 return $maintained_status{$filename} =~ /obsolete/i;
919}
920
921sub is_SPDX_License_valid {
922 my ($license) = @_;
923
924 return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$root/.git"));
925
926 my $root_path = abs_path($root);
927 my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
928 return 0 if ($status ne "");
929 return 1;
Anas Nashif1eb244c2017-10-01 17:06:36 -0400930}
931
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700932my $camelcase_seeded = 0;
933sub seed_camelcase_includes {
934 return if ($camelcase_seeded);
935
936 my $files;
937 my $camelcase_cache = "";
938 my @include_files = ();
939
940 $camelcase_seeded = 1;
941
942 if (-e ".git") {
Peter Bigot5b10fac2020-03-26 11:16:33 -0500943 my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700944 chomp $git_last_include_commit;
945 $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
946 } else {
947 my $last_mod_date = 0;
948 $files = `find $root/include -name "*.h"`;
949 @include_files = split('\n', $files);
950 foreach my $file (@include_files) {
951 my $date = POSIX::strftime("%Y%m%d%H%M",
952 localtime((stat $file)[9]));
953 $last_mod_date = $date if ($last_mod_date < $date);
954 }
955 $camelcase_cache = ".checkpatch-camelcase.date.$last_mod_date";
956 }
957
958 if ($camelcase_cache ne "" && -f $camelcase_cache) {
959 open(my $camelcase_file, '<', "$camelcase_cache")
960 or warn "$P: Can't read '$camelcase_cache' $!\n";
961 while (<$camelcase_file>) {
962 chomp;
963 $camelcase{$_} = 1;
964 }
965 close($camelcase_file);
966
967 return;
968 }
969
970 if (-e ".git") {
Peter Bigot5b10fac2020-03-26 11:16:33 -0500971 $files = `${git_command} ls-files "include/*.h"`;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700972 @include_files = split('\n', $files);
973 }
974
975 foreach my $file (@include_files) {
976 seed_camelcase_file($file);
977 }
978
979 if ($camelcase_cache ne "") {
980 unlink glob ".checkpatch-camelcase.*";
981 open(my $camelcase_file, '>', "$camelcase_cache")
982 or warn "$P: Can't write '$camelcase_cache' $!\n";
983 foreach (sort { lc($a) cmp lc($b) } keys(%camelcase)) {
984 print $camelcase_file ("$_\n");
985 }
986 close($camelcase_file);
987 }
988}
989
990sub git_commit_info {
991 my ($commit, $id, $desc) = @_;
992
993 return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
994
Peter Bigot5b10fac2020-03-26 11:16:33 -0500995 my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -0700996 $output =~ s/^\s*//gm;
997 my @lines = split("\n", $output);
998
Anas Nashifcbfb62c2015-10-14 06:08:54 -0400999 return ($id, $desc) if ($#lines < 0);
1000
Peter Bigot5b10fac2020-03-26 11:16:33 -05001001 if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001002# Maybe one day convert this block of bash into something that returns
1003# all matching commit ids, but it's very slow...
1004#
1005# echo "checking commits $1..."
1006# git rev-list --remotes | grep -i "^$1" |
1007# while read line ; do
1008# git log --format='%H %s' -1 $line |
1009# echo "commit $(cut -c 1-12,41-)"
1010# done
1011 } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04001012 $id = undef;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001013 } else {
1014 $id = substr($lines[0], 0, 12);
1015 $desc = substr($lines[0], 41);
1016 }
1017
1018 return ($id, $desc);
1019}
1020
1021$chk_signoff = 0 if ($file);
1022
1023my @rawlines = ();
1024my @lines = ();
1025my @fixed = ();
1026my @fixed_inserted = ();
1027my @fixed_deleted = ();
1028my $fixlinenr = -1;
1029
Anas Nashif0f3d5472016-11-07 15:57:57 -05001030# If input is git commits, extract all commits from the commit expressions.
1031# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
1032die "$P: No git repository found\n" if ($git && !-e ".git");
1033
1034if ($git) {
1035 my @commits = ();
1036 foreach my $commit_expr (@ARGV) {
1037 my $git_range;
1038 if ($commit_expr =~ m/^(.*)-(\d+)$/) {
1039 $git_range = "-$2 $1";
1040 } elsif ($commit_expr =~ m/\.\./) {
1041 $git_range = "$commit_expr";
1042 } else {
1043 $git_range = "-1 $commit_expr";
1044 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05001045 my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
Anas Nashif0f3d5472016-11-07 15:57:57 -05001046 foreach my $line (split(/\n/, $lines)) {
1047 $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
1048 next if (!defined($1) || !defined($2));
1049 my $sha1 = $1;
1050 my $subject = $2;
1051 unshift(@commits, $sha1);
1052 $git_commits{$sha1} = $subject;
1053 }
1054 }
1055 die "$P: no git commits after extraction!\n" if (@commits == 0);
1056 @ARGV = @commits;
1057}
1058
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001059my $vname;
Peter Bigot5b10fac2020-03-26 11:16:33 -05001060$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001061for my $filename (@ARGV) {
1062 my $FILE;
Anas Nashif0f3d5472016-11-07 15:57:57 -05001063 if ($git) {
1064 open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
1065 die "$P: $filename: git format-patch failed - $!\n";
1066 } elsif ($file) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001067 open($FILE, '-|', "diff -u /dev/null $filename") ||
1068 die "$P: $filename: diff failed - $!\n";
1069 } elsif ($filename eq '-') {
1070 open($FILE, '<&STDIN');
1071 } else {
1072 open($FILE, '<', "$filename") ||
1073 die "$P: $filename: open failed - $!\n";
1074 }
1075 if ($filename eq '-') {
1076 $vname = 'Your patch';
Anas Nashif0f3d5472016-11-07 15:57:57 -05001077 } elsif ($git) {
1078 $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001079 } else {
1080 $vname = $filename;
1081 }
1082 while (<$FILE>) {
1083 chomp;
1084 push(@rawlines, $_);
Peter A. Bigote49e3c82020-08-10 10:37:32 -05001085 $vname = qq("$1") if ($filename eq '-' && $_ =~ m/^Subject:\s+(.+)/i);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001086 }
1087 close($FILE);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04001088
1089 if ($#ARGV > 0 && $quiet == 0) {
1090 print '-' x length($vname) . "\n";
1091 print "$vname\n";
1092 print '-' x length($vname) . "\n";
1093 }
1094
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001095 if (!process($filename)) {
1096 $exit = 1;
1097 }
1098 @rawlines = ();
1099 @lines = ();
1100 @fixed = ();
1101 @fixed_inserted = ();
1102 @fixed_deleted = ();
1103 $fixlinenr = -1;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04001104 @modifierListFile = ();
1105 @typeListFile = ();
1106 build_types();
1107}
1108
1109if (!$quiet) {
1110 hash_show_words(\%use_type, "Used");
1111 hash_show_words(\%ignore_type, "Ignored");
1112
Peter Bigot5b10fac2020-03-26 11:16:33 -05001113 if (!$perl_version_ok) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04001114 print << "EOM"
1115
1116NOTE: perl $^V is not modern enough to detect all possible issues.
Peter Bigot5b10fac2020-03-26 11:16:33 -05001117 An upgrade to at least perl $minimum_perl_version is suggested.
Anas Nashifcbfb62c2015-10-14 06:08:54 -04001118EOM
1119 }
1120 if ($exit) {
1121 print << "EOM"
1122
1123NOTE: If any of the errors are false positives, please report
Anas Nashif1eb244c2017-10-01 17:06:36 -04001124 them to the maintainers.
Anas Nashifcbfb62c2015-10-14 06:08:54 -04001125EOM
1126 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001127}
1128
1129exit($exit);
1130
1131sub top_of_kernel_tree {
1132 my ($root) = @_;
1133
1134 my @tree_check = (
Gerard Marull-Paretas681262d2021-03-17 16:55:50 +01001135 "LICENSE", "CODEOWNERS", "Kconfig", "README.rst",
1136 "doc", "arch", "include", "drivers", "boards",
1137 "kernel", "lib", "scripts",
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001138 );
1139
1140 foreach my $check (@tree_check) {
1141 if (! -e $root . '/' . $check) {
1142 return 0;
1143 }
1144 }
1145 return 1;
1146}
1147
1148sub parse_email {
1149 my ($formatted_email) = @_;
1150
1151 my $name = "";
1152 my $address = "";
1153 my $comment = "";
1154
1155 if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) {
1156 $name = $1;
1157 $address = $2;
1158 $comment = $3 if defined $3;
1159 } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) {
1160 $address = $1;
1161 $comment = $2 if defined $2;
1162 } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
1163 $address = $1;
1164 $comment = $2 if defined $2;
Peter Bigot5b10fac2020-03-26 11:16:33 -05001165 $formatted_email =~ s/\Q$address\E.*$//;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001166 $name = $formatted_email;
1167 $name = trim($name);
1168 $name =~ s/^\"|\"$//g;
1169 # If there's a name left after stripping spaces and
1170 # leading quotes, and the address doesn't have both
1171 # leading and trailing angle brackets, the address
1172 # is invalid. ie:
1173 # "joe smith joe@smith.com" bad
1174 # "joe smith <joe@smith.com" bad
1175 if ($name ne "" && $address !~ /^<[^>]+>$/) {
1176 $name = "";
1177 $address = "";
1178 $comment = "";
1179 }
1180 }
1181
1182 $name = trim($name);
1183 $name =~ s/^\"|\"$//g;
1184 $address = trim($address);
1185 $address =~ s/^\<|\>$//g;
1186
1187 if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
1188 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
1189 $name = "\"$name\"";
1190 }
1191
1192 return ($name, $address, $comment);
1193}
1194
1195sub format_email {
1196 my ($name, $address) = @_;
1197
1198 my $formatted_email;
1199
1200 $name = trim($name);
1201 $name =~ s/^\"|\"$//g;
1202 $address = trim($address);
1203
1204 if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
1205 $name =~ s/(?<!\\)"/\\"/g; ##escape quotes
1206 $name = "\"$name\"";
1207 }
1208
1209 if ("$name" eq "") {
1210 $formatted_email = "$address";
1211 } else {
1212 $formatted_email = "$name <$address>";
1213 }
1214
1215 return $formatted_email;
1216}
1217
1218sub which {
1219 my ($bin) = @_;
1220
1221 foreach my $path (split(/:/, $ENV{PATH})) {
1222 if (-e "$path/$bin") {
1223 return "$path/$bin";
1224 }
1225 }
1226
1227 return "";
1228}
1229
1230sub which_conf {
1231 my ($conf) = @_;
1232
1233 foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
1234 if (-e "$path/$conf") {
1235 return "$path/$conf";
1236 }
1237 }
1238
1239 return "";
1240}
1241
1242sub expand_tabs {
1243 my ($str) = @_;
1244
1245 my $res = '';
1246 my $n = 0;
1247 for my $c (split(//, $str)) {
1248 if ($c eq "\t") {
1249 $res .= ' ';
1250 $n++;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05001251 for (; ($n % $tabsize) != 0; $n++) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001252 $res .= ' ';
1253 }
1254 next;
1255 }
1256 $res .= $c;
1257 $n++;
1258 }
1259
1260 return $res;
1261}
1262sub copy_spacing {
1263 (my $res = shift) =~ tr/\t/ /c;
1264 return $res;
1265}
1266
1267sub line_stats {
1268 my ($line) = @_;
1269
1270 # Drop the diff line leader and expand tabs
1271 $line =~ s/^.//;
1272 $line = expand_tabs($line);
1273
1274 # Pick the indent from the front of the line.
1275 my ($white) = ($line =~ /^(\s*)/);
1276
1277 return (length($line), length($white));
1278}
1279
1280my $sanitise_quote = '';
1281
1282sub sanitise_line_reset {
1283 my ($in_comment) = @_;
1284
1285 if ($in_comment) {
1286 $sanitise_quote = '*/';
1287 } else {
1288 $sanitise_quote = '';
1289 }
1290}
1291sub sanitise_line {
1292 my ($line) = @_;
1293
1294 my $res = '';
1295 my $l = '';
1296
1297 my $qlen = 0;
1298 my $off = 0;
1299 my $c;
1300
1301 # Always copy over the diff marker.
1302 $res = substr($line, 0, 1);
1303
1304 for ($off = 1; $off < length($line); $off++) {
1305 $c = substr($line, $off, 1);
1306
Peter Bigot5b10fac2020-03-26 11:16:33 -05001307 # Comments we are whacking completely including the begin
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001308 # and end, all to $;.
1309 if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
1310 $sanitise_quote = '*/';
1311
1312 substr($res, $off, 2, "$;$;");
1313 $off++;
1314 next;
1315 }
1316 if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
1317 $sanitise_quote = '';
1318 substr($res, $off, 2, "$;$;");
1319 $off++;
1320 next;
1321 }
1322 if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
1323 $sanitise_quote = '//';
1324
1325 substr($res, $off, 2, $sanitise_quote);
1326 $off++;
1327 next;
1328 }
1329
1330 # A \ in a string means ignore the next character.
1331 if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
1332 $c eq "\\") {
1333 substr($res, $off, 2, 'XX');
1334 $off++;
1335 next;
1336 }
1337 # Regular quotes.
1338 if ($c eq "'" || $c eq '"') {
1339 if ($sanitise_quote eq '') {
1340 $sanitise_quote = $c;
1341
1342 substr($res, $off, 1, $c);
1343 next;
1344 } elsif ($sanitise_quote eq $c) {
1345 $sanitise_quote = '';
1346 }
1347 }
1348
1349 #print "c<$c> SQ<$sanitise_quote>\n";
1350 if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
1351 substr($res, $off, 1, $;);
1352 } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
1353 substr($res, $off, 1, $;);
1354 } elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
1355 substr($res, $off, 1, 'X');
1356 } else {
1357 substr($res, $off, 1, $c);
1358 }
1359 }
1360
1361 if ($sanitise_quote eq '//') {
1362 $sanitise_quote = '';
1363 }
1364
1365 # The pathname on a #include may be surrounded by '<' and '>'.
1366 if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
1367 my $clean = 'X' x length($1);
1368 $res =~ s@\<.*\>@<$clean>@;
1369
1370 # The whole of a #error is a string.
1371 } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
1372 my $clean = 'X' x length($1);
1373 $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
1374 }
1375
Anas Nashif0f3d5472016-11-07 15:57:57 -05001376 if ($allow_c99_comments && $res =~ m@(//.*$)@) {
1377 my $match = $1;
1378 $res =~ s/\Q$match\E/"$;" x length($match)/e;
1379 }
1380
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001381 return $res;
1382}
1383
1384sub get_quoted_string {
1385 my ($line, $rawline) = @_;
1386
Peter Bigot5b10fac2020-03-26 11:16:33 -05001387 return "" if (!defined($line) || !defined($rawline));
Anas Nashifcbfb62c2015-10-14 06:08:54 -04001388 return "" if ($line !~ m/($String)/g);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001389 return substr($rawline, $-[0], $+[0] - $-[0]);
1390}
1391
1392sub ctx_statement_block {
1393 my ($linenr, $remain, $off) = @_;
1394 my $line = $linenr - 1;
1395 my $blk = '';
1396 my $soff = $off;
1397 my $coff = $off - 1;
1398 my $coff_set = 0;
1399
1400 my $loff = 0;
1401
1402 my $type = '';
1403 my $level = 0;
1404 my @stack = ();
1405 my $p;
1406 my $c;
1407 my $len = 0;
1408
1409 my $remainder;
1410 while (1) {
1411 @stack = (['', 0]) if ($#stack == -1);
1412
1413 #warn "CSB: blk<$blk> remain<$remain>\n";
1414 # If we are about to drop off the end, pull in more
1415 # context.
1416 if ($off >= $len) {
1417 for (; $remain > 0; $line++) {
1418 last if (!defined $lines[$line]);
1419 next if ($lines[$line] =~ /^-/);
1420 $remain--;
1421 $loff = $len;
1422 $blk .= $lines[$line] . "\n";
1423 $len = length($blk);
1424 $line++;
1425 last;
1426 }
1427 # Bail if there is no further context.
1428 #warn "CSB: blk<$blk> off<$off> len<$len>\n";
1429 if ($off >= $len) {
1430 last;
1431 }
1432 if ($level == 0 && substr($blk, $off) =~ /^.\s*#\s*define/) {
1433 $level++;
1434 $type = '#';
1435 }
1436 }
1437 $p = $c;
1438 $c = substr($blk, $off, 1);
1439 $remainder = substr($blk, $off);
1440
1441 #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
1442
1443 # Handle nested #if/#else.
1444 if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
1445 push(@stack, [ $type, $level ]);
1446 } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
1447 ($type, $level) = @{$stack[$#stack - 1]};
1448 } elsif ($remainder =~ /^#\s*endif\b/) {
1449 ($type, $level) = @{pop(@stack)};
1450 }
1451
1452 # Statement ends at the ';' or a close '}' at the
1453 # outermost level.
1454 if ($level == 0 && $c eq ';') {
1455 last;
1456 }
1457
1458 # An else is really a conditional as long as its not else if
1459 if ($level == 0 && $coff_set == 0 &&
1460 (!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
1461 $remainder =~ /^(else)(?:\s|{)/ &&
1462 $remainder !~ /^else\s+if\b/) {
1463 $coff = $off + length($1) - 1;
1464 $coff_set = 1;
1465 #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
1466 #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
1467 }
1468
1469 if (($type eq '' || $type eq '(') && $c eq '(') {
1470 $level++;
1471 $type = '(';
1472 }
1473 if ($type eq '(' && $c eq ')') {
1474 $level--;
1475 $type = ($level != 0)? '(' : '';
1476
1477 if ($level == 0 && $coff < $soff) {
1478 $coff = $off;
1479 $coff_set = 1;
1480 #warn "CSB: mark coff<$coff>\n";
1481 }
1482 }
1483 if (($type eq '' || $type eq '{') && $c eq '{') {
1484 $level++;
1485 $type = '{';
1486 }
1487 if ($type eq '{' && $c eq '}') {
1488 $level--;
1489 $type = ($level != 0)? '{' : '';
1490
1491 if ($level == 0) {
1492 if (substr($blk, $off + 1, 1) eq ';') {
1493 $off++;
1494 }
1495 last;
1496 }
1497 }
1498 # Preprocessor commands end at the newline unless escaped.
1499 if ($type eq '#' && $c eq "\n" && $p ne "\\") {
1500 $level--;
1501 $type = '';
1502 $off++;
1503 last;
1504 }
1505 $off++;
1506 }
1507 # We are truly at the end, so shuffle to the next line.
1508 if ($off == $len) {
1509 $loff = $len + 1;
1510 $line++;
1511 $remain--;
1512 }
1513
1514 my $statement = substr($blk, $soff, $off - $soff + 1);
1515 my $condition = substr($blk, $soff, $coff - $soff + 1);
1516
1517 #warn "STATEMENT<$statement>\n";
1518 #warn "CONDITION<$condition>\n";
1519
1520 #print "coff<$coff> soff<$off> loff<$loff>\n";
1521
1522 return ($statement, $condition,
1523 $line, $remain + 1, $off - $loff + 1, $level);
1524}
1525
1526sub statement_lines {
1527 my ($stmt) = @_;
1528
1529 # Strip the diff line prefixes and rip blank lines at start and end.
1530 $stmt =~ s/(^|\n)./$1/g;
1531 $stmt =~ s/^\s*//;
1532 $stmt =~ s/\s*$//;
1533
1534 my @stmt_lines = ($stmt =~ /\n/g);
1535
1536 return $#stmt_lines + 2;
1537}
1538
1539sub statement_rawlines {
1540 my ($stmt) = @_;
1541
1542 my @stmt_lines = ($stmt =~ /\n/g);
1543
1544 return $#stmt_lines + 2;
1545}
1546
1547sub statement_block_size {
1548 my ($stmt) = @_;
1549
1550 $stmt =~ s/(^|\n)./$1/g;
1551 $stmt =~ s/^\s*{//;
1552 $stmt =~ s/}\s*$//;
1553 $stmt =~ s/^\s*//;
1554 $stmt =~ s/\s*$//;
1555
1556 my @stmt_lines = ($stmt =~ /\n/g);
1557 my @stmt_statements = ($stmt =~ /;/g);
1558
1559 my $stmt_lines = $#stmt_lines + 2;
1560 my $stmt_statements = $#stmt_statements + 1;
1561
1562 if ($stmt_lines > $stmt_statements) {
1563 return $stmt_lines;
1564 } else {
1565 return $stmt_statements;
1566 }
1567}
1568
1569sub ctx_statement_full {
1570 my ($linenr, $remain, $off) = @_;
1571 my ($statement, $condition, $level);
1572
1573 my (@chunks);
1574
1575 # Grab the first conditional/block pair.
1576 ($statement, $condition, $linenr, $remain, $off, $level) =
1577 ctx_statement_block($linenr, $remain, $off);
1578 #print "F: c<$condition> s<$statement> remain<$remain>\n";
1579 push(@chunks, [ $condition, $statement ]);
1580 if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
1581 return ($level, $linenr, @chunks);
1582 }
1583
1584 # Pull in the following conditional/block pairs and see if they
1585 # could continue the statement.
1586 for (;;) {
1587 ($statement, $condition, $linenr, $remain, $off, $level) =
1588 ctx_statement_block($linenr, $remain, $off);
1589 #print "C: c<$condition> s<$statement> remain<$remain>\n";
1590 last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
1591 #print "C: push\n";
1592 push(@chunks, [ $condition, $statement ]);
1593 }
1594
1595 return ($level, $linenr, @chunks);
1596}
1597
1598sub ctx_block_get {
1599 my ($linenr, $remain, $outer, $open, $close, $off) = @_;
1600 my $line;
1601 my $start = $linenr - 1;
1602 my $blk = '';
1603 my @o;
1604 my @c;
1605 my @res = ();
1606
1607 my $level = 0;
1608 my @stack = ($level);
1609 for ($line = $start; $remain > 0; $line++) {
1610 next if ($rawlines[$line] =~ /^-/);
1611 $remain--;
1612
1613 $blk .= $rawlines[$line];
1614
1615 # Handle nested #if/#else.
1616 if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
1617 push(@stack, $level);
1618 } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
1619 $level = $stack[$#stack - 1];
1620 } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
1621 $level = pop(@stack);
1622 }
1623
1624 foreach my $c (split(//, $lines[$line])) {
1625 ##print "C<$c>L<$level><$open$close>O<$off>\n";
1626 if ($off > 0) {
1627 $off--;
1628 next;
1629 }
1630
1631 if ($c eq $close && $level > 0) {
1632 $level--;
1633 last if ($level == 0);
1634 } elsif ($c eq $open) {
1635 $level++;
1636 }
1637 }
1638
1639 if (!$outer || $level <= 1) {
1640 push(@res, $rawlines[$line]);
1641 }
1642
1643 last if ($level == 0);
1644 }
1645
1646 return ($level, @res);
1647}
1648sub ctx_block_outer {
1649 my ($linenr, $remain) = @_;
1650
1651 my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
1652 return @r;
1653}
1654sub ctx_block {
1655 my ($linenr, $remain) = @_;
1656
1657 my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1658 return @r;
1659}
1660sub ctx_statement {
1661 my ($linenr, $remain, $off) = @_;
1662
1663 my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1664 return @r;
1665}
1666sub ctx_block_level {
1667 my ($linenr, $remain) = @_;
1668
1669 return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
1670}
1671sub ctx_statement_level {
1672 my ($linenr, $remain, $off) = @_;
1673
1674 return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
1675}
1676
1677sub ctx_locate_comment {
1678 my ($first_line, $end_line) = @_;
1679
Peter A. Bigote49e3c82020-08-10 10:37:32 -05001680 # If c99 comment on the current line, or the line before or after
1681 my ($current_comment) = ($rawlines[$end_line - 1] =~ m@^\+.*(//.*$)@);
1682 return $current_comment if (defined $current_comment);
1683 ($current_comment) = ($rawlines[$end_line - 2] =~ m@^[\+ ].*(//.*$)@);
1684 return $current_comment if (defined $current_comment);
1685 ($current_comment) = ($rawlines[$end_line] =~ m@^[\+ ].*(//.*$)@);
1686 return $current_comment if (defined $current_comment);
1687
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001688 # Catch a comment on the end of the line itself.
Peter A. Bigote49e3c82020-08-10 10:37:32 -05001689 ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001690 return $current_comment if (defined $current_comment);
1691
1692 # Look through the context and try and figure out if there is a
1693 # comment.
1694 my $in_comment = 0;
1695 $current_comment = '';
1696 for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
1697 my $line = $rawlines[$linenr - 1];
1698 #warn " $line\n";
1699 if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
1700 $in_comment = 1;
1701 }
1702 if ($line =~ m@/\*@) {
1703 $in_comment = 1;
1704 }
1705 if (!$in_comment && $current_comment ne '') {
1706 $current_comment = '';
1707 }
1708 $current_comment .= $line . "\n" if ($in_comment);
1709 if ($line =~ m@\*/@) {
1710 $in_comment = 0;
1711 }
1712 }
1713
1714 chomp($current_comment);
1715 return($current_comment);
1716}
1717sub ctx_has_comment {
1718 my ($first_line, $end_line) = @_;
1719 my $cmt = ctx_locate_comment($first_line, $end_line);
1720
1721 ##print "LINE: $rawlines[$end_line - 1 ]\n";
1722 ##print "CMMT: $cmt\n";
1723
1724 return ($cmt ne '');
1725}
1726
1727sub raw_line {
1728 my ($linenr, $cnt) = @_;
1729
1730 my $offset = $linenr - 1;
1731 $cnt++;
1732
1733 my $line;
1734 while ($cnt) {
1735 $line = $rawlines[$offset++];
1736 next if (defined($line) && $line =~ /^-/);
1737 $cnt--;
1738 }
1739
1740 return $line;
1741}
1742
Peter Bigot5b10fac2020-03-26 11:16:33 -05001743sub get_stat_real {
1744 my ($linenr, $lc) = @_;
1745
1746 my $stat_real = raw_line($linenr, 0);
1747 for (my $count = $linenr + 1; $count <= $lc; $count++) {
1748 $stat_real = $stat_real . "\n" . raw_line($count, 0);
1749 }
1750
1751 return $stat_real;
1752}
1753
1754sub get_stat_here {
1755 my ($linenr, $cnt, $here) = @_;
1756
1757 my $herectx = $here . "\n";
1758 for (my $n = 0; $n < $cnt; $n++) {
1759 $herectx .= raw_line($linenr, $n) . "\n";
1760 }
1761
1762 return $herectx;
1763}
1764
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07001765sub cat_vet {
1766 my ($vet) = @_;
1767 my ($res, $coded);
1768
1769 $res = '';
1770 while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
1771 $res .= $1;
1772 if ($2 ne '') {
1773 $coded = sprintf("^%c", unpack('C', $2) + 64);
1774 $res .= $coded;
1775 }
1776 }
1777 $res =~ s/$/\$/;
1778
1779 return $res;
1780}
1781
1782my $av_preprocessor = 0;
1783my $av_pending;
1784my @av_paren_type;
1785my $av_pend_colon;
1786
1787sub annotate_reset {
1788 $av_preprocessor = 0;
1789 $av_pending = '_';
1790 @av_paren_type = ('E');
1791 $av_pend_colon = 'O';
1792}
1793
1794sub annotate_values {
1795 my ($stream, $type) = @_;
1796
1797 my $res;
1798 my $var = '_' x length($stream);
1799 my $cur = $stream;
1800
1801 print "$stream\n" if ($dbg_values > 1);
1802
1803 while (length($cur)) {
1804 @av_paren_type = ('E') if ($#av_paren_type < 0);
1805 print " <" . join('', @av_paren_type) .
1806 "> <$type> <$av_pending>" if ($dbg_values > 1);
1807 if ($cur =~ /^(\s+)/o) {
1808 print "WS($1)\n" if ($dbg_values > 1);
1809 if ($1 =~ /\n/ && $av_preprocessor) {
1810 $type = pop(@av_paren_type);
1811 $av_preprocessor = 0;
1812 }
1813
1814 } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
1815 print "CAST($1)\n" if ($dbg_values > 1);
1816 push(@av_paren_type, $type);
1817 $type = 'c';
1818
1819 } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
1820 print "DECLARE($1)\n" if ($dbg_values > 1);
1821 $type = 'T';
1822
1823 } elsif ($cur =~ /^($Modifier)\s*/) {
1824 print "MODIFIER($1)\n" if ($dbg_values > 1);
1825 $type = 'T';
1826
1827 } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
1828 print "DEFINE($1,$2)\n" if ($dbg_values > 1);
1829 $av_preprocessor = 1;
1830 push(@av_paren_type, $type);
1831 if ($2 ne '') {
1832 $av_pending = 'N';
1833 }
1834 $type = 'E';
1835
1836 } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
1837 print "UNDEF($1)\n" if ($dbg_values > 1);
1838 $av_preprocessor = 1;
1839 push(@av_paren_type, $type);
1840
1841 } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
1842 print "PRE_START($1)\n" if ($dbg_values > 1);
1843 $av_preprocessor = 1;
1844
1845 push(@av_paren_type, $type);
1846 push(@av_paren_type, $type);
1847 $type = 'E';
1848
1849 } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
1850 print "PRE_RESTART($1)\n" if ($dbg_values > 1);
1851 $av_preprocessor = 1;
1852
1853 push(@av_paren_type, $av_paren_type[$#av_paren_type]);
1854
1855 $type = 'E';
1856
1857 } elsif ($cur =~ /^(\#\s*(?:endif))/o) {
1858 print "PRE_END($1)\n" if ($dbg_values > 1);
1859
1860 $av_preprocessor = 1;
1861
1862 # Assume all arms of the conditional end as this
1863 # one does, and continue as if the #endif was not here.
1864 pop(@av_paren_type);
1865 push(@av_paren_type, $type);
1866 $type = 'E';
1867
1868 } elsif ($cur =~ /^(\\\n)/o) {
1869 print "PRECONT($1)\n" if ($dbg_values > 1);
1870
1871 } elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
1872 print "ATTR($1)\n" if ($dbg_values > 1);
1873 $av_pending = $type;
1874 $type = 'N';
1875
1876 } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
1877 print "SIZEOF($1)\n" if ($dbg_values > 1);
1878 if (defined $2) {
1879 $av_pending = 'V';
1880 }
1881 $type = 'N';
1882
1883 } elsif ($cur =~ /^(if|while|for)\b/o) {
1884 print "COND($1)\n" if ($dbg_values > 1);
1885 $av_pending = 'E';
1886 $type = 'N';
1887
1888 } elsif ($cur =~/^(case)/o) {
1889 print "CASE($1)\n" if ($dbg_values > 1);
1890 $av_pend_colon = 'C';
1891 $type = 'N';
1892
1893 } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
1894 print "KEYWORD($1)\n" if ($dbg_values > 1);
1895 $type = 'N';
1896
1897 } elsif ($cur =~ /^(\()/o) {
1898 print "PAREN('$1')\n" if ($dbg_values > 1);
1899 push(@av_paren_type, $av_pending);
1900 $av_pending = '_';
1901 $type = 'N';
1902
1903 } elsif ($cur =~ /^(\))/o) {
1904 my $new_type = pop(@av_paren_type);
1905 if ($new_type ne '_') {
1906 $type = $new_type;
1907 print "PAREN('$1') -> $type\n"
1908 if ($dbg_values > 1);
1909 } else {
1910 print "PAREN('$1')\n" if ($dbg_values > 1);
1911 }
1912
1913 } elsif ($cur =~ /^($Ident)\s*\(/o) {
1914 print "FUNC($1)\n" if ($dbg_values > 1);
1915 $type = 'V';
1916 $av_pending = 'V';
1917
1918 } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
1919 if (defined $2 && $type eq 'C' || $type eq 'T') {
1920 $av_pend_colon = 'B';
1921 } elsif ($type eq 'E') {
1922 $av_pend_colon = 'L';
1923 }
1924 print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
1925 $type = 'V';
1926
1927 } elsif ($cur =~ /^($Ident|$Constant)/o) {
1928 print "IDENT($1)\n" if ($dbg_values > 1);
1929 $type = 'V';
1930
1931 } elsif ($cur =~ /^($Assignment)/o) {
1932 print "ASSIGN($1)\n" if ($dbg_values > 1);
1933 $type = 'N';
1934
1935 } elsif ($cur =~/^(;|{|})/) {
1936 print "END($1)\n" if ($dbg_values > 1);
1937 $type = 'E';
1938 $av_pend_colon = 'O';
1939
1940 } elsif ($cur =~/^(,)/) {
1941 print "COMMA($1)\n" if ($dbg_values > 1);
1942 $type = 'C';
1943
1944 } elsif ($cur =~ /^(\?)/o) {
1945 print "QUESTION($1)\n" if ($dbg_values > 1);
1946 $type = 'N';
1947
1948 } elsif ($cur =~ /^(:)/o) {
1949 print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
1950
1951 substr($var, length($res), 1, $av_pend_colon);
1952 if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
1953 $type = 'E';
1954 } else {
1955 $type = 'N';
1956 }
1957 $av_pend_colon = 'O';
1958
1959 } elsif ($cur =~ /^(\[)/o) {
1960 print "CLOSE($1)\n" if ($dbg_values > 1);
1961 $type = 'N';
1962
1963 } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
1964 my $variant;
1965
1966 print "OPV($1)\n" if ($dbg_values > 1);
1967 if ($type eq 'V') {
1968 $variant = 'B';
1969 } else {
1970 $variant = 'U';
1971 }
1972
1973 substr($var, length($res), 1, $variant);
1974 $type = 'N';
1975
1976 } elsif ($cur =~ /^($Operators)/o) {
1977 print "OP($1)\n" if ($dbg_values > 1);
1978 if ($1 ne '++' && $1 ne '--') {
1979 $type = 'N';
1980 }
1981
1982 } elsif ($cur =~ /(^.)/o) {
1983 print "C($1)\n" if ($dbg_values > 1);
1984 }
1985 if (defined $1) {
1986 $cur = substr($cur, length($1));
1987 $res .= $type x length($1);
1988 }
1989 }
1990
1991 return ($res, $var);
1992}
1993
1994sub possible {
1995 my ($possible, $line) = @_;
1996 my $notPermitted = qr{(?:
1997 ^(?:
1998 $Modifier|
1999 $Storage|
2000 $Type|
2001 DEFINE_\S+
2002 )$|
2003 ^(?:
2004 goto|
2005 return|
2006 case|
2007 else|
2008 asm|__asm__|
2009 do|
2010 \#|
2011 \#\#|
2012 )(?:\s|$)|
2013 ^(?:typedef|struct|enum)\b
2014 )}x;
2015 warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
2016 if ($possible !~ $notPermitted) {
2017 # Check for modifiers.
2018 $possible =~ s/\s*$Storage\s*//g;
2019 $possible =~ s/\s*$Sparse\s*//g;
2020 if ($possible =~ /^\s*$/) {
2021
2022 } elsif ($possible =~ /\s/) {
2023 $possible =~ s/\s*$Type\s*//g;
2024 for my $modifier (split(' ', $possible)) {
2025 if ($modifier !~ $notPermitted) {
2026 warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002027 push(@modifierListFile, $modifier);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002028 }
2029 }
2030
2031 } else {
2032 warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002033 push(@typeListFile, $possible);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002034 }
2035 build_types();
2036 } else {
2037 warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
2038 }
2039}
2040
2041my $prefix = '';
2042
2043sub show_type {
2044 my ($type) = @_;
2045
Anas Nashif1eb244c2017-10-01 17:06:36 -04002046 $type =~ tr/[a-z]/[A-Z]/;
2047
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002048 return defined $use_type{$type} if (scalar keys %use_type > 0);
2049
2050 return !defined $ignore_type{$type};
2051}
2052
2053sub report {
2054 my ($level, $type, $msg) = @_;
2055
2056 if (!show_type($type) ||
2057 (defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
2058 return 0;
2059 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002060 my $output = '';
Anas Nashif1eb244c2017-10-01 17:06:36 -04002061 if ($color) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002062 if ($level eq 'ERROR') {
2063 $output .= RED;
2064 } elsif ($level eq 'WARNING') {
2065 $output .= YELLOW;
2066 } else {
2067 $output .= GREEN;
2068 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002069 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002070 $output .= $prefix . $level . ':';
2071 if ($show_types) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04002072 $output .= BLUE if ($color);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002073 $output .= "$type:";
2074 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04002075 $output .= RESET if ($color);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002076 $output .= ' ' . $msg . "\n";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002077
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002078 if ($showfile) {
2079 my @lines = split("\n", $output, -1);
2080 splice(@lines, 1, 1);
2081 $output = join("\n", @lines);
2082 }
2083 $output = (split('\n', $output))[0] . "\n" if ($terse);
2084
2085 push(our @report, $output);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002086
2087 return 1;
2088}
2089
2090sub report_dump {
2091 our @report;
2092}
2093
2094sub fixup_current_range {
2095 my ($lineRef, $offset, $length) = @_;
2096
2097 if ($$lineRef =~ /^\@\@ -\d+,\d+ \+(\d+),(\d+) \@\@/) {
2098 my $o = $1;
2099 my $l = $2;
2100 my $no = $o + $offset;
2101 my $nl = $l + $length;
2102 $$lineRef =~ s/\+$o,$l \@\@/\+$no,$nl \@\@/;
2103 }
2104}
2105
2106sub fix_inserted_deleted_lines {
2107 my ($linesRef, $insertedRef, $deletedRef) = @_;
2108
2109 my $range_last_linenr = 0;
2110 my $delta_offset = 0;
2111
2112 my $old_linenr = 0;
2113 my $new_linenr = 0;
2114
2115 my $next_insert = 0;
2116 my $next_delete = 0;
2117
2118 my @lines = ();
2119
2120 my $inserted = @{$insertedRef}[$next_insert++];
2121 my $deleted = @{$deletedRef}[$next_delete++];
2122
2123 foreach my $old_line (@{$linesRef}) {
2124 my $save_line = 1;
2125 my $line = $old_line; #don't modify the array
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002126 if ($line =~ /^(?:\+\+\+|\-\-\-)\s+\S+/) { #new filename
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002127 $delta_offset = 0;
2128 } elsif ($line =~ /^\@\@ -\d+,\d+ \+\d+,\d+ \@\@/) { #new hunk
2129 $range_last_linenr = $new_linenr;
2130 fixup_current_range(\$line, $delta_offset, 0);
2131 }
2132
2133 while (defined($deleted) && ${$deleted}{'LINENR'} == $old_linenr) {
2134 $deleted = @{$deletedRef}[$next_delete++];
2135 $save_line = 0;
2136 fixup_current_range(\$lines[$range_last_linenr], $delta_offset--, -1);
2137 }
2138
2139 while (defined($inserted) && ${$inserted}{'LINENR'} == $old_linenr) {
2140 push(@lines, ${$inserted}{'LINE'});
2141 $inserted = @{$insertedRef}[$next_insert++];
2142 $new_linenr++;
2143 fixup_current_range(\$lines[$range_last_linenr], $delta_offset++, 1);
2144 }
2145
2146 if ($save_line) {
2147 push(@lines, $line);
2148 $new_linenr++;
2149 }
2150
2151 $old_linenr++;
2152 }
2153
2154 return @lines;
2155}
2156
2157sub fix_insert_line {
2158 my ($linenr, $line) = @_;
2159
2160 my $inserted = {
2161 LINENR => $linenr,
2162 LINE => $line,
2163 };
2164 push(@fixed_inserted, $inserted);
2165}
2166
2167sub fix_delete_line {
2168 my ($linenr, $line) = @_;
2169
2170 my $deleted = {
2171 LINENR => $linenr,
2172 LINE => $line,
2173 };
2174
2175 push(@fixed_deleted, $deleted);
2176}
2177
2178sub ERROR {
2179 my ($type, $msg) = @_;
2180
2181 if (report("ERROR", $type, $msg)) {
2182 our $clean = 0;
2183 our $cnt_error++;
2184 return 1;
2185 }
2186 return 0;
2187}
2188sub WARN {
2189 my ($type, $msg) = @_;
2190
2191 if (report("WARNING", $type, $msg)) {
2192 our $clean = 0;
2193 our $cnt_warn++;
2194 return 1;
2195 }
2196 return 0;
2197}
2198sub CHK {
2199 my ($type, $msg) = @_;
2200
2201 if ($check && report("CHECK", $type, $msg)) {
2202 our $clean = 0;
2203 our $cnt_chk++;
2204 return 1;
2205 }
2206 return 0;
2207}
2208
2209sub check_absolute_file {
2210 my ($absolute, $herecurr) = @_;
2211 my $file = $absolute;
2212
2213 ##print "absolute<$absolute>\n";
2214
2215 # See if any suffix of this path is a path within the tree.
2216 while ($file =~ s@^[^/]*/@@) {
2217 if (-f "$root/$file") {
2218 ##print "file<$file>\n";
2219 last;
2220 }
2221 }
2222 if (! -f _) {
2223 return 0;
2224 }
2225
2226 # It is, so see if the prefix is acceptable.
2227 my $prefix = $absolute;
2228 substr($prefix, -length($file)) = '';
2229
2230 ##print "prefix<$prefix>\n";
2231 if ($prefix ne ".../") {
2232 WARN("USE_RELATIVE_PATH",
2233 "use relative pathname instead of absolute in changelog text\n" . $herecurr);
2234 }
2235}
2236
2237sub trim {
2238 my ($string) = @_;
2239
2240 $string =~ s/^\s+|\s+$//g;
2241
2242 return $string;
2243}
2244
2245sub ltrim {
2246 my ($string) = @_;
2247
2248 $string =~ s/^\s+//;
2249
2250 return $string;
2251}
2252
2253sub rtrim {
2254 my ($string) = @_;
2255
2256 $string =~ s/\s+$//;
2257
2258 return $string;
2259}
2260
2261sub string_find_replace {
2262 my ($string, $find, $replace) = @_;
2263
2264 $string =~ s/$find/$replace/g;
2265
2266 return $string;
2267}
2268
2269sub tabify {
2270 my ($leading) = @_;
2271
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002272 my $source_indent = $tabsize;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002273 my $max_spaces_before_tab = $source_indent - 1;
2274 my $spaces_to_tab = " " x $source_indent;
2275
2276 #convert leading spaces to tabs
2277 1 while $leading =~ s@^([\t]*)$spaces_to_tab@$1\t@g;
2278 #Remove spaces before a tab
2279 1 while $leading =~ s@^([\t]*)( {1,$max_spaces_before_tab})\t@$1\t@g;
2280
2281 return "$leading";
2282}
2283
2284sub pos_last_openparen {
2285 my ($line) = @_;
2286
2287 my $pos = 0;
2288
2289 my $opens = $line =~ tr/\(/\(/;
2290 my $closes = $line =~ tr/\)/\)/;
2291
2292 my $last_openparen = 0;
2293
2294 if (($opens == 0) || ($closes >= $opens)) {
2295 return -1;
2296 }
2297
2298 my $len = length($line);
2299
2300 for ($pos = 0; $pos < $len; $pos++) {
2301 my $string = substr($line, $pos);
2302 if ($string =~ /^($FuncArg|$balanced_parens)/) {
2303 $pos += length($1) - 1;
2304 } elsif (substr($line, $pos, 1) eq '(') {
2305 $last_openparen = $pos;
2306 } elsif (index($string, '(') == -1) {
2307 last;
2308 }
2309 }
2310
2311 return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
2312}
2313
2314sub process {
2315 my $filename = shift;
2316
2317 my $linenr=0;
2318 my $prevline="";
2319 my $prevrawline="";
2320 my $stashline="";
2321 my $stashrawline="";
2322
2323 my $length;
2324 my $indent;
2325 my $previndent=0;
2326 my $stashindent=0;
2327
2328 our $clean = 1;
2329 my $signoff = 0;
Peter Bigot5b10fac2020-03-26 11:16:33 -05002330 my $author = '';
2331 my $authorsignoff = 0;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002332 my $is_patch = 0;
Peter Bigot5b10fac2020-03-26 11:16:33 -05002333 my $is_binding_patch = -1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002334 my $in_header_lines = $file ? 0 : 1;
2335 my $in_commit_log = 0; #Scanning lines before patch
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002336 my $has_patch_separator = 0; #Found a --- line
Anas Nashif0f3d5472016-11-07 15:57:57 -05002337 my $has_commit_log = 0; #Encountered lines before patch
Peter Bigot5b10fac2020-03-26 11:16:33 -05002338 my $commit_log_lines = 0; #Number of commit log lines
Anas Nashif1eb244c2017-10-01 17:06:36 -04002339 my $commit_log_possible_stack_dump = 0;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002340 my $commit_log_long_line = 0;
2341 my $commit_log_has_diff = 0;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002342 my $reported_maintainer_file = 0;
2343 my $non_utf8_charset = 0;
2344
2345 my $last_blank_line = 0;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002346 my $last_coalesced_string_linenr = -1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002347
2348 our @report = ();
2349 our $cnt_lines = 0;
2350 our $cnt_error = 0;
2351 our $cnt_warn = 0;
2352 our $cnt_chk = 0;
2353
2354 # Trace the real file/line as we go.
2355 my $realfile = '';
2356 my $realline = 0;
2357 my $realcnt = 0;
2358 my $here = '';
Anas Nashif1eb244c2017-10-01 17:06:36 -04002359 my $context_function; #undef'd unless there's a known function
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002360 my $in_comment = 0;
2361 my $comment_edge = 0;
2362 my $first_line = 0;
2363 my $p1_prefix = '';
2364
2365 my $prev_values = 'E';
2366
2367 # suppression flags
2368 my %suppress_ifbraces;
2369 my %suppress_whiletrailers;
2370 my %suppress_export;
2371 my $suppress_statement = 0;
2372
2373 my %signatures = ();
2374
2375 # Pre-scan the patch sanitizing the lines.
2376 # Pre-scan the patch looking for any __setup documentation.
2377 #
2378 my @setup_docs = ();
2379 my $setup_docs = 0;
2380
2381 my $camelcase_file_seeded = 0;
2382
Peter Bigot5b10fac2020-03-26 11:16:33 -05002383 my $checklicenseline = 1;
2384
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002385 sanitise_line_reset();
2386 my $line;
2387 foreach my $rawline (@rawlines) {
2388 $linenr++;
2389 $line = $rawline;
2390
2391 push(@fixed, $rawline) if ($fix);
2392
2393 if ($rawline=~/^\+\+\+\s+(\S+)/) {
2394 $setup_docs = 0;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002395 if ($1 =~ m@Documentation/admin-guide/kernel-parameters.txt$@) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002396 $setup_docs = 1;
2397 }
2398 #next;
2399 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04002400 if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002401 $realline=$1-1;
2402 if (defined $2) {
2403 $realcnt=$3+1;
2404 } else {
2405 $realcnt=1+1;
2406 }
2407 $in_comment = 0;
2408
2409 # Guestimate if this is a continuing comment. Run
2410 # the context looking for a comment "edge". If this
2411 # edge is a close comment then we must be in a comment
2412 # at context start.
2413 my $edge;
2414 my $cnt = $realcnt;
2415 for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
2416 next if (defined $rawlines[$ln - 1] &&
2417 $rawlines[$ln - 1] =~ /^-/);
2418 $cnt--;
2419 #print "RAW<$rawlines[$ln - 1]>\n";
2420 last if (!defined $rawlines[$ln - 1]);
2421 if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
2422 $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
2423 ($edge) = $1;
2424 last;
2425 }
2426 }
2427 if (defined $edge && $edge eq '*/') {
2428 $in_comment = 1;
2429 }
2430
2431 # Guestimate if this is a continuing comment. If this
2432 # is the start of a diff block and this line starts
2433 # ' *' then it is very likely a comment.
2434 if (!defined $edge &&
2435 $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
2436 {
2437 $in_comment = 1;
2438 }
2439
2440 ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
2441 sanitise_line_reset($in_comment);
2442
2443 } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
2444 # Standardise the strings and chars within the input to
2445 # simplify matching -- only bother with positive lines.
2446 $line = sanitise_line($rawline);
2447 }
2448 push(@lines, $line);
2449
2450 if ($realcnt > 1) {
2451 $realcnt-- if ($line =~ /^(?:\+| |$)/);
2452 } else {
2453 $realcnt = 0;
2454 }
2455
2456 #print "==>$rawline\n";
2457 #print "-->$line\n";
2458
2459 if ($setup_docs && $line =~ /^\+/) {
2460 push(@setup_docs, $line);
2461 }
2462 }
2463
2464 $prefix = '';
2465
2466 $realcnt = 0;
2467 $linenr = 0;
2468 $fixlinenr = -1;
2469 foreach my $line (@lines) {
2470 $linenr++;
2471 $fixlinenr++;
2472 my $sline = $line; #copy of $line
2473 $sline =~ s/$;/ /g; #with comments as spaces
2474
2475 my $rawline = $rawlines[$linenr - 1];
2476
Peter Bigot5b10fac2020-03-26 11:16:33 -05002477# check if it's a mode change, rename or start of a patch
2478 if (!$in_commit_log &&
2479 ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ ||
2480 ($line =~ /^rename (?:from|to) \S+\s*$/ ||
2481 $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) {
2482 $is_patch = 1;
2483 }
2484
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002485#extract the line range in the file after the patch is applied
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002486 if (!$in_commit_log &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04002487 $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
2488 my $context = $4;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002489 $is_patch = 1;
2490 $first_line = $linenr + 1;
2491 $realline=$1-1;
2492 if (defined $2) {
2493 $realcnt=$3+1;
2494 } else {
2495 $realcnt=1+1;
2496 }
2497 annotate_reset();
2498 $prev_values = 'E';
2499
2500 %suppress_ifbraces = ();
2501 %suppress_whiletrailers = ();
2502 %suppress_export = ();
2503 $suppress_statement = 0;
Anas Nashif1eb244c2017-10-01 17:06:36 -04002504 if ($context =~ /\b(\w+)\s*\(/) {
2505 $context_function = $1;
2506 } else {
2507 undef $context_function;
2508 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002509 next;
2510
2511# track the line number as we move through the hunk, note that
2512# new versions of GNU diff omit the leading space on completely
2513# blank context lines so we need to count that too.
2514 } elsif ($line =~ /^( |\+|$)/) {
2515 $realline++;
2516 $realcnt-- if ($realcnt != 0);
2517
2518 # Measure the line length and indent.
2519 ($length, $indent) = line_stats($rawline);
2520
2521 # Track the previous line.
2522 ($prevline, $stashline) = ($stashline, $line);
2523 ($previndent, $stashindent) = ($stashindent, $indent);
2524 ($prevrawline, $stashrawline) = ($stashrawline, $rawline);
2525
2526 #warn "line<$line>\n";
2527
2528 } elsif ($realcnt == 1) {
2529 $realcnt--;
2530 }
2531
2532 my $hunk_line = ($realcnt != 0);
2533
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002534 $here = "#$linenr: " if (!$file);
2535 $here = "#$realline: " if ($file);
2536
2537 my $found_file = 0;
2538 # extract the filename as it passes
2539 if ($line =~ /^diff --git.*?(\S+)$/) {
2540 $realfile = $1;
2541 $realfile =~ s@^([^/]*)/@@ if (!$file);
2542 $in_commit_log = 0;
2543 $found_file = 1;
2544 } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
2545 $realfile = $1;
2546 $realfile =~ s@^([^/]*)/@@ if (!$file);
2547 $in_commit_log = 0;
2548
2549 $p1_prefix = $1;
2550 if (!$file && $tree && $p1_prefix ne '' &&
2551 -e "$root/$p1_prefix") {
2552 WARN("PATCH_PREFIX",
2553 "patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
2554 }
2555
2556 if ($realfile =~ m@^include/asm/@) {
2557 ERROR("MODIFIED_INCLUDE_ASM",
2558 "do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
2559 }
2560 $found_file = 1;
2561 }
Anas Nashif92a12a12016-05-20 18:26:59 -04002562 my $skipme = 0;
2563 foreach (@exclude) {
2564 if ($realfile =~ m@^(?:$_/)@) {
2565 $skipme = 1;
2566 }
2567 }
2568 if ($skipme) {
2569 next;
2570 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002571
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002572#make up the handle for any error we report on this line
2573 if ($showfile) {
2574 $prefix = "$realfile:$realline: "
2575 } elsif ($emacs) {
2576 if ($file) {
2577 $prefix = "$filename:$realline: ";
2578 } else {
2579 $prefix = "$filename:$linenr: ";
2580 }
2581 }
2582
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002583 if ($found_file) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04002584 if (is_maintained_obsolete($realfile)) {
2585 WARN("OBSOLETE",
2586 "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n");
2587 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002588 if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002589 $check = 1;
2590 } else {
2591 $check = $check_orig;
2592 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05002593 $checklicenseline = 1;
2594
2595 if ($realfile !~ /^MAINTAINERS/) {
2596 my $last_binding_patch = $is_binding_patch;
2597
2598 $is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@;
2599
2600 if (($last_binding_patch != -1) &&
2601 ($last_binding_patch ^ $is_binding_patch)) {
2602 WARN("DT_SPLIT_BINDING_PATCH",
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002603 "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.rst\n");
Peter Bigot5b10fac2020-03-26 11:16:33 -05002604 }
2605 }
2606
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002607 next;
2608 }
2609
2610 $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
2611
2612 my $hereline = "$here\n$rawline\n";
2613 my $herecurr = "$here\n$rawline\n";
2614 my $hereprev = "$here\n$prevrawline\n$rawline\n";
2615
2616 $cnt_lines++ if ($realcnt != 0);
2617
Peter Bigot5b10fac2020-03-26 11:16:33 -05002618# Verify the existence of a commit log if appropriate
2619# 2 is used because a $signature is counted in $commit_log_lines
2620 if ($in_commit_log) {
2621 if ($line !~ /^\s*$/) {
2622 $commit_log_lines++; #could be a $signature
2623 }
2624 } elsif ($has_commit_log && $commit_log_lines < 2) {
2625 WARN("COMMIT_MESSAGE",
2626 "Missing commit description - Add an appropriate one\n");
2627 $commit_log_lines = 2; #warn only once
2628 }
2629
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002630# Check if the commit log has what seems like a diff which can confuse patch
2631 if ($in_commit_log && !$commit_log_has_diff &&
2632 (($line =~ m@^\s+diff\b.*a/[\w/]+@ &&
2633 $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) ||
2634 $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ ||
2635 $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) {
2636 ERROR("DIFF_IN_COMMIT_MSG",
2637 "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr);
2638 $commit_log_has_diff = 1;
2639 }
2640
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002641# Check for incorrect file permissions
2642 if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
2643 my $permhere = $here . "FILE: $realfile\n";
2644 if ($realfile !~ m@scripts/@ &&
2645 $realfile !~ /\.(py|pl|awk|sh)$/) {
2646 ERROR("EXECUTE_PERMISSIONS",
2647 "do not set execute permissions for source files\n" . $permhere);
2648 }
2649 }
2650
Peter Bigot5b10fac2020-03-26 11:16:33 -05002651# Check the patch for a From:
2652 if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
2653 $author = $1;
2654 $author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
2655 $author =~ s/"//g;
2656 }
2657
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002658# Check the patch for a signoff:
2659 if ($line =~ /^\s*signed-off-by:/i) {
2660 $signoff++;
2661 $in_commit_log = 0;
Peter Bigot5b10fac2020-03-26 11:16:33 -05002662 if ($author ne '') {
2663 my $l = $line;
2664 $l =~ s/"//g;
2665 if ($l =~ /^\s*signed-off-by:\s*\Q$author\E/i) {
2666 $authorsignoff = 1;
2667 }
2668 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002669 }
2670
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002671# Check for patch separator
2672 if ($line =~ /^---$/) {
2673 $has_patch_separator = 1;
2674 $in_commit_log = 0;
2675 }
2676
Anas Nashifc2de83c2017-09-08 09:51:01 -04002677# Check if CODEOWNERS is being updated. If so, there's probably no need to
2678# emit the "does CODEOWNERS need updating?" message on file add/move/delete
2679 if ($line =~ /^\s*CODEOWNERS\s*\|/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002680 $reported_maintainer_file = 1;
2681 }
2682
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002683# Check signature styles
2684 if (!$in_header_lines &&
2685 $line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
2686 my $space_before = $1;
2687 my $sign_off = $2;
2688 my $space_after = $3;
2689 my $email = $4;
2690 my $ucfirst_sign_off = ucfirst(lc($sign_off));
2691
2692 if ($sign_off !~ /$signature_tags/) {
2693 WARN("BAD_SIGN_OFF",
2694 "Non-standard signature: $sign_off\n" . $herecurr);
2695 }
2696 if (defined $space_before && $space_before ne "") {
2697 if (WARN("BAD_SIGN_OFF",
2698 "Do not use whitespace before $ucfirst_sign_off\n" . $herecurr) &&
2699 $fix) {
2700 $fixed[$fixlinenr] =
2701 "$ucfirst_sign_off $email";
2702 }
2703 }
2704 if ($sign_off =~ /-by:$/i && $sign_off ne $ucfirst_sign_off) {
2705 if (WARN("BAD_SIGN_OFF",
2706 "'$ucfirst_sign_off' is the preferred signature form\n" . $herecurr) &&
2707 $fix) {
2708 $fixed[$fixlinenr] =
2709 "$ucfirst_sign_off $email";
2710 }
2711
2712 }
2713 if (!defined $space_after || $space_after ne " ") {
2714 if (WARN("BAD_SIGN_OFF",
2715 "Use a single space after $ucfirst_sign_off\n" . $herecurr) &&
2716 $fix) {
2717 $fixed[$fixlinenr] =
2718 "$ucfirst_sign_off $email";
2719 }
2720 }
2721
2722 my ($email_name, $email_address, $comment) = parse_email($email);
2723 my $suggested_email = format_email(($email_name, $email_address));
2724 if ($suggested_email eq "") {
2725 ERROR("BAD_SIGN_OFF",
2726 "Unrecognized email address: '$email'\n" . $herecurr);
2727 } else {
2728 my $dequoted = $suggested_email;
2729 $dequoted =~ s/^"//;
2730 $dequoted =~ s/" </ </;
2731 # Don't force email to have quotes
2732 # Allow just an angle bracketed address
2733 if ("$dequoted$comment" ne $email &&
2734 "<$email_address>$comment" ne $email &&
2735 "$suggested_email$comment" ne $email) {
2736 WARN("BAD_SIGN_OFF",
2737 "email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
2738 }
2739 }
2740
2741# Check for duplicate signatures
2742 my $sig_nospace = $line;
2743 $sig_nospace =~ s/\s//g;
2744 $sig_nospace = lc($sig_nospace);
2745 if (defined $signatures{$sig_nospace}) {
2746 WARN("BAD_SIGN_OFF",
2747 "Duplicate signature\n" . $herecurr);
2748 } else {
2749 $signatures{$sig_nospace} = 1;
2750 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05002751
2752# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
2753 if ($sign_off =~ /^co-developed-by:$/i) {
2754 if ($email eq $author) {
2755 WARN("BAD_SIGN_OFF",
2756 "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
2757 }
2758 if (!defined $lines[$linenr]) {
2759 WARN("BAD_SIGN_OFF",
2760 "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
2761 } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
2762 WARN("BAD_SIGN_OFF",
2763 "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
2764 } elsif ($1 ne $email) {
2765 WARN("BAD_SIGN_OFF",
2766 "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
2767 }
2768 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002769 }
2770
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002771# Check email subject for common tools that don't need to be mentioned
2772 if ($in_header_lines &&
2773 $line =~ /^Subject:.*\b(?:checkpatch|sparse|smatch)\b[^:]/i) {
2774 WARN("EMAIL_SUBJECT",
2775 "A patch subject line should describe the change not the tool that found it\n" . $herecurr);
2776 }
2777
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002778# Check for Gerrit Change-Ids not in any patch context
2779 if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04002780 ERROR("GERRIT_CHANGE_ID",
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002781 "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
Anas Nashif1eb244c2017-10-01 17:06:36 -04002782 }
2783
Anas Nashif76b09132016-02-20 13:53:35 -05002784# Check if the commit log is in a possible stack dump
2785 if ($in_commit_log && !$commit_log_possible_stack_dump &&
2786 ($line =~ /^\s*(?:WARNING:|BUG:)/ ||
2787 $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
2788 # timestamp
Peter Bigot5b10fac2020-03-26 11:16:33 -05002789 $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
2790 $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
2791 $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
2792 # stack dump address styles
Anas Nashif76b09132016-02-20 13:53:35 -05002793 $commit_log_possible_stack_dump = 1;
2794 }
2795
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002796# Check for line lengths > 75 in commit log, warn once
2797 if ($in_commit_log && !$commit_log_long_line &&
Anas Nashif76b09132016-02-20 13:53:35 -05002798 length($line) > 75 &&
2799 !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
2800 # file delta changes
2801 $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
2802 # filename then :
2803 $line =~ /^\s*(?:Fixes:|Link:)/i ||
2804 # A Fixes: or Link: line
2805 $commit_log_possible_stack_dump)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002806 WARN("COMMIT_LOG_LONG_LINE",
2807 "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
2808 $commit_log_long_line = 1;
2809 }
2810
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002811# Reset possible stack dump if a blank line is found
Anas Nashif76b09132016-02-20 13:53:35 -05002812 if ($in_commit_log && $commit_log_possible_stack_dump &&
2813 $line =~ /^\s*$/) {
2814 $commit_log_possible_stack_dump = 0;
2815 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002816
2817# Check for git id commit length and improperly formed commit descriptions
Anas Nashif76b09132016-02-20 13:53:35 -05002818 if ($in_commit_log && !$commit_log_possible_stack_dump &&
Peter A. Bigote49e3c82020-08-10 10:37:32 -05002819 $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04002820 $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002821 ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
Anas Nashif0f3d5472016-11-07 15:57:57 -05002822 ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
Anas Nashif76b09132016-02-20 13:53:35 -05002823 $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
2824 $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002825 my $init_char = "c";
2826 my $orig_commit = "";
2827 my $short = 1;
2828 my $long = 0;
2829 my $case = 1;
2830 my $space = 1;
2831 my $hasdesc = 0;
2832 my $hasparens = 0;
2833 my $id = '0123456789ab';
2834 my $orig_desc = "commit description";
2835 my $description = "";
2836
2837 if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
2838 $init_char = $1;
2839 $orig_commit = lc($2);
2840 } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) {
2841 $orig_commit = lc($1);
2842 }
2843
2844 $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i);
2845 $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i);
2846 $space = 0 if ($line =~ /\bcommit [0-9a-f]/i);
2847 $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
2848 if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) {
2849 $orig_desc = $1;
2850 $hasparens = 1;
2851 } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i &&
2852 defined $rawlines[$linenr] &&
2853 $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) {
2854 $orig_desc = $1;
2855 $hasparens = 1;
2856 } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i &&
2857 defined $rawlines[$linenr] &&
2858 $rawlines[$linenr] =~ /^\s*[^"]+"\)/) {
2859 $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i;
2860 $orig_desc = $1;
2861 $rawlines[$linenr] =~ /^\s*([^"]+)"\)/;
2862 $orig_desc .= " " . $1;
2863 $hasparens = 1;
2864 }
2865
2866 ($id, $description) = git_commit_info($orig_commit,
2867 $id, $orig_desc);
2868
Anas Nashif1eb244c2017-10-01 17:06:36 -04002869 if (defined($id) &&
2870 ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002871 ERROR("GIT_COMMIT_ID",
2872 "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr);
2873 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002874 }
2875
2876# Check for added, moved or deleted files
2877 if (!$reported_maintainer_file && !$in_commit_log &&
2878 ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ ||
2879 $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
2880 ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
2881 (defined($1) || defined($2))))) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04002882 $is_patch = 1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002883 $reported_maintainer_file = 1;
2884 WARN("FILE_PATH_CHANGES",
Anas Nashifc2de83c2017-09-08 09:51:01 -04002885 "added, moved or deleted file(s), does CODEOWNERS need updating?\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002886 }
2887
Peter Bigot5b10fac2020-03-26 11:16:33 -05002888# Check for adding new DT bindings not in schema format
2889 if (!$in_commit_log &&
2890 ($line =~ /^new file mode\s*\d+\s*$/) &&
2891 ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
2892 WARN("DT_SCHEMA_BINDING_PATCH",
2893 "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n");
2894 }
2895
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002896# Check for wrappage within a valid hunk of the file
2897 if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
2898 ERROR("CORRUPTED_PATCH",
2899 "patch seems to be corrupt (line wrapped?)\n" .
2900 $herecurr) if (!$emitted_corrupt++);
2901 }
2902
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002903# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
2904 if (($realfile =~ /^$/ || $line =~ /^\+/) &&
2905 $rawline !~ m/^$UTF8*$/) {
2906 my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
2907
2908 my $blank = copy_spacing($rawline);
2909 my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
2910 my $hereptr = "$hereline$ptr\n";
2911
2912 CHK("INVALID_UTF8",
2913 "Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
2914 }
2915
2916# Check if it's the start of a commit log
2917# (not a header line and we haven't seen the patch filename)
2918 if ($in_header_lines && $realfile =~ /^$/ &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04002919 !($rawline =~ /^\s+(?:\S|$)/ ||
2920 $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002921 $in_header_lines = 0;
2922 $in_commit_log = 1;
Anas Nashif0f3d5472016-11-07 15:57:57 -05002923 $has_commit_log = 1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002924 }
2925
2926# Check if there is UTF-8 in a commit log when a mail header has explicitly
2927# declined it, i.e defined some charset where it is missing.
2928 if ($in_header_lines &&
2929 $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
2930 $1 !~ /utf-8/i) {
2931 $non_utf8_charset = 1;
2932 }
2933
2934 if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
2935 $rawline =~ /$NON_ASCII_UTF8/) {
2936 WARN("UTF8_BEFORE_PATCH",
2937 "8-bit UTF-8 used in possible commit log\n" . $herecurr);
2938 }
2939
Anas Nashif1eb244c2017-10-01 17:06:36 -04002940# Check for absolute kernel paths in commit message
2941 if ($tree && $in_commit_log) {
2942 while ($line =~ m{(?:^|\s)(/\S*)}g) {
2943 my $file = $1;
2944
2945 if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
2946 check_absolute_file($1, $herecurr)) {
2947 #
2948 } else {
2949 check_absolute_file($file, $herecurr);
2950 }
2951 }
2952 }
2953
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002954# Check for various typo / spelling mistakes
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002955 if (defined($misspellings) &&
Dmitry Lukyantsevb2af5e82023-08-03 13:54:08 -07002956 ($spelling_file !~ /$realfile/) &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04002957 ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
2958 while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002959 my $typo = $1;
2960 my $typo_fix = $spelling_fix{lc($typo)};
2961 $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
2962 $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
Anas Nashif1eb244c2017-10-01 17:06:36 -04002963 my $msg_level = \&WARN;
2964 $msg_level = \&CHK if ($file);
2965 if (&{$msg_level}("TYPO_SPELLING",
2966 "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002967 $fix) {
2968 $fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
2969 }
2970 }
2971 }
2972
Peter Bigot5b10fac2020-03-26 11:16:33 -05002973# check for invalid commit id
2974 if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
2975 my $id;
2976 my $description;
2977 ($id, $description) = git_commit_info($2, undef, undef);
2978 if (!defined($id)) {
2979 WARN("UNKNOWN_COMMIT_ID",
2980 "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
2981 }
2982 }
2983
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07002984# ignore non-hunk lines and lines being removed
2985 next if (!$hunk_line || $line =~ /^-/);
2986
2987#trailing whitespace
2988 if ($line =~ /^\+.*\015/) {
2989 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2990 if (ERROR("DOS_LINE_ENDINGS",
2991 "DOS line endings\n" . $herevet) &&
2992 $fix) {
2993 $fixed[$fixlinenr] =~ s/[\s\015]+$//;
2994 }
2995 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
2996 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
2997 if (ERROR("TRAILING_WHITESPACE",
2998 "trailing whitespace\n" . $herevet) &&
2999 $fix) {
3000 $fixed[$fixlinenr] =~ s/\s+$//;
3001 }
3002
3003 $rpt_cleaners = 1;
3004 }
3005
3006# Check for FSF mailing addresses.
3007 if ($rawline =~ /\bwrite to the Free/i ||
Anas Nashif1eb244c2017-10-01 17:06:36 -04003008 $rawline =~ /\b675\s+Mass\s+Ave/i ||
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003009 $rawline =~ /\b59\s+Temple\s+Pl/i ||
3010 $rawline =~ /\b51\s+Franklin\s+St/i) {
3011 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
Anas Nashif1eb244c2017-10-01 17:06:36 -04003012 my $msg_level = \&ERROR;
3013 $msg_level = \&CHK if ($file);
3014 &{$msg_level}("FSF_MAILING_ADDRESS",
3015 "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)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003016 }
3017
3018# check for Kconfig help text having a real description
3019# Only applies when adding the entry originally, after that we do not have
3020# sufficient context to determine whether it is indeed long enough.
3021 if ($realfile =~ /Kconfig/ &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05003022 # 'choice' is usually the last thing on the line (though
3023 # Kconfig supports named choices), so use a word boundary
3024 # (\b) rather than a whitespace character (\s)
3025 $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003026 my $length = 0;
3027 my $cnt = $realcnt;
3028 my $ln = $linenr + 1;
3029 my $f;
3030 my $is_start = 0;
3031 my $is_end = 0;
3032 for (; $cnt > 0 && defined $lines[$ln - 1]; $ln++) {
3033 $f = $lines[$ln - 1];
3034 $cnt-- if ($lines[$ln - 1] !~ /^-/);
3035 $is_end = $lines[$ln - 1] =~ /^\+/;
3036
3037 next if ($f =~ /^-/);
3038 last if (!$file && $f =~ /^\@\@/);
3039
Peter Bigot5b10fac2020-03-26 11:16:33 -05003040 if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003041 $is_start = 1;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003042 } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003043 $length = -1;
3044 }
3045
3046 $f =~ s/^.//;
3047 $f =~ s/#.*//;
3048 $f =~ s/^\s+//;
3049 next if ($f =~ /^$/);
Peter Bigot5b10fac2020-03-26 11:16:33 -05003050
3051 # This only checks context lines in the patch
3052 # and so hopefully shouldn't trigger false
3053 # positives, even though some of these are
3054 # common words in help texts
3055 if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
3056 if|endif|menu|endmenu|source)\b/x) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003057 $is_end = 1;
3058 last;
3059 }
3060 $length++;
3061 }
3062 if ($is_start && $is_end && $length < $min_conf_desc_length) {
3063 WARN("CONFIG_DESCRIPTION",
3064 "please write a paragraph that describes the config symbol fully\n" . $herecurr);
3065 }
3066 #print "is_start<$is_start> is_end<$is_end> length<$length>\n";
3067 }
3068
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003069# check MAINTAINERS entries
3070 if ($realfile =~ /^MAINTAINERS$/) {
3071# check MAINTAINERS entries for the right form
3072 if ($rawline =~ /^\+[A-Z]:/ &&
3073 $rawline !~ /^\+[A-Z]:\t\S/) {
3074 if (WARN("MAINTAINERS_STYLE",
3075 "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) &&
3076 $fix) {
3077 $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
3078 }
3079 }
3080# check MAINTAINERS entries for the right ordering too
3081 my $preferred_order = 'MRLSWQBCPTFXNK';
3082 if ($rawline =~ /^\+[A-Z]:/ &&
3083 $prevrawline =~ /^[\+ ][A-Z]:/) {
3084 $rawline =~ /^\+([A-Z]):\s*(.*)/;
3085 my $cur = $1;
3086 my $curval = $2;
3087 $prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/;
3088 my $prev = $1;
3089 my $prevval = $2;
3090 my $curindex = index($preferred_order, $cur);
3091 my $previndex = index($preferred_order, $prev);
3092 if ($curindex < 0) {
3093 WARN("MAINTAINERS_STYLE",
3094 "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr);
3095 } else {
3096 if ($previndex >= 0 && $curindex < $previndex) {
3097 WARN("MAINTAINERS_STYLE",
3098 "Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n" . $hereprev);
3099 } elsif ((($prev eq 'F' && $cur eq 'F') ||
3100 ($prev eq 'X' && $cur eq 'X')) &&
3101 ($prevval cmp $curval) > 0) {
3102 WARN("MAINTAINERS_STYLE",
3103 "Misordered MAINTAINERS entry - list file patterns in alphabetic order\n" . $hereprev);
3104 }
3105 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04003106 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003107 }
3108
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003109# discourage the use of boolean for type definition attributes of Kconfig options
3110 if ($realfile =~ /Kconfig/ &&
3111 $line =~ /^\+\s*\bboolean\b/) {
3112 WARN("CONFIG_TYPE_BOOLEAN",
3113 "Use of boolean is deprecated, please use bool instead.\n" . $herecurr);
3114 }
3115
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003116 if (($realfile =~ /Makefile.*/ || $realfile =~ /Kbuild.*/) &&
3117 ($line =~ /\+(EXTRA_[A-Z]+FLAGS).*/)) {
3118 my $flag = $1;
3119 my $replacement = {
3120 'EXTRA_AFLAGS' => 'asflags-y',
3121 'EXTRA_CFLAGS' => 'ccflags-y',
3122 'EXTRA_CPPFLAGS' => 'cppflags-y',
3123 'EXTRA_LDFLAGS' => 'ldflags-y',
3124 };
3125
3126 WARN("DEPRECATED_VARIABLE",
3127 "Use of $flag is deprecated, please use \`$replacement->{$flag} instead.\n" . $herecurr) if ($replacement->{$flag});
3128 }
Javier B Perez5eecd882016-06-14 16:47:27 -05003129# Kconfig use tabs and no spaces in line
Anas Nashif34ffa152016-10-18 18:17:58 -04003130 if ($realfile =~ /Kconfig/ && $rawline =~ /^\+ /) {
Javier B Perez5eecd882016-06-14 16:47:27 -05003131 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3132 WARN("LEADING_SPACE",
3133 "please, no spaces at the start of a line\n" . $herevet);
3134 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003135
3136# check for DT compatible documentation
3137 if (defined $root &&
3138 (($realfile =~ /\.dtsi?$/ && $line =~ /^\+\s*compatible\s*=\s*\"/) ||
3139 ($realfile =~ /\.[ch]$/ && $line =~ /^\+.*\.compatible\s*=\s*\"/))) {
3140
3141 my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
3142
Antony Pavlov824519532019-05-09 16:40:56 +03003143 my $dt_path = $root . "/dts/bindings/";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003144 my $vp_file = $dt_path . "vendor-prefixes.txt";
3145
3146 foreach my $compat (@compats) {
3147 my $compat2 = $compat;
3148 $compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/;
3149 my $compat3 = $compat;
3150 $compat3 =~ s/\,([a-z]*)[0-9]*\-/\,$1<\.\*>\-/;
3151 `grep -Erq "$compat|$compat2|$compat3" $dt_path`;
3152 if ( $? >> 8 ) {
3153 WARN("UNDOCUMENTED_DT_STRING",
3154 "DT compatible string \"$compat\" appears un-documented -- check $dt_path\n" . $herecurr);
3155 }
3156
3157 next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
3158 my $vendor = $1;
Stephanos Ioannidis95c6da02020-05-05 09:20:51 +09003159 `grep -Eq "^$vendor\\b" $vp_file`;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003160 if ( $? >> 8 ) {
3161 WARN("UNDOCUMENTED_DT_STRING",
3162 "DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
3163 }
3164 }
3165 }
3166
Peter Bigot5b10fac2020-03-26 11:16:33 -05003167# check for using SPDX license tag at beginning of files
3168 if ($realline == $checklicenseline) {
3169 if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
3170 $checklicenseline = 2;
3171 } elsif ($rawline =~ /^\+/) {
3172 my $comment = "";
3173 if ($realfile =~ /\.(h|s|S)$/) {
3174 $comment = '/*';
3175 } elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
3176 $comment = '//';
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003177 } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05003178 $comment = '#';
3179 } elsif ($realfile =~ /\.rst$/) {
3180 $comment = '..';
3181 }
3182
3183# check SPDX comment style for .[chsS] files
3184 if ($realfile =~ /\.[chsS]$/ &&
3185 $rawline =~ /SPDX-License-Identifier:/ &&
3186 $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
3187 WARN("SPDX_LICENSE_TAG",
3188 "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
3189 }
3190
3191 if ($comment !~ /^$/ &&
3192 $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
3193 WARN("SPDX_LICENSE_TAG",
3194 "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
3195 } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
3196 my $spdx_license = $1;
3197 if (!is_SPDX_License_valid($spdx_license)) {
3198 WARN("SPDX_LICENSE_TAG",
3199 "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
3200 }
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003201 if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
3202 not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
3203 my $msg_level = \&WARN;
3204 $msg_level = \&CHK if ($file);
3205 if (&{$msg_level}("SPDX_LICENSE_TAG",
3206
3207 "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) &&
3208 $fix) {
3209 $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
3210 }
3211 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05003212 }
3213 }
3214 }
3215
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003216# check we are in a valid source file if not then ignore this hunk
Anas Nashif1eb244c2017-10-01 17:06:36 -04003217 next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003218
Peter Bigot5b10fac2020-03-26 11:16:33 -05003219# check for using SPDX-License-Identifier on the wrong line number
3220 if ($realline != $checklicenseline &&
3221 $rawline =~ /\bSPDX-License-Identifier:/ &&
3222 substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
3223 WARN("SPDX_LICENSE_TAG",
3224 "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
3225 }
3226
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003227# line length limit (with some exclusions)
3228#
3229# There are a few types of lines that may extend beyond $max_line_length:
3230# logging functions like pr_info that end in a string
3231# lines with a single string
3232# #defines that are a single string
Peter Bigot5b10fac2020-03-26 11:16:33 -05003233# lines with an RFC3986 like URL
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003234#
3235# There are 3 different line length message types:
Anas Nashif1eb244c2017-10-01 17:06:36 -04003236# LONG_LINE_COMMENT a comment starts before but extends beyond $max_line_length
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003237# LONG_LINE_STRING a string starts before but extends beyond $max_line_length
3238# LONG_LINE all other lines longer than $max_line_length
3239#
3240# if LONG_LINE is ignored, the other 2 types are also ignored
3241#
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003242
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003243 if ($line =~ /^\+/ && $length > $max_line_length) {
3244 my $msg_type = "LONG_LINE";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003245
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003246 # Check the allowed long line types first
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003247
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003248 # logging functions that end in a string that starts
3249 # before $max_line_length
3250 if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ &&
3251 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3252 $msg_type = "";
3253
3254 # lines with only strings (w/ possible termination)
3255 # #defines with only strings
3256 } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
3257 $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
3258 $msg_type = "";
3259
Peter Bigot5b10fac2020-03-26 11:16:33 -05003260 # More special cases
3261 } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ ||
3262 $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) {
3263 $msg_type = "";
3264
3265 # URL ($rawline is used in case the URL is in a comment)
3266 } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05003267 $msg_type = "";
3268
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003269 # Otherwise set the alternate message types
3270
3271 # a comment starts before $max_line_length
3272 } elsif ($line =~ /($;[\s$;]*)$/ &&
3273 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3274 $msg_type = "LONG_LINE_COMMENT"
3275
3276 # a quoted string starts before $max_line_length
3277 } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ &&
3278 length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
3279 $msg_type = "LONG_LINE_STRING"
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003280 }
3281
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003282 if ($msg_type ne "" &&
3283 (show_type("LONG_LINE") || show_type($msg_type))) {
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003284 my $msg_level = \&WARN;
3285 $msg_level = \&CHK if ($file);
3286 &{$msg_level}($msg_type,
3287 "line length of $length exceeds $max_line_length columns\n" . $herecurr);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003288 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003289 }
3290
3291# check for adding lines without a newline.
3292 if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
3293 WARN("MISSING_EOF_NEWLINE",
3294 "adding a line without newline at end of file\n" . $herecurr);
3295 }
3296
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003297# check we are in a valid source file C or perl if not then ignore this hunk
3298 next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
3299
3300# at the beginning of a line any tabs must come first and anything
Gerard Marull-Paretasabaa5b82022-06-16 15:50:44 +02003301# more than $tabsize must use tabs, except multi-line macros which may start
3302# with spaces on empty lines
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003303 if ($rawline =~ /^\+\s* \t\s*\S/ ||
Gerard Marull-Paretasabaa5b82022-06-16 15:50:44 +02003304 $rawline =~ /^\+\s* \s*/ &&
3305 $rawline !~ /^\+\s*\\$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003306 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3307 $rpt_cleaners = 1;
3308 if (ERROR("CODE_INDENT",
3309 "code indent should use tabs where possible\n" . $herevet) &&
3310 $fix) {
3311 $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
3312 }
3313 }
3314
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003315# check for repeated words separated by a single space
3316 if ($rawline =~ /^\+/) {
3317 while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) {
3318
3319 my $first = $1;
3320 my $second = $2;
3321
3322 if ($first =~ /(?:struct|union|enum)/) {
3323 pos($rawline) += length($first) + length($second) + 1;
3324 next;
3325 }
3326
3327 next if ($first ne $second);
3328 next if ($first eq 'long');
3329
3330 if (WARN("REPEATED_WORD",
3331 "Possible repeated word: '$first'\n" . $herecurr) &&
3332 $fix) {
3333 $fixed[$fixlinenr] =~ s/\b$first $second\b/$first/;
3334 }
3335 }
3336
3337 # if it's a repeated word on consecutive lines in a comment block
3338 if ($prevline =~ /$;+\s*$/ &&
3339 $prevrawline =~ /($word_pattern)\s*$/) {
3340 my $last_word = $1;
3341 if ($rawline =~ /^\+\s*\*\s*$last_word /) {
3342 if (WARN("REPEATED_WORD",
3343 "Possible repeated word: '$last_word'\n" . $hereprev) &&
3344 $fix) {
3345 $fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/;
3346 }
3347 }
3348 }
3349 }
3350
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003351# check for space before tabs.
3352 if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
3353 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3354 if (WARN("SPACE_BEFORE_TAB",
3355 "please, no space before tabs\n" . $herevet) &&
3356 $fix) {
3357 while ($fixed[$fixlinenr] =~
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003358 s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {}
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003359 while ($fixed[$fixlinenr] =~
3360 s/(^\+.*) +\t/$1\t/) {}
3361 }
3362 }
3363
Peter Bigot5b10fac2020-03-26 11:16:33 -05003364# check for assignments on the start of a line
3365 if ($sline =~ /^\+\s+($Assignment)[^=]/) {
3366 CHK("ASSIGNMENT_CONTINUATIONS",
3367 "Assignment operator '$1' should be on the previous line\n" . $hereprev);
3368 }
3369
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003370# check for && or || at the start of a line
3371 if ($rawline =~ /^\+\s*(&&|\|\|)/) {
3372 CHK("LOGICAL_CONTINUATIONS",
3373 "Logical continuations should be on the previous line\n" . $hereprev);
3374 }
3375
Anas Nashif0f3d5472016-11-07 15:57:57 -05003376# check indentation starts on a tab stop
Peter Bigot5b10fac2020-03-26 11:16:33 -05003377 if ($perl_version_ok &&
3378 $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05003379 my $indent = length($1);
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003380 if ($indent % $tabsize) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05003381 if (WARN("TABSTOP",
3382 "Statements should start on a tabstop\n" . $herecurr) &&
3383 $fix) {
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003384 $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e;
Anas Nashif0f3d5472016-11-07 15:57:57 -05003385 }
3386 }
3387 }
3388
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003389# check multi-line statement indentation matches previous line
Peter Bigot5b10fac2020-03-26 11:16:33 -05003390 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04003391 $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003392 $prevline =~ /^\+(\t*)(.*)$/;
3393 my $oldindent = $1;
3394 my $rest = $2;
3395
3396 my $pos = pos_last_openparen($rest);
3397 if ($pos >= 0) {
3398 $line =~ /^(\+| )([ \t]*)/;
3399 my $newindent = $2;
3400
3401 my $goodtabindent = $oldindent .
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003402 "\t" x ($pos / $tabsize) .
3403 " " x ($pos % $tabsize);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003404 my $goodspaceindent = $oldindent . " " x $pos;
3405
3406 if ($newindent ne $goodtabindent &&
3407 $newindent ne $goodspaceindent) {
3408
3409 if (CHK("PARENTHESIS_ALIGNMENT",
3410 "Alignment should match open parenthesis\n" . $hereprev) &&
3411 $fix && $line =~ /^\+/) {
3412 $fixed[$fixlinenr] =~
3413 s/^\+[ \t]*/\+$goodtabindent/;
3414 }
3415 }
3416 }
3417 }
3418
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003419# check for space after cast like "(int) foo" or "(struct foo) bar"
3420# avoid checking a few false positives:
3421# "sizeof(<type>)" or "__alignof__(<type>)"
3422# function pointer declarations like "(*foo)(int) = bar;"
3423# structure definitions like "(struct foo) { 0 };"
3424# multiline macros that define functions
3425# known attributes or the __attribute__ keyword
3426 if ($line =~ /^\+(.*)\(\s*$Type\s*\)([ \t]++)((?![={]|\\$|$Attribute|__attribute__))/ &&
3427 (!defined($1) || $1 !~ /\b(?:sizeof|__alignof__)\s*$/)) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003428 if (CHK("SPACING",
3429 "No space is necessary after a cast\n" . $herecurr) &&
3430 $fix) {
3431 $fixed[$fixlinenr] =~
3432 s/(\(\s*$Type\s*\))[ \t]+/$1/;
3433 }
3434 }
3435
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003436# Block comment styles
3437# Networking with an initial /*
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003438 if ($realfile =~ m@^(drivers/net/|net/)@ &&
3439 $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
3440 $rawline =~ /^\+[ \t]*\*/ &&
3441 $realline > 2) {
3442 WARN("NETWORKING_BLOCK_COMMENT_STYLE",
3443 "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
3444 }
3445
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003446# Block comments use * on subsequent lines
3447 if ($prevline =~ /$;[ \t]*$/ && #ends in comment
3448 $prevrawline =~ /^\+.*?\/\*/ && #starting /*
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003449 $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */
3450 $rawline =~ /^\+/ && #line is new
3451 $rawline !~ /^\+[ \t]*\*/) { #no leading *
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003452 WARN("BLOCK_COMMENT_STYLE",
3453 "Block comments use * on subsequent lines\n" . $hereprev);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003454 }
3455
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003456# Block comments use */ on trailing lines
3457 if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003458 $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/
3459 $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/
3460 $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003461 WARN("BLOCK_COMMENT_STYLE",
3462 "Block comments use a trailing */ on a separate line\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003463 }
3464
Anas Nashif0f3d5472016-11-07 15:57:57 -05003465# Block comment * alignment
3466 if ($prevline =~ /$;[ \t]*$/ && #ends in comment
3467 $line =~ /^\+[ \t]*$;/ && #leading comment
3468 $rawline =~ /^\+[ \t]*\*/ && #leading *
3469 (($prevrawline =~ /^\+.*?\/\*/ && #leading /*
3470 $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
3471 $prevrawline =~ /^\+[ \t]*\*/)) { #leading *
3472 my $oldindent;
3473 $prevrawline =~ m@^\+([ \t]*/?)\*@;
3474 if (defined($1)) {
3475 $oldindent = expand_tabs($1);
3476 } else {
3477 $prevrawline =~ m@^\+(.*/?)\*@;
3478 $oldindent = expand_tabs($1);
3479 }
3480 $rawline =~ m@^\+([ \t]*)\*@;
3481 my $newindent = $1;
3482 $newindent = expand_tabs($newindent);
3483 if (length($oldindent) ne length($newindent)) {
3484 WARN("BLOCK_COMMENT_STYLE",
3485 "Block comments should align the * on each line\n" . $hereprev);
3486 }
3487 }
3488
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003489# check for missing blank lines after struct/union declarations
3490# with exceptions for various attributes and macros
3491 if ($prevline =~ /^[\+ ]};?\s*$/ &&
3492 $line =~ /^\+/ &&
3493 !($line =~ /^\+\s*$/ ||
3494 $line =~ /^\+\s*EXPORT_SYMBOL/ ||
3495 $line =~ /^\+\s*MODULE_/i ||
3496 $line =~ /^\+\s*\#\s*(?:end|elif|else)/ ||
3497 $line =~ /^\+[a-z_]*init/ ||
3498 $line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
3499 $line =~ /^\+\s*DECLARE/ ||
Peter Bigot5b10fac2020-03-26 11:16:33 -05003500 $line =~ /^\+\s*builtin_[\w_]*driver/ ||
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003501 $line =~ /^\+\s*__setup/)) {
3502 if (CHK("LINE_SPACING",
3503 "Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
3504 $fix) {
3505 fix_insert_line($fixlinenr, "\+");
3506 }
3507 }
3508
3509# check for multiple consecutive blank lines
3510 if ($prevline =~ /^[\+ ]\s*$/ &&
3511 $line =~ /^\+\s*$/ &&
3512 $last_blank_line != ($linenr - 1)) {
3513 if (CHK("LINE_SPACING",
3514 "Please don't use multiple blank lines\n" . $hereprev) &&
3515 $fix) {
3516 fix_delete_line($fixlinenr, $rawline);
3517 }
3518
3519 $last_blank_line = $linenr;
3520 }
3521
3522# check for missing blank lines after declarations
3523 if ($sline =~ /^\+\s+\S/ && #Not at char 1
3524 # actual declarations
3525 ($prevline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
3526 # function pointer declarations
3527 $prevline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
3528 # foo bar; where foo is some local typedef or #define
3529 $prevline =~ /^\+\s+$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
3530 # known declaration macros
3531 $prevline =~ /^\+\s+$declaration_macros/) &&
3532 # for "else if" which can look like "$Ident $Ident"
3533 !($prevline =~ /^\+\s+$c90_Keywords\b/ ||
3534 # other possible extensions of declaration lines
3535 $prevline =~ /(?:$Compare|$Assignment|$Operators)\s*$/ ||
3536 # not starting a section or a macro "\" extended line
3537 $prevline =~ /(?:\{\s*|\\)$/) &&
3538 # looks like a declaration
3539 !($sline =~ /^\+\s+$Declare\s*$Ident\s*[=,;:\[]/ ||
3540 # function pointer declarations
3541 $sline =~ /^\+\s+$Declare\s*\(\s*\*\s*$Ident\s*\)\s*[=,;:\[\(]/ ||
3542 # foo bar; where foo is some local typedef or #define
Marcus Shawcroftf62e6812017-02-19 09:15:57 +00003543 $sline =~ /^\+\s+(?:volatile\s+)?$Ident(?:\s+|\s*\*\s*)$Ident\s*[=,;\[]/ ||
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003544 # known declaration macros
3545 $sline =~ /^\+\s+$declaration_macros/ ||
3546 # start of struct or union or enum
Martin Åbergc4766f92024-04-17 13:01:25 +02003547 $sline =~ /^\+\s+(?:volatile\s+)?(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003548 # start or end of block or continuation of declaration
3549 $sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
3550 # bitfield continuation
3551 $sline =~ /^\+\s+$Ident\s*:\s*\d+\s*[,;]/ ||
3552 # other possible extensions of declaration lines
3553 $sline =~ /^\+\s+\(?\s*(?:$Compare|$Assignment|$Operators)/) &&
3554 # indentation of previous and current line are the same
3555 (($prevline =~ /\+(\s+)\S/) && $sline =~ /^\+$1\S/)) {
3556 if (WARN("LINE_SPACING",
3557 "Missing a blank line after declarations\n" . $hereprev) &&
3558 $fix) {
3559 fix_insert_line($fixlinenr, "\+");
3560 }
3561 }
3562
3563# check for spaces at the beginning of a line.
3564# Exceptions:
3565# 1) within comments
3566# 2) indented preprocessor commands
3567# 3) hanging labels
Gerard Marull-Paretasabaa5b82022-06-16 15:50:44 +02003568# 4) empty lines in multi-line macros
3569 if ($rawline =~ /^\+ / && $line !~ /^\+ *(?:$;|#|$Ident:)/ &&
3570 $rawline !~ /^\+\s+\\$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003571 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
3572 if (WARN("LEADING_SPACE",
3573 "please, no spaces at the start of a line\n" . $herevet) &&
3574 $fix) {
3575 $fixed[$fixlinenr] =~ s/^\+([ \t]+)/"\+" . tabify($1)/e;
3576 }
3577 }
3578
3579# check we are in a valid C source file if not then ignore this hunk
3580 next if ($realfile !~ /\.(h|c)$/);
3581
Peter Bigot5b10fac2020-03-26 11:16:33 -05003582# check for unusual line ending [ or (
3583 if ($line =~ /^\+.*([\[\(])\s*$/) {
3584 CHK("OPEN_ENDED_LINE",
3585 "Lines should not end with a '$1'\n" . $herecurr);
3586 }
3587
Anas Nashif1eb244c2017-10-01 17:06:36 -04003588# check if this appears to be the start function declaration, save the name
3589 if ($sline =~ /^\+\{\s*$/ &&
3590 $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
3591 $context_function = $1;
3592 }
3593
3594# check if this appears to be the end of function declaration
3595 if ($sline =~ /^\+\}\s*$/) {
3596 undef $context_function;
3597 }
3598
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003599# check indentation of any line with a bare else
3600# (but not if it is a multiple line "if (foo) return bar; else return baz;")
3601# if the previous line is a break or return and is indented 1 tab more...
3602 if ($sline =~ /^\+([\t]+)(?:}[ \t]*)?else(?:[ \t]*{)?\s*$/) {
3603 my $tabs = length($1) + 1;
3604 if ($prevline =~ /^\+\t{$tabs,$tabs}break\b/ ||
3605 ($prevline =~ /^\+\t{$tabs,$tabs}return\b/ &&
3606 defined $lines[$linenr] &&
3607 $lines[$linenr] !~ /^[ \+]\t{$tabs,$tabs}return/)) {
3608 WARN("UNNECESSARY_ELSE",
3609 "else is not generally useful after a break or return\n" . $hereprev);
3610 }
3611 }
3612
3613# check indentation of a line with a break;
3614# if the previous line is a goto or return and is indented the same # of tabs
3615 if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
3616 my $tabs = $1;
3617 if ($prevline =~ /^\+$tabs(?:goto|return)\b/) {
3618 WARN("UNNECESSARY_BREAK",
3619 "break is not useful after a goto or return\n" . $hereprev);
3620 }
3621 }
3622
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003623# check for RCS/CVS revision markers
3624 if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
3625 WARN("CVS_KEYWORD",
3626 "CVS style keyword markers, these will _not_ be updated\n". $herecurr);
3627 }
3628
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003629# check for old HOTPLUG __dev<foo> section markings
3630 if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) {
3631 WARN("HOTPLUG_SECTION",
3632 "Using $1 is unnecessary\n" . $herecurr);
3633 }
3634
3635# Check for potential 'bare' types
3636 my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
3637 $realline_next);
3638#print "LINE<$line>\n";
Anas Nashif1eb244c2017-10-01 17:06:36 -04003639 if ($linenr > $suppress_statement &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003640 $realcnt && $sline =~ /.\s*\S/) {
3641 ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
3642 ctx_statement_block($linenr, $realcnt, 0);
3643 $stat =~ s/\n./\n /g;
3644 $cond =~ s/\n./\n /g;
3645
3646#print "linenr<$linenr> <$stat>\n";
3647 # If this statement has no statement boundaries within
3648 # it there is no point in retrying a statement scan
3649 # until we hit end of it.
3650 my $frag = $stat; $frag =~ s/;+\s*$//;
3651 if ($frag !~ /(?:{|;)/) {
3652#print "skip<$line_nr_next>\n";
3653 $suppress_statement = $line_nr_next;
3654 }
3655
3656 # Find the real next line.
3657 $realline_next = $line_nr_next;
3658 if (defined $realline_next &&
3659 (!defined $lines[$realline_next - 1] ||
3660 substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
3661 $realline_next++;
3662 }
3663
3664 my $s = $stat;
3665 $s =~ s/{.*$//s;
3666
3667 # Ignore goto labels.
3668 if ($s =~ /$Ident:\*$/s) {
3669
3670 # Ignore functions being called
3671 } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
3672
3673 } elsif ($s =~ /^.\s*else\b/s) {
3674
3675 # declarations always start with types
3676 } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
3677 my $type = $1;
3678 $type =~ s/\s+/ /g;
3679 possible($type, "A:" . $s);
3680
3681 # definitions in global scope can only start with types
3682 } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
3683 possible($1, "B:" . $s);
3684 }
3685
3686 # any (foo ... *) is a pointer cast, and foo is a type
3687 while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
3688 possible($1, "C:" . $s);
3689 }
3690
3691 # Check for any sort of function declaration.
3692 # int foo(something bar, other baz);
3693 # void (*store_gdt)(x86_descr_ptr *);
3694 if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
3695 my ($name_len) = length($1);
3696
3697 my $ctx = $s;
3698 substr($ctx, 0, $name_len + 1, '');
3699 $ctx =~ s/\)[^\)]*$//;
3700
3701 for my $arg (split(/\s*,\s*/, $ctx)) {
3702 if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
3703
3704 possible($1, "D:" . $s);
3705 }
3706 }
3707 }
3708
3709 }
3710
3711#
3712# Checks which may be anchored in the context.
3713#
3714
3715# Check for switch () and associated case and default
3716# statements should be at the same indent.
3717 if ($line=~/\bswitch\s*\(.*\)/) {
3718 my $err = '';
3719 my $sep = '';
3720 my @ctx = ctx_block_outer($linenr, $realcnt);
3721 shift(@ctx);
3722 for my $ctx (@ctx) {
3723 my ($clen, $cindent) = line_stats($ctx);
3724 if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
3725 $indent != $cindent) {
3726 $err .= "$sep$ctx\n";
3727 $sep = '';
3728 } else {
3729 $sep = "[...]\n";
3730 }
3731 }
3732 if ($err ne '') {
3733 ERROR("SWITCH_CASE_INDENT_LEVEL",
3734 "switch and case should be at the same indent\n$hereline$err");
3735 }
3736 }
3737
3738# if/while/etc brace do not go on next line, unless defining a do while loop,
3739# or if that brace on the next line is for something else
Krzysztof Chruścińskie90d69f2023-12-13 17:03:58 +01003740 if ($line =~ /(.*)\b((?:if|while|for|switch|(?:[A-Z_]+|)FOR_EACH(?!_NONEMPTY_TERM)[A-Z_]+)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003741 my $pre_ctx = "$1$2";
3742
3743 my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
3744
3745 if ($line =~ /^\+\t{6,}/) {
3746 WARN("DEEP_INDENTATION",
3747 "Too many leading tabs - consider code refactoring\n" . $herecurr);
3748 }
3749
3750 my $ctx_cnt = $realcnt - $#ctx - 1;
3751 my $ctx = join("\n", @ctx);
3752
3753 my $ctx_ln = $linenr;
3754 my $ctx_skip = $realcnt;
3755
3756 while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
3757 defined $lines[$ctx_ln - 1] &&
3758 $lines[$ctx_ln - 1] =~ /^-/)) {
3759 ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
3760 $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
3761 $ctx_ln++;
3762 }
3763
3764 #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
3765 #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
3766
3767 if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
3768 ERROR("OPEN_BRACE",
3769 "that open brace { should be on the previous line\n" .
3770 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
3771 }
3772 if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
3773 $ctx =~ /\)\s*\;\s*$/ &&
3774 defined $lines[$ctx_ln - 1])
3775 {
3776 my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
3777 if ($nindent > $indent) {
3778 WARN("TRAILING_SEMICOLON",
3779 "trailing semicolon indicates no statements, indent implies otherwise\n" .
3780 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
3781 }
3782 }
3783 }
3784
3785# Check relative indent for conditionals and blocks.
Krzysztof Chruścińskie90d69f2023-12-13 17:03:58 +01003786 if ($line =~ /\b(?:(?:if|while|for|(?:[A-Z_]+|)FOR_EACH(?!_NONEMPTY_TERM|_IDX|_FIXED_ARG|_IDX_FIXED_ARG)[A-Z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003787 ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
3788 ctx_statement_block($linenr, $realcnt, 0)
3789 if (!defined $stat);
3790 my ($s, $c) = ($stat, $cond);
3791
3792 substr($s, 0, length($c), '');
3793
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003794 # remove inline comments
3795 $s =~ s/$;/ /g;
3796 $c =~ s/$;/ /g;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003797
3798 # Find out how long the conditional actually is.
3799 my @newlines = ($c =~ /\n/gs);
3800 my $cond_lines = 1 + $#newlines;
3801
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003802 # Make sure we remove the line prefixes as we have
3803 # none on the first line, and are going to readd them
3804 # where necessary.
3805 $s =~ s/\n./\n/gs;
3806 while ($s =~ /\n\s+\\\n/) {
3807 $cond_lines += $s =~ s/\n\s+\\\n/\n/g;
3808 }
3809
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003810 # We want to check the first line inside the block
3811 # starting at the end of the conditional, so remove:
3812 # 1) any blank line termination
3813 # 2) any opening brace { on end of the line
3814 # 3) any do (...) {
3815 my $continuation = 0;
3816 my $check = 0;
3817 $s =~ s/^.*\bdo\b//;
3818 $s =~ s/^\s*{//;
3819 if ($s =~ s/^\s*\\//) {
3820 $continuation = 1;
3821 }
3822 if ($s =~ s/^\s*?\n//) {
3823 $check = 1;
3824 $cond_lines++;
3825 }
3826
3827 # Also ignore a loop construct at the end of a
3828 # preprocessor statement.
3829 if (($prevline =~ /^.\s*#\s*define\s/ ||
3830 $prevline =~ /\\\s*$/) && $continuation == 0) {
3831 $check = 0;
3832 }
3833
3834 my $cond_ptr = -1;
3835 $continuation = 0;
3836 while ($cond_ptr != $cond_lines) {
3837 $cond_ptr = $cond_lines;
3838
3839 # If we see an #else/#elif then the code
3840 # is not linear.
3841 if ($s =~ /^\s*\#\s*(?:else|elif)/) {
3842 $check = 0;
3843 }
3844
3845 # Ignore:
3846 # 1) blank lines, they should be at 0,
3847 # 2) preprocessor lines, and
3848 # 3) labels.
3849 if ($continuation ||
3850 $s =~ /^\s*?\n/ ||
3851 $s =~ /^\s*#\s*?/ ||
3852 $s =~ /^\s*$Ident\s*:/) {
3853 $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
3854 if ($s =~ s/^.*?\n//) {
3855 $cond_lines++;
3856 }
3857 }
3858 }
3859
3860 my (undef, $sindent) = line_stats("+" . $s);
3861 my $stat_real = raw_line($linenr, $cond_lines);
3862
3863 # Check if either of these lines are modified, else
3864 # this is not this patch's fault.
3865 if (!defined($stat_real) ||
3866 $stat !~ /^\+/ && $stat_real !~ /^\+/) {
3867 $check = 0;
3868 }
3869 if (defined($stat_real) && $cond_lines > 1) {
3870 $stat_real = "[...]\n$stat_real";
3871 }
3872
3873 #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
3874
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003875 if ($check && $s ne '' &&
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003876 (($sindent % $tabsize) != 0 ||
Anas Nashifcbfb62c2015-10-14 06:08:54 -04003877 ($sindent < $indent) ||
Anas Nashif1eb244c2017-10-01 17:06:36 -04003878 ($sindent == $indent &&
3879 ($s !~ /^\s*(?:\}|\{|else\b)/)) ||
Peter A. Bigote49e3c82020-08-10 10:37:32 -05003880 ($sindent > $indent + $tabsize))) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003881 WARN("SUSPECT_CODE_INDENT",
3882 "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
3883 }
3884 }
3885
3886 # Track the 'values' across context and added lines.
3887 my $opline = $line; $opline =~ s/^./ /;
3888 my ($curr_values, $curr_vars) =
3889 annotate_values($opline . "\n", $prev_values);
3890 $curr_values = $prev_values . $curr_values;
3891 if ($dbg_values) {
3892 my $outline = $opline; $outline =~ s/\t/ /g;
3893 print "$linenr > .$outline\n";
3894 print "$linenr > $curr_values\n";
3895 print "$linenr > $curr_vars\n";
3896 }
3897 $prev_values = substr($curr_values, -1);
3898
3899#ignore lines not being added
3900 next if ($line =~ /^[^\+]/);
3901
Anas Nashif1eb244c2017-10-01 17:06:36 -04003902# check for dereferences that span multiple lines
3903 if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ &&
3904 $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) {
3905 $prevline =~ /($Lval\s*(?:\.|->))\s*$/;
3906 my $ref = $1;
3907 $line =~ /^.\s*($Lval)/;
3908 $ref .= $1;
3909 $ref =~ s/\s//g;
3910 WARN("MULTILINE_DEREFERENCE",
3911 "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev);
3912 }
3913
Anas Nashif0f3d5472016-11-07 15:57:57 -05003914# check for declarations of signed or unsigned without int
3915 while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
3916 my $type = $1;
3917 my $var = $2;
3918 $var = "" if (!defined $var);
3919 if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
3920 my $sign = $1;
3921 my $pointer = $2;
3922
3923 $pointer = "" if (!defined $pointer);
3924
3925 if (WARN("UNSPECIFIED_INT",
3926 "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) &&
3927 $fix) {
3928 my $decl = trim($sign) . " int ";
3929 my $comp_pointer = $pointer;
3930 $comp_pointer =~ s/\s//g;
3931 $decl .= $comp_pointer;
3932 $decl = rtrim($decl) if ($var eq "");
3933 $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
3934 }
3935 }
3936 }
3937
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003938# TEST: allow direct testing of the type matcher.
3939 if ($dbg_type) {
3940 if ($line =~ /^.\s*$Declare\s*$/) {
3941 ERROR("TEST_TYPE",
3942 "TEST: is type\n" . $herecurr);
3943 } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
3944 ERROR("TEST_NOT_TYPE",
3945 "TEST: is not type ($1 is)\n". $herecurr);
3946 }
3947 next;
3948 }
3949# TEST: allow direct testing of the attribute matcher.
3950 if ($dbg_attr) {
3951 if ($line =~ /^.\s*$Modifier\s*$/) {
3952 ERROR("TEST_ATTR",
3953 "TEST: is attr\n" . $herecurr);
3954 } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
3955 ERROR("TEST_NOT_ATTR",
3956 "TEST: is not attr ($1 is)\n". $herecurr);
3957 }
3958 next;
3959 }
3960
3961# check for initialisation to aggregates open brace on the next line
3962 if ($line =~ /^.\s*{/ &&
3963 $prevline =~ /(?:^|[^=])=\s*$/) {
3964 if (ERROR("OPEN_BRACE",
3965 "that open brace { should be on the previous line\n" . $hereprev) &&
3966 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
3967 fix_delete_line($fixlinenr - 1, $prevrawline);
3968 fix_delete_line($fixlinenr, $rawline);
3969 my $fixedline = $prevrawline;
3970 $fixedline =~ s/\s*=\s*$/ = {/;
3971 fix_insert_line($fixlinenr, $fixedline);
3972 $fixedline = $line;
Anas Nashif1eb244c2017-10-01 17:06:36 -04003973 $fixedline =~ s/^(.\s*)\{\s*/$1/;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07003974 fix_insert_line($fixlinenr, $fixedline);
3975 }
3976 }
3977
3978#
3979# Checks which are anchored on the added line.
3980#
3981
3982# check for malformed paths in #include statements (uses RAW line)
3983 if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
3984 my $path = $1;
3985 if ($path =~ m{//}) {
3986 ERROR("MALFORMED_INCLUDE",
3987 "malformed #include filename\n" . $herecurr);
3988 }
3989 if ($path =~ "^uapi/" && $realfile =~ m@\binclude/uapi/@) {
3990 ERROR("UAPI_INCLUDE",
3991 "No #include in ...include/uapi/... should use a uapi/ path prefix\n" . $herecurr);
3992 }
3993 }
3994
3995# no C99 // comments
3996 if ($line =~ m{//}) {
3997 if (ERROR("C99_COMMENTS",
3998 "do not use C99 // comments\n" . $herecurr) &&
3999 $fix) {
4000 my $line = $fixed[$fixlinenr];
4001 if ($line =~ /\/\/(.*)$/) {
4002 my $comment = trim($1);
4003 $fixed[$fixlinenr] =~ s@\/\/(.*)$@/\* $comment \*/@;
4004 }
4005 }
4006 }
4007 # Remove C99 comments.
4008 $line =~ s@//.*@@;
4009 $opline =~ s@//.*@@;
4010
4011# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
4012# the whole statement.
4013#print "APW <$lines[$realline_next - 1]>\n";
4014 if (defined $realline_next &&
4015 exists $lines[$realline_next - 1] &&
4016 !defined $suppress_export{$realline_next} &&
4017 ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
4018 $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
4019 # Handle definitions which produce identifiers with
4020 # a prefix:
4021 # XXX(foo);
4022 # EXPORT_SYMBOL(something_foo);
4023 my $name = $1;
4024 if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
4025 $name =~ /^${Ident}_$2/) {
4026#print "FOO C name<$name>\n";
4027 $suppress_export{$realline_next} = 1;
4028
4029 } elsif ($stat !~ /(?:
4030 \n.}\s*$|
4031 ^.DEFINE_$Ident\(\Q$name\E\)|
4032 ^.DECLARE_$Ident\(\Q$name\E\)|
4033 ^.LIST_HEAD\(\Q$name\E\)|
4034 ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
4035 \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
4036 )/x) {
4037#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
4038 $suppress_export{$realline_next} = 2;
4039 } else {
4040 $suppress_export{$realline_next} = 1;
4041 }
4042 }
4043 if (!defined $suppress_export{$linenr} &&
4044 $prevline =~ /^.\s*$/ &&
4045 ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
4046 $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
4047#print "FOO B <$lines[$linenr - 1]>\n";
4048 $suppress_export{$linenr} = 2;
4049 }
4050 if (defined $suppress_export{$linenr} &&
4051 $suppress_export{$linenr} == 2) {
4052 WARN("EXPORT_SYMBOL",
4053 "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
4054 }
4055
4056# check for global initialisers.
Anas Nashif76b09132016-02-20 13:53:35 -05004057 if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004058 if (ERROR("GLOBAL_INITIALISERS",
Anas Nashif76b09132016-02-20 13:53:35 -05004059 "do not initialise globals to $1\n" . $herecurr) &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004060 $fix) {
Anas Nashif76b09132016-02-20 13:53:35 -05004061 $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004062 }
4063 }
4064# check for static initialisers.
Anas Nashif76b09132016-02-20 13:53:35 -05004065 if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004066 if (ERROR("INITIALISED_STATIC",
Anas Nashif76b09132016-02-20 13:53:35 -05004067 "do not initialise statics to $1\n" .
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004068 $herecurr) &&
4069 $fix) {
Anas Nashif76b09132016-02-20 13:53:35 -05004070 $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004071 }
4072 }
4073
4074# check for misordered declarations of char/short/int/long with signed/unsigned
4075 while ($sline =~ m{(\b$TypeMisordered\b)}g) {
4076 my $tmp = trim($1);
4077 WARN("MISORDERED_TYPE",
4078 "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
4079 }
4080
Peter Bigot5b10fac2020-03-26 11:16:33 -05004081# check for unnecessary <signed> int declarations of short/long/long long
4082 while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
4083 my $type = trim($1);
4084 next if ($type !~ /\bint\b/);
4085 next if ($type !~ /\b(?:short|long\s+long|long)\b/);
4086 my $new_type = $type;
4087 $new_type =~ s/\b\s*int\s*\b/ /;
4088 $new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
4089 $new_type =~ s/^const\s+//;
4090 $new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
4091 $new_type = "const $new_type" if ($type =~ /^const\b/);
4092 $new_type =~ s/\s+/ /g;
4093 $new_type = trim($new_type);
4094 if (WARN("UNNECESSARY_INT",
4095 "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) &&
4096 $fix) {
4097 $fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
4098 }
4099 }
4100
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004101# check for static const char * arrays.
4102 if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
4103 WARN("STATIC_CONST_CHAR_ARRAY",
4104 "static const char * array should probably be static const char * const\n" .
4105 $herecurr);
Peter Bigot5b10fac2020-03-26 11:16:33 -05004106 }
4107
4108# check for initialized const char arrays that should be static const
4109 if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
4110 if (WARN("STATIC_CONST_CHAR_ARRAY",
4111 "const array should probably be static const\n" . $herecurr) &&
4112 $fix) {
4113 $fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
4114 }
4115 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004116
4117# check for static char foo[] = "bar" declarations.
4118 if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
4119 WARN("STATIC_CONST_CHAR_ARRAY",
4120 "static char array declaration should probably be static const char\n" .
4121 $herecurr);
Peter Bigot5b10fac2020-03-26 11:16:33 -05004122 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004123
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004124# check for const <foo> const where <foo> is not a pointer or array type
4125 if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
4126 my $found = $1;
4127 if ($sline =~ /\bconst\s+\Q$found\E\s+const\b\s*\*/) {
4128 WARN("CONST_CONST",
4129 "'const $found const *' should probably be 'const $found * const'\n" . $herecurr);
4130 } elsif ($sline !~ /\bconst\s+\Q$found\E\s+const\s+\w+\s*\[/) {
4131 WARN("CONST_CONST",
4132 "'const $found const' should probably be 'const $found'\n" . $herecurr);
4133 }
4134 }
4135
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004136# check for non-global char *foo[] = {"bar", ...} declarations.
4137 if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
4138 WARN("STATIC_CONST_CHAR_ARRAY",
4139 "char * array declaration might be better as static const\n" .
4140 $herecurr);
4141 }
4142
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004143# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
4144 if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
4145 my $array = $1;
4146 if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) {
4147 my $array_div = $1;
4148 if (WARN("ARRAY_SIZE",
4149 "Prefer ARRAY_SIZE($array)\n" . $herecurr) &&
4150 $fix) {
4151 $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/;
4152 }
4153 }
4154 }
4155
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004156# check for function declarations without arguments like "int foo()"
Peter A. Bigote49e3c82020-08-10 10:37:32 -05004157 if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004158 if (ERROR("FUNCTION_WITHOUT_ARGS",
4159 "Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
4160 $fix) {
4161 $fixed[$fixlinenr] =~ s/(\b($Type)\s+($Ident))\s*\(\s*\)/$2 $3(void)/;
4162 }
4163 }
4164
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004165# check for new typedefs, only function parameters and sparse annotations
4166# make sense.
Yong Cong Sin20373622023-07-07 10:18:23 +08004167 if ($realfile =~ /\/include\/zephyr\/posix\/*.h/) {
4168 if ($line =~ /\btypedef\s/ &&
4169 $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
4170 $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
4171 $line !~ /\b$typeTypedefs\b/ &&
4172 $line !~ /\b__bitwise\b/) {
4173 WARN("NEW_TYPEDEFS",
4174 "do not add new typedefs\n" . $herecurr);
4175 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004176 }
4177
4178# * goes on variable not on type
4179 # (char*[ const])
4180 while ($line =~ m{(\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\))}g) {
4181 #print "AA<$1>\n";
4182 my ($ident, $from, $to) = ($1, $2, $2);
4183
4184 # Should start with a space.
4185 $to =~ s/^(\S)/ $1/;
4186 # Should not end with a space.
4187 $to =~ s/\s+$//;
4188 # '*'s should not have spaces between.
4189 while ($to =~ s/\*\s+\*/\*\*/) {
4190 }
4191
4192## print "1: from<$from> to<$to> ident<$ident>\n";
4193 if ($from ne $to) {
4194 if (ERROR("POINTER_LOCATION",
4195 "\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr) &&
4196 $fix) {
4197 my $sub_from = $ident;
4198 my $sub_to = $ident;
4199 $sub_to =~ s/\Q$from\E/$to/;
4200 $fixed[$fixlinenr] =~
4201 s@\Q$sub_from\E@$sub_to@;
4202 }
4203 }
4204 }
4205 while ($line =~ m{(\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident))}g) {
4206 #print "BB<$1>\n";
4207 my ($match, $from, $to, $ident) = ($1, $2, $2, $3);
4208
4209 # Should start with a space.
4210 $to =~ s/^(\S)/ $1/;
4211 # Should not end with a space.
4212 $to =~ s/\s+$//;
4213 # '*'s should not have spaces between.
4214 while ($to =~ s/\*\s+\*/\*\*/) {
4215 }
4216 # Modifiers should have spaces.
4217 $to =~ s/(\b$Modifier$)/$1 /;
4218
4219## print "2: from<$from> to<$to> ident<$ident>\n";
4220 if ($from ne $to && $ident !~ /^$Modifier$/) {
4221 if (ERROR("POINTER_LOCATION",
4222 "\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr) &&
4223 $fix) {
4224
4225 my $sub_from = $match;
4226 my $sub_to = $match;
4227 $sub_to =~ s/\Q$from\E/$to/;
4228 $fixed[$fixlinenr] =~
4229 s@\Q$sub_from\E@$sub_to@;
4230 }
4231 }
4232 }
4233
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004234# avoid BUG() or BUG_ON()
4235 if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04004236 my $msg_level = \&WARN;
4237 $msg_level = \&CHK if ($file);
4238 &{$msg_level}("AVOID_BUG",
4239 "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004240 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004241
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004242# avoid LINUX_VERSION_CODE
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004243 if ($line =~ /\bLINUX_VERSION_CODE\b/) {
4244 WARN("LINUX_VERSION_CODE",
4245 "LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
4246 }
4247
4248# check for uses of printk_ratelimit
4249 if ($line =~ /\bprintk_ratelimit\s*\(/) {
4250 WARN("PRINTK_RATELIMITED",
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004251 "Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004252 }
4253
Peter Bigot5b10fac2020-03-26 11:16:33 -05004254# printk should use KERN_* levels
4255 if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) {
4256 WARN("PRINTK_WITHOUT_KERN_LEVEL",
4257 "printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004258 }
4259
4260 if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
4261 my $orig = $1;
4262 my $level = lc($orig);
4263 $level = "warn" if ($level eq "warning");
4264 my $level2 = $level;
4265 $level2 = "dbg" if ($level eq "debug");
4266 WARN("PREFER_PR_LEVEL",
4267 "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
4268 }
4269
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004270 if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
4271 my $orig = $1;
4272 my $level = lc($orig);
4273 $level = "warn" if ($level eq "warning");
4274 $level = "dbg" if ($level eq "debug");
4275 WARN("PREFER_DEV_LEVEL",
4276 "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr);
4277 }
4278
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004279# ENOSYS means "bad syscall nr" and nothing else. This will have a small
4280# number of false positives, but assembly files are not checked, so at
4281# least the arch entry code will not trigger this warning.
4282 if ($line =~ /\bENOSYS\b/) {
4283 WARN("ENOSYS",
4284 "ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr);
4285 }
4286
Peter A. Bigote49e3c82020-08-10 10:37:32 -05004287# ENOTSUPP is not a standard error code and should be avoided in new patches.
4288# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP.
4289# Similarly to ENOSYS warning a small number of false positives is expected.
4290 if (!$file && $line =~ /\bENOTSUPP\b/) {
4291 if (WARN("ENOTSUPP",
4292 "ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr) &&
4293 $fix) {
4294 $fixed[$fixlinenr] =~ s/\bENOTSUPP\b/EOPNOTSUPP/;
4295 }
4296 }
4297
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004298# function brace can't be on same line, except for #defines of do while,
4299# or if closed on same line
Peter Bigot5b10fac2020-03-26 11:16:33 -05004300 if ($perl_version_ok &&
4301 $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
4302 $sline !~ /\#\s*define\b.*do\s*\{/ &&
4303 $sline !~ /}/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004304 if (ERROR("OPEN_BRACE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05004305 "open brace '{' following function definitions go on the next line\n" . $herecurr) &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004306 $fix) {
4307 fix_delete_line($fixlinenr, $rawline);
4308 my $fixed_line = $rawline;
4309 $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/;
4310 my $line1 = $1;
4311 my $line2 = $2;
4312 fix_insert_line($fixlinenr, ltrim($line1));
4313 fix_insert_line($fixlinenr, "\+{");
4314 if ($line2 !~ /^\s*$/) {
4315 fix_insert_line($fixlinenr, "\+\t" . trim($line2));
4316 }
4317 }
4318 }
4319
4320# open braces for enum, union and struct go on the same line.
4321 if ($line =~ /^.\s*{/ &&
4322 $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
4323 if (ERROR("OPEN_BRACE",
4324 "open brace '{' following $1 go on the same line\n" . $hereprev) &&
4325 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
4326 fix_delete_line($fixlinenr - 1, $prevrawline);
4327 fix_delete_line($fixlinenr, $rawline);
4328 my $fixedline = rtrim($prevrawline) . " {";
4329 fix_insert_line($fixlinenr, $fixedline);
4330 $fixedline = $rawline;
Anas Nashif1eb244c2017-10-01 17:06:36 -04004331 $fixedline =~ s/^(.\s*)\{\s*/$1\t/;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004332 if ($fixedline !~ /^\+\s*$/) {
4333 fix_insert_line($fixlinenr, $fixedline);
4334 }
4335 }
4336 }
4337
4338# missing space after union, struct or enum definition
4339 if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident){1,2}[=\{]/) {
4340 if (WARN("SPACING",
4341 "missing space after $1 definition\n" . $herecurr) &&
4342 $fix) {
4343 $fixed[$fixlinenr] =~
4344 s/^(.\s*(?:typedef\s+)?(?:enum|union|struct)(?:\s+$Ident){1,2})([=\{])/$1 $2/;
4345 }
4346 }
4347
4348# Function pointer declarations
4349# check spacing between type, funcptr, and args
4350# canonical declaration is "type (*funcptr)(args...)"
4351 if ($line =~ /^.\s*($Declare)\((\s*)\*(\s*)($Ident)(\s*)\)(\s*)\(/) {
4352 my $declare = $1;
4353 my $pre_pointer_space = $2;
4354 my $post_pointer_space = $3;
4355 my $funcname = $4;
4356 my $post_funcname_space = $5;
4357 my $pre_args_space = $6;
4358
4359# the $Declare variable will capture all spaces after the type
4360# so check it for a missing trailing missing space but pointer return types
4361# don't need a space so don't warn for those.
4362 my $post_declare_space = "";
4363 if ($declare =~ /(\s+)$/) {
4364 $post_declare_space = $1;
4365 $declare = rtrim($declare);
4366 }
4367 if ($declare !~ /\*$/ && $post_declare_space =~ /^$/) {
4368 WARN("SPACING",
4369 "missing space after return type\n" . $herecurr);
4370 $post_declare_space = " ";
4371 }
4372
4373# unnecessary space "type (*funcptr)(args...)"
4374# This test is not currently implemented because these declarations are
4375# equivalent to
4376# int foo(int bar, ...)
4377# and this is form shouldn't/doesn't generate a checkpatch warning.
4378#
4379# elsif ($declare =~ /\s{2,}$/) {
4380# WARN("SPACING",
4381# "Multiple spaces after return type\n" . $herecurr);
4382# }
4383
4384# unnecessary space "type ( *funcptr)(args...)"
4385 if (defined $pre_pointer_space &&
4386 $pre_pointer_space =~ /^\s/) {
4387 WARN("SPACING",
4388 "Unnecessary space after function pointer open parenthesis\n" . $herecurr);
4389 }
4390
4391# unnecessary space "type (* funcptr)(args...)"
4392 if (defined $post_pointer_space &&
4393 $post_pointer_space =~ /^\s/) {
4394 WARN("SPACING",
4395 "Unnecessary space before function pointer name\n" . $herecurr);
4396 }
4397
4398# unnecessary space "type (*funcptr )(args...)"
4399 if (defined $post_funcname_space &&
4400 $post_funcname_space =~ /^\s/) {
4401 WARN("SPACING",
4402 "Unnecessary space after function pointer name\n" . $herecurr);
4403 }
4404
4405# unnecessary space "type (*funcptr) (args...)"
4406 if (defined $pre_args_space &&
4407 $pre_args_space =~ /^\s/) {
4408 WARN("SPACING",
4409 "Unnecessary space before function pointer arguments\n" . $herecurr);
4410 }
4411
4412 if (show_type("SPACING") && $fix) {
4413 $fixed[$fixlinenr] =~
4414 s/^(.\s*)$Declare\s*\(\s*\*\s*$Ident\s*\)\s*\(/$1 . $declare . $post_declare_space . '(*' . $funcname . ')('/ex;
4415 }
4416 }
4417
4418# check for spacing round square brackets; allowed:
4419# 1. with a type on the left -- int [] a;
4420# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
4421# 3. inside a curly brace -- = { [0...10] = 5 }
Rubin Gerritsenf78c51d2024-06-07 14:57:32 +02004422# 4. inside macro arguments, example: #define HCI_ERR(err) [err] = #err
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004423 while ($line =~ /(.*?\s)\[/g) {
4424 my ($where, $prefix) = ($-[1], $1);
4425 if ($prefix !~ /$Type\s+$/ &&
4426 ($where != 0 || $prefix !~ /^.\s+$/) &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05004427 $prefix !~ /[{,:]\s+$/ &&
Rubin Gerritsenf78c51d2024-06-07 14:57:32 +02004428 $prefix !~ /\#define\s+.+\s+$/ &&
Anas Nashif98c50de2015-11-06 18:23:35 -05004429 $prefix !~ /:\s+$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004430 if (ERROR("BRACKET_SPACE",
4431 "space prohibited before open square bracket '['\n" . $herecurr) &&
4432 $fix) {
4433 $fixed[$fixlinenr] =~
4434 s/^(\+.*?)\s+\[/$1\[/;
4435 }
4436 }
4437 }
4438
4439# check for spaces between functions and their parentheses.
4440 while ($line =~ /($Ident)\s+\(/g) {
4441 my $name = $1;
4442 my $ctx_before = substr($line, 0, $-[1]);
4443 my $ctx = "$ctx_before$name";
4444
4445 # Ignore those directives where spaces _are_ permitted.
4446 if ($name =~ /^(?:
4447 if|for|while|switch|return|case|
4448 volatile|__volatile__|
4449 __attribute__|format|__extension__|
4450 asm|__asm__)$/x)
4451 {
4452 # cpp #define statements have non-optional spaces, ie
4453 # if there is a space between the name and the open
4454 # parenthesis it is simply not a parameter group.
4455 } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
4456
4457 # cpp #elif statement condition may start with a (
4458 } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
4459
4460 # If this whole things ends with a type its most
4461 # likely a typedef for a function.
4462 } elsif ($ctx =~ /$Type$/) {
4463
4464 } else {
4465 if (WARN("SPACING",
4466 "space prohibited between function name and open parenthesis '('\n" . $herecurr) &&
4467 $fix) {
4468 $fixed[$fixlinenr] =~
4469 s/\b$name\s+\(/$name\(/;
4470 }
4471 }
4472 }
4473
4474# Check operator spacing.
4475 if (!($line=~/\#\s*include/)) {
4476 my $fixed_line = "";
4477 my $line_fixed = 0;
4478
4479 my $ops = qr{
4480 <<=|>>=|<=|>=|==|!=|
4481 \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
4482 =>|->|<<|>>|<|>|=|!|~|
4483 &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
4484 \?:|\?|:
4485 }x;
4486 my @elements = split(/($ops|;)/, $opline);
4487
4488## print("element count: <" . $#elements . ">\n");
4489## foreach my $el (@elements) {
4490## print("el: <$el>\n");
4491## }
4492
4493 my @fix_elements = ();
4494 my $off = 0;
4495
4496 foreach my $el (@elements) {
4497 push(@fix_elements, substr($rawline, $off, length($el)));
4498 $off += length($el);
4499 }
4500
4501 $off = 0;
4502
4503 my $blank = copy_spacing($opline);
4504 my $last_after = -1;
4505
4506 for (my $n = 0; $n < $#elements; $n += 2) {
4507
4508 my $good = $fix_elements[$n] . $fix_elements[$n + 1];
4509
4510## print("n: <$n> good: <$good>\n");
4511
4512 $off += length($elements[$n]);
4513
4514 # Pick up the preceding and succeeding characters.
4515 my $ca = substr($opline, 0, $off);
4516 my $cc = '';
4517 if (length($opline) >= ($off + length($elements[$n + 1]))) {
4518 $cc = substr($opline, $off + length($elements[$n + 1]));
4519 }
4520 my $cb = "$ca$;$cc";
4521
4522 my $a = '';
4523 $a = 'V' if ($elements[$n] ne '');
4524 $a = 'W' if ($elements[$n] =~ /\s$/);
4525 $a = 'C' if ($elements[$n] =~ /$;$/);
4526 $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
4527 $a = 'O' if ($elements[$n] eq '');
4528 $a = 'E' if ($ca =~ /^\s*$/);
4529
4530 my $op = $elements[$n + 1];
4531
4532 my $c = '';
4533 if (defined $elements[$n + 2]) {
4534 $c = 'V' if ($elements[$n + 2] ne '');
4535 $c = 'W' if ($elements[$n + 2] =~ /^\s/);
4536 $c = 'C' if ($elements[$n + 2] =~ /^$;/);
4537 $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
4538 $c = 'O' if ($elements[$n + 2] eq '');
4539 $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
4540 } else {
4541 $c = 'E';
4542 }
4543
4544 my $ctx = "${a}x${c}";
4545
4546 my $at = "(ctx:$ctx)";
4547
4548 my $ptr = substr($blank, 0, $off) . "^";
4549 my $hereptr = "$hereline$ptr\n";
4550
4551 # Pull out the value of this operator.
4552 my $op_type = substr($curr_values, $off + 1, 1);
4553
4554 # Get the full operator variant.
4555 my $opv = $op . substr($curr_vars, $off, 1);
4556
4557 # Ignore operators passed as parameters.
4558 if ($op_type ne 'V' &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004559 $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004560
4561# # Ignore comments
4562# } elsif ($op =~ /^$;+$/) {
4563
4564 # ; should have either the end of line or a space or \ after it
4565 } elsif ($op eq ';') {
4566 if ($ctx !~ /.x[WEBC]/ &&
4567 $cc !~ /^\\/ && $cc !~ /^;/) {
4568 if (ERROR("SPACING",
4569 "space required after that '$op' $at\n" . $hereptr)) {
4570 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
4571 $line_fixed = 1;
4572 }
4573 }
4574
4575 # // is a comment
4576 } elsif ($op eq '//') {
4577
4578 # : when part of a bitfield
4579 } elsif ($opv eq ':B') {
4580 # skip the bitfield test for now
4581
4582 # No spaces for:
4583 # ->
4584 } elsif ($op eq '->') {
4585 if ($ctx =~ /Wx.|.xW/) {
4586 if (ERROR("SPACING",
4587 "spaces prohibited around that '$op' $at\n" . $hereptr)) {
4588 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4589 if (defined $fix_elements[$n + 2]) {
4590 $fix_elements[$n + 2] =~ s/^\s+//;
4591 }
4592 $line_fixed = 1;
4593 }
4594 }
4595
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004596 # , must not have a space before and must have a space on the right.
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004597 } elsif ($op eq ',') {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004598 my $rtrim_before = 0;
4599 my $space_after = 0;
4600 if ($ctx =~ /Wx./) {
4601 if (ERROR("SPACING",
4602 "space prohibited before that '$op' $at\n" . $hereptr)) {
4603 $line_fixed = 1;
4604 $rtrim_before = 1;
4605 }
4606 }
Anas Nashife7ee0832016-02-20 14:13:16 -05004607 if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/ && $cc !~ /^\)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004608 if (ERROR("SPACING",
4609 "space required after that '$op' $at\n" . $hereptr)) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004610 $line_fixed = 1;
4611 $last_after = $n;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004612 $space_after = 1;
4613 }
4614 }
4615 if ($rtrim_before || $space_after) {
4616 if ($rtrim_before) {
4617 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4618 } else {
4619 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
4620 }
4621 if ($space_after) {
4622 $good .= " ";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004623 }
4624 }
4625
4626 # '*' as part of a type definition -- reported already.
4627 } elsif ($opv eq '*_') {
4628 #warn "'*' is part of type\n";
4629
4630 # unary operators should have a space before and
4631 # none after. May be left adjacent to another
4632 # unary operator, or a cast
4633 } elsif ($op eq '!' || $op eq '~' ||
4634 $opv eq '*U' || $opv eq '-U' ||
4635 $opv eq '&U' || $opv eq '&&U') {
4636 if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
4637 if (ERROR("SPACING",
4638 "space required before that '$op' $at\n" . $hereptr)) {
4639 if ($n != $last_after + 2) {
4640 $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]);
4641 $line_fixed = 1;
4642 }
4643 }
4644 }
4645 if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
4646 # A unary '*' may be const
4647
4648 } elsif ($ctx =~ /.xW/) {
4649 if (ERROR("SPACING",
4650 "space prohibited after that '$op' $at\n" . $hereptr)) {
4651 $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]);
4652 if (defined $fix_elements[$n + 2]) {
4653 $fix_elements[$n + 2] =~ s/^\s+//;
4654 }
4655 $line_fixed = 1;
4656 }
4657 }
4658
4659 # unary ++ and unary -- are allowed no space on one side.
4660 } elsif ($op eq '++' or $op eq '--') {
4661 if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
4662 if (ERROR("SPACING",
4663 "space required one side of that '$op' $at\n" . $hereptr)) {
4664 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
4665 $line_fixed = 1;
4666 }
4667 }
4668 if ($ctx =~ /Wx[BE]/ ||
4669 ($ctx =~ /Wx./ && $cc =~ /^;/)) {
4670 if (ERROR("SPACING",
4671 "space prohibited before that '$op' $at\n" . $hereptr)) {
4672 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4673 $line_fixed = 1;
4674 }
4675 }
4676 if ($ctx =~ /ExW/) {
4677 if (ERROR("SPACING",
4678 "space prohibited after that '$op' $at\n" . $hereptr)) {
4679 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
4680 if (defined $fix_elements[$n + 2]) {
4681 $fix_elements[$n + 2] =~ s/^\s+//;
4682 }
4683 $line_fixed = 1;
4684 }
4685 }
4686
4687 # << and >> may either have or not have spaces both sides
4688 } elsif ($op eq '<<' or $op eq '>>' or
4689 $op eq '&' or $op eq '^' or $op eq '|' or
4690 $op eq '+' or $op eq '-' or
4691 $op eq '*' or $op eq '/' or
4692 $op eq '%')
4693 {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004694 if ($check) {
4695 if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) {
4696 if (CHK("SPACING",
4697 "spaces preferred around that '$op' $at\n" . $hereptr)) {
4698 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4699 $fix_elements[$n + 2] =~ s/^\s+//;
4700 $line_fixed = 1;
4701 }
4702 } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) {
4703 if (CHK("SPACING",
4704 "space preferred before that '$op' $at\n" . $hereptr)) {
4705 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]);
4706 $line_fixed = 1;
4707 }
4708 }
4709 } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004710 if (ERROR("SPACING",
4711 "need consistent spacing around '$op' $at\n" . $hereptr)) {
4712 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4713 if (defined $fix_elements[$n + 2]) {
4714 $fix_elements[$n + 2] =~ s/^\s+//;
4715 }
4716 $line_fixed = 1;
4717 }
4718 }
4719
4720 # A colon needs no spaces before when it is
4721 # terminating a case value or a label.
4722 } elsif ($opv eq ':C' || $opv eq ':L') {
4723 if ($ctx =~ /Wx./) {
4724 if (ERROR("SPACING",
4725 "space prohibited before that '$op' $at\n" . $hereptr)) {
4726 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4727 $line_fixed = 1;
4728 }
4729 }
4730
4731 # All the others need spaces both sides.
4732 } elsif ($ctx !~ /[EWC]x[CWE]/) {
4733 my $ok = 0;
4734
4735 # Ignore email addresses <foo@bar>
4736 if (($op eq '<' &&
4737 $cc =~ /^\S+\@\S+>/) ||
4738 ($op eq '>' &&
4739 $ca =~ /<\S+\@\S+$/))
4740 {
Peter A. Bigote49e3c82020-08-10 10:37:32 -05004741 $ok = 1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004742 }
4743
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004744 # for asm volatile statements
4745 # ignore a colon with another
4746 # colon immediately before or after
4747 if (($op eq ':') &&
4748 ($ca =~ /:$/ || $cc =~ /^:/)) {
4749 $ok = 1;
4750 }
4751
Gerard Marull-Paretas6a273832022-03-07 16:03:08 +01004752 # some macros require a separator
4753 # argument to be in parentheses,
4754 # e.g. (||).
4755 if ($ca =~ /\($/ || $cc =~ /^\)/) {
4756 $ok = 1;
4757 }
4758
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004759 # messages are ERROR, but ?: are CHK
4760 if ($ok == 0) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04004761 my $msg_level = \&ERROR;
4762 $msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004763
Anas Nashif1eb244c2017-10-01 17:06:36 -04004764 if (&{$msg_level}("SPACING",
4765 "spaces required around that '$op' $at\n" . $hereptr)) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004766 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4767 if (defined $fix_elements[$n + 2]) {
4768 $fix_elements[$n + 2] =~ s/^\s+//;
4769 }
4770 $line_fixed = 1;
4771 }
4772 }
4773 }
4774 $off += length($elements[$n + 1]);
4775
4776## print("n: <$n> GOOD: <$good>\n");
4777
4778 $fixed_line = $fixed_line . $good;
4779 }
4780
4781 if (($#elements % 2) == 0) {
4782 $fixed_line = $fixed_line . $fix_elements[$#elements];
4783 }
4784
4785 if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) {
4786 $fixed[$fixlinenr] = $fixed_line;
4787 }
4788
4789
4790 }
4791
4792# check for whitespace before a non-naked semicolon
4793 if ($line =~ /^\+.*\S\s+;\s*$/) {
4794 if (WARN("SPACING",
4795 "space prohibited before semicolon\n" . $herecurr) &&
4796 $fix) {
4797 1 while $fixed[$fixlinenr] =~
4798 s/^(\+.*\S)\s+;/$1;/;
4799 }
4800 }
4801
4802# check for multiple assignments
4803 if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
4804 CHK("MULTIPLE_ASSIGNMENTS",
4805 "multiple assignments should be avoided\n" . $herecurr);
4806 }
4807
4808## # check for multiple declarations, allowing for a function declaration
4809## # continuation.
4810## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
4811## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
4812##
4813## # Remove any bracketed sections to ensure we do not
4814## # falsly report the parameters of functions.
4815## my $ln = $line;
4816## while ($ln =~ s/\([^\(\)]*\)//g) {
4817## }
4818## if ($ln =~ /,/) {
4819## WARN("MULTIPLE_DECLARATION",
4820## "declaring multiple variables together should be avoided\n" . $herecurr);
4821## }
4822## }
4823
4824#need space before brace following if, while, etc
Anas Nashif0f3d5472016-11-07 15:57:57 -05004825 if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
Peter Bigot5b10fac2020-03-26 11:16:33 -05004826 $line =~ /\b(?:else|do)\{/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004827 if (ERROR("SPACING",
4828 "space required before the open brace '{'\n" . $herecurr) &&
4829 $fix) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05004830 $fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004831 }
4832 }
4833
4834## # check for blank lines before declarations
4835## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ &&
4836## $prevrawline =~ /^.\s*$/) {
4837## WARN("SPACING",
4838## "No blank lines before declarations\n" . $hereprev);
4839## }
4840##
4841
4842# closing brace should have a space following it when it has anything
4843# on the line
Peter Bigot5b10fac2020-03-26 11:16:33 -05004844 if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004845 if (ERROR("SPACING",
4846 "space required after that close brace '}'\n" . $herecurr) &&
4847 $fix) {
4848 $fixed[$fixlinenr] =~
4849 s/}((?!(?:,|;|\)))\S)/} $1/;
4850 }
4851 }
4852
4853# check spacing on square brackets
4854 if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
4855 if (ERROR("SPACING",
4856 "space prohibited after that open square bracket '['\n" . $herecurr) &&
4857 $fix) {
4858 $fixed[$fixlinenr] =~
4859 s/\[\s+/\[/;
4860 }
4861 }
4862 if ($line =~ /\s\]/) {
4863 if (ERROR("SPACING",
4864 "space prohibited before that close square bracket ']'\n" . $herecurr) &&
4865 $fix) {
4866 $fixed[$fixlinenr] =~
4867 s/\s+\]/\]/;
4868 }
4869 }
4870
4871# check spacing on parentheses
4872 if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
4873 $line !~ /for\s*\(\s+;/) {
4874 if (ERROR("SPACING",
4875 "space prohibited after that open parenthesis '('\n" . $herecurr) &&
4876 $fix) {
4877 $fixed[$fixlinenr] =~
4878 s/\(\s+/\(/;
4879 }
4880 }
4881 if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
4882 $line !~ /for\s*\(.*;\s+\)/ &&
4883 $line !~ /:\s+\)/) {
4884 if (ERROR("SPACING",
4885 "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
4886 $fix) {
4887 $fixed[$fixlinenr] =~
4888 s/\s+\)/\)/;
4889 }
4890 }
4891
4892# check unnecessary parentheses around addressof/dereference single $Lvals
4893# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar
4894
4895 while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004896 my $var = $1;
4897 if (CHK("UNNECESSARY_PARENTHESES",
4898 "Unnecessary parentheses around $var\n" . $herecurr) &&
4899 $fix) {
4900 $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/;
4901 }
4902 }
4903
4904# check for unnecessary parentheses around function pointer uses
4905# ie: (foo->bar)(); should be foo->bar();
4906# but not "if (foo->bar) (" to avoid some false positives
4907 if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) {
4908 my $var = $2;
4909 if (CHK("UNNECESSARY_PARENTHESES",
4910 "Unnecessary parentheses around function pointer $var\n" . $herecurr) &&
4911 $fix) {
4912 my $var2 = deparenthesize($var);
4913 $var2 =~ s/\s//g;
4914 $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/;
4915 }
4916 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004917
Anas Nashif1eb244c2017-10-01 17:06:36 -04004918# check for unnecessary parentheses around comparisons in if uses
Peter Bigot5b10fac2020-03-26 11:16:33 -05004919# when !drivers/staging or command-line uses --strict
4920 if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
4921 $perl_version_ok && defined($stat) &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04004922 $stat =~ /(^.\s*if\s*($balanced_parens))/) {
4923 my $if_stat = $1;
4924 my $test = substr($2, 1, -1);
4925 my $herectx;
4926 while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) {
4927 my $match = $1;
4928 # avoid parentheses around potential macro args
4929 next if ($match =~ /^\s*\w+\s*$/);
4930 if (!defined($herectx)) {
4931 $herectx = $here . "\n";
4932 my $cnt = statement_rawlines($if_stat);
4933 for (my $n = 0; $n < $cnt; $n++) {
4934 my $rl = raw_line($linenr, $n);
4935 $herectx .= $rl . "\n";
4936 last if $rl =~ /^[ \+].*\{/;
4937 }
4938 }
4939 CHK("UNNECESSARY_PARENTHESES",
4940 "Unnecessary parentheses around '$match'\n" . $herectx);
4941 }
4942 }
4943
Joe Perches6cdeefc2021-06-30 18:56:22 -07004944# check that goto labels aren't indented (allow a single space indentation)
4945# and ignore bitfield definitions like foo:1
4946# Strictly, labels can have whitespace after the identifier and before the :
4947# but this is not allowed here as many ?: uses would appear to be labels
4948 if ($sline =~ /^.\s+[A-Za-z_][A-Za-z\d_]*:(?!\s*\d+)/ &&
4949 $sline !~ /^. [A-Za-z\d_][A-Za-z\d_]*:/ &&
4950 $sline !~ /^.\s+default:/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004951 if (WARN("INDENTED_LABEL",
4952 "labels should not be indented\n" . $herecurr) &&
4953 $fix) {
4954 $fixed[$fixlinenr] =~
4955 s/^(.)\s+/$1/;
4956 }
4957 }
4958
4959# return is not a function
4960 if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
4961 my $spacing = $1;
Peter Bigot5b10fac2020-03-26 11:16:33 -05004962 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004963 $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
4964 my $value = $1;
4965 $value = deparenthesize($value);
4966 if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
4967 ERROR("RETURN_PARENTHESES",
4968 "return is not a function, parentheses are not required\n" . $herecurr);
4969 }
4970 } elsif ($spacing !~ /\s+/) {
4971 ERROR("SPACING",
4972 "space required before the open parenthesis '('\n" . $herecurr);
4973 }
4974 }
4975
4976# unnecessary return in a void function
4977# at end-of-function, with the previous line a single leading tab, then return;
4978# and the line before that not a goto label target like "out:"
4979 if ($sline =~ /^[ \+]}\s*$/ &&
4980 $prevline =~ /^\+\treturn\s*;\s*$/ &&
4981 $linenr >= 3 &&
4982 $lines[$linenr - 3] =~ /^[ +]/ &&
4983 $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) {
4984 WARN("RETURN_VOID",
4985 "void function return statements are not generally useful\n" . $hereprev);
4986 }
4987
4988# if statements using unnecessary parentheses - ie: if ((foo == bar))
Peter Bigot5b10fac2020-03-26 11:16:33 -05004989 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004990 $line =~ /\bif\s*((?:\(\s*){2,})/) {
4991 my $openparens = $1;
4992 my $count = $openparens =~ tr@\(@\(@;
4993 my $msg = "";
4994 if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
4995 my $comp = $4; #Not $1 because of $LvalOrFunc
4996 $msg = " - maybe == should be = ?" if ($comp eq "==");
4997 WARN("UNNECESSARY_PARENTHESES",
4998 "Unnecessary parentheses$msg\n" . $herecurr);
4999 }
5000 }
5001
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005002# comparisons with a constant or upper case identifier on the left
5003# avoid cases like "foo + BAR < baz"
5004# only fix matches surrounded by parentheses to avoid incorrect
5005# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
Peter Bigot5b10fac2020-03-26 11:16:33 -05005006 if ($perl_version_ok &&
Christopher Friedta3725412024-01-19 07:37:33 -05005007 !($line =~ /^\+(.*)($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*(.*)($Constant|[A-Z_][A-Z0-9_]*)(.*)/) &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005008 $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
5009 my $lead = $1;
5010 my $const = $2;
5011 my $comp = $3;
5012 my $to = $4;
5013 my $newcomp = $comp;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005014 if ($lead !~ /(?:$Operators|\.)\s*$/ &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005015 $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
5016 WARN("CONSTANT_COMPARISON",
5017 "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
5018 $fix) {
5019 if ($comp eq "<") {
5020 $newcomp = ">";
5021 } elsif ($comp eq "<=") {
5022 $newcomp = ">=";
5023 } elsif ($comp eq ">") {
5024 $newcomp = "<";
5025 } elsif ($comp eq ">=") {
5026 $newcomp = "<=";
5027 }
5028 $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/;
5029 }
5030 }
5031
5032# Return of what appears to be an errno should normally be negative
5033 if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005034 my $name = $1;
5035 if ($name ne 'EOF' && $name ne 'ERROR') {
Christopher Friedt6e27b7d2023-07-05 17:36:49 -04005036 # only print this warning if not dealing with 'lib/posix/*.c'
5037 if ($realfile =~ /.*\/lib\/posix\/*.c/) {
5038 WARN("USE_NEGATIVE_ERRNO",
5039 "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
5040 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005041 }
5042 }
5043
5044# Need a space before open parenthesis after if, while etc
5045 if ($line =~ /\b(if|while|for|switch)\(/) {
5046 if (ERROR("SPACING",
5047 "space required before the open parenthesis '('\n" . $herecurr) &&
5048 $fix) {
5049 $fixed[$fixlinenr] =~
5050 s/\b(if|while|for|switch)\(/$1 \(/;
5051 }
5052 }
5053
5054# Check for illegal assignment in if conditional -- and check for trailing
5055# statements after the conditional.
5056 if ($line =~ /do\s*(?!{)/) {
5057 ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
5058 ctx_statement_block($linenr, $realcnt, 0)
5059 if (!defined $stat);
5060 my ($stat_next) = ctx_statement_block($line_nr_next,
5061 $remain_next, $off_next);
5062 $stat_next =~ s/\n./\n /g;
5063 ##print "stat<$stat> stat_next<$stat_next>\n";
5064
5065 if ($stat_next =~ /^\s*while\b/) {
5066 # If the statement carries leading newlines,
5067 # then count those as offsets.
5068 my ($whitespace) =
5069 ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
5070 my $offset =
5071 statement_rawlines($whitespace) - 1;
5072
5073 $suppress_whiletrailers{$line_nr_next +
5074 $offset} = 1;
5075 }
5076 }
5077 if (!defined $suppress_whiletrailers{$linenr} &&
5078 defined($stat) && defined($cond) &&
5079 $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
5080 my ($s, $c) = ($stat, $cond);
5081
5082 if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005083 if (ERROR("ASSIGN_IN_IF",
5084 "do not use assignment in if condition\n" . $herecurr) &&
5085 $fix && $perl_version_ok) {
5086 if ($rawline =~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=\s*$LvalOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) {
5087 my $space = $1;
5088 my $not = $2;
5089 my $statement = $3;
5090 my $assigned = $4;
5091 my $test = $8;
5092 my $against = $9;
5093 my $brace = $15;
5094 fix_delete_line($fixlinenr, $rawline);
5095 fix_insert_line($fixlinenr, "$space$statement;");
5096 my $newline = "${space}if (";
5097 $newline .= '!' if defined($not);
5098 $newline .= '(' if (defined $not && defined($test) && defined($against));
5099 $newline .= "$assigned";
5100 $newline .= " $test $against" if (defined($test) && defined($against));
5101 $newline .= ')' if (defined $not && defined($test) && defined($against));
5102 $newline .= ')';
5103 $newline .= " {" if (defined($brace));
5104 fix_insert_line($fixlinenr + 1, $newline);
5105 }
5106 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005107 }
5108
5109 # Find out what is on the end of the line after the
5110 # conditional.
5111 substr($s, 0, length($c), '');
5112 $s =~ s/\n.*//g;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005113 $s =~ s/$;//g; # Remove any comments
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005114 if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
5115 $c !~ /}\s*while\s*/)
5116 {
5117 # Find out how long the conditional actually is.
5118 my @newlines = ($c =~ /\n/gs);
5119 my $cond_lines = 1 + $#newlines;
5120 my $stat_real = '';
5121
5122 $stat_real = raw_line($linenr, $cond_lines)
5123 . "\n" if ($cond_lines);
5124 if (defined($stat_real) && $cond_lines > 1) {
5125 $stat_real = "[...]\n$stat_real";
5126 }
5127
5128 ERROR("TRAILING_STATEMENTS",
5129 "trailing statements should be on next line\n" . $herecurr . $stat_real);
5130 }
5131 }
5132
5133# Check for bitwise tests written as boolean
5134 if ($line =~ /
5135 (?:
5136 (?:\[|\(|\&\&|\|\|)
5137 \s*0[xX][0-9]+\s*
5138 (?:\&\&|\|\|)
5139 |
5140 (?:\&\&|\|\|)
5141 \s*0[xX][0-9]+\s*
5142 (?:\&\&|\|\||\)|\])
5143 )/x)
5144 {
5145 WARN("HEXADECIMAL_BOOLEAN_TEST",
5146 "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
5147 }
5148
5149# if and else should not have general statements after it
5150 if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
5151 my $s = $1;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005152 $s =~ s/$;//g; # Remove any comments
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005153 if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
5154 ERROR("TRAILING_STATEMENTS",
5155 "trailing statements should be on next line\n" . $herecurr);
5156 }
5157 }
5158# if should not continue a brace
5159 if ($line =~ /}\s*if\b/) {
5160 ERROR("TRAILING_STATEMENTS",
5161 "trailing statements should be on next line (or did you mean 'else if'?)\n" .
5162 $herecurr);
5163 }
5164# case and default should not have general statements after them
5165 if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
5166 $line !~ /\G(?:
5167 (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
5168 \s*return\s+
5169 )/xg)
5170 {
5171 ERROR("TRAILING_STATEMENTS",
5172 "trailing statements should be on next line\n" . $herecurr);
5173 }
5174
5175 # Check for }<nl>else {, these must be at the same
5176 # indent level to be relevant to each other.
5177 if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
5178 $previndent == $indent) {
5179 if (ERROR("ELSE_AFTER_BRACE",
5180 "else should follow close brace '}'\n" . $hereprev) &&
5181 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
5182 fix_delete_line($fixlinenr - 1, $prevrawline);
5183 fix_delete_line($fixlinenr, $rawline);
5184 my $fixedline = $prevrawline;
5185 $fixedline =~ s/}\s*$//;
5186 if ($fixedline !~ /^\+\s*$/) {
5187 fix_insert_line($fixlinenr, $fixedline);
5188 }
5189 $fixedline = $rawline;
5190 $fixedline =~ s/^(.\s*)else/$1} else/;
5191 fix_insert_line($fixlinenr, $fixedline);
5192 }
5193 }
5194
5195 if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
5196 $previndent == $indent) {
5197 my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
5198
5199 # Find out what is on the end of the line after the
5200 # conditional.
5201 substr($s, 0, length($c), '');
5202 $s =~ s/\n.*//g;
5203
5204 if ($s =~ /^\s*;/) {
5205 if (ERROR("WHILE_AFTER_BRACE",
5206 "while should follow close brace '}'\n" . $hereprev) &&
5207 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
5208 fix_delete_line($fixlinenr - 1, $prevrawline);
5209 fix_delete_line($fixlinenr, $rawline);
5210 my $fixedline = $prevrawline;
5211 my $trailing = $rawline;
5212 $trailing =~ s/^\+//;
5213 $trailing = trim($trailing);
5214 $fixedline =~ s/}\s*$/} $trailing/;
5215 fix_insert_line($fixlinenr, $fixedline);
5216 }
5217 }
5218 }
5219
5220#Specific variable tests
5221 while ($line =~ m{($Constant|$Lval)}g) {
5222 my $var = $1;
5223
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005224#CamelCase
5225 if ($var !~ /^$Constant$/ &&
5226 $var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
5227#Ignore Page<foo> variants
5228 $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05005229#Ignore SI style variants like nS, mV and dB
5230#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
5231 $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005232#Ignore some three character SI units explicitly, like MiB and KHz
5233 $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005234 while ($var =~ m{($Ident)}g) {
5235 my $word = $1;
5236 next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
5237 if ($check) {
5238 seed_camelcase_includes();
5239 if (!$file && !$camelcase_file_seeded) {
5240 seed_camelcase_file($realfile);
5241 $camelcase_file_seeded = 1;
5242 }
5243 }
5244 if (!defined $camelcase{$word}) {
5245 $camelcase{$word} = 1;
5246 CHK("CAMELCASE",
5247 "Avoid CamelCase: <$word>\n" . $herecurr);
5248 }
5249 }
5250 }
5251 }
5252
5253#no spaces allowed after \ in define
5254 if ($line =~ /\#\s*define.*\\\s+$/) {
5255 if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
5256 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
5257 $fix) {
5258 $fixed[$fixlinenr] =~ s/\s+$//;
5259 }
5260 }
5261
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005262# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes
5263# itself <asm/foo.h> (uses RAW line)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005264 if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
5265 my $file = "$1.h";
5266 my $checkfile = "include/linux/$file";
5267 if (-f "$root/$checkfile" &&
5268 $realfile ne $checkfile &&
5269 $1 !~ /$allowed_asm_includes/)
5270 {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005271 my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`;
5272 if ($asminclude > 0) {
5273 if ($realfile =~ m{^arch/}) {
5274 CHK("ARCH_INCLUDE_LINUX",
5275 "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5276 } else {
5277 WARN("INCLUDE_LINUX",
5278 "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5279 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005280 }
5281 }
5282 }
5283
5284# multi-statement macros should be enclosed in a do while loop, grab the
5285# first statement and ensure its the whole macro if its not enclosed
5286# in a known good container
5287 if ($realfile !~ m@/vmlinux.lds.h$@ &&
5288 $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
5289 my $ln = $linenr;
5290 my $cnt = $realcnt;
5291 my ($off, $dstat, $dcond, $rest);
5292 my $ctx = '';
5293 my $has_flow_statement = 0;
5294 my $has_arg_concat = 0;
5295 ($dstat, $dcond, $ln, $cnt, $off) =
5296 ctx_statement_block($linenr, $realcnt, 0);
5297 $ctx = $dstat;
5298 #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
5299 #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
5300
5301 $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
Tom Burdicke29d9e12021-11-09 16:21:47 -06005302 $has_arg_concat = 1 if (($ctx =~ /\#\#/ || $ctx =~ /UTIL_CAT/) && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005303
Anas Nashif0f3d5472016-11-07 15:57:57 -05005304 $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
5305 my $define_args = $1;
5306 my $define_stmt = $dstat;
5307 my @def_args = ();
5308
5309 if (defined $define_args && $define_args ne "") {
5310 $define_args = substr($define_args, 1, length($define_args) - 2);
5311 $define_args =~ s/\s*//g;
Peter Bigot5b10fac2020-03-26 11:16:33 -05005312 $define_args =~ s/\\\+?//g;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005313 @def_args = split(",", $define_args);
5314 }
5315
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005316 $dstat =~ s/$;//g;
5317 $dstat =~ s/\\\n.//g;
5318 $dstat =~ s/^\s*//s;
5319 $dstat =~ s/\s*$//s;
5320
5321 # Flatten any parentheses and braces
5322 while ($dstat =~ s/\([^\(\)]*\)/1/ ||
5323 $dstat =~ s/\{[^\{\}]*\}/1/ ||
Anas Nashif76b09132016-02-20 13:53:35 -05005324 $dstat =~ s/.\[[^\[\]]*\]/1/)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005325 {
5326 }
5327
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005328 # Flatten any obvious string concatenation.
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005329 while ($dstat =~ s/($String)\s*$Ident/$1/ ||
5330 $dstat =~ s/$Ident\s*($String)/$1/)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005331 {
5332 }
5333
Anas Nashif0f3d5472016-11-07 15:57:57 -05005334 # Make asm volatile uses seem like a generic function
5335 $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
5336
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005337 my $exceptions = qr{
5338 $Declare|
5339 module_param_named|
5340 MODULE_PARM_DESC|
5341 DECLARE_PER_CPU|
5342 DEFINE_PER_CPU|
5343 __typeof__\(|
5344 union|
5345 struct|
5346 \.$Ident\s*=\s*|
Anas Nashif76b09132016-02-20 13:53:35 -05005347 ^\"|\"$|
5348 ^\[
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005349 }x;
5350 #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
Anas Nashif0f3d5472016-11-07 15:57:57 -05005351
5352 $ctx =~ s/\n*$//;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005353 my $stmt_cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005354 my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
Anas Nashif0f3d5472016-11-07 15:57:57 -05005355
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005356 if ($dstat ne '' &&
5357 $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
5358 $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
5359 $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
5360 $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants
5361 $dstat !~ /$exceptions/ &&
5362 $dstat !~ /^\.$Ident\s*=/ && # .foo =
5363 $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
5364 $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
5365 $dstat !~ /^for\s*$Constant$/ && # for (...)
5366 $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
5367 $dstat !~ /^do\s*{/ && # do {...
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005368 $dstat !~ /^\(\{/ && # ({...
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005369 $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
5370 {
Anas Nashif1eb244c2017-10-01 17:06:36 -04005371 if ($dstat =~ /^\s*if\b/) {
5372 ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
5373 "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
5374 } elsif ($dstat =~ /;/) {
5375 ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005376 "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
5377 } else {
Anas Nashif65f0c672018-05-08 10:19:30 -05005378 WARN("COMPLEX_MACRO",
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005379 "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
5380 }
Anas Nashif0f3d5472016-11-07 15:57:57 -05005381
5382 }
5383
5384 # Make $define_stmt single line, comment-free, etc
5385 my @stmt_array = split('\n', $define_stmt);
5386 my $first = 1;
5387 $define_stmt = "";
5388 foreach my $l (@stmt_array) {
5389 $l =~ s/\\$//;
5390 if ($first) {
5391 $define_stmt = $l;
5392 $first = 0;
5393 } elsif ($l =~ /^[\+ ]/) {
5394 $define_stmt .= substr($l, 1);
5395 }
5396 }
5397 $define_stmt =~ s/$;//g;
5398 $define_stmt =~ s/\s+/ /g;
5399 $define_stmt = trim($define_stmt);
5400
5401# check if any macro arguments are reused (ignore '...' and 'type')
5402 foreach my $arg (@def_args) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04005403 next if ($arg =~ /\.\.\./);
5404 next if ($arg =~ /^type$/i);
5405 my $tmp_stmt = $define_stmt;
Peter Bigot5b10fac2020-03-26 11:16:33 -05005406 $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
Anas Nashif1eb244c2017-10-01 17:06:36 -04005407 $tmp_stmt =~ s/\#+\s*$arg\b//g;
5408 $tmp_stmt =~ s/\b$arg\s*\#\#//g;
Peter Bigot5b10fac2020-03-26 11:16:33 -05005409 my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005410 if ($use_cnt > 1) {
5411 CHK("MACRO_ARG_REUSE",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005412 "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
5413 }
Anas Nashif0f3d5472016-11-07 15:57:57 -05005414# check if any macro arguments may have other precedence issues
Anas Nashif1eb244c2017-10-01 17:06:36 -04005415 if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
5416 ((defined($1) && $1 ne ',') ||
5417 (defined($2) && $2 ne ','))) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05005418 CHK("MACRO_ARG_PRECEDENCE",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005419 "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
Anas Nashif0f3d5472016-11-07 15:57:57 -05005420 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005421 }
5422
5423# check for macros with flow control, but without ## concatenation
5424# ## concatenation is commonly a macro that defines a function so ignore those
5425 if ($has_flow_statement && !$has_arg_concat) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005426 my $cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005427 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005428
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005429 WARN("MACRO_WITH_FLOW_CONTROL",
5430 "Macros with flow control statements should be avoided\n" . "$herectx");
5431 }
5432
5433# check for line continuations outside of #defines, preprocessor #, and asm
5434
5435 } else {
5436 if ($prevline !~ /^..*\\$/ &&
5437 $line !~ /^\+\s*\#.*\\$/ && # preprocessor
5438 $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm
5439 $line =~ /^\+.*\\$/) {
5440 WARN("LINE_CONTINUATIONS",
5441 "Avoid unnecessary line continuations\n" . $herecurr);
5442 }
5443 }
5444
5445# do {} while (0) macro tests:
5446# single-statement macros do not need to be enclosed in do while (0) loop,
5447# macro should not end with a semicolon
Peter Bigot5b10fac2020-03-26 11:16:33 -05005448 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005449 $realfile !~ m@/vmlinux.lds.h$@ &&
5450 $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
5451 my $ln = $linenr;
5452 my $cnt = $realcnt;
5453 my ($off, $dstat, $dcond, $rest);
5454 my $ctx = '';
5455 ($dstat, $dcond, $ln, $cnt, $off) =
5456 ctx_statement_block($linenr, $realcnt, 0);
5457 $ctx = $dstat;
5458
5459 $dstat =~ s/\\\n.//g;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005460 $dstat =~ s/$;/ /g;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005461
5462 if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {
5463 my $stmts = $2;
5464 my $semis = $3;
5465
5466 $ctx =~ s/\n*$//;
5467 my $cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005468 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005469
5470 if (($stmts =~ tr/;/;/) == 1 &&
5471 $stmts !~ /^\s*(if|while|for|switch)\b/) {
5472 WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",
5473 "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");
5474 }
5475 if (defined $semis && $semis ne "") {
5476 WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
5477 "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
5478 }
5479 } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
5480 $ctx =~ s/\n*$//;
5481 my $cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005482 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005483
5484 WARN("TRAILING_SEMICOLON",
5485 "macros should not use a trailing semicolon\n" . "$herectx");
5486 }
5487 }
5488
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005489# check for redundant bracing round if etc
5490 if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
5491 my ($level, $endln, @chunks) =
5492 ctx_statement_full($linenr, $realcnt, 1);
5493 #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
5494 #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
5495 if ($#chunks > 0 && $level == 0) {
5496 my @allowed = ();
5497 my $allow = 0;
5498 my $seen = 0;
5499 my $herectx = $here . "\n";
5500 my $ln = $linenr - 1;
5501 for my $chunk (@chunks) {
5502 my ($cond, $block) = @{$chunk};
5503
5504 # If the condition carries leading newlines, then count those as offsets.
5505 my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
5506 my $offset = statement_rawlines($whitespace) - 1;
5507
5508 $allowed[$allow] = 0;
5509 #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
5510
5511 # We have looked at and allowed this specific line.
5512 $suppress_ifbraces{$ln + $offset} = 1;
5513
5514 $herectx .= "$rawlines[$ln + $offset]\n[...]\n";
5515 $ln += statement_rawlines($block) - 1;
5516
5517 substr($block, 0, length($cond), '');
5518
5519 $seen++ if ($block =~ /^\s*{/);
5520
5521 #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
5522 if (statement_lines($cond) > 1) {
5523 #print "APW: ALLOWED: cond<$cond>\n";
5524 $allowed[$allow] = 1;
5525 }
5526 if ($block =~/\b(?:if|for|while)\b/) {
5527 #print "APW: ALLOWED: block<$block>\n";
5528 $allowed[$allow] = 1;
5529 }
5530 if (statement_block_size($block) > 1) {
5531 #print "APW: ALLOWED: lines block<$block>\n";
5532 $allowed[$allow] = 1;
5533 }
5534 $allow++;
5535 }
5536 if ($seen) {
5537 my $sum_allowed = 0;
5538 foreach (@allowed) {
5539 $sum_allowed += $_;
5540 }
5541 if ($sum_allowed == 0) {
5542 WARN("BRACES",
5543 "braces {} are not necessary for any arm of this statement\n" . $herectx);
5544 } elsif ($sum_allowed != $allow &&
5545 $seen != $allow) {
5546 CHK("BRACES",
5547 "braces {} should be used on all arms of this statement\n" . $herectx);
5548 }
5549 }
5550 }
5551 }
5552 if (!defined $suppress_ifbraces{$linenr - 1} &&
5553 $line =~ /\b(if|while|for|else)\b/) {
5554 my $allowed = 0;
5555
5556 # Check the pre-context.
5557 if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
5558 #print "APW: ALLOWED: pre<$1>\n";
5559 $allowed = 1;
5560 }
5561
5562 my ($level, $endln, @chunks) =
5563 ctx_statement_full($linenr, $realcnt, $-[0]);
5564
5565 # Check the condition.
5566 my ($cond, $block) = @{$chunks[0]};
5567 #print "CHECKING<$linenr> cond<$cond> block<$block>\n";
5568 if (defined $cond) {
5569 substr($block, 0, length($cond), '');
5570 }
5571 if (statement_lines($cond) > 1) {
5572 #print "APW: ALLOWED: cond<$cond>\n";
5573 $allowed = 1;
5574 }
5575 if ($block =~/\b(?:if|for|while)\b/) {
5576 #print "APW: ALLOWED: block<$block>\n";
5577 $allowed = 1;
5578 }
5579 if (statement_block_size($block) > 1) {
5580 #print "APW: ALLOWED: lines block<$block>\n";
5581 $allowed = 1;
5582 }
5583 # Check the post-context.
5584 if (defined $chunks[1]) {
5585 my ($cond, $block) = @{$chunks[1]};
5586 if (defined $cond) {
5587 substr($block, 0, length($cond), '');
5588 }
5589 if ($block =~ /^\s*\{/) {
5590 #print "APW: ALLOWED: chunk-1 block<$block>\n";
5591 $allowed = 1;
5592 }
5593 }
5594 if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005595 my $cnt = statement_rawlines($block);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005596 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005597
5598 WARN("BRACES",
5599 "braces {} are not necessary for single statement blocks\n" . $herectx);
5600 }
5601 }
5602
Anas Nashif1eb244c2017-10-01 17:06:36 -04005603# check for single line unbalanced braces
5604 if ($sline =~ /^.\s*\}\s*else\s*$/ ||
5605 $sline =~ /^.\s*else\s*\{\s*$/) {
5606 CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);
5607 }
5608
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005609# check for unnecessary blank lines around braces
5610 if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005611 if (CHK("BRACES",
5612 "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) &&
5613 $fix && $prevrawline =~ /^\+/) {
5614 fix_delete_line($fixlinenr - 1, $prevrawline);
5615 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005616 }
5617 if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005618 if (CHK("BRACES",
5619 "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) &&
5620 $fix) {
5621 fix_delete_line($fixlinenr, $rawline);
5622 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005623 }
5624
5625# no volatiles please
5626 my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
5627 if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
5628 WARN("VOLATILE",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005629 "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005630 }
5631
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005632# Check for user-visible strings broken across lines, which breaks the ability
5633# to grep for the string. Make exceptions when the previous string ends in a
5634# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
5635# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
5636 if ($line =~ /^\+\s*$String/ &&
5637 $prevline =~ /"\s*$/ &&
5638 $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
5639 if (WARN("SPLIT_STRING",
5640 "quoted string split across lines\n" . $hereprev) &&
5641 $fix &&
5642 $prevrawline =~ /^\+.*"\s*$/ &&
5643 $last_coalesced_string_linenr != $linenr - 1) {
5644 my $extracted_string = get_quoted_string($line, $rawline);
5645 my $comma_close = "";
5646 if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) {
5647 $comma_close = $1;
5648 }
5649
5650 fix_delete_line($fixlinenr - 1, $prevrawline);
5651 fix_delete_line($fixlinenr, $rawline);
5652 my $fixedline = $prevrawline;
5653 $fixedline =~ s/"\s*$//;
5654 $fixedline .= substr($extracted_string, 1) . trim($comma_close);
5655 fix_insert_line($fixlinenr - 1, $fixedline);
5656 $fixedline = $rawline;
5657 $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//;
5658 if ($fixedline !~ /\+\s*$/) {
5659 fix_insert_line($fixlinenr, $fixedline);
5660 }
5661 $last_coalesced_string_linenr = $linenr;
5662 }
5663 }
5664
5665# check for missing a space in a string concatenation
5666 if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {
5667 WARN('MISSING_SPACE',
5668 "break quoted strings at a space character\n" . $hereprev);
5669 }
5670
Anas Nashif1eb244c2017-10-01 17:06:36 -04005671# check for an embedded function name in a string when the function is known
5672# This does not work very well for -f --file checking as it depends on patch
5673# context providing the function name or a single line form for in-file
5674# function declarations
5675 if ($line =~ /^\+.*$String/ &&
5676 defined($context_function) &&
5677 get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&
5678 length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {
5679 WARN("EMBEDDED_FUNCTION_NAME",
5680 "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
5681 }
5682
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005683# check for spaces before a quoted newline
5684 if ($rawline =~ /^.*\".*\s\\n/) {
5685 if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
5686 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
5687 $fix) {
5688 $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
5689 }
5690
5691 }
5692
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005693# concatenated string without spaces between elements
Peter Bigot5b10fac2020-03-26 11:16:33 -05005694 if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
5695 if (CHK("CONCATENATED_STRING",
5696 "Concatenated strings should use spaces between elements\n" . $herecurr) &&
5697 $fix) {
5698 while ($line =~ /($String)/g) {
5699 my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
5700 $fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
5701 $fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
5702 }
5703 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005704 }
5705
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005706# uncoalesced string fragments
5707 if ($line =~ /$String\s*"/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05005708 if (WARN("STRING_FRAGMENTS",
5709 "Consecutive strings are generally better as a single string\n" . $herecurr) &&
5710 $fix) {
5711 while ($line =~ /($String)(?=\s*")/g) {
5712 my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
5713 $fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
5714 }
5715 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005716 }
5717
Anas Nashif1eb244c2017-10-01 17:06:36 -04005718# check for non-standard and hex prefixed decimal printf formats
5719 my $show_L = 1; #don't show the same defect twice
5720 my $show_Z = 1;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005721 while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04005722 my $string = substr($rawline, $-[1], $+[1] - $-[1]);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005723 $string =~ s/%%/__/g;
Anas Nashif1eb244c2017-10-01 17:06:36 -04005724 # check for %L
5725 if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005726 WARN("PRINTF_L",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005727 "\%L$1 is non-standard C, use %ll$1\n" . $herecurr);
5728 $show_L = 0;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005729 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04005730 # check for %Z
5731 if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) {
5732 WARN("PRINTF_Z",
5733 "%Z$1 is non-standard C, use %z$1\n" . $herecurr);
5734 $show_Z = 0;
5735 }
5736 # check for 0x<decimal>
5737 if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) {
5738 ERROR("PRINTF_0XDECIMAL",
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005739 "Prefixing 0x with decimal output is defective\n" . $herecurr);
5740 }
5741 }
5742
5743# check for line continuations in quoted strings with odd counts of "
Peter Bigot5b10fac2020-03-26 11:16:33 -05005744 if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005745 WARN("LINE_CONTINUATIONS",
5746 "Avoid line continuations in quoted strings\n" . $herecurr);
5747 }
5748
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005749# warn about #if 0
5750 if ($line =~ /^.\s*\#\s*if\s+0\b/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05005751 WARN("IF_0",
5752 "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
5753 }
5754
5755# warn about #if 1
5756 if ($line =~ /^.\s*\#\s*if\s+1\b/) {
5757 WARN("IF_1",
5758 "Consider removing the #if 1 and its #endif\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005759 }
5760
5761# check for needless "if (<foo>) fn(<foo>)" uses
5762 if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005763 my $tested = quotemeta($1);
5764 my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;';
5765 if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) {
5766 my $func = $1;
5767 if (WARN('NEEDLESS_IF',
5768 "$func(NULL) is safe and this check is probably not required\n" . $hereprev) &&
5769 $fix) {
5770 my $do_fix = 1;
5771 my $leading_tabs = "";
5772 my $new_leading_tabs = "";
5773 if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) {
5774 $leading_tabs = $1;
5775 } else {
5776 $do_fix = 0;
5777 }
5778 if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) {
5779 $new_leading_tabs = $1;
5780 if (length($leading_tabs) + 1 ne length($new_leading_tabs)) {
5781 $do_fix = 0;
5782 }
5783 } else {
5784 $do_fix = 0;
5785 }
5786 if ($do_fix) {
5787 fix_delete_line($fixlinenr - 1, $prevrawline);
5788 $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/;
5789 }
5790 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005791 }
5792 }
5793
5794# check for unnecessary "Out of Memory" messages
5795 if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
5796 $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
5797 (defined $1 || defined $3) &&
5798 $linenr > 3) {
5799 my $testval = $2;
5800 my $testline = $lines[$linenr - 3];
5801
5802 my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
5803# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
5804
Peter Bigot5b10fac2020-03-26 11:16:33 -05005805 if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
5806 $s !~ /\b__GFP_NOWARN\b/ ) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005807 WARN("OOM_MESSAGE",
5808 "Possible unnecessary 'out of memory' message\n" . $hereprev);
5809 }
5810 }
5811
5812# check for logging functions with KERN_<LEVEL>
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005813 if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005814 $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) {
5815 my $level = $1;
5816 if (WARN("UNNECESSARY_KERN_LEVEL",
5817 "Possible unnecessary $level\n" . $herecurr) &&
5818 $fix) {
5819 $fixed[$fixlinenr] =~ s/\s*$level\s*//;
5820 }
5821 }
5822
Anas Nashif1eb244c2017-10-01 17:06:36 -04005823# check for logging continuations
5824 if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) {
5825 WARN("LOGGING_CONTINUATION",
5826 "Avoid logging continuation uses where feasible\n" . $herecurr);
5827 }
5828
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005829# check for mask then right shift without a parentheses
Peter Bigot5b10fac2020-03-26 11:16:33 -05005830 if ($perl_version_ok &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005831 $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
5832 $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
5833 WARN("MASK_THEN_SHIFT",
5834 "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr);
5835 }
5836
5837# check for pointer comparisons to NULL
Peter Bigot5b10fac2020-03-26 11:16:33 -05005838 if ($perl_version_ok) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005839 while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
5840 my $val = $1;
5841 my $equal = "!";
5842 $equal = "" if ($4 eq "!=");
5843 if (CHK("COMPARISON_TO_NULL",
5844 "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) &&
5845 $fix) {
5846 $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/;
5847 }
5848 }
5849 }
5850
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005851# check for bad placement of section $InitAttribute (e.g.: __initdata)
5852 if ($line =~ /(\b$InitAttribute\b)/) {
5853 my $attr = $1;
5854 if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) {
5855 my $ptr = $1;
5856 my $var = $2;
5857 if ((($ptr =~ /\b(union|struct)\s+$attr\b/ &&
5858 ERROR("MISPLACED_INIT",
5859 "$attr should be placed after $var\n" . $herecurr)) ||
5860 ($ptr !~ /\b(union|struct)\s+$attr\b/ &&
5861 WARN("MISPLACED_INIT",
5862 "$attr should be placed after $var\n" . $herecurr))) &&
5863 $fix) {
5864 $fixed[$fixlinenr] =~ s/(\bstatic\s+(?:const\s+)?)(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*([=;])\s*/"$1" . trim(string_find_replace($2, "\\s*$attr\\s*", " ")) . " " . trim(string_find_replace($3, "\\s*$attr\\s*", "")) . " $attr" . ("$4" eq ";" ? ";" : " = ")/e;
5865 }
5866 }
5867 }
5868
5869# check for $InitAttributeData (ie: __initdata) with const
5870 if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
5871 my $attr = $1;
5872 $attr =~ /($InitAttributePrefix)(.*)/;
5873 my $attr_prefix = $1;
5874 my $attr_type = $2;
5875 if (ERROR("INIT_ATTRIBUTE",
5876 "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
5877 $fix) {
5878 $fixed[$fixlinenr] =~
5879 s/$InitAttributeData/${attr_prefix}initconst/;
5880 }
5881 }
5882
5883# check for $InitAttributeConst (ie: __initconst) without const
5884 if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
5885 my $attr = $1;
5886 if (ERROR("INIT_ATTRIBUTE",
5887 "Use of $attr requires a separate use of const\n" . $herecurr) &&
5888 $fix) {
5889 my $lead = $fixed[$fixlinenr] =~
5890 /(^\+\s*(?:static\s+))/;
5891 $lead = rtrim($1);
5892 $lead = "$lead " if ($lead !~ /^\+$/);
5893 $lead = "${lead}const ";
5894 $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/;
5895 }
5896 }
5897
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005898# check for __read_mostly with const non-pointer (should just be const)
5899 if ($line =~ /\b__read_mostly\b/ &&
5900 $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) {
5901 if (ERROR("CONST_READ_MOSTLY",
5902 "Invalid use of __read_mostly with const type\n" . $herecurr) &&
5903 $fix) {
5904 $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//;
5905 }
5906 }
5907
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005908# don't use __constant_<foo> functions outside of include/uapi/
5909 if ($realfile !~ m@^include/uapi/@ &&
5910 $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
5911 my $constant_func = $1;
5912 my $func = $constant_func;
5913 $func =~ s/^__constant_//;
5914 if (WARN("CONSTANT_CONVERSION",
5915 "$constant_func should be $func\n" . $herecurr) &&
5916 $fix) {
5917 $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
5918 }
5919 }
5920
5921# prefer usleep_range over udelay
5922 if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
5923 my $delay = $1;
5924 # ignore udelay's < 10, however
5925 if (! ($delay < 10) ) {
5926 CHK("USLEEP_RANGE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05005927 "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005928 }
5929 if ($delay > 2000) {
5930 WARN("LONG_UDELAY",
5931 "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
5932 }
5933 }
5934
5935# warn about unexpectedly long msleep's
5936 if ($line =~ /\bmsleep\s*\((\d+)\);/) {
5937 if ($1 < 20) {
5938 WARN("MSLEEP",
Peter Bigot5b10fac2020-03-26 11:16:33 -05005939 "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005940 }
5941 }
5942
5943# check for comparisons of jiffies
5944 if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
5945 WARN("JIFFIES_COMPARISON",
5946 "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
5947 }
5948
5949# check for comparisons of get_jiffies_64()
5950 if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
5951 WARN("JIFFIES_COMPARISON",
5952 "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
5953 }
5954
5955# warn about #ifdefs in C files
5956# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
5957# print "#ifdef in C files should be avoided\n";
5958# print "$herecurr";
5959# $clean = 0;
5960# }
5961
5962# warn about spacing in #ifdefs
5963 if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
5964 if (ERROR("SPACING",
5965 "exactly one space required after that #$1\n" . $herecurr) &&
5966 $fix) {
5967 $fixed[$fixlinenr] =~
5968 s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
5969 }
5970
5971 }
5972
5973# check for spinlock_t definitions without a comment.
5974 if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
5975 $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
5976 my $which = $1;
5977 if (!ctx_has_comment($first_line, $linenr)) {
5978 CHK("UNCOMMENTED_DEFINITION",
5979 "$1 definition without comment\n" . $herecurr);
5980 }
5981 }
5982# check for memory barriers without a comment.
Anas Nashif76b09132016-02-20 13:53:35 -05005983
5984 my $barriers = qr{
5985 mb|
5986 rmb|
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005987 wmb
Anas Nashif76b09132016-02-20 13:53:35 -05005988 }x;
5989 my $barrier_stems = qr{
5990 mb__before_atomic|
5991 mb__after_atomic|
5992 store_release|
5993 load_acquire|
5994 store_mb|
5995 (?:$barriers)
5996 }x;
5997 my $all_barriers = qr{
5998 (?:$barriers)|
5999 smp_(?:$barrier_stems)|
6000 virt_(?:$barrier_stems)
6001 }x;
6002
6003 if ($line =~ /\b(?:$all_barriers)\s*\(/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006004 if (!ctx_has_comment($first_line, $linenr)) {
6005 WARN("MEMORY_BARRIER",
6006 "memory barrier without comment\n" . $herecurr);
6007 }
6008 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006009
Anas Nashif76b09132016-02-20 13:53:35 -05006010 my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x;
6011
6012 if ($realfile !~ m@^include/asm-generic/@ &&
6013 $realfile !~ m@/barrier\.h$@ &&
6014 $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&
6015 $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {
6016 WARN("MEMORY_BARRIER",
6017 "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr);
6018 }
6019
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006020# check for waitqueue_active without a comment.
6021 if ($line =~ /\bwaitqueue_active\s*\(/) {
6022 if (!ctx_has_comment($first_line, $linenr)) {
6023 WARN("WAITQUEUE_ACTIVE",
6024 "waitqueue_active without comment\n" . $herecurr);
6025 }
6026 }
6027
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006028# check for data_race without a comment.
6029 if ($line =~ /\bdata_race\s*\(/) {
6030 if (!ctx_has_comment($first_line, $linenr)) {
6031 WARN("DATA_RACE",
6032 "data_race without comment\n" . $herecurr);
6033 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006034 }
6035
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006036# check of hardware specific defines
6037 if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
6038 CHK("ARCH_DEFINES",
6039 "architecture specific defines should be avoided\n" . $herecurr);
6040 }
6041
Anas Nashif1eb244c2017-10-01 17:06:36 -04006042# check that the storage class is not after a type
6043 if ($line =~ /\b($Type)\s+($Storage)\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006044 WARN("STORAGE_CLASS",
Anas Nashif1eb244c2017-10-01 17:06:36 -04006045 "storage class '$2' should be located before type '$1'\n" . $herecurr);
6046 }
6047# Check that the storage class is at the beginning of a declaration
6048 if ($line =~ /\b$Storage\b/ &&
6049 $line !~ /^.\s*$Storage/ &&
6050 $line =~ /^.\s*(.+?)\$Storage\s/ &&
6051 $1 !~ /[\,\)]\s*$/) {
6052 WARN("STORAGE_CLASS",
6053 "storage class should be at the beginning of the declaration\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006054 }
6055
6056# check the location of the inline attribute, that it is between
6057# storage class and type.
6058 if ($line =~ /\b$Type\s+$Inline\b/ ||
6059 $line =~ /\b$Inline\s+$Storage\b/) {
6060 ERROR("INLINE_LOCATION",
6061 "inline keyword should sit between storage class and type\n" . $herecurr);
6062 }
6063
6064# Check for __inline__ and __inline, prefer inline
6065 if ($realfile !~ m@\binclude/uapi/@ &&
6066 $line =~ /\b(__inline__|__inline)\b/) {
6067 if (WARN("INLINE",
6068 "plain inline is preferred over $1\n" . $herecurr) &&
6069 $fix) {
6070 $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/;
6071
6072 }
6073 }
6074
6075# Check for __attribute__ packed, prefer __packed
6076 if ($realfile !~ m@\binclude/uapi/@ &&
6077 $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
6078 WARN("PREFER_PACKED",
6079 "__packed is preferred over __attribute__((packed))\n" . $herecurr);
6080 }
6081
6082# Check for __attribute__ aligned, prefer __aligned
6083 if ($realfile !~ m@\binclude/uapi/@ &&
6084 $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
6085 WARN("PREFER_ALIGNED",
6086 "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
6087 }
6088
Peter Bigot5b10fac2020-03-26 11:16:33 -05006089# Check for __attribute__ section, prefer __section
6090 if ($realfile !~ m@\binclude/uapi/@ &&
6091 $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
6092 my $old = substr($rawline, $-[1], $+[1] - $-[1]);
6093 my $new = substr($old, 1, -1);
6094 if (WARN("PREFER_SECTION",
6095 "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
6096 $fix) {
6097 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
6098 }
6099 }
6100
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006101# Check for __attribute__ format(printf, prefer __printf
6102 if ($realfile !~ m@\binclude/uapi/@ &&
6103 $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
6104 if (WARN("PREFER_PRINTF",
6105 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
6106 $fix) {
6107 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
6108
6109 }
6110 }
6111
6112# Check for __attribute__ format(scanf, prefer __scanf
6113 if ($realfile !~ m@\binclude/uapi/@ &&
6114 $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
6115 if (WARN("PREFER_SCANF",
6116 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
6117 $fix) {
6118 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
6119 }
6120 }
6121
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006122# Check for __attribute__ weak, or __weak declarations (may have link issues)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006123 if ($perl_version_ok &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006124 $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
6125 ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
6126 $line =~ /\b__weak\b/)) {
6127 ERROR("WEAK_DECLARATION",
6128 "Using weak declarations can have unintended link defects\n" . $herecurr);
6129 }
6130
Kumar Gala93da8dc2020-06-02 12:38:11 -05006131# check for c99 types like uint8_t used outside of uapi/
6132 if ($realfile !~ m@\binclude/uapi/@ &&
6133 $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006134 my $type = $1;
6135 if ($type =~ /\b($typeC99Typedefs)\b/) {
6136 $type = $1;
6137 my $kernel_type = 'u';
6138 $kernel_type = 's' if ($type =~ /^_*[si]/);
6139 $type =~ /(\d+)/;
Kumar Gala93da8dc2020-06-02 12:38:11 -05006140 $kernel_type .= $1;
6141 if (CHK("PREFER_KERNEL_TYPES",
6142 "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) &&
6143 $fix) {
6144 $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/;
6145 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006146 }
6147 }
6148
Anas Nashif76b09132016-02-20 13:53:35 -05006149# check for cast of C90 native int or longer types constants
6150 if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {
6151 my $cast = $1;
6152 my $const = $2;
6153 if (WARN("TYPECAST_INT_CONSTANT",
6154 "Unnecessary typecast of c90 int constant\n" . $herecurr) &&
6155 $fix) {
6156 my $suffix = "";
6157 my $newconst = $const;
6158 $newconst =~ s/${Int_type}$//;
6159 $suffix .= 'U' if ($cast =~ /\bunsigned\b/);
6160 if ($cast =~ /\blong\s+long\b/) {
6161 $suffix .= 'LL';
6162 } elsif ($cast =~ /\blong\b/) {
6163 $suffix .= 'L';
6164 }
6165 $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;
6166 }
6167 }
6168
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006169# check for sizeof(&)
6170 if ($line =~ /\bsizeof\s*\(\s*\&/) {
6171 WARN("SIZEOF_ADDRESS",
6172 "sizeof(& should be avoided\n" . $herecurr);
6173 }
6174
6175# check for sizeof without parenthesis
6176 if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
6177 if (WARN("SIZEOF_PARENTHESIS",
6178 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
6179 $fix) {
6180 $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
6181 }
6182 }
6183
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006184# check for struct spinlock declarations
6185 if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) {
6186 WARN("USE_SPINLOCK_T",
6187 "struct spinlock should be spinlock_t\n" . $herecurr);
6188 }
6189
6190# check for seq_printf uses that could be seq_puts
6191 if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
6192 my $fmt = get_quoted_string($line, $rawline);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006193 $fmt =~ s/%%//g;
6194 if ($fmt !~ /%/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006195 if (WARN("PREFER_SEQ_PUTS",
6196 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
6197 $fix) {
6198 $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;
6199 }
6200 }
6201 }
6202
Peter Bigot5b10fac2020-03-26 11:16:33 -05006203# check for vsprintf extension %p<foo> misuses
6204 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006205 defined $stat &&
6206 $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
6207 $1 !~ /^_*volatile_*$/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05006208 my $stat_real;
6209
Anas Nashif1eb244c2017-10-01 17:06:36 -04006210 my $lc = $stat =~ tr@\n@@;
6211 $lc = $lc + $linenr;
6212 for (my $count = $linenr; $count <= $lc; $count++) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05006213 my $specifier;
6214 my $extension;
6215 my $qualifier;
6216 my $bad_specifier = "";
Anas Nashif1eb244c2017-10-01 17:06:36 -04006217 my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
6218 $fmt =~ s/%%//g;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006219
6220 while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {
6221 $specifier = $1;
6222 $extension = $2;
6223 $qualifier = $3;
6224 if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
6225 ($extension eq "f" &&
6226 defined $qualifier && $qualifier !~ /^w/)) {
6227 $bad_specifier = $specifier;
6228 last;
6229 }
6230 if ($extension eq "x" && !defined($stat_real)) {
6231 if (!defined($stat_real)) {
6232 $stat_real = get_stat_real($linenr, $lc);
6233 }
6234 WARN("VSPRINTF_SPECIFIER_PX",
6235 "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n");
6236 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04006237 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006238 if ($bad_specifier ne "") {
6239 my $stat_real = get_stat_real($linenr, $lc);
6240 my $ext_type = "Invalid";
6241 my $use = "";
6242 if ($bad_specifier =~ /p[Ff]/) {
6243 $use = " - use %pS instead";
6244 $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
6245 }
6246
6247 WARN("VSPRINTF_POINTER_EXTENSION",
6248 "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
Anas Nashif1eb244c2017-10-01 17:06:36 -04006249 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04006250 }
6251 }
6252
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006253# Check for misused memsets
Peter Bigot5b10fac2020-03-26 11:16:33 -05006254 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006255 defined $stat &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006256 $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006257
6258 my $ms_addr = $2;
6259 my $ms_val = $7;
6260 my $ms_size = $12;
6261
6262 if ($ms_size =~ /^(0x|)0$/i) {
6263 ERROR("MEMSET",
6264 "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n");
6265 } elsif ($ms_size =~ /^(0x|)1$/i) {
6266 WARN("MEMSET",
6267 "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n");
6268 }
6269 }
6270
6271# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006272# if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006273# defined $stat &&
6274# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6275# if (WARN("PREFER_ETHER_ADDR_COPY",
6276# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
6277# $fix) {
6278# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
6279# }
6280# }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006281
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006282# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006283# if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006284# defined $stat &&
6285# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6286# WARN("PREFER_ETHER_ADDR_EQUAL",
6287# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
6288# }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006289
6290# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
6291# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
Peter Bigot5b10fac2020-03-26 11:16:33 -05006292# if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006293# defined $stat &&
6294# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6295#
6296# my $ms_val = $7;
6297#
6298# if ($ms_val =~ /^(?:0x|)0+$/i) {
6299# if (WARN("PREFER_ETH_ZERO_ADDR",
6300# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
6301# $fix) {
6302# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
6303# }
6304# } elsif ($ms_val =~ /^(?:0xff|255)$/i) {
6305# if (WARN("PREFER_ETH_BROADCAST_ADDR",
6306# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
6307# $fix) {
6308# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
6309# }
6310# }
6311# }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006312
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006313# typecasts on min/max could be min_t/max_t
Peter Bigot5b10fac2020-03-26 11:16:33 -05006314 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006315 defined $stat &&
6316 $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
6317 if (defined $2 || defined $7) {
6318 my $call = $1;
6319 my $cast1 = deparenthesize($2);
6320 my $arg1 = $3;
6321 my $cast2 = deparenthesize($7);
6322 my $arg2 = $8;
6323 my $cast;
6324
6325 if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) {
6326 $cast = "$cast1 or $cast2";
6327 } elsif ($cast1 ne "") {
6328 $cast = $cast1;
6329 } else {
6330 $cast = $cast2;
6331 }
6332 WARN("MINMAX",
6333 "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n");
6334 }
6335 }
6336
6337# check usleep_range arguments
Peter Bigot5b10fac2020-03-26 11:16:33 -05006338 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006339 defined $stat &&
6340 $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
6341 my $min = $1;
6342 my $max = $7;
6343 if ($min eq $max) {
6344 WARN("USLEEP_RANGE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05006345 "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006346 } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
6347 $min > $max) {
6348 WARN("USLEEP_RANGE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05006349 "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006350 }
6351 }
6352
6353# check for naked sscanf
Peter Bigot5b10fac2020-03-26 11:16:33 -05006354 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006355 defined $stat &&
6356 $line =~ /\bsscanf\b/ &&
6357 ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
6358 $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
6359 $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
6360 my $lc = $stat =~ tr@\n@@;
6361 $lc = $lc + $linenr;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006362 my $stat_real = get_stat_real($linenr, $lc);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006363 WARN("NAKED_SSCANF",
6364 "unchecked sscanf return value\n" . "$here\n$stat_real\n");
6365 }
6366
6367# check for simple sscanf that should be kstrto<foo>
Peter Bigot5b10fac2020-03-26 11:16:33 -05006368 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006369 defined $stat &&
6370 $line =~ /\bsscanf\b/) {
6371 my $lc = $stat =~ tr@\n@@;
6372 $lc = $lc + $linenr;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006373 my $stat_real = get_stat_real($linenr, $lc);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006374 if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
6375 my $format = $6;
6376 my $count = $format =~ tr@%@%@;
6377 if ($count == 1 &&
6378 $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {
6379 WARN("SSCANF_TO_KSTRTO",
6380 "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n");
6381 }
6382 }
6383 }
6384
6385# check for new externs in .h files.
6386 if ($realfile =~ /\.h$/ &&
6387 $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
6388 if (CHK("AVOID_EXTERNS",
6389 "extern prototypes should be avoided in .h files\n" . $herecurr) &&
6390 $fix) {
6391 $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
6392 }
6393 }
6394
6395# check for new externs in .c files.
6396 if ($realfile =~ /\.c$/ && defined $stat &&
6397 $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
6398 {
6399 my $function_name = $1;
6400 my $paren_space = $2;
6401
6402 my $s = $stat;
6403 if (defined $cond) {
6404 substr($s, 0, length($cond), '');
6405 }
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006406 if ($s =~ /^\s*;/)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006407 {
6408 WARN("AVOID_EXTERNS",
6409 "externs should be avoided in .c files\n" . $herecurr);
6410 }
6411
6412 if ($paren_space =~ /\n/) {
6413 WARN("FUNCTION_ARGUMENTS",
6414 "arguments for function declarations should follow identifier\n" . $herecurr);
6415 }
6416
6417 } elsif ($realfile =~ /\.c$/ && defined $stat &&
6418 $stat =~ /^.\s*extern\s+/)
6419 {
6420 WARN("AVOID_EXTERNS",
6421 "externs should be avoided in .c files\n" . $herecurr);
6422 }
6423
Anas Nashif1eb244c2017-10-01 17:06:36 -04006424# check for function declarations that have arguments without identifier names
6425 if (defined $stat &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05006426 $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006427 $1 ne "void") {
6428 my $args = trim($1);
6429 while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
6430 my $arg = trim($1);
6431 if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
6432 WARN("FUNCTION_ARGUMENTS",
6433 "function definition argument '$arg' should also have an identifier name\n" . $herecurr);
6434 }
6435 }
6436 }
6437
Anas Nashif1eb244c2017-10-01 17:06:36 -04006438# check for function definitions
Peter Bigot5b10fac2020-03-26 11:16:33 -05006439 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006440 defined $stat &&
6441 $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
6442 $context_function = $1;
6443
6444# check for multiline function definition with misplaced open brace
6445 my $ok = 0;
6446 my $cnt = statement_rawlines($stat);
6447 my $herectx = $here . "\n";
6448 for (my $n = 0; $n < $cnt; $n++) {
6449 my $rl = raw_line($linenr, $n);
6450 $herectx .= $rl . "\n";
6451 $ok = 1 if ($rl =~ /^[ \+]\{/);
6452 $ok = 1 if ($rl =~ /\{/ && $n == 0);
6453 last if $rl =~ /^[ \+].*\{/;
6454 }
6455 if (!$ok) {
6456 ERROR("OPEN_BRACE",
6457 "open brace '{' following function definitions go on the next line\n" . $herectx);
6458 }
6459 }
6460
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006461# checks for new __setup's
6462 if ($rawline =~ /\b__setup\("([^"]*)"/) {
6463 my $name = $1;
6464
6465 if (!grep(/$name/, @setup_docs)) {
6466 CHK("UNDOCUMENTED_SETUP",
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006467 "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006468 }
6469 }
6470
Peter Bigot5b10fac2020-03-26 11:16:33 -05006471# check for pointless casting of alloc functions
6472 if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006473 WARN("UNNECESSARY_CASTS",
6474 "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
6475 }
6476
6477# alloc style
6478# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006479 if ($perl_version_ok &&
6480 $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006481 CHK("ALLOC_SIZEOF_STRUCT",
6482 "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
6483 }
6484
6485# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
Peter Bigot5b10fac2020-03-26 11:16:33 -05006486 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006487 defined $stat &&
6488 $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006489 my $oldfunc = $3;
6490 my $a1 = $4;
6491 my $a2 = $10;
6492 my $newfunc = "kmalloc_array";
6493 $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
6494 my $r1 = $a1;
6495 my $r2 = $a2;
6496 if ($a1 =~ /^sizeof\s*\S/) {
6497 $r1 = $a2;
6498 $r2 = $a1;
6499 }
6500 if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
6501 !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04006502 my $cnt = statement_rawlines($stat);
Peter Bigot5b10fac2020-03-26 11:16:33 -05006503 my $herectx = get_stat_here($linenr, $cnt, $here);
6504
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006505 if (WARN("ALLOC_WITH_MULTIPLY",
Anas Nashif1eb244c2017-10-01 17:06:36 -04006506 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
6507 $cnt == 1 &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006508 $fix) {
6509 $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006510 }
6511 }
6512 }
6513
6514# check for krealloc arg reuse
Peter Bigot5b10fac2020-03-26 11:16:33 -05006515 if ($perl_version_ok &&
6516 $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
6517 $1 eq $3) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006518 WARN("KREALLOC_ARG_REUSE",
6519 "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
6520 }
6521
6522# check for alloc argument mismatch
6523 if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) {
6524 WARN("ALLOC_ARRAY_ARGS",
6525 "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
6526 }
6527
6528# check for multiple semicolons
6529 if ($line =~ /;\s*;\s*$/) {
6530 if (WARN("ONE_SEMICOLON",
6531 "Statements terminations use 1 semicolon\n" . $herecurr) &&
6532 $fix) {
6533 $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
6534 }
6535 }
6536
Anas Nashif0f3d5472016-11-07 15:57:57 -05006537# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
6538 if ($realfile !~ m@^include/uapi/@ &&
6539 $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006540 my $ull = "";
6541 $ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
6542 if (CHK("BIT_MACRO",
6543 "Prefer using the BIT$ull macro\n" . $herecurr) &&
6544 $fix) {
6545 $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/;
6546 }
6547 }
6548
Keith Packardb021dec2023-07-17 14:45:26 -07006549# check for feature test macros that request C library API extensions, violating rules A.4 and A.5
6550
6551 if ($line =~ /#\s*define\s+$api_defines/) {
6552 ERROR("API_DEFINE",
Alberto Escolar Piedrasf9e30842024-02-16 16:52:56 +01006553 "do not specify non-standard feature test macros for embedded code\n" . "$here$rawline\n");
Keith Packardb021dec2023-07-17 14:45:26 -07006554 }
6555
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006556# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
6557 if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^CONFIG_/) {
6558 WARN("IS_ENABLED_CONFIG",
6559 "IS_ENABLED($1) is normally used as IS_ENABLED(CONFIG_$1)\n" . $herecurr);
6560 }
6561
Anas Nashif0f3d5472016-11-07 15:57:57 -05006562# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
6563 if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
6564 my $config = $1;
6565 if (WARN("PREFER_IS_ENABLED",
6566 "Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) &&
6567 $fix) {
6568 $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
6569 }
6570 }
6571
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006572# check for switch/default statements without a break;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006573 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006574 defined $stat &&
6575 $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006576 my $cnt = statement_rawlines($stat);
Peter Bigot5b10fac2020-03-26 11:16:33 -05006577 my $herectx = get_stat_here($linenr, $cnt, $here);
6578
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006579 WARN("DEFAULT_NO_BREAK",
6580 "switch default: should use break\n" . $herectx);
6581 }
6582
6583# check for gcc specific __FUNCTION__
6584 if ($line =~ /\b__FUNCTION__\b/) {
6585 if (WARN("USE_FUNC",
6586 "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) &&
6587 $fix) {
6588 $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
6589 }
6590 }
6591
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006592# check for uses of __DATE__, __TIME__, __TIMESTAMP__
6593 while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) {
6594 ERROR("DATE_TIME",
6595 "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr);
6596 }
6597
Carles Cufi43ae4a72022-10-26 20:34:15 +02006598# check for uses of __BYTE_ORDER__
6599 while ($line =~ /\b(__BYTE_ORDER__)\b/g) {
6600 ERROR("BYTE_ORDER",
Carles Cufi192d01e2022-10-28 12:29:34 +02006601 "Use of the '$1' macro is disallowed. Use CONFIG_(BIG|LITTLE)_ENDIAN instead\n" . $herecurr);
Carles Cufi43ae4a72022-10-26 20:34:15 +02006602 }
6603
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006604# check for use of yield()
6605 if ($line =~ /\byield\s*\(\s*\)/) {
6606 WARN("YIELD",
6607 "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr);
6608 }
6609
6610# check for comparisons against true and false
6611 if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {
6612 my $lead = $1;
6613 my $arg = $2;
6614 my $test = $3;
6615 my $otype = $4;
6616 my $trail = $5;
6617 my $op = "!";
6618
6619 ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i);
6620
6621 my $type = lc($otype);
6622 if ($type =~ /^(?:true|false)$/) {
6623 if (("$test" eq "==" && "$type" eq "true") ||
6624 ("$test" eq "!=" && "$type" eq "false")) {
6625 $op = "";
6626 }
6627
6628 CHK("BOOL_COMPARISON",
6629 "Using comparison to $otype is error prone\n" . $herecurr);
6630
6631## maybe suggesting a correct construct would better
6632## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr);
6633
6634 }
6635 }
6636
6637# check for semaphores initialized locked
6638 if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
6639 WARN("CONSIDER_COMPLETION",
6640 "consider using a completion\n" . $herecurr);
6641 }
6642
6643# recommend kstrto* over simple_strto* and strict_strto*
6644 if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
6645 WARN("CONSIDER_KSTRTO",
6646 "$1 is obsolete, use k$3 instead\n" . $herecurr);
6647 }
6648
6649# check for __initcall(), use device_initcall() explicitly or more appropriate function please
6650 if ($line =~ /^.\s*__initcall\s*\(/) {
6651 WARN("USE_DEVICE_INITCALL",
6652 "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
6653 }
6654
Peter Bigot5b10fac2020-03-26 11:16:33 -05006655# check for spin_is_locked(), suggest lockdep instead
6656 if ($line =~ /\bspin_is_locked\(/) {
6657 WARN("USE_LOCKDEP",
6658 "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
6659 }
6660
6661# check for deprecated apis
6662 if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
6663 my $deprecated_api = $1;
6664 my $new_api = $deprecated_apis{$deprecated_api};
6665 WARN("DEPRECATED_API",
6666 "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
6667 }
6668
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006669# check for various structs that are normally const (ops, kgdb, device_tree)
Anas Nashif1eb244c2017-10-01 17:06:36 -04006670# and avoid what seem like struct definitions 'struct foo {'
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006671 if (defined($const_structs) &&
6672 $line !~ /\bconst\b/ &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006673 $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006674 WARN("CONST_STRUCT",
Anas Nashif1eb244c2017-10-01 17:06:36 -04006675 "struct $1 should normally be const\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006676 }
6677
6678# use of NR_CPUS is usually wrong
6679# ignore definitions of NR_CPUS and usage to define arrays as likely right
6680 if ($line =~ /\bNR_CPUS\b/ &&
6681 $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
6682 $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
6683 $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
6684 $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
6685 $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
6686 {
6687 WARN("NR_CPUS",
6688 "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
6689 }
6690
6691# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
6692 if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
6693 ERROR("DEFINE_ARCH_HAS",
6694 "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
6695 }
6696
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006697# likely/unlikely comparisons similar to "(likely(foo) > 0)"
Peter Bigot5b10fac2020-03-26 11:16:33 -05006698 if ($perl_version_ok &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006699 $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
6700 WARN("LIKELY_MISUSE",
6701 "Using $1 should generally have parentheses around the comparison\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006702 }
6703
Peter Bigot5b10fac2020-03-26 11:16:33 -05006704# nested likely/unlikely calls
6705 if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
6706 WARN("LIKELY_MISUSE",
6707 "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
6708 }
6709
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006710# whine mightly about in_atomic
6711 if ($line =~ /\bin_atomic\s*\(/) {
6712 if ($realfile =~ m@^drivers/@) {
6713 ERROR("IN_ATOMIC",
6714 "do not use in_atomic in drivers\n" . $herecurr);
6715 } elsif ($realfile !~ m@^kernel/@) {
6716 WARN("IN_ATOMIC",
6717 "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
6718 }
6719 }
6720
Anas Nashif1eb244c2017-10-01 17:06:36 -04006721# check for mutex_trylock_recursive usage
6722 if ($line =~ /mutex_trylock_recursive/) {
6723 ERROR("LOCKING",
6724 "recursive locking is bad, do not use this ever.\n" . $herecurr);
6725 }
6726
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006727# check for lockdep_set_novalidate_class
6728 if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
6729 $line =~ /__lockdep_no_validate__\s*\)/ ) {
6730 if ($realfile !~ m@^kernel/lockdep@ &&
6731 $realfile !~ m@^include/linux/lockdep@ &&
6732 $realfile !~ m@^drivers/base/core@) {
6733 ERROR("LOCKDEP",
6734 "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
6735 }
6736 }
6737
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006738 if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ ||
6739 $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006740 WARN("EXPORTED_WORLD_WRITABLE",
6741 "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
6742 }
6743
Peter Bigot5b10fac2020-03-26 11:16:33 -05006744# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
6745# and whether or not function naming is typical and if
6746# DEVICE_ATTR permissions uses are unusual too
6747 if ($perl_version_ok &&
6748 defined $stat &&
6749 $stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
6750 my $var = $1;
6751 my $perms = $2;
6752 my $show = $3;
6753 my $store = $4;
6754 my $octal_perms = perms_to_octal($perms);
6755 if ($show =~ /^${var}_show$/ &&
6756 $store =~ /^${var}_store$/ &&
6757 $octal_perms eq "0644") {
6758 if (WARN("DEVICE_ATTR_RW",
6759 "Use DEVICE_ATTR_RW\n" . $herecurr) &&
6760 $fix) {
6761 $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
6762 }
6763 } elsif ($show =~ /^${var}_show$/ &&
6764 $store =~ /^NULL$/ &&
6765 $octal_perms eq "0444") {
6766 if (WARN("DEVICE_ATTR_RO",
6767 "Use DEVICE_ATTR_RO\n" . $herecurr) &&
6768 $fix) {
6769 $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
6770 }
6771 } elsif ($show =~ /^NULL$/ &&
6772 $store =~ /^${var}_store$/ &&
6773 $octal_perms eq "0200") {
6774 if (WARN("DEVICE_ATTR_WO",
6775 "Use DEVICE_ATTR_WO\n" . $herecurr) &&
6776 $fix) {
6777 $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
6778 }
6779 } elsif ($octal_perms eq "0644" ||
6780 $octal_perms eq "0444" ||
6781 $octal_perms eq "0200") {
6782 my $newshow = "$show";
6783 $newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
6784 my $newstore = $store;
6785 $newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
6786 my $rename = "";
6787 if ($show ne $newshow) {
6788 $rename .= " '$show' to '$newshow'";
6789 }
6790 if ($store ne $newstore) {
6791 $rename .= " '$store' to '$newstore'";
6792 }
6793 WARN("DEVICE_ATTR_FUNCTIONS",
6794 "Consider renaming function(s)$rename\n" . $herecurr);
6795 } else {
6796 WARN("DEVICE_ATTR_PERMS",
6797 "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr);
6798 }
6799 }
6800
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006801# Mode permission misuses where it seems decimal should be octal
6802# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
Peter Bigot5b10fac2020-03-26 11:16:33 -05006803# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
6804# specific definition of not visible in sysfs.
6805# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
6806# use the default permissions
6807 if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006808 defined $stat &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006809 $line =~ /$mode_perms_search/) {
6810 foreach my $entry (@mode_permission_funcs) {
6811 my $func = $entry->[0];
6812 my $arg_pos = $entry->[1];
6813
Anas Nashif0f3d5472016-11-07 15:57:57 -05006814 my $lc = $stat =~ tr@\n@@;
6815 $lc = $lc + $linenr;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006816 my $stat_real = get_stat_real($linenr, $lc);
Anas Nashif0f3d5472016-11-07 15:57:57 -05006817
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006818 my $skip_args = "";
6819 if ($arg_pos > 1) {
6820 $arg_pos--;
6821 $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
6822 }
Anas Nashif0f3d5472016-11-07 15:57:57 -05006823 my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
6824 if ($stat =~ /$test/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006825 my $val = $1;
6826 $val = $6 if ($skip_args ne "");
Peter Bigot5b10fac2020-03-26 11:16:33 -05006827 if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
6828 (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
6829 ($val =~ /^$Octal$/ && length($val) ne 4))) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006830 ERROR("NON_OCTAL_PERMISSIONS",
Anas Nashif0f3d5472016-11-07 15:57:57 -05006831 "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
6832 }
6833 if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006834 ERROR("EXPORTED_WORLD_WRITABLE",
Anas Nashif0f3d5472016-11-07 15:57:57 -05006835 "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006836 }
6837 }
6838 }
6839 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006840
Anas Nashif0f3d5472016-11-07 15:57:57 -05006841# check for uses of S_<PERMS> that could be octal for readability
Peter Bigot5b10fac2020-03-26 11:16:33 -05006842 while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
6843 my $oval = $1;
6844 my $octal = perms_to_octal($oval);
Anas Nashif0f3d5472016-11-07 15:57:57 -05006845 if (WARN("SYMBOLIC_PERMS",
6846 "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
6847 $fix) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05006848 $fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
Anas Nashif0f3d5472016-11-07 15:57:57 -05006849 }
6850 }
6851
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006852# validate content of MODULE_LICENSE against list from include/linux/module.h
6853 if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
6854 my $extracted_string = get_quoted_string($line, $rawline);
6855 my $valid_licenses = qr{
6856 GPL|
6857 GPL\ v2|
6858 GPL\ and\ additional\ rights|
6859 Dual\ BSD/GPL|
6860 Dual\ MIT/GPL|
6861 Dual\ MPL/GPL|
6862 Proprietary
6863 }x;
6864 if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) {
6865 WARN("MODULE_LICENSE",
6866 "unknown module license " . $extracted_string . "\n" . $herecurr);
6867 }
6868 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006869
6870# check for sysctl duplicate constants
6871 if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
6872 WARN("DUPLICATED_SYSCTL_CONST",
6873 "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
6874 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006875 }
6876
6877 # If we have no input at all, then there is nothing to report on
6878 # so just keep quiet.
6879 if ($#rawlines == -1) {
6880 exit(0);
6881 }
6882
6883 # In mailback mode only produce a report in the negative, for
6884 # things that appear to be patches.
6885 if ($mailback && ($clean == 1 || !$is_patch)) {
6886 exit(0);
6887 }
6888
6889 # This is not a patch, and we are are in 'no-patch' mode so
6890 # just keep quiet.
6891 if (!$chk_patch && !$is_patch) {
6892 exit(0);
6893 }
6894
Peter Bigot5b10fac2020-03-26 11:16:33 -05006895 if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006896 ERROR("NOT_UNIFIED_DIFF",
6897 "Does not appear to be a unified-diff format patch\n");
6898 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006899 if ($is_patch && $has_commit_log && $chk_signoff) {
6900 if ($signoff == 0) {
6901 ERROR("MISSING_SIGN_OFF",
6902 "Missing Signed-off-by: line(s)\n");
6903 } elsif (!$authorsignoff) {
6904 WARN("NO_AUTHOR_SIGN_OFF",
6905 "Missing Signed-off-by: line by nominal patch author '$author'\n");
6906 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006907 }
6908
6909 print report_dump();
6910 if ($summary && !($clean == 1 && $quiet == 1)) {
6911 print "$filename " if ($summary_file);
6912 print "total: $cnt_error errors, $cnt_warn warnings, " .
6913 (($check)? "$cnt_chk checks, " : "") .
6914 "$cnt_lines lines checked\n";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006915 }
6916
6917 if ($quiet == 0) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05006918 # If there were any defects found and not already fixing them
6919 if (!$clean and !$fix) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006920 print << "EOM"
6921
Anas Nashif0f3d5472016-11-07 15:57:57 -05006922NOTE: For some of the reported defects, checkpatch may be able to
6923 mechanically convert to the typical style using --fix or --fix-inplace.
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006924EOM
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006925 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04006926 # If there were whitespace errors which cleanpatch can fix
6927 # then suggest that.
6928 if ($rpt_cleaners) {
6929 $rpt_cleaners = 0;
6930 print << "EOM"
6931
6932NOTE: Whitespace errors detected.
6933 You may wish to use scripts/cleanpatch or scripts/cleanfile
6934EOM
6935 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006936 }
6937
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006938 if ($clean == 0 && $fix &&
6939 ("@rawlines" ne "@fixed" ||
6940 $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
6941 my $newfile = $filename;
6942 $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
6943 my $linecount = 0;
6944 my $f;
6945
6946 @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
6947
6948 open($f, '>', $newfile)
6949 or die "$P: Can't open $newfile for write\n";
6950 foreach my $fixed_line (@fixed) {
6951 $linecount++;
6952 if ($file) {
6953 if ($linecount > 3) {
6954 $fixed_line =~ s/^\+//;
6955 print $f $fixed_line . "\n";
6956 }
6957 } else {
6958 print $f $fixed_line . "\n";
6959 }
6960 }
6961 close($f);
6962
6963 if (!$quiet) {
6964 print << "EOM";
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006965
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006966Wrote EXPERIMENTAL --fix correction(s) to '$newfile'
6967
6968Do _NOT_ trust the results written to this file.
6969Do _NOT_ submit these changes without inspecting them for correctness.
6970
6971This EXPERIMENTAL file is simply a convenience to help rewrite patches.
6972No warranties, expressed or implied...
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006973EOM
6974 }
6975 }
6976
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006977 if ($quiet == 0) {
6978 print "\n";
6979 if ($clean == 1) {
6980 print "$vname has no obvious style problems and is ready for submission.\n";
6981 } else {
6982 print "$vname has style problems, please review.\n";
6983 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006984 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006985 return $clean;
6986}