From beatty@unh.cs.cmu.edu Sat Jul 4 12:04:01 1987 Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:03:37 EDT Message-Id: <8707041603.AA08600@prep.ai.mit.edu> To: phr@prep.ai.mit.edu (Paul Rubin) Date: Sat, 4 Jul 87 12:03:01 EDT From: Derek Beatty Subject: Re: gdb and X (msg 1 of 3) Status: R This is part 1 of 3 parts. It consists of the cursor I used, and a message I sent to Zalman Stern at Andrew regarding what I did, and why. The code and context diffs will follow in other messages. #define gdb_width 16 #define gdb_height 16 #define gdb_x_hot 7 #define gdb_y_hot 0 static short gdb_bits[] = { 0x0000, 0x0140, 0x0220, 0x0220, 0x23e2, 0x13e4, 0x09c8, 0x0ff8, 0x0220, 0x3ffe, 0x0630, 0x03e0, 0x0220, 0x1ffc, 0x2632, 0x01c0}; #define gdb_mask_width 16 #define gdb_mask_height 16 #define gdb_mask_x_hot 7 #define gdb_mask_y_hot 0 static short gdb_mask_bits[] = { 0x0360, 0x07f0, 0x07f0, 0x77f7, 0x7fff, 0x7fff, 0x1ffc, 0x1ffc, 0x7fff, 0x7fff, 0x7fff, 0x0ff8, 0x3ffe, 0x7fff, 0x7fff, 0x7fff}; > > The X support I added is minimal; it was inspired by Suntools' dbxtool, > together with the availability of the V10 implementation of the X V11 > toolkit specification. Design was guided by simplicity and the facilities > of the toolkit. The debugger window provides a view into the code > corresponding to the current stack frame, and several buttons for the > breakpoint, print, step, next, continue, finish, up, and down commands. > The standard gdb command interface remains available in the tty window from > which gdb was started. The breakpoint and print buttons make use of the > current selection, so you can do simple things like click at text in the > source window, then click the "Go 'til" button to continue until that > point. > > Such an interface is simple to program ( ~ 20 hours, about 700 lines), > but it has some drawbacks. First, I didn't take the time to understand > the longjmp's in gdb, and I'm not exactly happy with the idea of them > jumping out of my callback procedures that were invoked by toolkit routines. > There's one core dump bug (it shows up when gdb can't find a source > file) that I haven't tracked down, and it may be related to this. Second, > selection in the text window is not particularly graceful: double-clicking > highlights one word of text, as the toolkit defines a word. It would > be much more graceful were double-clicking to highlight a C identifier. > Finally, and most seriously, most buttons operate by building textual > command lines and passing them to gdb's execute_command function. This > means that all selected expressions are evaluated and printed in the > lexical scope corresponding to the current stack frame, although the > selected text may be in a different lexical scope. This serious bug would > require work to fix. > > I wrote the X support out of frustration at not having dbxtool available > when I work on a vax. The hope of portability to V11 via the toolkit > also helped motivate me to write V10 code at this late date. Finally, > I'd never written any nontrivial code that ran on a windowing system > (although that turns out still to be the case). Were I to make a more > serious effort at this project, I would probably add a general "define-button" > command akin to gdb's "define" command. > > Look in /usr/beatty/gnu/gdb on vlsi.cs.cmu.edu. All files I have modified > are marked, and also have associated backups (.B extensions). Bennet > Yee has a copy of the toolkit library; see /usr/bsy/Xtlib on f.gp.cs.cmu.edu. > > -- Derek > -- Derek Beatty From beatty@unh.cs.cmu.edu Sat Jul 4 12:12:47 1987 Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:09:20 EDT Message-Id: <8707041609.AA08643@prep.ai.mit.edu> To: phr@PREP.AI.MIT.EDU (Paul Rubin) Date: Sat, 4 Jul 87 12:07:25 EDT From: Derek Beatty Subject: Re: gdb and X (msg 2 of 3) In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am Status: R The following is "tool.c". I hereby grant permission to do anything you like with it. -- Derek Beatty [nosave] /* * gdb tool for X V10R4 (using V11-compatible toolkit). * Derek Beatty 30 June 87. */ #include #include #include #include "defs.h" #include "symtab.h" #include "gdb.cursor" #include "gdb_mask.cursor" /* forward refs */ static Window createFileText(); /* * Windows manipulated by this package. */ static Window icon, frame, srcLabelStrip, srcText, ctlPanel, execLabelStrip; static Cursor curse; /* * Source text display. */ static struct symtab *displayedSymtab= 0; extern struct symtab *current_source_symtab; extern int current_source_line; toolDisplaySource() { char *fullName; static Arg labelArgs[1]; int linenumbers_changed= 0; static int newWidget= 1; struct symtab_and_line get_selected_frame_sal(); struct symtab_and_line sal; /* we could be called before we are initialized */ if (!frame) return; sal= get_selected_frame_sal(); /* strictly this is wrong, but better than a blank display */ if (sal.symtab==NULL) { sal.symtab= current_source_symtab; /* current_source_line may be off by a small number like 4 */ sal.line= current_source_line; } /* * Switch to a new file if necessary. */ if (sal.symtab) linenumbers_changed= get_filename_and_charpos(sal.symtab, sal.line, &fullName); if (!fullName) sal.symtab= NULL; /* if the display may be wrong, destroy it */ if (linenumbers_changed || displayedSymtab != sal.symtab) { XtVPanedWindowDeletePane( srcText); XtSendDestroyNotify( srcText); XDestroyWindow( srcText); srcText= 0; } /* if there's no display, create one */ if (!srcText) { newWidget= 1; /* if there's no valid display, create a dummy display */ if (!sal.symtab ) { displayedSymtab= NULL; srcText= createFileText(frame, "/dev/null"); XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1); /* create /dev/null text widget */ XtSetArg(labelArgs[0], XtNlabel, "No source displayed."); XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs)); } else { displayedSymtab= sal.symtab; srcText= createFileText(frame, fullName); XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1); XtSetArg(labelArgs[0], XtNlabel, fullName); XtLabelSetValues(srcLabelStrip, labelArgs, XtNumber(labelArgs)); /* free filename (maybe: check gdb code!) */ } } /* * Update display and cursor positions as necessary. * Cursor should be placed on line sal.line. */ { static int prevTop= 0, highWaterMark= 0; int currentTop; Arg textArgs[1]; /* get positions of start of display, and caret */ XtSetArg(textArgs[0], XtNdisplayPosition, NULL); XtTextGetValues(srcText, textArgs, XtNumber(textArgs)); currentTop= cvtCharToLine(displayedSymtab, (int) textArgs[0].value); highWaterMark += currentTop - prevTop; if ( sal.line < currentTop || sal.line > highWaterMark || newWidget) { /* warp the display */ newWidget= 0; /* yes, these magic numbers are ugly, but I don't know how * to get the height of a text widget in a V11-portable way */ currentTop= (sal.line > 15) ? sal.line - 15 : 0; highWaterMark= currentTop + 35; XtSetArg(textArgs[0], XtNdisplayPosition, cvtLineToChar(displayedSymtab, currentTop)); XtTextSetValues(srcText, textArgs, XtNumber(textArgs)); } XtSetArg(textArgs[0], XtNinsertPosition, cvtLineToChar(displayedSymtab, sal.line)); XtTextSetValues(srcText, textArgs, XtNumber(textArgs)); prevTop= currentTop; } } /* return the character position of a line */ int cvtLineToChar( s, line) struct symtab *s; int line; { if (!s) return 0; if (!s->line_charpos) return 0; if (line < 0) line= 0; if (line > s->nlines) line= s->nlines; return *(s->line_charpos + line-1); } /* return the line position of a character */ int cvtCharToLine( s, chr) register struct symtab *s; register int chr; { register int lineNumber= 0; register int *lnp; if (!s) return 0; lnp= s->line_charpos; /* files are usually short, so sequential search is Ok */ while ( lineNumber < s->nlines && *lnp <= chr) { lineNumber++; lnp++; } if (lineNumber >= s->nlines) lineNumber= s->nlines; return lineNumber; } /* * title bar at bottom */ static char *execFileName; toolSetExecFile(s) char *s; { execFileName= s; if (execLabelStrip) { static Arg labelArgs[1]; XtSetArg(labelArgs[0], XtNlabel, execFileName); XtLabelSetValues(execLabelStrip, labelArgs, XtNumber(labelArgs)); } } /* * Command line into which command are placed for execution. * There's some ugly interaction between this and readline in main.c. */ extern char *line; extern int linesize; /* * Do any necessary prompting, etc. */ static char *gdbPrompt; static void printPrompt() { if (gdbPrompt) { printf("%s", gdbPrompt); fflush(stdout); } } /* * Callback procedures for control panel. */ /* used by "print" and "print*" buttons */ static void printButnProc_1( starflag) int starflag; { int selnLen; char *seln; char *cmd= starflag ? "print * " : "print "; register int cmdlen= strlen(cmd); seln= XFetchBytes(&selnLen); if (selnLen) { if (selnLen+cmdlen >= linesize-1) { linesize= (selnLen+cmdlen > linesize*2-1) ? selnLen+cmdlen+1 : linesize*2; line= (char *) xrealloc(line, linesize); } strcpy(line, cmd); strncpy(line+cmdlen, seln, selnLen); *(line+cmdlen+selnLen)= '\0'; execute_command(line, 0); free(seln); } printPrompt(); } static void printButnProc() { printButnProc_1( 0); } static void printStarButnProc() { printButnProc_1( 1); } static void nextButnProc() { strcpy(line, "next"); execute_command(line, 0); toolDisplaySource(); printPrompt(); } static void stepButnProc() { strcpy(line, "step"); execute_command(line, 0); toolDisplaySource(); printPrompt(); } static void contButnProc() { strcpy(line, "cont"); execute_command(line, 0); toolDisplaySource(); printPrompt(); } static void finButnProc() { strcpy(line, "finish"); execute_command(line, 0); toolDisplaySource(); printPrompt(); } /* used by "stop at" and "go till" buttons */ static void stopAtButnProc_1( gotillFlag) int gotillFlag; { XtTextPosition start, finish; static int lineNumber; XtTextGetSelectionPos(srcText, &start, &finish); if (!displayedSymtab) printf("No source file displayed.\n"); else { break_command_for_tool( displayedSymtab, cvtCharToLine(displayedSymtab, start), gotillFlag); if (gotillFlag) { strcpy(line, "cont"); execute_command(line, 0); toolDisplaySource(); } } printPrompt(); } static void stopAtButnProc() { stopAtButnProc_1( 0); } static void untilButnProc() { stopAtButnProc_1( 1); } /* decide if a character is trash */ static int garbage(c) char c; { if ('a' <= c && c <= 'z') return 0; if ('A' <= c && c <= 'Z') return 0; if ('0' <= c && c <= '9') return 0; if (c == '_') return 0; return 1; } static void stopInButnProc() { static int selnLen; static char *seln; char *sp, *selnp; seln= XFetchBytes(&selnLen); if (selnLen) { if (selnLen+6 >= linesize-1) { linesize= (selnLen+6 > linesize*2-1) ? selnLen+7 : linesize*2; line= (char *) xrealloc(line, linesize); } strcpy(line, "break "); /* copy selection but not garbage */ selnp= seln; sp= line+strlen(line); while (garbage(*selnp) && selnLen) selnp++, selnLen--; while (!garbage(*selnp) && selnLen) { *sp++= *selnp++; selnLen--; } *sp= '\0'; execute_command(line, 0); free(seln); } printPrompt(); } static void deIconifyButnProc() { XUnmapWindow(icon); XMapWindow(frame); } static void iconifyButnProc() { static Arg iconArgs[1]; XtSetArg(iconArgs[0], XtNlabel, gdbPrompt); XtCommandSetValues(icon, iconArgs, XtNumber(iconArgs)); XUnmapWindow(frame); XMapWindow(icon); } static void upButnProc() { strcpy(line, "up"); execute_command(line, 0); toolDisplaySource(); printPrompt(); } static void downButnProc() { strcpy(line, "down"); execute_command(line, 0); toolDisplaySource(); printPrompt(); } #define addbutton(w) XtSetArg(buttons[buttoncount], XtNwindow, w); \ buttoncount++; static Arg buttons[20]; static int buttoncount= 0; /* * Create control panel buttons. */ static createButtons(parent) Window parent; { static Window button; static Arg commandArgs[2]; #define crButn(label,fn) \ XtSetArg(commandArgs[0], XtNlabel, label);\ XtSetArg(commandArgs[1], XtNfunction, fn);\ button= XtCommandCreate(parent, commandArgs, XtNumber(commandArgs));\ addbutton(button); crButn("Brk At", stopAtButnProc); crButn("Brk In", stopInButnProc); crButn("Go 'til", untilButnProc); crButn("Print", printButnProc); crButn("Print*", printStarButnProc); crButn("Next", nextButnProc); crButn("Step", stepButnProc); crButn("Cont", contButnProc); crButn("Finish", finButnProc); crButn("Up", upButnProc); crButn("Down", downButnProc); crButn("Iconify", iconifyButnProc); #undef crButn } static Window createLabel(parent, name, label) Window parent; char *name, *label; { static Arg labelArgs[2]; XtSetArg(labelArgs[0], XtNname, name); XtSetArg(labelArgs[1], XtNlabel, label); return XtLabelCreate(frame, labelArgs, XtNumber(labelArgs)); } static Window createFileText( parent, filename) Window parent; char *filename; { static Arg fileArgs[2]; XtSetArg(fileArgs[0], XtNfile, filename); XtSetArg(fileArgs[1], XtNtextOptions, scrollVertical); return XtTextDiskCreate(parent, fileArgs, XtNumber(fileArgs)); } /***************** Externally referenced routine **************/ int createTool() { static Arg frameArgs[]= { {XtNwidth, (XtArgVal) 600}, {XtNheight, (XtArgVal) 700}, }; ResourceDataBase db; FILE *rdbFile; /* * init and database stuff... this is wrong but what the heck */ if (XOpenDisplay("") == NULL) return 0; printf("Initializing tool..."); fflush(stdout); XtInitialize(); /* should be checking .Xdefaults in $HOME */ if ((rdbFile= fopen(".Xresources", "r")) != NULL) { XtGetDataBase(rdbFile, &db); XtSetCurrentDataBase(db); fclose(rdbFile); } /* * create the frame */ frame= XtVPanedWindowCreate(RootWindow, frameArgs, XtNumber(frameArgs)); /* create source label strip and add to frame */ srcLabelStrip= createLabel(frame, "Source File", "No source file yet."); XtVPanedWindowAddPane(frame, srcLabelStrip, 0, 15, 15, 0); /* create text widget and add to frame */ srcText= createFileText(frame, "/dev/null"); XtVPanedWindowAddPane(frame, srcText, 1, 20, 1000, 1); /* create button box */ ctlPanel= XtButtonBoxCreate(frame, NULL, 0); createButtons( ctlPanel); XtButtonBoxAddButton(ctlPanel, buttons, buttoncount); XtVPanedWindowAddPane(frame, ctlPanel, 2, 30, 30, 0); /* create exec label strip and add */ execLabelStrip= createLabel(frame, "Executable", execFileName ? execFileName : "No executable specified."); XtVPanedWindowAddPane(frame, execLabelStrip, 3, 15, 15, 0); /* create icon */ { static Arg iconArgs[2]; XtSetArg(iconArgs[0], XtNlabel, "(gdb)"); XtSetArg(iconArgs[1], XtNfunction, deIconifyButnProc); icon= XtCommandCreate(RootWindow, iconArgs, XtNumber(iconArgs)); XMoveWindow(icon, 100, 100); /* HACK */ XSetIconWindow(frame, icon); } /* throw it onto the display */ curse= XCreateCursor(gdb_width, gdb_height, gdb_bits, gdb_mask_bits, gdb_x_hot, gdb_y_hot, BlackPixel, WhitePixel, GXcopy); XDefineCursor(frame, curse); XDefineCursor(icon, curse); XMapWindow(frame); XMapSubwindows(frame); XFlush(); printf("done\n"); return 1; } /**************** Externally referenced routine. ***********/ /* toolDispatcher -- dispatch events until data is available on fp */ toolDispatcher(fp, prompt) FILE *fp; char *prompt; { int inMask= 1 << fileno(fp); int xMask= 1 << dpyno(); int rfds= 0; int nfds; XEvent ev; int pend; gdbPrompt= prompt; while (! (rfds & inMask)) { pend= XPending(); if (!pend) { rfds= inMask | xMask; /* this isn't right for 4.3 but it works 'cuz of 4.2 compatibility */ nfds= select( 32, &rfds, 0, 0, (struct timeval *) 0); } if (pend || rfds & xMask) { XNextEvent(&ev); XtDispatchEvent(&ev); } } } From beatty@unh.cs.cmu.edu Sat Jul 4 12:17:44 1987 Received: by PREP.AI.MIT.EDU; Sat, 4 Jul 87 12:15:18 EDT Message-Id: <8707041615.AA08691@prep.ai.mit.edu> To: phr@PREP.AI.MIT.EDU (Paul Rubin) Date: Sat, 4 Jul 87 12:14:08 EDT From: Derek Beatty Subject: Re: gdb and X (msg 3 of 3) In-Reply-To: Message from "Paul Rubin" of Jul 4, 87 at 1:22 am Status: R Context diffs follow. The original files are from GDB 2.1 (emacs distribution 18.40). -- Derek Beatty [nosave] *** /usr/misc/.gdb/src/core.c Fri Mar 27 12:20:14 1987 --- core.c Sat Jul 4 11:12:16 1987 *************** *** 1,3 /* Work with core dump and executable files, for GDB. Copyright (C) 1986, 1987 Free Software Foundation, Inc. --- 1,5 ----- + /* modified by Beatty 1 Jul 87 for gdb tool. */ + /* Work with core dump and executable files, for GDB. Copyright (C) 1986, 1987 Free Software Foundation, Inc. *************** *** 257,262 } else if (from_tty) printf ("No exec file now.\n"); } /* If we have both a core file and an exec file, --- 259,267 ----- } else if (from_tty) printf ("No exec file now.\n"); + #ifdef TOOL + toolSetExecFile( filename ? filename : "No executable specified.\n"); + #endif /* def TOOL */ } /* If we have both a core file and an exec file, *** /usr/misc/.gdb/src/breakpoint.c Fri Mar 27 12:20:11 1987 --- breakpoint.c Wed Jul 1 11:27:31 1987 *************** *** 1,3 /* Everything about breakpoints, for GDB. Copyright (C) 1986, 1987 Free Software Foundation, Inc. --- 1,5 ----- + /* modified by Beatty 1 Jul 87 for gdbtool */ + /* Everything about breakpoints, for GDB. Copyright (C) 1986, 1987 Free Software Foundation, Inc. *************** *** 513,518 break; } } /* Set a breakpoint according to ARG (function, linenum or *address) and make it temporary if TEMPFLAG is nonzero. */ --- 515,571 ----- break; } } + + #ifdef TOOL + /* set a breakpoint from a symtab and line */ + void break_command_for_tool( s, line, tempflag) + struct symtab *s; + int line; + int tempflag; + { + register struct breakpoint *b; + struct symtab_and_line sal; + + sal.symtab= s; + sal.line= line; + sal.pc= find_line_pc( sal.symtab, sal.line); + if (sal.pc==0) { + error("No line %d in file \"%s\".\n", sal.line, sal.symtab->filename); + } else { + b= set_raw_breakpoint( sal); + b->number= ++breakpoint_count; + b->cond= 0; + if (tempflag) + b->enable= temporary; + + printf ("Breakpoint %d at 0x%x", b->number, b->address); + if (b->symtab) + printf (": file %s, line %d.", b->symtab->filename, b->line_number); + printf ("\n"); + + { + int others = 0; + ALL_BREAKPOINTS (b) + if (b->address == sal.pc && b->number != breakpoint_count) + others++; + if (others > 0) + { + printf ("Note: breakpoint%s ", (others > 1) ? "s" : ""); + ALL_BREAKPOINTS (b) + if (b->address == sal.pc && b->number != breakpoint_count) + { + others--; + printf ("%d%s%s ", + b->number, + (b->enable == disabled) ? " (disabled)" : "", + (others > 1) ? "," : ((others == 1) ? " and" : "")); + } + printf (" also set at pc 0x%x\n", sal.pc); + } + } + } + } + #endif /* def TOOL */ /* Set a breakpoint according to ARG (function, linenum or *address) and make it temporary if TEMPFLAG is nonzero. */ *** /usr/misc/.gdb/src/main.c Fri Mar 27 12:20:45 1987 --- main.c Sat Jul 4 11:13:32 1987 *************** *** 1,3 /* Top level for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. --- 1,5 ----- + /* modified by Beatty 30 june 87 for gdb tool */ + /* Top level for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. *************** *** 42,47 FILE *instream; void free_command_lines (); char *read_line (); static void initialize_main (); --- 44,54 ----- FILE *instream; + #ifdef TOOL + /* flag indicating whether we are running in a window system */ + int isaTool= 0; + #endif /* def TOOL */ + void free_command_lines (); char *read_line (); static void initialize_main (); *************** *** 214,219 while (1) { if (!setjmp (to_top_level)) command_loop (); clearerr (stdin); /* Don't get hung if C-d is typed. */ --- 221,232 ----- while (1) { + + #ifdef TOOL + if (!isaTool) + isaTool= createTool(); + #endif /* def TOOL */ + if (!setjmp (to_top_level)) command_loop (); clearerr (stdin); /* Don't get hung if C-d is typed. */ *************** *** 270,275 printf ("%s", prompt); fflush (stdout); quit_flag = 0; execute_command (read_line (instream == stdin), instream == stdin); /* Do any commands attached to breakpoint we stopped at. */ --- 283,294 ----- printf ("%s", prompt); fflush (stdout); + #ifdef TOOL + toolDisplaySource(); + if (isaTool) toolDispatcher(instream, + instream==stdin ? prompt : NULL); + #endif /* def TOOL */ + quit_flag = 0; execute_command (read_line (instream == stdin), instream == stdin); /* Do any commands attached to breakpoint we stopped at. */ *************** *** 320,325 while (1) { c = fgetc (instream); if (c == -1 || c == '\n') break; --- 339,345 ----- while (1) { + c = fgetc (instream); if (c == -1 || c == '\n') break; *************** *** 765,770 GDB is free software and you are welcome to distribute copies of it\n\ under certain conditions; type \"info copying\" to see the conditions.\n", version); } static void --- 785,793 ----- GDB is free software and you are welcome to distribute copies of it\n\ under certain conditions; type \"info copying\" to see the conditions.\n", version); + #ifdef TOOL + printf( "(CMU X support is available in this version.)\n"); + #endif } static void *** /usr/misc/.gdb/src/source.c Fri Mar 27 12:20:50 1987 --- source.c Wed Jul 1 17:56:58 1987 *************** *** 1,3 /* List lines of source files for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. --- 1,5 ----- + /* modified 1 July 87 by Beatty for gdbtool */ + /* List lines of source files for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. *************** *** 295,300 s->nlines = nlines; s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int)); } /* Print source lines from the file of symtab S, starting with line number LINE and stopping before line number STOPLINE. */ --- 297,328 ----- s->nlines = nlines; s->line_charpos = (int *) xrealloc (line_charpos, nlines * sizeof (int)); } + + #ifdef TOOL + /* Get full pathname and line number positions for a symtab + * return nonzero if line numbers may have changed + * set full pathname to NULL if no file found + */ + int + get_filename_and_charpos(s, line, fullname) + struct symtab *s; + int line; + char **fullname; + { + register int desc, linenums_changed= 0; + + desc= openp(source_path, 0, s->filename, O_RDONLY, 0, fullname); + if (desc < 0) { + *fullname= NULL; + return 0; + } + if (s->line_charpos==0) linenums_changed= 1; + if (linenums_changed) find_source_lines(s, desc); + close(desc); + return linenums_changed; + } + #endif /* def TOOL */ + /* Print source lines from the file of symtab S, starting with line number LINE and stopping before line number STOPLINE. */ *** /usr/misc/.gdb/src/stack.c Fri Mar 27 12:20:51 1987 --- stack.c Wed Jul 1 17:27:34 1987 *************** *** 1,3 /* Print and select stack frames for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. --- 1,5 ----- + /* modified by Beatty 1 Jul 87 for gdbtool */ + /* Print and select stack frames for GDB, the GNU debugger. Copyright (C) 1986, 1987 Free Software Foundation, Inc. *************** *** 42,47 static void select_calling_frame (); void print_frame_info (); /* Print a stack frame briefly. FRAME should be the frame address and LEVEL should be its level in the stack (or -1 for level not defined). --- 44,62 ----- static void select_calling_frame (); void print_frame_info (); + + #ifdef TOOL + /* get symtab and line of selected frame, for tool display */ + struct symtab_and_line + get_selected_frame_sal() + { + struct frame_info fi; + + fi= get_frame_info( selected_frame); + return find_pc_line(fi.pc, fi.next_frame); + } + + #endif /* TOOL */ /* Print a stack frame briefly. FRAME should be the frame address and LEVEL should be its level in the stack (or -1 for level not defined). End of context diffs. The presence of this line verifies that this message has not been truncated.