xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/guile/scm-param.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /* GDB parameters implemented in Guile.
2 
3    Copyright (C) 2008-2020 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "value.h"
22 #include "charset.h"
23 #include "gdbcmd.h"
24 #include "cli/cli-decode.h"
25 #include "completer.h"
26 #include "language.h"
27 #include "arch-utils.h"
28 #include "guile-internal.h"
29 
30 /* A union that can hold anything described by enum var_types.  */
31 
32 union pascm_variable
33 {
34   /* Hold an boolean value.  */
35   bool boolval;
36 
37   /* Hold an integer value.  */
38   int intval;
39 
40   /* Hold an auto_boolean.  */
41   enum auto_boolean autoboolval;
42 
43   /* Hold an unsigned integer value, for uinteger.  */
44   unsigned int uintval;
45 
46   /* Hold a string, for the various string types.  */
47   char *stringval;
48 
49   /* Hold a string, for enums.  */
50   const char *cstringval;
51 };
52 
53 /* A GDB parameter.
54 
55    Note: Parameters are added to gdb using a two step process:
56    1) Call make-parameter to create a <gdb:parameter> object.
57    2) Call register-parameter! to add the parameter to gdb.
58    It is done this way so that the constructor, make-parameter, doesn't have
59    any side-effects.  This means that the smob needs to store everything
60    that was passed to make-parameter.
61 
62    N.B. There is no free function for this smob.
63    All objects pointed to by this smob must live in GC space.  */
64 
65 typedef struct _param_smob
66 {
67   /* This always appears first.  */
68   gdb_smob base;
69 
70   /* The parameter name.  */
71   char *name;
72 
73   /* The last word of the command.
74      This is needed because add_cmd requires us to allocate space
75      for it. :-(  */
76   char *cmd_name;
77 
78   /* One of the COMMAND_* constants.  */
79   enum command_class cmd_class;
80 
81   /* The type of the parameter.  */
82   enum var_types type;
83 
84   /* The docs for the parameter.  */
85   char *set_doc;
86   char *show_doc;
87   char *doc;
88 
89   /* The corresponding gdb command objects.
90      These are NULL if the parameter has not been registered yet, or
91      is no longer registered.  */
92   struct cmd_list_element *set_command;
93   struct cmd_list_element *show_command;
94 
95   /* The value of the parameter.  */
96   union pascm_variable value;
97 
98   /* For an enum parameter, the possible values.  The vector lives in GC
99      space, it will be freed with the smob.  */
100   const char * const *enumeration;
101 
102   /* The set_func funcion or #f if not specified.
103      This function is called *after* the parameter is set.
104      It returns a string that will be displayed to the user.  */
105   SCM set_func;
106 
107   /* The show_func function or #f if not specified.
108      This function returns the string that is printed.  */
109   SCM show_func;
110 
111   /* The <gdb:parameter> object we are contained in, needed to
112      protect/unprotect the object since a reference to it comes from
113      non-gc-managed space (the command context pointer).  */
114   SCM containing_scm;
115 } param_smob;
116 
117 static const char param_smob_name[] = "gdb:parameter";
118 
119 /* The tag Guile knows the param smob by.  */
120 static scm_t_bits parameter_smob_tag;
121 
122 /* Keywords used by make-parameter!.  */
123 static SCM command_class_keyword;
124 static SCM parameter_type_keyword;
125 static SCM enum_list_keyword;
126 static SCM set_func_keyword;
127 static SCM show_func_keyword;
128 static SCM doc_keyword;
129 static SCM set_doc_keyword;
130 static SCM show_doc_keyword;
131 static SCM initial_value_keyword;
132 static SCM auto_keyword;
133 static SCM unlimited_keyword;
134 
135 static int pascm_is_valid (param_smob *);
136 static const char *pascm_param_type_name (enum var_types type);
137 static SCM pascm_param_value (enum var_types type, void *var,
138 			      int arg_pos, const char *func_name);
139 
140 /* Administrivia for parameter smobs.  */
141 
142 static int
143 pascm_print_param_smob (SCM self, SCM port, scm_print_state *pstate)
144 {
145   param_smob *p_smob = (param_smob *) SCM_SMOB_DATA (self);
146   SCM value;
147 
148   gdbscm_printf (port, "#<%s", param_smob_name);
149 
150   gdbscm_printf (port, " %s", p_smob->name);
151 
152   if (! pascm_is_valid (p_smob))
153     scm_puts (" {invalid}", port);
154 
155   gdbscm_printf (port, " %s ", pascm_param_type_name (p_smob->type));
156 
157   value = pascm_param_value (p_smob->type, &p_smob->value,
158 			     GDBSCM_ARG_NONE, NULL);
159   scm_display (value, port);
160 
161   scm_puts (">", port);
162 
163   scm_remember_upto_here_1 (self);
164 
165   /* Non-zero means success.  */
166   return 1;
167 }
168 
169 /* Create an empty (uninitialized) parameter.  */
170 
171 static SCM
172 pascm_make_param_smob (void)
173 {
174   param_smob *p_smob = (param_smob *)
175     scm_gc_malloc (sizeof (param_smob), param_smob_name);
176   SCM p_scm;
177 
178   memset (p_smob, 0, sizeof (*p_smob));
179   p_smob->cmd_class = no_class;
180   p_smob->type = var_boolean; /* ARI: var_boolean */
181   p_smob->set_func = SCM_BOOL_F;
182   p_smob->show_func = SCM_BOOL_F;
183   p_scm = scm_new_smob (parameter_smob_tag, (scm_t_bits) p_smob);
184   p_smob->containing_scm = p_scm;
185   gdbscm_init_gsmob (&p_smob->base);
186 
187   return p_scm;
188 }
189 
190 /* Returns non-zero if SCM is a <gdb:parameter> object.  */
191 
192 static int
193 pascm_is_parameter (SCM scm)
194 {
195   return SCM_SMOB_PREDICATE (parameter_smob_tag, scm);
196 }
197 
198 /* (gdb:parameter? scm) -> boolean */
199 
200 static SCM
201 gdbscm_parameter_p (SCM scm)
202 {
203   return scm_from_bool (pascm_is_parameter (scm));
204 }
205 
206 /* Returns the <gdb:parameter> object in SELF.
207    Throws an exception if SELF is not a <gdb:parameter> object.  */
208 
209 static SCM
210 pascm_get_param_arg_unsafe (SCM self, int arg_pos, const char *func_name)
211 {
212   SCM_ASSERT_TYPE (pascm_is_parameter (self), self, arg_pos, func_name,
213 		   param_smob_name);
214 
215   return self;
216 }
217 
218 /* Returns a pointer to the parameter smob of SELF.
219    Throws an exception if SELF is not a <gdb:parameter> object.  */
220 
221 static param_smob *
222 pascm_get_param_smob_arg_unsafe (SCM self, int arg_pos, const char *func_name)
223 {
224   SCM p_scm = pascm_get_param_arg_unsafe (self, arg_pos, func_name);
225   param_smob *p_smob = (param_smob *) SCM_SMOB_DATA (p_scm);
226 
227   return p_smob;
228 }
229 
230 /* Return non-zero if parameter P_SMOB is valid.  */
231 
232 static int
233 pascm_is_valid (param_smob *p_smob)
234 {
235   return p_smob->set_command != NULL;
236 }
237 
238 /* A helper function which return the default documentation string for
239    a parameter (which is to say that it's undocumented).  */
240 
241 static char *
242 get_doc_string (void)
243 {
244   return xstrdup (_("This command is not documented."));
245 }
246 
247 /* Subroutine of pascm_set_func, pascm_show_func to simplify them.
248    Signal the error returned from calling set_func/show_func.  */
249 
250 static void
251 pascm_signal_setshow_error (SCM exception, const char *msg)
252 {
253   /* Don't print the stack if this was an error signalled by the command
254      itself.  */
255   if (gdbscm_user_error_p (gdbscm_exception_key (exception)))
256     {
257       gdb::unique_xmalloc_ptr<char> excp_text
258 	= gdbscm_exception_message_to_string (exception);
259 
260       error ("%s", excp_text.get ());
261     }
262   else
263     {
264       gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
265       error ("%s", msg);
266     }
267 }
268 
269 /* A callback function that is registered against the respective
270    add_setshow_* set_func prototype.  This function will call
271    the Scheme function "set_func" which must exist.
272    Note: ARGS is always passed as NULL.  */
273 
274 static void
275 pascm_set_func (const char *args, int from_tty, struct cmd_list_element *c)
276 {
277   param_smob *p_smob = (param_smob *) get_cmd_context (c);
278   SCM self, result, exception;
279 
280   gdb_assert (gdbscm_is_procedure (p_smob->set_func));
281 
282   self = p_smob->containing_scm;
283 
284   result = gdbscm_safe_call_1 (p_smob->set_func, self, gdbscm_user_error_p);
285 
286   if (gdbscm_is_exception (result))
287     {
288       pascm_signal_setshow_error (result,
289 				  _("Error occurred setting parameter."));
290     }
291 
292   if (!scm_is_string (result))
293     error (_("Result of %s set-func is not a string."), p_smob->name);
294 
295   gdb::unique_xmalloc_ptr<char> msg = gdbscm_scm_to_host_string (result, NULL,
296 								 &exception);
297   if (msg == NULL)
298     {
299       gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
300       error (_("Error converting show text to host string."));
301     }
302 
303   /* GDB is usually silent when a parameter is set.  */
304   if (*msg.get () != '\0')
305     fprintf_filtered (gdb_stdout, "%s\n", msg.get ());
306 }
307 
308 /* A callback function that is registered against the respective
309    add_setshow_* show_func prototype.  This function will call
310    the Scheme function "show_func" which must exist and must return a
311    string that is then printed to FILE.  */
312 
313 static void
314 pascm_show_func (struct ui_file *file, int from_tty,
315 		 struct cmd_list_element *c, const char *value)
316 {
317   param_smob *p_smob = (param_smob *) get_cmd_context (c);
318   SCM value_scm, self, result, exception;
319 
320   gdb_assert (gdbscm_is_procedure (p_smob->show_func));
321 
322   value_scm = gdbscm_scm_from_host_string (value, strlen (value));
323   if (gdbscm_is_exception (value_scm))
324     {
325       error (_("Error converting parameter value \"%s\" to Scheme string."),
326 	     value);
327     }
328   self = p_smob->containing_scm;
329 
330   result = gdbscm_safe_call_2 (p_smob->show_func, self, value_scm,
331 			       gdbscm_user_error_p);
332 
333   if (gdbscm_is_exception (result))
334     {
335       pascm_signal_setshow_error (result,
336 				  _("Error occurred showing parameter."));
337     }
338 
339   gdb::unique_xmalloc_ptr<char> msg = gdbscm_scm_to_host_string (result, NULL,
340 								 &exception);
341   if (msg == NULL)
342     {
343       gdbscm_print_gdb_exception (SCM_BOOL_F, exception);
344       error (_("Error converting show text to host string."));
345     }
346 
347   fprintf_filtered (file, "%s\n", msg.get ());
348 }
349 
350 /* A helper function that dispatches to the appropriate add_setshow
351    function.  */
352 
353 static void
354 add_setshow_generic (enum var_types param_type, enum command_class cmd_class,
355 		     char *cmd_name, param_smob *self,
356 		     char *set_doc, char *show_doc, char *help_doc,
357 		     cmd_const_sfunc_ftype *set_func,
358 		     show_value_ftype *show_func,
359 		     struct cmd_list_element **set_list,
360 		     struct cmd_list_element **show_list,
361 		     struct cmd_list_element **set_cmd,
362 		     struct cmd_list_element **show_cmd)
363 {
364   struct cmd_list_element *param = NULL;
365   const char *tmp_name = NULL;
366 
367   switch (param_type)
368     {
369     case var_boolean:
370       add_setshow_boolean_cmd (cmd_name, cmd_class,
371 			       &self->value.boolval,
372 			       set_doc, show_doc, help_doc,
373 			       set_func, show_func,
374 			       set_list, show_list);
375 
376       break;
377 
378     case var_auto_boolean:
379       add_setshow_auto_boolean_cmd (cmd_name, cmd_class,
380 				    &self->value.autoboolval,
381 				    set_doc, show_doc, help_doc,
382 				    set_func, show_func,
383 				    set_list, show_list);
384       break;
385 
386     case var_uinteger:
387       add_setshow_uinteger_cmd (cmd_name, cmd_class,
388 				&self->value.uintval,
389 				set_doc, show_doc, help_doc,
390 				set_func, show_func,
391 				set_list, show_list);
392       break;
393 
394     case var_zinteger:
395       add_setshow_zinteger_cmd (cmd_name, cmd_class,
396 				&self->value.intval,
397 				set_doc, show_doc, help_doc,
398 				set_func, show_func,
399 				set_list, show_list);
400       break;
401 
402     case var_zuinteger:
403       add_setshow_zuinteger_cmd (cmd_name, cmd_class,
404 				 &self->value.uintval,
405 				 set_doc, show_doc, help_doc,
406 				 set_func, show_func,
407 				 set_list, show_list);
408       break;
409 
410     case var_zuinteger_unlimited:
411       add_setshow_zuinteger_unlimited_cmd (cmd_name, cmd_class,
412 					   &self->value.intval,
413 					   set_doc, show_doc, help_doc,
414 					   set_func, show_func,
415 					   set_list, show_list);
416       break;
417 
418     case var_string:
419       add_setshow_string_cmd (cmd_name, cmd_class,
420 			      &self->value.stringval,
421 			      set_doc, show_doc, help_doc,
422 			      set_func, show_func,
423 			      set_list, show_list);
424       break;
425 
426     case var_string_noescape:
427       add_setshow_string_noescape_cmd (cmd_name, cmd_class,
428 				       &self->value.stringval,
429 				       set_doc, show_doc, help_doc,
430 				       set_func, show_func,
431 				       set_list, show_list);
432 
433       break;
434 
435     case var_optional_filename:
436       add_setshow_optional_filename_cmd (cmd_name, cmd_class,
437 					 &self->value.stringval,
438 					 set_doc, show_doc, help_doc,
439 					 set_func, show_func,
440 					 set_list, show_list);
441       break;
442 
443     case var_filename:
444       add_setshow_filename_cmd (cmd_name, cmd_class,
445 				&self->value.stringval,
446 				set_doc, show_doc, help_doc,
447 				set_func, show_func,
448 				set_list, show_list);
449       break;
450 
451     case var_enum:
452       add_setshow_enum_cmd (cmd_name, cmd_class,
453 			    self->enumeration,
454 			    &self->value.cstringval,
455 			    set_doc, show_doc, help_doc,
456 			    set_func, show_func,
457 			    set_list, show_list);
458       /* Initialize the value, just in case.  */
459       self->value.cstringval = self->enumeration[0];
460       break;
461 
462     default:
463       gdb_assert_not_reached ("bad param_type value");
464     }
465 
466   /* Lookup created parameter, and register Scheme object against the
467      parameter context.  Perform this task against both lists.  */
468   tmp_name = cmd_name;
469   param = lookup_cmd (&tmp_name, *show_list, "", NULL, 0, 1);
470   gdb_assert (param != NULL);
471   set_cmd_context (param, self);
472   *set_cmd = param;
473 
474   tmp_name = cmd_name;
475   param = lookup_cmd (&tmp_name, *set_list, "", NULL, 0, 1);
476   gdb_assert (param != NULL);
477   set_cmd_context (param, self);
478   *show_cmd = param;
479 }
480 
481 /* Return an array of strings corresponding to the enum values for
482    ENUM_VALUES_SCM.
483    Throws an exception if there's a problem with the values.
484    Space for the result is allocated from the GC heap.  */
485 
486 static const char * const *
487 compute_enum_list (SCM enum_values_scm, int arg_pos, const char *func_name)
488 {
489   long i, size;
490   char **enum_values;
491   const char * const *result;
492 
493   SCM_ASSERT_TYPE (gdbscm_is_true (scm_list_p (enum_values_scm)),
494 		   enum_values_scm, arg_pos, func_name, _("list"));
495 
496   size = scm_ilength (enum_values_scm);
497   if (size == 0)
498     {
499       gdbscm_out_of_range_error (FUNC_NAME, arg_pos, enum_values_scm,
500 				 _("enumeration list is empty"));
501     }
502 
503   enum_values = XCNEWVEC (char *, size + 1);
504 
505   i = 0;
506   while (!scm_is_eq (enum_values_scm, SCM_EOL))
507     {
508       SCM value = scm_car (enum_values_scm);
509       SCM exception;
510 
511       if (!scm_is_string (value))
512 	{
513 	  freeargv (enum_values);
514 	  SCM_ASSERT_TYPE (0, value, arg_pos, func_name, _("string"));
515 	}
516       enum_values[i] = gdbscm_scm_to_host_string (value, NULL,
517 						  &exception).release ();
518       if (enum_values[i] == NULL)
519 	{
520 	  freeargv (enum_values);
521 	  gdbscm_throw (exception);
522 	}
523       ++i;
524       enum_values_scm = scm_cdr (enum_values_scm);
525     }
526   gdb_assert (i == size);
527 
528   result = gdbscm_gc_dup_argv (enum_values);
529   freeargv (enum_values);
530   return result;
531 }
532 
533 static const scheme_integer_constant parameter_types[] =
534 {
535   /* Note: var_integer is deprecated, and intentionally does not
536      appear here.  */
537   { "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */
538   { "PARAM_AUTO_BOOLEAN", var_auto_boolean },
539   { "PARAM_ZINTEGER", var_zinteger },
540   { "PARAM_UINTEGER", var_uinteger },
541   { "PARAM_ZUINTEGER", var_zuinteger },
542   { "PARAM_ZUINTEGER_UNLIMITED", var_zuinteger_unlimited },
543   { "PARAM_STRING", var_string },
544   { "PARAM_STRING_NOESCAPE", var_string_noescape },
545   { "PARAM_OPTIONAL_FILENAME", var_optional_filename },
546   { "PARAM_FILENAME", var_filename },
547   { "PARAM_ENUM", var_enum },
548 
549   END_INTEGER_CONSTANTS
550 };
551 
552 /* Return non-zero if PARAM_TYPE is a valid parameter type.  */
553 
554 static int
555 pascm_valid_parameter_type_p (int param_type)
556 {
557   int i;
558 
559   for (i = 0; parameter_types[i].name != NULL; ++i)
560     {
561       if (parameter_types[i].value == param_type)
562 	return 1;
563     }
564 
565   return 0;
566 }
567 
568 /* Return PARAM_TYPE as a string.  */
569 
570 static const char *
571 pascm_param_type_name (enum var_types param_type)
572 {
573   int i;
574 
575   for (i = 0; parameter_types[i].name != NULL; ++i)
576     {
577       if (parameter_types[i].value == param_type)
578 	return parameter_types[i].name;
579     }
580 
581   gdb_assert_not_reached ("bad parameter type");
582 }
583 
584 /* Return the value of a gdb parameter as a Scheme value.
585    If TYPE is not supported, then a <gdb:exception> object is returned.  */
586 
587 static SCM
588 pascm_param_value (enum var_types type, void *var,
589 		   int arg_pos, const char *func_name)
590 {
591   /* Note: We *could* support var_integer here in case someone is trying to get
592      the value of a Python-created parameter (which is the only place that
593      still supports var_integer).  To further discourage its use we do not.  */
594 
595   switch (type)
596     {
597     case var_string:
598     case var_string_noescape:
599     case var_optional_filename:
600     case var_filename:
601     case var_enum:
602       {
603 	const char *str = *(char **) var;
604 
605 	if (str == NULL)
606 	  str = "";
607 	return gdbscm_scm_from_host_string (str, strlen (str));
608       }
609 
610     case var_boolean:
611       {
612 	if (* (bool *) var)
613 	  return SCM_BOOL_T;
614 	else
615 	  return SCM_BOOL_F;
616       }
617 
618     case var_auto_boolean:
619       {
620 	enum auto_boolean ab = * (enum auto_boolean *) var;
621 
622 	if (ab == AUTO_BOOLEAN_TRUE)
623 	  return SCM_BOOL_T;
624 	else if (ab == AUTO_BOOLEAN_FALSE)
625 	  return SCM_BOOL_F;
626 	else
627 	  return auto_keyword;
628       }
629 
630     case var_zuinteger_unlimited:
631       if (* (int *) var == -1)
632 	return unlimited_keyword;
633       gdb_assert (* (int *) var >= 0);
634       /* Fall through.  */
635     case var_zinteger:
636       return scm_from_int (* (int *) var);
637 
638     case var_uinteger:
639       if (* (unsigned int *) var == UINT_MAX)
640 	return unlimited_keyword;
641       /* Fall through.  */
642     case var_zuinteger:
643       return scm_from_uint (* (unsigned int *) var);
644 
645     default:
646       break;
647     }
648 
649   return gdbscm_make_out_of_range_error (func_name, arg_pos,
650 					 scm_from_int (type),
651 					 _("program error: unhandled type"));
652 }
653 
654 /* Set the value of a parameter of type TYPE in VAR from VALUE.
655    ENUMERATION is the list of enum values for enum parameters, otherwise NULL.
656    Throws a Scheme exception if VALUE_SCM is invalid for TYPE.  */
657 
658 static void
659 pascm_set_param_value_x (enum var_types type, union pascm_variable *var,
660 			 const char * const *enumeration,
661 			 SCM value, int arg_pos, const char *func_name)
662 {
663   switch (type)
664     {
665     case var_string:
666     case var_string_noescape:
667     case var_optional_filename:
668     case var_filename:
669       SCM_ASSERT_TYPE (scm_is_string (value)
670 		       || (type != var_filename
671 			   && gdbscm_is_false (value)),
672 		       value, arg_pos, func_name,
673 		       _("string or #f for non-PARAM_FILENAME parameters"));
674       if (gdbscm_is_false (value))
675 	{
676 	  xfree (var->stringval);
677 	  if (type == var_optional_filename)
678 	    var->stringval = xstrdup ("");
679 	  else
680 	    var->stringval = NULL;
681 	}
682       else
683 	{
684 	  SCM exception;
685 
686 	  gdb::unique_xmalloc_ptr<char> string
687 	    = gdbscm_scm_to_host_string (value, NULL, &exception);
688 	  if (string == NULL)
689 	    gdbscm_throw (exception);
690 	  xfree (var->stringval);
691 	  var->stringval = string.release ();
692 	}
693       break;
694 
695     case var_enum:
696       {
697 	int i;
698 	SCM exception;
699 
700 	SCM_ASSERT_TYPE (scm_is_string (value), value, arg_pos, func_name,
701 		       _("string"));
702 	gdb::unique_xmalloc_ptr<char> str
703 	  = gdbscm_scm_to_host_string (value, NULL, &exception);
704 	if (str == NULL)
705 	  gdbscm_throw (exception);
706 	for (i = 0; enumeration[i]; ++i)
707 	  {
708 	    if (strcmp (enumeration[i], str.get ()) == 0)
709 	      break;
710 	  }
711 	if (enumeration[i] == NULL)
712 	  {
713 	    gdbscm_out_of_range_error (func_name, arg_pos, value,
714 				       _("not member of enumeration"));
715 	  }
716 	var->cstringval = enumeration[i];
717 	break;
718       }
719 
720     case var_boolean:
721       SCM_ASSERT_TYPE (gdbscm_is_bool (value), value, arg_pos, func_name,
722 		       _("boolean"));
723       var->boolval = gdbscm_is_true (value);
724       break;
725 
726     case var_auto_boolean:
727       SCM_ASSERT_TYPE (gdbscm_is_bool (value)
728 		       || scm_is_eq (value, auto_keyword),
729 		       value, arg_pos, func_name,
730 		       _("boolean or #:auto"));
731       if (scm_is_eq (value, auto_keyword))
732 	var->autoboolval = AUTO_BOOLEAN_AUTO;
733       else if (gdbscm_is_true (value))
734 	var->autoboolval = AUTO_BOOLEAN_TRUE;
735       else
736 	var->autoboolval = AUTO_BOOLEAN_FALSE;
737       break;
738 
739     case var_zinteger:
740     case var_uinteger:
741     case var_zuinteger:
742     case var_zuinteger_unlimited:
743       if (type == var_uinteger
744 	  || type == var_zuinteger_unlimited)
745 	{
746 	  SCM_ASSERT_TYPE (gdbscm_is_bool (value)
747 			   || scm_is_eq (value, unlimited_keyword),
748 			   value, arg_pos, func_name,
749 			   _("integer or #:unlimited"));
750 	  if (scm_is_eq (value, unlimited_keyword))
751 	    {
752 	      if (type == var_uinteger)
753 		var->intval = UINT_MAX;
754 	      else
755 		var->intval = -1;
756 	      break;
757 	    }
758 	}
759       else
760 	{
761 	  SCM_ASSERT_TYPE (scm_is_integer (value), value, arg_pos, func_name,
762 			   _("integer"));
763 	}
764 
765       if (type == var_uinteger
766 	  || type == var_zuinteger)
767 	{
768 	  unsigned int u = scm_to_uint (value);
769 
770 	  if (type == var_uinteger && u == 0)
771 	    u = UINT_MAX;
772 	  var->uintval = u;
773 	}
774       else
775 	{
776 	  int i = scm_to_int (value);
777 
778 	  if (type == var_zuinteger_unlimited && i < -1)
779 	    {
780 	      gdbscm_out_of_range_error (func_name, arg_pos, value,
781 					 _("must be >= -1"));
782 	    }
783 	  var->intval = i;
784 	}
785       break;
786 
787     default:
788       gdb_assert_not_reached ("bad parameter type");
789     }
790 }
791 
792 /* Parameter Scheme functions.  */
793 
794 /* (make-parameter name
795      [#:command-class cmd-class] [#:parameter-type param-type]
796      [#:enum-list enum-list] [#:set-func function] [#:show-func function]
797      [#:doc <string>] [#:set-doc <string>] [#:show-doc <string>]
798      [#:initial-value initial-value]) -> <gdb:parameter>
799 
800    NAME is the name of the parameter.  It may consist of multiple
801    words, in which case the final word is the name of the new parameter,
802    and earlier words must be prefix commands.
803 
804    CMD-CLASS is the kind of command.  It should be one of the COMMAND_*
805    constants defined in the gdb module.
806 
807    PARAM_TYPE is the type of the parameter.  It should be one of the
808    PARAM_* constants defined in the gdb module.
809 
810    If PARAM-TYPE is PARAM_ENUM, then ENUM-LIST is a list of strings that
811    are the valid values for this parameter.  The first value is the default.
812 
813    SET-FUNC, if provided, is called after the parameter is set.
814    It is a function of one parameter: the <gdb:parameter> object.
815    It must return a string to be displayed to the user.
816    Setting a parameter is typically a silent operation, so typically ""
817    should be returned.
818 
819    SHOW-FUNC, if provided, returns the string that is printed.
820    It is a function of two parameters: the <gdb:parameter> object
821    and the current value of the parameter as a string.
822 
823    DOC, SET-DOC, SHOW-DOC are the doc strings for the parameter.
824 
825    INITIAL-VALUE is the initial value of the parameter.
826 
827    The result is the <gdb:parameter> Scheme object.
828    The parameter is not available to be used yet, however.
829    It must still be added to gdb with register-parameter!.  */
830 
831 static SCM
832 gdbscm_make_parameter (SCM name_scm, SCM rest)
833 {
834   const SCM keywords[] = {
835     command_class_keyword, parameter_type_keyword, enum_list_keyword,
836     set_func_keyword, show_func_keyword,
837     doc_keyword, set_doc_keyword, show_doc_keyword,
838     initial_value_keyword, SCM_BOOL_F
839   };
840   int cmd_class_arg_pos = -1, param_type_arg_pos = -1;
841   int enum_list_arg_pos = -1, set_func_arg_pos = -1, show_func_arg_pos = -1;
842   int doc_arg_pos = -1, set_doc_arg_pos = -1, show_doc_arg_pos = -1;
843   int initial_value_arg_pos = -1;
844   char *s;
845   char *name;
846   int cmd_class = no_class;
847   int param_type = var_boolean; /* ARI: var_boolean */
848   SCM enum_list_scm = SCM_BOOL_F;
849   SCM set_func = SCM_BOOL_F, show_func = SCM_BOOL_F;
850   char *doc = NULL, *set_doc = NULL, *show_doc = NULL;
851   SCM initial_value_scm = SCM_BOOL_F;
852   const char * const *enum_list = NULL;
853   SCM p_scm;
854   param_smob *p_smob;
855 
856   gdbscm_parse_function_args (FUNC_NAME, SCM_ARG1, keywords, "s#iiOOOsssO",
857 			      name_scm, &name, rest,
858 			      &cmd_class_arg_pos, &cmd_class,
859 			      &param_type_arg_pos, &param_type,
860 			      &enum_list_arg_pos, &enum_list_scm,
861 			      &set_func_arg_pos, &set_func,
862 			      &show_func_arg_pos, &show_func,
863 			      &doc_arg_pos, &doc,
864 			      &set_doc_arg_pos, &set_doc,
865 			      &show_doc_arg_pos, &show_doc,
866 			      &initial_value_arg_pos, &initial_value_scm);
867 
868   /* If doc is NULL, leave it NULL.  See add_setshow_cmd_full.  */
869   if (set_doc == NULL)
870     set_doc = get_doc_string ();
871   if (show_doc == NULL)
872     show_doc = get_doc_string ();
873 
874   s = name;
875   name = gdbscm_canonicalize_command_name (s, 0);
876   xfree (s);
877   if (doc != NULL)
878     {
879       s = doc;
880       doc = gdbscm_gc_xstrdup (s);
881       xfree (s);
882     }
883   s = set_doc;
884   set_doc = gdbscm_gc_xstrdup (s);
885   xfree (s);
886   s = show_doc;
887   show_doc = gdbscm_gc_xstrdup (s);
888   xfree (s);
889 
890   if (!gdbscm_valid_command_class_p (cmd_class))
891     {
892       gdbscm_out_of_range_error (FUNC_NAME, cmd_class_arg_pos,
893 				 scm_from_int (cmd_class),
894 				 _("invalid command class argument"));
895     }
896   if (!pascm_valid_parameter_type_p (param_type))
897     {
898       gdbscm_out_of_range_error (FUNC_NAME, param_type_arg_pos,
899 				 scm_from_int (param_type),
900 				 _("invalid parameter type argument"));
901     }
902   if (enum_list_arg_pos > 0 && param_type != var_enum)
903     {
904       gdbscm_misc_error (FUNC_NAME, enum_list_arg_pos, enum_list_scm,
905 		_("#:enum-values can only be provided with PARAM_ENUM"));
906     }
907   if (enum_list_arg_pos < 0 && param_type == var_enum)
908     {
909       gdbscm_misc_error (FUNC_NAME, GDBSCM_ARG_NONE, SCM_BOOL_F,
910 			 _("PARAM_ENUM requires an enum-values argument"));
911     }
912   if (set_func_arg_pos > 0)
913     {
914       SCM_ASSERT_TYPE (gdbscm_is_procedure (set_func), set_func,
915 		       set_func_arg_pos, FUNC_NAME, _("procedure"));
916     }
917   if (show_func_arg_pos > 0)
918     {
919       SCM_ASSERT_TYPE (gdbscm_is_procedure (show_func), show_func,
920 		       show_func_arg_pos, FUNC_NAME, _("procedure"));
921     }
922   if (param_type == var_enum)
923     {
924       /* Note: enum_list lives in GC space, so we don't have to worry about
925 	 freeing it if we later throw an exception.  */
926       enum_list = compute_enum_list (enum_list_scm, enum_list_arg_pos,
927 				     FUNC_NAME);
928     }
929 
930   /* If initial-value is a function, we need the parameter object constructed
931      to pass it to the function.  A typical thing the function may want to do
932      is add an object-property to it to record the last known good value.  */
933   p_scm = pascm_make_param_smob ();
934   p_smob = (param_smob *) SCM_SMOB_DATA (p_scm);
935   /* These are all stored in GC space so that we don't have to worry about
936      freeing them if we throw an exception.  */
937   p_smob->name = name;
938   p_smob->cmd_class = (enum command_class) cmd_class;
939   p_smob->type = (enum var_types) param_type;
940   p_smob->doc = doc;
941   p_smob->set_doc = set_doc;
942   p_smob->show_doc = show_doc;
943   p_smob->enumeration = enum_list;
944   p_smob->set_func = set_func;
945   p_smob->show_func = show_func;
946 
947   if (initial_value_arg_pos > 0)
948     {
949       if (gdbscm_is_procedure (initial_value_scm))
950 	{
951 	  initial_value_scm = gdbscm_safe_call_1 (initial_value_scm,
952 						  p_smob->containing_scm, NULL);
953 	  if (gdbscm_is_exception (initial_value_scm))
954 	    gdbscm_throw (initial_value_scm);
955 	}
956       pascm_set_param_value_x (p_smob->type, &p_smob->value, enum_list,
957 			       initial_value_scm,
958 			       initial_value_arg_pos, FUNC_NAME);
959     }
960 
961   return p_scm;
962 }
963 
964 /* Subroutine of gdbscm_register_parameter_x to simplify it.
965    Return non-zero if parameter NAME is already defined in LIST.  */
966 
967 static int
968 pascm_parameter_defined_p (const char *name, struct cmd_list_element *list)
969 {
970   struct cmd_list_element *c;
971 
972   c = lookup_cmd_1 (&name, list, NULL, NULL, 1);
973 
974   /* If the name is ambiguous that's ok, it's a new parameter still.  */
975   return c != NULL && c != CMD_LIST_AMBIGUOUS;
976 }
977 
978 /* (register-parameter! <gdb:parameter>) -> unspecified
979 
980    It is an error to register a pre-existing parameter.  */
981 
982 static SCM
983 gdbscm_register_parameter_x (SCM self)
984 {
985   param_smob *p_smob
986     = pascm_get_param_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
987   char *cmd_name;
988   struct cmd_list_element **set_list, **show_list;
989 
990   if (pascm_is_valid (p_smob))
991     scm_misc_error (FUNC_NAME, _("parameter is already registered"), SCM_EOL);
992 
993   cmd_name = gdbscm_parse_command_name (p_smob->name, FUNC_NAME, SCM_ARG1,
994 					&set_list, &setlist);
995   xfree (cmd_name);
996   cmd_name = gdbscm_parse_command_name (p_smob->name, FUNC_NAME, SCM_ARG1,
997 					&show_list, &showlist);
998   p_smob->cmd_name = gdbscm_gc_xstrdup (cmd_name);
999   xfree (cmd_name);
1000 
1001   if (pascm_parameter_defined_p (p_smob->cmd_name, *set_list))
1002     {
1003       gdbscm_misc_error (FUNC_NAME, SCM_ARG1, self,
1004 		_("parameter exists, \"set\" command is already defined"));
1005     }
1006   if (pascm_parameter_defined_p (p_smob->cmd_name, *show_list))
1007     {
1008       gdbscm_misc_error (FUNC_NAME, SCM_ARG1, self,
1009 		_("parameter exists, \"show\" command is already defined"));
1010     }
1011 
1012   gdbscm_gdb_exception exc {};
1013   try
1014     {
1015       add_setshow_generic (p_smob->type, p_smob->cmd_class,
1016 			   p_smob->cmd_name, p_smob,
1017 			   p_smob->set_doc, p_smob->show_doc, p_smob->doc,
1018 			   (gdbscm_is_procedure (p_smob->set_func)
1019 			    ? pascm_set_func : NULL),
1020 			   (gdbscm_is_procedure (p_smob->show_func)
1021 			    ? pascm_show_func : NULL),
1022 			   set_list, show_list,
1023 			   &p_smob->set_command, &p_smob->show_command);
1024     }
1025   catch (const gdb_exception &except)
1026     {
1027       exc = unpack (except);
1028     }
1029 
1030   GDBSCM_HANDLE_GDB_EXCEPTION (exc);
1031   /* Note: At this point the parameter exists in gdb.
1032      So no more errors after this point.  */
1033 
1034   /* The owner of this parameter is not in GC-controlled memory, so we need
1035      to protect it from GC until the parameter is deleted.  */
1036   scm_gc_protect_object (p_smob->containing_scm);
1037 
1038   return SCM_UNSPECIFIED;
1039 }
1040 
1041 /* (parameter-value <gdb:parameter>) -> value
1042    (parameter-value <string>) -> value */
1043 
1044 static SCM
1045 gdbscm_parameter_value (SCM self)
1046 {
1047   SCM_ASSERT_TYPE (pascm_is_parameter (self) || scm_is_string (self),
1048 		   self, SCM_ARG1, FUNC_NAME, _("<gdb:parameter> or string"));
1049 
1050   if (pascm_is_parameter (self))
1051     {
1052       param_smob *p_smob = pascm_get_param_smob_arg_unsafe (self, SCM_ARG1,
1053 							    FUNC_NAME);
1054 
1055       return pascm_param_value (p_smob->type, &p_smob->value,
1056 				SCM_ARG1, FUNC_NAME);
1057     }
1058   else
1059     {
1060       SCM except_scm;
1061       struct cmd_list_element *alias, *prefix, *cmd;
1062       char *newarg;
1063       int found = -1;
1064       gdbscm_gdb_exception except {};
1065 
1066       gdb::unique_xmalloc_ptr<char> name
1067 	= gdbscm_scm_to_host_string (self, NULL, &except_scm);
1068       if (name == NULL)
1069 	gdbscm_throw (except_scm);
1070       newarg = concat ("show ", name.get (), (char *) NULL);
1071       try
1072 	{
1073 	  found = lookup_cmd_composition (newarg, &alias, &prefix, &cmd);
1074 	}
1075       catch (const gdb_exception &ex)
1076 	{
1077 	  except = unpack (ex);
1078 	}
1079 
1080       xfree (newarg);
1081       GDBSCM_HANDLE_GDB_EXCEPTION (except);
1082       if (!found)
1083 	{
1084 	  gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
1085 				     _("parameter not found"));
1086 	}
1087       if (cmd->var == NULL)
1088 	{
1089 	  gdbscm_out_of_range_error (FUNC_NAME, SCM_ARG1, self,
1090 				     _("not a parameter"));
1091 	}
1092 
1093       return pascm_param_value (cmd->var_type, cmd->var, SCM_ARG1, FUNC_NAME);
1094     }
1095 }
1096 
1097 /* (set-parameter-value! <gdb:parameter> value) -> unspecified */
1098 
1099 static SCM
1100 gdbscm_set_parameter_value_x (SCM self, SCM value)
1101 {
1102   param_smob *p_smob = pascm_get_param_smob_arg_unsafe (self, SCM_ARG1,
1103 							FUNC_NAME);
1104 
1105   pascm_set_param_value_x (p_smob->type, &p_smob->value, p_smob->enumeration,
1106 			   value, SCM_ARG2, FUNC_NAME);
1107 
1108   return SCM_UNSPECIFIED;
1109 }
1110 
1111 /* Initialize the Scheme parameter support.  */
1112 
1113 static const scheme_function parameter_functions[] =
1114 {
1115   { "make-parameter", 1, 0, 1, as_a_scm_t_subr (gdbscm_make_parameter),
1116     "\
1117 Make a GDB parameter object.\n\
1118 \n\
1119   Arguments: name\n\
1120       [#:command-class <cmd-class>] [#:parameter-type <parameter-type>]\n\
1121       [#:enum-list <enum-list>]\n\
1122       [#:set-func function] [#:show-func function]\n\
1123       [#:doc string] [#:set-doc string] [#:show-doc string]\n\
1124       [#:initial-value initial-value]\n\
1125     name: The name of the command.  It may consist of multiple words,\n\
1126       in which case the final word is the name of the new parameter, and\n\
1127       earlier words must be prefix commands.\n\
1128     cmd-class: The class of the command, one of COMMAND_*.\n\
1129       The default is COMMAND_NONE.\n\
1130     parameter-type: The kind of parameter, one of PARAM_*\n\
1131       The default is PARAM_BOOLEAN.\n\
1132     enum-list: If parameter-type is PARAM_ENUM, then this specifies the set\n\
1133       of values of the enum.\n\
1134     set-func: A function of one parameter: the <gdb:parameter> object.\n\
1135       Called *after* the parameter has been set.  Returns either \"\" or a\n\
1136       non-empty string to be displayed to the user.\n\
1137       If non-empty, GDB will add a trailing newline.\n\
1138     show-func: A function of two parameters: the <gdb:parameter> object\n\
1139       and the string representation of the current value.\n\
1140       The result is a string to be displayed to the user.\n\
1141       GDB will add a trailing newline.\n\
1142     doc: The \"doc string\" of the parameter.\n\
1143     set-doc: The \"doc string\" when setting the parameter.\n\
1144     show-doc: The \"doc string\" when showing the parameter.\n\
1145     initial-value: The initial value of the parameter." },
1146 
1147   { "register-parameter!", 1, 0, 0,
1148     as_a_scm_t_subr (gdbscm_register_parameter_x),
1149     "\
1150 Register a <gdb:parameter> object with GDB." },
1151 
1152   { "parameter?", 1, 0, 0, as_a_scm_t_subr (gdbscm_parameter_p),
1153     "\
1154 Return #t if the object is a <gdb:parameter> object." },
1155 
1156   { "parameter-value", 1, 0, 0, as_a_scm_t_subr (gdbscm_parameter_value),
1157     "\
1158 Return the value of a <gdb:parameter> object\n\
1159 or any gdb parameter if param is a string naming the parameter." },
1160 
1161   { "set-parameter-value!", 2, 0, 0,
1162     as_a_scm_t_subr (gdbscm_set_parameter_value_x),
1163     "\
1164 Set the value of a <gdb:parameter> object.\n\
1165 \n\
1166   Arguments: <gdb:parameter> value" },
1167 
1168   END_FUNCTIONS
1169 };
1170 
1171 void
1172 gdbscm_initialize_parameters (void)
1173 {
1174   parameter_smob_tag
1175     = gdbscm_make_smob_type (param_smob_name, sizeof (param_smob));
1176   scm_set_smob_print (parameter_smob_tag, pascm_print_param_smob);
1177 
1178   gdbscm_define_integer_constants (parameter_types, 1);
1179   gdbscm_define_functions (parameter_functions, 1);
1180 
1181   command_class_keyword = scm_from_latin1_keyword ("command-class");
1182   parameter_type_keyword = scm_from_latin1_keyword ("parameter-type");
1183   enum_list_keyword = scm_from_latin1_keyword ("enum-list");
1184   set_func_keyword = scm_from_latin1_keyword ("set-func");
1185   show_func_keyword = scm_from_latin1_keyword ("show-func");
1186   doc_keyword = scm_from_latin1_keyword ("doc");
1187   set_doc_keyword = scm_from_latin1_keyword ("set-doc");
1188   show_doc_keyword = scm_from_latin1_keyword ("show-doc");
1189   initial_value_keyword = scm_from_latin1_keyword ("initial-value");
1190   auto_keyword = scm_from_latin1_keyword ("auto");
1191   unlimited_keyword = scm_from_latin1_keyword ("unlimited");
1192 }
1193