public inbox for gdb-testers@sourceware.org
help / color / mirror / Atom feed
From: gdb-buildbot@sergiodj.net
To: gdb-testers@sourceware.org
Subject: [binutils-gdb] Implement convenience functions to examine GDB settings.
Date: Fri, 01 Nov 2019 01:46:00 -0000	[thread overview]
Message-ID: <9ad9b77d64920d3113a9e7ab9f022eb5a45cd49e@gdb-build> (raw)

*** TEST RESULTS FOR COMMIT 9ad9b77d64920d3113a9e7ab9f022eb5a45cd49e ***

commit 9ad9b77d64920d3113a9e7ab9f022eb5a45cd49e
Author:     Philippe Waroquiers <philippe.waroquiers@skynet.be>
AuthorDate: Sun Apr 28 14:38:18 2019 +0200
Commit:     Philippe Waroquiers <philippe.waroquiers@skynet.be>
CommitDate: Thu Oct 31 23:31:43 2019 +0100

    Implement convenience functions to examine GDB settings.
    
    The new convenience functions $_gdb_setting and $_gdb_setting_str
    provide access to the GDB settings in user-defined commands.
    Similarly, $_gdb_maint_setting and $_gdb_maint_setting_str
    provide access to the GDB maintenance settings.
    
    The patch was developed following a comment of Eli about the
    'set may-call-functions'.  Eli said that user-defined functions
    should have a way to change their behavior according to this setting.
    Rather than have a specialized $_may_call_functions, this patch
    implements a general way to access any GDB setting.
    
    Compared to doing such access via Python 'gdb.parameter' and/or
    'gdb.execute("set somesetting tosomevalue"):
    * The 'with' command is much better than the above python usage:
      if the user types C-c or an error happens between the set pagination off
      and the python "set pagination on", the above python
      does not restore the original setting.
    
    * Effectively, with the "gdb.parameter" python one liner, it is possible to do
      simple 'if' conditions, such as set and restore pagination.
      But mixing the "python if" within canned
      sequence of commands is cumbersome for non trivial combinations.
      E.g. if several commands have to be done for a certain condition
      accessed from python, I guess something like will be needed:
         python if __some_setting: gdb.execute("some command")
         python if __some_setting: gdb.execute("some other command")
         python if __some_setting: gdb.execute("some different command")
      (without speaking about nested "if-s").
    
      With the convenience function:
         if $_gdb_setting("some_setting")
            some command
            some other command
            some different command
         end
      Integer settings (for example print elements) will also be more difficult
      to use.
      For example, a user defined function that scans and prints a linked list
      might want to use the value of "set print elements" to stop printing
      the linked list.
      Doing that by mixing python expression/if is likely doable, but seems
      not easy with the above one liners.
    
    So, in summary, the $_gdb_setting and $_gdb_setting_str avoids to have the
    heterogeneous mix of python and GDB commands in one single script
    (and of course, it works even if python is not configured, but that
    must be an unusual setup I guess).
    
    gdb/ChangeLog
    2019-10-31  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
    
            * cli/cli-cmds.c (setting_cmd, value_from_setting)
            (gdb_setting_internal_fn, gdb_maint_setting_internal_fn)
            (str_value_from_setting, gdb_setting_str_internal_fn)
            (gdb_maint_setting_str_internal_fn): New functions.
            (_initialize_cli_cmds): Define the new convenience functions.
            * gdb/cli/cli-setshow.h (get_setshow_command_value_string): Constify.
            * gdb/cli/cli-setshow.c (get_setshow_command_value_string): Constify.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 3c26e6d6f3..7c68083b01 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2019-10-31  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* cli/cli-cmds.c (setting_cmd, value_from_setting)
+	(gdb_setting_internal_fn, gdb_maint_setting_internal_fn)
+	(str_value_from_setting, gdb_setting_str_internal_fn)
+	(gdb_maint_setting_str_internal_fn): New functions.
+	(_initialize_cli_cmds): Define the new convenience functions.
+	* gdb/cli/cli-setshow.h (get_setshow_command_value_string): Constify.
+	* gdb/cli/cli-setshow.c (get_setshow_command_value_string): Constify.
+
 2019-10-31  Christian Biesinger  <cbiesinger@google.com>
 
 	* agent.c (set_can_use_agent): When the setting is turned on,
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index a39ea22604..4e58ddc6d6 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -1912,6 +1912,200 @@ show_max_user_call_depth (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* Returns the cmd_list_element in SHOWLIST 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, struct cmd_list_element *showlist,
+	     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);
+
+  const char *a0 = (const char *) value_contents (argv[0]);
+  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;
+}
+
+/* Builds a value from the show CMD.  */
+
+static struct value *
+value_from_setting (const cmd_list_element *cmd, struct gdbarch *gdbarch)
+{
+  switch (cmd->var_type)
+    {
+    case var_integer:
+      if (*(int *) cmd->var == INT_MAX)
+	return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				   0);
+      else
+	return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				   *(int *) cmd->var);
+    case var_zinteger:
+      return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				 *(int *) cmd->var);
+    case var_boolean:
+      return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				 *(bool *) cmd->var ? 1 : 0);
+    case var_zuinteger_unlimited:
+      return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				 *(int *) cmd->var);
+    case var_auto_boolean:
+      {
+	int val;
+
+	switch (*(enum auto_boolean*) cmd->var)
+	  {
+	  case AUTO_BOOLEAN_TRUE:
+	    val = 1;
+	    break;
+	  case AUTO_BOOLEAN_FALSE:
+	    val = 0;
+	    break;
+	  case AUTO_BOOLEAN_AUTO:
+	    val = -1;
+	    break;
+	  default:
+	    gdb_assert_not_reached ("invalid var_auto_boolean");
+	  }
+	return value_from_longest (builtin_type (gdbarch)->builtin_int,
+				   val);
+      }
+    case var_uinteger:
+      if (*(unsigned int *) cmd->var == UINT_MAX)
+	return value_from_ulongest
+	  (builtin_type (gdbarch)->builtin_unsigned_int, 0);
+      else
+	return value_from_ulongest
+	  (builtin_type (gdbarch)->builtin_unsigned_int,
+	   *(unsigned int *) cmd->var);
+    case var_zuinteger:
+      return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
+				  *(unsigned int *) cmd->var);
+    case var_string:
+    case var_string_noescape:
+    case var_optional_filename:
+    case var_filename:
+    case var_enum:
+      if (*(char **) cmd->var)
+	return value_cstring (*(char **) cmd->var, strlen (*(char **) cmd->var),
+			      builtin_type (gdbarch)->builtin_char);
+      else
+	return value_cstring ("", 1,
+			      builtin_type (gdbarch)->builtin_char);
+    default:
+      gdb_assert_not_reached ("bad var_type");
+    }
+}
+
+/* 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)
+{
+  return value_from_setting (setting_cmd ("$_gdb_setting", showlist,
+					  argc, argv),
+			     gdbarch);
+}
+
+/* Implementation of the convenience function $_gdb_maint_setting.  */
+
+static struct value *
+gdb_maint_setting_internal_fn (struct gdbarch *gdbarch,
+			       const struct language_defn *language,
+			       void *cookie, int argc, struct value **argv)
+{
+  return value_from_setting (setting_cmd ("$_gdb_maint_setting",
+					  maintenance_show_cmdlist,
+					  argc, argv),
+			     gdbarch);
+}
+
+/* Builds a string value from the show CMD.  */
+
+static struct value *
+str_value_from_setting (const cmd_list_element *cmd, struct gdbarch *gdbarch)
+{
+  switch (cmd->var_type)
+    {
+    case var_integer:
+    case var_zinteger:
+    case var_boolean:
+    case var_zuinteger_unlimited:
+    case var_auto_boolean:
+    case var_uinteger:
+    case var_zuinteger:
+      {
+	std::string cmd_val = get_setshow_command_value_string (cmd);
+
+	return value_cstring (cmd_val.c_str (), cmd_val.size (),
+			      builtin_type (gdbarch)->builtin_char);
+      }
+
+    case var_string:
+    case var_string_noescape:
+    case var_optional_filename:
+    case var_filename:
+    case var_enum:
+      /* For these cases, we do not use get_setshow_command_value_string,
+	 as this function handle some characters specially, e.g. by
+	 escaping quotes.  So, we directly use the cmd->var string value,
+	 similarly to the value_from_setting code for these cases.  */
+      if (*(char **) cmd->var)
+	return value_cstring (*(char **) cmd->var, strlen (*(char **) cmd->var),
+			      builtin_type (gdbarch)->builtin_char);
+      else
+	return value_cstring ("", 1,
+			      builtin_type (gdbarch)->builtin_char);
+
+    default:
+      gdb_assert_not_reached ("bad var_type");
+    }
+}
+
+/* Implementation of the convenience function $_gdb_setting_str.  */
+
+static struct value *
+gdb_setting_str_internal_fn (struct gdbarch *gdbarch,
+			     const struct language_defn *language,
+			     void *cookie, int argc, struct value **argv)
+{
+  return str_value_from_setting (setting_cmd ("$_gdb_setting_str",
+					      showlist, argc, argv),
+				 gdbarch);
+}
+
+
+/* Implementation of the convenience function $_gdb_maint_setting_str.  */
+
+static struct value *
+gdb_maint_setting_str_internal_fn (struct gdbarch *gdbarch,
+				   const struct language_defn *language,
+				   void *cookie, int argc, struct value **argv)
+{
+  return str_value_from_setting (setting_cmd ("$_gdb_maint_setting_str",
+					      maintenance_show_cmdlist,
+					      argc, argv),
+				 gdbarch);
+}
+
 void
 _initialize_cli_cmds (void)
 {
@@ -2053,6 +2247,44 @@ 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_str", _("\
+$_gdb_setting_str - returns the value of a GDB setting as a string.\n\
+Usage: $_gdb_setting_str (setting)\n\
+\n\
+auto-boolean values are \"off\", \"on\", \"auto\".\n\
+boolean values are \"off\", \"on\".\n\
+Some integer settings accept an unlimited value, returned\n\
+as \"unlimited\"."),
+			 gdb_setting_str_internal_fn, NULL);
+
+  add_internal_function ("_gdb_setting", _("\
+$_gdb_setting - returns the value of a GDB setting.\n\
+Usage: $_gdb_setting (setting)\n\
+auto-boolean values are \"off\", \"on\", \"auto\".\n\
+boolean values are \"off\", \"on\".\n\
+Some integer settings accept an unlimited value, returned\n\
+as 0 or -1 depending on the setting."),
+			 gdb_setting_internal_fn, NULL);
+
+  add_internal_function ("_gdb_maint_setting_str", _("\
+$_gdb_maint_setting_str - returns the value of a GDB maintenance setting as a string.\n\
+Usage: $_gdb_maint_setting_str (setting)\n\
+\n\
+auto-boolean values are \"off\", \"on\", \"auto\".\n\
+boolean values are \"off\", \"on\".\n\
+Some integer settings accept an unlimited value, returned\n\
+as \"unlimited\"."),
+			 gdb_maint_setting_str_internal_fn, NULL);
+
+  add_internal_function ("_gdb_maint_setting", _("\
+$_gdb_maint_setting - returns the value of a GDB maintenance setting.\n\
+Usage: $_gdb_maint_setting (setting)\n\
+auto-boolean values are \"off\", \"on\", \"auto\".\n\
+boolean values are \"off\", \"on\".\n\
+Some integer settings accept an unlimited value, returned\n\
+as 0 or -1 depending on the setting."),
+			 gdb_maint_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 d8391597ac..4cf2437e2a 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -627,7 +627,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 /* See cli/cli-setshow.h.  */
 
 std::string
-get_setshow_command_value_string (cmd_list_element *c)
+get_setshow_command_value_string (const cmd_list_element *c)
 {
   string_file stb;
 
diff --git a/gdb/cli/cli-setshow.h b/gdb/cli/cli-setshow.h
index 8bfe7e89f0..dbb3e9fdff 100644
--- a/gdb/cli/cli-setshow.h
+++ b/gdb/cli/cli-setshow.h
@@ -58,7 +58,7 @@ extern void do_show_command (const char *arg, int from_tty,
 			     struct cmd_list_element *c);
 
 /* Get a string version of C's current value.  */
-extern std::string get_setshow_command_value_string (cmd_list_element *c);
+extern std::string get_setshow_command_value_string (const cmd_list_element *c);
 
 extern void cmd_show_list (struct cmd_list_element *list, int from_tty,
 			   const char *prefix);


             reply	other threads:[~2019-11-01  1:46 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-01  1:46 gdb-buildbot [this message]
2019-11-01  1:46 ` Failures on Ubuntu-Aarch64-m64, branch master gdb-buildbot
2019-11-01  2:18 ` Failures on Ubuntu-Aarch64-native-extended-gdbserver-m64, " gdb-buildbot
2019-11-01  2:46 ` Failures on Ubuntu-Aarch64-native-gdbserver-m64, " gdb-buildbot
2019-11-18 18:31 ` Failures on Fedora-i686, " gdb-buildbot
2019-11-18 18:56 ` Failures on Fedora-x86_64-cc-with-index, " gdb-buildbot
2019-11-18 19:19 ` Failures on Fedora-x86_64-m32, " gdb-buildbot
2019-11-18 19:42 ` Failures on Fedora-x86_64-m64, " gdb-buildbot
2019-11-18 20:13 ` Failures on Fedora-x86_64-native-extended-gdbserver-m32, " gdb-buildbot
2019-11-18 20:37 ` Failures on Fedora-x86_64-native-extended-gdbserver-m64, " gdb-buildbot
2019-11-18 20:59 ` Failures on Fedora-x86_64-native-gdbserver-m32, " gdb-buildbot
2019-11-18 21:06 ` *** COMPILATION FAILED *** Failures on Fedora-x86_64-w64-mingw32, branch master *** BREAKAGE *** gdb-buildbot
2019-11-18 21:26 ` Failures on Fedora-x86_64-native-gdbserver-m64, branch master gdb-buildbot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9ad9b77d64920d3113a9e7ab9f022eb5a45cd49e@gdb-build \
    --to=gdb-buildbot@sergiodj.net \
    --cc=gdb-testers@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).