Latest update.
This commit is contained in:
+77
-74
@@ -140,25 +140,33 @@ sub name_synopsis {
|
||||
foreach my $line ( split /\n+/, $syn ) {
|
||||
next unless $line =~ /^\s/;
|
||||
my $sym;
|
||||
my $is_prototype = 1;
|
||||
$line =~ s/STACK_OF\([^)]+\)/int/g;
|
||||
$line =~ s/SPARSE_ARRAY_OF\([^)]+\)/int/g;
|
||||
$line =~ s/__declspec\([^)]+\)//;
|
||||
if ( $line =~ /typedef.*\(\*\S+\)\s+\(/ ) {
|
||||
# a callback function with whitespace before the argument list:
|
||||
# typedef ... (*NAME) (...
|
||||
err($id, "function typedef has space before arg list: $line");
|
||||
}
|
||||
if ( $line =~ /env (\S*)=/ ) {
|
||||
# environment variable env NAME=...
|
||||
$sym = $1;
|
||||
} elsif ( $line =~ /typedef.*\(\*(\S+)\)\(.*/ ) {
|
||||
} elsif ( $line =~ /typedef.*\(\*(\S+)\)\s*\(/ ) {
|
||||
# a callback function pointer: typedef ... (*NAME)(...
|
||||
$sym = $1;
|
||||
} elsif ( $line =~ /typedef.* (\S+)\(.*/ ) {
|
||||
} elsif ( $line =~ /typedef.* (\S+)\(/ ) {
|
||||
# a callback function signature: typedef ... NAME(...
|
||||
$sym = $1;
|
||||
} elsif ( $line =~ /typedef.* (\S+);/ ) {
|
||||
# a simple typedef: typedef ... NAME;
|
||||
$is_prototype = 0;
|
||||
$sym = $1;
|
||||
} elsif ( $line =~ /enum (\S*) \{/ ) {
|
||||
# an enumeration: enum ... {
|
||||
$sym = $1;
|
||||
} elsif ( $line =~ /#(?:define|undef) ([A-Za-z0-9_]+)/ ) {
|
||||
$is_prototype = 0;
|
||||
$sym = $1;
|
||||
} elsif ( $line =~ /([A-Za-z0-9_]+)\(/ ) {
|
||||
$sym = $1;
|
||||
@@ -172,7 +180,7 @@ sub name_synopsis {
|
||||
|
||||
# Do some sanity checks on the prototype.
|
||||
err($id, "prototype missing spaces around commas: $line")
|
||||
if ( $line =~ /[a-z0-9],[^ ]/ );
|
||||
if $is_prototype && $line =~ /[a-z0-9],[^ ]/;
|
||||
}
|
||||
|
||||
foreach my $n ( keys %names ) {
|
||||
@@ -235,7 +243,7 @@ sub check_head_style {
|
||||
my $markup_re =
|
||||
qr/( # Capture group
|
||||
[BIL]< # The start of what we recurse on
|
||||
(?:(?-1)|.)*? # recurse the whole regexp (refering to
|
||||
(?:(?-1)|.)*? # recurse the whole regexp (referring to
|
||||
# the last opened capture group, i.e. the
|
||||
# start of this regexp), or pick next
|
||||
# character. Do NOT be greedy!
|
||||
@@ -447,6 +455,35 @@ sub check {
|
||||
check_section_location($id, $contents, "EXAMPLES", "SEE ALSO");
|
||||
}
|
||||
|
||||
# Make sure every link has a section.
|
||||
while ( $contents =~ /$markup_re/msg ) {
|
||||
my $target = $1;
|
||||
next unless $target =~ /^L<(.*)>$/; # Skip if not L<...>
|
||||
$target = $1; # Peal away L< and >
|
||||
$target =~ s/\/[^\/]*$//; # Peal away possible anchor
|
||||
$target =~ s/.*\|//g; # Peal away possible link text
|
||||
next if $target eq ''; # Skip if links within page, or
|
||||
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")
|
||||
}
|
||||
# Check for proper links to commands.
|
||||
while ( $contents =~ /L<([^>]*)\(1\)(?:\/.*)?>/g ) {
|
||||
my $target = $1;
|
||||
next if $target =~ /openssl-?/;
|
||||
next if -f "doc/man1/$target.pod";
|
||||
# TODO: Filter out "foreign manual" links.
|
||||
next if $target =~ /ps|apropos|sha1sum|procmail|perl/;
|
||||
err($id, "Bad command link L<$target(1)>");
|
||||
}
|
||||
# Check for proper in-man-3 API links.
|
||||
while ( $contents =~ /L<([^>]*)\(3\)(?:\/.*)?>/g ) {
|
||||
my $target = $1;
|
||||
err($id, "Bad L<$target>")
|
||||
unless $target =~ /^[_[:alpha:]][_[:alnum:]]*$/
|
||||
}
|
||||
|
||||
unless ( $contents =~ /=for openssl generic/ ) {
|
||||
if ( $filename =~ m|man3/| ) {
|
||||
name_synopsis($id, $filename, $contents);
|
||||
@@ -548,27 +585,6 @@ sub parsenum {
|
||||
|
||||
# Parse all the manpages, getting return map of what they document
|
||||
# (by looking at their NAME sections).
|
||||
sub getdocced
|
||||
{
|
||||
my $dir = shift;
|
||||
my %return;
|
||||
my %dups;
|
||||
|
||||
foreach my $pod ( glob("$dir/*.pod") ) {
|
||||
my %podinfo = extract_pod_info($pod);
|
||||
foreach my $n ( @{$podinfo{names}} ) {
|
||||
$return{$n} = $pod;
|
||||
err("# Duplicate $n in $pod and $dups{$n}")
|
||||
if defined $dups{$n} && $dups{$n} ne $pod;
|
||||
$dups{$n} = $pod;
|
||||
}
|
||||
}
|
||||
|
||||
return %return;
|
||||
}
|
||||
|
||||
# Map of documented functions; function => manpage
|
||||
my %docced;
|
||||
# Map of links in each POD file; filename => [ "foo(1)", "bar(3)", ... ]
|
||||
my %link_map = ();
|
||||
# Map of names in each POD file; "name(s)" => filename
|
||||
@@ -589,6 +605,11 @@ sub loadmissing($)
|
||||
}
|
||||
close FH;
|
||||
|
||||
for (@missing) {
|
||||
err("$missingfile:", "$_ is documented in $name_map{$_}")
|
||||
if exists $name_map{$_} && defined $name_map{$_};
|
||||
}
|
||||
|
||||
return @missing;
|
||||
}
|
||||
|
||||
@@ -613,17 +634,18 @@ sub checkmacros {
|
||||
open(IN, $f) || die "Can't open $f, $!";
|
||||
while ( <IN> ) {
|
||||
next unless /^#\s*define\s*(\S+)\(/;
|
||||
my $macro = $1;
|
||||
next if $docced{$macro} || defined $seen{$macro};
|
||||
next if $macro =~ /i2d_/
|
||||
|| $macro =~ /d2i_/
|
||||
|| $macro =~ /DEPRECATEDIN/
|
||||
|| $macro =~ /IMPLEMENT_/
|
||||
|| $macro =~ /DECLARE_/;
|
||||
my $macro = "$1(3)"; # We know they're all in section 3
|
||||
next if exists $name_map{$macro} || defined $seen{$macro};
|
||||
next if $macro =~ /^i2d_/
|
||||
|| $macro =~ /^d2i_/
|
||||
|| $macro =~ /^DEPRECATEDIN/
|
||||
|| $macro =~ /\Q_fnsig(3)\E$/
|
||||
|| $macro =~ /^IMPLEMENT_/
|
||||
|| $macro =~ /^_?DECLARE_/;
|
||||
|
||||
# Skip macros known to be missing
|
||||
next if $opt_v && grep( /^$macro$/, @missing);
|
||||
|
||||
next if $opt_v && grep( /^\Q$macro\E$/, @missing);
|
||||
|
||||
err("$f:", "macro $macro undocumented")
|
||||
if $opt_d || $opt_e;
|
||||
$count++;
|
||||
@@ -647,13 +669,14 @@ sub printem {
|
||||
my @missing = loadmissing($missingfile) if ( $opt_v );
|
||||
|
||||
foreach my $func ( parsenum($numfile) ) {
|
||||
next if $docced{$func} || defined $seen{$func};
|
||||
$func .= '(3)'; # We know they're all in section 3
|
||||
next if exists $name_map{$func} || defined $seen{$func};
|
||||
|
||||
# Skip ASN1 utilities
|
||||
next if $func =~ /^ASN1_/;
|
||||
|
||||
# Skip functions known to be missing
|
||||
next if $opt_v && grep( /^$func$/, @missing);
|
||||
# Skip functions known to be missing.
|
||||
next if $opt_v && grep( /^\Q$func\E$/, @missing);
|
||||
|
||||
err("$libname:", "function $func undocumented")
|
||||
if $opt_d || $opt_e;
|
||||
@@ -671,42 +694,21 @@ sub collectnames {
|
||||
my $section = $1;
|
||||
my $simplename = basename($filename, ".pod");
|
||||
my $id = "${filename}:1:";
|
||||
my %podinfo = extract_pod_info($filename, { debug => $debug });
|
||||
|
||||
my $contents = '';
|
||||
{
|
||||
local $/ = undef;
|
||||
open POD, $filename or die "Couldn't open $filename, $!";
|
||||
$contents = <POD>;
|
||||
close POD;
|
||||
unless ( grep { $simplename eq $_ } @{$podinfo{names}} ) {
|
||||
err($id, "$simplename not in NAME section");
|
||||
push @{$podinfo{names}}, $simplename;
|
||||
}
|
||||
|
||||
$contents =~ /=head1 NAME([^=]*)=head1 /ms;
|
||||
my $tmp = $1;
|
||||
unless ( defined $tmp ) {
|
||||
err($id, "weird name section");
|
||||
return;
|
||||
}
|
||||
$tmp =~ tr/\n/ /;
|
||||
$tmp =~ s/ -.*//g;
|
||||
|
||||
my @names =
|
||||
map { s|/|-|g; $_ } # Treat slash as dash
|
||||
map { s/^\s+//g; s/\s+$//g; $_ } # Trim prefix and suffix blanks
|
||||
split(/,/, $tmp);
|
||||
unless ( grep { $simplename eq $_ } @names ) {
|
||||
err($id, "missing $simplename");
|
||||
push @names, $simplename;
|
||||
}
|
||||
foreach my $name (@names) {
|
||||
foreach my $name (@{$podinfo{names}}) {
|
||||
next if $name eq "";
|
||||
if ( $name =~ /\s/ ) {
|
||||
err($id, "'$name' contains white space")
|
||||
}
|
||||
err($id, "'$name' contains white space")
|
||||
if $name =~ /\s/;
|
||||
my $name_sec = "$name($section)";
|
||||
if ( !exists $name_map{$name_sec} ) {
|
||||
$name_map{$name_sec} = $filename;
|
||||
} elsif ( $filename eq $name_map{$name_sec} ) {
|
||||
err($id, "$name_sec repeated in NAME section of",
|
||||
err($id, "$name_sec duplicated in NAME section of",
|
||||
$name_map{$name_sec});
|
||||
} else {
|
||||
err($id, "$name_sec also in NAME section of",
|
||||
@@ -716,12 +718,13 @@ sub collectnames {
|
||||
|
||||
my @foreign_names =
|
||||
map { map { s/\s+//g; $_ } split(/,/, $_) }
|
||||
$contents =~ /=for\s+comment\s+foreign\s+manuals:\s*(.*)\n\n/;
|
||||
$podinfo{contents} =~ /=for\s+openssl\s+foreign\s+manuals:\s*(.*)\n\n/;
|
||||
foreach ( @foreign_names ) {
|
||||
$name_map{$_} = undef; # It still exists!
|
||||
}
|
||||
|
||||
my @links = $contents =~ /L<
|
||||
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...
|
||||
@@ -871,10 +874,14 @@ if ( $opt_c ) {
|
||||
exit $status;
|
||||
}
|
||||
|
||||
if ( $opt_l ) {
|
||||
foreach ( @ARGV ? @ARGV : glob('doc/*/*.pod doc/internal/*/*.pod') ) {
|
||||
# Preparation for some options, populate %name_map and %link_map
|
||||
if ( $opt_l || $opt_u || $opt_v ) {
|
||||
foreach ( glob('doc/*/*.pod doc/internal/*/*.pod') ) {
|
||||
collectnames($_);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $opt_l ) {
|
||||
checklinks();
|
||||
}
|
||||
|
||||
@@ -894,10 +901,6 @@ if ( $opt_n ) {
|
||||
}
|
||||
|
||||
if ( $opt_u || $opt_v) {
|
||||
my %temp = getdocced('doc/man3');
|
||||
foreach ( keys %temp ) {
|
||||
$docced{$_} = $temp{$_};
|
||||
}
|
||||
if ( $opt_o ) {
|
||||
printem('crypto', 'util/libcrypto.num', 'util/missingcrypto111.txt');
|
||||
printem('ssl', 'util/libssl.num', 'util/missingssl111.txt');
|
||||
|
||||
Reference in New Issue
Block a user