|
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: 14435 (0x3863) Types: TextFile Names: »break.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦34cc4e2f7⟧ »./UNRELEASED/xgdb3.2.tar.Z« └─⟦80fac5d7c⟧ └─⟦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("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; }