diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index a39ea22604..ed699894f5 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\
+The unlimited value for integer, uinteger, zuinteger-unlimited\n\
+settings is represented 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\
+The unlimited value for integer, uinteger settings is 0.\n\
+The unlimited value for zuinteger-unlimited is -1."),
+			 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\
+The unlimited value for integer, uinteger, zuinteger-unlimited\n\
+settings is represented 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\
+The unlimited value for integer, uinteger settings is 0.\n\
+The unlimited value for zuinteger-unlimited is -1."),
+			 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);
-- 
2.20.1


From 51d8c0e284280513828eb86f6f3ec00c3569309d Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 28 Apr 2019 14:40:50 +0200
Subject: [PATCH 2/3] Test the convenience functions $_gdb_setting and
 $_gdb_int_setting.

gdb/testsuite/ChangeLog
2019-09-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/setshow.exp: Test $_gdb_setting and $_gdb_setting_str.
	* gdb.base/settings.exp: Test all settings types using
	$_gdb_maint_setting and $_gdb_maint_setting_str in proc_show_setting,
	that now verifies that the value of "maint show" is the same as
	returned by the settings functions.  Test the type of the
	maintenance settings.
	* gdb.base/default.exp: Update show_conv_list.
---
 gdb/testsuite/gdb.base/default.exp  |  4 ++
 gdb/testsuite/gdb.base/setshow.exp  | 74 ++++++++++++++++++++++-
 gdb/testsuite/gdb.base/settings.exp | 94 ++++++++++++++++++++++++++---
 3 files changed, 162 insertions(+), 10 deletions(-)

diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index cf009cdc77..82ed4be17c 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -604,6 +604,10 @@ set show_conv_list \
 	{$_cimag = <internal function _cimag>} \
 	{$_creal = <internal function _creal>} \
 	{$_isvoid = <internal function _isvoid>} \
+	{$_gdb_maint_setting_str = <internal function _gdb_maint_setting_str>} \
+	{$_gdb_maint_setting = <internal function _gdb_maint_setting>} \
+	{$_gdb_setting_str = <internal function _gdb_setting_str>} \
+	{$_gdb_setting = <internal function _gdb_setting>} \
 	{$_gdb_major = 9} \
 	{$_gdb_minor = 1} \
 	{$_shell_exitsignal = void} \
diff --git a/gdb/testsuite/gdb.base/setshow.exp b/gdb/testsuite/gdb.base/setshow.exp
index d807d75a66..5316b48509 100644
--- a/gdb/testsuite/gdb.base/setshow.exp
+++ b/gdb/testsuite/gdb.base/setshow.exp
@@ -84,6 +84,9 @@ gdb_test "show annotate" "Annotation_level is 0..*"  "show annotate (0)"
 #test annotation_level 0
 gdb_test "info line 1" "Line 1 of .* is at address .* but contains no code.*"  "annotation_level 0" 
 
+gdb_test "show args" "Argument list to give program being debugged when it is started is \"\"\."
+gdb_test "p \$_gdb_setting_str(\"args\")" " = \"\""
+
 gdb_test_no_output "set args ~"
 gdb_test "show args" "Argument list to give program being debugged when it is started is \"~\"..*" \
     "show args ~"
@@ -91,6 +94,9 @@ gdb_test "show args" "Argument list to give program being debugged when it is st
 gdb_test_no_output "set args foo bar blup baz bubble" "set args" 
 #test show args
 gdb_test "show args" "Argument list to give program being debugged when it is started is \"foo bar blup baz bubble\"..*" "show args"
+gdb_test "p \$_gdb_setting(\"args\")" " = \"foo bar blup baz bubble\"" \
+    "_gdb_setting args"
+
 
 # Don't test if we can't pass args or if we're using a stub.
 if { !$use_gdb_stub && ![target_info exists noargs] } {
@@ -100,32 +106,80 @@ if { !$use_gdb_stub && ![target_info exists noargs] } {
     gdb_test "run" "Starting program:.*foo bar blup baz bubble.*" "passing args"
 }
 #test set check range on
-gdb_test "set check range on" ".*" "set check range on" 
+# Note: the below might produce a warning, so match anything. 
+gdb_test "set check range on" ""
+
+gdb_test "p \$_gdb_setting(\"check range\")" " = \"on\"" \
+    "_gdb_setting check range on"
 #test show check range on
 gdb_test "show check range" "Range checking is \"on\"\..*" "show check range (on)" 
 #test set check range off with trailing space
 gdb_test_no_output "set check range off " "set check range off" 
 #test show check range off
 gdb_test "show check range" "Range checking is \"off\"\..*" "show check range (off)" 
+gdb_test "p \$_gdb_setting(\"check range\")" " = \"off\"" \
+    "_gdb_setting check range off"
 #test set check range auto
 gdb_test_no_output "set check range auto" "set check range auto" 
 #test show check range auto
 gdb_test "show check range" "Range checking is \"auto; currently .*" "show check range (auto)"
+gdb_test "p \$_gdb_setting(\"check range\")" " = \"auto\"" \
+    "_gdb_setting check range auto"
 
 # Test set check type on
-gdb_test "set check type on" ".*" "set check type on"
+gdb_test_no_output "set check type on"
 
 # Test show check type on
 gdb_test "show check type" "Strict type checking is on\..*" \
     "show check type (on)"
+gdb_test "p \$_gdb_setting_str(\"check type\")" " = \"on\"" \
+    "_gdb_setting_str check type on"
+gdb_test "p \$_gdb_setting(\"check type\")" " = 1" \
+    "_gdb_setting check type on 1"
 
 # Test set check type off with trailing space
 gdb_test_no_output "set check type off " "set check type off"
+gdb_test "p \$_gdb_setting_str(\"check type\")" " = \"off\"" \
+    "_gdb_setting_str check type off"
+gdb_test "p \$_gdb_setting(\"check type\")" " = 0" \
+    "_gdb_setting check type off 0"
 
 # Test show check type off
 gdb_test "show check type" "Strict type checking is off\..*" \
     "show check type (off)"
 
+#test set breakpoint pending
+
+#test set breakpoint pending on
+gdb_test_no_output "set breakpoint pending on"
+gdb_test "p \$_gdb_setting_str(\"breakpoint pending\")" " = \"on\"" \
+    "_gdb_setting_str breakpoint pending on"
+gdb_test "p \$_gdb_setting(\"breakpoint pending\")" " = 1" \
+    "_gdb_setting breakpoint pending 1"
+
+#test show breakpoint pending on
+gdb_test "show breakpoint pending" " is on\..*" "show breakpoint pending on"
+
+#test show breakpoint pending off
+gdb_test_no_output "set breakpoint pending off"
+gdb_test "show breakpoint pending" " is off\..*" "show breakpoint pending off"
+gdb_test "p \$_gdb_setting_str(\"breakpoint pending\")" " = \"off\"" \
+    "_gdb_setting_str breakpoint pending off"
+gdb_test "p \$_gdb_setting(\"breakpoint pending\")" " = 0" \
+    "_gdb_setting breakpoint pending 0"
+
+#test set breakpoint pending auto
+gdb_test_no_output "set breakpoint pending auto"
+
+#test show breakpoint pending auto
+gdb_test "show breakpoint pending" " is auto.*" "show breakpoint pending auto"
+gdb_test "p \$_gdb_setting_str(\"breakpoint pending\")" " = \"auto\"" \
+    "_gdb_setting_str breakpoint pending auto"
+gdb_test "p \$_gdb_setting(\"breakpoint pending\")" " = -1" \
+    "_gdb_setting breakpoint pending -1"
+
+
+
 #test set complaints 100
 gdb_test_no_output "set complaints 100" "set complaints 100" 
 #test show complaints 100
@@ -159,9 +213,17 @@ gdb_test "show environment FOOBARBAZ" "FOOBARBAZ = grbxgrbxgrbx.*"  "show enviro
 gdb_test_no_output "set height 100" "set height 100" 
 #test show height 100
 gdb_test "show height" "Number of lines gdb thinks are in a page is 100..*" "show height" 
+gdb_test "p \$_gdb_setting_str(\"height\")" " = \"100\"" \
+    "_gdb_setting_str height 100"
+gdb_test "p \$_gdb_setting(\"height\")" " = 100" \
+    "_gdb_setting height 100"
 # Back to infinite height to avoid pagers.  While at it, check that
 # literal "unlimited" works just as well as 0.
 gdb_test_no_output "set height unlimited"
+gdb_test "p \$_gdb_setting_str(\"height\")" " = \"unlimited\"" \
+    "_gdb_setting_str height unlimited"
+gdb_test "p \$_gdb_setting(\"height\")" " = 0" \
+    "_gdb_setting height unlimited"
 #test set history expansion on
 gdb_test_no_output "set history expansion on" "set history expansion on" 
 #test show history expansion on
@@ -182,6 +244,12 @@ gdb_test_no_output "set history filename ~/foobar.baz" \
 gdb_test "show history filename" \
     "The filename in which to record the command history is \"[string_to_regexp $HOME]/foobar.baz\"..*" \
     "show history filename (~/foobar.baz)"
+gdb_test "p \$_gdb_setting(\"history filename\")" \
+    " = \"[string_to_regexp $HOME]/foobar.baz\"..*" \
+    "_gdb_setting history filename"
+gdb_test "p \$_gdb_setting_str(\"history filename\")" \
+    " = \"[string_to_regexp $HOME]/foobar.baz\"..*" \
+    "_gdb_setting_str history filename"
 #get current working directory
 set PWD ""
 set test "show working directory"
@@ -209,7 +277,7 @@ gdb_test_no_output "set history size 100" "set history size 100"
 #test show history size 100
 gdb_test "show history size" "The size of the command history is 100..*" "show history size (100)" 
 #test set language asm
-gdb_test "set language asm" ".*" "set language asm" 
+gdb_test_no_output "set language asm"
 #test show language asm
 gdb_test "show language" "The current source language is \"asm\"..*" "show language (asm)" 
 #test set language rust, with a trailing space
diff --git a/gdb/testsuite/gdb.base/settings.exp b/gdb/testsuite/gdb.base/settings.exp
index 53049d6b59..3cb6e63efe 100644
--- a/gdb/testsuite/gdb.base/settings.exp
+++ b/gdb/testsuite/gdb.base/settings.exp
@@ -35,11 +35,80 @@ if { ![readline_is_used] } {
 }
 
 # Test the show command SHOW_CMD.  EXPECTED_RE is the expected output.
-# This procedure exists in order to make it easier to make the test
+# Also verifies that $_gdb_maint_setting_str produces an equivalent output,
+# matching it with EXPECTED_RE.  EXPECTED_RE double quotes are escaped
+# unless EXPECTED_RE_ESCAPED is true, indicating the quotes in EXPECTED_RE
+# are already escaped.
+# The value for the setting corresponding to SHOW_CMD is then reset
+# to RESET_VALUE, then set again to the value given by $_gdb_maint_setting_str
+# and $_gdb_maint_setting.  The default value of RESET_VALUE (0) should work for
+# most settings.  Note that we do not check that RESET_VALUE differs from
+# the expected value, as we assume different values will be verified.
+# The setting value must still be the one in force before calling show_setting.
+# In other words, this verifies that
+#   maint set test-settings <some_setting> $_gdb_maint_setting_str(<some_setting>)
+#   maint set test-settings <some_setting> $_gdb_maint_setting(<some_setting>)
+# do not change the setting value.
+# This procedure makes it easier to make the test
 # name/message unique, since we test the "show" commands many times.
 # EXPECTED_RE is made part of the test name.
-proc show_setting {show_cmd expected_re} {
-    gdb_test "$show_cmd" $expected_re "$show_cmd: $expected_re"
+proc show_setting {show_cmd expected_re {expected_re_escaped 0} {reset_value 0}} {
+    global gdb_prompt
+
+    with_test_prefix "$show_cmd $expected_re" {
+	gdb_test "$show_cmd" $expected_re "show"
+
+	# Remove the first two words (such as "maint show") to have the
+	# setting name to use for $_gdb_maint_setting_str.
+	regsub "\[^ \]+ +\[^ \]+ +\(.*\)" $show_cmd "\\1" maint_setting
+	if {$expected_re_escaped} {
+	    set escaped_expected_re $expected_re
+	} else {
+	    regsub -all "\"" $expected_re "\\\\\\\"" escaped_expected_re
+	}
+	set test "print \$_gdb_maint_setting_str"
+	set setting_str_value "xxxYYYxxx"
+	gdb_test_multiple "print \$_gdb_maint_setting_str(\"$maint_setting\")" $test {
+	    -re " = \"\($escaped_expected_re\)\".*$gdb_prompt $" {
+		set setting_str_value $expect_out(1,string)
+		regsub -all "\\\\" $expect_out(1,string) "" setting_str_value
+		pass $test
+	    }
+	}
+
+	# Change the setting value to RESET_VALUE, set it back to setting_str_value
+	# and check we still have the original value.
+	gdb_test_no_output "maintenance set $maint_setting $reset_value" "str reset $reset_value"
+	gdb_test_no_output "maintenance set $maint_setting $setting_str_value" "str set again"
+	gdb_test "$show_cmd" $expected_re "str show after reset+set again"
+
+	# Same test, but with value captured from $_gdb_maint_setting.
+	set test "print \$_gdb_maint_setting"
+	set setting_value "xxxYYYxxx"
+	gdb_test_multiple "print \$_gdb_maint_setting(\"$maint_setting\")" $test {
+	    -re " = \"\(.*\)\".*$gdb_prompt $" {
+		set setting_value $expect_out(1,string)
+		regsub -all "\\\\" $expect_out(1,string) "" setting_value
+		pass $test
+	    }
+	    -re " = \(.*\)\r\n$gdb_prompt $" {
+		set setting_value $expect_out(1,string)
+		pass $test
+	    }
+	}
+
+	gdb_test_no_output "maintenance set $maint_setting $reset_value" "reset $reset_value"
+	gdb_test_no_output "maintenance set $maint_setting $setting_value" "set again"
+	gdb_test "$show_cmd" $expected_re "show after reset+set again"
+    }
+}
+
+# Verifies that $_gdb_setting (SETTING) gives a value whose ptype matches EXPECTED.
+proc check_type {setting expected} {
+    with_test_prefix "check_type $setting $expected" {
+	gdb_test "print \$_gdb_maint_setting(\"$setting\")"
+	gdb_test "ptype $" "$expected"
+    }
 }
 
 # var_Xinteger tests.  VARIANT determines which command/variant to
@@ -68,16 +137,19 @@ proc test-integer {variant} {
 	# -1 means unlimited.  Other negative values are rejected.  -1
 	# -is tested further below, along the "unlimited" tests.
 	gdb_test "$set_cmd -2" "only -1 is allowed to set as unlimited"
+	check_type "test-settings $variant" "type = int"
     } elseif {$variant == "uinteger" || $variant == "zuinteger"} {
 	# Negative values are not accepted.
 	gdb_test "$set_cmd -1" "integer -1 out of range"
 	gdb_test "$set_cmd -2" "integer -2 out of range"
+	check_type "test-settings $variant" "type = unsigned int"
     } else {
 	# Negative values are not accepted.
 	gdb_test_no_output "$set_cmd -1"
 	show_setting "$show_cmd" "-1"
 	gdb_test_no_output "$set_cmd -2"
 	show_setting "$show_cmd" "-2"
+	check_type "test-settings $variant" "type = int"
     }
 
     # Regular integer is accepted.
@@ -234,6 +306,8 @@ proc_with_prefix test-boolean {} {
 	show_setting "$show_cmd" "on"
     }
 
+    check_type "test-settings boolean" "type = int"
+
     foreach_with_prefix value {
 	"of"
 	"off"
@@ -354,6 +428,8 @@ proc_with_prefix test-auto-boolean {} {
 	show_setting "$show_cmd" "auto"
     }
 
+    check_type "test-settings auto-boolean" "type = int"
+
     # "-" is not accepted as abbreviation of "-1".
     gdb_test "$set_cmd -" \
 	"\"on\", \"off\" or \"auto\" expected\\."
@@ -409,11 +485,13 @@ proc_with_prefix test-enum {} {
     # Various valid values.  Test both full value names and
     # abbreviations.
     gdb_test_no_output "$set_cmd x"
-    show_setting "$show_cmd" "xxx"
+    show_setting "$show_cmd" "xxx" 0 "zzz"
     gdb_test_no_output "$set_cmd yy"
-    show_setting "$show_cmd" "yyy"
+    show_setting "$show_cmd" "yyy" 0 "zzz"
     gdb_test_no_output "$set_cmd zzz"
-    show_setting "$show_cmd" "zzz"
+    show_setting "$show_cmd" "zzz" 0 "yyy"
+
+    check_type "test-settings enum" "type = char \\\[3\\\]"
 
     test_gdb_complete_multiple "$set_cmd " "" "" {
 	"xxx"
@@ -458,10 +536,12 @@ proc test-string {variant} {
     gdb_test_no_output "$set_cmd hello world"
     show_setting "$show_cmd" "hello world"
 
+    check_type "test-settings $variant" "type = char \\\[\[1-9\]\[0-9\]*\\\]"
+
     # A quoted string value.
     if {$variant == "string"} {
 	gdb_test_no_output "$set_cmd \"hello world\""
-	show_setting "$show_cmd" "\\\\\"hello world\\\\\""
+	show_setting "$show_cmd" "\\\\\"hello world\\\\\"" 1
     } else {
 	gdb_test_no_output "$set_cmd \"hello world\""
 	show_setting "$show_cmd" "\"hello world\""
-- 
2.20.1


From 7c6840123373fec635ce2fd00b9e2ec86a7d2fe9 Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 28 Apr 2019 14:44:44 +0200
Subject: [PATCH 3/3] NEWS and documentation for $_gdb_setting and
 $_gdb_int_setting.

gdb/ChangeLog
2019-09-07  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS: Mention $_gdb_setting, $_gdb_setting_str, $_gdb_maint_setting
	and $_gdb_maint_setting_str.

gdb/doc/ChangeLog
2019-09-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.texinfo (Convenience Funs): Document the new
	$_gdb_setting_str, $_gdb_maint_setting and $_gdb_maint_setting_str
	convenience functions.
---
 gdb/NEWS            |  6 ++++
 gdb/doc/gdb.texinfo | 80 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 25e67e43c8..a0d7ba9932 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -11,6 +11,12 @@
   scripts that should work error-free with many different versions,
   such as in system-wide init files.
 
+* New built-in convenience functions $_gdb_setting, $_gdb_setting_str,
+  $_gdb_maint_setting and $_gdb_maint_setting_str provide access to values
+  of the GDB settings and the GDB maintenance settings.  They are handy
+  for changing the logic of user defined commands depending on the
+  current GDB settings.
+
 * GDB now supports Thread Local Storage (TLS) variables on several
   FreeBSD architectures (amd64, i386, powerpc, riscv).  Other
   architectures require kernel changes.  TLS is not yet supported for
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 1208e4f615..cd1337ae85 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -11974,9 +11974,87 @@ $3 = void
 $4 = 1
 @end smallexample
 
+@item $_gdb_setting_str (@var{setting})
+@findex $_gdb_setting_str@r{, convenience function}
+Return the value of the @value{GDBN} @var{setting} as a string.
+@var{setting} is any setting that can be used in a @code{set} or
+@code{show} command (@pxref{Controlling GDB}).
+
+@smallexample
+(@value{GDBP}) show print frame-arguments
+Printing of non-scalar frame arguments is "scalars".
+(@value{GDBP}) p $_gdb_setting_str("print frame-arguments")
+$1 = "scalars"
+(@value{GDBP}) p $_gdb_setting_str("height")
+$2 = "30"
+(@value{GDBP})
+@end smallexample
+
+@item $_gdb_setting (@var{setting})
+@findex $_gdb_setting@r{, convenience function}
+Return the value of the @value{GDBN} @var{setting}.
+The type of the returned value depends on the setting.
+
+The value type for boolean and auto boolean settings is @code{int}.
+The boolean values @code{off} and @code{on} are converted to
+the integer values @code{0} and @code{1}.  The value @code{auto} is
+converted to the value @code{-1}.
+
+The value type for integer settings is either @code{unsigned int}
+or @code{int}, depending on the setting.
+
+Some integer settings accept an @code{unlimited} value.
+Depending on the setting, the @code{set} command also accepts
+the value @code{0} or the value @code{@minus{}1} as a synonym for
+@code{unlimited}.
+For example, @code{set height unlimited} is equivalent to
+@code{set height 0}.
+
+Some other settings that accept the @code{unlimited} value
+use the value @code{0} to literally mean zero.
+For example, @code{set history size 0} indicates to not
+record any @value{GDBN} commands in the command history.
+For such settings, @code{@minus{}1} is the synonym
+for @code{unlimited}.
+
+See the documentation of the corresponding @code{set} command for
+the numerical value equivalent to @code{unlimited}.
+
+The @code{$_gdb_setting} function converts the unlimited value
+to a @code{0} or a @code{@minus{}1} value according to what the
+@code{set} command uses.
+
+@smallexample
+@group
+(@value{GDBP}) p $_gdb_setting_str("height")
+$1 = "30"
+(@value{GDBP}) p $_gdb_setting("height")
+$2 = 30
+(@value{GDBP}) set height unlimited
+(@value{GDBP}) p $_gdb_setting_str("height")
+$3 = "unlimited"
+(@value{GDBP}) p $_gdb_setting("height")
+$4 = 0
+@end group
+@group
+(@value{GDBP}) p $_gdb_setting_str("history size")
+$5 = "unlimited"
+(@value{GDBP}) p $_gdb_setting("history size")
+$6 = -1
+(@value{GDBP}) p $_gdb_setting_str("disassemble-next-line")
+$7 = "auto"
+(@value{GDBP}) p $_gdb_setting("disassemble-next-line")
+$8 = -1
+(@value{GDBP})
+@end group
+@end smallexample
+
+Other setting types (enum, filename, optional filename, string, string noescape)
+are returned as string values.
+
 @end table
 
-These functions require @value{GDBN} to be configured with
+The following functions require @value{GDBN} to be configured with
 @code{Python} support.
 
 @table @code
