Update configurable sigalgs documentation for providers
[openssl.git] / util / find-doc-nits
index 815880ad01d429d77d46eac2807251191251bc8c..7d1cdb59b1dbd6e1845200237ffe5d6bed48fb51 100755 (executable)
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -35,6 +35,7 @@ our($opt_s);
 our($opt_o);
 our($opt_h);
 our($opt_l);
+our($opt_m);
 our($opt_n);
 our($opt_p);
 our($opt_u);
@@ -45,11 +46,12 @@ our($opt_c);
 sub help {
     print <<EOF;
 Find small errors (nits) in documentation.  Options:
-    -c List undocumented commands and options
+    -c List undocumented commands, undocumented options and unimplemented options.
     -d Detailed list of undocumented (implies -u)
     -e Detailed list of new undocumented (implies -v)
     -h Print this help message
     -l Print bogus links
+    -m Name(s) of manuals to focus on. Default: man1,man3,man5,man7
     -n Print nits in POD pages
     -o Causes -e/-v to count symbols added since 1.1.1 as new (implies -v)
     -u Count undocumented functions
@@ -58,7 +60,7 @@ EOF
     exit;
 }
 
-getopts('cdehlnouv');
+getopts('cdehlm:nouv');
 
 help() if $opt_h;
 $opt_u = 1 if $opt_d;
@@ -78,12 +80,16 @@ my $temp = '/tmp/docnits.txt';
 my $OUT;
 my $status = 0;
 
-my @sections = ( 'man1', 'man3', 'man5', 'man7' );
+$opt_m = "man1,man3,man5,man7" unless $opt_m;
+die "Argument of -m option may contain only man1, man3, man5, and/or man7"
+    unless $opt_m =~ /^(man[1357][, ]?)*$/;
+my @sections = ( split /[, ]/, $opt_m );
+
 my %mandatory_sections = (
-    '*' => [ 'NAME', 'DESCRIPTION', 'COPYRIGHT' ],
-    1   => [ 'SYNOPSIS', 'OPTIONS' ],
-    3   => [ 'SYNOPSIS', 'RETURN VALUES' ],
-    5   => [ ],
+    '*' => [ 'NAME', 'COPYRIGHT' ],
+    1   => [ 'DESCRIPTION', 'SYNOPSIS', 'OPTIONS' ],
+    3   => [ 'DESCRIPTION', 'SYNOPSIS', 'RETURN VALUES' ],
+    5   => [ 'DESCRIPTION' ],
     7   => [ ]
                          );
 
@@ -99,7 +105,7 @@ my $ignored = qr/(?| ^i2d_
                  |   ^sk_
                  |   ^SKM_DEFINE_STACK_OF_INTERNAL
                  |   ^lh_
-                 |   ^DEFINE_LHASH_OF_INTERNAL
+                 |   ^DEFINE_LHASH_OF_(INTERNAL|DEPRECATED)
                  )/x;
 
 # A common regexp for C symbol names
@@ -148,7 +154,7 @@ my %collected_results = ();
 #                       - exclusive selectors, only applicable together with
 #                         any of the manual selectors.  If any of these are
 #                         present, only the manuals from the given sections
-#                         will be include.  If none of these are present,
+#                         will be included.  If none of these are present,
 #                         the manuals from all sections will be returned.
 #
 # All returned manual files come from configdata.pm.
@@ -543,8 +549,10 @@ sub option_check {
         err($id, "Malformed option [1] in SYNOPSIS: $&");
     }
 
+    my @synopsis;
     while ( $synopsis =~ /$markup_re/msg ) {
         my $found = $&;
+        push @synopsis, $found if $found =~ /^B<-/;
         print STDERR "$id:DEBUG[option_check] SYNOPSIS: found $found\n"
             if $debug;
         my $option_uw = normalise_option($id, $filename, $found);
@@ -554,6 +562,7 @@ sub option_check {
 
     # In OPTIONS, we look for =item paragraphs.
     # (?=^\s*$) detects an empty line.
+    my @options;
     while ( $options =~ /=item\s+(.*?)(?=^\s*$)/msg ) {
         my $item = $&;
 
@@ -567,8 +576,19 @@ sub option_check {
             my $option_uw = normalise_option($id, $filename, $found);
             err($id, "Malformed option in OPTIONS: $found")
                 if defined $option_uw && $option_uw eq '';
+            if ($found =~ /^B<-/) {
+                push @options, $found;
+                err($id, "OPTIONS entry $found missing from SYNOPSIS")
+                    unless (grep /^\Q$found\E$/, @synopsis)
+                         || $id =~ /(openssl|-options)\.pod:1:$/;
+            }
         }
     }
+    foreach (@synopsis) {
+        my $option = $_;
+        err($id, "SYNOPSIS entry $option missing from OPTIONS")
+            unless (grep /^\Q$option\E$/, @options);
+    }
 }
 
 # Normal symbol form
@@ -681,17 +701,21 @@ sub check {
     my $dirname = basename(dirname($filename));
     my $contents = $podinfo{contents};
 
+    # Find what section this page is in; presume 3.
+    my $mansect = 3;
+    $mansect = $1 if $filename =~ /man([1-9])/;
+
     my $id = "${filename}:1:";
     check_head_style($id, $contents);
 
     # Check ordering of some sections in man3
-    if ( $filename =~ m|man3/| ) {
+    if ( $mansect == 3 ) {
         check_section_location($id, $contents, "RETURN VALUES", "EXAMPLES");
         check_section_location($id, $contents, "SEE ALSO", "HISTORY");
         check_section_location($id, $contents, "EXAMPLES", "SEE ALSO");
     }
 
-    # Make sure every link has a section.
+    # Make sure every link has a man section number.
     while ( $contents =~ /$markup_re/msg ) {
         my $target = $1;
         next unless $target =~ /^L<(.*)>$/;     # Skip if not L<...>
@@ -702,7 +726,7 @@ sub check {
         next if $target =~ /::/;                #   links to a Perl module, or
         next if $target =~ /^https?:/;          #   is a URL link, or
         next if $target =~ /\([1357]\)$/;       #   it has a section
-        err($id, "Section missing in $target")
+        err($id, "Missing man section number (likely, $mansect) in L<$target>")
     }
     # Check for proper links to commands.
     while ( $contents =~ /L<([^>]*)\(1\)(?:\/.*)?>/g ) {
@@ -710,9 +734,8 @@ sub check {
         next if $target =~ /openssl-?/;
         next if ( grep { basename($_) eq "$target.pod" }
                   files(TAGS => [ 'manual', 'man1' ]) );
-        # TODO: Filter out "foreign manual" links.
         next if $target =~ /ps|apropos|sha1sum|procmail|perl/;
-        err($id, "Bad command link L<$target(1)>");
+        err($id, "Bad command link L<$target(1)>") if grep /man1/, @sections;
     }
     # Check for proper in-man-3 API links.
     while ( $contents =~ /L<([^>]*)\(3\)(?:\/.*)?>/g ) {
@@ -722,10 +745,10 @@ sub check {
     }
 
     unless ( $contents =~ /^=for openssl generic/ms ) {
-        if ( $filename =~ m|man3/| ) {
+        if ( $mansect == 3 ) {
             name_synopsis($id, $filename, $contents);
             functionname_check($id, $filename, $contents);
-        } elsif ( $filename =~ m|man1/| ) {
+        } elsif ( $mansect == 1 ) {
             option_check($id, $filename, $contents)
         }
     }
@@ -789,7 +812,7 @@ sub check {
     close $OUT;
     unlink $temp || warn "Can't remove $temp, $!";
 
-    # Find what section this page is in; assume 3.
+    # Find what section this page is in; presume 3.
     my $section = 3;
     $section = $1 if $dirname =~ /man([1-9])/;
 
@@ -980,16 +1003,27 @@ sub collectnames {
         }
     }
 
-    my @links =
-        $podinfo{contents} =~ /L<
-                              # if the link is of the form L<something|name(s)>,
-                              # then remove 'something'.  Note that 'something'
-                              # may contain POD codes as well...
-                              (?:(?:[^\|]|<[^>]*>)*\|)?
-                              # we're only interested in references that have
-                              # a one digit section number
-                              ([^\/>\(]+\(\d\))
-                             /gx;
+    my @links = ();
+    # Don't use this regexp directly on $podinfo{contents}, as it causes
+    # a regexp recursion, which fails on really big PODs.  Instead, use
+    # $markup_re to pick up general markup, and use this regexp to check
+    # that the markup that was found is indeed a link.
+    my $linkre = qr/L<
+                    # if the link is of the form L<something|name(s)>,
+                    # then remove 'something'.  Note that 'something'
+                    # may contain POD codes as well...
+                    (?:(?:[^\|]|<[^>]*>)*\|)?
+                    # we're only interested in references that have
+                    # a one digit section number
+                    ([^\/>\(]+\(\d\))
+                   /x;
+    while ( $podinfo{contents} =~ /$markup_re/msg ) {
+        my $x = $1;
+
+        if ($x =~ $linkre) {
+            push @links, $1;
+        }
+    }
     $link_map{$filename} = [ @links ];
 }
 
@@ -1049,11 +1083,11 @@ sub checkflags {
                 err("$cmd does not implement help for -$expect_helpstr") unless m/^\s*"/;
                 $expect_helpstr = "";
             }
-            if (m/\{\s*"([^"]+)"\s*,\s*OPT_[A-Z0-9_]+\s*,\s*('[-\/:<>cEfFlMnNpsuU]'|0)\s*,(.*)$/
-                       && !($cmd eq "s_client" && $1 eq "wdebug")) {
+            if (m/\{\s*"([^"]+)"\s*,\s*OPT_[A-Z0-9_]+\s*,\s*('[-\/:<>cAEfFlMnNpsuU]'|0)(.*)$/
+                    && !($cmd eq "s_client" && $1 eq "wdebug")) {
                 push @cmdopts, $1;
                 $expect_helpstr = $1;
-                $expect_helpstr = "" if $3 =~ m/^\s*"/;
+                $expect_helpstr = "" if $3 =~ m/^\s*,\s*"/;
             } elsif (m/[\s,](OPT_[A-Z]+_OPTIONS?)\s*(,|$)/) {
                 push @cmdopts, @{ $genopts{$1} };
             }
@@ -1085,11 +1119,10 @@ sub checkflags {
     # See what's in the command not the manpage.
     my @undocced = sort grep { !defined $docopts{$_} } @cmdopts;
     foreach ( @undocced ) {
-        next if $cmd eq "openssl" && $_ eq "help";
-        err("$doc: undocumented option -$_");
+        err("$doc: undocumented $cmd option -$_");
     }
 
-    # See what's in the command not the manpage.
+    # See what's in the manpage not the command.
     my @unimpl = sort grep { my $e = $_; !(grep /^\Q$e\E$/, @cmdopts) } keys %docopts;
     foreach ( @unimpl ) {
         next if $_ eq "-"; # Skip the -- end-of-flags marker
@@ -1110,7 +1143,7 @@ if ( $opt_c ) {
 
     # Get the lists of generic options.
     my $active = "";
-    open OFH, "apps/include/opt.h"
+    open OFH, catdir($config{sourcedir}, "apps/include/opt.h")
         or die "Can't open apps/include/opt.h to list generic options, $!";
     while ( <OFH> ) {
         chop;
@@ -1181,7 +1214,7 @@ if ( $opt_l ) {
 
 if ( $opt_n ) {
     # If not given args, check that all man1 commands are named properly.
-    if ( scalar @ARGV == 0 ) {
+    if ( scalar @ARGV == 0 && grep /man1/, @sections ) {
         foreach ( files(TAGS => [ 'public_manual', 'man1' ]) ) {
             next if /openssl\.pod/
                 || /CA\.pl/ || /tsget\.pod/; # these commands are special cases