File:  [MW Coherent from dump] / coherent / b / bin / db / db5.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:36 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * db/db5.c
 * A debugger.
 * Expression evaluator.
 */

#include "db.h"

#define	VALUE	(-2)		/* must be distinct from chars		*/
#define	VILLEGAL (-3)		/* ditto				*/
#define	PRCFULL	(0<<8)		/* precedence wall for full expression 	*/
#define	PRECADD	(1<<8)		/* precedence of additive ops		*/
#define	PRECMUL	(2<<8)		/* precedence of multiplicative ops	*/
#define	PRIMARY	(4<<8)		/* precedence of primary expression	*/
#define	tk_preced(op)	((op)&(~0<<8))
#define	tk_char(op)	((op)&0377)

/*
 * Recursive expression reader;
 * returns -1 for error, 0 for null expr, 1 for good expr.
 */
int
expr(left, wall) register VAL *left; int wall;
{
	VAL v;
	register VAL *right;
	int token, result;
	WORD_T word;

	right = &v;
	token = lextoken(left);
	if (token==VALUE)
		;
	else if (token==VILLEGAL)
		return -1;
	else switch (tk_char(token)) {
	case '~':
		if (expr(left, PRIMARY)<=0)
			return -1;
		left->v_nval = ~left->v_nval;
		break;
	case '-':
		if (expr(left, PRIMARY)<=0)
			return -1;
		left->v_nval = -left->v_nval;
		break;
	case '*':
		/* Indirection. */
		if (expr(left, PRIMARY)<=0)
			return -1;
		add = left->v_nval;
		/* Fetch what the left points to. */
		getb(val_segn(left), (char *)&word, sizeof word);
		left->v_nval = (long)word;
		left->v_flag = 0;
		break;
	case '(':
		if (expr(left, PRCFULL)<=0)
			return -1;
		if ((token = lextoken((VAL *)NULL))==')')
			break;
		else {
			unlex(token);
			printe("Missing ')'");
			return -1;
		}
	default:
		unlex(token);
		left->v_flag = VNULL;
		return 0;
	}
	for (;;) {
		token = lextoken((VAL *)NULL);
		if (tk_preced(token) <= wall) {
			unlex(token);
			return 1;
		} else switch (tk_char(token)) {
		case '*':
			if ((result=expr(right, PRECMUL))<=0)
				break;
			left->v_nval *= right->v_nval;
			continue;
		case '/':
			if ((result=expr(right, PRECMUL))<=0)
				break;
			left->v_nval /= right->v_nval;
			continue;
		case '+':
			if ((result=expr(right, PRECADD))<=0)
				break;
			left->v_nval += right->v_nval;
			continue;
		case '-':
			if ((result=expr(right, PRECADD))<=0)
				break;
			left->v_nval -= right->v_nval;
			continue;
		default:
			unlex(token);
			printe("Unimplemented operator");
			return -1;
		}
		if (result==0)
			printe("Missing operand");
		return -1;
	}
}

/*
 * Evaluate an expression list.
 */
int
expr_list(vlist) VAL vlist[VALSIZE];
{
	register VAL *vp;
	register int c, n;

	vp = vlist;
	n = VALSIZE;
	do {
		if (expr(vp, PRCFULL)<0)
			return 0;
		vp++;
		--n;
	} while ((c=getn()) == ',');
	ungetn(c);
	while (n--)
		vp++->v_flag = VNULL;
	return 1;
}

/*
 * Lex a token. If value, store in given val ptr.
 */
int
lextoken(vp) VAL *vp;
{
	register int	c;

	for (;;) switch (c=getn()) {
	case ' ':
	case '\t':
		continue;
	case '.':
		if (vp == (VAL *)NULL) {
			printe("Missing operand before '.'");
			ungetn(c);
			return VILLEGAL;
		}
		vp->v_flag = VSEGN;
		vp->v_segn = cseg;
		vp->v_nval = dot;
		return VALUE;
		/*
		 * Only binary ops need be mentioned explicitly
		 * so precedences can be added.
		 */
	case '*':
	case '/':
		return c|PRECMUL;
	case '+':
	case '-':
		return c|PRECADD;
	default:
		if ('0'<=c && c<='9')
			return readval(vp, c);
		else if ('a'<=c && c<='z' || 'A'<=c && c<='Z' || c=='_' || c=='%')
			return readvar(vp, c);
		else
			return c;
	}
}

/*
 * Evaluate a value as an lvalue and return it.
 * If the value is VNULL, return 'v'.
 */
ADDR_T
lvalue(vp, v) register VAL *vp; ADDR_T v;
{
	return (vp->v_flag & VNULL) ? v : (ADDR_T)vp->v_nval;
}

#if	0			/* Covered by macro in db.h */
/*
 * If the given value is null, return 1, else 0.
 */
int
nvalue(vp) VAL *vp;
{
	return vp->v_flag & VNULL;
}
#endif

/*
 * Read a number.
 */
int
readval(vp, c) VAL *vp; register int c;
{
	long	l;
	register int	i, base;

	if (vp == (VAL *)NULL) {
		printe("Missing operand before number");
		ungetn(c);
		return VILLEGAL;
	}
	base = 10;
	if (c=='0') {
		base = 8;
		if ((c = getn())=='x') {
			base = 16;
		} else {
			ungetn(c);
		}
		c = '0';
	}
	if (c == '#')
		base = 16;
	else
		l = '0' - c;
	for (;;) {
		if ((10 <= (i=(c = getn())-('a'-10))
		    || 10 <= (i=c-('A'-10))
		    ||  0 <= (i=c-'0') && i <= 9)
		 && i < base)
			l = l*base - i;
		else
			break;
	}
	ungetn(c);
	vp->v_flag = 0;
	vp->v_nval = -l;
	return VALUE;
}

/*
 * Read symbol and place value in given val struct.
 */
int
readvar(vp, c) VAL *vp; int c;
{
	ungetn(c);
	if (vp == (VAL *)NULL) {
		printe("Missing operand before symbol");
		return VILLEGAL;
	}
	return (symval(vp)) ? VALUE : VILLEGAL;
}

/*
 * Evaluate a value as an rvalue and return it.
 * If the value is null, return 'v'.
 */
long
rvalue(vp, v) register VAL *vp; long v;
{
	return (vp->v_flag&VNULL) ? v : vp->v_nval;
}

/*
 * Push token back on input stream.
 */
void
unlex(c) int c;
{
	if (c != VILLEGAL && c != VALUE)
		ungetn(tk_char(c));
}

/*
 * Return the segment associated with a value.
 * If there is no segment associated with it,
 * look at the segmentation map to see if it is found.
 * If the value is null or not found, return the current segment.
 */
int
val_segn(vp) register VAL *vp;
{
	register int s;

	if (vp->v_flag & VNULL)
		return cseg;
	if (vp->v_flag & VSEGN)
		return vp->v_segn;		/* in known segment */
	else if ((s = find_seg((ADDR_T)vp->v_nval)) != SEG_NONE)
		return s;			/* in existing segment */
	else
		return cseg;			/* take a guess... */
}

/* end of db/db5.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.