diff options
-rw-r--r-- | gdb/cli/cli-cmds.c | 59 | ||||
-rw-r--r-- | gdb/cli/cli-decode.c | 321 | ||||
-rw-r--r-- | gdb/cli/cli-option.c | 104 | ||||
-rw-r--r-- | gdb/cli/cli-option.h | 54 | ||||
-rw-r--r-- | gdb/cli/cli-setshow.c | 247 | ||||
-rw-r--r-- | gdb/cli/cli-setshow.h | 20 | ||||
-rw-r--r-- | gdb/command.h | 113 | ||||
-rw-r--r-- | gdb/doc/python.texi | 28 | ||||
-rw-r--r-- | gdb/guile/scm-param.c | 320 | ||||
-rw-r--r-- | gdb/maint-test-options.c | 44 | ||||
-rw-r--r-- | gdb/python/py-param.c | 296 | ||||
-rw-r--r-- | gdb/python/python.c | 56 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/max-value-size.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/options.exp | 47 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/settings.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/with.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.guile/scm-parameter.exp | 23 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-parameter.exp | 15 | ||||
-rw-r--r-- | gdb/valprint.c | 9 |
19 files changed, 1136 insertions, 626 deletions
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index b41aa49..6c0d780 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -2213,22 +2213,40 @@ value_from_setting (const setting &var, struct gdbarch *gdbarch) { 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; @@ -2250,17 +2268,6 @@ value_from_setting (const setting &var, struct gdbarch *gdbarch) 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: @@ -2330,13 +2337,11 @@ str_value_from_setting (const setting &var, struct gdbarch *gdbarch) { 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); diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c index fdc29c0..2a4f9b4 100644 --- a/gdb/cli/cli-decode.c +++ b/gdb/cli/cli-decode.c @@ -496,6 +496,8 @@ empty_func (const char *args, int from_tty, cmd_list_element *c) 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. */ @@ -505,6 +507,7 @@ add_set_or_show_cmd (const char *name, 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) @@ -513,7 +516,7 @@ add_set_or_show_cmd (const char *name, 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. */ @@ -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. 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. */ @@ -534,6 +539,7 @@ static set_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, @@ -557,14 +563,16 @@ add_setshow_cmd_full_erased (const char *name, 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; @@ -575,14 +583,41 @@ add_setshow_cmd_full_erased (const char *name, 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. */ @@ -592,6 +627,7 @@ 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, @@ -604,16 +640,43 @@ add_setshow_cmd_full (const char *name, 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 @@ -982,25 +1045,6 @@ add_setshow_optional_filename_cmd (const char *name, command_class theclass, 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 @@ -1009,6 +1053,55 @@ integer_unlimited_completer (struct cmd_list_element *ignore, 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, const char *set_doc, const char *show_doc, const char *help_doc, @@ -1019,12 +1112,10 @@ add_setshow_integer_cmd (const char *name, enum command_class theclass, { 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; } @@ -1042,12 +1133,54 @@ add_setshow_integer_cmd (const char *name, command_class theclass, 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; } @@ -1058,7 +1191,7 @@ add_setshow_integer_cmd (const char *name, command_class theclass, 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, @@ -1068,12 +1201,9 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass, { 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; } @@ -1082,6 +1212,7 @@ add_setshow_uinteger_cmd (const char *name, enum command_class theclass, 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, @@ -1091,13 +1222,63 @@ add_setshow_uinteger_cmd (const char *name, command_class theclass, 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; } @@ -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 **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); @@ -1135,12 +1316,22 @@ add_setshow_zinteger_cmd (const char *name, command_class theclass, 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, @@ -1154,13 +1345,11 @@ add_setshow_zuinteger_unlimited_cmd (const char *name, 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; } @@ -1178,13 +1367,11 @@ add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass, 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; } @@ -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 **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); @@ -1222,7 +1409,7 @@ add_setshow_zuinteger_cmd (const char *name, command_class theclass, 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, diff --git a/gdb/cli/cli-option.c b/gdb/cli/cli-option.c index 95dc9ab..9b303b1 100644 --- a/gdb/cli/cli-option.c +++ b/gdb/cli/cli-option.c @@ -38,7 +38,7 @@ union option_value /* For var_uinteger options. */ unsigned int uinteger; - /* For var_zuinteger_unlimited options. */ + /* For var_integer and var_pinteger options. */ int integer; /* For var_enum options. */ @@ -356,42 +356,52 @@ parse_option (gdb::array_view<const option_def_group> options_group, 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: { @@ -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->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; @@ -664,8 +675,20 @@ get_val_type_str (const option_def &opt, std::string &buffer) case var_boolean: return "[on|off]"; case var_uinteger: - case var_zuinteger_unlimited: - return "NUMBER|unlimited"; + case var_integer: + case var_pinteger: + { + buffer = "NUMBER"; + if (opt.extra_literals != nullptr) + for (const literal_def *l = opt.extra_literals; + l->literal != nullptr; + l++) + { + buffer += '|'; + buffer += l->literal; + } + return buffer.c_str (); + } case var_enum: { buffer = ""; @@ -789,20 +812,31 @@ add_setshow_cmds_for_options (command_class cmd_class, { 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) { diff --git a/gdb/cli/cli-option.h b/gdb/cli/cli-option.h index 319ae3b..7b015b8 100644 --- a/gdb/cli/cli-option.h +++ b/gdb/cli/cli-option.h @@ -49,12 +49,13 @@ protected: used to create the option's "set/show" commands. */ constexpr option_def (const char *name_, var_types var_type_, + const literal_def *extra_literals_, erased_get_var_address_ftype *erased_get_var_address_, show_value_ftype *show_cmd_cb_, const char *set_doc_, const char *show_doc_, const char *help_doc_) - : name (name_), type (var_type_), + : name (name_), type (var_type_), extra_literals (extra_literals_), erased_get_var_address (erased_get_var_address_), var_address {}, show_cmd_cb (show_cmd_cb_), @@ -68,6 +69,9 @@ public: /* The option's type. */ var_types type; + /* Extra literals, such as `unlimited', accepted in lieu of a number. */ + const literal_def *extra_literals; + /* A function that gets the controlling variable's address, type erased. */ erased_get_var_address_ftype *erased_get_var_address; @@ -160,7 +164,7 @@ struct boolean_option_def : option_def const char *set_doc_, const char *show_doc_ = nullptr, const char *help_doc_ = nullptr) - : option_def (long_option_, var_boolean, + : option_def (long_option_, var_boolean, nullptr, (erased_get_var_address_ftype *) get_var_address_cb_, show_cmd_cb_, set_doc_, show_doc_, help_doc_) @@ -207,37 +211,59 @@ struct uinteger_option_def : option_def { uinteger_option_def (const char *long_option_, unsigned int *(*get_var_address_cb_) (Context *), + const literal_def *extra_literals_, show_value_ftype *show_cmd_cb_, const char *set_doc_, const char *show_doc_ = nullptr, const char *help_doc_ = nullptr) - : option_def (long_option_, var_uinteger, + : option_def (long_option_, var_uinteger, extra_literals_, (erased_get_var_address_ftype *) get_var_address_cb_, show_cmd_cb_, set_doc_, show_doc_, help_doc_) { 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. */ @@ -252,7 +278,7 @@ struct enum_option_def : option_def const char *set_doc_, const char *show_doc_ = nullptr, const char *help_doc_ = nullptr) - : option_def (long_option_, var_enum, + : option_def (long_option_, var_enum, nullptr, (erased_get_var_address_ftype *) get_var_address_cb_, show_cmd_cb_, set_doc_, show_doc_, help_doc_) @@ -273,7 +299,7 @@ struct string_option_def : option_def const char *set_doc_, const char *show_doc_ = nullptr, const char *help_doc_ = nullptr) - : option_def (long_option_, var_string, + : option_def (long_option_, var_string, nullptr, (erased_get_var_address_ftype *) get_var_address_cb_, show_cmd_cb_, set_doc_, show_doc_, help_doc_) diff --git a/gdb/cli/cli-setshow.c b/gdb/cli/cli-setshow.c index dccf04e..dad3e60 100644 --- a/gdb/cli/cli-setshow.c +++ b/gdb/cli/cli-setshow.c @@ -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 -is_unlimited_literal (const char **arg, bool expression) +get_literal_val (LONGEST &val, const literal_def *extra_literals, + const char **arg, bool expression) { *arg = skip_spaces (*arg); @@ -162,85 +163,104 @@ is_unlimited_literal (const char **arg, bool expression) 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; } @@ -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)); break; case var_uinteger: - case var_zuinteger: option_changed - = c->var->set<unsigned int> (parse_cli_var_uinteger (c->var->type (), - &arg, true)); + = c->var->set<unsigned int> (parse_cli_var_integer (c->var->type (), + c->var-> + extra_literals (), + &arg, true)); break; case var_integer: - case var_zinteger: - { - LONGEST val; - - if (*arg == '\0') - { - if (c->var->type () == var_integer) - error_no_arg (_("integer to set it to, or \"unlimited\"")); - else - error_no_arg (_("integer to set it to")); - } - - if (c->var->type () == var_integer && is_unlimited_literal (&arg, true)) - val = 0; - else - val = parse_and_eval_long (arg); - - if (val == 0 && c->var->type () == var_integer) - val = INT_MAX; - else if (val < INT_MIN - /* For var_integer, don't let the user set the value - to INT_MAX directly, as that exposes an - implementation detail to the user interface. */ - || (c->var->type () == var_integer && val >= INT_MAX) - || (c->var->type () == var_zinteger && val > INT_MAX)) - error (_("integer %s out of range"), plongest (val)); - - option_changed = c->var->set<int> (val); - } + case var_pinteger: + option_changed + = c->var->set<int> (parse_cli_var_integer (c->var->type (), + c->var->extra_literals (), + &arg, true)); break; case var_enum: { @@ -454,10 +451,6 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) option_changed = c->var->set<const char *> (match); } break; - case var_zuinteger_unlimited: - option_changed = c->var->set<int> - (parse_cli_var_zuinteger_unlimited (&arg, true)); - break; default: error (_("gdb internal error: bad var_type in do_setshow_command")); } @@ -551,7 +544,6 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) } break; case var_uinteger: - case var_zuinteger: { char s[64]; @@ -560,8 +552,7 @@ do_set_command (const char *arg, int from_tty, struct cmd_list_element *c) } break; case var_integer: - case var_zinteger: - case var_zuinteger_unlimited: + case var_pinteger: { char s[64]; @@ -623,36 +614,32 @@ get_setshow_command_value_string (const setting &var) } 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: diff --git a/gdb/cli/cli-setshow.h b/gdb/cli/cli-setshow.h index 78573c0..bc70ea6 100644 --- a/gdb/cli/cli-setshow.h +++ b/gdb/cli/cli-setshow.h @@ -29,21 +29,19 @@ extern int parse_cli_boolean_value (const char *arg); 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 diff --git a/gdb/command.h b/gdb/command.h index 7d6f9c7..e9c9f16 100644 --- a/gdb/command.h +++ b/gdb/command.h @@ -84,16 +84,18 @@ enum var_types value. */ var_auto_boolean, - /* Unsigned Integer. *VAR is an unsigned int. The user can type - 0 to mean "unlimited", which is stored in *VAR as UINT_MAX. */ + /* Unsigned Integer. *VAR is an unsigned int. In the Guile and Python + APIs 0 means unlimited, which is stored in *VAR as UINT_MAX. */ var_uinteger, - /* Like var_uinteger but signed. *VAR is an int. The user can - type 0 to mean "unlimited", which is stored in *VAR as - INT_MAX. The only remaining use of it is the Python API. - Don't use it elsewhere. */ + /* Like var_uinteger but signed. *VAR is an int. In the Guile and + Python APIs 0 means unlimited, which is stored in *VAR as INT_MAX. */ var_integer, + /* Like var_integer but negative numbers are not allowed, + except for special values. *VAR is an int. */ + var_pinteger, + /* String which the user enters with escapes (e.g. the user types \n and it is a real newline in the stored string). *VAR is a std::string, "" if the string is empty. */ @@ -106,22 +108,27 @@ enum var_types var_optional_filename, /* String which stores a filename. (*VAR) is a std::string. */ var_filename, - /* ZeroableInteger. *VAR is an int. Like var_integer except - that zero really means zero. */ - 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 @@ -152,15 +159,14 @@ inline bool var_type_uses<enum auto_boolean> (var_types t) 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. */ @@ -218,8 +224,9 @@ struct setting 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)); @@ -258,12 +265,14 @@ struct setting }; } - /* 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) { @@ -294,6 +303,10 @@ struct setting 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 @@ -356,6 +369,9 @@ private: 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; @@ -651,6 +667,11 @@ typedef void (show_value_ftype) (struct ui_file *file, 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, @@ -747,6 +768,20 @@ extern set_show_commands add_setshow_optional_filename_cmd cmd_list_element **show_list); extern set_show_commands add_setshow_integer_cmd + (const char *name, command_class theclass, int *var, + const literal_def *extra_literals, const char *set_doc, + const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, + show_value_ftype *show_func, cmd_list_element **set_list, + cmd_list_element **show_list); + +extern set_show_commands add_setshow_integer_cmd + (const char *name, command_class theclass, const literal_def *extra_literals, + const char *set_doc, const char *show_doc, const char *help_doc, + setting_func_types<int>::set set_func, + setting_func_types<int>::get get_func, show_value_ftype *show_func, + cmd_list_element **set_list, cmd_list_element **show_list); + +extern set_show_commands add_setshow_integer_cmd (const char *name, command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, cmd_list_element **set_list, @@ -759,6 +794,34 @@ extern set_show_commands add_setshow_integer_cmd 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, diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 7208af3..d9a9a5f 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -4611,14 +4611,18 @@ Python, true and false are represented using boolean constants, and @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 @@ -4648,21 +4652,23 @@ The value is a filename. This is just like @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 diff --git a/gdb/guile/scm-param.c b/gdb/guile/scm-param.c index a28bb8f..0bb87b0 100644 --- a/gdb/guile/scm-param.c +++ b/gdb/guile/scm-param.c @@ -75,9 +75,15 @@ struct param_smob /* 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; @@ -110,6 +116,49 @@ struct param_smob 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. */ @@ -117,18 +166,20 @@ struct param_smob static setting make_setting (param_smob *s) { - if (var_type_uses<bool> (s->type)) - return setting (s->type, &s->value.boolval); - else if (var_type_uses<int> (s->type)) - return setting (s->type, &s->value.intval); - else if (var_type_uses<auto_boolean> (s->type)) - return setting (s->type, &s->value.autoboolval); - else if (var_type_uses<unsigned int> (s->type)) - return setting (s->type, &s->value.uintval); - else if (var_type_uses<std::string> (s->type)) - return setting (s->type, s->value.stringval); - else if (var_type_uses<const char *> (s->type)) - return setting (s->type, &s->value.cstringval); + enum var_types type = s->type; + + 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"); } @@ -149,10 +200,9 @@ static SCM set_doc_keyword; 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); @@ -171,7 +221,7 @@ pascm_print_param_smob (SCM self, SCM port, scm_print_state *pstate) 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); @@ -369,7 +419,9 @@ pascm_show_func (struct ui_file *file, int from_tty, 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, @@ -398,32 +450,26 @@ add_setshow_generic (enum var_types param_type, enum command_class cmd_class, 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: @@ -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[] = { - /* 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 }; @@ -568,7 +612,7 @@ pascm_valid_parameter_type_p (int param_type) /* 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; @@ -588,10 +632,6 @@ pascm_param_type_name (enum var_types param_type) static SCM pascm_param_value (const setting &var, int arg_pos, const char *func_name) { - /* Note: We *could* support var_integer here in case someone is trying to get - the value of a Python-created parameter (which is the only place that - still supports var_integer). To further discourage its use we do not. */ - switch (var.type ()) { case var_string: @@ -631,20 +671,29 @@ pascm_param_value (const setting &var, int arg_pos, const char *func_name) 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; @@ -735,53 +784,91 @@ pascm_set_param_value_x (param_smob *p_smob, 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"); @@ -858,7 +945,7 @@ gdbscm_make_parameter (SCM name_scm, SCM rest) 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; @@ -913,12 +1000,12 @@ gdbscm_make_parameter (SCM name_scm, SCM rest) 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")); @@ -933,7 +1020,7 @@ gdbscm_make_parameter (SCM name_scm, SCM rest) 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. */ @@ -950,7 +1037,10 @@ gdbscm_make_parameter (SCM name_scm, SCM rest) 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; @@ -1031,7 +1121,8 @@ gdbscm_register_parameter_x (SCM self) 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), @@ -1203,5 +1294,4 @@ gdbscm_initialize_parameters (void) 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"); } diff --git a/gdb/maint-test-options.c b/gdb/maint-test-options.c index 5f0007a..9e2e211 100644 --- a/gdb/maint-test-options.c +++ b/gdb/maint-test-options.c @@ -61,13 +61,15 @@ 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 @@ -76,14 +78,14 @@ 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: @@ -131,8 +133,8 @@ struct test_options_opts 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; @@ -145,18 +147,18 @@ struct test_options_opts { 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); } @@ -203,22 +205,24 @@ static const gdb::option::option_def test_options_option_defs[] = { 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 */ }, diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c index 2771bf4..a1bd4e0 100644 --- a/gdb/python/py-param.c +++ b/gdb/python/py-param.c @@ -28,24 +28,70 @@ #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 } }; @@ -80,6 +126,9 @@ struct parmpy_object /* 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; @@ -96,18 +145,20 @@ struct parmpy_object static setting make_setting (parmpy_object *s) { - if (var_type_uses<bool> (s->type)) - return setting (s->type, &s->value.boolval); - else if (var_type_uses<int> (s->type)) - return setting (s->type, &s->value.intval); - else if (var_type_uses<auto_boolean> (s->type)) - return setting (s->type, &s->value.autoboolval); - else if (var_type_uses<unsigned int> (s->type)) - return setting (s->type, &s->value.uintval); - else if (var_type_uses<std::string> (s->type)) - return setting (s->type, s->value.stringval); - else if (var_type_uses<const char *> (s->type)) - return setting (s->type, &s->value.cstringval); + enum var_types type = s->type; + + 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"); } @@ -234,68 +285,98 @@ set_parameter_value (parmpy_object *self, PyObject *value) } 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; } @@ -534,7 +615,8 @@ get_show_value (struct ui_file *file, int from_tty, /* 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, @@ -544,7 +626,7 @@ add_setshow_generic (int parmclass, enum command_class cmdclass, { set_show_commands commands; - switch (parmclass) + switch (type) { case var_boolean: 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: 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, @@ -607,30 +699,6 @@ add_setshow_generic (int parmclass, enum command_class cmdclass, 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]; @@ -740,6 +808,8 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) 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)) @@ -756,33 +826,36 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) 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)) @@ -805,7 +878,8 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) 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); diff --git a/gdb/python/python.c b/gdb/python/python.c index 9d55811..54623f4 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -504,27 +504,45 @@ gdbpy_parameter_value (const setting &var) 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 (); } } diff --git a/gdb/testsuite/gdb.base/max-value-size.exp b/gdb/testsuite/gdb.base/max-value-size.exp index 0a001e9..cc9ae77 100644 --- a/gdb/testsuite/gdb.base/max-value-size.exp +++ b/gdb/testsuite/gdb.base/max-value-size.exp @@ -92,4 +92,4 @@ gdb_test "set max-value-size 1" \ 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" diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp index 486192e..5a2b6d8 100644 --- a/gdb/testsuite/gdb.base/options.exp +++ b/gdb/testsuite/gdb.base/options.exp @@ -98,19 +98,22 @@ proc make_cmd {variant} { # 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 @@ -118,10 +121,12 @@ proc expect_bool {operand} { # 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" } @@ -138,18 +143,19 @@ proc expect_string {str operand} { && [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. @@ -604,7 +610,8 @@ proc_with_prefix test-flag {variant} { # 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 --" \ @@ -822,13 +829,13 @@ proc_with_prefix test-boolean {variant} { } # 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 " "" "" { @@ -852,7 +859,7 @@ proc_with_prefix test-uinteger {variant option} { 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 { @@ -865,7 +872,7 @@ proc_with_prefix test-uinteger {variant option} { "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" @@ -878,15 +885,15 @@ proc_with_prefix test-uinteger {variant option} { } # 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" @@ -914,7 +921,7 @@ proc_with_prefix test-uinteger {variant option} { 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 \ @@ -1032,7 +1039,7 @@ foreach_with_prefix cmd { 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 diff --git a/gdb/testsuite/gdb.base/settings.exp b/gdb/testsuite/gdb.base/settings.exp index f2215c2..e542039 100644 --- a/gdb/testsuite/gdb.base/settings.exp +++ b/gdb/testsuite/gdb.base/settings.exp @@ -143,7 +143,7 @@ proc test-integer {variant} { 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. diff --git a/gdb/testsuite/gdb.base/with.exp b/gdb/testsuite/gdb.base/with.exp index 75f4ddc..233dc30 100644 --- a/gdb/testsuite/gdb.base/with.exp +++ b/gdb/testsuite/gdb.base/with.exp @@ -104,7 +104,7 @@ with_test_prefix "maint" { 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" "" \ diff --git a/gdb/testsuite/gdb.guile/scm-parameter.exp b/gdb/testsuite/gdb.guile/scm-parameter.exp index d62ae47..5c97f4c 100644 --- a/gdb/testsuite/gdb.guile/scm-parameter.exp +++ b/gdb/testsuite/gdb.guile/scm-parameter.exp @@ -113,24 +113,18 @@ foreach_with_prefix param { \\(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 { @@ -141,7 +135,7 @@ foreach_with_prefix param { 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" @@ -157,7 +151,7 @@ foreach_with_prefix param { 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 { @@ -189,8 +183,7 @@ 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" @@ -199,7 +192,7 @@ foreach_with_prefix kind { 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 @@ -217,7 +210,7 @@ foreach_with_prefix kind { 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 @@ -226,7 +219,7 @@ foreach_with_prefix kind { 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" diff --git a/gdb/testsuite/gdb.python/py-parameter.exp b/gdb/testsuite/gdb.python/py-parameter.exp index e6a26dd..bec1c61 100644 --- a/gdb/testsuite/gdb.python/py-parameter.exp +++ b/gdb/testsuite/gdb.python/py-parameter.exp @@ -434,6 +434,7 @@ proc_with_prefix test_integer_parameter { } { 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 "" @@ -443,6 +444,7 @@ proc_with_prefix test_integer_parameter { } { 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 "" @@ -452,6 +454,7 @@ proc_with_prefix test_integer_parameter { } { 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 @@ -461,6 +464,7 @@ proc_with_prefix test_integer_parameter { } { 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 @@ -470,6 +474,7 @@ proc_with_prefix test_integer_parameter { } { 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 "" @@ -526,6 +531,16 @@ proc_with_prefix test_integer_parameter { } { 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" } } diff --git a/gdb/valprint.c b/gdb/valprint.c index 1fed828..77d1f13 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -2861,8 +2861,8 @@ using boolean_option_def = gdb::option::boolean_option_def<value_print_options>; using uinteger_option_def = gdb::option::uinteger_option_def<value_print_options>; -using zuinteger_unlimited_option_def - = gdb::option::zuinteger_unlimited_option_def<value_print_options>; +using pinteger_option_def + = gdb::option::pinteger_option_def<value_print_options>; /* Definitions of options for the "print" and "compile print" commands. */ @@ -2907,15 +2907,17 @@ static const gdb::option::option_def value_print_option_defs[] = { 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."), @@ -2975,6 +2977,7 @@ pretty-printers for that value.") uinteger_option_def { "repeats", [] (value_print_options *opt) { return &opt->repeat_count_threshold; }, + uinteger_unlimited_literals, show_repeat_count_threshold, /* show_cmd_cb */ N_("Set threshold for repeated print elements."), N_("Show threshold for repeated print elements."), |