1*30118Ssam /* kdb_expr.c 7.2 86/11/20 */ 230107Ssam 330107Ssam #include "../kdb/defs.h" 430107Ssam 530107Ssam char *BADSYM; 630107Ssam char *BADVAR; 730107Ssam char *BADKET; 830107Ssam char *BADSYN; 930107Ssam char *NOCFN; 1030107Ssam char *NOADR; 1130107Ssam char *BADLOC; 1230107Ssam 1330107Ssam ADDR lastframe; 1430107Ssam ADDR savlastf; 1530107Ssam ADDR savframe; 1630107Ssam ADDR savpc; 1730107Ssam ADDR callpc; 1830107Ssam 1930107Ssam char *lp; 2030107Ssam int radix; 2130107Ssam char isymbol[1024]; 2230107Ssam 2330107Ssam char lastc, peekc; 2430107Ssam 2530107Ssam long ditto; 2630107Ssam long expv; 2730107Ssam 2830107Ssam /* term | term dyadic expr | */ 2930107Ssam expr(a) 3030107Ssam { 3130107Ssam register rc; 3230107Ssam register long lhs; 3330107Ssam 3430107Ssam rdc(); lp--; rc=term(a); 3530107Ssam 3630107Ssam while (rc) { 3730107Ssam lhs = expv; 3830107Ssam switch ((int)readchar()) { 3930107Ssam case '+': 4030107Ssam term(a|1); expv += lhs; break; 4130107Ssam case '-': 4230107Ssam term(a|1); expv = lhs - expv; break; 4330107Ssam case '#': 4430107Ssam term(a|1); expv = round(lhs,expv); break; 4530107Ssam case '*': 4630107Ssam term(a|1); expv *= lhs; break; 4730107Ssam case '%': 4830107Ssam term(a|1); expv = lhs/expv; break; 4930107Ssam case '&': 5030107Ssam term(a|1); expv &= lhs; break; 5130107Ssam case '|': 5230107Ssam term(a|1); expv |= lhs; break; 5330107Ssam case ')': 5430107Ssam if ((a&2)==0) 5530107Ssam error(BADKET); 5630107Ssam default: 5730107Ssam lp--; 5830107Ssam return (rc); 5930107Ssam } 6030107Ssam } 6130107Ssam return (rc); 6230107Ssam } 6330107Ssam 6430107Ssam /* item | monadic item | (expr) | */ 6530107Ssam static 6630107Ssam term(a) 6730107Ssam { 6830107Ssam 6930107Ssam switch ((int)readchar()) { 7030107Ssam case '*': 7130107Ssam term(a|1); expv=chkget(expv,DSP); 7230107Ssam return(1); 7330107Ssam case '@': 7430107Ssam term(a|1); expv=chkget(expv,ISP); 7530107Ssam return(1); 7630107Ssam case '-': 7730107Ssam term(a|1); expv = -expv; 7830107Ssam return(1); 7930107Ssam case '~': 8030107Ssam term(a|1); expv = ~expv; 8130107Ssam return(1); 8230107Ssam case '#': 8330107Ssam term(a|1); expv = !expv; 8430107Ssam return(1); 8530107Ssam case '(': 8630107Ssam expr(2); 8730107Ssam if (*lp!=')') 8830107Ssam error(BADSYN); 8930107Ssam lp++; 9030107Ssam return(1); 9130107Ssam } 9230107Ssam lp--; 9330107Ssam return (item(a)); 9430107Ssam } 9530107Ssam 9630107Ssam /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */ 9730107Ssam static 9830107Ssam item(a) 9930107Ssam { 10030107Ssam register base, d, regptr; 10130107Ssam char savc; 10230107Ssam register long frame; 10330107Ssam register struct nlist *symp; 10430107Ssam 10530107Ssam readchar(); 10630107Ssam if (symchar(0)) { 10730107Ssam readsym(); 10830107Ssam if (lastc=='.') { 10930107Ssam frame = pcb.pcb_fp; lastframe = 0; 11030107Ssam callpc= pcb.pcb_pc; 11130107Ssam while (errflg==0) { 11230107Ssam savpc=callpc; 11330107Ssam findsym(callpc,ISYM); 11430107Ssam if (eqsym(cursym->n_un.n_name,isymbol,'~')) 11530107Ssam break; 11630107Ssam callpc=get(frame-8, DSP); 11730107Ssam lastframe=frame; 11830107Ssam frame=get(frame, DSP)&ALIGN; 11930107Ssam if (frame==0) 12030107Ssam error(NOCFN); 12130107Ssam } 12230107Ssam savlastf=lastframe; savframe=frame; 12330107Ssam readchar(); 12430107Ssam if (symchar(0)) 12530107Ssam chkloc(expv=frame); 12630107Ssam } else if ((symp=lookup(isymbol))==0) 12730107Ssam error(BADSYM); 12830107Ssam else 12930107Ssam expv = symp->n_value; 13030107Ssam lp--; 13130107Ssam } else if (getnum()) 13230107Ssam ; 13330107Ssam else if (lastc=='.') { 13430107Ssam readchar(); 13530107Ssam if (symchar(0)) { 13630107Ssam lastframe=savlastf; callpc=savpc; 13730107Ssam chkloc(savframe); 13830107Ssam } else 13930107Ssam expv=dot; 14030107Ssam lp--; 14130107Ssam } else if (lastc=='"') 14230107Ssam expv=ditto; 14330107Ssam else if (lastc=='+') 14430107Ssam expv=inkdot(dotinc); 14530107Ssam else if (lastc=='^') 14630107Ssam expv=inkdot(-dotinc); 14730107Ssam else if (lastc=='<') { 14830107Ssam savc=rdc(); 14930107Ssam if ((regptr=getreg(savc)) != -1) 15030107Ssam expv = *(int *)regptr; 15130107Ssam else if ((base=varchk(savc)) != -1) 15230107Ssam expv=var[base]; 15330107Ssam else 15430107Ssam error(BADVAR); 15530107Ssam } else if (lastc=='\'') { 15630107Ssam d=4; expv=0; 15730107Ssam while (quotchar()) { 15830107Ssam if (d--) { 15930107Ssam expv <<= 8; 16030107Ssam expv |= lastc; 16130107Ssam } else 16230107Ssam error(BADSYN); 16330107Ssam } 16430107Ssam } else if (a) 16530107Ssam error(NOADR); 16630107Ssam else { 16730107Ssam lp--; 16830107Ssam return(0); 16930107Ssam } 17030107Ssam return (1); 17130107Ssam } 17230107Ssam 17330107Ssam /* service routines for expression reading */ 17430107Ssam static 17530107Ssam getnum() 17630107Ssam { 17730107Ssam register base,d,frpt; 17830107Ssam union { float r; long i;} real; 17930107Ssam 18030107Ssam if (!isdigit(lastc)) 18130107Ssam return (0); 18230107Ssam if ((base = radix) < 0) 18330107Ssam base = -base; 18430107Ssam expv = 0; 18530107Ssam while (base>10 ? isxdigit(lastc) : isdigit(lastc)) { 18630107Ssam register m = MAXINT/base; 18730107Ssam 18830107Ssam if (expv>m) /* avoid overflow */ 18930107Ssam expv = (expv-m)*base+m*base; 19030107Ssam else 19130107Ssam expv *= base; 19230107Ssam if ((d=convdig(lastc))>=base || d<0) 19330107Ssam error(BADSYN); 19430107Ssam expv += d; readchar(); 19530107Ssam if (expv==0) { 19630107Ssam if (lastc=='x' || lastc=='X') { 19730107Ssam base=16; readchar(); 19830107Ssam } else if (lastc=='t' || lastc=='T') { 19930107Ssam base=10; readchar(); 20030107Ssam } else if (lastc=='o' || lastc=='O') { 20130107Ssam base=8; readchar(); 20230107Ssam } 20330107Ssam } 20430107Ssam } 20530107Ssam if (lastc=='.' && (base==10 || expv==0)) { 20630107Ssam real.r=expv; frpt=0; base=10; 20730107Ssam while (isdigit(readchar())) { 20830107Ssam real.r *= base; frpt++; 20930107Ssam real.r += lastc-'0'; 21030107Ssam } 21130107Ssam while (frpt--) 21230107Ssam real.r /= base; 21330107Ssam expv = real.i; 21430107Ssam } 21530107Ssam peekc=lastc; 21630107Ssam return (1); 21730107Ssam } 21830107Ssam 21930107Ssam static 22030107Ssam readsym() 22130107Ssam { 22230107Ssam register char *p; 22330107Ssam 22430107Ssam p = isymbol; 22530107Ssam do { 22630107Ssam if (p < &isymbol[sizeof(isymbol)-1]) 22730107Ssam *p++ = lastc; 22830107Ssam readchar(); 22930107Ssam } while (symchar(1)); 23030107Ssam *p++ = 0; 23130107Ssam } 23230107Ssam 23330107Ssam static 23430107Ssam convdig(c) 23530107Ssam char c; 23630107Ssam { 23730107Ssam if (isdigit(c)) 23830107Ssam return (c-'0'); 23930107Ssam if (isxdigit(c)) 24030107Ssam return (c-'a'+10); 24130107Ssam return (-1); 24230107Ssam } 24330107Ssam 24430107Ssam static 24530107Ssam symchar(dig) 24630107Ssam { 24730107Ssam 24830107Ssam if (lastc=='\\') { 24930107Ssam readchar(); 250*30118Ssam return (1); 25130107Ssam } 25230107Ssam return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc)); 25330107Ssam } 25430107Ssam 25530107Ssam varchk(name) 25630107Ssam register name; 25730107Ssam { 25830107Ssam if (isdigit(name)) 25930107Ssam return (name-'0'); 26030107Ssam if (isalpha(name)) 26130107Ssam return ((name&037)-1+10); 26230107Ssam return (-1); 26330107Ssam } 26430107Ssam 26530107Ssam static 26630107Ssam chkloc(frame) 26730107Ssam long frame; 26830107Ssam { 26930107Ssam 27030107Ssam readsym(); 27130107Ssam do { 27230107Ssam if (localsym(frame)==0) 27330107Ssam error(BADLOC); 27430107Ssam expv=localval; 27530107Ssam } while (!eqsym(cursym->n_un.n_name,isymbol,'~')); 27630107Ssam } 27730107Ssam 27830107Ssam eqsym(s1, s2, c) 27930107Ssam register char *s1, *s2; 28030107Ssam { 28130107Ssam 28230107Ssam if (streq(s1,s2)) 28330107Ssam return (1); 28430107Ssam if (*s1 == c && streq(s1+1, s2)) 28530107Ssam return (1); 28630107Ssam return (0); 28730107Ssam } 28830107Ssam 28930107Ssam static 29030107Ssam streq(s1, s2) 29130107Ssam char *s1, *s2; 29230107Ssam { 29330107Ssam 29430107Ssam while (*s1 == *s2++) 29530107Ssam if (*s1++ == '\0') 29630107Ssam return (1); 29730107Ssam return (0); 29830107Ssam } 29930107Ssam 30030107Ssam static 30130107Ssam round(a,b) 30230107Ssam register long a, b; 30330107Ssam { 30430107Ssam register long w; 30530107Ssam 30630107Ssam w = (a/b)*b; 30730107Ssam if (a!=w) 30830107Ssam w += b; 30930107Ssam return (w); 31030107Ssam } 311