
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "regs.h"
#include "trace.h"
#include "lights.h"
#include "io.h"
#include "chan.h"
#include "console.h"
#include "screen.h"
#include "binloader.h"

char prtview[5][81];
char errview[5][81];
long total_cycles = 0;

char iline[256];
char *ibp = 0;
char *lastcmd = 0;

#define VIEW_CLEAR	-1
#define VIEW_NONE	0
#define VIEW_HELP	1
#define VIEW_MOUNT	2
#define VIEW_PRINT	3
#define VIEW_TRACE	4
#define VIEW_ERROR	5

int view = VIEW_CLEAR;
int newview = VIEW_HELP;

/*
 * IBM 709x console
 */

void
errorview()
{
	register i;

	screenposition (17,1);
	printf("\n");
	clearline();
	for (i = 0; i < 5; i++)
	{
		clearline();
		printf("%s\n", errview[i]);
		errview[i][0] = '\0';
	}
}

#if defined(UNIX)
void
sigintr (int sig)
{
   automatic = 0;
   signal (SIGINT, sigintr);
}
#endif

void
check_intr()
{
#if defined(WIN32)
	if (kbhit()) {
		automatic = 0;
	}
#endif
}

void
console()
{
	unsigned short c;
	int loadaddr;
	register int kp;

#if defined(UNIX)
        signal (SIGINT, sigintr);
#endif
redraw:
	if (newview == VIEW_NONE) {
		if (addrstop) {
			newview = VIEW_TRACE;
		} else if (prtview[4][0] != 0) {
			newview = VIEW_PRINT;
		} else {
			newview = VIEW_HELP;
		}
	}
	if (view != newview) {
		clear_screen();
		view = newview;
	}
	lights();
	switch (view) {

	case VIEW_HELP:
		help();
		newview = VIEW_NONE;
		break;

	case VIEW_MOUNT:
		listmount();
		newview = VIEW_NONE;
		break;

	case VIEW_TRACE:
		trace();
		break;

	case VIEW_ERROR:
		errorview();
		newview = VIEW_NONE;
		break;

	case VIEW_PRINT:
		pview();
	}
	keys();

	total_cycles += cycle_count;
	cycle_count = 0;
	next_lights = NEXTLIGHTS;

	if (ibp == 0 || *ibp == 0) {
		if (lastcmd != 0) {
printf(" %s                                                      \r.", lastcmd);
		} else {
printf("                                                         \r.");
		}
		ibp = (char *)fgets(iline, sizeof(iline), stdin);
		*(strchr(iline,'\n')) = '\0';
		if (ibp == 0) {
			iofin();
			exit(0);
		}
		if (*ibp == 0) {
			ibp = lastcmd;
			if (ibp == 0)
				goto redraw;
		} else {
			lastcmd = 0;
		}
	}

	c = *ibp++;
	switch (c) {

	case 'h':
		newview = VIEW_HELP;
		goto redraw;

	case 'r':
		reset();
		goto redraw;

	case 'c':
		if (strncmp(ibp, "lear", 4) == 0) {
			ibp += 4;
			clear();
			goto redraw;
		}
		if (strncmp(ibp, "lose", 4) == 0) {
		   ibp += 4;
		   while (*ibp == ' ') ibp++;
		   if (dismount(ibp) < 0) {
		      newview = VIEW_ERROR;
		      ibp = 0;
		      goto redraw;
		   }
		   newview = VIEW_MOUNT;
		   ibp = 0;
		   goto redraw;
		}
		goto syntax;

	case 'e':
		c = *ibp++;
		switch (c) {

		case 'm':
			mqh = kyh;
			mql = kyl;
			goto redraw;

		case 'i':
			run = 2;
			srh = kyh;
			srl = kyl;
			lastcmd = "ei";
			break;

		default:
			goto syntax;
		}
		break;

	case 'a':
		automatic = 1;
		goto redraw;

	case 'm':
		automatic = 0;
		goto redraw;

	case 's':
		c = *ibp++;
		switch (c) {

		case 't':
			run = 1;
			lastcmd = "st";
			break;

		case 's':
			run = 3;
			lastcmd = "ss";
			break;

		case 'w':
			c = *ibp++;
			if (c >= '1' && c <= '6') {
				setssw(c - '0');
				goto redraw;
			} else {
				goto syntax;
			}

		case 'a':
			c = *ibp;
			if (c >= '0' && c <= '7') {
				int i;

				addrstop = 1;
				stopic = 0;
				while (c >= '0' && c <= '7') {
					stopic = (stopic << 3) + (c - '0');
					c = *++ibp;
				}
				itrc_idx = 0;
				for (i = 0; i < 32; i++)
					itrc_buf[i] = 0;
				newview = VIEW_TRACE;
			} else if (c == 'l') {
				char s[100];

				ibp++;
				long_trace();
				fgets(s, sizeof(s), stdin);
				*(strchr(s,'\n')) = '\0';
			} else {
				addrstop = 0;
				newview = VIEW_NONE;
			}
			goto redraw;

		case 'c':
			single_cycle = 1 - single_cycle;
			lastcmd = "sc";
			goto redraw;

		default:
			goto syntax;
		}
		break;

	case 'd':
		c = *ibp++;
		switch (c) {

		case 'n':
			kyl = (kyl &   037777700000) |
			      (kyl+1 & 000000077777);
			srh = memh[kyl & (MEMLIMIT)];
			srl = getmeml(kyl & (MEMLIMIT));
			lastcmd = "dn";
			goto redraw;

		case 's':
			srh = memh[kyl & (MEMLIMIT)];
			srl = getmeml(kyl & (MEMLIMIT));
			lastcmd = "ds";
			goto redraw;

		default:
			goto syntax;
		}
		break;

	case 'l':
		c = *ibp++;
		switch (c) {

		case 'c':
			if (automatic == 0)
				break;
			reset();
			cun[0] = 0321;
			goto load_key;

		case 'f':
			while (*ibp == ' ') ibp++;
			if (automatic == 0)
				break;
			reset();
			loadaddr = 0;
			while (isdigit(*ibp)) 
			{
			   loadaddr = (loadaddr << 3) | (*ibp++ - '0');
			}
			if (loadaddr == 0) loadaddr = -1;
			while (*ibp == ' ') ibp++;
			if (binloader(ibp, loadaddr) < 0)
			{
			   newview = VIEW_ERROR;
			   ibp = 0;
			   goto redraw;
			}
			run = 3;
			goto loaded;
		case 't':
		case '\0':
			if (automatic == 0)
				break;
			reset();
			cun[0] = 0221;
load_key:
			if (unitcheck(0, 1) != -1) {
				csel[0] = READ_SEL;
				load_chan(0, 1);
				ic = 1;
				srh = 001;	/* LCHA 0 */
				srl = 014400000000;
				run = 3;
			}
loaded:
			lastcmd = "st";
			break;

		default:
			goto syntax;
		}
		break;


	case 'o':
		while (*ibp == ' ') ibp++;
		if (mount(ibp) < 0) {
		   newview = VIEW_ERROR;
		   ibp = 0;
		   goto redraw;
		}
		newview = VIEW_MOUNT;
		ibp = 0;
		goto redraw;

	case 'q':
		iofin();
		printf("\n");
		exit(0);

	case '-':
		kyh |= SIGN;
		c = *ibp++;
		goto setkey;

	case '+':
		c = *ibp++;
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '.':
		kyh &= ~SIGN;
setkey:
		kp = 11;
		for (;;) {
			if (c >= '0' && c <= '7') {
				unsigned long v;

				v = c - '0';
				if (kp < 0) {
					kyl =  (kyl & 037777700000) |
					      ((kyl & 000000007777) << 3) | v;
				} else if (kp == 11) {
					kyh = (kyh & (SIGN | 001)) | (v << 1);
				} else if (kp == 10) {
					kyh = (kyh & (SIGN | 006)) | (v >> 2);
					kyl = (kyl & 007777777777) | (v << 30);
				} else {
					kyl = (kyl & ~(07L << (3*kp))) |
					      (v << (3*kp));
				}
			} else if (c == '.') {
				if (kp == 11) {
					kyh = (kyh & SIGN);
					kyl = 0;
				} else if (kp == 10) {
					kyh = (kyh & (SIGN | 006));
					kyl = 0;
				} else {
					kyl = (kyl &
					       (037777777777 << (3*(kp+1))));
				}
				kp = -1;
			} else {
				ibp--;
				goto redraw;
			}
			if (kp == 0)
				goto redraw;
			kp--;
			c = *ibp++;
		}

	case 0:
		goto redraw;

	default:
		goto syntax;

	}
	lights();
	if (single_cycle) {
		next_steal = 0;
	} else {
		if (next_steal > NEXTLIGHTS)
			next_steal = NEXTLIGHTS;
	}
	return;

syntax:
	printf("%c", 7);
	ibp = 0;
	goto redraw;
}

void
setssw(int c)
{

	switch(c) {

	case 1:
		ssw ^= 040;
		break;

	case 2:
		ssw ^= 020;
		break;

	case 3:
		ssw ^= 010;
		break;

	case 4:
		ssw ^= 004;
		break;

	case 5:
		ssw ^= 002;
		break;

	case 6:
		ssw ^= 001;
		break;
	}
}

void
clear()
{
	register unsigned i;

	for (i = 0; i <= MEMLIMIT; i++) {
		memh[i] = 0;
		setmeml(i, 0L);
	}
	sih = 0;
	sil = 0;
	reset();
	prtview[0][0] = 0;
	prtview[1][0] = 0;
	prtview[2][0] = 0;
	prtview[3][0] = 0;
	prtview[4][0] = 0;
	errview[0][0] = 0;
	errview[1][0] = 0;
	errview[2][0] = 0;
	errview[3][0] = 0;
	errview[4][0] = 0;
}

void
reset()
{
	register i;

	srh = 0;
	srl = 0;
	ach = 0;
	acl = 0;
	mqh = 0;
	mql = 0;
	ic = 0;
	for (i = 0; i < 8; i++) {
		xr[i] = 0;
	}
	run = 0;
	sl = 0;
	op = 0;
	stop = 0;
	trap = 0;
	simulate = 0;
	multtag = 1;
	acoflo = 0;
	mqoflo = 0;
	rwsel = 0;
	divchk = 0;
	machchk = 0;
	iochk = 0;
	spill = 0;
	cycle_count = 0;
	single_cycle = 0;
	for (i = 0; i < MAXCHAN; i++) {
		cop[i] = 0;
		cun[i] = 0;
		car[i] = 0;
		cwr[i] = 0;
		clr[i] = 0;
		cdrh[i] = 0;
		cdrl[i] = 0;
		csel[i] = 0;
		cact[i] = 0;
		cchk[i] = 0;
		ceof[i] = 0;
		cbot[i] = 0;
		ceot[i] = 0;
		ceor[i] = 0;
		ctrp[i] = 0;
		ccyc[i] = 0;
	}
	ctrap_enb = 0;
	ctrap_ind = 0;
	chan_in_op = 0;
	view = VIEW_CLEAR;
}

void
clear_screen()
{

        clearscreen();
	screenposition (1,1);
}

void
keys()
{

	screenposition(23,1);
	clearline();
	printf("\n");
}
