/************************************************************************/
/*									*/
/*				mon86.c					*/
/*									*/
/*			Simple 8086 rom based monitor. 			*/
/*									*/
/************************************************************************/


#include <stdio.h>
#include <dos.h>


void debug();
int smatch();


struct table
{
	char	*t_name;		/* the name for this entry	*/
	int	(*t_fn)();		/* the function to execute	*/
};

int mem(), go(), error();


struct table cmd[] =
{
	"mem",	mem,
	"go",	go,
	"",	error
};


void main(argc, argv)
int argc;
char *argv[];
{
	if(argc != 2)
	{
		printf("%s: incorrect argument count\n", argv[0]);
		exit(1);
	}
	else
		printf("mon86 - demo 8086 monitor\n%s version\n", argv[1]);
	debug();
}


void debug()
{
	char line[BUFSIZ];
        char key[32];
	char *lp, *p;
        struct table *tp;
	char *skipwh();

	for(;;)
        {
		printf("\nmon86: ");
		gets(line);
		lp = skipwh(line);
		if(*lp == NULL)
			continue;
		p = key;
		while(*lp != NULL && !iswhite(*lp))
			*p++ = *lp++;
		*p = NULL;
		for(tp = cmd; *(tp -> t_name) != NULL; tp++)
			if(smatch(key, tp -> t_name))
                        	break;
		(*(tp -> t_fn))(lp);
	}
}


int iswhite(c)
register int c;
{
	return (c != NULL && (c == ' ' || c == '\t' || c == '\n' || c == '\r'));
}



char *skipwh(p)
register char *p;
{
	while(iswhite(*p))
		++p;
	return p;
}



/*									*/
/* smatch:								*/
/*	match two strings. return true if equal				*/
/*									*/
static int smatch(s1, s2)
char *s1, *s2;
{
	while(*s1 != '\0')
	{
		if(*s1 != *s2)
			break;
		++s1;
		++s2;
	}
	return *s1 == *s2;
}



int mem(lp)
char *lp;
{
	unsigned long l = 0l;
	unsigned int seg, offset;
	char far *fp;
        char buf[80];

	printf("Memory examine and change\n");
	lp = skipwh(lp);
	while(hexdigit(*lp) >= 0)
		l = (l << 4) + hexdigit(*lp++);
	if(*lp == ':')
	{
		++lp;
		seg = l;
		l = 0l;
		while(hexdigit(*lp) >= 0)
			l = (l << 4) + hexdigit(*lp++);
		offset = l;
	}
	else           	
	{
		seg = 0;
		offset = l;
	}
	fp = MK_FP(seg, offset);
	for(;;)
        {
		printf("%04x:%04x - %02x ", FP_SEG(fp), FP_OFF(fp), *fp & 0xff);
		gets(buf);
		lp = skipwh(buf);
		if(smatch(".", lp))
			break;
		if(!hexdigit(*lp) >= 0)
		{
			++fp;
			continue;
		}
		while(hexdigit(*lp) >= 0)
			l = (l << 4) + hexdigit(*lp++);
		*fp++ = l & 0xff;
	}
}


int go(lp)
char *lp;
{
	int  (far *fp)();
	unsigned long l = 0l;
        unsigned int seg, offset;

	lp = skipwh(lp);
	while(hexdigit(*lp) >= 0)
		l = (l << 4) + hexdigit(*lp++);
	if(*lp == ':')
	{
		++lp;
		seg = l;
		l = 0l;
		while(hexdigit(*lp) >= 0)
			l = (l << 4) + hexdigit(*lp++);
		offset = l;
	}
	else           	
	{
		seg = 0;
		offset = l;
	}
	fp = MK_FP(seg, offset);
	printf("Go from %04x:%04x", FP_SEG(fp), FP_OFF(fp));
        (*fp)();
}

int error()
{
	printf("*** Unknown command\n");
}


hexdigit(c)
int c;
{
	register char *p;
	register i;
	static char *set = "0123456789abcdef",
		*alt_set = "0123456789ABCDEF";

	for(i = 0, p = set; *p != NULL; i++, p++)
		if(c == *p)
			return i;
	for(i = 0, p = alt_set; *p != NULL; i++, p++)
		if(c == *p)
			return i;
	return -1;
}




