1 /* 2 * Copyright (c) 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)kdb_expr.c 7.4 (Berkeley) 12/15/86 7 */ 8 9 #include "../kdb/defs.h" 10 11 char *BADSYM; 12 char *BADVAR; 13 char *BADKET; 14 char *BADSYN; 15 char *NOCFN; 16 char *NOADR; 17 char *BADLOC; 18 19 ADDR lastframe; 20 ADDR savlastf; 21 ADDR savframe; 22 ADDR savpc; 23 ADDR callpc; 24 25 char *lp; 26 int radix; 27 char isymbol[1024]; 28 29 char lastc, peekc; 30 31 long ditto; 32 long expv; 33 34 static long 35 round(a,b) 36 register long a, b; 37 { 38 register long w; 39 40 w = (a/b)*b; 41 if (a!=w) 42 w += b; 43 return (w); 44 } 45 46 /* term | term dyadic expr | */ 47 expr(a) 48 { 49 register rc; 50 register long lhs; 51 52 (void) rdc(); lp--; rc=term(a); 53 54 while (rc) { 55 lhs = expv; 56 switch ((int)readchar()) { 57 case '+': 58 (void) term(a|1); expv += lhs; break; 59 case '-': 60 (void) term(a|1); expv = lhs - expv; break; 61 case '#': 62 (void) term(a|1); expv = round(lhs,expv); break; 63 case '*': 64 (void) term(a|1); expv *= lhs; break; 65 case '%': 66 (void) term(a|1); expv = lhs/expv; break; 67 case '&': 68 (void) term(a|1); expv &= lhs; break; 69 case '|': 70 (void) term(a|1); expv |= lhs; break; 71 case ')': 72 if ((a&2)==0) 73 error(BADKET); 74 default: 75 lp--; 76 return (rc); 77 } 78 } 79 return (rc); 80 } 81 82 /* item | monadic item | (expr) | */ 83 static 84 term(a) 85 { 86 87 switch ((int)readchar()) { 88 case '*': 89 (void) term(a|1); expv=chkget(expv,DSP); 90 return(1); 91 case '@': 92 (void) term(a|1); expv=chkget(expv,ISP); 93 return(1); 94 case '-': 95 (void) term(a|1); expv = -expv; 96 return(1); 97 case '~': 98 (void) term(a|1); expv = ~expv; 99 return(1); 100 case '#': 101 (void) term(a|1); expv = !expv; 102 return(1); 103 case '(': 104 (void) expr(2); 105 if (*lp!=')') 106 error(BADSYN); 107 lp++; 108 return(1); 109 } 110 lp--; 111 return (item(a)); 112 } 113 114 /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */ 115 static 116 item(a) 117 { 118 register base, d, regptr; 119 char savc; 120 register long frame; 121 register struct nlist *symp; 122 123 (void) readchar(); 124 if (symchar(0)) { 125 readsym(); 126 if (lastc=='.') { 127 frame = pcb.pcb_fp; lastframe = 0; 128 callpc = pcb.pcb_pc; 129 while (!errflg) { 130 savpc = callpc; 131 (void) findsym((long)callpc,ISYM); 132 if (eqsym(cursym->n_un.n_name,isymbol,'~')) 133 break; 134 callpc = getprevpc(frame); 135 lastframe = frame; 136 frame = getprevframe(frame); 137 if (frame == NOFRAME) 138 error(NOCFN); 139 } 140 savlastf = lastframe; savframe = frame; 141 (void) readchar(); 142 if (symchar(0)) 143 chkloc(expv=frame); 144 } else if ((symp=lookup(isymbol))==0) 145 error(BADSYM); 146 else 147 expv = symp->n_value; 148 lp--; 149 return (1); 150 } 151 if (getnum()) 152 return (1); 153 switch (lastc) { 154 case '.': 155 (void) readchar(); 156 if (symchar(0)) { 157 lastframe=savlastf; callpc=savpc; 158 chkloc((long)savframe); 159 } else 160 expv=dot; 161 lp--; 162 break; 163 case '"': 164 expv=ditto; 165 break; 166 case '+': 167 expv=inkdot(dotinc); 168 break; 169 case '^': 170 expv=inkdot(-dotinc); 171 break; 172 case '<': 173 savc=rdc(); 174 if ((regptr=getreg(savc)) != -1) 175 expv = *(int *)regptr; 176 else if ((base=varchk(savc)) != -1) 177 expv=var[base]; 178 else 179 error(BADVAR); 180 break; 181 case '\'': 182 d=4; expv=0; 183 while (quotchar()) { 184 if (d--) { 185 expv <<= 8; 186 expv |= lastc; 187 } else 188 error(BADSYN); 189 } 190 break; 191 default: 192 if (a) 193 error(NOADR); 194 lp--; 195 return(0); 196 } 197 return (1); 198 } 199 200 /* service routines for expression reading */ 201 static 202 getnum() 203 { 204 register base,d,frpt; 205 union { float r; long i;} real; 206 207 if (!isdigit(lastc)) 208 return (0); 209 if ((base = radix) < 0) 210 base = -base; 211 expv = 0; 212 while (base>10 ? isxdigit(lastc) : isdigit(lastc)) { 213 register m = MAXINT/base; 214 215 if (expv>m) /* avoid overflow */ 216 expv = (expv-m)*base+m*base; 217 else 218 expv *= base; 219 if ((d=convdig(lastc))>=base || d<0) 220 error(BADSYN); 221 expv += d; (void) readchar(); 222 if (expv==0) { 223 if (lastc=='x' || lastc=='X') { 224 base=16; (void) readchar(); 225 } else if (lastc=='t' || lastc=='T') { 226 base=10; (void) readchar(); 227 } else if (lastc=='o' || lastc=='O') { 228 base=8; (void) readchar(); 229 } 230 } 231 } 232 if (lastc=='.' && (base==10 || expv==0)) { 233 real.r=expv; frpt=0; base=10; 234 while (isdigit(readchar())) { 235 real.r *= base; frpt++; 236 real.r += lastc-'0'; 237 } 238 while (frpt--) 239 real.r /= base; 240 expv = real.i; 241 } 242 peekc=lastc; 243 return (1); 244 } 245 246 static 247 readsym() 248 { 249 register char *p; 250 251 p = isymbol; 252 do { 253 if (p < &isymbol[sizeof(isymbol)-1]) 254 *p++ = lastc; 255 (void) readchar(); 256 } while (symchar(1)); 257 *p++ = 0; 258 } 259 260 static 261 convdig(c) 262 char c; 263 { 264 if (isdigit(c)) 265 return (c-'0'); 266 if (isxdigit(c)) 267 return (c-'a'+10); 268 return (-1); 269 } 270 271 static 272 symchar(dig) 273 { 274 275 if (lastc=='\\') { 276 (void) readchar(); 277 return (1); 278 } 279 return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc)); 280 } 281 282 varchk(name) 283 register name; 284 { 285 if (isdigit(name)) 286 return (name-'0'); 287 if (isalpha(name)) 288 return ((name&037)-1+10); 289 return (-1); 290 } 291 292 static 293 chkloc(frame) 294 long frame; 295 { 296 297 readsym(); 298 do { 299 if (localsym(frame)==0) 300 error(BADLOC); 301 expv=localval; 302 } while (!eqsym(cursym->n_un.n_name,isymbol,'~')); 303 } 304 305 eqsym(s1, s2, c) 306 register char *s1, *s2; 307 { 308 309 if (streq(s1,s2)) 310 return (1); 311 if (*s1 == c && streq(s1+1, s2)) 312 return (1); 313 return (0); 314 } 315 316 static 317 streq(s1, s2) 318 char *s1, *s2; 319 { 320 321 while (*s1 == *s2++) 322 if (*s1++ == '\0') 323 return (1); 324 return (0); 325 } 326