|
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: 10844 (0x2a5c) Types: TextFile Names: »stack.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦34cc4e2f7⟧ »./UNRELEASED/xgdb3.2.tar.Z« └─⟦80fac5d7c⟧ └─⟦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) && strcomp(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("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("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 && !strcomp(tmp->function, func) && !strcomp(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("Searching for frame '%s'", fname); #endif DEBUG while((se = (stackEntry *)popQueueEntry(&stackInfo.SQ, LIFO))) { #ifdef DEBUG debug("popping off stack frame '%s'", se->function); #endif DEBUG if (!strcomp(se->function, fname)) { addQueueEntry(&stackInfo.SQ, se); Leave_void; } else { freeStackEntry(se); } } puke("Can't find queue entry for function '%s'!", fname); } else puke("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("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("Got 6 regs for non-info frame??"); Leave_void; } break; default: puke("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("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; }