#
#define EXTERN extern
# include "../mcons.h"
# include "../ccmn.h"
/*int	mbuf[1024];	/*INSTR*/
/*int	tbuf[36];	/*INSTR*/

int	(*acts[])()	{0,
			&coll,
			&save,
			&out,
			&asym,
			&asw,
			&csym,
			&csw,
			&incl,
			&decl,
			&sk2,
			&sk,
			&tabs,
			&semi
			};

char	*tmp[5]	{"/tmp/crt0a",
		"/tmp/crt1a",
		"/tmp/crt2a",
		"/tmp/crt3a",
		"/tmp/crt4a"
		};

char	*ignonl	"/usr/lib/aign";
char	*gtab	"/usr/lib/atab";

main(argc,argv)
	char	*argv[];
{
	auto	i,j,tm1,tm2,tm3;
	char	*fn,*av[8];
/*	extern	etext;	/*INSTR*/

/*	monitor(&main,&etext,&mbuf,1024);	/*INSTR*/
	if(argc < 2) {
		printf("Usage: cref [-aceilosux] file1 ...\n");
		exit();
	}

	lbuf[4] = '\t';
	if(*argv[1] == '-') {
		j = flags(argv);
		argv =+ j;
		argc =- j;
	}

	init();

	i = 0;
	while(++i < argc) {
		curs[0] = '_';
		curs[1] = '\t';
		curs[4] = '\t';
		cursl = 2;

		if(fopen(argv[i],ibuf1) < 0) {
			printf("Can't open %s\n",argv[i]);
			dexit();
		}
		ibuf = ibuf1;

		curf[0] = '\t';
		curfl = 1;
		while((curf[curfl] = *argv[i]++) != 0 && curfl <= 8)
			if(curf[curfl++] == '/')	curfl = 1;

		curf[curfl++] = '\t';
		if(curfl == 10)	curf[9] = -1;
/*		printf("%s %d\n",curf,curfl);/*DEBUG*/

		lno = 1;

		driver();

		close(file);
	}
	for(j = 0; j < 4;) {
		flsh(j,0);
		close(tp[j++]);
	}

/*	monitor(0);	/*INSTR*/
/*	dexit();	/*INSTR*/

/*	times(tbuf);	/*INSTR*/
/*	tm1 = tbuf[15]/6;	/*INSTR*/
/*	tm2 = tbuf[19]/6;	/*INSTR*/
/*	tm3 = tbuf[23]/6;	/*INSTR*/
/*	printf("Prep: %d  %d  %d\n",tm1,tm2,tm3);	/*INSTR*/

	if(utmp)	exit();
	fn = "/bin/sort";
	av[0] = "sort";
	av[1] = "-a";
	av[3] = "-o";
	av[5] = 0;
	for(i = 0; i < 4; i++) {
		av[4] = av[2] = tmp[i];
		callsys(fn,av);
		if(utmp)	break;
	}

/*	times(tbuf);	/*INSTR*/
/*	tm1 = tbuf[27]/6;	/*INSTR*/
/*	tm2 = tbuf[31]/6;	/*INSTR*/
/*	tm3 = tbuf[35]/6;	/*INSTR*/
/*	printf("Sort: %d  %d  %d\n",tm1,tm2,tm3);	/*INSTR*/

	if(usw) {
		fn = "/usr/bin/upost";
		av[0] = "upost";
		i = 0;
	} else {
		fn = "/usr/bin/crpost";
		av[0] = "crpost";
		av[1] = cross? "-4x": "-3";
		i = 1;
	}
	j = -1;
	while(++j < 4) {
		av[++i] = tmp[j];
		if(utmp)	break;
	}
	av[++i] = 0;

	callsys(fn,av);

/*	times(tbuf);	/*INSTR*/
/*	tm1 = tbuf[27]/6 - tm1;	/*INSTR*/
/*	tm2 = tbuf[31]/6 - tm2;	/*INSTR*/
/*	tm3 = tbuf[35]/6 - tm3;	/*INSTR*/
/*	printf("Post: %d  %d  %d\n",tm1,tm2,tm3);	/*INSTR*/

	dexit();
}

driver()
{
	auto	p;

top:
	l = -1;
	while((c = line[++l] = getc(ibuf)) != -1) {
		if(l >= 131) {
			printf("Line too long: %d %s\n",lno,curf);
			dexit();
		}

		if(c & 0200) {
			printf("Illegal character: %o line %d\n",c,lno);
			dexit();
		}

		if(fl) {
			if((*flag[fl])())
				continue;
		}

/*printf("cs = %d cc = %c ca = %d\n",cs,c,tab[cs].cl[c]);	/*DEBUG*/

		if(p = tab[cs].cl[c])
			(*acts[p])();
		continue;
	}
	if(ibuf == ibuf1)	return;
	ibuf = ibuf1;
	goto top;

}

init()
{
	int	b[3];
	auto	fi,i;
	extern	coll(),save(),out(),asym(),asw(),csym(),csw();
	extern	incl(),decl(),sk(),sk2();
	extern	dexit();

	ibuf1 = &ib1;
	ibuf2 = &ib2;

	xtab.hptr = &xpsp;
	xtab.symt = &xssp;
	xtab.hsiz = PTRX;
	xtab.ssiz = CHARX;
	xtab.nsym = 0;
	xtab.curb = 1;

	itab.hptr = &ipsp;
	itab.symt = &issp;
	itab.hsiz = PTRI;
	itab.ssiz = CHARI;
	itab.nsym = 0;
	itab.curb = 1;

	if((fi = open(gtab,0)) < 0) {
		printf("Cannot open grammar table; see lem\n");
		dexit();
	}

	i = -1;
	while(++i < NUMS)
		if(read(fi,tab[i].cl,512) < 512) {
			printf("Bad grammar table.\n");
			dexit();
		}

	close(fi);


	if((fi = open(ignonl,0)) < 0) {
		printf("Cannot open ignore/only file: %s\n",ignonl);
		dexit();
	}
	if((read(fi,b,6) == 6) && (b[0] == 0100200)) {
		if(read(fi,itab.hptr,b[1]) < b[1]) {
			printf("Cannot read ignore/only file: %s\n",ignonl);
			dexit();
		}
		if(read(fi,itab.symt,b[2]) < b[2]) {
			printf("Cannot read ignore/only file: %s\n",ignonl);
			dexit();
		}
		close(fi);
	} else {
		close(fi);
		compile();
	}

	if((signal(1,1) & 1) == 0)	signal(1,&dexit);
	if((signal(2,1) & 1) == 0)	signal(2,&dexit);
	if((signal(3,1) & 1) == 0)	signal(3,&dexit);
/*	signal(4,&dexit);
	signal(5,&dexit);
	signal(6,&dexit);
	signal(7,&dexit);
	signal(8,&dexit);
	signal(10,&dexit);
	signal(11,&dexit);
	signal(12,&dexit);
*/
	if(utmp == 0) {
		while((tp[4] = creat(tmp[4],0)) < 0)
			tmp[4][9]++;
		close(tp[4]);
		tmp[0][9] = tmp[4][9];
		tmp[1][9] = tmp[4][9];
		tmp[2][9] = tmp[4][9];
		tmp[3][9] = tmp[4][9];
		tp[0] = creat(tmp[0],CREATC);
		tp[1] = creat(tmp[1],CREATC);
		tp[2] = creat(tmp[2],CREATC);
		tp[3] = creat(tmp[3],CREATC);
	} else {
		if((tp[0] = creat(utmp,CREATC)) < 0) {
		printf("Can't create user's temp file.\n");
			exit();
		}
	}

	return;
}

error(a)
{
	printf("Error %d\n",a);
	dexit();
}

dexit()
{
	extern	nflush;

/*	printf("nflush = %d\n",nflush);	/*DEBUG*/
	if(tp[0] > 0 && utmp == 0) {
		unlink(tmp[0]);
		unlink(tmp[1]);
		unlink(tmp[2]);
		unlink(tmp[3]);
		unlink(tmp[4]);
	}
	exit();
}

callsys(f,v)
	char	f[],*v[];
{
	int	t,status,i;

	if((t = fork()) == 0) {
		execv(f,v);
		printf("Can't find %s\n",f);
		exit(1);
	} else {
		if(t == -1) {
			printf("Try again\n");
			return(1);
		}
	}

	while(t != wait(&status));
/*	printf("Status = %o, %s\n",status,f);	/*DEBUG*/
	if((t = (status & 0377)) != 0) {
		if(t != 2) {
			printf("Fatal error in %s\n",f);
			printf("t = %d\n",t);
		}
		dexit();
	}
	return((status>>8) & 0377);
}

flags(argv)
	char	*argv[];
{
	int	j,xx;
	char	*ap;

	j = 1;
	ap = argv[1];
	while(*++ap != '\0') {
		switch(*ap) {

			default:
				printf("Unrecognized flag: %c\n",*ap);
				dexit();

			case '1':	/* Symbol first */
				order = 1;
				continue;

			case '2':	/* Current file first */
				order = 2;
				continue;

			case '3':	/* Current symbol first */
				order = 3;
				continue;

			case 'a':	/* Assembler */
				cflag = 0;
				continue;

			case 'c':	/* C */
				gtab = "/usr/lib/ctab";
				if(!xx)
					ignonl = "/usr/lib/cign";
				cflag = 1;
				continue;

			case 'e':	/* English */
				gtab = "/usr/lib/etab";
				if(!xx)
					ignonl = "/usr/lib/eign";
				continue;

			case 'i':	/* Ignore file */
				if(!xx) {
					xx = 1;
					only = 0;
					ignonl = argv[++j];
				}
				continue;

			case 'l':	/* Line numbers in col. 3 */
				cross = 0;
				continue;

			case 'o':	/* Only file */
				if(!xx) {
					xx = 1;
					only = 1;
					ignonl = argv[++j];
				}
				continue;

			case 's':	/* Symbols in col. 3 */
				cross = 1;
				continue;

			case 't':
				utmp = argv[++j];
				tmp[0] = argv[j];
				continue;

			case 'u':	/* Unique symbols only */
				usw = 1;
				continue;

			case 'x':	/* C externals */
				xsw = 1;
				gtab = "/usr/lib/ctab";
				if(!xx)
					ignonl = "/usr/lib/cign";
				cflag = 1;
				continue;
		}
	}
	return(j);
}


compile()
{
	char	buf[40],*b;
	int	i,v;

	fopen(ignonl,ibuf1);

	b = buf - 1;
	while((*++b = getc(ibuf1)) != -1) {
		if(*b == '\n') {
			*b = '\0';
			search(buf,b - buf,&itab,1);
			b = buf - 1;
		} else {
			if(*b == '\t') {
				v = 0;
				while((i = getc(ibuf1)) != -1) {
					if(i == '\n')	break;
					v = v*10 + (i - '0');
				}
				search(buf,b - buf,&itab,v);
				b = buf - 1;
			} else {
				if((b - buf) > 39) {
					printf("Ignore/only symbol too long");
					dexit();
				}
			}
		}
	}
	close(ibuf1);
	return;
}
