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