- Re-cloned zonemaster-ldns with --recurse-submodules so the bundled ldns C library source (including Changelog and configure.ac) is present - Added autoconf, automake, libtool to Dockerfile.backend ldns-build stage so libtoolize + autoreconf can generate ldns/configure during make Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
342 lines
8.1 KiB
Perl
Executable File
342 lines
8.1 KiB
Perl
Executable File
#!/usr/bin/env perl
|
|
|
|
# Doxygen is useful for html documentation, but sucks
|
|
# in making manual pages. Still tool also parses the .h
|
|
# files with the doxygen documentation and creates
|
|
# the man page we want
|
|
#
|
|
# 2 way process
|
|
# 1. All the .h files are processed to create in file in which:
|
|
# filename | API | description | return values
|
|
# are documented
|
|
# 2. Another file is parsed which states which function should
|
|
# be grouped together in which manpage. Symlinks are also created.
|
|
#
|
|
# With this all in place, all documentation should be autogenerated
|
|
# from the doxydoc.
|
|
|
|
use Getopt::Std;
|
|
|
|
my $state;
|
|
my $description;
|
|
my $struct_description;
|
|
my $key;
|
|
my $return;
|
|
my $param;
|
|
my $api;
|
|
my $const;
|
|
|
|
my %description;
|
|
my %api;
|
|
my %return;
|
|
my %options;
|
|
my %manpages;
|
|
my %see_also;
|
|
|
|
my $BASE="doc/man";
|
|
my $MAN_SECTION = "3";
|
|
my $MAN_HEADER = ".ad l\n.TH ldns $MAN_SECTION \"30 May 2006\"\n";
|
|
my $MAN_MIDDLE = ".SH AUTHOR
|
|
The ldns team at NLnet Labs.
|
|
|
|
.SH REPORTING BUGS
|
|
Please report bugs to dns-team\@nlnetlabs.nl or on
|
|
GitHub at https://github.com/NLnetLabs/ldns/issues
|
|
|
|
.SH COPYRIGHT
|
|
Copyright (c) 2004 - 2006 NLnet Labs.
|
|
.PP
|
|
Licensed under the BSD License. There is NO warranty; not even for
|
|
MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE.
|
|
";
|
|
my $MAN_FOOTER = ".SH REMARKS
|
|
This manpage was automatically generated from the ldns source code.
|
|
";
|
|
|
|
getopts("em:",\%options);
|
|
# if -m manpage file is given process that file
|
|
# parse the file which tells us what manpages go together
|
|
my $functions, $see_also, $shorts;
|
|
my $i = 0;
|
|
my $report_errors = defined $options{'e'};
|
|
my $errors = 0;
|
|
my %unique;
|
|
|
|
if (defined $options{'m'}) {
|
|
# process
|
|
open(MAN, "<$options{'m'}") or die "Cannot open $options{'m'}";
|
|
# it's line based:
|
|
# func1, func2, .. | see_also1, see_also2, ...
|
|
while(<MAN>) {
|
|
chomp;
|
|
$i += 1;
|
|
if (/^#/) { next; }
|
|
if (/^$/) { next; }
|
|
my @parts = split /[\t ]*\|[\t ]*/, $_;
|
|
$functions = shift @parts;
|
|
@parts = split /[\t ]*-[\t ]*/, join ', ', @parts;
|
|
$see_also = shift @parts;
|
|
if (! $see_also) {
|
|
@parts = split /[\t ]*-[\t ]*/, $_;
|
|
$functions = shift @parts;
|
|
}
|
|
#print "{$functions}\n";
|
|
#print "{$see_also}\n";
|
|
my @funcs = split /[\t ]*,[\t ]*/, $functions;
|
|
my @also = split /[\t ]*,[\t ]*/, $see_also;
|
|
$manpages{$funcs[0]} = \@funcs;
|
|
$see_also{$funcs[0]} = \@also;
|
|
$shorts{$funcs[0]} = join '', @parts;
|
|
foreach (@funcs) {
|
|
if ($unique{$_}) {
|
|
push @{$unique{$_}}, ($i,);
|
|
} else {
|
|
$unique{$_} = [$i];
|
|
}
|
|
}
|
|
#print "[", $funcs[0], "]\n";
|
|
}
|
|
close(MAN);
|
|
while (($func, $lines) = each %unique ) {
|
|
if (scalar @$lines > 1) {
|
|
print STDERR "$func in function_manpages on lines: "
|
|
. join(", ",@$lines) . "\n" if $report_errors;
|
|
$errors += 1;
|
|
}
|
|
}
|
|
} else {
|
|
print "Need -m file to process the .h files\n";
|
|
exit 1;
|
|
}
|
|
|
|
# 0 - somewhere in the file
|
|
# 1 - in a doxygen par
|
|
# 2 - after doxygen, expect function
|
|
|
|
# create our pwd
|
|
mkdir "doc";
|
|
mkdir "doc/man";
|
|
mkdir "doc/man/man$MAN_SECTION";
|
|
|
|
$state = 0;
|
|
$i = 0;
|
|
my @lines = <STDIN>;
|
|
my $max = @lines;
|
|
|
|
while($i < $max) {
|
|
$typedef = "";
|
|
if ($lines[$i] =~ /^typedef struct/ and $lines[$i + 1] =~ /^struct/) {
|
|
# move typedef to below struct
|
|
$typedef = $lines[$i];
|
|
$j = $i;
|
|
while ($lines[$j] !~ /}/) {
|
|
$lines[$j] = $lines[$j+1];
|
|
$j++;
|
|
}
|
|
$lines[$j] = $lines[$j+1];
|
|
$lines[$j + 1] = $typedef;
|
|
}
|
|
|
|
$cur_line = $lines[$i];
|
|
chomp($cur_line);
|
|
if ($cur_line =~ /^\/\*\*[\t ]*$/) {
|
|
# /** Seen
|
|
#print "Comment seen! [$cur_line]\n";
|
|
$state = 1;
|
|
undef $description;
|
|
undef $struct_description;
|
|
$i++;
|
|
next;
|
|
}
|
|
if ($cur_line =~ /\*\// and $state == 1) {
|
|
#print "END Comment seen!\n";
|
|
if ($description =~ /^\\\\file/mg) {
|
|
# Doxygen text for the file, do not expect
|
|
# a function coming.
|
|
#
|
|
$state = 0;
|
|
} else {
|
|
$state = 2;
|
|
}
|
|
$i++;
|
|
next;
|
|
}
|
|
|
|
if ($state == 1) {
|
|
# inside doxygen
|
|
$cur_line =~ s/\\/\\\\/g;
|
|
$cur_line =~ s/^[ \t]*\* ?//;
|
|
$description = $description . "\n" . $cur_line;
|
|
#$description = $description . "\n.br\n" . $cur_line;
|
|
}
|
|
if ($state == 2 and $cur_line =~ /const/) {
|
|
# the const word exists in the function call
|
|
#$const = "const";
|
|
#s/[\t ]*const[\t ]*//;
|
|
} else {
|
|
#undef $const;
|
|
}
|
|
|
|
if ($cur_line =~ /^INLINE/) {
|
|
$cur_line =~ s/^INLINE\s*//;
|
|
while ($cur_line !~ /{/) {
|
|
$i++;
|
|
$cur_line .= " ".$lines[$i];
|
|
$cur_line =~ s/\n//;
|
|
}
|
|
$cur_line =~ s/{/;/;
|
|
}
|
|
|
|
if ($cur_line =~ /^[^#*\/ ]([\w\*]+)[\t ]+(.*?)[({](.*)\s*/ and $state == 2) {
|
|
while ($cur_line !~ /\)\s*;/) {
|
|
$i++;
|
|
$cur_line .= $lines[$i];
|
|
chomp($cur_line);
|
|
$cur_line =~ s/\n/ /g;
|
|
$cur_line =~ s/\s\s*/ /g;
|
|
}
|
|
$cur_line =~ /([\w\* ]+)[\t ]+(.*?)\((.*)\)\s*;/;
|
|
# this should also end the current comment parsing
|
|
$return = $1;
|
|
$key = $2;
|
|
$api = $3;
|
|
# sometimes the * is stuck to the function
|
|
# name instead to the return type
|
|
if ($key =~ /^\*/) {
|
|
#print"Name starts with *\n";
|
|
$key =~ s/^\*//;
|
|
if (defined($const)) {
|
|
$return = $const . " " . $return . '*';
|
|
} else {
|
|
$return = $return . '*';
|
|
}
|
|
}
|
|
$description =~ s/\\param\[in\][ \t]*([\*\w]+)[ \t]+/.br\n\\fB$1\\fR: /g;
|
|
$description =~ s/\\param\[out\][ \t]*([\*\w]+)[ \t]+/.br\n\\fB$1\\fR: /g;
|
|
$description =~ s/\\return[ \t]*/.br\nReturns /g;
|
|
|
|
# Delete leading spaces to prevent manpages to be ascii format-
|
|
# ted and enable justification of text.
|
|
#
|
|
$description =~ s/^[ \t]*//mg;
|
|
|
|
# Prevent hyphening of all caps and underscore words
|
|
$description =~ s/\b([A-Z_]+)\b/\\%$1/g;
|
|
|
|
$description{$key} = $description;
|
|
$api{$key} = $api;
|
|
$return{$key} = $return;
|
|
undef $description;
|
|
undef $struct_description;
|
|
$state = 0;
|
|
} elsif ($state == 2 and (
|
|
$cur_line =~ /^typedef\sstruct\s(\w+)\s(\w+);/ or
|
|
$cur_line =~ /^typedef\senum\s(\w+)\s(\w+);/)) {
|
|
$struct_description .= "\n.br\n" . $cur_line;
|
|
$key = $2;
|
|
$struct_description =~ s/\/\*\*\s*(.*?)\s*\*\//\\fB$1:\\fR/g;
|
|
$description{$key} = $struct_description;
|
|
$api{$key} = "struct";
|
|
$return{$key} = $1;
|
|
undef $description;
|
|
undef $struct_description;
|
|
$state = 0;
|
|
} else {
|
|
$struct_description .= "\n.br\n" . $cur_line;
|
|
}
|
|
$i++;
|
|
}
|
|
|
|
# create the manpages
|
|
foreach (keys %manpages) {
|
|
$name = $manpages{$_};
|
|
$also = $see_also{$_};
|
|
my $shrt = $shorts{$_};
|
|
|
|
$filename = @$name[0];
|
|
$filename = "$BASE/man$MAN_SECTION/$filename.$MAN_SECTION";
|
|
|
|
my $symlink_file = @$name[0] . "." . $MAN_SECTION;
|
|
|
|
# print STDOUT $filename,"\n";
|
|
open (MAN, ">$filename") or die "Can not open $filename";
|
|
|
|
print MAN $MAN_HEADER;
|
|
print MAN ".SH NAME\n";
|
|
print MAN join ", ", @$name;
|
|
if ($shrt) {
|
|
print MAN " \\- $shrt";
|
|
}
|
|
print MAN "\n\n";
|
|
print MAN ".SH SYNOPSIS\n";
|
|
|
|
print MAN "#include <stdint.h>\n.br\n";
|
|
print MAN "#include <stdbool.h>\n.br\n";
|
|
|
|
print MAN ".PP\n";
|
|
print MAN "#include <ldns/ldns.h>\n";
|
|
print MAN ".PP\n";
|
|
|
|
foreach (@$name) {
|
|
$b = $return{$_};
|
|
$b =~ s/\s+$//;
|
|
if ($api{$_} ne "struct") {
|
|
print MAN $b, " ", $_;
|
|
print MAN "(", $api{$_},");\n";
|
|
print MAN ".PP\n";
|
|
}
|
|
}
|
|
|
|
print MAN "\n.SH DESCRIPTION\n";
|
|
foreach (@$name) {
|
|
print MAN ".HP\n";
|
|
print MAN "\\fI", $_, "\\fR";
|
|
if ($api{$_} ne "struct") {
|
|
print MAN "()";
|
|
}
|
|
# print MAN ".br\n";
|
|
print MAN $description{$_};
|
|
print MAN "\n.PP\n";
|
|
}
|
|
|
|
print MAN $MAN_MIDDLE;
|
|
|
|
if (@$also) {
|
|
print MAN "\n.SH SEE ALSO\n\\fI";
|
|
print MAN join "\\fR, \\fI", @$also;
|
|
print MAN "\\fR.\nAnd ";
|
|
print MAN "\\fBperldoc Net::DNS\\fR, \\fBRFC1034\\fR,
|
|
\\fBRFC1035\\fR, \\fBRFC4033\\fR, \\fBRFC4034\\fR and \\fBRFC4035\\fR.\n";
|
|
} else {
|
|
print MAN ".SH SEE ALSO
|
|
\\fBperldoc Net::DNS\\fR, \\fBRFC1034\\fR,
|
|
\\fBRFC1035\\fR, \\fBRFC4033\\fR, \\fBRFC4034\\fR and \\fBRFC4035\\fR.\n";
|
|
}
|
|
|
|
print MAN $MAN_FOOTER;
|
|
|
|
# create symlinks
|
|
chdir("$BASE/man$MAN_SECTION");
|
|
foreach (@$name) {
|
|
print STDOUT $_,"\n";
|
|
my $new_file = $_ . "." . $MAN_SECTION;
|
|
if ($new_file eq $symlink_file) {
|
|
next;
|
|
}
|
|
#print STDOUT "\t", $new_file, " -> ", $symlink_file, "\n";
|
|
symlink $symlink_file, $new_file;
|
|
}
|
|
chdir("../../.."); # and back, tricky and fragile...
|
|
close(MAN);
|
|
}
|
|
foreach (keys %api) {
|
|
next if (/ / || /^$/);
|
|
if (not $unique{$_}) {
|
|
print STDERR "no man page for $_\n" if $report_errors;
|
|
#$errors += 1;
|
|
}
|
|
}
|
|
|
|
exit ($report_errors and $errors != 0);
|