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