]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* defs.h, infrun.c (wait_for_inferior), top.c: Call
authorStu Grossman <grossman@cygnus>
Fri, 21 Oct 1994 00:59:20 +0000 (00:59 +0000)
committerStu Grossman <grossman@cygnus>
Fri, 21 Oct 1994 00:59:20 +0000 (00:59 +0000)
target_wait_hook to allow GUI to handle blocking for inferior.  Call
call_command_hook in execute_command to provide means for wrapping
commands with GUI state change updates.
* gdbtk.c (gdb_cmd):  Force GUI into idle mode when errors occur.
* (gdb_stop):  New tcl command to stop the target process.
* (x_event, gdbtk_wait):  Allow GUI to interrupt gdb out of target
waits.
* (gdbtk_call_command):  Wrapper around command processing to
alert GUI of target state changes.
* (gdbtk_init):  Get the fd of X server for doing async
notification of X events (via x_event).  Setup new hooks.
* gdbtk.tcl:  Add scrollbars to assembly and command windows.
* Change window foreground & background colors.
* Create margin tag for breakpoints in source and assembly windows.
* Add new routines to be invoked when target state changes to/from
idle.
* Add start of expression window.
* Change bindings of mouse button 1 in assembly and source window
to just set or clear breakpoints when in the margin tag.
* Change shape of register window to be more vertical to better
reflect it's contents.
* Add stop button.
* Cleanup some code around command window bindings.

* infrun.c (wait_for_inferior):  Make sure
through_sigtramp_breakpoint is non-null before deleting.

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

index aabc9712b5741bf6c7bfcad22e91943e7f25fe9b..55931d563fb131e72d3a85fcb45e10be5150b8f2 100644 (file)
@@ -1,3 +1,33 @@
+Thu Oct 20 17:35:45 1994  Stu Grossman  (grossman@cygnus.com)
+
+       * defs.h, infrun.c (wait_for_inferior), top.c:  Call
+       target_wait_hook to allow GUI to handle blocking for inferior.  Call
+       call_command_hook in execute_command to provide means for wrapping
+       commands with GUI state change updates.
+       * gdbtk.c (gdb_cmd):  Force GUI into idle mode when errors occur.
+       * (gdb_stop):  New tcl command to stop the target process.
+       * (x_event, gdbtk_wait):  Allow GUI to interrupt gdb out of target
+       waits.
+       * (gdbtk_call_command):  Wrapper around command processing to
+       alert GUI of target state changes.
+       * (gdbtk_init):  Get the fd of X server for doing async
+       notification of X events (via x_event).  Setup new hooks.
+       * gdbtk.tcl:  Add scrollbars to assembly and command windows.
+       * Change window foreground & background colors.
+       * Create margin tag for breakpoints in source and assembly windows.
+       * Add new routines to be invoked when target state changes to/from
+       idle.
+       * Add start of expression window.
+       * Change bindings of mouse button 1 in assembly and source window
+       to just set or clear breakpoints when in the margin tag.
+       * Change shape of register window to be more vertical to better
+       reflect it's contents.
+       * Add stop button.
+       * Cleanup some code around command window bindings.
+
+       * infrun.c (wait_for_inferior):  Make sure
+       through_sigtramp_breakpoint is non-null before deleting.
+
 Thu Oct 20 10:26:43 1994  J.T. Conklin  (jtc@phishhead.cygnus.com)
 
        * config/powerpc/ppc-nw.mt (TDEPFILES): Removed exec.o.
index ada622338f67eded3e2e78826506491b933c374c..1bba0bdbc6f4c47593407e9974c35d4c5ae2842c 100644 (file)
@@ -689,7 +689,7 @@ extern char *strerror PARAMS ((int));                       /* 4.11.6.2 */
 # endif /* Not GNU C */
 #endif /* alloca not defined */
 
-/* TARGET_BYTE_ORDER and HOST_BYTE_ORDER must be defined to one of these.  */
+/* HOST_BYTE_ORDER must be defined to one of these.  */
 
 #if !defined (BIG_ENDIAN)
 #define BIG_ENDIAN 4321
@@ -706,6 +706,17 @@ extern char *strerror PARAMS ((int));                      /* 4.11.6.2 */
 
 #include "tm.h"
 
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+/* The target endianness is selectable at runtime.  Define
+   TARGET_BYTE_ORDER to be a variable.  The user can use the `set
+   endian' command to change it.  */
+#undef TARGET_BYTE_ORDER
+#define TARGET_BYTE_ORDER target_byte_order
+extern int target_byte_order;
+#endif
+
+extern void set_endian_from_file PARAMS ((bfd *));
+
 /* Number of bits in a char or unsigned char for the target machine.
    Just like CHAR_BIT in <limits.h> but describes the target machine.  */
 #if !defined (TARGET_CHAR_BIT)
@@ -778,6 +789,8 @@ extern char *strerror PARAMS ((int));                       /* 4.11.6.2 */
    from byte/word byte order.  */
 
 #if !defined (BITS_BIG_ENDIAN)
+#ifndef TARGET_BYTE_ORDER_SELECTABLE
+
 #if TARGET_BYTE_ORDER == BIG_ENDIAN
 #define BITS_BIG_ENDIAN 1
 #endif /* Big endian.  */
@@ -785,6 +798,12 @@ extern char *strerror PARAMS ((int));                      /* 4.11.6.2 */
 #if TARGET_BYTE_ORDER == LITTLE_ENDIAN
 #define BITS_BIG_ENDIAN 0
 #endif /* Little endian.  */
+
+#else /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
+
+#define BITS_BIG_ENDIAN (TARGET_BYTE_ORDER == BIG_ENDIAN)
+
+#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
 #endif /* BITS_BIG_ENDIAN not defined.  */
 
 /* In findvar.c.  */
@@ -854,6 +873,17 @@ extern void (*enable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
 extern void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
 extern void (*interactive_hook) PARAMS ((void));
 
+#ifdef __STDC__
+struct target_waitstatus;
+struct cmd_list_element;
+#endif
+
+extern int (*target_wait_hook) PARAMS ((int pid,
+                                       struct target_waitstatus *status));
+
+extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
+                                         char *cmd, int from_tty));
+
 /* Inhibit window interface if non-zero. */
 
 extern int no_windows;
index 9843b430774de0ce7192e06e9d40b86998f1408b..e96ea19d1d555989e8ef9ec9e0a402fb6cf37f6e 100644 (file)
@@ -54,6 +54,8 @@ static Tcl_Interp *interp = NULL;
 /* Handle for TK main window */
 static Tk_Window mainWindow = NULL;
 
+static int x_fd;               /* X network socket */
+
 static void
 null_routine(arg)
      int arg;
@@ -336,6 +338,12 @@ gdb_cmd (clientData, interp, argc, argv)
 
   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);
+
   bpstat_do_actions (&stop_bpstat);
   do_cleanups (old_chain);
 
@@ -367,6 +375,22 @@ gdb_listfiles (clientData, interp, argc, argv)
 
   return TCL_OK;
 }
+
+static int
+gdb_stop (clientData, interp, argc, argv)
+     ClientData clientData;
+     Tcl_Interp *interp;
+     int argc;
+     char *argv[];
+{
+  extern pid_t inferior_process_group;
+
+  /* XXX - This is WRONG for remote targets.  Probably need a target vector
+     entry to do this right.  */
+
+  kill (-inferior_process_group, SIGINT);
+}
+
 \f
 static void
 tk_command (cmd, from_tty)
@@ -401,11 +425,59 @@ gdbtk_interactive ()
   /* Tk_DoOneEvent (TK_DONT_WAIT|TK_IDLE_EVENTS); */
 }
 
+/* Come here when there is activity on the X file descriptor. */
+
+static void
+x_event (signo)
+     int signo;
+{
+  /* Process pending events */
+
+  while (Tk_DoOneEvent (TK_DONT_WAIT|TK_ALL_EVENTS) != 0);
+}
+
+static int
+gdbtk_wait (pid, ourstatus)
+     int pid;
+     struct target_waitstatus *ourstatus;
+{
+  signal (SIGIO, x_event);
+
+  pid = target_wait (pid, ourstatus);
+
+  signal (SIGIO, SIG_IGN);
+
+  return pid;
+}
+
+/* This is called from execute_command, and provides a wrapper around
+   various command routines in a place where both protocol messages and
+   user input both flow through.  Mostly this is used for indicating whether
+   the target process is running or not.
+*/
+
+static void
+gdbtk_call_command (cmdblk, arg, from_tty)
+     struct cmd_list_element *cmdblk;
+     char *arg;
+     int from_tty;
+{
+  if (cmdblk->class == class_run)
+    {
+      Tcl_VarEval (interp, "gdbtk_tcl_busy", NULL);
+      (*cmdblk->function.cfunc)(arg, from_tty);
+      Tcl_VarEval (interp, "gdbtk_tcl_idle", NULL);
+    }
+  else
+    (*cmdblk->function.cfunc)(arg, from_tty);
+}
+
 static void
 gdbtk_init ()
 {
   struct cleanup *old_chain;
   char *gdbtk_filename;
+  int i;
 
   old_chain = make_cleanup (cleanup_init, 0);
 
@@ -430,6 +502,7 @@ gdbtk_init ()
   Tcl_CreateCommand (interp, "gdb_cmd", gdb_cmd, NULL, NULL);
   Tcl_CreateCommand (interp, "gdb_loc", gdb_loc, NULL, NULL);
   Tcl_CreateCommand (interp, "gdb_listfiles", gdb_listfiles, NULL, NULL);
+  Tcl_CreateCommand (interp, "gdb_stop", gdb_stop, NULL, NULL);
 
   gdbtk_filename = getenv ("GDBTK_FILENAME");
   if (!gdbtk_filename)
@@ -441,6 +514,19 @@ gdbtk_init ()
   if (Tcl_EvalFile (interp, gdbtk_filename) != TCL_OK)
     error ("Failure reading %s: %s", gdbtk_filename, interp->result);
 
+  /* XXX - Get the file descriptor for the network socket.  This is not Kosher
+     as it involves looking at data private to Xlib.  */
+
+  x_fd = Tk_Display (mainWindow) -> fd;
+
+  /* Setup for I/O interrupts */
+
+  signal (SIGIO, SIG_IGN);
+
+  i = fcntl (x_fd, F_GETFL, 0);
+  fcntl (x_fd, F_SETFL, i|FASYNC);
+  fcntl (x_fd, F_SETOWN, getpid()); 
+
   command_loop_hook = Tk_MainLoop;
   fputs_unfiltered_hook = gdbtk_fputs;
   print_frame_info_listing_hook = null_routine;
@@ -451,6 +537,8 @@ gdbtk_init ()
   enable_breakpoint_hook = gdbtk_enable_breakpoint;
   disable_breakpoint_hook = gdbtk_disable_breakpoint;
   interactive_hook = gdbtk_interactive;
+  target_wait_hook = gdbtk_wait;
+  call_command_hook = gdbtk_call_command;
 
   discard_cleanups (old_chain);
 
index 9f52096e496314412fa3063f23caf2271836cc8d..08e7c4bc21b69b940601f33be1fea4355922c12d 100644 (file)
@@ -8,10 +8,8 @@ set screen_top 0
 set screen_bot 0
 set current_output_win .command.text
 set cfunc NIL
-
-proc test {} {
-       update_listing {termcap.c foo /etc/termcap 200}
-}
+option add *Foreground White
+option add *Background Blue
 
 proc echo string {puts stdout $string}
 
@@ -322,6 +320,8 @@ proc insert_breakpoint_tag {win line} {
        $win delete $line.0
        $win insert $line.0 "B"
        $win tag add $line $line.0
+       $win tag add delete $line.0 "$line.0 lineend"
+       $win tag add margin $line.0 "$line.0 lineend"
 
        $win configure -state disabled
 }
@@ -342,9 +342,57 @@ proc delete_breakpoint_tag {win line} {
        $win delete $line.0
        $win insert $line.0 " "
        $win tag delete $line
+       $win tag add delete $line.0 "$line.0 lineend"
+       $win tag add margin $line.0 "$line.0 lineend"
        $win configure -state disabled
 }
 
+proc gdbtk_tcl_busy {} {
+       .start configure -state disabled
+       .stop configure -state normal
+       .step configure -state disabled
+       .next configure -state disabled
+       .continue configure -state disabled
+       .finish configure -state disabled
+       .exit configure -state disabled
+       .up configure -state disabled
+       .down configure -state disabled
+       .bottom configure -state disabled
+       .asm_but configure -state disabled
+       .registers 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
+}
+
+proc gdbtk_tcl_idle {} {
+       .start configure -state normal
+       .stop configure -state disabled
+       .step configure -state normal
+       .next configure -state normal
+       .continue configure -state normal
+       .finish configure -state normal
+       .exit configure -state normal
+       .up configure -state normal
+       .down configure -state normal
+       .bottom configure -state normal
+       .asm_but configure -state normal
+       .registers 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
+}
+
 #
 # Local procedure:
 #
@@ -620,6 +668,49 @@ proc asm_window_button_1 {win x y xrel yrel} {
 
 proc do_nothing {} {}
 
+#
+# Local procedure:
+#
+#      create_expr_win - Creat expression display window
+#
+# Description:
+#
+#      Create the expression display window.
+#
+
+proc create_expr_win {} {
+       toplevel .expr
+       wm minsize .expr 1 1
+       wm title .expr Expression
+       canvas .expr.c -yscrollcommand {.expr.scroll set} -cursor hand2 \
+               -borderwidth 2 -relief groove
+       scrollbar .expr.scroll -orient vertical -command {.expr.c yview}
+       entry .expr.entry -borderwidth 2 -relief groove
+
+       pack .expr.entry -side bottom -fill x
+       pack .expr.c -side left -fill both -expand yes
+       pack .expr.scroll -side right -fill y
+
+       .expr.c create text 100 0 -text "Text string"
+       .expr.c create rectangle 245 195 255 205 -outline black -fill white
+}
+
+#
+# Local procedure:
+#
+#      display_expression (expression) - Display EXPRESSION in display window
+#
+# Description:
+#
+#      Display EXPRESSION and it's value in the expression display window.
+#
+
+proc display_expression {expression} {
+       if ![winfo exists .expr] {create_expr_win}
+
+
+}
+
 #
 # Local procedure:
 #
@@ -669,8 +760,10 @@ proc create_file_win {filename} {
 # Setup all the bindings
 
        bind $win <Enter> {focus %W}
-       bind $win <1> {listing_window_button_1 %W %X %Y %x %y}
+#      bind $win <1> {listing_window_button_1 %W %X %Y %x %y}
+       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}
@@ -688,7 +781,35 @@ proc create_file_win {filename} {
        set numlines [lindex [split $numlines .] 0]
        for {set i 1} {$i <= $numlines} {incr i} {
                $win insert $i.0 [format "   %4d " $i]
+               $win tag add margin $i.0 $i.8
+               $win tag add source $i.8 "$i.0 lineend"
+               }
+
+       $win tag bind margin <1> {listing_window_button_1 %W %X %Y %x %y}
+       $win tag bind source <1> {
+               %W mark set anchor "@%x,%y wordstart"
+               set last [%W index "@%x,%y wordend"]
+               %W tag remove sel 0.0 anchor
+               %W tag remove sel $last end
+               %W tag add sel anchor $last
+               }
+#      $win tag bind source <Double-Button-1> {
+#              %W mark set anchor "@%x,%y wordstart"
+#              set last [%W index "@%x,%y wordend"]
+#              %W tag remove sel 0.0 anchor
+#              %W tag remove sel $last end
+#              %W tag add sel anchor $last
+#              echo "Selected [selection get]"
+#              }
+       $win tag bind source <B1-Motion> {
+               %W tag remove sel 0.0 anchor
+               %W tag remove sel $last end
+               %W tag add sel anchor @%x,%y
                }
+       $win tag bind sel <1> do_nothing
+       $win tag bind sel <Double-Button-1> {display_expression [selection get]}
+       $win tag raise sel
+
 
 # Scan though the breakpoint data base and install any destined for this file
 
@@ -963,7 +1084,8 @@ proc asm_command {} {
                text $win -height 25 -width 80 -relief raised -borderwidth 2 \
                        -setgrid true -cursor hand2 \
                        -yscrollcommand asmscrollproc
-               scrollbar .asm.scroll -orient vertical -command {$win yview}
+               scrollbar .asm.scroll -orient vertical \
+                       -command {[asm_win_name $cfunc] yview}
                frame .asm.buts
 
                button .asm.stepi -text Stepi \
@@ -1011,7 +1133,7 @@ proc registers_command {} {
                wm title .reg Registers
                set win .reg.regs
 
-               text $win -height 25 -width 80 -relief raised \
+               text $win -height 41 -width 45 -relief raised \
                        -borderwidth 2 \
                        -setgrid true -cursor hand2
 
@@ -1044,7 +1166,7 @@ proc update_registers {} {
        gdb_cmd "info registers"
        set current_output_win .command.text
 
-       $win yview 1
+       $win yview 0
        $win configure -state disabled
 }
 
@@ -1209,6 +1331,7 @@ button .start -text Start -command \
         gdb_cmd {enable delete $bpnum}
         gdb_cmd run
         update_ptr }
+button .stop -text Stop -fg red -activeforeground red -state disabled -command gdb_stop
 button .step -text Step -command {gdb_cmd step ; update_ptr}
 button .next -text Next -command {gdb_cmd next ; update_ptr}
 button .continue -text Continue -command {gdb_cmd continue ; update_ptr}
@@ -1243,7 +1366,7 @@ button .files -text Files -command files_command
 
 pack .listing -side bottom -fill both -expand yes
 #pack .test -side bottom -fill x
-pack .start .step .next .continue .finish .up .down .bottom .asm_but \
+pack .start .stop .step .next .continue .finish .up .down .bottom .asm_but \
        .registers .files .exit -side left
 toplevel .command
 wm title .command Command
@@ -1251,10 +1374,12 @@ wm title .command Command
 # Setup command window
 
 label .command.label -text "* Command Buffer *" -borderwidth 2 -relief raised
-text .command.text -height 25 -width 80 -relief raised -borderwidth 2 -setgrid true -cursor hand2
+text .command.text -height 25 -width 80 -relief raised -borderwidth 2 -setgrid true -cursor hand2 -yscrollcommand {.command.scroll set}
+scrollbar .command.scroll -orient vertical -command {.command.text yview}
 
 pack .command.label -side top -fill x
-pack .command.text -side top -expand yes -fill both
+pack .command.text -side left -expand yes -fill both
+pack .command.scroll -side right -fill y
 
 set command_line {}
 
@@ -1262,6 +1387,10 @@ gdb_cmd {set language c}
 gdb_cmd {set height 0}
 gdb_cmd {set width 0}
 
+bind .command.text <Enter> {focus %W}
+bind .command.text <Delete> {delete_char %W}
+bind .command.text <BackSpace> {delete_char %W}
+bind .command.text <Control-u> {delete_line %W}
 bind .command.text <Any-Key> {
        global command_line
 
@@ -1280,10 +1409,7 @@ bind .command.text <Key-Return> {
        %W insert end "(gdb) "
        %W yview -pickplace end
        }
-bind .command.text <Enter> {focus %W}
-bind .command.text <Delete> {delete_char %W}
-bind .command.text <BackSpace> {delete_char %W}
-bind .command.text <Control-u> {delete_line %W}
+
 proc delete_char {win} {
        global command_line
 
index 9a9e35c7e0805e752dc46e37e3f8cbc8a4487803..fd3bf0aaad35e52fcb6ab6f89a12972f2b4d0247 100644 (file)
@@ -308,7 +308,7 @@ proceed (addr, siggnal, step)
      breakpoint to be hit again, but you can always continue, so it's not
      a big deal.)  */
 
-  if (! step && PREPARE_TO_PROCEED && breakpoint_here_p (read_pc ()))
+  if (! step && PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
     oneproc = 1;
 #endif /* PREPARE_TO_PROCEED */
 
@@ -362,10 +362,8 @@ The same program may be running in another process.");
    to be preserved over calls to it and cleared when the inferior
    is started.  */
 static CORE_ADDR prev_pc;
-static CORE_ADDR prev_sp;
 static CORE_ADDR prev_func_start;
 static char *prev_func_name;
-static CORE_ADDR prev_frame_address;
 
 \f
 /* Start remote-debugging of a machine over a serial link.  */
@@ -388,10 +386,8 @@ init_wait_for_inferior ()
 {
   /* These are meaningless until the first time through wait_for_inferior.  */
   prev_pc = 0;
-  prev_sp = 0;
   prev_func_start = 0;
   prev_func_name = NULL;
-  prev_frame_address = 0;
 
   trap_expected_after_continue = 0;
   breakpoints_inserted = 0;
@@ -423,7 +419,6 @@ wait_for_inferior ()
   struct target_waitstatus w;
   int another_trap;
   int random_signal;
-  CORE_ADDR stop_sp = 0;
   CORE_ADDR stop_func_start;
   CORE_ADDR stop_func_end;
   char *stop_func_name;
@@ -436,6 +431,7 @@ wait_for_inferior ()
   struct breakpoint *step_resume_breakpoint = NULL;
   struct breakpoint *through_sigtramp_breakpoint = NULL;
   int pid;
+  int update_step_sp = 0;
 
   old_cleanups = make_cleanup (delete_breakpoint_current_contents,
                               &step_resume_breakpoint);
@@ -462,7 +458,10 @@ wait_for_inferior ()
 
       registers_changed ();
 
-      pid = target_wait (-1, &w);
+      if (target_wait_hook)
+       pid = target_wait_hook (-1, &w);
+      else
+       pid = target_wait (-1, &w);
 
       flush_cached_frames ();
 
@@ -473,6 +472,17 @@ wait_for_inferior ()
        {
          fprintf_unfiltered (gdb_stderr, "[New %s]\n", target_pid_to_str (pid));
          add_thread (pid);
+
+         /* We may want to consider not doing a resume here in order to give
+            the user a chance to play with the new thread.  It might be good
+            to make that a user-settable option.  */
+
+         /* At this point, all threads are stopped (happens automatically in
+            either the OS or the native code).  Therefore we need to continue
+            all threads in order to make progress.  */
+
+         target_resume (-1, 0, TARGET_SIGNAL_0);
+         continue;
        }
 
       switch (w.kind)
@@ -498,8 +508,7 @@ wait_for_inferior ()
            printf_filtered ("\nProgram exited with code 0%o.\n", 
                             (unsigned int)w.value.integer);
          else
-           if (!batch_mode())
-             printf_filtered ("\nProgram exited normally.\n");
+           printf_filtered ("\nProgram exited normally.\n");
          gdb_flush (gdb_stdout);
          target_mourn_inferior ();
 #ifdef NO_SINGLE_STEP
@@ -559,7 +568,11 @@ wait_for_inferior ()
              target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
              /* FIXME: What if a signal arrives instead of the single-step
                 happening?  */
-             target_wait (pid, &w);
+
+             if (target_wait_hook)
+               target_wait_hook (pid, &w);
+             else
+               target_wait (pid, &w);
              insert_breakpoints ();
              target_resume (pid, 0, TARGET_SIGNAL_0);
              continue;
@@ -630,7 +643,6 @@ wait_for_inferior ()
              through_sigtramp_breakpoint = NULL;
            }
          prev_pc = 0;
-         prev_sp = 0;
          prev_func_name = NULL;
          step_range_start = 0;
          step_range_end = 0;
@@ -654,9 +666,6 @@ wait_for_inferior ()
          continue;
        }
 
-      set_current_frame (create_new_frame (read_fp (), stop_pc));
-      select_frame (get_current_frame (), 0);
-
 #ifdef HAVE_STEPPABLE_WATCHPOINT
       /* It may not be necessary to disable the watchpoint to stop over
         it.  For example, the PA can (with some kernel cooperation) 
@@ -696,8 +705,6 @@ wait_for_inferior ()
       STOPPED_BY_WATCHPOINT (w);
 #endif
 
-      stop_frame_address = FRAME_FP (get_current_frame ());
-      stop_sp = read_sp ();
       stop_func_start = 0;
       stop_func_name = 0;
       /* Don't care about return value; stop_func_start and stop_func_name
@@ -758,7 +765,7 @@ wait_for_inferior ()
            {
              /* See if there is a breakpoint at the current PC.  */
              stop_bpstat = bpstat_stop_status
-               (&stop_pc, stop_frame_address,
+               (&stop_pc,
 #if DECR_PC_AFTER_BREAK
                 /* Notice the case of stepping through a jump
                    that lands just after a breakpoint.
@@ -782,7 +789,8 @@ wait_for_inferior ()
              = !(bpstat_explains_signal (stop_bpstat)
                  || trap_expected
 #ifndef CALL_DUMMY_BREAKPOINT_OFFSET
-                 || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+                 || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+                                      FRAME_FP (get_current_frame ()))
 #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
                  || (step_range_end && step_resume_breakpoint == NULL));
          else
@@ -793,7 +801,8 @@ wait_for_inferior ()
                       news) give another signal besides SIGTRAP,
                       so check here as well as above.  */
 #ifndef CALL_DUMMY_BREAKPOINT_OFFSET
-                   || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+                   || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+                                        FRAME_FP (get_current_frame ()))
 #endif /* No CALL_DUMMY_BREAKPOINT_OFFSET.  */
                    );
              if (!random_signal)
@@ -904,7 +913,7 @@ wait_for_inferior ()
 #if 0
            /* FIXME - Need to implement nested temporary breakpoints */
            if (step_over_calls
-               && (stop_frame_address
+               && (FRAME_FP (get_current_frame ())
                    INNER_THAN step_frame_address))
              {
                another_trap = 1;
@@ -950,7 +959,8 @@ wait_for_inferior ()
            break;
 
          case BPSTAT_WHAT_THROUGH_SIGTRAMP:
-           delete_breakpoint (through_sigtramp_breakpoint);
+           if (through_sigtramp_breakpoint)
+             delete_breakpoint (through_sigtramp_breakpoint);
            through_sigtramp_breakpoint = NULL;
 
            /* If were waiting for a trap, hitting the step_resume_break
@@ -983,7 +993,7 @@ wait_for_inferior ()
         just stop silently, unless the user was doing an si/ni, in which
         case she'd better know what she's doing.  */
 
-      if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+      if (PC_IN_CALL_DUMMY (stop_pc, read_sp (), FRAME_FP (get_current_frame ()))
          && !step_range_end)
        {
          stop_print_frame = 0;
@@ -1017,17 +1027,21 @@ wait_for_inferior ()
             step range and either the stack or frame pointers
             just changed, we've stepped outside */
          && !(stop_pc == step_range_start
-              && stop_frame_address
-              && (stop_sp INNER_THAN prev_sp
-                  || stop_frame_address != step_frame_address)))
+              && FRAME_FP (get_current_frame ())
+              && (read_sp () INNER_THAN step_sp
+                  || FRAME_FP (get_current_frame ()) != step_frame_address)))
        {
          /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
             So definately need to check for sigtramp here.  */
          goto check_sigtramp2;
        }
 
-      /* We stepped out of the stepping range.  See if that was due
-        to a subroutine call that we should proceed to the end of.  */
+      /* We stepped out of the stepping range.  */
+
+      /* We can't update step_sp every time through the loop, because
+        reading the stack pointer would slow down stepping too much.
+        But we can update it every time we leave the step range.  */
+      update_step_sp = 1;
 
       /* Did we just take a signal?  */
       if (IN_SIGTRAMP (stop_pc, stop_func_name)
@@ -1052,8 +1066,7 @@ wait_for_inferior ()
            sr_sal.symtab = NULL;
            sr_sal.line = 0;
            /* We could probably be setting the frame to
-              prev_frame_address; the reason we don't is that it didn't used
-              to exist.  */
+              step_frame_address; I don't think anyone thought to try it.  */
            step_resume_breakpoint =
              set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
            if (breakpoints_inserted)
@@ -1073,6 +1086,9 @@ wait_for_inferior ()
        }
 
 #if 1
+      /* See if we left the step range due to a subroutine call that
+        we should proceed to the end of.  */
+
       if (stop_func_start)
        {
          struct symtab *s;
@@ -1096,7 +1112,7 @@ wait_for_inferior ()
           /* Might be a recursive call if either we have a prologue
              or the call instruction itself saves the PC on the stack.  */
           || prologue_pc != stop_func_start
-          || stop_sp != prev_sp)
+          || read_sp () != step_sp)
          && (/* PC is completely out of bounds of any known objfiles.  Treat
                 like a subroutine call. */
              ! stop_func_start
@@ -1112,6 +1128,16 @@ wait_for_inferior ()
 
              || stop_pc < prologue_pc
 
+             /* ...and if it is a leaf function, the prologue might
+                consist of gp loading only, so the call transfers to
+                the first instruction after the prologue.  */
+             || (stop_pc == prologue_pc
+
+                 /* Distinguish this from the case where we jump back
+                    to the first instruction after the prologue,
+                    within a function.  */
+                  && stop_func_start != prev_func_start)
+
              /* If we end up in certain places, it means we did a subroutine
                 call.  I'm not completely sure this is necessary now that we
                 have the above checks with stop_func_start (and now that
@@ -1183,7 +1209,7 @@ step_over_function:
            step_resume_breakpoint =
              set_momentary_breakpoint (sr_sal, get_current_frame (),
                                        bp_step_resume);
-           step_resume_breakpoint->frame = prev_frame_address;
+           step_resume_breakpoint->frame = step_frame_address;
            if (breakpoints_inserted)
              insert_breakpoints ();
          }
@@ -1341,8 +1367,10 @@ step_into_function:
                                          been at the start of a
                                          function. */
       prev_func_name = stop_func_name;
-      prev_sp = stop_sp;
-      prev_frame_address = stop_frame_address;
+
+      if (update_step_sp)
+       step_sp = read_sp ();
+      update_step_sp = 0;
 
       /* If we did not do break;, it means we should keep
         running the inferior and not return to debugger.  */
@@ -1417,8 +1445,6 @@ step_into_function:
       prev_pc = read_pc ();
       prev_func_start = stop_func_start;
       prev_func_name = stop_func_name;
-      prev_sp = stop_sp;
-      prev_frame_address = stop_frame_address;
     }
   do_cleanups (old_cleanups);
 }
@@ -1492,6 +1518,8 @@ Further execution is probably impossible.\n");
      if we have one.  */
   if (!stop_stack_dummy)
     {
+      select_frame (get_current_frame (), 0);
+
       if (stop_print_frame)
        {
          int source_only;
@@ -1499,7 +1527,7 @@ Further execution is probably impossible.\n");
          source_only = bpstat_print (stop_bpstat);
          source_only = source_only ||
                (   stop_step
-                && step_frame_address == stop_frame_address
+                && step_frame_address == FRAME_FP (get_current_frame ())
                 && step_start_function == find_pc_function (stop_pc));
 
           print_stack_frame (selected_frame, -1, source_only? -1: 1);
@@ -1828,7 +1856,6 @@ save_inferior_status (inf_status, restore_stack_info)
 {
   inf_status->stop_signal = stop_signal;
   inf_status->stop_pc = stop_pc;
-  inf_status->stop_frame_address = stop_frame_address;
   inf_status->stop_step = stop_step;
   inf_status->stop_stack_dummy = stop_stack_dummy;
   inf_status->stopped_by_random_signal = stopped_by_random_signal;
@@ -1898,7 +1925,6 @@ restore_inferior_status (inf_status)
 {
   stop_signal = inf_status->stop_signal;
   stop_pc = inf_status->stop_pc;
-  stop_frame_address = inf_status->stop_frame_address;
   stop_step = inf_status->stop_step;
   stop_stack_dummy = inf_status->stop_stack_dummy;
   stopped_by_random_signal = inf_status->stopped_by_random_signal;
index bf185b46343e5a0cb3007cf8861d968d8168e0bb..9679f58962c76afe21af9edbdaa8d0214933154e 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -379,6 +379,16 @@ void (*disable_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
 
 void (*interactive_hook) PARAMS ((void));
 
+/* Called when going to wait for the target.  Usually allows the GUI to run
+   while waiting for target events.  */
+
+int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
+
+/* Used by UI as a wrapper around command execution.  May do various things
+   like enabling/disabling buttons, etc...  */
+
+void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
+                                  int from_tty));
 \f
 /* Where to go for return_to_top_level (RETURN_ERROR).  */
 jmp_buf error_return;
@@ -858,6 +868,8 @@ execute_command (p, from_tty)
        do_setshow_command (arg, from_tty & caution, c);
       else if (c->function.cfunc == NO_FUNCTION)
        error ("That is not a command, just a help topic.");
+      else if (call_command_hook)
+       call_command_hook (c, arg, from_tty & caution);
       else
        (*c->function.cfunc) (arg, from_tty & caution);
    }