* 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.
+2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
+
+ Use observers to report stop events in MI.
+ * 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.
+
2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
Suppress normal stop observer when it's problematic.
arg1->data.pointer = breakpoint;
arg2->data.pointer = function;
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);
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);
static void mi_thread_exit (struct thread_info *t);
{
observer_attach_new_thread (mi_new_thread);
observer_attach_thread_exit (mi_thread_exit);
+ observer_attach_normal_stop (mi_on_normal_stop);
}
return mi;
return 0;
}
-static void
-mi_interpreter_exec_continuation (struct continuation_arg *arg, int error_p)
-{
- 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)
{
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)
mi_thread_exit (struct thread_info *t)
{
struct mi_interp *mi = top_level_interpreter_data ();
-
target_terminal_ours ();
fprintf_unfiltered (mi->event_channel, "thread-exited,id=\"%d\"", t->num);
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
const char *args);
static enum mi_cmd_result mi_execute_async_cli_command (char *cli_command,
char **argv, int argc);
-
-static void mi_exec_async_cli_cmd_continuation (struct continuation_arg *arg,
- int error_p);
-
static int register_changed_p (int regnum, struct regcache *,
struct regcache *);
static void get_register (int regnum, int format);
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:
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 */ );
/* 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_p)
-{
- /* 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,
+2008-06-10 Vladimir Prus <vladimir@codesourcery.com>
+
+ * 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.
+
2008-06-09 Tom Tromey <tromey@redhat.com>
* gdb.base/completion.exp: New tests for field name completion
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$" {
"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\"\}.*\\\]" \
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\"\}.*\\\]" \
# 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\"\}.*\\\]" \
"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\"\}.*\\\]" \
}
}
+ detect_async
+
return 0;
}
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
global hex
global decimal
global fullname_syntax
+ global async
set after_stopped ""
set after_reason ""
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)"}
set a $after_reason
- verbose -log "mi_expect_stop: expecting: .*\\*stopped,${r}${a}${bn}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}${a}${bn}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}${a}${bn}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}${a}${bn}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}${a}${bn}thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",fullname=\"${fullname_syntax}.*\",line=\"\[0-9\]*\"\}.*\r\n$mi_gdb_prompt$" {
+ -re ".*\\*stopped,${r}${a}${bn}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
}
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$" {