Allow . character as part of command names.

This patch adds . as an allowed character for user defined commands.
Combined with 'define-prefix', this allows to e.g. define a set of Valgrind
specific user command corresponding to the Valgrind monitor commands
(such as check_memory, v.info, v.set, ...).

gdb/ChangeLog
2019-11-30  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* command.h (valid_cmd_char_p): Declare.
	* cli/cli-decode.c (valid_cmd_char_p): New function factorizing
	the check of valid command char.
	(find_command_name_length, valid_user_defined_cmd_name_p): Use
	valid_cmd_char_p.
	* cli/cli-script.c (validate_comname): Likewise.
	* completer.c (gdb_completer_command_word_break_characters):
	Do not remove . from the word break char, update comments.
	(complete_line_internal_1): Use valid_cmd_char_p.
	* guile/scm-cmd.c (gdbscm_parse_command_name): Likewise.
	* python/py-cmd.c (gdbpy_parse_command_name): Likewise.

gdb/testsuite/ChangeLog
2019-11-30  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/define.exp: Test . in command names.
	* gdb.base/setshow.exp: Update test, as . is now part of
	command name.
This commit is contained in:
Philippe Waroquiers 2019-09-08 21:54:18 +02:00
parent 643c0cbedb
commit be09caf15d
10 changed files with 76 additions and 25 deletions

View File

@ -1,3 +1,17 @@
2019-11-30 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* command.h (valid_cmd_char_p): Declare.
* cli/cli-decode.c (valid_cmd_char_p): New function factorizing
the check of valid command char.
(find_command_name_length, valid_user_defined_cmd_name_p): Use
valid_cmd_char_p.
* cli/cli-script.c (validate_comname): Likewise.
* completer.c (gdb_completer_command_word_break_characters):
Do not remove . from the word break char, update comments.
(complete_line_internal_1): Use valid_cmd_char_p.
* guile/scm-cmd.c (gdbscm_parse_command_name): Likewise.
* python/py-cmd.c (gdbpy_parse_command_name): Likewise.
2019-11-30 Philippe Waroquiers <philippe.waroquiers@skynet.be> 2019-11-30 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* cli/cli-script.c (do_define_command): Ensure a redefined * cli/cli-script.c (do_define_command): Ensure a redefined

View File

@ -1372,7 +1372,7 @@ find_command_name_length (const char *text)
if (*p == '!' || *p == '|') if (*p == '!' || *p == '|')
return 1; return 1;
while (isalnum (*p) || *p == '-' || *p == '_' while (valid_cmd_char_p (*p)
/* Characters used by TUI specific commands. */ /* Characters used by TUI specific commands. */
|| *p == '+' || *p == '<' || *p == '>' || *p == '$') || *p == '+' || *p == '<' || *p == '>' || *p == '$')
p++; p++;
@ -1380,9 +1380,18 @@ find_command_name_length (const char *text)
return p - text; return p - text;
} }
/* Return TRUE if NAME is a valid user-defined command name. /* See command.h. */
This is a stricter subset of all gdb commands,
see find_command_name_length. */ bool
valid_cmd_char_p (int c)
{
/* Alas "42" is a legitimate user-defined command.
In the interests of not breaking anything we preserve that. */
return isalnum (c) || c == '-' || c == '_' || c == '.';
}
/* See command.h. */
bool bool
valid_user_defined_cmd_name_p (const char *name) valid_user_defined_cmd_name_p (const char *name)
@ -1392,14 +1401,9 @@ valid_user_defined_cmd_name_p (const char *name)
if (*name == '\0') if (*name == '\0')
return false; return false;
/* Alas "42" is a legitimate user-defined command.
In the interests of not breaking anything we preserve that. */
for (p = name; *p != '\0'; ++p) for (p = name; *p != '\0'; ++p)
{ {
if (isalnum (*p) if (valid_cmd_char_p (*p))
|| *p == '-'
|| *p == '_')
; /* Ok. */ ; /* Ok. */
else else
return false; return false;

View File

@ -1342,7 +1342,7 @@ validate_comname (const char **comname)
p = *comname; p = *comname;
while (*p) while (*p)
{ {
if (!isalnum (*p) && *p != '-' && *p != '_') if (!valid_cmd_char_p (*p))
error (_("Junk in argument list: \"%s\""), p); error (_("Junk in argument list: \"%s\""), p);
p++; p++;
} }

View File

@ -133,8 +133,16 @@ extern struct cli_suppress_notification cli_suppress_notification;
/* API to the manipulation of command lists. */ /* API to the manipulation of command lists. */
/* Return TRUE if NAME is a valid user-defined command name.
This is a stricter subset of all gdb commands,
see find_command_name_length. */
extern bool valid_user_defined_cmd_name_p (const char *name); extern bool valid_user_defined_cmd_name_p (const char *name);
/* Return TRUE if C is a valid command character. */
extern bool valid_cmd_char_p (int c);
/* Const-correct variant of the above. */ /* Const-correct variant of the above. */
extern struct cmd_list_element *add_cmd (const char *, enum command_class, extern struct cmd_list_element *add_cmd (const char *, enum command_class,

View File

@ -102,13 +102,13 @@ enum explicit_location_match_type
/* Variables which are necessary for fancy command line editing. */ /* Variables which are necessary for fancy command line editing. */
/* When completing on command names, we remove '-' from the list of /* When completing on command names, we remove '-' and '.' from the list of
word break characters, since we use it in command names. If the word break characters, since we use it in command names. If the
readline library sees one in any of the current completion strings, readline library sees one in any of the current completion strings,
it thinks that the string needs to be quoted and automatically it thinks that the string needs to be quoted and automatically
supplies a leading quote. */ supplies a leading quote. */
static const char gdb_completer_command_word_break_characters[] = static const char gdb_completer_command_word_break_characters[] =
" \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,"; " \t\n!@#$%^&*()+=|~`}{[]\"';:?/><,";
/* When completing on file names, we remove from the list of word /* When completing on file names, we remove from the list of word
break characters any characters that are commonly used in file break characters any characters that are commonly used in file
@ -1284,7 +1284,7 @@ complete_line_internal_1 (completion_tracker &tracker,
on command strings (as opposed to strings supplied by the on command strings (as opposed to strings supplied by the
individual command completer functions, which can be any string) individual command completer functions, which can be any string)
then we will switch to the special word break set for command then we will switch to the special word break set for command
strings, which leaves out the '-' character used in some strings, which leaves out the '-' and '.' character used in some
commands. */ commands. */
set_rl_completer_word_break_characters set_rl_completer_word_break_characters
(current_language->la_word_break_characters()); (current_language->la_word_break_characters());
@ -1347,7 +1347,7 @@ complete_line_internal_1 (completion_tracker &tracker,
/* lookup_cmd_1 advances p up to the first ambiguous thing, but /* lookup_cmd_1 advances p up to the first ambiguous thing, but
doesn't advance over that thing itself. Do so now. */ doesn't advance over that thing itself. Do so now. */
q = p; q = p;
while (*q && (isalnum (*q) || *q == '-' || *q == '_')) while (valid_cmd_char_p (*q))
++q; ++q;
if (q != tmp_command + point) if (q != tmp_command + point)
{ {
@ -1435,7 +1435,7 @@ complete_line_internal_1 (completion_tracker &tracker,
q = p; q = p;
while (q > tmp_command) while (q > tmp_command)
{ {
if (isalnum (q[-1]) || q[-1] == '-' || q[-1] == '_') if (valid_cmd_char_p (q[-1]))
--q; --q;
else else
break; break;

View File

@ -492,10 +492,7 @@ gdbscm_parse_command_name (const char *name,
lastchar = i; lastchar = i;
/* Find first character of the final word. */ /* Find first character of the final word. */
for (; i > 0 && (isalnum (name[i - 1]) for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
|| name[i - 1] == '-'
|| name[i - 1] == '_');
--i)
; ;
result = (char *) xmalloc (lastchar - i + 2); result = (char *) xmalloc (lastchar - i + 2);
memcpy (result, &name[i], lastchar - i + 1); memcpy (result, &name[i], lastchar - i + 1);

View File

@ -372,10 +372,7 @@ gdbpy_parse_command_name (const char *name,
lastchar = i; lastchar = i;
/* Find first character of the final word. */ /* Find first character of the final word. */
for (; i > 0 && (isalnum (name[i - 1]) for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
|| name[i - 1] == '-'
|| name[i - 1] == '_');
--i)
; ;
result = (char *) xmalloc (lastchar - i + 2); result = (char *) xmalloc (lastchar - i + 2);
memcpy (result, &name[i], lastchar - i + 1); memcpy (result, &name[i], lastchar - i + 1);

View File

@ -1,3 +1,9 @@
2019-11-30 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.base/define.exp: Test . in command names.
* gdb.base/setshow.exp: Update test, as . is now part of
command name.
2019-11-30 Philippe Waroquiers <philippe.waroquiers@skynet.be> 2019-11-30 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.base/define-prefix.exp: New file. * gdb.base/define-prefix.exp: New file.

View File

@ -130,6 +130,31 @@ gdb_test "help nextwhere" \
" A next command that first shows you where you're stepping from.*" \ " A next command that first shows you where you're stepping from.*" \
"preserve whitespace in help string" "preserve whitespace in help string"
# Verify that GDB allows a user to use . in a command name.
#
gdb_test_multiple "define dot.command" "define user command: dot.command" {
-re "Type commands for definition of \"dot.command\".\r\nEnd with a line saying just \"end\".\r\n>$" {
gdb_test "echo dot command\\n\nend" "" \
"define user command: dot.command"
}
}
# Verify that dot.command works.
#
gdb_test "dot.command" \
"dot command" \
"full name dot.command"
gdb_test "dot" \
"dot command" \
"partial name dot"
gdb_test "dot." \
"dot command" \
"partial name dot."
gdb_test "dot.c" \
"dot command" \
"partial name dot.c"
# Verify that the command parser doesn't require a space after an 'if' # Verify that the command parser doesn't require a space after an 'if'
# command in a user defined function. # command in a user defined function.
# #

View File

@ -355,7 +355,7 @@ gdb_test_no_output "set verbose off" "set verbose off"
gdb_test "show verbose" "Verbosity is off..*" "show verbose (off)" gdb_test "show verbose" "Verbosity is off..*" "show verbose (off)"
#test argument must be preceded by space #test argument must be preceded by space
foreach x {"history file" "solib-search-path" "data-directory"} { foreach x {"history file" "solib-search-path" "data-directory"} {
foreach y {"/home/" "." "~/home" "=home"} { foreach y {"/home/" "~/home" "=home"} {
gdb_test "set $x$y" "Argument must be preceded by space." \ gdb_test "set $x$y" "Argument must be preceded by space." \
"$x is not set to $y" "$x is not set to $y"
} }