Add a new verbose mode to checkpatch.pl to emit additional verbose
test descriptions.

The verbose mode is optional and can be enabled by the flag
--verbose.

The test descriptions are itself loaded from the checkpatch
documentation file at Documentation/dev-tools/checkpatch.rst.
The descriptions in the documentation are in a specified format
enclosed within .. CHECKPATCH_START and .. CHECKPATCH_END labels.

This serves a dual purpose as an external documentation to checkpatch
as well as enables flawless integration of the verbose mode.

A subtle example of the format is as follows:

Documentation/dev-tools/checkpatch.rst:

.. CHECKPATCH_START
TYPE_1

  Description line 1
  Description line 2,
  ...

TYPE_2

  Description line 1,
  etc.

.. CHECKPATCH_END

This file is parsed by checkpatch once the --verbose option
is specified. Verbose descriptions are not output when
the --terse option is specified.

Signed-off-by: Dwaipayan Ray <dwaipayanr...@gmail.com>
---
 scripts/checkpatch.pl | 55 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 7a323ca8a177..48eeb01074d5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -23,6 +23,8 @@ my $V = '0.32';
 use Getopt::Long qw(:config no_auto_abbrev);
 
 my $quiet = 0;
+my $verbose = 0;
+my %verbose_messages = ();
 my $tree = 1;
 my $chk_signoff = 1;
 my $chk_patch = 1;
@@ -61,6 +63,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 +81,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)
@@ -198,6 +202,49 @@ 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 @lines = ();
+       my $incl = 0;
+       while (<$docs>) {
+               my $line = $_;
+
+               if ($line =~ /\Q.. CHECKPATCH_START\E/) {
+                       $incl++;
+                       next;
+               } elsif ($line =~ /\Q.. CHECKPATCH_END\E/) {
+                       $incl--;
+                       next;
+               }
+               next if ($incl < 1);
+
+               $line =~ s/\s*\n?$//g;
+               push (@lines, $line);
+       }
+       close($docs);
+
+       my $linenr = 0;
+       my $cnt = scalar @lines;
+       while ($linenr < $cnt) {
+               while ($linenr < $cnt && $lines[$linenr] !~ /^[^\s]+/) {
+                       $linenr++;
+               }
+               last if ($linenr >= $cnt);
+
+               my $message = '';
+               my $type = $lines[$linenr++];
+
+               while ($linenr < $cnt && $lines[$linenr] !~ /^[^\s]+/) {
+                       $message .= trim($lines[$linenr++]) . "\n";
+               }
+
+               $message = trim($message);
+               $verbose_messages{$type} = $message;
+       }
+}
+
 # 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 +255,7 @@ foreach (@ARGV) {
 
 GetOptions(
        'q|quiet+'      => \$quiet,
+       'v|verbose!'    => \$verbose,
        'tree!'         => \$tree,
        'signoff!'      => \$chk_signoff,
        'patch!'        => \$chk_patch,
@@ -249,6 +297,8 @@ help(0) if ($help);
 
 list_types(0) if ($list_types);
 
+load_docs() if ($verbose && !$terse);
+
 $fix = 1 if ($fix_inplace);
 $check_orig = $check;
 
@@ -2185,6 +2235,11 @@ sub report {
                splice(@lines, 1, 1);
                $output = join("\n", @lines);
        }
+
+       if ($verbose && !$terse &&
+           exists $verbose_messages{$type}) {
+               $output .= $verbose_messages{$type} . "\n\n";
+       }
        $output = (split('\n', $output))[0] . "\n" if ($terse);
 
        push(our @report, $output);
-- 
2.30.0

Reply via email to