Subversion Repositories pentevo

Rev

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

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