ref: fe1eb39db7ae6904924f3ab1f6f9b34416f2eb1b
dir: /sys/src/cmd/db/expr.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); }