|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 10880 (0x2a80)
Types: TextFile
Names: »stack.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
└─⟦e10a7c8ba⟧ »./UNRELEASED/xgdb.tar.Z«
└─⟦ae30648b5⟧
└─⟦this⟧ »./stack.c«
\f
#ifndef lint
static char rcsid[] = "$Header: stack.c,v 1.1 89/07/05 15:36:37 hubbard Exp $";
#endif
/*
*
* Copyright 1988, 1989
* PCS Computer Systeme, GmbH
* Munich, West Germany
*
* All rights reserved.
*
* This is unsupported software and is subject to change without notice.
* PCS makes no representations about the suitability of this software
* for any purpose. It is supplied "as is" without express or implied
* warranty.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of PCS Computer Systeme not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission.
*
*/
/*
* Author: Jordan K. Hubbard
* For: PCS Computer Systems, GmbH.
* When: February 23rd, 1989.
*
* $Log: stack.c,v $
* Revision 1.1 89/07/05 15:36:37 hubbard
* Initial revision
*
*
*/
#include "xgdb.h"
static View *StackView;
/*
* Everything needed to handle the stack display pane.
*/
#define MAXDEPTH 100
static struct {
String *list; /* stack frame description list (for widget) */
int nitems; /* Number of frames in list */
Queue SQ; /* Queue of functions waiting to return */
} stackInfo;
QUEUE_ENTRY(_stackEntry)
int frame; /* Stack frame # */
String function; /* Function name */
String parms; /* Parameters to this call */
IS_TYPE stackEntry;
/*
* Mapped?
*/
Boolean stackMapped()
{
Entry("stackMapped");
if (StackView)
Leave(StackView->mapped);
Leave(FALSE);
}
/*
* Update the stack view.
*/
void stackUpdateView()
{
Entry("stackUpdateView");
if (stackMapped() &&
queueEmpty(&stackInfo.SQ) &&
strcmp(dbg_state.S_function, INITIAL)) {
debuggerQueryStack();
}
Leave_void;
}
/*
* Select a stack frame interactively.
*/
static void stackSelectFrame(w, client_data, data)
Widget w;
caddr_t client_data, data;
{
XtScrollListReturnStruct *fra = (XtScrollListReturnStruct *)data;
register stackEntry *se;
int item = fra->list_index;
Entry("stackSelectFrame");
if (queueActive(&stackInfo.SQ)) {
se = FIRST(&stackInfo.SQ, stackEntry);
while (se && item) {
se = NEXT(se);
item--;
}
if (se)
debuggerSetFrame(NULL, 0, se->frame);
else
puke("%p: Couldn't find stack entry for item %d",
fra->list_index);
}
Leave_void;
}
/*
* Free up a stack entry.
*/
static void freeStackEntry(se)
register stackEntry *se;
{
Entry("freeStackEntry");
if (NULLP(se))
puke("%p: Passed NULL pointer");
else {
XtFree(se->function);
XtFree(se->parms);
XtFree(se);
}
Leave_void;
}
/*
* Hilite a stack entry.
*/
static void hiliteStackFrame(se)
register stackEntry *se;
{
Entry("hiliteStackFrame");
XtScrollListHighlight(StackView->output, se->frame);
Leave_void;
}
/*
* Create a list based on the current stack queue and
* display it.
*/
static void createStackList()
{
register stackEntry *se;
char buf[255];
int fr = 0;
Entry("createStackList");
if (!stackInfo.list) {
stackInfo.list = (String *)XtMalloc(sizeof(String) * MAXDEPTH);
bzero(stackInfo.list, sizeof(String) * MAXDEPTH);
}
for (se = FIRST(&stackInfo.SQ, stackEntry); se; se = NEXT(se)) {
sprintf(buf, "#%d: %s\t\t%s", fr, se->function, se->parms);
STASH(stackInfo.list[fr], expand_string(buf, '\0'));
se->frame = fr;
fr++;
}
stackInfo.nitems = fr;
if (stackMapped() && stackInfo.nitems) {
XtScrollListChange(StackView->output, stackInfo.list,
stackInfo.nitems, 0, TRUE);
hiliteStackFrame(FIRST(&stackInfo.SQ, stackEntry));
}
Leave_void;
}
/*
* See if a stack entry is already on the queue.
*/
static stackEntry *findStackEntry(frame, func, parms)
register int frame;
register String func, parms;
{
register stackEntry *tmp;
Entry("findStackEntry");
tmp = FIRST(&stackInfo.SQ, stackEntry);
while (tmp) {
if (tmp->frame == frame &&
!strcmp(tmp->function, func) &&
!strcmp(tmp->parms, parms)) {
Leave(tmp);
}
else
tmp = NEXT(tmp);
}
Leave(NULL);
}
/*
* Return from a stack frame in the list.
*/
static void stackReturnFrame(fname)
String fname;
{
register stackEntry *se;
Entry("stackReturnFrame");
if (queueActive(&stackInfo.SQ)) {
se = FIRST(&stackInfo.SQ, stackEntry);
/*
* Pop off frames until we reach the one being returned
* and push it back.
*/
#ifdef DEBUG
debug("%p: Searching for frame '%s'", fname);
#endif DEBUG
while((se = (stackEntry *)popQueueEntry(&stackInfo.SQ, LIFO))) {
#ifdef DEBUG
debug("%p: popping off stack frame '%s'", se->function);
#endif DEBUG
if (!strcmp(se->function, fname)) {
addQueueEntry(&stackInfo.SQ, se);
Leave_void;
}
else {
freeStackEntry(se);
}
}
puke("%p: Can't find queue entry for function '%s'!",
fname);
}
else
puke("%p: Queue is empty!");
Leave_void;
}
/*
* Deal with stack frame change/query info from the debugger. This may
* involve adding frames, deleting them, or just ignoring them (already
* known). There are four types of frame information that we might get:
*
* # Registers Contents
* ---------------------
* 3 address, function, parameters.
* 4 function, parameters, file name, line #.
* 5 address, function, parameters, file name, line #.
* 6 frame #, address, function, parameters, file name, line #.
* 4 frame #, address, function, parameters.
*
* If we get 3 or 4, it's a function being entered. If it's 5, it's
* a function returning. If it's 6, or any of the others with a frame number,
* it's an information msg (stack frame moving, stack query, etc).
*
*/
void stackHandleFrame(T_PROCS_ARGS)
T_PROCS_DECL;
{
static String parameters = (String)NULL;
register stackEntry *se;
int nregs;
int func = 0, addr = 0, fname = 0, line = 0, frame = 0, parms = 0;
Boolean is_info, was_return = FALSE;
Entry("stackHandleFrame");
nregs = check_registers(regs, RE_NREGS);
is_info = (s[regs->start[0]] == '#') ? TRUE : FALSE;
#ifdef DEBUG
debug("%p: nregs = %d, is_info = %d", nregs, is_info);
#endif DEBUG
if (is_info)
frame = 1;
switch(nregs) {
case 3:
if (!is_info)
addr = 1;
func = 2;
parms = 3;
break;
case 4:
if (is_info)
addr = 2, func = 3, parms = 4;
else
func = 1, parms = 2, fname = 3, line = 4;
break;
case 5:
func = 2, parms = 3, fname = 4, line = 5;
if (!is_info) {
addr = 1;
was_return = TRUE;
}
break;
case 6:
if (is_info)
addr = 2, func = 3, parms = 4, fname = 5, line = 6;
else {
puke("%p: Got 6 regs for non-info frame??");
Leave_void;
}
break;
default:
puke("%p: Can't handle %d registers", nregs);
break;
}
if (addr)
STASHN(dbg_state.S_address, s + regs->start[addr],
regs->end[addr] - regs->start[addr]);
if (fname)
STASHN(dbg_state.S_file, s + regs->start[fname],
regs->end[fname] - regs->start[fname]);
if (frame) /* frame purposely starts with # char, skip over it */
STASHN(dbg_state.S_frame, s + regs->start[frame] + 1,
regs->end[frame] - regs->start[frame] - 1);
if (func)
STASHN(dbg_state.S_function, s + regs->start[func],
regs->end[func] - regs->start[func]);
if (line)
STASHN(dbg_state.S_line, s + regs->start[line],
regs->end[line] - regs->start[line]);
if (parms)
STASHN(parameters, s + regs->start[parms],
regs->end[parms] - regs->start[parms]);
if (!was_return) {
if (is_info && (se = findStackEntry(atoi(dbg_state.S_frame),
dbg_state.S_function,
parameters))) {
hiliteStackFrame(se);
}
else {
NEW(se, stackEntry);
STASHF(se->function, dbg_state.S_function);
STASHF(se->parms, parameters);
se->frame = atoi(dbg_state.S_frame);
addQueueEntry(&stackInfo.SQ, se);
#ifdef DEBUG
debug("%p: Added queue entry '%s'", se->function);
#endif DEBUG
createStackList();
}
}
else {
stackReturnFrame(dbg_state.S_function);
createStackList();
}
Leave_void;
}
/*
* The following are invoked directly by the translation manager.
*/
void stack_up(w, ev, av, ac)
Widget w;
XEvent *ev;
String *av;
Cardinal *ac;
{
Entry("stack_up");
debuggerUp(NULL, NULL, NULL);
Leave_void;
}
void stack_down(w, ev, av, ac)
Widget w;
XEvent *ev;
String *av;
Cardinal *ac;
{
Entry("stack_down");
debuggerDown(NULL, NULL, NULL);
Leave_void;
}
/*
* Create the stack view pane.
*/
void stackCreateView(w, client_data, data)
Widget w;
caddr_t client_data, data;
{
static FormField buttons[] = {
{ { "close", viewCloseShell }, 2, FALSE, 0, 0, 0, 0 },
{ { NULL, NULL }, 0, 0, 0, 0, 0, 0 },
};
static XtActionsRec stk_actions[] = {
{ "Up", stack_up },
{ "Down", stack_down },
};
static char stk_trans[] = "<Key>U: Up()\n <Key>D: Down()\n";
static XtTranslations trans = NULL;
FieldAttributes fla;
Field *flist;
String name = ((w) ? XtWidgetToName(w) : (String)data);
Entry("stackCreateView");
if (!StackView) {
convertFormToField(buttons, &flist);
if (!trans) {
XtAddActions(stk_actions, XtNumber(stk_actions));
trans = XtParseTranslationTable(stk_trans);
}
ii = 0;
XtSetArg(aa[ii], XtNforceColumns, TRUE); ii++;
XtSetArg(aa[ii], XtNdefaultColumns, 1); ii++;
XtSetArg(aa[ii], XtNrepositionOnHilite, TRUE); ii++;
XtSetArg(aa[ii], XtNscrollVertical, TRUE); ii++;
if (stackInfo.list && stackInfo.nitems) {
XtSetArg(aa[ii], XtNlist, stackInfo.list); ii++;
XtSetArg(aa[ii], XtNnumberStrings, stackInfo.nitems); ii++;
}
StackView = viewCreateShell(name, flist,
scrollListWidgetClass,
aa, ii);
XtAddCallback(StackView->output, XtNcallback, stackSelectFrame,
NULL);
XtAugmentTranslations(StackView->output, trans);
}
XtPopup(StackView->parent, XtGrabNone);
XRaiseWindow(XtDisplay(StackView->parent),
XtWindow(StackView->parent));
StackView->mapped = TRUE;
/* Make the field that invoked us go insensitive */
fla.sensitive = FALSE;
changeField(nameToField(name, client_data), FldSensitive, &fla);
stackUpdateView();
Leave_void;
}