forked from Imagelibrary/binutils-gdb
Rather than just `unlimited' allow the integer set commands (or command
options) to define arbitrary keywords for the user to use, removing
hardcoded arrangements for the `unlimited' keyword.
Remove the confusingly named `var_zinteger', `var_zuinteger' and
`var_zuinteger_unlimited' `set'/`show' command variable types redefining
them in terms of `var_uinteger', `var_integer' and `var_pinteger', which
have the range of [0;UINT_MAX], [INT_MIN;INT_MAX], and [0;INT_MAX] each.
Following existing practice `var_pinteger' allows extra negative values
to be used, however unlike `var_zuinteger_unlimited' any number of such
values can be defined rather than just `-1'.
The "p" in `var_pinteger' stands for "positive", for the lack of a more
appropriate unambiguous letter, even though 0 obviously is not positive;
"n" would be confusing as to whether it stands for "non-negative" or
"negative".
Add a new structure, `literal_def', the entries of which define extra
keywords allowed for a command and numerical values they correspond to.
Those values are not verified against the basic range supported by the
underlying variable type, allowing extra values to be allowed outside
that range, which may or may not be individually made visible to the
user. An optional value translation is possible with the structure to
follow the existing practice for some commands where user-entered 0 is
internally translated to UINT_MAX or INT_MAX. Such translation can now
be arbitrary. Literals defined by this structure are automatically used
for completion as necessary.
So for example:
const literal_def integer_unlimited_literals[] =
{
{ "unlimited", INT_MAX, 0 },
{ nullptr }
};
defines an extra `unlimited' keyword and a user-visible 0 value, both of
which get translated to INT_MAX for the setting to be used with.
Similarly:
const literal_def zuinteger_unlimited_literals[] =
{
{ "unlimited", -1, -1 },
{ nullptr }
};
defines the same keyword and a corresponding user-visible -1 value that
is used for the requested setting. If the last member were omitted (or
set to `{}') here, then only the keyword would be allowed for the user
to enter and while -1 would still be used internally trying to enter it
as a part of a command would result in an "integer -1 out of range"
error.
Use said error message in all cases (citing the invalid value requested)
replacing "only -1 is allowed to set as unlimited" previously used for
`var_zuinteger_unlimited' settings only rather than propagating it to
`var_pinteger' type. It could only be used for the specific case where
a single extra `unlimited' keyword was defined standing for -1 and the
use of numeric equivalents is discouraged anyway as it is for historical
reasons only that they expose GDB internals, confusingly different
across variable types. Similarly update the "must be >= -1" Guile error
message.
Redefine Guile and Python parameter types in terms of the new variable
types and interpret extra keywords as Scheme keywords and Python strings
used to communicate corresponding parameter values. Do not add a new
PARAM_INTEGER Guile parameter type, however do handle the `var_integer'
variable type now, permitting existing parameters defined by GDB proper,
such as `listsize', to be accessed from Scheme code.
With these changes in place it should be trivial for a Scheme or Python
programmer to expand the syntax of the `make-parameter' command and the
`gdb.Parameter' class initializer to have arbitrary extra literals along
with their internal representation supplied.
Update the testsuite accordingly.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
291 lines
9.2 KiB
Plaintext
291 lines
9.2 KiB
Plaintext
# This testcase is part of GDB, the GNU debugger.
|
|
|
|
# Copyright 2019-2023 Free Software Foundation, Inc.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# Test the "with" command.
|
|
|
|
load_lib completion-support.exp
|
|
|
|
standard_testfile .c
|
|
|
|
if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
|
|
return -1
|
|
}
|
|
|
|
clean_restart $binfile
|
|
|
|
# Test "maint with". VALUES is a list of values. A nested "with" is
|
|
# performed with each combination of pair of values from this list.
|
|
# This exercises setting a value, and restoring it too. This is
|
|
# particularly important for the "special" values like "unlimited",
|
|
# which for example for var_uinteger maps to 0 at the user-visible
|
|
# level, but maps to -1 internally.
|
|
|
|
proc test_with {setting values} {
|
|
foreach val1 $values {
|
|
foreach val2 $values {
|
|
gdb_test \
|
|
"maint with test-settings $setting $val1 -- maint with test-settings $setting $val2 -- p 1" \
|
|
" = 1"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Test "maint with" in the error case. SETTING is the "maint set
|
|
# test-setting" setting to exercise. TMP_VAL is the value to set the
|
|
# setting to. EXPECTED_RE is the expected GDB output, which should be
|
|
# an error of some kind. Also checks that the setting's original
|
|
# value is preserved across the error.
|
|
|
|
proc test_with_error {setting tmp_val expected_re} {
|
|
global gdb_prompt
|
|
|
|
with_test_prefix "$setting, $tmp_val" {
|
|
set test "save org value"
|
|
set org_val ""
|
|
gdb_test_multiple "maint show test-settings $setting" $test {
|
|
-re "(.*)\r\n$gdb_prompt $" {
|
|
set org_val $expect_out(1,string)
|
|
pass $test
|
|
}
|
|
}
|
|
|
|
gdb_test \
|
|
"maint with test-settings $setting $tmp_val -- p 1" \
|
|
$expected_re
|
|
|
|
gdb_test "maint show test-settings $setting" "^$org_val" \
|
|
"value hasn't changed across error"
|
|
}
|
|
}
|
|
|
|
# Test "with" framework basics, using the internal "maint with
|
|
# test-settings" subcommands.
|
|
with_test_prefix "maint" {
|
|
test_with "auto-boolean" {"on" "off" "auto"}
|
|
test_with "boolean" {"" "on" "off" "0" "1" "enable" "disable"}
|
|
test_with "integer" {"0" "1" "-1" "unlimited"}
|
|
test_with "uinteger" {"0" "1" "unlimited"}
|
|
test_with "zinteger" {"0" "1" "-1"}
|
|
test_with "zuinteger" {"0" "1"}
|
|
test_with "zuinteger-unlimited" {"-1" "unlimited" "0" "1"}
|
|
test_with "string" {"" "foo" "\"hello world\""}
|
|
test_with "string-noescape" {"" "foo" "\"hello world\""}
|
|
test_with "filename" {"/foo" "bar/x/y"}
|
|
test_with "optional-filename" {"" "/foo" "bar/x/y"}
|
|
test_with "enum" {"xxx" "yyy"}
|
|
|
|
# Check the most important error conditions. E.g., empty,
|
|
# negative or "unlimited" values for settings that don't accept
|
|
# those. Exhaustive error coverage of the set/with value parsing
|
|
# is left to "set" testing, in gdb.base/settings.exp.
|
|
test_with_error "auto-boolean" "" \
|
|
"\"on\", \"off\" or \"auto\" expected\\."
|
|
test_with_error "auto-boolean" "xxx" \
|
|
"\"on\", \"off\" or \"auto\" expected\\."
|
|
test_with_error "boolean" "2" "\"on\" or \"off\" expected\\."
|
|
test_with_error "uinteger" "-1" "integer -1 out of range"
|
|
test_with_error "uinteger" "" \
|
|
"Argument required \\(integer to set it to, or \"unlimited\"\\)\\."
|
|
test_with_error "zuinteger" "-1" "integer -1 out of range"
|
|
test_with_error "zuinteger" "" \
|
|
"Argument required \\(integer to set it to\\)\\."
|
|
test_with_error "zuinteger-unlimited" "-2" \
|
|
"integer -2 out of range"
|
|
test_with_error "zuinteger-unlimited" "" \
|
|
"Argument required \\(integer to set it to, or \"unlimited\"\\)\\."
|
|
test_with_error "filename" "" \
|
|
"Argument required \\(filename to set it to\\.\\)\\."
|
|
test_with_error "enum" "" \
|
|
"Requires an argument\\. Valid arguments are xxx, yyy, zzz\\."
|
|
}
|
|
|
|
# Basic/core tests using user-visible commands.
|
|
with_test_prefix "basics" {
|
|
gdb_test "print g_s" " = {a = 1, b = 2, c = 3}"
|
|
gdb_test "with print pretty -- print g_s" \
|
|
[multi_line \
|
|
" = {" \
|
|
" a = 1," \
|
|
" b = 2," \
|
|
" c = 3" \
|
|
"}"]
|
|
|
|
# A boolean setting.
|
|
gdb_test "with non-stop on -- show non-stop" \
|
|
"Controlling the inferior in non-stop mode is on\\."
|
|
gdb_test "show non-stop" \
|
|
"Controlling the inferior in non-stop mode is off\\."
|
|
|
|
# Language.
|
|
gdb_test "with language pascal -- show language" \
|
|
"The current source language is \"pascal\"\\."
|
|
|
|
gdb_test "show language" \
|
|
"The current source language is \"auto; currently c\"\\."
|
|
|
|
gdb_test "with language ada -- print g_s" \
|
|
" = \\(a => 1, b => 2, c => 3\\)"
|
|
|
|
# Nested "with"s.
|
|
gdb_test "with language ada -- with language c -- print g_s" \
|
|
" = {a = 1, b = 2, c = 3}"
|
|
|
|
# "w" alias.
|
|
gdb_test "w language pascal -- show language" \
|
|
"The current source language is \"pascal\"\\." \
|
|
"w alias works"
|
|
|
|
# An early prototype of the "with" command got this wrong.
|
|
gdb_test \
|
|
"w print repeats unlimited -- w print repeats 1 -- p \"1223334444\"" \
|
|
" = \"1\", '2' <repeats 2 times>, '3' <repeats 3 times>, '4' <repeats 4 times>"
|
|
}
|
|
|
|
# Check a user-defined command.
|
|
with_test_prefix "user-defined" {
|
|
# A user defined command.
|
|
set test "define usercmd"
|
|
gdb_test_multiple "define usercmd" $test {
|
|
-re "End with" {
|
|
gdb_test \
|
|
[multi_line_input \
|
|
{print g_s} \
|
|
{end}] \
|
|
"" \
|
|
$test
|
|
}
|
|
}
|
|
gdb_test "with language ada -- usercmd" \
|
|
" = \\(a => 1, b => 2, c => 3\\)"
|
|
}
|
|
|
|
# Check repeating.
|
|
with_test_prefix "repeat" {
|
|
clean_restart $binfile
|
|
|
|
# "with" with no command reinvokes the previous command.
|
|
gdb_test "with language ada" \
|
|
"No previous command to relaunch" \
|
|
"reinvoke with no previous command to relaunch"
|
|
|
|
gdb_test "print g_s" " = {a = 1, b = 2, c = 3}"
|
|
|
|
gdb_test "with language ada" \
|
|
" = \\(a => 1, b => 2, c => 3\\)" \
|
|
"reinvoke with language"
|
|
|
|
# Same, but with "--".
|
|
gdb_test "with language fortran --" \
|
|
" = \\( a = 1, b = 2, c = 3 \\)" \
|
|
"reinvoke with language and --"
|
|
|
|
# Repeating repeats the original "print g_s", not the last "with"
|
|
# command.
|
|
set test "repeat command line"
|
|
send_gdb "\n"
|
|
gdb_test_multiple "" $test {
|
|
-re " = {a = 1, b = 2, c = 3}\r\n$gdb_prompt $" {
|
|
pass $test
|
|
}
|
|
}
|
|
}
|
|
|
|
# Basic run control.
|
|
with_test_prefix "run control" {
|
|
clean_restart $binfile
|
|
|
|
if ![runto_main] {
|
|
return
|
|
}
|
|
|
|
# Check "with" with a synchronous execution command.
|
|
gdb_test "with disassemble-next-line on -- next" \
|
|
"return 0;.*=>.*"
|
|
}
|
|
|
|
# Check errors.
|
|
with_test_prefix "errors" {
|
|
gdb_test "with" "Missing arguments\\."
|
|
|
|
# Try both an unknown root setting and an unknown prefixed
|
|
# setting. The errors come from different locations in the
|
|
# sources.
|
|
gdb_test "with xxxx yyyy" \
|
|
"Undefined set command: \"xxxx\". Try \"help set\"\\."
|
|
gdb_test "with print xxxx yyyy" \
|
|
"Undefined set print command: \"xxxx yyyy\". Try \"help set print\"\\."
|
|
# Try one error case for "maint with", to make sure the right
|
|
# "maintenance with" prefix is shown.
|
|
gdb_test "maint with xxxx yyyy" \
|
|
"Undefined maintenance set command: \"xxxx\". Try \"help maintenance set\"\\."
|
|
|
|
# Try ambiguous settings.
|
|
gdb_test "with w" \
|
|
"Ambiguous set command \"w\": watchdog, width, write\\."
|
|
gdb_test "with print m" \
|
|
"Ambiguous set print command \"m\": max-depth, max-symbolic-offset, memory-tag-violations\\."
|
|
|
|
gdb_test "with variable xxx=1" \
|
|
"Cannot use this setting with the \"with\" command"
|
|
|
|
gdb_test "with print elements -- p 1" \
|
|
"Argument required \\(integer to set it to, or \"unlimited\"\\)\\."
|
|
|
|
gdb_test "with -- p 1" \
|
|
"Missing setting before '--' delimiter"
|
|
|
|
# Check that the setting is restored even if the command throws.
|
|
gdb_test "with print elements 1 -- unknowncommand" \
|
|
"Undefined command: \"unknowncommand\"\\. Try \"help\"\\."
|
|
gdb_test "show print elements" \
|
|
"Limit on string chars or array elements to print is 200\\."
|
|
}
|
|
|
|
# Check completion.
|
|
with_test_prefix "completion" {
|
|
test_gdb_complete_unique \
|
|
"with pri" \
|
|
"with print"
|
|
|
|
test_gdb_complete_unique \
|
|
"with print ele" \
|
|
"with print elements"
|
|
|
|
test_gdb_complete_unique \
|
|
"with print elements u" \
|
|
"with print elements unlimited"
|
|
|
|
test_gdb_complete_none \
|
|
"with print elements unlimited "
|
|
|
|
test_gdb_completion_offers_commands "with print elements unlimited -- "
|
|
|
|
# Check that the completer nests into the nested command line's
|
|
# completer.
|
|
test_gdb_complete_unique \
|
|
"with print elements unlimited -- with print ele" \
|
|
"with print elements unlimited -- with print elements"
|
|
|
|
# Check completion of "maint with". "maint with" and "with"'s
|
|
# completers share 99% of the code. All we need to care about
|
|
# here is that the completion word point is computed correctly, so
|
|
# any simple completion is sufficient.
|
|
test_gdb_complete_unique \
|
|
"maint with test-set" \
|
|
"maint with test-settings"
|
|
}
|