Tweak pretty_print_disassembler's intro comment
[deliverable/binutils-gdb.git] / gdb / cli / cli-logging.c
CommitLineData
0fac0b41
DJ
1/* Command-line output logging for GDB, the GNU debugger.
2
61baf725 3 Copyright (C) 2003-2017 Free Software Foundation, Inc.
0fac0b41
DJ
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
0fac0b41
DJ
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
0fac0b41
DJ
19
20#include "defs.h"
21#include "gdbcmd.h"
22#include "ui-out.h"
37ce89eb 23#include "interps.h"
0fac0b41 24
0fac0b41
DJ
25/* These hold the pushed copies of the gdb output files.
26 If NULL then nothing has yet been pushed. */
27struct saved_output_files
28{
29 struct ui_file *out;
30 struct ui_file *err;
31 struct ui_file *log;
32 struct ui_file *targ;
8d4d924b 33 struct ui_file *targerr;
0fac0b41
DJ
34};
35static struct saved_output_files saved_output;
36static char *saved_filename;
37
38static char *logging_filename;
920d2a44
AC
39static void
40show_logging_filename (struct ui_file *file, int from_tty,
41 struct cmd_list_element *c, const char *value)
42{
43 fprintf_filtered (file, _("The current logfile is \"%s\".\n"),
44 value);
45}
46
44be957e 47static int logging_overwrite;
58b61394
JK
48
49static void
50set_logging_overwrite (char *args, int from_tty, struct cmd_list_element *c)
51{
52 if (saved_filename)
53 warning (_("Currently logging to %s. Turn the logging off and on to "
54 "make the new setting effective."), saved_filename);
55}
56
920d2a44
AC
57static void
58show_logging_overwrite (struct ui_file *file, int from_tty,
59 struct cmd_list_element *c, const char *value)
60{
9a2b4c1b
MS
61 fprintf_filtered (file,
62 _("Whether logging overwrites or "
63 "appends to the log file is %s.\n"),
920d2a44
AC
64 value);
65}
66
58b61394 67/* Value as configured by the user. */
44be957e 68static int logging_redirect;
58b61394 69
ebcd3b23
MS
70/* The on-disk file in use if logging is currently active together
71 with redirection turned off (and therefore using tee_file_new).
72 For active logging with redirection the on-disk file is directly in
73 GDB_STDOUT and this variable is NULL. */
58b61394
JK
74static struct ui_file *logging_no_redirect_file;
75
76static void
77set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c)
78{
d7e74731 79 ui_file_up destroy_old_stdout;
58b61394 80 struct ui_file *output, *new_logging_no_redirect_file;
79a45e25 81 struct ui_out *uiout = current_uiout;
58b61394
JK
82
83 if (saved_filename == NULL
84 || (logging_redirect != 0 && logging_no_redirect_file == NULL)
85 || (logging_redirect == 0 && logging_no_redirect_file != NULL))
86 return;
87
88 if (logging_redirect != 0)
89 {
90 gdb_assert (logging_no_redirect_file != NULL);
91
ebcd3b23
MS
92 /* ui_out_redirect still has not been called for next
93 gdb_stdout. */
d7e74731 94 destroy_old_stdout.reset (gdb_stdout);
58b61394
JK
95
96 output = logging_no_redirect_file;
97 new_logging_no_redirect_file = NULL;
98
99 if (from_tty)
100 fprintf_unfiltered (saved_output.out, "Redirecting output to %s.\n",
101 logging_filename);
102 }
103 else
104 {
105 gdb_assert (logging_no_redirect_file == NULL);
d7e74731 106 output = new tee_file (saved_output.out, 0, gdb_stdout, 0);
58b61394
JK
107 new_logging_no_redirect_file = gdb_stdout;
108
109 if (from_tty)
110 fprintf_unfiltered (saved_output.out, "Copying output to %s.\n",
111 logging_filename);
112 }
113
37ce89eb
SS
114 /* Give the current interpreter a chance to do anything special that
115 it might need for logging, such as updating other channels. */
116 if (current_interp_set_logging (1, output, NULL) == 0)
117 {
118 gdb_stdout = output;
119 gdb_stdlog = output;
120 gdb_stderr = output;
121 gdb_stdtarg = output;
122 gdb_stdtargerr = output;
123 }
124
58b61394
JK
125 logging_no_redirect_file = new_logging_no_redirect_file;
126
ebcd3b23
MS
127 /* There is a former output pushed on the ui_out_redirect stack. We
128 want to replace it by OUTPUT so we must pop the former value
7becfd03
SM
129 first. Ideally, we should either do both the pop and push or do
130 neither of them. */
14dba4b4 131
7becfd03
SM
132 uiout->redirect (NULL);
133 uiout->redirect (output);
58b61394
JK
134}
135
920d2a44
AC
136static void
137show_logging_redirect (struct ui_file *file, int from_tty,
138 struct cmd_list_element *c, const char *value)
139{
140 fprintf_filtered (file, _("The logging output mode is %s.\n"), value);
141}
0fac0b41
DJ
142
143/* If we've pushed output files, close them and pop them. */
144static void
83a8ccca 145pop_output_files (void)
0fac0b41 146{
58b61394
JK
147 if (logging_no_redirect_file)
148 {
d7e74731 149 delete logging_no_redirect_file;
58b61394
JK
150 logging_no_redirect_file = NULL;
151 }
37ce89eb
SS
152
153 if (current_interp_set_logging (0, NULL, NULL) == 0)
154 {
155 /* Only delete one of the files -- they are all set to the same
156 value. */
d7e74731 157 delete gdb_stdout;
37ce89eb
SS
158
159 gdb_stdout = saved_output.out;
160 gdb_stderr = saved_output.err;
161 gdb_stdlog = saved_output.log;
162 gdb_stdtarg = saved_output.targ;
4a5be5ee 163 gdb_stdtargerr = saved_output.targerr;
37ce89eb
SS
164 }
165
0fac0b41
DJ
166 saved_output.out = NULL;
167 saved_output.err = NULL;
168 saved_output.log = NULL;
169 saved_output.targ = NULL;
8d4d924b 170 saved_output.targerr = NULL;
0fac0b41 171
4d6cceb4 172 /* Stay consistent with handle_redirections. */
112e8700
SM
173 if (!current_uiout->is_mi_like_p ())
174 current_uiout->redirect (NULL);
0fac0b41
DJ
175}
176
177/* This is a helper for the `set logging' command. */
178static void
179handle_redirections (int from_tty)
180{
d7e74731
PA
181 ui_file_up output;
182 ui_file_up no_redirect_file;
0fac0b41
DJ
183
184 if (saved_filename != NULL)
185 {
186 fprintf_unfiltered (gdb_stdout, "Already logging to %s.\n",
187 saved_filename);
188 return;
189 }
190
d7e74731
PA
191 stdio_file_up log (new stdio_file ());
192 if (!log->open (logging_filename, logging_overwrite ? "w" : "a"))
e2e0b3e5 193 perror_with_name (_("set logging"));
0fac0b41
DJ
194
195 /* Redirects everything to gdb_stdout while this is running. */
196 if (!logging_redirect)
197 {
d7e74731
PA
198 no_redirect_file = std::move (log);
199 output.reset (new tee_file (gdb_stdout, 0, no_redirect_file.get (), 0));
58b61394 200
0fac0b41
DJ
201 if (from_tty)
202 fprintf_unfiltered (gdb_stdout, "Copying output to %s.\n",
203 logging_filename);
58b61394
JK
204 }
205 else
206 {
207 gdb_assert (logging_no_redirect_file == NULL);
d7e74731 208 output = std::move (log);
58b61394
JK
209
210 if (from_tty)
211 fprintf_unfiltered (gdb_stdout, "Redirecting output to %s.\n",
212 logging_filename);
0fac0b41 213 }
0fac0b41
DJ
214
215 saved_filename = xstrdup (logging_filename);
216 saved_output.out = gdb_stdout;
217 saved_output.err = gdb_stderr;
218 saved_output.log = gdb_stdlog;
219 saved_output.targ = gdb_stdtarg;
8d4d924b 220 saved_output.targerr = gdb_stdtargerr;
0fac0b41 221
37ce89eb 222 /* Let the interpreter do anything it needs. */
d7e74731
PA
223 if (current_interp_set_logging (1, output.get (),
224 no_redirect_file.get ()) == 0)
37ce89eb 225 {
d7e74731
PA
226 gdb_stdout = output.get ();
227 gdb_stdlog = output.get ();
228 gdb_stderr = output.get ();
229 gdb_stdtarg = output.get ();
230 gdb_stdtargerr = output.get ();
37ce89eb 231 }
0fac0b41 232
d7e74731
PA
233 output.release ();
234 logging_no_redirect_file = no_redirect_file.release ();
235
37ce89eb 236 /* Don't do the redirect for MI, it confuses MI's ui-out scheme. */
112e8700 237 if (!current_uiout->is_mi_like_p ())
d7e74731 238 current_uiout->redirect (gdb_stdout);
0fac0b41
DJ
239}
240
241static void
242set_logging_on (char *args, int from_tty)
243{
244 char *rest = args;
cdb27c12 245
0fac0b41
DJ
246 if (rest && *rest)
247 {
248 xfree (logging_filename);
249 logging_filename = xstrdup (rest);
250 }
251 handle_redirections (from_tty);
252}
253
254static void
255set_logging_off (char *args, int from_tty)
256{
257 if (saved_filename == NULL)
258 return;
259
260 pop_output_files ();
261 if (from_tty)
262 fprintf_unfiltered (gdb_stdout, "Done logging to %s.\n", saved_filename);
263 xfree (saved_filename);
264 saved_filename = NULL;
265}
266
267static void
268set_logging_command (char *args, int from_tty)
269{
9a2b4c1b
MS
270 printf_unfiltered (_("\"set logging\" lets you log output to a file.\n"
271 "Usage: set logging on [FILENAME]\n"
272 " set logging off\n"
273 " set logging file FILENAME\n"
274 " set logging overwrite [on|off]\n"
275 " set logging redirect [on|off]\n"));
0fac0b41
DJ
276}
277
2c0b251b 278static void
0fac0b41
DJ
279show_logging_command (char *args, int from_tty)
280{
281 if (saved_filename)
a3f17187 282 printf_unfiltered (_("Currently logging to \"%s\".\n"), saved_filename);
0fac0b41
DJ
283 if (saved_filename == NULL
284 || strcmp (logging_filename, saved_filename) != 0)
a3f17187 285 printf_unfiltered (_("Future logs will be written to %s.\n"),
0fac0b41
DJ
286 logging_filename);
287
288 if (logging_overwrite)
a3f17187 289 printf_unfiltered (_("Logs will overwrite the log file.\n"));
0fac0b41 290 else
a3f17187 291 printf_unfiltered (_("Logs will be appended to the log file.\n"));
0fac0b41 292
58b61394
JK
293 if (saved_filename)
294 {
295 if (logging_redirect)
296 printf_unfiltered (_("Output is being sent only to the log file.\n"));
297 else
298 printf_unfiltered (_("Output is being logged and displayed.\n"));
299 }
0fac0b41 300 else
58b61394
JK
301 {
302 if (logging_redirect)
303 printf_unfiltered (_("Output will be sent only to the log file.\n"));
304 else
305 printf_unfiltered (_("Output will be logged and displayed.\n"));
306 }
0fac0b41
DJ
307}
308
2c0b251b
PA
309/* Provide a prototype to silence -Wmissing-prototypes. */
310extern initialize_file_ftype _initialize_cli_logging;
311
0fac0b41
DJ
312void
313_initialize_cli_logging (void)
314{
315 static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist;
316
0fac0b41 317 add_prefix_cmd ("logging", class_support, set_logging_command,
1bedd215 318 _("Set logging options"), &set_logging_cmdlist,
0fac0b41
DJ
319 "set logging ", 0, &setlist);
320 add_prefix_cmd ("logging", class_support, show_logging_command,
1bedd215 321 _("Show logging options"), &show_logging_cmdlist,
0fac0b41 322 "show logging ", 0, &showlist);
7915a72c
AC
323 add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite, _("\
324Set whether logging overwrites or appends to the log file."), _("\
325Show whether logging overwrites or appends to the log file."), _("\
326If set, logging overrides the log file."),
58b61394 327 set_logging_overwrite,
920d2a44 328 show_logging_overwrite,
2c5b56ce 329 &set_logging_cmdlist, &show_logging_cmdlist);
7915a72c
AC
330 add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, _("\
331Set the logging output mode."), _("\
332Show the logging output mode."), _("\
3b64bf98 333If redirect is off, output will go to both the screen and the log file.\n\
7915a72c 334If redirect is on, output will go only to the log file."),
58b61394 335 set_logging_redirect,
920d2a44 336 show_logging_redirect,
2c5b56ce 337 &set_logging_cmdlist, &show_logging_cmdlist);
7915a72c
AC
338 add_setshow_filename_cmd ("file", class_support, &logging_filename, _("\
339Set the current logfile."), _("\
340Show the current logfile."), _("\
341The logfile is used when directing GDB's output."),
2c5b56ce 342 NULL,
920d2a44 343 show_logging_filename,
b3f42336 344 &set_logging_cmdlist, &show_logging_cmdlist);
0fac0b41 345 add_cmd ("on", class_support, set_logging_on,
1a966eab 346 _("Enable logging."), &set_logging_cmdlist);
0fac0b41 347 add_cmd ("off", class_support, set_logging_off,
1a966eab 348 _("Disable logging."), &set_logging_cmdlist);
0fac0b41
DJ
349
350 logging_filename = xstrdup ("gdb.txt");
351}
This page took 0.935634 seconds and 4 git commands to generate.