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