This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Use observers to report stop events.


Presently, the *stopped async output, despite been documented as async,
is actually output during processing of MI command. Naturally, this is
not going to work in non-stop mode, since there may be more stops that
there were MI commands. This patches makes the *stopped output be printed
via observer. Presently, there's one regression in mi tests -- namely the
mi-async.exp test -- which uses hardcoded tests for *stopped and so
fails after update as predicated :-) I'll fix this up later; this is a local
change and should not affect the review of the patch itself.

Note that there are no current uses of the normal_stop observer, so this
patch is as safe as it can get :-)

- Volodya

	* defs.h (make_cleanup_restore_integer): New declaration.
	* utils.c (restore_integer_closure, restore_integer)
	(make_cleanup_restore_integer): New.
	* breakpoint.c (restore_always_inserted_mode): Remove.
	(update_breakpoints_after_exec): Use make_cleanup_restore_integer.

	* inferior.h (suppress_normal_stop_observer): New.
	* infcall.c (call_function_by_hand): Disable stop events when
	doing function calls.
	* infmcd.c (suppress_normal_stop_observer): New.
	(finish_command_continuation): Call normal_stop observer
	explicitly.
	(finish_command): Disable stop events inside proceed.
	* infrun.c (normal_stop): Don't call normal stop observer if
	suppressed of if multi-step is in progress.

	* interps.h (top_level_interpreter): New.
	* interps.c (top_level_interpreter): Rename to
	top_level_interpreter_ptr.
	(top_level_interpreter): New.

	* mi/mi-interp.c (mi_on_normal_stop): New.
	(mi_interpreter_init): Register mi_on_normal_stop.
	(mi_interpreter_exec_continuation): Remove.
	(mi_cmd_interpreter_exec): Don't register the above.
	* mi/mi-main.c (captured_mi_execute_command): Don't care
	about sync_execution.
	(mi_execute_async_cli_command): Don't install continuation.  Don't
	print *stopped.
	(mi_exec_async_cli_cmd_continuation): Remove.

	[gdb/testsuite]
	* gdb.mi/mi-break.exp (test_ignore_count): Adjust stopped pattern.
	* gdb.mi/mi-syn-frame.exp: Use mi_expect_stop instead of direct
	testing of stopped.
	* gdb.mi/mi2-syn-frame.exp: Likewise.
	* lib/mi-support.exp (default_mi_gdb_start): Call detect_async.
	(async, detect_async): New.
	(mi_expect_stop, mi_continue_to_line): Adjust expectation
	depending on if we're running in sync or async mode.
---
 gdb/breakpoint.c                       |   10 +----
 gdb/defs.h                             |    2 +
 gdb/infcall.c                          |    6 ++-
 gdb/infcmd.c                           |   16 +++++--
 gdb/inferior.h                         |    3 +
 gdb/infrun.c                           |    3 +-
 gdb/interps.c                          |   17 ++++++--
 gdb/interps.h                          |    2 +
 gdb/mi/mi-interp.c                     |   43 ++++++++++-----------
 gdb/mi/mi-main.c                       |   36 +----------------
 gdb/testsuite/gdb.mi/mi-break.exp      |    2 +-
 gdb/testsuite/gdb.mi/mi-syn-frame.exp  |    6 +--
 gdb/testsuite/gdb.mi/mi2-syn-frame.exp |   25 +++---------
 gdb/testsuite/lib/mi-support.exp       |   64 +++++++++++++++++++++++++++++---
 gdb/utils.c                            |   27 +++++++++++++
 15 files changed, 157 insertions(+), 105 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index d220d00..537b9bf 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1448,12 +1448,6 @@ reattach_breakpoints (int pid)
   return 0;
 }
 
-static void
-restore_always_inserted_mode (void *p)
-{
-  always_inserted_mode = (uintptr_t) p;
-}
-
 void
 update_breakpoints_after_exec (void)
 {
@@ -1469,9 +1463,7 @@ update_breakpoints_after_exec (void)
   /* The binary we used to debug is now gone, and we're updating
      breakpoints for the new binary.  Until we're done, we should not
      try to insert breakpoints.  */
-  cleanup = make_cleanup (restore_always_inserted_mode, 
-			  (void *) (uintptr_t) always_inserted_mode);
-  always_inserted_mode = 0;
+  cleanup = make_cleanup_restore_integer (&always_inserted_mode, 0);
 
   ALL_BREAKPOINTS_SAFE (b, temp)
   {
diff --git a/gdb/defs.h b/gdb/defs.h
index 5c35051..a632840 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -345,6 +345,8 @@ extern struct cleanup *make_cleanup_close (int fd);
 
 extern struct cleanup *make_cleanup_bfd_close (bfd *abfd);
 
+extern struct cleanup *make_cleanup_restore_integer (int *variable, int value);
+
 extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *);
 
 extern struct cleanup *make_my_cleanup (struct cleanup **,
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 721b32d..d879b79 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -706,6 +706,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
   {
     struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+    struct cleanup *old_cleanups2;
     int saved_async = 0;
 
     /* If all error()s out of proceed ended up calling normal_stop
@@ -718,8 +719,11 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 
     if (target_can_async_p ())
       saved_async = target_async_mask (0);
-    
+
+    old_cleanups2 = make_cleanup_restore_integer 
+      (&suppress_normal_stop_observer, 1);
     proceed (real_pc, TARGET_SIGNAL_0, 0);
+    do_cleanups (old_cleanups2);
     
     if (saved_async)
       target_async_mask (saved_async);
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 2823259..c787f95 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -202,6 +202,9 @@ int step_multi;
    in format described in environ.h.  */
 
 struct gdb_environ *inferior_environ;
+
+/* When set, normal_stop will not call the normal_stop observer.  */
+int suppress_normal_stop_observer = 0;
 
 /* Accessor routines. */
 
@@ -1275,9 +1278,14 @@ finish_command_continuation (struct continuation_arg *arg, int error)
 	  if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
 	    print_return_value (value_type); 
 	}
+
+      /* We suppress normal call of normal_stop observer and do it here so that
+	 that *stopped notification includes the return value.  */
+      observer_notify_normal_stop (stop_bpstat);
     }
 
-  delete_breakpoint (breakpoint);
+  suppress_normal_stop_observer = 0;
+  delete_breakpoint (breakpoint);  
 }
 
 /* "finish": Set a temporary breakpoint at the place the selected
@@ -1343,6 +1351,7 @@ finish_command (char *arg, int from_tty)
     }
 
   proceed_to_finish = 1;	/* We want stop_registers, please...  */
+  make_cleanup_restore_integer (&suppress_normal_stop_observer, 1);
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
 
   arg1 =
@@ -1358,10 +1367,7 @@ finish_command (char *arg, int from_tty)
   arg2->data.pointer = function;
   arg3->data.pointer = old_chain;
   add_continuation (finish_command_continuation, arg1);
-
-  /* Do this only if not running asynchronously or if the target
-     cannot do async execution.  Otherwise, complete this command when
-     the target actually stops, in fetch_inferior_event.  */
+  
   discard_cleanups (old_chain);
   if (!target_can_async_p ())
     do_all_continuations (0);
diff --git a/gdb/inferior.h b/gdb/inferior.h
index 3aaaa26..630cc52 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -399,6 +399,9 @@ extern int debug_displaced;
 void displaced_step_dump_bytes (struct ui_file *file,
                                 const gdb_byte *buf, size_t len);
 
+
+/* When set, normal_stop will not call the normal_stop observer.  */
+extern int suppress_normal_stop_observer;
 
 /* Possible values for gdbarch_call_dummy_location.  */
 #define ON_STACK 1
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 7f151f7..d6b78ea 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3635,7 +3635,8 @@ Further execution is probably impossible.\n"));
 
 done:
   annotate_stopped ();
-  observer_notify_normal_stop (stop_bpstat);
+  if (!suppress_normal_stop_observer && !step_multi)
+    observer_notify_normal_stop (stop_bpstat);
 }
 
 static int
diff --git a/gdb/interps.c b/gdb/interps.c
index 9d47843..936fe89 100644
--- a/gdb/interps.c
+++ b/gdb/interps.c
@@ -81,7 +81,7 @@ void _initialize_interpreter (void);
 
 static struct interp *interp_list = NULL;
 static struct interp *current_interpreter = NULL;
-static struct interp *top_level_interpreter = NULL;
+static struct interp *top_level_interpreter_ptr = NULL;
 
 static int interpreter_initialized = 0;
 
@@ -144,7 +144,7 @@ interp_set (struct interp *interp, int top_level)
   /* If we already have an interpreter, then trying to
      set top level interpreter is kinda pointless.  */
   gdb_assert (!top_level || !current_interpreter);
-  gdb_assert (!top_level || !top_level_interpreter);
+  gdb_assert (!top_level || !top_level_interpreter_ptr);
 
   if (current_interpreter != NULL)
     {
@@ -165,7 +165,7 @@ interp_set (struct interp *interp, int top_level)
 
   current_interpreter = interp;
   if (top_level)
-    top_level_interpreter = interp;
+    top_level_interpreter_ptr = interp;
 
   /* We use interpreter_p for the "set interpreter" variable, so we need
      to make sure we have a malloc'ed copy for the set command to free. */
@@ -476,11 +476,18 @@ interpreter_completer (char *text, char *word)
   return matches;
 }
 
+struct interp *
+top_level_interpreter (void)
+{
+  gdb_assert (top_level_interpreter_ptr);
+  return top_level_interpreter_ptr;
+}
+
 extern void *
 top_level_interpreter_data (void)
 {
-  gdb_assert (top_level_interpreter);
-  return top_level_interpreter->data;  
+  gdb_assert (top_level_interpreter_ptr);
+  return top_level_interpreter_ptr->data;
 }
 
 /* This just adds the "interpreter-exec" command.  */
diff --git a/gdb/interps.h b/gdb/interps.h
index e1030fa..5e91080 100644
--- a/gdb/interps.h
+++ b/gdb/interps.h
@@ -64,6 +64,8 @@ extern struct ui_out *interp_ui_out (struct interp *interp);
 extern int current_interp_named_p (const char *name);
 extern int current_interp_display_prompt_p (void);
 extern void current_interp_command_loop (void);
+/* Returns the top-level interpreter.  */
+extern struct interp *top_level_interpreter ();
 /* Returns opaque data associated with the top-level interpreter.  */
 extern void *top_level_interpreter_data (void);
 
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index ae9e07b..e874a56 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -65,6 +65,7 @@ static void mi1_command_loop (void);
 
 static void mi_insert_notify_hooks (void);
 static void mi_remove_notify_hooks (void);
+static void mi_on_normal_stop (struct bpstats *bs);
 
 static void mi_new_thread (struct thread_info *t);
 
@@ -88,7 +89,10 @@ mi_interpreter_init (int top_level)
   mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);
 
   if (top_level)
-    observer_attach_new_thread (mi_new_thread);
+    {
+      observer_attach_new_thread (mi_new_thread);
+      observer_attach_normal_stop (mi_on_normal_stop);
+    }
 
   return mi;
 }
@@ -167,26 +171,6 @@ mi_interpreter_prompt_p (void *data)
   return 0;
 }
 
-static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg, int  error)
-{
-  bpstat_do_actions (&stop_bpstat);
-  /* It's not clear what to do in the case of errror -- should we assume that
-     the target is stopped, or that it still runs?  */
-  if (!target_executing)
-    {
-      fputs_unfiltered ("*stopped", raw_stdout);
-      mi_out_put (uiout, raw_stdout);
-      fputs_unfiltered ("\n", raw_stdout);
-      fputs_unfiltered ("(gdb) \n", raw_stdout);
-      gdb_flush (raw_stdout);
-    }
-  else if (target_can_async_p ())
-    {
-      add_continuation (mi_interpreter_exec_continuation, NULL);
-    }
-}
-
 enum mi_cmd_result
 mi_cmd_interpreter_exec (char *command, char **argv, int argc)
 {
@@ -237,7 +221,6 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
   if (target_can_async_p () && target_executing)
     {
       fputs_unfiltered ("^running\n", raw_stdout);
-      add_continuation (mi_interpreter_exec_continuation, NULL);
     }
 
   if (mi_error_message != NULL)
@@ -317,6 +300,22 @@ mi_new_thread (struct thread_info *t)
   gdb_flush (mi->event_channel);
 }
 
+static void
+mi_on_normal_stop (struct bpstats *bs)
+{
+  /* Since this can be called when CLI command is executing,
+     using cli interpreter, be sure to use MI uiout for output,
+     not the current one.  */
+  struct ui_out *uiout = interp_ui_out (top_level_interpreter ());
+  struct mi_interp *mi = top_level_interpreter_data ();
+
+  fputs_unfiltered ("*stopped", raw_stdout);
+  mi_out_put (uiout, raw_stdout);
+  mi_out_rewind (uiout);
+  fputs_unfiltered ("\n", raw_stdout);
+  gdb_flush (raw_stdout);
+}
+
 extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */
 
 void
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 177d0ec..deb2df9 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -102,9 +102,6 @@ static void mi_execute_cli_command (const char *cmd, int args_p,
 				    const char *args);
 static enum mi_cmd_result mi_execute_async_cli_command (char *mi, char *args, int from_tty);
 
-static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, 
-						int error);
-
 static int register_changed_p (int regnum, struct regcache *,
 			       struct regcache *);
 static void get_register (int regnum, int format);
@@ -1067,15 +1064,11 @@ captured_mi_execute_command (struct ui_out *uiout, void *data)
 	      fputs_unfiltered ("\n", raw_stdout);
 	    }
 	  else
+	    /* The command does not want anything to be printed.  In that
+	       case, the command probably should not have written anything
+	       to uiout, but in case it has written something, discard it.  */
 	    mi_out_rewind (uiout);
 	}
-      else if (sync_execution)
-	{
-	  /* Don't print the prompt. We are executing the target in
-	     synchronous mode.  */
-	  args->action = EXECUTE_COMMAND_SUPPRESS_PROMPT;
-	  return;
-	}
       break;
 
     case CLI_COMMAND:
@@ -1296,12 +1289,6 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
 	fputs_unfiltered (current_token, raw_stdout);
       fputs_unfiltered ("^running\n", raw_stdout);
 
-      /* Ideally, we should be intalling continuation only when
-	 the target is already running. However, this will break right now,
-	 because continuation installed by the 'finish' command must be after
-	 the continuation that prints *stopped.  This issue will be
-	 fixed soon.  */
-      add_continuation (mi_exec_async_cli_cmd_continuation, NULL);
     }
 
   execute_command ( /*ui */ run, 0 /*from_tty */ );
@@ -1317,31 +1304,14 @@ mi_execute_async_cli_command (char *mi, char *args, int from_tty)
       /* Do this before doing any printing.  It would appear that some
          print code leaves garbage around in the buffer.  */
       do_cleanups (old_cleanups);
-      /* If the target was doing the operation synchronously we fake
-         the stopped message.  */
-      fputs_unfiltered ("*stopped", raw_stdout);
-      mi_out_put (uiout, raw_stdout);
-      mi_out_rewind (uiout);
       if (do_timings)
       	print_diff_now (current_command_ts);
-      fputs_unfiltered ("\n", raw_stdout);
       return MI_CMD_QUIET;
     }    
   return MI_CMD_DONE;
 }
 
 void
-mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg, int error)
-{
-  /* Assume 'error' means that target is stopped, too.  */
-  fputs_unfiltered ("*stopped", raw_stdout);
-  mi_out_put (uiout, raw_stdout);
-  fputs_unfiltered ("\n", raw_stdout);
-  fputs_unfiltered ("(gdb) \n", raw_stdout);
-  gdb_flush (raw_stdout);
-}
-
-void
 mi_load_progress (const char *section_name,
 		  unsigned long sent_so_far,
 		  unsigned long total_section,
diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index c0f5132..e4fd5c9 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -163,7 +163,7 @@ proc test_ignore_count {} {
     mi_run_cmd
 
     gdb_expect {
-        -re ".*func=\"callme\".*args=\\\[\{name=\"i\",value=\"2\"\}\\\].*\r\n$mi_gdb_prompt$" {
+        -re ".*\\*stopped.*func=\"callme\".*args=\\\[\{name=\"i\",value=\"2\"\}\\\].*\r\n($mi_gdb_prompt)?$" {
             pass "run to breakpoint with ignore count"
         }
         -re ".*$mi_gdb_prompt$" {
diff --git a/gdb/testsuite/gdb.mi/mi-syn-frame.exp b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
index ed89965..80d36c9 100644
--- a/gdb/testsuite/gdb.mi/mi-syn-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi-syn-frame.exp
@@ -60,9 +60,7 @@ mi_gdb_test "403-exec-continue" \
   "403\\^running" \
   "testing exec continue"
 
-# Presently, the *stopped notification for this case does not include
-# any information.  This can be considered a bug.
-mi_gdb_test "" "\\*stopped" "finished exec continue"
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "404-stack-list-frames 0 0" \
   "404\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
@@ -91,7 +89,7 @@ mi_gdb_test "407-stack-list-frames" \
 
 mi_gdb_test "408-exec-continue" "408\\^running"
 
-mi_gdb_test "" ".*\\*stopped.*" "finished exec continue"
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "409-stack-list-frames 0 0" \
   "409\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
diff --git a/gdb/testsuite/gdb.mi/mi2-syn-frame.exp b/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
index 9c1daab..6e9792a 100644
--- a/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi2-syn-frame.exp
@@ -58,15 +58,11 @@ mi_gdb_test "402-stack-list-frames" "402\\^done,stack=\\\[frame=\{level=\"0\",ad
 # Continue back to main()
 #
 
-send_gdb "403-exec-continue\n"
-gdb_expect {
-  -re "403\\^running\[\r\n\]+${my_mi_gdb_prompt}.*\\\*stopped\[\r\n\]+${my_mi_gdb_prompt}$" {
-    pass "403-exec-continue"
-  }
-  timeout {
-    fail "403-exec-continue"
-  }
-}
+mi_gdb_test "403-exec-continue" \
+  "403\\^running" \
+  "testing exec continue"
+
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "404-stack-list-frames 0 0" \
   "404\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
@@ -92,16 +88,9 @@ mi_gdb_test "407-stack-list-frames" \
   "407\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"subroutine\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"1\",addr=\"$hex\",func=\"handler\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"2\",addr=\"$hex\",func=\"<signal handler called>\"\},.*frame=\{level=\"$decimal\",addr=\"$hex\",func=\"have_a_very_merry_interrupt\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"<function called from gdb>\"\},frame=\{level=\"$decimal\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",line=\"$decimal\"\}.*\\\]" \
   "list stack frames"
 
+mi_gdb_test "408-exec-continue" "408\\^running"
 
-send_gdb "408-exec-continue\n"
-gdb_expect {
-  -re "408\\^running\[\r\n\]+${my_mi_gdb_prompt}.*\\\*stopped\[\r\n\]+${my_mi_gdb_prompt}$" {
-    pass "408-exec-continue"
-  }
-  timeout {
-    fail "408-exec-continue"
-  }
-}
+mi_expect_stop "really-no-reason" "" "" "" "" "" "finished exec continue"
 
 mi_gdb_test "409-stack-list-frames 0 0" \
   "409\\^done,stack=\\\[frame=\{level=\"0\",addr=\"$hex\",func=\"main\",file=\".*mi-syn-frame.c\",fullname=\"${fullname_syntax}${srcfile}\",line=\"$decimal\"\}.*\\\]" \
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 5926f16..0a6eb8a 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -227,6 +227,8 @@ proc default_mi_gdb_start { args } {
     	}
     }
 
+    detect_async
+
     return 0;
 }
 
@@ -911,6 +913,30 @@ proc mi_step { test } {
   return [mi_step_to {.*} {.*} {.*} {.*} $test]
 }
 
+set async "unknown"
+
+proc detect_async {} {
+    global async
+    global mi_gdb_prompt
+
+    if { $async == "unknown" } {
+        send_gdb "maint show linux-async\n"
+        
+	gdb_expect {
+	    -re ".*Controlling the GNU/Linux inferior in asynchronous mode is on...*$mi_gdb_prompt$" {
+                set async 1
+	    }
+	    -re ".*$mi_gdb_prompt$" {
+                set async 0
+	    }
+            timeout {
+                set async 0
+            }
+        }
+    }
+    return $async
+}
+
 # Wait for MI *stopped notification to appear.
 # The REASON, FUNC, ARGS, FILE and LINE are regular expressions
 # to match against whatever is output in *stopped.  ARGS should
@@ -933,6 +959,7 @@ proc mi_expect_stop { reason func args file line extra test } {
     global hex
     global decimal
     global fullname_syntax
+    global async
 
     set after_stopped ""
     set after_reason ""
@@ -944,10 +971,28 @@ proc mi_expect_stop { reason func args file line extra test } {
         set after_stopped [lindex $extra 0]
     }
 
+    if {$async} {
+        set prompt_re ""
+    } else {
+        set prompt_re "$mi_gdb_prompt"
+    }
+
+    if { $reason == "really-no-reason" } {
+        gdb_expect {
+          -re "\\*stopped\r\n$prompt_re$" {
+            pass "$test"
+          }
+          timeout {
+              fail "$test (unknown output after running)"
+          }
+        }
+        return
+    }
+    
     if { $reason == "exited-normally" } {
 
         gdb_expect {
-          -re "\\*stopped,reason=\"exited-normally\"\r\n$mi_gdb_prompt$" {
+          -re "\\*stopped,reason=\"exited-normally\"\r\n$prompt_re$" {
             pass "$test"
           }
           -re ".*$mi_gdb_prompt$" {fail "continue to end (2)"}
@@ -970,17 +1015,17 @@ proc mi_expect_stop { reason func args file line extra test } {
         set r "reason=\"$reason\","
     }
 
-    verbose -log "mi_expect_stop: expecting: .*\\*stopped,${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$mi_gdb_prompt$"
+    verbose -log "mi_expect_stop: expecting: .*\\*stopped,${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped\r\n$prompt_re$"
     gdb_expect {
-	-re ".*\\*stopped,${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$mi_gdb_prompt$" {
+	-re ".*\\*stopped,${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped\r\n$prompt_re$" {
 	    pass "$test"
             return $expect_out(2,string)
 	}
-	-re ".*\\*stopped,${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$mi_gdb_prompt$" {
+	-re ".*\\*stopped,${r}${bn}${after_reason}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$prompt_re$" {
 	    fail "$test (stopped at wrong place)"
 	    return -1
 	}
-	-re ".*\r\n${mi_gdb_prompt}$" {
+	-re ".*\r\n$mi_gdb_prompt$" {
 	    fail "$test (unknown output after running)"
 	    return -1
 	}
@@ -1337,9 +1382,16 @@ proc mi_continue_to_line {location test} {
 proc mi_get_stop_line {test} {
 
   global mi_gdb_prompt
+  global async
+
+  if {$async} {
+      set prompt_re ""
+  } else {
+      set prompt_re "$mi_gdb_prompt"
+  }
 
   gdb_expect {
-      -re ".*line=\"(.*)\".*\r\n$mi_gdb_prompt$" {
+      -re ".*line=\"(.*)\".*\r\n$prompt_re$" {
           return $expect_out(1,string)
       }
       -re ".*$mi_gdb_prompt$" {
diff --git a/gdb/utils.c b/gdb/utils.c
index d9953a0..fa8e455 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -277,6 +277,33 @@ make_cleanup_free_section_addr_info (struct section_addr_info *addrs)
   return make_my_cleanup (&cleanup_chain, do_free_section_addr_info, addrs);
 }
 
+struct restore_integer_closure
+{
+  int *variable;
+  int value;
+};
+
+static void
+restore_integer (void *p)
+{
+  struct restore_integer_closure *closure = p;
+  *(closure->variable) = closure->value;
+  xfree (closure);
+}
+
+/* Assign VALUE to *VARIABLE and arranges for the old value to
+   be restored via cleanup.  */
+struct cleanup *
+make_cleanup_restore_integer (int *variable, int value)
+{
+  struct restore_integer_closure *c =
+    xmalloc (sizeof (struct restore_integer_closure));
+  struct cleanup *cleanup = make_cleanup (restore_integer, (void *) c);
+  c->variable = variable;
+  c->value = *variable;    
+  *variable = value;
+  return cleanup;
+}
 
 struct cleanup *
 make_my_cleanup (struct cleanup **pmy_chain, make_cleanup_ftype *function,
-- 
1.5.3.5


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]