aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog17
-rw-r--r--gdb/defs.h40
-rw-r--r--gdb/gdbtk.c247
-rw-r--r--gdb/gdbtk.tcl248
-rw-r--r--gdb/main.c51
-rw-r--r--gdb/top.c8
6 files changed, 375 insertions, 236 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a8e98c6..70c689b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,20 @@
+Thu Dec 15 16:40:10 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, gdbtk.c (gdbtk_fputs), main.c (gdb_fputs), top.c: Add stream arg
+ to fputs_unfiltered_hook. Differentiate stdout from stderr when
+ passing text into tcl land.
+ * defs.h, top.c, utils.c (error): Add error_hook.
+ * gdbtk.c: Improve mechanism for capturing output values.
+ * (full_filename): Remove.
+ * (gdb_cmd call_wrapper gdbtk_init): Protect all calls from tcl
+ land with call_wrapper. This prevents longjmps (usually via
+ error()) from jumping out of tcl/tk and leaving things in an
+ indeterminate state.
+ * gdbtk.tcl: New view option to disable line numbers. Put catch
+ around most uses of gdb_cmd. Add update button to reg config
+ window. Stop doing immediate updates when selecting registers.
+ Change register view values into checkbuttons.
+
Tue Dec 13 15:15:33 1994 Stan Shebs <shebs@andros.cygnus.com>
* breakpoint.c, infrun.c, printcmd.c: Change long command help
diff --git a/gdb/defs.h b/gdb/defs.h
index a0721ef..835f877 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -33,6 +33,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* libiberty.h can't declare this one, but evidently we can. */
extern char *strsignal PARAMS ((int));
+#include "mmalloc.h"
+
/* For BFD64 and bfd_vma. */
#include "bfd.h"
@@ -138,28 +140,6 @@ extern int inside_main_func PARAMS ((CORE_ADDR pc));
extern char *chill_demangle PARAMS ((const char *));
-/* From libiberty.a */
-
-extern char *cplus_demangle PARAMS ((const char *, int));
-
-extern char *cplus_mangle_opname PARAMS ((char *, int));
-
-/* From libmmalloc.a (memory mapped malloc library) */
-
-extern PTR mmalloc_attach PARAMS ((int, PTR));
-
-extern PTR mmalloc_detach PARAMS ((PTR));
-
-extern PTR mmalloc PARAMS ((PTR, long));
-
-extern PTR mrealloc PARAMS ((PTR, PTR, long));
-
-extern void mfree PARAMS ((PTR, PTR));
-
-extern int mmalloc_setkey PARAMS ((PTR, int, PTR));
-
-extern PTR mmalloc_getkey PARAMS ((PTR, int));
-
/* From utils.c */
extern int strcmp_iw PARAMS ((const char *, const char *));
@@ -544,19 +524,9 @@ extern PTR xmmalloc PARAMS ((PTR, long));
extern PTR xmrealloc PARAMS ((PTR, PTR, long));
-extern PTR mmalloc PARAMS ((PTR, long));
-
-extern PTR mrealloc PARAMS ((PTR, PTR, long));
-
-extern void mfree PARAMS ((PTR, PTR));
-
-extern int mmcheck PARAMS ((PTR, void (*) (void)));
-
-extern int mmtrace PARAMS ((void));
-
extern int parse_escape PARAMS ((char **));
-extern const char * const reg_names[];
+extern char *reg_names[];
/* Message to be printed before the error message, when an error occurs. */
@@ -862,7 +832,7 @@ extern CORE_ADDR push_word PARAMS ((CORE_ADDR, unsigned LONGEST));
extern void (*init_ui_hook) PARAMS ((void));
extern void (*command_loop_hook) PARAMS ((void));
-extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer));
+extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream));
extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line,
int stopline, int noerror));
extern int (*query_hook) PARAMS (());
@@ -884,6 +854,8 @@ extern int (*target_wait_hook) PARAMS ((int pid,
extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
char *cmd, int from_tty));
+extern NORETURN void (*error_hook) PARAMS (());
+
/* Inhibit window interface if non-zero. */
extern int use_windows;
diff --git a/gdb/gdbtk.c b/gdb/gdbtk.c
index 290ed64..4acf0f4 100644
--- a/gdb/gdbtk.c
+++ b/gdb/gdbtk.c
@@ -31,6 +31,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
+#include <setjmp.h>
+#include "top.h"
/* Non-zero means that we're doing the gdbtk interface. */
int gdbtk = 0;
@@ -53,6 +55,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);
+
+ if (len <= saved_output_buf_free)
+ {
+ strcpy (saved_output_data_end, ptr);
+ saved_output_data_end += len;
+ saved_output_buf_free -= len;
+ return;
+ }
+
+ data_len = saved_output_data_end - saved_output_buf;
+ needed = (data_len + len + 1) * 2;
+
+ if (saved_output_buf == saved_output_static_buf)
+ {
+ char *tmp;
+
+ tmp = xmalloc (needed);
+ strcpy (tmp, saved_output_buf);
+ saved_output_buf = tmp;
+ }
+ else
+ saved_output_buf = xrealloc (saved_output_buf, needed);
+
+ saved_output_data_end = saved_output_buf + data_len;
+ saved_output_buf_free = (needed - data_len) - 1;
+
+ save_output (ptr);
+}
+
+#define get_saved_output() saved_output_buf
+
+static void
+finish_saving_output ()
+{
+ if (saved_output_buf != saved_output_static_buf)
+ free (saved_output_buf);
+
+ saved_output_buf = NULL;
+}
/* This routine redirects the output of fputs_unfiltered so that
the user can see what's going on in his debugger window. */
@@ -76,17 +142,37 @@ static void
gdbtk_flush (stream)
FILE *stream;
{
+ if (stream != gdb_stdout || saved_output_buf)
+ return;
+
+ /* Flush output from C to tcl land. */
+
flush_holdbuf ();
+ /* Force immediate screen update */
+
Tcl_VarEval (interp, "gdbtk_tcl_flush", NULL);
}
static void
-gdbtk_fputs (ptr)
+gdbtk_fputs (ptr, stream)
const char *ptr;
+ FILE *stream;
{
int len;
+ if (stream != gdb_stdout)
+ {
+ Tcl_VarEval (interp, "gdbtk_tcl_fputs_error ", "{", ptr, "}", NULL);
+ return;
+ }
+
+ if (saved_output_buf)
+ {
+ save_output (ptr);
+ return;
+ }
+
len = strlen (ptr) + 1;
if (len > holdfree)
@@ -122,43 +208,6 @@ gdbtk_query (args)
return val;
}
-#if 0
-static char *
-full_filename(symtab)
- struct symtab *symtab;
-{
- int pathlen;
- char *filename;
-
- if (!symtab)
- return NULL;
-
- if (symtab->fullname)
- return savestring(symtab->fullname, strlen(symtab->fullname));
-
- if (symtab->filename[0] == '/')
- return savestring(symtab->filename, strlen(symtab->filename));
-
- if (symtab->dirname)
- pathlen = strlen(symtab->dirname);
- else
- pathlen = 0;
- if (symtab->filename)
- pathlen += strlen(symtab->filename);
-
- filename = xmalloc(pathlen+1);
-
- if (symtab->dirname)
- strcpy(filename, symtab->dirname);
- else
- *filename = '\000';
- if (symtab->filename)
- strcat(filename, symtab->filename);
-
- return filename;
-}
-#endif
-
static void
breakpoint_notify(b, action)
struct breakpoint *b;
@@ -420,22 +469,6 @@ gdb_regnames (clientData, interp, argc, argv)
return map_arg_registers (argc, argv, get_register_name, 0);
}
-static char reg_value[200];
-static char *reg_valp = reg_value;
-
-static void
-save_reg_value (ptr)
- const char *ptr;
-{
- int len;
-
- len = strlen (ptr);
-
- strncpy (reg_valp, ptr, len + 1);
-
- reg_valp += len;
-}
-
#ifndef REGISTER_CONVERTIBLE
#define REGISTER_CONVERTIBLE(x) (0 != 0)
#endif
@@ -462,9 +495,7 @@ get_register (regnum, fp)
return;
}
- fputs_unfiltered_hook = save_reg_value;
- flush_hook = 0;
- reg_valp = reg_value;
+ start_saving_output (); /* Start collecting stdout */
/* Convert raw data to virtual format if necessary. */
@@ -479,10 +510,9 @@ get_register (regnum, fp)
val_print (REGISTER_VIRTUAL_TYPE (regnum), virtual_buffer, 0,
gdb_stdout, format, 1, 0, Val_pretty_default);
- fputs_unfiltered_hook = gdbtk_fputs;
- flush_hook = gdbtk_flush;
+ Tcl_AppendElement (interp, get_saved_output ());
- Tcl_AppendElement (interp, reg_value);
+ finish_saving_output (); /* Set stdout back to normal */
}
static int
@@ -552,15 +582,6 @@ gdb_changed_register_list (clientData, interp, argc, argv)
return map_arg_registers (argc, argv, register_changed_p, NULL);
}
-static int
-gdb_cmd_stub (cmd)
- char *cmd;
-{
- execute_command (cmd, 1);
-
- return 1; /* Indicate success */
-}
-
/* This implements the TCL command `gdb_cmd', which sends it's argument into
the GDB command scanner. */
@@ -571,40 +592,72 @@ gdb_cmd (clientData, interp, argc, argv)
int argc;
char *argv[];
{
- int val;
- struct cleanup *old_chain;
-
if (argc != 2)
{
Tcl_SetResult (interp, "wrong # args", TCL_STATIC);
return TCL_ERROR;
}
- old_chain = make_cleanup (null_routine, 0);
-
- val = catch_errors (gdb_cmd_stub, argv[1], "", RETURN_MASK_ERROR);
-
- /* In case of an error, we may need to force the GUI into idle mode because
- gdbtk_call_command may have bombed out while in the command routine. */
-
- if (val == 0)
- Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
+ execute_command (argv[1], 1);
bpstat_do_actions (&stop_bpstat);
- do_cleanups (old_chain);
/* Drain all buffered command output */
- gdb_flush (gdb_stderr);
gdb_flush (gdb_stdout);
- /* We could base the return value on val, but that would require most users
- to use catch. Since GDB errors are already being handled elsewhere, I
- see no reason to pass them up to the caller. */
-
return TCL_OK;
}
+/* This routine acts as a top-level for all GDB code called by tcl/Tk. It
+ handles cleanups, and calls to return_to_top_level (usually via error).
+ This is necessary in order to prevent a longjmp out of the bowels of Tk,
+ possibly leaving things in a bad state. Since this routine can be called
+ recursively, it needs to save and restore the contents of the jmp_buf as
+ necessary. */
+
+static int
+call_wrapper (clientData, interp, argc, argv)
+ ClientData clientData;
+ Tcl_Interp *interp;
+ int argc;
+ char *argv[];
+{
+ int val;
+ struct cleanup *saved_cleanup_chain;
+ Tcl_CmdProc *func;
+ jmp_buf saved_error_return;
+
+ func = (Tcl_CmdProc *)clientData;
+ memcpy (saved_error_return, error_return, sizeof (jmp_buf));
+
+ saved_cleanup_chain = save_cleanups ();
+
+ if (!setjmp (error_return))
+ val = func (clientData, interp, argc, argv);
+ else
+ {
+ val = TCL_ERROR; /* Flag an error for TCL */
+
+ finish_saving_output (); /* Restore stdout to normal */
+
+ gdb_flush (gdb_stderr); /* Flush error output */
+
+/* In case of an error, we may need to force the GUI into idle mode because
+ gdbtk_call_command may have bombed out while in the command routine. */
+
+ Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
+ }
+
+ do_cleanups (ALL_CLEANUPS);
+
+ restore_cleanups (saved_cleanup_chain);
+
+ memcpy (error_return, saved_error_return, sizeof (jmp_buf));
+
+ return val;
+}
+
static int
gdb_listfiles (clientData, interp, argc, argv)
ClientData clientData;
@@ -740,16 +793,18 @@ gdbtk_init ()
if (Tk_Init(interp) != TCL_OK)
error ("Tk_Init failed: %s", interp->result);
- Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
- Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
- Tcl_CreateCommand (interp, "gdb_sourcelines", gdb_sourcelines, NULL, NULL);
- Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
- Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
- Tcl_CreateCommand (interp, "gdb_regnames", gdb_regnames, NULL, NULL);
- Tcl_CreateCommand (interp, "gdb_fetch_registers", gdb_fetch_registers, NULL,
+ Tcl_CreateCommand (interp, "gdb_cmd", call_wrapper, gdb_cmd, NULL);
+ Tcl_CreateCommand (interp, "gdb_loc", call_wrapper, gdb_loc, NULL);
+ Tcl_CreateCommand (interp, "gdb_sourcelines", call_wrapper, gdb_sourcelines,
+ NULL);
+ Tcl_CreateCommand (interp, "gdb_listfiles", call_wrapper, gdb_listfiles,
NULL);
- Tcl_CreateCommand (interp, "gdb_changed_register_list",
- gdb_changed_register_list, NULL, NULL);
+ Tcl_CreateCommand (interp, "gdb_stop", call_wrapper, gdb_stop, NULL);
+ Tcl_CreateCommand (interp, "gdb_regnames", call_wrapper, gdb_regnames, NULL);
+ Tcl_CreateCommand (interp, "gdb_fetch_registers", call_wrapper,
+ gdb_fetch_registers, NULL);
+ Tcl_CreateCommand (interp, "gdb_changed_register_list", call_wrapper,
+ gdb_changed_register_list, NULL);
gdbtk_filename = getenv ("GDBTK_FILENAME");
if (!gdbtk_filename)
diff --git a/gdb/gdbtk.tcl b/gdb/gdbtk.tcl
index 97fec0e..f8ce86c 100644
--- a/gdb/gdbtk.tcl
+++ b/gdb/gdbtk.tcl
@@ -8,6 +8,8 @@ set screen_top 0
set screen_bot 0
set current_output_win .cmd.text
set cfunc NIL
+set line_numbers 1
+
#option add *Foreground Black
#option add *Background White
#option add *Font -*-*-medium-r-normal--18-*-*-*-m-*-*-1
@@ -46,6 +48,11 @@ proc gdbtk_tcl_fputs {arg} {
$current_output_win yview -pickplace end
}
+proc gdbtk_tcl_fputs_error {arg} {
+ .cmd.text insert end "$arg"
+ .cmd.text yview -pickplace end
+}
+
#
# GDB Callback:
#
@@ -354,43 +361,52 @@ proc delete_breakpoint_tag {win line} {
}
proc gdbtk_tcl_busy {} {
- .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
- .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
+ 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
+ }
+ 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
+ }
}
proc gdbtk_tcl_idle {} {
- .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
- .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
+ 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
+ }
+
+ 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
+ }
}
#
@@ -732,6 +748,7 @@ proc display_expression {expression} {
proc create_file_win {filename debug_file} {
global breakpoint_file
global breakpoint_line
+ global line_numbers
# Replace all the dirty characters in $filename with clean ones, and generate
# a unique name for the text widget.
@@ -767,25 +784,32 @@ proc create_file_win {filename debug_file} {
bind $win <1> do_nothing
bind $win <B1-Motion> do_nothing
- bind $win n {gdb_cmd next ; update_ptr}
- bind $win s {gdb_cmd step ; update_ptr}
- bind $win c {gdb_cmd continue ; update_ptr}
- bind $win f {gdb_cmd finish ; update_ptr}
- bind $win u {gdb_cmd up ; update_ptr}
- bind $win d {gdb_cmd down ; update_ptr}
+ bind $win n {catch {gdb_cmd next} ; update_ptr}
+ bind $win s {catch {gdb_cmd step} ; update_ptr}
+ bind $win c {catch {gdb_cmd continue} ; update_ptr}
+ bind $win f {catch {gdb_cmd finish} ; update_ptr}
+ bind $win u {catch {gdb_cmd up} ; update_ptr}
+ bind $win d {catch {gdb_cmd down} ; update_ptr}
$win delete 0.0 end
$win insert 0.0 [read $fh]
close $fh
-# Add margins (for annotations) and a line number to each line
+# Add margins (for annotations) and a line number to each line (if requested)
set numlines [$win index end]
set numlines [lindex [split $numlines .] 0]
- for {set i 1} {$i <= $numlines} {incr i} {
- $win insert $i.0 [format " %4d " $i]
- $win tag add source $i.8 "$i.0 lineend"
- }
+ if $line_numbers {
+ for {set i 1} {$i <= $numlines} {incr i} {
+ $win insert $i.0 [format " %4d " $i]
+ $win tag add source $i.8 "$i.0 lineend"
+ }
+ } else {
+ for {set i 1} {$i <= $numlines} {incr i} {
+ $win insert $i.0 " "
+ $win tag add source $i.8 "$i.0 lineend"
+ }
+ }
# Add the breakdots
@@ -873,12 +897,12 @@ proc create_asm_win {funcname pc} {
bind $win <Enter> {focus %W}
bind $win <1> {asm_window_button_1 %W %X %Y %x %y}
bind $win <B1-Motion> do_nothing
- bind $win n {gdb_cmd nexti ; update_ptr}
- bind $win s {gdb_cmd stepi ; update_ptr}
- bind $win c {gdb_cmd continue ; update_ptr}
- bind $win f {gdb_cmd finish ; update_ptr}
- bind $win u {gdb_cmd up ; update_ptr}
- bind $win d {gdb_cmd down ; update_ptr}
+ bind $win n {catch {gdb_cmd nexti} ; update_ptr}
+ bind $win s {catch {gdb_cmd stepi} ; update_ptr}
+ bind $win c {catch {gdb_cmd continue} ; update_ptr}
+ bind $win f {catch {gdb_cmd finish} ; update_ptr}
+ bind $win u {catch {gdb_cmd up} ; update_ptr}
+ bind $win d {catch {gdb_cmd down} ; update_ptr}
# Disassemble the code, and read it into the new text widget
@@ -1090,23 +1114,23 @@ proc create_asm_window {} {
frame .asm.row2
button .asm.stepi -width 6 -text Stepi \
- -command {gdb_cmd stepi ; update_ptr}
+ -command {catch {gdb_cmd stepi} ; update_ptr}
button .asm.nexti -width 6 -text Nexti \
- -command {gdb_cmd nexti ; update_ptr}
+ -command {catch {gdb_cmd nexti} ; update_ptr}
button .asm.continue -width 6 -text Cont \
- -command {gdb_cmd continue ; update_ptr}
+ -command {catch {gdb_cmd continue} ; update_ptr}
button .asm.finish -width 6 -text Finish \
- -command {gdb_cmd finish ; update_ptr}
- button .asm.up -width 6 -text Up -command {gdb_cmd up ; update_ptr}
+ -command {catch {gdb_cmd finish} ; update_ptr}
+ button .asm.up -width 6 -text Up -command {catch {gdb_cmd up} ; update_ptr}
button .asm.down -width 6 -text Down \
- -command {gdb_cmd down ; update_ptr}
+ -command {catch {gdb_cmd down} ; update_ptr}
button .asm.bottom -width 6 -text Bottom \
- -command {gdb_cmd {frame 0} ; update_ptr}
+ -command {catch {gdb_cmd {frame 0}} ; update_ptr}
pack .asm.stepi .asm.continue .asm.up .asm.bottom -side left -padx 3 -pady 5 -in .asm.row1
pack .asm.nexti .asm.finish .asm.down -side left -padx 3 -pady 5 -in .asm.row2
- pack .asm.row1 .asm.row2 -side top -anchor w
+ pack .asm.row2 .asm.row1 -side bottom -anchor w -before .asm.info
update
@@ -1127,9 +1151,23 @@ proc reg_config_menu {} {
set regnames [gdb_regnames]
set num_regs [llength $regnames]
- button .reg.config.done -text Done -command {destroy .reg.config}
+ frame .reg.config.buts
+
+ button .reg.config.done -text " Done " -command "
+ recompute_reg_display_list $num_regs
+ populate_reg_window
+ update_registers all
+ destroy .reg.config "
+
+ button .reg.config.update -text Update -command "
+ recompute_reg_display_list $num_regs
+ populate_reg_window
+ update_registers all "
+
+ pack .reg.config.buts -side bottom -fill x
- pack .reg.config.done -side bottom -fill x
+ pack .reg.config.done -side left -fill x -expand yes -in .reg.config.buts
+ pack .reg.config.update -side right -fill x -expand yes -in .reg.config.buts
# Since there can be lots of registers, we build the window with no more than
# 32 rows, and as many columns as needed.
@@ -1151,10 +1189,7 @@ proc reg_config_menu {} {
for {set regnum 0} {$regnum < $num_regs} {incr regnum} {
set regname [lindex $regnames $regnum]
checkbutton .reg.config.col$col.$row -text $regname -pady 0 \
- -variable regena($regnum) -relief flat -anchor w -bd 1 \
- -command "recompute_reg_display_list $num_regs
- populate_reg_window
- update_registers all"
+ -variable regena($regnum) -relief flat -anchor w -bd 1
pack .reg.config.col$col.$row -side top -fill both
@@ -1199,44 +1234,38 @@ proc create_registers_window {} {
build_framework .reg Registers
- .reg.menubar.view.menu add command -label Natural
- .reg.menubar.view.menu add command -label Config -command {
- reg_config_menu }
+# First, delete all the old menu entries
+
+ .reg.menubar.view.menu delete 0 last
# Hex menu item
- .reg.menubar.view.menu entryconfigure 0 -command {
- global reg_format
+ .reg.menubar.view.menu add radiobutton -variable reg_format \
+ -label Hex -value x -command {update_registers all}
- set reg_format x
- update_registers all
- }
# Decimal menu item
- .reg.menubar.view.menu entryconfigure 1 -command {
- global reg_format
+ .reg.menubar.view.menu add radiobutton -variable reg_format \
+ -label Decimal -value d -command {update_registers all}
- set reg_format d
- update_registers all
- }
# Octal menu item
- .reg.menubar.view.menu entryconfigure 2 -command {
- global reg_format
+ .reg.menubar.view.menu add radiobutton -variable reg_format \
+ -label Octal -value o -command {update_registers all}
- set reg_format o
- update_registers all
- }
# Natural menu item
- .reg.menubar.view.menu entryconfigure 3 -command {
- global reg_format
+ .reg.menubar.view.menu add radiobutton -variable reg_format \
+ -label Natural -value {} -command {update_registers all}
- set reg_format {}
- update_registers all
- }
+# Config menu item
+ .reg.menubar.view.menu add separator
+
+ .reg.menubar.view.menu add command -label Config -command {
+ reg_config_menu }
destroy .reg.label
# Install the reg names
populate_reg_window
+ update_registers all
}
# Convert regena into a list of the enabled $regnums
@@ -1534,7 +1563,7 @@ proc build_framework {win {title GDBtk} {label {}}} {
${win}.menubar.file.menu add command -label Close \
-command "destroy ${win}"
${win}.menubar.file.menu add command -label Quit \
- -command {gdb_cmd quit}
+ -command {catch {gdb_cmd quit}}
menubutton ${win}.menubar.view -padx 12 -text View \
-menu ${win}.menubar.view.menu -underline 0
@@ -1598,36 +1627,53 @@ proc create_source_window {} {
build_framework .src Source "*No file*"
+# First, delete all the old view menu entries
+
+ .src.menubar.view.menu delete 0 last
+
+# Line numbers enable/disable menu item
+ .src.menubar.view.menu add checkbutton -variable line_numbers \
+ -label "Line numbers" -onvalue 1 -offvalue 0 -command {
+ foreach source [array names wins] {
+ if {$source == "Blank"} continue
+ destroy $wins($source)
+ unset wins($source)
+ }
+ set cfile Blank
+ update_listing [gdb_loc]
+ }
+
frame .src.row1
frame .src.row2
button .src.start -width 6 -text Start -command \
- {gdb_cmd {break main}
- gdb_cmd {enable delete $bpnum}
- gdb_cmd run
+ {catch {gdb_cmd {break main}}
+ catch {gdb_cmd {enable delete $bpnum}}
+ catch {gdb_cmd run}
update_ptr }
button .src.stop -width 6 -text Stop -fg red -activeforeground red \
-state disabled -command gdb_stop
button .src.step -width 6 -text Step \
- -command {gdb_cmd step ; update_ptr}
+ -command {catch {gdb_cmd step} ; update_ptr}
button .src.next -width 6 -text Next \
- -command {gdb_cmd next ; update_ptr}
+ -command {catch {gdb_cmd next} ; update_ptr}
button .src.continue -width 6 -text Cont \
- -command {gdb_cmd continue ; update_ptr}
+ -command {catch {gdb_cmd continue} ; update_ptr}
button .src.finish -width 6 -text Finish \
- -command {gdb_cmd finish ; update_ptr}
- button .src.up -width 6 -text Up -command {gdb_cmd up ; update_ptr}
+ -command {catch {gdb_cmd finish} ; update_ptr}
+ button .src.up -width 6 -text Up \
+ -command {catch {gdb_cmd up} ; update_ptr}
button .src.down -width 6 -text Down \
- -command {gdb_cmd down ; update_ptr}
+ -command {catch {gdb_cmd down} ; update_ptr}
button .src.bottom -width 6 -text Bottom \
- -command {gdb_cmd {frame 0} ; update_ptr}
+ -command {catch {gdb_cmd {frame 0}} ; update_ptr}
pack .src.start .src.step .src.continue .src.up .src.bottom \
-side left -padx 3 -pady 5 -in .src.row1
pack .src.stop .src.next .src.finish .src.down -side left -padx 3 \
-pady 5 -in .src.row2
- pack .src.row1 .src.row2 -side top -anchor w
+ pack .src.row2 .src.row1 -side bottom -anchor w -before .src.info
$wins($cfile) insert 0.0 " This page intentionally left blank."
$wins($cfile) configure -width 88 -state disabled \
@@ -1667,7 +1713,7 @@ proc create_command_window {} {
%W insert end \n
%W yview -pickplace end
- gdb_cmd $command_line
+ catch "gdb_cmd {$command_line}"
set command_line {}
update_ptr
%W insert end "(gdb) "
diff --git a/gdb/main.c b/gdb/main.c
index e7c8070..228d62c 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -41,6 +41,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif
/* Temporary variable for SET_TOP_LEVEL. */
+
static int top_level_val;
/* Do a setjmp on error_return and quit_return. catch_errors is
@@ -52,6 +53,14 @@ static int top_level_val;
? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (jmp_buf))) \
, top_level_val)
+/* If nonzero, display time usage both at startup and for each command. */
+
+int display_time;
+
+/* If nonzero, display space usage both at startup and for each command. */
+
+int display_space;
+
extern void gdb_init PARAMS ((void));
int
@@ -93,6 +102,8 @@ main (argc, argv)
register int i;
+ long time_at_startup = get_run_time ();
+
/* start-sanitize-mpw */
#ifdef MPW
/* Drop into MacsBug, but only if the executable is specially named. */
@@ -174,13 +185,16 @@ main (argc, argv)
{"tty", required_argument, 0, 't'},
{"baud", required_argument, 0, 'b'},
{"b", required_argument, 0, 'b'},
- {"nw", no_argument, &no_windows, 1},
- {"nowindows", no_argument, &no_windows, 1},
+ {"nw", no_argument, &use_windows, 0},
+ {"nowindows", no_argument, &use_windows, 0},
+ {"w", no_argument, &use_windows, 1},
+ {"windows", no_argument, &use_windows, 1},
+ {"statistics", no_argument, 0, 13},
/* Allow machine descriptions to add more options... */
#ifdef ADDITIONAL_OPTIONS
ADDITIONAL_OPTIONS
#endif
- {0, no_argument, 0, 0},
+ {0, no_argument, 0, 0}
};
while (1)
@@ -212,6 +226,11 @@ main (argc, argv)
/* FIXME: what if the syntax is wrong (e.g. not digits)? */
annotation_level = atoi (optarg);
break;
+ case 13:
+ /* Enable the display of both time and space usage. */
+ display_time = 1;
+ display_space = 1;
+ break;
case 'f':
annotation_level = 1;
break;
@@ -522,6 +541,25 @@ GDB manual (available as on-line info or a printed manual).\n", gdb_stdout);
BEFORE_MAIN_LOOP_HOOK;
#endif
+ /* Show time and/or space usage. */
+
+ if (display_time)
+ {
+ long init_time = get_run_time () - time_at_startup;
+
+ printf_unfiltered ("Startup time: %ld.%06ld\n",
+ init_time / 1000000, init_time % 1000000);
+ }
+
+ if (display_space)
+ {
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+
+ printf_unfiltered ("Startup size: data size %ld\n",
+ (long) (lim - (char *) &environ));
+ }
+
/* The command loop. */
while (1)
@@ -570,7 +608,12 @@ fputs_unfiltered (linebuffer, stream)
{
if (fputs_unfiltered_hook)
{
- fputs_unfiltered_hook (linebuffer);
+ /* FIXME: I think we should only be doing this for stdout or stderr.
+ Either that or we should be passing stream to the hook so it can
+ deal with it. If that is cleaned up, this function can go back
+ into utils.c and the fputs_unfiltered_hook can replace the current
+ ability to avoid this function by not linking with main.c. */
+ fputs_unfiltered_hook (linebuffer, stream);
return;
}
diff --git a/gdb/top.c b/gdb/top.c
index 17e85c0..8109f51 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -354,7 +354,7 @@ void (*command_loop_hook) PARAMS ((void));
/* Called instead of fputs for all output. */
-void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer));
+void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream));
/* Called from print_frame_info to list the line we stopped in. */
@@ -391,6 +391,12 @@ int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
int from_tty));
+
+/* Takes control from error (). Typically used to prevent longjmps out of the
+ middle of the GUI. Usually used in conjunction with a catch routine. */
+
+NORETURN void (*error_hook) PARAMS (());
+
/* Where to go for return_to_top_level (RETURN_ERROR). */
jmp_buf error_return;