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.6 (Berkeley) 05/03/90 7 */ 8 9 #include "../kdb/defs.h" 10 11 char *kdbBADSYM; 12 char *kdbBADVAR; 13 char *kdbBADKET; 14 char *kdbBADSYN; 15 char *kdbNOCFN; 16 char *kdbNOADR; 17 char *kdbBADLOC; 18 19 ADDR kdblastframe; 20 ADDR kdbsavlastf; 21 ADDR kdbsavframe; 22 ADDR kdbsavpc; 23 ADDR kdbcallpc; 24 25 char *kdblp; 26 int kdbradix; 27 char kdbisymbol[1024]; 28 29 char kdblastc, kdbpeekc; 30 31 long kdbditto; 32 long kdbexpv; 33 34 static long 35 kdbround(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 kdbexpr(a) 48 { 49 register rc; 50 register long lhs; 51 52 (void) kdbrdc(); kdblp--; rc=kdbterm(a); 53 54 while (rc) { 55 lhs = kdbexpv; 56 switch ((int)kdbreadchar()) { 57 case '+': 58 (void) kdbterm(a|1); kdbexpv += lhs; break; 59 case '-': 60 (void) kdbterm(a|1); kdbexpv = lhs - kdbexpv; break; 61 case '#': 62 (void) kdbterm(a|1); kdbexpv = kdbround(lhs,kdbexpv); break; 63 case '*': 64 (void) kdbterm(a|1); kdbexpv *= lhs; break; 65 case '%': 66 (void) kdbterm(a|1); kdbexpv = lhs/kdbexpv; break; 67 case '&': 68 (void) kdbterm(a|1); kdbexpv &= lhs; break; 69 case '|': 70 (void) kdbterm(a|1); kdbexpv |= lhs; break; 71 case ')': 72 if ((a&2)==0) 73 kdberror(kdbBADKET); 74 default: 75 kdblp--; 76 return (rc); 77 } 78 } 79 return (rc); 80 } 81 82 /* item | monadic item | (expr) | */ 83 static 84 kdbterm(a) 85 { 86 87 switch ((int)kdbreadchar()) { 88 case '*': 89 (void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,DSP); 90 return(1); 91 case '@': 92 (void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,ISP); 93 return(1); 94 case '-': 95 (void) kdbterm(a|1); kdbexpv = -kdbexpv; 96 return(1); 97 case '~': 98 (void) kdbterm(a|1); kdbexpv = ~kdbexpv; 99 return(1); 100 case '#': 101 (void) kdbterm(a|1); kdbexpv = !kdbexpv; 102 return(1); 103 case '(': 104 (void) kdbexpr(2); 105 if (*kdblp!=')') 106 kdberror(kdbBADSYN); 107 kdblp++; 108 return(1); 109 } 110 kdblp--; 111 return (kdbitem(a)); 112 } 113 114 /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */ 115 static 116 kdbitem(a) 117 { 118 register base, d, regptr; 119 char savc; 120 register long frame; 121 register struct nlist *symp; 122 123 (void) kdbreadchar(); 124 if (kdbsymchar(0)) { 125 kdbreadsym(); 126 if (kdblastc=='.') { 127 frame = kdbpcb.pcb_fp; kdblastframe = 0; 128 kdbcallpc = kdbpcb.pcb_pc; 129 while (!kdberrflg) { 130 kdbsavpc = kdbcallpc; 131 (void) kdbfindsym((long)kdbcallpc,ISYM); 132 if (kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~')) 133 break; 134 kdbcallpc = getprevpc(frame); 135 kdblastframe = frame; 136 frame = getprevframe(frame); 137 if (frame == NOFRAME) 138 kdberror(kdbNOCFN); 139 } 140 kdbsavlastf = kdblastframe; kdbsavframe = frame; 141 (void) kdbreadchar(); 142 if (kdbsymchar(0)) 143 kdbchkloc(kdbexpv=frame); 144 } else if ((symp=kdblookup(kdbisymbol))==0) 145 kdberror(kdbBADSYM); 146 else 147 kdbexpv = symp->n_value; 148 kdblp--; 149 return (1); 150 } 151 if (kdbgetnum()) 152 return (1); 153 switch (kdblastc) { 154 case '.': 155 (void) kdbreadchar(); 156 if (kdbsymchar(0)) { 157 kdblastframe=kdbsavlastf; kdbcallpc=kdbsavpc; 158 kdbchkloc((long)kdbsavframe); 159 } else 160 kdbexpv=kdbdot; 161 kdblp--; 162 break; 163 case '"': 164 kdbexpv=kdbditto; 165 break; 166 case '+': 167 kdbexpv=kdbinkdot(kdbdotinc); 168 break; 169 case '^': 170 kdbexpv=kdbinkdot(-kdbdotinc); 171 break; 172 case '<': 173 savc=kdbrdc(); 174 if ((regptr=kdbgetreg(savc)) != -1) 175 kdbexpv = *(int *)regptr; 176 else if ((base=kdbvarchk(savc)) != -1) 177 kdbexpv=kdbvar[base]; 178 else 179 kdberror(kdbBADVAR); 180 break; 181 case '\'': 182 d=4; kdbexpv=0; 183 while (kdbquotchar()) { 184 if (d--) { 185 kdbexpv <<= 8; 186 kdbexpv |= kdblastc; 187 } else 188 kdberror(kdbBADSYN); 189 } 190 break; 191 default: 192 if (a) 193 kdberror(kdbNOADR); 194 kdblp--; 195 return(0); 196 } 197 return (1); 198 } 199 200 /* service routines for expression reading */ 201 static 202 kdbgetnum() 203 { 204 register base,d,frpt; 205 206 if (!isdigit(kdblastc)) 207 return (0); 208 if ((base = kdbradix) < 0) 209 base = -base; 210 kdbexpv = 0; 211 while (base>10 ? isxdigit(kdblastc) : isdigit(kdblastc)) { 212 register m = MAXINT/base; 213 214 if (kdbexpv>m) /* avoid overflow */ 215 kdbexpv = (kdbexpv-m)*base+m*base; 216 else 217 kdbexpv *= base; 218 if ((d=kdbconvdig(kdblastc))>=base || d<0) 219 kdberror(kdbBADSYN); 220 kdbexpv += d; (void) kdbreadchar(); 221 if (kdbexpv==0) { 222 if (kdblastc=='x' || kdblastc=='X') { 223 base=16; (void) kdbreadchar(); 224 } else if (kdblastc=='t' || kdblastc=='T') { 225 base=10; (void) kdbreadchar(); 226 } else if (kdblastc=='o' || kdblastc=='O') { 227 base=8; (void) kdbreadchar(); 228 } 229 } 230 } 231 if (kdblastc=='.' && (base==10 || kdbexpv==0)) { 232 frpt=0; base=10; 233 while (isdigit(kdbreadchar())) { 234 if (frpt) 235 continue; 236 frpt++; 237 if (kdblastc - '0' >= 5) 238 kdbexpv++; 239 } 240 } 241 kdbpeekc=kdblastc; 242 return (1); 243 } 244 245 static 246 kdbreadsym() 247 { 248 register char *p; 249 250 p = kdbisymbol; 251 do { 252 if (p < &kdbisymbol[sizeof(kdbisymbol)-1]) 253 *p++ = kdblastc; 254 (void) kdbreadchar(); 255 } while (kdbsymchar(1)); 256 *p++ = 0; 257 } 258 259 static 260 kdbconvdig(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 kdbsymchar(dig) 272 { 273 274 if (kdblastc=='\\') { 275 (void) kdbreadchar(); 276 return (1); 277 } 278 return (isalpha(kdblastc) || kdblastc=='_' || dig && isdigit(kdblastc)); 279 } 280 281 kdbvarchk(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 kdbchkloc(frame) 293 long frame; 294 { 295 296 kdbreadsym(); 297 do { 298 if (kdblocalsym(frame)==0) 299 kdberror(kdbBADLOC); 300 kdbexpv=kdblocalval; 301 } while (!kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~')); 302 } 303 304 kdbeqsym(s1, s2, c) 305 register char *s1, *s2; 306 { 307 308 if (kdbstreq(s1,s2)) 309 return (1); 310 if (*s1 == c && kdbstreq(s1+1, s2)) 311 return (1); 312 return (0); 313 } 314 315 static 316 kdbstreq(s1, s2) 317 char *s1, *s2; 318 { 319 320 while (*s1 == *s2++) 321 if (*s1++ == '\0') 322 return (1); 323 return (0); 324 } 325