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