|
|
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 b
Length: 14487 (0x3897)
Types: TextFile
Names: »break.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89
└─⟦e10a7c8ba⟧ »./UNRELEASED/xgdb.tar.Z«
└─⟦ae30648b5⟧
└─⟦this⟧ »./break.c«
\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("%p: 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("%p: 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("%p: 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("%p: 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("%p: 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;
}