* defs.h, gdbtk.c (gdbtk_fputs), main.c (gdb_fputs), top.c: Add stream arg
authorStu Grossman <grossman@cygnus>
Fri, 16 Dec 1994 01:07:35 +0000 (01:07 +0000)
committerStu Grossman <grossman@cygnus>
Fri, 16 Dec 1994 01:07:35 +0000 (01:07 +0000)
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.

gdb/ChangeLog
gdb/defs.h
gdb/gdbtk.c
gdb/gdbtk.tcl
gdb/main.c
gdb/top.c

index a8e98c6ab4e36179da207fc36e1e4147f9f2f8eb..70c689b0de292f62162ecc06fba0997a630a1b21 100644 (file)
@@ -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
index a0721ef2639a01ec2b2b0bba43bd268660169dbb..835f877a516eff0ab78249c8795a9892d98dc8e4 100644 (file)
@@ -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;
index 290ed644f18678d4fe82a25bd20e55ade897ae1a..4acf0f4aea0bc97797c979808dbbce200ad04fc5 100644 (file)
@@ -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;
+}
 \f
 /* 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;
 }
 \f
-#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
-\f
 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);
 }
 \f
-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)
index 97fec0eba0dc96f02e19eb151ea8033da8143e07..f8ce86c8ec35e1060dd9e4c61139d512e194694c 100644 (file)
@@ -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) "
index e7c8070a1cd408d2c2b9bd547ceb26f9eccf568a..228d62ce0c1b4494a6e4be69e22651293ea7f236 100644 (file)
@@ -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;
     }
 
index 17e85c02361332b5a474c7915546c0bc155563da..8109f516063aeddac3dad50f169fd96c314c8975 100644 (file)
--- 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 (());
+
 \f
 /* Where to go for return_to_top_level (RETURN_ERROR).  */
 jmp_buf error_return;