diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/db/expr.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/db/expr.c')
-rwxr-xr-x | sys/src/cmd/db/expr.c | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/sys/src/cmd/db/expr.c b/sys/src/cmd/db/expr.c new file mode 100755 index 000000000..d51079371 --- /dev/null +++ b/sys/src/cmd/db/expr.c @@ -0,0 +1,378 @@ +/* + * + * 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); +} |