Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. /* tex2html.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Konverter TeX-->HTML                                                      */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include "asmitree.h"
  13. #include "chardefs.h"
  14. #include <ctype.h>
  15. #include <sys/stat.h>
  16. #include <time.h>
  17. #include <string.h>
  18. #include "texrefs.h"
  19. #include "texutil.h"
  20. #include "textoc.h"
  21. #include "texfonts.h"
  22. #include "strutil.h"
  23.  
  24. #ifdef __MSDOS__
  25. # include <dir.h>
  26. #endif
  27.  
  28. /*--------------------------------------------------------------------------*/
  29.  
  30. #define TOKLEN 350
  31.  
  32. static char *TableName,
  33.             *BiblioName,
  34.             *ContentsName,
  35.             *IndexName,
  36. #define ErrorEntryCnt 3
  37.             *ErrorEntryNames[ErrorEntryCnt];
  38.  
  39. typedef enum
  40. {
  41.   EnvNone, EnvDocument, EnvItemize, EnvEnumerate, EnvDescription, EnvTable,
  42.   EnvTabular, EnvRaggedLeft, EnvRaggedRight, EnvCenter, EnvVerbatim,
  43.   EnvQuote, EnvTabbing, EnvBiblio, EnvMarginPar, EnvCaption, EnvHeading, EnvCount
  44. } EnvType;
  45.  
  46. static char *FontNames[FontCnt] =
  47. {
  48.   "", "EM", "B", "TT", "I", "SUP"
  49. };
  50.  
  51. typedef struct sEnvSave
  52. {
  53.   struct sEnvSave *Next;
  54.   EnvType SaveEnv;
  55.   int ListDepth, ActLeftMargin, LeftMargin, RightMargin;
  56.   int EnumCounter, FontNest;
  57.   Boolean InListItem;
  58. } TEnvSave, *PEnvSave;
  59.  
  60. typedef enum
  61. {
  62.   ColLeft, ColRight, ColCenter, ColBar
  63. } TColumn;
  64.  
  65. #define MAXCOLS 30
  66. #define MAXROWS 500
  67. typedef char *TableLine[MAXCOLS];
  68. typedef struct
  69. {
  70.   int ColumnCount, TColumnCount;
  71.   TColumn ColTypes[MAXCOLS];
  72.   int ColLens[MAXCOLS];
  73.   int LineCnt;
  74.   TableLine Lines[MAXROWS];
  75.   Boolean LineFlags[MAXROWS];
  76.   Boolean MultiFlags[MAXROWS];
  77. } TTable;
  78.  
  79. typedef struct sIndexSave
  80. {
  81.   struct sIndexSave *Next;
  82.   char *Name;
  83.   int RefCnt;
  84. } TIndexSave, *PIndexSave;
  85.  
  86. static char *EnvNames[EnvCount] =
  87. {
  88.   "___NONE___", "document", "itemize", "enumerate", "description", "table", "tabular",
  89.   "raggedleft", "raggedright", "center", "verbatim", "quote", "tabbing",
  90.   "thebibliography", "___MARGINPAR___", "___CAPTION___", "___HEADING___"
  91. };
  92.  
  93. static int IncludeNest;
  94. static FILE *infiles[50], *outfile;
  95. static char *outfilename;
  96. static char TocName[200];
  97.  
  98. #define CHAPMAX 6
  99. static int Chapters[CHAPMAX];
  100. static int TableNum, ErrState, FracState, BibIndent, BibCounter;
  101. #define TABMAX 100
  102. static int TabStops[TABMAX], TabStopCnt, CurrTabStop;
  103. static Boolean InAppendix, InMathMode, InListItem;
  104. static TTable *pThisTable;
  105. static int CurrRow, CurrCol;
  106. static char SrcDir[TOKLEN + 1], asname[TOKLEN];
  107. static Boolean GermanMode;
  108.  
  109. static int Structured;
  110.  
  111. static EnvType CurrEnv;
  112. static int CurrListDepth;
  113. static int EnumCounter;
  114. static int ActLeftMargin, LeftMargin, RightMargin;
  115. static int CurrPass;
  116. static PEnvSave EnvStack;
  117. static PIndexSave FirstIndex;
  118.  
  119. static PInstTable TeXTable;
  120.  
  121. /*--------------------------------------------------------------------------*/
  122.  
  123. void ChkStack(void)
  124. {
  125. }
  126.  
  127. static void SetSrcDir(const char *pSrcFile)
  128. {
  129.   const char *pSep;
  130.  
  131.   pSep = strchr(pSrcFile, PATHSEP);
  132.   if (!pSep)
  133.     pSep = strchr(pSrcFile, '/');
  134.  
  135.   if (!pSep)
  136.     *SrcDir = '\0';
  137.   else
  138.   {
  139.     size_t l = pSep + 1 - pSrcFile;
  140.  
  141.     if (l >= sizeof(SrcDir))
  142.     {
  143.       fprintf(stderr, "%s: path too long\n", pSrcFile);
  144.       exit(3);
  145.     }
  146.     memcpy(SrcDir, pSrcFile, l);
  147.     SrcDir[l] = '\0';
  148.   }
  149. }
  150.  
  151. static void error(char *Msg)
  152. {
  153.   int z;
  154.  
  155.   fprintf(stderr, "%s:%d.%d: %s\n", pInFileName, CurrLine, CurrColumn, Msg);
  156.   for (z = 0; z < IncludeNest; fclose(infiles[z++]));
  157.   fclose(outfile);
  158.   exit(2);
  159. }
  160.  
  161. static void SetLang(Boolean IsGerman)
  162. {
  163.   if (GermanMode == IsGerman)
  164.     return;
  165.  
  166.   GermanMode = IsGerman;
  167.   if (GermanMode)
  168.   {
  169.     TableName = "Tabelle";
  170.     BiblioName = "Literaturverzeichnis";
  171.     ContentsName = "Inhalt";
  172.     IndexName = "Index";
  173.     ErrorEntryNames[0] = "Typ";
  174.     ErrorEntryNames[1] = "Ursache";
  175.     ErrorEntryNames[2] = "Argument";
  176.   }
  177.   else
  178.   {
  179.     TableName = "Table";
  180.     BiblioName = "Bibliography";
  181.     ContentsName = "Contents";
  182.     IndexName = "Index";
  183.     ErrorEntryNames[0] = "Type";
  184.     ErrorEntryNames[1] = "Reason";
  185.     ErrorEntryNames[2] = "Argument";
  186.   }
  187. }
  188.  
  189. /*------------------------------------------------------------------------------*/
  190.  
  191. static void GetNext(char *Src, char *Dest)
  192. {
  193.   char *c = strchr(Src,' ');
  194.  
  195.   if (!c)
  196.   {
  197.     strcpy(Dest, Src);
  198.     *Src = '\0';
  199.   }
  200.   else
  201.   {
  202.     *c = '\0';
  203.     strcpy(Dest, Src);
  204.     for (c++; *c == ' '; c++);
  205.     strmov(Src, c);
  206.   }
  207. }
  208.  
  209. static void ReadAuxFile(char *Name)
  210. {
  211.   FILE *file = fopen(Name, "r");
  212.   char Line[300], Cmd[300], Nam[300], Val[300];
  213.  
  214.   if (!file)
  215.     return;
  216.  
  217.   while (!feof(file))
  218.   {
  219.     if (!fgets(Line, 299, file))
  220.       break;
  221.     if ((*Line) && (Line[strlen(Line) - 1] == '\n'))
  222.       Line[strlen(Line) - 1] = '\0';
  223.     GetNext(Line, Cmd);
  224.     if (!strcmp(Cmd, "Label"))
  225.     {
  226.       GetNext(Line, Nam); GetNext(Line, Val);
  227.       AddLabel(Nam, Val);
  228.     }
  229.     else if (!strcmp(Cmd, "Citation"))
  230.     {
  231.       GetNext(Line, Nam);
  232.       GetNext(Line, Val);
  233.       AddCite(Nam, Val);
  234.     }
  235.   }
  236.  
  237.   fclose(file);
  238. }
  239.  
  240. /*--------------------------------------------------------------------------*/
  241.  
  242. static Boolean issep(char inp)
  243. {
  244.   return ((inp == ' ') || (inp == '\t') || (inp == '\n'));
  245. }
  246.  
  247. static Boolean isalphanum(char inp)
  248. {
  249.   return ((inp >= 'A') && (inp <= 'Z'))
  250.       || ((inp >= 'a') && (inp <= 'z'))
  251.       || ((inp >= '0') && (inp <= '9'))
  252.       || (inp == '.');
  253. }
  254.  
  255. static char LastChar = '\0';
  256. static char SaveSep = '\0', SepString[TOKLEN] = "";
  257. static Boolean DidEOF;
  258. static char BufferLine[TOKLEN] = "", *BufferPtr = BufferLine;
  259. typedef struct
  260. {
  261.   char Token[TOKLEN], Sep[TOKLEN];
  262. } PushedToken;
  263. static int PushedTokenCnt = 0;
  264. static PushedToken PushedTokens[16];
  265.  
  266. static int GetChar(void)
  267. {
  268.   Boolean Comment;
  269.   static Boolean DidPar = False;
  270.   char *Result;
  271.  
  272.   if (*BufferPtr == '\0')
  273.   {
  274.     do
  275.     {
  276.       if (IncludeNest <= 0)
  277.         return EOF;
  278.       do
  279.       {
  280.         Result = fgets(BufferLine, TOKLEN, infiles[IncludeNest - 1]);
  281.         if (Result)
  282.           break;
  283.         fclose(infiles[--IncludeNest]);
  284.         if (IncludeNest <= 0)
  285.           return EOF;
  286.       }
  287.       while (True);
  288.       CurrLine++;
  289.       BufferPtr = BufferLine;
  290.       Comment = (strlen(BufferLine) >= 2) && (!strncmp(BufferLine, "%%", 2));
  291.       if ((*BufferLine == '\0') || (*BufferLine == '\n'))
  292.       {
  293.         if ((CurrEnv == EnvDocument) && (!DidPar))
  294.         {
  295.           strcpy(BufferLine, "\\par\n");
  296.           DidPar = True;
  297.           Comment = False;
  298.         }
  299.       }
  300.       else if (Comment)
  301.       {
  302.         if ((*BufferLine) && (BufferLine[strlen(BufferLine) - 1] == '\n'))
  303.           BufferLine[strlen(BufferLine) - 1] = '\0';
  304.         if (!strncmp(BufferLine + 2, "TITLE ", 6))
  305.           fprintf(outfile, "<TITLE>%s</TITLE>\n", BufferLine + 8);
  306.       }
  307.       else
  308.         DidPar = False;
  309.     }
  310.     while (Comment);
  311.   }
  312.   return *(BufferPtr++);
  313. }
  314.  
  315. static Boolean ReadToken(char *Dest)
  316. {
  317.   int ch, z;
  318.   Boolean Good;
  319.   char *run;
  320.  
  321.   if (PushedTokenCnt > 0)
  322.   {
  323.     strcpy(Dest, PushedTokens[0].Token);
  324.     strcpy(SepString, PushedTokens[0].Sep);
  325.     for (z = 0; z < PushedTokenCnt - 1; z++)
  326.       PushedTokens[z] = PushedTokens[z + 1];
  327.     PushedTokenCnt--;
  328.     return True;
  329.   }
  330.  
  331.   if (DidEOF)
  332.     return FALSE;
  333.  
  334.   CurrColumn = BufferPtr - BufferLine + 1;
  335.  
  336.   /* falls kein Zeichen gespeichert, fuehrende Blanks ueberspringen */
  337.  
  338.   *Dest = '\0';
  339.   *SepString = SaveSep;
  340.   run = SepString + ((SaveSep == '\0') ? 0 : 1);
  341.   if (LastChar == '\0')
  342.   {
  343.     do
  344.     {
  345.       ch = GetChar();
  346.       if (ch == '\r')
  347.         ch = GetChar();
  348.       if (issep(ch))
  349.         *(run++) = ' ';
  350.     }
  351.     while ((issep(ch)) && (ch != EOF));
  352.     *run = '\0';
  353.     if (ch == EOF)
  354.     {
  355.       DidEOF = TRUE;
  356.       return FALSE;
  357.     }
  358.   }
  359.   else
  360.   {
  361.     ch = LastChar;
  362.     LastChar = '\0';
  363.   }
  364.  
  365.   /* jetzt Zeichen kopieren, bis Leerzeichen */
  366.  
  367.   run = Dest;
  368.   SaveSep = '\0';
  369.   if (isalphanum(*(run++) = ch))
  370.   {
  371.     do
  372.     {
  373.       ch = GetChar();
  374.       Good = (!issep(ch)) && (isalphanum(ch)) && (ch != EOF);
  375.       if (Good)
  376.         *(run++) = ch;
  377.     }
  378.     while (Good);
  379.  
  380.     /* Dateiende ? */
  381.  
  382.     if (ch == EOF)
  383.       DidEOF = TRUE;
  384.  
  385.     /* Zeichen speichern ? */
  386.  
  387.     else if ((!issep(ch)) && (!isalphanum(ch)))
  388.       LastChar = ch;
  389.  
  390.     /* Separator speichern ? */
  391.  
  392.     else if (issep(ch))
  393.       SaveSep = ' ';
  394.   }
  395.  
  396.   /* Ende */
  397.  
  398.   *run = '\0';
  399.   return True;
  400. }
  401.  
  402. static void BackToken(char *Token)
  403. {
  404.   if (PushedTokenCnt >= 16)
  405.     return;
  406.   strcpy(PushedTokens[PushedTokenCnt].Token, Token);
  407.   strcpy(PushedTokens[PushedTokenCnt].Sep, SepString);
  408.   PushedTokenCnt++;
  409. }
  410.  
  411. /*--------------------------------------------------------------------------*/
  412.  
  413. static void assert_token(char *ref)
  414. {
  415.   char token[TOKLEN];
  416.  
  417.   ReadToken(token);
  418.   if (strcmp(ref, token))
  419.   {
  420.     as_snprintf(token, sizeof(token), "\"%s\" expected", ref);
  421.     error(token);
  422.   }
  423. }
  424.  
  425. static void collect_token(char *dest, char *term)
  426. {
  427.   char Comp[TOKLEN];
  428.   Boolean first = TRUE, done;
  429.  
  430.   *dest = '\0';
  431.   do
  432.   {
  433.     ReadToken(Comp);
  434.     done = (!strcmp(Comp, term));
  435.     if (!done)
  436.     {
  437.       if (!first)
  438.         strcat(dest, SepString);
  439.       strcat(dest, Comp);
  440.     }
  441.     first = False;
  442.   }
  443.   while (!done);
  444. }
  445.  
  446. /*--------------------------------------------------------------------------*/
  447.  
  448. static char OutLineBuffer[TOKLEN] = "", SideMargin[TOKLEN];
  449.  
  450. static void PutLine(Boolean DoBlock)
  451. {
  452.   int l, n, ptrcnt, diff, div, mod, divmod;
  453.   char *chz, *ptrs[50];
  454.   Boolean SkipFirst, IsFirst;
  455.  
  456.   fputs(Blanks(LeftMargin - 1), outfile);
  457.   if ((CurrEnv == EnvRaggedRight) || (!DoBlock))
  458.   {
  459.     fprintf(outfile, "%s", OutLineBuffer);
  460.     l = strlen(OutLineBuffer);
  461.   }
  462.   else
  463.   {
  464.     SkipFirst = ((CurrEnv == EnvItemize) || (CurrEnv == EnvEnumerate) || (CurrEnv == EnvDescription) || (CurrEnv == EnvBiblio));
  465.     if (LeftMargin == ActLeftMargin)
  466.       SkipFirst = False;
  467.     l = ptrcnt = 0;
  468.     IsFirst = SkipFirst;
  469.     for (chz = OutLineBuffer; *chz != '\0'; chz++)
  470.     {
  471.       if ((chz > OutLineBuffer) && (*(chz - 1) != ' ') && (*chz == ' '))
  472.       {
  473.         if (!IsFirst)
  474.           ptrs[ptrcnt++] = chz;
  475.         IsFirst = False;
  476.       }
  477.       l++;
  478.     }
  479.     (void)ptrs;
  480.     diff = RightMargin - LeftMargin + 1 - l;
  481.     div = (ptrcnt > 0) ? diff / ptrcnt : 0;
  482.     mod = diff - (ptrcnt * div);
  483.     divmod = (mod > 0) ? ptrcnt / mod : ptrcnt + 1;
  484.     IsFirst = SkipFirst;
  485.     ptrcnt = 0;
  486.     for (chz = OutLineBuffer; *chz != '\0'; chz++)
  487.     {
  488.       fputc(*chz, outfile);
  489.       if ((chz > OutLineBuffer) && (*(chz - 1) != ' ') && (*chz == ' '))
  490.       {
  491.         if (!IsFirst)
  492.         {
  493.           n = div;
  494.           if ((mod > 0) && ((ptrcnt % divmod) == 0))
  495.           {
  496.             mod--;
  497.             n++;
  498.           }
  499.           if (n > 0)
  500.             fputs(Blanks(n), outfile);
  501.           ptrcnt++;
  502.         }
  503.         IsFirst = False;
  504.       }
  505.     }
  506.     l = RightMargin - LeftMargin + 1;
  507.   }
  508.   if (*SideMargin != '\0')
  509.   {
  510.     fputs(Blanks(RightMargin - LeftMargin + 4 - l), outfile);
  511. #if 0
  512.     fprintf(outfile, "%s", SideMargin);
  513. #endif
  514.     *SideMargin = '\0';
  515.   }
  516.   fputc('\n', outfile);
  517.   LeftMargin = ActLeftMargin;
  518. }
  519.  
  520. static void AddLine(const char *Part, char *Sep)
  521. {
  522.   int mlen = RightMargin - LeftMargin + 1;
  523.   char *search, save;
  524.  
  525.   if (strlen(Sep) > 1)
  526.     Sep[1] = '\0';
  527.   if (*OutLineBuffer != '\0')
  528.     strcat(OutLineBuffer, Sep);
  529.   strcat(OutLineBuffer, Part);
  530.   if ((int)strlen(OutLineBuffer) >= mlen)
  531.   {
  532.     search = OutLineBuffer + mlen;
  533.     while (search >= OutLineBuffer)
  534.     {
  535.       if (*search == ' ')
  536.         break;
  537.       search--;
  538.     }
  539.     if (search <= OutLineBuffer)
  540.     {
  541.       PutLine(False);
  542.       *OutLineBuffer = '\0';
  543.     }
  544.     else
  545.     {
  546.       save = (*search);
  547.       *search = '\0';
  548.       PutLine(False);
  549.       *search = save;
  550.       for (; *search == ' '; search++);
  551.       strmov(OutLineBuffer, search);
  552.     }
  553.   }
  554. }
  555.  
  556. static void AddSideMargin(const char *Part, char *Sep)
  557. {
  558.   if (strlen(Sep) > 1)
  559.     Sep[1] = '\0';
  560.   if (*Sep != '\0')
  561.     if ((*SideMargin != '\0') || (!issep(*Sep)))
  562.       strcat(SideMargin, Sep);
  563.   strcat(SideMargin, Part);
  564. }
  565.  
  566. static void FlushLine(void)
  567. {
  568.   if (*OutLineBuffer != '\0')
  569.   {
  570.     PutLine(False);
  571.     *OutLineBuffer = '\0';
  572.   }
  573. }
  574.  
  575. static void ResetLine(void)
  576. {
  577.   *OutLineBuffer = '\0';
  578. }
  579.  
  580. static void AddTableEntry(const char *Part, char *Sep)
  581. {
  582.   char *Ptr = pThisTable->Lines[CurrRow][CurrCol];
  583.   int nlen = (!Ptr) ? 0 : strlen(Ptr);
  584.   Boolean UseSep = (nlen > 0);
  585.  
  586.   if (strlen(Sep) > 1)
  587.     Sep[1] = '\0';
  588.   if (UseSep)
  589.     nlen += strlen(Sep);
  590.   nlen += strlen(Part);
  591.   if (!Ptr)
  592.   {
  593.     Ptr = (char *) malloc(nlen + 1);
  594.     *Ptr = '\0';
  595.   }
  596.   else
  597.   {
  598.     char *NewPtr = (char *) realloc(Ptr, nlen + 1);
  599.  
  600.     if (NewPtr)
  601.       Ptr = NewPtr;
  602.   }
  603.   if (UseSep)
  604.     strcat(Ptr, Sep);
  605.   strcat(Ptr, Part);
  606.   pThisTable->Lines[CurrRow][CurrCol] = Ptr;
  607. }
  608.  
  609. static void DoAddNormal(const char *Part, char *Sep)
  610. {
  611.   if (!strcmp(Part, "<"))
  612.     Part = "&lt;";
  613.   else if (!strcmp(Part, ">"))
  614.     Part = "&gt;";
  615.   else if (!strcmp(Part, "&"))
  616.     Part = "&amp;";
  617.  
  618.   switch (CurrEnv)
  619.   {
  620.     case EnvMarginPar:
  621.       AddSideMargin(Part, Sep);
  622.       break;
  623.     case EnvTabular:
  624.       AddTableEntry(Part, Sep);
  625.       break;
  626.     default:
  627.       AddLine(Part, Sep);
  628.   }
  629. }
  630.  
  631. /*--------------------------------------------------------------------------*/
  632.  
  633. void PrFontDiff(int OldFlags, int NewFlags)
  634. {
  635.   tFontType z;
  636.   int Mask;
  637.   char erg[10];
  638.  
  639.   for (z = FontStandard + 1, Mask = 2; z < FontCnt; z++, Mask = Mask << 1)
  640.    if ((OldFlags^NewFlags) & Mask)
  641.    {
  642.      as_snprintf(erg, sizeof(erg), "<%s%s>", (NewFlags & Mask)?"":"/", FontNames[z]);
  643.      DoAddNormal(erg, "");
  644.    }
  645. }
  646.  
  647. void PrFontSize(tFontSize Type, Boolean On)
  648. {
  649.   char erg[10];
  650.  
  651.   strcpy(erg, "<");
  652.   if (FontNormalSize == Type)
  653.     return;
  654.  
  655.   if (!On)
  656.     strcat(erg, "/");
  657.   switch (Type)
  658.   {
  659.     case FontTiny:
  660.     case FontSmall:
  661.       strcat(erg, "SMALL");
  662.       break;
  663.     case FontLarge:
  664.     case FontHuge:
  665.       strcat(erg, "BIG");
  666.       break;
  667.     default:
  668.       break;
  669.   }
  670.   strcat (erg, ">");
  671.   DoAddNormal(erg, "");
  672.   if ((FontTiny == Type) || (FontHuge == Type))
  673.     DoAddNormal(erg, "");
  674. }
  675.  
  676. static void SaveEnv(EnvType NewEnv)
  677. {
  678.   PEnvSave NewSave;
  679.  
  680.   NewSave = (PEnvSave) malloc(sizeof(TEnvSave));
  681.   NewSave->Next = EnvStack;
  682.   NewSave->ListDepth = CurrListDepth;
  683.   NewSave->LeftMargin = LeftMargin;
  684.   NewSave->ActLeftMargin = ActLeftMargin;
  685.   NewSave->RightMargin = RightMargin;
  686.   NewSave->EnumCounter = EnumCounter;
  687.   NewSave->SaveEnv = CurrEnv;
  688.   NewSave->FontNest = FontNest;
  689.   NewSave->InListItem = InListItem;
  690.   EnvStack = NewSave;
  691.   CurrEnv = NewEnv;
  692.   FontNest = 0;
  693. }
  694.  
  695. static void RestoreEnv(void)
  696. {
  697.   PEnvSave OldSave;
  698.  
  699.   OldSave = EnvStack;
  700.   EnvStack = OldSave->Next;
  701.   CurrListDepth = OldSave->ListDepth;
  702.   LeftMargin = OldSave->LeftMargin;
  703.   ActLeftMargin = OldSave->ActLeftMargin;
  704.   RightMargin = OldSave->RightMargin;
  705.   EnumCounter = OldSave->EnumCounter;
  706.   FontNest = OldSave->FontNest;
  707.   InListItem = OldSave->InListItem;
  708.   CurrEnv = OldSave->SaveEnv;
  709.   free(OldSave);
  710. }
  711.  
  712. static void InitTableRow(int Index)
  713. {
  714.   int z;
  715.  
  716.   for (z = 0; z < pThisTable->TColumnCount; pThisTable->Lines[Index][z++] = NULL);
  717.   pThisTable->MultiFlags[Index] = False;
  718.   pThisTable->LineFlags[Index] = False;
  719. }
  720.  
  721. static void NextTableColumn(void)
  722. {
  723.   if (CurrEnv != EnvTabular)
  724.     error("table separation char not within tabular environment");
  725.  
  726.   if ((pThisTable->MultiFlags[CurrRow])
  727.    || (CurrCol >= pThisTable->TColumnCount))
  728.     error("too many columns within row");
  729.  
  730.   CurrCol++;
  731. }
  732.  
  733. static void DumpTable(void)
  734. {
  735.   int TextCnt, RowCnt, rowz, rowz2, rowz3, colz, colptr, ml, l, diff, sumlen, firsttext, indent;
  736.   char *ColTag;
  737.  
  738.   /* compute widths of individual rows */
  739.   /* get index of first text column */
  740.  
  741.   RowCnt = pThisTable->Lines[CurrRow][0] ? CurrRow + 1 : CurrRow;
  742.   firsttext = -1;
  743.   for (colz = colptr = 0; colz < pThisTable->ColumnCount; colz++)
  744.     if (pThisTable->ColTypes[colz] == ColBar)
  745.       pThisTable->ColLens[colz] = 1;
  746.     else
  747.     {
  748.       ml = 0;
  749.       for (rowz = 0; rowz < RowCnt; rowz++)
  750.         if ((!pThisTable->LineFlags[rowz]) && (!pThisTable->MultiFlags[rowz]))
  751.         {
  752.           l = (!pThisTable->Lines[rowz][colptr]) ? 0 : strlen(pThisTable->Lines[rowz][colptr]);
  753.           if (ml < l)
  754.             ml = l;
  755.         }
  756.       pThisTable->ColLens[colz] = ml + 2;
  757.       colptr++;
  758.       if (firsttext < 0) firsttext = colz;
  759.     }
  760.  
  761.   /* count number of text columns */
  762.  
  763.   for (colz = TextCnt = 0; colz < pThisTable->ColumnCount; colz++)
  764.     if (pThisTable->ColTypes[colz] != ColBar)
  765.       TextCnt++;
  766.  
  767.   /* get total width */
  768.  
  769.   for (colz = sumlen = 0; colz < pThisTable->ColumnCount; sumlen += pThisTable->ColLens[colz++]);
  770.   indent = (RightMargin - LeftMargin + 1 - sumlen) / 2;
  771.   if (indent < 0)
  772.     indent = 0;
  773.  
  774.   /* search for multicolumns and extend first field if table is too lean */
  775.  
  776.   ml = 0;
  777.   for (rowz = 0; rowz < RowCnt; rowz++)
  778.     if ((!pThisTable->LineFlags[rowz]) && (pThisTable->MultiFlags[rowz]))
  779.     {
  780.       l = (!pThisTable->Lines[rowz][0]) ? 0 : strlen(pThisTable->Lines[rowz][0]);
  781.       if (ml < l)
  782.         ml = l;
  783.     }
  784.   if (ml + 4 > sumlen)
  785.   {
  786.     diff = ml + 4 - sumlen;
  787.     pThisTable->ColLens[firsttext] += diff;
  788.   }
  789.  
  790.   /* tell browser to switch to table mode */
  791.  
  792.   fprintf(outfile, "<P><CENTER><TABLE SUMMARY=\"No Summary\" BORDER=1 CELLPADDING=5>\n");
  793.  
  794.   /* print rows */
  795.  
  796.   rowz = 0;
  797.   while (rowz < RowCnt)
  798.   {
  799.     /* find first text line */
  800.  
  801.     for (; rowz < RowCnt; rowz++)
  802.       if (!pThisTable->LineFlags[rowz])
  803.         break;
  804.  
  805.     /* find last text line */
  806.  
  807.     for (rowz2 = rowz; rowz2 < RowCnt; rowz2++)
  808.       if (pThisTable->LineFlags[rowz2])
  809.         break;
  810.     rowz2--;
  811.  
  812.     if (rowz < RowCnt)
  813.     {
  814.       /* if more than one line follows, take this as header line(s) */
  815.  
  816.       if ((rowz2 <= RowCnt - 3) && (pThisTable->LineFlags[rowz2 + 1]) && (pThisTable->LineFlags[rowz2 + 2]))
  817.         ColTag = "TH";
  818.       else
  819.         ColTag = "TD";
  820.  
  821.       /* start a row */
  822.  
  823.       fprintf(outfile, "<TR ALIGN=LEFT>\n");
  824.  
  825.       /* over all columns... */
  826.  
  827.       colptr = 0;
  828.       for (colz = 0; colz < ((pThisTable->MultiFlags[rowz])?firsttext + 1:pThisTable->ColumnCount); colz++)
  829.         if (pThisTable->ColTypes[colz] != ColBar)
  830.         {
  831.           /* start a column */
  832.  
  833.           fprintf(outfile, "<%s VALIGN=TOP NOWRAP", ColTag);
  834.           if (pThisTable->MultiFlags[rowz])
  835.             fprintf(outfile, " COLSPAN=%d", TextCnt);
  836.           switch (pThisTable->ColTypes[colz])
  837.           {
  838.             case ColLeft:
  839.               fputs(" ALIGN=LEFT>", outfile);
  840.               break;
  841.             case ColCenter:
  842.               fputs(" ALIGN=CENTER>", outfile);
  843.               break;
  844.             case ColRight:
  845.               fputs(" ALIGN=RIGHT>", outfile);
  846.               break;
  847.             default:
  848.               break;
  849.           }
  850.  
  851.           /* write items */
  852.  
  853.           for (rowz3 = rowz; rowz3 <= rowz2; rowz3++)
  854.           {
  855.             if (pThisTable->Lines[rowz3][colptr])
  856.               fputs(pThisTable->Lines[rowz3][colptr], outfile);
  857.             if (rowz3 != rowz2)
  858.               fputs("<BR>\n", outfile);
  859.           }
  860.  
  861.           /* end column */
  862.  
  863.           fprintf(outfile, "</%s>\n", ColTag);
  864.  
  865.           colptr++;
  866.         }
  867.  
  868.       /* end row */
  869.  
  870.       fprintf(outfile, "</TR>\n");
  871.  
  872.       for (rowz3 = rowz; rowz3 <= rowz2; rowz3++)
  873.         for (colz = 0; colz < pThisTable->ColumnCount; colz++)
  874.           if (pThisTable->Lines[rowz3][colz])
  875.           {
  876.             free(pThisTable->Lines[rowz3][colz]);
  877.             pThisTable->Lines[rowz3][colz] = NULL;
  878.           }
  879.  
  880.       rowz = rowz2 + 1;
  881.     }
  882.   }
  883.  
  884.   /* end table mode */
  885.  
  886.   fprintf(outfile, "</TABLE></CENTER>\n");
  887. }
  888.  
  889. static void GetTableName(char *Dest, size_t DestSize)
  890. {
  891.   int ThisTableNum = (CurrEnv == EnvTabular) ? TableNum + 1 : TableNum;
  892.  
  893.   if (InAppendix)
  894.     as_snprintf(Dest, DestSize, "%c.%d", Chapters[0] + 'A', ThisTableNum);
  895.   else
  896.     as_snprintf(Dest, DestSize, "%d.%d", Chapters[0], ThisTableNum);
  897. }
  898.  
  899. static void GetSectionName(char *Dest, size_t DestSize)
  900. {
  901.   int z;
  902.  
  903.   *Dest = '\0';
  904.   for (z = 0; z <= 2; z++)
  905.   {
  906.     if ((z > 0) && (Chapters[z] == 0))
  907.       break;
  908.     if ((InAppendix) && (z == 0))
  909.       as_snprcatf(Dest, DestSize, "%c.", Chapters[z] + 'A');
  910.     else
  911.       as_snprcatf(Dest, DestSize, "%d.", Chapters[z]);
  912.   }
  913. }
  914.  
  915. /*--------------------------------------------------------------------------*/
  916.  
  917. static char BackSepString[TOKLEN];
  918.  
  919. static void TeXFlushLine(Word Index)
  920. {
  921.   UNUSED(Index);
  922.  
  923.   if (CurrEnv == EnvTabular)
  924.   {
  925.     for (CurrCol++; CurrCol < pThisTable->TColumnCount; pThisTable->Lines[CurrRow][CurrCol++] = as_strdup(""));
  926.     CurrRow++;
  927.     if (CurrRow == MAXROWS)
  928.       error("too many rows in table");
  929.     InitTableRow(CurrRow);
  930.     CurrCol = 0;
  931.   }
  932.   else if (CurrEnv == EnvTabbing)
  933.   {
  934.     CurrTabStop = 0;
  935.     PrFontDiff(CurrFontFlags, 0);
  936.     AddLine("</TD></TR>", "");
  937.     FlushLine();
  938.     AddLine("<TR><TD NOWRAP>", "");
  939.     PrFontDiff(0, CurrFontFlags);
  940.   }
  941.   else
  942.   {
  943.     if (*OutLineBuffer == '\0')
  944.       strcpy(OutLineBuffer, " ");
  945.     AddLine("<BR>", "");
  946.     FlushLine();
  947.   }
  948. }
  949.  
  950. static void TeXKillLine(Word Index)
  951. {
  952.   UNUSED(Index);
  953.  
  954.   ResetLine();
  955.   if (CurrEnv == EnvTabbing)
  956.   {
  957.     AddLine("<TR><TD NOWRAP>", "");
  958.     PrFontDiff(0, CurrFontFlags);
  959.   }
  960. }
  961.  
  962. static void TeXDummy(Word Index)
  963. {
  964.   UNUSED(Index);
  965. }
  966.  
  967. static void TeXDummyEqual(Word Index)
  968. {
  969.   char Token[TOKLEN];
  970.   UNUSED(Index);
  971.  
  972.   assert_token("=");
  973.   ReadToken(Token);
  974. }
  975.  
  976. static void TeXDummyNoBrack(Word Index)
  977. {
  978.   char Token[TOKLEN];
  979.   UNUSED(Index);
  980.  
  981.   ReadToken(Token);
  982. }
  983.  
  984. static void TeXDummyInCurl(Word Index)
  985. {
  986.   char Token[TOKLEN];
  987.   UNUSED(Index);
  988.  
  989.   assert_token("{");
  990.   ReadToken(Token);
  991.   assert_token("}");
  992. }
  993.  
  994. static void TeXNewCommand(Word Index)
  995. {
  996.   char token[TOKLEN], command[TOKLEN], sum_token[TOKLEN], arg_cnt[TOKLEN];
  997.   int level;
  998.   UNUSED(Index);
  999.  
  1000.   assert_token("{");
  1001.   assert_token("\\");
  1002.   ReadToken(command);
  1003.   assert_token("}");
  1004.   ReadToken(token);
  1005.  
  1006.   if (!strcmp(token, "["))
  1007.   {
  1008.     ReadToken(arg_cnt);
  1009.     assert_token("]");
  1010.     ReadToken(token);
  1011.   }
  1012.   if (strcmp(token, "{"))
  1013.     error("\"{\" expected");
  1014.  
  1015.   level = 1;
  1016.   *sum_token = '\0';
  1017.   do
  1018.   {
  1019.     ReadToken(token);
  1020.     if (!strcmp(token, "{"))
  1021.       level++;
  1022.     else if (!strcmp(token, "}"))
  1023.       level--;
  1024.     if (level != 0)
  1025.       strmaxcat(sum_token, token, sizeof(sum_token));
  1026.   }
  1027.   while (level != 0);
  1028.   if (!strcmp(command, "asname"))
  1029.     strmaxcpy(asname, sum_token, sizeof(asname));
  1030. }
  1031.  
  1032. static void TeXDef(Word Index)
  1033. {
  1034.   char Token[TOKLEN];
  1035.   int level;
  1036.   UNUSED(Index);
  1037.  
  1038.   assert_token("\\");
  1039.   ReadToken(Token);
  1040.   assert_token("{");
  1041.   level = 1;
  1042.   do
  1043.   {
  1044.     ReadToken(Token);
  1045.     if (!strcmp(Token, "{"))
  1046.       level++;
  1047.     else if (!strcmp(Token, "}"))
  1048.       level--;
  1049.   }
  1050.   while (level != 0);
  1051. }
  1052.  
  1053. static void TeXFont(Word Index)
  1054. {
  1055.   char Token[TOKLEN];
  1056.   UNUSED(Index);
  1057.  
  1058.   assert_token("\\");
  1059.   ReadToken(Token);
  1060.   assert_token("=");
  1061.   ReadToken(Token);
  1062.   ReadToken(Token);
  1063.   assert_token("\\");
  1064.   ReadToken(Token);
  1065. }
  1066.  
  1067. static void TeXAppendix(Word Index)
  1068. {
  1069.   int z;
  1070.   UNUSED(Index);
  1071.  
  1072.   InAppendix = True;
  1073.   *Chapters = -1;
  1074.   for (z = 1; z < CHAPMAX; Chapters[z++] = 0);
  1075. }
  1076.  
  1077. static int LastLevel;
  1078.  
  1079. static void TeXNewSection(Word Level)
  1080. {
  1081.   int z;
  1082.  
  1083.   if (Level >= CHAPMAX)
  1084.     return;
  1085.  
  1086.   FlushLine();
  1087.   fputc('\n', outfile);
  1088.  
  1089.   assert_token("{");
  1090.   LastLevel = Level;
  1091.   SaveEnv(EnvHeading);
  1092.   RightMargin = 200;
  1093.  
  1094.   Chapters[Level]++;
  1095.   for (z = Level + 1; z < CHAPMAX; Chapters[z++] = 0);
  1096.   if (Level == 0)
  1097.     TableNum = 0;
  1098. }
  1099.  
  1100. static void EndSectionHeading(void)
  1101. {
  1102.   int Level = LastLevel;
  1103.   char Line[TOKLEN], Title[TOKLEN], *rep;
  1104.  
  1105.   strcpy(Title, OutLineBuffer);
  1106.   *OutLineBuffer = '\0';
  1107.  
  1108.   fprintf(outfile, "<H%d>", Level + 1);
  1109.  
  1110.   *Line = '\0';
  1111.   if (Level < 3)
  1112.   {
  1113.     GetSectionName(Line, sizeof(Line));
  1114.     fprintf(outfile, "<A NAME=\"sect_");
  1115.     for (rep = Line; *rep; rep++)
  1116.       fputc((*rep == '.') ? '_' : *rep, outfile);
  1117.     fprintf(outfile, "\">");
  1118.     as_snprcatf(Line, sizeof(Line), " ");
  1119.   }
  1120.   as_snprcatf(Line, sizeof(Line), "%s", Title);
  1121.  
  1122.   fprintf(outfile, "%s", Line);
  1123.  
  1124.   if (Level < 3)
  1125.   {
  1126.     fputs("</A>", outfile);
  1127.     GetSectionName(Line, sizeof(Line));
  1128.     as_snprcatf(Line, sizeof(Line), " %s", Title);
  1129.     AddToc(Line, 0);
  1130.   }
  1131.  
  1132.   fprintf(outfile, "</H%d>\n", Level + 1);
  1133. }
  1134.  
  1135. static EnvType GetEnvType(char *Name)
  1136. {
  1137.   EnvType z;
  1138.  
  1139.   if (!strcmp(Name, "longtable"))
  1140.     return EnvTabular;
  1141.   for (z = EnvNone + 1; z < EnvCount; z++)
  1142.     if (!strcmp(Name, EnvNames[z]))
  1143.       return z;
  1144.  
  1145.   error("unknown environment");
  1146.   return EnvNone;
  1147. }
  1148.  
  1149. static void TeXBeginEnv(Word Index)
  1150. {
  1151.   char EnvName[TOKLEN], Add[TOKLEN], *p;
  1152.   EnvType NEnv;
  1153.   Boolean done;
  1154.   TColumn NCol;
  1155.   UNUSED(Index);
  1156.  
  1157.   assert_token("{");
  1158.   ReadToken(EnvName);
  1159.   if ((NEnv = GetEnvType(EnvName)) == EnvTable)
  1160.   {
  1161.     ReadToken(Add);
  1162.     if (!strcmp(Add, "*"))
  1163.       assert_token("}");
  1164.     else if (strcmp(Add, "}"))
  1165.       error("unknown table environment");
  1166.   }
  1167.   else
  1168.     assert_token("}");
  1169.  
  1170.   if (NEnv != EnvVerbatim)
  1171.     SaveEnv(NEnv);
  1172.  
  1173.   switch (NEnv)
  1174.   {
  1175.     case EnvDocument:
  1176.       fputs("</HEAD>\n", outfile);
  1177.       fputs("<BODY>\n", outfile);
  1178.       break;
  1179.     case EnvItemize:
  1180.       FlushLine();
  1181.       fprintf(outfile, "<UL>\n");
  1182.       ++CurrListDepth;
  1183.       ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
  1184.       RightMargin = 70;
  1185.       EnumCounter = 0;
  1186.       InListItem = False;
  1187.       break;
  1188.     case EnvDescription:
  1189.       FlushLine();
  1190.       fprintf(outfile, "<DL COMPACT>\n");
  1191.       ++CurrListDepth;
  1192.       ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
  1193.       RightMargin = 70;
  1194.       EnumCounter = 0;
  1195.       InListItem = False;
  1196.       break;
  1197.     case EnvEnumerate:
  1198.       FlushLine();
  1199.       fprintf(outfile, "<OL>\n");
  1200.       ++CurrListDepth;
  1201.       ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
  1202.       RightMargin = 70;
  1203.       EnumCounter = 0;
  1204.       InListItem = False;
  1205.       break;
  1206.     case EnvBiblio:
  1207.       FlushLine();
  1208.       fprintf(outfile, "<P>\n");
  1209.       fprintf(outfile, "<H1><A NAME=\"sect_bib\">%s</A></H1>\n<DL COMPACT>\n", BiblioName);
  1210.       assert_token("{");
  1211.       ReadToken(Add);
  1212.       assert_token("}");
  1213.       ActLeftMargin = LeftMargin = 4 + (BibIndent = strlen(Add));
  1214.       AddToc(BiblioName, 0);
  1215.       break;
  1216.     case EnvVerbatim:
  1217.       FlushLine();
  1218.       fprintf(outfile, "<PRE>\n");
  1219.       if ((*BufferLine != '\0') && (*BufferPtr != '\0'))
  1220.       {
  1221.         fprintf(outfile, "%s", BufferPtr);
  1222.         *BufferLine = '\0';
  1223.         BufferPtr = BufferLine;
  1224.       }
  1225.       do
  1226.       {
  1227.         if (!fgets(Add, TOKLEN - 1, infiles[IncludeNest - 1]))
  1228.           break;
  1229.         CurrLine++;
  1230.         done = strstr(Add, "\\end{verbatim}") != NULL;
  1231.         if (!done)
  1232.         {
  1233.           for (p = Add; *p != '\0';)
  1234.             if (*p == '<')
  1235.             {
  1236.               memmove(p + 3, p, strlen(p) + 1);
  1237.               memcpy(p, "&lt;", 4);
  1238.               p += 4;
  1239.             }
  1240.             else if (*p == '>')
  1241.             {
  1242.               memmove(p + 3, p, strlen(p) + 1);
  1243.               memcpy(p, "&gt;", 4);
  1244.               p += 4;
  1245.             }
  1246.             else
  1247.               p++;
  1248.           fprintf(outfile, "%s", Add);
  1249.         }
  1250.       }
  1251.       while (!done);
  1252.       fprintf(outfile, "\n</PRE>\n");
  1253.       break;
  1254.     case EnvQuote:
  1255.       FlushLine();
  1256.       fprintf(outfile, "<BLOCKQUOTE>\n");
  1257.       ActLeftMargin = LeftMargin = 5;
  1258.       RightMargin = 70;
  1259.       break;
  1260.     case EnvTabbing:
  1261.       FlushLine();
  1262.       fputs("<TABLE SUMMARY=\"No Summary\" CELLPADDING=2>\n", outfile);
  1263.       TabStopCnt = 0;
  1264.       CurrTabStop = 0;
  1265.       RightMargin = TOKLEN - 1;
  1266.       AddLine("<TR><TD NOWRAP>", "");
  1267.       PrFontDiff(0, CurrFontFlags);
  1268.       break;
  1269.     case EnvTable:
  1270.       ReadToken(Add);
  1271.       if (strcmp(Add, "["))
  1272.         BackToken(Add);
  1273.       else
  1274.       {
  1275.         do
  1276.         {
  1277.           ReadToken(Add);
  1278.         }
  1279.         while (strcmp(Add, "]"));
  1280.       }
  1281.       FlushLine();
  1282.       fputc('\n', outfile);
  1283.       ++TableNum;
  1284.       break;
  1285.     case EnvCenter:
  1286.       FlushLine();
  1287.       fputs("<CENTER>\n", outfile);
  1288.       break;
  1289.     case EnvRaggedRight:
  1290.       FlushLine();
  1291.       fputs("<DIV ALIGN=LEFT>\n", outfile);
  1292.       break;
  1293.     case EnvRaggedLeft:
  1294.       FlushLine();
  1295.       fputs("<DIV ALIGN=RIGHT>\n", outfile);
  1296.       break;
  1297.     case EnvTabular:
  1298.       FlushLine();
  1299.       assert_token("{");
  1300.       pThisTable->ColumnCount = pThisTable->TColumnCount = 0;
  1301.       do
  1302.       {
  1303.         ReadToken(Add);
  1304.         done = !strcmp(Add, "}");
  1305.         if (!done)
  1306.         {
  1307.           if (pThisTable->ColumnCount >= MAXCOLS)
  1308.             error("too many columns in table");
  1309.           NCol = ColLeft;
  1310.           if (!strcmp(Add, "|"))
  1311.             NCol = ColBar;
  1312.           else if (!strcmp(Add, "l"))
  1313.             NCol = ColLeft;
  1314.           else if (!strcmp(Add, "r"))
  1315.             NCol = ColRight;
  1316.           else if (!strcmp(Add, "c"))
  1317.             NCol = ColCenter;
  1318.           else
  1319.             error("unknown table column descriptor");
  1320.           if ((pThisTable->ColTypes[pThisTable->ColumnCount++] = NCol) != ColBar)
  1321.             pThisTable->TColumnCount++;
  1322.         }
  1323.       }
  1324.       while (!done);
  1325.       InitTableRow(CurrRow = 0);
  1326.       CurrCol = 0;
  1327.       break;
  1328.     default:
  1329.       break;
  1330.   }
  1331. }
  1332.  
  1333. static void TeXEndEnv(Word Index)
  1334. {
  1335.   char EnvName[TOKLEN], Add[TOKLEN];
  1336.   EnvType NEnv;
  1337.   UNUSED(Index);
  1338.  
  1339.   assert_token("{");
  1340.   ReadToken(EnvName);
  1341.   if ((NEnv = GetEnvType(EnvName)) == EnvTable)
  1342.   {
  1343.     ReadToken(Add);
  1344.     if (!strcmp(Add, "*"))
  1345.       assert_token("}");
  1346.     else if (strcmp(Add, "}"))
  1347.       error("unknown table environment");
  1348.   }
  1349.   else
  1350.     assert_token("}");
  1351.  
  1352.   if (!EnvStack)
  1353.     error("end without begin");
  1354.   if (CurrEnv != NEnv)
  1355.     error("begin and end of environment do not match");
  1356.  
  1357.   switch (CurrEnv)
  1358.   {
  1359.     case EnvDocument:
  1360.       FlushLine();
  1361.       fputs("</BODY>\n", outfile);
  1362.       break;
  1363.     case EnvItemize:
  1364.       if (InListItem)
  1365.         AddLine("</LI>", "");
  1366.       FlushLine();
  1367.       fprintf(outfile, "</UL>\n");
  1368.       break;
  1369.     case EnvDescription:
  1370.       if (InListItem)
  1371.         AddLine("</DD>", "");
  1372.       FlushLine();
  1373.       fprintf(outfile, "</DL>\n");
  1374.       break;
  1375.     case EnvEnumerate:
  1376.       if (InListItem)
  1377.         AddLine("</LI>", "");
  1378.       FlushLine();
  1379.       fprintf(outfile, "</OL>\n");
  1380.       break;
  1381.     case EnvQuote:
  1382.       FlushLine();
  1383.       fprintf(outfile, "</BLOCKQUOTE>\n");
  1384.       break;
  1385.     case EnvBiblio:
  1386.       FlushLine();
  1387.       fprintf(outfile, "</DL>\n");
  1388.       break;
  1389.     case EnvTabbing:
  1390.       PrFontDiff(CurrFontFlags, 0);
  1391.       AddLine("</TD></TR>", "");
  1392.       FlushLine();
  1393.       fputs("</TABLE>", outfile);
  1394.       break;
  1395.     case EnvCenter:
  1396.       FlushLine();
  1397.       fputs("</CENTER>\n", outfile);
  1398.       break;
  1399.     case EnvRaggedRight:
  1400.     case EnvRaggedLeft:
  1401.       FlushLine();
  1402.       fputs("</DIV>\n", outfile);
  1403.       break;
  1404.     case EnvTabular:
  1405.       DumpTable();
  1406.       break;
  1407.     case EnvTable:
  1408.       FlushLine(); fputc('\n', outfile);
  1409.       break;
  1410.     default:
  1411.       break;
  1412.   }
  1413.  
  1414.   RestoreEnv();
  1415. }
  1416.  
  1417. static void TeXItem(Word Index)
  1418. {
  1419.   char Token[TOKLEN], Acc[TOKLEN];
  1420.   UNUSED(Index);
  1421.  
  1422.   if (InListItem)
  1423.     AddLine((CurrEnv == EnvDescription) ? "</DD>" : "</LI>", "");
  1424.   FlushLine();
  1425.   InListItem = True;
  1426.   switch(CurrEnv)
  1427.   {
  1428.     case EnvItemize:
  1429.       fprintf(outfile, "<LI>");
  1430.       LeftMargin = ActLeftMargin - 3;
  1431.       break;
  1432.     case EnvEnumerate:
  1433.       fprintf(outfile, "<LI>");
  1434.       LeftMargin = ActLeftMargin - 4;
  1435.       break;
  1436.     case EnvDescription:
  1437.       ReadToken(Token);
  1438.       if (strcmp(Token, "["))
  1439.         BackToken(Token);
  1440.       else
  1441.       {
  1442.         collect_token(Acc, "]");
  1443.         LeftMargin = ActLeftMargin - 4;
  1444.         fprintf(outfile, "<DT>%s", Acc);
  1445.       }
  1446.       fprintf(outfile, "<DD>");
  1447.       break;
  1448.     default:
  1449.       error("\\item not in a list environment");
  1450.   }
  1451. }
  1452.  
  1453. static void TeXBibItem(Word Index)
  1454. {
  1455.   char NumString[20], Token[TOKLEN], Name[TOKLEN], Value[TOKLEN];
  1456.   UNUSED(Index);
  1457.  
  1458.   if (CurrEnv != EnvBiblio)
  1459.     error("\\bibitem not in bibliography environment");
  1460.  
  1461.   assert_token("{");
  1462.   collect_token(Name, "}");
  1463.  
  1464.   FlushLine();
  1465.   AddLine("<DT>", "");
  1466.   ++BibCounter;
  1467.  
  1468.   LeftMargin = ActLeftMargin - BibIndent - 3;
  1469.   as_snprintf(Value, sizeof(Value), "<A NAME=\"cite_%s\">", Name);
  1470.   DoAddNormal(Value, "");
  1471.   as_snprintf(NumString, sizeof(NumString), "[%*d] </A><DD>", BibIndent, BibCounter);
  1472.   AddLine(NumString, "");
  1473.   as_snprintf(NumString, sizeof(NumString), "%d", BibCounter);
  1474.   AddCite(Name, NumString);
  1475.   ReadToken(Token);
  1476.   *SepString = '\0';
  1477.   BackToken(Token);
  1478. }
  1479.  
  1480. static void TeXAddDollar(Word Index)
  1481. {
  1482.   UNUSED(Index);
  1483.  
  1484.   DoAddNormal("$", BackSepString);
  1485. }
  1486.  
  1487. static void TeXAddUnderbar(Word Index)
  1488. {
  1489.   UNUSED(Index);
  1490.  
  1491.   DoAddNormal("_", BackSepString);
  1492. }
  1493.  
  1494. #if 0
  1495. static void TeXAddPot(Word Index)
  1496. {
  1497.   UNUSED(Index);
  1498.  
  1499.   DoAddNormal("^", BackSepString);
  1500. }
  1501. #endif
  1502.  
  1503. static void TeXAddAmpersand(Word Index)
  1504. {
  1505.   UNUSED(Index);
  1506.  
  1507.   DoAddNormal("&", BackSepString);
  1508. }
  1509.  
  1510. static void TeXAddAt(Word Index)
  1511. {
  1512.   UNUSED(Index);
  1513.  
  1514.   DoAddNormal("@", BackSepString);
  1515. }
  1516.  
  1517. static void TeXAddImm(Word Index)
  1518. {
  1519.   UNUSED(Index);
  1520.  
  1521.   DoAddNormal("#", BackSepString);
  1522. }
  1523.  
  1524. static void TeXAddPercent(Word Index)
  1525. {
  1526.   UNUSED(Index);
  1527.  
  1528.   DoAddNormal("%", BackSepString);
  1529. }
  1530.  
  1531. static void TeXAddAsterisk(Word Index)
  1532. {
  1533.   UNUSED(Index);
  1534.  
  1535.   DoAddNormal("*", BackSepString);
  1536. }
  1537.  
  1538. static void TeXAddSSharp(Word Index)
  1539. {
  1540.   UNUSED(Index);
  1541.  
  1542.   DoAddNormal("&szlig;", BackSepString);
  1543. }
  1544.  
  1545. static void TeXAddIn(Word Index)
  1546. {
  1547.   UNUSED(Index);
  1548.  
  1549.   DoAddNormal("in", BackSepString);
  1550. }
  1551.  
  1552. static void TeXAddReal(Word Index)
  1553. {
  1554.   UNUSED(Index);
  1555.  
  1556.   DoAddNormal("R", BackSepString);
  1557. }
  1558.  
  1559. static void TeXAddGreekMu(Word Index)
  1560. {
  1561.   UNUSED(Index);
  1562.  
  1563.   DoAddNormal("&micro;", BackSepString);
  1564. }
  1565.  
  1566. static void TeXAddGreekPi(Word Index)
  1567. {
  1568.   UNUSED(Index);
  1569.  
  1570.   DoAddNormal("&pi;", BackSepString);
  1571. }
  1572.  
  1573. static void TeXAddLessEq(Word Index)
  1574. {
  1575.   UNUSED(Index);
  1576.  
  1577.   DoAddNormal("&le;", BackSepString);
  1578. }
  1579.  
  1580. static void TeXAddGreaterEq(Word Index)
  1581. {
  1582.   UNUSED(Index);
  1583.  
  1584.   DoAddNormal("&ge;", BackSepString);
  1585. }
  1586.  
  1587. static void TeXAddNotEq(Word Index)
  1588. {
  1589.   UNUSED(Index);
  1590.  
  1591.   DoAddNormal("&ne;", BackSepString);
  1592. }
  1593.  
  1594. static void TeXAddMid(Word Index)
  1595. {
  1596.   UNUSED(Index);
  1597.  
  1598.   DoAddNormal("|", BackSepString);
  1599. }
  1600.  
  1601. static void TeXASName(Word Index)
  1602. {
  1603.   char arg[TOKLEN];
  1604.  
  1605.   UNUSED(Index);
  1606.  
  1607.   assert_token("{");
  1608.   collect_token(arg, "}");
  1609.   DoAddNormal(asname, BackSepString);
  1610. }
  1611.  
  1612. static void TeXAddLAnd(Word Index)
  1613. {
  1614.   UNUSED(Index);
  1615.  
  1616.   DoAddNormal("&and;", BackSepString);
  1617. }
  1618.  
  1619. static void TeXAddLOr(Word Index)
  1620. {
  1621.   UNUSED(Index);
  1622.  
  1623.   DoAddNormal("&or;", BackSepString);
  1624. }
  1625.  
  1626. static void TeXAddOPlus(Word Index)
  1627. {
  1628.   UNUSED(Index);
  1629.  
  1630.   DoAddNormal("&veebar;", BackSepString);
  1631. }
  1632.  
  1633. static void TeXAddRightArrow(Word Index)
  1634. {
  1635.   UNUSED(Index);
  1636.  
  1637.   DoAddNormal("&RightArrow;", BackSepString);
  1638. }
  1639.  
  1640. static void TeXAddLongRightArrow(Word Index)
  1641. {
  1642.   UNUSED(Index);
  1643.  
  1644.   DoAddNormal("&LongRightArrow;", BackSepString);
  1645. }
  1646.  
  1647. static void TeXAddLeftArrow(Word Index)
  1648. {
  1649.   UNUSED(Index);
  1650.  
  1651.   DoAddNormal("&LeftArrow;", BackSepString);
  1652. }
  1653.  
  1654. static void TeXAddGets(Word Index)
  1655. {
  1656.   UNUSED(Index);
  1657.  
  1658.   DoAddNormal("&LeftArrow;", BackSepString);
  1659. }
  1660.  
  1661. static void TeXAddLongLeftArrow(Word Index)
  1662. {
  1663.   UNUSED(Index);
  1664.  
  1665.   DoAddNormal("&LongLeftArrow;", BackSepString);
  1666. }
  1667.  
  1668. static void TeXAddLeftRightArrow(Word Index)
  1669. {
  1670.   UNUSED(Index);
  1671.  
  1672.   DoAddNormal("&LeftRightArrow;", BackSepString);
  1673. }
  1674.  
  1675. static void TeXDoFrac(Word Index)
  1676. {
  1677.   UNUSED(Index);
  1678.  
  1679.   assert_token("{");
  1680.   *SepString = '\0';
  1681.   BackToken("(");
  1682.   FracState = 0;
  1683. }
  1684.  
  1685. static void NextFracState(void)
  1686. {
  1687.   if (FracState == 0)
  1688.   {
  1689.     assert_token("{");
  1690.     *SepString = '\0';
  1691.     BackToken(")");
  1692.     BackToken("/");
  1693.     BackToken("(");
  1694.   }
  1695.   else if (FracState == 1)
  1696.   {
  1697.     *SepString = '\0';
  1698.     BackToken(")");
  1699.   }
  1700.   if ((++FracState) == 2)
  1701.     FracState = -1;
  1702. }
  1703.  
  1704. static void TeXNewFontType(Word Index)
  1705. {
  1706.   int NewFontFlags;
  1707.  
  1708.   NewFontFlags = (Index == FontStandard) ? 0 : CurrFontFlags | (1 << Index);
  1709.   PrFontDiff(CurrFontFlags, NewFontFlags);
  1710.   CurrFontFlags = NewFontFlags;
  1711. }
  1712.  
  1713. static void TeXEnvNewFontType(Word Index)
  1714. {
  1715.   char NToken[TOKLEN];
  1716.  
  1717.   SaveFont();
  1718.   TeXNewFontType(Index);
  1719.   assert_token("{");
  1720.   ReadToken(NToken);
  1721.   strcpy(SepString, BackSepString);
  1722.   BackToken(NToken);
  1723. }
  1724.  
  1725. static void TeXNewFontSize(Word Index)
  1726. {
  1727.   PrFontSize(CurrFontSize = (tFontSize) Index, True);
  1728. }
  1729.  
  1730. static void TeXEnvNewFontSize(Word Index)
  1731. {
  1732.   char NToken[TOKLEN];
  1733.  
  1734.   SaveFont();
  1735.   TeXNewFontSize(Index);
  1736.   assert_token("{");
  1737.   ReadToken(NToken);
  1738.   strcpy(SepString, BackSepString);
  1739.   BackToken(NToken);
  1740. }
  1741.  
  1742. static void TeXAddMarginPar(Word Index)
  1743. {
  1744.   UNUSED(Index);
  1745.  
  1746.   assert_token("{");
  1747.   SaveEnv(EnvMarginPar);
  1748. }
  1749.  
  1750. static void TeXEndHead(Word Index)
  1751. {
  1752.   UNUSED(Index);
  1753. }
  1754.  
  1755. static void TeXAddCaption(Word Index)
  1756. {
  1757.   char tmp[100];
  1758.   int cnt;
  1759.   UNUSED(Index);
  1760.  
  1761.   assert_token("{");
  1762.   if ((CurrEnv != EnvTable) && (CurrEnv != EnvTabular))
  1763.     error("caption outside of a table");
  1764.   FlushLine();
  1765.   fputs("<P><CENTER>", outfile);
  1766.   GetTableName(tmp, sizeof(tmp));
  1767.   SaveEnv(EnvCaption);
  1768.   AddLine(TableName, "");
  1769.   cnt = strlen(TableName);
  1770.   strcat(tmp, ": ");
  1771.   AddLine(tmp, " ");
  1772.   cnt += 1 + strlen(tmp);
  1773.   LeftMargin = 1;
  1774.   ActLeftMargin = cnt + 1;
  1775.   RightMargin = 70;
  1776. }
  1777.  
  1778. static void TeXHorLine(Word Index)
  1779. {
  1780.   UNUSED(Index);
  1781.  
  1782.   if (CurrEnv != EnvTabular)
  1783.     error("\\hline outside of a table");
  1784.  
  1785.   if (pThisTable->Lines[CurrRow][0])
  1786.     InitTableRow(++CurrRow);
  1787.   pThisTable->LineFlags[CurrRow] = True;
  1788.   InitTableRow(++CurrRow);
  1789. }
  1790.  
  1791. static void TeXMultiColumn(Word Index)
  1792. {
  1793.   char Token[TOKLEN], *endptr;
  1794.   int cnt;
  1795.   UNUSED(Index);
  1796.  
  1797.   if (CurrEnv != EnvTabular)
  1798.     error("\\hline outside of a table");
  1799.   if (CurrCol != 0)
  1800.     error("\\multicolumn must be in first column");
  1801.  
  1802.   assert_token("{");
  1803.   ReadToken(Token);
  1804.   assert_token("}");
  1805.   cnt = strtol(Token, &endptr, 10);
  1806.   if (*endptr != '\0')
  1807.     error("invalid numeric format to \\multicolumn");
  1808.   if (cnt != pThisTable->TColumnCount)
  1809.     error("\\multicolumn must span entire table");
  1810.   assert_token("{");
  1811.   do
  1812.   {
  1813.     ReadToken(Token);
  1814.   }
  1815.   while (strcmp(Token, "}"));
  1816.   pThisTable->MultiFlags[CurrRow] = True;
  1817. }
  1818.  
  1819. static void TeXIndex(Word Index)
  1820. {
  1821.   char Token[TOKLEN], Erg[TOKLEN];
  1822.   PIndexSave run, prev, neu;
  1823.   UNUSED(Index);
  1824.  
  1825.   assert_token("{");
  1826.   collect_token(Token, "}");
  1827.   run = FirstIndex;
  1828.   prev = NULL;
  1829.   while ((run) && (strcmp(Token, run->Name) > 0))
  1830.   {
  1831.     prev = run;
  1832.     run = run->Next;
  1833.   }
  1834.   if ((!run) || (strcmp(Token, run->Name) < 0))
  1835.   {
  1836.     neu = (PIndexSave) malloc(sizeof(TIndexSave));
  1837.     neu->Next = run;
  1838.     neu->RefCnt = 1;
  1839.     neu->Name = as_strdup(Token);
  1840.     if (!prev)
  1841.       FirstIndex = neu;
  1842.     else
  1843.       prev->Next = neu;
  1844.     run = neu;
  1845.   }
  1846.   else
  1847.     run->RefCnt++;
  1848.   as_snprintf(Erg, sizeof(Erg), "<A NAME=\"index_%s_%d\"></A>", Token, run->RefCnt);
  1849.   DoAddNormal(Erg, "");
  1850. }
  1851.  
  1852. static void FreeIndex(void)
  1853. {
  1854.   while (FirstIndex)
  1855.   {
  1856.     PIndexSave Old = FirstIndex;
  1857.     FirstIndex = Old->Next;
  1858.     if (Old->Name)
  1859.       free(Old->Name);
  1860.     free(Old);
  1861.   }
  1862. }
  1863.  
  1864. static int GetDim(Double *Factors)
  1865. {
  1866.   char Acc[TOKLEN];
  1867.   static char *UnitNames[] = {"cm", "mm", ""}, **run, *endptr;
  1868.   Double Value;
  1869.  
  1870.   assert_token("{");
  1871.   collect_token(Acc, "}");
  1872.   for (run = UnitNames; **run != '\0'; run++)
  1873.     if (!strcmp(*run, Acc + strlen(Acc) - strlen(*run)))
  1874.       break;
  1875.   if (**run == '\0')
  1876.     error("unknown unit for dimension");
  1877.   Acc[strlen(Acc) - strlen(*run)] = '\0';
  1878.   Value = strtod(Acc, &endptr);
  1879.   if (*endptr != '\0')
  1880.     error("invalid numeric format for dimension");
  1881.   return (int)(Value * Factors[run - UnitNames]);
  1882. }
  1883.  
  1884. static Double HFactors[] = { 4.666666, 0.4666666, 0 };
  1885. static Double VFactors[] = { 3.111111, 0.3111111, 0 };
  1886.  
  1887. static void TeXHSpace(Word Index)
  1888. {
  1889.   UNUSED(Index);
  1890.  
  1891.   DoAddNormal(Blanks(GetDim(HFactors)), "");
  1892. }
  1893.  
  1894. static void TeXVSpace(Word Index)
  1895. {
  1896.   int z, erg;
  1897.   UNUSED(Index);
  1898.  
  1899.   erg = GetDim(VFactors);
  1900.   FlushLine();
  1901.   for (z = 0; z < erg; z++)
  1902.     fputc('\n', outfile);
  1903. }
  1904.  
  1905. static void TeXRule(Word Index)
  1906. {
  1907.   int h = GetDim(HFactors);
  1908.   char Rule[200];
  1909.   UNUSED(Index);
  1910.  
  1911.   GetDim(VFactors);
  1912.   as_snprintf(Rule, sizeof(Rule), "<HR WIDTH=\"%d%%\" ALIGN=LEFT>", (h * 100) / 70);
  1913.   DoAddNormal(Rule, BackSepString);
  1914. }
  1915.  
  1916. static void TeXAddTabStop(Word Index)
  1917. {
  1918.   int z, n, p;
  1919.   UNUSED(Index);
  1920.  
  1921.   if (CurrEnv != EnvTabbing)
  1922.     error("tab marker outside of tabbing environment");
  1923.   if (TabStopCnt >= TABMAX)
  1924.     error("too many tab stops");
  1925.  
  1926.   n = strlen(OutLineBuffer);
  1927.   for (p = 0; p < TabStopCnt; p++)
  1928.     if (TabStops[p] > n)
  1929.       break;
  1930.   for (z = TabStopCnt - 1; z >= p; z--)
  1931.     TabStops[z + 1] = TabStops[z];
  1932.   TabStops[p] = n;
  1933.   TabStopCnt++;
  1934.  
  1935.   PrFontDiff(CurrFontFlags, 0);
  1936.   DoAddNormal("</TD><TD NOWRAP>", "");
  1937.   PrFontDiff(0, CurrFontFlags);
  1938. }
  1939.  
  1940. static void TeXJmpTabStop(Word Index)
  1941. {
  1942.   UNUSED(Index);
  1943.  
  1944.   if (CurrEnv != EnvTabbing)
  1945.     error("tab trigger outside of tabbing environment");
  1946.   if (CurrTabStop >= TabStopCnt)
  1947.     error("not enough tab stops");
  1948.  
  1949.   PrFontDiff(CurrFontFlags, 0);
  1950.   DoAddNormal("</TD><TD NOWRAP>", "");
  1951.   PrFontDiff(0, CurrFontFlags);
  1952.   CurrTabStop++;
  1953. }
  1954.  
  1955. static void TeXDoVerb(Word Index)
  1956. {
  1957.   char Token[TOKLEN], *pos, Marker;
  1958.   UNUSED(Index);
  1959.  
  1960.   ReadToken(Token);
  1961.   if (*SepString != '\0')
  1962.     error("invalid control character for \\verb");
  1963.   Marker = (*Token);
  1964.   strmov(Token, Token + 1);
  1965.   strcpy(SepString, BackSepString);
  1966.   do
  1967.   {
  1968.     DoAddNormal(SepString, "");
  1969.     pos = strchr(Token, Marker);
  1970.     if (pos)
  1971.     {
  1972.       *pos = '\0';
  1973.       DoAddNormal(Token, "");
  1974.       *SepString = '\0';
  1975.       BackToken(pos + 1);
  1976.       break;
  1977.     }
  1978.     else
  1979.     {
  1980.       DoAddNormal(Token, "");
  1981.       ReadToken(Token);
  1982.     }
  1983.   }
  1984.   while (True);
  1985. }
  1986.  
  1987. static void TeXErrEntry(Word Index)
  1988. {
  1989.   char Token[TOKLEN];
  1990.   UNUSED(Index);
  1991.  
  1992.   assert_token("{");
  1993.   ReadToken(Token);
  1994.   assert_token("}");
  1995.   assert_token("{");
  1996.   *SepString = '\0';
  1997.   BackToken("\\");
  1998.   BackToken("item");
  1999.   BackToken("[");
  2000.   BackToken(Token);
  2001.   BackToken("]");
  2002.   ErrState = 0;
  2003. }
  2004.  
  2005. static void NextErrState(void)
  2006. {
  2007.   if (ErrState < 3)
  2008.     assert_token("{");
  2009.   if (ErrState == 0)
  2010.   {
  2011.     *SepString = '\0';
  2012.     BackToken("\\");
  2013.     BackToken("begin");
  2014.     BackToken("{");
  2015.     BackToken("description");
  2016.     BackToken("}");
  2017.   }
  2018.   if ((ErrState >= 0) && (ErrState <= 2))
  2019.   {
  2020.     *SepString = '\0';
  2021.     BackToken("\\");
  2022.     BackToken("item");
  2023.     BackToken("[");
  2024.     BackToken(ErrorEntryNames[ErrState]);
  2025.     BackToken(":");
  2026.     BackToken("]");
  2027.     BackToken("\\");
  2028.     BackToken("\\");
  2029.   }
  2030.   if (ErrState == 3)
  2031.   {
  2032.     *SepString = '\0';
  2033.     BackToken("\\");
  2034.     BackToken("\\");
  2035.     BackToken(" ");
  2036.     BackToken("\\");
  2037.     BackToken("end");
  2038.     BackToken("{");
  2039.     BackToken("description");
  2040.     BackToken("}");
  2041.     ErrState = -1;
  2042.   }
  2043.   else
  2044.     ErrState++;
  2045. }
  2046.  
  2047. static void TeXWriteLabel(Word Index)
  2048. {
  2049.   char Name[TOKLEN], Value[TOKLEN];
  2050.   UNUSED(Index);
  2051.  
  2052.   assert_token("{");
  2053.   collect_token(Name, "}");
  2054.  
  2055.   if ((CurrEnv == EnvCaption) || (CurrEnv == EnvTabular))
  2056.     GetTableName(Value, sizeof(Value));
  2057.   else
  2058.   {
  2059.     GetSectionName(Value, sizeof(Value));
  2060.     if ((*Value) && (Value[strlen(Value) - 1] == '.'))
  2061.       Value[strlen(Value) - 1] = '\0';
  2062.   }
  2063.  
  2064.   AddLabel(Name, Value);
  2065.   as_snprintf(Value, sizeof(Value), "<A NAME=\"ref_%s\"></A>", Name);
  2066.   DoAddNormal(Value, "");
  2067. }
  2068.  
  2069. static void TeXWriteRef(Word Index)
  2070. {
  2071.   char Name[TOKLEN], Value[TOKLEN], HRef[TOKLEN];
  2072.   UNUSED(Index);
  2073.  
  2074.   assert_token("{");
  2075.   collect_token(Name, "}");
  2076.   GetLabel(Name, Value);
  2077.   as_snprintf(HRef, sizeof(HRef), "<A HREF=\"#ref_%s\">", Name);
  2078.   DoAddNormal(HRef, BackSepString);
  2079.   DoAddNormal(Value, "");
  2080.   DoAddNormal("</A>", "");
  2081. }
  2082.  
  2083. static void TeXWriteCitation(Word Index)
  2084. {
  2085.   char Name[TOKLEN], Value[TOKLEN], HRef[TOKLEN];
  2086.   UNUSED(Index);
  2087.  
  2088.   assert_token("{");
  2089.   collect_token(Name, "}");
  2090.   GetCite(Name, Value);
  2091.   as_snprintf(HRef, sizeof(HRef), "<A HREF=\"#cite_%s\">", Name);
  2092.   DoAddNormal(HRef, BackSepString);
  2093.   as_snprintf(Name, sizeof(Name), "[%s]", Value);
  2094.   DoAddNormal(Name, "");
  2095.   DoAddNormal("</A>", "");
  2096. }
  2097.  
  2098. static void TeXNewParagraph(Word Index)
  2099. {
  2100.   UNUSED(Index);
  2101.  
  2102.   FlushLine();
  2103.   fprintf(outfile, "<P>\n");
  2104. }
  2105.  
  2106. static void TeXContents(Word Index)
  2107. {
  2108.   FILE *file = fopen(TocName, "r");
  2109.   char Line[200], Ref[50], *ptr, *run;
  2110.   int Level;
  2111.   UNUSED(Index);
  2112.  
  2113.   if (!file)
  2114.   {
  2115.     Warning("contents file not found.");
  2116.     DoRepass = True;
  2117.     return;
  2118.   }
  2119.  
  2120.   FlushLine();
  2121.   fprintf(outfile, "<P>\n<H1>%s</H1><P>\n", ContentsName);
  2122.   while (!feof(file))
  2123.   {
  2124.     if (!fgets(Line, 199, file))
  2125.       break;
  2126.     if ((*Line != '\0') && (*Line != '\n'))
  2127.     {
  2128.       if (!strncmp(Line, BiblioName, strlen(BiblioName)))
  2129.       {
  2130.         strcpy(Ref, "bib");
  2131.         Level = 1;
  2132.       }
  2133.       else if (!strncmp(Line, IndexName, strlen(IndexName)))
  2134.       {
  2135.         strcpy(Ref, "index");
  2136.         Level = 1;
  2137.       }
  2138.       else
  2139.       {
  2140.         ptr = Ref;
  2141.         Level = 1;
  2142.         if ((*Line) && (Line[strlen(Line) - 1] == '\n'))
  2143.           Line[strlen(Line) - 1] = '\0';
  2144.         for (run = Line; *run != '\0'; run++)
  2145.           if (*run != ' ')
  2146.             break;
  2147.         for (; *run != '\0'; run++)
  2148.           if (*run == ' ')
  2149.             break;
  2150.           else if (*run == '.')
  2151.           {
  2152.             *(ptr++) = '_';
  2153.             Level++;
  2154.           }
  2155.           else if ((*run >= '0') && (*run <= '9'))
  2156.             *(ptr++) = (*run);
  2157.           else if ((*run >= 'A') && (*run <= 'Z'))
  2158.             *(ptr++) = (*run);
  2159.         *ptr = '\0';
  2160.       }
  2161.       fprintf(outfile, "<P><H%d>", Level);
  2162.       if (*Ref != '\0')
  2163.         fprintf(outfile, "<A HREF=\"#sect_%s\">", Ref);
  2164.       fputs(Line, outfile);
  2165.       if (*Ref != '\0')
  2166.         fprintf(outfile, "</A></H%d>", Level);
  2167.       fputc('\n', outfile);
  2168.     }
  2169.   }
  2170.  
  2171.   fclose(file);
  2172. }
  2173.  
  2174. static void TeXPrintIndex(Word Index)
  2175. {
  2176.   PIndexSave run;
  2177.   int i, rz;
  2178.   UNUSED(Index);
  2179.  
  2180.   FlushLine();
  2181.   fprintf(outfile, "<H1><A NAME=\"sect_index\">%s</A></H1>\n", IndexName);
  2182.   AddToc(IndexName, 0);
  2183.  
  2184.   fputs("<TABLE SUMMARY=\"Index\" BORDER=0 CELLPADDING=5>\n", outfile);
  2185.   rz = 0;
  2186.   for (run = FirstIndex; run; run = run->Next)
  2187.   {
  2188.     if ((rz % 5) == 0)
  2189.       fputs("<TR ALIGN=LEFT>\n", outfile);
  2190.     fputs("<TD VALIGN=TOP NOWRAP>", outfile);
  2191.     fputs(run->Name, outfile);
  2192.     for (i = 0; i < run->RefCnt; i++)
  2193.       fprintf(outfile, " <A HREF=\"#index_%s_%d\">%d</A>", run->Name, i + 1, i + 1);
  2194.     fputs("</TD>\n", outfile);
  2195.     if ((rz % 5) == 4)
  2196.       fputs("</TR>\n", outfile);
  2197.     rz++;
  2198.   }
  2199.   if ((rz % 5) != 0)
  2200.     fputs("</TR>\n", outfile);
  2201.   fputs("</TABLE>\n", outfile);
  2202. }
  2203.  
  2204. static void TeXParSkip(Word Index)
  2205. {
  2206.   char Token[TOKLEN];
  2207.   UNUSED(Index);
  2208.  
  2209.   ReadToken(Token);
  2210.   do
  2211.   {
  2212.     ReadToken(Token);
  2213.     if ((!strncmp(Token, "plus", 4)) || (!strncmp(Token, "minus", 5)))
  2214.     {
  2215.     }
  2216.     else
  2217.     {
  2218.       BackToken(Token);
  2219.       return;
  2220.     }
  2221.   }
  2222.   while (1);
  2223. }
  2224.  
  2225. static void TeXNLS(Word Index)
  2226. {
  2227.   char Token[TOKLEN], *Repl = "";
  2228.   Boolean Found = True;
  2229.   UNUSED(Index);
  2230.  
  2231.   *Token = '\0';
  2232.   ReadToken(Token);
  2233.   if (*SepString == '\0')
  2234.     switch (*Token)
  2235.     {
  2236.       case 'a':
  2237.         Repl = "&auml;";
  2238.         break;
  2239.       case 'e':
  2240.         Repl = "&euml;";
  2241.         break;
  2242.       case 'i':
  2243.         Repl = "&iuml;";
  2244.         break;
  2245.       case 'o':
  2246.         Repl = "&ouml;";
  2247.         break;
  2248.       case 'u':
  2249.         Repl = "&uuml;";
  2250.         break;
  2251.       case 'A':
  2252.         Repl = "&Auml;";
  2253.         break;
  2254.       case 'E':
  2255.         Repl = "&Euml;";
  2256.         break;
  2257.       case 'I':
  2258.         Repl = "&Iuml;";
  2259.         break;
  2260.       case 'O':
  2261.         Repl = "&Ouml;";
  2262.         break;
  2263.       case 'U':
  2264.         Repl = "&Uuml;";
  2265.         break;
  2266.       case 's':
  2267.         Repl = "&szlig;";
  2268.         break;
  2269.       default :
  2270.         Found = False;
  2271.     }
  2272.   else
  2273.     Found = False;
  2274.  
  2275.   if (Found)
  2276.   {
  2277.     if (strlen(Repl) > 1)
  2278.       memmove(Token + strlen(Repl), Token + 1, strlen(Token));
  2279.     memcpy(Token, Repl, strlen(Repl));
  2280.     strcpy(SepString, BackSepString);
  2281.   }
  2282.   else
  2283.     DoAddNormal("\"", BackSepString);
  2284.  
  2285.   BackToken(Token);
  2286. }
  2287.  
  2288. static void TeXNLSGrave(Word Index)
  2289. {
  2290.   char Token[TOKLEN], *Repl = "";
  2291.   Boolean Found = True;
  2292.   UNUSED(Index);
  2293.  
  2294.   *Token = '\0';
  2295.   ReadToken(Token);
  2296.   if (*SepString == '\0')
  2297.     switch (*Token)
  2298.     {
  2299.       case 'a':
  2300.         Repl = "&agrave;";
  2301.         break;
  2302.       case 'e':
  2303.         Repl = "&egrave;";
  2304.         break;
  2305.       case 'i':
  2306.         Repl = "&igrave;";
  2307.         break;
  2308.       case 'o':
  2309.         Repl = "&ograve;";
  2310.         break;
  2311.       case 'u':
  2312.         Repl = "&ugrave;";
  2313.         break;
  2314.       case 'A':
  2315.         Repl = "&Agrave;";
  2316.         break;
  2317.       case 'E':
  2318.         Repl = "&Egrave;";
  2319.         break;
  2320.       case 'I':
  2321.         Repl = "&Igrave;";
  2322.         break;
  2323.       case 'O':
  2324.         Repl = "&Ograve;";
  2325.         break;
  2326.       case 'U':
  2327.         Repl = "&Ugrave;";
  2328.         break;
  2329.       default:
  2330.         Found = False;
  2331.     }
  2332.   else
  2333.     Found = False;
  2334.  
  2335.   if (Found)
  2336.   {
  2337.     if (strlen(Repl) > 1)
  2338.       memmove(Token + strlen(Repl), Token + 1, strlen(Token));
  2339.     memcpy(Token, Repl, strlen(Repl));
  2340.     strcpy(SepString, BackSepString);
  2341.   }
  2342.   else
  2343.     DoAddNormal("\"", BackSepString);
  2344.  
  2345.   BackToken(Token);
  2346. }
  2347.  
  2348. static void TeXNLSAcute(Word Index)
  2349. {
  2350.   char Token[TOKLEN], *Repl = "";
  2351.   Boolean Found = True;
  2352.   UNUSED(Index);
  2353.  
  2354.   *Token = '\0';
  2355.   ReadToken(Token);
  2356.   if (*SepString == '\0')
  2357.     switch (*Token)
  2358.     {
  2359.       case 'a':
  2360.         Repl = "&aacute;";
  2361.         break;
  2362.       case 'e':
  2363.         Repl = "&eacute;";
  2364.         break;
  2365.       case 'i':
  2366.         Repl = "&iacute;";
  2367.         break;
  2368.       case 'o':
  2369.         Repl = "&oacute;";
  2370.         break;
  2371.       case 'u':
  2372.         Repl = "&uacute;";
  2373.         break;
  2374.       case 'A':
  2375.         Repl = "&Aacute;";
  2376.         break;
  2377.       case 'E':
  2378.         Repl = "&Eacute;";
  2379.         break;
  2380.       case 'I':
  2381.         Repl = "&Iacute;";
  2382.         break;
  2383.       case 'O':
  2384.         Repl = "&Oacute;";
  2385.         break;
  2386.       case 'U':
  2387.         Repl = "&Uacute;";
  2388.         break;
  2389.       default:
  2390.         Found = False;
  2391.     }
  2392.   else
  2393.     Found = False;
  2394.  
  2395.   if (Found)
  2396.   {
  2397.     if (strlen(Repl) > 1)
  2398.       memmove(Token + strlen(Repl), Token + 1, strlen(Token));
  2399.     memcpy(Token, Repl, strlen(Repl));
  2400.     strcpy(SepString, BackSepString);
  2401.   }
  2402.   else
  2403.     DoAddNormal("\"", BackSepString);
  2404.  
  2405.   BackToken(Token);
  2406. }
  2407.  
  2408. static void TeXNLSCirc(Word Index)
  2409. {
  2410.   char Token[TOKLEN], *Repl = "";
  2411.   Boolean Found = True;
  2412.   UNUSED(Index);
  2413.  
  2414.   *Token = '\0';
  2415.   ReadToken(Token);
  2416.   if (*SepString == '\0')
  2417.     switch (*Token)
  2418.     {
  2419.       case 'a':
  2420.         Repl = "&acirc;";
  2421.         break;
  2422.       case 'e':
  2423.         Repl = "&ecirc;";
  2424.         break;
  2425.       case 'i':
  2426.         Repl = "&icirc;";
  2427.         break;
  2428.       case 'o':
  2429.         Repl = "&ocirc;";
  2430.         break;
  2431.       case 'u':
  2432.         Repl = "&ucirc;";
  2433.         break;
  2434.       case 'A':
  2435.         Repl = "&Acirc;";
  2436.         break;
  2437.       case 'E':
  2438.         Repl = "&Ecirc;";
  2439.         break;
  2440.       case 'I':
  2441.         Repl = "&Icirc;";
  2442.         break;
  2443.       case 'O':
  2444.         Repl = "&Ocirc;";
  2445.         break;
  2446.       case 'U':
  2447.         Repl = "&Ucirc;";
  2448.         break;
  2449.       default:
  2450.         Found = False;
  2451.     }
  2452.   else
  2453.     Found = False;
  2454.  
  2455.   if (Found)
  2456.   {
  2457.     if (strlen(Repl) > 1)
  2458.       memmove(Token + strlen(Repl), Token + 1, strlen(Token));
  2459.     memcpy(Token, Repl, strlen(Repl));
  2460.     strcpy(SepString, BackSepString);
  2461.   }
  2462.   else
  2463.     DoAddNormal("\"", BackSepString);
  2464.  
  2465.   BackToken(Token);
  2466. }
  2467.  
  2468. static void TeXNLSTilde(Word Index)
  2469. {
  2470.   char Token[TOKLEN], *Repl = "";
  2471.   Boolean Found = True;
  2472.   UNUSED(Index);
  2473.  
  2474.   *Token = '\0';
  2475.   ReadToken(Token);
  2476.   if (*SepString == '\0')
  2477.     switch (*Token)
  2478.     {
  2479.       case 'n':
  2480.         Repl = "&ntilde;";
  2481.         break;
  2482.       case 'N':
  2483.         Repl = "&Ntilde;";
  2484.         break;
  2485.       default:
  2486.         Found = False;
  2487.     }
  2488.   else
  2489.     Found = False;
  2490.  
  2491.   if (Found)
  2492.   {
  2493.     if (strlen(Repl) > 1)
  2494.       memmove(Token + strlen(Repl), Token + 1, strlen(Token));
  2495.     memcpy(Token, Repl, strlen(Repl));
  2496.     strcpy(SepString, BackSepString);
  2497.   }
  2498.   else DoAddNormal("\"", BackSepString);
  2499.  
  2500.   BackToken(Token);
  2501. }
  2502.  
  2503. static void TeXCedilla(Word Index)
  2504. {
  2505.   char Token[TOKLEN];
  2506.   UNUSED(Index);
  2507.  
  2508.   assert_token("{");
  2509.   collect_token(Token, "}");
  2510.   if (!strcmp(Token, "c"))
  2511.     strcpy(Token, "&ccedil;");
  2512.   if (!strcmp(Token, "C"))
  2513.     strcpy(Token, "&Ccedil;");
  2514.  
  2515.   DoAddNormal(Token, BackSepString);
  2516. }
  2517.  
  2518. static Boolean TeXNLSSpec(char *Line)
  2519. {
  2520.   Boolean Found = True;
  2521.   char *Repl = NULL;
  2522.   int cnt = 0;
  2523.  
  2524.   if (*SepString == '\0')
  2525.     switch (*Line)
  2526.     {
  2527.       case 'o':
  2528.         cnt = 1;
  2529.         Repl = "&oslash;";
  2530.         break;
  2531.       case 'O':
  2532.         cnt = 1;
  2533.         Repl = "&Oslash;";
  2534.         break;
  2535.       case 'a':
  2536.         switch (Line[1])
  2537.         {
  2538.           case 'a':
  2539.             cnt = 2;
  2540.             Repl = "&aring;";
  2541.             break;
  2542.           case 'e':
  2543.             cnt = 2;
  2544.             Repl = "&aelig;";
  2545.             break;
  2546.           default:
  2547.             Found = False;
  2548.         }
  2549.         break;
  2550.       case 'A':
  2551.         switch (Line[1])
  2552.         {
  2553.           case 'A':
  2554.             cnt = 2;
  2555.             Repl = "&Aring;";
  2556.             break;
  2557.           case 'E':
  2558.             cnt = 2;
  2559.             Repl = "&AElig;";
  2560.             break;
  2561.           default:
  2562.             Found = False;
  2563.         }
  2564.         break;
  2565.       default:
  2566.         Found = False;
  2567.     }
  2568.  
  2569.   if (Found)
  2570.   {
  2571.     if ((int)strlen(Repl) != cnt)
  2572.       memmove(Line + strlen(Repl), Line + cnt, strlen(Line) - cnt + 1);
  2573.     memcpy(Line, Repl, strlen(Repl));
  2574.     strcpy(SepString, BackSepString);
  2575.   }
  2576.   else
  2577.     DoAddNormal("\"", BackSepString);
  2578.  
  2579.   BackToken(Line);
  2580.   return Found;
  2581. }
  2582.  
  2583. static void TeXHyphenation(Word Index)
  2584. {
  2585.   char Token[TOKLEN];
  2586.   UNUSED(Index);
  2587.  
  2588.   assert_token("{");
  2589.   collect_token(Token, "}");
  2590. }
  2591.  
  2592. static void TeXDoPot(void)
  2593. {
  2594.   char Token[TOKLEN];
  2595.  
  2596.   ReadToken(Token);
  2597.   if (!strcmp(Token, "1"))
  2598.     DoAddNormal("&sup1;", BackSepString);
  2599.   else if (!strcmp(Token, "2"))
  2600.     DoAddNormal("&sup2;", BackSepString);
  2601.   else if (!strcmp(Token, "3"))
  2602.     DoAddNormal("&sup3;", BackSepString);
  2603.   else if (!strcmp(Token, "{"))
  2604.   {
  2605.     SaveFont();
  2606.     TeXNewFontType(FontSuper);
  2607.     ReadToken(Token);
  2608.     strcpy(SepString, BackSepString);
  2609.     BackToken(Token);
  2610.   }
  2611.   else
  2612.   {
  2613.     DoAddNormal("^", BackSepString);
  2614.     AddLine(Token, "");
  2615.   }
  2616. }
  2617.  
  2618. static void TeXDoSpec(void)
  2619. {
  2620.   strcpy(BackSepString, SepString);
  2621.   TeXNLS(0);
  2622. }
  2623.  
  2624. static void TeXInclude(Word Index)
  2625. {
  2626.   char Token[2 * TOKLEN + 1], Msg[2 * TOKLEN + 1];
  2627.   UNUSED(Index);
  2628.  
  2629.   assert_token("{");
  2630.   strcpy(Token, SrcDir);
  2631.   collect_token(Token + strlen(Token), "}");
  2632.   infiles[IncludeNest] = fopen(Token, "r");
  2633.   if (!infiles[IncludeNest])
  2634.   {
  2635.     as_snprintf(Msg, sizeof(Msg), "file %s not found", Token);
  2636.     error(Msg);
  2637.   }
  2638.   else
  2639.     IncludeNest++;
  2640. }
  2641.  
  2642. static void TeXDocumentStyle(Word Index)
  2643. {
  2644.   char Token[TOKLEN];
  2645.   UNUSED(Index);
  2646.  
  2647.   ReadToken(Token);
  2648.   if (!strcmp(Token, "["))
  2649.   {
  2650.     do
  2651.     {
  2652.       ReadToken(Token);
  2653.       if (!strcmp(Token, "german"))
  2654.         SetLang(True);
  2655.     }
  2656.     while (strcmp(Token, "]"));
  2657.     assert_token("{");
  2658.     ReadToken(Token);
  2659.     if (CurrPass <= 1)
  2660.     {
  2661.       if (!as_strcasecmp(Token,  "article"))
  2662.       {
  2663.         AddInstTable(TeXTable, "section", 0, TeXNewSection);
  2664.         AddInstTable(TeXTable, "subsection", 1, TeXNewSection);
  2665.         AddInstTable(TeXTable, "subsubsection", 3, TeXNewSection);
  2666.       }
  2667.       else
  2668.       {
  2669.         AddInstTable(TeXTable, "chapter", 0, TeXNewSection);
  2670.         AddInstTable(TeXTable, "section", 1, TeXNewSection);
  2671.         AddInstTable(TeXTable, "subsection", 2, TeXNewSection);
  2672.         AddInstTable(TeXTable, "subsubsection", 3, TeXNewSection);
  2673.       }
  2674.     }
  2675.     assert_token("}");
  2676.   }
  2677. }
  2678.  
  2679. /*!------------------------------------------------------------------------
  2680.  * \fn     TeXUsePackage(Word Index)
  2681.  * \brief  parse \usepackage command
  2682.  * ------------------------------------------------------------------------ */
  2683.  
  2684. static void TeXUsePackage(Word Index)
  2685. {
  2686.   char Token[TOKLEN], Msg[2 * TOKLEN + 1];
  2687.   Boolean read_german_opt = False;
  2688.  
  2689.   UNUSED(Index);
  2690.  
  2691.   while (True)
  2692.   {
  2693.     ReadToken(Token);
  2694.     if (!strcmp(Token, "["))
  2695.     {
  2696.       do
  2697.       {
  2698.         ReadToken(Token);
  2699.         if (!strcmp(Token, "german"))
  2700.           read_german_opt = True;
  2701.       }
  2702.       while (strcmp(Token, "]"));
  2703.     }
  2704.     else if (!strcmp(Token, "{"))
  2705.     {
  2706.       ReadToken(Token);
  2707.       if (!as_strcasecmp(Token, "german"))
  2708.         SetLang(True);
  2709.       else if (!as_strcasecmp(Token, "babel"))
  2710.         SetLang(read_german_opt);
  2711.       else if (!as_strcasecmp(Token, "makeidx"));
  2712.       else if (!as_strcasecmp(Token, "hyperref"));
  2713.       else if (!as_strcasecmp(Token, "longtable"));
  2714.       else
  2715.       {
  2716.         as_snprintf(Msg, sizeof(Msg), "unknown package '%s'", Token);
  2717.         error(Msg);
  2718.       }
  2719.       assert_token("}");
  2720.       break;
  2721.     }
  2722.     else
  2723.     {
  2724.       as_snprintf(Msg, sizeof(Msg), "expecting [ or { after \\usepackage");
  2725.       error(Msg);
  2726.     }
  2727.   }
  2728. }
  2729.  
  2730. static void StartFile(char *Name)
  2731. {
  2732.   char comp[TOKLEN];
  2733.   struct stat st;
  2734.  
  2735.   /* create name ? */
  2736.  
  2737.   if (Structured)
  2738.   {
  2739.     as_snprintf(comp, sizeof(comp), "%s.dir/%s", outfilename, Name);
  2740.     Name = comp;
  2741.   }
  2742.  
  2743.   /* open file */
  2744.  
  2745.   if ((outfile = fopen(Name, "w")) == NULL)
  2746.   {
  2747.     perror(Name);
  2748.     exit(3);
  2749.   }
  2750.  
  2751.   /* write head */
  2752.  
  2753.   fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", outfile);
  2754.   fputs("<HTML>\n", outfile);
  2755.   fputs("<HEAD>\n", outfile);
  2756.   fprintf(outfile, "<META NAME=\"Author\" CONTENT=\"automatically generated by tex2html from %s\">\n", pInFileName);
  2757.   if (stat(pInFileName, &st))
  2758.     stat(Name, &st);
  2759.   strncpy(comp, ctime(&st.st_mtime), TOKLEN - 1);
  2760.   if ((*comp) && (comp[strlen(comp) - 1] == '\n'))
  2761.     comp[strlen(comp) - 1] = '\0';
  2762.   fprintf(outfile, "<META NAME=\"Last-modified\" CONTENT=\"%s\">\n", comp);
  2763. }
  2764.  
  2765. /*--------------------------------------------------------------------------*/
  2766.  
  2767. int main(int argc, char **argv)
  2768. {
  2769.   char Line[TOKLEN], Comp[TOKLEN], *p, AuxFile[200];
  2770.   int z, ergc, NumPassesLeft;
  2771.  
  2772.   /* assume defaults for flags */
  2773.  
  2774.   Structured = False;
  2775.  
  2776.   /* extract switches */
  2777.  
  2778.   ergc = 1;
  2779.   for (z = 1; z < argc; z++)
  2780.   {
  2781.     if (!strcmp(argv[z], "-w"))
  2782.       Structured = True;
  2783.     else
  2784.       argv[ergc++] = argv[z];
  2785.   }
  2786.   argc = ergc;
  2787.  
  2788.   /* do we want that ? */
  2789.  
  2790.   if (argc < 3)
  2791.   {
  2792.     fprintf(stderr, "calling convention: %s [switches] <input file> <output file>\n"
  2793.                     "switches: -w --> create structured document\n", *argv);
  2794.     exit(1);
  2795.   }
  2796.  
  2797.   pThisTable = (TTable*)calloc(1, sizeof(*pThisTable));
  2798.  
  2799.   /* save file names */
  2800.  
  2801.   pInFileName = argv[1];
  2802.   outfilename = argv[2];
  2803.  
  2804.   /* set up hash table */
  2805.  
  2806.   TeXTable = CreateInstTable(301);
  2807.  
  2808.   AddInstTable(TeXTable, "\\", 0, TeXFlushLine);
  2809.   AddInstTable(TeXTable, "par", 0, TeXNewParagraph);
  2810.   AddInstTable(TeXTable, "-", 0, TeXDummy);
  2811.   AddInstTable(TeXTable, "hyphenation", 0, TeXHyphenation);
  2812.   AddInstTable(TeXTable, "kill", 0, TeXKillLine);
  2813.   AddInstTable(TeXTable, "/", 0, TeXDummy);
  2814.   AddInstTable(TeXTable, "pagestyle", 0, TeXDummyInCurl);
  2815.   AddInstTable(TeXTable, "thispagestyle", 0, TeXDummyInCurl);
  2816.   AddInstTable(TeXTable, "sloppy", 0, TeXDummy);
  2817.   AddInstTable(TeXTable, "clearpage", 0, TeXDummy);
  2818.   AddInstTable(TeXTable, "cleardoublepage", 0, TeXDummy);
  2819.   AddInstTable(TeXTable, "topsep", 0, TeXDummyNoBrack);
  2820.   AddInstTable(TeXTable, "parskip", 0, TeXParSkip);
  2821.   AddInstTable(TeXTable, "parindent", 0, TeXDummyNoBrack);
  2822.   AddInstTable(TeXTable, "textwidth", 0, TeXDummyNoBrack);
  2823.   AddInstTable(TeXTable, "evensidemargin", 0, TeXDummyNoBrack);
  2824.   AddInstTable(TeXTable, "oddsidemargin", 0, TeXDummyNoBrack);
  2825.   AddInstTable(TeXTable, "hfuzz", 0, TeXDummyEqual);
  2826.   AddInstTable(TeXTable, "newcommand", 0, TeXNewCommand);
  2827.   AddInstTable(TeXTable, "def", 0, TeXDef);
  2828.   AddInstTable(TeXTable, "font", 0, TeXFont);
  2829.   AddInstTable(TeXTable, "documentstyle", 0, TeXDocumentStyle);
  2830.   AddInstTable(TeXTable, "documentclass", 0, TeXDocumentStyle);
  2831.   AddInstTable(TeXTable, "usepackage", 0, TeXUsePackage);
  2832.   AddInstTable(TeXTable, "appendix", 0, TeXAppendix);
  2833.   AddInstTable(TeXTable, "makeindex", 0, TeXDummy);
  2834.   AddInstTable(TeXTable, "begin", 0, TeXBeginEnv);
  2835.   AddInstTable(TeXTable, "end", 0, TeXEndEnv);
  2836.   AddInstTable(TeXTable, "item", 0, TeXItem);
  2837.   AddInstTable(TeXTable, "bibitem", 0, TeXBibItem);
  2838.   AddInstTable(TeXTable, "errentry", 0, TeXErrEntry);
  2839.   AddInstTable(TeXTable, "$", 0, TeXAddDollar);
  2840.   AddInstTable(TeXTable, "_", 0, TeXAddUnderbar);
  2841.   AddInstTable(TeXTable, "&", 0, TeXAddAmpersand);
  2842.   AddInstTable(TeXTable, "@", 0, TeXAddAt);
  2843.   AddInstTable(TeXTable, "#", 0, TeXAddImm);
  2844.   AddInstTable(TeXTable, "%", 0, TeXAddPercent);
  2845.   AddInstTable(TeXTable, "*", 0, TeXAddAsterisk);
  2846.   AddInstTable(TeXTable, "ss", 0, TeXAddSSharp);
  2847.   AddInstTable(TeXTable, "in", 0, TeXAddIn);
  2848.   AddInstTable(TeXTable, "rz", 0, TeXAddReal);
  2849.   AddInstTable(TeXTable, "mu", 0, TeXAddGreekMu);
  2850.   AddInstTable(TeXTable, "pi", 0, TeXAddGreekPi);
  2851.   AddInstTable(TeXTable, "leq", 0, TeXAddLessEq);
  2852.   AddInstTable(TeXTable, "geq", 0, TeXAddGreaterEq);
  2853.   AddInstTable(TeXTable, "neq", 0, TeXAddNotEq);
  2854.   AddInstTable(TeXTable, "mid", 0, TeXAddMid);
  2855.   AddInstTable(TeXTable, "asname", 0, TeXASName);
  2856.   AddInstTable(TeXTable, "land", 0, TeXAddLAnd);
  2857.   AddInstTable(TeXTable, "lor", 0, TeXAddLOr);
  2858.   AddInstTable(TeXTable, "oplus", 0, TeXAddOPlus);
  2859.   AddInstTable(TeXTable, "frac", 0, TeXDoFrac);
  2860.   AddInstTable(TeXTable, "rm", FontStandard, TeXNewFontType);
  2861.   AddInstTable(TeXTable, "em", FontEmphasized, TeXNewFontType);
  2862.   AddInstTable(TeXTable, "bf", FontBold, TeXNewFontType);
  2863.   AddInstTable(TeXTable, "tt", FontTeletype, TeXNewFontType);
  2864.   AddInstTable(TeXTable, "it", FontItalic, TeXNewFontType);
  2865.   AddInstTable(TeXTable, "bb", FontBold, TeXEnvNewFontType);
  2866.   AddInstTable(TeXTable, "tty", FontTeletype, TeXEnvNewFontType);
  2867.   AddInstTable(TeXTable, "ii", FontItalic, TeXEnvNewFontType);
  2868.   AddInstTable(TeXTable, "tiny", FontTiny, TeXNewFontSize);
  2869.   AddInstTable(TeXTable, "small", FontSmall, TeXNewFontSize);
  2870.   AddInstTable(TeXTable, "normalsize", FontNormalSize, TeXNewFontSize);
  2871.   AddInstTable(TeXTable, "large", FontLarge, TeXNewFontSize);
  2872.   AddInstTable(TeXTable, "huge", FontHuge, TeXNewFontSize);
  2873.   AddInstTable(TeXTable, "Huge", FontHuge, TeXNewFontSize);
  2874.   AddInstTable(TeXTable, "tin", FontTiny, TeXEnvNewFontSize);
  2875.   AddInstTable(TeXTable, "rightarrow", 0, TeXAddRightArrow);
  2876.   AddInstTable(TeXTable, "longrightarrow", 0, TeXAddLongRightArrow);
  2877.   AddInstTable(TeXTable, "leftarrow", 0, TeXAddLeftArrow);
  2878.   AddInstTable(TeXTable, "longleftarrow", 0, TeXAddLongLeftArrow);
  2879.   AddInstTable(TeXTable, "leftrightarrow", 0, TeXAddLeftRightArrow);
  2880.   AddInstTable(TeXTable, "gets", 0, TeXAddGets);
  2881.   AddInstTable(TeXTable, "marginpar", 0, TeXAddMarginPar);
  2882.   AddInstTable(TeXTable, "caption", 0, TeXAddCaption);
  2883.   AddInstTable(TeXTable, "endhead", 0, TeXEndHead);
  2884.   AddInstTable(TeXTable, "label", 0, TeXWriteLabel);
  2885.   AddInstTable(TeXTable, "ref", 0, TeXWriteRef);
  2886.   AddInstTable(TeXTable, "cite", 0, TeXWriteCitation);
  2887.   AddInstTable(TeXTable, "hline", 0, TeXHorLine);
  2888.   AddInstTable(TeXTable, "multicolumn", 0, TeXMultiColumn);
  2889.   AddInstTable(TeXTable, "ttindex", 0, TeXIndex);
  2890.   AddInstTable(TeXTable, "hspace", 0, TeXHSpace);
  2891.   AddInstTable(TeXTable, "vspace", 0, TeXVSpace);
  2892.   AddInstTable(TeXTable, "=", 0, TeXAddTabStop);
  2893.   AddInstTable(TeXTable, ">", 0, TeXJmpTabStop);
  2894.   AddInstTable(TeXTable, "verb", 0, TeXDoVerb);
  2895.   AddInstTable(TeXTable, "printindex", 0, TeXPrintIndex);
  2896.   AddInstTable(TeXTable, "tableofcontents", 0, TeXContents);
  2897.   AddInstTable(TeXTable, "rule", 0, TeXRule);
  2898.   AddInstTable(TeXTable, "\"", 0, TeXNLS);
  2899.   AddInstTable(TeXTable, "`", 0, TeXNLSGrave);
  2900.   AddInstTable(TeXTable, "'", 0, TeXNLSAcute);
  2901.   AddInstTable(TeXTable, "^", 0, TeXNLSCirc);
  2902.   AddInstTable(TeXTable, "~", 0, TeXNLSTilde);
  2903.   AddInstTable(TeXTable, "c", 0, TeXCedilla);
  2904.   AddInstTable(TeXTable, "newif", 0, TeXDummy);
  2905.   AddInstTable(TeXTable, "fi", 0, TeXDummy);
  2906.   AddInstTable(TeXTable, "ifelektor", 0, TeXDummy);
  2907.   AddInstTable(TeXTable, "elektortrue", 0, TeXDummy);
  2908.   AddInstTable(TeXTable, "elektorfalse", 0, TeXDummy);
  2909.   AddInstTable(TeXTable, "input", 0, TeXInclude);
  2910.  
  2911.   CurrPass = 0;
  2912.   NumPassesLeft = 3;
  2913.   do
  2914.   {
  2915.     CurrPass++;
  2916.  
  2917.     /* set up inclusion stack */
  2918.  
  2919.     DidEOF = False;
  2920.     IncludeNest = 0;
  2921.     *infiles = fopen(pInFileName, "r");
  2922.     if (!*infiles)
  2923.     {
  2924.       perror(pInFileName);
  2925.       exit(3);
  2926.     }
  2927.     else
  2928.       IncludeNest++;
  2929.     SetSrcDir(pInFileName);
  2930.  
  2931.     /* preset state variables */
  2932.  
  2933.     for (z = 0; z < CHAPMAX; Chapters[z++] = 0);
  2934.     TableNum = 0;
  2935.     TabStopCnt = 0;
  2936.     CurrTabStop = 0;
  2937.     ErrState = FracState = -1;
  2938.     InAppendix = False;
  2939.     EnvStack = NULL;
  2940.     CurrEnv = EnvNone;
  2941.     CurrListDepth = 0;
  2942.     ActLeftMargin = LeftMargin = 1;
  2943.     RightMargin = 70;
  2944.     EnumCounter = 0;
  2945.     InListItem = False;
  2946.     InitFont();
  2947.     CurrLine = 0;
  2948.     InitLabels();
  2949.     InitCites();
  2950.     InitToc();
  2951.     FirstIndex = NULL;
  2952.     *SideMargin = '\0';
  2953.     DoRepass = False;
  2954.     BibIndent = BibCounter = 0;
  2955.     GermanMode = True;
  2956.     SetLang(False);
  2957.  
  2958.     /* open help files */
  2959.  
  2960.     strmaxcpy(TocName, pInFileName, sizeof(TocName));
  2961.     p = strrchr(TocName, '.');
  2962.     if (p)
  2963.       *p = '\0';
  2964.     strcat(TocName, ".htoc");
  2965.  
  2966.     strmaxcpy(AuxFile, pInFileName, sizeof(AuxFile));
  2967.     p = strrchr(AuxFile, '.');
  2968.     if (p)
  2969.       *p = '\0';
  2970.     strcat(AuxFile, ".haux");
  2971.     ReadAuxFile(AuxFile);
  2972.  
  2973.     if (!strcmp(outfilename, "-"))
  2974.     {
  2975.       if (Structured)
  2976.       {
  2977.         printf("%s: structured write must be to a directory\n", *argv);
  2978.         exit(1);
  2979.       }
  2980.       else
  2981.         outfile = stdout;
  2982.     }
  2983.  
  2984.     /* do we need to make a directory ? */
  2985.  
  2986.     else if (Structured)
  2987.     {
  2988.       as_snprintf(Line, sizeof(Line), "%s.dir", outfilename);
  2989. #if (defined _WIN32) && (!defined __CYGWIN32__)
  2990.       mkdir(Line);
  2991. #elif (defined __MSDOS__)
  2992.       mkdir(Line);
  2993. #else
  2994.       mkdir(Line, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
  2995. #endif
  2996.       StartFile("intro.html");
  2997.     }
  2998.  
  2999.     /* otherwise open the single file */
  3000.  
  3001.     else
  3002.       StartFile(outfilename);
  3003.  
  3004.     /* start to parse */
  3005.  
  3006.     while (1)
  3007.     {
  3008.       if (!ReadToken(Line))
  3009.         break;
  3010.       if (!strcmp(Line, "\\"))
  3011.       {
  3012.         strcpy(BackSepString, SepString);
  3013.         if (!ReadToken(Line))
  3014.           error("unexpected end of file");
  3015.         if (*SepString != '\0')
  3016.           BackToken(Line);
  3017.         else if (!LookupInstTable(TeXTable, Line))
  3018.           if (!TeXNLSSpec(Line))
  3019.           {
  3020.             as_snprintf(Comp, sizeof(Comp), "unknown TeX command %s", Line);
  3021.             Warning(Comp);
  3022.           }
  3023.       }
  3024.       else if (!strcmp(Line, "$"))
  3025.       {
  3026.         InMathMode = !InMathMode;
  3027.         if (InMathMode)
  3028.         {
  3029.           strcpy(BackSepString, SepString);
  3030.           ReadToken(Line);
  3031.           strcpy(SepString, BackSepString);
  3032.           BackToken(Line);
  3033.         }
  3034.       }
  3035.       else if (!strcmp(Line, "&"))
  3036.         NextTableColumn();
  3037.       else if ((!strcmp(Line, "^")) && (InMathMode))
  3038.         TeXDoPot();
  3039.       else if ((!strcmp(Line, "\"")) && (GermanMode))
  3040.         TeXDoSpec();
  3041.       else if (!strcmp(Line, "{"))
  3042.         SaveFont();
  3043.       else if (!strcmp(Line, "}"))
  3044.       {
  3045.         if (FontNest > 0)
  3046.           RestoreFont();
  3047.         else if (ErrState >= 0)
  3048.           NextErrState();
  3049.         else if (FracState >= 0)
  3050.           NextFracState();
  3051.         else switch (CurrEnv)
  3052.         {
  3053.           case EnvMarginPar:
  3054.             RestoreEnv();
  3055.             break;
  3056.           case EnvCaption:
  3057.             FlushLine();
  3058.             fputs("</CENTER><P>\n", outfile);
  3059.             RestoreEnv();
  3060.             break;
  3061.           case EnvHeading:
  3062.             EndSectionHeading();
  3063.             RestoreEnv();
  3064.             break;
  3065.           default:
  3066.             RestoreFont();
  3067.         }
  3068.       }
  3069.       else
  3070.         DoAddNormal(Line, SepString);
  3071.     }
  3072.     FlushLine();
  3073.  
  3074.     fputs("</HTML>\n", outfile);
  3075.  
  3076.     for (z = 0; z < IncludeNest; fclose(infiles[z++]));
  3077.     fclose(outfile);
  3078.  
  3079.     unlink(AuxFile);
  3080.     PrintLabels(AuxFile);
  3081.     PrintCites(AuxFile);
  3082.     PrintToc(TocName);
  3083.  
  3084.     FreeLabels();
  3085.     FreeCites();
  3086.     FreeToc();
  3087.     FreeIndex();
  3088.     FreeFontStack();
  3089.  
  3090.     NumPassesLeft--;
  3091.     if (DoRepass)
  3092.       fprintf(stderr, "additional pass needed\n");
  3093.   }
  3094.   while (DoRepass && NumPassesLeft);
  3095.  
  3096.   DestroyInstTable(TeXTable);
  3097.  
  3098.   if (DoRepass)
  3099.   {
  3100.     fprintf(stderr, "additional passes needed but cowardly not done\n");
  3101.     return 3;
  3102.   }
  3103.   else
  3104.   {
  3105.     fprintf(stderr, "%d pass(es) needed\n", CurrPass);
  3106.     return 0;
  3107.   }
  3108. }
  3109.  
  3110. #ifdef CKMALLOC
  3111. #undef malloc
  3112. #undef realloc
  3113.  
  3114. void *ckmalloc(size_t s)
  3115. {
  3116.   void *tmp = malloc(s);
  3117.   if (!tmp)
  3118.   {
  3119.     fprintf(stderr, "allocation error(malloc): out of memory");
  3120.     exit(255);
  3121.   }
  3122.   return tmp;
  3123. }
  3124.  
  3125. void *ckrealloc(void *p, size_t s)
  3126. {
  3127.   void *tmp = realloc(p, s);
  3128.   if (!tmp)
  3129.   {
  3130.     fprintf(stderr, "allocation error(realloc): out of memory");
  3131.     exit(255);
  3132.   }
  3133.   return tmp;
  3134. }
  3135. #endif
  3136.