mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 01:28:46 +00:00
gdb: Allow quoting around string options in the gdb::option framework
Currently string options must be a single string with no whitespace, this limitation prevents the gdb::option framework being used in some places. After this commit, string options can be quoted in single or double quotes, and quote characters can be escaped with a backslash if needed to either place them within quotes, or to avoid starting a quoted argument. This test adds a new function extract_string_maybe_quoted which is basically a copy of extract_arg_maybe_quoted from cli/cli-utils.c, however, the cli-utils.c function will be deleted in the next commit. There are tests to exercise the new quoting mechanism. gdb/ChangeLog: * cli/cli-option.c (parse_option): Use extract_string_maybe_quoted to extract string arguments. * common/common-utils.c (extract_string_maybe_quoted): New function. * common/common-utils.h (extract_string_maybe_quoted): Declare. gdb/testsuite/ChangeLog: * gdb.base/options.exp (expect_string): Dequote strings in results. (test-string): Test strings with different quoting and reindent.
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
2019-07-11 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* cli/cli-option.c (parse_option): Use extract_string_maybe_quoted
|
||||
to extract string arguments.
|
||||
* common/common-utils.c (extract_string_maybe_quoted): New function.
|
||||
* common/common-utils.h (extract_string_maybe_quoted): Declare.
|
||||
|
||||
2019-07-11 Tom Tromey <tromey@adacore.com>
|
||||
|
||||
* main.c (get_init_files): Use GDBINIT, not gdbinit.
|
||||
|
||||
@@ -434,13 +434,12 @@ parse_option (gdb::array_view<const option_def_group> options_group,
|
||||
}
|
||||
|
||||
const char *arg_start = *args;
|
||||
*args = skip_to_space (*args);
|
||||
|
||||
std::string str = extract_string_maybe_quoted (args);
|
||||
if (*args == arg_start)
|
||||
error (_("-%s requires an argument"), match->name);
|
||||
|
||||
option_value val;
|
||||
val.string = savestring (arg_start, *args - arg_start);
|
||||
val.string = xstrdup (str.c_str ());
|
||||
return option_def_and_value {*match, match_ctx, val};
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,65 @@ savestring (const char *ptr, size_t len)
|
||||
return p;
|
||||
}
|
||||
|
||||
/* See documentation in common-utils.h. */
|
||||
|
||||
std::string
|
||||
extract_string_maybe_quoted (const char **arg)
|
||||
{
|
||||
bool squote = false;
|
||||
bool dquote = false;
|
||||
bool bsquote = false;
|
||||
std::string result;
|
||||
const char *p = *arg;
|
||||
|
||||
/* Find the start of the argument. */
|
||||
p = skip_spaces (p);
|
||||
|
||||
/* Parse p similarly to gdb_argv buildargv function. */
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (isspace (*p) && !squote && !dquote && !bsquote)
|
||||
break;
|
||||
else
|
||||
{
|
||||
if (bsquote)
|
||||
{
|
||||
bsquote = false;
|
||||
result += *p;
|
||||
}
|
||||
else if (*p == '\\')
|
||||
bsquote = true;
|
||||
else if (squote)
|
||||
{
|
||||
if (*p == '\'')
|
||||
squote = false;
|
||||
else
|
||||
result += *p;
|
||||
}
|
||||
else if (dquote)
|
||||
{
|
||||
if (*p == '"')
|
||||
dquote = false;
|
||||
else
|
||||
result += *p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*p == '\'')
|
||||
squote = true;
|
||||
else if (*p == '"')
|
||||
dquote = true;
|
||||
else
|
||||
result += *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
*arg = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The bit offset of the highest byte in a ULONGEST, for overflow
|
||||
checking. */
|
||||
|
||||
|
||||
@@ -94,6 +94,16 @@ void string_vappendf (std::string &dest, const char* fmt, va_list args)
|
||||
|
||||
char *savestring (const char *ptr, size_t len);
|
||||
|
||||
/* Extract the next word from ARG. The next word is defined as either,
|
||||
everything up to the next space, or, if the next word starts with either
|
||||
a single or double quote, then everything up to the closing quote. The
|
||||
enclosing quotes are not returned in the result string. The pointer in
|
||||
ARG is updated to point to the first character after the end of the
|
||||
word, or, for quoted words, the first character after the closing
|
||||
quote. */
|
||||
|
||||
std::string extract_string_maybe_quoted (const char **arg);
|
||||
|
||||
/* The strerror() function can return NULL for errno values that are
|
||||
out of range. Provide a "safe" version that always returns a
|
||||
printable string. */
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
2019-07-11 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||
|
||||
* gdb.base/options.exp (expect_string): Dequote strings in
|
||||
results.
|
||||
(test-string): Test strings with different quoting and reindent.
|
||||
|
||||
2019-07-10 Tom Tromey <tromey@adacore.com>
|
||||
|
||||
* gdb.ada/mi_ex_cond.exp: Update expected results.
|
||||
|
||||
@@ -128,6 +128,13 @@ proc expect_integer {option val operand} {
|
||||
# test-options xxx", with -string set to $STR. OPERAND is the
|
||||
# expected operand.
|
||||
proc expect_string {str operand} {
|
||||
# Dequote the string in the expected output.
|
||||
if { ( [string range $str 0 0] == "\""
|
||||
&& [string range $str end end] == "\"")
|
||||
|| ([string range $str 0 0] == "'"
|
||||
&& [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"
|
||||
}
|
||||
|
||||
@@ -967,26 +974,41 @@ proc_with_prefix test-string {variant} {
|
||||
"-string requires an argument"
|
||||
}
|
||||
|
||||
res_test_gdb_complete_none \
|
||||
"1 [expect_none ""]" \
|
||||
"$cmd -string STR"
|
||||
gdb_test "$cmd -string STR --" [expect_string "STR" ""]
|
||||
|
||||
# Completing at "-" after parsing STR should list all options.
|
||||
res_test_gdb_complete_multiple \
|
||||
"1 [expect_string "STR" "-"]" \
|
||||
"$cmd -string STR " "-" "" $all_options
|
||||
|
||||
# Check that only FOO is considered part of the string's value.
|
||||
# I.e., that we stop parsing the string at the first whitespace.
|
||||
if {$variant == "require-delimiter"} {
|
||||
foreach_with_prefix str {
|
||||
"STR"
|
||||
"\"STR\""
|
||||
"\\\"STR"
|
||||
"'STR'"
|
||||
"\\'STR"
|
||||
"\"STR AAA\""
|
||||
"'STR BBB'"
|
||||
"\"STR 'CCC' DDD\""
|
||||
"'STR \"EEE\" FFF'"
|
||||
"\"STR \\\"GGG\\\" HHH\""
|
||||
"'STR \\\'III\\\' JJJ'"
|
||||
} {
|
||||
res_test_gdb_complete_none \
|
||||
"1 [expect_string "FOO" "BAR"]" \
|
||||
"$cmd -string FOO BAR"
|
||||
} else {
|
||||
res_test_gdb_complete_none "0 BAR" "$cmd -string FOO BAR"
|
||||
"1 [expect_none ""]" \
|
||||
"$cmd -string ${str}"
|
||||
gdb_test "$cmd -string ${str} --" [expect_string "${str}" ""]
|
||||
|
||||
# Completing at "-" after parsing STR should list all options.
|
||||
res_test_gdb_complete_multiple \
|
||||
"1 [expect_string "${str}" "-"]" \
|
||||
"$cmd -string ${str} " "-" "" $all_options
|
||||
|
||||
# Check that only $STR is considered part of the string's value.
|
||||
# I.e., that we stop parsing the string at the first
|
||||
# whitespace or after the closing quote of $STR.
|
||||
if {$variant == "require-delimiter"} {
|
||||
res_test_gdb_complete_none \
|
||||
"1 [expect_string "${str}" "BAR"]" \
|
||||
"$cmd -string ${str} BAR"
|
||||
} else {
|
||||
res_test_gdb_complete_none "0 BAR" "$cmd -string ${str} BAR"
|
||||
}
|
||||
gdb_test "$cmd -string ${str} BAR --" "Unrecognized option at: BAR --"
|
||||
}
|
||||
gdb_test "$cmd -string FOO BAR --" "Unrecognized option at: BAR --"
|
||||
}
|
||||
|
||||
# Run the options framework tests first.
|
||||
|
||||
Reference in New Issue
Block a user