379 lines
5.3 KiB
C
379 lines
5.3 KiB
C
/*
|
|
*
|
|
* 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);
|
|
}
|