This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[commit] Have catch_exception() capture the error output
- From: Andrew Cagney <cagney at gnu dot org>
- To: gdb-patches at sources dot redhat dot com
- Date: Fri, 14 Jan 2005 14:26:43 -0500
- Subject: [commit] Have catch_exception() capture the error output
MI output is littered with:
(gdb)
PASS: gdb.mi/mi-var-cmd.exp: create lsimple->integer
-var-create int * int
&"Attempt to use a type name as an expression.\n"
&"mi_cmd_var_create: unable to create variable object\n"
^error,msg="mi_cmd_var_create: unable to create variable object"
(gdb)
(notice how the error message both appears as output and as the
command's result)
This occurs because the error is printed unconditionally (ignoring
error_silent). Talk about a design flaw, it should be possible to
capture the error and then at the call site print it, supress it, or
re-format it.
The attached modifies catch_exception (but not the others) so that the
error message is captured but not printed - it's left to the caller to
print et.al. the message. To preserve the existing output, and keep the
test results consistent, the catch_exception call sites were also
modified to print the exception.
As always tested in PPC GNU/Linux.
committed,
Andrew
2005-01-13 Andrew Cagney <cagney@gnu.org>
* mi/mi-main.c (mi_execute_command): Print the exception.
* cli/cli-interp.c (safe_execute_command): Print the exception.
* exceptions.h (exception_print): Declare.
* exceptions.c (struct catcher): Add field print_message.
(catcher_init): Add parameter print_message, store in the catcher
struct.
(print_and_throw): Only print the message when print_message.
(catch_exceptions_with_msg, catch_errors): Pass print_message=1 to
catcher_init.
(catch_exception): Pass print_message=0 to catcher_init.
Index: exceptions.c
===================================================================
RCS file: /cvs/src/src/gdb/exceptions.c,v
retrieving revision 1.5
diff -p -u -r1.5 exceptions.c
--- exceptions.c 14 Jan 2005 01:20:36 -0000 1.5
+++ exceptions.c 14 Jan 2005 18:50:13 -0000
@@ -69,8 +69,13 @@ struct catcher
enum catcher_state state;
/* Jump buffer pointing back at the exception handler. */
SIGJMP_BUF buf;
- /* Status buffer belonging to that exception handler. */
+ /* Status buffer belonging to the exception handler. */
volatile struct exception *exception;
+ /* Should the error / quit message be printed? Old code assumes
+ that this file prints the error/quit message when first reported.
+ New code instead directly handles the printing of error/quit
+ messages. */
+ int print_message;
/* Saved/current state. */
int mask;
char *saved_error_pre_print;
@@ -88,7 +93,8 @@ static SIGJMP_BUF *
catcher_init (struct ui_out *func_uiout,
char *errstring,
volatile struct exception *exception,
- return_mask mask)
+ return_mask mask,
+ int print_message)
{
struct catcher *new_catcher = XZALLOC (struct catcher);
@@ -99,6 +105,7 @@ catcher_init (struct ui_out *func_uiout,
new_catcher->exception = exception;
new_catcher->mask = mask;
+ new_catcher->print_message = print_message;
/* Override error/quit messages during FUNC. */
new_catcher->saved_error_pre_print = error_pre_print;
@@ -295,6 +302,40 @@ do_write (void *data, const char *buffer
}
+void
+exception_print (struct ui_file *file, const char *pre_print,
+ struct exception e)
+{
+ if (e.reason < 0 && e.message != NULL)
+ {
+ target_terminal_ours ();
+ wrap_here (""); /* Force out any buffered output */
+ gdb_flush (file);
+ annotate_error_begin ();
+ if (pre_print)
+ fputs_filtered (pre_print, file);
+
+ /* KLUGE: cagney/2005-01-13: Write the string out one line at a
+ time as that way the MI's behavior is preserved. */
+ {
+ const char *start;
+ const char *end;
+ for (start = e.message; start != NULL; start = end)
+ {
+ end = strchr (start, '\n');
+ if (end == NULL)
+ fputs_filtered (start, file);
+ else
+ {
+ end++;
+ ui_file_write (file, start, end - start);
+ }
+ }
+ }
+ fprintf_filtered (file, "\n");
+ }
+}
+
NORETURN static void
print_and_throw (enum return_reason reason, enum errors error,
const char *prefix, const char *fmt,
@@ -322,18 +363,23 @@ print_and_throw (enum return_reason reas
xfree (last_message);
last_message = ui_file_xstrdup (tmp_stream, &len);
- if (deprecated_error_begin_hook)
- deprecated_error_begin_hook ();
+ /* Print the mesage to stderr, but only if the catcher isn't going
+ to handle/print it locally. */
+ if (current_catcher->print_message)
+ {
+ if (deprecated_error_begin_hook)
+ deprecated_error_begin_hook ();
- /* Write the message plus any pre_print to gdb_stderr. */
- target_terminal_ours ();
- wrap_here (""); /* Force out any buffered output */
- gdb_flush (gdb_stdout);
- annotate_error_begin ();
- if (error_pre_print)
- fputs_filtered (error_pre_print, gdb_stderr);
- ui_file_put (tmp_stream, do_write, gdb_stderr);
- fprintf_filtered (gdb_stderr, "\n");
+ /* Write the message plus any pre_print to gdb_stderr. */
+ target_terminal_ours ();
+ wrap_here (""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ annotate_error_begin ();
+ if (error_pre_print)
+ fputs_filtered (error_pre_print, gdb_stderr);
+ ui_file_put (tmp_stream, do_write, gdb_stderr);
+ fprintf_filtered (gdb_stderr, "\n");
+ }
/* Throw the exception. */
e.reason = reason;
@@ -417,7 +463,7 @@ catch_exception (struct ui_out *uiout,
{
volatile struct exception exception;
SIGJMP_BUF *catch;
- catch = catcher_init (uiout, NULL, &exception, mask);
+ catch = catcher_init (uiout, NULL, &exception, mask, 0);
for (SIGSETJMP ((*catch));
catcher_state_machine (CATCH_ITER);)
(*func) (uiout, func_args);
@@ -434,7 +480,7 @@ catch_exceptions_with_msg (struct ui_out
{
volatile struct exception exception;
volatile int val = 0;
- SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask);
+ SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask, 1);
for (SIGSETJMP ((*catch)); catcher_state_machine (CATCH_ITER);)
val = (*func) (uiout, func_args);
gdb_assert (val >= 0);
@@ -462,7 +508,7 @@ catch_errors (catch_errors_ftype *func,
{
volatile int val = 0;
volatile struct exception exception;
- SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask);
+ SIGJMP_BUF *catch = catcher_init (uiout, errstring, &exception, mask, 1);
/* This illustrates how it is possible to nest the mechanism and
hence catch "break". Of course this doesn't address the need to
also catch "return". */
Index: exceptions.h
===================================================================
RCS file: /cvs/src/src/gdb/exceptions.h,v
retrieving revision 1.5
diff -p -u -r1.5 exceptions.h
--- exceptions.h 14 Jan 2005 02:33:24 -0000 1.5
+++ exceptions.h 14 Jan 2005 18:50:14 -0000
@@ -65,6 +65,11 @@ struct exception
/* A pre-defined non-exception. */
extern const struct exception exception_none;
+/* If E is an exception, print it's error message on the specified
+ stream. */
+extern void exception_print (struct ui_file *file, const char *pre_print,
+ struct exception e);
+
/* Throw an exception (as described by "struct exception"). Will
execute a LONG JUMP to the inner most containing exception handler
established using catch_exceptions() (or similar).
@@ -121,6 +126,10 @@ extern int catch_exceptions_with_msg (st
void *func_args,
char *errstring, char **gdberrmsg,
return_mask mask);
+
+/* This function, in addition, suppresses the printing of the captured
+ error message. It's up to the client to print it. */
+
extern struct exception catch_exception (struct ui_out *uiout,
catch_exception_ftype *func,
void *func_args,
Index: cli/cli-interp.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-interp.c,v
retrieving revision 1.7
diff -p -u -r1.7 cli-interp.c
--- cli/cli-interp.c 13 Jan 2005 23:31:17 -0000 1.7
+++ cli/cli-interp.c 14 Jan 2005 18:50:14 -0000
@@ -125,11 +125,16 @@ do_captured_execute_command (struct ui_o
static struct exception
safe_execute_command (struct ui_out *uiout, char *command, int from_tty)
{
+ struct exception e;
struct captured_execute_command_args args;
args.command = command;
args.from_tty = from_tty;
- return catch_exception (uiout, do_captured_execute_command, &args,
- RETURN_MASK_ALL);
+ e = catch_exception (uiout, do_captured_execute_command, &args,
+ RETURN_MASK_ALL);
+ /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the
+ caller should print the exception. */
+ exception_print (gdb_stderr, NULL, e);
+ return e;
}
Index: mi/mi-main.c
===================================================================
RCS file: /cvs/src/src/gdb/mi/mi-main.c,v
retrieving revision 1.71
diff -p -u -r1.71 mi-main.c
--- mi/mi-main.c 14 Jan 2005 02:33:24 -0000 1.71
+++ mi/mi-main.c 14 Jan 2005 18:50:14 -0000
@@ -1156,6 +1156,7 @@ mi_execute_command (char *cmd, int from_
args.command = command;
result = catch_exception (uiout, captured_mi_execute_command, &args,
RETURN_MASK_ALL);
+ exception_print (gdb_stderr, NULL, result);
if (args.action == EXECUTE_COMMAND_SUPRESS_PROMPT)
{