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

Philippe Waroquiers
2019-07-06T10:50:03Z

The new convenience functions $_gdb_setting and $_gdb_int_setting
provide access to the GDB settings in user-defined commands.

gdb/ChangeLog
2019-07-06 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.
---
gdb/cli/cli-cmds.c | 103 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 368ddf526d..4316b0d578 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1905,6 +1905,98 @@ 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);
+ std::string cmd_val = get_setshow_command_value_string (cmd);
+
+ return value_cstring (cmd_val.c_str (), strlen (cmd_val.c_str ()),
+ builtin_type (gdbarch)->builtin_char);
+}
+
+
void
_initialize_cli_cmds (void)
{
@@ -2045,6 +2137,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\
--
2.20.1