This is the mail archive of the
insight@sources.redhat.com
mailing list for the Insight project.
Re: [RFA] insight gdb_stdlog bug
- To: David Taylor <taylor at cygnus dot com>
- Subject: Re: [RFA] insight gdb_stdlog bug
- From: Andrew Cagney <ac131313 at cygnus dot com>
- Date: Fri, 12 Jan 2001 19:05:44 +0930
- Cc: insight at sources dot redhat dot com, gdb-patches at sourceware dot cygnus dot com
- References: <200012202252.RAA28763@texas.cygnus.com>
David Taylor wrote:
>
> When GDBTK_TO_RESULT is set, insight gobbles all output written to
> gdb_stdlog. But, the stuff written to gdb_stdlog isn't meant to be
> parsed by insight -- it's meant to be read by a person.
>
> While it might be desired -- when GDBTK_TO_RESULT is not set -- that
> gdb_stdlog go the same place as gdb_stdout, it cannot have the same
> pointer value as gdb_stdout or the code won't be able to distinguish
> output meant for gdb_stdout vs output meant for gdb_stdlog when
> GDBTK_TO_RESULT is set.
>
> The following patch fixes that. (The result is that output written to
> gdb_stdlog appears in the insight console window if it is active.)
>
> ChangeLog entries (3 separate ChangeLog files):
>
> * main.c (captured_main): Initialize gdb_stdlog to a copy of
> gdb_stdout rather than to gdb_stdout, so that code can distinguish
> them.
>
> * tui/tui-file.c (tui_file_fputs): Handle gdb_stdlog the same
> as gdb_stdout.
>
> * gdbtk/generic/gdbtk-hooks.c (gdbtk_fputs): Distinguish between
> gdb_stdlog and gdb_stdout.
David,
This feels wrong. Anything touching tui/tui-file.c is going in the
wrong direction. Rather than depend on tui-file.c, gdbtk should, like
mi, create its own *-file object and use that.
The attatched (very old) patch does this. From memory, its poossible
approval was lost in time.
Andrew
Index: ChangeLog-gdbtk
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/ChangeLog-gdbtk,v
retrieving revision 2.113
diff -p -r2.113 ChangeLog-gdbtk
*** ChangeLog-gdbtk 1999/06/21 20:12:40 2.113
--- ChangeLog-gdbtk 1999/06/25 07:34:29
***************
*** 1,3 ****
--- 1,27 ----
+ Wed May 26 10:37:25 1999 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gdbtk-hooks.c (gdbtk_fputs): Make static.
+ (gdbtk_add_hooks): Delete assignment of flush_hook.
+ (struct gdbtk_file): Dummy structure.
+ (gdbtk_file_delete, gdbtk_file_new): New functions. Implement
+ ``struct gdb_file'' for GDBtk.
+ (gdbtk_flush): Delete function.
+
+ * gdbtk.h (gdbtk_claim_stdio, gdbtk_release_stdio,
+ gdbtk_null_stdio): Add declarations.
+ * gdbtk-hooks.c (gdbtk_claim_stdio, gdbtk_release_stdio,
+ gdbtk_null_stdio): New functions. Switch between output
+ alternatives.
+
+ * gdbtk.c (gdbtk_fputs): Delete declaration.
+ (gdbtk_init): Replace assignment of fputs_unfiltered_hook with
+ calls to gdbtk_claim_stdio and gdbtk_release_stdio.
+
+ * gdbtk-variable.c (create_variable): Call gdbtk_claim_stdio() to
+ restore GDBtk output. Call gdbtk_null_stdio() to discard the
+ output.
+ (variable_value_changed): Ditto.
+
1999-06-21 James Ingham <jingham@leda.cygnus.com>
* gdbtk.c (target_should_use_timer): Add check for "linuxthreads"
Index: gdbtk-hooks.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk-hooks.c,v
retrieving revision 2.25
diff -p -r2.25 gdbtk-hooks.c
*** gdbtk-hooks.c 1999/06/15 19:24:18 2.25
--- gdbtk-hooks.c 1999/06/25 07:34:30
*************** static void gdbtk_warning PARAMS ((con
*** 90,96 ****
static char* gdbtk_readline PARAMS ((char *));
static void gdbtk_readline_begin (char *format, ...);
static void gdbtk_readline_end PARAMS ((void));
- static void gdbtk_flush PARAMS ((GDB_FILE *));
static void gdbtk_pre_add_symbol PARAMS ((char *));
static void gdbtk_print_frame_info PARAMS ((struct symtab *, int, int, int));
static void gdbtk_post_add_symbol PARAMS ((void));
--- 90,95 ----
*************** static void gdbtk_error_begin PARAMS ((v
*** 103,114 ****
static void report_error (void);
static void gdbtk_annotate_signal (void);
! /*
! * gdbtk_fputs can't be static, because we need to call it in gdbtk.c.
! * See note there for details.
! */
!
! void gdbtk_fputs PARAMS ((const char *, GDB_FILE *));
int gdbtk_load_hash PARAMS ((char *, unsigned long));
static void breakpoint_notify PARAMS ((struct breakpoint *, const char *));
--- 102,108 ----
static void report_error (void);
static void gdbtk_annotate_signal (void);
! static void gdbtk_fputs PARAMS ((const char *, GDB_FILE *));
int gdbtk_load_hash PARAMS ((char *, unsigned long));
static void breakpoint_notify PARAMS ((struct breakpoint *, const char *));
*************** gdbtk_add_hooks(void)
*** 129,135 ****
print_frame_info_listing_hook = gdbtk_print_frame_info;
query_hook = gdbtk_query;
warning_hook = gdbtk_warning;
- flush_hook = gdbtk_flush;
create_breakpoint_hook = gdbtk_create_breakpoint;
delete_breakpoint_hook = gdbtk_delete_breakpoint;
--- 123,128 ----
*************** gdbtk_add_hooks(void)
*** 162,169 ****
}
/* These control where to put the gdb output which is created by
! {f}printf_{un}filtered and friends. gdbtk_fputs and gdbtk_flush are the
! lowest level of these routines and capture all output from the rest of GDB.
The reason to use the result_ptr rather than the gdbtk_interp's result
directly is so that a call_wrapper invoked function can preserve its result
--- 155,163 ----
}
/* These control where to put the gdb output which is created by
! {f}printf_{un}filtered and friends. gdbtk_fputs is the lowest
! level of these routines and capture all output from the rest of
! GDB.
The reason to use the result_ptr rather than the gdbtk_interp's result
directly is so that a call_wrapper invoked function can preserve its result
*************** int gdbtk_two_elem_cmd (cmd_name, argv1)
*** 205,221 ****
return result;
}
- static void
- gdbtk_flush (stream)
- GDB_FILE *stream;
- {
- #if 0
- /* Force immediate screen update */
-
- Tcl_VarEval (gdbtk_interp, "gdbtk_tcl_flush", NULL);
- #endif
- }
-
/* This handles all the output from gdb. All the gdb printf_xxx functions
* eventually end up here. The output is either passed to the result_ptr
* where it will go to the result of some gdbtk command, or passed to the
--- 199,204 ----
*************** gdbtk_flush (stream)
*** 236,246 ****
*
*/
! void
gdbtk_fputs (ptr, stream)
const char *ptr;
GDB_FILE *stream;
{
in_fputs = 1;
if (result_ptr != NULL)
--- 219,238 ----
*
*/
! static int gdbtk_file_magic;
!
! struct gdbtk_file
! {
! int *magic;
! };
!
! static void
gdbtk_fputs (ptr, stream)
const char *ptr;
GDB_FILE *stream;
{
+ /* struct gdbtk_file *gdbtk = gdb_file_data (stream); */
+ /* ASSERT (gdbtk_file->magic == &gdbtk_file_magic); */
in_fputs = 1;
if (result_ptr != NULL)
*************** gdbtk_fputs (ptr, stream)
*** 276,281 ****
--- 268,342 ----
}
in_fputs = 0;
+ }
+
+ static gdb_file_delete_ftype gdbtk_file_delete;
+ static void
+ gdbtk_file_delete (stream)
+ struct gdb_file *stream;
+ {
+ struct gdbtk_file *gdbtk = gdb_file_data (stream);
+ /* ASSERT (gdbtk_file->magic == &gdbtk_file_magic); */
+ free (gdbtk);
+ }
+
+ static struct gdb_file *gdbtk_file_new PARAMS ((void));
+ static struct gdb_file *
+ gdbtk_file_new ()
+ {
+ struct gdb_file *gdb_file = gdb_file_new ();
+ struct gdbtk_file *gdbtk_file = xmalloc (sizeof (struct gdbtk_file));
+ gdbtk_file->magic = &gdbtk_file_magic;
+ set_gdb_file_fputs (gdb_file, gdbtk_fputs);
+ set_gdb_file_data (gdb_file, gdbtk_file, gdbtk_file_delete);
+ return gdb_file;
+ }
+
+ static struct gdb_file *tty_stdout;
+ static struct gdb_file *tty_stderr;
+
+ static struct gdb_file *gdbtk_stdout;
+ static struct gdb_file *gdbtk_stderr;
+
+ static struct gdb_file *null_stdout;
+ static struct gdb_file *null_stderr;
+
+ void
+ gdbtk_claim_stdio ()
+ {
+ static int done;
+ if (!done)
+ {
+ /* save the original gdb_stdout/gdb_stderr. */
+ tty_stdout = gdb_stdout;
+ tty_stderr = gdb_stderr;
+ /* create GDBtk's stdout/stderr. */
+ gdbtk_stdout = gdbtk_file_new ();
+ gdbtk_stderr = gdbtk_file_new ();
+ /* and null devices */
+ null_stdout = gdb_file_new ();
+ null_stderr = gdb_file_new ();
+ done = 1;
+ }
+ /* select our stdio */
+ gdb_stdout = gdbtk_stdout;
+ gdb_stderr = gdbtk_stderr;
+ }
+
+ void
+ gdbtk_release_stdio ()
+ {
+ /* restore the original stdio. */
+ gdb_stdout = tty_stdout;
+ gdb_stderr = tty_stderr;
+ }
+
+ void
+ gdbtk_null_stdio ()
+ {
+ /* null output */
+ gdb_stdout = null_stdout;
+ gdb_stderr = null_stderr;
}
/*
Index: gdbtk-variable.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk-variable.c,v
retrieving revision 2.7
diff -p -r2.7 gdbtk-variable.c
*** gdbtk-variable.c 1999/05/25 19:06:14 2.7
--- gdbtk-variable.c 1999/06/25 07:34:34
*************** create_variable (name, real_name, frame)
*** 546,553 ****
/* Several of the GDB_* calls can cause messages to be displayed. We swallow
those here, because we don't need them (the "value" command will
show them). */
! old_fputs = fputs_unfiltered_hook;
! fputs_unfiltered_hook = null_fputs;
/* Parse and evaluate the expression, filling in as much
of the variable's data as possible */
--- 546,552 ----
/* Several of the GDB_* calls can cause messages to be displayed. We swallow
those here, because we don't need them (the "value" command will
show them). */
! gdbtk_null_stdio ();
/* Parse and evaluate the expression, filling in as much
of the variable's data as possible */
*************** create_variable (name, real_name, frame)
*** 572,578 ****
FREEIF ((char *) var);
/* Restore the output hook to normal */
! fputs_unfiltered_hook = old_fputs;
return NULL;
}
--- 571,577 ----
FREEIF ((char *) var);
/* Restore the output hook to normal */
! gdbtk_claim_stdio ();
return NULL;
}
*************** create_variable (name, real_name, frame)
*** 584,590 ****
FREEIF (var);
/* Restore the output hook to normal */
! fputs_unfiltered_hook = old_fputs;
printf_unfiltered ("Attempt to use a type name as an expression.");
return NULL;
--- 583,589 ----
FREEIF (var);
/* Restore the output hook to normal */
! gdbtk_claim_stdio ();
printf_unfiltered ("Attempt to use a type name as an expression.");
return NULL;
*************** create_variable (name, real_name, frame)
*** 623,629 ****
GDB_select_frame (old_fi, -1);
/* Restore the output hook to normal */
! fputs_unfiltered_hook = old_fputs;
var->num_children = number_of_children (var);
var->format = variable_default_display (var);
--- 622,628 ----
GDB_select_frame (old_fi, -1);
/* Restore the output hook to normal */
! gdbtk_claim_stdio ();
var->num_children = number_of_children (var);
var->format = variable_default_display (var);
*************** variable_value_changed (var)
*** 1130,1137 ****
/* evaluate_expression can output errors to the screen,
so swallow them here. */
! old_hook = fputs_unfiltered_hook;
! fputs_unfiltered_hook = null_fputs;
/* Arrays, struct, classes, unions never change value */
if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_STRUCT
--- 1129,1135 ----
/* evaluate_expression can output errors to the screen,
so swallow them here. */
! gdbtk_null_stdio ();
/* Arrays, struct, classes, unions never change value */
if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_STRUCT
*************** variable_value_changed (var)
*** 1179,1185 ****
}
/* Restore the original fputs_hook. */
! fputs_unfiltered_hook = old_hook;
}
/* Restore selected frame */
--- 1177,1183 ----
}
/* Restore the original fputs_hook. */
! gdbtk_claim_stdio ();
}
/* Restore selected frame */
*************** call_gdb_type_print (val)
*** 1476,1483 ****
int result;
/* Save the old hook and install new hook */
! old_hook = fputs_unfiltered_hook;
! fputs_unfiltered_hook = variable_fputs;
/* Call our command with our args */
clear_gdb_output ();
--- 1474,1480 ----
int result;
/* Save the old hook and install new hook */
! gdbtk_null_stdio ();
/* Call our command with our args */
clear_gdb_output ();
*************** call_gdb_type_print (val)
*** 1489,1495 ****
result = TCL_ERROR;
/* Restore fputs hook */
! fputs_unfiltered_hook = old_hook;
return result;
}
--- 1486,1492 ----
result = TCL_ERROR;
/* Restore fputs hook */
! gdbtk_claim_stdio ();
return result;
}
*************** call_gdb_val_print (val, format)
*** 1505,1512 ****
int result;
/* Save the old hook and install new hook */
! old_hook = fputs_unfiltered_hook;
! fputs_unfiltered_hook = variable_fputs;
/* Call our command with our args */
clear_gdb_output ();
--- 1502,1508 ----
int result;
/* Save the old hook and install new hook */
! gdbtk_null_stdio ();
/* Call our command with our args */
clear_gdb_output ();
*************** call_gdb_val_print (val, format)
*** 1516,1522 ****
r = GDB_value_fetch_lazy (val);
if (r != GDB_OK)
{
! fputs_unfiltered_hook = old_hook;
return TCL_ERROR;
}
}
--- 1512,1518 ----
r = GDB_value_fetch_lazy (val);
if (r != GDB_OK)
{
! gdbtk_claim_stdio ();
return TCL_ERROR;
}
}
*************** call_gdb_val_print (val, format)
*** 1528,1534 ****
result = TCL_ERROR;
/* Restore fputs hook */
! fputs_unfiltered_hook = old_hook;
return result;
}
--- 1524,1530 ----
result = TCL_ERROR;
/* Restore fputs hook */
! gdbtk_claim_stdio ();
return result;
}
Index: gdbtk.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk.c,v
retrieving revision 2.135
diff -p -r2.135 gdbtk.c
*** gdbtk.c 1999/06/21 20:12:37 2.135
--- gdbtk.c 1999/06/25 07:34:35
*************** void gdbtk_add_hooks PARAMS ((void));
*** 112,125 ****
int gdbtk_test PARAMS ((char *));
- /*
- * gdbtk_fputs is defined in the gdbtk_hooks.c, but we need it here
- * because we delay adding this hook till all the setup is done. That
- * way errors will go to stdout.
- */
-
- extern void gdbtk_fputs PARAMS ((const char *, GDB_FILE *));
-
/* Handle for TCL interpreter */
Tcl_Interp *gdbtk_interp = NULL;
--- 112,117 ----
*************** gdbtk_find_main";
*** 525,531 ****
/* fputs_unfiltered_hook = NULL; */ /* Force errors to stdout/stderr */
! fputs_unfiltered_hook = gdbtk_fputs;
if (Tcl_GlobalEval (gdbtk_interp, (char *) script) != TCL_OK)
{
--- 517,524 ----
/* fputs_unfiltered_hook = NULL; */ /* Force errors to stdout/stderr */
! /* create custom GDBtk streams. */
! gdbtk_claim_stdio ();
if (Tcl_GlobalEval (gdbtk_interp, (char *) script) != TCL_OK)
{
*************** gdbtk_find_main";
*** 536,542 ****
msg = Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY);
! fputs_unfiltered_hook = NULL; /* Force errors to stdout/stderr */
#ifdef _WIN32
MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
--- 529,535 ----
msg = Tcl_GetVar (gdbtk_interp, "errorInfo", TCL_GLOBAL_ONLY);
! gdbtk_release_stdio (); /* Force errors to stdout/stderr */
#ifdef _WIN32
MessageBox (NULL, msg, NULL, MB_OK | MB_ICONERROR | MB_TASKMODAL);
Index: gdbtk.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk.h,v
retrieving revision 2.8
diff -p -r2.8 gdbtk.h
*** gdbtk.h 1999/04/02 18:33:13 2.8
--- gdbtk.h 1999/06/25 07:34:35
*************** extern int x_event PARAMS ((int));
*** 149,154 ****
--- 149,159 ----
extern int gdbtk_two_elem_cmd PARAMS ((char *, char *));
extern int call_wrapper PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST []));
+ /* GDBtk stdio control functions. */
+ extern void gdbtk_claim_stdio PARAMS ((void));
+ extern void gdbtk_release_stdio PARAMS ((void));
+ extern void gdbtk_null_stdio PARAMS ((void));
+
#ifdef _WIN32
extern void close_bfds ();
#endif /* _WIN32 */