I just pushed a slightly improved version of the patch, which improves
the fallback logic.  It also uses the same trick for the help fallback,
which was broken in the original version below.

--Z

On Fri, 2009-11-27 at 14:08 -0800, Zachary T Welch wrote:
> The command refactoring caused subcommand handlers to produce duplicate
> output when run.  The problem was introduced by failing to ensure all
> such invocations went through a top-level "catcher" script, prefixing
> the command name with the 'ocd_' prefix and consuming its results.
> 
> The fix is to ensure such a top-level "catcher" script gets created
> for each top-level command, regardless of whether it has a handler.
> Indeed, this patch removes all command registrations for sub-commands,
> which would not have worked in the new registration scheme anyway.
> 
> For now, dispatch of subcommands continues to be handled by the new
> 'unknown' command handler, which gets fixed here to strip the 'ocd_'
> prefix if searching for the top-level command name fails initially.
> Some Jim commands may be registered with this prefix, and that situation
> seems to require the current fallback approach.  Otherwise, that prefix
> could be stripped unconditionally and the logic made a little simpler.
> 
> Overall, the command dispatching remains more complicated than desired,
> but this patch fixes the immediate regressions.
> 
> Signed-off-by: Zachary T Welch <z...@superlucidity.net>
> ---
>  src/helper/command.c |   45 +++++++++++++++++++++++++++++++--------------
>  1 files changed, 31 insertions(+), 14 deletions(-)
> 
> diff --git a/src/helper/command.c b/src/helper/command.c
> index 62fb487..135cd3f 100644
> --- a/src/helper/command.c
> +++ b/src/helper/command.c
> @@ -44,6 +44,9 @@
>  #include "jim-eventloop.h"
>  
> 
> +/* nice short description of source file */
> +#define __THIS__FILE__ "command.c"
> +
>  Jim_Interp *interp = NULL;
>  
>  static int run_command(struct command_context *context,
> @@ -185,8 +188,12 @@ static int script_command(Jim_Interp *interp, int argc, 
> Jim_Obj *const *argv)
>       return script_command_run(interp, argc, argv, c, true);
>  }
>  
> -/* nice short description of source file */
> -#define __THIS__FILE__ "command.c"
> +static struct command *command_root(struct command *c)
> +{
> +     while (NULL != c->parent)
> +             c = c->parent;
> +     return c;
> +}
>  
>  /**
>   * Find a command by name from a list of commands.
> @@ -296,19 +303,22 @@ static int register_command_handler(struct command *c)
>       if (NULL == full_name)
>               return retval;
>  
> -     const char *ocd_name = alloc_printf("ocd_%s", full_name);
> -     if (NULL == full_name)
> -             goto free_full_name;
> +     if (NULL != c->handler)
> +     {
> +             const char *ocd_name = alloc_printf("ocd_%s", full_name);
> +             if (NULL == full_name)
> +                     goto free_full_name;
>  
> -     Jim_CreateCommand(interp, ocd_name, script_command, c, NULL);
> -     free((void *)ocd_name);
> +             Jim_CreateCommand(interp, ocd_name, script_command, c, NULL);
> +             free((void *)ocd_name);
> +     }
>  
>       /* we now need to add an overrideable proc */
>       const char *override_name = alloc_printf("proc %s {args} {"
>                       "if {[catch {eval ocd_%s $args}] == 0} "
>                       "{return \"\"} else {return -code error}}",
>                       full_name, full_name);
> -     if (NULL == full_name)
> +     if (NULL == override_name)
>               goto free_full_name;
>  
>       Jim_Eval_Named(interp, override_name, __THIS__FILE__, __LINE__);
> @@ -343,7 +353,7 @@ struct command* register_command(struct command_context 
> *context,
>  
>       if (NULL != c->handler)
>       {
> -             int retval = register_command_handler(c);
> +             int retval = register_command_handler(command_root(c));
>               if (ERROR_OK != retval)
>               {
>                       unregister_command(context, parent, name);
> @@ -875,15 +885,22 @@ COMMAND_HANDLER(handle_help_command)
>  }
>  
>  static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
> -             struct command *head, struct command **out)
> +             struct command *head, struct command **out, bool top_level)
>  {
>       if (0 == argc)
>               return argc;
> -     struct command *c = command_find(head, Jim_GetString(argv[0], NULL));
> +     const char *cmd_name = Jim_GetString(argv[0], NULL);
> +     struct command *c = command_find(head, cmd_name);
>       if (NULL == c)
> -             return argc;
> +     {
> +             if (top_level && strncmp(cmd_name, "ocd_", 4) == 0)
> +                     c = command_find(head, cmd_name + 4);
> +
> +             if (NULL == c)
> +                     return argc;
> +     }
>       *out = c;
> -     return command_unknown_find(--argc, ++argv, (*out)->children, out);
> +     return command_unknown_find(--argc, ++argv, (*out)->children, out, 
> false);
>  }
>  
>  static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const 
> *argv)
> @@ -893,7 +910,7 @@ static int command_unknown(Jim_Interp *interp, int argc, 
> Jim_Obj *const *argv)
>  
>       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);
> +     int remaining = command_unknown_find(argc - 1, argv + 1, c, &c, true);
>       // if nothing could be consumed, then it's really an unknown command
>       if (remaining == argc - 1)
>       {


_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to