Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* tex2doc.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Konverter TeX-->ASCII-DOC */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include "asmitree.h"
#include "chardefs.h"
#include <ctype.h>
#include <string.h>
#include "strutil.h"
#include "findhyphen.h"
#ifndef __MSDOS__
#include "ushyph.h"
#include "grhyph.h"
#endif
#include "chardefs.h"
#include "texutil.h"
#include "texrefs.h"
#include "textoc.h"
#include "texfonts.h"
#include "nls.h"
/*--------------------------------------------------------------------------*/
#define TOKLEN 250
static char *TableName
,
*BiblioName
,
*ContentsName
,
#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
;
typedef enum
{
AlignNone
, AlignCenter
, AlignLeft
, AlignRight
} TAlignment
;
typedef struct sEnvSave
{
struct sEnvSave
*Next
;
EnvType SaveEnv
;
int ListDepth
, ActLeftMargin
, LeftMargin
, RightMargin
;
int EnumCounter
, FontNest
;
TAlignment Alignment
;
} 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
;
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 TocName
[200];
static char SrcDir
[TOKLEN
+ 1], asname
[TOKLEN
];
#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
;
static TTable
*pThisTable
;
static int CurrRow
, CurrCol
;
static Boolean GermanMode
;
static EnvType CurrEnv
;
static int CurrPass
;
static int CurrListDepth
;
static int EnumCounter
;
static int ActLeftMargin
, LeftMargin
, RightMargin
;
static TAlignment Alignment
;
static PEnvSave EnvStack
;
static PInstTable TeXTable
;
static tCodepage Codepage
;
static const tNLSCharacterTab
*pCharacterTab
;
static Boolean enable_hyphenation
;
/*--------------------------------------------------------------------------*/
void ChkStack
(void)
{
}
static void SetSrcDir
(const char *pSrcFile
)
{
const char *pSep
;
pSep
= strchr(pSrcFile
, PATHSEP
);
if (!pSep
)
pSep
= strchr(pSrcFile
, '/');
if (!pSep
)
*SrcDir
= '\0';
else
{
size_t l
= pSep
+ 1 - pSrcFile
;
if (l
>= sizeof(SrcDir
))
{
fprintf(stderr
, "%s: path too long\n", pSrcFile
);
exit(3);
}
memcpy(SrcDir
, pSrcFile
, l
);
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
++]));
fclose(outfile
);
exit(2);
}
static void SetLang
(Boolean IsGerman
)
{
char **pp
;
if (GermanMode
== IsGerman
)
return;
DestroyTree
();
GermanMode
= IsGerman
;
if (GermanMode
)
{
TableName
= "Tabelle";
BiblioName
= "Literaturverzeichnis";
ContentsName
= "Inhalt";
ErrorEntryNames
[0] = "Typ";
ErrorEntryNames
[1] = "Ursache";
ErrorEntryNames
[2] = "Argument";
#ifndef __MSDOS__
BuildTree
(GRHyphens
);
#endif
}
else
{
TableName
= "Table";
BiblioName
= "Bibliography";
ContentsName
= "Contents";
ErrorEntryNames
[0] = "Type";
ErrorEntryNames
[1] = "Reason";
ErrorEntryNames
[2] = "Argument";
#ifndef __MSDOS__
BuildTree
(USHyphens
);
for (pp
= USExceptions
; *pp
!= NULL
; pp
++)
AddException
(*pp
);
#endif
}
}
/*------------------------------------------------------------------------------*/
static void GetNext
(char *Src
, char *Dest
)
{
char *c
= strchr(Src
, ' ');
if (!c
)
{
strcpy(Dest
, Src
);
*Src
= '\0';
}
else
{
*c
= '\0';
strcpy(Dest
, Src
);
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;
while (!feof(file
))
{
if (!fgets(Line
, 299, file
))
break;
if ((*Line
) && (Line
[strlen(Line
) - 1] == '\n'))
Line
[strlen(Line
) - 1] = '\0';
GetNext
(Line
, Cmd
);
if (!strcmp(Cmd
, "Label"))
{
GetNext
(Line
, Nam
);
GetNext
(Line
, Val
);
AddLabel
(Nam
, Val
);
}
else if (!strcmp(Cmd
, "Citation"))
{
GetNext
(Line
, Nam
);
GetNext
(Line
, Val
);
AddCite
(Nam
, Val
);
}
}
fclose(file
);
}
/*--------------------------------------------------------------------------*/
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
)
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
);
if (strcmp(ref
, 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
);
done
= !strcmp(Comp
, term
);
if (!done
)
{
if (!first
)
strcat(dest
, SepString
);
strcat(dest
, Comp
);
}
first
= False
;
}
while (!done
);
}
/*--------------------------------------------------------------------------*/
static const char CHR_ae
[3] = HYPHEN_CHR_ae
,
CHR_oe
[3] = HYPHEN_CHR_oe
,
CHR_ue
[3] = HYPHEN_CHR_ue
,
CHR_AE
[3] = HYPHEN_CHR_AE
,
CHR_OE
[3] = HYPHEN_CHR_OE
,
CHR_UE
[3] = HYPHEN_CHR_UE
,
CHR_sz
[3] = HYPHEN_CHR_sz
;
static int visible_clen
(char ch
)
{
if (Codepage
!= eCodepageASCII
)
return 1;
else if (ch
== *CHR_ae
)
return CharTab_GetLength
(pCharacterTab
, eCH_ae
);
else if (ch
== *CHR_oe
)
return CharTab_GetLength
(pCharacterTab
, eCH_oe
);
else if (ch
== *CHR_ue
)
return CharTab_GetLength
(pCharacterTab
, eCH_ue
);
else if (ch
== *CHR_AE
)
return CharTab_GetLength
(pCharacterTab
, eCH_Ae
);
else if (ch
== *CHR_OE
)
return CharTab_GetLength
(pCharacterTab
, eCH_Oe
);
else if (ch
== *CHR_UE
)
return CharTab_GetLength
(pCharacterTab
, eCH_Ue
);
else if (ch
== *CHR_sz
)
return CharTab_GetLength
(pCharacterTab
, eCH_sz
);
else
return 1;
}
static int visible_strlen
(const char *pStr
)
{
int res
= 0;
while (*pStr
)
res
+= visible_clen
(*pStr
++);
return res
;
}
static int visible_strnlen
(const char *pStr
, int MaxLen
)
{
int res
= 0;
while (*pStr
&& MaxLen
)
{
res
+= visible_clen
(*pStr
++);
MaxLen
--;
}
return res
;
}
static void outc
(char ch
)
{
char Buf
[3];
if (ch
== *CHR_ae
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_ae
, Buf
), outfile
);
else if (ch
== *CHR_oe
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_oe
, Buf
), outfile
);
else if (ch
== *CHR_ue
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_ue
, Buf
), outfile
);
else if (ch
== *CHR_AE
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_Ae
, Buf
), outfile
);
else if (ch
== *CHR_OE
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_Oe
, Buf
), outfile
);
else if (ch
== *CHR_UE
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_Ue
, Buf
), outfile
);
else if (ch
== *CHR_sz
)
fputs(CharTab_GetNULTermString
(pCharacterTab
, eCH_sz
, Buf
), outfile
);
else
fputc(ch
, outfile
);
}
static void outs
(const char *pStr
)
{
while (*pStr
)
outc
(*pStr
++);
}
static char OutLineBuffer
[TOKLEN
] = "", SideMargin
[TOKLEN
];
static void PutLine
(Boolean DoBlock
)
{
int ll
= RightMargin
- LeftMargin
+ 1;
int l
, n
, ptrcnt
, diff
, div, mod
, divmod
;
char *chz
, *ptrs
[50];
Boolean SkipFirst
, IsFirst
;
outs
(Blanks
(LeftMargin
- 1));
if ((Alignment
!= AlignNone
) || (!DoBlock
))
{
l
= visible_strlen
(OutLineBuffer
);
diff
= ll
- l
;
switch (Alignment
)
{
case AlignRight
:
outs
(Blanks
(diff
));
l
= ll
;
break;
case AlignCenter
:
outs
(Blanks
(diff
>> 1));
l
+= diff
>> 1;
break;
default:
break;
}
outs
(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
+= visible_clen
(*chz
);
}
(void)ptrs
;
diff
= ll
+ 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
++)
{
outc
(*chz
);
if ((chz
> OutLineBuffer
) && (*(chz
- 1) != ' ') && (*chz
== ' '))
{
if (!IsFirst
)
{
n
= div;
if ((mod
> 0) && (!(ptrcnt
% divmod
)))
{
mod
--;
n
++;
}
if (n
> 0)
outs
(Blanks
(n
));
ptrcnt
++;
}
IsFirst
= False
;
}
}
l
= RightMargin
- LeftMargin
+ 1;
}
if (*SideMargin
!= '\0')
{
outs
(Blanks
(ll
+ 3 - l
));
outs
(SideMargin
);
*SideMargin
= '\0';
}
outc
('\n');
LeftMargin
= ActLeftMargin
;
}
static void AddLine
(const char *Part
, char *Sep
)
{
int mlen
= RightMargin
- LeftMargin
+ 1, *hyppos
, hypcnt
, z
, hlen
, vlen
;
char *search
, save
, *lastalpha
;
if (strlen(Sep
) > 1)
Sep
[1] = '\0';
if (*OutLineBuffer
!= '\0')
strcat(OutLineBuffer
, Sep
);
strcat(OutLineBuffer
, Part
);
vlen
= visible_strlen
(OutLineBuffer
);
if (vlen
>= mlen
)
{
search
= OutLineBuffer
+ mlen
;
while (search
>= OutLineBuffer
)
{
if (*search
== ' ')
break;
if (search
> OutLineBuffer
)
{
if (*(search
- 1) == '-')
break;
else if (*(search
- 1) == '/')
break;
else if (*(search
- 1) == ';')
break;
else if (*(search
- 1) == ';')
break;
}
search
--;
}
if (search
<= OutLineBuffer
)
{
PutLine
(True
);
*OutLineBuffer
= '\0';
}
else
{
if (*search
== ' ')
{
for (lastalpha
= search
+ 1; *lastalpha
!= '\0'; lastalpha
++)
if ((as_tolower
(*lastalpha
) < 'a') || (as_tolower
(*lastalpha
) > 'z'))
break;
if (lastalpha
- search
> 3)
{
save
= (*lastalpha
);
*lastalpha
= '\0';
if (enable_hyphenation
)
DoHyphens
(search
+ 1, &hyppos
, &hypcnt
);
else
hypcnt
= 0;
*lastalpha
= save
;
hlen
= -1;
for (z
= 0; z
< hypcnt
; z
++)
if (visible_strnlen
(OutLineBuffer
, search
- OutLineBuffer
) + hyppos
[z
] + 1 < mlen
)
hlen
= hyppos
[z
];
if (hlen
> 0)
{
memmove(search
+ hlen
+ 2, search
+ hlen
+ 1, strlen(search
+ hlen
+ 1) + 1);
search
[hlen
+ 1] = '-';
search
+= hlen
+ 2;
}
if (hypcnt
> 0)
free(hyppos
);
}
}
save
= (*search
);
*search
= '\0';
PutLine
(True
);
*search
= save
;
for (; *search
== ' '; search
++);
strcpy(OutLineBuffer
, search
);
}
}
}
static void AddSideMargin
(const char *Part
, char *Sep
)
{
if (strlen(Sep
) > 1)
Sep
[1] = '\0';
if (*Sep
!= '\0')
if ((*SideMargin
!= '\0') || (!issep
(*Sep
)))
strcat(SideMargin
, Sep
);
strcat(SideMargin
, Part
);
}
static void FlushLine
(void)
{
if (*OutLineBuffer
!= '\0')
{
PutLine
(False
);
*OutLineBuffer
= '\0';
}
}
static void ResetLine
(void)
{
*OutLineBuffer
= '\0';
}
/*--------------------------------------------------------------------------*/
void PrFontDiff
(int OldFlags
, int NewFlags
)
{
(void)OldFlags
;
(void)NewFlags
;
}
void PrFontSize
(tFontSize Type
, Boolean On
)
{
(void)Type
;
(void)On
;
}
static void SaveEnv
(EnvType NewEnv
)
{
PEnvSave NewSave
;
NewSave
= (PEnvSave
) malloc(sizeof(TEnvSave
));
NewSave
->Next
= EnvStack
;
NewSave
->ListDepth
= CurrListDepth
;
NewSave
->LeftMargin
= LeftMargin
;
NewSave
->Alignment
= Alignment
;
NewSave
->ActLeftMargin
= ActLeftMargin
;
NewSave
->RightMargin
= RightMargin
;
NewSave
->EnumCounter
= EnumCounter
;
NewSave
->SaveEnv
= CurrEnv
;
NewSave
->FontNest
= FontNest
;
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
;
Alignment
= OldSave
->Alignment
;
EnumCounter
= OldSave
->EnumCounter
;
FontNest
= OldSave
->FontNest
;
CurrEnv
= OldSave
->SaveEnv
;
free(OldSave
);
}
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 AddTableEntry
(const char *Part
, char *Sep
)
{
char *Ptr
= pThisTable
->Lines
[CurrRow
][CurrCol
];
int nlen
= Ptr
? strlen(Ptr
) : 0;
Boolean UseSep
= (nlen
> 0);
if (strlen(Sep
) > 1)
Sep
[1] = '\0';
if (UseSep
)
nlen
+= strlen(Sep
);
nlen
+= strlen(Part
);
if (!Ptr
)
{
Ptr
= (char *) malloc(nlen
+ 1);
*Ptr
= '\0';
}
else
{
char *NewPtr
= (char *) realloc(Ptr
, nlen
+ 1);
if (NewPtr
)
Ptr
= NewPtr
;
}
if (UseSep
)
strcat(Ptr
, Sep
);
strcat(Ptr
, Part
);
pThisTable
->Lines
[CurrRow
][CurrCol
] = Ptr
;
}
static void DoPrnt
(char *Ptr
, TColumn Align
, int len
)
{
int l
= (!Ptr
) ? 0 : visible_strlen
(Ptr
), diff
;
len
-= 2;
diff
= len
- l
;
outc
(' ');
switch (Align
)
{
case ColRight
:
outs
(Blanks
(diff
));
break;
case ColCenter
:
outs
(Blanks
((diff
+ 1) / 2));
break;
default:
break;
}
if (Ptr
)
{
outs
(Ptr
);
free(Ptr
);
}
switch (Align
)
{
case ColLeft
:
outs
(Blanks
(diff
));
break;
case ColCenter
:
outs
(Blanks
(diff
/ 2));
break;
default:
break;
}
outc
(' ');
}
static void DumpTable
(void)
{
int RowCnt
, rowz
, colz
, colptr
, ml
, l
, diff
, sumlen
, firsttext
, indent
;
/* 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 : visible_strlen
(pThisTable
->Lines
[rowz
][colptr
]);
if (ml
< l
)
ml
= l
;
}
pThisTable
->ColLens
[colz
] = ml
+ 2;
colptr
++;
if (firsttext
< 0)
firsttext
= colz
;
}
/* 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] ? strlen(pThisTable
->Lines
[rowz
][0]) : 0;
if (ml
< l
)
ml
= l
;
}
if (ml
+ 4 > sumlen
)
{
diff
= ml
+ 4 - sumlen
;
pThisTable
->ColLens
[firsttext
] += diff
;
}
/* print rows */
for (rowz
= 0; rowz
< RowCnt
; rowz
++)
{
outs
(Blanks
(LeftMargin
- 1 + indent
));
if (pThisTable
->MultiFlags
[rowz
])
{
l
= sumlen
;
if (pThisTable
->ColTypes
[0] == ColBar
)
{
l
--;
outc
('|');
}
if (pThisTable
->ColTypes
[pThisTable
->ColumnCount
- 1] == ColBar
)
l
--;
for (colz
= 0; colz
< pThisTable
->ColumnCount
; colz
++)
{
if (!colz
)
DoPrnt
(pThisTable
->Lines
[rowz
][colz
], pThisTable
->ColTypes
[firsttext
], l
);
else if (pThisTable
->Lines
[rowz
][colz
])
{
free(pThisTable
->Lines
[rowz
][colz
]);
pThisTable
->Lines
[rowz
][colz
] = NULL
;
}
pThisTable
->Lines
[rowz
][0] = NULL
;
}
if (pThisTable
->ColTypes
[pThisTable
->ColumnCount
- 1] == ColBar
)
outc
('|');
}
else
{
for (colz
= colptr
= 0; colz
< pThisTable
->ColumnCount
; colz
++)
if (pThisTable
->LineFlags
[rowz
])
{
if (pThisTable
->ColTypes
[colz
] == ColBar
)
outc
('+');
else
for (l
= 0; l
< pThisTable
->ColLens
[colz
]; l
++)
outc
('-');
}
else
if (pThisTable
->ColTypes
[colz
] == ColBar
)
outc
('|');
else
{
DoPrnt
(pThisTable
->Lines
[rowz
][colptr
], pThisTable
->ColTypes
[colz
], pThisTable
->ColLens
[colz
]);
pThisTable
->Lines
[rowz
][colptr
] = NULL
;
colptr
++;
}
}
outc
('\n');
}
}
static void DoAddNormal
(const char *Part
, char *Sep
)
{
switch (CurrEnv
)
{
case EnvMarginPar
:
AddSideMargin
(Part
, Sep
);
break;
case EnvTabular
:
AddTableEntry
(Part
, Sep
);
break;
default:
AddLine
(Part
, Sep
);
}
}
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 (*OutLineBuffer
== '\0')
strcpy(OutLineBuffer
, " ");
FlushLine
();
}
if (CurrEnv
== EnvTabbing
)
CurrTabStop
= 0;
}
static void TeXKillLine
(Word Index
)
{
UNUSED
(Index
);
ResetLine
();
}
static void TeXDummy
(Word Index
)
{
UNUSED
(Index
);
}
static void TeXDummyNoBrack
(Word Index
)
{
char Token
[TOKLEN
];
UNUSED
(Index
);
ReadToken
(Token
);
}
static void TeXDummyEqual
(Word Index
)
{
char Token
[TOKLEN
];
UNUSED
(Index
);
assert_token
("=");
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
);
if (!strcmp(token
, "["))
{
ReadToken
(arg_cnt
);
assert_token
("]");
ReadToken
(token
);
}
if (strcmp(token
, "{"))
error
("\"{\" expected");
level
= 1;
*sum_token
= '\0';
do
{
ReadToken
(token
);
if (!strcmp(token
, "{"))
level
++;
else if (!strcmp(token
, "}"))
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
);
if (!strcmp(Token
, "{"))
level
++;
else if (!strcmp(Token
, "}"))
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
();
outc
('\n');
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
, z
;
char Line
[TOKLEN
], Title
[TOKLEN
];
strcpy(Title
, OutLineBuffer
);
*OutLineBuffer
= '\0';
*Line
= '\0';
if (Level
< 3)
{
GetSectionName
(Line
, sizeof(Line
));
as_snprcatf
(Line
, sizeof(Line
), " ");
if ((Level
== 2) && (((strlen(Line
) + strlen(Title
))&1) == 0))
as_snprcatf
(Line
, sizeof(Line
), " ");
}
as_snprcatf
(Line
, sizeof(Line
), "%s", Title
);
outs
(" ");
outs
(Line
);
outs
("\n ");
for (z
= 0; z
< (int)strlen(Line
); z
++)
switch(Level
)
{
case 0:
outc
('=');
break;
case 1:
outc
('-');
break;
case 2:
outc
(((z
&1) == 0) ? '-' : ' ');
break;
case 3:
outc
('.');
break;
}
outc
('\n');
if (Level
< 3)
{
GetSectionName
(Line
, sizeof(Line
));
as_snprcatf
(Line
, sizeof(Line
), " %s", Title
);
AddToc
(Line
, 5 + Level
);
}
}
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
];
EnvType NEnv
;
Boolean done
;
TColumn NCol
;
int z
;
UNUSED
(Index
);
assert_token
("{");
ReadToken
(EnvName
);
if ((NEnv
= GetEnvType
(EnvName
)) == EnvTable
)
{
ReadToken
(Add
);
if (!strcmp(Add
, "*"))
assert_token
("}");
else if (strcmp(Add
, "}"))
error
("unknown table environment");
}
else
assert_token
("}");
if (NEnv
!= EnvVerbatim
)
SaveEnv
(NEnv
);
switch (NEnv
)
{
case EnvItemize
:
case EnvEnumerate
:
case EnvDescription
:
FlushLine
();
if (CurrListDepth
== 0)
outc
('\n');
++CurrListDepth
;
ActLeftMargin
= LeftMargin
= (CurrListDepth
* 4) + 1;
RightMargin
= 70;
EnumCounter
= 0;
break;
case EnvBiblio
:
FlushLine
(); outc
('\n');
outs
(" ");
outs
(BiblioName
);
outs
("\n ");
for (z
= 0; z
< (int)strlen(BiblioName
); z
++)
outc
('=');
outc
('\n');
assert_token
("{");
ReadToken
(Add
);
assert_token
("}");
ActLeftMargin
= LeftMargin
= 4 + (BibIndent
= strlen(Add
));
break;
case EnvVerbatim
:
FlushLine
();
if ((*BufferLine
!= '\0') && (*BufferPtr
!= '\0'))
{
outs
(BufferPtr
);
*BufferLine
= '\0';
BufferPtr
= BufferLine
;
}
do
{
if (!fgets(Add
, TOKLEN
-1, infiles
[IncludeNest
- 1]))
break;
CurrLine
++;
done
= strstr(Add
, "\\end{verbatim}") != NULL
;
if (!done
)
outs
(Add
);
}
while (!done
);
outc
('\n');
break;
case EnvQuote
:
FlushLine
();
outc
('\n');
ActLeftMargin
= LeftMargin
= 5;
RightMargin
= 70;
break;
case EnvTabbing
:
FlushLine
();
outc
('\n');
TabStopCnt
= 0;
CurrTabStop
= 0;
break;
case EnvTable
:
ReadToken
(Add
);
if (strcmp(Add
, "["))
BackToken
(Add
);
else
do
{
ReadToken
(Add
);
}
while (strcmp(Add
, "]"));
FlushLine
();
outc
('\n');
++TableNum
;
break;
case EnvCenter
:
FlushLine
();
Alignment
= AlignCenter
;
break;
case EnvRaggedRight
:
FlushLine
();
Alignment
= AlignLeft
;
break;
case EnvRaggedLeft
:
FlushLine
();
Alignment
= AlignRight
;
break;
case EnvTabular
:
FlushLine
();
assert_token
("{");
pThisTable
->ColumnCount
= pThisTable
->TColumnCount
= 0;
do
{
ReadToken
(Add
);
done
= !strcmp(Add
, "}");
if (!done
)
{
if (pThisTable
->ColumnCount
>= MAXCOLS
)
error
("too many columns in table");
if (!strcmp(Add
, "|"))
NCol
= ColBar
;
else if (!strcmp(Add
, "l"))
NCol
= ColLeft
;
else if (!strcmp(Add
, "r"))
NCol
= ColRight
;
else if (!strcmp(Add
, "c"))
NCol
= ColCenter
;
else
{
NCol
= ColBar
;
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
);
if (!strcmp(Add
, "*"))
assert_token
("}");
else if (strcmp(Add
, "}"))
error
("unknown table environment");
}
else
assert_token
("}");
if (!EnvStack
)
error
("end without begin");
if (CurrEnv
!= NEnv
)
{
char Str
[100];
as_snprintf
(Str
, sizeof(Str
), "begin (%s) and end (%s) of environment do not match",
EnvNames
[CurrEnv
], EnvNames
[NEnv
]);
error
(Str
);
}
switch (CurrEnv
)
{
case EnvItemize
:
case EnvEnumerate
:
case EnvDescription
:
FlushLine
();
if (CurrListDepth
== 1)
outc
('\n');
break;
case EnvBiblio
:
case EnvQuote
:
case EnvTabbing
:
FlushLine
();
outc
('\n');
break;
case EnvCenter
:
case EnvRaggedRight
:
case EnvRaggedLeft
:
FlushLine
();
break;
case EnvTabular
:
DumpTable
();
break;
case EnvTable
:
FlushLine
();
outc
('\n');
break;
default:
break;
}
RestoreEnv
();
}
static void TeXItem
(Word Index
)
{
char NumString
[20], Token
[TOKLEN
], Acc
[TOKLEN
];
UNUSED
(Index
);
FlushLine
();
switch(CurrEnv
)
{
case EnvItemize
:
LeftMargin
= ActLeftMargin
- 3;
AddLine
(" - ", "");
break;
case EnvEnumerate
:
LeftMargin
= ActLeftMargin
- 4;
as_snprintf
(NumString
, sizeof(NumString
), "%3d ", ++EnumCounter
);
AddLine
(NumString
, "");
break;
case EnvDescription
:
ReadToken
(Token
);
if (strcmp(Token
, "[")) BackToken
(Token
);
else
{
collect_token
(Acc
, "]");
LeftMargin
= ActLeftMargin
- 4;
as_snprintf
(NumString
, sizeof(NumString
), "%3s ", Acc
);
AddLine
(NumString
, "");
}
break;
default:
error
("\\item not in a list environment");
}
}
static void TeXBibItem
(Word Index
)
{
char NumString
[20], Token
[TOKLEN
], Name
[TOKLEN
], Format
[10];
UNUSED
(Index
);
if (CurrEnv
!= EnvBiblio
)
error
("\\bibitem not in bibliography environment");
assert_token
("{");
collect_token
(Name
, "}");
FlushLine
();
outc
('\n');
++BibCounter
;
LeftMargin
= ActLeftMargin
- BibIndent
- 3;
as_snprintf
(Format
, sizeof(Format
), "[%%%dd] ", BibIndent
);
as_snprintf
(NumString
, sizeof(NumString
), Format
, 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 TeXAddSSharp
(Word Index
)
{
UNUSED
(Index
);
DoAddNormal
(HYPHEN_CHR_sz
, 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
)
{
char Buf
[3];
UNUSED
(Index
);
DoAddNormal
(CharTab_GetNULTermString
(pCharacterTab
, eCH_mu
, Buf
), BackSepString
);
}
static void TeXAddGreekPi
(Word Index
)
{
UNUSED
(Index
);
DoAddNormal
("Pi", 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 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 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 TeXAddRightArrow
(Word Index
)
{
UNUSED
(Index
);
DoAddNormal
("->", BackSepString
);
}
static void TeXAddLongRightArrow
(Word Index
)
{
UNUSED
(Index
);
DoAddNormal
("-->", BackSepString
);
}
static void TeXAddLongLeftArrow
(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 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
)
{
CurrFontType
= (tFontType
) Index
;
}
static void TeXEnvNewFontType
(Word Index
)
{
char NToken
[TOKLEN
];
SaveFont
();
CurrFontType
= (tFontType
) Index
;
assert_token
("{");
ReadToken
(NToken
);
strcpy(SepString
, BackSepString
);
BackToken
(NToken
);
}
static void TeXNewFontSize
(Word Index
)
{
CurrFontSize
= (tFontSize
) Index
;
}
static void TeXEnvNewFontSize
(Word Index
)
{
char NToken
[TOKLEN
];
SaveFont
();
CurrFontSize
= (tFontSize
) Index
;
assert_token
("{");
ReadToken
(NToken
);
strcpy(SepString
, BackSepString
);
BackToken
(NToken
);
}
static void TeXAddMarginPar
(Word Index
)
{
UNUSED
(Index
);
assert_token
("{");
SaveEnv
(EnvMarginPar
);
}
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
();
outc
('\n');
GetTableName
(tmp
, sizeof(tmp
));
SaveEnv
(EnvCaption
);
AddLine
(TableName
, "");
cnt
= strlen(TableName
);
strcat(tmp
, ": ");
AddLine
(tmp
, " ");
cnt
+= 1 + strlen(tmp
);
LeftMargin
= 1;
ActLeftMargin
= cnt
+ 1;
RightMargin
= 70;
}
static void TeXEndHead
(Word Index
)
{
UNUSED
(Index
);
}
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
("\\multicolumn 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
);
}
while (strcmp(Token
, "}"));
pThisTable
->MultiFlags
[CurrRow
] = True
;
}
static void TeXIndex
(Word Index
)
{
char Token
[TOKLEN
];
UNUSED
(Index
);
assert_token
("{");
do
{
ReadToken
(Token
);
}
while (strcmp(Token
, "}"));
}
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
++)
if (!strcmp(*run
, Acc
+ strlen(Acc
) - strlen(*run
)))
break;
if (**run
== '\0')
error
("unknown unit for dimension");
Acc
[strlen(Acc
) - strlen(*run
)] = '\0';
Value
= strtod(Acc
, &endptr
);
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
++)
outc
('\n');
}
static void TeXRule
(Word Index
)
{
int h
= GetDim
(HFactors
), v
= GetDim
(VFactors
);
char Rule
[200];
UNUSED
(Index
);
for (v
= 0; v
< h
; Rule
[v
++] = '-');
Rule
[v
] = '\0';
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");
n
= strlen(OutLineBuffer
);
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
++;
}
static void TeXJmpTabStop
(Word Index
)
{
int diff
;
UNUSED
(Index
);
if (CurrEnv
!= EnvTabbing
)
error
("tab trigger outside of tabbing environment");
if (CurrTabStop
>= TabStopCnt
)
error
("not enough tab stops");
diff
= TabStops
[CurrTabStop
] - strlen(OutLineBuffer
);
if (diff
> 0)
DoAddNormal
(Blanks
(diff
), "");
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
, "");
pos
= strchr(Token
, Marker
);
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
);
}
static void TeXWriteRef
(Word Index
)
{
char Name
[TOKLEN
], Value
[TOKLEN
];
UNUSED
(Index
);
assert_token
("{");
collect_token
(Name
, "}");
GetLabel
(Name
, Value
);
DoAddNormal
(Value
, BackSepString
);
}
static void TeXWriteCitation
(Word Index
)
{
char Name
[TOKLEN
], Value
[TOKLEN
];
UNUSED
(Index
);
assert_token
("{");
collect_token
(Name
, "}");
GetCite
(Name
, Value
);
as_snprintf
(Name
, sizeof(Name
), "[%s]", Value
);
DoAddNormal
(Name
, BackSepString
);
}
static void TeXNewParagraph
(Word Index
)
{
UNUSED
(Index
);
FlushLine
();
outc
('\n');
}
static void TeXContents
(Word Index
)
{
FILE
*file
= fopen(TocName
, "r");
char Line
[200];
UNUSED
(Index
);
if (!file
)
{
Warning
("contents file not found.");
DoRepass
= True
;
return;
}
FlushLine
();
outs
(" ");
outs
(ContentsName
);
outs
("\n\n");
while (!feof(file
))
{
if (!fgets(Line
, 199, file
))
break;
outs
(Line
);
}
fclose(file
);
}
static void TeXParSkip
(Word Index
)
{
char Token
[TOKLEN
];
UNUSED
(Index
);
ReadToken
(Token
);
do
{
ReadToken
(Token
);
if ((!strncmp(Token
, "plus", 4)) || (!strncmp(Token
, "minus", 5)))
{
}
else
{
BackToken
(Token
);
return;
}
}
while (1);
}
static void TeXNLS
(Word Index
)
{
char Token
[TOKLEN
], Buf
[3];
const char *Repl
= NULL
;
UNUSED
(Index
);
/* NOTE: For characters relevant to hyphenation, insert the
(codepage-independent) hyphen characters at this place.
Transformation to codepage-dependent character takes
place @ output: */
*Token
= '\0';
ReadToken
(Token
);
if (*SepString
== '\0')
switch (*Token
)
{
case 'a':
Repl
= HYPHEN_CHR_ae
;
break;
case 'e':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ee
, Buf
);
break;
case 'i':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ie
, Buf
);
break;
case 'o':
Repl
= HYPHEN_CHR_oe
;
break;
case 'u':
Repl
= HYPHEN_CHR_ue
;
break;
case 'A':
Repl
= HYPHEN_CHR_AE
;
break;
case 'E':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ee
, Buf
);
break;
case 'I':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ie
, Buf
);
break;
case 'O':
Repl
= HYPHEN_CHR_OE
;
break;
case 'U':
Repl
= HYPHEN_CHR_UE
;
break;
case 's':
Repl
= HYPHEN_CHR_sz
;
break;
default :
break;
}
if (Repl
)
{
if (strlen(Repl
) > 1)
memmove(Token
+ strlen(Repl
), Token
+ 1, strlen(Token
));
memcpy(Token
, Repl
, strlen(Repl
));
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal
("\"", BackSepString
);
BackToken
(Token
);
}
static void TeXNLSGrave
(Word Index
)
{
char Token
[TOKLEN
], Buf
[3];
const char *Repl
= NULL
;
UNUSED
(Index
);
*Token
= '\0';
ReadToken
(Token
);
if (*SepString
== '\0')
switch (*Token
)
{
case 'a':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_agrave
, Buf
);
break;
case 'A':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Agrave
, Buf
);
break;
case 'e':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_egrave
, Buf
);
break;
case 'E':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Egrave
, Buf
);
break;
case 'i':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_igrave
, Buf
);
break;
case 'I':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Igrave
, Buf
);
break;
case 'o':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ograve
, Buf
);
break;
case 'O':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ograve
, Buf
);
break;
case 'u':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ugrave
, Buf
);
break;
case 'U':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ugrave
, Buf
);
break;
default:
break;
}
if (Repl
)
{
if (strlen(Repl
) > 1)
memmove(Token
+ strlen(Repl
), Token
+ 1, strlen(Token
));
memcpy(Token
, Repl
, strlen(Repl
));
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal
("\"", BackSepString
);
BackToken
(Token
);
}
static void TeXNLSAcute
(Word Index
)
{
char Token
[TOKLEN
], Buf
[3];
const char *Repl
= NULL
;
UNUSED
(Index
);
*Token
= '\0';
ReadToken
(Token
);
if (*SepString
== '\0')
switch (*Token
)
{
case 'a':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_aacute
, Buf
);
break;
case 'A':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Aacute
, Buf
);
break;
case 'e':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_eacute
, Buf
);
break;
case 'E':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Eacute
, Buf
);
break;
case 'i':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_iacute
, Buf
);
break;
case 'I':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Iacute
, Buf
);
break;
case 'o':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_oacute
, Buf
);
break;
case 'O':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Oacute
, Buf
);
break;
case 'u':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_uacute
, Buf
);
break;
case 'U':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Uacute
, Buf
);
break;
default:
break;
}
if (Repl
)
{
if (strlen(Repl
) > 1)
memmove(Token
+ strlen(Repl
), Token
+ 1, strlen(Token
));
memcpy(Token
, Repl
, strlen(Repl
));
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal
("\"", BackSepString
);
BackToken
(Token
);
}
static void TeXNLSCirc
(Word Index
)
{
char Token
[TOKLEN
], Buf
[3];
const char *Repl
= "";
UNUSED
(Index
);
*Token
= '\0';
ReadToken
(Token
);
if (*SepString
== '\0')
switch (*Token
)
{
case 'a':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_acirc
, Buf
);
break;
case 'A':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Acirc
, Buf
);
break;
case 'e':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ecirc
, Buf
);
break;
case 'E':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ecirc
, Buf
);
break;
case 'i':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_icirc
, Buf
);
break;
case 'I':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Icirc
, Buf
);
break;
case 'o':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ocirc
, Buf
);
break;
case 'O':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ocirc
, Buf
);
break;
case 'u':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ucirc
, Buf
);
break;
case 'U':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ucirc
, Buf
);
break;
default:
break;
}
if (Repl
)
{
if (strlen(Repl
) > 1)
memmove(Token
+ strlen(Repl
), Token
+ 1, strlen(Token
));
memcpy(Token
, Repl
, strlen(Repl
));
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal
("\"", BackSepString
);
BackToken
(Token
);
}
static void TeXNLSTilde
(Word Index
)
{
char Token
[TOKLEN
], Buf
[3];
const char *Repl
= "";
UNUSED
(Index
);
*Token
= '\0';
ReadToken
(Token
);
if (*SepString
== '\0')
switch (*Token
)
{
case 'n':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_ntilde
, Buf
);
break;
case 'N':
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Ntilde
, Buf
);
break;
}
if (Repl
)
{
if (strlen(Repl
) > 1)
memmove(Token
+ strlen(Repl
), Token
+ 1, strlen(Token
));
memcpy(Token
, Repl
, strlen(Repl
));
strcpy(SepString
, BackSepString
);
}
else
DoAddNormal
("\"", BackSepString
);
BackToken
(Token
);
}
static void TeXCedilla
(Word Index
)
{
char Token
[TOKLEN
], Buf
[3];
UNUSED
(Index
);
assert_token
("{");
collect_token
(Token
, "}");
if (!strcmp(Token
, "c"))
strcpy(Token
, CharTab_GetNULTermString
(pCharacterTab
, eCH_ccedil
, Buf
));
if (!strcmp(Token
, "C"))
strcpy(Token
, CharTab_GetNULTermString
(pCharacterTab
, eCH_Ccedil
, Buf
));
DoAddNormal
(Token
, BackSepString
);
}
static void TeXAsterisk
(Word Index
)
{
(void)Index
;
DoAddNormal
("*", BackSepString
);
}
static Boolean TeXNLSSpec
(char *Line
)
{
Boolean Found
= True
;
char Buf
[3];
const char *Repl
= NULL
;
int cnt
= 0;
if (*SepString
== '\0')
switch (*Line
)
{
case 'o':
cnt
= 1;
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_oslash
, Buf
);
break;
case 'O':
cnt
= 1;
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Oslash
, Buf
);
break;
case 'a':
switch (Line
[1])
{
case 'a':
cnt
= 2;
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_aring
, Buf
);
break;
case 'e':
cnt
= 2;
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_aelig
, Buf
);
break;
default:
Found
= False
;
}
break;
case 'A':
switch (Line
[1])
{
case 'A':
cnt
= 2;
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Aring
, Buf
);
break;
case 'E':
cnt
= 2;
Repl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_Aelig
, Buf
);
break;
default:
Found
= False
;
}
break;
default:
Found
= False
;
}
if (Found
)
{
if ((int)strlen(Repl
) != cnt
)
memmove(Line
+ strlen(Repl
), Line
+ cnt
, strlen(Line
) - cnt
+ 1);
memcpy(Line
, Repl
, strlen(Repl
));
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
, "}");
AddException
(Token
);
}
static void TeXDoPot
(void)
{
char Token
[TOKLEN
];
ReadToken
(Token
);
if (*Token
== '2')
{
char Buf
[3];
const char *pRepl
= CharTab_GetNULTermString
(pCharacterTab
, eCH_e2
, Buf
);
if (strlen(pRepl
) > 1)
memmove(Token
+ strlen(pRepl
), Token
+ 1, strlen(Token
));
memcpy(Token
, pRepl
, strlen(pRepl
));
}
else
DoAddNormal
("^", BackSepString
);
BackToken
(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
("{");
strcpy(Token
, SrcDir
);
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
);
if (!strcmp(Token
, "["))
{
do
{
ReadToken
(Token
);
if (!strcmp(Token
, "german"))
SetLang
(True
);
}
while (strcmp(Token
, "]"));
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
);
if (!strcmp(Token
, "["))
{
do
{
ReadToken
(Token
);
if (!strcmp(Token
, "german"))
read_german_opt
= True
;
}
while (strcmp(Token
, "]"));
}
else if (!strcmp(Token
, "{"))
{
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
);
}
}
}
/*--------------------------------------------------------------------------*/
int main
(int argc
, char **argv
)
{
char Line
[TOKLEN
], Comp
[TOKLEN
], *p
, AuxFile
[200];
int z
, NumPassesLeft
;
if (argc
< 3)
{
fprintf(stderr
, "calling convention: %s <input file> <output file>\n", *argv
);
exit(1);
}
nls_init
();
if (!NLS_Initialize
(&argc
, argv
))
exit(3);
enable_hyphenation
= True
;
if (argc
)
{
int z
, dest
;
z
= dest
= 1;
while (z
< argc
)
if (!as_strcasecmp
(argv
[z
], "-nohyphen"))
{
enable_hyphenation
= False
;
z
++;
}
else
argv
[dest
++] = argv
[z
++];
argc
= dest
;
}
Codepage
= NLS_GetCodepage
();
pCharacterTab
= GetCharacterTab
(Codepage
);
pThisTable
= (TTable
*)calloc(1, sizeof(*pThisTable
));
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
, "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
, "land", 0, TeXAddLAnd
);
AddInstTable
(TeXTable
, "lor", 0, TeXAddLOr
);
AddInstTable
(TeXTable
, "oplus", 0, TeXAddOPlus
);
AddInstTable
(TeXTable
, "mid", 0, TeXAddMid
);
AddInstTable
(TeXTable
, "asname", 0, TeXASName
);
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
, "tin", FontTiny
, TeXEnvNewFontSize
);
AddInstTable
(TeXTable
, "rightarrow", 0, TeXAddRightArrow
);
AddInstTable
(TeXTable
, "longrightarrow", 0, TeXAddLongRightArrow
);
AddInstTable
(TeXTable
, "leftarrow", 0, TeXAddLeftArrow
);
AddInstTable
(TeXTable
, "gets", 0, TeXAddGets
);
AddInstTable
(TeXTable
, "longleftarrow", 0, TeXAddLongLeftArrow
);
AddInstTable
(TeXTable
, "leftrightarrow", 0, TeXAddLeftRightArrow
);
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, TeXDummy
);
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
, "*", 0, TeXAsterisk
);
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
++;
DidEOF
= False
;
IncludeNest
= 0;
pInFileName
= argv
[1];
*infiles
= fopen(pInFileName
, "r");
if (!*infiles
)
{
perror(pInFileName
);
exit(3);
}
else
IncludeNest
++;
SetSrcDir
(pInFileName
);
if (!strcmp(argv
[2], "-"))
outfile
= stdout
;
else
{
outfile
= fopen(argv
[2], "w");
if (!outfile
)
{
perror(argv
[2]);
exit(3);
}
}
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;
Alignment
= AlignNone
;
EnumCounter
= 0;
InitFont
();
CurrLine
= 0;
InitLabels
();
InitCites
();
InitToc
();
*SideMargin
= '\0';
DoRepass
= False
;
BibIndent
= BibCounter
= 0;
GermanMode
= True
;
SetLang
(False
);
strcpy(TocName
, pInFileName
);
p
= strrchr(TocName
, '.');
if (p
)
*p
= '\0';
strcat(TocName
, ".dtoc");
strcpy(AuxFile
, pInFileName
);
p
= strrchr(AuxFile
, '.');
if (p
)
*p
= '\0';
strcat(AuxFile
, ".daux");
ReadAuxFile
(AuxFile
);
while (1)
{
if (!ReadToken
(Line
))
break;
if (!strcmp(Line
, "\\"))
{
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
);
}
}
else if (!strcmp(Line
, "$"))
{
InMathMode
= !InMathMode
;
if (InMathMode
)
{
strcpy(BackSepString
, SepString
);
ReadToken
(Line
);
strcpy(SepString
, BackSepString
);
BackToken
(Line
);
}
}
else if (!strcmp(Line
, "&"))
NextTableColumn
();
else if ((!strcmp(Line
, "^")) && (InMathMode
))
TeXDoPot
();
else if ((!strcmp(Line
, "\"")) && (GermanMode
))
TeXDoSpec
();
else if (!strcmp(Line
, "{"))
SaveFont
();
else if (!strcmp(Line
, "}"))
{
if (FontNest
> 0)
RestoreFont
();
else if (ErrState
>= 0)
NextErrState
();
else if (FracState
>= 0)
NextFracState
();
else switch (CurrEnv
)
{
case EnvMarginPar
:
RestoreEnv
();
break;
case EnvCaption
:
FlushLine
();
RestoreEnv
();
break;
case EnvHeading
:
EndSectionHeading
();
RestoreEnv
();
break;
default:
RestoreFont
();
}
}
else
DoAddNormal
(Line
, SepString
);
}
FlushLine
();
for (z
= 0; z
< IncludeNest
; fclose(infiles
[z
++]));
fclose(outfile
);
unlink
(AuxFile
);
PrintLabels
(AuxFile
);
PrintCites
(AuxFile
);
PrintToc
(TocName
);
FreeLabels
();
FreeCites
();
DestroyTree
();
FreeToc
();
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
)
{
void *tmp
= malloc(s
);
if (!tmp
)
{
fprintf(stderr
, "allocation error(malloc): out of memory");
exit(255);
}
return tmp
;
}
void *ckrealloc
(void *p
, size_t s
)
{
void *tmp
= realloc(p
, s
);
if (!tmp
)
{
fprintf(stderr
, "allocation error(realloc): out of memory");
exit(255);
}
return tmp
;
}
#endif