From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21339 invoked by alias); 22 Jun 2003 20:53:27 -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 21282 invoked from network); 22 Jun 2003 20:53:25 -0000 Received: from unknown (HELO crack.them.org) (146.82.138.56) by sources.redhat.com with SMTP; 22 Jun 2003 20:53: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 19UBqr-0002vF-00 for ; Sun, 22 Jun 2003 15:54:17 -0500 Received: from drow by nevyn.them.org with local (Exim 3.36 #1 (Debian)) id 19UBpy-0003gj-00 for ; Sun, 22 Jun 2003 16:53:22 -0400 Date: Sun, 22 Jun 2003 20:53:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sources.redhat.com Subject: RFC: "set logging" Message-ID: <20030622205322.GA14138@nevyn.them.org> Mail-Followup-To: gdb-patches@sources.redhat.com Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.1i X-SW-Source: 2003-06/txt/msg00713.txt.bz2 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? -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer 2003-06-22 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. * top.c (handle_redirections, pop_output_files): New functions. (set_logging_help, set_logging_command, show_logging_command): New functions. (init_main): Create "set logging" and "show logging" commands. 2003-06-22 Daniel Jacobowitz * mi-out.c (mi_ui_out_impl): Add NULL for redirect member. 2003-06-22 Daniel Jacobowitz * tui-out.c (tui_ui_out_impl): Add NULL for redirect member. 2003-06-22 Daniel Jacobowitz * gdb.texinfo (Logging output): New chapter. 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 22 Jun 2003 20:47:08 -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: top.c =================================================================== RCS file: /cvs/src/src/gdb/top.c,v retrieving revision 1.73 diff -u -p -r1.73 top.c --- top.c 8 Jun 2003 18:27:14 -0000 1.73 +++ top.c 22 Jun 2003 20:47:09 -0000 @@ -1746,6 +1746,224 @@ dont_repeat_command (char *ignored, int necessarily reading from stdin. */ } +/* Functions and variables for gdb output redirection. */ + +/* These hold the pushed copies of the gdb output files. + If NULL then nothing has yet been pushed. */ +static struct ui_file *saved_stdout; +static struct ui_file *saved_stderr; +static struct ui_file *saved_stdlog; +static struct ui_file *saved_stdtarg; +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_stdout; + gdb_stderr = saved_stderr; + gdb_stdlog = saved_stdlog; + gdb_stdtarg = saved_stdtarg; + saved_stdout = NULL; + saved_stderr = NULL; + saved_stdlog = NULL; + saved_stdtarg = 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_stdout = gdb_stdout; + saved_stderr = gdb_stderr; + saved_stdlog = gdb_stdlog; + saved_stdtarg = 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_help () +{ + printf_unfiltered ("Usage: set logging on [FILENAME]\n"); + printf_unfiltered (" set logging off\n"); + printf_unfiltered (" set logging FILENAME\n"); + printf_unfiltered (" set logging overwrite [on|off]\n"); + printf_unfiltered (" set logging append [on|off]\n"); +} + +static void +set_logging_command (char *args, int from_tty) +{ + char *first_word, *rest; + + if (args == NULL) + { + set_logging_help (); + return; + } + + /* Find the first word and the rest of the line. */ + first_word = args; + rest = first_word; + while (*rest && !isspace (*rest)) + rest++; + if (*rest) + { + *rest = '\0'; + rest++; + while (*rest && isspace (*rest)) + rest++; + } + if (*rest == '\0') + rest = NULL; + + if (strcmp (first_word, "off") == 0) + { + if (rest) + { + set_logging_help (); + return; + } + + 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; + return; + } + + if (strcmp (first_word, "on") == 0) + { + if (rest) + { + xfree (logging_filename); + logging_filename = xstrdup (rest); + } + if (!logging_filename) + logging_filename = xstrdup ("gdb.txt"); + + handle_redirections (from_tty); + return; + } + + if (strcmp (first_word, "file") == 0) + { + if (rest == NULL) + { + set_logging_help (); + return; + } + + if (logging_filename) + xfree (logging_filename); + logging_filename = xstrdup (rest); + return; + } + + if (strcmp (first_word, "overwrite") == 0) + { + if (rest == NULL + || strcmp (rest, "1") == 0 + || strcmp (rest, "true") == 0 + || strcmp (rest, "on") == 0) + logging_overwrite = 1; + else if (strcmp (rest, "0") == 0 + || strcmp (rest, "false") == 0 + || strcmp (rest, "off") == 0) + logging_overwrite = 0; + else + set_logging_help (); + return; + } + + if (strcmp (first_word, "redirect") == 0) + { + if (rest == NULL + || strcmp (rest, "1") == 0 + || strcmp (rest, "true") == 0 + || strcmp (rest, "on") == 0) + logging_redirect = 1; + else if (strcmp (rest, "0") == 0 + || strcmp (rest, "false") == 0 + || strcmp (rest, "off") == 0) + logging_redirect = 0; + else + set_logging_help (); + return; + } + + set_logging_help (); + return; +} + +void +show_logging_command (char *args, int from_tty) +{ + if (saved_filename) + printf_unfiltered ("Currently logging to %s.\n", saved_filename); + if (logging_filename == NULL || saved_filename == NULL + || strcmp (logging_filename, saved_filename) != 0) + printf_unfiltered ("Future logs will be written to %s.\n", + logging_filename ? logging_filename : "gdb.txt"); + + 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"); +} + /* Functions to manipulate command line editing control variables. */ /* Number of commands to print in each call to show_commands. */ @@ -2080,6 +2298,11 @@ ie. the number of previous commands to k Use \"on\" to enable the notification, and \"off\" to disable it.", &setlist), &showlist); } + + add_cmd ("logging", no_class, set_logging_command, + "Set logging options", &setlist); + add_cmd ("logging", no_class, show_logging_command, + "Show logging options", &showlist); } void 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 22 Jun 2003 20:47:09 -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 22 Jun 2003 20:47:09 -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: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.166 diff -u -p -r1.166 gdb.texinfo --- doc/gdb.texinfo 22 Jun 2003 04:27:24 -0000 1.166 +++ doc/gdb.texinfo 22 Jun 2003 20:47:13 -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 + +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 [@var{file}] +Enable logging. If @var{file} is specified, then the current logfile will be +changed to @var{file}. +@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 22 Jun 2003 20:47:13 -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 22 Jun 2003 20:47:13 -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). */ };