DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦a4ec116db⟧ TextFile

    Length: 11004 (0x2afc)
    Types: TextFile
    Names: »stack.c,v«

Derivation

└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
    └─⟦34cc4e2f7⟧ »./UNRELEASED/xgdb3.2.tar.Z« 
        └─⟦80fac5d7c⟧ 
            └─⟦this⟧ »./RCS/stack.c,v« 

TextFile

head     1.1;
access   ;
symbols  ;
locks    hubbard:1.1; strict;
comment  @ * @;


1.1
date     89.07.05.15.36.37;  author hubbard;  state Exp;
branches ;
next     ;


desc
@Initial checkin, Beta version 0.1.
@



1.1
log
@Initial revision
@
text
@\f


#ifndef lint
static char rcsid[] = "$Header$";
#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$
 * 
 */

#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;
}
@