rewrite 'unknown' command dispatching in C
Rewrite the magical 'unknown' command in C as a Jim handler, allowing it to dispatch commands to any level in the tree.
This commit is contained in:
parent
769fbfa058
commit
62e5649600
|
@ -853,6 +853,70 @@ COMMAND_HANDLER(handle_usage_command)
|
||||||
return CALL_COMMAND_HANDLER(command_help_show, c, 0, false);
|
return CALL_COMMAND_HANDLER(command_help_show, c, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
|
||||||
|
struct command *head, struct command **out)
|
||||||
|
{
|
||||||
|
if (0 == argc)
|
||||||
|
return argc;
|
||||||
|
struct command *c = command_find(head, Jim_GetString(argv[0], NULL));
|
||||||
|
if (NULL == c)
|
||||||
|
return argc;
|
||||||
|
*out = c;
|
||||||
|
return command_unknown_find(--argc, ++argv, (*out)->children, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||||
|
{
|
||||||
|
const char *cmd_name = Jim_GetString(argv[0], NULL);
|
||||||
|
script_debug(interp, cmd_name, argc - 1, argv + 1);
|
||||||
|
|
||||||
|
struct command_context *cmd_ctx = current_command_context();
|
||||||
|
struct command *c = cmd_ctx->commands;
|
||||||
|
int remaining = command_unknown_find(argc - 1, argv + 1, c, &c);
|
||||||
|
// if nothing could be consumed, then it's really an unknown command
|
||||||
|
if (remaining == argc - 1)
|
||||||
|
{
|
||||||
|
const char *cmd = Jim_GetString(argv[1], NULL);
|
||||||
|
LOG_ERROR("Unknown command:\n %s", cmd);
|
||||||
|
return JIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = true;
|
||||||
|
Jim_Obj *const *start;
|
||||||
|
unsigned count;
|
||||||
|
if (c->handler)
|
||||||
|
{
|
||||||
|
// include the command name in the list
|
||||||
|
count = remaining + 1;
|
||||||
|
start = argv + (argc - remaining - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = command_find(cmd_ctx->commands, "help");
|
||||||
|
if (NULL == c)
|
||||||
|
{
|
||||||
|
LOG_ERROR("unknown command, but help is missing too");
|
||||||
|
return JIM_ERR;
|
||||||
|
}
|
||||||
|
count = argc - remaining;
|
||||||
|
start = argv;
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned nwords;
|
||||||
|
const char **words = script_command_args_alloc(count, start, &nwords);
|
||||||
|
if (NULL == words)
|
||||||
|
return JIM_ERR;
|
||||||
|
|
||||||
|
int retval = run_command(cmd_ctx, c, words, nwords);
|
||||||
|
|
||||||
|
script_command_args_free(words, nwords);
|
||||||
|
|
||||||
|
if (!found && ERROR_OK == retval)
|
||||||
|
retval = ERROR_FAIL;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
int help_add_command(struct command_context *cmd_ctx, struct command *parent,
|
int help_add_command(struct command_context *cmd_ctx, struct command *parent,
|
||||||
const char *cmd_name, const char *help_text, const char *usage)
|
const char *cmd_name, const char *help_text, const char *usage)
|
||||||
|
@ -1032,6 +1096,7 @@ struct command_context* command_init(const char *startup_tcl)
|
||||||
Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
|
Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
|
||||||
Jim_NewStringObj(interp, HostOs , strlen(HostOs)));
|
Jim_NewStringObj(interp, HostOs , strlen(HostOs)));
|
||||||
|
|
||||||
|
Jim_CreateCommand(interp, "unknown", &command_unknown, NULL, NULL);
|
||||||
Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL);
|
Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL);
|
||||||
Jim_CreateCommand(interp, "echo", jim_echo, NULL, NULL);
|
Jim_CreateCommand(interp, "echo", jim_echo, NULL, NULL);
|
||||||
Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL);
|
Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL);
|
||||||
|
|
|
@ -44,23 +44,6 @@ proc cmd_help {cmdname h indent} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# If a fn is unknown to Tcl, we try to execute it as an OpenOCD command
|
|
||||||
#
|
|
||||||
# We also support two level commands. "flash banks" is translated to
|
|
||||||
# flash_banks
|
|
||||||
proc unknown {args} {
|
|
||||||
# do the name mangling from "flash banks" to "flash_banks"
|
|
||||||
if {[llength $args]>=2} {
|
|
||||||
set cmd_name "[lindex $args 0]_[lindex $args 1]"
|
|
||||||
if {[catch {info body $cmd_name}]==0} {
|
|
||||||
# the command exists, try it...
|
|
||||||
return [eval "$cmd_name [lrange $args 2 end]"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# This really is an unknown command.
|
|
||||||
return -code error "Unknown command: $args"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Try flipping / and \ to find file if the filename does not
|
# Try flipping / and \ to find file if the filename does not
|
||||||
# match the precise spelling
|
# match the precise spelling
|
||||||
proc find {filename} {
|
proc find {filename} {
|
||||||
|
|
Loading…
Reference in New Issue