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