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 300
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 ThisTable;
105 static int CurrRow, CurrCol;
106 static char SrcDir[TOKLEN + 1];
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
ChkStack(void)123 void ChkStack(void)
124 {
125 }
126
SetSrcDir(const char * pSrcFile)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
error(char * Msg)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
SetLang(Boolean IsGerman)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
GetNext(char * Src,char * Dest)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
ReadAuxFile(char * Name)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
issep(char inp)242 static Boolean issep(char inp)
243 {
244 return ((inp == ' ') || (inp == '\t') || (inp == '\n'));
245 }
246
isalphanum(char inp)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
GetChar(void)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
ReadToken(char * Dest)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
BackToken(char * Token)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
assert_token(char * ref)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
collect_token(char * dest,char * term)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
PutLine(Boolean DoBlock)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
AddLine(const char * Part,char * Sep)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
AddSideMargin(const char * Part,char * Sep)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
FlushLine(void)566 static void FlushLine(void)
567 {
568 if (*OutLineBuffer != '\0')
569 {
570 PutLine(False);
571 *OutLineBuffer = '\0';
572 }
573 }
574
ResetLine(void)575 static void ResetLine(void)
576 {
577 *OutLineBuffer = '\0';
578 }
579
AddTableEntry(const char * Part,char * Sep)580 static void AddTableEntry(const char *Part, char *Sep)
581 {
582 char *Ptr = ThisTable.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 ThisTable.Lines[CurrRow][CurrCol] = Ptr;
607 }
608
DoAddNormal(const char * Part,char * Sep)609 static void DoAddNormal(const char *Part, char *Sep)
610 {
611 if (!strcmp(Part, "<"))
612 Part = "<";
613 else if (!strcmp(Part, ">"))
614 Part = ">";
615 else if (!strcmp(Part, "&"))
616 Part = "&";
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
PrFontDiff(int OldFlags,int NewFlags)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
PrFontSize(tFontSize Type,Boolean On)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
SaveEnv(EnvType NewEnv)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
RestoreEnv(void)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
InitTableRow(int Index)712 static void InitTableRow(int Index)
713 {
714 int z;
715
716 for (z = 0; z < ThisTable.TColumnCount; ThisTable.Lines[Index][z++] = NULL);
717 ThisTable.MultiFlags[Index] = False;
718 ThisTable.LineFlags[Index] = False;
719 }
720
NextTableColumn(void)721 static void NextTableColumn(void)
722 {
723 if (CurrEnv != EnvTabular)
724 error("table separation char not within tabular environment");
725
726 if ((ThisTable.MultiFlags[CurrRow])
727 || (CurrCol >= ThisTable.TColumnCount))
728 error("too many columns within row");
729
730 CurrCol++;
731 }
732
DumpTable(void)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 = ThisTable.Lines[CurrRow][0] ? CurrRow + 1 : CurrRow;
742 firsttext = -1;
743 for (colz = colptr = 0; colz < ThisTable.ColumnCount; colz++)
744 if (ThisTable.ColTypes[colz] == ColBar)
745 ThisTable.ColLens[colz] = 1;
746 else
747 {
748 ml = 0;
749 for (rowz = 0; rowz < RowCnt; rowz++)
750 if ((!ThisTable.LineFlags[rowz]) && (!ThisTable.MultiFlags[rowz]))
751 {
752 l = (!ThisTable.Lines[rowz][colptr]) ? 0 : strlen(ThisTable.Lines[rowz][colptr]);
753 if (ml < l)
754 ml = l;
755 }
756 ThisTable.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 < ThisTable.ColumnCount; colz++)
764 if (ThisTable.ColTypes[colz] != ColBar)
765 TextCnt++;
766
767 /* get total width */
768
769 for (colz = sumlen = 0; colz < ThisTable.ColumnCount; sumlen += ThisTable.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 ((!ThisTable.LineFlags[rowz]) && (ThisTable.MultiFlags[rowz]))
779 {
780 l = (!ThisTable.Lines[rowz][0]) ? 0 : strlen(ThisTable.Lines[rowz][0]);
781 if (ml < l)
782 ml = l;
783 }
784 if (ml + 4 > sumlen)
785 {
786 diff = ml + 4 - sumlen;
787 ThisTable.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 (!ThisTable.LineFlags[rowz])
803 break;
804
805 /* find last text line */
806
807 for (rowz2 = rowz; rowz2 < RowCnt; rowz2++)
808 if (ThisTable.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) && (ThisTable.LineFlags[rowz2 + 1]) && (ThisTable.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 < ((ThisTable.MultiFlags[rowz])?firsttext + 1:ThisTable.ColumnCount); colz++)
829 if (ThisTable.ColTypes[colz] != ColBar)
830 {
831 /* start a column */
832
833 fprintf(outfile, "<%s VALIGN=TOP NOWRAP", ColTag);
834 if (ThisTable.MultiFlags[rowz])
835 fprintf(outfile, " COLSPAN=%d", TextCnt);
836 switch (ThisTable.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 (ThisTable.Lines[rowz3][colptr])
856 fputs(ThisTable.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 < ThisTable.ColumnCount; colz++)
874 if (ThisTable.Lines[rowz3][colz])
875 {
876 free(ThisTable.Lines[rowz3][colz]);
877 ThisTable.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
GetTableName(char * Dest,size_t DestSize)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
GetSectionName(char * Dest,size_t DestSize)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
TeXFlushLine(Word Index)919 static void TeXFlushLine(Word Index)
920 {
921 UNUSED(Index);
922
923 if (CurrEnv == EnvTabular)
924 {
925 for (CurrCol++; CurrCol < ThisTable.TColumnCount; ThisTable.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
TeXKillLine(Word Index)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
TeXDummy(Word Index)962 static void TeXDummy(Word Index)
963 {
964 UNUSED(Index);
965 }
966
TeXDummyEqual(Word Index)967 static void TeXDummyEqual(Word Index)
968 {
969 char Token[TOKLEN];
970 UNUSED(Index);
971
972 assert_token("=");
973 ReadToken(Token);
974 }
975
TeXDummyNoBrack(Word Index)976 static void TeXDummyNoBrack(Word Index)
977 {
978 char Token[TOKLEN];
979 UNUSED(Index);
980
981 ReadToken(Token);
982 }
983
TeXDummyInCurl(Word Index)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
TeXNewCommand(Word Index)994 static void TeXNewCommand(Word Index)
995 {
996 char Token[TOKLEN];
997 int level;
998 UNUSED(Index);
999
1000 assert_token("{");
1001 assert_token("\\");
1002 ReadToken(Token);
1003 assert_token("}");
1004 ReadToken(Token);
1005 if (!strcmp(Token, "["))
1006 {
1007 ReadToken(Token);
1008 assert_token("]");
1009 }
1010 assert_token("{");
1011 level = 1;
1012 do
1013 {
1014 ReadToken(Token);
1015 if (!strcmp(Token, "{"))
1016 level++;
1017 else if (!strcmp(Token, "}"))
1018 level--;
1019 }
1020 while (level != 0);
1021 }
1022
TeXDef(Word Index)1023 static void TeXDef(Word Index)
1024 {
1025 char Token[TOKLEN];
1026 int level;
1027 UNUSED(Index);
1028
1029 assert_token("\\");
1030 ReadToken(Token);
1031 assert_token("{");
1032 level = 1;
1033 do
1034 {
1035 ReadToken(Token);
1036 if (!strcmp(Token, "{"))
1037 level++;
1038 else if (!strcmp(Token, "}"))
1039 level--;
1040 }
1041 while (level != 0);
1042 }
1043
TeXFont(Word Index)1044 static void TeXFont(Word Index)
1045 {
1046 char Token[TOKLEN];
1047 UNUSED(Index);
1048
1049 assert_token("\\");
1050 ReadToken(Token);
1051 assert_token("=");
1052 ReadToken(Token);
1053 ReadToken(Token);
1054 assert_token("\\");
1055 ReadToken(Token);
1056 }
1057
TeXAppendix(Word Index)1058 static void TeXAppendix(Word Index)
1059 {
1060 int z;
1061 UNUSED(Index);
1062
1063 InAppendix = True;
1064 *Chapters = -1;
1065 for (z = 1; z < CHAPMAX; Chapters[z++] = 0);
1066 }
1067
1068 static int LastLevel;
1069
TeXNewSection(Word Level)1070 static void TeXNewSection(Word Level)
1071 {
1072 int z;
1073
1074 if (Level >= CHAPMAX)
1075 return;
1076
1077 FlushLine();
1078 fputc('\n', outfile);
1079
1080 assert_token("{");
1081 LastLevel = Level;
1082 SaveEnv(EnvHeading);
1083 RightMargin = 200;
1084
1085 Chapters[Level]++;
1086 for (z = Level + 1; z < CHAPMAX; Chapters[z++] = 0);
1087 if (Level == 0)
1088 TableNum = 0;
1089 }
1090
EndSectionHeading(void)1091 static void EndSectionHeading(void)
1092 {
1093 int Level = LastLevel;
1094 char Line[TOKLEN], Title[TOKLEN], *rep;
1095
1096 strcpy(Title, OutLineBuffer);
1097 *OutLineBuffer = '\0';
1098
1099 fprintf(outfile, "<H%d>", Level + 1);
1100
1101 *Line = '\0';
1102 if (Level < 3)
1103 {
1104 GetSectionName(Line, sizeof(Line));
1105 fprintf(outfile, "<A NAME=\"sect_");
1106 for (rep = Line; *rep; rep++)
1107 fputc((*rep == '.') ? '_' : *rep, outfile);
1108 fprintf(outfile, "\">");
1109 as_snprcatf(Line, sizeof(Line), " ");
1110 }
1111 as_snprcatf(Line, sizeof(Line), "%s", Title);
1112
1113 fprintf(outfile, "%s", Line);
1114
1115 if (Level < 3)
1116 {
1117 fputs("</A>", outfile);
1118 GetSectionName(Line, sizeof(Line));
1119 as_snprcatf(Line, sizeof(Line), " %s", Title);
1120 AddToc(Line, 0);
1121 }
1122
1123 fprintf(outfile, "</H%d>\n", Level + 1);
1124 }
1125
GetEnvType(char * Name)1126 static EnvType GetEnvType(char *Name)
1127 {
1128 EnvType z;
1129
1130 if (!strcmp(Name, "longtable"))
1131 return EnvTabular;
1132 for (z = EnvNone + 1; z < EnvCount; z++)
1133 if (!strcmp(Name, EnvNames[z]))
1134 return z;
1135
1136 error("unknown environment");
1137 return EnvNone;
1138 }
1139
TeXBeginEnv(Word Index)1140 static void TeXBeginEnv(Word Index)
1141 {
1142 char EnvName[TOKLEN], Add[TOKLEN], *p;
1143 EnvType NEnv;
1144 Boolean done;
1145 TColumn NCol;
1146 UNUSED(Index);
1147
1148 assert_token("{");
1149 ReadToken(EnvName);
1150 if ((NEnv = GetEnvType(EnvName)) == EnvTable)
1151 {
1152 ReadToken(Add);
1153 if (!strcmp(Add, "*"))
1154 assert_token("}");
1155 else if (strcmp(Add, "}"))
1156 error("unknown table environment");
1157 }
1158 else
1159 assert_token("}");
1160
1161 if (NEnv != EnvVerbatim)
1162 SaveEnv(NEnv);
1163
1164 switch (NEnv)
1165 {
1166 case EnvDocument:
1167 fputs("</HEAD>\n", outfile);
1168 fputs("<BODY>\n", outfile);
1169 break;
1170 case EnvItemize:
1171 FlushLine();
1172 fprintf(outfile, "<UL>\n");
1173 ++CurrListDepth;
1174 ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
1175 RightMargin = 70;
1176 EnumCounter = 0;
1177 InListItem = False;
1178 break;
1179 case EnvDescription:
1180 FlushLine();
1181 fprintf(outfile, "<DL COMPACT>\n");
1182 ++CurrListDepth;
1183 ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
1184 RightMargin = 70;
1185 EnumCounter = 0;
1186 InListItem = False;
1187 break;
1188 case EnvEnumerate:
1189 FlushLine();
1190 fprintf(outfile, "<OL>\n");
1191 ++CurrListDepth;
1192 ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
1193 RightMargin = 70;
1194 EnumCounter = 0;
1195 InListItem = False;
1196 break;
1197 case EnvBiblio:
1198 FlushLine();
1199 fprintf(outfile, "<P>\n");
1200 fprintf(outfile, "<H1><A NAME=\"sect_bib\">%s</A></H1>\n<DL COMPACT>\n", BiblioName);
1201 assert_token("{");
1202 ReadToken(Add);
1203 assert_token("}");
1204 ActLeftMargin = LeftMargin = 4 + (BibIndent = strlen(Add));
1205 AddToc(BiblioName, 0);
1206 break;
1207 case EnvVerbatim:
1208 FlushLine();
1209 fprintf(outfile, "<PRE>\n");
1210 if ((*BufferLine != '\0') && (*BufferPtr != '\0'))
1211 {
1212 fprintf(outfile, "%s", BufferPtr);
1213 *BufferLine = '\0';
1214 BufferPtr = BufferLine;
1215 }
1216 do
1217 {
1218 if (!fgets(Add, TOKLEN - 1, infiles[IncludeNest - 1]))
1219 break;
1220 CurrLine++;
1221 done = strstr(Add, "\\end{verbatim}") != NULL;
1222 if (!done)
1223 {
1224 for (p = Add; *p != '\0';)
1225 if (*p == '<')
1226 {
1227 memmove(p + 3, p, strlen(p) + 1);
1228 memcpy(p, "<", 4);
1229 p += 4;
1230 }
1231 else if (*p == '>')
1232 {
1233 memmove(p + 3, p, strlen(p) + 1);
1234 memcpy(p, ">", 4);
1235 p += 4;
1236 }
1237 else
1238 p++;
1239 fprintf(outfile, "%s", Add);
1240 }
1241 }
1242 while (!done);
1243 fprintf(outfile, "\n</PRE>\n");
1244 break;
1245 case EnvQuote:
1246 FlushLine();
1247 fprintf(outfile, "<BLOCKQUOTE>\n");
1248 ActLeftMargin = LeftMargin = 5;
1249 RightMargin = 70;
1250 break;
1251 case EnvTabbing:
1252 FlushLine();
1253 fputs("<TABLE SUMMARY=\"No Summary\" CELLPADDING=2>\n", outfile);
1254 TabStopCnt = 0;
1255 CurrTabStop = 0;
1256 RightMargin = TOKLEN - 1;
1257 AddLine("<TR><TD NOWRAP>", "");
1258 PrFontDiff(0, CurrFontFlags);
1259 break;
1260 case EnvTable:
1261 ReadToken(Add);
1262 if (strcmp(Add, "["))
1263 BackToken(Add);
1264 else
1265 {
1266 do
1267 {
1268 ReadToken(Add);
1269 }
1270 while (strcmp(Add, "]"));
1271 }
1272 FlushLine();
1273 fputc('\n', outfile);
1274 ++TableNum;
1275 break;
1276 case EnvCenter:
1277 FlushLine();
1278 fputs("<CENTER>\n", outfile);
1279 break;
1280 case EnvRaggedRight:
1281 FlushLine();
1282 fputs("<DIV ALIGN=LEFT>\n", outfile);
1283 break;
1284 case EnvRaggedLeft:
1285 FlushLine();
1286 fputs("<DIV ALIGN=RIGHT>\n", outfile);
1287 break;
1288 case EnvTabular:
1289 FlushLine();
1290 assert_token("{");
1291 ThisTable.ColumnCount = ThisTable.TColumnCount = 0;
1292 do
1293 {
1294 ReadToken(Add);
1295 done = !strcmp(Add, "}");
1296 if (!done)
1297 {
1298 if (ThisTable.ColumnCount >= MAXCOLS)
1299 error("too many columns in table");
1300 NCol = ColLeft;
1301 if (!strcmp(Add, "|"))
1302 NCol = ColBar;
1303 else if (!strcmp(Add, "l"))
1304 NCol = ColLeft;
1305 else if (!strcmp(Add, "r"))
1306 NCol = ColRight;
1307 else if (!strcmp(Add, "c"))
1308 NCol = ColCenter;
1309 else
1310 error("unknown table column descriptor");
1311 if ((ThisTable.ColTypes[ThisTable.ColumnCount++] = NCol) != ColBar)
1312 ThisTable.TColumnCount++;
1313 }
1314 }
1315 while (!done);
1316 InitTableRow(CurrRow = 0);
1317 CurrCol = 0;
1318 break;
1319 default:
1320 break;
1321 }
1322 }
1323
TeXEndEnv(Word Index)1324 static void TeXEndEnv(Word Index)
1325 {
1326 char EnvName[TOKLEN], Add[TOKLEN];
1327 EnvType NEnv;
1328 UNUSED(Index);
1329
1330 assert_token("{");
1331 ReadToken(EnvName);
1332 if ((NEnv = GetEnvType(EnvName)) == EnvTable)
1333 {
1334 ReadToken(Add);
1335 if (!strcmp(Add, "*"))
1336 assert_token("}");
1337 else if (strcmp(Add, "}"))
1338 error("unknown table environment");
1339 }
1340 else
1341 assert_token("}");
1342
1343 if (!EnvStack)
1344 error("end without begin");
1345 if (CurrEnv != NEnv)
1346 error("begin and end of environment do not match");
1347
1348 switch (CurrEnv)
1349 {
1350 case EnvDocument:
1351 FlushLine();
1352 fputs("</BODY>\n", outfile);
1353 break;
1354 case EnvItemize:
1355 if (InListItem)
1356 AddLine("</LI>", "");
1357 FlushLine();
1358 fprintf(outfile, "</UL>\n");
1359 break;
1360 case EnvDescription:
1361 if (InListItem)
1362 AddLine("</DD>", "");
1363 FlushLine();
1364 fprintf(outfile, "</DL>\n");
1365 break;
1366 case EnvEnumerate:
1367 if (InListItem)
1368 AddLine("</LI>", "");
1369 FlushLine();
1370 fprintf(outfile, "</OL>\n");
1371 break;
1372 case EnvQuote:
1373 FlushLine();
1374 fprintf(outfile, "</BLOCKQUOTE>\n");
1375 break;
1376 case EnvBiblio:
1377 FlushLine();
1378 fprintf(outfile, "</DL>\n");
1379 break;
1380 case EnvTabbing:
1381 PrFontDiff(CurrFontFlags, 0);
1382 AddLine("</TD></TR>", "");
1383 FlushLine();
1384 fputs("</TABLE>", outfile);
1385 break;
1386 case EnvCenter:
1387 FlushLine();
1388 fputs("</CENTER>\n", outfile);
1389 break;
1390 case EnvRaggedRight:
1391 case EnvRaggedLeft:
1392 FlushLine();
1393 fputs("</DIV>\n", outfile);
1394 break;
1395 case EnvTabular:
1396 DumpTable();
1397 break;
1398 case EnvTable:
1399 FlushLine(); fputc('\n', outfile);
1400 break;
1401 default:
1402 break;
1403 }
1404
1405 RestoreEnv();
1406 }
1407
TeXItem(Word Index)1408 static void TeXItem(Word Index)
1409 {
1410 char Token[TOKLEN], Acc[TOKLEN];
1411 UNUSED(Index);
1412
1413 if (InListItem)
1414 AddLine((CurrEnv == EnvDescription) ? "</DD>" : "</LI>", "");
1415 FlushLine();
1416 InListItem = True;
1417 switch(CurrEnv)
1418 {
1419 case EnvItemize:
1420 fprintf(outfile, "<LI>");
1421 LeftMargin = ActLeftMargin - 3;
1422 break;
1423 case EnvEnumerate:
1424 fprintf(outfile, "<LI>");
1425 LeftMargin = ActLeftMargin - 4;
1426 break;
1427 case EnvDescription:
1428 ReadToken(Token);
1429 if (strcmp(Token, "["))
1430 BackToken(Token);
1431 else
1432 {
1433 collect_token(Acc, "]");
1434 LeftMargin = ActLeftMargin - 4;
1435 fprintf(outfile, "<DT>%s", Acc);
1436 }
1437 fprintf(outfile, "<DD>");
1438 break;
1439 default:
1440 error("\\item not in a list environment");
1441 }
1442 }
1443
TeXBibItem(Word Index)1444 static void TeXBibItem(Word Index)
1445 {
1446 char NumString[20], Token[TOKLEN], Name[TOKLEN], Value[TOKLEN];
1447 UNUSED(Index);
1448
1449 if (CurrEnv != EnvBiblio)
1450 error("\\bibitem not in bibliography environment");
1451
1452 assert_token("{");
1453 collect_token(Name, "}");
1454
1455 FlushLine();
1456 AddLine("<DT>", "");
1457 ++BibCounter;
1458
1459 LeftMargin = ActLeftMargin - BibIndent - 3;
1460 as_snprintf(Value, sizeof(Value), "<A NAME=\"cite_%s\">", Name);
1461 DoAddNormal(Value, "");
1462 as_snprintf(NumString, sizeof(NumString), "[%*d] </A><DD>", BibIndent, BibCounter);
1463 AddLine(NumString, "");
1464 as_snprintf(NumString, sizeof(NumString), "%d", BibCounter);
1465 AddCite(Name, NumString);
1466 ReadToken(Token);
1467 *SepString = '\0';
1468 BackToken(Token);
1469 }
1470
TeXAddDollar(Word Index)1471 static void TeXAddDollar(Word Index)
1472 {
1473 UNUSED(Index);
1474
1475 DoAddNormal("$", BackSepString);
1476 }
1477
TeXAddUnderbar(Word Index)1478 static void TeXAddUnderbar(Word Index)
1479 {
1480 UNUSED(Index);
1481
1482 DoAddNormal("_", BackSepString);
1483 }
1484
1485 #if 0
1486 static void TeXAddPot(Word Index)
1487 {
1488 UNUSED(Index);
1489
1490 DoAddNormal("^", BackSepString);
1491 }
1492 #endif
1493
TeXAddAmpersand(Word Index)1494 static void TeXAddAmpersand(Word Index)
1495 {
1496 UNUSED(Index);
1497
1498 DoAddNormal("&", BackSepString);
1499 }
1500
TeXAddAt(Word Index)1501 static void TeXAddAt(Word Index)
1502 {
1503 UNUSED(Index);
1504
1505 DoAddNormal("@", BackSepString);
1506 }
1507
TeXAddImm(Word Index)1508 static void TeXAddImm(Word Index)
1509 {
1510 UNUSED(Index);
1511
1512 DoAddNormal("#", BackSepString);
1513 }
1514
TeXAddPercent(Word Index)1515 static void TeXAddPercent(Word Index)
1516 {
1517 UNUSED(Index);
1518
1519 DoAddNormal("%", BackSepString);
1520 }
1521
TeXAddAsterisk(Word Index)1522 static void TeXAddAsterisk(Word Index)
1523 {
1524 UNUSED(Index);
1525
1526 DoAddNormal("*", BackSepString);
1527 }
1528
TeXAddSSharp(Word Index)1529 static void TeXAddSSharp(Word Index)
1530 {
1531 UNUSED(Index);
1532
1533 DoAddNormal("ß", BackSepString);
1534 }
1535
TeXAddIn(Word Index)1536 static void TeXAddIn(Word Index)
1537 {
1538 UNUSED(Index);
1539
1540 DoAddNormal("in", BackSepString);
1541 }
1542
TeXAddReal(Word Index)1543 static void TeXAddReal(Word Index)
1544 {
1545 UNUSED(Index);
1546
1547 DoAddNormal("R", BackSepString);
1548 }
1549
TeXAddGreekMu(Word Index)1550 static void TeXAddGreekMu(Word Index)
1551 {
1552 UNUSED(Index);
1553
1554 DoAddNormal("µ", BackSepString);
1555 }
1556
TeXAddGreekPi(Word Index)1557 static void TeXAddGreekPi(Word Index)
1558 {
1559 UNUSED(Index);
1560
1561 DoAddNormal("Pi", BackSepString);
1562 }
1563
TeXAddLessEq(Word Index)1564 static void TeXAddLessEq(Word Index)
1565 {
1566 UNUSED(Index);
1567
1568 DoAddNormal("<=", BackSepString);
1569 }
1570
TeXAddGreaterEq(Word Index)1571 static void TeXAddGreaterEq(Word Index)
1572 {
1573 UNUSED(Index);
1574
1575 DoAddNormal(">=", BackSepString);
1576 }
1577
TeXAddNotEq(Word Index)1578 static void TeXAddNotEq(Word Index)
1579 {
1580 UNUSED(Index);
1581
1582 DoAddNormal("<>", BackSepString);
1583 }
1584
TeXAddMid(Word Index)1585 static void TeXAddMid(Word Index)
1586 {
1587 UNUSED(Index);
1588
1589 DoAddNormal("|", BackSepString);
1590 }
1591
TeXAddRightArrow(Word Index)1592 static void TeXAddRightArrow(Word Index)
1593 {
1594 UNUSED(Index);
1595
1596 DoAddNormal("->", BackSepString);
1597 }
1598
TeXAddLongRightArrow(Word Index)1599 static void TeXAddLongRightArrow(Word Index)
1600 {
1601 UNUSED(Index);
1602
1603 DoAddNormal("-->", BackSepString);
1604 }
1605
TeXAddLeftArrow(Word Index)1606 static void TeXAddLeftArrow(Word Index)
1607 {
1608 UNUSED(Index);
1609
1610 DoAddNormal("<-", BackSepString);
1611 }
1612
TeXAddLeftRightArrow(Word Index)1613 static void TeXAddLeftRightArrow(Word Index)
1614 {
1615 UNUSED(Index);
1616
1617 DoAddNormal("<->", BackSepString);
1618 }
1619
TeXDoFrac(Word Index)1620 static void TeXDoFrac(Word Index)
1621 {
1622 UNUSED(Index);
1623
1624 assert_token("{");
1625 *SepString = '\0';
1626 BackToken("(");
1627 FracState = 0;
1628 }
1629
NextFracState(void)1630 static void NextFracState(void)
1631 {
1632 if (FracState == 0)
1633 {
1634 assert_token("{");
1635 *SepString = '\0';
1636 BackToken(")");
1637 BackToken("/");
1638 BackToken("(");
1639 }
1640 else if (FracState == 1)
1641 {
1642 *SepString = '\0';
1643 BackToken(")");
1644 }
1645 if ((++FracState) == 2)
1646 FracState = -1;
1647 }
1648
TeXNewFontType(Word Index)1649 static void TeXNewFontType(Word Index)
1650 {
1651 int NewFontFlags;
1652
1653 NewFontFlags = (Index == FontStandard) ? 0 : CurrFontFlags | (1 << Index);
1654 PrFontDiff(CurrFontFlags, NewFontFlags);
1655 CurrFontFlags = NewFontFlags;
1656 }
1657
TeXEnvNewFontType(Word Index)1658 static void TeXEnvNewFontType(Word Index)
1659 {
1660 char NToken[TOKLEN];
1661
1662 SaveFont();
1663 TeXNewFontType(Index);
1664 assert_token("{");
1665 ReadToken(NToken);
1666 strcpy(SepString, BackSepString);
1667 BackToken(NToken);
1668 }
1669
TeXNewFontSize(Word Index)1670 static void TeXNewFontSize(Word Index)
1671 {
1672 PrFontSize(CurrFontSize = (tFontSize) Index, True);
1673 }
1674
TeXEnvNewFontSize(Word Index)1675 static void TeXEnvNewFontSize(Word Index)
1676 {
1677 char NToken[TOKLEN];
1678
1679 SaveFont();
1680 TeXNewFontSize(Index);
1681 assert_token("{");
1682 ReadToken(NToken);
1683 strcpy(SepString, BackSepString);
1684 BackToken(NToken);
1685 }
1686
TeXAddMarginPar(Word Index)1687 static void TeXAddMarginPar(Word Index)
1688 {
1689 UNUSED(Index);
1690
1691 assert_token("{");
1692 SaveEnv(EnvMarginPar);
1693 }
1694
TeXEndHead(Word Index)1695 static void TeXEndHead(Word Index)
1696 {
1697 UNUSED(Index);
1698 }
1699
TeXAddCaption(Word Index)1700 static void TeXAddCaption(Word Index)
1701 {
1702 char tmp[100];
1703 int cnt;
1704 UNUSED(Index);
1705
1706 assert_token("{");
1707 if ((CurrEnv != EnvTable) && (CurrEnv != EnvTabular))
1708 error("caption outside of a table");
1709 FlushLine();
1710 fputs("<P><CENTER>", outfile);
1711 GetTableName(tmp, sizeof(tmp));
1712 SaveEnv(EnvCaption);
1713 AddLine(TableName, "");
1714 cnt = strlen(TableName);
1715 strcat(tmp, ": ");
1716 AddLine(tmp, " ");
1717 cnt += 1 + strlen(tmp);
1718 LeftMargin = 1;
1719 ActLeftMargin = cnt + 1;
1720 RightMargin = 70;
1721 }
1722
TeXHorLine(Word Index)1723 static void TeXHorLine(Word Index)
1724 {
1725 UNUSED(Index);
1726
1727 if (CurrEnv != EnvTabular)
1728 error("\\hline outside of a table");
1729
1730 if (ThisTable.Lines[CurrRow][0])
1731 InitTableRow(++CurrRow);
1732 ThisTable.LineFlags[CurrRow] = True;
1733 InitTableRow(++CurrRow);
1734 }
1735
TeXMultiColumn(Word Index)1736 static void TeXMultiColumn(Word Index)
1737 {
1738 char Token[TOKLEN], *endptr;
1739 int cnt;
1740 UNUSED(Index);
1741
1742 if (CurrEnv != EnvTabular)
1743 error("\\hline outside of a table");
1744 if (CurrCol != 0)
1745 error("\\multicolumn must be in first column");
1746
1747 assert_token("{");
1748 ReadToken(Token);
1749 assert_token("}");
1750 cnt = strtol(Token, &endptr, 10);
1751 if (*endptr != '\0')
1752 error("invalid numeric format to \\multicolumn");
1753 if (cnt != ThisTable.TColumnCount)
1754 error("\\multicolumn must span entire table");
1755 assert_token("{");
1756 do
1757 {
1758 ReadToken(Token);
1759 }
1760 while (strcmp(Token, "}"));
1761 ThisTable.MultiFlags[CurrRow] = True;
1762 }
1763
TeXIndex(Word Index)1764 static void TeXIndex(Word Index)
1765 {
1766 char Token[TOKLEN], Erg[TOKLEN];
1767 PIndexSave run, prev, neu;
1768 UNUSED(Index);
1769
1770 assert_token("{");
1771 collect_token(Token, "}");
1772 run = FirstIndex;
1773 prev = NULL;
1774 while ((run) && (strcmp(Token, run->Name) > 0))
1775 {
1776 prev = run;
1777 run = run->Next;
1778 }
1779 if ((!run) || (strcmp(Token, run->Name) < 0))
1780 {
1781 neu = (PIndexSave) malloc(sizeof(TIndexSave));
1782 neu->Next = run;
1783 neu->RefCnt = 1;
1784 neu->Name = as_strdup(Token);
1785 if (!prev)
1786 FirstIndex = neu;
1787 else
1788 prev->Next = neu;
1789 run = neu;
1790 }
1791 else
1792 run->RefCnt++;
1793 as_snprintf(Erg, sizeof(Erg), "<A NAME=\"index_%s_%d\"></A>", Token, run->RefCnt);
1794 DoAddNormal(Erg, "");
1795 }
1796
FreeIndex(void)1797 static void FreeIndex(void)
1798 {
1799 while (FirstIndex)
1800 {
1801 PIndexSave Old = FirstIndex;
1802 FirstIndex = Old->Next;
1803 if (Old->Name)
1804 free(Old->Name);
1805 free(Old);
1806 }
1807 }
1808
GetDim(Double * Factors)1809 static int GetDim(Double *Factors)
1810 {
1811 char Acc[TOKLEN];
1812 static char *UnitNames[] = {"cm", "mm", ""}, **run, *endptr;
1813 Double Value;
1814
1815 assert_token("{");
1816 collect_token(Acc, "}");
1817 for (run = UnitNames; **run != '\0'; run++)
1818 if (!strcmp(*run, Acc + strlen(Acc) - strlen(*run)))
1819 break;
1820 if (**run == '\0')
1821 error("unknown unit for dimension");
1822 Acc[strlen(Acc) - strlen(*run)] = '\0';
1823 Value = strtod(Acc, &endptr);
1824 if (*endptr != '\0')
1825 error("invalid numeric format for dimension");
1826 return (int)(Value * Factors[run - UnitNames]);
1827 }
1828
1829 static Double HFactors[] = { 4.666666, 0.4666666, 0 };
1830 static Double VFactors[] = { 3.111111, 0.3111111, 0 };
1831
TeXHSpace(Word Index)1832 static void TeXHSpace(Word Index)
1833 {
1834 UNUSED(Index);
1835
1836 DoAddNormal(Blanks(GetDim(HFactors)), "");
1837 }
1838
TeXVSpace(Word Index)1839 static void TeXVSpace(Word Index)
1840 {
1841 int z, erg;
1842 UNUSED(Index);
1843
1844 erg = GetDim(VFactors);
1845 FlushLine();
1846 for (z = 0; z < erg; z++)
1847 fputc('\n', outfile);
1848 }
1849
TeXRule(Word Index)1850 static void TeXRule(Word Index)
1851 {
1852 int h = GetDim(HFactors);
1853 char Rule[200];
1854 UNUSED(Index);
1855
1856 GetDim(VFactors);
1857 as_snprintf(Rule, sizeof(Rule), "<HR WIDTH=\"%d%%\" ALIGN=LEFT>", (h * 100) / 70);
1858 DoAddNormal(Rule, BackSepString);
1859 }
1860
TeXAddTabStop(Word Index)1861 static void TeXAddTabStop(Word Index)
1862 {
1863 int z, n, p;
1864 UNUSED(Index);
1865
1866 if (CurrEnv != EnvTabbing)
1867 error("tab marker outside of tabbing environment");
1868 if (TabStopCnt >= TABMAX)
1869 error("too many tab stops");
1870
1871 n = strlen(OutLineBuffer);
1872 for (p = 0; p < TabStopCnt; p++)
1873 if (TabStops[p] > n)
1874 break;
1875 for (z = TabStopCnt - 1; z >= p; z--)
1876 TabStops[z + 1] = TabStops[z];
1877 TabStops[p] = n;
1878 TabStopCnt++;
1879
1880 PrFontDiff(CurrFontFlags, 0);
1881 DoAddNormal("</TD><TD NOWRAP>", "");
1882 PrFontDiff(0, CurrFontFlags);
1883 }
1884
TeXJmpTabStop(Word Index)1885 static void TeXJmpTabStop(Word Index)
1886 {
1887 UNUSED(Index);
1888
1889 if (CurrEnv != EnvTabbing)
1890 error("tab trigger outside of tabbing environment");
1891 if (CurrTabStop >= TabStopCnt)
1892 error("not enough tab stops");
1893
1894 PrFontDiff(CurrFontFlags, 0);
1895 DoAddNormal("</TD><TD NOWRAP>", "");
1896 PrFontDiff(0, CurrFontFlags);
1897 CurrTabStop++;
1898 }
1899
TeXDoVerb(Word Index)1900 static void TeXDoVerb(Word Index)
1901 {
1902 char Token[TOKLEN], *pos, Marker;
1903 UNUSED(Index);
1904
1905 ReadToken(Token);
1906 if (*SepString != '\0')
1907 error("invalid control character for \\verb");
1908 Marker = (*Token);
1909 strmov(Token, Token + 1);
1910 strcpy(SepString, BackSepString);
1911 do
1912 {
1913 DoAddNormal(SepString, "");
1914 pos = strchr(Token, Marker);
1915 if (pos)
1916 {
1917 *pos = '\0';
1918 DoAddNormal(Token, "");
1919 *SepString = '\0';
1920 BackToken(pos + 1);
1921 break;
1922 }
1923 else
1924 {
1925 DoAddNormal(Token, "");
1926 ReadToken(Token);
1927 }
1928 }
1929 while (True);
1930 }
1931
TeXErrEntry(Word Index)1932 static void TeXErrEntry(Word Index)
1933 {
1934 char Token[TOKLEN];
1935 UNUSED(Index);
1936
1937 assert_token("{");
1938 ReadToken(Token);
1939 assert_token("}");
1940 assert_token("{");
1941 *SepString = '\0';
1942 BackToken("\\");
1943 BackToken("item");
1944 BackToken("[");
1945 BackToken(Token);
1946 BackToken("]");
1947 ErrState = 0;
1948 }
1949
NextErrState(void)1950 static void NextErrState(void)
1951 {
1952 if (ErrState < 3)
1953 assert_token("{");
1954 if (ErrState == 0)
1955 {
1956 *SepString = '\0';
1957 BackToken("\\");
1958 BackToken("begin");
1959 BackToken("{");
1960 BackToken("description");
1961 BackToken("}");
1962 }
1963 if ((ErrState >= 0) && (ErrState <= 2))
1964 {
1965 *SepString = '\0';
1966 BackToken("\\");
1967 BackToken("item");
1968 BackToken("[");
1969 BackToken(ErrorEntryNames[ErrState]);
1970 BackToken(":");
1971 BackToken("]");
1972 BackToken("\\");
1973 BackToken("\\");
1974 }
1975 if (ErrState == 3)
1976 {
1977 *SepString = '\0';
1978 BackToken("\\");
1979 BackToken("\\");
1980 BackToken(" ");
1981 BackToken("\\");
1982 BackToken("end");
1983 BackToken("{");
1984 BackToken("description");
1985 BackToken("}");
1986 ErrState = -1;
1987 }
1988 else
1989 ErrState++;
1990 }
1991
TeXWriteLabel(Word Index)1992 static void TeXWriteLabel(Word Index)
1993 {
1994 char Name[TOKLEN], Value[TOKLEN];
1995 UNUSED(Index);
1996
1997 assert_token("{");
1998 collect_token(Name, "}");
1999
2000 if ((CurrEnv == EnvCaption) || (CurrEnv == EnvTabular))
2001 GetTableName(Value, sizeof(Value));
2002 else
2003 {
2004 GetSectionName(Value, sizeof(Value));
2005 if ((*Value) && (Value[strlen(Value) - 1] == '.'))
2006 Value[strlen(Value) - 1] = '\0';
2007 }
2008
2009 AddLabel(Name, Value);
2010 as_snprintf(Value, sizeof(Value), "<A NAME=\"ref_%s\"></A>", Name);
2011 DoAddNormal(Value, "");
2012 }
2013
TeXWriteRef(Word Index)2014 static void TeXWriteRef(Word Index)
2015 {
2016 char Name[TOKLEN], Value[TOKLEN], HRef[TOKLEN];
2017 UNUSED(Index);
2018
2019 assert_token("{");
2020 collect_token(Name, "}");
2021 GetLabel(Name, Value);
2022 as_snprintf(HRef, sizeof(HRef), "<A HREF=\"#ref_%s\">", Name);
2023 DoAddNormal(HRef, BackSepString);
2024 DoAddNormal(Value, "");
2025 DoAddNormal("</A>", "");
2026 }
2027
TeXWriteCitation(Word Index)2028 static void TeXWriteCitation(Word Index)
2029 {
2030 char Name[TOKLEN], Value[TOKLEN], HRef[TOKLEN];
2031 UNUSED(Index);
2032
2033 assert_token("{");
2034 collect_token(Name, "}");
2035 GetCite(Name, Value);
2036 as_snprintf(HRef, sizeof(HRef), "<A HREF=\"#cite_%s\">", Name);
2037 DoAddNormal(HRef, BackSepString);
2038 as_snprintf(Name, sizeof(Name), "[%s]", Value);
2039 DoAddNormal(Name, "");
2040 DoAddNormal("</A>", "");
2041 }
2042
TeXNewParagraph(Word Index)2043 static void TeXNewParagraph(Word Index)
2044 {
2045 UNUSED(Index);
2046
2047 FlushLine();
2048 fprintf(outfile, "<P>\n");
2049 }
2050
TeXContents(Word Index)2051 static void TeXContents(Word Index)
2052 {
2053 FILE *file = fopen(TocName, "r");
2054 char Line[200], Ref[50], *ptr, *run;
2055 int Level;
2056 UNUSED(Index);
2057
2058 if (!file)
2059 {
2060 Warning("contents file not found.");
2061 DoRepass = True;
2062 return;
2063 }
2064
2065 FlushLine();
2066 fprintf(outfile, "<P>\n<H1>%s</H1><P>\n", ContentsName);
2067 while (!feof(file))
2068 {
2069 if (!fgets(Line, 199, file))
2070 break;
2071 if ((*Line != '\0') && (*Line != '\n'))
2072 {
2073 if (!strncmp(Line, BiblioName, strlen(BiblioName)))
2074 {
2075 strcpy(Ref, "bib");
2076 Level = 1;
2077 }
2078 else if (!strncmp(Line, IndexName, strlen(IndexName)))
2079 {
2080 strcpy(Ref, "index");
2081 Level = 1;
2082 }
2083 else
2084 {
2085 ptr = Ref;
2086 Level = 1;
2087 if ((*Line) && (Line[strlen(Line) - 1] == '\n'))
2088 Line[strlen(Line) - 1] = '\0';
2089 for (run = Line; *run != '\0'; run++)
2090 if (*run != ' ')
2091 break;
2092 for (; *run != '\0'; run++)
2093 if (*run == ' ')
2094 break;
2095 else if (*run == '.')
2096 {
2097 *(ptr++) = '_';
2098 Level++;
2099 }
2100 else if ((*run >= '0') && (*run <= '9'))
2101 *(ptr++) = (*run);
2102 else if ((*run >= 'A') && (*run <= 'Z'))
2103 *(ptr++) = (*run);
2104 *ptr = '\0';
2105 }
2106 fprintf(outfile, "<P><H%d>", Level);
2107 if (*Ref != '\0')
2108 fprintf(outfile, "<A HREF=\"#sect_%s\">", Ref);
2109 fputs(Line, outfile);
2110 if (*Ref != '\0')
2111 fprintf(outfile, "</A></H%d>", Level);
2112 fputc('\n', outfile);
2113 }
2114 }
2115
2116 fclose(file);
2117 }
2118
TeXPrintIndex(Word Index)2119 static void TeXPrintIndex(Word Index)
2120 {
2121 PIndexSave run;
2122 int i, rz;
2123 UNUSED(Index);
2124
2125 FlushLine();
2126 fprintf(outfile, "<H1><A NAME=\"sect_index\">%s</A></H1>\n", IndexName);
2127 AddToc(IndexName, 0);
2128
2129 fputs("<TABLE SUMMARY=\"Index\" BORDER=0 CELLPADDING=5>\n", outfile);
2130 rz = 0;
2131 for (run = FirstIndex; run; run = run->Next)
2132 {
2133 if ((rz % 5) == 0)
2134 fputs("<TR ALIGN=LEFT>\n", outfile);
2135 fputs("<TD VALIGN=TOP NOWRAP>", outfile);
2136 fputs(run->Name, outfile);
2137 for (i = 0; i < run->RefCnt; i++)
2138 fprintf(outfile, " <A HREF=\"#index_%s_%d\">%d</A>", run->Name, i + 1, i + 1);
2139 fputs("</TD>\n", outfile);
2140 if ((rz % 5) == 4)
2141 fputs("</TR>\n", outfile);
2142 rz++;
2143 }
2144 if ((rz % 5) != 0)
2145 fputs("</TR>\n", outfile);
2146 fputs("</TABLE>\n", outfile);
2147 }
2148
TeXParSkip(Word Index)2149 static void TeXParSkip(Word Index)
2150 {
2151 char Token[TOKLEN];
2152 UNUSED(Index);
2153
2154 ReadToken(Token);
2155 do
2156 {
2157 ReadToken(Token);
2158 if ((!strncmp(Token, "plus", 4)) || (!strncmp(Token, "minus", 5)))
2159 {
2160 }
2161 else
2162 {
2163 BackToken(Token);
2164 return;
2165 }
2166 }
2167 while (1);
2168 }
2169
TeXNLS(Word Index)2170 static void TeXNLS(Word Index)
2171 {
2172 char Token[TOKLEN], *Repl = "";
2173 Boolean Found = True;
2174 UNUSED(Index);
2175
2176 *Token = '\0';
2177 ReadToken(Token);
2178 if (*SepString == '\0')
2179 switch (*Token)
2180 {
2181 case 'a':
2182 Repl = "ä";
2183 break;
2184 case 'e':
2185 Repl = "ë";
2186 break;
2187 case 'i':
2188 Repl = "ï";
2189 break;
2190 case 'o':
2191 Repl = "ö";
2192 break;
2193 case 'u':
2194 Repl = "ü";
2195 break;
2196 case 'A':
2197 Repl = "Ä";
2198 break;
2199 case 'E':
2200 Repl = "Ë";
2201 break;
2202 case 'I':
2203 Repl = "Ï";
2204 break;
2205 case 'O':
2206 Repl = "Ö";
2207 break;
2208 case 'U':
2209 Repl = "Ü";
2210 break;
2211 case 's':
2212 Repl = "ß";
2213 break;
2214 default :
2215 Found = False;
2216 }
2217 else
2218 Found = False;
2219
2220 if (Found)
2221 {
2222 if (strlen(Repl) > 1)
2223 memmove(Token + strlen(Repl), Token + 1, strlen(Token));
2224 memcpy(Token, Repl, strlen(Repl));
2225 strcpy(SepString, BackSepString);
2226 }
2227 else
2228 DoAddNormal("\"", BackSepString);
2229
2230 BackToken(Token);
2231 }
2232
TeXNLSGrave(Word Index)2233 static void TeXNLSGrave(Word Index)
2234 {
2235 char Token[TOKLEN], *Repl = "";
2236 Boolean Found = True;
2237 UNUSED(Index);
2238
2239 *Token = '\0';
2240 ReadToken(Token);
2241 if (*SepString == '\0')
2242 switch (*Token)
2243 {
2244 case 'a':
2245 Repl = "à";
2246 break;
2247 case 'e':
2248 Repl = "è";
2249 break;
2250 case 'i':
2251 Repl = "ì";
2252 break;
2253 case 'o':
2254 Repl = "ò";
2255 break;
2256 case 'u':
2257 Repl = "ù";
2258 break;
2259 case 'A':
2260 Repl = "À";
2261 break;
2262 case 'E':
2263 Repl = "È";
2264 break;
2265 case 'I':
2266 Repl = "Ì";
2267 break;
2268 case 'O':
2269 Repl = "Ò";
2270 break;
2271 case 'U':
2272 Repl = "Ù";
2273 break;
2274 default:
2275 Found = False;
2276 }
2277 else
2278 Found = False;
2279
2280 if (Found)
2281 {
2282 if (strlen(Repl) > 1)
2283 memmove(Token + strlen(Repl), Token + 1, strlen(Token));
2284 memcpy(Token, Repl, strlen(Repl));
2285 strcpy(SepString, BackSepString);
2286 }
2287 else
2288 DoAddNormal("\"", BackSepString);
2289
2290 BackToken(Token);
2291 }
2292
TeXNLSAcute(Word Index)2293 static void TeXNLSAcute(Word Index)
2294 {
2295 char Token[TOKLEN], *Repl = "";
2296 Boolean Found = True;
2297 UNUSED(Index);
2298
2299 *Token = '\0';
2300 ReadToken(Token);
2301 if (*SepString == '\0')
2302 switch (*Token)
2303 {
2304 case 'a':
2305 Repl = "á";
2306 break;
2307 case 'e':
2308 Repl = "é";
2309 break;
2310 case 'i':
2311 Repl = "í";
2312 break;
2313 case 'o':
2314 Repl = "ó";
2315 break;
2316 case 'u':
2317 Repl = "ú";
2318 break;
2319 case 'A':
2320 Repl = "Á";
2321 break;
2322 case 'E':
2323 Repl = "É";
2324 break;
2325 case 'I':
2326 Repl = "Í";
2327 break;
2328 case 'O':
2329 Repl = "Ó";
2330 break;
2331 case 'U':
2332 Repl = "Ú";
2333 break;
2334 default:
2335 Found = False;
2336 }
2337 else
2338 Found = False;
2339
2340 if (Found)
2341 {
2342 if (strlen(Repl) > 1)
2343 memmove(Token + strlen(Repl), Token + 1, strlen(Token));
2344 memcpy(Token, Repl, strlen(Repl));
2345 strcpy(SepString, BackSepString);
2346 }
2347 else
2348 DoAddNormal("\"", BackSepString);
2349
2350 BackToken(Token);
2351 }
2352
TeXNLSCirc(Word Index)2353 static void TeXNLSCirc(Word Index)
2354 {
2355 char Token[TOKLEN], *Repl = "";
2356 Boolean Found = True;
2357 UNUSED(Index);
2358
2359 *Token = '\0';
2360 ReadToken(Token);
2361 if (*SepString == '\0')
2362 switch (*Token)
2363 {
2364 case 'a':
2365 Repl = "â";
2366 break;
2367 case 'e':
2368 Repl = "ê";
2369 break;
2370 case 'i':
2371 Repl = "î";
2372 break;
2373 case 'o':
2374 Repl = "ô";
2375 break;
2376 case 'u':
2377 Repl = "û";
2378 break;
2379 case 'A':
2380 Repl = "Â";
2381 break;
2382 case 'E':
2383 Repl = "Ê";
2384 break;
2385 case 'I':
2386 Repl = "Î";
2387 break;
2388 case 'O':
2389 Repl = "Ô";
2390 break;
2391 case 'U':
2392 Repl = "Û";
2393 break;
2394 default:
2395 Found = False;
2396 }
2397 else
2398 Found = False;
2399
2400 if (Found)
2401 {
2402 if (strlen(Repl) > 1)
2403 memmove(Token + strlen(Repl), Token + 1, strlen(Token));
2404 memcpy(Token, Repl, strlen(Repl));
2405 strcpy(SepString, BackSepString);
2406 }
2407 else
2408 DoAddNormal("\"", BackSepString);
2409
2410 BackToken(Token);
2411 }
2412
TeXNLSTilde(Word Index)2413 static void TeXNLSTilde(Word Index)
2414 {
2415 char Token[TOKLEN], *Repl = "";
2416 Boolean Found = True;
2417 UNUSED(Index);
2418
2419 *Token = '\0';
2420 ReadToken(Token);
2421 if (*SepString == '\0')
2422 switch (*Token)
2423 {
2424 case 'n':
2425 Repl = "ñ";
2426 break;
2427 case 'N':
2428 Repl = "Ñ";
2429 break;
2430 default:
2431 Found = False;
2432 }
2433 else
2434 Found = False;
2435
2436 if (Found)
2437 {
2438 if (strlen(Repl) > 1)
2439 memmove(Token + strlen(Repl), Token + 1, strlen(Token));
2440 memcpy(Token, Repl, strlen(Repl));
2441 strcpy(SepString, BackSepString);
2442 }
2443 else DoAddNormal("\"", BackSepString);
2444
2445 BackToken(Token);
2446 }
2447
TeXCedilla(Word Index)2448 static void TeXCedilla(Word Index)
2449 {
2450 char Token[TOKLEN];
2451 UNUSED(Index);
2452
2453 assert_token("{");
2454 collect_token(Token, "}");
2455 if (!strcmp(Token, "c"))
2456 strcpy(Token, "ç");
2457 if (!strcmp(Token, "C"))
2458 strcpy(Token, "Ç");
2459
2460 DoAddNormal(Token, BackSepString);
2461 }
2462
TeXNLSSpec(char * Line)2463 static Boolean TeXNLSSpec(char *Line)
2464 {
2465 Boolean Found = True;
2466 char *Repl = NULL;
2467 int cnt = 0;
2468
2469 if (*SepString == '\0')
2470 switch (*Line)
2471 {
2472 case 'o':
2473 cnt = 1;
2474 Repl = "ø";
2475 break;
2476 case 'O':
2477 cnt = 1;
2478 Repl = "Ø";
2479 break;
2480 case 'a':
2481 switch (Line[1])
2482 {
2483 case 'a':
2484 cnt = 2;
2485 Repl = "å";
2486 break;
2487 case 'e':
2488 cnt = 2;
2489 Repl = "æ";
2490 break;
2491 default:
2492 Found = False;
2493 }
2494 break;
2495 case 'A':
2496 switch (Line[1])
2497 {
2498 case 'A':
2499 cnt = 2;
2500 Repl = "Å";
2501 break;
2502 case 'E':
2503 cnt = 2;
2504 Repl = "Æ";
2505 break;
2506 default:
2507 Found = False;
2508 }
2509 break;
2510 default:
2511 Found = False;
2512 }
2513
2514 if (Found)
2515 {
2516 if ((int)strlen(Repl) != cnt)
2517 memmove(Line + strlen(Repl), Line + cnt, strlen(Line) - cnt + 1);
2518 memcpy(Line, Repl, strlen(Repl));
2519 strcpy(SepString, BackSepString);
2520 }
2521 else
2522 DoAddNormal("\"", BackSepString);
2523
2524 BackToken(Line);
2525 return Found;
2526 }
2527
TeXHyphenation(Word Index)2528 static void TeXHyphenation(Word Index)
2529 {
2530 char Token[TOKLEN];
2531 UNUSED(Index);
2532
2533 assert_token("{");
2534 collect_token(Token, "}");
2535 }
2536
TeXDoPot(void)2537 static void TeXDoPot(void)
2538 {
2539 char Token[TOKLEN];
2540
2541 ReadToken(Token);
2542 if (!strcmp(Token, "1"))
2543 DoAddNormal("¹", BackSepString);
2544 else if (!strcmp(Token, "2"))
2545 DoAddNormal("²", BackSepString);
2546 else if (!strcmp(Token, "3"))
2547 DoAddNormal("³", BackSepString);
2548 else if (!strcmp(Token, "{"))
2549 {
2550 SaveFont();
2551 TeXNewFontType(FontSuper);
2552 ReadToken(Token);
2553 strcpy(SepString, BackSepString);
2554 BackToken(Token);
2555 }
2556 else
2557 {
2558 DoAddNormal("^", BackSepString);
2559 AddLine(Token, "");
2560 }
2561 }
2562
TeXDoSpec(void)2563 static void TeXDoSpec(void)
2564 {
2565 strcpy(BackSepString, SepString);
2566 TeXNLS(0);
2567 }
2568
TeXInclude(Word Index)2569 static void TeXInclude(Word Index)
2570 {
2571 char Token[2 * TOKLEN + 1], Msg[2 * TOKLEN + 1];
2572 UNUSED(Index);
2573
2574 assert_token("{");
2575 strcpy(Token, SrcDir);
2576 collect_token(Token + strlen(Token), "}");
2577 infiles[IncludeNest] = fopen(Token, "r");
2578 if (!infiles[IncludeNest])
2579 {
2580 as_snprintf(Msg, sizeof(Msg), "file %s not found", Token);
2581 error(Msg);
2582 }
2583 else
2584 IncludeNest++;
2585 }
2586
TeXDocumentStyle(Word Index)2587 static void TeXDocumentStyle(Word Index)
2588 {
2589 char Token[TOKLEN];
2590 UNUSED(Index);
2591
2592 ReadToken(Token);
2593 if (!strcmp(Token, "["))
2594 {
2595 do
2596 {
2597 ReadToken(Token);
2598 if (!strcmp(Token, "german"))
2599 SetLang(True);
2600 }
2601 while (strcmp(Token, "]"));
2602 assert_token("{");
2603 ReadToken(Token);
2604 if (CurrPass <= 1)
2605 {
2606 if (!as_strcasecmp(Token, "article"))
2607 {
2608 AddInstTable(TeXTable, "section", 0, TeXNewSection);
2609 AddInstTable(TeXTable, "subsection", 1, TeXNewSection);
2610 AddInstTable(TeXTable, "subsubsection", 3, TeXNewSection);
2611 }
2612 else
2613 {
2614 AddInstTable(TeXTable, "chapter", 0, TeXNewSection);
2615 AddInstTable(TeXTable, "section", 1, TeXNewSection);
2616 AddInstTable(TeXTable, "subsection", 2, TeXNewSection);
2617 AddInstTable(TeXTable, "subsubsection", 3, TeXNewSection);
2618 }
2619 }
2620 assert_token("}");
2621 }
2622 }
2623
TeXUsePackage(Word Index)2624 static void TeXUsePackage(Word Index)
2625 {
2626 char Token[TOKLEN];
2627 UNUSED(Index);
2628
2629 assert_token("{");
2630 ReadToken(Token);
2631 if (!strcmp(Token, "german"))
2632 SetLang(True);
2633 assert_token("}");
2634 }
2635
StartFile(char * Name)2636 static void StartFile(char *Name)
2637 {
2638 char comp[TOKLEN];
2639 struct stat st;
2640
2641 /* create name ? */
2642
2643 if (Structured)
2644 {
2645 as_snprintf(comp, sizeof(comp), "%s.dir/%s", outfilename, Name);
2646 Name = comp;
2647 }
2648
2649 /* open file */
2650
2651 if ((outfile = fopen(Name, "w")) == NULL)
2652 {
2653 perror(Name);
2654 exit(3);
2655 }
2656
2657 /* write head */
2658
2659 fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", outfile);
2660 fputs("<HTML>\n", outfile);
2661 fputs("<HEAD>\n", outfile);
2662 fprintf(outfile, "<META NAME=\"Author\" CONTENT=\"automatically generated by tex2html from %s\">\n", pInFileName);
2663 if (stat(pInFileName, &st))
2664 stat(Name, &st);
2665 strncpy(comp, ctime(&st.st_mtime), TOKLEN - 1);
2666 if ((*comp) && (comp[strlen(comp) - 1] == '\n'))
2667 comp[strlen(comp) - 1] = '\0';
2668 fprintf(outfile, "<META NAME=\"Last-modified\" CONTENT=\"%s\">\n", comp);
2669 }
2670
2671 /*--------------------------------------------------------------------------*/
2672
main(int argc,char ** argv)2673 int main(int argc, char **argv)
2674 {
2675 char Line[TOKLEN], Comp[TOKLEN], *p, AuxFile[200];
2676 int z, ergc, NumPassesLeft;
2677
2678 /* assume defaults for flags */
2679
2680 Structured = False;
2681
2682 /* extract switches */
2683
2684 ergc = 1;
2685 for (z = 1; z < argc; z++)
2686 {
2687 if (!strcmp(argv[z], "-w"))
2688 Structured = True;
2689 else
2690 argv[ergc++] = argv[z];
2691 }
2692 argc = ergc;
2693
2694 /* do we want that ? */
2695
2696 if (argc < 3)
2697 {
2698 fprintf(stderr, "calling convention: %s [switches] <input file> <output file>\n"
2699 "switches: -w --> create structured document\n", *argv);
2700 exit(1);
2701 }
2702
2703 /* save file names */
2704
2705 pInFileName = argv[1];
2706 outfilename = argv[2];
2707
2708 /* set up hash table */
2709
2710 TeXTable = CreateInstTable(301);
2711
2712 AddInstTable(TeXTable, "\\", 0, TeXFlushLine);
2713 AddInstTable(TeXTable, "par", 0, TeXNewParagraph);
2714 AddInstTable(TeXTable, "-", 0, TeXDummy);
2715 AddInstTable(TeXTable, "hyphenation", 0, TeXHyphenation);
2716 AddInstTable(TeXTable, "kill", 0, TeXKillLine);
2717 AddInstTable(TeXTable, "/", 0, TeXDummy);
2718 AddInstTable(TeXTable, "pagestyle", 0, TeXDummyInCurl);
2719 AddInstTable(TeXTable, "thispagestyle", 0, TeXDummyInCurl);
2720 AddInstTable(TeXTable, "sloppy", 0, TeXDummy);
2721 AddInstTable(TeXTable, "clearpage", 0, TeXDummy);
2722 AddInstTable(TeXTable, "cleardoublepage", 0, TeXDummy);
2723 AddInstTable(TeXTable, "topsep", 0, TeXDummyNoBrack);
2724 AddInstTable(TeXTable, "parskip", 0, TeXParSkip);
2725 AddInstTable(TeXTable, "parindent", 0, TeXDummyNoBrack);
2726 AddInstTable(TeXTable, "textwidth", 0, TeXDummyNoBrack);
2727 AddInstTable(TeXTable, "evensidemargin", 0, TeXDummyNoBrack);
2728 AddInstTable(TeXTable, "oddsidemargin", 0, TeXDummyNoBrack);
2729 AddInstTable(TeXTable, "hfuzz", 0, TeXDummyEqual);
2730 AddInstTable(TeXTable, "newcommand", 0, TeXNewCommand);
2731 AddInstTable(TeXTable, "def", 0, TeXDef);
2732 AddInstTable(TeXTable, "font", 0, TeXFont);
2733 AddInstTable(TeXTable, "documentstyle", 0, TeXDocumentStyle);
2734 AddInstTable(TeXTable, "documentclass", 0, TeXDocumentStyle);
2735 AddInstTable(TeXTable, "usepackage", 0, TeXUsePackage);
2736 AddInstTable(TeXTable, "appendix", 0, TeXAppendix);
2737 AddInstTable(TeXTable, "makeindex", 0, TeXDummy);
2738 AddInstTable(TeXTable, "begin", 0, TeXBeginEnv);
2739 AddInstTable(TeXTable, "end", 0, TeXEndEnv);
2740 AddInstTable(TeXTable, "item", 0, TeXItem);
2741 AddInstTable(TeXTable, "bibitem", 0, TeXBibItem);
2742 AddInstTable(TeXTable, "errentry", 0, TeXErrEntry);
2743 AddInstTable(TeXTable, "$", 0, TeXAddDollar);
2744 AddInstTable(TeXTable, "_", 0, TeXAddUnderbar);
2745 AddInstTable(TeXTable, "&", 0, TeXAddAmpersand);
2746 AddInstTable(TeXTable, "@", 0, TeXAddAt);
2747 AddInstTable(TeXTable, "#", 0, TeXAddImm);
2748 AddInstTable(TeXTable, "%", 0, TeXAddPercent);
2749 AddInstTable(TeXTable, "*", 0, TeXAddAsterisk);
2750 AddInstTable(TeXTable, "ss", 0, TeXAddSSharp);
2751 AddInstTable(TeXTable, "in", 0, TeXAddIn);
2752 AddInstTable(TeXTable, "rz", 0, TeXAddReal);
2753 AddInstTable(TeXTable, "mu", 0, TeXAddGreekMu);
2754 AddInstTable(TeXTable, "pi", 0, TeXAddGreekPi);
2755 AddInstTable(TeXTable, "leq", 0, TeXAddLessEq);
2756 AddInstTable(TeXTable, "geq", 0, TeXAddGreaterEq);
2757 AddInstTable(TeXTable, "neq", 0, TeXAddNotEq);
2758 AddInstTable(TeXTable, "mid", 0, TeXAddMid);
2759 AddInstTable(TeXTable, "frac", 0, TeXDoFrac);
2760 AddInstTable(TeXTable, "rm", FontStandard, TeXNewFontType);
2761 AddInstTable(TeXTable, "em", FontEmphasized, TeXNewFontType);
2762 AddInstTable(TeXTable, "bf", FontBold, TeXNewFontType);
2763 AddInstTable(TeXTable, "tt", FontTeletype, TeXNewFontType);
2764 AddInstTable(TeXTable, "it", FontItalic, TeXNewFontType);
2765 AddInstTable(TeXTable, "bb", FontBold, TeXEnvNewFontType);
2766 AddInstTable(TeXTable, "tty", FontTeletype, TeXEnvNewFontType);
2767 AddInstTable(TeXTable, "ii", FontItalic, TeXEnvNewFontType);
2768 AddInstTable(TeXTable, "tiny", FontTiny, TeXNewFontSize);
2769 AddInstTable(TeXTable, "small", FontSmall, TeXNewFontSize);
2770 AddInstTable(TeXTable, "normalsize", FontNormalSize, TeXNewFontSize);
2771 AddInstTable(TeXTable, "large", FontLarge, TeXNewFontSize);
2772 AddInstTable(TeXTable, "huge", FontHuge, TeXNewFontSize);
2773 AddInstTable(TeXTable, "Huge", FontHuge, TeXNewFontSize);
2774 AddInstTable(TeXTable, "tin", FontTiny, TeXEnvNewFontSize);
2775 AddInstTable(TeXTable, "rightarrow", 0, TeXAddRightArrow);
2776 AddInstTable(TeXTable, "longrightarrow", 0, TeXAddLongRightArrow);
2777 AddInstTable(TeXTable, "leftarrow", 0, TeXAddLeftArrow);
2778 AddInstTable(TeXTable, "leftrightarrow", 0, TeXAddLeftRightArrow);
2779 AddInstTable(TeXTable, "marginpar", 0, TeXAddMarginPar);
2780 AddInstTable(TeXTable, "caption", 0, TeXAddCaption);
2781 AddInstTable(TeXTable, "endhead", 0, TeXEndHead);
2782 AddInstTable(TeXTable, "label", 0, TeXWriteLabel);
2783 AddInstTable(TeXTable, "ref", 0, TeXWriteRef);
2784 AddInstTable(TeXTable, "cite", 0, TeXWriteCitation);
2785 AddInstTable(TeXTable, "hline", 0, TeXHorLine);
2786 AddInstTable(TeXTable, "multicolumn", 0, TeXMultiColumn);
2787 AddInstTable(TeXTable, "ttindex", 0, TeXIndex);
2788 AddInstTable(TeXTable, "hspace", 0, TeXHSpace);
2789 AddInstTable(TeXTable, "vspace", 0, TeXVSpace);
2790 AddInstTable(TeXTable, "=", 0, TeXAddTabStop);
2791 AddInstTable(TeXTable, ">", 0, TeXJmpTabStop);
2792 AddInstTable(TeXTable, "verb", 0, TeXDoVerb);
2793 AddInstTable(TeXTable, "printindex", 0, TeXPrintIndex);
2794 AddInstTable(TeXTable, "tableofcontents", 0, TeXContents);
2795 AddInstTable(TeXTable, "rule", 0, TeXRule);
2796 AddInstTable(TeXTable, "\"", 0, TeXNLS);
2797 AddInstTable(TeXTable, "`", 0, TeXNLSGrave);
2798 AddInstTable(TeXTable, "'", 0, TeXNLSAcute);
2799 AddInstTable(TeXTable, "^", 0, TeXNLSCirc);
2800 AddInstTable(TeXTable, "~", 0, TeXNLSTilde);
2801 AddInstTable(TeXTable, "c", 0, TeXCedilla);
2802 AddInstTable(TeXTable, "newif", 0, TeXDummy);
2803 AddInstTable(TeXTable, "fi", 0, TeXDummy);
2804 AddInstTable(TeXTable, "ifelektor", 0, TeXDummy);
2805 AddInstTable(TeXTable, "elektortrue", 0, TeXDummy);
2806 AddInstTable(TeXTable, "elektorfalse", 0, TeXDummy);
2807 AddInstTable(TeXTable, "input", 0, TeXInclude);
2808
2809 CurrPass = 0;
2810 NumPassesLeft = 3;
2811 do
2812 {
2813 CurrPass++;
2814
2815 /* set up inclusion stack */
2816
2817 DidEOF = False;
2818 IncludeNest = 0;
2819 *infiles = fopen(pInFileName, "r");
2820 if (!*infiles)
2821 {
2822 perror(pInFileName);
2823 exit(3);
2824 }
2825 else
2826 IncludeNest++;
2827 SetSrcDir(pInFileName);
2828
2829 /* preset state variables */
2830
2831 for (z = 0; z < CHAPMAX; Chapters[z++] = 0);
2832 TableNum = 0;
2833 TabStopCnt = 0;
2834 CurrTabStop = 0;
2835 ErrState = FracState = -1;
2836 InAppendix = False;
2837 EnvStack = NULL;
2838 CurrEnv = EnvNone;
2839 CurrListDepth = 0;
2840 ActLeftMargin = LeftMargin = 1;
2841 RightMargin = 70;
2842 EnumCounter = 0;
2843 InListItem = False;
2844 InitFont();
2845 CurrLine = 0;
2846 InitLabels();
2847 InitCites();
2848 InitToc();
2849 FirstIndex = NULL;
2850 *SideMargin = '\0';
2851 DoRepass = False;
2852 BibIndent = BibCounter = 0;
2853 GermanMode = True;
2854 SetLang(False);
2855
2856 /* open help files */
2857
2858 strmaxcpy(TocName, pInFileName, sizeof(TocName));
2859 p = strrchr(TocName, '.');
2860 if (p)
2861 *p = '\0';
2862 strcat(TocName, ".htoc");
2863
2864 strmaxcpy(AuxFile, pInFileName, sizeof(AuxFile));
2865 p = strrchr(AuxFile, '.');
2866 if (p)
2867 *p = '\0';
2868 strcat(AuxFile, ".haux");
2869 ReadAuxFile(AuxFile);
2870
2871 if (!strcmp(outfilename, "-"))
2872 {
2873 if (Structured)
2874 {
2875 printf("%s: structured write must be to a directory\n", *argv);
2876 exit(1);
2877 }
2878 else
2879 outfile = stdout;
2880 }
2881
2882 /* do we need to make a directory ? */
2883
2884 else if (Structured)
2885 {
2886 as_snprintf(Line, sizeof(Line), "%s.dir", outfilename);
2887 #if (defined _WIN32) && (!defined __CYGWIN32__)
2888 mkdir(Line);
2889 #elif (defined __MSDOS__)
2890 mkdir(Line);
2891 #else
2892 mkdir(Line, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
2893 #endif
2894 StartFile("intro.html");
2895 }
2896
2897 /* otherwise open the single file */
2898
2899 else
2900 StartFile(outfilename);
2901
2902 /* start to parse */
2903
2904 while (1)
2905 {
2906 if (!ReadToken(Line))
2907 break;
2908 if (!strcmp(Line, "\\"))
2909 {
2910 strcpy(BackSepString, SepString);
2911 if (!ReadToken(Line))
2912 error("unexpected end of file");
2913 if (*SepString != '\0')
2914 BackToken(Line);
2915 else if (!LookupInstTable(TeXTable, Line))
2916 if (!TeXNLSSpec(Line))
2917 {
2918 as_snprintf(Comp, sizeof(Comp), "unknown TeX command %s", Line);
2919 Warning(Comp);
2920 }
2921 }
2922 else if (!strcmp(Line, "$"))
2923 {
2924 InMathMode = !InMathMode;
2925 if (InMathMode)
2926 {
2927 strcpy(BackSepString, SepString);
2928 ReadToken(Line);
2929 strcpy(SepString, BackSepString);
2930 BackToken(Line);
2931 }
2932 }
2933 else if (!strcmp(Line, "&"))
2934 NextTableColumn();
2935 else if ((!strcmp(Line, "^")) && (InMathMode))
2936 TeXDoPot();
2937 else if ((!strcmp(Line, "\"")) && (GermanMode))
2938 TeXDoSpec();
2939 else if (!strcmp(Line, "{"))
2940 SaveFont();
2941 else if (!strcmp(Line, "}"))
2942 {
2943 if (FontNest > 0)
2944 RestoreFont();
2945 else if (ErrState >= 0)
2946 NextErrState();
2947 else if (FracState >= 0)
2948 NextFracState();
2949 else switch (CurrEnv)
2950 {
2951 case EnvMarginPar:
2952 RestoreEnv();
2953 break;
2954 case EnvCaption:
2955 FlushLine();
2956 fputs("</CENTER><P>\n", outfile);
2957 RestoreEnv();
2958 break;
2959 case EnvHeading:
2960 EndSectionHeading();
2961 RestoreEnv();
2962 break;
2963 default:
2964 RestoreFont();
2965 }
2966 }
2967 else
2968 DoAddNormal(Line, SepString);
2969 }
2970 FlushLine();
2971
2972 fputs("</HTML>\n", outfile);
2973
2974 for (z = 0; z < IncludeNest; fclose(infiles[z++]));
2975 fclose(outfile);
2976
2977 unlink(AuxFile);
2978 PrintLabels(AuxFile);
2979 PrintCites(AuxFile);
2980 PrintToc(TocName);
2981
2982 FreeLabels();
2983 FreeCites();
2984 FreeToc();
2985 FreeIndex();
2986 FreeFontStack();
2987
2988 NumPassesLeft--;
2989 if (DoRepass)
2990 fprintf(stderr, "additional pass recommended\n");
2991 }
2992 while (DoRepass && NumPassesLeft);
2993
2994 DestroyInstTable(TeXTable);
2995
2996 if (DoRepass)
2997 {
2998 fprintf(stderr, "additional passes needed but cowardly not done\n");
2999 return 3;
3000 }
3001 else
3002 {
3003 fprintf(stderr, "%d pass(es) needed\n", CurrPass);
3004 return 0;
3005 }
3006 }
3007
3008 #ifdef CKMALLOC
3009 #undef malloc
3010 #undef realloc
3011
ckmalloc(size_t s)3012 void *ckmalloc(size_t s)
3013 {
3014 void *tmp = malloc(s);
3015 if (!tmp)
3016 {
3017 fprintf(stderr, "allocation error(malloc): out of memory");
3018 exit(255);
3019 }
3020 return tmp;
3021 }
3022
ckrealloc(void * p,size_t s)3023 void *ckrealloc(void *p, size_t s)
3024 {
3025 void *tmp = realloc(p, s);
3026 if (!tmp)
3027 {
3028 fprintf(stderr, "allocation error(realloc): out of memory");
3029 exit(255);
3030 }
3031 return tmp;
3032 }
3033 #endif
3034