From patchwork Sun Apr 28 15:18:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philippe Waroquiers X-Patchwork-Id: 32440 Received: (qmail 20294 invoked by alias); 28 Apr 2019 15:18:32 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 20193 invoked by uid 89); 28 Apr 2019 15:18:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy=unlimited, Throws, showing, H*Ad:D*be X-HELO: mailsec108.isp.belgacom.be Received: from mailsec108.isp.belgacom.be (HELO mailsec108.isp.belgacom.be) (195.238.20.104) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 28 Apr 2019 15:18:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skynet.be; i=@skynet.be; q=dns/txt; s=securemail; t=1556464709; x=1588000709; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2ntgE2YfzJJZ3afKumVMiS3oSWMuuelvDTZdxcyyq5U=; b=07bw9LX0wRVxtW1vCfInUibtSyN3bQzYsy7adDi1LSa31omUCTCn5ex/ hLyN+bggqopz3ooftLCTEhvZa5RsbQ==; Received: from 59.151-129-109.adsl-dyn.isp.belgacom.be (HELO md.home) ([109.129.151.59]) by relay.skynet.be with ESMTP/TLS/DHE-RSA-AES128-GCM-SHA256; 28 Apr 2019 17:18:23 +0200 From: Philippe Waroquiers To: gdb-patches@sourceware.org Cc: Philippe Waroquiers Subject: [RFA 1/3] Implement convenience functions to examine GDB settings. Date: Sun, 28 Apr 2019 17:18:14 +0200 Message-Id: <20190428151816.31598-2-philippe.waroquiers@skynet.be> In-Reply-To: <20190428151816.31598-1-philippe.waroquiers@skynet.be> References: <20190428151816.31598-1-philippe.waroquiers@skynet.be> MIME-Version: 1.0 X-IsSubscribed: yes 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 | 71 +++++++++++++++------------- gdb/cli/cli-setshow.h | 5 ++ 4 files changed, 158 insertions(+), 33 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4f595922f6..4835c6fae5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -6023,3 +6023,13 @@ version-control: never coding: utf-8 End: +2019-04-28 Philippe Waroquiers + + * 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 5f3b973f06..b1498452ba 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -1664,6 +1664,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 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) { @@ -1787,6 +1881,17 @@ Generic command for showing things about the debugger."), /* Another way to get at the same thing. */ add_info ("set", show_command, _("Show all GDB settings.")); + 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 5b87f905d0..eac5d48ea3 100644 --- a/gdb/cli/cli-setshow.c +++ b/gdb/cli/cli-setshow.c @@ -551,55 +551,42 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) } } -/* 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. */ +/* See cli-setshow.h. */ void -do_show_command (const char *arg, int from_tty, struct cmd_list_element *c) +do_print_setting (string_file *stb, 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); - switch (c->var_type) { 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: internal_error (__FILE__, __LINE__, - _("do_show_command: " + _("do_print_setting: " "invalid var_auto_boolean")); break; } @@ -608,35 +595,53 @@ do_show_command (const char *arg, int from_tty, struct 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: - error (_("gdb internal error: bad var_type in do_show_command")); + error (_("gdb internal error: bad var_type in do_print_setting")); } +} + +/* 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); + do_print_setting (&stb, c); - /* FIXME: cagney/2005-02-10: Need to split this in half: code to - convert the value into a string (esentially the above); and - code to print the value out. For the latter there should be - MI and CLI specific versions. */ + /* FIXME: cagney/2005-02-10: For code to print the value out, + there should be MI and CLI specific versions. */ if (uiout->is_mi_like_p ()) uiout->field_stream ("value", stb); diff --git a/gdb/cli/cli-setshow.h b/gdb/cli/cli-setshow.h index e4d13c3510..27ef5ea387 100644 --- a/gdb/cli/cli-setshow.h +++ b/gdb/cli/cli-setshow.h @@ -31,4 +31,9 @@ extern void do_show_command (const char *arg, int from_tty, 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 */