scripts/gdb: add lx_current support for arm64
[linux-2.6-microblaze.git] / scripts / checkpatch.pl
index df8b23d..23697a6 100755 (executable)
@@ -23,6 +23,9 @@ my $V = '0.32';
 use Getopt::Long qw(:config no_auto_abbrev);
 
 my $quiet = 0;
+my $verbose = 0;
+my %verbose_messages = ();
+my %verbose_emitted = ();
 my $tree = 1;
 my $chk_signoff = 1;
 my $chk_patch = 1;
@@ -61,6 +64,7 @@ my $spelling_file = "$D/spelling.txt";
 my $codespell = 0;
 my $codespellfile = "/usr/share/codespell/dictionary.txt";
 my $conststructsfile = "$D/const_structs.checkpatch";
+my $docsfile = "$D/../Documentation/dev-tools/checkpatch.rst";
 my $typedefsfile;
 my $color = "auto";
 my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
@@ -78,6 +82,7 @@ Version: $V
 
 Options:
   -q, --quiet                quiet
+  -v, --verbose              verbose mode
   --no-tree                  run without a kernel tree
   --no-signoff               do not check for 'Signed-off-by' line
   --patch                    treat FILE as patchfile (default)
@@ -158,15 +163,51 @@ sub list_types {
        my $text = <$script>;
        close($script);
 
-       my @types = ();
+       my %types = ();
        # Also catch when type or level is passed through a variable
-       for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
-               push (@types, $_);
+       while ($text =~ /(?:(\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
+               if (defined($1)) {
+                       if (exists($types{$2})) {
+                               $types{$2} .= ",$1" if ($types{$2} ne $1);
+                       } else {
+                               $types{$2} = $1;
+                       }
+               } else {
+                       $types{$2} = "UNDETERMINED";
+               }
        }
-       @types = sort(uniq(@types));
+
        print("#\tMessage type\n\n");
-       foreach my $type (@types) {
+       if ($color) {
+               print(" ( Color coding: ");
+               print(RED . "ERROR" . RESET);
+               print(" | ");
+               print(YELLOW . "WARNING" . RESET);
+               print(" | ");
+               print(GREEN . "CHECK" . RESET);
+               print(" | ");
+               print("Multiple levels / Undetermined");
+               print(" )\n\n");
+       }
+
+       foreach my $type (sort keys %types) {
+               my $orig_type = $type;
+               if ($color) {
+                       my $level = $types{$type};
+                       if ($level eq "ERROR") {
+                               $type = RED . $type . RESET;
+                       } elsif ($level eq "WARN") {
+                               $type = YELLOW . $type . RESET;
+                       } elsif ($level eq "CHK") {
+                               $type = GREEN . $type . RESET;
+                       }
+               }
                print(++$count . "\t" . $type . "\n");
+               if ($verbose && exists($verbose_messages{$orig_type})) {
+                       my $message = $verbose_messages{$orig_type};
+                       $message =~ s/\n/\n\t/g;
+                       print("\t" . $message . "\n\n");
+               }
        }
 
        exit($exitcode);
@@ -198,6 +239,46 @@ if (-f $conf) {
        unshift(@ARGV, @conf_args) if @conf_args;
 }
 
+sub load_docs {
+       open(my $docs, '<', "$docsfile")
+           or warn "$P: Can't read the documentation file $docsfile $!\n";
+
+       my $type = '';
+       my $desc = '';
+       my $in_desc = 0;
+
+       while (<$docs>) {
+               chomp;
+               my $line = $_;
+               $line =~ s/\s+$//;
+
+               if ($line =~ /^\s*\*\*(.+)\*\*$/) {
+                       if ($desc ne '') {
+                               $verbose_messages{$type} = trim($desc);
+                       }
+                       $type = $1;
+                       $desc = '';
+                       $in_desc = 1;
+               } elsif ($in_desc) {
+                       if ($line =~ /^(?:\s{4,}|$)/) {
+                               $line =~ s/^\s{4}//;
+                               $desc .= $line;
+                               $desc .= "\n";
+                       } else {
+                               $verbose_messages{$type} = trim($desc);
+                               $type = '';
+                               $desc = '';
+                               $in_desc = 0;
+                       }
+               }
+       }
+
+       if ($desc ne '') {
+               $verbose_messages{$type} = trim($desc);
+       }
+       close($docs);
+}
+
 # Perl's Getopt::Long allows options to take optional arguments after a space.
 # Prevent --color by itself from consuming other arguments
 foreach (@ARGV) {
@@ -208,6 +289,7 @@ foreach (@ARGV) {
 
 GetOptions(
        'q|quiet+'      => \$quiet,
+       'v|verbose!'    => \$verbose,
        'tree!'         => \$tree,
        'signoff!'      => \$chk_signoff,
        'patch!'        => \$chk_patch,
@@ -247,13 +329,27 @@ GetOptions(
 
 help(0) 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);
+
+if ($color =~ /^[01]$/) {
+       $color = !$color;
+} elsif ($color =~ /^always$/i) {
+       $color = 1;
+} elsif ($color =~ /^never$/i) {
+       $color = 0;
+} elsif ($color =~ /^auto$/i) {
+       $color = (-t STDOUT);
+} else {
+       die "$P: Invalid color mode: $color\n";
+}
+
+load_docs() if ($verbose);
 list_types(0) if ($list_types);
 
 $fix = 1 if ($fix_inplace);
 $check_orig = $check;
 
-die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
-
 my $exit = 0;
 
 my $perl_version_ok = 1;
@@ -268,18 +364,6 @@ if ($#ARGV < 0) {
        push(@ARGV, '-');
 }
 
-if ($color =~ /^[01]$/) {
-       $color = !$color;
-} elsif ($color =~ /^always$/i) {
-       $color = 1;
-} elsif ($color =~ /^never$/i) {
-       $color = 0;
-} elsif ($color =~ /^auto$/i) {
-       $color = (-t STDOUT);
-} else {
-       die "$P: Invalid color mode: $color\n";
-}
-
 # skip TAB size 1 to avoid additional checks on $tabsize - 1
 die "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2);
 
@@ -2209,7 +2293,16 @@ sub report {
                splice(@lines, 1, 1);
                $output = join("\n", @lines);
        }
-       $output = (split('\n', $output))[0] . "\n" if ($terse);
+
+       if ($terse) {
+               $output = (split('\n', $output))[0] . "\n";
+       }
+
+       if ($verbose && exists($verbose_messages{$type}) &&
+           !exists($verbose_emitted{$type})) {
+               $output .= $verbose_messages{$type} . "\n\n";
+               $verbose_emitted{$type} = 1;
+       }
 
        push(our @report, $output);
 
@@ -3152,7 +3245,7 @@ sub process {
                    ($line =~ /^new file mode\s*\d+\s*$/) &&
                    ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
                        WARN("DT_SCHEMA_BINDING_PATCH",
-                            "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n");
+                            "DT bindings should be in DT schema format. See: Documentation/devicetree/bindings/writing-schema.rst\n");
                }
 
 # Check for wrappage within a valid hunk of the file
@@ -5736,7 +5829,7 @@ sub process {
                                next if ($arg =~ /\.\.\./);
                                next if ($arg =~ /^type$/i);
                                my $tmp_stmt = $define_stmt;
-                               $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
+                               $tmp_stmt =~ s/\b(__must_be_array|offsetof|sizeof|sizeof_field|__stringify|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
                                $tmp_stmt =~ s/\#+\s*$arg\b//g;
                                $tmp_stmt =~ s/\b$arg\s*\#\#//g;
                                my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
@@ -6606,9 +6699,11 @@ sub process {
                                        $specifier = $1;
                                        $extension = $2;
                                        $qualifier = $3;
-                                       if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
+                                       if ($extension !~ /[4SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
                                            ($extension eq "f" &&
-                                            defined $qualifier && $qualifier !~ /^w/)) {
+                                            defined $qualifier && $qualifier !~ /^w/) ||
+                                           ($extension eq "4" &&
+                                            defined $qualifier && $qualifier !~ /^cc/)) {
                                                $bad_specifier = $specifier;
                                                last;
                                        }
@@ -6911,7 +7006,7 @@ sub process {
                }
 
 # check for alloc argument mismatch
-               if ($line =~ /\b(kcalloc|kmalloc_array)\s*\(\s*sizeof\b/) {
+               if ($line =~ /\b((?:devm_)?(?:kcalloc|kmalloc_array))\s*\(\s*sizeof\b/) {
                        WARN("ALLOC_ARRAY_ARGS",
                             "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
                }
@@ -7103,6 +7198,17 @@ sub process {
                             "Using $1 should generally have parentheses around the comparison\n" . $herecurr);
                }
 
+# return sysfs_emit(foo, fmt, ...) fmt without newline
+               if ($line =~ /\breturn\s+sysfs_emit\s*\(\s*$FuncArg\s*,\s*($String)/ &&
+                   substr($rawline, $-[6], $+[6] - $-[6]) !~ /\\n"$/) {
+                       my $offset = $+[6] - 1;
+                       if (WARN("SYSFS_EMIT",
+                                "return sysfs_emit(...) formats should include a terminating newline\n" . $herecurr) &&
+                           $fix) {
+                               substr($fixed[$fixlinenr], $offset, 0) = '\\n';
+                       }
+               }
+
 # nested likely/unlikely calls
                if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
                        WARN("LIKELY_MISUSE",