From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31693 invoked by alias); 23 Jun 2003 22:15:40 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 10234 invoked from network); 23 Jun 2003 21:48:25 -0000 Received: from unknown (HELO crack.them.org) (146.82.138.56) by sources.redhat.com with SMTP; 23 Jun 2003 21:48:25 -0000 Received: from dsl093-172-017.pit1.dsl.speakeasy.net ([66.93.172.17] helo=nevyn.them.org ident=mail) by crack.them.org with asmtp (Exim 3.12 #1 (Debian)) id 19UZBd-0005Dh-00 for ; Mon, 23 Jun 2003 16:49:18 -0500 Received: from drow by nevyn.them.org with local (Exim 3.36 #1 (Debian)) id 19UZAk-0005To-00 for ; Mon, 23 Jun 2003 17:48:22 -0400 Date: Mon, 23 Jun 2003 22:15:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: Re: RFC: "set logging" Message-ID: <20030623214822.GA12881@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com References: <20030622205322.GA14138@nevyn.them.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20030622205322.GA14138@nevyn.them.org> User-Agent: Mutt/1.5.1i X-SW-Source: 2003-06/txt/msg00743.txt.bz2 On Sun, Jun 22, 2003 at 04:53:22PM -0400, Daniel Jacobowitz wrote: > As discussed earlier: > set logging on [FILE] > set logging off > set logging overwrite [I changed the default to append] > set logging redirect > set logging file > show logging > > I decided that one-off command logging was really a different class of thing > from this patch, which is straight output logging, not really script-useful > redirection. So that's gone. > > Is this OK? Any comments? Docs OK? Here's an update, based on feedback. Barring comments I'll commit it in a couple of days to mainline, and next week to the branch. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer 2003-06-23 Daniel Jacobowitz * cli-out.c (struct ui_out_data): Add original_stream. (cli_redirect): New function. (cli_ui_out_impl): Add cli_redirect. (cli_out_new): Initialize original_stream. * ui-out.c (default_ui_out_impl): Add NULL for redirect member. (uo_redirect, ui_out_redirect): New. * ui-out.h (struct ui_out_impl): Add redirect member. (redirect_ftype): New. (ui_out_redirect): Add prototype. * Makefile.in: Add rules for cli-logging.c. * NEWS: Mention "set logging". 2003-06-23 Daniel Jacobowitz * cli-logging.c: New file. 2003-06-23 Daniel Jacobowitz * mi-out.c (mi_ui_out_impl): Add NULL for redirect member. 2003-06-23 Daniel Jacobowitz * tui-out.c (tui_ui_out_impl): Add NULL for redirect member. 2003-06-23 Daniel Jacobowitz * gdb.texinfo (Logging output): New chapter. Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.410 diff -u -p -r1.410 Makefile.in --- Makefile.in 21 Jun 2003 23:14:43 -0000 1.410 +++ Makefile.in 23 Jun 2003 21:41:42 -0000 @@ -146,10 +146,12 @@ TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYST SUBDIR_CLI_OBS = \ cli-dump.o \ cli-decode.o cli-script.o cli-cmds.o cli-setshow.o cli-utils.o \ + cli-logging.o \ cli-interp.o SUBDIR_CLI_SRCS = \ cli/cli-dump.c \ cli/cli-decode.c cli/cli-script.c cli/cli-cmds.c cli/cli-setshow.c \ + cli/cli-logging.c \ cli/cli-interp.c \ cli/cli-utils.c SUBDIR_CLI_DEPS = @@ -2410,7 +2412,7 @@ z8k-tdep.o: z8k-tdep.c $(defs_h) $(frame # gdb/cli/ dependencies # # Need to explicitly specify the compile rule as make will do nothing -# or try to compile the object file into the mi directory. +# or try to compile the object file into the cli directory. cli-cmds.o: $(srcdir)/cli/cli-cmds.c $(defs_h) $(completer_h) $(target_h) \ $(gdb_wait_h) $(gdb_regex_h) $(gdb_string_h) $(filenames_h) \ @@ -2429,6 +2431,8 @@ cli-dump.o: $(srcdir)/cli/cli-dump.c $(d cli-interp.o: $(srcdir)/cli/cli-interp.c $(defs_h) $(interps_h) $(wrapper_h) \ $(event_top_h) $(ui_out_h) $(cli_out_h) $(top_h) $(gdb_string_h) $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-interp.c +cli-logging.o: $(srcdir)/cli/cli-logging.c $(defs_h) $(ui_out_h) $(gdbcmd_h) + $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/cli/cli-logging.c cli-script.o: $(srcdir)/cli/cli-script.c $(defs_h) $(value_h) $(language_h) \ $(ui_out_h) $(gdb_string_h) $(top_h) $(cli_cmds_h) $(cli_decode_h) \ $(cli_script_h) Index: NEWS =================================================================== RCS file: /cvs/src/src/gdb/NEWS,v retrieving revision 1.111 diff -u -p -r1.111 NEWS --- NEWS 23 Jun 2003 03:28:13 -0000 1.111 +++ NEWS 23 Jun 2003 21:41:43 -0000 @@ -6,6 +6,11 @@ *** Changes in GDB 6.0: +* GDB supports logging output to a file + +There are two new commands, "set logging" and "show logging", which can be +used to capture GDB's output to a file. + * The meaning of "detach" has changed for gdbserver The "detach" command will now resume the application, as documented. To Index: cli-out.c =================================================================== RCS file: /cvs/src/src/gdb/cli-out.c,v retrieving revision 1.16 diff -u -p -r1.16 cli-out.c --- cli-out.c 8 Mar 2003 20:04:27 -0000 1.16 +++ cli-out.c 23 Jun 2003 21:41:43 -0000 @@ -31,6 +31,7 @@ struct ui_out_data { struct ui_file *stream; + struct ui_file *original_stream; int suppress_output; }; typedef struct ui_out_data cli_out_data; @@ -64,6 +65,7 @@ static void cli_message (struct ui_out * const char *format, va_list args); static void cli_wrap_hint (struct ui_out *uiout, char *identstring); static void cli_flush (struct ui_out *uiout); +static int cli_redirect (struct ui_out *uiout, struct ui_file *outstream); /* This is the CLI ui-out implementation functions vector */ @@ -87,6 +89,7 @@ static struct ui_out_impl cli_ui_out_imp cli_message, cli_wrap_hint, cli_flush, + cli_redirect, 0, /* Does not need MI hacks (i.e. needs CLI hacks). */ }; @@ -324,6 +327,24 @@ cli_flush (struct ui_out *uiout) gdb_flush (data->stream); } +int +cli_redirect (struct ui_out *uiout, struct ui_file *outstream) +{ + struct ui_out_data *data = ui_out_data (uiout); + if (outstream != NULL) + { + data->original_stream = data->stream; + data->stream = outstream; + } + else if (data->original_stream != NULL) + { + data->stream = data->original_stream; + data->original_stream = NULL; + } + + return 0; +} + /* local functions */ /* Like cli_field_fmt, but takes a variable number of args @@ -362,6 +383,7 @@ cli_out_new (struct ui_file *stream) cli_out_data *data = XMALLOC (cli_out_data); data->stream = stream; + data->original_stream = NULL; data->suppress_output = 0; return ui_out_new (&cli_ui_out_impl, data, flags); } Index: ui-out.c =================================================================== RCS file: /cvs/src/src/gdb/ui-out.c,v retrieving revision 1.27 diff -u -p -r1.27 ui-out.c --- ui-out.c 8 Jun 2003 18:27:14 -0000 1.27 +++ ui-out.c 23 Jun 2003 21:41:43 -0000 @@ -206,6 +206,7 @@ struct ui_out_impl default_ui_out_impl = default_message, default_wrap_hint, default_flush, + NULL, 0, /* Does not need MI hacks. */ }; @@ -254,6 +255,7 @@ static void uo_message (struct ui_out *u const char *format, va_list args); static void uo_wrap_hint (struct ui_out *uiout, char *identstring); static void uo_flush (struct ui_out *uiout); +static int uo_redirect (struct ui_out *uiout, struct ui_file *outstream); /* Prototypes for local functions */ @@ -638,6 +640,12 @@ ui_out_flush (struct ui_out *uiout) uo_flush (uiout); } +int +ui_out_redirect (struct ui_out *uiout, struct ui_file *outstream) +{ + return uo_redirect (uiout, outstream); +} + /* set the flags specified by the mask given */ int ui_out_set_flags (struct ui_out *uiout, int mask) @@ -979,6 +987,15 @@ uo_flush (struct ui_out *uiout) if (!uiout->impl->flush) return; uiout->impl->flush (uiout); +} + +int +uo_redirect (struct ui_out *uiout, struct ui_file *outstream) +{ + if (!uiout->impl->redirect) + return -1; + uiout->impl->redirect (uiout, outstream); + return 0; } /* local functions */ Index: ui-out.h =================================================================== RCS file: /cvs/src/src/gdb/ui-out.h,v retrieving revision 1.17 diff -u -p -r1.17 ui-out.h --- ui-out.h 3 Feb 2003 01:18:37 -0000 1.17 +++ ui-out.h 23 Jun 2003 21:41:43 -0000 @@ -231,6 +231,8 @@ typedef void (message_ftype) (struct ui_ const char *format, va_list args); typedef void (wrap_hint_ftype) (struct ui_out * uiout, char *identstring); typedef void (flush_ftype) (struct ui_out * uiout); +typedef int (redirect_ftype) (struct ui_out * uiout, + struct ui_file * outstream); /* ui-out-impl */ @@ -254,6 +256,7 @@ struct ui_out_impl message_ftype *message; wrap_hint_ftype *wrap_hint; flush_ftype *flush; + redirect_ftype *redirect; int is_mi_like_p; }; @@ -265,5 +268,9 @@ extern struct ui_out_data *ui_out_data ( extern struct ui_out *ui_out_new (struct ui_out_impl *impl, struct ui_out_data *data, int flags); + +/* Redirect the ouptut of a ui_out object temporarily. */ + +extern int ui_out_redirect (struct ui_out *uiout, struct ui_file *outstream); #endif /* UI_OUT_H */ Index: cli/cli-logging.c =================================================================== RCS file: cli/cli-logging.c diff -N cli/cli-logging.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ cli/cli-logging.c 23 Jun 2003 21:41:43 -0000 @@ -0,0 +1,205 @@ +/* Command-line output logging for GDB, the GNU debugger. + + Copyright 2003 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcmd.h" +#include "ui-out.h" + +#include "gdb_string.h" + +/* These hold the pushed copies of the gdb output files. + If NULL then nothing has yet been pushed. */ +struct saved_output_files +{ + struct ui_file *out; + struct ui_file *err; + struct ui_file *log; + struct ui_file *targ; +}; +static struct saved_output_files saved_output; +static char *saved_filename; + +static char *logging_filename; +int logging_overwrite, logging_redirect; + +/* If we've pushed output files, close them and pop them. */ +static void +pop_output_files () +{ + /* Only delete one of the files -- they are all set to the same + value. */ + ui_file_delete (gdb_stdout); + gdb_stdout = saved_output.out; + gdb_stderr = saved_output.err; + gdb_stdlog = saved_output.log; + gdb_stdtarg = saved_output.targ; + saved_output.out = NULL; + saved_output.err = NULL; + saved_output.log = NULL; + saved_output.targ = NULL; + + ui_out_redirect (uiout, NULL); +} + +/* This is a helper for the `set logging' command. */ +static void +handle_redirections (int from_tty) +{ + struct ui_file *output; + + if (saved_filename != NULL) + { + fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n", + saved_filename); + return; + } + + output = gdb_fopen (logging_filename, logging_overwrite ? "w" : "a"); + if (output == NULL) + perror_with_name ("set logging"); + + /* Redirects everything to gdb_stdout while this is running. */ + if (!logging_redirect) + { + output = tee_file_new (gdb_stdout, 0, output, 1); + if (output == NULL) + perror_with_name ("set logging"); + if (from_tty) + fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n", + logging_filename); + } + else if (from_tty) + fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n", + logging_filename); + + saved_filename = xstrdup (logging_filename); + saved_output.out = gdb_stdout; + saved_output.err = gdb_stderr; + saved_output.log = gdb_stdlog; + saved_output.targ = gdb_stdtarg; + + gdb_stdout = output; + gdb_stderr = output; + gdb_stdlog = output; + gdb_stdtarg = output; + + if (ui_out_redirect (uiout, gdb_stdout) < 0) + warning ("Current output protocol does not support redirection"); +} + +static void +set_logging_on (char *args, int from_tty) +{ + char *rest = args; + if (rest && *rest) + { + xfree (logging_filename); + logging_filename = xstrdup (rest); + } + handle_redirections (from_tty); +} + +static void +set_logging_off (char *args, int from_tty) +{ + if (saved_filename == NULL) + return; + + pop_output_files (); + if (from_tty) + fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename); + xfree (saved_filename); + saved_filename = NULL; +} + +static void +set_logging_command (char *args, int from_tty) +{ + printf_unfiltered ("\"set logging\" lets you log output to a file.\n"); + printf_unfiltered ("Usage: set logging on [FILENAME]\n"); + printf_unfiltered (" set logging off\n"); + printf_unfiltered (" set logging file FILENAME\n"); + printf_unfiltered (" set logging overwrite [on|off]\n"); + printf_unfiltered (" set logging redirect [on|off]\n"); +} + +void +show_logging_command (char *args, int from_tty) +{ + if (saved_filename) + printf_unfiltered ("Currently logging to \"%s\".\n", saved_filename); + if (saved_filename == NULL + || strcmp (logging_filename, saved_filename) != 0) + printf_unfiltered ("Future logs will be written to %s.\n", + logging_filename); + + if (logging_overwrite) + printf_unfiltered ("Logs will overwrite the log file.\n"); + else + printf_unfiltered ("Logs will be appended to the log file.\n"); + + if (logging_redirect) + printf_unfiltered ("Output will be sent only to the log file.\n"); + else + printf_unfiltered ("Output will be logged and displayed.\n"); +} + +void +_initialize_cli_logging (void) +{ + static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist; + + + add_prefix_cmd ("logging", class_support, set_logging_command, + "Set logging options", &set_logging_cmdlist, + "set logging ", 0, &setlist); + add_prefix_cmd ("logging", class_support, show_logging_command, + "Show logging options", &show_logging_cmdlist, + "show logging ", 0, &showlist); + add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite, + "Set whether logging overwrites or appends " + "to the log file.\n", + "Show whether logging overwrites or appends " + "to the log file.\n", + NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist); + add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, + "Set the logging output mode.\n" + "If redirect is off, output will go to both the " + "screen and the log file.\n" + "If redirect is on, output will go only to the log " + "file.", + "Show the logging output mode.\n" + "If redirect is off, output will go to both the " + "screen and the log file.\n" + "If redirect is on, output will go only to the log " + "file.", + NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist); + add_setshow_cmd ("file", class_support, var_filename, &logging_filename, + "Set the current logfile.", "Show the current logfile.", + NULL, NULL, &set_logging_cmdlist, &show_logging_cmdlist); + add_cmd ("on", class_support, set_logging_on, + "Enable logging.", &set_logging_cmdlist); + add_cmd ("off", class_support, set_logging_off, + "Disable logging.", &set_logging_cmdlist); + + logging_filename = xstrdup ("gdb.txt"); +} Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.167 diff -u -p -r1.167 gdb.texinfo --- doc/gdb.texinfo 23 Jun 2003 03:28:14 -0000 1.167 +++ doc/gdb.texinfo 23 Jun 2003 21:41:46 -0000 @@ -757,6 +757,7 @@ type @kbd{quit} or @kbd{C-d} to exit. * Invoking GDB:: How to start @value{GDBN} * Quitting GDB:: How to quit @value{GDBN} * Shell Commands:: How to use shell commands inside @value{GDBN} +* Logging output:: How to log @value{GDBN}'s output to a file @end menu @node Invoking GDB @@ -1208,6 +1209,32 @@ You do not have to use the @code{shell} @item make @var{make-args} Execute the @code{make} program with the specified arguments. This is equivalent to @samp{shell make @var{make-args}}. +@end table + +@node Logging output +@section Logging output +@cindex logging @value{GDBN} output + +You may want to save the output of @value{GDBN} commands to a file. +There are several commands to control @value{GDBN}'s logging. + +@table @code +@kindex set logging +@item set logging on +Enable logging. +@item set logging off +Disable logging. +@item set logging file @var{file} +Change the name of the current logfile. The default logfile is @file{gdb.txt}. +@item set logging overwrite [on|off] +By default, @value{GDBN} will append to the logfile. Set @code{overwrite} if +you want @code{set logging on} to overwrite the logfile instead. +@item set logging redirect [on|off] +By default, @value{GDBN} output will go to both the terminal and the logfile. +Set @code{redirect} if you want output to go only to the log file. +@kindex show logging +@item show logging +Show the current values of the logging settings. @end table @node Commands Index: mi/mi-out.c =================================================================== RCS file: /cvs/src/src/gdb/mi/mi-out.c,v retrieving revision 1.26 diff -u -p -r1.26 mi-out.c --- mi/mi-out.c 8 Mar 2003 20:04:27 -0000 1.26 +++ mi/mi-out.c 23 Jun 2003 21:41:46 -0000 @@ -86,6 +86,7 @@ struct ui_out_impl mi_ui_out_impl = mi_message, mi_wrap_hint, mi_flush, + NULL, 1, /* Needs MI hacks. */ }; Index: tui/tui-out.c =================================================================== RCS file: /cvs/src/src/gdb/tui/tui-out.c,v retrieving revision 1.5 diff -u -p -r1.5 tui-out.c --- tui/tui-out.c 13 Mar 2003 20:24:06 -0000 1.5 +++ tui/tui-out.c 23 Jun 2003 21:41:47 -0000 @@ -90,6 +90,7 @@ static struct ui_out_impl tui_ui_out_imp tui_message, tui_wrap_hint, tui_flush, + NULL, 0, /* Does not need MI hacks (i.e. needs CLI hacks). */ };