summaryrefslogtreecommitdiff
path: root/doc/doxyparse.pl
diff options
context:
space:
mode:
Diffstat (limited to 'doc/doxyparse.pl')
-rwxr-xr-xdoc/doxyparse.pl344
1 files changed, 344 insertions, 0 deletions
diff --git a/doc/doxyparse.pl b/doc/doxyparse.pl
new file mode 100755
index 0000000..66c846a
--- /dev/null
+++ b/doc/doxyparse.pl
@@ -0,0 +1,344 @@
+#!/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. Which consists out of
+Jelte Jansen and Miek Gieben.
+
+.SH REPORTING BUGS
+Please report bugs to ldns-team\@nlnetlabs.nl or in
+our bugzilla at
+http://www.nlnetlabs.nl/bugs/index.html
+
+.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 by
+use of Doxygen and some perl.
+";
+
+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);