|
|
1.1 root 1: static char sccsid[] = "@(#)cmd.c 2.8";
2:
3: #include <ctype.h>
4: #include <stdio.h>
5: #include "cdb.h"
6: #include <signal.h>
7:
8: static char vsbTarget[100]; /* used for string searches */
9: static char vchSearch = '/'; /* contains either ? or / */
10:
11: export CMDE vcmdDef;
12: export char *vsbCmd, *vsbCmdOld;
13: export long vdot;
14: export TYR vtyDot[cTyMax];
15: export int viln, vslop; /* line number & offset from true line number */
16: export char vsbFileTemp[80]; /* name of vifdTemp file */
17:
18:
19: /* C A L L S H E L L */
20:
21: local void CallShell(sbCmd)
22: char *sbCmd;
23: {
24: char stShell[20];
25:
26: if ((sbCmd == sbNil) OR (*sbCmd == chNull)) {
27: sprintf(stShell, "%s -i", getenv("SHELL"));
28: sbCmd = stShell;
29: } /* if */
30: system(sbCmd);
31: printf("\nback in cdb, debugging %s\n", vsbSymfile);
32: } /* CallShell */
33:
34:
35: /* E A T C M D L I S T */
36:
37: export char * EatCmdList()
38: {
39: char *sbCmd, *sbTemp;
40: TKE tk;
41:
42: sbCmd = vsbCmd;
43: tk = TkPeek();
44: if (tk == tkNil)
45: return(sbNil);
46:
47: if (tk != tkLCB) {
48: vsbCmd = sbNil; /* give caller the rest of line */
49: }
50: else {
51: tk = TkNext(); /* eat { */
52: sbCmd = vsbCmd;
53: sbTemp = SbFEob(vsbCmd) - 1;
54: if (*sbTemp == '}')
55: *sbTemp = chNull;
56: vsbCmd = sbTemp + 1;
57: } /* if */
58: while (*sbCmd == ' ')
59: sbCmd++;
60: return(sbCmd);
61: } /* EatCmdList */
62:
63:
64: /* E A T F I L E N A M E */
65:
66: local void EatFilename(sbName, psbIn)
67: char *sbName, **psbIn;
68: {
69: int cch;
70: char *sbIn;
71:
72: sbIn = *psbIn;
73: while (*sbIn == '\t' OR *sbIn == ' ')
74: sbIn++;
75: cch = strcspn(sbIn, "\t ;}");
76: strncpy(sbName, sbIn, cch);
77: sbName[cch] = chNull;
78: *psbIn = sbIn + cch;
79: } /* EatFilename */
80:
81:
82: /* S B F E O B */
83:
84: export char *SbFEob(sb)
85: char *sb;
86: {
87: int cNest;
88:
89: /* return pointer to AFTER '}', or to the chNull */
90: cNest = (*sb == '{') ? 0 : 1;
91: while (*sb) {
92: if (*sb == '{')
93: cNest++;
94: else if (*sb == '}')
95: if (--cNest == 0)
96: return(sb+1);
97: sb++;
98: } /* while */
99: return(sb);
100: } /* SbFEob */
101:
102:
103: /* F D O C O M M A N D */
104:
105: export FLAGT FDoCommand(sbCmdIn, fTop)
106: char *sbCmdIn;
107: FLAGT fTop;
108: {
109: int valShort, ln, cLn, cnt, ifd, ipd;
110: int sig, ibp, i, ilnSave;
111: FLAGT fHaveValue, fDidit, fDoit, fCommand;
112: char ch, chBp, chCmd, chNext;
113: char *sbBp, *sbTemp, *sbCmds, *sbTwoChars;
114: char sbName[80];
115: long valExp, adrLong;
116: ADRT adr;
117: TKE tk, tkRet;
118: ASE as;
119: pTYR ty;
120: TYR rgTy[cTyMax];
121:
122: /* the commands */
123: sbCmds = "\n<>-+?/^!~;{}AabBcCdDeEfFgiIklLMpqQrRsStTwWxzZ";
124: sbTwoChars = "<bi"; /* commands of two or more characters */
125: if (!fTop)
126: PushCmd(vsbCmd);
127: vsbCmd = vsbCmdOld = sbCmdIn;
128:
129: tk = TkNext();
130: do {
131: if ((tk == tkStr) AND (FSbCmp("help", vsbTok))) {
132: Help();
133: vcmdDef = cmdNil;
134: return(fTop);
135: }
136: else if (tk == tkStrConstant) {
137: printf("%s", vsbTok);
138: vcmdDef = cmdNil;
139: tk = TkNext();
140: continue;
141: } /* if */
142:
143: /* we guess whether to parse an expression */
144: /* this is a little weird because we try to do the `right' thing */
145: adrLong = 0;
146: chCmd = vsbTok[0];
147: fHaveValue = false;
148: fCommand = (tk == tkNil);
149: if (strchr(sbCmds, chCmd) != NULL) {
150: /* the first letter LOOKS like a command, keep going */
151: fCommand = (vcbTok == 1);
152: if ((vcbTok > 1) AND (tk == tkStr)) {
153: /* it is longer than 1 character, might be a variable name */
154: chNext = vsbTok[1];
155: if ( (vcbTok == 2)
156: AND (strchr(sbTwoChars, chCmd) != NULL) ) {
157: fCommand = (chCmd == 'b' AND strchr("abBtTuUxX", chNext))
158: OR (chCmd == 'i' AND chNext == 'f')
159: OR (chCmd == '<' AND chNext == '<');
160: } /* if */
161: } /* if */
162: /* a final chance to change our minds */
163: TkPeek(); /* load peek token information */
164: if ( (tk == tkStr)
165: AND (*vsbCmd != ' ')
166: AND (vsbTokPeek[0] != chNull)
167: AND !(strchr(";}", vsbTokPeek[0])) ) {
168: fCommand = false;
169: } /* if */
170: } /* if */
171:
172: if (!fCommand) {
173: /* assume it is a beginning expression */
174: vipd = IpdFAdr(AdrFIfdLn(vifd, viln)); /* force things right */
175: if ((tkRet = TkFExpr(&adrLong, rgTy)) != tkNil) {
176: valExp = ValFAdr(adrLong, rgTy); /* many cmds just want value */
177: valShort = valExp;
178: fHaveValue = true;
179: }
180: else {
181: if (PrecFTk(tkRet))
182: tk = TkNext();
183: UError("Unknown variable - %s", vsbTok);
184: } /* if */
185: } /* if */
186:
187: cnt = 1;
188: chCmd = vsbTok[0];
189: switch (chCmd) {
190: default:
191: vcmdDef = cmdNil;
192: UError("Unknown command `%c' (%#o)\n", chCmd, chCmd);
193: case '\n':
194: case '~':
195: case chNull: /* default command */
196: if (!fHaveValue) {
197: switch (vcmdDef) {
198: case cmdPrint:
199: viln++;
200: PrintLine(viln, 1, true);
201: break;
202: case cmdUpArrow:
203: case cmdDisplay:
204: i = IncFTyMode(vtyDot, vmode);
205: vdot += (vcmdDef == cmdUpArrow) ? -i : i;
206: DispVal(vdot, vtyDot, vmode, true, true, true);
207: printf("\n");
208: break;
209: case cmdLineSingle:
210: printf("s: ");
211: IbpFSingle(false, false);
212: break;
213: case cmdProcSingle:
214: printf("S: ");
215: IbpFSingle(true, false);
216: break;
217: } /* switch */
218: }
219: else if (tkRet == tkNumber) {
220: i = valShort;
221: if (i > 0)
222: viln = i;
223: else viln += i;
224: vslop = 0;
225: PrintLine(viln, 1, true);
226: vcmdDef = cmdPrint;
227: }
228: else if (tkRet == tkAdr) {
229: vdot = adrLong;
230: CopyTy(vtyDot, rgTy);
231: DispVal(vdot, vtyDot, modeNil, true, true, true);
232: printf("\n");
233: vcmdDef = cmdDisplay;
234: } /* if */
235: break;
236: case '+': /* go forward N (1) line and print it */
237: case '-': /* go backward N (1) line and print it */
238: i = GetExpr(&ty, tkNil);
239: if (ty == tyNil)
240: i = 1;
241: viln += (chCmd=='-') ? -abs(i) : abs(i);
242: PrintLine(viln, 1, true);
243: vcmdDef = cmdPrint;
244: continue;
245: case '!':
246: CallShell(vsbCmd); /* shell escape */
247: vsbCmd = sbNil;
248: break;
249: case '^': /* attempt to move backward, displaying memory */
250: GetMode(vmode);
251: vdot -= IncFTyMode(vtyDot, vmode);
252: DispVal(vdot, vtyDot, vmode, true, true, true);
253: printf("\n");
254: vcmdDef = cmdUpArrow;
255: break;
256: case '/': /* 2 commands: 'X/Y' == display *X in format Y
257: * '/hi mom' == search FORWARDS and print
258: */
259: case '?': /* 2 commands: 'X?Y' == display X in format Y
260: * '?hi mom' == search BACKWARDS and print
261: */
262: if (!fHaveValue) {
263: /* search for something */
264: if (*vsbCmd != chNull) {
265: strcpy(vsbTarget, vsbCmd);
266: *vsbCmd = chNull;
267: } /* if */
268: vchSearch = chCmd;
269: Find(vsbTarget, (chCmd=='?'));
270: vcmdDef = cmdPrint;
271: }
272: else {
273: vdot = adrLong;
274: CopyTy(vtyDot, rgTy);
275: GetMode(vmode);
276: if (chCmd == '/') {
277: /* this prints the CONTENTS of an address */
278: DispVal(vdot, vtyDot, vmode, true, true, true);
279: vcmdDef = cmdDisplay;
280: }
281: else {
282: /* this prints an ADDRESS */
283: vmode->cnt = 1;
284: DispVal(vdot, vtyDot, vmode, true, false, false);
285: vcmdDef = cmdNil;
286: } /* if */
287: printf("\n");
288: } /* if */
289: break;
290: case '<': /* playback commands */
291: EatFilename(sbName, &vsbCmd);
292: SetPlayback(sbName, (vsbTok[1] == '<'));
293: break;
294: case '>': /* record commands */
295: TkPeek();
296: if (vsbTokPeek[1] == chNull) {
297: if ( (vsbTokPeek[0] == 't')
298: OR (vsbTokPeek[0] == 'f')) {
299: TkNext(); /* actually eat next token */
300: StateRecord(vsbTok[0] == 't');
301: break;
302: }
303: else if (vsbTokPeek[0] == 'c') {
304: TkNext(); /* actually eat next token */
305: SetRecord(sbNil);
306: break;
307: } /* if */
308: /* we fall through on other, 1 character filenames */
309: } /* if */
310: EatFilename(sbName, &vsbCmd);
311: SetRecord(sbName);
312: break;
313: case ';': /* just a command delimiter */
314: vcmdDef = cmdNil;
315: break;
316: case 'A': /* toggle main assertion state */
317: if (viadMac > 0)
318: vas = (vas==asSuspended) ? asActive : asSuspended;
319: printf("Assertions are %s\n", (vas==asSuspended) ?
320: "SUSPENDED" : "ACTIVE");
321: vcmdDef = cmdNil;
322: break;
323: case 'a': /* maintain assertion list */
324: if (fHaveValue) {
325: TkNext();
326: switch (vsbTok[0]) {
327: case 'a':
328: as = asActive;
329: break;
330: case 'd':
331: as = asNil;
332: break;
333: case 's':
334: as = asSuspended;
335: break;
336: default:
337: UError("Invalid assertion maintenance command");
338: } /* switch */
339: ModAssert(valShort, as);
340: break;
341: } /* if */
342: if ((sbTemp=EatCmdList()) != sbNil)
343: AddAssert(sbTemp);
344: break;
345: case 'B': /* list all breakpoints */
346: ListBp();
347: break;
348: case 'b': /* set (set again) a break point */
349: vipd = IpdFAdr(AdrFIfdLn(vifd, viln));
350: chBp = vsbTok[1];
351: sbBp = EatCmdList();
352: ibp = ibpNil;
353: if (chBp == 'a') {
354: if (!fHaveValue)
355: UError("correct form is `address ba [<cmds>]'");
356: else
357: adr = valShort;
358: ibp = IbpFAdr(adr, 1, sbBp);
359: }
360: else if (chBp == chNull) {
361: /* vanilla breakpoint */
362: i = (fHaveValue) ? valShort : viln;
363: adr = AdrFIfdLn(vifd, i);
364: ibp = IbpFAdr(adr, 1, sbBp);
365: }
366: else {
367: ch = (isupper(chBp)) ? tolower(chBp) : chBp;
368: i = (fHaveValue) ? valShort : (ch=='u') ? 1 : -1;
369: ibp = IbpFSet(chBp, i, sbBp);
370: } /* if */
371: if (ibp != ibpNil) {
372: PrintPos(vrgBp[ibp].adr, fmtProc+fmtLn+fmtSave);
373: printf(":b \n");
374: } /* if */
375: vcmdDef = cmdNil;
376: break;
377: case 'C':
378: case 'c':
379: vipd = IpdFAdr(AdrFIfdLn(vifd, viln));
380: if (fHaveValue) {
381: /* we have a continuance count */
382: i = valShort;
383: if (vibp != ibpNil)
384: vrgBp[vibp].count = i;
385: } /* if */
386: i = GetExpr(&ty, tkNil);
387: if (ty != tyNil) {
388: adr = AdrFIfdLn(vifd, i);
389: ibp = IbpFAdr(adr, -1, "");
390: } /* if */
391: if (chCmd == 'c')
392: vsig = 0; /* do not pass signal back to child */
393: IbpFRun(ptResume);
394: vcmdDef = cmdNil;
395: continue;
396: case 'D':
397: ClearAll();
398: vcmdDef = cmdNil;
399: break;
400: case 'd':
401: adr = adrNil;
402: if (!fHaveValue)
403: adr = AdrFIfdLn(vifd, viln);
404: else if (valShort > 0
405: AND valShort < vibpMac) /* make sure it is range */
406: adr = vrgBp[valShort].adr;
407: if ((adr == adrNil)
408: OR (!FClearBp(adr)) ) {
409: printf("No such breakpoint\n");
410: ListBp();
411: break;
412: } /* if */
413: vcmdDef = cmdNil;
414: break;
415: case 'e':
416: adr = AdrFIfdLn(vifd, viln);
417: tk = TkPeek();
418: if (tk == tkNil) {
419: PrintPos(adr, fmtFile+fmtProc+fmtLn+fmtEol);
420: }
421: else {
422: fDidit = false;
423: EatFilename(sbName, &vsbCmd);
424: if (strchr(sbName, '.') == NULL) {
425: if ((ipd = IpdFName(sbName)) != ipdNil) {
426: OpenIpd(ipd, true);
427: PrintPos(adrNil,fmtFile+fmtProc+fmtLn+fmtPrint);
428: fDidit = true;
429: } /* if */
430: } /* if */
431: if (!fDidit) {
432: strcpy(vsbFileTemp, sbName);
433: if ((ifd = IfdFName(vsbFileTemp)) == vifdNil)
434: ifd = vifdTemp;
435: ifd = IfdFOpen(ifd);
436: if (ifd != vifdNil) {
437: PrintPos(adrNil, fmtFile+fmtLn+fmtPrint);
438: fDidit = true;
439: } /* if */
440: } /* if */
441: if (!fDidit)
442: UError("No such procedure or file name: %s",sbName);
443: } /* if */
444: vcmdDef = cmdPrint;
445: break;
446: case 'E':
447: cnt = (fHaveValue) ? valShort : 0;
448: OpenStack(cnt);
449: vcmdDef = cmdPrint;
450: break;
451: case 'F': /* find and fix bug */
452: FindAndFix();
453: break;
454: case 'f': /* set address display format */
455: tk = TkNext();
456: if (tk == tkStrConstant) {
457: strncpy(vsbFmt, vsbTok, 20); /* snarf */
458: vsbFmt[19] = chNull; /* just to be safe */
459: }
460: else if (tk == tkSemi) {
461: vsbFmt[0] = chNull;
462: }
463: else {
464: UError("Bad argument to the 'f' command");
465: } /* if */
466: vcmdDef = cmdNil;
467: break;
468: case 'g': /* 'goto' command (I'm SORRY!!!!!!!!) */
469: adr = GetExpr(&ty, tkNil);
470: if (ty == tyNil) {
471: UError("I need a linenumber");
472: } /* if */
473: GotoLn(adr);
474: break;
475: case 'i': /* conditional command */
476: fDoit = GetExpr(&ty, tkNil);
477: if (ty == tyNil)
478: fDoit = false;
479: tk = vtk; /* look ahead by expression parser */
480: if (tk != tkLCB)
481: UError("Missing {");
482: if (!fDoit) {
483: vsbCmd = SbFEob(vsbCmd); /* eat the first block */
484: tk = TkNext();
485: if (tk != tkLCB)
486: continue; /* we ate first part of next command */
487: } /* if */
488: break;
489: case '{': /* beginning of block, eat block */
490: vsbCmd = SbFEob(vsbCmd); /* returns ptr to matching }+1 */
491: break;
492: case '}': /* end of block */
493: break; /* we just throw it away */
494: case 'I': /* information about cdb's state */
495: ShowState();
496: vcmdDef = cmdNil;
497: break;
498: case 'k':
499: if (vpid == pidNil)
500: UError("No process to kill");
501: if (!YesNo("Really kill child? "))
502: break; /* their finger slipped or something */
503: KillChild();
504: printf("process killed\n");
505: vcmdDef = cmdNil;
506: break;
507: case 'l':
508: ListSomething();
509: break;
510: case 'L':
511: PrintPos(vpc, fmtFile+fmtProc+fmtLn+fmtPrint);
512: /* which puts us at the break */
513: vcmdDef = cmdPrint;
514: break;
515: case 'M': /* print|set map values */
516: DoMap();
517: vcmdDef = cmdNil;
518: break;
519: case 'p':
520: if (fHaveValue) {
521: i = valShort;
522: if (i < 0)
523: viln += i;
524: else viln = i;
525: vslop = 0;
526: } /* if */
527: cnt = GetExpr(&ty, tkNil);
528: if ((ty == tyNil) OR (cnt <= 0))
529: cnt = 1;
530: PrintLine(viln, cnt, true);
531: vcmdDef = cmdPrint;
532: continue;
533: case 'q':
534: if (!YesNo("Really quit? "))
535: break; /* their finger slipped or something */
536: exit(0);
537: /* NOTREACHED */
538: break;
539: case 'Q': /* quiet command, just eat it */
540: break;
541: case 'r':
542: case 'R':
543: ibp = IbpFNewChild((chCmd == 'R') ? sbNil : vsbCmd);
544: if (ibp == ibpNil)
545: /* just fire it up */
546: ibp = IbpFRun(ptResume);
547: vcmdDef = cmdNil;
548: break;
549: case 'S':
550: case 's':
551: i = (fHaveValue) ? valShort : 1;
552: vcmdDef = (chCmd=='s') ? cmdLineSingle : cmdProcSingle;
553: while (i--)
554: if (ibpNil != IbpFSingle(chCmd=='S', false))
555: break;
556: break;
557: case 'T':
558: case 't':
559: i = (fHaveValue) ? valShort : 20; /* default to 20 deep */
560: StackTrace(i, (chCmd=='T')); /* do locals, too, on T */
561: vcmdDef = cmdNil;
562: break;
563: case 'W':
564: cnt = 21;
565: case 'w':
566: viln = (fHaveValue) ? valShort : viln;
567: vslop = 0;
568: ilnSave = viln;
569: if (cnt == 1)
570: cnt = 11; /* i.e. - we didn't come through W */
571: i = GetExpr(&ty, tkNil);
572: if ((ty != tyNil) AND (i >= 1))
573: cnt = i;
574: ln = Max(viln-cnt/2, 0);
575: cLn = Min(cnt/2, viln-ln);
576: PrintLine(ln, cLn, true);
577: printf(">"); /* shows them which line they are on */
578: viln++;
579: cLn = Min(cnt-cLn, vrgFd[vifd].ilnMac-viln+1);
580: PrintLine(viln, cLn, true);
581: viln = ilnSave;
582: vcmdDef = cmdPrint;
583: continue;
584: case 'x': /* clear command line and exit current level */
585: if ((!fHaveValue) OR (valShort == 0))
586: vsbCmd = PopCmd();
587: return(true);
588: case 'z':
589: sig = (fHaveValue) ? valShort : vsig;
590: TkNext();
591: if (sig == SIGTRAP)
592: printf(
593: "WARNING: You are modifying the breakpoint signal!\n");
594: SaMaintain(sig, vsbTok);
595: break;
596: case 'Z':
597: vcaseMod = (vcaseMod) ? 0 : 040;
598: printf("Searches will %sbe case sensitive\n",
599: (vcaseMod!=0) ? "NOT " : "");
600: vcmdDef = cmdNil;
601: break;
602: } /* switch */
603: }
604: while ((tk = TkNext()) != tkNil);
605:
606: return(fTop);
607: } /* FDoCommand */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.