xref: /plan9/sys/src/cmd/db/expr.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  *
33e12c5d1SDavid du Colombier  *	debugger
43e12c5d1SDavid du Colombier  *
53e12c5d1SDavid du Colombier  */
63e12c5d1SDavid du Colombier 
73e12c5d1SDavid du Colombier #include "defs.h"
83e12c5d1SDavid du Colombier #include "fns.h"
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier static long	round(long, long);
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier extern	char	lastc, peekc;
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier extern	ADDR	ditto;
15*7dd7cddfSDavid du Colombier vlong	expv;
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier static WORD
18219b2ee8SDavid du Colombier ascval(void)
19219b2ee8SDavid du Colombier {
20219b2ee8SDavid du Colombier 	Rune r;
21219b2ee8SDavid du Colombier 	int i;
22219b2ee8SDavid du Colombier 	char buf[UTFmax+1];
23219b2ee8SDavid du Colombier 
24219b2ee8SDavid du Colombier 	for (i = 0; i < UTFmax; i++) {	/* extract a rune */
25219b2ee8SDavid du Colombier 		if (fullrune(buf, i))
26219b2ee8SDavid du Colombier 			break;
27219b2ee8SDavid du Colombier 		if (readchar() == 0)
28219b2ee8SDavid du Colombier 			return (0);
29219b2ee8SDavid du Colombier 		buf[i] = lastc;
30219b2ee8SDavid du Colombier 	}
31219b2ee8SDavid du Colombier 	buf[i] = 0;
32219b2ee8SDavid du Colombier 	chartorune(&r, buf);
33219b2ee8SDavid du Colombier 	while(quotchar())	/*discard chars to ending quote */
34219b2ee8SDavid du Colombier 		;
35219b2ee8SDavid du Colombier 	return((WORD) r);
36219b2ee8SDavid du Colombier }
37219b2ee8SDavid du Colombier 
38219b2ee8SDavid du Colombier /*
39219b2ee8SDavid du Colombier  * read a floating point number
40219b2ee8SDavid du Colombier  * the result must fit in a WORD
41219b2ee8SDavid du Colombier  */
42219b2ee8SDavid du Colombier 
43219b2ee8SDavid du Colombier static WORD
44219b2ee8SDavid du Colombier fpin(char *buf)
45219b2ee8SDavid du Colombier {
46219b2ee8SDavid du Colombier 	union {
47219b2ee8SDavid du Colombier 		WORD w;
48219b2ee8SDavid du Colombier 		float f;
49219b2ee8SDavid du Colombier 	} x;
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier 	x.f = atof(buf);
52219b2ee8SDavid du Colombier 	return (x.w);
53219b2ee8SDavid du Colombier }
543e12c5d1SDavid du Colombier 
553e12c5d1SDavid du Colombier WORD
563e12c5d1SDavid du Colombier defval(WORD w)
573e12c5d1SDavid du Colombier {
583e12c5d1SDavid du Colombier 	if (expr(0))
593e12c5d1SDavid du Colombier 		return (expv);
603e12c5d1SDavid du Colombier 	else
613e12c5d1SDavid du Colombier 		return (w);
623e12c5d1SDavid du Colombier }
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier expr(int a)
653e12c5d1SDavid du Colombier {	/* term | term dyadic expr |  */
663e12c5d1SDavid du Colombier 	int	rc;
673e12c5d1SDavid du Colombier 	WORD	lhs;
683e12c5d1SDavid du Colombier 
693e12c5d1SDavid du Colombier 	rdc();
703e12c5d1SDavid du Colombier 	reread();
713e12c5d1SDavid du Colombier 	rc=term(a);
723e12c5d1SDavid du Colombier 	while (rc) {
733e12c5d1SDavid du Colombier 		lhs = expv;
743e12c5d1SDavid du Colombier 		switch ((int)readchar()) {
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 		case '+':
773e12c5d1SDavid du Colombier 			term(a|1);
783e12c5d1SDavid du Colombier 			expv += lhs;
793e12c5d1SDavid du Colombier 			break;
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 		case '-':
823e12c5d1SDavid du Colombier 			term(a|1);
833e12c5d1SDavid du Colombier 			expv = lhs - expv;
843e12c5d1SDavid du Colombier 			break;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 		case '#':
873e12c5d1SDavid du Colombier 			term(a|1);
883e12c5d1SDavid du Colombier 			expv = round(lhs,expv);
893e12c5d1SDavid du Colombier 			break;
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 		case '*':
923e12c5d1SDavid du Colombier 			term(a|1);
933e12c5d1SDavid du Colombier 			expv *= lhs;
943e12c5d1SDavid du Colombier 			break;
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier 		case '%':
973e12c5d1SDavid du Colombier 			term(a|1);
983e12c5d1SDavid du Colombier 			if(expv != 0)
993e12c5d1SDavid du Colombier 				expv = lhs/expv;
1003e12c5d1SDavid du Colombier 			else{
1013e12c5d1SDavid du Colombier 				if(lhs)
1023e12c5d1SDavid du Colombier 					expv = 1;
1033e12c5d1SDavid du Colombier 				else
1043e12c5d1SDavid du Colombier 					expv = 0;
1053e12c5d1SDavid du Colombier 			}
1063e12c5d1SDavid du Colombier 			break;
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier 		case '&':
1093e12c5d1SDavid du Colombier 			term(a|1);
1103e12c5d1SDavid du Colombier 			expv &= lhs;
1113e12c5d1SDavid du Colombier 			break;
1123e12c5d1SDavid du Colombier 
1133e12c5d1SDavid du Colombier 		case '|':
1143e12c5d1SDavid du Colombier 			term(a|1);
1153e12c5d1SDavid du Colombier 			expv |= lhs;
1163e12c5d1SDavid du Colombier 			break;
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier 		case ')':
1193e12c5d1SDavid du Colombier 			if ((a&2)==0)
1203e12c5d1SDavid du Colombier 				error("unexpected `)'");
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 		default:
1233e12c5d1SDavid du Colombier 			reread();
1243e12c5d1SDavid du Colombier 			return(rc);
1253e12c5d1SDavid du Colombier 		}
1263e12c5d1SDavid du Colombier 	}
1273e12c5d1SDavid du Colombier 	return(rc);
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier 
1303e12c5d1SDavid du Colombier term(int a)
1313e12c5d1SDavid du Colombier {	/* item | monadic item | (expr) | */
132*7dd7cddfSDavid du Colombier 	WORD e;
1333e12c5d1SDavid du Colombier 
1343e12c5d1SDavid du Colombier 	switch ((int)readchar()) {
1353e12c5d1SDavid du Colombier 
1363e12c5d1SDavid du Colombier 	case '*':
1373e12c5d1SDavid du Colombier 		term(a|1);
138*7dd7cddfSDavid du Colombier 		if (get4(cormap, (ADDR)expv, &e) < 0)
139219b2ee8SDavid du Colombier 			error("%r");
140*7dd7cddfSDavid du Colombier 		expv = e;
1413e12c5d1SDavid du Colombier 		return(1);
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 	case '@':
1443e12c5d1SDavid du Colombier 		term(a|1);
145*7dd7cddfSDavid du Colombier 		if (get4(symmap, (ADDR)expv, &e) < 0)
146219b2ee8SDavid du Colombier 			error("%r");
147*7dd7cddfSDavid du Colombier 		expv = e;
1483e12c5d1SDavid du Colombier 		return(1);
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier 	case '-':
1513e12c5d1SDavid du Colombier 		term(a|1);
1523e12c5d1SDavid du Colombier 		expv = -expv;
1533e12c5d1SDavid du Colombier 		return(1);
1543e12c5d1SDavid du Colombier 
1553e12c5d1SDavid du Colombier 	case '~':
1563e12c5d1SDavid du Colombier 		term(a|1);
1573e12c5d1SDavid du Colombier 		expv = ~expv;
1583e12c5d1SDavid du Colombier 		return(1);
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 	case '(':
1613e12c5d1SDavid du Colombier 		expr(2);
1623e12c5d1SDavid du Colombier 		if (readchar()!=')')
1633e12c5d1SDavid du Colombier 			error("syntax error: `)' expected");
1643e12c5d1SDavid du Colombier 		return(1);
1653e12c5d1SDavid du Colombier 
1663e12c5d1SDavid du Colombier 	default:
1673e12c5d1SDavid du Colombier 		reread();
1683e12c5d1SDavid du Colombier 		return(item(a));
1693e12c5d1SDavid du Colombier 	}
1703e12c5d1SDavid du Colombier }
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier item(int a)
173219b2ee8SDavid du Colombier {	/* name [ . local ] | number | . | ^  | <register | 'x | | */
174219b2ee8SDavid du Colombier 	char	*base;
1753e12c5d1SDavid du Colombier 	char	savc;
176*7dd7cddfSDavid du Colombier 	WORD e;
1773e12c5d1SDavid du Colombier 	Symbol s;
1783e12c5d1SDavid du Colombier 	char gsym[MAXSYM], lsym[MAXSYM];
1793e12c5d1SDavid du Colombier 
1803e12c5d1SDavid du Colombier 	readchar();
1813e12c5d1SDavid du Colombier 	if (isfileref()) {
1823e12c5d1SDavid du Colombier 		readfname(gsym);
1833e12c5d1SDavid du Colombier 		rdc();			/* skip white space */
1843e12c5d1SDavid du Colombier 		if (lastc == ':') {	/* it better be */
1853e12c5d1SDavid du Colombier 			rdc();		/* skip white space */
1863e12c5d1SDavid du Colombier 			if (!getnum(readchar))
1873e12c5d1SDavid du Colombier 				error("bad number");
1883e12c5d1SDavid du Colombier 			if (expv == 0)
1893e12c5d1SDavid du Colombier 				expv = 1;	/* file begins at line 1 */
1903e12c5d1SDavid du Colombier 			expv = file2pc(gsym, expv);
1913e12c5d1SDavid du Colombier 			if (expv == -1)
192219b2ee8SDavid du Colombier 				error("%r");
1933e12c5d1SDavid du Colombier 			return 1;
1943e12c5d1SDavid du Colombier 		}
1953e12c5d1SDavid du Colombier 		error("bad file location");
1963e12c5d1SDavid du Colombier 	} else if (symchar(0)) {
1973e12c5d1SDavid du Colombier 		readsym(gsym);
1983e12c5d1SDavid du Colombier 		if (lastc=='.') {
1993e12c5d1SDavid du Colombier 			readchar();	/* ugh */
200219b2ee8SDavid du Colombier 			if (lastc == '.') {
201219b2ee8SDavid du Colombier 				lsym[0] = '.';
202219b2ee8SDavid du Colombier 				readchar();
203219b2ee8SDavid du Colombier 				readsym(lsym+1);
204219b2ee8SDavid du Colombier 			} else if (symchar(0)) {
2053e12c5d1SDavid du Colombier 				readsym(lsym);
206219b2ee8SDavid du Colombier 			} else
207219b2ee8SDavid du Colombier 				lsym[0] = 0;
208*7dd7cddfSDavid du Colombier 			if (localaddr(cormap, gsym, lsym, &e, rget) < 0)
209219b2ee8SDavid du Colombier 				error("%r");
210*7dd7cddfSDavid du Colombier 			expv = e;
2113e12c5d1SDavid du Colombier 		}
2123e12c5d1SDavid du Colombier 		else {
2133e12c5d1SDavid du Colombier 			if (lookup(0, gsym, &s) == 0)
2143e12c5d1SDavid du Colombier 				error("symbol not found");
2153e12c5d1SDavid du Colombier 			expv = s.value;
2163e12c5d1SDavid du Colombier 		}
2173e12c5d1SDavid du Colombier 		reread();
2183e12c5d1SDavid du Colombier 	} else if (getnum(readchar)) {
2193e12c5d1SDavid du Colombier 		;
2203e12c5d1SDavid du Colombier 	} else if (lastc=='.') {
2213e12c5d1SDavid du Colombier 		readchar();
222219b2ee8SDavid du Colombier 		if (!symchar(0) && lastc != '.') {
2233e12c5d1SDavid du Colombier 			expv = dot;
2243e12c5d1SDavid du Colombier 		} else {
225219b2ee8SDavid du Colombier 			if (findsym(rget(cormap, mach->pc), CTEXT, &s) == 0)
226219b2ee8SDavid du Colombier 				error("no current function");
227219b2ee8SDavid du Colombier 			if (lastc == '.') {
228219b2ee8SDavid du Colombier 				lsym[0] = '.';
229219b2ee8SDavid du Colombier 				readchar();
230219b2ee8SDavid du Colombier 				readsym(lsym+1);
231219b2ee8SDavid du Colombier 			} else
2323e12c5d1SDavid du Colombier 				readsym(lsym);
233*7dd7cddfSDavid du Colombier 			if (localaddr(cormap, s.name, lsym, &e, rget) < 0)
234219b2ee8SDavid du Colombier 				error("%r");
235*7dd7cddfSDavid du Colombier 			expv = e;
2363e12c5d1SDavid du Colombier 		}
2373e12c5d1SDavid du Colombier 		reread();
2383e12c5d1SDavid du Colombier 	} else if (lastc=='"') {
2393e12c5d1SDavid du Colombier 		expv=ditto;
2403e12c5d1SDavid du Colombier 	} else if (lastc=='+') {
2413e12c5d1SDavid du Colombier 		expv=inkdot(dotinc);
2423e12c5d1SDavid du Colombier 	} else if (lastc=='^') {
2433e12c5d1SDavid du Colombier 		expv=inkdot(-dotinc);
2443e12c5d1SDavid du Colombier 	} else if (lastc=='<') {
2453e12c5d1SDavid du Colombier 		savc=rdc();
246219b2ee8SDavid du Colombier 		base = regname(savc);
247219b2ee8SDavid du Colombier 		expv = rget(cormap, base);
2483e12c5d1SDavid du Colombier 	}
2493e12c5d1SDavid du Colombier 	else if (lastc=='\'')
2503e12c5d1SDavid du Colombier 		expv = ascval();
2513e12c5d1SDavid du Colombier 	else if (a)
2523e12c5d1SDavid du Colombier 		error("address expected");
2533e12c5d1SDavid du Colombier 	else {
2543e12c5d1SDavid du Colombier 		reread();
2553e12c5d1SDavid du Colombier 		return(0);
2563e12c5d1SDavid du Colombier 	}
2573e12c5d1SDavid du Colombier 	return(1);
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier 
2603e12c5d1SDavid du Colombier #define	MAXBASE	16
2613e12c5d1SDavid du Colombier 
2623e12c5d1SDavid du Colombier /* service routines for expression reading */
2633e12c5d1SDavid du Colombier getnum(int (*rdf)(void))
2643e12c5d1SDavid du Colombier {
2653e12c5d1SDavid du Colombier 	char *cp;
2663e12c5d1SDavid du Colombier 	int base, d;
2673e12c5d1SDavid du Colombier 	BOOL fpnum;
2683e12c5d1SDavid du Colombier 	char num[MAXLIN];
2693e12c5d1SDavid du Colombier 
2703e12c5d1SDavid du Colombier 	base = 0;
2713e12c5d1SDavid du Colombier 	fpnum = FALSE;
2723e12c5d1SDavid du Colombier 	if (lastc == '#') {
2733e12c5d1SDavid du Colombier 		base = 16;
2743e12c5d1SDavid du Colombier 		(*rdf)();
2753e12c5d1SDavid du Colombier 	}
2763e12c5d1SDavid du Colombier 	if (convdig(lastc) >= MAXBASE)
2773e12c5d1SDavid du Colombier 		return (0);
2783e12c5d1SDavid du Colombier 	if (lastc == '0')
2793e12c5d1SDavid du Colombier 		switch ((*rdf)()) {
2803e12c5d1SDavid du Colombier 		case 'x':
2813e12c5d1SDavid du Colombier 		case 'X':
2823e12c5d1SDavid du Colombier 			base = 16;
2833e12c5d1SDavid du Colombier 			(*rdf)();
2843e12c5d1SDavid du Colombier 			break;
2853e12c5d1SDavid du Colombier 
2863e12c5d1SDavid du Colombier 		case 't':
2873e12c5d1SDavid du Colombier 		case 'T':
2883e12c5d1SDavid du Colombier 			base = 10;
2893e12c5d1SDavid du Colombier 			(*rdf)();
2903e12c5d1SDavid du Colombier 			break;
2913e12c5d1SDavid du Colombier 
2923e12c5d1SDavid du Colombier 		case 'o':
2933e12c5d1SDavid du Colombier 		case 'O':
2943e12c5d1SDavid du Colombier 			base = 8;
2953e12c5d1SDavid du Colombier 			(*rdf)();
2963e12c5d1SDavid du Colombier 			break;
2973e12c5d1SDavid du Colombier 		default:
2983e12c5d1SDavid du Colombier 			if (base == 0)
2993e12c5d1SDavid du Colombier 				base = 8;
3003e12c5d1SDavid du Colombier 			break;
3013e12c5d1SDavid du Colombier 		}
3023e12c5d1SDavid du Colombier 	if (base == 0)
3033e12c5d1SDavid du Colombier 		base = 10;
3043e12c5d1SDavid du Colombier 	expv = 0;
3053e12c5d1SDavid du Colombier 	for (cp = num, *cp = lastc; ;(*rdf)()) {
3063e12c5d1SDavid du Colombier 		if ((d = convdig(lastc)) < base) {
3073e12c5d1SDavid du Colombier 			expv *= base;
3083e12c5d1SDavid du Colombier 			expv += d;
3093e12c5d1SDavid du Colombier 			*cp++ = lastc;
3103e12c5d1SDavid du Colombier 		}
3113e12c5d1SDavid du Colombier 		else if (lastc == '.') {
3123e12c5d1SDavid du Colombier 			fpnum = TRUE;
3133e12c5d1SDavid du Colombier 			*cp++ = lastc;
3143e12c5d1SDavid du Colombier 		} else {
3153e12c5d1SDavid du Colombier 			reread();
3163e12c5d1SDavid du Colombier 			break;
3173e12c5d1SDavid du Colombier 		}
3183e12c5d1SDavid du Colombier 	}
3193e12c5d1SDavid du Colombier 	if (fpnum)
3203e12c5d1SDavid du Colombier 		expv = fpin(num);
3213e12c5d1SDavid du Colombier 	return (1);
3223e12c5d1SDavid du Colombier }
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier void
3253e12c5d1SDavid du Colombier readsym(char *isymbol)
3263e12c5d1SDavid du Colombier {
3273e12c5d1SDavid du Colombier 	char	*p;
3283e12c5d1SDavid du Colombier 
3293e12c5d1SDavid du Colombier 	p = isymbol;
3303e12c5d1SDavid du Colombier 	do {
3313e12c5d1SDavid du Colombier 		if (p < &isymbol[MAXSYM-1])
3323e12c5d1SDavid du Colombier 			*p++ = lastc;
3333e12c5d1SDavid du Colombier 		readchar();
3343e12c5d1SDavid du Colombier 	} while (symchar(1));
3353e12c5d1SDavid du Colombier 	*p = 0;
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier 
3383e12c5d1SDavid du Colombier void
3393e12c5d1SDavid du Colombier readfname(char *filename)
3403e12c5d1SDavid du Colombier {
3413e12c5d1SDavid du Colombier 	char	*p;
3423e12c5d1SDavid du Colombier 	char	c;
3433e12c5d1SDavid du Colombier 
3443e12c5d1SDavid du Colombier 	/* snarf chars until un-escaped char in terminal char set */
3453e12c5d1SDavid du Colombier 	p = filename;
3463e12c5d1SDavid du Colombier 	do {
3473e12c5d1SDavid du Colombier 		if ((c = lastc) != '\\' && p < &filename[MAXSYM-1])
3483e12c5d1SDavid du Colombier 			*p++ = c;
3493e12c5d1SDavid du Colombier 		readchar();
3503e12c5d1SDavid du Colombier 	} while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
3513e12c5d1SDavid du Colombier 	*p = 0;
3523e12c5d1SDavid du Colombier 	reread();
3533e12c5d1SDavid du Colombier }
3543e12c5d1SDavid du Colombier 
3553e12c5d1SDavid du Colombier convdig(int c)
3563e12c5d1SDavid du Colombier {
3573e12c5d1SDavid du Colombier 	if (isdigit(c))
3583e12c5d1SDavid du Colombier 		return(c-'0');
3593e12c5d1SDavid du Colombier 	else if (!isxdigit(c))
3603e12c5d1SDavid du Colombier 		return(MAXBASE);
3613e12c5d1SDavid du Colombier 	else if (isupper(c))
3623e12c5d1SDavid du Colombier 		return(c-'A'+10);
3633e12c5d1SDavid du Colombier 	else
3643e12c5d1SDavid du Colombier 		return(c-'a'+10);
3653e12c5d1SDavid du Colombier }
3663e12c5d1SDavid du Colombier 
3673e12c5d1SDavid du Colombier symchar(int dig)
3683e12c5d1SDavid du Colombier {
3693e12c5d1SDavid du Colombier 	if (lastc=='\\') {
3703e12c5d1SDavid du Colombier 		readchar();
3713e12c5d1SDavid du Colombier 		return(TRUE);
3723e12c5d1SDavid du Colombier 	}
3733e12c5d1SDavid du Colombier 	return(isalpha(lastc) || lastc=='_' || dig && isdigit(lastc));
3743e12c5d1SDavid du Colombier }
3753e12c5d1SDavid du Colombier 
3763e12c5d1SDavid du Colombier static long
3773e12c5d1SDavid du Colombier round(long a, long b)
3783e12c5d1SDavid du Colombier {
3793e12c5d1SDavid du Colombier 	long w;
3803e12c5d1SDavid du Colombier 
3813e12c5d1SDavid du Colombier 	w = (a/b)*b;
3823e12c5d1SDavid du Colombier 	if (a!=w)
3833e12c5d1SDavid du Colombier 		w += b;
3843e12c5d1SDavid du Colombier 	return(w);
3853e12c5d1SDavid du Colombier }
386