public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Sobisch <simonsobisch@web.de>
To: "Maciej W. Rozycki" <macro@embecosm.com>, gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>,
	Simon Marchi <simon.marchi@polymtl.ca>,
	Tom Tromey <tom@tromey.com>
Subject: Re: [PATCH v5 6/8] GDB: Allow arbitrary keywords in integer set commands
Date: Wed, 30 Mar 2022 12:42:17 +0200	[thread overview]
Message-ID: <31c7d89e-b786-02ef-6524-0f3bea04e994@web.de> (raw)
In-Reply-To: <alpine.DEB.2.20.2203301105350.11552@tpp.orcam.me.uk>


Am 30.03.2022 um 12:24 schrieb Maciej W. Rozycki:
> Rather than just `unlimited' allow the integer set commands (or command
> options) to define arbitrary keywords for the user to use, removing
> hardcoded arrangements for the `unlimited' keyword.
>
> Make obsolete the confusingly named `var_zinteger', `var_zuinteger' and
> `var_zuinteger_unlimited' `set'/`show' command variable types redefining
> them in terms of `var_uinteger', `var_integer' and `var_pinteger', which
> have the range of [0;UINT_MAX], [INT_MIN;INT_MAX], and [0;INT_MAX] each.

Those "confusingly named" parts go into python, too; maybe someone could
create a follow-up patch or adjust this one.
I think keeping them aligned is very useful (if renamed the old python
names should stay as aliases for the new ones, and ideally the doc
should reference a "until GDB 12: named ..." entry as this helps a lot
when creating python extensions).

 From the docs:

----------------------------------------------------------------

gdb.PARAM_ZINTEGER

     The value is an integer. This is like PARAM_INTEGER, except 0 is
interpreted as itself.
gdb.PARAM_ZUINTEGER

     The value is an unsigned integer. This is like PARAM_INTEGER,
except 0 is interpreted as itself, and the value cannot be negative.
gdb.PARAM_ZUINTEGER_UNLIMITED

     The value is a signed integer. This is like PARAM_ZUINTEGER, except
the special value -1 should be interpreted to mean “unlimited”. Other
negative values are not allowed.

----------------------------------------------------------------

Simon


>
> Following existing practice `var_pinteger' allows extra negative values
> to be used, however unlike `var_zuinteger_unlimited' any number of such
> values can be defined rather than just `-1'.
>
> The "p" in `var_pinteger' stands for "positive", for the lack of a more
> appropriate unambiguous letter, even though 0 obviously is not positive;
> "n" would be confusing as to whether it stands for "non-negative" or
> "negative".
>
> Add a new structure, `literal_def', the entries of which define extra
> keywords allowed for a command and numerical values they correspond to.
> Those values are not verified against the basic range supported by the
> underlying variable type, allowing extra values to be allowed outside
> that range, which may or may not be individually made visible to the
> user.  An optional value translation is possible with the structure to
> follow the existing practice for some commands where user-entered 0 is
> internally translated to UINT_MAX or INT_MAX.  Such translation can now
> be arbitrary.  Literals defined by this structure are automatically used
> for completion as necessary.
>
> So for example:
>
> const literal_def integer_unlimited_literals[] =
>    {
>      { "unlimited", 0, INT_MAX, true },
>      { nullptr }
>    };
>
> defines an extra `unlimited' keyword and a user-visible 0 value, both of
> which get translated to INT_MAX for the setting to be used with.
>
> Similarly:
>
> const literal_def zuinteger_unlimited_literals[] =
>    {
>      { "unlimited", -1, -1, true },
>      { nullptr }
>    };
>
> defines the same keyword and a corresponding user-visible -1 value that is
> used for the requested setting.  If the last member was set to `false'
> here, then only the keyword would be allowed for the user to enter and
> while -1 would still be used internally trying to enter it as a part of a
> command would result in an "integer -1 out of range" error.
>
> The obsolete command variable types still remain for Guile and Python
> use.  Eventually they need to be removed, however that would require a
> further rework of our Guile and Python support code.  Given that these
> variable types have been exported as keywords for those languages, those
> definitions have to stay, however it would be better to redefine them in
> terms of the modern variable types and overall export a better interface
> that reflects the flexibility of our core code now.
>
> There is no user-visible change from this rework, so no documentation or
> testsuite updates.
> ---
> Hi,
>
>   NB I have observed that the value of INT_MIN is not correctly handled:
> internally -2147483648 is interpreted as 2147483648 and consequently such
> a value is rejected, e.g:
>
> (gdb) show heuristic-fence-post
> The distance searched for the start of a function is 0.
> (gdb) set heuristic-fence-post -2147483647
> (gdb) show heuristic-fence-post
> The distance searched for the start of a function is -2147483647.
> (gdb) set heuristic-fence-post -2147483648
> integer 2147483648 out of range
> (gdb)
>
> umm... (not that it makes sense to set negative values for the heuristic
> fence post, but that's irrelevant here).  I haven't tried to track the
> root cause for this.
>
>    Maciej
>
> No change from v4.
>
> New change in v4.
> ---
>   gdb/cli/cli-cmds.c       |   56 ++++----
>   gdb/cli/cli-decode.c     |  302 ++++++++++++++++++++++++++++++++++++++---------
>   gdb/cli/cli-option.c     |  116 +++++++++++-------
>   gdb/cli/cli-option.h     |   34 +++--
>   gdb/cli/cli-setshow.c    |  249 ++++++++++++++++++--------------------
>   gdb/cli/cli-setshow.h    |   20 +--
>   gdb/command.h            |  108 ++++++++++++++--
>   gdb/guile/scm-param.c    |  102 +++++++++------
>   gdb/maint-test-options.c |    4
>   gdb/python/py-param.c    |   39 ++++--
>   gdb/python/python.c      |   49 +++----
>   gdb/valprint.c           |    9 -
>   12 files changed, 716 insertions(+), 372 deletions(-)
>
> gdb-setshow-cmd-extra-literals.diff
> Index: src/gdb/cli/cli-cmds.c
> ===================================================================
> --- src.orig/gdb/cli/cli-cmds.c
> +++ src/gdb/cli/cli-cmds.c
> @@ -2200,22 +2200,37 @@ value_from_setting (const setting &var,
>   {
>     switch (var.type ())
>       {
> +    case var_uinteger:
>       case var_integer:
> -      if (var.get<int> () == INT_MAX)
> -	return value_from_longest (builtin_type (gdbarch)->builtin_int,
> -				   0);
> -      else
> -	return value_from_longest (builtin_type (gdbarch)->builtin_int,
> -				   var.get<int> ());
> -    case var_zinteger:
> -      return value_from_longest (builtin_type (gdbarch)->builtin_int,
> -				 var.get<int> ());
> +    case var_pinteger:
> +      {
> +	LONGEST value
> +	  = (var.type () == var_uinteger
> +	     ? static_cast<LONGEST> (var.get<unsigned int> ())
> +	     : static_cast<LONGEST> (var.get<int> ()));
> +
> +	if (var.extra_literals () != nullptr)
> +	  for (const literal_def *l = var.extra_literals ();
> +	       l->literal != nullptr;
> +	       l++)
> +	    if (value == l->use)
> +	      {
> +		value = l->val;
> +		break;
> +	      }
> +
> +	if (var.type () == var_uinteger)
> +	  return
> +	    value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
> +				 static_cast<const unsigned int> (value));
> +	else
> +	  return
> +	    value_from_longest (builtin_type (gdbarch)->builtin_int,
> +				static_cast<const int> (value));
> +      }
>       case var_boolean:
>         return value_from_longest (builtin_type (gdbarch)->builtin_int,
>   				 var.get<bool> () ? 1 : 0);
> -    case var_zuinteger_unlimited:
> -      return value_from_longest (builtin_type (gdbarch)->builtin_int,
> -				 var.get<int> ());
>       case var_auto_boolean:
>         {
>   	int val;
> @@ -2237,17 +2252,6 @@ value_from_setting (const setting &var,
>   	return value_from_longest (builtin_type (gdbarch)->builtin_int,
>   				   val);
>         }
> -    case var_uinteger:
> -      if (var.get<unsigned int> () == UINT_MAX)
> -	return value_from_ulongest
> -	  (builtin_type (gdbarch)->builtin_unsigned_int, 0);
> -      else
> -	return value_from_ulongest
> -	  (builtin_type (gdbarch)->builtin_unsigned_int,
> -	   var.get<unsigned int> ());
> -    case var_zuinteger:
> -      return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
> -				  var.get<unsigned int> ());
>       case var_string:
>       case var_string_noescape:
>       case var_optional_filename:
> @@ -2317,13 +2321,11 @@ str_value_from_setting (const setting &v
>   {
>     switch (var.type ())
>       {
> +    case var_uinteger:
>       case var_integer:
> -    case var_zinteger:
> +    case var_pinteger:
>       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 (var);
>
> Index: src/gdb/cli/cli-decode.c
> ===================================================================
> --- src.orig/gdb/cli/cli-decode.c
> +++ src/gdb/cli/cli-decode.c
> @@ -580,11 +580,51 @@ add_setshow_cmd_full_erased (const char
>     return {set, show};
>   }
>
> +/* Completes on integer commands that support extra literals.  */
> +
> +static void
> +integer_literals_completer (struct cmd_list_element *c,
> +			    completion_tracker &tracker,
> +			    const char *text, const char *word)
> +{
> +  const literal_def *extra_literals = c->var->extra_literals ();
> +
> +  if (*text == '\0')
> +    {
> +      tracker.add_completion (make_unique_xstrdup ("NUMBER"));
> +      for (const literal_def *l = extra_literals;
> +	   l->literal != nullptr;
> +	   l++)
> +	tracker.add_completion (make_unique_xstrdup (l->literal));
> +    }
> +  else
> +    for (const literal_def *l = extra_literals;
> +	 l->literal != nullptr;
> +	 l++)
> +      if (startswith (l->literal, text))
> +	tracker.add_completion (make_unique_xstrdup (l->literal));
> +}
> +
> +/* Add element named NAME to both the command SET_LIST and SHOW_LIST.
> +   THECLASS 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.  EXTRA_LITERALS if non-NULL define extra literals to be
> +   accepted in lieu of a number for integer variables.  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.  */
> +
>   template<typename T>
>   static set_show_commands
>   add_setshow_cmd_full (const char *name,
>   		      enum command_class theclass,
>   		      var_types var_type, T *var,
> +		      const literal_def *extra_literals,
>   		      const char *set_doc, const char *show_doc,
>   		      const char *help_doc,
>   		      typename setting_func_types<T>::set set_setting_func,
> @@ -595,18 +635,44 @@ add_setshow_cmd_full (const char *name,
>   		      struct cmd_list_element **show_list)
>   {
>     auto erased_args
> -    = setting::erase_args (var_type, var,
> +    = setting::erase_args (var_type, var, extra_literals,
>   			   set_setting_func, get_setting_func);
> +  auto cmds = add_setshow_cmd_full_erased (name,
> +					   theclass,
> +					   var_type, erased_args,
> +					   set_doc, show_doc,
> +					   help_doc,
> +					   set_func,
> +					   show_func,
> +					   set_list,
> +					   show_list);
>
> -  return add_setshow_cmd_full_erased (name,
> -				      theclass,
> -				      var_type, erased_args,
> -				      set_doc, show_doc,
> -				      help_doc,
> -				      set_func,
> -				      show_func,
> -				      set_list,
> -				      show_list);
> +  if (extra_literals != nullptr)
> +    set_cmd_completer (cmds.set, integer_literals_completer);
> +
> +  return cmds;
> +}
> +
> +/* Same as above but omitting EXTRA_LITERALS.  */
> +
> +template<typename T>
> +static set_show_commands
> +add_setshow_cmd_full (const char *name,
> +		      enum command_class theclass,
> +		      var_types var_type, T *var,
> +		      const char *set_doc, const char *show_doc,
> +		      const char *help_doc,
> +		      typename setting_func_types<T>::set set_setting_func,
> +		      typename setting_func_types<T>::get get_setting_func,
> +		      cmd_func_ftype *set_func,
> +		      show_value_ftype *show_func,
> +		      struct cmd_list_element **set_list,
> +		      struct cmd_list_element **show_list)
> +{
> +  return add_setshow_cmd_full (name, theclass, var_type, var, nullptr,
> +			       set_doc, show_doc, help_doc,
> +			       set_setting_func, get_setting_func,
> +			       set_func, show_func, set_list, show_list);
>   }
>
>   /* Add element named NAME to command list LIST (the list for set or
> @@ -975,25 +1041,6 @@ add_setshow_optional_filename_cmd (const
>     return cmds;
>   }
>
> -/* Completes on literal "unlimited".  Used by integer commands that
> -   support a special "unlimited" value.  */
> -
> -static void
> -integer_unlimited_completer (struct cmd_list_element *ignore,
> -			     completion_tracker &tracker,
> -			     const char *text, const char *word)
> -{
> -  static const char * const keywords[] =
> -    {
> -      "unlimited",
> -      NULL,
> -    };
> -
> -  if (*text == '\0')
> -    tracker.add_completion (make_unique_xstrdup ("NUMBER"));
> -  complete_on_enum (tracker, keywords, text, word);
> -}
> -
>   /* 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
> @@ -1002,6 +1049,55 @@ integer_unlimited_completer (struct cmd_
>
>   set_show_commands
>   add_setshow_integer_cmd (const char *name, enum command_class theclass,
> +			 int *var, const literal_def *extra_literals,
> +			 const char *set_doc, const char *show_doc,
> +			 const char *help_doc,
> +			 cmd_func_ftype *set_func,
> +			 show_value_ftype *show_func,
> +			 struct cmd_list_element **set_list,
> +			 struct cmd_list_element **show_list)
> +{
> +  set_show_commands commands
> +    = add_setshow_cmd_full<int> (name, theclass, var_integer, var,
> +				 extra_literals, set_doc, show_doc,
> +				 help_doc, nullptr, nullptr, set_func,
> +				 show_func, set_list, show_list);
> +  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 literal_def *extra_literals,
> +			 const char *set_doc, const char *show_doc,
> +			 const char *help_doc,
> +			 setting_func_types<int>::set set_func,
> +			 setting_func_types<int>::get get_func,
> +			 show_value_ftype *show_func,
> +			 cmd_list_element **set_list,
> +			 cmd_list_element **show_list)
> +{
> +  auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
> +					 extra_literals, set_doc, show_doc,
> +					 help_doc, set_func, get_func, nullptr,
> +					 show_func, set_list, show_list);
> +  return cmds;
> +}
> +
> +/* Accept `unlimited' or 0, translated internally to INT_MAX.  */
> +const literal_def integer_unlimited_literals[] =
> +  {
> +    { "unlimited", 0, INT_MAX, true },
> +    { nullptr }
> +  };
> +
> +/* Same as above but using `integer_unlimited_literals', with a pointer
> +   to a global storage buffer.  */
> +
> +set_show_commands
> +add_setshow_integer_cmd (const char *name, enum command_class theclass,
>   			 int *var,
>   			 const char *set_doc, const char *show_doc,
>   			 const char *help_doc,
> @@ -1012,12 +1108,10 @@ add_setshow_integer_cmd (const char *nam
>   {
>     set_show_commands commands
>       = add_setshow_cmd_full<int> (name, theclass, var_integer, var,
> +				 integer_unlimited_literals,
>   				 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;
>   }
>
> @@ -1035,12 +1129,54 @@ add_setshow_integer_cmd (const char *nam
>   			 cmd_list_element **show_list)
>   {
>     auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
> +					 integer_unlimited_literals,
>   					 set_doc, show_doc, help_doc, set_func,
>   					 get_func, nullptr, show_func, set_list,
>   					 show_list);
> +  return cmds;
> +}
>
> -  set_cmd_completer (cmds.set, integer_unlimited_completer);
> +/* 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
> +   value.  SET_DOC and SHOW_DOC are the documentation strings.  */
> +
> +set_show_commands
> +add_setshow_pinteger_cmd (const char *name, enum command_class theclass,
> +			  int *var, const literal_def *extra_literals,
> +			  const char *set_doc, const char *show_doc,
> +			  const char *help_doc,
> +			  cmd_func_ftype *set_func,
> +			  show_value_ftype *show_func,
> +			  struct cmd_list_element **set_list,
> +			  struct cmd_list_element **show_list)
> +{
> +  set_show_commands commands
> +    = add_setshow_cmd_full<int> (name, theclass, var_pinteger, var,
> +				 extra_literals, set_doc, show_doc,
> +				 help_doc, nullptr, nullptr, set_func,
> +				 show_func, set_list, show_list);
> +  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_pinteger_cmd (const char *name, command_class theclass,
> +			  const literal_def *extra_literals,
> +			  const char *set_doc, const char *show_doc,
> +			  const char *help_doc,
> +			  setting_func_types<int>::set set_func,
> +			  setting_func_types<int>::get get_func,
> +			  show_value_ftype *show_func,
> +			  cmd_list_element **set_list,
> +			  cmd_list_element **show_list)
> +{
> +  auto cmds = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr,
> +					 extra_literals, set_doc, show_doc,
> +					 help_doc, set_func, get_func, nullptr,
> +					 show_func, set_list, show_list);
>     return cmds;
>   }
>
> @@ -1051,7 +1187,7 @@ add_setshow_integer_cmd (const char *nam
>
>   set_show_commands
>   add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
> -			  unsigned int *var,
> +			  unsigned int *var, const literal_def *extra_literals,
>   			  const char *set_doc, const char *show_doc,
>   			  const char *help_doc,
>   			  cmd_func_ftype *set_func,
> @@ -1061,12 +1197,9 @@ add_setshow_uinteger_cmd (const char *na
>   {
>     set_show_commands commands
>       = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
> -					  set_doc, show_doc, help_doc,
> -					  nullptr, nullptr, set_func,
> +					  extra_literals, 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;
>   }
>
> @@ -1075,6 +1208,7 @@ add_setshow_uinteger_cmd (const char *na
>
>   set_show_commands
>   add_setshow_uinteger_cmd (const char *name, command_class theclass,
> +			  const literal_def *extra_literals,
>   			  const char *set_doc, const char *show_doc,
>   			  const char *help_doc,
>   			  setting_func_types<unsigned int>::set set_func,
> @@ -1084,13 +1218,63 @@ add_setshow_uinteger_cmd (const char *na
>   			  cmd_list_element **show_list)
>   {
>     auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
> -						  nullptr, set_doc, show_doc,
> -						  help_doc, set_func, get_func,
> -						  nullptr, show_func, set_list,
> +						  nullptr, extra_literals,
> +						  set_doc, show_doc, help_doc,
> +						  set_func, get_func, nullptr,
> +						  show_func, set_list,
>   						  show_list);
> +  return cmds;
> +}
>
> -  set_cmd_completer (cmds.set, integer_unlimited_completer);
> +/* Accept `unlimited' or 0, translated internally to UINT_MAX.  */
> +const literal_def uinteger_unlimited_literals[] =
> +  {
> +    { "unlimited", 0, UINT_MAX, true },
> +    { nullptr }
> +  };
> +
> +/* Same as above but using `uinteger_unlimited_literals', with a pointer
> +   to a global storage buffer.  */
> +
> +set_show_commands
> +add_setshow_uinteger_cmd (const char *name, enum 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,
> +			  struct cmd_list_element **set_list,
> +			  struct cmd_list_element **show_list)
> +{
> +  set_show_commands commands
> +    = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
> +					  uinteger_unlimited_literals,
> +					  set_doc, show_doc, help_doc, nullptr,
> +					  nullptr, set_func, show_func,
> +					  set_list, show_list);
> +  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_func_types<unsigned int>::set set_func,
> +			  setting_func_types<unsigned int>::get get_func,
> +			  show_value_ftype *show_func,
> +			  cmd_list_element **set_list,
> +			  cmd_list_element **show_list)
> +{
> +  auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
> +						  nullptr,
> +						  uinteger_unlimited_literals,
> +						  set_doc, show_doc, help_doc,
> +						  set_func, get_func, nullptr,
> +						  show_func, set_list,
> +						  show_list);
>     return cmds;
>   }
>
> @@ -1109,7 +1293,7 @@ add_setshow_zinteger_cmd (const char *na
>   			  struct cmd_list_element **set_list,
>   			  struct cmd_list_element **show_list)
>   {
> -  return add_setshow_cmd_full<int> (name, theclass, var_zinteger, var,
> +  return add_setshow_cmd_full<int> (name, theclass, var_integer, var,
>   				    set_doc, show_doc, help_doc,
>   				    nullptr, nullptr, set_func,
>   				    show_func, set_list, show_list);
> @@ -1128,12 +1312,22 @@ add_setshow_zinteger_cmd (const char *na
>   			  cmd_list_element **set_list,
>   			  cmd_list_element **show_list)
>   {
> -  return add_setshow_cmd_full<int> (name, theclass, var_zinteger, nullptr,
> +  return add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
>   				    set_doc, show_doc, help_doc, set_func,
>   				    get_func, nullptr, show_func, set_list,
>   				    show_list);
>   }
>
> +/* Accept `unlimited' or -1, using -1 internally.  */
> +const literal_def zuinteger_unlimited_literals[] =
> +  {
> +    { "unlimited", -1, -1, true },
> +    { nullptr }
> +  };
> +
> +/* Same as above but using `zuinteger_unlimited_literals', with a pointer
> +   to a global storage buffer.  */
> +
>   set_show_commands
>   add_setshow_zuinteger_unlimited_cmd (const char *name,
>   				     enum command_class theclass,
> @@ -1147,13 +1341,11 @@ add_setshow_zuinteger_unlimited_cmd (con
>   				     struct cmd_list_element **show_list)
>   {
>     set_show_commands commands
> -    = add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited, var,
> +    = add_setshow_cmd_full<int> (name, theclass, var_pinteger, var,
> +				 zuinteger_unlimited_literals,
>   				 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;
>   }
>
> @@ -1171,13 +1363,11 @@ add_setshow_zuinteger_unlimited_cmd (con
>   				     cmd_list_element **show_list)
>   {
>     auto cmds
> -    = add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited,
> -				 nullptr, set_doc, show_doc, help_doc, set_func,
> +    = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr,
> +				 zuinteger_unlimited_literals,
> +				 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;
>   }
>
> @@ -1196,7 +1386,7 @@ add_setshow_zuinteger_cmd (const char *n
>   			   struct cmd_list_element **set_list,
>   			   struct cmd_list_element **show_list)
>   {
> -  return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
> +  return add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
>   					     var, set_doc, show_doc, help_doc,
>   					     nullptr, nullptr, set_func,
>   					     show_func, set_list, show_list);
> @@ -1215,7 +1405,7 @@ add_setshow_zuinteger_cmd (const char *n
>   			   cmd_list_element **set_list,
>   			   cmd_list_element **show_list)
>   {
> -  return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
> +  return add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
>   					     nullptr, set_doc, show_doc,
>   					     help_doc, set_func, get_func,
>   					     nullptr, show_func, set_list,
> Index: src/gdb/cli/cli-option.c
> ===================================================================
> --- src.orig/gdb/cli/cli-option.c
> +++ src/gdb/cli/cli-option.c
> @@ -38,7 +38,7 @@ union option_value
>     /* For var_uinteger options.  */
>     unsigned int uinteger;
>
> -  /* For var_zuinteger_unlimited options.  */
> +  /* For var_integer and var_pinteger options.  */
>     int integer;
>
>     /* For var_enum options.  */
> @@ -356,42 +356,55 @@ parse_option (gdb::array_view<const opti
>   	return option_def_and_value {*match, match_ctx, val};
>         }
>       case var_uinteger:
> -    case var_zuinteger_unlimited:
> +    case var_integer:
> +    case var_pinteger:
>         {
>   	if (completion != nullptr)
>   	  {
> -	    if (**args == '\0')
> -	      {
> -		/* Convenience to let the user know what the option
> -		   can accept.  Note there's no common prefix between
> -		   the strings on purpose, so that readline doesn't do
> -		   a partial match.  */
> -		completion->tracker.add_completion
> -		  (make_unique_xstrdup ("NUMBER"));
> -		completion->tracker.add_completion
> -		  (make_unique_xstrdup ("unlimited"));
> -		return {};
> -	      }
> -	    else if (startswith ("unlimited", *args))
> +	    if (match->extra_literals != nullptr)
>   	      {
> -		completion->tracker.add_completion
> -		  (make_unique_xstrdup ("unlimited"));
> -		return {};
> +		/* Convenience to let the user know what the option can
> +		   accept.  Make sure there's no common prefix between
> +		   "NUMBER" and all the strings when adding new ones,
> +		   so that readline doesn't do a partial match.  */
> +		if (**args == '\0')
> +		  {
> +		    completion->tracker.add_completion
> +		      (make_unique_xstrdup ("NUMBER"));
> +		    for (const literal_def *l = match->extra_literals;
> +			 l->literal != nullptr;
> +			 l++)
> +		      completion->tracker.add_completion
> +			(make_unique_xstrdup (l->literal));
> +		    return {};
> +		  }
> +		else
> +		  {
> +		    bool completions = false;
> +		    for (const literal_def *l = match->extra_literals;
> +			 l->literal != nullptr;
> +			 l++)
> +		      if (startswith (l->literal, *args))
> +			{
> +			  completion->tracker.add_completion
> +			    (make_unique_xstrdup (l->literal));
> +			  completions = true;
> +			}
> +		    if (completions)
> +		      return {};
> +		  }
>   	      }
>   	  }
>
> -	if (match->type == var_zuinteger_unlimited)
> -	  {
> -	    option_value val;
> -	    val.integer = parse_cli_var_zuinteger_unlimited (args, false);
> -	    return option_def_and_value {*match, match_ctx, val};
> -	  }
> +	LONGEST v = parse_cli_var_integer (match->type,
> +					   match->extra_literals,
> +					   args, false);
> +	option_value val;
> +	if (match->type == var_uinteger)
> +	  val.uinteger = v;
>   	else
> -	  {
> -	    option_value val;
> -	    val.uinteger = parse_cli_var_uinteger (match->type, args, false);
> -	    return option_def_and_value {*match, match_ctx, val};
> -	  }
> +	  val.integer = v;
> +	return option_def_and_value {*match, match_ctx, val};
>         }
>       case var_enum:
>         {
> @@ -593,7 +606,7 @@ save_option_value_in_ctx (gdb::optional<
>         *ov->option.var_address.uinteger (ov->option, ov->ctx)
>   	= ov->value->uinteger;
>         break;
> -    case var_zuinteger_unlimited:
> +    case var_integer:
>         *ov->option.var_address.integer (ov->option, ov->ctx)
>   	= ov->value->integer;
>         break;
> @@ -664,8 +677,20 @@ get_val_type_str (const option_def &opt,
>       case var_boolean:
>         return "[on|off]";
>       case var_uinteger:
> -    case var_zuinteger_unlimited:
> -      return "NUMBER|unlimited";
> +    case var_integer:
> +    case var_pinteger:
> +      {
> +	buffer = "NUMBER";
> +	if (opt.extra_literals != nullptr)
> +	  for (const literal_def *l = opt.extra_literals;
> +	       l->literal != nullptr;
> +	       l++)
> +	    {
> +	      buffer += '|';
> +	      buffer += l->literal;
> +	    }
> +	return buffer.c_str ();
> +      }
>       case var_enum:
>         {
>   	buffer = "";
> @@ -789,20 +814,31 @@ add_setshow_cmds_for_options (command_cl
>   	{
>   	  add_setshow_uinteger_cmd (option.name, cmd_class,
>   				    option.var_address.uinteger (option, data),
> +				    option.extra_literals,
>   				    option.set_doc, option.show_doc,
>   				    option.help_doc,
>   				    nullptr, option.show_cmd_cb,
>   				    set_list, show_list);
>   	}
> -      else if (option.type == var_zuinteger_unlimited)
> +      else if (option.type == var_integer)
>   	{
> -	  add_setshow_zuinteger_unlimited_cmd
> -	    (option.name, cmd_class,
> -	     option.var_address.integer (option, data),
> -	     option.set_doc, option.show_doc,
> -	     option.help_doc,
> -	     nullptr, option.show_cmd_cb,
> -	     set_list, show_list);
> +	  add_setshow_integer_cmd (option.name, cmd_class,
> +				   option.var_address.integer (option, data),
> +				   option.extra_literals,
> +				   option.set_doc, option.show_doc,
> +				   option.help_doc,
> +				   nullptr, option.show_cmd_cb,
> +				   set_list, show_list);
> +	}
> +      else if (option.type == var_pinteger)
> +	{
> +	  add_setshow_pinteger_cmd (option.name, cmd_class,
> +				    option.var_address.integer (option, data),
> +				    option.extra_literals,
> +				    option.set_doc, option.show_doc,
> +				    option.help_doc,
> +				    nullptr, option.show_cmd_cb,
> +				    set_list, show_list);
>   	}
>         else if (option.type == var_enum)
>   	{
> Index: src/gdb/cli/cli-option.h
> ===================================================================
> --- src.orig/gdb/cli/cli-option.h
> +++ src/gdb/cli/cli-option.h
> @@ -49,12 +49,13 @@ struct option_def
>        used to create the option's "set/show" commands.  */
>     constexpr option_def (const char *name_,
>   			var_types var_type_,
> +			const literal_def *extra_literals_,
>   			erased_get_var_address_ftype *erased_get_var_address_,
>   			show_value_ftype *show_cmd_cb_,
>   			const char *set_doc_,
>   			const char *show_doc_,
>   			const char *help_doc_)
> -    : name (name_), type (var_type_),
> +    : name (name_), type (var_type_), extra_literals (extra_literals_),
>         erased_get_var_address (erased_get_var_address_),
>         var_address {},
>         show_cmd_cb (show_cmd_cb_),
> @@ -68,6 +69,9 @@ struct option_def
>     /* The option's type.  */
>     var_types type;
>
> +  /* Extra literals, such as `unlimited', accepted in lieu of a number.  */
> +  const literal_def *extra_literals;
> +
>     /* A function that gets the controlling variable's address, type
>        erased.  */
>     erased_get_var_address_ftype *erased_get_var_address;
> @@ -160,7 +164,7 @@ struct boolean_option_def : option_def
>   		      const char *set_doc_,
>   		      const char *show_doc_ = nullptr,
>   		      const char *help_doc_ = nullptr)
> -    : option_def (long_option_, var_boolean,
> +    : option_def (long_option_, var_boolean, nullptr,
>   		  (erased_get_var_address_ftype *) get_var_address_cb_,
>   		  show_cmd_cb_,
>   		  set_doc_, show_doc_, help_doc_)
> @@ -207,11 +211,12 @@ struct uinteger_option_def : option_def
>   {
>     uinteger_option_def (const char *long_option_,
>   		       unsigned int *(*get_var_address_cb_) (Context *),
> +		       const literal_def *extra_literals_,
>   		       show_value_ftype *show_cmd_cb_,
>   		       const char *set_doc_,
>   		       const char *show_doc_ = nullptr,
>   		       const char *help_doc_ = nullptr)
> -    : option_def (long_option_, var_uinteger,
> +    : option_def (long_option_, var_uinteger, extra_literals_,
>   		  (erased_get_var_address_ftype *) get_var_address_cb_,
>   		  show_cmd_cb_,
>   		  set_doc_, show_doc_, help_doc_)
> @@ -220,18 +225,19 @@ struct uinteger_option_def : option_def
>     }
>   };
>
> -/* A var_zuinteger_unlimited command line option.  */
> +/* A var_integer command line option.  */
>
>   template<typename Context>
> -struct zuinteger_unlimited_option_def : option_def
> +struct integer_option_def : option_def
>   {
> -  zuinteger_unlimited_option_def (const char *long_option_,
> -				  int *(*get_var_address_cb_) (Context *),
> -				  show_value_ftype *show_cmd_cb_,
> -				  const char *set_doc_,
> -				  const char *show_doc_ = nullptr,
> -				  const char *help_doc_ = nullptr)
> -    : option_def (long_option_, var_zuinteger_unlimited,
> +  integer_option_def (const char *long_option_,
> +		      int *(*get_var_address_cb_) (Context *),
> +		      const literal_def *extra_literals_,
> +		      show_value_ftype *show_cmd_cb_,
> +		      const char *set_doc_,
> +		      const char *show_doc_ = nullptr,
> +		      const char *help_doc_ = nullptr)
> +    : option_def (long_option_, var_integer, extra_literals_,
>   		  (erased_get_var_address_ftype *) get_var_address_cb_,
>   		  show_cmd_cb_,
>   		  set_doc_, show_doc_, help_doc_)
> @@ -252,7 +258,7 @@ struct enum_option_def : option_def
>   		   const char *set_doc_,
>   		   const char *show_doc_ = nullptr,
>   		   const char *help_doc_ = nullptr)
> -    : option_def (long_option_, var_enum,
> +    : option_def (long_option_, var_enum, nullptr,
>   		  (erased_get_var_address_ftype *) get_var_address_cb_,
>   		  show_cmd_cb_,
>   		  set_doc_, show_doc_, help_doc_)
> @@ -273,7 +279,7 @@ struct string_option_def : option_def
>   		     const char *set_doc_,
>   		     const char *show_doc_ = nullptr,
>   		     const char *help_doc_ = nullptr)
> -    : option_def (long_option_, var_string,
> +    : option_def (long_option_, var_string, nullptr,
>   		  (erased_get_var_address_ftype *) get_var_address_cb_,
>   		  show_cmd_cb_,
>   		  set_doc_, show_doc_, help_doc_)
> Index: src/gdb/cli/cli-setshow.c
> ===================================================================
> --- src.orig/gdb/cli/cli-setshow.c
> +++ src/gdb/cli/cli-setshow.c
> @@ -149,10 +149,11 @@ deprecated_show_value_hack (struct ui_fi
>       }
>   }
>
> -/* Returns true if ARG is "unlimited".  */
> +/* Returns true and the value in VAL if ARG is an accepted literal.  */
>
>   static bool
> -is_unlimited_literal (const char **arg, bool expression)
> +get_literal_val (LONGEST &val, const literal_def *extra_literals,
> +		 const char **arg, bool expression)
>   {
>     *arg = skip_spaces (*arg);
>
> @@ -162,85 +163,108 @@ is_unlimited_literal (const char **arg,
>
>     size_t len = p - *arg;
>
> -  if (len > 0 && strncmp ("unlimited", *arg, len) == 0)
> -    {
> -      *arg += len;
> -
> -      /* If parsing an expression (i.e., parsing for a "set" command),
> -	 anything after "unlimited" is junk.  For options, anything
> -	 after "unlimited" might be a command argument or another
> -	 option.  */
> -      if (expression)
> +  if (len > 0 && extra_literals != nullptr)
> +    for (const literal_def *l = extra_literals;
> +	 l->literal != nullptr;
> +	 l++)
> +      if (strncmp (l->literal, *arg, len) == 0)
>   	{
> -	  const char *after = skip_spaces (*arg);
> -	  if (*after != '\0')
> -	    error (_("Junk after \"%.*s\": %s"),
> -		   (int) len, unl_start, after);
> -	}
> +	  *arg += len;
>
> -      return true;
> -    }
> +	  /* If parsing an expression (i.e., parsing for a "set" command),
> +	     anything after the literal is junk.  For options, anything
> +	     after the literal might be a command argument or another
> +	     option.  */
> +	  if (expression)
> +	    {
> +	      const char *after = skip_spaces (*arg);
> +	      if (*after != '\0')
> +		error (_("Junk after \"%.*s\": %s"),
> +		       (int) len, unl_start, after);
> +	    }
> +
> +	  val = l->use;
> +	  return true;
> +	}
>
>     return false;
>   }
>
>   /* See cli-setshow.h.  */
>
> -unsigned int
> -parse_cli_var_uinteger (var_types var_type, const char **arg,
> -			bool expression)
> +LONGEST
> +parse_cli_var_integer (var_types var_type, const literal_def *extra_literals,
> +		       const char **arg, bool expression)
>   {
>     LONGEST val;
>
>     if (*arg == nullptr || **arg == '\0')
>       {
> -      if (var_type == var_uinteger)
> -	error_no_arg (_("integer to set it to, or \"unlimited\""));
> -      else
> +      if (extra_literals == nullptr)
>   	error_no_arg (_("integer to set it to"));
> -    }
> -
> -  if (var_type == var_uinteger && is_unlimited_literal (arg, expression))
> -    val = 0;
> -  else if (expression)
> -    val = parse_and_eval_long (*arg);
> -  else
> -    val = get_ulongest (arg);
> -
> -  if (var_type == var_uinteger && val == 0)
> -    val = UINT_MAX;
> -  else if (val < 0
> -	   /* For var_uinteger, don't let the user set the value
> -	      to UINT_MAX directly, as that exposes an
> -	      implementation detail to the user interface.  */
> -	   || (var_type == var_uinteger && val >= UINT_MAX)
> -	   || (var_type == var_zuinteger && val > UINT_MAX))
> -    error (_("integer %s out of range"), plongest (val));
> -
> -  return val;
> -}
> -
> -/* See cli-setshow.h.  */
> +      else
> +	{
> +	  std::string buffer = "";
> +	  size_t count = 0;
>
> -int
> -parse_cli_var_zuinteger_unlimited (const char **arg, bool expression)
> -{
> -  LONGEST val;
> +	  for (const literal_def *l = extra_literals;
> +	       l->literal != nullptr;
> +	       l++, count++)
> +	    {
> +	      if (count != 0)
> +		buffer += ", ";
> +	      buffer = buffer + '"' + l->literal + '"';
> +	    }
> +	  if (count > 1)
> +	    error_no_arg
> +	      (string_printf (_("integer to set it to, or one of: %s"),
> +			      buffer.c_str ()).c_str ());
> +	  else
> +	    error_no_arg
> +	      (string_printf (_("integer to set it to, or %s"),
> +			      buffer.c_str ()).c_str ());
> +	}
> +    }
>
> -  if (*arg == nullptr || **arg == '\0')
> -    error_no_arg (_("integer to set it to, or \"unlimited\""));
> +  if (!get_literal_val (val, extra_literals, arg, expression))
> +    {
> +      if (expression)
> +	val = parse_and_eval_long (*arg);
> +      else
> +	val = get_ulongest (arg);
>
> -  if (is_unlimited_literal (arg, expression))
> -    val = -1;
> -  else if (expression)
> -    val = parse_and_eval_long (*arg);
> -  else
> -    val = get_ulongest (arg);
> +      enum tribool allowed = TRIBOOL_UNKNOWN;
> +      if (extra_literals != nullptr)
> +	{
> +	  for (const literal_def *l = extra_literals;
> +	       l->literal != nullptr;
> +	       l++)
> +	    if (val == l->val)
> +	      {
> +		allowed = l->allow ? TRIBOOL_TRUE : TRIBOOL_FALSE;
> +		val = l->use;
> +		break;
> +	      }
> +	    else if (val == l->use)
> +	      {
> +		allowed = TRIBOOL_FALSE;
> +		break;
> +	      }
> +	}
>
> -  if (val > INT_MAX)
> -    error (_("integer %s out of range"), plongest (val));
> -  else if (val < -1)
> -    error (_("only -1 is allowed to set as unlimited"));
> +      if (allowed == TRIBOOL_UNKNOWN)
> +	{
> +	  if (var_type == var_pinteger && val < 0)
> +	    error (_("only -1 is allowed to set as unlimited"));
> +	  else if (val > UINT_MAX || val < INT_MIN
> +		   || (var_type == var_uinteger && val < 0)
> +		   || (var_type == var_integer && val > INT_MAX)
> +		   || (var_type == var_pinteger && val > INT_MAX))
> +	    allowed = TRIBOOL_FALSE;
> +	}
> +      if (allowed == TRIBOOL_FALSE)
> +	error (_("integer %s out of range"), plongest (val));
> +    }
>
>     return val;
>   }
> @@ -405,41 +429,18 @@ do_set_command (const char *arg, int fro
>         option_changed = c->var->set<enum auto_boolean> (parse_auto_binary_operation (arg));
>         break;
>       case var_uinteger:
> -    case var_zuinteger:
>         option_changed
> -	= c->var->set<unsigned int> (parse_cli_var_uinteger (c->var->type (),
> -							     &arg, true));
> +	= c->var->set<unsigned int> (parse_cli_var_integer (c->var->type (),
> +							    c->var->
> +							    extra_literals (),
> +							    &arg, true));
>         break;
>       case var_integer:
> -    case var_zinteger:
> -      {
> -	LONGEST val;
> -
> -	if (*arg == '\0')
> -	  {
> -	    if (c->var->type () == var_integer)
> -	      error_no_arg (_("integer to set it to, or \"unlimited\""));
> -	    else
> -	      error_no_arg (_("integer to set it to"));
> -	  }
> -
> -	if (c->var->type () == var_integer && is_unlimited_literal (&arg, true))
> -	  val = 0;
> -	else
> -	  val = parse_and_eval_long (arg);
> -
> -	if (val == 0 && c->var->type () == var_integer)
> -	  val = INT_MAX;
> -	else if (val < INT_MIN
> -		 /* For var_integer, don't let the user set the value
> -		    to INT_MAX directly, as that exposes an
> -		    implementation detail to the user interface.  */
> -		 || (c->var->type () == var_integer && val >= INT_MAX)
> -		 || (c->var->type () == var_zinteger && val > INT_MAX))
> -	  error (_("integer %s out of range"), plongest (val));
> -
> -	option_changed = c->var->set<int> (val);
> -      }
> +    case var_pinteger:
> +      option_changed
> +	= c->var->set<int> (parse_cli_var_integer (c->var->type (),
> +						   c->var->extra_literals (),
> +						   &arg, true));
>         break;
>       case var_enum:
>         {
> @@ -454,10 +455,6 @@ do_set_command (const char *arg, int fro
>   	option_changed = c->var->set<const char *> (match);
>         }
>         break;
> -    case var_zuinteger_unlimited:
> -      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"));
>       }
> @@ -551,7 +548,6 @@ do_set_command (const char *arg, int fro
>   	  }
>   	  break;
>   	case var_uinteger:
> -	case var_zuinteger:
>   	  {
>   	    char s[64];
>
> @@ -560,8 +556,7 @@ do_set_command (const char *arg, int fro
>   	  }
>   	  break;
>   	case var_integer:
> -	case var_zinteger:
> -	case var_zuinteger_unlimited:
> +	case var_pinteger:
>   	  {
>   	    char s[64];
>
> @@ -623,36 +618,32 @@ get_setshow_command_value_string (const
>   	}
>         break;
>       case var_uinteger:
> -    case var_zuinteger:
> -      {
> -	const unsigned int value = var.get<unsigned int> ();
> -
> -	if (var.type () == var_uinteger
> -	    && value == UINT_MAX)
> -	  stb.puts ("unlimited");
> -	else
> -	  stb.printf ("%u", value);
> -      }
> -      break;
>       case var_integer:
> -    case var_zinteger:
> +    case var_pinteger:
>         {
> -	const int value = var.get<int> ();
> +	bool printed = false;
> +	const LONGEST value
> +	  = (var.type () == var_uinteger
> +	     ? static_cast<LONGEST> (var.get<unsigned int> ())
> +	     : static_cast<LONGEST> (var.get<int> ()));
>
> -	if (var.type () == var_integer
> -	    && value == INT_MAX)
> -	  stb.puts ("unlimited");
> -	else
> -	  stb.printf ("%d", value);
> -      }
> -      break;
> -    case var_zuinteger_unlimited:
> -      {
> -	const int value = var.get<int> ();
> -	if (value == -1)
> -	  stb.puts ("unlimited");
> -	else
> -	  stb.printf ("%d", value);
> +	if (var.extra_literals () != nullptr)
> +	  for (const literal_def *l = var.extra_literals ();
> +	       l->literal != nullptr;
> +	       l++)
> +	    if (value == l->use)
> +	      {
> +		stb.puts (l->literal);
> +		printed = true;
> +		break;
> +	      }
> +	if (!printed)
> +	  {
> +	    if (var.type () == var_uinteger)
> +	      stb.printf ("%u", static_cast<const unsigned int> (value));
> +	    else
> +	      stb.printf ("%d", static_cast<const int> (value));
> +	  }
>         }
>         break;
>       default:
> Index: src/gdb/cli/cli-setshow.h
> ===================================================================
> --- src.orig/gdb/cli/cli-setshow.h
> +++ src/gdb/cli/cli-setshow.h
> @@ -29,21 +29,19 @@ extern int parse_cli_boolean_value (cons
>      past a successfully parsed value.  */
>   extern int parse_cli_boolean_value (const char **arg);
>
> -/* Parse ARG, an option to a var_uinteger or var_zuinteger variable.
> -   Either returns the parsed value on success or throws an error.  If
> -   EXPRESSION is true, *ARG is parsed as an expression; otherwise, it
> -   is parsed with get_ulongest.  It's not possible to parse the
> +/* Parse ARG, an option to a var_uinteger, var_integer or var_pinteger
> +   variable.  Return the parsed value on success or throw an error.  If
> +   EXTRA_LITERALS is non-null, then interpret those literals accordingly.
> +   If EXPRESSION is true, *ARG is parsed as an expression; otherwise,
> +   it is parsed with get_ulongest.  It's not possible to parse the
>      integer as an expression when there may be valid input after the
>      integer, such as when parsing command options.  E.g., "print
>      -elements NUMBER -obj --".  In such case, parsing as an expression
>      would parse "-obj --" as part of the expression as well.  */
> -extern unsigned int parse_cli_var_uinteger (var_types var_type,
> -					    const char **arg,
> -					    bool expression);
> -
> -/* Like parse_cli_var_uinteger, for var_zuinteger_unlimited.  */
> -extern int parse_cli_var_zuinteger_unlimited (const char **arg,
> -					      bool expression);
> +extern LONGEST parse_cli_var_integer (var_types var_type,
> +				      const literal_def *extra_literals,
> +				      const char **arg,
> +				      bool expression);
>
>   /* Parse ARG, an option to a var_enum variable.  ENUM is a
>      null-terminated array of possible values. Either returns the parsed
> Index: src/gdb/command.h
> ===================================================================
> --- src.orig/gdb/command.h
> +++ src/gdb/command.h
> @@ -84,16 +84,18 @@ typedef enum var_types
>          value.  */
>       var_auto_boolean,
>
> -    /* Unsigned Integer.  *VAR is an unsigned int.  The user can type
> -       0 to mean "unlimited", which is stored in *VAR as UINT_MAX.  */
> +    /* Unsigned Integer.  *VAR is an unsigned int.  In the Guile and Python
> +       APIs 0 means unlimited, which is stored in *VAR as UINT_MAX.  */
>       var_uinteger,
>
> -    /* Like var_uinteger but signed.  *VAR is an int.  The user can
> -       type 0 to mean "unlimited", which is stored in *VAR as
> -       INT_MAX.  The only remaining use of it is the Python API.
> -       Don't use it elsewhere.  */
> +    /* Like var_uinteger but signed.  *VAR is an int.  In the Guile and
> +       Python APIs 0 means unlimited, which is stored in *VAR as INT_MAX.  */
>       var_integer,
>
> +    /* Like var_integer but negative numbers are not allowed,
> +       except for special values.  *VAR is an int.  */
> +    var_pinteger,
> +
>       /* String which the user enters with escapes (e.g. the user types
>          \n and it is a real newline in the stored string).
>          *VAR is a std::string, "" if the string is empty.  */
> @@ -106,15 +108,16 @@ typedef enum var_types
>       var_optional_filename,
>       /* String which stores a filename.  (*VAR) is a std::string.  */
>       var_filename,
> -    /* ZeroableInteger.  *VAR is an int.  Like var_integer except
> -       that zero really means zero.  */
> +    /* Like var_integer.  *VAR is an int.  The only remaining uses
> +       of it are the Guile and Python APIs.  Don't use it elsewhere.  */
>       var_zinteger,
> -    /* ZeroableUnsignedInteger.  *VAR is an unsigned int.  Zero really
> -       means zero.  */
> +    /* Like var_uinteger.  *VAR is an unsigned int.  The only remaining
> +       uses of it are the Guile and Python APIs.  Don't use it elsewhere.  */
>       var_zuinteger,
> -    /* ZeroableUnsignedInteger with unlimited value.  *VAR is an int,
> -       but its range is [0, INT_MAX].  -1 stands for unlimited and
> -       other negative numbers are not allowed.  */
> +    /* Like var_pinteger.  *VAR is an int, but its range is [-1, INT_MAX].
> +       -1 stands for unlimited and other negative numbers are not allowed.
> +       The only remaining uses of it are the Guile and Python APIs.  Don't
> +       use it elsewhere.  */
>       var_zuinteger_unlimited,
>       /* Enumerated type.  Can only have one of the specified values.
>          *VAR is a char pointer to the name of the element that we
> @@ -123,6 +126,22 @@ typedef enum var_types
>     }
>   var_types;
>
> +/* A structure describing an extra literal accepted and shown in place
> +   of a number.  */
> +typedef struct literal_defs
> +  {
> +    /* The literal to define, e.g. "unlimited".  */
> +    const char *literal;
> +    /* A number optionally accepted that stands for the literal.  */
> +    LONGEST val;
> +    /* The number to substitute internally for LITERAL or VAL;
> +       the use of this number is not allowed (unless the same as VAL).  */
> +    LONGEST use;
> +    /* True if the use of VAL is allowed; otherwise only the literal is.  */
> +    bool allow;
> +  }
> +literal_def;
> +
>   /* Return true if a setting of type VAR_TYPE is backed with type T.
>
>      This function is left without definition intentionally.  This template is
> @@ -153,15 +172,14 @@ inline bool var_type_uses<enum auto_bool
>   template<>
>   inline bool var_type_uses<unsigned int> (var_types t)
>   {
> -  return (t == var_uinteger || t == var_zinteger || t == var_zuinteger);
> +  return t == var_uinteger;
>   }
>
>   /* Return true if a setting of type T is backed by an int variable.  */
>   template<>
>   inline bool var_type_uses<int> (var_types t)
>   {
> -  return (t == var_integer || t == var_zinteger
> -	  || t == var_zuinteger_unlimited);
> +  return t == var_integer || t == var_pinteger;
>   }
>
>   /* Return true if a setting of type T is backed by a std::string variable.  */
> @@ -233,6 +251,7 @@ struct setting
>     struct erased_args
>     {
>       void *var;
> +    const void *extra_literals;
>       erased_func setter;
>       erased_func getter;
>     };
> @@ -240,6 +259,7 @@ struct setting
>     template<typename T>
>     static erased_args erase_args (var_types var_type,
>   				 T *var,
> +				 const literal_def *extra_literals,
>   				 typename setting_func_types<T>::set set_setting_func,
>   				 typename setting_func_types<T>::get get_setting_func)
>     {
> @@ -254,6 +274,7 @@ struct setting
>
>       return {
>   	var,
> +	extra_literals,
>   	reinterpret_cast<erased_func> (set_setting_func),
>   	reinterpret_cast<erased_func> (get_setting_func)
>       };
> @@ -265,6 +286,7 @@ struct setting
>     setting (var_types var_type, const erased_args &args)
>       : m_var_type (var_type),
>         m_var (args.var),
> +      m_extra_literals (args.extra_literals),
>         m_getter (args.getter),
>         m_setter (args.setter)
>     {
> @@ -295,6 +317,10 @@ struct setting
>     var_types type () const
>     { return m_var_type; }
>
> +  /* Access any extra literals accepted.  */
> +  const literal_def *extra_literals () const
> +  { return static_cast<const literal_def *> (m_extra_literals); }
> +
>     /* Return the current value.
>
>        The template parameter T is the type of the variable used to store the
> @@ -357,6 +383,9 @@ struct setting
>        non-nullptr.  */
>     void *m_var = nullptr;
>
> +  /* Any extra literals accepted.  */
> +  const void *m_extra_literals = nullptr;
> +
>     /* Pointer to a user provided getter.  */
>     erased_func m_getter = nullptr;
>
> @@ -652,6 +681,11 @@ typedef void (show_value_ftype) (struct
>      instead print the value out directly.  */
>   extern show_value_ftype deprecated_show_value_hack;
>
> +/* Various sets of extra literals accepted.  */
> +extern const literal_def integer_unlimited_literals[];
> +extern const literal_def uinteger_unlimited_literals[];
> +extern const literal_def zuinteger_unlimited_literals[];
> +
>   extern set_show_commands add_setshow_enum_cmd
>     (const char *name, command_class theclass, const char *const *enumlist,
>      const char **var, const char *set_doc, const char *show_doc,
> @@ -748,6 +782,20 @@ extern set_show_commands add_setshow_opt
>      cmd_list_element **show_list);
>
>   extern set_show_commands add_setshow_integer_cmd
> +  (const char *name, command_class theclass, int *var,
> +   const literal_def *extra_literals, 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 literal_def *extra_literals,
> +   const char *set_doc, const char *show_doc, const char *help_doc,
> +   setting_func_types<int>::set set_func,
> +   setting_func_types<int>::get 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,
> @@ -760,6 +808,34 @@ extern set_show_commands add_setshow_int
>      setting_func_types<int>::get get_func, show_value_ftype *show_func,
>      cmd_list_element **set_list, cmd_list_element **show_list);
>
> +extern set_show_commands add_setshow_pinteger_cmd
> +  (const char *name, command_class theclass, int *var,
> +   const literal_def *extra_literals, 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_pinteger_cmd
> +  (const char *name, command_class theclass, const literal_def *extra_literals,
> +   const char *set_doc, const char *show_doc, const char *help_doc,
> +   setting_func_types<int>::set set_func,
> +   setting_func_types<int>::get 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 literal_def *extra_literals,
> +   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 literal_def *extra_literals,
> +   const char *set_doc, const char *show_doc, const char *help_doc,
> +   setting_func_types<unsigned int>::set set_func,
> +   setting_func_types<unsigned int>::get 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,
> Index: src/gdb/guile/scm-param.c
> ===================================================================
> --- src.orig/gdb/guile/scm-param.c
> +++ src/gdb/guile/scm-param.c
> @@ -117,18 +117,33 @@ struct param_smob
>   static setting
>   make_setting (param_smob *s)
>   {
> -  if (var_type_uses<bool> (s->type))
> -    return setting (s->type, &s->value.boolval);
> -  else if (var_type_uses<int> (s->type))
> -    return setting (s->type, &s->value.intval);
> -  else if (var_type_uses<auto_boolean> (s->type))
> -    return setting (s->type, &s->value.autoboolval);
> -  else if (var_type_uses<unsigned int> (s->type))
> -    return setting (s->type, &s->value.uintval);
> -  else if (var_type_uses<std::string> (s->type))
> -    return setting (s->type, s->value.stringval);
> -  else if (var_type_uses<const char *> (s->type))
> -    return setting (s->type, &s->value.cstringval);
> +  enum var_types type = s->type;
> +
> +  switch (type)
> +    {
> +    case var_zinteger:
> +      type = var_integer;
> +      break;
> +    case var_zuinteger:
> +      type = var_uinteger;
> +      break;
> +    case var_zuinteger_unlimited:
> +      type = var_pinteger;
> +      break;
> +    }
> +
> +  if (var_type_uses<bool> (type))
> +    return setting (type, &s->value.boolval);
> +  else if (var_type_uses<int> (type))
> +    return setting (type, &s->value.intval);
> +  else if (var_type_uses<auto_boolean> (type))
> +    return setting (type, &s->value.autoboolval);
> +  else if (var_type_uses<unsigned int> (type))
> +    return setting (type, &s->value.uintval);
> +  else if (var_type_uses<std::string> (type))
> +    return setting (type, s->value.stringval);
> +  else if (var_type_uses<const char *> (type))
> +    return setting (type, &s->value.cstringval);
>     else
>       gdb_assert_not_reached ("unhandled var type");
>   }
> @@ -588,10 +603,6 @@ pascm_param_type_name (enum var_types pa
>   static SCM
>   pascm_param_value (const setting &var, int arg_pos, const char *func_name)
>   {
> -  /* Note: We *could* support var_integer here in case someone is trying to get
> -     the value of a Python-created parameter (which is the only place that
> -     still supports var_integer).  To further discourage its use we do not.  */
> -
>     switch (var.type ())
>       {
>       case var_string:
> @@ -631,20 +642,35 @@ pascm_param_value (const setting &var, i
>   	  return auto_keyword;
>         }
>
> -    case var_zuinteger_unlimited:
> -      if (var.get<int> () == -1)
> -	return unlimited_keyword;
> -      gdb_assert (var.get<int> () >= 0);
> -      /* Fall through.  */
> -    case var_zinteger:
> -      return scm_from_int (var.get<int> ());
> -
>       case var_uinteger:
> -      if (var.get<unsigned int> ()== UINT_MAX)
> -	return unlimited_keyword;
> -      /* Fall through.  */
> -    case var_zuinteger:
> -      return scm_from_uint (var.get<unsigned int> ());
> +    case var_integer:
> +    case var_pinteger:
> +      {
> +	LONGEST value
> +	  = (var.type () == var_uinteger
> +	     ? static_cast<LONGEST> (var.get<unsigned int> ())
> +	     : static_cast<LONGEST> (var.get<int> ()));
> +
> +	bool literal = false;
> +	if (var.extra_literals () != nullptr)
> +	  for (const literal_def *l = var.extra_literals ();
> +	       l->literal != nullptr;
> +	       l++)
> +	    if (value == l->use)
> +	      {
> +		if (strcmp (l->literal, "unlimited") == 0)
> +		  return unlimited_keyword;
> +		value = l->val;
> +		literal = true;
> +	      }
> +	if (var.type () == var_pinteger && !literal)
> +	  gdb_assert (value >= 0);
> +
> +	if (var.type () == var_uinteger)
> +	  return scm_from_uint (static_cast<const unsigned int> (value));
> +	else
> +	  return scm_from_int (static_cast<const int> (value));
> +      }
>
>       default:
>         break;
> @@ -666,14 +692,14 @@ pascm_set_param_value_x (param_smob *p_s
>   {
>     setting var = make_setting (p_smob);
>
> -  switch (var.type ())
> +  switch (p_smob->type)
>       {
>       case var_string:
>       case var_string_noescape:
>       case var_optional_filename:
>       case var_filename:
>         SCM_ASSERT_TYPE (scm_is_string (value)
> -		       || (var.type () != var_filename
> +		       || (p_smob->type != var_filename
>   			   && gdbscm_is_false (value)),
>   		       value, arg_pos, func_name,
>   		       _("string or #f for non-PARAM_FILENAME parameters"));
> @@ -739,8 +765,8 @@ pascm_set_param_value_x (param_smob *p_s
>       case var_uinteger:
>       case var_zuinteger:
>       case var_zuinteger_unlimited:
> -      if (var.type () == var_uinteger
> -	  || var.type () == var_zuinteger_unlimited)
> +      if (p_smob->type == var_uinteger
> +	  || p_smob->type == var_zuinteger_unlimited)
>   	{
>   	  SCM_ASSERT_TYPE (gdbscm_is_bool (value)
>   			   || scm_is_eq (value, unlimited_keyword),
> @@ -748,7 +774,7 @@ pascm_set_param_value_x (param_smob *p_s
>   			   _("integer or #:unlimited"));
>   	  if (scm_is_eq (value, unlimited_keyword))
>   	    {
> -	      if (var.type () == var_uinteger)
> +	      if (p_smob->type == var_uinteger)
>   		var.set<unsigned int> (UINT_MAX);
>   	      else
>   		var.set<int> (-1);
> @@ -761,12 +787,12 @@ pascm_set_param_value_x (param_smob *p_s
>   			   _("integer"));
>   	}
>
> -      if (var.type () == var_uinteger
> -	  || var.type () == var_zuinteger)
> +      if (p_smob->type == var_uinteger
> +	  || p_smob->type == var_zuinteger)
>   	{
>   	  unsigned int u = scm_to_uint (value);
>
> -	  if (var.type () == var_uinteger && u == 0)
> +	  if (p_smob->type == var_uinteger && u == 0)
>   	    u = UINT_MAX;
>   	  var.set<unsigned int> (u);
>   	}
> @@ -774,7 +800,7 @@ pascm_set_param_value_x (param_smob *p_s
>   	{
>   	  int i = scm_to_int (value);
>
> -	  if (var.type () == var_zuinteger_unlimited && i < -1)
> +	  if (p_smob->type == var_zuinteger_unlimited && i < -1)
>   	    {
>   	      gdbscm_out_of_range_error (func_name, arg_pos, value,
>   					 _("must be >= -1"));
> Index: src/gdb/maint-test-options.c
> ===================================================================
> --- src.orig/gdb/maint-test-options.c
> +++ src/gdb/maint-test-options.c
> @@ -207,6 +207,7 @@ static const gdb::option::option_def tes
>     gdb::option::uinteger_option_def<test_options_opts> {
>       "uinteger",
>       [] (test_options_opts *opts) { return &opts->uint_opt; },
> +    uinteger_unlimited_literals,
>       nullptr, /* show_cmd_cb */
>       N_("A uinteger option."),
>       nullptr, /* show_doc */
> @@ -214,9 +215,10 @@ static const gdb::option::option_def tes
>     },
>
>     /* A zuinteger_unlimited option.  */
> -  gdb::option::zuinteger_unlimited_option_def<test_options_opts> {
> +  gdb::option::integer_option_def<test_options_opts> {
>       "zuinteger-unlimited",
>       [] (test_options_opts *opts) { return &opts->zuint_unl_opt; },
> +    zuinteger_unlimited_literals,
>       nullptr, /* show_cmd_cb */
>       N_("A zuinteger-unlimited option."),
>       nullptr, /* show_doc */
> Index: src/gdb/python/py-param.c
> ===================================================================
> --- src.orig/gdb/python/py-param.c
> +++ src/gdb/python/py-param.c
> @@ -96,18 +96,33 @@ struct parmpy_object
>   static setting
>   make_setting (parmpy_object *s)
>   {
> -  if (var_type_uses<bool> (s->type))
> -    return setting (s->type, &s->value.boolval);
> -  else if (var_type_uses<int> (s->type))
> -    return setting (s->type, &s->value.intval);
> -  else if (var_type_uses<auto_boolean> (s->type))
> -    return setting (s->type, &s->value.autoboolval);
> -  else if (var_type_uses<unsigned int> (s->type))
> -    return setting (s->type, &s->value.uintval);
> -  else if (var_type_uses<std::string> (s->type))
> -    return setting (s->type, s->value.stringval);
> -  else if (var_type_uses<const char *> (s->type))
> -    return setting (s->type, &s->value.cstringval);
> +  enum var_types type = s->type;
> +
> +  switch (type)
> +    {
> +    case var_zinteger:
> +      type = var_integer;
> +      break;
> +    case var_zuinteger:
> +      type = var_uinteger;
> +      break;
> +    case var_zuinteger_unlimited:
> +      type = var_pinteger;
> +      break;
> +    }
> +
> +  if (var_type_uses<bool> (type))
> +    return setting (type, &s->value.boolval);
> +  else if (var_type_uses<int> (type))
> +    return setting (type, &s->value.intval);
> +  else if (var_type_uses<auto_boolean> (type))
> +    return setting (type, &s->value.autoboolval);
> +  else if (var_type_uses<unsigned int> (type))
> +    return setting (type, &s->value.uintval);
> +  else if (var_type_uses<std::string> (type))
> +    return setting (type, s->value.stringval);
> +  else if (var_type_uses<const char *> (type))
> +    return setting (type, &s->value.cstringval);
>     else
>       gdb_assert_not_reached ("unhandled var type");
>   }
> Index: src/gdb/python/python.c
> ===================================================================
> --- src.orig/gdb/python/python.c
> +++ src/gdb/python/python.c
> @@ -502,35 +502,34 @@ gdbpy_parameter_value (const setting &va
>   	  Py_RETURN_NONE;
>         }
>
> -    case var_integer:
> -      if (var.get<int> () == INT_MAX)
> -	Py_RETURN_NONE;
> -      /* Fall through.  */
> -    case var_zinteger:
> -      return gdb_py_object_from_longest (var.get<int> ()).release ();
> -
> -    case var_zuinteger_unlimited:
> -      {
> -	int val = var.get<int> ();
> -
> -	if (val == -1)
> -	  Py_RETURN_NONE;
> -	return gdb_py_object_from_longest (val).release ();
> -      }
> -
>       case var_uinteger:
> +    case var_integer:
> +    case var_pinteger:
>         {
> -	unsigned int val = var.get<unsigned int> ();
> +	LONGEST value
> +	  = (var.type () == var_uinteger
> +	     ? static_cast<LONGEST> (var.get<unsigned int> ())
> +	     : static_cast<LONGEST> (var.get<int> ()));
>
> -	if (val == UINT_MAX)
> -	  Py_RETURN_NONE;
> -	return gdb_py_object_from_ulongest (val).release ();
> -      }
> +	if (var.extra_literals () != nullptr)
> +	  for (const literal_def *l = var.extra_literals ();
> +	       l->literal != nullptr;
> +	       l++)
> +	    if (value == l->use)
> +	      {
> +		if (strcmp (l->literal, "unlimited") == 0)
> +		  Py_RETURN_NONE;
> +		value = l->val;
> +	      }
>
> -    case var_zuinteger:
> -      {
> -	unsigned int val = var.get<unsigned int> ();
> -	return gdb_py_object_from_ulongest (val).release ();
> +	if (var.type () == var_uinteger)
> +	  return
> +	    gdb_py_object_from_ulongest
> +	      (static_cast<const unsigned int> (value)).release ();
> +	else
> +	  return
> +	    gdb_py_object_from_longest
> +	      (static_cast<const int> (value)).release ();
>         }
>       }
>
> Index: src/gdb/valprint.c
> ===================================================================
> --- src.orig/gdb/valprint.c
> +++ src/gdb/valprint.c
> @@ -2974,8 +2974,8 @@ using boolean_option_def
>     = gdb::option::boolean_option_def<value_print_options>;
>   using uinteger_option_def
>     = gdb::option::uinteger_option_def<value_print_options>;
> -using zuinteger_unlimited_option_def
> -  = gdb::option::zuinteger_unlimited_option_def<value_print_options>;
> +using integer_option_def
> +  = gdb::option::integer_option_def<value_print_options>;
>
>   /* Definitions of options for the "print" and "compile print"
>      commands.  */
> @@ -3011,15 +3011,17 @@ static const gdb::option::option_def val
>     uinteger_option_def {
>       "elements",
>       [] (value_print_options *opt) { return &opt->print_max; },
> +    uinteger_unlimited_literals,
>       show_print_max, /* show_cmd_cb */
>       N_("Set limit on string chars or array elements to print."),
>       N_("Show limit on string chars or array elements to print."),
>       N_("\"unlimited\" causes there to be no limit."),
>     },
>
> -  zuinteger_unlimited_option_def {
> +  integer_option_def {
>       "max-depth",
>       [] (value_print_options *opt) { return &opt->max_depth; },
> +    zuinteger_unlimited_literals,
>       show_print_max_depth, /* show_cmd_cb */
>       N_("Set maximum print depth for nested structures, unions and arrays."),
>       N_("Show maximum print depth for nested structures, unions, and arrays."),
> @@ -3079,6 +3081,7 @@ pretty-printers for that value.")
>     uinteger_option_def {
>       "repeats",
>       [] (value_print_options *opt) { return &opt->repeat_count_threshold; },
> +    uinteger_unlimited_literals,
>       show_repeat_count_threshold, /* show_cmd_cb */
>       N_("Set threshold for repeated print elements."),
>       N_("Show threshold for repeated print elements."),

  reply	other threads:[~2022-03-30 10:42 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-30 10:23 [PATCH v5 0/8] gdb: split array and string limiting options Maciej W. Rozycki
2022-03-30 10:23 ` [PATCH v5 1/8] GDB: Remove extraneous full stops from `set' command error messages Maciej W. Rozycki
2022-06-24 14:32   ` Andrew Burgess
2022-06-29 14:29     ` Maciej W. Rozycki
2022-03-30 10:23 ` [PATCH v5 2/8] GDB/Python: Use None for `var_zuinteger_unlimited' value set to `unlimited' Maciej W. Rozycki
2022-03-30 10:35   ` Simon Sobisch
2022-03-30 10:40     ` Maciej W. Rozycki
2022-03-30 10:50       ` Simon Sobisch
2022-03-30 11:52         ` Maciej W. Rozycki
2022-06-24 14:40   ` Andrew Burgess
2022-06-29 16:48     ` Maciej W. Rozycki
2022-03-30 10:24 ` [PATCH v5 3/8] GDB: Add `NUMBER' completion to `set' integer commands Maciej W. Rozycki
2022-05-25 18:36   ` Bruno Larsen
2022-05-26 10:09     ` Maciej W. Rozycki
2022-05-26 11:46       ` Bruno Larsen
2022-05-26 14:24         ` Maciej W. Rozycki
2022-06-24 15:08   ` Andrew Burgess
2022-06-30 14:24     ` [PATCH v6 " Maciej W. Rozycki
2022-06-30 15:53       ` Eli Zaretskii
2022-06-30 18:59         ` Maciej W. Rozycki
2022-06-30 16:01       ` Andrew Burgess
2022-03-30 10:24 ` [PATCH v5 4/8] GDB/testsuite: Tighten `set print elements' error check Maciej W. Rozycki
2022-06-24 15:09   ` Andrew Burgess
2022-06-29 14:29     ` Maciej W. Rozycki
2022-03-30 10:24 ` [PATCH v5 5/8] GDB/testsuite: Add coverage for `print -elements' command Maciej W. Rozycki
2022-06-24 15:57   ` Andrew Burgess
2022-07-07 11:04     ` Maciej W. Rozycki
2022-03-30 10:24 ` [PATCH v5 6/8] GDB: Allow arbitrary keywords in integer set commands Maciej W. Rozycki
2022-03-30 10:42   ` Simon Sobisch [this message]
2022-03-30 10:58     ` Maciej W. Rozycki
2022-06-28 14:04   ` Andrew Burgess
2022-08-17 22:03     ` Maciej W. Rozycki
2022-03-30 10:24 ` [PATCH v5 7/8] GDB: Add a character string limiting option Maciej W. Rozycki
2022-03-30 12:29   ` Eli Zaretskii
2022-03-30 10:24 ` [PATCH v5 8/8] GDB/testsuite: Expand for character string limiting options Maciej W. Rozycki
2022-04-13 11:20 ` [PING][PATCH v5 0/8] gdb: split array and " Maciej W. Rozycki
2022-04-13 12:10   ` Simon Sobisch
2022-04-13 12:18     ` Maciej W. Rozycki
2022-04-20 19:17 ` [PING^2][PATCH " Maciej W. Rozycki
2022-04-26 19:57   ` Simon Sobisch
2022-04-27 12:00     ` Maciej W. Rozycki
2022-04-27 12:02 ` [PING^3][PATCH " Maciej W. Rozycki
2022-05-04 10:05 ` [PING^4][PATCH " Maciej W. Rozycki
2022-05-12 21:20 ` [PING^5][PATCH " Maciej W. Rozycki
2022-05-20 10:49 ` [PING^6][PATCH " Maciej W. Rozycki
2022-05-25 15:52 ` [PING^7][PATCH " Maciej W. Rozycki
2022-05-25 19:20 ` [PATCH " Bruno Larsen
2022-06-02 17:55 ` [PING^8][PATCH " Maciej W. Rozycki
2022-06-07 17:23   ` Simon Sobisch
2022-06-15 22:47 ` [PING^9][PATCH " Maciej W. Rozycki
2022-06-22 11:25 ` [PING^10][PATCH " Maciej W. Rozycki

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=31c7d89e-b786-02ef-6524-0f3bea04e994@web.de \
    --to=simonsobisch@web.de \
    --cc=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=macro@embecosm.com \
    --cc=simon.marchi@polymtl.ca \
    --cc=tom@tromey.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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).