1/* Handle set and show GDB commands.
2
3   Copyright (c) 2000, 2001, 2002, 2003, 2007 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 "gdb_string.h"
23
24#include "ui-out.h"
25
26#include "cli/cli-decode.h"
27#include "cli/cli-cmds.h"
28#include "cli/cli-setshow.h"
29
30/* Prototypes for local functions */
31
32static int parse_binary_operation (char *);
33
34
35static enum auto_boolean
36parse_auto_binary_operation (const char *arg)
37{
38  if (arg != NULL && *arg != '\0')
39    {
40      int length = strlen (arg);
41      while (isspace (arg[length - 1]) && length > 0)
42	length--;
43      if (strncmp (arg, "on", length) == 0
44	  || strncmp (arg, "1", length) == 0
45	  || strncmp (arg, "yes", length) == 0
46	  || strncmp (arg, "enable", length) == 0)
47	return AUTO_BOOLEAN_TRUE;
48      else if (strncmp (arg, "off", length) == 0
49	       || strncmp (arg, "0", length) == 0
50	       || strncmp (arg, "no", length) == 0
51	       || strncmp (arg, "disable", length) == 0)
52	return AUTO_BOOLEAN_FALSE;
53      else if (strncmp (arg, "auto", length) == 0
54	       || (strncmp (arg, "-1", length) == 0 && length > 1))
55	return AUTO_BOOLEAN_AUTO;
56    }
57  error (_("\"on\", \"off\" or \"auto\" expected."));
58  return AUTO_BOOLEAN_AUTO; /* pacify GCC */
59}
60
61static int
62parse_binary_operation (char *arg)
63{
64  int length;
65
66  if (!arg || !*arg)
67    return 1;
68
69  length = strlen (arg);
70
71  while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
72    length--;
73
74  if (strncmp (arg, "on", length) == 0
75      || strncmp (arg, "1", length) == 0
76      || strncmp (arg, "yes", length) == 0
77      || strncmp (arg, "enable", length) == 0)
78    return 1;
79  else if (strncmp (arg, "off", length) == 0
80	   || strncmp (arg, "0", length) == 0
81	   || strncmp (arg, "no", length) == 0
82	   || strncmp (arg, "disable", length) == 0)
83    return 0;
84  else
85    {
86      error (_("\"on\" or \"off\" expected."));
87      return 0;
88    }
89}
90
91void
92deprecated_show_value_hack (struct ui_file *ignore_file,
93			    int ignore_from_tty,
94			    struct cmd_list_element *c,
95			    const char *value)
96{
97  /* If there's no command or value, don't try to print it out.  */
98  if (c == NULL || value == NULL)
99    return;
100  /* Print doc minus "show" at start.  */
101  print_doc_line (gdb_stdout, c->doc + 5);
102  switch (c->var_type)
103    {
104    case var_string:
105    case var_string_noescape:
106    case var_optional_filename:
107    case var_filename:
108    case var_enum:
109      printf_filtered ((" is \"%s\".\n"), value);
110      break;
111    default:
112      printf_filtered ((" is %s.\n"), value);
113      break;
114    }
115}
116
117/* Do a "set" or "show" command.  ARG is NULL if no argument, or the text
118   of the argument, and FROM_TTY is nonzero if this command is being entered
119   directly by the user (i.e. these are just like any other
120   command).  C is the command list element for the command.  */
121
122void
123do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
124{
125  if (c->type == set_cmd)
126    {
127      switch (c->var_type)
128	{
129	case var_string:
130	  {
131	    char *new;
132	    char *p;
133	    char *q;
134	    int ch;
135
136	    if (arg == NULL)
137	      arg = "";
138	    new = (char *) xmalloc (strlen (arg) + 2);
139	    p = arg;
140	    q = new;
141	    while ((ch = *p++) != '\000')
142	      {
143		if (ch == '\\')
144		  {
145		    /* \ at end of argument is used after spaces
146		       so they won't be lost.  */
147		    /* This is obsolete now that we no longer strip
148		       trailing whitespace and actually, the backslash
149		       didn't get here in my test, readline or
150		       something did something funky with a backslash
151		       right before a newline.  */
152		    if (*p == 0)
153		      break;
154		    ch = parse_escape (&p);
155		    if (ch == 0)
156		      break;	/* C loses */
157		    else if (ch > 0)
158		      *q++ = ch;
159		  }
160		else
161		  *q++ = ch;
162	      }
163#if 0
164	    if (*(p - 1) != '\\')
165	      *q++ = ' ';
166#endif
167	    *q++ = '\0';
168	    new = (char *) xrealloc (new, q - new);
169	    if (*(char **) c->var != NULL)
170	      xfree (*(char **) c->var);
171	    *(char **) c->var = new;
172	  }
173	  break;
174	case var_string_noescape:
175	  if (arg == NULL)
176	    arg = "";
177	  if (*(char **) c->var != NULL)
178	    xfree (*(char **) c->var);
179	  *(char **) c->var = savestring (arg, strlen (arg));
180	  break;
181	case var_optional_filename:
182	  if (arg == NULL)
183	    arg = "";
184	  if (*(char **) c->var != NULL)
185	    xfree (*(char **) c->var);
186	  *(char **) c->var = savestring (arg, strlen (arg));
187	  break;
188	case var_filename:
189	  if (arg == NULL)
190	    error_no_arg (_("filename to set it to."));
191	  if (*(char **) c->var != NULL)
192	    xfree (*(char **) c->var);
193	  {
194	    /* Clear trailing whitespace of filename.  */
195	    char *ptr = arg + strlen (arg) - 1;
196	    while (ptr >= arg && (*ptr == ' ' || *ptr == '\t'))
197	      ptr--;
198	    *(ptr + 1) = '\0';
199	  }
200	  *(char **) c->var = tilde_expand (arg);
201	  break;
202	case var_boolean:
203	  *(int *) c->var = parse_binary_operation (arg);
204	  break;
205	case var_auto_boolean:
206	  *(enum auto_boolean *) c->var = parse_auto_binary_operation (arg);
207	  break;
208	case var_uinteger:
209	  if (arg == NULL)
210	    error_no_arg (_("integer to set it to."));
211	  *(unsigned int *) c->var = parse_and_eval_long (arg);
212	  if (*(unsigned int *) c->var == 0)
213	    *(unsigned int *) c->var = UINT_MAX;
214	  break;
215	case var_integer:
216	  {
217	    unsigned int val;
218	    if (arg == NULL)
219	      error_no_arg (_("integer to set it to."));
220	    val = parse_and_eval_long (arg);
221	    if (val == 0)
222	      *(int *) c->var = INT_MAX;
223	    else if (val >= INT_MAX)
224	      error (_("integer %u out of range"), val);
225	    else
226	      *(int *) c->var = val;
227	    break;
228	  }
229	case var_zinteger:
230	  if (arg == NULL)
231	    error_no_arg (_("integer to set it to."));
232	  *(int *) c->var = parse_and_eval_long (arg);
233	  break;
234	case var_enum:
235	  {
236	    int i;
237	    int len;
238	    int nmatches;
239	    const char *match = NULL;
240	    char *p;
241
242	    /* if no argument was supplied, print an informative error message */
243	    if (arg == NULL)
244	      {
245		char msg[1024];
246		strcpy (msg, "Requires an argument. Valid arguments are ");
247		for (i = 0; c->enums[i]; i++)
248		  {
249		    if (i != 0)
250		      strcat (msg, ", ");
251		    strcat (msg, c->enums[i]);
252		  }
253		strcat (msg, ".");
254		error (("%s"), msg);
255	      }
256
257	    p = strchr (arg, ' ');
258
259	    if (p)
260	      len = p - arg;
261	    else
262	      len = strlen (arg);
263
264	    nmatches = 0;
265	    for (i = 0; c->enums[i]; i++)
266	      if (strncmp (arg, c->enums[i], len) == 0)
267		{
268		  if (c->enums[i][len] == '\0')
269		    {
270		      match = c->enums[i];
271		      nmatches = 1;
272		      break; /* exact match. */
273		    }
274		  else
275		    {
276		      match = c->enums[i];
277		      nmatches++;
278		    }
279		}
280
281	    if (nmatches <= 0)
282	      error (_("Undefined item: \"%s\"."), arg);
283
284	    if (nmatches > 1)
285	      error (_("Ambiguous item \"%s\"."), arg);
286
287	    *(const char **) c->var = match;
288	  }
289	  break;
290	default:
291	  error (_("gdb internal error: bad var_type in do_setshow_command"));
292	}
293    }
294  else if (c->type == show_cmd)
295    {
296      struct cleanup *old_chain;
297      struct ui_stream *stb;
298
299      stb = ui_out_stream_new (uiout);
300      old_chain = make_cleanup_ui_out_stream_delete (stb);
301
302      /* Possibly call the pre hook.  */
303      if (c->pre_show_hook)
304	(c->pre_show_hook) (c);
305
306      switch (c->var_type)
307	{
308	case var_string:
309	  if (*(char **) c->var)
310	    fputstr_filtered (*(char **) c->var, '"', stb->stream);
311	  break;
312	case var_string_noescape:
313	case var_optional_filename:
314	case var_filename:
315	case var_enum:
316	  if (*(char **) c->var)
317	    fputs_filtered (*(char **) c->var, stb->stream);
318	  break;
319	case var_boolean:
320	  fputs_filtered (*(int *) c->var ? "on" : "off", stb->stream);
321	  break;
322	case var_auto_boolean:
323	  switch (*(enum auto_boolean*) c->var)
324	    {
325	    case AUTO_BOOLEAN_TRUE:
326	      fputs_filtered ("on", stb->stream);
327	      break;
328	    case AUTO_BOOLEAN_FALSE:
329	      fputs_filtered ("off", stb->stream);
330	      break;
331	    case AUTO_BOOLEAN_AUTO:
332	      fputs_filtered ("auto", stb->stream);
333	      break;
334	    default:
335	      internal_error (__FILE__, __LINE__,
336			      _("do_setshow_command: invalid var_auto_boolean"));
337	      break;
338	    }
339	  break;
340	case var_uinteger:
341	  if (*(unsigned int *) c->var == UINT_MAX)
342	    {
343	      fputs_filtered ("unlimited", stb->stream);
344	      break;
345	    }
346	  /* else fall through */
347	case var_zinteger:
348	  fprintf_filtered (stb->stream, "%u", *(unsigned int *) c->var);
349	  break;
350	case var_integer:
351	  if (*(int *) c->var == INT_MAX)
352	    {
353	      fputs_filtered ("unlimited", stb->stream);
354	    }
355	  else
356	    fprintf_filtered (stb->stream, "%d", *(int *) c->var);
357	  break;
358
359	default:
360	  error (_("gdb internal error: bad var_type in do_setshow_command"));
361	}
362
363
364      /* FIXME: cagney/2005-02-10: Need to split this in half: code to
365	 convert the value into a string (esentially the above); and
366	 code to print the value out.  For the latter there should be
367	 MI and CLI specific versions.  */
368
369      if (ui_out_is_mi_like_p (uiout))
370	ui_out_field_stream (uiout, "value", stb);
371      else
372	{
373	  long length;
374	  char *value = ui_file_xstrdup (stb->stream, &length);
375	  make_cleanup (xfree, value);
376	  if (c->show_value_func != NULL)
377	    c->show_value_func (gdb_stdout, from_tty, c, value);
378	  else
379	    deprecated_show_value_hack (gdb_stdout, from_tty, c, value);
380	}
381      do_cleanups (old_chain);
382    }
383  else
384    error (_("gdb internal error: bad cmd_type in do_setshow_command"));
385  c->func (c, NULL, from_tty);
386  if (c->type == set_cmd && deprecated_set_hook)
387    deprecated_set_hook (c);
388}
389
390/* Show all the settings in a list of show commands.  */
391
392void
393cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix)
394{
395  struct cleanup *showlist_chain;
396
397  showlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "showlist");
398  for (; list != NULL; list = list->next)
399    {
400      /* If we find a prefix, run its list, prefixing our output by its
401         prefix (with "show " skipped).  */
402      if (list->prefixlist && !list->abbrev_flag)
403	{
404	  struct cleanup *optionlist_chain
405	    = make_cleanup_ui_out_tuple_begin_end (uiout, "optionlist");
406	  char *new_prefix = strstr (list->prefixname, "show ") + 5;
407	  if (ui_out_is_mi_like_p (uiout))
408	    ui_out_field_string (uiout, "prefix", new_prefix);
409	  cmd_show_list (*list->prefixlist, from_tty, new_prefix);
410	  /* Close the tuple.  */
411	  do_cleanups (optionlist_chain);
412	}
413      else
414	{
415	  struct cleanup *option_chain
416	    = make_cleanup_ui_out_tuple_begin_end (uiout, "option");
417	  ui_out_text (uiout, prefix);
418	  ui_out_field_string (uiout, "name", list->name);
419	  ui_out_text (uiout, ":  ");
420	  if (list->type == show_cmd)
421	    do_setshow_command ((char *) NULL, from_tty, list);
422	  else
423	    cmd_func (list, NULL, from_tty);
424          /* Close the tuple.  */
425	  do_cleanups (option_chain);
426	}
427    }
428  /* Close the tuple.  */
429  do_cleanups (showlist_chain);
430}
431
432