home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / misc / adoc / source / gencode.c < prev    next >
C/C++ Source or Header  |  1995-04-13  |  16KB  |  737 lines

  1. /*                                                               -*- C -*-
  2.  *  GENCODE.C
  3.  *
  4.  *  (c)Copyright 1995 by Tobias Ferber,  All Rights Reserved.
  5.  *
  6.  *  This file is part of ADOC.
  7.  *
  8.  *  ADOC is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published
  10.  *  by the Free Software Foundation; either version 1 of the License,
  11.  *  or (at your option) any later version.
  12.  *
  13.  *  ADOC is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. /* $VER: $Id: gencode.c,v 1.15 1995/04/13 21:10:55 tf Exp $ */
  24.  
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30.  
  31. #include "libfun.h"
  32. #include "adoc.h"
  33.  
  34. /* texinfo sepeator for library and function name (used in @node and @xref) */
  35.  
  36. /* makeinfo has a problem when using "." or ":" or "/" here... */
  37. #define CHAPSEC " "
  38.  
  39. /* convert tabs in `s' to spaces with a tab step of `ts' */
  40.  
  41. static void fexpand(FILE *fp, int ts, char *s)
  42. {
  43.   int column= 0;
  44.  
  45.   while(*s)
  46.   {
  47.     switch(*s)
  48.     {
  49.       case '\n':
  50.         fputc(*s,fp);
  51.         column= 0;
  52.         break;
  53.  
  54.       case '\t':
  55.         /*do { fputc(' ',fp); } while( (++column) % ts);*/
  56.         do { fputc(' ',fp); ++column; } while(column % ts);
  57.         break;
  58.  
  59.      default:
  60.        fputc(*s,fp);
  61.        ++column;
  62.        break;
  63.     }
  64.     ++s;
  65.   }
  66. }
  67.  
  68.  
  69. /*
  70. **  AUTODOCS
  71. */
  72.  
  73. int gen_autodoc_toc(FILE *fp)
  74. {
  75.   char *fun;
  76.  
  77.   fprintf(fp,"TABLE OF CONTENTS\n\n");
  78.  
  79.   for(fun= stepfun(0); fun; fun= stepfun(1))
  80.     fprintf(fp,"%s\n",fun);
  81.  
  82.   return 0;
  83. }
  84.  
  85.  
  86. int gen_autodoc(FILE *fp, int cols, int tabsize, int flags, char **body_macros)
  87. {
  88.   int err= 0;
  89.  
  90.   char *fun, *sec, *text;
  91.  
  92.   for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  93.   {
  94.     if(flags & ADOC_FORM_FEEDS)
  95.       fputc('\f',fp);
  96.  
  97.     fprintf(fp,"%s%*s\n\n",fun,(int)(cols-strlen(fun)),fun);
  98.  
  99.     for(sec= stepsec(0); sec && (err==0); sec= stepsec(1))
  100.     {
  101.       /* indent the section heading with 3 spaces */
  102.       if(*sec)
  103.         fprintf(fp,"   %s\n",sec);
  104.  
  105.       if( (text= getsec(sec)) )
  106.       {
  107.         if(text && *text)
  108.         {
  109.           char *x= strexpand(text, body_macros);
  110.  
  111.           if(x)
  112.           {
  113.             if(tabsize > 0)
  114.               fexpand(fp,tabsize,x);
  115.  
  116.             else
  117.               fputs(x,fp);
  118.  
  119.             free(x);
  120.           }
  121.           else err= __LINE__;
  122.         }
  123.  
  124.         fputc('\n',fp);
  125.       }
  126.     }
  127.   }
  128.  
  129.   return err;
  130. }
  131.  
  132.  
  133. /*
  134. **  TEXINFO
  135. */
  136.  
  137.  
  138. /* split `fun' into `chapter' and `section'.
  139.    the string returned by this function has to be disposed via free() by the caller */
  140.  
  141. static char *chapsec(char *fun, char **chapter, char **section)
  142. {
  143.   char *c= strdup(fun);
  144.   char *s= (char *)0;
  145.  
  146.   if(c)
  147.   {
  148.     if( (s= strchr(c,'/')) )
  149.       *s++= '\0';
  150.   }
  151.  
  152.   *chapter= c;
  153.   *section= s;
  154.  
  155.   return c;
  156. }
  157.  
  158. /*
  159.  *  The implementation of references in Texinfo are perfectly silly :'(
  160.  *  Instead of offering one simple reference macro, Texinfo comes up
  161.  *  with context-sensitive @ref{}, @xref{}, @pref{}, ... and prints
  162.  *  a `See ...' or `See also ...' right in front of it...
  163.  */
  164.  
  165. static int see_also(FILE *fp, char *refs, int flags)
  166. {
  167.   int err= 0;
  168.   char *buf= strdup(refs);
  169.  
  170. #define isref(c) ( ('A'<=(c) && (c)<='Z') || \
  171.                    ('a'<=(c) && (c)<='z') || \
  172.                    ('0'<=(c) && (c)<='9') || ((c)=='_') || ((c)=='-') || ((c)=='/') || ((c)=='.') )
  173.  
  174.   if(buf)
  175.   {
  176.     /* make `s' the working pointer in `buf' */
  177.     char *s= buf;
  178.  
  179.     /*
  180.      *  former revisions of ADOC used to indent the parsed references
  181.      *  by the same amount of white space as the first.  Actually we
  182.      *  do not indent them amymore, so out it goes....
  183.      */
  184.  
  185.     /* indentation string of the first reference */
  186. #if 0
  187.     char *indent= (char *)0;
  188. #endif
  189.  
  190.     int num_refs= 0;
  191.  
  192.     while( *s && (err==0) )
  193.     {
  194.       char *l, *r;
  195.  
  196.       /* move `l' and `r' to the left and right end of a reference in `s' */
  197.  
  198.       for(l=s; *l && !isref(*l); l++) ;
  199.       for(r=l; *r &&  isref(*r); r++) ;
  200.  
  201.       /* terminate the reference string with a '\0' */
  202.       if(*r) *r++= '\0';
  203.  
  204.       /* save the indentation of the first reference */
  205. #if 0
  206.       if(num_refs == 0)
  207.       {
  208.         if( (indent= strdup(s)) )
  209.         {
  210.           char *t= indent;
  211.  
  212.           while(*t==' ' || *t=='\t')
  213.             ++t;
  214.  
  215.           *t= '\0';
  216.         }
  217.         else err= __LINE__;
  218.       }
  219. #endif
  220.  
  221.       /* move `s' behind the reference */
  222.       s= r;
  223.  
  224.       if( *l && (err==0) )
  225.       {
  226.         /* look for a function `l' and initialize `fun' to it's name */
  227.         char *fun= (char *)0;
  228.  
  229. /*fprintf(stderr,"--> @ref{%s} ?\n",l);*/
  230.  
  231.         if( getfun(l) )
  232.           fun= strdup(l);
  233.  
  234.         else if( !strchr(l,'/') )
  235.         {
  236.       if( islib(l) )
  237.         fun= strdup(l);
  238.  
  239.       else
  240.       {
  241.             /*
  242.              *  Okay, we tried it the easy way but perhaps this is a reference
  243.              *  into the library without the library name in front of it.
  244.              *  Let's try appending `l' to the the current library name...
  245.              */
  246.  
  247.             char *f= getfun( (char *)0 );
  248.  
  249.             if(f)
  250.             {
  251.               char *x, *xl, *xr;
  252.  
  253.               if( (x= chapsec(f, &xl, &xr)) )
  254.               {
  255.                 size_t len= strlen(xl) + 1 + strlen(l) + 1;
  256.                 char *y= (char *)malloc( len * sizeof(char) );
  257.  
  258.                 if(y)
  259.                 {
  260.                   sprintf(y,"%s/%s",xl,l);
  261.  
  262. /*fprintf(stderr,"--> @ref{%s} ?\n",y);*/
  263.  
  264.                   if( getfun(y) )
  265.                     fun= strdup(y);
  266.  
  267.                   free(y);
  268.                 }
  269.                 else err= __LINE__;
  270.  
  271.                 free(x);
  272.               }
  273.               else err= __LINE__;
  274.             }
  275.             else /* no current function? */
  276.               err= __LINE__;
  277.       }
  278.         }
  279.  
  280.         if(err == 0)
  281.         {
  282.           /* print the reference */
  283.  
  284.           if( fun )
  285.           {
  286.             char *cs, *chapter, *section;
  287.  
  288.             if( (cs= chapsec(fun, &chapter, §ion)) )
  289.             {
  290.               if(flags & TEXI_ITEMIZE_REFERENCES)
  291.               {
  292.                 if(num_refs==0)
  293.                   fprintf(fp,"@itemize\n");
  294.  
  295.         if(section)  fprintf(fp,"@item\n@xref{%s%s%s}.\n",chapter,CHAPSEC,section);
  296.         else         fprintf(fp,"@item\n@xref{%s}.\n",chapter);
  297.               }
  298.               else /* not itemized */
  299.               {
  300.                 if( (num_refs==0) && (flags & TEXI_GROUP_SECTIONS) )
  301.                   fprintf(fp,"@group\n");
  302.  
  303.         fprintf(fp,"%s",(num_refs==0) ? "@*@xref" : "@ref");
  304.  
  305.         if(section)  fprintf(fp,"{%s%s%s},\n",chapter,CHAPSEC,section);
  306.         else         fprintf(fp,"{%s},\n",chapter);
  307.               }
  308.  
  309.               free(cs);
  310.             }
  311.             else err= __LINE__;
  312.  
  313.             free(fun);
  314.           }
  315.           else /* !fun */
  316.           {
  317.             if(flags & TEXI_ITEMIZE_REFERENCES)
  318.             {
  319.               if(num_refs==0)
  320.                 fprintf(fp,"@itemize\n");
  321.  
  322.               fprintf(fp,"@item\nSee @file{%s}\n",l);
  323.             }
  324.             else /* not itemized */
  325.             {
  326.               if( (num_refs==0) && (flags & TEXI_GROUP_SECTIONS) )
  327.                 fprintf(fp,"@group\n");
  328.  
  329.               fprintf(fp,"%s{%s},\n",((num_refs==0) ? "@*See @file":"@file"),l);
  330.             }
  331.           }
  332.  
  333.           /* now at least one reference is printed */
  334.           ++num_refs;
  335.         }
  336.       }
  337.     }
  338.  
  339.     if(num_refs > 0)
  340.     {
  341.       if(flags & TEXI_ITEMIZE_REFERENCES)
  342.         fprintf(fp,"@end itemize\n");
  343.  
  344.       else /* not itemized */
  345.       {
  346.         if(flags & TEXI_GROUP_SECTIONS)
  347.           fprintf(fp,"@end group\n");
  348.  
  349.         fprintf(fp,"for more information.\n");
  350.       }
  351.     }
  352.  
  353. #if 0
  354.     if(indent)
  355.       free(indent);
  356. #endif
  357.  
  358.     free(buf);
  359.   }
  360.   else err= __LINE__;
  361.  
  362. #undef isref
  363.  
  364.   return err;
  365. }
  366.  
  367.  
  368. int gen_texinfo_header(FILE *fp, char *fname, char **header_macros)
  369. {
  370.   int err= 0;
  371.  
  372.   char *default_header=
  373.     "\\input texinfo  @c -*-texinfo-*-\n"
  374.     "@comment %%**start of header\n"
  375.     "@setfilename PROJECT.guide\n"
  376.     "@settitle Autodocs for @code{PROJECT}\n"
  377.     "@paragraphindent 0\n"
  378.     "@iftex\n"
  379.     "@afourpaper\n"
  380.     "@finalout\n"
  381.     "@setchapternewpage on\n"  /* odd */
  382.     "@end iftex\n"
  383.     "@comment %%**end of header\n\n"
  384.     "@ifinfo\n"
  385.     "@node Top\n"
  386.     "@top\n"
  387.     "This document describes @code{PROJECT} version REVISION.\n\n"
  388.     "@noindent Copyright @copyright{} COPYRIGHT\n"
  389.     "@end ifinfo\n\n"
  390.     "@titlepage\n"
  391.     "@title PROJECT\n"
  392.     "@subtitle Documentation taken from source code\n"
  393.     "@subtitle Edition EDITION for Version REVISION\n"
  394.     "@subtitle @today\n"
  395.     "@author AUTHOR\n\n"
  396.     "@page\n"
  397.     "@vskip 0pt plus 1filll\n"
  398.     "Copyright @copyright{} COPYRIGHT\n"
  399.     "@end titlepage\n"
  400.     "@headings double\n\n";
  401.  
  402.   if(fname && *fname)
  403.   {
  404.     FILE *fh= fopen(fname,"r");
  405.  
  406.     if(fh)
  407.     {
  408.       char *header= (char *)0;
  409.       size_t header_size= 0;
  410.  
  411.       /* compute the size of the header file */
  412.  
  413. #ifdef BUGGY_FTELL
  414.  
  415.       do {
  416.  
  417.         (void)fgetc(fh);
  418.  
  419.         if(!feof(fh))
  420.           ++header_size;
  421.  
  422.       } while(!feof(fh) || ferror(fh))
  423.  
  424. #else /* ftell() works fine */
  425.  
  426.       if( fseek(fh,0L,2L) >= 0) /* 2 == OFFSET_END */
  427.         header_size= ftell(fh);
  428.  
  429.       else
  430.         err= __LINE__;
  431.  
  432. #endif /* BUGGY_FTELL */
  433.  
  434.       if(!ferror(fh) && header_size > 0)
  435.       {
  436.         if(fseek(fh,-header_size,1L) < 0) /* 1 == OFFSET_CURRENT */
  437.           err= __LINE__;
  438.       }
  439.       else err= __LINE__;
  440.  
  441.  
  442.       /* load the header */
  443.  
  444.       if(err == 0)
  445.       {
  446.         if( (header= (char *)malloc( (header_size + 1) * sizeof(char) )) )
  447.         {
  448.           fread(header, sizeof(char), header_size, fh);
  449.           header[header_size]= '\0';
  450.  
  451.           if( ferror(fh) )
  452.           {
  453.             free(header);
  454.             header= (char *)0;
  455.             err= __LINE__;
  456.           }
  457.         }
  458.         else err= __LINE__;
  459.       }
  460.  
  461.       if(err == 0)
  462.       {
  463.         char *x= strexpand(header, header_macros);
  464.  
  465.         if(x)
  466.         {
  467.           fputs(x,fp);
  468.           free(x);
  469.         }
  470.         else /* out of memory */
  471.           err= __LINE__;
  472.       }
  473.  
  474.       fclose(fh);
  475.     }
  476.   }
  477.  
  478.   else /* !fname */
  479.   {
  480.     char *x= strexpand(default_header, header_macros);
  481.  
  482.     if(x)
  483.     {
  484.       fputs(x,fp);
  485.       free(x);
  486.     }
  487.     else /* out of memory */
  488.       err= __LINE__;
  489.   }
  490.  
  491.   return err;
  492. }
  493.  
  494.  
  495.  
  496. int gen_texinfo(FILE *fp, int tabsize, int flags, char *body_environment, char **body_macros)
  497. {
  498.   int err= 0;
  499.   char *fun, *sec;
  500.  
  501.   /* main menu:
  502.      create a @menu with an entry for each library.
  503.      an additional entry will be created for the function index */
  504.  
  505.   if(err == 0)
  506.   {
  507.     char *last_chapter = (char *)0;  /* last printed chapter */
  508.     char *last_cs      = (char *)0;  /* string allocated for `last_chapter' */
  509.  
  510.     fprintf(fp,"@menu\n");
  511.  
  512.     for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  513.     {
  514.       char *cs, *chapter, *section;
  515.  
  516.       if( (cs= chapsec(fun, &chapter, §ion)) )
  517.       {
  518.         if( !last_chapter || strcmp(last_chapter, chapter) )
  519.         {
  520.           fprintf(fp,"* %s::\n", chapter);
  521.  
  522.           if(last_cs)
  523.             free(last_cs);
  524.  
  525.           last_cs      = cs;
  526.           last_chapter = chapter;
  527.         }
  528.         else
  529.           free(cs);
  530.       }
  531.       else /* out of memory */
  532.         err= __LINE__;
  533.     }
  534.  
  535.     if(last_cs)
  536.       free(last_cs);
  537.  
  538.     if( !(flags & TEXI_NO_INDEX) )
  539.       fprintf(fp, "\n"
  540.                   "* Function Index::\n");
  541.  
  542.     fprintf(fp,"@end menu\n\n");
  543.   }
  544.  
  545. #if 0
  546.  
  547.   /* create one single (flat) menu for functions mapped to
  548.      @chapters.  This code is obsolete since we introduced
  549.      the hierarchical layout with libraries mapped to
  550.      @chapters and functions mapped to @sections. */
  551.  
  552.   if(err == 0)
  553.   {
  554.     fprintf(fp,"@menu\n");
  555.  
  556.     for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  557.     {
  558.       char *cs, *chapter, *section;
  559.  
  560.       if( (cs= chapsec(fun, &chapter, §ion)) )
  561.       {
  562.         fprintf(fp,"* %s %s::\n", chapter, section);
  563.         free(cs);
  564.       }
  565.       else /* out of memory */
  566.         err= __LINE__;
  567.     }
  568.  
  569.     if( !(flags & TEXI_NO_INDEX) )
  570.       fprintf(fp, "\n"
  571.                   "* Function Index::\n");
  572.  
  573.     fprintf(fp,"@end menu\n\n");
  574.   }
  575.  
  576. #endif
  577.  
  578.   /* chapters & sections */
  579.  
  580.   if(err == 0)
  581.   {
  582.     char *last_chapter = (char *)0;
  583.     char *last_cs      = (char *)0;
  584.  
  585.     for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  586.     {
  587.       char *cs, *chapter, *section;
  588.  
  589.       if( (cs= chapsec(fun, &chapter, §ion)) )
  590.       {
  591.         if( !last_chapter || strcmp(last_chapter, chapter) )
  592.         {
  593.           /*
  594.            *  Start a new library
  595.            */
  596.  
  597.           fprintf(fp, "\n"
  598.                       "@node %s\n"
  599.                       "@chapter %s\n\n"
  600.                       ,chapter
  601.                       ,chapter
  602.           );
  603.  
  604.           /* print a sub menu for the current chapter */
  605.  
  606.           pushfun();
  607.           {
  608.             int done;
  609.             char *sub_fun;
  610.  
  611.             fprintf(fp,"@menu\n");
  612.             for(sub_fun= fun, done= 0; sub_fun && (err==0) && !done; sub_fun= stepfun(1))
  613.             {
  614.               char *sub_cs, *sub_chapter, *sub_section;
  615.  
  616.               if( (sub_cs= chapsec(sub_fun, &sub_chapter, &sub_section)) )
  617.               {
  618.                 if( (done= strcmp(sub_chapter, chapter)) == 0 )
  619.                   fprintf(fp,"* %s %s::\n", sub_chapter, sub_section);
  620.  
  621.                 free(sub_cs);
  622.               }
  623.               else err= __LINE__;
  624.             }
  625.             fprintf(fp,"@end menu\n\n");
  626.           }
  627.           popfun();
  628.  
  629.           if(last_cs)
  630.             free(last_cs);
  631.  
  632.           last_cs      = cs;
  633.           last_chapter = chapter;
  634.         }
  635.  
  636.         else /* we didn't start a new page for the chapter */
  637.         {
  638.           if(flags & TEXI_FUNCTION_NEWPAGE)
  639.             fprintf(fp,"@page\n");
  640.         }
  641.  
  642.         /*
  643.          *  Begin a new function
  644.          */
  645.  
  646.         fprintf(fp, "\n"
  647.                     "@node %s%s%s\n"
  648.                     "@section %s\n"
  649.                     "@findex %s\n"
  650.                     "\n"
  651.                     ,chapter,CHAPSEC,section
  652.                     ,section
  653.                     ,section
  654.         );
  655.  
  656.         if(flags & TEXI_TABLE_FUNCTIONS)
  657.           fprintf(fp,"@table @b\n");
  658.  
  659.         for(sec= stepsec(0); sec && (err == 0); sec= stepsec(1))
  660.         {
  661.           char *text= getsec(sec);
  662.  
  663.           if(text && *text)
  664.           {
  665.             if(flags & TEXI_TABLE_FUNCTIONS)
  666.               fprintf(fp,"@item %s\n",sec);
  667.             else
  668.              fprintf(fp,"@b{%s}\n",sec);  /* was @strong{} or @code{} */
  669.              /*fprintf(fp,"@noindent\n@b{%s}\n",sec);*/
  670.  
  671.  
  672.             if( (flags & TEXI_PARSE_REFERENCES) && (strcmp(sec,"SEE ALSO") == 0) )
  673.               err= see_also(fp, text, flags);
  674.  
  675.             else /* ! "SEE ALSO" */
  676.             {
  677.               char *x= strexpand(text,body_macros);
  678.  
  679.               if(x)
  680.               {
  681.                 fprintf(fp,"@noindent\n"
  682.                            "@%s\n",body_environment);
  683.  
  684.                 if(flags & TEXI_GROUP_SECTIONS)
  685.                   fprintf(fp,"@group\n");
  686.  
  687.                 if(tabsize > 0)
  688.                   fexpand(fp,tabsize,x);
  689.                 else
  690.                   fputs(x,fp);
  691.  
  692.                 if(flags & TEXI_GROUP_SECTIONS)
  693.                   fprintf(fp,"@end group\n");
  694.  
  695.                 fprintf(fp,"@end %s\n"
  696.                            "@refill\n",body_environment);
  697.  
  698.                 free(x);
  699.               }
  700.               else /* out of memory */
  701.                 err= __LINE__;
  702.             }
  703.           }
  704.           /* else (!text) -> no error */
  705.  
  706.           fprintf(fp,"\n");
  707.         }
  708.  
  709.         if(flags & TEXI_TABLE_FUNCTIONS)
  710.           fprintf(fp,"@end table\n");
  711.       }
  712.       else /* out of memory */
  713.         err= __LINE__;
  714.     }
  715.  
  716.     if(last_cs)
  717.       free(last_cs);
  718.   }
  719.  
  720.  
  721.   /* index */
  722.  
  723.   if(err == 0)
  724.   {
  725.     if( !(flags & TEXI_NO_INDEX) )
  726.       fprintf(fp, "@node Function Index\n"
  727.                   "@unnumbered Function Index\n"
  728.                   "@printindex fn\n"
  729.                   "\n"
  730.                   "@page\n"
  731.                   "@contents\n"
  732.                   "@bye\n");
  733.   }
  734.  
  735.   return err;
  736. }
  737.