[RFAv2 1/3] Implement convenience functions to examine GDB settings.

Philippe Waroquiers philippe.waroquiers@skynet.be
Fri Jul 5 19:58:00 GMT 2019


The new convenience functions $_gdb_setting and $_gdb_int_setting
provide access to the GDB settings in user-defined commands.
---
 gdb/ChangeLog         |  10 ++++
 gdb/cli/cli-cmds.c    | 105 ++++++++++++++++++++++++++++++++++++++++++
 gdb/cli/cli-setshow.c |  43 ++++++++++++-----
 gdb/cli/cli-setshow.h |   5 ++
 4 files changed, 151 insertions(+), 12 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a462b27ba5..ab414dca9f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -9112,3 +9112,13 @@ version-control: never
 coding: utf-8
 End:
 
+2019-04-28  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* cli/cli-cmds.c (setting_cmd, gdb_int_setting_internal_fn,
+	gdb_setting_internal_fn): New functions.
+	(_initialize_cli_cmds): Define the new convenience functions.
+	* cli/cli-setshow.h (do_print_setting): New declaration.
+	* cli/cli-setshow.c (do_print_setting): New function (mostly
+	copied from do_show_command).
+	(do_show_command): Call do_print_setting.
+	(do_print_setting): New function.
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 368ddf526d..a4d3f5ec9e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1905,6 +1905,100 @@ show_max_user_call_depth (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* Returns the cmd_list_element corresponding to the first argument
+   of ARGV, which must contain one single value.
+   Throws an error if no value provided, or value not correct.
+   FNNAME is used in the error message.  */
+
+static cmd_list_element *
+setting_cmd (const char *fnname, int argc, struct value **argv)
+{
+  if (argc == 0)
+    error (_("You must provide an argument to %s"), fnname);
+  if (argc != 1)
+    error (_("You can only provide one argument to %s"), fnname);
+
+  struct type *type0 = check_typedef (value_type (argv[0]));
+
+  if (TYPE_CODE (type0) != TYPE_CODE_ARRAY
+      && TYPE_CODE (type0) != TYPE_CODE_STRING)
+    error (_("First argument of %s must be a string."), fnname);
+
+  int len0 = TYPE_LENGTH (type0);
+  std::vector<char> arg0 (len0);
+
+  memcpy (arg0.data (), value_contents (argv[0]), len0);
+
+  const char *a0 = arg0.data ();
+  cmd_list_element *cmd = lookup_cmd (&a0, showlist, "", -1, 0);
+
+  if (cmd == nullptr || cmd_type (cmd) != show_cmd)
+    error (_("First argument of %s must be a "
+	     "valid setting of the 'show' command."), fnname);
+
+  return cmd;
+}
+
+/* Implementation of the convenience function $_gdb_int_setting.  */
+
+static struct value *
+gdb_int_setting_internal_fn (struct gdbarch *gdbarch,
+			     const struct language_defn *language,
+			     void *cookie, int argc, struct value **argv)
+{
+  cmd_list_element *cmd = setting_cmd ("$_gdb_int_setting", argc, argv);
+
+  switch (cmd->var_type)
+    {
+    case var_boolean:
+    case var_integer:
+    case var_zinteger:
+    case var_zuinteger_unlimited:
+      return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				 *(int *) cmd->var);
+    case var_auto_boolean:
+      {
+	int val = *(int *) cmd->var;
+
+	if (val == 0)
+	  val = 1;
+	else if (val == 1)
+	  val = 0;
+	return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				   val);
+      }
+    case var_uinteger:
+      if (*(unsigned int *) cmd->var == UINT_MAX)
+	return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				   0);
+      else
+	return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				   *(unsigned int *) cmd->var);
+    case var_zuinteger:
+      return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				 *(unsigned int *) cmd->var);
+    default:
+      error (_("Setting type not convertible to integer"));
+    }
+}
+
+/* Implementation of the convenience function $_gdb_setting.  */
+
+static struct value *
+gdb_setting_internal_fn (struct gdbarch *gdbarch,
+			 const struct language_defn *language,
+			 void *cookie, int argc, struct value **argv)
+{
+  cmd_list_element *cmd = setting_cmd ("$_gdb_setting", argc, argv);
+  string_file stb;
+
+  do_print_setting (&stb, cmd);
+
+  return value_cstring (stb.c_str (), strlen (stb.c_str ()),
+			builtin_type (gdbarch)->builtin_char);
+}
+
+
 void
 _initialize_cli_cmds (void)
 {
@@ -2045,6 +2139,17 @@ abbreviations for commands and/or values.  E.g.:\n\
   set_cmd_completer_handle_brkchars (c, with_command_completer);
   add_com_alias ("w", "with", class_vars, 1);
 
+  add_internal_function ("_gdb_setting", _("\
+$_gdb_setting - returns the value of a GDB setting as a string.\n\
+Usage: $_gdb_setting (setting)"),
+			 gdb_setting_internal_fn, NULL);
+
+  add_internal_function ("_gdb_int_setting", _("\
+$_gdb_int_setting - returns the value of an integer GDB setting as an integer.\n\
+Usage: $_int_gdb_int_setting (setting)\n\
+Throws an error if SETTING cannot be converted to an integer."),
+			 gdb_int_setting_internal_fn, NULL);
+
   add_cmd ("commands", no_set_class, show_commands, _("\
 Show the history of commands you typed.\n\
 You can supply a command number to start with, or a `+' to start after\n\
diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index 6fb32441ac..56c9dcab9f 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -634,29 +634,29 @@ get_setshow_command_value_string (cmd_list_element *c)
     {
     case var_string:
       if (*(char **) c->var)
-	stb.putstr (*(char **) c->var, '"');
+	stb->putstr (*(char **) c->var, '"');
       break;
     case var_string_noescape:
     case var_optional_filename:
     case var_filename:
     case var_enum:
       if (*(char **) c->var)
-	stb.puts (*(char **) c->var);
+	stb->puts (*(char **) c->var);
       break;
     case var_boolean:
-      stb.puts (*(int *) c->var ? "on" : "off");
+      stb->puts (*(int *) c->var ? "on" : "off");
       break;
     case var_auto_boolean:
       switch (*(enum auto_boolean*) c->var)
 	{
 	case AUTO_BOOLEAN_TRUE:
-	  stb.puts ("on");
+	  stb->puts ("on");
 	  break;
 	case AUTO_BOOLEAN_FALSE:
-	  stb.puts ("off");
+	  stb->puts ("off");
 	  break;
 	case AUTO_BOOLEAN_AUTO:
-	  stb.puts ("auto");
+	  stb->puts ("auto");
 	  break;
 	default:
 	  gdb_assert_not_reached ("invalid var_auto_boolean");
@@ -667,29 +667,48 @@ get_setshow_command_value_string (cmd_list_element *c)
     case var_zuinteger:
       if (c->var_type == var_uinteger
 	  && *(unsigned int *) c->var == UINT_MAX)
-	stb.puts ("unlimited");
+	stb->puts ("unlimited");
       else
-	stb.printf ("%u", *(unsigned int *) c->var);
+	stb->printf ("%u", *(unsigned int *) c->var);
       break;
     case var_integer:
     case var_zinteger:
       if (c->var_type == var_integer
 	  && *(int *) c->var == INT_MAX)
-	stb.puts ("unlimited");
+	stb->puts ("unlimited");
       else
-	stb.printf ("%d", *(int *) c->var);
+	stb->printf ("%d", *(int *) c->var);
       break;
     case var_zuinteger_unlimited:
       {
 	if (*(int *) c->var == -1)
-	  stb.puts ("unlimited");
+	  stb->puts ("unlimited");
 	else
-	  stb.printf ("%d", *(int *) c->var);
+	  stb->printf ("%d", *(int *) c->var);
       }
       break;
     default:
       gdb_assert_not_reached ("bad var_type");
     }
+}
+
+/* Do a "show" command.  ARG is NULL if no argument, or the
+   text of the argument, and FROM_TTY is nonzero if this command is
+   being entered directly by the user (i.e. these are just like any
+   other command).  C is the command list element for the command.  */
+
+void
+do_show_command (const char *arg, int from_tty, struct cmd_list_element *c)
+{
+  struct ui_out *uiout = current_uiout;
+
+  gdb_assert (c->type == show_cmd);
+
+  string_file stb;
+
+  /* Possibly call the pre hook.  */
+  if (c->pre_show_hook)
+    (c->pre_show_hook) (c);
 
   return std::move (stb.string ());
 }
diff --git a/gdb/cli/cli-setshow.h b/gdb/cli/cli-setshow.h
index 8bfe7e89f0..bcd6e475cd 100644
--- a/gdb/cli/cli-setshow.h
+++ b/gdb/cli/cli-setshow.h
@@ -63,4 +63,9 @@ extern std::string get_setshow_command_value_string (cmd_list_element *c);
 extern void cmd_show_list (struct cmd_list_element *list, int from_tty,
 			   const char *prefix);
 
+/* Prints in STB the current value of the GDB setting shown by C.  */
+
+void
+do_print_setting (string_file *stb, struct cmd_list_element *c);
+
 #endif /* CLI_CLI_SETSHOW_H */
-- 
2.20.1



More information about the Gdb-patches mailing list