/*
*
* debugger
*
*/
#include "defs.h"
#include "fns.h"
static long round(long, long);
extern ADDR ditto;
uvlong 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);
}
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 = round(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);
}
term(int a)
{ /* item | monadic item | (expr) | */
ADDR e;
switch ((int)readchar()) {
case '*':
term(a|1);
if (geta(cormap, expv, &e) < 0)
error("%r");
expv = e;
return(1);
case '@':
term(a|1);
if (geta(symmap, expv, &e) < 0)
error("%r");
expv = e;
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));
}
}
item(int a)
{ /* name [ . local ] | number | . | ^ | <register | 'x | | */
char *base;
char savc;
uvlong e;
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 */
expv = file2pc(gsym, expv);
if (expv == -1)
error("%r");
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, gsym, lsym, &e, rget) < 0)
error("%r");
expv = e;
}
else {
if (lookup(0, gsym, &s) == 0)
error("symbol not found");
expv = s.value;
}
reread();
} else if (getnum(readchar)) {
;
} else if (lastc=='.') {
readchar();
if (!symchar(0) && lastc != '.') {
expv = dot;
} else {
if (findsym(rget(cormap, mach->pc), CTEXT, &s) == 0)
error("no current function");
if (lastc == '.') {
lsym[0] = '.';
readchar();
readsym(lsym+1);
} else
readsym(lsym);
if (localaddr(cormap, s.name, lsym, &e, rget) < 0)
error("%r");
expv = e;
}
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 = rget(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 */
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();
}
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);
}
symchar(int dig)
{
if (lastc=='\\') {
readchar();
return(TRUE);
}
return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
}
static long
round(long a, long b)
{
long w;
w = (a/b)*b;
if (a!=w)
w += b;
return(w);
}
|