Mailing List Archive

cvs commit: apache-devsite/apidoc mkapidict
coar 98/05/03 13:00:23

Added: apidoc mkapidict
Log:
This is the Perl script that turns the api-dict.html template,
the api.list definition file, and the dict-*.html entity
documentation files into a single monolithic cross-referenced
dictionary.

Revision Changes Path
1.1 apache-devsite/apidoc/mkapidict

Index: mkapidict
===================================================================
#!/usr/local/bin/perl
#
# Read from STDIN, produce HTML. Simple, really. The first argument on the
# command line ($ARGV[0]) is the name of the file which provides the
# framework into which the generated text is inserted.
#
# Edit history:
#
# 1998-05-03 Ken Coar
# Cleaned up a little bit, from horrible to bad, before checking in to
# CVS.
# 1998-04-?? Ken Coar
# Prototyped..
#

if (! $ARGV[0]) {
print "Template file must be specified.\n";
die ("missing required input.");
};

$InFile = $ARGV[0];
$OutFile = "$ARGV[0].bak";

%Routine = ();
%Constant = ();
%Structure = ();
%Cell = ();
%Entity = ();
%SeeAlso = ();
@Prologue = ();
@Epilogue = ();

#
#
# Just in case the input template was the output from a previous run,
# save it in case *this* run doesn't work as expected.
#
# Now copy the input file to a backup, extracting the prologue and
# epilogue sections as we go.
#
open INFILE, "<$InFile" || dir ("Can't open input file $InFile");
open OUTFILE, ">$OutFile" || die ("Can't open output file $OutFile");
$state = 1;
while ($line = <INFILE>) {
print OUTFILE $line;
if ($state == 1) {
push (@Prologue, $line);
} elsif ($state == 2) {
push (@Epilogue, $line);
};
if ($line =~ m:<!--.*%%BEGIN%%.*-->:) {
$state = 0;
} elsif ($line =~ m:<!--.*%%END%%.*-->:) {
push (@Epilogue, $line);
$state = 2;
};
};
close INFILE;
close OUTFILE;

$DataLine = 0;

while (! eof(STDIN)) {
local (@field) = ("", "", "", "", "", "", "", "");
local ($rec);

$rec = &get_record(1);
next if (! $rec);
chomp($rec);
@field = split(m:\|:, $rec);
$rec =~ s:\$\*:$field[1]:g;
@field = split(m:\|:, $rec);
if ($field[0] !~ m:^[RSCDX]$:i) {
print STDERR "Unrecognised record identifier /$field[0]/ ",
"for record ending on line $DataLine;\n",
"\tmissing continuation character?\n";
next;
};
if ($Entity{$field[1]}) {
print STDERR "Entity $field[1] redefined at line $DataLine.\n";
};
$Entity{$field[1]} = 1;
if ($field[0] =~ /R/i) {
$Routine{$field[1]} = $rec;
} elsif ($field[0] =~ /S/i) {
$Structure{$field[1]} = $rec;
} elsif ($field[0] =~ /C/i) {
$Constant{$field[1]} = $rec;
} elsif ($field[0] =~ /D/i) {
$Cell{$field[1]} = $rec;
} elsif ($field[0] =~ /X/i) {
$SeeAlso{$field[1]} = $field[4];
};
};

#
# Done reading in the input.. time to make the doughnuts.
#
print @Prologue;
print <<EOHT;
<H2>Table of Contents</H2>
<UL>
<LI><A HREF="#Routines">Routine Descriptions</A>
</LI>
<LI><A HREF="#Structures">Data Structure Definitions</A>
</LI>
<LI><A HREF="#Cells">Global Data Cells</A>
</LI>
<LI><A HREF="#Constants">Constant Definitions</A>
</LI>
</UL>
<HR>
EOHT

print <<EOHT;
<H2>
<A NAME="Routines">
Routine Descriptions
</A>
</H2>
<HR>
EOHT
&dump_list(%Routine);

print <<EOHT;
<H2>
<A NAME="Structures">
Data Structure Definitions
</A>
</H2>
<HR>
EOHT
&dump_list(%Structure);

print <<EOHT;
<H2>
<A NAME="Cells">
Global Data Cells
</A>
</H2>
<HR>
EOHT
&dump_list(%Cell);

print <<EOHT;
<H2>
<A NAME="Constants">
Constant Definitions
</A>
</H2>
<P>
Many of the compile-time choices are determined by the settings of
various constants created with <CODE>#define</CODE> statements.
Things like the maximum size of fixed-length buffers, the server
version string, and operating system-specific code fragment compilation
are controlled by constants.
</P>
<P>
Some of the Apache Web server's constants (such as
<A HREF="#SERVER_VERSION"><SAMP>SERVER_VERSION</SAMP></A>)
can be overridden with
compile-time definitions on the compiler command line. Others, like
<A HREF="#MAX_STRING_LEN"><SAMP>MAX_STRING_LEN</SAMP></A>,
are provided as conveniences, and shouldn't be modified except under
special circumstances. Still others, such as
<A HREF="#OR_LIMIT"><SAMP>OR_LIMIT</SAMP></A>,
have specific values that <STRONG>must not</STRONG> be altered.
</P>
<HR>
EOHT
&dump_list(%Constant);
print @Epilogue;

#
# Dump a hash in alphabetical order.
#
sub dump_list {
local (%list) = @_;
local (@keys) = sort {uc($a) cmp uc($b)} (keys(%list));

foreach $key (@keys) {
my ($edited, $iname, $idef, $isamp, $iref, $idesc) =
split(m:\|:, $list{$key});
print <<EOHT;
<H3>
<A NAME="$iname">
$iname
</A>
</H3>
EOHT
$edited = &edit_inline($idef, $iname);
if (! $edited) {
$edited = "No prototype or definition available.";
};
print <<EOHT;
<P>
Definition:
</P>
<DL>
<DD>
<PRE>
$edited
</PRE>
</DD>
</DL>
EOHT
$edited = &edit_inline($isamp, $iname);
if (! $edited) {
$edited = "No examples available.";
};
print <<EOHT;
<P>
Usage example:
</P>
<DL>
<DD>
<PRE>
$edited
</PRE>
</DD>
</DL>
EOHT
if (! $idesc) {
print <<EOHT;
<P>
No documentation available.
</P>
EOHT
} elsif (! -r $idesc) {
print <<EOHT;
<P>
Documentation file not accessible.
</P>
EOHT
} else {
open DFILE, "<$idesc";
print <DFILE>;
close (DFILE);
};
$edited = $iref;
$edited =~ s/[\s,]//g;
if ($edited) {
local ($ref) = $iref;
local ($ref_list) = " <DD>";
local ($sees) = "";

$ref =~ s/\s+//g;
print <<EOHT;
<DL COMPACT>
<DT><EM>See also:</EM>
</DT>
EOHT
#
# Expand any aliased 'see-also' entries.
#
foreach (split(m:,:, $ref)) {
if ($SeeAlso{$_}) {
$sees .= ",$SeeAlso{$_}";
} else {
$sees .= ",$_";
};
};
$ref = $sees;
foreach (sort(split(m:,:, $ref))) {
local ($item) = "<SAMP>$_</SAMP>";

next if (($_ eq "") || ($_ eq $iname));
if ($Entity{$_}) {
$item = "<A HREF=\"#$_\">$item</A>";
} else {
print STDERR "$iname cross-references to undefined ";
print STDERR "entity $_.\n";
};
$ref_list .= $item . ",\n ";
};
$ref_list =~ s:,\n $:\n:;
print $ref_list;
print <<EOHT;
</DD>
</DL>
EOHT
};
print " <HR>\n";
};
};

#
# Turn any inline references to other structures or constants into links.
#
sub edit_inline {
local ($wip, $rname) = @_;
local ($ref);

foreach $ref (keys(%Entity)) {
if ($ref ne $rname) {
$wip =~ s:\b$ref\b:<A HREF="#$ref">$ref</A>:g;
};
};
return $wip;
};

#
# Read a record from the input stream. Comments are trimmed, as is
# trailing whitespace. Leading whitespace is trimmed IFF the argument to the
# functional evaluates as true. A terminal slosh indicates that the next
# line should be read and the record re-processed. All '\n' occurrences
# in the input are converted to newlines before being returned.
#
sub get_record {
local ($trim_leading_ws) = @_;
local ($trim_next) = 1;
my ($line);

$line = <STDIN> || return "";
$DataLine++;
chomp ($line);
$line =~ s/#;.*//;
$line =~ s/\s+$//;
if ($trim_leading_ws) {
$line =~ s/^\s+//;
};
if ($line =~ m:\\$:) {
$line =~ s:\\n\s+\\$:\\n\\:;
$line =~ s:\\$::;
$trim_next = 0 if ($line =~ m:\\n$:);
$line .= &get_record($trim_next);
};
$line =~ s:\\n:\n:g;
return ($line);
};