Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

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