0707070001000311610407550000000000010000041577120460261373600000200000000000. 0707070001000311630407550000000000010000031577210460260163300000400000000000cdb 0707070001000311641006440000000000010000010000000454650113100001400000000000cdb/GET.err 0707070001000311651004440000000000010000011577300454650113100001500000025476cdb/access.c /* $Header: access.c,v 6.1 86/08/18 13:14:26 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <errno.h>
#include "cdb.h"

/*
 * This file contains routine to read and write information
 * from the child process.  As it currently stands, this is done
 * by calling `Ptrace'.  This will change when we get farther on
 * in the remote debuging/multi-process stuff.
 */

#define cbCacheMax	2048
char		vsbCommCache[cbCacheMax];
ADRT		vadrCacheMin, vadrCacheMax; /* the address range in the cache */
export FLAGT	vfCacheValid = false;


/* G E T   U S E R */

export REGT GetUser(adr)
ADRT    adr;
{
    int4	ret;
    REGT	val;

    /* Read information from the `user' structure */

    if (adr == adrNil)
	return(0);

    if (v->pid != pidNil) {

	ret = Ptrace(ptReadUser, v->pid, (char *)adr, 0);
	if ((ret == -1) AND (errno == EIO))
	    SysPanic("Failed on ptReadUser - %s.", SbFAdr(adr, true));
	val = ret;

    } else if (v->fnCore != fnNil) {

	if (lseek(v->fnCore, adr, seekBegin) < 0L)
	    UError("Address (%s) not found.", SbFAdr(adr, true));
	if (read(v->fnCore, &val, v->cpu->cbPointer) < 1)
	    UError("Cannot read location (%s).", SbFAdr(adr, true));

    } else {

	UError("No child process AND no core file.");

    } /* if */

    return(val);
} /* GetUser */


/* P U T   U S E R */

export void PutUser(adr, val)
ADRT    adr;
REGT    val;
{
    int2	i;

    /* Write information to the `user' structure */

    if (adr == adrNil)
	return;

    if (v->pid != pidNil) {

	i = Ptrace(ptWriteUser, v->pid, (char *)adr, val);
	if ((i == -1) AND (errno == EIO))
	    SysPanic("Failed on ptWriteUser - %s, %d.", SbFAdr(adr, true), val);

    } else if (v->fnCore != fnNil) {

	if (lseek(v->fnCore, adr, seekBegin) < 0L)
	    UError("Address (%s) not found.", SbFAdr(adr, true));
	if (write(v->fnCore, &val, v->cpu->cbPointer) < 1 )
	    UError("Cannot write location (%s).", SbFAdr(adr, true));

    } else {

	UError("No child process AND no core file.");

    } /* if */
} /* PutUser */


/* G E T   W O R D */

export int GetWord(adr, space)
ADRT	adr;
int2	space;
{
    /* Read an `int' from the child */

    return(Access(accRead, adr, space, 0));
} /* GetWord */


/* P U T   W O R D */

export void PutWord(adr, space, val)
ADRT	adr;
int2	space;
int	val;
{
    /* Write an `int' to the child */

    Access(accWrite, adr, space, val);
} /* PutWord */


/* S E T   C O M M   C A C H E */

export void SetCommCache(adrSrc, cb)
ADRT	adrSrc;
int	cb;
{
    int		cbCache, cbSlop, cbMove;
    ADRT	adrMax;
    
    if (!vfUseCache)
	return;

    /* This cache is used for READING large blocks from the
     * child process.  This can substantially reduce the communications
     * overhead during stack traces and other large read operations.
     * The cache also has write-through capabilities, but this
     * is simply to help with the read operations.
     */

    if (cb > cbCacheMax)
	cb = cbCacheMax;

    adrMax = adrSrc + cb;

    if (!vfCacheValid)
	vadrCacheMin = vadrCacheMax = 0;

    cbCache = vadrCacheMax - vadrCacheMin;

    /* see if we already have part of this in memory */

    if ((adrSrc >= vadrCacheMin) AND (adrSrc < vadrCacheMax)) {
	/* we have the beginning of it */
	if (adrMax <= vadrCacheMax)
	    return;	/* it's ALL in the cache already */

	cbSlop = adrMax - vadrCacheMax; /* amount NOT in cache */
	cbMove = cbSlop + (cbCache - cbCacheMax); /* cache motion needed */

	if (cbMove > 0) {
	    /* fix it so there is room to read cbSlop bytes */
	    MoveBytes(vsbCommCache, vsbCommCache+cbMove, cbCache-cbMove);
	    vadrCacheMin += cbMove;
	} /* if */

	/* fill in end of buffer */
	if (v->fnComm == fnNil)
	    GetBlock(vadrCacheMax, spaceData,
			(ADRT)(vsbCommCache+cbCache), cbSlop);
	else
	    XBlockTransfer(v->pid, (ADRT)(vsbCommCache + cbCache),
			vadrCacheMax, cbSlop, false);
	vadrCacheMax += cbSlop;

    } else if ((adrMax > vadrCacheMin) AND (adrMax <= vadrCacheMax)) {

	/* we have the end of it */
	if (adrSrc >= vadrCacheMin)
	    return;	/* it's ALL in the cache already */

	cbSlop = vadrCacheMin - adrSrc; /* amount NOT in cache */
	cbMove = cbSlop + (cbCache - cbCacheMax); /* cache motion needed */

	if (cbMove > 0) {
	    /* fix it so there is room to read cbSlop bytes */
	    MoveBytes(vsbCommCache+cbMove, vsbCommCache, cbCache-cbMove);
	    vadrCacheMax -= cbMove;
	} /* if */

	vadrCacheMin = adrSrc;
	/* fill in head of buffer */
	if (v->fnComm == fnNil)
	    GetBlock(adrSrc, spaceData, (ADRT)vsbCommCache, cbSlop);
	else
	    XBlockTransfer(v->pid, (ADRT)vsbCommCache, adrSrc, cbSlop, false);

    } else {

	/* total miss - read it in */
	if (v->fnComm == fnNil)
	    GetBlock(adrSrc, spaceData, (ADRT)vsbCommCache, cb);
	else
	    XBlockTransfer(v->pid, (ADRT)vsbCommCache, adrSrc, cb, false);
	vadrCacheMin = adrSrc;
	vadrCacheMax = adrSrc + cb;
    } /* if */

    vfCacheValid = true;
} /* SetCommCache */


/* R E A D   D A T A */

export void ReadData(adrDest, adrSrc, cb)
ADRT	adrDest, adrSrc;
int2	cb;
{
    /* Block read from data space */

    GetBlock(adrSrc, spaceData, adrDest, cb);
} /* ReadData */


/* W R I T E   D A T A */

export void WriteData(adrDest, adrSrc, cb)
ADRT	adrDest, adrSrc;
int2	cb;
{
    /* Block write to data space */

    PutBlock(adrDest, spaceData, adrSrc, cb);
} /* WriteData */


/* B L O C K   T R A N S F E R */

export void BlockTransfer(adrDest, adrSrc, space, cb)
ADRT	adrDest, adrSrc;
int2	space, cb;
{
#define cbMax        1024
    int2		cbMove;
    char	buf[cbMax], *sbT = buf;

    /* Move an arbitrary block ->within<- the child */

    while (cb > 0) {
	cbMove = Min(cb, cbMax);
	GetBlock(adrSrc, space, (ADRT)sbT, cbMove);
	PutBlock(adrDest, space, (ADRT)sbT, cbMove);
	cb -= cbMove;
	sbT += cbMove;
    } /* while */
} /* BlockTransfer */


/* A C C E S S */

export int Access(accRequest, adr, space, value)
int2	accRequest, space;
int	value;
ADRT    adr;
{
    int		ret, val, pt, fn;
    int2	*pshort;
    int4	*plong;
    ADRT	adrTemp;
    FLAGT       fRead;
    pMAPR	map;

    /* Read or Write to the Data or Text space of the child */

    fRead = (accRequest == accRead);
    if ((v->pid != pidNil)		/* live process */
       AND ((space != spaceText)	/* data area OR */
	  OR (! v->fPureText)) ) {	/* corruptible text */

	/* we get the info from the process */

	if (space == spaceData) {
	    pt = (fRead) ? ptReadD : ptWriteD;  /* data space */
	} else {
	    pt = (fRead) ? ptReadI : ptWriteI;  /* instruction space */
	    adr += v->adrText;	/* add in offset of text space */
	} /* if */

	/* try to avoid going over comm link */
	if (vfUseCache			/* They want us to use cache */
	   AND vfCacheValid		/* and it is correct */
	   AND (space == spaceData)	/* We only cache data space */
	   AND (adr >= vadrCacheMin)
	   AND ((adr+v->cpu->cbInt) <= vadrCacheMax)) {

	    /* it is in the cache */
	    if (v->cpu->cbInt == 2) {
		pshort = (int2 *) (vsbCommCache + (adr - vadrCacheMin));
		if (fRead)
		    return(*pshort);
		else
		    *pshort = value;
	    } else {
		plong = (int4 *) (vsbCommCache + (adr - vadrCacheMin));
		if (fRead)
		    return(*plong);
		else
		    *plong = value;
	    } /* if */
	} /* if in cache */

	errno = 0;
	val = Ptrace(pt, v->pid, (char *)adr, value);

	if ((val == -1) AND (errno == EIO)) {
	    if (v->ps == psRunning)
	       UError("Cannot read data from a running process: %d.",
			IprFPr(v));

	    if (vfInDisplay) {
		vfBadAddress = true;
		UError(sbNil);	/* let DisplaySe do it's own thing */
	    } /* if */
	    UError("Cannot %s location (%s).",
		((fRead) ? "read" : "write"), SbFAdr(adr, true));
	} /* if */
	return(val);
    } /* if */

    /* we do not (or cannot) get it from the process.
     * Get it from a file.
     */

    val = 0;

    if ((space == spaceData)
       AND (v->fnCore != fnNil)
       AND ((adrTemp = AdrFPurify(adr, false)) != adrNil) ) {
	fn = v->fnCore;
	adr = adrTemp;
    } else {
	adr = AdrFPurify(adr, true);
	fn = v->fnExec;
    } /* if */

    if (adr == adrNil)
	UError("Address not found (%s).", SbFAdr(adr, true));

    if (lseek(fn, adr, seekBegin) < 0L)
	UError("Address not found (%s).", SbFAdr(adr, true));

    ret = (fRead) ? read(fn, &val, v->cpu->cbInt) 
		  : write(fn, &value, v->cpu->cbInt);

    if (ret != v->cpu->cbInt)
	UError("Cannot %s location (%s): %s.",
		((fRead) ? "read" : "write"),
		SbFAdr(adr, true), SbFError(errno));
    return(val);
} /* Access */


/* A D R   F   P U R I F Y */

export ADRT AdrFPurify(adr, fExec)
ADRT	adr;
FLAGT	fExec;
{
#define FInBounds(x, low, high) ((x>=low) && (x<high))
    pMAPR	map;

    /* We first make sure that the appropriate file is open,
     * then we use the map to move the virutal address to the
     * correct file offset.
     */

    if (fExec) {
	if (v->fnExec == fnNil) {
	    v->fnExec = open(v->sbExec, O_RDONLY);
	    if (v->fnExec == fnNil)
		Panic("Cannot open %s: %s.", v->sbExec, SbFError(errno));
	} /* if */
	map = &v->mapExec;
    } else {
	if (v->fnCore == fnNil) {
	    if (v->sbCore == sbNil)
		return(adrNil);
	    v->fnCore = open(v->sbExec, O_RDONLY);
	    if (v->fnCore == fnNil) {
		printf("Cannot open %s: %s\n", v->sbCore, SbFError(errno));
		free(v->sbCore);
		v->sbCore = sbNil;
		UError(sbNil);
	    } /* if */
	} /* if */
	map = &v->mapCore;
    } /* if */

    if (FInBounds(adr, map->b1, map->e1)) {
	adr += map->f1 - map->b1;
    } else if (FInBounds(adr, map->b2, map->e2)) {
	adr += map->f2 - map->b2;
    } else {
	adr = adrNil;
    } /* if */
    return(adr);
} /* AdrFPurify */


/* D O   M A P */

export void DoMap()
{
    int		i;
    char        ch;
    ADRT        *padr, adrT;
    TKE         tk;
    SER		ase;

    tk = TkNext();
    if (tk != tkNil) {
	/* they want to modify the map in some way */
	ch = vsbTok[0];
	if ( (tk != tkStr)
	   OR (ch != 'E' AND ch != 'C') ) {
	    UError("usage: M (E|C) [exp] ; [exp] ; .. (up to 6 expressions).");
	} else {
	    padr = (ch == 'E') ? &(v->mapExec.b1) : &(v->mapCore.b1);
	    TkNext();
	} /* if */

	for (i=0; i<6; i++, padr++) {
	    if (vtk == tkSemi) {
		TkNext();
		continue;
	    } /* if */
	    adrT = LongFExpr(&ase, vtk);
	    if (ase.asym.st == stNil)
		break;
	    *padr = adrT;
	    if (vtk == tkSemi)
		TkNext();
	} /* for */
    } /* if */

    if (v->sbExec != sbNil) {
	printf("Executable file (%s):\n", v->sbExec);
	printf(" %10s", SbFAdr(v->mapExec.b1, false));
	printf(" %10s", SbFAdr(v->mapExec.e1, false));
	printf(" %10s\n", SbFAdr(v->mapExec.f1, false));
	printf(" %10s", SbFAdr(v->mapExec.b2, false));
	printf(" %10s", SbFAdr(v->mapExec.e2, false));
	printf(" %10s\n", SbFAdr(v->mapExec.f2, false));
    } /* if */

    if (v->sbCore != sbNil) {
	printf("\nCore file (%s):\n", v->sbCore);
	printf(" %10s", SbFAdr(v->mapCore.b1, false));
	printf(" %10s", SbFAdr(v->mapCore.e1, false));
	printf(" %10s\n", SbFAdr(v->mapCore.f1, false));
	printf(" %10s", SbFAdr(v->mapCore.b2, false));
	printf(" %10s", SbFAdr(v->mapCore.e2, false));
	printf(" %10s\n", SbFAdr(v->mapCore.f2, false));
    } /* if */
} /* DoMap */
0707070001000311661004440000000000010000011600540454650113100001500000007605cdb/assert.c /* $Header: assert.c,v 5.9 86/05/28 08:02:33 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* These routines maintain the list of assertions.  */

#include "cdb.h"


/* F   S A V E   A S S E R T I O N S */

export FLAGT FSaveAssertions(fp)
FILE	*fp;
{
    int		iad;
    FLAGT	fDidOne;
    pADR	ad;

    fDidOne = false;
    for (iad = 0, ad = v->rgAd; iad < v->iadMac; iad++, ad++) {
	fprintf(fp, "a %s\n", ad->sbCheck);
	if (ad->as != asActive)
	    fprintf(fp, "%d a s\n", iad);
	fDidOne = true;
    } /* for */

    if (fDidOne)
	/* set general assertion state correctly */
	fprintf(fp, "A %c\n", (v->as == asActive) ? 'a' : 's');

    return(fDidOne);
} /* FSaveAssertions */


/* L I S T   A S S E R T */

export void ListAssert()
{
    FAST int	i;

    if (v->iadMac == 0)
	UError("No assertions.");
    printf("Assertions as a group are %s\n\n",
		(v->as == asActive) ? "ACTIVE" : "SUSPENDED");
    for (i=0; i < v->iadMac; i++) {
	printf("%2d: %s %s\n", i,
	    (v->rgAd[i].as==asActive) ? "Active" : "Suspended",
	    v->rgAd[i].sbCheck);
    } /* for */
} /* ListAssert */


/* A D D   A S S E R T */

export void AddAssert(sbCheck, cb)
SBT	sbCheck;
int2	cb;
{
    int		iad;

    if (v->iadMac >= v->iadMax) {
	v->iadMax += 10;
	if (v->iadMax == 10) {
	    v->rgAd = (pADR) malloc(v->iadMax * cbADR);
	} else {
	    v->rgAd = (pADR) realloc(v->rgAd, v->iadMax * cbADR);
	} /* if */
	if (v->rgAd == 0)
	    Panic("Ran out of memory.");
    } /* if */
    iad = v->iadMac++;

    v->rgAd[iad].sbCheck = (SBT) malloc(cb+1);
    strcpy(v->rgAd[iad].sbCheck, sbCheck);
    v->rgAd[iad].sbCheck[cb] = chNull;

    v->rgAd[iad].as = asActive;
    if (!v->fQuiet)
	printf("Assertion %d: Active \"%s\"\n", iad, v->rgAd[iad].sbCheck);
    v->as = asActive;
    if (!v->fQuiet)
	printf("Assertions are ACTIVE\n");
} /* AddAssert */


/* M O D   A S S E R T */

export void ModAssert(iad, as)
int2	iad;
ASE	as;
{
    if (iad < 0 OR iad >= v->iadMac)
	UError("Bad assertion number: %d.", iad);

    v->rgAd[iad].as = as;
    if (as == asNil) {
	/* delete the assertoion */
	free(v->rgAd[iad].sbCheck);
	v->rgAd[iad] = v->rgAd[v->iadMac-1];	/* fold array back on itself */
	v->iadMac--;
    } else if (as == asActive) {
	/* if we turn one on, make sure MAIN switch is on */
	if (v->as == asActive)
	    v->as = asActive;
	return;
    } /* if */

    if (v->as == asSuspended)
	return;
    for (iad = 0; iad < v->iadMac; iad++)
	if (v->rgAd[iad].as == asActive)
	    return;

    if (!v->fQuiet)
	printf("Assertions are SUSPENDED\n");
    v->as = asSuspended;
} /* ModAssert */


/* F   D O   A S S E R T */

export FLAGT FDoAssert(pt)
int2	pt;
{
    int		iad, cmdSave;
    int4	cnt;

    cmdSave = vcmdDef;
    v->fRunAssert = false;  /* prevents recursive entry from RunProcess */
    for (cnt=(pt==ptSingle) ? 1 : -1;cnt != 0; --cnt) {
	/* we do the assertions BEFORE the line is executed */

	if (v->pid == pidNil)
	    return(true);

	for(iad=0; iad < v->iadMac; iad++) {
	    if ((v->rgAd[iad].as == asActive)
	       AND (FDoCommand(v->rgAd[iad].sbCheck, false))) {
		/* we hit an 'x' (exit) command - stop the parade! */
		printf("\nHit on assertion %d: \"%s\"\n",
			    iad, v->rgAd[iad].sbCheck);
		printf("Last line executed was:\n");
		PrintPosition(v->pcLast, fmtFile+fmtProc+fmtLn+fmtLine);
		printf("Next line to execute is:\n");
		SetViewPosition(v->acntx.pc);
		ShowViewPosition(fmtFile+fmtProc+fmtLn+fmtLine);
		v->fRunAssert = true;
		vcmdDef = cmdPrint;
		return(true);
	    } /* if */
	} /* for */

	v->pcLast = v->acntx.pc;	/* remember where the current line is */
	vcmdDef = cmdSave;

	/* step the process one statement's worth */
	SingleStep(cmdLineSingle, true);
	if (v->bp != bpNil) {
	    v->fRunAssert = true;
	    return(false);
	} /* if */
    } /* for */

    SetViewPosition(v->acntx.pc);	/* restore our context */
    v->fRunAssert = true;
    vcmdDef = cmdSave;
    return(true);
} /* FDoAssert */
0707070001000311671004440000000000010000011574610454650113100001200000065243cdb/cmd.c /* $Header: cmd.c,v 6.6 86/09/11 18:13:32 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"
#include "signal.h"
#include "errno.h"

static char	vsbOffset[15] = "---> "; /* used to offset comments */
static char	vsbTarget[100];	/* used for string searches */
static char	vchSearch = '/';	/* contains either ? or / */

export FLAGT	vfIgnoreCase = true;
export CMDE	vcmdDef;
export char	vsbFileTemp[256]; /* name of ifdTemp file */

MODER	vamodeInst = {dfInstruction, -1, 1, 0};


/* S E T   C M D */

export void SetCmd(sb)
SBT	sb;
{
    if (v->sbCmdStart != sbNil)
	free(v->sbCmdStart);
    v->sbCmd = v->sbCmdStart = SbFAlloc(sb);
} /* SetCmd */


/* I L N   F   N O R M A L I Z E */

export int IlnFNormalize(ifd, iln)
int	ifd, iln;
{
    if (iln < 1)
	iln = 1;
    else if (iln >= v->rgFd[ifd].ilnMac)
	iln = v->rgFd[ifd].ilnMac - 1;
    return(iln);
} /* IlnFNormalize */


/* C A L L   S H E L L */

export void CallShell(sbCmd)
SBT	sbCmd;
{
    SBT		sbShell;
    char	sbBuffer[100];

    if ((sbCmd == sbNil) OR (*sbCmd == chNull)) {
	sbShell = getenv("SHELL");
	if (sbShell == sbNil)
	    sbShell = "/bin/sh";
	sprintf(sbBuffer, "%s -i", sbShell);
	sbCmd = sbShell;
    } /* if */
    system(sbCmd);
    if (!v->fQuiet)
	printf("\nBack in %s, debugging %s.\n", vsbDebugName, v->sbExec);
} /* CallShell */


/* E A T   C M D   L I S T */

export char * EatCmdList(pcnt)
int2	*pcnt;
{
    SBT		sbCmd, sbTemp;
    TKE		tk;

    sbCmd = v->sbCmd;
    tk = TkPeek();
    if (tk == tkNil)
	return(sbNil);

    if (tk != tkLCB) {
	/* give caller the rest of line */
	v->sbCmd = sbTemp = sbCmd + strlen(sbCmd);
    } else {
	tk = TkNext();	/* eat { */
	sbCmd = v->sbCmd;
	sbTemp = SbFEob(v->sbCmd) - 1;
	v->sbCmd = sbTemp + 1;
    } /* if */
    while ((*sbCmd == ' ') OR (*sbCmd == '\t'))
	sbCmd++;
    *pcnt = sbTemp - sbCmd;
    return(sbCmd);
} /* EatCmdList */


/* E A T   F I L E N A M E */

local void EatFilename(sbName, psbIn)
SBT	sbName, *psbIn;
{
    int		cch;
    SBT		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 SBT SbFEob(sb)
SBT	sb;
{
    int		cNest;
    FLAGT	fString = false;

    /* return pointer to AFTER chRCB, or to the chNull */
    cNest = (*sb == chLCB) ? 0 : 1;
    while (*sb) {
	if ((*sb == '\\') AND (sb[1] == '"')) {
	    sb += 2;
	    continue;
	}
	if (fString) {
	    if (*sb == '"')
		fString = false;	/* end of string literal */
	} else if (*sb == '"') {
	    fString = true;		/* beginning of string literal */
	} else if (*sb == chLCB) {
	    cNest++;			/* additional nesting */
	} else if (*sb == chRCB) {
	    if (--cNest <= 0)
		return(sb+1);
	}
	sb++;
    } /* while */
    return(sb);
} /* SbFEob */


/* G O T O   I L N */

export void GotoIln(iln)
int2	iln;
{
    ADRT	adr;

    adr = AdrFIfdIln(v->ifd, iln);
    if (IpdFAdr(adr) != IpdFAdr(v->acntx.pc))
	UError("You can't goto a line outside of the current procedure.");
    PutReg(upc, adr);
} /* GotoIln */


/* F   C H K   C O M M A N D */

local FLAGT FChkCommand()
{
    FLAGT	fCommand;
    char	chCmd, chNext;
    SBT		sbCmds, sbTwoChars;
    TKE		tk;

    /* We guess whether we have a command or an expression.
     * We start with the current token.
     * This is a little weird because we try to do the `right' thing
     */

    if (vtk == tkCharConstant)
	return(false);

    sbCmds = "aAbBcCdDeEfFghHiIklLMNpPqQrRsStTvwWxYzZ\n<>-+@?/^!~;{}";
    sbTwoChars = "<>bcisSY";	/* commands of two or more characters */

    tk = vtk;
    chCmd = vsbTok[0];
    fCommand = (tk == tkNil);
    if (strchr(sbCmds, chCmd) != sbNil) {
	/* the first letter LOOKS like a command, keep going */
	fCommand = (vcbTok == 1);
	if ((vcbTok > 1)
	   AND ((tk == tkStr) OR (tk== tkRShift) OR (tk == tkLShift))) {
	    /* It is longer than 1 character, might be a variable name */
	    chNext = vsbTok[1];
	    if ( (vcbTok == 2)
	       AND (strchr(sbTwoChars, chCmd) != sbNil) ) {
		fCommand =   (chCmd == 'b' AND strchr("bBituUxX", chNext))
			  OR ((chCmd == 'c' OR chCmd == 'C')
					AND strchr("uU", chNext))
			  OR (chCmd == 'Y' AND strchr("chopqs", chNext))
			  OR (chCmd == 'i' AND chNext == 'f')
			  OR ((chCmd == 's' OR chCmd == 'S')
			     AND (chNext == 'I' OR chNext == 'i'))
			  OR (chCmd == '<' AND chNext == '<')
			  OR (chCmd == '>' AND chNext == '>');
	    } /* if */
	} /* if */
	/* a final chance to change our minds */
	TkPeek(); /* load peek token information */
	if (   (tk == tkStr)
	   AND (*v->sbCmd != ' ')
	   AND (vsbTokPeek[0] != chNull)
	   AND !(strchr(";\175", vsbTokPeek[0])) ) {
	    fCommand = false;
	} /* if */
    } /* if */
    return(fCommand);
} /* FChkCommand */


/* F   D O   C O M M A N D */

export FLAGT FDoCommand(sbCmdIn, fTop)
char	*sbCmdIn;
FLAGT	fTop;
{
    char	ch, chBp, chCmd, chNext;
    char	sbName[80], sbBuf1[200], sbBuf2[200];
    SBT		sb, sbBp, sbTemp;
    int		valInt;
    int2	iln, cLn, cnt, ifd, ipd;
    int2	sig, i, ilnSave, bpc;
    pBPR	bp;
    pPRR	pr;
    FLAGT	fHaveValue, fOutput, fDidit, fDoit, fCommand, fMachineStatement;
    ADRT	adr;
    TKE		tk;
    ASE		as;
    SER		aseExpr, aseT, *seExpr = &aseExpr, *seT = &aseT;
    VALU	val;
    FLAGT	fFreedProcess;

    /* the commands */
    SetCmd(sbCmdIn);

    tk = TkNext();
    do {
	if ((tk == tkStr) AND (FSbCmp("help", vsbTok))) {
	    Help();
	    vcmdDef = cmdNil;
	    continue;
	} else if (tk == tkStrConstant) {
	    printf("%s", vsbTok);
	    vcmdDef = cmdNil;
	    continue;
	} /* if */

	fHaveValue = false;
	fCommand = FChkCommand();
	*seExpr = *v->seDot;

	if (!fCommand) {
	    /* Assume it is a beginning expression */
	    SetViewPosition(adrNil);
	    SeFExpr(seExpr);
	    if (seExpr->asym.st != stNil) {
		/* we got something - get value for those who care */
		*seT = *seExpr;
		Coerce(vseInt, seT);
		seT->ti.fConstant = seExpr->ti.fConstant;
		val = ValFSe(seT); /* many just want value */
		valInt = val.valInt;
		fHaveValue = true;
	    } else {
		UError("Unknown name '%s'.", vsbTok);
	    } /* if */
	} /* if */

	cnt = 1;
	chCmd = vsbTok[0];
	chNext = vsbTok[1];

	switch (chCmd) {
	    default:
		    vcmdDef = cmdNil;
#ifdef V7_PRINTF
		    UError("Unknown command `%c' (0%o)\n.", chCmd, chCmd);
#else
		    UError("Unknown command `%c' (%#o)\n.", chCmd, chCmd);
#endif /* V7_PRINTF */

	    case '\n':
	    case '~':
	    case chNull:		/* default command */
		    if (!fHaveValue) {
			switch (vcmdDef) {
			    case cmdPrint:
				/* we print it, if we have it */
				
				if ((v->rgFd[v->ifd].iline != 0)
				   AND (! v->rgFd[v->ifd].fNoSource)) {
				    v->iln = IlnFNormalize(v->ifd, v->iln+1);
				    v->slop = 0;
				    ShowViewPosition(fmtLn+fmtSrcLineOnly);
				    if (vfWindows AND !vfEofSeen)
					UpLine(true);
				    break;
				} /* if */

				/* else we fall through and treat it
				 * as a disassembly request.
				 */
				*v->seDot = *vseCnAdr;
				v->seDot->val.valAdr = v->adrInst;
				*vmode = vamodeInst;
				vcmdDef = cmdDisplay;

				/* fall through */

			    case cmdUpArrow:
			    case cmdDisplay:
				IncFSeMode(v->seDot, vmode,
					((vcmdDef == cmdUpArrow) ? -1 : 1) );
				DisplaySe(v->seDot, vmode, true, true, true);
				printf("\n");
				break;

			    case cmdLineSingle:
				printf("s: ");
				SingleStep(vcmdDef, false);
				break;

			    case cmdMachSingle:
				printf("si: ");
				SingleStep(vcmdDef, false);
				break;

			    case cmdMachProc:
				printf("Si: ");
				SingleStep(vcmdDef, false);
				break;

			    case cmdLineProc:
				printf("S: ");
				SingleStep(vcmdDef, false);
				break;
			} /* switch */
		    } else if (seExpr->asym.st == stNumber) {
			if (valInt > 0)
			    v->iln = valInt;
			 else
			     v->iln += valInt;
			v->iln = IlnFNormalize(v->ifd, v->iln);
			v->slop = 0;
			ShowViewPosition(fmtLn+fmtSrcLineOnly);
			if (vfWindows)
			    UpLine(true);
			vcmdDef = cmdPrint;
		    } else  {
			*v->seDot = *seExpr;
			vmode->df = dfNil;
			vmode->len = -1;
			vmode->cnt = 1;
			vmode->imap = 0;
			vcmdDef = cmdDisplay;
			DisplaySe(v->seDot, vmode, true, true, true);
			printf("\n");
		    } /* if */
		    break;

	    case '+':	/* go forward N (1) line and print it */
	    case '-':	/* go backward N (1) line and print it */
		    i = LongFExpr(seT, tkNil);
		    if (seT->asym.st == stNil)
			i = 1;
		    v->iln += (chCmd=='-') ? -abs(i) : abs(i);
		    v->iln = IlnFNormalize(v->ifd, v->iln);
		    ShowViewPosition(fmtLn+fmtSrcLineOnly);
		    if (vfWindows)
			UpLine(true);
		    vcmdDef = cmdPrint;
		    break;

	    case '!':
		    sbTemp = EatCmdList(&cnt);
		    strncpy(sbName, sbTemp, cnt);
		    sbName[cnt] = chNull;
		    CallShell(sbName);	/* shell escape */
		    vcmdDef = cmdNil;
		    break;

	    case '^':	/* attempt to move backward, displaying memory */
		    GetMode(vmode);
		    IncFSeMode(v->seDot, vmode, -1);
		    DisplaySe(v->seDot, 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 */
	    case '?':	/*	'?hi mom' == search BACKWARDS and print */
		    if (!fHaveValue) {
			/* search for something */
			if (*v->sbCmd != chNull) {
			    strcpy(vsbTarget, v->sbCmd);
			    *v->sbCmd = chNull;
			} /* if */
			vchSearch = chCmd;
			Find(vsbTarget, (chCmd=='?'));
			v->slop = 0;
			vcmdDef = cmdPrint;
		    } else {
			*v->seDot = *seExpr;
			if (chCmd == '/') {
			    /* this prints the CONTENTS of an address */
			    GetMode(vmode);
			    DisplaySe(v->seDot, vmode, true, true, true);
			    vcmdDef = cmdDisplay;
			} else {
			    /* this prints an ADDRESS */
			    vmode->df = dfAdr;
			    vmode->len = v->cpu->cbPointer;
			    vmode->cnt = 1;
			    GetMode(vmode);
			    DisplaySe(v->seDot, vmode, true, false, false);
			    vcmdDef = cmdNil;
			} /* if */
			printf("\n");
		    } /* if */
		    break;

	    case '<':	/* playback commands */
		    EatFilename(sbName, &v->sbCmd);
		    SetPlayback(sbName, false, (chNext == '<'));
		    break;

	    case '>':	/* record commands */
		    fOutput = (chNext == '>');
		    tk = TkPeek();
		    if ((tk == tkSemi) OR (tk == tkNil)) {
			StateRecord();
			break;
		    }
		    if (vsbTokPeek[1] == chNull) {
		        if (  (vsbTokPeek[0] == 't')
			   OR (vsbTokPeek[0] == 'f')) {
			    TkNext();	/* actually eat next token */
			    if (fOutput)
				vfOutput = (vsbTok[0] == 't');
			    else
				vfRecord = (vsbTok[0] == 't');
			    break;
		        } else if (vsbTokPeek[0] == 'c') {
			    TkNext();	/* actually eat next token */
			    if (fOutput)
				SetOutput(sbNil);
			    else
				SetRecord(sbNil);
			    break;
		        } /* if */
			/* we fall through on other, 1 character filenames */
		    } /* if */
		    EatFilename(sbName, &v->sbCmd);
		    if (fOutput)
			SetOutput(sbName);
		    else
			SetRecord(sbName);
		    break;

	    case ';':	/* just a command delimiter */
		    vcmdDef = cmdNil;
		    break;

	    case 'A':	/* modify main assertion state */
		    tk = TkPeek();
		    if (tk != tkNil) {
			TkNext();
			v->as = ((*vsbTok == '1') OR
				(*vsbTok == 'a')) ? asActive : asSuspended;
		    } else {
			if (v->iadMac <= 0)
			    UError("There are currently no assertions.");
			v->as = (v->as==asSuspended) ? asActive : asSuspended;
			printf("Assertions are %s\n", (v->as==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(valInt, as);
			break;
		    } /* if */
		    if ((sbTemp=EatCmdList(&cnt)) != sbNil)
			AddAssert(sbTemp, cnt);
		    break;

	    case 'B': /* list all breakpoints */
		    ListBp();
		    break;

	    case 'b':	/* set (set again) a break point */
		    chBp = chNext;
		    sbBp = EatCmdList(&cnt);
		    bp = bpNil;
		    if (chBp == chNull) {
			/* vanilla breakpoint */
			if (! fHaveValue) {
			    adr = AdrFIfdIln(v->ifd, v->iln);
			} else {
			    /* there are two flavors - iln and addr */
			    if (seExpr->asym.st == stNumber) {
				/* normal line number */
				adr = AdrFIfdIln(v->ifd, valInt);
			    } else {
				/* raw address */
				adr = seExpr->val.valAdr;
				if (adr == v->rgPd[IpdFAdr(adr)].adr)
				    adr = AdrFPreamble(adr);
			    } /* if */
			} /* if */
			bp = BpFAddBp(adr, 1, sbBp, cnt);
		    } else if (chBp == 'i') {
			/* instruction level break */
			if (fHaveValue) {
			    ValFSe(seExpr);
			    Coerce(vseCnAdr, seExpr);
			    adr = seExpr->val.valAdr;
			} else {
			    adr = v->adrInst;
			} /* if */
			bp = BpFAddBp(adr, 1, sbBp, cnt);
		    } else {
			SetViewPosition(adrNil);
			ch = chBp | 040;	/* convert to lower */
			i = (fHaveValue) ? valInt : (ch=='u') ? 1 : -1;
			bpc = (ch == 'u') ? bpcUp :
					(ch == 'b') ? bpcBegin :
					(ch == 't') ? bpcProc :
					(ch == 'x') ? bpcEnd : bpcNil;
			bp = BpFSet(bpc, (chBp != ch), i, sbBp, cnt);
		    } /* if */
		    if ((bp != bpNil) AND (!v->fQuiet)) {
			printf("Break set at ");
			PrintPosition(bp->adr, fmtProc+fmtLn+fmtEol);
		    } /* if */
		    vcmdDef = cmdNil;
		    break;

	    case 'C':
	    case 'c':
		    if (chNext != chNull) {
			/* they want to set a breakpoint, too */
			i = (fHaveValue) ? valInt : 1;
			BpFSet(bpcUp, chNext == 'U', i, sbNil, 0);
			fHaveValue = false;
		    } /* if */

		    if (fHaveValue) {
			/* we have a continuance count */
			i = valInt;
			if (v->bp != bpNil)
			    v->bp->count = i;
		    } /* if */

		    i = LongFExpr(seT, tkNil);
		    if (seT->asym.st != stNil) {
			adr = AdrFIfdIln(v->ifd, i);
			bp = BpFAddBp(adr, -1, "", 0);
		    } /* if */

		    if (chCmd == 'C') {
			v->sig = v->sigOrig;
			if ((v->sig == v->os->sigTrap)
			   AND (v->os->mpSigSa[v->sig].fIgnore))
			    v->sig = 0;	/* this prevents *extreme* weirdness */
		    } /* if */
		    if (viprMax == 1) {
			RunProcess(ptResume, psRunning, !vfAnalyzeStop);
			if (vfAnalyzeStop)
			    /* This says that a 'c' in a breakpoint
			     * command string is ALSWAYS the last
			     * command - like it or not!
			     * This solves ugly recursion problem.....
			     */
			    return(true);
		    } else {
			/* multiprocess */
			RunProcess(ptResume, psRunning, false);
		    } /* if */

		    vcmdDef = cmdNil;
		    break;

	    case 'D':
		    ClearAllBp();
		    vcmdDef = cmdNil;
		    break;

	    case 'd':
		    adr = adrNil;
		    if (!fHaveValue) {
			/* if they want default, try current line number */
			SetViewPosition(adrNil);
			adr = AdrFIpdIln(v->ipd, v->iln);
			if (bpNil == BpFAdr(adr, false))
			    /* no such line OR no break, try it with the pc */
			    adr = v->acntx.pc;
		    } else if ((valInt >= 0) AND (valInt < v->ibpMac)) {
			/* give them named break */
			adr = v->rgBp[valInt].adr;
		    } /* if */

		    bp = BpFAdr(adr, false);
		    if (bp == bpNil) {
			printf("No such breakpoint\n");
			ListBp();
		    } else {
			ClearBp(bp);
		    } /* if */

		    vcmdDef = cmdNil;
		    break;

	    case 'e':
		    vcmdDef = cmdPrint;
		    if (fHaveValue) {
			OpenStack(valInt);
			break;
		    } /* if */
		    tk = TkPeek();
		    if (tk == tkNil) {
			SetViewPosition(adrNil);
			PrintPosition(adrNil, fmtFile+fmtProc+fmtLn+fmtEol);
		    } else {
			fDidit = false;
			EatFilename(sbName, &v->sbCmd);
			if ( (strchr(sbName, '.') == sbNil)
			   AND ((ipd = IpdFName(sbName)) != ipdNil) ) {
			    /* assume it's a procedure name */
			    OpenIpd(ipd, true);
			    ShowViewPosition(fmtFile+fmtProc
					+fmtLn+fmtLine+fmtEol);
			    fDidit = true;
			} else {
			    /* assume it's a file name */
			    if ((ifd = IfdFName(sbName)) == ifdNil) {
				ifd = ifdTemp;
				strcpy(vsbFileTemp, sbName);
				v->rgFd[ifd].iss = IssFSb(vsbFileTemp);
				v->ifd = ifdNil;
			    } /* if */
			    OpenIfd(ifd);
			    ShowViewPosition(fmtFile+fmtLn+fmtLine);
			    fDidit = true;
			} /* if */
			if (!fDidit)
			    UError("No such procedure or file name: %s.",
				sbName);
		    } /* if */
		    break;

	    case 'E':
		    cnt = (fHaveValue) ? valInt : 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[20-1] = chNull;	/* just to be safe */
		    } else if ((tk == tkSemi) OR (tk == tkNil)) {
			vsbFmt[0] = chNull;
		    } else {
			UError("Bad argument to the 'f' command.");
		    } /* if */
		    vcmdDef = cmdNil;
		    break;

	    case 'g':	/* 'goto' command (I'm SORRY!!!!!!!!) */
		    valInt = LongFExpr(seT, tkNil);
		    if (seT->asym.st == stNil) {
			UError("I need a linenumber.");
		    } /* if */
		    GotoIln(valInt);
		    break;

	    case 'H':   /* Halt - i.e. throw away rest of the command line */
		    SetCmd(sbNil);
		    if (v->fQuiet) {
			/* they don't know where they are - tell them */
			v->fQuiet = false;
			printf("\n%s\n", SbFSignal(v->sigOrig));
			ShowViewPosition(fmtFile+fmtProc+fmtLn+fmtLine+fmtEol);
		    } /* if */
		    break;

	    case 'h':	/* show history */
		    h_print();
		    break;

	    case 'i':	/* conditional command */
		    fDoit = LongFExpr(seT, tkNil);
		    if (seT->asym.st == stNil)
			fDoit = false;
		    tk = vtk;	/* look ahead by expression parser */
		    if (tk != tkLCB)
			UError("Missing {.");
		    if (!fDoit) {
			v->sbCmd = SbFEob(v->sbCmd); /* eat the first block */
			tk = TkNext();
			if (tk != tkLCB)
			    continue;	/* we ate first part of next command */
		    } /* if */
		    break;

	    case chLCB:	/* beginning of block. eat block. Mmmm, block good! */
		    v->sbCmd = SbFEob(v->sbCmd);
			/* returns ptr to matching RCB+1 */
		    break;

	    case chRCB:	/* end of block */
		    break;	/* we just throw it away */

	    case 'I':	/* information about cdb's state */
		    ShowState();
		    vcmdDef = cmdNil;
		    break;

	    case 'k':
		    if (v->pid == 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':
		    i = fmtFile+fmtProc+fmtLn+fmtLine+fmtEol;
		    if (v->fMachineStep)
			i += fmtInst;
		    SetViewPosition(v->acntx.pc); /* puts us at current break */
		    ShowViewPosition(i);
		    vcmdDef = cmdPrint;
		    break;

	    case 'M':	/* print|set map values */
		    DoMap();
		    vcmdDef = cmdNil;
		    break;

	    case 'N':	/* change size of source code display window */
		    TkNext();
		    i = atoi(vsbTok);
		    TkNext();
		    SetSrcWw(i, atoi(vsbTok));
		    MarkLine(v->iln);
		    UpLine(true);
		    break;

	    case 'P':	/* process management commands */
		    if ((viprMax == 1) AND ! vfAttach) {
			ListPr(prNil);
			break;
		    } /* if */

		    if (fHaveValue) {
			pr = PrFIpr(valInt);
			if (pr == prNil)
			    UError("No such process.");
			sbTemp = SbFAlloc(v->sbCmd);
			SetCmd(sbNil);	/* clear commands of outgoing */
			SetGlobalPr(pr);
			SetCmd(sbTemp); /* and use the saved commands */
			free(sbTemp);
		    } /* if */

		    tk = TkNext();
		    if (tk == tkNil && !fHaveValue) {
			ListPr(prNil);
		    } else {
			strcpy(sbBuf1, vsbTok);
			sb = sbBuf1;
			fFreedProcess = false;
			while (*sb) {
			    switch (*sb) {
				default:
				    printf("\
    Process management subcommands:\n\
       Example '1 P s 2' would make process 1 the active\n\
			 process and send it an interrupt\n\
    b	Toggle breakpoint inheritance after fork'ing\n\
    c	Toggle debug-my-Children flag\n\
    e	Toggle stop-after-Exec flag\n\
    f	Toggle stop-after-Fork flag\n\
    E	Add a new top level process by name\n\
    F	Free process to continue running\n\
    P	Add a new top level process by process id\n\
    s n	Send signal number n to process\n");
				    break;

				case 'b':
				    v->fRemoveBpsOnFork = !v->fRemoveBpsOnFork;
				    break;

				case 'c':
				    v->fDebugChildren = !v->fDebugChildren;
				    break;

				case 'e':
				    v->fStopOnExec = !v->fStopOnExec;
				    break;

				case 'f':
				    v->fStopOnFork = !v->fStopOnFork;
				    break;

				case 'E':
				    tk = TkNext();
				    if ((tk != tkStr) AND (tk != tkStrConstant))
					UError("I need a program name.");
				    pr = PrFInitPr(vsbTok);
				    SetGlobalPr(pr);
				    break;

				case 'F':
				    FreeProcess(v);
				    fFreedProcess = true;
				    break;

				case 'P':
				    tk = TkNext();
				    if (tk != tkNumber)
					UError("I need a process number.");
				    i = atoi(vsbTok);
				    if (vfAttach AND v != prNil) {
					if (Ptrace(ptMultiChild,i,0,0) == -1){
					    switch(errno) {
					    default:
						UError("Can not attach to process %d.",i);
					    case ESRCH:
						UError("Process %d does not exist.",i);
					    case EPERM:
						UError("You do not have permission to attach to process %d.",i);
					    }
					}
					v->pid = i;
					v->pidParent = pidNil;
					SendSignal(SIGINT);
					Waiter(wtProcess,v->pid);
				    } else {
				    	PrFAttachProcess(atoi(vsbTok));
				    }
				    break;

				case 's':
				    tk = TkNext();
				    if (tk != tkNumber)
					UError("I need a simple signal number.");
				    i = atoi(vsbTok);
				    SendSignal(i);
				    break;

			    } /* switch */
			    *sb++;
			} /* while */
			if (! v->fQuiet) {
			    if(fFreedProcess) {
				ListPr(prNil);
			    } else {
				ListPr(v);
			    } /* if */
			}
		    } /* if */
		    break;

	    case 'p':
		    if (fHaveValue) {
			i = valInt;
			if (i < 0)
			    v->iln += i;
			else
			    v->iln = i;
			v->iln = IlnFNormalize(v->ifd, v->iln);
			v->slop = 0;
		    } /* if */
		    cnt = LongFExpr(seT, tkNil);
		    if ((seT->asym.st == stNil) OR (cnt <= 0))
			cnt = 1;
		    if (vfWindows) {
			SetViewPosition(adrNil);
			ShowViewPosition(fmtFile+fmtProc+fmtLn+fmtLine+fmtEol);
		    } else {
			PrintLine(v->iln, cnt, true, stdout);
		    } /* if */
		    vcmdDef = cmdPrint;
		    break;

	    case 'q':
		    ch = ChFChoice("Quit? [nsy] ", "nsy");
		    if (ch == 'n') {
			break;
		    } if (ch == 's') {
			SaveAll();
		    } /* if */
		    CdbExit(0);
		    /* NOTREACHED */
		    break;

	    case 'Q':	/* quiet command, just eat it */
		    v->fQuiet = !v->fQuiet;
		    break;

	    case 'r':
	    case 'R':
		    v->fDoingSingle = false;
		    NewChild((chCmd == 'R') ? sbNil : v->sbCmd, false);
		    if (v->bp == bpNil)
			RunProcess(ptResume, psRunning, viprMax == 1);
		    vcmdDef = cmdNil;
		    break;

	    case 'S':
	    case 's':
		    i = (fHaveValue) ? valInt : 1;
		    fMachineStatement = false;
		    if (chNext == 'I') {
			fMachineStatement = true;
			chNext = 'i';
		    } /* if */

		    vcmdDef = (chCmd=='s') ?
			((chNext == 'i') ? cmdMachSingle : cmdLineSingle)
			: ((chNext == 'i') ? cmdMachProc : cmdLineProc);

		    while (i--) {
			if (fMachineStatement) {
			    do {
				SingleStep(vcmdDef, false);
				if ((v->pid == pidNil) /* child died/term'ed */
				   OR (v->bp != bpNil)) /* REAL breakpoint */
				    break;
			    } while (v->slop != 0);
			} else {
			    SingleStep(vcmdDef, false);
			} /* if */

			if ((v->pid == pidNil) /* child died/terminated */
			   OR (v->bp != bpNil)) /* REAL breakpoint */
			    break;
		    } /* while */
		    break;

	    case 'T':
	    case 't':
		    i = (fHaveValue) ? valInt : 20; /* default to 20 deep */
		    TkPeek();
		    StackTrace(i, (chCmd=='T')); /* do locals, too, on T */
		    vcmdDef = cmdNil;
		    break;

	    case 'v':
		    EditFile(v->ifd, v->iln);
		    break;

	    case 'W':
		    cnt = 21;
	    case 'w':
		    if (fHaveValue)
			v->iln = IlnFNormalize(v->ifd, valInt);
		    v->slop = 0;
		    ilnSave = v->iln;
		    if (cnt == 1)
			cnt = 11;	/* i.e. - we didn't come through W */
		    i = LongFExpr(seT, tkNil);
		    if ((seT->asym.st != stNil) AND (i >= 1))
			cnt = i;
		    iln = Max(v->iln-cnt/2, 1);
		    cLn = Min(cnt/2, v->iln-iln);
		    if (vfWindows) {
			CenterWw(v->iln);
			MarkLine(v->iln);
			UpLine(true);
		    } else {
			PrintLine(iln, cLn, true, stdout);
			/* shows them which line they are on */
			if (vfpWwSrc != NULL)
			    fprintf(vfpWwSrc, ">");
			else
			    printf(">");
			v->iln++;
			cLn = Min(cnt-cLn, v->rgFd[v->ifd].ilnMac-v->iln+1);
			PrintLine(v->iln, cLn, true, stdout);
		    } /* if */
		    v->iln = ilnSave;
		    vcmdDef = cmdPrint;
		    break;

	    case 'x':	/* clear command line and exit current level */
		    if ((!fHaveValue) OR (valInt == 0))
			SetCmd(sbNil);
		    return(true);

	    case 'Y':	/* commands used for demo's */
		    switch (chNext) {
			case '\0':
			    /* this line is a comment */
			    if (vfComment) {
				if (*v->sbCmd != chNull) {
				    Highlight(true);
				    printf("%s%s\n", vsbOffset, v->sbCmd+1);
				    Highlight(false);
				} else {
				    printf("\n");
				} /* if */
			    } /* if */
			    SetCmd(sbNil);
			    break;

			case 'c':
			    /* a "no pause" command */
			    if (tkNil == TkPeek())
				SetCmd("\n");;	/* stuff a <cr> in there */
			    printf("%s%s\n", "cdb >", v->sbCmd);
			    break;

			case 'h':
			    /* set the comment highlight ON and OFF value */
			    SetCmd(sbNil);
			    break;

			case 'o':
			    /* set the comment offset to the given string */
			    strcpy(vsbOffset, v->sbCmd+1);
			    SetCmd(sbNil);
			    break;

			case 'p':
			    /* pause for the given number of seconds */
			    i = LongFExpr(seT, tkNil) - vsleepDemo;
			    if (i > 0)
				sleep(i);
			    break;

			case 'q':
			    CdbExit(0);
			    break;

			case 's':
			    /* Change the sleep time.
			     * We allow this only if it was already in effect.
			     */
			    if (vsleepDemo != 0)
				vsleepDemo = LongFExpr(seT, tkNil);
			    break;
		    } /* switch */
		    break;

	    case 'z':	/* 'zignals' processing */
		    sig = (fHaveValue) ? valInt : v->sigOrig;
		    TkNext();
		    strcpy(sbBuf1, vsbTok);
		    sbBp = EatCmdList(&cnt);
		    if (sbBp == sbNil)
			sbBuf2[0] = 0;
		    else
			strncpy(sbBuf2, sbBp, cnt);
		    sbBuf2[cnt] = chNull;
		    SaMaintain(sig, sbBuf1, sbBuf2);
		    break;

	    case 'Z':	/* toggle case sensitivity */
		    vfIgnoreCase = !vfIgnoreCase;
		    vcaseMod = (vcaseMod) ? 0 : 040;
		    printf("Searches will %sbe case sensitive\n",
			(vcaseMod!=0) ? "NOT " : "");
		    vcmdDef = cmdNil;
		    break;
	} /* switch */

	if ((vtk != tkSemi) AND (chCmd != 'i')) {
	    while ((tk = TkNext()) != tkSemi)
		if (tk == tkNil)
		    return(fTop);
	} /* if */
    } while ((tk = TkNext()) != tkNil);
    
    return(fTop);
} /* FDoCommand */
0707070001000311701004440000000000010000011577650454650113200001700000044205cdb/csupport.c /* $Header: csupport.c,v 6.2 86/09/11 18:13:45 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This module supplies major support to the C expression evaluator. */

#include "cdb.h"

export FLAGT vfInFalse;

/* a bunch of types for expression evaluation */

SER	aseAdr,    aseCnAdr,    aseChar,  aseCnChar;
SER	aseUChar,  aseCnUChar,  aseShort, aseCnShort;
SER	aseUShort, aseCnUShort, aseInt,   aseCnInt;
SER	aseUInt,   aseCnUInt,   aseLong,  aseCnLong;
SER	aseULong,  aseCnULong,  aseFloat, aseCnFloat;
SER	aseDouble, aseCnDouble, aseInit;
SER	aseLogical,  aseCnLogical,  aseComplex, aseCnComplex;

export pSER	vseInit = &aseInit;
export pSER	vseAdr = &aseAdr;
export pSER	vseCnAdr = &aseCnAdr;
export pSER	vseChar = &aseChar;
export pSER	vseCnChar = &aseCnChar;
export pSER	vseUChar = &aseUChar;
export pSER	vseCnUChar = &aseCnUChar;
export pSER	vseShort = &aseShort;
export pSER	vseCnShort = &aseCnShort;
export pSER	vseUShort = &aseUShort;
export pSER	vseCnUShort = &aseCnUShort;
export pSER	vseInt = &aseInt;
export pSER	vseCnInt = &aseCnInt;
export pSER	vseUInt = &aseUInt;
export pSER	vseCnUInt = &aseCnUInt;
export pSER	vseLong = &aseLong;
export pSER	vseCnLong = &aseCnLong;
export pSER	vseULong = &aseULong;
export pSER	vseCnULong = &aseCnULong;
export pSER	vseFloat = &aseFloat;
export pSER	vseCnFloat = &aseCnFloat;
export pSER	vseDouble = &aseDouble;
export pSER	vseCnDouble = &aseCnDouble;
export pSER	vseLogical = &aseLogical;
export pSER	vseCnLogical = &aseCnLogical;
export pSER	vseComplex = &aseComplex;
export pSER	vseCnComplex = &aseCnComplex;


/* map basic types into the type names */
SBT	vmpBtSb[] = {
	"undefined",
	"address",
	"char",
	"unsigned char",
	"short",
	"unsigned short",
	"int",
	"unsigned int",
	"long",
	"unsigned long",
	"float",
	"double",
	"struct",
	"union",
	"enum",
	"typedef",
	"long long",
	"unsigned long long",
	"set",
	"range",
	"complex",
	"logical",
	"subRange",
	"void",
	};


/* I N I T   S E */

export void InitSe()
{
    int		i;

    /* Set up all of the constant SE's */
    aseInit.isymRef = isymNil;
    aseInit.isymTypedef = isymNil;
    aseInit.asym.iss = issNil;
    aseInit.asym.value = -1;
    aseInit.asym.sc = scNil;
    aseInit.asym.st = stExpr;	/* changes at end of InitSe */
    aseInit.asym.index = 0;
    aseInit.ti.bt = btNil;
    aseInit.ti.fConstant = false;
    aseInit.ti.tq0 = tqNil;
    aseInit.ti.tq1 = tqNil;
    aseInit.ti.tq2 = tqNil;
    aseInit.ti.tq3 = tqNil;
    aseInit.ti.tq4 = tqNil;
    aseInit.ti.tq5 = tqNil;

    for (i=0; i < idimMax; i++) {
	aseInit.rgRng[i].iaux = iauxNil;
	aseInit.rgRng[i].dnLow = 0;
	aseInit.rgRng[i].dnHigh = 0;
    } /* for */

#define SetupSe(se, bx, f) {*se=aseInit;se->ti.bt=bx;se->ti.fConstant=f;}
    /* set up standard type descriptors */
    SetupSe(vseAdr, btAdr, false);
    vseAdr->ti.tq0 = tqPtr;
    SetupSe(vseCnAdr, btULong, true);
    SetupSe(vseChar, btChar, false);
    SetupSe(vseCnChar, btChar, true);
    SetupSe(vseUChar, btUChar, false);
    SetupSe(vseCnUChar, btUChar, true);
    SetupSe(vseShort, btShort, false);
    SetupSe(vseCnShort, btShort, true);
    SetupSe(vseUShort, btUShort, false);
    SetupSe(vseCnUShort, btUShort, true);
    SetupSe(vseInt, btInt, false);
    SetupSe(vseCnInt, btInt, true);
    SetupSe(vseUInt, btUInt, false);
    SetupSe(vseCnUInt, btUInt, true);
    SetupSe(vseLong, btLong, false);
    SetupSe(vseCnLong, btLong, true);
    SetupSe(vseULong, btULong, false);
    SetupSe(vseCnULong, btULong, true);
    SetupSe(vseFloat, btFloat, false);
    SetupSe(vseCnFloat, btFloat, true);
    SetupSe(vseDouble, btDouble, false);
    SetupSe(vseCnDouble, btDouble, true);
    SetupSe(vseLogical, btLogical, false);
    SetupSe(vseCnLogical, btLogical, true);
    SetupSe(vseComplex, btComplex, false);
    SetupSe(vseCnComplex, btComplex, true);

    aseInit.asym.st = stNil;
} /* InitSe */


/*  G E T   A D R */

export void GetAdr(se)
pSER	se;
{
    SBT		sbName;
    int2	ipd;

    /* Given an SER containing only a name, search for it in the
     * current context and return a full-blown SER.
     */

    if (se->asym.st != stStr)
	return;	/* we already looked it up */

    sbName = SbFIss(se->asym.iss);
    if (  ((*sbName == '$') AND FSpecial(se) )
       OR ((v->ipd != ipdNil) AND FLocal(se, v->ipd, v->stackdepth))
       OR			FGlobal(se) 
       OR			FEnum(se) ) {
	/* everything was done by routines */
    } else if ((ipd = IpdFName(sbName)) != ipdNil) {
	SeFSym(se, SymFIsym(v->rgPd[ipd].isym), true);
    } else if (FSpecial(se)) {
	/* routine did everything */
    } else {
	UError("Unknown name \"%s\".", sbName);
    } /* if */
} /* GetAdr */


/* G E T   V A L */

export void GetVal(se)
pSER	se;
{
    /* First look up the thing named in the SER and then get its value */

    GetAdr(se);
    se->val = ValFSe(se);
    se->asym.st = stExpr;
} /* GetVal */


/* G E T   O R I G */

export void GetOrig(se)
pSER	se;
{
    if (! (se->ti.fConstant)
       OR (se->asym.st == stStr)) {
	GetVal(se);
    } /* if */
} /* GetOrig */


/* F   B I N   O P   L E G A L   F   T Y */

local FLAGT FBinOpLegalFSe(se)
pSER	se;
{
    /* Determine if the given SER could legally be used in a binary operation */

#if 0
    if ((se->ti.tq0 == tqPtr)
     OR (se->ti.tq0 == tqArray))
#endif
    if (se->ti.tq0 != tqNil)
	return(true);

    switch (se->ti.bt) {
	default:
	case btNil:
	case btUnion:
	case btStruct:	return(false);
	case btAdr:
	case btInt:
	case btUInt:
	case btUShort:
	case btShort:
	case btLong:
	case btULong:
	case btChar:
	case btUChar:
	case btFloat:
	case btDouble:
	case btLogical:
	case btComplex:
	case btEnum:	return(true);
    } /* switch */
} /* FBinOpLegalFSe */


/* M A X   F   S E   S E */

local FLAGT MaxFSeSe(seMax, se1, se2)
pSER	seMax, se1, se2;
{
    int2	cb1, cb2;

    /* Return the 'larger' type of the two given.
     * E.g. float + int OR int + float will return float.
     */

    if (!FBinOpLegalFSe(se1) OR !FBinOpLegalFSe(se2))
	return(false);

    cb1 = CbFSe(se1);
    cb2 = CbFSe(se2);

    /* the rule here is that the physically large size wins */
    if (cb1 > cb2) {
	CopyTy(seMax, se1);
    } else if (cb2 > cb1) {
	CopyTy(seMax, se2);
    } else {
	/* same size - look to for type preference */
	if ((se2->ti.tq0 != tqNil)  /* <--- is this right?? KLUDGE */
	   OR (se2->ti.bt == btFloat)
	   OR (se2->ti.bt == btDouble))
	    CopyTy(seMax, se2);
	else
	    CopyTy(seMax, se1);
    } /* if */
    return(true);
} /* MaxFSeSe */


/*  R E S  F  O P S     */

export void ResFOps(seRet, se1, se2)
pSER	seRet, se1, se2;
{
    int2   	fDoIntOp, fConstant, cb1, tq1, tq2;
    SER		ase;

    /* Determine the resultant type of an expression.
     * If pointers and/or arrays are invloved, allow for
     * expression multiplication, etc.
     */

    GetOrig(se1);
    GetOrig(se2);

    fDoIntOp = MaxFSeSe(seRet, se1, se2);

    if (!fDoIntOp)
	UError("Cannot allow that combination of operand(s) and operator.");

    /* Do the pointer crap - ^%##&%#*&^%$#*^@#&!!!!!!! */

    tq1 = se1->ti.tq0;
    tq2 = se2->ti.tq0;
    fConstant = (tq1 == tqNil) AND (tq2 == tqNil);

    if (((tq1 == tqPtr) OR (tq1 == tqArray)) AND (tq2 == tqNil)) {

	Coerce(vseCnLong, se2);
	CopyTy(seRet, se1);
	ase = *se1;
	RemoveTq(&ase);
	se2->val.valLong *= CbFSe(&ase);
	if (tq1 == tqArray)
	    seRet->ti.tq0 = tqPtr;

    } else if (((tq2 == tqPtr) OR (tq2 == tqArray)) AND (tq1 == tqNil)) {

	Coerce(vseCnLong, se1);
	CopyTy(seRet, se2);
	ase = *se2;
	RemoveTq(&ase);
	se1->val.valLong *= CbFSe(&ase);
	if (tq2 == tqArray)
	    seRet->ti.tq0 = tqPtr;

    } else if ((tq2 == tqPtr OR tq2 == tqArray)
	   AND (tq1 == tqPtr OR tq1 == tqArray)) {

	/* massive kludge - not kosher - etc. */
	ase = *se1;
	RemoveTq(&ase);
	cb1 = CbFSe(&ase);
	Coerce(vseCnULong, se1);
	Coerce(vseCnULong, se2);
	se1->val.valULong /= cb1; /* we ASSUME they are of the same array! */
	se2->val.valULong /= cb1;
	fConstant = true;
	CopyTy(seRet, vseCnInt);

    } else if ((seRet->ti.tq0 == tqProc) AND (seRet->ti.tq1 == tqNil)) {

	RemoveTq(seRet);
	seRet->ti.bt = btAdr;

    } /* if */

    Coerce(seRet, se1);
    Coerce(seRet, se2);
    seRet->asym.st = stExpr;
    seRet->asym.iss = issNil; /* it no longer has a name, it is just a value */
    seRet->ti.fConstant = fConstant;
} /* ResFOps */


#define DoCoerce(btX, valX)\
case btX: switch (btFrom) {\
    case btAdr:seFrom->val.valX = val.valAdr; break;\
    case btChar:seFrom->val.valX = val.valChar; break;\
    case btUChar:seFrom->val.valX = val.valUChar; break;\
    case btShort:seFrom->val.valX = val.valShort; break;\
    case btUShort:seFrom->val.valX = val.valUShort; break;\
    case btInt:seFrom->val.valX = val.valInt; break;\
    case btEnum: case btUInt:seFrom->val.valX = val.valUInt; break;\
    case btLong:seFrom->val.valX = val.valLong; break;\
    case btULong:seFrom->val.valX = val.valULong; break;\
    case btFloat:seFrom->val.valX = val.valFloat; break;\
    case btDouble:seFrom->val.valX = val.valDouble; break;\
    case btLogical:seFrom->val.valX = val.valUInt; break;\
} /* switch */


/* C O E R C E */

export void Coerce(seTo, seFrom)
pSER	seTo, seFrom;
{
    int2	tqTo, tqFrom;
    int2	btTo, btFrom;
    VALU	val;

    /* Coerce seFrom to the same type as seTo */

    tqTo = seTo->ti.tq0;
    tqFrom = seFrom->ti.tq0;

    btTo = (tqTo == tqNil) ? seTo->ti.bt : btAdr;
    btFrom = (tqFrom == tqNil) ? seFrom->ti.bt : btAdr;

    val = seFrom->val;
    ZeroBlock(&seFrom->val, sizeof(VALU));

    /* The following switch is much hairier than it looks!
     * see macro define above for DoCoerce.
     */

    switch (btTo) {
	default:		UError("unknown basic type (%d) in Coerce.");
	case btNil:		UError("Result type undefined.");
	case btTypedef:		Panic("btTypedef in Coerce.");
	case btStruct:
	case btComplex:
	case btUnion:		/* We allow this to 'happen as it will' .... */
				break;
	case btEnum:
	DoCoerce(btUInt, valUInt);	break;
	DoCoerce(btChar, valChar);	break;
	DoCoerce(btUChar, valUChar);	break;
	DoCoerce(btInt, valInt);	break;
	DoCoerce(btLong, valLong);	break;
	DoCoerce(btULong, valULong);	break;
	DoCoerce(btShort, valShort);	break;
	DoCoerce(btUShort, valUShort);	break;
	DoCoerce(btFloat, valFloat);	break;
	DoCoerce(btDouble, valDouble);	break;
	DoCoerce(btLogical, valUInt);	break;
	DoCoerce(btAdr, valAdr);	break;
    } /* switch */

    CopyTy(seFrom, seTo);
} /* Coerce */


/* A S S I G N */

export void Assign(seDest, seSrc)
pSER	seDest, seSrc;
{
    int2	cb1, cb2;
    pSER	seT;

    /* Assign (with fear and loathing) the source value to the
     * destination location.
     * Perform implict coersions, etc.
     */

    if ((seDest->ti.fConstant) OR (seDest->ti.tq0 == tqArray))
	UError("You may not assign to a constant");

    if (seDest->asym.sc == scCdbLocal) {
	/* make the special take on the type of seSrc */
	SpecialSideEffects(seDest, seSrc); /* some specials have side effects */
	CopyTy(seDest, seSrc);
	if (seDest->ti.tq0 == tqArray) {
	    RemoveTq(seDest);
	    AddTq(seDest, tqPtr);
	} /* if */
	seDest->ti.fConstant = false;
	if (CbFSe(seDest) > cbVALU)
	  UError("You may not assign more than %d bytes to a special variable.",
		cbVALU);
	seT = (pSER) seDest->asym.value;
	*seT = *seDest;
    } /* if */

    GetOrig(seSrc);
    Coerce(seDest, seSrc);

    cb1 = CbFSe(seSrc);
    if (!vfInFalse) {
	if (cb1 <= v->cpu->cbDouble) {
	    WriteVal(seDest, seSrc);
	} else {
	    cb2 = CbFSe(seSrc);
	    if (cb1 != cb2) {
		printf("WARNING: X=Y: X is %d bytes and Y is %d bytes\n",
		    cb1, cb2);
		cb1 = Min(cb1, cb2);
		printf("  Moving %d bytes\n", cb1);
	    } /* if */
	    BlockTransfer(seDest->asym.value, seSrc->asym.value,
			spaceData, cb1);
	} /* if */
    } /* if */
} /* Assign */


/* M I N */

export int Min(x, y)
int	x, y;
{
    return((x<y) ? x : y);
} /* Min */


/* M A X */

export int Max(x, y)
int	x, y;
{
    return((x>y) ? x : y);
} /* Max */


/* Z E R O   B L O C K */

export void ZeroBlock(sb, cb)
FAST SBT	sb;
FAST int2	cb;
{
    while (cb--)
	*sb++ = 0;
} /* ZeroBlock */


/* S B   F   B T */

export SBT SbFBt(bt)
int2	bt;
{
    if (bt < 0 OR bt >= btMax)
	Panic("Bt out of bounds.");
    return(vmpBtSb[bt]);
} /* SbFBt */


/* S E   F   S Y M */

export void SeFSym(se, sym, fRecurse)
pSER	se;
pSYMR	sym;
FLAGT	fRecurse;
{
    int2	tq, i, bt, idim, idimTemp;
    char	sbBuf[100];
    pAUXU	aux;
    SER		ase;
    pSYMR	symCommon;

    /* Given a SYMR, develop a full-blown SER. */

    *se = *vseInit;	/* initialize */
    se->asym = *sym;	/* get the base symbol */
    se->val.valAdr = 0;	/* more or less sets field to 0 */

    aux = AuxFIaux(se->asym.index);	/* point into AUX info universe */
    switch (se->asym.st) {
	default:
		Panic("Bad st in SeFSym (%d).", se->asym.st);
		break;

	case stCommon:
		DoCommon(se, sym);
		break;

	case stBlock:		/* probably a typedef'd struct/union */
		break;	/* all done */

	case stProc:		/*     "      "  Procedure */
		if (aux == auxNil)
		    return;	/* was generated by normal text label */
		aux++;	/* skip past isymLast */
		/* fall through into main code */

	case stGlobal:		/* external symbol */
	case stStatic:		/* static */
	case stParam:		/* procedure argument */
	case stLocal:		/* local variable */
	case stMember:		/* member of something */
	case stTypedef:		/* Type definition */
		se->ti = (aux++)->ti;
		bt = se->ti.bt;

		/* pick up reference pointer, if any */
		if ( (bt == btStruct)
		   OR (bt == btUnion)
		   OR (bt == btEnum)
		   OR (bt == btTypedef) )
		    se->isymRef = (aux++)->isym;

		/* collect dimensions */
		idim = 0;
		for (i=0; i < itqMax; i++) {
		    if (tqArray == TqFSe(se, i)) {
			se->rgRng[idim].iaux = (aux++)->iaux;
			se->rgRng[idim].dnLow = (aux++)->dn;
			se->rgRng[idim].dnHigh = (aux++)->dn;
			idim++;
		    } /* if */
		} /* for */

		/* collect and fix up the bit field info */
		if (se->asym.sc == scBits) {
		    se->bitsWidth = (aux++)->width;
		    se->bitsOffset = se->asym.value;
		    se->asym.value = 0; /* will be filled in with struct adr */
		} /* if */

		/* follow and collect type info */
		if ((bt == btTypedef)
		   AND (fRecurse OR (se->asym.iss == issNil))) {
		    /* WOW! Real Recursion!! (neato!) */
		    se->isymTypedef = se->isymRef;
		    sym = SymFIsym(se->isymRef);
		    SeFSym(&ase, sym, true);
		    se->isymRef = ase.isymRef; /* get THEIR ref value */
		    se->ti.bt = ase.ti.bt;	/* get underlying type */

		    /* Tack on THEIR tq info */
		    idimTemp = 0;
		    for (i = 0; i < itqMax; i++) {
			if ((tq = TqFSe(&ase, i)) == tqNil)
			    break;
			AddTq(se, tq);
			if (tq == tqArray) {
			    /* add this to the dimensions we already have */
			    if (idim >= idimMax)
				UError("%s has more than %d dimensions.",
				    SbFIss(se->asym.iss), idimMax);
			    se->rgRng[idim++] = ase.rgRng[idimTemp++];
			} /* if */
		    } /* for */

		} /* if */
		break;
    } /* switch */

    bt = se->ti.bt;
    if ( (bt == btStruct OR bt == btUnion OR bt == btEnum)
       AND (se->isymRef == isymNil) )
	se->ti.bt = btUChar;	/* the type was never defined! */

    if ((se->ti.tq0 == tqArray) OR (se->ti.tq0 == tqProc))
	se->val.valAdr = se->asym.value;

    if ((se->asym.st == stMember) AND (se->ti.lc == lcFortran)) {
	DoCommon(&ase, sym);
	se->asym.value = (se->asym.value / 8) +  ase.asym.value;
    } else if (se->asym.sc == scAbs) {
	se->val.valInt = se->asym.value;
    } else if ((se->asym.st == stGlobal)
		OR (se->asym.st == stStatic)
		OR (se->asym.st == stCommon)) {
	se->asym.value += v->adrData;
    } /* if */
} /* SeFSym */


/* C O P Y   T Y */

export void CopyTy(seDest, seSrc)
pSER	seDest, seSrc;
{
    FLAGT	fConstant = seDest->ti.fConstant;
    SYMR	asym;
    VALU	val;
    
    val = seDest->val;

    /* Copy ONLY the type information */

    asym = seDest->asym;
    *seDest = *seSrc;
    seDest->asym = asym;
    seDest->val = val;
    seDest->ti.fConstant = fConstant;
} /* CopyTy */


/* T Q   F   S E */

export int TqFSe(se, cnt)
pSER	se;
int2	cnt;
{
    switch (cnt) {
	default: Panic("tq out of bounds.");
	case 0:	return(se->ti.tq0);
	case 1:	return(se->ti.tq1);
	case 2:	return(se->ti.tq2);
	case 3:	return(se->ti.tq3);
	case 4:	return(se->ti.tq4);
	case 5:	return(se->ti.tq5);
    } /* switch */
} /* TqFSe */


/* A D D   T Q */

export void AddTq(se, tq)
pSER	se;
int2	tq;
{
    if (se->ti.tq0 == tqNil)
	se->ti.tq0 = tq;
    else if (se->ti.tq1 == tqNil)
	se->ti.tq1 = tq;
    else if (se->ti.tq2 == tqNil)
	se->ti.tq2 = tq;
    else if (se->ti.tq3 == tqNil)
	se->ti.tq3 = tq;
    else if (se->ti.tq4 == tqNil)
	se->ti.tq4 = tq;
    else if (se->ti.tq5 == tqNil)
	se->ti.tq5 = tq;
    else
	UError("Type of %s is too complex.", SbFIss(se->asym.iss));
} /* AddTq */


/* R E M O V E   T Q */

export void RemoveTq(se)
pSER	se;
{
    se->ti.tq0 = se->ti.tq1;
    se->ti.tq1 = se->ti.tq2;
    se->ti.tq2 = se->ti.tq3;
    se->ti.tq3 = se->ti.tq4;
    se->ti.tq4 = se->ti.tq5;
    se->ti.tq5 = tqNil;
} /* RemoveTq */


/* C B   F   S E */

export int CbFSe(se)
pSER	se;
{
    int2	cb, tq;

    /* Determine the size in bytes of the type given */

    if (se == seNil)
	return(0);

    if (se->asym.sc == scBits)
	return(-1);	/* a bit field */

    cb = 0;
    tq = se->ti.tq0;
    if ((tq == tqPtr) OR (tq == tqProc) OR (tq == tqRef)) {
	cb = v->cpu->cbPointer;
    } else {
	switch (se->ti.bt) {
	    case btAdr:		cb = v->cpu->cbPointer;	break;
	    case btLogical:	/* for now, f77 treats logical as an int */
	    case btEnum:
	    case btInt:
	    case btUInt:	cb = v->cpu->cbInt;	break;
	    case btUShort:
	    case btShort:	cb = v->cpu->cbShort;	break;
	    case btLong:
	    case btULong:	cb = v->cpu->cbLong;	break;
	    case btChar:
	    case btUChar:	cb = 1	;		break;
	    case btFloat:	cb = v->cpu->cbFloat;	break;
	    case btComplex:	/* f77 treats logical as a pair of floats */
	    case btDouble:	cb = v->cpu->cbDouble;	break;
	    case btUnion:
	    case btStruct:	{
				int4	isymSave = v->isym;
				cb = SymFIsym(se->isymRef)->value;
				SymFIsym(isymSave);
				};
	} /* switch */
    } /* if */

    if (tq == tqArray) {
	int	x, i;

	x = 1;
	/* this STILL may not be quite right..... */
	for (i = itqMax-1; i >= 0; i--) {
	    tq = TqFSe(se, i);
	    if (tq == tqNil) {
		continue;
	    } else if (tq != tqArray) {
		/* we hit a pointer or proc, throw out count, reset cb */
		cb = v->cpu->cbPointer;
		x = 1;
	    } else {
		x *= se->rgRng[i].dnHigh - se->rgRng[i].dnLow + 1;
	    } /* if */
	} /* for */
	cb *= x;
    } /* if */

    return(cb);
} /* CbFSe */
0707070001000311711004440000000000010000011575520454650113200001200000001122cdb/fib.c #include <stdio.h>

main(argc, argv)
char **argv;
{
	int	value;
	int	result;

	if(argc < 2) {
		fprintf(stderr, "Usage: %s number\n");
		exit(1);
	}


	value = atoi(argv[1]);
	if(value > 15) {
		fprintf(stderr, "Number too big\n");
		exit(1);
	}

	result = fib(value);

	fprintf(stdout, "Fib(%d) = %d\n", value, result);
	exit(0);
}

fib(n)
{
	int	pid;
	int	status;
	int	result;

	if((pid = fork()) < 0) {
		exit(0);
	}

	if(pid == 0) {
		if(n <= 0)
			exit(0);
		if(n == 1)
			exit(1);
		exit(fib(n-1)+fib(n-2));
	}
	else {
		wait(&status);
		result = (status>>8)&0xff;
		return(result);
	}
}
0707070001000311721004440000000000010000011575610454650113200001600000020140cdb/kptrace.c /* @(#)kptrace.c	1.3 8/8/86 */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <errno.h>
#include <termio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <ctype.h>

#include "cdb.h"

struct termio vatty;

extern void Transmit();
int	vsigKludge = 0;
int	vsignal;
int	vcSecWait = 2;
int	vmsgqid;		/* message que msqid for talking to cu */

/* the following message types are exchanged between cu and cdb */
#define MSG_SHUTDOWN	1	/* sent by cdb when it is going to exit */
#define MSG_RESUME	2	/* sent by cdb when cu should resume control */
#define MSG_SCAN	3	/* sent by transmit when recieve should resume
					scanning for "*** sysdebug " */
#define MSG_SYSDEBUG	4	/* sent by transmit when recieve has sent signal
					indicating sysdebug was entered */
#define MSG_INITCOMM	5	/* sent by cdb when successfully starts up */


#define iBufMax	10
int	viBuf;
char	vrgBuf[iBufMax][128];
SBT	vsbRx;

#define cbMsgMax 256	/* max bytes host OR remote can tx OR rx at one time */
char	vsbTxLast[cbMsgMax]; /* copy of last transmisson */



/* S B   F   I N D E X */

local SBT SbFIndex(i)
int	i;
{
    if (i > 0)
	return(sbNil);
    if ((i += viBuf) < 0)
	i += iBufMax;
    return(vrgBuf[i]);
} /* SbFIndex */

local int HexFIndex(i)
int i;
{
	char *pt;

	pt = SbFIndex(i);
/*
	if (!isxdigit(pt[0]) || FHdrCmp(pt,"bad address")) {
		errno = EIO;
		return(-1);
	}
*/

	return(strtol(pt,NULL,16));
}


/* R E A D   S B */

export int ReadSb(fn, sb, cb)
int	fn, cb;
FAST SBT	sb;
{
    FAST int	i, ret;
    char	ch;

    i = 0;
    while (--cb > 0) {
	do {
	    ret = read(fn, &ch, 1);
	} while (ret == 1 && !(ch &= 0x7f));
	*sb++ = ch;
	i++;
	if (ret < 0)
	    return(ret);
	if (ret == 0)
	    break;
	if (ch == '\n' || ch == '\r')
	    break;
    } /* while */
    *sb = chNull;
    return(i);
} /* ReadSb */


/* F   W A I T   F O R */

local int FWaitFor(sbWait, cSeconds)
SBT	sbWait;
int	cSeconds;
{
    int		ret, err;

    vcsRemote = csReading;
    viBuf = 0;
    while (1) {
	alarm(cSeconds);

	ret = ReadSb(v->fnComm, vrgBuf[viBuf], sizeof(vrgBuf[viBuf]));
	err = errno;

	alarm(0);

	if (ret > 0) {
	    if (FHdrCmp(sbWait, vrgBuf[viBuf]))
		break;;
	    if (v->debuglevel >= 10)
		printf("%s", vrgBuf[viBuf]);
	} else if (ret < 0) {
	     /* Then we timed out OR we lost the line.
	      * Or .......
	      */
	    if (v->debuglevel >= 10)
			printf("timeout\n");
		break;;
	} /* if */

	if (++viBuf >= iBufMax)
	    viBuf = 0;
    } /* while */
    vcsRemote = csNil;
    if (vfInterruptPending) {
	vfInterruptPending = false;
	Fixer();
    }
    return(ret>0);
} /* FWaitFor */

/* S E N D   M E S S A G E   T O   C U  */
local void FSendCuMsg(m)
int m;
{
	struct msgbuf msgb;

	msgb.mtype = m;
	msgsnd(vmsgqid,&msgb,0,0);
}



/* W A I T   F O R   D E B U G */

/* tell cu to resume processing and look for "*** sysdebug " */
local void FWaitForDebug()
{
	struct msgbuf msgb;

	signal(SIGINT, SIG_IGN);
    	vfInWait = true;
	FSendCuMsg(MSG_RESUME);
	msgrcv(vmsgqid,&msgb,0,MSG_SYSDEBUG,0);
    	vfInWait = false;
	signal(SIGINT, Fixer);
}


/* G E T   P R O M P T */

local int GetPrompt()
{
    return(FWaitFor("cdb", vcSecWait));
} /* GetPrompt */


/* T R A N S M I T */

export void Transmit(sbTx)
SBT	sbTx;
{
    int		cbTx, cb;

    /* Transmit the string */
    if (sbTx != vsbTxLast)
	strcpy(vsbTxLast, sbTx);	/* save for re-transmission */
    
    cbTx = strlen(sbTx);

    if (v->fCommDebug) {
	char	sbTemp[200];
	strcpy(sbTemp, sbTx);
	sbTemp[strlen(sbTemp)-1] = '\n';
	printf("TxHost: %s", sbTemp);
    } /* if */

    if (v->fnComm <= 2)
	Panic("Transmit - v->fnComm: %d.", v->fnComm);

    vcsRemote = csWriting;
    cb = write(v->fnComm, sbTx, cbTx);
    vcsRemote = csWriteDone;

    if (cb != cbTx)
	SysPanic("Transmit: %d bytes to go, %d went.", cbTx, cb);
} /* Transmit */


/* P T R A C E */

export int Ptrace(pt, pid, adr, value)
int	pt, pid;
char	*adr;
int	value;
{
    int		ret;
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return( ptrace(pt, pid, adr, value) );

    switch (pt) {
	default:
	    return( -1 );

	case ptReadI:
	case ptReadD:
	    /* put:	r adr
	     * get:	12345678
	     */
	    sprintf(sbPt, "r %x\r", adr);
	    Transmit(sbPt);
	    GetPrompt();
	    return(HexFIndex(-2));

	case ptReadUser:
	    /* put:	x reg
	     * get:	12345678
	     */
	    sprintf(sbPt, "x %x\r", adr);
	    Transmit(sbPt);
	    GetPrompt();
	    return(HexFIndex(-2));

	case ptWriteI:
	case ptWriteD:
	    /* put:	M adr hi-2-bytes lo-2-bytes
	     * get:	..... prompt
	     */
	    sprintf(sbPt, "M %x %x %x\r", adr, (value >> 16) & 0x0000ffff,
			value & 0x0000ffff);
	    Transmit(sbPt);
	    GetPrompt();
	    return(value);

	case ptWriteUser:
	    /* put:	m reg value
	     * get:	prompt
	     */
	    sprintf(sbPt, "m %x %x\r", adr, value);
	    Transmit(sbPt);
	    GetPrompt();
	    return(value);

	case ptResume:
	    /* put:	e
	     * get:	who knows!!!!
	     */
	    Transmit("e\r");
	    FWaitFor("e", vcSecWait);
	    return(0);

	case ptTerm:
	    Transmit("E\r");
	    FWaitFor("E", vcSecWait);
	    v->pid = 0;
	    vsigKludge = -1;
	    return(0);

	case ptSingle:
	    Transmit("s 1\r");
	    GetPrompt();
	    Transmit("e\r");
	    FWaitFor("e", vcSecWait);
	    return(0);

    } /* switch */
} /* Ptrace */


/* S E N D   S I G N A L */

export int SendSignal(sig)
int2	sig;
{
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return(kill(v->pid, sig));

    printf("Please push the RED BUTTON to enter sys debug\n");
} /* SendSignal */


/* W A I T */

export int Wait(pstatus)
int	*pstatus;
{
    int		ret, sig;
    char	sbTemp[200];

    if (v->fnComm == fnNil)
	return(wait(pstatus));

    /* here we do what is necessary to *look like* "wait (2)" */

    if (vsigKludge != 0) {
	*pstatus = vsigKludge<0 ? 0 :(vsigKludge << 8) + 0x7f;
	vsigKludge = 0;
	return(v->pid);
    } /* if */

    FWaitForDebug();
    ReadSb(v->fnComm,sbTemp,sizeof(sbTemp));

    if (FHdrCmp("single", sbTemp)) {
	sig = SIGTRAP;
    } else if (FHdrCmp("for unknown", sbTemp)) {
	sig = SIGTRAP;
    } else if (FHdrCmp("interrupt", sbTemp)) {
	sig = SIGINT;
    } else if (FHdrCmp("call", sbTemp)) {
	sig = SIGINT;
    } else if (FHdrCmp("invalid", sbTemp)) {
	sig = SIGILL;
    } else if (FHdrCmp("breakpoint", sbTemp)) {
	sig = SIGTRAP;
    } else {
	sig = SIGTRAP;
    } /* if */

    *pstatus = (sig << 8) + 0x7f;

    if(!GetPrompt()) {
    	Transmit("p\r");
    	GetPrompt();
    }
    return(v->pid);
} /* Wait */


/* C R E A T E   T A R G E T */

export void CreateTarget()
{
    int		ret;
    char	sbBuf[200];

    if (v->fnComm == fnNil) {
	OsCreateTarget();	/* cause a NATIVE process to be born */
	return;
    } /* if */

    v->pid = 1;
    vsigKludge = SIGINT;

    printf("Force system into sysdebug (somehow....)\n");
    FWaitForDebug();
    FWaitFor("+ ", 1);
    Transmit("p\r");
    GetPrompt();

    AllBpInstall();
    printf("Target is now running\n");
} /* CreateTarget */


/* X   B L O C K   M O V E */

export void XBlockMove(pid, adrDest, adrSrc, cb)
int	pid;
ADRT	adrDest, adrSrc;
int	cb;
{
    /* transfer a block WITHIN the remote machine */
} /* XBlockMove */


/* X   B L O C K   T R A N S F E R */

export void XBlockTransfer(pid, adrDest, adrSrc, cbIn, fTx)
int	pid;
ADRT	adrDest, adrSrc;
int	cbIn;
FLAGT	fTx;
{
} /* XBlockTransfer */


/* C L O S E   C O M M */

export void CloseComm()
{
    int		ipr;
    char	sbBuf[cbMsgMax];

    if (v->fnComm != fnNil && v->pid ) {
	RemoveAllBp();
	Transmit("e\r");
	FWaitFor("e", vcSecWait);
    } /* if */
    FSendCuMsg(MSG_SHUTDOWN);	/* tell cu that cdb is closing down */
} /* CloseComm */


/* I N I T   C O M M */

export void InitComm(pr)
pPRR	pr;
{
    int n;

    /* get the message queue id and file descriptor number passed from cu */
    if (sscanf(pr->sbComm,":%d:%d",&vmsgqid,&n) != 2)
	UError("Invalid comm string from cu : %s", pr->sbComm);

    v->fnComm = n;
    v->os->fClearFp = false;
    v->os->adrReg0 = 0;	 /* Magic values */
    v->os->adr_u_ar0 = 0;
    v->os->adrUser = 0;
    v->os->adrEntry = adrNil;	/* so we do NOT do ExecInit automatically */
    v->cpu->fBackupOnBpt = false;

    FSendCuMsg(MSG_INITCOMM);	/* tell cu that cdb is initialized */
} /* InitComm */
0707070001000311731004440000000000010000011576600454650113200001100000021526cdb/bp.c /* $Header: bp.c,v 6.3 86/09/03 10:48:43 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/*
 * This file cantains the routines that manage the breakpoint list.
 */

#include "cdb.h"

local BPR vabpContinue = {adrNil, 0, 0, 0, 1, 1, "Q"};
export pBPR vbpContinue = &vabpContinue;
local BPR vabpStop = {adrNil, 0, 0, 0, 1, 1, "Q"};
export pBPR vbpStop = &vabpStop;

export FLAGT	vfNewBreaks = false;


/* F   S A V E   B P */

export FLAGT FSaveBp(fp)
FILE	*fp;
{
    int		ibp;
    FLAGT	fDidOne;
    pBPR	bp;
    char	sbBuf[200];

    fDidOne = false;
    for (ibp = 0, bp = v->rgBp; ibp < v->ibpMac; ibp++, bp++) {
	fprintf(fp, "0x%x bi %s\n", bp->adr, bp->sbBp);
	fDidOne = true;
    } /* for */
    return(fDidOne);
} /* FSaveBp */


/* L I S T   B P */

export void ListBp()
{
    FAST int	ibp;
    FAST pBPR	bp;

    /* Show all active breakpoints for the current process */

    if (v->ibpMac == 0)
	UError("No breakpoints set.");

    bp = v->rgBp;
    for (ibp=0; ibp < v->ibpMac; ibp++, bp++) {
	printf("%2d ", ibp);
	PrintPosition(bp->adr, fmtProc+fmtLn);
	printf("  count: %d", bp->count);
#ifdef CDB_DEBUG
	printf("  addr: %lx  inst: %d", bp->adr, bp->inst);
#endif /* CDB_DEBUG */
	if (bp->count <= 0)
	    printf(" (temp)");
	if (bp->sbBp[0] != chNull)
	    printf("   <%s>", bp->sbBp);
	printf("\n");
    } /* for */
} /* ListBp */


/* A L L   B P   I N S T A L L */

export void AllBpInstall()
{
    FAST int	ibp;

    /* Make sure ALL bp's are in the child */

    for (ibp=0; ibp < v->ibpMac; ibp++)
	if (v->rgBp[ibp].inst == 0)
	    InstallBp(v->rgBp+ibp);
} /* AllBpInstall */


/* R E M O V E	 A L L	 B P */

export void RemoveAllBp()
{
    FAST int	ibp;
    FAST pBPR	bp;

    if ((v->ps != psStopped) AND (v->ps != psNoChild))
	UError("You may not remove breakpoints from a non-stopped process.");

    /* Make sure NO bp's are in the child */

    for (ibp=0, bp=v->rgBp; ibp < v->ibpMac; bp++, ibp++)
	RemoveBp(bp);
} /* RemoveAllBp */


/* C L E A R   B P */

export void ClearBp(bp)
pBPR	bp;
{
    FAST int	ibp = bp - v->rgBp;

    /* Remove one bp from the current list. Move the others up one slot */

    if ((v->ps != psStopped) AND (v->ps != psNoChild))
	UError("You may not remove breakpoints from a running process.");

    if ((bp == bpNil) OR (ibp >= v->ibpMac))
	return;

    RemoveBp(v->rgBp + ibp);
    ShowBp(bp, false);
    v->ibpMac--;

    /* cause rest to move up */
    for ( ; ibp < v->ibpMac; ibp++)
	v->rgBp[ibp] = v->rgBp[ibp+1];
} /* ClearBp */


/* C L E A R   A L L */

export void ClearAllBp()
{
    FAST int	ibp;
    FAST pBPR	bp;

    /* Clear ALL bp's */

    for (ibp=0, bp=v->rgBp; ibp < v->ibpMac; bp++, ibp++)
	ShowBp(bp, false);

    RemoveAllBp();
    v->ibpMac = 0;
    if (!v->fQuiet)
	printf("All breakpoints deleted\n");
} /* ClearAllBp */


/* B P	 F   I F D   I L N */

export pBPR BpFIfdIln(ifd, iln)
int2	ifd, iln;
{
    FAST int	ibp;
    FAST pBPR	bp;

    /* Given an file/line number, return the bp there, if any. */

    if (ifd == ifdNil)
	return(bpNil);

    for (ibp=0, bp=v->rgBp; ibp < v->ibpMac; bp++, ibp++)
	if ((bp->ifd == ifd) AND (bp->iln == iln))
	    return(bp); 
    return(bpNil);
} /* BpFAdr */


/* B P	 F   A D R */

export pBPR BpFAdr(adr)
FAST ADRT	adr;
{
    FAST int	ibp;
    FAST pBPR	bp;

    /* Given an address, return the bp there, if any. */

    if (adr == adrNil)
	return(bpNil);

    for (ibp=0, bp=v->rgBp; ibp < v->ibpMac; bp++, ibp++)
	if (bp->adr == adr)
	    return(bp); 
    return(bpNil);
} /* BpFAdr */


/* B P	 F   P R O C E S S */

export pBPR BpFProcess(adr)
ADRT	adr;
{
    FAST int	ibp;
    FAST pBPR	bp, bpRet;

    /* This is called whenever a process has stopped.
     * We remove all 0-count temps and process the
     * other breakpoints for break counts.
     *
     * If we are stopped at a break, its bp is returned.
     */

    bpRet = bpNil;
    for (ibp=0, bp=v->rgBp; ibp < v->ibpMac; bp++, ibp++) {
	if (bp->count == 0) {
	    if (bp->adr == adr)
		bpRet = vbpStop;
	    ClearBp(bp);
	    ibp--;	/* ClearBp shuffles things, back up one */
	    bp--;
	    continue;
	} /* if */

	if ((bp->adr != adr) OR (bp->inst == 0))
	    continue; /* wrong address OR not installed */

	/* This break is at the correct address, adjust its count */
	if (bp->count < 0) {
	    /* it's a temp break */
	    if ((bp->count += 1) == 0) {
		v->abp = *bp; /* transfer into the holding slot */
		bpRet = &v->abp;
		ClearBp(bp);
		ibp--;
		bp--;
	    } else {
		bpRet = vbpContinue;
	    } /* if */
	} else {
	    /* it's a permanent break */
	    if ((bp->count -= 1) <= 0) {
		bp->count = 1;	/* we refresh it if it goes 0 */
		bpRet = bp;
	    } else {
		bpRet = vbpContinue;
	    } /* if */
	} /* if */
    } /* for */

    v->bp = bpRet;
    return(bpRet);
} /* BpFProcess */


/* B P	 F   A D D   B P */

export pBPR BpFAddBp(adr, count, sbCmd, cb)
ADRT	adr;
int2	count, cb;
SBT	sbCmd;
{
    FAST pBPR	bp;

    /* Add a breakpoint to the current process */

    if (adr == adrNil)
	UError("Attempt to set breakpoint at invalid address.");

    /* see if we already have this one - if so, remove it */
    bp = BpFAdr(adr);
    if (bp != bpNil) {
	if (count == 0)
	    return(bp); /* temp bp's do NOT cause removal */
	ClearBp(bp);
    } /* if */

    if (v->ibpMac >= v->ibpMax) {
	v->ibpMax += 10;
	if (v->ibpMax == 10) {
	    v->bp = bpNil;
	    v->rgBp = (pBPR) malloc(v->ibpMax*cbBPR);	/* allocate bp table */
	} else {
	    v->rgBp = (pBPR) realloc(v->rgBp, v->ibpMax*cbBPR);
	} /* if */
	if (v->rgBp == 0)
	    Panic("Ran out of memory.");
    } /* if */

    bp = v->rgBp + v->ibpMac;
    v->ibpMac++;

    bp->adr = adr;
    bp->count = count;
    bp->ifd = IfdIlnFAdr(&bp->iln, adr);
    if (sbCmd == sbNil) {
	bp->sbBp[0] = chNull;
    } else {
	strncpy(bp->sbBp, sbCmd, cb);
	bp->sbBp[cb] = chNull;
    } /* if */
    bp->inst = 0;	/* forces it to be installed at next run */
    ShowBp(bp, true);
    return(bp);
} /* BpFAddBp */


/* B P	 F   S E T */

export pBPR BpFSet(bpc, fTemp, cnt, sbCmd, cb)
int2	bpc, cnt, cb, fTemp;
SBT	sbCmd;
{
    ADRT	adr;
    int		ipd, ifdSave, ipdSave, ilnSave;
    char	sbTok[50], sbTemp[100];
    pBPR	bp;
    CNTXR	acntx;
    TKE		tk;

    /* Set one of a number of fancy breaks - uplevel, proc begin, exit... */

    /* the ifd is set to nil at the end */
    ipd = ipdSave = v->ipd;
    ifdSave = v->ifd;
    ilnSave = v->iln;

    acntx = v->acntx;

    if (cnt >= 0) {		/* they want to do this stack relative */
	if (v->pid == pidNil)
	    UError("Command is stack-relative, but there is no child process.");

	while ((cnt > 0) AND ! acntx.fEndOfStack) {
	    NextFrame(&acntx);
	    --cnt;
	} /* if */
	if (acntx.fEndOfStack)
	    UError("Stack isn't that deep!");
    } /* if */

    switch (bpc) {
	default:
	    UError("Unknown breakpoint type `%d'.", bpc);

	case bpcBegin:
	    ipd = (cnt >= 0) ? IpdFAdr(acntx.pc) : v->ipd;
	    OpenIpd(ipd, true); /* force it open */
	    adr = AdrFIpdIln(v->ipd, v->iln);
	    break;

	case bpcEnd:
	    ipd = (cnt >= 0) ? IpdFAdr(acntx.pc) : v->ipd;
	    adr = AdrFEndOfProc(ipd);
	    break;

	case bpcUp:
	    /* move past instruction which fixes the stack pointer */
	    adr = AdrFStackFix(acntx.pc);
	    if (vfNewBreaks) {
		sprintf(sbTemp, "Q;if ((int)$fp == 0x%x) {%sH}{c}", acntx.fp,
			    (fTemp) ? "d;" : "");
		fTemp = false;
		sbCmd = sbTemp;
		cb = strlen(sbCmd);
	    } /* if */
	    break;

	case bpcProc:	/* trace breakpoint */
	    if (cnt >= 0) {
		if ((ipd = IpdFAdr(acntx.pc)) == ipdNil)
		    UError("No symbols for that procedure.");
		v->ipd = ipd;
	    } else {
		TkPeek();
		if ( (tk == tkStr)
		   AND ((ipd = IpdFName(vsbTokPeek)) != ipdNil) ) {
		    TkNext();	/* actually eat it */
		    v->ipd = ipd;
		} /* if */
	    } /* if */

	    /* set break at entrance */
	    sbCmd = "Q;bU {Q;\"Exiting %s: \";$result/n;c};\"Entering \";1t;c";
	    sprintf(sbTemp, sbCmd, SbFIpd(ipd));
	    sbCmd = sbTemp;
	    cb = strlen(sbCmd);
	    OpenIpd(ipd, true);	/* force it open */
	    adr = AdrFIpdIln(ipd, v->iln);
	    break;
    } /* switch */

    if (adr != adrNil)
	bp = BpFAddBp(adr, ((fTemp) ? -1 : 1), sbCmd, cb);

    v->ifd = ifdNil;
    OpenIfd(ifdSave);
    v->iln = ilnSave;
    v->ipd = ipdSave;
    return(bp);
} /* BpFSet */


/* Fork Save Hack - clean it up laster........  */

struct FSS {
	int2	pid;
	ADRT	adr;
	uint4	inst;
	};
#define ifsMax 512
struct FSS vrgFs[ifsMax];
int	vifsMac = 0;

/* S A V E   F O R K   B P */

export void SaveForkBp(bp)
pBPR	bp;
{
    vrgFs[vifsMac].adr = bp->adr;
    vrgFs[vifsMac].inst = bp->inst;
    vrgFs[vifsMac].pid = v->pid;
    vifsMac++;
} /* SaveForkBp */


/* B P   F   F O R K    S A V E */

export pBPR BpFForkSave(pid, adr)
int2	pid;
ADRT	adr;
{
    int		ifs;
    static BPR	abp;

    for (ifs = 0; ifs < vifsMac; ifs++)
	if ((vrgFs[ifs].pid == pid) AND (vrgFs[ifs].adr == adr)) {
	    abp.adr = adr;
	    abp.inst = vrgFs[ifs].inst;
	    return(&abp);
	} /* if */
    return(bpNil);
} /* BpFForkSave */
0707070001000311741004440000000000010000011577570454650113200001200000036734cdb/cpu.c /* $Header: cpu68.c,v 6.3 86/09/01 17:20:42 peter Exp $ */

/* This program is an unpublished work fully protected by the
 * United States Copyright Laws and is considered a TRADE SECRET
 * belonging to Third Eye Software, Inc.
 */

/* ******************************************************* */
/*							   */
/* This is the Motorola 68000 (and 68010 and 68020) module */
/*							   */
/* ******************************************************* */

#if 0
exportdefine X_InitRegisters	1
exportdefine X_ListRegisters	1
#endif

#include "cdb.h"

#include <errno.h>
#include <sys/param.h>

#if (OP_SYS == SYSV)
#include <signal.h>
#include <sys/types.h>
#endif

#include <sys/dir.h>
#include <sys/user.h>

#if ((OP_SYS == BSD42) || (OP_SYS == BSD41c))
#include <machine/reg.h>
#else
#include <sys/reg.h>
#endif


CPUR	vacpu68;	/* where we put 68000 relative info */
ADRT	vadrRegBase;	/* used in GetMask/DoReg */

#if (HOST_CPU == M68000)
/* these are 'export'ed in main.c */
pCPUR	vcpuHost = &vacpu68;
#endif

#if (SYS == P60V)
#define R8	AR0
#define R9	AR1
#define R10	AR2
#define R11	AR3
#define R12	AR4
#define R13	AR5
#define R14	AR6
#define SP	USP
#define R15	SP
#undef PS
#define PS	SR
#endif /* (SYS == P60V) */

#if (SYS == AR68V)
#define R0	D0
#define R1	D1
#define R2	D2
#define R3	D3
#define R4	D4
#define R5	D5
#define R6	D6
#define R7	D7
#define R8	A0
#define R9	A1
#define R10	A2
#define R11	A3
#define R12	A4
#define R13	A5
#define R14	A6
#define R15	A7
#define PS	SR
#endif

#if (SYS == SUN42)
#define R8	AR0
#define R9	AR1
#define R10	AR2
#define R11	AR3
#define R12	AR4
#define R13	AR5
#define R14	AR6
#define R15	AR7
#endif

#ifndef FP
#define FP	R14
#endif /* FP */

export int2 vrgOffset[] = {
	R0,  R1,  R2,  R3,
	R4,  R5,  R6,  R7,
	R8,  R9,  R10, R11,
	R12, R13, R14, R15,
	SP,  PC,  FP,  PS,
	FP
	};

#define	IntFSb(sb) ((int)sb)

export SER vrgReg[40];		/* array of register variables */
export int viregMax;


/* A D R   F   S T A C K   F I X */

export ADRT AdrFStackFix(adr)
ADRT	adr;
{
    int2	inst;

    /* given an address immediately after a procedure call, step over any
     * stack fix-up instructions.
     */

#define TST_INST	0x4a5f
#define TSTL_INST	0x4a9f
#define CMPML_INST	0xbf8f
#define ADDW_INST	0xdefc
#define ADDQ_INST	0x500f
#define ADDN_INST	0x504f

    GetBlock(adr, spaceText, (ADRT)&inst, 2);
    if ( (inst == TST_INST)
       OR (inst == TSTL_INST)
       OR (inst == CMPML_INST)
       OR ((inst & 0xf13f)  == ADDQ_INST))
	adr += 2;
    else if ((inst & 0xf1ff) == ADDN_INST)
	adr += 4;
    return(adr);
} /* AdrFStackFix */


/* A D R   F   P R E A M B L E */

export ADRT AdrFPreamble(adr)
ADRT	adr;
{
    /* given the first address in a procedure, return the address of the
     * first `real' instruction - ie. after the csav0 or the brb whatever
     */

    int		op, ipd, iln;

#   define BRA		0x60
#   define LINK		0x4e

    /* First we try it based on opening brackets */
    ipd = IpdFAdr(adr);
    if (v->rgPd[ipd].iline != 0)
	return(AdrFirstFIpd(ipd));

    /* then we do it based on skipping over branch */
    op = GetByte(adr, spaceText);	/* get instruction */
    if (op == BRA) {
	adr++;
	op = GetByte(adr, spaceText);
	adr++;
	if (op == 0)
	    adr += 2;	/* it's a long branch */
    } else if (op == LINK) {
	adr += 4;
    } /* if */

    return(adr);
} /* AdrFPreamble */


/* F   A T   C A L L */

export FLAGT FAtCall(adr)
ADRT	adr;
{
#define JSR_INST	0x4e80
#define BSR_INST	0x6100
#define cbInsMax	2

    int2	inst = 0;
    /* return true or false based on whether the instruction at adr
     * is a procedure call of any kind.
     */

    GetBlock(adr, spaceText, (ADRT)&inst, cbInsMax);
    v->fAtSyscall = ((inst & 0xffff) == v->os->instSyscall);
    return(((inst & 0xff00) == BSR_INST) OR ((inst & 0xffc0) == JSR_INST));
} /* FAtCall */


/* R E T   F   S P */

export ADRT RetFSp(sp)
ADRT	sp;
{
    ADRT	adr;
    /* given the stack pointer immediately after a procedure call,
     * return the return address
     */
    GetBlock(sp, spaceData, (ADRT)&adr, v->cpu->cbPointer);
    return(adr); /* get return */
} /* RetFSp */



/* N E X T   I N S T   A D R   F   A D R */

local ADRT NextInstAdrFAdr(adr)
ADRT adr;
{
    vfOutputSuppress = true;
    PrintInstruction(adr);
    vfOutputSuppress = false;
    return(adr + vcbInst);
} /* NextInstAdrFAdr */


/* A D R   R E G   F   C N T X */

local ADRT AdrRegFCntx(cntx, reg)
pCNTXR cntx;
ADRT reg;
{
    ADRT	fp, pc;
    FAST ADRT	adr;
    ADRT	adrRet;
    ADRT	adrNext;
    ADRT	adrBase;
    pPDR	pd;
    uint1	op;
    int2	offset;
    uint4	mask;
    uint2	maskImage;
    uint4	maskSave, maskTest;
    int4	longOffset;
    int		inc, i, c;

#   define cInstMax	15

#   define MOVL		0x2e
#   define MOVEML	0x48
#   define MISC		0x4e
#   define LINK		0x4e
#   define LINK20	0x48
#   define BRA		0x60
#   define TST		0x4a

#   define maskReverse	0x10000000

    pc = cntx->pc;
    fp = cntx->fp;

    pd = v->rgPd + IpdFAdr(pc);
    if (pd->dadrRegBase == adrNil) {
	adr = pd->adr;	/* get start of this proc */

	/*
	 * Step throught the code looking for a link instruction.
	 * Some procedures will not have a link instruction.
	 */

	adrNext = adr;
	adrBase = adrNil;
	for(c = 0; c < cInstMax; ++c) {
	    adr = adrNext;
	    adrNext = NextInstAdrFAdr(adr);
	    op = GetByte(adr, spaceText);	/* get instruction */

	    if(op == BRA) {
		/*
		 * handle the normal case where the preamble code is
		 * generated at the end of the procedure so the first
		 * instruction is a branch/jump to the end
		 */
		adr++;
		op = GetByte(adr, spaceText);
		adr++;
		if (op == 0) {
		    GetBlock(adr, spaceText, (ADRT)&offset, 2);
		    adr += offset;
/* (CPU == M68020) */
		} else if (op == 0xff) {
		    GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
		    adr += longOffset;
/* (CPU == M68020) */
		} else {
		    adr += op;
		} /* if */
		adrNext = adr;
		continue;
	    } /* if */

#if (MFG == SUN)
             if (op == 0xdf) {
                adr++;
                op = GetByte(adr, spaceText);
                adr++;
                if(op == 0xfc) {
                    GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
                    pd->dadrRegBase += longOffset;
                }
            }
#endif /* (MFG == SUN) */

#if (MFG == ISI)
	    if (op == MOVL) {
		adr++;
		op = GetByte(adr, spaceText);
		if(op == 0x87) {
		    mask = 0x0080;
		    break;
		}
		if(op == 0x8d) {
		    mask = 0x2000;
		    break;
		}
	    }
#endif

	    if (op == MISC) {	/* also is JMP */
		adr++;
		op = GetByte(adr, spaceText);
		adr++;
		/*
		 * if we hit a trap instruction or a
		 * return instruction we are done
		 */
		if((op & 0xf0) == 0x70 || (op & 0xf0) == 0x40) {
		    pd->dadrRegBase = 0;
		    pd->maskReg = 0;
		    return(adrNil);
		} /* if */

		/*
		 * if we hit a jmp, follow it if the target is (pc)
		 */
		if((op & 0xfe) == 0xf8) {
		    if(op & 0x01) {
			GetBlock(adr, spaceText, (ADRT)&offset, 2);
			adrNext = offset;
		    } else {
			GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
			adrNext = longOffset;
		    }
		    continue;
		}

		/*
		 *	check for short link instruction
		 */
		if((op & 0xf8) == 0x50) {
		    GetBlock(adr, spaceText, (ADRT)&offset, 2);
		    adrBase = offset;
		    pd->dadrRegBase = adrBase;
		    continue;
		} /* if */
	    } /* if */

	    if (op == MOVEML) {
		adr++;
		op = GetByte(adr, spaceText);
		adr++;

/* (CPU == M68020) */
		/* check for 68020 32 bit link instruction */
		if ((op & 0xf8) == 0x08) {
		    GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
		    adrBase = longOffset;
		    pd->dadrRegBase = adrBase;
		    continue;
		} /* if */
/* (CPU == M68020) */

		if (op & 0x80) {
		    GetBlock(adr, spaceText, (ADRT)&maskImage, 2);
		    adr += 2;
		    mask = maskImage;
		    if((op & 0x38) == 0x20) {
			mask |= maskReverse;
		    }
		    pd->maskReg = mask;
		    /* modify dadrRegBase if an offset is specified */
		    if(op == 0xef) {
			GetBlock(adr, spaceText, (ADRT)&offset, 2);
			pd->dadrRegBase += offset;
		    }
		    else if(op == 0xee) {
			GetBlock(adr, spaceText, (ADRT)&offset, 2);
			pd->dadrRegBase = offset;
			break;
		    }
		    break;
		} /* if */
	    } /* if */
	} /* for */
    } /* if */

    mask = pd->maskReg;
    vadrRegBase = fp + pd->dadrRegBase;
    maskSave = mask & 0x0000ffff;	/* only lower 16 bits are used */
    if (mask & maskReverse) {
	reg = 15 - reg;
	inc = - v->cpu->cbRegister;
    } else {
	inc = v->cpu->cbRegister;
    } /* if */

    maskTest = 1 << reg;
    adrRet = adrNil;

    if (maskSave & maskTest) {
	/* it has a saved copy of this register */
	adrRet = vadrRegBase;	/* set to base of saved registers */
	if (mask & maskReverse)
	    adrRet += inc;

	for (i = 0; i < reg; i++) {
	    if (maskSave & 1)
		adrRet += inc;	/* a saved reg takes up space */
	    maskSave >>= 1;
	} /* for */
    } /* if */

    return(adrRet);
} /* AdrRegFCntx */

/*  D O   R E G */

export void DoReg(seReg, cntx)
pSER	seReg;
pCNTXR	cntx;
{
    int		inc, maskSave, maskTest, i;
    ADRT	adrRet, reg, adr;
    CNTXR	acntx;

    /* Given a desired fp and the register, we walk back up the stack,
     * looking for frames that may have saved this register.  If we find
     * one, we figure out the memory address of the saved register and
     * continue.  Only when we reach our desired frame, after (perhaps)
     * seeing this register get saved N times, do we actually know for sure
     * where the %@#%$# thing is!
     */

    reg = seReg->asym.value;
    adrRet = reg;	/* by default we assume it is still in the reg */

    for (acntx = v->acntx; acntx.fp != cntx->fp; NextFrame(&acntx)) {
	if (acntx.fp == 0)
	    Panic("Clobbered stack(?)");

	/* find out the address this register is stored at in this frame */

	if((adr = AdrRegFCntx(&acntx, reg)) != adrNil) {
		seReg->asym.sc = scRegImage;	/* REAL storage class */
		adrRet = adr;	
	}
    } /* for */

    seReg->asym.value = adrRet;
} /* DoReg */


/* N E X T   F R A M E */

export int NextFrame(cntx)
pCNTXR	cntx;
{
    /* Set the context values to be the next frame
     * OR we give them an fp of 0 to indicate end-of-stack.
     * Returns true if we had to slide around a
     * proc-call-from-the-command-line mini frame.
     */

    if ((v->adrStartLow <= cntx->pc) AND (v->adrStartHigh > cntx->pc)) {
	/* this check handles the case where ONLY "start" is on the stack */
	/* there is nothing beyond the start frame */
	cntx->fEndOfStack = true;
	return(false);
    } /* if */

    cntx->fEndOfStack = false;
    cntx->pc = GetWord(cntx->fp + v->cpu->cbPointer, spaceData);
    cntx->fp = GetWord(cntx->fp, spaceData);
    cntx->ap = cntx->fp;	/* they are the same */

    if (cntx->pc == v->adrBreak) {
	/* this frame is the end of a proc-call from the command line */
	cntx->pc = GetWord(cntx->fp + v->cpu->cbPointer, spaceData);
	cntx->fp = GetWord(cntx->fp, spaceData);
	cntx->ap = cntx->fp;
	return(true);
    } /* if */

    /* see if this is the 'start' frame */
    if ((v->adrStartLow <= cntx->pc) AND (v->adrStartHigh > cntx->pc)) {
	cntx->fEndOfStack = true;
    } else {
	cntx->fEndOfStack = (cntx->fp == 0);
    } /* if */

    return(false);
} /* NextFrame */


/* I N I T   R E G I S T E R S */

export void InitRegisters(cpu)
pCPUR	cpu;
{
    ADRT	adr;
    pSER	se;

    cpu->rgReg = vrgReg;
    se = vrgReg;

    InitSpc(se++, "result", u0, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "fp", ufp, stExpr, scRegister, tqPtr, btInt, false);
    InitSpc(se++, "sp", usp, stExpr, scRegister, tqPtr, btInt, false);
    InitSpc(se++, "pc", upc, stExpr, scRegister, tqPtr, btInt, false);

    InitSpc(se++, "d0", u0, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d1", u1, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d2", u2, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d3", u3, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d4", u4, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d5", u5, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d6", u6, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d7", u7, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a0", u8, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a1", u9, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a2", u10, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a3", u11, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a4", u12, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a5", u13, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a6", u14, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a7", u15, stExpr, scRegister, tqNil, btInt, false);

#if (MFG == ISI)
#define FP_REGS	((ADRT)(((struct user *)0)->u_68881_regs));
#endif /* (MFG == ISI) */

#ifdef FP_REGS
    adr = FP_REGS;
    InitSpc(se++, "fd0", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd1", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd2", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd3", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd4", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd5", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd6", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd7", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;

    InitSpc(se++, "f0", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
    InitSpc(se++, "f1", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
    InitSpc(se++, "f2", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
    InitSpc(se++, "f3", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
#endif /* FP_REGS */

    cpu->iregMax = se - vrgReg;;
} /* InitRegisters */


/* L I S T   R E G I S T E R S */

export void ListRegisters(sbRegs)
SBT	sbRegs;
{
    int		i;
    pSER	se;
    MODER	amode;

    vmode->cnt = 1;
    vmode->df = dfNil;
    vmode->len = -1;
    GetMode(vmode);

    if ((v->pid == pidNil) AND (v->fnCore == fnNil))
	UError("No process.");

    if ((vmode->df != dfPStr) AND (vmode->df != dfStr)) {
	/* then we can use a more compact form */
	ColOn();
	if (vmode->df == dfNil)
	    amode = *vmode;
	se = v->cpu->rgReg;
	DisplaySe(se++, vmode, true, true, true); /* result */
	PadTo(20);
	if (amode.df == dfNil)
	    *vmode = amode;
	DisplaySe(se++, vmode, true, true, true); /* fp */
	PadTo(40);
	if (amode.df == dfNil)
	    *vmode = amode;
	DisplaySe(se++, vmode, true, true, true); /* sp */
	PadTo(60);
	if (amode.df == dfNil)
	    *vmode = amode;
	DisplaySe(se++, vmode, true, true, true); /* pc */
	printf("\n\n");

	if (amode.df == dfNil)
	    *vmode = amode;
	for (i = 4; i < v->cpu->iregMax; i += 4) {
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    PadTo(20);
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    PadTo(40);
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    PadTo(60);
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    printf("\n");
	} /* for */
	ColOff();
    } else {
	se = v->cpu->rgReg;
	for (i = 0; i < v->cpu->iregMax; i++, se++) {
	    if ( (sbRegs != sbNil)
		  AND (!FHdrCmp(sbRegs, SbFIss(se->asym.iss))) ) 
		continue;	/* not interesting */
	    DisplaySe(se, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    printf("\n");
	} /* for */
    } /* if */
} /* ListRegisters */
0707070001000311751004440000000000010000011575170454650113300001400000003633cdb/dummy.c /* $Header: dummy.c,v 6.3 86/09/15 09:32:05 peter Exp $ */
/* CDB 6.0 (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

/* The stub routines satisfy various external references to missing options */

#include "cdb.h"

/* P R I N T   V E R S I O N */

export void PrintVersion(x)
int	x;
{
#include "vers.h"

    if (x == 1) {
	printf("CDB %d.%d ", major, minor);
	printf("(C) Copyright 1984 by Third Eye Software, Inc.\n");
    } else {
	printf("\n\n");
	printf("\tCDB Release %d.%d, local release %d.\n",major, minor, load);
	printf("\tLoaded on %s by %s\n", date, user);
	printf("\tThis debugger is configured for\n");
	printf("\t*** %s ***\n", SYS_NAME);
    } /* if */
} /* PrintVersion */


#ifndef LANG_FORTRAN
export void F_PxSe() {}
export pSYMR F_SymFAdr() {}
export void PxCommon() {}
export void DoCommon() {}
#endif /* LANG_FORTRAN */

#ifndef WINDOWS
export void ClearTargetScreen() { }
export void SetSrcWw() { }
export void CenterWw() { }
export void UpLine() { }
export void MakeActive() { }
export void InitAllWw() { }
export void RestoreAllWw() { }
export void WwCmd() { }
export void EdOpenFile() { }
export void JumpScrollWw() { }
export void MarkLine() { }
export void ShowBp() { }
export void Highlight() { }
#endif /* WINDOWS */

#ifndef REMOTE
export void CloseComm() { }
export void InitComm() { }
export void XBlockTransfer() { }

export void CreateTarget()
{
    OsCreateTarget();
}

export int SendSignal(sig)
int	sig;
{
    return(kill(v->pid, sig));
}

export int Ptrace(pt, pid, adr, value)
int	pt,  pid, value;
char	*adr;
{
    return(ptrace(pt, pid, adr, value));
}

export int Wait(pstatus)
int	*pstatus;
{
    return(wait(pstatus));
}

#endif /* REMOTE */

#ifndef MULTI
char * vsbMultiErr = "Debugger is not equipped with multiprocess option.";
export void FreeProcess() {}
export pPRR PrFAttachProcess() {UError(vsbMultiErr);}
export pPRR PrFExec() {UError(vsbMultiErr);}
#endif /* MULTI */
0707070001000311761004440000000000010000011575350454650113300001600000016342cdb/history.c /* $Header: history.c,v 5.4 86/06/02 23:24:54 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This file contains routines that will allow redirection of input
 * from a history buffer and from a unix file
 */

#define		h_SIZE 21
#define		LINE_SIZE 256
#define error printf

static struct {
	char	string [LINE_SIZE];
	int	number;
} h_buffer [h_SIZE];

static int 	h_index;		/* index into the buffer */
static int	h_number;		/* sequence number */

static int	h_count;		/* # in buff now */ 
static int	h_init;			/* initialize history */

extern char * redo();

/*
 *	Routines:
 *
 *		h_insert (string)	insert string in history buffer
 *		h_get (index)		return assoc. with index
 *		h_set (index)		set h_p to the indexth
 *						string and set history.
 *		h_print (index)	print the indexth string
 *		h_modify (index)	modify the indexth string
 *						with "redo", set historyp
 *						to the new string and set
 *						history.
 *
 */



/* this routine will insert the string in the next available position in
 *	the history buffer and assign it the next sequence number.
 */

h_insert (string)

	char * string;

{
	register int	empty;
	register char	*pstring;

	if (!h_init) {

		h_index= -1;
		h_init= 1;

	}

	/* remove leading blanks */
	pstring= string - 1;
	empty = 1;
	while (empty && ++pstring && *pstring)
	    empty= (*pstring == '\t' || *pstring == ' ');

	if (!empty) {

		h_index++;
		h_index%= h_SIZE;
		if (h_count != h_SIZE)
			h_count++;
		
		strcpy (h_buffer[h_index].string, pstring);

		/* make sure it is terminated with a \n */
		if (pstring [strlen (pstring) - 1] != '\n')
			strcat (h_buffer[h_index].string, "\n");
		h_buffer [h_index].number= ++ h_number;

	}

} /* h_insert */

char *
h_search (str, len)

char *str;
int len;

{
	register int i, j;

	for (i= 0, j= h_index; i < h_count; i++)
		if (!strncmp (str, h_buffer [j].string, len)) {

			return (h_buffer [j].string);

		 } else {

			j= j - 1;
			if (j < 0) j= h_SIZE;

		}

	return ((char *) 0);

}


char *
h_get (index)

	int index;

{
	register int i;

	if (!h_init) {

		h_index= -1;
		h_init= 1;

	}


	for (i= 0; i < h_count; i++)
		if (h_buffer [i]. number == index)
			return (h_buffer [i].string);

	return ((char *) 0);


} /* h_get */




#define isnum(x) ((x >= '0') && (x <= '9'))
h_set (buf)

char *buf;

{
	register char	*pbuf;
	register char	*insert;
	register int	delnum;
	register int	num;

	if (!h_init) {

		h_index= -1;
		h_init= 1;

	}

	pbuf= buf + 1;
	if (*pbuf == '#') {

		if (h_index == -1) {

			error ("History element not available\n");
			strcpy (buf, "\n");
			return (1);

		}

		insert= h_get (h_number);
		delnum= 2;

	} else if (isnum (*pbuf)) {

		num= 0;

		while (isnum (*pbuf))
			num = (num * 10) + (*(pbuf++) - '0');

		insert= h_get (num);
		if (insert == (char *) 0) {
			error ("History element out of range: %d\n", num);
			strcpy (buf, "\n");
			return (1);
		}
		delnum= pbuf - buf;

	} else {

		while (*pbuf && *pbuf != ' ' && *pbuf != '\t' && *pbuf != '\n')
			pbuf++;

		insert= h_search (buf + 1, pbuf-buf-1);
		if (insert == (char *) 0) {
			error ("History element not found\n");
			strcpy (buf, "\n");
			return (1);
		}
		delnum= pbuf-buf;

	}

	copydown (buf, 0, delnum);
	copyup (buf, 0, strlen (insert) - 1);
	strncpy (buf, insert, strlen (insert) - 1);

	return (0);

} /* h_set */





h_print ()

{
	register int i;

	if (!h_init) {

		h_index= -1;
		h_init= 1;

	}

	i= h_number - (h_SIZE - 2);
	for (i= (i > 0 ? i : 1); i <= h_number; i++)

		printf ("%3d  %s", i, h_get (i));

} /* h_print */




h_modify (buf)

char *buf;

{
	if (!h_init) {

		h_index= -1;
		h_init= 1;

	}

	*buf= '%';
	if (buf [1] == '%')
		buf [1]= '#';

	if (h_set (buf))
		return (1);

	else {
		redo (buf);
	}

	return (0);

} /* h_modify */

/* the following routine will recieve a pointer to a line and allow the
 *	user to modify it, if he presses ctrl-y at any time a null will
 *	be returned, else the poiter to the original string will be
 *	returned
 */

char *redo (realline)
char *realline;
{
	char line_buff [3] [LINE_SIZE];
	register char *line; /* new line */
	register char *in;   /* mod line */
	register char *last;
	register char *traverse;	/* traverse ptr for input line */
	register int  len;	/* length of input line */
	register int  pos;	/* pos we are up to in input line */
	register int temp;

	line= &line_buff [0] [0]; /* new line */
	in= &line_buff [1] [0];   /* mod line */
	last= &line_buff [2] [0];
	if (strlen (realline) > 255)
		UError ("Redo: line too large.");

	printf ("REDO (type '?' for help):\n");
	strcpy (line, realline);
	strcpy (last, realline);
	*in= ' '; *(in + 1)= 0;

	while (*in) {
		traverse=	in;
		pos=	0;
		len=	strlen (in);
		while (*traverse) {
			switch (*traverse) {

			case ' ':
				traverse++;
				pos++;
				continue;

			case 'i':
			case 'I':
				copyup (line, pos, len - pos - 1);
				strncpy (line + pos, ++traverse, len - pos - 1);
				break;

			case 'd':
			case 'D':
				copydown (line, pos, 1);
				copydown (in, pos, 1);
				len--;
				continue;

			case 'r':
			case 'R':
				*traverse= 'i';
				temp= strlen (in) - pos -1;
				copyup (in, pos, temp);
				len+= temp;
				for (; temp; temp--)
					*(traverse+temp-1)= 'd';
				continue;

			case '':
				return (realline);

			case '?':
				if (traverse == in) {
				    printf ("REDO help:\n");
				    printf ("	? - display help\n");
				    printf ("	<CR> - accept line\n");
				    printf ("	i - insert\n");
				    printf ("	r - replace\n");
				    printf ("	d - delete\n");
printf("REDO is a one line positional editor.  Use one of the above\n");
printf("commands underneath the desired position.  I and r are followed by\n");
printf("the string you want inserted or replaced and the d's go under the\n");
printf("characters you want deleted.  D's may be followed by an i or r\n");
printf("but an i or r must be the last commands on a line. <CR> must be\n");
printf("the only character on a line to accept the line.\n");
				    break;
				};

			default:
				printf ("ERROR: you must enter ?,i,r,d\n");
				strcpy (line, last);
				break;

			}; break;};

		strcpy(last, line);
		printf ("OLD: %s\nMOD: ",line);
		gets (in);
		in[255]= 0;
	}; /* while */

	strcpy (realline, line);

	return (realline);

} /* redo.c */





/* this routine will copy a string upwards making room in the middle of
	of it for another string */

copyup (line, pos, num)

	register	char	*line;
	register	int	pos;	/* position to start at */
	register	int	num;	/* number of spaces to open up */

{
	register	int	len;
	register	char	*newend;
	register	char	*oldend;

	len=	strlen (line);
	if (len < pos) {
		for (oldend= line + len; len != pos; len++)
			*oldend++ = ' ';
		*oldend= 0;
	};
	newend=	line + num + len;
	for (oldend= line + len;oldend != (line + pos - 1);oldend--, newend--)
		*newend=	*oldend;

} /* copyup */





/* this routine will copy a string downwards deleting part of the string */


copydown (line, pos, num)

	register	char	*line;
	register	int	pos;	/* position to start at */
	register	int	num;	/* number of spaces to delete */

{
	register	int	len;
	register	char	*newpos;
	register	char	*oldpos;

	len=	strlen (line);
	if (len <= pos) return;
	newpos=	line + pos;
	for (oldpos= line + pos + num; (newpos == line) || *(newpos - 1); oldpos++, newpos++)
		*newpos=	*oldpos;

} /* copydown */
0707070001000311771004440000000000010000011576250454650113300001300000036444cdb/main.c static char *sccsid = "$Header: main.c,v 6.5 86/09/18 08:00:12 peter Exp $";

#include <setjmp.h>
#include <signal.h>
#include <ctype.h>
#include <varargs.h>

#include "cdb.h"

/* --- KLUDGES --- */
extern jmp_buf venvFixer;
export int	*venv;
export int	vfFPConv = false;	/* floating point conversion required */
#define NAN	0x80000000

/* --- end KLUDGES --- */


#define chPid	'\\'	/* indicates that exec name is actually a PID */

#if 0
export int2	viprMax; /* actually defined in waitSingle.c OR waitMulti.c */
export FLAGT	vfAttach; /* actually defined in waitSingle.c OR waitMulti.c */
export pCPUR	vcpuHost;

exportdefine dprint(x, y) {if (x <= v->debuglevel) printf y; fflush(stdout);}
exportdefine cbLineMax 1024
exportdefine iwwNil	-1

#endif

export char	vsbOptions[2048];	/* default per process options */
export SBT	vsbDefaultFile = sbNil;
static MODER	amode;
export pMODER	vmode;	/* default mode record */
export char	**venvpParent;
export int1	vcaseMod = 0;	    /* has 0 or 040 for case sensitive search */
export SBT	vsbDebugName;		/* name debuger was invoked by */
export int2	vpidCdb = pidNil;	/* our own process id */
export int	vcActive = 0;		/* number of *active* processes */
export char	vsbPrompt[100];
export ADRT	vadrUser = ADR_USER;	/* address of u. in kernel */
export ADRT	vadrReg0 = ADR_REG0;	/* offset to Register 0 */
export ADRT	vadrUar0 = ADR_U_AR0;	/* offset to u.u_ar0 */
export int	vcsRemote = csNil;	/* comm state of remote */
export FLAGT	vfInWait = false;	/* in XWait on remote process */
export FLAGT	vfInterruptPending = false; /* we have a SIGINT for remote */

export FLAGT	vfWindows = false;	/* use windows instead of tty mode */
export FILE	*vfpWwSrc = stdout;	/* dumb window used for source */
export int	vfnTarget = fnNil;	/* alternate device for target */
export int	viwwTarget = iwwNil;	/* window target is in  */
export int	viwwSrc = iwwNil;	/* window source is displayed in */
export SBT	vsbDevSrc;		/* device for source display */
export int	viwwCmd = iwwNil;	/* window commands are in  */
export SBT	vsbDevWw;		/* device for comm to window manager */

/* the following must remain INT's! */
export int	vlcDefault = lcC;	/* default language code */
export int	vfUseCache = false;	/* use caching for remote comm */
export int	vfCommDebug = false;	/* watch remote comm messages */


/* P R I N T   U S A G E */

local void PrintUsage()
{
MoreOn();
printf("Usage: cdb [options] objectfile\n");
printf("Options are:\n");
printf("    -B N	Baud rate for remote line.\n");
printf("    -C file	Set core file.\n");
printf("    -d dir	Add directory to list to be searched for sources.\n");
printf("    -D		Ignore all currently specified alternate directories.\n");
printf("    -e entry	Specify entry label (default is main).\n");
printf("    -E file	Create top level process from file.\n");
printf("    -f N	Use floating point format conversion N.\n");
printf("    -L (c|f)	Set default language code.\n");
printf("    -m file	Default specification file.\n");
printf("    -p file	Command playback from file.\n");
printf("    -P pid	Debug existing process with given process id.\n");
printf("    -r file	Command recording to file.\n");
printf("    -R file	Output recording to file.\n");
printf("    -S		Perform stty's each time target starts and stops.\n");
printf("    -t device	Device name for remote debug connection.\n");
printf("    -Ttext offset  Offset for all text addresses.\n");
printf("    -Tdata offset  Offset for all data addresses.\n");
printf("    -V		Print debugger version information.\n");
printf("    -W		Use windows interface.\n");
printf("\nDebugging & Internal options (use with caution!):\n");
printf("    -u #	Override compiled in address of \"u.\".\n");
printf("    -U #	Override compiled in offset of \"u_ar0\".\n");
printf("    -wC# dev	Commands in window #, on device dev.\n");
printf("    -wS# dev	Source code in window #, on device dev.\n");
printf("    -wT# dev	Taregt output in window #, on device dev).\n");
printf("    -x level	Set internal debugging printout level.\n");
printf("    -X		Show all remote communications transactions.\n");
printf("    -Z N	Set demo timer to N seconds.\n");
    MoreOff();
    exit(1);
} /* PrintUsage */


/* M A I N */

export void main(argc, argv, envp)
int	argc;
char	*argv[];
char	*envp[];
{
    int		cMainArgs, i, iExec, x;
    FLAGT	fUsedArg, fSingle, fInitComm, fExecWm, fTryGraphics;
    SBT		sbArg, sbTemp;
    char	sbCmd[100], *rgSbExec[100];

    PrintVersion(1);

    venv = venvFixer;
    if (setjmp(venvFixer)) {
	/* in case we hit an error during initialization */
	printf("Cannot continue\n");
	exit(1);
    } /* if */

    /* General Initiialization */

    venvpParent = envp;
    vpidCdb = getpid();
    vsbDebugName = SbFBase(argv[0]);
    vcaseMod = 040; /* start out with case INsensitive searches */
    vfRecord = false;	/* we aren't recording (yet) */
    fTryGraphics = true;

    /* do NOT reverse the order of these init's! */
    InitSe();		/* init special default SE's for expression eval */
    InitCpu(vcpuHost);	/* init global cpu record */
    InitSpecials();	/* init system specials (_FILE, _LINE, etc.) */
    InitProcessTable();

    /* setup the default display record */
    vmode = &amode;
    vmode->cnt = 1;
    vmode->len = vcpuHost->cbInt; /* kludge? */
    vmode->df = dfDecimal;
    vmode->imap = 0;

    /* set default lc based on first character of program name */
    sbTemp = strrchr(vsbDebugName, '/');
    if (sbTemp == sbNil)
	sbTemp = vsbDebugName;
    else
	sbTemp++;	/* increment past '/' */

    switch (*sbTemp) {
	case 'x':
	    AddOptions(vsbOptions, "-x 100" , "-X", "-t TEST", sbNil);
	    /* and fall through */

	default:
	case 'c':
	    vlcDefault = lcC;
	    break;

	case 'f':
	    vlcDefault = lcFortran;
	    AddOptions(vsbOptions, "-e MAIN", sbNil);
	    break;
    } /* switch */

    iExec = 0;
    cMainArgs = 0;
    for (i = 1; i < argc; i++) {
	sbArg = argv[i];
	if (*sbArg != '-') {
	    if (*sbArg == '?')
		PrintUsage();

	    switch (cMainArgs) {
		default:
		    if (viprMax > 1)
			PrintUsage();
		    /* fall through */

		case 1:
		    if (viprMax > 1) {
			AddOptions(vsbOptions, "-C", sbArg, sbNil);
			break;
		    } /* if */
		    /* fall through */

		case 0:
		    rgSbExec[iExec++] = sbArg;
		    break;
	    } /* switch */
	    cMainArgs++;

	} else {

	    while (*++sbArg != chNull) {   /* move off '-' or last switch */
		/* point to a potential argument */
		sbTemp = (sbArg[1] != chNull) ? sbArg+1 : argv[i+1];
		fUsedArg = true; /* set FALSE if option does NOT use arg */

		switch (*sbArg) {
		    /* first we do options that are not the generic case */
		    default:
			PrintUsage();

		    case '.':
			Purchase(sbArg+1);
			exit(0);

		    case 'A':
			UError("You may not use 'A' on the command line.");
			break;

		    case 'E':
			rgSbExec[iExec++] = sbTemp;
			break;

		    case 'm':
			vsbDefaultFile = sbTemp;
			break;

		    case 'P':	/* Process id */
			sbCmd[0] = chPid;
			sbCmd[1] = chNull;
			strcat(sbCmd, sbTemp);
			rgSbExec[iExec++] = SbFAlloc(sbCmd);
			break;

		    case 'p':	/* playback file */
			SetPlayback(sbTemp, true, fSingle);
			break;

		    case 'R':	/* output record file */
			SetOutput(sbTemp);
			break;

		    case 'r':	/* command record file */
			SetRecord(sbTemp);
			break;

		    case 'T':
			AddOptions(vsbOptions, sbArg, argv[i+1], sbNil);
			sbArg[1] = chNull;	/* pretend arg was one letter */
			break;

		    case 'w':
			fTryGraphics = false;
			x = atoi(sbArg+2);
			vfWindows = true;
			switch (sbArg[1]) {
			    default:	PrintUsage();

			    case 'C':
				viwwCmd = x;
				vsbDevWw = argv[i+1];
				break;
			    case 'S':
				viwwSrc = x;
				vsbDevSrc = argv[i+1];
				break;
			    case 'T':
				viwwTarget = x;
				if ((vfnTarget =
					open(argv[i+1], O_RDWR, 0666)) < 0)
				    UError("Trouble opening %s: %s.",
					    argv[i+1], SbFError(errno));
			} /* switch */
			sbArg[1] = chNull;
			break;

		    case 'V':
			fUsedArg = false;
			PrintVersion();
			exit(0);
			break;

		    case 'W':
			fUsedArg = false;
			vfWindows = true;
			fExecWm = true;
			break;

#if (CPU == PDN)
		    case 'z':
			fUsedArg = false;
			vfPdnExtStart = !vfPdnExtStart;
			break;
#endif /* (CPU == PDN) */

		    case 'Z':	/* Have demo move forward in X second steps */
			vfComment = true;
			fSingle = true;
			SetDemoTimer(atoi(sbTemp));
			break;

	    /* --------- Generic option handling --------------- */

		    /* Generic options with no argument go here */
		    case 'X':	/* debug remote comm */
		    case 'S':	/* Use stty calls on stop/start of child */
			fUsedArg = false;
			sbTemp = sbNil;

			/* and fall through */

		    /* Generic options with 1 argument go here */
		    case 'B':	/* baud rate */
		    case 'C':	/* core file */
		    case 'd':	/* alternate directory */
		    case 'e':	/* alternate entry point */
		    case 't':	/* name of device for remote cdb */
		    case 'u':	/* set address of u. */
		    case 'U':	/* set offset of u.u_ar0 */
		    case 'x':	/* set dprint level */
			sbCmd[0] = '-';
			sbCmd[1] = *sbArg;
			sbCmd[2] = chNull;
			AddOptions(vsbOptions, sbCmd, sbTemp, sbNil);
			break;

		} /* switch */

		if (fUsedArg) {
		    if (sbArg[1] == chNull)
			i++;	/* eat next word - it was the arg we used */
		    break;	/* and fall out of the loop */
		} /* if */
	    } /* while there are more switches in this bunch */
	} /* if it starts with a - */
    } /* for all command line arguments */

    Validate();		/* perform validation */

    if (iExec == 0) {
	/* come on.... ya gotta give us something! */
	printf("Program to debug (<return> to see switches): ");
	sbCmd[0] = chNull;
	gets(sbCmd);
	if (sbCmd[0] == chNull) {
	    printf("\nYou need to supply a program name.\n\n");
	    PrintUsage();
	} /* if */
	rgSbExec[iExec++] = SbFAlloc(sbCmd);
    } /* if */

    /* Create the top level processes */
    for (i = 0; i < iExec; i++) {
	sbArg = rgSbExec[i];
	if (*sbArg == chPid)
	    PrFAttachProcess(atoi(sbArg+1));
	else
	    PrFInitPr(sbArg);
    } /* for */
    v = vrgPr[0];	/* we start off with first program they mentioned */

    if (vfWindows)
	InitAllWw(fExecWm, fTryGraphics, argv);

    if (setjmp(venvFixer) == 0) {
	/* first time */
	if ((v->fnCore != fnNil) OR (v->pid != pidNil)) {
	    FDoCommand("L", true);	/* put them at the 'stop' location */
	} else {
	    sprintf(sbCmd, "e %s", v->sbInit); /* first line to execute */
	    FDoCommand(sbCmd, true);
	    v->acntx.pc = v->adrInit;
	} /* if */
    } /* if */

    venv = venvFixer;
    InitSignals();	/* don't dump on the customers! */
    vcNest = 0; 	/* nesting level for printing structure indents */
    vfAnalyzeStop = false;
    ClearMore();	/* Reset the state of psuedo-more */
    ClearCol();		/* Reset the state of column counting */

    DebugIt(true);

    CdbExit(0);
} /* main */


/* S A V E   A L L */

export void SaveAll()
{
    char	sbFile[100];
    FLAGT	fNeedFile;
    FILE	*fp;

    sprintf(sbFile, "%s.rc", v->sbExec);
    fp = fopen(sbFile, "w");
    if (fp == NULL) {
	printf("Cannot open save file.\n%s: %s\n", sbFile, SbFError(errno));
	return;
    } /* if */

    fNeedFile = FSaveBp(fp);
    fNeedFile |= FSaveAssertions(fp);

    fclose(fp);
    if (!fNeedFile)
	unlink(sbFile);	/* nothing was writtne out */
} /* SaveAll */


/* C D B   E X I T */

export void CdbExit(value)
int	value;
{
#if (OP_SYS == SYSV)
#include <fcntl.h>

    if (fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY) == -1)
	SysPanic("fcntl on ~O_NDELAY");
    sleep(1); /* to disturb the ether and make O_NDELAY go away */
#endif (OP_SYS == SYSV)

    if (setjmp(venvFixer) != 0) {
	/* we failed during shutdown - Bailout! */
	exit(value);
    } /* if */

    ReapChildren();

    CloseComm();
    if (vfWindows)
	RestoreAllWw();
    exit(value);
} /* CdbExit */


/* L O N G   F   S B */

export int4 LongFSb(sb)
SBT	sb;
{
    int		tk;
    char	sbTok[100];

    vcbTok = sizeof(sbTok);
    tk = TkFStr(&sb, sbTok, &vcbTok, true);
    if (tk != tkNumber)
	return(NAN);
    return(yylval.val.valLong);
} /* LongFSb */


/* A D D   O P T I O N S */

/* VARARGS2 */
export void AddOptions(sbOption, va_alist)
SBT	sbOption;
va_dcl
{
    va_list	ap;
    SBT		sb;

    va_start(ap);

    while ((sb = va_arg(ap, SBT)) != sbNil) {
	strcat(sbOption, sb);
	strcat(sbOption, " ");
    } /* while */

    va_end(ap);
} /* AddOptions */


/* A P P L Y   O P T I O N S */

export void ApplyOptions(pr, sbOptions)
pPRR	pr;
SBT	sbOptions;
{
    int		i, argc;
    FLAGT	fUsedArg;
    SBT		sbArg, sbOpt;
    char	*argv[100];

    DoArgs(pr->sbExec, sbOptions, argv, false);
    for (argc = 0; argv[argc] != sbNil; argc++)
	;

    fUsedArg = true;
    for (i = 1; i < argc; i++) {
	sbOpt = argv[i];
	if (*sbOpt != '-') {
	    /* can this happen ????? - for now we will ignore it */
	} else {
	    while (*++sbOpt != chNull) {   /* move off '-' or last switch */
		/* point to a potential argument */
		sbArg = (sbOpt[1] != chNull) ? sbOpt+1 : argv[i+1];
		fUsedArg = true; /* set FALSE if option does NOT use arg */

		switch (*sbOpt) {
		    default:
			printf("ApplyOptions: Unkown option \"%c\"\n");
			fUsedArg = false;
			break;

		    case 'A': /* */
			pr->iBaud = atoi(sbArg);
			fUsedArg = false;
			break;

		    case 'B': /* baud rate */
			pr->iBaud = atoi(sbArg);
			break;

		    case 'C':	/* name of core file  */
			pr->sbCore = SbFAlloc(sbArg);
			break;

		    case 'D':	/* thow out alternate directories */
			pr->idirMac = 0;
			fUsedArg = false;
			break;

		    case 'd':	/* alternate directory */
			AddDir(pr, sbArg);
			break;

		    case 'E':	/* REAL name of executable */
			pr->sbExec = SbFAlloc(sbArg);
			break;

		    case 'e':	/* entry point */
			pr->sbInit = SbFAlloc(sbArg);
			pr->adrInit = adrNil;
			break;

		    case 'f':	/* floating point format conversion */
			/* KLUDGE */
			vfFPConv = true;		/* convert for target */
			fUsedArg = false;
			break;

		    case 'L':	/* Language code */
			pr->lc = (*sbArg == 'f') ? lcFortran : lcC;
			break;

		    case 'P':
		printf("You may not specify 'P pid' in the defaults file\n");
			break;

		    case 'S':	/* Toggle stty calls on child start/stop */
			pr->fStty = ! pr->fStty;
			fUsedArg = false;
			break;

		    case 't':	/* name of device for remote cdb */
			pr->sbComm = sbArg;
			pr->fStty = false;	/* no piont in doing this */
			break;

		    case 'T':
			if ( strcmp( "Ttext", sbArg) == 0 ){	/* text adrs */
			    sbOpt[1] = chNull;
			    if ((pr->adrText = LongFSb(sbArg) == NAN))
			     printf("Ttext requires a number as an argument\n");
			    break;
			} else if ( strcmp( "Tdata", sbArg) == 0 ){
			    sbOpt[1] = chNull;
			    if ((pr->adrData = LongFSb(sbArg) == NAN))
			     printf("Tdata requires a number as an argument\n");
			    break;
			} /* if */
			break;

		    case 'u':	/* set address of u. */
			vadrUser = LongFSb(sbArg);
			if ((vadrUser = LongFSb(sbArg) == NAN))
			    printf("Tdata requires a number as an argument\n");
			break;

		    case 'U':	/* set offset of u.u_ar0 */
			if ((vadrUar0 = LongFSb(sbArg) == NAN))
			    printf("Tdata requires a number as an argument\n");
			break;

		    case 'x':	/* set dprint level */
			pr->debuglevel = atoi(sbArg);
			break;

		    case 'X':
			pr->fCommDebug = true;
			fUsedArg = false;
			break;
		} /* switch */

		if (fUsedArg) {
		    if (sbOpt[1] == chNull)
			i++;	/* eat next word - it was the arg we used */
		    break;	/* and fall out of the loop */
		} /* if */
	    } /* while */
	} /* if */
    } /* for */
    if (pr->sbInit == sbNil)
	pr->sbInit = SbFAlloc("main");
} /* ApplyOptions */
0707070001000312001004440000000000010000011600140454650113300002000000007106cdb/procedure.c /* $Header: procedure.c,v 6.2 86/09/14 20:23:51 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"

#include <setjmp.h>


/* C A R G   F   I P D */

export int CargFIpd(ipd)
int2	ipd;
{
    int2	carg = 0;
    int4	isym;

    if (v->rgPd[ipd].iline == 0)
	return(0);

    isym = v->rgPd[ipd].isym + 1;
    while (FNextLocal(false, true, isym)) {
	carg++;
	isym = v->isym + 1;	/* point one past current sym */
    } /* if */
    return(carg);
} /* CargFIpd */


/* D O   P R O C */

export void DoProc(seRet, seProc, seFirst, seMac)
pSER	seRet, seProc, seFirst, seMac;
{
    int2	ipd, cbArg, cArg, x, sigSave;
    pBPR	bp;
    ADRT	adr, adrSave;
    char	sbCmdSave[300];
    char	*sbSaveState;
    int		*envSave;
    jmp_buf	envProc;

    if (v->adrCall == adrNil)
	UError("You must load with \"-lcdb\" to invoke procedure calls.");

    if (v->pid == pidNil)
	UError("No child process.");

#if (CPU == I80386)
    UError("Kernel bug prevents procedure calls for the moment.");
#endif
#if (MFG == PYRAMID)
    UError("Procedure calls are not yet implemented on Pyramid machines.");
#endif /* (MFG == PYRAMID) */

    /* save register values and prepare for errors */
    if ((x = setjmp(envProc)) == 0) {
	envSave = venv;
	sigSave = v->sig;
	venv = envProc;
	sbSaveState = SaveState();
    } else {
	if (x != 2)
	    goto keepgoing;	/* They did NOT hit a ^C */
	/* error city, wonder what went wrong??? */
	if (v->pid != pidNil)
	    RestoreState(sbSaveState);
	v->sig = sigSave;
	venv = envSave;
	if (--v->cNestProc == 0)
	    ClearBp(BpFAdr(v->adrBreak, true));
	UError("Exiting procedure call state.");
    } /* if */

    adrSave = AdrFIpdIln(v->ipd, v->iln);
    adr = seProc->asym.value;

    /* see if they did a reasonable call */
    ipd = IpdFAdr(adr);
    cArg = seMac - seFirst;
    if (cArg < CargFIpd(ipd)) {
	printf("WARNING: Too few parameters!\n");
	PxProc(ipd, true, true);
	fflush();
    } /* if */

    CallProcedure(adr, seFirst, cArg);	/* CPU specific */

    if (v->cNestProc == 0)
	bp = BpFAddBp(v->adrBreak, 1, "Q", 3);  /* and set a break there */
    v->cNestProc++;	/* count of proc call nesting */

    strcpy(sbCmdSave, v->sbCmd); /* so it doesn't get clobbered by proc call */
    SetCmd(sbNil);

    /* and away we go........ */
    RunProcess(ptResume, psRunning, true);

keepgoing:
    while ((v->bp == bpNil) OR (v->adrBreak != v->bp->adr))
	DebugIt(false);

    if (--v->cNestProc == 0)
	ClearBp(bp);

    SeFReturn(seRet, seProc);	/* CPU specific */

    RestoreState(sbSaveState);	/* this un-does the stack fiddling */
    v->sig = sigSave;
    venv = envSave;	/* return to normal error handling */
    strcpy(v->sbSave, sbCmdSave);	/* restore command line */
    SetCmd(v->sbSave);
    SetViewPosition(adrSave);
} /* DoProc */


/* F   C A L L   U S E R   P R O C */

export FLAGT FCallUserProc(sbProc, cArg, arg1)
SBT	sbProc;
int2	cArg;
int4	arg1;
{
#define cArgMax	20
    int2	i, ipd;
    int4	*parg;
    SER		*se, rgSe[cArgMax], aseProc, aseRet;


#if (MFG == PYRAMID) || (CPU == I80386)
    return(false);
#endif /* (MFG == PYRAMID) */

    ipd = IpdFName(sbProc);
    if (ipd == ipdNil)
	return(false);	/* nope! */

    if (cArg > cArgMax)
	UError("No more than %d arguments when calling from the debugger.",
			cArgMax);

    /* turn args into SE's */
    for (i = 0, parg = &arg1, se = rgSe; i < cArg; i++, se++, parg++) {
	*se = *vseCnInt;
	se->val.valInt = *parg;
    } /* for */

    SeFSym(&aseProc, SymFIsym(v->rgPd[ipd].isym), true); /* get proc goodies */
    DoProc(&aseRet, &aseProc, rgSe, rgSe + cArg);
    return(true);
} /* FCallUserProc */
0707070001000312011004440000000000010000011600500454650113300001600000006125cdb/cdbdemo.c /* This program is used to test and to demonstrate the features of CDB.
 * It tries to have a "little of everything", so it doesn't make much sense.
 */

#include <stdio.h>

typedef union {
	struct { int s11; } s1;
	struct { int s21, s22; } s2;
	struct { int s31, s32, s33; } s3;
	} U1U, *pU1U;
U1U	a_union;

struct foo {
	struct foo *fooNext;
	struct bar *pbar;	/* deliberately points at undefined struct */
	} afoo;

typedef enum COLOR {red, orange, yellow, green=10, blue, purple} COLORE;

struct RECS {
	short	a;
	char	b[9];
	long	c;
	unsigned bits1 : 1;
	unsigned bits2 : 2;
	unsigned bits3 : 3;
	unsigned bits4 : 4;
	COLORE	color;
	int	(*prtn)();
	};

extern int AddArgs();
extern int main();
extern int First();
extern char * Second();
extern int Third();

struct RECS a_record = {-1, "Apple Pi", 987654321L, 1, 2, 4, 8, purple,AddArgs};

struct RECS record_array[] = {
	{0, "First",	 0L, 0, 0, 0, 0, red, First},
	{1, "Second",	-1L, 1, 1, 1, 1, orange, AddArgs},
	{2, "Third",	-2L, 1, 2, 2, 2, yellow, Third},
	{3, "Fourth",	-3L, 1, 3, 3, 3, green, main},
	{4, "Fifth",	-4L, 1, 1, 4, 4, blue, AddArgs},
	{5, "Sixth",	-5L, 1, 2, 5, 5, purple, First},
	};

char	*string_array[5] = { "0", "1", "2", "3", "4" };
char	char_array[2][5]= {	00, 01, 02, 03, 04,
			10, 11, 12, 13, 14,
			};
int	int_array[4][7]= {	00, 01, 02, 03, 04, 05, 06,
			10, 11, 12, 13, 14, 15, 16,
			20, 21, 22, 23, 24, 25, 26,
			30, 31, 32, 33, 34, 35, 36
			};
int	loop;


/* M A I N */

main(argc, argv)
int	argc;
char	*argv[];
{
    char	*string_array[3];

    string_array[0] = "a";
    string_array[1] = "b";
    string_array[2] = "c";

    while (*argv)
	printf("%s\n",*(argv++));

    for (loop=1; loop != 0; loop++) {
	First(loop, loop, loop);
    } /* for */

    printf("done\n");
    exit(0);
} /* main */


/* S E C O N D */

char * Second(aaa, bbb, ccc)
register char	aaa;
register short ccc;
int	bbb;
{
    long	x;

    x = aaa + bbb + ccc;
    Third(aaa, -1, "A good message");
    return((char *) 0);
} /* Second */


/* T H I R D */

Third(select, random, message)
register long	 select;
register int	random;
char	*message;
{
    float	fl;
    double	xfl;
    static struct RECS *precord;

    precord = &a_record;
    xfl = fl = 5.8;

    if (select != 0) {
	int random;

	random = -9;
	switch (select % 7) {
	    case 1:	printf("1\n");	break;
	    case 2:	printf("2\n");	break;
	    case 3:	printf("3\n");	break;
	    case 4:	printf("4\n");	break;
	    default:	printf("default\n");	break;
	} /* switch */
    } /* if */

    printf("%s\n", message);
} /* Third */


/* F I R S T */

First(i, j, k)
int	i;
char	j;
short	k;
{
    Second(i, j+1, k+2);
} /* First */


/* A D D   A R G S */

static int AddArgs(i, d)
int	i, d;
{
    int		value;

    value = i + d;
    Second(i, i+1, i+2);
    return(value);
} /* AddArgs */


/* _ R E C S */

static _RECS(rec, x)
struct RECS *rec;
int	x;
{
    if (x != -1)
	fprintf(stderr, "x == %d\n", x);
    fprintf(stderr,"a = %d, b = %s, c = %d\n", rec->a, rec->b, rec->c);
    fprintf(stderr,"bits = %d %d %d %d, color = %d",
	rec->bits1, rec->bits2, rec->bits3, rec->bits4, rec->color);
    fflush(stderr);
} /* _RECS */
0707070001000312021004440000000000010000011574550454650113300001500000044507cdb/cpulib.c /* $Header: cpulib.c,v 6.4 86/09/14 20:23:31 peter Exp $ */
/* (C) Copyright 1985 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"

#include <sys/param.h>

#if (OP_SYS == SYSV)
#include <signal.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#define cbUserPage (ctob(USIZE))
#endif

#if (MFG == SIEMENS)
#include <sys/types.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/vtimes.h>
#endif /* (MFG == SIEMENS) */

#include <sys/dir.h>
#include <sys/user.h>

#if (OP_SYS == BSD42)
#define cbUserPage (NBPG*UPAGES)
#endif /* (OP_SYS == BSD42) */

export uint4 vcbUserPage = cbUserPage;

typedef union {
	long	lng;
	struct { short	shortHi, shortLo; } shorts;
	struct { char	chHiHi, chHiLo, chLoHi, chLoLo; } chars;
	} SELECTU;



#ifndef X_ListRegisters
/* L I S T   R E G I S T E R S */

export void ListRegisters(sbRegs)
SBT	sbRegs;
{
    int		i;
    pSER	se;
    MODER	amode;

    vmode->cnt = 1;
    vmode->df = dfNil;
    vmode->len = -1;
    GetMode(vmode);
    if (vmode->df == dfNil)
	amode = *vmode;

    if ((v->pid == pidNil) AND (v->fnCore == fnNil))
	UError("No process.");

    ColOn();
    se = v->cpu->rgReg;
    for (i = 0; i < v->cpu->iregMax; i++, se++) {
	if ( (sbRegs != sbNil)
	      AND (!FHdrCmp(sbRegs, SbFIss(se->asym.iss))) ) 
	    continue;	/* not interesting */
	PadTo((i%4) * 20);
	DisplaySe(se, vmode, true, true, true);
	if (amode.df == dfNil)
	    *vmode = amode;
	if (i%4 == 3)
	    printf("\n");
    } /* for */
    if (i%4 != 0)
	printf("\n");
    ColOff();
} /* ListRegisters */
#endif /* X_ListRegisters */


#ifndef X_GetByte
/* G E T   B Y T E */

export uint1 GetByte(adr, space)
ADRT	adr;
int2	space;
{
    SELECTU	select;
    ADRT        adrOnWord;

    adrOnWord = adr & ~v->cpu->alignment;
    select.lng = Access(accRead, adrOnWord, space, 0);

    if (v->cpu->byteSex == vcpuHost->byteSex) {
	switch (adr & v->cpu->alignment) {
	    case 0:	return(select.chars.chHiHi);
	    case 1:	return(select.chars.chHiLo);
	    case 2:	return(select.chars.chLoHi);
	    case 3:	return(select.chars.chLoLo);
	} /* switch */
    } else {
	switch (adr & v->cpu->alignment) {
	    case 0:	return(select.chars.chLoLo);
	    case 1:	return(select.chars.chLoHi);
	    case 2:	return(select.chars.chHiLo);
	    case 3:	return(select.chars.chHiHi);
	} /* switch */
    } /* if */
} /* GetByte */
#endif /* X_GetByte */


#ifndef X_PutByte
/* P U T   B Y T E */

export void PutByte(adr, space, val)
ADRT    adr;
int2    space;
uint1	val;
{
    SELECTU	select;
    ADRT	adrOnWord;

    adrOnWord = adr & ~v->cpu->alignment;
    select.lng = Access(accRead, adrOnWord, space, 0);

    if (v->cpu->byteSex == vcpuHost->byteSex) {
	switch (adr & v->cpu->alignment) {
	    case 0:	select.chars.chHiHi = val; break;
	    case 1:	select.chars.chHiLo = val; break;
	    case 2:	select.chars.chLoHi = val; break;
	    case 3:	select.chars.chLoLo = val; break;
	} /* switch */
    } else {
	switch (adr & v->cpu->alignment) {
	    case 0:	select.chars.chLoLo = val; break;
	    case 1:	select.chars.chLoHi = val; break;
	    case 2:	select.chars.chHiLo = val; break;
	    case 3:	select.chars.chHiHi = val; break;
	} /* switch */
    } /* if */

    Access(accWrite, adrOnWord, space, select.lng);
} /* PutByte */
#endif /* X_PutByte */


#ifndef X_GetBlock
/* G E T   B L O C K */

export void GetBlock(adrSrc, space, adrDest, cb)
FAST ADRT	adrSrc, adrDest;
int2	space, cb;
{
    int2	*pShort;
    int4	*pLong;
    char        *pCh;
    ADRT	adrSave = adrDest;
    SELECTU	select;

    if (((adrSrc ^ adrDest) & v->cpu->alignment) == 0) {
	/* addresses are in sync RE alignment */

	while (adrSrc & v->cpu->alignment) {
	    /* they're off alignment - move both to next boundary */
	    pCh = (char *) adrDest;	/* point to receiving area */
	    *pCh = GetByte(adrSrc++, space);
	    adrDest++;
	} /* while */

	if (cb == 2) {
	    /* special check for shorts */
	    select.lng = GetWord(adrSrc, space);
	    pShort = (int2 *) adrDest;
	    if (v->cpu->byteSex == vcpuHost->byteSex)
		*pShort = select.shorts.shortHi;
	    else
		*pShort = select.shorts.shortLo;
	    return;
	} /* if */

	pLong = (int4 *) adrDest;	/* point to receiving area */
	while (cb >= v->cpu->cbInt) {
	    *pLong++ = GetWord(adrSrc, space);
	    adrSrc += v->cpu->cbInt;
	    cb -= v->cpu->cbInt;
	} /* while */
	adrDest = (ADRT) pLong;
    } /* if */

    /* This last loop handles odd bytes OR blocks which were
     * not in sync RE alignment.
     */
    pCh = (char *) adrDest;	/* point to receiving area */
    while (cb--)
	*pCh++ = GetByte(adrSrc++, space);
} /* GetBlock */
#endif /* X_GetBlock */


#ifndef X_PutBlock
/* P U T   B L O C K */

export void PutBlock(adrDest, space, adrSrc, cb)
ADRT    adrDest, adrSrc;
int2	space, cb;
{
    int2	*pShort;
    int		*pLong;
    char        *pCh;
    SELECTU	select;

    if (((adrSrc ^ adrDest) & v->cpu->alignment) == 0) {

	/* addresses are in sync RE alignment */
	while (adrSrc & v->cpu->alignment) {
	    /* they're off alignment - move both to next boundary */
	    pCh = (char *) adrDest;	/* point to receiving area */
	    *pCh = GetByte(adrSrc++, space);
	    adrDest++;
	} /* while */

	if (cb == 2) {
	    /* special check for shorts */
	    pShort = (short *) adrSrc;
	    select.lng = GetWord(adrDest, space);
	    if (v->cpu->byteSex == vcpuHost->byteSex)
		select.shorts.shortHi = *pShort;
	    else
		select.shorts.shortLo = *pShort;
	    PutWord(adrDest, space, select.lng);
	    return;
	} /* if */

	pLong = (int4 *) adrSrc;	/* point to receiving area */
	while (cb >= v->cpu->cbInt) {
	    PutWord(adrDest, space, *pLong++);
	    adrDest += v->cpu->cbInt;
	    cb -= v->cpu->cbInt;
	} /* while */
	adrSrc = (ADRT) pLong;
    } /* if */

    /* This last loop handles odd bytes OR blocks which were
     * not in sync RE alignment.
     */
    pCh = (char *) adrSrc;	/* point to receiving area */
    while (cb--)
	PutByte(adrDest++, space, *pCh++);
} /* PutBlock */
#endif /* X_PutBlock */


#ifndef X_AdrFReg
/* A D R   F   R E G */

export ADRT AdrFReg(reg)
int	reg;
{
    if (vrgOffset[reg] == NAR)
	return(adrNil);

    if (v->os->adrReg0 == 0) {
	return(reg);
    } else {
	if (vrgOffset[reg] == NAR)
	    return(adrNil);
	if (v->os->adrReg0 == adrNil)
	    return(vrgOffset[reg]);
	else
	   return((ADRT)(v->os->adrReg0 + v->cpu->cbRegister * vrgOffset[reg]));
    } /* if */
} /* AdrFReg */
#endif /* X_AdrFReg */


#ifndef X_GetReg
/* G E T   R E G  */

export REGT GetReg(reg)
int2	reg;
{
    if ((reg == upc) AND (v->acntx.pc != adrNil))
	return(v->acntx.pc);	/* this is valid */
    else
	return(GetUser(AdrFReg(reg)));
} /* GetReg */
#endif /* X_GetReg */


#ifndef X_PutReg
/* P U T   R E G  */

export void PutReg(reg, val)
int2	reg;
REGT	val;
{
    ADRT	adr;

    adr = AdrFReg(reg);
    if (adr == adrNil)
	return;

    /* keep our globals up to date */
    switch (reg) {
	case upc:	v->acntx.pc = val;
			/* PC is set at continuation time, not here */
			return;

	case ufp:	v->acntx.fp = val;
			if (v->cpu->fApIsFp)
			    v->acntx.ap = val;
			break;
	case usp:	v->acntx.sp = val;	break;
	case uap:	v->acntx.ap = val;
			if (v->cpu->fApIsFp)
			    v->acntx.fp = val;
			break;
    } /* switch */

    PutUser(AdrFReg(reg), val);
} /* PutReg */
#endif /* X_PutReg */


#ifndef X_ReadPc
/* R E A D   P C */

export void ReadPc()
{
#if 0
    if (v->os->adrUser != adrNil) {
	if (v->os->adrReg0 != 0)
	    v->os->adrReg0 = GetUser(v->os->adr_u_ar0) - v->os->adrUser;
    } else {
	v->os->adrReg0 = GetUser(v->os->adr_u_ar0) & (vcbUserPage-1);
    } /* if */
#endif

    if (v->os->adr_u_ar0 != 0) {
	if (v->os->adrUser != adrNil)
	    v->os->adrReg0 = GetUser(v->os->adr_u_ar0) - v->os->adrUser;
	else
	    v->os->adrReg0 = GetUser(v->os->adr_u_ar0) & (vcbUserPage-1);
    } /* if */

    v->acntx.pc = adrNil;	/* to force re-reading of pc */
    v->acntx.pc = GetReg(upc);
} /* ReadPc */
#endif /* X_ReadPc */


#ifndef X_SetCntx
/* S E T   C N T X */

export void SetCntx()
{
    v->acntx.fp = GetReg(ufp);
    v->acntx.sp = GetReg(usp);
    if (v->cpu->fApIsFp)
	v->acntx.ap = v->acntx.fp;
    else
	v->acntx.ap = GetReg(uap);
    v->acntx.fEndOfStack = false;
} /* SetCntx */
#endif /* X_SetCntx */


#ifndef X_SaveState
/* S A V E   S T A T E */

export SBT SaveState()
{
    int2	i;
    SBT		sbSave;
    REGT	*rgReg;

    /* Save all of the registers for the current process */

    sbSave = (SBT) malloc(uregMax * v->cpu->cbRegister);
    rgReg = (REGT *) sbSave;

    for (i = 0; i < uregMax; i++) {
	if ( (i == uap) AND (v->cpu->fApIsFp) )
	    continue;
	rgReg[i] = GetReg(i);
    }   /* for */
    if (v->cpu->fApIsFp)
	rgReg[uap] = rgReg[ufp];

    return(sbSave);
} /* SaveState */
#endif /* X_SaveState */


#ifndef X_RestoreState
/* R E S T O R E   R E G S */

export void RestoreState(sbSave)
SBT	sbSave;
{
    int2	i;
    REGT	*rgReg;

    /* Restore all of the registers for the current process */

    rgReg = (REGT *) sbSave;
    for (i = 0; i< uregMax; i++) {
	if ((i == uap) AND (v->cpu->fApIsFp))
	    continue;
	PutReg(i, rgReg[i]);
    } /* for */

    v->acntx.pc = rgReg[upc];
    v->acntx.fp = rgReg[ufp];
    v->acntx.sp = rgReg[usp];
    v->acntx.ap = rgReg[uap];
    free(sbSave);
} /* RestoreState */
#endif /* X_RestoreState */


#ifndef X_MoveBytes
/* M O V E   B Y T E S */

export void MoveBytes(adrDest, adrSrc, cb)
ADRT	adrDest, adrSrc;
FAST int2	cb;
{
    FAST SBT	sb1, sb2;

    sb1 = (SBT)adrSrc;
    sb2 = (SBT)adrDest;
    while (cb--)
	*sb2++ = *sb1++;
} /* MoveBytes */
#endif /* X_MoveBytes */


#ifndef X_ValFReg
/* V A L   F   R E G */

export VALU ValFReg(se, cb)
pSER	se;
int2	cb;
{
    uint4	along;
    VALU	val;

    along = GetReg((int) se->asym.value);

    if (cb == v->cpu->cbChar) {
	val.valUChar = along & 0xff;
    } else if (cb == v->cpu->cbShort) {
	val.valUShort = along & 0xffff;
    } else if (cb == v->cpu->cbLong) {
	val.valULong = along;
    } else if (cb == v->cpu->cbDouble) {
	union { struct{ uint4 long1, long2;} longs; double adouble;}doublestuff;
	if (v->cpu->byteSex == byteSexBig) {
	    doublestuff.longs.long1 = along;
	    doublestuff.longs.long2 = GetReg((int) se->asym.value + 1);
	} else {
	    doublestuff.longs.long2 = along;
	    doublestuff.longs.long1 = GetReg((int) se->asym.value + 1);
	} /* if */
	val.valDouble = doublestuff.adouble;
    } else {
	/* I wonder what it is????? */
	val.valULong = along;
    } /* if */
    return(val);
} /* ValFReg */
#endif /* X_ValFReg */


#ifndef X_StoreReg
/* S T O R E   R E G */

export void StoreReg(seDest, seSrc)
pSER	seDest, seSrc;
{
    int2	cb = CbFSe(seDest);
    uint4	along;
    ADRT	adr = seDest->asym.value;

    along = seSrc->val.valLong;		/* KLUDGE!???? */
    if (cb == v->cpu->cbShort) {
	PutReg((int)adr, along & 0x000000ff);
    } else if (cb == v->cpu->cbShort) {
	PutReg((int)adr, along & 0x0000ffff);
    } else {
	PutReg((int)adr, along);
    } /* if */
} /* StoreReg */
#endif /* X_StoreReg */


#ifndef X_ValFUser
/* V A L   F   U S E R */

export VALU ValFUser(se)
pSER	se;
{
    uint4	along;
    VALU	val;
    int2	cb;

    cb  = CbFSe(se);
    along = GetUser((int) se->asym.value);
    if (cb == v->cpu->cbChar) {
	val.valUChar = along;
    } else if (cb == v->cpu->cbShort) {
	val.valUShort = along;
    } else {
	val.valULong = along;
    } /* if */
    return(val);
} /* ValFUser */
#endif /* X_ValFUser */


#ifndef X_StoreUser
/* S T O R E   U S E R */

export void StoreUser(seDest, seSrc)
pSER	seDest, seSrc;
{
    int2	cb = CbFSe(seDest);
    uint4	along;
    ADRT	adr = seDest->asym.value;

    along = seSrc->val.valLong;		/* KLUDGE!???? */
    if (cb == v->cpu->cbChar) {
	PutUser((int)adr, along & 0x000000ff);
    } else if (cb == v->cpu->cbShort) {
	PutUser((int)adr, along & 0x0000ffff);
    } else {
	PutUser((int)adr, along);
    } /* if */
} /* StoreUser */
#endif /* X_StoreUser */


#ifndef X_InstallBp
/* I N S T A L L   B P */

export void InstallBp(bp)
pBPR	bp;
{
    uint2	value;

    if (bp->inst != 0)
	Panic("Double set of breakpoint.");

    GetBlock(bp->adr, spaceText, (ADRT)&bp->inst, v->cpu->cbBp);
    PutBlock(bp->adr, spaceText, (ADRT)&v->cpu->instBp, v->cpu->cbBp);
} /* InstallBp */
#endif /* X_InstallBp */


#ifndef X_RemoveBp
/* R E M O V E   B P */

export void RemoveBp(bp)
pBPR	bp;
{
    uint4	value = bp->inst;

    if ((v->pid != pidNil) AND (value != 0))
	PutBlock(bp->adr, spaceText, (ADRT)&bp->inst, v->cpu->cbBp);
    bp->inst = 0;
} /* RemoveBp */
#endif /* X_RemoveBp */


#ifndef X_SavePcFp
/* S A V E   P C   F P */

export void SavePcFp()
{
    v->acntx.sp -= v->cpu->cbPointer;
    PutWord(v->acntx.sp, spaceData, v->acntx.pc + v->adrText);
    v->acntx.sp -= v->cpu->cbPointer;
    PutWord(v->acntx.sp, spaceData, v->acntx.fp);
} /* SavePcFp */
#endif /* X_SavePcFp */


#ifndef X_SetCallProc
/* S E T   C A L L   P R O C */

export void SetCallProc(adr, sp, cArg)
ADRT	adr, sp;
int2	cArg;
{
    /* Given the callee's address, the current SP and count of arguments,
     * do whatever is necessary so that we can 'continue' into a
     * procedure call from the command line.
     */

    PutReg(upc, adr);
    v->acntx.sp -= v->cpu->cbPointer;
    /* we will pretend we are calling from location `_end_' */
    PutBlock(v->acntx.sp, spaceData, (ADRT)&v->adrBreak, v->cpu->cbPointer);
    v->acntx.pc = adr;
} /* SetCallProc */
#endif /* X_SetCallProc */


#ifndef X_CallProcedure
/* C A L L   P R O C E D U R E */

export void CallProcedure(adrProc, seFirst, cArg)
ADRT	adrProc;
pSER	seFirst;
int	cArg;
{
    int		cbArg;
    ADRT	adrValue;
    pSER	se;

    SavePcFp();		/* save pc and fp for stack trace info */
    v->acntx.fp = v->acntx.sp;	/* FP becomes new sp value */
    PutReg(ufp, v->acntx.fp);

    /* push arg's in reverse order -- they currently are on the top of
     *	the yacc expression evaluation stack where they were pushed
     *	by the parser.
     */
    for (se = seFirst + cArg - 1; se >= seFirst; se--) { 
	cbArg = CbFSe(se);
	if (cbArg < v->cpu->cbInt) {
	    Coerce(vseCnInt, se);	/* KLUDGE */
	    cbArg = v->cpu->cbInt;
	} else if ((se->ti.bt == btFloat) AND (se->ti.tq0 == tqNil)) {
	    Coerce(vseCnDouble, se);
	    cbArg = v->cpu->cbDouble;
	} /* if */
	adrValue = AdrFSe(se);
	v->acntx.sp -= cbArg;
	PutBlock(v->acntx.sp, spaceData, adrValue, cbArg);
    } /* for */

    /* set pc/stack/etc so we can "continue" into proc call */
    SetCallProc(adrProc, v->acntx.sp, cArg);
    PutReg(usp, v->acntx.sp);	/* and save the goodies */
} /* CallProcedure */
#endif /* X_CallProcedure */


#ifndef X_SeFReturn
/* S E   F   R E T U R N */

export void SeFReturn(seRet, seProc)
pSER	seRet, seProc;
{
    /* Get the return value from the stack after a cmd line proc call */

    RemoveTq(seProc, tqNil);
    seRet->asym.iss = IssFSb("$result");
    if (!FSpecial(seRet))
	Panic("Can't find $result!");

    CopyTy(seRet, seProc);
    seRet->val = ValFSe(seRet);
    seRet->ti.fConstant = true;
    seRet->asym.value = seRet->val.valAdr;
    seRet->asym.sc = scNil;
    seRet->asym.iss = seProc->asym.iss;
} /* SeFReturn */
#endif /* X_SeFReturn */


#ifndef X_GetArgN
/* G E T   A R G   N */

export void GetArgN(cntx, se, iarg)
pCNTXR	cntx;
pSER	se;
int2	iarg;
{
    *se = *vseInt;
    se->asym.value = cntx->ap + (iarg + 1) * v->cpu->cbRegister;
} /* GetArgN */
#endif /* X_GetArgN */


#ifndef X_DispUnknown
/* D I S P   U N K N O W N */

export void DispUnknown(cntx, ipd)
pCNTXR	cntx;
int2	ipd;
{
    int		cParam, i;
    ADRT	ap;
#define cParamMax 6

    /* we print first N (N<=8) parameters */
    ap = cntx->ap + v->cpu->cbInt;	/* step over return address */
    cParam = Min( cParamMax, GetWord(ap, spaceData));
    printf("%s(", SbFIpd(ipd));
    for (i=0; i < cParam-1; i++) {
	ap += v->cpu->cbInt;
	printf("%s, ", SbFAdr(GetWord(ap, spaceData), true));
    } /* if */
    printf("%s)\n", SbFAdr(GetWord(ap, spaceData), true));
} /* DispUnknown */
#endif /* X_DispUnknown */

#ifndef X_FixPc
/* F I X   P C */

export void FixPc()
{
    uint4	value = 0;
    ADRT	pc;
    pBPR	bp;

    if ((v->sigOrig == v->os->sigTrap) AND (v->cpu->fBackupOnBpt)) {

	bp = BpFAdr(v->acntx.pc - v->cpu->cbBp, true);
	if ((v->fDoingSingle)
	   AND ((bp == bpNil) OR (bp->inst == 0)) ) {
	    /* WE don't have a hard BPT there - but what
	     * if the USER does???  For the moment, there's
	     * not much we can do.....
	     */
	    return;
	} /* if */

	value = 0;
	if (v->acntx.pc != ADR_TEXT_BASE)
	    GetBlock(v->acntx.pc - v->cpu->cbBp, spaceText,
			    (ADRT)&value, v->cpu->cbBp);

	if (value == v->cpu->instBp) {
	    /* back up, if we are at a breakpoint */
	    v->acntx.pc -= v->cpu->cbBp;
	    PutReg(upc, v->acntx.pc);
	} /* if */
    } /* if */
} /* FixPc */
#endif /* X_FixPc */


#ifndef X_FinishCpu
/* F I N I S H   C P U */

export void FinishCpu()
{
    /* do any CPU dependent clean up necessary */
} /* FinishCpu */
#endif /* X_FinishCpu */


#ifndef X_InitRegisters
/* I N I T   R E G I S T E R S */

export void InitRegisters(cpu)
pCPUR	cpu;
{
    int		i;
    char	sb[10];
    pSER	se;

    cpu->rgReg = vrgReg;
    se = vrgReg;
    InitSpc(se++, "result", 0, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "fp", ufp, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "sp", usp, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "ap", uap, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "pc", upc, stExpr, scRegister, tqNil, btInt, false);

    for (i = 0; i < 16; i++) {
	sprintf(sb, "r%d", i);
	InitSpc(se++, SbFAlloc(sb), (uint4)i, stExpr,
		scRegister, tqNil, btInt, false);
    } /* for */

    cpu->iregMax = se - vrgReg;
} /* InitRegisters */
#endif /* X_InitRegisters */


#ifndef X_InitCpu
/* I N I T   C P U */

export void InitCpu(cpu)
pCPUR	cpu;
{
    int		i;
    pSER	se;

#if (CPU != HOST_CPU)
    if (cpu == vcpuHost)
	InitHostCpu(cpu);
#endif /* (CPU != HOST_CPU) */

    cpu->cBadMax = 10;

    cpu->cbChar = 1;
    cpu->cbShort = sizeof(short);
    cpu->cbInt = sizeof(int);
    cpu->cbLong = sizeof(long);
    cpu->cbPointer = sizeof(char *);
    cpu->cbFloat = sizeof(float);
    cpu->cbDouble = sizeof(double);
    cpu->cbRegister = cpu->cbPointer;

    cpu->bitSex = BIT_SEX;
    cpu->byteSex = BYTE_SEX;
    cpu->instBp = BPT_INST;
    cpu->cbBp = CB_BP;
    cpu->alignment = ALIGNMENT_MASK;
    cpu->fApIsFp = FPISAP;
    cpu->fBackupOnBpt = BPT_BACKUP;
    cpu->fCalleeStackCleanup = CALLEE_STACK_CLEANUP;

    InitRegisters(cpu);
} /* InitCpu */
#endif /* X_InitCpu */


#if (CPU != HOST_CPU)
/* I N I T   C P U */

export void InitHostCpu(cpu)
pCPUR	cpu;
{
    cpu->bitSex = BIT_SEX;
    cpu->byteSex = BYTE_SEX;
    cpu->alignment = ALIGNMENT_MASK;
} /* InitHostCpu */
#endif /* (CPU != HOST_CPU) */
0707070001000312031004440000000000010000011576710454650113300001500000062544cdb/format.c /* $Header: format.c,v 6.2 86/09/01 17:19:46 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This file does the data formatting.
 * WARNING - DisplaySe is a ---> SWAMP <----.
 * Only Masochists should venture forth into this stuff.
 */

#include "cdb.h"
#include <setjmp.h>

export FLAGT	vfInDisplay = false;
export FLAGT	vfBadAddress = false;
export char vsbFmt[60]; /* format spec for addresses */
static char vsbAdr[60]; /* where we stick last address formatted - SbFAdr */

export int vcNest;	/* nesting level for printing structures and unions */
export SBT vsbSpaces =
"                                                                             ";

#if 0
/* Don't remove this section - it is picked up by 'make ext.h' */
exportdefine PrintNest(cNest, cb) if (cNest) printf("%.*s", cNest*cb, vsbSpaces)
#endif


/* S B   F   A D R */

export SBT SbFAdr(adr, fMask)
ADRT    adr;
FLAGT   fMask;
{
    /* Format an address in the current, user-defined format */

    if (vsbFmt[0] == chNull)
#ifdef V7_PRINTF
        strcpy(vsbFmt, "0x%lx");
#else
        strcpy(vsbFmt, "%#lx");
#endif /* V7_PRINTF */
    if (fMask AND (v->cpu->cbPointer == 2))
        adr &= 0x0000ffffL;
    sprintf(vsbAdr, vsbFmt, adr);
    return(vsbAdr);
} /* SbFAdr */


/* S B   F   B I N A R Y */

export SBT SbFBinary(value, cbits)
FAST uint4	value;
int	cbits;
{
    FAST int	i;
    FAST SBT	sb;
    static char	sbBuf[40];

    /* generate a string of 0/1's for the given value */

    sb = sbBuf;
    value <<= 32 - cbits;
    for (i = 32-cbits+1; i <= 32; ++i, value <<= 1) {
	*sb++ = (value & 0x80000000) ? '1' : '0';
	if ((i % 4) == 0)
	    *sb++ = ' ';
    } /* for */
    sb[-1] = chNull;	/* overwrite last ' ' */
    return(sbBuf);
} /* SbFBinary */


/* D F   F   S E */

export DFE DfFSe(se, fAlternate)
pSER	se;
FLAGT	fAlternate;
{
    int2	tq;

    /* Determine the `natural' display format for the given value */

    if (se->asym.st == stCommon)
	return(dfCommon);

    tq = se->ti.tq0;
    if ((tq == tqPtr) OR (tq == tqArray)) {
	if ( fAlternate
	   AND ((se->ti.bt == btChar) OR (se->ti.bt == btUChar))
	   AND (TqFSe(se, 1) == tqNil) ) {
	    return((tq == tqPtr) ? dfPStr : dfStr);	/* so it looks pretty */
	} else if (tqProc == TqFSe(se, 1)) {
	    return(dfProc);
	} /* if */
	return(dfAdr);	/* use address display mode */
    } /* if */
    
    switch (se->ti.bt) {
	case btNil:	return(dfNil);
	case btUnion:
	case btStruct:	return( (fAlternate) ? dfStruct : dfAdr );
	case btUChar:
	case btUShort:
	case btUInt:
	case btULong:	return(dfUnsigned);
	case btShort:
	case btInt:
	case btLong:	return(dfDecimal);
	case btFloat:
	case btDouble:	return(dfGFloat);
	case btComplex: return(dfComplex);
	case btLogical:	return(dfBoolean);
	case btEnum:	return(dfEnum);
	case btChar:	if ((tq == tqArray) AND fAlternate)
			    return(dfStr);
			 else
			    return(dfChar);
    } /* switch */
    return(dfDecimal);
} /* DfFSe */


/* C B   F   C H */

export int CbFCh(ch)
char    ch;
{
    /* Return the size in byte associated with a given format character */

    switch (ch) {
	case 'A':	return(v->cpu->cbPointer);
        case 'b':
        case 'c':       return(v->cpu->cbChar);
        case 'e':
        case 'f':
        case 'g':       return(v->cpu->cbFloat);
        case 'E':
        case 'F':
        case 'G':       return(v->cpu->cbDouble);
        case 'D':
        case 'O':
        case 'U':
        case 'X':       return(v->cpu->cbLong);
    } /* switch */
    return(-1);	/* says to use current size */
} /* CbFCh */


/* D F   F   C H */

export DFE DfFCh(ch)
char    ch;
{
    /* Return the display format associated with a given character */

    switch (ch) {
	case 'A':	return(dfAdr);
        case 'B':       return(dfBinary);
        case 'a':       return(dfStr);
        case 'C':
        case 'c':       return(dfChar);
        case 'b':
        case 'D':
        case 'd':       return(dfDecimal);
        case 'E':
        case 'e':       return(dfEFloat);
        case 'F':
        case 'f':       return(dfFFloat);
        case 'G':
        case 'g':       return(dfGFloat);
	case 'I':	return(dfCompiler);
	case 'i':	return(dfInstruction);
        case 'N':       return(dfStandard);
        case 'n':       return(dfNil);
        case 'O':
        case 'o':       return(dfOctal);
        case 'P':       return(dfProc);
        case 'p':       return(dfProcLine);
        case 'S':       return(dfStruct);
        case 's':       return(dfPStr);
        case 'U':
        case 'u':       return(dfUnsigned);
	case 't':	return(dfType);
        case 'X':
        case 'x':       return(dfHex);
    } /* switch */
    return(dfNil);
} /* DfFCh */


/* G E T   M O D E */

export void GetMode(mode)
pMODER  mode;
{
    char        ch;
    TKE         tk;

    /* Get a display mode (if any) from the current command line */

    /* NOTE: we assume WE get next token!! */
    tk = TkNext();

    if (tk == tkNil) {
        return;
    } else if (tk == tkNumber) {
        mode->cnt = atoi(vsbTok);
        tk = TkNext();
    } else {
        mode->cnt = 1;
    } /* if */

    if (tk == tkStr) {
        ch = vsbTok[0];
        /* determine # of bytes based on format */
        mode->len = CbFCh(ch);
        /* mode->len = -1; */
        mode->df = DfFCh(ch);
	if ((mode->df == dfNil) AND (ch != 'n'))
	    UError("Unknown display mode.");
        if (vsbTok[1] != chNull)
            mode->len = (vsbTok[1] == 'b') ? 1 : 
                        (vsbTok[1] == 's') ? 2 :
                        (vsbTok[1] == 'l') ? 4 : atoi(&vsbTok[1]);
        tk = TkNext();
    } /* if */
} /* GetMode */


/* I N C   F   S E   M O D E */

export int IncFSeMode(se, mode, multiplier)
pSER    se;
pMODER  mode;
int	multiplier;
{
    int		i, df;

    if ((se->asym.sc == scCdbLocal)	/* we do NOT allow inc's of specials */
       OR (mode->df == dfType))
        return;

    se->asym.iss = issNil;
    df = mode->df;
    if ((df == dfInstruction) OR (df == dfCompiler)) {
	i = vcbInst;
	if (se->asym.sc == scRegister) {
	    ValFSe(se); /* get current value */
	    se->asym.sc = scData;	/* make it NOT a register */
	    se->ti.fConstant = true;
	    se->val.valAdr = se->val.valInt; /* KLUDGE ?? */
	    se->asym.value = se->val.valAdr;
	    se->ti.bt = btAdr;
	} /* if */
	v->adrInst = se->val.valAdr + i;
    } else if (se->asym.sc == scRegister) {
        i = 1;
    } else if (mode->df == dfStr) {
	if (mode->len < 0) {
	    i = -mode->len;
	    mode->len = -1;
	} else {
	    i = mode->cnt * mode->len;
	} /* if */
    } else if (mode->df == dfPStr) {
	i = mode->cnt * v->cpu->cbPointer;
    } else if ((df == dfProc) OR (df == dfProcLine)) {
	i = 0;
    } else {
	i = mode->cnt * mode->len;
    } /* if */

    i *= multiplier;  /* multiplier is either 1 or -1 */
    se->asym.value += i;
    se->val.valAdr += i;
} /* IncFSeMode */


/* D I S P L A Y   S E */

export void DisplaySe(se, mode, fShowAdr, fIndirect, fAlternate)
pSER	se;
pMODER  mode;
FLAGT   fShowAdr, fIndirect, fAlternate;
{
    int2	modval, width, cPrint, cb, len, lenSave;
    int2	cntStruct, fmt, cnt, i, ipd, iln;
    int		*envSave;
    uint4	mask;
    FLAGT       fCharArray, fLocal, fDoStd, fCheckNull, fRandomLength, fDefault;
    char        ch, sbBuf[100];
    SBT		sbVar;
    DFE         df;
    MODER	amodeT;
    ADRT	adrWorking;
    SER		aseT, aseSave, *seSave;
    VALU	val;
    jmp_buf	envDisplaySe;   /* for error recovery */

    df = dfNil;
    envSave = venv;

    if (setjmp(envDisplaySe)) {
	/* we bomnbed out. see if this was for (char *)/n situation */
	if (fDefault AND (df == dfPStr)) {
	    fDefault = false;
	    df = dfHex;
	    printf(" ");
	    goto Pstr_SecondPass;
	} else if (fDefault AND (df == dfFFloat
				OR df == dfEFloat
				OR df == dfGFloat)) {
	    printf("<<invalid float or double (NAN)>>\n");
	} else if (vfBadAddress) {
	    printf("<<bad address>>\n");
	} /* if */
	venv = envSave;
	vfInDisplay = false;
	return;
	/* UError(sbNil);	/* hand it back up to next level */
    } else {
	venv = envDisplaySe;
	vfInDisplay = true;
	vfBadAddress = false;
    } /* if */

Pstr_SecondPass:

    fDoStd = false;	/* says to use user supplied formatting if possible */
    fDefault = false;
    modval = 1;
    seSave = se;
    aseT = *se;	/* we work out on a copy, not the original */
    se = &aseT;

    /* if the mode is supplied, we change the type of se */
    if ((df != dfNil) OR (mode == modeNil)) {
	mode = &amodeT;
        cnt = 1;
	len = -1;
	cntStruct = 1;
	fDefault = true;
    } else {
        df = mode->df;
        cnt = mode->cnt;
        cntStruct = mode->len;
	if ((df == dfStruct) OR (df == dfNil) OR (df == dfStandard))
	    mode->len = -1;
	len = mode->len;

        /* this may not be right, but we need to force the size of what we
         * are looking at to be the size we requested in the format.
         * this way, when we say `sbWord/c;<cr>;<cr>;.='H' ' we actually
         * do the `correct' character assignment.
         */
        if (len > 0) {
            switch (len) {
                case 1: CopyTy(se, vseChar);
			if ((df == dfUnsigned)
			   OR (df == dfHex)
			   OR (df == dfOctal))
			    se->ti.bt = btUChar;
			break;
                case 2: CopyTy(se, vseShort);
			if ((df == dfUnsigned)
			   OR (df == dfHex)
			   OR (df == dfOctal))
			    se->ti.bt = btUShort;
			break;
                case 4: CopyTy(se, vseLong);
			if ((df == dfUnsigned)
			   OR (df == dfHex)
			   OR (df == dfOctal))
			    se->ti.bt = btULong;
			break;
            } /* switch */
        } /* if */
    } /* if */

    aseSave = *se;	/* for use during looping */

    if (df == dfStandard) {
	fDoStd = true;
	df = dfNil;
    } /* if */

    lenSave = len;
    fCharArray = false;

    if (df == dfNil) {
	/* they did not specify display format */
	if (! fIndirect) {
	    df = dfAdr;
	    len = v->cpu->cbPointer;
	} else {
	    df = DfFSe(se, fAlternate);
	    if (df == dfPStr) {
		len = -1;
	    } else if (df == dfStr) {
		if (se->ti.tq0 == tqNil) {
		    len = -1;
		} else {
		    fCharArray = true;
		    len = CbFSe(se);
		} /* if */
	    } else {
		len = CbFSe(se);
	    } /* if */
	} /* if */

	/* remember this stuff */
	mode->df = df;
	mode->cnt = cnt;
	mode->len = len;
    } /* if */

    if ((!fIndirect) AND (len == -1))
	mode->len = len = v->cpu->cbPointer;

    fRandomLength = (len == -1);
    if ( fRandomLength
       AND (df != dfStr)
       AND (df != dfPStr)
       AND (df != dfCompiler)
       AND (df != dfInstruction))
        mode->len = len = CbFSe(se);

    cb = len;
    mask = 0xffffffff;
    if (df == dfBinary) {
	modval = 1;
	if (len <= 4) {
	    width = (len+1) * 8 + 2;
	    len *= 8;
	} else {
	    /* they gave us bits */
	    width = len + 2 + len / 8;
	    mode->len = (len + 7) / 8; /* round up to the next byte */
	} /* if */
    } else if (df == dfPStr) {
	cb = v->cpu->cbPointer;
    } else if (df == dfStr) {
	cb = v->cpu->cbChar;
	if (fRandomLength)
	    mode->len = 0;	/* we will stuff final count in here for Inc */
    } else if (df == dfProcLine) {
        fShowAdr = false;
    } else if (fShowAdr
		AND (len == -1)
		AND ! ((df == dfInstruction) OR (df == dfCompiler)) ) {
	cnt = 1;
	mask = 0xffffffff;
    } else {
        /* here we try to skull out a good width for this size */
        width = 7;
        modval = 8;
	mask = (len == 1) ? 0x000000ff : 0x0000ffff;
        if (len >= 4) {
            width = 14;
            modval = 4;
	    mask = 0xffffffff;
        } /* if */
    } /* if */

    if (cnt == 1)
        width = 0; /* we don't try to add anything if there's just one */

    if ((df == dfInstruction)
       OR (df == dfCompiler)) {
	/* this is a little kludgey */
	ValFSe(se);	/* get the value of the thing */
	se->ti.fConstant = true;	/* lock it in place */
	if (cnt > 1) {
	    /* even weirder - we force the thing to change altogether */
	    se->asym.sc = scData;	
	    se->asym.value = se->val.valAdr;
	    *seSave = *se;
	    aseSave = *se;
	    se = seSave;
	} /* if */
    } else if (df == dfType) {
	fIndirect = false;
	fShowAdr = false;
	cnt = 1;
    } /* if */

    amodeT = *mode;
    mode = &amodeT;
    amodeT.cnt = 1;

    cPrint = 0;
    while (cnt--) {
	if (fIndirect) {
	    val = ValFSe(se);
	} else {
	    val.valAdr = se->asym.value;
	    if (df != dfType)
		CopyTy(se, vseCnAdr);
	} /*if */

        if (fShowAdr
	   AND fIndirect
	   AND (df != dfStruct)
	   AND (df != dfCompiler)
	   AND (df != dfInstruction)
	   AND (!se->ti.fConstant OR (se->asym.sc != scNil))
	   AND (cPrint % modval == 0)) {
            if ((cnt == 0)	/* i.e. we are not doing multiple values */
               AND ((sbVar = SbFIss(se->asym.iss)) != sbNil)
	       AND (*sbVar != chNull))
                printf("%s = ", sbVar);
             else
/* printf("%s  ", SbFNearest(se->asym.value, true, true, false)); */
                printf("%s  ", SbFAdr(se->asym.value, true));
	} else if ((se->asym.sc == scRegister) AND fShowAdr AND !fIndirect) {
	    printf("$r");
        } /* if */

	se->val = val;
	se->ti.fConstant = true;
        switch (df) {
	    case dfCompiler:
		Coerce(vseCnAdr, se);
		SetViewPosition(se->val.valAdr);
		fmt = fmtLn + fmtLine;
		if (v->rgFd[v->ifd].fNoSource) {
		    fmt += fmtProc;
		} else if (v->slop == 0) {
		    Highlight(true);
		    PrintPosition(adrNil, fmtProc+fmtLn+fmtLine);
		    Highlight(false);
		} /* if */
		PrintPosition(adrNil, fmt+fmtInst);
		break;

	    case dfInstruction:
		Coerce(vseCnAdr, se);
		PrintPosition(se->val.valAdr, fmtProc+fmtLn+fmtInst+fmtLine);
		break;

            case dfType:
		PxSe(se, fAlternate);
                break;

            case dfBinary:
		Coerce(vseCnULong, se);
                printf("%*s", width, SbFBinary(se->val.valULong, len));
                break;

            case dfAdr:
		Coerce(vseCnAdr, se);
                printf("%*s", width, SbFAdr(se->val.valAdr, true));
                break;

            case dfDecimal:
		Coerce(vseCnLong, se);
                printf("%*ld", width, se->val.valLong);
                break;

            case dfUnsigned:
		Coerce(vseCnULong, se);
		se->val.valULong &= mask;
                printf("%*lu", width, se->val.valULong);
                break;

            case dfOctal:
		Coerce(vseCnULong, se);
		se->val.valULong &= mask;
#ifdef V7_PRINTF
                sprintf(sbBuf, "0%lo", se->val.valULong);
                printf("%*s", width, sbBuf);
#else
                printf("%#*lo", width, se->val.valULong);
#endif /* V7_PRINTF */
                break;

            case dfHex:
		Coerce(vseCnULong, se);
		se->val.valULong &= mask;
#ifdef V7_PRINTF
                sprintf(sbBuf, "0x%lo", se->val.valULong);
                printf("%*s", width, sbBuf);
#else
                printf("%#*lx", width, se->val.valULong);
#endif /* V7_PRINTF */
                break;

            case dfChar:
		Coerce(vseCnChar, se);
                if (  (se->val.valUChar < ' ')
		   OR (se->val.valUChar > chRCB) ) {
#if (CPU == PDN)
		    ch = AsciiFEbcdic(se->val.valUChar);
#else
		    ch = se->val.valUChar & 0177;
#endif /* (CPU == PDN) */
		    ch += (ch < ' ') ? 0100 : (ch > chRCB) ? -0100 : 0;
#ifdef V7_PRINTF
                    printf("'^%c' (0%o)", ch, se->val.valUChar);
#else
                    printf("'^%c' (%#x)", ch, se->val.valUChar);
#endif /* V7_PRINTF */
		} else {
		    printf("'%c'", se->val.valChar);
		} /* if */
                break;

            case dfFFloat:
            case dfEFloat:
            case dfGFloat:
		Coerce(vseCnDouble, se);
		if (lenSave == -1) {
		    if (df == dfFFloat)
			printf("%*f", width, se->val.valDouble);
		    else if (df == dfEFloat)
			printf("%*e", width, se->val.valDouble);
		    else
			printf("%*g", width, se->val.valDouble);
		} else {
		    if (df == dfFFloat)
			printf("%*.*f", width, lenSave, se->val.valDouble);
		    else if (df == dfEFloat)
			printf("%*.*e", width, lenSave, se->val.valDouble);
		    else
			printf("%*.*g", width, lenSave, se->val.valDouble);
		} /* if */
                break;

	    case dfBoolean:
		Coerce(vseCnULong, se);
                printf("%*s", width, se->val.valULong?"TRUE":"FALSE");
		break;

	    case dfComplex:
		printf("(%f,%f)", se->val.valComplex.valReal,
			se->val.valComplex.valImaginary);
		break;

	    case dfEnum:
		PxEnum(se);
                break;

	    case dfStruct:
		PxStruct(se, cntStruct, true, fAlternate, fDoStd);
                break;

	    case dfCommon:
		PxCommon(se, true, fAlternate);
                break;

            case dfProc:
		Coerce(vseCnAdr, se);
                if (se->val.valAdr == 0)
		    printf("<null proc pointer>");
		else
		    printf("%s()", 
			SbFNearest(se->val.valAdr, true, false, false));
		venv = envSave;
                break;

            case dfProcLine:
		Coerce(vseCnAdr, se);
                PrintPosition(se->val.valAdr, fmtFile+fmtProc+fmtLn+fmtLine);
		venv = envSave;
		vcmdDef = cmdNil;
		vfInDisplay = false;
		return;		/* probably a kludge */
                break;

            case dfPStr:
		Coerce(vseCnAdr, se);
                se->asym.value = se->val.valAdr;
		/* and fall into string stuff */

            case dfStr: 
		adrWorking = se->asym.value;
                fCheckNull = fCharArray;
                if (fRandomLength) {
                    if (adrWorking == 0) {
			printf("<null pointer>");
			break;
                    } /* if */
		    fCheckNull = true;
		    len = 128;
		    if (se->ti.lc == lcFortran)
			len = Min(len, CbFSe(se));
                } /* if */
		fLocal = (se->asym.sc == scCdbSystem); /* from OUR space */
		printf("\"");
                for (i=0; i != len; i++) {
                    ch = (fLocal) ? (* ((char *) adrWorking+i))
#if (CPU == PDN)
			 : ChFRemote(GetByte((ADRT)(adrWorking+i), spaceData));
#else
				: GetByte((ADRT)(adrWorking+i), spaceData);
#endif /* (CPU == PDN) */
                    if ((ch == chNull) AND fCheckNull)
                        break;
                    if (ch < ' ')
                        printf("^%c", ch+0100);
                     else printf("%c", ch);
                } /* for */
		printf("\"");
                break;
        } /* switch */
	*se = aseSave;

	if (fRandomLength) {
	    i += 1;	/* if we did /s or /a, this moves us past the chNull */
	    if (df == dfStr)
		mode->len = -i;	/* remember size for IncFSeMode */
	} /* if */

        if (cnt) {
	    /* we are doing more than one */
	    IncFSeMode(se, mode, 1);
	    aseSave = *se;	/* save this */
            if ( ((++cPrint % modval) == 0)
               OR (df == dfPStr)
	       OR (df == dfStr)
	       OR (df == dfCompiler)
	       OR (df == dfInstruction)
	       OR (df == dfStruct) ) {
                printf("\n");
            } /* if */
        } /* if */

    } /* while */

    if (fDoStd)
	mode->df = dfStandard;
    vfInDisplay = false;
    venv = envSave;
} /* DisplaySe */


/* P X   E N U M */

export void PxEnum(se)
pSER	se;
{
    int		valInt;

    /* Print the symbolic name of the value as a member of a specific ENUM */

    valInt = se->val.valInt;
    if (se->isymRef == isymNil) {
	/* they don't have enough info to figure out name */
	printf("%d", valInt);
	return;
    } /* if */

    SetNextSym(se->isymRef+1);
    while (FNextSym(stMember, stNil, stNil, stEnd, false, sbNil, nil)) {
	if (v->sym->value == valInt) {
	    printf("%s", SbFIss(v->sym->iss));
	    return;
	} /* if */
    } /* while */
    printf("Value %d is not defined for 'enum %s'", valInt,
		SbFIss(SymFIsym(se->isymRef)->iss) );
} /* PxEnum */


/* P X   S T R U C T */

export void PxStruct(seStruct, cntStruct, fDoVal, fAlternate, fDoStd)
pSER	seStruct;
int2	cntStruct;
FLAGT	fDoVal, fAlternate, fDoStd;
{
    int2	bt;
    int4	isymSave;
    char	sbProc[100];
    SBT		sbType, sbName;
    SER		aseField;
    pSYMR	sym;

    /* Itterate through all members of a struct or union,
     * printing either their type or their value.
     * Recurse as necessary.
     */

    if (seStruct->isymRef == isymNil)
	UError("There is insufficient information to do a structure dump.");

    if (seStruct->ti.tq0 != tqNil) {
	printf("\"%s\" is of type:\n", SbFIss(seStruct->asym.iss));
	PxSe(seStruct, false);
	printf("\nWhich is not appropriate for format mode 'S'.\n");
	UError(sbNil);
    } /* if */

    bt = seStruct->ti.bt;
    if ((bt != btStruct) AND (bt != btUnion))
	UError("\"%s\" is not a struct or a union.", SbFIss(seStruct->asym.iss));
    
    sym = SymFIsym(seStruct->isymRef);

    sbType = SbFIss(sym->iss);
    if ((sbType == sbNil)
       AND (seStruct->isymTypedef != isymNil)) {
	sbType = SbFIss(SymFIsym(seStruct->isymTypedef)->iss);
    } /* if */

    if (!fDoStd AND fDoVal AND fAlternate AND (v->pid != pidNil)) {
	/* Try calling a user defined print routine for this struct/union.
	 * Its name is of the form "_structname".
	 */
	fflush(stdout);
	sprintf(sbProc, "_%s", sbType);
	if (FCallUserProc(sbProc, 2, seStruct->asym.value, cntStruct))
	    return;
    } /* if */

    /* now that we know whether the user is supplying his own,
     * we put out the standard lead in.
     */
    MoreOn();

    PrintNest(vcNest, 4);
    if ( ((sbName = SbFIss(seStruct->asym.iss)) != sbNil)
       AND (*sbName != chNull))
	printf("%s = ", sbName);
     else
	printf("%s ", SbFAdr(seStruct->asym.value, true));

    if (bt == btStruct)
	printf("struct ");
    else if (bt == btUnion)
	printf("union ");
    
    if (sbType != sbNil)
	printf("%s ", sbType);
    printf("{\n");

    vcNest++;
    SetNextSym(seStruct->isymRef + 1);
    while (FNextSym(stMember, stNil, stNil, stEnd, false, sbNil, nil)) {

	isymSave = v->isym;
	SeFSym(&aseField, v->sym, true);
	AdjustFieldOffset(seStruct, &aseField);
	bt = aseField.ti.bt;

	if ( (aseField.ti.tq0 == tqNil)
	   AND ((bt == btStruct) OR (bt == btUnion)) ) {
	    if (fDoVal)
		DisplaySe(& aseField, modeNil, false, true, fAlternate);
	    else
		PxSe(& aseField, fAlternate);
	} else {
	    PrintNest(vcNest, 4);
	    if (fDoVal)
		DisplaySe(& aseField, modeNil, true, true, fAlternate);
	    else
		PxSe(& aseField, fAlternate);
	} /* if */
	printf(";\n");

	SymFIsym(isymSave);

    } /* while */

    vcNest--;
    PrintNest(vcNest, 4);
    printf("}");
    if (seStruct->asym.iss != issNil)
	printf(" %s", SbFIss(seStruct->asym.iss));
    MoreOff();
} /* PxStruct */


/* P X   P R O C */

export void PxProc(ipd, fDoName, fAlternate)
int2	ipd;
FLAGT	fDoName, fAlternate;
{
    int2	ifd, iln, slop, i;
    int4	isym;
    SER		ase, *se = &ase;

    printf("%s(", fDoName ? SbFIpd(ipd) : "");

    if (v->rgPd[ipd].iline == 0) {
	printf(")");
	return;
    } /* if */

    i = 0;
    isym = v->rgPd[ipd].isym + 1;
    while (FNextLocal(false, true, isym)) {
	if (i++ > 0)
	    printf(", ");
	printf("%s", SbFIss(v->sym->iss));
	isym = v->isym + 1;
    } /* while */
    printf(")");

    isym = v->rgPd[ipd].isym + 1;
    while (FNextLocal(false, true, isym)) {
	isym = v->isym + 1;
	SeFSym(se, v->sym, true);
	printf("\n");
	PxSe(se, fAlternate);
	printf(";");
    } /* while */
} /* PxProc */


/* P X   S E */

export void PxSe(se, fAlternate)
pSER	se;
FLAGT	fAlternate;
{
    int2	i, idim, ipd, cPtr, tq, tqLast, st, sc, bt;
    SBT		sbName;
    FLAGT	fDidName, fNeedRP, fDoProc;
    pRNGR	rng;
    SER		ase;

    /* Print the TYPE of the given SE */
    if (se->ti.lc == lcFortran) {
	F_PxSe(se, fAlternate);
	return;
    } /* if */

    tqLast = tqNil;
    fDidName = false;
    st = se->asym.st;
    sc = se->asym.sc;
    bt = se->ti.bt;
    tq = se->ti.tq0;

    /* print storage class */
    if (st == stGlobal) {
	printf("<global> ");
	if (sc == scAbs)
	    printf("<absolute> ");
    } else if (st == stStatic)
	printf("static ");
    else if (  (sc == scRegister)
	    OR (sc == scFloatRegister)
	    OR (sc == scRegImage))
	printf("register ");
    else if ((sc == scCdbSystem) OR (sc == scCdbLocal))
	printf("<special> ");

    if ((se->isymTypedef != 0)
       AND (tq == tqNil)) {
	SeFSym(& ase, &(se->asym), false); /* get JUST the first level */
	/* KLUDGE!!!!! */
	printf("%s %s\n", SbFIss(SymFIsym(se->isymTypedef)->iss),
			SbFIss(se->asym.iss));
	if (! fAlternate)
	    return;	/* they wanted the short form */
    } /* if */

    if ( (tq == tqNil)
       AND (fAlternate)
       AND ((bt == btStruct)
       OR (bt == btUnion)) ) {
	PxStruct(se, -1, false, fAlternate, true);
	fDidName = true;
    } else if (se->asym.st == stCommon) {
	PxCommon(se, false, fAlternate);
	fDidName = true;
    } else {
	/* print type name */
	printf("%s ", SbFBt(bt));
	if ((bt == btEnum)
	   OR (bt == btStruct)
	   OR (bt == btUnion)) {
	    printf("%s ", SbFIss(SymFIsym(se->isymRef)->iss));
	}
    } /* if */

    /* first we total up the dimensions */
    for (idim = 0, i = itqMax-1; i >= 0; i--) {
	if (tqArray == TqFSe(se, i))
	    idim++;
    } /* for */

    sbName = SbSafeFIss(se->asym.iss);
    fNeedRP = false;
    tqLast = tqNil;
    fDoProc = false;
    for (i = itqMax-1; i >= 0; i--) {

	if ((tq = TqFSe(se, i)) == tqNil)
	    continue;

	if (fDoProc) {
	    printf("(");
	    fNeedRP = true;
	} /* if */

	switch (tq) {
	    case tqPtr:
		printf("*");
		break;

	    case tqProc:
		fDoProc = true;
		break;

	    case tqArray:
		if (! fDidName) {
		    printf("%s", sbName);
		    fDidName = true;
		} /* if */
		idim--;
		rng = se->rgRng + idim;
		if (rng->dnLow > rng->dnHigh)
		    printf("[]");
		 else
		    printf("[%d]", rng->dnHigh + 1);	/* KLUDGE - C only */
		break;
	} /* switch */

	tqLast = tq;
    } /* for */

    if (fDoProc) {
	if (fNeedRP) {
	    printf("%s)", sbName);
	    fDidName = true;
	} /* if */
	ipd = IpdFAdr(se->asym.value);
	if (ipd != ipdNil)
	    PxProc(ipd, ! fDidName, fAlternate);
	else
	    printf("%s()", sbName);
	fDidName = true;
    } /* if */

    if (!fDidName)
	if (se->asym.iss != issNil)
	    printf("%s", sbName);
    if (se->asym.sc == scBits)
	printf(" : %d", se->bitsWidth);
} /* PxSe */
0707070001000312041004440000000000010000011601600454650113400001200000011034cdb/loe.c /* This program is used to test and to demonstrate
 * the features of CDB.  It tries to have a "little
 * of everything", so it doesn't make much sense.
 */

#include <stdio.h>
#include <signal.h>

typedef union {
	struct { int s11; } s1;
	struct { int s21, s22; } s2;
	struct { int s31, s32, s33; } s3;
	} U1U, *pU1U;
U1U	a_union;

struct foo {
	struct foo *fooNext;
	struct bar *pbar;  /* points at undefined struct */
	} afoo;

typedef struct foo *pFOOR;

typedef enum COLOR {red, orange, yellow,
		green=10, blue, purple} COLORE;
COLORE	colore;

typedef struct RECS {
	short	a;
	char	b[9];
	long	c;
	unsigned bits1 : 1;
	unsigned bits2 : 2;
	unsigned bits3 : 3;
	unsigned bits4 : 4;
	COLORE	color : 5;
	int	(*prtn)();
	} RECR, *pRECR;

extern int main();
extern int First();
extern char * Second();
extern int Third();

struct RECS a_record = {-1, "Apple Pi",
	987654321L, 1, 2, 4, 8, purple,main};

struct RECS record_array[] = {
	{0, "First",	 0L, 0, 0, 0, 0, red, First},
	{1, "Second",	-1L, 1, 1, 1, 1, orange, main},
	{2, "Third",	-2L, 1, 2, 2, 2, yellow, Third},
	{3, "Fourth",	-3L, 1, 3, 3, 3, green, main},
	{4, "Fifth",	-4L, 1, 1, 4, 4, blue, main},
	{5, "Sixth",	-5L, 1, 2, 5, 5, purple, First},
	};

char	*string_array[5] = { "0", "1", "2", "3", "4" };
char	himom[15] = "Hi there, Mom!";
char	char_array[2][5]= {
			00, 01, 02, 03, 04,
			10, 11, 12, 13, 14,
			};
int	int_array[4][7]= {
			00, 01, 02, 03, 04, 05, 06,
			10, 11, 12, 13, 14, 15, 16,
			20, 21, 22, 23, 24, 25, 26,
			30, 31, 32, 33, 34, 35, 36
			};
char	dbl_array[10][128] = {"0","1","2","3","4","5","6","7","8","9"};
int	loop, seconds, recurse;


/* A L A R M I S T */

Alarmist()
{
    signal(SIGALRM, Alarmist);
    alarm(seconds);
} /* Alarmist /* 


/* M A I N */

int main(argc, argv, envp)
int	argc;
char	*argv[];
char	*envp[];
{
    int		recurseLevel, cMainArgs, i, fUsedArg;
    char	*sbArg, *sbTemp, *sbUsage;

    sbUsage = "Usage: loe [-s #] [-r #]\n";
    cMainArgs = 0;

    for (i = 1; i < argc; ++i) {
	sbArg = argv[i];
	if (*sbArg != '-') {

	    printf(sbUsage);
	    exit(1);

	} else {

	    /* this is an option string */
	    ++sbArg;	/* move past the '-' */
	    while (*sbArg) {
		/* point to a potential argument */
		sbTemp = (sbArg[1] != '\0') ? sbArg+1 : argv[i+1];
		fUsedArg = 0; /* set to true if option uses an arguement */

		switch (*sbArg) {
		    default:
			printf(sbUsage);
			exit(1);
		    
		    case 'r':
			recurseLevel = atoi(sbTemp);
			fUsedArg = 1;
			break;

		    case 's':
			seconds = atoi(sbTemp);
			fUsedArg = 1;
			break;

		} /* switch */
		++sbArg;
		if (fUsedArg) {
		    if (*sbArg == '\0')
			i++;	/* eat next word - it was the arg we used */
		    *sbArg = '\0';
		} /* if */
	    } /* while */
	} /* if */
    } /* for all command line arguments */

    /* Main code */
    string_array[0] = "a";
    string_array[1] = "b";
    string_array[2] = "c";

    while (*argv)
	printf("%s\n",*(argv++));

    for (loop=1; loop != 0; loop++) {
	recurse = recurseLevel;
	First(loop, loop, loop);
    } /* for */

    printf("done\n");
    exit(0);
} /* main */


/* S E C O N D */

char * Second(aaa, bbb, ccc)
register char	aaa;
register short ccc;
int	bbb;
{
    long	x;

    if (recurse) {
	--recurse;
	Second(aaa+recurse+1, bbb+recurse+1, ccc+recurse+1);
	return((char *)recurse);
    } /* if */

    x = aaa + bbb + ccc;
    Third(aaa, -1, "A good message", &a_record);
    return((char *) 0);
} /* Second */


/* T H I R D */

Third(select, random, message, rec)
register long	 select;
int	random;
register char	*message;
pRECR	rec;
{
    register float	fl;
    double	xfl;
    static struct RECS *precord;

    precord = rec;
    xfl = fl = 5.8;

    if (select != 0) {
	int random;

	random = -9;
	switch (select % 7) {
	    case 1:	printf("1\n");	break;
	    case 2:	printf("2\n");	break;
	    case 3:	printf("3\n");	break;
	    case 4:	printf("4\n");	break;
	    default:	printf("default\n");	break;
	} /* switch */
    } /* if */

    printf("%s\n", message);
} /* Third */


/* F I R S T */

First(i, j, k)
int	i;
char	j;
short	k;
{
    Second(i, j+1, k+2);
} /* First */


/* A D D   A R G S */

static double AddArgs(i, d)
int	i, d;
{
    int		value;

    value = i + d;
    Second(i, i+1, i+2);
    return(value * 3.2);
} /* AddArgs */


/* _ R E C S */

static void _RECS(rec, x)
struct RECS *rec;
int	x;
{
    if (x != -1)
	fprintf(stderr, "x == %d\n", x);
    fprintf(stderr,"a = %d, b = %s, c = %d\n",
		rec->a, rec->b, rec->c);
    fprintf(stderr,"bits = %d %d %d %d, color = %d\n",
	rec->bits1, rec->bits2, rec->bits3,
	rec->bits4, rec->color);
    fflush(stderr);
} /* _RECS */
0707070001000312051004440000000000010000011602230454650113400001600000037437cdb/process.c /* $Header: process.c,v 5.41 86/07/25 12:53:11 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"
#include <ctype.h>

extern FILE * FpFSb();
extern char *gets();

export pPRR	v;	/* THE master global */
local pPRR	vprUserSet = prNil;
export pPRR	*vrgPr;
export int2	viprMax;	/* number of slots in process table */

local PRR	vaprDefault;	/* default, phony record for "v" to point at */
local SBT	vsbGrepFile = "/usr/tmp/cdbgrep";
local char	vchA = chNull;

SBT vmpPsSb[] = { "Nil",
		"No process",
		"Stopped",
		"Running",
		"Dying",
		"Forking",
		"Execing",
		"Continuing"
		};


/* I N I T   P R O C E S S   T A B L E */

export void InitProcessTable()
{
    int		ipr;
    FILE	*fp;
    SBT		sb;
    char	buffer[256];

    vrgPr = (pPRR *) malloc(viprMax * cbPRR);

    for (ipr = 0; ipr < viprMax; ipr++)
	vrgPr[ipr] = prNil;

    /* set up a phony process descriptor for us to point at */
    v = &vaprDefault;
    v->ipd = ipdNil;
    v->ifd = ifdNil;
    v->iln = ilnNil;
    v->slop = 0;
    v->rgFd = (pFDR) malloc(cbFDR);
    v->fnExec = fnNil;
    v->fnCore = fnNil;
    v->fnCdb = fnNil;
    v->hdr.ifdMax = 1;
} /* InitProcessTable */


/* S B   O P T I O N S   F   D E F A U L T */

export SBT SbOptionsFDefault(sbExec)
SBT	sbExec;
{
    int		i, cb;
    FILE	*fp;
    char	*sb, *sbEnd, sbBuffer[1024];
    static char	sbReturn[2048];

    /* look to see if there are default for this file */

    if (vsbDefaultFile == sbNil)
	return(sbNil);

    fp = FpFSb(vsbDefaultFile, "r");
    if (fp == NULL)
	UError("%s: %s.", vsbDefaultFile, SbFError(errno));

    for (i = 1; i <= 2; i++) {
	while (sb = fgets(sbBuffer, sizeof(sbBuffer), fp)) {
	    if (*sb == '#')	/* ignore comments */
		continue;
	    sbEnd = sb;
	    while (! isspace(*sbEnd))	/* skip over name */
		sbEnd++;
	    *sbEnd = chNull;	/* so we can do comparison */
	    if ( FSbCmp(sbExec, sb)
	       OR ((i == 2) AND (*sb == '*')) ) {
		/* found the name we are looking for */
		strcpy(sbReturn, sbEnd + 1);
		cb = strlen(sbReturn);
		sbReturn[cb-1] = chNull;	/* clip off "\n" */
		while (sb = fgets(sbBuffer, sizeof(sbBuffer), fp)) {
		    if (*sb == '#')	/* ignore comments */
			continue;
		    else if (*sb != '\t')
			break;	/* all done for this entry */
		    strcat(sbReturn, sb);
		    cb = strlen(sbReturn);
		    sbReturn[cb-1] = chNull;	/* clip off "\n" */
		} /* while */
		return(sbReturn);
	    } /* if */
	} /* while */
	fseek(fp, 0L, seekBegin);
	sbExec = strrchr(sbExec, '/');
	if ((sbExec == sbNil) OR (sbExec[1] == chNull))
	    break;
	sbExec++;	/* get past the '/' */
    } /* for */

    return(sbNil);
} /* SbOptionsFDefault */


/* S B   F   P S */

export SBT SbFPs(ps)
int2	ps;
{
    if ((ps < 0) OR (ps >= psMax))
	return("unknown");
    return(vmpPsSb[ps]);
} /* SbFPs */


/* L I S T   P R */

export void ListPr(prIn)
pPRR	prIn;
{
    int2	i, iMax;
    pPRR	pr;

    i = 0;
    iMax = viprMax;

    if (prIn != prNil) {
	i = IprFPr(prIn);
	iMax = i + 1;
    } /* if */

    printf("    #    PID   PPID  Status        CBEF Name and Arguments\n");
    for (; i < iMax; i++) {
	pr = vrgPr[i];
	if (pr != prNil) {
	    printf("%s%2d%7d%7d  %-13s %1d%1d%1d%1d %s %s\n",
		(pr == vprUserSet) ? ">> " : "   ",
		i, pr->pid, pr->pidParent, SbFPs(pr->ps),
		pr->fDebugChildren, !pr->fRemoveBpsOnFork,
		pr->fStopOnExec, pr->fStopOnFork,
		pr->sbExec, pr->sbArgsChild ? pr->sbArgsChild : "");
	} /* if */
    } /* for */
} /* ListPr */


/* R E A P   C H I L D R E N */

export void ReapChildren()
{
    int2	i;
    pPRR	pr;

    for (i=0; i < viprMax; i++) {
	if ((pr = vrgPr[i]) != prNil) {
	    if (pr->pid != pidNil) {
		if (pr->pidParent == vpidCdb) {
		    Ptrace(ptTerm, pr->pid, 0, 0);
		} else {
		    SetGlobalPr(pr);
		    if (pr->ps == psRunning) {
			SendSignal(2);
			Waiter(wtProcess, v->pid);
			v->sig = 0;	/* phony signal, don't pass it */
		    } /* if */
		    RemoveAllBp();
		    FreeProcess(pr);
		} /* if */
	    } /* if */
	} /* if */
    } /* for */
} /* ReapChildren */


/* P R	 F   F N */

export pPRR PrFFn(fn)
int2	fn;
{
    int2	i;

    for (i=0; i < viprMax; i++) {
	if ((vrgPr[i] != prNil)
	  AND (vrgPr[i]->fnComm == fn))
	    return(vrgPr[i]);
    } /* for */
    return(prNil);
} /* PrFFn */


/* I P R   F   P R */

export int2 IprFPr(pr)
pPRR	pr;
{
    int2	ipr;

    if (pr == prNil)
	Panic("IprFPr: nil pr.");

    for (ipr = 0; pr != vrgPr[ipr]; ipr++)
	;
    return(ipr);
} /* IprFPr */


/* P R	 F   I P R */

export pPRR PrFIpr(ipr)
int2	ipr;
{
    if ((ipr < 0) OR (ipr >= viprMax))
	return(prNil);
    return(vrgPr[ipr]);
} /* PrFPid */


/* P R	 F   S B */

export pPRR PrFSb(sb)
SBT	sb;
{
    int2	i;

    for (i=0; i < viprMax; i++) {
	if ((vrgPr[i] != prNil)
	  AND (FSbCmp(vrgPr[i]->sbName, sb)) )
	    return(vrgPr[i]);
    } /* for */
    return(prNil);
} /* PrFSb */


/* P R	 F   P I D */

export pPRR PrFPid(pid)
int2	pid;
{
    int2	i;

    for (i=0; i < viprMax; i++) {
	if ((vrgPr[i] != prNil)
	  AND (vrgPr[i]->pid == pid))
	    return(vrgPr[i]);
    } /* for */
    return(prNil);
} /* PrFPid */


/* S E T   G L O B A L	 P R */

export void SetGlobalPr(pr)
FAST	pPRR	pr;
{
    int4	ipr, ilnSave, ipdSave, ifdSave, slopSave;
    ADRT	adrSave;
    static pPRR	prSave = prNil;

    if (pr != prNil) {
	prSave = v;
    } else {
	if (prSave != prNil) {
	    pr = prSave;
	    prSave = prNil;
	} /* if */
	
	if (pr->sbExec == sbNil) {
	    for (ipr = 0; ipr < viprMax; ipr++) {
		if (vrgPr[ipr] != prNil) {
		    pr = vrgPr[ipr];
		    break;
		} /* if */
	    } /* for */
	    if (pr == prNil) {
		v = (prSave != prNil) ? prSave : &vaprDefault;
		vprUserSet = v;
		if (vcActive > 1)
		    SetPrompt("%s (%d) >", vsbDebugName, IprFPr(v));
		return;
	    } /* if */
	} /* if */
    } /* if */

    vprUserSet = v;
    if (v == pr)
	return; /* we are already set up */
    
    if (vcActive > 1)
	SetPrompt("%s (%d) >", vsbDebugName, IprFPr(pr));

    /* close currently open files of old global process */
    if (v != prNil) {
	if (v->fnCdb != fnNil) {
	    close(v->fnCdb);
	    v->fnCdb = fnNil;
	} /* if */
	if (v->fnExec != fnNil) {
	    close(v->fnExec);
	    v->fnExec = fnNil;
	} /* if */
	if (v->fnCore != fnNil) {
	    close(v->fnCore);
	    v->fnCore = fnNil;
	} /* if */
    } /* if */

    v = pr;
    vprUserSet = v;
    if (v == &vaprDefault)
	return;

    if ((v->fnCdb == fnNil) AND (v->sbCdb != sbNil))
	pr->fnCdb = open(pr->sbCdb, O_RDONLY);

    /* now we do a little dance to restore their viewing context */
    ifdSave = v->ifd;
    ipdSave = v->ipd;
    ilnSave = v->iln;
    slopSave = v->slop;
    adrSave = v->adrInst;
    v->ifd = ifdNil;	/* this forces reopen */
    if (ifdSave != ifdNil)
	OpenIfd(ifdSave);
    v->ipd = ipdSave;
    v->iln = ilnSave;
    v->slop = slopSave;
    v->adrInst = adrSave;
} /* SetGlobalPr */


/* P R	 F   A L L O C */

export pPRR PrFAlloc()
{
    int2	i;
    pPRR	pr;

    /* find a free process slot and initialize it. */

    for (i=0; i < viprMax; i++)
	if (vrgPr[i] == prNil)
	    break;
    if (i == viprMax)
	UError("Too many processes (> %d).", viprMax);

    /* First we ZERO EVERYTHING!!!!! */
    vrgPr[i] = (pPRR) calloc(1, cbPRR);	/* get a zeroed block */
    pr = vrgPr[i];
    pr->fnCdb = pr->fnComm = pr->fnExec = pr->fnCore = fnNil;
    pr->adrInit = pr->adrBreak = pr->adrCall = adrNil;
    pr->adrSb = pr->adrSbStart = pr->adrSbMax = adrNil;
    pr->adrStartLow = pr->adrStartHigh = adrNil;
    pr->adrText = pr->adrData = 0;
    pr->fStty = vfWindows;	/* if not windows, user must set himself */
    pr->as = asSuspended;
    pr->fAtSyscall = false;
    pr->fForkedProcess = false;
    pr->fDebugChildren = (viprMax > 1);
    return(pr);
} /* PrFAlloc */


/* D E A L L O C   P R */

export void DeallocPr(pr, fSaveLocals)
pPRR	pr;
FLAGT	fSaveLocals;
{
    if (v == pr)
	SetGlobalPr(vrgPr[0]);

    if (pr->pidParent == vpidCdb)
	/* We DON'T remove first level process records */
	return;

    vrgPr[IprFPr(pr)] = prNil;	/* clear our slot in the table */

    if (!pr->fForkedProcess) {
	if (pr->fnExec != fnNil)
	    close(pr->fnExec);
	if (pr->sbExec != sbNil)
	    free(pr->sbExec);

	if (pr->fnCdb != fnNil)
	    close(pr->fnCdb);
	if (pr->sbCdb != sbNil)
	    free(pr->sbCdb);

	if (pr->fnCore != fnNil)
	    close(pr->fnCore);
	if (pr->sbCore != sbNil)
	    free(pr->sbCore);

	/* free symbol table stuff */
	if (pr->isymCacheMax == pr->hdr.isymMax) {
	    /* it means we did it in a single alloc - semi- KLUDGE */
	    free(pr->symCache - pr->hdr.cbSymOffset);
	} else {
	    free(pr->symCache);
	    free(pr->lineCache);
	    free(pr->auxCache);
	    free(pr->sbCache);
	} /* if */

	free(pr->os->adrTty);
	free(pr->os);
    } /* if */

    /* free assertions, breakpoints, local variables and our DOT */
    /* these are always copied when we fork */
    if (pr->rgAd != 0)
	free(pr->rgAd);
    if (pr->rgBp != 0)
	free(pr->rgBp);
    if (pr->seDot != seNil)
	free(pr->seDot);
    if (pr->sbArgsChild != sbNil)
	free(pr->sbArgsChild);

    if (!fSaveLocals AND (pr->rgLv != 0))
	free(pr->rgLv);

    free(pr);
} /* DeallocPr */


/* P R   F   I N I T   P R */

export pPRR PrFInitPr(sbExec)
SBT	sbExec;
{
    char	sbOptions[2048];
    pPRR	pr;
    
    sbOptions[0] = chNull;
    AddOptions(sbOptions, vsbOptions, SbOptionsFDefault(sbExec), sbNil);

    pr = PrFAlloc();	/* get a process slot */
    pr->sbExec = SbFAlloc(sbExec);
    ApplyOptions(pr, sbOptions);
    InitPr(pr);
    return(pr);
} /* PrFInitPr */


/* I N I T   P R */

export void InitPr(pr)
pPRR	pr;
{
    int2	ipd, fnExec;
    int4	mtimeCdb, cbl;
    FLAGT	fTranslate;
    ADRT	adr;
    char	ch, *sb, sbCmd[200];
    SER		ase;
    pPRR	prSave;
    static FLAGT fFirstTime = true;

    prSave = v;
    v = pr;

    sb = SbFSearch(pr->sbExec, 5);
    if (sb == sbNil)
	UError(vsbFilename);

    fnExec = open(sb, O_RDONLY);
    if (fnExec < 0)
	UError("%s: %s.", sb, SbFError(errno));

    if (! FSbCmp(sb, pr->sbExec)) {
	printf("Using \"%s\" as executable.\n", sb);
	free(pr->sbExec);	/* get rid of old name */
	pr->sbExec = SbFAlloc(sb);
    } /* if */
    pr->fnExec = fnExec;
    pr->mtimeExec = AgeFFn(pr->fnExec);

    strcpy(sbCmd, pr->sbExec);	/* build file name for symbol table */
    strcat(sbCmd, ".cdb");
    pr->sbCdb = SbFAlloc(sbCmd);

    fTranslate = false;
    pr->fnCdb = open(pr->sbCdb, O_RDONLY);
    if (pr->fnCdb < 0) {
	fTranslate = true;
    } else if (pr->mtimeExec > AgeFFn(pr->fnCdb)) {
	fTranslate = true;
	close(pr->fnCdb);
    } else {
	/* check version stamp */
	if (read(pr->fnCdb, &(pr->hdr), cbHDRR) != cbHDRR)
	    Panic("Cannot read header of %s.", pr->sbCdb);
	if (pr->hdr.vstamp != CURRENT_VERSION) {
	    fTranslate = true;
	    close(pr->fnCdb);
	} /* if */
    } /* if */

    if (fTranslate) {	/* needs recreating for some reason */
	printf("Translating %s to %s ...", pr->sbExec, pr->sbCdb);
	fflush(stdout);

	/* Translate to the Hindi, thank you very much */
	sprintf(sbCmd, "cdbtrans %s", pr->sbExec);
	if (system(sbCmd) != 0) {
	    printf("\nTranslation failed\n");
	    exit(1);
	} /* if */
	pr->fnCdb = open(pr->sbCdb, O_RDONLY);
	mtimeCdb = AgeFFn(pr->fnCdb);

	printf("Done\n");

	if (read(pr->fnCdb, &(pr->hdr), cbHDRR) != cbHDRR)
	    Panic("Cannot read header of %s.", pr->sbCdb);
	if (pr->hdr.vstamp != CURRENT_VERSION) {
	    printf("\n\
Problem: The symbol table translator (\"cdbtrans\") that is invoked seems to\n\
be a different version than this debugger wants to work with.\n\
Please mention this problem to your system administrator.\n");
	    exit(1);
	} /* if */
    } /* if */

    pr->isymLo = pr->isymLim = 0;
    pr->iauxLo = pr->iauxLim = 0;
    pr->ilineLo = pr->ilineLim = 0;
    pr->issLo = pr->issLim = 0;
    vfCacheSymbols = true;	/* we do this by default */

    if (pr->isymCacheMax == 0) {
	/* then they want a total read of the ".cdb" file */
	cbl = CblFFn(pr->fnCdb);	/* get file size */
	adr = (ADRT) malloc((int)cbl);
	if (adr == 0) {
	    UError("Ran out of memory, please specify cache sizes.");
	    exit(1);
	} /* if */

	lseek(pr->fnCdb, 0L, seekBegin);	/* rewind to beginning */
	if (read(pr->fnCdb, (char *)adr, cbl) < 0)
	    Panic("Symbol table read failed: %s.", SbFError(errno));
	close(pr->fnCdb);
	pr->fnCdb = fnNil;

	pr->symCache = (pSYMR) (adr + pr->hdr.cbSymOffset);
	pr->isymLim = pr->isymCacheMax = pr->hdr.isymMax;

	pr->auxCache = (pAUXU) (adr + pr->hdr.cbAuxOffset);
	pr->iauxLim = pr->iauxCacheMax = pr->hdr.iauxMax;

	pr->lineCache = (pLINER) (adr + pr->hdr.cbLineOffset);
	pr->ilineLim = pr->ilineCacheMax = pr->hdr.ilineMax;

	pr->sbCache = (SBT) (adr + pr->hdr.cbSsOffset);
	pr->issLim = pr->issCacheMax = pr->hdr.issMax;

	pr->rgFd = (pFDR) (adr + pr->hdr.cbFdOffset);
	pr->rgPd = (pPDR) (adr + pr->hdr.cbPdOffset);
	pr->rgTd = (pTDR) (adr + pr->hdr.cbTdOffset);
	vfCacheSymbols = false;
    } else {
	Panic("Peter hasn't finished the non-virtual code yet...");

	pr->isymLim = pr->isymCacheMax;
	pr->symCache = (pSYMR) malloc(pr->isymCacheMax*cbSYMR);

	if (pr->ilineCacheMax == 0)
	    pr->ilineCacheMax = pr->hdr.ilineMax;
	pr->ilineLim = pr->ilineCacheMax;
	pr->lineCache = (pLINER) malloc(pr->ilineCacheMax*cbLINER);

	if (pr->iauxCacheMax == 0)
	    pr->iauxCacheMax = pr->hdr.iauxMax;
	pr->iauxLim = pr->iauxCacheMax;
	pr->auxCache = (pAUXU) malloc(pr->iauxCacheMax*cbAUXU);

	if (pr->issCacheMax == 0)
	    pr->issCacheMax = pr->hdr.issMax;
	pr->issLim = pr->issCacheMax;
	pr->sbCache = malloc(pr->issCacheMax);

	/* force cache init's */
	LineFIline(0);
	SymFIsym(0);
	AuxFIaux(0);
	SbFIss(0);
    } /* if */

    if (pr->rgFd[1].adr != 0)
	pr->rgFd[0].adr = 0; /* to prevent inifinite loop in IfdFAdr */

    pr->cpu = (pCPUR) malloc(cbCPUR);
    InitCpu(pr->cpu);	/* fill in cpu goodies */
    InitOs(pr);		/* perform OS specific initializations */

    if (pr->fnCore != fnNil) {
	ReadPc();
	SetCntx();	/* to make process globals be correct */
    } /* if */

    ipd = IpdFName(v->sbInit);
    if (ipd == ipdNil) {
	/* no luck finding specified procedure */
	pr->adrInit = pr->hdr.entrypoint;
    } else {
	pr->adrInit = AdrFPreamble(pr->rgPd[ipd].adr);
    } /* if */

    /* set up procedure-call-from-the-command-line addresses */
    ipd = IpdFName("_cdbend");
    if (ipd != ipdNil) {
	/* we do the file lookup to set the correct context for label search */
	pr->ifd = IfdFAdr(pr->rgPd[ipd].adr);
	pr->adrBreak = AdrFLabel("cdbBreak");
	if (pr->adrBreak == adrNil) {
	    pr->adrCall = pr->adrBreak = pr->rgPd[ipd].adr;
        } else {
            pr->adrCall = AdrFLabel("cdbCall");
        } /* if */

	/* set up string space */
        ase = *vseInt;
        ase.asym.iss = IssFSb("_cdbbuffer");
        pr->adrSb = pr->adrSbStart = (FGlobal(&ase)) ? ase.asym.value : adrNil;
        ase.asym.iss = IssFSb("_cdbbufMax");
        pr->adrSbMax = (FGlobal(&ase)) ? ase.asym.value : adrNil;
    } /* if */
    if ((pr->adrCall == adrNil) AND (ADR_CALL == 0))
		/* we will just use a random address */
	pr->adrBreak = pr->adrCall = pr->adrInit;

    /* set up string-save-buuffer addresses */
    ase = *vseInt;
    ase.asym.iss = IssFSb("_cdbbuffer");
    pr->adrSb = pr->adrSbStart = (FGlobal(&ase)) ? ase.asym.value : adrNil;
    ase.asym.iss = IssFSb("_cdbbufMax");
    pr->adrSbMax = (FGlobal(&ase)) ? ase.asym.value : adrNil;

    pr->ipdFork = IpdFName("fork");
    pr->ifd = ifdNil;
    pr->ipd = ipdNil;
    pr->iln = 0;
    pr->slop = 0;
    pr->ps = psNoChild;
    pr->pid = pidNil;
    pr->pidParent = vpidCdb;	/* will be changed if different */
    pr->seDot = (pSER) malloc(cbSER);	/* create our own stack element */

    if (pr->sbComm != sbNil)
	InitComm(pr);

    if (fFirstTime) {
	/* We haven't done master RC file yet - do it */
	sb = getenv("HOME");
	if (sb != sbNil) {
	    sprintf(sbCmd, "%s/.cdbrc", sb);
	    PlaybackFile(sbCmd);
	} /* if */
	fFirstTime = false;
    } /* if i*/

    /* Do any rc file that may exist for this executable */
    sprintf(sbCmd, "%s.rc", pr->sbExec);
    fnExec = open(sbCmd, O_RDONLY);
    if ((fnExec >= 0) AND (pr->mtimeExec < AgeFFn(fnExec)))
	PlaybackFile(sbCmd);

    v = prSave;
} /* InitPr */
0707070001000312061004440000000000010000011604120454650113400001100000000050cdb/t1.c main()
{
    printf("%*g\n", 0, 5.6);
}
0707070001000312071004440000000000010000011604210454650113400002100000017321cdb/waitSingle.c /* $Header$ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <signal.h>
#include <errno.h>

#include "cdb.h"

export int2	viprMax = 1;	/* we only allow room for one process */
export FLAGT	vfAttach = true;


/* P P I D   F   P I D */

export PpidFPid(pid)
int	pid;
{
    int		ppid;

    ppid = Ptrace(ptPpid, pid, 0, 0);
    if (ppid == -1)
	UError("Attempting to find parent of %d: %s.", pid, SbFError(errno));
    return(ppid);
} /* PpidFPid */


/* S B   E X E C   F   P I D */

export SBT SbExecFPid(pid)
int	pid;
{
    static char	sbCmd[257];

    Ptrace(ptCmdName, pid, sbCmd, 0);
    return(sbCmd);
} /* SbExecFPid */


/* F R E E   P R O C E S S */

export void FreeProcess(pr)
pPRR	pr;
{
    if (pr == prNil)
	return;

    SetGlobalPr(pr);

    RemoveAllBp(true);
    Ptrace(ptReleaseChild, pr->pid, (char *) 1, 0);
    if (pr->pidParent != vpidCdb) {
	DeallocPr(pr, false);
    } else {
	pr->pid = pidNil;
	pr->ps = psNoChild;
    } /* if */

    SetGlobalPr(prNil);
} /* FreeProcess */


/* C O P Y   P R */

export void CopyPr(pr1, pr2)
pPRR	pr1, pr2;
{
    int2	cb;

    /* Make pr1 identical to pr2 */

    *pr1 = *pr2;	/* this gets all of the normal fields */

    /* KLUDGE - need to create CopyOs, CopyCpu */

    /* KLUDGE - need to check ALL fields and make our own copies
     * so that DeallocPr is free to throw everything away.
     */
    
    pr1->fForkedProcess = true;

    /* setup tables */
    cb = pr1->ibpMax * cbBPR;	/* breakpoints */
    pr1->rgBp = (pBPR) malloc(cb);
    MoveBytes(pr1->rgBp, pr2->rgBp, cb);

    cb = pr1->ilvMax * cbSER;	/* local variables */
    pr1->rgLv = (pSER) malloc(cb);
    MoveBytes(pr1->rgLv, pr2->rgLv, cb);

    cb = pr1->iadMax * cbADR;	/* assertions */
    pr1->rgAd = (pADR) malloc(cb);
    MoveBytes(pr1->rgAd, pr2->rgAd, cb);

    pr1->seDot = (pSER)malloc(cbSER);
    pr1->sbArgsChild = SbFAlloc(pr2->sbArgsChild);
} /* CopyPr */


/* P R   F O R K */

export pPRR PrFFork(pidChild, fAttached)
int2	pidChild;
FLAGT	fAttached;
{
    int		pidParent;
    SBT		sbExec;
    pPRR	pr, prParent;

    /* A new child has come into the world.
     * Register it with the draft board.
     */

    /* First we have to find out who the parent is */
    pidParent = PpidFPid(pidChild);
    prParent = PrFPid(pidParent);

    if (fAttached AND (prParent != prNil)) {
	/* We know the family, but the kid has been
	 * away from home for a long time.
	 * Check his id at the door */
	sbExec = SbExecFPid(pidChild);
	if (! FSbCmp(sbExec, prParent->sbExec))
	    prParent = prNil;
    } /* if */

    if (prParent == prNil) {

	/* A stranger in a strange land */
	pr = PrFInitPr( SbExecFPid(pidChild) );

    } else {

	/* A friend of the family */
	pr = PrFAlloc();
	CopyPr(pr, prParent);

	if (pr->fRemoveBpsOnFork) {
	    SetGlobalPr(pr);
	    RemoveAllBp(true);
	    SetGlobalPr(prNil);
	} /* if */

	pr->fnComm = pr->fnCdb = pr->fnExec = pr->fnCore = fnNil;

    } /* if */

    pr->pid = pidChild;
    pr->pidParent = pidParent;
    pr->ps = psFork;
    if (vfNotify) {
	printf("New process\n");
	ListPr(pr);
    } /* if */

    ++vcActive;		/* count of Active proceesses */
    return(pr);
} /* PrFFork */


/* P R   F   A T T A C H   P R O C E S S */

export pPRR PrFAttachProcess(pid)
int2	pid;
{
    int		ret;
    SBT		sb;
    pPRR	pr, prSave;

    ret = Ptrace(ptMultiChild, pid, 0, 0);	/* make him ours */
    if (ret == -1)
	UError("Unable to attach to process %d: %s.", pid, SbFError(errno));

    /* Chicken and Egg problem: We can't call Waiter, because we
     * don't have a process record because we don't have the process
     * name because we haven't waited on the process yet.
     * Sooooooo, we send SIGINT, wait a couple of seconds and
     * hope that the process has stopped.
     */
    kill(pid, SIGINT);
    sleep(2);

    pr = PrFFork(pid, true);
    pr->ps = psStopped;

    prSave = v;
    SetGlobalPr(pr);
    ReadPc();
    SetCntx();
    SetViewPosition(pr->acntx.pc);
    v->pgrpSave = getpgrp(pid);
    /* setpgrp(pid, getpgrp(0)); /* make him the same process group as us */
    return(pr);
} /* PrFAttachProcess */


/* P R   F   E X E C */

export pPRR PrFExec(pr)
pPRR	pr;
{
    extern char * gets();
    int2	pidParent, pidChild = pr->pid;
    char	*sbExec, sbBuf[200];
    FLAGT	fStopOnExec;		/* stop immediately after exec */
    FLAGT	fStopOnFork;		/* stop BOTH process after fork */
    FLAGT	fRemoveBpsOnFork;	/* child does NOT get parent's BPs */
    FLAGT	fDebugChildren;		/* indicates we WANT the kids */
    pSER	rgLv;
    FLAGT	fDoingSingle;
    
    pidParent = pr->pidParent;	/* Remember Mom */

    sbExec = SbExecFPid(pr->pid);	/* Find out who we are */
    if (sbExec == sbNil) {
	printf("Unable to determine name of program for process #%d\n",
	    pidChild);
	printf("Please type name of executable: ");
	sbExec = gets(sbBuf);
	if ((sbExec == sbNil) OR (*sbExec == chNull)) {
	    Ptrace(ptReleaseChild, pidChild, (char *) 1, 0);
	    UError("Aborting debugging of process #%d.", pidChild);
	} /* if */
    } /* if */

    fStopOnExec = pr->fStopOnExec;
    fStopOnFork = pr->fStopOnFork;
    fRemoveBpsOnFork = pr->fRemoveBpsOnFork;
    fDebugChildren = pr->fDebugChildren;
    fDoingSingle = pr->fDoingSingle;
    rgLv = pr->rgLv;

    DeallocPr(pr, true);		/* kill old identity */

#if 0
    pr = PrFAlloc();		/* a clean slate */
    pr->sbExec = SbFAlloc(sbExec);	/* our new name */
    pr->sbCore = sbNil;
    pr->isymCacheMax = 0;
    InitPr(pr);
#endif
    pr = PrFInitPr(sbExec);
    pr->pid = pidChild;
    pr->pidParent = pidParent;

    pr->fStopOnExec = fStopOnExec;
    pr->fStopOnFork = fStopOnFork;
    pr->fRemoveBpsOnFork = fRemoveBpsOnFork;
    pr->fDebugChildren = fDebugChildren;
    pr->fDoingSingle = fDoingSingle;
    pr->rgLv = rgLv;
    pr->ps = psRunning;

    SetGlobalPr(pr);
    ReadPc();
    SetCntx();
#if 0
    SetGlobalPr(prNil);
#endif 0

    if (vfNotify) {
	printf("Process exec'ed\n");
	ListPr(pr);
    } /* if */
    return(pr);
} /* PrFExec */

#ifdef BILLB
int DeadChild, InGetchar;

/*
	This routine catches the child died signal and sets a flag to 
	that effect. If there is potential that the process is about
	to enter getchar after checking the DeadChild flag then an alarm 
	is started to prevent the hang.
*/
CatchChildSig()
{
	signal(SIGCLD,CatchChildSig);
	DeadChild++;
	if (InGetchar) alarm(1);
}
#endif BILLB





/* W A I T E R */

export void Waiter(wt, pid)
int2	wt, pid;
{
    extern char * gets();
    extern char * MouseGets();
    int		status;
    int2	waitReturn;
    SBT		sb;

    /* Wait for something to happen in a
     * SINGLE PROCESS environment
     */

    while (1) {
	switch (wt) {
	    case wtTty:
	    case wtAnything:
		vsbGet[0] = vsbGet[1] = vsbGet[2] = vsbGet[3] = chNull;
		vsbGet = gets(vsbGet);
		return;
		/* NOTREACHED */
		break;

	    case wtProcess:
		if (v->ps == psStopped)
		    return;	/* process is already stopped and analyzed */
		/* else fall through */

	    case wtAnyProcess:
		pid = v->pid;
		v->fQuiet = false;

		signal(SIGINT, SIG_IGN);	/* ignore INT */

		waitReturn = Wait(&status);

		if (v->fStty)
		    SetMyTty();
		signal(SIGINT, Fixer);	/* reconnect to the Fixer routine */
		v->sig = 0;	/* for safety reasons */

		if (waitReturn == -1) {
		    if (errno == EINTR) {
			printf("PANIC! received signal: %d (%s).\n",
			    status>>8, SbFSignal(status>>8));
			/* what do we do here?? */
			exit(1);
		    } else {	/* some sort of error occurred */
			perror(vsbDebugName);
			exit(1);
		    } /* if */
		} /* if */

		v->status = status;
		AnalyzeStop();
		if (v->ps == psContinue) {
		    RunProcess(ptResume, psRunning, false);
		    break;
		} else if (v->ps == psRunning) {
		    continue;
		} else {
		    return; /* either a normal bp OR a signal of some sort */
		} /* if */
	} /*switch */
    } /* while */
} /* Waiter */
0707070001000312101004440000000000010000011605110454650113400001500000002555cdb/cdbend.c /* $Header: cdbend.c,v 6.1 86/08/05 17:44:27 peter Exp $ */

/* This program is an unpublished work fully protected by the
 * United States Copyright Laws and is considered a TRADE SECRET
 * belonging to Third Eye Software, Inc.
 */

/* This module is placed in /usr/lib/libcdb.a */

#include "config.h"

#if (CPU == VAX) || (CPU == CCI632)
    /* Yes, they are identical (weird!.......) */
#define DONE
/* if you need more space for string constants, increase size of __buffer */
char	_cdbbuffer[1000];
char	_cdbbufMax;	/* used only to size the buffer */

_cdbend()
{
    /* SetCallProc sets r1 == numarg and r0 == the procedure address */
    asm("cdbCall:  calls	r1,(r0)");
    asm("cdbBreak: bpt");
}
#endif /* (CPU == VAX) || (CPU == CCI632) */

#if (CPU == PY9X)
#define DONE
/* if you need more space for string constants, increase size of __buffer */
char	_cdbbuffer[1000];
char	_cdbbufMax;	/* used only to size the buffer */

_cdbend()
{
    /* SetCallProc sets r1 == numarg and r0 == the procedure address */
    asm("cdbCall:  call	(tr13)");
    asm("cdbBreak: bpt");
}
#endif /* (CPU == PY9X) */

#ifndef DONE
/* if you need more space for string constants, increase size of _cdbbuffer */
char	_cdbbuffer[1000];
char	_cdbbufMax;	/* used only to size the buffer */

_cdbend()
{
    int	x;
    x = 1;	/* just something to hang a breakpoint on - see proc.c */
}
#endif /* DONE */
0707070001000312111004440000000000010000011601000454650113400001300000025231cdb/expr.c /* $Header: expr.c,v 6.3 86/09/04 17:37:03 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This module reads and write `se's.  All data used by the expression
 * evaluators eventually came from here.
 */

#include "cdb.h"

export int	vtkLast;	/* tk last seen */
export SBT	vsbLex;		/* pointer to yylex string buffer */
export SER	vase;		/* communicate back to the world */
export pSER	vseArgs;	/* communicate to DoProc */
    /*
     * NOTES: 1) vseArgs could be a parameter. 2) the args are at
     * the TOP of the parsing stack and may need their own space eventually.
     */

#define Mask(width) (~(~0L<<width))	/* generate a bunch of 1111111's */

/* The way we screw up a bandit is to AND, OR and XOR values into
 * their addresses and return values.  We then rotate the diddle value
 * N to the left giving a reasonably unpredictable cycle of
 * "sometimes good and sometimes garbage" values.
 */
/* Rotate a long to the left by cnt bits */
#define Rotate(along, cnt) \
	(along = (along << (cnt)) | ((along >> (32 - (cnt))) & Mask(cnt)))

int4	vXor = 0x8000L;		/* set to 0 for good guys */
int4	vAnd = 0xEFFFFFFFL;	/* set to -1 for good guys */
int4	vOr = 0x400L;		/* set to 0 for good guys */


/* Y Y L E X */

export int yylex()
{
    int		tk;

    /* The following provides an intermediat interface between yyparse
     * and the current scanner.
     */

    if (vtkLast == -1) { /* new invocation of yyparse */
	tk = vtk;
    } else {
	tk = TkNext();/* we're always one character behind */
    } /* if */

    /* the last time through we must return an EOF to the parser so
     * that it can end gracefully
     */

    if (vtk == tkNil) {
	vtkLast = -1;
	return (-1);
    } else {
	vtkLast = tk;
	if ((tk == tkStr) || (tk == tkStrConstant))
	    vsbLex = SbSafeFSb(vsbTok);
	return(tk);
    } /* if */
} /* yylex */


/* C O N V E R T   F L O A T */

export void ConvertFloat(se, fFromHostToRemote)
pSER	se;
FLAGT	fFromHostToRemote;
{
    int		bt;

    bt = se->ti.bt;
} /* ConvertFloat */


/* E X T R A C T   B I T S */

export long ExtractBits(x, pos, width)
int4	x;
int2	pos, width;
{
    int2	bitSex = vcpuHost->bitSex;
    int4	mask = Mask(width);

    if (bitSex == bitSexLittle) {
	x = (x >> pos) & mask;
    } else if (bitSex == bitSexBig) {
	x = (x >> ((v->cpu->cbInt * 8) - pos - width)) & mask;
    } else {
	Panic("Unknown bit-sex code (%d).", bitSex);
    } /* if */
    return(x);
} /* ExtractBits */


/* S E T   B I T S */

export long SetBits(x, pos, width, val)
int4	x;
int2	pos, width;
int4	val;
{
    int2	shift, bitSex = vcpuHost->bitSex;
    int4	mask = Mask(width);

    if (bitSex == bitSexLittle) {
	x &= ~(mask << pos); x |= (mask & val) << pos;
    } else if (bitSex == bitSexBig) {
	shift = (v->cpu->cbInt * 8) - pos - width;
	x &= ~ (mask << shift);
	x |= (mask & val) << shift;
    } else {
	Panic("Unknown bit-sex code (%d).", bitSex);
    } /* if */
    return(x);
} /* SetBits */


/* A D R   F   S E */

export ADRT AdrFSe(se)
FAST pSER	se;
{
    int2	bt;

    bt = (se->ti.tq0 == tqNil) ? se->ti.bt : btAdr;
    switch (bt) {
			/* ValFSe and WriteVal will limit to 8 bytes */
	default:	return((ADRT)&(se->val.valDouble));

	case btAdr:	return((ADRT)&(se->val.valAdr));
	case btChar:	return((ADRT)&(se->val.valChar));
	case btUChar:	return((ADRT)&(se->val.valUChar));
	case btShort:	return((ADRT)&(se->val.valShort));
	case btUShort:	return((ADRT)&(se->val.valUShort));
	case btInt:	return((ADRT)&(se->val.valInt));
	case btUInt:	return((ADRT)&(se->val.valUInt));
	case btLong:	return((ADRT)&(se->val.valLong));
	case btULong:	return((ADRT)&(se->val.valULong));
	case btFloat:	return((ADRT)&(se->val.valFloat));
	case btDouble:	return((ADRT)&(se->val.valDouble));
	case btLogical:	return((ADRT)&(se->val.valUInt));
	case btComplex:	return((ADRT)&(se->val.valComplex));
    } /* switch */
} /* AdrFSe */


/* V A L   F   S E */

export VALU ValFSe(se)
FAST pSER	se;
{
    int2	sc, tq, offset, cb, bt;
    int4	along;
    FAST ADRT	adrSrc, adrDest;
    pSER	seT;

    tq = se->ti.tq0;

    if ((tq == tqProc) OR (tq == tqArray)) {
	/* these two have the value already setup */
	return(se->val);
    } /* if */

    if (se->ti.fConstant)
	return(se->val); /* it was a constant - ergo, it IS its own value */
    
    sc = se->asym.sc;
    adrSrc = se->asym.value;
    adrDest = AdrFSe(se);
    bt = se->ti.bt;

    cb = CbFSe(se);
    if (cb > 8)
	cb = 8; /* this routine is not designed for more than a double */
	/* KLUDGE */

    /* we read things based on the sc - storage class */

    switch (sc) {
	default:
	    if (cb <= 0)
		UError("Expression garbaged.");
	    /* just normal data */
	    ReadData(adrDest, adrSrc, cb);
	    break;

	case scFloatRegister:	/* float register variable */
	case scRegister:	/* register variable */
	    se->val = ValFReg(se, cb);
	    break;

	case scRegImage:	/* saved register*/
	    if ((v->cpu->byteSex == byteSexBig) AND (cb < v->cpu->cbRegister))
		adrSrc += (v->cpu->cbRegister - cb);
	    ReadData(adrDest, adrSrc, cb);
	    break;

	case scUserStruct:	/* random magic value in USER struct */
	    se->val = ValFUser(se);
	    break;

	case scCdbSystem:	/* debugger System variable */
	    /* a system variable */
	    MoveBytes(adrDest, adrSrc, cb);
	    break;

	case scCdbLocal:	/* debugger local */
	    /* a debugger 'local' variable */
	    seT = (pSER) adrSrc;
	    adrSrc = AdrFSe(seT);
	    MoveBytes(adrDest, adrSrc, cb);
	    break;

	case scBits:		/* bit field */
	    adrSrc += (se->bitsOffset / 8); /* lowest byte containing bits */
	    offset = se->bitsOffset % 8;
	    cb = (se->bitsWidth + offset + 7) / 8; /* # bytes we need to read */
	    along = 0;
	    ReadData((ADRT)&along, adrSrc, cb);
	    along = ExtractBits(along, offset, se->bitsWidth);
	    if ((bt == btChar) OR (bt == btShort)
	       OR (bt == btInt) OR (bt == btLong)) {
		/* we need to sign extend the bit field */
		if (ExtractBits(along, se->bitsWidth - 1, 1) != 0)
		    along |= (~0 << se->bitsWidth);
	    } /* if */
	    se->val.valULong = along;
    } /* switch */

    if ( ((bt == btFloat) OR (bt == btDouble))
       AND (v->cpu->fpc != vcpuHost->fpc))
	ConvertFloat(se, false);

    /* diddle things to screw up bandits */
    Rotate(vXor, se->val.valAdr & 1);
    se->val.valAdr ^= vXor;
    return(se->val);
} /* ValFSe */


/* W R I T E   V A L */

export void WriteVal(seDest, seSrc)
FAST pSER	seDest, seSrc;
{
    int2	offset, cb, bt;
    int4	along;
    ADRT	adrDest, adrSrc;
    pSER	seT;
    VALU	valTemp;

    /* This routine ASSUMES that the types are compatible. */

    if ((seDest->ti.fConstant) OR (seDest->ti.tq0 == tqArray))
	UError("You may not assign to a constant.");

    /* diddle things to screw up bandits */
    Rotate(vOr, seSrc->val.valAdr & 3);
    seSrc->val.valAdr |= vOr;
    seDest->asym.value &= vAnd;
    Rotate(vAnd, seSrc->val.valAdr & 7);

    adrDest = seDest->asym.value;
    adrSrc = AdrFSe(seSrc);
    cb = CbFSe(seDest);
    bt = seSrc->ti.bt;

    /* fix floating point format if different */
    valTemp = seSrc->val;	/* save for later */
    if ( ((bt == btFloat) OR (bt == btDouble))
       AND (v->cpu->fpc != vcpuHost->fpc) )
	ConvertFloat(seSrc, true);

    switch (seDest->asym.sc) {
	default:
	    if (cb <= 0)
		UError("Expression garbaged.");
	    WriteData(adrDest, adrSrc, cb);
	    break;

	case scFloatRegister:	/* float register variable */
	case scRegister:	/* register variaable */
	    StoreReg(seDest, seSrc);	/* cpu dependent */
	    break;

	case scRegImage:	/* saved register*/
	    if ((v->cpu->byteSex == byteSexBig) AND (cb < v->cpu->cbRegister))
		adrDest += (v->cpu->cbRegister - cb);
	    WriteData(adrDest, adrSrc, cb);
	    break;

	case scUserStruct:	/* random magic value in USER struct */
	    StoreUser(seDest, seSrc);
	    break;

	case scCdbSystem: 	/* debugger System variable */
	    MoveBytes(adrDest, adrSrc, cb);
	    break;

	case scCdbLocal: /* debugger local */
	    seT = (pSER) adrDest;
	    adrDest = AdrFSe(seT); /* this is the TRUE effective address */
	    MoveBytes(adrDest, adrSrc, cb);
	    seDest->val = seSrc->val;	/* keep a local copy */
	    break;

	case scBits:	/* bit field */
	    offset = seDest->bitsOffset % 8;
	    cb = (seDest->bitsWidth + offset + 7) / 8; /* # bytes we read */
	    adrDest += (seDest->bitsOffset / 8); /* lowest byte of bits */
	    along = 0;
	    ReadData((ADRT)&along, adrDest, cb); /* get current value */
	    Coerce(vseCnULong, seSrc);
	    along = SetBits(along, offset,
			seDest->bitsWidth, seSrc->val.valULong);
	    WriteData(adrDest, (ADRT)&along, cb);
	    break;
    } /* switch */

    seSrc->val.valDouble = valTemp.valDouble;	/* restore from temp */
} /* WriteVal */


/* A D R   F   S T O R E */

export ADRT AdrFStore(sb, cb)
SBT	sb;
int2	cb;
{
    ADRT	adr;

    /* this routine stores data in the CHILD's address space.
     * this is mostly useful for passing strings as arguements to
     * procedure calls from the command line.
     */
    if (cb & 1) /* if it's odd, force to even */
	cb++;	/* force to word boundary */

    if (v->adrSb == adrNil)
	UError("Process is not loaded with \"-lcdb\".");

    /* will it fit? */
    if (v->adrSb + cb >= v->adrSbMax) {
	/* no, we will go back and use the buffer over again */
	v->adrSb = v->adrSbStart;
	if (v->adrSb + cb >= v->adrSbMax)
	    UError("Item is too big. There is only room for %d bytes.\n\
See the man pages re: cdbend.c.", v->adrSbMax - v->adrSb);
    } /* if */

    adr = v->adrSb;
    v->adrSb += cb;	/* advance to next free byte */
    WriteData(adr, (ADRT)sb, cb);
    return(adr);
} /* AdrFStore */


/* S E	 F   E X P R */

export pSER SeFExpr(se)
pSER	se;
{
    int2	lc;
    SBT		sb;

    if (vtk == tkNil) {
	if (se != seNil)
	    *se = *vseInit;
	return(seNil);
    } /* if */

    /* globals for yacc */
    vseArgs = (pSER) -1;
    vtkLast = -1;	/* indicates initial entry into yylex */
    vfInFalse= 0;

    lc = v->lc;
    if (lc == lcAuto) {
	if (v->ifd == ifdNil) {
	    lc = vlcDefault;
	} else {
	    sb = SbFIss(v->rgFd[v->ifd].iss);
	    switch (sb[strlen(sb)-1]) {
		default:	lc = vlcDefault;	break;
		case 'c':	lc = lcC;	break;
		case 'f':	lc = lcFortran;	break;
	    } /* switch */
	} /* if */
    } /* if */

    switch (lc) {
	default:

#ifdef LANG_C
	case lcC:
	    cgramyparse();
	    break;
#endif /* LANG_C */

#if 0
#ifdef LANG_FORTRAN
	case lcFortran:
	    fgramyparse();
	    break;
#endif /* LANG_FORTRAN */
#endif /* 0 */

    } /* switch */

    if (se != seNil) {
	*se = vase;
	return(se);
    } else {
	return(&vase);
    } /* if */
} /* SeFExpr */


/* L O N G   F	 E X P R */

export int4 LongFExpr(seRet, tk)
pSER	seRet;
TKE	tk;
{
    if (tk == tkNil)
	TkNext();
    SeFExpr(seRet);
    if (seRet->asym.st == stNil)
	return(0L);

    Coerce(vseCnLong, seRet);
    return(seRet->val.valLong);
} /* LongFExpr */
0707070001000312121004440000000000010000011602240454650113400001300000006765cdb/math.c /* $Header: math.c,v 6.1 86/08/05 17:44:50 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"

/*
 * This file is a giant macro generating procedures that do all
 * operators on all types.
 */

#define DoCase(OP, XX) seRet->val.XX = se1->val.XX OP se2->val.XX; break
#define DoNormal(OP)	switch (bt) {\
	case btChar:	DoCase(OP,valChar);\
	case btUChar:	DoCase(OP,valUChar);\
	case btShort:	DoCase(OP,valShort);\
	case btUShort:	DoCase(OP,valUShort);\
	case btInt:	DoCase(OP,valInt);\
	case btEnum: case btUInt:	DoCase(OP,valUInt);\
	case btLong:	DoCase(OP,valLong);\
	case btULong:	DoCase(OP,valULong);\
	case btFloat:	DoCase(OP,valFloat);\
	case btDouble:	DoCase(OP,valDouble);\
	case btAdr:	DoCase(OP,valAdr);\
    } /* switch */

#define DoException(OP)	   switch (bt) {\
	case btAdr:	DoCase(OP,valAdr);\
	case btChar:	DoCase(OP,valChar);\
	case btUChar:	DoCase(OP,valUChar);\
	case btShort:	DoCase(OP,valShort);\
	case btUShort:	DoCase(OP,valUShort);\
	case btInt:	DoCase(OP,valInt);\
	case btEnum: case btUInt:	DoCase(OP,valUInt);\
	case btLong:	DoCase(OP,valLong);\
	case btULong:	DoCase(OP,valULong);\
	case btFloat:	UError ("Float not allowed in 'OP'."); break;\
	case btDouble:	UError ("Double not allowed in 'OP'."); break;\
    } /* switch */

#define DoProc(Name, Do, op) void Name(seRet, se1, se2)\
	pSER	seRet, se1, se2;\
	{\
	    int2 bt;\
	    ResFOps(seRet, se1, se2);\
	    bt = (seRet->ti.tq0 != tqNil ? btAdr : seRet->ti.bt);\
	    Do(op)\
	    if (bt == btAdr) {\
		seRet->ti.fConstant = true; \
		seRet->asym.value = seRet->val.valAdr; \
	    }\
	}


/* We have to expand MUL because Sun STILL hasn't fixed their compiler! */

/* M U L */

void Mul(seRet, se1, se2)
pSER	seRet, se1, se2;
{
#define OP *
    int2 bt;
    ResFOps(seRet, se1, se2);
    
    bt = (seRet->ti.tq0 != tqNil ? btAdr : seRet->ti.bt);
    switch (bt) {
	case btChar:
#if (MFG != SUN)
	/* The Sun compiler goes into an infinite loop on expressions of
	 * the form "charA = charB * charC".  So we just fall through
	 * into the unsigned char code.  This will probably not cause
	 * anybody to lose any sleep.
	 */
	DoCase(OP,valChar);
#endif /* (MFG != SUN) */
	case btUChar:	DoCase(OP,valUChar);
	case btShort:	DoCase(OP,valShort);
	case btUShort:	DoCase(OP,valUShort);
	case btInt:	DoCase(OP,valInt);
	case btEnum: case btUInt:	DoCase(OP,valUInt);
	case btLong:	DoCase(OP,valLong);
	case btULong:	DoCase(OP,valULong);
	case btFloat:	DoCase(OP,valFloat);
	case btDouble:	DoCase(OP,valDouble);
	case btAdr:	DoCase(OP,valAdr);
    } /* switch */
    if (bt == btAdr)
	seRet->ti.fConstant = true;
} /* Mul */

DoProc(Div, DoNormal,/)
DoProc(Add, DoNormal,+)
DoProc(Subtract, DoNormal,-)
DoProc(LOr, DoNormal,||)
DoProc(LAnd, DoNormal,&&)
DoProc(LT, DoNormal,<)
DoProc(LE, DoNormal,<=)
DoProc(GT, DoNormal,>)
DoProc(GE, DoNormal,>=)
DoProc(EQ, DoNormal,==)
DoProc(NE, DoNormal,!=)

DoProc(RShift, DoException,>>)
DoProc(LShift, DoException,<<)
DoProc(BOr, DoException,|)
DoProc(BAnd, DoException,&)
DoProc(XOr, DoException,^)
DoProc(Mod, DoException,%)

/* now for UNARY operators */

#undef DoCase
#define DoCase(op,XX) seRet->val.XX = op se->val.XX; break

#undef DoProc
#define DoProc(Name, Do, op) void Name(seRet, se)\
	pSER	seRet, se;\
	{\
	    int2 bt;\
	    GetOrig(se);\
	    Coerce(se, seRet);\
	    seRet->asym.st = stExpr;\
	    seRet->ti.fConstant |= (seRet->ti.tq0 == tqNil);\
	    bt = (seRet->ti.tq0 != tqNil ? btAdr : seRet->ti.bt);\
	    Do(op)\
	}

DoProc(Bang, DoException,!)
DoProc(Tilda, DoException,~)
0707070001000312131004440000000000010000011602600454650113400001500000007434cdb/single.c /* $Header: single.c,v 5.15 86/04/28 13:30:07 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"


/* A D R   F   R E T U R N   P C */

local ADRT AdrFReturnPc()
{
    CNTXR	acntx;

    /* given the current context, return the return address */

    acntx = v->acntx;
    NextFrame(&acntx);
    if (acntx.fEndOfStack)
	return(adrNil);

    return(acntx.pc); /* get return */
} /* AdrFReturnPc */


/* S I N G L E   S T E P */

export void SingleStep(cmd, fQuiet)
CMDE	cmd;
FLAGT	fQuiet;
{
    int2	fmt, ipd, ipdBefore, iln, slop;
    ADRT	adr;
    FLAGT	fBigStep, fMachineStep;
    pBPR	bp;

    fBigStep = (cmd == cmdMachProc) OR (cmd == cmdLineProc);
    fMachineStep = (cmd == cmdMachSingle) OR (cmd == cmdMachProc);
    fmt = (fQuiet) ? fmtNil :
	(fmtProc + fmtLn + fmtLine + fmtEol + (fMachineStep ? fmtInst : 0));
    slop = -1; /* just to get us into loop first time */

    if (v->pid == pidNil) {
	/* we have no process, create one! */
	v->fDoingSingle = fMachineStep;
	NewChild(v->sbArgsChild, !fMachineStep);
	SetViewPosition(v->acntx.pc);
	ShowViewPosition(fmt);
	return;
    } /* if */

    /* The idea here is to loop until we get someplace interesting. This
     * usually means at an address that translates EXACTLY (slop == 0) to
     * a known line number.
     */

    while (slop != 0) {
        if (FAtCall(v->acntx.pc)) { /* at proc call */
	    /* follow the call - this way we don't have to deal with N ways
	     * to compute callee's address.
	     */
	    ipdBefore = IpdFAdr(v->acntx.pc);

	    RunProcess(ptSingle, psRunning, true);

	    if (v->bp != bpNil)
		return;	/* a REAL breakpoint */

	    ipd = IpdFAdr(v->acntx.pc);
	    if (ipdBefore != ipd) {
		/* The way we get here is if we were at a BREAK that
		 * was exactly on a proc call.  RunProcess stepped
		 * us off the call instruction so that it could
		 * replace the break.
		 */
	    } /* if */

	    if (!fBigStep) {
		if (fMachineStep)
		    break;
		if (v->rgPd[ipd].iline != 0) {
		    /* we have source for it */
		    adr = AdrFPreamble(v->acntx.pc); /* allows for intro code */
		    if (adr != v->acntx.pc) {
			/* temp BP after intro code */
			bp = BpFAddBp(adr, 0, sbNil, 0);
			if (bp->inst == 0)
			    InstallBp(bp);
			if (ipd == v->ipdFork)
			    SaveForkBp(bp);
			RunProcess(ptResume, psRunning, true);
		    } /* if */
		    break; /* go to the stuff at end of this procedure */
		} /* if */
		/* if we get here, then the proc call goes to the
		 * twilight zone - fall into fBigStep code
		 */
	    } /* if */

	    adr = RetFSp(v->acntx.sp);
	    if (!fMachineStep)
		adr = AdrFStackFix(adr);
	    bp = BpFAddBp(adr, 0, sbNil, 0);
	    if (bp->inst == 0)
		InstallBp(bp);
	    if (ipd == v->ipdFork)
		SaveForkBp(bp);
	    RunProcess(ptResume, psRunning, true);

	} else {	/* NOT at a procedure call */

	    RunProcess(ptSingle, psRunning, true);
	    if (v->bp != bpNil)
		return; /* a REAL breakpoint, so it MUST be kosher! */

	    if (!fMachineStep AND (v->rgPd[IpdFAdr(v->acntx.pc)].iline == 0) ) {
		/* They want to statement step in STARTING in non-symboled code.
		 * The only way to get here is to machine step into
		 * non-symboled code, or to get a signal of some sort.
		 * So we cross our fingers that the frame pointer
		 * is kosher and do a temporary uplevel break.
		 */
		adr = AdrFReturnPc(); /* get return */
		if (adr != adrNil)
		    BpFAddBp(adr, 0, sbNil, 0);
		RunProcess(ptResume, psRunning, true);
		slop = -1;
	    } /* if */
	} /* if */

	if ( (v->bp != bpNil) OR (v->pid == pidNil) )
	    return;
	if (fMachineStep)
	    break;
	IpdIlnFAdr(&iln, &slop, v->acntx.pc);
    } /* while */

    if ((v->pid != pidNil) AND (v->bp == bpNil)) {
	SetViewPosition(v->acntx.pc);
	ShowViewPosition(fmt);
    } /* if */

    v->fMachineStep = fMachineStep;
} /* SingleStep */
0707070001000312141004440000000000010000011603140454650113400001600000040763cdb/xptrace.c /* $Header: xptrace.c,v 6.1 86/08/05 17:46:51 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <errno.h>
#include <sgtty.h>
#include <signal.h>
#include <syscall.h>
#include <sys/time.h>

#include "cdb.h"
#include "xptrace.h"

extern FILE *fdopen();
extern void Transmit();

int	vfnTx, vfnRx;
int	vlevelSave = 0;
FLAGT	vfTest = false;
FLAGT	vfExecKludge = false;

int	vsignal, vpidServer;
char	vsbRemoteDevice[100];	/* name of device connected to remote */

char	_sbRx[cbMsgMax];	/* buffer for received messages */
SBT	vsbRx;		/* points to next character in receive buffer */
#define cbRx sizeof(_sbRx)
char	vsbTxLast[cbMsgMax]; /* copy of last transmisson */
int	vpidLast;	/* pid of last process we received message from */



/* V A L   F   P S B   */

long ValFPsb(psb)
SBT	*psb;
{
    int		x = 0;
    char	ch, *sb = *psb;

    /* this routine eats a hex number from a string and advances
     * the string pointer to the next character AFTER the first
     * non-hex character.  E.g if we start with "1234|abcd",
     * we will return the integer value 0x1234 and leave the string
     * pointing to the 'a'.
     */

#define FHex(ch) (((ch >='0') AND (ch <= '9')) OR ((ch >= 'a') AND (ch <= 'f')))

    if ((sb == sbNil) OR (*sb == chNull))
	return(0);

    while (true) {
	ch = *sb++;
	if (! FHex(ch))
	    break;
	x = (x * 16) + ((ch <= '9') ? (ch - '0') : ((ch - 'a') + 10));
    } /* while */
    *psb = sb;
    return(x);
} /* ValFPsb */


/* S B   F   T X   M S G */

local void SbFTxMsg(sbTx)
SBT	sbTx;
{
    int		pid, msg, pt, value, count;
    long	adr, adr2;
    char	*sb, sbName[cbMsgMax], sbArgs[cbMsgMax];

    printf("TxHost: %s", sbTx);

    if (v->fCommDebug AND (v->debuglevel >= 100)) {
	sb = sbTx;
	msg = ValFPsb(&sb);	/* get message number */
	pid = ValFPsb(&sb);	/* get process id */

	switch (msg) {
	    default:
		printf("msg = %d, pid = %d\n", msg, pid);
		break;

	    case msgPtrace:
		pt = ValFPsb(&sb);
		adr = ValFPsb(&sb);
		value = ValFPsb(&sb);

		switch (pt) {
		    default:    printf("Unknown Ptrace request: %d", pt);
				break;

		    case  ptReadI:	printf("Read Text");	break;
		    case  ptReadD:	printf("Read Data");	break;
		    case  ptWriteI:	printf("Write Text");	break;
		    case  ptWriteD:	printf("Write Data");	break;
		    case  ptReadUser:	printf("Read User");	break;
		    case  ptWriteUser:	printf("Write User");	break;
		    case  ptSingle:	printf("Single Step");	break;
		    case  ptResume:	printf("****** Resume ******");	break;
		    case  ptTerm:	printf("Terminate");	break;
		} /* switch */
		printf("	pid: %d	adr: %#x	value: %d (%#x)\n",
			    pid, adr, value, value);
		break;

	    case msgWait:
		    printf("******* Waiting for process %d ********\n", pid);
		    break;

	    case msgExec:
		sscanf(sb, "%[^|]|%[^\n]", sbName, sbArgs);
		printf("Exec pid %d as %s with args \"%s\"\n",	
			pid, sbName, sbArgs);
		break;

	    case msgInput:
		printf("Input from host: \"%s\"", sb);
		break;

	    case msgRtoH:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		printf("Remote to Host: pid: %d	from: %#x  count %d\n",
				adr, count);
		break;

	    case msgHtoR:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		printf("Host to Remote: pid: %d	start at: %#x  count %d\n",
				adr, count);
		break;

	    case msgMove:
		adr = ValFPsb(&sb);
		adr2 = ValFPsb(&sb);
		count = ValFPsb(&sb);
		printf("Block Move: pid: %d  dest: %#x  src: %#x, count %d\n",
				adr, adr2, count);
		break;

	} /* switch */
    } /*  if */
} /* SbFTxMsg */


/* R E A D   S B */

export int ReadSb(fn, sb, cb, sbMatch)
int	fn, cb;
FAST SBT	sb;
SBT	sbMatch;
{
    FAST int	i, ret;
    int		cbMatch;
    char	ch;

    cbMatch = (sbMatch == sbNil) ? cb+1 : strlen(sbMatch);
    i = 0;
    while (--cb > 0) {
	ret = read(fn, &ch, 1);
	*sb++ = ch;
	i++;
	if (ret == 0)
	    return(0);
	if (ret < 0)
	    SysPanic("Read from Remote on %d.", fn);
	if (ch == '\n')
	    break;
	if ((i >= cbMatch)
	   AND (ch == sbMatch[cbMatch-1])) {
	    *sb = chNull;
	    if (FTailCmp(sbMatch, sb))
		return(i);
	} /* if */
    } /* while */
    *sb = chNull;
    return(i);
} /* ReadSb */


/* S E T   R E M O T E   L E V E L */

local void SetRemoteLevel(level)
int	level;
{
    char	sbBuf[100];

    sprintf(sbBuf, "%x|%x|%x\n", msgLevel, v->pid, level);
    vlevelSave = level;
    Transmit(sbBuf);
    RetFReply();
} /* SetRemoteLevel */


/* T R A N S M I T */

export void Transmit(sbTx)
SBT	sbTx;
{
    int		cbTx, cb;

    /* Transmit the string */
    if (vlevelSave != v->debuglevel)
	SetRemoteLevel(v->debuglevel);

    if (sbTx != vsbTxLast)
	strcpy(vsbTxLast, sbTx);	/* save for re-transmission */
    
    cbTx = strlen(sbTx);

    if (v->fCommDebug)
	SbFTxMsg(sbTx);

    if (v->fnComm <= 2)
	Panic("Transmit - v->fnComm: %d.", v->fnComm);

    vcsRemote = csWriting;
    cb = write((vfTest) ? vfnTx : v->fnComm, sbTx, cbTx);
    vcsRemote = csWriteDone;

    if (cb != cbTx)
	SysPanic("Transmit: %d bytes to go, %d went.", cbTx, cb);
} /* Transmit */


/* R E C E I V E */

export void Receive(fNewPid, sbMatch)
FLAGT	fNewPid;
SBT	sbMatch;
{
    int		cb, cRetry, status, pid;

    cRetry = 0;
    while (true) {
	vsbRx = _sbRx;

	vcsRemote = csReading;
	cb = ReadSb((vfTest) ? vfnRx : v->fnComm, vsbRx, cbRx, sbMatch);
	vcsRemote = csNil;
	if (vfInterruptPending)
	    Fixer();

	if (v->fCommDebug)
	    printf("RxHost: %s", vsbRx);

	status = 0;
	if (sscanf(vsbRx, "%x", &status) != 1)
	    Panic("bad target status %s", _sbRx);
	if ((vsbRx = strchr(vsbRx, chDelim)) == sbNil) /* skip status */
	    Panic("missing separator 1 %s", _sbRx);
	vsbRx++;

	if (sscanf(vsbRx, "%x", &pid) != 1)
	    Panic("bad target pid %s", _sbRx);
	if ((vsbRx = strchr(vsbRx, chDelim)) == sbNil) /* skip process id */
	    Panic("missing separator 2 %s", _sbRx);
	vsbRx++;

	if ((pid != v->pid) AND !fNewPid) {
	    /* This is from a different process than we wanted. */
	    Panic("Wanted data from %d, got it from %d", v->pid, pid);
	} /* if */

	switch (status) {
	    default:
		errno = status;	/* "OK" or error for caller */
		return;

	    case statusNewPid:
		v->pid = pid;	/* KLUDGE - This may not be correct */
		errno = 0;
		return;

	    case statusRetry:
		cRetry++;
		if (cRetry >= cRetryMax)
		    Panic("Excessive retries, Last Transmit was:\n%s\n",
			vsbTxLast);
		Transmit(vsbTxLast);
		break;

	    case statusPrint:
		/* this is output for OUR screen */
		/* we do NOT treat this as a response to our last command */
		printf("<%d> %s", pid, vsbRx);
		break;
	} /* switch */
    } /* while */
} /* Receive */


/* R E T   F   R E P L Y */

local int RetFReply()
{
    int		ret;

    /* Get response from remote.
     * ASSUME that there is a simple numerical reply.
     */

    Receive(false, sbNil);	/* get a string from remote */
    if (sscanf(vsbRx, "%x", &ret) != 1)
	Panic("Bad reply from target: %s", _sbRx);
    return(ret);
} /* RetFReply */


/* P T R A C E */

export int Ptrace(pt, pid, adr, value)
int	pt, pid;
char	*adr;
int	value;
{
    int		ret;
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return( ptrace(pt, pid, adr, value) );

    switch (pt) {
	case ptReadI:
	case ptReadD:
	case ptReadUser:
	    sprintf(sbPt, "%x|%x|%x|%x|%x\n", msgPtrace, pid, pt, adr, value);
	    Transmit(sbPt);	/* send a message to junior */
	    ret = RetFReply();
#ifdef notdef
/* this would be needed in a BINARY protocol */
	    if (v->cpu->byteSex != vcpuHost ->byteSex)
		Translate(&ret, sizeof(ret));
#endif
	    return(ret);
	    break;

	case ptWriteI:
	case ptWriteD:
	case ptWriteUser:
#ifdef notdef
/* this would be needed in a BINARY protocol */
	    if (v->cpu->byteSex != vcpuHost ->byteSex)
		Translate(&value, sizeof(value));
#endif
	    /* and fall through */

	case ptResume:
	case ptTerm:
	case ptSingle:
	    sprintf(sbPt, "%x|%x|%x|%x|%x\n", msgPtrace, pid, pt, adr, value);
	    Transmit(sbPt);	/* send a message to junior */
	    return( RetFReply() );
	    break;

    } /* switch */

    Transmit(sbPt);	/* send a message to junior */
    return( RetFReply() );
} /* Ptrace */


/* S E N D   S I G N A L */

export int SendSignal(sig)
int2	sig;
{
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return(kill(v->pid, sig));

    sprintf(sbPt, "%x|%x|%x\n", msgSignal, v->pid, sig);
    Transmit(sbPt);
    /* we DON'T wait for a reply since this is happening at
     * interrupt level.  The target should stop and return
     * status indictaing reciept of this signal.  This assumes
     * that the target has not stopped all by itself prior
     * to the signal.
     */
} /* SendSignal */


/* W A I T */

export int Wait(pstatus)
int	*pstatus;
{
    int		ret;
    char	sbTemp[20];

    if (v->fnComm == fnNil)
	return(wait(pstatus));

    /* here we do what is necessary to *look like* "wait (2)" */

    if (vfExecKludge) {
	*pstatus = (v->os->sigTrap << 8) + 0x7f;
	vfExecKludge = false;
	return(v->pid);
    } /* if */

    sprintf(sbTemp, "%x|%x\n", msgWait, v->pid);
    Transmit(sbTemp);
    vfInWait = true;
    ret = RetFReply();
    vfInWait = false;

#if 1
    *pstatus = ret;
#else
    switch (vsignal) {
	default:
	    Panic("Unexpected signal: %d", vsignal);

	case SIGTRAP:
	case SIGBUS:
	    *pstatus = (vsignal << 8) + 0x7f;
    } /* switch */
#endif

    return(v->pid);	/* KLUDGE - no good for multi-process remote */
} /* Wait */


/* C R E A T E   T A R G E T */

export void CreateTarget()
{
    int		ret;
    char	sbBuf[200];

    if (v->fnComm == fnNil) {
	OsCreateTarget();	/* cause a NATIVE process to be born */
	return;
    } /* if */

    if (vfTest) {
	close(v->fnExec);
	v->fnExec = fnNil;
    } /* if */

    v->pid = 1;
    sprintf(sbBuf, "%x|%x|%s|%s\n", msgExec, v->pid, v->sbExec, v->sbArgsChild);
    Transmit(sbBuf);

    Receive(true, sbNil);	/* get a string from remote */
    if (sscanf(vsbRx, "%x", &ret) != 1)
	Panic("Bad reply from target: %s", _sbRx);

    vfExecKludge = false;
    if (ret == -1) {
	vfExecKludge = true;
    } else if (ret > 0) {
	dprint(1, ("Bad exec in target.  Remote reports error: %d", ret));
	errno = ret;
    } /* if */
} /* CreateTarget */


/* X   B L O C K   M O V E */

export void XBlockMove(pid, adrDest, adrSrc, cb)
int	pid;
ADRT	adrDest, adrSrc;
int	cb;
{
    /* transfer a block WITHIN the remote machine */
    char	sbBuf[cbMsgMax];

    sprintf(sbBuf, "%x|%x|%x|%x|%x\n", msgMove, v->pid, adrDest, adrSrc, cb);
    Transmit(sbBuf);
    RetFReply();
} /* XBlockMove */


/* X   B L O C K   T R A N S F E R */

export void XBlockTransfer(pid, adrDest, adrSrc, cbIn, fTx)
int	pid;
ADRT	adrDest, adrSrc;
int	cbIn;
FLAGT	fTx;
{
    char	ch1, ch2, sbBuf[cbMsgMax];
    SBT		sbTx, sbRx, sbSrc, sbDest, sbT;
    short	val, cb, cbThisTime, cbSave;
    ADRT	adrDestIn;

    if (fTx) {
	/* write FROM host TO remote */
#ifdef notdef
/* this would be needed in a BINARY protocol */
	if (v->cpu->byteSex != vcpuHost ->byteSex)
	    Translate(adrSrc, cbIn);
#endif
    } else {
	/* read FROM remote TO host */
	adrDestIn = adrDest;
	cbSave = cbIn;
    } /* if */
    sbSrc = (SBT) adrSrc;

    while (cbIn >= 0) {
	int rcb;
	cb = Min(cbIn, (cbMsgMax-24)/2);
	if (fTx) {
	    cbThisTime = cb;
	    cbIn -= cb;
	    /* write FROM host TO remote */
	    sprintf(sbBuf, "%x|%x|%x|%x|", msgHtoR, pid, adrDest, cb);
	    sbTx = sbBuf + strlen(sbBuf);
	    while (cb--) {
		val = (*sbSrc & 0xf0) >> 4;
		*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
		val = *sbSrc++ & 0x0f;
		*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
	    } /* while */
	    *sbTx = '\n';
	    Transmit(sbBuf);
	    RetFReply();
	} else {
	    /* read FROM remote TO host */
	    sprintf(sbBuf, "%x|%x|%x|%x\n", msgRtoH, pid, adrSrc, cb);
	    Transmit(sbBuf);
	    Receive(false, sbNil);
	    if (sscanf(vsbRx, "%x", &rcb) != 1)
	    	Panic("bad target byte count %s", _sbRx);
	    if ((vsbRx = strchr(vsbRx, chDelim)) == sbNil) /* skip count */
	        Panic("missing separator 3 %s", _sbRx);
	    vsbRx++;
	    if ( rcb > cb )
		Panic("too many bytes transferred R to H");
	    cbThisTime = rcb;
	    cbIn -= rcb;
	    sbDest = (SBT) adrDest;
	    while (rcb--) {
		ch1 = *vsbRx++;
		ch2 = *vsbRx++;
		val = ((ch1 - ((ch1 > '9') ? ('a'-10) : '0')) << 4)
		    | (ch2 - ((ch2 > '9') ? ('a'-10) : '0'));
		if ((val & ~0x0ff) != 0 )
		    Panic("bad block transfer R to H");
		*sbDest++ = val;
	    } /* while */
	} /* if */
	adrSrc += cbThisTime;
	adrDest += cbThisTime;
    } /* while */

#ifdef notdef
/* this would be needed in a BINARY protocol */
    if ((!fTx) AND (v->cpu->byteSex != vcpuHost ->byteSex))
	Translate(adrDestIn, cbSave);
#endif
} /* XBlockTransfer */


#ifdef notdef
/* this would be needed in a BINARY protocol */
/* T R A N S L A T E */

local void Translate(adr, cb)
ADRT	adr;
int	cb;
{
    union STUFFU {
	long	lng;
	struct { short	shortLo, shortHi; } shorts;
	struct { char	chLoLo, chLoHi, chHiLo, chHiHi; } chars;
	}	stuffIn, stuffOut;

    /* given a pointer to a value, perform the motion between
     * the host and child.  This routine, and the people who
     * call it, assume that this translation is symmetrical.
     * We only perform this on data of 2 or 4 bytes.
     */

    if (cb == 2) {

	stuffIn.shorts.shortLo = *((short *)adr);
	stuffOut.chars.chLoLo = stuffIn.chars.chLoHi;
	stuffOut.chars.chLoHi = stuffIn.chars.chLoLo;
	*((short *)adr) = stuffOut.shorts.shortLo;

    } else if (cb == 4) {

	stuffIn.lng = *((long *)adr);
	stuffOut.chars.chLoLo = stuffIn.chars.chHiHi;
	stuffOut.chars.chLoHi = stuffIn.chars.chHiLo;
	stuffOut.chars.chHiLo = stuffIn.chars.chLoHi;
	stuffOut.chars.chHiHi = stuffIn.chars.chLoLo;
	*((long *)adr) = stuffOut.lng;

    } /* if */
} /* Translate */
#endif


/* C L O S E   C O M M */

export void CloseComm()
{
    int		ipr;
    char	sbBuf[cbMsgMax];

    if (v->fnComm != fnNil) {
	sprintf(sbBuf, "%x|%x\n", msgQuit, 0);
	Transmit(sbBuf);	/* send a message to junior */
    } /* if */

    if (vfTest) {
	close(vfnTx);
	close(vfnRx);
	kill(vpidServer, 9);
    } else {
	close(v->fnComm);
    } /* if */
} /* CloseComm */


/* I N I T   C O M M */

export void InitComm(pr)
pPRR	pr;
{
    int		rgFnPtoC[2], rgFnCtoP[2];
    char	sbTx[10], sbRx[10], sbLevel[10];

    if (FSbCmp(pr->sbComm, "TEST")) {

	vfTest = true;
	if (pipe(rgFnPtoC) != 0)
	    Panic("Failed on pipe open: %s", SbFError(errno));

	if (pipe(rgFnCtoP) != 0)
	    Panic("Failed on pipe open: %s", SbFError(errno));

	/* pipes - write 1, read 0 */

	if (vpidServer = fork()) {

	    /* parent */
	    v->fnComm = vfnTx = rgFnPtoC[1];
	    vfnRx = rgFnCtoP[0];
	    close(rgFnCtoP[1]);
	    close(rgFnPtoC[0]);

	} else {

	    /* child */
	    if (v->fnExec != fnNil)
		close(v->fnExec);
	    if (v->fnCore != fnNil)
		close(v->fnCore);
	    close(rgFnCtoP[0]);
	    close(rgFnPtoC[1]);

	    close(0);
	    dup(rgFnPtoC[0]);
	    close(rgFnPtoC[0]);

	    close(1);
	    dup(rgFnCtoP[1]);
	    close(rgFnCtoP[1]);

	    execl("remote", "remote", 0);

	    printf("Execl of remote failed: %d %d\n", sbTx, sbRx);
	    exit(1);

	} /* if */

    } else {

#if (! ANY_BSD)
	WARNING: This code is BSD specific.  Similar things may done for
	System V.
#endif

	struct sgttyb ttyarg;
	static int bauds[]={ 300, 600, 1200, 1800, 2400, 4800, 9600};
	static int bcode[]={B300,B600,B1200,B1800,B2400,B4800,B9600};
	int n;
	char sbLevel[20];

	vfTest = false;
	v->fnComm = open(pr->sbComm, O_RDWR, 0);
	if (v->fnComm == -1)
	    UError("Cannot open %s: %s.", pr->sbComm, SbFError(errno));

	n = OTTYDISC;
	ioctl(v->fnComm, TIOCSETD, &n);	/* set old line discipline */

	/* set baud rates, etc */

	ttyarg.sg_ispeed = 0;
	for (n = 0; n < sizeof(bauds)/sizeof(int); n++) {
	    if (bauds[n] == v->iBaud)
	        ttyarg.sg_ispeed = ttyarg.sg_ospeed = bcode[n];
	} /* for */

	if (ttyarg.sg_ispeed == 0 ) {
	    if (v->iBaud != 0) {
		fprintf(stderr, "Cannot set %d baud\n", v->iBaud);
		exit(1);
	    } /* if */
	    ttyarg.sg_ispeed = ttyarg.sg_ospeed = B9600;
	} /* if */

	ttyarg.sg_erase = 0177;
	ttyarg.sg_kill = 025;
	ttyarg.sg_flags = EVENP + ODDP + CBREAK;
	ioctl(v->fnComm, TIOCSETP, &ttyarg);
	
    /* here we do any necessary initial handshaking...... */

#if LOCAL_COMM_INIT
	InitShakeMTOS(v->fnComm);
#endif LOCAL_COMM_INIT

	/* flush any echo or info from starting target */
	sleep(1);
	ioctl(v->fnComm, TIOCFLUSH, NULL);	/* flush input */

	ttyarg.sg_flags &= ~CBREAK;		/* return to cooked */
	ioctl(v->fnComm, TIOCSETP, &ttyarg);

#if 0
    /* this might be useful if the UNIX kernel supports it */
    /* the bk(4) line discipline is supposed to be better for fast stuff */
	n = NETLDISC;
	ioctl(v->fnComm, TIOCSETD, &n);
#endif 0

    } /* if */

    /* Test the link and (as a side effect) set debuglevel */

    vlevelSave = v->debuglevel;
    sprintf(sbLevel, "%x|%x|%x\n", msgLevel, v->pid, v->debuglevel);
    Transmit(sbLevel);
    Receive(false, sbNil);
} /* InitComm */
0707070001000312151004440000000000010000011605120454650113500001400000050744cdb/files.c /* $Header: files.c,v 6.1 86/09/14 20:23:43 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This module does the source file open/closes and the source line
 * printing, etc.
 */

#include "cdb.h"
#include <errno.h>

FILE	*vfpSrc;	/* currently open source file */
export char vsbFilename[256];	/* full name OR error message from SbFSearch */


/* S B   F   A L L O C */

export SBT SbFAlloc(sb)
SBT	sb;
{
    SBT		sbNew;
    
    /* Given a string, allocate new space and copy it into it */

    if (sb == sbNil)
	return(sbNil);

    sbNew = (SBT) malloc(strlen(sb) + 1);
    strcpy(sbNew, sb);
    return(sbNew);
} /* SbFAlloc */


/* A D D   D I R */

export void AddDir(pr, sbDir)
pPRR	pr;
SBT	sbDir;
{
    /* Add an alternate directory to the list */
#define increment	10

    if (pr->idirMac >= pr->idirMax) {
	pr->idirMax += increment;
	if (pr->idirMax == increment) {
	    pr->rgSbDir = (SBT *) malloc(pr->idirMax * sizeof(SBT));
	} else {
	    pr->rgSbDir = (SBT *)realloc(pr->rgSbDir, pr->idirMax*sizeof(SBT));
	} /* if */
	if (pr->rgSbDir == 0)
	    Panic("Ran out of memory.");
    } /* if */

    pr->rgSbDir[pr->idirMac] = SbFAlloc(sbDir);
    pr->idirMac++;
} /* AddDir */


/* L I S T   D I R */

export void ListDir()
{
    FAST int	i;

    /* Show alternate directories */

    printf("Source directories - search order\n");
    for (i = 0; i < v->idirMac; i++)
	printf("%2d  %s\n", i, v->rgSbDir[i]);
    printf("%2d  %s\n", i, ".");
} /* ListDir */


/* S B   F   B A S E */

export SBT SbFBase(sb)
SBT sb;
{
    FAST SBT	sbTemp;

    sbTemp = strrchr(sb, '/');
    if (sbTemp != sbNil)
	return(SbFAlloc(sbTemp + 1));
    return(sb);
} /* SbFBase */


/* E D I T   F I L E */

export void EditFile(ifd, iln)
int2	ifd, iln;
{
    int2	cb;
    SBT		sbFile;
    char	sbCopy[256], sbCmd[356];
    pFDR	fd;

    /* Edit the given file, starting at line iln */

    fd = v->rgFd + ifd;
    sbFile = SbFIss(fd->iss);	/* get the current name */

    /* see if they are allowed to do this */
    if (access(sbFile, 4+2) == -1)
	/* that didn't work - tell them why */
	UError("%s: %s.", SbFError(errno), sbFile);

    cb = strlen(sbFile);
    strcpy(sbCopy, sbFile);

    if (fd->fEdited) {

	/* file has already been edited, don't copy it again */
	sbCopy[cb-1] = chNull;	/* cut off the # */
	printf("%s has already been edited, going to NEW file\n", sbCopy);

    } else if (ifd != ifdTemp) {

	/* cp file to sbFile# */
	sprintf(sbCmd, "cp %s %s#", sbFile, sbFile);
	if (vfpSrc != NULL) {
	    fclose(vfpSrc); /* close source file */
	    vfpSrc = NULL;
	} /* if */
	system(sbCmd);	/* do the copy */
	strcat(sbCopy, "#");
	fd->iss = IssFSb(SbFAlloc(sbCopy));
	fd->issShort = IssFSb(SbFBase(sbCopy));
	fd->fEdited = true;
	if (fd->rgLn != 0) {
	    free(fd->rgLn);
	    fd->rgLn = 0;
	} /* if */

	v->ifd = ifdNil;
	OpenIfd(ifd);	/* force re-open to new file name */

	sbCopy[strlen(sbCopy)-1] = chNull;	/* cut off the # */
    } /* if */

    /* goto vi at correct line number */
    sprintf(sbCmd, "vi +%d %s", iln, sbCopy);
    CallShell(sbCmd);
    v->iln = iln;
} /* EditFile */


/* S B   F   S E A R C H */

export SBT SbFSearch(sbFile, permissions)
SBT	sbFile;
int2	permissions;
{
    int		i, result, errnoSave;
    FLAGT	fFullPath;
    char	sbTemp[256], sbError[256];;

    /* Find the named file. If there are alternate directories,
     * try them in order until we succeed.
     */

    errnoSave = 0;
    sbTemp[0] = chNull;
    result = -1;

    fFullPath = (sbFile[0] == '/');

    if (! fFullPath) {
	if (sbFile[0] == '.') {
	    /* it starts with a dot - try a pure access */
	    result = access(sbFile, permissions);
	    if (result != -1) {
		strcpy(vsbFilename, sbFile);
		return(vsbFilename);
	    } else if (errno != ENOENT) {
		errnoSave = errno;
		strcpy(sbError, sbFile);
	    } /* if */
	} /* if */

	for (i = 0; i < v->idirMac; i++) {
	    /* slap the directory name on the front */
	    if (FSbCmp(v->rgSbDir, ".")) {
		strcpy(sbTemp, sbFile);
	    } else {
		strcpy(sbTemp, v->rgSbDir[i]);
		strcat(sbTemp, "/");
		strcat(sbTemp, sbFile);
	    } /* if */

	    /* try to open it */
	    result = access(sbTemp, permissions);
	    if (result != -1) {
		/* we found something interesting */
		strcpy(vsbFilename, sbTemp);
		return(vsbFilename);
	    } /* if */
	    if ((errnoSave == 0) AND (errno != ENOENT)) {
		errnoSave = errno;
		strcpy(sbError, sbTemp);
	    } /* if */
	} /* for */
    } /* if */

    /* if we get here either a) it is a full path name
     * or b) we could not find it in one of the alternate directories.
     * So we try using exactly the name they gave us.
     */
    result = access(sbFile, permissions);
    if (result != -1) {
	strcpy(vsbFilename, sbFile);
	return(vsbFilename);
    } else if (errnoSave == 0) {
	errnoSave = errno;
	strcpy(sbError, sbFile);
    } /* if */

    sprintf(vsbFilename, "%s: %s", sbError, SbFError(errnoSave));
    return(sbNil);
} /* SbFSearch */


/* F P   F   S B */

FILE *FpFSb(sbFile, sbFlags)
SBT	sbFile, sbFlags;
{
    int		i;
    SBT		sb;
    FILE	*fp;

    /* Open the named file. If there are alternate directories,
     * try them in order until we succeed.
     */

    sb = SbFSearch(sbFile, 04);
    if (sb == sbNil)
	return(NULL);

    fp = fopen(sb, sbFlags);
    if (fp == NULL)
	sprintf(vsbFilename, "%s: %s", sb, SbFError(errno));
    else
	strcpy(sbFile, vsbFilename);
    return(fp);
} /* FpFSb */


/* S E T   R G   L N */

local void SetRgLn(ifdIn, fp)
int2	ifdIn;
FILE	*fp;
{
    int2	cbNew, ifd, iln, ilnMac;
    uint4	*rgLn;
    char	buf[cbLineMax];
    pFDR	fdT, fd = v->rgFd + ifdIn;

    /* Create the line index array for the given file.
     * We make two passes - the first to size the array
     * and the second to fill it.
     */

    if (fd->rgLn != 0)
	return;	/* it's already there */

    /* count the lines */
    iln = 0;
    rewind(fp);
    while (fgets(buf, cbLineMax, fp) != NULL)
	iln++;
    iln++;	/* this array is 1 based, not zero */

    cbNew = iln * sizeof(uint4);
    rgLn = (uint4 *) malloc(cbNew);  /* get enough space for line array */

    if (rgLn == 0) {	/* allocation failed */
	/* we just walk down the list, releasing space */
	fdT = v->rgFd;

	for (ifd = 0; ifd < v->hdr.ifdMax; fdT++, ifd++) {
	    if (fdT->rgLn != 0) {
		free(fdT->rgLn);	/* throw it away */
		fdT->rgLn = 0;
		rgLn = (uint4 *) malloc(cbNew);  /* try again */
		if (rgLn != 0)
		    break;	/* NOW it fits! */
	    } /* if */
	} /* for */

	if (ifd >= v->hdr.ifdMax)
	    Panic("Ran out of memory in SetRgLn.");
    } /* if */

    fd->ilnMac = iln;
    fd->rgLn = rgLn;

    rewind(fp);	/* once more, from the top */
    ilnMac = iln;
    for (iln = 1; iln < ilnMac; iln++) {
	rgLn[iln] = ftell(fp);
	if (fgets(buf, cbLineMax, fp) == NULL)
	    break;
    } /* for */
} /* SetRgLn */


/* I P D   F   N A M E */

export int IpdFName(sbProc)
FAST SBT	sbProc;
{
    FAST int2	ipd, ipdMax, ipdNextFile;

    /* Map a procedure name to an ipd */

    if ((v->ipd != ipdNil)
       AND (FSbCmp(SbFIpd(v->ipd), sbProc)) )
	return(v->ipd);

    ipdNextFile = (v->ifd == v->hdr.ifdMax - 1) ?
			v->hdr.ipdMax : v->rgFd[v->ifd+1].ipd;

    /* first we check for this name in CURRENT file - i.e. check for statics */
    ipdMax = ipdNextFile;
    for (ipd = v->rgFd[v->ifd].ipd; ipd < ipdMax; ipd++)
	if (FSbCmp(SbFIpd(ipd), sbProc))
	    return(ipd);

    /* check UP TO current file */
    ipdMax = v->rgFd[v->ifd].ipd;
    for (ipd = 0; ipd < ipdMax; ipd++)
	if (FSbCmp(SbFIpd(ipd), sbProc))
	    return(ipd);

    /* check AFTER current file */
    ipdMax = v->hdr.ipdMax;
    for (ipd = ipdNextFile; ipd < ipdMax; ipd++)
	if (FSbCmp(SbFIpd(ipd), sbProc))
	    return(ipd);

    return(ipdNil);
} /* IpdFName */


/* I L N   F I R S T   F   I P D */

export int IlnFirstFIpd(ipd)
int2	ipd;
{
    int2	iln, slop;
    int4	iline;

    /* Return the iln of the first executable line in ipd */
    iline = v->rgPd[ipd].iline;
    if (iline == 0)
	return(ilnNil);	/* no line info */

    return(LineFIline(iline)->iln);
} /* IlnFirstFIpd */


/* A D R   F I R S T   F   I P D */

export int AdrFirstFIpd(ipd)
int2	ipd;
{
    int2	iln, slop;
    int4	iline;

    /* Return the adr of the first executable line in ipd, based on line info.
     * return adrNil if no line info.
     */

    iline = v->rgPd[ipd].iline;
    if (iline == 0)
	return(adrNil);	/* no line info */

    /* First iline is now THE CORRECT first iline!!! */
    return(v->rgPd[ipd].adr + LineFIline(iline)->dadr);
} /* AdrFirstFIpd */


/* O P E N   I P D */

export void OpenIpd(ipd, fForce)
int2	ipd;
FLAGT	fForce;
{
    int2	ifd;
    pPDR	pd;

    /* 'Open' the procedure - this includes getting the right source file
     * setup and determining the first 'real' line in the proc.
     */

    if (ipd == ipdNil) {
	v->ipd = ipdNil;
	return;
    } /* if */

    pd = v->rgPd + ipd;
    ifd = IfdFAdr(pd->adr);	
    if (fForce OR (ipd != v->ipd))
	OpenIfd(ifd);	/* open parent file */
    v->ifd = ifd;
    v->iln = (pd->iline == 0) ? ilnNil : IlnFirstFIpd(ipd);
    v->ipd = ipd;
    v->slop = 0;
    v->adrInst = pd->adr;
    v->stackdepth = -1;
} /* OpenIpd */


/* O P E N   I F D */

export void OpenIfd(ifd)
int2	ifd;
{
    char	sbTemp[256];
    int2	cb;
    int4	mtimeSrc;
    pFDR	fd;
    FILE	*fp, *fpTemp;
    static pPRR	prLast = prNil;

    /* Open the source file connected with ifd */

    if (ifd == v->ifd)		/* same file */
	return;

    if (ifd < 0 OR ifd >= v->hdr.ifdMax)
	Panic("Ifd out of range: %d.", ifd);

    fd = v->rgFd + ifd;

    /* we use ifdTemp for `unrelated' files */
    if (ifd != ifdTemp) {
	/* a normal source file */
	if ((ifd == v->ifd) AND (fd->rgLn != 0))
	    return;

	if (fd->fNoSource OR (fd->iline == 0))
	    goto NoSource;
	strcpy(sbTemp, SbFIss(fd->iss));
    } else {
	strcpy(sbTemp, vsbFileTemp);
    } /* if */


    /* Now we try to open the source file */

     cb = strlen(sbTemp);
     if ((sbTemp[cb-1] == 'o') AND (sbTemp[cb-2] == '.'))
 	goto NoSource;
 
    fp = FpFSb(sbTemp, "r");

    if (fp == NULL) {
	/* well, that didn't work */
	if (ifd == ifdTemp)
	    UError(vsbFilename);

	cb = strlen(sbTemp);
	if ((sbTemp[cb-1] == 'o') OR (sbTemp[cb-1] == 's')) {
	    /* it's a ".o" file - try to find a ".c" somewhere */
	    sbTemp[cb-1] = 'c';
	    fp = FpFSb(sbTemp, "r");
	    if (fp == NULL)
		goto NoSource;
	} else {
	    if (fd->iline != 0)
		printf("%s\n", vsbFilename);
	    goto NoSource;
	} /* if */
    } /* if */

    /* We got a good one! */

    if (ifd == ifdTemp) {
	/* do some quick cleanup (kludges??) */
	if (fd->rgLn != 0) {
	    /* ie. there was already a file connected with ifdTemp */
	    free(fd->rgLn);
	    fd->rgLn = 0;
	    fd->ilnMac = 0;
	} /* if */
	fd->iline = -1;	/* so we think of it as printable */
	fd->iss = IssFSb(vsbFileTemp);
	fd->issShort = IssFSb(SbFBase(vsbFileTemp));
    } /* if */

    /* let's get rid of any currently open stuff */
    if (vfpSrc != NULL) {
	fclose(vfpSrc);	/* there is a currently open file */
	vfpSrc = NULL;
    } /* if */

    vfpSrc = fp;
    prLast = v;	/* remember which process we opened the file for */
    v->ipd = v->rgFd[ifd].ipd;
    v->ifd = ifd;
    v->stackdepth = -1;
    v->iln = 1;
    v->slop = 0;

    if (fd->rgLn == 0) {

	/* we need to see its age and build line array */
	mtimeSrc = AgeFFn(fileno(vfpSrc));

	/* Remember - the greater the time, the YOUNGER it is */
	if ((!fd->fWarned) AND (mtimeSrc > v->mtimeExec)) {
	    /* This file is younger than the executable.
	     * See if there is a # file around.
	     */
	    strcat(sbTemp, "#");;
	    fpTemp = fopen(sbTemp, "r");
	    if (fpTemp == NULL) {

		/* no # file exists - remove the # from the name */
		sbTemp[strlen(sbTemp)-1] = '\0';

	    } else {

		/* let's use the older (better?) temp */
		fclose(fp);
		fp = vfpSrc = fpTemp;
		printf("WARNING: Using \"%s\" instead of \"%s\"\n",
			    sbTemp, SbFIss(fd->iss));
		fd->fEdited = true;

	    } /* if */
	    if (!fd->fEdited)
		printf("WARNING: \"%s\" is younger than \"%s\"\n",
				sbTemp, v->sbExec);
	} /* if */
	SetRgLn(ifd, vfpSrc);	/* figure out line endings */
    } /* if */

    if (! FSbCmp(SbFIss(fd->iss), sbTemp)) {
	/* we modified name in some way */
	fd->iss = IssFSb(SbFAlloc(sbTemp));
	fd->issShort = IssFSb(SbFBase(sbTemp));
    } /* if */

    if (viwwSrc != iwwNil)
	EdOpenFile(ifd);
    
    fd->fWarned = true;
    return;	/* normal exit */

NoSource:
    /* there is no source file for us to open
     * could be either a .o OR a missing source.
     */
    fd->fNoSource = true;
    if (vfpSrc != NULL)
	fclose(vfpSrc);
    vfpSrc = NULL;
    v->ifd = ifd;
    v->stackdepth = -1;
    v->ipd = fd->ipd;
    v->slop = 0;
    v->iln = 0;
} /* OpenIfd */


/* S E T   V I E W   P O S I T I O N */

export void SetViewPosition(adr)
{
    int2	ipd, iln, slop;

    /* Set the position globals to be correct for 'adr */

    if (adr == adrNil) {

	/* determine adr FROM the current file/line/stack context */
	if (v->rgFd[v->ifd].iline == 0) {
	    /* no source line numbers */
	    return;	/* ?? */
	} /* if */

	v->slop = 0;
	adr = AdrFIfdIln(v->ifd, v->iln);
	if (adr == adrNil) {
	    v->ipd = ipdNil;
	    v->adrInst = adrNil;
	    return;
	} /* if */
	v->ipd = IpdFAdr(adr);
	v->adrInst = adr;

    } else {

	ipd = IpdIlnFAdr(&iln, &slop, adr);	/* map to line number */
	OpenIpd(ipd, true);	/* This will also open our file for us */
	v->adrInst = adr;
	v->iln = iln;
	v->slop = slop;

    } /* if */

} /* SetViewPosition */


/* I F D   F   N A M E */

export int IfdFName(sbFile)
FAST SBT	sbFile;
{
    FAST int2	ifd, ifdMax;
    FAST pFDR	fd;

    /* Map a name to an ifd */

    if ((v->ifd != ifdNil)
       AND FSbCmp(SbFIss(v->rgFd[v->ifd].iss), sbFile))
	return(v->ifd);

    ifdMax = v->hdr.ifdMax;
    for (ifd = 0, fd = v->rgFd; ifd < ifdMax; fd++, ifd++) {
	if (FSbCmp(SbFIss(fd->iss), sbFile))
	    return(ifd);
    } /* for */

    for (ifd = 0, fd = v->rgFd; ifd < ifdMax; fd++, ifd++) {
	if ( (fd->iss != fd->issShort)
	   AND (FSbCmp(SbFIss(fd->issShort), sbFile)) )
	    return(ifd);
    } /* for */

    return(ifdNil);
} /* IfdFName */


/* S B   F   P R E P A R E   L I N E */

export SBT SbFPrepareLine(sbIn)
FAST SBT	sbIn;
{
    FAST int	col, cnt;
    FAST SBT	sb;
    static char	sbBuf[1024];

    /* this routine expands any tabs and removes any trailing \n */

    col = 0;
    sb = sbBuf;
    while (*sbIn != '\n') {
	if (*sbIn != '\t') {
	    *sb++ = *sbIn++;
	    ++col;
	} else {
	    cnt = 8 - col % 8;
	    col += cnt;
	    while (cnt--)
		*sb++ = ' ';
	    ++sbIn;
	} /* if */
    } /* for */

    *sb = chNull;
    return(sbBuf);
} /* SbFExpandTabs */


/* P R I N T   L I N E */

export void PrintLine(iln, count, fPrintLn, fp)
int2	iln, count;
FLAGT	fPrintLn;
FILE	*fp;
{
    int2	ifd, col;
    int4	offset;
    char	linebuf[cbLineMax];
    pFDR	fd;

    /* Print the given line(s) in the currently open source file.  */
    col = (vfWindows) ? 71 : 100;

    if (v->ifd == ifdNil)
	UError("I have no source file for this address.");

    fd = v->rgFd + v->ifd;
    if ((fd->iline == 0) OR (fd->fNoSource))
	UError("I have no source file for this address.");

    if (iln == ilnNil)
	iln = 1;
    iln = Min(iln, fd->ilnMac);
    count = Min(fd->ilnMac-iln, count);

    offset = fd->rgLn[iln];
    if (fseek(vfpSrc, offset, 0))
	SysPanic("Bad seek in PrintLine.");

    while (count--) {
	if (fgets(linebuf, cbLineMax, vfpSrc) == NULL)
	    SysPanic("Bad read in PrintLine.");
	if (fPrintLn)
	    fprintf(fp, "%4d:", iln);
	if (linebuf[0] == '\014')
	    strcpy(linebuf, "\n"); /* line feeds casue the window to clear */
	fprintf(fp, "	%.*s", col, SbFPrepareLine(linebuf));
	if (count)
	    fprintf(fp, "\n");
	iln++;
    } /* while */

    if (fp != stdout)
	fflush(fp);
    else
	printf("\n");

    v->iln = iln - 1;	/* set to last line printed */
} /* PrintLine */


/* F I N D */

export void Find(sbTarget, fBack)
SBT	sbTarget;
FLAGT	fBack;
{
    int		i, lineinc, count, iln, ilnStart, ilnMac;
    uint4	*rgLn;
    char	linebuf[cbLineMax];
    pFDR	fd;

    /* Search the currently open source (forwards or backwards)
     * for an instance of the target.
     * Wrap around the end/beginning of the file.
     */

    fd = v->rgFd + v->ifd;
    if (fd->fNoSource OR (fd->iline == 0))
	UError("I have no source for file %s.", SbFIss(fd->iss));

    iln = v->iln;
    ilnMac = fd->ilnMac;
    rgLn = fd->rgLn;
    if (fBack) {
	lineinc = -1;
	iln--;  /* for backup */
	count = iln;
    } else {
	lineinc = 1;
	iln++;  /* start at next line */
	count = ilnMac - iln;
    } /* if */
    ilnStart = iln;

    if (fseek(vfpSrc, rgLn[iln], 0))
	SysPanic("Bad seek in Find - offset %d.",rgLn[iln]);

    InitPattern(sbTarget);
    while (count--) {
	if (fBack AND (fseek(vfpSrc, rgLn[iln], 0) != 0) )
	    SysPanic("Bad seek in Find - offset %d.",rgLn[iln]);
	if (fgets(linebuf, cbLineMax, vfpSrc) == NULL)
	    SysPanic("Bad read in Find.");
	if ((i = IFPattern(linebuf)) >= 0)
	    goto Winner;
	iln += lineinc;
    } /* while */

    /* that didn't work, try it from the top of file */
    if (fBack) {
	iln = ilnMac - 1;
	count = ilnMac - ilnStart - 1;
    } else {
	iln = 1;
	count = ilnStart;
    } /* if */

    if (fseek(vfpSrc, rgLn[iln], 0))
	SysPanic("Bad seek in Find.");

    while (count--) {
	if (fBack AND (fseek(vfpSrc, rgLn[iln], 0) != 0) )
	    SysPanic("Bad seek in Find.");
	if (fgets(linebuf, 200, vfpSrc) == NULL)
	    SysPanic("Bad read in Find.");
	if ((i = IFPattern(linebuf)) >= 0)
	    goto Winner;
	iln += lineinc;
    } /* while */
    UError("No Match - %s.", sbTarget);

Winner:
    v->iln = iln;
    ShowViewPosition(fmtLn+fmtLine+fmtEol);
} /* Find */


/* S H O W   V I E W   P O S I T I O N */

ShowViewPosition(fmt)
int2	fmt;
{
    if ((vfWindows)
       AND (v->iln != ilnNil)) {
	JumpScrollWw(v->iln);
	if (fmt & fmtSrcLineOnly)
	    fmt &= ~(fmtLine|fmtLn);
	PrintPosition(adrNil, fmt);
	MarkLine(v->iln);
    } else {
	if (fmt & fmtSrcLineOnly)
	    fmt |= fmtLine;
	PrintPosition(adrNil, fmt);
    } /* if */
} /* ShowViewPosition */



/* P R I N T   P O S I T I O N */

export void PrintPosition(adr, fmt)
ADRT	adr;
int2	fmt;
{
    int2	ifdSave, ipdSave, ilnSave, slopSave;
    int2	ifd, ipd, iln, slop;
    SBT		sbLine;
#define cbBuf	200
    char	sbBuf[cbBuf];
    FLAGT	fHaveLines;
    ADRT	adrSave;

    /* Do a formatted print of the given address.
     * fmt options are:
     *	fmtFile		print the file name
     *	fmtProc		print the procedure name
     *	fmtLn		print the line number
     *	fmtPrint	print the line (or instruction if no source)
     *  fmtInst		print instruction, even if we have source
     *
     *	These options can be added or |'d together, e.g. fmtFile+fmtProc.
     */

    /* clean out buffer */
    ZeroBlock(sbBuf, cbBuf);
    sbLine = sbBuf;

    if (adr != adrNil) {
	ifd = IfdFAdr(adr);
	ipd = IpdIlnFAdr(&iln, &slop, adr);
    } else {
	ifd = v->ifd;
	ipd = v->ipd;
	iln = v->iln;
	slop = v->slop;
	adr = v->adrInst;
    } /* if */

    fHaveLines = (ifd == ifdTemp) OR (v->rgFd[ifd].iline != 0);

    if (fmt & fmtFile) {
	strcat(sbLine, SbFIss(v->rgFd[ifd].issShort));
	sbLine += strlen(sbLine);
	*sbLine++ = ':';
    } /* if */

    if (slop < 0) {
	/* we are in the intro code of a proc with source info */
	strcat(sbLine, SbFNearest(adr, true, false, true));
	sbLine += strlen(sbLine);
	*sbLine++ = ':';
    } else {
	if ((fmt & fmtProc) AND (ifd != ifdTemp) AND (ipd != ipdNil)) {
	    if (fHaveLines) {
		strcat(sbLine, SbFIpd(ipd));
	    } else {
		strcat(sbLine, SbFNearest(adr, true, false, false));
	    } /* if */
	    sbLine += strlen(sbLine);
	    *sbLine++ = ':';
	} /* if */

	if (fHaveLines AND (fmt & fmtLn)) {
	    if (iln != ilnNil) {
		if (fmt & (fmtFile|fmtProc))
		    sprintf(sbLine, "%d", iln);
		else
		    sprintf(sbLine, "%4d", iln);
		sbLine += strlen(sbLine);
	    } /* if */
	    if (slop != 0) {
		*sbLine++ = '+';
		strcat(sbLine, SbFAdr(slop, true));
		sbLine += strlen(sbLine);
	    } /* if */
	    *sbLine++ = ':';
	} /* if */
    } /* if */

    if (fmt & (fmtLine | fmtInst)) {
	if (fHaveLines
	   AND ! v->rgFd[ifd].fNoSource
	   AND ((fmt & fmtInst) == 0)) {
	    printf("%s", sbBuf);
	    if (ifd != v->ifd) {
		ifdSave = v->ifd;
		ipdSave = v->ipd;
		ilnSave = v->iln;
		slopSave = v->slop;
		adrSave = v->adrInst;

		OpenIfd(ifd);
		PrintLine(iln, 1, false, stdout);

		v->ifd = ifdNil;
		if (ifdSave != ifdNil) 
		    OpenIfd(ifdSave);
		v->ipd = ipdSave;
		v->iln = ilnSave;
		v->slop = slopSave;
		v->adrInst = adrSave;
	    } else {
		PrintLine(iln, 1, false, stdout);
	    } /* if */
	 } else {
	    printf("%-20s", sbBuf);
	    PrintInstruction(adr);
	    if (fmt & fmtEol)
		printf("\n");
	 } /* if */
    } else {
	*--sbLine = chNull;	/* takes out last `:' */
	if (fmt & fmtEol)
	    *sbLine++ = '\n';
	printf("%s", sbBuf);
    } /* if */
} /* PrintPosition */
0707070001000312161004440000000000010000011603150454650113500001300000001106cdb/mloe.c 
main (argc, argv, envp)
int	argc;
char *argv[];
{
    int	x;

    printf ("This is the beginning\n");
    routine1 (argv, envp);
    exit(0);
} /* main */


routine1 (argv, envp)
char *argv[];
{
    int		i;
    char *buf = "loe";

    printf ("before fork\n");

    argv [0] = buf;
    if (fork()) {
	printf ("parent: after fork\n");
	for (i=0; i < 20; i++) {
	    sleep(10);
	    printf("Parent is alive\n");
	} /* for */
	wait (0);
    } else {
	printf ("child: before the exec\n");
	execve ("loe", argv, envp);
	perror("Child failed to exec: ");
    } /* if */
} /* routine1 */
0707070001000312171004440000000000010000011603240454650113500001600000022253cdb/cmdline.c /* $Header: cmdline.c,v 5.14 86/06/05 09:11:40 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This file contains the routines that read the commnad line from the TTY and
 * maintain the record & playback files.
 * TkNext(), in tk.c, the tokenizer, is what most routines call to actually get
 * something from the current command line.
 */

#include "cdb.h"

extern char *gets();

export FILE	*vfpOutput, *vfpRecord, *vfpPlayback;
char	vsbRecord[50], vsbOutput[50];
export int4	vcStepPlayback, vsleepDemo;
export FLAGT	vfComment, vfOutput, vfRecord, vfEofSeen = false;;
export SBT 	vsbGet;	/* points to buffer for Waiter tty input */

#define chEOF 04	/* a ^D */
#define cbSbCmd 200	/* max command length */
#define cbSbQuery 20	/* max query (Yes/No) length */


/* N E X T   C M D */

export void NextCmd(sbBuffer, cbBuffer, sbPrompt)
SBT	sbBuffer, sbPrompt;
int2	cbBuffer;
{
    FLAGT	fDoit, fPrompt = true;
    SBT		sbCmd, sbTemp;
    char	sbQuery[cbSbQuery];

    while (vfpPlayback != NULL) {

	sbBuffer[0] = chNull;
	sbCmd = fgets(sbBuffer, cbBuffer, vfpPlayback);

	if (sbCmd == sbNil) {
EndOfFile:
	    /* end-of-file for playback */
	    fclose(vfpPlayback);
	    vfpPlayback = NULL;
	    vcStepPlayback = 1;
	    break; /* which will put us into the TTY code */
	} /* if */

	if ((sbTemp = strrchr(sbCmd, '\n')) != NULL)
	    *sbTemp = chNull;	/* step on new-line */

	if (*sbCmd == '~') {
	    /* Make the command prettier than a '~' */
	    sbCmd++;
	    /* *sbCmd = ' '; */
	} /* if */

	if ((vcStepPlayback == 0)
	   OR (--vcStepPlayback > 0)) {
	    if ((*sbCmd != 'Y') OR (!vfComment))
		printf("%s%s\n", sbPrompt, sbCmd);
	} else {	/* we are doing playback stepping */
	    if (vfComment == true) {
		if (*sbCmd == 'Y') {
		    vcStepPlayback = 1;
		    return;
		} /* if */
		printf("%s%s", sbPrompt, sbCmd);
		if (vsleepDemo == 0) {
		    printf("	[HIT <CR> TO CONTINUE] ");
		} else {
		    printf("\n");
		    if (FTimedInput(vsleepDemo)) {
			/* timed out */
			vcStepPlayback = 1;
			return;
		    } /* if */
		    /* they want to take control, kill future timing
		     * and fall through to normal input code.
		     */
		    SetDemoTimer(0);
		    printf("	[HIT <CR> TO CONTINUE] ");
		} /* if */
	    } else {
		printf("%s%s  (<cr>, <#>, C, Q, S or ?): ", sbPrompt, sbCmd);
	    } /* if */

	    fDoit = false;
	    while (!fDoit) {
		gets(sbQuery);
		fDoit = true;
		switch (*sbQuery) {
		    default:	fDoit = false;
				break;

		    case 'Q':   goto EndOfFile;
				break;

		    case 'S':   vcStepPlayback = 1;
				goto ContinueMainLoop;
				break;

		    case 'C':   vcStepPlayback = 0;
				break;

		    case chNull:
				vcStepPlayback = 1;
				break;

		    case '?':
	    printf("<cr> executes THIS command line,\n");
	    printf("<#> does that number of command lines,\n");
	    printf("S skips this command,\n");
	    printf("Q quits playback mode,\n");
	    printf("C continues until the end of ALL playback files.\n");
	    printf("%s%s  (<cr>, <#>, C, Q, S or ?): ", sbPrompt, sbCmd);
				fDoit = false;
				break;

		    case '0': case '1': case '2': case '3':
		    case '4': case '5': case '6': case '7':
		    case '8': case '9':
				vcStepPlayback = atoi(sbQuery);
				break;

		} /* switch */
	    } /* while */
	} /* if */

	return;
ContinueMainLoop: ;
    } /* while */

    /* there is no playback file, read from terminal */
    v->fQuiet = false;	/* since we need TTY input, we get noisy */
    if (fPrompt)
	printf("%s", sbPrompt);
    vsbGet = sbBuffer;
    sbBuffer[0] = 0;

    Waiter(wtTty, 0);

    sbCmd = vsbGet;

    if (sbCmd == sbNil) {
	sbBuffer[0] = chNull;
    } else if (*sbCmd == '%') {
	h_modify(sbCmd);
    } else if (*sbCmd == '#') {
	h_set(sbCmd);
    } else if (*sbCmd == chNull) {
	sbCmd[0] = '~';
	sbCmd[1] = chNull;
    } /* if */
} /* NextCmd */


/* D E B U G   I T */

export void DebugIt(fTopLevel)
FLAGT	fTopLevel;
{
    int		i, cnt;
    FLAGT	fRet;
#define cbCmdMax	200
    char	sbCmd[cbCmdMax];

    if (fTopLevel)
	SetPrompt("%s >", vsbDebugName);
    else
	SetPrompt("%s >>", vsbDebugName);

    fRet = true;
    while (fRet) {
	cnt = 1;
	vcNest = 0; 	/* nesting level for printing structure indents */
	NextCmd(sbCmd, cbCmdMax, vsbPrompt);
	if (*sbCmd == chNull) {
	    printf("   "); /* clear away the ^D */
	    cnt = strlen(vsbPrompt) + 3;
	    while (cnt--)
		printf("\010");  /* backspace over prompt */
	    cnt = 10;
	    sbCmd[0] = '~';
	    sbCmd[1] = chNull;
	    vfEofSeen = true;
#if (OP_SYS == BSD42)
	/* These turkeys don't know the meaning of the word compatibility! */
	    clearerr(stdin);
#endif
	} /* if */

	for (i=0; (i < cnt) AND fRet; i++) {
	    RecordCmd(sbCmd);
	    fRet = FDoCommand(sbCmd, fTopLevel);
	} /* for */
	vfEofSeen = false;
    } /* while */
    SetPrompt("%s >", vsbDebugName);
} /* DebugIt */


/* R E C O R D	 C M D */

export void RecordCmd(sbCmd)
SBT	sbCmd;
{
    h_insert(sbCmd);	/* it's history, now */

    if ((*sbCmd != '>') AND (*sbCmd != '<')) {
	if (vfRecord AND (vfpRecord != NULL))
	    fprintf(vfpRecord, "%s\n", sbCmd);	/* make a recording */
	if (vfOutput AND (vfpOutput != NULL))
	    fprintf(vfpOutput, "%s\n", sbCmd);	/* make a recording */
    } /* if */
} /* RecordCmd */


/* Y E S   N O */

export int YesNo(sbPrompt)
SBT	sbPrompt;
{
    char	sbAnswer[cbSbQuery];

    NextCmd(sbAnswer, cbSbQuery, sbPrompt);
    RecordCmd(sbAnswer);
    return(sbAnswer[0] == 'y' OR sbAnswer[0] == 'Y');
} /* YesNo */


/* C H   F   C H O I C E */

export char ChFChoice(sbPrompt, sbChoice)
SBT	sbPrompt, sbChoice;
{
    char	*sbTemp, sbResponse[cbSbQuery];

    sbTemp = sbNil;
    while (sbTemp == sbNil) {
	NextCmd(sbResponse, cbSbQuery, sbPrompt);
	RecordCmd(sbResponse);
	if ((sbChoice[0] != ' ') AND (sbResponse[0] == '~'))
	    return(sbChoice[0]);	/* give them default */
	sbTemp = strchr(sbChoice, sbResponse[0]);
    } /* while */
    return(*sbTemp);
} /* ChFhoice */


/* S E T   P L A Y B A C K */

export void SetPlayback(sbPlayback, fQuiet, fSinglestep)
SBT	sbPlayback;
FLAGT	fQuiet, fSinglestep;
{
    FILE	*fpTemp;

    if (vfpPlayback != NULL)
	fclose(vfpPlayback);
    if ((sbPlayback == sbNil) OR (*sbPlayback == chNull))
	UError("No playback name specified.");
    if ((fpTemp = fopen(sbPlayback, "r")) == NULL)
	UError("Can't open %s as playback file: %s.", sbPlayback,
			SbFError(errno));
    if (!fQuiet)
	printf("Playing back from %s\n", sbPlayback);
    vfpPlayback = fpTemp;
    vcStepPlayback = (fSinglestep) ? 1 : 0;
} /* SetPlayback */


/* S E T   O U T P U T */

export void SetOutput(sbOutput)
SBT	sbOutput;
{
    FILE	*fpTemp;

    if (vfpOutput != NULL) {
	if (!v->fQuiet)
	    printf("Closing output file\n");
	fclose(vfpOutput);
	vfOutput = false;
	vfpOutput = NULL;
    } /* if */
    if ((sbOutput == sbNil) OR (*sbOutput == chNull))
	return;
    if ((fpTemp = fopen(sbOutput, "w")) == NULL)
	UError("Can't open %s as output file.", sbOutput);
    strncpy(vsbOutput, sbOutput, 49);
    vfOutput = true;
    vfpOutput = fpTemp;
} /* SetOutput */


/* S E T   R E C O R D */

export void SetRecord(sbRecord)
SBT	sbRecord;
{
    FILE	*fpTemp;

    if (vfpRecord != NULL) {
	if (!v->fQuiet)
	    printf("Closing record file\n");
	fclose(vfpRecord);
	vfRecord = false;
	vfpRecord = NULL;
    } /* if */
    if ((sbRecord == sbNil) OR (*sbRecord == chNull))
	return;
    if ((fpTemp = fopen(sbRecord, "w")) == NULL)
	UError("Can't open %s as record file.", sbRecord);
    strncpy(vsbRecord, sbRecord, 49);
    vfRecord = true;
    vfpRecord = fpTemp;
} /* SetRecord */


/* S T A T E   R E C O R D */

export void StateRecord()
{
    if (vfpOutput != NULL)
	printf("Sending OUTPUT to \"%s\".\n", vsbOutput);
    if (vfpRecord != NULL) {
	printf("Sending COMMANDS to \"%s\".\n", vsbRecord);
    }
    printf("Output recording is %s.\n", (vfOutput) ? "ON" : "OFF");
    printf("Command recording is %s.\n", (vfRecord) ? "ON" : "OFF");
} /* StateRecord */


/* S H O W   S T A T E */

export void ShowState()
{
    printf("Debugging %s, %d files %d procedures.\n",
		v->sbExec, v->hdr.ifdMax, v->hdr.ipdMax);
    if (v->fnCore != fnNil)
	printf("Core file is %s.\n", v->sbCore);
     else
	printf("No core file.\n");
    if (v->pid != pidNil)
	printf("There is an active child process, #%d.\n", v->pid);
     else
	printf("No active child process.\n");
    if (v->iadMac == 0)
	printf("No assertions.\n");
     else if (v->as == asSuspended)
	printf("Assertions are suspended.\n");
     else
	printf("%d assertions are active.\n", v->iadMac);
    StateRecord(vfRecord);
    printf("Searches are %scase sensitive.\n",
	(vcaseMod!=0) ? "NOT " : "");
} /* ShowState */


/* P L A Y B A C K   F I L E */

export void PlaybackFile(sbFile)
SBT	sbFile;
{
    char	*sbTemp, *sbTemp2, sbCmd[200];
    FILE	*fp;

    /* This routine is called when you have a file that you
     * want to playback with no prompts, no commands printed,
     * and no user interaction.
     */

    if ((fp = fopen(sbFile, "r")) == NULL)
	return;

    while (true) {
	sbCmd[0] = chNull;
	sbTemp = fgets(sbCmd, 200, fp);
	if (sbTemp == sbNil) {
	    fclose(fp);
	    return;
	} /* if */

	if ((sbTemp2 = strrchr(sbCmd, '\n')) != NULL)
	    *sbTemp2 = chNull;	/* step on new-line */

	if (*sbTemp == '~')
	    *sbCmd = ' ';

	RecordCmd(sbCmd);
	FDoCommand(sbCmd, true);
    } /* while */
} /* PlaybackFile */
0707070001000312201004440000000000010000011604320454650113500001400000036734cdb/cpu68.c /* $Header: cpu68.c,v 6.3 86/09/01 17:20:42 peter Exp $ */

/* This program is an unpublished work fully protected by the
 * United States Copyright Laws and is considered a TRADE SECRET
 * belonging to Third Eye Software, Inc.
 */

/* ******************************************************* */
/*							   */
/* This is the Motorola 68000 (and 68010 and 68020) module */
/*							   */
/* ******************************************************* */

#if 0
exportdefine X_InitRegisters	1
exportdefine X_ListRegisters	1
#endif

#include "cdb.h"

#include <errno.h>
#include <sys/param.h>

#if (OP_SYS == SYSV)
#include <signal.h>
#include <sys/types.h>
#endif

#include <sys/dir.h>
#include <sys/user.h>

#if ((OP_SYS == BSD42) || (OP_SYS == BSD41c))
#include <machine/reg.h>
#else
#include <sys/reg.h>
#endif


CPUR	vacpu68;	/* where we put 68000 relative info */
ADRT	vadrRegBase;	/* used in GetMask/DoReg */

#if (HOST_CPU == M68000)
/* these are 'export'ed in main.c */
pCPUR	vcpuHost = &vacpu68;
#endif

#if (SYS == P60V)
#define R8	AR0
#define R9	AR1
#define R10	AR2
#define R11	AR3
#define R12	AR4
#define R13	AR5
#define R14	AR6
#define SP	USP
#define R15	SP
#undef PS
#define PS	SR
#endif /* (SYS == P60V) */

#if (SYS == AR68V)
#define R0	D0
#define R1	D1
#define R2	D2
#define R3	D3
#define R4	D4
#define R5	D5
#define R6	D6
#define R7	D7
#define R8	A0
#define R9	A1
#define R10	A2
#define R11	A3
#define R12	A4
#define R13	A5
#define R14	A6
#define R15	A7
#define PS	SR
#endif

#if (SYS == SUN42)
#define R8	AR0
#define R9	AR1
#define R10	AR2
#define R11	AR3
#define R12	AR4
#define R13	AR5
#define R14	AR6
#define R15	AR7
#endif

#ifndef FP
#define FP	R14
#endif /* FP */

export int2 vrgOffset[] = {
	R0,  R1,  R2,  R3,
	R4,  R5,  R6,  R7,
	R8,  R9,  R10, R11,
	R12, R13, R14, R15,
	SP,  PC,  FP,  PS,
	FP
	};

#define	IntFSb(sb) ((int)sb)

export SER vrgReg[40];		/* array of register variables */
export int viregMax;


/* A D R   F   S T A C K   F I X */

export ADRT AdrFStackFix(adr)
ADRT	adr;
{
    int2	inst;

    /* given an address immediately after a procedure call, step over any
     * stack fix-up instructions.
     */

#define TST_INST	0x4a5f
#define TSTL_INST	0x4a9f
#define CMPML_INST	0xbf8f
#define ADDW_INST	0xdefc
#define ADDQ_INST	0x500f
#define ADDN_INST	0x504f

    GetBlock(adr, spaceText, (ADRT)&inst, 2);
    if ( (inst == TST_INST)
       OR (inst == TSTL_INST)
       OR (inst == CMPML_INST)
       OR ((inst & 0xf13f)  == ADDQ_INST))
	adr += 2;
    else if ((inst & 0xf1ff) == ADDN_INST)
	adr += 4;
    return(adr);
} /* AdrFStackFix */


/* A D R   F   P R E A M B L E */

export ADRT AdrFPreamble(adr)
ADRT	adr;
{
    /* given the first address in a procedure, return the address of the
     * first `real' instruction - ie. after the csav0 or the brb whatever
     */

    int		op, ipd, iln;

#   define BRA		0x60
#   define LINK		0x4e

    /* First we try it based on opening brackets */
    ipd = IpdFAdr(adr);
    if (v->rgPd[ipd].iline != 0)
	return(AdrFirstFIpd(ipd));

    /* then we do it based on skipping over branch */
    op = GetByte(adr, spaceText);	/* get instruction */
    if (op == BRA) {
	adr++;
	op = GetByte(adr, spaceText);
	adr++;
	if (op == 0)
	    adr += 2;	/* it's a long branch */
    } else if (op == LINK) {
	adr += 4;
    } /* if */

    return(adr);
} /* AdrFPreamble */


/* F   A T   C A L L */

export FLAGT FAtCall(adr)
ADRT	adr;
{
#define JSR_INST	0x4e80
#define BSR_INST	0x6100
#define cbInsMax	2

    int2	inst = 0;
    /* return true or false based on whether the instruction at adr
     * is a procedure call of any kind.
     */

    GetBlock(adr, spaceText, (ADRT)&inst, cbInsMax);
    v->fAtSyscall = ((inst & 0xffff) == v->os->instSyscall);
    return(((inst & 0xff00) == BSR_INST) OR ((inst & 0xffc0) == JSR_INST));
} /* FAtCall */


/* R E T   F   S P */

export ADRT RetFSp(sp)
ADRT	sp;
{
    ADRT	adr;
    /* given the stack pointer immediately after a procedure call,
     * return the return address
     */
    GetBlock(sp, spaceData, (ADRT)&adr, v->cpu->cbPointer);
    return(adr); /* get return */
} /* RetFSp */



/* N E X T   I N S T   A D R   F   A D R */

local ADRT NextInstAdrFAdr(adr)
ADRT adr;
{
    vfOutputSuppress = true;
    PrintInstruction(adr);
    vfOutputSuppress = false;
    return(adr + vcbInst);
} /* NextInstAdrFAdr */


/* A D R   R E G   F   C N T X */

local ADRT AdrRegFCntx(cntx, reg)
pCNTXR cntx;
ADRT reg;
{
    ADRT	fp, pc;
    FAST ADRT	adr;
    ADRT	adrRet;
    ADRT	adrNext;
    ADRT	adrBase;
    pPDR	pd;
    uint1	op;
    int2	offset;
    uint4	mask;
    uint2	maskImage;
    uint4	maskSave, maskTest;
    int4	longOffset;
    int		inc, i, c;

#   define cInstMax	15

#   define MOVL		0x2e
#   define MOVEML	0x48
#   define MISC		0x4e
#   define LINK		0x4e
#   define LINK20	0x48
#   define BRA		0x60
#   define TST		0x4a

#   define maskReverse	0x10000000

    pc = cntx->pc;
    fp = cntx->fp;

    pd = v->rgPd + IpdFAdr(pc);
    if (pd->dadrRegBase == adrNil) {
	adr = pd->adr;	/* get start of this proc */

	/*
	 * Step throught the code looking for a link instruction.
	 * Some procedures will not have a link instruction.
	 */

	adrNext = adr;
	adrBase = adrNil;
	for(c = 0; c < cInstMax; ++c) {
	    adr = adrNext;
	    adrNext = NextInstAdrFAdr(adr);
	    op = GetByte(adr, spaceText);	/* get instruction */

	    if(op == BRA) {
		/*
		 * handle the normal case where the preamble code is
		 * generated at the end of the procedure so the first
		 * instruction is a branch/jump to the end
		 */
		adr++;
		op = GetByte(adr, spaceText);
		adr++;
		if (op == 0) {
		    GetBlock(adr, spaceText, (ADRT)&offset, 2);
		    adr += offset;
/* (CPU == M68020) */
		} else if (op == 0xff) {
		    GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
		    adr += longOffset;
/* (CPU == M68020) */
		} else {
		    adr += op;
		} /* if */
		adrNext = adr;
		continue;
	    } /* if */

#if (MFG == SUN)
             if (op == 0xdf) {
                adr++;
                op = GetByte(adr, spaceText);
                adr++;
                if(op == 0xfc) {
                    GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
                    pd->dadrRegBase += longOffset;
                }
            }
#endif /* (MFG == SUN) */

#if (MFG == ISI)
	    if (op == MOVL) {
		adr++;
		op = GetByte(adr, spaceText);
		if(op == 0x87) {
		    mask = 0x0080;
		    break;
		}
		if(op == 0x8d) {
		    mask = 0x2000;
		    break;
		}
	    }
#endif

	    if (op == MISC) {	/* also is JMP */
		adr++;
		op = GetByte(adr, spaceText);
		adr++;
		/*
		 * if we hit a trap instruction or a
		 * return instruction we are done
		 */
		if((op & 0xf0) == 0x70 || (op & 0xf0) == 0x40) {
		    pd->dadrRegBase = 0;
		    pd->maskReg = 0;
		    return(adrNil);
		} /* if */

		/*
		 * if we hit a jmp, follow it if the target is (pc)
		 */
		if((op & 0xfe) == 0xf8) {
		    if(op & 0x01) {
			GetBlock(adr, spaceText, (ADRT)&offset, 2);
			adrNext = offset;
		    } else {
			GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
			adrNext = longOffset;
		    }
		    continue;
		}

		/*
		 *	check for short link instruction
		 */
		if((op & 0xf8) == 0x50) {
		    GetBlock(adr, spaceText, (ADRT)&offset, 2);
		    adrBase = offset;
		    pd->dadrRegBase = adrBase;
		    continue;
		} /* if */
	    } /* if */

	    if (op == MOVEML) {
		adr++;
		op = GetByte(adr, spaceText);
		adr++;

/* (CPU == M68020) */
		/* check for 68020 32 bit link instruction */
		if ((op & 0xf8) == 0x08) {
		    GetBlock(adr, spaceText, (ADRT)&longOffset, 4);
		    adrBase = longOffset;
		    pd->dadrRegBase = adrBase;
		    continue;
		} /* if */
/* (CPU == M68020) */

		if (op & 0x80) {
		    GetBlock(adr, spaceText, (ADRT)&maskImage, 2);
		    adr += 2;
		    mask = maskImage;
		    if((op & 0x38) == 0x20) {
			mask |= maskReverse;
		    }
		    pd->maskReg = mask;
		    /* modify dadrRegBase if an offset is specified */
		    if(op == 0xef) {
			GetBlock(adr, spaceText, (ADRT)&offset, 2);
			pd->dadrRegBase += offset;
		    }
		    else if(op == 0xee) {
			GetBlock(adr, spaceText, (ADRT)&offset, 2);
			pd->dadrRegBase = offset;
			break;
		    }
		    break;
		} /* if */
	    } /* if */
	} /* for */
    } /* if */

    mask = pd->maskReg;
    vadrRegBase = fp + pd->dadrRegBase;
    maskSave = mask & 0x0000ffff;	/* only lower 16 bits are used */
    if (mask & maskReverse) {
	reg = 15 - reg;
	inc = - v->cpu->cbRegister;
    } else {
	inc = v->cpu->cbRegister;
    } /* if */

    maskTest = 1 << reg;
    adrRet = adrNil;

    if (maskSave & maskTest) {
	/* it has a saved copy of this register */
	adrRet = vadrRegBase;	/* set to base of saved registers */
	if (mask & maskReverse)
	    adrRet += inc;

	for (i = 0; i < reg; i++) {
	    if (maskSave & 1)
		adrRet += inc;	/* a saved reg takes up space */
	    maskSave >>= 1;
	} /* for */
    } /* if */

    return(adrRet);
} /* AdrRegFCntx */

/*  D O   R E G */

export void DoReg(seReg, cntx)
pSER	seReg;
pCNTXR	cntx;
{
    int		inc, maskSave, maskTest, i;
    ADRT	adrRet, reg, adr;
    CNTXR	acntx;

    /* Given a desired fp and the register, we walk back up the stack,
     * looking for frames that may have saved this register.  If we find
     * one, we figure out the memory address of the saved register and
     * continue.  Only when we reach our desired frame, after (perhaps)
     * seeing this register get saved N times, do we actually know for sure
     * where the %@#%$# thing is!
     */

    reg = seReg->asym.value;
    adrRet = reg;	/* by default we assume it is still in the reg */

    for (acntx = v->acntx; acntx.fp != cntx->fp; NextFrame(&acntx)) {
	if (acntx.fp == 0)
	    Panic("Clobbered stack(?)");

	/* find out the address this register is stored at in this frame */

	if((adr = AdrRegFCntx(&acntx, reg)) != adrNil) {
		seReg->asym.sc = scRegImage;	/* REAL storage class */
		adrRet = adr;	
	}
    } /* for */

    seReg->asym.value = adrRet;
} /* DoReg */


/* N E X T   F R A M E */

export int NextFrame(cntx)
pCNTXR	cntx;
{
    /* Set the context values to be the next frame
     * OR we give them an fp of 0 to indicate end-of-stack.
     * Returns true if we had to slide around a
     * proc-call-from-the-command-line mini frame.
     */

    if ((v->adrStartLow <= cntx->pc) AND (v->adrStartHigh > cntx->pc)) {
	/* this check handles the case where ONLY "start" is on the stack */
	/* there is nothing beyond the start frame */
	cntx->fEndOfStack = true;
	return(false);
    } /* if */

    cntx->fEndOfStack = false;
    cntx->pc = GetWord(cntx->fp + v->cpu->cbPointer, spaceData);
    cntx->fp = GetWord(cntx->fp, spaceData);
    cntx->ap = cntx->fp;	/* they are the same */

    if (cntx->pc == v->adrBreak) {
	/* this frame is the end of a proc-call from the command line */
	cntx->pc = GetWord(cntx->fp + v->cpu->cbPointer, spaceData);
	cntx->fp = GetWord(cntx->fp, spaceData);
	cntx->ap = cntx->fp;
	return(true);
    } /* if */

    /* see if this is the 'start' frame */
    if ((v->adrStartLow <= cntx->pc) AND (v->adrStartHigh > cntx->pc)) {
	cntx->fEndOfStack = true;
    } else {
	cntx->fEndOfStack = (cntx->fp == 0);
    } /* if */

    return(false);
} /* NextFrame */


/* I N I T   R E G I S T E R S */

export void InitRegisters(cpu)
pCPUR	cpu;
{
    ADRT	adr;
    pSER	se;

    cpu->rgReg = vrgReg;
    se = vrgReg;

    InitSpc(se++, "result", u0, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "fp", ufp, stExpr, scRegister, tqPtr, btInt, false);
    InitSpc(se++, "sp", usp, stExpr, scRegister, tqPtr, btInt, false);
    InitSpc(se++, "pc", upc, stExpr, scRegister, tqPtr, btInt, false);

    InitSpc(se++, "d0", u0, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d1", u1, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d2", u2, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d3", u3, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d4", u4, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d5", u5, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d6", u6, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "d7", u7, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a0", u8, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a1", u9, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a2", u10, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a3", u11, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a4", u12, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a5", u13, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a6", u14, stExpr, scRegister, tqNil, btInt, false);
    InitSpc(se++, "a7", u15, stExpr, scRegister, tqNil, btInt, false);

#if (MFG == ISI)
#define FP_REGS	((ADRT)(((struct user *)0)->u_68881_regs));
#endif /* (MFG == ISI) */

#ifdef FP_REGS
    adr = FP_REGS;
    InitSpc(se++, "fd0", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd1", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd2", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd3", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd4", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd5", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd6", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;
    InitSpc(se++, "fd7", adr, stExpr, scUserStruct, tqNil, btDouble, false);
    adr += 8;

    InitSpc(se++, "f0", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
    InitSpc(se++, "f1", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
    InitSpc(se++, "f2", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
    InitSpc(se++, "f3", adr, stExpr, scUserStruct, tqNil, btFloat, false);
    adr += 4;
#endif /* FP_REGS */

    cpu->iregMax = se - vrgReg;;
} /* InitRegisters */


/* L I S T   R E G I S T E R S */

export void ListRegisters(sbRegs)
SBT	sbRegs;
{
    int		i;
    pSER	se;
    MODER	amode;

    vmode->cnt = 1;
    vmode->df = dfNil;
    vmode->len = -1;
    GetMode(vmode);

    if ((v->pid == pidNil) AND (v->fnCore == fnNil))
	UError("No process.");

    if ((vmode->df != dfPStr) AND (vmode->df != dfStr)) {
	/* then we can use a more compact form */
	ColOn();
	if (vmode->df == dfNil)
	    amode = *vmode;
	se = v->cpu->rgReg;
	DisplaySe(se++, vmode, true, true, true); /* result */
	PadTo(20);
	if (amode.df == dfNil)
	    *vmode = amode;
	DisplaySe(se++, vmode, true, true, true); /* fp */
	PadTo(40);
	if (amode.df == dfNil)
	    *vmode = amode;
	DisplaySe(se++, vmode, true, true, true); /* sp */
	PadTo(60);
	if (amode.df == dfNil)
	    *vmode = amode;
	DisplaySe(se++, vmode, true, true, true); /* pc */
	printf("\n\n");

	if (amode.df == dfNil)
	    *vmode = amode;
	for (i = 4; i < v->cpu->iregMax; i += 4) {
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    PadTo(20);
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    PadTo(40);
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    PadTo(60);
	    DisplaySe(se++, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    printf("\n");
	} /* for */
	ColOff();
    } else {
	se = v->cpu->rgReg;
	for (i = 0; i < v->cpu->iregMax; i++, se++) {
	    if ( (sbRegs != sbNil)
		  AND (!FHdrCmp(sbRegs, SbFIss(se->asym.iss))) ) 
		continue;	/* not interesting */
	    DisplaySe(se, vmode, true, true, true);
	    if (amode.df == dfNil)
		*vmode = amode;
	    printf("\n");
	} /* for */
    } /* if */
} /* ListRegisters */
0707070001000312211004440000000000010000011601720454650113500001200000037437cdb/dis.c #
/****************************************************************************

	DEBUGGER - 68000 instruction printout

****************************************************************************/

#include "cdb.h"


char *badop = "\t???";
char *IMDF;				/* immediate data format */

char *bname[16] = { "ra", "sr", "hi", "ls", "cc", "cs", "ne",
		    "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le" };

char *shro[4] = { "as", "ls", "rox", "ro" };

char *bit[4] = { "btst", "bchg", "bclr", "bset" };

int vcbScale[] = { 1, 2, 4, 8 };

int omove(),obranch(),oimmed(),oprint(),oneop(),soneop(),oreg(),ochk();
int olink(),omovem(),oquick(),omoveq(),otrap(),oscc(),opmode(),shroi();
int extend(),biti();

int obkpt(), ocallm(), ocas(), ochk2(), olmul(), otrapcc(), obits();
int cpgen(), cpscc(), cpdbcc(), cptrap(), cpbcc(), cpsave(), cprest();


struct opdesc
{			
	unsigned short mask, match;
	int (*opfun)();
	char *farg;
} opdecode[] =
{					/* order is important below */
  0xF000, 0x1000, omove, "b",		/* move instructions */
  0xF000, 0x2000, omove, "l",
  0xF000, 0x3000, omove, "w",
  0xF000, 0x6000, obranch, 0,		/* branches */
  0xFF00, 0x0000, oimmed, "or",		/* op class 0  */
  0xF9C0, 0x00C0, ochk2, 0,		/* 68020 */
  0xFF00, 0x0200, oimmed, "and",
  0xFF00, 0x0400, oimmed, "sub",
  0xFFC0, 0x06C0, ocallm, 0,		/* 68020 */
  0xFF00, 0x0600, oimmed, "add",
  0xFF00, 0x0A00, oimmed, "eor",
  0xFF00, 0x0C00, oimmed, "cmp",
  0xF100, 0x0100, biti, 0,
  0xFF00, 0x0800, biti, 0,
  0xF9C0, 0x08C0, ocas, 0,		/* 68020 */
  0xFFC0, 0x40C0, oneop, "move_from_sr", /* op class 4 */
  0xFF00, 0x4000, soneop, "negx",
  0xFF00, 0x4200, soneop, "clr",
  0xFFC0, 0x44C0, oneop, "move_to_ccr",
  0xFF00, 0x4400, soneop, "neg",
  0xFFC0, 0x46C0, oneop, "move_to_sr",
  0xFF00, 0x4600, soneop, "not",
  0xFFF8, 0x4808, olink, "link",			/* 68020 */
  0xFFC0, 0x4800, oneop, "nbcd",
  0xFFF8, 0x4840, oreg, "\tswap\td%ld",
  0xFFF8, 0x4848, obkpt, 0,				/* 68020 */
  0xFFC0, 0x4840, oneop, "pea",
  0xFFF8, 0x49C0, oreg, "\textb\td%ld",			/* 68020 */
  0xFFF8, 0x4880, oreg, "\textw\td%ld",
  0xFFF8, 0x48C0, oreg, "\textl\td%ld",
  0xFB80, 0x4880, omovem, 0,
  0xFFC0, 0x4AC0, oneop, "tas",
  0xFF00, 0x4A00, soneop, "tst",
  0xFFC0, 0x4C00, olmul, "mul",
  0xFFC0, 0x4C10, olmul, "div",
  0xFFF0, 0x4E40, otrap, 0,
  0xFFF8, 0x4E50, olink, 0,
  0xFFF8, 0x4E58, oreg, "\tunlk\ta%ld",
  0xFFF8, 0x4E60, oreg, "\tmove\ta%ld,usp",
  0xFFF8, 0x4E68, oreg, "\tmove\tusp,a%ld",
  0xFFFF, 0x4E70, oprint, "reset",
  0xFFFF, 0x4E71, oprint, "nop",
  0xFFFF, 0x4E72, oprint, "stop",
  0xFFFF, 0x4E73, oprint, "rte",
  0xFFFF, 0x4E75, oprint, "rts",
  0xFFFF, 0x4E76, oprint, "trapv",
  0xFFFF, 0x4E77, oprint, "rtr",
  0xFFC0, 0x4E80, oneop, "jsr",
  0xFFC0, 0x4EC0, oneop, "jmp",
  0xF140, 0x4100, ochk, "chk",		/* 68020 modified */
  0xF1C0, 0x41C0, ochk, "lea",
  0xF0C0, 0x50C0, oscc, 0,
  0xF100, 0x5000, oquick, "addq",
  0xF100, 0x5100, oquick, "subq",
  0xF0F8, 0x50F8, otrapcc, 0,
  0xF000, 0x7000, omoveq, 0,
  0xF1C0, 0x80C0, ochk, "divu",
  0xF1C0, 0x81C0, ochk, "divs",
  0xF1F0, 0x8100, extend, "sbcd",
  0xF000, 0x8000, opmode, "or",
  0xF1C0, 0x91C0, opmode, "sub",
  0xF130, 0x9100, extend, "subx",
  0xF000, 0x9000, opmode, "sub",
  0xF1C0, 0xB1C0, opmode, "cmp",
  0xF138, 0xB108, extend, "cmpm",
  0xF100, 0xB000, opmode, "cmp",
  0xF100, 0xB100, opmode, "eor",
  0xF1C0, 0xC0C0, ochk, "mulu",
  0xF1C0, 0xC1C0, ochk, "muls",
  0xF1F8, 0xC188, extend, "exg",
  0xF1F8, 0xC148, extend, "exg",
  0xF1F8, 0xC140, extend, "exg",
  0xF1F0, 0xC100, extend, "abcd",
  0xF000, 0xC000, opmode, "and",
  0xF1C0, 0xD1C0, opmode, "add",
  0xF130, 0xD100, extend, "addx",
  0xF000, 0xD000, opmode, "add",
  0xF8C0, 0xE8C0, obits, 0,
  0xF100, 0xE000, shroi, "r",
  0xF100, 0xE100, shroi, "l",
  0xF1C0, 0xF000, cpgen, 0,
  0xF1F8, 0xF048, cpdbcc, 0,
  0xF1F8, 0xF078, cptrap, 0,
  0xF1C0, 0xF040, cpscc, 0,
  0xF1C0, 0xF080, cpbcc, 0,
  0xF1C0, 0xF100, cpsave, 0,
  0xF1C0, 0xF140, cprest, 0,
  0, 0, 0, 0
};

export int vcbInst;

static long ladr; /* instruction pointer */
int spacehint = -1;

export void PrintInstruction(adr)
long adr;
{
	register int inst;
	register struct opdesc *p;
	register int (*fun)();
	pBPR	bp;

	if ((bp = BpFAdr(adr, true)) != bpNil)
	    RemoveBp(bp); /* don't show then them the break */

	IMDF = "#%ld."; /* what to do ?? ERR */

	ladr = adr;
	inst = instfetch(2) & 0xffff;
	for (p = opdecode; p->mask; p++)
	    if ((inst & p->mask) == p->match)
		break;

	if (p->mask != 0)
	    (*p->opfun)(inst, p->farg);
	else
	    printf(badop);
	vcbInst = ladr - adr;
} /* PrintInstruction */

long
instfetch(size)
int size;
{
	long l;

	l = GetWord(ladr, spaceText);
	if (size==2)
	    l = (short)(l>>16);
	ladr += size;
	return(l);
}

printc(c) {
    printf("%c",c);
}

getdisp(size)
{
    switch(size) {
    case 0:
    case 1:
	return(0);
    case 2:
	return(instfetch(2));
    case 3:
	return(instfetch(4));
/*
    default:
	Panic("Bad addressing operand.");
*/
    }
}

fullformat(reg, index)
long reg, index;
{
    long base;
    long outer;

    base = getdisp((index>>4)&0x3);
    outer = getdisp(index&0x3);

    printf("(");
    if(index&0x07) {
	printf("[");
    }

    if((base != 0) || ((index&0x80) && ((index&0x40)||(index&0x04)))) {
	if((index&0x30) == 0x30)
	    printf("0x%08x", base);
	else
	    printf("0x%04x", base);
	if(((index&0x80)==0x00)||(((index&0x40)==0x00)&&((index&0x04)==0x00)))
	    printf(",");
    }

    if((index&0x80) == 0x00)
	if(reg == (-1))
	    printf("pc");
	else
	    printf("a%d", reg);

    if((index&0x04) && ((index&0x07) != 0))
	printf("]");

    if((index&0x40) == 0x00) {
	if((index&0x04) || ((index&0x80) == 0x00))
	    printf(",");
	printf("%c%d", (index&0x8000)?'a':'d', (index>>12)&0x7);
	if(index&0x0600) {
	    printf("*%d", vcbScale[(index>>9)&0x3]);
	}
    }

    if(((index&0x04) == 0x00) && ((index&0x07) != 0))
	printf("]");

    if((index & 0x03) && outer != 0) {
	if((index&0x03) == 0x03)
	    printf("%#8x", outer);
	else
	    printf("%#4x", outer);
    }

    printf(")");
}

printea(mode, reg, size)
long mode, reg;
int size;
{
    register long index,disp;
    register long i; /* random temp */

    switch ((int)(mode)) {
      default:	printf("???"); break;

      case 0:	printf("d%ld",reg);
		    break;

      case 1:	printf("a%ld",reg);
		    break;

      case 2:	printf("a%ld@",reg);
		    break;

      case 3:	printf("a%ld@+",reg);
		    break;

      case 4:	printf("a%ld@-",reg);
		    break;

      case 5:	{ int offset = instfetch(2);
		    if (reg == 6) {
			char * sb;
			/* we try to find a nice name for this fp(x) */
			sb = SbFStackOffset(ladr, 1, offset);
			if (sb != 0)
			    printf("%s", sb);
			else
			    printf("a%ld@(%ld.)", reg, offset);
		    } else {
			printf("a%ld@(%ld.)", reg, offset);
		    } /* if */
		break;
		}

      case 6:	index = instfetch(2);
		    disp = (char)(index&0377);
/* (CPU == M68020) */
		    if(index&0x0700) {
			if(index&0x0100) {
			    fullformat(reg, index);
			}
			else {
			    printf("a%d@(%d,%c%ld%c*%d)", reg, disp,
			      (index&0100000)?'a':'d',(index>>12)&07,
			      (index&04000)?'l':'w', vcbScale[(index>>9)&0x03]);
			}
			break;
		    }
/* (CPU == M68020) */
		    printf("a%d@(%d,%c%ld%c)", reg, disp,
		      (index&0100000)?'a':'d',(index>>12)&07,
		      (index&04000)?'l':'w');
		    break;

      case 7:	switch ((int)(reg)) {
		  default:	printf("???"); break;

		  case 0:	index = instfetch(2);
				printf("%x:w",index);
				break;

		  case 1:	index = instfetch(4);
				if(spacehint == spaceText) {
				    PrintPosition(index, fmtProc+fmtLn);
				    break;
				} else {
				    printf("%s",
					SbFNearest(index, true, true, false));
				}
				break;

		  case 2:	printf("pc@(%ld.)",instfetch(2));
				break;

		  case 3:	index = instfetch(2);
				disp = (char)(index&0377);
/* (CPU == M68020) */
				if(index&0x0700) {
				    if(index&0x0100) {
					fullformat(-1L, index);
				    }
				    else {
					printf("pc@(%d,%c%ld%c*%d)",
					    disp,
					    (index&0100000)?'a':'d',
					    (index>>12)&07,
					    (index&04000)?'l':'w',
					    vcbScale[(index>>9)&0x03]);
				    }
				    break;
				}
/* (CPU == M68020) */
				printf("pc@(%ld,%c%ld:%c)", disp,
				(index&0100000) ? 'a' : 'd', (index>>12)&07,
				(index&04000) ? 'l' : 'w');
				break;

		  case 4:	index = instfetch(size==4?4:2);
				printf(IMDF, index);
				break;
	    } /* switch */
	    break;
    } /* switch */
}

printEA(ea,size)
long ea;
int size;
{
	printea((ea>>3)&07,ea&07,size);
}

mapsize(inst)
long inst;
{
	inst >>= 6;
	inst &= 03;
	return((inst==0) ? 1 : (inst==1) ? 2 : (inst==2) ? 4 : -1);
}

char suffix(size)
register int size;
{
	return((size==1) ? 'b' : (size==2) ? 'w' : (size==4) ? 'l' : '?');
}

omove(inst, s)
long inst;
char *s;
{
	int size;

	printf("\tmov%c\t",*s);
	size = ((*s == 'b') ? 1 : (*s == 'w') ? 2 : 4);
	printea((inst>>3)&07,inst&07,size);
	printc(',');
	printea((inst>>6)&07,(inst>>9)&07,size);
}

obranch(inst,dummy)
long inst;
{
	long disp = inst & 0377;
	char *s; 
	int pcrel = ladr;

	s = "s ";
	if (disp > 127) disp |= ~0377;
	else if (disp == 0) { s = " "; disp = instfetch(2); }
/* 68020 */
	else if (disp == 0xff) { s = " "; disp = instfetch(4); }
/* 68020 */
	printf("\tb%s%s\t",bname[(int)((inst>>8)&017)],s);
	PrintPosition(disp+pcrel, fmtProc+fmtLn);
	/*printf("ps2:%x",disp+pcrel);*/
	/*psymoff(disp+inkdot(2), ISYM, "");*/
}

oscc(inst,dummy)
long inst;
{
	printf("\ts%s\t",bname[(int)((inst>>8)&017)]);
	printea((inst>>3)&07,inst&07,1);
}

biti(inst, dummy)
long inst;
{
	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
	if (inst&0x0100) printf("d%ld,", inst>>9);
	else { printf(IMDF, instfetch(2)); printc(','); }
	printEA(inst);
}

opmode(inst,opcode)
long inst;
{
	register int opmode = (int)((inst>>6) & 07);
	register int reg = (int)((inst>>9) & 07);
	int size;

	size = (opmode==0 || opmode==4) ?
		1 : (opmode==1 || opmode==3 || opmode==5) ? 2 : 4;
	printf("\t%s%c\t", opcode, suffix(size));
	if (opmode>=4 && opmode<=6)
	{
		printf("d%d,",reg);
		printea((inst>>3)&07,inst&07, size);
	}
	else
	{
		printea((inst>>3)&07,inst&07, size);
		printf(",%c%d",(opmode<=2)?'d':'a',reg);
	}
}

shroi(inst,ds)
long inst;
char *ds;
{
	int rx, ry;
	char *opcode;
	if ((inst & 0xC0) == 0xC0)
	{
		opcode = shro[(int)((inst>>9)&03)];
		printf("\t%s%s\t", opcode, ds);
		printEA(inst);
	}
	else
	{
		opcode = shro[(int)((inst>>3)&03)];
		printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
		rx = (int)((inst>>9)&07); ry = (int)(inst&07);
		if ((inst>>5)&01) printf("d%d,d%d", rx, ry);
		else
		{
			printf(IMDF, (rx ? rx : 8));
			printf(",d%d", ry);
		}
	}
}		

oimmed(inst,opcode) 
long inst;
register char *opcode;
{
	register int size = mapsize(inst);
	long const;

	if (size > 0)
	{
		const = instfetch(size==4?4:2);
		printf("\t%s%c\t", opcode, suffix(size));
		printf(IMDF, const); printc(',');
		printEA(inst,size);
	}
	else printf(badop);
}

oreg(inst,opcode)
long inst;
register char *opcode;
{
	printf(opcode, (inst & 07));
}

extend(inst, opcode)
long	inst;
char	*opcode;
{
	register int size = mapsize(inst);
	int ry = (inst&07), rx = ((inst>>9)&07);
	char c;

	c = ((inst & 0x1000) ? suffix(size) : ' ');
	printf("\t%s%c\t", opcode, c);
	if (*opcode == 'e')
	{
		if (inst & 0x0080) printf("d%ld,a%ld", rx, ry);
		else if (inst & 0x0008) printf("a%ld,a%ld", rx, ry);
		else printf("d%ld,d%ld", rx, ry);
	}
	else if ((inst & 0xF000) == 0xB000) printf("a%ld@+,a%ld@+", ry, rx);
	else if (inst & 0x8) printf("a%ld@-,a%ld@-", ry, rx);
	else printf("d%ld,d%ld", ry, rx);
}

olink(inst,dummy)
long inst;
{
	printf("\tlink\ta%ld,", inst&07);
	if(inst&0x08)
	    printf(IMDF, instfetch(4));		/* 68020 */
	else
	    printf(IMDF, instfetch(2));
}

otrap(inst,dummy)
long inst;
{
	printf("\ttrap\t");
	printf(IMDF, inst&017);
}

oneop(inst,opcode)
long inst;
register char *opcode;
{
	if( *opcode == 'j' ) spacehint = spaceText;
	printf("\t%s\t",opcode);
	printEA(inst);
	spacehint = -1;
}

pregmask(mask)
register int mask;
{
	register int i;
	register int flag = 0;

	printf("#<");
	for (i=0; i<16; i++)
	{
		if (mask&1)
		{
			if (flag) printc(','); else flag++;
			printf("%c%d",(i<8)?'d':'a',i&07);
		}
		mask >>= 1;
	}
	printf(">");
}

omovem(inst,dummy)
long inst;
{
	register int i, list = 0, mask = 0100000;
	register int reglist = (int)(instfetch(2));

	if ((inst & 070) == 040)	/* predecrement */
	{
		for(i = 15; i > 0; i -= 2)
		{ list |= ((mask & reglist) >> i); mask >>= 1; }
		for(i = 1; i < 16; i += 2)
		{ list |= ((mask & reglist) << i); mask >>= 1; }
		reglist = list;
	}
	printf("\tmovem%c\t",(inst&100)?'l':'w');
	if (inst&02000)
	{
		printEA(inst);
		printc(',');
		pregmask(reglist);
	}
	else
	{
		pregmask(reglist);
		printc(',');
		printEA(inst);
	}
}

ochk(inst,opcode)
long inst;
register char *opcode;
{
	printf("\t%s\t",opcode);
	printEA(inst, (inst&0x80)?2:4);
	printf(",%c%ld",(*opcode=='l')?'a':'d',(inst>>9)&07);
}

soneop(inst,opcode)
long inst;
register char *opcode;
{
	register int size = mapsize(inst);

	if (size > 0)
	{
		printf("\t%s%c\t",opcode,suffix(size));
		printEA(inst);
	}
	else printf(badop);
}

oquick(inst,opcode)
long inst;
register char *opcode;
{
	register int size = mapsize(inst);
	register int data = (int)((inst>>9) & 07);

	if (data == 0) data = 8;
	if (size > 0)
	{
		printf("\t%s%c\t", opcode, suffix(size));
		printf(IMDF, data); printc(',');
		printEA(inst);
	}
	else printf(badop);
}

omoveq(inst,dummy)
long inst;
{
	register int data = (int)(inst & 0377);

	if (data > 127) data |= ~0377;
	printf("\tmoveq\t"); printf(IMDF, data);
	printf(",d%ld", (inst>>9)&07);
}

oprint(inst,opcode)
long inst;
register char *opcode;
{
	printf("\t%s",opcode);
}

/*** 68020 instructions ***/

obkpt(inst)
long inst;
{
    printf("\tbkpt\t%d", inst&0x07);
}

ocallm(inst)
long inst;
{
	/* also RTM */
	/* FIXME */
}

ocas(inst)
long inst;
{
	/* FIXME */
}

ochk2(inst)
long inst;
{
	/* also the cmp2 instruction */
	/* FIXME */
}

olmul(inst, opcode)
long inst;
register char *opcode;
{
	long extra = instfetch(2);

	printf("\t%s", opcode);

	printEA(inst, 0);
	/* FIXME */
}

char *trapccname[16] = {
    "t",  "f",  "hi", "ls",
    "cc", "cs", "ne", "eq",
    "vc", "vs", "pl", "mi",
    "ge", "lt", "gt", "le"
};

otrapcc(inst)
long inst;
{
    long operand;

    printf("\ttrap\t%s", trapccname[(inst>>8)&0x0f]);

    switch(inst&0x07) {
    case 0x02:
	operand = instfetch(2);
	printf(",#0x%04x", operand);
	break;
    case 0x03:
	operand = instfetch(4);
	printf(",#0x%08x", operand);
	break;
    case 0x04:
	operand = 0;
	break;
    }
}	

char *bitfld[8] = {
	"bftst",
	"bfextu",
	"bfchg",
	"bfexts",
	"bfclr",
	"bfffo",
	"bfset",
	"bfins"
};

obits(inst)
long inst;
{
    long extra = instfetch(2);

    printf("%s", bitfld[(inst>>8)&0x0f]);
    if((inst&0x0700) == 0x0700)
	printf("d%d,", (extra>>12)&0x07);

    printEA(inst, 0);

    if(extra&0x0800)
	printf("{d%d:", (extra>>6)&0x7);
    else
	printf("{%d:", (extra>>6)&0x1f);
    if(extra&0x0020)
	printf("d%d}", extra&0x7);
    else
	printf("%d}", extra&0x1f);

    if((inst&0x0700) != 0x0700 && (inst&0x0100))
	printf(",d%d", (extra>>12)&0x07);
}

cpgen(inst)
long inst;
{
    long extra;

    extra = instfetch(2);
    printf("\tcpGEN\t%d,0x%04x,", (inst>>9)&0x07, extra&0xffff);
    printEA(inst, 0);
}


cpdbcc(inst)
long inst;
{
    long extra;
    long disp;
    int pcrel = ladr;

    extra = instfetch(2);
    disp = instfetch(2);
    printf("\tcpDBcc\t%d,d%d,0x%04x,", (inst>>9)&0x07, inst&0x07, extra&0xffff);
    PrintPosition(disp+pcrel, fmtProc+fmtLn);
}


cptrap(inst)
long inst;
{
    long extra;
    long operand;

    extra = instfetch(2);
    printf("\tcpDBcc\t%d,0x%04x,", (inst>>9)&0x07, extra&0xffff);
    switch(inst&0x07) {
    case 0x02:
	operand = instfetch(2);
	break;	
    case 0x03:
	operand = instfetch(4);
	break;	
    case 0x04:
	break;
    }
}


cpscc(inst)
long inst;
{
    long extra;

    extra = instfetch(2);
    printf("\tcpScc\t%d,0x%04x,", (inst>>9)&0x07, extra&0xffff);
    printEA(inst, 0);
}


cpbcc(inst)
long inst;
{
}


cpsave(inst)
long inst;
{
}


cprest(inst)
long inst;
{
}

0707070001000312221004440000000000010000011603610454650113600001400000037437cdb/dis68.c #
/****************************************************************************

	DEBUGGER - 68000 instruction printout

****************************************************************************/

#include "cdb.h"


char *badop = "\t???";
char *IMDF;				/* immediate data format */

char *bname[16] = { "ra", "sr", "hi", "ls", "cc", "cs", "ne",
		    "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le" };

char *shro[4] = { "as", "ls", "rox", "ro" };

char *bit[4] = { "btst", "bchg", "bclr", "bset" };

int vcbScale[] = { 1, 2, 4, 8 };

int omove(),obranch(),oimmed(),oprint(),oneop(),soneop(),oreg(),ochk();
int olink(),omovem(),oquick(),omoveq(),otrap(),oscc(),opmode(),shroi();
int extend(),biti();

int obkpt(), ocallm(), ocas(), ochk2(), olmul(), otrapcc(), obits();
int cpgen(), cpscc(), cpdbcc(), cptrap(), cpbcc(), cpsave(), cprest();


struct opdesc
{			
	unsigned short mask, match;
	int (*opfun)();
	char *farg;
} opdecode[] =
{					/* order is important below */
  0xF000, 0x1000, omove, "b",		/* move instructions */
  0xF000, 0x2000, omove, "l",
  0xF000, 0x3000, omove, "w",
  0xF000, 0x6000, obranch, 0,		/* branches */
  0xFF00, 0x0000, oimmed, "or",		/* op class 0  */
  0xF9C0, 0x00C0, ochk2, 0,		/* 68020 */
  0xFF00, 0x0200, oimmed, "and",
  0xFF00, 0x0400, oimmed, "sub",
  0xFFC0, 0x06C0, ocallm, 0,		/* 68020 */
  0xFF00, 0x0600, oimmed, "add",
  0xFF00, 0x0A00, oimmed, "eor",
  0xFF00, 0x0C00, oimmed, "cmp",
  0xF100, 0x0100, biti, 0,
  0xFF00, 0x0800, biti, 0,
  0xF9C0, 0x08C0, ocas, 0,		/* 68020 */
  0xFFC0, 0x40C0, oneop, "move_from_sr", /* op class 4 */
  0xFF00, 0x4000, soneop, "negx",
  0xFF00, 0x4200, soneop, "clr",
  0xFFC0, 0x44C0, oneop, "move_to_ccr",
  0xFF00, 0x4400, soneop, "neg",
  0xFFC0, 0x46C0, oneop, "move_to_sr",
  0xFF00, 0x4600, soneop, "not",
  0xFFF8, 0x4808, olink, "link",			/* 68020 */
  0xFFC0, 0x4800, oneop, "nbcd",
  0xFFF8, 0x4840, oreg, "\tswap\td%ld",
  0xFFF8, 0x4848, obkpt, 0,				/* 68020 */
  0xFFC0, 0x4840, oneop, "pea",
  0xFFF8, 0x49C0, oreg, "\textb\td%ld",			/* 68020 */
  0xFFF8, 0x4880, oreg, "\textw\td%ld",
  0xFFF8, 0x48C0, oreg, "\textl\td%ld",
  0xFB80, 0x4880, omovem, 0,
  0xFFC0, 0x4AC0, oneop, "tas",
  0xFF00, 0x4A00, soneop, "tst",
  0xFFC0, 0x4C00, olmul, "mul",
  0xFFC0, 0x4C10, olmul, "div",
  0xFFF0, 0x4E40, otrap, 0,
  0xFFF8, 0x4E50, olink, 0,
  0xFFF8, 0x4E58, oreg, "\tunlk\ta%ld",
  0xFFF8, 0x4E60, oreg, "\tmove\ta%ld,usp",
  0xFFF8, 0x4E68, oreg, "\tmove\tusp,a%ld",
  0xFFFF, 0x4E70, oprint, "reset",
  0xFFFF, 0x4E71, oprint, "nop",
  0xFFFF, 0x4E72, oprint, "stop",
  0xFFFF, 0x4E73, oprint, "rte",
  0xFFFF, 0x4E75, oprint, "rts",
  0xFFFF, 0x4E76, oprint, "trapv",
  0xFFFF, 0x4E77, oprint, "rtr",
  0xFFC0, 0x4E80, oneop, "jsr",
  0xFFC0, 0x4EC0, oneop, "jmp",
  0xF140, 0x4100, ochk, "chk",		/* 68020 modified */
  0xF1C0, 0x41C0, ochk, "lea",
  0xF0C0, 0x50C0, oscc, 0,
  0xF100, 0x5000, oquick, "addq",
  0xF100, 0x5100, oquick, "subq",
  0xF0F8, 0x50F8, otrapcc, 0,
  0xF000, 0x7000, omoveq, 0,
  0xF1C0, 0x80C0, ochk, "divu",
  0xF1C0, 0x81C0, ochk, "divs",
  0xF1F0, 0x8100, extend, "sbcd",
  0xF000, 0x8000, opmode, "or",
  0xF1C0, 0x91C0, opmode, "sub",
  0xF130, 0x9100, extend, "subx",
  0xF000, 0x9000, opmode, "sub",
  0xF1C0, 0xB1C0, opmode, "cmp",
  0xF138, 0xB108, extend, "cmpm",
  0xF100, 0xB000, opmode, "cmp",
  0xF100, 0xB100, opmode, "eor",
  0xF1C0, 0xC0C0, ochk, "mulu",
  0xF1C0, 0xC1C0, ochk, "muls",
  0xF1F8, 0xC188, extend, "exg",
  0xF1F8, 0xC148, extend, "exg",
  0xF1F8, 0xC140, extend, "exg",
  0xF1F0, 0xC100, extend, "abcd",
  0xF000, 0xC000, opmode, "and",
  0xF1C0, 0xD1C0, opmode, "add",
  0xF130, 0xD100, extend, "addx",
  0xF000, 0xD000, opmode, "add",
  0xF8C0, 0xE8C0, obits, 0,
  0xF100, 0xE000, shroi, "r",
  0xF100, 0xE100, shroi, "l",
  0xF1C0, 0xF000, cpgen, 0,
  0xF1F8, 0xF048, cpdbcc, 0,
  0xF1F8, 0xF078, cptrap, 0,
  0xF1C0, 0xF040, cpscc, 0,
  0xF1C0, 0xF080, cpbcc, 0,
  0xF1C0, 0xF100, cpsave, 0,
  0xF1C0, 0xF140, cprest, 0,
  0, 0, 0, 0
};

export int vcbInst;

static long ladr; /* instruction pointer */
int spacehint = -1;

export void PrintInstruction(adr)
long adr;
{
	register int inst;
	register struct opdesc *p;
	register int (*fun)();
	pBPR	bp;

	if ((bp = BpFAdr(adr, true)) != bpNil)
	    RemoveBp(bp); /* don't show then them the break */

	IMDF = "#%ld."; /* what to do ?? ERR */

	ladr = adr;
	inst = instfetch(2) & 0xffff;
	for (p = opdecode; p->mask; p++)
	    if ((inst & p->mask) == p->match)
		break;

	if (p->mask != 0)
	    (*p->opfun)(inst, p->farg);
	else
	    printf(badop);
	vcbInst = ladr - adr;
} /* PrintInstruction */

long
instfetch(size)
int size;
{
	long l;

	l = GetWord(ladr, spaceText);
	if (size==2)
	    l = (short)(l>>16);
	ladr += size;
	return(l);
}

printc(c) {
    printf("%c",c);
}

getdisp(size)
{
    switch(size) {
    case 0:
    case 1:
	return(0);
    case 2:
	return(instfetch(2));
    case 3:
	return(instfetch(4));
/*
    default:
	Panic("Bad addressing operand.");
*/
    }
}

fullformat(reg, index)
long reg, index;
{
    long base;
    long outer;

    base = getdisp((index>>4)&0x3);
    outer = getdisp(index&0x3);

    printf("(");
    if(index&0x07) {
	printf("[");
    }

    if((base != 0) || ((index&0x80) && ((index&0x40)||(index&0x04)))) {
	if((index&0x30) == 0x30)
	    printf("0x%08x", base);
	else
	    printf("0x%04x", base);
	if(((index&0x80)==0x00)||(((index&0x40)==0x00)&&((index&0x04)==0x00)))
	    printf(",");
    }

    if((index&0x80) == 0x00)
	if(reg == (-1))
	    printf("pc");
	else
	    printf("a%d", reg);

    if((index&0x04) && ((index&0x07) != 0))
	printf("]");

    if((index&0x40) == 0x00) {
	if((index&0x04) || ((index&0x80) == 0x00))
	    printf(",");
	printf("%c%d", (index&0x8000)?'a':'d', (index>>12)&0x7);
	if(index&0x0600) {
	    printf("*%d", vcbScale[(index>>9)&0x3]);
	}
    }

    if(((index&0x04) == 0x00) && ((index&0x07) != 0))
	printf("]");

    if((index & 0x03) && outer != 0) {
	if((index&0x03) == 0x03)
	    printf("%#8x", outer);
	else
	    printf("%#4x", outer);
    }

    printf(")");
}

printea(mode, reg, size)
long mode, reg;
int size;
{
    register long index,disp;
    register long i; /* random temp */

    switch ((int)(mode)) {
      default:	printf("???"); break;

      case 0:	printf("d%ld",reg);
		    break;

      case 1:	printf("a%ld",reg);
		    break;

      case 2:	printf("a%ld@",reg);
		    break;

      case 3:	printf("a%ld@+",reg);
		    break;

      case 4:	printf("a%ld@-",reg);
		    break;

      case 5:	{ int offset = instfetch(2);
		    if (reg == 6) {
			char * sb;
			/* we try to find a nice name for this fp(x) */
			sb = SbFStackOffset(ladr, 1, offset);
			if (sb != 0)
			    printf("%s", sb);
			else
			    printf("a%ld@(%ld.)", reg, offset);
		    } else {
			printf("a%ld@(%ld.)", reg, offset);
		    } /* if */
		break;
		}

      case 6:	index = instfetch(2);
		    disp = (char)(index&0377);
/* (CPU == M68020) */
		    if(index&0x0700) {
			if(index&0x0100) {
			    fullformat(reg, index);
			}
			else {
			    printf("a%d@(%d,%c%ld%c*%d)", reg, disp,
			      (index&0100000)?'a':'d',(index>>12)&07,
			      (index&04000)?'l':'w', vcbScale[(index>>9)&0x03]);
			}
			break;
		    }
/* (CPU == M68020) */
		    printf("a%d@(%d,%c%ld%c)", reg, disp,
		      (index&0100000)?'a':'d',(index>>12)&07,
		      (index&04000)?'l':'w');
		    break;

      case 7:	switch ((int)(reg)) {
		  default:	printf("???"); break;

		  case 0:	index = instfetch(2);
				printf("%x:w",index);
				break;

		  case 1:	index = instfetch(4);
				if(spacehint == spaceText) {
				    PrintPosition(index, fmtProc+fmtLn);
				    break;
				} else {
				    printf("%s",
					SbFNearest(index, true, true, false));
				}
				break;

		  case 2:	printf("pc@(%ld.)",instfetch(2));
				break;

		  case 3:	index = instfetch(2);
				disp = (char)(index&0377);
/* (CPU == M68020) */
				if(index&0x0700) {
				    if(index&0x0100) {
					fullformat(-1L, index);
				    }
				    else {
					printf("pc@(%d,%c%ld%c*%d)",
					    disp,
					    (index&0100000)?'a':'d',
					    (index>>12)&07,
					    (index&04000)?'l':'w',
					    vcbScale[(index>>9)&0x03]);
				    }
				    break;
				}
/* (CPU == M68020) */
				printf("pc@(%ld,%c%ld:%c)", disp,
				(index&0100000) ? 'a' : 'd', (index>>12)&07,
				(index&04000) ? 'l' : 'w');
				break;

		  case 4:	index = instfetch(size==4?4:2);
				printf(IMDF, index);
				break;
	    } /* switch */
	    break;
    } /* switch */
}

printEA(ea,size)
long ea;
int size;
{
	printea((ea>>3)&07,ea&07,size);
}

mapsize(inst)
long inst;
{
	inst >>= 6;
	inst &= 03;
	return((inst==0) ? 1 : (inst==1) ? 2 : (inst==2) ? 4 : -1);
}

char suffix(size)
register int size;
{
	return((size==1) ? 'b' : (size==2) ? 'w' : (size==4) ? 'l' : '?');
}

omove(inst, s)
long inst;
char *s;
{
	int size;

	printf("\tmov%c\t",*s);
	size = ((*s == 'b') ? 1 : (*s == 'w') ? 2 : 4);
	printea((inst>>3)&07,inst&07,size);
	printc(',');
	printea((inst>>6)&07,(inst>>9)&07,size);
}

obranch(inst,dummy)
long inst;
{
	long disp = inst & 0377;
	char *s; 
	int pcrel = ladr;

	s = "s ";
	if (disp > 127) disp |= ~0377;
	else if (disp == 0) { s = " "; disp = instfetch(2); }
/* 68020 */
	else if (disp == 0xff) { s = " "; disp = instfetch(4); }
/* 68020 */
	printf("\tb%s%s\t",bname[(int)((inst>>8)&017)],s);
	PrintPosition(disp+pcrel, fmtProc+fmtLn);
	/*printf("ps2:%x",disp+pcrel);*/
	/*psymoff(disp+inkdot(2), ISYM, "");*/
}

oscc(inst,dummy)
long inst;
{
	printf("\ts%s\t",bname[(int)((inst>>8)&017)]);
	printea((inst>>3)&07,inst&07,1);
}

biti(inst, dummy)
long inst;
{
	printf("\t%s\t", bit[(int)((inst>>6)&03)]);
	if (inst&0x0100) printf("d%ld,", inst>>9);
	else { printf(IMDF, instfetch(2)); printc(','); }
	printEA(inst);
}

opmode(inst,opcode)
long inst;
{
	register int opmode = (int)((inst>>6) & 07);
	register int reg = (int)((inst>>9) & 07);
	int size;

	size = (opmode==0 || opmode==4) ?
		1 : (opmode==1 || opmode==3 || opmode==5) ? 2 : 4;
	printf("\t%s%c\t", opcode, suffix(size));
	if (opmode>=4 && opmode<=6)
	{
		printf("d%d,",reg);
		printea((inst>>3)&07,inst&07, size);
	}
	else
	{
		printea((inst>>3)&07,inst&07, size);
		printf(",%c%d",(opmode<=2)?'d':'a',reg);
	}
}

shroi(inst,ds)
long inst;
char *ds;
{
	int rx, ry;
	char *opcode;
	if ((inst & 0xC0) == 0xC0)
	{
		opcode = shro[(int)((inst>>9)&03)];
		printf("\t%s%s\t", opcode, ds);
		printEA(inst);
	}
	else
	{
		opcode = shro[(int)((inst>>3)&03)];
		printf("\t%s%s%c\t", opcode, ds, suffix(mapsize(inst)));
		rx = (int)((inst>>9)&07); ry = (int)(inst&07);
		if ((inst>>5)&01) printf("d%d,d%d", rx, ry);
		else
		{
			printf(IMDF, (rx ? rx : 8));
			printf(",d%d", ry);
		}
	}
}		

oimmed(inst,opcode) 
long inst;
register char *opcode;
{
	register int size = mapsize(inst);
	long const;

	if (size > 0)
	{
		const = instfetch(size==4?4:2);
		printf("\t%s%c\t", opcode, suffix(size));
		printf(IMDF, const); printc(',');
		printEA(inst,size);
	}
	else printf(badop);
}

oreg(inst,opcode)
long inst;
register char *opcode;
{
	printf(opcode, (inst & 07));
}

extend(inst, opcode)
long	inst;
char	*opcode;
{
	register int size = mapsize(inst);
	int ry = (inst&07), rx = ((inst>>9)&07);
	char c;

	c = ((inst & 0x1000) ? suffix(size) : ' ');
	printf("\t%s%c\t", opcode, c);
	if (*opcode == 'e')
	{
		if (inst & 0x0080) printf("d%ld,a%ld", rx, ry);
		else if (inst & 0x0008) printf("a%ld,a%ld", rx, ry);
		else printf("d%ld,d%ld", rx, ry);
	}
	else if ((inst & 0xF000) == 0xB000) printf("a%ld@+,a%ld@+", ry, rx);
	else if (inst & 0x8) printf("a%ld@-,a%ld@-", ry, rx);
	else printf("d%ld,d%ld", ry, rx);
}

olink(inst,dummy)
long inst;
{
	printf("\tlink\ta%ld,", inst&07);
	if(inst&0x08)
	    printf(IMDF, instfetch(4));		/* 68020 */
	else
	    printf(IMDF, instfetch(2));
}

otrap(inst,dummy)
long inst;
{
	printf("\ttrap\t");
	printf(IMDF, inst&017);
}

oneop(inst,opcode)
long inst;
register char *opcode;
{
	if( *opcode == 'j' ) spacehint = spaceText;
	printf("\t%s\t",opcode);
	printEA(inst);
	spacehint = -1;
}

pregmask(mask)
register int mask;
{
	register int i;
	register int flag = 0;

	printf("#<");
	for (i=0; i<16; i++)
	{
		if (mask&1)
		{
			if (flag) printc(','); else flag++;
			printf("%c%d",(i<8)?'d':'a',i&07);
		}
		mask >>= 1;
	}
	printf(">");
}

omovem(inst,dummy)
long inst;
{
	register int i, list = 0, mask = 0100000;
	register int reglist = (int)(instfetch(2));

	if ((inst & 070) == 040)	/* predecrement */
	{
		for(i = 15; i > 0; i -= 2)
		{ list |= ((mask & reglist) >> i); mask >>= 1; }
		for(i = 1; i < 16; i += 2)
		{ list |= ((mask & reglist) << i); mask >>= 1; }
		reglist = list;
	}
	printf("\tmovem%c\t",(inst&100)?'l':'w');
	if (inst&02000)
	{
		printEA(inst);
		printc(',');
		pregmask(reglist);
	}
	else
	{
		pregmask(reglist);
		printc(',');
		printEA(inst);
	}
}

ochk(inst,opcode)
long inst;
register char *opcode;
{
	printf("\t%s\t",opcode);
	printEA(inst, (inst&0x80)?2:4);
	printf(",%c%ld",(*opcode=='l')?'a':'d',(inst>>9)&07);
}

soneop(inst,opcode)
long inst;
register char *opcode;
{
	register int size = mapsize(inst);

	if (size > 0)
	{
		printf("\t%s%c\t",opcode,suffix(size));
		printEA(inst);
	}
	else printf(badop);
}

oquick(inst,opcode)
long inst;
register char *opcode;
{
	register int size = mapsize(inst);
	register int data = (int)((inst>>9) & 07);

	if (data == 0) data = 8;
	if (size > 0)
	{
		printf("\t%s%c\t", opcode, suffix(size));
		printf(IMDF, data); printc(',');
		printEA(inst);
	}
	else printf(badop);
}

omoveq(inst,dummy)
long inst;
{
	register int data = (int)(inst & 0377);

	if (data > 127) data |= ~0377;
	printf("\tmoveq\t"); printf(IMDF, data);
	printf(",d%ld", (inst>>9)&07);
}

oprint(inst,opcode)
long inst;
register char *opcode;
{
	printf("\t%s",opcode);
}

/*** 68020 instructions ***/

obkpt(inst)
long inst;
{
    printf("\tbkpt\t%d", inst&0x07);
}

ocallm(inst)
long inst;
{
	/* also RTM */
	/* FIXME */
}

ocas(inst)
long inst;
{
	/* FIXME */
}

ochk2(inst)
long inst;
{
	/* also the cmp2 instruction */
	/* FIXME */
}

olmul(inst, opcode)
long inst;
register char *opcode;
{
	long extra = instfetch(2);

	printf("\t%s", opcode);

	printEA(inst, 0);
	/* FIXME */
}

char *trapccname[16] = {
    "t",  "f",  "hi", "ls",
    "cc", "cs", "ne", "eq",
    "vc", "vs", "pl", "mi",
    "ge", "lt", "gt", "le"
};

otrapcc(inst)
long inst;
{
    long operand;

    printf("\ttrap\t%s", trapccname[(inst>>8)&0x0f]);

    switch(inst&0x07) {
    case 0x02:
	operand = instfetch(2);
	printf(",#0x%04x", operand);
	break;
    case 0x03:
	operand = instfetch(4);
	printf(",#0x%08x", operand);
	break;
    case 0x04:
	operand = 0;
	break;
    }
}	

char *bitfld[8] = {
	"bftst",
	"bfextu",
	"bfchg",
	"bfexts",
	"bfclr",
	"bfffo",
	"bfset",
	"bfins"
};

obits(inst)
long inst;
{
    long extra = instfetch(2);

    printf("%s", bitfld[(inst>>8)&0x0f]);
    if((inst&0x0700) == 0x0700)
	printf("d%d,", (extra>>12)&0x07);

    printEA(inst, 0);

    if(extra&0x0800)
	printf("{d%d:", (extra>>6)&0x7);
    else
	printf("{%d:", (extra>>6)&0x1f);
    if(extra&0x0020)
	printf("d%d}", extra&0x7);
    else
	printf("%d}", extra&0x1f);

    if((inst&0x0700) != 0x0700 && (inst&0x0100))
	printf(",d%d", (extra>>12)&0x07);
}

cpgen(inst)
long inst;
{
    long extra;

    extra = instfetch(2);
    printf("\tcpGEN\t%d,0x%04x,", (inst>>9)&0x07, extra&0xffff);
    printEA(inst, 0);
}


cpdbcc(inst)
long inst;
{
    long extra;
    long disp;
    int pcrel = ladr;

    extra = instfetch(2);
    disp = instfetch(2);
    printf("\tcpDBcc\t%d,d%d,0x%04x,", (inst>>9)&0x07, inst&0x07, extra&0xffff);
    PrintPosition(disp+pcrel, fmtProc+fmtLn);
}


cptrap(inst)
long inst;
{
    long extra;
    long operand;

    extra = instfetch(2);
    printf("\tcpDBcc\t%d,0x%04x,", (inst>>9)&0x07, extra&0xffff);
    switch(inst&0x07) {
    case 0x02:
	operand = instfetch(2);
	break;	
    case 0x03:
	operand = instfetch(4);
	break;	
    case 0x04:
	break;
    }
}


cpscc(inst)
long inst;
{
    long extra;

    extra = instfetch(2);
    printf("\tcpScc\t%d,0x%04x,", (inst>>9)&0x07, extra&0xffff);
    printEA(inst, 0);
}


cpbcc(inst)
long inst;
{
}


cpsave(inst)
long inst;
{
}


cprest(inst)
long inst;
{
}

0707070001000312231004440000000000010000011601210454650113600001300000003014cdb/help.c /* $Header: help.c,v 5.7 86/05/28 08:03:49 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This module does the help invocation and FindAndFixBug */

#include "cdb.h"

char	*vrgSbMsg[] = {
	"No known bugs.",
	"I can see the problem, but it will do you good to find it yourself.",
	"Things look good, but you may have a halting problem.",
	"Hmm, seems to be in the hardware.",
	"Have you considered that it might be the work of Communists Mutants?",
	"Not known not to work.",
	"Aha!!! It's.... no, that's not it.",
	"You expected this command to work?",
	"I don't know. I'd much rather play rogue.",
	"There's no bug in this program. It's the C optimizer!!",
	"Cosmic ray error - use smaller chips.",
	"This command available in CDB Version 84.3 and later",
	"brain damage (core dumped) (mos dumped) (everything dumped)"
	};
#define cMsg (sizeof vrgSbMsg / sizeof vrgSbMsg[0])

long time();

/* H E L P */

export void Help()
{
    FILE	*fp;
    char	sb[128];

#ifndef HELP_FILE
#define HELP_FILE "/usr/lib/cdbhelp.text"
#endif
    if ((fp = fopen(HELP_FILE, "r")) == NULL)
	SysPanic("Cannot open help file %s.", HELP_FILE);

    MoreOn();
    while (fgets(sb, sizeof(sb), fp) != NULL)
	printf("%s", sb);
    MoreOff();
    fclose(fp);
} /* Help */


/* F I N D   A N D   F I X */

export void FindAndFix()
{
    int		i;
    long	x;

    time(&x);
    srand((int)x);
    i = rand() % (cMsg+1);
    if (i < cMsg)
	printf("%s\n", vrgSbMsg[i]);
    else
	system ("/usr/games/fortune");
} /* FindAndFix */
0707070001000312241004440000000000010000011601370454650113600001100000011104cdb/l2.c /* This program is used to test and to demonstrate
 * the features of CDB.  It tries to have a "little
 * of everything", so it doesn't make much sense.
 */

#include <stdio.h>
#include <signal.h>

typedef union {
	struct { int s11; } s1;
	struct { int s21, s22; } s2;
	struct { int s31, s32, s33; } s3;
	} U1U, *pU1U;
U1U	a_union;

struct foo {
	struct foo *fooNext;
	struct bar *pbar;  /* points at undefined struct */
	} afoo;

typedef struct foo *pFOOR;

typedef enum COLOR {red, orange, yellow,
		green=10, blue, purple} COLORE;
COLORE	colore;

typedef struct RECS {
	short	a;
	char	b[9];
	long	c;
	unsigned bits1 : 1;
	unsigned bits2 : 2;
	unsigned bits3 : 3;
	unsigned bits4 : 4;
	COLORE	color : 5;
	int	(*prtn)();
	} RECR, *pRECR;

extern int main();
extern int First();
extern char * Second();
extern int Third();

struct RECS a_record = {-1, "Apple Pi",
	987654321L, 1, 2, 4, 8, purple,main};

struct RECS record_array[] = {
	{0, "First",	 0L, 0, 0, 0, 0, red, First},
	{1, "Second",	-1L, 1, 1, 1, 1, orange, main},
	{2, "Third",	-2L, 1, 2, 2, 2, yellow, Third},
	{3, "Fourth",	-3L, 1, 3, 3, 3, green, main},
	{4, "Fifth",	-4L, 1, 1, 4, 4, blue, main},
	{5, "Sixth",	-5L, 1, 2, 5, 5, purple, First},
	};

char	*string_array[5] = { "0", "1", "2", "3", "4" };
char	himom[15] = "Hi there, Mom!";
char	char_array[2][5]= {
			00, 01, 02, 03, 04,
			10, 11, 12, 13, 14,
			};
int	int_array[4][7]= {
			00, 01, 02, 03, 04, 05, 06,
			10, 11, 12, 13, 14, 15, 16,
			20, 21, 22, 23, 24, 25, 26,
			30, 31, 32, 33, 34, 35, 36
			};
char	dbl_array[10][128] = {"0","1","2","3","4","5","6","7","8","9"};
int	loop, seconds, recurse;


/* A L A R M I S T */

Alarmist()
{
    signal(SIGALRM, Alarmist);
    alarm(seconds);
} /* Alarmist /* 


/* M A I N */

int main(argc, argv, envp)
int	argc;
char	*argv[];
char	*envp[];
{
    int		recurseLevel, cMainArgs, i, fUsedArg;
    char	*sbArg, *sbTemp, *sbUsage;

    sbUsage = "Usage: loe [-s #] [-r #]\n";
    cMainArgs = 0;

    for (i = 1; i < argc; ++i) {
	sbArg = argv[i];
	if (*sbArg != '-') {

	    printf(sbUsage);
	    exit(1);

	} else {

	    /* this is an option string */
	    ++sbArg;	/* move past the '-' */
	    while (*sbArg) {
		/* point to a potential argument */
		sbTemp = (sbArg[1] != '\0') ? sbArg+1 : argv[i+1];
		fUsedArg = 0; /* set to true if option uses an arguement */

		switch (*sbArg) {
		    default:
			printf(sbUsage);
			exit(1);
		    
		    case 'r':
			recurseLevel = atoi(sbTemp);
			fUsedArg = 1;
			break;

		    case 's':
			seconds = atoi(sbTemp);
			fUsedArg = 1;
			break;

		} /* switch */
		++sbArg;
		if (fUsedArg) {
		    if (*sbArg == '\0')
			i++;	/* eat next word - it was the arg we used */
		    *sbArg = '\0';
		} /* if */
	    } /* while */
	} /* if */
    } /* for all command line arguments */

    /* Main code */
    if (seconds != 0)
	alarm(seconds);

    string_array[0] = "a";
    string_array[1] = "b";
    string_array[2] = "c";

    while (*argv)
	printf("%s\n",*(argv++));

    for (loop=1; loop != 0; loop++) {
	recurse = recurseLevel;
	First(loop, loop, loop);
    } /* for */

    printf("done\n");
    exit(0);
} /* main */


/* S E C O N D */

char * Second(aaa, bbb, ccc)
register char	aaa;
register short ccc;
int	bbb;
{
    long	x;

    if (recurse) {
	--recurse;
	Second(aaa+recurse+1, bbb+recurse+1, ccc+recurse+1);
	return((char *)recurse);
    } /* if */

    x = aaa + bbb + ccc;
    Third(aaa, -1, "A good message", &a_record);
    return((char *) 0);
} /* Second */


/* T H I R D */

Third(select, random, message, rec)
register long	 select;
int	random;
register char	*message;
pRECR	rec;
{
    register float	fl;
    double	xfl;
    static struct RECS *precord;

    precord = rec;
    xfl = fl = 5.8;

    if (select != 0) {
	int random;

	random = -9;
	switch (select % 7) {
	    case 1:	printf("1\n");	break;
	    case 2:	printf("2\n");	break;
	    case 3:	printf("3\n");	break;
	    case 4:	printf("4\n");	break;
	    default:	printf("default\n");	break;
	} /* switch */
    } /* if */

    printf("%s\n", message);
} /* Third */


/* F I R S T */

First(i, j, k)
int	i;
char	j;
short	k;
{
    Second(i, j+1, k+2);
} /* First */


/* A D D   A R G S */

static double AddArgs(i, d)
int	i, d;
{
    int		value;

    value = i + d;
    Second(i, i+1, i+2);
    return(value * 3.2);
} /* AddArgs */


/* _ R E C S */

static void _RECS(rec, x)
struct RECS *rec;
int	x;
{
    if (x != -1)
	fprintf(stderr, "x == %d\n", x);
    fprintf(stderr,"a = %d, b = %s, c = %d\n",
		rec->a, rec->b, rec->c);
    fprintf(stderr,"bits = %d %d %d %d, color = %d\n",
	rec->bits1, rec->bits2, rec->bits3,
	rec->bits4, rec->color);
    fflush(stderr);
} /* _RECS */
0707070001000312251004440000000000010000011602020454650113600001200000020351cdb/lib.c /* $Header: lib.c,v 6.2 86/08/12 22:28:00 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"
#include <setjmp.h>
#include <varargs.h>
#include <signal.h>

jmp_buf venvFixer;

#define OFF	-1
local int	vcLines = OFF;
local int	vcMoreUsers = 0;	/* count of nesting calls to MoreOn */
export int	vcLinesMax = 22;
local int	vcColUsers = 0;		/* cont of nesting calls to ColOn */
local int	vcCol = OFF;


/* F   B L O C K   C M P */

export int FBlockCmp(sb1, sb2, cb)
register char	*sb1, *sb2;
register int	cb;
{
    while (*sb1++ == *sb2++) {
	if (--cb == 0)
	    return(1);
    } /* while */
    return(0);
} /* FBlockCmp */


/* S B   C O N C A T */

export char * SbConcat(sbDest, sb1)
register char	*sbDest;
char	*sb1;
{
    static char	sbBuf1[400], sbBuf2[400];
    register char *sb;
    register char **psb = &sb1;
    char 	*sbRet;

    if (sbDest == 0) {
	/* thay want default buffer */
	while (*psb && (*psb != sbBuf1))
	    psb++;
	sbDest = (*psb == sbBuf1) ? sbBuf2 : sbBuf1;
	ZeroBlock(sbDest, sizeof(sbBuf1));
	psb = &sb1;
    } /* if */

    sbRet = sbDest;
    while ((sb = *(psb++)) != 0) {
	while (*sbDest++ = *sb++)
	    ;
	sbDest--; /* back up to the ending '\0' */
    } /* while */
    *sbDest = '\0';

    return(sbRet);
} /* SbConcat */


/* L O N G   F   R O U N D */

export int4 LongFRound(x, y)
int4	x, y;
{
    return( ((x + y - 1) / y) * y );
} /* LongFRound */


/* C O L   O N */

export void ColOn()
{
    /* enable column counting */
    if (++vcColUsers == 1)
	vcCol = 0;
} /* ColOn */


/* C O L   O F F */

export void ColOff()
{
    /* disable column counting */
    if (--vcColUsers == 0)
	vcCol = OFF;
} /* ColOff */


/* P A D   T O */

export void PadTo(col)
int	col;
{
    if (col <= vcCol)
	return;

    printf("%.*s", col - vcCol, vsbSpaces);
} /* PadTo */


/* C L E A R   C O L */

export void ClearCol()
{
    vcColUsers = 0;
    vcCol = OFF;
} /* ClearPad */


/* M O R E   O N */

export void MoreOn()
{
    /* enable the 'more' simulation in printf */
    if (++vcMoreUsers == 1)
	vcLines = 0;
} /* MoreOn */


/* M O R E   O F F */

export void MoreOff()
{
    /* disable the 'more' simulation in printf */
    if (--vcMoreUsers == 0)
	vcLines = OFF;
} /* MoreOff */


/* C L E A R   M O R E */

export void ClearMore()
{
    vcMoreUsers = 0;
    vcLines = OFF;
} /* ClearMore */


export FLAGT vfOutputSuppress = false;

/* P R I N T F */

/*VARARGS1*/
export int printf(format, va_alist)
char	*format;
va_dcl
{
    FAST int	cb;
    va_list	ap;
    FILE	ioT;
    char	sbBuffer[cbLineMax];

#ifndef _IOSTRG
#define _IOSTRG	0
#endif

#if (OP_SYS == SYSV)
#define TYPE (unsigned char *)
#else
#define TYPE
#endif

    if (vfOutputSuppress)
	return;

    ioT._cnt = sizeof(sbBuffer);
    ioT._base = ioT._ptr = TYPE sbBuffer;
    ioT._flag = _IOWRT + _IOSTRG;	/* a writable 'string' channel */
    ioT._file = _NFILE;

    va_start(ap);
#if (MFG != SEQUENT) && (MFG != SIEMENS)
    cb = _doprnt(format, ap, &ioT);
    va_end(ap);
    putc('\0', &ioT);		/* null terminated */
#else
    /* I just love companies that produce "standard" systems...... */
    _doprnt(format, ap, &ioT);
    va_end(ap);
    putc('\0', &ioT);		/* null terminated */
    cb = strlen(sbBuffer);
#endif /* (MFG != SEQUENT) && (MFG != SIEMENS) */

    if (vfOutput AND (vfpOutput != NULL))
	fwrite(sbBuffer, 1, cb, vfpOutput);

    fwrite(sbBuffer, 1, cb, stdout);

    if (vcLines != OFF) {
	/* they are asking us to simulate MORE */
	if ((sbBuffer[cb-1] == '\n')
	   AND (++vcLines >= vcLinesMax)) {
	    char	ch;
	    vcLines = 0;
	    ch = ChFChoice("More? [yQq] ", "yQq");
	    if (ch == 'Q') {
		UError(sbNil);
	    } else if (ch == 'q') {
		longjmp(venvFixer, 1);
	    } /* if */
	    vcLines = 0;
	} /* if */
    } /* if */

    if (vcCol != OFF) {
	/* keep track of column */
	if (sbBuffer[cb-1] == '\n') {
	    vcCol = 0;
	} else {
	    /* mini kludge - we will deal with tabs later */
	    vcCol += strlen(sbBuffer);
	} /* if */
    } /* if */

    if (v->sbComm != sbNil)
	fflush(stdout);
    return(cb);
} /* printf */


/* F P R I N T F */

/*VARARGS2*/
export int fprintf(fp, format, va_alist)
FILE	*fp;
char	*format;
va_dcl
{
    FAST int	cb;
    va_list	ap;
    FILE	ioT;
    char	sbBuffer[cbLineMax];

    ioT._cnt = sizeof(sbBuffer);
    ioT._base = ioT._ptr = TYPE sbBuffer;
    ioT._flag = _IOWRT + _IOSTRG;	/* a writable 'string' channel */
    ioT._file = _NFILE;

    va_start(ap);
#if (MFG != SEQUENT) && (MFG != SIEMENS)
    cb = _doprnt(format, ap, &ioT);
    va_end(ap);
    putc('\0', &ioT);		/* null terminated */
#else
    /* I just love companies that produce "standard" systems...... */
    _doprnt(format, ap, &ioT);
    va_end(ap);
    putc('\0', &ioT);		/* null terminated */
    cb = strlen(sbBuffer);
#endif /* (MFG != SEQUENT) && (MFG != SIEMENS) */

    fwrite(sbBuffer, 1, cb, fp);

    if (fp == stdout) {
	if (vfOutput AND (vfpOutput != NULL))
	    fwrite(sbBuffer, 1, cb, vfpOutput);

	if (vcLines != OFF) {
	    /* they are asking us to simulate MORE */
	    if ((sbBuffer[cb-1] == '\n')
	       AND (++vcLines >= vcLinesMax)) {
		char	ch;
		vcLines = 0;
		ch = ChFChoice("More? [yQq] ", "yQq");
		if (ch == 'q') {
		    UError(sbNil);
		} else if (ch == 'Q') {
		    longjmp(venvFixer, 1);
		} /* if */
		vcLines = 0;
	    } /* if */
	} /* if */

	if (vcCol != OFF) {
	    /* keep track of column */
	    if (sbBuffer[cb-1] == '\n') {
		vcCol = 0;
	    } else {
		/* mini kludge - we will deal with tabs later */
		vcCol += strlen(sbBuffer);
	    } /* if */
	} /* if */
    } /* if */

    return(cb);
} /* fprintf */


/* F I X E R */

export void Fixer()
{
    signal(SIGINT, SIG_IGN);

    /* check the communications state to remote */
    if (vcsRemote != csNil) {
	signal(SIGINT, Fixer);
	if (vfInWait) {
	    /* do something that generates the remote interrupt */
	    SendSignal(SIGINT);
	    return;
	} /* if */
	vfInterruptPending = true;
	return;
    } /* if */

    vcNest = 0;
    if (v != prNil)
	v->fRunAssert = true;

    if ((vfpPlayback != NULL)
       AND (vcStepPlayback == 0))
	vcStepPlayback = 1;	/* gives them a chance to regain control */
    printf("\n");
    signal(SIGINT, Fixer);
    longjmp(venv, 2);
} /* Fixer */


/* S E T   P R O M P T */

/* VARARGS1 */
export void SetPrompt(sbMsg, arg1, arg2, arg3, arg4)
SBT	sbMsg;
int	arg1, arg2, arg3, arg4;
{
    sprintf(vsbPrompt, sbMsg, arg1, arg2, arg3, arg4);
} /* SetPrompt */


/* P A N I C */

/* VARARGS1 */
export void Panic(sbMsg, arg1, arg2, arg3, arg4)
SBT	sbMsg;
int	arg1, arg2, arg3, arg4;
{
    printf("CDB error - ");
    if (sbMsg != sbNil)
	printf(sbMsg, arg1, arg2, arg3, arg4);
    printf("\n");
    longjmp(venv, 1);
} /* Panic */


/* S Y S   P A N I C */

/* VARARGS1 */
export void SysPanic(sbMsg, arg1, arg2, arg3, arg4)
SBT	sbMsg;
int	arg1, arg2, arg3, arg4;
{
    int		err;

    err = errno;
    printf("CDB error - ");
    if (sbMsg != sbNil)
	printf(sbMsg, arg1, arg2, arg3, arg4);
    printf("\n");

    if (err != 0)
	printf("%s\n", SbFError(err));
    longjmp(venv, 1);
} /* Panic */


/* U   E R R O R */

/* VARARGS1 */
export void UError(sbMsg, arg1, arg2, arg3, arg4)
SBT	sbMsg;
int	arg1, arg2, arg3, arg4;
{
    if (sbMsg != sbNil) {
	printf(sbMsg, arg1, arg2, arg3, arg4);
	printf("\n");
    } /* if */
    longjmp(venv, 1);
} /* UError */


/* The following routines exist in  AT&T Land, but not Berzerkeley */

/* s t r c h r */

export char * strchr(sb, ch)
register char	*sb, ch;
{
    /* find first instance of ch in sb, return nil if not found */
    while ((*sb != '\0') && (*sb != ch))
	sb++;
    return((*sb == '\0') ? (char *)0 : sb);
} /* strchr */


/* s t r r c h r */

export char * strrchr(sb, ch)
register char	*sb, ch;
{
    register char 	*sbBack;

    sbBack = sb + strlen(sb);
    while (*sbBack != ch && sbBack != sb)
	sbBack--;
    return((*sbBack == ch) ? sbBack : (char *)0);
} /* strrchr */


/* s t r c s p n */

export int strcspn(sbSpan, sbNot)
register char	*sbSpan, *sbNot;
{
    register int	cSpan;
    register char	*sbSave;

    /* return count of chars from start of sbSpan that do NOT occur in sbNot */
    cSpan = 0;
    sbSave = sbNot;
    while (*sbSpan != '\0') {
	while (*sbNot != '\0') {
	    if (*sbNot == *sbSpan)
		return(cSpan);
	    sbNot++;
	} /* while */
	sbSpan++;
	cSpan++;
	sbNot = sbSave;
    } /* while */
    return(cSpan);
} /* strcspn */
0707070001000312261004440000000000010000011603010454650113600001300000014137cdb/list.c /* $Header: list.c,v 5.23 86/07/18 06:13:40 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* These routines list various things */

#include "cdb.h"

#define cScreenMax 21

/* L I S T   F I L E S */

local void ListFiles(sbFile)
SBT	sbFile;
{
    int2	i;
    SBT		sb;
    FLAGT	fAll = false;
    pFDR	fd;

    if (sbFile != sbNil) {
	fAll = true;
	if (*sbFile == '*')
	    sbFile = sbNil;
    } /* if */

    MoreOn();

    printf("     File name            Address   First procedure\n");
    for (i=0, fd = v->rgFd; i < v->hdr.ifdMax; fd++, i++) {
	sb = SbFIss(fd->iss);
	if ((sbFile != sbNil)
	   AND (!FHdrCmp(sbFile, sb)))
	    continue;
	if (!fAll AND ((i == ifdTemp) OR (fd->iline == 0)))
	    continue;	/* has no symbols */
	printf("%3d: %-15s%s  %10s   %s\n",
		    i, sb, (fd->iline == 0) ? " " : "*",
		    SbFAdr(fd->adr, true), SbFIpd(fd->ipd));
    } /* for */
    MoreOff();
} /* ListFiles */


/* L I S T   P R O C S */

local void ListProcs(sbProc)
SBT	sbProc;
{
    int2	i, j;
    int4	iline;
    SBT		sb;
    FLAGT	fAll = false;
    ADRT	dadr, dadrLast;
    pLINER	line;
    pPDR	pd;


    if (sbProc != sbNil) {
	fAll = true;
	if (*sbProc == '*')
	    sbProc = sbNil;
    } /* if */

    MoreOn();
    for (i = 0, pd = v->rgPd; i < v->hdr.ipdMax; pd++, i++) {
	sb = SbFIpd(i);
	if ((sbProc != sbNil)
	   AND (!FHdrCmp(sbProc, sb)))
	    continue;
	iline = pd->iline;
	if (!fAll AND (iline == 0))
	    continue;	/* has no symbols */
	printf("%3d: %-15s%s  %s", i,
			sb, (iline == 0) ?" " : "*", SbFAdr(pd->adr, true));

	if ((v->debuglevel > 0) AND (iline != 0)) {
	    printf("	%d", iline);

	    dadrLast = 0;
	    for (j = 0; iline < v->hdr.ilineMax; j++, iline++) {
		line = LineFIline(iline);
		dadr = line->dadr;
		if (line->dadr < dadrLast)
		    break;
		printf("%s%3d %3d: 0x%lx", (i % 4) ? "\t" : "\n\t",
				iline, line->iln, dadr);
		dadrLast = dadr;
	    } /* for */
	} /* if */

	printf("\n");
    } /* for */
    MoreOff();
} /* ListProcs */


/* L I S T   G L O B A L S */

local void ListGlobals(sbGlobal)
SBT	sbGlobal;
{
    int2	c;
    int4	isym;
    FLAGT	fData;
    SBT		sb;
    SER		ase, *se = &ase;
    pSYMR	sym;
    MODER	amode, amodeSave;

    amode.len = -1;
    if ((v->pid == pidNil) AND (v->fnCore == fnNil)) {
	fData = false;
	amode.df = dfHex;
	printf("No process - accessing exec/core file\n");
    } else {
	amode.df = dfNil;
	fData = true;
    } /* if */

    TkPeek();
    if (vtk == tkSlash OR vtkPeek == tkSlash) {
	if (vtkPeek == tkSlash)
	    TkNext();
	else
	    sbGlobal = sbNil;
	GetMode(&amode);
    } /* if */

    amode.cnt = 1;
    amodeSave = amode;

    MoreOn();

    c = 0;
    if (v->ifd != ifdNil) {

	SetNextSym(v->rgFd[v->ifd].isym+1);
	while (FNextSym(stStatic, stNil, stNil, stFile, false, sbNil, nil)) {
	    isym = v->isym;
	    sb = SbFIss(v->sym->iss);
	    if ((sbGlobal != sbNil)
	       AND (!FHdrCmp(sbGlobal, sb)) )
		continue;

	    SeFSym(se, v->sym, true);
	    if (c++ == 0)
		printf("---- Statics global to file \"%s\"----\n",
			SbFIss(v->rgFd[v->ifd].iss) );
	    if (!fData)
		printf("%-20s @ ", SbFIss(se->asym.iss));
	    amode = amodeSave;
	    DisplaySe(se, &amode, true, fData, fData);
	    printf("\n");
	    SymFIsym(isym);
	} /* while */

    } /* if */

    if (c != 0)
	printf("\n---- Globals ----\n");
    SetNextSym(v->hdr.isymGl);
    while (FNextSym(stGlobal, stNil, stNil, stNil, false, sbNil, nil)) {
	isym = v->isym;
	sb = SbFIss(v->sym->iss);
	if ((sbGlobal != sbNil)
	   AND (!FHdrCmp(sbGlobal, sb)) )
	    continue;

	SeFSym(se, v->sym, true);
	if (!fData)
	    printf("%-20s @ ", SbFIss(se->asym.iss));
	amode = amodeSave;
	DisplaySe(se, &amode, true, fData, fData);
	printf("\n");
	SymFIsym(isym);
    } /* while */

    MoreOff();
} /* ListGlobals */


/* L I S T   L O C A L S */

local void ListLocals(sbProc, cnt)
SBT	sbProc;
int2	cnt;
{
    int2	ipd;
    CNTXR	acntx;

    if ((v->pid == pidNil) AND (v->fnCore == fnNil))
	UError("No child process.");

    MoreOn();
    ipd = (sbProc == sbNil) ? v->ipd : IpdFName(sbProc);

    CntxFIpd(&acntx, &ipd, cnt);
    if (acntx.fEndOfStack)
	UError("Procedure \"%s\" is not active on the stack.",
		SbFIpd(ipd));

    if ((ipd == ipdNil) OR (v->rgPd[ipd].iline == 0))
	UError("I don't have symbols for this procedure.");

    DispFrame(&acntx, cnt, true, true);
    MoreOff();
} /* ListLocals */


/* L I S T   T Y P E D E F S */

local void ListTypedefs(sb)
SBT	sb;
{
    int		i;
    pTDR	td;
    SER		ase;

    MoreOn();
    for (i = 0, td = v->rgTd; i < v->hdr.itdMax; td++, i++) {
	if ((sb != sbNil) AND !FHdrCmp(sb, SbFIss(td->iss)))
	    continue;
	printf("typedef ");
	SeFSym(&ase, SymFIsym(td->isym), true);
	PxSe(&ase, false);
	printf(";\n");
    } /* for */
    MoreOff();
} /* ListTypedefs */


/* L I S T   S O M E T H I N G */

export void ListSomething()
{
    int2	cnt;
    char	chCmd, *sbArg, sbName[20];
    TKE		tk;
    FLAGT	fDidit;

    tk = TkNext();
    if ((vcbTok == 1) AND (tk != tkNumber)) {
	fDidit = false;
	sbArg = sbNil;
	chCmd = vsbTok[0];
	if (tkSemi != TkPeek()) {
	    tk = TkNext();
	    sbArg = vsbTok;
	    if (*sbArg == chNull)
		sbArg = sbNil;
	} /* if */

	fDidit = true;
	switch (chCmd) {
	    default:	fDidit = false; break;
	    case 'a':   ListAssert(); break;
	    case 'b':   ListBp(); break;
	    case 'd':   ListDir(); break;
	    case 'f':   ListFiles(sbArg); break;
	    case 'g':   ListGlobals(sbArg); break;
	    case 'p':   ListProcs(sbArg); break;
	    case 'P':	ListPr(prNil); break;
	    case 'r':   ListRegisters(sbArg); break;
	    case 's':   ListSpecials(sbArg); break;
	    case 't':   ListTypedefs(sbArg); break;
	    case 'z':   ListSa(); break;
	} /* switch */
	if (fDidit)
	    return;
    } /* if */

    if (tk == tkStr) {
	strcpy(sbName, vsbTok);
	cnt = -1;
	if ((TkNext() == tkDot)
	   AND (TkNext() == tkNumber))
	    cnt = atoi(vsbTok);
	/* list the named proc at the given level */
	ListLocals(sbName, cnt);
    } else if (tk == tkNumber) {
	/* list the given stack depth level */
	cnt = atoi(vsbTok);
	ListLocals("-", cnt);
    } else {
	/* list the current proc at the given level */
	ListLocals(sbNil, v->stackdepth);
    } /* if */
} /* ListSomething */
0707070001000312271004440000000000010000011603620454650113600001100000024707cdb/os.c /* $Header: osV.c,v 6.1 86/09/15 09:33:13 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <termio.h>
#include <varargs.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/signal.h>
#include <sys/dir.h>
#include <sys/user.h>

#include <core.h>
#include <a.out.h>

#define cbUserPage      ctob(USIZE)

export char	**venvpParent;
typedef int	*pENVR;	/* KLUDGE?? */
jmp_buf	venvFixer;   /* for error recovery */
SAR	vmpSigSa[NSIG];	/* signal action array */

#if 0
exportdefine cArgsMax	100
#endif

char	*vargvChild[cArgsMax];

struct termio	histty, mytty;
static char	vsbPattern[300];

SBT	vmpSigSb[] = {
	sbNil,
	"hangup",
	"interrupt",
	"quit",
	"illegal instruction",
	"breakpoint",
	"IOT instruction",
	"EMT instruction",
	"floating point exception",
	"kill",
	"bus error",
	"segmentation violation",
	"bad argument to system call",
	"write on a pipe with no one to read it",
	"alarm clock",
	"software termination signal from kill",
	"user defined signal 1",
	"user defined signal 2",
	"child stop or exit",
	"power fail",
	};
int visigSbMax = sizeof(vmpSigSb) / sizeof(SBT);


/* I N I T   P A T T E R N */

export void InitPattern(sbPattern)
SBT	sbPattern;
{
    strcpy(vsbPattern, sbPattern);
} /* InitPattern */


/* I   F   P A T T E R N */

export int IFPattern(sbLine)
FAST SBT	sbLine;
{
    FAST int2	cbLine, cbPattern, i;

    /* Return the index of the Pattern within the line */

    i = 0;	/* the index of sbPattern in sbLine */
    cbLine = strlen(sbLine);
    cbPattern = strlen(vsbPattern);
    while (cbLine >= cbPattern) {
	if (FHdrCmp(vsbPattern, sbLine, cbPattern))
	    return(i);
	i++;
	sbLine++;
	cbLine--;
    } /* while */
    return(-1);
} /* IFPattern */


/* S B   F   S I G N A L */

export SBT SbFSignal(sig)
int2	sig;
{
    SBT		sb;
    static char sbTemp[100];

    if (sig < visigSbMax && sig>0) {
	sb = vmpSigSb[sig];
    } else {
	sprintf(sbTemp, "signal %d", sig);
	sb = sbTemp;
    } /* if */
    return(sb);
} /* SbFSignal */


/* S E T   J M P */

export int SetJmp(env)
pENVR	env;
{
    return(setjmp(env));
} /* SetJmp */


/* L O N G   J M P */

export void LongJmp(env)
pENVR	env;
{
    longjmp(env);
} /* LongJmp */


/* S W I T C H   T T Y S */

local void SwitchTtys(tty1, tty2)
struct termio	*tty1, *tty2;
{
    ioctl(0, TCGETA, tty1);  /* save state */
    if (! FBlockCmp(tty1, tty2, sizeof(*tty1)))
	ioctl(0, TCSETAW, tty2);	/* restore state */
} /* SwitchTtys */


/* S E T   M Y   T T Y */

export void SetMyTty()
{
    SwitchTtys(&histty, &mytty);
} /* SetMyTty */


/* S E T   H I S   T T Y */

export void SetHisTty()
{
    SwitchTtys(&mytty, &histty);
} /* SetHisTty */


/* I N I T   M Y   T T Y */

export void InitMyTty()
{
    ioctl(0, TCGETA, &mytty);  /* get my state */
    histty = mytty;	/* to start with, he is same as me */
} /* InitMyTty */


/* S E T   D E M O   T I M E R */

export void SetDemoTimer(cSeconds)
int	cSeconds;
{
#if 0
    /* 4.2 code - never really done for System V */

    /* this helps setup for timed-out demo code */
    struct sgttyb	tty;
    gtty(0, &tty);
    if (cSeconds > 0)
	tty.sg_flags |= CBREAK;
    else
	tty.sg_flags &= ~CBREAK;
    stty(0, &tty);

    vsleepDemo = cSeconds;
#endif
} /* SetDemoTimer */


/* F   T I M E D   I N P U T */

export FLAGT FTimedInput(cSeconds)
int	cSeconds;
{
#if 0
    /* 4.2 code - never really done for System V */

    int		x, mRead, mWrite, mExcept;
    char	buf[100];

    /* return 'true' if cSeonds elapse and no keys struck */
    struct timeval tv;

    mRead = 1;		/* interested in stdin */
    mWrite = 0;
    mExcept = 0;
    tv.tv_sec = cSeconds;
    tv.tv_usec = 0;
    x = select(1, &mRead, &mWrite, &mExcept, &tv);
    return(x== 0);
#endif
} /* FTimedInput */


/* S B   F   E R R O R */

export SBT SbFError(error)
int	error;
{
    extern char *sys_errlist[];
    extern int   sys_nerr;

    if (error < 0 OR error >= sys_nerr)
	UError("Unknown error number (%d).", error);
    return(sys_errlist[error]);
} /* SbFError */


/* O O P S */

export void Oops(sig)
int	sig;
{
    signal(sig, Oops);
    if (vfInDisplay)
	UError(sbNil);

UError("\nSorry, Cdb has encountered a \"%s\" error. Try a different command.",
	SbFSignal(sig));
} /* Oops */


/* A L A R M */

local void Alarm()
{
    signal(SIGALRM, Alarm);
} /* Alarm */


/* I N I T   S I G N A L S */

export void InitSignals()
{
    signal(SIGALRM, Alarm);
    signal(SIGINT, Fixer);
    signal(SIGILL, Oops);
    signal(SIGFPE, Oops);
    signal(SIGBUS, Oops);
    signal(SIGSEGV, Oops);
    signal(SIGSYS, Oops);
    signal(SIGPIPE, Oops);
} /* InitSignals */


/* O S   C R E A T E   T A R G E T */

export void OsCreateTarget()
{
    int2	sig, fn;

    if (v->fnExec != fnNil)
	close(v->fnExec);	/* in case it is PURE or SPLIT I&D */
    v->fnExec = fnNil;

    if ((v->pid = fork()) == 0) {
	signal(SIGINT, SIG_DFL);
	if (setjmp(venv)) {
	    printf("Exec failed\n");
	    exit(1);
	} /* if */
	for (sig=1; sig<NSIG; sig++)
	    signal(sig, SIG_DFL);	/* start out with default response */

	if (vfnTarget != fnNil) {
	    /* set up the target with the specified device */
	    close(0);
	    dup(vfnTarget);
	    close(1);
	    dup(vfnTarget);
	    close(2);
	    dup(vfnTarget);
	} /* if */

	if (vfWindows)
	    ClearTargetScreen();

	for (fn = 3; fn < _NFILE; fn++)
	    close(fn);

	DoArgs(v->sbExec, v->sbArgsChild, vargvChild, true);
	SetHisTty();
	Ptrace(ptChild, 0, (char *)0, 0); /* Hi, Mom! */
	execv(v->sbExec, vargvChild);

	/* if we get here, we are child BUT exec failed */
	perror(v->sbExec);
	exit(1);
    } /* if */
} /* OsCreateTarget */


/* I N I T   S A */

export void InitSa()
{
    FAST int	i;
    pSAR	sa;

    sa = vmpSigSa;
    for (i=0; i < NSIG; i++, sa++) {
	sa->fIgnore = true;
	sa->fReport = true;
	sa->fStop = true;
    } /* for */

    /* now we set some of them to NOT report, ignore or stop! */
    /* the 'Q' option shuts up the printout of the signal settings */

    SaMaintain(SIGALRM, "isrQ", sbNil); /* we don't stop, report or Ignore */
    SaMaintain(SIGKILL, "isrQ", sbNil);
    SaMaintain(SIGTERM, "isrQ", sbNil);
    SaMaintain(SIGCLD, "isrQ", sbNil);
} /* InitSa */


/* I N I T   C O R E */

export void InitCore(pr)
pPRR	pr;
{
    int		sig;
    long	cbText, cbData, cbStack;
    static char auserCore[cbUserPage];
    struct user *userCore = (struct user *) auserCore;
    struct stat statbuf;

    if (pr->sbCore == sbNil) {
	pr->fnCore = fnNil;
	return;
    } /* if */

    pr->fnCore = open(pr->sbCore, 0);	/* open it read-only */
    if (pr->fnCore < 0) {
	printf("%s not accessible\n", pr->sbCore);
	pr->fnCore = fnNil;
	return;
    } /* if */

    fstat(pr->fnCore, &statbuf);
    if (pr->mtimeExec > statbuf.st_mtime) {
	printf("WARNING: `%s' is older than `%s' - ignoring %s.\n",
	    pr->sbCore, pr->sbExec, pr->sbCore);
	goto Failed;
    } /* if */

    /* we do have a corefile! */
    if ((read(pr->fnCore, userCore, cbUserPage) != cbUserPage)) {
	printf("Can't read '%s' - ignoring it\n", pr->sbCore);
	goto Failed;
    } /* if */

    if (pr->hdr.magic != userCore->u_exdata.ux_mag) {
	printf("WARNING: `%s' cannot be the core file for %s - ignoring %s\n",
		pr->sbCore, pr->sbExec, pr->sbCore);
	goto Failed;
    } /* if */

#if (MFG == ARETE)
    pr->sig = *(int *)(auserCore + 0xf04);
#else
    pr->sig = userCore->u_arg[0];
#endif
    if (pr->sig != 0)
	printf("Child died due to \"%s\"\n", SbFSignal(pr->sig));

    cbText = ctob(userCore->u_tsize);
    cbData = ctob(userCore->u_dsize);
#if (MFG == ARETE || MFG == PLEXUS)
    cbStack = ctob(userCore->u_ssize) - cbUserPage;
#else
    cbStack = ctob(userCore->u_ssize);
#endif

    /* core files for read only programs do NOT contain the instructions! */
#if (MFG == INTEL)
    /* Intel 386 stuff */
    pr->mapCore.b1 = pr->mapExec.b2;
#else
    /* Normal COFF stuff */
    pr->mapCore.b1 = (pr->hdr.magic==magicReadOnly) ?
		LongFRound(cbText,TXTRNDSIZ) :
		(pr->hdr.magic == magicDemand) ? cbText : 0L;
#endif

    pr->mapCore.e1 = cbData + ((pr->hdr.magic==magicImpure) ?
		cbText : pr->mapCore.b1);
    pr->mapCore.f1 = cbUserPage;

#if (MFG == PLEXUS)
    {
	ADRT usrstack = (ADRT)userCore->u_usrstack;

	/* use default end of user stack for old machines */
	if (usrstack == NULL) usrstack = cbStorageMax;
	pr->mapCore.b2 = usrstack - cbStack;
	pr->mapCore.e2 = usrstack;
    }
#else
    pr->mapCore.b2 = cbStorageMax - cbStack;
    pr->mapCore.e2 = cbStorageMax;
#endif
    pr->mapCore.f2 = cbUserPage +
		((pr->hdr.magic==magicReadOnly || pr->hdr.magic == 0413)
				 ? cbData : pr->mapCore.e1);
    return;

Failed:
    close(pr->fnCore);
    pr->fnCore = fnNil;
    pr->sbCore = SbFAlloc("no core");
} /* InitCore */


/* I N I T   O S */

export void InitOs(pr)
pPRR	pr;
{
    int2	ipd;
    int4	cbData, cbText;
    struct aouthdr	aoutSym;
    struct filehdr	fileSym;
    struct scnhdr	scnSym;
    struct user		auser;

    pr->os = (pOSR) malloc(cbOSR);
    pr->os->adrTty = (ADRT) malloc(sizeof(struct termio));
    pr->os->sigTrap = SIGTRAP;
    pr->os->sigMax = NSIG;
    pr->os->mpSigSa = vmpSigSa;
    pr->os->fIntegerOffsets = INTEGER_OFFSETS;
    pr->os->fClearFp = CLEAR_FP;

    if (vadrUar0 == adrNil)
	vadrUar0 = (ADRT)&(auser.u_ar0) - (ADRT)&auser;
    pr->os->adr_u_ar0 = vadrUar0;
    pr->os->adrUser = vadrUser;
    pr->os->adrReg0 = vadrReg0;
    pr->os->adrEntry = (ADRT)&(auser.u_exdata.ux_entloc) - (ADRT)&auser;
    pr->os->dadrEntMax = 4;

    InitSignals(pr);
    InitSa(pr);		/* set default signal handling */

    /* set up mapExec */
    lseek(v->fnExec, 0L, seekBegin);
    if (read(v->fnExec, &fileSym, sizeof(fileSym)) != sizeof(fileSym)
        || read(v->fnExec, &aoutSym, sizeof(aoutSym)) != sizeof(aoutSym)
        || read(v->fnExec, &scnSym, sizeof(scnSym)) != sizeof(scnSym))
	SysPanic("Cannot read header of %s.", v->sbExec);

    pr->hdr.magic = aoutSym.magic;
    cbData = aoutSym.dsize;
    cbText = aoutSym.tsize;

    /* text section */
    pr->mapExec.f1 = scnSym.s_scnptr;
    pr->mapExec.b1 = scnSym.s_paddr;
    pr->mapExec.e1 = scnSym.s_paddr + scnSym.s_size;

    /* Data section */
    if (read(v->fnExec, &scnSym, sizeof(scnSym)) != sizeof(scnSym))
	SysPanic("Cannot read second section header.");

    pr->mapExec.f2 = scnSym.s_scnptr;
    pr->mapExec.b2 = scnSym.s_paddr;
    pr->mapExec.e2 = scnSym.s_paddr + scnSym.s_size;

    if (pr->adrBreak == adrNil) {
	ipd = IpdFName("_end_");
	if (ipd != ipdNil)
	    pr->adrCall = pr->adrBreak = pr->rgPd[ipd].adr;
    } /* if */

    InitCore(pr);
} /* InitOs */


0707070001000312301004440000000000010000011605060454650113700001200000024707cdb/osV.c /* $Header: osV.c,v 6.1 86/09/15 09:33:13 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <termio.h>
#include <varargs.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/signal.h>
#include <sys/dir.h>
#include <sys/user.h>

#include <core.h>
#include <a.out.h>

#define cbUserPage      ctob(USIZE)

export char	**venvpParent;
typedef int	*pENVR;	/* KLUDGE?? */
jmp_buf	venvFixer;   /* for error recovery */
SAR	vmpSigSa[NSIG];	/* signal action array */

#if 0
exportdefine cArgsMax	100
#endif

char	*vargvChild[cArgsMax];

struct termio	histty, mytty;
static char	vsbPattern[300];

SBT	vmpSigSb[] = {
	sbNil,
	"hangup",
	"interrupt",
	"quit",
	"illegal instruction",
	"breakpoint",
	"IOT instruction",
	"EMT instruction",
	"floating point exception",
	"kill",
	"bus error",
	"segmentation violation",
	"bad argument to system call",
	"write on a pipe with no one to read it",
	"alarm clock",
	"software termination signal from kill",
	"user defined signal 1",
	"user defined signal 2",
	"child stop or exit",
	"power fail",
	};
int visigSbMax = sizeof(vmpSigSb) / sizeof(SBT);


/* I N I T   P A T T E R N */

export void InitPattern(sbPattern)
SBT	sbPattern;
{
    strcpy(vsbPattern, sbPattern);
} /* InitPattern */


/* I   F   P A T T E R N */

export int IFPattern(sbLine)
FAST SBT	sbLine;
{
    FAST int2	cbLine, cbPattern, i;

    /* Return the index of the Pattern within the line */

    i = 0;	/* the index of sbPattern in sbLine */
    cbLine = strlen(sbLine);
    cbPattern = strlen(vsbPattern);
    while (cbLine >= cbPattern) {
	if (FHdrCmp(vsbPattern, sbLine, cbPattern))
	    return(i);
	i++;
	sbLine++;
	cbLine--;
    } /* while */
    return(-1);
} /* IFPattern */


/* S B   F   S I G N A L */

export SBT SbFSignal(sig)
int2	sig;
{
    SBT		sb;
    static char sbTemp[100];

    if (sig < visigSbMax && sig>0) {
	sb = vmpSigSb[sig];
    } else {
	sprintf(sbTemp, "signal %d", sig);
	sb = sbTemp;
    } /* if */
    return(sb);
} /* SbFSignal */


/* S E T   J M P */

export int SetJmp(env)
pENVR	env;
{
    return(setjmp(env));
} /* SetJmp */


/* L O N G   J M P */

export void LongJmp(env)
pENVR	env;
{
    longjmp(env);
} /* LongJmp */


/* S W I T C H   T T Y S */

local void SwitchTtys(tty1, tty2)
struct termio	*tty1, *tty2;
{
    ioctl(0, TCGETA, tty1);  /* save state */
    if (! FBlockCmp(tty1, tty2, sizeof(*tty1)))
	ioctl(0, TCSETAW, tty2);	/* restore state */
} /* SwitchTtys */


/* S E T   M Y   T T Y */

export void SetMyTty()
{
    SwitchTtys(&histty, &mytty);
} /* SetMyTty */


/* S E T   H I S   T T Y */

export void SetHisTty()
{
    SwitchTtys(&mytty, &histty);
} /* SetHisTty */


/* I N I T   M Y   T T Y */

export void InitMyTty()
{
    ioctl(0, TCGETA, &mytty);  /* get my state */
    histty = mytty;	/* to start with, he is same as me */
} /* InitMyTty */


/* S E T   D E M O   T I M E R */

export void SetDemoTimer(cSeconds)
int	cSeconds;
{
#if 0
    /* 4.2 code - never really done for System V */

    /* this helps setup for timed-out demo code */
    struct sgttyb	tty;
    gtty(0, &tty);
    if (cSeconds > 0)
	tty.sg_flags |= CBREAK;
    else
	tty.sg_flags &= ~CBREAK;
    stty(0, &tty);

    vsleepDemo = cSeconds;
#endif
} /* SetDemoTimer */


/* F   T I M E D   I N P U T */

export FLAGT FTimedInput(cSeconds)
int	cSeconds;
{
#if 0
    /* 4.2 code - never really done for System V */

    int		x, mRead, mWrite, mExcept;
    char	buf[100];

    /* return 'true' if cSeonds elapse and no keys struck */
    struct timeval tv;

    mRead = 1;		/* interested in stdin */
    mWrite = 0;
    mExcept = 0;
    tv.tv_sec = cSeconds;
    tv.tv_usec = 0;
    x = select(1, &mRead, &mWrite, &mExcept, &tv);
    return(x== 0);
#endif
} /* FTimedInput */


/* S B   F   E R R O R */

export SBT SbFError(error)
int	error;
{
    extern char *sys_errlist[];
    extern int   sys_nerr;

    if (error < 0 OR error >= sys_nerr)
	UError("Unknown error number (%d).", error);
    return(sys_errlist[error]);
} /* SbFError */


/* O O P S */

export void Oops(sig)
int	sig;
{
    signal(sig, Oops);
    if (vfInDisplay)
	UError(sbNil);

UError("\nSorry, Cdb has encountered a \"%s\" error. Try a different command.",
	SbFSignal(sig));
} /* Oops */


/* A L A R M */

local void Alarm()
{
    signal(SIGALRM, Alarm);
} /* Alarm */


/* I N I T   S I G N A L S */

export void InitSignals()
{
    signal(SIGALRM, Alarm);
    signal(SIGINT, Fixer);
    signal(SIGILL, Oops);
    signal(SIGFPE, Oops);
    signal(SIGBUS, Oops);
    signal(SIGSEGV, Oops);
    signal(SIGSYS, Oops);
    signal(SIGPIPE, Oops);
} /* InitSignals */


/* O S   C R E A T E   T A R G E T */

export void OsCreateTarget()
{
    int2	sig, fn;

    if (v->fnExec != fnNil)
	close(v->fnExec);	/* in case it is PURE or SPLIT I&D */
    v->fnExec = fnNil;

    if ((v->pid = fork()) == 0) {
	signal(SIGINT, SIG_DFL);
	if (setjmp(venv)) {
	    printf("Exec failed\n");
	    exit(1);
	} /* if */
	for (sig=1; sig<NSIG; sig++)
	    signal(sig, SIG_DFL);	/* start out with default response */

	if (vfnTarget != fnNil) {
	    /* set up the target with the specified device */
	    close(0);
	    dup(vfnTarget);
	    close(1);
	    dup(vfnTarget);
	    close(2);
	    dup(vfnTarget);
	} /* if */

	if (vfWindows)
	    ClearTargetScreen();

	for (fn = 3; fn < _NFILE; fn++)
	    close(fn);

	DoArgs(v->sbExec, v->sbArgsChild, vargvChild, true);
	SetHisTty();
	Ptrace(ptChild, 0, (char *)0, 0); /* Hi, Mom! */
	execv(v->sbExec, vargvChild);

	/* if we get here, we are child BUT exec failed */
	perror(v->sbExec);
	exit(1);
    } /* if */
} /* OsCreateTarget */


/* I N I T   S A */

export void InitSa()
{
    FAST int	i;
    pSAR	sa;

    sa = vmpSigSa;
    for (i=0; i < NSIG; i++, sa++) {
	sa->fIgnore = true;
	sa->fReport = true;
	sa->fStop = true;
    } /* for */

    /* now we set some of them to NOT report, ignore or stop! */
    /* the 'Q' option shuts up the printout of the signal settings */

    SaMaintain(SIGALRM, "isrQ", sbNil); /* we don't stop, report or Ignore */
    SaMaintain(SIGKILL, "isrQ", sbNil);
    SaMaintain(SIGTERM, "isrQ", sbNil);
    SaMaintain(SIGCLD, "isrQ", sbNil);
} /* InitSa */


/* I N I T   C O R E */

export void InitCore(pr)
pPRR	pr;
{
    int		sig;
    long	cbText, cbData, cbStack;
    static char auserCore[cbUserPage];
    struct user *userCore = (struct user *) auserCore;
    struct stat statbuf;

    if (pr->sbCore == sbNil) {
	pr->fnCore = fnNil;
	return;
    } /* if */

    pr->fnCore = open(pr->sbCore, 0);	/* open it read-only */
    if (pr->fnCore < 0) {
	printf("%s not accessible\n", pr->sbCore);
	pr->fnCore = fnNil;
	return;
    } /* if */

    fstat(pr->fnCore, &statbuf);
    if (pr->mtimeExec > statbuf.st_mtime) {
	printf("WARNING: `%s' is older than `%s' - ignoring %s.\n",
	    pr->sbCore, pr->sbExec, pr->sbCore);
	goto Failed;
    } /* if */

    /* we do have a corefile! */
    if ((read(pr->fnCore, userCore, cbUserPage) != cbUserPage)) {
	printf("Can't read '%s' - ignoring it\n", pr->sbCore);
	goto Failed;
    } /* if */

    if (pr->hdr.magic != userCore->u_exdata.ux_mag) {
	printf("WARNING: `%s' cannot be the core file for %s - ignoring %s\n",
		pr->sbCore, pr->sbExec, pr->sbCore);
	goto Failed;
    } /* if */

#if (MFG == ARETE)
    pr->sig = *(int *)(auserCore + 0xf04);
#else
    pr->sig = userCore->u_arg[0];
#endif
    if (pr->sig != 0)
	printf("Child died due to \"%s\"\n", SbFSignal(pr->sig));

    cbText = ctob(userCore->u_tsize);
    cbData = ctob(userCore->u_dsize);
#if (MFG == ARETE || MFG == PLEXUS)
    cbStack = ctob(userCore->u_ssize) - cbUserPage;
#else
    cbStack = ctob(userCore->u_ssize);
#endif

    /* core files for read only programs do NOT contain the instructions! */
#if (MFG == INTEL)
    /* Intel 386 stuff */
    pr->mapCore.b1 = pr->mapExec.b2;
#else
    /* Normal COFF stuff */
    pr->mapCore.b1 = (pr->hdr.magic==magicReadOnly) ?
		LongFRound(cbText,TXTRNDSIZ) :
		(pr->hdr.magic == magicDemand) ? cbText : 0L;
#endif

    pr->mapCore.e1 = cbData + ((pr->hdr.magic==magicImpure) ?
		cbText : pr->mapCore.b1);
    pr->mapCore.f1 = cbUserPage;

#if (MFG == PLEXUS)
    {
	ADRT usrstack = (ADRT)userCore->u_usrstack;

	/* use default end of user stack for old machines */
	if (usrstack == NULL) usrstack = cbStorageMax;
	pr->mapCore.b2 = usrstack - cbStack;
	pr->mapCore.e2 = usrstack;
    }
#else
    pr->mapCore.b2 = cbStorageMax - cbStack;
    pr->mapCore.e2 = cbStorageMax;
#endif
    pr->mapCore.f2 = cbUserPage +
		((pr->hdr.magic==magicReadOnly || pr->hdr.magic == 0413)
				 ? cbData : pr->mapCore.e1);
    return;

Failed:
    close(pr->fnCore);
    pr->fnCore = fnNil;
    pr->sbCore = SbFAlloc("no core");
} /* InitCore */


/* I N I T   O S */

export void InitOs(pr)
pPRR	pr;
{
    int2	ipd;
    int4	cbData, cbText;
    struct aouthdr	aoutSym;
    struct filehdr	fileSym;
    struct scnhdr	scnSym;
    struct user		auser;

    pr->os = (pOSR) malloc(cbOSR);
    pr->os->adrTty = (ADRT) malloc(sizeof(struct termio));
    pr->os->sigTrap = SIGTRAP;
    pr->os->sigMax = NSIG;
    pr->os->mpSigSa = vmpSigSa;
    pr->os->fIntegerOffsets = INTEGER_OFFSETS;
    pr->os->fClearFp = CLEAR_FP;

    if (vadrUar0 == adrNil)
	vadrUar0 = (ADRT)&(auser.u_ar0) - (ADRT)&auser;
    pr->os->adr_u_ar0 = vadrUar0;
    pr->os->adrUser = vadrUser;
    pr->os->adrReg0 = vadrReg0;
    pr->os->adrEntry = (ADRT)&(auser.u_exdata.ux_entloc) - (ADRT)&auser;
    pr->os->dadrEntMax = 4;

    InitSignals(pr);
    InitSa(pr);		/* set default signal handling */

    /* set up mapExec */
    lseek(v->fnExec, 0L, seekBegin);
    if (read(v->fnExec, &fileSym, sizeof(fileSym)) != sizeof(fileSym)
        || read(v->fnExec, &aoutSym, sizeof(aoutSym)) != sizeof(aoutSym)
        || read(v->fnExec, &scnSym, sizeof(scnSym)) != sizeof(scnSym))
	SysPanic("Cannot read header of %s.", v->sbExec);

    pr->hdr.magic = aoutSym.magic;
    cbData = aoutSym.dsize;
    cbText = aoutSym.tsize;

    /* text section */
    pr->mapExec.f1 = scnSym.s_scnptr;
    pr->mapExec.b1 = scnSym.s_paddr;
    pr->mapExec.e1 = scnSym.s_paddr + scnSym.s_size;

    /* Data section */
    if (read(v->fnExec, &scnSym, sizeof(scnSym)) != sizeof(scnSym))
	SysPanic("Cannot read second section header.");

    pr->mapExec.f2 = scnSym.s_scnptr;
    pr->mapExec.b2 = scnSym.s_paddr;
    pr->mapExec.e2 = scnSym.s_paddr + scnSym.s_size;

    if (pr->adrBreak == adrNil) {
	ipd = IpdFName("_end_");
	if (ipd != ipdNil)
	    pr->adrCall = pr->adrBreak = pr->rgPd[ipd].adr;
    } /* if */

    InitCore(pr);
} /* InitOs */


0707070001000312311004440000000000010000011602030454650113700001100000034153cdb/pt.c /* $Header: pt.c,v 6.4 86/09/14 20:23:55 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <signal.h>
#include <setjmp.h>
#include "cdb.h"

export FLAGT	vfAnalyzeStop = false;


/* S B   F   N E X T   A R G */

export SBT SbFNextArg(psbIn)
SBT	*psbIn;
{
    char	chExit;
    SBT		sb, sbRet, sbTemp;

    sb = *psbIn;

    /* skip white space */
    while (*sb == ' ' OR *sb == '\t')
	sb++;

    if (*sb == chNull)
	return(sbNil);	/* that's all, folks! */

    sbRet = sb;
    sbTemp = sb;

    if ((*sb != '"') AND (*sb != '\'')) {

	/* eat all non-white space characters */
	while ((*sb != chNull)
	   AND (*sb != ' ')
	   AND (*sb != '\t')) {
	    if ((*sb == '"') OR (*sb =='\'')) {
		chExit = *sb++;
		goto DoString;	/* I know, it's a horrible hack!!! */
	    } /* if */
	    *sbTemp++ = *sb++;
	} /* while */

    } else {

	chExit = *sb;	/* remember starting character */
	*sbTemp++ = *sb++;	/* so caller knows it's magic */
DoString:
	/* collect arg involving string literal */

	while ((*sb != chNull) AND (*sb != chExit)) {
	    /* this routine will walk us over all escape sequences */
	    *sbTemp++ = ChFEscape(&sb, true);
	} /* while */
	if (*sb != chExit)
	    UError("String constant in arg list is missing ending %c.", chExit);
    } /* if */

    *sbTemp = chNull;
    *psbIn = sb + 1;	/* point them at next available character */
    return(sbRet);
} /* SbFNextArg */


/* D O	 A R G S */

export void DoArgs(sbProgram, sbArgs, argv, fReassign)
SBT	sbProgram, sbArgs;
char	**argv;
FLAGT	fReassign;
{
    int		i;
    SBT		sbFile, sbArgCur;
    static char	sbBuffer[1024];

    for (i = 0; i < cArgsMax; i++)
	argv[i] = sbNil;

    *argv++ = sbProgram; /* set the filename */

    if (sbArgs == sbNil)
	return;

    strcpy(sbBuffer, sbArgs);	/* copy it to a safe place to hack on it */
    sbArgs = sbBuffer;
    sbArgs[strlen(sbArgs)+1] = chNull; /* this puts a SECOND null at end */

    /* eat the arguments */
    while ((sbArgs != sbNil)
       AND (*sbArgs != chNull)) {

	sbArgCur = SbFNextArg(&sbArgs);
	if (sbArgCur == sbNil)
	    break;

	if ((*sbArgCur == '"') OR (*sbArgCur == '\'')) {
	    /* it's a string literal */
	    *argv++ = sbArgCur + 1;	/* cut off the ' or " */
	    continue;
	} /* if */

	/* check for indirection */
	if (!fReassign
	   OR ((*sbArgCur != '<') AND (*sbArgCur != '>')) ) {
	    *argv++ = sbArgCur;	/* we just pass it on */
	} else {
	    /* find that file name */
	    sbFile = sbArgCur + 1;  /* initially we assume `<foo' vs `< foo' */
	    if ((sbArgCur[1] == '>') OR (sbArgCur[1] == '&'))
		sbFile++;

	    if (*sbFile == chNull) {
		/* there was white space between < and sbFile */
		sbFile = SbFNextArg(&sbArgs);
		if (sbFile == sbNil) {
		    printf("Illegal indirection\n");
		    exit(1);
		} /* if */
	    } /* if */

	    if (*sbArgCur == '<') {
		/* changing stdin */
		close(0);
		if (open(sbFile, O_RDONLY) < 0) {
		    perror(sbFile);
		    exit(1);
		} /* if */

	    } else if (*sbArgCur == '>') {

		if (sbArgCur[1] == '>') {
		    /* changing stderr */
		    close(2);
		} else {
		    /* changing stdout */
		    close(1);
		} /* if */

		if ( (open(sbFile, O_WRONLY) < 0) 
		   AND (creat(sbFile, 0666) < 0) ) {
		    perror(sbFile);
		    exit(1);
		} /* if */

		if (sbArgCur[1] == '&') {
		    /* changing BOTH stdout AND stderr */
		    close(2);
		    dup(1);	/* duplicate stdout's decriptor into stderr's */
		} /* if */

	    } /* if */
	} /* if */
    } /* while */
    *argv = sbNil;
} /* DoArgs */


/* A N A L Y Z E   S T O P */

export void AnalyzeStop()
{
    int2	statLo, statHi, psSave;
    SAR		asa;
    pBPR	bpFork;
    SBT		sbSave;
    FLAGT	fNewCommands;

    /* The current process is examined to determine the reason it stopped.
     * If it was do a break which is being ignored, we continue it
     * automatically.
     */

    v->sigOrig = statHi = v->status >> 8;
    v->sig = 0;
    statLo = v->status & 0377;
    v->bp = bpNil;

    if (statLo == 0) {	/* child terminated */

	if (statHi != 0)
	    printf("Process %d exited with %d\n", v->pid, statHi);
	else
	    printf("Process %d terminated normally\n", v->pid);
	v->pid = pidNil;

	KillChild();	/* go bury the corpse */

    } else if ((statLo & 0177) != 0177) {  /* terminated on signal */

	if (v->ps == psDying) {
	    v->ps = psNoChild;
	    return;	/* this was expected */
	} /* if */

	v->sigOrig = v->sig = v->status & 0x7f;
	printf("Child terminated on signal %d - %s", v->sigOrig,
			SbFSignal(v->sigOrig));
	if (v->status & 0200) {
	    printf("(core dumped)");
	    if (v->fnCore != fnNil)
		close(v->fnCore);
	    free(v->sbCore);
	    v->sbCore = SbFAlloc("./core");
	    InitCore(v, nil);
	} /* if */

	v->pid = pidNil;
	printf(" at %s\n", SbFAdr(v->acntx.pc, true));
	SetViewPosition(v->acntx.pc);
	ShowViewPosition(fmtProc+fmtLn+fmtLine+fmtEol);
	KillChild();	/* it's already dead, but this does general stuff */

    } else {	/* child stopped */

#if (SYS == MX2)
	if (v->sigOrig == SIGBPT)
	    v->sigOrig = SIGTRAP;
#endif /* (SYS == MX2) */

	sbSave = sbNil;
	fNewCommands = false;
	psSave = v->ps;
	v->ps = psStopped;
	ReadPc();	/* get a cleaned up pc */

	asa = v->os->mpSigSa[v->sigOrig]; /* get a COPY of this action record */
	if (! asa.fIgnore)
	    v->sig = v->sigOrig;

	if (v->sigOrig != v->os->sigTrap) {

	    if (asa.sbSa[0] != 0) {
		fNewCommands = true;
		sbSave = SbFAlloc(v->sbCmd);	/* save current stuff */
		SetCmd(asa.sbSa);
		asa.fStop = true;	/* THEY must continue if desired */
	    } /* if */

	    if (v->fDoingSingle AND !asa.fStop) {
		if (asa.fReport) {
		    SetViewPosition(v->acntx.pc);
		    printf("\n%s\n", SbFSignal(v->sigOrig));
		    ShowViewPosition(fmtProc+fmtLn+fmtLine+fmtEol);
		} /* if */
		Ptrace(ptSingle, v->pid, (char *)1, v->sig);
		v->ps = psRunning;
		return;
	    } /* if */

	    if (asa.fStop)
		v->bp = vbpStop;	/* primarily used to alert SingleStep */
	} else {

	    /* We have received the signal SIGTRAP.
	     * We need to go through a series of test to determine
	     * what this means.  
	     */

	    FixPc(); /* modifies v->acntx.pc to point AT the break, if any */

	    /* we first attempt to map a breakpoint to this address */
	    v->bp = BpFProcess(v->acntx.pc);

	    if (v->bp == bpNil) {
		bpFork = BpFForkSave(v->pidParent, v->acntx.pc);
		if (bpFork != bpNil) {
		    RemoveBp(bpFork);
		    v->bp = vbpStop;
		} /* if */
	    } /* if */

	    if (v->bp == bpNil) {

		/* a trap signal, but no breakpoint */
		asa.fReport = false;
		asa.fStop = false;
		switch (psSave) {
		    case psRunning:
			/* There are only three ways that we can arrive here:
			 *	1. We single stepped a process.
			 *	   a.  Normal instruction step.
			 *	   b.  Step over trap in execve.
			 *	2. One of our processes did an exec().
			 *	3. Some commie mutant sent SIGTRAP to
			 *	   one of process.
			 *
			 * If #1 is true, we simply stop.
			 * If #2 is true, then the PC must be within N
			 * byte of the start address.  If it isn't, we
			 * assume case #3 and ignore it.
			 */
			if (!v->fDoingSingle OR v->fAtSyscall) {
			    ADRT	adr;

			    if (v->os->adrEntry != adrNil) {
				adr = GetUser(v->os->adrEntry);
				if ((v->acntx.pc >= adr)
				   AND (v->acntx.pc< adr + v->os->dadrEntMax)) {
				       if (v->pidParent != vpidCdb) {
					    /* We seem to have done an exec().
					     * Change our symbol table.
					     */
					    v = PrFExec(v);
					    if (v->fStopOnExec) {
						asa.fStop = true;
						asa.fReport = true;
					    } /* if */
					} else {
					    asa.fStop = true;
					} /* if */
					ExecInit(! v->fDoingSingle);
				}/* if */
			    } /* if */
			} /* if */

			if (v->fDoingSingle)
			    asa.fStop = true;
			break;

		    case psExec:
			asa.fStop = true;
			break;

		    case psFork:
			asa.fStop = v->fStopOnFork;
			break;

		    default:

			Panic("SIGTRAP for process %d with ps of %s.", 
				v->pid, SbFPs(psSave));
		} /* switch */

	    } else if (v->bp == vbpContinue) {

		/* we hit a break, but the continue count said to ignore it */
		asa.fReport = false;
		asa.fStop = false;

	    } else if (v->bp == vbpStop) {

		/* we hit a temporary break */
		asa.fReport = false;
		asa.fStop = true;
		v->bp = bpNil;

	    } else if (v->bp->adr == v->adrBreak) {

		/* Return from a Procedure Call from the Command Line */
		SetCntx();
		return;	/* special kludge for proc-calls from the cmd line */

	    } else {

		/* a vanilla flavored break */
		if (v->bp->sbBp[0] != chNull) {
		    fNewCommands = true;
		    SetCmd(v->bp->sbBp);
		} /* if */

	    } /* if */

	} /* if - end of SIGTRAP code */

	if ((v->sbCmd != sbNil) AND (*v->sbCmd == 'Q'))
	    asa.fReport = false;

	v->fAtSyscall = false;
	if (asa.fStop == false) {
	    v->ps = psContinue;
	    return;
	} /* if */

	SetCntx();	/* we'll be here for awhile, get rest of goodies */
	SetViewPosition(v->acntx.pc);
	if (asa.fReport) {
	    printf("\n%s\n", SbFSignal(v->sigOrig));
	    ShowViewPosition(fmtProc+fmtLn+fmtLine+fmtEol);
	} /* if */

	if (fNewCommands) {
	    /* process any commands that we were handed */
	    vfAnalyzeStop = true;
	    FDoCommand(v->sbCmd, false);
	    vfAnalyzeStop = false;
	    SetCmd(sbSave);
	    if (sbSave != sbNil)
		free(sbSave);
	} /* if */
    } /* if */
} /* AnalyzeStop */


/* R U N   P R O C E S S */

export void RunProcess(pt, ps, fWait)
int2	pt, ps;
FLAGT	fWait;
{
    pBPR	bpRun;

    vfCacheValid = false;
    v->fMachineStep = false;

    if (v->pid == pidNil)
	UError("No process.");

    AllBpInstall();	/* make sure they are all in */

    if ((v->fRunAssert)
       AND (v->as == asActive)
       AND (v->ps != psFork)
       AND (v->iadMac > 0)) {
	/* do the assertions */
	if (FDoAssert(pt)	/* an assertion came up true */
	   OR (v->pid == pidNil)	/* the child died during assertions */
	   OR (v->bp != bpNil) )	/* we hit a breakpoint */
	    return;
    } /* if */

    /* hit the GO button */
    v->ps = ps;
    if (v->fStty)
	SetHisTty();

    /* get us off any break we might be on */
    while ((bpRun = BpFAdr(v->acntx.pc, true)) != bpNil) {
	RemoveBp(bpRun);	/* pull it out */
	while ((bpRun->adr == v->acntx.pc)
	   AND (v->ps == ps)) {
	    v->fDoingSingle = true;
	    Ptrace(ptSingle, v->pid, (char *)v->acntx.pc, v->sig);
	    Waiter(wtProcess, v->pid);
	} /* while */
	AllBpInstall();	/* make sure they are all in */
	if (v->bp != bpNil)
	    return;
	if (pt == ptSingle)
	    return; /* we have already single stepped it for them */
    } /* while */

    errno = 0;
    /* start/continue child */
    v->ps = ps;
    v->fDoingSingle = (pt == ptSingle);
    Ptrace(pt, v->pid, (char *)v->acntx.pc, v->sig);
    if (fWait)
	Waiter(wtProcess, v->pid);
} /* RunProcess */


/* K I L L   C H I L D */

export void KillChild()
{
    if (--vcActive < 0)	/* count of Active proceesses */
	vcActive = 0;

    if (v->pid != pidNil) {
	if (v->pid < 3) {
	    printf("Process %d (%s) is a system process.\n", v->pid, v->sbExec);
	    if (! YesNo("Do you REALLY want to kill it ?"))
		UError(sbNil);
	} /* if */
	RemoveAllBp();
	v->ps = psDying;
	Ptrace(ptTerm, v->pid, (char *)0, 0);
	Waiter(wtProcess, v->pid); /* wait for the obituary */
    } /* if */

    if (v->pidParent != vpidCdb) {
	/* not a direct child */
	DeallocPr(v, false);
	return;
    } /* if */

    v->pid = pidNil;
    v->fMachineStep = false;
    v->fDoingSingle = false;
    v->ps = psNoChild;
    v->acntx.pc = v->adrInit;
    v->sig = 0;
    v->acntx.fp = 0;
    v->acntx.fEndOfStack = true;
    RemoveAllBp(true);

    if (v->fnCore != fnNil) {
	ReadPc();
	SetCntx();	/* refresh from the core file */
    } /* if */

    if (v->fnExec == fnNil) {
	/* opening for writing keeps other people from using file */
	v->fnExec = open(v->sbExec, O_RDONLY);
	if (v->fnExec == -1) {
	    perror(v->sbExec);
	    v->fnExec = fnNil;
	} /* if */
    } /* if */
    if (viprMax > 1)
	SetGlobalPr(prNil);

    if (v->cNestProc != 0) {
	extern jmp_buf venvFixer;
	v->cNestProc = 0;
	venv = venvFixer;
	UError("Exiting procedure call state.");
    } /* if */
} /* KillChild */


/* N E W   C H I L D */

export void NewChild(sbArgs, fInit)
SBT	sbArgs;
FLAGT	fInit;
{
    FLAGT	fMaster, fDoingSingle;

    if (v->pidParent != vpidCdb)
	UError("You cannot 'run' a grandchild process!");

    fDoingSingle = v->fDoingSingle;
    KillChild(); /* in case there is already one out there */

    InitMyTty(); /* reads in my state to 'mytty' */

    if (sbArgs == sbNil) {
	v->sbArgsChild = sbNil; 	/* do the child with no arguments */
    } else {
	fMaster = (sbArgs == v->sbCmd);	/* this is the normal command line */
	while (*sbArgs == ' ' OR *sbArgs == '\011')
	    sbArgs++;	/* eat leading white space */
	if (*sbArgs != chNull) {
	    if (v->sbArgsChild != sbNil)
		free(v->sbArgsChild);
	    v->sbArgsChild = SbFAlloc(sbArgs);
	    if (fMaster) {
		/* eat it - this way we don't
		 * try to execute the arguments to the child
		 * as debugger commands
		 */
		SetCmd(sbNil);
	    } /* if */
	} /* if */
    } /* if */

    printf("running '%s", v->sbExec);
    if (v->sbArgsChild != sbNil)
	printf(" %s",  v->sbArgsChild);
    printf("'\n");

    v->fDoingSingle = fDoingSingle;
    fflush(stdout);
    CreateTarget();

    ++vcActive;		/* count of Active processes */
    v->ps = (v->os->adrEntry == adrNil) ? psExec : psRunning;
    Waiter(wtProcess, v->pid); /* wait for child to stop and report */
    if (v->os->adrEntry == adrNil)
	ExecInit(fInit);
} /* NewChild */


/* E X E C   I N I T */

export void ExecInit(fInit)
FLAGT	fInit;
{
    if (v->fDebugChildren)
	Ptrace(ptMultiChild, v->pid, 0, 0);	/* put our stamp on him */

    if (v->os->fClearFp)
	PutReg(ufp, (REGT)0);	/* some systems do not zero out the fp */

    if (fInit OR (v->as == asActive)) {
	/* we don't want assertions during initialization */
	BpFAddBp(v->adrInit, 0, sbNil, 0); /* at first USER instruction */

	v->fRunAssert = false;

	RunProcess(ptResume, psExec, true);

	v->fRunAssert = true;
	/* we should now have a fully initialized, stopped process,
	 * waiting at the first executable line of 'main' or whatever.
	 */

	if (v->adrStartLow == adrNil) {
	    int		ipd;
	    CNTXR	acntx;

	    /* init stack-walk stop variables. */
	    acntx = v->acntx;
	    NextFrame(&acntx);
	    ipd = IpdFAdr(acntx.pc);
	    v->adrStartLow = v->rgPd[ipd].adr;
	    v->adrStartHigh = v->rgPd[ipd +1].adr;
	} /* if */
    } /* if */
} /* ExecInit */
0707070001000312321004440000000000010000011603630454650113700001500000003643cdb/signal.c /* $Header: signal.c,v 5.5 86/07/18 06:14:13 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"


/* S A	 M A I N T A I N */

export void SaMaintain(sig, sbOptions, sbCmds)
int	sig;
SBT	sbCmds, sbOptions;
{
    FLAGT	fCommands, fShowSignal;
    pSAR	sa;

    /* toggle options based on the flags:
     * r = report,  s = stop,  i = ignore signal, Q = do it quietly
     * c = get commands after switches
     */

    if (sig == v->os->sigTrap)
	printf( "WARNING: You are modifying the breakpoint signal!\n");

    fCommands = false;
    fShowSignal = ! v->fQuiet;

    sa = v->os->mpSigSa + sig;
    while (*sbOptions) {
	switch (*sbOptions) {
	    case 'r':
		sa->fReport = !sa->fReport;
		break;
	    case 's':
		sa->fStop = !sa->fStop;
		break;
	    case 'i':
		sa->fIgnore = !sa->fIgnore;
		break;
	    case 'Q':
		fShowSignal = false;
		break;
	    case 'c':
		fCommands = true;
		break;
	    default:
		printf("Unknown signal command: \"%c\"\n", *sbOptions);
		fShowSignal = true;
		goto ShowSignal;
	} /* switch */
	sbOptions++;
    } /* while */

    if (fCommands)
	strcpy(sa->sbSa, sbCmds);

ShowSignal:
    if (fShowSignal) {
	printf("   Stop  Ignore  Report  Name\n");
	printf("%2d  %c      %c       %c     %s\n", sig,
			(sa->fStop) ? 'T':'F',
			(sa->fIgnore) ? 'T':'F',
			(sa->fReport) ? 'T':'F',
			SbFSignal(sig));
	if (sa->sbSa[0] != chNull)
	    printf("\t%s\n", sa->sbSa);
    } /* if */
} /* SaMaintain */


/* L I S T   S A */

export void ListSa()
{
    int		sig;
    pSAR	sa;

    MoreOn();

    printf("   Stop  Ignore  Report  Name\n");
    for (sig=1;	sig < v->os->sigMax; sig++) {
	sa = v->os->mpSigSa + sig;
	printf("%2d  %c      %c       %c     %s\n", sig,
			(sa->fStop) ? 'T':'F',
			(sa->fIgnore) ? 'T':'F',
			(sa->fReport) ? 'T':'F',
			SbFSignal(sig));
	if (sa->sbSa[0] != chNull)
	    printf("\t%s\n", sa->sbSa);
    } /* for */

    MoreOff();
} /* ListSa */
0707070001000312331004440000000000010000011604010454650113700001200000043124cdb/sym.c /* $Header: sym.c,v 6.1 86/08/05 17:45:06 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <sys/types.h>
#include <sys/stat.h>

#include "cdb.h"

export FLAGT	vfCacheSymbols = true;	/* If TRUE, we are cacheing symbols */

#ifndef bitSb
#define bitSb 0x80000000	/* used to make memory strings into ISS's */
#endif


/*  L I N E   F   I L I N E */

export pLINER LineFIline(iline)
FAST int4 iline;
{
    int4	ilineRead, cRead, offset;

    /* This returns line symbol 'iline' */

    if ((iline < 0) OR (iline >= v->hdr.ilineMax))
	Panic("iline out of bounds (%d).", iline);

    if (! vfCacheSymbols)
	return(v->lineCache + iline);

    if ((iline >= v->ilineLo) AND (iline < v->ilineLim))
	return(v->lineCache + iline - v->ilineLo); /* already in memory */

    ilineRead = (iline / v->ilineCacheMax) * v->ilineCacheMax;
    offset = v->hdr.cbLineOffset + (ilineRead * cbLINER);
    if (lseek(v->fnCdb, offset, 0) < 0L)
	SysPanic("Bad seek in LineFIline.");
    cRead = read(v->fnCdb, v->lineCache, v->ilineCacheMax*cbLINER);

    if (cRead < 0)
	SysPanic("Bad read in LineFIline (cRead: %ld).", cRead);
    v->ilineLo = ilineRead;
    v->ilineLim = ilineRead + (cRead/cbLINER);
    if (v->ilineLim > v->hdr.ilineMax)
	v->ilineLim = v->hdr.ilineMax;
    return(v->lineCache + iline - v->ilineLo);
} /* LineFIline */


/*  A U X   F   I A U X */

export pAUXU AuxFIaux(iaux)
FAST int4 iaux;
{
    int4	iauxRead, cRead, offset;

    /* This guarantees that auxillary symbol 'iaux' is in the cache */

    if ((iaux < 0) OR (iaux >= v->hdr.iauxMax))
	Panic("iaux out of bounds (%d).", iaux);

    if (! vfCacheSymbols)
	return(v->auxCache + iaux);

    if ( (iaux >= v->iauxLo)
       AND ( ((iaux + cAuxMax) < v->iauxLim)
	  OR ((iaux < v->iauxLim) AND (v->iauxLim == v->hdr.iauxMax)) ) )
	return(v->auxCache + iaux - v->iauxLo); /* it is already in memory */

    iauxRead = (iaux / v->iauxCacheMax) * v->iauxCacheMax;
    offset = v->hdr.cbAuxOffset + (iauxRead * cbAUXU);
    if (lseek(v->fnCdb, offset, 0) < 0L)
	SysPanic("Bad seek in AuxFIaux.");
    cRead = read(v->fnCdb, v->auxCache, v->iauxCacheMax*cbAUXU);

    if (cRead < 0)
	SysPanic("Bad read in AuxFIaux (cRead: %ld).", cRead);
    v->iauxLo = iauxRead;
    v->iauxLim = iauxRead + (cRead/cbAUXU);
    if (v->iauxLim > v->hdr.iauxMax)
	v->iauxLim = v->hdr.iauxMax;
    return(v->auxCache + iaux - v->iauxLo);
} /* AuxFIaux */


/* I S Y M   F   S Y M */

export int4 IsymFSym(sym)
pSYMR	sym;
{
    return((sym - v->symCache) + v->isymLo);
} /* IsymFSym */


/* S Y M   F   I S Y M */

export pSYMR SymFIsym(isym)
int4    isym;
{
    int4	isymRead, cRead, offset;

    /* This sets the global "vsym" to point at symbol "isym" */
    if ((isym < 0) OR (isym >= v->hdr.isymMax))
	Panic("isym out of bounds (%d).", isym);

    v->isym = isym;
    if (! vfCacheSymbols) {
	v->sym = v->symCache + isym;
	return(v->sym);
    } /* if */

    if ((isym < v->isymLo) OR (isym >= v->isymLim)) {
	/* rats - cache fault */
	isymRead = (isym / v->isymCacheMax) * v->isymCacheMax;
	offset = v->hdr.cbSymOffset + (isymRead * cbSYMR);
	if (lseek(v->fnCdb, offset, 0) < 0L)
	    SysPanic("Bad seek in SymFIsym.");
	cRead = read(v->fnCdb, v->symCache, v->isymCacheMax*cbSYMR);

	if (cRead < 0)
	    SysPanic("Bad read in SymFIsym (cRead: %ld).", cRead);
	v->isymLo = isymRead;
	v->isymLim = isymRead + (cRead/cbSYMR);
	if (v->isymLim > v->hdr.isymMax)
	    v->isymLim = v->hdr.isymMax;
    } /* if */

    v->sym = v->symCache + isym - v->isymLo;
    return(v->sym);
} /* SymFIsym */


/* S E T   N E X T   S Y M */

export void SetNextSym(isym)
FAST int4    isym;
{
    if (isym < 0 OR isym >= v->hdr.isymMax)
	Panic("isym out of bounds (%d).", isym);

    v->isym = isym - 1;
    if (v->isym < 0)
	v->sym = symNil;
     else
	SymFIsym(v->isym);
} /* SetNextSym */


/* F   N E X T   S Y M */

export FLAGT FNextSym(stHit1, stHit2, stHit3, stStop, fEnterBlocks, sbHit, Cmp)
FAST int2	stHit1, stHit2, stHit3, stStop;
FLAGT	fEnterBlocks;
SBT	sbHit;
FLAGT   (* Cmp)();
{
    FAST int2	st;
    int4	isym;
    pSYMR	sym;

    /* This routine is the main symbol table scanner.  It looks for
     * a symbol of type stHit1, 2 or 3 (optionally checking the name),
     * or for something of type stStop, bailing out at that point.
     *
     * If fEnterBlocks is FALSE and a symbol of type stBlock, stProc,
     * stCommon or stFile is encountered, we skip to the symbol
     * following the matching stEnd.
     * Requesting stBlock as stHit1, 2, 3 or stStop will cause this 
     * setting to be moot.
     */

    isym = v->isym + 1;	/* always startwith the NEXT sym */
    while (isym < v->hdr.isymMax) {
	/* look through what is in the cache */
	
	for (sym = SymFIsym(isym); isym < v->isymLim; sym++, isym++) {
	    
	    st = sym->st;
	    if ( ((st == stHit1)
		   OR (st == stHit2) 
		   OR (st == stHit3)) 
	       AND ((sbHit == sbNil)
		     OR ((*Cmp)(sbHit, SbFSym(sym)))) ) {
		v->isym = isym;
		v->sym = sym;
		return(true);
	    } else if (st == stStop) {
		v->isym = isym;
		v->sym = sym;
		return(false);
	    } else if (!fEnterBlocks
		    AND ((st == stBlock)
		      OR (st == stCommon)
		      OR (st == stProc)
		      OR (st == stFile)) ) {
		isym = IsymNextFBlock(isym);
		if (isym == 0) {
		    v->isym = isymNil;
		    v->sym = symNil;
		    return(false);	/* KLUDGE - for text labels */
		} /* if */
		break;	/* to force cache adjustment, if any */
	    } /* if */
	} /* for */

    } /* while */

    v->isym = 0;
    v->sym = symNil;
    return(false); /* off the end of the symbol table */
} /* FNextSym */


/* S B   F   I S S */

export SBT SbFIss(iss)
FAST int4	iss;
{
    FAST int4	offset, cRead, issSave;
    SBT		sbTest;

    /* given an Index into String Space, return a pointer to the string */

    if (iss == issNil)
	return(sbNil);

    if (iss & bitSb)
	/* this is a memory resident string; remove bit and return */
	return((SBT)(iss & ~bitSb));

    if (v->hdr.issMax == 0)
	return(sbNil);

    if ((iss < 0) OR (iss >= v->hdr.issMax))
	Panic("Iss out of bounds (%d).", iss);

    if (! vfCacheSymbols)
	return(v->sbCache + iss );

    if ((iss >= v->issLo) AND (iss < v->issLim)) {
	/* start of string is in the cache */

	if (v->hdr.issMax == v->issCacheMax) {
	    /* entire string space is in memory */
	    return(v->sbCache + iss);
	} /* if */

	/* make sure the WHOLE string is in the cache */
	issSave = iss;
	sbTest = v->sbCache + (iss - v->issLo);
	while ((iss < v->issLim) AND (*sbTest != chNull)) {
	    sbTest++;
	    iss++;
	} /* while */
	iss = issSave;
	if (*sbTest == chNull)
	    return(v->sbCache + (iss - v->issLo));
    } /* if */

    /* not in (or not ALL in) the cache - make it the first thing */
    offset = v->hdr.cbSsOffset + iss;
    if (lseek(v->fnCdb, offset, 0) < 0L)
	SysPanic("Bad seek in SbFIss.");
    cRead = read(v->fnCdb, v->sbCache, v->issCacheMax);
    if (cRead < 0)
	SysPanic("Bad read in SbFIss (cRead: %d).", cRead);
    v->issLo = iss;
    v->issLim = iss + cRead;
    return(v->sbCache + (iss - v->issLo));
} /* SbFIss */


/* S B   F   I P D */

export SBT SbFIpd(ipd)
int2	ipd;
{
    if (ipd == ipdNil)
	return("");
    return( SbFIss( SymFIsym(v->rgPd[ipd].isym)->iss) );
} /* SbFIpd */


/* S B   F   S Y M */

export SBT SbFSym(sym)
pSYMR	sym;
{
    return(SbFIss(sym->iss));
} /* SbFSym */


/* I S S   F   S B */

export int4 IssFSb(sb)
SBT	sb;
{
    return( bitSb | ((uint4)(sb)) );
} /* IssFSb */


/* S B   S A F E   F   S B */

export SBT SbSafeFSb(sb)
FAST SBT  sb;
{
    SBT		sbSave, sbMax, sbRet;
#define cbSbSafe 2048
    static char	sbSafe[cbSbSafe];	/* where we stick names of things */
    static SBT	sbSafeNext = sbSafe;	/* next available place */

    /* this guy sticks names in a TEMPORARILY safe place */

    sbSave = sb;
    sbMax = sbSafe + cbSbSafe;
    sbRet = sbSafeNext;

    while ((sbSafeNext < sbMax) AND (*sbSafeNext++ = *sb++))
	;

    if (sbSafeNext >= sbMax) {
	/* start over at beginning of buffer */
	sbRet = sbSafeNext = sbSafe;	/* reuse the buffer */
	sb = sbSave;
	while ((sbSafeNext < sbMax) AND (*sbSafeNext++ = *sb++))
	    ;
	if (sbSafeNext >= sbMax)
	    UError("String is too long for internal buffer of %d bytes.",
			cbSbSafe);
    } /* if */

    return(sbRet);
} /* SbSafeFSb */


/* I S S   S A F E   F   S B */

export int4 IssSafeFSb(sb)
SBT	sb;
{
    return( IssFSb( SbSafeFSb(sb) ) );
} /* IssSafeFSb */


/* S B   S A F E   F   I S S */

export SBT SbSafeFIss(iss)
int4	iss;
{
    return( SbSafeFSb( SbFIss(iss) ) );
} /* SbSafeFIss */


/* F   S B   C M P */

export FLAGT FSbCmp(sb1, sb2)
SBT	sb1, sb2;
{
    if ((sb1 == sbNil) OR (sb2 == sbNil))
	return(sb1 == sb2);

    while ((*sb1 | vcaseMod) == (*sb2 | vcaseMod)) {
	if (*sb1 == chNull)
	    return(true);
	sb1++;
	sb2++;
    } /* while */

    return(false);
} /* FSbCmp */


/* F   H D R   C M P */

export FLAGT FHdrCmp(sbHdr, sbCheck)
SBT	sbHdr, sbCheck;
{
    while ((*sbHdr | vcaseMod) == (*sbCheck | vcaseMod)) {
	if (*sbHdr == chNull)
	    return(true);
	sbHdr++;
	sbCheck++;
    } /* while */

    return(*sbHdr == chNull);
} /* FHdrCmp */


/* F   T A I L   C M P */

export FLAGT FTailCmp(sbTail, sbIn)
SBT	sbTail, sbIn;
{
    int		cbIn, cbTail;

    cbIn = strlen(sbIn);
    cbTail = strlen(sbTail);
    if (cbIn < cbTail)
	return(false);
    return(FSbCmp(sbTail, sbIn+(cbIn-cbTail)));
} /* FTailCmp */


/* F   N E X T   L O C A L */

export FLAGT FNextLocal(fLocal, fParam, isym)
FLAGT   fLocal, fParam;
int4	isym;
{
    int2	st;
    static int2	ifd;
    static pPRR	prSave;
    static int4	isymMin, isymMac;

    if ((v != prSave) OR (isym < isymMin) OR (isym >= isymMac)) {
	/* refresh our hint */
	prSave = v;
	ifd = IfdFIsym(isym);
	isymMin = v->rgFd[ifd].isym;
	isymMac = v->rgFd[ifd+1].isym;
    } /* if */

    if (v->rgFd[ifd].lc == lcC) {
	SetNextSym(isym);
	while (FNextSym(stParam, stLocal, stStatic, stProc, true, sbNil, nil)) {
	    if (v->isym >= isymMac)
		return(false);
	    /* we have a param OR a local */
	    st = v->sym->st;
	    if ( ((st == stParam) AND !fParam)
	       OR ((st == stLocal OR st == stStatic) AND !fLocal) ) {
		/* not what we were looking for */
		if (fParam AND !fLocal)
		    return(false); /* NEVER any params after locals */
		continue;
	    } /* if */
	    return(true);
	} /* while */
    } else if (v->rgFd[ifd].lc == lcFortran) {
	SetNextSym(isym);
	while (FNextSym(stParam,stCommon, stStatic, stProc,false, sbNil, nil)) {
	    if (v->isym >= isymMac)
		return(false);
	    /* we have a param OR a local */
	    st = v->sym->st;
	    if ( ((st == stParam) AND !fParam)
	       OR ((st == stStatic OR st == stCommon) AND !fLocal) ) {
		/* not what we were looking for */
		continue;
	    } /* if */
	    return(true);
	} /* while */
    } /* if */
    return(false);
} /* FNextLocal */


/* I P D   F   A D R */

export int IpdFAdr(adr)
FAST ADRT	adr;
{
    FAST int2 	ipd, ipdHi, ipdLo;

    if (adr >= v->rgPd[v->hdr.ipdMax-1].adr)
	return(v->hdr.ipdMax-1);	/* check for past last entry */

    if ((v->ipd != ipdNil)
       AND (v->rgPd[v->ipd].adr <= adr)
       AND (v->rgPd[v->ipd+1].adr > adr))
	return(v->ipd);

    /* binary search the proc table */
    ipdLo = 0;
    ipdHi = v->hdr.ipdMax - 1;
    while (true) {
	ipd = (ipdLo+ipdHi) / 2;
	if (adr < v->rgPd[ipd].adr) {

	    ipdHi = ipd - 1;

	} else if (adr >= v->rgPd[ipd+1].adr) {

	    ipdLo = ipd + 1;

	} else {

	    /* walk backwards to first proc with this adr */
	    while (ipd && v->rgPd[ipd].adr == v->rgPd[ipd-1].adr)
		ipd--;
	    return(ipd);	/* gotchya! */

	} /* if */

	if (ipdLo > ipdHi)
	    UError("Address (%s) does not map to instruction space.",
			SbFAdr(adr, false));
    } /* while */
} /* IpdFAdr */


/* I F D   F   A D R */

export int IfdFAdr(adr)
FAST ADRT	adr;
{
    FAST int2	ifd, ifdHi, ifdLo;
    pFDR	fd;

    if (adr >= v->rgFd[v->hdr.ifdMax-1].adr)
	return(v->hdr.ifdMax-1);	/* check for past last entry */

    if ((v->ifd != ifdNil)
       AND (v->rgFd[v->ifd].adr <= adr)
       AND (v->rgFd[v->ifd+1].adr > adr))
	return(v->ifd);

    /* binary search the file table */
    ifdLo = (v->rgFd[0].adr == adrNil) ? 1 : 0; /* ifd0 is for temp files */
    ifdHi = v->hdr.ifdMax - 1;
    while (true) {
	ifd = (ifdLo+ifdHi) / 2;
	if (adr < v->rgFd[ifd].adr) {

	    ifdHi = ifd - 1;
		
	} else if (adr >= v->rgFd[ifd+1].adr) {

	    ifdLo = ifd + 1;

	} else {

	    /* gotchya! */
	    /* Now we walk forward to the last file i a row with this adr */
	    fd = v->rgFd + ifd;
	    while (fd->adr == fd[1].adr)
		fd++;
	    return(fd - v->rgFd);	/* give them the index */

	} /* if */

	if (ifdLo > ifdHi)
	    UError("Address (%s) does not map to a file.", SbFAdr(adr, false));
    } /* while */
} /* IfdFAdr */


/* I F D   F   I S Y M */

export int IfdFIsym(isym)
FAST int4	isym;
{
    FAST int2	ifd, ifdHi, ifdLo;
    pFDR	fd;

    if (isym >= v->rgFd[v->hdr.ifdMax-1].isym)
	return(v->hdr.ifdMax-1);	/* check for past last entry */

    if ((v->ifd != ifdNil)
       AND (v->rgFd[v->ifd].isym <= isym)
       AND (v->rgFd[v->ifd+1].isym > isym))
	return(v->ifd);

    /* binary search the file table */
    ifdLo = 1; /* ifd0 is for temp files */
    ifdHi = v->hdr.ifdMax - 1;
    while (true) {
	ifd = (ifdLo+ifdHi) / 2;
	if (isym < v->rgFd[ifd].isym) {

	    ifdHi = ifd - 1;
		
	} else if (isym >= v->rgFd[ifd+1].isym) {

	    ifdLo = ifd + 1;

	} else {

	    /* gotchya! */
	    return(ifd);	/* give them the index */

	} /* if */

	if (ifdLo > ifdHi)
	    UError("Isym (%d) does not map to a file.", isym);
    } /* while */
} /* IfdFIsym */


/* I L I N E   L I M   F   I P D */

local int4 IlineLimFIpd(ipd)
int2	ipd;
{
    int4	iline, ilineMax;
    ADRT	adr;
    pPDR	pd = v->rgPd + ipd;
    FAST int	ipdNext;

    /* given an ipd, find the next highest iline NOT in the proc */
    if (pd->iline == 0)
	return(0);	/* no line info */

    /* find the next procedure with symbols */
    if (ipd == v->hdr.ipdMax-1)  {
	return(v->hdr.ilineMax);	/* we are last procedure */
    } else {
	ipdNext = ipd + 1;
	while (ipdNext < v->hdr.ipdMax) {
	    if (v->rgPd[ipdNext].iline != 0)
		break;
	    ipdNext++;
	} /* while */
	if (ipdNext == v->hdr.ipdMax)
	    return(v->hdr.ilineMax);	/* we are last procedure with symbols */
    } /* if */

    return(v->rgPd[ipdNext].iline);
} /* IlineLimFIpd */


/* A D R   F   I P D   I L N */

export ADRT AdrFIpdIln(ipd, iln)
int2     ipd, iln;
{
    FAST int4	iline, ilineLim;
    ADRT	adr;
    pPDR	pd;

    if (ipd == ipdNil)
	return(adrNil);

    pd = v->rgPd + ipd;
    if (pd->iline == 0)
	return(pd->adr);

    iline = pd->iline;
    if (iln < LineFIline(iline)->iln)
	return(adrNil);		/* this iln is BEFORE this procedure */

    ilineLim = IlineLimFIpd(ipd);
    if (iln > LineFIline(ilineLim-1)->iln)
	return(adrNil);	/* this iln is AFTER this procedure */

    /* start at beginning of enclosing proc */
    while ((iline < ilineLim) AND (LineFIline(iline)->iln < iln))
	++iline;

    if (iline >= ilineLim)
	iline = ilineLim - 1;	/* off end of proc */

    adr = pd->adr + LineFIline(iline)->dadr;
    return(adr);
} /* AdrFIpdIln */


/* I P D   I L N   F   A D R */

export int IpdIlnFAdr(piln, pslop, adr)
int2     *piln, *pslop;
ADRT    adr;
{
    int2	ipd;
    FAST int4	iline, ilineLim;
    FAST ADRT	dadr;
    pPDR	pd;
    pLINER	line;

    *piln = ilnNil;
    *pslop = 0;

    if (adr == adrNil)
	return(ipdNil);

    ipd = IpdFAdr(adr);
    pd = v->rgPd + ipd;
    /* delta adr from start of proc */
    dadr = adr - pd->adr;

    if (pd->iline == 0) {  /* proc does not have line numbers */
	*pslop = dadr;
	return(ipd);
    } /* if */

    /* we now have the proc, try to get the line number */

    iline = pd->iline;
    ilineLim = IlineLimFIpd(ipd);

    /* find highest iln that maps to this dadr */
    while ((iline < ilineLim) AND LineFIline(iline)->dadr <= dadr)
	iline++;

    if ((iline > pd->iline)
       AND ((iline >= ilineLim)
	   OR (LineFIline(iline)->dadr > dadr)))
	iline--;	/* overshoot - backup one */

    line = LineFIline(iline);
    *piln = line ->iln;
    *pslop = dadr - line->dadr;
    return(ipd);
} /* IpdIlnFAdr */


/* I F D   I L N   F A D R */

export int2 IfdIlnFAdr(piln, adr)
int2	*piln;
ADRT	adr;
{
    int4	slop;

    IpdIlnFAdr(piln, &slop, adr);
    return(IfdFAdr(adr));
} /* IfdIlnFAdr */


/* A D R   F   I F D   I L N */

export ADRT AdrFIfdIln(ifd, iln)
int2     ifd, iln;
{
    FAST pPDR	pd, pdLim;

    if ((ifd == ifdNil) OR (ifd == ifdTemp))
	return(adrNil);

    if (v->rgFd[ifd].iline == 0)
	return(adrNil);	/* no symbols, so this is a meaningless map */

    /* first find ipd of enclosing procedure */

    pd = v->rgPd + v->rgFd[ifd].ipd;	/* first procedure in file */
    if (iln < LineFIline(pd->iline)->iln)
	return(adrNil);	/* line is BEFORE first procedure */

    if (ifd == v->hdr.ifdMax-1)
	pdLim = v->rgPd + v->hdr.ipdMax - 1;	/* last procedure in file */
    else
	pdLim = v->rgPd + v->rgFd[ifd+1].ipd;

    /* loop til we find one with greater iln's */
    while ((pd < pdLim) AND (LineFIline(pd->iline)->iln < iln))
	pd++;

    if (pd >= pdLim)
	pd = pdLim - 1;	/* off end of file */
    else if (LineFIline(pd->iline)->iln > iln)
	pd--;	/* overshoot */

    /* now we know proc, call main routine */
    return( AdrFIpdIln(pd-v->rgPd, iln) );
} /* AdrFIfdIln */


/* A D R   F   E N D   O F   P R O C */

export ADRT AdrFEndOfProc(ipd)
int2	ipd;
{
    int4	iline;

    iline = IlineLimFIpd(ipd);
    if (iline == 0)
	UError("No symbols - unable to determine end-of-procedure.");
    /* get address of last line */
    return(v->rgPd[ipd].adr + LineFIline(iline-1)->dadr);
} /* AdrFEndOfProc */


/* C B L   F   F N */

export long CblFFn(fn)
int2	fn;
{
    struct stat statbuf;

    fstat(fn, &statbuf);
    return(statbuf.st_size);
} /* CblFFn */


/* A G E   F   F N */

export long AgeFFn(fn)
int2	fn;
{
    struct stat statbuf;

    fstat(fn, &statbuf);
    return(statbuf.st_mtime);
} /* AgeFFn */
0707070001000312341004440000000000010000011601570454650113700001100000030136cdb/tk.c /* $Header: tk.c,v 5.14 86/05/28 08:04:42 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <ctype.h>
#include "cdb.h"

#define cbNumMax 40
#define	chTab	'\t'
#define	chSpace	' '
#define chUnder	'_'
#define chDollar '$'
#define	chBackSlash '\\'
#define FOctal(ch) ((ch >= '0') && (ch <= '7'))

export int2	vcbTok, vcbPeek;
export TKE	vtk, vtkPeek;
export char	vsbTok[100], vsbTokPeek[100];

typedef struct {	/* keyword */
	SBT	sbKey;
	int2	tk;
	} KWR, *pKWR;
#define cbKWR	sizeof(KWR)
#define kwNil ((pKWR)0)

KWR vrgKwCdb[] = {
	"$in",	tkInside,
	"$arg",	tkArg,
	};
#define ikwCdbMax (sizeof(vrgKwCdb)/cbKWR)

KWR vrgKwC[] = {
	"sizeof",	tkSizeof,
	"unsigned",	tkUnsigned,
	"char",		tkChar,
	"short",	tkShort,
	"int",		tkInt,
	"long",		tkLong,
	"float",	tkFloat,
	"double",	tkDouble,
	"struct",	tkStruct,
	"union",	tkUnion,
	"enum",		tkEnum,
	};
#define ikwCMax (sizeof(vrgKwC)/cbKWR)

KWR vrgKwFor[] = {
	".NE.",	tkNotEqual,
	".EQ.",	tkEqual,
	".LT.",	tkLT,
	".LE.",	tkLE,
	".GT.",	tkGT,
	".GE.",	tkGE,
	".OR.", tkLOR,
	".AND.", tkLAND,
	".NOT.", tkBang,
	".TRUE.", tkNumber,
	".FALSE.", tkNumber,
	"integer",	tkInt,
	"character",	tkChar,
	"real",		tkFloat,
	"complex",	tkComplex,
	"logical",	tkLogical,
	};
#define ikwForMax (sizeof(vrgKwFor)/cbKWR)

/* leave isodigit as a routine so we can icrement arguments */

export int isodigit (ch)
char ch;
{
    return (isdigit(ch) && (ch!='8') && (ch!='9'));
} /* isodigit */


/* S E A R C H   T D */

export void SearchTd(ptk, sb)
TKE	*ptk;
SBT	sb;
{
    pTDR	td;
    int		i;

    if (! vfTypedefs)
	return;

    for (i = 0, td = v->rgTd; i < v->hdr.itdMax; i++, td++) {
	if (strcmp(sb, SbFIss(td->iss)) == 0) {
	    SeFSym(&yylval, SymFIsym(td->isym), true);
	    *ptk = tkTypedef;
	    return;
	} /* if */
    } /* for */
} /* SearchTd */


/* S E A R C H   K W */

export void SearchKw(ptk, sbKey, rgKw, ikwMax)
TKE	*ptk;
SBT	sbKey;
pKWR	rgKw;
int2	ikwMax;
{
    int		i;

    for (i=0; i < ikwMax; i++) {
	if (FSbCmp(sbKey, rgKw[i].sbKey)) {
	    *ptk = rgKw[i].tk;
	    return;
	} /* if */
    } /* for */
} /* SearchKw */


/* C H   F   E S C A P E */

export char ChFEscape(psbIn, fEatBackSlash)
SBT	*psbIn;
FLAGT	fEatBackSlash;
{
    int		i, intval;
    char	ch;

    ch = **psbIn;
    (*psbIn)++;
    if (fEatBackSlash) {
	if (ch != chBackSlash)
	    return(ch);	/* vanilla flavored char */
	ch = **psbIn;
	(*psbIn)++;
    } /* if */

    switch (ch) {
	case 'b':	return('\b');
	case 'f':	return('\f');
	case 'n':	return('\n');
	case 'r':	return('\r');
	case 't':	return('\t');

	case '0': case '1': case '2': case '3':
	case '4': case '5': case '6': case '7':
	    /* it is an arbitrary 1-3 octal digit thingie */
	    intval = 0;
	    for (i=0; i<3; i++) {
		intval = (intval * 8) + (ch - '0');
		ch = **psbIn;	/* look at NEXT character */
		if (!FOctal(ch))
		    break;
		(*psbIn)++;	/* is good digit, advance str pointer */
	    } /* for */
	    return(intval);
    } /* switch */
    return(ch);	/* by default we just ignore the backslash */
} /* ChFEscape */


/* T K   F   S T R */

export TKE TkFStr(psbCmd, sbTok, pcb, fIgnoreErrors)
SBT	*psbCmd, sbTok;
int2	*pcb;
FLAGT	fIgnoreErrors;
{
    int		i, cbMax;
    FLAGT	fFloat;
    char	ch, sbTemp[100], sbNum[300];
    SBT		sbCmd, sbStart, sbNumT;
    TKE		tk;

    /* given a string, copy first token to safe place and advance string */

    cbMax = *pcb;
    sbCmd = *psbCmd;
    if (sbCmd == sbNil)
	return(tkNil);

    while ((*sbCmd == chTab) OR (*sbCmd == chSpace))
	sbCmd++;	/* eat leading tabs and spaces */

    if (*sbCmd == chNull) {
	*pcb = 0;
	sbTok[0] = chNull;
	return(tkNil);
    } /* if */

    sbStart = sbCmd; /* remember where we started */

    tk = tkNil;
    ch = *sbCmd++;
    if (isalpha(ch)
	OR (ch == chUnder)
	OR (ch == chDollar)) {  /* string (var|command) token */
	tk = tkStr;
	while (isalnum(*sbCmd)
	       OR (*sbCmd == chUnder) 
	       OR (*sbCmd == chDollar))
	    sbCmd++;
    } else if ( isdigit(ch) OR ((ch == '.') AND (isdigit(*sbCmd))) ) {
	/* number */
	tk = tkNumber;
	sbNumT = sbNum;

	if ((ch == '0') && (*sbCmd != '.')) {

	    /* hex or octal */
	    if (*sbCmd == 'x') {
		/* it's a hex number */
	        sbCmd++;
	        while (isxdigit(*sbNumT++ = *sbCmd))
		    sbCmd++;
		*--sbNumT = '\0';
		if ((sbNumT - sbNum) >= cbNumMax)
		    UError("Hex constant has too many characters(> %d).",
				cbNumMax);
		sscanf (sbNum, "%lx", &yylval.val.valLong);
	    } else {
		/* it's octal */
		*sbNumT++ = ch;	/* get 0 so if it really is 0 we get a num */
	        while (isodigit(*sbNumT++ = *sbCmd))
		    sbCmd++;
		*--sbNumT = '\0';
		if ((sbNumT - sbNum) >= cbNumMax)
		    UError("Octal constant has too many characters(> %d).",
				cbNumMax);
		sscanf (sbNum, "%lo", &yylval.val.valLong);
	    } /* if octal or hex */

	} else { /* it's either an integer or float */

	    fFloat = (ch == '.'); /* of the form ".123" */
	    *sbNumT++ = ch;	/* save first digit OR '.' */
	    /* pick up digit string */
	    while (isdigit(*sbNumT++ = *sbCmd))
		sbCmd++;

	    if (*sbCmd == '.') {
		/* a float of the form "123.456" */
		*sbCmd++;	/* increment past the '.' */
		/* and the fractional part */
		while (isdigit(*sbNumT++ = *sbCmd))
		    sbCmd++;
		fFloat = true;
	    } /* if */

	    if ( ((*sbCmd == 'e') OR (*sbCmd == 'E'))
	       AND (isdigit(sbCmd[1])
		  OR (sbCmd[1] == '+')
		  OR (sbCmd[1] == '-')) ) {
		/* a float of the form "xxx.xxxeYY" OR "xxxEYYY" */
		*sbCmd++;	/* increment past the 'e' */
		if ((*sbCmd == '-') OR (*sbCmd == '+'))
		    *sbNumT++ = *sbCmd++; /* pick up the sign */
		/* and the fractional part */
		while (isdigit(*sbNumT++ = *sbCmd))
		    sbCmd++;
		fFloat = true;
	    } /* if */

	    *--sbNumT = '\0';
	    if ((sbNumT - sbNum) >= cbNumMax)
		UError("Numeric constant has too many characters(> %d).",
			    cbNumMax);

	    if (fFloat) { /* its a float */

		if ((sbNumT - sbNum) >= cbNumMax)
		    UError("Float constant has too many characters(> %d).",
				cbNumMax);
		sscanf (sbNum, "%lf", &yylval.val.valDouble);
		CopyTy(&yylval, vseCnDouble);
		tk = tkFltConstant;

	    } else { /* it's a good old regular number */

		if ((sbNumT - sbNum) >= cbNumMax)
		    UError("Integer constant has too many characters(> %d).",
				cbNumMax);
		sscanf (sbNum, "%ld", &yylval.val.valLong);

	    } /* if float or integer */
	} /* if */

	if (tk == tkNumber) {
	    if (*sbCmd == 'L' OR *sbCmd == 'l') { /* they wanted a long */
		sbCmd++;
		CopyTy(&yylval, vseCnLong);
	    } else if ((yylval.val.valLong & 0xffff8000) == 0) {
		yylval.val.valInt = yylval.val.valLong;
		CopyTy(&yylval, vseCnInt);
	    } else {
		CopyTy(&yylval, vseCnLong);
	    } /* if */
	} /* if find out long or short */

	yylval.ti.fConstant = true;

    } else if (! ispunct(ch)) {

	/* it's  <something else> !! */
	tk = tkOther;

    } else {

	/* hopefully an interesting operator or something */
	switch (ch) {
	    case '[':	tk = tkLSB;	break;
	    case ']':	tk = tkRSB;	break;
	    case '(':	tk = tkLP;	break;
	    case ')':	tk = tkRP;	break;
	    case '{':	tk = tkLCB;	break;
	    case '}':	tk = tkRCB;	break;
	    case '?':	tk = tkQuest;	break;
	    case '@':	tk = tkAt;	break;
	    case '$':	tk = tkDollar;	break;
	    case '#':	tk = tkHash;	break;
	    case ';':	tk = tkSemi;	break;
	    case ',':	tk = tkComma;	break;
	    case '~':	tk = tkTilda;	break;
	    case '_':	tk = tkUnderScore; break;
	    case '\\':	tk = tkBackSlash; break;

	    case '\'':	tk = tkCharConstant;
			sbTok[0] = ChFEscape(&sbCmd, true);
			if (!fIgnoreErrors AND (*sbCmd != '\''))
			    UError("Character constant is missing ending '.");
			sbCmd++;
			*pcb = 1;
			goto special;

	    case '"':	tk = tkStrConstant;
			i = 0;
			while ((*sbCmd != chNull) AND (*sbCmd != '"')) {
			    sbTok[i] = ChFEscape(&sbCmd, true);
			    i++;
			   if (i >= cbMax)
			    UError("String literals may not be larger than %d.",
					cbMax);
			} /* while */
			if (!fIgnoreErrors AND (*sbCmd != '"'))
			    UError("String constant is missing ending \".");
			sbCmd++;
			*pcb = i;
	   		goto special;

	    case '.':	tk = tkDot;
			if (v->lc != lcFortran)
			    break;

			/* pick up the Fortrash symbol */
			tk = tkNil;
			sbNumT = sbCmd;
			while (*sbNumT AND (*sbNumT != '.'))
			    sbNumT++;
			i = sbNumT - (sbCmd - 1);
			strncpy(sbTemp, sbCmd-1, i); /* get the whole thing */
			sbTemp[i] = chNull;
			SearchKw(&tk, sbTemp, vrgKwFor, ikwForMax);
			if (tk != tkNil) {
			    /* we have a hit */
			    sbCmd += i - 1;
			} /* if */
			break;

	    case ':':	tk = tkColon;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssign;
			} /* if */
			break;

	    case '+':	tk = tkPlus;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssPlus;
			} else if (*sbCmd == '+') {
			    sbCmd++;
			    tk = tkPlusPlus;
			} /* if */
			break;

	    case '-':	tk = tkMinus;
			if (*sbCmd == '>') {
			    sbCmd++;
			    tk = tkPtr;
			} else if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssMinus;
			} else if (*sbCmd == '-') {
			    sbCmd++;
			    tk = tkMinusMinus;
			} /* if */
			break;

	    case '*':	tk = tkStar;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssMult;
			} else if ((v->lc == lcC) AND (*sbCmd == '/')) {
			    sbCmd++;
			    tk = tkEndComment;
			} else if ((v->lc == lcFortran) AND (*sbCmd == '*')) {
			    sbCmd++;
			    tk = tkPower;
			} /* if */
			break;

	    case '/':	tk = tkSlash;
			if (*sbCmd == '/') {
			    sbCmd++;
			    tk = tkDiv;
			    if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssDiv;
			    } /* if */
			} else if (*sbCmd == '*') {
			    sbCmd++;
			    tk = tkStartComment;
			} /* if */
			break;

	    case '%':	tk = tkModulo;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssMod;
			} /* if */
			break;

	    case '&':	tk = tkBitAnd;
			if (*sbCmd == '&') {
			    sbCmd++;
			    tk = tkLAND;
			} else if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssBAND;
			} /* if */
			break;

	    case '|':	tk = tkBitOr;
			if (*sbCmd == '|') {
			    sbCmd++;
			    tk = tkLOR;
			} else if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssBOR;
			} /* if */
			break;

	    case '^':	tk = tkXOR;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkAssXOR;
			} /* if */
			break;

	    case '!':	tk = tkBang;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkNotEqual;
			} /* if */
			break;

	    case '=':	tk = tkAssign;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkEqual;
			} /* if */
			break;

	    case '<':	tk = tkLT;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkLE;
			} else if (*sbCmd =='<') {
			    sbCmd++;
			    tk = tkLShift;
			    if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssLeft;
			    } /* if */
			} else if (*sbCmd == '>') {
			    sbCmd++;
			    tk = tkNotEqual;
			} /* if */
			break;

	    case '>':	tk = tkGT;
			if (*sbCmd == '=') {
			    sbCmd++;
			    tk = tkGE;
			} else if (*sbCmd == '>') {
			    sbCmd++;
			    tk = tkRShift;
			    if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssRight;
			    } /* if */
			} /* if */
			break;
	} /* switch */
    } /* if */

    *pcb = sbCmd - sbStart;
    if (*pcb >= cbMax)
	UError("Token is too large.  May not exceed %d characters.", cbMax);
    strncpy(sbTok, sbStart, *pcb);

special:	/* used by character and string constant routines */
    sbTok[*pcb] = chNull;
    *psbCmd = sbCmd;

    if (tk == tkStr) {
	/* typedefs override commands */
	SearchTd(&tk, sbTok);
	if (tk != tkStr)
	    return(tk);

	/* commands override language keywords */
	SearchKw(&tk, sbTok, vrgKwCdb, ikwCdbMax);
	if (tk != tkStr)
	    return(tk);

	switch (v->lc) {
	    default:
	    case lcC:	     SearchKw(&tk, sbTok, vrgKwC, ikwCMax); break;
	    case lcFortran:  SearchKw(&tk, sbTok, vrgKwFor, ikwForMax); break;
	} /* switch */
    } /* if */
    return(tk);
} /* TkFStr */


/* T K   P E E K */

export TKE TkPeek()
{
    char	*sbCmd;

    /* used to peek at next token in global command line */
    sbCmd = v->sbCmd;
    vcbPeek = sizeof(vsbTokPeek);
    vtkPeek = TkFStr(&sbCmd, vsbTokPeek, &vcbPeek, true);
    return(vtkPeek);
} /* TkPeek */


/* T K   N E X T */

export TKE TkNext()
{
    /* used by most routines to eat next token in the global command line */

    vcbTok = sizeof(vsbTok);
    vtk = TkFStr(&v->sbCmd, vsbTok, &vcbTok, false);
    return(vtk);
} /* TkNext */
0707070001000312351004440000000000010000011603210454650113700001400000000441cdb/valid.c /* $Header: valid.c,v 5.6 86/03/31 08:09:33 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"

int4 	vAnd, vOr, vXor;


/* V A L I D A T E */

Validate() {
    vAnd = -1;
    vOr = 0;
    vXor = 0;
} /* Validate */


Purchase() {}
0707070001000312361004440000000000010000011603300454650113700001200000067333cdb/var.c /* $Header: var.c,v 6.2 86/09/14 20:24:02 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "cdb.h"

/* In the following array, symbols of type stExpr point to a debugger global,
 * and can therefore have their address directly computed.  Those
 * with type stNil point into the CURRENT process structure (v).
 * These have the field offset of the desired field.  By default, the fields
 * are of type INT.  If they are going to be something else, you
 * have to do extra fiddling aroung in InitSpecials and FSpecial.
 * The first 2 are extra special in that thay are a dynamic calculation
 * of the current FILE and PROCEDURE names.
 */

export int	vfStrict = true;	/* prevents sloppy struct references */
export int	vfTypedefs = true;	/* allows typedefs in scanner */
export int	vfNotify = true;	/* notify me about stopped processes */
export int	vdadrMax = 1024; /* distance to nearest label to use offset */
export int	vfArnulf = false;	/* Arnulf's disassembly flag */

#if (CPU == PDN)
int	vfPdnExtStart = 1;
#endif /* (CPU == PDN) */

#define APR(x)		((uint4)(&(((pPRR)0)->x)))

static pSER vrgSpc;	/* array of System Special variables */
static int vispcMax;


/* I N I T   S P C */

export void InitSpc(se, sb, value, st, sc, tq0, bt, fConstant)
pSER	se;
SBT	sb;
int	st, sc, tq0, bt;
FLAGT	fConstant;
{
    *se = *vseInit;
    se->asym.iss = IssFSb(sb);;
    se->asym.value = value;
    se->asym.st = st;
    se->asym.sc = sc;
    se->ti.fConstant = fConstant;
    se->ti.tq0 = tq0;
    se->ti.bt = bt;
} /* InitSpc */


/* I N I T   S P E C I A L S */

export void InitSpecials()
{
    int		ispc;
    pSER	se;

    vispcMax = 20;	/* This number MUST BE >= number of system specials */
    vrgSpc = (pSER) malloc(vispcMax * cbSER);
    se = vrgSpc;

	/* ----- P R O C E S S   V A L U E S ------ */
#define ispcProcess	0
    InitSpc(se++, "_PROCESS", 0L, stNil, scCdbSystem, tqNil, btInt, true);
#define ispcFile	1
    InitSpc(se++, "_FILE", 0L, stNil, scCdbSystem, tqArray, btChar, true);
#define ispcProcedure	2
    InitSpc(se++, "_PROCEDURE", 0L, stNil, scCdbSystem, tqArray, btChar, true);
#define ispcLine	3
    InitSpc(se++, "_LINE", APR(iln), stNil, scCdbSystem, tqNil, btInt, true);
#define ispcBreak	4
    InitSpc(se++, "_BREAK", 0L, stNil, scCdbSystem, tqNil, btInt, true);
#define	ispcText	5
    InitSpc(se++,"_TEXT",APR(adrText), stNil, scCdbSystem, tqNil, btInt, false);
#define	ispcData	6
    InitSpc(se++,"_DATA",APR(adrData), stNil, scCdbSystem, tqNil, btInt, false);
#define ispcNormalMin	7

    InitSpc(se++, "_TRACE", APR(tracelevel), stNil,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_LEVEL", APR(debuglevel), stNil,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++,  "_LANGUAGE", APR(lc), stNil,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_COMM", APR(fCommDebug), stNil,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_CACHE", (uint4)&vfUseCache, stExpr,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_ARNULF", (uint4)&vfArnulf, stExpr,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_NOTIFY", (uint4)&vfNotify, stExpr,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_STRICT", (uint4)&vfStrict, stExpr,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "_TYPES", (uint4)&vfTypedefs, stExpr,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "SIGNAL", APR(sig), stNil,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "R_SIGNAL", APR(sigOrig), stNil,
				scCdbSystem, tqNil, btInt, false);
    InitSpc(se++, "DELTA", (uint4)&vdadrMax, stExpr,
				scCdbSystem, tqNil, btInt, false);
#if (CPU == PDN)
    InitSpc(se++, "_EXT", (Ulong)&vfExtStart, stExpr,
				scCdbSystem, tqNil, btInt, false);
#endif /* (CPU == PDN) */

    ispc = se - vrgSpc;
    if (ispc >= vispcMax)
       Panic("Under allocated systems specials array: %d > %d.",
		ispc, vispcMax);
    vispcMax = ispc;
} /* InitSpecials */


/* L I S T   S P E C I A L S */

export void ListSpecials(sbSpc)
SBT	sbSpc;
{
    int		i;
    SBT		sb;
    pSER	se;
    SER		ase;

    MoreOn();

    /* first check the System Specials */
    printf("System special variables\n");
    for (i=0; i < vispcMax; i++) {
	se = vrgSpc + i;
	sb = SbFIss(se->asym.iss);
	if (sbSpc != sbNil) {
	    if (!FHdrCmp(sbSpc, sb))
		continue;	/* not interesting */
	} else {
	    if (*sb == '_')
		continue;	/* they didn't ask for it */
	} /* if */
	ase = *se;	/* we do this on a COPY */
	FSpecial(&ase);
	DisplaySe(&ase, modeNil, true, true, true);
	printf("\n");
    } /* for */

    /* next do user defined stuff */
    if ( v->ilvMac > 0) {
	printf("\nUser special variables\n");
	for (i=0; i < v->ilvMac ; i++) {
	    se = v->rgLv + i;
	    if ((sbSpc != sbNil)
	       AND (!FHdrCmp(sbSpc, SbFIss(se->asym.iss))) )
		continue;	/* not interesting */
	    ase = *se;	/* we do this on a COPY */
	    FSpecial(&ase);
	    DisplaySe(&ase, modeNil, true, true, true);
	    printf("\n");
	} /* for */
    } /* if */

    MoreOff();
} /* ListSpecials */


/* F   S P E C I A L */

export FLAGT FSpecial(seRet)
pSER	seRet;
{
    int		i;
    SBT		sbSpc = SbSafeFIss(seRet->asym.iss);
    pSER	seT;
    FLAGT	fDollar = false;

    if (*sbSpc == '$') {
	sbSpc++;
	fDollar = true;
	if (*sbSpc == '_')
	    fDollar = false;	/* hidden system special */
    } /* if */

    /* first check the registers */
    for (i=0; i < v->cpu->iregMax; i++) {
	seT = v->cpu->rgReg + i;
	if (FSbCmp(SbFIss(seT->asym.iss), sbSpc)) {
	    *seRet = *seT;
	    return(true);
	} /* if */
    } /* for */

    /* next, check system specials */
    for (i=0; i < vispcMax; i++) {
	seT = vrgSpc + i;
	if (FSbCmp(SbFIss(seT->asym.iss), sbSpc)) {
	    *seRet = *seT;
	    if (seRet->asym.st == stNil) {
		seRet->asym.st = stExpr;
		switch (i) {
		    default:
			seRet->asym.value += (long)v; /* offset in cur PRR */
			if (seRet->ti.fConstant) {
			    seRet->ti.fConstant = false;
			    seRet->val = ValFSe(seRet);
			    seRet->ti.fConstant = true;
			} /* if */
			break;

		    case ispcProcedure:	/* magic hack for procedure name */
			seRet->asym.value =
				seRet->val.valAdr = (ADRT) SbFIpd(v->ipd);
			break;

		    case ispcFile:	/* magic hack for file name */
			seRet->asym.value =
			 seRet->val.valAdr = (ADRT) SbFIss(v->rgFd[v->ifd].iss);
			break;

		    case ispcProcess:	/* infer process number */
			seRet->asym.value = seRet->val.valInt = IprFPr(v);
			break;

		    case ispcBreak:	/* infer break point number */
			seRet->asym.value = seRet->val.valInt = 
				(v->bp == bpNil) ? -1 : v->bp - v->rgBp;
			break;

		} /* switch */
	    } /* if */
	    return(true);
	} /* if */
    } /* for */

    /* next check the user defined specials */
    for (i=0; i < v->ilvMac; i++) {
	seT = v->rgLv + i;
	if (FSbCmp(SbFIss(seT->asym.iss), sbSpc)) {
	    *seRet = *seT;
	    return(true);
	} /* if */
    } /* for */

    if (!fDollar)
	return(false);	/* keeps typo's from becoming special variables! */

    /* no luck = try to define a new special with this name */
    if (v->ilvMac >= v->ilvMax) {
	SER	ase, *se;

	if (v->ilvMax == 0) {
	    v->ilvMax = 10;
	    v->rgLv = (pSER) malloc(v->ilvMax * cbSER);
	} else {
	    v->ilvMax += 10;
	    v->rgLv = (pSER) realloc(v->rgLv, v->ilvMax * cbSER);
	    if (v->rgLv == 0)
		Panic("Ran out of memory.");
	} /* if */

	ase = *vseInt;
	ase.asym.sc = scCdbLocal;
	ase = *vseInt;
	ase.asym.sc = scCdbLocal;
	for (i = v->ilvMax-10, se = v->rgLv+i; i < v->ilvMax; se++, i++)
	    *se = ase;
    } /* if */

    i = v->ilvMac++;
    seT = v->rgLv + i;
    *seT = *vseInt;
    seT->asym.iss = IssFSb(SbFAlloc(sbSpc));
    seT->asym.sc = scCdbLocal;
    seT->asym.st = stExpr;
    seT->asym.value = (ADRT) seT;	/* points  at itself */
    *seRet = *seT;
    return(true);
} /* FSpecial */


/* S P E C I A L   S I D E   E F F E C T S */

export void SpecialSideEffects(seNew, seCur)
pSER	seNew, seCur;
{
    /* this is called just before ASSIGNing a new value to a special */
    if (FSbCmp("_TRACE", SbFIss(seCur->asym.iss))) {
	v->cCallNest =  -1;	/* force them to reinitialize this */
    } /* if */
} /* SpecialSideEffects */


/* A D J U S T   F I E L D   O F F S E T */

export void AdjustFieldOffset(seStruct, seField)
pSER	seStruct, seField;
{
    if (seField->asym.sc == scBits) {
	/* set address to base of struct */
	seField->asym.value = seStruct->asym.value;
    } else {
	/* set address to byte boundary */
	seField->asym.value = (seField->asym.value / 8) + seStruct->asym.value;
    } /* if */
    if ((seField->ti.tq0 == tqArray) OR (seField->ti.tq0 == tqProc))
	seField->val.valAdr = seField->asym.value;
} /* AdjustFieldOffset */


/* F   F I E L D */

export FLAGT FField(seStruct, seField)
pSER	seStruct, seField;
{
    FLAGT	fFoundIt = false;
    SBT		sbField;

    /* somewhere in this struct/union is the field info, stuff it in seField */

    sbField = SbSafeFIss(seField->asym.iss); /* get the name of the field */

    SetNextSym(seStruct->isymRef + 1);
    if (FNextSym(stMember, stNil, stNil, stEnd, false, sbField, FSbCmp))
	fFoundIt = true;

    if (! fFoundIt AND ! vfStrict AND (v->ifd != ifdNil)) {
	/* No luck! -  search elsewhere for this field name.  */
	SetNextSym(v->rgFd[v->ifd].isym+1);	/* start at beginning of file */

	if (FNextSym(stMember, stNil, stNil, stFile, true, sbField, FSbCmp))
	    fFoundIt = true;
    } /* if */

    if (! fFoundIt) {
	UError("No such field name \"%s\" for \"%s %s\".",
		    sbField,
		    (seStruct->ti.bt==btStruct) ? "struct" : "union",
		    SbFIss(seStruct->asym.iss) );
	return(false);
    } /* if */

    /* Success! - get the type goodies */
    SeFSym(seField, v->sym, true);
    AdjustFieldOffset(seStruct, seField);
    return(true);
} /* FField */


/* I S Y M   N E X T   F   B L O C K */

export long IsymNextFBlock(isym)
int4	isym;
{
    pSYMR	sym = SymFIsym(isym);
    pAUXU	aux;

    if (sym->st == stProc) {
	/* first AUX for proc is isymLast+1 of block */
	aux = AuxFIaux(sym->index);
	return(aux->isym);
    } else {
	return(sym->index);
    } /* if */
} /* IsymNextFBlock */


/* I S Y M   F	 E N C L O S I N G */

export long IsymFEnclosing(adr)
ADRT	adr;
{
    int4	isym, isymTemp;

    /* This routine finds the inner most enclosing scope
     * and returns the isym of the beginning block.
     */

    isym = v->rgPd[IpdFAdr(adr)].isym;

    SetNextSym(isym + 1);
    while (FNextSym(stBlock, stNil, stNil, stProc, true, sbNil, nil)) {
	if (v->sym->sc != scText) {
	    /* skip non-text blocks */
	    isymTemp = IsymNextFBlock(v->isym);
	    if (isymTemp == isymNil)
		return(isymNil);
	    SetNextSym(isymTemp);
	    continue;
	} /* if */

	if (adr < v->sym->value)
	    break;	/* everything from here on is too far in memory */
	
	/* Look at matching END symbol */
	SymFIsym(v->sym->index-1);
	if (adr >= v->sym->value ) {
	    /* we can completely skip this block - it's before us */
	    continue; /* this works because FNextSym moves to next symbol */
	} /* if */

	SymFIsym(v->sym->index);	/* point back to BLOCK */
	isym = v->isym;	/* remember this - it is currently the inner most */
    } /* while */

    return(isym);
} /* IsymFEnclosing */


/* I S Y M   F	 A D R */

export long IsymFAdr(adr, isymHint)
ADRT	adr;
int4	isymHint;
{
    int2	ipd;
    int4	isym;

    /* This routine finds the next outer enclosing scope
     * and returns the isym of the beginning block.
     */

    if (isymHint == isymNil) {
	/* they know nothing - get inner most */
	return( IsymFEnclosing(adr) );
    } /* if */

    /* We now look for block ends */

    /* Start with symbol following the block we last gave them */
    isym = IsymNextFBlock(isymHint);
    if (isym == isymNil)
	return(isymNil);

    SetNextSym(isym);

    while (FNextSym(stEnd, stBlock, stProc, stFile, true, sbNil, nil)) {

	if (v->sym->st == stProc) {
	    /* This may not be correct for PASCAL - 
	     * C Efficiency KLUDGE!
	     */
	    return(isymNil);
	} else if (v->sym->st == stEnd) {
	    if (v->sym->sc == scText)
		return(v->sym->index);	/* isym of matcing block */
	    continue;	/* non-text stuff is uninteresting */
	} else {
	    /* It is a BLOCK start.
	     * By definition, its entire contents are uninteresting.
	     */
	    SetNextSym(IsymNextFBlock(v->isym));
	} /* if */
	
    } /* while */
    return(isymNil);
} /* IsymFAdr */


/* S Y M   F   A D R  */

export pSYMR SymFAdr(adr, sb)
ADRT	adr;
SBT	sb;
{
    int4	isym;

    /* This routine uses 'adr' to establish a scope.
     * It then searches outward from that scope for a
     * variable whose name is *sb.
     */

    if (v->rgFd[IfdFAdr(adr)].lc == lcFortran)
	return((pSYMR)F_SymFAdr(adr, sb));

    isym = isymNil;
    while (true) {
	isym = IsymFAdr(adr, isym);	/* this finds our location in symbols */
	if (isym == isymNil)
	    break;	/* we ran out of scopes to look in */
	SymFIsym(isym);
	if (v->sym->st == stFile)
	    break;	/* we are beginning of file */

	while (true) {
	    if (FNextSym(stParam, stLocal, stStatic, stEnd, false, sb, FSbCmp))
		return(v->sym);
	    if ((v->sym == symNil) OR (v->sym->sc == scText))
		break;
	    /* this is an info block of some sort - continue */
	} /* while */

    } /* while */

    /* If we get here, sb was not the name of a Local, Param,
     * or local Static of any kind.
     */
    return(symNil);
} /* SymFAdr */


/* F   T Y P E   F   N A M E */

export FLAGT FTypeFName(seType, tk)
pSER	seType;
int2	tk;
{
    int2	ipd;
    SBT		sb;
    CNTXR	acntx;
    int4	isym, iss;
    
    iss = seType->asym.iss;;

    sb = SbFIss(iss);
    ipd = v->ipd;
    CntxFIpd(&acntx, &ipd, -1); /* get our start address */

    isym = isymNil;
    while (true) {
	isym = IsymFAdr(acntx.pc, isym);/* this finds our location in symbols */
	if (isym == isymNil)
	    break;	/* we ran out of scopes to look in */
	SetNextSym(isym+1); /* info starts 1 after block start */
	if (FNextSym(stTypedef, stBlock, stNil, stEnd, true, sb, FSbCmp))
	    goto Success;
    } /* while */

    /* not defined inside the current procedure, try the file */
    SetNextSym(v->rgFd[v->ifd].isym+1);
    if (FNextSym(stTypedef, stBlock, stNil, stFile, false, sb, FSbCmp))
	goto Success;

    if (! vfStrict) {
	/* try the entire symbol table */
	SetNextSym(1);
	if (FNextSym(stTypedef, stBlock, stNil, stNil, true, sb, FSbCmp))
	    goto Success;
    } /* if */

    return(false);	/* no luck */

Success:
    if (v->sym->st == stBlock) {
	/* then they were looking for a struct, union or enum */
	*seType = *vseInit;
	seType->asym.iss = iss;
	seType->isymRef = v->isym;
	switch (tk) {
	    default:		Panic("Unknown tk in FTypeFName: %d.", tk);
	    case tkStruct:	seType->ti.bt = btStruct;	break;
	    case tkUnion:	seType->ti.bt = btUnion;	break;
	    case tkEnum:	seType->ti.bt = btEnum;		break;
	} /* switch */
    } else {
	SeFSym(seType, v->sym, true);
    } /* if */
    return(true);
} /* FTypeFName */


/* F   E N U M */

export FLAGT FEnum(se)
pSER	se;
{
    int2	ipd;
    FLAGT	fDoLocalScope;
    SBT		sb;
    CNTXR	acntx;
    int4	isym, iss;
    
    iss = se->asym.iss;;
    sb = SbFIss(iss);
    ipd = v->ipd;

    if (v->pid == pidNil) {
	/* there is no process, look in current proc */
	acntx.pc = AdrFIpdIln(v->ipd, v->iln);
	fDoLocalScope = (acntx.pc == adrNil);
    } else {
	CntxFIpd(&acntx, &ipd, -1); /* get our start address */
	fDoLocalScope = ! acntx.fEndOfStack;
    } /* if */

    if (fDoLocalScope) {
	isym = isymNil;
	while (true) {
	    isym = IsymFAdr(acntx.pc, isym);/* find our location in symbols */
	    if (isym == isymNil)
		break;	/* we ran out of scopes to look in */
	    SetNextSym(isym+1); /* info starts 1 after block start */
	    while (FNextSym(stMember, stNil, stNil, stEnd, true, sb, FSbCmp)) {
		if (v->sym->index == 0)
		    goto Success;
	    } /* while */
	} /* while */
    } /* if */

    /* not defined inside the current procedure, try the file */
    SetNextSym(v->rgFd[v->ifd].isym+1);
    while (FNextSym(stMember, stNil, stNil, stFile, true, sb, FSbCmp)) {
	if (v->sym->index == 0)
	    goto Success;
    } /* while */

    return(false);	/* no luck */

Success:
    isym = v->isym;
    SeFSym(se, v->sym, true);
    se->val.valUInt = se->asym.value;
    se->ti.fConstant = true;
    se->ti.bt = btEnum;
    /* now we get the isym of the start by finding the end */
    SetNextSym(isym);
    FNextSym(stEnd, stNil, stNil, stNil, false, sbNil, nil);
    se->isymRef = v->sym->index; /* the end points back to the start */
    return(true);
} /* FEnum */


/* P A R A M   O F F S E T */

local int ParamOffset(pc)
ADRT	pc;
{
    SER		ase;
    /* this routine allows for procedures which return more than an INT */

    SeFSym(&ase, SymFIsym(v->rgPd[IpdFAdr(pc)].isym), true);
    if ((TqFSe(&ase, 1) == tqNil)
       AND ((ase.ti.bt == btUnion) OR (ase.ti.bt == btStruct))) {
	return(4);
    } else {
	return(0);
    } /* if */
} /* ParamOffset */


/* S E T   A D R */

export void SetAdr(se, cntx)
pSER	se;
pCNTXR	cntx;
{
    /* given an SE and and a properly set group of walking
     * variables in the 'v' record, make the address correct.
     */

    if (se->asym.sc == scRegister) {
	DoReg(se, cntx);	/* finds register values */
    } else if (se->asym.st == stParam) {
	se->asym.value += cntx->ap;
#if (STRUCT_RETURN_OFFSET)
	se->asym.value += ParamOffset(cntx->pc);
#endif /* (STRUCT_RETURN_OFFSET) */
	if ((v->os->fIntegerOffsets)
	   AND (v->cpu->byteSex == byteSexBig)
	   AND ((se->asym.value & (v->cpu->cbInt - 1)) == 0)) {
	    /* Args on the stack are NOT where they appear to be */
	    int cb = CbFSe(se);
	    if (cb < v->cpu->cbInt)
		se->asym.value += (v->cpu->cbInt - cb);
	} /* if */
    } else if (se->asym.st == stLocal) {
	se->asym.value += cntx->fp;
    } /* if */

    if (se->ti.tq0 == tqRef) {
	se->ti.tq0 = tqPtr;
	GetVal(se);
	se->asym.value = se->val.valAdr;
	RemoveTq(se);	/* get rid of qualifier*/
    } /* if */

    if ((se->ti.tq0 == tqArray) OR (se->ti.tq0 == tqProc))
	se->val.valAdr = se->asym.value;
} /* SetAdr */


/* F   L O C A L */

export FLAGT FLocal(se, ipd, cnt)
pSER	se;
int2	ipd, cnt;
{
    pSYMR	sym;
    SBT		sb = SbSafeFIss(se->asym.iss);
    FLAGT	fPhony = false;
    CNTXR	acntx;

    if ((v->pid == pidNil) AND (v->fnCore == fnNil)) {
	/* there is no process, look in current proc */
	fPhony = true;
	acntx.pc = AdrFIpdIln(v->ipd, v->iln);
	if (acntx.pc == adrNil)
	    UError("No symbolic information for current location.");
    } else {
	CntxFIpd(&acntx, &ipd, cnt);
	if (acntx.fEndOfStack)
	    return(false);
    } /* if */

    sym = SymFAdr(acntx.pc, sb);	/* find this variable, based on scope */
    if (sym == symNil)
	return(false);

    /* get all of the type goodies */
    SeFSym(se, sym, true);
    if (fPhony) {
	se->asym.value = adrNil;
    } else {
	SetAdr(se, &acntx);
    } /* if */
    return(true);
} /* FLocal */


/* F   G L O B A L */

export FLAGT FGlobal(se)
pSER	se;
{
    SBT		sb = SbSafeFIss(se->asym.iss);

    /* first we try statics in current file */

    if (v->ifd != ifdNil) {
	SetNextSym(v->rgFd[v->ifd].isym+1);
	if (FNextSym(stStatic, stNil, stNil, stFile, false, sb, FSbCmp)) {
	    SeFSym(se, v->sym, true);
	    return(true);
	} /* if */
    } /* if */

    /* no luck, try globals */
    SetNextSym(v->hdr.isymGl);
    if (FNextSym(stGlobal, stNil, stNil, stNil, false, sb, FSbCmp)) {
	SeFSym(se, v->sym, true);
	return(true);
    } /* if */
    return(false);
} /* FGlobal */


/* A D R   F   L A B E L */

export ADRT AdrFLabel(sbLabel)
SBT	sbLabel;
{
    int2	ipd = IpdFName(sbLabel);

    if (ipd != ipdNil)
	return(v->rgPd[ipd].adr);	/* it was in the proc table */

    /* look for a local label in the current file */
    if (v->ifd != ifdNil) {
	SetNextSym(v->rgFd[v->ifd].isym + 1);
	if (FNextSym(stLabel, stNil, stNil, stFile, true, sbLabel, FSbCmp))
	    return((ADRT)(v->sym->value));
    } /* if */
    return(adrNil);
} /* AdrFLabel */


/* C N T X   F   I P D */

export pCNTXR CntxFIpd(cntx, pipd, cnt)
pCNTXR	cntx;
int2	*pipd, cnt;
{
    int2	depth, ipdX, ipd = *pipd;
    FLAGT	fDontCare;

    if (fDontCare = (cnt == -1))
	cnt = 10000;

    depth = 0;
    *cntx = v->acntx;
    while (! cntx->fEndOfStack) {
	ipdX = IpdFAdr(cntx->pc);
	if (ipdX == ipd) {
	    if ((fDontCare) OR (cnt == depth))
		return;
	} /* if */
	if ((ipd == ipdNil) AND (cnt == depth)) {
	    *pipd= ipdX;
	    return;
	}
	if (cnt < depth)
	    UError("Procedure '%s' is not at that stack depth.", SbFIpd(ipd));
	depth++;
	NextFrame(cntx);
    } /* for */
} /* SetStackFIpd */


/* S B   F   R E G */

export SBT SbFReg(pc, reg)
ADRT	pc;
int	reg;
{
    int4	isym;

    /* This routine uses pc to establish a scope.
     * It then searches outward from that scope for a
     * register variable using the given regietr number.
     */

    if (v->rgPd[IpdFAdr(pc)].iline == 0)
	return(sbNil);	/* no symbols */

    isym = isymNil;
    while (true) {
	isym = IsymFAdr(pc, isym);	/* this finds our location in symbols */
	if (isym == isymNil)
	    break;	/* we ran out of scopes to look in */
	SetNextSym(isym+1); /* info starts 1 after block start */

	while (FNextSym(stParam, stLocal, stNil, stEnd, true, sbNil, nil)) {
	    if ((v->sym->sc == scRegister) AND (v->sym->value == reg))
		return(SbFIss(v->sym->iss));
	} /* while */
    } /* while */

    /* If we get here, sb was not a register thingiemabob */
    return(sbNil);
} /* SbFReg */


/* S B   F   S T A C K   O F F S E T */

export SBT SbFStackOffset(pc, fFp, offset)
ADRT	pc;
FLAGT	fFp;
int2	offset;
{
    int4	isym;

    /* This routine uses 'adr' to establish a scope.
     * It then searches outward from that scope for a
     * variable with the given stack offset.
     */

    isym = isymNil;
    while (true) {
	isym = IsymFAdr(pc, isym);	/* this finds our location in symbols */
	if (isym == isymNil)
	    break;	/* we ran out of scopes to look in */
	SetNextSym(isym+1); /* info starts 1 after block start */

	while (FNextSym(stParam, stLocal, stNil, stEnd, true, sbNil, nil)) {
	    if (v->sym->value == offset)
		return(SbFIss(v->sym->iss));
	} /* while */
    } /* while */

    /* If we get here, sb was not the offset of a Local or Param */
    return(sbNil);
} /* SbFStackOffset */


/* S B	 F   L A B E L	 A D R */

export SBT SbFLabelAdr(adr)
ADRT	adr;
{
    return(SbFNearest(adr, true, false, true));
} /* SbFLabelAdr */


/* S B	 F   N E A R E S T */

export SBT SbFNearest(adr, fText, fData, fProcOnly)
ADRT	adr;
FLAGT	fText, fData, fProcOnly;
{
    int2	ipd, ifd;
    SBT		sbT;
    ADRT	dadr;
    SYMR	asymNearest;
    static char sbLabel[100];

    /* given an address, find the NEAREST text OR data label to it.
     * return a formatted string containing the goodies.
     */

    asymNearest.iss = issNil;
    asymNearest.value = 0;

    ipd = ipdNil;
    if (fText) { 
	ipd = IpdFAdr(adr);
	asymNearest = * SymFIsym(v->rgPd[ipd].isym);

	if (!fProcOnly AND ((ifd = IfdFAdr(adr)) != ifdNil) ) {
	    /* check local text addresses for closer match */
	    SetNextSym(v->rgFd[ifd].isym + 1);
	    while (FNextSym(stLabel, stNil, stNil, stFile, true, sbNil, nil)) {
		if ((v->sym->value <= adr)
		   AND (v->sym->value >= asymNearest.value)) {
		    asymNearest = *(v->sym);
		} /* if */
	    } /* while */
	} /* if */
    } /* if */


    if ( fData				 /* they want us to check data labels */
       AND ( !fText			/* we didn't check text space */
	  OR !v->fPureText	/* text and data addresses might intermingle */
          OR (ipd == v->hdr.ipdMax-1)) ) {    /* we mapped to last procedure */
	/* check statics in this file */
	SetNextSym(v->rgFd[v->ifd].isym+1);
	while (FNextSym(stStatic, stLabel, stNil, stFile, true, sbNil, nil)) {
	    if ((v->sym->value <= adr)
	       AND (v->sym->value >= asymNearest.value)) {
		asymNearest = *(v->sym);
	    } /* if */
	} /* while */
	/* check global symbols */
	SetNextSym(v->hdr.isymGl);
	while (FNextSym(stGlobal, stNil, stNil, stNil, false, sbNil, nil)) {
	    if ((v->sym->value <= adr)
	       AND (v->sym->value >= asymNearest.value)) {
		asymNearest = *(v->sym);
	    } /* if */
	} /* while */
    } /* if */

    dadr = adr - asymNearest.value;
    sbT = SbFIss(asymNearest.iss);
    if (dadr == 0)
	sprintf(sbLabel, "%s", sbT);
    else if (dadr < vdadrMax)
	sprintf(sbLabel, "%s+%s", sbT, SbFAdr(dadr, true));
    else
	sprintf(sbLabel, "%s", SbFAdr(adr, true));
    return(sbLabel);
} /* SbFNearest */


/* D I S P   F R A M E */

export void DispFrame(cntx, cnt, fDoLocals, fList)
pCNTXR	cntx;
int2	cnt;
FLAGT	fDoLocals, fList;
{
    int2	ipd, ifd, iln, slop, i;
    int4	isym, isymStart;
    SER		aseTemp, ase, *se = &ase;

    /* First we set the cache for those going ovewr remote lines */

    ipd = IpdFAdr(cntx->pc);
    if (v->rgPd[ipd].iline == 0) {
	DispUnknown(cntx, ipd);
	return;
    } /* if */

    if (!fList)
	printf("%s(", SbFIpd(ipd));
    isymStart = isym = v->rgPd[ipd].isym + 1;
    i = 0;
    while (FNextLocal(false, true, isym)) {
	isym = v->isym + 1;
	SeFSym(se, v->sym, true);
	if (!fList AND i++)
	    printf(", ");
	SetAdr(se, cntx);
	if (!fList)
	    printf("%s=", SbFIss(se->asym.iss));
	DisplaySe(se, modeNil, fList, true, fList);
	if (fList) {
	    /* check to see if this is correct for current stop point */
	    aseTemp.asym.iss = se->asym.iss;
	    FLocal(&aseTemp, ipd, cnt);
	    if (aseTemp.asym.value != se->asym.value)
		printf("	*** Caution: variable is hidden or out of scope *** ");
	    printf("\n");
	} /* if */
    } /* while */

    if (!fList) {
	printf(")");
	if (v->cpu->fCalleeStackCleanup)
	    cntx->pc -= 1;
	ipd = IpdIlnFAdr(&iln, &slop, cntx->pc);
	ifd = IfdFAdr(cntx->pc);
	printf("	[%s:%d]\n", SbFIss(v->rgFd[ifd].iss), iln);
    } /* if */

    if (fDoLocals) {
	if (!fList)
	    vcNest++;	/* in case we have a structure to indent */
	if (v->rgFd[IfdFAdr(cntx->pc)].lc == lcFortran)
	    isym = isymStart;
	while (FNextLocal(true, false, isym)) {
	    isym = v->isym + 1;
	    SeFSym(se, v->sym, true);
	    if ( !fList
	       AND ((se->ti.tq0 != tqNil)
	          OR ((se->ti.bt != btStruct) AND (se->ti.bt != btUnion))) )
		printf("%s", "    ");
	    SetAdr(se, cntx);
	    DisplaySe(se, modeNil, true, true, true);
	    if (fList) {
		/* check to see if this is correct for current stop point */
		aseTemp.asym.iss = se->asym.iss;
		FLocal(&aseTemp, ipd, cnt);
		if (aseTemp.asym.value != se->asym.value)
		    printf("	*** Caution: variable is hidden or out of scope *** ");
	    } /* if */
	    printf("\n");
	} /* while */
	if (!fList)
	    vcNest--;
    } /* if */
} /* DispFrame */


/* S T A C K   T R A C E */

export void StackTrace(cnt, fDoLocals)
int2	cnt;
FLAGT	fDoLocals;
{
    int		i;
    ADRT	adrMin;
    CNTXR	acntx;

    if ((v->pid == pidNil) AND (v->fnCore == fnNil))
	UError("No process.");
    if (v->ps == psRunning)
	UError("Cannot do a stack trace on a running process.");

    MoreOn();

    acntx = v->acntx;
    adrMin = v->acntx.sp;
    for (i=0; ((i < cnt) AND (! acntx.fEndOfStack)); i++) {
	/* force the cache to the current frame */
	/* handles 95% of frames */
	SetCommCache(adrMin, Max((acntx.fp - adrMin) + 32, 128) );
	adrMin = acntx.fp; /* next loop's min value */

	if (cnt > 1)
	    printf("%2d ", i);
	DispFrame(&acntx, i, fDoLocals, false);
	if (NextFrame(&acntx) == true)
	    printf("----------- Command Line Procedure Call -----------\n");
    } /* for */
    MoreOff();
} /* StackTrace */


/* O P E N   S T A C K */

export void OpenStack(cnt)
int2	cnt;
{
    int2	cntIn = cnt;
    ADRT	adrMin;
    CNTXR	acntx;

    acntx = v->acntx;
    adrMin = v->acntx.sp;
    while (cnt-- AND (! acntx.fEndOfStack)) {
	adrMin = acntx.fp; /* next iteration's min stack value */
	NextFrame(&acntx);
    } /* while */

    if (acntx.fEndOfStack)
	UError("Stack isn't that deep!");

    if (v->cpu->fCalleeStackCleanup AND (cntIn != 0))
	acntx.pc -= 1;

    SetViewPosition(acntx.pc);
    ShowViewPosition(fmtFile+fmtProc+fmtLn+fmtLine+fmtEol);
    v->stackdepth = cntIn;

    /* force the cache to the current frame */
    SetCommCache(adrMin, (acntx.fp - adrMin) + 32); /* handles 95% of frames */
} /* OpenStack */


/* S T A C K   D E P T H */

export int StackDepth()
{
    int		cnt;
    CNTXR	acntx;

    cnt = 0;
    if (v->pid == pidNil)
	return(0);

    for (acntx = v->acntx; ! acntx.fEndOfStack; NextFrame(&acntx))
	cnt++;
    return(cnt);
} /* StackDepth */

0707070001000312371004440000000000010000011606350454650114000002000000027401cdb/waitMulti.c /* $Header: waitMulti.c,v 5.9 86/06/02 23:26:03 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

/* This module contains most of the code used for MULTI-PROCESS debugging.
 * This module is mutually exclusive with swait.c.
 */


#include "cdb.h"

#include <signal.h>

#if (OP_SYS == BSD42)
#include <sys/time.h>
#include <sys/wait.h>
#endif (OP_SYS == BSD42)

#if (OP_SYS == SYSV)
#include <fcntl.h>
#endif (OP_SYS == SYSV)

#include <errno.h>

export int2	viprMax = 100;	/* allow lots of room */


/* P P I D   F   P I D */

export PpidFPid(pid)
int	pid;
{
    int		ppid;

    ppid = Ptrace(ptPpid, pid, 0, 0);
    if (ppid == -1)
	UError("Attempting to find parent of %d: %s.", SbFError(errno));
    return(ppid);
} /* PpidFPid */


/* S B   E X E C   F   P I D */

export SBT SbExecFPid(pid)
int	pid;
{
    static char	sbCmd[257];

    Ptrace(ptCmdName, pid, sbCmd, 0);
    return(sbCmd);
} /* SbExecFPid */


/* F R E E   P R O C E S S */

export void FreeProcess(pr)
pPRR	pr;
{
    if (pr == prNil)
	return;

    SetGlobalPr(pr);

    RemoveAllBp(true);
    /* setpgrp(v->pid, v->pgrpSave); /* */
    Ptrace(ptReleaseChild, pr->pid, (char *) 1, 0);
    if (pr->pidParent != vpidCdb) {
	DeallocPr(pr, false);
    } else {
	pr->pid = pidNil;
	pr->ps = psNoChild;
    } /* if */

    SetGlobalPr(prNil);
} /* FreeProcess */


/* C O P Y   P R */

export void CopyPr(pr1, pr2)
pPRR	pr1, pr2;
{
    int2	cb;

    /* Make pr1 identical to pr2 */

    *pr1 = *pr2;	/* this gets all of the normal fields */

    /* KLUDGE - need to create CopyOs, CopyCpu */

    /* KLUDGE - need to check ALL fields and make our own copies
     * so that DeallocPr is free to throw everything away.
     */
    
    pr1->fForkedProcess = true;

    /* setup tables */
    cb = pr1->ibpMax * cbBPR;	/* breakpoints */
    pr1->rgBp = (pBPR) malloc(cb);
    MoveBytes(pr1->rgBp, pr2->rgBp, cb);

    cb = pr1->ilvMax * cbSER;	/* local variables */
    pr1->rgLv = (pSER) malloc(cb);
    MoveBytes(pr1->rgLv, pr2->rgLv, cb);

    cb = pr1->iadMax * cbADR;	/* assertions */
    pr1->rgAd = (pADR) malloc(cb);
    MoveBytes(pr1->rgAd, pr2->rgAd, cb);

    pr1->seDot = (pSER)malloc(cbSER);
    pr1->sbArgsChild = SbFAlloc(pr2->sbArgsChild);
} /* CopyPr */


/* P R   F O R K */

export pPRR PrFFork(pidChild, fAttached)
int2	pidChild;
FLAGT	fAttached;
{
    int		pidParent;
    SBT		sbExec;
    pPRR	pr, prParent;

    /* A new child has come into the world.
     * Register it with the draft board.
     */

    /* First we have to find out who the parent is */
    pidParent = PpidFPid(pidChild);
    prParent = PrFPid(pidParent);

    if (fAttached AND (prParent != prNil)) {
	/* We know the family, but the kid has been
	 * away from home for a long time.
	 * Check his id at the door */
	sbExec = SbExecFPid(pidChild);
	if (! FSbCmp(sbExec, prParent->sbExec))
	    prParent = prNil;
    } /* if */

    if (prParent == prNil) {

	/* A stranger in a strange land */
	pr = PrFInitPr( SbExecFPid(pidChild) );

    } else {

	/* A friend of the family */
	pr = PrFAlloc();
	CopyPr(pr, prParent);

	if (pr->fRemoveBpsOnFork) {
	    SetGlobalPr(pr);
	    RemoveAllBp(true);
	    SetGlobalPr(prNil);
	} /* if */

	pr->fnComm = pr->fnCdb = pr->fnExec = pr->fnCore = fnNil;

    } /* if */

    pr->pid = pidChild;
    pr->pidParent = pidParent;
    pr->ps = psFork;
    if (vfNotify) {
	printf("New process\n");
	ListPr(pr);
    } /* if */

    ++vcActive;		/* count of Active proceesses */
    return(pr);
} /* PrFFork */


/* P R   F   A T T A C H   P R O C E S S */

export pPRR PrFAttachProcess(pid)
int2	pid;
{
    int		ret;
    SBT		sb;
    pPRR	pr, prSave;

    ret = Ptrace(ptMultiChild, pid, 0, 0);	/* make him ours */
    if (ret == -1)
	UError("Unable to attach to process %d: %s.", pid, SbFError(errno));

    /* Chicken and Egg problem: We can't call Waiter, because we
     * don't have a process record because we don't have the process
     * name because we haven't waited on the process yet.
     * Sooooooo, we send SIGINT, wait a couple of seconds and
     * hope that the process has stopped.
     */
    kill(pid, SIGINT);
    sleep(2);

    pr = PrFFork(pid, true);
    pr->ps = psRunning;

    prSave = v;
    SetGlobalPr(pr);
    ReadPc();
    SetCntx();
    SetViewPosition(pr->acntx.pc);
    v->pgrpSave = getpgrp(pid);
    /* setpgrp(pid, getpgrp(0)); /* make him the same process group as us */
    return(pr);
} /* PrFAttachProcess */


/* P R   F   E X E C */

export pPRR PrFExec(pr)
pPRR	pr;
{
    extern char * gets();
    int2	pidParent, pidChild = pr->pid;
    char	*sbExec, sbBuf[200];
    FLAGT	fStopOnExec;		/* stop immediately after exec */
    FLAGT	fStopOnFork;		/* stop BOTH process after fork */
    FLAGT	fRemoveBpsOnFork;	/* child does NOT get parent's BPs */
    FLAGT	fDebugChildren;		/* indicates we WANT the kids */
    pSER	rgLv;
    FLAGT	fDoingSingle;
    
    pidParent = pr->pidParent;	/* Remember Mom */

    sbExec = SbExecFPid(pr->pid);	/* Find out who we are */
    if (sbExec == sbNil) {
	printf("Unable to determine name of program for process #%d\n",
	    pidChild);
	printf("Please type name of executable: ");
	sbExec = gets(sbBuf);
	if ((sbExec == sbNil) OR (*sbExec == chNull)) {
	    Ptrace(ptReleaseChild, pidChild, (char *) 1, 0);
	    UError("Aborting debugging of process #%d.", pidChild);
	} /* if */
    } /* if */

    fStopOnExec = pr->fStopOnExec;
    fStopOnFork = pr->fStopOnFork;
    fRemoveBpsOnFork = pr->fRemoveBpsOnFork;
    fDebugChildren = pr->fDebugChildren;
    fDoingSingle = pr->fDoingSingle;
    rgLv = pr->rgLv;

    DeallocPr(pr, true);		/* kill old identity */

#if 0
    pr = PrFAlloc();		/* a clean slate */
    pr->sbExec = SbFAlloc(sbExec);	/* our new name */
    pr->sbCore = sbNil;
    pr->isymCacheMax = 0;
    InitPr(pr);
#endif
    pr = PrFInitPr(sbExec);
    pr->pid = pidChild;
    pr->pidParent = pidParent;

    pr->fStopOnExec = fStopOnExec;
    pr->fStopOnFork = fStopOnFork;
    pr->fRemoveBpsOnFork = fRemoveBpsOnFork;
    pr->fDebugChildren = fDebugChildren;
    pr->fDoingSingle = fDoingSingle;
    pr->rgLv = rgLv;
    pr->ps = psRunning;

    SetGlobalPr(pr);
    ReadPc();
    SetCntx();
#if 0
    SetGlobalPr(prNil);
#endif 0

    if (vfNotify) {
	printf("Process exec'ed\n");
	ListPr(pr);
    } /* if */
    return(pr);
} /* PrFExec */

#ifdef BILLB
int DeadChild, InGetchar;

/*
	This routine catches the child died signal and sets a flag to 
	that effect. If there is potential that the process is about
	to enter getchar after checking the DeadChild flag then an alarm 
	is started to prevent the hang.
*/
CatchChildSig()
{
	signal(SIGCLD,CatchChildSig);
	DeadChild++;
	if (InGetchar) alarm(1);
}
#endif BILLB



/* N O   H A N G   G E T S */
export SBT NoHangGets(sb, fRedoPrompt, fHang)
SBT	sb;
FLAGT	fRedoPrompt, fHang;
{
#if (OP_SYS == SYSV)
    int		ch;
    SBT		sbTemp;

    /* this routine ASSUMES that we already have O_NDELAY set */

    if (fHang) {
#ifndef BILLB
	if (fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY) == -1)
	    SysPanic("fcntl on ~O_NDELAY");
	sleep(1); /* to disturb the ether and make O_NDELAY go away */
#endif BILLB
	if (fRedoPrompt)
	    printf("\n%s", vsbPrompt);
	return(gets(sb));
    } else {
#ifdef BILLB
	/* check for a dead child already occuring */
	InGetchar++;
	if (DeadChild) {
		InGetchar = 0;
		alarm(0);
		return((SBT)-1);
	}
#endif BILLB

	/* wait for the first character */
	sbTemp = sb;
	ch = getchar();

#ifdef BILLB
	/* char retrieved or child died */
	InGetchar = 0;
	alarm(0);
#endif BILLB

	if (ch != EOF) {

	    /* There is something there.  Let them type in peace */
#ifdef BILLB
	    signal(SIGCLD,SIG_DFL);
#else
	    if (fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY) == -1)
		SysPanic("fcntl clearing O_NDELAY");
#endif BILLB

	    while ((*sb++ = ch) != '\n')
		ch = getchar();

	    sb[-1] = 0;	/* step on ending <cr> */

#ifdef BILLB
	    signal(SIGCLD,CatchChildSig);
#else
	    if (fcntl(0, F_SETFL, O_NDELAY | fcntl(0, F_GETFL, 0)) == -1)
		SysPanic("fcntl setting O_NDELAY");
#endif BILLB
	    return(sbTemp);

	} /* if */
	return((SBT)-1);
    } /* if */
#else
    int		nfd, readfd, writefd, exceptfd;
    struct timeval	atimeval, *ptimeval;

    nfd = 1;		/* used for the select call */
    writefd = 0;
    exceptfd = 0;
    atimeval.tv_sec = 0;
    ptimeval = &atimeval;

    readfd = 1;
    if (!fHang) {
	ptimeval->tv_usec = 500000;	/* 1/2 second */
    } else {
	ptimeval = 0;	/* we wait forever */
	if (fRedoPrompt)
	    printf("\n%s", vsbPrompt);
    } /* if */

    fflush(stdout);
    if (0 != select(nfd, &readfd, &writefd, &exceptfd, ptimeval))
	return(gets(sb));
    return((SBT)-1);	/* says we didn't see anything before timeout */
#endif /* (OP_SYS == SYSV) */
} /* NoHangGets */


/* N O   H A N G   W A I T */

export int NoHangWait(pstatus)
int	*pstatus;
{
#if (OP_SYS == SYSV)
    int		ret;

    alarm(1);
    ret = wait(pstatus);
#ifdef BILLB
    if ((ret == -1) AND (errno == EINTR)) {
	DeadChild = 0;	/* not cleared until we are sure no signals lost */
	return(0);	/* timed out */
    }
#else
    if ((ret == -1) AND (errno == EINTR))
	return(0);	/* timed out */
#endif BILLB
    return(ret);
#else
    return( wait3(pstatus, WNOHANG, nil) );
#endif /* (OP_SYS == SYSV) */
} /* NoHangWait */


/* W A I T E R */

export long Waiter(wt, pidWait)
int2	wt, pidWait;
{
    int		pid, ppid, waitReturn, status;
    FLAGT	fRunningChildren, fRedoPrompt;
    pPRR	pr, prSave = v;

    /* Wait for something to happen in a
     * MULTIPLE PROCESS environment
     */

    vfUseCache = false;	/* just in case they turned it on */
    fRedoPrompt = false;
    fRunningChildren = true;	/* assume we do until we fail on wait3 */

#if (OP_SYS == SYSV)
#ifndef BILLB
    if (fcntl(0, F_SETFL, O_NDELAY | fcntl(0, F_GETFL, 0)) == -1)
	SysPanic("fcntl on O_NDELAY");
#endif BILLB
#endif (OP_SYS == SYSV)

    while (1) {
	if (wt == wtTty) {
	    /* there are no children we need to deal with */
	    /* See if we should get something from the terminal */
	    if ((SBT)-1 != NoHangGets(vsbGet, fRedoPrompt, !fRunningChildren))
		break;
	    /* a negative return indicates no command line yet */
	} /* if */

	waitReturn = 0;
	if (fRunningChildren) {
	    if (vcActive <= 1)
		signal(SIGINT, SIG_IGN);	/* ignore INT */

	    waitReturn = NoHangWait(&status);

	    if (vcActive <= 1)
		signal(SIGINT, Fixer);	/* reconnect to the Fixer routine */
	    if (waitReturn == -1) {

		if (errno == ECHILD) {
		    /* it's no crime not to have children.... */
		    fRunningChildren = false;
		    waitReturn = 0;
		} else if (errno == EINTR) {
		    printf("PANIC! received signal: %d (%s).\n",
			status>>8, SbFSignal(status>>8));
		    /* what do we do here?? */
		    exit(1);
		} else {	/* some sort of error occurred */
		    perror(vsbDebugName);
		    exit(1);
		} /* if */
	    } /* if */
	} /* if */
	
	if (waitReturn > 0) {
	    pid = waitReturn;
	    pr = PrFPid(pid);
	    if (pr == prNil) {
		/* We weren't expecting this guy.
		 * The highest probability is that he
		 * is the result of a fork.  
		 */

		pr = PrFFork(pid, false);
		if (pr == prNil) {
		    /* PrFFork didn't like him */
		    /* What should we do here? Kill him? */
		    continue;
		} /* if */
	    } /* if */

	    if (pr->ps == psStopped)
		continue;

	    SetGlobalPr(pr);	/* make him the boss */

	    if (v->fStty)
		SetMyTty();
	    v->status = status;

	    AnalyzeStop();
	    fRedoPrompt = true;
	    fRunningChildren = true;	/* as a default */

	    if (v->ps == psContinue) {
		/* He's not supposed to stop yet, onward! */
		RunProcess(ptResume, psRunning, false);
		continue;
	    } /* if */

	    if ((wt == wtProcess) AND (pid == pidWait)) {
		break;	/* we were waiting for this guy */
	    } else if (vfNotify AND (vcActive > 1)) {
		pr = PrFPid(pid);
		if (pr != prNil) {
		    printf("Process stopped:\n");
		    ListPr(pr);
		} /* if */
	    } /* if */
	} /* if */
    } /* while */

    SetGlobalPr(prSave);
} /* Waiter */
0707070001000312401004440000000000010000011607700454650114000001600000033650cdb/xremote.c /* $Header */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This module is the REMOTE end of the CDB Standard Remote Debugging package.
 * It is set up to run as a normal UNIX user process.  To modify it for
 * use in other environments, simply implement the functionality without
 * changing the interface.  A full description of the protocol may be
 * found in the file "xptrace.h".
 */

#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include "xptrace.h"

#define O_RDONLY	0
#define chNull '\0'
typedef char *SBT;
#define sbNil ((SBT)0)
#define true 1
#define false 0
#define AND &&
#define OR ||

extern int errno;
extern void SendStatus();

#define DEBUG 1

#if DEBUG
#define dprint(x, y) {if (x <= vlevel) fprintf y; fflush(stderr);}
#else
#define dprint(x, y)
#endif

int	vpidChild = 0;	/* KLUDGE - this limits us to one sub-process */
int	vfCommDebug;	/* if true, causes echoing of all messages */
int	vlevel = 0;		/* debug print level for dprint */
FILE	*vfpTx, *vfpRx;	/* they may be the same in some cases */


#define cArgsMax	100	/* max number of args to child */
#define cbBufMax 1024	/* pick a number suited to the size of your system */
char	vsbBuf[cbBufMax];	/* buffer where we format messages */
SBT	vsbTx = vsbBuf;


#if 1
/* Change this to "if 0" when this is a subroutine of another program */
extern FILE *fdopen();


/* M A I N */

void main(argc, argv)
int	argc;
char	**argv;
{
    int		i, fUsedArg, cMainArgs;
    SBT		sbArg, sbTemp, sbUsage, sbTx, sbRx, sbTty;

    sbUsage = "Usage: cdbremote [-d#] [device-name]";

    sbTx = sbRx = sbNil;

    cMainArgs = 0;
    for (i=1; i<argc; ++i) {
	if (*(sbArg=argv[i]) != '-') {
	    if (cMainArgs == 0) {
		sbTty = sbArg;
	    } else {
		printf(sbUsage);
		exit(1);
	    } /* if */
	    cMainArgs++;
	} else {
	    sbArg++;	/* move past the '-' */

	    /* point to a potential argument */
	    sbTemp = (sbArg[1] != chNull) ? sbArg+1 : argv[i+1];
	    fUsedArg = true; /* set FALSE if option does NOT use arg */

	    switch (*sbArg) {
		default:
		    printf(sbUsage);
		    exit(1);
		    break;

		case 'T':
		    sbTx = sbTemp;
		    break;

		case 'R':
		    sbRx = sbTemp;
		    break;

		case 'd':
		    vlevel = atoi(sbTemp);
		    vfCommDebug = true;
		    break;

	    } /* switch */

	    if ((fUsedArg) AND (sbArg[1] == chNull))
		i++;	/* eat next word - it was the arg we used */
	} /* if */
    } /* for */

    if (sbTty != sbNil) {
	dprint(1, (stderr, "Opening %s for READ and WRITE\n", sbTty));
	vfpTx = fopen(sbTty, "r+");
	if (vfpTx == NULL) {
	    perror(sbTty);
	    exit(1);
	} /* if */
	vfpRx = vfpTx;
    } else {
	if (sbTx != sbNil) {
	    dprint(1, (stderr, "Using channel %s for WRITE\n", sbTx));
	    vfpTx = fdopen(atoi(sbTx), "w");
	    if (vfpTx == NULL) {
		perror(sbTx);
		exit(1);
	    } /* if */
	} else {
	    dprint(1, (stderr, "Using stdout for WRITE\n", sbTx));
	    vfpTx = stdout;
	} /* if */

	if (sbRx != sbNil) {
	    dprint(1, (stderr, "Using channel %s for READ\n", sbRx));
	    vfpRx = fdopen(atoi(sbRx), "r");
	    if (vfpTx == NULL) {
		perror(sbRx);
		exit(1);
	    } /* if */
	} else {
	    dprint(1, (stderr, "Using stdin for READ\n", sbTx));
	    vfpRx = stdin;
	} /* if */
    } /* if */

    DebugServer(vfpTx, vfpRx);
} /* main */
#endif


/* T X   S T R I N G */

int TxString(sb)
SBT	sb;
{
    dprint(1, (stderr, "TxRemote: %s", sb));

    fputs(sb, vfpTx);
    fflush(vfpTx);
} /* TxString */


/* R X   S B */

void RxSb(sb)
SBT	sb;
{
    SBT		sbRet;

    sbRet = fgets(sb, 200, vfpRx);
    if (sbRet == NULL) {
	/* the line went away */
	dprint(1, (stderr, "Comm line closed\n"));
	exit(1);
    } /* if */

    dprint(1,(stderr, "RxRemote:%s", sb));
} /* RxSb */


/* C D B   P A N I C */

int RemotePanic(sbFmt, arg1, arg2, arg3)
SBT	sbFmt;
int	arg1, arg2, arg3;
{
    fprintf(stderr, "Remote Panic - ");
    fprintf(stderr, sbFmt, arg1, arg2, arg3);
    fprintf(stderr, "\n");
    fflush(stderr);
} /* RemotePanic */


/* V A L   F   P S B   */

long ValFPsb(psb)
SBT	*psb;
{
    int		x = 0;
    char	ch, *sb = *psb;

    /* this routine eats a hex number from a string and advances
     * the string pointer to the next character AFTER the first
     * non-hex character.  E.g if we start with "1234|abcd",
     * we will return the integer value 0x1234 and leave the string
     * pointing to the 'a'.
     */

#define FHex(ch) (((ch >='0') AND (ch <= '9')) OR ((ch >= 'a') AND (ch <= 'f')))

    if ((sb == sbNil) OR (*sb == chNull))
	return(0);

    while (true) {
	ch = *sb++;
	if (! FHex(ch))
	    break;
	x = (x * 16) + ((ch <= '9') ? (ch - '0') : ((ch - 'a') + 10));
    } /* while */
    *psb = sb;
    return(x);
} /* ValFPsb */


/* R E A D   H E X   B Y T E S */

void ReadHexBytes(pid, adr, count, sb)
int	pid, count;
long	adr;
SBT	sb;
{
    char	ch1, ch2, *sbDest;
    short	val;

    /* used with the host-to-remote block transfer command */
    sbDest = (SBT) adr;
    while (count--) {
	ch1 = *sb++;
	ch2 = *sb++;
	val = ((ch1 - ((ch1 > '9') ? ('a'-10) : '0')) << 4)
	       + (ch2 - ((ch2 > '9') ? ('a'-10) : '0'));
	*sbDest++ = val;
    } /* while */
} /* ReadHexBytes */


/* W R I T E   H E X   B Y T E S */

void WriteHexBytes(pid, adr, count)
int	pid, count;
long	adr;
{
    SBT		sbTx, sbSrc;
    short	val;

    /* used with the remote-to-host block transfer command */

    sbSrc = (char *) adr;
    sbTx = vsbTx;
    sprintf(sbTx, "%x|%x|%x|", statusOk, pid, count);
    sbTx = sbTx + strlen(sbTx);
    while (count--) {
	val = (*sbSrc & 0xf0) >> 4;
	*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
	val = *sbSrc++ & 0x0f;
	*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
    } /* while */
    *sbTx = '\n';
    TxString(sbTx);
} /* WriteHexBytes */


/* L O C A L   P T R A C E */

void LocalPtrace(pt, pid, adr, value)
int	pt, pid, value;
long	adr;
{
    int		status;
    
    /* This routine does whatever is necessary to implement
     * the ptrace(2) system call.
     *
     * For UNIX systems, this means we just call ptrace itself.
     */

    /* On a majority of systems, Instruction and Data Space
     * are identical.  On systems where this is not true, you
     * will need to deal with them separatly.
     */

    dprint(10, (stderr, "pt: %d  adr: %x  value: %d\n", pt, adr, value));

    errno = 0;
    switch (pt) {
	default:	RemotePanic("Unknown ptrace request: %d.", pt);	break;

	case  ptReadI:
	case  ptReadD:
		/* Read memory */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptWriteI:
	case  ptWriteD:
		/* Write memory */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptReadUser:
		/* Read Registers */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptWriteUser:
		/* Write Registers */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptSingle:
		/* Single Step the child */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptResume:
		/* Continue an existing child */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptTerm:
		/* Terminate an existing child */
		value = ptrace(pt, pid, adr, value);
		vpidChild = 0;
		break;
    } /* switch */

    status = ((value == -1 ) AND (errno != EIO)) ? statusOk : errno;
    SendStatus(status, pid, value);
} /* LocalPtrace */


/* L O C A L    W A I T */

int LocalWait(pstatus)
int	*pstatus;
{
    /* This routine does whatever is necessary to implement
     * the wait(2) system call.
     *
     * For UNIX systems, this means we just call wait itself.
     */

    return(wait(pstatus));
} /* LocalWait */


/* S E N D   S T A T U S */

void SendStatus(status, pid, value)
int	status, pid, value;
{
    sprintf(vsbTx, "%x|%x|%x\n", status, pid, value);
    TxString(vsbTx);
} /* SendStatus */


/* N E X T   A R G */

char * NextArg(psbIn)
SBT	*psbIn;
{
    SBT		sbRet;

    /* skip white space */
    while (**psbIn == ' ' OR **psbIn == '\t')
	(*psbIn)++;

    if (**psbIn == chNull)
	return(sbNil);	/* that's all, folks! */

    sbRet = *psbIn;	/* set current arg pointer */
    while (**psbIn != chNull
       AND **psbIn != ' '
       AND **psbIn != '\t')
	(*psbIn)++;	/* skip all non-white space characters */

    **psbIn = chNull;	/* overwrite the tab, space, or 0 with a 0 */
    (*psbIn)++;
    return(sbRet);
} /* NextArg */


/* D O	 A R G S */

void DoArgs(sbProgram, sbArgs, argv, fReassign)
SBT	sbProgram, sbArgs;
char	**argv;
int	fReassign;
{
    int		i;
    SBT		sbFile, sbArgCur;
    char	sbBuffer[1024];

    for (i=0; i < cArgsMax; i++)
	argv[i] = sbNil;

    *argv++ = sbProgram; /* set the filename */

    if (sbArgs == sbNil)
	return;

    strcpy(sbBuffer, sbArgs);	/* copy it to a safe place to hack on it */
    sbArgs = sbBuffer;
    sbArgs[strlen(sbArgs)+1] = chNull; /* this puts a SECOND null at end */

    /* eat the arguments */
    while ((sbArgs != sbNil)
       AND (*sbArgs != chNull)) {
	sbArgCur = NextArg(&sbArgs);
	if (sbArgCur == sbNil)
	    break;

	/* check for indirection */
	if (!fReassign
	   OR ((*sbArgCur != '<') AND (*sbArgCur != '>')) ) {
	    *argv++ = sbArgCur;	/* we just pass it on */
	} else {
	    /* find that file name */
	    sbFile = sbArgCur + 1;  /* initially we assume `<foo' vs `< foo' */
	    if (*sbFile == chNull) {
		/* there was white space between < and sbFile */
		sbFile = NextArg(&sbArgs);
		if (sbFile == sbNil) {
		    printf("Illegal indirection\n");
		    exit(1);
		} /* if */
	    } /* if */

	    if (*sbArgCur == '<') {
		/* changing stdin */
		close(0);
		if (open(sbFile, O_RDONLY) < 0) {
		    perror(sbFile);
		    exit(1);
		} /* if */
	    } else if (*sbArgCur == '>') {
		/* changing stdout */
		close(1);
		if ( (open(sbFile, 2) < 0) 	/* O_WRONLY */
		   AND (creat(sbFile, 0666) < 0) ) {
		    perror(sbFile);
		    exit(1);
		} /* if */
	    } /* if */
	} /* if */
    } /* while */
    *argv = sbNil;
} /* DoArgs */


/* P I D   F   E X E C   C H I L D */

int PidFExecChild(sbExec, sbArgs)
SBT	sbExec, sbArgs;
{
    int		pid, fn, sig;
    char	*argvChild[cArgsMax];

    /* Parse the argument list passed into an argv array.
     * Create a child process, initialize it to a more or less virgin state,
     * (i.e. clean up the signals, close the files,....) and return the pid
     * to the caller.
     */

    if ((pid = fork()) == 0) {
	/* we are the CHILD process */

	for (sig=1; sig<NSIG; sig++)
	    signal(sig, SIG_DFL);	/* start out with default response */

	for (fn = 3; fn < _NFILE; fn++)
	    close(fn);

	DoArgs(sbExec, sbArgs, argvChild, true);
	ptrace(ptChild, 0, (char *)0, 0); /* Hi, Mom! */
	execv(sbExec, argvChild);

	/* if we get here, we are child BUT exec failed */
	perror(sbExec);
	RemotePanic("Exec failed.");
	exit(1);
    } /* if */

    if (pid == -1) {
	perror(sbExec);
	RemotePanic("Fork failed.");
    } /* if */

    return(pid);
} /* PidFExecChild */


/* D E B U G   S E R V E R */

int DebugServer(fpTx, fpRx)
FILE	*fpTx, *fpRx;
{
    int		pid, result, status, msg, pt, value, count;
    int		sig, sigExit = 0;
    long	adr, adr2;
    char	*sb, sbBuf[cbBufMax], sbName[cbBufMax], sbArgs[cbBufMax];

    /* This routine is the main command loop.
     * It acts as the Parent process to the target process.
     */

    dprint(1, (stderr, "Entering debug server\n"));

#ifdef unix
    signal(SIGINT, SIG_IGN);
#endif

    vfpRx = fpRx;
    vfpTx = fpTx;

    /* startup wait */
    result = LocalWait(&value);

    while (true) {
	RxSb(sbBuf);	/* get a message from the host */
	sb = sbBuf;
	msg = ValFPsb(&sb);	/* get message number */
	pid = ValFPsb(&sb);	/* get process id */
	dprint(1, (stderr, "msg = %d, pid = %d\n", msg, pid));

	status = statusOk;	/* to start with */

	switch (msg) {
	    default:
		SendStatus(statusRetry, pid, 0);
		break;

	    case msgPtrace:
		pt = ValFPsb(&sb);
		adr = ValFPsb(&sb);
		value = ValFPsb(&sb);

		LocalPtrace(pt, pid, adr, value);
		break;

	    case msgWait:
		result = LocalWait(&value);
		sigExit = (value >> 8) & 0xff;
		SendStatus(statusOk, pid, value);
		break;

	    case msgQuit:
		if (pid == 0) {
		    sprintf(vsbTx, "%x|%x\n", statusOk, pid);
		    TxString(vsbTx);
		    return;	/* all done */
		} /* if */
		LocalPtrace(ptTerm, pid, (char *)0, 0);
		break;


	    case msgExec:
		if (vpidChild != 0) {
		    /* KLUDGE - if you need more than one at a time,
		     * this will not work correctly.
		     */
		    LocalPtrace(ptTerm, vpidChild, (char *)0, 0);
		    vpidChild = 0;
		} /* if */

		/* the pid returned should either be that specified by the host
		 * OR one determined by the local environment.
		 */
		
		/* sb now points at "program|args" */

		sscanf(sb, "%[^|]|%[^|]", sbName, sbArgs);
		sbArgs[strlen(sbArgs)-1] = '\0'; /* clear the <nl> */
		dprint(1, (stderr, "Execing: %s, args:%s\n", sbName, sbArgs));

		vpidChild = PidFExecChild(sbName, sbArgs);
		if (pid != vpidChild) {
		    pid = vpidChild;
		    status = statusNewPid;
		} /* if */

		/* If we send a value of 0, it means that parent MUST send
		 * us msgWait.  A value of -1 says that it* must NOT send
		 * us the wait message.  What you send is based on how
		 * your PidFExecChild works.  The UNIX version needs the wait.
		 */
		SendStatus(status, pid, 0);
		break;

	    case msgInput:
		/* KLUDGE - this should be fed to the program, somehow */
		dprint(1, ("KLUDGE - inputing: %s", sb));
		SendStatus(statusOk, pid, 0);
		break;

	    case msgHtoR:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		ReadHexBytes(pid, adr, count, sb);
		SendStatus(statusOk, pid, 0);
		break;

	    case msgRtoH:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		WriteHexBytes(pid, adr, count);
		break;

	    case msgMove:
		adr = ValFPsb(&sb);
		adr2 = ValFPsb(&sb);
		count = ValFPsb(&sb);
		/* MoveBlock((char *)adr, (char *)adr2, count); */
		SendStatus(status, pid, 0);
		break;

	    case msgSignal:
		sig = ValFPsb(&sb);
		kill(pid, sig);
		SendStatus(statusOk, pid, 0);
		break;

	    case msgLevel:
		vlevel = ValFPsb(&sb);
		SendStatus(statusOk, pid, 0);
		break;

	    case msgDump:
		/* Fill in with any appropriate goodies */
		/* starting here ---->v			*/
		sprintf(vsbTx, "%x|%x|RemoteStat pc:%x fp:%x sp:%x\n",
		    statusPrint, pid, 0, 0, 0);
		TxString(vsbTx);
		SendStatus(statusOk, pid, 0);
	} /* switch */
    } /* while */
} /* DebugServer */
0707070001000312411004440000000000010000011611410454650114000001200000000675cdb/SYS.h /* This file is automatically created by config */
#define SYS_NAME "Plexus running System V.2"
#define	SYS	P60V
#define	CPU	M68000
#define	OP_SYS	SYSV
#define	MFG	PLEXUS
#define	m68	1
#define BPT_INST	0x4e420000	/* trap 2 */
#define ADR_START	0x3c
#define cbCodeOffset	2048
#define cbStorageMax	0x7ff000
#define NO_UNDERLINES	0
#define PERCENT_SIGNS	1
#define BPT_BACKUP	1
#define LANG_C 1
#define LANG_C 1
#define ALSO_EQUAL	1
#define MULTI	1
0707070001000312421004440000000000010000011605210454650114000001200000037356cdb/cdb.h /* $Header: cdb.h,v 6.2 86/09/01 17:20:08 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <stdio.h>

#define int1	char
#define uint1	unsigned char
#define int2	short
#define uint2	unsigned short
#define int4	long
#define uint4	unsigned long

#include "config.h"

extern char *malloc();
extern free();
extern long lseek();
extern int errno;
extern char *strchr(), *strrchr(), *strcpy(), *strncpy(), *strcat(), *strncat();
extern int strlen(), strspn();
extern long time();
extern char *getenv();

/* random stuff */
#define false 0
#define true  1

#define bits unsigned	/* makes bit fields definitions shorter */
#define FAST register

#define NAR	10000	/* Not A Register */

#define export		/* something that belongs in ext.h  */
#define exportdefine
#define local static	/* something not to be known outside of this module */

#define NOT(x)	(!(x))
#define AND &&
#define OR  ||

#define seekBegin	0	/* these are used with lseek() and fseek() */
#define seekRelative	1
#define seekEnd		2

typedef char *SBT;
#define sbNil ((SBT)0)
#define chNull '\0'
#define nil ((char *)0)	/* good for where a general nil pointer is needed */
#define FLAGT uint2
typedef uint4	ADRT, *pADRT;
#define	adrNil ((ADRT) 0xffffffff)

/* and now  - The Symbol Table! - Ta Da! */
#include "sym.h"

/* define token type */
typedef uint2 TKE, *pTKE;
extern TKE	vtk;
extern TKE	TkNext();

#define cbSbBpMax 100	/* max length of BP commands */

typedef struct BPS {    /* breakpoint */
	ADRT	adr;		/* address of breakpoint */
	uint4 	inst;		/* instruction that lives there */
	int2	ifd;		/* file this maps to, if any */
	int2	iln;		/* line, if any */
	int2	count;		/* number of times to hit before stop */
	int2	countInit;	/* re-initialize main count */
	char	sbBp[cbSbBpMax];	/* commands for bp */
	} BPR, *pBPR;
#define cbBPR sizeof(BPR)
#define bpNil ((pBPR)0)
#define ibpNil  -1

/* break point codes */
#define bpcNil		0
#define bpcBegin	1
#define bpcEnd		2
#define bpcUp		3
#define bpcProc		4

/* assertion states */
#define asNil	   	0       /* assertions are not being used */
#define asActive	1       /* assertions ARE being used */
#define asSuspended     2       /* being used, but temporarily suspended */
typedef int ASE, *pASE;

typedef struct {	/* the assertion descriptor */
	SBT	sbCheck;	/* points to command list for this check */
	ASE	as;		/* state of THIS assertion check */
	} ADR, *pADR;
#define cbADR sizeof(ADR)


/*
 * Multivalued union used in expression
 * evaluator for all types
 */
/* This does NOT want to be defined on our int1, int2, etc.! */
typedef union {
	char	valChar;
	unsigned char	valUChar;
	short	valShort;
	unsigned short	valUShort;
	int	valInt;
	unsigned int	valUInt;
	long	valLong;
	unsigned long	valULong;
	float	valFloat;
	double	valDouble;
	ADRT	valAdr;
	int	*valPtr;
#ifdef LONGLONG
	long long		valLongLong;
	unsigned long long	valULongLong;
#endif /* LONGLONG */
	char	*sbName;
	struct {
		float	valReal;
		float	valImaginary;
		} valComplex;
	} VALU, *pVALU;
#define cbVALU sizeof(VALU)

typedef struct {	/* run-time Stack Element record */
	SYMR	asym;		/* copy of original symbol */
	TIR	ti;		/* type info */
	int4	isymRef;	/* -> to base type if struct/union/enum/etc */
	int4	isymTypedef;	/* typedef location, if used */
	VALU	val;		/* current value of this thing */
	int2	bitsWidth;	/* bit field width */	
	int4	bitsOffset;	/* bit field offset from start of struct */
	RNGR	rgRng[idimMax];	/* dimensions are actually subranges */
	} SER, *pSER;
#define seNil ((pSER)0)
#define cbSER sizeof(SER)

#define chLCB	'{'
#define chRCB	'}'
#define FUpper(ch) (((ch) >= 'A') AND ((ch) <= 'Z'))

/* display format */
#define dfNil		0
#define dfDecimal       1
#define dfUnsigned      2
#define dfOctal		3
#define dfHex		4
#define dfFFloat	5
#define dfEFloat	6
#define dfGFloat	7
#define dfChar		8
#define dfByte		9
#define dfPStr		10
#define dfStr		11
#define dfProc		12
#define dfAdr		13
#define dfStruct	14
#define dfType		15
#define dfEnum		16
#define dfProcLine	17
#define dfInstruction	18
#define dfCompiler	19
#define dfStandard	20
#define	dfBoolean	21
#define	dfComplex	22
#define dfCommon	23
#define dfBinary	24
typedef int     DFE, *pDFE;

typedef struct MODES {  /* used for passing around output format info */
	DFE	df;	/* display format */
	int2	len;	/* length of item (if meaningful) */
	int2	cnt;	/* number of times to apply the format */
	int2	imap;	/* selects map set to use (normally 0) */
	} MODER, *pMODER;
#define cbMODER sizeof(MODER)
#define modeNil ((pMODER)0)

typedef struct MAPS {
	ADRT    b1;
	ADRT    e1;
	ADRT    f1;
	ADRT    b2;
	ADRT    e2;
	ADRT    f2;
	} MAPR, *pMAPR;
#define fnNil -1

/* format control for PrintPos */
#define fmtNil		0       /* we don't want nothin' printed */
#define fmtFile		0x01    /* print the file name */
#define fmtProc		0x02    /* print the procedure name */
#define fmtLn		0x04    /* print the line number */
#define fmtLine 	0x08    /* print the current line */
#define fmtEol		0x10    /* print an end-of-line */
#define fmtInst		0x40	/* print instruction */
#define fmtSrcLineOnly	0x80

/* command types */
#define cmdNil	  	0
#define cmdPrint	1       /* print lines */
#define cmdDisplay      2       /* display the contents of a variable */
#define cmdUpArrow      3       /* display contents of previous location */
#define cmdLineSingle	4       /* statement step */
#define cmdMachSingle	5       /* instruction step */
#define cmdLineProc	6       /* statement step - DON'T follow proc calls */
#define cmdMachProc	7       /* inst. step - DON'T follow proc calls */
typedef int CMDE, *pCMDE;

typedef struct {	/* signal action record */
	bits	fStop : 1;	/* if true, stop on signal */
	bits	fReport : 1;	/* if true, report signal */
	bits	fIgnore : 1;	/* if true, ignore signal */
	char	sbSa[cbSbBpMax]; /* commands for signal */
	} SAR, *pSAR;
#define cbSAR (sizeof(SAR))
#define saNil ((pSAR)0)

/* these are internal names for registers, REAL offsets are in vrgReg */
#define 	u0	0
#define 	u1	1
#define 	u2	2
#define 	u3	3
#define 	u4	4
#define 	u5	5
#define 	u6	6
#define 	u7	7
#define 	u8	8
#define 	u9	9
#define 	u10	10
#define 	u11	11
#define 	u12	12
#define 	u13	13
#define 	u14	14
#define 	u15	15
#define		uregMax 21


/* address spaces for looking at child */
#define spaceText 1
#define spaceData 2

#define pidNil 0

/* requests for `access' */
#define accRead	 	0
#define accWrite	1

/* requests for `ptrace' system call */
#define ptChild	 	0
#define ptReadI	 	1
#define ptReadD	 	2
#define ptReadUser      3
#define ptWriteI	4
#define ptWriteD	5
#define ptWriteUser     6
#define ptResume	7
#define ptTerm	  	8
#define ptSingle	9

/* the following are NEW ptrace requests add for multiprocess work */
#define ptMultiChild	10	/* we own you and your firstborn */
#define ptReleaseChild	11	/* go `way ya bother me, Kid.... */
#define ptPpid		12	/* give us pid of parent of this process */
#define ptCmdName	13	/* return name of executable */

/* these were from `#include <fcntl.h>' on a System III */
#define O_RDONLY	0
#define O_WRONLY	1
#define O_RDWR  	2

#include "tk.h"
/* these are alternate names for some tokens */
#define tkModulo tkPercent
#define tkBitAnd tkAmper
#define tkMul tkStar
#define tkLT tkLAB
#define tkGT tkRAB
#define tkXOR tkUpArrow	
#define tkBitOr tkBar

/* sex codes (also known as Blue Laws) */
#define bitSexNil	0
#define bitSexLittle	1
#define bitSexBig	2

#define byteSexNil	0
#define byteSexLittle	1
#define byteSexBig	2

/* Floating point classes */
#define fpcNil		0
#define fpcMit		1
#define	fpcDec		2


#define cbArgsMax	1024	/* size of command line */

typedef struct CPUS {
	int1	cbChar;		/* size (in bytes) of char, int, etc. */
	int1	cbShort;
	int1	cbInt;
	int1	cbLong;
	int1	cbFloat;
	int1	cbDouble;
	int1	cbPointer;
	int1	cbRegister;
	/* "style" information */
	int1	bitSex;		/* bit ordering with in word */
	int1	byteSex;	/* byte ordering with long */
	int1	alignment;	/* "int" alignment - 0, 1, or 3 */
	int1	fpc;		/* floating point class */
	/* registers */
	int2	iregMax;	/* size of rgReg */
	pSER	rgReg;		/* points at register goodies */
	/* miscellaneous */
	int4	instBp;		/* a breakpoint instruction */
	int2	cbBp;		/* number of bytes in BP */
	int2	cBadMax;	/* see BpFSingle */

	bits	fApIsFp : 1;	/* AP is the same as FP */
	bits	fBackupOnBpt : 1;	/* PC points past BPT instruction */
	bits	fCalleeStackCleanup : 1;	/* E.g. Vax & CCI */
	} CPUR, *pCPUR;
#define cpuNil ((pCPUR)0)
#define cbCPUR sizeof(CPUR)

/* process state */
#define psNil		0
#define psNoChild	1	/* no live process */
#define psStopped	2	/* live process - stopped at BP or SIG */
#define psRunning	3	/* live process - currently running */
#define psDying		4	/* process is being killed */
#define psFork		5	/* process is result of a fork */
#define psExec		6	/* process has just done an exec */
#define psContinue	7	/* analyze stop */
#define psMax		8

/* communication state */
#define csNil		0	/* comm is quiescent */
#define csReading	1	/* we are waiting for reply from remote */
#define csWriteDone	2	/* we finished writing and are about to read */
#define csWriting	3	/* we are writing to remote */

/* Wait-ing types */
#define wtNil		0
#define wtTty		1	/* tty input */
#define wtAnything	2
#define wtAnyProcess	3
#define wtProcess	4	/* for a specific process */

typedef struct OSS {	/* OS dependent stuff */
	ADRT	adrTty;		/* address of child's channel 0 tty buffer */
	int2	sigTrap;	/* breakpoint signal */
	int2	sigMax;		/* number of signal */
	pSAR	mpSigSa;	/* signal action records */
	/* these next three will be adrNil if inapplicable - e.g. remote */
	ADRT	adrReg0;	/* location of register 0 in "user" */
	ADRT	adr_u_ar0;	/* offset to pointer to reg0 */
	ADRT	adrUser;	/* base address of user structure IN KERNEL!!!*/
	ADRT	adrEntry;	/* offset to u.entloc or whatever */
	ADRT	dadrEntMax;	/* maximum we might be away from entry */
	int4	instSyscall;	/* system call instruction */
	bits fIntegerOffsets : 1;  /* we need to add sizeof(int) - sizeof(x) */
	bits fClearFp : 1;	/* we clear the FP when we create new child */
	} OSR, *pOSR;
#define cbOSR sizeof(OSR)
#define osNil ((pOSR)0)

typedef struct CNTXS {	/* Context Record - used for walking the stack */
	ADRT	pc;
	ADRT	fp;
	ADRT	ap;
	ADRT	sp;
	ADRT	csp;	/* a Pyramidism - the control stack pointer */
	bits	fEndOfStack : 1;
	} CNTXR, *pCNTXR;
#define cbCNTXR sizeof(CNTXR)
#define cntxNil ((pCNTXR)0)

typedef struct PRS {	/* per process values */
	SBT	sbName;			/* nickname for this process */
	    /* Runtime goodies */
	int2	pid;			/* process id */
	int2	pidParent;		/* Hi, Mom! */
	int	pgrpSave;		/* process's previous process grp */
	int2	status;			/* status at last stop */
	CNTXR	acntx;			/* current context info */
	int2	ps;			/* process state */
	int	iln, slop;		/* line number & offset from line */
	    /* dynamically accessible things MUST be INT */
	int	lc;			/* language code */
	int	fCommDebug;		/* debug remote communications */
	int	debuglevel;		/* controls debugger debugging output */
	int	tracelevel;		/* level of tracing */
	int	sigOrig, sig;		/* signal we stopped on */
	    /* Object pointers */
	pCPUR	cpu;			/* cpu dependent stuff */
	pOSR	os;			/* os dependent stuff */
	    /* remote communications */
	SBT	sbComm;			/* name of communications port */
	int2	fnComm;			/* communications channel */
	int2	iBaud;			/* index into baud rate table */
	    /* Random stuff */
	    /* bits from all over the place */
	    /* 13 used, 19 to go */
	bits	fQuiet : 1;		/* silences many messages during BP */
	bits	fDoingSingle : 1;	/* indicates last 'run' was single */
	bits	fAtSyscall : 1;		/* single stepping over system call */
	bits	fMachineStep : 1;	/* we are instruction stepping */
	bits	fRunAssert : 1;		/* check for active assertions */
	bits	fPureText : 1;		/* instructions are shared/read-only*/
	bits	fStty : 1;		/* Use stty each child start/stop */
	bits	fForkedProcess : 1;	/* Don't Deallocate entire PRR */

	    /* multi-process bits */
	bits	fStopOnExec : 1;	/* stop immediately after exec */
	bits	fStopOnFork : 1;	/* stop BOTH process after fork */
	bits	fClearStop : 1;		/* single-step set StopOnExec */
	bits	fRemoveBpsOnFork : 1;	/* child does NOT get parent's BPs */
	bits	fDebugChildren : 1;	/* indicates we WANT the kids */

	ADRT	adrStartLow;		/* Normally adr of _start */
	ADRT	adrStartHigh;	/* Normally adr of routine AFTER _start */
	ADRT	adrInit;		/* main for C, program for Pascal */
	ADRT	adrInst;		/* last address we examined */
	ADRT	adrText;		/* base address of the code area */
	ADRT	adrData;		/* base address of the data area */
	SBT	sbInit;			/* statement step start address */

	    /* various primary file info */
	HDRR	hdr;			/* copy of HDR from sbCdb */
	SBT	sbCdb;			/* cdb symbol file */
	int2	fnCdb;	 		/* file number of cdb symbol file */
	SBT	sbExec;			/* executable file */
	int2	fnExec;	 		/* file number of executable file */
	SBT	sbCore;			/* core file */
	int2	fnCore;	 		/* file number of core file */
	int4	mtimeExec;		/* last time exec was changed */
	MAPR	mapExec;		/* map of executable file */
	MAPR	mapCore;		/* map of core file */
	SBT	*rgSbDir;		/* alternate directories for source */
	int2	idirMac;		/* number in use */
	int2	idirMax;		/* number allocated */
	    /* pointers to memory resident copies of ... */
	pPDR	rgPd;			/* procedure descriptore array */
	int2	ipd;			/* current procedure */
	pFDR	rgFd;			/* file descriptore array */
	int2	ifd;			/* current file */
	    /* AUX Cache variables */
	int4	iauxLo, iauxLim;	/* min/max indicies in cache */
	int4	iauxCacheMax;		/* cache size */
	pAUXU	auxCache;		/* auxillary symbol cache */
	    /* LINE Cache variables */
	int4	ilineLo, ilineLim;	/* min/max indicies in cache */
	int4	ilineCacheMax;		/* cache size */
	pLINER	lineCache;		/* line symbol cache */
	pLINER	line;			/* current line symbol */
	    /* SYM Cache variables */
	int4	isymLo, isymLim;	/* min/max indicies in cache */
	int4	isymCacheMax;		/* cache size */
	pSYMR	symCache;		/* symbol cache */
	pSYMR	sym;			/* the `current' symbol */
	int4	isym;			/* sym index for surrent sym */
	    /* ISS (String Space) Cache variables */
	int4	issLo, issLim;		/* min/max indicies in cache */
	int4	issCacheMax;		/* cache size */
	SBT	sbCache;		/* string cache */
	    /* Typedefs */
	pTDR	rgTd;			/* typedef array */
	    /* Breakpoints */
	int2	ibpMac;			/* current/max number BPR's in use */
	int2	ibpMax;			/* number allocated */
	pBPR	rgBp;			/* array of BPR's */
	int2	ibtMac;			/* trace points */
	int2	ibtMax;			/* number allocated */
	pBPR	rgBt;			/* array of tracing BPR's */
	int2	cCallNest;		/* used for dynamic call graph */
	pBPR	bp;			/* pointer to current BPR */
	BPR	abp;			/* holding slot for a breakpoint */
	int	ipdFork;		/* ditto */
	    /* Assertion info */
	int2	iadMac;			/* in use */
	int2	iadMax;			/* allocated */
	pADR	rgAd;			/* the list of assertions */
	ADRT	pcLast;			/* last address seen during assert */
	ASE	as;			/* state of the assertions as a whole */
	    /* procedure call from the command line stuff */
	ADRT	adrBreak; /* the place we break at when doing proc calls */
	ADRT	adrCall;  	/* location of call instruction in _end_ */
	int2	cNestProc;	/* nesting depth of proc's from cmd line */
	char	sbSave[100]; /* where we put saved command AFTER proc is done */
	    /* command line per process cruft */
	SBT	sbCmd;			/* current command line */
	SBT	sbCmdStart;		/* remembered for freeing purposes */
	    /* string storage in child */
	ADRT	adrSbStart;		/* where the buffer starts */
	ADRT	adrSb;			/* where we store next byte in buffer */
	ADRT	adrSbMax;		/* first adr AFTER buffer */
	SBT	sbArgsChild;  		/* args for child */
	    /* debugger local variables */
	int2	ilvMac;			/* number of locals used */
	int2	ilvMax;			/* number allocated */
	pSER	rgLv;			/* pointer to local variables */
	int2	stackdepth;		/* default depth for params/locals */
	pSER	seDot;			/* last expression result */
	} PRR, *pPRR;
#define cbPRR sizeof(PRR)
#define prNil ((pPRR)0)

#include "ext.h"  /* external declarations for all `export'ed procedures */
0707070001000312431004440000000000010000011607100454650114100001500000012025cdb/config.h /* $Header: config.h,v 6.5 86/09/15 09:32:10 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include "SYS.h"

/* SYS names */
#define ONYXIII	1
#define VAX41	2
#define VAX41c	3
#define VAX42	4
#define REG68	5
#define SUN42	6
#define SUNGH42	7
#define NSC32V	8
#define VAX41S42 9
#define ELXSI64	10
#define MEGA42	11
#define AR68V	12
#define ISI42	13
#define P60V	14
#define VAXV	15
#define CTVMega	16
#define CTVMini	17
#define CCI42	18
#define ATT3B2	19
#define CPC19V	20
#define PY9X42	21
#define SYM3242	22
#define	OPUS32V	23
#define	INTER32V	24
#define	HS550	25
#define	MX32V	26
#define IN386V	27

/* CPU definitions */
#define Z8000	1
#define VAX	2
#define M68000	3
#define N32000	4
#define I8086	5
#define CCI632	6
#define A3B2	7
#define PY9X	8
#define I80386	9

/* Operating system definitions */
#define SYSIII	1
#define BSD41	2
#define BSD41c	3
#define BSD42	4
#define V7	5
#define REGULUS	6
#define MSDOS	7
#define SYSV	8

#define O_S OP_SYS

/* Manufacturer definitions */
#define ONYX	1
#define DEC	2
#define IBM	3
#define ALCYON	4
#define SUN	5
#define PLEXUS	6
#define MEGA	7
#define ARETE	8
#define ISI	9
#define CT	10
#define CCI	11
#define ATT	12
#define CPC	13
#define XYZ	14
#define ELXSI	15
#define PYRAMID	16
#define GOULD	17
#define INTEL	18
#define NSC	19
#define MOTOROLA	20
#define SYMMETRIC	21
#define OPUS	22
#define SIEMENS	23
#define FAIRCHILD	24
#define INTERGRAPH	25
#define ENCORE	26

/* Compiler definitions */
#define GH68	1

#ifdef HOST_CPU
    /* This allows the host CPU code to compile differently */
#undef CPU
#define CPU HOST_CPU
#endif

/* CPU defaults */
#if (CPU == M68000)

#ifndef BPT_INST
#define BPT_INST	0x4e410000	/* trap 1 */
#endif

#define CB_BP		2
#define ALIGNMENT_MASK	1
#define BYTE_SEX	byteSexBig
#define BIT_SEX		bitSexBig
#define FPISAP		1
#endif /* (CPU == M68000) */

#if (CPU == VAX)
#define BPT_INST	03
#define CB_BP		1
#define ADR_PROC_BASE	2
#define ALIGNMENT_MASK	0
#define BYTE_SEX	byteSexLittle
#define BIT_SEX		bitSexLittle
#define CALLE_STACK_CLEANUP	1
#endif /* (CPU == VAX) */

#if (CPU == I80386)
#define ALIGNMENT_MASK	0
#define BYTE_SEX	byteSexLittle
#define BIT_SEX		bitSexLittle
#define FPISAP		1
#define	DADR_ENTMAX	4
#define BPT_INST 	0xcc
#define CB_BP		1
#endif /* (CPU == I80386) */

#if (CPU == N32000)
#define ALIGNMENT_MASK	0
#define BYTE_SEX	byteSexLittle
#define BIT_SEX		bitSexLittle
#define FPISAP		1
#define INST_SYSCALL	0xe2
#define	DADR_ENTMAX	4
#define BPT_INST 	0xf2
#define CB_BP		1
#define CLEAR_FP	0
#endif /* (CPU == N32000) */

#if (CPU == CCI632)
#define CB_BP	1		/* size of a breakpoint */
#define BPT_INST	0x30000000	/* a breakpoint instruction */
#define ALIGNMENT_MASK	3
#define BYTE_SEX	byteSexBig
#define BIT_SEX		bitSexBig
#define NO_STACK_CLEANUP	1
#endif /* (CPU == CCI632) */

#if (CPU == A3B2)
#define BPT_INST	0x2e000000	/* a BPT instruction */
#define CB_BP		1
#define ALIGNMENT_MASK	3
#define BYTE_SEX	byteSexBig
#define BIT_SEX		bitSexBig
#define FPISAP		1
#endif /* (CPU == A3B2) */

#if (CPU == PY9X)
#define CB_BP	4		/* size of a breakpoint */
#define BPT_INST	0xf0000000	/* a BPT instruction */
#define ALIGNMENT_MASK	3
#define BYTE_SEX	byteSexBig
#define BIT_SEX		bitSexBig
#define FPISAP		1
#define NO_STACK_CLEANUP	1
#endif /* (CPU == PY9X) */

#if (CPU == PDN)
#define CB_BP	2		/* size of a breakpoint */
#define BPT_INST	0xf0000000	/* a BPT instruction */
#define ALIGNMENT_MASK	1
#define BYTE_SEX	byteSexBig
#define BIT_SEX		bitSexBig
#define FPISAP		1
#endif /* (CPU == PDN) */

/* the following give us the default values */

#define ANY_BSD ( (O_S == BSD41) || (O_S == BSD41c) || (O_S == BSD42) )

#ifndef REMOTE_OS
#define REMOTE_OS O_S
#endif

#ifndef HOST_CPU
#define HOST_CPU CPU
#endif

#ifndef CALLEE_STACK_CLEANUP
#define CALLEE_STACK_CLEANUP	0
#endif

#ifndef FPISAP
#define FPISAP		0
#endif

#ifndef BPT_BACKUP
#define BPT_BACKUP	0
#endif

#ifndef REGT
#define REGT unsigned int
#endif

#ifndef ADR_USER
/* address of struct user in kernel address space */
#define ADR_USER adrNil
#endif

#ifndef ADR_REG0
#define ADR_REG0 adrNil
#endif

#ifndef ADR_U_AR0
#define ADR_U_AR0 adrNil
#endif

#ifndef cbStorageMax
#define cbStorageMax	(0x7ffff000L)
#endif

#ifndef INTEGER_OFFSETS
/* A big-endian machine (e.g. 68000) with parameters on integer boundaires */
#define INTEGER_OFFSETS	0
#endif

#ifndef ADR_PROC_BASE
#define ADR_PROC_BASE 0
#endif

#ifndef CLEAR_FP
#define CLEAR_FP	1
#endif

#ifndef ADR_TEXT_BASE
#define ADR_TEXT_BASE	0L
#endif

#ifndef cbCodeOffset
#define cbCodeOffset	1024
#endif

#ifndef ADR_CALL
#define ADR_CALL	adrNil
#define ADR_BREAK	adrNil
#endif

#ifndef PID_FIRST_USER
#define PID_FIRST_USER	3
#endif

#ifndef STRUCT_RETURN_OFFSET
#define STRUCT_RETURN_OFFSET	0
#endif

#ifndef NO_UNDERSCORES
#define NO_UNDERSCORES	0
#endif

#ifndef PERCENT_SIGNS
#define PERCENT_SIGNS 0
#endif

#ifndef upc
#define 	usp	16
#define 	upc	17
#define 	ufp	18
#define 	upsw	19
#define		uap	20
#endif

#ifndef CHECK_REG_PARAMS
#define CHECK_REG_PARAMS	0
#else
#undef ALSO_EQUAL
#define ALSO_EQUAL	1
#endif

#ifndef ALSO_EQUAL
#define ALSO_EQUAL	0
#endif

0707070001000312441004440000000000010000011607620454650114100001200000033665cdb/ext.h #define X_InitRegisters 1
#define X_ListRegisters 1
extern int2 vrgOffset[];
extern SER vrgReg[];
extern int viregMax;
extern ADRT AdrFStackFix(/* adr */);
extern ADRT AdrFPreamble(/* adr */);
extern FLAGT FAtCall(/* adr */);
extern ADRT RetFSp(/* sp */);
extern void DoReg(/* seReg, cntx */);
extern int NextFrame(/* cntx */);
extern void InitRegisters(/* cpu */);
extern void ListRegisters(/* sbRegs */);
extern int vcbInst;
extern void PrintInstruction(/* adr */);
extern char **venvpParent;
#define cArgsMax 100
extern void InitPattern(/* sbPattern */);
extern int IFPattern(/* sbLine */);
extern SBT SbFSignal(/* sig */);
extern int SetJmp(/* env */);
extern void LongJmp(/* env */);
extern void SetMyTty(/*  */);
extern void SetHisTty(/*  */);
extern void InitMyTty(/*  */);
extern void SetDemoTimer(/* cSeconds */);
extern FLAGT FTimedInput(/* cSeconds */);
extern SBT SbFError(/* error */);
extern void Oops(/* sig */);
extern void InitSignals(/*  */);
extern void OsCreateTarget(/*  */);
extern void InitSa(/*  */);
extern void InitCore(/* pr */);
extern void InitOs(/* pr */);
extern int *venv;
extern int vfFPConv;
extern int2 viprMax;
extern FLAGT vfAttach;
extern pCPUR vcpuHost;
#define dprint(x, y) {if (x <= v->debuglevel) printf y; fflush(stdout);}
#define cbLineMax 1024
#define iwwNil -1
extern char vsbOptions[];
extern SBT vsbDefaultFile;
extern pMODER vmode;
extern char **venvpParent;
extern int1 vcaseMod;
extern SBT vsbDebugName;
extern int2 vpidCdb;
extern int vcActive;
extern char vsbPrompt[];
extern ADRT vadrUser;
extern ADRT vadrReg0;
extern ADRT vadrUar0;
extern int vcsRemote;
extern FLAGT vfInWait;
extern FLAGT vfInterruptPending;
extern FLAGT vfWindows;
extern FILE *vfpWwSrc;
extern int vfnTarget;
extern int viwwTarget;
extern int viwwSrc;
extern SBT vsbDevSrc;
extern int viwwCmd;
extern SBT vsbDevWw;
extern int vlcDefault;
extern int vfUseCache;
extern int vfCommDebug;
extern void main(/* argc, argv, envp */);
extern void SaveAll(/*  */);
extern void CdbExit(/* value */);
extern int4 LongFSb(/* sb */);
extern void AddOptions(/* sbOption, va_alist */);
extern void ApplyOptions(/* pr, sbOptions */);
extern FLAGT vfCacheValid;
extern REGT GetUser(/* adr */);
extern void PutUser(/* adr, val */);
extern int GetWord(/* adr, space */);
extern void PutWord(/* adr, space, val */);
extern void SetCommCache(/* adrSrc, cb */);
extern void ReadData(/* adrDest, adrSrc, cb */);
extern void WriteData(/* adrDest, adrSrc, cb */);
extern void BlockTransfer(/* adrDest, adrSrc, space, cb */);
extern int Access(/* accRequest, adr, space, value */);
extern ADRT AdrFPurify(/* adr, fExec */);
extern void DoMap(/*  */);
extern FLAGT FSaveAssertions(/* fp */);
extern void ListAssert(/*  */);
extern void AddAssert(/* sbCheck, cb */);
extern void ModAssert(/* iad, as */);
extern FLAGT FDoAssert(/* pt */);
extern pBPR vbpContinue;
extern pBPR vbpStop;
extern FLAGT vfNewBreaks;
extern FLAGT FSaveBp(/* fp */);
extern void ListBp(/*  */);
extern void AllBpInstall(/*  */);
extern void RemoveAllBp(/*  */);
extern void ClearBp(/* bp */);
extern void ClearAllBp(/*  */);
extern pBPR BpFIfdIln(/* ifd, iln */);
extern pBPR BpFAdr(/* adr */);
extern pBPR BpFProcess(/* adr */);
extern pBPR BpFAddBp(/* adr, count, sbCmd, cb */);
extern pBPR BpFSet(/* bpc, fTemp, cnt, sbCmd, cb */);
extern void SaveForkBp(/* bp */);
extern pBPR BpFForkSave(/* pid, adr */);
extern FLAGT vfIgnoreCase;
extern CMDE vcmdDef;
extern char vsbFileTemp[];
extern void SetCmd(/* sb */);
extern int IlnFNormalize(/* ifd, iln */);
extern void CallShell(/* sbCmd */);
extern char * EatCmdList(/* pcnt */);
extern SBT SbFEob(/* sb */);
extern void GotoIln(/* iln */);
extern FLAGT FDoCommand(/* sbCmdIn, fTop */);
extern FILE *vfpOutput, *vfpRecord, *vfpPlayback;
extern int4 vcStepPlayback, vsleepDemo;
extern FLAGT vfComment, vfOutput, vfRecord, vfEofSeen;
extern SBT  vsbGet;
extern void NextCmd(/* sbBuffer, cbBuffer, sbPrompt */);
extern void DebugIt(/* fTopLevel */);
extern void RecordCmd(/* sbCmd */);
extern int YesNo(/* sbPrompt */);
extern char ChFChoice(/* sbPrompt, sbChoice */);
extern void SetPlayback(/* sbPlayback, fQuiet, fSinglestep */);
extern void SetOutput(/* sbOutput */);
extern void SetRecord(/* sbRecord */);
extern void StateRecord(/*  */);
extern void ShowState(/*  */);
extern void PlaybackFile(/* sbFile */);
extern uint4 vcbUserPage;
extern void ListRegisters(/* sbRegs */);
extern uint1 GetByte(/* adr, space */);
extern void PutByte(/* adr, space, val */);
extern void GetBlock(/* adrSrc, space, adrDest, cb */);
extern void PutBlock(/* adrDest, space, adrSrc, cb */);
extern ADRT AdrFReg(/* reg */);
extern REGT GetReg(/* reg */);
extern void PutReg(/* reg, val */);
extern void ReadPc(/*  */);
extern void SetCntx(/*  */);
extern SBT SaveState(/*  */);
extern void RestoreState(/* sbSave */);
extern void MoveBytes(/* adrDest, adrSrc, cb */);
extern VALU ValFReg(/* se, cb */);
extern void StoreReg(/* seDest, seSrc */);
extern VALU ValFUser(/* se */);
extern void StoreUser(/* seDest, seSrc */);
extern void InstallBp(/* bp */);
extern void RemoveBp(/* bp */);
extern void SavePcFp(/*  */);
extern void SetCallProc(/* adr, sp, cArg */);
extern void CallProcedure(/* adrProc, seFirst, cArg */);
extern void SeFReturn(/* seRet, seProc */);
extern void GetArgN(/* cntx, se, iarg */);
extern void DispUnknown(/* cntx, ipd */);
extern void FixPc(/*  */);
extern void FinishCpu(/*  */);
extern void InitRegisters(/* cpu */);
extern void InitCpu(/* cpu */);
extern void InitHostCpu(/* cpu */);
extern FLAGT vfInFalse;
extern pSER vseInit;
extern pSER vseAdr;
extern pSER vseCnAdr;
extern pSER vseChar;
extern pSER vseCnChar;
extern pSER vseUChar;
extern pSER vseCnUChar;
extern pSER vseShort;
extern pSER vseCnShort;
extern pSER vseUShort;
extern pSER vseCnUShort;
extern pSER vseInt;
extern pSER vseCnInt;
extern pSER vseUInt;
extern pSER vseCnUInt;
extern pSER vseLong;
extern pSER vseCnLong;
extern pSER vseULong;
extern pSER vseCnULong;
extern pSER vseFloat;
extern pSER vseCnFloat;
extern pSER vseDouble;
extern pSER vseCnDouble;
extern pSER vseLogical;
extern pSER vseCnLogical;
extern pSER vseComplex;
extern pSER vseCnComplex;
extern void InitSe(/*  */);
extern void GetAdr(/* se */);
extern void GetVal(/* se */);
extern void GetOrig(/* se */);
extern void ResFOps(/* seRet, se1, se2 */);
extern void Coerce(/* seTo, seFrom */);
extern void Assign(/* seDest, seSrc */);
extern int Min(/* x, y */);
extern int Max(/* x, y */);
extern void ZeroBlock(/* sb, cb */);
extern SBT SbFBt(/* bt */);
extern void SeFSym(/* se, sym, fRecurse */);
extern void CopyTy(/* seDest, seSrc */);
extern int TqFSe(/* se, cnt */);
extern void AddTq(/* se, tq */);
extern void RemoveTq(/* se */);
extern int CbFSe(/* se */);
extern void PrintVersion(/* x */);
extern void F_PxSe(/*  */);
extern pSYMR F_SymFAdr(/*  */);
extern void PxCommon(/*  */);
extern void DoCommon(/*  */);
extern void ClearTargetScreen(/*  */);
extern void SetSrcWw(/*  */);
extern void CenterWw(/*  */);
extern void UpLine(/*  */);
extern void MakeActive(/*  */);
extern void InitAllWw(/*  */);
extern void RestoreAllWw(/*  */);
extern void WwCmd(/*  */);
extern void EdOpenFile(/*  */);
extern void JumpScrollWw(/*  */);
extern void MarkLine(/*  */);
extern void ShowBp(/*  */);
extern void Highlight(/*  */);
extern void CloseComm(/*  */);
extern void InitComm(/*  */);
extern void XBlockTransfer(/*  */);
extern void CreateTarget(/*  */);
extern int SendSignal(/* sig */);
extern int Ptrace(/* pt, pid, adr, value */);
extern int Wait(/* pstatus */);
extern void FreeProcess(/*  */);
extern pPRR PrFAttachProcess(/* ) {UError(vsbMultiErr */);
extern pPRR PrFExec(/* ) {UError(vsbMultiErr */);
extern int vtkLast;
extern SBT vsbLex;
extern SER vase;
extern pSER vseArgs;
extern int yylex(/*  */);
extern void ConvertFloat(/* se, fFromHostToRemote */);
extern long ExtractBits(/* x, pos, width */);
extern long SetBits(/* x, pos, width, val */);
extern ADRT AdrFSe(/* se */);
extern VALU ValFSe(/* se */);
extern void WriteVal(/* seDest, seSrc */);
extern ADRT AdrFStore(/* sb, cb */);
extern pSER SeFExpr(/* se */);
extern int4 LongFExpr(/* seRet, tk */);
extern char vsbFilename[];
extern SBT SbFAlloc(/* sb */);
extern void AddDir(/* pr, sbDir */);
extern void ListDir(/*  */);
extern SBT SbFBase(/* sb */);
extern void EditFile(/* ifd, iln */);
extern SBT SbFSearch(/* sbFile, permissions */);
extern int IpdFName(/* sbProc */);
extern int IlnFirstFIpd(/* ipd */);
extern int AdrFirstFIpd(/* ipd */);
extern void OpenIpd(/* ipd, fForce */);
extern void OpenIfd(/* ifd */);
extern void SetViewPosition(/* adr */);
extern int IfdFName(/* sbFile */);
extern SBT SbFPrepareLine(/* sbIn */);
extern void PrintLine(/* iln, count, fPrintLn, fp */);
extern void Find(/* sbTarget, fBack */);
extern void PrintPosition(/* adr, fmt */);
extern FLAGT vfInDisplay;
extern FLAGT vfBadAddress;
extern char vsbFmt[];
extern int vcNest;
extern SBT vsbSpaces;
#define PrintNest(cNest, cb) if (cNest) printf("%.*s", cNest*cb, vsbSpaces)
extern SBT SbFAdr(/* adr, fMask */);
extern SBT SbFBinary(/* value, cbits */);
extern DFE DfFSe(/* se, fAlternate */);
extern int CbFCh(/* ch */);
extern DFE DfFCh(/* ch */);
extern void GetMode(/* mode */);
extern int IncFSeMode(/* se, mode, multiplier */);
extern void DisplaySe(/* se, mode, fShowAdr, fIndirect, fAlternate */);
extern void PxEnum(/* se */);
extern void PxStruct(/* seStruct, cntStruct, fDoVal, fAlternate, fDoStd */);
extern void PxProc(/* ipd, fDoName, fAlternate */);
extern void PxSe(/* se, fAlternate */);
extern void Help(/*  */);
extern void FindAndFix(/*  */);
extern void ListSomething(/*  */);
extern int vcLinesMax;
extern int FBlockCmp(/* sb1, sb2, cb */);
extern char * SbConcat(/* sbDest, sb1 */);
extern int4 LongFRound(/* x, y */);
extern void ColOn(/*  */);
extern void ColOff(/*  */);
extern void PadTo(/* col */);
extern void ClearCol(/*  */);
extern void MoreOn(/*  */);
extern void MoreOff(/*  */);
extern void ClearMore(/*  */);
extern FLAGT vfOutputSuppress;
extern int printf(/* format, va_alist */);
extern int fprintf(/* fp, format, va_alist */);
extern void Fixer(/*  */);
extern void SetPrompt(/* sbMsg, arg1, arg2, arg3, arg4 */);
extern void Panic(/* sbMsg, arg1, arg2, arg3, arg4 */);
extern void SysPanic(/* sbMsg, arg1, arg2, arg3, arg4 */);
extern void UError(/* sbMsg, arg1, arg2, arg3, arg4 */);
extern char * strchr(/* sb, ch */);
extern char * strrchr(/* sb, ch */);
extern int strcspn(/* sbSpan, sbNot */);
extern int CargFIpd(/* ipd */);
extern void DoProc(/* seRet, seProc, seFirst, seMac */);
extern FLAGT FCallUserProc(/* sbProc, cArg, arg1 */);
extern pPRR v;
extern pPRR *vrgPr;
extern int2 viprMax;
extern void InitProcessTable(/*  */);
extern SBT SbOptionsFDefault(/* sbExec */);
extern SBT SbFPs(/* ps */);
extern void ListPr(/* prIn */);
extern void ReapChildren(/*  */);
extern pPRR PrFFn(/* fn */);
extern int2 IprFPr(/* pr */);
extern pPRR PrFIpr(/* ipr */);
extern pPRR PrFSb(/* sb */);
extern pPRR PrFPid(/* pid */);
extern void SetGlobalPr(/* pr */);
extern pPRR PrFAlloc(/*  */);
extern void DeallocPr(/* pr, fSaveLocals */);
extern pPRR PrFInitPr(/* sbExec */);
extern void InitPr(/* pr */);
extern FLAGT vfAnalyzeStop;
extern SBT SbFNextArg(/* psbIn */);
extern void DoArgs(/* sbProgram, sbArgs, argv, fReassign */);
extern void AnalyzeStop(/*  */);
extern void RunProcess(/* pt, ps, fWait */);
extern void KillChild(/*  */);
extern void NewChild(/* sbArgs, fInit */);
extern void ExecInit(/* fInit */);
extern void SaMaintain(/* sig, sbOptions, sbCmds */);
extern void ListSa(/*  */);
extern void SingleStep(/* cmd, fQuiet */);
extern FLAGT vfCacheSymbols;
extern pLINER LineFIline(/* iline */);
extern pAUXU AuxFIaux(/* iaux */);
extern int4 IsymFSym(/* sym */);
extern pSYMR SymFIsym(/* isym */);
extern void SetNextSym(/* isym */);
extern FLAGT FNextSym(/* stHit1, stHit2, stHit3, stStop, fEnterBlocks, sbHit, Cmp */);
extern SBT SbFIss(/* iss */);
extern SBT SbFIpd(/* ipd */);
extern SBT SbFSym(/* sym */);
extern int4 IssFSb(/* sb */);
extern SBT SbSafeFSb(/* sb */);
extern int4 IssSafeFSb(/* sb */);
extern SBT SbSafeFIss(/* iss */);
extern FLAGT FSbCmp(/* sb1, sb2 */);
extern FLAGT FHdrCmp(/* sbHdr, sbCheck */);
extern FLAGT FTailCmp(/* sbTail, sbIn */);
extern FLAGT FNextLocal(/* fLocal, fParam, isym */);
extern int IpdFAdr(/* adr */);
extern int IfdFAdr(/* adr */);
extern int IfdFIsym(/* isym */);
extern ADRT AdrFIpdIln(/* ipd, iln */);
extern int IpdIlnFAdr(/* piln, pslop, adr */);
extern int2 IfdIlnFAdr(/* piln, adr */);
extern ADRT AdrFIfdIln(/* ifd, iln */);
extern ADRT AdrFEndOfProc(/* ipd */);
extern long CblFFn(/* fn */);
extern long AgeFFn(/* fn */);
extern int2 vcbTok, vcbPeek;
extern TKE vtk, vtkPeek;
extern char vsbTok[], vsbTokPeek[];
extern int isodigit (/* ch */);
extern void SearchTd(/* ptk, sb */);
extern void SearchKw(/* ptk, sbKey, rgKw, ikwMax */);
extern char ChFEscape(/* psbIn, fEatBackSlash */);
extern TKE TkFStr(/* psbCmd, sbTok, pcb, fIgnoreErrors */);
extern TKE TkPeek(/*  */);
extern TKE TkNext(/*  */);
extern int vfStrict;
extern int vfTypedefs;
extern int vfNotify;
extern int vdadrMax;
extern int vfArnulf;
extern void InitSpc(/* se, sb, value, st, sc, tq0, bt, fConstant */);
extern void InitSpecials(/*  */);
extern void ListSpecials(/* sbSpc */);
extern FLAGT FSpecial(/* seRet */);
extern void SpecialSideEffects(/* seNew, seCur */);
extern void AdjustFieldOffset(/* seStruct, seField */);
extern FLAGT FField(/* seStruct, seField */);
extern long IsymNextFBlock(/* isym */);
extern long IsymFEnclosing(/* adr */);
extern long IsymFAdr(/* adr, isymHint */);
extern pSYMR SymFAdr(/* adr, sb */);
extern FLAGT FTypeFName(/* seType, tk */);
extern FLAGT FEnum(/* se */);
extern void SetAdr(/* se, cntx */);
extern FLAGT FLocal(/* se, ipd, cnt */);
extern FLAGT FGlobal(/* se */);
extern ADRT AdrFLabel(/* sbLabel */);
extern pCNTXR CntxFIpd(/* cntx, pipd, cnt */);
extern SBT SbFReg(/* pc, reg */);
extern SBT SbFStackOffset(/* pc, fFp, offset */);
extern SBT SbFLabelAdr(/* adr */);
extern SBT SbFNearest(/* adr, fText, fData, fProcOnly */);
extern void DispFrame(/* cntx, cnt, fDoLocals, fList */);
extern void StackTrace(/* cnt, fDoLocals */);
extern void OpenStack(/* cnt */);
extern int StackDepth(/*  */);
0707070001000312451004440000000000010000011611330454650114100001200000032567cdb/sym.h /* $Header: sym.h,v 5.18 86/07/18 06:14:35 peter Exp $ */

/* (C) Copyright 1984 by Third Eye Software, Inc.
 *
 * Third Eye Software, Inc. grants reproduction and use rights to
 * all parties, PROVIDED that this copyright notice is maintained
 * in the copy.
 *
 * Third Eye makes no claims about the applicability of this
 * symbol table to a particular use.
 */

/* 
 * This file contains the definition of the Third Eye Symbol Table.
 *
 * Symbols are assumed to be in 'encounter order' - i.e. the order that
 * the things they represent were encountered by the compiler/assembler/loader.
 * EXCEPT for globals!	These are assumed to be bunched together,
 * probably right after the last 'normal' symbol.  Globals ARE sorted
 * in ascending order.
 *
 * -----------------------------------------------------------------
 * A brief word about Third Eye naming/use conventions:
 *
 * All arrays and index's are 0 based.
 * All "ifooMax" values are the highest legal value PLUS ONE. This makes
 * them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
 *
 * "isym"	Index into the SYMbol table.
 * "ipd"	Index into the Procedure Descriptor array.
 * "ifd"	Index into the File Descriptor array.
 * "iss"	Index into String Space.
 * "cb"		Count of Bytes.
 * "rgPd"	array whose domain is "0..ipdMax-1" and RanGe is PDR.
 * "rgFd"	array whose domain is "0..ifdMax-1" and RanGe is FDR.
 */

#ifndef int4
#define int1	char
#define uint1	unsigned char
#define int2	short
#define uint2	unsigned short
#define int4	long
#define uint4	unsigned long
#define bits	unsigned int
typedef uint4	ADRT;
#endif

/* 
 * HDR structure.
 * As long as all the pointers are set correctly,
 * we don't care WHAT order the various sections come out in!
 *
 * A file produced solely for the use of CDB will probably NOT have
 * any instructions or data areas in it, as these are available
 * in the original.
 */

#define CURRENT_VERSION	7

typedef struct HDS {
	int2	magic;		/* magic numer as defined below */
	int2	vstamp;		/* version stamp */
	uint4	cbText;		/* text size in bytes, padded to FW boundary */
	uint4	cbData;		/* initialized data	"  "		*/
	uint4	cbBss;		/* uninitialized data	"  "		*/
	uint4	entrypoint;

	int4	ipdMax;		/* number of procedures */
	uint4	cbPdOffset;	/* offset to procedure array */
	int4	ifdMax;		/* number of files */
	uint4	cbFdOffset;	/* offset to file array */
	int4	ilineMax;	/* number of line numbers (0 if none) */
	uint4	cbLineOffset;	/* offset to start of LINE's*/
	int4	issMax;		/* max index into string space */
	uint4	cbSsOffset;	/* offset to start of string space */
	int4	isymMax;	/* number of symbols */
	uint4	cbSymOffset;	/* offset to start of symbols*/
	int4	isymGl;		/* lowest isym of a global */
	int4	isymGlMax;	/* highest isym of a global + 1 */
	int4	iauxMax;	/* number of auxillary symbols */
	uint4	cbAuxOffset;	/* offset to start of auxillary symbols*/
	int4	itdMax;		/* number of typedefs */
	uint4	cbTdOffset;	/* offset to start of typedef info */
	int4	ijokeDay;	/* index to joke of the day -
				 * if (ijokeDay == ijokeNil) then
				 *   ****'em if they can't take a joke.
				 */
	} HDRR, *pHDRR; 
#define cbHDRR sizeof(HDRR)
#define hdrNil ((pHDRR)0)
#define ijokeNil -1

/* magic number definitions */
#define magicNil	-1
#define magicLpd	0401		/* lpd (UNIX/RT) */
#define magicOverlay	0405		/* overlay */
#define magicImpure	0407		/* impure format */
#define magicReadOnly	0410		/* read-only text */
#define magicSplit	0411		/* separated I&D */
#define magicDemand	0413		/* demand load format */
#define magicSDemand	0415		/* short format,demand load(MegaTest) */

/* language codes as seen in ti.lc and fd.lc */
#define lcAuto		-1	/* used at runtime - never stored in bits */
#define lcC		0
#define lcFortran 	1


/*
 * The FDR and PDR structures speed mapping of address <-> name.
 * They are sorted in ascending memory order and are kept in
 * memory by CDB at runtime.
 */

/* 
 * File Descriptor
 *
 * There is one of these for EVERY FILE, whether compiled with
 * full debugging symbols or not.  The name of a file should be
 * the path name given to the compiler.	 This allows the user
 * to simply specify the names of the directories where the COMPILES
 * were done, and we will be able to find their files.
 * A field whose comment starts with "R - " indicates that it is a
 * runtime field and should be set to 0.
 */

typedef struct FDS {
	ADRT	adr;		/* memory address of beginning of file */
	int4	iss;		/* file name (of source, if known) */
	int4	issShort;	/* base file name of source */
	int4	isym;		/* beginning of symbols */
	int4	iline;		/* file's line symbols */
	int2	ipd;		/* start of procedures for this file */
	int2	ilnMac; 	/* R - number of text lines in file */
	uint4	*rgLn;		/* R - the line pointer array (if any) */
	bits	fWarned : 1;	/* R - they were warned about age problems */
	bits	fEdited : 1;	/* R - edited during debug session */
	bits	fNoSource : 1;	/* R - we couldn't find the source file */
	bits	lc : 2;		/* language code for this file */
	bits	reserved : 11;	/* reserved for future TES use */
	} FDR, *pFDR;
#define cbFDR sizeof(FDR)
#define fdNil ((pFDR)0)

#define ifdNil -1
#define ifdTemp 0	/* element 0 of rgFd is ALWAYS reserved for runtime */
#define ilnNil -1


/* 
 * Procedure Descriptor
 *
 * There is one of these for EVERY TEXT LABEL.
 * If a procedure is in a file with full symbols, then isym
 * will point to the PROC symbols, else it will point to the
 * global symbol for the label.
 */

typedef struct PDS {
	ADRT	adr;		/* memory address of beginning of proc */
	int4	isym;		/* beginning of symbols */
	int4	iline;		/* proc's line symbols */
	uint4	maskReg;	/* saved copy of saved register mask */
	ADRT	dadrRegBase;	/* delta base address of saved registers */
	} PDR, *pPDR;
#define cbPDR sizeof(PDR)
#define pdNil ((pPDR)0)
#define ipdNil	-1


/*
 * Line Numbers
 *
 * Line Numbers are segregated from the normal symbols because they
 * are [1] smaller (4 bytes vs 12) , [2] are of no interest to your
 * average loader, and [3] are never needed in the middle of normal
 * scanning and therefore slow things down.
 *
 * By definition, the first LINER for any given procedure will have
 * a delta address (dadr) of 0.  This conveniently allows deduction
 * of start-of-proc when building the PDR array.
 */

typedef struct LINES {
	uint2	iln;	/* line number, file relative, starting at 1 */
	uint2	dadr;	/* delta address from start of procedure */
	} LINER, *pLINER;
#define lineNil ((pLINER)0)
#define cbLINER sizeof(LINER)
#define ilineNil	-1L


/* The following are value definitions for the fields in the SYMR */

/*
 * Storage Classes
 */

#define scNil		0
#define scText		1	/* text symbol */
#define scData		2	/* initialized data symbol */
#define scBss		3	/* un-initialized data symbol */
#define scRegister	4	/* value of symbol is register number */
#define scAbs		5	/* value of symbol is absolute */
#define scUndefined	6	/* who knows? */
#define scCdbLocal	7	/* variable's value is IN se->va.?? */
#define scBits		8	/* this is a bit field */
#define scCdbSystem	9	/* variable's value is IN CDB's address space */
#define scRegImage	10	/* register value saved on stack */
#define scInfo		11	/* symbol contains debugger information */
#define scUserStruct	12	/* address in struct user for current process */
#define scFloatRegister	13	/* value of symbol is float register number */
#define scMax		32


/*
 *   Symbol Types
 */

#define stNil		0	/* Nuthin' special */
#define stGlobal	1	/* external symbol */
#define stStatic	2	/* static */
#define stParam		3	/* procedure argument */
#define stLocal		4	/* local variable */
#define stLabel		5	/* label */
#define stProc		6	/*     "      "	 Procedure */
#define stBlock		7	/* beginnning of block */
#define stEnd		8	/* end (of anything) */
#define stMember	9	/* member (of anything	- struct/union/enum */
#define stTypedef	10	/* type definition */
#define stFile		11	/* file name */
#define stRegReloc	12	/* register relocation */
#define stForward	13	/* forwarding address */
#define stCommon	14	/* Fortran common block */
    /* Psuedo-symbols - internal to debugger */
#define stStr		60	/* string */
#define stNumber	61	/* pure number (ie. 4 NOR 2+2) */
#define stExpr		62	/* 2+2 vs. 4 */
#define stType		63	/* post-coersion SER */
#define stMax		64


/*
 * The Symbol Structure
 */

typedef struct SYMS {
	int4	iss;		/* index into String Space of name */
	int4	value;		/* value of symbol */
	bits	st : 6;		/* symbol type */
	bits	sc  : 5;	/* storage class - text, data, etc */
	bits	index : 21;	/* index into sym/aux table */
	} SYMR, *pSYMR;
#define symNil ((pSYMR)0)
#define cbSYMR sizeof(SYMR)
#define isymNil 0L
#define issNil 0L


/* A U X I L L A R Y   T Y P E	 I N F O R M A T I O N */

/* definitions for fields in TIR */

/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
#define tqNil	0	/* bt is what you see */
#define tqPtr	1	/* pointer */
#define tqProc	2	/* procedure */
#define tqArray 3	/* duh */
#define tqRef	4	/* indicates Fortran REF param (ANSI C & C++, too) */
#define tqMax	8

/* basic types as seen in ti.bt */
#define btNil		0	/* undefined */
#define btAdr		1	/* address - integer same size as pointer */
#define btChar		2	/* character */
#define btUChar		3	/* unsigned character */
#define btShort		4	/* short */
#define btUShort	5	/* unsigned short */
#define btInt		6	/* int */
#define btUInt		7	/* unsigned int */
#define btLong		8	/* long */
#define btULong		9	/* unsigned long */
#define btFloat		10	/* float (real) */
#define btDouble	11	/* Double (real) */
#define btStruct	12	/* Structure (Record) */
#define btUnion		13	/* Union (variant) */
#define btEnum		14	/* Enumerated */
#define btTypedef	15	/* defined via a typedef, isymRef points */
#define btLongLong	16	/* E.g. ELXSI 64 bit integers */
#define btULongLong	17	/* E.g. ELXSI 64 bit integers */
#define	btSet		18	/* pascal type set */
#define	btRange		19	/* pascal type range */
#define btComplex	20	/* f77 type complex */
#define btLogical	21	/* f77 type logical */
#define btSubRange	22	/* defined on something of type btRange */
#define btVoid		23	/* void type */
#define btComplex16	24	/* f77 type complex */
#define btLog1		25	/* f77 type logical */
#define btLog2		26	/* f77 type logical */
#define btLog4		27	/* f77 type logical */
#define btInt1		28	/* f77 type logical */
#define btMax		64

/*
 * Type Information Record
 */

typedef struct {
	bits	reserved : 4;	/* reserved by Third Eye for future use */
	bits	continued : 1;  /* indicates additional info in next AUX */
	bits	lc  : 2;	/* language code */
	bits	bt  : 6;	/* basic type */
	bits	tq5 : 3;
	/* ---- 16 bit boundary ---- */
	bits	fConstant : 1; /* value IS value, not address */
	bits	tq0 : 3;
	bits	tq1 : 3;	/* type qualifiers - tqPtr, etc. */
	bits	tq2 : 3;
	bits	tq3 : 3;
	bits	tq4 : 3;
	} TIR, *pTIR;
#define cbTIR sizeof(TIR)
#define tiNil ((pTIR)0)
#define itqMax 6


typedef struct RNGS {	/* a range */
	int4	iaux;	/* aux of senior scalar */
	int4	dnLow;	/* lowest legal value */
	int4	dnHigh;	/* highest legal value */
	} RNGR, *pRNGR;
#define cbRNGR sizeof(RNGR)
#define rngNil ((pRNGR)0)

#define idimMax 4	/* maximum number of dimesions */

/*
 * Auxillary information occurs only if needed.
 * It ALWAYS occurs in this order when present.
 *
 *	    isymMac		used by stProc only
 *	    TIR			type info
 *	    TIR			additional TQ info (if first TIR was not enough)
 *	    isymRef		if (bt == btStruct/etc.) OR (bt == btTypedef)
 *	    RNGR		RNGR's are used to describe the array dimensions
 *	    ...			There are as many as there are "tqArray"s in TIR
 *	    RNGR		up to idimMax
 *	    width in bits	if (bit field), width in bits.
 */
#define cAuxMax (4 + idimMax*3)

/* a union of all possible info in the AUX universe */
typedef union {
	TIR	ti;
	int4	isym;
	int4	iss;
	int4	width;
	int4	iaux;
	int4	dn;
	} AUXU, *pAUXU;
#define cbAUXU sizeof(AUXU)
#define auxNil ((pAUXU)0)
#define iauxNil	0L


/* Type Def structure */
typedef struct TDS {
	int4	iss;	/* name of typedef */
	int4	isym;	/* location of type information */
	} TDR, *pTDR;
#define cbTDR	sizeof(TDR)
#define tdNil ((pTDR)0)

/*
 * The following table defines the meaning of each SYM field as
 * a function of the "st". (scD/B == scData OR scBss)
 *
 * Note: the value "isymMac" is used by symbols that have the concept
 * of enclosing a block of related information.	 This value is the
 * isym of the first symbol AFTER the End associated with the primary
 * symbol. For example if a procedure was at isym==90 and had an
 * isymMac==155, the associated end would be at isym==154, and the
 * symbol at 155 would probably (although not necessarily) be the
 * symbol for the next procedure or file.  This allows rapid skipping over
 * internal information of various sorts. "stEnd"s ALWAYS have the
 * isym of the primary symbol that started the block.
 * 

ST		SC	VALUE		INDEX
--------	------	--------	------
stFile		scText	address		isymMac
stLabel		scText	address		---
stGlobal	scD/B	address		iaux
stStatic	scD/B	address		iaux
stParam		scAbs	offset		iaux
stLocal		scAbs	offset		iaux
stProc		scText	address		iaux	(isymMac is first AUX)

stMember	scNil	ordinal		---	(if member of enum)
stMember	scNil	byte offset	iaux	(if member of struct/union)
stMember	scBits	bit offset	iaux	(bit field spec)

stBlock		scText	address		isymMac (text block)
stBlock		scNil	cb		isymMac (struct/union member define)
stBlock		scNil	cMembers	isymMac (enum member define)

stEnd		scText	address		isymStart
stEnd		scNil	-------		isymStart (struct/union/enum)

stTypedef	scNil	-------		iaux
stRegReloc	sc???	value		old register number
stForward	sc???	new address	isym to original symbol

 *
 */
0707070001000312461004440000000000010000011606550454650114100001500000004525cdb/tokens.h /* $Header: tokens.h,v 5.2 86/04/10 19:20:06 peter Exp $ */

/* This file is used as an automatic header for all expression evaluators
 * in the debugger.  This is the ONLY valid place to introduce a new
 * token name!
 */

%token tkNil		/* end of expr */
%token tkBang		/* ! */
%token tkDQuote		/* " */
%token tkHash		/* # */
%token tkDollar		/* $ */
%token tkPercent	/* % */
%token tkAmper		/* & */
%token tkSQuote		/* ' */
%token tkLP		/* ( */
%token tkRP		/* ) */
%token tkStar		/* * */
%token tkPlus		/* + */
%token tkComma		/* , */
%token tkMinus		/* - */
%token tkDot		/* . */
%token tkSlash		/* / */
%token tkColon		/* : */
%token tkSemi		/* ; */
%token tkLAB		/* < */
%token tkAssign		/* = */
%token tkRAB		/* > */
%token tkQuest		/* ? */
%token tkAt		/* @ */
%token tkLSB		/* [ */
%token tkBackSlash	/* \ */
%token tkRSB		/* ] */
%token tkUpArrow	/* ^ */
%token tkUnderScore	/* _ */
%token tkLCB		/* { */
%token tkBar		/* | */
%token tkRCB		/* } */
%token tkTilda		/* ~ */
%token tkAssPlus	/* += */
%token tkAssMinus	/* -= */
%token tkAssMult	/* *= */
%token tkAssDiv		/* /= */
%token tkAssMod		/* %= */
%token tkAssXOR		/* ^= */
%token tkAssBAND	/* &= */
%token tkAssBOR		/* |= */
%token tkAssLeft	/* <<= */
%token tkAssRight	/* >>= */
%token tkLAND		/* && */
%token tkLOR		/* || */
%token tkLE		/* <= */
%token tkGE		/* >= */
%token tkEqual		/* == */
%token tkNotEqual	/* != */
%token tkLShift		/* << */
%token tkRShift		/* >> */
%token tkPtr		/* -> */
%token tkDiv		/* //  for division */
%token tkNumber		/* 0123456789 */
%token tkStr		/* Hi */
%token tkStrConstant	/* "Hi\n" */
%token tkCharConstant	/* '\t' for instance */
%token tkFltConstant	/* .1, 0.1, 1.1, 1., 1e1, etc...... */
%token tkEOE		/* end of expression */
%token tkAdr		/* this is an address */
%token tkSizeof		/* the C sizeof operator */
%token tkInside		/* inside of procedure */
%token tkArg		/* get arg N of proc */
%token tkPlusPlus	/* ++ */
%token tkMinusMinus	/* -- */
%token tkFunc		/* it's a function internal */
%token tkStartComment	/* in C, a '/' followed by a '*' */
%token tkEndComment	/* in C, a '*' followed by a '/' */
%token tkPower

    /* types */
%token tkUnsigned
%token tkChar
%token tkShort
%token tkInt
%token tkLong
%token tkFloat
%token tkDouble
%token tkStruct
%token tkUnion
%token tkEnum
%token tkTypedef
%token tkComplex
%token tkLogical
%token tkOther		/* <Twilight Zone> */
0707070001000312471004440000000000010000011607020454650114100001600000011073cdb/xptrace.h /* $Header: xptrace.h,v 5.8 85/12/21 16:15:09 peter Exp $ */
/* (C) Copyright 1984 Third Eye Software Inc. - All Rights Reserved */

/*
 *
 * The modules xptrace.c and xremote.c implement a simple, ASCII based
 * protocol for controlling a remote debug server.
 *
 * The host is in control of the conversation.  The entire exchange
 * is "host says something", "remote replies".
 *
 * All numbers are hexidecimal and are represented by the characters
 * [0..9,a..f].  The only non-printing character used is "new line"
 * <nl> (012) which is the "end-of-transmission" character.
 *
 * The symbol <pid> is the "process id" of the process in question.
 * It is aggreed upon during the "msgExec" transaction.
 *
 * The remote's messages are of the form:
 *	<status> '|' <pid> '|' <reply value> <nl>
 * The reply value is not always present.
 *
 *	Status		Meaning
 *	------		-------
 * -3	statusNewPid	The pid in the message is the result of an EXEC
 * -2	statusRetry	Re-transmit last message to remote
 * -1	statusPrint	Reply is string destined for command terminal screen
 *  0	statusOk	Execution ok, reply is defined by command last given
 *	> statusOk	(gtr than statusOk) same meanings as "errno" on host.
 *
 *
 * The host's messages are of the general form:
 *	<message identifier> | <pid> | <argument> | (argument> | ... <nl>
 *
 *	Messages from Host
 *	------------------
 *
 *	msgExec '|' <pid> '|' <program name> '|' "<args>" <nl>
 *		The <pid> passed is the host's vote for the process id,
 *		HOWEVER, if the remote returns statusNewPid, that <pid>
 *		will be the one	actually used for all future communications
 *		about this process. If the remote doesn't care, it should
 *		return the same <pid> as was passed by host.
 *		If <pid> is already in use, the remote should infer a
 *		msgQuit on that process.
 *
 *	msgQuit '|' <pid> <nl>
 *		Debugger is done working with process <pid>.
 *
 *	msgWait '|' <pid> <nl>
 *		Wait for process <pid> to do something. (Hit a
 *		breakpoint, die, etc.)  If <pid> == 0, we are waiting
 *		for ANY process to do something.
 *
 *	msgPtrace '|' <pid> '|' <request> '|' <address> '|' <value> <nl>
 *		The meanings, and expected responses, are exactly as
 *		outlined in "ptrace(2)" in the UNIX manual.  Request 9
 *		"single step" is NOT optional!
 *
 *	msgInput  '|' <pid> '|' "any ASCII string NOT containing a <nl>" <nl>
 *		The string is meant to be inserted into the TTY input
 *		queue for the target process. Not all systems allow this.
 *
 *	These next three commands facilitate block data handling.
 *
 *	msgRtoH   '|' <pid> '|' <source address> '|' <count> <nl>
 *		Transfer data FROM remote TO host.  The first field
 *		of the reply is the number of bytes
 *		actually being transfered.  The host will continue
 *		to request the unsent portions.  This allows the
 *		remote to cope with small buffer sizes.
 *
 *	msgHtoR   '|' <pid> '|' <destination address> '|' <count>
 *			'|' <data - two ASCII hex characters per byte> .... <nl>
 *		Transfer data FROM host TO remote.
 *
 *	msgMove   '|' <pid> '|' <destination address>
 *			'|' <source adrress> '|' <count> <nl>
 *		Transfer data WITHIN remote.
 *
 *	msgSignal '|' <pid> '|' <signal number> <nl>
 *		Send signal to a running process.  This is applicable only
 *		when the host is waiting for a response to msgWait.
 *
 *	msgDump   '|' <pid> <nl>
 *		Reply with statusPrint and any useful information in ascii
 *		for debugging DebugServer or its operating system interface.
 *
 *	msgLevel  '|' <pid> '|' <level><nl>
 *		Set debug level of DebugServer in target system.
 */

#define cbMsgMax 256	/* max bytes host OR remote can tx OR rx at one time */
#define chDelim	'|'	/* delimiter for arguments */

/* Maximum number of retires on a transmission */
#define cRetryMax	3

/* messages sent host-to-remote */
#define msgQuit		1
#define msgExec		2
#define msgPtrace	3
#define msgWait		4
#define msgInput	5
#define msgRtoH		6
#define msgHtoR		7
#define msgMove		8
#define msgSignal	9
#define msgDump		10
#define msgLevel	11
#define msgMax		12	/* highest valid message number + 1 */

/* status values - first item in ALL remote-to-host messages */
/* values >0 are assumed to have the same meaning as shown in <errno.h> */
#define statusOk	0
#define statusPrint	-1
#define	statusRetry	-2
#define	statusNewPid	-3

/* return values to WAIT */
#define rvTerminate	1
#define rvBreakpoint	2
#define rvInterrupt	3

/* requests for `ptrace' system call */
#define ptChild	 	0
#define ptReadI	 	1
#define ptReadD	 	2
#define ptReadUser      3
#define ptWriteI	4
#define ptWriteD	5
#define ptWriteUser     6
#define ptResume	7
#define ptTerm	  	8
#define ptSingle	9
0707070001000312501004440000000000010000011607450454650114100001200000130005cdb/cdb.1 .ds CX $Header: cdb.1,v 6.6 86/10/30 12:41:39 peter Exp $
.ds CC Copyright (C) 1984 Third Eye Software, Inc. - All Rights Reserved
.ds TW \v'.25m'\s+2~\s-2\v'-.25m'
.ds ST \v'.25m'*\v'-.25m'
.ds IM \v'.1m'=\v'-.1m'\s-2\h'-.1m'>\h'.1m'\s+2
.ds LE \(<=
.ds LT \s-2<\s+2
.ds GT \s-2>\s+2
.ds CD \s-2CDB\s+2
.TH CDB 1 "30 October 1986"
.SH NAME
cdb \- C program debugger, Version 6.1
.SH SYNOPSIS
\fBcdb\fP [\fIoptions\fP\^] \fIobjectfile\fP
.SH DESCRIPTION
.PP
\*(CD\s-2\*(Tm\s+2 is a debugger for C, FORTRAN and assembly programs.
It provides a controlled environment for their execution.
Depending on the options ordered/installed, \*(CD may be used to debug
single or multiple processes which are native or remote to the
processor that \*(CD is running on.
Not all options are available in all configurations.
.PP
Be forewarned that \*(CD's command set is large and involved
(some would say baroque).
It is often best to do a quick scan of the summary at the end of
this document and then play with the debugger for a while on a program
you are familiar with.
It is possible to do significant work with just the following commands:
\fBb\fP (set breakpoint), \fBc\fP (continue), \fBd\fP (delete break),
\fBe\fP (enter procedure),
\fBr\fP (run program), \fBp\fP (print line of source),
and \fBt\fP (trace stack),
.PP
Before using \*(CD, it is highly recommended that you read the ``Caveats''
section near the end of this document.
It highlights a number of problems that you may encounter.
If the debugger seems to be acting very strangely, read the caveats
again and see if you have accidently stumbled into one of the known items.
.SH OPTIONS
.PP
\fIObjectfile\fP is an executable program file that has had some (or all)
of its component modules compiled for debugging.
The method for doing this varies so please check with your site administrator.
Default values are shown in ( )'s.
.IP "\fB-B\fP \fIN\fP" 17n
Baud rate for remote communications line.
.IP "\fB-C\fP \fIcorefile\fP" 17n
Set core file.
\fICorefile\fP is assumed to be a core image of \fIobjectfile\fP.
.IP "\fB-d\fP \fIdirectory\fP" 17n
Names an alternate directory where files are searched for.
Alternate directories will be searched in the order given.
If a file is not found in an alternate, the current directory is searched.
.IP "\fB-D\fP" 17n
Ignore all currently specified alternate directories.
This option is primarily used inside the \fIdefaults\fP file.
.IP "\fB-e\fP \fIentry\fP" 17n
Specify entry label (main).
.IP "\fB-f \fIN\fP" 17n
Use floating point format conversion N.
See \fIRemote Debugging\fP.
.IP "\fB-L\fP \fI(c|f)\fP" 17n
Set default language code to ``c'' or ``f''ortran (c).
.IP "\fB-m\fP \fIfile\fP" 17n
Default specification file.
See the file \fI/usr/lib/cdb.defs\fP for a full description.
.IP "\fB-p\fP \fIfile\fP" 17n
Startup with command playback from file.
.IP "\fB-P\fP \fIpid\fP" 17n
Attach to process with process id \fIpid\fP.
.IP "\fB-r\fP \fIfile\fP" 17n
Startup with commands recording to file.
.IP "\fB-R\fP \fIfile\fP" 17n
Startup with output recording to file.
.IP "\fB-S\fP" 17n
Forces \*(CD to do stty's on each target process start and stop.
.IP "\fB-t\fP \fIdevice\fP" 17n
specify device for remote debug connection.
.IP "\fBTtext\fP \fIoffset\fP" 17n
Offset for all text addresses.
See \fIRemote Debugging\fP.
.IP "\fBTdata\fP \fIoffset\fP" 17n
Offset for all data addresses.
See \fIRemote Debugging\fP.
.IP "\fBW\fP" 17n
Use windows interface.
This is ignored if your system does not have the windowing option installed.
.PP
The following options are generally used while debugging \*(CD or for
doing automatic demonstrations:
.IP "\fB-u\fP \fIhex address\fP" 17n
Override compiled in address of ``u.'' in kernel space.
.IP "\fB-U\fP \fIhex offset\fP" 17n
Override compiled in offset of ``u_ar0'' in ``u.''.
.IP "\fB-x\fP \fIlevel\fP" 17n
Set internal debugging printout level.
.IP "\fB-X\fP" 17n
Show all remote communications transactions.
.IP "\fB-Z\fP \fIN\fP" 17n
Set demo timer to N seconds.
.SH "Starting \*(CD"
.PP
When you first invoke the debugger (e.g. ``cdb foo''),
it looks for two files to playback for initializations.
These are, in order, ``~/.cdbrc'' and ``foo.rc''.
The first contains anything you \fIalways\fP want done for you
in the debugger (e.g. changing the output radix for addresses).
The second is specific to the program you are debugging.
It normally is created automatically on exit from \*(CD
by answering ``s'' to the ``Quit'' prompt.
.SH CONVENTIONS
.sp 1
.PP
.SM "IMPORTANT:"
\*(CD supports the concepts of \fIcurrent-process\fP, \fIcurrent-file\fP,
\fIcurrent-procedure\fP and \fIcurrent-line\fP.
These are a function of what you have been
\fIviewing\fP
most recently.
Many commands use these for defaults.
It is important to keep this in mind when deciding how a command will default
in any particular situation.
.PP
In the descriptions, the following notational conventions are used:
.RS 3n
.IP "(A | B | C)" 17n
one of A or B or C.
.IP "\fIfile\fP" 17n
a file name.
.IP "\fIproc\fP" 17n
a procedure name.
.IP "\fInumber\fP" 17n
a specific number (e.g. 9, \fInot\fP 4+5).
.IP "\fIline\fP" 17n
a line number (default is current line).
.IP "\fIstack\fP" 17n
a stack depth, as indicated by the \fBt\fP command.
.IP "\fIexp\fP" 17n
any expression (defaults to 1 unless otherwise stated).
.RE
.sp 1
.PP
\fBExpressions\fP
.PP
\fBExpressions\fP may be composed of any combination of variables,
constants and C operators.
The following differences and exceptions should be noted:
.RS 3n
.IP "1." 3n
Do \fInot\fP type a <cr> in the middle of an expression.
.IP "2."
If there is no active target process and no core file, you will only
be able to do expressions containing constants.
.IP "3."
Use ``//'' for Division, instead of ``/''.
.IP "4."
If the first expression begins with ``\-'', use ( ) around it.
This distinguishes it from the ``\-'' command.
.RE
.sp 1
.PP
\fBProcedure Calls\fP
.PP
\fBProcedures\fP may be invoked from the command line.
Procedures are handled from within the expression evaluator, therefore
you can use them in expressions.
For example:
.sp .5
.br
                 foo = AddArgs(1, 2) * 3;
.PP
\fBCaveats for procedure calls from the command line:\fP
.RS 3n
.IP "1." 4n
Procedures that return more information than a \fIlong\fP
are generally not handled correctly.
.IP "2."
Any breakpoints encountered during command line procedure invocation
will be handled as usual.
.RE
.PP
You may do a procedure call to any \fItext label\fP that is
in your \fIobjectfile\fP.
For example, let's assume that you reference \fIprintf\fP in your program.
The code for this is in the target; therefore you could say, from the command
line:
.sp .5
.br
                 printf("Hello, %s!\\n", "world");
.PP
By the way, on many systems, you have to print a newline before any
of the information appears.
If you wonder what procedures are available,
do a list procedures command (``l p *'').
If you want to have some library routines available for debugging,
but they aren't referenced anywhere in your code (and therefore not loaded),
you can add a phony procedure call that references them.
It is not necessary to have ``correct calls'', just ``foo()'' will work
fine, since you aren't actually going to execute these statements from
within your code.
.sp 1
.PP
\fBVariables\fP
.PP
\fBVariable names\fP are exactly what you named them.
Case sensitivity is controlled by the \fBZ\fP command.
Note: some symbol table formats cause cropping of variable and procedure
names to 7 or 8 characters.
You can still type the whole name if you wish, but the match is done only
on the characters present in the symbol table.
.PP
If you are interested in the value of some variable \fIfoo\fP, there
are a number of ways of getting at it, depending on where and what it is.
The following describes the search performed for each name style.
.IP "foo" 17n
Performs a scope search, starting at the ``stop point''
in the current procedure and proceeding outwards.
Locals, local statics and parameters are checked,
then file statics, then globals and finally special variables.
.IP "Bar#foo" 17n
Search the stack for the first instance of procedure ``Bar''.
If found, use the frame's ``stop point'' to perform a scope search for ``foo''.
.IP "3#foo" 17n
Specifies that the frame that is at \fIstack 3\fP is to be used
for the scope search.
This is \fIvery\fP useful if you are debugging a recursive procedure
and there are multiple instances of it on the stack.
Also look at the \fBe\fP command with the stack depth enter option.
.IP ":foo" 17n
Search for a global named ``foo''.
.IP "$foo" 17n
Search the list of special variables for ``$foo''.
(See explanation below.)
.IP "\fIproc\fP#\fIline\fP" 17n
Produces the \fImemory address\fP of the code associated with the
given line number in the given procedure.
.IP "#\fIline\fP" 17n
Produces the \fImemory address\fP of the code associated with the
given line number in the current file.
.IP "\s+8.\s-8" 17n
Dot is the \fIname\fP for the last thing you looked at (see \fIData\fP below).
It has the same \fItype\fP that you viewed it as.
This means that if you look at a \fIlong\fP as a \fIchar\fP,
then ``.'' will be considered to be a char.
This is useful for functioning on things in weird ways, like
changing the second highest byte of a long without changing the
rest of the long.
Dot may be modified, used in another expression, etc.
.SM "NOTE WELL\c"
:  The dot in \*(CD is \fInot\fP the same as the dot
in other debuggers in which it is just a number.
If you use it, it will be dereferenced like any other name.
If you say ``.+30'', it will perform whatever arithmetic is appropriate
to the type of dot.
.PP
\fBSpecial variables\fP are names for things that are not normally directly
accessible, either because they are machine registers, live in the
process' user structure, or live in the debugger's address space.
If you simply type a name (e.g. ``result''), a normal scope search
will be performed and, assuming there was no variable in-scope
called ``result'', the list of \fIexisting\fP special variables
is searched.
If you preface a name with a ``$'' then (1) only the special variables
will be searched and (2) if there is no special with the
given name, \fIone will be created\fP.
.PP
User special variables are of the same type as the last expression they
were assigned.
For example, saying ``$mumble=3*4'' will create special variable $mumble
and assign to it the value of 12 and make it type \fIint\fP.
These variables may be used just like any other variables,
\fIexcept\fP you may not meaningfully take the address of them.
.PP
Predefined special variables include:
.IP "r0, pc, sp, etc." 17n
These are the names for the registers, the stack pointer, etc.
To find which names are available on your system, list the registers
with the ``l r'' command.
All registers act as integers of the correct size for the register.
It goes without saying (but I will anyway) that messing with the
contents of registers when you are debugging high-level code can
produce interesting results.
.IP "result" 17n
This can be used for checking the return value of a procedure.
It is of type \fIlong\fP and maps to the register most commonly
used for returning integers.
On most systems, this is also the register used for returning
pointers to things.
This is value is \fInot\fP guaranteed to be correct.
It is supplied only as an aid.
.PP
There are a number system defined variables.
Modifying their values will change the way the debugger operates.
The currently defined ones are:
.IP "SIGNAL" 17n
The signal number that will be passed back to the target.
It will be 0 if that signal is masked by the signal handling code.
.IP "R_SIGNAL" 17n
The signal number that caused the current process to stop.
.IP "STRICT" 17n
Default value is 1.
If zero, it allows you to make ``old style'' references to struct
and union members.
E.g. If you type ``foo.xx'', but there is no field named ``xx'' connected
with foo, \*(CD will start at the top of the current file and look
for the first element with name ``xx'' and use its relative offset and type.
.IP "DELTA" 17n
This tells the disassembler the farthest distance you can be from the
nearest label or global and still get things in the form ``foo+0x2bc''.
.PP
System specials beginning with an ``_'' are not normally listed.
They represent the internal state of the debugger.
To see them all, type "l s _".
.IP "_LANGUAGE" 17n
Shows which expression evaluator is in use.
-1 indicates auto-select based on type of current file.
0 indicates C.
1 indicates FORTRAN.
.IP "_COMM" 17n
If non-zero, it causes massive quantities of information about the
remote communications link to spew onto the screen.
.IP "_CACHE" 17n
If non-zero, this causes \*(CD to use a cache for stack addresses.
This may cause remote debugging to react much more quickly.
.PP
The following specials are Read Only.
.IP "_PROCESS" 17n
The \*(CD defined process number of the current process.
.IP "_FILE" 17n
The name of the current file.
.IP "_PROCEDURE" 17n
The name of the current procedure.
.IP "_LINE" 17n
The current line number.
.IP "_BREAK" 17n
The current breakpoint number.
.SH COMMANDS
.PP
\*(CD has a large number of commands for viewing and manipulating the
program being debugged.
They are explained below, grouped by functional similarity.
.PP
Defaults are defined for virtually all arguments.
An argument is optional unless explicitly stated otherwise.
.SH Viewing Commands
.PP
The \fBe\fP command (enter) is used to show or change your current
\fIviewing\fP location in the code.
.IP "\fBe\fP" 17n
Show current file, procedure and line number. (e.g. test.c:PrintLine:28)
.IP "\fBe\fP (\fIproc\fP | \fIfile\fP)" 17n
Enter \fIproc\fP or \fIfile\fP and print first line. 
For procedures, this is the first executable line or instruction.
.IP "\fIstack\fP \fBe\fP" 17n
Go to the call site referenced by \fIstack\fP.
This form also sets a default depth for displaying locals and parameters.
This means that when you are looking at one instance of a recursively
called routine, the values are correct for the frame at the given
stack depth.
\fBL\fP is a synonym for \fB0e\fP.
I.e. the place you are stopped at in the procedure at top-of-stack.
.IP "\fBl\fP (a | b | d | f | g | p | r | s | z) \fIstring\fP" 17n
List a-assertions, b-breakpoints, d-directories, f-files, g-globals,
p-procedures, r-registers, s-special variables, z-zignals (signals).
If \fIstring\fP is present, only those things with the same initial
characters are listed (try it).
.IP "\fBl\fP \fIproc\fP" 17n
List all locals and parameters of the current-procedure (or \fIproc\fP).
Data is displayed using the /n format.
.IP "\fInumber\fP \fBp\fP \fIexp\fP" 17n
Print 1 (or \fIexp\fP) lines starting at the current (or \fInumber\fP) line.
The current viewing position is set to the last line printed.
.IP "\fInumber\fP" 17n
Print line \fInumber\fP in the current file.
This is a short form of the previous command.
.IP "\fB+\fP\fIexp\fP" 17n
Move to \fIexp\fP (default 1) lines after current line.
.IP "\fB\-\fP\fIexp\fP" 17n
Move to \fIexp\fP (default 1) lines before current line.
.IP "\fIline\fP \fBw\fP \fIexp\fP" 17n
.IP "\fIline\fP \fBW\fP \fIexp\fP" 17n
Print a window of text, \fIexp\fP (default 11) lines big,
centered about the current line (or \fIline\fP).
The current line will be indicated by a ``>'' in the left most print position.
``W'' is the same as ``w'', but the default is 21.
The current viewing position is unchanged.
.SH Stack
.IP "\fIexp\fP \fBt\fP" 17n
.IP "\fIexp\fP \fBT\fP" 17n
Trace stack for first \fIexp\fP levels (default 20).
``T'' is the same as \fBt\fP, but locals are also displayed
using format \fB/n\fP.
(See below).
.SH Data
.IP "\fIexp\fP" 17n
If the beginning of \fIexp\fP does not look like a command,
it is handled as if you had typed ``\fIexp\fP\fB/\fPn''.
Be careful with one letter variable names, as
they may be taken as a \fIcommand\fP rather than as a \fIvariable\fP.
If an expression begins with a variable that might be mistaken for a
command, just eliminate any white space between the variable and the
first operator.
Use ``k=\ \ 9'' instead of ``k\ \ =\ \ 9''.
Use ``p/n'' instead of just ``p''.
.IP "\fIexp\fP \fB/\fP \fIformat\fP" 17n
Show the value of \fIexp\fP using \fIformat\fP.
E.g. ``foo/x'' would
print the contents of ``foo'' as an integer, in hexadecimal.
.IP "\fIexp\fP \fB@\fP \fIformat\fP" 17n
Show the address of \fIexp\fP using \fIformat\fP.
E.g. ``foo@o'' would print the address of
``foo'' in octal.
.IP "\s+8\fB\v'0.2m'^\v'-0.2m'\fP\s0 \fIformat\fP" 17n
Back up to preceding memory location (based on size of last thing displayed).
Use previous format or \fIformat\fP, if supplied.
This normally doesn't work very well if you are displaying instructions
on a machine with variable length instructions.
.PP
A \fIformat\fP is of the form \fIcount\fP X \fIsize\fP,
where \fIcount\fP is the number of times to apply the format style ``X''.
\fISize\fP indicates the number of bytes to be formated.
Both count and size must be \fInumbers\fP.
E.g. ``foo/4x2'' would print, starting at ``foo'', four 2-byte numbers in hex.
.PP
There are some alternate notations for the sizes of things:
.RS 3n
.IP "b"
1 byte.
.IP "s"
2 bytes (short).
.IP "l"
4 bytes (long).
.RE
.PP
These are appended to the \fIstyle\fP.
E.g. ``foo/xb'' prints a hex byte.
The formats which print numbers allow an upper case character to 
be synonymous with appending the letter ``l''.
(e.g. ``O'' will print in long octal, as will ``ol'')
The following formats are available:
.sp 1
.RS 3n
.IP "n" 17n
Use the ``normal'' format, based on type.
This is what you get if you don't specify a format.
.IP "t"
Show what ``type'' \*(CD thinks this variable (procedure) is.
.IP "a"
Print a string using \fIexp\fP as the address of the first byte.
This will print up to the first null character or 128 characters,
whichever occurs first.
The \fIsize\fP value can be used to force printing of a given
number of bytes, regardless of the occurrence of null characters.
.IP "s"
Print a string using \fIexp\fP as the address of a pointer to the first byte.
Same as saying ``*\fIexp\fP/a''.
.IP "p"
Print the name of the procedure containing address \fIexp\fP,
along with the file name and the source line or instruction that address
maps to.
.IP "i"
Using the \fIexp\fP as an address, disassemble a machine instruction.
.IP "I"
Using the \fIexp\fP as an address, disassemble a machine instruction.
If the address maps evenly to a line number in the source,
print that first.
This is good for looking at what the compiler generated for a line of source.
.IP "S"
Do a formated dump of a structure.
This is the default for things of type struct.
This format is not available on all systems.
See the note below.
.IP "d"
Print in decimal.
.IP "u"
Print in unsigned decimal.
.IP "o"
Print in octal.
.IP "x"
Print in hexadecimal.
.IP "c"
Print \fIexp\fP as a character.
.IP "e"
Print in ``e'' floating point notation. See note below. (Reference printf(3).)
.IP "f"
Print in ``f'' floating point notation. See note below.
.IP "g"
Print in ``g'' floating point notation. (Default for float & double.)
.PD
.RE
.PP
Note:
When using the ``e'' or ``f'' formats, the size specifies the precision desired.
If unspecified, the system default is used.
.PP
Note: When \*(CD dumps a struct (or a union) it uses a straight forward
formatting algorithm.
For large, complex or bizarre structs, this may not be the best way of
doing things.
Just before \*(CD uses its own method, it checks to see if you
have another way you would like it to be done.
If you have a type called ``struct FOO'',
and you print something of that type,
and \*(CD finds that there
is a procedure in the target process by the name ``_FOO'',
it will invoke that procedure, passing it two arguments:
1) a pointer to the struct and 2) the \fIsize\fP parameter (default
value is -1, user passable values are 0..intMax).
For example, if ``fooFirst'' was a node in a tree, you might
type ``fooFirst/n2'' (Remember, for structs ``n'' is the same as ``S'').
The routine ``_FOO'' might then dump the fields of fooFirst and its
first two levels of children (or whatever is appropriate).
This feature may be overridden by using the ``N'' format,
instead of ``S'' or ``n''.
.SH Process Control Commands
.IP "\fBr\fP \fIarguments\fP" 17n
Run a new target process with \fIarguments\fP.
If a process already exists, terminate it.
If no \fIarguments\fP are given, the last ones given are used again.
\fIArguments\fP may contain ``<'' and ``>'' for redirecting stdin and stdout.
.P
In a multi-process configuration, this will cause re-running of the
current process \fIif and only if\fP it is a direct child of \*(CD.
.IP "\fBR\fP" 17n
Run a new target \- set args to nil.
.IP "\fBk\fP" 17n
Kill the current process.
.IP "\fIexp\fP \fBc\fP \fIline\fP" 17n
.PD .1v
.IP "\fIexp\fP \fBC\fP \fIline\fP" 17n
Continue after a breakpoint or an interrupt.
If \fIexp\fP is given, the current breakpoint will have its count
set to this value.
If \fIline\fP is given, a temporary breakpoint is set at that line number.
(See next section).
``C'' unconditionally continues with the signal that stopped the process,
``c'' continues with or without the signal, based on the current
signal handling specified for that signal by the \fBz\fP ``zignal'' command.
.PD
.IP "\fIexp\fP \fBcU\fP" 17n
If a either continue command is immediately followed by one of `u' or `U',
it causes an uplevel breakpoint to be set.
For example, ``cU'' is identical to ``bU;c'', and ``2 Cu'' is identicaal
to ``2 bu;C''.
This is useful if you have accidentally single stepped into a procedure
you meant to step over, or you want execution to proceed to some
place further up the stack.
.IP "\fInumber\fP \fBP\fP \fIsubcommand\fP" 17n
This command is used exclusively during multiprocess debugging.
.br
If no number or options are given, list the process slots in use.
If a number is supplied, that process becomes the \fIcurrent process\fP.
If a subcommand is supplied, it is applied to the current process.
For example ``1 P s 2'' would make process 1 the active
process and send it an interrupt (signal 2).
.RS 17n
.IP "\fBb\fP" 10n
Toggle breakpoint inheritance after forking.
If true (1), children of the current process will inherit all
breakpoints set at the time of the fork.
.IP "\fBc\fP" 10n
Toggle flag causing children to be debugged.
If true (1), children of the current process will be added to the list
of processes under control of \*(CD.
.IP "\fBe\fP" 10n
Toggle flag causing children to stop upon execution of the \fIexec\fP
system call.
This acts as if a breakpoint were encountered at the first instruction
of routine ``main''.
.IP "\fBf\fP" 10n
Toggle flag causing children to stop upon execution of the \fIfork\fP
system call.
This acts as if a breakpoint were encountered immediately following
the fork.
This will normally mean you are in the middle of the library routine ``fork''
from /lib/libc.a.
.IP "\fBs\fP \fInumber\fP" 10n
Send signal \fInumber\fP to the current process.
.IP "\fBE\fP \fIoptions\fP" 10n
Add a new top level process.
The options may be any of those permitted when invoking \*(CD from the shell.
.IP "\fBF\fP \fInumber\fP" 10n
Free process to continue running.
Prior to detaching, all breakpoints are pulled.
.IP "\fBP\fP \fInumber\fP" 10n
Attach to the existing process whose process id is \fInumber\fP.
.RE
.SH Signal Handling
\*(CD catches all signals bound for the target process.
This is a function of the \fIptrace(2)\fP mechanism.
For many signals, this is a reasonable thing to do \- most processes
are not set up to handle segmentation errors, etc.
However, some processes do quite a bit with signals and the constant
need to continue from a signal catch can be a pain.
.IP "\fIexp\fP \fBz\fP [irsQc [\fIcmds\fP]]" 20n
Maintains the ``zignal'' (signal) handling table.
\fIExp\fP is a valid signal number (default is the ``current'' signal).
The options toggle the state of the appropriate flag \- i to ignore,
r to report and s to stop.
If the ``Q'' is present, the new state of the signal is \fInot\fP printed.
If the ``c'' flag is present, then the signal's command list is set
so that they are executed every time the signal is encountered.
If no commands are supplied, any existing commands are removed.
If you wish to continue from a signal that has commands, you must supply
the ``c'' command in the command list of the signal.
.PP
Do an ``l z'' command to list the current handling of signals.
For Example: assuming a start up state of (\fIdon't stop\fP,
\fIdon't ignore\fP, \fIdon't report\fP),
the command ``14z sr'' would set the alarm clock signal
to \fIstop\fP (but still \fIdon't ignore\fP) and
\fIreport\fP that it had occurred.
Doing ``14z sr'' again would toggle these flags back to the other state.
.PP
.SM "\fIWARNING\fP\c"
: Do not mess around with the ``breakpoint'' signal!
If you change its state, you had better know what you are doing.
.PD
.SH Breakpoint Commands
.PP
\*(CD provides a number of commands for setting and removing breakpoints.
Other than its address, a breakpoint has two items associated with it:
.IP "count" 17n
The number of times it will be encountered prior to recognition.
If the count is negative, the break will be removed after recognition.
Once a count goes to 1, it will stay there until explicitly
set to a different value by a \fIc\fP command.
A count of 0 is used by the single-step mechanism
and means that the break is to be removed the next time the process
stops for any reason whatsoever.
Currently the count field can only be set when using the ``c'' command
to continue from a breakpoint.
.IP "commands" 17n
Actions to be taken upon recognition.
These are separated by ``;'' and may be enclosed in {\ }'s to
delimit the list given to the breakpoint.
If the first character is anything other than ``{'', the rest of the line is
given to the breakpoint as commands.
.PP
The breakpoint commands are:
.IP "\fBD\fP" 17n
Delete all breakpoints.
.ne 6v
.IP "\fBB\fP" 17n
List breakpoints.
Breakpoints are shown in this format:
.ne 6v
   procedure:ln   count   commands
   0 foo:12         \-1    <t;i/D>
   1 bar:29          5    <Q;if *argv==\-1 {"Trashed argv again"}{c}>
.PP
The number on the left is an index number for use with the \fId\fP command.
.PD
.IP "\fIline\fP \fBb\fP \fIcmds\fP" 17n
Set breakpoint at a source line.
When the breakpoint is hit, commands are executed.
If immediate continuation is desired, finish the
command list with ``c'' (see 1 in ``B'' example above).
.PP
An example: let's say you want to set a break in some file other than
where you are at the moment.
First use the ``e'' command to get you to the right file or procedure.
Look around for the place you want to put the break (using searches, or
just printing the lines).
Once you are there, you can just say ``b'' to set a break on that line.
.PP
See the warning in the
.SM CAVEATS
section.
.IP "\fInumber\fP \fBd\fP" 17n
Delete breakpoint.
If no number is given, then
it will attempt to delete a breakpoint at the current line.
If there is no such break, an ``l b'' command will be executed.
.IP "\fIexp\fP \fBbi\fP" 17n
Set a breakpoint on an instruction.
The expression may be an legal expression, especially one involving
procedure names or other text labels.
In no expression is given, then the address of last thing you looked at with
the ``/i'' or ``/I'' display mode will be used.
E.g. ``printf+0x12 bi'' would set a break 18 bytes into procedure printf.
.PP
In the following commands, if the second character is made upper case
(e.g. \fBbU\fP instead of \fBbu\fP) then the breakpoint will be
temporary instead of permanent.
.PD
.IP "\fIstack\fP \fBbu\fP \fIcmds\fP" 17n
.PD .1v
.IP "\fIstack\fP \fBbU\fP \fIcmds\fP" 17n
Set an up-level breakpoint.
The break is set \fIimmediately\fP after the return to the specified level.
A very common sequence after accidentally single stepping into a procedure
is ``bU<nl>c'', i.e. set a temporary, up-level break and continue.
The command ``cU'' accomplishes the same thing.
.PD
.IP "\fIstack\fP \fBbb\fP \fIcmds\fP" 17n
.PD .1v
.IP "\fIstack\fP \fBbB\fP \fIcmds\fP" 17n
Set a breakpoint at beginning of procedure.
If \fIstack\fP is missing, then the current procedure is used.
.PD
.IP "\fIstack\fP \fBbx\fP \fIcmds\fP" 17n
.PD .1v
.IP "\fIstack\fP \fBbX\fP \fIcmds\fP" 17n
Set a breakpoint at procedure exit.
If \fIstack\fP is missing, then the current procedure is used.
This is at a point such that \fIall\fP returns of any kind will go through it.
(This is somewhat machine dependent.  
It does not work well on \s-2VAX\s+2en or
CCI Power 6/32's due to their method of returning from procedures.)
.sp .5
.PP
The next few commands, while not strictly part of the breakpoint group,
are used almost exclusively in the command lists of breakpoints.
.sp .5
.IP "\fBif\fP \fIexp\fP {\fIcommands\fP}{\fIcommands\fP}" 17n
Conditional command execution.
If \fIexp\fP evaluates to a non-zero value, the first group of commands
will be executed, else the second group, if present.
This command is nestable.
.IP "\fBg\fP \fIlinenumber\fP" 17n
Goto the \fIlinenumber\fP.
This changes the program counter so that \fIlinenumber\fP is the next
execution point.
.IP "\fBQ\fP" 17n
The ``Quiet'' command.
If this appears as the first command in a breakpoint's command list,
the normal announcement of (\fIprocedure:linenumber:  textextext\fP)
is not made.
This allows quiet checks of variables, etc. to be made without
cluttering up the screen with unwanted stuff.
.TP 17n
\fB"\fP\fIany string you like\fP\fB"\fP
Prints the string.
The string may have the standard
.SM UNIX
character escapes in it.
This command can be useful for commenting things in breakpoint commands.
.SH "Single Stepping"
.PP
Single Stepping is normally done at the
.SM STATEMENT
level.
.IP "\fIexp\fP \fBs\fP" 17n
Single step \fIexp\fP (default is 1) statements.
Successive <cr>'s will repeat with a count of 1.
If you accidently step down into a procedure you don't care about,
use the ``cU'' command to set a temporary up-level break and then continue
.IP "\fIexp\fP \fBS\fP" 17n
Single step \- like ``s'', but treat procedure calls as a
normal statements (don't follow them down).
.sp .3
.IP "\fBsi\fP and \fBSi\fP" 17n
These are similar to the statement single step commands, but
cause the process to only advance by one machine instruction.
Furthermore, the stop-position is shown as a disassembled instruction,
not as a statement.
.SH Assertions
Assertions (a slight misnomer) are lists of commands that are executed
\fIbefore every statement\fP.
This means that if there is even one active assertion, the program
will be automatically single stepped.
Translation: it will run very slowly.
.P
A primary use for assertions is tracking down those nasty bugs
involving someone stepping on a global (or similar joys).
Some examples will follow the command descriptions.
.IP "\fBa\fP \fIcmds\fP" 17n
Create a new assertion with the given command list.
.IP "\fIexp\fP \fBa (a | d | s)\fP" 17n
Modify assertion numbered \fIexp\fP: a-activate it, d-delete it, s-suspend it.
Suspended assertions continue to exist, but are not ``in use''.
.IP "\fBA (a | s)\fP" 17n
Set the overall state of the assertions mechanism: a-activate it, s-suspend it.
.IP "\fIexp\fP \fBx\fP" 17n
Force an exit from the assertion mode.
If no expression is present, or if it evaluates to 0, exit immediately, else
finish executing the current assertion.
See the example below.
I.e. if any assertion executes an ``x'' command, the program will be stopped
and the assertion doing the ``x'' will be identified.
.P
A useful assertion might be:
.br
.sp .5
       a if (foo!=$foo) {$foo=foo;foo/d;if (foo>9) {x}}
.PP
This command will create an assertion to report the changing value of
some global (foo), and stop if it ever exceeds some value.
It uses a debugger special variable to keep track of the old value of foo.
.PP
Another example might be:
.PP
                 \fBa\fP L;if (foo > (bar\-9)*10) {A;1 x;c}{bar \-= 10}
.PP
This assertion prints the line about to be executed, then checks the condition.
If it is false, bar is decremented by 10.
If it is true, assertions are suspended, assertion mode is exited, and
the program continues at normal speed.
Without the number before the ``x'' command, the ``c'' command would not have
been seen.
.SH Searching Commands
.IP "\fB/\fP\fIstring\fP" 17n
Search forwards through the current file,
from the line after the current line, for \fIstring\fP.
.IP "\fB?\fP\fIstring\fP" 17n
Search backwards for \fIstring\fP, from the line before the current line.
.PP
NOTE: Searches wrap around begin/end of file and obey the current
case sensitivity setting (see Miscellaneous)..
If a string is not given, the previous one is used.
Under BSD 4.2, full regular expressions are supported.
Wild cards will be available soon for System V.
.SH Record and Playback Commands
.PP
\*(CD contains a record-and-playback feature to help recreate program states.
This is particularly useful for bugs requiring long setups.
.PP
The commands are:
.IP "\fB>\fP \fIfile\fP" 17n
Set command recordfile to \fIfile\fP and turn command recording on.
.IP "\fB>\fP (t | f | c)" 17n
Turn command recording on (t) or off (f).
Close command recording file (c).
If no argument, give current status.
.IP "\fB>>\fP \fIfile\fP" 17n
Set screen output recordfile to \fIfile\fP and
turn screen output recording on.
.IP "\fB>>\fP (t | f | c)"  17n
Turn screen output recording on (t) or off (f).
Close screen output recording file (c).
If no argument, state what is going on.
.IP "\fB<\fP \fIfile\fP" 17n
Start command playback from \fIfile\fP.
.IP "\fB<<\fP \fIfile\fP" 17n
Start command playback from \fIfile\fP,
using the single-stepping feature of playback.
.PP
Any line beginning with ``>'' or ``<'' will NOT be placed in the current
record file.  This can be overridden by simply beginning the line with a space.
.PP
Although an attempt has been made to do things reasonably, it IS possible
to fake out the recording mechanism.  Be particularly careful about trying to
playback from a file currently open for recording or vice versa \- strange
things may happen.
.SH "History Commands"
\*(CD has a simple history mechanism that remembers the last 20 commands.
This can be useful for re-examining long expressions, etc.
.IP "\fBhistory\fP or \fBh\fP" 17n
Print the existing history.
.IP "\fB##\fP" 17n
Re-execute the last command.
.IP "\fB#\fP \fInumber\fP" 17n
Re-execute the specified command.
.IP "\fB#\fP \fIstring\fP" 17n
Re-execute the command which starts with the given string.
.IP "\fB%\fP \fItarget\fP" 17n
This is similar to \fB#\fP, but passes the specified command to a
simple line editor.
Directions for its use are available upon invocation.
.IP "\fB%%\fP" 17n
Edit the last command.
.SH Miscellaneous Commands
.IP "<cr>" 17n
(carriage return) will attempt to repeat the last
command, possibly with an appropriate increment.
.IP "\fB\s+8\v'0.2m'^\v'-0.2m'\s0D\fP" 17n
(control-D) like <cr>, but does it 10 times.
.IP "\fB!\fP \fIcommand-line\fP" 17n
Invokes a shell.
If commands are present, they are executed and the shell
will return immediately, otherwise the shell returns when exited.
.TP
\fBf "\fP\fIprintf-style-format\fP\fB"\fP
Set address printing format, using printf(3) style formating specification.
If there is no argument, this defaults to ``%#lx'', which prints 
the address in long hex.
All addresses are treated as if they are \fIlong\fP,
so you should handle all 4 bytes to get something meaningful.
The intent of this is for people who would rather see memory addresses
in decimal or octal or ??.
.IP "\fBF\fP" 17n
Find and fix bug \- just what you've been looking for.
.IP "\fBI\fP" 17n
Prints out information about the state of \*(CD.
.IP "\fBq\fP" 17n
Quit.
Answers to the prompt are no (default), save or yes.
``n'' will leave you in \*(CD, ``y'' will exit, and
``s'' will save breakpoints and assertions and then exit.
If the program you are debugging is ``foo'', the save file will be ``foo.rc''.
.IP "\fBZ\fP" 17n
Toggle case sensitivity in searches.
This affects everything(!) \- file names, procedure
names, variables and string searches!
(\*(CD starts out as
.SM NOT
case sensitive.)
.SH FILES
a.out, core, *.c
.SH SEE\ ALSO
ptrace(2), a.out(5), core(5).
.SH DIAGNOSTICS
Most errors cause a reasonably accurate message to be given.
.SH CAVEATS
.PP
1.  WARNING!  If you are using macros that take arguments,
\fIdo not\fP break the argument list with a new line \fIduring invocation\fP!
The preprocessor (cpp) used by the compiler (cc) will generate
the correct expansion, but \fBall line numbers for the rest
of the file will be off by 1!\fP
This will cause \*(CD to report the wrong location in the code.
This is a preprocessor problem and will affect \fIall\fP source level debuggers.
.PP
2.  The debugger depends on the symbol table for information about
how machine instructions map to lines.
Most C compilers only issue line symbols at the end of each
statement or line, \fIwhichever is greater.\fP
This means that if you are in the habit of saying ``a = 0; b = 1;'' on one line,
the only way to put a break \fIafter\fP the assignment to ``a'' and \fIbefore\fP
the one to ``b'', is to use the disassembler to spot the right location
and the use the \fBbi\fP command.
.PP
3.  Another ramification of this is that multi-line statements
(e.g. if's with a new-line in the middle of the condition)
only have a line symbol generated at the
\fIend\fP of the list of conditions!
If you try to set a break on any but the \fIlast\fP line of this statement, the
break may actually be set
\s-2\fION THE PRECEDING STATEMENT\fP\s+2!!!!
You can tell when this happens, because \*(CD will tell you
what line it really set the break on and it is different from what you
expected.
This does not happen on all systems (BSD 4.2 seems to be immune to it).
.PP
4.  Some C ``statements'' do not put the code where you would expect it.
For example, assume:
.br
    99: for (i=0; i<9; i++) {
   100:     foo(i);
   101: }
.br
A breakpoint placed on line 99 will be hit only \fIonce\fP on most systems.
The code for incrementing is placed at line 101!
Each system is a little different and you will have to get used to what
your particular complier does.
A good way of finding out what will happen is to use single stepping
and see what order it prints out the lines in.
.PP
5.  On some systems, if \*(CD is run on a shared-text file that is
currently being executed by someone else, interesting things may happen.
If you set breakpoints, when you run the program you will get an
interesting (and obscure) message.
This is often \fI``I/O error - cannot write location 0x1234''\fP.
If the other person starts running the object file while you are debugging,
they and you may have some interesting interactions (all QUITE obscure).
.PP
6.  The output of \fByacc\fP (y.tab.c) has line number information
in it that will drive \*(CD nuts.
Removal of these lines fixes the problem, but makes
it more difficult to find compiler error locations in the original ``.y'' file.
.PP
7.  The Green Hills Software's C does some
optimization even when the "-O" flag is not given on the compile line.
This can cause variables to appear to have strange values.
To defeat this optimization, your compile line should contian
"-g -X18 -Dregister=".
This tells the compiler to not put anything into registers that you
don't tell it to put there (X18) and that all register declarations
should be eaten by the preprocessor.
.PP
8.  If you force an interrupt (by typing ^C or DEL) while the program
is executing a system call, you may encounter problems of various sorts,
depending on what type of system you have.
Under System V, the system call is \fInot\fP restarted and,
when you continue, the program may very well abort due to an error
return from the system call.
.PP
Under BSD 4.2, the system call is \fIalways\fP restarted for you.
Although this is generally desirable, it does cause a problem with
``procedure calls from the command line''.
What happens is that \*(CD pushes the arguments onto the stack,
simulates a call to the desired procedure and continues the target process.
Unfortuantely, the system puts the process right back into the interrupted
system call!
This often happens when you are sitting at an input prompt (a read) and
type an interrupt.
One way around this is to have a phony command that you can put a
breakpoint on.
Then, when you need to talk to \*(CD, you just type that command and you
encounter the breakpoint in a ``clean'' state.
.PP
9.  String constants are stored in a magic buffer in the file
that is loaded with your program by using ``-lcdb''
(``-lg'' on some systems).
\*(CD starts storing strings at the beginning of this buffer, and
moves along as more assigns are made.
If \*(CD reaches the end of this buffer, it will go back and
reuse the buffer from the beginning.
In general this shouldn't cause any problems, BUT if you are using
very long strings \fIor\fP you assign a string constant to a global pointer,
you may find that things are shifting under your feet.
To fix this problem, you can obtain a copy of ``/usr/lib/cdbend.c'',
increase the size of the _cdbbuffer_, and use the .o file instead of -lcdb.
.
.SH BUGS
.PP
No bugs.
(If you believe that, I have this bridge in New York ........)
.PP
Third Eye Software is \fIvery\fP interested in hearing about bugs.
.SH AUTHOR
Peter Rowell, Third Eye Software, Inc.
.bp
.sp -2v
.ce
\fBCOMMAND SUMMARY\fP
.sp 2
.PD .1v
.ps 8
.vs 9
.IP "<cr>" \w'\fBif\fP\ \fIexp\fP\ {\fIcommands\fP}{\fIcommands\fP}'u+2n
Repeat previous command.
.IP "\fB\s+8\v'0.2m'^\v'-0.2m'\s0D\fP"
Repeat previous command ten times.
.IP "\fBa\fP \fIcmds\fP"
Create a new assertion with the given command list.
.IP "\fIexp\fP \fBa (a | d | s)\fP"
Modify assertion numbered \fIexp\fP. a-activate, d-delete, s-suspend.
.IP "\fBA\fP"
Toggle the overall state of the assertions mechanism.
.IP "\fIline\fP \fBb\fP \fIcmds\fP"
Set breakpoint.
.IP "\fIstack\fP \fBbb\fP \fIcmds\fP"
Set breakpoint at beginning of procedure.
.IP "\fIstack\fP \fBbu\fP \fIcmds\fP"
Set up level breakpoint.
.IP "\fIstack\fP \fBbx\fP \fIcmds\fP"
Set procedure exit breakpoint.
.IP "\fIexp\fP \fBc, C\fP \fIline\fP"
Continue from breakpoint without (C == with) signal.
.IP "\fInumber\fP \fBd\fP"
Delete breakpoint.
.IP "\fBD\fP"
Delete all breakpoints.
.IP "\fBe\fP"
Print current file, procedure and line number.
.IP "\fBe\fP (\fIproc\fP\||\|\fIfile\fP)"
Enter procedure or file.
.IP "\fIstack\fP \fBe\fP"
Enter procedure using stack address.
.TP
\fBf "\fPprintf-style-format\fB"\fP
Change address printing format.
.IP "\fBF\fP"
Find and fix bug.
.IP "\fBg\fP \fIlinenumber\fP"
Goto the \fIlinenumber\fP in the current procedure.
.IP "\fBhelp\fP"
Print brief information about the commands.
.IP "\fBif\fP \fIexp\fP {\fIcmds\fP}{\fIcmds\fP}"
Conditionally execute commands.
.IP "\fBk\fP"
Kill current process.
.IP "\fBl\fP (a | b | d | f | g | p | r | s | z) \fIstring\fP"
List assertions, breakpoints, directories, files,
globals, procedures, registers, specials, zignals.
.IP "\fBl\fP \fIproc\fP"
List all parameters and locals of procedure.
.IP "\fIline\fP \fBp\fP \fIexp\fP"
Print line in source file.
.IP "\fInumber\fP \fBP\fP \fIoptions\fP"
Perform functions on the numbered process.
.IP "\fBQ\fP"
Quiet breakpoint reporting.
.IP "\fBq\fP"
Quit debugger.
.IP "\fBr\fP \fIarguments\fP"
Run target process with arguments.
.IP "\fBR\fP"
Run target process with no arguments.
.IP "\fIexp\fP \fBs, si\fP"
Single step, follow procedure calls.
.IP "\fIexp\fP \fBS, Si\fP"
Single step, do not follow procedure calls.
.IP "\fIexp\fP \fBt\fP"
Stack trace.
.IP "\fIexp\fP \fBT\fP"
Stack trace with locals.
.IP "\fIline\fP \fBw\fP \fIexp\fP"
Print a window (default 11) around the current line.
.IP "\fIline\fP \fBW\fP \fIexp\fP"
Print a window (default 21) around the current line.
.IP "\fIexp\fP \fBx\fP"
Force an exit from the assertion mode, possibly saving command list.
.IP "\fIexp\fP \fBz\fP \fI[cirsQ [cmds]]\fP"
Toggle the given flags for the signal.
.IP "\fBZ\fP"
Toggle case sensitivity in searches.
.IP "\fB<\fP (or \fB<<\fP) \fIfile\fP"
Playback (with singlestep) from file.
.IP "\fB>\fP (or \fB>>\fP) \fIfile\fP"
Record commands (screen output) to file.
.IP "\fB>\fP (or \fB>>\fP) (t | f | c)"
Turn command (screen output) recording on, off or close file.
.IP "\fB/\fP\fIstring\fP"
Search forwards in file for string.
.IP "\fB?\fP\fIstring\fP"
Search backwards in file for string.
.TP
\fB"\fP\fIany string\fP\fB"\fP
Print the string.
.IP "\fIline\fP"
Print source line.
.IP "\fIexp\fP"
Print value of expression using ``/n'' format.
.IP "\fIexp\fP \fB@\fP \fIformat\fP"
Print address of expression.
.IP "\fIexp\fP \fB/\fP \fIformat\fP"
Print value of expression.
.IP "\fB\s+8\v'0.2m'^\v'-0.2m'\s0\fP \fIformat\fP"
Print value of previous memory location.
.IP "\fB!\fP \fIcommand-line\fP"
Execute shell (with or without commands).
0707070001000312511004440000000000010000011610200454650114200001500000003627cdb/cdb.defs #
# This file allows you to specify default debugger switches. 
#
# Its two primary uses are for (1) programs you debug frequently that
# have a lot of arguments, such as alternate directory specifications,
# and (2) programs that are not directly created by the debugger, such
# as those attached with the P option and those that are the result of
# fork's or exec's in a multi process environment.
#
# The line contains 2 items - name and the argument list.  Any line
# starting with a tab is a continuation of the preceeding line.
# Any line beginning with a "#" is a comment. Blank lines are ignored.
#
#   foo  <TAB> arguments for foo
#        <TAB> more arguments for foo
#        <TAB> more arguments for foo
#   bar  <TAB> arguments for bar
#	    
# When a new process is started, CDB gets its command name from the user
# structure and looks down the list of names.  If it finds no match, it 
# takes the base name (e.g. "/usr/lib/uucp/uucico" yeilds "uucico") and looks
# for that name.  If it still can't find the name, it will prompt you for
# the data.
#
# The arguments are the same as you would type on the shell command
# line when running CDB.  Not all switches are meaningful in this context.
#
# For example, let's say you work with uucico.  The following line might
# appear in your process file:

myuucico	-d /usr/src/usr.lib/uucp -E /u/mydir/work/uucico

#	
# This means that whenever you are debugging "myuucico", the list of
# alternate directories will be "/usr/src/usr.lib/uucp" and ".",
# in addition to any directories specified on the command line, and
# the executable is stated to be the one found in you own working
# directory.
#
# If you work with the "normal" uucico (e.g. invoked via uucp),
# you might specify:

uucico	-D -d /usr/src/usr.lib/uucp -E /usr/lib/uucp/uucico

#
# Which says that ONLY the master source directory is to be used and
# that the executable is the one in the master uucp directory.
0707070001000312521004440000000000010000011610360454650114200002100000005056cdb/cdbdemo.scri Yo   
Yh "[7m" "[0m"
Yc p
Y When CDB starts up, it takes you to the first executable
Y statement in procedure "main".
Y The 'current line' is pointed to by the arrow.
Y
Y First we list the procedures that are compiled with
Y full symbols:
l p
Y Now we enter procedure "Third".
e Third
W
Y The "switch" at line 119 looks like a good place for
Y a breakpoint.
119b
Y Having set our break, we now run the program with
Y the arguments of "arg1 arg2 arg3".  The user program
Y will print these out and fall into a loop where
Y procedure "First" calls procedure "Second" which
Y calls procedure "Third", which is where our
Y breakpoint is placed.
r arg1 arg2 arg3
Y Having hit the break, let's do a stack trace.
t
Y The stack trace shows the stack depth, procedure
Y name, parameter names and values, and file name and
Y line number where the procedure has stopped.
Y Procedure "Third's" last parameter, "message",
Y printed in hex. If we look at its type, we can
Y find out why.
message/t
Y We can also see it in the definition of
Y procedure "Third".
Third/t
Y To see all of the locals of a procedure we can say....
l Third
Y Third has a local variable "precord".
precord/t
Yc precord
Y Pointers print in hex by default. If we want to see
Y what precord points to...
*precord/N
Y And to see what the declaration is, we can use the
Y '.' feature.
./t
Y Let's look at the procedure list again
l p
Y One procedure that is not called from anywhere in the program
Y is "AddArgs". It returns the sum of its arguments.  It also
Y happens to call "Second", which calls "Third" which
Y is where we have a breakpoint - let's see what happens.
Y P.S. we will catch its return value in a
Y CDB special variable.
$save=AddArgs(1,2)
Y Doing a stack trace, you can see just where we are.
t
Y Now we continue from the break.
c
Y And do another stack trace.
t
Y You can look at the special variable just by
Y typing its name.
$save
Y We will use the 'L' command to print where we
Y last stopped.
L
Yc t
Y Looking at the stack, we decide to go look at
Y "main" at the point where it called "First". 
Y We can do this by typing its stack depth followed
Y by the Enter command.
3e
Yc w 3
Y Looking at the loop, we decide to get rid of
Y the existing breakpoints....
c D
Y And set a conditional breakpoint at the bottom
Y of the loop.  This breakpoint causes us to 'goto'
Y line 79 when "loop" gets too big.  We have effectively
Y patched the source code!
c 79b Q; if (loop >= 5) {g 81}; c
Y Now when we run, we no longer have an infinite loop!
r
Y CDB has many more features than this short
Y demonstration can cover.
Yc q
Yc y
0707070001000312531004440000000000010000011610630454650114200002100000011127cdb/cdbhelp.text 			 COMMAND SUMMARY


     <cr>                         Repeat previous command.
     ^D                           Repeat previous command ten times.
     a cmds                       Create a new assertion with the
                                  given command list.
     <exp> a (a | d | s)          Modify assertion numbered exp.  a-
                                  activate, d-delete, s-suspend.
     A (a | s)                    Change the overall state of the
                                  assertions mechanism.
     line b cmds                  Set breakpoint.
     stack bb cmds                Set procedure entry (beginning) breakpoint.
     stack bu cmds                Set up-level breakpoint.
     stack bx cmds                Set procedure exit breakpoint.
     addr bi cmds		  Set break at instruction address.
     B                            List all breakpoints
     exp c line                   Continue from breakpoint with no signal.
     exp C line                   Continue from breakpoint with signal.
     exp cu line		  Continue from breakpoint to calling routine.
     number d                     Delete breakpoint.
     D                            Delete all breakpoints.
     e                            Print current file, procedure and line number.
     e (proc | file)              Enter procedure or file.
     stack e                      Enter procedure using stack address.
     f "printf-style-format"      Change address printing format.
     F                            Find and fix bug.
     g line			  Goto line and proceed.
     help                         Print brief information about the commands.
     h				  History list.
     if exp {commands}{commands}  Conditionally execute commands.
     I                            Print information about debugger.
     k                            Kill child process.
     l (a | b | f | g | p | r | s | z) string
                                  List assertions, breakpoints, files, globals,
                                  procedures, registers, specials, zignals.
     l proc                       List all parameters and locals of procedure.
     L				  Show where we are, same as 0e.
     M				  Print address map for process and core file.
     line p exp                   Print line in source file.
     number P options		  Perform functions on the numbered process.
     P ?			  Give options for P command.
     Q                            Quiet breakpoint reporting for current break.
     q                            Quit debugger.
     r arguments                  Run child process with arguments.
     R                            Run child process with no arguments.
     exp s                        Single step, follow procedure calls.
     exp S                        Single step, do not follow procedure calls.
     exp si (Si)		  Like s and S, but machine step, not statement.
     exp t                        Stack trace.
     exp T                        Stack trace with locals.
     v				  Vi edit current file at current line.
     line w exp                   Print a window (default 11) around
                                  the current line.
     line W exp                   Print a window (default 21) around
                                  the current line.
     exp x                        Force an exit from assertion mode.
				  Possibly saving command list.
     exp z [irsQ]                 Toggle the given flags (ignore, report,
				  stop, Quiet) for signal number exp.
     Z                            Toggle case sensitivity in searches.

     < (or <<) file               Playback (with singlestep) from file.
     > (t | f | c)                Turn recording on or off, or close
                                  recording file.
     > file                       Record commands to file.
     >> file			  Same commands as >, but send all screen
				  output to file.
     /string                      Search forwards in file for string.
     ?string                      Search backwards in file for string.
     "any string"                 Print the string.
     line                         Print source line.
     exp                          Print value of expression using '/n' format.
     exp @ format                 Print address of expression.
     exp / format                 Print value of expression.
     ^ format                     Print value of previous memory location.
     !command-line                Execute shell (with or without commands).
     #n				  Repeat command number n.
     #string			  Repeat command which starts with string.
     %(n | string)	  Edit previous command found by number or contents.

0707070001000312541004440000000000010000011611260454650114200001700000002326cdb/cdbtrans.1 .ds CX $Header: cdbtrans.1,v 5.1 86/04/07 22:05:10 peter Exp $
.ds CC Copyright (C) 1985 Third Eye Software, Inc. - All Rights Reserved
.ds CD \s-2CDB\s+2
.TH CDBTRANS 1 "7 April 1986"
.SH NAME
cdbtrans - \*(CD symbol table translator
.SH SYNOPSIS
\fBcdbtrans\fP [\fIoptions\fP\^] \fIobjectfile\fP
.SH DESCRIPTION
.PP
.SH OPTIONS
.IP "\fB-a\fP" 17n
Toggles whether leading underlines are eaten. (Default is true).
.IP "\fB-s#\fP"
scales up the size of internal tables used during translation.
If \fIcdbtrans\fP fails with a message that something overflowed,
try it again with "-s2" or "-s5" or ....
.IP "\fB-v\fP"
prints a verbose copy of the new symbol tabel to stdout.
.IP "\fB-w\fP"
informs you of any decisions made in cleaning up damaged or
missing symbol information in the original a.out file.
.PP
The translator is used by \fIcdb\fP as a preprocessor of the symbol table.
In addition to translating your local symbol table to the Third Eye format,
it also knows about a number of different types of damage and errors
that can occur on your system.
.SH FILES
a.out, *.cdb
.SH SEE\ ALSO
cdb(1), a.out(5)
.SH DIAGNOSTICS
Most errors cause a reasonably accurate message to be given.
.SH AUTHOR
Peter Rowell, Third Eye Software, Inc.
0707070001000312551004440000000000010000011611440454650114200001400000036505cdb/cgram.y /* $Header: cgram.y,v 5.20 86/07/18 06:14:40 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* DON'T TOUCH THIS IN ANYWAY OR THE WORLD WILL BREAK IN TWO!!! */
/* This is true to ending comment about 50 lines down */

%nonassoc	precLow
%left   	tkComma
%nonassoc	precGlobal
%nonassoc	precLocal
%right		tkAssign tkAssPlus tkAssMinus tkAssMult tkAssDiv tkAssMod tkAssXOR  tkAssBAND tkAssBOR tkAssLeft tkAssRight
%left   	tkQuest
%left   	tkLOR
%left		tkLAND
%left		tkBar
%left		tkUpArrow
%left		tkAmper
%left		tkEqual tkNotEqual
%left		tkLAB tkRAB tkLE tkGE
%left		tkLShift tkRShift
%left		tkPlus tkMinus
%left		tkStar tkDiv tkPercent
%left		precDeref precAddress precUMinus
%right		tkBang tkTilda tkPlusPlus tkMinusMinus tkSizeof precCoersion
%left		tkLSB tkLP tkDot tkPtr
%nonassoc	precLessHigh
%nonassoc	precHigh

/* start symbol */
%start  nontStart

/* the following stuff is in don't touch land because of the order
 * that yacc shoves its stuff (and the stuff it shoves) into the
 * resulting file.
 */
%{
#include "cdb.h"
%}

%union {
    SER    ase;
    }
%{

#define yyerror(x) if (yychar) {strcpy(vsbErr,x); yyerrok; yychar=0; vtkLast= -1; goto yynewstate;} else UError(vsbErr)

#define YYSTYPE SER

/* this macro will do the assign operations like +=,*= etc. */
#define AssignOp(src,dest,operand,operation)\
	    aseTmp1 = src;\
	    operation(& aseTmp2, & aseTmp1, & operand);\
	    Assign(& src, & aseTmp2);\
	    dest = src;

/* END OF DON'T TOUCH */

export char	vsbErr[200];	/* last error committed */
static	int	vipdGram, vilnGram;
static SBT	vsbGram;
static SER	aseTmp1, aseTmp2, aseTmp3; /* temps */

%}
%%

/* beginning of productions */

nontStart:  nontE
	{
	    vase = $1;
	}
    |
	{
	    vase.asym.st = stNil;
	}
    |   error
    ;

/* this is a seperate production for ',' otherwise yacc complains */

nontE:
	nontE tkComma nontE
	{
	    $$ = $3;
	}
    |   nontExpr
	{
	    $$ = $1;
	}
    ;

/* basically this is all of the binary operations */

nontExpr:
	nontExpr tkStar nontExpr
	{
	    Mul(& $$, & $1, & $3);
	}

    |   nontExpr tkDiv nontExpr
	{
	    Div(& $$, & $1, & $3);
	}

    |   nontExpr tkPercent nontExpr
	{
	    Mod(& $$, & $1, & $3);
	}

    |   nontExpr tkPlus nontExpr
	{
	    Add(& $$, & $1, & $3);
	}

    |   nontExpr tkMinus nontExpr
	{
	    Subtract(& $$, & $1, & $3);
	}

    |   nontExpr tkRShift nontExpr
	{
	    RShift(& $$, & $1, & $3);
	}

    |   nontExpr tkLShift nontExpr
	{
	    LShift(& $$, & $1, & $3);
	}

    |   nontExpr tkLAB nontExpr
	{
	    LT(& $$, & $1, & $3);
	}

    |   nontExpr tkRAB nontExpr
	{
	    GT(& $$, & $1, & $3);
	}

    |   nontExpr tkLE nontExpr
	{
	    LE(& $$, & $1, & $3);
	}

    |   nontExpr tkGE nontExpr
	{
	    GE(& $$, & $1, & $3);
	}

    |   nontExpr tkEqual nontExpr
	{
	    EQ(& $$, & $1, & $3);
	}

    |   nontExpr tkNotEqual nontExpr
	{
	    NE(& $$, & $1, & $3);
	}

    |   nontExpr tkAmper nontExpr
	{
	    BAnd(& $$, & $1, & $3);
	}

    |   nontExpr tkUpArrow nontExpr
	{
	    XOr(& $$, & $1, & $3);
	}

    |   nontExpr tkBar nontExpr
	{
	    BOr(& $$, & $1, & $3);
	}

    |   nontExpr tkLAND nontExpr
	{
	    LAnd(& $$, & $1, & $3);
	}

    |   nontExpr tkLOR nontExpr
	{
	    LOr(& $$, & $1, & $3);
	}

    /* '?:' -  this is a fun one, here's the scheme:
		We must evaluate everything because this might be embedded
		in some more complicated expression. When we are in the
		false code (i.e. a ? b : c -- if a is true, c is the false
		code) evaluate everything except those things that change
		state (Assignment and procedure calls).

		'vfInFalse' is the flag for this and the code takes into
		account nested '?:' statements.
    */
    |   nontExpr tkQuest
	{
	    GetVal(& $1);
	    Coerce(vseCnLong, & $1);
	    $$.val.valLong = vfInFalse;
	    vfInFalse = vfInFalse || ($1.val.valLong == 0);
	}
	 nontExpr tkColon
	{
	    vfInFalse = $3.val.valLong || !vfInFalse;
	}
	nontExpr %prec tkQuest
	{
	    $$ = ($1.val.valLong != 0) ? $4 : $7;
	    GetVal(& $$);
	    vfInFalse = $3.val.valLong;
	}

    |   nontExpr tkAssign nontExpr
	{
	    Assign(& $1, & $3);
	    $$ = $1;
	}
    |   nontExpr tkAssPlus nontExpr
	{
		AssignOp($1, $$, $3,Add);
	}

    |   nontExpr tkAssMinus nontExpr
	{
	    AssignOp($1, $$, $3,Subtract);
	}

    |   nontExpr tkAssMult nontExpr
	{
	    AssignOp($1, $$, $3,Mul);
	}

    |   nontExpr tkAssDiv nontExpr
	{
	    AssignOp($1, $$, $3,Div);
	}

    |   nontExpr tkAssMod nontExpr
	{
	    AssignOp($1, $$, $3,Mod);
	}

    |   nontExpr tkAssXOR nontExpr
	{
	    AssignOp($1, $$, $3,XOr);
	}

    |   nontExpr tkAssBAND nontExpr
	{
	    AssignOp($1, $$, $3,BAnd);
	}

    |   nontExpr tkAssBOR nontExpr
	{
	    AssignOp($1, $$, $3,BOr);
	}

    |   nontExpr tkAssLeft nontExpr
	{
	    AssignOp($1, $$, $3,LShift);
	}

    |   nontExpr tkAssRight nontExpr
	{
	    AssignOp($1, $$, $3,RShift);
	}

    /* procedure call-- get the args then do the call */
    |   nontExpr tkLP 
	{
	    /* at this point we set up the pointer for args */
	    if (vseArgs == (pSER) -1) /* first time*/
		vseArgs = & yyv[YYMAXDEPTH];
	    $$.val.valLong = (long) vseArgs; /* KLUDGE?!?!?!??! */
	}
	nontExprList tkRP
	{
	    if ($1.ti.tq0 == tqProc) {
		if (!vfInFalse)
		    DoProc(& $$, & $1, vseArgs, $3.val.valLong);
		vseArgs = (pSER) $3.val.valLong; /* reset */
	    } else if (($1.ti.tq1 == tqProc) AND ($1.ti.tq0 == tqPtr)) {
		/* we will dereference it for them */
		if (!vfInFalse) {
		    GetOrig(&$1);
		    $1.asym.sc = scNil;
		    Coerce(vseAdr, & $1);
		    $1.asym.value = $1.val.valAdr;
		    DoProc(& $$, & $1, vseArgs, $3.val.valLong);
		} /* if */
		vseArgs = (pSER) $3.val.valLong; /* reset */
	    } else {
		UError("Illegal function");
	    }
	}
		
    |	nontIdent tkHash tkNumber
       	{
	    /* given procname#linenumber, give address */
	    vsbGram = SbFIss($1.asym.iss);
	    vipdGram = IpdFName(vsbGram);
	    Coerce(vseCnInt, &$3);
	    vilnGram = $3.val.valInt;

LineToAdrKludge:
	    if (v->rgPd[vipdGram].iline == 0) {
		UError("I have no line numbers for procedure \"%s\"", vsbGram);
	    } else {
		CopyTy(& $$, vseCnULong);
		$$.val.valAdr = $$.asym.value =
		   AdrFIfdIln(IfdFAdr(v->rgPd[vipdGram].adr), vilnGram);
		if ($$.val.valAdr == adrNil)
		    UError("Line %d does not map to code in procedure %s",
			vilnGram, vsbGram);
		$$.ti.bt = btAdr;
		$$.ti.fConstant = true;
		$$.asym.st = stExpr;
	    } /* if */
	}

    |	tkHash tkNumber
       	{
	    vipdGram = v->ipd;
	    Coerce(vseCnInt, &$2);
	    vilnGram = $2.val.valInt;
	    vsbGram = SbFIpd(v->ipd);
	    goto LineToAdrKludge;
	}

    |   nontTerm	    %prec precLow
	{
	    $$ = $1;
	    GetAdr(& $$);
	    if (($$.ti.bt == btFloat) OR ($$.ti.bt == btDouble))
		ValFSe(&$$);
	}
    ;

/* these are basically single op type stuff */

nontTerm:
	tkAmper nontTerm	%prec precAddress
	{
	    GetAdr(& $2);
	    if ( ($2.ti.fConstant)
	       AND ($2.ti.tq0 == tqNil)
	       AND ($2.ti.bt != btStruct)
	       AND ($2.ti.bt != btUnion) )
		UError("Operand for '&' incorrect");
	    /* we turn it into a constant pointer to itself */
	    $$ = $2;
	    $$.val.valAdr = $2.asym.value;
	    $$.ti.fConstant = true;
	    AddTq(&$$, tqPtr);
	}

    |   nontTerm tkLSB nontExpr tkRSB	%prec tkLSB
	{
	    int		cb;

	    GetOrig(& $1);
	    GetOrig(& $3);

	    if (($1.ti.tq0 != tqArray) 
	       AND ($1.ti.tq0 != tqPtr)) {
		/* we allow this to act the same as if $1 were
		 * the name of an array of the type of $1.
		 */
		AddTq(&$1, tqArray);
		$1.val.valAdr = $1.asym.value;
	    } /* if */

	    Add(&$$, & $1, & $3);
	    $$.asym.sc = scNil;
	    if ($$.ti.tq0 == tqNil)
		Coerce(vseAdr, & $$);
	    $$.asym.value = $$.val.valAdr;
	    RemoveTq(& $$);	/* get rid of array/pointer-ness */
	    $$.ti.fConstant = false;
	    GetVal(& $$);
	    if (($$.ti.tq0 == tqArray) OR ($$.ti.tq0 == tqProc))
		$$.val.valAdr = $$.asym.value;
	    $$.asym.iss = issNil;
	}

    |   tkMinus nontTerm	%prec precUMinus
	{
	    GetOrig(& $2);
	    aseTmp1 = $2;
	    ZeroBlock(& aseTmp1.val, sizeof (VALU));
	    Subtract(& $$, & aseTmp1, & $2);
	}

    |   tkBang nontTerm
	{
	    Bang(& $$, & $2);
	}

    |   tkTilda nontTerm
	{
	    Tilda(& $$, & $2);
	}

    |   tkPlusPlus nontTerm
	{
	    aseTmp1 = *vseCnChar;
	    aseTmp1.val.valChar = 1;
	    GetAdr(& $2);
	    aseTmp2 = $2;
	    Add(& aseTmp3, & aseTmp2, & aseTmp1);
	    Assign(& $2, & aseTmp3);
	    $$ = $2;
	}

    |   tkMinusMinus nontTerm
	{
	    aseTmp1 = *vseCnChar;
	    aseTmp1.val.valChar = 1;
	    GetAdr(& $2);
	    aseTmp2 = $2;
	    Subtract(& aseTmp3, & aseTmp2, & aseTmp1);
	    Assign(& $2, & aseTmp3);
	    $$ = $2;
	}

    |   nontTerm tkPlusPlus
	{
	    aseTmp1 = *vseCnChar;
	    aseTmp1.val.valChar = 1;
	    GetAdr(& $1);
	    aseTmp2 = $1;
	    aseTmp3 = $1;
	    GetOrig (& aseTmp3);	/* need 'before' value */
	    Add(& $$, & aseTmp2, & aseTmp1);
	    Assign(& $1, & $$);
	    $$ = aseTmp3;
	    $$.ti.fConstant = true;
	    $$.asym.iss = issNil;
	}


    |   nontTerm tkMinusMinus
	{
	    aseTmp1 = *vseCnChar;
	    aseTmp1.val.valChar = 1;
	    GetAdr(& $1);
	    aseTmp2 = $1;
	    aseTmp3 = $1;
	    ValFSe(& aseTmp3);
	    /* GetOrig (& aseTmp3);	/* need 'before' value */
	    Subtract(& $$, & aseTmp2, & aseTmp1);
	    Assign(& $1, & $$);
	    $$ = aseTmp3;
	    $$.ti.fConstant = true;
	    $$.asym.iss = issNil;
	}

    |   tkArg tkLP nontExpr tkRP
	{
	    /* $arg(x)  - returns the x'th INT arg */
	    char	sbName[10];

	    GetVal(& $3);
	    Coerce(vseCnInt, &$3);
	    $$ = *vseInt;
	    GetArgN(&$$, $3.val.valInt);
	    sprintf(sbName, "$arg(%d)", $3.val.valInt);
	    $$.asym.iss = IssFSb(sbName);
	}

    |   tkInside tkLP nontIdent tkRP
	{
	    int		ipd;

	    /* returns true if current pc is in the named procedure */

	    $$ = *vseCnInt;
	    $$.asym.iss = $1.asym.iss;
	    $$.val.valInt = IpdFAdr(v->acntx.pc)
				== IpdFName(SbFIss($3.asym.iss));
	}

    |   tkSizeof nontTerm
	{
	    GetAdr(& $2);
	    $$ = *vseCnInt;
	    $$.val.valInt = CbFSe(& $2);
	}

    |   tkLP nontType  tkRP nontTerm    %prec precCoersion
	{
	    /* type cast to KEYWORD type */
	    GetOrig(& $4);
	    Coerce(& $2, & $4);
	    $$ = $4;
	}

    |   nontIdent
	{
	    $$ = $1;
	    if (($$.ti.bt == btFloat) OR ($$.ti.bt == btDouble))
		ValFSe(&$$);
	}

    |   tkNumber
	{
	    $$ = yylval;
	    $$.asym.st = stNumber;
	}

    |   tkFltConstant
	{
	    $$ = yylval;
	    $$.asym.st = stExpr;
	}

    |   tkStrConstant
	{
	    $$ = *vseCnAdr;
	    $$.asym.value = AdrFStore(vsbLex, strlen(vsbLex) + 1);
	    $$.val.valAdr = $$.asym.value;
	}
    |   tkCharConstant
	{
	    $$ = *vseCnChar;
	    $$.asym.st = stExpr;
	    $$.val.valChar = vsbTok[0];
	}

    |	nontTerm tkDot nontIdent
	{
	    $$.asym.iss = $3.asym.iss;	/* give result the field name */
	    GetAdr(& $1);

	    if (vfStrict) {
		if ( ($1.ti.tq0 != tqNil)
		 OR ((($1.ti.bt != btStruct)
		    AND ($1.ti.bt != btUnion))) ) {
    printf("You may not use the \".\" operator on something of this type\n");
		PxSe(&$1, true);
		UError("");
		} /* if */
	    } /* if */

	    FField(& $1, & $$);
	}

    |	nontTerm tkPtr nontIdent
	{
	    GetVal(& $1);

	    if (vfStrict) {
		if ( ($1.ti.tq0 != tqPtr)
		 OR ((($1.ti.bt != btStruct)
		    AND ($1.ti.bt != btUnion))) ) {
    printf("You may not use the \"->\" operator on something of this type\n");
		PxSe(&$1, true);
		UError("");
		} /* if */
	    } /* if */

	    if ($1.ti.tq0 == tqNil)
		Coerce(vseAdr, & $1);
	    $1.asym.value = $1.val.valAdr;
	    $$.asym.iss = $3.asym.iss;	/* give result the field name */
	    FField(& $1, & $$);
	}

    |	tkStar nontTerm			%prec precDeref
	{
	    GetOrig(& $2);

	    $$ = $2;
	    $$.asym.sc = scNil;
	    if ($$.ti.tq0 == tqNil)
		Coerce(vseAdr, & $$);
	    $$.asym.value = $$.val.valAdr;
	    $$.ti.fConstant = false;
	    RemoveTq(& $$);	/* get rid of array/pointer-ness */
	    GetVal(& $$);
	    if (($$.ti.tq0 == tqArray) OR ($$.ti.tq0 == tqProc))
		$$.val.valAdr = $$.asym.value;
	    $$.asym.iss = issNil;
	}

    |	tkDot
	{
	    $$ = *v->seDot;
	}

    |   tkColon nontIdent		%prec precGlobal
	{
	    $$ = $2;
	    if (!FGlobal(& $$))
		UError("No such global: %s", SbFIss($2.asym.iss));
	}

    |   tkNumber tkHash nontIdent	%prec precLocal
	{
	    $$ = $3;
	    Coerce(vseCnInt, &$1);
    	    if (!FLocal(& $$, ipdNil, $1.val.valInt))
		UError("No such local: %s", SbFIss($3.asym.iss));
	}

    |   nontIdent tkHash nontIdent	%prec precLocal
	{
	    int	ipd;

	    $$ = $3;
	    ipd = IpdFName(SbFIss($1.asym.iss));
    	    if (!FLocal(& $$, ipd, -1))
		UError("No such local: %s", SbFIss($3.asym.iss));
	}

    |	tkLP nontE tkRP
	{
	    $$ = $2;
	    $$.asym.st = stExpr;
	}
    ;

nontIdent:  tkStr
	{
	    $$.asym.st = stStr;
	    $$.asym.iss = IssFSb(vsbLex);
	}
    ;

nontExprList:   /* empty */
    |   nontExprList2
    ;

nontExprList2:  nontExpr	%prec tkComma
	{
	    GetVal(& $1);
	    *(--vseArgs) = $1;
	}
    |   nontExpr tkComma nontExprList2
	{
	    GetVal(& $1);
	    *(--vseArgs) = $1;
	}
    ;

nontType:   nontBase nontDesc
	{
	    int		tq, i, idim, idimTemp;
	    $$ = $1;

	    /* Tack on $2's info */
	    idim = 0;	/* first, count their dimensions */
	    for (i = 0; i < itqMax; i++) {
		if ((tq = TqFSe(&$$, i)) == tqNil)
		    break;
		if (tq == tqArray)
		    idim++;
	    } /* for */

	    idimTemp = 0;
	    for (i = 0; i < itqMax; i++) {
		if ((tq = TqFSe(&$2, i)) == tqNil)
		    break;
		AddTq(&$$, tq);
		if (tq == tqArray) {
		    /* add this to the dimensions we already have */
		    if (idim >= idimMax)
			UError("%s has more than %d dimensions",
			    SbFIss($$.asym.iss), idimMax);
		    $$.rgRng[idim++] = $2.rgRng[idimTemp++];
		} /* if */
	    } /* for */

	    /* $$.ti = $2.ti;	/* KLUDGE?!?!?! - YES! */
	    $$.ti.bt = $1.ti.bt;
	    $$.ti.fConstant = true;
	}

nontDesc:	       %prec precLow
	{ /* no abstractor ( *, [], () ) */
	    CopyTy(& $$, vseInit);
	}

    |   nontFDesc
	{
	    $$ = $1;
	}
    |   tkLP nontFDesc tkRP     %prec precLessHigh
	{
	    $$ = $2;
	    $$.asym.st = stType;
	}
    ;

nontFDesc: tkStar nontDesc         %prec precHigh
	{
	    AddTq(& $2, tqPtr);
	    $$ = $2;
	}
    |   nontDesc tkLSB tkRSB	%prec precHigh
	{
	    /* KLUDGE ! I KNOW this ain't right! */
	    if ($1.asym.st != stType) {
		AddTq(& $1, tqArray);
	    } else {
		AddTq(& $1, tqArray);
	    }
	    $$ = $1;
	}

    |   nontDesc tkLP tkRP      %prec precHigh
	{
	    if ($1.asym.st != stType) {
		AddTq(& $1, tqProc);
	    } else {
		AddTq(& $1, tqProc);
	    }
	    $$ = $1;
	}
    ;

nontBase: tkStruct nontIdent
	{
	    $$.asym.iss = $2.asym.iss;
	    if (!FTypeFName(& $$, tkStruct))
		UError("Struct identifier (%s) not found", SbFIss($2.asym.iss));
	}

    |	tkUnion nontIdent
	{
	    $$.asym.iss = $2.asym.iss;
	    if (!FTypeFName(& $$, tkUnion))
		UError("Union identifier (%s) not found", SbFIss($2.asym.iss));
	}

    |	tkEnum nontIdent
	{
	    $$.asym.iss = $2.asym.iss;
	    if (!FTypeFName(& $$, tkEnum))
		UError("Enum identifier (%s) not found", SbFIss($2.asym.iss));
	}

    |	tkTypedef
	{
	    CopyTy(& $$, & $1);
	}

    |	tkUnsigned tkChar
	{
	    CopyTy(& $$, vseCnUChar);
	}

    |   tkUnsigned tkShort
	{
	    CopyTy(& $$, vseCnUShort);
	}

    |   tkUnsigned tkInt
	{
	    CopyTy(& $$, vseCnUInt);
	}

    |   tkUnsigned tkLong
	{
	    CopyTy(& $$, vseCnULong);
	}

    |    tkChar
	{
	    CopyTy(& $$, vseCnChar);
	}

    |    tkShort
	{
	    CopyTy(& $$, vseCnShort);
	}

    |    tkInt
	{
	    CopyTy(& $$, vseCnInt);
	}

    |    tkLong
	{
	    CopyTy(& $$, vseCnLong);
	}

    |    tkFloat
	{
	    CopyTy(& $$, vseCnFloat);
	}

    |    tkDouble
	{
	    CopyTy(& $$, vseCnDouble);
	}
    ;
%%
0707070001000312561004440000000000010000011607040454650114200001700000002343cdb/config.awk BEGIN	{
	    RCS = "$Header: config.awk,v 6.2 86/09/15 09:32:24 peter Exp $";
	    list = "abcdefghijklmnopqrstuvwxyz";
	    if (FS != " ") {
		isysSelect = index(list, FS);
		if (isysSelect == 0)
		    exit(1);
		fGotit = 0;
	    } else {
		fGotit = 1;
		isysSelect = 0;
	    }
	    fIndirect = 0;
	    FS = " ";
	    isysCur = 0;
	}

/^LOOKFOR/	{
	    if (isysSelect == isysCur)
		sbMore = substr($0, 8);
	    next;
	}

/^FIND/	{
	    if (sbMore == substr($0, 5)) {
		isysSelect = isysCur;
		sbMore = "";
		next;
	    }

	}

/^@/	{
	    ++isysCur;
	    if (isysSelect == 0) {
		printf "\t%s\t%s\n", substr(list, isysCur, 1), substr($0, 2);
	    } else if (isysSelect == isysCur) {
		fGotit = 1;
		printf "SYSNAME = %s\n", substr($0, 2) >> "SYS.make";
		print "/* This file is automatically created by config */" > "SYS.h"
		printf "#define SYS_NAME \"%s\"\n", substr($0, 2) >> "SYS.h";
	    }
	    next;
	}

/^#define/ {
	    if (isysSelect == isysCur) {
		print $0 >> "SYS.h"
	    }
	    next;
	}

/^\$/	{   next; }
/^$/	{   next; }
/^-/	{   next; }

	{
	    if (isysSelect == isysCur) {
		print $0 >> "SYS.make"
	    }
	    next;
	}

END	{
	    if (fGotit == 0) {
	      printf "There is no system '%s'.\n", substr(list, isysSelect, 1);
	    }
	}
0707070001000312571004440000000000010000011607220454650114200001600000012404cdb/config.db $Header: config.db,v 6.5 86/09/15 09:32:33 peter Exp $
----------------------------
@Integrated Solutions VME Series running 4.2 BSD
CPU	= 68
OS	= Bsd
#define	SYS	ISI42
#define CPU	M68000
#define OP_SYS	BSD42
#define MFG	ISI
#define BPT_INST	0x4e4f0000	/* trap 15 */
#define BPT_BACKUP	1
#define INTEGER_OFFSETS	1
#define EXEC_F1	EXEC_B1
#define EXEC_F2	(aexec.a_text)
#define EXEC_B2	ctob(stoc(ctos(btoc(pr->mapExec.e1))))
#define CORE_B1	ctob(stoc(ctos(btoc(pr->mapExec.e1))))
#define M68020	1
--------------------------------
@INTeL 80386 running System V.3
CPU	= 386
OS	= V
#define	SYS	IN386V
#define CPU	I80386
#define OP_SYS	SYSV
#define MFG	INTEL
#define INTEGER_OFFSETS		1
#define STRUCT_RETURN_OFFSET	1
#define NO_UNDERLINES	1
#define PERCENT_SIGNS	0
#define ADR_REG0	0
#define CLEAR_FP	0
#define spaceUser	3
#define cbStorageMax	0xc0000000
#define CHECK_REG_PARAMS	1
#define BPT_BACKUP	1
#define TXTRNDSIZ	0x2000
---------------------------
@DEC VAXen running 4.2 BSD
#define ADR_USER	((ADRT)0x7ffff000)	/* BSD 4.2 */

LOOKFOR VAX COMMON

---------------------------
@DEC VAXen running Ultrix 1.2
#define ADR_USER	((ADRT)0x7fffe400)	/* Ultrix */

FIND VAX COMMON

CPU	= Vax
OS	= Bsd
#define	SYS	VAX42
#define CPU	VAX
#define OP_SYS	BSD42
#define MFG	DEC
#define ADR_PROC_BASE	2
#define CALLEE_STACK_CLEANUP	1
----------------------------
@DEC VAXen running System V
CPU	= Vax
OS	= V
#define	SYS	VAXV
#define CPU	VAX
#define OP_SYS	SYSV
#define MFG	DEC
#define ADR_PROC_BASE	2
#define ADR_USER	0x7ffff800
#define CALLEE_STACK_CLEANUP	1
---------------------------
@Sun Microsystems running 4.2 BSD
CPU	= 68
OS	= Bsd
#define	SYS	SUN42	
#define	CPU	M68000
#define	OP_SYS	BSD42
#define	MFG	SUN
#define ADR_TEXT_BASE	0x8000L
#define ADR_LOWEST	0x8000L
#define BPT_INST	0x4e4f0000	/* trap 15 */
#define BPT_BACKUP	1
#define EXEC_B1	((v->adrText != 0) ? v->adrText : N_TXTADDR(aexec))
#define EXEC_B2	((v->adrData != 0) ? v->adrData : N_DATADDR(aexec))
#define INTEGER_OFFSETS	1
----------------------------
@Arete running System V.2
CPU	= 68
OS	= V
#define	SYS	AR68V
#define	CPU	M68000
#define	OP_SYS	SYSV
#define	MFG	ARETE
#define	_5000_60_80 1
#define	m68	1
#define BPT_INST	0x4e410000	/* trap 1 */
#define ADR_USER ((ADRT)0x1000)
#define ADR_START	0x3c
#define cbCodeOffset	2048
#define cbStorageMax	0xfff000
#define NO_UNDERLINES	1
#define PERCENT_SIGNS	1
#define BPT_BACKUP	1
#defile CHECK_REG_PARAMS	1	/* 68000 only */
#defile ALSO_EQUAL	1	/* 68020 only */
-------------------------------
@Siemens PDN cross from Unidot 32000
CPU	= Pdn
OS	= Pdn
SYS_O_EXTRAS	= sptrace.o
#define	SYS	PDN
#define	CPU	PDN
#define	OS	PDN
#define	MFG	SIEMENS
#define COMM_CACHE 1
#define REGT	uint4
--------------------------------
@Opus 532 running System V.2.2
CPU	= 32
OS	= V
#define	SYS	OPUS32V
#define CPU	N32000
#define OP_SYS	SYSV
#define MFG	OPUS
#define ADR_USER	((ADRT)0xe1f800)
#define NO_UNDERLINES	0
#define PERCENT_SIGNS	0
#define RPS	PS
--------------------------------
@Intergraph InterPro 32 running System V.2.2
CPU	= 32
OS	= V
#define	SYS	INTER32V
#define CPU	N32000
#define OP_SYS	SYSV
#define MFG	INTERGRAPH
#define PS	PSR_MOD
#define NO_UNDERLINES	0
#define PERCENT_SIGNS	0
--------------------------------
@Pyramid running OSx
CPU	= PY9X
OS	= Bsd
#define CPU	PY9X
#define OP_SYS	BSD42
#define MFG PYRAMID
#define SYS PY9X42
#define EXEC_B1	0
#define EXEC_B2	(pr->mapExec.e1)
#define CORE_F1	0x1000
#define CORE_F2	(CORE_F1 + pr->mapCore.e1 - pr->mapCore.b1)
#define CORE_E2	(0xc00cd800)	/* USRSTACK??? */
#define ctob(x) ((ADRT)ptob(x))
#define bitHigh	0x02000000
#define upc 15
#define usp 14
#define ufp 13
#define uap 13
--------------------------------
@Plexus running System V.2
CPU	= 68
OS	= V
#define	SYS	P60V
#define	CPU	M68000
#define	OP_SYS	SYSV
#define	MFG	PLEXUS
#define	m68	1
#define BPT_INST	0x4e420000	/* trap 2 */
#define ADR_START	0x3c
#define cbCodeOffset	2048
#define cbStorageMax	0x7ff000
#define NO_UNDERLINES	0
#define PERCENT_SIGNS	1
#define BPT_BACKUP	1
#define LANG_C 1
--------------------------------
@Encore HostStation 550 running System UMAX 4.2
#define	SYS	HS550

LOOKFOR ENCORE COMMON

--------------------------------
@Encore MultiMax running System UMAX 4.2
#define	SYS	MX32V

FIND ENCORE COMMON

CPU	= 32
OS	= Bsd
#define CPU	N32000
#define OP_SYS	SYSV
#define MFG	ENCORE
#define ADR_USER	((ADRT)0xe1f800)
#define NO_UNDERLINES	0
#define PERCENT_SIGNS	0
#define PS	PSR
#define cbStorageMax	USRSTACK

#define X_ReadPc	1
#define X_InstallBp	1
#define X_RemoveBp	1

#define R0 PT_R0
#define R1 PT_R1
#define R2 PT_R2
#define R3 PT_R3
#define R4 PT_R4
#define R5 PT_R5
#define R6 PT_R6
#define R7 PT_R7
#define SP PT_SP
#define FP PT_FP
#define PC PT_PC
#define PS PT_PS
--------------------------------
@Siemens MX2 runnting Sinix
CPU	= 32
OS	= Mx2
#define	SYS	MX2
#define CPU	N32000
#define OP_SYS	BSD42
#define MFG	SIEMENS
#define ADR_USER	((ADRT)0x00c06000)
#define D302 1
#define USRSTACK	TOPUSER
#define SP	RSP
#define PC	RPC
#define FP	RFP
#define STRUCT_RETURN_OFFSET	1
--------------------------------
@Sequent running 4.2 BSD
CPU	= 32
OS	= Bsd
#define	SYS	SEQ3242
#define CPU	N32000
#define OP_SYS	BSD42
#define MFG	SEQUENT
#define ADR_USER	((ADRT)0x00ff0200)
#define EXEC_B1	N_ADDRADJ(aexec)
#define EXEC_E1	aexec.a_text
#define EXEC_F2 N_DATAOFF(aexec)
#define CORE_F2	(pr->mapCore.f1 + cbData)
#define STRUCT_RETURN_OFFSET	1
0707070001000312601004440000000000010000011607740454650114200001700000000421cdb/newvers.sh if [ ! -r vers.h ]; then echo "0 0 0 0 0" > vers.h; fi
awk 'NR==1	{ printf "static int load= %d ;\n", $4+1; \
printf "static int major=6,minor=1,fix= 1;\n"}' < vers.h > V2

echo "static char user[]=\"$USER\";" >> V2
echo "static char date[]=\"`date`\";" >> V2
mv V2 vers.h
0707070001000312611004440000000000010000011610030454650114200002100000025402cdb/ND.waitMulti /* $Header: waitMulti.c,v 5.9 86/06/02 23:26:03 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

/* This module contains most of the code used for MULTI-PROCESS debugging.
 * This module is mutually exclusive with swait.c.
 */


#include "cdb.h"

#include <signal.h>

#if (OP_SYS == BSD42)
#include <sys/time.h>
#include <sys/wait.h>
#endif (OP_SYS == BSD42)

#if (OP_SYS == SYSV)
#include <fcntl.h>
#endif (OP_SYS == SYSV)

#include <errno.h>

export int2	viprMax = 100;	/* allow lots of room */


/* P P I D   F   P I D */

export PpidFPid(pid)
int	pid;
{
    int		ppid;

    ppid = Ptrace(ptPpid, pid, 0, 0);
    if (ppid == -1)
	UError("Attempting to find parent of %d: %s.", SbFError(errno));
    return(ppid);
} /* PpidFPid */


/* S B   E X E C   F   P I D */

export SBT SbExecFPid(pid)
int	pid;
{
    static char	sbCmd[257];

    Ptrace(ptCmdName, pid, sbCmd, 0);
    return(sbCmd);
} /* SbExecFPid */


/* F R E E   P R O C E S S */

export void FreeProcess(pr)
pPRR	pr;
{
    if (pr == prNil)
	return;

    SetGlobalPr(pr);

    RemoveAllBp(true);
    /* setpgrp(v->pid, v->pgrpSave); /* */
    Ptrace(ptReleaseChild, pr->pid, (char *) 1, 0);
    if (pr->pidParent != vpidCdb) {
	DeallocPr(pr, false);
    } else {
	pr->pid = pidNil;
	pr->ps = psNoChild;
    } /* if */

    SetGlobalPr(prNil);
} /* FreeProcess */


/* C O P Y   P R */

export void CopyPr(pr1, pr2)
pPRR	pr1, pr2;
{
    int2	cb;

    /* Make pr1 identical to pr2 */

    *pr1 = *pr2;	/* this gets all of the normal fields */

    /* KLUDGE - need to create CopyOs, CopyCpu */

    /* KLUDGE - need to check ALL fields and make our own copies
     * so that DeallocPr is free to throw everything away.
     */
    
    pr1->fForkedProcess = true;

    /* setup tables */
    cb = pr1->ibpMax * cbBPR;	/* breakpoints */
    pr1->rgBp = (pBPR) malloc(cb);
    MoveBytes(pr1->rgBp, pr2->rgBp, cb);

    cb = pr1->ilvMax * cbSER;	/* local variables */
    pr1->rgLv = (pSER) malloc(cb);
    MoveBytes(pr1->rgLv, pr2->rgLv, cb);

    cb = pr1->iadMax * cbADR;	/* assertions */
    pr1->rgAd = (pADR) malloc(cb);
    MoveBytes(pr1->rgAd, pr2->rgAd, cb);

    pr1->seDot = (pSER)malloc(cbSER);
    pr1->sbArgsChild = SbFAlloc(pr2->sbArgsChild);
} /* CopyPr */


/* P R   F O R K */

export pPRR PrFFork(pidChild, fAttached)
int2	pidChild;
FLAGT	fAttached;
{
    int		pidParent;
    SBT		sbExec;
    pPRR	pr, prParent;

    /* A new child has come into the world.
     * Register it with the draft board.
     */

    /* First we have to find out who the parent is */
    pidParent = PpidFPid(pidChild);
    prParent = PrFPid(pidParent);

    if (fAttached AND (prParent != prNil)) {
	/* We know the family, but the kid has been
	 * away from home for a long time.
	 * Check his id at the door */
	sbExec = SbExecFPid(pidChild);
	if (! FSbCmp(sbExec, prParent->sbExec))
	    prParent = prNil;
    } /* if */

    if (prParent == prNil) {

	/* A stranger in a strange land */
	pr = PrFInitPr( SbExecFPid(pidChild) );

    } else {

	/* A friend of the family */
	pr = PrFAlloc();
	CopyPr(pr, prParent);

	if (pr->fRemoveBpsOnFork) {
	    SetGlobalPr(pr);
	    RemoveAllBp(true);
	    SetGlobalPr(prNil);
	} /* if */

	pr->fnComm = pr->fnCdb = pr->fnExec = pr->fnCore = fnNil;

    } /* if */

    pr->pid = pidChild;
    pr->pidParent = pidParent;
    pr->ps = psFork;
    if (vfNotify) {
	printf("New process\n");
	ListPr(pr);
    } /* if */

    ++vcActive;		/* count of Active proceesses */
    return(pr);
} /* PrFFork */


/* P R   F   A T T A C H   P R O C E S S */

export pPRR PrFAttachProcess(pid)
int2	pid;
{
    int		ret;
    SBT		sb;
    pPRR	pr, prSave;

    ret = Ptrace(ptMultiChild, pid, 0, 0);	/* make him ours */
    if (ret == -1)
	UError("Unable to attach to process %d: %s.", pid, SbFError(errno));

    /* Chicken and Egg problem: We can't call Waiter, because we
     * don't have a process record because we don't have the process
     * name because we haven't waited on the process yet.
     * Sooooooo, we send SIGINT, wait a couple of seconds and
     * hope that the process has stopped.
     */
    kill(pid, SIGINT);
    sleep(2);

    pr = PrFFork(pid, true);
    pr->ps = psRunning;

    prSave = v;
    SetGlobalPr(pr);
    ReadPc();
    SetCntx();
    SetViewPosition(pr->acntx.pc);
    v->pgrpSave = getpgrp(pid);
    /* setpgrp(pid, getpgrp(0)); /* make him the same process group as us */
    return(pr);
} /* PrFAttachProcess */


/* P R   F   E X E C */

export pPRR PrFExec(pr)
pPRR	pr;
{
    extern char * gets();
    int2	pidParent, pidChild = pr->pid;
    char	*sbExec, sbBuf[200];
    FLAGT	fStopOnExec;		/* stop immediately after exec */
    FLAGT	fStopOnFork;		/* stop BOTH process after fork */
    FLAGT	fRemoveBpsOnFork;	/* child does NOT get parent's BPs */
    FLAGT	fDebugChildren;		/* indicates we WANT the kids */
    pSER	rgLv;
    FLAGT	fDoingSingle;
    
    pidParent = pr->pidParent;	/* Remember Mom */

    sbExec = SbExecFPid(pr->pid);	/* Find out who we are */
    if (sbExec == sbNil) {
	printf("Unable to determine name of program for process #%d\n",
	    pidChild);
	printf("Please type name of executable: ");
	sbExec = gets(sbBuf);
	if ((sbExec == sbNil) OR (*sbExec == chNull)) {
	    Ptrace(ptReleaseChild, pidChild, (char *) 1, 0);
	    UError("Aborting debugging of process #%d.", pidChild);
	} /* if */
    } /* if */

    fStopOnExec = pr->fStopOnExec;
    fStopOnFork = pr->fStopOnFork;
    fRemoveBpsOnFork = pr->fRemoveBpsOnFork;
    fDebugChildren = pr->fDebugChildren;
    fDoingSingle = pr->fDoingSingle;
    rgLv = pr->rgLv;

    DeallocPr(pr, true);		/* kill old identity */

#if 0
    pr = PrFAlloc();		/* a clean slate */
    pr->sbExec = SbFAlloc(sbExec);	/* our new name */
    pr->sbCore = sbNil;
    pr->isymCacheMax = 0;
    InitPr(pr);
#endif
    pr = PrFInitPr(sbExec);
    pr->pid = pidChild;
    pr->pidParent = pidParent;

    pr->fStopOnExec = fStopOnExec;
    pr->fStopOnFork = fStopOnFork;
    pr->fRemoveBpsOnFork = fRemoveBpsOnFork;
    pr->fDebugChildren = fDebugChildren;
    pr->fDoingSingle = fDoingSingle;
    pr->rgLv = rgLv;
    pr->ps = psRunning;

    SetGlobalPr(pr);
    ReadPc();
    SetCntx();
#if 0
    SetGlobalPr(prNil);
#endif 0

    if (vfNotify) {
	printf("Process exec'ed\n");
	ListPr(pr);
    } /* if */
    return(pr);
} /* PrFExec */


/* N O   H A N G   G E T S */
export SBT NoHangGets(sb, fRedoPrompt, fHang)
SBT	sb;
FLAGT	fRedoPrompt, fHang;
{
#if (OP_SYS == SYSV)
    int		ch;
    SBT		sbTemp;

    /* this routine ASSUMES that we already have O_NDELAY set */

    if (fHang) {
	if (fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY) == -1)
	    SysPanic("fcntl on ~O_NDELAY");
	sleep(1); /* to disturb the ether and make O_NDELAY go away */
	if (fRedoPrompt)
	    printf("\n%s", vsbPrompt);
	return(gets(sb));
    } else {
	sbTemp = sb;
	ch = getchar();
	if (ch != EOF) {

	    /* There is something there.  Let them type in peace */
	    if (fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NDELAY) == -1)
		SysPanic("fcntl clearing O_NDELAY");

	    while ((*sb++ = ch) != '\n')
		ch = getchar();
	    sb[-1] = 0;	/* step on ending <cr> */

	    if (fcntl(0, F_SETFL, O_NDELAY | fcntl(0, F_GETFL, 0)) == -1)
		SysPanic("fcntl setting O_NDELAY");
	    return(sbTemp);

	} /* if */
	return((SBT)-1);
    } /* if */
#else
    int		nfd, readfd, writefd, exceptfd;
    struct timeval	atimeval, *ptimeval;

    nfd = 1;		/* used for the select call */
    writefd = 0;
    exceptfd = 0;
    atimeval.tv_sec = 0;
    ptimeval = &atimeval;

    readfd = 1;
    if (!fHang) {
	ptimeval->tv_usec = 500000;	/* 1/2 second */
    } else {
	ptimeval = 0;	/* we wait forever */
	if (fRedoPrompt)
	    printf("\n%s", vsbPrompt);
    } /* if */

    fflush(stdout);
    if (0 != select(nfd, &readfd, &writefd, &exceptfd, ptimeval))
	return(gets(sb));
    return((SBT)-1);	/* says we didn't see anything before timeout */
#endif /* (OP_SYS == SYSV) */
} /* NoHangGets */


/* N O   H A N G   W A I T */

export int NoHangWait(pstatus)
int	*pstatus;
{
#if (OP_SYS == SYSV)
    int		ret;

    alarm(1);
    ret = wait(pstatus);
    if ((ret == -1) AND (errno == EINTR))
	return(0);	/* timed out */
    return(ret);
#else
    return( wait3(pstatus, WNOHANG, nil) );
#endif /* (OP_SYS == SYSV) */
} /* NoHangWait */


/* W A I T E R */

export long Waiter(wt, pidWait)
int2	wt, pidWait;
{
    int		pid, ppid, waitReturn, status;
    FLAGT	fRunningChildren, fRedoPrompt;
    pPRR	pr, prSave = v;

    /* Wait for something to happen in a
     * MULTIPLE PROCESS environment
     */

    vfUseCache = false;	/* just in case they turned it on */
    fRedoPrompt = false;
    fRunningChildren = true;	/* assume we do until we fail on wait3 */

#if (OP_SYS == SYSV)
    if (fcntl(0, F_SETFL, O_NDELAY | fcntl(0, F_GETFL, 0)) == -1)
	SysPanic("fcntl on O_NDELAY");
#endif (OP_SYS == SYSV)

    while (1) {
	if (wt == wtTty) {
	    /* there are no children we need to deal with */
	    /* See if we should get something from the terminal */
	    if ((SBT)-1 != NoHangGets(vsbGet, fRedoPrompt, !fRunningChildren))
		break;
	    /* a negative return indicates no command line yet */
	} /* if */

	waitReturn = 0;
	if (fRunningChildren) {
	    if (vcActive <= 1)
		signal(SIGINT, SIG_IGN);	/* ignore INT */

	    waitReturn = NoHangWait(&status);

	    if (vcActive <= 1)
		signal(SIGINT, Fixer);	/* reconnect to the Fixer routine */
	    if (waitReturn == -1) {

		if (errno == ECHILD) {
		    /* it's no crime not to have children.... */
		    fRunningChildren = false;
		    waitReturn = 0;
		} else if (errno == EINTR) {
		    printf("PANIC! received signal: %d (%s).\n",
			status>>8, SbFSignal(status>>8));
		    /* what do we do here?? */
		    exit(1);
		} else {	/* some sort of error occurred */
		    perror(vsbDebugName);
		    exit(1);
		} /* if */
	    } /* if */
	} /* if */
	
	if (waitReturn > 0) {
	    pid = waitReturn;
	    pr = PrFPid(pid);
	    if (pr == prNil) {
		/* We weren't expecting this guy.
		 * The highest probability is that he
		 * is the result of a fork.  
		 */

		pr = PrFFork(pid, false);
		if (pr == prNil) {
		    /* PrFFork didn't like him */
		    /* What should we do here? Kill him? */
		    continue;
		} /* if */
	    } /* if */

	    if (pr->ps == psStopped)
		continue;

	    SetGlobalPr(pr);	/* make him the boss */

	    if (v->fStty)
		SetMyTty();
	    v->status = status;

	    AnalyzeStop();
	    fRedoPrompt = true;
	    fRunningChildren = true;	/* as a default */

	    if (v->ps == psContinue) {
		/* He's not supposed to stop yet, onward! */
		RunProcess(ptResume, psRunning, false);
		continue;
	    } /* if */

	    if ((wt == wtProcess) AND (pid == pidWait)) {
		break;	/* we were waiting for this guy */
	    } else if (vfNotify AND (vcActive > 1)) {
		pr = PrFPid(pid);
		if (pr != prNil) {
		    printf("Process stopped:\n");
		    ListPr(pr);
		} /* if */
	    } /* if */
	} /* if */
    } /* while */

    SetGlobalPr(prSave);
} /* Waiter */
0707070001000312621004440000000000010000011611360454650114300001600000005475cdb/Configure 
# (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved
# $Header: Configure,v 6.3 86/09/14 20:24:23 peter Exp $
#
# In order to install CDB you need to have write permission to
# the directory you will be installing into AND write permission
# for directory /usr/lib (probably this means being 'root').

n=''
c=''
contains=grep

: first determine how to suppress newline on echo command
(echo "hi there\c" ; echo " ") >.echotmp
if $contains c .echotmp >/dev/null 2>&1 ; then
    n='-n'
    c=''
    pager=more
else
    n=''
    c='\c'
    pager=pg
fi
rm .echotmp

echo "CDB Configuration Program"
echo " "

HFILE="SYS.h"
MFILE="SYS.make"
MKFILE="Makefile"

rm -f $HFILE $MFILE $MKFILE

until test -r $HFILE
do
    echo "The following systems are available:"
    echo " "
    awk -f config.awk config.db | $pager
    echo " "
    echo $n "Please type the letter of your system > $c"
    read sysnum
    awk -F${sysnum} -f config.awk config.db
done

# Create the Makefile
echo "# WARNING! This file is automatically overwritten by the" > $MKFILE
echo "# Configure shell script.  Anything you change in here will" >> $MKFILE
echo "# be lost the next time you get an update to the debugger." >> $MKFILE
echo "#" >> $MKFILE
cat $MFILE >> $MKFILE
rm -f $MFILE

grammars=""
libs=""
o_extras=""
c_extras=""

if test -r cgram.y; then
    grammars="$grammars cgram.o"
    echo "#define LANG_C 1" >> $HFILE
fi

if test -r fsupport.c; then
#    grammars="$grammars fgram.o"
    o_extras="$o_extras fsupport.o"
    c_extras="$c_extras fsupport.c"
    echo "#define LANG_FORTRAN 1" >> $HFILE
fi

if test -r ww.c; then
    o_extras="$o_extras ww.o"
    c_extras="$c_extras ww.c"
    echo "WM	= wm" >> $MKFILE
    echo "WMINSTALL	= wminstall" >> $MKFILE
    libs="$libs -ltermcap"
    echo "#define WINDOWS 1" >> $HFILE
    if test -r /usr/include/vt.h
    then
	if $contains ISI $HFILE > /dev/null
	then
	    libs="$libs -ltools -lvt"
	    echo "#define HAS_GRAPHICS 1" >> $HFILE
	fi
    fi
fi

man=man1
if test -r /usr/man/p_man/man1; then
    man=p_man/man1
fi
echo "MAN	= $man" >> $MKFILE

echo "LIBS	= $libs" >> $MKFILE
echo "O_EXTRAS	= $o_extras" >> $MKFILE
echo "C_EXTRAS	= $c_extras" >> $MKFILE
echo "GRAMMARS	= $grammars" >> $MKFILE
echo " " >> $MKFILE
echo "##########  END OF CONFIGURATION PARAMETERS ##########" >> $MKFILE
echo " " >> $MKFILE
echo " " >> $MKFILE

# Finally the rest of the $MKFILE
cat Make.Cdb >> $MKFILE

if test -d THIRDI
then
    echo "CFLAGS=$(DEBUGFLAGS)" >> $MKFILE
    echo "#define THIRDI 1" >> $HFILE
fi

cat << "MeSsAgE"

Your system is now ready to be built. In order to:

  - Build cdb, type "make all"
  - Install locally (you MUST be root), type "make "BASE=/" install"
  - Create a directory for distribution to customers, type "make distinstall"
  - Create a demo directory for ditribution, type "make demoinstall"

MeSsAgE
exit 0
0707070001000312631004440000000000010000011605340454650114300001500000002334cdb/DEMO_HDR The accompanying tape contains a demonstration copy of CDB, the source-level
debugger from Third Eye Software.  If you have any problems, please contact
your supplier.

This tape contains the following files:
  /usr/bin/
    cdb			Single process debugger.
    cdbtrans		Symbol table translator (invoked by debuggers).
    docdbdemo		Shell script for running demos.

  /usr/lib/
    cdbhelp.text	Online help file.
    libcdb.a		Special library for some CDB functions.
    cdbend.c		Source file for libcdb.a

  /usr/lib/cdb/
    READ_ME*		Description of demo stuff.
    cdbdemo*		Demo program.
    cdbdemo.c		Source for demo program.
    cdbdemo.cdb		Translated symbol table for demo.
    cdbdemo.script	Playback file to drive demo.

  /usr/man/man1/
    cdb.1		Troff file for cdb man pages.
    cdbtrans.1		Troff file for cdbtrans man pages.


Additionally, you may have some of the following optional files:

    /usr/bin/mdb   Multiprocess debugger (ISI only).

    /usr/bin/wdb   Shell script to run cdb in windowed mode.
    /usr/bin/wm	   Window manger for use on ascii terminals (BSD only).
    /usr/man/man1/wm.1		Troff file for wm man pages.

    Papers describing the window manager code.
    /usr/doc/Paper.jacob
    /usr/doc/USINGWM

0707070001000312641004440000000000010000011605520454650114300001500000022066cdb/Make.Cdb # $Header: Make.Cdb,v 6.3 86/09/15 09:32:15 peter Exp $
# (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved

# This file contains information for MAKEing various flavors of
# Third Eye Software's CDB debugger.
# It is used by the Configure shell script to create the file "Makefile".

.SUFFIXES: .o .s .a .c .y

# DANGER - we have evidence that the 4.2 VAX optimizer generates bad code.
# Do NOT compile CDB with the -O flag on a VAX 4.2 (and possibly others!)
# CFLAGS		= -O -c

CFLAGS		= -c
DEBUGFLAGS	= -g -c
#DEBUGFLAGS	= -gx -c	# use this line for PYRAMID systems
# Un-comment the next line to debug the debuggers themselves
CFLAGS		= $(DEBUGFLAGS)

# This is where directory hierarchies start from
BASE = 	../
DEMO_BASE = 	../

# ################################# #
# Files that compose the debuggers  #
# ################################# #

OPTIONS =	cpu68.c dis68.c \
		cpuVax.c disVax.c \
		cpuCci.c disCci.c \
		cpu3b2.c dis3b2.c \
		cpuPy9x.c disPy9x.c \
		cpu386.c dis386.c \
		cpu32.c dis32.c \
		cpuPdn.c disPdn.c \
		osV.c osBsd.c osEncore.c osSiemens.c \
		xptrace.h xptrace.c xremote.c \
		fsupport.c ww.c \
		waitSingle.c waitMulti.c 

#		cpuElxsi.c disElxsi.c
#		cpuF32.c disF32.c

GENERIC =	cpu.c dis.c os.c

HFILES =	config.h cdb.h sym.h tokens.h

CFILES =	main.c access.c assert.c bp.c\
		cmd.c cmdline.c cpulib.c csupport.c dummy.c \
		cdbend.c expr.c files.c format.c help.c history.c \
		list.c lib.c math.c \
		procedure.c process.c pt.c \
		signal.c single.c sym.c tk.c valid.c var.c \
		$(C_EXTRAS)

# grammars are done first so that tk.h (y.tab.h) is correct
OFILES =	$(GRAMMARS) $(O_EXTRAS) $(SYS_O_EXTRAS) \
		cpu.o dis.o os.o\
		main.o access.o assert.o bp.o\
		cmd.o cmdline.o cpulib.o\
		csupport.o expr.o\
		files.o format.o\
		help.o history.o\
		list.o lib.o math.o\
		procedure.o process.o pt.o\
		signal.o single.o sym.o tk.o\
		valid.o var.o

# These are the documentation files (and other random stuff) for CDB
OTHERFILES =	cdb.1 cdbtrans.1 names cdbhelp.text cdb.defs\
		cgram.y wdb newvers.sh \
		READ_ME Porting loe.c ext.sed\
		Configure Make.Cdb config.awk config.db\
		DEMO_HDR READ_ME_DEMO cdbdemo.c cdbdemo.script dodemo\
		demovalid.c demo.h demotime.c demo.c

ALLFILES =	$(CFILES) $(HFILES) $(OTHERFILES) $(OPTIONS)


# ###############################
#  ------ Start of Rules ------ #
# ###############################

all:	Makefile Message debug cdbtrans cdbdemo $(WM)

# Normal way to make cdb
debug:	ext.h cdb rdb kdb

# if you modify (or add) any procedure formals, execute this rule.
ext.h:	$(GENERIC) $(CFILES)
	grep '^[ 	]*export' $(GENERIC) $(CFILES) | sed -f ext.sed > ext.h

# Single process, native
cdb:	Makefile $(OFILES) waitSingle.o libcdb.a
	make "DUMMYFLAGS=" dummy.o
	$(CC) -o $@ $(OFILES) waitSingle.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

# Single process, remote
rdb:	Makefile $(OFILES) waitSingle.o rptrace.o libcdb.a cdbremote
	make "DUMMYFLAGS=-DREMOTE" dummy.o
	$(CC) -o $@ $(OFILES) rptrace.o waitSingle.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

kdb:	Makefile $(OFILES) waitSingle.o kptrace.o libcdb.a 
	make "DUMMYFLAGS=-DREMOTE" dummy.o
	$(CC) -o $@ $(OFILES) kptrace.o waitSingle.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

# Multiple processes, native
mdb:	Makefile $(OFILES) waitMulti.o libcdb.a
	make "DUMMYFLAGS=-DMULTI" dummy.o
	$(CC) -o $@ $(OFILES) waitMulti.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

# dummy module is ALWAYS recompiled.
# It contains stub routines for missing options.
# It also contains version info.
dummy.o:
	sh newvers.sh
	$(CC) $(CFLAGS) $(DUMMYFLAGS) dummy.c

# Remote debug server
remote:	xremote.o
	$(CC) -o $@ xremote.o
cdbremote: cdbremote.o
	$(CC) -o $@ cdbremote.o

# Symbol table translator
TRANSDIR=	../trans$(OS)
cdbtrans:	SYS.h config.h sym.h
	cd $(TRANSDIR); rm -f SYS.h config.h sym.h
	ln SYS.h config.h sym.h $(TRANSDIR)
	cd $(TRANSDIR); make $(MFLAGS) all
	rm -f cdbtrans
	ln $(TRANSDIR)/cdbtrans .

# Ascii window manager
WMDIR=	../wm
wm:
	cd $(WMDIR); make $(MFLAGS) all
	rm -f wm
	ln $(WMDIR)/wm .

wminstall:	wm
	strip wm
	rm -f $(BASE)usr/bin/wm
	cp wm $(BASE)usr/bin
	chmod 555 $(BASE)usr/bin/wm

Message:
	@echo This makefile is currently setup for a
	@echo $(SYSNAME)
	@echo CPU = $(CPU), OS = $(OS).
	@echo If this is incorrect, run the Configure script.

# demotime is used for setting the magic time on demo copies of the debugger
demotime:	demotime.o
	$(CC) -o demotime demotime.o

dodemo:
	echo "cdb -Z0 -p cdbdemo.script cdbdemo" > dodemo
	chmod 555 dodemo

cdbdemo:	cdbdemo.c
	$(CC) -g -o $@ $@.c libcdb.a

cdb.demo:	cdb demovalid.o
	mv cdb cdb.save
	mv valid.o valid.save
	mv demovalid.o valid.o
	make cdb
	mv cdb cdb.demo
	mv valid.o demovalid.o
	mv valid.save valid.o
	mv cdb.save cdb

reset:	demotime cdb.demo $(TRANS)	# TES local command
	echo "rm -f $(DEMO_BASE)usr/bin/cdb*" | su2 
	cp cdb.demo $(DEMO_BASE)usr/bin/cdb
	cp cdbtrans $(DEMO_BASE)usr/bin
	demotime - $(DEMO_BASE)usr/bin/cdb*
	touch demo

DIRS:
	@echo "You *must* be ROOT to do the installation."
	-cd $(BASE);mkdir usr usr/bin usr/lib usr/lib/cdb usr/man usr/man/$(MAN)

cdbinstall:	all
	strip cdb cdbtrans
	rm -f $(BASE)usr/bin/cdb $(BASE)usr/bin/cdbtrans
	cp cdb cdbtrans $(BASE)usr/bin
	chmod 111 $(BASE)usr/bin/cdb $(BASE)usr/bin/cdbtrans
	rm -f $(BASE)usr/man/$(MAN)/cdb.1 $(BASE)usr/man/$(MAN)/cdbtrans.1
	cp cdb.1 cdbtrans.1 $(BASE)usr/man/$(MAN)
	chmod 444 $(BASE)usr/man/$(MAN)/cdb.1 $(BASE)usr/man/$(MAN)/cdbtrans.1
	rm -f $(BASE)usr/lib/cdbhelp.text $(BASE)usr/lib/libcdb.a \
			$(BASE)usr/lib/cdbend.c
	cp cdbhelp.text libcdb.a cdbend.c $(BASE)usr/lib
	chmod 444 $(BASE)usr/lib/cdbhelp.text $(BASE)usr/lib/libcdb.a \
			$(BASE)usr/lib/cdbend.c
	rm -f $(BASE)usr/lib/cdb/cdbdemo $(BASE)usr/lib/cdb/cdbdemo.c \
		    $(BASE)usr/lib/cdb/cdbdemo.script $(BASE)usr/lib/cdb/dodemo
	cp dodemo cdbdemo cdbdemo.c cdbdemo.script $(BASE)usr/lib/cdb
	chmod 555 $(BASE)usr/lib/cdb/cdbdemo $(BASE)usr/lib/cdb/dodemo
	chmod 444 $(BASE)usr/lib/cdb/cdbdemo.c $(BASE)usr/lib/cdb/cdbdemo.script

demoinstall:	cdb.demo demotime
	@echo "You *must* be ROOT to do the installation."
	mv cdb cdb.save
	mv cdb.demo cdb
	-make "BASE=$(DEMO_BASE)" install
	mv cdb cdb.demo
	mv cdb.save cdb
	demotime $(DEMO_BASE)usr/bin/cdb*

# Move things to interesting places
install:	DIRS cdbinstall $(WMINSTALL)

demo.tar: demoinstall
	cd $(DEMO_BASE); rm -f cdb.demo.tar; tar vcf cdb.demo.tar usr
	@echo ""
	@echo "Make a print of DEMO_HDR to give to customer"

.c.o:	$*.c
	$(CC) $(CFLAGS) $*.c

.y.c:
	cat tokens.h $*.y > Y.y
	yacc -d Y.y
	sed -e '/}/ s/YYSTYPE/NOTUSED/' -e '/extern/ s/YYSTYPE/SER/' \
	     -e '/prec/d' < y.tab.h > tk.h
	grep -v "^#.*line" y.tab.c |\
	  sed -e 's/yy/$*y/g' -e 's/$*ylex/yylex/g' -e 's/$*ylval/yylval/g'\
	      -e 's/YY/$*Y/g' > $*.c
	rm y.tab.h y.tab.c Y.y

cdbend.o:
	$(CC) $(DEBUGFLAGS) cdbend.c

libcdb.a:	cdbend.o
	ld -o libcdb.a -r cdbend.o

TEST:	loe fib

# "loe" is a liitle-of-everything file used for testing/playing with cdb
# "fib" is the world's worst implementation of a fibonaci number computer
loe fib:	FRC
	$(CC) -g -o $@ $@.c libcdb.a

# Link the appropriate files to the GENERIC ones
os.c:
	ln os$(OS).c os.c
cpu.c:
	ln cpu$(CPU).c cpu.c
dis.c:
	ln dis$(CPU).c dis.c

Makefile:	config.db Make.Cdb
	@echo "The configuration information and/or master makefile"
	@echo "has changed. You should run the shell script"
	@echo "'Configure' again.  This will be your only warning."
	touch Makefile

tags:	FRC
	ctags -w $(HFILES) $(CFILES) $(GENERIC)

clean:
	rm -f *.o *.cdb cdb rdb cdbremote remote mdb loe cdb.demo cdbdemo\
		cdbtrans libcdb.a mkerr tk.h cgram.c vers.h kdb
	cd ../transV; make clean

allfiles:	Makefile
	@echo "$(ALLFILES)" >allfiles

FRC:

# These two rules are used by Third Eye's BACKUP mechanism
.PRECIOUS:	SAVE
SAVE:	$(ALLFILES)
	BACKUP $?
	rm -f SAVE os.c cpu.c dis.c
	touch SAVE
	chmod 0 SAVE

# The following will create a list of first-level dependecies for cdb.
# It should be run if you add any non-system include files to cdb.
depend:	$(CFILES) $(HFILES)
	echo '# start of automatic dependencies' > .X1
	grep '^#[ 	]*include' $(CFILES) $(GENERIC) | grep '"' > .X2
	sed -e 's/#[ 	]*include//' -e 's/"//g' -e 's/\.c/.o/' -e 's/\/\*.*\*\///' <.X2 >> .X1
	cp Makefile newMake
	(echo '/^# start of auto/,$$d'; echo '$$r .X1'; echo w; echo q) | /bin/ed - newMake
	mv Makefile oldMake
	mv newMake Makefile
	rm oldMake
	@rm .X1 .X2
	@echo DONE with depend

# start of static dependencies
ww.o: cdb.h
fsupport.o: cdb.h
cpu.o: cdb.h
dis.o: cdb.h
os.o: cdb.h
cgram.c: tokens.h
fgram.c: tokens.h
cgram.o: cdb.h cgram.c
fgram.o: cdb.h fgram.c
demovalid.o: cdb.h demo.h

# Don't put anything below the following line!
# It is manipulated by the automatic dependency rule above.

# start of automatic dependencies
main.o: cdb.h
access.o: cdb.h
assert.o: cdb.h
bp.o: cdb.h
cmd.o: cdb.h
cmdline.o: cdb.h
cpulib.o: cdb.h
csupport.o: cdb.h
dummy.o: cdb.h
cdbend.o: config.h
expr.o: cdb.h
files.o: cdb.h
format.o: cdb.h
help.o: cdb.h
list.o: cdb.h
lib.o: cdb.h
math.o: cdb.h
procedure.o: cdb.h
process.o: cdb.h
pt.o: cdb.h
signal.o: cdb.h
single.o: cdb.h
sym.o: cdb.h
tk.o: cdb.h
valid.o: cdb.h
var.o: cdb.h
xptrace.o: cdb.h
xptrace.o: xptrace.h
xremote.o: xptrace.h
waitSingle.o: cdb.h
waitMulti.o: cdb.h
0707070001000312651004440000000000010000011606600454650114300001500000022630cdb/Makefile # WARNING! This file is automatically overwritten by the
# Configure shell script.  Anything you change in here will
# be lost the next time you get an update to the debugger.
#
SYSNAME = Plexus running System V.2
CPU	= 68
OS	= V
MAN	= man1
LIBS	= 
O_EXTRAS	= 
C_EXTRAS	= 
GRAMMARS	=  cgram.o
 
##########  END OF CONFIGURATION PARAMETERS ##########
 
 
# $Header: Make.Cdb,v 6.3 86/09/15 09:32:15 peter Exp $
# (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved

# This file contains information for MAKEing various flavors of
# Third Eye Software's CDB debugger.
# It is used by the Configure shell script to create the file "Makefile".

.SUFFIXES: .o .s .a .c .y

# DANGER - we have evidence that the 4.2 VAX optimizer generates bad code.
# Do NOT compile CDB with the -O flag on a VAX 4.2 (and possibly others!)
# CFLAGS		= -O -c

CFLAGS		= -c
DEBUGFLAGS	= -g -c
#DEBUGFLAGS	= -gx -c	# use this line for PYRAMID systems
# Un-comment the next line to debug the debuggers themselves
CFLAGS		= $(DEBUGFLAGS)

# This is where directory hierarchies start from
BASE = 	../
DEMO_BASE = 	../

# ################################# #
# Files that compose the debuggers  #
# ################################# #

OPTIONS =	cpu68.c dis68.c \
		cpuVax.c disVax.c \
		cpuCci.c disCci.c \
		cpu3b2.c dis3b2.c \
		cpuPy9x.c disPy9x.c \
		cpu386.c dis386.c \
		cpu32.c dis32.c \
		cpuPdn.c disPdn.c \
		osV.c osBsd.c osEncore.c osSiemens.c \
		xptrace.h xptrace.c xremote.c \
		fsupport.c ww.c \
		waitSingle.c waitMulti.c 

#		cpuElxsi.c disElxsi.c
#		cpuF32.c disF32.c

GENERIC =	cpu.c dis.c os.c

HFILES =	config.h cdb.h sym.h tokens.h

CFILES =	main.c access.c assert.c bp.c\
		cmd.c cmdline.c cpulib.c csupport.c dummy.c \
		cdbend.c expr.c files.c format.c help.c history.c \
		list.c lib.c math.c \
		procedure.c process.c pt.c \
		signal.c single.c sym.c tk.c valid.c var.c \
		$(C_EXTRAS)

# grammars are done first so that tk.h (y.tab.h) is correct
OFILES =	$(GRAMMARS) $(O_EXTRAS) $(SYS_O_EXTRAS) \
		cpu.o dis.o os.o\
		main.o access.o assert.o bp.o\
		cmd.o cmdline.o cpulib.o\
		csupport.o expr.o\
		files.o format.o\
		help.o history.o\
		list.o lib.o math.o\
		procedure.o process.o pt.o\
		signal.o single.o sym.o tk.o\
		valid.o var.o

# These are the documentation files (and other random stuff) for CDB
OTHERFILES =	cdb.1 cdbtrans.1 names cdbhelp.text cdb.defs\
		cgram.y wdb newvers.sh \
		READ_ME Porting loe.c ext.sed\
		Configure Make.Cdb config.awk config.db\
		DEMO_HDR READ_ME_DEMO cdbdemo.c cdbdemo.script dodemo\
		demovalid.c demo.h demotime.c demo.c

ALLFILES =	$(CFILES) $(HFILES) $(OTHERFILES) $(OPTIONS)


# ###############################
#  ------ Start of Rules ------ #
# ###############################

all:	Makefile Message debug cdbtrans cdbdemo $(WM)

# Normal way to make cdb
debug:	ext.h cdb rdb kdb

# if you modify (or add) any procedure formals, execute this rule.
ext.h:	$(GENERIC) $(CFILES)
	grep '^[ 	]*export' $(GENERIC) $(CFILES) | sed -f ext.sed > ext.h

# Single process, native
cdb:	Makefile $(OFILES) waitSingle.o libcdb.a
	make "DUMMYFLAGS=" dummy.o
	$(CC) -o $@ $(OFILES) waitSingle.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

# Single process, remote
rdb:	Makefile $(OFILES) waitSingle.o rptrace.o libcdb.a cdbremote
	make "DUMMYFLAGS=-DREMOTE" dummy.o
	$(CC) -o $@ $(OFILES) rptrace.o waitSingle.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

kdb:	Makefile $(OFILES) waitSingle.o kptrace.o libcdb.a 
	make "DUMMYFLAGS=-DREMOTE" dummy.o
	$(CC) -o $@ $(OFILES) kptrace.o waitSingle.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

# Multiple processes, native
mdb:	Makefile $(OFILES) waitMulti.o libcdb.a
	make "DUMMYFLAGS=-DMULTI" dummy.o
	$(CC) -o $@ $(OFILES) waitMulti.o dummy.o libcdb.a $(LIBS)
	@rm dummy.o

# dummy module is ALWAYS recompiled.
# It contains stub routines for missing options.
# It also contains version info.
dummy.o:
	sh newvers.sh
	$(CC) $(CFLAGS) $(DUMMYFLAGS) dummy.c

# Remote debug server
remote:	xremote.o
	$(CC) -o $@ xremote.o
cdbremote: cdbremote.o
	$(CC) -o $@ cdbremote.o

# Symbol table translator
TRANSDIR=	../trans$(OS)
cdbtrans:	SYS.h config.h sym.h
	cd $(TRANSDIR); rm -f SYS.h config.h sym.h
	ln SYS.h config.h sym.h $(TRANSDIR)
	cd $(TRANSDIR); make $(MFLAGS) all
	rm -f cdbtrans
	ln $(TRANSDIR)/cdbtrans .

# Ascii window manager
WMDIR=	../wm
wm:
	cd $(WMDIR); make $(MFLAGS) all
	rm -f wm
	ln $(WMDIR)/wm .

wminstall:	wm
	strip wm
	rm -f $(BASE)usr/bin/wm
	cp wm $(BASE)usr/bin
	chmod 555 $(BASE)usr/bin/wm

Message:
	@echo This makefile is currently setup for a
	@echo $(SYSNAME)
	@echo CPU = $(CPU), OS = $(OS).
	@echo If this is incorrect, run the Configure script.

# demotime is used for setting the magic time on demo copies of the debugger
demotime:	demotime.o
	$(CC) -o demotime demotime.o

dodemo:
	echo "cdb -Z0 -p cdbdemo.script cdbdemo" > dodemo
	chmod 555 dodemo

cdbdemo:	cdbdemo.c
	$(CC) -g -o $@ $@.c libcdb.a

cdb.demo:	cdb demovalid.o
	mv cdb cdb.save
	mv valid.o valid.save
	mv demovalid.o valid.o
	make cdb
	mv cdb cdb.demo
	mv valid.o demovalid.o
	mv valid.save valid.o
	mv cdb.save cdb

reset:	demotime cdb.demo $(TRANS)	# TES local command
	echo "rm -f $(DEMO_BASE)usr/bin/cdb*" | su2 
	cp cdb.demo $(DEMO_BASE)usr/bin/cdb
	cp cdbtrans $(DEMO_BASE)usr/bin
	demotime - $(DEMO_BASE)usr/bin/cdb*
	touch demo

DIRS:
	@echo "You *must* be ROOT to do the installation."
	-cd $(BASE);mkdir usr usr/bin usr/lib usr/lib/cdb usr/man usr/man/$(MAN)

cdbinstall:	all
	strip cdb cdbtrans
	rm -f $(BASE)usr/bin/cdb $(BASE)usr/bin/cdbtrans
	cp cdb cdbtrans $(BASE)usr/bin
	chmod 111 $(BASE)usr/bin/cdb $(BASE)usr/bin/cdbtrans
	rm -f $(BASE)usr/man/$(MAN)/cdb.1 $(BASE)usr/man/$(MAN)/cdbtrans.1
	cp cdb.1 cdbtrans.1 $(BASE)usr/man/$(MAN)
	chmod 444 $(BASE)usr/man/$(MAN)/cdb.1 $(BASE)usr/man/$(MAN)/cdbtrans.1
	rm -f $(BASE)usr/lib/cdbhelp.text $(BASE)usr/lib/libcdb.a \
			$(BASE)usr/lib/cdbend.c
	cp cdbhelp.text libcdb.a cdbend.c $(BASE)usr/lib
	chmod 444 $(BASE)usr/lib/cdbhelp.text $(BASE)usr/lib/libcdb.a \
			$(BASE)usr/lib/cdbend.c
	rm -f $(BASE)usr/lib/cdb/cdbdemo $(BASE)usr/lib/cdb/cdbdemo.c \
		    $(BASE)usr/lib/cdb/cdbdemo.script $(BASE)usr/lib/cdb/dodemo
	cp dodemo cdbdemo cdbdemo.c cdbdemo.script $(BASE)usr/lib/cdb
	chmod 555 $(BASE)usr/lib/cdb/cdbdemo $(BASE)usr/lib/cdb/dodemo
	chmod 444 $(BASE)usr/lib/cdb/cdbdemo.c $(BASE)usr/lib/cdb/cdbdemo.script

demoinstall:	cdb.demo demotime
	@echo "You *must* be ROOT to do the installation."
	mv cdb cdb.save
	mv cdb.demo cdb
	-make "BASE=$(DEMO_BASE)" install
	mv cdb cdb.demo
	mv cdb.save cdb
	demotime $(DEMO_BASE)usr/bin/cdb*

# Move things to interesting places
install:	DIRS cdbinstall $(WMINSTALL)

demo.tar: demoinstall
	cd $(DEMO_BASE); rm -f cdb.demo.tar; tar vcf cdb.demo.tar usr
	@echo ""
	@echo "Make a print of DEMO_HDR to give to customer"

.c.o:	$*.c
	$(CC) $(CFLAGS) $*.c

.y.c:
	cat tokens.h $*.y > Y.y
	yacc -d Y.y
	sed -e '/}/ s/YYSTYPE/NOTUSED/' -e '/extern/ s/YYSTYPE/SER/' \
	     -e '/prec/d' < y.tab.h > tk.h
	grep -v "^#.*line" y.tab.c |\
	  sed -e 's/yy/$*y/g' -e 's/$*ylex/yylex/g' -e 's/$*ylval/yylval/g'\
	      -e 's/YY/$*Y/g' > $*.c
	rm y.tab.h y.tab.c Y.y

cdbend.o:
	$(CC) $(DEBUGFLAGS) cdbend.c

libcdb.a:	cdbend.o
	ld -o libcdb.a -r cdbend.o

TEST:	loe fib

# "loe" is a liitle-of-everything file used for testing/playing with cdb
# "fib" is the world's worst implementation of a fibonaci number computer
loe fib:	FRC
	$(CC) -g -o $@ $@.c libcdb.a

# Link the appropriate files to the GENERIC ones
os.c:
	ln os$(OS).c os.c
cpu.c:
	ln cpu$(CPU).c cpu.c
dis.c:
	ln dis$(CPU).c dis.c

Makefile:	config.db Make.Cdb
	@echo "The configuration information and/or master makefile"
	@echo "has changed. You should run the shell script"
	@echo "'Configure' again.  This will be your only warning."
	touch Makefile

tags:	FRC
	ctags -w $(HFILES) $(CFILES) $(GENERIC)

clean:
	rm -f *.o *.cdb cdb rdb cdbremote remote mdb loe cdb.demo cdbdemo\
		cdbtrans libcdb.a mkerr tk.h cgram.c vers.h kdb
	cd ../transV; make clean

allfiles:	Makefile
	@echo "$(ALLFILES)" >allfiles

FRC:

# These two rules are used by Third Eye's BACKUP mechanism
.PRECIOUS:	SAVE
SAVE:	$(ALLFILES)
	BACKUP $?
	rm -f SAVE os.c cpu.c dis.c
	touch SAVE
	chmod 0 SAVE

# The following will create a list of first-level dependecies for cdb.
# It should be run if you add any non-system include files to cdb.
depend:	$(CFILES) $(HFILES)
	echo '# start of automatic dependencies' > .X1
	grep '^#[ 	]*include' $(CFILES) $(GENERIC) | grep '"' > .X2
	sed -e 's/#[ 	]*include//' -e 's/"//g' -e 's/\.c/.o/' -e 's/\/\*.*\*\///' <.X2 >> .X1
	cp Makefile newMake
	(echo '/^# start of auto/,$$d'; echo '$$r .X1'; echo w; echo q) | /bin/ed - newMake
	mv Makefile oldMake
	mv newMake Makefile
	rm oldMake
	@rm .X1 .X2
	@echo DONE with depend

# start of static dependencies
ww.o: cdb.h
fsupport.o: cdb.h
cpu.o: cdb.h
dis.o: cdb.h
os.o: cdb.h
cgram.c: tokens.h
fgram.c: tokens.h
cgram.o: cdb.h cgram.c
fgram.o: cdb.h fgram.c
demovalid.o: cdb.h demo.h

# Don't put anything below the following line!
# It is manipulated by the automatic dependency rule above.

# start of automatic dependencies
main.o: cdb.h
access.o: cdb.h
assert.o: cdb.h
bp.o: cdb.h
cmd.o: cdb.h
cmdline.o: cdb.h
cpulib.o: cdb.h
csupport.o: cdb.h
dummy.o: cdb.h
cdbend.o: config.h
expr.o: cdb.h
files.o: cdb.h
format.o: cdb.h
help.o: cdb.h
list.o: cdb.h
lib.o: cdb.h
math.o: cdb.h
procedure.o: cdb.h
process.o: cdb.h
pt.o: cdb.h
signal.o: cdb.h
single.o: cdb.h
sym.o: cdb.h
tk.o: cdb.h
valid.o: cdb.h
var.o: cdb.h
xptrace.o: cdb.h
xptrace.o: xptrace.h
xremote.o: xptrace.h
waitSingle.o: cdb.h
waitMulti.o: cdb.h
0707070001000312661004440000000000010000011607660454650114300001400000016070cdb/Porting After the list of flags is the beginning of a general discussion of
porting CDB to new systems and environments.

COMPILE TIME FLAGS
These are the compile-time flags that can be set to affect how CDB works.  
The value column shows the legal range of values.  The construct (a | b)
indicates that one of the set {a,b} is needed and that 'a' is the default
if left unspecified.  The value "--auto--" indictaes that the flag is
automatically derived from other values.

The lists for OS, CPU, MFG, etc. are in config.h.  If you need to add
something, let us know so it can be added to the master copy.

Name		Value(s)	Explanation
-------------	------------	--------------------------------------------
CDB_DEBUG	(0 | 1)		Used to #if certain pieces of code. (obsolete)
SYS		from SYS list	Unique name specifying a particular
				implementation.
OP_SYS		from OS list	Operating system CDB is running under.
REMOTE_OS	from OS list	OS for target. Defaults to OP_SYS.
ANY_BSD		--auto--	Indicates OS is a Berkely derivative.
CPU		from CPU list	Machine target is running on.
HOST_CPU	from CPU list	Machine CDB is running on. Defaults to CPU.
MFG		from MFG list	Manufacturer of Host/Remote system.
COMPILER	from list	Specifies compiler peculiarities (e.g. Green
				Hills register saving).
LANG_C		(1 | 0)		Include C language routines.
LANG_FORTRAN	(0 | 1)		Include FORTRAN language routines.


These two are used only in compiling "dummy.c"

REMOTE		(0 | 1)		Loaded with real remote routines, not dummies.
WINDOWS		(0 | 1)		Loaded with real window routines, not dummies.


These flags are normally set in the CPU default section in config.h.

BPT_INST	value		Breakpoint instruction.
BPT_BACKUP	(0 | 1)		PC must be backed up to point at BPT.
CALLEE_STACK_CLEANUP (0 | 1)	Calle does stack cleanup
FPISAP		(0 | 1)		Frame ptr and Argument ptr are the same.
LONGLONG	(0 | 1)		System has type (long long).
REGT		(unsigned int)	An unsigned type the same size as a register.
BYTE_SEX    byteSex{Little,Big}	E.g. Vax == Little, 68000 == Big
BIT_SEX      bitSex{Little,Big}	E.g. Vax == Little, 68000 == Big
ALIGNMENT	(0,1,3)		Alignment mask for 4 byte integers
				0 = On any byte address
				1 = On any EVEN address
				3 = On any FOUR BYTE address


These flags are highly system dependent.

INTEGER_OFFSETS	(0 | 1)		Param offsets in symtab are a little off.
V7_PRINTF	(0 | 1)		Host system printf does not support "%#x".
ADR_USER	(adrNil)	Base address of struct user in KERNEL space.
ADR_REG0	(adrNil)	Offset of register 0 from ADR_USER.
ADR_U_AR0	(adrNil)	Offset of u.u_ar0.
LOCAL_COMM_INIT	(0 | 1)		Local init/handshake for remote comm.
ADR_TEXT_BASE	0		Lowest address user programs are loaded at.
ADR_PROC_BASE	0		
CLEAR_FP	(1 | 0)		Set FP to 0 on creation of new child.
ADR_START_LOW	(adrNil)	First address of start frame.
ADR_START_HIGH	(adrNil)	Last address of start frame + 1.
TRAMPOLINE	(0 | 1)		Siganl handling uses trampoline code


These flags are defaulted based on OP_SYS. HOWEVER(!), they tend to be
*massively* system dependent.  You must have the correct definitions
for EXEC_F1,B1,E1 for CDB to work at all. EXEC_F2,B2,C2 allow you
to look at initialized globals when there is no child and no core.
The CORE values are necessary only if you can/want to look at core files.

EXEC_B1		Lowest text address
EXEC_E1		Highest text address + 1
EXEC_F1		File address of byte with address EXEC_B1
EXEC_B2		Lowest data address
EXEC_E2		Highest data address + 1
EXEC_F2		File address of byte with address EXEC_B2

CORE_B1		Lowest data address
CORE_E1		Highest data address + 1
CORE_F1		File address of byte with address CORE_B1
CORE_B2		Lowest stack address
CORE_E2		Highest stack address + 1
CORE_F2		File address of byte with address CORE_B2

TXTRNDSIZ
cbCodeOffset
cbStorageMax
INT_16
N_DATADDR
DEBUG


These flags are normally specified in the appropriate CPU module.
If one is DEFINED, then the corresponding routine will NOT be compiled
in the module "cpulib.c". 

If DEFINED			You have a special routine to
------------------		-----------------------------------------------
X_InitRegisters			Initialize register array.
X_InitSpecials			Initialize "system special" variables.
X_ListRegisters		  	List of register array.
X_GetByte			Get a byte.
X_PutByte			Put a byte.
X_GetBlock			Get a block.
X_PutBlock			Put a block.
X_GetReg			Get a register.
X_PutReg			Put a register.
X_ReadPc			Read the PC and setup magic values.
X_SetCntx			Create the pr->cntx record.
X_SaveState			Save register state.
X_RestoreState			Restore register state.
X_MoveBytes			High speed memory-to-memory block copy.
X_ValFReg			Get a typed register.
X_StoreReg			Put typed register.
X_ValFUser			Get a typed struct user field.
X_StoreUser			Put typed struct user field.
X_InstallBp			Install breakpoints.
X_RemoveBp			Remove breakpoints.
X_GetArgN			Get the Nth argument of a proc w/o symbols.
X_DispUnknown			Display the frame for a proc w/o symbols.
X_FixPc				Fix the PC after a breakpoint.
X_FinishCpu			Cleanup on debugger shutdown.
X_InitCpu			Setup the CPUR record.

These are used for procedure call from the command line.
If DEFINED			You have a special routine to
------------------		-----------------------------------------------
X_SavePcFp			Create magic frame on stack.
X_SetCallProc			Set all registers, push arguments.
X_CallProcedure			Actually do the call.
X_SeFReturn			Extract the return value from whereever.




Porting CDB should prove to be substantialy easier than porting other
debuggers.  This is largely due to the fact that it already has been
ported to over 50 systems.  These systems vary in minor and major ways.
Whenever we have encountered a difference, we have striven to understand
what the general solution was and recoded for that case.

The debugger is composed of 5 major subsections:

    1. The Central Debugger is that code that seems to be independent
	of everything else.
    2. The cpu modules contain code specific to a given architecture.
    3. The os modules contain code specfic to a given operating system.
    4. The communication method used to control the target process.
    5. The wait modules "wait" differently for single process and
	multiprocess situations.


Porting to a New System 

The best approach to bringing the debugger up in a new environement is to
look at the options currently available and pick those that are closest
to the new situation.  For example, when we did the NSC 32000 port, we
already had the VAX port done.  Since the 32000 is closer in many ways
to a VAX than it is to a 68000, we started with the cpuVax module and
hacked it from there.  We also started with the SYS.h info for a VAX and
modified as necessary to produce the SYS.h info for the 32000.


Tweaking an Existing Port

Given the growing number of machines that CDB already works with, it is
more likely that all the pieces you need are in place, but some of the
values (or equations) being used are not correct for your system.  For
example, I have yet to see two 68000 systems (either BSD or System V)
that have the same ADR_TEXT_BASE (the lowest address that user code
is normally loaded at).  Another value that seems to change a lot is
ADR_USER (the base address of "stuct user u" in the kernel).



0707070001000312671004440000000000010000011610560454650114300001400000002230cdb/READ_ME Welcome to the CDB Source Directory

This directory contains the following:

    1.	The source code for CDB.
    2.	Configure, a shell script for setting up for compilation.
    3.	Documentaion for CDB
	cdb.1	    The man pages for CDB.  This is intended as a
		    TROFF file but it should work OK for nroff.
		    To print it: `n/troff -man cdb.1'

	cdbtrans.1  The man pages for the symbol table translator used
		    by CDB.

	names	    This explains the naming conventions used inside of CDB.
		    It uses the MM macro package for n/troff.
	
	Camera ready copies of these documents are supplied.
	Feel free to make as many copies as necessary.


In order to install CDB you need to do the following:

    1.  You need to have write permission to the directory you will
        be installing into AND write permission for directory
	/usr/lib (probably this means being 'root').

    2.  Execute 'Configure'.  If you do not see your system listed as
	one of the options, call Third Eye Software.

    3.  Execute 'make all'.  Make sure that the system echoed is the
	one that you want.

    4.  Execute 'make install'.

$Header: READ_ME,v 5.7 86/04/07 22:05:30 peter Exp $
0707070001000312701004440000000000010000011610740454650114300002100000000657cdb/READ_ME_DEMO This directory contains a short demonstration of CDB.  The demo program
is a trivial file that does nothing interesting.  The main idea is to
show you just a few of the many features of CDB and to encourage you
to read the manual pages.  We find that most users of CDB limit
themselves to just a few commands.  Many of them are completely unware
of some the more interesting aspects of CDB.

To run the demo, simply type "dodemo".
0707070001000312711004440000000000010000011611030454650114300001300000000042cdb/dodemo wdb -Z0 -p cdbdemo.script cdbdemo
0707070001000312721004440000000000010000011611120454650114300001400000000330cdb/ext.sed s/[	]/ /g
s/.*://
t clear2
: clear2

s/^.*exportdefine/#define/
t end

s/^export/extern/
s/;.*/;/
s/ *=.*/;/
t clear1
: clear1

s/(/(/
t proc

s@\[[^\[]*\]@\[\]@g
b end

: proc
s/(\(.*\)).*/(\/\* \1 \*\/);/

: end
b
0707070001000312731004440000000000010000011611210454650114300001200000015500cdb/names .ds CX $Header: names,v 5.2 86/05/02 19:04:20 peter Exp $
.ds CC (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Resereved
.nr N 4
.nr O 1i
.nr S 12
.so /usr/lib/tmac/tmac.m
.TL
Type, Variable and Procedure Naming Conventions
.AU "Peter W. Rowell" PWR
.MT 4
.P
The names used throughout Third Eye Software's various products
adhere to a fairly rigid system.
This system is based on one originally developed by Charles Simonyi.
There are several aims to this system, the most important of which are:
.BL 5
.LI
Visual type checking.
It is \fIimmediately\fP obvious that an assignment or index is incorrect.
E.g. ``monthNext\ \=\ yearLast'' is clearly wrong.
.LI
Reduction and/or elimination of name conflicts.
Two things (variables or whatever) can only have the same name if
they are in fact the same thing.
.LI
Decrease in name choosing time.
Since the ``creativity'' has been removed, names are not \fIchosen\fP
\- they are constructed.
.LI
Enhanced readability/maintainability of the code.
Since all programmers working on a project are using the \fIsame\fP
naming convention, where one person leaves off and another starts
is not only \fIvisually\fP undetectable, it often becomes
\fIemotionally\fP less important to the programmers involved.
This reduces intra-group finger pointing, etc.
.LE
.sp 1
.P
\fBRules of Name Construction\fP
.AL 1
.LI
All variable names start with a lower case letter.
E.g. foo.
.LI
All function names start with an upper case letter.
E.g. Procedure.
.LI
Variables, and functions that return a value, start with the
a 1 to 4 character type specifier.
E.g. fooLast and FooFromAdr.
.LI
Variable names may have 0 or more trailing modifiers to indicate
their particular usage in the current context.
E.g. foo, fooFirst, fooFirstKludge.
.LI
All global variables have the character `v' prepended.
E.g. vfooNext.
Historically, the `v' meant ``virtual''.
.P
NOTE:  Although manifest constants are
.SM NOT
distinguished by all upper case, this does not cause a problem.
If what looks like
a variable does not begin with `v',
and it is not defined in the current procedure, it
.SM MUST
be a constant.
.LE
.P
The rules for constructed TYPES are:
.AL 1
.LI
All type names, other than primitives of the language (e.g. char),
have a base type that is all upper case.
E.g. typedef char * ADRT.
.LI
The last letter indicates the `class' of the type.
Specifically:
.LE
.VL 13 4
.LI T
means that this Type is simply a different name for one of the
language primtives.
(e.g. typedef char FLAGT;)
.LI S
means that the type is a Struct.
(e.g. struct FOOS {int x;};).
.LI R
means that the type is a Record (struct in C).
(e.g. typedef struct FOOS FOOR;).
.LI U
means the type is a Union.
.LI E
means an Enumerated type.
This notation is also used with `#define'd values if their usage is
the same as enums.
E.g. a storage class might look like:
.DS
typedef enum {scText, scData, scBss} SCE;
.DE
.LI p
Pointers occur for many types and are constructed by prepending
a lower case `p' to the type name.
.DS
typedef FOOR *pFOOR; /* creates the type `pointer to FOOR' */
.DE
.LE
.P
There are certain concepts that appear repeatedly.
These often are simple types such as `index' or `count' that may
apply to all sorts of situations.
Examples are shown below.
The declared type is \fIint\fP unless shown in ()'s.
.VL 13 4
.LI cApples
Count of apple's.
.LI ifoo
Index of foo's.
.LI dx
The first Difference of x. (dx = xFirst - xLast)
.LI cbFoo
Count of Bytes in foo.
.LI cbFOOR
Count of bytes in a record of type FOOR.
This is normally `#define cbFOOR sizeof(FOOR)'.
.LI chFoo
Character relating to a Foo. (char)
.LI sbFile
String of bytes (character string).
(char *sbFile OR char sbFile[10])
.LI fDidit
A flag (boolean).
(smallest type available OR 1 bit field)
.LE
.P
Modifiers may be added to clarify the usage of a particular value.
Certain modifiers have well defined meanings.
These are:
.VL 13 4
.LI fooNil
A standard Nobody-Home value for foo.
Depending on
FOO, this may be -1, 0, ((pFOOR)0), or ???.
This value is almost guaranteed to be `#define'd.
.LI fooFirst
First foo value.
For all foo, fooX >= fooFirst.
.LI fooLast
Last foo value.
For all foo, fooX <= fooLast.
.LI fooMin
Minimum value of foo.
For all foo, fooX >= fooMin.
.LI fooLim
Limit of foo.
For all foo, fooX < fooLim.
Used for
non-index type values.
.LI ifooMax
Maximum value of ifoo.
For all foo, fooX < fooMax.
Used mostly in the form `ifooMax'.
This value is almost always `#define'd.
An exception is the size of dynamic arrays.
.LI ifooMac
The Current maximum ifoo value.
When ifoo is the domain of an array used as a stack,
ifooMax is the total size, and ifooMac is what we are currently using.
ifoo < ifooMac <= ifooMax.
.LE
.P
Values in some sequence may be modified by:
fooPrev, fooInit, fooLow, fooHigh, fooNext, fooOld, fooNew, etc.
.P
The conventions for array declarations are:
.VL 13 4
.LI mpBarFoo
an array (MaP) with domain BAR and range FOO.
E.g. fooX = mpBarFoo[barFirst];
.LI rgFoo
an array with domain `ifoo' and range FOO.
E.g. fooX = rgFoo[ifoo];
.LE
.sp 1
.P
\fBProcedures\fP
.P
Procedure names are inherently more complex and the conventions are less rigid.
If a value is returned, it is always the first part of the name.
The letter `F' indicates a mapping From the arguments to the return value(s).
The 1 or 2 most important arguments occur after the 'F'.
E.g. IpdFAdr(adr) returns an Index into the Procedure Descriptor array
as a function of an ADdRess.
.P
In the case where some arguments are being passed by reference, these
are always the first in the argument list, mimicing the ordering in the
assignment statement.
.P
If there is no return value, then the name is composed of an imperative verb
(Do, Get, Put, Print, etc.) followed by the first one or two argument
types (PutCh, PrintLine, etc.).
.bp
.P
\fBExamples\fP
.P
The following examples show how the naming conventions work together.
.sp 1
.nf
.cs 1 21
typedef char *ADRT;              /* an address type of some sort */
#define adrNil ((ADRT)0)         /* standard nil value */

typedef enum {fsNil,             /* foo state */
              fsActive,
              fsDead
              } FSE, *pFSE;

typedef struct FOOS {            /* the FOO structure */
        ADRT    adrFirst;
        ADRT    adrLast;
        struct FOOS *fooNext;    /* essentially of type pFOOR */
        FSE     fs;
        } FOOR, *pFOOR;
#define cbFOOR sizeof(FOOR)
#define fooNil ((pFOOR)0)        /* standard nil value */

#define ifooMax 100              /* size of foo array */
FOOR    vrgFoo[ifooMax];         /* global array of foo's */
int     vifooMac;                /* how many foo's we are currently using */

ADRT AdrFFoo(foo)
pFOOR   foo;
{
    if (foo->fs == fsActive)     /* some random computations */
        return(foo->adrFirst);
    return(adrNil);
}

void FreeFoo(foo)                /* does NOT return a value */
pFOOR   foo;
{
    /* deallocate in some way... */
    foo->fs = fsDead;
}
.fi
0707070001000312741004440000000000010000011605530454650114300001400000000014cdb/version /*	0	0	7	*/
0707070001000312751004440000000000010000011605620454650114300001100000046033cdb/tags APR	var.c	?^#define APR(x)		((uint4)(&(((pPRR)0)->x)))$?
Access	access.c	?^export int Access(accRequest, adr, space, value)$?
AddAssert	assert.c	?^export void AddAssert(sbCheck, cb)$?
AddDir	files.c	?^export void AddDir(pr, sbDir)$?
AddOptions	main.c	?^export void AddOptions(sbOption, va_alist)$?
AddTq	csupport.c	?^export void AddTq(se, tq)$?
AdjustFieldOffset	var.c	?^export void AdjustFieldOffset(seStruct, seField)$?
AdrFEndOfProc	sym.c	?^export ADRT AdrFEndOfProc(ipd)$?
AdrFIfdIln	sym.c	?^export ADRT AdrFIfdIln(ifd, iln)$?
AdrFIpdIln	sym.c	?^export ADRT AdrFIpdIln(ipd, iln)$?
AdrFLabel	var.c	?^export ADRT AdrFLabel(sbLabel)$?
AdrFPreamble	cpu.c	?^export ADRT AdrFPreamble(adr)$?
AdrFPurify	access.c	?^export ADRT AdrFPurify(adr, fExec)$?
AdrFReg	cpulib.c	?^export ADRT AdrFReg(reg)$?
AdrFReturnPc	single.c	?^local ADRT AdrFReturnPc()$?
AdrFSe	expr.c	?^export ADRT AdrFSe(se)$?
AdrFStackFix	cpu.c	?^export ADRT AdrFStackFix(adr)$?
AdrFStore	expr.c	?^export ADRT AdrFStore(sb, cb)$?
AdrFirstFIpd	files.c	?^export int AdrFirstFIpd(ipd)$?
AdrRegFCntx	cpu.c	?^local ADRT AdrRegFCntx(cntx, reg)$?
AgeFFn	sym.c	?^export long AgeFFn(fn)$?
Alarm	os.c	?^local void Alarm()$?
AllBpInstall	bp.c	?^export void AllBpInstall()$?
AnalyzeStop	pt.c	?^export void AnalyzeStop()$?
ApplyOptions	main.c	?^export void ApplyOptions(pr, sbOptions)$?
Assign	csupport.c	?^export void Assign(seDest, seSrc)$?
AuxFIaux	sym.c	?^export pAUXU AuxFIaux(iaux)$?
BlockTransfer	access.c	?^export void BlockTransfer(adrDest, adrSrc, space, ?
BpFAddBp	bp.c	?^export pBPR BpFAddBp(adr, count, sbCmd, cb)$?
BpFAdr	bp.c	?^export pBPR BpFAdr(adr)$?
BpFForkSave	bp.c	?^export pBPR BpFForkSave(pid, adr)$?
BpFIfdIln	bp.c	?^export pBPR BpFIfdIln(ifd, iln)$?
BpFProcess	bp.c	?^export pBPR BpFProcess(adr)$?
BpFSet	bp.c	?^export pBPR BpFSet(bpc, fTemp, cnt, sbCmd, cb)$?
CallProcedure	cpulib.c	?^export void CallProcedure(adrProc, seFirst, cArg)$?
CallShell	cmd.c	?^export void CallShell(sbCmd)$?
CargFIpd	procedure.c	?^export int CargFIpd(ipd)$?
CbFCh	format.c	?^export int CbFCh(ch)$?
CbFSe	csupport.c	?^export int CbFSe(se)$?
CblFFn	sym.c	?^export long CblFFn(fn)$?
CdbExit	main.c	?^export void CdbExit(value)$?
CenterWw	dummy.c	?^export void CenterWw() { }$?
ChFChoice	cmdline.c	?^export char ChFChoice(sbPrompt, sbChoice)$?
ChFEscape	tk.c	?^export char ChFEscape(psbIn, fEatBackSlash)$?
ClearAllBp	bp.c	?^export void ClearAllBp()$?
ClearBp	bp.c	?^export void ClearBp(bp)$?
ClearCol	lib.c	?^export void ClearCol()$?
ClearMore	lib.c	?^export void ClearMore()$?
ClearTargetScreen	dummy.c	?^export void ClearTargetScreen() { }$?
CloseComm	dummy.c	?^export void CloseComm() { }$?
CntxFIpd	var.c	?^export pCNTXR CntxFIpd(cntx, pipd, cnt)$?
Coerce	csupport.c	?^export void Coerce(seTo, seFrom)$?
ColOff	lib.c	?^export void ColOff()$?
ColOn	lib.c	?^export void ColOn()$?
ConvertFloat	expr.c	?^export void ConvertFloat(se, fFromHostToRemote)$?
CopyTy	csupport.c	?^export void CopyTy(seDest, seSrc)$?
CreateTarget	dummy.c	?^export void CreateTarget()$?
DeallocPr	process.c	?^export void DeallocPr(pr, fSaveLocals)$?
DebugIt	cmdline.c	?^export void DebugIt(fTopLevel)$?
DfFCh	format.c	?^export DFE DfFCh(ch)$?
DfFSe	format.c	?^export DFE DfFSe(se, fAlternate)$?
DispFrame	var.c	?^export void DispFrame(cntx, cnt, fDoLocals, fList)?
DispUnknown	cpulib.c	?^export void DispUnknown(cntx, ipd)$?
DisplaySe	format.c	?^export void DisplaySe(se, mode, fShowAdr, fIndirec?
DoArgs	pt.c	?^export void DoArgs(sbProgram, sbArgs, argv, fReass?
DoCase	math.c	?^#define DoCase(OP, XX) seRet->val.XX = se1->val.XX?
DoCoerce	csupport.c	?^#define DoCoerce(btX, valX)\\$?
DoCommon	dummy.c	?^export void DoCommon() {}$?
DoException	math.c	?^#define DoException(OP)	   switch (bt) {\\$?
DoMap	access.c	?^export void DoMap()$?
DoNormal	math.c	?^#define DoNormal(OP)	switch (bt) {\\$?
DoProc	math.c	?^#define DoProc(Name, Do, op) void Name(seRet, se1,?
DoReg	cpu.c	?^export void DoReg(seReg, cntx)$?
EatCmdList	cmd.c	?^export char * EatCmdList(pcnt)$?
EatFilename	cmd.c	?^local void EatFilename(sbName, psbIn)$?
EdOpenFile	dummy.c	?^export void EdOpenFile() { }$?
EditFile	files.c	?^export void EditFile(ifd, iln)$?
ExecInit	pt.c	?^export void ExecInit(fInit)$?
ExtractBits	expr.c	?^export long ExtractBits(x, pos, width)$?
FAtCall	cpu.c	?^export FLAGT FAtCall(adr)$?
FBinOpLegalFSe	csupport.c	?^local FLAGT FBinOpLegalFSe(se)$?
FBlockCmp	lib.c	?^export int FBlockCmp(sb1, sb2, cb)$?
FCallUserProc	procedure.c	?^export FLAGT FCallUserProc(sbProc, cArg, arg1)$?
FChkCommand	cmd.c	?^local FLAGT FChkCommand()$?
FDoAssert	assert.c	?^export FLAGT FDoAssert(pt)$?
FDoCommand	cmd.c	?^export FLAGT FDoCommand(sbCmdIn, fTop)$?
FEnum	var.c	?^export FLAGT FEnum(se)$?
FField	var.c	?^export FLAGT FField(seStruct, seField)$?
FGlobal	var.c	?^export FLAGT FGlobal(se)$?
FHdrCmp	sym.c	?^export FLAGT FHdrCmp(sbHdr, sbCheck)$?
FLocal	var.c	?^export FLAGT FLocal(se, ipd, cnt)$?
FNextLocal	sym.c	?^export FLAGT FNextLocal(fLocal, fParam, isym)$?
FNextSym	sym.c	?^export FLAGT FNextSym(stHit1, stHit2, stHit3, stSt?
FOctal	tk.c	?^#define FOctal(ch) ((ch >= '0') && (ch <= '7'))$?
FSaveAssertions	assert.c	?^export FLAGT FSaveAssertions(fp)$?
FSaveBp	bp.c	?^export FLAGT FSaveBp(fp)$?
FSbCmp	sym.c	?^export FLAGT FSbCmp(sb1, sb2)$?
FSpecial	var.c	?^export FLAGT FSpecial(seRet)$?
FTailCmp	sym.c	?^export FLAGT FTailCmp(sbTail, sbIn)$?
FTimedInput	os.c	?^export FLAGT FTimedInput(cSeconds)$?
FTypeFName	var.c	?^export FLAGT FTypeFName(seType, tk)$?
FUpper	cdb.h	?^#define FUpper(ch) (((ch) >= 'A') AND ((ch) <= 'Z'?
F_PxSe	dummy.c	?^export void F_PxSe() {}$?
F_SymFAdr	dummy.c	?^export pSYMR F_SymFAdr() {}$?
Find	files.c	?^export void Find(sbTarget, fBack)$?
FindAndFix	help.c	?^export void FindAndFix()$?
FinishCpu	cpulib.c	?^export void FinishCpu()$?
FixPc	cpulib.c	?^export void FixPc()$?
Fixer	lib.c	?^export void Fixer()$?
FpFSb	files.c	?^FILE *FpFSb(sbFile, sbFlags)$?
FreeProcess	dummy.c	?^export void FreeProcess() {}$?
GetAdr	csupport.c	?^export void GetAdr(se)$?
GetArgN	cpulib.c	?^export void GetArgN(cntx, se, iarg)$?
GetBlock	cpulib.c	?^export void GetBlock(adrSrc, space, adrDest, cb)$?
GetByte	cpulib.c	?^export uint1 GetByte(adr, space)$?
GetMode	format.c	?^export void GetMode(mode)$?
GetOrig	csupport.c	?^export void GetOrig(se)$?
GetReg	cpulib.c	?^export REGT GetReg(reg)$?
GetUser	access.c	?^export REGT GetUser(adr)$?
GetVal	csupport.c	?^export void GetVal(se)$?
GetWord	access.c	?^export int GetWord(adr, space)$?
GotoIln	cmd.c	?^export void GotoIln(iln)$?
Help	help.c	?^export void Help()$?
Highlight	dummy.c	?^export void Highlight() { }$?
IFPattern	os.c	?^export int IFPattern(sbLine)$?
IfdFAdr	sym.c	?^export int IfdFAdr(adr)$?
IfdFIsym	sym.c	?^export int IfdFIsym(isym)$?
IfdFName	files.c	?^export int IfdFName(sbFile)$?
IfdIlnFAdr	sym.c	?^export int2 IfdIlnFAdr(piln, adr)$?
IlineLimFIpd	sym.c	?^local int4 IlineLimFIpd(ipd)$?
IlnFNormalize	cmd.c	?^export int IlnFNormalize(ifd, iln)$?
IlnFirstFIpd	files.c	?^export int IlnFirstFIpd(ipd)$?
IncFSeMode	format.c	?^export int IncFSeMode(se, mode, multiplier)$?
InitAllWw	dummy.c	?^export void InitAllWw() { }$?
InitComm	dummy.c	?^export void InitComm() { }$?
InitCore	os.c	?^export void InitCore(pr)$?
InitCpu	cpulib.c	?^export void InitCpu(cpu)$?
InitHostCpu	cpulib.c	?^export void InitHostCpu(cpu)$?
InitMyTty	os.c	?^export void InitMyTty()$?
InitOs	os.c	?^export void InitOs(pr)$?
InitPattern	os.c	?^export void InitPattern(sbPattern)$?
InitPr	process.c	?^export void InitPr(pr)$?
InitProcessTable	process.c	?^export void InitProcessTable()$?
InitRegisters	cpulib.c	?^export void InitRegisters(cpu)$?
InitSa	os.c	?^export void InitSa()$?
InitSe	csupport.c	?^export void InitSe()$?
InitSignals	os.c	?^export void InitSignals()$?
InitSpc	var.c	?^export void InitSpc(se, sb, value, st, sc, tq0, bt?
InitSpecials	var.c	?^export void InitSpecials()$?
InstallBp	cpulib.c	?^export void InstallBp(bp)$?
IntFSb	cpu.c	?^#define	IntFSb(sb) ((int)sb)$?
IpdFAdr	sym.c	?^export int IpdFAdr(adr)$?
IpdFName	files.c	?^export int IpdFName(sbProc)$?
IpdIlnFAdr	sym.c	?^export int IpdIlnFAdr(piln, pslop, adr)$?
IprFPr	process.c	?^export int2 IprFPr(pr)$?
IssFSb	sym.c	?^export int4 IssFSb(sb)$?
IssSafeFSb	sym.c	?^export int4 IssSafeFSb(sb)$?
IsymFAdr	var.c	?^export long IsymFAdr(adr, isymHint)$?
IsymFEnclosing	var.c	?^export long IsymFEnclosing(adr)$?
IsymFSym	sym.c	?^export int4 IsymFSym(sym)$?
IsymNextFBlock	var.c	?^export long IsymNextFBlock(isym)$?
JumpScrollWw	dummy.c	?^export void JumpScrollWw() { }$?
KillChild	pt.c	?^export void KillChild()$?
LineFIline	sym.c	?^export pLINER LineFIline(iline)$?
ListAssert	assert.c	?^export void ListAssert()$?
ListBp	bp.c	?^export void ListBp()$?
ListDir	files.c	?^export void ListDir()$?
ListFiles	list.c	?^local void ListFiles(sbFile)$?
ListGlobals	list.c	?^local void ListGlobals(sbGlobal)$?
ListLocals	list.c	?^local void ListLocals(sbProc, cnt)$?
ListPr	process.c	?^export void ListPr(prIn)$?
ListProcs	list.c	?^local void ListProcs(sbProc)$?
ListRegisters	cpulib.c	?^export void ListRegisters(sbRegs)$?
ListSa	signal.c	?^export void ListSa()$?
ListSomething	list.c	?^export void ListSomething()$?
ListSpecials	var.c	?^export void ListSpecials(sbSpc)$?
ListTypedefs	list.c	?^local void ListTypedefs(sb)$?
LongFExpr	expr.c	?^export int4 LongFExpr(seRet, tk)$?
LongFRound	lib.c	?^export int4 LongFRound(x, y)$?
LongFSb	main.c	?^export int4 LongFSb(sb)$?
LongJmp	os.c	?^export void LongJmp(env)$?
MakeActive	dummy.c	?^export void MakeActive() { }$?
MarkLine	dummy.c	?^export void MarkLine() { }$?
Mask	expr.c	?^#define Mask(width) (~(~0L<<width))	/* generate a ?
Max	csupport.c	?^export int Max(x, y)$?
MaxFSeSe	csupport.c	?^local FLAGT MaxFSeSe(seMax, se1, se2)$?
Min	csupport.c	?^export int Min(x, y)$?
Mmain	main.c	?^export void main(argc, argv, envp)$?
ModAssert	assert.c	?^export void ModAssert(iad, as)$?
MoreOff	lib.c	?^export void MoreOff()$?
MoreOn	lib.c	?^export void MoreOn()$?
MoveBytes	cpulib.c	?^export void MoveBytes(adrDest, adrSrc, cb)$?
Mul	math.c	?^void Mul(seRet, se1, se2)$?
NOT	cdb.h	?^#define NOT(x)	(!(x))$?
NewChild	pt.c	?^export void NewChild(sbArgs, fInit)$?
NextCmd	cmdline.c	?^export void NextCmd(sbBuffer, cbBuffer, sbPrompt)$?
NextFrame	cpu.c	?^export int NextFrame(cntx)$?
NextInstAdrFAdr	cpu.c	?^local ADRT NextInstAdrFAdr(adr)$?
Oops	os.c	?^export void Oops(sig)$?
OpenIfd	files.c	?^export void OpenIfd(ifd)$?
OpenIpd	files.c	?^export void OpenIpd(ipd, fForce)$?
OpenStack	var.c	?^export void OpenStack(cnt)$?
OsCreateTarget	os.c	?^export void OsCreateTarget()$?
PadTo	lib.c	?^export void PadTo(col)$?
Panic	lib.c	?^export void Panic(sbMsg, arg1, arg2, arg3, arg4)$?
ParamOffset	var.c	?^local int ParamOffset(pc)$?
PlaybackFile	cmdline.c	?^export void PlaybackFile(sbFile)$?
PrFAlloc	process.c	?^export pPRR PrFAlloc()$?
PrFAttachProcess	dummy.c	?^export pPRR PrFAttachProcess() {UError(vsbMultiErr?
PrFExec	dummy.c	?^export pPRR PrFExec() {UError(vsbMultiErr);}$?
PrFFn	process.c	?^export pPRR PrFFn(fn)$?
PrFInitPr	process.c	?^export pPRR PrFInitPr(sbExec)$?
PrFIpr	process.c	?^export pPRR PrFIpr(ipr)$?
PrFPid	process.c	?^export pPRR PrFPid(pid)$?
PrFSb	process.c	?^export pPRR PrFSb(sb)$?
PrintInstruction	dis.c	?^export void PrintInstruction(adr)$?
PrintLine	files.c	?^export void PrintLine(iln, count, fPrintLn, fp)$?
PrintNest	format.c	?^exportdefine PrintNest(cNest, cb) if (cNest) print?
PrintPosition	files.c	?^export void PrintPosition(adr, fmt)$?
PrintUsage	main.c	?^local void PrintUsage()$?
PrintVersion	dummy.c	?^export void PrintVersion(x)$?
Ptrace	dummy.c	?^export int Ptrace(pt, pid, adr, value)$?
Purchase	valid.c	?^Purchase() {}$?
PutBlock	cpulib.c	?^export void PutBlock(adrDest, space, adrSrc, cb)$?
PutByte	cpulib.c	?^export void PutByte(adr, space, val)$?
PutReg	cpulib.c	?^export void PutReg(reg, val)$?
PutUser	access.c	?^export void PutUser(adr, val)$?
PutWord	access.c	?^export void PutWord(adr, space, val)$?
PxCommon	dummy.c	?^export void PxCommon() {}$?
PxEnum	format.c	?^export void PxEnum(se)$?
PxProc	format.c	?^export void PxProc(ipd, fDoName, fAlternate)$?
PxSe	format.c	?^export void PxSe(se, fAlternate)$?
PxStruct	format.c	?^export void PxStruct(seStruct, cntStruct, fDoVal, ?
ReadData	access.c	?^export void ReadData(adrDest, adrSrc, cb)$?
ReadPc	cpulib.c	?^export void ReadPc()$?
ReapChildren	process.c	?^export void ReapChildren()$?
RecordCmd	cmdline.c	?^export void RecordCmd(sbCmd)$?
RemoveAllBp	bp.c	?^export void RemoveAllBp()$?
RemoveBp	cpulib.c	?^export void RemoveBp(bp)$?
RemoveTq	csupport.c	?^export void RemoveTq(se)$?
ResFOps	csupport.c	?^export void ResFOps(seRet, se1, se2)$?
RestoreAllWw	dummy.c	?^export void RestoreAllWw() { }$?
RestoreState	cpulib.c	?^export void RestoreState(sbSave)$?
RetFSp	cpu.c	?^export ADRT RetFSp(sp)$?
Rotate	expr.c	?^#define Rotate(along, cnt) \\$?
RunProcess	pt.c	?^export void RunProcess(pt, ps, fWait)$?
SaMaintain	signal.c	?^export void SaMaintain(sig, sbOptions, sbCmds)$?
SaveAll	main.c	?^export void SaveAll()$?
SaveForkBp	bp.c	?^export void SaveForkBp(bp)$?
SavePcFp	cpulib.c	?^export void SavePcFp()$?
SaveState	cpulib.c	?^export SBT SaveState()$?
SbConcat	lib.c	?^export char * SbConcat(sbDest, sb1)$?
SbFAdr	format.c	?^export SBT SbFAdr(adr, fMask)$?
SbFAlloc	files.c	?^export SBT SbFAlloc(sb)$?
SbFBase	files.c	?^export SBT SbFBase(sb)$?
SbFBinary	format.c	?^export SBT SbFBinary(value, cbits)$?
SbFBt	csupport.c	?^export SBT SbFBt(bt)$?
SbFEob	cmd.c	?^export SBT SbFEob(sb)$?
SbFError	os.c	?^export SBT SbFError(error)$?
SbFIpd	sym.c	?^export SBT SbFIpd(ipd)$?
SbFIss	sym.c	?^export SBT SbFIss(iss)$?
SbFLabelAdr	var.c	?^export SBT SbFLabelAdr(adr)$?
SbFNearest	var.c	?^export SBT SbFNearest(adr, fText, fData, fProcOnly?
SbFNextArg	pt.c	?^export SBT SbFNextArg(psbIn)$?
SbFPrepareLine	files.c	?^export SBT SbFPrepareLine(sbIn)$?
SbFPs	process.c	?^export SBT SbFPs(ps)$?
SbFReg	var.c	?^export SBT SbFReg(pc, reg)$?
SbFSearch	files.c	?^export SBT SbFSearch(sbFile, permissions)$?
SbFSignal	os.c	?^export SBT SbFSignal(sig)$?
SbFStackOffset	var.c	?^export SBT SbFStackOffset(pc, fFp, offset)$?
SbFSym	sym.c	?^export SBT SbFSym(sym)$?
SbOptionsFDefault	process.c	?^export SBT SbOptionsFDefault(sbExec)$?
SbSafeFIss	sym.c	?^export SBT SbSafeFIss(iss)$?
SbSafeFSb	sym.c	?^export SBT SbSafeFSb(sb)$?
SeFExpr	expr.c	?^export pSER SeFExpr(se)$?
SeFReturn	cpulib.c	?^export void SeFReturn(seRet, seProc)$?
SeFSym	csupport.c	?^export void SeFSym(se, sym, fRecurse)$?
SearchKw	tk.c	?^export void SearchKw(ptk, sbKey, rgKw, ikwMax)$?
SearchTd	tk.c	?^export void SearchTd(ptk, sb)$?
SendSignal	dummy.c	?^export int SendSignal(sig)$?
SetAdr	var.c	?^export void SetAdr(se, cntx)$?
SetBits	expr.c	?^export long SetBits(x, pos, width, val)$?
SetCallProc	cpulib.c	?^export void SetCallProc(adr, sp, cArg)$?
SetCmd	cmd.c	?^export void SetCmd(sb)$?
SetCntx	cpulib.c	?^export void SetCntx()$?
SetCommCache	access.c	?^export void SetCommCache(adrSrc, cb)$?
SetDemoTimer	os.c	?^export void SetDemoTimer(cSeconds)$?
SetGlobalPr	process.c	?^export void SetGlobalPr(pr)$?
SetHisTty	os.c	?^export void SetHisTty()$?
SetJmp	os.c	?^export int SetJmp(env)$?
SetMyTty	os.c	?^export void SetMyTty()$?
SetNextSym	sym.c	?^export void SetNextSym(isym)$?
SetOutput	cmdline.c	?^export void SetOutput(sbOutput)$?
SetPlayback	cmdline.c	?^export void SetPlayback(sbPlayback, fQuiet, fSingl?
SetPrompt	lib.c	?^export void SetPrompt(sbMsg, arg1, arg2, arg3, arg?
SetRecord	cmdline.c	?^export void SetRecord(sbRecord)$?
SetRgLn	files.c	?^local void SetRgLn(ifdIn, fp)$?
SetSrcWw	dummy.c	?^export void SetSrcWw() { }$?
SetViewPosition	files.c	?^export void SetViewPosition(adr)$?
ShowBp	dummy.c	?^export void ShowBp() { }$?
ShowState	cmdline.c	?^export void ShowState()$?
ShowViewPosition	files.c	?^ShowViewPosition(fmt)$?
SingleStep	single.c	?^export void SingleStep(cmd, fQuiet)$?
SpecialSideEffects	var.c	?^export void SpecialSideEffects(seNew, seCur)$?
StackDepth	var.c	?^export int StackDepth()$?
StackTrace	var.c	?^export void StackTrace(cnt, fDoLocals)$?
StateRecord	cmdline.c	?^export void StateRecord()$?
StoreReg	cpulib.c	?^export void StoreReg(seDest, seSrc)$?
StoreUser	cpulib.c	?^export void StoreUser(seDest, seSrc)$?
SwitchTtys	os.c	?^local void SwitchTtys(tty1, tty2)$?
SymFAdr	var.c	?^export pSYMR SymFAdr(adr, sb)$?
SymFIsym	sym.c	?^export pSYMR SymFIsym(isym)$?
SysPanic	lib.c	?^export void SysPanic(sbMsg, arg1, arg2, arg3, arg4?
TkFStr	tk.c	?^export TKE TkFStr(psbCmd, sbTok, pcb, fIgnoreError?
TkNext	tk.c	?^export TKE TkNext()$?
TkPeek	tk.c	?^export TKE TkPeek()$?
TqFSe	csupport.c	?^export int TqFSe(se, cnt)$?
UError	lib.c	?^export void UError(sbMsg, arg1, arg2, arg3, arg4)$?
UpLine	dummy.c	?^export void UpLine() { }$?
ValFReg	cpulib.c	?^export VALU ValFReg(se, cb)$?
ValFSe	expr.c	?^export VALU ValFSe(se)$?
ValFUser	cpulib.c	?^export VALU ValFUser(se)$?
Validate	valid.c	?^Validate() {$?
Wait	dummy.c	?^export int Wait(pstatus)$?
WriteData	access.c	?^export void WriteData(adrDest, adrSrc, cb)$?
WriteVal	expr.c	?^export void WriteVal(seDest, seSrc)$?
WwCmd	dummy.c	?^export void WwCmd() { }$?
XBlockTransfer	dummy.c	?^export void XBlockTransfer() { }$?
YesNo	cmdline.c	?^export int YesNo(sbPrompt)$?
ZeroBlock	csupport.c	?^export void ZeroBlock(sb, cb)$?
_cdbend	cdbend.c	?^_cdbend()$?
biti	dis.c	?^biti(inst, dummy)$?
copydown	history.c	?^copydown (line, pos, num)$?
copyup	history.c	?^copyup (line, pos, num)$?
cpbcc	dis.c	?^cpbcc(inst)$?
cpdbcc	dis.c	?^cpdbcc(inst)$?
cpgen	dis.c	?^cpgen(inst)$?
cprest	dis.c	?^cprest(inst)$?
cpsave	dis.c	?^cpsave(inst)$?
cpscc	dis.c	?^cpscc(inst)$?
cptrap	dis.c	?^cptrap(inst)$?
dprint	main.c	?^exportdefine dprint(x, y) {if (x <= v->debuglevel)?
extend	dis.c	?^extend(inst, opcode)$?
fprintf	lib.c	?^export int fprintf(fp, format, va_alist)$?
fullformat	dis.c	?^fullformat(reg, index)$?
getdisp	dis.c	?^getdisp(size)$?
h_get	history.c	?^h_get (index)$?
h_insert	history.c	?^h_insert (string)$?
h_modify	history.c	?^h_modify (buf)$?
h_print	history.c	?^h_print ()$?
h_search	history.c	?^h_search (str, len)$?
h_set	history.c	?^h_set (buf)$?
instfetch	dis.c	?^instfetch(size)$?
isnum	history.c	?^#define isnum(x) ((x >= '0') && (x <= '9'))$?
isodigit	tk.c	?^export int isodigit (ch)$?
mapsize	dis.c	?^mapsize(inst)$?
obits	dis.c	?^obits(inst)$?
obkpt	dis.c	?^obkpt(inst)$?
obranch	dis.c	?^obranch(inst,dummy)$?
ocallm	dis.c	?^ocallm(inst)$?
ocas	dis.c	?^ocas(inst)$?
ochk	dis.c	?^ochk(inst,opcode)$?
ochk2	dis.c	?^ochk2(inst)$?
oimmed	dis.c	?^oimmed(inst,opcode) $?
olink	dis.c	?^olink(inst,dummy)$?
olmul	dis.c	?^olmul(inst, opcode)$?
omove	dis.c	?^omove(inst, s)$?
omovem	dis.c	?^omovem(inst,dummy)$?
omoveq	dis.c	?^omoveq(inst,dummy)$?
oneop	dis.c	?^oneop(inst,opcode)$?
opmode	dis.c	?^opmode(inst,opcode)$?
oprint	dis.c	?^oprint(inst,opcode)$?
oquick	dis.c	?^oquick(inst,opcode)$?
oreg	dis.c	?^oreg(inst,opcode)$?
oscc	dis.c	?^oscc(inst,dummy)$?
otrap	dis.c	?^otrap(inst,dummy)$?
otrapcc	dis.c	?^otrapcc(inst)$?
pregmask	dis.c	?^pregmask(mask)$?
printEA	dis.c	?^printEA(ea,size)$?
printc	dis.c	?^printc(c) {$?
printea	dis.c	?^printea(mode, reg, size)$?
printf	lib.c	?^export int printf(format, va_alist)$?
redo	history.c	?^char *redo (realline)$?
shroi	dis.c	?^shroi(inst,ds)$?
sizeof	os.c	?^int visigSbMax = sizeof(vmpSigSb) / sizeof(SBT);$?
soneop	dis.c	?^soneop(inst,opcode)$?
strchr	lib.c	?^export char * strchr(sb, ch)$?
strcspn	lib.c	?^export int strcspn(sbSpan, sbNot)$?
strrchr	lib.c	?^export char * strrchr(sb, ch)$?
suffix	dis.c	?^char suffix(size)$?
yylex	expr.c	?^export int yylex()$?
0707070001000312761004440000000000010000011610050454650114400002100000002174cdb/xREAD_ME_REM If you will be working with CDB as a remote debugger, the following are
items of interest:

    1.	To make a remote debugger, see the make rule for "rdb".
	If you are using Third Eye's protocol, simply say "make rdb".

    2.	If you wish to test/observe Third Eye's protocol, execute
	the following: "rdb -tTEST foo", where foo is the executable.
	This will cause rdb to fork and exec a copy of the remote
	debug server.  This is about 98% accurate in terms of
	observable interactions between the debugger and the server.

	To see what is passing back and forth, type the following
	at the debugger prompt: "_comm=1".  This will print out
	what is transmitted and received by the host.  If you
	type: "_level=101" you will get even more debug info PLUS
	the level is passed to the remote server which will also
	print out debug info.

To use a remote debugger from a host to a target which have the same
byte order, ALL of your modifications will be restricted to a file
similar to xptrace.c.  If you think you MUST modify something else,
you should probably talk to Peter Rowell at Third Eye first.

		Third Eye Software, Inc.
		    415-321-0967
0707070001000312771004440000000000010000011610230454650114400002000000041130cdb/cdbremote.c /* $Header */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

/* This module is the REMOTE end of the CDB Standard Remote Debugging package.
 * It is set up to run as a normal UNIX user process.  To modify it for
 * use in other environments, simply implement the functionality without
 * changing the interface.  A full description of the protocol may be
 * found in the file "rptrace.h".
 */

#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <termio.h>
#include "rptrace.h"

#define O_RDONLY	0
#define chNull '\0'
typedef char *SBT;
#define sbNil ((SBT)0)
#define true 1
#define false 0
#define FLAGT unsigned short
#define FAST register
#define AND &&
#define OR ||

extern int errno;
extern void SendStatus();

#define DEBUG 0

#if DEBUG
#define dprint(x, y) {if (x <= vlevel) fprintf y; fflush(stderr);}
#else
#define dprint(x, y)
#endif

int	vpidChild = 0;	/* KLUDGE - this limits us to one sub-process */
int	vfCommDebug;	/* if true, causes echoing of all messages */
int	vlevel = 0;		/* debug print level for dprint */


#define cArgsMax	100	/* max number of args to child */
#define cbBufMax 1024	/* pick a number suited to the size of your system */
char	vsbBuf[cbBufMax];	/* buffer where we format messages */
SBT	vsbTx = vsbBuf;

int	vfnTx, vfnRx;
char	vsbTxLast[cbMsgMax]; /* copy of last transmisson */
char	vsbRxLast[cbMsgMax]; /* copy of last recieve data */
FLAGT	vfRecieveDone;	/* true if remote sent new line rather than ack */
char	vTxSeq;		/* next sequence number to transmit */
char	vRxChk;		/* last valid check character receieved */
struct termio	vTtyOrig,vTtyTmp;

/* T I M E U P */
timeup()
{
	/* just catch an alarm and let i/o routine get EINTR */
	return;
}


/* Q U I T */
quit(stat)
int stat;
{
	/* restore tty attributes */
	ioctl(0,TCSETAF,&vTtyOrig);

	/* terminate the process */
	exit(stat);
}

/* M A I N */

void main(argc, argv)
int	argc;
char	**argv;
{
	/* tell user about special feature */
	printf("Type \"quit\\n\" to force exit\n");

	/* get current tty characteristics for restoring later */
	ioctl(0, TCGETA, &vTtyOrig);

	/* catch all signals so that tty gets restored */
	signal(SIGHUP, quit);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, quit);
	signal(SIGILL, quit);
	signal(SIGIOT, quit);
	signal(SIGEMT, quit);
	signal(SIGFPE, quit);
	signal(SIGBUS, quit);
	signal(SIGSEGV, quit);
	signal(SIGSYS, quit);
	signal(SIGPIPE, quit);
	signal(SIGTERM, quit);
	signal(SIGUSR1, quit);
	signal(SIGUSR2, quit);

	/* change tty to not echo */
	vTtyTmp = vTtyOrig;
	vTtyTmp.c_oflag &= ~OPOST;
	vTtyTmp.c_lflag = ICANON;
	vTtyTmp.c_cc[VERASE] = 0;
	vTtyTmp.c_cc[VKILL] = 0;
	vTtyTmp.c_cc[VEOF] = 0;
	vTtyTmp.c_cc[VEOL] = 0;
	ioctl(0,TCSETAF,&vTtyTmp);

	/* do the processing loop */
	vfnRx = 0;	/* standard in */
	vfnTx = 1;	/* standard out */
	DebugServer();

	/* all done */
	quit(0);
} /* main */

/* R E A D   S B */

ReadSb(sb, cb)
int	cb;
SBT	sb;
{
    FAST int	i, ret;

	/* if WriteSb found our message return it now */
	if (vfRecieveDone) {
		vfRecieveDone = false;
		strncpy(sb,vsbRxLast+2,cb-1);
		sb[cb-1] = 0;
		return(strlen(sb));
	}

	/* loop reading until a valid string is received */
	for(;;) {
		ret = read(vfnRx, vsbRxLast, sizeof(vsbRxLast));
		if (ret <= 0)
	    		RemotePanic("Read from Remote on %d.", vfnRx);
		
		/* if this is a proper request, ack and return results */
		if (fFsbValidMsg(vsbRxLast,vRxChk)) {
			char sbAck[2];
			vRxChk = sbAck[0] = vsbRxLast[0];
			sbAck[1] = '\n';
			write(vfnTx, sbAck, 2);
			strncpy(sb,vsbRxLast+2,cb-1);
			sb[cb-1] = 0;
			return(strlen(sb));
		}

		/* if this is a resync request then ignore sequence bit */
		if (strncmp(vsbRxLast,"~~~",3) == 0) {
			vRxChk = 0;
			continue;
		}

		/* no good, so send a NAK and try again */
		write(vfnTx,"~\n",2);

		/* if this is a quit request then exit */
		if(strncmp(vsbRxLast,"quit\n",4) == 0) quit(1);
	}

} /* ReadSb */


/* W R I T E   S B */

WriteSb(sb)
FAST SBT	sb;
{
    FAST int	i, ret;
    FAST char ch;
    FAST SBT sbTx;
    int AlarmTime = 2;
    int sum = 0;
    int cnt = 0;
    char sbAck[sizeof(vsbRxLast)];

	/* save the string in vsbTxLast and compute the check byte */
	sbTx = vsbTxLast+2;
	while((ch = *sb++) != '\n') {
		if (ch < ' ' || ch > '~')
			RemotePanic("WriteSb: Attempt to send non-printable char");
		sum += ch;
		*sbTx++ = ch;
		cnt++;
	}
	*sbTx++ = '\n';
	*sbTx = 0;
	vsbTxLast[0] = sum%47 + vTxSeq + ' ';
	vsbTxLast[1] = cnt + ' ';
	cnt += 3;

	/* advance the sequence number for the next character */
	vTxSeq = vTxSeq ? 0 : 47;

	/* loop transmitting until a valid ack is recieved */
	i = 0;
	for(;;) {
		
		/* after too many errors try to resync the sequence bit */
		if (++i > 10) {
			write(vfnTx,"~~~\n",4);
			i = 0;
		}
		
		/* flush out any extraneous garbage in input buffer */
		ioctl(vfnRx, TCFLSH, 0);

		/* send the message */
		ret = write(vfnTx, vsbTxLast, cnt);
		if (cnt != ret)
			RemotePanic("WriteSb: %d bytes to go, %d went.", cnt, ret);

		/* get an ack or timeout */
		signal(SIGALRM, timeup);
		alarm(AlarmTime);
		ret = read(vfnRx, sbAck, sizeof(sbAck));
		alarm(0);

		/* check for error */
		if (ret < 0) {
			if (errno != EINTR)
				RemotePanic("WriteSb: error reading ack");

			/* try again but give a longer timeout */
			AlarmTime += 2;
			continue;
		}

		/* if we got a valid ack then we are done */
		if (ret == 2 && sbAck[0] == vsbTxLast[0]) return;

		/* retransmit if we get a nak */
		if (sbAck[0] == '~') {
			/* if this is a resync request then do so */
			if (sbAck[1] == '~' && sbAck[2] == '~')
				vRxChk = 0;
			continue;
		}

		/* if this is another copy of the last message he sent,
		 * then he probably lost my last ack and is still trying to
		 * send a message that I already processed. So we just send our
		 * new message again. It will have the side effect of being an
		 * ack to the last message as well.
		 */
		if (sbAck[0] == vsbRxLast[0] && ret > 2) continue;

		/* if this is a valid new message rather than an ack, then we
		 * must have lost the ack from the last message and this is 
		 * his next transmission. We will acknowledge the reciept of
		 * a valid message and save this line for ReadSb.
		 */
		if (fFsbValidMsg(sbAck,vRxChk)) {
			vfRecieveDone = true;
			strcpy(vsbRxLast,sbAck);
			sbAck[1] = '\n';
			vRxChk = sbAck[0];
			write(vfnTx, sbAck, 2);
			return;
		}

		/* if this is a quit request then exit */
		if(strncmp(sbAck,"quit\n",4) == 0) quit(1);

		/* I have no idea what this line is so we will just try again */
	}
} /* WriteSb */


/* F   F   S B   V A L I D   M S G */

fFsbValidMsg(sbMsg, chk)
SBT		sbMsg;		/* message to validate */
char		chk;		/* check character from previous message */
{
	FAST SBT sb;
	FAST char ch;
	int sum = 0;
	int cnt = ' ';

	/* calculate expected check byte */
	sb = sbMsg+2;
	while((ch = *sb++) != '\n') {
		if (ch < ' ' || ch > '~')
			return(false);
		sum += ch;
		cnt++;
	}
	sum = sum%47 + ' ';

	/* calculate sequence bit */
	if (chk) {
		/* must be opposite of last transmission */
		if (chk < ' '+47) sum += 47;
	} else {
		/* resync with whatever sequence bit this has */
		if (sbMsg[0] >= ' '+47) sum += 47;
	}

	return(sum == sbMsg[0] && cnt == sbMsg[1]);
} /* fFsbValidMsg */


/* C D B   P A N I C */

int RemotePanic(sbFmt, arg1, arg2, arg3)
SBT	sbFmt;
int	arg1, arg2, arg3;
{
    fprintf(stderr, "Remote Panic - ");
    fprintf(stderr, sbFmt, arg1, arg2, arg3);
    fprintf(stderr, "\n");
    fflush(stderr);
} /* RemotePanic */


/* V A L   F   P S B   */

long ValFPsb(psb)
SBT	*psb;
{
    int		x = 0;
    char	ch, *sb = *psb;

    /* this routine eats a hex number from a string and advances
     * the string pointer to the next character AFTER the first
     * non-hex character.  E.g if we start with "1234|abcd",
     * we will return the integer value 0x1234 and leave the string
     * pointing to the 'a'.
     */

#define FHex(ch) (((ch >='0') AND (ch <= '9')) OR ((ch >= 'a') AND (ch <= 'f')))

    if ((sb == sbNil) OR (*sb == chNull))
	return(0);

    while (true) {
	ch = *sb++;
	if (! FHex(ch))
	    break;
	x = (x * 16) + ((ch <= '9') ? (ch - '0') : ((ch - 'a') + 10));
    } /* while */
    *psb = sb;
    return(x);
} /* ValFPsb */


/* R E A D   H E X   B Y T E S */

void ReadHexBytes(adr, count, sb)
int	count;
long	adr;
SBT	sb;
{
    char	ch1, ch2, *sbDest;
    short	val;

    /* used with the host-to-remote block transfer command */
    sbDest = (SBT) adr;
    while (count--) {
	ch1 = *sb++;
	ch2 = *sb++;
	val = ((ch1 - ((ch1 > '9') ? ('a'-10) : '0')) << 4)
	       + (ch2 - ((ch2 > '9') ? ('a'-10) : '0'));
	*sbDest++ = val;
    } /* while */
} /* ReadHexBytes */


/* W R I T E   H E X   B Y T E S */

void WriteHexBytes(adr, count)
int	count;
long	adr;
{
    SBT		sbTx, sbSrc;
    short	val;

    /* used with the remote-to-host block transfer command */

    sbSrc = (char *) adr;
    sbTx = vsbTx;
    sprintf(sbTx, "%c%x|", ' '+statusOk, count);
    sbTx = sbTx + strlen(sbTx);
    while (count--) {
	val = (*sbSrc & 0xf0) >> 4;
	*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
	val = *sbSrc++ & 0x0f;
	*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
    } /* while */
    *sbTx = '\n';
    WriteSb(vsbTx);
} /* WriteHexBytes */


/* L O C A L   P T R A C E */

void LocalPtrace(pt, pid, adr, value)
int	pt, pid, value;
long	adr;
{
    int		status;
    
    /* This routine does whatever is necessary to implement
     * the ptrace(2) system call.
     *
     * For UNIX systems, this means we just call ptrace itself.
     */

    /* On a majority of systems, Instruction and Data Space
     * are identical.  On systems where this is not true, you
     * will need to deal with them separatly.
     */

    dprint(10, (stderr, "pt: %d  adr: %x  value: %d\n", pt, adr, value));

    errno = 0;
    switch (pt) {
	default: errno = EINVAL;
		value = -1;

	case  ptReadI:
	case  ptReadD:
		/* Read memory */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptWriteI:
	case  ptWriteD:
		/* Write memory */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptReadUser:
		/* Read Registers */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptWriteUser:
		/* Write Registers */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptSingle:
		/* Single Step the child */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptResume:
		/* Continue an existing child */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptTerm:
		/* Terminate an existing child */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptMultiChild:
		/* we own you and your firstborn */
		value = ptrace(pt, adr, 0, 0);
		if (value == 0)
			vpidChild = adr;
		break;

	case  ptReleaseChild:
		/* go `way ya bother me, Kid.... */
		value = ptrace(pt, pid, adr, value);
		vpidChild = 0;
		break;

	case  ptPpid:
		/* give us pid of parent of this process */
		value = ptrace(pt, pid, adr, value);
		break;

	case  ptCmdName:
		/* return name of executable */
		{
		char name[256];

		memset(name,0,sizeof(name));
		value = ptrace(pt, pid, name, 0);
    		sprintf(vsbTx, "%c%s\n", ' '+errno, name);
    		WriteSb(vsbTx);
		return;
		}

    } /* switch */

    SendStatus(errno, value);
} /* LocalPtrace */


/* S E N D   S T A T U S */

void SendStatus(status, value)
int	status, value;
{
    sprintf(vsbTx, "%c%x\n", ' '+status, value);
    WriteSb(vsbTx);
} /* SendStatus */


/* N E X T   A R G */

char * NextArg(psbIn)
SBT	*psbIn;
{
    SBT		sbRet;

    /* skip white space */
    while (**psbIn == ' ' OR **psbIn == '\t')
	(*psbIn)++;

    if (**psbIn == chNull)
	return(sbNil);	/* that's all, folks! */

    sbRet = *psbIn;	/* set current arg pointer */
    while (**psbIn != chNull
       AND **psbIn != ' '
       AND **psbIn != '\t')
	(*psbIn)++;	/* skip all non-white space characters */

    **psbIn = chNull;	/* overwrite the tab, space, or 0 with a 0 */
    (*psbIn)++;
    return(sbRet);
} /* NextArg */


/* D O	 A R G S */

void DoArgs(sbProgram, sbArgs, argv, fReassign)
SBT	sbProgram, sbArgs;
char	**argv;
int	fReassign;
{
    int		i;
    SBT		sbFile, sbArgCur;
    char	sbBuffer[1024];

    for (i=0; i < cArgsMax; i++)
	argv[i] = sbNil;

    *argv++ = sbProgram; /* set the filename */

    if (sbArgs == sbNil)
	return;

    strcpy(sbBuffer, sbArgs);	/* copy it to a safe place to hack on it */
    sbArgs = sbBuffer;
    sbArgs[strlen(sbArgs)+1] = chNull; /* this puts a SECOND null at end */

    /* eat the arguments */
    while ((sbArgs != sbNil)
       AND (*sbArgs != chNull)) {
	sbArgCur = NextArg(&sbArgs);
	if (sbArgCur == sbNil)
	    break;

	/* check for indirection */
	if (!fReassign
	   OR ((*sbArgCur != '<') AND (*sbArgCur != '>')) ) {
	    *argv++ = sbArgCur;	/* we just pass it on */
	} else {
	    /* find that file name */
	    sbFile = sbArgCur + 1;  /* initially we assume `<foo' vs `< foo' */
	    if (*sbFile == chNull) {
		/* there was white space between < and sbFile */
		sbFile = NextArg(&sbArgs);
		if (sbFile == sbNil) {
		    printf("Illegal indirection\n");
		    exit(1);
		} /* if */
	    } /* if */

	    if (*sbArgCur == '<') {
		/* changing stdin */
		close(0);
		if (open(sbFile, O_RDONLY) < 0) {
		    perror(sbFile);
		    exit(1);
		} /* if */
	    } else if (*sbArgCur == '>') {
		/* changing stdout */
		close(1);
		if ( (open(sbFile, 2) < 0) 	/* O_WRONLY */
		   AND (creat(sbFile, 0666) < 0) ) {
		    perror(sbFile);
		    exit(1);
		} /* if */
	    } /* if */
	} /* if */
    } /* while */
    *argv = sbNil;
} /* DoArgs */


/* P I D   F   E X E C   C H I L D */

int PidFExecChild(sbExec, sbArgs)
SBT	sbExec, sbArgs;
{
    int		pid, fn, sig;
    char	*argvChild[cArgsMax];

    /* Parse the argument list passed into an argv array.
     * Create a child process, initialize it to a more or less virgin state,
     * (i.e. clean up the signals, close the files,....) and return the pid
     * to the caller.
     */

    if ((pid = fork()) == 0) {
	/* we are the CHILD process */

	for (sig=1; sig<NSIG; sig++)
	    signal(sig, SIG_DFL);	/* start out with default response */

	for (fn = 3; fn < _NFILE; fn++)
	    close(fn);

	DoArgs(sbExec, sbArgs, argvChild, true);
	ptrace(ptChild, 0, (char *)0, 0); /* Hi, Mom! */
	execv(sbExec, argvChild);

	/* if we get here, we are child BUT exec failed */
	perror(sbExec);
	RemotePanic("Exec failed.");
	exit(1);
    } /* if */

    return(pid);
} /* PidFExecChild */


/* D E B U G   S E R V E R */

int DebugServer(fpTx, fpRx)
FILE	*fpTx, *fpRx;
{
    int		result, status, msg, pt, value, count;
    int		sig;
    long	adr, adr2;
    char	*sb, sbBuf[cbBufMax], sbName[cbBufMax], sbArgs[cbBufMax];

    /* This routine is the main command loop.
     * It acts as the Parent process to the target process.
     */

    dprint(1, (stderr, "Entering debug server\n"));


    while (true) {
	ReadSb(sbBuf,sizeof(sbBuf));	/* get a message from the host */
	sb = sbBuf;
	msg = *sb++ - ' ';	/* get message number */
	dprint(1, (stderr, "msg = %d\n", msg));

	status = statusOk;	/* to start with */

	switch (msg) {
	    default:
		/* check for in the range of Ptrace messages */
		if (msg<msgPtrace || msg>msgPtrace+ptMax) {
			SendStatus(statusRetry, 0);
			break;
		}

	    	/* must be a ptrace request */
		pt = msg-msgPtrace;
		adr = ValFPsb(&sb);
		if (sb[-1] == '\n')
			value = 0;
		else
			value = ValFPsb(&sb);

		LocalPtrace(pt, vpidChild, adr, value);
		break;

	    case msgWait:
		waitagain:
		result = wait(&value);
		if (result < 0) {
			SendStatus(errno, value);
		} else if (result == vpidChild) {
			if ((value&0xff) != 0177) vpidChild = 0;
			SendStatus(statusOk, value);
		} else {
			/* our child must have forked so we will release this */
			ptrace(ptReleaseChild, result, 0, 0);
			goto waitagain;
		}
		break;

	    case msgQuit:
		quit(0);
		return;	/* all done */


	    case msgExec:
		if (vpidChild > 1) {
		    ptrace(ptTerm, vpidChild, (char *)0, 0);
		    vpidChild = 0;
		} /* if */

		/* sb now points at "program|args" */

		sscanf(sb, "%[^|]|%[^|]", sbName, sbArgs);
		sbArgs[strlen(sbArgs)-1] = '\0'; /* clear the <nl> */
		dprint(1, (stderr, "Execing: %s, args:%s\n", sbName, sbArgs));

		vpidChild = PidFExecChild(sbName, sbArgs);
		if (vpidChild == -1) {
		    vpidChild = 0;
		    status = errno;
		} /* if */
		SendStatus(status, vpidChild);
		break;

	    case msgHtoR:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		ReadHexBytes(adr, count, sb);
		SendStatus(statusOk, 0);
		break;

	    case msgRtoH:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		WriteHexBytes(adr, count);
		break;

	    case msgMove:
		adr = ValFPsb(&sb);
		adr2 = ValFPsb(&sb);
		count = ValFPsb(&sb);
		/* MoveBlock((char *)adr, (char *)adr2, count); */
		SendStatus(status, 0);
		break;

	    case msgSignal:
		sig = ValFPsb(&sb);
		result = kill(vpidChild, sig);
		SendStatus(result?errno:statusOk, result);
		break;

	    case msgLevel:
		vlevel = ValFPsb(&sb);
		SendStatus(statusOk, 0);
		break;

	} /* switch */
    } /* while */
} /* DebugServer */
0707070001000313001004440000000000010000011612130454650114400001600000043056cdb/rptrace.c /* $Header: rptrace.c,v 6.1 86/08/05 17:46:51 peter Exp $ */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <errno.h>
#include <signal.h>
#include <termio.h>

#include "cdb.h"
#include "rptrace.h"

extern void Transmit();

int	vfnTx, vfnRx;
int	vlevelSave = 0;
FLAGT	vfTest = false;

int	vsignal, vpidServer;
char	vsbRemoteDevice[100];	/* name of device connected to remote */

char	_sbRx[cbMsgMax];	/* buffer for received messages */
SBT	vsbRx;		/* points to next character in receive buffer */
#define cbRx sizeof(_sbRx)
char	vsbTxLast[cbMsgMax]; /* copy of last transmisson */
char	vsbRxLast[cbMsgMax]; /* copy of last recieve data */
int	vpidRemote;		/* pid of the process being remotely debugged */
FLAGT	vfRecieveDone;	/* true if remote sent new line rather than ack */
char	vTxSeq;		/* next sequence number to transmit */
char	vRxChk;		/* last valid check character receieved */

struct termio vTtyarg;	/* initial tty settings */

/* V A L   F   P S B   */

long ValFPsb(psb)
SBT	*psb;
{
    int		x = 0;
    char	ch, *sb = *psb;

    /* this routine eats a hex number from a string and advances
     * the string pointer to the next character AFTER the first
     * non-hex character.  E.g if we start with "1234|abcd",
     * we will return the integer value 0x1234 and leave the string
     * pointing to the 'a'.
     */

#define FHex(ch) (((ch >='0') AND (ch <= '9')) OR ((ch >= 'a') AND (ch <= 'f')))

    if ((sb == sbNil) OR (*sb == chNull))
	return(0);

    while (true) {
	ch = *sb++;
	if (! FHex(ch))
	    break;
	x = (x * 16) + ((ch <= '9') ? (ch - '0') : ((ch - 'a') + 10));
    } /* while */
    *psb = sb;
    return(x);
} /* ValFPsb */


/* S B   F   T X   M S G */

local void SbFTxMsg(sbTx)
SBT	sbTx;
{
    int		msg, pt, value, count;
    long	adr, adr2;
    char	*sb, sbName[cbMsgMax], sbArgs[cbMsgMax];

    printf("TxHost: %s", sbTx);

    if (v->fCommDebug AND (v->debuglevel >= 100)) {
	sb = sbTx;
	msg = *sb++ - ' ';	/* get message number */

	switch (msg) {
	    default:
		/* check for in the range of Ptrace messages */
		if (msg<msgPtrace || msg>msgPtrace+ptMax) {
			printf("msg = %d\n", msg);
			break;
		}

	    	/* must be a ptrace request */
		pt = msg-msgPtrace;
		adr = ValFPsb(&sb);
		if (sb[-1] == '\n')
			value = 0;
		else
			value = ValFPsb(&sb);

		switch (pt) {
		    default:    printf("Unknown Ptrace request: %d", pt);
				break;

		    case  ptReadI:	printf("Read Text");	break;
		    case  ptReadD:	printf("Read Data");	break;
		    case  ptWriteI:	printf("Write Text");	break;
		    case  ptWriteD:	printf("Write Data");	break;
		    case  ptReadUser:	printf("Read User");	break;
		    case  ptWriteUser:	printf("Write User");	break;
		    case  ptSingle:	printf("Single Step");	break;
		    case  ptResume:	printf("****** Resume ******");	break;
		    case  ptTerm:	printf("Terminate");	break;
		} /* switch */
		printf("	adr: %#x	value: %d (%#x)\n",
			    adr, value, value);
		break;

	    case msgWait:
		    printf("******* Waiting for process ********\n");
		    break;

	    case msgExec:
		sscanf(sb, "%[^|]|%[^\n]", sbName, sbArgs);
		printf("Exec %s with args \"%s\"\n", sbName, sbArgs);
		break;


	    case msgRtoH:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		printf("Remote to Host: from: %x  count %d\n",
				adr, count);
		break;

	    case msgHtoR:
		adr = ValFPsb(&sb);
		count = ValFPsb(&sb);
		printf("Host to Remote: start at: %x  count %d\n",
				adr, count);
		break;

	    case msgMove:
		adr = ValFPsb(&sb);
		adr2 = ValFPsb(&sb);
		count = ValFPsb(&sb);
		printf("Block Move: dest: %x  src: %#x, count %d\n",
				adr, adr2, count);
		break;

	} /* switch */
    } /*  if */
} /* SbFTxMsg */


/* F   F   S B   V A L I D   M S G */

local FLAGT fFsbValidMsg(sbMsg, chk)
SBT		sbMsg;		/* message to validate */
char		chk;		/* check character from previous message */
{
	FAST SBT sb;
	FAST char ch;
	int sum = 0;
	int cnt = ' ';

	/* calculate expected check byte */
	sb = sbMsg+2;
	while((ch = *sb++) != '\n') {
		if (ch < ' ' || ch > '~')
			return(false);
		sum += ch;
		cnt++;
	}
	sum = sum%47 + ' ';

	/* calculate sequence bit */
	if (chk) {
		/* must be opposite of last transmission */
		if (chk < ' '+47) sum += 47;
	} else {
		/* resync with whatever sequence bit this has */
		if (sbMsg[0] >= ' '+47) sum += 47;
	}


	return(sum == sbMsg[0] && cnt == sbMsg[1]);
} /* fFsbValidMsg */


/* R E A D   S B */

export int ReadSb(sb, cb)
int	cb;
SBT	sb;
{
    FAST int	i, ret;

	/* if WriteSb found our message return it now */
	if (vfRecieveDone) {
		vfRecieveDone = false;
		strncpy(sb,vsbRxLast+2,cb-1);
		sb[cb-1] = 0;
		return(strlen(sb));
	}

	/* loop reading until a valid string is received */
	for(;;) {
		ret = read(vfnRx, vsbRxLast, sizeof(vsbRxLast));
		if (ret <= 0) {
			if (errno == EINTR) continue;
	    		SysPanic("Read from Remote on %d.", vfnRx);
		}
		
		/* if this is a proper request, ack and return results */
		if (fFsbValidMsg(vsbRxLast,vRxChk)) {
			char sbAck[2];

			vRxChk = sbAck[0] = vsbRxLast[0];
			sbAck[1] = '\n';
			write(vfnTx, sbAck, 2);
			strncpy(sb,vsbRxLast+2,cb-1);
			sb[cb-1] = 0;
			return(strlen(sb));
		}

		/* if this is a resync request then ignore sequence bit */
		if (strncmp(vsbRxLast,"~~~",3) == 0) {
			vRxChk = 0;
			continue;
		}

		/* no good, so send a NAK and try again */
		write(vfnTx,"~\n",2);
	}

} /* ReadSb */


/* W R I T E   S B */

export int WriteSb(sb)
FAST SBT	sb;
{
    static int success = false;
    int AlarmTime = 2;
    int sum = 0;
    int cnt = 0;
    char sbAck[sizeof(vsbRxLast)];
    FAST int	i, ret;
    FAST char ch;
    FAST SBT sbTx;

	/* save the string in vsbTxLast and compute the check byte */
	sbTx = vsbTxLast+2;
	while((ch = *sb++) != '\n') {
		if (ch < ' ' || ch > '~')
			Panic("WriteSb: Attempt to send non-printable char");
		sum += ch;
		*sbTx++ = ch;
		cnt++;
	}
	*sbTx++ = '\n';
	*sbTx = 0;
	vsbTxLast[0] = sum%47 + vTxSeq + ' ';
	vsbTxLast[1] = cnt + ' ';
	cnt += 3;

	/* advance the sequence number for the next character */
	vTxSeq = vTxSeq ? 0 : 47;

	/* loop transmitting until a valid ack is recieved */
	i=0;
	for(;;) {

		/* after too many errors checkout whats happening */
		if (++i % 10 == 0) {
			/* if we have never communicated successfully then
			 * the line is probably not initialized correctly
			 */
			if (!success) {
				printf("Unable to establish contact with cdbremote\n");
				CloseComm();
				exit(1);
			}

			/* After too many tries to resync give up */
			if (i >= 40) {
				printf("Lost contact with cdbremote.\n");
				CloseComm();
				exit(1);
			}

			/* try to resync the sequence bit */
			write(vfnTx,"~~~\n",4);
		}
		
		/* flush out any extraneous garbage in input buffer */
		if (!vfTest) ioctl(vfnRx, TCFLSH, 0);

		/* send the message */
		ret = write(vfnTx, vsbTxLast, cnt);
		if (cnt != ret)
			SysPanic("WriteSb: %d bytes to go, %d went.", cnt, ret);

		/* get an ack or timeout */
		alarm(AlarmTime);
		ret = read(vfnRx, sbAck, sizeof(sbAck));
		alarm(0);

		/* check for error */
		if (ret < 0) {
			if (errno != EINTR)
				SysPanic("WriteSb: error reading ack");

			/* try again but give a longer timeout */
			AlarmTime += 2;
			continue;
		}

		/* if we got a valid ack then we are done */
		if (ret == 2 && sbAck[0] == vsbTxLast[0]) {
			success = true;
			return;
		}

		/* retransmit if we get a nak */
		if (sbAck[0] == '~') {
			/* if this is a resync request then do so */
			if (sbAck[1] == '~' && sbAck[2] == '~')
				vRxChk = 0;
			continue;
		}

		/* if this is another copy of the last message he sent,
		 * then he probably lost my last ack and is still trying to
		 * send a message that I already processed. So we just send our
		 * new message again. It will have the side effect of being an
		 * ack to the last message as well.
		 */
		if (sbAck[0] == vsbRxLast[0] && ret > 2) continue;

		/* if this is a valid new message rather than an ack, then we
		 * must have lost the ack from the last message and this is 
		 * his next transmission. We will acknowledge the reciept of
		 * a valid message and save this line for ReadSb.
		 */
		if (fFsbValidMsg(sbAck,vRxChk)) {
			/* if cdbremote is not running the echo of our command
			 * could look valid so check for that */
			if (!success && strncmp(sbAck,vsbTxLast,ret) == 0) {
				printf("You forgot to start cdbremote\n");
				CloseComm();
				exit(1);
			}
			vfRecieveDone = true;
			strcpy(vsbRxLast,sbAck);
			sbAck[1] = '\n';
			vRxChk = sbAck[0];
			write(vfnTx, sbAck, 2);
			success = true;
			return;
		}

		/* I have no idea what this line is so we will just try again */
	}
} /* WriteSb */


/* S E T   R E M O T E   L E V E L */

local void SetRemoteLevel(level)
int	level;
{
    char	sbBuf[100];

    sprintf(sbBuf, "%c%x\n", ' '+msgLevel, level);
    vlevelSave = level;
    Transmit(sbBuf);
    RetFReply();
} /* SetRemoteLevel */


/* T R A N S M I T */

export void Transmit(sbTx)
SBT	sbTx;
{
    /* Transmit the string */
    if (vlevelSave != v->debuglevel)
	SetRemoteLevel(v->debuglevel);

    if (v->fCommDebug)
	SbFTxMsg(sbTx);

    if (vfnTx <= 2)
	Panic("Transmit - v->fnComm: %d.", v->fnComm);

    vcsRemote = csWriting;
    WriteSb(sbTx);
    vcsRemote = csWriteDone;
} /* Transmit */


/* R E C E I V E */

export void Receive()
{
    int		cb, cRetry, status;

    cRetry = 0;
    while (true) {
	vsbRx = _sbRx;

	vcsRemote = csReading;
	cb = ReadSb(vsbRx, cbRx);
	vcsRemote = csNil;
	if (vfInterruptPending) {
	    vfInterruptPending = false;
	    Fixer();
	}

	if (v->fCommDebug)
	    printf("RxHost: %s", vsbRx);

	status = *vsbRx++ - ' ';

	switch (status) {
	    default:
		errno = status;	/* "OK" or error for caller */
		return;

	    case statusRetry:
		cRetry++;
		if (cRetry >= cRetryMax)
		    Panic("Excessive retries, Last Transmit was:\n%s\n",
			vsbTxLast+2);
		Transmit(vsbTxLast+2);
		break;

	} /* switch */
    } /* while */
} /* Receive */


/* R E T   F   R E P L Y */

local int RetFReply()
{
    int		ret;

    /* Get response from remote.
     * ASSUME that there is a simple numerical reply.
     */

    Receive();	/* get a string from remote */
    if (sscanf(vsbRx, "%x", &ret) != 1)
	Panic("Bad reply from target: %s", _sbRx);
    return(ret);
} /* RetFReply */


/* P T R A C E */

export int Ptrace(pt, pid, adr, value)
int	pt, pid;
char	*adr;
int	value;
{
    int		ret;
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return( ptrace(pt, pid, adr, value) );

	/* if this is for some other process then panic */
	if(pid != vpidRemote && pt != ptMultiChild)
		Panic("Ptrace: Remote pid is %d but request is for %d.",
			vpidRemote, pid);

    switch (pt) {
	case ptMultiChild:
		/* the remote needs the new pid so we cheat */
		adr = (char*)pid;
		vpidRemote = pid;
		/* and fall through */
	case ptReadI:
	case ptReadD:
	case ptReadUser:
		value = 0;
		/* and fall through */
	case ptWriteI:
	case ptWriteD:
	case ptWriteUser:
	case ptResume:
	case ptTerm:
	case ptSingle:
	case ptReleaseChild:
	case ptPpid:
	    if (value == 0)
	        sprintf(sbPt, "%c%x\n", ' '+msgPtrace+pt, adr);
	    else
	        sprintf(sbPt, "%c%x|%x\n", ' '+msgPtrace+pt, adr, value);
	    Transmit(sbPt);	/* send a message to junior */
	    return( RetFReply() );

	case ptCmdName:
	    sprintf(sbPt, "%c%x|%x\n", ' '+msgPtrace+pt, 0, 0);
	    Transmit(sbPt);	/* send a message to junior */
    	    Receive();	/* get a string from remote */
	    vsbRx[strlen(vsbRx)-1] = 0;	/* clear the \n from the string */
	    strcpy(adr,vsbRx);
	    return;
    } /* switch */

} /* Ptrace */


/* S E N D   S I G N A L */

export int SendSignal(sig)
int2	sig;
{
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return(kill(v->pid, sig));

    sprintf(sbPt, "%c%x\n", ' '+msgSignal, sig);
    Transmit(sbPt);
    /* we DON'T wait for a reply since this is happening at
     * interrupt level.  The target should stop and return
     * status indictaing reciept of this signal.  This assumes
     * that the target has not stopped all by itself prior
     * to the signal.
     */

     /* I do not believe the above comment so I will get reply. billb */
     return(RetFReply());
} /* SendSignal */


/* W A I T */

export int Wait(pstatus)
int	*pstatus;
{
    int		ret;
    char	sbTemp[20];

    if (v->fnComm == fnNil)
	return(wait(pstatus));

    /* here we do what is necessary to *look like* "wait (2)" */

    sprintf(sbTemp, "%c\n", ' '+msgWait);
    Transmit(sbTemp);
    vfInWait = true;
    ret = RetFReply();
    vfInWait = false;

    *pstatus = ret;

    return(errno ? -1: vpidRemote);
} /* Wait */


/* C R E A T E   T A R G E T */

export void CreateTarget()
{
    int		ret;
    char	sbBuf[200];

    if (v->fnComm == fnNil) {
	OsCreateTarget();	/* cause a NATIVE process to be born */
	return;
    } /* if */

    if (vfTest) {
	close(v->fnExec);
	v->fnExec = fnNil;
    } /* if */

    sprintf(sbBuf, "%c%s|%s\n", ' '+msgExec, v->sbExec, v->sbArgsChild);
    Transmit(sbBuf);

    v->pid = RetFReply();
    vpidRemote = v->pid;

    if (errno)
	dprint(1, ("Bad exec in target.  Remote reports error: %d", errno));
} /* CreateTarget */


/* X   B L O C K   M O V E */

export void XBlockMove(pid, adrDest, adrSrc, cb)
int	pid;
ADRT	adrDest, adrSrc;
int	cb;
{
    /* transfer a block WITHIN the remote machine */
    char	sbBuf[cbMsgMax];

    sprintf(sbBuf, "%c%x|%x|%x\n", ' '+msgMove, adrDest, adrSrc, cb);
    Transmit(sbBuf);
    RetFReply();
} /* XBlockMove */


/* X   B L O C K   T R A N S F E R */

export void XBlockTransfer(pid, adrDest, adrSrc, cbIn, fTx)
int	pid;
ADRT	adrDest, adrSrc;
int	cbIn;
FLAGT	fTx;
{
    char	ch1, ch2, sbBuf[cbMsgMax];
    SBT		sbTx, sbRx, sbSrc, sbDest, sbT;
    short	val, cb, cbThisTime, cbSave;
    ADRT	adrDestIn;

    if (fTx) {
	/* write FROM host TO remote */
    } else {
	/* read FROM remote TO host */
	adrDestIn = adrDest;
	cbSave = cbIn;
    } /* if */
    sbSrc = (SBT) adrSrc;

    while (cbIn >= 0) {
	int rcb;
	cb = Min(cbIn, (cbMsgMax-24)/2);
	if (fTx) {
	    cbThisTime = cb;
	    cbIn -= cb;
	    /* write FROM host TO remote */
	    sprintf(sbBuf, "%c%x|%x|", ' '+msgHtoR, adrDest, cb);
	    sbTx = sbBuf + strlen(sbBuf);
	    while (cb--) {
		val = (*sbSrc & 0xf0) >> 4;
		*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
		val = *sbSrc++ & 0x0f;
		*sbTx++ = val + ((val > 9) ? ('a'-10) : '0');
	    } /* while */
	    *sbTx = '\n';
	    Transmit(sbBuf);
	    RetFReply();
	} else {
	    /* read FROM remote TO host */
	    sprintf(sbBuf, "%c%x|%x\n", ' '+msgRtoH, adrSrc, cb);
	    Transmit(sbBuf);
	    Receive();
	    if (sscanf(vsbRx, "%x", &rcb) != 1)
	    	Panic("bad target byte count %s", _sbRx);
	    if ((vsbRx = strchr(vsbRx, chDelim)) == sbNil) /* skip count */
	        Panic("missing separator 3 %s", _sbRx);
	    vsbRx++;
	    if ( rcb > cb )
		Panic("too many bytes transferred R to H");
	    cbThisTime = rcb;
	    cbIn -= rcb;
	    sbDest = (SBT) adrDest;
	    while (rcb--) {
		ch1 = *vsbRx++;
		ch2 = *vsbRx++;
		val = ((ch1 - ((ch1 > '9') ? ('a'-10) : '0')) << 4)
		    | (ch2 - ((ch2 > '9') ? ('a'-10) : '0'));
		if ((val & ~0x0ff) != 0 )
		    Panic("bad block transfer R to H");
		*sbDest++ = val;
	    } /* while */
	} /* if */
	adrSrc += cbThisTime;
	adrDest += cbThisTime;
    } /* while */

} /* XBlockTransfer */


/* C L O S E   C O M M */

export void CloseComm()
{
    int		ipr;
    char	sbBuf[cbMsgMax];

    if (v->fnComm != fnNil) {
	sprintf(sbBuf, "%c\n", ' '+msgQuit);
	Transmit(sbBuf);	/* send a message to junior */
    } /* if */

    if (vfTest) {
	close(vfnTx);
	close(vfnRx);
	kill(vpidServer, 9);
    } else {
	ioctl(v->fnComm, TCSETAF, &vTtyarg);
	close(v->fnComm);
    } /* if */
} /* CloseComm */


/* I N I T   C O M M */

export void InitComm(pr)
pPRR	pr;
{
    int		rgFnPtoC[2], rgFnCtoP[2];
    char	sbTx[10], sbRx[10], sbLevel[10];

    if (FSbCmp(pr->sbComm, "TEST")) {

	vfTest = true;
	if (pipe(rgFnPtoC) != 0)
	    Panic("Failed on pipe open: %s", SbFError(errno));

	if (pipe(rgFnCtoP) != 0)
	    Panic("Failed on pipe open: %s", SbFError(errno));

	/* pipes - write 1, read 0 */

	if (vpidServer = fork()) {

	    /* parent */
	    v->fnComm = vfnTx = rgFnPtoC[1];
	    vfnRx = rgFnCtoP[0];
	    close(rgFnCtoP[1]);
	    close(rgFnPtoC[0]);

	} else {

	    /* child */
	    if (v->fnExec != fnNil)
		close(v->fnExec);
	    if (v->fnCore != fnNil)
		close(v->fnCore);
	    close(rgFnCtoP[0]);
	    close(rgFnPtoC[1]);

	    close(0);
	    dup(rgFnPtoC[0]);
	    close(rgFnPtoC[0]);

	    close(1);
	    dup(rgFnCtoP[1]);
	    close(rgFnCtoP[1]);

	    execl("cdbremote", "cdbremote", 0);

	    printf("Execl of remote failed: %d %d\n", sbTx, sbRx);
	    exit(1);

	} /* if */

    } else {
	struct termio ttyarg;
	static int bauds[]={ 300, 600, 1200, 1800, 2400, 4800, 9600};
	static int bcode[]={B300,B600,B1200,B1800,B2400,B4800,B9600};
	int n;

	vfTest = false;

	/* check for startup from cu with channel already open */
	if (pr->sbComm[0] == ':' ) {
		/* cu passed us an open file descriptor */
		v->fnComm = strtol(&pr->sbComm[1],0,0);
	} else {
		v->fnComm = open(pr->sbComm, O_RDWR, 0);
		if (v->fnComm == -1)
		    UError("Cannot open %s: %s.", pr->sbComm, SbFError(errno));
	}

	/* set baud rates, etc */
	ioctl(v->fnComm, TCGETA, &ttyarg);
	vTtyarg = ttyarg;
	for (n = 0; n < sizeof(bauds)/sizeof(int); n++) {
		if (bauds[n] == v->iBaud) {
			ttyarg.c_cflag &= ~CBAUD;
	        	ttyarg.c_cflag |= bcode[n];
		}
	} /* for */

	ttyarg.c_cc[VERASE] = 0177;
	ttyarg.c_cc[VKILL] = 025;
	ttyarg.c_cc[VEOL] = 0;
	ttyarg.c_cc[VEOF] = 0;
	ttyarg.c_iflag |= ISTRIP|IGNCR;
	ttyarg.c_iflag &= ~(INLCR|ICRNL);
	ttyarg.c_oflag &= ~(OPOST);
	ttyarg.c_lflag = ICANON;
	ioctl(v->fnComm, TCSETAF, &ttyarg);
	vfnTx = vfnRx = v->fnComm;
	
    } /* if */

    /* Test the link and (as a side effect) set debuglevel */

    vlevelSave = v->debuglevel;
    sprintf(sbLevel, "%c%x\n", ' '+msgLevel, v->debuglevel);
    Transmit(sbLevel);
    Receive();
} /* InitComm */
0707070001000313011004440000000000010000011614200454650114400001600000011441cdb/rptrace.h 
/* $Header: rptrace.h,v 5.8 85/12/21 16:15:09 peter Exp $ */
/* (C) Copyright 1984 Third Eye Software Inc. - All Rights Reserved */

/*
 *
 * The modules rptrace.c and cdbremote.c implement a simple, ASCII based
 * protocol for controlling a remote debug server.
 *
 * The host is in control of the conversation.  The entire exchange
 * is "host says something", "remote replies".
 *
 * All numbers are hexidecimal and are represented by the characters
 * [0..9,a..f].  The only non-printing character used is "new line"
 * <nl> (012) which is the "end-of-transmission" character.
 *
 * The symbol <pid> is the "process id" of the process in question.
 * It is aggreed upon during the "msgExec" transaction.
 *
 * The remote's messages are of the form:
 *	<status> '|' <pid> '|' <reply value> <nl>
 * The reply value is not always present.
 *
 *	Status		Meaning
 *	------		-------
 * -3	statusNewPid	The pid in the message is the result of an EXEC
 * -2	statusRetry	Re-transmit last message to remote
 * -1	statusPrint	Reply is string destined for command terminal screen
 *  0	statusOk	Execution ok, reply is defined by command last given
 *	> statusOk	(gtr than statusOk) same meanings as "errno" on host.
 *
 *
 * The host's messages are of the general form:
 *	<message identifier> | <pid> | <argument> | (argument> | ... <nl>
 *
 *	Messages from Host
 *	------------------
 *
 *	msgExec '|' <pid> '|' <program name> '|' "<args>" <nl>
 *		The <pid> passed is the host's vote for the process id,
 *		HOWEVER, if the remote returns statusNewPid, that <pid>
 *		will be the one	actually used for all future communications
 *		about this process. If the remote doesn't care, it should
 *		return the same <pid> as was passed by host.
 *		If <pid> is already in use, the remote should infer a
 *		msgQuit on that process.
 *
 *	msgQuit '|' <pid> <nl>
 *		Debugger is done working with process <pid>.
 *
 *	msgWait '|' <pid> <nl>
 *		Wait for process <pid> to do something. (Hit a
 *		breakpoint, die, etc.)  If <pid> == 0, we are waiting
 *		for ANY process to do something.
 *
 *	msgPtrace '|' <pid> '|' <request> '|' <address> '|' <value> <nl>
 *		The meanings, and expected responses, are exactly as
 *		outlined in "ptrace(2)" in the UNIX manual.  Request 9
 *		"single step" is NOT optional!
 *
 *	msgInput  '|' <pid> '|' "any ASCII string NOT containing a <nl>" <nl>
 *		The string is meant to be inserted into the TTY input
 *		queue for the target process. Not all systems allow this.
 *
 *	These next three commands facilitate block data handling.
 *
 *	msgRtoH   '|' <pid> '|' <source address> '|' <count> <nl>
 *		Transfer data FROM remote TO host.  The first field
 *		of the reply is the number of bytes
 *		actually being transfered.  The host will continue
 *		to request the unsent portions.  This allows the
 *		remote to cope with small buffer sizes.
 *
 *	msgHtoR   '|' <pid> '|' <destination address> '|' <count>
 *			'|' <data - two ASCII hex characters per byte> .... <nl>
 *		Transfer data FROM host TO remote.
 *
 *	msgMove   '|' <pid> '|' <destination address>
 *			'|' <source adrress> '|' <count> <nl>
 *		Transfer data WITHIN remote.
 *
 *	msgSignal '|' <pid> '|' <signal number> <nl>
 *		Send signal to a running process.  This is applicable only
 *		when the host is waiting for a response to msgWait.
 *
 *	msgDump   '|' <pid> <nl>
 *		Reply with statusPrint and any useful information in ascii
 *		for debugging DebugServer or its operating system interface.
 *
 *	msgLevel  '|' <pid> '|' <level><nl>
 *		Set debug level of DebugServer in target system.
 */

#define cbMsgMax 256	/* max bytes host OR remote can tx OR rx at one time */
#define chDelim	'|'	/* delimiter for arguments */

/* Maximum number of retires on a transmission */
#define cRetryMax	3

/* messages sent host-to-remote */
#define msgQuit		1
#define msgExec		2
#define msgPtrace	30
#define msgWait		4
#define msgRtoH		6
#define msgHtoR		7
#define msgMove		8
#define msgSignal	9
#define msgLevel	11

/* status values - first item in ALL remote-to-host messages */
/* values 0-90 are assumed to have the same meaning as shown in <errno.h> */
#define statusOk	0
#define	statusRetry	93

/* return values to WAIT */
#define rvTerminate	1
#define rvBreakpoint	2
#define rvInterrupt	3

/* requests for `ptrace' system call */
#define ptChild	 	0
#define ptReadI	 	1
#define ptReadD	 	2
#define ptReadUser      3
#define ptWriteI	4
#define ptWriteD	5
#define ptWriteUser     6
#define ptResume	7
#define ptTerm	  	8
#define ptSingle	9

/* the following are NEW ptrace requests add for multiprocess work */
#define ptMultiChild	10	/* we own you and your firstborn */
#define ptReleaseChild	11	/* go `way ya bother me, Kid.... */
#define ptPpid		12	/* give us pid of parent of this process */
#define ptCmdName	13	/* return name of executable */

#define ptMax		13	/* maximum acceptable ptrace command */
0707070001000313020407550000000000010000021614630460260163300001000000000000cdb/KDB 0707070001000313031006440000000000010000010000000454650114400002000000000000cdb/KDB/GET.err 0707070001000313041004440000000000010000011614720454650114400002200000017321cdb/KDB/kptrace.c /* @(#)kptrace.c	2.1 12/21/87 */
/* (C) Copyright 1984 by Third Eye Software, Inc. - All Rights Reserved */

#include <errno.h>
#include <termio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include "cdb.h"

struct termio vatty;

extern void Transmit();
int	vsigKludge = 0;
int	vsignal;
int	vcSecWait = 2;
int	vmsgqid;		/* message que msqid for talking to cu */

/* the following message types are exchanged between cu and cdb */
#define MSG_SHUTDOWN	1	/* sent by cdb when it is going to exit */
#define MSG_RESUME	2	/* sent by cdb when cu should resume control */
#define MSG_SCAN	3	/* sent by transmit when recieve should resume
					scanning for "*** sysdebug " */
#define MSG_SYSDEBUG	4	/* sent by transmit when recieve has sent signal
					indicating sysdebug was entered */
#define MSG_INITCOMM	5	/* sent by cdb when successfully starts up */


#define iBufMax	10
int	viBuf;
char	vrgBuf[iBufMax][128];
SBT	vsbRx;

#define cbMsgMax 256	/* max bytes host OR remote can tx OR rx at one time */
char	vsbTxLast[cbMsgMax]; /* copy of last transmisson */



/* S B   F   I N D E X */

local SBT SbFIndex(i)
int	i;
{
    if (i > 0)
	return(sbNil);
    if ((i += viBuf) < 0)
	i += iBufMax;
    return(vrgBuf[i]);
} /* SbFIndex */


/* R E A D   S B */

export int ReadSb(fn, sb, cb)
int	fn, cb;
FAST SBT	sb;
{
    FAST int	i, ret;
    char	ch;

    i = 0;
    while (--cb > 0) {
	ret = read(fn, &ch, 1);
	*sb++ = ch;
	i++;
	if (ret < 0)
	    return(ret);
	if (ret == 0)
	    break;
	if (ch == '\n' || ch == '\r')
	    break;
    } /* while */
    *sb = chNull;
    return(i);
} /* ReadSb */


/* F   W A I T   F O R */

local void FWaitFor(sbWait, cSeconds)
SBT	sbWait;
int	cSeconds;
{
    int		ret, err;

    vcsRemote = csReading;
    viBuf = 0;
    while (1) {
	alarm(cSeconds);

	ret = ReadSb(v->fnComm, vrgBuf[viBuf], sizeof(vrgBuf[viBuf]));
	err = errno;

	alarm(0);

	if (ret > 0) {
	    if (FHdrCmp(sbWait, vrgBuf[viBuf]))
		break;;
	    if (v->debuglevel >= 10)
		printf("%s", vrgBuf[viBuf]);
	} else if (ret < 0) {
	     /* Then we timed out OR we lost the line.
	      * Or .......
	      */
		break;;
	} /* if */

	if (++viBuf >= iBufMax)
	    viBuf = 0;
    } /* while */
    vcsRemote = csNil;
    if (vfInterruptPending) {
	vfInterruptPending = false;
	Fixer();
    }
} /* FWaitFor */

/* S E N D   M E S S A G E   T O   C U  */
local void FSendCuMsg(m)
int m;
{
	struct msgbuf msgb;

	msgb.mtype = m;
	msgsnd(vmsgqid,&msgb,0,0);
}



/* W A I T   F O R   D E B U G */

/* tell cu to resume processing and look for "*** sysdebug " */
local void FWaitForDebug()
{
	struct msgbuf msgb;

    	vfInWait = true;
	signal(SIGINT, Fixer);
	FSendCuMsg(MSG_RESUME);
	msgrcv(vmsgqid,&msgb,0,MSG_SYSDEBUG,0);
    	vfInWait = false;
}


/* G E T   P R O M P T */

local void GetPrompt()
{
    FWaitFor("cdb", vcSecWait);
} /* GetPrompt */


/* T R A N S M I T */

export void Transmit(sbTx)
SBT	sbTx;
{
    int		cbTx, cb;

    /* Transmit the string */
    if (sbTx != vsbTxLast)
	strcpy(vsbTxLast, sbTx);	/* save for re-transmission */
    
    cbTx = strlen(sbTx);

    if (v->fCommDebug) {
	char	sbTemp[200];
	strcpy(sbTemp, sbTx);
	sbTemp[strlen(sbTemp)-1] = '\n';
	printf("TxHost: %s", sbTemp);
    } /* if */

    if (v->fnComm <= 2)
	Panic("Transmit - v->fnComm: %d.", v->fnComm);

    vcsRemote = csWriting;
    cb = write(v->fnComm, sbTx, cbTx);
    vcsRemote = csWriteDone;

    if (cb != cbTx)
	SysPanic("Transmit: %d bytes to go, %d went.", cbTx, cb);
} /* Transmit */


/* P T R A C E */

export int Ptrace(pt, pid, adr, value)
int	pt, pid;
char	*adr;
int	value;
{
    int		ret;
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return( ptrace(pt, pid, adr, value) );

    switch (pt) {
	default:
	    return( -1 );

	case ptReadI:
	case ptReadD:
	    /* put:	r adr
	     * get:	12345678
	     */
	    sprintf(sbPt, "r %x\r", adr);
	    Transmit(sbPt);
	    GetPrompt();
	    sscanf(SbFIndex(-2), "%x", &value);
	    return(value);

	case ptReadUser:
	    /* put:	x reg
	     * get:	12345678
	     */
	    sprintf(sbPt, "x %x\r", adr);
	    Transmit(sbPt);
	    GetPrompt();
	    sscanf(SbFIndex(-2), "%x", &value);
	    return(value);

	case ptWriteI:
	case ptWriteD:
	    /* put:	M adr hi-2-bytes lo-2-bytes
	     * get:	..... prompt
	     */
	    sprintf(sbPt, "M %x %x %x\r", adr, (value >> 16) & 0x0000ffff,
			value & 0x0000ffff);
	    Transmit(sbPt);
	    GetPrompt();
	    return(value);

	case ptWriteUser:
	    /* put:	m reg value
	     * get:	prompt
	     */
	    sprintf(sbPt, "m %x %x\r", adr, value);
	    Transmit(sbPt);
	    GetPrompt();
	    return(value);

	case ptResume:
	    /* put:	e
	     * get:	who knows!!!!
	     */
	    Transmit("e\r");
	    FWaitFor("e", vcSecWait);
	    return(0);

	case ptTerm:
	    Transmit("E\r");
	    FWaitFor("E", vcSecWait);
	    v->pid = 0;
	    vsigKludge = -1;
	    return(0);

	case ptSingle:
	    Transmit("s 1\r");
	    GetPrompt();
	    Transmit("e\r");
	    FWaitFor("e", vcSecWait);
	    return(0);

    } /* switch */
} /* Ptrace */


/* S E N D   S I G N A L */

export int SendSignal(sig)
int2	sig;
{
    char	sbPt[100];

    if (v->fnComm == fnNil)
	return(kill(v->pid, sig));

    printf("Please push the RED BUTTON to enter sys debug\n");
} /* SendSignal */


/* W A I T */

export int Wait(pstatus)
int	*pstatus;
{
    int		ret, sig;
    char	sbTemp[200];

    if (v->fnComm == fnNil)
	return(wait(pstatus));

    /* here we do what is necessary to *look like* "wait (2)" */

    if (vsigKludge != 0) {
	*pstatus = vsigKludge<0 ? 0 :(vsigKludge << 8) + 0x7f;
	vsigKludge = 0;
	return(v->pid);
    } /* if */

    FWaitForDebug();
    ReadSb(v->fnComm,sbTemp,sizeof(sbTemp));

    if (FHdrCmp("single", sbTemp)) {
	sig = SIGTRAP;
    } else if (FHdrCmp("for unknown", sbTemp)) {
	sig = SIGTRAP;
    } else if (FHdrCmp("interrupt", sbTemp)) {
	sig = SIGINT;
    } else if (FHdrCmp("call", sbTemp)) {
	sig = SIGINT;
    } else if (FHdrCmp("invalid", sbTemp)) {
	sig = SIGILL;
    } else if (FHdrCmp("breakpoint", sbTemp)) {
	sig = SIGTRAP;
    } else {
	sig = SIGTRAP;
    } /* if */

    *pstatus = (sig << 8) + 0x7f;

    GetPrompt();
    return(v->pid);
} /* Wait */


/* C R E A T E   T A R G E T */

export void CreateTarget()
{
    int		ret;
    char	sbBuf[200];

    if (v->fnComm == fnNil) {
	OsCreateTarget();	/* cause a NATIVE process to be born */
	return;
    } /* if */

    v->pid = 1;
    vsigKludge = SIGINT;

    printf("Force system into sysdebug (somehow....)\n");
    FWaitForDebug();
    FWaitFor("+ ", 1);
    Transmit("p\r");
    GetPrompt();

    AllBpInstall();
    printf("Target is now running\n");
} /* CreateTarget */


/* X   B L O C K   M O V E */

export void XBlockMove(pid, adrDest, adrSrc, cb)
int	pid;
ADRT	adrDest, adrSrc;
int	cb;
{
    /* transfer a block WITHIN the remote machine */
} /* XBlockMove */


/* X   B L O C K   T R A N S F E R */

export void XBlockTransfer(pid, adrDest, adrSrc, cbIn, fTx)
int	pid;
ADRT	adrDest, adrSrc;
int	cbIn;
FLAGT	fTx;
{
} /* XBlockTransfer */


/* C L O S E   C O M M */

export void CloseComm()
{
    int		ipr;
    char	sbBuf[cbMsgMax];

    if (v->fnComm != fnNil && v->pid ) {
	RemoveAllBp();
	Transmit("e\r");
	FWaitFor("e", vcSecWait);
    } /* if */
    FSendCuMsg(MSG_SHUTDOWN);	/* tell cu that cdb is closing down */
} /* CloseComm */


/* I N I T   C O M M */

export void InitComm(pr)
pPRR	pr;
{
    int n;

    /* get the message queue id and file descriptor number passed from cu */
    if (sscanf(pr->sbComm,":%d:%d",&vmsgqid,&n) != 2)
	UError("Invalid comm string from cu : %s", pr->sbComm);

    v->fnComm = n;
    v->os->adrReg0 = 0;	 /* Magic values */
    v->os->adrUser = 0;
    v->os->adrEntry = adrNil;	/* so we do NOT do ExecInit automatically */
    v->cpu->fBackupOnBpt = false;

    FSendCuMsg(MSG_INITCOMM);	/* tell cu that cdb is initialized */
} /* InitComm */
0707070001000313050407550000000000010000021615620460260163400000700000000000transV 0707070001000313061006440000000000010000010000000454650114400001700000000000transV/GET.err 0707070001000313071004440000000000010000011615710454650114400001500000007300transV/aux.c /* $Header: aux.c,v 1.8 86/08/06 15:10:31 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include "trans.h"

export int4	viaux, viauxMac, viauxMax = 0;
export int4	viauxFile;
export int4	viauxProcPhony;		/* something for phony procs */
export int4	viauxGlobalPhony;	/* something for unknown globals */
export pAUXU	vrgAux;				/* aux table */


/* I N I T   A U X */

export void InitAux()
{
    AUXU	aaux;

    aaux.isym = 0;
    IauxFAdd(&aaux);

    /* build something for phony procedures to point at */
    aaux.isym = isymNil;
    viauxProcPhony = IauxFAdd(&aaux);
    aaux.isym = 0;
    aaux.ti.tq0 = tqProc;
    aaux.ti.bt = btInt;
    IauxFAdd(&aaux);
    viauxGlobalPhony = IauxFAdd(AuxFBt(btInt));
} /* InitAux */


/* I A U X   F   A D D */

export int4 IauxFAdd(aux)
pAUXU	aux;
{
    if (viauxMac >= viauxMax) {
	viauxMax *= 2;
	vrgAux = (pAUXU) realloc(vrgAux, viauxMax * cbAUXU);
	if (vrgAux == 0)
	    Panic("Ran out of memory - auxillary table expansion");
    } /* if */
    viaux = viauxMac++;
    vrgAux[viaux] = *aux;

    return(viaux);
} /* IauxFAdd */


/* C H A N G E   A U X */

export void ChangeAux(iaux, aux)
int4	iaux;
pAUXU	aux;
{
    if (iaux > viauxMac)
	Panic("Change non-existant aux (%d)", iaux);
    if (iaux < viauxFile)
	dprint(10, ("ChangeAux: %s %ld\n", vsbEnt, visym));
    dprint(10, ("ChangeAux:\t%ld\t%ld\n", iaux, viaux-iaux));
    vrgAux[iaux] = *aux;
} /* ChangeAux */


/* A U X   F   I A U X */

export pAUXU AuxFIaux(iaux)
{
    if (iaux >= viauxMac)
	Panic("Accessed non-existant aux (%d)", iaux);

    if (iaux < viauxFile)
	dprint(10, ("AuxFIaux: %s %ld\n", vsbEnt, visym));
    dprint(10, ("AuxFIaux:\t%ld\t%ld\n", iaux, viaux-iaux));
    return(vrgAux + iaux);
} /* AuxFIaux */


/* A D D   T Q */

export void AddTq(iaux, tq)
int	tq;
int4	iaux;
{
    AUXU	aaux;

    aaux = *AuxFIaux(iaux);
    if (aaux.ti.tq5 != tqNil)
	Panic("Type is too complex");

    aaux.ti.tq5 = aaux.ti.tq4;
    aaux.ti.tq4 = aaux.ti.tq3;
    aaux.ti.tq3 = aaux.ti.tq2;
    aaux.ti.tq2 = aaux.ti.tq1;
    aaux.ti.tq1 = aaux.ti.tq0;
    aaux.ti.tq0 = tq;

    ChangeAux(iaux, &aaux);
} /* AddTq */


/* A U X   F   B T */

export pAUXU AuxFBt(bt)
int	bt;
{
    static AUXU	aaux;

    aaux.isym = 0;	/* zero out the word */
    aaux.ti.bt = bt;
    aaux.ti.lc = vlc;
    return(&aaux);
} /* AuxFBt */


/* P A T C H   T Q */

export void PatchTq(iaux, tq)
int	tq;
int4	iaux;
{
    AUXU	aaux;

    aaux = *AuxFIaux(iaux);

    if (aaux.ti.tq0 == tqNil)
	aaux.ti.tq0 = tq;
    else if (aaux.ti.tq1 == tqNil)
	aaux.ti.tq1 = tq;
    else if (aaux.ti.tq2 == tqNil)
	aaux.ti.tq2 = tq;
    else if (aaux.ti.tq3 == tqNil)
	aaux.ti.tq3 = tq;
    else if (aaux.ti.tq4 == tqNil)
	aaux.ti.tq4 = tq;
    else if (aaux.ti.tq5 == tqNil)
	aaux.ti.tq5 = tq;
    else
	Panic("Type is too complex");

    ChangeAux(iaux, &aaux);
} /* PatchTq */


/*  A D D   D I M */

export void AddDim(dim)
int	dim;
{
    AUXU	aaux;

    aaux.iaux = 1;
    IauxFAdd(&aaux);
    aaux.dn = 0;
    IauxFAdd(&aaux);
    aaux.dn = dim - 1;
    IauxFAdd(&aaux);
} /* AddDim */


/* I A U X   F   C O P Y */

export int4 IauxFCopy(iauxType)
int4	iauxType;
{
    int2	cAux = 0;
    int4	iaux;
    AUXU	aaux;

    /* we figure out how many aux's we have and then do a block copy */
    aaux = *AuxFIaux(iauxType);
    if (FComplexBt(aaux.ti.bt))
	cAux++;
    if (aaux.ti.tq0 == tqArray) cAux += 3;
    if (aaux.ti.tq1 == tqArray) cAux += 3;
    if (aaux.ti.tq2 == tqArray) cAux += 3;
    if (aaux.ti.tq3 == tqArray) cAux += 3;
    if (aaux.ti.tq4 == tqArray) cAux += 3;
    if (aaux.ti.tq5 == tqArray) cAux += 3;

    iaux = IauxFAdd(&aaux);
    for (iauxType++; cAux; cAux--)
	IauxFAdd(AuxFIaux(iauxType++));

    return(iaux);
} /* IauxFCopy */
0707070001000313101004440000000000010000011611760454650114400001700000003634transV/fread.c /* $Header: fread.c,v 1.2 85/09/16 08:57:17 peter Exp $ */




/* This version avoids long multiplies.
 * It is almost PURE AT&T code!
 */




/*	@(#)fread.c	3.11	*/
/*LINTLIBRARY*/
/*
 * This version reads directly from the buffer rather than looping on getc.
 * Ptr args aren't checked for NULL because the program would be a
 * catastrophic mess anyway.  Better to abort than just to return NULL.
 */
#include <stdio.h>

/*	@(#)stdiom.h	1.1	*/

/* The following macros improve performance of the stdio by reducing the
	number of calls to _bufsync and _wrtchk.  _BUFSYNC has the same
	effect as _bufsync, and _WRTCHK has the same effect as _wrtchk,
	but often these functions have no effect, and in those cases the
	macros avoid the expense of calling the functions.  */

#define _BUFSYNC(iop)	if (_bufend(iop) - iop->_ptr <   \
				( iop->_cnt < 0 ? 0 : iop->_cnt ) )  \
					_bufsync(iop)
#define _WRTCHK(iop)	((((iop->_flag & (_IOWRT | _IOEOF)) != _IOWRT) \
				|| (iop->_base == NULL)  \
				|| (iop->_ptr == iop->_base && iop->_cnt == 0 \
					&& !(iop->_flag & (_IONBF | _IOLBF)))) \
			? _wrtchk(iop) : 0 )
/* end of stdiom.h */

#define MIN(x, y)	(x < y ? x : y)

extern int _filbuf();
extern _bufsync();
extern char *memcpy();

int
fread(ptr, size, count, iop)
char *ptr;
int size, count;
register FILE *iop;
{
	register unsigned int nleft;
	register int n;

	if (size <= 0 || count <= 0) return 0;
	nleft = (count == 1) ? size : count * size;

	/* Put characters in the buffer */
	/* note that the meaning of n when just starting this loop is
	   irrelevant.  It is defined in the loop */
	for ( ; ; ) {
		if (iop->_cnt <= 0) { /* empty buffer */
			if (_filbuf(iop) == EOF)
				return (count - (nleft + size - 1)/size);
			iop->_ptr--;
			iop->_cnt++;
		}
		n = MIN(nleft, iop->_cnt);
		ptr = memcpy(ptr, (char *) iop->_ptr, n) + n;
		iop->_cnt -= n;
		iop->_ptr += n;
		_BUFSYNC(iop);
		if ((nleft -= n) <= 0)
			return (count);
	}
}
0707070001000313111004440000000000010000011612140454650114500001600000011051transV/init.c /* $Header: init.c,v 1.16 86/06/26 12:17:02 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include "trans.h"
#include <sys/stat.h>

export int	vfdSym; 	/* file descriptor to read from the file */
export char	*vsbStr;        /* string table buffer for OUR symbol table */
export int4	vcbStr; 	/* size of string table */
export HDRR	vahdr;
export ADRT	vadrFirstLine;

export int	*vmpIsymentIaux;		/* map V's no's to tes aux's */
export LDFILE	*vlfd;		/* loader file desc to access symtab */
export LDFILE	*vlfdLines;	/* loader file desc to access LINES */
export LDFILE	*vlfdStrings;	/* loader file desc to access STRINGS */
export int4	vcsym;          /* globally accessable length of symbol table */
export int4	vcbSsIn;        /* globally accessable size of string table */


/* I N I T   S Y M */

export void InitSym(sbFile, scale)
SBT	sbFile;
int	scale;
{
    int4	scaleSym, cLine, ret, cbSsOffset;
    AOUTHDR	opthead;	/* optional header info */
    SCNHDR	secthead;

    /* open the executable */
    if ((vlfd = ldopen(sbFile, NULL)) == NULL) {
	perror(sbFile);
	exit(1);
    } /* if */

    if (HEADER(vlfd).f_opthdr != sizeof(AOUTHDR))
	Panic("%s: bad optional header size (%d)\n", 
	    sbFile, HEADER(vlfd).f_opthdr);

    if (ldohseek(vlfd) == FAILURE)
	Panic("%s: bad optional header seek\n", sbFile);

    if (FREAD(&opthead, HEADER(vlfd).f_opthdr, 1, vlfd) != 1)
	Panic("%s: bad optional header read\n", sbFile);

    if (ldtbseek(vlfd) == FAILURE)
	Panic("%s: bad table seek\n", sbFile);

    /* Now we open two more streams for LINES and STRINGS */
    if ((vlfdLines = ldopen(sbFile, NULL)) == NULL) {
	perror(sbFile);
	exit(1);
    } /* if */

    if ((vlfdStrings = ldopen(sbFile, NULL)) == NULL) {
	perror(sbFile);
	exit(1);
    } /* if */

    vcsym = HEADER(vlfd).f_nsyms;
    if (vcsym == 0)
	Panic("%s is stripped.. There is nothing to translate!", sbFile);

    vahdr.cbText = opthead.tsize;
    vahdr.cbData = opthead.dsize;
    vahdr.cbBss = opthead.bsize;
    vahdr.entrypoint = opthead.entry;

    /* Make the tables proportionate to the size of the incoming symtab */

    scaleSym = (scale > 3) ? 3 : scale;

    /* string space */
    vcbSsIn = 0;
    cbSsOffset = HEADER(vlfd).f_symptr + (vcsym * SYMESZ);
    if (cbSsOffset > 0) {
	if (FSEEK(vlfdStrings, cbSsOffset, 0) != OKFSEEK)
	    Panic("Can't seek to string table");
	ret = FREAD((char *)&vcbSsIn, sizeof(vcbSsIn), 1, vlfdStrings);
	if ((ret != EOF) AND (ret != 1) AND (ret != 0))
	    Panic("Can't read string table: %ld", vcbSsIn);
    } /* if */

    InitSs((vcsym * 9) + vcbSsIn + 1000); /* exceeds theoretical maximum */

    /* file table */
    if (vifdMax == 0)
	vifdMax = 500;
    vrgFd = (pFDR) malloc(vifdMax * cbFDR);	
    if (vrgFd == fdNil)
	Panic("Ran out of memory - file table");

    /* proc table */
    if (vipdMax == 0)
	vipdMax = 1000;
    vrgPd = (pPDR) malloc(vipdMax * cbPDR);
    if (vrgPd == pdNil)
	Panic("Ran out of memory - procedure table");

    /* symbol table */
    if (visymMax == 0)
	visymMax = Max(2000, vcsym) * scaleSym;
    vrgSym = (pSYMR) malloc(visymMax * cbSYMR);
    if (vrgSym == symNil)
	Panic("Ran out of memory - symbol table");
    SymFAlloc(issNil, stNil, scNil, adrNil, 0L);

    /* global symbol table */
    if (visymGlMax == 0)
	visymGlMax = Max(1000, (vcsym / 4)) * scaleSym;
    vrgSymGlobal = (pSYMR) malloc(visymGlMax * cbSYMR);
    if (vrgSymGlobal == symNil)
	Panic("Ran out of memory - global symbol table");
    
    /* aux table */
    if (viauxMax == 0)
	viauxMax = Max(5000, vcsym) * scaleSym;
    vrgAux = (pAUXU) malloc(viauxMax * cbAUXU);
    if (vrgAux == auxNil)
	Panic("Ran out of memory - auxillary table");
    InitAux();

    /* line no table */
    if (vilineMax == 0) {
	if (ldshread(vlfdLines, 1, &secthead) != SUCCESS)
	    Panic("Could not read section header for line number info");
	vilineMax = Max(200, secthead.s_nlnno + 2);
    } /* if */
    vrgLine = (pLINER) malloc(vilineMax * cbLINER); 
    if (vrgLine == lineNil)
	Panic("Ran out of memory - line number table");

    if (vitdMax == 0)
	vitdMax = Max(2000, (vcsym /  20)) * scaleSym;
    vrgTd = (pTDR) malloc(vitdMax * cbTDR);	/* typedef table */
    if (vrgTd == 0)
	Panic("Ran out of memory - typedefs table");

    /* Next we set up a null line entry */
    vrgLine[0].iln = 0;
    vrgLine[0].dadr = 0;
    vilineMac++;

    vdot = 0;

    vmpIsymentIaux = (int4 *) malloc(vcsym * sizeof(int));
    if (vmpIsymentIaux == 0) {
	perror("Ran out of memory - symbol table map");
	exit(1);
    } /* if */
    ZeroBlock(vmpIsymentIaux, vcsym * sizeof(int));

} /* InitSym */
0707070001000313121004440000000000010000011612570454650114500001700000006627transV/ldlib.c /* $Header: ldlib.c,v 1.2 85/09/16 08:57:24 peter Exp $ */

/* NOTICE - This is hacked AT&T code!  For the purposes of the
 * Third Eye Software, Inc. COFF translator, it is functionally
 * equivalent.  I have just coded around a HUGE number of
 * expensive consistency checks that WE don't need.
 * If existence of this code makes you nervous, delete it and 
 * re-load the translator.
 */

/* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
 * This code ASSUMES that the ldptr used for reading SYMBOLS
 * is NOT THE SAME as the ldptr used for reading LINES!!
 * If they are, everything will break horribly!
 */

#include "trans.h"

static int	viVlnMax = 0;
static int	viVln = 0;
static LINENO	*vrgVLines;
static SYMENT	*vrgVSyms;


int ldlinit(ldptr, fcnindx)
LDFILE		*ldptr;
{
    extern int		fseek( );
    extern int		ldtbread( );
    extern int		ldshread( );

    static int		fFirstTime = true;
    SCNHDR		secthead;
    LINENO		line;
    long		endlnptr;

    if (vsyment->n_numaux != 1) {
      return(FAILURE);
    } else {
      if (fFirstTime) {
	fFirstTime = false;
	if (ldshread(ldptr, vsyment->n_scnum, &secthead) == SUCCESS) {
	  viVlnMax = secthead.s_nlnno;
	  viVln = 0;
	  if (FSEEK(ldptr, secthead.s_lnnoptr, BEGINNING) == OKFSEEK) {
	      vrgVLines = (LINENO *) malloc(viVlnMax * LINESZ);
	      if (FREAD(vrgVLines, LINESZ, viVlnMax, ldptr) != viVlnMax)
		  return(FAILURE);
	  }
	}
      } /* if */
      return(SUCCESS);
    }
}


int ldlitem(ldptr, linenum, lineent)
LDFILE		*ldptr;
int		linenum;
LINENO		*lineent;
{

  LINENO	*temp;

  viVln++;
  if (viVln >= viVlnMax)
    return(FAILURE);

  temp = (LINENO *) ((int)vrgVLines + viVln * LINESZ);

#if (CPU == CCI632) || (CPU == A3B2)

  if ((unsigned long)temp & 3) {
	/* we need to hand copy it */
	CopyBlock(lineent, temp, sizeof(*lineent));
  } else {
	*lineent = *temp;
  } /* if */

#else

    *lineent = *temp;

#endif (CPU == CCI632) || (CPU == A3B2)

    if (lineent->l_lnno != 0)
	return(SUCCESS);
    return(FAILURE);
}

#if 1
/* this version lets FREAD do its job in terms of buffering */

int ldtbread(ldptr, symnum, symentry)
LDFILE	*ldptr;
long	symnum;
SYMENT	*symentry;
{
    static int		isyment = 0, fFirstTime = true;
    extern int		fseek( );

    if (fFirstTime) {
	fFirstTime = false;
	if (FSEEK(ldptr, HEADER(ldptr).f_symptr, BEGINNING) != OKFSEEK)
	    return(FAILURE);
    } /* if */

    if (isyment != symnum)
	Panic("Symbol read assumption wrong: %ld instead of %ld",
		symnum, isyment);
    isyment++;

    if (FREAD(symentry, SYMESZ, 1, ldptr) != 1)
	return(FAILURE);
    return(SUCCESS);
}

#else

/* This version just reads the whole damn thing in in one shot */
int ldtbread(ldptr, symnum, symentry)
LDFILE	*ldptr;
long	symnum;
SYMENT	*symentry;
{
    static int		fFirstTime = true;
    extern int		fseek( );
    SYMENT		*temp;

    if (fFirstTime) {
	fFirstTime = false;
	if (FSEEK(ldptr, HEADER(ldptr).f_symptr, BEGINNING) != OKFSEEK)
	    return(FAILURE);
	vrgVSyms = (SYMENT *) malloc(vcsym * SYMESZ);
	if (FREAD(vrgVSyms, SYMESZ, vcsym, ldptr) != vcsym)
	    return(FAILURE);
    } /* if */

    temp = (SYMENT *) ((int) vrgVSym + symnum * SYMESZ);

#if (CPU == CCI632) || (CPU == A3B2)

    if ((unsigned long)temp & 3) {
	/* we need to hand copy it */
	CopyBlock(symentry, temp, sizeof(*symentry));
    } else {
	*symentry = *temp;
    } /* if */

#else

    *symentry = *temp;

#endif (CPU == CCI632) || (CPU == A3B2)

    return(SUCCESS);
}
#endif
0707070001000313131004440000000000010000011613130454650114500001600000007735transV/main.c /* $Header: main.c,v 1.11 86/06/19 23:32:52 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

/* ********************************************************** */
/* This is the symbol table translator for COFF style symbols */
/* ********************************************************** */

#include "trans.h"

export int	vfVerbose;		/* true if we want text out */
export int	vlevel;			/* debugging level */
export ADRT	vdot;			/* last known adr in TEXT space */

#if 0
exportdefine dprint(x, y) {if (vlevel >= x) printf y;}
#endif


/* M A I N */

export void main(argc, argv) 
int     argc;
char    *argv[];
{
    int		scale = 1;
    SBT		sbUsage, sbArg, sbProgram;
    FLAGT	fDidOne = false;
    pFDR	fd;
    pPDR	pd;

    sbUsage = "Usage: trans [-vup] [-s#] object_file\n";
    sbProgram = sbNil;

    while (*(++argv) != 0) {
	sbArg = *argv;
	if (*sbArg != '-') {
	    if (fDidOne)
		Panic("Too many files: %s", sbUsage);
	    fDidOne = true;
	    sbProgram = sbArg;
	} else {
	    switch (sbArg[1]) {
		case 'a':
		    vfPercentSigns = !vfPercentSigns;
		    vfNoUnderlines = !vfNoUnderlines;
		    break;
		case 'p':
		    vfPercentSigns = !vfPercentSigns;
		    break;
		case 'u':
		    vfNoUnderlines = !vfNoUnderlines;
		    break;
		case 'd':
		    vlevel = atoi(sbArg+2);
		    break;
		case 's':
		    scale = atoi(sbArg+2);
		    if ((scale <= 0) || (scale > 30)) {
			printf("Bad scaling parameter: %d > 30\n", scale);
			exit(1);
		    } /* if */
		    break;
		case 'S':
		    /* this is a redo with specific sizes */
		    sscanf(sbArg+2, "%d,%d,%d,%d,%d,%d,%d",
			&vifdMac, &vipdMac, &visymMac, &visymGlMac,
			&viauxMac, &vilineMac, &vissMac);
		    break;

		case 'v':
		    vfVerbose++;
		    break;
		case 'w':
		    vfWarnUndefined++;
		    break;
		default:
		    Panic("Illegal option.\n%s", sbUsage);
	    } /* switch */
	} /* if */
    } /* while */

    if (!fDidOne)
	Panic("%s", sbUsage);

    InitSym(sbProgram, scale);
    Map(sbProgram);
    EndFile();	/* end the last file done */

    DumpAll(sbProgram);

    if (vfVerbose)
	PrintAll();

    exit(0);
} /* main */


/* D U M P   A L L */

export void DumpAll(sbFile)
char	*sbFile;
{
    char	sbBuf[200];
    int		cGlobals, fn;
    long	cbOffset;
    extern struct exec	vhead;

    strcpy(sbBuf, sbFile);
    strcat(sbBuf, ".cdb");

    vahdr.vstamp = CURRENT_VERSION;
    vahdr.ijokeDay = ijokeNil;

    if ((fn = open(sbBuf, O_WRONLY+O_CREAT, 0666)) <= -1) {
	perror("can't open output file");
	exit(1);
    } /* if */

#define WRITE_IT(buf, size, count, msg) \
    if (write(fn, buf, (size) * (count)) != (size) * (count)) {\
	    perror(msg);\
	    exit(1);\
    } else {\
	cbOffset += (size) * (count);\
    } /* if */

    cbOffset = 0;
    WRITE_IT(&vahdr, cbHDRR, 1, "header")

    vahdr.ipdMax = vipd;
    vahdr.cbPdOffset = cbOffset;
    WRITE_IT(vrgPd, cbPDR, vipdMac, "procedures")

    vahdr.ifdMax = vifd + 1;
    vahdr.cbFdOffset = cbOffset;
    WRITE_IT(vrgFd, cbFDR, vifdMac, "files")

    vahdr.ilineMax = viline + 1;
    vahdr.cbLineOffset = cbOffset;
    WRITE_IT(vrgLine, cbLINER, vilineMac, "lines")

    vahdr.iauxMax = viauxMac;
    vahdr.cbAuxOffset = cbOffset;
    WRITE_IT(vrgAux, cbAUXU, viauxMac, "auxes")

    vahdr.isymMax = visymMac + visymGlMac; /* ALL symbols */
    vahdr.cbSymOffset = cbOffset;
    WRITE_IT(vrgSym, cbSYMR, visymMac, "symbols")

    vahdr.isymGl = visymMac;
    vahdr.isymGlMax = vahdr.isymMax;
    WRITE_IT(vrgSymGlobal, cbSYMR, visymGlMac, "globals")

    vahdr.itdMax = vitdMac;
    vahdr.cbTdOffset = cbOffset;
    WRITE_IT(vrgTd, cbTDR, vitdMac, "td's")

    vahdr.issMax = vissMac;
    vahdr.cbSsOffset = cbOffset;
    WRITE_IT(vsbNewStr, vissMac, 1, "strings");

    lseek(fn, 0L, 0);
    WRITE_IT(&vahdr, cbHDRR, 1, "header")
} /* DumpAll */


/* P A N I C */

/* VARARGS1 */
export void Panic(sbMsg, arg1, arg2, arg3, arg4)
SBT	sbMsg;
int	arg1, arg2, arg3, arg4;
{
    if (sbMsg != sbNil)
	printf(sbMsg, arg1, arg2, arg3, arg4);
    printf("\n");
    exit(1);
} /* Panic */
0707070001000313141004440000000000010000011613470454650114500001500000013165transV/map.c /* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */
/* $Header: map.c,v 1.9 86/09/07 11:46:11 peter Exp $ */

#include "trans.h"

export pSYMENTR vsyment;		/* current sysV symbol entry */
export pAUXENTR vauxent;		/* current sysV aux entry */
export SBT	vsbEnt;			/* current symbol's name */

export int4	vcsymCur;		/* upward count of symbols */
export FLAGT	vfNoUnderlines = NO_UNDERLINES;
export FLAGT	vfPercentSigns = PERCENT_SIGNS;
export FLAGT	vfBlockAdded = false;
export int4	vrgIsymBlock[20];
export int4	viBlock;


/* N E X T  S Y M E N T */

export pSYMENTR NextSyment()
{
    SBT			sb;
    static char 	sbBuffer[10];
    static SYMENTR	asyment;
    static AUXENTR	aauxent;

    vsyment = &asyment;
    vauxent = &aauxent;
    if (vcsymCur < 0)
	vcsymCur = 0;
    else
	vcsymCur += (vsyment->n_numaux + 1);

    if (ldtbread(vlfd, vcsymCur, vsyment) == FAILURE)
	Panic("Can't read %dth symbol", vcsymCur);

    if (vsyment->n_numaux) {
	if (ldtbread(vlfd, vcsymCur + 1, vauxent) == FAILURE)
	    Panic("Can't read %dth aux", vcsymCur);
     } else
	vauxent = 0;

#ifdef SYSV_0
    strcpy(sbBuffer, vsyment->n_name);
    sbBuffer[8] = 0;
    vsbEnt = sbBuffer;
#else
    vsbEnt = (SBT) ldgetname(vlfdStrings, vsyment);
#endif

    if ((!vfNoUnderlines) AND (*vsbEnt == '_'))
	vsbEnt++;

    if (vfPercentSigns) {
	for (sb = vsbEnt; *sb; sb++) {
	    if (*sb == '%')
		*sb = '$';
	} /* for */
    } /* if */

    return(vsyment);
} /* NextSyment */


/* M A P */

export void Map()
{
    FAST pSYMENTR syment;
    FAST pSYMR	sym;
    SBT		sb;
    FLAGT	fBfPending;
    pSYMR	symBlock;
    SYMENTR	asyment;
    int4	isym;
    int		sc, st, cauxLast;
    pPDR	pd;
    pFDR	fd;
    static int mpCoffSc[] = { scNil, scText, scData, scBss, scAbs };

    vcsymCur = -1;
    cauxLast = 0;
    fBfPending = false;

    DoFile(adrNil, "temp");
#if (MFG == CT)
    DoFile((ADRT)0, "dummy");
#endif /* (MFG == CT) */

    while ((vcsymCur + cauxLast) < vcsym) {

	NextSyment();
	cauxLast = vsyment->n_numaux + 1;

	if (fBfPending AND (vsyment->n_sclass != C_FCN)) {
	    fBfPending = false;

	    /* previous symbol was p;roc WITH info but NO BODY!! */
	    if (!vfDidLastFile) {
		if (vdotEnd == adrNil)
		    vdotEnd = vdot;
		EndFile(vdotEnd);
		vfDidLastFile = true;
	    } /* if */

	    sym->st = stProc;
	    sym->index = viauxProcPhony;
	    ProcInsert(isym, sym->value, 0);
	} /* if */

	sc = mpCoffSc[vsyment->n_scnum >= 0 ? vsyment->n_scnum : 0];
	st = stNil;
	isym = vcsymCur;
	switch (vsyment->n_sclass) {

	case C_FILE:
	    DoFile(vdotEnd, vauxent->x_file.x_fname);
	    break;

	case C_TPDEF:
	    DoTypedef();
	    st = stTypedef;
	    sc = scInfo;
	    goto dovar;	/* KLUDGE - is this right?? */
	    break;

	case C_STRTAG:
	    DoStruct(btStruct);
	    break;

	case C_UNTAG:
	    DoStruct(btUnion);
	    break;

	case C_ENTAG:
	    DoEnum();
	    break;

	case C_REG:
	    sc = scRegister;
	    goto DoLocal;

	case C_AUTO:
	    sc = scAbs;
DoLocal:
	    st = stLocal;
	    if (!vfBlockAdded) {
		sym = SymFAlloc(issNil, stBlock, scText,
				SymFIsym(visymProc)->value);
		PushIsym(visym);
		vfBlockAdded = true;
	    } /* if */
	    goto dovar;

	case C_EXT:
	    st = stGlobal;
	    if (sc == scText) {
		if (visymProc != isymNil)
		    EndProc(vsyment->n_value);
		goto dovar;
	    } else {
		sym = SymFGlobal(IssFSb(vsbEnt),stGlobal, sc, vsyment->n_value);
		goto doglobal;
	    } /* if */
	    break;

	case C_STAT:
	    if (vsyment->n_name[0] == '.') {
		sb = vsyment->n_name;
		if (FSbCmp(sb, ".text")) {

		    if (vfDidText)
			/* handles files with no file symbol */
			DoFile(adrNil, "phony file");

		    /* not all compiler/assembler/loaders put these out */
		    SymFIsym(visymFile)->value = vrgFd[vifd].adr = 
			    vsyment->n_value;
		    vrgFd[vifd].adr = vsyment->n_value;
		    vdotEnd = vsyment->n_value + vauxent->x_scn.x_scnlen;
		    vfDidText = true;
		    break;

		} else if (FSbCmp(sb, ".data") OR FSbCmp(sb, ".bss"))
		    break;	/* we get these by the bushelful */
	    } /* if */

	    if (sc == scText)
		vdot = vsyment->n_value;

	    st = stStatic;
	    goto dovar;

	case C_LABEL:
	    sc = scText;
	    st = stLabel;
	    vdot = vsyment->n_value;
	    goto dovar;

	case C_REGPARM:
	    sc = scRegister;
	    st = stParam;
	    if (CHECK_REG_PARAMS)
		vfAlsoEqual = false;
	    goto dovar;

	case C_ARG:
	    sc = scAbs;
	    st = stParam;
	    goto dovar;

dovar:
	    sym = SymFAlloc(IssFSb(vsbEnt), st, sc, vsyment->n_value);
	    if (st == stTypedef)
		AddTd(sym);

doglobal:
	    isym = visym;
	    asyment= *vsyment;
	    sym->index = IauxFSyment(&asyment);

#if 0
	    if ((sc == scText) AND (vsyment->n_type == 0)) {
		if (vsyment->n_sclass == C_EXT) {
#endif
	    if (sc == scText) {
		if (vsyment->n_sclass == C_EXT) {

		    if (vsyment->n_type != 0) {
			fBfPending = true;
			break;
		    } /* if */

		    /* it's a procedure with no type info */
		    if (!vfDidLastFile) {
			if (vdotEnd == adrNil)
			    vdotEnd = vdot;
			EndFile(vdotEnd);
			vfDidLastFile = true;
		    } /* if */

		    sym->st = stProc;
		    ProcInsert(isym, sym->value, 0);

		} else if (vsyment->n_sclass == C_STAT) {

		    /* it's a label */
		    sym->st = stLabel;

		} /* if */
	    } /* if */
#if 0
	    if ((vlc == lcFortran) AND (st == stParam))
		AddTq(sym->index, tqRef);
#endif
	    break;

	case C_FCN:
	    fBfPending = false;
	    if (FSbCmp(vsbEnt,".bf")) {
		DoProc(vsyment->n_value);
	    } else {
		EndProc(vsyment->n_value);
	    } /* if */
	    break;

	case C_BLOCK:
	    if (FSbCmp(vsbEnt, ".bb")) {
		DoLBrac(vsyment->n_value);
	    } else {
		DoRBrac(vsyment->n_value);
	    } /* if */
	    break;

	} /*switch */

    } /* while */

    FixFd();
} /* Map */
0707070001000313151004440000000000010000011614210454650114500001600000006651transV/misc.c /* $Header: misc.c,v 1.4 86/06/19 23:32:58 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include "trans.h"

export int4	vissMac, vissMax;
export SBT	vsbNewStr, vsbMac, vsbMax;	/* new string table */

#define modHash		512

typedef struct HASHS {
	char	*sb;
	int	iss;
	struct HASHS	*hashNext;
} HASHR, *pHASHR;
#define cbHASHR sizeof(HASHR)
#define hashNil ((pHASHR)0)

HASHR		vrgHash[modHash];
pHASHR	vhashMac, vhashMax;


/* I N I T   S S */

export void InitSs(cb)
int	cb;
{
    /* setup string space */
    vissMax = cb;
    vsbNewStr = (SBT) malloc(vissMax);
    if (vsbNewStr == sbNil)
	Panic("Ran out of memory - string table");
    vsbMac = vsbNewStr;
    *vsbMac++ = 0;	/* start off with a null string */
    vissMac = 1;
} /* InitSs */


/* S B   F   I S S */

export SBT SbFIss(iss)
int4	iss;
{
    if ((iss < 0) OR (iss >= vissMac))
	Panic("Iss out of bounds (%ld)", iss);
    
    return(vsbNewStr + iss);
} /* SbFIss */


/* I S S   F   S B */

export int4 IssFSb(sb)
FAST SBT	sb;
{
    FAST pHASHR	hash;
    FAST pHASHR	hashPrev;
    FAST SBT	sbTemp;
    FAST int	sum;

    /* first do a hash to see if we already have it */
    sum = 0;
    if (sb != 0) {
	sbTemp = sb;

	while (*sbTemp)
	    sum += *sbTemp++;
    } /* if */
    hash = vrgHash + (sum % modHash);

    while (hash) {
	if ( (hash->sb != 0)
	   && (!strcmp(sb, hash->sb)) ) {
	    return(hash->iss);			/* GOT IT! */
	} /* if */
	hashPrev = hash;
	hash = hash->hashNext;
    } /* while */
    hash = hashPrev;

    /* we don't have it yet, create it */
    if (vhashMac >= vhashMax) {
	vhashMac = (pHASHR) malloc(3000 * cbHASHR);
	if (vhashMac == 0)
	    Panic("Ran out of memory - hash expansion");
	vhashMax = vhashMac + 3000;
    } /* if */
    hash->hashNext = vhashMac++;
    hash = hash->hashNext;

    if (vissMac + strlen(sb) > vissMax)
	Panic("Ran out of string space"); /* this error "can't happen" ... */

    sbTemp = hash->sb = vsbMac;
    hash->iss = vissMac;

    while (*(sbTemp++) = *(sb++))
	;

    vsbMac = sbTemp;
    vissMac = vsbMac - vsbNewStr;
    hash->hashNext = hashNil;

    return (hash->iss);
} /* IssFSb */


/* M A X */

export int Max(a, b)
int	a, b;
{
    return( (a > b) ? a : b );
} /* Max */


/* C O P Y   B L O C K */

export void CopyBlock (dest, src, size)
FAST char	*dest;
FAST char	*src;
FAST int	size;
{
    while (size--)
	*(dest++)= *(src++);
} /* CopyBlock */


/* Z E R O   B L O C K */

export void ZeroBlock (src, size)
FAST char	*src;
FAST int	size;
{
    while (size--)
	*(src++)= 0;
} /* ZeroBlock */


/* F   S B   C M P */

export FLAGT FSbCmp(sb1, sb2)
FAST char *sb1, *sb2;
{
    if (sb1 == 0 || sb2 == 0)
	return(false);

    while (*sb1 == *sb2) {
	if (*sb1 == '\0')
	    return(true);
	sb1++;
	sb2++;
    } /* while */

    return(false);
} /* FSbCmp */


/* D O   R   B R A C */

export void DoRBrac(adr)
ADRT	adr;
{
    vdot = adr;
    SymFAlloc(issNil, stEnd, scText, adr, vrgIsymBlock[--viBlock]);
    SymFIsym(vrgIsymBlock[viBlock])->index = visym + 1;
} /* DoRBrac */


/* D O   L   B R A C */

export void DoLBrac(adr)
ADRT	adr;
{
    pSYMR	sym;

    SymFAlloc(issNil, stBlock, scText, adr, 0L);
    vdot = adr;
    vrgIsymBlock[viBlock++] = visym;
} /* DoLBrac */


/* F   C O M P L E X   B T */

export FLAGT FComplexBt(bt)
int	bt;
{
    switch (bt) {
	case btUnion:
	case btStruct:
	case btEnum:
	case btTypedef:
	    return (true);

    default:
	    return (false);
    } /* switch */
} /* FComplexBt */
0707070001000313161004440000000000010000011614550454650114500001700000017230transV/print.c /* $Header: print.c,v 1.6 86/06/19 23:33:01 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include "trans.h"

int	vindent;


/* P R I N T   T Q */

local void PrintTq(tq)
int	tq;
{
    switch (tq) {
	case tqArray:	printf("Array of "); break;
	case tqPtr:	printf("Pointer to "); break;
	case tqProc:	printf("Function returning "); break;
	case tqRef:	printf("Reference to "); break;
    } /* switch */
} /* PrintTq */


/* P R I N T   B T */

local void PrintBt(bt)
int	bt;
{
    switch (bt) {
	default:	printf("Unknown-bt(%d)", bt);	break;
	case btAdr:	printf("Adr ");			break;
	case btChar:	printf("Char ");		break;
	case btUChar:	printf("UChar ");		break;
	case btShort:	printf("Short ");		break;
	case btUShort:	printf("UShort ");		break;
	case btInt:	printf("Int ");			break;
	case btUInt:	printf("UInt ");		break;
	case btLong:	printf("Long ");		break;
	case btULong:	printf("ULong ");		break;
	case btFloat:	printf("Float ");		break;
	case btDouble:	printf("Double ");		break;
	case btStruct:	printf("Struct ");		break;
	case btUnion:	printf("Union ");		break;
	case btEnum:	printf("Enum ");		break;
	case btTypedef: printf("User type ");		break;
	case btRange:	printf("Range ");		break;
	case btSubRange: printf("Subrange ");		break;
	case btComplex:	printf("Complex ");		break;
	case btLogical:	printf("Logical ");		break;
	case btVoid:	printf("Void ");		break;
    } /* switch */
} /* PrintBt */


/* I A U X   F   P R I N T   T Y P E */

local void IauxFPrintType(iaux)
int4	iaux;
{
    AUXU	aaux;

    aaux = *AuxFIaux(iaux++);
    PrintTq(aaux.ti.tq0);
    PrintTq(aaux.ti.tq1);
    PrintTq(aaux.ti.tq2);
    PrintTq(aaux.ti.tq3);
    PrintTq(aaux.ti.tq4);
    PrintTq(aaux.ti.tq5);
    if (aaux.ti.lc != lcC)
	printf("Fortran ");
    PrintBt(aaux.ti.bt);

    if (FComplexBt(aaux.ti.bt)) {
	printf("ref = %ld ", AuxFIaux(iaux++)->isym);
    } else if (aaux.ti.bt == btRange) {
	printf("[%ld", AuxFIaux(iaux++)->dn);
	printf("..%ld] ", AuxFIaux(iaux++)->dn);
    } else if (aaux.ti.bt == btSubRange) {
	iaux++;		/* step over iaux of parent */
	printf("[%ld", AuxFIaux(iaux++)->dn);
	printf("..%ld] ", AuxFIaux(iaux++)->dn);
    } /* if */

#define PRINTDIM(tq)\
    if (tq == tqArray) {\
	iaux++;	/* step over iaux of base scalar type */\
	printf("[%ld", AuxFIaux(iaux++)->dn);\
	printf(", %ld] ", AuxFIaux(iaux++)->dn);\
    }

    PRINTDIM(aaux.ti.tq5);
    PRINTDIM(aaux.ti.tq4);
    PRINTDIM(aaux.ti.tq3);
    PRINTDIM(aaux.ti.tq2);
    PRINTDIM(aaux.ti.tq1);
    PRINTDIM(aaux.ti.tq0);

    return(iaux);
} /* IauxFPrintType */


/* P R I N T   S Y M */

local void PrintSym(sym)
pSYMR	sym;
{
    int4	iaux;

    if (sym->iss != issNil)
	printf("\"%s\": ", SbFIss(sym->iss));
    else
	printf("\"\": ");

    switch (sym->st) {
	case stTypedef:
		break;

	case stParam:
	case stLocal:
	case stNil:
		printf("%ld, ", sym->value);
		break;
	case stProc:
		if (sym->index != viauxProcPhony)
		    vindent++;
	case stLabel:
	case stEnd:
	case stFile:
	case stCommon:
	case stBlock:
	case stStatic:
	case stGlobal:
		if (sym->value == adrNil)
		    printf("adrNil, ");
		else
		    printf("%#lx, ", sym->value);
		break;
	case stMember:
		printf("offset %ld, ", sym->value);
		break;
    } /* switch */

    switch (sym->st) {
	case stNil:	printf("stNil "); break;
	case stGlobal:	printf("Extern "); break;
	case stStatic:	printf("Static "); break;
	case stParam:	printf("Param "); break;
	case stLocal:	printf("Local "); break;
	case stLabel:	printf("Label "); break;
	case stCommon:	printf("Common "); vindent++; break;
	case stBlock:	printf("Block "); vindent++; break;
	case stProc:	printf("Procedure "); break;
	case stMember:	printf("Member "); break;
	case stEnd:	printf("End "); break;
	case stTypedef:	printf("Typedef "); break;
	case stFile:	printf("File name "); vindent++; break;
    } /* switch */

    switch (sym->sc) {
	case scNil:		printf("scNil "); break;
	case scText:		printf("Text "); break;
	case scData:		printf("Data "); break;
	case scBss:		printf("Bss "); break;
	case scRegister:	printf("Register "); break;
	case scAbs:		printf("Absolute "); break;
	case scUndefined:	printf("scUndefined "); break;
	case scInfo:		printf("Info "); break;
	case scBits:		printf("BitField "); break;
    } /* switch */

    iaux = sym->index;
    switch (sym->st) {
	default: printf("ref = %ld ", iaux);	break;

	case stLabel:
	    break;
	case stProc:
		printf("ref = %ld ", AuxFIaux(iaux++)->isym);
		/* fall through */

	case stMember:
		if (iaux == 0)	/* it MUST be an ENUM name */
		    break;
		/* fall through */

	case stStatic:
	case stGlobal:
	case stLocal:
	case stParam:
	case stTypedef:
		iaux = IauxFPrintType(iaux);
		if (sym->sc == scBits)
		    printf("width = %ld ", AuxFIaux(iaux)->width);
		break;
    } /* switch */
    printf("\n");

} /* PrintSym */


/* P R I N T   I N D E N T */

local void PrintIndent()
{
    register int	i;

    for (i = 0; i < vindent; i++)
	printf("    ");
} /* PrintIndent */


/* P R I N T   L I N E S */

local void PrintLines(iline)
register int	iline;
{
    int		i;
    ADRT	dadr, dadrLast;

    dadrLast = 0;
    for (i = 0; iline < vilineMac; i++, iline++) {
	dadr = vrgLine[iline].dadr;
	if (vrgLine[iline].dadr < dadrLast)
	    break;
	printf("%s%3d %3d: 0x%lx", (i % 4) ? "\t" : "\n\t",
			iline, vrgLine[iline].iln, dadr);
	dadrLast = dadr;
    } /* for */
} /* PrintLines */


/* P R I N T   F I L E S */

local void PrintFiles()
{
    register int	ifd;
    register pFDR	fd;
    
    for (ifd = 0, fd = vrgFd; ifd < vifdMac; ifd++, fd++) {
	printf("%3d: \"%s\" %#lx", ifd, SbFIss(fd->iss), fd->adr);
	if (fd->ipd != ipdNil)
	    printf("\t\"%s\"", SbFIss(SymFIsym(vrgPd[fd->ipd].isym)->iss) );
	printf("\n");
    } /* for */
} /* PrintFiles */


/* P R I N T   P R O C S */

local void PrintProcs()
{
    register int	ipd;
    pPDR	pd;

    pd = vrgPd;
    for (ipd = 0; ipd < vipdMac; ipd++, pd++) {
	printf("%3d: \"%s\" addr: %#lx  isym: %ld",
		ipd, SbFIss(SymFIsym(pd->isym)->iss), pd->adr, pd->isym);
	if (pd->iline > 0)
	    PrintLines(pd->iline);
	printf("\n");
    } /* for */
} /* PrintProcs */


/* P R I N T   A L L */

export void PrintAll() 
{
    register int	i;
    pTDR	td;

    printf("Header infomation:\n");

    printf("	vstamp:		%8ld\n", vahdr.vstamp);
    printf("	cbText:		%8ld\n", vahdr.cbText);
    printf("	cbData:		%8ld\n", vahdr.cbData);
    printf("	cbBss:		%8ld\n", vahdr.cbBss);
    printf("	ipdMax:		%8ld\n", vahdr.ipdMax);
    printf("	cbPdOffset:	%8ld\n", vahdr.cbPdOffset);
    printf("	ifdMax:		%8ld\n", vahdr.ifdMax);
    printf("	cbFdOffset:	%8ld\n", vahdr.cbFdOffset);
    printf("	ilineMax:	%8ld\n", vahdr.ilineMax);
    printf("	cbLineOffset:	%8ld\n", vahdr.cbLineOffset);
    printf("	issMax:		%8ld\n", vahdr.issMax);
    printf("	cbSsOffset:	%8ld\n", vahdr.cbSsOffset);
    printf("	isymMax:	%8ld\n", vahdr.isymMax);
    printf("	cbSymOffset:	%8ld\n", vahdr.cbSymOffset);
    printf("	isymGl:		%8ld\n", vahdr.isymGl);
    printf("	isymGlMax:	%8ld\n", vahdr.isymGlMax);
    printf("	iauxMax:	%8ld\n", vahdr.iauxMax);
    printf("	cbAuxOffset:	%8ld\n", vahdr.cbAuxOffset);
    printf("	itdMax:		%8ld\n", vahdr.itdMax);
    printf("	cbTdOffset:	%8ld\n", vahdr.cbTdOffset);

    vindent = 0;
    printf("\n\nSYMBOLS:\n\n");
    for (i = 0 ; i < visymMac; i++) {
	if (vrgSym[i].st == stEnd)
	    vindent--;
	PrintIndent();
	printf("%d. ", i);
	PrintSym(vrgSym + i);
    } /* for */

    printf("\n\nGLOBALS:\n\n");
    for (i= 0 ; i < visymGlMac; i++)
	PrintSym(vrgSymGlobal + i);

    printf("\n\nTYPEDEFS\n\n");
    for (i= 0, td = vrgTd; i < vitdMac; td++, i++) {
	printf("%2d: %s  ", i, SbFIss(td->iss));
	PrintSym(vrgSym + td->isym);
    } /* for */

    printf("\n\nPROCS:\n\n");
    PrintProcs();

    printf("\n\nFILES:\n\n");
    PrintFiles();
} /* PrintAll */
0707070001000313171004440000000000010000011615450454650114500001500000004116transV/sym.c /* $Header: sym.c,v 1.6 86/06/26 12:17:05 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include "trans.h"

export int4	visym, visymMac, visymMax = 0;
export pSYMR	vrgSym;	/* symbol table */
export int4	visymGl, visymGlMac, visymGlMax = 0;
export pSYMR	vrgSymGlobal;	/* Global symbol table */
export pSYMR	vsym;	/* symbol associated with visym OR visymGl */

#define istackMax	100
local int4	vrgIsymStack[istackMax];
local int	vistack = 0;


/* P U S H   I S Y M */

export void PushIsym(isym)
int4	isym;
{
    if (vistack >= istackMax)
	Panic("Symbol stack overflow");

    vrgIsymStack[vistack++] = isym;
} /* PushIsym */


/* I S Y M   F   P O P */

export int4 IsymFPop()
{
    if (vistack <= 0)
	Panic("Symbol stack underflow");

    return(vrgIsymStack[--vistack]);
} /* SymFPop */


/* I S Y M   F   S Y M */

export int4 IsymFSym(sym)
pSYMR	sym;
{
    return(sym - vrgSym);
} /* IsymFSym */


/* S Y M   F   I S Y M */

export pSYMR SymFIsym(isym)
int4	isym;
{
    dprint(10, ("SymFIsym:\t%ld\t%ld\n", isym, visym-isym));
    return(vrgSym + isym);
} /* SymFIsym */


/* S Y M   F   A L L O C */

export pSYMR SymFAlloc(iss, st, sc, value, index)
int4	iss;
int2	sc, st;
int4	value, index;
{
    FAST pSYMR	sym;
    static SYMR	asymZeroes;

    if (visymMac >= visymMax)
	Panic("Symbol table overrun");
	/* "can't happen" .... */

    visym = visymMac++;
    vsym = sym = vrgSym + visym;
    sym->iss = iss;
    sym->value = value;
    sym->st = st;
    sym->sc = sc;
    sym->index = index;
    return(sym);
} /* SymFAlloc */


/* S Y M   F   G L O B A L */

export pSYMR SymFGlobal(iss, st, sc, value)
int4	iss;
int2	sc, st;
int4	value;
{
    FAST pSYMR	sym;

    if (visymGlMac >= visymGlMax) {
	visymGlMax *= 2;
	vrgSymGlobal = (pSYMR) realloc(vrgSymGlobal, visymGlMax * cbSYMR);
	if (vrgSymGlobal == symNil)
	    Panic("Global symbol table overrun");
    } /* if */

    visymGl = visymGlMac++;
    vsym = sym = vrgSymGlobal + visymGl;
    sym->iss = iss;
    sym->value = value;
    sym->st = st;
    sym->sc = sc;
    sym->index = 0;
    return(sym);
} /* SymFGlobal */
0707070001000313201004440000000000010000011615720454650114500001600000032421transV/type.c /* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */
/* $Header: type.c,v 1.26 86/09/18 07:58:04 peter Exp $ */

#include "trans.h"

export int4	vipd, vipdMac, vipdMax = 0;	
export pPDR	vrgPd;	/* procedure descriptors */
export int4	vifd, vifdMac, vifdMax = 0;
export pFDR	vrgFd;	/* file decriptors */
export int4	viline, vilineMac, vilineMax = 0;
export pLINER	vrgLine;	/* line info */
export int4	vitd, vitdMac, vitdMax = 0;
export pTDR	vrgTd;		/* typedefs */

export int4	visymProc;
export int4	visymEnd;
export FLAGT	vfWarnUndefined = false;
export ADRT	vdotStart;
export ADRT	vdotEnd;		/* adr current file ends at */
export FLAGT	vfDidLastFile;		/* obscure hack for Motorola LD */
export FLAGT	vfDidText;		/* detects files w/o file symbol */
export int4	visymFile;
export int	vlc = lcC;		/* language code for current file */

export FLAGT	vfAlsoEqual = ALSO_EQUAL;
int		vcsymProc = 0;
ADRT		vadrProc = adrNil;
int		vilnProc;


/* I A U X   F   I S Y M E N T */

export int4 IauxFIsyment(isyment)
int4	isyment;
{
    int4	iaux = iauxNil;

    /* check for garbage in the tagndx field OR the mapping array */
    if ((isyment >= vcsym) OR (isyment < 0)) {
	printf("Warning: %d: %s had its type info garbaged (isyment: %ld)\n",
		    vcsymCur, vsbEnt, isyment);
    } else if (isyment == 0) {
	iaux = iauxNil;
    } else {
	iaux = vmpIsymentIaux[isyment];
	if ((iaux < 0) OR (iaux >= viauxMac)) {
	    printf("Warning: %d: %s had its type info garbaged (iaux: %ld)\n",
		    vcsymCur, vsbEnt, iaux);
	    iaux = iauxNil;
	} /* if */
    } /* if */
    return(iaux);
} /* IauxFIsyment */


/* A D D   T D */

export void AddTd(sym)
pSYMR	sym;
{
    int4	i, iss;
    pTDR	td;

    iss = sym->iss;
    for (i = 0, td = vrgTd; i < vitdMac; i++, td++)
	if (td->iss == iss)
	    return;	/* we already have it */

    if (vitdMac >= vitdMax) {
	vrgTd = (pTDR) realloc(vrgTd, vitdMax*2*cbTDR);
	if (vrgTd == 0)
	    Panic("Ran out of memory - typedef table expansion");
	vitdMax *= 2;
    } /* if */
    vitd = vitdMac++;
    vrgTd[vitd].iss = sym->iss;
    vrgTd[vitd].isym = IsymFSym(sym);
} /* AddTd */


/* D O   T Y P E D E F */

export void DoTypedef()
{
    pSYMR	sym;
    int4	isym;
    int4	iaux;

    if (vauxent != 0) { /* we have a pointer to parent */
	iaux = IauxFIsyment(vauxent->x_sym.x_tagndx);
	if (iaux != iauxNil) {
	    isym = AuxFIaux(iaux + 1)->isym;
	    sym = SymFIsym(isym);
	    if (sym->iss == issNil)
		sym->iss = IssFSb(vsbEnt);
	} /* if */
    } /* if */
} /* DoTypedef */


/* D O   E N U M */

export void DoEnum() 
{
    /* generate the syms for beginning, ending and members of
     *	a enum and return an iaux to the type pointing at this
     *	enum.
     */
    pSYMR	sym;			/* sym for the beginning of enum */
    pSYMR	symField;		/* sym used for its fields and stEnd */
    int4	isymStart;		/* isym for this symbol */
    AUXU	aaux;

    /* get sym and init for Enum */
    sym = SymFAlloc(issNil, stBlock, scInfo, 0L, 0L);
    isymStart = visym;
    if (*vsbEnt == '.') 
	sym->iss = issNil;
     else
	sym->iss = IssFSb(vsbEnt);

    /* put out an aux that will be used when refering to this type.  */
    vmpIsymentIaux[vcsymCur] = IauxFAdd(AuxFBt(btEnum));
    aaux.isym = isymStart;
    IauxFAdd(&aaux);

    /* get the members */
    while ((NextSyment())->n_sclass == C_MOE) {
	symField = SymFAlloc(IssFSb(vsbEnt), stMember, scInfo,
			vsyment->n_value, 0L);
    } /* while */

    /*
     * put out end of enum with a link back to the front
     *	and link original sym to the next symbol.
     */

    SymFIsym(isymStart)->index = visym + 2;
    symField = SymFAlloc(issNil, stEnd, scInfo, 0L, isymStart);
} /* DoEnum */


/* D O   S T R U C T */

export void DoStruct(bt) 
int2	bt;
{
    /*
     * put out the syms and auxs for the beginning, end, and
     *	fields of a structure or union. Return an iaux that
     *	can be used refering to the struct or union.
     */
    pSYMR	sym;		/* sym for the str/un */
    FAST pSYMR	symField;	/* sym used for fields and stEnd */
    FAST int4	iauxType;	/* iaux for type of field */
    int4	isymStart;
    int2	sclass, cb;		/* size of structure/union */
    AUXU	aaux;

    /* get sym for beginning, set st as passed */
    if (vlc == lcC) {
	sym = SymFAlloc(issNil, stBlock, scInfo,
		    vauxent->x_sym.x_misc.x_lnsz.x_size, 0L);
    } else if (vlc == lcFortran) {
	sym = SymFAlloc(issNil, stCommon, scInfo, adrNil, 0L);
    } /* if */

    isymStart = visym;
    if (*vsbEnt == '.') 
	sym->iss = issNil;
     else
	sym->iss = IssFSb(vsbEnt);

    /* generate aux to be referenced when refering to this struct */
    vmpIsymentIaux[vcsymCur] = IauxFAdd(AuxFBt(bt));
    aaux.isym = isymStart;
    IauxFAdd(&aaux);

    sclass = (bt == btStruct ? C_MOS : C_MOU);

    while ( ((NextSyment())->n_sclass == sclass)
	   OR (vsyment->n_sclass == C_FIELD) ) {
	symField = SymFAlloc(IssFSb(vsbEnt), stMember, scInfo,
		vsyment->n_value, IauxFSyment(vsyment));
	if (vsyment->n_sclass == C_FIELD) {
	    symField->sc = scBits;
	    aaux.width = vauxent->x_sym.x_misc.x_lnsz.x_size;
	    IauxFAdd(&aaux);
	} else {
	    symField->value *= 8; /* need offset in BITS */
	} /* if */
    } /* while */

    /* 
     * put out end of struct with a link back to the front
     *	and link original sym to the next symbol.
     */
    SymFIsym(isymStart)->index = visym + 2;
    symField = SymFAlloc(issNil, stEnd, scInfo, 0L, isymStart);
} /* DoStruct */


/* I A U X  F  S Y M E N T */

export int4 IauxFSyment(syment)
pSYMENTR	syment;
{
    FAST int	i;
    int		type, dt, bt, cDim;
    int4	iauxRet, iaux;
    AUXU	aaux;

    static short	mpCoffBt[] = {
	    btInt,	/* bt null */
	    btNil,	/* unknown */
	    btChar, btShort, btInt, btLong, btFloat,
	    btDouble, btStruct, btUnion, btEnum, btEnum,	/* member */
	    btUChar, btUShort, btUInt, btULong
	    };

    static short mpDtTq[] = { tqNil, tqPtr, tqProc, tqArray };

    if ((syment->n_type == 0)
       AND (syment->n_sclass == C_EXT)
       AND (syment->n_scnum == 1)) {
	/* its a 'stripped' procedure name */
	return(viauxProcPhony);
    } /* if */

    bt = mpCoffBt[BTYPE(syment->n_type)];
    iauxRet = IauxFAdd(AuxFBt(bt));

    if (FComplexBt(bt)) {
	if (vauxent != 0) {
	    iaux = IauxFIsyment(vauxent->x_sym.x_tagndx);
	    if (iaux == iauxNil)
		vauxent = 0;	/* loader or someone trashed the COFF info */
	} /* if */

	if (vauxent == 0) {
	    /* This is a weird case.  We have a pointer to
	     * a structure (enum, union,.. ) that was never
	     * defined OR was forward referenced.  We handle
	     * it by changing them to a pointer to CHAR.
	     */
	    if (vfWarnUndefined)
		printf("Warning: %s references an undefined type\n", vsbEnt);
	    iauxRet = IauxFAdd(AuxFBt(btChar));
	    return(iauxRet);
	} else {
	    IauxFAdd(AuxFIaux(iaux+1));
	} /* if */
    } /* if */

    /* Pick up type qualifier information */
    cDim = 0;
    for (type = syment->n_type >> 4; type != 0; type >>= 2) {
	dt = type & 03;
	switch (dt) {
	    case DT_PTR:
		if ((vlc == lcFortran) AND (vsym->st == stParam)) {
		    PatchTq(iauxRet, tqRef);
		} else {
		    PatchTq(iauxRet, mpDtTq[dt]);
		}
		break;
	    case DT_ARY:
		cDim++;
	    case DT_FCN:
		PatchTq(iauxRet, mpDtTq[dt]);
	} /* switch */
    } /* for */

    if (vlc == lcFortran) {
	/* we stack dimensions in opposite order from C */
	for (i = 0; i < cDim; ++i)
	    AddDim(vauxent->x_sym.x_fcnary.x_ary.x_dimen[i]);
    } else {
	/* we stack dimensions in opposite order */
	for (i = cDim-1; i >= 0; i--)
	    AddDim(vauxent->x_sym.x_fcnary.x_ary.x_dimen[i]);
    } /* if */
	
    return(iauxRet);
} /* IauxFSyment */


/* E N D   F I L E */

export void EndFile(adr)
ADRT	adr;
{
    register pSYMR	sym;

    if (visymProc != isymNil)
	EndProc(adr);

    sym = SymFAlloc(issNil, stEnd, scText, adr, visymFile);
    sym = SymFIsym(visymFile);
    sym->index = visym + 1;	/* forward link */

    if ((vifdMac > 0) AND (sym->value == adrNil)) {
	sym->value = vdotStart;
	vrgFd[vifd].adr = vdotStart;
    } /* if */

    visymFile = isymNil;
    visymEnd = isymNil;
} /* EndFile */


/* D O   F I L E */

export void DoFile (adr, sbName)
ADRT	adr;
SBT	sbName;
{
    register pFDR	fd;
    register pSYMR	sym;
    int	cb;

    if ((vifdMac > 0) AND (adr == adrNil))
	adr = vdot;

    if (visymFile != isymNil)
	EndFile(adr);

    if (vifdMac >= vifdMax) {
	vifdMax *= 2;
	vrgFd = (pFDR) realloc(vrgFd, vifdMax * cbFDR);
	if (vrgFd == 0)
	    Panic("Ran out of memory - file table expansion");
    } /* if */

    vifd = vifdMac++;
    fd = vrgFd + vifd;

    cb = strlen(sbName);
    fd->iss = fd->issShort = IssFSb(sbName);
    fd->adr = adr;
    fd->ipd = ipdNil;
    fd->isym = visymMac;
    fd->iline = vilineMac;
    fd->rgLn = 0;
    vlc = (sbName[cb-1] == 'f') ? lcFortran : lcC;
    fd->lc = vlc;

    sym = SymFAlloc(fd->iss, stFile, scText, adr, 0L);

    visymFile = visym;
    viauxFile = viaux;
    vdotEnd = adrNil;
    vdotStart = adr;
    vfDidText = false;
} /* DoFile */


/* F I X  F D */

export void FixFd()
{
    register pFDR	fd;
    register pPDR	pd;
    register int	ifd;
    register int	ipd;

    if (visymFile != isymNil)
	EndFile(vdot); /* maybe adrText + cbText? */

    /* synchronize the fd's and pd's */
    fd = vrgFd + 1;
    pd = vrgPd;
    for (ipd = ifd = 0; ifd < vifdMac; ifd++, fd++) {
	if (fd->adr == adrNil)
	    continue; /* nothing there */
	while ((ipd < vipdMac) && (fd->adr > pd->adr)) {
	    ipd++;
	    pd++;
	} /* while */
	fd->ipd = ipd;
	if (SymFIsym(pd->isym)->st == stNil)
	    pd->iline = 0;
	fd->iline = pd->iline;	/* is this always correct? */
    } /* for */
} /* FixFd */


/* E N D   P R O C */

export void EndProc(adr)
ADRT	adr;
{
    int4	isymBlock;
    pSYMR	sym;
    pSYMR	symBlock;
    AUXU	aaux;

    if (vfBlockAdded) {	/* we added a block */
	isymBlock = IsymFPop();
	SymFAlloc(issNil, stEnd, scText, adr, isymBlock);
	symBlock = SymFIsym(isymBlock);
	symBlock->index = visym + 1;
	vfBlockAdded = false;
    } /* if */

    sym = SymFAlloc(issNil, stEnd, scText, adr, visymProc);
    visymEnd = visym;
    aaux.isym = visymMac;
    ChangeAux(SymFIsym (visymProc)->index, &aaux);

    if (vcsymProc != 0)
	DoProcLines();
    vcsymProc = 0;

    visymProc = isymNil;
    vfAlsoEqual = ALSO_EQUAL;
} /* EndProc */


/* D O   L I N E */

export void DoLine(iln, adr)
int	iln;
ADRT	adr;
{
    if (vilineMac >= vilineMax)
	Panic("Ran out of line entries"); /* "can't happen" ..... */
    viline = vilineMac++;

    vrgLine[viline].iln = iln;
    vrgLine[viline].dadr = adr - vrgPd[vipd].adr;
    vdot = adr;
} /* DoLine */


/* D O   P R O C   L I N E S */

export void DoProcLines()
{
    struct lineno	alineno;
    ADRT	adr;
    int		i, iline;

    if (ldlinit(vlfdLines, vcsymProc) == FAILURE)
	return;

    iline = 1;
    i = 0;
    while (ldlitem(vlfdLines, iline, &alineno) != FAILURE) {
	adr = alineno.l_addr.l_paddr;
	if ((i != 0) AND (vadrProc == adr))
	    vilineMac--;	/* throw away the previous line */

	if ( (vadrProc < adr) OR (vfAlsoEqual AND (vadrProc == adr)) ) {
	    DoLine(alineno.l_lnno + vilnProc, adr);
	    i++;
	} /* if */

	iline = alineno.l_lnno + 1;
    } /* while */
} /* DoProcLines */


/* D O   P R O C  */

export void DoProc(adr)
ADRT	adr;
{
    int4	iaux;
    pSYMR	symProc;
    pSYMR	sym;
    AUXU	aaux;

    /* this procedure is called when we hit ".bf" fcn symbol, note
     * that we assume visym points to the symbol containing the name
     * and type of the procedure we are just starting.
     */

    visymProc = visym;
    symProc = SymFIsym(visymProc);

    aaux.isym = isymNil;
    iaux = symProc->index;
    symProc->index = IauxFAdd(&aaux); 	/* leave room for isymLast */
    IauxFCopy(iaux); /* and then copy its goodies after it */
    symProc->st = stProc;

    ProcInsert(visymProc, symProc->value, vilineMac);
    vcsymProc = vcsymCur - 2;
    vadrProc = adr;
    vilnProc = vauxent->x_sym.x_misc.x_lnsz.x_lnno - 1;
} /* DoProc */


/* P R O C   I N S E R T */

export void ProcInsert(isym, adr, iline)
FAST int4	isym;
FAST ADRT	adr;
FAST int2	iline;
{
    FAST pPDR	pd;
    FAST int	ipd;
    int		ipdLast, ipdInsert;
    pSYMR	sym;

    /* first fix the last end's address */
    if (visymEnd > 0) {
	sym = SymFIsym (visymEnd);
	sym->value = adr;
	sym = SymFIsym(visymEnd-1);	/* and the guy before him, too! */
	if (sym->st == stEnd)
	    sym->value = adr;
	visymEnd = 0;
    } /* if */

    ipdLast = vipd;
    if (vipdMac >= vipdMax) {
	vipdMax *= 2;
	vrgPd = (pPDR) realloc(vrgPd, vipdMax * cbPDR);
	if (vrgPd == 0)
	    Panic("Ran out of memory - procedure table expansion");
    } /* if */

    vipd = vipdMac++;
    ipd = vipd;

    if ((vipd >= 1) AND (adr < vrgPd[ipdLast].adr)) {
	/* We must insert, not append.
	 * 	First, walk backward, find the place, move the rest up and
	 *	set up the pointer.
	 */
	pd = vrgPd;
	for (ipd = 0; pd->adr < adr; ipd++, pd++)
	    ;

/* 	ipdInsert = (ipd == 0) ? 0 : (ipd - 1); */
 	ipdInsert = ipd;

	if ((ipd >= 0)
	    AND (SymFIsym(pd->isym)->iss == SymFIsym(isym)->iss)) {
	    /* This is a duplicate of the previous entry */
	    vipdMac--;
	    vipd = ipdLast;
	    return;
	} /* if */

	for (ipd = vipdMac-1; ipd > ipdInsert; ipd--) {
	    vrgPd[ipd] = vrgPd[ipd-1];
	} /* for */

	ipd = ipdInsert;
    } /* if */

    pd = vrgPd + ipd;
    pd->isym = isym;
    pd->adr = adr;
    pd->iline = iline;
    pd->dadrRegBase = adrNil;

    if (vrgFd[vifd].adr == adrNil) {
	/* use the addr of this routine */
	SymFIsym(visymFile)->value = adr;;
	vrgFd[vifd].adr = adr;
    } /* if */
} /* ProcInsert */
0707070001000313211004440000000000010000011613140454650114500002000000002550transV/Makefile # $Header: Makefile,v 1.7 86/07/18 06:03:46 peter Exp $
# (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved
#
#  This Makefile makes two versions of `trans':
#
#	cdbtrans  - Runs native on a System V machine
#	xtrans - Runs on 4.2 and works with System V exectuables.
#

HFILES	= trans.h
CFILES	= aux.c init.c main.c map.c misc.c print.c sym.c type.c
ALLFILES =	Makefile $(HFILES) $(CFILES)

OFILES	= aux.o init.o main.o map.o misc.o print.o sym.o type.o ldlib.o
BFILES	= aux.b init.b main.b map.b misc.b print.b sym.b type.b ldlib.b

CC	= cc
CFLAGS	= -g
LFLAGS	= -g

XCC	= m68cc
XLIBLD	= /usr/local/src/cmd/sgs/m68k/lib/libld.a

.SUFFIXES: .b

.c.b:
	-mv $*.o $*.x
	$(XCC) $(CFLAGS) -c -I/usr/5include $*.c
	mv $*.o $*.b
	-mv $*.x $*.o

all:	sym.h config.h ext.h cdbtrans

cdbtrans:	$(OFILES) Makefile
	$(CC) $(LFLAGS) -o $@ $(OFILES) -lld

xtrans: $(BFILES) Makefile
	$(XCC) $(LFLAGS) -o $@ $(BFILES) $(XLIBLD)

ext.h:	$(CFILES)
	grep "^export" $(CFILES) | sed -f ext.sed > ext.h

config.h:	../cdb/config.h
	rm -f config.h SYS.h
	ln ../cdb/config.h .
	ln ../cdb/SYS.h .

sym.h:	../cdb/sym.h
	rm -f sym.h
	ln ../cdb/sym.h .

.PRECIOUS:	save

save:	$(ALLFILES)
	backup transV $?
	rm -f save
	touch save
	chmod 0 save

tags:	$(CFILES)
	ctags $(CFILES) > /dev/null

clean:
	@rm -f cdbtrans xtrans config.h SYS.h sym.h ext.h $(OFILES) $(BFILES)

$(OFILES):	trans.h sym.h
0707070001000313221004440000000000010000011613320454650114500001700000000367transV/READ_ME $Header: READ_ME,v 1.2 85/09/16 08:58:15 peter Exp $

(C) Copyright 1985 Third Eye Software, Inc. - All Rigths Reserved

This directory contains the source code for the symbol table
translator from UniDot format to the Third Eye Software format.

0707070001000313231004440000000000010000011613410454650114500001700000000326transV/ext.sed s/[	]/ /g
s/.*://
t clear2
: clear2

s/^.*exportdefine/#define/
t end

s/^export/extern/
s/;.*/;/
s/ *=.*/;/
t clear1
: clear1

s/(/(/
t proc

s@\[[^\[]*\]@\[\]@g
b end

: proc
s/(\(.*\))/(\/\* \1 \*\/);/

: end
b
0707070001000313241004440000000000010000011613500454650114500001700000002627transV/trans.h /* $Header: trans.h,v 1.3 86/07/18 06:03:49 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include <sys/types.h>
#include <fcntl.h> 
#include <a.out.h>
#include <stdio.h>
#include <ldfcn.h>

typedef union auxent AUXENTR, *pAUXENTR;
#define cbAUXENTR sizeof(AUXENTR)
#define auxentNil ((pAUXENTR)0)

typedef struct syment SYMENTR, *pSYMENTR;
#define cbSYMENTR sizeof(SYMENTR)
#define symentNil ((pSYMENTR)0)

#define int1	char
#define uint1	unsigned char
#define int2	short
#define uint2	unsigned short
#define int4	long
#define uint4	unsigned long

/* this include must come AFTER the 'int' defines */
#include "config.h"

/* random stuff */
#define false 0
#define true  1
#define DONT_CARE	-1

#define void int
#define bits unsigned	/* makes bit fields definitions shorter */
#define FAST register

#define export		/* something that belongs in ext.h  */
#define exportdefine
#define local static	/* something not to be known outside of this module */

#define NOT(x)	(!(x))
#define AND &&
#define OR  ||

#define chNull '\0'

#define seekBegin	0	/* these are used with lseek() and fseek() */
#define seekRelative	1
#define seekEnd		2

typedef char *SBT;
#define nil ((char *)0)	/* good for where a general nil pointer is needed */
#define sbNil ((SBT)0)
#define FLAGT int4
typedef uint4	ADRT, *pADRT;
#define	adrNil ((ADRT) 0xffffffff)

#include "sym.h"

#undef IssFSb

#include "ext.h"
0707070001000313241004440000000000010000011613500454650114500001300000000000TRAILER!!! g.h:	../cdb/config.h
	rm -f config.h SYS.h
	ln ../cdb/config.h .
	ln ../cdb/SYS.h .

sym.h:	../cdb/sym.h
	rm -f sym.h
	ln ../cdb/sym.h .

.PRECIOUS:	save

save:	$(ALLFILES)
	backup transV $?
	rm -f save
	touch save
	chmod 0 save

tags:	$(CFILES)
	ctags $(CFILES) > /dev/null

clean:
	@rm -f cdbtrans xtrans config.h SYS.h sym.h ext.h $(OFILES) $(BFILES)

$(OFILES):	trans.h sym.h
0707070001000313221004440000000000010000011613320454650114500001700000000367transV/READ_ME $Header: READ_ME,v 1.2 85/09/16 08:58:15 peter Exp $

(C) Copyright 1985 Third Eye Software, Inc. - All Rigths Reserved

This directory contains the source code for the symbol table
translator from UniDot format to the Third Eye Software format.

0707070001000313231004440000000000010000011613410454650114500001700000000326transV/ext.sed s/[	]/ /g
s/.*://
t clear2
: clear2

s/^.*exportdefine/#define/
t end

s/^export/extern/
s/;.*/;/
s/ *=.*/;/
t clear1
: clear1

s/(/(/
t proc

s@\[[^\[]*\]@\[\]@g
b end

: proc
s/(\(.*\))/(\/\* \1 \*\/);/

: end
b
0707070001000313241004440000000000010000011613500454650114500001700000002627transV/trans.h /* $Header: trans.h,v 1.3 86/07/18 06:03:49 peter Exp $ */
/* (C) Copyright 1985 Third Eye Software, Inc. - All Rights Reserved */

#include <sys/types.h>
#include <fcntl.h> 
#include <a.out.h>
#include <stdio.h>
#include <ldfcn.h>

typedef union auxent AUXENTR, *pAUXENTR;
#define cbAUXENTR sizeof(AUXENTR)
#define auxentNil ((pAUXENTR)0)

typedef struct syment SYMENTR, *pSYMENTR;
#define cbSYMENTR sizeof(SYMENTR)
#define symentNil ((pSYMENTR)0)

#define int1	char
#define uint1	unsigned char
#define int2	short
#define uint2	unsigned short
#define int4	long
#define uint4	unsigned long

/* this include must come AFTER the 'int' defines */
#include "config.h"

/* random stuff */
#define false 0
#define true  1
#define DONT_CARE	-1

#define void int
#define bits unsigned	/* makes bit fields definitions shorter */
#define FAST register

#define export		/* something that belongs in ext.h  */
#define exportdefine
#define local static	/* something not to be known outside of this module */

#define NOT(x)	(!(x))
#define AND &&
#define OR  ||

#define chNull '\0'

#define seekBegin	0	/* these are used with lseek() and fseek() */
#define seekRelative	1
#define seekEnd		2

typedef char *SBT;
#define nil ((char *)0)	/* good for where a general nil pointer is needed */
#define sbNil ((SBT)0)
#define FLAGT int4
typedef uint4	ADRT, *pADRT;
#define	adrNil ((ADRT) 0xffff