From: Daniel Jacobowitz Date: Sat, 28 Jun 2003 16:19:07 +0000 (+0000) Subject: ./ X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0fac0b4199c69f27906e7343e434dd0b98e5163e;p=binutils-gdb.git ./ * cli/cli-logging.c: New file. * 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". mi/ * mi-out.c (mi_ui_out_impl): Add NULL for redirect member. tui/ * tui-out.c (tui_ui_out_impl): Add NULL for redirect member. doc/ * gdb.texinfo (Logging output): New chapter. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 30ef061bd9f..e3f1554a2ba 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2003-06-28 Daniel Jacobowitz + + * cli/cli-logging.c: New file. + * 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-27 Elena Zannoni * config/powerpc/ppc64-linux.mh (NATDEPFILES): Add linux-nat.o. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 28433cd09af..8d056d84791 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -146,10 +146,12 @@ TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@ 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_h) $(symtab_h) $(gdbcmd_h) \ # 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 $(defs_h) $(gdb_string_h) \ 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) diff --git a/gdb/NEWS b/gdb/NEWS index 604f085cc9d..6b853e6911a 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,10 @@ *** Changes since 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. *** Changes in GDB 6.0: diff --git a/gdb/cli-out.c b/gdb/cli-out.c index 38bf36ffaf2..2e5a3c16b16 100644 --- a/gdb/cli-out.c +++ b/gdb/cli-out.c @@ -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 *uiout, int verbosity, 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_impl = 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); } diff --git a/gdb/cli/cli-logging.c b/gdb/cli/cli-logging.c new file mode 100644 index 00000000000..67ec672931b --- /dev/null +++ b/gdb/cli/cli-logging.c @@ -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"); +} diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 3d396013241..fe7da200af9 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2003-06-28 Daniel Jacobowitz + + * gdb.texinfo (Logging output): New chapter. + 2003-06-24 Joel Brobecker * gdb.texinfo (Unsupported languages): New section. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 05715e137df..e6da37c3b80 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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 @@ -1210,6 +1211,32 @@ 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 @chapter @value{GDBN} Commands diff --git a/gdb/mi/ChangeLog b/gdb/mi/ChangeLog index ed861f023bc..f4a4ad810dc 100644 --- a/gdb/mi/ChangeLog +++ b/gdb/mi/ChangeLog @@ -1,3 +1,7 @@ +2003-06-28 Daniel Jacobowitz + + * mi-out.c (mi_ui_out_impl): Add NULL for redirect member. + 2003-06-17 Daniel Jacobowitz * mi-cmds.c (mi_cmds): Add "-target-disconnect". diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c index 2aac5289829..637ceb42ca1 100644 --- a/gdb/mi/mi-out.c +++ b/gdb/mi/mi-out.c @@ -86,6 +86,7 @@ struct ui_out_impl mi_ui_out_impl = mi_message, mi_wrap_hint, mi_flush, + NULL, 1, /* Needs MI hacks. */ }; diff --git a/gdb/tui/ChangeLog b/gdb/tui/ChangeLog index 9ab34614aa0..aa2fc5a87a0 100644 --- a/gdb/tui/ChangeLog +++ b/gdb/tui/ChangeLog @@ -1,3 +1,7 @@ +2003-06-28 Daniel Jacobowitz + + * tui-out.c (tui_ui_out_impl): Add NULL for redirect member. + 2003-06-22 Daniel Jacobowitz * tui-hooks.c: Update include order. diff --git a/gdb/tui/tui-out.c b/gdb/tui/tui-out.c index 94fda09b14c..e1be56a6b00 100644 --- a/gdb/tui/tui-out.c +++ b/gdb/tui/tui-out.c @@ -90,6 +90,7 @@ static struct ui_out_impl tui_ui_out_impl = tui_message, tui_wrap_hint, tui_flush, + NULL, 0, /* Does not need MI hacks (i.e. needs CLI hacks). */ }; diff --git a/gdb/ui-out.c b/gdb/ui-out.c index 71e6d6ac070..5fb8eaa69e8 100644 --- a/gdb/ui-out.c +++ b/gdb/ui-out.c @@ -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 *uiout, int verbosity, 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) @@ -981,6 +989,15 @@ uo_flush (struct ui_out *uiout) 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 */ /* list of column headers manipulation routines */ diff --git a/gdb/ui-out.h b/gdb/ui-out.h index a52c3453722..3102e750ca5 100644 --- a/gdb/ui-out.h +++ b/gdb/ui-out.h @@ -231,6 +231,8 @@ typedef void (message_ftype) (struct ui_out * uiout, int verbosity, 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; }; @@ -266,4 +269,8 @@ 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 */