This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] Use observers to report stop events.
- From: Vladimir Prus <vladimir at codesourcery dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Fri, 11 Apr 2008 20:45:57 +0300
- Subject: [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