130296Ssam /* 230296Ssam * Copyright (c) 1986 Regents of the University of California. 330296Ssam * All rights reserved. The Berkeley software License Agreement 430296Ssam * specifies the terms and conditions for redistribution. 530296Ssam * 6*38199Smckusick * @(#)kdb_expr.c 7.5 (Berkeley) 05/29/89 730296Ssam */ 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 3430296Ssam static long 3530296Ssam round(a,b) 3630296Ssam register long a, b; 3730296Ssam { 3830296Ssam register long w; 3930296Ssam 4030296Ssam w = (a/b)*b; 4130296Ssam if (a!=w) 4230296Ssam w += b; 4330296Ssam return (w); 4430296Ssam } 4530296Ssam 4630107Ssam /* term | term dyadic expr | */ 4730107Ssam expr(a) 4830107Ssam { 4930107Ssam register rc; 5030107Ssam register long lhs; 5130107Ssam 5230296Ssam (void) rdc(); lp--; rc=term(a); 5330107Ssam 5430107Ssam while (rc) { 5530107Ssam lhs = expv; 5630107Ssam switch ((int)readchar()) { 5730107Ssam case '+': 5830296Ssam (void) term(a|1); expv += lhs; break; 5930107Ssam case '-': 6030296Ssam (void) term(a|1); expv = lhs - expv; break; 6130107Ssam case '#': 6230296Ssam (void) term(a|1); expv = round(lhs,expv); break; 6330107Ssam case '*': 6430296Ssam (void) term(a|1); expv *= lhs; break; 6530107Ssam case '%': 6630296Ssam (void) term(a|1); expv = lhs/expv; break; 6730107Ssam case '&': 6830296Ssam (void) term(a|1); expv &= lhs; break; 6930107Ssam case '|': 7030296Ssam (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 '*': 8930296Ssam (void) term(a|1); expv=chkget(expv,DSP); 9030107Ssam return(1); 9130107Ssam case '@': 9230296Ssam (void) term(a|1); expv=chkget(expv,ISP); 9330107Ssam return(1); 9430107Ssam case '-': 9530296Ssam (void) term(a|1); expv = -expv; 9630107Ssam return(1); 9730107Ssam case '~': 9830296Ssam (void) term(a|1); expv = ~expv; 9930107Ssam return(1); 10030107Ssam case '#': 10130296Ssam (void) term(a|1); expv = !expv; 10230107Ssam return(1); 10330107Ssam case '(': 10430296Ssam (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 12330296Ssam (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; 13130296Ssam (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; 14130296Ssam (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 '.': 15530296Ssam (void) readchar(); 15630107Ssam if (symchar(0)) { 15730107Ssam lastframe=savlastf; callpc=savpc; 15830296Ssam 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 20630107Ssam if (!isdigit(lastc)) 20730107Ssam return (0); 20830107Ssam if ((base = radix) < 0) 20930107Ssam base = -base; 21030107Ssam expv = 0; 21130107Ssam while (base>10 ? isxdigit(lastc) : isdigit(lastc)) { 21230107Ssam register m = MAXINT/base; 21330107Ssam 21430107Ssam if (expv>m) /* avoid overflow */ 21530107Ssam expv = (expv-m)*base+m*base; 21630107Ssam else 21730107Ssam expv *= base; 21830107Ssam if ((d=convdig(lastc))>=base || d<0) 21930107Ssam error(BADSYN); 22030296Ssam expv += d; (void) readchar(); 22130107Ssam if (expv==0) { 22230107Ssam if (lastc=='x' || lastc=='X') { 22330296Ssam base=16; (void) readchar(); 22430107Ssam } else if (lastc=='t' || lastc=='T') { 22530296Ssam base=10; (void) readchar(); 22630107Ssam } else if (lastc=='o' || lastc=='O') { 22730296Ssam base=8; (void) readchar(); 22830107Ssam } 22930107Ssam } 23030107Ssam } 23130107Ssam if (lastc=='.' && (base==10 || expv==0)) { 232*38199Smckusick frpt=0; base=10; 23330107Ssam while (isdigit(readchar())) { 234*38199Smckusick if (frpt) 235*38199Smckusick continue; 236*38199Smckusick frpt++; 237*38199Smckusick if (lastc - '0' >= 5) 238*38199Smckusick expv++; 23930107Ssam } 24030107Ssam } 24130107Ssam peekc=lastc; 24230107Ssam return (1); 24330107Ssam } 24430107Ssam 24530107Ssam static 24630107Ssam readsym() 24730107Ssam { 24830107Ssam register char *p; 24930107Ssam 25030107Ssam p = isymbol; 25130107Ssam do { 25230296Ssam if (p < &isymbol[sizeof(isymbol)-1]) 25330296Ssam *p++ = lastc; 25430296Ssam (void) readchar(); 25530107Ssam } while (symchar(1)); 25630107Ssam *p++ = 0; 25730107Ssam } 25830107Ssam 25930107Ssam static 26030107Ssam convdig(c) 26130107Ssam char c; 26230107Ssam { 26330107Ssam if (isdigit(c)) 26430107Ssam return (c-'0'); 26530107Ssam if (isxdigit(c)) 26630107Ssam return (c-'a'+10); 26730107Ssam return (-1); 26830107Ssam } 26930107Ssam 27030107Ssam static 27130107Ssam symchar(dig) 27230107Ssam { 27330107Ssam 27430107Ssam if (lastc=='\\') { 27530296Ssam (void) readchar(); 27630118Ssam return (1); 27730107Ssam } 27830107Ssam return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc)); 27930107Ssam } 28030107Ssam 28130107Ssam varchk(name) 28230107Ssam register name; 28330107Ssam { 28430107Ssam if (isdigit(name)) 28530107Ssam return (name-'0'); 28630107Ssam if (isalpha(name)) 28730107Ssam return ((name&037)-1+10); 28830107Ssam return (-1); 28930107Ssam } 29030107Ssam 29130107Ssam static 29230107Ssam chkloc(frame) 29330107Ssam long frame; 29430107Ssam { 29530107Ssam 29630107Ssam readsym(); 29730107Ssam do { 29830107Ssam if (localsym(frame)==0) 29930107Ssam error(BADLOC); 30030107Ssam expv=localval; 30130107Ssam } while (!eqsym(cursym->n_un.n_name,isymbol,'~')); 30230107Ssam } 30330107Ssam 30430107Ssam eqsym(s1, s2, c) 30530107Ssam register char *s1, *s2; 30630107Ssam { 30730107Ssam 30830107Ssam if (streq(s1,s2)) 30930107Ssam return (1); 31030107Ssam if (*s1 == c && streq(s1+1, s2)) 31130107Ssam return (1); 31230107Ssam return (0); 31330107Ssam } 31430107Ssam 31530107Ssam static 31630107Ssam streq(s1, s2) 31730107Ssam char *s1, *s2; 31830107Ssam { 31930107Ssam 32030107Ssam while (*s1 == *s2++) 32130107Ssam if (*s1++ == '\0') 32230107Ssam return (1); 32330107Ssam return (0); 32430107Ssam } 325