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.5 (Berkeley) 05/29/89 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 206 if (!isdigit(lastc)) 207 return (0); 208 if ((base = radix) < 0) 209 base = -base; 210 expv = 0; 211 while (base>10 ? isxdigit(lastc) : isdigit(lastc)) { 212 register m = MAXINT/base; 213 214 if (expv>m) /* avoid overflow */ 215 expv = (expv-m)*base+m*base; 216 else 217 expv *= base; 218 if ((d=convdig(lastc))>=base || d<0) 219 error(BADSYN); 220 expv += d; (void) readchar(); 221 if (expv==0) { 222 if (lastc=='x' || lastc=='X') { 223 base=16; (void) readchar(); 224 } else if (lastc=='t' || lastc=='T') { 225 base=10; (void) readchar(); 226 } else if (lastc=='o' || lastc=='O') { 227 base=8; (void) readchar(); 228 } 229 } 230 } 231 if (lastc=='.' && (base==10 || expv==0)) { 232 frpt=0; base=10; 233 while (isdigit(readchar())) { 234 if (frpt) 235 continue; 236 frpt++; 237 if (lastc - '0' >= 5) 238 expv++; 239 } 240 } 241 peekc=lastc; 242 return (1); 243 } 244 245 static 246 readsym() 247 { 248 register char *p; 249 250 p = isymbol; 251 do { 252 if (p < &isymbol[sizeof(isymbol)-1]) 253 *p++ = lastc; 254 (void) readchar(); 255 } while (symchar(1)); 256 *p++ = 0; 257 } 258 259 static 260 convdig(c) 261 char c; 262 { 263 if (isdigit(c)) 264 return (c-'0'); 265 if (isxdigit(c)) 266 return (c-'a'+10); 267 return (-1); 268 } 269 270 static 271 symchar(dig) 272 { 273 274 if (lastc=='\\') { 275 (void) readchar(); 276 return (1); 277 } 278 return (isalpha(lastc) || lastc=='_' || dig && isdigit(lastc)); 279 } 280 281 varchk(name) 282 register name; 283 { 284 if (isdigit(name)) 285 return (name-'0'); 286 if (isalpha(name)) 287 return ((name&037)-1+10); 288 return (-1); 289 } 290 291 static 292 chkloc(frame) 293 long frame; 294 { 295 296 readsym(); 297 do { 298 if (localsym(frame)==0) 299 error(BADLOC); 300 expv=localval; 301 } while (!eqsym(cursym->n_un.n_name,isymbol,'~')); 302 } 303 304 eqsym(s1, s2, c) 305 register char *s1, *s2; 306 { 307 308 if (streq(s1,s2)) 309 return (1); 310 if (*s1 == c && streq(s1+1, s2)) 311 return (1); 312 return (0); 313 } 314 315 static 316 streq(s1, s2) 317 char *s1, *s2; 318 { 319 320 while (*s1 == *s2++) 321 if (*s1++ == '\0') 322 return (1); 323 return (0); 324 } 325