Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Lancelot SIX via Gdb-patches <gdb-patches@sourceware.org>
To: gdb-patches@sourceware.org
Cc: Lancelot SIX <lsix@lancelotsix.com>
Subject: [PATCH v4 4/4] gdb: Setting setter return a bool to tell if the value changed
Date: Wed, 29 Sep 2021 22:50:11 +0100	[thread overview]
Message-ID: <20210929215011.1489639-5-lsix@lancelotsix.com> (raw)
In-Reply-To: <20210929215011.1489639-1-lsix@lancelotsix.com>

GDB can notify observers when a parameter is changed.

To do that, do_set_command (in gdb/cli/cli-setshow.c) compares the new
value against the old one before updating it, and based on that notifies
observers.  This looks like something like:

    int valuechanged = 0;
    switch (cmd->var.type ())
    {
    case var_integer:
      {
        LONGEST new_val = parse_and_eval_long (arg)
        if (new_val != cmd->var.get<int> ())
        {
          cmd->var.get<int> (new_val);
          value_changes = 1;
        }
      }
    case var_uinteger:
    case var_zuinteger:
      {
        unsigned int val
          = parse_cli_var_uinteger (c->var->type (), &arg, true);
        if (c->var->get<unsigned int> () != val)
          {
            c->var->set<unsigned int> (val);
            option_changed = true;
          }
      }
    case...
      /* And so on for all possible var_types.  */
    }

This comparison is done for each possible var_type, which leads to
unnecessary logic duplication.

In this patch I propose to move all those checks in one place within the
setting setter method.  This limits the code duplication and simplifies
the do_set_command implementation.

This patch also changes slightly the way a value change is detected.
Instead of comparing the user provided value against the current value
of the setting, we compare the value of the setting before and after the
set operation.  This is meant to handle edge cases where trying to set
an unrecognized value would be equivalent to a noop (the actual value
remains unchanged).  Doing this requires that the original value needs
to be copied before the update, which can be non trivial for
std::string.

There should be no user visible change introduced by this commit.

Tested on x86_64 GNU/Linux.

[1] https://review.lttng.org/c/binutils-gdb/+/5831/41

Change-Id: If064b9cede3eb56275aacd2b286f74eceb1aed11
---
 gdb/cli/cli-setshow.c | 83 +++++++------------------------------------
 gdb/command.h         |  6 +++-
 2 files changed, 18 insertions(+), 71 deletions(-)

diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c
index a027891de05..f06c92731e0 100644
--- a/gdb/cli/cli-setshow.c
+++ b/gdb/cli/cli-setshow.c
@@ -360,26 +360,12 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	*q++ = '\0';
 	newobj = (char *) xrealloc (newobj, q - newobj);
 
-	const std::string &cur_val = c->var->get<std::string> ();
-	if (strcmp (cur_val.c_str(),  newobj) != 0)
-	  {
-	    c->var->set<std::string> (std::string (newobj));
-
-	    option_changed = true;
-	  }
+	option_changed = c->var->set<std::string> (std::string (newobj));
 	xfree (newobj);
       }
       break;
     case var_string_noescape:
-      {
-	const std::string &cur_val = c->var->get<std::string> ();
-	if (strcmp (cur_val.c_str (), arg) != 0)
-	  {
-	    c->var->set<std::string> (std::string (arg));
-
-	    option_changed = true;
-	  }
-      }
+      option_changed = c->var->set<std::string> (std::string (arg));
       break;
     case var_filename:
       if (*arg == '\0')
@@ -405,13 +391,8 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	else
 	  val = xstrdup ("");
 
-	const std::string &cur_val = c->var->get<std::string> ();
-	if (strcmp (cur_val.c_str (), val) != 0)
-	  {
-	    c->var->set<std::string> (std::string (val));
-
-	    option_changed = true;
-	  }
+	option_changed
+	  = c->var->set<std::string> (std::string (val));
 	xfree (val);
       }
       break;
@@ -421,39 +402,18 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 
 	if (val < 0)
 	  error (_("\"on\" or \"off\" expected."));
-	if (val != c->var->get<bool> ())
-	  {
-	    c->var->set<bool> (val);
 
-	    option_changed = true;
-	  }
+	option_changed = c->var->set<bool> (val);
       }
       break;
     case var_auto_boolean:
-      {
-	enum auto_boolean val = parse_auto_binary_operation (arg);
-
-	if (c->var->get<enum auto_boolean> () != val)
-	  {
-	    c->var->set<enum auto_boolean> (val);
-
-	    option_changed = true;
-	  }
-      }
+      option_changed = c->var->set<enum auto_boolean> (parse_auto_binary_operation (arg));
       break;
     case var_uinteger:
     case var_zuinteger:
-      {
-	unsigned int val
-	  = parse_cli_var_uinteger (c->var->type (), &arg, true);
-
-	if (c->var->get<unsigned int> () != val)
-	  {
-	    c->var->set<unsigned int> (val);
-
-	    option_changed = true;
-	  }
-      }
+      option_changed
+	= c->var->set<unsigned int> (parse_cli_var_uinteger (c->var->type (),
+							     &arg, true));
       break;
     case var_integer:
     case var_zinteger:
@@ -483,12 +443,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 		 || (c->var->type () == var_zinteger && val > INT_MAX))
 	  error (_("integer %s out of range"), plongest (val));
 
-	if (c->var->get<int> () != val)
-	  {
-	    c->var->set<int> (val);
-
-	    option_changed = true;
-	  }
+	option_changed = c->var->set<int> (val);
       }
       break;
     case var_enum:
@@ -501,24 +456,12 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
 	if (*after != '\0')
 	  error (_("Junk after item \"%.*s\": %s"), len, arg, after);
 
-	if (c->var->get<const char *> () != match)
-	  {
-	    c->var->set<const char *> (match);
-
-	    option_changed = true;
-	  }
+	option_changed = c->var->set<const char *> (match);
       }
       break;
     case var_zuinteger_unlimited:
-      {
-	int val = parse_cli_var_zuinteger_unlimited (&arg, true);
-
-	if (c->var->get<int> () != val)
-	  {
-	    c->var->set<int> (val);
-	    option_changed = true;
-	  }
-      }
+      option_changed = c->var->set<int>
+	(parse_cli_var_zuinteger_unlimited (&arg, true));
       break;
     default:
       error (_("gdb internal error: bad var_type in do_setshow_command"));
diff --git a/gdb/command.h b/gdb/command.h
index 5ab25c74a9f..2d4561318bc 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -315,12 +315,14 @@ struct setting
 
      The var_type of the setting must match T.  */
   template<typename T>
-  void set (const T &v)
+  bool set (const T &v)
   {
     /* Check that the current instance is of one of the supported types for
        this instantiation.  */
     gdb_assert (var_type_uses<T> (m_var_type));
 
+    const T old_value = this->get<T> ();
+
     if (m_var == nullptr)
       {
 	gdb_assert (m_setter != nullptr);
@@ -329,6 +331,8 @@ struct setting
       }
     else
       *static_cast<T *> (m_var) = v;
+
+    return old_value != this->get<T> ();
   }
 
 private:
-- 
2.33.0


  parent reply	other threads:[~2021-09-29 21:52 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-29 21:50 [PATCH v4 0/4] Refactor cmd_list_element.var Lancelot SIX via Gdb-patches
2021-09-29 21:50 ` [PATCH v4 1/4] gdb: Introduce setting construct within cmd_list_element Lancelot SIX via Gdb-patches
2021-09-30 12:12   ` Simon Marchi via Gdb-patches
2021-09-30 12:30     ` Simon Marchi via Gdb-patches
2021-09-30 23:15       ` Lancelot SIX via Gdb-patches
2021-10-01  1:16         ` Simon Marchi via Gdb-patches
2021-09-30 12:39   ` Simon Marchi via Gdb-patches
2021-09-29 21:50 ` [PATCH v4 2/4] gdb: make string-like set show commands use std::string variable Lancelot SIX via Gdb-patches
2021-09-29 21:50 ` [PATCH v4 3/4] gdb: Have setter and getter callbacks for settings Lancelot SIX via Gdb-patches
2021-09-30 12:42   ` Simon Marchi via Gdb-patches
2021-10-05 19:10   ` Simon Marchi via Gdb-patches
2021-10-05 20:27     ` Lancelot SIX via Gdb-patches
2021-10-05 20:39       ` Simon Marchi via Gdb-patches
2021-10-05 22:21         ` Lancelot SIX via Gdb-patches
2021-09-29 21:50 ` Lancelot SIX via Gdb-patches [this message]
2021-09-30 12:43   ` [PATCH v4 4/4] gdb: Setting setter return a bool to tell if the value changed Simon Marchi via Gdb-patches
2021-09-30 12:44 ` [PATCH v4 0/4] Refactor cmd_list_element.var Simon Marchi via Gdb-patches
2021-10-03 19:22   ` Lancelot SIX via Gdb-patches

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=20210929215011.1489639-5-lsix@lancelotsix.com \
    --to=gdb-patches@sourceware.org \
    --cc=lsix@lancelotsix.com \
    /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