diff options
-rw-r--r-- | gdb/ChangeLog | 33 | ||||
-rw-r--r-- | gdb/gdbtk.c | 181 | ||||
-rw-r--r-- | gdb/gdbtk.tcl | 90 |
3 files changed, 173 insertions, 131 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 504b5c0..1b26e26 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,36 @@ +Sun Dec 18 23:31:20 1994 Stu Grossman (grossman@cygnus.com) + + * gdbtk.c (gdbtk_wait gdbtk_init): Use different method of + enabling I/O interrupts for SVR4 (streams). + * (start_saving_output save_output get_saved_output + finish_saving_output flush_holdbuf gdbtk_flush gdbtk_fputs + gdbtk_init): + Totally revamp to use TCLs dynamic string functions. Also, quote + all data passed back to TCL to prevent errors with unmatched + braces, odd characters, etc... This fixes several wierd problems + with outputting strings containing unmatched braces. + * (breakpoint_notify gdb_loc): Use long hex format to output + addresses of breakpoints and PCs. This fixes some Alpha problems. + * (breakpoint_notify): Add stream arg to call to gdbtk_fputs. + * (gdb_listfiles): Also, go through the symtabs when looking for + files. This makes xcoff work (sort of), but probably breaks + something else. + * (gdb_stop): Return TCL_OK instead of nothing. This fixes odd + TCL errors when hitting stop button. + * (tk_command): Don't pass interp->result on to Tcl_{Var}Eval, as + that will trash the result. strdup the result instead and pass + that on. Improve error handling as well. + + * gdbtk.tcl (gdbtk_tcl_flush): Use global def of + current_output_win. Makes flushing actually work! + * (asm_win_name create_asm_win update_assembly): Bunch of fixes + to make assembly windows stop flashing when loading a new file. + * (gdbtk_tcl_busy gdbtk_tcl_idle): Use catch to prevent gdb_cmd + errors from losing control. + * (create_source_window): Add source file selection to View menu. + * (create_command_window (<Key-Return> binding): Quote text fed + into gdb_cmd to prevent eval errors. + Sun Dec 18 11:52:58 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) * sparc-tdep.c (sparc_pop_frame): Remove erroneous extra argument diff --git a/gdb/gdbtk.c b/gdb/gdbtk.c index 4acf0f4..e3d8412 100644 --- a/gdb/gdbtk.c +++ b/gdb/gdbtk.c @@ -33,6 +33,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <unistd.h> #include <setjmp.h> #include "top.h" +#ifndef FASYNC +#include <sys/stropts.h> +#endif +#include <string.h> /* Non-zero means that we're doing the gdbtk interface. */ int gdbtk = 0; @@ -55,94 +59,70 @@ null_routine(arg) { } -static char *saved_output_buf = NULL; /* Start of output buffer */ -static char *saved_output_data_end = NULL; /* Ptr to nul at end of data */ -static int saved_output_buf_free = 0; /* Amount of free space in buffer */ -static char saved_output_static_buf[200]; /* Default buffer */ - -static void -start_saving_output () -{ - if (saved_output_buf) - abort (); /* Should always be zero at this point */ - - saved_output_buf = saved_output_static_buf; - saved_output_data_end = saved_output_buf; - *saved_output_data_end = '\000'; - saved_output_buf_free = sizeof saved_output_static_buf - 1; -} - -static void -save_output (ptr) - const char *ptr; -{ - int len; - int needed, data_len; - - len = strlen (ptr); +/* The following routines deal with stdout/stderr data, which is created by + {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the + lowest level of these routines and capture all output from the rest of GDB. + Normally they present their data to tcl via callbacks to the following tcl + routines: gdbtk_tcl_fputs, gdbtk_tcl_fputs_error, and gdbtk_flush. These + in turn call tk routines to update the display. - if (len <= saved_output_buf_free) - { - strcpy (saved_output_data_end, ptr); - saved_output_data_end += len; - saved_output_buf_free -= len; - return; - } + Under some circumstances, you may want to collect the output so that it can + be returned as the value of a tcl procedure. This can be done by + surrounding the output routines with calls to start_saving_output and + finish_saving_output. The saved data can then be retrieved with + get_saved_output (but this must be done before the call to + finish_saving_output). */ - data_len = saved_output_data_end - saved_output_buf; - needed = (data_len + len + 1) * 2; +/* Dynamic string header for stdout. */ - if (saved_output_buf == saved_output_static_buf) - { - char *tmp; +static Tcl_DString stdout_buffer; - tmp = xmalloc (needed); - strcpy (tmp, saved_output_buf); - saved_output_buf = tmp; - } - else - saved_output_buf = xrealloc (saved_output_buf, needed); +/* Use this to collect stdout output that will be returned as the result of a + tcl command. */ - saved_output_data_end = saved_output_buf + data_len; - saved_output_buf_free = (needed - data_len) - 1; +static int saving_output = 0; - save_output (ptr); +static void +start_saving_output () +{ + saving_output = 1; } -#define get_saved_output() saved_output_buf +#define get_saved_output() (Tcl_DStringValue (&stdout_buffer)) static void finish_saving_output () { - if (saved_output_buf != saved_output_static_buf) - free (saved_output_buf); + saving_output = 0; - saved_output_buf = NULL; + Tcl_DStringFree (&stdout_buffer); } /* This routine redirects the output of fputs_unfiltered so that the user can see what's going on in his debugger window. */ -static char holdbuf[200]; -static char *holdbufp = holdbuf; -static int holdfree = sizeof (holdbuf); - static void flush_holdbuf () { - if (holdbufp == holdbuf) - return; + char *s, *argv[1]; + + /* We use Tcl_Merge to quote braces and funny characters as necessary. */ + + argv[0] = Tcl_DStringValue (&stdout_buffer); + s = Tcl_Merge (1, argv); - Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", holdbuf, "}", NULL); - holdbufp = holdbuf; - holdfree = sizeof (holdbuf); + Tcl_DStringFree (&stdout_buffer); + + Tcl_VarEval (interp, "gdbtk_tcl_fputs ", s, NULL); + + free (s); } static void gdbtk_flush (stream) FILE *stream; { - if (stream != gdb_stdout || saved_output_buf) + if (stream != gdb_stdout || saving_output) return; /* Flush output from C to tcl land. */ @@ -167,28 +147,13 @@ gdbtk_fputs (ptr, stream) return; } - if (saved_output_buf) - { - save_output (ptr); - return; - } - - len = strlen (ptr) + 1; + Tcl_DStringAppend (&stdout_buffer, ptr, -1); - if (len > holdfree) - { - flush_holdbuf (); - - if (len > sizeof (holdbuf)) - { - Tcl_VarEval (interp, "gdbtk_tcl_fputs ", "{", ptr, "}", NULL); - return; - } - } + if (saving_output) + return; - strncpy (holdbufp, ptr, len); - holdbufp += len - 1; - holdfree -= len - 1; + if (Tcl_DStringLength (&stdout_buffer) > 1000) + flush_holdbuf (); } static int @@ -228,7 +193,7 @@ breakpoint_notify(b, action) sprintf (bpnum, "%d", b->number); sprintf (line, "%d", sal.line); - sprintf (pc, "0x%x", b->address); + sprintf (pc, "0x%lx", b->address); v = Tcl_VarEval (interp, "gdbtk_tcl_breakpoint ", @@ -241,8 +206,8 @@ breakpoint_notify(b, action) if (v != TCL_OK) { - gdbtk_fputs (interp->result); - gdbtk_fputs ("\n"); + gdbtk_fputs (interp->result, gdb_stdout); + gdbtk_fputs ("\n", gdb_stdout); } } @@ -334,7 +299,7 @@ gdb_loc (clientData, interp, argc, argv) sprintf (buf, "%d", sal.line); Tcl_AppendElement (interp, buf); /* line number */ - sprintf (buf, "0x%x", pc); + sprintf (buf, "0x%lx", pc); Tcl_AppendElement (interp, buf); /* PC */ return TCL_OK; @@ -668,10 +633,14 @@ gdb_listfiles (clientData, interp, argc, argv) int val; struct objfile *objfile; struct partial_symtab *psymtab; + struct symtab *symtab; ALL_PSYMTABS (objfile, psymtab) Tcl_AppendElement (interp, psymtab->filename); + ALL_SYMTABS (objfile, symtab) + Tcl_AppendElement (interp, symtab->filename); + return TCL_OK; } @@ -683,6 +652,8 @@ gdb_stop (clientData, interp, argc, argv) char *argv[]; { target_stop (); + + return TCL_OK; } @@ -691,10 +662,22 @@ tk_command (cmd, from_tty) char *cmd; int from_tty; { - Tcl_VarEval (interp, cmd, NULL); + int retval; + char *result; + struct cleanup *old_chain; + + retval = Tcl_Eval (interp, cmd); + + result = strdup (interp->result); - gdbtk_fputs (interp->result); - gdbtk_fputs ("\n"); + old_chain = make_cleanup (free, result); + + if (retval != TCL_OK) + error (result); + + printf_unfiltered ("%s\n", result); + + do_cleanups (old_chain); } static void @@ -735,7 +718,24 @@ gdbtk_wait (pid, ourstatus) int pid; struct target_waitstatus *ourstatus; { +#ifdef FASYNC signal (SIGIO, x_event); +#else +#if 1 + sigset (SIGIO, x_event); +#else + /* This is possibly needed for SVR4... */ + { + struct sigaction action; + static sigset_t nullsigmask = {0}; + + action.sa_handler = iosig; + action.sa_mask = nullsigmask; + action.sa_flags = SA_RESTART; + sigaction(SIGIO, &action, NULL); + } +#endif +#endif pid = target_wait (pid, ourstatus); @@ -782,6 +782,8 @@ gdbtk_init () if (!interp) error ("Tcl_CreateInterp failed"); + Tcl_DStringInit (&stdout_buffer); /* Setup stdout buffer */ + mainWindow = Tk_CreateMainWindow (interp, NULL, "gdb", "Gdb"); if (!mainWindow) @@ -824,9 +826,14 @@ gdbtk_init () signal (SIGIO, SIG_IGN); +#ifdef FASYNC i = fcntl (x_fd, F_GETFL, 0); fcntl (x_fd, F_SETFL, i|FASYNC); fcntl (x_fd, F_SETOWN, getpid()); +#else + if (ioctl (x_fd, I_SETSIG, S_INPUT|S_RDNORM) < 0) + perror ("gdbtk_init: ioctl I_SETSIG failed"); +#endif /* ifndef FASYNC */ command_loop_hook = Tk_MainLoop; fputs_unfiltered_hook = gdbtk_fputs; diff --git a/gdb/gdbtk.tcl b/gdb/gdbtk.tcl index f8ce86c..82610d7 100644 --- a/gdb/gdbtk.tcl +++ b/gdb/gdbtk.tcl @@ -9,6 +9,7 @@ set screen_bot 0 set current_output_win .cmd.text set cfunc NIL set line_numbers 1 +set breakpoint_file(-1) {[garbage]} #option add *Foreground Black #option add *Background White @@ -64,6 +65,8 @@ proc gdbtk_tcl_fputs_error {arg} { # proc gdbtk_tcl_flush {} { + global current_output_win + $current_output_win yview -pickplace end update idletasks } @@ -137,6 +140,8 @@ proc gdbtk_tcl_breakpoint {action bpnum file line pc} { } proc asm_win_name {funcname} { + if {$funcname == "*None*"} {return .asm.text} + regsub -all {\.} $funcname _ temp return .asm.func_${temp} @@ -362,50 +367,50 @@ proc delete_breakpoint_tag {win line} { proc gdbtk_tcl_busy {} { if [winfo exists .src] { - .src.start configure -state disabled - .src.stop configure -state normal - .src.step configure -state disabled - .src.next configure -state disabled - .src.continue configure -state disabled - .src.finish configure -state disabled - .src.up configure -state disabled - .src.down configure -state disabled - .src.bottom configure -state disabled + catch {.src.start configure -state disabled} + catch {.src.stop configure -state normal} + catch {.src.step configure -state disabled} + catch {.src.next configure -state disabled} + catch {.src.continue configure -state disabled} + catch {.src.finish configure -state disabled} + catch {.src.up configure -state disabled} + catch {.src.down configure -state disabled} + catch {.src.bottom configure -state disabled} } if [winfo exists .asm] { - .asm.stepi configure -state disabled - .asm.nexti configure -state disabled - .asm.continue configure -state disabled - .asm.finish configure -state disabled - .asm.up configure -state disabled - .asm.down configure -state disabled - .asm.bottom configure -state disabled - .asm.close configure -state disabled + catch {.asm.stepi configure -state disabled} + catch {.asm.nexti configure -state disabled} + catch {.asm.continue configure -state disabled} + catch {.asm.finish configure -state disabled} + catch {.asm.up configure -state disabled} + catch {.asm.down configure -state disabled} + catch {.asm.bottom configure -state disabled} + catch {.asm.close configure -state disabled} } } proc gdbtk_tcl_idle {} { if [winfo exists .src] { - .src.start configure -state normal - .src.stop configure -state disabled - .src.step configure -state normal - .src.next configure -state normal - .src.continue configure -state normal - .src.finish configure -state normal - .src.up configure -state normal - .src.down configure -state normal - .src.bottom configure -state normal + catch {.src.start configure -state normal} + catch {.src.stop configure -state disabled} + catch {.src.step configure -state normal} + catch {.src.next configure -state normal} + catch {.src.continue configure -state normal} + catch {.src.finish configure -state normal} + catch {.src.up configure -state normal} + catch {.src.down configure -state normal} + catch {.src.bottom configure -state normal} } if [winfo exists .asm] { - .asm.stepi configure -state normal - .asm.nexti configure -state normal - .asm.continue configure -state normal - .asm.finish configure -state normal - .asm.up configure -state normal - .asm.down configure -state normal - .asm.bottom configure -state normal - .asm.close configure -state normal + catch {.asm.stepi configure -state normal} + catch {.asm.nexti configure -state normal} + catch {.asm.continue configure -state normal} + catch {.asm.finish configure -state normal} + catch {.asm.up configure -state normal} + catch {.asm.down configure -state normal} + catch {.asm.bottom configure -state normal} + catch {.asm.close configure -state normal} } } @@ -1134,15 +1139,11 @@ proc create_asm_window {} { update - pack forget .asm.text - update_assembly [gdb_loc] } } proc reg_config_menu {} { - global reg_format - catch {destroy .reg.config} toplevel .reg.config wm geometry .reg.config +300+300 @@ -1431,7 +1432,7 @@ proc update_assembly {linespec} { # stick in the new one. if {$funcname != $cfunc } { - pack forget $win + set oldwin $win set cfunc $funcname set win [asm_win_name $cfunc] @@ -1446,6 +1447,7 @@ proc update_assembly {linespec} { # Pack the text widget, and scroll to the right place + pack forget $oldwin pack $win -side left -expand yes -fill both \ -after .asm.scroll .asm.scroll configure -command "$win yview" @@ -1457,7 +1459,6 @@ proc update_assembly {linespec} { if {$current_asm_label != "$pc $funcname"} then { set .asm.label "$pc $funcname" -# .asm.label configure -text "$pc $funcname" set current_asm_label "$pc $funcname" } @@ -1491,9 +1492,6 @@ proc update_assembly {linespec} { $win yview [expr $line - $asm_screen_height / 2] } -# echo "Picking line $line" -# $win yview -pickplace $line - $win configure -state disabled } } @@ -1631,6 +1629,10 @@ proc create_source_window {} { .src.menubar.view.menu delete 0 last +# Source file selection + .src.menubar.view.menu add command -label "Select source file" \ + -command files_command + # Line numbers enable/disable menu item .src.menubar.view.menu add checkbutton -variable line_numbers \ -label "Line numbers" -onvalue 1 -offvalue 0 -command { @@ -1713,7 +1715,7 @@ proc create_command_window {} { %W insert end \n %W yview -pickplace end - catch "gdb_cmd {$command_line}" + catch "gdb_cmd [list $command_line]" set command_line {} update_ptr %W insert end "(gdb) " |