1 /* Handle set and show GDB commands.
2
3 Copyright (C) 2000-2024 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #include "readline/tilde.h"
19 #include "value.h"
20 #include <ctype.h>
21 #include "arch-utils.h"
22 #include "observable.h"
23 #include "interps.h"
24
25 #include "ui-out.h"
26
27 #include "cli/cli-decode.h"
28 #include "cli/cli-cmds.h"
29 #include "cli/cli-setshow.h"
30 #include "cli/cli-utils.h"
31
32 /* Return true if the change of command parameter should be notified. */
33
34 static bool
notify_command_param_changed_p(bool param_changed,struct cmd_list_element * c)35 notify_command_param_changed_p (bool param_changed, struct cmd_list_element *c)
36 {
37 if (!param_changed)
38 return false;
39
40 return c->theclass != class_maintenance && c->theclass != class_obscure;
41 }
42
43
44 static enum auto_boolean
parse_auto_binary_operation(const char * arg)45 parse_auto_binary_operation (const char *arg)
46 {
47 if (arg != NULL && *arg != '\0')
48 {
49 int length = strlen (arg);
50
51 while (isspace (arg[length - 1]) && length > 0)
52 length--;
53
54 /* Note that "o" is ambiguous. */
55
56 if ((length == 2 && strncmp (arg, "on", length) == 0)
57 || strncmp (arg, "1", length) == 0
58 || strncmp (arg, "yes", length) == 0
59 || strncmp (arg, "enable", length) == 0)
60 return AUTO_BOOLEAN_TRUE;
61 else if ((length >= 2 && strncmp (arg, "off", length) == 0)
62 || strncmp (arg, "0", length) == 0
63 || strncmp (arg, "no", length) == 0
64 || strncmp (arg, "disable", length) == 0)
65 return AUTO_BOOLEAN_FALSE;
66 else if (strncmp (arg, "auto", length) == 0
67 || (length > 1 && strncmp (arg, "-1", length) == 0))
68 return AUTO_BOOLEAN_AUTO;
69 }
70 error (_("\"on\", \"off\" or \"auto\" expected."));
71 return AUTO_BOOLEAN_AUTO; /* Pacify GCC. */
72 }
73
74 /* See cli-setshow.h. */
75
76 int
parse_cli_boolean_value(const char ** arg)77 parse_cli_boolean_value (const char **arg)
78 {
79 const char *p = skip_to_space (*arg);
80 size_t length = p - *arg;
81
82 /* Note that "o" is ambiguous. */
83
84 if ((length == 2 && strncmp (*arg, "on", length) == 0)
85 || strncmp (*arg, "1", length) == 0
86 || strncmp (*arg, "yes", length) == 0
87 || strncmp (*arg, "enable", length) == 0)
88 {
89 *arg = skip_spaces (*arg + length);
90 return 1;
91 }
92 else if ((length >= 2 && strncmp (*arg, "off", length) == 0)
93 || strncmp (*arg, "0", length) == 0
94 || strncmp (*arg, "no", length) == 0
95 || strncmp (*arg, "disable", length) == 0)
96 {
97 *arg = skip_spaces (*arg + length);
98 return 0;
99 }
100 else
101 return -1;
102 }
103
104 /* See cli-setshow.h. */
105
106 int
parse_cli_boolean_value(const char * arg)107 parse_cli_boolean_value (const char *arg)
108 {
109 if (!arg || !*arg)
110 return 1;
111
112 int b = parse_cli_boolean_value (&arg);
113 if (b >= 0 && *arg != '\0')
114 return -1;
115
116 return b;
117 }
118
119
120 static void
deprecated_show_value_hack(struct ui_file * ignore_file,int ignore_from_tty,struct cmd_list_element * c,const char * value)121 deprecated_show_value_hack (struct ui_file *ignore_file,
122 int ignore_from_tty,
123 struct cmd_list_element *c,
124 const char *value)
125 {
126 /* If there's no command or value, don't try to print it out. */
127 if (c == NULL || value == NULL)
128 return;
129
130 /* Print doc minus "Show " at start. Tell print_doc_line that
131 this is for a 'show value' prefix. */
132 print_doc_line (gdb_stdout, c->doc + 5, true);
133
134 gdb_assert (c->var.has_value ());
135
136 switch (c->var->type ())
137 {
138 case var_string:
139 case var_string_noescape:
140 case var_optional_filename:
141 case var_filename:
142 case var_enum:
143 gdb_printf ((" is \"%s\".\n"), value);
144 break;
145
146 default:
147 gdb_printf ((" is %s.\n"), value);
148 break;
149 }
150 }
151
152 /* Returns true and the value in VAL if ARG is an accepted literal. */
153
154 static bool
get_literal_val(LONGEST & val,const literal_def * extra_literals,const char ** arg,bool expression)155 get_literal_val (LONGEST &val, const literal_def *extra_literals,
156 const char **arg, bool expression)
157 {
158 *arg = skip_spaces (*arg);
159
160 const char *unl_start = *arg;
161
162 const char *p = skip_to_space (*arg);
163
164 size_t len = p - *arg;
165
166 if (len > 0 && extra_literals != nullptr)
167 for (const literal_def *l = extra_literals;
168 l->literal != nullptr;
169 l++)
170 if (strncmp (l->literal, *arg, len) == 0)
171 {
172 *arg += len;
173
174 /* If parsing an expression (i.e., parsing for a "set" command),
175 anything after the literal is junk. For options, anything
176 after the literal might be a command argument or another
177 option. */
178 if (expression)
179 {
180 const char *after = skip_spaces (*arg);
181 if (*after != '\0')
182 error (_("Junk after \"%.*s\": %s"),
183 (int) len, unl_start, after);
184 }
185
186 val = l->use;
187 return true;
188 }
189
190 return false;
191 }
192
193 /* See cli-setshow.h. */
194
195 LONGEST
parse_cli_var_integer(var_types var_type,const literal_def * extra_literals,const char ** arg,bool expression)196 parse_cli_var_integer (var_types var_type, const literal_def *extra_literals,
197 const char **arg, bool expression)
198 {
199 LONGEST val;
200
201 if (*arg == nullptr || **arg == '\0')
202 {
203 if (extra_literals == nullptr)
204 error_no_arg (_("integer to set it to"));
205 else
206 {
207 std::string buffer = "";
208 size_t count = 0;
209
210 for (const literal_def *l = extra_literals;
211 l->literal != nullptr;
212 l++, count++)
213 {
214 if (count != 0)
215 buffer += ", ";
216 buffer = buffer + '"' + l->literal + '"';
217 }
218 if (count > 1)
219 error_no_arg
220 (string_printf (_("integer to set it to, or one of: %s"),
221 buffer.c_str ()).c_str ());
222 else
223 error_no_arg
224 (string_printf (_("integer to set it to, or %s"),
225 buffer.c_str ()).c_str ());
226 }
227 }
228
229 if (!get_literal_val (val, extra_literals, arg, expression))
230 {
231 if (expression)
232 val = parse_and_eval_long (*arg);
233 else
234 val = get_ulongest (arg);
235
236 enum tribool allowed = TRIBOOL_UNKNOWN;
237 if (extra_literals != nullptr)
238 {
239 for (const literal_def *l = extra_literals;
240 l->literal != nullptr;
241 l++)
242 if (l->val.has_value () && val == *l->val)
243 {
244 allowed = TRIBOOL_TRUE;
245 val = l->use;
246 break;
247 }
248 else if (val == l->use)
249 allowed = TRIBOOL_FALSE;
250 }
251
252 if (allowed == TRIBOOL_UNKNOWN)
253 {
254 if (val > UINT_MAX || val < INT_MIN
255 || (var_type == var_uinteger && val < 0)
256 || (var_type == var_integer && val > INT_MAX)
257 || (var_type == var_pinteger && val < 0)
258 || (var_type == var_pinteger && val > INT_MAX))
259 allowed = TRIBOOL_FALSE;
260 }
261 if (allowed == TRIBOOL_FALSE)
262 error (_("integer %s out of range"), plongest (val));
263 }
264
265 return val;
266 }
267
268 /* See cli-setshow.h. */
269
270 const char *
parse_cli_var_enum(const char ** args,const char * const * enums)271 parse_cli_var_enum (const char **args, const char *const *enums)
272 {
273 /* If no argument was supplied, print an informative error
274 message. */
275 if (args == NULL || *args == NULL || **args == '\0')
276 {
277 std::string msg;
278
279 for (size_t i = 0; enums[i]; i++)
280 {
281 if (i != 0)
282 msg += ", ";
283 msg += enums[i];
284 }
285 error (_("Requires an argument. Valid arguments are %s."),
286 msg.c_str ());
287 }
288
289 const char *p = skip_to_space (*args);
290 size_t len = p - *args;
291
292 int nmatches = 0;
293 const char *match = NULL;
294 for (size_t i = 0; enums[i]; i++)
295 if (strncmp (*args, enums[i], len) == 0)
296 {
297 if (enums[i][len] == '\0')
298 {
299 match = enums[i];
300 nmatches = 1;
301 break; /* Exact match. */
302 }
303 else
304 {
305 match = enums[i];
306 nmatches++;
307 }
308 }
309
310 if (nmatches == 0)
311 error (_("Undefined item: \"%.*s\"."), (int) len, *args);
312
313 if (nmatches > 1)
314 error (_("Ambiguous item \"%.*s\"."), (int) len, *args);
315
316 *args += len;
317 return match;
318 }
319
320 /* Do a "set" command. ARG is NULL if no argument, or the
321 text of the argument, and FROM_TTY is nonzero if this command is
322 being entered directly by the user (i.e. these are just like any
323 other command). C is the command list element for the command. */
324
325 void
do_set_command(const char * arg,int from_tty,struct cmd_list_element * c)326 do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
327 {
328 /* A flag to indicate the option is changed or not. */
329 bool option_changed = false;
330
331 gdb_assert (c->type == set_cmd);
332
333 if (arg == NULL)
334 arg = "";
335
336 gdb_assert (c->var.has_value ());
337
338 switch (c->var->type ())
339 {
340 case var_string:
341 {
342 std::string newobj;
343 const char *p;
344 int ch;
345
346 newobj.reserve (strlen (arg));
347 p = arg;
348 while ((ch = *p++) != '\000')
349 {
350 if (ch == '\\')
351 {
352 /* \ at end of argument is used after spaces
353 so they won't be lost. */
354 /* This is obsolete now that we no longer strip
355 trailing whitespace and actually, the backslash
356 didn't get here in my test, readline or
357 something did something funky with a backslash
358 right before a newline. */
359 if (*p == 0)
360 break;
361 ch = parse_escape (get_current_arch (), &p);
362 if (ch == 0)
363 break; /* C loses */
364 else if (ch > 0)
365 newobj.push_back (ch);
366 }
367 else
368 newobj.push_back (ch);
369 }
370 newobj.shrink_to_fit ();
371
372 option_changed = c->var->set<std::string> (std::move (newobj));
373 }
374 break;
375 case var_string_noescape:
376 option_changed = c->var->set<std::string> (std::string (arg));
377 break;
378 case var_filename:
379 if (*arg == '\0')
380 error_no_arg (_("filename to set it to."));
381 [[fallthrough]];
382 case var_optional_filename:
383 {
384 char *val = NULL;
385
386 if (*arg != '\0')
387 {
388 /* Clear trailing whitespace of filename. */
389 const char *ptr = arg + strlen (arg) - 1;
390
391 while (ptr >= arg && (*ptr == ' ' || *ptr == '\t'))
392 ptr--;
393 gdb::unique_xmalloc_ptr<char> copy
394 = make_unique_xstrndup (arg, ptr + 1 - arg);
395
396 val = tilde_expand (copy.get ());
397 }
398 else
399 val = xstrdup ("");
400
401 option_changed
402 = c->var->set<std::string> (std::string (val));
403 xfree (val);
404 }
405 break;
406 case var_boolean:
407 {
408 int val = parse_cli_boolean_value (arg);
409
410 if (val < 0)
411 error (_("\"on\" or \"off\" expected."));
412
413 option_changed = c->var->set<bool> (val);
414 }
415 break;
416 case var_auto_boolean:
417 option_changed = c->var->set<enum auto_boolean> (parse_auto_binary_operation (arg));
418 break;
419 case var_uinteger:
420 option_changed
421 = c->var->set<unsigned int> (parse_cli_var_integer (c->var->type (),
422 c->var->
423 extra_literals (),
424 &arg, true));
425 break;
426 case var_integer:
427 case var_pinteger:
428 option_changed
429 = c->var->set<int> (parse_cli_var_integer (c->var->type (),
430 c->var->extra_literals (),
431 &arg, true));
432 break;
433 case var_enum:
434 {
435 const char *end_arg = arg;
436 const char *match = parse_cli_var_enum (&end_arg, c->enums);
437
438 int len = end_arg - arg;
439 const char *after = skip_spaces (end_arg);
440 if (*after != '\0')
441 error (_("Junk after item \"%.*s\": %s"), len, arg, after);
442
443 option_changed = c->var->set<const char *> (match);
444 }
445 break;
446 default:
447 error (_("gdb internal error: bad var_type in do_setshow_command"));
448 }
449
450 c->func (NULL, from_tty, c);
451
452 if (notify_command_param_changed_p (option_changed, c))
453 {
454 char *name, *cp;
455 struct cmd_list_element **cmds;
456 struct cmd_list_element *p;
457 int i;
458 int length = 0;
459
460 /* Compute the whole multi-word command options. If user types command
461 'set foo bar baz on', c->name is 'baz', and GDB can't pass "bar" to
462 command option change notification, because it is confusing. We can
463 trace back through field 'prefix' to compute the whole options,
464 and pass "foo bar baz" to notification. */
465
466 for (i = 0, p = c; p != NULL; i++)
467 {
468 length += strlen (p->name);
469 length++;
470
471 p = p->prefix;
472 }
473 cp = name = (char *) xmalloc (length);
474 cmds = XNEWVEC (struct cmd_list_element *, i);
475
476 /* Track back through filed 'prefix' and cache them in CMDS. */
477 for (i = 0, p = c; p != NULL; i++)
478 {
479 cmds[i] = p;
480 p = p->prefix;
481 }
482
483 /* Don't trigger any observer notification if subcommands is not
484 setlist. */
485 i--;
486 if (cmds[i]->subcommands != &setlist)
487 {
488 xfree (cmds);
489 xfree (name);
490
491 return;
492 }
493 /* Traverse them in the reversed order, and copy their names into
494 NAME. */
495 for (i--; i >= 0; i--)
496 {
497 memcpy (cp, cmds[i]->name, strlen (cmds[i]->name));
498 cp += strlen (cmds[i]->name);
499
500 if (i != 0)
501 {
502 cp[0] = ' ';
503 cp++;
504 }
505 }
506 cp[0] = 0;
507
508 xfree (cmds);
509
510 switch (c->var->type ())
511 {
512 case var_string:
513 case var_string_noescape:
514 case var_filename:
515 case var_optional_filename:
516 interps_notify_param_changed
517 (name, c->var->get<std::string> ().c_str ());
518 break;
519 case var_enum:
520 interps_notify_param_changed
521 (name, c->var->get<const char *> ());
522 break;
523 case var_boolean:
524 {
525 const char *opt = c->var->get<bool> () ? "on" : "off";
526
527 interps_notify_param_changed (name, opt);
528 }
529 break;
530 case var_auto_boolean:
531 {
532 const char *s
533 = auto_boolean_enums[c->var->get<enum auto_boolean> ()];
534
535 interps_notify_param_changed (name, s);
536 }
537 break;
538 case var_uinteger:
539 {
540 char s[64];
541
542 xsnprintf (s, sizeof s, "%u", c->var->get<unsigned int> ());
543 interps_notify_param_changed (name, s);
544 }
545 break;
546 case var_integer:
547 case var_pinteger:
548 {
549 char s[64];
550
551 xsnprintf (s, sizeof s, "%d", c->var->get<int> ());
552 interps_notify_param_changed (name, s);
553 }
554 break;
555 }
556 xfree (name);
557 }
558 }
559
560 /* See cli/cli-setshow.h. */
561
562 std::string
get_setshow_command_value_string(const setting & var)563 get_setshow_command_value_string (const setting &var)
564 {
565 string_file stb;
566
567 switch (var.type ())
568 {
569 case var_string:
570 {
571 std::string value = var.get<std::string> ();
572 if (!value.empty ())
573 stb.putstr (value.c_str (), '"');
574 }
575 break;
576 case var_string_noescape:
577 case var_optional_filename:
578 case var_filename:
579 stb.puts (var.get<std::string> ().c_str ());
580 break;
581 case var_enum:
582 {
583 const char *value = var.get<const char *> ();
584 if (value != nullptr)
585 stb.puts (value);
586 }
587 break;
588 case var_boolean:
589 stb.puts (var.get<bool> () ? "on" : "off");
590 break;
591 case var_auto_boolean:
592 switch (var.get<enum auto_boolean> ())
593 {
594 case AUTO_BOOLEAN_TRUE:
595 stb.puts ("on");
596 break;
597 case AUTO_BOOLEAN_FALSE:
598 stb.puts ("off");
599 break;
600 case AUTO_BOOLEAN_AUTO:
601 stb.puts ("auto");
602 break;
603 default:
604 gdb_assert_not_reached ("invalid var_auto_boolean");
605 break;
606 }
607 break;
608 case var_uinteger:
609 case var_integer:
610 case var_pinteger:
611 {
612 bool printed = false;
613 const LONGEST value
614 = (var.type () == var_uinteger
615 ? static_cast<LONGEST> (var.get<unsigned int> ())
616 : static_cast<LONGEST> (var.get<int> ()));
617
618 if (var.extra_literals () != nullptr)
619 for (const literal_def *l = var.extra_literals ();
620 l->literal != nullptr;
621 l++)
622 if (value == l->use)
623 {
624 stb.puts (l->literal);
625 printed = true;
626 break;
627 }
628 if (!printed)
629 {
630 if (var.type () == var_uinteger)
631 stb.printf ("%u", static_cast<unsigned int> (value));
632 else
633 stb.printf ("%d", static_cast<int> (value));
634 }
635 }
636 break;
637 default:
638 gdb_assert_not_reached ("bad var_type");
639 }
640
641 return stb.release ();
642 }
643
644
645 /* Do a "show" command. ARG is NULL if no argument, or the
646 text of the argument, and FROM_TTY is nonzero if this command is
647 being entered directly by the user (i.e. these are just like any
648 other command). C is the command list element for the command. */
649
650 void
do_show_command(const char * arg,int from_tty,struct cmd_list_element * c)651 do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
652 {
653 struct ui_out *uiout = current_uiout;
654
655 gdb_assert (c->type == show_cmd);
656 gdb_assert (c->var.has_value ());
657
658 std::string val = get_setshow_command_value_string (*c->var);
659
660 /* FIXME: cagney/2005-02-10: There should be MI and CLI specific
661 versions of code to print the value out. */
662
663 if (uiout->is_mi_like_p ())
664 uiout->field_string ("value", val);
665 else
666 {
667 if (c->show_value_func != NULL)
668 c->show_value_func (gdb_stdout, from_tty, c, val.c_str ());
669 else
670 deprecated_show_value_hack (gdb_stdout, from_tty, c, val.c_str ());
671 }
672
673 c->func (NULL, from_tty, c);
674 }
675
676 /* Show all the settings in a list of show commands. */
677
678 void
cmd_show_list(struct cmd_list_element * list,int from_tty)679 cmd_show_list (struct cmd_list_element *list, int from_tty)
680 {
681 struct ui_out *uiout = current_uiout;
682
683 ui_out_emit_tuple tuple_emitter (uiout, "showlist");
684 for (; list != NULL; list = list->next)
685 {
686 /* We skip show command aliases to avoid showing duplicated values. */
687
688 /* If we find a prefix, run its list, prefixing our output by its
689 prefix (with "show " skipped). */
690 if (list->is_prefix () && !list->is_alias ())
691 {
692 ui_out_emit_tuple optionlist_emitter (uiout, "optionlist");
693 std::string prefixname = list->prefixname ();
694 const char *new_prefix = strstr (prefixname.c_str (), "show ") + 5;
695
696 if (uiout->is_mi_like_p ())
697 uiout->field_string ("prefix", new_prefix);
698 cmd_show_list (*list->subcommands, from_tty);
699 }
700 else if (list->theclass != no_set_class && !list->is_alias ())
701 {
702 ui_out_emit_tuple option_emitter (uiout, "option");
703
704 if (list->prefix != nullptr)
705 {
706 /* If we find a prefix, output it (with "show " skipped). */
707 std::string prefixname = list->prefix->prefixname ();
708 prefixname = (!list->prefix->is_prefix () ? ""
709 : strstr (prefixname.c_str (), "show ") + 5);
710 uiout->text (prefixname);
711 }
712 uiout->field_string ("name", list->name);
713 uiout->text (": ");
714 if (list->type == show_cmd)
715 do_show_command (NULL, from_tty, list);
716 else
717 cmd_func (list, NULL, from_tty);
718 }
719 }
720 }
721
722
723