]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - util/find-doc-nits
unix-Makefile.tmpl and ci.yml: Merge cmd-nits into doc-nits
[thirdparty/openssl.git] / util / find-doc-nits
index 006edbd184b6a4f57c927d349b5e8e7e3217edc2..e8439b8626129b875606a75ee5188797cb352a51 100755 (executable)
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2002-2021 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
@@ -28,9 +28,6 @@ use configdata;
 # Set to 1 for debug output
 my $debug = 0;
 
-# Where to find openssl command
-my $openssl = "./util/opensslwrap.sh";
-
 # Options.
 our($opt_d);
 our($opt_e);
@@ -91,17 +88,23 @@ my %mandatory_sections = (
                          );
 
 # Symbols that we ignored.
-# They are internal macros that we currently don't document
+# They are reserved macros that we currently don't document
 my $ignored = qr/(?| ^i2d_
                  |   ^d2i_
                  |   ^DEPRECATEDIN
+                 |   ^OSSL_DEPRECATED
                  |   \Q_fnsig(3)\E$
                  |   ^IMPLEMENT_
                  |   ^_?DECLARE_
                  |   ^sk_
                  |   ^SKM_DEFINE_STACK_OF_INTERNAL
+                 |   ^lh_
+                 |   ^DEFINE_LHASH_OF_INTERNAL
                  )/x;
 
+# A common regexp for C symbol names
+my $C_symbol = qr/\b[[:alpha:]][_[:alnum:]]*\b/;
+
 # Collect all POD files, both internal and public, and regardless of location
 # We collect them in a hash table with each file being a key, so we can attach
 # tags to them.  For example, internal docs will have the word "internal"
@@ -345,6 +348,7 @@ sub name_synopsis {
 
         my $sym;
         my $is_prototype = 1;
+        $line =~ s/LHASH_OF\([^)]+\)/int/g;
         $line =~ s/STACK_OF\([^)]+\)/int/g;
         $line =~ s/SPARSE_ARRAY_OF\([^)]+\)/int/g;
         $line =~ s/__declspec\([^)]+\)//;
@@ -365,27 +369,27 @@ sub name_synopsis {
         if ( $line =~ /env (\S*)=/ ) {
             # environment variable env NAME=...
             $sym = $1;
-        } elsif ( $line =~ /typedef.*\(\*?(\S+)\)\s*\(/ ) {
+        } elsif ( $line =~ /typedef.*\(\*?($C_symbol)\)\s*\(/ ) {
             # a callback function pointer: typedef ... (*NAME)(...
             # a callback function signature: typedef ... (NAME)(...
             $sym = $1;
-        } elsif ( $line =~ /typedef.* (\S+)\s*\(/ ) {
+        } elsif ( $line =~ /typedef.*($C_symbol)\s*\(/ ) {
             # a callback function signature: typedef ... NAME(...
             $sym = $1;
-        } elsif ( $line =~ /typedef.* (\S+);/ ) {
+        } elsif ( $line =~ /typedef.*($C_symbol);/ ) {
             # a simple typedef: typedef ... NAME;
             $is_prototype = 0;
             $sym = $1;
-        } elsif ( $line =~ /enum (\S*) \{/ ) {
+        } elsif ( $line =~ /enum ($C_symbol) \{/ ) {
             # an enumeration: enum ... {
             $sym = $1;
-        } elsif ( $line =~ /#\s*(?:define|undef) ([A-Za-z0-9_]+)/ ) {
+        } elsif ( $line =~ /#\s*(?:define|undef) ($C_symbol)/ ) {
             $is_prototype = 0;
             $sym = $1;
-        } elsif ( $line =~ /^[^\(]*?\(\*([A-Za-z0-9_]+)\s*\(/ ) {
+        } elsif ( $line =~ /^[^\(]*?\(\*($C_symbol)\s*\(/ ) {
             # a function returning a function pointer: TYPE (*NAME(args))(args)
             $sym = $1;
-        } elsif ( $line =~ /^[^\(]*?([A-Za-z0-9_]+)\s*\(/ ) {
+        } elsif ( $line =~ /^[^\(]*?($C_symbol)\s*\(/ ) {
             # a simple function declaration
             $sym = $1;
         }
@@ -603,6 +607,7 @@ my %preferred_words = (
     'bitmask'       => 'bit mask',
     'builtin'       => 'built-in',
    #'epoch'         => 'Epoch', # handled specially, below
+    'fall-back'     => 'fallback',
     'file name'     => 'filename',
     'file system'   => 'filesystem',
     'host name'     => 'hostname',
@@ -772,7 +777,8 @@ sub check {
 
     open my $OUT, '>', $temp
         or die "Can't open $temp, $!";
-    podchecker($filename, $OUT);
+    err($id, "POD errors")
+        if podchecker($filename, $OUT) != 0;
     close $OUT;
     open $OUT, '<', $temp
         or die "Can't read $temp, $!";
@@ -878,7 +884,7 @@ sub checkstate () {
 
         err("$_ is supposedly public but is documented as internal")
             if ( $declared_public && $name_map{$_} =~ /\/internal\// );
-        err("$_ is supposedly internal but is documented as public")
+        err("$_ is supposedly internal (maybe missing from other.syms) but is documented as public")
             if ( $declared_internal && $name_map{$_} !~ /\/internal\// );
     }
 }
@@ -1020,21 +1026,39 @@ my %skips = (
     'digest' => 1,
 );
 
+my %genopts; # generic options parsed from apps/include/opt.h
+
 # Check the flags of a command and see if everything is in the manpage
 sub checkflags {
     my $cmd = shift;
     my $doc = shift;
-    my %cmdopts;
+    my @cmdopts;
     my %docopts;
-    my %localskips;
 
-    # Get the list of options in the command.
-    open CFH, "$openssl list --options $cmd|"
-        or die "Can list options for $cmd, $!";
+    # Get the list of options in the command source file.
+    my $active = 0;
+    my $expect_helpstr = "";
+    open CFH, "apps/$cmd.c"
+        or die "Can't open apps/$cmd.c to list options for $cmd, $!";
     while ( <CFH> ) {
         chop;
-        s/ .$//;
-        $cmdopts{$_} = 1;
+        if ($active) {
+            last if m/^\s*};/;
+            if ($expect_helpstr ne "") {
+                next if m/^\s*#\s*if/;
+                err("$cmd does not implement help for -$expect_helpstr") unless m/^\s*"/;
+                $expect_helpstr = "";
+            } elsif (m/\{\s*"([^"]+)"\s*,\s*OPT_[A-Z0-9_]+\s*,\s*('[-\/:<>cEfFlMnNpsuU]'|0)\s*,(.*)$/
+                       && !($cmd eq "s_client" && $1 eq "wdebug")) {
+                push @cmdopts, $1;
+                $expect_helpstr = $1;
+                $expect_helpstr = "" if $3 =~ m/^\s*"/;
+            } elsif (m/[\s,](OPT_[A-Z]+_OPTIONS?)\s*(,|$)/) {
+                push @cmdopts, @{ $genopts{$1} };
+            }
+        } elsif (m/^const\s+OPTIONS\s*/) {
+            $active = 1;
+        }
     }
     close CFH;
 
@@ -1044,12 +1068,6 @@ sub checkflags {
     while ( <CFH> ) {
         chop;
         last if /DESCRIPTION/;
-        if ( /=for openssl ifdef (.*)/ ) {
-            foreach my $f ( split / /, $1 ) {
-                $localskips{$f} = 1;
-            }
-            next;
-        }
         my $opt;
         if ( /\[B<-([^ >]+)/ ) {
             $opt = $1;
@@ -1064,16 +1082,17 @@ sub checkflags {
     close CFH;
 
     # See what's in the command not the manpage.
-    my @undocced = sort grep { !defined $docopts{$_} } keys %cmdopts;
+    my @undocced = sort grep { !defined $docopts{$_} } @cmdopts;
     foreach ( @undocced ) {
-        next if /-/; # Skip the -- end-of-flags marker
+        next if $cmd eq "openssl" && $_ eq "help";
         err("$doc: undocumented option -$_");
     }
 
     # See what's in the command not the manpage.
-    my @unimpl = sort grep { !defined $cmdopts{$_} } keys %docopts;
+    my @unimpl = sort grep { my $e = $_; !(grep /^\Q$e\E$/, @cmdopts) } keys %docopts;
     foreach ( @unimpl ) {
-        next if defined $skips{$_} || defined $localskips{$_};
+        next if $_ eq "-"; # Skip the -- end-of-flags marker
+        next if defined $skips{$_};
         err("$doc: $cmd does not implement -$_");
     }
 }
@@ -1088,18 +1107,27 @@ sub checkflags {
 if ( $opt_c ) {
     my @commands = ();
 
-    # Get list of commands.
-    open FH, "$openssl list -1 -commands|"
-        or die "Can't list commands, $!";
-    while ( <FH> ) {
+    # Get the lists of generic options.
+    my $active = "";
+    open OFH, "apps/include/opt.h"
+        or die "Can't open apps/include/opt.h to list generic options, $!";
+    while ( <OFH> ) {
         chop;
-        push @commands, $_;
+        push @{ $genopts{$active} }, $1 if $active ne "" && m/^\s+\{\s*"([^"]+)"\s*,\s*OPT_/;
+        $active = $1 if m/^\s*#\s*define\s+(OPT_[A-Z]+_OPTIONS?)\s*\\\s*$/;
+        $active = "" if m/^\s*$/;
     }
-    close FH;
+    close OFH;
+
+    # Get list of commands.
+    opendir(DIR, "apps");
+    @commands = grep(/\.c$/, readdir(DIR));
+    closedir(DIR);
 
     # See if each has a manpage.
     foreach my $cmd ( @commands ) {
-        next if $cmd eq 'help' || $cmd eq 'exit';
+        $cmd =~ s/\.c$//;
+        next if $cmd eq 'progs' || $cmd eq 'cmp_mock_srv' || $cmd eq 'vms_decc_init';
         my @doc = ( grep { basename($_) eq "openssl-$cmd.pod"
                            # For "tsget" and "CA.pl" pod pages
                            || basename($_) eq "$cmd.pod" }
@@ -1113,18 +1141,6 @@ if ( $opt_c ) {
             checkflags($cmd, @doc);
         }
     }
-
-    # See what help is missing.
-    open FH, "$openssl list --missing-help |"
-        or die "Can't list missing help, $!";
-    while ( <FH> ) {
-        chop;
-        my ($cmd, $flag) = split;
-        err("$cmd has no help for -$flag");
-    }
-    close FH;
-
-    exit $status;
 }
 
 # Populate %state
@@ -1166,7 +1182,8 @@ if ( $opt_n ) {
     # If not given args, check that all man1 commands are named properly.
     if ( scalar @ARGV == 0 ) {
         foreach ( files(TAGS => [ 'public_manual', 'man1' ]) ) {
-            next if /CA.pl/ || /openssl\.pod/ || /tsget\.pod/;
+            next if /openssl\.pod/
+                || /CA\.pl/ || /tsget\.pod/; # these commands are special cases
             err("$_ doesn't start with openssl-") unless /openssl-/;
         }
     }