Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 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