1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)command.c 5.5 (Berkeley) 04/04/91"; 10 #endif /* not lint */ 11 12 /* 13 * adb - commands 14 */ 15 16 #include "defs.h" 17 #include <ctype.h> 18 #include <sys/wait.h> 19 #include <paths.h> 20 21 extern char BADEQ[]; /* "unexpected `='" */ 22 extern char NOMATCH[]; /* "cannot locate value" */ 23 extern char BADVAR[]; /* "bad variable" */ 24 extern char BADCOM[]; /* "bad command" */ 25 extern char NOFORK[]; /* "try again" */ 26 27 /* 28 * executing is used in main() to see if it is necessary to 29 * delete any breakpoints that might have been set; if an 30 * error occurs while a subprocess command is running, executing 31 * will be set. 32 */ 33 int executing; 34 35 /* lastcom remembers the previous command */ 36 static struct { 37 int c; /* the command */ 38 int star; /* true iff it was in alternate space */ 39 } lastcom; 40 41 /* 42 * Execute the given command buffer. 43 * If defcom is nonzero, it is used as the default command. 44 */ 45 command(buf, defcom) 46 char *buf; 47 int defcom; 48 { 49 50 lp = buf; 51 do { 52 cmds(defcom); 53 flushbuf(); 54 } while (rdc() == ';'); 55 unreadc(); 56 } 57 58 static 59 cmds(defcom) 60 int defcom; 61 { 62 int c; 63 struct reglist *reg; 64 65 /* 66 * Pick up the optional first expression (`dot'), 67 * then, if the next character is a comma, pick up 68 * the second optional expression (`ecount'). 69 */ 70 if (gavedot = oexpr()) 71 ditto = dot = edot = expv; 72 else 73 edot = dot; /* probably equal, but possibly truncating */ 74 if (rdc() == ',') { 75 if (!oexpr()) 76 error("count expected"); 77 gavecount = 1; 78 ecount = expv; 79 } else { 80 gavecount = 0; 81 ecount = 1; 82 unreadc(); 83 } 84 85 /* 86 * Pick up the command. If there is no command, do the 87 * previous (or default) command, and if no dot was given, 88 * use the `next' dot. 89 */ 90 c = rdc(); 91 if (eol(c)) { 92 if (defcom != 0) { 93 lastcom.c = defcom; 94 lastcom.star = 0; 95 } 96 if (!gavedot) 97 dot = inkdot(dotinc); 98 unreadc(); 99 } else { 100 lastcom.c = c; 101 lastcom.star = 0; 102 } 103 104 switch (lastcom.c) { 105 106 case '=': 107 fmtcom(SP_NONE, 1); 108 break; 109 110 case '/': 111 fmtcom(SP_DATA, 0); 112 break; 113 114 case '?': 115 fmtcom(SP_INSTR, 0); 116 break; 117 118 case '>': 119 lastcom.c = 0; 120 if ((reg = reglookup()) != NULL) { 121 if (setreg(reg, edot)) 122 prints("register write failed"); 123 break; 124 } 125 if ((c = varlookup(rdc())) != -1) 126 var[c] = edot; 127 else 128 error(BADVAR); 129 break; 130 131 case '!': 132 lastcom.c = 0; 133 shell(); 134 break; 135 136 case '$': 137 lastcom.c = 0; 138 printtrace(nextchar()); 139 break; 140 141 case ':': 142 if (!executing) { 143 executing = 1; 144 subpcs(nextchar()); 145 executing = 0; 146 lastcom.c = 0; 147 } 148 break; 149 150 case 0: 151 prints("adb\n"); 152 break; 153 154 default: 155 error(BADCOM); 156 /* NOTREACHED */ 157 } 158 } 159 160 /* 161 * Perform a format-based command (one in ? / or =). 162 */ 163 static 164 fmtcom(space, eqcom) 165 int space, eqcom; 166 { 167 /* special commands m, lL, wW do not operate in SP_NONE (`=') */ 168 void mcom(), lcom(), wcom(); 169 static struct fcmd { 170 int c; 171 void (*fn)(); 172 } fcmd[] = { 173 { 'm', mcom }, 174 { 'l', lcom }, { 'L', lcom }, 175 { 'w', wcom }, { 'W', wcom }, 176 0 177 }; 178 register struct fcmd *f; 179 register int c; 180 int ptype = space; 181 static char stformat[LINELEN] = "X\"= \"^i"; 182 static char eqformat[LINELEN] = "z"; 183 184 /* 185 * Are we operating in the alternate `star' space? 186 */ 187 if (!eqcom) { 188 if (rdc() == '*') 189 lastcom.star = 1; 190 else 191 unreadc(); 192 if (lastcom.star) { 193 space |= SP_STAR; 194 /* print as data for instr, and vice versa */ 195 ptype = (SP_DATA + SP_INSTR) - ptype; 196 } 197 } 198 199 /* 200 * Check for the special commands first. 201 */ 202 c = rdc(); 203 for (f = fcmd; f->c; f++) { 204 if (c == f->c) { 205 if (eqcom) 206 error(BADEQ); 207 (*f->fn)(space, ptype, isupper(c)); 208 return; 209 } 210 } 211 unreadc(); 212 getformat(eqcom ? eqformat : stformat, LINELEN); 213 scanform(!eqcom, eqcom ? eqformat : stformat, space, ptype); 214 } 215 216 /* 217 * Set a map (?m, /m commands). 218 */ 219 /* ARGSUSED */ 220 static void 221 mcom(space, ptype, fullword) 222 int space, ptype, fullword; 223 { 224 register struct map *smap; 225 register struct m1 *mm; 226 char c; 227 228 smap = space & SP_DATA ? &datmap : &txtmap; 229 mm = space & SP_STAR ? &smap->m2 : &smap->m1; 230 if (oexpr()) { 231 mm->b = expv; 232 if (oexpr()) { 233 mm->e = expv; 234 if (oexpr()) 235 mm->f = expv; 236 } 237 } 238 if ((c = rdc()) == '?') 239 smap->ufd = symfile.fd; 240 else if (c == '/') 241 smap->ufd = corefile.fd; 242 else 243 unreadc(); 244 } 245 246 /* 247 * Locate a value (l, L commands). 248 */ 249 static void 250 lcom(space, ptype, fullword) 251 int space, ptype, fullword; 252 { 253 register expr_t val, mask; 254 addr_t savdot; 255 256 /* search for exp */ 257 savdot = dot; 258 val = rexpr(); 259 if (oexpr()) 260 mask = expv; 261 else 262 mask = ~0L; 263 if (fullword) { 264 expr_t w; 265 266 dotinc = sizeof(w); 267 for (;;) { 268 (void) adbread(space, dot, &w, sizeof(w)); 269 if (iserr() || (w & mask) == val) 270 break; 271 dot = inkdot(sizeof(w)); 272 } 273 } else { 274 hword_t hw; 275 276 dotinc = sizeof(hw); 277 mask = (hword_t)mask; 278 val = (hword_t)val; 279 for (;;) { 280 (void) adbread(space, dot, &hw, sizeof(hw)); 281 if (iserr() || (hw & mask) == val) 282 break; 283 dot = inkdot(sizeof(hw)); 284 } 285 } 286 if (iserr()) { 287 dot = savdot; 288 errflag = NOMATCH; 289 } 290 psymoff("%R", dot, ptype, maxoff, ""); 291 } 292 293 /* 294 * Write new values (w, W). 295 */ 296 static void 297 wcom(space, ptype, fullword) 298 int space, ptype, fullword; 299 { 300 addr_t savdot; 301 hword_t hw; 302 303 (void) rexpr(); 304 do { 305 savdot = dot; 306 pdot(); 307 showdot(fullword, space, ptype); /* also advances */ 308 errflag = NULL; 309 dot = savdot; 310 if (fullword) 311 (void) adbwrite(space, dot, &expv, sizeof(expv)); 312 else { 313 hw = expv; 314 (void) adbwrite(space, dot, &hw, sizeof(hw)); 315 } 316 savdot = dot; 317 adbprintf("=%8t"); 318 showdot(fullword, space, ptype); 319 printc('\n'); 320 } while (oexpr() && !iserr()); 321 dot = savdot; 322 checkerr(); 323 } 324 325 /* 326 * Do a shell escape. 327 * 328 * THE vfork CODE BELOW IS CURRENTLY BROKEN 329 * MUST CHANGE signal TO sigvec BELOW 330 */ 331 static 332 shell() 333 { 334 int rc, unixpid; 335 union wait status; 336 char *argp = lp; 337 char *getenv(), *eshell = getenv("SHELL"); 338 339 if (eshell == 0) 340 eshell = _PATH_BSHELL; 341 while (readchar() != '\n') 342 /* void */; 343 #ifndef VFORK 344 #define vfork fork 345 #endif 346 if ((unixpid = vfork()) == 0) { 347 *lp = 0; 348 (void) signal(SIGINT, sigint); 349 (void) signal(SIGQUIT, sigquit); 350 execl(eshell, "sh", "-c", argp, (char *)NULL); 351 _exit(16); 352 /* NOTREACHED */ 353 } 354 #ifdef VFORK 355 *lp = '\n'; 356 #endif 357 if (unixpid == -1) 358 error(NOFORK); 359 (void) signal(SIGINT, SIG_IGN); 360 while ((rc = wait(&status)) != unixpid && rc != -1) 361 /* void */; 362 (void) signal(SIGINT, intcatch); 363 prints("!"); 364 unreadc(); 365 } 366 367 /* 368 * Read a format into the given buffer. If nothing is 369 * read, leave the buffer alone. 370 */ 371 static 372 getformat(buf, n) 373 char *buf; 374 register int n; 375 { 376 register char *p = buf; 377 register int c, quote = 0; 378 379 while ((c = readchar()), quote ? c != '\n' : !eol(c)) { 380 if (c == '"') 381 quote = !quote; 382 if (--n > 0) 383 *p++ = c; 384 } 385 unreadc(); 386 if (p != buf) /* nonempty */ 387 *p++ = 0; 388 } 389 390 /* 391 * Convert a (one-character) variable name to an index, or -1 for 392 * error. 393 */ 394 varlookup(name) 395 register int name; 396 { 397 398 if (isdigit(name)) 399 return (name - '0'); 400 if (isalpha(name)) 401 return (isupper(name) ? name - 'A' + 10 : name - 'a' + 10); 402 return (-1); 403 } 404 405 /* 406 * If the text at the current input point matches a register name, 407 * consume that text and return a pointer to the register; otherwise 408 * leave it unconsumed and return NULL. 409 */ 410 struct reglist * 411 reglookup() 412 { 413 register struct reglist *p; 414 register char *a, *b, c0, c1; 415 char *oldlp = lp; 416 extern struct reglist reglist[]; 417 418 c0 = rdc(); 419 c1 = readchar(); 420 for (p = reglist; (a = p->r_name) != NULL; p++) { 421 if (*a++ != c0 || *a++ != c1) 422 continue; 423 b = lp; 424 do { 425 if (*a == 0) { /* name matched: stop short */ 426 lp = b; 427 return (p); 428 } 429 } while (*a++ == *b++); 430 } 431 lp = oldlp; 432 return (NULL); 433 } 434