/*indexmaker

Transforms a file produced by the Latex \makeindex command into a file
in theindex environment. The program assumes its input file has been
presorted (see below).

Within an \indexentry, items and subitems are separated by the symbol
:  (colon).  Thus in:
\indexentry{gnu:su}{22}
gnu is the item and su is the subitem.  This separator symbol can be
easily changed.  Change the value assigned to SEP in the preamble to
the program.  Subsubitems are not supported.

Takes lines in the form:
\indexentry{gnu}{3}
and transforms them into
\item gnu, 3
Or lines of the form
\indexentry{gnu}{3}
\indexentry{gnu:su}{22}
and transforms them into
\item gnu, 3
     \subitem su, 22

Items and subitems with the same names and different page references
such as:
\indexentry{gnu}{4}
\indexentry{gnu}{5}
transform into
\item gnu, 4, 5

The num field can be null for items:
\indexentry{gnu}{}
transforms into
\item gnu

An item can have no main entry:
\indexentry{gnu}{12}
\indexentry{gnu1:kk}{3}
transforms into
\item gnu, 12
\item gnu1
     \subitem kk, 3

The output file begins with
\begin{theindex}
and ends with the entry
\end{theindex}

The program adds the entry
\indexspace
between entries that begin with different letters (upper and lower
case versions of the same letter are not different letters).

The program assumes the input is in the correct format except that it
does not check before the first {.
 
Before running this program, sort the input file with: 
sort -t{ +0 -2df  +2nu
so that text is sorted alphabetically, page numbers are sorted
numerically, and duplicate entries are eliminated.

Shells are available to perform the sorting and call this program.
The shells are:
makeindex f1 > f2 
for the sun and 
sgimakeindex f1 > f2 
for the sgi.  f1 is the name of the file containing the \indexentries;
f2 is the file into which the output is to be put.

Philip M. Lewis -- January 1991

*/

#include <stdio.h>
#include <ctype.h>
#define MAXLENGTH 256
#define SEP ':'


int makelc (char ii) {

if ((ii >=65) && (ii <=90))
	ii += 32;

return ii;

}




main() {


char item [MAXLENGTH];
char subitem [MAXLENGTH];
char pages [MAXLENGTH];
int c;
char last = ' ';
int itemptr = 0;
int subitemptr = 0;
int pagesptr = 0;
char titem [MAXLENGTH];
char tsubitem [MAXLENGTH];
char tpages [MAXLENGTH];
int titemptr = 0;
int tsubitemptr = 0;
int tpagesptr = 0;
int st = 1;
int i;
int flag = 0;
int skipnum = 0;
//printf("\\documentstyle{book}\n");
//printf("\\begin{document}\n");
printf("\\begin{theindex}\n");

while ((c=getchar()) != EOF) {
	switch (st) {
		case 1 : goto state1;
		case 2 : goto state2;
		case 3 : goto state3;
		case 4 : goto state4;
		case 5 : goto state5;
		case 6 : goto state6;
		case 7 : goto state7;
		case 8 : goto state8;
		case 21: goto state21;
		case 22: goto state22;
		case 23: goto state23;
		case 24: goto state24;
		case 31: goto state31;
		case 32: goto state32;
		case 33: goto state33;
		case 34: goto state34;

	};

state1:   /* looking for item field */
	switch (c) {
		case '{':
			st = 2 ;
			break;	
		default:	
			st = 1 ;
		
	};

	goto lend2;

state2:  /* accumulating item field */

	switch (c) {
		case SEP:
			st = 3;
			break;	
		case '}':
			st = 4;	
			break;
		case '(':    /*looking for (see */
			titem[titemptr++]=c;	
			st = 21;
			break;
			
		default:
			titem[titemptr++]=c;	
			st = 2;
	};
	goto lend2;

state21:  /* accumulating item field */

	switch (c) {
		case SEP:
			st = 3;
			break;	
		case '}':
			st = 4;	
			break;	

		case 's':
			titem[titemptr++]=c;	
			st = 22;
			break;
		
		default:
			titem[titemptr++]=c;	
			st = 2;
	};
	goto lend2;

state22:  /* accumulating item field */

	switch (c) {
		case SEP:
			st = 3;
			break;	
		case '}':
			st = 4;	
			break;
		case 'e':
			titem[titemptr++]=c;	
			st = 23;
			break;
			
		default:
			titem[titemptr++]=c;	
			st = 2;
	};
	goto lend2;

state23:  /* accumulating item field */

	switch (c) {
		case SEP:
			st = 3;
			break;	
		case '}':
			st = 4;	
			break;	
		case 'e':
			titem[titemptr++]=c;	
			st = 24;
			break;
		
		default:
			titem[titemptr++]=c;	
			st = 2;
	};
	goto lend2;

state24:  /* accumulating item field */

	switch (c) {
		case SEP:
			st = 3;
			break;	
		case '}':
			st = 4;	
			break;
		case ' ':
			titem[titemptr++]=c;	
			st = 24;
			skipnum = 1;
			break;
			
		default:
			titem[titemptr++]=c;	
			st = 2;
	};
	goto lend2;


state3: /*accumulating subitem field */

	switch (c) {
		case '}':
			st = 4;
			break;
		case '(': /*looking for (see*/
			tsubitem[tsubitemptr++]=c;	
			st = 31;
			break;
						
		default:
			tsubitem[tsubitemptr++]=c;	
			st = 3;
	};
	goto lend2;

state31: /*accumulating subitem field */

	switch (c) {
		case '}':
			st = 4;
			break;
		case 's':
			tsubitem[tsubitemptr++]=c;	
			st = 32;
			break;
						
		default:
			tsubitem[tsubitemptr++]=c;	
			st = 3;
	};
	goto lend2;

state32: /*accumulating subitem field */

	switch (c) {
		case '}':
			st = 4;
			break;
		case 'e':
			tsubitem[tsubitemptr++]=c;	
			st = 33;
			break;
						
		default:
			tsubitem[tsubitemptr++]=c;	
			st = 3;
	};
	goto lend2;

state33: /*accumulating subitem field */

	switch (c) {
		case '}':
			st = 4;
			break;
		case 'e':
			tsubitem[tsubitemptr++]=c;	
			st = 34;
			break;
						
		default:
			tsubitem[tsubitemptr++]=c;	
			st = 3;
	};
	goto lend2;

state34: /*accumulating subitem field */

	switch (c) {
		case '}':
			st = 4;
			break;
		case ' ':
			tsubitem[tsubitemptr++]=c;	
			st = 31;
			skipnum = 1;
			break;
						
		default:
			tsubitem[tsubitemptr++]=c;	
			st = 3;
	};
	goto lend2;


state4: /*looking for page field */
	
	switch (c) {
		case '{':
			st = 5;	
			break;		
		default:
			st = 4;		
	};
	goto lend2;

state5: /*accumulating page field*/
	
	switch (c) {
		case '}':		
			st = 6;	
			break;		
		default:
			tpages[tpagesptr++]=c;	
			st = 5;
	};
	goto lend2;

state6: /*skip to end of line */

	switch (c) {
		case '\n':		
			goto state7;		
		default:
			st = 6;
	};
	goto lend2;

state7: /*completed line */

	if (skipnum == 1) {
		skipnum = 0;
		tpagesptr = 0;
	}
			
	if (itemptr != titemptr) {
		if (tsubitemptr != 0) flag = 1;
		goto state8;
	}
	i=0;
	while (i < titemptr) {
		if (item[i] != titem [i]) {
			if (tsubitemptr != 0) flag = 1;
			goto state8; /*new item*/
		}
		i++;
	}
	if (subitemptr != tsubitemptr) goto state8;	
	i=0;
	while (i < tsubitemptr) {
		if (subitem[i] != tsubitem [i]) 

			goto state8; /*new subitem */
		i++;
	}
	if (pagesptr != 0) {
		pages[pagesptr++]=',';
		pages[pagesptr++]=' ';
	}
	i=0;
	while (i < tpagesptr) {
		pages[pagesptr++] = tpages[i];
		i++;
	}
	titemptr =0;
	tsubitemptr = 0;
	tpagesptr = 0;

	st = 1;
	goto lend2;

state8: /*new item8 */

	if (itemptr != 0) {
		if (subitemptr ==  0) {
			if ((last != ' ') && (makelc(last) != makelc(item[0])))
				printf ("\\indexspace\n");		

			last = item[0];
			printf("\\item ");
			i=0;
			while (i < itemptr) {
				putchar(item[i]); 
				i++;
			}
		}
	

		else {
			printf("     \\subitem ");
			i=0;
			while (i < subitemptr) {
				putchar(subitem[i]); 
				i++;
			}
		}
	}	
	if (pagesptr != 0) printf(", ");
	i=0;
	while (i < pagesptr) {
		putchar(pages[i]); 
		i++;
	}
	putchar('\n');

	i=0;
	while (i < titemptr) {
		item[i] =titem[i];
		i++;
	}

	i=0;
	while (i < tsubitemptr) {
		subitem[i] =tsubitem[i];
		i++;
	}
	
	i=0;
	while (i < tpagesptr) {
		pages[i] =tpages[i];
		i++;
	}

	itemptr = titemptr;
	subitemptr = tsubitemptr;
	pagesptr = tpagesptr;
	titemptr =0;
	tsubitemptr = 0;
	tpagesptr = 0;

	if (flag == 1){
		if ((last != ' ') && (makelc(last) != makelc(item[0])))
			printf ("\\indexspace\n");			
		last = item[0];
		printf("\\item ");
		i = 0;
		while (i < itemptr) {
			putchar(item[i]);
			i++;
		}
	if (itemptr != 0) putchar('\n');
	flag = 0;
	}
		st = 1;
lend2:;

}

lend:
	if (itemptr != 0) {
		if (subitemptr ==  0) {
			if ((last != ' ') && (makelc(last) != makelc(item[0])))
				printf ("\\indexspace\n");
			
			last = item[0];
			printf("\\item ");
			i=0;
			while (i < itemptr)  {
				putchar(item[i]); 
				i++;
			}
		}

		else {
			printf("     \\subitem ");
			i=0;
			while (i < subitemptr) { 
				putchar(subitem[i]); 
				i++;
			}
		}
	}
	if (pagesptr != 0) printf(", ");

	i=0;
	while (i < pagesptr) {
		putchar(pages[i]); 
		i++;
	}
	putchar('\n');

	i=0;
	while (i < titemptr) {
		item[i] =titem[i];
		i++;
	}

	i=0;
	while (i < tsubitemptr) {
		subitem[i] =tsubitem[i];
		i++;
	}
	
	i=0;
	while (i < tpagesptr) {
		pages[i] =tpages[i];
		i++;
	}

	itemptr = titemptr;
	subitemptr = tsubitemptr;
	pagesptr = tpagesptr;
	titemptr =0;
	tsubitemptr = 0;
	tpagesptr = 0;

	if (itemptr != 0) {
		if (subitemptr ==  0) {
			if ((last != ' ') && (makelc(last) != makelc(item[0]))) {
				printf ("\\indexspace\n");
			}
			last = item[0];
			printf("\\item ");
			i=0;
			while (i < itemptr) {
				putchar(item[i]); 
				i++;
			}
		}

		else {
			printf("     \\subitem ");
			i=0;
			while (i < subitemptr)  {
				putchar(subitem[i]); 
				i++;
			}
		}
	}
	if (pagesptr != 0) printf(", ");
	
	i=0;
	while (i < pagesptr) {
		putchar(pages[i]); 
		i++;
	}
	putchar('\n');

	printf("\\end{theindex}\n");
//	printf("\\end{document}\n");
}




