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 b

⟦b77d8c705⟧ TextFile

    Length: 14435 (0x3863)
    Types: TextFile
    Names: »break.c«

Derivation

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

TextFile

\f


#ifndef lint
static char rcsid[] = "$Header: break.c,v 1.1 89/07/05 15:35:54 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:	break.c,v $
 * Revision 1.1  89/07/05  15:35:54  hubbard
 * Initial revision
 * 
 * 
 */

#include "xgdb.h"

static View *BreakpointView;

/*
 * Everything needed to handle the breakpoint display pane.
 */

QUEUE_ENTRY(_break)
     int num;			/* breakpoint number */
     String addr;		/* breakpoint address */
     String line;		/* breakpoint line (if any) */
     String file;		/* breakpoint file (if any) */
     Widget cmd;		/* Associated command widget */
     Boolean enabled;		/* enabled? */
     Boolean selected;		/* targeted for change? */
IS_TYPE breakEntry;

static struct {
     int current;		/* "current" breakpoint */
     Widget select;		/* selected breakpoints */
     Widget box;		/* outer frame for breakpoint entries */
     Queue BQ;
} breakInfo;

/*
 * Mapped?
 */
Boolean breakMapped()
{
     Entry("breakMapped");

     if (BreakpointView)
	  Leave(BreakpointView->mapped);
     Leave(FALSE);
}

/*
 * Display the list of selected breakpoints.
 */
static void breakDisplaySelected()
{
     breakEntry *bp;
     int len, i;
     char select_line[500], tmp[10];
     Boolean first;

     Entry("breakDisplaySelected");

     /* Build the select list from scratch */     
     select_line[0] = '\0';
     first = TRUE;
     /* Walk the list backwards to list bkpts in some semblance of order */
     for (bp = LAST(&breakInfo.BQ, breakEntry); bp; bp = PREV(bp)) {
	  if (bp->selected) {
	       if (first) {
		    sprintf(tmp, "%d", bp->num);
		    strcpy(select_line, tmp);
		    first = FALSE;
	       }
	       else {
		    sprintf(tmp, ", %d", bp->num);
		    strcat(select_line, tmp);
	       }
	  }
     }
     if (!strlen(select_line))
	  strcpy(select_line, "No breakpoints selected");

     len = strlen(select_line);
     if (len < 30) {
	  for (i = len; i < 30; i++)
	       select_line[i] = ' ';
	  select_line[i] = '\0';
     }

     i = 0;
     XtSetArg(args[i], XtNlabel, select_line);	i++;
     XtSetValues(breakInfo.select, args, i);
     Leave_void;
}

/*
 * Toggle the selection state of a breakpoint interactively.
 */
static void breakSelectEntry(w, client_data, data)
Widget w;
caddr_t client_data;
caddr_t data;
{
     breakEntry *bp = (breakEntry *)client_data;

     Entry("breakSelectEntry");

     /* toggle */
     bp->selected = !bp->selected;
     breakDisplaySelected();
     Leave_void;
}

/*
 * Clear the list of selected breakpoints.
 */
void breakClearSelected()
{
     breakEntry *bp;

     Entry("breakClearSelected");

     for (bp = FIRST(&breakInfo.BQ, breakEntry); bp; bp = NEXT(bp))
	  bp->selected = FALSE;
     breakDisplaySelected();
     Leave_void;
}

static XtCallbackRec call[] = {
     { breakSelectEntry, NULL },
     { NULL, NULL },
};

/* Given a breakpoint number, find the associated queue entry */
static breakEntry *bkpt_to_entry(bkpt)
register int bkpt;
{
     breakEntry *ptr;

     Entry("bkpt_to_entry");

     if (queueEmpty(&breakInfo.BQ))
	  Leave(NULL);
     for (ptr = FIRST(&breakInfo.BQ, breakEntry); ptr; ptr = NEXT(ptr))
	  if (ptr->num == bkpt)
	       Leave(ptr);
     Leave(NULL);
}

/* Given a queue entry, construct a printable version of it */
static String bkptEntry_to_name(bpe)
breakEntry *bpe;
{
     char bkpt_line[256], *bl;

     Entry("bkptEntry_to_name");

     sprintf(bkpt_line,
	     " #%d\t\taddr %s\t\tfile: %s\t\t\tline %s",
	     bpe->num, bpe->addr, bpe->file, bpe->line);
     bl = (String)expand_string(bkpt_line, ' ');
     Leave(bl);
}

/*
 * update the breakpoint view.
 */
void breakUpdateView()
{
     static breakEntry *high = NULL;
     static Boolean highState;
     breakEntry *ent;

     Entry("breakUpdateView");

     if (breakMapped()) {
	  if (breakInfo.current != atoi(dbg_state.S_breakpoint)) {
	       breakInfo.current = atoi(dbg_state.S_breakpoint);
	       ent = bkpt_to_entry(breakInfo.current);
	       if (ent) {
		    if (high) {
			 /* Reset old entry first */
			 high->selected = highState;
			 
			 i = 0;
			 XtSetArg(args[i], XtNforeground,
				  app_resources.colors.foreground);	i++;
			 XtSetArg(args[i], XtNbackground,
				  app_resources.colors.background);	i++;
			 XtSetValues(high->cmd, args, i);
		    }
		    high = ent;
		    highState = high->selected;
		    high->selected = TRUE;
		    
		    i = 0;
		    XtSetArg(args[i], XtNforeground,
			     app_resources.colors.background);		i++;
		    XtSetArg(args[i], XtNbackground,
			     app_resources.colors.foreground);		i++;
		    XtSetValues(high->cmd, args, i);

		    breakDisplaySelected();
	       }
	       else
		    puke("Unknown breakpoint '%s'", dbg_state.S_breakpoint);
	  }
     }
     Leave_void;
}

/*
 * Add a breakpoint to the view.
 * The breakpoint number must always be in regs[1].
 * The other register contents vary (see below).
 */

void breakAddBreakpoint(T_PROCS_ARGS)
T_PROCS_DECL;
{
     char *bp_name;
     int num_args, bkpt_num;
     breakEntry *bp;

     Entry("breakAddBreakpoint");

     /*
      * Woo! Here it gets hairy. We can be called in at least 4 different
      * ways:
      *
      * 1. With 2 registers, meaning we've got a breakpoint for which
      *    there is no file/line information: Reg #2 contains the address.
      * 2. With 3 registers, meaning we were called from an update all
      *    scan for a breakpoint w/o file/line info: Reg #2 contains the
      *    enable state "y or n", #3 the address.
      * 3. With 4 registers, meaning we've got a breakpoint with
      *    file/line info: Reg #2 is address, #3 is file, #4 is line number.
      * 4. With 5 registers, meaning we were called from an update all
      *    scan for a break point with file/line info: Reg #2 is enable state,
      *    #3 is address, #4 is file and #5 is line.
      */

     /* So, just how many args were we called with? */
     num_args = check_registers(regs, 5);

     /* #1 is always breakpoint number */
     bkpt_num = atoi(s + regs->start[1]);

     /* Do we already know about this breakpoint? */
     if (bkpt_to_entry(bkpt_num)) {
	  Leave_void;
     }

     /* Allocate a new breakpoint entry */
     NEW(bp, breakEntry);
     bp->num = bkpt_num;

     /* #2 might be address or enable state */
     if (num_args % 2) { /* enable state */
	  if (s[regs->start[2]] == 'n') /* disabled */
	       bp->enabled = FALSE;
	  else if (s[regs->start[2]] == 'y')
	       bp->enabled = TRUE;
	  else
	       puke("Bad enable state: %s", substr(s, regs->start[2],
						   regs->end[2]));
	  STASHN(bp->addr, s + regs->start[3], regs->end[3] - regs->start[3]);
     }
     else { /* It's the address. Enable state not given (assume TRUE) */
	  bp->enabled = TRUE;
	  STASHN(bp->addr, s + regs->start[2], regs->end[2] - regs->start[2]);
     }
     if (num_args > 3) { /* We have file/line info too, either at 3/4 or 4/5 */
	  int off = (num_args % 2) ? 1 : 0;
	  STASHN(bp->file, s + regs->start[3 + off],
	       regs->end[3 + off] - regs->start[3 + off]);
	  STASHN(bp->line, s + regs->start[4 + off],
	       regs->end[4 + off] - regs->start[4 + off]);
     }
     else {
	  STASH(bp->file, "(unknown)");
	  STASH(bp->line, "xxxx");
     }
     /* Add the bkpt to the queue */
     addQueueEntry(&breakInfo.BQ, bp);

     if (BreakpointView) {
	  char name[20];

	  bp_name = bkptEntry_to_name(bp);
	  sprintf(name, "Bkpt #%d", bp->num);

	  i = 0;
	  call[0].closure = (caddr_t)bp;
	  XtSetArg(args[i], XtNborderWidth, 0);		i++;
	  XtSetArg(args[i], XtNcallback, call);		i++;
	  XtSetArg(args[i], XtNlabel, bp_name);		i++;
	  if (bp->enabled == FALSE) {
	       XtSetArg(args[i], XtNsensitive, FALSE);	i++;
	  }
	  bp->cmd = XtCreateManagedWidget(name, commandWidgetClass,
					  breakInfo.box, args, i);
     }
     Leave_void;
}

/*
 * Remove multiple breakpoints from the view.
 */
void breakDeleteBreakpoints(T_PROCS_ARGS)
T_PROCS_DECL;
{
     Entry("breakDeleteBreakpoints");

     printf("break delete breakpoints called\n");
     Leave_void;
}

/*
 * remove a breakpoint from the view.
 */
void breakDeleteBreakpoint(T_PROC_ARGS)
T_PROC_DECL;
{
     breakEntry *bp;
     static char *fake_list[] = {
	  "No breakpoints",
	  NULL,
     };

     Entry("breakDeleteBreakpoint");

     bp = bkpt_to_entry(atoi(s));
     if (NULLP(bp)) {
	  puke("Invalid breakpoint specified, '%s'.", substr(s, 0, len));
	  Leave_void;
     }
     removeQueueEntry(&breakInfo.BQ, bp);
     if (BreakpointView) {
	  XtDestroyWidget(bp->cmd);
	  breakDisplaySelected();
     }
     Leave_void;
}

/*
 * Enable a breakpoint.
 */
void breakEnableBreakpoint(T_PROC_ARGS)
T_PROC_DECL;
{
     breakEntry *bp;

     Entry("breakEnableBreakpoint");

     bp = bkpt_to_entry(atoi(s));
     if (NULLP(bp)) {
	  puke("Invalid breakpoint specified, '%s'.", substr(s, 0, len));
	  Leave_void;
     }
     bp->enabled = TRUE;
     if (BreakpointView)
	  XtSetSensitive(bp->cmd, TRUE);
     Leave_void;
}

/*
 * Disable a breakpoint.
 */
void breakDisableBreakpoint(T_PROC_ARGS)
T_PROC_DECL;
{
     breakEntry *bp;

     Entry("breakDisableBreakpoint");

     bp = bkpt_to_entry(atoi(s));
     if (NULLP(bp)) {
	  puke("Invalid breakpoint specified, '%s'.", substr(s, 0, len));
	  Leave_void;
     }
     bp->enabled = FALSE;
     if (BreakpointView)
	  XtSetSensitive(bp->cmd, FALSE);
     Leave_void;
}

/*
 * The following functions are called interactively from the break
 * view, not automatically by the debugger parser.
 */
static char msg1[] = "No breakpoint is selected in the view";
/*
 * Interactively delete a breakpoint.
 */
void breakpointDelete()
{
     breakEntry *bp;
     Boolean acted = FALSE;

     Entry("breakpointDelete");

     for (bp = FIRST(&breakInfo.BQ, breakEntry); bp; bp = NEXT(bp)) {
	  if (bp->selected) {
	       debuggerDeleteBkpt(NULL, NULL, bp->num);
	       acted = TRUE;
	  }
     }
     if (!acted) /* no breakpoints were selected */
	  popupErrorMessage(NULL, msg1, strlen(msg1));
     Leave_void;
}
/*
 * Interactively disable a breakpoint.
 */
void breakpointDisable()
{
     breakEntry *bp;
     Boolean acted = FALSE;

     Entry("breakpointDisable");

     for (bp = FIRST(&breakInfo.BQ, breakEntry); bp; bp = NEXT(bp))
	  if (bp->selected) {
	       debuggerDisableBkpt(NULL, NULL, bp->num);
	       acted = TRUE;
	  }
     if (!acted) /* no breakpoints were selected */
	  popupErrorMessage(NULL, msg1, strlen(msg1));
     Leave_void;
}

/*
 * Interactively enable a breakpoint.
 */
void breakpointEnable()
{
     breakEntry *bp;
     Boolean acted = FALSE;

     Entry("breakpointEnable");

     for (bp = FIRST(&breakInfo.BQ, breakEntry); bp; bp = NEXT(bp))
	  if (bp->selected) {
	       debuggerEnableBkpt(NULL, NULL, bp->num);
	       acted = TRUE;
	  }
     if (!acted) /* no breakpoints were selected */
	  popupErrorMessage(NULL, msg1, strlen(msg1));
     Leave_void;
}

/*
 * Create the breakpoint view pane.
 */
void breakCreateView(w, client_data, data)
Widget w;
caddr_t client_data, data;
{
     static FormField buttons[] = {
	  { { "close", viewCloseShell },	   2,  FALSE,  0,  0,  0,  0 },
	  { { "update",debuggerQueryBreakpoints},  2,  FALSE,  0, 15,  0,  1 },
	  { { "delete", breakpointDelete },	   2,  FALSE,  0,  5,  0,  2 },
	  { { "disable", breakpointDisable },	   2,  FALSE,  0,  5,  0,  3 },
	  { { "enable", breakpointEnable },	   2,  FALSE,  0,  5,  0,  4 },
	  { { "<reset>", breakClearSelected },	   2,  FALSE,  0, 20,  0,  5 },
	  { { NULL, NULL },			   0,      0,  0,  0,  0,  0 },
     };
     FieldAttributes fla;
     Field *flist;
     String name = ((w) ? XtWidgetToName(w) : (String)data);

     Entry("breakCreateView");

     if (!BreakpointView) {
	  convertFormToField(buttons, &flist);
	  
	  ii = 0;
	  XtSetArg(aa[ii], XtNallowVert, TRUE);				ii++;
	  XtSetArg(aa[ii], XtNallowHoriz, TRUE);			ii++;
	  XtSetArg(aa[ii], XtNmin, 50);					ii++;
	  XtSetArg(aa[ii], XtNmax, 1500);				ii++;
	  BreakpointView = viewCreateShell(name, flist,
					   viewportWidgetClass,
					   aa, ii);
	  i = 0;
	  breakInfo.box = XtCreateManagedWidget("bkpts", boxWidgetClass,
						BreakpointView->output,
						args, i);
	  i = 0;
	  XtSetArg(args[i], XtNlabel, "No breakpoints selected");	i++;
	  XtSetArg(args[i], XtNresize, TRUE);				i++;
	  breakInfo.select = XtCreateManagedWidget("bkpts", labelWidgetClass,
						   breakInfo.box, args, i);

	  /* breakpoints added before view created */
	  if (queueActive(&breakInfo.BQ)) {
	       register breakEntry *bp = FIRST(&breakInfo.BQ, breakEntry);

	       while(bp) {
		    char name[30];
		    sprintf(name, "Bkpt #%d", bp->num);

		    i = 0;
		    call[0].closure = (caddr_t)bp;
		    XtSetArg(args[i], XtNborderWidth, 0);		i++;
		    XtSetArg(args[i], XtNlabel, bkptEntry_to_name(bp)); i++;
		    XtSetArg(args[i], XtNcallback, call);		i++;
		    if (bp->enabled == FALSE) {
			 XtSetArg(args[i], XtNsensitive, FALSE);	i++;
		    }
		    bp->cmd = XtCreateManagedWidget(name, commandWidgetClass,
						    breakInfo.box, args, i);
		    bp = NEXT(bp);
	       }
	  }
     }
     XtPopup(BreakpointView->parent, XtGrabNone);
     XRaiseWindow(XtDisplay(BreakpointView->parent),
		  XtWindow(BreakpointView->parent));
     BreakpointView->mapped = TRUE;

     /* Make the field that invoked us go insensitive */
     fla.sensitive = FALSE;
     changeField(nameToField(name, client_data), FldSensitive, &fla);
     breakUpdateView();
     Leave_void;
}