|
|
Power 6/32 Unix version 1.2b
static char sccsid[] = "@(#)cmd.c 2.8";
#include <ctype.h>
#include <stdio.h>
#include "cdb.h"
#include <signal.h>
static char vsbTarget[100]; /* used for string searches */
static char vchSearch = '/'; /* contains either ? or / */
export CMDE vcmdDef;
export char *vsbCmd, *vsbCmdOld;
export long vdot;
export TYR vtyDot[cTyMax];
export int viln, vslop; /* line number & offset from true line number */
export char vsbFileTemp[80]; /* name of vifdTemp file */
/* C A L L S H E L L */
local void CallShell(sbCmd)
char *sbCmd;
{
char stShell[20];
if ((sbCmd == sbNil) OR (*sbCmd == chNull)) {
sprintf(stShell, "%s -i", getenv("SHELL"));
sbCmd = stShell;
} /* if */
system(sbCmd);
printf("\nback in cdb, debugging %s\n", vsbSymfile);
} /* CallShell */
/* E A T C M D L I S T */
export char * EatCmdList()
{
char *sbCmd, *sbTemp;
TKE tk;
sbCmd = vsbCmd;
tk = TkPeek();
if (tk == tkNil)
return(sbNil);
if (tk != tkLCB) {
vsbCmd = sbNil; /* give caller the rest of line */
}
else {
tk = TkNext(); /* eat { */
sbCmd = vsbCmd;
sbTemp = SbFEob(vsbCmd) - 1;
if (*sbTemp == '}')
*sbTemp = chNull;
vsbCmd = sbTemp + 1;
} /* if */
while (*sbCmd == ' ')
sbCmd++;
return(sbCmd);
} /* EatCmdList */
/* E A T F I L E N A M E */
local void EatFilename(sbName, psbIn)
char *sbName, **psbIn;
{
int cch;
char *sbIn;
sbIn = *psbIn;
while (*sbIn == '\t' OR *sbIn == ' ')
sbIn++;
cch = strcspn(sbIn, "\t ;}");
strncpy(sbName, sbIn, cch);
sbName[cch] = chNull;
*psbIn = sbIn + cch;
} /* EatFilename */
/* S B F E O B */
export char *SbFEob(sb)
char *sb;
{
int cNest;
/* return pointer to AFTER '}', or to the chNull */
cNest = (*sb == '{') ? 0 : 1;
while (*sb) {
if (*sb == '{')
cNest++;
else if (*sb == '}')
if (--cNest == 0)
return(sb+1);
sb++;
} /* while */
return(sb);
} /* SbFEob */
/* F D O C O M M A N D */
export FLAGT FDoCommand(sbCmdIn, fTop)
char *sbCmdIn;
FLAGT fTop;
{
int valShort, ln, cLn, cnt, ifd, ipd;
int sig, ibp, i, ilnSave;
FLAGT fHaveValue, fDidit, fDoit, fCommand;
char ch, chBp, chCmd, chNext;
char *sbBp, *sbTemp, *sbCmds, *sbTwoChars;
char sbName[80];
long valExp, adrLong;
ADRT adr;
TKE tk, tkRet;
ASE as;
pTYR ty;
TYR rgTy[cTyMax];
/* the commands */
sbCmds = "\n<>-+?/^!~;{}AabBcCdDeEfFgiIklLMpqQrRsStTwWxzZ";
sbTwoChars = "<bi"; /* commands of two or more characters */
if (!fTop)
PushCmd(vsbCmd);
vsbCmd = vsbCmdOld = sbCmdIn;
tk = TkNext();
do {
if ((tk == tkStr) AND (FSbCmp("help", vsbTok))) {
Help();
vcmdDef = cmdNil;
return(fTop);
}
else if (tk == tkStrConstant) {
printf("%s", vsbTok);
vcmdDef = cmdNil;
tk = TkNext();
continue;
} /* if */
/* we guess whether to parse an expression */
/* this is a little weird because we try to do the `right' thing */
adrLong = 0;
chCmd = vsbTok[0];
fHaveValue = false;
fCommand = (tk == tkNil);
if (strchr(sbCmds, chCmd) != NULL) {
/* the first letter LOOKS like a command, keep going */
fCommand = (vcbTok == 1);
if ((vcbTok > 1) AND (tk == tkStr)) {
/* it is longer than 1 character, might be a variable name */
chNext = vsbTok[1];
if ( (vcbTok == 2)
AND (strchr(sbTwoChars, chCmd) != NULL) ) {
fCommand = (chCmd == 'b' AND strchr("abBtTuUxX", chNext))
OR (chCmd == 'i' AND chNext == 'f')
OR (chCmd == '<' AND chNext == '<');
} /* if */
} /* if */
/* a final chance to change our minds */
TkPeek(); /* load peek token information */
if ( (tk == tkStr)
AND (*vsbCmd != ' ')
AND (vsbTokPeek[0] != chNull)
AND !(strchr(";}", vsbTokPeek[0])) ) {
fCommand = false;
} /* if */
} /* if */
if (!fCommand) {
/* assume it is a beginning expression */
vipd = IpdFAdr(AdrFIfdLn(vifd, viln)); /* force things right */
if ((tkRet = TkFExpr(&adrLong, rgTy)) != tkNil) {
valExp = ValFAdr(adrLong, rgTy); /* many cmds just want value */
valShort = valExp;
fHaveValue = true;
}
else {
if (PrecFTk(tkRet))
tk = TkNext();
UError("Unknown variable - %s", vsbTok);
} /* if */
} /* if */
cnt = 1;
chCmd = vsbTok[0];
switch (chCmd) {
default:
vcmdDef = cmdNil;
UError("Unknown command `%c' (%#o)\n", chCmd, chCmd);
case '\n':
case '~':
case chNull: /* default command */
if (!fHaveValue) {
switch (vcmdDef) {
case cmdPrint:
viln++;
PrintLine(viln, 1, true);
break;
case cmdUpArrow:
case cmdDisplay:
i = IncFTyMode(vtyDot, vmode);
vdot += (vcmdDef == cmdUpArrow) ? -i : i;
DispVal(vdot, vtyDot, vmode, true, true, true);
printf("\n");
break;
case cmdLineSingle:
printf("s: ");
IbpFSingle(false, false);
break;
case cmdProcSingle:
printf("S: ");
IbpFSingle(true, false);
break;
} /* switch */
}
else if (tkRet == tkNumber) {
i = valShort;
if (i > 0)
viln = i;
else viln += i;
vslop = 0;
PrintLine(viln, 1, true);
vcmdDef = cmdPrint;
}
else if (tkRet == tkAdr) {
vdot = adrLong;
CopyTy(vtyDot, rgTy);
DispVal(vdot, vtyDot, modeNil, true, true, true);
printf("\n");
vcmdDef = cmdDisplay;
} /* if */
break;
case '+': /* go forward N (1) line and print it */
case '-': /* go backward N (1) line and print it */
i = GetExpr(&ty, tkNil);
if (ty == tyNil)
i = 1;
viln += (chCmd=='-') ? -abs(i) : abs(i);
PrintLine(viln, 1, true);
vcmdDef = cmdPrint;
continue;
case '!':
CallShell(vsbCmd); /* shell escape */
vsbCmd = sbNil;
break;
case '^': /* attempt to move backward, displaying memory */
GetMode(vmode);
vdot -= IncFTyMode(vtyDot, vmode);
DispVal(vdot, vtyDot, vmode, true, true, true);
printf("\n");
vcmdDef = cmdUpArrow;
break;
case '/': /* 2 commands: 'X/Y' == display *X in format Y
* '/hi mom' == search FORWARDS and print
*/
case '?': /* 2 commands: 'X?Y' == display X in format Y
* '?hi mom' == search BACKWARDS and print
*/
if (!fHaveValue) {
/* search for something */
if (*vsbCmd != chNull) {
strcpy(vsbTarget, vsbCmd);
*vsbCmd = chNull;
} /* if */
vchSearch = chCmd;
Find(vsbTarget, (chCmd=='?'));
vcmdDef = cmdPrint;
}
else {
vdot = adrLong;
CopyTy(vtyDot, rgTy);
GetMode(vmode);
if (chCmd == '/') {
/* this prints the CONTENTS of an address */
DispVal(vdot, vtyDot, vmode, true, true, true);
vcmdDef = cmdDisplay;
}
else {
/* this prints an ADDRESS */
vmode->cnt = 1;
DispVal(vdot, vtyDot, vmode, true, false, false);
vcmdDef = cmdNil;
} /* if */
printf("\n");
} /* if */
break;
case '<': /* playback commands */
EatFilename(sbName, &vsbCmd);
SetPlayback(sbName, (vsbTok[1] == '<'));
break;
case '>': /* record commands */
TkPeek();
if (vsbTokPeek[1] == chNull) {
if ( (vsbTokPeek[0] == 't')
OR (vsbTokPeek[0] == 'f')) {
TkNext(); /* actually eat next token */
StateRecord(vsbTok[0] == 't');
break;
}
else if (vsbTokPeek[0] == 'c') {
TkNext(); /* actually eat next token */
SetRecord(sbNil);
break;
} /* if */
/* we fall through on other, 1 character filenames */
} /* if */
EatFilename(sbName, &vsbCmd);
SetRecord(sbName);
break;
case ';': /* just a command delimiter */
vcmdDef = cmdNil;
break;
case 'A': /* toggle main assertion state */
if (viadMac > 0)
vas = (vas==asSuspended) ? asActive : asSuspended;
printf("Assertions are %s\n", (vas==asSuspended) ?
"SUSPENDED" : "ACTIVE");
vcmdDef = cmdNil;
break;
case 'a': /* maintain assertion list */
if (fHaveValue) {
TkNext();
switch (vsbTok[0]) {
case 'a':
as = asActive;
break;
case 'd':
as = asNil;
break;
case 's':
as = asSuspended;
break;
default:
UError("Invalid assertion maintenance command");
} /* switch */
ModAssert(valShort, as);
break;
} /* if */
if ((sbTemp=EatCmdList()) != sbNil)
AddAssert(sbTemp);
break;
case 'B': /* list all breakpoints */
ListBp();
break;
case 'b': /* set (set again) a break point */
vipd = IpdFAdr(AdrFIfdLn(vifd, viln));
chBp = vsbTok[1];
sbBp = EatCmdList();
ibp = ibpNil;
if (chBp == 'a') {
if (!fHaveValue)
UError("correct form is `address ba [<cmds>]'");
else
adr = valShort;
ibp = IbpFAdr(adr, 1, sbBp);
}
else if (chBp == chNull) {
/* vanilla breakpoint */
i = (fHaveValue) ? valShort : viln;
adr = AdrFIfdLn(vifd, i);
ibp = IbpFAdr(adr, 1, sbBp);
}
else {
ch = (isupper(chBp)) ? tolower(chBp) : chBp;
i = (fHaveValue) ? valShort : (ch=='u') ? 1 : -1;
ibp = IbpFSet(chBp, i, sbBp);
} /* if */
if (ibp != ibpNil) {
PrintPos(vrgBp[ibp].adr, fmtProc+fmtLn+fmtSave);
printf(":b \n");
} /* if */
vcmdDef = cmdNil;
break;
case 'C':
case 'c':
vipd = IpdFAdr(AdrFIfdLn(vifd, viln));
if (fHaveValue) {
/* we have a continuance count */
i = valShort;
if (vibp != ibpNil)
vrgBp[vibp].count = i;
} /* if */
i = GetExpr(&ty, tkNil);
if (ty != tyNil) {
adr = AdrFIfdLn(vifd, i);
ibp = IbpFAdr(adr, -1, "");
} /* if */
if (chCmd == 'c')
vsig = 0; /* do not pass signal back to child */
IbpFRun(ptResume);
vcmdDef = cmdNil;
continue;
case 'D':
ClearAll();
vcmdDef = cmdNil;
break;
case 'd':
adr = adrNil;
if (!fHaveValue)
adr = AdrFIfdLn(vifd, viln);
else if (valShort > 0
AND valShort < vibpMac) /* make sure it is range */
adr = vrgBp[valShort].adr;
if ((adr == adrNil)
OR (!FClearBp(adr)) ) {
printf("No such breakpoint\n");
ListBp();
break;
} /* if */
vcmdDef = cmdNil;
break;
case 'e':
adr = AdrFIfdLn(vifd, viln);
tk = TkPeek();
if (tk == tkNil) {
PrintPos(adr, fmtFile+fmtProc+fmtLn+fmtEol);
}
else {
fDidit = false;
EatFilename(sbName, &vsbCmd);
if (strchr(sbName, '.') == NULL) {
if ((ipd = IpdFName(sbName)) != ipdNil) {
OpenIpd(ipd, true);
PrintPos(adrNil,fmtFile+fmtProc+fmtLn+fmtPrint);
fDidit = true;
} /* if */
} /* if */
if (!fDidit) {
strcpy(vsbFileTemp, sbName);
if ((ifd = IfdFName(vsbFileTemp)) == vifdNil)
ifd = vifdTemp;
ifd = IfdFOpen(ifd);
if (ifd != vifdNil) {
PrintPos(adrNil, fmtFile+fmtLn+fmtPrint);
fDidit = true;
} /* if */
} /* if */
if (!fDidit)
UError("No such procedure or file name: %s",sbName);
} /* if */
vcmdDef = cmdPrint;
break;
case 'E':
cnt = (fHaveValue) ? valShort : 0;
OpenStack(cnt);
vcmdDef = cmdPrint;
break;
case 'F': /* find and fix bug */
FindAndFix();
break;
case 'f': /* set address display format */
tk = TkNext();
if (tk == tkStrConstant) {
strncpy(vsbFmt, vsbTok, 20); /* snarf */
vsbFmt[19] = chNull; /* just to be safe */
}
else if (tk == tkSemi) {
vsbFmt[0] = chNull;
}
else {
UError("Bad argument to the 'f' command");
} /* if */
vcmdDef = cmdNil;
break;
case 'g': /* 'goto' command (I'm SORRY!!!!!!!!) */
adr = GetExpr(&ty, tkNil);
if (ty == tyNil) {
UError("I need a linenumber");
} /* if */
GotoLn(adr);
break;
case 'i': /* conditional command */
fDoit = GetExpr(&ty, tkNil);
if (ty == tyNil)
fDoit = false;
tk = vtk; /* look ahead by expression parser */
if (tk != tkLCB)
UError("Missing {");
if (!fDoit) {
vsbCmd = SbFEob(vsbCmd); /* eat the first block */
tk = TkNext();
if (tk != tkLCB)
continue; /* we ate first part of next command */
} /* if */
break;
case '{': /* beginning of block, eat block */
vsbCmd = SbFEob(vsbCmd); /* returns ptr to matching }+1 */
break;
case '}': /* end of block */
break; /* we just throw it away */
case 'I': /* information about cdb's state */
ShowState();
vcmdDef = cmdNil;
break;
case 'k':
if (vpid == pidNil)
UError("No process to kill");
if (!YesNo("Really kill child? "))
break; /* their finger slipped or something */
KillChild();
printf("process killed\n");
vcmdDef = cmdNil;
break;
case 'l':
ListSomething();
break;
case 'L':
PrintPos(vpc, fmtFile+fmtProc+fmtLn+fmtPrint);
/* which puts us at the break */
vcmdDef = cmdPrint;
break;
case 'M': /* print|set map values */
DoMap();
vcmdDef = cmdNil;
break;
case 'p':
if (fHaveValue) {
i = valShort;
if (i < 0)
viln += i;
else viln = i;
vslop = 0;
} /* if */
cnt = GetExpr(&ty, tkNil);
if ((ty == tyNil) OR (cnt <= 0))
cnt = 1;
PrintLine(viln, cnt, true);
vcmdDef = cmdPrint;
continue;
case 'q':
if (!YesNo("Really quit? "))
break; /* their finger slipped or something */
exit(0);
/* NOTREACHED */
break;
case 'Q': /* quiet command, just eat it */
break;
case 'r':
case 'R':
ibp = IbpFNewChild((chCmd == 'R') ? sbNil : vsbCmd);
if (ibp == ibpNil)
/* just fire it up */
ibp = IbpFRun(ptResume);
vcmdDef = cmdNil;
break;
case 'S':
case 's':
i = (fHaveValue) ? valShort : 1;
vcmdDef = (chCmd=='s') ? cmdLineSingle : cmdProcSingle;
while (i--)
if (ibpNil != IbpFSingle(chCmd=='S', false))
break;
break;
case 'T':
case 't':
i = (fHaveValue) ? valShort : 20; /* default to 20 deep */
StackTrace(i, (chCmd=='T')); /* do locals, too, on T */
vcmdDef = cmdNil;
break;
case 'W':
cnt = 21;
case 'w':
viln = (fHaveValue) ? valShort : viln;
vslop = 0;
ilnSave = viln;
if (cnt == 1)
cnt = 11; /* i.e. - we didn't come through W */
i = GetExpr(&ty, tkNil);
if ((ty != tyNil) AND (i >= 1))
cnt = i;
ln = Max(viln-cnt/2, 0);
cLn = Min(cnt/2, viln-ln);
PrintLine(ln, cLn, true);
printf(">"); /* shows them which line they are on */
viln++;
cLn = Min(cnt-cLn, vrgFd[vifd].ilnMac-viln+1);
PrintLine(viln, cLn, true);
viln = ilnSave;
vcmdDef = cmdPrint;
continue;
case 'x': /* clear command line and exit current level */
if ((!fHaveValue) OR (valShort == 0))
vsbCmd = PopCmd();
return(true);
case 'z':
sig = (fHaveValue) ? valShort : vsig;
TkNext();
if (sig == SIGTRAP)
printf(
"WARNING: You are modifying the breakpoint signal!\n");
SaMaintain(sig, vsbTok);
break;
case 'Z':
vcaseMod = (vcaseMod) ? 0 : 040;
printf("Searches will %sbe case sensitive\n",
(vcaseMod!=0) ? "NOT " : "");
vcmdDef = cmdNil;
break;
} /* switch */
}
while ((tk = TkNext()) != tkNil);
return(fTop);
} /* FDoCommand */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.