GDB: Allow arbitrary keywords in integer set commands

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.

Remove 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.

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", INT_MAX, 0 },
    { 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 },
    { nullptr }
  };

defines the same keyword and a corresponding user-visible -1 value that
is used for the requested setting.  If the last member were omitted (or
set to `{}') 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.

Use said error message in all cases (citing the invalid value requested)
replacing "only -1 is allowed to set as unlimited" previously used for
`var_zuinteger_unlimited' settings only rather than propagating it to
`var_pinteger' type.  It could only be used for the specific case where
a single extra `unlimited' keyword was defined standing for -1 and the
use of numeric equivalents is discouraged anyway as it is for historical
reasons only that they expose GDB internals, confusingly different
across variable types.  Similarly update the "must be >= -1" Guile error
message.

Redefine Guile and Python parameter types in terms of the new variable
types and interpret extra keywords as Scheme keywords and Python strings
used to communicate corresponding parameter values.  Do not add a new
PARAM_INTEGER Guile parameter type, however do handle the `var_integer'
variable type now, permitting existing parameters defined by GDB proper,
such as `listsize', to be accessed from Scheme code.

With these changes in place it should be trivial for a Scheme or Python
programmer to expand the syntax of the `make-parameter' command and the
`gdb.Parameter' class initializer to have arbitrary extra literals along
with their internal representation supplied.

Update the testsuite accordingly.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
Maciej W. Rozycki 2023-01-19 21:15:56 +00:00
parent 0fcd58d843
commit 7aeb03e2d4
19 changed files with 1140 additions and 630 deletions

View file

@ -2213,22 +2213,40 @@ value_from_setting (const setting &var, struct gdbarch *gdbarch)
{ {
switch (var.type ()) switch (var.type ())
{ {
case var_uinteger:
case var_integer: case var_integer:
if (var.get<int> () == INT_MAX) case var_pinteger:
return value_from_longest (builtin_type (gdbarch)->builtin_int, {
0); LONGEST value
else = (var.type () == var_uinteger
return value_from_longest (builtin_type (gdbarch)->builtin_int, ? static_cast<LONGEST> (var.get<unsigned int> ())
var.get<int> ()); : static_cast<LONGEST> (var.get<int> ()));
case var_zinteger:
return value_from_longest (builtin_type (gdbarch)->builtin_int, if (var.extra_literals () != nullptr)
var.get<int> ()); for (const literal_def *l = var.extra_literals ();
l->literal != nullptr;
l++)
if (value == l->use)
{
if (l->val.has_value ())
value = *l->val;
else
return allocate_value (builtin_type (gdbarch)->builtin_void);
break;
}
if (var.type () == var_uinteger)
return
value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
static_cast<unsigned int> (value));
else
return
value_from_longest (builtin_type (gdbarch)->builtin_int,
static_cast<int> (value));
}
case var_boolean: case var_boolean:
return value_from_longest (builtin_type (gdbarch)->builtin_int, return value_from_longest (builtin_type (gdbarch)->builtin_int,
var.get<bool> () ? 1 : 0); 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: case var_auto_boolean:
{ {
int val; int val;
@ -2250,17 +2268,6 @@ value_from_setting (const setting &var, struct gdbarch *gdbarch)
return value_from_longest (builtin_type (gdbarch)->builtin_int, return value_from_longest (builtin_type (gdbarch)->builtin_int,
val); 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:
case var_string_noescape: case var_string_noescape:
case var_optional_filename: case var_optional_filename:
@ -2330,13 +2337,11 @@ str_value_from_setting (const setting &var, struct gdbarch *gdbarch)
{ {
switch (var.type ()) switch (var.type ())
{ {
case var_integer:
case var_zinteger:
case var_boolean:
case var_zuinteger_unlimited:
case var_auto_boolean:
case var_uinteger: case var_uinteger:
case var_zuinteger: case var_integer:
case var_pinteger:
case var_boolean:
case var_auto_boolean:
{ {
std::string cmd_val = get_setshow_command_value_string (var); std::string cmd_val = get_setshow_command_value_string (var);

View file

@ -496,6 +496,8 @@ empty_func (const char *args, int from_tty, cmd_list_element *c)
TYPE is set_cmd or show_cmd. TYPE is set_cmd or show_cmd.
THECLASS is as in add_cmd. THECLASS is as in add_cmd.
VAR_TYPE is the kind of thing we are setting. VAR_TYPE is the kind of thing we are setting.
EXTRA_LITERALS if non-NULL define extra literals to be accepted in lieu of
a number for integer variables.
ARGS is a pre-validated type-erased reference to the variable being ARGS is a pre-validated type-erased reference to the variable being
controlled by this command. controlled by this command.
DOC is the documentation string. */ DOC is the documentation string. */
@ -505,6 +507,7 @@ add_set_or_show_cmd (const char *name,
enum cmd_types type, enum cmd_types type,
enum command_class theclass, enum command_class theclass,
var_types var_type, var_types var_type,
const literal_def *extra_literals,
const setting::erased_args &arg, const setting::erased_args &arg,
const char *doc, const char *doc,
struct cmd_list_element **list) struct cmd_list_element **list)
@ -513,7 +516,7 @@ add_set_or_show_cmd (const char *name,
gdb_assert (type == set_cmd || type == show_cmd); gdb_assert (type == set_cmd || type == show_cmd);
c->type = type; c->type = type;
c->var.emplace (var_type, arg); c->var.emplace (var_type, extra_literals, arg);
/* This needs to be something besides NULL so that this isn't /* This needs to be something besides NULL so that this isn't
treated as a help class. */ treated as a help class. */
@ -523,10 +526,12 @@ add_set_or_show_cmd (const char *name,
/* Add element named NAME to both command lists SET_LIST and SHOW_LIST. /* Add element named NAME to both command lists SET_LIST and SHOW_LIST.
THECLASS is as in add_cmd. VAR_TYPE is the kind of thing we are THECLASS is as in add_cmd. VAR_TYPE is the kind of thing we are
setting. ARGS is a pre-validated type-erased reference to the setting. EXTRA_LITERALS if non-NULL define extra literals to be
variable being controlled by this command. SET_FUNC and SHOW_FUNC accepted in lieu of a number for integer variables. ARGS is a
are the callback functions (if non-NULL). SET_DOC, SHOW_DOC and pre-validated type-erased reference to the variable being controlled
HELP_DOC are the documentation strings. by this command. SET_FUNC and SHOW_FUNC are the callback functions
(if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation
strings.
Return the newly created set and show commands. */ Return the newly created set and show commands. */
@ -534,6 +539,7 @@ static set_show_commands
add_setshow_cmd_full_erased (const char *name, add_setshow_cmd_full_erased (const char *name,
enum command_class theclass, enum command_class theclass,
var_types var_type, var_types var_type,
const literal_def *extra_literals,
const setting::erased_args &args, const setting::erased_args &args,
const char *set_doc, const char *show_doc, const char *set_doc, const char *show_doc,
const char *help_doc, const char *help_doc,
@ -557,14 +563,16 @@ add_setshow_cmd_full_erased (const char *name,
full_set_doc = make_unique_xstrdup (set_doc); full_set_doc = make_unique_xstrdup (set_doc);
full_show_doc = make_unique_xstrdup (show_doc); full_show_doc = make_unique_xstrdup (show_doc);
} }
set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, args, set = add_set_or_show_cmd (name, set_cmd, theclass, var_type,
extra_literals, args,
full_set_doc.release (), set_list); full_set_doc.release (), set_list);
set->doc_allocated = 1; set->doc_allocated = 1;
if (set_func != NULL) if (set_func != NULL)
set->func = set_func; set->func = set_func;
show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, args, show = add_set_or_show_cmd (name, show_cmd, theclass, var_type,
extra_literals, args,
full_show_doc.release (), show_list); full_show_doc.release (), show_list);
show->doc_allocated = 1; show->doc_allocated = 1;
show->show_value_func = show_func; show->show_value_func = show_func;
@ -575,18 +583,82 @@ add_setshow_cmd_full_erased (const char *name,
return {set, show}; 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 command lists SET_LIST and SHOW_LIST. /* Add element named NAME to both command lists SET_LIST and SHOW_LIST.
THECLASS is as in add_cmd. VAR_TYPE is the kind of thing we are 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 setting. VAR is address of the variable being controlled by this
command. If nullptr is given as VAR, then both SET_SETTING_FUNC and command. EXTRA_LITERALS if non-NULL define extra literals to be
GET_SETTING_FUNC must be provided. SET_SETTING_FUNC and GET_SETTING_FUNC accepted in lieu of a number for integer variables. If nullptr is
are callbacks used to access and modify the underlying property, given as VAR, then both SET_SETTING_FUNC and GET_SETTING_FUNC must
whatever its storage is. SET_FUNC and SHOW_FUNC are the callback be provided. SET_SETTING_FUNC and GET_SETTING_FUNC are callbacks
functions (if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the 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. documentation strings.
Return the newly created set and show commands. */ 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,
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)
{
auto erased_args
= setting::erase_args (var_type, var,
set_setting_func, get_setting_func);
auto cmds = add_setshow_cmd_full_erased (name,
theclass,
var_type, extra_literals,
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> template<typename T>
static set_show_commands static set_show_commands
add_setshow_cmd_full (const char *name, add_setshow_cmd_full (const char *name,
@ -601,19 +673,10 @@ add_setshow_cmd_full (const char *name,
struct cmd_list_element **set_list, struct cmd_list_element **set_list,
struct cmd_list_element **show_list) struct cmd_list_element **show_list)
{ {
auto erased_args return add_setshow_cmd_full (name, theclass, var_type, var, nullptr,
= setting::erase_args (var_type, var, set_doc, show_doc, help_doc,
set_setting_func, get_setting_func); set_setting_func, get_setting_func,
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);
} }
/* Add element named NAME to command list LIST (the list for set or /* Add element named NAME to command list LIST (the list for set or
@ -982,31 +1045,61 @@ add_setshow_optional_filename_cmd (const char *name, command_class theclass,
return cmds; 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 /* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). THECLASS is as in list for set/show or some sublist thereof). THECLASS is as in
add_cmd. VAR is address of the variable which will contain the add_cmd. VAR is address of the variable which will contain the
value. SET_DOC and SHOW_DOC are the documentation strings. This value. SET_DOC and SHOW_DOC are the documentation strings. This
function is only used in Python API. Please don't use it elsewhere. */ function is only used in Python API. Please don't use it elsewhere. */
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", INT_MAX, 0 },
{ nullptr }
};
/* Same as above but using `integer_unlimited_literals', with a pointer
to a global storage buffer. */
set_show_commands set_show_commands
add_setshow_integer_cmd (const char *name, enum command_class theclass, add_setshow_integer_cmd (const char *name, enum command_class theclass,
int *var, int *var,
@ -1019,12 +1112,10 @@ add_setshow_integer_cmd (const char *name, enum command_class theclass,
{ {
set_show_commands commands set_show_commands commands
= add_setshow_cmd_full<int> (name, theclass, var_integer, var, = add_setshow_cmd_full<int> (name, theclass, var_integer, var,
integer_unlimited_literals,
set_doc, show_doc, help_doc, set_doc, show_doc, help_doc,
nullptr, nullptr, set_func, nullptr, nullptr, set_func,
show_func, set_list, show_list); show_func, set_list, show_list);
set_cmd_completer (commands.set, integer_unlimited_completer);
return commands; return commands;
} }
@ -1042,12 +1133,54 @@ add_setshow_integer_cmd (const char *name, command_class theclass,
cmd_list_element **show_list) cmd_list_element **show_list)
{ {
auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr, auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
integer_unlimited_literals,
set_doc, show_doc, help_doc, set_func, set_doc, show_doc, help_doc, set_func,
get_func, nullptr, show_func, set_list, get_func, nullptr, show_func, set_list,
show_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; return cmds;
} }
@ -1056,6 +1189,57 @@ add_setshow_integer_cmd (const char *name, command_class theclass,
add_cmd. VAR is address of the variable which will contain the add_cmd. VAR is address of the variable which will contain the
value. SET_DOC and SHOW_DOC are the documentation strings. */ value. SET_DOC and SHOW_DOC are the documentation strings. */
set_show_commands
add_setshow_uinteger_cmd (const char *name, enum 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,
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,
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_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)
{
auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
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 UINT_MAX. */
const literal_def uinteger_unlimited_literals[] =
{
{ "unlimited", UINT_MAX, 0 },
{ nullptr }
};
/* Same as above but using `uinteger_unlimited_literals', with a pointer
to a global storage buffer. */
set_show_commands set_show_commands
add_setshow_uinteger_cmd (const char *name, enum command_class theclass, add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
unsigned int *var, unsigned int *var,
@ -1068,12 +1252,10 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
{ {
set_show_commands commands set_show_commands commands
= add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var, = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
set_doc, show_doc, help_doc, uinteger_unlimited_literals,
nullptr, nullptr, set_func, set_doc, show_doc, help_doc, nullptr,
show_func, set_list, show_list); nullptr, set_func, show_func,
set_list, show_list);
set_cmd_completer (commands.set, integer_unlimited_completer);
return commands; return commands;
} }
@ -1091,13 +1273,12 @@ add_setshow_uinteger_cmd (const char *name, command_class theclass,
cmd_list_element **show_list) cmd_list_element **show_list)
{ {
auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
nullptr, set_doc, show_doc, nullptr,
help_doc, set_func, get_func, uinteger_unlimited_literals,
nullptr, show_func, set_list, set_doc, show_doc, help_doc,
set_func, get_func, nullptr,
show_func, set_list,
show_list); show_list);
set_cmd_completer (cmds.set, integer_unlimited_completer);
return cmds; return cmds;
} }
@ -1116,7 +1297,7 @@ add_setshow_zinteger_cmd (const char *name, enum command_class theclass,
struct cmd_list_element **set_list, struct cmd_list_element **set_list,
struct cmd_list_element **show_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, set_doc, show_doc, help_doc,
nullptr, nullptr, set_func, nullptr, nullptr, set_func,
show_func, set_list, show_list); show_func, set_list, show_list);
@ -1135,12 +1316,22 @@ add_setshow_zinteger_cmd (const char *name, command_class theclass,
cmd_list_element **set_list, cmd_list_element **set_list,
cmd_list_element **show_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, set_doc, show_doc, help_doc, set_func,
get_func, nullptr, show_func, set_list, get_func, nullptr, show_func, set_list,
show_list); show_list);
} }
/* Accept `unlimited' or -1, using -1 internally. */
const literal_def pinteger_unlimited_literals[] =
{
{ "unlimited", -1, -1 },
{ nullptr }
};
/* Same as above but using `pinteger_unlimited_literals', with a pointer
to a global storage buffer. */
set_show_commands set_show_commands
add_setshow_zuinteger_unlimited_cmd (const char *name, add_setshow_zuinteger_unlimited_cmd (const char *name,
enum command_class theclass, enum command_class theclass,
@ -1154,13 +1345,11 @@ add_setshow_zuinteger_unlimited_cmd (const char *name,
struct cmd_list_element **show_list) struct cmd_list_element **show_list)
{ {
set_show_commands commands 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,
pinteger_unlimited_literals,
set_doc, show_doc, help_doc, nullptr, set_doc, show_doc, help_doc, nullptr,
nullptr, set_func, show_func, set_list, nullptr, set_func, show_func, set_list,
show_list); show_list);
set_cmd_completer (commands.set, integer_unlimited_completer);
return commands; return commands;
} }
@ -1178,13 +1367,11 @@ add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass,
cmd_list_element **show_list) cmd_list_element **show_list)
{ {
auto cmds auto cmds
= add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited, = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr,
nullptr, set_doc, show_doc, help_doc, set_func, pinteger_unlimited_literals,
set_doc, show_doc, help_doc, set_func,
get_func, nullptr, show_func, set_list, get_func, nullptr, show_func, set_list,
show_list); show_list);
set_cmd_completer (cmds.set, integer_unlimited_completer);
return cmds; return cmds;
} }
@ -1203,7 +1390,7 @@ add_setshow_zuinteger_cmd (const char *name, enum command_class theclass,
struct cmd_list_element **set_list, struct cmd_list_element **set_list,
struct cmd_list_element **show_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, var, set_doc, show_doc, help_doc,
nullptr, nullptr, set_func, nullptr, nullptr, set_func,
show_func, set_list, show_list); show_func, set_list, show_list);
@ -1222,7 +1409,7 @@ add_setshow_zuinteger_cmd (const char *name, command_class theclass,
cmd_list_element **set_list, cmd_list_element **set_list,
cmd_list_element **show_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, nullptr, set_doc, show_doc,
help_doc, set_func, get_func, help_doc, set_func, get_func,
nullptr, show_func, set_list, nullptr, show_func, set_list,

View file

@ -38,7 +38,7 @@ union option_value
/* For var_uinteger options. */ /* For var_uinteger options. */
unsigned int uinteger; unsigned int uinteger;
/* For var_zuinteger_unlimited options. */ /* For var_integer and var_pinteger options. */
int integer; int integer;
/* For var_enum options. */ /* For var_enum options. */
@ -356,42 +356,52 @@ parse_option (gdb::array_view<const option_def_group> options_group,
return option_def_and_value {*match, match_ctx, val}; return option_def_and_value {*match, match_ctx, val};
} }
case var_uinteger: case var_uinteger:
case var_zuinteger_unlimited: case var_integer:
case var_pinteger:
{ {
if (completion != nullptr) if (completion != nullptr && match->extra_literals != nullptr)
{ {
/* 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') 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 completion->tracker.add_completion
(make_unique_xstrdup ("NUMBER")); (make_unique_xstrdup ("NUMBER"));
completion->tracker.add_completion for (const literal_def *l = match->extra_literals;
(make_unique_xstrdup ("unlimited")); l->literal != nullptr;
l++)
completion->tracker.add_completion
(make_unique_xstrdup (l->literal));
return {}; return {};
} }
else if (startswith ("unlimited", *args)) else
{ {
completion->tracker.add_completion bool completions = false;
(make_unique_xstrdup ("unlimited")); for (const literal_def *l = match->extra_literals;
return {}; 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) LONGEST v = parse_cli_var_integer (match->type,
{ match->extra_literals,
option_value val; args, false);
val.integer = parse_cli_var_zuinteger_unlimited (args, false); option_value val;
return option_def_and_value {*match, match_ctx, val}; if (match->type == var_uinteger)
} val.uinteger = v;
else else
{ val.integer = v;
option_value val; return option_def_and_value {*match, match_ctx, val};
val.uinteger = parse_cli_var_uinteger (match->type, args, false);
return option_def_and_value {*match, match_ctx, val};
}
} }
case var_enum: case var_enum:
{ {
@ -593,7 +603,8 @@ save_option_value_in_ctx (gdb::optional<option_def_and_value> &ov)
*ov->option.var_address.uinteger (ov->option, ov->ctx) *ov->option.var_address.uinteger (ov->option, ov->ctx)
= ov->value->uinteger; = ov->value->uinteger;
break; break;
case var_zuinteger_unlimited: case var_integer:
case var_pinteger:
*ov->option.var_address.integer (ov->option, ov->ctx) *ov->option.var_address.integer (ov->option, ov->ctx)
= ov->value->integer; = ov->value->integer;
break; break;
@ -664,8 +675,20 @@ get_val_type_str (const option_def &opt, std::string &buffer)
case var_boolean: case var_boolean:
return "[on|off]"; return "[on|off]";
case var_uinteger: case var_uinteger:
case var_zuinteger_unlimited: case var_integer:
return "NUMBER|unlimited"; 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: case var_enum:
{ {
buffer = ""; buffer = "";
@ -789,20 +812,31 @@ add_setshow_cmds_for_options (command_class cmd_class,
{ {
add_setshow_uinteger_cmd (option.name, cmd_class, add_setshow_uinteger_cmd (option.name, cmd_class,
option.var_address.uinteger (option, data), option.var_address.uinteger (option, data),
option.extra_literals,
option.set_doc, option.show_doc, option.set_doc, option.show_doc,
option.help_doc, option.help_doc,
nullptr, option.show_cmd_cb, nullptr, option.show_cmd_cb,
set_list, show_list); set_list, show_list);
} }
else if (option.type == var_zuinteger_unlimited) else if (option.type == var_integer)
{ {
add_setshow_zuinteger_unlimited_cmd add_setshow_integer_cmd (option.name, cmd_class,
(option.name, cmd_class, option.var_address.integer (option, data),
option.var_address.integer (option, data), option.extra_literals,
option.set_doc, option.show_doc, option.set_doc, option.show_doc,
option.help_doc, option.help_doc,
nullptr, option.show_cmd_cb, nullptr, option.show_cmd_cb,
set_list, show_list); 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) else if (option.type == var_enum)
{ {

View file

@ -49,12 +49,13 @@ protected:
used to create the option's "set/show" commands. */ used to create the option's "set/show" commands. */
constexpr option_def (const char *name_, constexpr option_def (const char *name_,
var_types var_type_, var_types var_type_,
const literal_def *extra_literals_,
erased_get_var_address_ftype *erased_get_var_address_, erased_get_var_address_ftype *erased_get_var_address_,
show_value_ftype *show_cmd_cb_, show_value_ftype *show_cmd_cb_,
const char *set_doc_, const char *set_doc_,
const char *show_doc_, const char *show_doc_,
const char *help_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_), erased_get_var_address (erased_get_var_address_),
var_address {}, var_address {},
show_cmd_cb (show_cmd_cb_), show_cmd_cb (show_cmd_cb_),
@ -68,6 +69,9 @@ public:
/* The option's type. */ /* The option's type. */
var_types 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 /* A function that gets the controlling variable's address, type
erased. */ erased. */
erased_get_var_address_ftype *erased_get_var_address; 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 *set_doc_,
const char *show_doc_ = nullptr, const char *show_doc_ = nullptr,
const char *help_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_, (erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_, show_cmd_cb_,
set_doc_, show_doc_, help_doc_) set_doc_, show_doc_, help_doc_)
@ -207,37 +211,59 @@ struct uinteger_option_def : option_def
{ {
uinteger_option_def (const char *long_option_, uinteger_option_def (const char *long_option_,
unsigned int *(*get_var_address_cb_) (Context *), unsigned int *(*get_var_address_cb_) (Context *),
const literal_def *extra_literals_,
show_value_ftype *show_cmd_cb_, show_value_ftype *show_cmd_cb_,
const char *set_doc_, const char *set_doc_,
const char *show_doc_ = nullptr, const char *show_doc_ = nullptr,
const char *help_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_, (erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_, show_cmd_cb_,
set_doc_, show_doc_, help_doc_) set_doc_, show_doc_, help_doc_)
{ {
var_address.uinteger = detail::get_var_address<unsigned int, Context>; var_address.uinteger = detail::get_var_address<unsigned int, Context>;
} }
uinteger_option_def (const char *long_option_,
unsigned 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)
: uinteger_option_def (long_option_, get_var_address_cb_, nullptr,
show_cmd_cb_, set_doc_, show_doc_, help_doc_)
{ /* Nothing. */ }
}; };
/* A var_zuinteger_unlimited command line option. */ /* A var_pinteger command line option. */
template<typename Context> template<typename Context>
struct zuinteger_unlimited_option_def : option_def struct pinteger_option_def : option_def
{ {
zuinteger_unlimited_option_def (const char *long_option_, pinteger_option_def (const char *long_option_,
int *(*get_var_address_cb_) (Context *), int *(*get_var_address_cb_) (Context *),
show_value_ftype *show_cmd_cb_, const literal_def *extra_literals_,
const char *set_doc_, show_value_ftype *show_cmd_cb_,
const char *show_doc_ = nullptr, const char *set_doc_,
const char *help_doc_ = nullptr) const char *show_doc_ = nullptr,
: option_def (long_option_, var_zuinteger_unlimited, const char *help_doc_ = nullptr)
: option_def (long_option_, var_pinteger, extra_literals_,
(erased_get_var_address_ftype *) get_var_address_cb_, (erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_, show_cmd_cb_,
set_doc_, show_doc_, help_doc_) set_doc_, show_doc_, help_doc_)
{ {
var_address.integer = detail::get_var_address<int, Context>; var_address.integer = detail::get_var_address<int, Context>;
} }
pinteger_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)
: pinteger_option_def (long_option_, get_var_address_cb_, nullptr,
show_cmd_cb_, set_doc_, show_doc_, help_doc_)
{ /* Nothing. */ }
}; };
/* An var_enum command line option. */ /* An var_enum command line option. */
@ -252,7 +278,7 @@ struct enum_option_def : option_def
const char *set_doc_, const char *set_doc_,
const char *show_doc_ = nullptr, const char *show_doc_ = nullptr,
const char *help_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_, (erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_, show_cmd_cb_,
set_doc_, show_doc_, help_doc_) set_doc_, show_doc_, help_doc_)
@ -273,7 +299,7 @@ struct string_option_def : option_def
const char *set_doc_, const char *set_doc_,
const char *show_doc_ = nullptr, const char *show_doc_ = nullptr,
const char *help_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_, (erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_, show_cmd_cb_,
set_doc_, show_doc_, help_doc_) set_doc_, show_doc_, help_doc_)

View file

@ -149,10 +149,11 @@ deprecated_show_value_hack (struct ui_file *ignore_file,
} }
} }
/* Returns true if ARG is "unlimited". */ /* Returns true and the value in VAL if ARG is an accepted literal. */
static bool 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); *arg = skip_spaces (*arg);
@ -162,85 +163,104 @@ is_unlimited_literal (const char **arg, bool expression)
size_t len = p - *arg; size_t len = p - *arg;
if (len > 0 && strncmp ("unlimited", *arg, len) == 0) if (len > 0 && extra_literals != nullptr)
{ for (const literal_def *l = extra_literals;
*arg += len; l->literal != nullptr;
l++)
/* If parsing an expression (i.e., parsing for a "set" command), if (strncmp (l->literal, *arg, len) == 0)
anything after "unlimited" is junk. For options, anything
after "unlimited" might be a command argument or another
option. */
if (expression)
{ {
const char *after = skip_spaces (*arg); *arg += len;
if (*after != '\0')
error (_("Junk after \"%.*s\": %s"),
(int) len, unl_start, after);
}
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; return false;
} }
/* See cli-setshow.h. */ /* See cli-setshow.h. */
unsigned int LONGEST
parse_cli_var_uinteger (var_types var_type, const char **arg, parse_cli_var_integer (var_types var_type, const literal_def *extra_literals,
bool expression) const char **arg, bool expression)
{ {
LONGEST val; LONGEST val;
if (*arg == nullptr || **arg == '\0') if (*arg == nullptr || **arg == '\0')
{ {
if (var_type == var_uinteger) if (extra_literals == nullptr)
error_no_arg (_("integer to set it to, or \"unlimited\""));
else
error_no_arg (_("integer to set it to")); error_no_arg (_("integer to set it to"));
else
{
std::string buffer = "";
size_t count = 0;
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 (var_type == var_uinteger && is_unlimited_literal (arg, expression)) if (!get_literal_val (val, extra_literals, arg, expression))
val = 0; {
else if (expression) if (expression)
val = parse_and_eval_long (*arg); val = parse_and_eval_long (*arg);
else else
val = get_ulongest (arg); val = get_ulongest (arg);
if (var_type == var_uinteger && val == 0) enum tribool allowed = TRIBOOL_UNKNOWN;
val = UINT_MAX; if (extra_literals != nullptr)
else if (val < 0 {
/* For var_uinteger, don't let the user set the value for (const literal_def *l = extra_literals;
to UINT_MAX directly, as that exposes an l->literal != nullptr;
implementation detail to the user interface. */ l++)
|| (var_type == var_uinteger && val >= UINT_MAX) if (l->val.has_value () && val == *l->val)
|| (var_type == var_zuinteger && val > UINT_MAX)) {
error (_("integer %s out of range"), plongest (val)); allowed = TRIBOOL_TRUE;
val = l->use;
break;
}
else if (val == l->use)
allowed = TRIBOOL_FALSE;
}
return val; if (allowed == TRIBOOL_UNKNOWN)
} {
if (val > UINT_MAX || val < INT_MIN
/* See cli-setshow.h. */ || (var_type == var_uinteger && val < 0)
|| (var_type == var_integer && val > INT_MAX)
int || (var_type == var_pinteger && val < 0)
parse_cli_var_zuinteger_unlimited (const char **arg, bool expression) || (var_type == var_pinteger && val > INT_MAX))
{ allowed = TRIBOOL_FALSE;
LONGEST val; }
if (allowed == TRIBOOL_FALSE)
if (*arg == nullptr || **arg == '\0') error (_("integer %s out of range"), plongest (val));
error_no_arg (_("integer to set it to, or \"unlimited\"")); }
if (is_unlimited_literal (arg, expression))
val = -1;
else if (expression)
val = parse_and_eval_long (*arg);
else
val = get_ulongest (arg);
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"));
return val; return val;
} }
@ -405,41 +425,18 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
option_changed = c->var->set<enum auto_boolean> (parse_auto_binary_operation (arg)); option_changed = c->var->set<enum auto_boolean> (parse_auto_binary_operation (arg));
break; break;
case var_uinteger: case var_uinteger:
case var_zuinteger:
option_changed option_changed
= c->var->set<unsigned int> (parse_cli_var_uinteger (c->var->type (), = c->var->set<unsigned int> (parse_cli_var_integer (c->var->type (),
&arg, true)); c->var->
extra_literals (),
&arg, true));
break; break;
case var_integer: case var_integer:
case var_zinteger: case var_pinteger:
{ option_changed
LONGEST val; = c->var->set<int> (parse_cli_var_integer (c->var->type (),
c->var->extra_literals (),
if (*arg == '\0') &arg, true));
{
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);
}
break; break;
case var_enum: case var_enum:
{ {
@ -454,10 +451,6 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
option_changed = c->var->set<const char *> (match); option_changed = c->var->set<const char *> (match);
} }
break; break;
case var_zuinteger_unlimited:
option_changed = c->var->set<int>
(parse_cli_var_zuinteger_unlimited (&arg, true));
break;
default: default:
error (_("gdb internal error: bad var_type in do_setshow_command")); error (_("gdb internal error: bad var_type in do_setshow_command"));
} }
@ -551,7 +544,6 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
} }
break; break;
case var_uinteger: case var_uinteger:
case var_zuinteger:
{ {
char s[64]; char s[64];
@ -560,8 +552,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c)
} }
break; break;
case var_integer: case var_integer:
case var_zinteger: case var_pinteger:
case var_zuinteger_unlimited:
{ {
char s[64]; char s[64];
@ -623,36 +614,32 @@ get_setshow_command_value_string (const setting &var)
} }
break; break;
case var_uinteger: 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_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 if (var.extra_literals () != nullptr)
&& value == INT_MAX) for (const literal_def *l = var.extra_literals ();
stb.puts ("unlimited"); l->literal != nullptr;
else l++)
stb.printf ("%d", value); if (value == l->use)
} {
break; stb.puts (l->literal);
case var_zuinteger_unlimited: printed = true;
{ break;
const int value = var.get<int> (); }
if (value == -1) if (!printed)
stb.puts ("unlimited"); {
else if (var.type () == var_uinteger)
stb.printf ("%d", value); stb.printf ("%u", static_cast<unsigned int> (value));
else
stb.printf ("%d", static_cast<int> (value));
}
} }
break; break;
default: default:

View file

@ -29,21 +29,19 @@ extern int parse_cli_boolean_value (const char *arg);
past a successfully parsed value. */ past a successfully parsed value. */
extern int parse_cli_boolean_value (const char **arg); extern int parse_cli_boolean_value (const char **arg);
/* Parse ARG, an option to a var_uinteger or var_zuinteger variable. /* Parse ARG, an option to a var_uinteger, var_integer or var_pinteger
Either returns the parsed value on success or throws an error. If variable. Return the parsed value on success or throw an error. If
EXPRESSION is true, *ARG is parsed as an expression; otherwise, it EXTRA_LITERALS is non-null, then interpret those literals accordingly.
is parsed with get_ulongest. It's not possible to parse the 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 as an expression when there may be valid input after the
integer, such as when parsing command options. E.g., "print integer, such as when parsing command options. E.g., "print
-elements NUMBER -obj --". In such case, parsing as an expression -elements NUMBER -obj --". In such case, parsing as an expression
would parse "-obj --" as part of the expression as well. */ would parse "-obj --" as part of the expression as well. */
extern unsigned int parse_cli_var_uinteger (var_types var_type, extern LONGEST parse_cli_var_integer (var_types var_type,
const char **arg, const literal_def *extra_literals,
bool expression); 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);
/* Parse ARG, an option to a var_enum variable. ENUM is a /* Parse ARG, an option to a var_enum variable. ENUM is a
null-terminated array of possible values. Either returns the parsed null-terminated array of possible values. Either returns the parsed

View file

@ -84,16 +84,18 @@ enum var_types
value. */ value. */
var_auto_boolean, var_auto_boolean,
/* Unsigned Integer. *VAR is an unsigned int. The user can type /* Unsigned Integer. *VAR is an unsigned int. In the Guile and Python
0 to mean "unlimited", which is stored in *VAR as UINT_MAX. */ APIs 0 means unlimited, which is stored in *VAR as UINT_MAX. */
var_uinteger, var_uinteger,
/* Like var_uinteger but signed. *VAR is an int. The user can /* Like var_uinteger but signed. *VAR is an int. In the Guile and
type 0 to mean "unlimited", which is stored in *VAR as Python APIs 0 means unlimited, which is stored in *VAR as INT_MAX. */
INT_MAX. The only remaining use of it is the Python API.
Don't use it elsewhere. */
var_integer, 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 /* String which the user enters with escapes (e.g. the user types
\n and it is a real newline in the stored string). \n and it is a real newline in the stored string).
*VAR is a std::string, "" if the string is empty. */ *VAR is a std::string, "" if the string is empty. */
@ -106,22 +108,27 @@ enum var_types
var_optional_filename, var_optional_filename,
/* String which stores a filename. (*VAR) is a std::string. */ /* String which stores a filename. (*VAR) is a std::string. */
var_filename, var_filename,
/* ZeroableInteger. *VAR is an int. Like var_integer except
that zero really means zero. */
var_zinteger,
/* ZeroableUnsignedInteger. *VAR is an unsigned int. Zero really
means zero. */
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. */
var_zuinteger_unlimited,
/* Enumerated type. Can only have one of the specified values. /* Enumerated type. Can only have one of the specified values.
*VAR is a char pointer to the name of the element that we *VAR is a char pointer to the name of the element that we
find. */ find. */
var_enum var_enum
}; };
/* A structure describing an extra literal accepted and shown in place
of a number. */
struct literal_def
{
/* The literal to define, e.g. "unlimited". */
const char *literal;
/* The number to substitute internally for LITERAL or VAL;
the use of this number is not allowed (unless the same as VAL). */
LONGEST use;
/* An optional number accepted that stands for the literal. */
gdb::optional<LONGEST> val;
};
/* Return true if a setting of type VAR_TYPE is backed with type T. /* Return true if a setting of type VAR_TYPE is backed with type T.
This function is left without definition intentionally. This template is This function is left without definition intentionally. This template is
@ -152,15 +159,14 @@ inline bool var_type_uses<enum auto_boolean> (var_types t)
template<> template<>
inline bool var_type_uses<unsigned int> (var_types t) 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. */ /* Return true if a setting of type T is backed by an int variable. */
template<> template<>
inline bool var_type_uses<int> (var_types t) inline bool var_type_uses<int> (var_types t)
{ {
return (t == var_integer || t == var_zinteger return t == var_integer || t == var_pinteger;
|| t == var_zuinteger_unlimited);
} }
/* Return true if a setting of type T is backed by a std::string variable. */ /* Return true if a setting of type T is backed by a std::string variable. */
@ -218,8 +224,9 @@ struct setting
Type T must match the var type VAR_TYPE (see VAR_TYPE_USES). */ Type T must match the var type VAR_TYPE (see VAR_TYPE_USES). */
template<typename T> template<typename T>
setting (var_types var_type, T *var) setting (var_types var_type, T *var,
: m_var_type (var_type), m_var (var) const literal_def *extra_literals = nullptr)
: m_var_type (var_type), m_var (var), m_extra_literals (extra_literals)
{ {
gdb_assert (var != nullptr); gdb_assert (var != nullptr);
gdb_assert (var_type_uses<T> (var_type)); gdb_assert (var_type_uses<T> (var_type));
@ -258,12 +265,14 @@ struct setting
}; };
} }
/* Create a setting backed by pre-validated type-erased args. /* Create a setting backed by pre-validated type-erased args and using
ERASED_VAR's fields' real types must match the var type VAR_TYPE EXTRA_LITERALS. ERASED_VAR's fields' real types must match the var
(see VAR_TYPE_USES). */ type VAR_TYPE (see VAR_TYPE_USES). */
setting (var_types var_type, const erased_args &args) setting (var_types var_type, const literal_def *extra_literals,
const erased_args &args)
: m_var_type (var_type), : m_var_type (var_type),
m_var (args.var), m_var (args.var),
m_extra_literals (extra_literals),
m_getter (args.getter), m_getter (args.getter),
m_setter (args.setter) m_setter (args.setter)
{ {
@ -294,6 +303,10 @@ struct setting
var_types type () const var_types type () const
{ return m_var_type; } { return m_var_type; }
/* Access any extra literals accepted. */
const literal_def *extra_literals () const
{ return m_extra_literals; }
/* Return the current value. /* Return the current value.
The template parameter T is the type of the variable used to store the The template parameter T is the type of the variable used to store the
@ -356,6 +369,9 @@ private:
non-nullptr. */ non-nullptr. */
void *m_var = nullptr; void *m_var = nullptr;
/* Any extra literals accepted. */
const literal_def *m_extra_literals = nullptr;
/* Pointer to a user provided getter. */ /* Pointer to a user provided getter. */
erased_func m_getter = nullptr; erased_func m_getter = nullptr;
@ -651,6 +667,11 @@ typedef void (show_value_ftype) (struct ui_file *file,
instead print the value out directly. */ instead print the value out directly. */
extern show_value_ftype deprecated_show_value_hack; 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 pinteger_unlimited_literals[];
extern set_show_commands add_setshow_enum_cmd extern set_show_commands add_setshow_enum_cmd
(const char *name, command_class theclass, const char *const *enumlist, (const char *name, command_class theclass, const char *const *enumlist,
const char **var, const char *set_doc, const char *show_doc, const char **var, const char *set_doc, const char *show_doc,
@ -746,6 +767,20 @@ extern set_show_commands add_setshow_optional_filename_cmd
show_value_ftype *show_func, cmd_list_element **set_list, show_value_ftype *show_func, cmd_list_element **set_list,
cmd_list_element **show_list); 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 extern set_show_commands add_setshow_integer_cmd
(const char *name, command_class theclass, int *var, const char *set_doc, (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, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func,
@ -759,6 +794,34 @@ extern set_show_commands add_setshow_integer_cmd
setting_func_types<int>::get get_func, show_value_ftype *show_func, setting_func_types<int>::get get_func, show_value_ftype *show_func,
cmd_list_element **set_list, cmd_list_element **show_list); 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 extern set_show_commands add_setshow_uinteger_cmd
(const char *name, command_class theclass, unsigned int *var, (const char *name, command_class theclass, unsigned int *var,
const char *set_doc, const char *show_doc, const char *help_doc, const char *set_doc, const char *show_doc, const char *help_doc,

View file

@ -4611,14 +4611,18 @@ Python, true and false are represented using boolean constants, and
@findex PARAM_UINTEGER @findex PARAM_UINTEGER
@findex gdb.PARAM_UINTEGER @findex gdb.PARAM_UINTEGER
@item gdb.PARAM_UINTEGER @item gdb.PARAM_UINTEGER
The value is an unsigned integer. The value of 0 should be The value is an unsigned integer. The value of @code{None} should be
interpreted to mean ``unlimited''. interpreted to mean ``unlimited'' (literal @code{'unlimited'} can also
be used to set that value), and the value of 0 is reserved and should
not be used.
@findex PARAM_INTEGER @findex PARAM_INTEGER
@findex gdb.PARAM_INTEGER @findex gdb.PARAM_INTEGER
@item gdb.PARAM_INTEGER @item gdb.PARAM_INTEGER
The value is a signed integer. The value of 0 should be interpreted The value is a signed integer. The value of @code{None} should be
to mean ``unlimited''. interpreted to mean ``unlimited'' (literal @code{'unlimited'} can also
be used to set that value), and the value of 0 is reserved and should
not be used.
@findex PARAM_STRING @findex PARAM_STRING
@findex gdb.PARAM_STRING @findex gdb.PARAM_STRING
@ -4648,21 +4652,23 @@ The value is a filename. This is just like
@findex PARAM_ZINTEGER @findex PARAM_ZINTEGER
@findex gdb.PARAM_ZINTEGER @findex gdb.PARAM_ZINTEGER
@item gdb.PARAM_ZINTEGER @item gdb.PARAM_ZINTEGER
The value is an integer. This is like @code{PARAM_INTEGER}, except 0 The value is a signed integer. This is like @code{PARAM_INTEGER},
is interpreted as itself. except that 0 is allowed and the value of @code{None} is not supported.
@findex PARAM_ZUINTEGER @findex PARAM_ZUINTEGER
@findex gdb.PARAM_ZUINTEGER @findex gdb.PARAM_ZUINTEGER
@item gdb.PARAM_ZUINTEGER @item gdb.PARAM_ZUINTEGER
The value is an unsigned integer. This is like @code{PARAM_INTEGER}, The value is an unsigned integer. This is like @code{PARAM_UINTEGER},
except 0 is interpreted as itself, and the value cannot be negative. except that 0 is allowed and the value of @code{None} is not supported.
@findex PARAM_ZUINTEGER_UNLIMITED @findex PARAM_ZUINTEGER_UNLIMITED
@findex gdb.PARAM_ZUINTEGER_UNLIMITED @findex gdb.PARAM_ZUINTEGER_UNLIMITED
@item gdb.PARAM_ZUINTEGER_UNLIMITED @item gdb.PARAM_ZUINTEGER_UNLIMITED
The value is a signed integer. This is like @code{PARAM_ZUINTEGER}, The value is a signed integer. This is like @code{PARAM_INTEGER}
except the special value -1 should be interpreted to mean including that the value of @code{None} should be interpreted to mean
``unlimited''. Other negative values are not allowed. ``unlimited'' (literal @code{'unlimited'} can also be used to set that
value), except that 0 is allowed, and the value cannot be negative,
except the special value -1 is returned for the setting of ``unlimited''.
@findex PARAM_ENUM @findex PARAM_ENUM
@findex gdb.PARAM_ENUM @findex gdb.PARAM_ENUM

View file

@ -75,9 +75,15 @@ struct param_smob
/* One of the COMMAND_* constants. */ /* One of the COMMAND_* constants. */
enum command_class cmd_class; enum command_class cmd_class;
/* Guile parameter type name. */
const char *pname;
/* The type of the parameter. */ /* The type of the parameter. */
enum var_types type; enum var_types type;
/* Extra literals, such as `unlimited', accepted in lieu of a number. */
const literal_def *extra_literals;
/* The docs for the parameter. */ /* The docs for the parameter. */
char *set_doc; char *set_doc;
char *show_doc; char *show_doc;
@ -110,6 +116,49 @@ struct param_smob
SCM containing_scm; SCM containing_scm;
}; };
/* Guile parameter types as in PARAMETER_TYPES later on. */
enum param_types
{
param_boolean,
param_auto_boolean,
param_zinteger,
param_uinteger,
param_zuinteger,
param_zuinteger_unlimited,
param_string,
param_string_noescape,
param_optional_filename,
param_filename,
param_enum,
};
/* Translation from Guile parameters to GDB variable types. Keep in the
same order as PARAM_TYPES due to C++'s lack of designated initializers. */
static const struct
{
/* The type of the parameter. */
enum var_types type;
/* Extra literals, such as `unlimited', accepted in lieu of a number. */
const literal_def *extra_literals;
}
param_to_var[] =
{
{ var_boolean },
{ var_auto_boolean },
{ var_integer },
{ var_uinteger, uinteger_unlimited_literals },
{ var_uinteger },
{ var_pinteger, pinteger_unlimited_literals },
{ var_string },
{ var_string_noescape },
{ var_optional_filename },
{ var_filename },
{ var_enum }
};
/* Wraps a setting around an existing param_smob. This abstraction /* Wraps a setting around an existing param_smob. This abstraction
is used to manipulate the value in S->VALUE in a type safe manner using is used to manipulate the value in S->VALUE in a type safe manner using
the setting interface. */ the setting interface. */
@ -117,18 +166,20 @@ struct param_smob
static setting static setting
make_setting (param_smob *s) make_setting (param_smob *s)
{ {
if (var_type_uses<bool> (s->type)) enum var_types type = s->type;
return setting (s->type, &s->value.boolval);
else if (var_type_uses<int> (s->type)) if (var_type_uses<bool> (type))
return setting (s->type, &s->value.intval); return setting (type, &s->value.boolval);
else if (var_type_uses<auto_boolean> (s->type)) else if (var_type_uses<int> (type))
return setting (s->type, &s->value.autoboolval); return setting (type, &s->value.intval, s->extra_literals);
else if (var_type_uses<unsigned int> (s->type)) else if (var_type_uses<auto_boolean> (type))
return setting (s->type, &s->value.uintval); return setting (type, &s->value.autoboolval);
else if (var_type_uses<std::string> (s->type)) else if (var_type_uses<unsigned int> (type))
return setting (s->type, s->value.stringval); return setting (type, &s->value.uintval, s->extra_literals);
else if (var_type_uses<const char *> (s->type)) else if (var_type_uses<std::string> (type))
return setting (s->type, &s->value.cstringval); return setting (type, s->value.stringval);
else if (var_type_uses<const char *> (type))
return setting (type, &s->value.cstringval);
else else
gdb_assert_not_reached ("unhandled var type"); gdb_assert_not_reached ("unhandled var type");
} }
@ -149,10 +200,9 @@ static SCM set_doc_keyword;
static SCM show_doc_keyword; static SCM show_doc_keyword;
static SCM initial_value_keyword; static SCM initial_value_keyword;
static SCM auto_keyword; static SCM auto_keyword;
static SCM unlimited_keyword;
static int pascm_is_valid (param_smob *); static int pascm_is_valid (param_smob *);
static const char *pascm_param_type_name (enum var_types type); static const char *pascm_param_type_name (enum param_types type);
static SCM pascm_param_value (const setting &var, int arg_pos, static SCM pascm_param_value (const setting &var, int arg_pos,
const char *func_name); const char *func_name);
@ -171,7 +221,7 @@ pascm_print_param_smob (SCM self, SCM port, scm_print_state *pstate)
if (! pascm_is_valid (p_smob)) if (! pascm_is_valid (p_smob))
scm_puts (" {invalid}", port); scm_puts (" {invalid}", port);
gdbscm_printf (port, " %s ", pascm_param_type_name (p_smob->type)); gdbscm_printf (port, " %s ", p_smob->pname);
value = pascm_param_value (make_setting (p_smob), GDBSCM_ARG_NONE, NULL); value = pascm_param_value (make_setting (p_smob), GDBSCM_ARG_NONE, NULL);
scm_display (value, port); scm_display (value, port);
@ -369,7 +419,9 @@ pascm_show_func (struct ui_file *file, int from_tty,
function. */ function. */
static set_show_commands static set_show_commands
add_setshow_generic (enum var_types param_type, enum command_class cmd_class, add_setshow_generic (enum var_types param_type,
const literal_def *extra_literals,
enum command_class cmd_class,
char *cmd_name, param_smob *self, char *cmd_name, param_smob *self,
char *set_doc, char *show_doc, char *help_doc, char *set_doc, char *show_doc, char *help_doc,
cmd_func_ftype *set_func, cmd_func_ftype *set_func,
@ -398,34 +450,28 @@ add_setshow_generic (enum var_types param_type, enum command_class cmd_class,
case var_uinteger: case var_uinteger:
commands = add_setshow_uinteger_cmd (cmd_name, cmd_class, commands = add_setshow_uinteger_cmd (cmd_name, cmd_class,
&self->value.uintval, set_doc, &self->value.uintval,
extra_literals, set_doc,
show_doc, help_doc, set_func, show_doc, help_doc, set_func,
show_func, set_list, show_list); show_func, set_list, show_list);
break; break;
case var_zinteger: case var_integer:
commands = add_setshow_zinteger_cmd (cmd_name, cmd_class, commands = add_setshow_integer_cmd (cmd_name, cmd_class,
&self->value.intval, set_doc, &self->value.intval,
extra_literals, set_doc,
show_doc, help_doc, set_func,
show_func, set_list, show_list);
break;
case var_pinteger:
commands = add_setshow_pinteger_cmd (cmd_name, cmd_class,
&self->value.intval,
extra_literals, set_doc,
show_doc, help_doc, set_func, show_doc, help_doc, set_func,
show_func, set_list, show_list); show_func, set_list, show_list);
break; break;
case var_zuinteger:
commands = add_setshow_zuinteger_cmd (cmd_name, cmd_class,
&self->value.uintval, set_doc,
show_doc, help_doc, set_func,
show_func, set_list, show_list);
break;
case var_zuinteger_unlimited:
commands = add_setshow_zuinteger_unlimited_cmd (cmd_name, cmd_class,
&self->value.intval,
set_doc, show_doc,
help_doc, set_func,
show_func, set_list,
show_list);
break;
case var_string: case var_string:
commands = add_setshow_string_cmd (cmd_name, cmd_class, commands = add_setshow_string_cmd (cmd_name, cmd_class,
self->value.stringval, set_doc, self->value.stringval, set_doc,
@ -532,19 +578,17 @@ compute_enum_list (SCM enum_values_scm, int arg_pos, const char *func_name)
static const scheme_integer_constant parameter_types[] = static const scheme_integer_constant parameter_types[] =
{ {
/* Note: var_integer is deprecated, and intentionally does not { "PARAM_BOOLEAN", param_boolean }, /* ARI: param_boolean */
appear here. */ { "PARAM_AUTO_BOOLEAN", param_auto_boolean },
{ "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */ { "PARAM_ZINTEGER", param_zinteger },
{ "PARAM_AUTO_BOOLEAN", var_auto_boolean }, { "PARAM_UINTEGER", param_uinteger },
{ "PARAM_ZINTEGER", var_zinteger }, { "PARAM_ZUINTEGER", param_zuinteger },
{ "PARAM_UINTEGER", var_uinteger }, { "PARAM_ZUINTEGER_UNLIMITED", param_zuinteger_unlimited },
{ "PARAM_ZUINTEGER", var_zuinteger }, { "PARAM_STRING", param_string },
{ "PARAM_ZUINTEGER_UNLIMITED", var_zuinteger_unlimited }, { "PARAM_STRING_NOESCAPE", param_string_noescape },
{ "PARAM_STRING", var_string }, { "PARAM_OPTIONAL_FILENAME", param_optional_filename },
{ "PARAM_STRING_NOESCAPE", var_string_noescape }, { "PARAM_FILENAME", param_filename },
{ "PARAM_OPTIONAL_FILENAME", var_optional_filename }, { "PARAM_ENUM", param_enum },
{ "PARAM_FILENAME", var_filename },
{ "PARAM_ENUM", var_enum },
END_INTEGER_CONSTANTS END_INTEGER_CONSTANTS
}; };
@ -568,7 +612,7 @@ pascm_valid_parameter_type_p (int param_type)
/* Return PARAM_TYPE as a string. */ /* Return PARAM_TYPE as a string. */
static const char * static const char *
pascm_param_type_name (enum var_types param_type) pascm_param_type_name (enum param_types param_type)
{ {
int i; int i;
@ -588,10 +632,6 @@ pascm_param_type_name (enum var_types param_type)
static SCM static SCM
pascm_param_value (const setting &var, int arg_pos, const char *func_name) 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 ()) switch (var.type ())
{ {
case var_string: case var_string:
@ -631,20 +671,29 @@ pascm_param_value (const setting &var, int arg_pos, const char *func_name)
return auto_keyword; 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: case var_uinteger:
if (var.get<unsigned int> ()== UINT_MAX) case var_integer:
return unlimited_keyword; case var_pinteger:
/* Fall through. */ {
case var_zuinteger: LONGEST value
return scm_from_uint (var.get<unsigned int> ()); = (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)
return scm_from_latin1_keyword (l->literal);
if (var.type () == var_pinteger)
gdb_assert (value >= 0);
if (var.type () == var_uinteger)
return scm_from_uint (static_cast<unsigned int> (value));
else
return scm_from_int (static_cast<int> (value));
}
default: default:
break; break;
@ -735,53 +784,91 @@ pascm_set_param_value_x (param_smob *p_smob,
var.set<enum auto_boolean> (AUTO_BOOLEAN_FALSE); var.set<enum auto_boolean> (AUTO_BOOLEAN_FALSE);
break; break;
case var_zinteger: case var_integer:
case var_uinteger: case var_uinteger:
case var_zuinteger: case var_pinteger:
case var_zuinteger_unlimited: {
if (var.type () == var_uinteger const literal_def *extra_literals = p_smob->extra_literals;
|| var.type () == var_zuinteger_unlimited) enum tribool allowed = TRIBOOL_UNKNOWN;
{ enum var_types var_type = var.type ();
SCM_ASSERT_TYPE (scm_is_integer (value) bool integer = scm_is_integer (value);
|| scm_is_eq (value, unlimited_keyword), bool keyword = scm_is_keyword (value);
value, arg_pos, func_name, std::string buffer = "";
_("integer or #:unlimited")); size_t count = 0;
if (scm_is_eq (value, unlimited_keyword)) LONGEST val;
if (extra_literals != nullptr)
for (const literal_def *l = extra_literals;
l->literal != nullptr;
l++, count++)
{ {
if (var.type () == var_uinteger) if (count != 0)
var.set<unsigned int> (UINT_MAX); buffer += ", ";
else buffer = buffer + "#:" + l->literal;
var.set<int> (-1); if (keyword
break; && allowed == TRIBOOL_UNKNOWN
&& scm_is_eq (value,
scm_from_latin1_keyword (l->literal)))
{
val = l->use;
allowed = TRIBOOL_TRUE;
}
} }
}
else
{
SCM_ASSERT_TYPE (scm_is_integer (value), value, arg_pos, func_name,
_("integer"));
}
if (var.type () == var_uinteger if (allowed == TRIBOOL_UNKNOWN)
|| var.type () == var_zuinteger) {
{ if (extra_literals == nullptr)
unsigned int u = scm_to_uint (value); SCM_ASSERT_TYPE (integer, value, arg_pos, func_name,
_("integer"));
else if (count > 1)
SCM_ASSERT_TYPE (integer, value, arg_pos, func_name,
string_printf (_("integer or one of: %s"),
buffer.c_str ()).c_str ());
else
SCM_ASSERT_TYPE (integer, value, arg_pos, func_name,
string_printf (_("integer or %s"),
buffer.c_str ()).c_str ());
if (var.type () == var_uinteger && u == 0) val = (var_type == var_uinteger
u = UINT_MAX; ? static_cast<LONGEST> (scm_to_uint (value))
var.set<unsigned int> (u); : static_cast<LONGEST> (scm_to_int (value)));
}
else
{
int i = scm_to_int (value);
if (var.type () == var_zuinteger_unlimited && i < -1) if (extra_literals != nullptr)
{ for (const literal_def *l = extra_literals;
gdbscm_out_of_range_error (func_name, arg_pos, value, l->literal != nullptr;
_("must be >= -1")); l++)
{
if (l->val.has_value () && val == *l->val)
{
allowed = TRIBOOL_TRUE;
val = l->use;
break;
}
else if (val == l->use)
allowed = TRIBOOL_FALSE;
}
} }
var.set<int> (i);
} if (allowed == TRIBOOL_UNKNOWN)
break; {
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 < 0)
|| (var_type == var_pinteger && val > INT_MAX))
allowed = TRIBOOL_FALSE;
}
if (allowed == TRIBOOL_FALSE)
gdbscm_out_of_range_error (func_name, arg_pos, value,
_("integer out of range"));
if (var_type == var_uinteger)
var.set<unsigned int> (static_cast<unsigned int> (val));
else
var.set<int> (static_cast<int> (val));
break;
}
default: default:
gdb_assert_not_reached ("bad parameter type"); gdb_assert_not_reached ("bad parameter type");
@ -858,7 +945,7 @@ gdbscm_make_parameter (SCM name_scm, SCM rest)
char *s; char *s;
char *name; char *name;
int cmd_class = no_class; int cmd_class = no_class;
int param_type = var_boolean; /* ARI: var_boolean */ int param_type = param_boolean; /* ARI: param_boolean */
SCM enum_list_scm = SCM_BOOL_F; SCM enum_list_scm = SCM_BOOL_F;
SCM set_func = SCM_BOOL_F, show_func = SCM_BOOL_F; SCM set_func = SCM_BOOL_F, show_func = SCM_BOOL_F;
char *doc = NULL, *set_doc = NULL, *show_doc = NULL; char *doc = NULL, *set_doc = NULL, *show_doc = NULL;
@ -913,12 +1000,12 @@ gdbscm_make_parameter (SCM name_scm, SCM rest)
scm_from_int (param_type), scm_from_int (param_type),
_("invalid parameter type argument")); _("invalid parameter type argument"));
} }
if (enum_list_arg_pos > 0 && param_type != var_enum) if (enum_list_arg_pos > 0 && param_type != param_enum)
{ {
gdbscm_misc_error (FUNC_NAME, enum_list_arg_pos, enum_list_scm, gdbscm_misc_error (FUNC_NAME, enum_list_arg_pos, enum_list_scm,
_("#:enum-values can only be provided with PARAM_ENUM")); _("#:enum-values can only be provided with PARAM_ENUM"));
} }
if (enum_list_arg_pos < 0 && param_type == var_enum) if (enum_list_arg_pos < 0 && param_type == param_enum)
{ {
gdbscm_misc_error (FUNC_NAME, GDBSCM_ARG_NONE, SCM_BOOL_F, gdbscm_misc_error (FUNC_NAME, GDBSCM_ARG_NONE, SCM_BOOL_F,
_("PARAM_ENUM requires an enum-values argument")); _("PARAM_ENUM requires an enum-values argument"));
@ -933,7 +1020,7 @@ gdbscm_make_parameter (SCM name_scm, SCM rest)
SCM_ASSERT_TYPE (gdbscm_is_procedure (show_func), show_func, SCM_ASSERT_TYPE (gdbscm_is_procedure (show_func), show_func,
show_func_arg_pos, FUNC_NAME, _("procedure")); show_func_arg_pos, FUNC_NAME, _("procedure"));
} }
if (param_type == var_enum) if (param_type == param_enum)
{ {
/* Note: enum_list lives in GC space, so we don't have to worry about /* Note: enum_list lives in GC space, so we don't have to worry about
freeing it if we later throw an exception. */ freeing it if we later throw an exception. */
@ -950,7 +1037,10 @@ gdbscm_make_parameter (SCM name_scm, SCM rest)
freeing them if we throw an exception. */ freeing them if we throw an exception. */
p_smob->name = name; p_smob->name = name;
p_smob->cmd_class = (enum command_class) cmd_class; p_smob->cmd_class = (enum command_class) cmd_class;
p_smob->type = (enum var_types) param_type; p_smob->pname
= pascm_param_type_name (static_cast<enum param_types> (param_type));
p_smob->type = param_to_var[param_type].type;
p_smob->extra_literals = param_to_var[param_type].extra_literals;
p_smob->doc = doc; p_smob->doc = doc;
p_smob->set_doc = set_doc; p_smob->set_doc = set_doc;
p_smob->show_doc = show_doc; p_smob->show_doc = show_doc;
@ -1031,7 +1121,8 @@ gdbscm_register_parameter_x (SCM self)
try try
{ {
p_smob->commands = add_setshow_generic p_smob->commands = add_setshow_generic
(p_smob->type, p_smob->cmd_class, p_smob->cmd_name, p_smob, (p_smob->type, p_smob->extra_literals,
p_smob->cmd_class, p_smob->cmd_name, p_smob,
p_smob->set_doc, p_smob->show_doc, p_smob->doc, p_smob->set_doc, p_smob->show_doc, p_smob->doc,
(gdbscm_is_procedure (p_smob->set_func) ? pascm_set_func : NULL), (gdbscm_is_procedure (p_smob->set_func) ? pascm_set_func : NULL),
(gdbscm_is_procedure (p_smob->show_func) ? pascm_show_func : NULL), (gdbscm_is_procedure (p_smob->show_func) ? pascm_show_func : NULL),
@ -1203,5 +1294,4 @@ gdbscm_initialize_parameters (void)
show_doc_keyword = scm_from_latin1_keyword ("show-doc"); show_doc_keyword = scm_from_latin1_keyword ("show-doc");
initial_value_keyword = scm_from_latin1_keyword ("initial-value"); initial_value_keyword = scm_from_latin1_keyword ("initial-value");
auto_keyword = scm_from_latin1_keyword ("auto"); auto_keyword = scm_from_latin1_keyword ("auto");
unlimited_keyword = scm_from_latin1_keyword ("unlimited");
} }

View file

@ -61,13 +61,15 @@
available kinds of commands (boolean, enum, flag, string, uinteger): available kinds of commands (boolean, enum, flag, string, uinteger):
(gdb) maint test-options require-delimiter -[TAB] (gdb) maint test-options require-delimiter -[TAB]
-bool -enum -flag -string -uinteger -xx1 -xx2 -bool -pinteger-unlimited -xx1
-enum -string -xx2
-flag -uinteger-unlimited
(gdb) maint test-options require-delimiter -bool o[TAB] (gdb) maint test-options require-delimiter -bool o[TAB]
off on off on
(gdb) maint test-options require-delimiter -enum [TAB] (gdb) maint test-options require-delimiter -enum [TAB]
xxx yyy zzz xxx yyy zzz
(gdb) maint test-options require-delimiter -uinteger [TAB] (gdb) maint test-options require-delimiter -uinteger-unlimited [TAB]
NUMBER unlimited NUMBER unlimited
'-xx1' and '-xx2' are flag options too. They exist in order to '-xx1' and '-xx2' are flag options too. They exist in order to
@ -76,14 +78,14 @@
Invoking the commands makes them print out the options parsed: Invoking the commands makes them print out the options parsed:
(gdb) maint test-options unknown-is-error -flag -enum yyy cmdarg (gdb) maint test-options unknown-is-error -flag -enum yyy cmdarg
-flag 1 -xx1 0 -xx2 0 -bool 0 -enum yyy -uint 0 -zuint-unl 0 -- cmdarg -flag 1 -xx1 0 -xx2 0 -bool 0 -enum yyy -uint-unl 0 -pint-unl 0 -string '' -- cmdarg
(gdb) maint test-options require-delimiter -flag -enum yyy cmdarg (gdb) maint test-options require-delimiter -flag -enum yyy cmdarg
-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -- -flag -enum yyy cmdarg -flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl 0 -pint-unl 0 -string '' -- -flag -enum yyy cmdarg
(gdb) maint test-options require-delimiter -flag -enum yyy cmdarg -- (gdb) maint test-options require-delimiter -flag -enum yyy cmdarg --
Unrecognized option at: cmdarg -- Unrecognized option at: cmdarg --
(gdb) maint test-options require-delimiter -flag -enum yyy -- cmdarg (gdb) maint test-options require-delimiter -flag -enum yyy -- cmdarg
-flag 1 -xx1 0 -xx2 0 -bool 0 -enum yyy -uint 0 -zuint-unl 0 -- cmdarg -flag 1 -xx1 0 -xx2 0 -bool 0 -enum yyy -uint-unl 0 -pint-unl 0 -string '' -- cmdarg
The "maint show test-options-completion-result" command exists in The "maint show test-options-completion-result" command exists in
order to do something similar for completion: order to do something similar for completion:
@ -131,8 +133,8 @@ struct test_options_opts
bool xx2_opt = false; bool xx2_opt = false;
bool boolean_opt = false; bool boolean_opt = false;
const char *enum_opt = test_options_enum_values_xxx; const char *enum_opt = test_options_enum_values_xxx;
unsigned int uint_opt = 0; unsigned int uint_unl_opt = 0;
int zuint_unl_opt = 0; int pint_unl_opt = 0;
std::string string_opt; std::string string_opt;
test_options_opts () = default; test_options_opts () = default;
@ -145,18 +147,18 @@ struct test_options_opts
{ {
gdb_printf (file, gdb_printf (file,
_("-flag %d -xx1 %d -xx2 %d -bool %d " _("-flag %d -xx1 %d -xx2 %d -bool %d "
"-enum %s -uint %s -zuint-unl %s -string '%s' -- %s\n"), "-enum %s -uint-unl %s -pint-unl %s -string '%s' -- %s\n"),
flag_opt, flag_opt,
xx1_opt, xx1_opt,
xx2_opt, xx2_opt,
boolean_opt, boolean_opt,
enum_opt, enum_opt,
(uint_opt == UINT_MAX (uint_unl_opt == UINT_MAX
? "unlimited" ? "unlimited"
: pulongest (uint_opt)), : pulongest (uint_unl_opt)),
(zuint_unl_opt == -1 (pint_unl_opt == -1
? "unlimited" ? "unlimited"
: plongest (zuint_unl_opt)), : plongest (pint_unl_opt)),
string_opt.c_str (), string_opt.c_str (),
args); args);
} }
@ -203,22 +205,24 @@ static const gdb::option::option_def test_options_option_defs[] = {
N_("An enum option."), N_("An enum option."),
}, },
/* A uinteger option. */ /* A uinteger + "unlimited" option. */
gdb::option::uinteger_option_def<test_options_opts> { gdb::option::uinteger_option_def<test_options_opts> {
"uinteger", "uinteger-unlimited",
[] (test_options_opts *opts) { return &opts->uint_opt; }, [] (test_options_opts *opts) { return &opts->uint_unl_opt; },
uinteger_unlimited_literals,
nullptr, /* show_cmd_cb */ nullptr, /* show_cmd_cb */
N_("A uinteger option."), N_("A uinteger option."),
nullptr, /* show_doc */ nullptr, /* show_doc */
N_("A help doc that spawns\nmultiple lines."), N_("A help doc that spawns\nmultiple lines."),
}, },
/* A zuinteger_unlimited option. */ /* A pinteger + "unlimited" option. */
gdb::option::zuinteger_unlimited_option_def<test_options_opts> { gdb::option::pinteger_option_def<test_options_opts> {
"zuinteger-unlimited", "pinteger-unlimited",
[] (test_options_opts *opts) { return &opts->zuint_unl_opt; }, [] (test_options_opts *opts) { return &opts->pint_unl_opt; },
pinteger_unlimited_literals,
nullptr, /* show_cmd_cb */ nullptr, /* show_cmd_cb */
N_("A zuinteger-unlimited option."), N_("A pinteger-unlimited option."),
nullptr, /* show_doc */ nullptr, /* show_doc */
nullptr, /* help_doc */ nullptr, /* help_doc */
}, },

View file

@ -28,24 +28,70 @@
#include "language.h" #include "language.h"
#include "arch-utils.h" #include "arch-utils.h"
/* Python parameter types as in PARM_CONSTANTS below. */
enum param_types
{
param_boolean,
param_auto_boolean,
param_uinteger,
param_integer,
param_string,
param_string_noescape,
param_optional_filename,
param_filename,
param_zinteger,
param_zuinteger,
param_zuinteger_unlimited,
param_enum,
}
param_types;
/* Translation from Python parameters to GDB variable types. Keep in the
same order as PARAM_TYPES due to C++'s lack of designated initializers. */
static const struct
{
/* The type of the parameter. */
enum var_types type;
/* Extra literals, such as `unlimited', accepted in lieu of a number. */
const literal_def *extra_literals;
}
param_to_var[] =
{
{ var_boolean },
{ var_auto_boolean },
{ var_uinteger, uinteger_unlimited_literals },
{ var_integer, integer_unlimited_literals },
{ var_string },
{ var_string_noescape },
{ var_optional_filename },
{ var_filename },
{ var_integer },
{ var_uinteger },
{ var_pinteger, pinteger_unlimited_literals },
{ var_enum }
};
/* Parameter constants and their values. */ /* Parameter constants and their values. */
static struct { static struct {
const char *name; const char *name;
int value; int value;
} parm_constants[] = } parm_constants[] =
{ {
{ "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */ { "PARAM_BOOLEAN", param_boolean }, /* ARI: param_boolean */
{ "PARAM_AUTO_BOOLEAN", var_auto_boolean }, { "PARAM_AUTO_BOOLEAN", param_auto_boolean },
{ "PARAM_UINTEGER", var_uinteger }, { "PARAM_UINTEGER", param_uinteger },
{ "PARAM_INTEGER", var_integer }, { "PARAM_INTEGER", param_integer },
{ "PARAM_STRING", var_string }, { "PARAM_STRING", param_string },
{ "PARAM_STRING_NOESCAPE", var_string_noescape }, { "PARAM_STRING_NOESCAPE", param_string_noescape },
{ "PARAM_OPTIONAL_FILENAME", var_optional_filename }, { "PARAM_OPTIONAL_FILENAME", param_optional_filename },
{ "PARAM_FILENAME", var_filename }, { "PARAM_FILENAME", param_filename },
{ "PARAM_ZINTEGER", var_zinteger }, { "PARAM_ZINTEGER", param_zinteger },
{ "PARAM_ZUINTEGER", var_zuinteger }, { "PARAM_ZUINTEGER", param_zuinteger },
{ "PARAM_ZUINTEGER_UNLIMITED", var_zuinteger_unlimited }, { "PARAM_ZUINTEGER_UNLIMITED", param_zuinteger_unlimited },
{ "PARAM_ENUM", var_enum }, { "PARAM_ENUM", param_enum },
{ NULL, 0 } { NULL, 0 }
}; };
@ -80,6 +126,9 @@ struct parmpy_object
/* The type of the parameter. */ /* The type of the parameter. */
enum var_types type; enum var_types type;
/* Extra literals, such as `unlimited', accepted in lieu of a number. */
const literal_def *extra_literals;
/* The value of the parameter. */ /* The value of the parameter. */
union parmpy_variable value; union parmpy_variable value;
@ -96,18 +145,20 @@ struct parmpy_object
static setting static setting
make_setting (parmpy_object *s) make_setting (parmpy_object *s)
{ {
if (var_type_uses<bool> (s->type)) enum var_types type = s->type;
return setting (s->type, &s->value.boolval);
else if (var_type_uses<int> (s->type)) if (var_type_uses<bool> (type))
return setting (s->type, &s->value.intval); return setting (type, &s->value.boolval);
else if (var_type_uses<auto_boolean> (s->type)) else if (var_type_uses<int> (type))
return setting (s->type, &s->value.autoboolval); return setting (type, &s->value.intval, s->extra_literals);
else if (var_type_uses<unsigned int> (s->type)) else if (var_type_uses<auto_boolean> (type))
return setting (s->type, &s->value.uintval); return setting (type, &s->value.autoboolval);
else if (var_type_uses<std::string> (s->type)) else if (var_type_uses<unsigned int> (type))
return setting (s->type, s->value.stringval); return setting (type, &s->value.uintval, s->extra_literals);
else if (var_type_uses<const char *> (s->type)) else if (var_type_uses<std::string> (type))
return setting (s->type, &s->value.cstringval); return setting (type, s->value.stringval);
else if (var_type_uses<const char *> (type))
return setting (type, &s->value.cstringval);
else else
gdb_assert_not_reached ("unhandled var type"); gdb_assert_not_reached ("unhandled var type");
} }
@ -234,68 +285,98 @@ set_parameter_value (parmpy_object *self, PyObject *value)
} }
break; break;
case var_integer:
case var_zinteger:
case var_uinteger: case var_uinteger:
case var_zuinteger: case var_integer:
case var_zuinteger_unlimited: case var_pinteger:
{ {
long l; const literal_def *extra_literals = self->extra_literals;
int ok; enum tribool allowed = TRIBOOL_UNKNOWN;
enum var_types var_type = self->type;
std::string buffer = "";
size_t count = 0;
LONGEST val;
if (value == Py_None if (extra_literals != nullptr)
&& (self->type == var_uinteger || self->type == var_integer))
l = 0;
else if (value == Py_None && self->type == var_zuinteger_unlimited)
l = -1;
else if (!PyLong_Check (value))
{ {
PyErr_SetString (PyExc_RuntimeError, gdb::unique_xmalloc_ptr<char>
_("The value must be integer.")); str (python_string_to_host_string (value));
return -1; const char *s = str != nullptr ? str.get () : nullptr;
} PyErr_Clear ();
else if (! gdb_py_int_as_long (value, &l))
return -1;
switch (self->type) for (const literal_def *l = extra_literals;
{ l->literal != nullptr;
case var_uinteger: l++, count++)
if (l == 0) {
l = UINT_MAX; if (count != 0)
/* Fall through. */ buffer += ", ";
case var_zuinteger: buffer = buffer + "'" + l->literal + "'";
ok = (l >= 0 && l <= UINT_MAX); if (allowed == TRIBOOL_UNKNOWN
break; && ((value == Py_None && !strcmp ("unlimited", l->literal))
|| (s != nullptr && !strcmp (s, l->literal))))
case var_zuinteger_unlimited: {
ok = (l >= -1 && l <= INT_MAX); val = l->use;
break; allowed = TRIBOOL_TRUE;
}
case var_integer: }
ok = (l >= INT_MIN && l <= INT_MAX);
if (l == 0)
l = INT_MAX;
break;
case var_zinteger:
ok = (l >= INT_MIN && l <= INT_MAX);
break;
default:
gdb_assert_not_reached ("unknown var_ constant");
} }
if (! ok) if (allowed == TRIBOOL_UNKNOWN)
{
val = PyLong_AsLongLong (value);
if (PyErr_Occurred ())
{
if (extra_literals == nullptr)
PyErr_SetString (PyExc_RuntimeError,
_("The value must be integer."));
else if (count > 1)
PyErr_SetString (PyExc_RuntimeError,
string_printf (_("integer or one of: %s"),
buffer.c_str ()).c_str ());
else
PyErr_SetString (PyExc_RuntimeError,
string_printf (_("integer or %s"),
buffer.c_str ()).c_str ());
return -1;
}
if (extra_literals != nullptr)
for (const literal_def *l = extra_literals;
l->literal != nullptr;
l++)
{
if (l->val.has_value () && val == *l->val)
{
allowed = TRIBOOL_TRUE;
val = l->use;
break;
}
else if (val == l->use)
allowed = TRIBOOL_FALSE;
}
}
if (allowed == TRIBOOL_UNKNOWN)
{
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 < 0)
|| (var_type == var_pinteger && val > INT_MAX))
allowed = TRIBOOL_FALSE;
}
if (allowed == TRIBOOL_FALSE)
{ {
PyErr_SetString (PyExc_RuntimeError, PyErr_SetString (PyExc_RuntimeError,
_("Range exceeded.")); _("Range exceeded."));
return -1; return -1;
} }
if (self->type == var_uinteger || self->type == var_zuinteger) if (self->type == var_uinteger)
self->value.uintval = (unsigned) l; self->value.uintval = (unsigned) val;
else else
self->value.intval = (int) l; self->value.intval = (int) val;
break; break;
} }
@ -534,7 +615,8 @@ get_show_value (struct ui_file *file, int from_tty,
/* A helper function that dispatches to the appropriate add_setshow /* A helper function that dispatches to the appropriate add_setshow
function. */ function. */
static void static void
add_setshow_generic (int parmclass, enum command_class cmdclass, add_setshow_generic (enum var_types type, const literal_def *extra_literals,
enum command_class cmdclass,
gdb::unique_xmalloc_ptr<char> cmd_name, gdb::unique_xmalloc_ptr<char> cmd_name,
parmpy_object *self, parmpy_object *self,
const char *set_doc, const char *show_doc, const char *set_doc, const char *show_doc,
@ -544,7 +626,7 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
{ {
set_show_commands commands; set_show_commands commands;
switch (parmclass) switch (type)
{ {
case var_boolean: case var_boolean:
commands = add_setshow_boolean_cmd (cmd_name.get (), cmdclass, commands = add_setshow_boolean_cmd (cmd_name.get (), cmdclass,
@ -564,18 +646,28 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
case var_uinteger: case var_uinteger:
commands = add_setshow_uinteger_cmd (cmd_name.get (), cmdclass, commands = add_setshow_uinteger_cmd (cmd_name.get (), cmdclass,
&self->value.uintval, set_doc, &self->value.uintval,
extra_literals, set_doc,
show_doc, help_doc, get_set_value, show_doc, help_doc, get_set_value,
get_show_value, set_list, show_list); get_show_value, set_list, show_list);
break; break;
case var_integer: case var_integer:
commands = add_setshow_integer_cmd (cmd_name.get (), cmdclass, commands = add_setshow_integer_cmd (cmd_name.get (), cmdclass,
&self->value.intval, set_doc, &self->value.intval,
extra_literals, set_doc,
show_doc, help_doc, get_set_value, show_doc, help_doc, get_set_value,
get_show_value, set_list, show_list); get_show_value, set_list, show_list);
break; break;
case var_pinteger:
commands = add_setshow_pinteger_cmd (cmd_name.get (), cmdclass,
&self->value.intval,
extra_literals, set_doc,
show_doc, help_doc, get_set_value,
get_show_value, set_list, show_list);
break;
case var_string: case var_string:
commands = add_setshow_string_cmd (cmd_name.get (), cmdclass, commands = add_setshow_string_cmd (cmd_name.get (), cmdclass,
self->value.stringval, set_doc, self->value.stringval, set_doc,
@ -607,30 +699,6 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
get_show_value, set_list, show_list); get_show_value, set_list, show_list);
break; break;
case var_zinteger:
commands = add_setshow_zinteger_cmd (cmd_name.get (), cmdclass,
&self->value.intval, set_doc,
show_doc, help_doc, get_set_value,
get_show_value, set_list, show_list);
break;
case var_zuinteger:
commands = add_setshow_zuinteger_cmd (cmd_name.get (), cmdclass,
&self->value.uintval, set_doc,
show_doc, help_doc, get_set_value,
get_show_value, set_list,
show_list);
break;
case var_zuinteger_unlimited:
commands = add_setshow_zuinteger_unlimited_cmd (cmd_name.get (), cmdclass,
&self->value.intval,
set_doc, show_doc,
help_doc, get_set_value,
get_show_value, set_list,
show_list);
break;
case var_enum: case var_enum:
/* Initialize the value, just in case. */ /* Initialize the value, just in case. */
self->value.cstringval = self->enumeration[0]; self->value.cstringval = self->enumeration[0];
@ -740,6 +808,8 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
int parmclass, cmdtype; int parmclass, cmdtype;
PyObject *enum_values = NULL; PyObject *enum_values = NULL;
struct cmd_list_element **set_list, **show_list; struct cmd_list_element **set_list, **show_list;
const literal_def *extra_literals;
enum var_types type;
if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass, if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass,
&enum_values)) &enum_values))
@ -756,33 +826,36 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
return -1; return -1;
} }
if (parmclass != var_boolean /* ARI: var_boolean */ if (parmclass != param_boolean /* ARI: param_boolean */
&& parmclass != var_auto_boolean && parmclass != param_auto_boolean
&& parmclass != var_uinteger && parmclass != var_integer && parmclass != param_uinteger && parmclass != param_integer
&& parmclass != var_string && parmclass != var_string_noescape && parmclass != param_string && parmclass != param_string_noescape
&& parmclass != var_optional_filename && parmclass != var_filename && parmclass != param_optional_filename && parmclass != param_filename
&& parmclass != var_zinteger && parmclass != var_zuinteger && parmclass != param_zinteger && parmclass != param_zuinteger
&& parmclass != var_zuinteger_unlimited && parmclass != var_enum) && parmclass != param_zuinteger_unlimited && parmclass != param_enum)
{ {
PyErr_SetString (PyExc_RuntimeError, PyErr_SetString (PyExc_RuntimeError,
_("Invalid parameter class argument.")); _("Invalid parameter class argument."));
return -1; return -1;
} }
if (enum_values && parmclass != var_enum) if (enum_values && parmclass != param_enum)
{ {
PyErr_SetString (PyExc_RuntimeError, PyErr_SetString (PyExc_RuntimeError,
_("Only PARAM_ENUM accepts a fourth argument.")); _("Only PARAM_ENUM accepts a fourth argument."));
return -1; return -1;
} }
if (parmclass == var_enum) if (parmclass == param_enum)
{ {
if (! compute_enum_values (obj, enum_values)) if (! compute_enum_values (obj, enum_values))
return -1; return -1;
} }
else else
obj->enumeration = NULL; obj->enumeration = NULL;
obj->type = (enum var_types) parmclass; type = param_to_var[parmclass].type;
extra_literals = param_to_var[parmclass].extra_literals;
obj->type = type;
obj->extra_literals = extra_literals;
memset (&obj->value, 0, sizeof (obj->value)); memset (&obj->value, 0, sizeof (obj->value));
if (var_type_uses<std::string> (obj->type)) if (var_type_uses<std::string> (obj->type))
@ -805,7 +878,8 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
try try
{ {
add_setshow_generic (parmclass, (enum command_class) cmdtype, add_setshow_generic (type, extra_literals,
(enum command_class) cmdtype,
std::move (cmd_name), obj, std::move (cmd_name), obj,
set_doc.get (), show_doc.get (), set_doc.get (), show_doc.get (),
doc.get (), set_list, show_list); doc.get (), set_list, show_list);

View file

@ -504,27 +504,45 @@ gdbpy_parameter_value (const setting &var)
Py_RETURN_NONE; Py_RETURN_NONE;
} }
case var_integer:
if (var.get<int> () == INT_MAX)
Py_RETURN_NONE;
/* Fall through. */
case var_zinteger:
case var_zuinteger_unlimited:
return gdb_py_object_from_longest (var.get<int> ()).release ();
case var_uinteger: 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) if (var.extra_literals () != nullptr)
Py_RETURN_NONE; for (const literal_def *l = var.extra_literals ();
return gdb_py_object_from_ulongest (val).release (); l->literal != nullptr;
} l++)
if (value == l->use)
{
if (strcmp (l->literal, "unlimited") == 0)
{
/* Compatibility hack for API brokenness. */
if (var.type () == var_pinteger
&& l->val.has_value ()
&& *l->val == -1)
value = -1;
else
Py_RETURN_NONE;
}
else if (l->val.has_value ())
value = *l->val;
else
return host_string_to_python_string (l->literal).release ();
}
case var_zuinteger: if (var.type () == var_uinteger)
{ return
unsigned int val = var.get<unsigned int> (); gdb_py_object_from_ulongest
return gdb_py_object_from_ulongest (val).release (); (static_cast<unsigned int> (value)).release ();
else
return
gdb_py_object_from_longest
(static_cast<int> (value)).release ();
} }
} }

View file

@ -92,4 +92,4 @@ gdb_test "set max-value-size 1" \
gdb_test "set max-value-size 0" \ gdb_test "set max-value-size 0" \
"max-value-size set too low, increasing to \[0-9\]+ bytes" "max-value-size set too low, increasing to \[0-9\]+ bytes"
gdb_test "set max-value-size -5" \ gdb_test "set max-value-size -5" \
"only -1 is allowed to set as unlimited" "integer -5 out of range"

View file

@ -98,19 +98,22 @@ proc make_cmd {variant} {
# test-options xxx", with no flag/option set. OPERAND is the expected # test-options xxx", with no flag/option set. OPERAND is the expected
# operand. # operand.
proc expect_none {operand} { proc expect_none {operand} {
return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '' -- $operand" return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl 0 -pint-unl 0\
-string '' -- $operand"
} }
# Return a string for the expected result of running "maint # Return a string for the expected result of running "maint
# test-options xxx", with -flag set. OPERAND is the expected operand. # test-options xxx", with -flag set. OPERAND is the expected operand.
proc expect_flag {operand} { proc expect_flag {operand} {
return "-flag 1 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '' -- $operand" return "-flag 1 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl 0 -pint-unl 0\
-string '' -- $operand"
} }
# Return a string for the expected result of running "maint # Return a string for the expected result of running "maint
# test-options xxx", with -bool set. OPERAND is the expected operand. # test-options xxx", with -bool set. OPERAND is the expected operand.
proc expect_bool {operand} { proc expect_bool {operand} {
return "-flag 0 -xx1 0 -xx2 0 -bool 1 -enum xxx -uint 0 -zuint-unl 0 -string '' -- $operand" return "-flag 0 -xx1 0 -xx2 0 -bool 1 -enum xxx -uint-unl 0 -pint-unl 0\
-string '' -- $operand"
} }
# Return a string for the expected result of running "maint # Return a string for the expected result of running "maint
@ -118,10 +121,12 @@ proc expect_bool {operand} {
# OPTION determines which option to expect set. OPERAND is the # OPTION determines which option to expect set. OPERAND is the
# expected operand. # expected operand.
proc expect_integer {option val operand} { proc expect_integer {option val operand} {
if {$option == "uinteger"} { if {$option == "uinteger-unlimited"} {
return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint $val -zuint-unl 0 -string '' -- $operand" return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl $val\
} elseif {$option == "zuinteger-unlimited"} { -pint-unl 0 -string '' -- $operand"
return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl $val -string '' -- $operand" } elseif {$option == "pinteger-unlimited"} {
return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl 0\
-pint-unl $val -string '' -- $operand"
} else { } else {
error "unsupported option: $option" error "unsupported option: $option"
} }
@ -138,18 +143,19 @@ proc expect_string {str operand} {
&& [string range $str end end] == "'")} { && [string range $str end end] == "'")} {
set str [string range $str 1 end-1] set str [string range $str 1 end-1]
} }
return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '$str' -- $operand" return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl 0 -pint-unl 0\
-string '$str' -- $operand"
} }
set all_options { set all_options {
"-bool" "-bool"
"-enum" "-enum"
"-flag" "-flag"
"-pinteger-unlimited"
"-string" "-string"
"-uinteger" "-uinteger-unlimited"
"-xx1" "-xx1"
"-xx2" "-xx2"
"-zuinteger-unlimited"
} }
# Basic option-machinery + "print" command integration tests. # Basic option-machinery + "print" command integration tests.
@ -604,7 +610,8 @@ proc_with_prefix test-flag {variant} {
# Extract twice the same flag, separated by one space. # Extract twice the same flag, separated by one space.
gdb_test "$cmd -xx1 -xx2 -xx1 -xx2 -xx1 -- non flags args" \ gdb_test "$cmd -xx1 -xx2 -xx1 -xx2 -xx1 -- non flags args" \
"-flag 0 -xx1 1 -xx2 1 -bool 0 -enum xxx -uint 0 -zuint-unl 0 -string '' -- non flags args" "-flag 0 -xx1 1 -xx2 1 -bool 0 -enum xxx -uint-unl 0 -pint-unl 0\
-string '' -- non flags args"
# Extract 2 known flags in front of unknown flags. # Extract 2 known flags in front of unknown flags.
gdb_test "$cmd -xx1 -xx2 -a -b -c -xx1 --" \ gdb_test "$cmd -xx1 -xx2 -a -b -c -xx1 --" \
@ -822,13 +829,13 @@ proc_with_prefix test-boolean {variant} {
} }
# Uinteger option tests. OPTION is which integer option we're # Uinteger option tests. OPTION is which integer option we're
# testing. Can be "uinteger" or "zuinteger-unlimited". # testing. Can be "uinteger-unlimited" or "pinteger-unlimited".
proc_with_prefix test-uinteger {variant option} { proc_with_prefix test-uinteger {variant option} {
global all_options global all_options
set cmd "[make_cmd $variant] -$option" set cmd "[make_cmd $variant] -$option"
# Test completing a uinteger option: # Test completing an integer option:
res_test_gdb_complete_multiple \ res_test_gdb_complete_multiple \
"1 [expect_none ""]" \ "1 [expect_none ""]" \
"$cmd " "" "" { "$cmd " "" "" {
@ -852,7 +859,7 @@ proc_with_prefix test-uinteger {variant option} {
gdb_test "$cmd 1 -- 999" [expect_integer $option "1" "999"] gdb_test "$cmd 1 -- 999" [expect_integer $option "1" "999"]
gdb_test "$cmd unlimited -- 999" \ gdb_test "$cmd unlimited -- 999" \
[expect_integer $option "unlimited" "999"] [expect_integer $option "unlimited" "999"]
if {$option == "zuinteger-unlimited"} { if {$option == "pinteger-unlimited"} {
gdb_test "$cmd -1 --" [expect_integer $option "unlimited" ""] gdb_test "$cmd -1 --" [expect_integer $option "unlimited" ""]
gdb_test "$cmd 0 --" [expect_integer $option "0" ""] gdb_test "$cmd 0 --" [expect_integer $option "0" ""]
} else { } else {
@ -865,7 +872,7 @@ proc_with_prefix test-uinteger {variant option} {
"Expected integer at: unlimitedx --" "Expected integer at: unlimitedx --"
# Don't offer completions until we're past the # Don't offer completions until we're past the
# -uinteger/-zuinteger-unlimited argument. # -uinteger-unlimited/-pinteger-unlimited argument.
res_test_gdb_complete_none \ res_test_gdb_complete_none \
"1 [expect_none ""]" \ "1 [expect_none ""]" \
"$cmd 1" "$cmd 1"
@ -878,15 +885,15 @@ proc_with_prefix test-uinteger {variant option} {
} }
# Try "-1". # Try "-1".
if {$option == "uinteger"} { if {$option == "uinteger-unlimited"} {
# -1 is invalid uinteger. # -1 is invalid uinteger-unlimited.
foreach value {"-1" "-1 "} { foreach value {"-1" "-1 "} {
res_test_gdb_complete_none \ res_test_gdb_complete_none \
"1 [expect_none ""]" \ "1 [expect_none ""]" \
"$cmd $value" "$cmd $value"
} }
} else { } else {
# -1 is valid for zuinteger-unlimited. # -1 is valid for pinteger-unlimited.
res_test_gdb_complete_none \ res_test_gdb_complete_none \
"1 [expect_none ""]" \ "1 [expect_none ""]" \
"$cmd -1" "$cmd -1"
@ -914,7 +921,7 @@ proc_with_prefix test-uinteger {variant option} {
res_test_gdb_complete_none "0 " "$cmd 1 " res_test_gdb_complete_none "0 " "$cmd 1 "
} }
# Test completing non-option arguments after "-uinteger 1 ". # Test completing non-option arguments after "-uinteger-unlimited 1 ".
foreach operand {"x" "x " "1a" "1a " "1-" "1- "} { foreach operand {"x" "x " "1a" "1a " "1-" "1- "} {
if {$variant == "require-delimiter"} { if {$variant == "require-delimiter"} {
res_test_gdb_complete_none \ res_test_gdb_complete_none \
@ -1032,7 +1039,7 @@ foreach_with_prefix cmd {
test-misc $cmd test-misc $cmd
test-flag $cmd test-flag $cmd
test-boolean $cmd test-boolean $cmd
foreach subcmd {"uinteger" "zuinteger-unlimited" } { foreach subcmd {"uinteger-unlimited" "pinteger-unlimited" } {
test-uinteger $cmd $subcmd test-uinteger $cmd $subcmd
} }
test-enum $cmd test-enum $cmd

View file

@ -143,7 +143,7 @@ proc test-integer {variant} {
if {$variant == "zuinteger-unlimited"} { if {$variant == "zuinteger-unlimited"} {
# -1 means unlimited. Other negative values are rejected. -1 # -1 means unlimited. Other negative values are rejected. -1
# -is tested further below, along the "unlimited" tests. # -is tested further below, along the "unlimited" tests.
gdb_test "$set_cmd -2" "only -1 is allowed to set as unlimited" gdb_test "$set_cmd -2" "integer -2 out of range"
check_type "test-settings $variant" "type = int" check_type "test-settings $variant" "type = int"
} elseif {$variant == "uinteger" || $variant == "zuinteger"} { } elseif {$variant == "uinteger" || $variant == "zuinteger"} {
# Negative values are not accepted. # Negative values are not accepted.

View file

@ -104,7 +104,7 @@ with_test_prefix "maint" {
test_with_error "zuinteger" "" \ test_with_error "zuinteger" "" \
"Argument required \\(integer to set it to\\)\\." "Argument required \\(integer to set it to\\)\\."
test_with_error "zuinteger-unlimited" "-2" \ test_with_error "zuinteger-unlimited" "-2" \
"only -1 is allowed to set as unlimited" "integer -2 out of range"
test_with_error "zuinteger-unlimited" "" \ test_with_error "zuinteger-unlimited" "" \
"Argument required \\(integer to set it to, or \"unlimited\"\\)\\." "Argument required \\(integer to set it to, or \"unlimited\"\\)\\."
test_with_error "filename" "" \ test_with_error "filename" "" \

View file

@ -113,24 +113,18 @@ foreach_with_prefix param {
\\(3\\) \\(3\\)\\)>" \\(3\\) \\(3\\)\\)>"
switch -- $param { switch -- $param {
"listsize" { "listsize" {
set param_get_one $param_type_error set param_get_zero "#:unlimited"
set param_get_zero $param_type_error set param_get_minus_one -1
set param_get_minus_one $param_type_error
set param_get_unlimited $param_type_error
set param_set_minus_one "" set param_set_minus_one ""
} }
"print elements" { "print elements" {
set param_get_one 1
set param_get_zero "#:unlimited" set param_get_zero "#:unlimited"
set param_get_minus_one "#:unlimited" set param_get_minus_one "#:unlimited"
set param_get_unlimited "#:unlimited"
set param_set_minus_one $param_range_error set param_set_minus_one $param_range_error
} }
"max-completions" { "max-completions" {
set param_get_one 1
set param_get_zero 0 set param_get_zero 0
set param_get_minus_one "#:unlimited" set param_get_minus_one "#:unlimited"
set param_get_unlimited "#:unlimited"
set param_set_minus_one "" set param_set_minus_one ""
} }
default { default {
@ -141,7 +135,7 @@ foreach_with_prefix param {
gdb_test_no_output "set $param 1" "test set to 1" gdb_test_no_output "set $param 1" "test set to 1"
gdb_test "guile (print (parameter-value \"$param\"))" \ gdb_test "guile (print (parameter-value \"$param\"))" \
$param_get_one "test value of 1" 1 "test value of 1"
gdb_test_no_output "set $param 0" "test set to 0" gdb_test_no_output "set $param 0" "test set to 0"
@ -157,7 +151,7 @@ foreach_with_prefix param {
gdb_test_no_output "set $param unlimited" "test set to 'unlimited'" gdb_test_no_output "set $param unlimited" "test set to 'unlimited'"
gdb_test "guile (print (parameter-value \"$param\"))" \ gdb_test "guile (print (parameter-value \"$param\"))" \
$param_get_unlimited "test value of 'unlimited'" "#:unlimited" "test value of 'unlimited'"
} }
foreach_with_prefix kind { foreach_with_prefix kind {
@ -189,8 +183,7 @@ foreach_with_prefix kind {
#:unlimited" \ #:unlimited" \
"Error while executing Scheme code\\."] "Error while executing Scheme code\\."]
set param_minus_one_error "integer -1 out of range" set param_minus_one_error "integer -1 out of range"
set param_minus_two_range "integer -2 out of range" set param_minus_two_error "integer -2 out of range"
set param_minus_two_unlimited "only -1 is allowed to set as unlimited"
switch -- $kind { switch -- $kind {
PARAM_UINTEGER { PARAM_UINTEGER {
set param_get_zero "#:unlimited" set param_get_zero "#:unlimited"
@ -199,7 +192,7 @@ foreach_with_prefix kind {
set param_str_unlimited unlimited set param_str_unlimited unlimited
set param_set_unlimited "" set param_set_unlimited ""
set param_set_minus_one $param_minus_one_error set param_set_minus_one $param_minus_one_error
set param_set_minus_two $param_minus_two_range set param_set_minus_two $param_minus_two_error
} }
PARAM_ZINTEGER { PARAM_ZINTEGER {
set param_get_zero 0 set param_get_zero 0
@ -217,7 +210,7 @@ foreach_with_prefix kind {
set param_str_unlimited 2 set param_str_unlimited 2
set param_set_unlimited $param_integer_error set param_set_unlimited $param_integer_error
set param_set_minus_one $param_minus_one_error set param_set_minus_one $param_minus_one_error
set param_set_minus_two $param_minus_two_range set param_set_minus_two $param_minus_two_error
} }
PARAM_ZUINTEGER_UNLIMITED { PARAM_ZUINTEGER_UNLIMITED {
set param_get_zero 0 set param_get_zero 0
@ -226,7 +219,7 @@ foreach_with_prefix kind {
set param_str_unlimited unlimited set param_str_unlimited unlimited
set param_set_unlimited "" set param_set_unlimited ""
set param_set_minus_one "" set param_set_minus_one ""
set param_set_minus_two $param_minus_two_unlimited set param_set_minus_two $param_minus_two_error
} }
default { default {
error "invalid kind: $kind" error "invalid kind: $kind"

View file

@ -434,6 +434,7 @@ proc_with_prefix test_integer_parameter { } {
set param_get_minus_one None set param_get_minus_one None
set param_get_minus_five 1 set param_get_minus_five 1
set param_get_none None set param_get_none None
set param_get_unlimited None
set param_set_minus_one $param_range_error set param_set_minus_one $param_range_error
set param_set_minus_five $param_range_error set param_set_minus_five $param_range_error
set param_set_none "" set param_set_none ""
@ -443,6 +444,7 @@ proc_with_prefix test_integer_parameter { } {
set param_get_minus_one -1 set param_get_minus_one -1
set param_get_minus_five -5 set param_get_minus_five -5
set param_get_none None set param_get_none None
set param_get_unlimited None
set param_set_minus_one -1 set param_set_minus_one -1
set param_set_minus_five -5 set param_set_minus_five -5
set param_set_none "" set param_set_none ""
@ -452,6 +454,7 @@ proc_with_prefix test_integer_parameter { } {
set param_get_minus_one -1 set param_get_minus_one -1
set param_get_minus_five -5 set param_get_minus_five -5
set param_get_none 5 set param_get_none 5
set param_get_unlimited 0
set param_set_minus_one "" set param_set_minus_one ""
set param_set_minus_five "" set param_set_minus_five ""
set param_set_none $param_integer_error set param_set_none $param_integer_error
@ -461,6 +464,7 @@ proc_with_prefix test_integer_parameter { } {
set param_get_minus_one 0 set param_get_minus_one 0
set param_get_minus_five 1 set param_get_minus_five 1
set param_get_none 5 set param_get_none 5
set param_get_unlimited 0
set param_set_minus_one $param_range_error set param_set_minus_one $param_range_error
set param_set_minus_five $param_range_error set param_set_minus_five $param_range_error
set param_set_none $param_integer_error set param_set_none $param_integer_error
@ -470,6 +474,7 @@ proc_with_prefix test_integer_parameter { } {
set param_get_minus_one -1 set param_get_minus_one -1
set param_get_minus_five 1 set param_get_minus_five 1
set param_get_none -1 set param_get_none -1
set param_get_unlimited -1
set param_set_minus_one "" set param_set_minus_one ""
set param_set_minus_five $param_range_error set param_set_minus_five $param_range_error
set param_set_none "" set param_set_none ""
@ -526,6 +531,16 @@ proc_with_prefix test_integer_parameter { } {
gdb_test "python print(gdb.parameter('test-$kind'))" \ gdb_test "python print(gdb.parameter('test-$kind'))" \
$param_get_zero "test value of 0 via gdb.parameter" $param_get_zero "test value of 0 via gdb.parameter"
py_param_test_maybe_no_output \
"python test_param_$kind.value = 'unlimited'" \
$param_set_none "test set to 'unlimited'"
gdb_test "python print(test_param_$kind.value)" \
$param_get_unlimited "test value of 'unlimited'"
gdb_test "python print(gdb.parameter('test-$kind'))" \
$param_get_unlimited "test value of 'unlimited' via gdb.parameter"
} }
} }

View file

@ -2861,8 +2861,8 @@ using boolean_option_def
= gdb::option::boolean_option_def<value_print_options>; = gdb::option::boolean_option_def<value_print_options>;
using uinteger_option_def using uinteger_option_def
= gdb::option::uinteger_option_def<value_print_options>; = gdb::option::uinteger_option_def<value_print_options>;
using zuinteger_unlimited_option_def using pinteger_option_def
= gdb::option::zuinteger_unlimited_option_def<value_print_options>; = gdb::option::pinteger_option_def<value_print_options>;
/* Definitions of options for the "print" and "compile print" /* Definitions of options for the "print" and "compile print"
commands. */ commands. */
@ -2907,15 +2907,17 @@ static const gdb::option::option_def value_print_option_defs[] = {
uinteger_option_def { uinteger_option_def {
"elements", "elements",
[] (value_print_options *opt) { return &opt->print_max; }, [] (value_print_options *opt) { return &opt->print_max; },
uinteger_unlimited_literals,
show_print_max, /* show_cmd_cb */ show_print_max, /* show_cmd_cb */
N_("Set limit on string chars or array elements to print."), N_("Set limit on string chars or array elements to print."),
N_("Show 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."), N_("\"unlimited\" causes there to be no limit."),
}, },
zuinteger_unlimited_option_def { pinteger_option_def {
"max-depth", "max-depth",
[] (value_print_options *opt) { return &opt->max_depth; }, [] (value_print_options *opt) { return &opt->max_depth; },
pinteger_unlimited_literals,
show_print_max_depth, /* show_cmd_cb */ show_print_max_depth, /* show_cmd_cb */
N_("Set maximum print depth for nested structures, unions and arrays."), N_("Set maximum print depth for nested structures, unions and arrays."),
N_("Show maximum print depth for nested structures, unions, and arrays."), N_("Show maximum print depth for nested structures, unions, and arrays."),
@ -2975,6 +2977,7 @@ pretty-printers for that value.")
uinteger_option_def { uinteger_option_def {
"repeats", "repeats",
[] (value_print_options *opt) { return &opt->repeat_count_threshold; }, [] (value_print_options *opt) { return &opt->repeat_count_threshold; },
uinteger_unlimited_literals,
show_repeat_count_threshold, /* show_cmd_cb */ show_repeat_count_threshold, /* show_cmd_cb */
N_("Set threshold for repeated print elements."), N_("Set threshold for repeated print elements."),
N_("Show threshold for repeated print elements."), N_("Show threshold for repeated print elements."),