From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id +ABNHpovEGGAKgAAWB0awg (envelope-from ) for ; Sun, 08 Aug 2021 15:25:14 -0400 Received: by simark.ca (Postfix, from userid 112) id 78FA61EDF7; Sun, 8 Aug 2021 15:25:14 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 2CCBD1E79C for ; Sun, 8 Aug 2021 15:25:12 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D9F9E384F019 for ; Sun, 8 Aug 2021 19:25:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D9F9E384F019 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1628450711; bh=LjLnTLXfbM4/aSfXDXgYJCsn6+2X35Py+tc3soVflDw=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=a4bYiLPTYXsS1CSYsWYwq9HPdeardxcuMry9QL7BJOQ5BLqcaqBufaF7bKhZj98O+ SIdKpe3zeT0HlieBJeXlYmX8Xdwwr7GTzHv3XBkWyHc+k5nyFDgk+IDKcaZuae+CTt pSx/BJYhVKM1V+uR3MFzbhk9YGN4HXcNGpvukd1E= Received: from lndn.lancelotsix.com (vps-42846194.vps.ovh.net [IPv6:2001:41d0:801:2000::2400]) by sourceware.org (Postfix) with ESMTPS id E59E93848432 for ; Sun, 8 Aug 2021 19:23:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E59E93848432 Received: from Plymouth.lan (unknown [IPv6:2a02:390:9086:0:634a:c6a1:40ee:68b1]) by lndn.lancelotsix.com (Postfix) with ESMTPSA id 0415984197; Sun, 8 Aug 2021 19:23:28 +0000 (UTC) To: gdb-patches@sourceware.org Subject: [PATCH v2 3/4] gdb: Have setter and getter callbacks for settings Date: Sun, 8 Aug 2021 20:23:01 +0100 Message-Id: <20210808192302.3768766-4-lsix@lancelotsix.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210808192302.3768766-1-lsix@lancelotsix.com> References: <20210808192302.3768766-1-lsix@lancelotsix.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.5.11 (lndn.lancelotsix.com [0.0.0.0]); Sun, 08 Aug 2021 19:23:29 +0000 (UTC) X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Lancelot SIX via Gdb-patches Reply-To: Lancelot SIX Cc: Lancelot SIX Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" The main motivation behind this improvement is to help the implementation of a patch Simon Marchi is preparing to fix a bug when MI or Python try to access parameters that are inferior dependent (see PR/28085). This commit extends the previous one, which introduces the setting object to represent a static variable that can be set or shown with the appropriate commands. This patch proposes that a setting can either contain a pointer to a static variable holding a setting, or pointers to a pair of setter and getter callback functions. The callbacks functions can be used to generate values on the fly when the setting is accessed (or set the value in a context dependent way). This is useful when the source of truth is not contained in the variable pointed to by the setting instance. Given that the callback function call is hidden within the setting abstraction introduced earlier, none of the sites accessing the setting needs to be updated. The registered getter or setter is used whatever the way to access it is (through MI, Python, Guild, the "with" command and the $_gdb_setting / $_gdb_setting_str convenience functions). All the add_setshow_*_cmd are given a new overload that will accept the pair of function pointers (set / get functions) instead of the pointer to a global variable. Tested on GNU/Linux x86_64 with no regression observed. --- gdb/cli/cli-decode.c | 366 +++++++++++++++++++++++++++++++++++++++---- gdb/command.h | 324 +++++++++++++++++++++++++++++++++++++- 2 files changed, 650 insertions(+), 40 deletions(-) diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c index 865e1331c8f..3b08bda6493 100644 --- a/gdb/cli/cli-decode.c +++ b/gdb/cli/cli-decode.c @@ -460,6 +460,10 @@ empty_func (const char *args, int from_tty, cmd_list_element *c) CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are setting. VAR is address of the variable being controlled by this command. + SET_SETTING_FUNC is a pointer to an optional function callback used to set + the setting value. + GET_SETTING_FUNC is a pointer to an optional function callback used to get + the setting value. DOC is the documentation string. */ template @@ -469,6 +473,8 @@ add_set_or_show_cmd (const char *name, enum command_class theclass, var_types var_type, T *var, + setting_setter_ftype set_setting_func, + setting_getter_ftype get_setting_func, const char *doc, struct cmd_list_element **list) { @@ -476,7 +482,14 @@ add_set_or_show_cmd (const char *name, gdb_assert (type == set_cmd || type == show_cmd); c->type = type; - c->var.set_p (var_type, var); + + gdb_assert ((var != nullptr) + != (set_setting_func != nullptr && get_setting_func != nullptr)); + if (var != nullptr) + c->var.set_p (var_type, var); + else + c->var.set_accessors (var_type, set_setting_func, get_setting_func); + /* This needs to be something besides NULL so that this isn't treated as a help class. */ c->func = empty_func; @@ -486,9 +499,11 @@ add_set_or_show_cmd (const char *name, /* Add element named NAME to both the command SET_LIST and SHOW_LIST. CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are setting. VAR is address of the variable being controlled by this - command. SET_FUNC and SHOW_FUNC are the callback functions (if - non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation - strings. + command. If nullptr is given as VAR, then both SET_SETTING_FUNC and + GET_SETTING_FUNC must be provided. SET_SETTING_FUNC and GET_SETTING_FUNC are + callbacks used to access and modify the underlying property, whatever its + storage is. SET_FUNC and SHOW_FUNC are the callback functions (if non-NULL). + SET_DOC, SHOW_DOC and HELP_DOC are the documentation strings. Return the newly created set and show commands. */ @@ -499,6 +514,8 @@ add_setshow_cmd_full (const char *name, var_types var_type, T *var, const char *set_doc, const char *show_doc, const char *help_doc, + setting_setter_ftype set_setting_func, + setting_getter_ftype get_setting_func, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, @@ -520,6 +537,7 @@ add_setshow_cmd_full (const char *name, full_show_doc = xstrdup (show_doc); } set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, var, + set_setting_func, get_setting_func, full_set_doc, set_list); set->doc_allocated = 1; @@ -527,6 +545,7 @@ add_setshow_cmd_full (const char *name, set->func = set_func; show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, var, + set_setting_func, get_setting_func, full_show_doc, show_list); show->doc_allocated = 1; show->show_value_func = show_func; @@ -558,12 +577,36 @@ add_setshow_enum_cmd (const char *name, set_show_commands commands = add_setshow_cmd_full (name, theclass, var_enum, var, set_doc, show_doc, help_doc, - set_func, show_func, - set_list, show_list); + nullptr, nullptr, set_func, + show_func, set_list, show_list); commands.set->enums = enumlist; return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_enum_cmd (const char *name, command_class theclass, + const char *const *enumlist, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, var_enum, + nullptr, set_doc, show_doc, + help_doc, set_func, get_func, + nullptr, show_func, set_list, + show_list); + + cmds.set->enums = enumlist; + + return cmds; +} + /* See cli-decode.h. */ const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL }; @@ -584,17 +627,42 @@ add_setshow_auto_boolean_cmd (const char *name, struct cmd_list_element **show_list) { set_show_commands commands - = add_setshow_cmd_full (name, theclass, - var_auto_boolean,var, - set_doc, show_doc, help_doc, - set_func, show_func, - set_list, show_list); + = add_setshow_cmd_full (name, theclass, var_auto_boolean, + var, set_doc, show_doc, help_doc, + nullptr, nullptr, set_func, + show_func, set_list, show_list); commands.set->enums = auto_boolean_enums; return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_auto_boolean_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, + var_auto_boolean, + nullptr, set_doc, + show_doc, help_doc, + set_func, get_func, + nullptr, show_func, + set_list, show_list); + + cmds.set->enums = auto_boolean_enums; + + return cmds; +} + /* See cli-decode.h. */ const char * const boolean_enums[] = { "on", "off", NULL }; @@ -616,7 +684,7 @@ add_setshow_boolean_cmd (const char *name, enum command_class theclass, bool *va set_show_commands commands = add_setshow_cmd_full (name, theclass, var_boolean, var, set_doc, show_doc, help_doc, - set_func, show_func, + nullptr, nullptr, set_func, show_func, set_list, show_list); commands.set->enums = boolean_enums; @@ -624,6 +692,29 @@ add_setshow_boolean_cmd (const char *name, enum command_class theclass, bool *va return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_boolean_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, var_boolean, nullptr, + set_doc, show_doc, help_doc, + set_func, get_func, nullptr, + show_func, set_list, show_list); + + cmds.set->enums = boolean_enums; + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). */ @@ -640,14 +731,38 @@ add_setshow_filename_cmd (const char *name, enum command_class theclass, set_show_commands commands = add_setshow_cmd_full (name, theclass, var_filename, var, set_doc, show_doc, help_doc, - set_func, show_func, - set_list, show_list); + nullptr, nullptr, set_func, + show_func, set_list, show_list); set_cmd_completer (commands.set, filename_completer); return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_filename_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, var_filename, + nullptr, set_doc, show_doc, + help_doc, set_func, get_func, + nullptr, show_func, set_list, + show_list); + + set_cmd_completer (cmds.set, filename_completer); + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). */ @@ -663,9 +778,9 @@ add_setshow_string_cmd (const char *name, enum command_class theclass, { set_show_commands commands = add_setshow_cmd_full (name, theclass, var_string, var, - set_doc, show_doc, help_doc, - set_func, show_func, - set_list, show_list); + set_doc, show_doc, help_doc, + nullptr, nullptr, set_func, + show_func, set_list, show_list); /* Disable the default symbol completer. */ set_cmd_completer (commands.set, nullptr); @@ -673,6 +788,31 @@ add_setshow_string_cmd (const char *name, enum command_class theclass, return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_string_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, var_string, + nullptr, set_doc, show_doc, + help_doc, set_func, get_func, + nullptr, show_func, set_list, + show_list); + + /* Disable the default symbol completer. */ + set_cmd_completer (cmds.set, nullptr); + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). */ @@ -689,8 +829,8 @@ add_setshow_string_noescape_cmd (const char *name, enum command_class theclass, set_show_commands commands = add_setshow_cmd_full (name, theclass, var_string_noescape, var, set_doc, show_doc, help_doc, - set_func, show_func, set_list, - show_list); + nullptr, nullptr, set_func, show_func, + set_list, show_list); /* Disable the default symbol completer. */ set_cmd_completer (commands.set, nullptr); @@ -698,6 +838,32 @@ add_setshow_string_noescape_cmd (const char *name, enum command_class theclass, return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_string_noescape_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, + var_string_noescape, nullptr, + set_doc, show_doc, help_doc, + set_func, get_func, + nullptr, show_func, set_list, + show_list); + + /* Disable the default symbol completer. */ + set_cmd_completer (cmds.set, nullptr); + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). */ @@ -714,14 +880,38 @@ add_setshow_optional_filename_cmd (const char *name, enum command_class theclass set_show_commands commands = add_setshow_cmd_full (name, theclass, var_optional_filename, var, set_doc, show_doc, help_doc, - set_func, show_func, set_list, - show_list); - + nullptr, nullptr, set_func, show_func, + set_list, show_list); + set_cmd_completer (commands.set, filename_completer); return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_optional_filename_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = + add_setshow_cmd_full (name, theclass, var_optional_filename, + nullptr, set_doc, show_doc, help_doc, + set_func, get_func, nullptr, show_func, + set_list,show_list); + + set_cmd_completer (cmds.set, filename_completer); + + return cmds; +} + /* Completes on literal "unlimited". Used by integer commands that support a special "unlimited" value. */ @@ -756,15 +946,39 @@ add_setshow_integer_cmd (const char *name, enum command_class theclass, struct cmd_list_element **show_list) { set_show_commands commands - = add_setshow_cmd_full (name, theclass, var_integer, var, set_doc, - show_doc, help_doc, set_func, show_func, - set_list, show_list); + = add_setshow_cmd_full (name, theclass, var_integer, var, + set_doc, show_doc, help_doc, + nullptr, nullptr, set_func, + show_func, set_list, show_list); set_cmd_completer (commands.set, integer_unlimited_completer); return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_integer_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, var_integer, nullptr, + set_doc, show_doc, help_doc, set_func, + get_func, nullptr, show_func, set_list, + show_list); + + set_cmd_completer (cmds.set, integer_unlimited_completer); + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). CLASS is as in add_cmd. VAR is address of the variable which will contain the @@ -783,14 +997,38 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass, set_show_commands commands = add_setshow_cmd_full (name, theclass, var_uinteger, var, set_doc, show_doc, help_doc, - set_func, show_func, - set_list, show_list); + nullptr, nullptr, set_func, + show_func, set_list, show_list); set_cmd_completer (commands.set, integer_unlimited_completer); return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_uinteger_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds = add_setshow_cmd_full (name, theclass, var_uinteger, + nullptr, set_doc, show_doc, + help_doc, set_func, get_func, + nullptr, show_func, set_list, + show_list); + + set_cmd_completer (cmds.set, integer_unlimited_completer); + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). CLASS is as in add_cmd. VAR is address of the variable which will contain the @@ -808,8 +1046,27 @@ add_setshow_zinteger_cmd (const char *name, enum command_class theclass, { return add_setshow_cmd_full (name, theclass, var_zinteger, var, set_doc, show_doc, help_doc, - set_func, show_func, - set_list, show_list); + nullptr, nullptr, set_func, + show_func, set_list, show_list); +} + +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_zinteger_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + return add_setshow_cmd_full (name, theclass, var_zinteger, nullptr, + set_doc, show_doc, help_doc, set_func, + get_func, nullptr, show_func, set_list, + show_list); } set_show_commands @@ -826,14 +1083,39 @@ add_setshow_zuinteger_unlimited_cmd (const char *name, { set_show_commands commands = add_setshow_cmd_full (name, theclass, var_zuinteger_unlimited, var, - set_doc, show_doc, help_doc, set_func, - show_func, set_list, show_list); + set_doc, show_doc, help_doc, nullptr, + nullptr, set_func, show_func, set_list, + show_list); set_cmd_completer (commands.set, integer_unlimited_completer); return commands; } +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + auto cmds + = add_setshow_cmd_full (name, theclass, var_zuinteger_unlimited, + nullptr, set_doc, show_doc, help_doc, set_func, + get_func, nullptr, show_func, set_list, + show_list); + + set_cmd_completer (cmds.set, integer_unlimited_completer); + + return cmds; +} + /* Add element named NAME to both the set and show command LISTs (the list for set/show or some sublist thereof). CLASS is as in add_cmd. VAR is address of the variable which will contain the @@ -851,7 +1133,27 @@ add_setshow_zuinteger_cmd (const char *name, enum command_class theclass, { return add_setshow_cmd_full (name, theclass, var_zuinteger, var, set_doc, show_doc, help_doc, - set_func, show_func, set_list, + nullptr, nullptr, set_func, + show_func, set_list, show_list); +} + +/* Same as above but using a getter and a setter function instead of a pointer + to a global storage buffer. */ + +set_show_commands +add_setshow_zuinteger_cmd (const char *name, command_class theclass, + const char *set_doc, const char *show_doc, + const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, + cmd_list_element **set_list, + cmd_list_element **show_list) +{ + return add_setshow_cmd_full (name, theclass, var_zuinteger, + nullptr, set_doc, show_doc, + help_doc, set_func, get_func, + nullptr, show_func, set_list, show_list); } diff --git a/gdb/command.h b/gdb/command.h index 4e4583dcfa8..7b8fe5ea9f0 100644 --- a/gdb/command.h +++ b/gdb/command.h @@ -181,6 +181,194 @@ inline bool var_type_uses (var_types t) return t == var_enum; } +/* Function signature for a callback used to get a value from a setting. */ + +template +using setting_getter_ftype = T (*) (); + +/* Contains a function to access a parameter of a setting. */ + +union setting_getter +{ + setting_getter_ftype get_bool; + setting_getter_ftype get_int; + setting_getter_ftype get_uint; + setting_getter_ftype get_auto_boolean; + setting_getter_ftype get_string; + setting_getter_ftype get_const_string; +}; + + +/* Get the function from GETTERS that is appropriate for type T (const and non + const versions). */ + +template +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters); + +template +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters); + +/* Extract the setting_getter_ftype field from GETTERS. */ +template<> +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters) +{ return getters.get_bool; } + +template<> +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters) +{ return getters.get_bool; } + +/* Extract the setting_getter_ftype field from GETTERS. */ +template<> +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters) +{ return getters.get_int; } + +template<> +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters) +{ return getters.get_int; } + +/* Extract the setting_getter_ftype field from GETTERS. */ +template<> +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters) +{ return getters.get_uint; } + +template<> +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters) +{ return getters.get_uint; } + +/* Extract the setting_getter_ftype field from GETTERS. */ +template<> +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters) +{ return getters.get_auto_boolean; } + +template<> +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters) +{ return getters.get_auto_boolean; } + +/* Extract the setting_getter_ftype field from GETTERS. */ +template<> +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters) +{ return getters.get_string; } + +template<> +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters) +{ return getters.get_string; } + +/* Extract the setting_getter_ftype field from GETTERS. */ +template<> +inline const setting_getter_ftype & +get_setting_getter (const setting_getter &getters) +{ return getters.get_const_string; } + +template<> +inline setting_getter_ftype & +get_setting_getter (setting_getter &getters) +{ return getters.get_const_string; } + +/* Function signature for a callback used to set a value to a setting. */ + +template +using setting_setter_ftype = void (*) (T); + +/* Contains a function to set a value of a setting. */ +union setting_setter +{ + setting_setter_ftype set_bool; + setting_setter_ftype set_int; + setting_setter_ftype set_uint; + setting_setter_ftype set_auto_boolean; + setting_setter_ftype set_string; + setting_setter_ftype set_const_string; +}; + +/* Get the function from SETTERS that is appropriate for type T (const and non + const versions). */ + +template +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters); + +template +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters); + +/* Extract the setting_setter_ftype field from SETTERS. */ +template<> +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters) +{ return setters.set_bool; } + +template<> +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters) +{ return setters.set_bool; } + +/* Extract the setting_setter_ftype field from SETTERS. */ +template<> +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters) +{ return setters.set_int; } + +template<> +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters) +{ return setters.set_int; } + +/* Extract the setting_setter_ftype field from SETTERS. */ +template<> +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters) +{ return setters.set_uint; } + +template<> +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters) +{ return setters.set_uint; } + +/* Extract the setting_setter_ftype field from SETTERS. */ +template<> +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters) +{ return setters.set_auto_boolean; } + +template<> +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters) +{ return setters.set_auto_boolean; } + +/* Extract the setting_setter_ftype field from SETTERS. */ +template<> +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters) +{ return setters.set_string; } + +template<> +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters) +{ return setters.set_string; } + +/* Extract the setting_setter_ftype field from SETTERS. */ +template<> +inline const setting_setter_ftype & +get_setting_setter (const setting_setter &setters) +{ return setters.set_const_string; } + +template<> +inline setting_setter_ftype & +get_setting_setter (setting_setter &setters) +{ return setters.set_const_string; } + /* Abstraction that contains access to data that can be set or shown. The underlying data can be of any VAR_TYPES type. */ @@ -214,10 +402,18 @@ struct base_setting template T get () const { - return *get_p (); + gdb_assert (var_type_uses (this->m_var_type)); + auto getter = get_setting_getter (this->m_getter); + + if (getter != nullptr) + return (*getter) (); + else + return *get_p (); } - /* Sets the value V to the underlying buffer. + /* Sets the value referenced by the setting to V. If we have a user-provided + setter, use it to set the setting. Otherwise copy the value V to the + internally referenced buffer. The template parameter T indicates the type of the variable used to store the setting. @@ -231,25 +427,50 @@ struct base_setting gdb_assert (var_type_uses (this->m_var_type)); gdb_assert (!this->empty ()); - *static_cast (this->m_var) = v; + auto setter = get_setting_setter (this->m_setter); + + if (setter != nullptr) + (*setter) (v); + else + *static_cast (this->m_var) = v; + } + + /* Set the user provided setter and getter functions. */ + template + void + set_accessors (var_types var_type, + setting_setter_ftype setter, + setting_getter_ftype getter) + { + this->m_var_type = var_type; + get_setting_setter (this->m_setter) = setter; + get_setting_getter (this->m_getter) = getter; } /* A setting is valid (can be evaluated to true) if it contains a valid - reference to a memory buffer. */ - explicit operator bool () const + reference to a memory buffer, or if it has getter and setter callbacks + set. */ + explicit operator bool() const { - return !this->empty (); + return (m_getter.get_bool != nullptr && m_setter.set_bool != nullptr) + || !this->empty(); } protected: - /* The type of the variable M_VAR is pointing to. If M_VAR is nullptr, - M_VAR_TYPE is ignored. */ + /* The type of the variable M_VAR is pointing to. If M_VAR is nullptr or if + m_getter and m_setter are nullptr, M_VAR_TYPE is ignored. */ var_types m_var_type { var_boolean }; /* Pointer to the enclosed variable. The type of the variable is encoded in M_VAR_TYPE. Can be nullptr. */ void *m_var { nullptr }; + /* Pointer to a user provided getter. */ + union setting_getter m_getter { .get_bool = nullptr }; + + /* Pointer to a user provided setter. */ + union setting_setter m_setter { .set_bool = nullptr }; + /* Indicates if the current instance has a underlying buffer. */ bool empty () const { @@ -563,72 +784,159 @@ extern set_show_commands add_setshow_enum_cmd show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_enum_cmd + (const char *name, command_class theclass, const char *const *enumlist, + const char *set_doc, const char *show_doc, + const char *help_doc, setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_auto_boolean_cmd (const char *name, command_class theclass, auto_boolean *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_auto_boolean_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + extern set_show_commands add_setshow_boolean_cmd (const char *name, command_class theclass, bool *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_boolean_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_filename_cmd (const char *name, command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_filename_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_string_cmd (const char *name, command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_string_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + extern set_show_commands add_setshow_string_noescape_cmd (const char *name, command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_string_noescape_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_optional_filename_cmd (const char *name, command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_optional_filename_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + extern set_show_commands add_setshow_integer_cmd (const char *name, command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_integer_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_uinteger_cmd (const char *name, command_class theclass, unsigned int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_uinteger_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_zinteger_cmd (const char *name, command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_zinteger_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_zuinteger_cmd (const char *name, command_class theclass, unsigned int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_zuinteger_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, + setting_getter_ftype get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + extern set_show_commands add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, cmd_list_element **show_list); +extern set_show_commands add_setshow_zuinteger_unlimited_cmd + (const char *name, command_class theclass, const char *set_doc, + const char *show_doc, const char *help_doc, + setting_setter_ftype set_func, setting_getter_ftype get_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + /* Do a "show" command for each thing on a command list. */ extern void cmd_show_list (struct cmd_list_element *, int); -- 2.31.1