#
#include "mkconf.h"
#
/*
 *	UNIX SUPPORT GROUP MODIFICATION ?.??
 */
/*
 * Revised Jan 1977 by TMR
 */
#define EOT	0
#define CONTINUE	1
#define MAXLOW	01000
#define LOW	0400
#define EGOOD	0
#define EBAD	1

char	*z;
struct tab *vect[118];
int flagf, flagb, flagm, flags;
int	nkl;
int	lastc	0;
int	lowend	LOW;		/* End of low core */
char	*dev;

int	log;
main(argc,argv)
int	argc;
char	**argv;
{
	register struct tab *p;
	register struct ord *q;
	int	*y;
	int i, n, ev,*s;
	char	*ap;
	struct tab *search();
	extern fout;

	argv++;
	argc--;
	flagf = flagb = flags = 1;
	if(argc&&(argv[0][0] == '-')){
		ap = argv[0];
		while(*++ap){
			switch(*ap){
			default:
				printf("%c: Not an option\n",*ap);
				exit();
			case 'a':
				if(digit(argv[1][0])){
					lowend = atoi(argv[1],8);
					if((lowend < 0)||(lowend > 01000)){
						printf("low core ends at 0777!\n");
						exit(1);
					}
					printf("End of low core - %o\n",lowend);
				}else{
					printf("%s: not an address!\n",argv[1]);
					exit(1);
				}
				continue;
			case 'n':
				flags = 0;
				continue;
			case 't':
				flags = 2;
				continue;
			}
		}
	}
	dev = "console";
	set(p = lookup("console"));
	install(p,060,p->size);

	dev = "clock";
	set(p = lookup("clock"));
	install(p,0100,p->size);
	install(p,0104,p->size);
	dev = "mem";
	set(p = lookup("mem"));

	for(s= &vect[30];s<&vect[33];s++)
		*s = RESERVED;
	while(input());

/*
 * pass1 -- create interrupt vectors
 */
	nkl = 0;
	flush();
	if((fout = creat("l.s", 0666)) <0){
		fout = 0;
		printf("Can't create l.s\n");
		flush();
		exit(1);
	}
	flush();
	if(memflg == -1)
		puke(stra40);
	else
		puke(stra);
	low();
	if(flagb)
		puke(strb);
	puke(strd);
	for(p=table; p->name; p++){
		if(p->count != 0 && p->key & INTR){
			printf("\n%s%s", p->codeb, p->codec);
		}
	}
	flush();
	if(flags == 1)
		printf("\n.globl\t_stray\nstray:\tjsr\tr0,call; _stray\n");
	printf("\n");
	flush();
	close(fout);

/*
 * pass 2 -- create configuration table
 */

	init();
	z = search(&std);

	if((fout = creat("c.c", 0666))<0){
		fout = 0;
		printf("Can't create c.c\n");
		flush();
		exit(1);
	}
	puke(stre);
	i = 0;
	for(q= &border[0] ; q->name ; q++){
		printf("/*%2.2d*/",i++);
		if(q->flag)
			printf("%s\n", q->addr->coded);
		else
			printf("%s\n",z->coded);
	}
	puke(strf);
	i = 0;
	for(q = &corder[0] ; q->name ; q++){
		printf("/*%2.2d*/",i++);
		if(q->flag)
			printf("%s\n", q->addr->codee);
		else
			printf("%s\n",z->codee);
	}
	puke(strg);
	i = 0;
	for(q = &dorder[0] ; q->name ; q++){
		printf("/*%2.2d*/",i++);
		if(q->flag)
			printf("%s\n", q->addr->codef);
		else
			printf("%s\n",z->codef);
	}
	puke(strh);
	printf("\nint\trootdev\t{(%d<<8)|%d};\n",rootdev.hibyte&0377,
		rootdev.lobyte&0377);
	printf("int\tswapdev\t{(%d<<8)|%d};\n",swapdev.hibyte&0377,
		swapdev.lobyte&0377);
	printf("int\tswplo\t%d;\n",swplo);
	printf("int\tnswap\t%d;\n",nswap);
	printf("\n\n");
	puke(stri);
	if(log){
		printf("int\t*errtabs[]{\n");
		for(q= &border[0];q->name;q++){
			if(q->flag)
				printf("\t%s\n",q->addr->codeg);
		}
		printf("\t0};\n");
	}
	flush();
	close(fout);
	fout = 0;
	if(lowend != LOW){
		printf("End of low core %o\n",lowend);
	}
	flush();
	exit(EGOOD);
}

/*
 * Print string
 */
puke(s)
char **s;
{
	char *c;

	while(c = *s++)
		printf("%s\n", c);
}

char	*lp;
char line[100];
char	*arg[4];
/*
 * Read input and build vector array
 */
input()
{
	int	ind,ix;
	register char *p;
	char	*sp;
	register struct tab *q;
	register char c;
	int	n;
	struct ord *o;
	char	*s,*t;
	int	i,count, addr,v,f;


/*	
 *	force initial typing of 40, 45, or 70
 */

	ix = 0;
	for(i=0;i<4;i++){
		arg[i] = 0;
	}


	p = line;
	arg[0] = line;
	ind = 0;
	lastc = ' ';
	while((c=get()) != '\n') {
		if(c == '\0')
			return(EOT);
		if((c == ' ')||(c == '\t')){
			continue;
		}
		sp = p;
		if(alpha(c)){
			do {
				*p++ = c;
				c = get();
			}while(alpha(c)||digit(c));
			*p++ = '\0';
			lastc = c;
			goto sarg;
		}
		if(digit(c)){
			do {
				*p++ = c;
				c = get();
			}while(digit(c));
			*p++ = '\0';
			lastc = c;
			goto sarg;
		}
		goto skip;
	sarg:
		arg[ind++] = sp;
	skip:
		;
	}
	if(p == line)
		return(CONTINUE);
	*p++ = '\0';
	for(;memflg == -2;){
		if(equal("45",arg[0])){
			memflg = 1;
			return(CONTINUE);
		}else
		if(equal("70",arg[0])){
			memflg = 1;
			vect[9] = lookup("parity");
			return(CONTINUE);
		}else
		if(equal("34",arg[0])||equal("40",arg[0])){
			memflg = -1;
			return(CONTINUE);
		}else{
			printf("Which processor? 40? 34? 45? 70?\n");
			return(CONTINUE);
		}
		return(0);
	}
	if(equal("root",arg[0])){
		if((ind == 3)||(ind == 2)){
			;
		}else{
			printf("root: Arg count!\n");
			return(CONTINUE);
		}
		if(lookup(arg[1]) == FALSE){
			printf("root: %s Unknown device?\n",arg[1]);
			return(CONTINUE);
		}
		n = 0;
		if(ind == 3)
			n = atoi(arg[2],10);
		if((n < 0)||(n >=256)){
			printf("root: %s Minor device number out of range\n",arg[2]);
			return(CONTINUE);
		}
		rootdev.lobyte = n;
		i = 0;
		f = 0;
		for(o = &border[0];o->name;o++){
			if(equal(o->name,arg[1])){
				if((o->flag&BLOCK) == 0){
					printf("root: %s Not in Block Device Table\n",
			arg[1]);
					swapdev = SWAPDEV;
					rootdev = ROOTDEV;
					return(CONTINUE);
				}
				f++;
				break;
			}
			i++;
		}
		if(f == 0){
			printf("root: %s Device not in Configuration Table!\n",
				arg[1]);
			return(CONTINUE);
		}
		rootdev.hibyte = i;
		return(CONTINUE);
	}else
	if(equal("swap",arg[0])){
		if((ind == 3)||(ind == 2)){
			;
		}else{
			printf("swap: Arg count!\n");
			return(CONTINUE);
		}
		if(lookup(arg[1]) == FALSE){
			printf("swap: %s Unknown device?\n",arg[1]);
			return(CONTINUE);
		}
		n = 0;
		if(ind == 3)
			n = atoi(arg[2],10);
		if((n < 0)||(n >= 256)){
			printf("swap: %s Minor device number out of range\n",
				arg[2]);
			return(CONTINUE);
		}
		swapdev.lobyte = n;
		i = 0;
		f = 0;
		for(o = &border[0];o->name;o++){
			if(equal(o->name,arg[1])){
				if((o->flag&BLOCK) == 0){
					printf("swap: %s not in Block Device Table\n",
					arg[1]);
					return(CONTINUE);
				}
				f++;
				break;
			}
			i++;
		}
		if(f == 0){
			printf("swap: %s Device not in Configuration Table!\n",
				arg[1]);
			return(CONTINUE);
		}
		swapdev.hibyte = i;
		return(CONTINUE);
	}else
	if(equal("swplo",arg[0])){
		if(ind != 2){
			printf("swplo: Arg count\n");
			return(CONTINUE);
		}
		if(digit(arg[1][0]) == FALSE){
			printf("swplo: %s swap offset?\n",arg[1]);
			return(CONTINUE);
		}
		i = 0;
		if((i = atoi(arg[1],10)) == 0){
			printf("Swap offset cannot be zero!\n");
			return(CONTINUE);
		}
		swplo = i;
		return(CONTINUE);
	}else
	if(equal("nswap",arg[0])){
		if(ind != 2){
			printf("nswap: Arg count\n");
			return(CONTINUE);
		}
		if(digit(arg[1][0]) == FALSE){
			printf("nswap: %s number of swap blocks?\n",arg[1]);
			return(CONTINUE);
		}
		nswap = atoi(arg[1],10);
		return(CONTINUE);
	}else
	if(equal("list",arg[0])){
		list();
		return(CONTINUE);
	}else
	if(equal("location",arg[0])){
		location();
		return(CONTINUE);
	}else
	if(equal("errorlog",arg[0])){
		log++;
		return(CONTINUE);
	}else
	if(equal("q",arg[0])||equal("quit",arg[0])){
		exit(1);
	}
	n = 0;
	ix = 0;
	dev = arg[0];
	if(digit(arg[0][0])){
		dev = arg[1];
		n = atoi(arg[0],10);
		ix++;
	}
	if(n == 0)
		n = 1;
	f = 0;
	for(q=table;q->name;q++){
		if(equal(q->name,dev)){
			f++;
			break;
		}
	}
	if(f == 0){
		printf("%s: Unknown device!\n",dev);
		return(CONTINUE);
	}
	s = arg[ix];
	if(alpha(*s)){
		ix++;
	}
	v = 0;
	t = arg[ix];
	if(digit(*t)){
		v = atoi(arg[ix],8);
		if(v&03){
			printf("Vectors at double word boundary only!\n");
			return(CONTINUE);
		}
	}
	/*
	 * Install device
	 */
	if(q->count < 0) {
		printf("%s: no more, no less\n", dev);
		return(CONTINUE);
	}
	if((q->address < 0300) && (n + q->count > 1)) {
		q->count = 1;
		printf("%s: only one\n", dev);
		return(CONTINUE);
	}
	count = q->count;
	if(q->count < 0)
		count = 0;
	for(i=0;i<n;i++){
		if(v == 0)
			addr = q->address + (i+count) * q->size;
		else
			addr = v + i * q->size;
		if(q->key&EVEN){
			if((addr&07) != 0){
				printf("Even address required for %s!\n",dev);
				printf("Specify %o instead\n",
					(addr+7)&0177770);
				return(CONTINUE);
			}
		}
		if(install(q,addr,q->size) == FALSE){
			return(CONTINUE);
		}
	}
	q->count =+ n;
	set(q);
	return(CONTINUE);
}

/*
 * Compare two strings
 */
equal(p, q)
char *p, *q;
{
	register char *a, *b;

	a = p;
	b = q;
	while(*a++ == *b)
		if(*b++ == '\0')
			return(TRUE);
	return(FALSE);
}
/*
 * Initialize arrays
 */
init()
{
	register struct	ord *p,*q;

	for(p = &border[0] ; p->name ; p++)
		p->addr = search(p);

	for(p = &corder[0] ; p->name ; p++)
		p->addr = search(p);
	for(p = &dorder[0] ; p->name ; p++)
		p->addr = search(p);



}
/*
 * Search a config table for device 
 */
struct	tab	*search(p)
struct	ord	*p;
{
	register struct tab *q;
	for(q = &table[0] ; q->name ; q++)
		if(equal(p->name,q->name))
			return(q);
	return(0);
}
/*
 * Insert an entry in configuration table 
 */
set(p)
struct tab *p;
{
	register struct ord *q;
	register i;

	i = 0;
	if(p->key&BLOCK){
		for(q = &border[0] ; q->name ; q++)
			if(equal(q->name,p->name)){
				i++;
				q->flag =| BLOCK;
			}
		if(i == 0){
			if(bextra == &border[NBFROZ-1]){
				printf("Bdev Table overflow\n");
				exit(1);
			}
			bextra->name = p->name;
			bextra->flag =| BLOCK;
			bextra++;
		}
	}
	if(p->key&CHAR){
		for(q = &corder[0] ; q->name ; q++){
			if(equal(q->name,p->name)){
				i++;
				q->flag =| CHAR;
			}
		}
		if(i == 0){
			if(cextra == &corder[NCFROZ-1]){
				printf("Cdev Table overflow\n");
				exit(1);
			}
			cextra->name = p->name;
			cextra->flag =| CHAR;
			cextra++;
		}
	}
	if(p->key&DISCP){
		for(q = &dorder[0] ; q->name ; q++){
			if(equal(q->name,p->name)){
				i++;
				q->flag =| DISCP;
			}
		}
	}
}
/*
 * Print fixed and floating low core vectors
 */
low()
{
	register	addr;
	register struct tab *p;
	int	ev, i, n;
	register	*q;
	int	hat;

/*
	for(q= &vect[0];q<&vect[118];q++){
		i = *q;
		if(i&&(i != RESERVED))
			printf("addr %o %s\n",(q - &vect[0] + 050),(*q)->name);
	}
*/

	hat = 0;
	for(addr=050;addr<=lowend;){
	if((addr >= 0240) && flagb){
		flagb = 0;
		puke(strb);
		addr =+ 014;
		hat = 0;
		continue;
	}
	if((addr >= 0300)&&flagf){
		flagf = 0;
		puke(strc);
	}
	q = vect[(addr - 050)/4];
	if(q == 0){
		if(flags){
			if(hat == 0)
				printf("\n. = %o^.\n",addr);
			hat++;
			if(flags == 1)
				printf("\tstray;\tbr7+%d.\n",(addr/4)%16);
			else
				printf("\ttrap;\tbr7+15.\n");
		}
		addr =+ 4;
	}else{
		if((i = q) == RESERVED){
			printf("Bad size; collision with Reserved location\n");
		}
		if(addr >= 0300){
			if((q->key&EVEN) && (addr&07)){
				printf("\t.=.+4\n");
				addr =+ 4;
			}
		}
		printf("\n. = %o^.\n",addr);
		hat = 0;
		if(q->key & KL) {
			printf(q->codea, nkl, nkl);
			addr =+ q->size;
			nkl++;
		} else {
			printf(q->codea, q->used, q->used);
			q->used++;
			addr =+ q->size;
		}
		}
	}
}
/*
 * Install a vector in low core map for later printing
 */
install(q,ad,size)
struct tab *q;
{
	register i, adr;

	if((q->key&INTR) == 0)
		return(TRUE);
	adr = ad;
	if(ad >= lowend){
		if(ad >= MAXLOW)
			printf("%s: Vector beyond maximum range %o\n",dev,MAXLOW);
		else
			lowend = ad;
	}
	if(ad - 050  < 0){
		printf("%s: Vector address %o in fixed vector area 0-050\n",dev,ad);
		return(FALSE);
	}
	ad = (ad - 050)/4;
	for(i=0;i<size;i=+ 4){
		if(vect[ad + (i/4)]){
			if(vect[ad + (i/4)] == RESERVED)
				printf("%s: Vector at %o reserved\n",dev,adr + i);
			else
				printf("%s: Vector at %o occupied by %s\n",dev,adr + i,
				vect[ad + (i/4)]->name);
			return(FALSE);
		}
	}
	for(i=0;i<size;i=+ 4){
		vect[ad + (i/4)] = q;
	}
	return(TRUE);
}
/*
 * Check character to see if it is a digit
 */
digit(cc)
{
	register char c;
	c = cc;
	if((c >= '0')&&(c <= '9'))
		return(TRUE);
	return(FALSE);
}
/*
 * Check character to see if it is alphabetic
 */
alpha(cc)
{
	register char c;
	c = cc;
	if((c >= 'a')&&(c <= 'z'))
		return(TRUE);
	if((c >= 'A')&&(c <= 'Z'))
		return(TRUE);
	return(FALSE);
}
/*
 * list keyword - print list of devices added
 */
list()
{
 register int	*q;
	register addr;
	 register i;

	for(addr = 050;addr<lowend;){
		if(q = vect[(addr - 050)/4]){
			if((i = q) == RESERVED){
				printf("%o Reserved\n",addr);
				addr =+ 4;
				continue;
			}
			printf("%o %s",addr,q->name);
			if(q->size > 04){
				printf(" <%d>",q->size/4);
			}
			printf("\n");
			addr =+ q->size;
			continue;
		}
		addr =+ 4;
	}
}
/*
 * location keyword - print list of locations currently occupied
 */
location()
{
	register int	*q;
	register addr;
	register i;

	for(addr = 050;addr<lowend;addr=+ 4){
		if(q = vect[(addr - 050)/4]){
			if((i = q) == RESERVED){
				printf("%o Reserved\n",addr);
				continue;
			}
			printf("%o %s\n",addr,q->name);
		}
	}
}
/*
 * Look in table to see if device is known
 */
lookup(q)
char	*q;
{
	register struct tab *p;

	for(p = table;p->name;p++){
		if(equal(p->name,q))
			return(p);
	}
	return(FALSE);
}
/*
 * Read a character
 */
get()
{
	register char c;

	c = lastc;
	if(lastc){
		lastc = 0;
		return(c);
	}
	return(getchar());
}
/*
 * Convert an ascii string to integer
 */
atoi(p,base)
char	*p;
{
	register n;

	n = 0;
	while(digit(*p)){
		n =* base;
		n =+ *p++ - '0';
	}
	return(n);
}
