1*30296Ssam /* 2*30296Ssam * Copyright (c) 1986 Regents of the University of California. 3*30296Ssam * All rights reserved. The Berkeley software License Agreement 4*30296Ssam * specifies the terms and conditions for redistribution. 5*30296Ssam * 6*30296Ssam * @(#)kdb_expr.c 7.4 (Berkeley) 12/15/86 7*30296Ssam */ 830107Ssam 930107Ssam #include "../kdb/defs.h" 1030107Ssam 1130107Ssam char *BADSYM; 1230107Ssam char *BADVAR; 1330107Ssam char *BADKET; 1430107Ssam char *BADSYN; 1530107Ssam char *NOCFN; 1630107Ssam char *NOADR; 1730107Ssam char *BADLOC; 1830107Ssam 1930107Ssam ADDR lastframe; 2030107Ssam ADDR savlastf; 2130107Ssam ADDR savframe; 2230107Ssam ADDR savpc; 2330107Ssam ADDR callpc; 2430107Ssam 2530107Ssam char *lp; 2630107Ssam int radix; 2730107Ssam char isymbol[1024]; 2830107Ssam 2930107Ssam char lastc, peekc; 3030107Ssam 3130107Ssam long ditto; 3230107Ssam long expv; 3330107Ssam 34*30296Ssam static long 35*30296Ssam round(a,b) 36*30296Ssam register long a, b; 37*30296Ssam { 38*30296Ssam register long w; 39*30296Ssam 40*30296Ssam w = (a/b)*b; 41*30296Ssam if (a!=w) 42*30296Ssam w += b; 43*30296Ssam return (w); 44*30296Ssam } 45*30296Ssam 4630107Ssam /* term | term dyadic expr | */ 4730107Ssam expr(a) 4830107Ssam { 4930107Ssam register rc; 5030107Ssam register long lhs; 5130107Ssam 52*30296Ssam (void) rdc(); lp--; rc=term(a); 5330107Ssam 5430107Ssam while (rc) { 5530107Ssam lhs = expv; 5630107Ssam switch ((int)readchar()) { 5730107Ssam case '+': 58*30296Ssam (void) term(a|1); expv += lhs; break; 5930107Ssam case '-': 60*30296Ssam (void) term(a|1); expv = lhs - expv; break; 6130107Ssam case '#': 62*30296Ssam (void) term(a|1); expv = round(lhs,expv); break; 6330107Ssam case '*': 64*30296Ssam (void) term(a|1); expv *= lhs; break; 6530107Ssam case '%': 66*30296Ssam (void) term(a|1); expv = lhs/expv; break; 6730107Ssam case '&': 68*30296Ssam (void) term(a|1); expv &= lhs; break; 6930107Ssam case '|': 70*30296Ssam (void) term(a|1); expv |= lhs; break; 7130107Ssam case ')': 7230107Ssam if ((a&2)==0) 7330107Ssam error(BADKET); 7430107Ssam default: 7530107Ssam lp--; 7630107Ssam return (rc); 7730107Ssam } 7830107Ssam } 7930107Ssam return (rc); 8030107Ssam } 8130107Ssam 8230107Ssam /* item | monadic item | (expr) | */ 8330107Ssam static 8430107Ssam term(a) 8530107Ssam { 8630107Ssam 8730107Ssam switch ((int)readchar()) { 8830107Ssam case '*': 89*30296Ssam (void) term(a|1); expv=chkget(expv,DSP); 9030107Ssam return(1); 9130107Ssam case '@': 92*30296Ssam (void) term(a|1); expv=chkget(expv,ISP); 9330107Ssam return(1); 9430107Ssam case '-': 95*30296Ssam (void) term(a|1); expv = -expv; 9630107Ssam return(1); 9730107Ssam case '~': 98*30296Ssam (void) term(a|1); expv = ~expv; 9930107Ssam return(1); 10030107Ssam case '#': 101*30296Ssam (void) term(a|1); expv = !expv; 10230107Ssam return(1); 10330107Ssam case '(': 104*30296Ssam (void) expr(2); 10530107Ssam if (*lp!=')') 10630107Ssam error(BADSYN); 10730107Ssam lp++; 10830107Ssam return(1); 10930107Ssam } 11030107Ssam lp--; 11130107Ssam return (item(a)); 11230107Ssam } 11330107Ssam 11430107Ssam /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */ 11530107Ssam static 11630107Ssam item(a) 11730107Ssam { 11830107Ssam register base, d, regptr; 11930107Ssam char savc; 12030107Ssam register long frame; 12130107Ssam register struct nlist *symp; 12230107Ssam 123*30296Ssam (void) readchar(); 12430107Ssam if (symchar(0)) { 12530107Ssam readsym(); 12630107Ssam if (lastc=='.') { 12730107Ssam frame = pcb.pcb_fp; lastframe = 0; 12830136Ssam callpc = pcb.pcb_pc; 12930136Ssam while (!errflg) { 13030136Ssam savpc = callpc; 131*30296Ssam (void) findsym((long)callpc,ISYM); 13230136Ssam if (eqsym(cursym->n_un.n_name,isymbol,'~')) 13330136Ssam break; 13430136Ssam callpc = getprevpc(frame); 13530136Ssam lastframe = frame; 13630136Ssam frame = getprevframe(frame); 13730136Ssam if (frame == NOFRAME) 13830136Ssam error(NOCFN); 13930107Ssam } 14030136Ssam savlastf = lastframe; savframe = frame; 141*30296Ssam (void) readchar(); 14230107Ssam if (symchar(0)) 14330107Ssam chkloc(expv=frame); 14430107Ssam } else if ((symp=lookup(isymbol))==0) 14530107Ssam error(BADSYM); 14630107Ssam else 14730107Ssam expv = symp->n_value; 14830107Ssam lp--; 14930136Ssam return (1); 15030136Ssam } 15130136Ssam if (getnum()) 15230136Ssam return (1); 15330136Ssam switch (lastc) { 15430136Ssam case '.': 155*30296Ssam (void) readchar(); 15630107Ssam if (symchar(0)) { 15730107Ssam lastframe=savlastf; callpc=savpc; 158*30296Ssam chkloc((long)savframe); 15930107Ssam } else 16030107Ssam expv=dot; 16130107Ssam lp--; 16230136Ssam break; 16330136Ssam case '"': 16430107Ssam expv=ditto; 16530136Ssam break; 16630136Ssam case '+': 16730107Ssam expv=inkdot(dotinc); 16830136Ssam break; 16930136Ssam case '^': 17030107Ssam expv=inkdot(-dotinc); 17130136Ssam break; 17230136Ssam case '<': 17330107Ssam savc=rdc(); 17430107Ssam if ((regptr=getreg(savc)) != -1) 17530107Ssam expv = *(int *)regptr; 17630107Ssam else if ((base=varchk(savc)) != -1) 17730107Ssam expv=var[base]; 17830107Ssam else 17930107Ssam error(BADVAR); 18030136Ssam break; 18130136Ssam case '\'': 18230107Ssam d=4; expv=0; 18330107Ssam while (quotchar()) { 18430107Ssam if (d--) { 18530107Ssam expv <<= 8; 18630107Ssam expv |= lastc; 18730107Ssam } else 18830107Ssam error(BADSYN); 18930107Ssam } 19030136Ssam break; 19130136Ssam default: 19230136Ssam if (a) 19330136Ssam error(NOADR); 19430107Ssam lp--; 19530107Ssam return(0); 19630107Ssam } 19730107Ssam return (1); 19830107Ssam } 19930107Ssam 20030107Ssam /* service routines for expression reading */ 20130107Ssam static 20230107Ssam getnum() 20330107Ssam { 20430107Ssam register base,d,frpt; 20530107Ssam union { float r; long i;} real; 20630107Ssam 20730107Ssam if (!isdigit(lastc)) 20830107Ssam return (0); 20930107Ssam if ((base = radix) < 0) 21030107Ssam base = -base; 21130107Ssam expv = 0; 21230107Ssam while (base>10 ? isxdigit(lastc) : isdigit(lastc)) { 21330107Ssam register m = MAXINT/base; 21430107Ssam 21530107Ssam if (expv>m) /* avoid overflow */ 21630107Ssam expv = (expv-m)*base+m*base; 21730107Ssam else 21830107Ssam expv *= base; 21930107Ssam if ((d=convdig(lastc))>=base || d<0) 22030107Ssam error(BADSYN); 221*30296Ssam expv += d; (void) readchar(); 22230107Ssam if (expv==0) { 22330107Ssam if (lastc=='x' || lastc=='X') { 224*30296Ssam base=16; (void) readchar(); 22530107Ssam } else if (lastc=='t' || lastc=='T') { 226*30296Ssam base=10; (void) readchar(); 22730107Ssam } else if (lastc=='o' || lastc=='O') { 228*30296Ssam base=8; (void) readchar(); 22930107Ssam } 23030107Ssam } 23130107Ssam } 23230107Ssam if (lastc=='.' && (base==10 || expv==0)) { 23330107Ssam real.r=expv; frpt=0; base=10; 23430107Ssam while (isdigit(readchar())) { 23530107Ssam real.r *= base; frpt++; 23630107Ssam real.r += lastc-'0'; 23730107Ssam } 23830107Ssam while (frpt--) 23930107Ssam real.r /= base; 24030107Ssam expv = real.i; 24130107Ssam } 24230107Ssam peekc=lastc; 24330107Ssam return (1); 24430107Ssam } 24530107Ssam 24630107Ssam static 24730107Ssam readsym() 24830107Ssam { 24930107Ssam register char *p; 25030107Ssam 25130107Ssam p = isymbol; 25230107Ssam do { 253*30296Ssam if (p < &isymbol[sizeof(isymbol)-1]) 254*30296Ssam *p++ = lastc; 255*30296Ssam (void) readchar(); 25630107Ssam } while (symchar(1)); 25730107Ssam *p++ = 0; 25830107Ssam } 25930107Ssam 26030107Ssam static 26130107Ssam convdig(c) 26230107Ssam char c; 26330107Ssam { 26430107Ssam if (isdigit(c)) 26530107Ssam return (c-'0'); 26630107Ssam if (isxdigit(c)) 26730107Ssam return (c-'a'+10); 26830107Ssam return (-1); 26930107Ssam } 27030107Ssam 27130107Ssam static 27230107Ssam symchar(dig) 27330107Ssam { 27430107Ssam 27530107Ssam if (lastc=='\\') { 276*30296Ssam (void) readchar(); 27730118Ssam return (1); 27830107Ssam } 27930107Ssam return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc)); 28030107Ssam } 28130107Ssam 28230107Ssam varchk(name) 28330107Ssam register name; 28430107Ssam { 28530107Ssam if (isdigit(name)) 28630107Ssam return (name-'0'); 28730107Ssam if (isalpha(name)) 28830107Ssam return ((name&037)-1+10); 28930107Ssam return (-1); 29030107Ssam } 29130107Ssam 29230107Ssam static 29330107Ssam chkloc(frame) 29430107Ssam long frame; 29530107Ssam { 29630107Ssam 29730107Ssam readsym(); 29830107Ssam do { 29930107Ssam if (localsym(frame)==0) 30030107Ssam error(BADLOC); 30130107Ssam expv=localval; 30230107Ssam } while (!eqsym(cursym->n_un.n_name,isymbol,'~')); 30330107Ssam } 30430107Ssam 30530107Ssam eqsym(s1, s2, c) 30630107Ssam register char *s1, *s2; 30730107Ssam { 30830107Ssam 30930107Ssam if (streq(s1,s2)) 31030107Ssam return (1); 31130107Ssam if (*s1 == c && streq(s1+1, s2)) 31230107Ssam return (1); 31330107Ssam return (0); 31430107Ssam } 31530107Ssam 31630107Ssam static 31730107Ssam streq(s1, s2) 31830107Ssam char *s1, *s2; 31930107Ssam { 32030107Ssam 32130107Ssam while (*s1 == *s2++) 32230107Ssam if (*s1++ == '\0') 32330107Ssam return (1); 32430107Ssam return (0); 32530107Ssam } 326