opensc-explorer: refactor ambiguous_match()
* most importantly: immediately return success on exact match - this allows one command to be a prefix of another one - it fixes the long-standing breakage between 'find' and 'find_tags' * fail on second prefix-only match instead of waiting until the end * check all parameters * add comments * inform caller on whether the match was ambiguous or there was no match * move printing error messages to processing loopt in main()
This commit is contained in:
parent
593a90f64e
commit
c817be8faa
|
@ -288,21 +288,33 @@ static void select_current_path_or_die(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct command *
|
static struct command *
|
||||||
ambiguous_match(struct command *table, const char *cmd)
|
ambiguous_match(struct command *table, const char *cmd, int *ambiguous)
|
||||||
{
|
{
|
||||||
struct command *last_match = NULL;
|
struct command *last_match = NULL;
|
||||||
int matches = 0;
|
|
||||||
|
|
||||||
|
if (table != NULL && cmd != NULL) {
|
||||||
for (; table->name; table++) {
|
for (; table->name; table++) {
|
||||||
if (strncasecmp(cmd, table->name, strlen(cmd)) == 0) {
|
size_t cmdlen = strlen(cmd);
|
||||||
last_match = table;
|
|
||||||
matches++;
|
/* compare cmd with prefix of known command */
|
||||||
}
|
if (strncasecmp(table->name, cmd, cmdlen) == 0) {
|
||||||
}
|
/* succeed immediately if lengths match too, i.e. exact match */
|
||||||
if (matches > 1) {
|
if (cmdlen == strlen(table->name))
|
||||||
fprintf(stderr, "Ambiguous command: %s\n", cmd);
|
return table;
|
||||||
|
/* fail on multiple prefix-only matches */
|
||||||
|
if (last_match != NULL) {
|
||||||
|
if (ambiguous != NULL)
|
||||||
|
*ambiguous = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/* remember latest prefix-only match */
|
||||||
|
last_match = table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* indicate as non-ambiguous if there was no match */
|
||||||
|
if (ambiguous != NULL && last_match == NULL)
|
||||||
|
*ambiguous = 0;
|
||||||
return last_match;
|
return last_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2178,6 +2190,10 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!feof(script)) {
|
while (!feof(script)) {
|
||||||
|
char *line;
|
||||||
|
int cargc;
|
||||||
|
char *cargv[260];
|
||||||
|
int multiple;
|
||||||
struct command *cmd;
|
struct command *cmd;
|
||||||
char prompt[3*SC_MAX_PATH_STRING_SIZE];
|
char prompt[3*SC_MAX_PATH_STRING_SIZE];
|
||||||
|
|
||||||
|
@ -2190,8 +2206,10 @@ int main(int argc, char *argv[])
|
||||||
continue;
|
continue;
|
||||||
for (r=cargc; r < (int)DIM(cargv); r++)
|
for (r=cargc; r < (int)DIM(cargv); r++)
|
||||||
cargv[r] = "";
|
cargv[r] = "";
|
||||||
cmd = ambiguous_match(cmds, cargv[0]);
|
cmd = ambiguous_match(cmds, cargv[0], &multiple);
|
||||||
if (cmd == NULL) {
|
if (cmd == NULL) {
|
||||||
|
fprintf(stderr, "%s command: %s\n",
|
||||||
|
(multiple) ? "Ambiguous" : "Unknown", cargv[0]);
|
||||||
do_help(0, NULL);
|
do_help(0, NULL);
|
||||||
} else {
|
} else {
|
||||||
cmd->func(cargc-1, cargv+1);
|
cmd->func(cargc-1, cargv+1);
|
||||||
|
|
Loading…
Reference in New Issue