blob: 27fbd880ef6397f87e141d3d35830e668ab002c9 [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 }
4422 while ($line =~ /(.*?\s)\[/g) {
4423 my ($where, $prefix) = ($-[1], $1);
4424 if ($prefix !~ /$Type\s+$/ &&
4425 ($where != 0 || $prefix !~ /^.\s+$/) &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05004426 $prefix !~ /[{,:]\s+$/ &&
Anas Nashif98c50de2015-11-06 18:23:35 -05004427 $prefix !~ /:\s+$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004428 if (ERROR("BRACKET_SPACE",
4429 "space prohibited before open square bracket '['\n" . $herecurr) &&
4430 $fix) {
4431 $fixed[$fixlinenr] =~
4432 s/^(\+.*?)\s+\[/$1\[/;
4433 }
4434 }
4435 }
4436
4437# check for spaces between functions and their parentheses.
4438 while ($line =~ /($Ident)\s+\(/g) {
4439 my $name = $1;
4440 my $ctx_before = substr($line, 0, $-[1]);
4441 my $ctx = "$ctx_before$name";
4442
4443 # Ignore those directives where spaces _are_ permitted.
4444 if ($name =~ /^(?:
4445 if|for|while|switch|return|case|
4446 volatile|__volatile__|
4447 __attribute__|format|__extension__|
4448 asm|__asm__)$/x)
4449 {
4450 # cpp #define statements have non-optional spaces, ie
4451 # if there is a space between the name and the open
4452 # parenthesis it is simply not a parameter group.
4453 } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
4454
4455 # cpp #elif statement condition may start with a (
4456 } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
4457
4458 # If this whole things ends with a type its most
4459 # likely a typedef for a function.
4460 } elsif ($ctx =~ /$Type$/) {
4461
4462 } else {
4463 if (WARN("SPACING",
4464 "space prohibited between function name and open parenthesis '('\n" . $herecurr) &&
4465 $fix) {
4466 $fixed[$fixlinenr] =~
4467 s/\b$name\s+\(/$name\(/;
4468 }
4469 }
4470 }
4471
4472# Check operator spacing.
4473 if (!($line=~/\#\s*include/)) {
4474 my $fixed_line = "";
4475 my $line_fixed = 0;
4476
4477 my $ops = qr{
4478 <<=|>>=|<=|>=|==|!=|
4479 \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
4480 =>|->|<<|>>|<|>|=|!|~|
4481 &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
4482 \?:|\?|:
4483 }x;
4484 my @elements = split(/($ops|;)/, $opline);
4485
4486## print("element count: <" . $#elements . ">\n");
4487## foreach my $el (@elements) {
4488## print("el: <$el>\n");
4489## }
4490
4491 my @fix_elements = ();
4492 my $off = 0;
4493
4494 foreach my $el (@elements) {
4495 push(@fix_elements, substr($rawline, $off, length($el)));
4496 $off += length($el);
4497 }
4498
4499 $off = 0;
4500
4501 my $blank = copy_spacing($opline);
4502 my $last_after = -1;
4503
4504 for (my $n = 0; $n < $#elements; $n += 2) {
4505
4506 my $good = $fix_elements[$n] . $fix_elements[$n + 1];
4507
4508## print("n: <$n> good: <$good>\n");
4509
4510 $off += length($elements[$n]);
4511
4512 # Pick up the preceding and succeeding characters.
4513 my $ca = substr($opline, 0, $off);
4514 my $cc = '';
4515 if (length($opline) >= ($off + length($elements[$n + 1]))) {
4516 $cc = substr($opline, $off + length($elements[$n + 1]));
4517 }
4518 my $cb = "$ca$;$cc";
4519
4520 my $a = '';
4521 $a = 'V' if ($elements[$n] ne '');
4522 $a = 'W' if ($elements[$n] =~ /\s$/);
4523 $a = 'C' if ($elements[$n] =~ /$;$/);
4524 $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
4525 $a = 'O' if ($elements[$n] eq '');
4526 $a = 'E' if ($ca =~ /^\s*$/);
4527
4528 my $op = $elements[$n + 1];
4529
4530 my $c = '';
4531 if (defined $elements[$n + 2]) {
4532 $c = 'V' if ($elements[$n + 2] ne '');
4533 $c = 'W' if ($elements[$n + 2] =~ /^\s/);
4534 $c = 'C' if ($elements[$n + 2] =~ /^$;/);
4535 $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
4536 $c = 'O' if ($elements[$n + 2] eq '');
4537 $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
4538 } else {
4539 $c = 'E';
4540 }
4541
4542 my $ctx = "${a}x${c}";
4543
4544 my $at = "(ctx:$ctx)";
4545
4546 my $ptr = substr($blank, 0, $off) . "^";
4547 my $hereptr = "$hereline$ptr\n";
4548
4549 # Pull out the value of this operator.
4550 my $op_type = substr($curr_values, $off + 1, 1);
4551
4552 # Get the full operator variant.
4553 my $opv = $op . substr($curr_vars, $off, 1);
4554
4555 # Ignore operators passed as parameters.
4556 if ($op_type ne 'V' &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004557 $ca =~ /\s$/ && $cc =~ /^\s*[,\)]/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004558
4559# # Ignore comments
4560# } elsif ($op =~ /^$;+$/) {
4561
4562 # ; should have either the end of line or a space or \ after it
4563 } elsif ($op eq ';') {
4564 if ($ctx !~ /.x[WEBC]/ &&
4565 $cc !~ /^\\/ && $cc !~ /^;/) {
4566 if (ERROR("SPACING",
4567 "space required after that '$op' $at\n" . $hereptr)) {
4568 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
4569 $line_fixed = 1;
4570 }
4571 }
4572
4573 # // is a comment
4574 } elsif ($op eq '//') {
4575
4576 # : when part of a bitfield
4577 } elsif ($opv eq ':B') {
4578 # skip the bitfield test for now
4579
4580 # No spaces for:
4581 # ->
4582 } elsif ($op eq '->') {
4583 if ($ctx =~ /Wx.|.xW/) {
4584 if (ERROR("SPACING",
4585 "spaces prohibited around that '$op' $at\n" . $hereptr)) {
4586 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4587 if (defined $fix_elements[$n + 2]) {
4588 $fix_elements[$n + 2] =~ s/^\s+//;
4589 }
4590 $line_fixed = 1;
4591 }
4592 }
4593
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004594 # , must not have a space before and must have a space on the right.
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004595 } elsif ($op eq ',') {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004596 my $rtrim_before = 0;
4597 my $space_after = 0;
4598 if ($ctx =~ /Wx./) {
4599 if (ERROR("SPACING",
4600 "space prohibited before that '$op' $at\n" . $hereptr)) {
4601 $line_fixed = 1;
4602 $rtrim_before = 1;
4603 }
4604 }
Anas Nashife7ee0832016-02-20 14:13:16 -05004605 if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/ && $cc !~ /^\)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004606 if (ERROR("SPACING",
4607 "space required after that '$op' $at\n" . $hereptr)) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004608 $line_fixed = 1;
4609 $last_after = $n;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004610 $space_after = 1;
4611 }
4612 }
4613 if ($rtrim_before || $space_after) {
4614 if ($rtrim_before) {
4615 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4616 } else {
4617 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
4618 }
4619 if ($space_after) {
4620 $good .= " ";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004621 }
4622 }
4623
4624 # '*' as part of a type definition -- reported already.
4625 } elsif ($opv eq '*_') {
4626 #warn "'*' is part of type\n";
4627
4628 # unary operators should have a space before and
4629 # none after. May be left adjacent to another
4630 # unary operator, or a cast
4631 } elsif ($op eq '!' || $op eq '~' ||
4632 $opv eq '*U' || $opv eq '-U' ||
4633 $opv eq '&U' || $opv eq '&&U') {
4634 if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
4635 if (ERROR("SPACING",
4636 "space required before that '$op' $at\n" . $hereptr)) {
4637 if ($n != $last_after + 2) {
4638 $good = $fix_elements[$n] . " " . ltrim($fix_elements[$n + 1]);
4639 $line_fixed = 1;
4640 }
4641 }
4642 }
4643 if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
4644 # A unary '*' may be const
4645
4646 } elsif ($ctx =~ /.xW/) {
4647 if (ERROR("SPACING",
4648 "space prohibited after that '$op' $at\n" . $hereptr)) {
4649 $good = $fix_elements[$n] . rtrim($fix_elements[$n + 1]);
4650 if (defined $fix_elements[$n + 2]) {
4651 $fix_elements[$n + 2] =~ s/^\s+//;
4652 }
4653 $line_fixed = 1;
4654 }
4655 }
4656
4657 # unary ++ and unary -- are allowed no space on one side.
4658 } elsif ($op eq '++' or $op eq '--') {
4659 if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
4660 if (ERROR("SPACING",
4661 "space required one side of that '$op' $at\n" . $hereptr)) {
4662 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]) . " ";
4663 $line_fixed = 1;
4664 }
4665 }
4666 if ($ctx =~ /Wx[BE]/ ||
4667 ($ctx =~ /Wx./ && $cc =~ /^;/)) {
4668 if (ERROR("SPACING",
4669 "space prohibited before that '$op' $at\n" . $hereptr)) {
4670 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4671 $line_fixed = 1;
4672 }
4673 }
4674 if ($ctx =~ /ExW/) {
4675 if (ERROR("SPACING",
4676 "space prohibited after that '$op' $at\n" . $hereptr)) {
4677 $good = $fix_elements[$n] . trim($fix_elements[$n + 1]);
4678 if (defined $fix_elements[$n + 2]) {
4679 $fix_elements[$n + 2] =~ s/^\s+//;
4680 }
4681 $line_fixed = 1;
4682 }
4683 }
4684
4685 # << and >> may either have or not have spaces both sides
4686 } elsif ($op eq '<<' or $op eq '>>' or
4687 $op eq '&' or $op eq '^' or $op eq '|' or
4688 $op eq '+' or $op eq '-' or
4689 $op eq '*' or $op eq '/' or
4690 $op eq '%')
4691 {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004692 if ($check) {
4693 if (defined $fix_elements[$n + 2] && $ctx !~ /[EW]x[EW]/) {
4694 if (CHK("SPACING",
4695 "spaces preferred around that '$op' $at\n" . $hereptr)) {
4696 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4697 $fix_elements[$n + 2] =~ s/^\s+//;
4698 $line_fixed = 1;
4699 }
4700 } elsif (!defined $fix_elements[$n + 2] && $ctx !~ /Wx[OE]/) {
4701 if (CHK("SPACING",
4702 "space preferred before that '$op' $at\n" . $hereptr)) {
4703 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]);
4704 $line_fixed = 1;
4705 }
4706 }
4707 } elsif ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004708 if (ERROR("SPACING",
4709 "need consistent spacing around '$op' $at\n" . $hereptr)) {
4710 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4711 if (defined $fix_elements[$n + 2]) {
4712 $fix_elements[$n + 2] =~ s/^\s+//;
4713 }
4714 $line_fixed = 1;
4715 }
4716 }
4717
4718 # A colon needs no spaces before when it is
4719 # terminating a case value or a label.
4720 } elsif ($opv eq ':C' || $opv eq ':L') {
4721 if ($ctx =~ /Wx./) {
4722 if (ERROR("SPACING",
4723 "space prohibited before that '$op' $at\n" . $hereptr)) {
4724 $good = rtrim($fix_elements[$n]) . trim($fix_elements[$n + 1]);
4725 $line_fixed = 1;
4726 }
4727 }
4728
4729 # All the others need spaces both sides.
4730 } elsif ($ctx !~ /[EWC]x[CWE]/) {
4731 my $ok = 0;
4732
4733 # Ignore email addresses <foo@bar>
4734 if (($op eq '<' &&
4735 $cc =~ /^\S+\@\S+>/) ||
4736 ($op eq '>' &&
4737 $ca =~ /<\S+\@\S+$/))
4738 {
Peter A. Bigote49e3c82020-08-10 10:37:32 -05004739 $ok = 1;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004740 }
4741
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004742 # for asm volatile statements
4743 # ignore a colon with another
4744 # colon immediately before or after
4745 if (($op eq ':') &&
4746 ($ca =~ /:$/ || $cc =~ /^:/)) {
4747 $ok = 1;
4748 }
4749
Gerard Marull-Paretas6a273832022-03-07 16:03:08 +01004750 # some macros require a separator
4751 # argument to be in parentheses,
4752 # e.g. (||).
4753 if ($ca =~ /\($/ || $cc =~ /^\)/) {
4754 $ok = 1;
4755 }
4756
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004757 # messages are ERROR, but ?: are CHK
4758 if ($ok == 0) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04004759 my $msg_level = \&ERROR;
4760 $msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004761
Anas Nashif1eb244c2017-10-01 17:06:36 -04004762 if (&{$msg_level}("SPACING",
4763 "spaces required around that '$op' $at\n" . $hereptr)) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004764 $good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
4765 if (defined $fix_elements[$n + 2]) {
4766 $fix_elements[$n + 2] =~ s/^\s+//;
4767 }
4768 $line_fixed = 1;
4769 }
4770 }
4771 }
4772 $off += length($elements[$n + 1]);
4773
4774## print("n: <$n> GOOD: <$good>\n");
4775
4776 $fixed_line = $fixed_line . $good;
4777 }
4778
4779 if (($#elements % 2) == 0) {
4780 $fixed_line = $fixed_line . $fix_elements[$#elements];
4781 }
4782
4783 if ($fix && $line_fixed && $fixed_line ne $fixed[$fixlinenr]) {
4784 $fixed[$fixlinenr] = $fixed_line;
4785 }
4786
4787
4788 }
4789
4790# check for whitespace before a non-naked semicolon
4791 if ($line =~ /^\+.*\S\s+;\s*$/) {
4792 if (WARN("SPACING",
4793 "space prohibited before semicolon\n" . $herecurr) &&
4794 $fix) {
4795 1 while $fixed[$fixlinenr] =~
4796 s/^(\+.*\S)\s+;/$1;/;
4797 }
4798 }
4799
4800# check for multiple assignments
4801 if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
4802 CHK("MULTIPLE_ASSIGNMENTS",
4803 "multiple assignments should be avoided\n" . $herecurr);
4804 }
4805
4806## # check for multiple declarations, allowing for a function declaration
4807## # continuation.
4808## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
4809## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
4810##
4811## # Remove any bracketed sections to ensure we do not
4812## # falsly report the parameters of functions.
4813## my $ln = $line;
4814## while ($ln =~ s/\([^\(\)]*\)//g) {
4815## }
4816## if ($ln =~ /,/) {
4817## WARN("MULTIPLE_DECLARATION",
4818## "declaring multiple variables together should be avoided\n" . $herecurr);
4819## }
4820## }
4821
4822#need space before brace following if, while, etc
Anas Nashif0f3d5472016-11-07 15:57:57 -05004823 if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
Peter Bigot5b10fac2020-03-26 11:16:33 -05004824 $line =~ /\b(?:else|do)\{/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004825 if (ERROR("SPACING",
4826 "space required before the open brace '{'\n" . $herecurr) &&
4827 $fix) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05004828 $fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004829 }
4830 }
4831
4832## # check for blank lines before declarations
4833## if ($line =~ /^.\t+$Type\s+$Ident(?:\s*=.*)?;/ &&
4834## $prevrawline =~ /^.\s*$/) {
4835## WARN("SPACING",
4836## "No blank lines before declarations\n" . $hereprev);
4837## }
4838##
4839
4840# closing brace should have a space following it when it has anything
4841# on the line
Peter Bigot5b10fac2020-03-26 11:16:33 -05004842 if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004843 if (ERROR("SPACING",
4844 "space required after that close brace '}'\n" . $herecurr) &&
4845 $fix) {
4846 $fixed[$fixlinenr] =~
4847 s/}((?!(?:,|;|\)))\S)/} $1/;
4848 }
4849 }
4850
4851# check spacing on square brackets
4852 if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
4853 if (ERROR("SPACING",
4854 "space prohibited after that open square bracket '['\n" . $herecurr) &&
4855 $fix) {
4856 $fixed[$fixlinenr] =~
4857 s/\[\s+/\[/;
4858 }
4859 }
4860 if ($line =~ /\s\]/) {
4861 if (ERROR("SPACING",
4862 "space prohibited before that close square bracket ']'\n" . $herecurr) &&
4863 $fix) {
4864 $fixed[$fixlinenr] =~
4865 s/\s+\]/\]/;
4866 }
4867 }
4868
4869# check spacing on parentheses
4870 if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
4871 $line !~ /for\s*\(\s+;/) {
4872 if (ERROR("SPACING",
4873 "space prohibited after that open parenthesis '('\n" . $herecurr) &&
4874 $fix) {
4875 $fixed[$fixlinenr] =~
4876 s/\(\s+/\(/;
4877 }
4878 }
4879 if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
4880 $line !~ /for\s*\(.*;\s+\)/ &&
4881 $line !~ /:\s+\)/) {
4882 if (ERROR("SPACING",
4883 "space prohibited before that close parenthesis ')'\n" . $herecurr) &&
4884 $fix) {
4885 $fixed[$fixlinenr] =~
4886 s/\s+\)/\)/;
4887 }
4888 }
4889
4890# check unnecessary parentheses around addressof/dereference single $Lvals
4891# ie: &(foo->bar) should be &foo->bar and *(foo->bar) should be *foo->bar
4892
4893 while ($line =~ /(?:[^&]&\s*|\*)\(\s*($Ident\s*(?:$Member\s*)+)\s*\)/g) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04004894 my $var = $1;
4895 if (CHK("UNNECESSARY_PARENTHESES",
4896 "Unnecessary parentheses around $var\n" . $herecurr) &&
4897 $fix) {
4898 $fixed[$fixlinenr] =~ s/\(\s*\Q$var\E\s*\)/$var/;
4899 }
4900 }
4901
4902# check for unnecessary parentheses around function pointer uses
4903# ie: (foo->bar)(); should be foo->bar();
4904# but not "if (foo->bar) (" to avoid some false positives
4905 if ($line =~ /(\bif\s*|)(\(\s*$Ident\s*(?:$Member\s*)+\))[ \t]*\(/ && $1 !~ /^if/) {
4906 my $var = $2;
4907 if (CHK("UNNECESSARY_PARENTHESES",
4908 "Unnecessary parentheses around function pointer $var\n" . $herecurr) &&
4909 $fix) {
4910 my $var2 = deparenthesize($var);
4911 $var2 =~ s/\s//g;
4912 $fixed[$fixlinenr] =~ s/\Q$var\E/$var2/;
4913 }
4914 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004915
Anas Nashif1eb244c2017-10-01 17:06:36 -04004916# check for unnecessary parentheses around comparisons in if uses
Peter Bigot5b10fac2020-03-26 11:16:33 -05004917# when !drivers/staging or command-line uses --strict
4918 if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
4919 $perl_version_ok && defined($stat) &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04004920 $stat =~ /(^.\s*if\s*($balanced_parens))/) {
4921 my $if_stat = $1;
4922 my $test = substr($2, 1, -1);
4923 my $herectx;
4924 while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) {
4925 my $match = $1;
4926 # avoid parentheses around potential macro args
4927 next if ($match =~ /^\s*\w+\s*$/);
4928 if (!defined($herectx)) {
4929 $herectx = $here . "\n";
4930 my $cnt = statement_rawlines($if_stat);
4931 for (my $n = 0; $n < $cnt; $n++) {
4932 my $rl = raw_line($linenr, $n);
4933 $herectx .= $rl . "\n";
4934 last if $rl =~ /^[ \+].*\{/;
4935 }
4936 }
4937 CHK("UNNECESSARY_PARENTHESES",
4938 "Unnecessary parentheses around '$match'\n" . $herectx);
4939 }
4940 }
4941
Joe Perches6cdeefc2021-06-30 18:56:22 -07004942# check that goto labels aren't indented (allow a single space indentation)
4943# and ignore bitfield definitions like foo:1
4944# Strictly, labels can have whitespace after the identifier and before the :
4945# but this is not allowed here as many ?: uses would appear to be labels
4946 if ($sline =~ /^.\s+[A-Za-z_][A-Za-z\d_]*:(?!\s*\d+)/ &&
4947 $sline !~ /^. [A-Za-z\d_][A-Za-z\d_]*:/ &&
4948 $sline !~ /^.\s+default:/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004949 if (WARN("INDENTED_LABEL",
4950 "labels should not be indented\n" . $herecurr) &&
4951 $fix) {
4952 $fixed[$fixlinenr] =~
4953 s/^(.)\s+/$1/;
4954 }
4955 }
4956
4957# return is not a function
4958 if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
4959 my $spacing = $1;
Peter Bigot5b10fac2020-03-26 11:16:33 -05004960 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004961 $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
4962 my $value = $1;
4963 $value = deparenthesize($value);
4964 if ($value =~ m/^\s*$FuncArg\s*(?:\?|$)/) {
4965 ERROR("RETURN_PARENTHESES",
4966 "return is not a function, parentheses are not required\n" . $herecurr);
4967 }
4968 } elsif ($spacing !~ /\s+/) {
4969 ERROR("SPACING",
4970 "space required before the open parenthesis '('\n" . $herecurr);
4971 }
4972 }
4973
4974# unnecessary return in a void function
4975# at end-of-function, with the previous line a single leading tab, then return;
4976# and the line before that not a goto label target like "out:"
4977 if ($sline =~ /^[ \+]}\s*$/ &&
4978 $prevline =~ /^\+\treturn\s*;\s*$/ &&
4979 $linenr >= 3 &&
4980 $lines[$linenr - 3] =~ /^[ +]/ &&
4981 $lines[$linenr - 3] !~ /^[ +]\s*$Ident\s*:/) {
4982 WARN("RETURN_VOID",
4983 "void function return statements are not generally useful\n" . $hereprev);
4984 }
4985
4986# if statements using unnecessary parentheses - ie: if ((foo == bar))
Peter Bigot5b10fac2020-03-26 11:16:33 -05004987 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07004988 $line =~ /\bif\s*((?:\(\s*){2,})/) {
4989 my $openparens = $1;
4990 my $count = $openparens =~ tr@\(@\(@;
4991 my $msg = "";
4992 if ($line =~ /\bif\s*(?:\(\s*){$count,$count}$LvalOrFunc\s*($Compare)\s*$LvalOrFunc(?:\s*\)){$count,$count}/) {
4993 my $comp = $4; #Not $1 because of $LvalOrFunc
4994 $msg = " - maybe == should be = ?" if ($comp eq "==");
4995 WARN("UNNECESSARY_PARENTHESES",
4996 "Unnecessary parentheses$msg\n" . $herecurr);
4997 }
4998 }
4999
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005000# comparisons with a constant or upper case identifier on the left
5001# avoid cases like "foo + BAR < baz"
5002# only fix matches surrounded by parentheses to avoid incorrect
5003# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
Peter Bigot5b10fac2020-03-26 11:16:33 -05005004 if ($perl_version_ok &&
Christopher Friedta3725412024-01-19 07:37:33 -05005005 !($line =~ /^\+(.*)($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*(.*)($Constant|[A-Z_][A-Z0-9_]*)(.*)/) &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005006 $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
5007 my $lead = $1;
5008 my $const = $2;
5009 my $comp = $3;
5010 my $to = $4;
5011 my $newcomp = $comp;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005012 if ($lead !~ /(?:$Operators|\.)\s*$/ &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005013 $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
5014 WARN("CONSTANT_COMPARISON",
5015 "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
5016 $fix) {
5017 if ($comp eq "<") {
5018 $newcomp = ">";
5019 } elsif ($comp eq "<=") {
5020 $newcomp = ">=";
5021 } elsif ($comp eq ">") {
5022 $newcomp = "<";
5023 } elsif ($comp eq ">=") {
5024 $newcomp = "<=";
5025 }
5026 $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/;
5027 }
5028 }
5029
5030# Return of what appears to be an errno should normally be negative
5031 if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005032 my $name = $1;
5033 if ($name ne 'EOF' && $name ne 'ERROR') {
Christopher Friedt6e27b7d2023-07-05 17:36:49 -04005034 # only print this warning if not dealing with 'lib/posix/*.c'
5035 if ($realfile =~ /.*\/lib\/posix\/*.c/) {
5036 WARN("USE_NEGATIVE_ERRNO",
5037 "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
5038 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005039 }
5040 }
5041
5042# Need a space before open parenthesis after if, while etc
5043 if ($line =~ /\b(if|while|for|switch)\(/) {
5044 if (ERROR("SPACING",
5045 "space required before the open parenthesis '('\n" . $herecurr) &&
5046 $fix) {
5047 $fixed[$fixlinenr] =~
5048 s/\b(if|while|for|switch)\(/$1 \(/;
5049 }
5050 }
5051
5052# Check for illegal assignment in if conditional -- and check for trailing
5053# statements after the conditional.
5054 if ($line =~ /do\s*(?!{)/) {
5055 ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
5056 ctx_statement_block($linenr, $realcnt, 0)
5057 if (!defined $stat);
5058 my ($stat_next) = ctx_statement_block($line_nr_next,
5059 $remain_next, $off_next);
5060 $stat_next =~ s/\n./\n /g;
5061 ##print "stat<$stat> stat_next<$stat_next>\n";
5062
5063 if ($stat_next =~ /^\s*while\b/) {
5064 # If the statement carries leading newlines,
5065 # then count those as offsets.
5066 my ($whitespace) =
5067 ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
5068 my $offset =
5069 statement_rawlines($whitespace) - 1;
5070
5071 $suppress_whiletrailers{$line_nr_next +
5072 $offset} = 1;
5073 }
5074 }
5075 if (!defined $suppress_whiletrailers{$linenr} &&
5076 defined($stat) && defined($cond) &&
5077 $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
5078 my ($s, $c) = ($stat, $cond);
5079
5080 if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005081 if (ERROR("ASSIGN_IN_IF",
5082 "do not use assignment in if condition\n" . $herecurr) &&
5083 $fix && $perl_version_ok) {
5084 if ($rawline =~ /^\+(\s+)if\s*\(\s*(\!)?\s*\(\s*(($Lval)\s*=\s*$LvalOrFunc)\s*\)\s*(?:($Compare)\s*($FuncArg))?\s*\)\s*(\{)?\s*$/) {
5085 my $space = $1;
5086 my $not = $2;
5087 my $statement = $3;
5088 my $assigned = $4;
5089 my $test = $8;
5090 my $against = $9;
5091 my $brace = $15;
5092 fix_delete_line($fixlinenr, $rawline);
5093 fix_insert_line($fixlinenr, "$space$statement;");
5094 my $newline = "${space}if (";
5095 $newline .= '!' if defined($not);
5096 $newline .= '(' if (defined $not && defined($test) && defined($against));
5097 $newline .= "$assigned";
5098 $newline .= " $test $against" if (defined($test) && defined($against));
5099 $newline .= ')' if (defined $not && defined($test) && defined($against));
5100 $newline .= ')';
5101 $newline .= " {" if (defined($brace));
5102 fix_insert_line($fixlinenr + 1, $newline);
5103 }
5104 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005105 }
5106
5107 # Find out what is on the end of the line after the
5108 # conditional.
5109 substr($s, 0, length($c), '');
5110 $s =~ s/\n.*//g;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005111 $s =~ s/$;//g; # Remove any comments
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005112 if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
5113 $c !~ /}\s*while\s*/)
5114 {
5115 # Find out how long the conditional actually is.
5116 my @newlines = ($c =~ /\n/gs);
5117 my $cond_lines = 1 + $#newlines;
5118 my $stat_real = '';
5119
5120 $stat_real = raw_line($linenr, $cond_lines)
5121 . "\n" if ($cond_lines);
5122 if (defined($stat_real) && $cond_lines > 1) {
5123 $stat_real = "[...]\n$stat_real";
5124 }
5125
5126 ERROR("TRAILING_STATEMENTS",
5127 "trailing statements should be on next line\n" . $herecurr . $stat_real);
5128 }
5129 }
5130
5131# Check for bitwise tests written as boolean
5132 if ($line =~ /
5133 (?:
5134 (?:\[|\(|\&\&|\|\|)
5135 \s*0[xX][0-9]+\s*
5136 (?:\&\&|\|\|)
5137 |
5138 (?:\&\&|\|\|)
5139 \s*0[xX][0-9]+\s*
5140 (?:\&\&|\|\||\)|\])
5141 )/x)
5142 {
5143 WARN("HEXADECIMAL_BOOLEAN_TEST",
5144 "boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
5145 }
5146
5147# if and else should not have general statements after it
5148 if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
5149 my $s = $1;
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005150 $s =~ s/$;//g; # Remove any comments
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005151 if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
5152 ERROR("TRAILING_STATEMENTS",
5153 "trailing statements should be on next line\n" . $herecurr);
5154 }
5155 }
5156# if should not continue a brace
5157 if ($line =~ /}\s*if\b/) {
5158 ERROR("TRAILING_STATEMENTS",
5159 "trailing statements should be on next line (or did you mean 'else if'?)\n" .
5160 $herecurr);
5161 }
5162# case and default should not have general statements after them
5163 if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
5164 $line !~ /\G(?:
5165 (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
5166 \s*return\s+
5167 )/xg)
5168 {
5169 ERROR("TRAILING_STATEMENTS",
5170 "trailing statements should be on next line\n" . $herecurr);
5171 }
5172
5173 # Check for }<nl>else {, these must be at the same
5174 # indent level to be relevant to each other.
5175 if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ &&
5176 $previndent == $indent) {
5177 if (ERROR("ELSE_AFTER_BRACE",
5178 "else should follow close brace '}'\n" . $hereprev) &&
5179 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
5180 fix_delete_line($fixlinenr - 1, $prevrawline);
5181 fix_delete_line($fixlinenr, $rawline);
5182 my $fixedline = $prevrawline;
5183 $fixedline =~ s/}\s*$//;
5184 if ($fixedline !~ /^\+\s*$/) {
5185 fix_insert_line($fixlinenr, $fixedline);
5186 }
5187 $fixedline = $rawline;
5188 $fixedline =~ s/^(.\s*)else/$1} else/;
5189 fix_insert_line($fixlinenr, $fixedline);
5190 }
5191 }
5192
5193 if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ &&
5194 $previndent == $indent) {
5195 my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
5196
5197 # Find out what is on the end of the line after the
5198 # conditional.
5199 substr($s, 0, length($c), '');
5200 $s =~ s/\n.*//g;
5201
5202 if ($s =~ /^\s*;/) {
5203 if (ERROR("WHILE_AFTER_BRACE",
5204 "while should follow close brace '}'\n" . $hereprev) &&
5205 $fix && $prevline =~ /^\+/ && $line =~ /^\+/) {
5206 fix_delete_line($fixlinenr - 1, $prevrawline);
5207 fix_delete_line($fixlinenr, $rawline);
5208 my $fixedline = $prevrawline;
5209 my $trailing = $rawline;
5210 $trailing =~ s/^\+//;
5211 $trailing = trim($trailing);
5212 $fixedline =~ s/}\s*$/} $trailing/;
5213 fix_insert_line($fixlinenr, $fixedline);
5214 }
5215 }
5216 }
5217
5218#Specific variable tests
5219 while ($line =~ m{($Constant|$Lval)}g) {
5220 my $var = $1;
5221
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005222#CamelCase
5223 if ($var !~ /^$Constant$/ &&
5224 $var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
5225#Ignore Page<foo> variants
5226 $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05005227#Ignore SI style variants like nS, mV and dB
5228#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
5229 $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005230#Ignore some three character SI units explicitly, like MiB and KHz
5231 $var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005232 while ($var =~ m{($Ident)}g) {
5233 my $word = $1;
5234 next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
5235 if ($check) {
5236 seed_camelcase_includes();
5237 if (!$file && !$camelcase_file_seeded) {
5238 seed_camelcase_file($realfile);
5239 $camelcase_file_seeded = 1;
5240 }
5241 }
5242 if (!defined $camelcase{$word}) {
5243 $camelcase{$word} = 1;
5244 CHK("CAMELCASE",
5245 "Avoid CamelCase: <$word>\n" . $herecurr);
5246 }
5247 }
5248 }
5249 }
5250
5251#no spaces allowed after \ in define
5252 if ($line =~ /\#\s*define.*\\\s+$/) {
5253 if (WARN("WHITESPACE_AFTER_LINE_CONTINUATION",
5254 "Whitespace after \\ makes next lines useless\n" . $herecurr) &&
5255 $fix) {
5256 $fixed[$fixlinenr] =~ s/\s+$//;
5257 }
5258 }
5259
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005260# warn if <asm/foo.h> is #included and <linux/foo.h> is available and includes
5261# itself <asm/foo.h> (uses RAW line)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005262 if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
5263 my $file = "$1.h";
5264 my $checkfile = "include/linux/$file";
5265 if (-f "$root/$checkfile" &&
5266 $realfile ne $checkfile &&
5267 $1 !~ /$allowed_asm_includes/)
5268 {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005269 my $asminclude = `grep -Ec "#include\\s+<asm/$file>" $root/$checkfile`;
5270 if ($asminclude > 0) {
5271 if ($realfile =~ m{^arch/}) {
5272 CHK("ARCH_INCLUDE_LINUX",
5273 "Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5274 } else {
5275 WARN("INCLUDE_LINUX",
5276 "Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
5277 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005278 }
5279 }
5280 }
5281
5282# multi-statement macros should be enclosed in a do while loop, grab the
5283# first statement and ensure its the whole macro if its not enclosed
5284# in a known good container
5285 if ($realfile !~ m@/vmlinux.lds.h$@ &&
5286 $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
5287 my $ln = $linenr;
5288 my $cnt = $realcnt;
5289 my ($off, $dstat, $dcond, $rest);
5290 my $ctx = '';
5291 my $has_flow_statement = 0;
5292 my $has_arg_concat = 0;
5293 ($dstat, $dcond, $ln, $cnt, $off) =
5294 ctx_statement_block($linenr, $realcnt, 0);
5295 $ctx = $dstat;
5296 #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
5297 #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
5298
5299 $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
Tom Burdicke29d9e12021-11-09 16:21:47 -06005300 $has_arg_concat = 1 if (($ctx =~ /\#\#/ || $ctx =~ /UTIL_CAT/) && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005301
Anas Nashif0f3d5472016-11-07 15:57:57 -05005302 $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
5303 my $define_args = $1;
5304 my $define_stmt = $dstat;
5305 my @def_args = ();
5306
5307 if (defined $define_args && $define_args ne "") {
5308 $define_args = substr($define_args, 1, length($define_args) - 2);
5309 $define_args =~ s/\s*//g;
Peter Bigot5b10fac2020-03-26 11:16:33 -05005310 $define_args =~ s/\\\+?//g;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005311 @def_args = split(",", $define_args);
5312 }
5313
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005314 $dstat =~ s/$;//g;
5315 $dstat =~ s/\\\n.//g;
5316 $dstat =~ s/^\s*//s;
5317 $dstat =~ s/\s*$//s;
5318
5319 # Flatten any parentheses and braces
5320 while ($dstat =~ s/\([^\(\)]*\)/1/ ||
5321 $dstat =~ s/\{[^\{\}]*\}/1/ ||
Anas Nashif76b09132016-02-20 13:53:35 -05005322 $dstat =~ s/.\[[^\[\]]*\]/1/)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005323 {
5324 }
5325
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005326 # Flatten any obvious string concatenation.
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005327 while ($dstat =~ s/($String)\s*$Ident/$1/ ||
5328 $dstat =~ s/$Ident\s*($String)/$1/)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005329 {
5330 }
5331
Anas Nashif0f3d5472016-11-07 15:57:57 -05005332 # Make asm volatile uses seem like a generic function
5333 $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
5334
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005335 my $exceptions = qr{
5336 $Declare|
5337 module_param_named|
5338 MODULE_PARM_DESC|
5339 DECLARE_PER_CPU|
5340 DEFINE_PER_CPU|
5341 __typeof__\(|
5342 union|
5343 struct|
5344 \.$Ident\s*=\s*|
Anas Nashif76b09132016-02-20 13:53:35 -05005345 ^\"|\"$|
5346 ^\[
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005347 }x;
5348 #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
Anas Nashif0f3d5472016-11-07 15:57:57 -05005349
5350 $ctx =~ s/\n*$//;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005351 my $stmt_cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005352 my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
Anas Nashif0f3d5472016-11-07 15:57:57 -05005353
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005354 if ($dstat ne '' &&
5355 $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
5356 $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
5357 $dstat !~ /^[!~-]?(?:$Lval|$Constant)$/ && # 10 // foo() // !foo // ~foo // -foo // foo->bar // foo.bar->baz
5358 $dstat !~ /^'X'$/ && $dstat !~ /^'XX'$/ && # character constants
5359 $dstat !~ /$exceptions/ &&
5360 $dstat !~ /^\.$Ident\s*=/ && # .foo =
5361 $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
5362 $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
5363 $dstat !~ /^for\s*$Constant$/ && # for (...)
5364 $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
5365 $dstat !~ /^do\s*{/ && # do {...
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005366 $dstat !~ /^\(\{/ && # ({...
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005367 $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
5368 {
Anas Nashif1eb244c2017-10-01 17:06:36 -04005369 if ($dstat =~ /^\s*if\b/) {
5370 ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
5371 "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
5372 } elsif ($dstat =~ /;/) {
5373 ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005374 "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
5375 } else {
Anas Nashif65f0c672018-05-08 10:19:30 -05005376 WARN("COMPLEX_MACRO",
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005377 "Macros with complex values should be enclosed in parentheses\n" . "$herectx");
5378 }
Anas Nashif0f3d5472016-11-07 15:57:57 -05005379
5380 }
5381
5382 # Make $define_stmt single line, comment-free, etc
5383 my @stmt_array = split('\n', $define_stmt);
5384 my $first = 1;
5385 $define_stmt = "";
5386 foreach my $l (@stmt_array) {
5387 $l =~ s/\\$//;
5388 if ($first) {
5389 $define_stmt = $l;
5390 $first = 0;
5391 } elsif ($l =~ /^[\+ ]/) {
5392 $define_stmt .= substr($l, 1);
5393 }
5394 }
5395 $define_stmt =~ s/$;//g;
5396 $define_stmt =~ s/\s+/ /g;
5397 $define_stmt = trim($define_stmt);
5398
5399# check if any macro arguments are reused (ignore '...' and 'type')
5400 foreach my $arg (@def_args) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04005401 next if ($arg =~ /\.\.\./);
5402 next if ($arg =~ /^type$/i);
5403 my $tmp_stmt = $define_stmt;
Peter Bigot5b10fac2020-03-26 11:16:33 -05005404 $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 -04005405 $tmp_stmt =~ s/\#+\s*$arg\b//g;
5406 $tmp_stmt =~ s/\b$arg\s*\#\#//g;
Peter Bigot5b10fac2020-03-26 11:16:33 -05005407 my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
Anas Nashif0f3d5472016-11-07 15:57:57 -05005408 if ($use_cnt > 1) {
5409 CHK("MACRO_ARG_REUSE",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005410 "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
5411 }
Anas Nashif0f3d5472016-11-07 15:57:57 -05005412# check if any macro arguments may have other precedence issues
Anas Nashif1eb244c2017-10-01 17:06:36 -04005413 if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
5414 ((defined($1) && $1 ne ',') ||
5415 (defined($2) && $2 ne ','))) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05005416 CHK("MACRO_ARG_PRECEDENCE",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005417 "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
Anas Nashif0f3d5472016-11-07 15:57:57 -05005418 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005419 }
5420
5421# check for macros with flow control, but without ## concatenation
5422# ## concatenation is commonly a macro that defines a function so ignore those
5423 if ($has_flow_statement && !$has_arg_concat) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005424 my $cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005425 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005426
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005427 WARN("MACRO_WITH_FLOW_CONTROL",
5428 "Macros with flow control statements should be avoided\n" . "$herectx");
5429 }
5430
5431# check for line continuations outside of #defines, preprocessor #, and asm
5432
5433 } else {
5434 if ($prevline !~ /^..*\\$/ &&
5435 $line !~ /^\+\s*\#.*\\$/ && # preprocessor
5436 $line !~ /^\+.*\b(__asm__|asm)\b.*\\$/ && # asm
5437 $line =~ /^\+.*\\$/) {
5438 WARN("LINE_CONTINUATIONS",
5439 "Avoid unnecessary line continuations\n" . $herecurr);
5440 }
5441 }
5442
5443# do {} while (0) macro tests:
5444# single-statement macros do not need to be enclosed in do while (0) loop,
5445# macro should not end with a semicolon
Peter Bigot5b10fac2020-03-26 11:16:33 -05005446 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005447 $realfile !~ m@/vmlinux.lds.h$@ &&
5448 $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
5449 my $ln = $linenr;
5450 my $cnt = $realcnt;
5451 my ($off, $dstat, $dcond, $rest);
5452 my $ctx = '';
5453 ($dstat, $dcond, $ln, $cnt, $off) =
5454 ctx_statement_block($linenr, $realcnt, 0);
5455 $ctx = $dstat;
5456
5457 $dstat =~ s/\\\n.//g;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005458 $dstat =~ s/$;/ /g;
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005459
5460 if ($dstat =~ /^\+\s*#\s*define\s+$Ident\s*${balanced_parens}\s*do\s*{(.*)\s*}\s*while\s*\(\s*0\s*\)\s*([;\s]*)\s*$/) {
5461 my $stmts = $2;
5462 my $semis = $3;
5463
5464 $ctx =~ s/\n*$//;
5465 my $cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005466 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005467
5468 if (($stmts =~ tr/;/;/) == 1 &&
5469 $stmts !~ /^\s*(if|while|for|switch)\b/) {
5470 WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",
5471 "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");
5472 }
5473 if (defined $semis && $semis ne "") {
5474 WARN("DO_WHILE_MACRO_WITH_TRAILING_SEMICOLON",
5475 "do {} while (0) macros should not be semicolon terminated\n" . "$herectx");
5476 }
5477 } elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
5478 $ctx =~ s/\n*$//;
5479 my $cnt = statement_rawlines($ctx);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005480 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005481
5482 WARN("TRAILING_SEMICOLON",
5483 "macros should not use a trailing semicolon\n" . "$herectx");
5484 }
5485 }
5486
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005487# check for redundant bracing round if etc
5488 if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
5489 my ($level, $endln, @chunks) =
5490 ctx_statement_full($linenr, $realcnt, 1);
5491 #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
5492 #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
5493 if ($#chunks > 0 && $level == 0) {
5494 my @allowed = ();
5495 my $allow = 0;
5496 my $seen = 0;
5497 my $herectx = $here . "\n";
5498 my $ln = $linenr - 1;
5499 for my $chunk (@chunks) {
5500 my ($cond, $block) = @{$chunk};
5501
5502 # If the condition carries leading newlines, then count those as offsets.
5503 my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
5504 my $offset = statement_rawlines($whitespace) - 1;
5505
5506 $allowed[$allow] = 0;
5507 #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
5508
5509 # We have looked at and allowed this specific line.
5510 $suppress_ifbraces{$ln + $offset} = 1;
5511
5512 $herectx .= "$rawlines[$ln + $offset]\n[...]\n";
5513 $ln += statement_rawlines($block) - 1;
5514
5515 substr($block, 0, length($cond), '');
5516
5517 $seen++ if ($block =~ /^\s*{/);
5518
5519 #print "cond<$cond> block<$block> allowed<$allowed[$allow]>\n";
5520 if (statement_lines($cond) > 1) {
5521 #print "APW: ALLOWED: cond<$cond>\n";
5522 $allowed[$allow] = 1;
5523 }
5524 if ($block =~/\b(?:if|for|while)\b/) {
5525 #print "APW: ALLOWED: block<$block>\n";
5526 $allowed[$allow] = 1;
5527 }
5528 if (statement_block_size($block) > 1) {
5529 #print "APW: ALLOWED: lines block<$block>\n";
5530 $allowed[$allow] = 1;
5531 }
5532 $allow++;
5533 }
5534 if ($seen) {
5535 my $sum_allowed = 0;
5536 foreach (@allowed) {
5537 $sum_allowed += $_;
5538 }
5539 if ($sum_allowed == 0) {
5540 WARN("BRACES",
5541 "braces {} are not necessary for any arm of this statement\n" . $herectx);
5542 } elsif ($sum_allowed != $allow &&
5543 $seen != $allow) {
5544 CHK("BRACES",
5545 "braces {} should be used on all arms of this statement\n" . $herectx);
5546 }
5547 }
5548 }
5549 }
5550 if (!defined $suppress_ifbraces{$linenr - 1} &&
5551 $line =~ /\b(if|while|for|else)\b/) {
5552 my $allowed = 0;
5553
5554 # Check the pre-context.
5555 if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
5556 #print "APW: ALLOWED: pre<$1>\n";
5557 $allowed = 1;
5558 }
5559
5560 my ($level, $endln, @chunks) =
5561 ctx_statement_full($linenr, $realcnt, $-[0]);
5562
5563 # Check the condition.
5564 my ($cond, $block) = @{$chunks[0]};
5565 #print "CHECKING<$linenr> cond<$cond> block<$block>\n";
5566 if (defined $cond) {
5567 substr($block, 0, length($cond), '');
5568 }
5569 if (statement_lines($cond) > 1) {
5570 #print "APW: ALLOWED: cond<$cond>\n";
5571 $allowed = 1;
5572 }
5573 if ($block =~/\b(?:if|for|while)\b/) {
5574 #print "APW: ALLOWED: block<$block>\n";
5575 $allowed = 1;
5576 }
5577 if (statement_block_size($block) > 1) {
5578 #print "APW: ALLOWED: lines block<$block>\n";
5579 $allowed = 1;
5580 }
5581 # Check the post-context.
5582 if (defined $chunks[1]) {
5583 my ($cond, $block) = @{$chunks[1]};
5584 if (defined $cond) {
5585 substr($block, 0, length($cond), '');
5586 }
5587 if ($block =~ /^\s*\{/) {
5588 #print "APW: ALLOWED: chunk-1 block<$block>\n";
5589 $allowed = 1;
5590 }
5591 }
5592 if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005593 my $cnt = statement_rawlines($block);
Peter Bigot5b10fac2020-03-26 11:16:33 -05005594 my $herectx = get_stat_here($linenr, $cnt, $here);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005595
5596 WARN("BRACES",
5597 "braces {} are not necessary for single statement blocks\n" . $herectx);
5598 }
5599 }
5600
Anas Nashif1eb244c2017-10-01 17:06:36 -04005601# check for single line unbalanced braces
5602 if ($sline =~ /^.\s*\}\s*else\s*$/ ||
5603 $sline =~ /^.\s*else\s*\{\s*$/) {
5604 CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);
5605 }
5606
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005607# check for unnecessary blank lines around braces
5608 if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005609 if (CHK("BRACES",
5610 "Blank lines aren't necessary before a close brace '}'\n" . $hereprev) &&
5611 $fix && $prevrawline =~ /^\+/) {
5612 fix_delete_line($fixlinenr - 1, $prevrawline);
5613 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005614 }
5615 if (($rawline =~ /^.\s*$/ && $prevline =~ /^..*{\s*$/)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005616 if (CHK("BRACES",
5617 "Blank lines aren't necessary after an open brace '{'\n" . $hereprev) &&
5618 $fix) {
5619 fix_delete_line($fixlinenr, $rawline);
5620 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005621 }
5622
5623# no volatiles please
5624 my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
5625 if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
5626 WARN("VOLATILE",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005627 "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005628 }
5629
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005630# Check for user-visible strings broken across lines, which breaks the ability
5631# to grep for the string. Make exceptions when the previous string ends in a
5632# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
5633# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
5634 if ($line =~ /^\+\s*$String/ &&
5635 $prevline =~ /"\s*$/ &&
5636 $prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
5637 if (WARN("SPLIT_STRING",
5638 "quoted string split across lines\n" . $hereprev) &&
5639 $fix &&
5640 $prevrawline =~ /^\+.*"\s*$/ &&
5641 $last_coalesced_string_linenr != $linenr - 1) {
5642 my $extracted_string = get_quoted_string($line, $rawline);
5643 my $comma_close = "";
5644 if ($rawline =~ /\Q$extracted_string\E(\s*\)\s*;\s*$|\s*,\s*)/) {
5645 $comma_close = $1;
5646 }
5647
5648 fix_delete_line($fixlinenr - 1, $prevrawline);
5649 fix_delete_line($fixlinenr, $rawline);
5650 my $fixedline = $prevrawline;
5651 $fixedline =~ s/"\s*$//;
5652 $fixedline .= substr($extracted_string, 1) . trim($comma_close);
5653 fix_insert_line($fixlinenr - 1, $fixedline);
5654 $fixedline = $rawline;
5655 $fixedline =~ s/\Q$extracted_string\E\Q$comma_close\E//;
5656 if ($fixedline !~ /\+\s*$/) {
5657 fix_insert_line($fixlinenr, $fixedline);
5658 }
5659 $last_coalesced_string_linenr = $linenr;
5660 }
5661 }
5662
5663# check for missing a space in a string concatenation
5664 if ($prevrawline =~ /[^\\]\w"$/ && $rawline =~ /^\+[\t ]+"\w/) {
5665 WARN('MISSING_SPACE',
5666 "break quoted strings at a space character\n" . $hereprev);
5667 }
5668
Anas Nashif1eb244c2017-10-01 17:06:36 -04005669# check for an embedded function name in a string when the function is known
5670# This does not work very well for -f --file checking as it depends on patch
5671# context providing the function name or a single line form for in-file
5672# function declarations
5673 if ($line =~ /^\+.*$String/ &&
5674 defined($context_function) &&
5675 get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&
5676 length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {
5677 WARN("EMBEDDED_FUNCTION_NAME",
5678 "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
5679 }
5680
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005681# check for spaces before a quoted newline
5682 if ($rawline =~ /^.*\".*\s\\n/) {
5683 if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
5684 "unnecessary whitespace before a quoted newline\n" . $herecurr) &&
5685 $fix) {
5686 $fixed[$fixlinenr] =~ s/^(\+.*\".*)\s+\\n/$1\\n/;
5687 }
5688
5689 }
5690
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005691# concatenated string without spaces between elements
Peter Bigot5b10fac2020-03-26 11:16:33 -05005692 if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
5693 if (CHK("CONCATENATED_STRING",
5694 "Concatenated strings should use spaces between elements\n" . $herecurr) &&
5695 $fix) {
5696 while ($line =~ /($String)/g) {
5697 my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
5698 $fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
5699 $fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
5700 }
5701 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005702 }
5703
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005704# uncoalesced string fragments
5705 if ($line =~ /$String\s*"/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05005706 if (WARN("STRING_FRAGMENTS",
5707 "Consecutive strings are generally better as a single string\n" . $herecurr) &&
5708 $fix) {
5709 while ($line =~ /($String)(?=\s*")/g) {
5710 my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
5711 $fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
5712 }
5713 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005714 }
5715
Anas Nashif1eb244c2017-10-01 17:06:36 -04005716# check for non-standard and hex prefixed decimal printf formats
5717 my $show_L = 1; #don't show the same defect twice
5718 my $show_Z = 1;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005719 while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04005720 my $string = substr($rawline, $-[1], $+[1] - $-[1]);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005721 $string =~ s/%%/__/g;
Anas Nashif1eb244c2017-10-01 17:06:36 -04005722 # check for %L
5723 if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005724 WARN("PRINTF_L",
Anas Nashif1eb244c2017-10-01 17:06:36 -04005725 "\%L$1 is non-standard C, use %ll$1\n" . $herecurr);
5726 $show_L = 0;
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005727 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04005728 # check for %Z
5729 if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) {
5730 WARN("PRINTF_Z",
5731 "%Z$1 is non-standard C, use %z$1\n" . $herecurr);
5732 $show_Z = 0;
5733 }
5734 # check for 0x<decimal>
5735 if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) {
5736 ERROR("PRINTF_0XDECIMAL",
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005737 "Prefixing 0x with decimal output is defective\n" . $herecurr);
5738 }
5739 }
5740
5741# check for line continuations in quoted strings with odd counts of "
Peter Bigot5b10fac2020-03-26 11:16:33 -05005742 if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005743 WARN("LINE_CONTINUATIONS",
5744 "Avoid line continuations in quoted strings\n" . $herecurr);
5745 }
5746
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005747# warn about #if 0
5748 if ($line =~ /^.\s*\#\s*if\s+0\b/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05005749 WARN("IF_0",
5750 "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
5751 }
5752
5753# warn about #if 1
5754 if ($line =~ /^.\s*\#\s*if\s+1\b/) {
5755 WARN("IF_1",
5756 "Consider removing the #if 1 and its #endif\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005757 }
5758
5759# check for needless "if (<foo>) fn(<foo>)" uses
5760 if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005761 my $tested = quotemeta($1);
5762 my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;';
5763 if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) {
5764 my $func = $1;
5765 if (WARN('NEEDLESS_IF',
5766 "$func(NULL) is safe and this check is probably not required\n" . $hereprev) &&
5767 $fix) {
5768 my $do_fix = 1;
5769 my $leading_tabs = "";
5770 my $new_leading_tabs = "";
5771 if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) {
5772 $leading_tabs = $1;
5773 } else {
5774 $do_fix = 0;
5775 }
5776 if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) {
5777 $new_leading_tabs = $1;
5778 if (length($leading_tabs) + 1 ne length($new_leading_tabs)) {
5779 $do_fix = 0;
5780 }
5781 } else {
5782 $do_fix = 0;
5783 }
5784 if ($do_fix) {
5785 fix_delete_line($fixlinenr - 1, $prevrawline);
5786 $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/;
5787 }
5788 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005789 }
5790 }
5791
5792# check for unnecessary "Out of Memory" messages
5793 if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
5794 $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
5795 (defined $1 || defined $3) &&
5796 $linenr > 3) {
5797 my $testval = $2;
5798 my $testline = $lines[$linenr - 3];
5799
5800 my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
5801# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
5802
Peter Bigot5b10fac2020-03-26 11:16:33 -05005803 if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
5804 $s !~ /\b__GFP_NOWARN\b/ ) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005805 WARN("OOM_MESSAGE",
5806 "Possible unnecessary 'out of memory' message\n" . $hereprev);
5807 }
5808 }
5809
5810# check for logging functions with KERN_<LEVEL>
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005811 if ($line !~ /printk(?:_ratelimited|_once)?\s*\(/ &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005812 $line =~ /\b$logFunctions\s*\(.*\b(KERN_[A-Z]+)\b/) {
5813 my $level = $1;
5814 if (WARN("UNNECESSARY_KERN_LEVEL",
5815 "Possible unnecessary $level\n" . $herecurr) &&
5816 $fix) {
5817 $fixed[$fixlinenr] =~ s/\s*$level\s*//;
5818 }
5819 }
5820
Anas Nashif1eb244c2017-10-01 17:06:36 -04005821# check for logging continuations
5822 if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) {
5823 WARN("LOGGING_CONTINUATION",
5824 "Avoid logging continuation uses where feasible\n" . $herecurr);
5825 }
5826
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005827# check for mask then right shift without a parentheses
Peter Bigot5b10fac2020-03-26 11:16:33 -05005828 if ($perl_version_ok &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005829 $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
5830 $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
5831 WARN("MASK_THEN_SHIFT",
5832 "Possible precedence defect with mask then right shift - may need parentheses\n" . $herecurr);
5833 }
5834
5835# check for pointer comparisons to NULL
Peter Bigot5b10fac2020-03-26 11:16:33 -05005836 if ($perl_version_ok) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005837 while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
5838 my $val = $1;
5839 my $equal = "!";
5840 $equal = "" if ($4 eq "!=");
5841 if (CHK("COMPARISON_TO_NULL",
5842 "Comparison to NULL could be written \"${equal}${val}\"\n" . $herecurr) &&
5843 $fix) {
5844 $fixed[$fixlinenr] =~ s/\b\Q$val\E\s*(?:==|\!=)\s*NULL\b/$equal$val/;
5845 }
5846 }
5847 }
5848
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005849# check for bad placement of section $InitAttribute (e.g.: __initdata)
5850 if ($line =~ /(\b$InitAttribute\b)/) {
5851 my $attr = $1;
5852 if ($line =~ /^\+\s*static\s+(?:const\s+)?(?:$attr\s+)?($NonptrTypeWithAttr)\s+(?:$attr\s+)?($Ident(?:\[[^]]*\])?)\s*[=;]/) {
5853 my $ptr = $1;
5854 my $var = $2;
5855 if ((($ptr =~ /\b(union|struct)\s+$attr\b/ &&
5856 ERROR("MISPLACED_INIT",
5857 "$attr should be placed after $var\n" . $herecurr)) ||
5858 ($ptr !~ /\b(union|struct)\s+$attr\b/ &&
5859 WARN("MISPLACED_INIT",
5860 "$attr should be placed after $var\n" . $herecurr))) &&
5861 $fix) {
5862 $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;
5863 }
5864 }
5865 }
5866
5867# check for $InitAttributeData (ie: __initdata) with const
5868 if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
5869 my $attr = $1;
5870 $attr =~ /($InitAttributePrefix)(.*)/;
5871 my $attr_prefix = $1;
5872 my $attr_type = $2;
5873 if (ERROR("INIT_ATTRIBUTE",
5874 "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
5875 $fix) {
5876 $fixed[$fixlinenr] =~
5877 s/$InitAttributeData/${attr_prefix}initconst/;
5878 }
5879 }
5880
5881# check for $InitAttributeConst (ie: __initconst) without const
5882 if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
5883 my $attr = $1;
5884 if (ERROR("INIT_ATTRIBUTE",
5885 "Use of $attr requires a separate use of const\n" . $herecurr) &&
5886 $fix) {
5887 my $lead = $fixed[$fixlinenr] =~
5888 /(^\+\s*(?:static\s+))/;
5889 $lead = rtrim($1);
5890 $lead = "$lead " if ($lead !~ /^\+$/);
5891 $lead = "${lead}const ";
5892 $fixed[$fixlinenr] =~ s/(^\+\s*(?:static\s+))/$lead/;
5893 }
5894 }
5895
Anas Nashifcbfb62c2015-10-14 06:08:54 -04005896# check for __read_mostly with const non-pointer (should just be const)
5897 if ($line =~ /\b__read_mostly\b/ &&
5898 $line =~ /($Type)\s*$Ident/ && $1 !~ /\*\s*$/ && $1 =~ /\bconst\b/) {
5899 if (ERROR("CONST_READ_MOSTLY",
5900 "Invalid use of __read_mostly with const type\n" . $herecurr) &&
5901 $fix) {
5902 $fixed[$fixlinenr] =~ s/\s+__read_mostly\b//;
5903 }
5904 }
5905
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005906# don't use __constant_<foo> functions outside of include/uapi/
5907 if ($realfile !~ m@^include/uapi/@ &&
5908 $line =~ /(__constant_(?:htons|ntohs|[bl]e(?:16|32|64)_to_cpu|cpu_to_[bl]e(?:16|32|64)))\s*\(/) {
5909 my $constant_func = $1;
5910 my $func = $constant_func;
5911 $func =~ s/^__constant_//;
5912 if (WARN("CONSTANT_CONVERSION",
5913 "$constant_func should be $func\n" . $herecurr) &&
5914 $fix) {
5915 $fixed[$fixlinenr] =~ s/\b$constant_func\b/$func/g;
5916 }
5917 }
5918
5919# prefer usleep_range over udelay
5920 if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
5921 my $delay = $1;
5922 # ignore udelay's < 10, however
5923 if (! ($delay < 10) ) {
5924 CHK("USLEEP_RANGE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05005925 "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005926 }
5927 if ($delay > 2000) {
5928 WARN("LONG_UDELAY",
5929 "long udelay - prefer mdelay; see arch/arm/include/asm/delay.h\n" . $herecurr);
5930 }
5931 }
5932
5933# warn about unexpectedly long msleep's
5934 if ($line =~ /\bmsleep\s*\((\d+)\);/) {
5935 if ($1 < 20) {
5936 WARN("MSLEEP",
Peter Bigot5b10fac2020-03-26 11:16:33 -05005937 "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07005938 }
5939 }
5940
5941# check for comparisons of jiffies
5942 if ($line =~ /\bjiffies\s*$Compare|$Compare\s*jiffies\b/) {
5943 WARN("JIFFIES_COMPARISON",
5944 "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
5945 }
5946
5947# check for comparisons of get_jiffies_64()
5948 if ($line =~ /\bget_jiffies_64\s*\(\s*\)\s*$Compare|$Compare\s*get_jiffies_64\s*\(\s*\)/) {
5949 WARN("JIFFIES_COMPARISON",
5950 "Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
5951 }
5952
5953# warn about #ifdefs in C files
5954# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
5955# print "#ifdef in C files should be avoided\n";
5956# print "$herecurr";
5957# $clean = 0;
5958# }
5959
5960# warn about spacing in #ifdefs
5961 if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
5962 if (ERROR("SPACING",
5963 "exactly one space required after that #$1\n" . $herecurr) &&
5964 $fix) {
5965 $fixed[$fixlinenr] =~
5966 s/^(.\s*\#\s*(ifdef|ifndef|elif))\s{2,}/$1 /;
5967 }
5968
5969 }
5970
5971# check for spinlock_t definitions without a comment.
5972 if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
5973 $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
5974 my $which = $1;
5975 if (!ctx_has_comment($first_line, $linenr)) {
5976 CHK("UNCOMMENTED_DEFINITION",
5977 "$1 definition without comment\n" . $herecurr);
5978 }
5979 }
5980# check for memory barriers without a comment.
Anas Nashif76b09132016-02-20 13:53:35 -05005981
5982 my $barriers = qr{
5983 mb|
5984 rmb|
Peter A. Bigote49e3c82020-08-10 10:37:32 -05005985 wmb
Anas Nashif76b09132016-02-20 13:53:35 -05005986 }x;
5987 my $barrier_stems = qr{
5988 mb__before_atomic|
5989 mb__after_atomic|
5990 store_release|
5991 load_acquire|
5992 store_mb|
5993 (?:$barriers)
5994 }x;
5995 my $all_barriers = qr{
5996 (?:$barriers)|
5997 smp_(?:$barrier_stems)|
5998 virt_(?:$barrier_stems)
5999 }x;
6000
6001 if ($line =~ /\b(?:$all_barriers)\s*\(/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006002 if (!ctx_has_comment($first_line, $linenr)) {
6003 WARN("MEMORY_BARRIER",
6004 "memory barrier without comment\n" . $herecurr);
6005 }
6006 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006007
Anas Nashif76b09132016-02-20 13:53:35 -05006008 my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x;
6009
6010 if ($realfile !~ m@^include/asm-generic/@ &&
6011 $realfile !~ m@/barrier\.h$@ &&
6012 $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&
6013 $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {
6014 WARN("MEMORY_BARRIER",
6015 "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr);
6016 }
6017
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006018# check for waitqueue_active without a comment.
6019 if ($line =~ /\bwaitqueue_active\s*\(/) {
6020 if (!ctx_has_comment($first_line, $linenr)) {
6021 WARN("WAITQUEUE_ACTIVE",
6022 "waitqueue_active without comment\n" . $herecurr);
6023 }
6024 }
6025
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006026# check for data_race without a comment.
6027 if ($line =~ /\bdata_race\s*\(/) {
6028 if (!ctx_has_comment($first_line, $linenr)) {
6029 WARN("DATA_RACE",
6030 "data_race without comment\n" . $herecurr);
6031 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006032 }
6033
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006034# check of hardware specific defines
6035 if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
6036 CHK("ARCH_DEFINES",
6037 "architecture specific defines should be avoided\n" . $herecurr);
6038 }
6039
Anas Nashif1eb244c2017-10-01 17:06:36 -04006040# check that the storage class is not after a type
6041 if ($line =~ /\b($Type)\s+($Storage)\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006042 WARN("STORAGE_CLASS",
Anas Nashif1eb244c2017-10-01 17:06:36 -04006043 "storage class '$2' should be located before type '$1'\n" . $herecurr);
6044 }
6045# Check that the storage class is at the beginning of a declaration
6046 if ($line =~ /\b$Storage\b/ &&
6047 $line !~ /^.\s*$Storage/ &&
6048 $line =~ /^.\s*(.+?)\$Storage\s/ &&
6049 $1 !~ /[\,\)]\s*$/) {
6050 WARN("STORAGE_CLASS",
6051 "storage class should be at the beginning of the declaration\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006052 }
6053
6054# check the location of the inline attribute, that it is between
6055# storage class and type.
6056 if ($line =~ /\b$Type\s+$Inline\b/ ||
6057 $line =~ /\b$Inline\s+$Storage\b/) {
6058 ERROR("INLINE_LOCATION",
6059 "inline keyword should sit between storage class and type\n" . $herecurr);
6060 }
6061
6062# Check for __inline__ and __inline, prefer inline
6063 if ($realfile !~ m@\binclude/uapi/@ &&
6064 $line =~ /\b(__inline__|__inline)\b/) {
6065 if (WARN("INLINE",
6066 "plain inline is preferred over $1\n" . $herecurr) &&
6067 $fix) {
6068 $fixed[$fixlinenr] =~ s/\b(__inline__|__inline)\b/inline/;
6069
6070 }
6071 }
6072
6073# Check for __attribute__ packed, prefer __packed
6074 if ($realfile !~ m@\binclude/uapi/@ &&
6075 $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
6076 WARN("PREFER_PACKED",
6077 "__packed is preferred over __attribute__((packed))\n" . $herecurr);
6078 }
6079
6080# Check for __attribute__ aligned, prefer __aligned
6081 if ($realfile !~ m@\binclude/uapi/@ &&
6082 $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
6083 WARN("PREFER_ALIGNED",
6084 "__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
6085 }
6086
Peter Bigot5b10fac2020-03-26 11:16:33 -05006087# Check for __attribute__ section, prefer __section
6088 if ($realfile !~ m@\binclude/uapi/@ &&
6089 $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
6090 my $old = substr($rawline, $-[1], $+[1] - $-[1]);
6091 my $new = substr($old, 1, -1);
6092 if (WARN("PREFER_SECTION",
6093 "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
6094 $fix) {
6095 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
6096 }
6097 }
6098
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006099# Check for __attribute__ format(printf, prefer __printf
6100 if ($realfile !~ m@\binclude/uapi/@ &&
6101 $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
6102 if (WARN("PREFER_PRINTF",
6103 "__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
6104 $fix) {
6105 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
6106
6107 }
6108 }
6109
6110# Check for __attribute__ format(scanf, prefer __scanf
6111 if ($realfile !~ m@\binclude/uapi/@ &&
6112 $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
6113 if (WARN("PREFER_SCANF",
6114 "__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
6115 $fix) {
6116 $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
6117 }
6118 }
6119
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006120# Check for __attribute__ weak, or __weak declarations (may have link issues)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006121 if ($perl_version_ok &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006122 $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
6123 ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
6124 $line =~ /\b__weak\b/)) {
6125 ERROR("WEAK_DECLARATION",
6126 "Using weak declarations can have unintended link defects\n" . $herecurr);
6127 }
6128
Kumar Gala93da8dc2020-06-02 12:38:11 -05006129# check for c99 types like uint8_t used outside of uapi/
6130 if ($realfile !~ m@\binclude/uapi/@ &&
6131 $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006132 my $type = $1;
6133 if ($type =~ /\b($typeC99Typedefs)\b/) {
6134 $type = $1;
6135 my $kernel_type = 'u';
6136 $kernel_type = 's' if ($type =~ /^_*[si]/);
6137 $type =~ /(\d+)/;
Kumar Gala93da8dc2020-06-02 12:38:11 -05006138 $kernel_type .= $1;
6139 if (CHK("PREFER_KERNEL_TYPES",
6140 "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) &&
6141 $fix) {
6142 $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/;
6143 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006144 }
6145 }
6146
Anas Nashif76b09132016-02-20 13:53:35 -05006147# check for cast of C90 native int or longer types constants
6148 if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {
6149 my $cast = $1;
6150 my $const = $2;
6151 if (WARN("TYPECAST_INT_CONSTANT",
6152 "Unnecessary typecast of c90 int constant\n" . $herecurr) &&
6153 $fix) {
6154 my $suffix = "";
6155 my $newconst = $const;
6156 $newconst =~ s/${Int_type}$//;
6157 $suffix .= 'U' if ($cast =~ /\bunsigned\b/);
6158 if ($cast =~ /\blong\s+long\b/) {
6159 $suffix .= 'LL';
6160 } elsif ($cast =~ /\blong\b/) {
6161 $suffix .= 'L';
6162 }
6163 $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;
6164 }
6165 }
6166
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006167# check for sizeof(&)
6168 if ($line =~ /\bsizeof\s*\(\s*\&/) {
6169 WARN("SIZEOF_ADDRESS",
6170 "sizeof(& should be avoided\n" . $herecurr);
6171 }
6172
6173# check for sizeof without parenthesis
6174 if ($line =~ /\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/) {
6175 if (WARN("SIZEOF_PARENTHESIS",
6176 "sizeof $1 should be sizeof($1)\n" . $herecurr) &&
6177 $fix) {
6178 $fixed[$fixlinenr] =~ s/\bsizeof\s+((?:\*\s*|)$Lval|$Type(?:\s+$Lval|))/"sizeof(" . trim($1) . ")"/ex;
6179 }
6180 }
6181
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006182# check for struct spinlock declarations
6183 if ($line =~ /^.\s*\bstruct\s+spinlock\s+\w+\s*;/) {
6184 WARN("USE_SPINLOCK_T",
6185 "struct spinlock should be spinlock_t\n" . $herecurr);
6186 }
6187
6188# check for seq_printf uses that could be seq_puts
6189 if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
6190 my $fmt = get_quoted_string($line, $rawline);
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006191 $fmt =~ s/%%//g;
6192 if ($fmt !~ /%/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006193 if (WARN("PREFER_SEQ_PUTS",
6194 "Prefer seq_puts to seq_printf\n" . $herecurr) &&
6195 $fix) {
6196 $fixed[$fixlinenr] =~ s/\bseq_printf\b/seq_puts/;
6197 }
6198 }
6199 }
6200
Peter Bigot5b10fac2020-03-26 11:16:33 -05006201# check for vsprintf extension %p<foo> misuses
6202 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006203 defined $stat &&
6204 $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
6205 $1 !~ /^_*volatile_*$/) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05006206 my $stat_real;
6207
Anas Nashif1eb244c2017-10-01 17:06:36 -04006208 my $lc = $stat =~ tr@\n@@;
6209 $lc = $lc + $linenr;
6210 for (my $count = $linenr; $count <= $lc; $count++) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05006211 my $specifier;
6212 my $extension;
6213 my $qualifier;
6214 my $bad_specifier = "";
Anas Nashif1eb244c2017-10-01 17:06:36 -04006215 my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
6216 $fmt =~ s/%%//g;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006217
6218 while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {
6219 $specifier = $1;
6220 $extension = $2;
6221 $qualifier = $3;
6222 if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
6223 ($extension eq "f" &&
6224 defined $qualifier && $qualifier !~ /^w/)) {
6225 $bad_specifier = $specifier;
6226 last;
6227 }
6228 if ($extension eq "x" && !defined($stat_real)) {
6229 if (!defined($stat_real)) {
6230 $stat_real = get_stat_real($linenr, $lc);
6231 }
6232 WARN("VSPRINTF_SPECIFIER_PX",
6233 "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");
6234 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04006235 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006236 if ($bad_specifier ne "") {
6237 my $stat_real = get_stat_real($linenr, $lc);
6238 my $ext_type = "Invalid";
6239 my $use = "";
6240 if ($bad_specifier =~ /p[Ff]/) {
6241 $use = " - use %pS instead";
6242 $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
6243 }
6244
6245 WARN("VSPRINTF_POINTER_EXTENSION",
6246 "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
Anas Nashif1eb244c2017-10-01 17:06:36 -04006247 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04006248 }
6249 }
6250
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006251# Check for misused memsets
Peter Bigot5b10fac2020-03-26 11:16:33 -05006252 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006253 defined $stat &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006254 $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006255
6256 my $ms_addr = $2;
6257 my $ms_val = $7;
6258 my $ms_size = $12;
6259
6260 if ($ms_size =~ /^(0x|)0$/i) {
6261 ERROR("MEMSET",
6262 "memset to 0's uses 0 as the 2nd argument, not the 3rd\n" . "$here\n$stat\n");
6263 } elsif ($ms_size =~ /^(0x|)1$/i) {
6264 WARN("MEMSET",
6265 "single byte memset is suspicious. Swapped 2nd/3rd argument?\n" . "$here\n$stat\n");
6266 }
6267 }
6268
6269# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006270# if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006271# defined $stat &&
6272# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6273# if (WARN("PREFER_ETHER_ADDR_COPY",
6274# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
6275# $fix) {
6276# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
6277# }
6278# }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006279
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006280# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006281# if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006282# defined $stat &&
6283# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6284# WARN("PREFER_ETHER_ADDR_EQUAL",
6285# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
6286# }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006287
6288# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
6289# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
Peter Bigot5b10fac2020-03-26 11:16:33 -05006290# if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006291# defined $stat &&
6292# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
6293#
6294# my $ms_val = $7;
6295#
6296# if ($ms_val =~ /^(?:0x|)0+$/i) {
6297# if (WARN("PREFER_ETH_ZERO_ADDR",
6298# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
6299# $fix) {
6300# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
6301# }
6302# } elsif ($ms_val =~ /^(?:0xff|255)$/i) {
6303# if (WARN("PREFER_ETH_BROADCAST_ADDR",
6304# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
6305# $fix) {
6306# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
6307# }
6308# }
6309# }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006310
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006311# typecasts on min/max could be min_t/max_t
Peter Bigot5b10fac2020-03-26 11:16:33 -05006312 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006313 defined $stat &&
6314 $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
6315 if (defined $2 || defined $7) {
6316 my $call = $1;
6317 my $cast1 = deparenthesize($2);
6318 my $arg1 = $3;
6319 my $cast2 = deparenthesize($7);
6320 my $arg2 = $8;
6321 my $cast;
6322
6323 if ($cast1 ne "" && $cast2 ne "" && $cast1 ne $cast2) {
6324 $cast = "$cast1 or $cast2";
6325 } elsif ($cast1 ne "") {
6326 $cast = $cast1;
6327 } else {
6328 $cast = $cast2;
6329 }
6330 WARN("MINMAX",
6331 "$call() should probably be ${call}_t($cast, $arg1, $arg2)\n" . "$here\n$stat\n");
6332 }
6333 }
6334
6335# check usleep_range arguments
Peter Bigot5b10fac2020-03-26 11:16:33 -05006336 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006337 defined $stat &&
6338 $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
6339 my $min = $1;
6340 my $max = $7;
6341 if ($min eq $max) {
6342 WARN("USLEEP_RANGE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05006343 "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 -07006344 } elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
6345 $min > $max) {
6346 WARN("USLEEP_RANGE",
Peter Bigot5b10fac2020-03-26 11:16:33 -05006347 "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 -07006348 }
6349 }
6350
6351# check for naked sscanf
Peter Bigot5b10fac2020-03-26 11:16:33 -05006352 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006353 defined $stat &&
6354 $line =~ /\bsscanf\b/ &&
6355 ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
6356 $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
6357 $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
6358 my $lc = $stat =~ tr@\n@@;
6359 $lc = $lc + $linenr;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006360 my $stat_real = get_stat_real($linenr, $lc);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006361 WARN("NAKED_SSCANF",
6362 "unchecked sscanf return value\n" . "$here\n$stat_real\n");
6363 }
6364
6365# check for simple sscanf that should be kstrto<foo>
Peter Bigot5b10fac2020-03-26 11:16:33 -05006366 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006367 defined $stat &&
6368 $line =~ /\bsscanf\b/) {
6369 my $lc = $stat =~ tr@\n@@;
6370 $lc = $lc + $linenr;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006371 my $stat_real = get_stat_real($linenr, $lc);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006372 if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
6373 my $format = $6;
6374 my $count = $format =~ tr@%@%@;
6375 if ($count == 1 &&
6376 $format =~ /^"\%(?i:ll[udxi]|[udxi]ll|ll|[hl]h?[udxi]|[udxi][hl]h?|[hl]h?|[udxi])"$/) {
6377 WARN("SSCANF_TO_KSTRTO",
6378 "Prefer kstrto<type> to single variable sscanf\n" . "$here\n$stat_real\n");
6379 }
6380 }
6381 }
6382
6383# check for new externs in .h files.
6384 if ($realfile =~ /\.h$/ &&
6385 $line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
6386 if (CHK("AVOID_EXTERNS",
6387 "extern prototypes should be avoided in .h files\n" . $herecurr) &&
6388 $fix) {
6389 $fixed[$fixlinenr] =~ s/(.*)\bextern\b\s*(.*)/$1$2/;
6390 }
6391 }
6392
6393# check for new externs in .c files.
6394 if ($realfile =~ /\.c$/ && defined $stat &&
6395 $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
6396 {
6397 my $function_name = $1;
6398 my $paren_space = $2;
6399
6400 my $s = $stat;
6401 if (defined $cond) {
6402 substr($s, 0, length($cond), '');
6403 }
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006404 if ($s =~ /^\s*;/)
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006405 {
6406 WARN("AVOID_EXTERNS",
6407 "externs should be avoided in .c files\n" . $herecurr);
6408 }
6409
6410 if ($paren_space =~ /\n/) {
6411 WARN("FUNCTION_ARGUMENTS",
6412 "arguments for function declarations should follow identifier\n" . $herecurr);
6413 }
6414
6415 } elsif ($realfile =~ /\.c$/ && defined $stat &&
6416 $stat =~ /^.\s*extern\s+/)
6417 {
6418 WARN("AVOID_EXTERNS",
6419 "externs should be avoided in .c files\n" . $herecurr);
6420 }
6421
Anas Nashif1eb244c2017-10-01 17:06:36 -04006422# check for function declarations that have arguments without identifier names
6423 if (defined $stat &&
Peter Bigot5b10fac2020-03-26 11:16:33 -05006424 $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006425 $1 ne "void") {
6426 my $args = trim($1);
6427 while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
6428 my $arg = trim($1);
6429 if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
6430 WARN("FUNCTION_ARGUMENTS",
6431 "function definition argument '$arg' should also have an identifier name\n" . $herecurr);
6432 }
6433 }
6434 }
6435
Anas Nashif1eb244c2017-10-01 17:06:36 -04006436# check for function definitions
Peter Bigot5b10fac2020-03-26 11:16:33 -05006437 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006438 defined $stat &&
6439 $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
6440 $context_function = $1;
6441
6442# check for multiline function definition with misplaced open brace
6443 my $ok = 0;
6444 my $cnt = statement_rawlines($stat);
6445 my $herectx = $here . "\n";
6446 for (my $n = 0; $n < $cnt; $n++) {
6447 my $rl = raw_line($linenr, $n);
6448 $herectx .= $rl . "\n";
6449 $ok = 1 if ($rl =~ /^[ \+]\{/);
6450 $ok = 1 if ($rl =~ /\{/ && $n == 0);
6451 last if $rl =~ /^[ \+].*\{/;
6452 }
6453 if (!$ok) {
6454 ERROR("OPEN_BRACE",
6455 "open brace '{' following function definitions go on the next line\n" . $herectx);
6456 }
6457 }
6458
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006459# checks for new __setup's
6460 if ($rawline =~ /\b__setup\("([^"]*)"/) {
6461 my $name = $1;
6462
6463 if (!grep(/$name/, @setup_docs)) {
6464 CHK("UNDOCUMENTED_SETUP",
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006465 "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.txt\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006466 }
6467 }
6468
Peter Bigot5b10fac2020-03-26 11:16:33 -05006469# check for pointless casting of alloc functions
6470 if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006471 WARN("UNNECESSARY_CASTS",
6472 "unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
6473 }
6474
6475# alloc style
6476# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
Peter Bigot5b10fac2020-03-26 11:16:33 -05006477 if ($perl_version_ok &&
6478 $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 -07006479 CHK("ALLOC_SIZEOF_STRUCT",
6480 "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
6481 }
6482
6483# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
Peter Bigot5b10fac2020-03-26 11:16:33 -05006484 if ($perl_version_ok &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006485 defined $stat &&
6486 $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 -07006487 my $oldfunc = $3;
6488 my $a1 = $4;
6489 my $a2 = $10;
6490 my $newfunc = "kmalloc_array";
6491 $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
6492 my $r1 = $a1;
6493 my $r2 = $a2;
6494 if ($a1 =~ /^sizeof\s*\S/) {
6495 $r1 = $a2;
6496 $r2 = $a1;
6497 }
6498 if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
6499 !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
Anas Nashif1eb244c2017-10-01 17:06:36 -04006500 my $cnt = statement_rawlines($stat);
Peter Bigot5b10fac2020-03-26 11:16:33 -05006501 my $herectx = get_stat_here($linenr, $cnt, $here);
6502
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006503 if (WARN("ALLOC_WITH_MULTIPLY",
Anas Nashif1eb244c2017-10-01 17:06:36 -04006504 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
6505 $cnt == 1 &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006506 $fix) {
6507 $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 -07006508 }
6509 }
6510 }
6511
6512# check for krealloc arg reuse
Peter Bigot5b10fac2020-03-26 11:16:33 -05006513 if ($perl_version_ok &&
6514 $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
6515 $1 eq $3) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006516 WARN("KREALLOC_ARG_REUSE",
6517 "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
6518 }
6519
6520# check for alloc argument mismatch
6521 if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) {
6522 WARN("ALLOC_ARRAY_ARGS",
6523 "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
6524 }
6525
6526# check for multiple semicolons
6527 if ($line =~ /;\s*;\s*$/) {
6528 if (WARN("ONE_SEMICOLON",
6529 "Statements terminations use 1 semicolon\n" . $herecurr) &&
6530 $fix) {
6531 $fixed[$fixlinenr] =~ s/(\s*;\s*){2,}$/;/g;
6532 }
6533 }
6534
Anas Nashif0f3d5472016-11-07 15:57:57 -05006535# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
6536 if ($realfile !~ m@^include/uapi/@ &&
6537 $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006538 my $ull = "";
6539 $ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
6540 if (CHK("BIT_MACRO",
6541 "Prefer using the BIT$ull macro\n" . $herecurr) &&
6542 $fix) {
6543 $fixed[$fixlinenr] =~ s/\(?\s*1\s*[ulUL]*\s*<<\s*(\d+|$Ident)\s*\)?/BIT${ull}($1)/;
6544 }
6545 }
6546
Keith Packardb021dec2023-07-17 14:45:26 -07006547# check for feature test macros that request C library API extensions, violating rules A.4 and A.5
6548
6549 if ($line =~ /#\s*define\s+$api_defines/) {
6550 ERROR("API_DEFINE",
Alberto Escolar Piedrasf9e30842024-02-16 16:52:56 +01006551 "do not specify non-standard feature test macros for embedded code\n" . "$here$rawline\n");
Keith Packardb021dec2023-07-17 14:45:26 -07006552 }
6553
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006554# check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too)
6555 if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^CONFIG_/) {
6556 WARN("IS_ENABLED_CONFIG",
6557 "IS_ENABLED($1) is normally used as IS_ENABLED(CONFIG_$1)\n" . $herecurr);
6558 }
6559
Anas Nashif0f3d5472016-11-07 15:57:57 -05006560# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
6561 if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
6562 my $config = $1;
6563 if (WARN("PREFER_IS_ENABLED",
6564 "Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) &&
6565 $fix) {
6566 $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
6567 }
6568 }
6569
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006570# check for switch/default statements without a break;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006571 if ($perl_version_ok &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006572 defined $stat &&
6573 $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006574 my $cnt = statement_rawlines($stat);
Peter Bigot5b10fac2020-03-26 11:16:33 -05006575 my $herectx = get_stat_here($linenr, $cnt, $here);
6576
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006577 WARN("DEFAULT_NO_BREAK",
6578 "switch default: should use break\n" . $herectx);
6579 }
6580
6581# check for gcc specific __FUNCTION__
6582 if ($line =~ /\b__FUNCTION__\b/) {
6583 if (WARN("USE_FUNC",
6584 "__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr) &&
6585 $fix) {
6586 $fixed[$fixlinenr] =~ s/\b__FUNCTION__\b/__func__/g;
6587 }
6588 }
6589
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006590# check for uses of __DATE__, __TIME__, __TIMESTAMP__
6591 while ($line =~ /\b(__(?:DATE|TIME|TIMESTAMP)__)\b/g) {
6592 ERROR("DATE_TIME",
6593 "Use of the '$1' macro makes the build non-deterministic\n" . $herecurr);
6594 }
6595
Carles Cufi43ae4a72022-10-26 20:34:15 +02006596# check for uses of __BYTE_ORDER__
6597 while ($line =~ /\b(__BYTE_ORDER__)\b/g) {
6598 ERROR("BYTE_ORDER",
Carles Cufi192d01e2022-10-28 12:29:34 +02006599 "Use of the '$1' macro is disallowed. Use CONFIG_(BIG|LITTLE)_ENDIAN instead\n" . $herecurr);
Carles Cufi43ae4a72022-10-26 20:34:15 +02006600 }
6601
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006602# check for use of yield()
6603 if ($line =~ /\byield\s*\(\s*\)/) {
6604 WARN("YIELD",
6605 "Using yield() is generally wrong. See yield() kernel-doc (sched/core.c)\n" . $herecurr);
6606 }
6607
6608# check for comparisons against true and false
6609 if ($line =~ /\+\s*(.*?)\b(true|false|$Lval)\s*(==|\!=)\s*(true|false|$Lval)\b(.*)$/i) {
6610 my $lead = $1;
6611 my $arg = $2;
6612 my $test = $3;
6613 my $otype = $4;
6614 my $trail = $5;
6615 my $op = "!";
6616
6617 ($arg, $otype) = ($otype, $arg) if ($arg =~ /^(?:true|false)$/i);
6618
6619 my $type = lc($otype);
6620 if ($type =~ /^(?:true|false)$/) {
6621 if (("$test" eq "==" && "$type" eq "true") ||
6622 ("$test" eq "!=" && "$type" eq "false")) {
6623 $op = "";
6624 }
6625
6626 CHK("BOOL_COMPARISON",
6627 "Using comparison to $otype is error prone\n" . $herecurr);
6628
6629## maybe suggesting a correct construct would better
6630## "Using comparison to $otype is error prone. Perhaps use '${lead}${op}${arg}${trail}'\n" . $herecurr);
6631
6632 }
6633 }
6634
6635# check for semaphores initialized locked
6636 if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
6637 WARN("CONSIDER_COMPLETION",
6638 "consider using a completion\n" . $herecurr);
6639 }
6640
6641# recommend kstrto* over simple_strto* and strict_strto*
6642 if ($line =~ /\b((simple|strict)_(strto(l|ll|ul|ull)))\s*\(/) {
6643 WARN("CONSIDER_KSTRTO",
6644 "$1 is obsolete, use k$3 instead\n" . $herecurr);
6645 }
6646
6647# check for __initcall(), use device_initcall() explicitly or more appropriate function please
6648 if ($line =~ /^.\s*__initcall\s*\(/) {
6649 WARN("USE_DEVICE_INITCALL",
6650 "please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
6651 }
6652
Peter Bigot5b10fac2020-03-26 11:16:33 -05006653# check for spin_is_locked(), suggest lockdep instead
6654 if ($line =~ /\bspin_is_locked\(/) {
6655 WARN("USE_LOCKDEP",
6656 "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
6657 }
6658
6659# check for deprecated apis
6660 if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
6661 my $deprecated_api = $1;
6662 my $new_api = $deprecated_apis{$deprecated_api};
6663 WARN("DEPRECATED_API",
6664 "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
6665 }
6666
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006667# check for various structs that are normally const (ops, kgdb, device_tree)
Anas Nashif1eb244c2017-10-01 17:06:36 -04006668# and avoid what seem like struct definitions 'struct foo {'
Peter A. Bigote49e3c82020-08-10 10:37:32 -05006669 if (defined($const_structs) &&
6670 $line !~ /\bconst\b/ &&
Anas Nashif1eb244c2017-10-01 17:06:36 -04006671 $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006672 WARN("CONST_STRUCT",
Anas Nashif1eb244c2017-10-01 17:06:36 -04006673 "struct $1 should normally be const\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006674 }
6675
6676# use of NR_CPUS is usually wrong
6677# ignore definitions of NR_CPUS and usage to define arrays as likely right
6678 if ($line =~ /\bNR_CPUS\b/ &&
6679 $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
6680 $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
6681 $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
6682 $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
6683 $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
6684 {
6685 WARN("NR_CPUS",
6686 "usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
6687 }
6688
6689# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
6690 if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
6691 ERROR("DEFINE_ARCH_HAS",
6692 "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
6693 }
6694
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006695# likely/unlikely comparisons similar to "(likely(foo) > 0)"
Peter Bigot5b10fac2020-03-26 11:16:33 -05006696 if ($perl_version_ok &&
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006697 $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
6698 WARN("LIKELY_MISUSE",
6699 "Using $1 should generally have parentheses around the comparison\n" . $herecurr);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006700 }
6701
Peter Bigot5b10fac2020-03-26 11:16:33 -05006702# nested likely/unlikely calls
6703 if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
6704 WARN("LIKELY_MISUSE",
6705 "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
6706 }
6707
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006708# whine mightly about in_atomic
6709 if ($line =~ /\bin_atomic\s*\(/) {
6710 if ($realfile =~ m@^drivers/@) {
6711 ERROR("IN_ATOMIC",
6712 "do not use in_atomic in drivers\n" . $herecurr);
6713 } elsif ($realfile !~ m@^kernel/@) {
6714 WARN("IN_ATOMIC",
6715 "use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
6716 }
6717 }
6718
Anas Nashif1eb244c2017-10-01 17:06:36 -04006719# check for mutex_trylock_recursive usage
6720 if ($line =~ /mutex_trylock_recursive/) {
6721 ERROR("LOCKING",
6722 "recursive locking is bad, do not use this ever.\n" . $herecurr);
6723 }
6724
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006725# check for lockdep_set_novalidate_class
6726 if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
6727 $line =~ /__lockdep_no_validate__\s*\)/ ) {
6728 if ($realfile !~ m@^kernel/lockdep@ &&
6729 $realfile !~ m@^include/linux/lockdep@ &&
6730 $realfile !~ m@^drivers/base/core@) {
6731 ERROR("LOCKDEP",
6732 "lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
6733 }
6734 }
6735
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006736 if ($line =~ /debugfs_create_\w+.*\b$mode_perms_world_writable\b/ ||
6737 $line =~ /DEVICE_ATTR.*\b$mode_perms_world_writable\b/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006738 WARN("EXPORTED_WORLD_WRITABLE",
6739 "Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
6740 }
6741
Peter Bigot5b10fac2020-03-26 11:16:33 -05006742# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
6743# and whether or not function naming is typical and if
6744# DEVICE_ATTR permissions uses are unusual too
6745 if ($perl_version_ok &&
6746 defined $stat &&
6747 $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*\)/) {
6748 my $var = $1;
6749 my $perms = $2;
6750 my $show = $3;
6751 my $store = $4;
6752 my $octal_perms = perms_to_octal($perms);
6753 if ($show =~ /^${var}_show$/ &&
6754 $store =~ /^${var}_store$/ &&
6755 $octal_perms eq "0644") {
6756 if (WARN("DEVICE_ATTR_RW",
6757 "Use DEVICE_ATTR_RW\n" . $herecurr) &&
6758 $fix) {
6759 $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
6760 }
6761 } elsif ($show =~ /^${var}_show$/ &&
6762 $store =~ /^NULL$/ &&
6763 $octal_perms eq "0444") {
6764 if (WARN("DEVICE_ATTR_RO",
6765 "Use DEVICE_ATTR_RO\n" . $herecurr) &&
6766 $fix) {
6767 $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
6768 }
6769 } elsif ($show =~ /^NULL$/ &&
6770 $store =~ /^${var}_store$/ &&
6771 $octal_perms eq "0200") {
6772 if (WARN("DEVICE_ATTR_WO",
6773 "Use DEVICE_ATTR_WO\n" . $herecurr) &&
6774 $fix) {
6775 $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
6776 }
6777 } elsif ($octal_perms eq "0644" ||
6778 $octal_perms eq "0444" ||
6779 $octal_perms eq "0200") {
6780 my $newshow = "$show";
6781 $newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
6782 my $newstore = $store;
6783 $newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
6784 my $rename = "";
6785 if ($show ne $newshow) {
6786 $rename .= " '$show' to '$newshow'";
6787 }
6788 if ($store ne $newstore) {
6789 $rename .= " '$store' to '$newstore'";
6790 }
6791 WARN("DEVICE_ATTR_FUNCTIONS",
6792 "Consider renaming function(s)$rename\n" . $herecurr);
6793 } else {
6794 WARN("DEVICE_ATTR_PERMS",
6795 "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr);
6796 }
6797 }
6798
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006799# Mode permission misuses where it seems decimal should be octal
6800# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
Peter Bigot5b10fac2020-03-26 11:16:33 -05006801# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
6802# specific definition of not visible in sysfs.
6803# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
6804# use the default permissions
6805 if ($perl_version_ok &&
Anas Nashif0f3d5472016-11-07 15:57:57 -05006806 defined $stat &&
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006807 $line =~ /$mode_perms_search/) {
6808 foreach my $entry (@mode_permission_funcs) {
6809 my $func = $entry->[0];
6810 my $arg_pos = $entry->[1];
6811
Anas Nashif0f3d5472016-11-07 15:57:57 -05006812 my $lc = $stat =~ tr@\n@@;
6813 $lc = $lc + $linenr;
Peter Bigot5b10fac2020-03-26 11:16:33 -05006814 my $stat_real = get_stat_real($linenr, $lc);
Anas Nashif0f3d5472016-11-07 15:57:57 -05006815
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006816 my $skip_args = "";
6817 if ($arg_pos > 1) {
6818 $arg_pos--;
6819 $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
6820 }
Anas Nashif0f3d5472016-11-07 15:57:57 -05006821 my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
6822 if ($stat =~ /$test/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006823 my $val = $1;
6824 $val = $6 if ($skip_args ne "");
Peter Bigot5b10fac2020-03-26 11:16:33 -05006825 if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
6826 (($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
6827 ($val =~ /^$Octal$/ && length($val) ne 4))) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006828 ERROR("NON_OCTAL_PERMISSIONS",
Anas Nashif0f3d5472016-11-07 15:57:57 -05006829 "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
6830 }
6831 if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006832 ERROR("EXPORTED_WORLD_WRITABLE",
Anas Nashif0f3d5472016-11-07 15:57:57 -05006833 "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006834 }
6835 }
6836 }
6837 }
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006838
Anas Nashif0f3d5472016-11-07 15:57:57 -05006839# check for uses of S_<PERMS> that could be octal for readability
Peter Bigot5b10fac2020-03-26 11:16:33 -05006840 while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
6841 my $oval = $1;
6842 my $octal = perms_to_octal($oval);
Anas Nashif0f3d5472016-11-07 15:57:57 -05006843 if (WARN("SYMBOLIC_PERMS",
6844 "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
6845 $fix) {
Peter Bigot5b10fac2020-03-26 11:16:33 -05006846 $fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
Anas Nashif0f3d5472016-11-07 15:57:57 -05006847 }
6848 }
6849
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006850# validate content of MODULE_LICENSE against list from include/linux/module.h
6851 if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
6852 my $extracted_string = get_quoted_string($line, $rawline);
6853 my $valid_licenses = qr{
6854 GPL|
6855 GPL\ v2|
6856 GPL\ and\ additional\ rights|
6857 Dual\ BSD/GPL|
6858 Dual\ MIT/GPL|
6859 Dual\ MPL/GPL|
6860 Proprietary
6861 }x;
6862 if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) {
6863 WARN("MODULE_LICENSE",
6864 "unknown module license " . $extracted_string . "\n" . $herecurr);
6865 }
6866 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006867
6868# check for sysctl duplicate constants
6869 if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
6870 WARN("DUPLICATED_SYSCTL_CONST",
6871 "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
6872 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006873 }
6874
6875 # If we have no input at all, then there is nothing to report on
6876 # so just keep quiet.
6877 if ($#rawlines == -1) {
6878 exit(0);
6879 }
6880
6881 # In mailback mode only produce a report in the negative, for
6882 # things that appear to be patches.
6883 if ($mailback && ($clean == 1 || !$is_patch)) {
6884 exit(0);
6885 }
6886
6887 # This is not a patch, and we are are in 'no-patch' mode so
6888 # just keep quiet.
6889 if (!$chk_patch && !$is_patch) {
6890 exit(0);
6891 }
6892
Peter Bigot5b10fac2020-03-26 11:16:33 -05006893 if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006894 ERROR("NOT_UNIFIED_DIFF",
6895 "Does not appear to be a unified-diff format patch\n");
6896 }
Peter Bigot5b10fac2020-03-26 11:16:33 -05006897 if ($is_patch && $has_commit_log && $chk_signoff) {
6898 if ($signoff == 0) {
6899 ERROR("MISSING_SIGN_OFF",
6900 "Missing Signed-off-by: line(s)\n");
6901 } elsif (!$authorsignoff) {
6902 WARN("NO_AUTHOR_SIGN_OFF",
6903 "Missing Signed-off-by: line by nominal patch author '$author'\n");
6904 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006905 }
6906
6907 print report_dump();
6908 if ($summary && !($clean == 1 && $quiet == 1)) {
6909 print "$filename " if ($summary_file);
6910 print "total: $cnt_error errors, $cnt_warn warnings, " .
6911 (($check)? "$cnt_chk checks, " : "") .
6912 "$cnt_lines lines checked\n";
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006913 }
6914
6915 if ($quiet == 0) {
Anas Nashif0f3d5472016-11-07 15:57:57 -05006916 # If there were any defects found and not already fixing them
6917 if (!$clean and !$fix) {
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006918 print << "EOM"
6919
Anas Nashif0f3d5472016-11-07 15:57:57 -05006920NOTE: For some of the reported defects, checkpatch may be able to
6921 mechanically convert to the typical style using --fix or --fix-inplace.
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006922EOM
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006923 }
Anas Nashif1eb244c2017-10-01 17:06:36 -04006924 # If there were whitespace errors which cleanpatch can fix
6925 # then suggest that.
6926 if ($rpt_cleaners) {
6927 $rpt_cleaners = 0;
6928 print << "EOM"
6929
6930NOTE: Whitespace errors detected.
6931 You may wish to use scripts/cleanpatch or scripts/cleanfile
6932EOM
6933 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006934 }
6935
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006936 if ($clean == 0 && $fix &&
6937 ("@rawlines" ne "@fixed" ||
6938 $#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
6939 my $newfile = $filename;
6940 $newfile .= ".EXPERIMENTAL-checkpatch-fixes" if (!$fix_inplace);
6941 my $linecount = 0;
6942 my $f;
6943
6944 @fixed = fix_inserted_deleted_lines(\@fixed, \@fixed_inserted, \@fixed_deleted);
6945
6946 open($f, '>', $newfile)
6947 or die "$P: Can't open $newfile for write\n";
6948 foreach my $fixed_line (@fixed) {
6949 $linecount++;
6950 if ($file) {
6951 if ($linecount > 3) {
6952 $fixed_line =~ s/^\+//;
6953 print $f $fixed_line . "\n";
6954 }
6955 } else {
6956 print $f $fixed_line . "\n";
6957 }
6958 }
6959 close($f);
6960
6961 if (!$quiet) {
6962 print << "EOM";
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006963
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006964Wrote EXPERIMENTAL --fix correction(s) to '$newfile'
6965
6966Do _NOT_ trust the results written to this file.
6967Do _NOT_ submit these changes without inspecting them for correctness.
6968
6969This EXPERIMENTAL file is simply a convenience to help rewrite patches.
6970No warranties, expressed or implied...
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006971EOM
6972 }
6973 }
6974
Anas Nashifcbfb62c2015-10-14 06:08:54 -04006975 if ($quiet == 0) {
6976 print "\n";
6977 if ($clean == 1) {
6978 print "$vname has no obvious style problems and is ready for submission.\n";
6979 } else {
6980 print "$vname has style problems, please review.\n";
6981 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006982 }
Inaky Perez-Gonzalez8ddf82c2015-04-10 16:44:37 -07006983 return $clean;
6984}