]> git.ipfire.org Git - thirdparty/u-boot.git/blobdiff - scripts/checkpatch.pl
Merge tag 'v2024.01-rc3' into next
[thirdparty/u-boot.git] / scripts / checkpatch.pl
index cf59e2bb7059370e8f4e4caeb0bb132356fd280d..b8eb57f38c74ae2feae98f9021d2c408ab579bbb 100755 (executable)
@@ -63,6 +63,7 @@ my $min_conf_desc_length = 4;
 my $spelling_file = "$D/spelling.txt";
 my $codespell = 0;
 my $codespellfile = "/usr/share/codespell/dictionary.txt";
+my $user_codespellfile = "";
 my $conststructsfile = "$D/const_structs.checkpatch";
 my $u_boot = 0;
 my $docsfile = "$D/../doc/develop/checkpatch.rst";
@@ -131,7 +132,7 @@ Options:
   --ignore-perl-version      override checking of perl version.  expect
                              runtime errors.
   --codespell                Use the codespell dictionary for spelling/typos
-                             (default:/usr/share/codespell/dictionary.txt)
+                             (default:$codespellfile)
   --codespellfile            Use this codespell dictionary
   --typedefsfile             Read additional types from this file
   --color[=WHEN]             Use colors 'always', 'never', or only when output
@@ -319,7 +320,7 @@ GetOptions(
        'debug=s'       => \%debug,
        'test-only=s'   => \$tst_only,
        'codespell!'    => \$codespell,
-       'codespellfile=s'       => \$codespellfile,
+       'codespellfile=s'       => \$user_codespellfile,
        'typedefsfile=s'        => \$typedefsfile,
        'u-boot'        => \$u_boot,
        'color=s'       => \$color,
@@ -328,9 +329,32 @@ GetOptions(
        'kconfig-prefix=s'      => \${CONFIG_},
        'h|help'        => \$help,
        'version'       => \$help
-) or help(1);
+) or $help = 2;
+
+if ($user_codespellfile) {
+       # Use the user provided codespell file unconditionally
+       $codespellfile = $user_codespellfile;
+} elsif (!(-f $codespellfile)) {
+       # If /usr/share/codespell/dictionary.txt is not present, try to find it
+       # under codespell's install directory: <codespell_root>/data/dictionary.txt
+       if (($codespell || $help) && which("codespell") ne "" && which("python") ne "") {
+               my $python_codespell_dict = << "EOF";
+
+import os.path as op
+import codespell_lib
+codespell_dir = op.dirname(codespell_lib.__file__)
+codespell_file = op.join(codespell_dir, 'data', 'dictionary.txt')
+print(codespell_file, end='')
+EOF
+
+               my $codespell_dict = `python -c "$python_codespell_dict" 2> /dev/null`;
+               $codespellfile = $codespell_dict if (-f $codespell_dict);
+       }
+}
 
-help(0) if ($help);
+# $help is 1 if either -h, --help or --version is passed as option - exitcode: 0
+# $help is 2 if invalid option is passed - exitcode: 1
+help($help - 1) if ($help);
 
 die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
 die "$P: --verbose cannot be used with --terse\n" if ($verbose && $terse);
@@ -492,7 +516,8 @@ our $Attribute      = qr{
                        ____cacheline_aligned|
                        ____cacheline_aligned_in_smp|
                        ____cacheline_internodealigned_in_smp|
-                       __weak
+                       __weak|
+                       __alloc_size\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\)
                  }x;
 our $Modifier;
 our $Inline    = qr{inline|__always_inline|noinline|__inline|__inline__};
@@ -504,7 +529,7 @@ our $Binary = qr{(?i)0b[01]+$Int_type?};
 our $Hex       = qr{(?i)0x[0-9a-f]+$Int_type?};
 our $Int       = qr{[0-9]+$Int_type?};
 our $Octal     = qr{0[0-7]+$Int_type?};
-our $String    = qr{"[X\t]*"};
+our $String    = qr{(?:\b[Lu])?"[X\t]*"};
 our $Float_hex = qr{(?i)0x[0-9a-f]+p-?[0-9]+[fl]?};
 our $Float_dec = qr{(?i)(?:[0-9]+\.[0-9]*|[0-9]*\.[0-9]+)(?:e-?[0-9]+)?[fl]?};
 our $Float_int = qr{(?i)[0-9]+e-?[0-9]+[fl]?};
@@ -1089,10 +1114,10 @@ sub is_maintained_obsolete {
 sub is_SPDX_License_valid {
        my ($license) = @_;
 
-       return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot"));
+       return 1 if (!$tree || which("python3") eq "" || !(-x "$root/scripts/spdxcheck.py") || !(-e "$gitroot"));
 
        my $root_path = abs_path($root);
-       my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
+       my $status = `cd "$root_path"; echo "$license" | scripts/spdxcheck.py -`;
        return 0 if ($status ne "");
        return 1;
 }
@@ -1186,7 +1211,8 @@ sub git_commit_info {
 #                  git log --format='%H %s' -1 $line |
 #                  echo "commit $(cut -c 1-12,41-)"
 #              done
-       } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
+       } elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./ ||
+                $lines[0] =~ /^fatal: bad object $commit/) {
                $id = undef;
        } else {
                $id = substr($lines[0], 0, 12);
@@ -2580,8 +2606,8 @@ sub u_boot_line {
                     "Possible new uclass - make sure to add a sandbox driver, plus a test in test/dm/<name>.c\n" . $herecurr);
        }
 
-       # try to get people to use the livetree API
-       if ($line =~ /^\+.*fdtdec_/) {
+       # try to get people to use the livetree API, except when changing tooling
+       if ($line =~ /^\+.*fdtdec_/ && $realfile !~ /^tools\//) {
                WARN("LIVETREE",
                     "Use the livetree API (dev_read_...)\n" . $herecurr);
        }
@@ -2604,18 +2630,24 @@ sub u_boot_line {
                     "strl$1 is preferred over strn$1 because it always produces a nul-terminated string\n" . $herecurr);
        }
 
-       # use defconfig to manage CONFIG_CMD options
-       if ($line =~ /\+\s*#\s*(define|undef)\s+(CONFIG_CMD\w*)\b/) {
-               ERROR("DEFINE_CONFIG_CMD",
-                     "All commands are managed by Kconfig\n" . $herecurr);
+       # use Kconfig for all CONFIG symbols
+       if ($line =~ /\+\s*#\s*(define|undef)\s+(CONFIG_\w*)\b/) {
+               ERROR("DEFINE_CONFIG_SYM",
+                     "All CONFIG symbols are managed by Kconfig\n" . $herecurr);
        }
 
-       # Don't put common.h and dm.h in header files
-       if ($realfile =~ /\.h$/ && $rawline =~ /^\+#include\s*<(common|dm)\.h>*/) {
+       # Don't put dm.h in header files
+       if ($realfile =~ /\.h$/ && $rawline =~ /^\+#include\s*<dm\.h>*/) {
                ERROR("BARRED_INCLUDE_IN_HDR",
                      "Avoid including common.h and dm.h in header files\n" . $herecurr);
        }
 
+       # Don't add common.h to files
+       if ($rawline =~ /^\+#include\s*<common\.h>*/) {
+               ERROR("BARRED_INCLUDE_COMMON_H",
+                     "Do not add common.h to files\n" . $herecurr);
+       }
+
        # Do not disable fdt / initrd relocation
        if ($rawline =~ /^\+.*(fdt|initrd)_high=0xffffffff/) {
                ERROR("DISABLE_FDT_OR_INITRD_RELOC",
@@ -2654,6 +2686,12 @@ sub u_boot_line {
                "DEVICE_PRIV_AUTO", $herecurr);
        u_boot_struct_name($line, "per_device_plat_auto", "_plat",
                "DEVICE_PLAT_AUTO", $herecurr);
+
+       # Avoid using the pre-schema driver model tags
+       if ($line =~ /^\+.*u-boot,dm-.*/) {
+               ERROR("PRE_SCHEMA",
+                     "Driver model schema uses 'bootph-...' tags now\n" . $herecurr);
+       }
 }
 
 sub exclude_global_initialisers {
@@ -2697,6 +2735,8 @@ sub process {
        my $reported_maintainer_file = 0;
        my $non_utf8_charset = 0;
 
+       my $last_git_commit_id_linenr = -1;
+
        my $last_blank_line = 0;
        my $last_coalesced_string_linenr = -1;
 
@@ -3019,10 +3059,10 @@ sub process {
                                        my ($email_name, $email_comment, $email_address, $comment1) = parse_email($ctx);
                                        my ($author_name, $author_comment, $author_address, $comment2) = parse_email($author);
 
-                                       if ($email_address eq $author_address && $email_name eq $author_name) {
+                                       if (lc $email_address eq lc $author_address && $email_name eq $author_name) {
                                                $author_sob = $ctx;
                                                $authorsignoff = 2;
-                                       } elsif ($email_address eq $author_address) {
+                                       } elsif (lc $email_address eq lc $author_address) {
                                                $author_sob = $ctx;
                                                $authorsignoff = 3;
                                        } elsif ($email_name eq $author_name) {
@@ -3280,10 +3320,20 @@ sub process {
                }
 
 # Check for git id commit length and improperly formed commit descriptions
-               if ($in_commit_log && !$commit_log_possible_stack_dump &&
+# A correctly formed commit description is:
+#    commit <SHA-1 hash length 12+ chars> ("Complete commit subject")
+# with the commit subject '("' prefix and '")' suffix
+# This is a fairly compilicated block as it tests for what appears to be
+# bare SHA-1 hash with  minimum length of 5.  It also avoids several types of
+# possible SHA-1 matches.
+# A commit match can span multiple lines so this block attempts to find a
+# complete typical commit on a maximum of 3 lines
+               if ($perl_version_ok &&
+                   $in_commit_log && !$commit_log_possible_stack_dump &&
                    $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
                    $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
-                   ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
+                   (($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
+                     ($line =~ /\bcommit\s*$/i && defined($rawlines[$linenr]) && $rawlines[$linenr] =~ /^\s*[0-9a-f]{5,}\b/i)) ||
                     ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
                      $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
                      $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
@@ -3293,49 +3343,56 @@ sub process {
                        my $long = 0;
                        my $case = 1;
                        my $space = 1;
-                       my $hasdesc = 0;
-                       my $hasparens = 0;
                        my $id = '0123456789ab';
                        my $orig_desc = "commit description";
                        my $description = "";
+                       my $herectx = $herecurr;
+                       my $has_parens = 0;
+                       my $has_quotes = 0;
+
+                       my $input = $line;
+                       if ($line =~ /(?:\bcommit\s+[0-9a-f]{5,}|\bcommit\s*$)/i) {
+                               for (my $n = 0; $n < 2; $n++) {
+                                       if ($input =~ /\bcommit\s+[0-9a-f]{5,}\s*($balanced_parens)/i) {
+                                               $orig_desc = $1;
+                                               $has_parens = 1;
+                                               # Always strip leading/trailing parens then double quotes if existing
+                                               $orig_desc = substr($orig_desc, 1, -1);
+                                               if ($orig_desc =~ /^".*"$/) {
+                                                       $orig_desc = substr($orig_desc, 1, -1);
+                                                       $has_quotes = 1;
+                                               }
+                                               last;
+                                       }
+                                       last if ($#lines < $linenr + $n);
+                                       $input .= " " . trim($rawlines[$linenr + $n]);
+                                       $herectx .= "$rawlines[$linenr + $n]\n";
+                               }
+                               $herectx = $herecurr if (!$has_parens);
+                       }
 
-                       if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
+                       if ($input =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
                                $init_char = $1;
                                $orig_commit = lc($2);
-                       } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) {
+                               $short = 0 if ($input =~ /\bcommit\s+[0-9a-f]{12,40}/i);
+                               $long = 1 if ($input =~ /\bcommit\s+[0-9a-f]{41,}/i);
+                               $space = 0 if ($input =~ /\bcommit [0-9a-f]/i);
+                               $case = 0 if ($input =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
+                       } elsif ($input =~ /\b([0-9a-f]{12,40})\b/i) {
                                $orig_commit = lc($1);
                        }
 
-                       $short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i);
-                       $long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i);
-                       $space = 0 if ($line =~ /\bcommit [0-9a-f]/i);
-                       $case = 0 if ($line =~ /\b[Cc]ommit\s+[0-9a-f]{5,40}[^A-F]/);
-                       if ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)"\)/i) {
-                               $orig_desc = $1;
-                               $hasparens = 1;
-                       } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s*$/i &&
-                                defined $rawlines[$linenr] &&
-                                $rawlines[$linenr] =~ /^\s*\("([^"]+)"\)/) {
-                               $orig_desc = $1;
-                               $hasparens = 1;
-                       } elsif ($line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("[^"]+$/i &&
-                                defined $rawlines[$linenr] &&
-                                $rawlines[$linenr] =~ /^\s*[^"]+"\)/) {
-                               $line =~ /\bcommit\s+[0-9a-f]{5,}\s+\("([^"]+)$/i;
-                               $orig_desc = $1;
-                               $rawlines[$linenr] =~ /^\s*([^"]+)"\)/;
-                               $orig_desc .= " " . $1;
-                               $hasparens = 1;
-                       }
-
                        ($id, $description) = git_commit_info($orig_commit,
                                                              $id, $orig_desc);
 
                        if (defined($id) &&
-                          ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) {
+                           ($short || $long || $space || $case || ($orig_desc ne $description) || !$has_quotes) &&
+                           $last_git_commit_id_linenr != $linenr - 1) {
                                ERROR("GIT_COMMIT_ID",
-                                     "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr);
+                                     "Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herectx);
                        }
+                       #don't report the next line if this line ends in commit and the sha1 hash is the next line
+                       $last_git_commit_id_linenr = $linenr if ($line =~ /\bcommit\s*$/i);
                }
 
 # Check for added, moved or deleted files
@@ -4542,6 +4599,7 @@ sub process {
                        #   XXX(foo);
                        #   EXPORT_SYMBOL(something_foo);
                        my $name = $1;
+                       $name =~ s/^\s*($Ident).*/$1/;
                        if ($stat =~ /^(?:.\s*}\s*\n)?.([A-Z_]+)\s*\(\s*($Ident)/ &&
                            $name =~ /^${Ident}_$2/) {
 #print "FOO C name<$name>\n";
@@ -5475,9 +5533,13 @@ sub process {
                        }
                }
 
-#goto labels aren't indented, allow a single space however
-               if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
-                  !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
+# check that goto labels aren't indented (allow a single space indentation)
+# and ignore bitfield definitions like foo:1
+# Strictly, labels can have whitespace after the identifier and before the :
+# but this is not allowed here as many ?: uses would appear to be labels
+               if ($sline =~ /^.\s+[A-Za-z_][A-Za-z\d_]*:(?!\s*\d+)/ &&
+                   $sline !~ /^. [A-Za-z\d_][A-Za-z\d_]*:/ &&
+                   $sline !~ /^.\s+default:/) {
                        if (WARN("INDENTED_LABEL",
                                 "labels should not be indented\n" . $herecurr) &&
                            $fix) {
@@ -5572,7 +5634,7 @@ sub process {
 # Return of what appears to be an errno should normally be negative
                if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
                        my $name = $1;
-                       if ($name ne 'EOF' && $name ne 'ERROR') {
+                       if ($name ne 'EOF' && $name ne 'ERROR' && $name !~ /^EPOLL/) {
                                WARN("USE_NEGATIVE_ERRNO",
                                     "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr);
                        }
@@ -6242,7 +6304,8 @@ sub process {
                }
 
 # concatenated string without spaces between elements
-               if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
+               if ($line =~ /$String[A-Z_]/ ||
+                   ($line =~ /([A-Za-z0-9_]+)$String/ && $1 !~ /^[Lu]$/)) {
                        if (CHK("CONCATENATED_STRING",
                                "Concatenated strings should use spaces between elements\n" . $herecurr) &&
                            $fix) {
@@ -6255,7 +6318,7 @@ sub process {
                }
 
 # uncoalesced string fragments
-               if ($line =~ /$String\s*"/) {
+               if ($line =~ /$String\s*[Lu]?"/) {
                        if (WARN("STRING_FRAGMENTS",
                                 "Consecutive strings are generally better as a single string\n" . $herecurr) &&
                            $fix) {