]>
Commit | Line | Data |
---|---|---|
0fac0b41 DJ |
1 | /* Command-line output logging for GDB, the GNU debugger. |
2 | ||
d01e8234 | 3 | Copyright (C) 2003-2025 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 | 19 | |
5b9707eb | 20 | #include "cli/cli-cmds.h" |
0fac0b41 | 21 | #include "ui-out.h" |
37ce89eb | 22 | #include "interps.h" |
d770d56f | 23 | #include "cli/cli-style.h" |
6ff96754 | 24 | #include "cli/cli-decode.h" |
0fac0b41 | 25 | |
ce1a6f42 | 26 | static std::string saved_filename; |
0fac0b41 | 27 | |
e0700ba4 | 28 | static std::string logging_filename = "gdb.txt"; |
920d2a44 AC |
29 | static void |
30 | show_logging_filename (struct ui_file *file, int from_tty, | |
31 | struct cmd_list_element *c, const char *value) | |
32 | { | |
6cb06a8c TT |
33 | gdb_printf (file, _("The current logfile is \"%ps\".\n"), |
34 | styled_string (file_name_style.style (), value)); | |
920d2a44 AC |
35 | } |
36 | ||
491144b5 | 37 | static bool logging_overwrite; |
58b61394 JK |
38 | |
39 | static void | |
5be5dbf0 | 40 | maybe_warn_already_logging () |
58b61394 | 41 | { |
ce1a6f42 | 42 | if (!saved_filename.empty ()) |
58b61394 | 43 | warning (_("Currently logging to %s. Turn the logging off and on to " |
ce1a6f42 | 44 | "make the new setting effective."), saved_filename.c_str ()); |
58b61394 JK |
45 | } |
46 | ||
5be5dbf0 | 47 | static void |
eb4c3f4a TT |
48 | set_logging_overwrite (const char *args, |
49 | int from_tty, struct cmd_list_element *c) | |
5be5dbf0 PA |
50 | { |
51 | maybe_warn_already_logging (); | |
52 | } | |
53 | ||
920d2a44 AC |
54 | static void |
55 | show_logging_overwrite (struct ui_file *file, int from_tty, | |
56 | struct cmd_list_element *c, const char *value) | |
57 | { | |
45aec4e5 | 58 | if (logging_overwrite) |
6cb06a8c | 59 | gdb_printf (file, _("on: Logging overwrites the log file.\n")); |
45aec4e5 | 60 | else |
6cb06a8c | 61 | gdb_printf (file, _("off: Logging appends to the log file.\n")); |
920d2a44 AC |
62 | } |
63 | ||
58b61394 | 64 | /* Value as configured by the user. */ |
491144b5 CB |
65 | static bool logging_redirect; |
66 | static bool debug_redirect; | |
58b61394 | 67 | |
58b61394 | 68 | static void |
eb4c3f4a TT |
69 | set_logging_redirect (const char *args, |
70 | int from_tty, struct cmd_list_element *c) | |
58b61394 | 71 | { |
5be5dbf0 | 72 | maybe_warn_already_logging (); |
58b61394 JK |
73 | } |
74 | ||
920d2a44 AC |
75 | static void |
76 | show_logging_redirect (struct ui_file *file, int from_tty, | |
77 | struct cmd_list_element *c, const char *value) | |
78 | { | |
45aec4e5 | 79 | if (logging_redirect) |
6cb06a8c | 80 | gdb_printf (file, _("on: Output will go only to the log file.\n")); |
45aec4e5 | 81 | else |
6cb06a8c | 82 | gdb_printf |
45aec4e5 TV |
83 | (file, |
84 | _("off: Output will go to both the screen and the log file.\n")); | |
85 | } | |
86 | ||
87 | static void | |
88 | show_logging_debug_redirect (struct ui_file *file, int from_tty, | |
89 | struct cmd_list_element *c, const char *value) | |
90 | { | |
91 | if (debug_redirect) | |
6cb06a8c | 92 | gdb_printf (file, _("on: Debug output will go only to the log file.\n")); |
45aec4e5 | 93 | else |
6cb06a8c | 94 | gdb_printf |
45aec4e5 TV |
95 | (file, |
96 | _("off: Debug output will go to both the screen and the log file.\n")); | |
920d2a44 | 97 | } |
0fac0b41 DJ |
98 | |
99 | /* If we've pushed output files, close them and pop them. */ | |
100 | static void | |
83a8ccca | 101 | pop_output_files (void) |
0fac0b41 | 102 | { |
ca1285d1 | 103 | current_interp_set_logging (NULL, false, false); |
0fac0b41 | 104 | |
4d6cceb4 | 105 | /* Stay consistent with handle_redirections. */ |
112e8700 SM |
106 | if (!current_uiout->is_mi_like_p ()) |
107 | current_uiout->redirect (NULL); | |
0fac0b41 DJ |
108 | } |
109 | ||
110 | /* This is a helper for the `set logging' command. */ | |
111 | static void | |
112 | handle_redirections (int from_tty) | |
113 | { | |
ce1a6f42 | 114 | if (!saved_filename.empty ()) |
0fac0b41 | 115 | { |
6cb06a8c TT |
116 | gdb_printf ("Already logging to %s.\n", |
117 | saved_filename.c_str ()); | |
0fac0b41 DJ |
118 | return; |
119 | } | |
120 | ||
0735b091 | 121 | stdio_file_up log (new no_terminal_escape_file ()); |
e0700ba4 | 122 | if (!log->open (logging_filename.c_str (), logging_overwrite ? "w" : "a")) |
e2e0b3e5 | 123 | perror_with_name (_("set logging")); |
0fac0b41 DJ |
124 | |
125 | /* Redirects everything to gdb_stdout while this is running. */ | |
616268b6 | 126 | if (from_tty) |
0fac0b41 | 127 | { |
616268b6 | 128 | if (!logging_redirect) |
6cb06a8c TT |
129 | gdb_printf ("Copying output to %s.\n", |
130 | logging_filename.c_str ()); | |
616268b6 | 131 | else |
6cb06a8c TT |
132 | gdb_printf ("Redirecting output to %s.\n", |
133 | logging_filename.c_str ()); | |
ca1285d1 AH |
134 | |
135 | if (!debug_redirect) | |
6cb06a8c TT |
136 | gdb_printf ("Copying debug output to %s.\n", |
137 | logging_filename.c_str ()); | |
ca1285d1 | 138 | else |
6cb06a8c TT |
139 | gdb_printf ("Redirecting debug output to %s.\n", |
140 | logging_filename.c_str ()); | |
0fac0b41 | 141 | } |
0fac0b41 | 142 | |
ce1a6f42 | 143 | saved_filename = logging_filename; |
0fac0b41 | 144 | |
37ce89eb | 145 | /* Let the interpreter do anything it needs. */ |
ca1285d1 AH |
146 | current_interp_set_logging (std::move (log), logging_redirect, |
147 | debug_redirect); | |
616268b6 PA |
148 | |
149 | /* Redirect the current ui-out object's output to the log. Use | |
150 | gdb_stdout, not log, since the interpreter may have created a tee | |
151 | that wraps the log. Don't do the redirect for MI, it confuses | |
152 | MI's ui-out scheme. Note that we may get here with MI as current | |
153 | interpreter, but with the current ui_out as a CLI ui_out, with | |
154 | '-interpreter-exec console "set logging on"'. */ | |
112e8700 | 155 | if (!current_uiout->is_mi_like_p ()) |
d7e74731 | 156 | current_uiout->redirect (gdb_stdout); |
0fac0b41 DJ |
157 | } |
158 | ||
159 | static void | |
aa360cd5 | 160 | set_logging_on (const char *args, int from_tty) |
0fac0b41 | 161 | { |
aa360cd5 | 162 | const char *rest = args; |
cdb27c12 | 163 | |
0fac0b41 | 164 | if (rest && *rest) |
e0700ba4 SM |
165 | logging_filename = rest; |
166 | ||
0fac0b41 DJ |
167 | handle_redirections (from_tty); |
168 | } | |
169 | ||
170 | static void | |
aa360cd5 | 171 | set_logging_off (const char *args, int from_tty) |
0fac0b41 | 172 | { |
ce1a6f42 | 173 | if (saved_filename.empty ()) |
0fac0b41 DJ |
174 | return; |
175 | ||
176 | pop_output_files (); | |
177 | if (from_tty) | |
6cb06a8c TT |
178 | gdb_printf ("Done logging to %s.\n", |
179 | saved_filename.c_str ()); | |
ce1a6f42 | 180 | saved_filename.clear (); |
0fac0b41 DJ |
181 | } |
182 | ||
6ff96754 TV |
183 | static bool logging_enabled; |
184 | ||
185 | static void | |
186 | set_logging_enabled (const char *args, | |
187 | int from_tty, struct cmd_list_element *c) | |
188 | { | |
189 | if (logging_enabled) | |
190 | set_logging_on (args, from_tty); | |
191 | else | |
192 | set_logging_off (args, from_tty); | |
193 | } | |
194 | ||
195 | static void | |
196 | show_logging_enabled (struct ui_file *file, int from_tty, | |
197 | struct cmd_list_element *c, const char *value) | |
198 | { | |
199 | if (logging_enabled) | |
6cb06a8c | 200 | gdb_printf (file, _("on: Logging is enabled.\n")); |
6ff96754 | 201 | else |
6cb06a8c | 202 | gdb_printf (file, _("off: Logging is disabled.\n")); |
6ff96754 TV |
203 | } |
204 | ||
5fe70629 | 205 | INIT_GDB_FILE (cli_logging) |
0fac0b41 DJ |
206 | { |
207 | static struct cmd_list_element *set_logging_cmdlist, *show_logging_cmdlist; | |
208 | ||
6ff96754 | 209 | /* Set/show logging. */ |
f54bdb6d SM |
210 | add_setshow_prefix_cmd ("logging", class_support, |
211 | _("Set logging options."), | |
212 | _("Show logging options."), | |
213 | &set_logging_cmdlist, &show_logging_cmdlist, | |
214 | &setlist, &showlist); | |
215 | ||
6ff96754 | 216 | /* Set/show logging overwrite. */ |
7915a72c AC |
217 | add_setshow_boolean_cmd ("overwrite", class_support, &logging_overwrite, _("\ |
218 | Set whether logging overwrites or appends to the log file."), _("\ | |
219 | Show whether logging overwrites or appends to the log file."), _("\ | |
0a4a1c6a | 220 | If set, logging overwrites the log file."), |
58b61394 | 221 | set_logging_overwrite, |
920d2a44 | 222 | show_logging_overwrite, |
2c5b56ce | 223 | &set_logging_cmdlist, &show_logging_cmdlist); |
6ff96754 TV |
224 | |
225 | /* Set/show logging redirect. */ | |
7915a72c AC |
226 | add_setshow_boolean_cmd ("redirect", class_support, &logging_redirect, _("\ |
227 | Set the logging output mode."), _("\ | |
228 | Show the logging output mode."), _("\ | |
3b64bf98 | 229 | If redirect is off, output will go to both the screen and the log file.\n\ |
7915a72c | 230 | If redirect is on, output will go only to the log file."), |
58b61394 | 231 | set_logging_redirect, |
920d2a44 | 232 | show_logging_redirect, |
2c5b56ce | 233 | &set_logging_cmdlist, &show_logging_cmdlist); |
6ff96754 TV |
234 | |
235 | /* Set/show logging debugredirect. */ | |
ca1285d1 AH |
236 | add_setshow_boolean_cmd ("debugredirect", class_support, |
237 | &debug_redirect, _("\ | |
238 | Set the logging debug output mode."), _("\ | |
239 | Show the logging debug output mode."), _("\ | |
240 | If debug redirect is off, debug will go to both the screen and the log file.\n\ | |
241 | If debug redirect is on, debug will go only to the log file."), | |
242 | set_logging_redirect, | |
45aec4e5 | 243 | show_logging_debug_redirect, |
ca1285d1 | 244 | &set_logging_cmdlist, &show_logging_cmdlist); |
e0700ba4 | 245 | |
6ff96754 | 246 | /* Set/show logging file. */ |
7915a72c AC |
247 | add_setshow_filename_cmd ("file", class_support, &logging_filename, _("\ |
248 | Set the current logfile."), _("\ | |
249 | Show the current logfile."), _("\ | |
250 | The logfile is used when directing GDB's output."), | |
2c5b56ce | 251 | NULL, |
920d2a44 | 252 | show_logging_filename, |
b3f42336 | 253 | &set_logging_cmdlist, &show_logging_cmdlist); |
6ff96754 TV |
254 | |
255 | /* Set/show logging enabled. */ | |
256 | set_show_commands setshow_logging_enabled_cmds | |
257 | = add_setshow_boolean_cmd ("enabled", class_support, &logging_enabled, | |
258 | _("Enable logging."), | |
259 | _("Show whether logging is enabled."), | |
260 | _("When on, enable logging."), | |
261 | set_logging_enabled, | |
262 | show_logging_enabled, | |
263 | &set_logging_cmdlist, &show_logging_cmdlist); | |
264 | ||
265 | /* Set logging on, deprecated alias. */ | |
266 | cmd_list_element *set_logging_on_cmd | |
267 | = add_alias_cmd ("on", setshow_logging_enabled_cmds.set, class_support, | |
268 | false, &set_logging_cmdlist); | |
269 | deprecate_cmd (set_logging_on_cmd, "set logging enabled on"); | |
270 | set_logging_on_cmd->default_args = "on"; | |
271 | ||
272 | /* Set logging off, deprecated alias. */ | |
273 | cmd_list_element *set_logging_off_cmd | |
274 | = add_alias_cmd ("off", setshow_logging_enabled_cmds.set, class_support, | |
275 | false, &set_logging_cmdlist); | |
276 | deprecate_cmd (set_logging_off_cmd, "set logging enabled off"); | |
277 | set_logging_off_cmd->default_args = "off"; | |
0fac0b41 | 278 | } |