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);
  };
  
  
  

Reply via email to