V8/usr/src/cmd/adb/command.c

Compare this file to the similar file:
Show the results in this format:

#
/*
 *
 *	UNIX debugger
 *
 */

#include "defs.h"
#include <signal.h>
#include "regs.h"

MSG	BADEQ;
MSG	NOMATCH;
MSG	BADVAR;
MSG	BADCOM;
MSG	NOFORK;

BOOL	executing;
char	*lp;

char	lastc;
char	eqformat[ARB] = "z";
char	stformat[ARB] = "X\"= \"^i";

ADDR	ditto;

ADDR	dot;
WORD	dotinc;
WORD	adrval, cntval, loopcnt;
int	adrflg, cntflg;
int	adrsp, dotsp, ditsp;

/* command decoding */

command(buf,defcom)
register char	*buf;
char	defcom;
{
	int	modifier, regptr;
	char	savc;
	char	*savlp=lp;
	static char lastcom = '=';

	if (defcom == 0)
		defcom = lastcom;
	if (buf) {
		if (*buf==EOR)
			return(FALSE);
		lp=buf;
	}
	do {
		if (adrflg=expr(0)) {
			dot=ditto=expv;
			dotsp=ditsp=expsp;
		}
		adrval=dot;
		adrsp=dotsp;
		if (rdc()==',' && expr(0)) {
			cntflg=TRUE;
			cntval=expv;
		} else {
			cntflg=FALSE;
			cntval=1;
			reread();
		}
		if (!eol(rdc()))
			lastcom=lastc;
		else {
			if (adrflg==0)
				dot=inkdot(dotinc);
			reread();
			lastcom=defcom;
		}
		switch(lastcom&STRIP) {
		case '/':
		case '=':
		case '?':
			acommand(lastcom & STRIP);
			break;

		case '>':
			lastcom=0; 
			savc=rdc();
			if ((regptr=getreg(savc)) != BADREG)
				rput(regptr, wtor(dot));
			else if ((modifier=varchk(savc)) != -1)	
				var[modifier]=dot;
			else	
				error(BADVAR);
			break;

		case '!':
			lastcom=0;
			shell(); 
			break;

		case '$':
			lastcom=0;
			printtrace(nextchar()); 
			break;

		case ':':
			if (!executing) { 
				executing=TRUE;
				subpcs(nextchar());
				executing=FALSE;
				lastcom=0;
			}
			break;

		case 0:
			prints(DBNAME);
			break;

		default: 
			error(BADCOM);
		}
		flushbuf();
	} while (rdc()==';');
	if (buf)
		lp=savlp; 
	else
		reread(); 
	return(adrflg && dot!=0);
}

/*
 * [/?][wml]
 */

acommand(pc)
char pc;
{
	register int itype;
	int eqcom;
	int star;
	char wformat[1];
	ADDR savdot;
	
	switch (pc) {
	case '/':
		itype = CORF | DATASP; 
		break;

	case '=':
		itype = NOSP; 
		break;

	case '?':
		itype = SYMF | INSTSP; 
		break;
	}
	eqcom = FALSE;
	star = FALSE;
	if (pc == '=')
		eqcom = TRUE;
	else {
		if (rdc()=='*')
			star = TRUE; 
		else
			reread(); 
		if (star) {
			if (itype & SYMF)
				itype = SYMF | DATASP;
			else
				itype = CORF | INSTSP;
		}
		if ((adrsp & SPTYPE) == REGSP) {
			itype &=~ SPTYPE;
			itype |= REGSP;
		}
	}
	switch (rdc()) {
	case 'm':
		if (eqcom)
			error(BADEQ); 
		cmdmap(itype, star);
		break;

	case 'L':
	case 'l':
		if (eqcom)
			error(BADEQ); 
		cmdsrc(lastc, itype, itype);
		break;

	case 'W':
	case 'w':
		if (eqcom)
			error(BADEQ); 
		wformat[0]=lastc; 
		expr(1);
		do {  
			savdot=dot;
			psymoff((WORD)dot, itype, itype & SYMF ?"?%16t":"/%16t"); 
			exform(1,wformat,itype,itype);
			errflg=0; 
			dot=savdot;
			if (wformat[0] == 'W')
				lput(dot,itype,wtol(expv));
			else
				sput(dot,itype,wtos(expv));
			savdot=dot;
			printf("=%8t"); 
			exform(1,wformat,itype,itype);
			newline();
		} while (expr(0) && errflg==0);
		dot=savdot;
		chkerr();
		break;

	default:
		reread();
		getformat(eqcom ? eqformat : stformat);
		if (!eqcom)
			psymoff((WORD)dot, itype, itype & SYMF ?"?%16t":"/%16t");
		scanform(cntval,(eqcom?eqformat:stformat),itype,itype);
	}
}

cmdsrc(c, itype, ptype)
char c;
{
	register WORD w;
	register WORD locval, locmsk;
	ADDR savdot;

	if (c == 'L')
		dotinc = sizeof(TLONG);
	else
		dotinc = sizeof(TSHORT);
	savdot=dot;
	expr(1); 
	locval=expv;
	if (expr(0))
		locmsk=expv; 
	else
		locmsk = ~0;
	if (c == 'L') {
		for (;;) {
			w = ltow(lget(dot, itype));
			if (errflg || mkfault
			||  (w & locmsk) == locval)
				break;
			dot = inkdot(dotinc);
		}
	}
	else {
		for (;;) {
			w = stow(sget(dot, itype));
			if (errflg || mkfault
			||  (w & locmsk) == locval)
				break;
			dot = inkdot(dotinc);
		}
	}
	if (errflg) { 
		dot=savdot; 
		errflg=NOMATCH;
	}
	psymoff((WORD)dot,ptype,"");
}

/*
 * collect a register name; return register offset
 * this is not what i'd call a good division of labour
 */

int
getreg(regnam)
{
	char	buf[LINSIZ];
	register char *p;
	register int c;

	p = buf;
	*p++ = regnam;
	while (isalnum(c = readchar()))
		*p++ = c;
	*p = 0;
	reread();
	return (rname(buf));
}

/*
 * shell escape
 */

shell()
{
	int	rc, status, unixpid;
	char *sh;
	char *argp = lp;
	int (*isig)();
	extern (*sigint)(), (*sigqit)();
	char *getenv();

	if ((sh = getenv("SHELL")) == NULL)
		sh = "/bin/sh";
	while (lastc!=EOR)
		rdc();
	if ((unixpid=fork())==0) {
		signal(SIGINT, sigint);
		signal(SIGQUIT, sigqit);
		*lp=0;
		execl(sh, "sh", "-c", argp, 0);
		_exit(16);
	} else if (unixpid == -1) {
		error(NOFORK);
	} else {
		isig = signal(SIGINT, SIG_IGN);
		while ((rc = wait(&status)) != unixpid && rc != -1)
			;
		signal(SIGINT, isig);
		prints("!"); 
		reread();
	}
}