| /* | 
 |  * | 
 |  *	debugger | 
 |  * | 
 |  */ | 
 |  | 
 | #include "defs.h" | 
 | #include "fns.h" | 
 |  | 
 | static long	dbround(long, long); | 
 |  | 
 | extern	ADDR	ditto; | 
 | vlong	expv; | 
 |  | 
 | static WORD | 
 | ascval(void) | 
 | { | 
 | 	Rune r; | 
 |  | 
 | 	if (readchar() == 0) | 
 | 		return (0); | 
 | 	r = lastc; | 
 | 	while(quotchar())	/*discard chars to ending quote */ | 
 | 		; | 
 | 	return((WORD) r); | 
 | } | 
 |  | 
 | /* | 
 |  * read a floating point number | 
 |  * the result must fit in a WORD | 
 |  */ | 
 |  | 
 | static WORD | 
 | fpin(char *buf) | 
 | { | 
 | 	union { | 
 | 		WORD w; | 
 | 		float f; | 
 | 	} x; | 
 |  | 
 | 	x.f = atof(buf); | 
 | 	return (x.w); | 
 | } | 
 |  | 
 | WORD | 
 | defval(WORD w) | 
 | { | 
 | 	if (expr(0)) | 
 | 		return (expv); | 
 | 	else | 
 | 		return (w); | 
 | } | 
 |  | 
 | int | 
 | expr(int a) | 
 | {	/* term | term dyadic expr |  */ | 
 | 	int	rc; | 
 | 	WORD	lhs; | 
 |  | 
 | 	rdc(); | 
 | 	reread(); | 
 | 	rc=term(a); | 
 | 	while (rc) { | 
 | 		lhs = expv; | 
 | 		switch ((int)readchar()) { | 
 |  | 
 | 		case '+': | 
 | 			term(a|1); | 
 | 			expv += lhs; | 
 | 			break; | 
 |  | 
 | 		case '-': | 
 | 			term(a|1); | 
 | 			expv = lhs - expv; | 
 | 			break; | 
 |  | 
 | 		case '#': | 
 | 			term(a|1); | 
 | 			expv = dbround(lhs,expv); | 
 | 			break; | 
 |  | 
 | 		case '*': | 
 | 			term(a|1); | 
 | 			expv *= lhs; | 
 | 			break; | 
 |  | 
 | 		case '%': | 
 | 			term(a|1); | 
 | 			if(expv != 0) | 
 | 				expv = lhs/expv; | 
 | 			else{ | 
 | 				if(lhs) | 
 | 					expv = 1; | 
 | 				else | 
 | 					expv = 0; | 
 | 			} | 
 | 			break; | 
 |  | 
 | 		case '&': | 
 | 			term(a|1); | 
 | 			expv &= lhs; | 
 | 			break; | 
 |  | 
 | 		case '|': | 
 | 			term(a|1); | 
 | 			expv |= lhs; | 
 | 			break; | 
 |  | 
 | 		case ')': | 
 | 			if ((a&2)==0) | 
 | 				error("unexpected `)'"); | 
 |  | 
 | 		default: | 
 | 			reread(); | 
 | 			return(rc); | 
 | 		} | 
 | 	} | 
 | 	return(rc); | 
 | } | 
 |  | 
 | int | 
 | term(int a) | 
 | {	/* item | monadic item | (expr) | */ | 
 | 	u32int u; | 
 |  | 
 | 	switch ((int)readchar()) { | 
 |  | 
 | 	case '*': | 
 | 		term(a|1); | 
 | 		if (get4(cormap, (ADDR)expv, &u) < 0) | 
 | 			error("%r"); | 
 | 		expv = u; | 
 | 		return(1); | 
 |  | 
 | 	case '@': | 
 | 		term(a|1); | 
 | 		if (get4(symmap, (ADDR)expv, &u) < 0) | 
 | 			error("%r"); | 
 | 		expv = u; | 
 | 		return(1); | 
 |  | 
 | 	case '-': | 
 | 		term(a|1); | 
 | 		expv = -expv; | 
 | 		return(1); | 
 |  | 
 | 	case '~': | 
 | 		term(a|1); | 
 | 		expv = ~expv; | 
 | 		return(1); | 
 |  | 
 | 	case '(': | 
 | 		expr(2); | 
 | 		if (readchar()!=')') | 
 | 			error("syntax error: `)' expected"); | 
 | 		return(1); | 
 |  | 
 | 	default: | 
 | 		reread(); | 
 | 		return(item(a)); | 
 | 	} | 
 | } | 
 |  | 
 | int | 
 | item(int a) | 
 | {	/* name [ . local ] | number | . | ^  | <register | 'x | | */ | 
 | 	char	*base; | 
 | 	char	savc; | 
 | 	u64int u; | 
 | 	Symbol s; | 
 | 	char gsym[MAXSYM], lsym[MAXSYM]; | 
 |  | 
 | 	readchar(); | 
 | 	if (isfileref()) { | 
 | 		readfname(gsym); | 
 | 		rdc();			/* skip white space */ | 
 | 		if (lastc == ':') {	/* it better be */ | 
 | 			rdc();		/* skip white space */ | 
 | 			if (!getnum(readchar)) | 
 | 				error("bad number"); | 
 | 			if (expv == 0) | 
 | 				expv = 1;	/* file begins at line 1 */ | 
 | 			if(file2pc(gsym, expv, &u) < 0) | 
 | 				error("%r"); | 
 | 			expv = u; | 
 | 			return 1; | 
 | 		} | 
 | 		error("bad file location"); | 
 | 	} else if (symchar(0)) {	 | 
 | 		readsym(gsym); | 
 | 		if (lastc=='.') { | 
 | 			readchar();	/* ugh */ | 
 | 			if (lastc == '.') { | 
 | 				lsym[0] = '.'; | 
 | 				readchar(); | 
 | 				readsym(lsym+1); | 
 | 			} else if (symchar(0)) { | 
 | 				readsym(lsym); | 
 | 			} else | 
 | 				lsym[0] = 0; | 
 | 			if (localaddr(cormap, correg, gsym, lsym, &u) < 0) | 
 | 				error("%r"); | 
 | 			expv = u; | 
 | 		} | 
 | 		else { | 
 | 			if (lookupsym(0, gsym, &s) < 0) | 
 | 				error("symbol not found"); | 
 | 			if (s.loc.type != LADDR) | 
 | 				error("symbol not kept in memory"); | 
 | 			expv = s.loc.addr; | 
 | 		} | 
 | 		reread(); | 
 | 	} else if (getnum(readchar)) { | 
 | 		; | 
 | 	} else if (lastc=='.') {	 | 
 | 		readchar(); | 
 | 		if (!symchar(0) && lastc != '.') { | 
 | 			expv = dot; | 
 | 		} else { | 
 | 			if (findsym(locaddr(dbrget(cormap, mach->pc)), CTEXT, &s) < 0) | 
 | 				error("no current function"); | 
 | 			if (lastc == '.') { | 
 | 				lsym[0] = '.'; | 
 | 				readchar(); | 
 | 				readsym(lsym+1); | 
 | 			} else | 
 | 				readsym(lsym); | 
 | 			if (localaddr(cormap, correg, s.name, lsym, &u) < 0) | 
 | 				error("%r"); | 
 | 			expv = u; | 
 | 		}	 | 
 | 		reread(); | 
 | 	} else if (lastc=='"') { | 
 | 		expv=ditto; | 
 | 	} else if (lastc=='+') { | 
 | 		expv=inkdot(dotinc); | 
 | 	} else if (lastc=='^') { | 
 | 		expv=inkdot(-dotinc); | 
 | 	} else if (lastc=='<') { | 
 | 		savc=rdc(); | 
 | 		base = regname(savc); | 
 | 		expv = dbrget(cormap, base); | 
 | 	} | 
 | 	else if (lastc=='\'') | 
 | 		expv = ascval(); | 
 | 	else if (a) | 
 | 		error("address expected"); | 
 | 	else {	 | 
 | 		reread(); | 
 | 		return(0); | 
 | 	} | 
 | 	return(1); | 
 | } | 
 |  | 
 | #define	MAXBASE	16 | 
 |  | 
 | /* service routines for expression reading */ | 
 | int | 
 | getnum(int (*rdf)(void)) | 
 | { | 
 | 	char *cp; | 
 | 	int base, d; | 
 | 	BOOL fpnum; | 
 | 	char num[MAXLIN]; | 
 |  | 
 | 	base = 0; | 
 | 	fpnum = FALSE; | 
 | 	if (lastc == '#') { | 
 | 		base = 16; | 
 | 		(*rdf)(); | 
 | 	} | 
 | 	if (convdig(lastc) >= MAXBASE) | 
 | 		return (0); | 
 | 	if (lastc == '0') | 
 | 		switch ((*rdf)()) { | 
 | 		case 'x': | 
 | 		case 'X': | 
 | 			base = 16; | 
 | 			(*rdf)(); | 
 | 			break; | 
 |  | 
 | 		case 't': | 
 | 		case 'T': | 
 | 			base = 10; | 
 | 			(*rdf)(); | 
 | 			break; | 
 |  | 
 | 		case 'o': | 
 | 		case 'O': | 
 | 			base = 8; | 
 | 			(*rdf)(); | 
 | 			break; | 
 | 		default: | 
 | 			if (base == 0) | 
 | 				base = 8; | 
 | 			break; | 
 | 		} | 
 | 	if (base == 0) | 
 | 		base = 10; | 
 | 	expv = 0; | 
 | 	for (cp = num, *cp = lastc; ;(*rdf)()) { | 
 | 		if ((d = convdig(lastc)) < base) { | 
 | 			expv *= base; | 
 | 			expv += d; | 
 | 			*cp++ = lastc; | 
 | 		} | 
 | 		else if (lastc == '.') { | 
 | 			fpnum = TRUE; | 
 | 			*cp++ = lastc; | 
 | 		} else { | 
 | 			reread(); | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | 	if (fpnum) | 
 | 		expv = fpin(num); | 
 | 	return (1); | 
 | } | 
 |  | 
 | void | 
 | readsym(char *isymbol) | 
 | { | 
 | 	char	*p; | 
 | 	Rune r; | 
 |  | 
 | 	p = isymbol; | 
 | 	do { | 
 | 		if (p < &isymbol[MAXSYM-UTFmax-1]){ | 
 | 			r = lastc; | 
 | 			p += runetochar(p, &r); | 
 | 		} | 
 | 		readchar(); | 
 | 	} while (symchar(1)); | 
 | 	*p = 0; | 
 | } | 
 |  | 
 | void | 
 | readfname(char *filename) | 
 | { | 
 | 	char	*p; | 
 | 	Rune	c; | 
 |  | 
 | 	/* snarf chars until un-escaped char in terminal char set */ | 
 | 	p = filename; | 
 | 	do { | 
 | 		if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1]) | 
 | 			p += runetochar(p, &c); | 
 | 		readchar(); | 
 | 	} while (c == '\\' || strchr(CMD_VERBS, lastc) == 0); | 
 | 	*p = 0; | 
 | 	reread(); | 
 | } | 
 |  | 
 | int | 
 | convdig(int c) | 
 | { | 
 | 	if (isdigit(c)) | 
 | 		return(c-'0'); | 
 | 	else if (!isxdigit(c)) | 
 | 		return(MAXBASE); | 
 | 	else if (isupper(c)) | 
 | 		return(c-'A'+10); | 
 | 	else | 
 | 		return(c-'a'+10); | 
 | } | 
 |  | 
 | int | 
 | symchar(int dig) | 
 | { | 
 | 	if (lastc=='\\') { | 
 | 		readchar(); | 
 | 		return(TRUE); | 
 | 	} | 
 | 	return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc)); | 
 | } | 
 |  | 
 | static long | 
 | dbround(long a, long b) | 
 | { | 
 | 	long w; | 
 |  | 
 | 	w = (a/b)*b; | 
 | 	if (a!=w) | 
 | 		w += b; | 
 | 	return(w); | 
 | } | 
 |  | 
 | ulong | 
 | dbrget(Map *map, char *name) | 
 | { | 
 | 	u64int u; | 
 |  | 
 | 	USED(map); | 
 | 	if(rget(correg, name, &u) < 0) | 
 | 		return ~(ulong)0; | 
 | 	return u; | 
 | } |