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