lib: fix "reduce strcmp in CLI" fallout (10bac801)
In "lib/cli: reduce strcmp in CLI hot paths", I failed to notice that
CMD_VARIABLE as a boolean test covers a superset of the other types of
variables. Thus, the patch broke processing of IP/IPv6/Integer range
parameters in the CLI.
Fix by some reordering and introducing TERMINAL_RECORD macro (which
marks whether a given terminal type is a parameter) to be used in places
where the check is really for all kinds of variables.
Reported-by: Timo Teräs <timo.teras@iki.fi>
Tested-by: Martin Winter <mwinter@netdef.org>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/lib/command.c b/lib/command.c
index 922e7b5..c70391d 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -506,15 +506,7 @@
token = XCALLOC(MTYPE_CMD_TOKENS, sizeof(*token));
token->type = TOKEN_TERMINAL;
- if (cmd[0] == '[')
- token->terminal = TERMINAL_OPTION;
- else if ((cmd[0] >= 'A' && cmd[0] <= 'Z') || (cmd[0] == '<'))
- token->terminal = TERMINAL_VARIABLE;
- else if (cmd[0] == '.')
- token->terminal = TERMINAL_VARARG;
- else if (cmd[0] == '<')
- token->terminal = TERMINAL_RANGE;
- else if (strcmp (cmd, "A.B.C.D") == 0)
+ if (strcmp (cmd, "A.B.C.D") == 0)
token->terminal = TERMINAL_IPV4;
else if (strcmp (cmd, "A.B.C.D/M") == 0)
token->terminal = TERMINAL_IPV4_PREFIX;
@@ -522,6 +514,14 @@
token->terminal = TERMINAL_IPV6;
else if (strcmp (cmd, "X:X::X:X/M") == 0)
token->terminal = TERMINAL_IPV6_PREFIX;
+ else if (cmd[0] == '[')
+ token->terminal = TERMINAL_OPTION;
+ else if (cmd[0] == '.')
+ token->terminal = TERMINAL_VARARG;
+ else if (cmd[0] == '<')
+ token->terminal = TERMINAL_RANGE;
+ else if (cmd[0] >= 'A' && cmd[0] <= 'Z')
+ token->terminal = TERMINAL_VARIABLE;
else
token->terminal = TERMINAL_LITERAL;
@@ -1341,9 +1341,7 @@
/* We have to record the input word as argument if it matched
* against a variable. */
- if (token->terminal == TERMINAL_VARARG
- || token->terminal == TERMINAL_VARIABLE
- || token->terminal == TERMINAL_OPTION)
+ if (TERMINAL_RECORD (token->terminal))
{
if (push_argument(argc, argv, word))
return MATCHER_EXCEED_ARGC_MAX;
@@ -1585,9 +1583,7 @@
{
word_token = vector_slot(keyword_vector, j);
if ((word_token->type == TOKEN_TERMINAL
- && (word_token->terminal == TERMINAL_VARARG
- || word_token->terminal == TERMINAL_VARIABLE
- || word_token->terminal == TERMINAL_OPTION))
+ && TERMINAL_RECORD (word_token->terminal))
|| word_token->type == TOKEN_MULTIPLE)
{
if (push_argument(argc, argv, NULL))
@@ -1873,14 +1869,12 @@
switch (type)
{
case exact_match:
- if (!(cmd_token->terminal == TERMINAL_OPTION
- || cmd_token->terminal == TERMINAL_VARIABLE)
+ if (!TERMINAL_RECORD (cmd_token->terminal)
&& strcmp (command, str) == 0)
match++;
break;
case partly_match:
- if (!(cmd_token->terminal == TERMINAL_OPTION
- || cmd_token->terminal == TERMINAL_VARIABLE)
+ if (!TERMINAL_RECORD (cmd_token->terminal)
&& strncmp (command, str, strlen (command)) == 0)
{
if (matched && strcmp (matched, str) != 0)
@@ -1929,8 +1923,7 @@
}
break;
case extend_match:
- if (cmd_token->terminal == TERMINAL_OPTION
- || cmd_token->terminal == TERMINAL_VARIABLE)
+ if (TERMINAL_RECORD (cmd_token->terminal))
match++;
break;
case no_match:
@@ -1951,18 +1944,8 @@
const char *dst = token->cmd;
/* Skip variable arguments. */
- switch (token->terminal)
- {
- case TERMINAL_OPTION:
- case TERMINAL_VARIABLE:
- case TERMINAL_VARARG:
- case TERMINAL_IPV4:
- case TERMINAL_IPV4_PREFIX:
- case TERMINAL_RANGE:
- return NULL;
- default:
- break;
- }
+ if (TERMINAL_RECORD (token->terminal))
+ return NULL;
/* In case of 'command \t', given src is NULL string. */
if (src == NULL)