home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / fish / disks / d1070.lha / Programs / ADoc / source / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  19.8 KB  |  787 lines

  1. /*                                                               -*- C -*-
  2.  *  MAIN.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: main.c,v 1.17 1995/03/31 14:10:41 tf Exp $ */
  24.  
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <stdarg.h>
  29. #include <time.h>
  30. #include <stdio.h>
  31.  
  32. #include "adoc.h"
  33. #include "flist.h"
  34. #include "libfun.h"
  35. #include "mactab.h"
  36. #include "version.h"
  37. #include "debug.h"
  38.  
  39. /*@*/
  40.  
  41. /* local variables */
  42. static char *whoami;
  43. static FILE *ferr;
  44.  
  45. /* function to export `ferr' to the scanner */
  46. FILE *get_ferr(void) { return ferr; }
  47.  
  48. /**/
  49.  
  50. static void echo(const char *fmt, ...)
  51. {
  52.   va_list argp;
  53.   va_start(argp,fmt);
  54.  
  55.   fprintf(stderr,"%s: ",whoami);
  56.   vfprintf(stderr,(char *)fmt,argp);
  57.   fprintf(stderr,"\n");
  58.   fflush(stderr);
  59.  
  60.   va_end(argp);
  61. }
  62.  
  63.  
  64. /**/
  65.  
  66. int main(int argc, char *argv[])
  67. {
  68.   int err= 0; /* return code */
  69.  
  70.   char *outfile    = (char *)0;      /* --output-file       */
  71.   char *errfile    = (char *)0;      /* --error-file        */
  72.   char *headerfile = (char *)0;      /* --texi-header-file  */
  73.   char *yank_type  = "*";            /* --yank-type         */
  74.   char *body_env   = "smallexample"; /* -B<environment>     */
  75.  
  76.   int page_width         = 80;       /* --page-width        */
  77.   int tabsize            = 8;        /* --tab-size          */
  78.   int tabs_to_spaces     = 0;        /* --tabs-to-spaces    */
  79.   int output_type        = 1;        /* --output-type       */
  80.   int table_of_contents  = 0;        /* --table-of-contents */
  81.   int sort_entries       = 1;        /* --preserve-order    */
  82.   int texi_flags         = TEXI_CREATE_HEADER | TEXI_PARSE_REFERENCES | TEXI_ITEMIZE_REFERENCES;
  83.   int adoc_flags         = ADOC_FORM_FEEDS;
  84.   int warn_mask          = WARN_NORMAL;
  85.   int scanner_flags      = 0;        /* --indented-comments */
  86.                                      /* --unindent-bodytext */
  87.   int minimum_indentation = -1;      /* --reindent-bodytext */
  88.  
  89.   /* handles for the macro tables */
  90.  
  91.   int texi_macros = 0;
  92.   int body_macros = 0;
  93.  
  94. #ifdef _DCC /* Dice */
  95.   expand_args(argc,argv, &argc,&argv);
  96. #endif /* _DCC */
  97.  
  98.   /* filenames on MS-DOG systems look very ugly: all uppercase and
  99.    * backslashes.  Perform some cosmetics */
  100.  
  101. #ifdef __MSDOS__
  102.   whoami= "adoc";
  103.  
  104. #else
  105.   whoami= argv[0];
  106.  
  107. #endif /*__MSDOS__*/
  108.  
  109.  
  110.   /* set the debugging defaults */
  111.   D(bug_init(0,stdout));
  112.  
  113.   /* initialize the default error stream */
  114.   ferr= stderr;
  115.  
  116.   if(err == 0)
  117.   {
  118.     /* prepare the texinfo macro table */
  119.     texi_macros= mactab_new( 4+10 );
  120.  
  121.     if(!texi_macros)
  122.       err= 1;
  123.   }
  124.  
  125.   if(err == 0)
  126.   {
  127.     /* prepare the body-text macro table */
  128.     body_macros= mactab_new( 2 );
  129.  
  130.     if(!body_macros)
  131.       err= 2;
  132.   }
  133.  
  134.   if(err)
  135.     echo("error %d creating macro tables -- not enough memory?", err);
  136.  
  137.   else
  138.  
  139.   /* BEGIN scanning command line arguments */
  140.  
  141.   while( (--argc > 0) && (err <= 0) )
  142.   {
  143.     char *arg= *++argv;
  144.  
  145. #ifdef DEBUG
  146.     if(argc > 1)  { D(bug("examining command line argument `%s' ( `%s', ... ) [%d]", argv[0], argv[1], argc-1)); }
  147.     else          { D(bug("examining command line argument `%s' ( ) [%d]", argv[0], argc-1)); }
  148. #endif /* DEBUG */
  149.  
  150.     if(*arg=='-')
  151.     {
  152.       /* remember the original command-line option string */
  153.       char *opt= arg;
  154.  
  155.       if(arg[1]=='-')
  156.         arg= convert_args(*argv);
  157.  
  158.       switch(*++arg)
  159.       {
  160.  
  161. /*-0*/  case '0':
  162.           output_type= 0;
  163.           break;
  164.  
  165. /*-1*/  case '1':
  166.           output_type= 1;
  167.           break;
  168.  
  169. /*-2*/  case '2':
  170.           output_type= 2;
  171.           tabs_to_spaces= 1;
  172.           minimum_indentation= 0;
  173.           break;
  174.  
  175. /*-b*/  case 'b':
  176.           texi_flags |= TEXI_TABLE_FUNCTIONS;
  177.           break;
  178.  
  179. /*-B*/  case 'B':
  180.           if(arg[1]) ++arg;
  181.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  182.  
  183.           if(arg && *arg)
  184.           {
  185.             body_env= arg;
  186.           }
  187.           else
  188.           {
  189.             echo("missing texinfo body text environment after %s option",opt);
  190.             err= 1;
  191.           }
  192.           break;
  193.  
  194. /*-c*/  case 'c':
  195.           err= mactab_add(body_macros, "\\*", "/*", "*\\", "*/", (char *)0);
  196.  
  197.           if(err)
  198.             echo("error %d adding comment convertion macros",err);
  199.           break;
  200.  
  201. /*-d*/  case 'd':
  202.  
  203. #ifdef DEBUG
  204.  
  205.           if(arg[1]) { D(bug_level= atoi( &(arg[1]) )); }
  206.           else       { D(bug_level= 1); }
  207.  
  208. #else /* !DEBUG */
  209.           echo("not compiled w/ -DDEBUG.  No debug information available -- Sorry");
  210.           /* no error */
  211.  
  212. #endif /* DEBUG */
  213.  
  214.           break;
  215.  
  216.  
  217. /*-D*/  case 'D':
  218.           if(arg[1] && --argc > 0)
  219.           {
  220.             char *lhs= &arg[1];
  221.             char *rhs= *(++argv);
  222.  
  223.             err= mactab_add(texi_macros, lhs, rhs, (char *)0);
  224.  
  225.             if(err)
  226.               echo("error adding texinfo macro `%s' = `%s'", lhs, rhs);
  227.           }
  228.           else
  229.           {
  230.             echo("missing macro %s after `%s' option",(arg[1] ? "value":"name"),opt);
  231.             err= 1;
  232.           }
  233.           break;
  234.  
  235. /*-E*/  case 'E':
  236.           if(arg[1]) ++arg;
  237.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  238.  
  239.           if(arg && *arg)
  240.           {
  241.             if(errfile)
  242.             {
  243.               echo("warning: option `%s' has already been seen", opt);
  244.               D(bug("%s \"%s\" superseeds -E \"%s\"", opt, arg, errfile));
  245.             }
  246.  
  247.             /*errfile= strcmp(arg,"-") ? arg : (char *)0;*/
  248.             errfile= arg;
  249.           }
  250.           else /* !(arg && *arg) */
  251.           {
  252.             echo("missing filename after `%s' option", opt);
  253.             err= 1;
  254.           }
  255.           break;
  256.  
  257. /*-f*/  case 'f':
  258.           if(arg[1])
  259.           {
  260.             while(*++arg) switch(*arg)
  261.             {
  262.               case 'f':
  263.                 adoc_flags |= ADOC_FORM_FEEDS;
  264.                 texi_flags |= TEXI_FUNCTION_NEWPAGE;
  265.                 break;
  266.  
  267.               default:
  268.                 echo("unknown paging option: `%s'",opt);
  269.                 break;
  270.             }
  271.           }
  272.           else /* !arg[1] */
  273.           {
  274.             adoc_flags &= ~ADOC_FORM_FEEDS;
  275.             texi_flags &= ~TEXI_FUNCTION_NEWPAGE;
  276.           }
  277.           break;
  278.  
  279. /*-g*/  case 'g':
  280.           if(arg[1])
  281.           {
  282.             while(*++arg) switch(*arg)
  283.             {
  284.               case 's':
  285.                 texi_flags |= TEXI_GROUP_SECTIONS;
  286.                 break;
  287.  
  288.               default:
  289.                 echo("unknown grouping option: `%s'",opt);
  290.                 err= 1;
  291.                 break;
  292.             }
  293.           }
  294.           else texi_flags &= ~TEXI_GROUP_SECTIONS;
  295.           break;
  296.  
  297. /*-H*/  case 'H':
  298.           if(arg[1]) ++arg;
  299.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  300.  
  301.           if(arg && *arg)
  302.           {
  303.             if(headerfile)
  304.             {
  305.               echo("warning: option `%s' has already been seen", opt);
  306.               D(bug("%s \"%s\" superseeds -H \"%s\"", opt, arg, headerfile));
  307.             }
  308.  
  309.             headerfile= arg;
  310.           }
  311.           else /* !(arg && *arg) */
  312.           {
  313.             echo("missing texinfo header filename after `%s' option", opt);
  314.             err= 1;
  315.           }
  316.           break;
  317.  
  318. /*-h*/  case 'h':
  319.           printf("usage: %s [options] [-o outfile] [@ listfile] [infiles...]\n\n", whoami);
  320.           display_args( arg[1] ? atoi(&arg[1]) : 3 );
  321.           err= -1;    /* negative means exit w/o error */
  322.           break;
  323.  
  324. /*-I*/  case 'I':
  325.           table_of_contents= 1;
  326.           break;
  327.  
  328. /*-i*/  case 'i':
  329.           yank_type= "i";
  330.           break;
  331.  
  332. /*-j*/  case 'j':
  333.           if(arg[1]) ++arg;
  334.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  335.  
  336.           if(arg && *arg)
  337.           {
  338.             if( (minimum_indentation= atoi(arg)) < 0 )
  339.             {
  340.               echo("illegal indentation: %d  (must be >= 0)", minimum_indentation);
  341.               err= 1;
  342.             }
  343.           }
  344.           else /* !(arg && *arg) */
  345.           {
  346.             echo("missing indentation after `%s' option", opt);
  347.             err= 1;
  348.           }
  349.           break;
  350.  
  351. /*-l*/  case 'l':
  352.           if(arg[1]) ++arg;
  353.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  354.  
  355.           if(arg && *arg)
  356.           {
  357.             page_width= atoi(arg);
  358.  
  359.             if(page_width < 1)
  360.             {
  361.               echo("illegal page width: `%s'  (must be > 0)", arg);
  362.               err= 1;
  363.             }
  364.           }
  365.           else /* !(arg && *arg) */
  366.           {
  367.             echo("missing page width after `%s' option", opt);
  368.             err= 1;
  369.           }
  370.           break;
  371.  
  372. /*-M*/  case 'M':
  373.           if(arg[1] && --argc > 0)
  374.           {
  375.             char *lhs= &arg[1];
  376.             char *rhs= *(++argv);
  377.  
  378.             err= mactab_add(body_macros, lhs, rhs, (char *)0);
  379.  
  380.             if(err)
  381.               echo("error adding body macro `%s' -> `%s'", lhs, rhs);
  382.           }
  383.           else
  384.           {
  385.             echo("missing macro %s after `%s' option",(arg[1] ? "value":"name"),opt);
  386.             err= 1;
  387.           }
  388.           break;
  389.  
  390. /*-n*/  case 'n':
  391.           output_type= 0;
  392.           break;
  393.  
  394. /*-o*/  case 'o':
  395.           if(arg[1]) ++arg;
  396.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  397.  
  398.           if(arg && *arg)
  399.           {
  400.             if(outfile)
  401.               echo("warning: option `%s' has already been seen", opt);
  402.  
  403.             outfile= arg;
  404.           }
  405.           else /* !(arg && *arg) */
  406.           {
  407.             echo("missing filename after `%s' option", opt);
  408.             err= 1;
  409.           }
  410.           break;
  411.  
  412. /*-p*/  case 'p':
  413.           sort_entries= arg[1] ? 1:0;
  414.           break;
  415.  
  416. /*-q*/  case 'q':
  417.           break;
  418.  
  419. /*-T*/  case 'T':
  420.           if(arg[1]) ++arg;
  421.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  422.  
  423.           if(arg && *arg)
  424.           {
  425.             tabs_to_spaces= 1;
  426.             tabsize= atoi(arg);
  427.  
  428.             if(tabsize < 1)
  429.             {
  430.               echo("illegal tab step: `%d'  (must be >= 1)", tabsize);
  431.               err= 1;
  432.             }
  433.           }
  434.           else /* !(arg && *arg) */
  435.           {
  436.             echo("missing tab size after `%s' option", opt);
  437.             err= 1;
  438.           }
  439.           break;
  440.  
  441. /*-t*/  case 't':
  442.           tabs_to_spaces= arg[1] ? atoi(&arg[1]) : 1;
  443.           break;
  444.  
  445. /*-U*/  case 'U':
  446.           if(arg[1]) ++arg;
  447.           else arg= (--argc > 0) ? *(++argv) : (char *)0;
  448.  
  449.           if(arg && *arg)
  450.           {
  451.             mactab_remove(texi_macros, arg, (char *)0);
  452.             mactab_remove(body_macros, arg, (char *)0);
  453.           }
  454.  
  455.           else /* !(arg && *arg) */
  456.           {
  457.             echo("missing macro after `%s' option", opt);
  458.             err= 1;
  459.           }
  460.           break;
  461.  
  462. /*-u*/  case 'u':
  463.           if(arg[1])
  464.           {
  465.             scanner_flags &= ~SCANNER_UNINDENT_BODYTEXT;
  466.             minimum_indentation= -1;
  467.           }
  468.           else scanner_flags |= SCANNER_UNINDENT_BODYTEXT;
  469.           break;
  470.  
  471. /*-v*/  case 'v':
  472.           printf("ADOC Version " VERSION " (compiled " __DATE__ ", " __TIME__ ")\n"
  473.                  "(c)Copyright 1995 by Tobias Ferber,  All Rights Reserved\n" );
  474.           err= -1;
  475.           break;
  476.  
  477. /*-W*/  case 'W':
  478.           if(arg[1])
  479.           {
  480.             ++arg;
  481.  
  482.             if( isdigit(*arg) )
  483.               warn_mask |= atoi(arg);
  484.  
  485.             else switch( strarg(arg, "none",       /* 1 */
  486.                                      "arnings",    /* 2 */
  487.                                      "keywords",   /* 3 */
  488.                                      "absence",    /* 4 */
  489.                                      "untitled",   /* 5 */
  490.                                      "all", "") )  /* 6 */
  491.             {
  492.               case 1:   warn_mask  = WARN_NONE;                 break;
  493.               case 2:   warn_mask |= WARN_NORMAL;               break;
  494.               case 3:   warn_mask |= WARN_UNKNOWN_KEYWORDS;     break;
  495.               case 4:   warn_mask |= WARN_MISSING_KEYWORDS;     break;
  496.               case 5:   warn_mask |= WARN_UNTITLED_SECTION;     break;
  497.               case 6:   warn_mask |= WARN_ALL;                  break;
  498.  
  499.               default:
  500.                 echo("unknown warning method: `%s'",opt);
  501.                 err= 1;
  502.                 break;
  503.             }
  504.           }
  505.           else warn_mask= WARN_NONE;
  506.           break;
  507.  
  508. /*-x*/  case 'x':
  509.           if(arg[1])
  510.           {
  511.             switch( strarg(++arg, "off",        /* 1 */
  512.                                   "on",         /* 2 */
  513.                                   "itemize",    /* 3 */
  514.                                   "", "") )     /* 4 */
  515.             {
  516.               case 1:   texi_flags &= ~TEXI_PARSE_REFERENCES;
  517.                         texi_flags &= ~TEXI_ITEMIZE_REFERENCES;   break;
  518.  
  519.               case 2:   texi_flags |=  TEXI_PARSE_REFERENCES;
  520.                         texi_flags &= ~TEXI_ITEMIZE_REFERENCES;   break;
  521.  
  522.               case 3:   texi_flags |=  TEXI_PARSE_REFERENCES;
  523.                         texi_flags |=  TEXI_ITEMIZE_REFERENCES;   break;
  524.  
  525.               default:
  526.                 echo("unknown reference handlig option: `%s'",opt);
  527.                 err= 1;
  528.                 break;
  529.             }
  530.           }
  531.           else texi_flags &= ~(TEXI_PARSE_REFERENCES | TEXI_ITEMIZE_REFERENCES);
  532.           break;
  533.  
  534.  
  535. /*-Y*/  case 'Y':
  536.           if(arg[1]) scanner_flags &= ~SCANNER_ALLOW_INDENTED_COMMENTS;
  537.           else       scanner_flags |=  SCANNER_ALLOW_INDENTED_COMMENTS;
  538.           break;
  539.  
  540. /*-y*/  case 'y':
  541.           if(arg[1]) ++arg;
  542.           else arg= (--argc > 0) ? *(++argv) : (char *)0L;
  543.  
  544.           if(arg && *arg)
  545.             yank_type= arg;
  546.  
  547.           else /* !(arg && *arg) */
  548.           {
  549.             echo("missing comment type string after `%s' option", opt);
  550.             err= 1;
  551.           }
  552.           break;
  553.  
  554. /*-z*/  case 'z':
  555.           texi_flags &= ~TEXI_CREATE_HEADER;
  556.           break;
  557.  
  558. /*-Z*/  case 'Z':
  559.           if(arg[1]) texi_flags &= ~TEXI_NO_INDEX;
  560.           else       texi_flags |=  TEXI_NO_INDEX;
  561.           break;
  562.  
  563.           /*
  564.            *  The following options are ignored for compatibility
  565.            *  with Bill Koester's original version `autodoc' which
  566.            *  is part of C=ommodore's Native Developer Kit (NDK).
  567.            */
  568.  
  569. /*-C*/  case 'C':
  570. /*-F*/  case 'F':
  571. /*-s*/  case 's':
  572. /*-a*/  case 'a':
  573. /*-r*/  case 'r':
  574. /*-w*/  case 'w':
  575.           echo("warning: option `%s' ignored for compatibility", opt);
  576.           break;
  577.  
  578. /*- */  case '\0':
  579.           if( (err= flist_addfile("")) )
  580.              echo("out of memory... hmmmmmmmmmpf!");
  581.            break;
  582.  
  583. /*??*/  default:
  584.           echo("unrecognized option `%s'", opt);
  585.           err= 1;
  586.           break;
  587.       }
  588.     }
  589.     else if(*arg=='@')
  590.     {
  591.       if(arg[1]) ++arg;
  592.       else arg= (--argc > 0) ? *(++argv) : (char *)0L;
  593.  
  594.       if(arg && *arg)
  595.       {
  596.         if( (err= flist_from_file(arg)) )
  597.           echo("out of memory... aaarrrrrrgggggghh!");
  598.       }
  599.       else /* !(arg && *arg) */
  600.       {
  601.         echo("missing filename after `%s'", *argv);
  602.         err= 1;
  603.       }
  604.     }
  605.     else /* *arg != '@' */
  606.     {
  607.       if(arg && *arg)
  608.       {
  609.         if( (err= flist_addfile(arg)) )
  610.           echo("out of memory... aaaiiiiiieeeeeeeee!");
  611.       }
  612.       else echo("internal problem parsing command line arguments: arg is empty");
  613.     }
  614.   }
  615.   /* END scanning command line arguments */
  616.   D(bug("command line argument parsing done"));
  617.  
  618.   if(err == 0)
  619.   {
  620.     /* prepare the error stream */
  621.  
  622.     if(errfile && *errfile)
  623.     {
  624.       D(bug("opening error stream `%s'",errfile));
  625.  
  626.       if( !(ferr= fopen(errfile,"w")) )
  627.       {
  628.         echo("could not write error messages to `%s'",errfile);
  629.         err= __LINE__;
  630.       }
  631.     }
  632.     /*else ferr is initialized to stderr */
  633.  
  634.     /* if no filename is given then read from stdin */
  635.  
  636.     if( !flist_getname() )
  637.       flist_addfile("");
  638.  
  639.  
  640.     /* read the input files (the scanner takes them from the flist queue) */
  641.  
  642.     D(bug("reading autodocs of type `%s'", yank_type));
  643.  
  644.     if(err == 0)
  645.       err= read_source(yank_type, warn_mask, scanner_flags);
  646.  
  647.     if(err < 0)
  648.       err= -err;  /* I/O error */
  649.  
  650.     D(bug("disposing file list"));
  651.     flist_dispose();
  652.  
  653.     /*
  654.      */
  655.  
  656.     if( (err == 0) && (minimum_indentation >= 0) )
  657.     {
  658.       if( (err= funindent(minimum_indentation, tabsize)) )
  659.         echo("error %d reworking body text indentation -- not enough memory?",err);
  660.  
  661.       /* funindent() already performed that conversion */
  662.       else tabs_to_spaces= 0;
  663.     }
  664.  
  665.  
  666.     if( (err == 0) && (output_type > 0) )
  667.     {
  668.       FILE *fout;
  669.  
  670.       /* prepare the output file */
  671.  
  672.       if(outfile && *outfile)
  673.       {
  674.         D(bug("opening output stream `%s'",outfile));
  675.  
  676.         if(!(fout= fopen(outfile,"w")) )
  677.         {
  678.           echo("could not write to `%s'",outfile);
  679.           err= __LINE__;
  680.         }
  681.       }
  682.       else fout= stdout;
  683.  
  684.  
  685.       if( fout && (err==0) )
  686.       {
  687.         if(sort_entries)
  688.         {
  689.           D(bug("sorting entries"));
  690.           funsort();
  691.         }
  692.  
  693.         switch(output_type)
  694.         {
  695.           case 1: /* --autodoc */
  696.  
  697.             if(table_of_contents)
  698.             {
  699.               D(bug("writing table of contents"));
  700.               err= gen_autodoc_toc(fout);
  701.             }
  702.             if(err == 0)
  703.             {
  704.               D(bug("writing autodocs"));
  705.               err= gen_autodoc( fout, page_width, tabs_to_spaces ? tabsize : 0, adoc_flags, mactab(body_macros) );
  706.             }
  707.             break;
  708.  
  709.           case 2: /* --texinfo */
  710.             if(texi_flags & TEXI_CREATE_HEADER)
  711.             {
  712.               D(bug("creating texinfo header"));
  713.               err= gen_texinfo_header( fout, headerfile, mactab(texi_macros) );
  714.             }
  715.  
  716.             if(err == 0)
  717.             {
  718.               D(bug("adding texinfo body macros"));
  719.               err= mactab_add( body_macros,  "@",        "@@",
  720.                                              "{",        "@{",
  721.                                              "}",        "@}",
  722.                                           /* "...",      "@dots{}", */
  723.                                           /* "TeX",      "@TeX{}",  */
  724.                                              "e.g. ",    "e.g.@: ",
  725.                                              "E.g. ",    "E.g.@: ",
  726.                                              "i.e. ",    "i.e.@: ",
  727.                                              "I.e. ",    "I.e.@: ",   (char *)0 );
  728.             }
  729.  
  730.             if(err == 0)
  731.             {
  732.               D(bug("creating texinfo output"));
  733.               err+= gen_texinfo( fout, tabs_to_spaces ? tabsize : 0, texi_flags, body_env, mactab(body_macros) );
  734.             }
  735.  
  736.             if(err)
  737.               echo("error creating texinfo output");
  738.             break;
  739.  
  740.           default: /* --dry-run */
  741.             break;
  742.         }
  743.       }
  744.  
  745.       if(fout && (fout != stdout))
  746.         fclose(fout);
  747.     }
  748.  
  749.     D(bug("disposing libfun entries"));
  750.     funfree();
  751.   }
  752.  
  753. #ifdef DEBUG
  754.   mactab_debug(bug_stream);
  755. #endif
  756.  
  757.   D(bug("disposing macro tables"));
  758.   mactab_dispose(body_macros);
  759.   mactab_dispose(texi_macros);
  760.  
  761.   /*
  762.   */
  763.  
  764.   if(err > 0)
  765.   {
  766.     echo("[%s] *** Error %d", (outfile && *outfile) ? outfile : "stdout", err);
  767.     fprintf(ferr,"%s terminated abnormally (error %d)\n", whoami, err);
  768.   }
  769.  
  770.   D(bug("closing I/O streams"));
  771.  
  772.   if( ferr && (ferr != stderr) && (ferr != stdout) )
  773.     fclose(ferr);
  774.  
  775.   D(bug("exiting adoc returning %d (%s)", (err>0) ? 1:0, (err>0) ? "error":"success" ));
  776.   D(bug_exit());
  777.  
  778. #ifdef DEBUG
  779.  
  780.   if(bug_stream && (bug_stream != stdout))
  781.     fclose(bug_stream);
  782.  
  783. #endif /*DEBUG*/
  784.  
  785.   return (err > 0) ? 1:0;
  786. }
  787.