helper/command: simplify run_command()
[fw/openocd] / src / helper / command.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
6  *   oyvind.harboe@zylin.com                                               *
7  *                                                                         *
8  *   Copyright (C) 2008, Duane Ellis                                       *
9  *   openocd@duaneeellis.com                                               *
10  *                                                                         *
11  *   part of this file is taken from libcli (libcli.sourceforge.net)       *
12  *   Copyright (C) David Parrish (david@dparrish.com)                      *
13  *                                                                         *
14  *   This program is free software; you can redistribute it and/or modify  *
15  *   it under the terms of the GNU General Public License as published by  *
16  *   the Free Software Foundation; either version 2 of the License, or     *
17  *   (at your option) any later version.                                   *
18  *                                                                         *
19  *   This program is distributed in the hope that it will be useful,       *
20  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
21  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
22  *   GNU General Public License for more details.                          *
23  *                                                                         *
24  *   You should have received a copy of the GNU General Public License     *
25  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
26  ***************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 /* see Embedded-HOWTO.txt in Jim Tcl project hosted on BerliOS*/
33 #define JIM_EMBEDDED
34
35 /* @todo the inclusion of target.h here is a layering violation */
36 #include <jtag/jtag.h>
37 #include <target/target.h>
38 #include "command.h"
39 #include "configuration.h"
40 #include "log.h"
41 #include "time_support.h"
42 #include "jim-eventloop.h"
43
44 /* nice short description of source file */
45 #define __THIS__FILE__ "command.c"
46
47 struct log_capture_state {
48         Jim_Interp *interp;
49         Jim_Obj *output;
50 };
51
52 static int unregister_command(struct command_context *context,
53         struct command *parent, const char *name);
54 static char *command_name(struct command *c, char delim);
55 static int help_add_command(struct command_context *cmd_ctx,
56         const char *cmd_name, const char *help_text, const char *usage_text);
57 static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name);
58
59 /* wrap jimtcl internal data */
60 static inline bool jimcmd_is_proc(Jim_Cmd *cmd)
61 {
62         return cmd->isproc;
63 }
64
65 static void tcl_output(void *privData, const char *file, unsigned line,
66         const char *function, const char *string)
67 {
68         struct log_capture_state *state = privData;
69         Jim_AppendString(state->interp, state->output, string, strlen(string));
70 }
71
72 static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
73 {
74         /* capture log output and return it. A garbage collect can
75          * happen, so we need a reference count to this object */
76         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
77         if (NULL == tclOutput)
78                 return NULL;
79
80         struct log_capture_state *state = malloc(sizeof(*state));
81         if (NULL == state)
82                 return NULL;
83
84         state->interp = interp;
85         Jim_IncrRefCount(tclOutput);
86         state->output = tclOutput;
87
88         log_add_callback(tcl_output, state);
89
90         return state;
91 }
92
93 /* Classic openocd commands provide progress output which we
94  * will capture and return as a Tcl return value.
95  *
96  * However, if a non-openocd command has been invoked, then it
97  * makes sense to return the tcl return value from that command.
98  *
99  * The tcl return value is empty for openocd commands that provide
100  * progress output.
101  *
102  * Therefore we set the tcl return value only if we actually
103  * captured output.
104  */
105 static void command_log_capture_finish(struct log_capture_state *state)
106 {
107         if (NULL == state)
108                 return;
109
110         log_remove_callback(tcl_output, state);
111
112         int length;
113         Jim_GetString(state->output, &length);
114
115         if (length > 0)
116                 Jim_SetResult(state->interp, state->output);
117         else {
118                 /* No output captured, use tcl return value (which could
119                  * be empty too). */
120         }
121         Jim_DecrRefCount(state->interp, state->output);
122
123         free(state);
124 }
125
126 /*
127  * FIXME: workaround for memory leak in jimtcl 0.80
128  * Jim API Jim_CreateCommand() converts the command name in a Jim object and
129  * does not free the object. Fixed for jimtcl 0.81 by e4416cf86f0b
130  * Use the internal jimtcl API Jim_CreateCommandObj, not exported by jim.h,
131  * and override the bugged API through preprocessor's macro.
132  * This workaround works only when jimtcl is compiled as OpenOCD submodule.
133  * If jimtcl is linked-in from a precompiled library, either static or dynamic,
134  * the symbol Jim_CreateCommandObj is not exported and the build will use the
135  * bugged API.
136  * To be removed when OpenOCD will switch to jimtcl 0.81
137  */
138 #if JIM_VERSION == 80
139 static int workaround_createcommand(Jim_Interp *interp, const char *cmdName,
140         Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc);
141 int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj,
142         Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
143 __attribute__((weak, alias("workaround_createcommand")));
144 static int workaround_createcommand(Jim_Interp *interp, const char *cmdName,
145         Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
146 {
147         if ((void *)Jim_CreateCommandObj == (void *)workaround_createcommand)
148                 return Jim_CreateCommand(interp, cmdName, cmdProc, privData, delProc);
149
150         Jim_Obj *cmd_name = Jim_NewStringObj(interp, cmdName, -1);
151         Jim_IncrRefCount(cmd_name);
152         int retval = Jim_CreateCommandObj(interp, cmd_name, cmdProc, privData, delProc);
153         Jim_DecrRefCount(interp, cmd_name);
154         return retval;
155 }
156 #define Jim_CreateCommand workaround_createcommand
157 #endif /* JIM_VERSION == 80 */
158 /* FIXME: end of workaround for memory leak in jimtcl 0.80 */
159
160 static int command_retval_set(Jim_Interp *interp, int retval)
161 {
162         int *return_retval = Jim_GetAssocData(interp, "retval");
163         if (return_retval != NULL)
164                 *return_retval = retval;
165
166         return (retval == ERROR_OK) ? JIM_OK : retval;
167 }
168
169 extern struct command_context *global_cmd_ctx;
170
171 /* dump a single line to the log for the command.
172  * Do nothing in case we are not at debug level 3 */
173 void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv)
174 {
175         if (debug_level < LOG_LVL_DEBUG)
176                 return;
177
178         char *dbg = alloc_printf("command -");
179         for (unsigned i = 0; i < argc; i++) {
180                 int len;
181                 const char *w = Jim_GetString(argv[i], &len);
182                 char *t = alloc_printf("%s %s", dbg, w);
183                 free(dbg);
184                 dbg = t;
185         }
186         LOG_DEBUG("%s", dbg);
187         free(dbg);
188 }
189
190 static void script_command_args_free(char **words, unsigned nwords)
191 {
192         for (unsigned i = 0; i < nwords; i++)
193                 free(words[i]);
194         free(words);
195 }
196
197 static char **script_command_args_alloc(
198         unsigned argc, Jim_Obj * const *argv, unsigned *nwords)
199 {
200         char **words = malloc(argc * sizeof(char *));
201         if (NULL == words)
202                 return NULL;
203
204         unsigned i;
205         for (i = 0; i < argc; i++) {
206                 int len;
207                 const char *w = Jim_GetString(argv[i], &len);
208                 words[i] = strdup(w);
209                 if (words[i] == NULL) {
210                         script_command_args_free(words, i);
211                         return NULL;
212                 }
213         }
214         *nwords = i;
215         return words;
216 }
217
218 struct command_context *current_command_context(Jim_Interp *interp)
219 {
220         /* grab the command context from the associated data */
221         struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
222         if (NULL == cmd_ctx) {
223                 /* Tcl can invoke commands directly instead of via command_run_line(). This would
224                  * happen when the Jim Tcl interpreter is provided by eCos or if we are running
225                  * commands in a startup script.
226                  *
227                  * A telnet or gdb server would provide a non-default command context to
228                  * handle piping of error output, have a separate current target, etc.
229                  */
230                 cmd_ctx = global_cmd_ctx;
231         }
232         return cmd_ctx;
233 }
234
235 /**
236  * Find a command by name from a list of commands.
237  * @returns Returns the named command if it exists in the list.
238  * Returns NULL otherwise.
239  */
240 static struct command *command_find(struct command *head, const char *name)
241 {
242         for (struct command *cc = head; cc; cc = cc->next) {
243                 if (strcmp(cc->name, name) == 0)
244                         return cc;
245         }
246         return NULL;
247 }
248
249 /**
250  * Add the command into the linked list, sorted by name.
251  * @param head Address to head of command list pointer, which may be
252  * updated if @c c gets inserted at the beginning of the list.
253  * @param c The command to add to the list pointed to by @c head.
254  */
255 static void command_add_child(struct command **head, struct command *c)
256 {
257         assert(head);
258         if (NULL == *head) {
259                 *head = c;
260                 return;
261         }
262
263         while ((*head)->next && (strcmp(c->name, (*head)->name) > 0))
264                 head = &(*head)->next;
265
266         if (strcmp(c->name, (*head)->name) > 0) {
267                 c->next = (*head)->next;
268                 (*head)->next = c;
269         } else {
270                 c->next = *head;
271                 *head = c;
272         }
273 }
274
275 static struct command **command_list_for_parent(
276         struct command_context *cmd_ctx, struct command *parent)
277 {
278         return parent ? &parent->children : &cmd_ctx->commands;
279 }
280
281 static void command_free(struct command *c)
282 {
283         /** @todo if command has a handler, unregister its jim command! */
284
285         while (NULL != c->children) {
286                 struct command *tmp = c->children;
287                 c->children = tmp->next;
288                 command_free(tmp);
289         }
290
291         free(c->name);
292         free(c);
293 }
294
295 static struct command *command_new(struct command_context *cmd_ctx,
296         struct command *parent, const struct command_registration *cr)
297 {
298         assert(cr->name);
299
300         /*
301          * If it is a non-jim command with no .usage specified,
302          * log an error.
303          *
304          * strlen(.usage) == 0 means that the command takes no
305          * arguments.
306         */
307         if ((cr->jim_handler == NULL) && (cr->usage == NULL)) {
308                 LOG_ERROR("BUG: command '%s%s%s' does not have the "
309                         "'.usage' field filled out",
310                         parent && parent->name ? parent->name : "",
311                         parent && parent->name ? " " : "",
312                         cr->name);
313         }
314
315         struct command *c = calloc(1, sizeof(struct command));
316         if (NULL == c)
317                 return NULL;
318
319         c->name = strdup(cr->name);
320         if (!c->name)
321                 goto command_new_error;
322
323         c->parent = parent;
324         c->handler = cr->handler;
325         c->jim_handler = cr->jim_handler;
326         c->mode = cr->mode;
327
328         command_add_child(command_list_for_parent(cmd_ctx, parent), c);
329
330         if (cr->help || cr->usage) {
331                 char *full_name = command_name(c, ' ');
332                 help_add_command(cmd_ctx, full_name, cr->help, cr->usage);
333                 free(full_name);
334         }
335
336         return c;
337
338 command_new_error:
339         command_free(c);
340         return NULL;
341 }
342
343 static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
344
345 static struct command *register_command(struct command_context *context,
346         struct command *parent, const struct command_registration *cr)
347 {
348         if (!context || !cr->name)
349                 return NULL;
350
351         const char *name = cr->name;
352         struct command **head = command_list_for_parent(context, parent);
353         struct command *c = command_find(*head, name);
354         if (NULL != c) {
355                 /* TODO: originally we treated attempting to register a cmd twice as an error
356                  * Sometimes we need this behaviour, such as with flash banks.
357                  * http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */
358                 LOG_DEBUG("command '%s' is already registered in '%s' context",
359                         name, parent ? parent->name : "<global>");
360                 return c;
361         }
362
363         c = command_new(context, parent, cr);
364         if (NULL == c)
365                 return NULL;
366
367         char *full_name = command_name(c, ' ');
368         LOG_DEBUG("registering '%s'...", full_name);
369         int retval = Jim_CreateCommand(context->interp, full_name,
370                                 command_unknown, c, NULL);
371         if (retval != JIM_OK) {
372                 unregister_command(context, parent, name);
373                 return NULL;
374         }
375         return c;
376 }
377
378 static int ___register_commands(struct command_context *cmd_ctx, struct command *parent,
379         const struct command_registration *cmds, void *data,
380         struct target *override_target)
381 {
382         int retval = ERROR_OK;
383         unsigned i;
384         for (i = 0; cmds[i].name || cmds[i].chain; i++) {
385                 const struct command_registration *cr = cmds + i;
386
387                 struct command *c = NULL;
388                 if (NULL != cr->name) {
389                         c = register_command(cmd_ctx, parent, cr);
390                         if (NULL == c) {
391                                 retval = ERROR_FAIL;
392                                 break;
393                         }
394                         c->jim_handler_data = data;
395                         c->jim_override_target = override_target;
396                 }
397                 if (NULL != cr->chain) {
398                         struct command *p = c ? : parent;
399                         retval = ___register_commands(cmd_ctx, p, cr->chain, data, override_target);
400                         if (ERROR_OK != retval)
401                                 break;
402                 }
403         }
404         if (ERROR_OK != retval) {
405                 for (unsigned j = 0; j < i; j++)
406                         unregister_command(cmd_ctx, parent, cmds[j].name);
407         }
408         return retval;
409 }
410
411 int __register_commands(struct command_context *cmd_ctx, const char *cmd_prefix,
412         const struct command_registration *cmds, void *data,
413         struct target *override_target)
414 {
415         struct command *parent = NULL;
416
417         if (cmd_prefix)
418                 parent = command_find(cmd_ctx->commands, cmd_prefix);
419
420         return ___register_commands(cmd_ctx, parent, cmds, data, override_target);
421 }
422
423 int unregister_all_commands(struct command_context *context,
424         struct command *parent)
425 {
426         if (context == NULL)
427                 return ERROR_OK;
428
429         struct command **head = command_list_for_parent(context, parent);
430         while (NULL != *head) {
431                 struct command *tmp = *head;
432                 *head = tmp->next;
433                 command_free(tmp);
434         }
435
436         return ERROR_OK;
437 }
438
439 static int unregister_command(struct command_context *context,
440         struct command *parent, const char *name)
441 {
442         if ((!context) || (!name))
443                 return ERROR_COMMAND_SYNTAX_ERROR;
444
445         struct command *p = NULL;
446         struct command **head = command_list_for_parent(context, parent);
447         for (struct command *c = *head; NULL != c; p = c, c = c->next) {
448                 if (strcmp(name, c->name) != 0)
449                         continue;
450
451                 char *full_name = command_name(c, ' ');
452                 help_del_command(context, full_name);
453                 free(full_name);
454
455                 if (p)
456                         p->next = c->next;
457                 else
458                         *head = c->next;
459
460                 command_free(c);
461                 return ERROR_OK;
462         }
463
464         return ERROR_OK;
465 }
466
467 void command_output_text(struct command_context *context, const char *data)
468 {
469         if (context && context->output_handler && data)
470                 context->output_handler(context, data);
471 }
472
473 void command_print_sameline(struct command_invocation *cmd, const char *format, ...)
474 {
475         char *string;
476
477         va_list ap;
478         va_start(ap, format);
479
480         string = alloc_vprintf(format, ap);
481         if (string != NULL && cmd) {
482                 /* we want this collected in the log + we also want to pick it up as a tcl return
483                  * value.
484                  *
485                  * The latter bit isn't precisely neat, but will do for now.
486                  */
487                 Jim_AppendString(cmd->ctx->interp, cmd->output, string, -1);
488                 /* We already printed it above
489                  * command_output_text(context, string); */
490                 free(string);
491         }
492
493         va_end(ap);
494 }
495
496 void command_print(struct command_invocation *cmd, const char *format, ...)
497 {
498         char *string;
499
500         va_list ap;
501         va_start(ap, format);
502
503         string = alloc_vprintf(format, ap);
504         if (string != NULL && cmd) {
505                 strcat(string, "\n");   /* alloc_vprintf guaranteed the buffer to be at least one
506                                          *char longer */
507                 /* we want this collected in the log + we also want to pick it up as a tcl return
508                  * value.
509                  *
510                  * The latter bit isn't precisely neat, but will do for now.
511                  */
512                 Jim_AppendString(cmd->ctx->interp, cmd->output, string, -1);
513                 /* We already printed it above
514                  * command_output_text(context, string); */
515                 free(string);
516         }
517
518         va_end(ap);
519 }
520
521 static char *__command_name(struct command *c, char delim, unsigned extra)
522 {
523         char *name;
524         unsigned len = strlen(c->name);
525         if (NULL == c->parent) {
526                 /* allocate enough for the name, child names, and '\0' */
527                 name = malloc(len + extra + 1);
528                 if (!name) {
529                         LOG_ERROR("Out of memory");
530                         return NULL;
531                 }
532                 strcpy(name, c->name);
533         } else {
534                 /* parent's extra must include both the space and name */
535                 name = __command_name(c->parent, delim, 1 + len + extra);
536                 char dstr[2] = { delim, 0 };
537                 strcat(name, dstr);
538                 strcat(name, c->name);
539         }
540         return name;
541 }
542
543 static char *command_name(struct command *c, char delim)
544 {
545         return __command_name(c, delim, 0);
546 }
547
548 static bool command_can_run(struct command_context *cmd_ctx, struct command *c, const char *full_name)
549 {
550         if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode)
551                 return true;
552
553         /* Many commands may be run only before/after 'init' */
554         const char *when;
555         switch (c->mode) {
556                 case COMMAND_CONFIG:
557                         when = "before";
558                         break;
559                 case COMMAND_EXEC:
560                         when = "after";
561                         break;
562                 /* handle the impossible with humor; it guarantees a bug report! */
563                 default:
564                         when = "if Cthulhu is summoned by";
565                         break;
566         }
567         LOG_ERROR("The '%s' command must be used %s 'init'.",
568                         full_name ? full_name : c->name, when);
569         return false;
570 }
571
572 static int run_command(struct command_context *context,
573         struct command *c, const char **words, unsigned num_words)
574 {
575         struct command_invocation cmd = {
576                 .ctx = context,
577                 .current = c,
578                 .name = c->name,
579                 .argc = num_words - 1,
580                 .argv = words + 1,
581         };
582
583         cmd.output = Jim_NewEmptyStringObj(context->interp);
584         Jim_IncrRefCount(cmd.output);
585
586         int retval = c->handler(&cmd);
587         if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
588                 /* Print help for command */
589                 command_run_linef(context, "usage %s", words[0]);
590         } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
591                 /* just fall through for a shutdown request */
592         } else {
593                 if (retval != ERROR_OK)
594                         LOG_DEBUG("Command '%s' failed with error code %d",
595                                                 words[0], retval);
596                 /* Use the command output as the Tcl result */
597                 Jim_SetResult(context->interp, cmd.output);
598         }
599         Jim_DecrRefCount(context->interp, cmd.output);
600
601         return retval;
602 }
603
604 int command_run_line(struct command_context *context, char *line)
605 {
606         /* all the parent commands have been registered with the interpreter
607          * so, can just evaluate the line as a script and check for
608          * results
609          */
610         /* run the line thru a script engine */
611         int retval = ERROR_FAIL;
612         int retcode;
613         /* Beware! This code needs to be reentrant. It is also possible
614          * for OpenOCD commands to be invoked directly from Tcl. This would
615          * happen when the Jim Tcl interpreter is provided by eCos for
616          * instance.
617          */
618         struct target *saved_target_override = context->current_target_override;
619         context->current_target_override = NULL;
620
621         Jim_Interp *interp = context->interp;
622         struct command_context *old_context = Jim_GetAssocData(interp, "context");
623         Jim_DeleteAssocData(interp, "context");
624         retcode = Jim_SetAssocData(interp, "context", NULL, context);
625         if (retcode == JIM_OK) {
626                 /* associated the return value */
627                 Jim_DeleteAssocData(interp, "retval");
628                 retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
629                 if (retcode == JIM_OK) {
630                         retcode = Jim_Eval_Named(interp, line, 0, 0);
631
632                         Jim_DeleteAssocData(interp, "retval");
633                 }
634                 Jim_DeleteAssocData(interp, "context");
635                 int inner_retcode = Jim_SetAssocData(interp, "context", NULL, old_context);
636                 if (retcode == JIM_OK)
637                         retcode = inner_retcode;
638         }
639         context->current_target_override = saved_target_override;
640         if (retcode == JIM_OK) {
641                 const char *result;
642                 int reslen;
643
644                 result = Jim_GetString(Jim_GetResult(interp), &reslen);
645                 if (reslen > 0) {
646                         command_output_text(context, result);
647                         command_output_text(context, "\n");
648                 }
649                 retval = ERROR_OK;
650         } else if (retcode == JIM_EXIT) {
651                 /* ignore.
652                  * exit(Jim_GetExitCode(interp)); */
653         } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) {
654                 return retcode;
655         } else {
656                 Jim_MakeErrorMessage(interp);
657                 /* error is broadcast */
658                 LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
659
660                 if (retval == ERROR_OK) {
661                         /* It wasn't a low level OpenOCD command that failed */
662                         return ERROR_FAIL;
663                 }
664                 return retval;
665         }
666
667         return retval;
668 }
669
670 int command_run_linef(struct command_context *context, const char *format, ...)
671 {
672         int retval = ERROR_FAIL;
673         char *string;
674         va_list ap;
675         va_start(ap, format);
676         string = alloc_vprintf(format, ap);
677         if (string != NULL) {
678                 retval = command_run_line(context, string);
679                 free(string);
680         }
681         va_end(ap);
682         return retval;
683 }
684
685 void command_set_output_handler(struct command_context *context,
686         command_output_handler_t output_handler, void *priv)
687 {
688         context->output_handler = output_handler;
689         context->output_handler_priv = priv;
690 }
691
692 struct command_context *copy_command_context(struct command_context *context)
693 {
694         struct command_context *copy_context = malloc(sizeof(struct command_context));
695
696         *copy_context = *context;
697
698         return copy_context;
699 }
700
701 void command_done(struct command_context *cmd_ctx)
702 {
703         if (NULL == cmd_ctx)
704                 return;
705
706         free(cmd_ctx);
707 }
708
709 /* find full path to file */
710 static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
711 {
712         if (argc != 2)
713                 return JIM_ERR;
714         const char *file = Jim_GetString(argv[1], NULL);
715         char *full_path = find_file(file);
716         if (full_path == NULL)
717                 return JIM_ERR;
718         Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
719         free(full_path);
720
721         Jim_SetResult(interp, result);
722         return JIM_OK;
723 }
724
725 COMMAND_HANDLER(jim_echo)
726 {
727         if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) {
728                 LOG_USER_N("%s", CMD_ARGV[1]);
729                 return JIM_OK;
730         }
731         if (CMD_ARGC != 1)
732                 return JIM_ERR;
733         LOG_USER("%s", CMD_ARGV[0]);
734         return JIM_OK;
735 }
736
737 /* Capture progress output and return as tcl return value. If the
738  * progress output was empty, return tcl return value.
739  */
740 static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
741 {
742         if (argc != 2)
743                 return JIM_ERR;
744
745         struct log_capture_state *state = command_log_capture_start(interp);
746
747         /* disable polling during capture. This avoids capturing output
748          * from polling.
749          *
750          * This is necessary in order to avoid accidentally getting a non-empty
751          * string for tcl fn's.
752          */
753         bool save_poll = jtag_poll_get_enabled();
754
755         jtag_poll_set_enabled(false);
756
757         const char *str = Jim_GetString(argv[1], NULL);
758         int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
759
760         jtag_poll_set_enabled(save_poll);
761
762         command_log_capture_finish(state);
763
764         return retcode;
765 }
766
767 struct help_entry {
768         struct list_head lh;
769         char *cmd_name;
770         char *help;
771         char *usage;
772 };
773
774 static COMMAND_HELPER(command_help_show, struct help_entry *c,
775         bool show_help, const char *cmd_match);
776
777 static COMMAND_HELPER(command_help_show_list, bool show_help, const char *cmd_match)
778 {
779         struct help_entry *entry;
780
781         list_for_each_entry(entry, CMD_CTX->help_list, lh)
782                 CALL_COMMAND_HANDLER(command_help_show, entry, show_help, cmd_match);
783         return ERROR_OK;
784 }
785
786 #define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n))
787
788 static void command_help_show_indent(unsigned n)
789 {
790         for (unsigned i = 0; i < n; i++)
791                 LOG_USER_N("  ");
792 }
793 static void command_help_show_wrap(const char *str, unsigned n, unsigned n2)
794 {
795         const char *cp = str, *last = str;
796         while (*cp) {
797                 const char *next = last;
798                 do {
799                         cp = next;
800                         do {
801                                 next++;
802                         } while (*next != ' ' && *next != '\t' && *next != '\0');
803                 } while ((next - last < HELP_LINE_WIDTH(n)) && *next != '\0');
804                 if (next - last < HELP_LINE_WIDTH(n))
805                         cp = next;
806                 command_help_show_indent(n);
807                 LOG_USER("%.*s", (int)(cp - last), last);
808                 last = cp + 1;
809                 n = n2;
810         }
811 }
812
813 static COMMAND_HELPER(command_help_show, struct help_entry *c,
814         bool show_help, const char *cmd_match)
815 {
816         unsigned int n = 0;
817         for (const char *s = strchr(c->cmd_name, ' '); s; s = strchr(s + 1, ' '))
818                 n++;
819
820         /* If the match string occurs anywhere, we print out
821          * stuff for this command. */
822         bool is_match = (strstr(c->cmd_name, cmd_match) != NULL) ||
823                 ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) ||
824                 ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL));
825
826         if (is_match) {
827                 command_help_show_indent(n);
828                 LOG_USER_N("%s", c->cmd_name);
829
830                 if (c->usage && strlen(c->usage) > 0) {
831                         LOG_USER_N(" ");
832                         command_help_show_wrap(c->usage, 0, n + 5);
833                 } else
834                         LOG_USER_N("\n");
835         }
836
837         if (is_match && show_help) {
838                 char *msg;
839
840                 /* TODO: factorize jim_command_mode() to avoid running jim command here */
841                 char *request = alloc_printf("command mode %s", c->cmd_name);
842                 if (!request) {
843                         LOG_ERROR("Out of memory");
844                         return ERROR_FAIL;
845                 }
846                 int retval = Jim_Eval(CMD_CTX->interp, request);
847                 free(request);
848                 enum command_mode mode = COMMAND_UNKNOWN;
849                 if (retval != JIM_ERR) {
850                         const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL);
851                         if (!strcmp(result, "any"))
852                                 mode = COMMAND_ANY;
853                         else if (!strcmp(result, "config"))
854                                 mode = COMMAND_CONFIG;
855                         else if (!strcmp(result, "exec"))
856                                 mode = COMMAND_EXEC;
857                 }
858
859                 /* Normal commands are runtime-only; highlight exceptions */
860                 if (mode != COMMAND_EXEC) {
861                         const char *stage_msg = "";
862
863                         switch (mode) {
864                                 case COMMAND_CONFIG:
865                                         stage_msg = " (configuration command)";
866                                         break;
867                                 case COMMAND_ANY:
868                                         stage_msg = " (command valid any time)";
869                                         break;
870                                 default:
871                                         stage_msg = " (?mode error?)";
872                                         break;
873                         }
874                         msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
875                 } else
876                         msg = alloc_printf("%s", c->help ? : "");
877
878                 if (NULL != msg) {
879                         command_help_show_wrap(msg, n + 3, n + 3);
880                         free(msg);
881                 } else
882                         return -ENOMEM;
883         }
884
885         return ERROR_OK;
886 }
887
888 COMMAND_HANDLER(handle_help_command)
889 {
890         bool full = strcmp(CMD_NAME, "help") == 0;
891         int retval;
892         char *cmd_match;
893
894         if (CMD_ARGC <= 0)
895                 cmd_match = strdup("");
896
897         else {
898                 cmd_match = strdup(CMD_ARGV[0]);
899
900                 for (unsigned int i = 1; i < CMD_ARGC && cmd_match; ++i) {
901                         char *prev = cmd_match;
902                         cmd_match = alloc_printf("%s %s", prev, CMD_ARGV[i]);
903                         free(prev);
904                 }
905         }
906
907         if (cmd_match == NULL) {
908                 LOG_ERROR("unable to build search string");
909                 return -ENOMEM;
910         }
911         retval = CALL_COMMAND_HANDLER(command_help_show_list, full, cmd_match);
912
913         free(cmd_match);
914         return retval;
915 }
916
917 static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
918         struct command *head, struct command **out)
919 {
920         if (0 == argc)
921                 return argc;
922         const char *cmd_name = Jim_GetString(argv[0], NULL);
923         struct command *c = command_find(head, cmd_name);
924         if (NULL == c)
925                 return argc;
926         *out = c;
927         return command_unknown_find(--argc, ++argv, (*out)->children, out);
928 }
929
930 static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv)
931 {
932         char *prev, *all;
933         int i;
934
935         assert(argc >= 1);
936
937         all = strdup(Jim_GetString(argv[0], NULL));
938         if (!all) {
939                 LOG_ERROR("Out of memory");
940                 return NULL;
941         }
942
943         for (i = 1; i < argc; ++i) {
944                 prev = all;
945                 all = alloc_printf("%s %s", all, Jim_GetString(argv[i], NULL));
946                 free(prev);
947                 if (!all) {
948                         LOG_ERROR("Out of memory");
949                         return NULL;
950                 }
951         }
952
953         return all;
954 }
955
956 static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx,
957                 struct command *c, int argc, Jim_Obj * const *argv)
958 {
959         if (c->jim_handler)
960                 return c->jim_handler(interp, argc, argv);
961
962         /* use c->handler */
963         unsigned int nwords;
964         char **words = script_command_args_alloc(argc, argv, &nwords);
965         if (!words)
966                 return JIM_ERR;
967
968         int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
969         script_command_args_free(words, nwords);
970         return command_retval_set(interp, retval);
971 }
972
973 static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
974 {
975         script_debug(interp, argc, argv);
976
977         /* check subcommands */
978         if (argc > 1) {
979                 char *s = alloc_printf("%s %s", Jim_GetString(argv[0], NULL), Jim_GetString(argv[1], NULL));
980                 Jim_Obj *js = Jim_NewStringObj(interp, s, -1);
981                 Jim_IncrRefCount(js);
982                 free(s);
983                 Jim_Cmd *cmd = Jim_GetCommand(interp, js, JIM_NONE);
984                 if (cmd) {
985                         int retval = Jim_EvalObjPrefix(interp, js, argc - 2, argv + 2);
986                         Jim_DecrRefCount(interp, js);
987                         return retval;
988                 }
989                 Jim_DecrRefCount(interp, js);
990         }
991
992         struct command *c = jim_to_command(interp);
993         if (!c->jim_handler && !c->handler) {
994                 Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv);
995                 return JIM_ERR;
996         }
997
998         struct command_context *cmd_ctx = current_command_context(interp);
999
1000         if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL)))
1001                 return JIM_ERR;
1002
1003         target_call_timer_callbacks_now();
1004
1005         /*
1006          * Black magic of overridden current target:
1007          * If the command we are going to handle has a target prefix,
1008          * override the current target temporarily for the time
1009          * of processing the command.
1010          * current_target_override is used also for event handlers
1011          * therefore we prevent touching it if command has no prefix.
1012          * Previous override is saved and restored back to ensure
1013          * correct work when command_unknown() is re-entered.
1014          */
1015         struct target *saved_target_override = cmd_ctx->current_target_override;
1016         if (c->jim_override_target)
1017                 cmd_ctx->current_target_override = c->jim_override_target;
1018
1019         int retval = exec_command(interp, cmd_ctx, c, argc, argv);
1020
1021         if (c->jim_override_target)
1022                 cmd_ctx->current_target_override = saved_target_override;
1023
1024         return retval;
1025 }
1026
1027 static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1028 {
1029         struct command_context *cmd_ctx = current_command_context(interp);
1030         enum command_mode mode;
1031
1032         if (argc > 1) {
1033                 char *full_name = alloc_concatenate_strings(argc - 1, argv + 1);
1034                 if (!full_name)
1035                         return JIM_ERR;
1036                 Jim_Obj *s = Jim_NewStringObj(interp, full_name, -1);
1037                 Jim_IncrRefCount(s);
1038                 Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE);
1039                 Jim_DecrRefCount(interp, s);
1040                 free(full_name);
1041                 if (cmd && jimcmd_is_proc(cmd)) {
1042                         Jim_SetResultString(interp, "any", -1);
1043                         return JIM_OK;
1044                 }
1045                 struct command *c = cmd_ctx->commands;
1046                 int remaining = command_unknown_find(argc - 1, argv + 1, c, &c);
1047                 /* if nothing could be consumed, then it's an unknown command */
1048                 if (remaining == argc - 1) {
1049                         Jim_SetResultString(interp, "unknown", -1);
1050                         return JIM_OK;
1051                 }
1052                 mode = c->mode;
1053         } else
1054                 mode = cmd_ctx->mode;
1055
1056         const char *mode_str;
1057         switch (mode) {
1058                 case COMMAND_ANY:
1059                         mode_str = "any";
1060                         break;
1061                 case COMMAND_CONFIG:
1062                         mode_str = "config";
1063                         break;
1064                 case COMMAND_EXEC:
1065                         mode_str = "exec";
1066                         break;
1067                 default:
1068                         mode_str = "unknown";
1069                         break;
1070         }
1071         Jim_SetResultString(interp, mode_str, -1);
1072         return JIM_OK;
1073 }
1074
1075 int help_del_all_commands(struct command_context *cmd_ctx)
1076 {
1077         struct help_entry *curr, *n;
1078
1079         list_for_each_entry_safe(curr, n, cmd_ctx->help_list, lh) {
1080                 list_del(&curr->lh);
1081                 free(curr->cmd_name);
1082                 free(curr->help);
1083                 free(curr->usage);
1084                 free(curr);
1085         }
1086         return ERROR_OK;
1087 }
1088
1089 static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name)
1090 {
1091         struct help_entry *curr;
1092
1093         list_for_each_entry(curr, cmd_ctx->help_list, lh) {
1094                 if (!strcmp(cmd_name, curr->cmd_name)) {
1095                         list_del(&curr->lh);
1096                         free(curr->cmd_name);
1097                         free(curr->help);
1098                         free(curr->usage);
1099                         free(curr);
1100                         break;
1101                 }
1102         }
1103
1104         return ERROR_OK;
1105 }
1106
1107 static int help_add_command(struct command_context *cmd_ctx,
1108         const char *cmd_name, const char *help_text, const char *usage_text)
1109 {
1110         int cmp = -1; /* add after curr */
1111         struct help_entry *curr;
1112
1113         list_for_each_entry_reverse(curr, cmd_ctx->help_list, lh) {
1114                 cmp = strcmp(cmd_name, curr->cmd_name);
1115                 if (cmp >= 0)
1116                         break;
1117         }
1118
1119         struct help_entry *entry;
1120         if (cmp) {
1121                 entry = calloc(1, sizeof(*entry));
1122                 if (!entry) {
1123                         LOG_ERROR("Out of memory");
1124                         return ERROR_FAIL;
1125                 }
1126                 entry->cmd_name = strdup(cmd_name);
1127                 if (!entry->cmd_name) {
1128                         LOG_ERROR("Out of memory");
1129                         free(entry);
1130                         return ERROR_FAIL;
1131                 }
1132                 list_add(&entry->lh, &curr->lh);
1133         } else {
1134                 entry = curr;
1135         }
1136
1137         if (help_text) {
1138                 char *text = strdup(help_text);
1139                 if (!text) {
1140                         LOG_ERROR("Out of memory");
1141                         return ERROR_FAIL;
1142                 }
1143                 free(entry->help);
1144                 entry->help = text;
1145         }
1146
1147         if (usage_text) {
1148                 char *text = strdup(usage_text);
1149                 if (!text) {
1150                         LOG_ERROR("Out of memory");
1151                         return ERROR_FAIL;
1152                 }
1153                 free(entry->usage);
1154                 entry->usage = text;
1155         }
1156
1157         return ERROR_OK;
1158 }
1159
1160 COMMAND_HANDLER(handle_help_add_command)
1161 {
1162         if (CMD_ARGC != 2)
1163                 return ERROR_COMMAND_SYNTAX_ERROR;
1164
1165         const char *help = !strcmp(CMD_NAME, "add_help_text") ? CMD_ARGV[1] : NULL;
1166         const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? CMD_ARGV[1] : NULL;
1167         if (!help && !usage) {
1168                 LOG_ERROR("command name '%s' is unknown", CMD_NAME);
1169                 return ERROR_COMMAND_SYNTAX_ERROR;
1170         }
1171         const char *cmd_name = CMD_ARGV[0];
1172         return help_add_command(CMD_CTX, cmd_name, help, usage);
1173 }
1174
1175 /* sleep command sleeps for <n> milliseconds
1176  * this is useful in target startup scripts
1177  */
1178 COMMAND_HANDLER(handle_sleep_command)
1179 {
1180         bool busy = false;
1181         if (CMD_ARGC == 2) {
1182                 if (strcmp(CMD_ARGV[1], "busy") == 0)
1183                         busy = true;
1184                 else
1185                         return ERROR_COMMAND_SYNTAX_ERROR;
1186         } else if (CMD_ARGC < 1 || CMD_ARGC > 2)
1187                 return ERROR_COMMAND_SYNTAX_ERROR;
1188
1189         unsigned long duration = 0;
1190         int retval = parse_ulong(CMD_ARGV[0], &duration);
1191         if (ERROR_OK != retval)
1192                 return retval;
1193
1194         if (!busy) {
1195                 int64_t then = timeval_ms();
1196                 while (timeval_ms() - then < (int64_t)duration) {
1197                         target_call_timer_callbacks_now();
1198                         usleep(1000);
1199                 }
1200         } else
1201                 busy_sleep(duration);
1202
1203         return ERROR_OK;
1204 }
1205
1206 static const struct command_registration command_subcommand_handlers[] = {
1207         {
1208                 .name = "mode",
1209                 .mode = COMMAND_ANY,
1210                 .jim_handler = jim_command_mode,
1211                 .usage = "[command_name ...]",
1212                 .help = "Returns the command modes allowed by a command: "
1213                         "'any', 'config', or 'exec'. If no command is "
1214                         "specified, returns the current command mode. "
1215                         "Returns 'unknown' if an unknown command is given. "
1216                         "Command can be multiple tokens.",
1217         },
1218         COMMAND_REGISTRATION_DONE
1219 };
1220
1221 static const struct command_registration command_builtin_handlers[] = {
1222         {
1223                 .name = "ocd_find",
1224                 .mode = COMMAND_ANY,
1225                 .jim_handler = jim_find,
1226                 .help = "find full path to file",
1227                 .usage = "file",
1228         },
1229         {
1230                 .name = "capture",
1231                 .mode = COMMAND_ANY,
1232                 .jim_handler = jim_capture,
1233                 .help = "Capture progress output and return as tcl return value. If the "
1234                                 "progress output was empty, return tcl return value.",
1235                 .usage = "command",
1236         },
1237         {
1238                 .name = "echo",
1239                 .handler = jim_echo,
1240                 .mode = COMMAND_ANY,
1241                 .help = "Logs a message at \"user\" priority. "
1242                         "Output message to stdout. "
1243                         "Option \"-n\" suppresses trailing newline",
1244                 .usage = "[-n] string",
1245         },
1246         {
1247                 .name = "add_help_text",
1248                 .handler = handle_help_add_command,
1249                 .mode = COMMAND_ANY,
1250                 .help = "Add new command help text; "
1251                         "Command can be multiple tokens.",
1252                 .usage = "command_name helptext_string",
1253         },
1254         {
1255                 .name = "add_usage_text",
1256                 .handler = handle_help_add_command,
1257                 .mode = COMMAND_ANY,
1258                 .help = "Add new command usage text; "
1259                         "command can be multiple tokens.",
1260                 .usage = "command_name usage_string",
1261         },
1262         {
1263                 .name = "sleep",
1264                 .handler = handle_sleep_command,
1265                 .mode = COMMAND_ANY,
1266                 .help = "Sleep for specified number of milliseconds.  "
1267                         "\"busy\" will busy wait instead (avoid this).",
1268                 .usage = "milliseconds ['busy']",
1269         },
1270         {
1271                 .name = "help",
1272                 .handler = handle_help_command,
1273                 .mode = COMMAND_ANY,
1274                 .help = "Show full command help; "
1275                         "command can be multiple tokens.",
1276                 .usage = "[command_name]",
1277         },
1278         {
1279                 .name = "usage",
1280                 .handler = handle_help_command,
1281                 .mode = COMMAND_ANY,
1282                 .help = "Show basic command usage; "
1283                         "command can be multiple tokens.",
1284                 .usage = "[command_name]",
1285         },
1286         {
1287                 .name = "command",
1288                 .mode = COMMAND_ANY,
1289                 .help = "core command group (introspection)",
1290                 .chain = command_subcommand_handlers,
1291                 .usage = "",
1292         },
1293         COMMAND_REGISTRATION_DONE
1294 };
1295
1296 struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp)
1297 {
1298         struct command_context *context = calloc(1, sizeof(struct command_context));
1299         const char *HostOs;
1300
1301         context->mode = COMMAND_EXEC;
1302
1303         /* context can be duplicated. Put list head on separate mem-chunk to keep list consistent */
1304         context->help_list = malloc(sizeof(*context->help_list));
1305         INIT_LIST_HEAD(context->help_list);
1306
1307         /* Create a jim interpreter if we were not handed one */
1308         if (interp == NULL) {
1309                 /* Create an interpreter */
1310                 interp = Jim_CreateInterp();
1311                 /* Add all the Jim core commands */
1312                 Jim_RegisterCoreCommands(interp);
1313                 Jim_InitStaticExtensions(interp);
1314         }
1315
1316         context->interp = interp;
1317
1318         /* Stick to lowercase for HostOS strings. */
1319 #if defined(_MSC_VER)
1320         /* WinXX - is generic, the forward
1321          * looking problem is this:
1322          *
1323          *   "win32" or "win64"
1324          *
1325          * "winxx" is generic.
1326          */
1327         HostOs = "winxx";
1328 #elif defined(__linux__)
1329         HostOs = "linux";
1330 #elif defined(__APPLE__) || defined(__DARWIN__)
1331         HostOs = "darwin";
1332 #elif defined(__CYGWIN__)
1333         HostOs = "cygwin";
1334 #elif defined(__MINGW32__)
1335         HostOs = "mingw32";
1336 #elif defined(__ECOS)
1337         HostOs = "ecos";
1338 #elif defined(__FreeBSD__)
1339         HostOs = "freebsd";
1340 #elif defined(__NetBSD__)
1341         HostOs = "netbsd";
1342 #elif defined(__OpenBSD__)
1343         HostOs = "openbsd";
1344 #else
1345 #warning "Unrecognized host OS..."
1346         HostOs = "other";
1347 #endif
1348         Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
1349                 Jim_NewStringObj(interp, HostOs, strlen(HostOs)));
1350
1351         register_commands(context, NULL, command_builtin_handlers);
1352
1353         Jim_SetAssocData(interp, "context", NULL, context);
1354         if (Jim_Eval_Named(interp, startup_tcl, "embedded:startup.tcl", 1) == JIM_ERR) {
1355                 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD)");
1356                 Jim_MakeErrorMessage(interp);
1357                 LOG_USER_N("%s", Jim_GetString(Jim_GetResult(interp), NULL));
1358                 exit(-1);
1359         }
1360         Jim_DeleteAssocData(interp, "context");
1361
1362         return context;
1363 }
1364
1365 void command_exit(struct command_context *context)
1366 {
1367         if (!context)
1368                 return;
1369
1370         Jim_FreeInterp(context->interp);
1371         free(context->help_list);
1372         command_done(context);
1373 }
1374
1375 int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode)
1376 {
1377         if (!cmd_ctx)
1378                 return ERROR_COMMAND_SYNTAX_ERROR;
1379
1380         cmd_ctx->mode = mode;
1381         return ERROR_OK;
1382 }
1383
1384 void process_jim_events(struct command_context *cmd_ctx)
1385 {
1386         static int recursion;
1387         if (recursion)
1388                 return;
1389
1390         recursion++;
1391         Jim_ProcessEvents(cmd_ctx->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
1392         recursion--;
1393 }
1394
1395 #define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \
1396         int parse ## name(const char *str, type * ul) \
1397         { \
1398                 if (!*str) { \
1399                         LOG_ERROR("Invalid command argument"); \
1400                         return ERROR_COMMAND_ARGUMENT_INVALID; \
1401                 } \
1402                 char *end; \
1403                 errno = 0; \
1404                 *ul = func(str, &end, 0); \
1405                 if (*end) { \
1406                         LOG_ERROR("Invalid command argument"); \
1407                         return ERROR_COMMAND_ARGUMENT_INVALID; \
1408                 } \
1409                 if ((max == *ul) && (ERANGE == errno)) { \
1410                         LOG_ERROR("Argument overflow"); \
1411                         return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
1412                 } \
1413                 if (min && (min == *ul) && (ERANGE == errno)) { \
1414                         LOG_ERROR("Argument underflow"); \
1415                         return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
1416                 } \
1417                 return ERROR_OK; \
1418         }
1419 DEFINE_PARSE_NUM_TYPE(_ulong, unsigned long, strtoul, 0, ULONG_MAX)
1420 DEFINE_PARSE_NUM_TYPE(_ullong, unsigned long long, strtoull, 0, ULLONG_MAX)
1421 DEFINE_PARSE_NUM_TYPE(_long, long, strtol, LONG_MIN, LONG_MAX)
1422 DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX)
1423
1424 #define DEFINE_PARSE_WRAPPER(name, type, min, max, functype, funcname) \
1425         int parse ## name(const char *str, type * ul) \
1426         { \
1427                 functype n; \
1428                 int retval = parse ## funcname(str, &n); \
1429                 if (ERROR_OK != retval) \
1430                         return retval; \
1431                 if (n > max) \
1432                         return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
1433                 if (min) \
1434                         return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
1435                 *ul = n; \
1436                 return ERROR_OK; \
1437         }
1438
1439 #define DEFINE_PARSE_ULONGLONG(name, type, min, max) \
1440         DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long long, _ullong)
1441 DEFINE_PARSE_ULONGLONG(_uint, unsigned, 0, UINT_MAX)
1442 DEFINE_PARSE_ULONGLONG(_u64,  uint64_t, 0, UINT64_MAX)
1443 DEFINE_PARSE_ULONGLONG(_u32,  uint32_t, 0, UINT32_MAX)
1444 DEFINE_PARSE_ULONGLONG(_u16,  uint16_t, 0, UINT16_MAX)
1445 DEFINE_PARSE_ULONGLONG(_u8,   uint8_t,  0, UINT8_MAX)
1446
1447 DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX)
1448
1449 #define DEFINE_PARSE_LONGLONG(name, type, min, max) \
1450         DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong)
1451 DEFINE_PARSE_LONGLONG(_int, int,     n < INT_MIN,   INT_MAX)
1452 DEFINE_PARSE_LONGLONG(_s64, int64_t, n < INT64_MIN, INT64_MAX)
1453 DEFINE_PARSE_LONGLONG(_s32, int32_t, n < INT32_MIN, INT32_MAX)
1454 DEFINE_PARSE_LONGLONG(_s16, int16_t, n < INT16_MIN, INT16_MAX)
1455 DEFINE_PARSE_LONGLONG(_s8,  int8_t,  n < INT8_MIN,  INT8_MAX)
1456
1457 static int command_parse_bool(const char *in, bool *out,
1458         const char *on, const char *off)
1459 {
1460         if (strcasecmp(in, on) == 0)
1461                 *out = true;
1462         else if (strcasecmp(in, off) == 0)
1463                 *out = false;
1464         else
1465                 return ERROR_COMMAND_SYNTAX_ERROR;
1466         return ERROR_OK;
1467 }
1468
1469 int command_parse_bool_arg(const char *in, bool *out)
1470 {
1471         if (command_parse_bool(in, out, "on", "off") == ERROR_OK)
1472                 return ERROR_OK;
1473         if (command_parse_bool(in, out, "enable", "disable") == ERROR_OK)
1474                 return ERROR_OK;
1475         if (command_parse_bool(in, out, "true", "false") == ERROR_OK)
1476                 return ERROR_OK;
1477         if (command_parse_bool(in, out, "yes", "no") == ERROR_OK)
1478                 return ERROR_OK;
1479         if (command_parse_bool(in, out, "1", "0") == ERROR_OK)
1480                 return ERROR_OK;
1481         return ERROR_COMMAND_SYNTAX_ERROR;
1482 }
1483
1484 COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
1485 {
1486         switch (CMD_ARGC) {
1487                 case 1: {
1488                         const char *in = CMD_ARGV[0];
1489                         if (command_parse_bool_arg(in, out) != ERROR_OK) {
1490                                 LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
1491                                 return ERROR_COMMAND_SYNTAX_ERROR;
1492                         }
1493                 }
1494                         /* fallthrough */
1495                 case 0:
1496                         LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
1497                         break;
1498                 default:
1499                         return ERROR_COMMAND_SYNTAX_ERROR;
1500         }
1501         return ERROR_OK;
1502 }