|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 40909 (0x9fcd)
Types: TextFile
Names: »index.y«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
└─⟦c319c2751⟧ »unix3.0/TeX3.0.tar.Z«
└─⟦036c765ac⟧
└─⟦this⟧ »TeX3.0/LaTeX/LaTeXindex/index.y«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./tex82/LaTeX/LaTeXindex/index.y«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
└─⟦63303ae94⟧ »unix3.14/TeX3.14.tar.Z«
└─⟦c58930e5c⟧
└─⟦this⟧ »TeX3.14/LaTeX/LaTeXindex/index.y«
/* $Header: index.y,v 1.5 88/01/25 17:37:20 root Exp $ */
/* Yacc parser for LaTeX index processor */
/* Roman numeral code written by John Renner (adobe!renner@decwrl.dec.com) */
%{
#include <stdio.h>
#include <local/standard.h>
#include <local/profile.h>
#include <ctype.h>
#include <pwd.h>
#define TABLEINCREMENT 50 /* Number of additional entries added when expanding a table */
#define ODD(i) (((i) % 2) == 1)
#define ITEMDEPTH 3 /* Number of nestings of \item's, \subitem's, \subsubitem's, etc. */
char *ItemRep[] = { "\\item", "\\subitem", "\\subsubitem", NULL }; /* and their representation */
char *calloc(), *realloc();
enum TokenType {controlword, controlsymbol, string, integer, roman, comma, obrace, cbrace, whitespace};
struct IndexEntry {
char literal[81]; /* Literal representation of index entry */
char alphabetic[81]; /* Alphabetic representation for sorting of index entry */
struct Token *tokenlist; /* Doubly linked token list */
struct IndexEntry *subitem; /* Pointer to subitem table, subsubitem table, etc */
int subitemcount; /* Number of items in subitem table */
int subitemtabsize; /* Subitem table size currently allocated */
struct PageNoTable *pagenos; /* List of page numbers */
int pagetablecount; /* Number of items in page number table */
int pagetablesize; /* Size of page number table currently allocated */
};
struct Token {
enum TokenType type; /* Token type */
char lexeme[81]; /* Representation of all the token types */
struct Token *prev, *next;
};
struct PageNoTable {
int number; /* Page number */
Boolean range; /* True if this is the beginning of a range */
Boolean roman; /* True if this was a roman numeral */
};
struct IndexEntry *IndexTable = NULL; /* Table of primary index entries */
int IndexTableCount = 0; /* Count of number of elements used in index table */
int IndexTableSize = 0; /* Current allocated size of index table */
int ExitStatus = SUCCEED; /* Guess */
int LineNo = 1; /* Line number at start of token */
int EndLineNo = 1; /* Line number at end of token */
Boolean Label = FALSE; /* True if -l option given */
Boolean Range; /* True if this \indexentry is a range */
PROFILE_STANZA *SortStanza = NULL; /* Alphabetize stanza */
extern int optind; /* From getopt(3) */
extern char *optarg;
char *Whoami; /* argv[0] */
char *Usage = "Usage: %s [-l] [-f alphabetizefile] [file...]\n";
char *Marker[] = { "alphabetize", NULL }; /* Markers for alphabetize stanza */
char IdxFileName[81]; /* .idx file name */
char Literal[81]; /* Literal string of key */
char Alphabetic[81]; /* Alphabetic string of key */
FILE *InputFile; /* Current input file */
FILE *OutputFile; /* Current output file */
struct Token *CurKey; /* Current key we are constructing */
struct IndexEntry **CurSearchTable; /* Current table to search for match */
struct IndexEntry *CurEntry; /* Current table entry */
struct IndexEntry *PrevEntry; /* Previous Entry */
%}
%union {
char value[81];
struct Token *t;
}
%token <value> ROMAN CONTROLSEQUENCE INTEGER WHITESPACE STRING INDEXENTRY
%type <t> noncommaelement anyelement anyelements
%%
indexfile :
optwhitespace
indexentries
{
sort(IndexTable, IndexTableCount);
fprintf(OutputFile, "\\begin{theindex}\n");
if (Label) {
fprintf(OutputFile,
"\\newcommand{\\largeletter}[1]{{\\pagebreak[2]\\Large\\hspace{-.5in}\\parbox[t]{.5in}{\\makebox[.35in][r]");
fprintf(OutputFile, "{\\uppercase{#1}}}\\nopagebreak[4]\\vspace{-1.5ex}}}\n");
}
printindexentries(IndexTable, IndexTableCount, 1);
fprintf(OutputFile, "\\end{theindex}\n");
}
;
indexentries :
indexentries
indexentry
|
indexentry
;
indexentry :
INDEXENTRY
{
CurSearchTable = &IndexTable, PrevEntry = NULL;
CurKey = NULL;
Range = FALSE;
}
optwhitespace
'{'
keys
'}'
optwhitespace
'{'
optwhitespace
anumber
optwhitespace
'}'
optwhitespace
;
anumber :
INTEGER
{
struct PageNoTable *p;
if (!(p = findpage(CurEntry->pagenos, CurEntry->pagetablecount, atoi($1), FALSE))) {
if (CurEntry->pagetablecount >= CurEntry->pagetablesize) {
if (!(CurEntry->pagenos = (struct PageNoTable *)reallocate(CurEntry->pagenos, CurEntry->pagetablesize,
TABLEINCREMENT, sizeof(struct PageNoTable)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
CurEntry->pagetablesize += TABLEINCREMENT;
}
CurEntry->pagenos[CurEntry->pagetablecount].number = atoi($1);
CurEntry->pagenos[CurEntry->pagetablecount].roman = FALSE;
CurEntry->pagenos[CurEntry->pagetablecount].range = Range;
CurEntry->pagetablecount++;
} else
p->range = Range;
}
|
ROMAN
{
struct PageNoTable *p;
if (!(p = findpage(CurEntry->pagenos, CurEntry->pagetablecount, rmtoi($1), TRUE))) {
if (CurEntry->pagetablecount >= CurEntry->pagetablesize) {
if (!(CurEntry->pagenos = (struct PageNoTable *)reallocate(CurEntry->pagenos, CurEntry->pagetablesize,
TABLEINCREMENT, sizeof(struct PageNoTable)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
CurEntry->pagetablesize += TABLEINCREMENT;
}
CurEntry->pagenos[CurEntry->pagetablecount].number = rmtoi($1);
CurEntry->pagenos[CurEntry->pagetablecount].roman = TRUE;
CurEntry->pagenos[CurEntry->pagetablecount].range = Range;
CurEntry->pagetablecount++;
} else
p->range = Range;
}
keys :
multiplekeys
key
{
struct Token *t;
for (t = CurKey; t->next; t = t->next)
;
if (t->type == string)
if (t->lexeme[strlen(t->lexeme) - 1] == '-') {
t->lexeme[strlen(t->lexeme) - 1] = '\0';
Range = TRUE;
}
goto installkey;
}
;
multiplekeys :
multiplekeys
key
','
{
struct Token *t;
installkey: strcpy(Literal, literalstring(CurKey));
strcpy(Alphabetic, alphabetizestring(CurKey, SortStanza));
if (!*CurSearchTable) {
if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, 0, TABLEINCREMENT,
sizeof(struct IndexEntry)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
if (!PrevEntry)
IndexTableSize = TABLEINCREMENT;
else
PrevEntry->subitemtabsize = TABLEINCREMENT;
}
if (!(CurEntry = findentry(*CurSearchTable, PrevEntry ? PrevEntry->subitemcount : IndexTableCount, Literal))) {
if (!PrevEntry) {
if (IndexTableCount >= IndexTableSize) {
if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, IndexTableSize, TABLEINCREMENT,
sizeof(struct IndexEntry)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
IndexTableSize += TABLEINCREMENT;
}
CurEntry = (*CurSearchTable + IndexTableCount);
IndexTableCount++;
} else {
if (PrevEntry->subitemcount >= PrevEntry->subitemtabsize) {
if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, PrevEntry->subitemtabsize,
TABLEINCREMENT, sizeof(struct IndexEntry)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
PrevEntry->subitemtabsize += TABLEINCREMENT;
}
CurEntry = (*CurSearchTable + PrevEntry->subitemcount);
PrevEntry->subitemcount++;
}
strcpy(CurEntry->literal, Literal);
strcpy(CurEntry->alphabetic, Alphabetic);
CurKey->prev = CurEntry->tokenlist, CurEntry->tokenlist = CurKey;
CurEntry->subitem = NULL, CurEntry->subitemcount = CurEntry->subitemtabsize = 0;
CurEntry->pagenos = NULL, CurEntry->pagetablecount = CurEntry->pagetablesize = 0;
}
CurSearchTable = &CurEntry->subitem;
PrevEntry = CurEntry;
CurKey = NULL;
}
|
/* epsilon */
;
key :
key
noncommaelement
|
noncommaelement
;
noncommaelement :
CONTROLSEQUENCE
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = isalpha($1[1]) ? controlword : controlsymbol;
strcpy($$->lexeme, $1);
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
|
ROMAN
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = roman;
strcpy($$->lexeme, $1);
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
|
INTEGER
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = integer;
strcpy($$->lexeme, $1);
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
|
WHITESPACE
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = whitespace;
strcpy($$->lexeme, $1);
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
|
STRING
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = string;
strcpy($$->lexeme, $1);
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
|
'{'
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = obrace;
strcpy($$->lexeme, "{");
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
}
anyelements
'}'
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = cbrace;
strcpy($$->lexeme, "}");
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
;
anyelements :
anyelements
anyelement
{
$$ = $2;
}
|
/* epsilon */
{
; /* Do nothing */
}
;
anyelement :
noncommaelement /* Default action is $$ = $1 */
|
','
{
if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
yyerror("memory allocation failure");
exit(FAIL);
}
$$->type = comma;
strcpy($$->lexeme, ",");
$$->next = NULL;
if (!CurKey)
$$->prev = CurKey, CurKey = $$;
else {
struct Token *p;
for (p = CurKey; p->next; p = p->next)
;
p->next = $$, $$->prev = p;
}
$$ = CurKey;
}
;
optwhitespace :
WHITESPACE
|
;
%%
#include "indexlex.c"
main(argc, argv)
int argc;
char *argv[];
{
int c;
Boolean sortfilegiven = FALSE;
char sortfilename[81];
char indfilename[81];
struct passwd *pwentry;
FILE *stanzafileptr;
Whoami = argv[0];
pwentry = getpwuid(geteuid());
sprintf(sortfilename, "%s/.alphabetize", pwentry->pw_dir);
while ((c = getopt(argc, argv, "f:l")) != EOF)
switch (c) {
case 'l':
Label = TRUE;
break;
case 'f':
strcpy(sortfilename, optarg);
sortfilegiven = TRUE;
break;
case '?':
fprintf(stderr, Usage, Whoami);
exit(FAIL);
}
stanzafileptr = fopen(sortfilename, "r");
if (sortfilegiven && !stanzafileptr) {
fprintf(stderr, "%s: cannot open alphabetization file %s\n", Whoami, sortfilename);
exit(FAIL);
}
if (stanzafileptr) {
if (!(SortStanza = profile_read_profile(stanzafileptr))) {
fprintf(stderr, "%s: file %s is not in stanza format\n", Whoami, sortfilename);
fclose(stanzafileptr);
exit(FAIL);
}
if (!(SortStanza = profile_has_stanza(SortStanza, Marker))) {
fprintf(stderr, "%s: file %s does not contain a stanza with marker %s\n", Whoami, sortfilename, Marker[0]);
fclose(stanzafileptr);
exit(FAIL);
}
fclose(stanzafileptr);
}
checkstanza(SortStanza);
if (optind == argc) {
InputFile = stdin;
OutputFile = stdout;
strcpy(IdxFileName, "stdin");
}
do {
if (InputFile != stdin) {
strcpy(IdxFileName, argv[optind]);
if (!(InputFile = fopen(argv[optind], "r"))) {
strcpy(IdxFileName, argv[optind]);
strcat(IdxFileName, ".idx");
if (!(InputFile = fopen(IdxFileName, "r"))) {
fprintf(stderr, "%s: cannot open %s\n", Whoami, IdxFileName);
ExitStatus = FAIL;
continue;
}
}
if (strlen(IdxFileName) >= 4 && EQ(&IdxFileName[strlen(IdxFileName)-4], ".idx"))
sprintf(indfilename, "%.*s.ind", strlen(IdxFileName)-4, IdxFileName);
else
sprintf(indfilename, "%s.ind", IdxFileName);
if (!(OutputFile = fopen(indfilename, "w"))) {
fprintf(stderr, "%s: cannot open output file %s\n", Whoami, indfilename);
fclose(InputFile);
ExitStatus = FAIL;
continue;
}
} else
strcpy(IdxFileName, "stdin");
if (yyparse() != 0)
ExitStatus = FAIL;
fclose(InputFile);
fclose(OutputFile);
freetables(IndexTable, IndexTableCount);
IndexTable = NULL, IndexTableCount = IndexTableSize = 0, LineNo = EndLineNo = 1;
yysptr = yysbuf; /* Resets Lex lookahead buffer */
} while (++optind < argc);
exit(ExitStatus);
}
yyerror(s)
char *s;
{
fprintf(stderr, "\"%s\", line %d: %s\n", IdxFileName, LineNo, s);
}
/* Allocates additional space for tables. Returns NULL if memory allocation failure or inconsistent parameters */
char *reallocate(table, current, increment, elementsize)
char *table; /* pointer to current table */
int current; /* current size of table */
int increment; /* additional entries to add */
int elementsize; /* size of an element in the table */
{
char *calloc(), *realloc();
char *p;
if ((!table && current > 0) || current < 0 || increment < 0 || elementsize < 0)
return NULL;
if (increment == 0 || elementsize == 0)
return table;
if (current == 0)
if (!(p = calloc(increment, elementsize)))
return NULL;
else
return p;
else
if (!(p = realloc(table, (current + increment) * elementsize)))
return NULL;
else
return p;
}
/* Frees the space allocated for all the tables */
freetables(index, noentries)
struct IndexEntry *index; /* index table */
int noentries; /* number of entries in table */
{
struct Token *t, *ttemp;
int i;
if (!index || noentries == 0)
return;
for (i = 0; i < noentries; i++)
if (index[i].subitem)
freetables(index[i].subitem, index[i].subitemcount); /* recursion! */
for (t = index[i].tokenlist; t; t = ttemp)
ttemp = t->next, free(t);
if (index[i].pagenos)
free(index[i].pagenos);
free(index);
}
/* Checks alphabetize stanza for validity */
checkstanza(ps)
PROFILE_STANZA *ps;
{
PROFILE_BINDING *pb;
PROFILE_VALUE *pv;
int count;
if (!ps)
return;
if (pb = profile_has_binding(ps, "skipchars"))
for (pv = pb->value; pv; pv = pv->next)
if (pv->class != PROFILE_CHARACTER)
switch (pv->class) {
case PROFILE_INTEGER:
fprintf(stderr, "%s: illegal integer constant %d in skipchars binding\n", Whoami, pv->value.i);
break;
case PROFILE_HEX:
fprintf(stderr, "%s: illegal hex constant 0x%x in skipchars binding\n", Whoami, pv->value.i);
break;
case PROFILE_OCTAL:
fprintf(stderr, "%s: illegal octal constant 0%o in skipchars binding\n", Whoami, pv->value.i);
break;
case PROFILE_FLOAT:
fprintf(stderr, "%s: illegal float constant %f in skipchars binding\n", Whoami, pv->value.f);
break;
case PROFILE_STRING:
case PROFILE_OTHER:
fprintf(stderr, "%s: illegal string constant %s in skipchars binding\n", Whoami, pv->value.s);
break;
}
if (pb = profile_has_binding(ps, "mapctrlsequence")) {
for (count = 0, pv = pb->value; pv; pv = pv->next, count++)
if (pv->class != PROFILE_OTHER || pv->class != PROFILE_STRING)
switch (pv->class) {
case PROFILE_INTEGER:
fprintf(stderr, "%s: illegal integer constant %d in mapctrlsequence binding\n", Whoami, pv->value.i);
break;
case PROFILE_HEX:
fprintf(stderr, "%s: illegal hex constant 0x%x in mapctrlsequence binding\n", Whoami, pv->value.i);
break;
case PROFILE_OCTAL:
fprintf(stderr, "%s: illegal octal constant 0%o in mapctrlsequence binding\n", Whoami, pv->value.i);
break;
case PROFILE_FLOAT:
fprintf(stderr, "%s: illegal float constant %f in mapctrlsequence binding\n", Whoami, pv->value.f);
break;
case PROFILE_CHARACTER:
fprintf(stderr, "%s: illegal character constant %c in mapctrlsequence binding\n", Whoami, pv->value.c);
break;
}
if (ODD(count))
fprintf(stderr, "%s: must have an even number of string values for mapctrlsequence binding\n", Whoami);
}
if (pb = profile_has_binding(ps, "mapindexentry")) {
for (count = 0, pv = pb->value; pv; pv = pv->next, count++)
if (pv->class != PROFILE_OTHER || pv->class != PROFILE_STRING)
switch (pv->class) {
case PROFILE_INTEGER:
fprintf(stderr, "%s: illegal integer constant %d in mapindexentry binding\n", Whoami, pv->value.i);
break;
case PROFILE_HEX:
fprintf(stderr, "%s: illegal hex constant 0x%x in mapindexentry binding\n", Whoami, pv->value.i);
break;
case PROFILE_OCTAL:
fprintf(stderr, "%s: illegal octal constant 0%o in mapindexentry binding\n", Whoami, pv->value.i);
break;
case PROFILE_FLOAT:
fprintf(stderr, "%s: illegal float constant %f in mapindexentry binding\n", Whoami, pv->value.f);
break;
case PROFILE_CHARACTER:
fprintf(stderr, "%s: illegal character constant %c in mapindexentry binding\n", Whoami, pv->value.c);
break;
}
if (ODD(count))
fprintf(stderr, "%s: must have an even number of string values for mapindexentry binding\n", Whoami);
}
}
/* Returns the literal string of a token list */
char *literalstring(t)
struct Token *t;
{
static char literal[81];
strcpy(literal, "");
for (t = CurKey; t; t = t->next)
strcat(literal, t->lexeme);
return literal;
}
/* Returns alphabetization string for a token list and a stanza */
char *alphabetizestring(tokenlist, stanza)
struct Token *tokenlist;
PROFILE_STANZA *stanza;
{
char litstring[81];
char ctrlstring[21];
char c;
static char alphastring[81];
int i;
Boolean add;
struct Token *t;
PROFILE_BINDING *pb;
PROFILE_VALUE *pv;
if (!tokenlist)
return NULL;
strcpy(alphastring, "");
if (!stanza) {
for (t = tokenlist; t; t = t->next)
switch (t->type) {
case string:
case integer:
case roman:
case comma:
case obrace:
case cbrace:
strcat(alphastring, t->lexeme);
break;
}
return alphastring;
} else {
strcpy(litstring, literalstring(tokenlist));
for (pb = stanza->binding; pb; pb = pb->next)
if (EQ(pb->name, "mapindexentry"))
for (pv = pb->value; pv && pv->next; pv = pv->next, pv = pv->next)
if ((pv->class == PROFILE_STRING || pv->class == PROFILE_OTHER) && (pv->next->class == PROFILE_STRING ||
pv->next->class == PROFILE_OTHER))
if (EQ(litstring, pv->value.s)) {
strcpy(alphastring, pv->next->value.s);
return alphastring;
}
for (t = tokenlist; t; t = t->next)
switch (t->type) {
case controlword:
case controlsymbol:
for (pb = stanza->binding; pb; pb = pb->next)
if (EQ(pb->name, "mapctrlsequence"))
for (pv = pb->value; pv && pv->next; pv = pv->next, pv = pv->next)
if ((pv->class == PROFILE_STRING || pv->class == PROFILE_OTHER) && (pv->next->class ==
PROFILE_STRING || pv->next->class == PROFILE_OTHER))
if (strlen(pv->value.s) > 0) {
if (pv->value.s[0] != '\\')
sprintf(ctrlstring, "\\%s", pv->value.s);
else
strcpy(ctrlstring, pv->value.s);
if (EQ(ctrlstring, t->lexeme))
strcat(alphastring, pv->next->value.s);
}
break;
case string:
case integer:
case roman:
for (i = 0; t->lexeme[i]; i++) {
add = TRUE;
for (pb = stanza->binding; pb; pb = pb->next)
if (EQ(pb->name, "skipchars"))
for (pv = pb->value; pv; pv = pv->next)
if (pv->class == PROFILE_CHARACTER)
if (pv->value.c == t->lexeme[i]) {
add = FALSE;
goto breaktwice1;
}
breaktwice1: if (add)
alphastring[strlen(alphastring) + 1] = '\0', alphastring[strlen(alphastring)] = t->lexeme[i];
}
break;
case comma:
c = ',';
goto insert;
case obrace:
c = '{';
goto insert;
case cbrace:
c = '}';
insert: add = TRUE;
for (pb = stanza->binding; pb; pb = pb->next)
if (EQ(pb->name, "skipchars"))
for (pv = pb->value; pv; pv = pv->next)
if (pv->class == PROFILE_CHARACTER)
if (pv->value.c == c) {
add = FALSE;
goto breaktwice2;
}
breaktwice2: if (add)
alphastring[strlen(alphastring) + 1] = '\0', alphastring[strlen(alphastring)] = c;
break;
}
return alphastring;
}
}
/* Finds an entry in a table. Returns NULL if not found. */
struct IndexEntry *findentry(table, noentries, string)
struct IndexEntry *table;
int noentries;
char *string;
{
int i;
if (noentries <= 0)
return NULL;
for (i = 0; i < noentries; i++)
if (EQ(string, table[i].literal))
return &table[i];
return NULL;
}
/* Returns pointer to page number if found, NULL otherwise */
struct PageNoTable *findpage(pagearray, elements, pageno, aromannum)
struct PageNoTable *pagearray;
int elements;
int pageno;
Boolean aromannum;
{
int i;
if (!pagearray)
return NULL;
for (i = 0; i < elements; i++)
if ((pagearray[i].number == pageno) &&
(pagearray[i].roman == aromannum))
return &pagearray[i];
return NULL;
}
/* Sorts the entries in the structures */
sort(base, numberelements)
struct IndexEntry *base;
int numberelements;
{
int i;
int numericcompare();
int alphacompare();
for (i = 0; i < numberelements; i++) {
if (base[i].pagenos)
qsort(base[i].pagenos, base[i].pagetablecount, sizeof(struct PageNoTable), numericcompare);
if (base[i].subitem)
sort(base[i].subitem, base[i].subitemcount); /* recursion! */
}
qsort(base, numberelements, sizeof(struct IndexEntry), alphacompare);
}
int numericcompare(e1, e2)
struct PageNoTable *e1, *e2;
{
if ((e1->roman == TRUE) && (e2->roman == FALSE))
return -1;
if ((e1->roman == FALSE) && (e2->roman == TRUE))
return 1;
/* else either both roman or both integers */
if (e1->number == e2->number)
return 0;
else if (e1->number < e2->number)
return -1;
else
return 1;
}
int alphacompare(e1, e2)
struct IndexEntry *e1, *e2;
{
char s1[81], s2[81];
strcpy(s1, e1->alphabetic), strcpy(s2, e2->alphabetic);
return(strcmp(string_downshift(s1), string_downshift(s2)));
}
int rmtoi (romanstr)
char *romanstr;
{
register char *p = romanstr;
register int w;
register int prevw = (-1);
register int result = 0;
int romanwt();
while (*p) {
if ((w = romanwt(*p)) == (-1)) {
fprintf(stderr, "illegal char in roman string:'%c'\n", (*p));
return (-1);
} else {
if (prevw > 0) { /* check for subtractive
* notation */
if (w > prevw) { /* e.g., the case "ix" */
result += (w - prevw) - prevw;
} else
result += w;
} else {
result += w;
}
}
prevw = w;
p++;
}
return (result);
}
static int romanwt (c)
register char c;
{
static char romanlett[7] = {'m', 'd', 'c', 'l', 'x', 'v', 'i'};
static int weight[7] = {1000, 500, 100, 50, 10, 5, 1};
register char *pt;
if (isupper(c))
c = tolower(c);
pt = romanlett;
while (*pt) {
if (*pt == c) {
return (weight[(int) (pt - romanlett)]);
} else
pt++;
}
return (-1); /* roman letter not found */
}
/* Used for storing state of previous page number */
struct State {
Boolean roman; /* Roman/arabic */
Boolean range; /* Range or single page number */
Boolean rangecomplete; /* True if there has been an end to the range */
int pagerange[2]; /* 0 element for single page or 0 and 1 for a page range */
} State;
/* Prints out the contents of the state structure */
printstate(s, itemrep, item, comma)
struct State s;
char *itemrep; /* \item, \subitem, \subsubitem, etc. */
char *item; /* Actual name of item */
Boolean comma; /* Whether to print out a comma or a newline */
{
if (s.range && !s.rangecomplete) {
fprintf(stderr, "%s: file %s, %s %s ends with a range\n", Whoami, IdxFileName, itemrep, item);
ExitStatus = FAIL;
}
if (!s.range) {
if (s.roman)
fprintf(OutputFile, "{\\romannumeral %d}", s.pagerange[0]);
else
fprintf(OutputFile, "%d", s.pagerange[0]);
} else
if (s.pagerange[0] == s.pagerange[1] - 1) {
if (s.roman)
fprintf(OutputFile, "{\\romannumeral %d}, {\\romannumeral %d}", s.pagerange[0], s.pagerange[1]);
else
fprintf(OutputFile, "%d, %d", s.pagerange[0], s.pagerange[1]);
} else {
if (s.roman)
fprintf(OutputFile, "{\\romannumeral %d}--{\\romannumeral %d}", s.pagerange[0], s.pagerange[1]);
else
fprintf(OutputFile, "%d--%d", s.pagerange[0], s.pagerange[1]);
}
if (comma)
fprintf(OutputFile, ", ");
else
fprintf(OutputFile, "\n");
}
/* Prints out the index entries.
Action Table
cur pg--->|| 1. !range | 2. !range | 3. range | 4. range
prev pg || roman | !roman | roman | !roman
===V======||============================|============================|============================|=============================
1. none ||(1,1) |(1,2) |(1,3) |(1,4)
||set roman TRUE |set roman FALSE |set roman TRUE |set roman FALSE
||set range FALSE |set range FALSE |set range TRUE |set range TRUE
||set page number |set page number |set rangecomplete FALSE |set rangecomplete FALSE
|| | |set start page=end page |set start page=end page
----------||----------------------------|----------------------------|----------------------------|-----------------------------
2. !range ||(2,1) |(2,2) |(2,3) |(2,4)
roman ||if prev pg+1=cur pg&&there |print out prev pg |if prev pg+1=cur pg&&there |print out previous page
||is a next pg&&next pg-1=cur |set roman FALSE |is a next pg&&next pg is |set roman FALSE
||pg&&next pg is roman, |set range FALSE |roman, |set range TRUE
|| make a range with |set page number | make a range with |set rangecomplete FALSE
|| rangecomplete set to next | | rangecomplete FALSE |set start pg=end pg
|| pg and skip over next pg | |else |
||else | | print out previous page |
|| print out prev pg | | set roman TRUE |
|| set roman TRUE | | set range TRUE |
|| set range FALSE | | set rangecomplete FALSE |
|| set page number | | set start pg=end pg |
----------||----------------------------|----------------------------|----------------------------|-----------------------------
3. !range ||(3,1) |(3,2) |(3,3) |(3,4)
!roman ||cannot happen |if prev pg+1=cur pg&&there |cannot happen |if prev pg+1=cur pg&&there
|| |is a next pg&&next pg-1= | |is a next pg
|| |cur pg, | | make a range with
|| | make a range with | | rangecomplete FALSE
|| | rangecomplete set to next | |else
|| | pg and skip over next pg | | print out prev pg
|| |else | | set roman FALSE
|| | print out prev pg | | set range TRUE
|| | set roman FALSE | | set rangecomplete FALSE
|| | set range FALSE | |
|| | set page number | |
----------||----------------------------|----------------------------|----------------------------|-----------------------------
4. range ||(4,1) |(4,2) |(4,3) |(4,4)
roman ||if prev pg rangecomplete |write out prev pg |if range !complete || last |write out prev pg
|| if prev pg+1=cur pg |set roman FALSE |pg of prev range+1=this pg |set roman FALSE
|| adjust new end pg |set range FALSE | set range !complete |set range TRUE
|| else |set page number |else |set rangecomplete FALSE
|| write out prev pg | | print out prev pg |set start pg=end pg
|| set roman TRUE | | set roman TRUE |
|| set range FALSE | | set range TRUE |
|| endif | | set rangecomplete FALSE |
||else | | set start pg=end pg |
|| set prev pg rangecomplete | | |
|| set end pg | | |
----------||----------------------------|----------------------------|----------------------------|-----------------------------
5. range ||(5,1) |(5,2) |(5,3) |(5,4)
!roman ||cannot happen |if prev pg rangecomplete |cannot happen |if range !complete or last pg
|| | if prev pg+1=cur pg | |of prev range+1=this pg,
|| | adjust new end pg | | set range !complete
|| | else | |else
|| | write out prev pg | | print out prev range
|| | set roman FALSE | | set roman FALSE
|| | set range FALSE | | set range TRUE
|| | endif | | set rangecomplete FALSE
|| |else | | set start pg=end pg
|| | set prev pg rangecomplete | |
|| | set end pg | |
----------||----------------------------|----------------------------|----------------------------|-----------------------------
*/
printindexentries(base, noelements, level)
struct IndexEntry *base;
int noelements;
int level;
{
int i, j;
Boolean prevoutput = FALSE;
char c;
char letter = '\0';
if (level > ITEMDEPTH)
return;
for (i = 0; i < noelements; i++) {
if (level == 1)
if (strlen(base[i].alphabetic) > 0)
if (isalpha(base[i].alphabetic[0])) {
if (isupper(c = base[i].alphabetic[0]))
c = tolower(c);
if (!letter) {
if (Label) {
fprintf(OutputFile, "\\indexspace\n");
fprintf(OutputFile, "\\largeletter{%c}\n", c);
} else if (prevoutput)
fprintf(OutputFile, "\\indexspace\n");
} else if (letter != c) {
fprintf(OutputFile, "\\indexspace\n");
if (Label)
fprintf(OutputFile, "\\largeletter{%c}\n", c);
}
letter = c;
}
prevoutput = TRUE;
for (j = 1; j < level; j++)
fprintf(OutputFile, " ");
fprintf(OutputFile, "%s %s ", ItemRep[level - 1], base[i].literal);
j = 0;
if (base[i].pagenos)
for (j = 0; j < base[i].pagetablecount; j++) {
if (j == 0)
if (!base[i].pagenos[j].range)
if (base[i].pagenos[j].roman) {
/* (1,1) */
State.roman = TRUE;
State.range = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
} else {
/* (1,2) */
State.roman = State.range = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
else
if (base[i].pagenos[j].roman) {
/* (1,3) */
State.roman = State.range = TRUE;
State.rangecomplete = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
} else {
/* (1,4) */
State.roman = State.rangecomplete = FALSE;
State.range = TRUE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
else if (!State.range)
if (State.roman)
if (!base[i].pagenos[j].range)
if (base[i].pagenos[j].roman) {
/* (2,1) */
if (State.pagerange[0] + 1 == base[i].pagenos[j].number && j < base[i].pagetablecount - 1 &&
base[i].pagenos[j].number == base[i].pagenos[j+1].number - 1 && base[i].pagenos[j+1].roman) {
State.roman = State.range = TRUE;
State.rangecomplete = ! base[i].pagenos[j+1].range;
State.pagerange[1] = base[i].pagenos[j+1].number;
j++;
} else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = TRUE;
State.range = FALSE;
State.pagerange[0] = base[i].pagenos[j].number;
}
} else {
/* (2,2) */
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.range = FALSE;
State.pagerange[0] = base[i].pagenos[j].number;
}
else
if (base[i].pagenos[j].roman) {
/* (2,3) */
if (State.pagerange[0] + 1 == base[i].pagenos[j].number && j < base[i].pagetablecount - 1 &&
base[i].pagenos[j+1].roman) {
State.roman = State.range = TRUE;
State.rangecomplete = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j-1].number;
} else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.range = TRUE;
State.rangecomplete = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
} else {
/* (2,4) */
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.rangecomplete = FALSE;
State.range = TRUE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
else
if (!base[i].pagenos[j].range)
if (base[i].pagenos[j].roman)
/* (3,1) */ ;
else {
/* (3,2) */
if (State.pagerange[0]+1 == base[i].pagenos[j].number && j < base[i].pagetablecount-1 &&
base[i].pagenos[j].number == base[i].pagenos[j+1].number-1) {
State.roman = FALSE;
State.range = TRUE;
State.rangecomplete = ! base[i].pagenos[j+1].range;
State.pagerange[1] = base[i].pagenos[j+1].number;
j++;
} else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.range = FALSE;
State.pagerange[0] = base[i].pagenos[j].number;
}
}
else
if (base[i].pagenos[j].roman)
/* (3,3) */ ;
else {
/* (3,4) */
if (State.pagerange[0]+1 == base[i].pagenos[j].number && j < base[i].pagetablecount-1) {
State.roman = State.rangecomplete = FALSE;
State.range = TRUE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j-1].number;
} else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.range = TRUE;
State.rangecomplete = State.roman = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
}
else
if (State.roman)
if (!base[i].pagenos[j].range)
if (base[i].pagenos[j].roman) {
/* (4,1) */
if (State.rangecomplete)
if (State.pagerange[1]+1 == base[i].pagenos[j].number)
State.pagerange[1]++;
else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = TRUE;
State.range = FALSE;
State.pagerange[0] = base[i].pagenos[j].number;
}
else {
State.rangecomplete = TRUE;
State.pagerange[1] = base[i].pagenos[j].number;
}
} else {
/* (4,2) */
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.range = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
else
if (base[i].pagenos[j].roman) {
/* (4,3) */
if (!State.rangecomplete || State.pagerange[1]+1 == base[i].pagenos[j].number)
State.rangecomplete = FALSE;
else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.range = TRUE;
State.rangecomplete = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
} else {
/* (4,4) */
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.rangecomplete = FALSE;
State.range = TRUE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
else
if (!base[i].pagenos[j].range)
if (base[i].pagenos[j].roman)
/* (5,1) */ ;
else {
/* (5,2) */
if (State.rangecomplete)
if (State.pagerange[1]+1 == base[i].pagenos[j].number)
State.pagerange[1]++;
else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.range = FALSE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
else {
State.rangecomplete = TRUE;
State.pagerange[1] = base[i].pagenos[j].number;
}
}
else
if (base[i].pagenos[j].roman)
/* (5,3) */ ;
else {
if (!State.rangecomplete || State.pagerange[1]+1 == base[i].pagenos[j].number)
/* (5,4) */
State.rangecomplete = FALSE;
else {
printstate(State, ItemRep[level-1], base[i].literal, TRUE);
State.roman = State.rangecomplete = FALSE;
State.range = TRUE;
State.pagerange[0] = State.pagerange[1] = base[i].pagenos[j].number;
}
}
}
if (j > 0)
printstate(State, ItemRep[level-1], base[i].literal, FALSE);
else
fprintf(OutputFile, "\n");
if (base[i].subitem)
printindexentries(base[i].subitem, base[i].subitemcount, level+1); /* recursion */
}
}