/* tex2html.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Konverter TeX-->HTML */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include "asmitree.h"
#include "chardefs.h"
#include <ctype.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include "texrefs.h"
#include "texutil.h"
#include "textoc.h"
#include "texfonts.h"
#include "strutil.h"
#ifdef __MSDOS__
# include <dir.h>
#endif
/*--------------------------------------------------------------------------*/
#define TOKLEN 350
static char *TableName,
*BiblioName,
*ContentsName,
*IndexName,
#define ErrorEntryCnt 3
*ErrorEntryNames[ErrorEntryCnt];
typedef enum
{
EnvNone, EnvDocument, EnvItemize, EnvEnumerate, EnvDescription, EnvTable,
EnvTabular, EnvRaggedLeft, EnvRaggedRight, EnvCenter, EnvVerbatim,
EnvQuote, EnvTabbing, EnvBiblio, EnvMarginPar, EnvCaption, EnvHeading, EnvCount
} EnvType;
static char *FontNames[FontCnt] =
{
"", "EM", "B", "TT", "I", "SUP"
};
typedef struct sEnvSave
{
struct sEnvSave *Next;
EnvType SaveEnv;
int ListDepth, ActLeftMargin, LeftMargin, RightMargin;
int EnumCounter, FontNest;
Boolean InListItem;
} TEnvSave, *PEnvSave;
typedef enum
{
ColLeft, ColRight, ColCenter, ColBar
} TColumn;
#define MAXCOLS 30
#define MAXROWS 500
typedef char *TableLine[MAXCOLS];
typedef struct
{
int ColumnCount, TColumnCount;
TColumn ColTypes[MAXCOLS];
int ColLens[MAXCOLS];
int LineCnt;
TableLine Lines[MAXROWS];
Boolean LineFlags[MAXROWS];
Boolean MultiFlags[MAXROWS];
} TTable;
typedef struct sIndexSave
{
struct sIndexSave *Next;
char *Name;
int RefCnt;
} TIndexSave, *PIndexSave;
static char *EnvNames[EnvCount] =
{
"___NONE___", "document", "itemize", "enumerate", "description", "table", "tabular",
"raggedleft", "raggedright", "center", "verbatim", "quote", "tabbing",
"thebibliography", "___MARGINPAR___", "___CAPTION___", "___HEADING___"
};
static int IncludeNest;
static FILE *infiles[50], *outfile;
static char *outfilename;
static char TocName[200];
#define CHAPMAX 6
static int Chapters[CHAPMAX];
static int TableNum, ErrState, FracState, BibIndent, BibCounter;
#define TABMAX 100
static int TabStops[TABMAX], TabStopCnt, CurrTabStop;
static Boolean InAppendix, InMathMode, InListItem;
static TTable *pThisTable;
static int CurrRow, CurrCol;
static char SrcDir[TOKLEN + 1], asname[TOKLEN];
static Boolean GermanMode;
static int Structured;
static EnvType CurrEnv;
static int CurrListDepth;
static int EnumCounter;
static int ActLeftMargin, LeftMargin, RightMargin;
static int CurrPass;
static PEnvSave EnvStack;
static PIndexSave FirstIndex;
static PInstTable TeXTable;
/*--------------------------------------------------------------------------*/
void ChkStack(void)
{
}
static void SetSrcDir(const char *pSrcFile)
{
const char *pSep;
pSep
= strchr(pSrcFile
, PATHSEP
);
if (!pSep)
if (!pSep)
*SrcDir = '\0';
else
{
size_t l = pSep + 1 - pSrcFile;
if (l >= sizeof(SrcDir))
{
fprintf(stderr
, "%s: path too long\n", pSrcFile
);
}
SrcDir[l] = '\0';
}
}
static void error(char *Msg)
{
int z;
fprintf(stderr
, "%s:%d.%d: %s\n", pInFileName
, CurrLine
, CurrColumn
, Msg
);
for (z
= 0; z
< IncludeNest
; fclose(infiles
[z
++]));
}
static void SetLang(Boolean IsGerman)
{
if (GermanMode == IsGerman)
return;
GermanMode = IsGerman;
if (GermanMode)
{
TableName = "Tabelle";
BiblioName = "Literaturverzeichnis";
ContentsName = "Inhalt";
IndexName = "Index";
ErrorEntryNames[0] = "Typ";
ErrorEntryNames[1] = "Ursache";
ErrorEntryNames[2] = "Argument";
}
else
{
TableName = "Table";
BiblioName = "Bibliography";
ContentsName = "Contents";
IndexName = "Index";
ErrorEntryNames[0] = "Type";
ErrorEntryNames[1] = "Reason";
ErrorEntryNames[2] = "Argument";
}
}
/*------------------------------------------------------------------------------*/
static void GetNext(char *Src, char *Dest)
{
if (!c)
{
*Src = '\0';
}
else
{
*c = '\0';
for (c++; *c == ' '; c++);
strmov(Src, c);
}
}
static void ReadAuxFile(char *Name)
{
FILE
*file
= fopen(Name
, "r");
char Line[300], Cmd[300], Nam[300], Val[300];
if (!file)
return;
{
if (!fgets(Line
, 299, file
))
break;
if ((*Line
) && (Line
[strlen(Line
) - 1] == '\n'))
Line
[strlen(Line
) - 1] = '\0';
GetNext(Line, Cmd);
{
GetNext(Line, Nam); GetNext(Line, Val);
AddLabel(Nam, Val);
}
else if (!strcmp(Cmd
, "Citation"))
{
GetNext(Line, Nam);
GetNext(Line, Val);
AddCite(Nam, Val);
}
}
}
/*--------------------------------------------------------------------------*/
static Boolean issep(char inp)
{
return ((inp == ' ') || (inp == '\t') || (inp == '\n'));
}
static Boolean isalphanum(char inp)
{
return ((inp >= 'A') && (inp <= 'Z'))
|| ((inp >= 'a') && (inp <= 'z'))
|| ((inp >= '0') && (inp <= '9'))
|| (inp == '.');
}
static char LastChar = '\0';
static char SaveSep = '\0', SepString[TOKLEN] = "";
static Boolean DidEOF;
static char BufferLine[TOKLEN] = "", *BufferPtr = BufferLine;
typedef struct
{
char Token[TOKLEN], Sep[TOKLEN];
} PushedToken;
static int PushedTokenCnt = 0;
static PushedToken PushedTokens[16];
static int GetChar(void)
{
Boolean Comment;
static Boolean DidPar = False;
char *Result;
if (*BufferPtr == '\0')
{
do
{
if (IncludeNest <= 0)
return EOF;
do
{
Result
= fgets(BufferLine
, TOKLEN
, infiles
[IncludeNest
- 1]);
if (Result)
break;
fclose(infiles
[--IncludeNest
]);
if (IncludeNest <= 0)
return EOF;
}
while (True);
CurrLine++;
BufferPtr = BufferLine;
Comment
= (strlen(BufferLine
) >= 2) && (!strncmp(BufferLine
, "%%", 2));
if ((*BufferLine == '\0') || (*BufferLine == '\n'))
{
if ((CurrEnv == EnvDocument) && (!DidPar))
{
strcpy(BufferLine
, "\\par\n");
DidPar = True;
Comment = False;
}
}
else if (Comment)
{
if ((*BufferLine
) && (BufferLine
[strlen(BufferLine
) - 1] == '\n'))
BufferLine
[strlen(BufferLine
) - 1] = '\0';
if (!strncmp(BufferLine
+ 2, "TITLE ", 6))
fprintf(outfile
, "<TITLE>%s</TITLE>\n", BufferLine
+ 8);
}
else
DidPar = False;
}
while (Comment);
}
return *(BufferPtr++);
}
static Boolean ReadToken(char *Dest)
{
int ch, z;
Boolean Good;
char *run;
if (PushedTokenCnt > 0)
{
strcpy(Dest
, PushedTokens
[0].
Token);
strcpy(SepString
, PushedTokens
[0].
Sep);
for (z = 0; z < PushedTokenCnt - 1; z++)
PushedTokens[z] = PushedTokens[z + 1];
PushedTokenCnt--;
return True;
}
if (DidEOF)
return FALSE;
CurrColumn = BufferPtr - BufferLine + 1;
/* falls kein Zeichen gespeichert, fuehrende Blanks ueberspringen */
*Dest = '\0';
*SepString = SaveSep;
run = SepString + ((SaveSep == '\0') ? 0 : 1);
if (LastChar == '\0')
{
do
{
ch = GetChar();
if (ch == '\r')
ch = GetChar();
if (issep(ch))
*(run++) = ' ';
}
while ((issep(ch)) && (ch != EOF));
*run = '\0';
if (ch == EOF)
{
DidEOF = TRUE;
return FALSE;
}
}
else
{
ch = LastChar;
LastChar = '\0';
}
/* jetzt Zeichen kopieren, bis Leerzeichen */
run = Dest;
SaveSep = '\0';
if (isalphanum(*(run++) = ch))
{
do
{
ch = GetChar();
Good = (!issep(ch)) && (isalphanum(ch)) && (ch != EOF);
if (Good)
*(run++) = ch;
}
while (Good);
/* Dateiende ? */
if (ch == EOF)
DidEOF = TRUE;
/* Zeichen speichern ? */
else if ((!issep(ch)) && (!isalphanum(ch)))
LastChar = ch;
/* Separator speichern ? */
else if (issep(ch))
SaveSep = ' ';
}
/* Ende */
*run = '\0';
return True;
}
static void BackToken(char *Token)
{
if (PushedTokenCnt >= 16)
return;
strcpy(PushedTokens
[PushedTokenCnt
].
Token, Token
);
strcpy(PushedTokens
[PushedTokenCnt
].
Sep, SepString
);
PushedTokenCnt++;
}
/*--------------------------------------------------------------------------*/
static void assert_token(char *ref)
{
char token[TOKLEN];
ReadToken(token);
{
as_snprintf(token, sizeof(token), "\"%s\" expected", ref);
error(token);
}
}
static void collect_token(char *dest, char *term)
{
char Comp[TOKLEN];
Boolean first = TRUE, done;
*dest = '\0';
do
{
ReadToken(Comp);
if (!done)
{
if (!first)
}
first = False;
}
while (!done);
}
/*--------------------------------------------------------------------------*/
static char OutLineBuffer[TOKLEN] = "", SideMargin[TOKLEN];
static void PutLine(Boolean DoBlock)
{
int l
, n
, ptrcnt
, diff
, div, mod
, divmod
;
char *chz, *ptrs[50];
Boolean SkipFirst, IsFirst;
fputs(Blanks
(LeftMargin
- 1), outfile
);
if ((CurrEnv == EnvRaggedRight) || (!DoBlock))
{
fprintf(outfile
, "%s", OutLineBuffer
);
}
else
{
SkipFirst = ((CurrEnv == EnvItemize) || (CurrEnv == EnvEnumerate) || (CurrEnv == EnvDescription) || (CurrEnv == EnvBiblio));
if (LeftMargin == ActLeftMargin)
SkipFirst = False;
l = ptrcnt = 0;
IsFirst = SkipFirst;
for (chz = OutLineBuffer; *chz != '\0'; chz++)
{
if ((chz > OutLineBuffer) && (*(chz - 1) != ' ') && (*chz == ' '))
{
if (!IsFirst)
ptrs[ptrcnt++] = chz;
IsFirst = False;
}
l++;
}
(void)ptrs;
diff = RightMargin - LeftMargin + 1 - l;
div = (ptrcnt
> 0) ? diff
/ ptrcnt
: 0;
mod
= diff
- (ptrcnt
* div);
divmod = (mod > 0) ? ptrcnt / mod : ptrcnt + 1;
IsFirst = SkipFirst;
ptrcnt = 0;
for (chz = OutLineBuffer; *chz != '\0'; chz++)
{
if ((chz > OutLineBuffer) && (*(chz - 1) != ' ') && (*chz == ' '))
{
if (!IsFirst)
{
if ((mod > 0) && ((ptrcnt % divmod) == 0))
{
mod--;
n++;
}
if (n > 0)
fputs(Blanks
(n
), outfile
);
ptrcnt++;
}
IsFirst = False;
}
}
l = RightMargin - LeftMargin + 1;
}
if (*SideMargin != '\0')
{
fputs(Blanks
(RightMargin
- LeftMargin
+ 4 - l
), outfile
);
#if 0
fprintf(outfile
, "%s", SideMargin
);
#endif
*SideMargin = '\0';
}
LeftMargin = ActLeftMargin;
}
static void AddLine(const char *Part, char *Sep)
{
int mlen = RightMargin - LeftMargin + 1;
char *search, save;
Sep[1] = '\0';
if (*OutLineBuffer != '\0')
if ((int)strlen(OutLineBuffer
) >= mlen
)
{
search = OutLineBuffer + mlen;
while (search >= OutLineBuffer)
{
if (*search == ' ')
break;
search--;
}
if (search <= OutLineBuffer)
{
PutLine(False);
*OutLineBuffer = '\0';
}
else
{
save = (*search);
*search = '\0';
PutLine(False);
*search = save;
for (; *search == ' '; search++);
strmov(OutLineBuffer, search);
}
}
}
static void AddSideMargin(const char *Part, char *Sep)
{
Sep[1] = '\0';
if (*Sep != '\0')
if ((*SideMargin != '\0') || (!issep(*Sep)))
}
static void FlushLine(void)
{
if (*OutLineBuffer != '\0')
{
PutLine(False);
*OutLineBuffer = '\0';
}
}
static void ResetLine(void)
{
*OutLineBuffer = '\0';
}
static void AddTableEntry(const char *Part, char *Sep)
{
char *Ptr = pThisTable->Lines[CurrRow][CurrCol];
int nlen
= (!Ptr
) ? 0 : strlen(Ptr
);
Boolean UseSep = (nlen > 0);
Sep[1] = '\0';
if (UseSep)
if (!Ptr)
{
Ptr
= (char *) malloc(nlen
+ 1);
*Ptr = '\0';
}
else
{
char *NewPtr
= (char *) realloc(Ptr
, nlen
+ 1);
if (NewPtr)
Ptr = NewPtr;
}
if (UseSep)
pThisTable->Lines[CurrRow][CurrCol] = Ptr;
}
static void DoAddNormal(const char *Part, char *Sep)
{
Part = "<";
Part = ">";
Part = "&";
switch (CurrEnv)
{
case EnvMarginPar:
AddSideMargin(Part, Sep);
break;
case EnvTabular:
AddTableEntry(Part, Sep);
break;
default:
AddLine(Part, Sep);
}
}
/*--------------------------------------------------------------------------*/
void PrFontDiff(int OldFlags, int NewFlags)
{
tFontType z;
int Mask;
char erg[10];
for (z = FontStandard + 1, Mask = 2; z < FontCnt; z++, Mask = Mask << 1)
if ((OldFlags^NewFlags) & Mask)
{
as_snprintf(erg, sizeof(erg), "<%s%s>", (NewFlags & Mask)?"":"/", FontNames[z]);
DoAddNormal(erg, "");
}
}
void PrFontSize(tFontSize Type, Boolean On)
{
char erg[10];
if (FontNormalSize == Type)
return;
if (!On)
switch (Type)
{
case FontTiny:
case FontSmall:
break;
case FontLarge:
case FontHuge:
break;
default:
break;
}
DoAddNormal(erg, "");
if ((FontTiny == Type) || (FontHuge == Type))
DoAddNormal(erg, "");
}
static void SaveEnv(EnvType NewEnv)
{
PEnvSave NewSave;
NewSave
= (PEnvSave
) malloc(sizeof(TEnvSave
));
NewSave->Next = EnvStack;
NewSave->ListDepth = CurrListDepth;
NewSave->LeftMargin = LeftMargin;
NewSave->ActLeftMargin = ActLeftMargin;
NewSave->RightMargin = RightMargin;
NewSave->EnumCounter = EnumCounter;
NewSave->SaveEnv = CurrEnv;
NewSave->FontNest = FontNest;
NewSave->InListItem = InListItem;
EnvStack = NewSave;
CurrEnv = NewEnv;
FontNest = 0;
}
static void RestoreEnv(void)
{
PEnvSave OldSave;
OldSave = EnvStack;
EnvStack = OldSave->Next;
CurrListDepth = OldSave->ListDepth;
LeftMargin = OldSave->LeftMargin;
ActLeftMargin = OldSave->ActLeftMargin;
RightMargin = OldSave->RightMargin;
EnumCounter = OldSave->EnumCounter;
FontNest = OldSave->FontNest;
InListItem = OldSave->InListItem;
CurrEnv = OldSave->SaveEnv;
}
static void InitTableRow(int Index)
{
int z;
for (z = 0; z < pThisTable->TColumnCount; pThisTable->Lines[Index][z++] = NULL);
pThisTable->MultiFlags[Index] = False;
pThisTable->LineFlags[Index] = False;
}
static void NextTableColumn(void)
{
if (CurrEnv != EnvTabular)
error("table separation char not within tabular environment");
if ((pThisTable->MultiFlags[CurrRow])
|| (CurrCol >= pThisTable->TColumnCount))
error("too many columns within row");
CurrCol++;
}
static void DumpTable(void)
{
int TextCnt, RowCnt, rowz, rowz2, rowz3, colz, colptr, ml, l, diff, sumlen, firsttext, indent;
char *ColTag;
/* compute widths of individual rows */
/* get index of first text column */
RowCnt = pThisTable->Lines[CurrRow][0] ? CurrRow + 1 : CurrRow;
firsttext = -1;
for (colz = colptr = 0; colz < pThisTable->ColumnCount; colz++)
if (pThisTable->ColTypes[colz] == ColBar)
pThisTable->ColLens[colz] = 1;
else
{
ml = 0;
for (rowz = 0; rowz < RowCnt; rowz++)
if ((!pThisTable->LineFlags[rowz]) && (!pThisTable->MultiFlags[rowz]))
{
l
= (!pThisTable
->Lines
[rowz
][colptr
]) ? 0 : strlen(pThisTable
->Lines
[rowz
][colptr
]);
if (ml < l)
ml = l;
}
pThisTable->ColLens[colz] = ml + 2;
colptr++;
if (firsttext < 0) firsttext = colz;
}
/* count number of text columns */
for (colz = TextCnt = 0; colz < pThisTable->ColumnCount; colz++)
if (pThisTable->ColTypes[colz] != ColBar)
TextCnt++;
/* get total width */
for (colz = sumlen = 0; colz < pThisTable->ColumnCount; sumlen += pThisTable->ColLens[colz++]);
indent = (RightMargin - LeftMargin + 1 - sumlen) / 2;
if (indent < 0)
indent = 0;
/* search for multicolumns and extend first field if table is too lean */
ml = 0;
for (rowz = 0; rowz < RowCnt; rowz++)
if ((!pThisTable->LineFlags[rowz]) && (pThisTable->MultiFlags[rowz]))
{
l
= (!pThisTable
->Lines
[rowz
][0]) ? 0 : strlen(pThisTable
->Lines
[rowz
][0]);
if (ml < l)
ml = l;
}
if (ml + 4 > sumlen)
{
diff = ml + 4 - sumlen;
pThisTable->ColLens[firsttext] += diff;
}
/* tell browser to switch to table mode */
fprintf(outfile
, "<P><CENTER><TABLE SUMMARY=\"No Summary\" BORDER=1 CELLPADDING=5>\n");
/* print rows */
rowz = 0;
while (rowz < RowCnt)
{
/* find first text line */
for (; rowz < RowCnt; rowz++)
if (!pThisTable->LineFlags[rowz])
break;
/* find last text line */
for (rowz2 = rowz; rowz2 < RowCnt; rowz2++)
if (pThisTable->LineFlags[rowz2])
break;
rowz2--;
if (rowz < RowCnt)
{
/* if more than one line follows, take this as header line(s) */
if ((rowz2 <= RowCnt - 3) && (pThisTable->LineFlags[rowz2 + 1]) && (pThisTable->LineFlags[rowz2 + 2]))
ColTag = "TH";
else
ColTag = "TD";
/* start a row */
fprintf(outfile
, "<TR ALIGN=LEFT>\n");
/* over all columns... */
colptr = 0;
for (colz = 0; colz < ((pThisTable->MultiFlags[rowz])?firsttext + 1:pThisTable->ColumnCount); colz++)
if (pThisTable->ColTypes[colz] != ColBar)
{
/* start a column */
fprintf(outfile
, "<%s VALIGN=TOP NOWRAP", ColTag
);
if (pThisTable->MultiFlags[rowz])
fprintf(outfile
, " COLSPAN=%d", TextCnt
);
switch (pThisTable->ColTypes[colz])
{
case ColLeft:
fputs(" ALIGN=LEFT>", outfile
);
break;
case ColCenter:
fputs(" ALIGN=CENTER>", outfile
);
break;
case ColRight:
fputs(" ALIGN=RIGHT>", outfile
);
break;
default:
break;
}
/* write items */
for (rowz3 = rowz; rowz3 <= rowz2; rowz3++)
{
if (pThisTable->Lines[rowz3][colptr])
fputs(pThisTable
->Lines
[rowz3
][colptr
], outfile
);
if (rowz3 != rowz2)
fputs("<BR>\n", outfile
);
}
/* end column */
fprintf(outfile
, "</%s>\n", ColTag
);
colptr++;
}
/* end row */
for (rowz3 = rowz; rowz3 <= rowz2; rowz3++)
for (colz = 0; colz < pThisTable->ColumnCount; colz++)
if (pThisTable->Lines[rowz3][colz])
{
free(pThisTable
->Lines
[rowz3
][colz
]);
pThisTable->Lines[rowz3][colz] = NULL;
}
rowz = rowz2 + 1;
}
}
/* end table mode */
fprintf(outfile
, "</TABLE></CENTER>\n");
}
static void GetTableName(char *Dest, size_t DestSize)
{
int ThisTableNum = (CurrEnv == EnvTabular) ? TableNum + 1 : TableNum;
if (InAppendix)
as_snprintf(Dest, DestSize, "%c.%d", Chapters[0] + 'A', ThisTableNum);
else
as_snprintf(Dest, DestSize, "%d.%d", Chapters[0], ThisTableNum);
}
static void GetSectionName(char *Dest, size_t DestSize)
{
int z;
*Dest = '\0';
for (z = 0; z <= 2; z++)
{
if ((z > 0) && (Chapters[z] == 0))
break;
if ((InAppendix) && (z == 0))
as_snprcatf(Dest, DestSize, "%c.", Chapters[z] + 'A');
else
as_snprcatf(Dest, DestSize, "%d.", Chapters[z]);
}
}
/*--------------------------------------------------------------------------*/
static char BackSepString[TOKLEN];
static void TeXFlushLine(Word Index)
{
UNUSED(Index);
if (CurrEnv == EnvTabular)
{
for (CurrCol++; CurrCol < pThisTable->TColumnCount; pThisTable->Lines[CurrRow][CurrCol++] = as_strdup(""));
CurrRow++;
if (CurrRow == MAXROWS)
error("too many rows in table");
InitTableRow(CurrRow);
CurrCol = 0;
}
else if (CurrEnv == EnvTabbing)
{
CurrTabStop = 0;
PrFontDiff(CurrFontFlags, 0);
AddLine("</TD></TR>", "");
FlushLine();
AddLine("<TR><TD NOWRAP>", "");
PrFontDiff(0, CurrFontFlags);
}
else
{
if (*OutLineBuffer == '\0')
AddLine("<BR>", "");
FlushLine();
}
}
static void TeXKillLine(Word Index)
{
UNUSED(Index);
ResetLine();
if (CurrEnv == EnvTabbing)
{
AddLine("<TR><TD NOWRAP>", "");
PrFontDiff(0, CurrFontFlags);
}
}
static void TeXDummy(Word Index)
{
UNUSED(Index);
}
static void TeXDummyEqual(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
assert_token("=");
ReadToken(Token);
}
static void TeXDummyNoBrack(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
ReadToken(Token);
}
static void TeXDummyInCurl(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
assert_token("{");
ReadToken(Token);
assert_token("}");
}
static void TeXNewCommand(Word Index)
{
char token[TOKLEN], command[TOKLEN], sum_token[TOKLEN], arg_cnt[TOKLEN];
int level;
UNUSED(Index);
assert_token("{");
assert_token("\\");
ReadToken(command);
assert_token("}");
ReadToken(token);
{
ReadToken(arg_cnt);
assert_token("]");
ReadToken(token);
}
error("\"{\" expected");
level = 1;
*sum_token = '\0';
do
{
ReadToken(token);
level++;
level--;
if (level != 0)
strmaxcat(sum_token, token, sizeof(sum_token));
}
while (level != 0);
if (!strcmp(command
, "asname"))
strmaxcpy(asname, sum_token, sizeof(asname));
}
static void TeXDef(Word Index)
{
char Token[TOKLEN];
int level;
UNUSED(Index);
assert_token("\\");
ReadToken(Token);
assert_token("{");
level = 1;
do
{
ReadToken(Token);
level++;
level--;
}
while (level != 0);
}
static void TeXFont(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
assert_token("\\");
ReadToken(Token);
assert_token("=");
ReadToken(Token);
ReadToken(Token);
assert_token("\\");
ReadToken(Token);
}
static void TeXAppendix(Word Index)
{
int z;
UNUSED(Index);
InAppendix = True;
*Chapters = -1;
for (z = 1; z < CHAPMAX; Chapters[z++] = 0);
}
static int LastLevel;
static void TeXNewSection(Word Level)
{
int z;
if (Level >= CHAPMAX)
return;
FlushLine();
assert_token("{");
LastLevel = Level;
SaveEnv(EnvHeading);
RightMargin = 200;
Chapters[Level]++;
for (z = Level + 1; z < CHAPMAX; Chapters[z++] = 0);
if (Level == 0)
TableNum = 0;
}
static void EndSectionHeading(void)
{
int Level = LastLevel;
char Line[TOKLEN], Title[TOKLEN], *rep;
*OutLineBuffer = '\0';
fprintf(outfile
, "<H%d>", Level
+ 1);
*Line = '\0';
if (Level < 3)
{
GetSectionName(Line, sizeof(Line));
fprintf(outfile
, "<A NAME=\"sect_");
for (rep = Line; *rep; rep++)
fputc((*rep
== '.') ? '_' : *rep
, outfile
);
as_snprcatf(Line, sizeof(Line), " ");
}
as_snprcatf(Line, sizeof(Line), "%s", Title);
if (Level < 3)
{
GetSectionName(Line, sizeof(Line));
as_snprcatf(Line, sizeof(Line), " %s", Title);
AddToc(Line, 0);
}
fprintf(outfile
, "</H%d>\n", Level
+ 1);
}
static EnvType GetEnvType(char *Name)
{
EnvType z;
if (!strcmp(Name
, "longtable"))
return EnvTabular;
for (z = EnvNone + 1; z < EnvCount; z++)
if (!strcmp(Name
, EnvNames
[z
]))
return z;
error("unknown environment");
return EnvNone;
}
static void TeXBeginEnv(Word Index)
{
char EnvName[TOKLEN], Add[TOKLEN], *p;
EnvType NEnv;
Boolean done;
TColumn NCol;
UNUSED(Index);
assert_token("{");
ReadToken(EnvName);
if ((NEnv = GetEnvType(EnvName)) == EnvTable)
{
ReadToken(Add);
assert_token("}");
error("unknown table environment");
}
else
assert_token("}");
if (NEnv != EnvVerbatim)
SaveEnv(NEnv);
switch (NEnv)
{
case EnvDocument:
fputs("</HEAD>\n", outfile
);
fputs("<BODY>\n", outfile
);
break;
case EnvItemize:
FlushLine();
++CurrListDepth;
ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
RightMargin = 70;
EnumCounter = 0;
InListItem = False;
break;
case EnvDescription:
FlushLine();
fprintf(outfile
, "<DL COMPACT>\n");
++CurrListDepth;
ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
RightMargin = 70;
EnumCounter = 0;
InListItem = False;
break;
case EnvEnumerate:
FlushLine();
++CurrListDepth;
ActLeftMargin = LeftMargin = (CurrListDepth * 4) + 1;
RightMargin = 70;
EnumCounter = 0;
InListItem = False;
break;
case EnvBiblio:
FlushLine();
fprintf(outfile
, "<H1><A NAME=\"sect_bib\">%s</A></H1>\n<DL COMPACT>\n", BiblioName
);
assert_token("{");
ReadToken(Add);
assert_token("}");
ActLeftMargin
= LeftMargin
= 4 + (BibIndent
= strlen(Add
));
AddToc(BiblioName, 0);
break;
case EnvVerbatim:
FlushLine();
if ((*BufferLine != '\0') && (*BufferPtr != '\0'))
{
*BufferLine = '\0';
BufferPtr = BufferLine;
}
do
{
if (!fgets(Add
, TOKLEN
- 1, infiles
[IncludeNest
- 1]))
break;
CurrLine++;
done
= strstr(Add
, "\\end{verbatim}") != NULL
;
if (!done)
{
for (p = Add; *p != '\0';)
if (*p == '<')
{
p += 4;
}
else if (*p == '>')
{
p += 4;
}
else
p++;
}
}
while (!done);
break;
case EnvQuote:
FlushLine();
fprintf(outfile
, "<BLOCKQUOTE>\n");
ActLeftMargin = LeftMargin = 5;
RightMargin = 70;
break;
case EnvTabbing:
FlushLine();
fputs("<TABLE SUMMARY=\"No Summary\" CELLPADDING=2>\n", outfile
);
TabStopCnt = 0;
CurrTabStop = 0;
RightMargin = TOKLEN - 1;
AddLine("<TR><TD NOWRAP>", "");
PrFontDiff(0, CurrFontFlags);
break;
case EnvTable:
ReadToken(Add);
BackToken(Add);
else
{
do
{
ReadToken(Add);
}
}
FlushLine();
++TableNum;
break;
case EnvCenter:
FlushLine();
fputs("<CENTER>\n", outfile
);
break;
case EnvRaggedRight:
FlushLine();
fputs("<DIV ALIGN=LEFT>\n", outfile
);
break;
case EnvRaggedLeft:
FlushLine();
fputs("<DIV ALIGN=RIGHT>\n", outfile
);
break;
case EnvTabular:
FlushLine();
assert_token("{");
pThisTable->ColumnCount = pThisTable->TColumnCount = 0;
do
{
ReadToken(Add);
if (!done)
{
if (pThisTable->ColumnCount >= MAXCOLS)
error("too many columns in table");
NCol = ColLeft;
NCol = ColBar;
NCol = ColLeft;
NCol = ColRight;
NCol = ColCenter;
else
error("unknown table column descriptor");
if ((pThisTable->ColTypes[pThisTable->ColumnCount++] = NCol) != ColBar)
pThisTable->TColumnCount++;
}
}
while (!done);
InitTableRow(CurrRow = 0);
CurrCol = 0;
break;
default:
break;
}
}
static void TeXEndEnv(Word Index)
{
char EnvName[TOKLEN], Add[TOKLEN];
EnvType NEnv;
UNUSED(Index);
assert_token("{");
ReadToken(EnvName);
if ((NEnv = GetEnvType(EnvName)) == EnvTable)
{
ReadToken(Add);
assert_token("}");
error("unknown table environment");
}
else
assert_token("}");
if (!EnvStack)
error("end without begin");
if (CurrEnv != NEnv)
error("begin and end of environment do not match");
switch (CurrEnv)
{
case EnvDocument:
FlushLine();
fputs("</BODY>\n", outfile
);
break;
case EnvItemize:
if (InListItem)
AddLine("</LI>", "");
FlushLine();
break;
case EnvDescription:
if (InListItem)
AddLine("</DD>", "");
FlushLine();
break;
case EnvEnumerate:
if (InListItem)
AddLine("</LI>", "");
FlushLine();
break;
case EnvQuote:
FlushLine();
fprintf(outfile
, "</BLOCKQUOTE>\n");
break;
case EnvBiblio:
FlushLine();
break;
case EnvTabbing:
PrFontDiff(CurrFontFlags, 0);
AddLine("</TD></TR>", "");
FlushLine();
fputs("</TABLE>", outfile
);
break;
case EnvCenter:
FlushLine();
fputs("</CENTER>\n", outfile
);
break;
case EnvRaggedRight:
case EnvRaggedLeft:
FlushLine();
fputs("</DIV>\n", outfile
);
break;
case EnvTabular:
DumpTable();
break;
case EnvTable:
FlushLine
(); fputc('\n', outfile
);
break;
default:
break;
}
RestoreEnv();
}
static void TeXItem(Word Index)
{
char Token[TOKLEN], Acc[TOKLEN];
UNUSED(Index);
if (InListItem)
AddLine((CurrEnv == EnvDescription) ? "</DD>" : "</LI>", "");
FlushLine();
InListItem = True;
switch(CurrEnv)
{
case EnvItemize:
LeftMargin = ActLeftMargin - 3;
break;
case EnvEnumerate:
LeftMargin = ActLeftMargin - 4;
break;
case EnvDescription:
ReadToken(Token);
BackToken(Token);
else
{
collect_token(Acc, "]");
LeftMargin = ActLeftMargin - 4;
}
break;
default:
error("\\item not in a list environment");
}
}
static void TeXBibItem(Word Index)
{
char NumString[20], Token[TOKLEN], Name[TOKLEN], Value[TOKLEN];
UNUSED(Index);
if (CurrEnv != EnvBiblio)
error("\\bibitem not in bibliography environment");
assert_token("{");
collect_token(Name, "}");
FlushLine();
AddLine("<DT>", "");
++BibCounter;
LeftMargin = ActLeftMargin - BibIndent - 3;
as_snprintf(Value, sizeof(Value), "<A NAME=\"cite_%s\">", Name);
DoAddNormal(Value, "");
as_snprintf(NumString, sizeof(NumString), "[%*d] </A><DD>", BibIndent, BibCounter);
AddLine(NumString, "");
as_snprintf(NumString, sizeof(NumString), "%d", BibCounter);
AddCite(Name, NumString);
ReadToken(Token);
*SepString = '\0';
BackToken(Token);
}
static void TeXAddDollar(Word Index)
{
UNUSED(Index);
DoAddNormal("$", BackSepString);
}
static void TeXAddUnderbar(Word Index)
{
UNUSED(Index);
DoAddNormal("_", BackSepString);
}
#if 0
static void TeXAddPot(Word Index)
{
UNUSED(Index);
DoAddNormal("^", BackSepString);
}
#endif
static void TeXAddAmpersand(Word Index)
{
UNUSED(Index);
DoAddNormal("&", BackSepString);
}
static void TeXAddAt(Word Index)
{
UNUSED(Index);
DoAddNormal("@", BackSepString);
}
static void TeXAddImm(Word Index)
{
UNUSED(Index);
DoAddNormal("#", BackSepString);
}
static void TeXAddPercent(Word Index)
{
UNUSED(Index);
DoAddNormal("%", BackSepString);
}
static void TeXAddAsterisk(Word Index)
{
UNUSED(Index);
DoAddNormal("*", BackSepString);
}
static void TeXAddSSharp(Word Index)
{
UNUSED(Index);
DoAddNormal("ß", BackSepString);
}
static void TeXAddIn(Word Index)
{
UNUSED(Index);
DoAddNormal("in", BackSepString);
}
static void TeXAddReal(Word Index)
{
UNUSED(Index);
DoAddNormal("R", BackSepString);
}
static void TeXAddGreekMu(Word Index)
{
UNUSED(Index);
DoAddNormal("µ", BackSepString);
}
static void TeXAddGreekPi(Word Index)
{
UNUSED(Index);
DoAddNormal("π", BackSepString);
}
static void TeXAddLessEq(Word Index)
{
UNUSED(Index);
DoAddNormal("≤", BackSepString);
}
static void TeXAddGreaterEq(Word Index)
{
UNUSED(Index);
DoAddNormal("≥", BackSepString);
}
static void TeXAddNotEq(Word Index)
{
UNUSED(Index);
DoAddNormal("≠", BackSepString);
}
static void TeXAddMid(Word Index)
{
UNUSED(Index);
DoAddNormal("|", BackSepString);
}
static void TeXASName(Word Index)
{
char arg[TOKLEN];
UNUSED(Index);
assert_token("{");
collect_token(arg, "}");
DoAddNormal(asname, BackSepString);
}
static void TeXAddLAnd(Word Index)
{
UNUSED(Index);
DoAddNormal("∧", BackSepString);
}
static void TeXAddLOr(Word Index)
{
UNUSED(Index);
DoAddNormal("∨", BackSepString);
}
static void TeXAddOPlus(Word Index)
{
UNUSED(Index);
DoAddNormal("⊻", BackSepString);
}
static void TeXAddRightArrow(Word Index)
{
UNUSED(Index);
DoAddNormal("→", BackSepString);
}
static void TeXAddLongRightArrow(Word Index)
{
UNUSED(Index);
DoAddNormal("⟶", BackSepString);
}
static void TeXAddLeftArrow(Word Index)
{
UNUSED(Index);
DoAddNormal("←", BackSepString);
}
static void TeXAddGets(Word Index)
{
UNUSED(Index);
DoAddNormal("←", BackSepString);
}
static void TeXAddLongLeftArrow(Word Index)
{
UNUSED(Index);
DoAddNormal("⟵", BackSepString);
}
static void TeXAddLeftRightArrow(Word Index)
{
UNUSED(Index);
DoAddNormal("↔", BackSepString);
}
static void TeXDoFrac(Word Index)
{
UNUSED(Index);
assert_token("{");
*SepString = '\0';
BackToken("(");
FracState = 0;
}
static void NextFracState(void)
{
if (FracState == 0)
{
assert_token("{");
*SepString = '\0';
BackToken(")");
BackToken("/");
BackToken("(");
}
else if (FracState == 1)
{
*SepString = '\0';
BackToken(")");
}
if ((++FracState) == 2)
FracState = -1;
}
static void TeXNewFontType(Word Index)
{
int NewFontFlags;
NewFontFlags = (Index == FontStandard) ? 0 : CurrFontFlags | (1 << Index);
PrFontDiff(CurrFontFlags, NewFontFlags);
CurrFontFlags = NewFontFlags;
}
static void TeXEnvNewFontType(Word Index)
{
char NToken[TOKLEN];
SaveFont();
TeXNewFontType(Index);
assert_token("{");
ReadToken(NToken);
strcpy(SepString
, BackSepString
);
BackToken(NToken);
}
static void TeXNewFontSize(Word Index)
{
PrFontSize(CurrFontSize = (tFontSize) Index, True);
}
static void TeXEnvNewFontSize(Word Index)
{
char NToken[TOKLEN];
SaveFont();
TeXNewFontSize(Index);
assert_token("{");
ReadToken(NToken);
strcpy(SepString
, BackSepString
);
BackToken(NToken);
}
static void TeXAddMarginPar(Word Index)
{
UNUSED(Index);
assert_token("{");
SaveEnv(EnvMarginPar);
}
static void TeXEndHead(Word Index)
{
UNUSED(Index);
}
static void TeXAddCaption(Word Index)
{
char tmp[100];
int cnt;
UNUSED(Index);
assert_token("{");
if ((CurrEnv != EnvTable) && (CurrEnv != EnvTabular))
error("caption outside of a table");
FlushLine();
fputs("<P><CENTER>", outfile
);
GetTableName(tmp, sizeof(tmp));
SaveEnv(EnvCaption);
AddLine(TableName, "");
AddLine(tmp, " ");
LeftMargin = 1;
ActLeftMargin = cnt + 1;
RightMargin = 70;
}
static void TeXHorLine(Word Index)
{
UNUSED(Index);
if (CurrEnv != EnvTabular)
error("\\hline outside of a table");
if (pThisTable->Lines[CurrRow][0])
InitTableRow(++CurrRow);
pThisTable->LineFlags[CurrRow] = True;
InitTableRow(++CurrRow);
}
static void TeXMultiColumn(Word Index)
{
char Token[TOKLEN], *endptr;
int cnt;
UNUSED(Index);
if (CurrEnv != EnvTabular)
error("\\hline outside of a table");
if (CurrCol != 0)
error("\\multicolumn must be in first column");
assert_token("{");
ReadToken(Token);
assert_token("}");
cnt
= strtol(Token
, &endptr
, 10);
if (*endptr != '\0')
error("invalid numeric format to \\multicolumn");
if (cnt != pThisTable->TColumnCount)
error("\\multicolumn must span entire table");
assert_token("{");
do
{
ReadToken(Token);
}
pThisTable->MultiFlags[CurrRow] = True;
}
static void TeXIndex(Word Index)
{
char Token[TOKLEN], Erg[TOKLEN];
PIndexSave run, prev, neu;
UNUSED(Index);
assert_token("{");
collect_token(Token, "}");
run = FirstIndex;
prev = NULL;
while ((run
) && (strcmp(Token
, run
->Name
) > 0))
{
prev = run;
run = run->Next;
}
if ((!run
) || (strcmp(Token
, run
->Name
) < 0))
{
neu
= (PIndexSave
) malloc(sizeof(TIndexSave
));
neu->Next = run;
neu->RefCnt = 1;
neu->Name = as_strdup(Token);
if (!prev)
FirstIndex = neu;
else
prev->Next = neu;
run = neu;
}
else
run->RefCnt++;
as_snprintf(Erg, sizeof(Erg), "<A NAME=\"index_%s_%d\"></A>", Token, run->RefCnt);
DoAddNormal(Erg, "");
}
static void FreeIndex(void)
{
while (FirstIndex)
{
PIndexSave Old = FirstIndex;
FirstIndex = Old->Next;
if (Old->Name)
}
}
static int GetDim(Double *Factors)
{
char Acc[TOKLEN];
static char *UnitNames[] = {"cm", "mm", ""}, **run, *endptr;
Double Value;
assert_token("{");
collect_token(Acc, "}");
for (run = UnitNames; **run != '\0'; run++)
break;
if (**run == '\0')
error("unknown unit for dimension");
if (*endptr != '\0')
error("invalid numeric format for dimension");
return (int)(Value * Factors[run - UnitNames]);
}
static Double HFactors[] = { 4.666666, 0.4666666, 0 };
static Double VFactors[] = { 3.111111, 0.3111111, 0 };
static void TeXHSpace(Word Index)
{
UNUSED(Index);
DoAddNormal(Blanks(GetDim(HFactors)), "");
}
static void TeXVSpace(Word Index)
{
int z, erg;
UNUSED(Index);
erg = GetDim(VFactors);
FlushLine();
for (z = 0; z < erg; z++)
}
static void TeXRule(Word Index)
{
int h = GetDim(HFactors);
char Rule[200];
UNUSED(Index);
GetDim(VFactors);
as_snprintf(Rule, sizeof(Rule), "<HR WIDTH=\"%d%%\" ALIGN=LEFT>", (h * 100) / 70);
DoAddNormal(Rule, BackSepString);
}
static void TeXAddTabStop(Word Index)
{
int z, n, p;
UNUSED(Index);
if (CurrEnv != EnvTabbing)
error("tab marker outside of tabbing environment");
if (TabStopCnt >= TABMAX)
error("too many tab stops");
for (p = 0; p < TabStopCnt; p++)
if (TabStops[p] > n)
break;
for (z = TabStopCnt - 1; z >= p; z--)
TabStops[z + 1] = TabStops[z];
TabStops[p] = n;
TabStopCnt++;
PrFontDiff(CurrFontFlags, 0);
DoAddNormal("</TD><TD NOWRAP>", "");
PrFontDiff(0, CurrFontFlags);
}
static void TeXJmpTabStop(Word Index)
{
UNUSED(Index);
if (CurrEnv != EnvTabbing)
error("tab trigger outside of tabbing environment");
if (CurrTabStop >= TabStopCnt)
error("not enough tab stops");
PrFontDiff(CurrFontFlags, 0);
DoAddNormal("</TD><TD NOWRAP>", "");
PrFontDiff(0, CurrFontFlags);
CurrTabStop++;
}
static void TeXDoVerb(Word Index)
{
char Token[TOKLEN], *pos, Marker;
UNUSED(Index);
ReadToken(Token);
if (*SepString != '\0')
error("invalid control character for \\verb");
Marker = (*Token);
strmov(Token, Token + 1);
strcpy(SepString
, BackSepString
);
do
{
DoAddNormal(SepString, "");
if (pos)
{
*pos = '\0';
DoAddNormal(Token, "");
*SepString = '\0';
BackToken(pos + 1);
break;
}
else
{
DoAddNormal(Token, "");
ReadToken(Token);
}
}
while (True);
}
static void TeXErrEntry(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
assert_token("{");
ReadToken(Token);
assert_token("}");
assert_token("{");
*SepString = '\0';
BackToken("\\");
BackToken("item");
BackToken("[");
BackToken(Token);
BackToken("]");
ErrState = 0;
}
static void NextErrState(void)
{
if (ErrState < 3)
assert_token("{");
if (ErrState == 0)
{
*SepString = '\0';
BackToken("\\");
BackToken("begin");
BackToken("{");
BackToken("description");
BackToken("}");
}
if ((ErrState >= 0) && (ErrState <= 2))
{
*SepString = '\0';
BackToken("\\");
BackToken("item");
BackToken("[");
BackToken(ErrorEntryNames[ErrState]);
BackToken(":");
BackToken("]");
BackToken("\\");
BackToken("\\");
}
if (ErrState == 3)
{
*SepString = '\0';
BackToken("\\");
BackToken("\\");
BackToken(" ");
BackToken("\\");
BackToken("end");
BackToken("{");
BackToken("description");
BackToken("}");
ErrState = -1;
}
else
ErrState++;
}
static void TeXWriteLabel(Word Index)
{
char Name[TOKLEN], Value[TOKLEN];
UNUSED(Index);
assert_token("{");
collect_token(Name, "}");
if ((CurrEnv == EnvCaption) || (CurrEnv == EnvTabular))
GetTableName(Value, sizeof(Value));
else
{
GetSectionName(Value, sizeof(Value));
if ((*Value
) && (Value
[strlen(Value
) - 1] == '.'))
Value
[strlen(Value
) - 1] = '\0';
}
AddLabel(Name, Value);
as_snprintf(Value, sizeof(Value), "<A NAME=\"ref_%s\"></A>", Name);
DoAddNormal(Value, "");
}
static void TeXWriteRef(Word Index)
{
char Name[TOKLEN], Value[TOKLEN], HRef[TOKLEN];
UNUSED(Index);
assert_token("{");
collect_token(Name, "}");
GetLabel(Name, Value);
as_snprintf(HRef, sizeof(HRef), "<A HREF=\"#ref_%s\">", Name);
DoAddNormal(HRef, BackSepString);
DoAddNormal(Value, "");
DoAddNormal("</A>", "");
}
static void TeXWriteCitation(Word Index)
{
char Name[TOKLEN], Value[TOKLEN], HRef[TOKLEN];
UNUSED(Index);
assert_token("{");
collect_token(Name, "}");
GetCite(Name, Value);
as_snprintf(HRef, sizeof(HRef), "<A HREF=\"#cite_%s\">", Name);
DoAddNormal(HRef, BackSepString);
as_snprintf(Name, sizeof(Name), "[%s]", Value);
DoAddNormal(Name, "");
DoAddNormal("</A>", "");
}
static void TeXNewParagraph(Word Index)
{
UNUSED(Index);
FlushLine();
}
static void TeXContents(Word Index)
{
FILE
*file
= fopen(TocName
, "r");
char Line[200], Ref[50], *ptr, *run;
int Level;
UNUSED(Index);
if (!file)
{
Warning("contents file not found.");
DoRepass = True;
return;
}
FlushLine();
fprintf(outfile
, "<P>\n<H1>%s</H1><P>\n", ContentsName
);
{
if (!fgets(Line
, 199, file
))
break;
if ((*Line != '\0') && (*Line != '\n'))
{
{
Level = 1;
}
{
Level = 1;
}
else
{
ptr = Ref;
Level = 1;
if ((*Line
) && (Line
[strlen(Line
) - 1] == '\n'))
Line
[strlen(Line
) - 1] = '\0';
for (run = Line; *run != '\0'; run++)
if (*run != ' ')
break;
for (; *run != '\0'; run++)
if (*run == ' ')
break;
else if (*run == '.')
{
*(ptr++) = '_';
Level++;
}
else if ((*run >= '0') && (*run <= '9'))
*(ptr++) = (*run);
else if ((*run >= 'A') && (*run <= 'Z'))
*(ptr++) = (*run);
*ptr = '\0';
}
fprintf(outfile
, "<P><H%d>", Level
);
if (*Ref != '\0')
fprintf(outfile
, "<A HREF=\"#sect_%s\">", Ref
);
if (*Ref != '\0')
fprintf(outfile
, "</A></H%d>", Level
);
}
}
}
static void TeXPrintIndex(Word Index)
{
PIndexSave run;
int i, rz;
UNUSED(Index);
FlushLine();
fprintf(outfile
, "<H1><A NAME=\"sect_index\">%s</A></H1>\n", IndexName
);
AddToc(IndexName, 0);
fputs("<TABLE SUMMARY=\"Index\" BORDER=0 CELLPADDING=5>\n", outfile
);
rz = 0;
for (run = FirstIndex; run; run = run->Next)
{
if ((rz % 5) == 0)
fputs("<TR ALIGN=LEFT>\n", outfile
);
fputs("<TD VALIGN=TOP NOWRAP>", outfile
);
fputs(run
->Name
, outfile
);
for (i = 0; i < run->RefCnt; i++)
fprintf(outfile
, " <A HREF=\"#index_%s_%d\">%d</A>", run
->Name
, i
+ 1, i
+ 1);
fputs("</TD>\n", outfile
);
if ((rz % 5) == 4)
fputs("</TR>\n", outfile
);
rz++;
}
if ((rz % 5) != 0)
fputs("</TR>\n", outfile
);
fputs("</TABLE>\n", outfile
);
}
static void TeXParSkip(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
ReadToken(Token);
do
{
ReadToken(Token);
{
}
else
{
BackToken(Token);
return;
}
}
while (1);
}
static void TeXNLS(Word Index)
{
char Token[TOKLEN], *Repl = "";
Boolean Found = True;
UNUSED(Index);
*Token = '\0';
ReadToken(Token);
if (*SepString == '\0')
switch (*Token)
{
case 'a':
Repl = "ä";
break;
case 'e':
Repl = "ë";
break;
case 'i':
Repl = "ï";
break;
case 'o':
Repl = "ö";
break;
case 'u':
Repl = "ü";
break;
case 'A':
Repl = "Ä";
break;
case 'E':
Repl = "Ë";
break;
case 'I':
Repl = "Ï";
break;
case 'O':
Repl = "Ö";
break;
case 'U':
Repl = "Ü";
break;
case 's':
Repl = "ß";
break;
default :
Found = False;
}
else
Found = False;
if (Found)
{
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal("\"", BackSepString);
BackToken(Token);
}
static void TeXNLSGrave(Word Index)
{
char Token[TOKLEN], *Repl = "";
Boolean Found = True;
UNUSED(Index);
*Token = '\0';
ReadToken(Token);
if (*SepString == '\0')
switch (*Token)
{
case 'a':
Repl = "à";
break;
case 'e':
Repl = "è";
break;
case 'i':
Repl = "ì";
break;
case 'o':
Repl = "ò";
break;
case 'u':
Repl = "ù";
break;
case 'A':
Repl = "À";
break;
case 'E':
Repl = "È";
break;
case 'I':
Repl = "Ì";
break;
case 'O':
Repl = "Ò";
break;
case 'U':
Repl = "Ù";
break;
default:
Found = False;
}
else
Found = False;
if (Found)
{
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal("\"", BackSepString);
BackToken(Token);
}
static void TeXNLSAcute(Word Index)
{
char Token[TOKLEN], *Repl = "";
Boolean Found = True;
UNUSED(Index);
*Token = '\0';
ReadToken(Token);
if (*SepString == '\0')
switch (*Token)
{
case 'a':
Repl = "á";
break;
case 'e':
Repl = "é";
break;
case 'i':
Repl = "í";
break;
case 'o':
Repl = "ó";
break;
case 'u':
Repl = "ú";
break;
case 'A':
Repl = "Á";
break;
case 'E':
Repl = "É";
break;
case 'I':
Repl = "Í";
break;
case 'O':
Repl = "Ó";
break;
case 'U':
Repl = "Ú";
break;
default:
Found = False;
}
else
Found = False;
if (Found)
{
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal("\"", BackSepString);
BackToken(Token);
}
static void TeXNLSCirc(Word Index)
{
char Token[TOKLEN], *Repl = "";
Boolean Found = True;
UNUSED(Index);
*Token = '\0';
ReadToken(Token);
if (*SepString == '\0')
switch (*Token)
{
case 'a':
Repl = "â";
break;
case 'e':
Repl = "ê";
break;
case 'i':
Repl = "î";
break;
case 'o':
Repl = "ô";
break;
case 'u':
Repl = "û";
break;
case 'A':
Repl = "Â";
break;
case 'E':
Repl = "Ê";
break;
case 'I':
Repl = "Î";
break;
case 'O':
Repl = "Ô";
break;
case 'U':
Repl = "Û";
break;
default:
Found = False;
}
else
Found = False;
if (Found)
{
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal("\"", BackSepString);
BackToken(Token);
}
static void TeXNLSTilde(Word Index)
{
char Token[TOKLEN], *Repl = "";
Boolean Found = True;
UNUSED(Index);
*Token = '\0';
ReadToken(Token);
if (*SepString == '\0')
switch (*Token)
{
case 'n':
Repl = "ñ";
break;
case 'N':
Repl = "Ñ";
break;
default:
Found = False;
}
else
Found = False;
if (Found)
{
strcpy(SepString
, BackSepString
);
}
else DoAddNormal("\"", BackSepString);
BackToken(Token);
}
static void TeXCedilla(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
assert_token("{");
collect_token(Token, "}");
DoAddNormal(Token, BackSepString);
}
static Boolean TeXNLSSpec(char *Line)
{
Boolean Found = True;
char *Repl = NULL;
int cnt = 0;
if (*SepString == '\0')
switch (*Line)
{
case 'o':
cnt = 1;
Repl = "ø";
break;
case 'O':
cnt = 1;
Repl = "Ø";
break;
case 'a':
switch (Line[1])
{
case 'a':
cnt = 2;
Repl = "å";
break;
case 'e':
cnt = 2;
Repl = "æ";
break;
default:
Found = False;
}
break;
case 'A':
switch (Line[1])
{
case 'A':
cnt = 2;
Repl = "Å";
break;
case 'E':
cnt = 2;
Repl = "Æ";
break;
default:
Found = False;
}
break;
default:
Found = False;
}
if (Found)
{
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal("\"", BackSepString);
BackToken(Line);
return Found;
}
static void TeXHyphenation(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
assert_token("{");
collect_token(Token, "}");
}
static void TeXDoPot(void)
{
char Token[TOKLEN];
ReadToken(Token);
DoAddNormal("¹", BackSepString);
DoAddNormal("²", BackSepString);
DoAddNormal("³", BackSepString);
{
SaveFont();
TeXNewFontType(FontSuper);
ReadToken(Token);
strcpy(SepString
, BackSepString
);
BackToken(Token);
}
else
{
DoAddNormal("^", BackSepString);
AddLine(Token, "");
}
}
static void TeXDoSpec(void)
{
strcpy(BackSepString
, SepString
);
TeXNLS(0);
}
static void TeXInclude(Word Index)
{
char Token[2 * TOKLEN + 1], Msg[2 * TOKLEN + 1];
UNUSED(Index);
assert_token("{");
collect_token
(Token
+ strlen(Token
), "}");
infiles
[IncludeNest
] = fopen(Token
, "r");
if (!infiles[IncludeNest])
{
as_snprintf(Msg, sizeof(Msg), "file %s not found", Token);
error(Msg);
}
else
IncludeNest++;
}
static void TeXDocumentStyle(Word Index)
{
char Token[TOKLEN];
UNUSED(Index);
ReadToken(Token);
{
do
{
ReadToken(Token);
SetLang(True);
}
assert_token("{");
ReadToken(Token);
if (CurrPass <= 1)
{
if (!as_strcasecmp(Token, "article"))
{
AddInstTable(TeXTable, "section", 0, TeXNewSection);
AddInstTable(TeXTable, "subsection", 1, TeXNewSection);
AddInstTable(TeXTable, "subsubsection", 3, TeXNewSection);
}
else
{
AddInstTable(TeXTable, "chapter", 0, TeXNewSection);
AddInstTable(TeXTable, "section", 1, TeXNewSection);
AddInstTable(TeXTable, "subsection", 2, TeXNewSection);
AddInstTable(TeXTable, "subsubsection", 3, TeXNewSection);
}
}
assert_token("}");
}
}
/*!------------------------------------------------------------------------
* \fn TeXUsePackage(Word Index)
* \brief parse \usepackage command
* ------------------------------------------------------------------------ */
static void TeXUsePackage(Word Index)
{
char Token[TOKLEN], Msg[2 * TOKLEN + 1];
Boolean read_german_opt = False;
UNUSED(Index);
while (True)
{
ReadToken(Token);
{
do
{
ReadToken(Token);
read_german_opt = True;
}
}
{
ReadToken(Token);
if (!as_strcasecmp(Token, "german"))
SetLang(True);
else if (!as_strcasecmp(Token, "babel"))
SetLang(read_german_opt);
else if (!as_strcasecmp(Token, "makeidx"));
else if (!as_strcasecmp(Token, "hyperref"));
else if (!as_strcasecmp(Token, "longtable"));
else
{
as_snprintf(Msg, sizeof(Msg), "unknown package '%s'", Token);
error(Msg);
}
assert_token("}");
break;
}
else
{
as_snprintf(Msg, sizeof(Msg), "expecting [ or { after \\usepackage");
error(Msg);
}
}
}
static void StartFile(char *Name)
{
char comp[TOKLEN];
struct stat st;
/* create name ? */
if (Structured)
{
as_snprintf(comp, sizeof(comp), "%s.dir/%s", outfilename, Name);
Name = comp;
}
/* open file */
if ((outfile
= fopen(Name
, "w")) == NULL
)
{
}
/* write head */
fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n", outfile
);
fputs("<HTML>\n", outfile
);
fputs("<HEAD>\n", outfile
);
fprintf(outfile
, "<META NAME=\"Author\" CONTENT=\"automatically generated by tex2html from %s\">\n", pInFileName
);
if (stat(pInFileName, &st))
stat(Name, &st);
if ((*comp
) && (comp
[strlen(comp
) - 1] == '\n'))
comp
[strlen(comp
) - 1] = '\0';
fprintf(outfile
, "<META NAME=\"Last-modified\" CONTENT=\"%s\">\n", comp
);
}
/*--------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
char Line[TOKLEN], Comp[TOKLEN], *p, AuxFile[200];
int z, ergc, NumPassesLeft;
/* assume defaults for flags */
Structured = False;
/* extract switches */
ergc = 1;
for (z = 1; z < argc; z++)
{
Structured = True;
else
argv[ergc++] = argv[z];
}
argc = ergc;
/* do we want that ? */
if (argc < 3)
{
fprintf(stderr
, "calling convention: %s [switches] <input file> <output file>\n"
"switches: -w --> create structured document\n", *argv);
}
pThisTable
= (TTable
*)calloc(1, sizeof(*pThisTable
));
/* save file names */
pInFileName = argv[1];
outfilename = argv[2];
/* set up hash table */
TeXTable = CreateInstTable(301);
AddInstTable(TeXTable, "\\", 0, TeXFlushLine);
AddInstTable(TeXTable, "par", 0, TeXNewParagraph);
AddInstTable(TeXTable, "-", 0, TeXDummy);
AddInstTable(TeXTable, "hyphenation", 0, TeXHyphenation);
AddInstTable(TeXTable, "kill", 0, TeXKillLine);
AddInstTable(TeXTable, "/", 0, TeXDummy);
AddInstTable(TeXTable, "pagestyle", 0, TeXDummyInCurl);
AddInstTable(TeXTable, "thispagestyle", 0, TeXDummyInCurl);
AddInstTable(TeXTable, "sloppy", 0, TeXDummy);
AddInstTable(TeXTable, "clearpage", 0, TeXDummy);
AddInstTable(TeXTable, "cleardoublepage", 0, TeXDummy);
AddInstTable(TeXTable, "topsep", 0, TeXDummyNoBrack);
AddInstTable(TeXTable, "parskip", 0, TeXParSkip);
AddInstTable(TeXTable, "parindent", 0, TeXDummyNoBrack);
AddInstTable(TeXTable, "textwidth", 0, TeXDummyNoBrack);
AddInstTable(TeXTable, "evensidemargin", 0, TeXDummyNoBrack);
AddInstTable(TeXTable, "oddsidemargin", 0, TeXDummyNoBrack);
AddInstTable(TeXTable, "hfuzz", 0, TeXDummyEqual);
AddInstTable(TeXTable, "newcommand", 0, TeXNewCommand);
AddInstTable(TeXTable, "def", 0, TeXDef);
AddInstTable(TeXTable, "font", 0, TeXFont);
AddInstTable(TeXTable, "documentstyle", 0, TeXDocumentStyle);
AddInstTable(TeXTable, "documentclass", 0, TeXDocumentStyle);
AddInstTable(TeXTable, "usepackage", 0, TeXUsePackage);
AddInstTable(TeXTable, "appendix", 0, TeXAppendix);
AddInstTable(TeXTable, "makeindex", 0, TeXDummy);
AddInstTable(TeXTable, "begin", 0, TeXBeginEnv);
AddInstTable(TeXTable, "end", 0, TeXEndEnv);
AddInstTable(TeXTable, "item", 0, TeXItem);
AddInstTable(TeXTable, "bibitem", 0, TeXBibItem);
AddInstTable(TeXTable, "errentry", 0, TeXErrEntry);
AddInstTable(TeXTable, "$", 0, TeXAddDollar);
AddInstTable(TeXTable, "_", 0, TeXAddUnderbar);
AddInstTable(TeXTable, "&", 0, TeXAddAmpersand);
AddInstTable(TeXTable, "@", 0, TeXAddAt);
AddInstTable(TeXTable, "#", 0, TeXAddImm);
AddInstTable(TeXTable, "%", 0, TeXAddPercent);
AddInstTable(TeXTable, "*", 0, TeXAddAsterisk);
AddInstTable(TeXTable, "ss", 0, TeXAddSSharp);
AddInstTable(TeXTable, "in", 0, TeXAddIn);
AddInstTable(TeXTable, "rz", 0, TeXAddReal);
AddInstTable(TeXTable, "mu", 0, TeXAddGreekMu);
AddInstTable(TeXTable, "pi", 0, TeXAddGreekPi);
AddInstTable(TeXTable, "leq", 0, TeXAddLessEq);
AddInstTable(TeXTable, "geq", 0, TeXAddGreaterEq);
AddInstTable(TeXTable, "neq", 0, TeXAddNotEq);
AddInstTable(TeXTable, "mid", 0, TeXAddMid);
AddInstTable(TeXTable, "asname", 0, TeXASName);
AddInstTable(TeXTable, "land", 0, TeXAddLAnd);
AddInstTable(TeXTable, "lor", 0, TeXAddLOr);
AddInstTable(TeXTable, "oplus", 0, TeXAddOPlus);
AddInstTable(TeXTable, "frac", 0, TeXDoFrac);
AddInstTable(TeXTable, "rm", FontStandard, TeXNewFontType);
AddInstTable(TeXTable, "em", FontEmphasized, TeXNewFontType);
AddInstTable(TeXTable, "bf", FontBold, TeXNewFontType);
AddInstTable(TeXTable, "tt", FontTeletype, TeXNewFontType);
AddInstTable(TeXTable, "it", FontItalic, TeXNewFontType);
AddInstTable(TeXTable, "bb", FontBold, TeXEnvNewFontType);
AddInstTable(TeXTable, "tty", FontTeletype, TeXEnvNewFontType);
AddInstTable(TeXTable, "ii", FontItalic, TeXEnvNewFontType);
AddInstTable(TeXTable, "tiny", FontTiny, TeXNewFontSize);
AddInstTable(TeXTable, "small", FontSmall, TeXNewFontSize);
AddInstTable(TeXTable, "normalsize", FontNormalSize, TeXNewFontSize);
AddInstTable(TeXTable, "large", FontLarge, TeXNewFontSize);
AddInstTable(TeXTable, "huge", FontHuge, TeXNewFontSize);
AddInstTable(TeXTable, "Huge", FontHuge, TeXNewFontSize);
AddInstTable(TeXTable, "tin", FontTiny, TeXEnvNewFontSize);
AddInstTable(TeXTable, "rightarrow", 0, TeXAddRightArrow);
AddInstTable(TeXTable, "longrightarrow", 0, TeXAddLongRightArrow);
AddInstTable(TeXTable, "leftarrow", 0, TeXAddLeftArrow);
AddInstTable(TeXTable, "longleftarrow", 0, TeXAddLongLeftArrow);
AddInstTable(TeXTable, "leftrightarrow", 0, TeXAddLeftRightArrow);
AddInstTable(TeXTable, "gets", 0, TeXAddGets);
AddInstTable(TeXTable, "marginpar", 0, TeXAddMarginPar);
AddInstTable(TeXTable, "caption", 0, TeXAddCaption);
AddInstTable(TeXTable, "endhead", 0, TeXEndHead);
AddInstTable(TeXTable, "label", 0, TeXWriteLabel);
AddInstTable(TeXTable, "ref", 0, TeXWriteRef);
AddInstTable(TeXTable, "cite", 0, TeXWriteCitation);
AddInstTable(TeXTable, "hline", 0, TeXHorLine);
AddInstTable(TeXTable, "multicolumn", 0, TeXMultiColumn);
AddInstTable(TeXTable, "ttindex", 0, TeXIndex);
AddInstTable(TeXTable, "hspace", 0, TeXHSpace);
AddInstTable(TeXTable, "vspace", 0, TeXVSpace);
AddInstTable(TeXTable, "=", 0, TeXAddTabStop);
AddInstTable(TeXTable, ">", 0, TeXJmpTabStop);
AddInstTable(TeXTable, "verb", 0, TeXDoVerb);
AddInstTable(TeXTable, "printindex", 0, TeXPrintIndex);
AddInstTable(TeXTable, "tableofcontents", 0, TeXContents);
AddInstTable(TeXTable, "rule", 0, TeXRule);
AddInstTable(TeXTable, "\"", 0, TeXNLS);
AddInstTable(TeXTable, "`", 0, TeXNLSGrave);
AddInstTable(TeXTable, "'", 0, TeXNLSAcute);
AddInstTable(TeXTable, "^", 0, TeXNLSCirc);
AddInstTable(TeXTable, "~", 0, TeXNLSTilde);
AddInstTable(TeXTable, "c", 0, TeXCedilla);
AddInstTable(TeXTable, "newif", 0, TeXDummy);
AddInstTable(TeXTable, "fi", 0, TeXDummy);
AddInstTable(TeXTable, "ifelektor", 0, TeXDummy);
AddInstTable(TeXTable, "elektortrue", 0, TeXDummy);
AddInstTable(TeXTable, "elektorfalse", 0, TeXDummy);
AddInstTable(TeXTable, "input", 0, TeXInclude);
CurrPass = 0;
NumPassesLeft = 3;
do
{
CurrPass++;
/* set up inclusion stack */
DidEOF = False;
IncludeNest = 0;
*infiles
= fopen(pInFileName
, "r");
if (!*infiles)
{
}
else
IncludeNest++;
SetSrcDir(pInFileName);
/* preset state variables */
for (z = 0; z < CHAPMAX; Chapters[z++] = 0);
TableNum = 0;
TabStopCnt = 0;
CurrTabStop = 0;
ErrState = FracState = -1;
InAppendix = False;
EnvStack = NULL;
CurrEnv = EnvNone;
CurrListDepth = 0;
ActLeftMargin = LeftMargin = 1;
RightMargin = 70;
EnumCounter = 0;
InListItem = False;
InitFont();
CurrLine = 0;
InitLabels();
InitCites();
InitToc();
FirstIndex = NULL;
*SideMargin = '\0';
DoRepass = False;
BibIndent = BibCounter = 0;
GermanMode = True;
SetLang(False);
/* open help files */
strmaxcpy(TocName, pInFileName, sizeof(TocName));
if (p)
*p = '\0';
strmaxcpy(AuxFile, pInFileName, sizeof(AuxFile));
if (p)
*p = '\0';
ReadAuxFile(AuxFile);
if (!strcmp(outfilename
, "-"))
{
if (Structured)
{
printf("%s: structured write must be to a directory\n", *argv
);
}
else
outfile = stdout;
}
/* do we need to make a directory ? */
else if (Structured)
{
as_snprintf(Line, sizeof(Line), "%s.dir", outfilename);
#if (defined _WIN32) && (!defined __CYGWIN32__)
mkdir(Line);
#elif (defined __MSDOS__)
mkdir(Line);
#else
mkdir(Line, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
#endif
StartFile("intro.html");
}
/* otherwise open the single file */
else
StartFile(outfilename);
/* start to parse */
while (1)
{
if (!ReadToken(Line))
break;
{
strcpy(BackSepString
, SepString
);
if (!ReadToken(Line))
error("unexpected end of file");
if (*SepString != '\0')
BackToken(Line);
else if (!LookupInstTable(TeXTable, Line))
if (!TeXNLSSpec(Line))
{
as_snprintf(Comp, sizeof(Comp), "unknown TeX command %s", Line);
Warning(Comp);
}
}
{
InMathMode = !InMathMode;
if (InMathMode)
{
strcpy(BackSepString
, SepString
);
ReadToken(Line);
strcpy(SepString
, BackSepString
);
BackToken(Line);
}
}
NextTableColumn();
else if ((!strcmp(Line
, "^")) && (InMathMode
))
TeXDoPot();
else if ((!strcmp(Line
, "\"")) && (GermanMode
))
TeXDoSpec();
SaveFont();
{
if (FontNest > 0)
RestoreFont();
else if (ErrState >= 0)
NextErrState();
else if (FracState >= 0)
NextFracState();
else switch (CurrEnv)
{
case EnvMarginPar:
RestoreEnv();
break;
case EnvCaption:
FlushLine();
fputs("</CENTER><P>\n", outfile
);
RestoreEnv();
break;
case EnvHeading:
EndSectionHeading();
RestoreEnv();
break;
default:
RestoreFont();
}
}
else
DoAddNormal(Line, SepString);
}
FlushLine();
fputs("</HTML>\n", outfile
);
for (z
= 0; z
< IncludeNest
; fclose(infiles
[z
++]));
unlink(AuxFile);
PrintLabels(AuxFile);
PrintCites(AuxFile);
PrintToc(TocName);
FreeLabels();
FreeCites();
FreeToc();
FreeIndex();
FreeFontStack();
NumPassesLeft--;
if (DoRepass)
fprintf(stderr
, "additional pass needed\n");
}
while (DoRepass && NumPassesLeft);
DestroyInstTable(TeXTable);
if (DoRepass)
{
fprintf(stderr
, "additional passes needed but cowardly not done\n");
return 3;
}
else
{
fprintf(stderr
, "%d pass(es) needed\n", CurrPass
);
return 0;
}
}
#ifdef CKMALLOC
#undef malloc
#undef realloc
void *ckmalloc(size_t s)
{
if (!tmp)
{
fprintf(stderr
, "allocation error(malloc): out of memory");
}
return tmp;
}
void *ckrealloc(void *p, size_t s)
{
if (!tmp)
{
fprintf(stderr
, "allocation error(realloc): out of memory");
}
return tmp;
}
#endif