plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

expr.c (5694B)


      1 /*
      2  *
      3  *	debugger
      4  *
      5  */
      6 
      7 #include "defs.h"
      8 #include "fns.h"
      9 
     10 static long	dbround(long, long);
     11 
     12 extern	ADDR	ditto;
     13 vlong	expv;
     14 
     15 static WORD
     16 ascval(void)
     17 {
     18 	Rune r;
     19 
     20 	if (readchar() == 0)
     21 		return (0);
     22 	r = lastc;
     23 	while(quotchar())	/*discard chars to ending quote */
     24 		;
     25 	return((WORD) r);
     26 }
     27 
     28 /*
     29  * read a floating point number
     30  * the result must fit in a WORD
     31  */
     32 
     33 static WORD
     34 fpin(char *buf)
     35 {
     36 	union {
     37 		WORD w;
     38 		float f;
     39 	} x;
     40 
     41 	x.f = atof(buf);
     42 	return (x.w);
     43 }
     44 
     45 WORD
     46 defval(WORD w)
     47 {
     48 	if (expr(0))
     49 		return (expv);
     50 	else
     51 		return (w);
     52 }
     53 
     54 int
     55 expr(int a)
     56 {	/* term | term dyadic expr |  */
     57 	int	rc;
     58 	WORD	lhs;
     59 
     60 	rdc();
     61 	reread();
     62 	rc=term(a);
     63 	while (rc) {
     64 		lhs = expv;
     65 		switch ((int)readchar()) {
     66 
     67 		case '+':
     68 			term(a|1);
     69 			expv += lhs;
     70 			break;
     71 
     72 		case '-':
     73 			term(a|1);
     74 			expv = lhs - expv;
     75 			break;
     76 
     77 		case '#':
     78 			term(a|1);
     79 			expv = dbround(lhs,expv);
     80 			break;
     81 
     82 		case '*':
     83 			term(a|1);
     84 			expv *= lhs;
     85 			break;
     86 
     87 		case '%':
     88 			term(a|1);
     89 			if(expv != 0)
     90 				expv = lhs/expv;
     91 			else{
     92 				if(lhs)
     93 					expv = 1;
     94 				else
     95 					expv = 0;
     96 			}
     97 			break;
     98 
     99 		case '&':
    100 			term(a|1);
    101 			expv &= lhs;
    102 			break;
    103 
    104 		case '|':
    105 			term(a|1);
    106 			expv |= lhs;
    107 			break;
    108 
    109 		case ')':
    110 			if ((a&2)==0)
    111 				error("unexpected `)'");
    112 
    113 		default:
    114 			reread();
    115 			return(rc);
    116 		}
    117 	}
    118 	return(rc);
    119 }
    120 
    121 int
    122 term(int a)
    123 {	/* item | monadic item | (expr) | */
    124 	u32int u;
    125 
    126 	switch ((int)readchar()) {
    127 
    128 	case '*':
    129 		term(a|1);
    130 		if (get4(cormap, (ADDR)expv, &u) < 0)
    131 			error("%r");
    132 		expv = u;
    133 		return(1);
    134 
    135 	case '@':
    136 		term(a|1);
    137 		if (get4(symmap, (ADDR)expv, &u) < 0)
    138 			error("%r");
    139 		expv = u;
    140 		return(1);
    141 
    142 	case '-':
    143 		term(a|1);
    144 		expv = -expv;
    145 		return(1);
    146 
    147 	case '~':
    148 		term(a|1);
    149 		expv = ~expv;
    150 		return(1);
    151 
    152 	case '(':
    153 		expr(2);
    154 		if (readchar()!=')')
    155 			error("syntax error: `)' expected");
    156 		return(1);
    157 
    158 	default:
    159 		reread();
    160 		return(item(a));
    161 	}
    162 }
    163 
    164 int
    165 item(int a)
    166 {	/* name [ . local ] | number | . | ^  | <register | 'x | | */
    167 	char	*base;
    168 	char	savc;
    169 	u64int u;
    170 	Symbol s;
    171 	char gsym[MAXSYM], lsym[MAXSYM];
    172 
    173 	readchar();
    174 	if (isfileref()) {
    175 		readfname(gsym);
    176 		rdc();			/* skip white space */
    177 		if (lastc == ':') {	/* it better be */
    178 			rdc();		/* skip white space */
    179 			if (!getnum(readchar))
    180 				error("bad number");
    181 			if (expv == 0)
    182 				expv = 1;	/* file begins at line 1 */
    183 			if(file2pc(gsym, expv, &u) < 0)
    184 				error("%r");
    185 			expv = u;
    186 			return 1;
    187 		}
    188 		error("bad file location");
    189 	} else if (symchar(0)) {
    190 		readsym(gsym);
    191 		if (lastc=='.') {
    192 			readchar();	/* ugh */
    193 			if (lastc == '.') {
    194 				lsym[0] = '.';
    195 				readchar();
    196 				readsym(lsym+1);
    197 			} else if (symchar(0)) {
    198 				readsym(lsym);
    199 			} else
    200 				lsym[0] = 0;
    201 			if (localaddr(cormap, correg, gsym, lsym, &u) < 0)
    202 				error("%r");
    203 			expv = u;
    204 		}
    205 		else {
    206 			if (lookupsym(0, gsym, &s) < 0)
    207 				error("symbol not found");
    208 			if (s.loc.type != LADDR)
    209 				error("symbol not kept in memory");
    210 			expv = s.loc.addr;
    211 		}
    212 		reread();
    213 	} else if (getnum(readchar)) {
    214 		;
    215 	} else if (lastc=='.') {
    216 		readchar();
    217 		if (!symchar(0) && lastc != '.') {
    218 			expv = dot;
    219 		} else {
    220 			if (findsym(locaddr(dbrget(cormap, mach->pc)), CTEXT, &s) < 0)
    221 				error("no current function");
    222 			if (lastc == '.') {
    223 				lsym[0] = '.';
    224 				readchar();
    225 				readsym(lsym+1);
    226 			} else
    227 				readsym(lsym);
    228 			if (localaddr(cormap, correg, s.name, lsym, &u) < 0)
    229 				error("%r");
    230 			expv = u;
    231 		}
    232 		reread();
    233 	} else if (lastc=='"') {
    234 		expv=ditto;
    235 	} else if (lastc=='+') {
    236 		expv=inkdot(dotinc);
    237 	} else if (lastc=='^') {
    238 		expv=inkdot(-dotinc);
    239 	} else if (lastc=='<') {
    240 		savc=rdc();
    241 		base = regname(savc);
    242 		expv = dbrget(cormap, base);
    243 	}
    244 	else if (lastc=='\'')
    245 		expv = ascval();
    246 	else if (a)
    247 		error("address expected");
    248 	else {
    249 		reread();
    250 		return(0);
    251 	}
    252 	return(1);
    253 }
    254 
    255 #define	MAXBASE	16
    256 
    257 /* service routines for expression reading */
    258 int
    259 getnum(int (*rdf)(void))
    260 {
    261 	char *cp;
    262 	int base, d;
    263 	BOOL fpnum;
    264 	char num[MAXLIN];
    265 
    266 	base = 0;
    267 	fpnum = FALSE;
    268 	if (lastc == '#') {
    269 		base = 16;
    270 		(*rdf)();
    271 	}
    272 	if (convdig(lastc) >= MAXBASE)
    273 		return (0);
    274 	if (lastc == '0')
    275 		switch ((*rdf)()) {
    276 		case 'x':
    277 		case 'X':
    278 			base = 16;
    279 			(*rdf)();
    280 			break;
    281 
    282 		case 't':
    283 		case 'T':
    284 			base = 10;
    285 			(*rdf)();
    286 			break;
    287 
    288 		case 'o':
    289 		case 'O':
    290 			base = 8;
    291 			(*rdf)();
    292 			break;
    293 		default:
    294 			if (base == 0)
    295 				base = 8;
    296 			break;
    297 		}
    298 	if (base == 0)
    299 		base = 10;
    300 	expv = 0;
    301 	for (cp = num, *cp = lastc; ;(*rdf)()) {
    302 		if ((d = convdig(lastc)) < base) {
    303 			expv *= base;
    304 			expv += d;
    305 			*cp++ = lastc;
    306 		}
    307 		else if (lastc == '.') {
    308 			fpnum = TRUE;
    309 			*cp++ = lastc;
    310 		} else {
    311 			reread();
    312 			break;
    313 		}
    314 	}
    315 	if (fpnum)
    316 		expv = fpin(num);
    317 	return (1);
    318 }
    319 
    320 void
    321 readsym(char *isymbol)
    322 {
    323 	char	*p;
    324 	Rune r;
    325 
    326 	p = isymbol;
    327 	do {
    328 		if (p < &isymbol[MAXSYM-UTFmax-1]){
    329 			r = lastc;
    330 			p += runetochar(p, &r);
    331 		}
    332 		readchar();
    333 	} while (symchar(1));
    334 	*p = 0;
    335 }
    336 
    337 void
    338 readfname(char *filename)
    339 {
    340 	char	*p;
    341 	Rune	c;
    342 
    343 	/* snarf chars until un-escaped char in terminal char set */
    344 	p = filename;
    345 	do {
    346 		if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1])
    347 			p += runetochar(p, &c);
    348 		readchar();
    349 	} while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
    350 	*p = 0;
    351 	reread();
    352 }
    353 
    354 int
    355 convdig(int c)
    356 {
    357 	if (isdigit(c))
    358 		return(c-'0');
    359 	else if (!isxdigit(c))
    360 		return(MAXBASE);
    361 	else if (isupper(c))
    362 		return(c-'A'+10);
    363 	else
    364 		return(c-'a'+10);
    365 }
    366 
    367 int
    368 symchar(int dig)
    369 {
    370 	if (lastc=='\\') {
    371 		readchar();
    372 		return(TRUE);
    373 	}
    374 	return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
    375 }
    376 
    377 static long
    378 dbround(long a, long b)
    379 {
    380 	long w;
    381 
    382 	w = (a/b)*b;
    383 	if (a!=w)
    384 		w += b;
    385 	return(w);
    386 }
    387 
    388 ulong
    389 dbrget(Map *map, char *name)
    390 {
    391 	u64int u;
    392 
    393 	USED(map);
    394 	if(rget(correg, name, &u) < 0)
    395 		return ~(ulong)0;
    396 	return u;
    397 }