blob: 833f20f555531de315251423f5fa7025c1bd41b6 [file] [log] [blame]
Kamil Rytarowskib7d5a9c2017-04-26 15:16:04 +02001#!/usr/bin/env perl
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002# (c) 2001, Dave Jones. (the file handling bit)
3# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
4# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
5# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
6# Licensed under the terms of the GNU GPL License version 2
7
8use strict;
Kamil Rytarowskib7d5a9c2017-04-26 15:16:04 +02009use warnings;
Paolo Bonzini1db42692018-11-29 09:52:58 +010010use Term::ANSIColor qw(:constants);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000011
12my $P = $0;
13$P =~ s@.*/@@g;
14
Matheus Ferst72205282021-05-20 16:51:42 -030015our $SrcFile = qr{\.(?:(h|c)(\.inc)?|cpp|s|S|pl|py|sh)$};
Paolo Bonzini777d05b2017-10-04 16:35:53 +020016
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000017my $V = '0.31';
18
19use Getopt::Long qw(:config no_auto_abbrev);
20
21my $quiet = 0;
22my $tree = 1;
23my $chk_signoff = 1;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +010024my $chk_patch = undef;
25my $chk_branch = undef;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000026my $tst_only;
27my $emacs = 0;
28my $terse = 0;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +010029my $file = undef;
Paolo Bonzini1db42692018-11-29 09:52:58 +010030my $color = "auto";
Paolo Bonzini141de882016-08-09 17:47:44 +020031my $no_warnings = 0;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000032my $summary = 1;
33my $mailback = 0;
34my $summary_file = 0;
35my $root;
36my %debug;
37my $help = 0;
Zhao Liue072af12024-01-05 16:38:48 +080038my $codespell = 0;
39my $codespellfile = "/usr/share/codespell/dictionary.txt";
40my $user_codespellfile = "";
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000041
42sub help {
43 my ($exitcode) = @_;
44
45 print << "EOM";
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +010046Usage:
47
48 $P [OPTION]... [FILE]...
49 $P [OPTION]... [GIT-REV-LIST]
50
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000051Version: $V
52
53Options:
54 -q, --quiet quiet
Aleksandar Markovic143a7682020-06-20 15:32:07 +020055 --no-tree run without a qemu tree
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000056 --no-signoff do not check for 'Signed-off-by' line
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +010057 --patch treat FILE as patchfile
58 --branch treat args as GIT revision list
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000059 --emacs emacs compile window format
60 --terse one line per report
61 -f, --file treat FILE as regular source file
Paolo Bonzini141de882016-08-09 17:47:44 +020062 --strict fail if only warnings are found
Aleksandar Markovic143a7682020-06-20 15:32:07 +020063 --root=PATH PATH to the qemu tree root
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000064 --no-summary suppress the per-file summary
65 --mailback only produce a report in case of warnings/errors
66 --summary-file include the filename in summary
67 --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of
68 'values', 'possible', 'type', and 'attr' (default
69 is all off)
70 --test-only=WORD report only warnings/errors containing WORD
71 literally
Zhao Liue072af12024-01-05 16:38:48 +080072 --codespell Use the codespell dictionary for spelling/typos
73 (default: $codespellfile)
74 --codespellfile Use this codespell dictionary
Paolo Bonzini1db42692018-11-29 09:52:58 +010075 --color[=WHEN] Use colors 'always', 'never', or only when output
76 is a terminal ('auto'). Default is 'auto'.
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000077 -h, --help, --version display this help and exit
78
79When FILE is - read standard input.
80EOM
81
82 exit($exitcode);
83}
84
Paolo Bonzini1db42692018-11-29 09:52:58 +010085# Perl's Getopt::Long allows options to take optional arguments after a space.
86# Prevent --color by itself from consuming other arguments
87foreach (@ARGV) {
88 if ($_ eq "--color" || $_ eq "-color") {
89 $_ = "--color=$color";
90 }
91}
92
Blue Swirl1ec3f6f2011-01-20 20:54:26 +000093GetOptions(
Zhao Liue072af12024-01-05 16:38:48 +080094 'q|quiet+' => \$quiet,
95 'tree!' => \$tree,
96 'signoff!' => \$chk_signoff,
97 'patch!' => \$chk_patch,
98 'branch!' => \$chk_branch,
99 'emacs!' => \$emacs,
100 'terse!' => \$terse,
101 'f|file!' => \$file,
102 'strict!' => \$no_warnings,
103 'root=s' => \$root,
104 'summary!' => \$summary,
105 'mailback!' => \$mailback,
106 'summary-file!' => \$summary_file,
107 'debug=s' => \%debug,
108 'test-only=s' => \$tst_only,
109 'codespell!' => \$codespell,
110 'codespellfile=s' => \$user_codespellfile,
111 'color=s' => \$color,
112 'no-color' => sub { $color = 'never'; },
113 'h|help' => \$help,
114 'version' => \$help
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000115) or help(1);
116
Zhao Liue072af12024-01-05 16:38:48 +0800117if ($user_codespellfile) {
118 # Use the user provided codespell file unconditionally
119 $codespellfile = $user_codespellfile;
120} elsif (!(-f $codespellfile)) {
121 # If /usr/share/codespell/dictionary.txt is not present, try to find it
122 # under codespell's install directory: <codespell_root>/data/dictionary.txt
123 if (($codespell || $help) && which("python3") ne "") {
124 my $python_codespell_dict = << "EOF";
125
126import os.path as op
127import codespell_lib
128codespell_dir = op.dirname(codespell_lib.__file__)
129codespell_file = op.join(codespell_dir, 'data', 'dictionary.txt')
130print(codespell_file, end='')
131EOF
132
133 my $codespell_dict = `python3 -c "$python_codespell_dict" 2> /dev/null`;
134 $codespellfile = $codespell_dict if (-f $codespell_dict);
135 }
136}
137
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000138help(0) if ($help);
139
140my $exit = 0;
141
142if ($#ARGV < 0) {
143 print "$P: no input files\n";
144 exit(1);
145}
146
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100147if (!defined $chk_branch && !defined $chk_patch && !defined $file) {
Paolo Bonzini777d05b2017-10-04 16:35:53 +0200148 $chk_branch = $ARGV[0] =~ /.\.\./ ? 1 : 0;
149 $file = $ARGV[0] =~ /$SrcFile/ ? 1 : 0;
150 $chk_patch = $chk_branch || $file ? 0 : 1;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100151} elsif (!defined $chk_branch && !defined $chk_patch) {
152 if ($file) {
153 $chk_branch = $chk_patch = 0;
154 } else {
Paolo Bonzini777d05b2017-10-04 16:35:53 +0200155 $chk_branch = $ARGV[0] =~ /.\.\./ ? 1 : 0;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100156 $chk_patch = $chk_branch ? 0 : 1;
157 }
158} elsif (!defined $chk_branch && !defined $file) {
159 if ($chk_patch) {
160 $chk_branch = $file = 0;
161 } else {
Paolo Bonzini777d05b2017-10-04 16:35:53 +0200162 $chk_branch = $ARGV[0] =~ /.\.\./ ? 1 : 0;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100163 $file = $chk_branch ? 0 : 1;
164 }
165} elsif (!defined $chk_patch && !defined $file) {
166 if ($chk_branch) {
167 $chk_patch = $file = 0;
168 } else {
Paolo Bonzini777d05b2017-10-04 16:35:53 +0200169 $file = $ARGV[0] =~ /$SrcFile/ ? 1 : 0;
170 $chk_patch = $file ? 0 : 1;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100171 }
172} elsif (!defined $chk_branch) {
173 $chk_branch = $chk_patch || $file ? 0 : 1;
174} elsif (!defined $chk_patch) {
175 $chk_patch = $chk_branch || $file ? 0 : 1;
176} elsif (!defined $file) {
177 $file = $chk_patch || $chk_branch ? 0 : 1;
178}
179
180if (($chk_patch && $chk_branch) ||
181 ($chk_patch && $file) ||
182 ($chk_branch && $file)) {
183 die "Only one of --file, --branch, --patch is permitted\n";
184}
185if (!$chk_patch && !$chk_branch && !$file) {
186 die "One of --file, --branch, --patch is required\n";
187}
188
Paolo Bonzini1db42692018-11-29 09:52:58 +0100189if ($color =~ /^always$/i) {
190 $color = 1;
191} elsif ($color =~ /^never$/i) {
192 $color = 0;
193} elsif ($color =~ /^auto$/i) {
194 $color = (-t STDOUT);
195} else {
196 die "Invalid color mode: $color\n";
197}
198
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000199my $dbg_values = 0;
200my $dbg_possible = 0;
201my $dbg_type = 0;
202my $dbg_attr = 0;
Don Slutza99ac042012-09-02 19:22:35 -0400203my $dbg_adv_dcs = 0;
Don Slutz54243022012-09-02 19:22:36 -0400204my $dbg_adv_checking = 0;
Don Slutz69402a62012-09-02 19:22:37 -0400205my $dbg_adv_apw = 0;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000206for my $key (keys %debug) {
207 ## no critic
208 eval "\${dbg_$key} = '$debug{$key}';";
209 die "$@" if ($@);
210}
211
212my $rpt_cleaners = 0;
213
214if ($terse) {
215 $emacs = 1;
216 $quiet++;
217}
218
219if ($tree) {
220 if (defined $root) {
221 if (!top_of_kernel_tree($root)) {
222 die "$P: $root: --root does not point at a valid tree\n";
223 }
224 } else {
225 if (top_of_kernel_tree('.')) {
226 $root = '.';
227 } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
228 top_of_kernel_tree($1)) {
229 $root = $1;
230 }
231 }
232
233 if (!defined $root) {
Aleksandar Markovic143a7682020-06-20 15:32:07 +0200234 print "Must be run from the top-level dir. of a qemu tree\n";
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000235 exit(2);
236 }
237}
238
239my $emitted_corrupt = 0;
240
241our $Ident = qr{
242 [A-Za-z_][A-Za-z\d_]*
243 (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
244 }x;
245our $Storage = qr{extern|static|asmlinkage};
246our $Sparse = qr{
Paolo Bonzinif1e155b2015-08-16 23:01:19 +0200247 __force
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000248 }x;
249
250# Notes to $Attribute:
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000251our $Attribute = qr{
252 const|
Paolo Bonzini71c47b02015-08-16 23:15:46 +0200253 volatile|
Marc-André Lureau89057702022-04-20 17:26:02 +0400254 G_NORETURN|
Marc-André Lureauc0840172022-02-24 00:58:22 +0400255 G_GNUC_WARN_UNUSED_RESULT|
Marc-André Lureau887ce502022-02-24 00:58:22 +0400256 G_GNUC_NULL_TERMINATED|
Paolo Bonzini71c47b02015-08-16 23:15:46 +0200257 QEMU_PACKED|
Marc-André Lureau9edc6312022-02-20 20:39:25 +0400258 G_GNUC_PRINTF
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000259 }x;
260our $Modifier;
Paolo Bonzini71c47b02015-08-16 23:15:46 +0200261our $Inline = qr{inline};
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000262our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
263our $Lval = qr{$Ident(?:$Member)*};
264
265our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
266our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
267our $Compare = qr{<=|>=|==|!=|<|>};
268our $Operators = qr{
269 <=|>=|==|!=|
270 =>|->|<<|>>|<|>|!|~|
271 &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
272 }x;
273
274our $NonptrType;
275our $Type;
276our $Declare;
277
Joe Perchesb37c4aa2018-04-30 13:46:47 +0100278our $NON_ASCII_UTF8 = qr{
279 [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000280 | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
281 | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
282 | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
283 | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
284 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
285 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
286}x;
287
Joe Perchesb37c4aa2018-04-30 13:46:47 +0100288our $UTF8 = qr{
289 [\x09\x0A\x0D\x20-\x7E] # ASCII
290 | $NON_ASCII_UTF8
291}x;
292
Paolo Bonzini874acb62019-05-17 15:19:00 +0200293# some readers default to ISO-8859-1 when showing email source. detect
294# when UTF-8 is incorrectly interpreted as ISO-8859-1 and reencoded back.
295# False positives are possible but very unlikely.
296our $UTF8_MOJIBAKE = qr{
297 \xC3[\x82-\x9F] \xC2[\x80-\xBF] # c2-df 80-bf
298 | \xC3\xA0 \xC2[\xA0-\xBF] \xC2[\x80-\xBF] # e0 a0-bf 80-bf
299 | \xC3[\xA1-\xAC\xAE\xAF] (?: \xC2[\x80-\xBF]){2} # e1-ec/ee/ef 80-bf 80-bf
300 | \xC3\xAD \xC2[\x80-\x9F] \xC2[\x80-\xBF] # ed 80-9f 80-bf
301 | \xC3\xB0 \xC2[\x90-\xBF] (?: \xC2[\x80-\xBF]){2} # f0 90-bf 80-bf 80-bf
302 | \xC3[\xB1-\xB3] (?: \xC2[\x80-\xBF]){3} # f1-f3 80-bf 80-bf 80-bf
303 | \xC3\xB4 \xC2[\x80-\x8F] (?: \xC2[\x80-\xBF]){2} # f4 80-b8 80-bf 80-bf
304}x;
305
Paolo Bonzinia6859de2014-06-10 10:52:02 +0200306# There are still some false positives, but this catches most
307# common cases.
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000308our $typeTypedefs = qr{(?x:
Philippe Mathieu-Daudé5fa96ca2018-06-25 09:41:56 -0300309 (?![KMGTPE]iB) # IEC binary prefix (do not match)
Paolo Bonzinia6859de2014-06-10 10:52:02 +0200310 [A-Z][A-Z\d_]*[a-z][A-Za-z\d_]* # camelcase
311 | [A-Z][A-Z\d_]*AIOCB # all uppercase
312 | [A-Z][A-Z\d_]*CPU # all uppercase
313 | QEMUBH # all uppercase
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000314)};
315
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000316our @typeList = (
317 qr{void},
318 qr{(?:unsigned\s+)?char},
319 qr{(?:unsigned\s+)?short},
320 qr{(?:unsigned\s+)?int},
321 qr{(?:unsigned\s+)?long},
322 qr{(?:unsigned\s+)?long\s+int},
323 qr{(?:unsigned\s+)?long\s+long},
324 qr{(?:unsigned\s+)?long\s+long\s+int},
325 qr{unsigned},
326 qr{float},
327 qr{double},
328 qr{bool},
329 qr{struct\s+$Ident},
330 qr{union\s+$Ident},
331 qr{enum\s+$Ident},
332 qr{${Ident}_t},
333 qr{${Ident}_handler},
334 qr{${Ident}_handler_fn},
Cédric Le Goaterf0707d22016-04-01 11:40:06 +0200335 qr{target_(?:u)?long},
Greg Kurz825bfa02017-09-14 11:12:07 +0200336 qr{hwaddr},
Peter Xu82870f32018-04-25 15:01:03 +0800337 # external libraries
Paul Durrant8d0f08e2018-05-22 11:42:50 -0700338 qr{xen\w+_handle},
Peter Xu82870f32018-04-25 15:01:03 +0800339 # Glib definitions
340 qr{gchar},
341 qr{gshort},
342 qr{glong},
343 qr{gint},
344 qr{gboolean},
345 qr{guchar},
346 qr{gushort},
347 qr{gulong},
348 qr{guint},
349 qr{gfloat},
350 qr{gdouble},
351 qr{gpointer},
352 qr{gconstpointer},
353 qr{gint8},
354 qr{guint8},
355 qr{gint16},
356 qr{guint16},
357 qr{gint32},
358 qr{guint32},
359 qr{gint64},
360 qr{guint64},
361 qr{gsize},
362 qr{gssize},
363 qr{goffset},
364 qr{gintptr},
365 qr{guintptr},
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000366);
Paolo Bonzinif1e155b2015-08-16 23:01:19 +0200367
Daniel P. Berrangé1f593812025-05-15 14:13:13 +0100368# Match text found in common license boilerplate comments:
369# for new files the SPDX-License-Identifier line is sufficient.
370our @LICENSE_BOILERPLATE = (
371 "licensed under the terms of the GNU GPL",
372 "under the terms of the GNU General Public License",
373 "under the terms of the GNU Lesser General Public",
374 "Permission is hereby granted, free of charge",
375 "GNU GPL, version 2 or later",
376 "See the COPYING file"
377);
378our $LICENSE_BOILERPLATE_RE = join("|", @LICENSE_BOILERPLATE);
379
Zhao Liue072af12024-01-05 16:38:48 +0800380# Load common spelling mistakes and build regular expression list.
381my $misspellings;
382my %spelling_fix;
383
384if ($codespell) {
385 if (open(my $spelling, '<', $codespellfile)) {
386 while (<$spelling>) {
387 my $line = $_;
388
389 $line =~ s/\s*\n?$//g;
390 $line =~ s/^\s*//g;
391
392 next if ($line =~ m/^\s*#/);
393 next if ($line =~ m/^\s*$/);
394 next if ($line =~ m/, disabled/i);
395
396 $line =~ s/,.*$//;
397
398 my ($suspect, $fix) = split(/->/, $line);
399
400 $spelling_fix{$suspect} = $fix;
401 }
402 close($spelling);
403 } else {
404 warn "No codespell typos will be found - file '$codespellfile': $!\n";
405 }
406}
407
408$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
409
Paolo Bonzinif1e155b2015-08-16 23:01:19 +0200410# This can be modified by sub possible. Since it can be empty, be careful
411# about regexes that always match, because they can cause infinite loops.
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000412our @modifierList = (
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000413);
414
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000415sub build_types {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000416 my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
Paolo Bonzinif1e155b2015-08-16 23:01:19 +0200417 if (@modifierList > 0) {
418 my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
419 $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
420 } else {
421 $Modifier = qr{(?:$Attribute|$Sparse)};
422 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000423 $NonptrType = qr{
424 (?:$Modifier\s+|const\s+)*
425 (?:
426 (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
427 (?:$typeTypedefs\b)|
428 (?:${all}\b)
429 )
430 (?:\s+$Modifier|\s+const)*
431 }x;
432 $Type = qr{
433 $NonptrType
434 (?:[\s\*]+\s*const|[\s\*]+|(?:\s*\[\s*\])+)?
435 (?:\s+$Inline|\s+$Modifier)*
436 }x;
437 $Declare = qr{(?:$Storage\s+)?$Type};
438}
439build_types();
440
441$chk_signoff = 0 if ($file);
442
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000443my @rawlines = ();
444my @lines = ();
445my $vname;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100446if ($chk_branch) {
447 my @patches;
Paolo Bonzinic182b612018-11-29 09:35:47 +0100448 my %git_commits = ();
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100449 my $HASH;
Philippe Mathieu-Daudéaf692fd2024-04-02 13:59:58 +0200450 open($HASH, "-|", "git", "log", "--reverse", "--no-merges", "--no-mailmap", "--format=%H %s", $ARGV[0]) ||
451 die "$P: git log --reverse --no-merges --no-mailmap --format='%H %s' $ARGV[0] failed - $!\n";
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100452
Paolo Bonzinic182b612018-11-29 09:35:47 +0100453 for my $line (<$HASH>) {
454 $line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
455 next if (!defined($1) || !defined($2));
456 my $sha1 = $1;
457 my $subject = $2;
458 push(@patches, $sha1);
459 $git_commits{$sha1} = $subject;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000460 }
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100461
462 close $HASH;
463
Daniel P. Berrangé2d4274d2020-10-21 17:31:35 +0100464 die "$P: no revisions returned for revlist '$ARGV[0]'\n"
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100465 unless @patches;
466
Paolo Bonzinic182b612018-11-29 09:35:47 +0100467 my $i = 1;
468 my $num_patches = @patches;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100469 for my $hash (@patches) {
470 my $FILE;
Alex Bennée66cf7012021-06-23 11:27:44 +0100471 open($FILE, '-|', "git",
472 "-c", "diff.renamelimit=0",
473 "-c", "diff.renames=True",
474 "-c", "diff.algorithm=histogram",
Philippe Mathieu-Daudéaf692fd2024-04-02 13:59:58 +0200475 "show", "--no-mailmap",
Alex Bennée66cf7012021-06-23 11:27:44 +0100476 "--patch-with-stat", $hash) ||
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100477 die "$P: git show $hash - $!\n";
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100478 while (<$FILE>) {
479 chomp;
480 push(@rawlines, $_);
481 }
482 close($FILE);
Paolo Bonzinic182b612018-11-29 09:35:47 +0100483 $vname = substr($hash, 0, 12) . ' (' . $git_commits{$hash} . ')';
484 if ($num_patches > 1 && $quiet == 0) {
Paolo Bonzini1db42692018-11-29 09:52:58 +0100485 my $prefix = "$i/$num_patches";
486 $prefix = BLUE . BOLD . $prefix . RESET if $color;
487 print "$prefix Checking commit $vname\n";
Paolo Bonzinic182b612018-11-29 09:35:47 +0100488 $vname = "Patch $i/$num_patches";
489 } else {
490 $vname = "Commit " . $vname;
491 }
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100492 if (!process($hash)) {
493 $exit = 1;
Paolo Bonzinic182b612018-11-29 09:35:47 +0100494 print "\n" if ($num_patches > 1 && $quiet == 0);
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100495 }
496 @rawlines = ();
497 @lines = ();
Paolo Bonzinic182b612018-11-29 09:35:47 +0100498 $i++;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000499 }
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100500} else {
501 for my $filename (@ARGV) {
502 my $FILE;
503 if ($file) {
504 open($FILE, '-|', "diff -u /dev/null $filename") ||
505 die "$P: $filename: diff failed - $!\n";
506 } elsif ($filename eq '-') {
507 open($FILE, '<&STDIN');
508 } else {
509 open($FILE, '<', "$filename") ||
510 die "$P: $filename: open failed - $!\n";
511 }
512 if ($filename eq '-') {
513 $vname = 'Your patch';
514 } else {
515 $vname = $filename;
516 }
Paolo Bonzinic182b612018-11-29 09:35:47 +0100517 print "Checking $filename...\n" if @ARGV > 1 && $quiet == 0;
Daniel P. Berrange8e1fe172017-09-13 10:10:00 +0100518 while (<$FILE>) {
519 chomp;
520 push(@rawlines, $_);
521 }
522 close($FILE);
523 if (!process($filename)) {
524 $exit = 1;
525 }
526 @rawlines = ();
527 @lines = ();
528 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000529}
530
531exit($exit);
532
533sub top_of_kernel_tree {
534 my ($root) = @_;
535
536 my @tree_check = (
Blue Swirlb6469682011-01-20 20:58:56 +0000537 "COPYING", "MAINTAINERS", "Makefile",
Daniel P. Berrangé336a7452019-08-23 17:09:24 +0100538 "README.rst", "docs", "VERSION",
Philippe Mathieu-Daudé8d7f2e72023-10-04 11:06:28 +0200539 "linux-user", "system"
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000540 );
541
542 foreach my $check (@tree_check) {
543 if (! -e $root . '/' . $check) {
544 return 0;
545 }
546 }
547 return 1;
548}
549
Zhao Liue072af12024-01-05 16:38:48 +0800550sub which {
551 my ($bin) = @_;
552
553 foreach my $path (split(/:/, $ENV{PATH})) {
554 if (-e "$path/$bin") {
555 return "$path/$bin";
556 }
557 }
558
559 return "";
560}
561
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000562sub expand_tabs {
563 my ($str) = @_;
564
565 my $res = '';
566 my $n = 0;
567 for my $c (split(//, $str)) {
568 if ($c eq "\t") {
569 $res .= ' ';
570 $n++;
571 for (; ($n % 8) != 0; $n++) {
572 $res .= ' ';
573 }
574 next;
575 }
576 $res .= $c;
577 $n++;
578 }
579
580 return $res;
581}
582sub copy_spacing {
583 (my $res = shift) =~ tr/\t/ /c;
584 return $res;
585}
586
587sub line_stats {
588 my ($line) = @_;
589
590 # Drop the diff line leader and expand tabs
591 $line =~ s/^.//;
592 $line = expand_tabs($line);
593
594 # Pick the indent from the front of the line.
595 my ($white) = ($line =~ /^(\s*)/);
596
597 return (length($line), length($white));
598}
599
600my $sanitise_quote = '';
601
602sub sanitise_line_reset {
603 my ($in_comment) = @_;
604
605 if ($in_comment) {
606 $sanitise_quote = '*/';
607 } else {
608 $sanitise_quote = '';
609 }
610}
611sub sanitise_line {
612 my ($line) = @_;
613
614 my $res = '';
615 my $l = '';
616
617 my $qlen = 0;
618 my $off = 0;
619 my $c;
620
621 # Always copy over the diff marker.
622 $res = substr($line, 0, 1);
623
624 for ($off = 1; $off < length($line); $off++) {
625 $c = substr($line, $off, 1);
626
Stefan Weilcb8d4c82016-03-23 15:59:57 +0100627 # Comments we are wacking completely including the begin
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000628 # and end, all to $;.
629 if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
630 $sanitise_quote = '*/';
631
632 substr($res, $off, 2, "$;$;");
633 $off++;
634 next;
635 }
636 if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
637 $sanitise_quote = '';
638 substr($res, $off, 2, "$;$;");
639 $off++;
640 next;
641 }
642 if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
643 $sanitise_quote = '//';
644
645 substr($res, $off, 2, $sanitise_quote);
646 $off++;
647 next;
648 }
649
650 # A \ in a string means ignore the next character.
651 if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
652 $c eq "\\") {
653 substr($res, $off, 2, 'XX');
654 $off++;
655 next;
656 }
657 # Regular quotes.
658 if ($c eq "'" || $c eq '"') {
659 if ($sanitise_quote eq '') {
660 $sanitise_quote = $c;
661
662 substr($res, $off, 1, $c);
663 next;
664 } elsif ($sanitise_quote eq $c) {
665 $sanitise_quote = '';
666 }
667 }
668
669 #print "c<$c> SQ<$sanitise_quote>\n";
670 if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
671 substr($res, $off, 1, $;);
672 } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
673 substr($res, $off, 1, $;);
674 } elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
675 substr($res, $off, 1, 'X');
676 } else {
677 substr($res, $off, 1, $c);
678 }
679 }
680
681 if ($sanitise_quote eq '//') {
682 $sanitise_quote = '';
683 }
684
685 # The pathname on a #include may be surrounded by '<' and '>'.
686 if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
687 my $clean = 'X' x length($1);
688 $res =~ s@\<.*\>@<$clean>@;
689
690 # The whole of a #error is a string.
691 } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
692 my $clean = 'X' x length($1);
693 $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
694 }
695
696 return $res;
697}
698
699sub ctx_statement_block {
700 my ($linenr, $remain, $off) = @_;
701 my $line = $linenr - 1;
702 my $blk = '';
703 my $soff = $off;
704 my $coff = $off - 1;
705 my $coff_set = 0;
706
707 my $loff = 0;
708
709 my $type = '';
710 my $level = 0;
711 my @stack = ();
712 my $p;
713 my $c;
714 my $len = 0;
715
716 my $remainder;
717 while (1) {
718 @stack = (['', 0]) if ($#stack == -1);
719
720 #warn "CSB: blk<$blk> remain<$remain>\n";
721 # If we are about to drop off the end, pull in more
722 # context.
723 if ($off >= $len) {
724 for (; $remain > 0; $line++) {
725 last if (!defined $lines[$line]);
726 next if ($lines[$line] =~ /^-/);
727 $remain--;
728 $loff = $len;
729 $blk .= $lines[$line] . "\n";
730 $len = length($blk);
731 $line++;
732 last;
733 }
734 # Bail if there is no further context.
735 #warn "CSB: blk<$blk> off<$off> len<$len>\n";
736 if ($off >= $len) {
737 last;
738 }
739 }
740 $p = $c;
741 $c = substr($blk, $off, 1);
742 $remainder = substr($blk, $off);
743
744 #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
745
746 # Handle nested #if/#else.
747 if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
748 push(@stack, [ $type, $level ]);
749 } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
750 ($type, $level) = @{$stack[$#stack - 1]};
751 } elsif ($remainder =~ /^#\s*endif\b/) {
752 ($type, $level) = @{pop(@stack)};
753 }
754
755 # Statement ends at the ';' or a close '}' at the
756 # outermost level.
757 if ($level == 0 && $c eq ';') {
758 last;
759 }
760
761 # An else is really a conditional as long as its not else if
762 if ($level == 0 && $coff_set == 0 &&
763 (!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
764 $remainder =~ /^(else)(?:\s|{)/ &&
765 $remainder !~ /^else\s+if\b/) {
766 $coff = $off + length($1) - 1;
767 $coff_set = 1;
768 #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
769 #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
770 }
771
772 if (($type eq '' || $type eq '(') && $c eq '(') {
773 $level++;
774 $type = '(';
775 }
776 if ($type eq '(' && $c eq ')') {
777 $level--;
778 $type = ($level != 0)? '(' : '';
779
780 if ($level == 0 && $coff < $soff) {
781 $coff = $off;
782 $coff_set = 1;
783 #warn "CSB: mark coff<$coff>\n";
784 }
785 }
786 if (($type eq '' || $type eq '{') && $c eq '{') {
787 $level++;
788 $type = '{';
789 }
790 if ($type eq '{' && $c eq '}') {
791 $level--;
792 $type = ($level != 0)? '{' : '';
793
794 if ($level == 0) {
795 if (substr($blk, $off + 1, 1) eq ';') {
796 $off++;
797 }
798 last;
799 }
800 }
801 $off++;
802 }
803 # We are truly at the end, so shuffle to the next line.
804 if ($off == $len) {
805 $loff = $len + 1;
806 $line++;
807 $remain--;
808 }
809
810 my $statement = substr($blk, $soff, $off - $soff + 1);
811 my $condition = substr($blk, $soff, $coff - $soff + 1);
812
813 #warn "STATEMENT<$statement>\n";
814 #warn "CONDITION<$condition>\n";
815
816 #print "coff<$coff> soff<$off> loff<$loff>\n";
817
818 return ($statement, $condition,
819 $line, $remain + 1, $off - $loff + 1, $level);
820}
821
822sub statement_lines {
823 my ($stmt) = @_;
824
825 # Strip the diff line prefixes and rip blank lines at start and end.
826 $stmt =~ s/(^|\n)./$1/g;
827 $stmt =~ s/^\s*//;
828 $stmt =~ s/\s*$//;
829
830 my @stmt_lines = ($stmt =~ /\n/g);
831
832 return $#stmt_lines + 2;
833}
834
835sub statement_rawlines {
836 my ($stmt) = @_;
837
838 my @stmt_lines = ($stmt =~ /\n/g);
839
840 return $#stmt_lines + 2;
841}
842
843sub statement_block_size {
844 my ($stmt) = @_;
845
846 $stmt =~ s/(^|\n)./$1/g;
Fam Zheng04f25622015-09-11 19:07:36 +0800847 $stmt =~ s/^\s*\{//;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +0000848 $stmt =~ s/}\s*$//;
849 $stmt =~ s/^\s*//;
850 $stmt =~ s/\s*$//;
851
852 my @stmt_lines = ($stmt =~ /\n/g);
853 my @stmt_statements = ($stmt =~ /;/g);
854
855 my $stmt_lines = $#stmt_lines + 2;
856 my $stmt_statements = $#stmt_statements + 1;
857
858 if ($stmt_lines > $stmt_statements) {
859 return $stmt_lines;
860 } else {
861 return $stmt_statements;
862 }
863}
864
865sub ctx_statement_full {
866 my ($linenr, $remain, $off) = @_;
867 my ($statement, $condition, $level);
868
869 my (@chunks);
870
871 # Grab the first conditional/block pair.
872 ($statement, $condition, $linenr, $remain, $off, $level) =
873 ctx_statement_block($linenr, $remain, $off);
874 #print "F: c<$condition> s<$statement> remain<$remain>\n";
875 push(@chunks, [ $condition, $statement ]);
876 if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
877 return ($level, $linenr, @chunks);
878 }
879
880 # Pull in the following conditional/block pairs and see if they
881 # could continue the statement.
882 for (;;) {
883 ($statement, $condition, $linenr, $remain, $off, $level) =
884 ctx_statement_block($linenr, $remain, $off);
885 #print "C: c<$condition> s<$statement> remain<$remain>\n";
886 last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
887 #print "C: push\n";
888 push(@chunks, [ $condition, $statement ]);
889 }
890
891 return ($level, $linenr, @chunks);
892}
893
894sub ctx_block_get {
895 my ($linenr, $remain, $outer, $open, $close, $off) = @_;
896 my $line;
897 my $start = $linenr - 1;
898 my $blk = '';
899 my @o;
900 my @c;
901 my @res = ();
902
903 my $level = 0;
904 my @stack = ($level);
905 for ($line = $start; $remain > 0; $line++) {
906 next if ($rawlines[$line] =~ /^-/);
907 $remain--;
908
909 $blk .= $rawlines[$line];
910
911 # Handle nested #if/#else.
912 if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
913 push(@stack, $level);
914 } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
915 $level = $stack[$#stack - 1];
916 } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
917 $level = pop(@stack);
918 }
919
920 foreach my $c (split(//, $lines[$line])) {
921 ##print "C<$c>L<$level><$open$close>O<$off>\n";
922 if ($off > 0) {
923 $off--;
924 next;
925 }
926
927 if ($c eq $close && $level > 0) {
928 $level--;
929 last if ($level == 0);
930 } elsif ($c eq $open) {
931 $level++;
932 }
933 }
934
935 if (!$outer || $level <= 1) {
936 push(@res, $rawlines[$line]);
937 }
938
939 last if ($level == 0);
940 }
941
942 return ($level, @res);
943}
944sub ctx_block_outer {
945 my ($linenr, $remain) = @_;
946
947 my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
948 return @r;
949}
950sub ctx_block {
951 my ($linenr, $remain) = @_;
952
953 my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
954 return @r;
955}
956sub ctx_statement {
957 my ($linenr, $remain, $off) = @_;
958
959 my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
960 return @r;
961}
962sub ctx_block_level {
963 my ($linenr, $remain) = @_;
964
965 return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
966}
967sub ctx_statement_level {
968 my ($linenr, $remain, $off) = @_;
969
970 return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
971}
972
973sub ctx_locate_comment {
974 my ($first_line, $end_line) = @_;
975
976 # Catch a comment on the end of the line itself.
977 my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
978 return $current_comment if (defined $current_comment);
979
980 # Look through the context and try and figure out if there is a
981 # comment.
982 my $in_comment = 0;
983 $current_comment = '';
984 for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
985 my $line = $rawlines[$linenr - 1];
986 #warn " $line\n";
987 if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
988 $in_comment = 1;
989 }
990 if ($line =~ m@/\*@) {
991 $in_comment = 1;
992 }
993 if (!$in_comment && $current_comment ne '') {
994 $current_comment = '';
995 }
996 $current_comment .= $line . "\n" if ($in_comment);
997 if ($line =~ m@\*/@) {
998 $in_comment = 0;
999 }
1000 }
1001
1002 chomp($current_comment);
1003 return($current_comment);
1004}
1005sub ctx_has_comment {
1006 my ($first_line, $end_line) = @_;
1007 my $cmt = ctx_locate_comment($first_line, $end_line);
1008
1009 ##print "LINE: $rawlines[$end_line - 1 ]\n";
1010 ##print "CMMT: $cmt\n";
1011
1012 return ($cmt ne '');
1013}
1014
1015sub raw_line {
1016 my ($linenr, $cnt) = @_;
1017
1018 my $offset = $linenr - 1;
1019 $cnt++;
1020
1021 my $line;
1022 while ($cnt) {
1023 $line = $rawlines[$offset++];
1024 next if (defined($line) && $line =~ /^-/);
1025 $cnt--;
1026 }
1027
1028 return $line;
1029}
1030
1031sub cat_vet {
1032 my ($vet) = @_;
1033 my ($res, $coded);
1034
1035 $res = '';
1036 while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
1037 $res .= $1;
1038 if ($2 ne '') {
1039 $coded = sprintf("^%c", unpack('C', $2) + 64);
1040 $res .= $coded;
1041 }
1042 }
1043 $res =~ s/$/\$/;
1044
1045 return $res;
1046}
1047
1048my $av_preprocessor = 0;
1049my $av_pending;
1050my @av_paren_type;
1051my $av_pend_colon;
1052
1053sub annotate_reset {
1054 $av_preprocessor = 0;
1055 $av_pending = '_';
1056 @av_paren_type = ('E');
1057 $av_pend_colon = 'O';
1058}
1059
1060sub annotate_values {
1061 my ($stream, $type) = @_;
1062
1063 my $res;
1064 my $var = '_' x length($stream);
1065 my $cur = $stream;
1066
1067 print "$stream\n" if ($dbg_values > 1);
1068
1069 while (length($cur)) {
1070 @av_paren_type = ('E') if ($#av_paren_type < 0);
1071 print " <" . join('', @av_paren_type) .
1072 "> <$type> <$av_pending>" if ($dbg_values > 1);
1073 if ($cur =~ /^(\s+)/o) {
1074 print "WS($1)\n" if ($dbg_values > 1);
1075 if ($1 =~ /\n/ && $av_preprocessor) {
1076 $type = pop(@av_paren_type);
1077 $av_preprocessor = 0;
1078 }
1079
Florian Mickler61669f92011-11-25 10:24:16 +01001080 } elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001081 print "CAST($1)\n" if ($dbg_values > 1);
1082 push(@av_paren_type, $type);
1083 $type = 'C';
1084
1085 } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
1086 print "DECLARE($1)\n" if ($dbg_values > 1);
1087 $type = 'T';
1088
1089 } elsif ($cur =~ /^($Modifier)\s*/) {
1090 print "MODIFIER($1)\n" if ($dbg_values > 1);
1091 $type = 'T';
1092
1093 } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
1094 print "DEFINE($1,$2)\n" if ($dbg_values > 1);
1095 $av_preprocessor = 1;
1096 push(@av_paren_type, $type);
1097 if ($2 ne '') {
1098 $av_pending = 'N';
1099 }
1100 $type = 'E';
1101
1102 } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
1103 print "UNDEF($1)\n" if ($dbg_values > 1);
1104 $av_preprocessor = 1;
1105 push(@av_paren_type, $type);
1106
1107 } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
1108 print "PRE_START($1)\n" if ($dbg_values > 1);
1109 $av_preprocessor = 1;
1110
1111 push(@av_paren_type, $type);
1112 push(@av_paren_type, $type);
1113 $type = 'E';
1114
1115 } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
1116 print "PRE_RESTART($1)\n" if ($dbg_values > 1);
1117 $av_preprocessor = 1;
1118
1119 push(@av_paren_type, $av_paren_type[$#av_paren_type]);
1120
1121 $type = 'E';
1122
1123 } elsif ($cur =~ /^(\#\s*(?:endif))/o) {
1124 print "PRE_END($1)\n" if ($dbg_values > 1);
1125
1126 $av_preprocessor = 1;
1127
1128 # Assume all arms of the conditional end as this
1129 # one does, and continue as if the #endif was not here.
1130 pop(@av_paren_type);
1131 push(@av_paren_type, $type);
1132 $type = 'E';
1133
1134 } elsif ($cur =~ /^(\\\n)/o) {
1135 print "PRECONT($1)\n" if ($dbg_values > 1);
1136
1137 } elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
1138 print "ATTR($1)\n" if ($dbg_values > 1);
1139 $av_pending = $type;
1140 $type = 'N';
1141
1142 } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
1143 print "SIZEOF($1)\n" if ($dbg_values > 1);
1144 if (defined $2) {
1145 $av_pending = 'V';
1146 }
1147 $type = 'N';
1148
1149 } elsif ($cur =~ /^(if|while|for)\b/o) {
1150 print "COND($1)\n" if ($dbg_values > 1);
1151 $av_pending = 'E';
1152 $type = 'N';
1153
1154 } elsif ($cur =~/^(case)/o) {
1155 print "CASE($1)\n" if ($dbg_values > 1);
1156 $av_pend_colon = 'C';
1157 $type = 'N';
1158
1159 } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
1160 print "KEYWORD($1)\n" if ($dbg_values > 1);
1161 $type = 'N';
1162
1163 } elsif ($cur =~ /^(\()/o) {
1164 print "PAREN('$1')\n" if ($dbg_values > 1);
1165 push(@av_paren_type, $av_pending);
1166 $av_pending = '_';
1167 $type = 'N';
1168
1169 } elsif ($cur =~ /^(\))/o) {
1170 my $new_type = pop(@av_paren_type);
1171 if ($new_type ne '_') {
1172 $type = $new_type;
1173 print "PAREN('$1') -> $type\n"
1174 if ($dbg_values > 1);
1175 } else {
1176 print "PAREN('$1')\n" if ($dbg_values > 1);
1177 }
1178
1179 } elsif ($cur =~ /^($Ident)\s*\(/o) {
1180 print "FUNC($1)\n" if ($dbg_values > 1);
1181 $type = 'V';
1182 $av_pending = 'V';
1183
1184 } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
1185 if (defined $2 && $type eq 'C' || $type eq 'T') {
1186 $av_pend_colon = 'B';
1187 } elsif ($type eq 'E') {
1188 $av_pend_colon = 'L';
1189 }
1190 print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
1191 $type = 'V';
1192
1193 } elsif ($cur =~ /^($Ident|$Constant)/o) {
1194 print "IDENT($1)\n" if ($dbg_values > 1);
1195 $type = 'V';
1196
1197 } elsif ($cur =~ /^($Assignment)/o) {
1198 print "ASSIGN($1)\n" if ($dbg_values > 1);
1199 $type = 'N';
1200
1201 } elsif ($cur =~/^(;|{|})/) {
1202 print "END($1)\n" if ($dbg_values > 1);
1203 $type = 'E';
1204 $av_pend_colon = 'O';
1205
1206 } elsif ($cur =~/^(,)/) {
1207 print "COMMA($1)\n" if ($dbg_values > 1);
1208 $type = 'C';
1209
1210 } elsif ($cur =~ /^(\?)/o) {
1211 print "QUESTION($1)\n" if ($dbg_values > 1);
1212 $type = 'N';
1213
1214 } elsif ($cur =~ /^(:)/o) {
1215 print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
1216
1217 substr($var, length($res), 1, $av_pend_colon);
1218 if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
1219 $type = 'E';
1220 } else {
1221 $type = 'N';
1222 }
1223 $av_pend_colon = 'O';
1224
1225 } elsif ($cur =~ /^(\[)/o) {
1226 print "CLOSE($1)\n" if ($dbg_values > 1);
1227 $type = 'N';
1228
1229 } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
1230 my $variant;
1231
1232 print "OPV($1)\n" if ($dbg_values > 1);
1233 if ($type eq 'V') {
1234 $variant = 'B';
1235 } else {
1236 $variant = 'U';
1237 }
1238
1239 substr($var, length($res), 1, $variant);
1240 $type = 'N';
1241
1242 } elsif ($cur =~ /^($Operators)/o) {
1243 print "OP($1)\n" if ($dbg_values > 1);
1244 if ($1 ne '++' && $1 ne '--') {
1245 $type = 'N';
1246 }
1247
1248 } elsif ($cur =~ /(^.)/o) {
1249 print "C($1)\n" if ($dbg_values > 1);
1250 }
1251 if (defined $1) {
1252 $cur = substr($cur, length($1));
1253 $res .= $type x length($1);
1254 }
1255 }
1256
1257 return ($res, $var);
1258}
1259
1260sub possible {
1261 my ($possible, $line) = @_;
1262 my $notPermitted = qr{(?:
1263 ^(?:
1264 $Modifier|
1265 $Storage|
1266 $Type|
1267 DEFINE_\S+
1268 )$|
1269 ^(?:
1270 goto|
1271 return|
1272 case|
1273 else|
1274 asm|__asm__|
Paolo Bonzinie20122f2018-07-04 18:05:43 +02001275 do
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001276 )(?:\s|$)|
Paolo Bonzinie20122f2018-07-04 18:05:43 +02001277 ^(?:typedef|struct|enum)\b|
1278 ^\#
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001279 )}x;
1280 warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
1281 if ($possible !~ $notPermitted) {
1282 # Check for modifiers.
1283 $possible =~ s/\s*$Storage\s*//g;
1284 $possible =~ s/\s*$Sparse\s*//g;
1285 if ($possible =~ /^\s*$/) {
1286
1287 } elsif ($possible =~ /\s/) {
Paolo Bonzinie20122f2018-07-04 18:05:43 +02001288 $possible =~ s/\s*(?:$Type|\#\#)\s*//g;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001289 for my $modifier (split(' ', $possible)) {
1290 if ($modifier !~ $notPermitted) {
1291 warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
1292 push(@modifierList, $modifier);
1293 }
1294 }
1295
1296 } else {
1297 warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
1298 push(@typeList, $possible);
1299 }
1300 build_types();
1301 } else {
1302 warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
1303 }
1304}
1305
1306my $prefix = '';
1307
1308sub report {
Paolo Bonzini1db42692018-11-29 09:52:58 +01001309 my ($level, $msg) = @_;
1310 if (defined $tst_only && $msg !~ /\Q$tst_only\E/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001311 return 0;
1312 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001313
Paolo Bonzini1db42692018-11-29 09:52:58 +01001314 my $output = '';
1315 $output .= BOLD if $color;
1316 $output .= $prefix;
1317 $output .= RED if $color && $level eq 'ERROR';
1318 $output .= MAGENTA if $color && $level eq 'WARNING';
1319 $output .= $level . ':';
1320 $output .= RESET if $color;
1321 $output .= ' ' . $msg . "\n";
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001322
Paolo Bonzini1db42692018-11-29 09:52:58 +01001323 $output = (split('\n', $output))[0] . "\n" if ($terse);
1324
1325 push(our @report, $output);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001326
1327 return 1;
1328}
1329sub report_dump {
1330 our @report;
1331}
1332sub ERROR {
Paolo Bonzini1db42692018-11-29 09:52:58 +01001333 if (report("ERROR", $_[0])) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001334 our $clean = 0;
1335 our $cnt_error++;
1336 }
1337}
1338sub WARN {
Paolo Bonzini1db42692018-11-29 09:52:58 +01001339 if (report("WARNING", $_[0])) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001340 our $clean = 0;
1341 our $cnt_warn++;
1342 }
1343}
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001344
Daniel P. Berrangé2b96c1a2024-10-07 15:40:28 +01001345sub checkspdx {
1346 my ($file, $expr) = @_;
1347
1348 # Imported Linux headers probably have SPDX tags, but if they
1349 # don't we're not requiring contributors to fix this, as these
1350 # files are not expected to be modified locally in QEMU.
1351 # Also don't accidentally detect own checking code.
1352 if ($file =~ m,include/standard-headers, ||
1353 $file =~ m,linux-headers, ||
1354 $file =~ m,checkpatch.pl,) {
1355 return;
1356 }
1357
1358 my $origexpr = $expr;
1359
1360 # Flatten sub-expressions
1361 $expr =~ s/\(|\)/ /g;
1362 $expr =~ s/OR|AND/ /g;
1363
1364 # Merge WITH exceptions to the license
1365 $expr =~ s/\s+WITH\s+/-WITH-/g;
1366
1367 # Cull more leading/trailing whitespace
1368 $expr =~ s/^\s*//g;
1369 $expr =~ s/\s*$//g;
1370
1371 my @bits = split / +/, $expr;
1372
1373 my $prefer = "GPL-2.0-or-later";
1374 my @valid = qw(
1375 GPL-2.0-only
1376 LGPL-2.1-only
1377 LGPL-2.1-or-later
1378 BSD-2-Clause
1379 BSD-3-Clause
1380 MIT
1381 );
1382
1383 my $nonpreferred = 0;
1384 my @unknown = ();
1385 foreach my $bit (@bits) {
1386 if ($bit eq $prefer) {
1387 next;
1388 }
1389 if (grep /^$bit$/, @valid) {
1390 $nonpreferred = 1;
1391 } else {
1392 push @unknown, $bit;
1393 }
1394 }
1395 if (@unknown) {
1396 ERROR("Saw unacceptable licenses '" . join(',', @unknown) .
1397 "', valid choices for QEMU are:\n" . join("\n", $prefer, @valid));
1398 }
1399
1400 if ($nonpreferred) {
1401 WARN("Saw acceptable license '$origexpr' but note '$prefer' is " .
1402 "preferred for new files unless the code is derived from a " .
1403 "source file with an existing declared license that must be " .
1404 "retained. Please explain the license choice in the commit " .
1405 "message.");
1406 }
1407}
1408
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001409# All three of the methods below take a 'file info' record
1410# which is a hash ref containing
1411#
1412# 'isgit': 1 if an enhanced git diff or 0 for a plain diff
1413# 'githeader': 1 if still parsing git patch header, 0 otherwise
1414# 'linestart': line number of start of file diff
1415# 'lineend': line number of end of file diff
1416# 'filenew': the new filename
1417# 'fileold': the old filename (same as 'new filename' except
1418# for renames in git diffs)
1419# 'action': one of 'modified' (always) or 'new' or 'deleted' or
1420# 'renamed' (git diffs only)
1421# 'mode': file mode for new/deleted files (git diffs only)
1422# 'similarity': file similarity when renamed (git diffs only)
1423# 'facts': hash ref for storing any metadata related to checks
1424#
1425
1426# Called at the end of each patch, with the list of
1427# real filenames that were seen in the patch
1428sub process_file_list {
1429 my @fileinfos = @_;
Daniel P. Berrangé9bec5f92025-05-12 17:48:20 +01001430
1431 # According to tests/qtest/bios-tables-test.c: do not
1432 # change expected file in the same commit with adding test
1433 my @acpi_testexpected;
1434 my @acpi_nontestexpected;
1435
1436 foreach my $fileinfo (@fileinfos) {
1437 # Note: shell script that rebuilds the expected files is in
1438 # the same directory as files themselves.
1439 # Note: allowed diff list can be changed both when changing
1440 # expected files and when changing tests.
1441 if ($fileinfo->{filenew} =~ m#^tests/data/acpi/# &&
1442 $fileinfo->{filenew} !~ m#^\.sh$#) {
1443 push @acpi_testexpected, $fileinfo->{filenew};
1444 } elsif ($fileinfo->{filenew} !~
1445 m#^tests/qtest/bios-tables-test-allowed-diff.h$#) {
1446 push @acpi_nontestexpected, $fileinfo->{filenew};
1447 }
1448 }
1449 if (int(@acpi_testexpected) > 0 and int(@acpi_nontestexpected) > 0) {
1450 ERROR("Do not add expected files together with tests, " .
1451 "follow instructions in " .
1452 "tests/qtest/bios-tables-test.c. Files\n\n " .
1453 join("\n ", @acpi_testexpected) .
1454 "\n\nand\n\n " .
1455 join("\n ", @acpi_nontestexpected) .
1456 "\n\nfound in the same patch\n");
1457 }
Daniel P. Berrangé1d745e62025-05-12 18:01:00 +01001458
1459 my $sawmaintainers = 0;
1460 my @maybemaintainers;
1461 foreach my $fileinfo (@fileinfos) {
1462 if ($fileinfo->{action} ne "modified" &&
1463 $fileinfo->{filenew} !~ m#^tests/data/acpi/#) {
1464 push @maybemaintainers, $fileinfo->{filenew};
1465 }
1466 if ($fileinfo->{filenew} eq "MAINTAINERS") {
1467 $sawmaintainers = 1;
1468 }
1469 }
1470
1471 # If we don't see a MAINTAINERS update, prod the user to check
1472 if (int(@maybemaintainers) > 0 && !$sawmaintainers) {
1473 WARN("added, moved or deleted file(s):\n\n " .
1474 join("\n ", @maybemaintainers) .
1475 "\n\nDoes MAINTAINERS need updating?\n");
1476 }
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001477}
1478
1479# Called at the start of processing a diff hunk for a file
1480sub process_start_of_file {
1481 my $fileinfo = shift;
Daniel P. Berrangéf48f16e2025-05-12 17:11:55 +01001482
1483 # Check for incorrect file permissions
1484 if ($fileinfo->{action} eq "new" && ($fileinfo->{mode} & 0111)) {
1485 my $permhere = $fileinfo->{linestart} . "FILE: " .
1486 $fileinfo->{filenew} . "\n";
1487 if ($fileinfo->{filenew} =~
Daniel P. Berrangé45abbf22025-05-15 13:57:45 +01001488 /(\bMakefile.*|\.(c|cc|cpp|h|mak|s|S))$/) {
Daniel P. Berrangéf48f16e2025-05-12 17:11:55 +01001489 ERROR("do not set execute permissions for source " .
1490 "files\n" . $permhere);
1491 }
1492 }
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001493}
1494
1495# Called at the end of processing a diff hunk for a file
1496sub process_end_of_file {
1497 my $fileinfo = shift;
Daniel P. Berrangéb3693402025-05-08 17:43:40 +01001498
1499 if ($fileinfo->{action} eq "new" &&
1500 !exists $fileinfo->{facts}->{sawspdx}) {
1501 if ($fileinfo->{filenew} =~
Daniel P. Berrangé81941aa2025-05-21 09:47:00 +01001502 /(\.(c|h|py|pl|sh|json|inc|rs)|Makefile.*)$/) {
Daniel P. Berrangéb3693402025-05-08 17:43:40 +01001503 # source code files MUST have SPDX license declared
1504 ERROR("New file '" . $fileinfo->{filenew} .
1505 "' requires 'SPDX-License-Identifier'");
1506 } else {
1507 # Other files MAY have SPDX license if appropriate
1508 WARN("Does new file '" . $fileinfo->{filenew} .
1509 "' need 'SPDX-License-Identifier'?");
1510 }
1511 }
Daniel P. Berrangé1f593812025-05-15 14:13:13 +01001512 if ($fileinfo->{action} eq "new" &&
1513 exists $fileinfo->{facts}->{sawboilerplate}) {
1514 ERROR("New file '" . $fileinfo->{filenew} . "' must " .
1515 "not have license boilerplate header text, only " .
1516 "the SPDX-License-Identifier, unless this file was " .
1517 "copied from existing code already having such text.");
1518 }
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001519}
1520
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001521sub process {
1522 my $filename = shift;
1523
1524 my $linenr=0;
1525 my $prevline="";
1526 my $prevrawline="";
1527 my $stashline="";
1528 my $stashrawline="";
1529
1530 my $length;
1531 my $indent;
1532 my $previndent=0;
1533 my $stashindent=0;
1534
1535 our $clean = 1;
1536 my $signoff = 0;
1537 my $is_patch = 0;
1538
Joe Perches5fc7e402018-04-30 13:46:49 +01001539 my $in_header_lines = $file ? 0 : 1;
Joe Perchesb37c4aa2018-04-30 13:46:47 +01001540 my $in_commit_log = 0; #Scanning lines before patch
Stefano Garzarella503eb472024-08-13 21:23:14 +01001541 my $reported_mixing_imported_file = 0;
1542 my $in_imported_file = 0;
1543 my $in_no_imported_file = 0;
Pasi Savanainenbf139a02018-04-30 13:46:48 +01001544 my $non_utf8_charset = 0;
1545
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001546 our @report = ();
1547 our $cnt_lines = 0;
1548 our $cnt_error = 0;
1549 our $cnt_warn = 0;
1550 our $cnt_chk = 0;
1551
1552 # Trace the real file/line as we go.
1553 my $realfile = '';
1554 my $realline = 0;
1555 my $realcnt = 0;
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001556 my $fileinfo;
1557 my @fileinfolist;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001558 my $here = '';
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001559 my $oldhere = '';
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001560 my $in_comment = 0;
1561 my $comment_edge = 0;
1562 my $first_line = 0;
1563 my $p1_prefix = '';
1564
1565 my $prev_values = 'E';
1566
1567 # suppression flags
1568 my %suppress_ifbraces;
1569 my %suppress_whiletrailers;
1570 my %suppress_export;
1571
1572 # Pre-scan the patch sanitizing the lines.
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001573
1574 sanitise_line_reset();
1575 my $line;
1576 foreach my $rawline (@rawlines) {
1577 $linenr++;
1578 $line = $rawline;
1579
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001580 if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
1581 $realline=$1-1;
1582 if (defined $2) {
1583 $realcnt=$3+1;
1584 } else {
1585 $realcnt=1+1;
1586 }
1587 $in_comment = 0;
1588
1589 # Guestimate if this is a continuing comment. Run
1590 # the context looking for a comment "edge". If this
1591 # edge is a close comment then we must be in a comment
1592 # at context start.
1593 my $edge;
1594 my $cnt = $realcnt;
1595 for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
1596 next if (defined $rawlines[$ln - 1] &&
1597 $rawlines[$ln - 1] =~ /^-/);
1598 $cnt--;
1599 #print "RAW<$rawlines[$ln - 1]>\n";
1600 last if (!defined $rawlines[$ln - 1]);
1601 if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
1602 $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
1603 ($edge) = $1;
1604 last;
1605 }
1606 }
1607 if (defined $edge && $edge eq '*/') {
1608 $in_comment = 1;
1609 }
1610
1611 # Guestimate if this is a continuing comment. If this
1612 # is the start of a diff block and this line starts
1613 # ' *' then it is very likely a comment.
1614 if (!defined $edge &&
1615 $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
1616 {
1617 $in_comment = 1;
1618 }
1619
1620 ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
1621 sanitise_line_reset($in_comment);
1622
1623 } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
1624 # Standardise the strings and chars within the input to
1625 # simplify matching -- only bother with positive lines.
1626 $line = sanitise_line($rawline);
1627 }
1628 push(@lines, $line);
1629
1630 if ($realcnt > 1) {
1631 $realcnt-- if ($line =~ /^(?:\+| |$)/);
1632 } else {
1633 $realcnt = 0;
1634 }
1635
1636 #print "==>$rawline\n";
1637 #print "-->$line\n";
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001638 }
1639
1640 $prefix = '';
1641
1642 $realcnt = 0;
1643 $linenr = 0;
1644 foreach my $line (@lines) {
1645 $linenr++;
1646
1647 my $rawline = $rawlines[$linenr - 1];
1648
1649#extract the line range in the file after the patch is applied
1650 if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
1651 $is_patch = 1;
1652 $first_line = $linenr + 1;
1653 $realline=$1-1;
1654 if (defined $2) {
1655 $realcnt=$3+1;
1656 } else {
1657 $realcnt=1+1;
1658 }
1659 annotate_reset();
1660 $prev_values = 'E';
1661
1662 %suppress_ifbraces = ();
1663 %suppress_whiletrailers = ();
1664 %suppress_export = ();
1665 next;
1666
1667# track the line number as we move through the hunk, note that
1668# new versions of GNU diff omit the leading space on completely
1669# blank context lines so we need to count that too.
1670 } elsif ($line =~ /^( |\+|$)/) {
1671 $realline++;
1672 $realcnt-- if ($realcnt != 0);
1673
1674 # Measure the line length and indent.
1675 ($length, $indent) = line_stats($rawline);
1676
1677 # Track the previous line.
1678 ($prevline, $stashline) = ($stashline, $line);
1679 ($previndent, $stashindent) = ($stashindent, $indent);
1680 ($prevrawline, $stashrawline) = ($stashrawline, $rawline);
1681
1682 #warn "line<$line>\n";
1683
1684 } elsif ($realcnt == 1) {
1685 $realcnt--;
1686 }
1687
1688 my $hunk_line = ($realcnt != 0);
1689
1690#make up the handle for any error we report on this line
1691 $prefix = "$filename:$realline: " if ($emacs && $file);
1692 $prefix = "$filename:$linenr: " if ($emacs && !$file);
1693
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001694 $oldhere = $here;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001695 $here = "#$linenr: " if (!$file);
1696 $here = "#$realline: " if ($file);
1697
1698 # extract the filename as it passes
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001699 if ($line =~ /^diff --git\s+(\S+)\s+(\S+)$/) {
1700 my $fileold = $1;
1701 my $filenew = $2;
1702
1703 if (defined $fileinfo) {
1704 $fileinfo->{lineend} = $oldhere;
1705 process_end_of_file($fileinfo)
1706 }
1707 $fileold =~ s@^([^/]*)/@@ if (!$file);
1708 $filenew =~ s@^([^/]*)/@@ if (!$file);
1709 $realfile = $filenew;
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001710
1711 $fileinfo = {
1712 "isgit" => 1,
1713 "githeader" => 1,
1714 "linestart" => $here,
1715 "lineend" => 0,
1716 "fileold" => $fileold,
1717 "filenew" => $filenew,
1718 "action" => "modified",
1719 "mode" => 0,
1720 "similarity" => 0,
1721 "facts" => {},
1722 };
1723 push @fileinfolist, $fileinfo;
1724 } elsif (defined $fileinfo && $fileinfo->{githeader} &&
1725 $line =~ /^(new|deleted) (?:file )?mode\s+([0-7]+)$/) {
1726 $fileinfo->{action} = $1;
1727 $fileinfo->{mode} = oct($2);
1728 } elsif (defined $fileinfo && $fileinfo->{githeader} &&
1729 $line =~ /^similarity index (\d+)%/) {
1730 $fileinfo->{similarity} = int($1);
1731 } elsif (defined $fileinfo && $fileinfo->{githeader} &&
1732 $line =~ /^rename (from|to) [\w\/\.\-]+\s*$/) {
1733 $fileinfo->{action} = "renamed";
1734 # For a no-change rename, we'll never have any "+++..."
1735 # lines, so trigger actions now
1736 if ($1 eq "to" && $fileinfo->{similarity} == 100) {
1737 process_start_of_file($fileinfo);
1738 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001739 } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
1740 $realfile = $1;
Paolo Bonzini1a5c63c2018-08-10 16:35:19 +02001741 $realfile =~ s@^([^/]*)/@@ if (!$file);
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001742
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001743 $p1_prefix = $1;
1744 if (!$file && $tree && $p1_prefix ne '' &&
1745 -e "$root/$p1_prefix") {
1746 WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
1747 }
1748
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01001749 if (defined $fileinfo && !$fileinfo->{isgit}) {
1750 $fileinfo->{lineend} = $oldhere;
1751 process_end_of_file($fileinfo);
1752 }
1753
1754 if (!defined $fileinfo || !$fileinfo->{isgit}) {
1755 $fileinfo = {
1756 "isgit" => 0,
1757 "githeader" => 0,
1758 "linestart" => $here,
1759 "lineend" => 0,
1760 "fileold" => $realfile,
1761 "filenew" => $realfile,
1762 "action" => "modified",
1763 "mode" => 0,
1764 "similarity" => 0,
1765 "facts" => {},
1766 };
1767 push @fileinfolist, $fileinfo;
1768 } else {
1769 $fileinfo->{githeader} = 0;
1770 }
1771 process_start_of_file($fileinfo);
1772
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001773 next;
1774 }
1775
1776 $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
1777
1778 my $hereline = "$here\n$rawline\n";
1779 my $herecurr = "$here\n$rawline\n";
1780 my $hereprev = "$here\n$prevrawline\n$rawline\n";
1781
1782 $cnt_lines++ if ($realcnt != 0);
1783
Philippe Mathieu-Daudébc7f3b02020-01-30 17:32:21 +01001784# Only allow Python 3 interpreter
1785 if ($realline == 1 &&
1786 $line =~ /^\+#!\ *\/usr\/bin\/(?:env )?python$/) {
1787 ERROR("please use python3 interpreter\n" . $herecurr);
1788 }
1789
Stefan Hajnoczif8dccbb2016-07-15 10:46:54 +01001790# Accept git diff extended headers as valid patches
1791 if ($line =~ /^(?:rename|copy) (?:from|to) [\w\/\.\-]+\s*$/) {
1792 $is_patch = 1;
1793 }
1794
Philippe Mathieu-Daudée3812d12024-04-02 13:59:57 +02001795 if ($line =~ /^(Author|From): .* via .*<qemu-\w+\@nongnu\.org>/) {
Daniel P. Berrangéf5177792018-08-23 11:21:43 +01001796 ERROR("Author email address is mangled by the mailing list\n" . $herecurr);
1797 }
1798
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001799#check the patch for a signoff:
1800 if ($line =~ /^\s*signed-off-by:/i) {
1801 # This is a signoff, if ugly, so do not double report.
1802 $signoff++;
Joe Perchesb37c4aa2018-04-30 13:46:47 +01001803 $in_commit_log = 0;
1804
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001805 if (!($line =~ /^\s*Signed-off-by:/)) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02001806 ERROR("The correct form is \"Signed-off-by\"\n" .
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001807 $herecurr);
1808 }
1809 if ($line =~ /^\s*signed-off-by:\S/i) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02001810 ERROR("space required after Signed-off-by:\n" .
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001811 $herecurr);
1812 }
1813 }
1814
Daniel P. Berrangé2b96c1a2024-10-07 15:40:28 +01001815# Check SPDX-License-Identifier references a permitted license
1816 if ($rawline =~ m,SPDX-License-Identifier: (.*?)(\*/)?\s*$,) {
Daniel P. Berrangéb3693402025-05-08 17:43:40 +01001817 $fileinfo->{facts}->{sawspdx} = 1;
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01001818 &checkspdx($realfile, $1);
Daniel P. Berrangé2b96c1a2024-10-07 15:40:28 +01001819 }
1820
Daniel P. Berrangé1f593812025-05-15 14:13:13 +01001821 if ($rawline =~ /$LICENSE_BOILERPLATE_RE/) {
1822 $fileinfo->{facts}->{sawboilerplate} = 1;
1823 }
1824
Daniel P. Berrangé6b752182024-10-07 16:21:54 +01001825 if ($rawline =~ m,(SPDX-[a-zA-Z0-9-_]+):,) {
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01001826 my $tag = $1;
1827 my @permitted = qw(
1828 SPDX-License-Identifier
1829 );
Daniel P. Berrangé6b752182024-10-07 16:21:54 +01001830
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01001831 unless (grep { /^$tag$/ } @permitted) {
1832 ERROR("Tag $tag not permitted in QEMU code, " .
1833 "valid choices are: " .
1834 join(", ", @permitted));
1835 }
Daniel P. Berrangé6b752182024-10-07 16:21:54 +01001836 }
1837
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001838# Check for wrappage within a valid hunk of the file
1839 if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
1840 ERROR("patch seems to be corrupt (line wrapped?)\n" .
1841 $herecurr) if (!$emitted_corrupt++);
1842 }
1843
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001844# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
1845 if (($realfile =~ /^$/ || $line =~ /^\+/) &&
1846 $rawline !~ m/^$UTF8*$/) {
1847 my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
1848
1849 my $blank = copy_spacing($rawline);
1850 my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
1851 my $hereptr = "$hereline$ptr\n";
1852
1853 ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
1854 }
1855
Paolo Bonzini874acb62019-05-17 15:19:00 +02001856 if ($rawline =~ m/$UTF8_MOJIBAKE/) {
1857 ERROR("Doubly-encoded UTF-8\n" . $herecurr);
1858 }
Joe Perchesb37c4aa2018-04-30 13:46:47 +01001859# Check if it's the start of a commit log
1860# (not a header line and we haven't seen the patch filename)
1861 if ($in_header_lines && $realfile =~ /^$/ &&
Joe Perches5fc7e402018-04-30 13:46:49 +01001862 !($rawline =~ /^\s+\S/ ||
1863 $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
Joe Perchesb37c4aa2018-04-30 13:46:47 +01001864 $in_header_lines = 0;
1865 $in_commit_log = 1;
1866 }
1867
Pasi Savanainenbf139a02018-04-30 13:46:48 +01001868# Check if there is UTF-8 in a commit log when a mail header has explicitly
1869# declined it, i.e defined some charset where it is missing.
1870 if ($in_header_lines &&
1871 $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
1872 $1 !~ /utf-8/i) {
1873 $non_utf8_charset = 1;
1874 }
1875
1876 if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
Joe Perchesb37c4aa2018-04-30 13:46:47 +01001877 $rawline =~ /$NON_ASCII_UTF8/) {
1878 WARN("8-bit UTF-8 used in possible commit log\n" . $herecurr);
1879 }
1880
Zhao Liue072af12024-01-05 16:38:48 +08001881# Check for various typo / spelling mistakes
1882 if (defined($misspellings) &&
1883 ($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
1884 while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {
1885 my $typo = $1;
1886 my $blank = copy_spacing($rawline);
1887 my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);
1888 my $hereptr = "$hereline$ptr\n";
1889 my $typo_fix = $spelling_fix{lc($typo)};
1890 $typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
1891 $typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
1892 WARN("'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $hereptr);
1893 }
1894 }
1895
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001896# ignore non-hunk lines and lines being removed
1897 next if (!$hunk_line || $line =~ /^-/);
1898
Stefano Garzarella503eb472024-08-13 21:23:14 +01001899# Check that updating imported files from Linux are not mixed with other changes
1900 if ($realfile =~ /^(linux-headers|include\/standard-headers)\//) {
1901 if (!$in_imported_file) {
1902 WARN("added, moved or deleted file(s) " .
1903 "imported from Linux, are you using " .
1904 "scripts/update-linux-headers.sh?\n" .
1905 $herecurr);
1906 }
1907 $in_imported_file = 1;
1908 } else {
1909 $in_no_imported_file = 1;
1910 }
1911
1912 if (!$reported_mixing_imported_file &&
1913 $in_imported_file && $in_no_imported_file) {
1914 ERROR("headers imported from Linux should be self-" .
1915 "contained in a patch with no other changes\n" .
1916 $herecurr);
1917 $reported_mixing_imported_file = 1;
1918 }
1919
Radim Krčmář93bf13c2016-08-09 19:38:41 +02001920# ignore files that are being periodically imported from Linux
1921 next if ($realfile =~ /^(linux-headers|include\/standard-headers)\//);
1922
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001923#trailing whitespace
1924 if ($line =~ /^\+.*\015/) {
1925 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1926 ERROR("DOS line endings\n" . $herevet);
1927
Lluís Vilanova0cebabd2016-09-07 14:49:04 +02001928 } elsif ($realfile =~ /^docs\/.+\.txt/ ||
1929 $realfile =~ /^docs\/.+\.md/) {
1930 if ($rawline =~ /^\+\s+$/ && $rawline !~ /^\+ {4}$/) {
1931 # TODO: properly check we're in a code block
1932 # (surrounding text is 4-column aligned)
1933 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1934 ERROR("code blocks in documentation should have " .
1935 "empty lines with exactly 4 columns of " .
1936 "whitespace\n" . $herevet);
1937 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001938 } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
1939 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
1940 ERROR("trailing whitespace\n" . $herevet);
1941 $rpt_cleaners = 1;
1942 }
1943
Vladimir Sementsov-Ogievskiyc3e58752017-07-31 19:01:34 +03001944# checks for trace-events files
1945 if ($realfile =~ /trace-events$/ && $line =~ /^\+/) {
1946 if ($rawline =~ /%[-+ 0]*#/) {
1947 ERROR("Don't use '#' flag of printf format ('%#') in " .
1948 "trace-events, use '0x' prefix instead\n" . $herecurr);
1949 } else {
1950 my $hex =
1951 qr/%[-+ *.0-9]*([hljztL]|ll|hh)?(x|X|"\s*PRI[xX][^"]*"?)/;
1952
Michael Tokarevd30b5bc2023-07-14 14:33:18 +03001953 # don't consider groups split by [.:/ ], like 2A.20:12ab
Vladimir Sementsov-Ogievskiy45042732017-10-04 18:44:20 +03001954 my $tmpline = $rawline;
1955 $tmpline =~ s/($hex[.:\/ ])+$hex//g;
Vladimir Sementsov-Ogievskiyc3e58752017-07-31 19:01:34 +03001956
1957 if ($tmpline =~ /(?<!0x)$hex/) {
1958 ERROR("Hex numbers must be prefixed with '0x'\n" .
1959 $herecurr);
1960 }
1961 }
1962 }
1963
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001964# check we are in a valid source file if not then ignore this hunk
Paolo Bonzini777d05b2017-10-04 16:35:53 +02001965 next if ($realfile !~ /$SrcFile/);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001966
Eric Blake205f31a2018-02-22 15:58:38 -06001967#90 column limit; exempt URLs, if no other words on line
Paolo Bonzinif1e155b2015-08-16 23:01:19 +02001968 if ($line =~ /^\+/ &&
1969 !($line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
Eric Blake205f31a2018-02-22 15:58:38 -06001970 !($rawline =~ /^[^[:alnum:]]*https?:\S*$/) &&
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001971 $length > 80)
1972 {
Paolo Bonzini8fbe3d12015-09-07 11:53:02 +02001973 if ($length > 90) {
1974 ERROR("line over 90 characters\n" . $herecurr);
1975 } else {
1976 WARN("line over 80 characters\n" . $herecurr);
1977 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001978 }
1979
1980# check for spaces before a quoted newline
1981 if ($rawline =~ /^.*\".*\s\\n/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02001982 ERROR("unnecessary whitespace before a quoted newline\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001983 }
1984
1985# check for adding lines without a newline.
1986 if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02001987 ERROR("adding a line without newline at end of file\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00001988 }
1989
Paolo Bonzini93eb8e32016-08-10 10:05:03 +02001990# check for RCS/CVS revision markers
1991 if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|\b)/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02001992 ERROR("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
Paolo Bonzini93eb8e32016-08-10 10:05:03 +02001993 }
1994
Paolo Bonzini906fb132016-08-09 17:47:42 +02001995# tabs are only allowed in assembly source code, and in
1996# some scripts we imported from other projects.
1997 next if ($realfile =~ /\.(s|S)$/);
Peter Maydell7a470a32020-09-25 17:23:13 +01001998 next if ($realfile =~ /(checkpatch|get_maintainer)\.pl$/);
Matheus Tavares Bernardino321b0ca2022-09-20 10:42:28 -03001999 next if ($realfile =~ /^target\/hexagon\/imported\/*/);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002000
Blue Swirlad36ce82011-02-05 13:18:20 +00002001 if ($rawline =~ /^\+.*\t/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002002 my $herevet = "$here\n" . cat_vet($rawline) . "\n";
Blue Swirlb6469682011-01-20 20:58:56 +00002003 ERROR("code indent should never use tabs\n" . $herevet);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002004 $rpt_cleaners = 1;
2005 }
2006
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002007# check we are in a valid C source file if not then ignore this hunk
Matheus Ferst72205282021-05-20 16:51:42 -03002008 next if ($realfile !~ /\.((h|c)(\.inc)?|cpp)$/);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002009
Peter Maydell8c06fbd2018-12-14 13:30:48 +00002010# Block comment styles
2011
2012 # Block comments use /* on a line of its own
Michael S. Tsirkin1ef47f402022-11-07 09:52:16 -05002013 my $commentline = $rawline;
Michael S. Tsirkin53a3b832022-11-08 08:52:06 -05002014 while ($commentline =~ s@^(\+.*)/\*.*\*/@$1@o) { # remove inline /*...*/
Michael S. Tsirkin1ef47f402022-11-07 09:52:16 -05002015 }
2016 if ($commentline =~ m@^\+.*/\*\*?+[ \t]*[^ \t]@) { # /* or /** non-blank
Peter Maydell8c06fbd2018-12-14 13:30:48 +00002017 WARN("Block comments use a leading /* on a separate line\n" . $herecurr);
2018 }
2019
2020# Block comments use * on subsequent lines
2021 if ($prevline =~ /$;[ \t]*$/ && #ends in comment
2022 $prevrawline =~ /^\+.*?\/\*/ && #starting /*
2023 $prevrawline !~ /\*\/[ \t]*$/ && #no trailing */
2024 $rawline =~ /^\+/ && #line is new
2025 $rawline !~ /^\+[ \t]*\*/) { #no leading *
2026 WARN("Block comments use * on subsequent lines\n" . $hereprev);
2027 }
2028
2029# Block comments use */ on trailing lines
2030 if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */
2031 $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/
2032 $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/
2033 $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */
2034 WARN("Block comments use a trailing */ on a separate line\n" . $herecurr);
2035 }
2036
2037# Block comment * alignment
2038 if ($prevline =~ /$;[ \t]*$/ && #ends in comment
2039 $line =~ /^\+[ \t]*$;/ && #leading comment
2040 $rawline =~ /^\+[ \t]*\*/ && #leading *
2041 (($prevrawline =~ /^\+.*?\/\*/ && #leading /*
2042 $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
2043 $prevrawline =~ /^\+[ \t]*\*/)) { #leading *
2044 my $oldindent;
2045 $prevrawline =~ m@^\+([ \t]*/?)\*@;
2046 if (defined($1)) {
2047 $oldindent = expand_tabs($1);
2048 } else {
2049 $prevrawline =~ m@^\+(.*/?)\*@;
2050 $oldindent = expand_tabs($1);
2051 }
2052 $rawline =~ m@^\+([ \t]*)\*@;
2053 my $newindent = $1;
2054 $newindent = expand_tabs($newindent);
2055 if (length($oldindent) ne length($newindent)) {
2056 WARN("Block comments should align the * on each line\n" . $hereprev);
2057 }
2058 }
2059
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002060# Check for potential 'bare' types
2061 my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
2062 $realline_next);
2063 if ($realcnt && $line =~ /.\s*\S/) {
2064 ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
2065 ctx_statement_block($linenr, $realcnt, 0);
2066 $stat =~ s/\n./\n /g;
2067 $cond =~ s/\n./\n /g;
2068
2069 # Find the real next line.
2070 $realline_next = $line_nr_next;
2071 if (defined $realline_next &&
2072 (!defined $lines[$realline_next - 1] ||
2073 substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
2074 $realline_next++;
2075 }
2076
2077 my $s = $stat;
2078 $s =~ s/{.*$//s;
2079
2080 # Ignore goto labels.
2081 if ($s =~ /$Ident:\*$/s) {
2082
2083 # Ignore functions being called
2084 } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
2085
2086 } elsif ($s =~ /^.\s*else\b/s) {
2087
2088 # declarations always start with types
2089 } 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) {
2090 my $type = $1;
2091 $type =~ s/\s+/ /g;
2092 possible($type, "A:" . $s);
2093
2094 # definitions in global scope can only start with types
2095 } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
2096 possible($1, "B:" . $s);
2097 }
2098
2099 # any (foo ... *) is a pointer cast, and foo is a type
2100 while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
2101 possible($1, "C:" . $s);
2102 }
2103
2104 # Check for any sort of function declaration.
2105 # int foo(something bar, other baz);
2106 # void (*store_gdt)(x86_descr_ptr *);
2107 if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
2108 my ($name_len) = length($1);
2109
2110 my $ctx = $s;
2111 substr($ctx, 0, $name_len + 1, '');
2112 $ctx =~ s/\)[^\)]*$//;
2113
2114 for my $arg (split(/\s*,\s*/, $ctx)) {
2115 if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
2116
2117 possible($1, "D:" . $s);
2118 }
2119 }
2120 }
2121
2122 }
2123
2124#
2125# Checks which may be anchored in the context.
2126#
2127
2128# Check for switch () and associated case and default
2129# statements should be at the same indent.
2130 if ($line=~/\bswitch\s*\(.*\)/) {
2131 my $err = '';
2132 my $sep = '';
2133 my @ctx = ctx_block_outer($linenr, $realcnt);
2134 shift(@ctx);
2135 for my $ctx (@ctx) {
2136 my ($clen, $cindent) = line_stats($ctx);
2137 if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
2138 $indent != $cindent) {
2139 $err .= "$sep$ctx\n";
2140 $sep = '';
2141 } else {
2142 $sep = "[...]\n";
2143 }
2144 }
2145 if ($err ne '') {
2146 ERROR("switch and case should be at the same indent\n$hereline$err");
2147 }
2148 }
2149
2150# if/while/etc brace do not go on next line, unless defining a do while loop,
2151# or if that brace on the next line is for something else
2152 if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
2153 my $pre_ctx = "$1$2";
2154
2155 my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
2156 my $ctx_cnt = $realcnt - $#ctx - 1;
2157 my $ctx = join("\n", @ctx);
2158
2159 my $ctx_ln = $linenr;
2160 my $ctx_skip = $realcnt;
2161
2162 while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
2163 defined $lines[$ctx_ln - 1] &&
2164 $lines[$ctx_ln - 1] =~ /^-/)) {
2165 ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
2166 $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
2167 $ctx_ln++;
2168 }
2169
2170 #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
2171 #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
2172
Max Reitza97ceca2014-11-26 17:20:24 +01002173 # The length of the "previous line" is checked against 80 because it
2174 # includes the + at the beginning of the line (if the actual line has
2175 # 79 or 80 characters, it is no longer possible to add a space and an
2176 # opening brace there)
2177 if ($#ctx == 0 && $ctx !~ /{\s*/ &&
Fam Zheng04f25622015-09-11 19:07:36 +08002178 defined($lines[$ctx_ln - 1]) && $lines[$ctx_ln - 1] =~ /^\+\s*\{/ &&
Max Reitza97ceca2014-11-26 17:20:24 +01002179 defined($lines[$ctx_ln - 2]) && length($lines[$ctx_ln - 2]) < 80) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002180 ERROR("that open brace { should be on the previous line\n" .
2181 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
2182 }
2183 if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
2184 $ctx =~ /\)\s*\;\s*$/ &&
2185 defined $lines[$ctx_ln - 1])
2186 {
2187 my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
2188 if ($nindent > $indent) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02002189 ERROR("trailing semicolon indicates no statements, indent implies otherwise\n" .
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002190 "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
2191 }
2192 }
2193 }
2194
Eric Blakef4bdc132017-12-01 17:24:33 -06002195# 'do ... while (0/false)' only makes sense in macros, without trailing ';'
2196 if ($line =~ /while\s*\((0|false)\);/) {
2197 ERROR("suspicious ; after while (0)\n" . $herecurr);
2198 }
2199
Philippe Mathieu-Daudéee0f3c02020-02-18 10:43:50 +01002200# Check superfluous trailing ';'
2201 if ($line =~ /;;$/) {
2202 ERROR("superfluous trailing semicolon\n" . $herecurr);
2203 }
2204
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002205# Check relative indent for conditionals and blocks.
2206 if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
2207 my ($s, $c) = ($stat, $cond);
2208
2209 substr($s, 0, length($c), '');
2210
2211 # Make sure we remove the line prefixes as we have
zhaolichang65fdb3c2020-09-17 15:50:23 +08002212 # none on the first line, and are going to re-add them
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002213 # where necessary.
2214 $s =~ s/\n./\n/gs;
2215
2216 # Find out how long the conditional actually is.
2217 my @newlines = ($c =~ /\n/gs);
2218 my $cond_lines = 1 + $#newlines;
2219
2220 # We want to check the first line inside the block
2221 # starting at the end of the conditional, so remove:
2222 # 1) any blank line termination
2223 # 2) any opening brace { on end of the line
2224 # 3) any do (...) {
2225 my $continuation = 0;
2226 my $check = 0;
2227 $s =~ s/^.*\bdo\b//;
Fam Zheng04f25622015-09-11 19:07:36 +08002228 $s =~ s/^\s*\{//;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002229 if ($s =~ s/^\s*\\//) {
2230 $continuation = 1;
2231 }
2232 if ($s =~ s/^\s*?\n//) {
2233 $check = 1;
2234 $cond_lines++;
2235 }
2236
2237 # Also ignore a loop construct at the end of a
2238 # preprocessor statement.
2239 if (($prevline =~ /^.\s*#\s*define\s/ ||
2240 $prevline =~ /\\\s*$/) && $continuation == 0) {
2241 $check = 0;
2242 }
2243
2244 my $cond_ptr = -1;
2245 $continuation = 0;
2246 while ($cond_ptr != $cond_lines) {
2247 $cond_ptr = $cond_lines;
2248
2249 # If we see an #else/#elif then the code
2250 # is not linear.
2251 if ($s =~ /^\s*\#\s*(?:else|elif)/) {
2252 $check = 0;
2253 }
2254
2255 # Ignore:
2256 # 1) blank lines, they should be at 0,
2257 # 2) preprocessor lines, and
2258 # 3) labels.
2259 if ($continuation ||
2260 $s =~ /^\s*?\n/ ||
2261 $s =~ /^\s*#\s*?/ ||
2262 $s =~ /^\s*$Ident\s*:/) {
2263 $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
2264 if ($s =~ s/^.*?\n//) {
2265 $cond_lines++;
2266 }
2267 }
2268 }
2269
2270 my (undef, $sindent) = line_stats("+" . $s);
2271 my $stat_real = raw_line($linenr, $cond_lines);
2272
2273 # Check if either of these lines are modified, else
2274 # this is not this patch's fault.
2275 if (!defined($stat_real) ||
2276 $stat !~ /^\+/ && $stat_real !~ /^\+/) {
2277 $check = 0;
2278 }
2279 if (defined($stat_real) && $cond_lines > 1) {
2280 $stat_real = "[...]\n$stat_real";
2281 }
2282
2283 #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";
2284
Blue Swirlb6469682011-01-20 20:58:56 +00002285 if ($check && (($sindent % 4) != 0 ||
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002286 ($sindent <= $indent && $s ne ''))) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02002287 ERROR("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002288 }
2289 }
2290
2291 # Track the 'values' across context and added lines.
2292 my $opline = $line; $opline =~ s/^./ /;
2293 my ($curr_values, $curr_vars) =
2294 annotate_values($opline . "\n", $prev_values);
2295 $curr_values = $prev_values . $curr_values;
2296 if ($dbg_values) {
2297 my $outline = $opline; $outline =~ s/\t/ /g;
2298 print "$linenr > .$outline\n";
2299 print "$linenr > $curr_values\n";
2300 print "$linenr > $curr_vars\n";
2301 }
2302 $prev_values = substr($curr_values, -1);
2303
2304#ignore lines not being added
2305 if ($line=~/^[^\+]/) {next;}
2306
2307# TEST: allow direct testing of the type matcher.
2308 if ($dbg_type) {
2309 if ($line =~ /^.\s*$Declare\s*$/) {
2310 ERROR("TEST: is type\n" . $herecurr);
2311 } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
2312 ERROR("TEST: is not type ($1 is)\n". $herecurr);
2313 }
2314 next;
2315 }
2316# TEST: allow direct testing of the attribute matcher.
2317 if ($dbg_attr) {
2318 if ($line =~ /^.\s*$Modifier\s*$/) {
2319 ERROR("TEST: is attr\n" . $herecurr);
2320 } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
2321 ERROR("TEST: is not attr ($1 is)\n". $herecurr);
2322 }
2323 next;
2324 }
2325
2326# check for initialisation to aggregates open brace on the next line
Fam Zheng04f25622015-09-11 19:07:36 +08002327 if ($line =~ /^.\s*\{/ &&
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002328 $prevline =~ /(?:^|[^=])=\s*$/) {
2329 ERROR("that open brace { should be on the previous line\n" . $hereprev);
2330 }
2331
2332#
2333# Checks which are anchored on the added line.
2334#
2335
2336# check for malformed paths in #include statements (uses RAW line)
2337 if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
2338 my $path = $1;
2339 if ($path =~ m{//}) {
2340 ERROR("malformed #include filename\n" .
2341 $herecurr);
2342 }
2343 }
2344
2345# no C99 // comments
Peter Xu8d061272019-04-26 14:27:05 +08002346 if ($line =~ m{//} &&
2347 $rawline !~ m{// SPDX-License-Identifier: }) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002348 ERROR("do not use C99 // comments\n" . $herecurr);
2349 }
2350 # Remove C99 comments.
2351 $line =~ s@//.*@@;
2352 $opline =~ s@//.*@@;
2353
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002354# check for global initialisers.
2355 if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
2356 ERROR("do not initialise globals to 0 or NULL\n" .
2357 $herecurr);
2358 }
2359# check for static initialisers.
2360 if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
2361 ERROR("do not initialise statics to 0 or NULL\n" .
2362 $herecurr);
2363 }
2364
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002365# * goes on variable not on type
2366 # (char*[ const])
2367 if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
2368 my ($from, $to) = ($1, $1);
2369
2370 # Should start with a space.
2371 $to =~ s/^(\S)/ $1/;
2372 # Should not end with a space.
2373 $to =~ s/\s+$//;
2374 # '*'s should not have spaces between.
2375 while ($to =~ s/\*\s+\*/\*\*/) {
2376 }
2377
2378 #print "from<$from> to<$to>\n";
2379 if ($from ne $to) {
2380 ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr);
2381 }
2382 } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
2383 my ($from, $to, $ident) = ($1, $1, $2);
2384
2385 # Should start with a space.
2386 $to =~ s/^(\S)/ $1/;
2387 # Should not end with a space.
2388 $to =~ s/\s+$//;
2389 # '*'s should not have spaces between.
2390 while ($to =~ s/\*\s+\*/\*\*/) {
2391 }
2392 # Modifiers should have spaces.
2393 $to =~ s/(\b$Modifier$)/$1 /;
2394
2395 #print "from<$from> to<$to> ident<$ident>\n";
2396 if ($from ne $to && $ident !~ /^$Modifier$/) {
2397 ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr);
2398 }
2399 }
2400
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002401# function brace can't be on same line, except for #defines of do while,
2402# or if closed on same line
Fam Zheng04f25622015-09-11 19:07:36 +08002403 if (($line=~/$Type\s*$Ident\(.*\).*\s\{/) and
2404 !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002405 ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
2406 }
2407
2408# open braces for enum, union and struct go on the same line.
Fam Zheng04f25622015-09-11 19:07:36 +08002409 if ($line =~ /^.\s*\{/ &&
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002410 $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
2411 ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
2412 }
2413
2414# missing space after union, struct or enum definition
2415 if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01002416 ERROR("missing space after $1 definition\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002417 }
2418
2419# check for spacing round square brackets; allowed:
2420# 1. with a type on the left -- int [] a;
2421# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
2422# 3. inside a curly brace -- = { [0...10] = 5 }
Leonid Bloch409db6e2015-10-29 11:48:37 +02002423# 4. after a comma -- [1] = 5, [2] = 6
Leonid Bloch8800cf02015-10-29 11:48:38 +02002424# 5. in a macro definition -- #define abc(x) [x] = y
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002425 while ($line =~ /(.*?\s)\[/g) {
2426 my ($where, $prefix) = ($-[1], $1);
2427 if ($prefix !~ /$Type\s+$/ &&
2428 ($where != 0 || $prefix !~ /^.\s+$/) &&
Leonid Bloch8800cf02015-10-29 11:48:38 +02002429 $prefix !~ /\#\s*define[^(]*\([^)]*\)\s+$/ &&
Heinrich Schuchardt66e9d202018-04-10 16:34:14 -07002430 $prefix !~ /[,{:]\s+$/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002431 ERROR("space prohibited before open square bracket '['\n" . $herecurr);
2432 }
2433 }
2434
2435# check for spaces between functions and their parentheses.
2436 while ($line =~ /($Ident)\s+\(/g) {
2437 my $name = $1;
2438 my $ctx_before = substr($line, 0, $-[1]);
2439 my $ctx = "$ctx_before$name";
2440
2441 # Ignore those directives where spaces _are_ permitted.
2442 if ($name =~ /^(?:
2443 if|for|while|switch|return|case|
Jeff Cody000980c2016-11-01 10:38:35 -04002444 volatile|__volatile__|coroutine_fn|
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002445 __attribute__|format|__extension__|
2446 asm|__asm__)$/x)
2447 {
2448
Tomoki Sekiyama69d5d212013-08-07 11:39:50 -04002449 # Ignore 'catch (...)' in C++
2450 } elsif ($name =~ /^catch$/ && $realfile =~ /(\.cpp|\.h)$/) {
2451
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002452 # cpp #define statements have non-optional spaces, ie
2453 # if there is a space between the name and the open
2454 # parenthesis it is simply not a parameter group.
2455 } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
2456
2457 # cpp #elif statement condition may start with a (
2458 } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
2459
2460 # If this whole things ends with a type its most
2461 # likely a typedef for a function.
2462 } elsif ($ctx =~ /$Type$/) {
2463
2464 } else {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02002465 ERROR("space prohibited between function name and open parenthesis '('\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002466 }
2467 }
2468# Check operator spacing.
Phil Dennis-Jordan3fbb78c2024-10-24 14:35:55 +02002469 if (!($line=~/\#\s*(include|import)/)) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002470 my $ops = qr{
2471 <<=|>>=|<=|>=|==|!=|
2472 \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
2473 =>|->|<<|>>|<|>|=|!|~|
2474 &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
Tomoki Sekiyama69d5d212013-08-07 11:39:50 -04002475 \?|::|:
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002476 }x;
2477 my @elements = split(/($ops|;)/, $opline);
2478 my $off = 0;
2479
2480 my $blank = copy_spacing($opline);
2481
2482 for (my $n = 0; $n < $#elements; $n += 2) {
2483 $off += length($elements[$n]);
2484
Stefan Weile7d81002011-12-10 00:19:46 +01002485 # Pick up the preceding and succeeding characters.
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002486 my $ca = substr($opline, 0, $off);
2487 my $cc = '';
2488 if (length($opline) >= ($off + length($elements[$n + 1]))) {
2489 $cc = substr($opline, $off + length($elements[$n + 1]));
2490 }
2491 my $cb = "$ca$;$cc";
2492
2493 my $a = '';
2494 $a = 'V' if ($elements[$n] ne '');
2495 $a = 'W' if ($elements[$n] =~ /\s$/);
2496 $a = 'C' if ($elements[$n] =~ /$;$/);
2497 $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
2498 $a = 'O' if ($elements[$n] eq '');
2499 $a = 'E' if ($ca =~ /^\s*$/);
2500
2501 my $op = $elements[$n + 1];
2502
2503 my $c = '';
2504 if (defined $elements[$n + 2]) {
2505 $c = 'V' if ($elements[$n + 2] ne '');
2506 $c = 'W' if ($elements[$n + 2] =~ /^\s/);
2507 $c = 'C' if ($elements[$n + 2] =~ /^$;/);
2508 $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
2509 $c = 'O' if ($elements[$n + 2] eq '');
2510 $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
2511 } else {
2512 $c = 'E';
2513 }
2514
2515 my $ctx = "${a}x${c}";
2516
2517 my $at = "(ctx:$ctx)";
2518
2519 my $ptr = substr($blank, 0, $off) . "^";
2520 my $hereptr = "$hereline$ptr\n";
2521
2522 # Pull out the value of this operator.
2523 my $op_type = substr($curr_values, $off + 1, 1);
2524
2525 # Get the full operator variant.
2526 my $opv = $op . substr($curr_vars, $off, 1);
2527
2528 # Ignore operators passed as parameters.
2529 if ($op_type ne 'V' &&
2530 $ca =~ /\s$/ && $cc =~ /^\s*,/) {
2531
2532# # Ignore comments
2533# } elsif ($op =~ /^$;+$/) {
2534
2535 # ; should have either the end of line or a space or \ after it
2536 } elsif ($op eq ';') {
2537 if ($ctx !~ /.x[WEBC]/ &&
2538 $cc !~ /^\\/ && $cc !~ /^;/) {
2539 ERROR("space required after that '$op' $at\n" . $hereptr);
2540 }
2541
2542 # // is a comment
2543 } elsif ($op eq '//') {
2544
Tomoki Sekiyama69d5d212013-08-07 11:39:50 -04002545 # Ignore : used in class declaration in C++
2546 } elsif ($opv eq ':B' && $ctx =~ /Wx[WE]/ &&
2547 $line =~ /class/ && $realfile =~ /(\.cpp|\.h)$/) {
2548
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002549 # No spaces for:
2550 # ->
2551 # : when part of a bitfield
2552 } elsif ($op eq '->' || $opv eq ':B') {
2553 if ($ctx =~ /Wx.|.xW/) {
2554 ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
2555 }
2556
2557 # , must have a space on the right.
Alexander Graf9fbe4782011-06-29 08:04:27 +02002558 # not required when having a single },{ on one line
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002559 } elsif ($op eq ',') {
Alexander Graf9fbe4782011-06-29 08:04:27 +02002560 if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/ &&
Fam Zheng04f25622015-09-11 19:07:36 +08002561 ($elements[$n] . $elements[$n + 2]) !~ " *}\\{") {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002562 ERROR("space required after that '$op' $at\n" . $hereptr);
2563 }
2564
2565 # '*' as part of a type definition -- reported already.
2566 } elsif ($opv eq '*_') {
2567 #warn "'*' is part of type\n";
2568
2569 # unary operators should have a space before and
2570 # none after. May be left adjacent to another
2571 # unary operator, or a cast
2572 } elsif ($op eq '!' || $op eq '~' ||
2573 $opv eq '*U' || $opv eq '-U' ||
2574 $opv eq '&U' || $opv eq '&&U') {
Tomoki Sekiyama69d5d212013-08-07 11:39:50 -04002575 if ($op eq '~' && $ca =~ /::$/ && $realfile =~ /(\.cpp|\.h)$/) {
2576 # '~' used as a name of Destructor
2577
2578 } elsif ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002579 ERROR("space required before that '$op' $at\n" . $hereptr);
2580 }
2581 if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
2582 # A unary '*' may be const
2583
2584 } elsif ($ctx =~ /.xW/) {
2585 ERROR("space prohibited after that '$op' $at\n" . $hereptr);
2586 }
2587
2588 # unary ++ and unary -- are allowed no space on one side.
2589 } elsif ($op eq '++' or $op eq '--') {
2590 if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
2591 ERROR("space required one side of that '$op' $at\n" . $hereptr);
2592 }
2593 if ($ctx =~ /Wx[BE]/ ||
2594 ($ctx =~ /Wx./ && $cc =~ /^;/)) {
2595 ERROR("space prohibited before that '$op' $at\n" . $hereptr);
2596 }
2597 if ($ctx =~ /ExW/) {
2598 ERROR("space prohibited after that '$op' $at\n" . $hereptr);
2599 }
2600
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002601 # A colon needs no spaces before when it is
2602 # terminating a case value or a label.
2603 } elsif ($opv eq ':C' || $opv eq ':L') {
2604 if ($ctx =~ /Wx./) {
2605 ERROR("space prohibited before that '$op' $at\n" . $hereptr);
2606 }
2607
2608 # All the others need spaces both sides.
2609 } elsif ($ctx !~ /[EWC]x[CWE]/) {
2610 my $ok = 0;
2611
Tomoki Sekiyama69d5d212013-08-07 11:39:50 -04002612 if ($realfile =~ /\.cpp|\.h$/) {
2613 # Ignore template arguments <...> in C++
2614 if (($op eq '<' || $op eq '>') && $line =~ /<.*>/) {
2615 $ok = 1;
2616 }
2617
2618 # Ignore :: in C++
2619 if ($op eq '::') {
2620 $ok = 1;
2621 }
2622 }
2623
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002624 # Ignore email addresses <foo@bar>
2625 if (($op eq '<' &&
2626 $cc =~ /^\S+\@\S+>/) ||
2627 ($op eq '>' &&
2628 $ca =~ /<\S+\@\S+$/))
2629 {
2630 $ok = 1;
2631 }
2632
2633 # Ignore ?:
2634 if (($opv eq ':O' && $ca =~ /\?$/) ||
2635 ($op eq '?' && $cc =~ /^:/)) {
2636 $ok = 1;
2637 }
2638
2639 if ($ok == 0) {
2640 ERROR("spaces required around that '$op' $at\n" . $hereptr);
2641 }
2642 }
2643 $off += length($elements[$n + 1]);
2644 }
2645 }
2646
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002647#need space before brace following if, while, etc
Fam Zheng04f25622015-09-11 19:07:36 +08002648 if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
2649 $line =~ /do\{/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002650 ERROR("space required before the open brace '{'\n" . $herecurr);
2651 }
2652
2653# closing brace should have a space following it when it has anything
2654# on the line
2655 if ($line =~ /}(?!(?:,|;|\)))\S/) {
2656 ERROR("space required after that close brace '}'\n" . $herecurr);
2657 }
2658
2659# check spacing on square brackets
2660 if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
2661 ERROR("space prohibited after that open square bracket '['\n" . $herecurr);
2662 }
2663 if ($line =~ /\s\]/) {
2664 ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
2665 }
2666
2667# check spacing on parentheses
2668 if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
2669 $line !~ /for\s*\(\s+;/) {
2670 ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
2671 }
2672 if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
2673 $line !~ /for\s*\(.*;\s+\)/ &&
2674 $line !~ /:\s+\)/) {
2675 ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
2676 }
2677
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002678# Return is not a function.
2679 if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
2680 my $spacing = $1;
2681 my $value = $2;
2682
2683 # Flatten any parentheses
2684 $value =~ s/\(/ \(/g;
2685 $value =~ s/\)/\) /g;
2686 while ($value =~ s/\[[^\{\}]*\]/1/ ||
2687 $value !~ /(?:$Ident|-?$Constant)\s*
2688 $Compare\s*
2689 (?:$Ident|-?$Constant)/x &&
2690 $value =~ s/\([^\(\)]*\)/1/) {
2691 }
2692#print "value<$value>\n";
Paolo Bonzinic20b1392019-06-21 13:28:54 +02002693 if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/ &&
2694 $line =~ /;$/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002695 ERROR("return is not a function, parentheses are not required\n" . $herecurr);
2696
2697 } elsif ($spacing !~ /\s+/) {
2698 ERROR("space required before the open parenthesis '('\n" . $herecurr);
2699 }
2700 }
2701# Return of what appears to be an errno should normally be -'ve
2702 if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
2703 my $name = $1;
2704 if ($name ne 'EOF' && $name ne 'ERROR') {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02002705 ERROR("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002706 }
2707 }
2708
Paolo Bonzini50db69a2018-12-06 12:01:40 +01002709 if ($line =~ /^.\s*(Q(?:S?LIST|SIMPLEQ|TAILQ)_HEAD)\s*\(\s*[^,]/ &&
2710 $line !~ /^.typedef/) {
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01002711 ERROR("named $1 should be typedefed separately\n" . $herecurr);
Paolo Bonzini50db69a2018-12-06 12:01:40 +01002712 }
2713
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002714# Need a space before open parenthesis after if, while etc
2715 if ($line=~/\b(if|while|for|switch)\(/) {
2716 ERROR("space required before the open parenthesis '('\n" . $herecurr);
2717 }
2718
2719# Check for illegal assignment in if conditional -- and check for trailing
2720# statements after the conditional.
2721 if ($line =~ /do\s*(?!{)/) {
2722 my ($stat_next) = ctx_statement_block($line_nr_next,
2723 $remain_next, $off_next);
2724 $stat_next =~ s/\n./\n /g;
2725 ##print "stat<$stat> stat_next<$stat_next>\n";
2726
2727 if ($stat_next =~ /^\s*while\b/) {
2728 # If the statement carries leading newlines,
2729 # then count those as offsets.
2730 my ($whitespace) =
2731 ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
2732 my $offset =
2733 statement_rawlines($whitespace) - 1;
2734
2735 $suppress_whiletrailers{$line_nr_next +
2736 $offset} = 1;
2737 }
2738 }
2739 if (!defined $suppress_whiletrailers{$linenr} &&
2740 $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
2741 my ($s, $c) = ($stat, $cond);
2742
2743 if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
2744 ERROR("do not use assignment in if condition\n" . $herecurr);
2745 }
2746
2747 # Find out what is on the end of the line after the
2748 # conditional.
2749 substr($s, 0, length($c), '');
2750 $s =~ s/\n.*//g;
2751 $s =~ s/$;//g; # Remove any comments
2752 if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
2753 $c !~ /}\s*while\s*/)
2754 {
2755 # Find out how long the conditional actually is.
2756 my @newlines = ($c =~ /\n/gs);
2757 my $cond_lines = 1 + $#newlines;
2758 my $stat_real = '';
2759
2760 $stat_real = raw_line($linenr, $cond_lines)
2761 . "\n" if ($cond_lines);
2762 if (defined($stat_real) && $cond_lines > 1) {
2763 $stat_real = "[...]\n$stat_real";
2764 }
2765
2766 ERROR("trailing statements should be on next line\n" . $herecurr . $stat_real);
2767 }
2768 }
2769
2770# Check for bitwise tests written as boolean
2771 if ($line =~ /
2772 (?:
2773 (?:\[|\(|\&\&|\|\|)
2774 \s*0[xX][0-9]+\s*
2775 (?:\&\&|\|\|)
2776 |
2777 (?:\&\&|\|\|)
2778 \s*0[xX][0-9]+\s*
2779 (?:\&\&|\|\||\)|\])
2780 )/x)
2781 {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02002782 ERROR("boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002783 }
2784
2785# if and else should not have general statements after it
2786 if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
2787 my $s = $1;
2788 $s =~ s/$;//g; # Remove any comments
2789 if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
2790 ERROR("trailing statements should be on next line\n" . $herecurr);
2791 }
2792 }
2793# if should not continue a brace
2794 if ($line =~ /}\s*if\b/) {
2795 ERROR("trailing statements should be on next line\n" .
2796 $herecurr);
2797 }
2798# case and default should not have general statements after them
2799 if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
2800 $line !~ /\G(?:
2801 (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
2802 \s*return\s+
2803 )/xg)
2804 {
2805 ERROR("trailing statements should be on next line\n" . $herecurr);
2806 }
2807
2808 # Check for }<nl>else {, these must be at the same
2809 # indent level to be relevant to each other.
2810 if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
2811 $previndent == $indent) {
2812 ERROR("else should follow close brace '}'\n" . $hereprev);
2813 }
2814
2815 if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
2816 $previndent == $indent) {
2817 my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
2818
2819 # Find out what is on the end of the line after the
2820 # conditional.
2821 substr($s, 0, length($c), '');
2822 $s =~ s/\n.*//g;
2823
2824 if ($s =~ /^\s*;/) {
2825 ERROR("while should follow close brace '}'\n" . $hereprev);
2826 }
2827 }
2828
2829#studly caps, commented out until figure out how to distinguish between use of existing and adding new
2830# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
2831# print "No studly caps, use _\n";
2832# print "$herecurr";
2833# $clean = 0;
2834# }
2835
2836#no spaces allowed after \ in define
2837 if ($line=~/\#\s*define.*\\\s$/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02002838 ERROR("Whitespace after \\ makes next lines useless\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002839 }
2840
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002841# multi-statement macros should be enclosed in a do while loop, grab the
2842# first statement and ensure its the whole macro if its not enclosed
2843# in a known good container
2844 if ($realfile !~ m@/vmlinux.lds.h$@ &&
2845 $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
2846 my $ln = $linenr;
2847 my $cnt = $realcnt;
2848 my ($off, $dstat, $dcond, $rest);
2849 my $ctx = '';
2850
2851 my $args = defined($1);
2852
2853 # Find the end of the macro and limit our statement
2854 # search to that.
2855 while ($cnt > 0 && defined $lines[$ln - 1] &&
2856 $lines[$ln - 1] =~ /^(?:-|..*\\$)/)
2857 {
2858 $ctx .= $rawlines[$ln - 1] . "\n";
2859 $cnt-- if ($lines[$ln - 1] !~ /^-/);
2860 $ln++;
2861 }
2862 $ctx .= $rawlines[$ln - 1];
2863
2864 ($dstat, $dcond, $ln, $cnt, $off) =
2865 ctx_statement_block($linenr, $ln - $linenr + 1, 0);
2866 #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
2867 #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
2868
2869 # Extract the remainder of the define (if any) and
2870 # rip off surrounding spaces, and trailing \'s.
2871 $rest = '';
2872 while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) {
2873 #print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n";
2874 if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
2875 $rest .= substr($lines[$ln - 1], $off) . "\n";
2876 $cnt--;
2877 }
2878 $ln++;
2879 $off = 0;
2880 }
2881 $rest =~ s/\\\n.//g;
2882 $rest =~ s/^\s*//s;
2883 $rest =~ s/\s*$//s;
2884
2885 # Clean up the original statement.
2886 if ($args) {
2887 substr($dstat, 0, length($dcond), '');
2888 } else {
2889 $dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
2890 }
2891 $dstat =~ s/$;//g;
2892 $dstat =~ s/\\\n.//g;
2893 $dstat =~ s/^\s*//s;
2894 $dstat =~ s/\s*$//s;
2895
2896 # Flatten any parentheses and braces
2897 while ($dstat =~ s/\([^\(\)]*\)/1/ ||
2898 $dstat =~ s/\{[^\{\}]*\}/1/ ||
2899 $dstat =~ s/\[[^\{\}]*\]/1/)
2900 {
2901 }
2902
2903 my $exceptions = qr{
2904 $Declare|
2905 module_param_named|
2906 MODULE_PARAM_DESC|
2907 DECLARE_PER_CPU|
2908 DEFINE_PER_CPU|
2909 __typeof__\(|
2910 union|
2911 struct|
2912 \.$Ident\s*=\s*|
2913 ^\"|\"$
2914 }x;
2915 #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
2916 if ($rest ne '' && $rest ne ',') {
2917 if ($rest !~ /while\s*\(/ &&
2918 $dstat !~ /$exceptions/)
2919 {
2920 ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
2921 }
2922
2923 } elsif ($ctx !~ /;/) {
2924 if ($dstat ne '' &&
2925 $dstat !~ /^(?:$Ident|-?$Constant)$/ &&
2926 $dstat !~ /$exceptions/ &&
2927 $dstat !~ /^\.$Ident\s*=/ &&
2928 $dstat =~ /$Operators/)
2929 {
2930 ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
2931 }
2932 }
2933 }
2934
Su Hang2b9aef62018-03-06 15:04:50 +08002935# check for missing bracing around if etc
2936 if ($line =~ /(^.*)\b(?:if|while|for)\b/ &&
2937 $line !~ /\#\s*if/) {
Su Hang053e45d2018-03-26 10:06:22 +08002938 my $allowed = 0;
2939
2940 # Check the pre-context.
2941 if ($line =~ /(\}.*?)$/) {
2942 my $pre = $1;
2943
2944 if ($line !~ /else/) {
2945 print "APW: ALLOWED: pre<$pre> line<$line>\n"
2946 if $dbg_adv_apw;
2947 $allowed = 1;
2948 }
2949 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002950 my ($level, $endln, @chunks) =
2951 ctx_statement_full($linenr, $realcnt, 1);
Don Slutz69402a62012-09-02 19:22:37 -04002952 if ($dbg_adv_apw) {
2953 print "APW: chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
2954 print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n"
2955 if $#chunks >= 1;
2956 }
Blue Swirlb6469682011-01-20 20:58:56 +00002957 if ($#chunks >= 0 && $level == 0) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002958 my $seen = 0;
2959 my $herectx = $here . "\n";
2960 my $ln = $linenr - 1;
2961 for my $chunk (@chunks) {
2962 my ($cond, $block) = @{$chunk};
2963
2964 # If the condition carries leading newlines, then count those as offsets.
2965 my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
2966 my $offset = statement_rawlines($whitespace) - 1;
2967
2968 #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
2969
2970 # We have looked at and allowed this specific line.
2971 $suppress_ifbraces{$ln + $offset} = 1;
2972
2973 $herectx .= "$rawlines[$ln + $offset]\n[...]\n";
2974 $ln += statement_rawlines($block) - 1;
2975
2976 substr($block, 0, length($cond), '');
2977
Max Reitza97ceca2014-11-26 17:20:24 +01002978 my $spaced_block = $block;
2979 $spaced_block =~ s/\n\+/ /g;
2980
Fam Zheng04f25622015-09-11 19:07:36 +08002981 $seen++ if ($spaced_block =~ /^\s*\{/);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002982
Don Slutz69402a62012-09-02 19:22:37 -04002983 print "APW: cond<$cond> block<$block> allowed<$allowed>\n"
2984 if $dbg_adv_apw;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002985 if (statement_lines($cond) > 1) {
Don Slutz69402a62012-09-02 19:22:37 -04002986 print "APW: ALLOWED: cond<$cond>\n"
2987 if $dbg_adv_apw;
2988 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002989 }
2990 if ($block =~/\b(?:if|for|while)\b/) {
Don Slutz69402a62012-09-02 19:22:37 -04002991 print "APW: ALLOWED: block<$block>\n"
2992 if $dbg_adv_apw;
2993 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002994 }
2995 if (statement_block_size($block) > 1) {
Don Slutz69402a62012-09-02 19:22:37 -04002996 print "APW: ALLOWED: lines block<$block>\n"
2997 if $dbg_adv_apw;
2998 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00002999 }
3000 }
Su Hang053e45d2018-03-26 10:06:22 +08003001 if ($seen != ($#chunks + 1) && !$allowed) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003002 ERROR("braces {} are necessary for all arms of this statement\n" . $herectx);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003003 }
3004 }
3005 }
3006 if (!defined $suppress_ifbraces{$linenr - 1} &&
Jan Kiszka789f88d2011-01-21 18:19:40 +01003007 $line =~ /\b(if|while|for|else)\b/ &&
Blue Swirld0510af2011-07-15 20:09:10 +00003008 $line !~ /\#\s*if/ &&
Jan Kiszka789f88d2011-01-21 18:19:40 +01003009 $line !~ /\#\s*else/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003010 my $allowed = 0;
3011
Don Slutzdfe70532012-09-02 19:22:38 -04003012 # Check the pre-context.
3013 if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
3014 my $pre = $1;
3015
3016 if ($line !~ /else/) {
3017 print "APW: ALLOWED: pre<$pre> line<$line>\n"
3018 if $dbg_adv_apw;
3019 $allowed = 1;
3020 }
3021 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003022
3023 my ($level, $endln, @chunks) =
3024 ctx_statement_full($linenr, $realcnt, $-[0]);
3025
3026 # Check the condition.
3027 my ($cond, $block) = @{$chunks[0]};
Don Slutz54243022012-09-02 19:22:36 -04003028 print "CHECKING<$linenr> cond<$cond> block<$block>\n"
3029 if $dbg_adv_checking;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003030 if (defined $cond) {
3031 substr($block, 0, length($cond), '');
3032 }
3033 if (statement_lines($cond) > 1) {
Don Slutz69402a62012-09-02 19:22:37 -04003034 print "APW: ALLOWED: cond<$cond>\n"
3035 if $dbg_adv_apw;
3036 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003037 }
3038 if ($block =~/\b(?:if|for|while)\b/) {
Don Slutz69402a62012-09-02 19:22:37 -04003039 print "APW: ALLOWED: block<$block>\n"
3040 if $dbg_adv_apw;
3041 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003042 }
3043 if (statement_block_size($block) > 1) {
Don Slutz69402a62012-09-02 19:22:37 -04003044 print "APW: ALLOWED: lines block<$block>\n"
3045 if $dbg_adv_apw;
3046 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003047 }
3048 # Check the post-context.
3049 if (defined $chunks[1]) {
3050 my ($cond, $block) = @{$chunks[1]};
3051 if (defined $cond) {
3052 substr($block, 0, length($cond), '');
3053 }
3054 if ($block =~ /^\s*\{/) {
Don Slutz69402a62012-09-02 19:22:37 -04003055 print "APW: ALLOWED: chunk-1 block<$block>\n"
3056 if $dbg_adv_apw;
3057 $allowed = 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003058 }
3059 }
Don Slutza99ac042012-09-02 19:22:35 -04003060 print "DCS: level=$level block<$block> allowed=$allowed\n"
3061 if $dbg_adv_dcs;
Blue Swirlb6469682011-01-20 20:58:56 +00003062 if ($level == 0 && $block !~ /^\s*\{/ && !$allowed) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003063 my $herectx = $here . "\n";;
3064 my $cnt = statement_rawlines($block);
3065
3066 for (my $n = 0; $n < $cnt; $n++) {
3067 $herectx .= raw_line($linenr, $n) . "\n";;
3068 }
3069
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003070 ERROR("braces {} are necessary even for single statement blocks\n" . $herectx);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003071 }
3072 }
3073
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003074# no volatiles please
3075 my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
Marc-André Lureau6b012d22017-12-15 19:18:10 +01003076 if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/ &&
3077 $line !~ /sig_atomic_t/ &&
3078 !ctx_has_comment($first_line, $linenr)) {
3079 my $msg = "Use of volatile is usually wrong, please add a comment\n" . $herecurr;
3080 ERROR($msg);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003081 }
3082
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003083# warn about #if 0
3084 if ($line =~ /^.\s*\#\s*if\s+0\b/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003085 ERROR("if this code is redundant consider removing it\n" .
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003086 $herecurr);
3087 }
3088
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003089# check for needless g_free() checks
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003090 if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
3091 my $expr = $1;
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003092 if ($line =~ /\bg_free\(\Q$expr\E\);/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003093 ERROR("g_free(NULL) is safe this check is probably not required\n" . $hereprev);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003094 }
3095 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003096
3097# warn about #ifdefs in C files
3098# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
3099# print "#ifdef in C files should be avoided\n";
3100# print "$herecurr";
3101# $clean = 0;
3102# }
3103
3104# warn about spacing in #ifdefs
3105 if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
3106 ERROR("exactly one space required after that #$1\n" . $herecurr);
3107 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003108# check for memory barriers without a comment.
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003109 if ($line =~ /\b(smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003110 if (!ctx_has_comment($first_line, $linenr)) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003111 ERROR("memory barrier without comment\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003112 }
3113 }
3114# check of hardware specific defines
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003115# we have e.g. CONFIG_LINUX and CONFIG_WIN32 for common cases
3116# where they might be necessary.
3117 if ($line =~ m@^.\s*\#\s*if.*\b__@) {
Paolo Bonzini63ae8b92016-09-21 18:49:07 +02003118 WARN("architecture specific defines should be avoided\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003119 }
3120
3121# Check that the storage class is at the beginning of a declaration
3122 if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003123 ERROR("storage class should be at the beginning of the declaration\n" . $herecurr)
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003124 }
3125
3126# check the location of the inline attribute, that it is between
3127# storage class and type.
3128 if ($line =~ /\b$Type\s+$Inline\b/ ||
3129 $line =~ /\b$Inline\s+$Storage\b/) {
3130 ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
3131 }
3132
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003133# check for sizeof(&)
3134 if ($line =~ /\bsizeof\s*\(\s*\&/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003135 ERROR("sizeof(& should be avoided\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003136 }
3137
3138# check for new externs in .c files.
3139 if ($realfile =~ /\.c$/ && defined $stat &&
3140 $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
3141 {
3142 my $function_name = $1;
3143 my $paren_space = $2;
3144
3145 my $s = $stat;
3146 if (defined $cond) {
3147 substr($s, 0, length($cond), '');
3148 }
3149 if ($s =~ /^\s*;/ &&
3150 $function_name ne 'uninitialized_var')
3151 {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003152 ERROR("externs should be avoided in .c files\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003153 }
3154
3155 if ($paren_space =~ /\n/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003156 ERROR("arguments for function declarations should follow identifier\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003157 }
3158
3159 } elsif ($realfile =~ /\.c$/ && defined $stat &&
3160 $stat =~ /^.\s*extern\s+/)
3161 {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003162 ERROR("externs should be avoided in .c files\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003163 }
3164
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003165# check for pointless casting of g_malloc return
Paolo Bonzinidfdb4f32022-04-06 14:27:52 +02003166 if ($line =~ /\*\s*\)\s*g_(try|)(m|re)alloc(0?)(_n)?\b/) {
3167 if ($2 eq 'm') {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003168 ERROR("unnecessary cast may hide bugs, use g_$1new$3 instead\n" . $herecurr);
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003169 } else {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003170 ERROR("unnecessary cast may hide bugs, use g_$1renew$3 instead\n" . $herecurr);
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003171 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003172 }
3173
3174# check for gcc specific __FUNCTION__
3175 if ($line =~ /__FUNCTION__/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003176 ERROR("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003177 }
3178
Julia Suvorovafb8446d2018-03-02 13:43:19 +03003179# recommend g_path_get_* over g_strdup(basename/dirname(...))
3180 if ($line =~ /\bg_strdup\s*\(\s*(basename|dirname)\s*\(/) {
3181 WARN("consider using g_path_get_$1() in preference to g_strdup($1())\n" . $herecurr);
3182 }
3183
Philippe Mathieu-Daudéce2ff9c2021-09-03 19:45:10 +02003184# enforce g_memdup2() over g_memdup()
3185 if ($line =~ /\bg_memdup\s*\(/) {
3186 ERROR("use g_memdup2() instead of unsafe g_memdup()\n" . $herecurr);
3187 }
3188
Paolo Bonzini5e43efb2015-09-16 18:35:09 +02003189# recommend qemu_strto* over strto* for numeric conversions
Eric Blake01fb8e12016-06-09 20:48:07 -06003190 if ($line =~ /\b(strto[^kd].*?)\s*\(/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003191 ERROR("consider using qemu_$1 in preference to $1\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003192 }
Paolo Bonzinie8c20912017-07-04 11:26:37 +02003193# recommend sigaction over signal for portability, when establishing a handler
3194 if ($line =~ /\bsignal\s*\(/ && !($line =~ /SIG_(?:IGN|DFL)/)) {
3195 ERROR("use sigaction to establish signal handlers; signal is not portable\n" . $herecurr);
3196 }
Alexander Bulekovef56ffb2023-04-27 17:10:08 -04003197# recommend qemu_bh_new_guarded instead of qemu_bh_new
3198 if ($realfile =~ /.*\/hw\/.*/ && $line =~ /\bqemu_bh_new\s*\(/) {
3199 ERROR("use qemu_bh_new_guarded() instead of qemu_bh_new() to avoid reentrancy problems\n" . $herecurr);
3200 }
3201# recommend aio_bh_new_guarded instead of aio_bh_new
3202 if ($realfile =~ /.*\/hw\/.*/ && $line =~ /\baio_bh_new\s*\(/) {
3203 ERROR("use aio_bh_new_guarded() instead of aio_bh_new() to avoid reentrancy problems\n" . $herecurr);
3204 }
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003205# check for module_init(), use category-specific init macros explicitly please
3206 if ($line =~ /^module_init\s*\(/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003207 ERROR("please use block_init(), type_init() etc. instead of module_init()\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003208 }
3209# check for various ops structs, ensure they are const.
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003210 my $struct_ops = qr{AIOCBInfo|
3211 BdrvActionOps|
3212 BlockDevOps|
3213 BlockJobDriver|
3214 DisplayChangeListenerOps|
3215 GraphicHwOps|
3216 IDEDMAOps|
3217 KVMCapabilityInfo|
3218 MemoryRegionIOMMUOps|
3219 MemoryRegionOps|
3220 MemoryRegionPortio|
3221 QEMUFileOps|
3222 SCSIBusInfo|
3223 SCSIReqOps|
3224 Spice[A-Z][a-zA-Z0-9]*Interface|
Bernhard Beschow9a86e022022-01-17 15:58:05 +01003225 TypeInfo|
Paolo Bonzini71c47b02015-08-16 23:15:46 +02003226 USBDesc[A-Z][a-zA-Z0-9]*|
3227 VhostOps|
3228 VMStateDescription|
3229 VMStateInfo}x;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003230 if ($line !~ /\bconst\b/ &&
Paolo Bonzinie20e7182016-10-14 10:45:45 +02003231 $line =~ /\b($struct_ops)\b.*=/) {
3232 ERROR("initializer for struct $1 should normally be const\n" .
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003233 $herecurr);
3234 }
3235
Dov Murikbfac6d12020-09-14 17:26:23 +00003236# format strings checks
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003237 my $string;
3238 while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
3239 $string = substr($rawline, $-[1], $+[1] - $-[1]);
3240 $string =~ s/%%/__/g;
Dov Murikbfac6d12020-09-14 17:26:23 +00003241 # check for %L{u,d,i} in strings
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003242 if ($string =~ /(?<!%)%L[udi]/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003243 ERROR("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
Dov Murikbfac6d12020-09-14 17:26:23 +00003244 }
3245 # check for %# or %0# in printf-style format strings
3246 if ($string =~ /(?<!%)%0?#/) {
3247 ERROR("Don't use '#' flag of printf format " .
3248 "('%#') in format strings, use '0x' " .
3249 "prefix instead\n" . $herecurr);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003250 }
3251 }
3252
Stefan Weil9964d8f2012-06-17 06:57:41 +02003253# QEMU specific tests
3254 if ($rawline =~ /\b(?:Qemu|QEmu)\b/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003255 ERROR("use QEMU instead of Qemu or QEmu\n" . $herecurr);
Stefan Weil9964d8f2012-06-17 06:57:41 +02003256 }
Stefan Hajnoczi8b6ee9a2015-03-23 15:29:31 +00003257
Jason J. Herne5d596c22015-12-11 13:30:42 -05003258# Qemu error function tests
3259
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01003260 # Find newlines in error messages
3261 my $qemu_error_funcs = qr{error_setg|
3262 error_setg_errno|
3263 error_setg_win32|
3264 error_setg_file_open|
3265 error_set|
3266 error_prepend|
3267 warn_reportf_err|
3268 error_reportf_err|
3269 error_vreport|
3270 warn_vreport|
3271 info_vreport|
3272 error_report|
3273 warn_report|
3274 info_report|
3275 g_test_message}x;
Jason J. Herne5d596c22015-12-11 13:30:42 -05003276
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01003277 if ($rawline =~ /\b(?:$qemu_error_funcs)\s*\(.*\".*\\n/) {
Paolo Bonzinic2df8782016-08-09 17:47:43 +02003278 ERROR("Error messages should not contain newlines\n" . $herecurr);
Jason J. Herne5d596c22015-12-11 13:30:42 -05003279 }
Daniel P. Berrangé619bf372025-05-12 18:11:58 +01003280
3281 # Continue checking for error messages that contains newlines.
3282 # This check handles cases where string literals are spread
3283 # over multiple lines.
3284 # Example:
3285 # error_report("Error msg line #1"
3286 # "Error msg line #2\n");
3287 my $quoted_newline_regex = qr{\+\s*\".*\\n.*\"};
3288 my $continued_str_literal = qr{\+\s*\".*\"};
3289
3290 if ($rawline =~ /$quoted_newline_regex/) {
3291 # Backtrack to first line that does not contain only
3292 # a quoted literal and assume that it is the start
3293 # of the statement.
3294 my $i = $linenr - 2;
3295
3296 while (($i >= 0) & $rawlines[$i] =~ /$continued_str_literal/) {
3297 $i--;
3298 }
3299
3300 if ($rawlines[$i] =~ /\b(?:$qemu_error_funcs)\s*\(/) {
3301 ERROR("Error messages should not contain newlines\n" . $herecurr);
3302 }
3303 }
Jason J. Herne5d596c22015-12-11 13:30:42 -05003304
Paolo Bonzini3f822cf2016-07-21 11:03:11 +02003305# check for non-portable libc calls that have portable alternatives in QEMU
Stefan Hajnoczi8b6ee9a2015-03-23 15:29:31 +00003306 if ($line =~ /\bffs\(/) {
3307 ERROR("use ctz32() instead of ffs()\n" . $herecurr);
3308 }
3309 if ($line =~ /\bffsl\(/) {
3310 ERROR("use ctz32() or ctz64() instead of ffsl()\n" . $herecurr);
3311 }
3312 if ($line =~ /\bffsll\(/) {
3313 ERROR("use ctz64() instead of ffsll()\n" . $herecurr);
3314 }
Paolo Bonzini3f822cf2016-07-21 11:03:11 +02003315 if ($line =~ /\bbzero\(/) {
3316 ERROR("use memset() instead of bzero()\n" . $herecurr);
3317 }
Wei Yange31db8a2019-10-17 08:46:33 +08003318 if ($line =~ /\bgetpagesize\(\)/) {
Marc-André Lureau8e3b0cb2022-03-23 19:57:22 +04003319 ERROR("use qemu_real_host_page_size() instead of getpagesize()\n" . $herecurr);
Wei Yange31db8a2019-10-17 08:46:33 +08003320 }
3321 if ($line =~ /\bsysconf\(_SC_PAGESIZE\)/) {
Marc-André Lureau8e3b0cb2022-03-23 19:57:22 +04003322 ERROR("use qemu_real_host_page_size() instead of sysconf(_SC_PAGESIZE)\n" . $herecurr);
Wei Yange31db8a2019-10-17 08:46:33 +08003323 }
Philippe Mathieu-Daudé837cd582023-02-22 00:00:42 +01003324 if ($line =~ /\b(g_)?assert\(0\)/) {
3325 ERROR("use g_assert_not_reached() instead of assert(0)\n" . $herecurr);
3326 }
Pierrick Bouvier2540a552024-09-18 21:46:41 -07003327 if ($line =~ /\b(g_)?assert\(false\)/) {
3328 ERROR("use g_assert_not_reached() instead of assert(false)\n" .
3329 $herecurr);
3330 }
Daniel Henrique Barbozace1992d2024-04-24 17:24:25 -03003331 if ($line =~ /\bstrerrorname_np\(/) {
3332 ERROR("use strerror() instead of strerrorname_np()\n" . $herecurr);
3333 }
Dr. David Alan Gilbert6e938952017-04-27 17:55:26 +01003334 my $non_exit_glib_asserts = qr{g_assert_cmpstr|
3335 g_assert_cmpint|
3336 g_assert_cmpuint|
3337 g_assert_cmphex|
3338 g_assert_cmpfloat|
3339 g_assert_true|
3340 g_assert_false|
3341 g_assert_nonnull|
3342 g_assert_null|
3343 g_assert_no_error|
3344 g_assert_error|
3345 g_test_assert_expected_messages|
3346 g_test_trap_assert_passed|
3347 g_test_trap_assert_stdout|
3348 g_test_trap_assert_stdout_unmatched|
3349 g_test_trap_assert_stderr|
3350 g_test_trap_assert_stderr_unmatched}x;
3351 if ($realfile !~ /^tests\// &&
3352 $line =~ /\b(?:$non_exit_glib_asserts)\(/) {
3353 ERROR("Use g_assert or g_assert_not_reached\n". $herecurr);
3354 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003355 }
3356
Daniel P. Berrangé25374ba2025-05-12 16:57:38 +01003357 if (defined $fileinfo) {
3358 process_end_of_file($fileinfo);
3359 }
3360 process_file_list(@fileinfolist);
3361
Paolo Bonzinifd9c0cf2018-11-29 09:31:41 +01003362 if ($is_patch && $chk_signoff && $signoff == 0) {
3363 ERROR("Missing Signed-off-by: line(s)\n");
3364 }
3365
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003366 # If we have no input at all, then there is nothing to report on
3367 # so just keep quiet.
3368 if ($#rawlines == -1) {
Paolo Bonzini1ff7ebf2018-11-29 09:30:59 +01003369 return 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003370 }
3371
3372 # In mailback mode only produce a report in the negative, for
3373 # things that appear to be patches.
3374 if ($mailback && ($clean == 1 || !$is_patch)) {
Paolo Bonzini1ff7ebf2018-11-29 09:30:59 +01003375 return 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003376 }
3377
3378 # This is not a patch, and we are are in 'no-patch' mode so
3379 # just keep quiet.
3380 if (!$chk_patch && !$is_patch) {
Paolo Bonzini1ff7ebf2018-11-29 09:30:59 +01003381 return 1;
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003382 }
3383
Stefano Garzarellafb4176d2020-09-17 19:02:12 +02003384 if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003385 ERROR("Does not appear to be a unified-diff format patch\n");
3386 }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003387
3388 print report_dump();
3389 if ($summary && !($clean == 1 && $quiet == 1)) {
3390 print "$filename " if ($summary_file);
3391 print "total: $cnt_error errors, $cnt_warn warnings, " .
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003392 "$cnt_lines lines checked\n";
3393 print "\n" if ($quiet == 0);
3394 }
3395
3396 if ($quiet == 0) {
3397 # If there were whitespace errors which cleanpatch can fix
3398 # then suggest that.
Blue Swirlb6469682011-01-20 20:58:56 +00003399# if ($rpt_cleaners) {
3400# print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
3401# print " scripts/cleanfile\n\n";
3402# }
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003403 }
3404
3405 if ($clean == 1 && $quiet == 0) {
3406 print "$vname has no obvious style problems and is ready for submission.\n"
3407 }
3408 if ($clean == 0 && $quiet == 0) {
3409 print "$vname has style problems, please review. If any of these errors\n";
3410 print "are false positives report them to the maintainer, see\n";
3411 print "CHECKPATCH in MAINTAINERS.\n";
3412 }
3413
Paolo Bonzini141de882016-08-09 17:47:44 +02003414 return ($no_warnings ? $clean : $cnt_error == 0);
Blue Swirl1ec3f6f2011-01-20 20:54:26 +00003415}