{
switch (var.type ())
{
+ case var_uinteger:
case var_integer:
- if (var.get<int> () == INT_MAX)
- return value_from_longest (builtin_type (gdbarch)->builtin_int,
- 0);
- else
- return value_from_longest (builtin_type (gdbarch)->builtin_int,
- var.get<int> ());
- case var_zinteger:
- return value_from_longest (builtin_type (gdbarch)->builtin_int,
- var.get<int> ());
+ case var_pinteger:
+ {
+ LONGEST value
+ = (var.type () == var_uinteger
+ ? static_cast<LONGEST> (var.get<unsigned int> ())
+ : static_cast<LONGEST> (var.get<int> ()));
+
+ if (var.extra_literals () != nullptr)
+ for (const literal_def *l = var.extra_literals ();
+ l->literal != nullptr;
+ l++)
+ if (value == l->use)
+ {
+ 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:
return value_from_longest (builtin_type (gdbarch)->builtin_int,
var.get<bool> () ? 1 : 0);
- case var_zuinteger_unlimited:
- return value_from_longest (builtin_type (gdbarch)->builtin_int,
- var.get<int> ());
case var_auto_boolean:
{
int val;
return value_from_longest (builtin_type (gdbarch)->builtin_int,
val);
}
- case var_uinteger:
- if (var.get<unsigned int> () == UINT_MAX)
- return value_from_ulongest
- (builtin_type (gdbarch)->builtin_unsigned_int, 0);
- else
- return value_from_ulongest
- (builtin_type (gdbarch)->builtin_unsigned_int,
- var.get<unsigned int> ());
- case var_zuinteger:
- return value_from_ulongest (builtin_type (gdbarch)->builtin_unsigned_int,
- var.get<unsigned int> ());
case var_string:
case var_string_noescape:
case var_optional_filename:
{
switch (var.type ())
{
+ case var_uinteger:
case var_integer:
- case var_zinteger:
+ case var_pinteger:
case var_boolean:
- case var_zuinteger_unlimited:
case var_auto_boolean:
- case var_uinteger:
- case var_zuinteger:
{
std::string cmd_val = get_setshow_command_value_string (var);
TYPE is set_cmd or show_cmd.
THECLASS is as in add_cmd.
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
controlled by this command.
DOC is the documentation string. */
enum cmd_types type,
enum command_class theclass,
var_types var_type,
+ const literal_def *extra_literals,
const setting::erased_args &arg,
const char *doc,
struct cmd_list_element **list)
gdb_assert (type == set_cmd || type == show_cmd);
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
treated as a help class. */
/* 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
- setting. ARGS is a pre-validated type-erased reference to the
- variable being controlled by this command. SET_FUNC and SHOW_FUNC
- are the callback functions (if non-NULL). SET_DOC, SHOW_DOC and
- HELP_DOC are the documentation strings.
+ 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 controlled
+ by this command. SET_FUNC and SHOW_FUNC are the callback functions
+ (if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation
+ strings.
Return the newly created set and show commands. */
add_setshow_cmd_full_erased (const char *name,
enum command_class theclass,
var_types var_type,
+ const literal_def *extra_literals,
const setting::erased_args &args,
const char *set_doc, const char *show_doc,
const char *help_doc,
full_set_doc = make_unique_xstrdup (set_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);
set->doc_allocated = 1;
if (set_func != NULL)
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);
show->doc_allocated = 1;
show->show_value_func = show_func;
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.
THECLASS is as in add_cmd. VAR_TYPE is the kind of thing we are
setting. VAR is address of the variable being controlled by this
- command. If nullptr is given as VAR, then both SET_SETTING_FUNC and
- GET_SETTING_FUNC must be provided. SET_SETTING_FUNC and GET_SETTING_FUNC
- are callbacks used to access and modify the underlying property,
- whatever its storage is. SET_FUNC and SHOW_FUNC are the callback
- functions (if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the
+ command. EXTRA_LITERALS if non-NULL define extra literals to be
+ accepted in lieu of a number for integer variables. If nullptr is
+ given as VAR, then both SET_SETTING_FUNC and GET_SETTING_FUNC must
+ be provided. SET_SETTING_FUNC and GET_SETTING_FUNC are callbacks
+ used to access and modify the underlying property, whatever its
+ storage is. SET_FUNC and SHOW_FUNC are the callback functions
+ (if non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the
documentation strings.
Return the newly created set and show commands. */
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,
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 add_setshow_cmd_full_erased (name,
- theclass,
- var_type, erased_args,
- set_doc, show_doc,
- help_doc,
- set_func,
- show_func,
- set_list,
- show_list);
+ return cmds;
+}
+
+/* Same as above but omitting EXTRA_LITERALS. */
+
+template<typename T>
+static set_show_commands
+add_setshow_cmd_full (const char *name,
+ enum command_class theclass,
+ var_types var_type, T *var,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ typename setting_func_types<T>::set set_setting_func,
+ typename setting_func_types<T>::get get_setting_func,
+ cmd_func_ftype *set_func,
+ show_value_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
+{
+ return add_setshow_cmd_full (name, theclass, var_type, var, nullptr,
+ set_doc, show_doc, help_doc,
+ set_setting_func, get_setting_func,
+ set_func, show_func, set_list, show_list);
}
/* Add element named NAME to command list LIST (the list for set or
return cmds;
}
-/* Completes on literal "unlimited". Used by integer commands that
- support a special "unlimited" value. */
-
-static void
-integer_unlimited_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char *word)
-{
- static const char * const keywords[] =
- {
- "unlimited",
- NULL,
- };
-
- if (*text == '\0')
- tracker.add_completion (make_unique_xstrdup ("NUMBER"));
- complete_on_enum (tracker, keywords, text, word);
-}
-
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). THECLASS 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. This
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
add_setshow_integer_cmd (const char *name, enum command_class theclass,
int *var,
{
set_show_commands commands
= add_setshow_cmd_full<int> (name, theclass, var_integer, var,
+ integer_unlimited_literals,
set_doc, show_doc, help_doc,
nullptr, nullptr, set_func,
show_func, set_list, show_list);
-
- set_cmd_completer (commands.set, integer_unlimited_completer);
-
return commands;
}
cmd_list_element **show_list)
{
auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
+ integer_unlimited_literals,
set_doc, show_doc, help_doc, set_func,
get_func, nullptr, show_func, set_list,
show_list);
+ return cmds;
+}
- set_cmd_completer (cmds.set, integer_unlimited_completer);
+/* Add element named NAME to both the set and show command LISTs (the
+ list for set/show or some sublist thereof). CLASS is as in
+ add_cmd. VAR is address of the variable which will contain the
+ value. SET_DOC and SHOW_DOC are the documentation strings. */
+
+set_show_commands
+add_setshow_pinteger_cmd (const char *name, enum command_class theclass,
+ int *var, const literal_def *extra_literals,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ cmd_func_ftype *set_func,
+ show_value_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
+{
+ set_show_commands commands
+ = add_setshow_cmd_full<int> (name, theclass, var_pinteger, var,
+ extra_literals, set_doc, show_doc,
+ help_doc, nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
+ return commands;
+}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_pinteger_cmd (const char *name, command_class theclass,
+ const literal_def *extra_literals,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<int>::set set_func,
+ setting_func_types<int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr,
+ extra_literals, set_doc, show_doc,
+ help_doc, set_func, get_func, nullptr,
+ show_func, set_list, show_list);
return cmds;
}
set_show_commands
add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
- unsigned int *var,
+ unsigned int *var, const literal_def *extra_literals,
const char *set_doc, const char *show_doc,
const char *help_doc,
cmd_func_ftype *set_func,
{
set_show_commands commands
= add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
- set_doc, show_doc, help_doc,
- nullptr, nullptr, set_func,
+ extra_literals, set_doc, show_doc,
+ help_doc, nullptr, nullptr, set_func,
show_func, set_list, show_list);
-
- set_cmd_completer (commands.set, integer_unlimited_completer);
-
return commands;
}
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,
cmd_list_element **show_list)
{
auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
- nullptr, set_doc, show_doc,
- help_doc, set_func, get_func,
- nullptr, show_func, set_list,
+ nullptr, extra_literals,
+ set_doc, show_doc, help_doc,
+ set_func, get_func, nullptr,
+ show_func, set_list,
show_list);
+ return cmds;
+}
+
+/* Accept `unlimited' or 0, translated internally to UINT_MAX. */
+const literal_def uinteger_unlimited_literals[] =
+ {
+ { "unlimited", UINT_MAX, 0 },
+ { nullptr }
+ };
- set_cmd_completer (cmds.set, integer_unlimited_completer);
+/* Same as above but using `uinteger_unlimited_literals', with a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_uinteger_cmd (const char *name, enum command_class theclass,
+ unsigned int *var,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ cmd_func_ftype *set_func,
+ show_value_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
+{
+ set_show_commands commands
+ = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
+ uinteger_unlimited_literals,
+ set_doc, show_doc, help_doc, nullptr,
+ nullptr, set_func, show_func,
+ set_list, show_list);
+ return commands;
+}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_uinteger_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<unsigned int>::set set_func,
+ setting_func_types<unsigned int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
+ nullptr,
+ uinteger_unlimited_literals,
+ set_doc, show_doc, help_doc,
+ set_func, get_func, nullptr,
+ show_func, set_list,
+ show_list);
return cmds;
}
struct cmd_list_element **set_list,
struct cmd_list_element **show_list)
{
- return add_setshow_cmd_full<int> (name, theclass, var_zinteger, var,
+ return add_setshow_cmd_full<int> (name, theclass, var_integer, var,
set_doc, show_doc, help_doc,
nullptr, nullptr, set_func,
show_func, set_list, show_list);
cmd_list_element **set_list,
cmd_list_element **show_list)
{
- return add_setshow_cmd_full<int> (name, theclass, var_zinteger, nullptr,
+ return add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
set_doc, show_doc, help_doc, set_func,
get_func, nullptr, show_func, set_list,
show_list);
}
+/* Accept `unlimited' or -1, using -1 internally. */
+const literal_def 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
add_setshow_zuinteger_unlimited_cmd (const char *name,
enum command_class theclass,
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited, var,
+ = add_setshow_cmd_full<int> (name, theclass, var_pinteger, var,
+ pinteger_unlimited_literals,
set_doc, show_doc, help_doc, nullptr,
nullptr, set_func, show_func, set_list,
show_list);
-
- set_cmd_completer (commands.set, integer_unlimited_completer);
-
return commands;
}
cmd_list_element **show_list)
{
auto cmds
- = add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited,
- nullptr, set_doc, show_doc, help_doc, set_func,
+ = add_setshow_cmd_full<int> (name, theclass, var_pinteger, nullptr,
+ pinteger_unlimited_literals,
+ set_doc, show_doc, help_doc, set_func,
get_func, nullptr, show_func, set_list,
show_list);
-
- set_cmd_completer (cmds.set, integer_unlimited_completer);
-
return cmds;
}
struct cmd_list_element **set_list,
struct cmd_list_element **show_list)
{
- return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
+ return add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
var, set_doc, show_doc, help_doc,
nullptr, nullptr, set_func,
show_func, set_list, show_list);
cmd_list_element **set_list,
cmd_list_element **show_list)
{
- return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
+ return add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
nullptr, set_doc, show_doc,
help_doc, set_func, get_func,
nullptr, show_func, set_list,
/* For var_uinteger options. */
unsigned int uinteger;
- /* For var_zuinteger_unlimited options. */
+ /* For var_integer and var_pinteger options. */
int integer;
/* For var_enum options. */
return option_def_and_value {*match, match_ctx, val};
}
case var_uinteger:
- case var_zuinteger_unlimited:
+ case var_integer:
+ case var_pinteger:
{
- if (completion != nullptr)
+ if (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')
{
- /* Convenience to let the user know what the option
- can accept. Note there's no common prefix between
- the strings on purpose, so that readline doesn't do
- a partial match. */
completion->tracker.add_completion
(make_unique_xstrdup ("NUMBER"));
- completion->tracker.add_completion
- (make_unique_xstrdup ("unlimited"));
+ for (const literal_def *l = match->extra_literals;
+ l->literal != nullptr;
+ l++)
+ completion->tracker.add_completion
+ (make_unique_xstrdup (l->literal));
return {};
}
- else if (startswith ("unlimited", *args))
+ else
{
- completion->tracker.add_completion
- (make_unique_xstrdup ("unlimited"));
- return {};
+ bool completions = false;
+ for (const literal_def *l = match->extra_literals;
+ l->literal != nullptr;
+ l++)
+ if (startswith (l->literal, *args))
+ {
+ completion->tracker.add_completion
+ (make_unique_xstrdup (l->literal));
+ completions = true;
+ }
+ if (completions)
+ return {};
}
}
- if (match->type == var_zuinteger_unlimited)
- {
- option_value val;
- val.integer = parse_cli_var_zuinteger_unlimited (args, false);
- return option_def_and_value {*match, match_ctx, val};
- }
+ LONGEST v = parse_cli_var_integer (match->type,
+ match->extra_literals,
+ args, false);
+ option_value val;
+ if (match->type == var_uinteger)
+ val.uinteger = v;
else
- {
- option_value val;
- val.uinteger = parse_cli_var_uinteger (match->type, args, false);
- return option_def_and_value {*match, match_ctx, val};
- }
+ val.integer = v;
+ return option_def_and_value {*match, match_ctx, val};
}
case var_enum:
{
*ov->option.var_address.uinteger (ov->option, ov->ctx)
= ov->value->uinteger;
break;
- case var_zuinteger_unlimited:
+ case var_integer:
+ case var_pinteger:
*ov->option.var_address.integer (ov->option, ov->ctx)
= ov->value->integer;
break;
case var_boolean:
return "[on|off]";
case var_uinteger:
- case var_zuinteger_unlimited:
- return "NUMBER|unlimited";
+ case var_integer:
+ case var_pinteger:
+ {
+ buffer = "NUMBER";
+ if (opt.extra_literals != nullptr)
+ for (const literal_def *l = opt.extra_literals;
+ l->literal != nullptr;
+ l++)
+ {
+ buffer += '|';
+ buffer += l->literal;
+ }
+ return buffer.c_str ();
+ }
case var_enum:
{
buffer = "";
{
add_setshow_uinteger_cmd (option.name, cmd_class,
option.var_address.uinteger (option, data),
+ option.extra_literals,
option.set_doc, option.show_doc,
option.help_doc,
nullptr, option.show_cmd_cb,
set_list, show_list);
}
- else if (option.type == var_zuinteger_unlimited)
+ else if (option.type == var_integer)
+ {
+ add_setshow_integer_cmd (option.name, cmd_class,
+ option.var_address.integer (option, data),
+ option.extra_literals,
+ option.set_doc, option.show_doc,
+ option.help_doc,
+ nullptr, option.show_cmd_cb,
+ set_list, show_list);
+ }
+ else if (option.type == var_pinteger)
{
- add_setshow_zuinteger_unlimited_cmd
- (option.name, cmd_class,
- option.var_address.integer (option, data),
- option.set_doc, option.show_doc,
- option.help_doc,
- nullptr, option.show_cmd_cb,
- set_list, show_list);
+ add_setshow_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)
{
used to create the option's "set/show" commands. */
constexpr option_def (const char *name_,
var_types var_type_,
+ const literal_def *extra_literals_,
erased_get_var_address_ftype *erased_get_var_address_,
show_value_ftype *show_cmd_cb_,
const char *set_doc_,
const char *show_doc_,
const char *help_doc_)
- : name (name_), type (var_type_),
+ : name (name_), type (var_type_), extra_literals (extra_literals_),
erased_get_var_address (erased_get_var_address_),
var_address {},
show_cmd_cb (show_cmd_cb_),
/* The option's type. */
var_types type;
+ /* Extra literals, such as `unlimited', accepted in lieu of a number. */
+ const literal_def *extra_literals;
+
/* A function that gets the controlling variable's address, type
erased. */
erased_get_var_address_ftype *erased_get_var_address;
const char *set_doc_,
const char *show_doc_ = nullptr,
const char *help_doc_ = nullptr)
- : option_def (long_option_, var_boolean,
+ : option_def (long_option_, var_boolean, nullptr,
(erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_,
set_doc_, show_doc_, help_doc_)
{
uinteger_option_def (const char *long_option_,
unsigned int *(*get_var_address_cb_) (Context *),
+ const literal_def *extra_literals_,
show_value_ftype *show_cmd_cb_,
const char *set_doc_,
const char *show_doc_ = nullptr,
const char *help_doc_ = nullptr)
- : option_def (long_option_, var_uinteger,
+ : option_def (long_option_, var_uinteger, extra_literals_,
(erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_,
set_doc_, show_doc_, help_doc_)
{
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>
-struct zuinteger_unlimited_option_def : option_def
+struct pinteger_option_def : option_def
{
- zuinteger_unlimited_option_def (const char *long_option_,
- int *(*get_var_address_cb_) (Context *),
- show_value_ftype *show_cmd_cb_,
- const char *set_doc_,
- const char *show_doc_ = nullptr,
- const char *help_doc_ = nullptr)
- : option_def (long_option_, var_zuinteger_unlimited,
+ pinteger_option_def (const char *long_option_,
+ int *(*get_var_address_cb_) (Context *),
+ const literal_def *extra_literals_,
+ show_value_ftype *show_cmd_cb_,
+ const char *set_doc_,
+ const char *show_doc_ = nullptr,
+ const char *help_doc_ = nullptr)
+ : option_def (long_option_, var_pinteger, extra_literals_,
(erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_,
set_doc_, show_doc_, help_doc_)
{
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. */
const char *set_doc_,
const char *show_doc_ = nullptr,
const char *help_doc_ = nullptr)
- : option_def (long_option_, var_enum,
+ : option_def (long_option_, var_enum, nullptr,
(erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_,
set_doc_, show_doc_, help_doc_)
const char *set_doc_,
const char *show_doc_ = nullptr,
const char *help_doc_ = nullptr)
- : option_def (long_option_, var_string,
+ : option_def (long_option_, var_string, nullptr,
(erased_get_var_address_ftype *) get_var_address_cb_,
show_cmd_cb_,
set_doc_, show_doc_, help_doc_)
}
}
-/* Returns true if ARG is "unlimited". */
+/* Returns true and the value in VAL if ARG is an accepted literal. */
static bool
-is_unlimited_literal (const char **arg, bool expression)
+get_literal_val (LONGEST &val, const literal_def *extra_literals,
+ const char **arg, bool expression)
{
*arg = skip_spaces (*arg);
size_t len = p - *arg;
- if (len > 0 && strncmp ("unlimited", *arg, len) == 0)
- {
- *arg += len;
-
- /* If parsing an expression (i.e., parsing for a "set" command),
- anything after "unlimited" is junk. For options, anything
- after "unlimited" might be a command argument or another
- option. */
- if (expression)
+ if (len > 0 && extra_literals != nullptr)
+ for (const literal_def *l = extra_literals;
+ l->literal != nullptr;
+ l++)
+ if (strncmp (l->literal, *arg, len) == 0)
{
- const char *after = skip_spaces (*arg);
- if (*after != '\0')
- error (_("Junk after \"%.*s\": %s"),
- (int) len, unl_start, after);
- }
+ *arg += len;
- return true;
- }
+ /* If parsing an expression (i.e., parsing for a "set" command),
+ anything after the literal is junk. For options, anything
+ after the literal might be a command argument or another
+ option. */
+ if (expression)
+ {
+ const char *after = skip_spaces (*arg);
+ if (*after != '\0')
+ error (_("Junk after \"%.*s\": %s"),
+ (int) len, unl_start, after);
+ }
+
+ val = l->use;
+ return true;
+ }
return false;
}
/* See cli-setshow.h. */
-unsigned int
-parse_cli_var_uinteger (var_types var_type, const char **arg,
- bool expression)
+LONGEST
+parse_cli_var_integer (var_types var_type, const literal_def *extra_literals,
+ const char **arg, bool expression)
{
LONGEST val;
if (*arg == nullptr || **arg == '\0')
{
- if (var_type == var_uinteger)
- error_no_arg (_("integer to set it to, or \"unlimited\""));
- else
+ if (extra_literals == nullptr)
error_no_arg (_("integer to set it to"));
- }
-
- if (var_type == var_uinteger && is_unlimited_literal (arg, expression))
- val = 0;
- else if (expression)
- val = parse_and_eval_long (*arg);
- else
- val = get_ulongest (arg);
-
- if (var_type == var_uinteger && val == 0)
- val = UINT_MAX;
- else if (val < 0
- /* For var_uinteger, don't let the user set the value
- to UINT_MAX directly, as that exposes an
- implementation detail to the user interface. */
- || (var_type == var_uinteger && val >= UINT_MAX)
- || (var_type == var_zuinteger && val > UINT_MAX))
- error (_("integer %s out of range"), plongest (val));
-
- return val;
-}
-
-/* See cli-setshow.h. */
+ else
+ {
+ std::string buffer = "";
+ size_t count = 0;
-int
-parse_cli_var_zuinteger_unlimited (const char **arg, bool expression)
-{
- LONGEST val;
+ for (const literal_def *l = extra_literals;
+ l->literal != nullptr;
+ l++, count++)
+ {
+ if (count != 0)
+ buffer += ", ";
+ buffer = buffer + '"' + l->literal + '"';
+ }
+ if (count > 1)
+ error_no_arg
+ (string_printf (_("integer to set it to, or one of: %s"),
+ buffer.c_str ()).c_str ());
+ else
+ error_no_arg
+ (string_printf (_("integer to set it to, or %s"),
+ buffer.c_str ()).c_str ());
+ }
+ }
- if (*arg == nullptr || **arg == '\0')
- error_no_arg (_("integer to set it to, or \"unlimited\""));
+ if (!get_literal_val (val, extra_literals, arg, expression))
+ {
+ if (expression)
+ val = parse_and_eval_long (*arg);
+ else
+ val = get_ulongest (arg);
- if (is_unlimited_literal (arg, expression))
- val = -1;
- else if (expression)
- val = parse_and_eval_long (*arg);
- else
- val = get_ulongest (arg);
+ enum tribool allowed = TRIBOOL_UNKNOWN;
+ if (extra_literals != nullptr)
+ {
+ for (const literal_def *l = extra_literals;
+ l->literal != nullptr;
+ l++)
+ if (l->val.has_value () && val == *l->val)
+ {
+ allowed = TRIBOOL_TRUE;
+ val = l->use;
+ break;
+ }
+ else if (val == l->use)
+ allowed = TRIBOOL_FALSE;
+ }
- if (val > INT_MAX)
- error (_("integer %s out of range"), plongest (val));
- else if (val < -1)
- error (_("only -1 is allowed to set as unlimited"));
+ if (allowed == TRIBOOL_UNKNOWN)
+ {
+ if (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)
+ error (_("integer %s out of range"), plongest (val));
+ }
return val;
}
option_changed = c->var->set<enum auto_boolean> (parse_auto_binary_operation (arg));
break;
case var_uinteger:
- case var_zuinteger:
option_changed
- = c->var->set<unsigned int> (parse_cli_var_uinteger (c->var->type (),
- &arg, true));
+ = c->var->set<unsigned int> (parse_cli_var_integer (c->var->type (),
+ c->var->
+ extra_literals (),
+ &arg, true));
break;
case var_integer:
- case var_zinteger:
- {
- LONGEST val;
-
- if (*arg == '\0')
- {
- if (c->var->type () == var_integer)
- error_no_arg (_("integer to set it to, or \"unlimited\""));
- else
- error_no_arg (_("integer to set it to"));
- }
-
- if (c->var->type () == var_integer && is_unlimited_literal (&arg, true))
- val = 0;
- else
- val = parse_and_eval_long (arg);
-
- if (val == 0 && c->var->type () == var_integer)
- val = INT_MAX;
- else if (val < INT_MIN
- /* For var_integer, don't let the user set the value
- to INT_MAX directly, as that exposes an
- implementation detail to the user interface. */
- || (c->var->type () == var_integer && val >= INT_MAX)
- || (c->var->type () == var_zinteger && val > INT_MAX))
- error (_("integer %s out of range"), plongest (val));
-
- option_changed = c->var->set<int> (val);
- }
+ case var_pinteger:
+ option_changed
+ = c->var->set<int> (parse_cli_var_integer (c->var->type (),
+ c->var->extra_literals (),
+ &arg, true));
break;
case var_enum:
{
option_changed = c->var->set<const char *> (match);
}
break;
- case var_zuinteger_unlimited:
- option_changed = c->var->set<int>
- (parse_cli_var_zuinteger_unlimited (&arg, true));
- break;
default:
error (_("gdb internal error: bad var_type in do_setshow_command"));
}
}
break;
case var_uinteger:
- case var_zuinteger:
{
char s[64];
}
break;
case var_integer:
- case var_zinteger:
- case var_zuinteger_unlimited:
+ case var_pinteger:
{
char s[64];
}
break;
case var_uinteger:
- case var_zuinteger:
- {
- const unsigned int value = var.get<unsigned int> ();
-
- if (var.type () == var_uinteger
- && value == UINT_MAX)
- stb.puts ("unlimited");
- else
- stb.printf ("%u", value);
- }
- break;
case var_integer:
- case var_zinteger:
- {
- const int value = var.get<int> ();
-
- if (var.type () == var_integer
- && value == INT_MAX)
- stb.puts ("unlimited");
- else
- stb.printf ("%d", value);
- }
- break;
- case var_zuinteger_unlimited:
+ case var_pinteger:
{
- const int value = var.get<int> ();
- if (value == -1)
- stb.puts ("unlimited");
- else
- stb.printf ("%d", value);
+ 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.extra_literals () != nullptr)
+ for (const literal_def *l = var.extra_literals ();
+ l->literal != nullptr;
+ l++)
+ if (value == l->use)
+ {
+ stb.puts (l->literal);
+ printed = true;
+ break;
+ }
+ if (!printed)
+ {
+ if (var.type () == var_uinteger)
+ stb.printf ("%u", static_cast<unsigned int> (value));
+ else
+ stb.printf ("%d", static_cast<int> (value));
+ }
}
break;
default:
past a successfully parsed value. */
extern int parse_cli_boolean_value (const char **arg);
-/* Parse ARG, an option to a var_uinteger or var_zuinteger variable.
- Either returns the parsed value on success or throws an error. If
- EXPRESSION is true, *ARG is parsed as an expression; otherwise, it
- is parsed with get_ulongest. It's not possible to parse the
+/* Parse ARG, an option to a var_uinteger, var_integer or var_pinteger
+ variable. Return the parsed value on success or throw an error. If
+ EXTRA_LITERALS is non-null, then interpret those literals accordingly.
+ If EXPRESSION is true, *ARG is parsed as an expression; otherwise,
+ it is parsed with get_ulongest. It's not possible to parse the
integer as an expression when there may be valid input after the
integer, such as when parsing command options. E.g., "print
-elements NUMBER -obj --". In such case, parsing as an expression
would parse "-obj --" as part of the expression as well. */
-extern unsigned int parse_cli_var_uinteger (var_types var_type,
- const char **arg,
- bool expression);
-
-/* Like parse_cli_var_uinteger, for var_zuinteger_unlimited. */
-extern int parse_cli_var_zuinteger_unlimited (const char **arg,
- bool expression);
+extern LONGEST parse_cli_var_integer (var_types var_type,
+ const literal_def *extra_literals,
+ const char **arg,
+ bool expression);
/* Parse ARG, an option to a var_enum variable. ENUM is a
null-terminated array of possible values. Either returns the parsed
value. */
var_auto_boolean,
- /* Unsigned Integer. *VAR is an unsigned int. The user can type
- 0 to mean "unlimited", which is stored in *VAR as UINT_MAX. */
+ /* Unsigned Integer. *VAR is an unsigned int. In the Guile and Python
+ APIs 0 means unlimited, which is stored in *VAR as UINT_MAX. */
var_uinteger,
- /* Like var_uinteger but signed. *VAR is an int. The user can
- type 0 to mean "unlimited", which is stored in *VAR as
- INT_MAX. The only remaining use of it is the Python API.
- Don't use it elsewhere. */
+ /* Like var_uinteger but signed. *VAR is an int. In the Guile and
+ Python APIs 0 means unlimited, which is stored in *VAR as INT_MAX. */
var_integer,
+ /* Like var_integer but negative numbers are not allowed,
+ except for special values. *VAR is an int. */
+ var_pinteger,
+
/* String which the user enters with escapes (e.g. the user types
\n and it is a real newline in the stored string).
*VAR is a std::string, "" if the string is empty. */
var_optional_filename,
/* String which stores a filename. (*VAR) is a std::string. */
var_filename,
- /* ZeroableInteger. *VAR is an int. Like var_integer except
- that zero really means zero. */
- 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.
*VAR is a char pointer to the name of the element that we
find. */
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.
This function is left without definition intentionally. This template is
template<>
inline bool var_type_uses<unsigned int> (var_types t)
{
- return (t == var_uinteger || t == var_zinteger || t == var_zuinteger);
+ return t == var_uinteger;
}
/* Return true if a setting of type T is backed by an int variable. */
template<>
inline bool var_type_uses<int> (var_types t)
{
- return (t == var_integer || t == var_zinteger
- || t == var_zuinteger_unlimited);
+ return t == var_integer || t == var_pinteger;
}
/* Return true if a setting of type T is backed by a std::string variable. */
Type T must match the var type VAR_TYPE (see VAR_TYPE_USES). */
template<typename T>
- setting (var_types var_type, T *var)
- : m_var_type (var_type), m_var (var)
+ setting (var_types var_type, T *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_type_uses<T> (var_type));
};
}
- /* Create a setting backed by pre-validated type-erased args.
- ERASED_VAR's fields' real types must match the var type VAR_TYPE
- (see VAR_TYPE_USES). */
- setting (var_types var_type, const erased_args &args)
+ /* Create a setting backed by pre-validated type-erased args and using
+ EXTRA_LITERALS. ERASED_VAR's fields' real types must match the var
+ type VAR_TYPE (see VAR_TYPE_USES). */
+ setting (var_types var_type, const literal_def *extra_literals,
+ const erased_args &args)
: m_var_type (var_type),
m_var (args.var),
+ m_extra_literals (extra_literals),
m_getter (args.getter),
m_setter (args.setter)
{
var_types type () const
{ return m_var_type; }
+ /* Access any extra literals accepted. */
+ const literal_def *extra_literals () const
+ { return m_extra_literals; }
+
/* Return the current value.
The template parameter T is the type of the variable used to store the
non-nullptr. */
void *m_var = nullptr;
+ /* Any extra literals accepted. */
+ const literal_def *m_extra_literals = nullptr;
+
/* Pointer to a user provided getter. */
erased_func m_getter = nullptr;
instead print the value out directly. */
extern show_value_ftype deprecated_show_value_hack;
+/* Various sets of extra literals accepted. */
+extern const literal_def integer_unlimited_literals[];
+extern const literal_def uinteger_unlimited_literals[];
+extern const literal_def pinteger_unlimited_literals[];
+
extern set_show_commands add_setshow_enum_cmd
(const char *name, command_class theclass, const char *const *enumlist,
const char **var, const char *set_doc, const char *show_doc,
show_value_ftype *show_func, cmd_list_element **set_list,
cmd_list_element **show_list);
+extern set_show_commands add_setshow_integer_cmd
+ (const char *name, command_class theclass, int *var,
+ const literal_def *extra_literals, const char *set_doc,
+ const char *show_doc, const char *help_doc, cmd_func_ftype *set_func,
+ show_value_ftype *show_func, cmd_list_element **set_list,
+ cmd_list_element **show_list);
+
+extern set_show_commands add_setshow_integer_cmd
+ (const char *name, command_class theclass, const literal_def *extra_literals,
+ const char *set_doc, const char *show_doc, const char *help_doc,
+ setting_func_types<int>::set set_func,
+ setting_func_types<int>::get get_func, show_value_ftype *show_func,
+ cmd_list_element **set_list, cmd_list_element **show_list);
+
extern set_show_commands add_setshow_integer_cmd
(const char *name, command_class theclass, int *var, const char *set_doc,
const char *show_doc, const char *help_doc, cmd_func_ftype *set_func,
setting_func_types<int>::get get_func, show_value_ftype *show_func,
cmd_list_element **set_list, cmd_list_element **show_list);
+extern set_show_commands add_setshow_pinteger_cmd
+ (const char *name, command_class theclass, int *var,
+ const literal_def *extra_literals, const char *set_doc,
+ const char *show_doc, const char *help_doc, cmd_func_ftype *set_func,
+ show_value_ftype *show_func, cmd_list_element **set_list,
+ cmd_list_element **show_list);
+
+extern set_show_commands add_setshow_pinteger_cmd
+ (const char *name, command_class theclass, const literal_def *extra_literals,
+ const char *set_doc, const char *show_doc, const char *help_doc,
+ setting_func_types<int>::set set_func,
+ setting_func_types<int>::get get_func, show_value_ftype *show_func,
+ cmd_list_element **set_list, cmd_list_element **show_list);
+
+extern set_show_commands add_setshow_uinteger_cmd
+ (const char *name, command_class theclass, unsigned int *var,
+ const literal_def *extra_literals,
+ const char *set_doc, const char *show_doc, const char *help_doc,
+ cmd_func_ftype *set_func, show_value_ftype *show_func,
+ cmd_list_element **set_list, cmd_list_element **show_list);
+
+extern set_show_commands add_setshow_uinteger_cmd
+ (const char *name, command_class theclass, const literal_def *extra_literals,
+ const char *set_doc, const char *show_doc, const char *help_doc,
+ setting_func_types<unsigned int>::set set_func,
+ setting_func_types<unsigned int>::get get_func, show_value_ftype *show_func,
+ cmd_list_element **set_list, cmd_list_element **show_list);
+
extern set_show_commands add_setshow_uinteger_cmd
(const char *name, command_class theclass, unsigned int *var,
const char *set_doc, const char *show_doc, const char *help_doc,
@findex PARAM_UINTEGER
@findex gdb.PARAM_UINTEGER
@item gdb.PARAM_UINTEGER
-The value is an unsigned integer. The value of 0 should be
-interpreted to mean ``unlimited''.
+The value is an unsigned integer. The value of @code{None} should be
+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 gdb.PARAM_INTEGER
@item gdb.PARAM_INTEGER
-The value is a signed integer. The value of 0 should be interpreted
-to mean ``unlimited''.
+The value is a signed integer. The value of @code{None} should be
+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 gdb.PARAM_STRING
@findex PARAM_ZINTEGER
@findex gdb.PARAM_ZINTEGER
@item gdb.PARAM_ZINTEGER
-The value is an integer. This is like @code{PARAM_INTEGER}, except 0
-is interpreted as itself.
+The value is a signed integer. This is like @code{PARAM_INTEGER},
+except that 0 is allowed and the value of @code{None} is not supported.
@findex PARAM_ZUINTEGER
@findex gdb.PARAM_ZUINTEGER
@item gdb.PARAM_ZUINTEGER
-The value is an unsigned integer. This is like @code{PARAM_INTEGER},
-except 0 is interpreted as itself, and the value cannot be negative.
+The value is an unsigned integer. This is like @code{PARAM_UINTEGER},
+except that 0 is allowed and the value of @code{None} is not supported.
@findex PARAM_ZUINTEGER_UNLIMITED
@findex gdb.PARAM_ZUINTEGER_UNLIMITED
@item gdb.PARAM_ZUINTEGER_UNLIMITED
-The value is a signed integer. This is like @code{PARAM_ZUINTEGER},
-except the special value -1 should be interpreted to mean
-``unlimited''. Other negative values are not allowed.
+The value is a signed integer. This is like @code{PARAM_INTEGER}
+including that the value of @code{None} should be interpreted to mean
+``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 gdb.PARAM_ENUM
/* One of the COMMAND_* constants. */
enum command_class cmd_class;
+ /* Guile parameter type name. */
+ const char *pname;
+
/* 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;
+
/* The docs for the parameter. */
char *set_doc;
char *show_doc;
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
is used to manipulate the value in S->VALUE in a type safe manner using
the setting interface. */
static setting
make_setting (param_smob *s)
{
- if (var_type_uses<bool> (s->type))
- return setting (s->type, &s->value.boolval);
- else if (var_type_uses<int> (s->type))
- return setting (s->type, &s->value.intval);
- else if (var_type_uses<auto_boolean> (s->type))
- return setting (s->type, &s->value.autoboolval);
- else if (var_type_uses<unsigned int> (s->type))
- return setting (s->type, &s->value.uintval);
- else if (var_type_uses<std::string> (s->type))
- return setting (s->type, s->value.stringval);
- else if (var_type_uses<const char *> (s->type))
- return setting (s->type, &s->value.cstringval);
+ enum var_types type = s->type;
+
+ if (var_type_uses<bool> (type))
+ return setting (type, &s->value.boolval);
+ else if (var_type_uses<int> (type))
+ return setting (type, &s->value.intval, s->extra_literals);
+ else if (var_type_uses<auto_boolean> (type))
+ return setting (type, &s->value.autoboolval);
+ else if (var_type_uses<unsigned int> (type))
+ return setting (type, &s->value.uintval, s->extra_literals);
+ else if (var_type_uses<std::string> (type))
+ return setting (type, s->value.stringval);
+ else if (var_type_uses<const char *> (type))
+ return setting (type, &s->value.cstringval);
else
gdb_assert_not_reached ("unhandled var type");
}
static SCM show_doc_keyword;
static SCM initial_value_keyword;
static SCM auto_keyword;
-static SCM unlimited_keyword;
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,
const char *func_name);
\f
if (! pascm_is_valid (p_smob))
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);
scm_display (value, port);
function. */
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 *set_doc, char *show_doc, char *help_doc,
cmd_func_ftype *set_func,
case var_uinteger:
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_func, set_list, show_list);
break;
- case var_zinteger:
- commands = add_setshow_zinteger_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_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);
+ case var_integer:
+ commands = add_setshow_integer_cmd (cmd_name, cmd_class,
+ &self->value.intval,
+ extra_literals, 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);
+ 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_func, set_list, show_list);
break;
case var_string:
static const scheme_integer_constant parameter_types[] =
{
- /* Note: var_integer is deprecated, and intentionally does not
- appear here. */
- { "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */
- { "PARAM_AUTO_BOOLEAN", var_auto_boolean },
- { "PARAM_ZINTEGER", var_zinteger },
- { "PARAM_UINTEGER", var_uinteger },
- { "PARAM_ZUINTEGER", var_zuinteger },
- { "PARAM_ZUINTEGER_UNLIMITED", var_zuinteger_unlimited },
- { "PARAM_STRING", var_string },
- { "PARAM_STRING_NOESCAPE", var_string_noescape },
- { "PARAM_OPTIONAL_FILENAME", var_optional_filename },
- { "PARAM_FILENAME", var_filename },
- { "PARAM_ENUM", var_enum },
+ { "PARAM_BOOLEAN", param_boolean }, /* ARI: param_boolean */
+ { "PARAM_AUTO_BOOLEAN", param_auto_boolean },
+ { "PARAM_ZINTEGER", param_zinteger },
+ { "PARAM_UINTEGER", param_uinteger },
+ { "PARAM_ZUINTEGER", param_zuinteger },
+ { "PARAM_ZUINTEGER_UNLIMITED", param_zuinteger_unlimited },
+ { "PARAM_STRING", param_string },
+ { "PARAM_STRING_NOESCAPE", param_string_noescape },
+ { "PARAM_OPTIONAL_FILENAME", param_optional_filename },
+ { "PARAM_FILENAME", param_filename },
+ { "PARAM_ENUM", param_enum },
END_INTEGER_CONSTANTS
};
/* Return PARAM_TYPE as a string. */
static const char *
-pascm_param_type_name (enum var_types param_type)
+pascm_param_type_name (enum param_types param_type)
{
int i;
static SCM
pascm_param_value (const setting &var, int arg_pos, const char *func_name)
{
- /* Note: We *could* support var_integer here in case someone is trying to get
- the value of a Python-created parameter (which is the only place that
- still supports var_integer). To further discourage its use we do not. */
-
switch (var.type ())
{
case var_string:
return auto_keyword;
}
- case var_zuinteger_unlimited:
- if (var.get<int> () == -1)
- return unlimited_keyword;
- gdb_assert (var.get<int> () >= 0);
- /* Fall through. */
- case var_zinteger:
- return scm_from_int (var.get<int> ());
-
case var_uinteger:
- if (var.get<unsigned int> ()== UINT_MAX)
- return unlimited_keyword;
- /* Fall through. */
- case var_zuinteger:
- return scm_from_uint (var.get<unsigned int> ());
+ case var_integer:
+ case var_pinteger:
+ {
+ LONGEST value
+ = (var.type () == var_uinteger
+ ? static_cast<LONGEST> (var.get<unsigned int> ())
+ : static_cast<LONGEST> (var.get<int> ()));
+
+ 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:
break;
var.set<enum auto_boolean> (AUTO_BOOLEAN_FALSE);
break;
- case var_zinteger:
+ case var_integer:
case var_uinteger:
- case var_zuinteger:
- case var_zuinteger_unlimited:
- if (var.type () == var_uinteger
- || var.type () == var_zuinteger_unlimited)
- {
- SCM_ASSERT_TYPE (scm_is_integer (value)
- || scm_is_eq (value, unlimited_keyword),
- value, arg_pos, func_name,
- _("integer or #:unlimited"));
- if (scm_is_eq (value, unlimited_keyword))
+ case var_pinteger:
+ {
+ const literal_def *extra_literals = p_smob->extra_literals;
+ enum tribool allowed = TRIBOOL_UNKNOWN;
+ enum var_types var_type = var.type ();
+ bool integer = scm_is_integer (value);
+ bool keyword = scm_is_keyword (value);
+ std::string buffer = "";
+ size_t count = 0;
+ LONGEST val;
+
+ if (extra_literals != nullptr)
+ for (const literal_def *l = extra_literals;
+ l->literal != nullptr;
+ l++, count++)
{
- if (var.type () == var_uinteger)
- var.set<unsigned int> (UINT_MAX);
- else
- var.set<int> (-1);
- break;
+ if (count != 0)
+ buffer += ", ";
+ buffer = buffer + "#:" + l->literal;
+ if (keyword
+ && 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
- || var.type () == var_zuinteger)
- {
- unsigned int u = scm_to_uint (value);
+ if (allowed == TRIBOOL_UNKNOWN)
+ {
+ if (extra_literals == nullptr)
+ 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 ());
+
+ val = (var_type == var_uinteger
+ ? static_cast<LONGEST> (scm_to_uint (value))
+ : static_cast<LONGEST> (scm_to_int (value)));
+
+ 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 (var.type () == var_uinteger && u == 0)
- u = UINT_MAX;
- var.set<unsigned int> (u);
- }
- else
- {
- int i = scm_to_int (value);
+ 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)
+ gdbscm_out_of_range_error (func_name, arg_pos, value,
+ _("integer out of range"));
- if (var.type () == var_zuinteger_unlimited && i < -1)
- {
- gdbscm_out_of_range_error (func_name, arg_pos, value,
- _("must be >= -1"));
- }
- var.set<int> (i);
- }
- break;
+ if (var_type == var_uinteger)
+ var.set<unsigned int> (static_cast<unsigned int> (val));
+ else
+ var.set<int> (static_cast<int> (val));
+
+ break;
+ }
default:
gdb_assert_not_reached ("bad parameter type");
char *s;
char *name;
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 set_func = SCM_BOOL_F, show_func = SCM_BOOL_F;
char *doc = NULL, *set_doc = NULL, *show_doc = NULL;
scm_from_int (param_type),
_("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,
_("#: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,
_("PARAM_ENUM requires an enum-values argument"));
SCM_ASSERT_TYPE (gdbscm_is_procedure (show_func), show_func,
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
freeing it if we later throw an exception. */
freeing them if we throw an exception. */
p_smob->name = name;
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->set_doc = set_doc;
p_smob->show_doc = show_doc;
try
{
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,
(gdbscm_is_procedure (p_smob->set_func) ? pascm_set_func : NULL),
(gdbscm_is_procedure (p_smob->show_func) ? pascm_show_func : NULL),
show_doc_keyword = scm_from_latin1_keyword ("show-doc");
initial_value_keyword = scm_from_latin1_keyword ("initial-value");
auto_keyword = scm_from_latin1_keyword ("auto");
- unlimited_keyword = scm_from_latin1_keyword ("unlimited");
}
available kinds of commands (boolean, enum, flag, string, uinteger):
(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]
off on
(gdb) maint test-options require-delimiter -enum [TAB]
xxx yyy zzz
- (gdb) maint test-options require-delimiter -uinteger [TAB]
+ (gdb) maint test-options require-delimiter -uinteger-unlimited [TAB]
NUMBER unlimited
'-xx1' and '-xx2' are flag options too. They exist in order to
Invoking the commands makes them print out the options parsed:
(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
- -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 --
Unrecognized option at: 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
order to do something similar for completion:
bool xx2_opt = false;
bool boolean_opt = false;
const char *enum_opt = test_options_enum_values_xxx;
- unsigned int uint_opt = 0;
- int zuint_unl_opt = 0;
+ unsigned int uint_unl_opt = 0;
+ int pint_unl_opt = 0;
std::string string_opt;
test_options_opts () = default;
{
gdb_printf (file,
_("-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,
xx1_opt,
xx2_opt,
boolean_opt,
enum_opt,
- (uint_opt == UINT_MAX
+ (uint_unl_opt == UINT_MAX
? "unlimited"
- : pulongest (uint_opt)),
- (zuint_unl_opt == -1
+ : pulongest (uint_unl_opt)),
+ (pint_unl_opt == -1
? "unlimited"
- : plongest (zuint_unl_opt)),
+ : plongest (pint_unl_opt)),
string_opt.c_str (),
args);
}
N_("An enum option."),
},
- /* A uinteger option. */
+ /* A uinteger + "unlimited" option. */
gdb::option::uinteger_option_def<test_options_opts> {
- "uinteger",
- [] (test_options_opts *opts) { return &opts->uint_opt; },
+ "uinteger-unlimited",
+ [] (test_options_opts *opts) { return &opts->uint_unl_opt; },
+ uinteger_unlimited_literals,
nullptr, /* show_cmd_cb */
N_("A uinteger option."),
nullptr, /* show_doc */
N_("A help doc that spawns\nmultiple lines."),
},
- /* A zuinteger_unlimited option. */
- gdb::option::zuinteger_unlimited_option_def<test_options_opts> {
- "zuinteger-unlimited",
- [] (test_options_opts *opts) { return &opts->zuint_unl_opt; },
+ /* A pinteger + "unlimited" option. */
+ gdb::option::pinteger_option_def<test_options_opts> {
+ "pinteger-unlimited",
+ [] (test_options_opts *opts) { return &opts->pint_unl_opt; },
+ pinteger_unlimited_literals,
nullptr, /* show_cmd_cb */
- N_("A zuinteger-unlimited option."),
+ N_("A pinteger-unlimited option."),
nullptr, /* show_doc */
nullptr, /* help_doc */
},
#include "language.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. */
static struct {
const char *name;
int value;
} parm_constants[] =
{
- { "PARAM_BOOLEAN", var_boolean }, /* ARI: var_boolean */
- { "PARAM_AUTO_BOOLEAN", var_auto_boolean },
- { "PARAM_UINTEGER", var_uinteger },
- { "PARAM_INTEGER", var_integer },
- { "PARAM_STRING", var_string },
- { "PARAM_STRING_NOESCAPE", var_string_noescape },
- { "PARAM_OPTIONAL_FILENAME", var_optional_filename },
- { "PARAM_FILENAME", var_filename },
- { "PARAM_ZINTEGER", var_zinteger },
- { "PARAM_ZUINTEGER", var_zuinteger },
- { "PARAM_ZUINTEGER_UNLIMITED", var_zuinteger_unlimited },
- { "PARAM_ENUM", var_enum },
+ { "PARAM_BOOLEAN", param_boolean }, /* ARI: param_boolean */
+ { "PARAM_AUTO_BOOLEAN", param_auto_boolean },
+ { "PARAM_UINTEGER", param_uinteger },
+ { "PARAM_INTEGER", param_integer },
+ { "PARAM_STRING", param_string },
+ { "PARAM_STRING_NOESCAPE", param_string_noescape },
+ { "PARAM_OPTIONAL_FILENAME", param_optional_filename },
+ { "PARAM_FILENAME", param_filename },
+ { "PARAM_ZINTEGER", param_zinteger },
+ { "PARAM_ZUINTEGER", param_zuinteger },
+ { "PARAM_ZUINTEGER_UNLIMITED", param_zuinteger_unlimited },
+ { "PARAM_ENUM", param_enum },
{ NULL, 0 }
};
/* 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;
+
/* The value of the parameter. */
union parmpy_variable value;
static setting
make_setting (parmpy_object *s)
{
- if (var_type_uses<bool> (s->type))
- return setting (s->type, &s->value.boolval);
- else if (var_type_uses<int> (s->type))
- return setting (s->type, &s->value.intval);
- else if (var_type_uses<auto_boolean> (s->type))
- return setting (s->type, &s->value.autoboolval);
- else if (var_type_uses<unsigned int> (s->type))
- return setting (s->type, &s->value.uintval);
- else if (var_type_uses<std::string> (s->type))
- return setting (s->type, s->value.stringval);
- else if (var_type_uses<const char *> (s->type))
- return setting (s->type, &s->value.cstringval);
+ enum var_types type = s->type;
+
+ if (var_type_uses<bool> (type))
+ return setting (type, &s->value.boolval);
+ else if (var_type_uses<int> (type))
+ return setting (type, &s->value.intval, s->extra_literals);
+ else if (var_type_uses<auto_boolean> (type))
+ return setting (type, &s->value.autoboolval);
+ else if (var_type_uses<unsigned int> (type))
+ return setting (type, &s->value.uintval, s->extra_literals);
+ else if (var_type_uses<std::string> (type))
+ return setting (type, s->value.stringval);
+ else if (var_type_uses<const char *> (type))
+ return setting (type, &s->value.cstringval);
else
gdb_assert_not_reached ("unhandled var type");
}
}
break;
- case var_integer:
- case var_zinteger:
case var_uinteger:
- case var_zuinteger:
- case var_zuinteger_unlimited:
+ case var_integer:
+ case var_pinteger:
{
- long l;
- int ok;
-
- if (value == Py_None
- && (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))
+ const literal_def *extra_literals = self->extra_literals;
+ enum tribool allowed = TRIBOOL_UNKNOWN;
+ enum var_types var_type = self->type;
+ std::string buffer = "";
+ size_t count = 0;
+ LONGEST val;
+
+ if (extra_literals != nullptr)
{
- PyErr_SetString (PyExc_RuntimeError,
- _("The value must be integer."));
- return -1;
+ gdb::unique_xmalloc_ptr<char>
+ str (python_string_to_host_string (value));
+ const char *s = str != nullptr ? str.get () : nullptr;
+ PyErr_Clear ();
+
+ for (const literal_def *l = extra_literals;
+ l->literal != nullptr;
+ l++, count++)
+ {
+ if (count != 0)
+ buffer += ", ";
+ buffer = buffer + "'" + l->literal + "'";
+ if (allowed == TRIBOOL_UNKNOWN
+ && ((value == Py_None && !strcmp ("unlimited", l->literal))
+ || (s != nullptr && !strcmp (s, l->literal))))
+ {
+ val = l->use;
+ allowed = TRIBOOL_TRUE;
+ }
+ }
}
- else if (! gdb_py_int_as_long (value, &l))
- return -1;
- switch (self->type)
+ if (allowed == TRIBOOL_UNKNOWN)
{
- case var_uinteger:
- if (l == 0)
- l = UINT_MAX;
- /* Fall through. */
- case var_zuinteger:
- ok = (l >= 0 && l <= UINT_MAX);
- break;
-
- case var_zuinteger_unlimited:
- ok = (l >= -1 && l <= INT_MAX);
- break;
-
- 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");
+ 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 (! ok)
+ if (allowed == TRIBOOL_FALSE)
{
PyErr_SetString (PyExc_RuntimeError,
_("Range exceeded."));
return -1;
}
- if (self->type == var_uinteger || self->type == var_zuinteger)
- self->value.uintval = (unsigned) l;
+ if (self->type == var_uinteger)
+ self->value.uintval = (unsigned) val;
else
- self->value.intval = (int) l;
+ self->value.intval = (int) val;
break;
}
/* A helper function that dispatches to the appropriate add_setshow
function. */
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,
parmpy_object *self,
const char *set_doc, const char *show_doc,
{
set_show_commands commands;
- switch (parmclass)
+ switch (type)
{
case var_boolean:
commands = add_setshow_boolean_cmd (cmd_name.get (), cmdclass,
case var_uinteger:
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,
get_show_value, set_list, show_list);
break;
case var_integer:
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,
get_show_value, set_list, show_list);
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:
commands = add_setshow_string_cmd (cmd_name.get (), cmdclass,
self->value.stringval, set_doc,
get_show_value, set_list, show_list);
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:
/* Initialize the value, just in case. */
self->value.cstringval = self->enumeration[0];
int parmclass, cmdtype;
PyObject *enum_values = NULL;
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,
&enum_values))
return -1;
}
- if (parmclass != var_boolean /* ARI: var_boolean */
- && parmclass != var_auto_boolean
- && parmclass != var_uinteger && parmclass != var_integer
- && parmclass != var_string && parmclass != var_string_noescape
- && parmclass != var_optional_filename && parmclass != var_filename
- && parmclass != var_zinteger && parmclass != var_zuinteger
- && parmclass != var_zuinteger_unlimited && parmclass != var_enum)
+ if (parmclass != param_boolean /* ARI: param_boolean */
+ && parmclass != param_auto_boolean
+ && parmclass != param_uinteger && parmclass != param_integer
+ && parmclass != param_string && parmclass != param_string_noescape
+ && parmclass != param_optional_filename && parmclass != param_filename
+ && parmclass != param_zinteger && parmclass != param_zuinteger
+ && parmclass != param_zuinteger_unlimited && parmclass != param_enum)
{
PyErr_SetString (PyExc_RuntimeError,
_("Invalid parameter class argument."));
return -1;
}
- if (enum_values && parmclass != var_enum)
+ if (enum_values && parmclass != param_enum)
{
PyErr_SetString (PyExc_RuntimeError,
_("Only PARAM_ENUM accepts a fourth argument."));
return -1;
}
- if (parmclass == var_enum)
+ if (parmclass == param_enum)
{
if (! compute_enum_values (obj, enum_values))
return -1;
}
else
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));
if (var_type_uses<std::string> (obj->type))
try
{
- add_setshow_generic (parmclass, (enum command_class) cmdtype,
+ add_setshow_generic (type, extra_literals,
+ (enum command_class) cmdtype,
std::move (cmd_name), obj,
set_doc.get (), show_doc.get (),
doc.get (), set_list, show_list);
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_integer:
+ case var_pinteger:
{
- unsigned int val = var.get<unsigned int> ();
-
- if (val == UINT_MAX)
- Py_RETURN_NONE;
- return gdb_py_object_from_ulongest (val).release ();
- }
-
- case var_zuinteger:
- {
- unsigned int val = var.get<unsigned int> ();
- return gdb_py_object_from_ulongest (val).release ();
+ LONGEST value
+ = (var.type () == var_uinteger
+ ? static_cast<LONGEST> (var.get<unsigned int> ())
+ : static_cast<LONGEST> (var.get<int> ()));
+
+ if (var.extra_literals () != nullptr)
+ for (const literal_def *l = var.extra_literals ();
+ l->literal != nullptr;
+ l++)
+ if (value == l->use)
+ {
+ 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 ();
+ }
+
+ if (var.type () == var_uinteger)
+ return
+ gdb_py_object_from_ulongest
+ (static_cast<unsigned int> (value)).release ();
+ else
+ return
+ gdb_py_object_from_longest
+ (static_cast<int> (value)).release ();
}
}
gdb_test "set max-value-size 0" \
"max-value-size set too low, increasing to \[0-9\]+ bytes"
gdb_test "set max-value-size -5" \
- "only -1 is allowed to set as unlimited"
+ "integer -5 out of range"
# test-options xxx", with no flag/option set. OPERAND is the expected
# 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
# test-options xxx", with -flag set. OPERAND is the expected 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
# test-options xxx", with -bool set. OPERAND is the expected 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
# OPTION determines which option to expect set. OPERAND is the
# expected operand.
proc expect_integer {option val operand} {
- if {$option == "uinteger"} {
- return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint $val -zuint-unl 0 -string '' -- $operand"
- } elseif {$option == "zuinteger-unlimited"} {
- return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint 0 -zuint-unl $val -string '' -- $operand"
+ if {$option == "uinteger-unlimited"} {
+ return "-flag 0 -xx1 0 -xx2 0 -bool 0 -enum xxx -uint-unl $val\
+ -pint-unl 0 -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 {
error "unsupported option: $option"
}
&& [string range $str end end] == "'")} {
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 {
"-bool"
"-enum"
"-flag"
+ "-pinteger-unlimited"
"-string"
- "-uinteger"
+ "-uinteger-unlimited"
"-xx1"
"-xx2"
- "-zuinteger-unlimited"
}
# Basic option-machinery + "print" command integration tests.
# Extract twice the same flag, separated by one space.
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.
gdb_test "$cmd -xx1 -xx2 -a -b -c -xx1 --" \
}
# 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} {
global all_options
set cmd "[make_cmd $variant] -$option"
- # Test completing a uinteger option:
+ # Test completing an integer option:
res_test_gdb_complete_multiple \
"1 [expect_none ""]" \
"$cmd " "" "" {
gdb_test "$cmd 1 -- 999" [expect_integer $option "1" "999"]
gdb_test "$cmd 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 0 --" [expect_integer $option "0" ""]
} else {
"Expected integer at: unlimitedx --"
# Don't offer completions until we're past the
- # -uinteger/-zuinteger-unlimited argument.
+ # -uinteger-unlimited/-pinteger-unlimited argument.
res_test_gdb_complete_none \
"1 [expect_none ""]" \
"$cmd 1"
}
# Try "-1".
- if {$option == "uinteger"} {
- # -1 is invalid uinteger.
+ if {$option == "uinteger-unlimited"} {
+ # -1 is invalid uinteger-unlimited.
foreach value {"-1" "-1 "} {
res_test_gdb_complete_none \
"1 [expect_none ""]" \
"$cmd $value"
}
} else {
- # -1 is valid for zuinteger-unlimited.
+ # -1 is valid for pinteger-unlimited.
res_test_gdb_complete_none \
"1 [expect_none ""]" \
"$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- "} {
if {$variant == "require-delimiter"} {
res_test_gdb_complete_none \
test-misc $cmd
test-flag $cmd
test-boolean $cmd
- foreach subcmd {"uinteger" "zuinteger-unlimited" } {
+ foreach subcmd {"uinteger-unlimited" "pinteger-unlimited" } {
test-uinteger $cmd $subcmd
}
test-enum $cmd
if {$variant == "zuinteger-unlimited"} {
# -1 means unlimited. Other negative values are rejected. -1
# -is tested further below, along the "unlimited" tests.
- gdb_test "$set_cmd -2" "only -1 is allowed to set as unlimited"
+ gdb_test "$set_cmd -2" "integer -2 out of range"
check_type "test-settings $variant" "type = int"
} elseif {$variant == "uinteger" || $variant == "zuinteger"} {
# Negative values are not accepted.
test_with_error "zuinteger" "" \
"Argument required \\(integer to set it to\\)\\."
test_with_error "zuinteger-unlimited" "-2" \
- "only -1 is allowed to set as unlimited"
+ "integer -2 out of range"
test_with_error "zuinteger-unlimited" "" \
"Argument required \\(integer to set it to, or \"unlimited\"\\)\\."
test_with_error "filename" "" \
\\(3\\) \\(3\\)\\)>"
switch -- $param {
"listsize" {
- set param_get_one $param_type_error
- set param_get_zero $param_type_error
- set param_get_minus_one $param_type_error
- set param_get_unlimited $param_type_error
+ set param_get_zero "#:unlimited"
+ set param_get_minus_one -1
set param_set_minus_one ""
}
"print elements" {
- set param_get_one 1
set param_get_zero "#:unlimited"
set param_get_minus_one "#:unlimited"
- set param_get_unlimited "#:unlimited"
set param_set_minus_one $param_range_error
}
"max-completions" {
- set param_get_one 1
set param_get_zero 0
set param_get_minus_one "#:unlimited"
- set param_get_unlimited "#:unlimited"
set param_set_minus_one ""
}
default {
gdb_test_no_output "set $param 1" "test set to 1"
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 unlimited" "test set to 'unlimited'"
gdb_test "guile (print (parameter-value \"$param\"))" \
- $param_get_unlimited "test value of 'unlimited'"
+ "#:unlimited" "test value of 'unlimited'"
}
foreach_with_prefix kind {
#:unlimited" \
"Error while executing Scheme code\\."]
set param_minus_one_error "integer -1 out of range"
- set param_minus_two_range "integer -2 out of range"
- set param_minus_two_unlimited "only -1 is allowed to set as unlimited"
+ set param_minus_two_error "integer -2 out of range"
switch -- $kind {
PARAM_UINTEGER {
set param_get_zero "#:unlimited"
set param_str_unlimited unlimited
set param_set_unlimited ""
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 {
set param_get_zero 0
set param_str_unlimited 2
set param_set_unlimited $param_integer_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 {
set param_get_zero 0
set param_str_unlimited unlimited
set param_set_unlimited ""
set param_set_minus_one ""
- set param_set_minus_two $param_minus_two_unlimited
+ set param_set_minus_two $param_minus_two_error
}
default {
error "invalid kind: $kind"
set param_get_minus_one None
set param_get_minus_five 1
set param_get_none None
+ set param_get_unlimited None
set param_set_minus_one $param_range_error
set param_set_minus_five $param_range_error
set param_set_none ""
set param_get_minus_one -1
set param_get_minus_five -5
set param_get_none None
+ set param_get_unlimited None
set param_set_minus_one -1
set param_set_minus_five -5
set param_set_none ""
set param_get_minus_one -1
set param_get_minus_five -5
set param_get_none 5
+ set param_get_unlimited 0
set param_set_minus_one ""
set param_set_minus_five ""
set param_set_none $param_integer_error
set param_get_minus_one 0
set param_get_minus_five 1
set param_get_none 5
+ set param_get_unlimited 0
set param_set_minus_one $param_range_error
set param_set_minus_five $param_range_error
set param_set_none $param_integer_error
set param_get_minus_one -1
set param_get_minus_five 1
set param_get_none -1
+ set param_get_unlimited -1
set param_set_minus_one ""
set param_set_minus_five $param_range_error
set param_set_none ""
gdb_test "python print(gdb.parameter('test-$kind'))" \
$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"
}
}
= gdb::option::boolean_option_def<value_print_options>;
using uinteger_option_def
= gdb::option::uinteger_option_def<value_print_options>;
-using zuinteger_unlimited_option_def
- = gdb::option::zuinteger_unlimited_option_def<value_print_options>;
+using pinteger_option_def
+ = gdb::option::pinteger_option_def<value_print_options>;
/* Definitions of options for the "print" and "compile print"
commands. */
uinteger_option_def {
"elements",
[] (value_print_options *opt) { return &opt->print_max; },
+ uinteger_unlimited_literals,
show_print_max, /* show_cmd_cb */
N_("Set limit on string chars or array elements to print."),
N_("Show limit on string chars or array elements to print."),
N_("\"unlimited\" causes there to be no limit."),
},
- zuinteger_unlimited_option_def {
+ pinteger_option_def {
"max-depth",
[] (value_print_options *opt) { return &opt->max_depth; },
+ pinteger_unlimited_literals,
show_print_max_depth, /* show_cmd_cb */
N_("Set maximum print depth for nested structures, unions and arrays."),
N_("Show maximum print depth for nested structures, unions, and arrays."),
uinteger_option_def {
"repeats",
[] (value_print_options *opt) { return &opt->repeat_count_threshold; },
+ uinteger_unlimited_literals,
show_repeat_count_threshold, /* show_cmd_cb */
N_("Set threshold for repeated print elements."),
N_("Show threshold for repeated print elements."),