This is the mail archive of the insight@sourceware.cygnus.com mailing list for the Insight project.


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

RFA: gdbtk using ``struct gdb_file *''


Hello,

The attached patch makes the minimum number of changes I can find that
get Insight to use a ``struct gdb_file'' object instead of the old
fputs_unfiltered_hook.  The ``struct gdb_file'' object provide a
tighter, more controlled, mechanism for managing GDB's stdout, stderr,
targout and stdlog data streams. 

With this patch in place, it starts to be come possible for GDBtk to
differentiates between the various output streams: target output in a
separate window; log messages in red (on a blue background? ;-); ...

If you look carefully, you'll notice that I didn't entirely succeed in
my quest.  gdbtk-variable.c still uses fputs_unfiltered_hook :-(  That
can, however, be fixed in a second pass.

Comments? Suggestions? Further tests?

		Andrew

Mon Sep 20 12:18:24 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_fputs): Delete declaration.

	* gdbtk.h (enum gdbtk_stdio): Declare.
	(gdbtk_set_stdio): Declare.
	* gdbtk-hooks.c (gdbtk_set_stdio): New function.  Switch GDBtk's
 	output.

	* gdbtk.c (gdbtk_init), gdbtk-cmds.c (gdb_restore_fputs): Use
 	gdbtk_set_stdio instead of modifying fputs_unfiltered_hook
 	directly.
Index: gdbtk-cmds.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk-cmds.c,v
retrieving revision 2.58
diff -p -r2.58 gdbtk-cmds.c
*** gdbtk-cmds.c	1999/09/19 06:12:27	2.58
--- gdbtk-cmds.c	1999/09/20 06:24:31
*************** gdb_restore_fputs (clientData, interp, o
*** 1820,1827 ****
       int objc;
       Tcl_Obj *CONST objv[];
  {
!     fputs_unfiltered_hook = gdbtk_fputs;
!     return TCL_OK;
  }
  
  /* This implements the TCL command `gdb_regnames', which returns a list of
--- 1820,1827 ----
       int objc;
       Tcl_Obj *CONST objv[];
  {
!   gdbtk_set_stdio (GDBTK_STDIO_TCL);
!   return TCL_OK;
  }
  
  /* This implements the TCL command `gdb_regnames', which returns a list of
Index: gdbtk-hooks.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk-hooks.c,v
retrieving revision 2.28
diff -p -r2.28 gdbtk-hooks.c
*** gdbtk-hooks.c	1999/09/03 10:15:31	2.28
--- gdbtk-hooks.c	1999/09/20 06:24:31
*************** static void gdbtk_warning PARAMS ((const
*** 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,115 ****
  static void report_error (void);
  static void gdbtk_annotate_signal (void);
  static void gdbtk_set_hook (struct cmd_list_element *cmdblk);
! 
! /*
!  * 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_set_hook (struct cmd_list_element *cmdblk);
! static void gdbtk_fputs (const char *, struct gdb_file *);
  int gdbtk_load_hash PARAMS ((char *, unsigned long));
  static void breakpoint_notify PARAMS ((struct breakpoint *, const char *));
  
*************** gdbtk_add_hooks (void)
*** 131,137 ****
    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;
--- 124,129 ----
*************** gdbtk_add_hooks (void)
*** 164,171 ****
  }
  
  /* 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
--- 156,164 ----
  }
  
  /* 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
*************** gdbtk_two_elem_cmd (cmd_name, argv1)
*** 208,224 ****
    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
--- 201,206 ----
*************** gdbtk_flush (stream)
*** 239,249 ****
   *
   */
  
! void
! gdbtk_fputs (ptr, stream)
!      const char *ptr;
!      GDB_FILE *stream;
  {
    in_fputs = 1;
  
    if (result_ptr != NULL)
--- 221,252 ----
   *
   */
  
! static int gdbtk_file_magic;
! 
! struct gdbtk_file
  {
+   int *magic;
+ };
+ 
+ static void
+ gdbtk_fputs (const char *ptr, struct gdb_file *stream)
+ {
+   /* FIXME: cagney/1999-09-20: The gdbtk-variable.c code uses the
+      fputs_unfiltered_hook to either disable or re-direct gdbtk_stdout
+      and gdbtk_stderr. Once that code has been re-written to use a
+      cleaner output-capture mechanism the check/call to
+      fputs_unfiltered_hook, below, can be deleted. */
+   /* FIXME: cagney/1999-09-20: Should this code be wrapped in the
+      in_fputs semaphore? The original code that this is replicating
+      didn't. */
+   if (fputs_unfiltered_hook)
+     {
+       fputs_unfiltered_hook (ptr, stream);
+       return;
+     }
+ 
+   /* 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)
*** 280,285 ****
--- 283,351 ----
  
    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;
+ }
+ 
+ enum gdbtk_stdio
+ gdbtk_set_stdio (enum gdbtk_stdio new_stdio)
+ {
+   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 enum gdbtk_stdio current_stdio;
+   static int done;
+   /* Initialize the various gdbtk_files. */
+   if (!done)
+     {
+       /* save the original gdb_stdout/gdb_stderr. */
+       tty_stdout = gdb_stdout;
+       tty_stderr = gdb_stderr;
+       current_stdio = GDBTK_STDIO_TTY;
+       /* create GDBtk's stdout/stderr. */
+       gdbtk_stdout = gdbtk_file_new ();
+       gdbtk_stderr = gdbtk_file_new ();
+       done = 1;
+     }
+   /* Flip stdout/stderr as requested. */
+   {
+     enum gdbtk_stdio old_stdio = current_stdio;
+     switch (new_stdio)
+       {
+       case GDBTK_STDIO_TTY:
+ 	gdb_stdout = tty_stdout;
+ 	gdb_stderr = tty_stderr;
+ 	break;
+       case GDBTK_STDIO_TCL:
+ 	gdb_stdout = gdbtk_stdout;
+ 	gdb_stderr = gdbtk_stderr;
+ 	break;
+       }
+     current_stdio = new_stdio;
+     return old_stdio;
+   }
+ }
+ 
  
  /*
   * This routes all warnings to the Tcl function "gdbtk_tcl_warning".
Index: gdbtk.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk.c,v
retrieving revision 2.143
diff -p -r2.143 gdbtk.c
*** gdbtk.c	1999/09/19 06:12:27	2.143
--- gdbtk.c	1999/09/20 06:24:33
*************** proc gdbtk_find_main {} {\n\
*** 523,531 ****
  gdbtk_find_main";
  #endif /* NO_TCLPRO_DEBUGGER */
  
!     /* fputs_unfiltered_hook = NULL; *//* Force errors to stdout/stderr */
! 
!     fputs_unfiltered_hook = gdbtk_fputs;
  
      if (Tcl_GlobalEval (gdbtk_interp, (char *) script) != TCL_OK)
        {
--- 523,530 ----
  gdbtk_find_main";
  #endif /* NO_TCLPRO_DEBUGGER */
  
!     /* gdbtk_set_stdio (GDBTK_STDIO_TTY); *//* Force errors to stdout/stderr */
!     gdbtk_set_stdio (GDBTK_STDIO_TCL);
  
      if (Tcl_GlobalEval (gdbtk_interp, (char *) script) != TCL_OK)
        {
Index: gdbtk.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/gdbtk.h,v
retrieving revision 2.12
diff -p -r2.12 gdbtk.h
*** gdbtk.h	1999/08/28 01:30:09	2.12
--- gdbtk.h	1999/09/20 06:24:33
*************** extern int x_event PARAMS ((int));
*** 154,160 ****
  extern int gdbtk_two_elem_cmd PARAMS ((char *, char *));
  extern int call_wrapper PARAMS ((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST[]));
  extern int target_is_native PARAMS ((struct target_ops *t));
- extern void gdbtk_fputs PARAMS ((const char *, GDB_FILE *));
  
  #ifdef _WIN32
  extern void close_bfds ();
--- 154,159 ----
*************** extern void
*** 169,174 ****
--- 168,183 ----
        (SYMBOL_DEMANGLED_NAME (symbol) != NULL \
         ? SYMBOL_DEMANGLED_NAME (symbol)       \
         : SYMBOL_NAME (symbol))
+ 
+ /* Control GDB_STDOUT and GDB_STDERR.  GDBtk normally captures all
+    output in a buffer (intended for TCL). */
+ 
+ enum gdbtk_stdio {
+   GDBTK_STDIO_TTY, /* Output goes to the attached terminal. */
+   GDBTK_STDIO_TCL /* Output goes direct to TCL */
+ };
+ 
+ enum gdbtk_stdio gdbtk_set_stdio (enum gdbtk_stdio val);
  
  /* Local variables: */
  /* change-log-default-name: "ChangeLog-gdbtk" */

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