helper/command: register full-name commands in jim
[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                 char *full_name = command_name(c, ' ');
590                 if (NULL != full_name) {
591                         command_run_linef(context, "usage %s", full_name);
592                         free(full_name);
593                 }
594         } else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
595                 /* just fall through for a shutdown request */
596         } else {
597                 if (retval != ERROR_OK) {
598                         char *full_name = command_name(c, ' ');
599                         LOG_DEBUG("Command '%s' failed with error code %d",
600                                                 full_name ? full_name : c->name, retval);
601                         free(full_name);
602                 }
603                 /* Use the command output as the Tcl result */
604                 Jim_SetResult(context->interp, cmd.output);
605         }
606         Jim_DecrRefCount(context->interp, cmd.output);
607
608         return retval;
609 }
610
611 int command_run_line(struct command_context *context, char *line)
612 {
613         /* all the parent commands have been registered with the interpreter
614          * so, can just evaluate the line as a script and check for
615          * results
616          */
617         /* run the line thru a script engine */
618         int retval = ERROR_FAIL;
619         int retcode;
620         /* Beware! This code needs to be reentrant. It is also possible
621          * for OpenOCD commands to be invoked directly from Tcl. This would
622          * happen when the Jim Tcl interpreter is provided by eCos for
623          * instance.
624          */
625         struct target *saved_target_override = context->current_target_override;
626         context->current_target_override = NULL;
627
628         Jim_Interp *interp = context->interp;
629         struct command_context *old_context = Jim_GetAssocData(interp, "context");
630         Jim_DeleteAssocData(interp, "context");
631         retcode = Jim_SetAssocData(interp, "context", NULL, context);
632         if (retcode == JIM_OK) {
633                 /* associated the return value */
634                 Jim_DeleteAssocData(interp, "retval");
635                 retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
636                 if (retcode == JIM_OK) {
637                         retcode = Jim_Eval_Named(interp, line, 0, 0);
638
639                         Jim_DeleteAssocData(interp, "retval");
640                 }
641                 Jim_DeleteAssocData(interp, "context");
642                 int inner_retcode = Jim_SetAssocData(interp, "context", NULL, old_context);
643                 if (retcode == JIM_OK)
644                         retcode = inner_retcode;
645         }
646         context->current_target_override = saved_target_override;
647         if (retcode == JIM_OK) {
648                 const char *result;
649                 int reslen;
650
651                 result = Jim_GetString(Jim_GetResult(interp), &reslen);
652                 if (reslen > 0) {
653                         command_output_text(context, result);
654                         command_output_text(context, "\n");
655                 }
656                 retval = ERROR_OK;
657         } else if (retcode == JIM_EXIT) {
658                 /* ignore.
659                  * exit(Jim_GetExitCode(interp)); */
660         } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) {
661                 return retcode;
662         } else {
663                 Jim_MakeErrorMessage(interp);
664                 /* error is broadcast */
665                 LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
666
667                 if (retval == ERROR_OK) {
668                         /* It wasn't a low level OpenOCD command that failed */
669                         return ERROR_FAIL;
670                 }
671                 return retval;
672         }
673
674         return retval;
675 }
676
677 int command_run_linef(struct command_context *context, const char *format, ...)
678 {
679         int retval = ERROR_FAIL;
680         char *string;
681         va_list ap;
682         va_start(ap, format);
683         string = alloc_vprintf(format, ap);
684         if (string != NULL) {
685                 retval = command_run_line(context, string);
686                 free(string);
687         }
688         va_end(ap);
689         return retval;
690 }
691
692 void command_set_output_handler(struct command_context *context,
693         command_output_handler_t output_handler, void *priv)
694 {
695         context->output_handler = output_handler;
696         context->output_handler_priv = priv;
697 }
698
699 struct command_context *copy_command_context(struct command_context *context)
700 {
701         struct command_context *copy_context = malloc(sizeof(struct command_context));
702
703         *copy_context = *context;
704
705         return copy_context;
706 }
707
708 void command_done(struct command_context *cmd_ctx)
709 {
710         if (NULL == cmd_ctx)
711                 return;
712
713         free(cmd_ctx);
714 }
715
716 /* find full path to file */
717 static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
718 {
719         if (argc != 2)
720                 return JIM_ERR;
721         const char *file = Jim_GetString(argv[1], NULL);
722         char *full_path = find_file(file);
723         if (full_path == NULL)
724                 return JIM_ERR;
725         Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
726         free(full_path);
727
728         Jim_SetResult(interp, result);
729         return JIM_OK;
730 }
731
732 COMMAND_HANDLER(jim_echo)
733 {
734         if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) {
735                 LOG_USER_N("%s", CMD_ARGV[1]);
736                 return JIM_OK;
737         }
738         if (CMD_ARGC != 1)
739                 return JIM_ERR;
740         LOG_USER("%s", CMD_ARGV[0]);
741         return JIM_OK;
742 }
743
744 /* Capture progress output and return as tcl return value. If the
745  * progress output was empty, return tcl return value.
746  */
747 static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
748 {
749         if (argc != 2)
750                 return JIM_ERR;
751
752         struct log_capture_state *state = command_log_capture_start(interp);
753
754         /* disable polling during capture. This avoids capturing output
755          * from polling.
756          *
757          * This is necessary in order to avoid accidentally getting a non-empty
758          * string for tcl fn's.
759          */
760         bool save_poll = jtag_poll_get_enabled();
761
762         jtag_poll_set_enabled(false);
763
764         const char *str = Jim_GetString(argv[1], NULL);
765         int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
766
767         jtag_poll_set_enabled(save_poll);
768
769         command_log_capture_finish(state);
770
771         return retcode;
772 }
773
774 struct help_entry {
775         struct list_head lh;
776         char *cmd_name;
777         char *help;
778         char *usage;
779 };
780
781 static COMMAND_HELPER(command_help_show, struct help_entry *c,
782         bool show_help, const char *cmd_match);
783
784 static COMMAND_HELPER(command_help_show_list, bool show_help, const char *cmd_match)
785 {
786         struct help_entry *entry;
787
788         list_for_each_entry(entry, CMD_CTX->help_list, lh)
789                 CALL_COMMAND_HANDLER(command_help_show, entry, show_help, cmd_match);
790         return ERROR_OK;
791 }
792
793 #define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n))
794
795 static void command_help_show_indent(unsigned n)
796 {
797         for (unsigned i = 0; i < n; i++)
798                 LOG_USER_N("  ");
799 }
800 static void command_help_show_wrap(const char *str, unsigned n, unsigned n2)
801 {
802         const char *cp = str, *last = str;
803         while (*cp) {
804                 const char *next = last;
805                 do {
806                         cp = next;
807                         do {
808                                 next++;
809                         } while (*next != ' ' && *next != '\t' && *next != '\0');
810                 } while ((next - last < HELP_LINE_WIDTH(n)) && *next != '\0');
811                 if (next - last < HELP_LINE_WIDTH(n))
812                         cp = next;
813                 command_help_show_indent(n);
814                 LOG_USER("%.*s", (int)(cp - last), last);
815                 last = cp + 1;
816                 n = n2;
817         }
818 }
819
820 static COMMAND_HELPER(command_help_show, struct help_entry *c,
821         bool show_help, const char *cmd_match)
822 {
823         unsigned int n = 0;
824         for (const char *s = strchr(c->cmd_name, ' '); s; s = strchr(s + 1, ' '))
825                 n++;
826
827         /* If the match string occurs anywhere, we print out
828          * stuff for this command. */
829         bool is_match = (strstr(c->cmd_name, cmd_match) != NULL) ||
830                 ((c->usage != NULL) && (strstr(c->usage, cmd_match) != NULL)) ||
831                 ((c->help != NULL) && (strstr(c->help, cmd_match) != NULL));
832
833         if (is_match) {
834                 command_help_show_indent(n);
835                 LOG_USER_N("%s", c->cmd_name);
836
837                 if (c->usage && strlen(c->usage) > 0) {
838                         LOG_USER_N(" ");
839                         command_help_show_wrap(c->usage, 0, n + 5);
840                 } else
841                         LOG_USER_N("\n");
842         }
843
844         if (is_match && show_help) {
845                 char *msg;
846
847                 /* TODO: factorize jim_command_mode() to avoid running jim command here */
848                 char *request = alloc_printf("command mode %s", c->cmd_name);
849                 if (!request) {
850                         LOG_ERROR("Out of memory");
851                         return ERROR_FAIL;
852                 }
853                 int retval = Jim_Eval(CMD_CTX->interp, request);
854                 free(request);
855                 enum command_mode mode = COMMAND_UNKNOWN;
856                 if (retval != JIM_ERR) {
857                         const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL);
858                         if (!strcmp(result, "any"))
859                                 mode = COMMAND_ANY;
860                         else if (!strcmp(result, "config"))
861                                 mode = COMMAND_CONFIG;
862                         else if (!strcmp(result, "exec"))
863                                 mode = COMMAND_EXEC;
864                 }
865
866                 /* Normal commands are runtime-only; highlight exceptions */
867                 if (mode != COMMAND_EXEC) {
868                         const char *stage_msg = "";
869
870                         switch (mode) {
871                                 case COMMAND_CONFIG:
872                                         stage_msg = " (configuration command)";
873                                         break;
874                                 case COMMAND_ANY:
875                                         stage_msg = " (command valid any time)";
876                                         break;
877                                 default:
878                                         stage_msg = " (?mode error?)";
879                                         break;
880                         }
881                         msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
882                 } else
883                         msg = alloc_printf("%s", c->help ? : "");
884
885                 if (NULL != msg) {
886                         command_help_show_wrap(msg, n + 3, n + 3);
887                         free(msg);
888                 } else
889                         return -ENOMEM;
890         }
891
892         return ERROR_OK;
893 }
894
895 COMMAND_HANDLER(handle_help_command)
896 {
897         bool full = strcmp(CMD_NAME, "help") == 0;
898         int retval;
899         char *cmd_match;
900
901         if (CMD_ARGC <= 0)
902                 cmd_match = strdup("");
903
904         else {
905                 cmd_match = strdup(CMD_ARGV[0]);
906
907                 for (unsigned int i = 1; i < CMD_ARGC && cmd_match; ++i) {
908                         char *prev = cmd_match;
909                         cmd_match = alloc_printf("%s %s", prev, CMD_ARGV[i]);
910                         free(prev);
911                 }
912         }
913
914         if (cmd_match == NULL) {
915                 LOG_ERROR("unable to build search string");
916                 return -ENOMEM;
917         }
918         retval = CALL_COMMAND_HANDLER(command_help_show_list, full, cmd_match);
919
920         free(cmd_match);
921         return retval;
922 }
923
924 static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
925         struct command *head, struct command **out)
926 {
927         if (0 == argc)
928                 return argc;
929         const char *cmd_name = Jim_GetString(argv[0], NULL);
930         struct command *c = command_find(head, cmd_name);
931         if (NULL == c)
932                 return argc;
933         *out = c;
934         return command_unknown_find(--argc, ++argv, (*out)->children, out);
935 }
936
937 static char *alloc_concatenate_strings(int argc, Jim_Obj * const *argv)
938 {
939         char *prev, *all;
940         int i;
941
942         assert(argc >= 1);
943
944         all = strdup(Jim_GetString(argv[0], NULL));
945         if (!all) {
946                 LOG_ERROR("Out of memory");
947                 return NULL;
948         }
949
950         for (i = 1; i < argc; ++i) {
951                 prev = all;
952                 all = alloc_printf("%s %s", all, Jim_GetString(argv[i], NULL));
953                 free(prev);
954                 if (!all) {
955                         LOG_ERROR("Out of memory");
956                         return NULL;
957                 }
958         }
959
960         return all;
961 }
962
963 static int exec_command(Jim_Interp *interp, struct command_context *cmd_ctx,
964                 struct command *c, int argc, Jim_Obj * const *argv)
965 {
966         if (c->jim_handler)
967                 return c->jim_handler(interp, argc, argv);
968
969         /* use c->handler */
970         unsigned int nwords;
971         char **words = script_command_args_alloc(argc, argv, &nwords);
972         if (!words)
973                 return JIM_ERR;
974
975         int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
976         script_command_args_free(words, nwords);
977         return command_retval_set(interp, retval);
978 }
979
980 static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
981 {
982         script_debug(interp, argc, argv);
983
984         /* check subcommands */
985         if (argc > 1) {
986                 char *s = alloc_printf("%s %s", Jim_GetString(argv[0], NULL), Jim_GetString(argv[1], NULL));
987                 Jim_Obj *js = Jim_NewStringObj(interp, s, -1);
988                 Jim_IncrRefCount(js);
989                 free(s);
990                 Jim_Cmd *cmd = Jim_GetCommand(interp, js, JIM_NONE);
991                 if (cmd) {
992                         int retval = Jim_EvalObjPrefix(interp, js, argc - 2, argv + 2);
993                         Jim_DecrRefCount(interp, js);
994                         return retval;
995                 }
996                 Jim_DecrRefCount(interp, js);
997         }
998
999         struct command *c = jim_to_command(interp);
1000         if (!c->jim_handler && !c->handler) {
1001                 Jim_EvalObjPrefix(interp, Jim_NewStringObj(interp, "usage", -1), 1, argv);
1002                 return JIM_ERR;
1003         }
1004
1005         struct command_context *cmd_ctx = current_command_context(interp);
1006
1007         if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL)))
1008                 return JIM_ERR;
1009
1010         target_call_timer_callbacks_now();
1011
1012         /*
1013          * Black magic of overridden current target:
1014          * If the command we are going to handle has a target prefix,
1015          * override the current target temporarily for the time
1016          * of processing the command.
1017          * current_target_override is used also for event handlers
1018          * therefore we prevent touching it if command has no prefix.
1019          * Previous override is saved and restored back to ensure
1020          * correct work when command_unknown() is re-entered.
1021          */
1022         struct target *saved_target_override = cmd_ctx->current_target_override;
1023         if (c->jim_override_target)
1024                 cmd_ctx->current_target_override = c->jim_override_target;
1025
1026         int retval = exec_command(interp, cmd_ctx, c, argc, argv);
1027
1028         if (c->jim_override_target)
1029                 cmd_ctx->current_target_override = saved_target_override;
1030
1031         return retval;
1032 }
1033
1034 static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
1035 {
1036         struct command_context *cmd_ctx = current_command_context(interp);
1037         enum command_mode mode;
1038
1039         if (argc > 1) {
1040                 char *full_name = alloc_concatenate_strings(argc - 1, argv + 1);
1041                 if (!full_name)
1042                         return JIM_ERR;
1043                 Jim_Obj *s = Jim_NewStringObj(interp, full_name, -1);
1044                 Jim_IncrRefCount(s);
1045                 Jim_Cmd *cmd = Jim_GetCommand(interp, s, JIM_NONE);
1046                 Jim_DecrRefCount(interp, s);
1047                 free(full_name);
1048                 if (cmd && jimcmd_is_proc(cmd)) {
1049                         Jim_SetResultString(interp, "any", -1);
1050                         return JIM_OK;
1051                 }
1052                 struct command *c = cmd_ctx->commands;
1053                 int remaining = command_unknown_find(argc - 1, argv + 1, c, &c);
1054                 /* if nothing could be consumed, then it's an unknown command */
1055                 if (remaining == argc - 1) {
1056                         Jim_SetResultString(interp, "unknown", -1);
1057                         return JIM_OK;
1058                 }
1059                 mode = c->mode;
1060         } else
1061                 mode = cmd_ctx->mode;
1062
1063         const char *mode_str;
1064         switch (mode) {
1065                 case COMMAND_ANY:
1066                         mode_str = "any";
1067                         break;
1068                 case COMMAND_CONFIG:
1069                         mode_str = "config";
1070                         break;
1071                 case COMMAND_EXEC:
1072                         mode_str = "exec";
1073                         break;
1074                 default:
1075                         mode_str = "unknown";
1076                         break;
1077         }
1078         Jim_SetResultString(interp, mode_str, -1);
1079         return JIM_OK;
1080 }
1081
1082 int help_del_all_commands(struct command_context *cmd_ctx)
1083 {
1084         struct help_entry *curr, *n;
1085
1086         list_for_each_entry_safe(curr, n, cmd_ctx->help_list, lh) {
1087                 list_del(&curr->lh);
1088                 free(curr->cmd_name);
1089                 free(curr->help);
1090                 free(curr->usage);
1091                 free(curr);
1092         }
1093         return ERROR_OK;
1094 }
1095
1096 static int help_del_command(struct command_context *cmd_ctx, const char *cmd_name)
1097 {
1098         struct help_entry *curr;
1099
1100         list_for_each_entry(curr, cmd_ctx->help_list, lh) {
1101                 if (!strcmp(cmd_name, curr->cmd_name)) {
1102                         list_del(&curr->lh);
1103                         free(curr->cmd_name);
1104                         free(curr->help);
1105                         free(curr->usage);
1106                         free(curr);
1107                         break;
1108                 }
1109         }
1110
1111         return ERROR_OK;
1112 }
1113
1114 static int help_add_command(struct command_context *cmd_ctx,
1115         const char *cmd_name, const char *help_text, const char *usage_text)
1116 {
1117         int cmp = -1; /* add after curr */
1118         struct help_entry *curr;
1119
1120         list_for_each_entry_reverse(curr, cmd_ctx->help_list, lh) {
1121                 cmp = strcmp(cmd_name, curr->cmd_name);
1122                 if (cmp >= 0)
1123                         break;
1124         }
1125
1126         struct help_entry *entry;
1127         if (cmp) {
1128                 entry = calloc(1, sizeof(*entry));
1129                 if (!entry) {
1130                         LOG_ERROR("Out of memory");
1131                         return ERROR_FAIL;
1132                 }
1133                 entry->cmd_name = strdup(cmd_name);
1134                 if (!entry->cmd_name) {
1135                         LOG_ERROR("Out of memory");
1136                         free(entry);
1137                         return ERROR_FAIL;
1138                 }
1139                 list_add(&entry->lh, &curr->lh);
1140         } else {
1141                 entry = curr;
1142         }
1143
1144         if (help_text) {
1145                 char *text = strdup(help_text);
1146                 if (!text) {
1147                         LOG_ERROR("Out of memory");
1148                         return ERROR_FAIL;
1149                 }
1150                 free(entry->help);
1151                 entry->help = text;
1152         }
1153
1154         if (usage_text) {
1155                 char *text = strdup(usage_text);
1156                 if (!text) {
1157                         LOG_ERROR("Out of memory");
1158                         return ERROR_FAIL;
1159                 }
1160                 free(entry->usage);
1161                 entry->usage = text;
1162         }
1163
1164         return ERROR_OK;
1165 }
1166
1167 COMMAND_HANDLER(handle_help_add_command)
1168 {
1169         if (CMD_ARGC != 2)
1170                 return ERROR_COMMAND_SYNTAX_ERROR;
1171
1172         const char *help = !strcmp(CMD_NAME, "add_help_text") ? CMD_ARGV[1] : NULL;
1173         const char *usage = !strcmp(CMD_NAME, "add_usage_text") ? CMD_ARGV[1] : NULL;
1174         if (!help && !usage) {
1175                 LOG_ERROR("command name '%s' is unknown", CMD_NAME);
1176                 return ERROR_COMMAND_SYNTAX_ERROR;
1177         }
1178         const char *cmd_name = CMD_ARGV[0];
1179         return help_add_command(CMD_CTX, cmd_name, help, usage);
1180 }
1181
1182 /* sleep command sleeps for <n> milliseconds
1183  * this is useful in target startup scripts
1184  */
1185 COMMAND_HANDLER(handle_sleep_command)
1186 {
1187         bool busy = false;
1188         if (CMD_ARGC == 2) {
1189                 if (strcmp(CMD_ARGV[1], "busy") == 0)
1190                         busy = true;
1191                 else
1192                         return ERROR_COMMAND_SYNTAX_ERROR;
1193         } else if (CMD_ARGC < 1 || CMD_ARGC > 2)
1194                 return ERROR_COMMAND_SYNTAX_ERROR;
1195
1196         unsigned long duration = 0;
1197         int retval = parse_ulong(CMD_ARGV[0], &duration);
1198         if (ERROR_OK != retval)
1199                 return retval;
1200
1201         if (!busy) {
1202                 int64_t then = timeval_ms();
1203                 while (timeval_ms() - then < (int64_t)duration) {
1204                         target_call_timer_callbacks_now();
1205                         usleep(1000);
1206                 }
1207         } else
1208                 busy_sleep(duration);
1209
1210         return ERROR_OK;
1211 }
1212
1213 static const struct command_registration command_subcommand_handlers[] = {
1214         {
1215                 .name = "mode",
1216                 .mode = COMMAND_ANY,
1217                 .jim_handler = jim_command_mode,
1218                 .usage = "[command_name ...]",
1219                 .help = "Returns the command modes allowed by a command: "
1220                         "'any', 'config', or 'exec'. If no command is "
1221                         "specified, returns the current command mode. "
1222                         "Returns 'unknown' if an unknown command is given. "
1223                         "Command can be multiple tokens.",
1224         },
1225         COMMAND_REGISTRATION_DONE
1226 };
1227
1228 static const struct command_registration command_builtin_handlers[] = {
1229         {
1230                 .name = "ocd_find",
1231                 .mode = COMMAND_ANY,
1232                 .jim_handler = jim_find,
1233                 .help = "find full path to file",
1234                 .usage = "file",
1235         },
1236         {
1237                 .name = "capture",
1238                 .mode = COMMAND_ANY,
1239                 .jim_handler = jim_capture,
1240                 .help = "Capture progress output and return as tcl return value. If the "
1241                                 "progress output was empty, return tcl return value.",
1242                 .usage = "command",
1243         },
1244         {
1245                 .name = "echo",
1246                 .handler = jim_echo,
1247                 .mode = COMMAND_ANY,
1248                 .help = "Logs a message at \"user\" priority. "
1249                         "Output message to stdout. "
1250                         "Option \"-n\" suppresses trailing newline",
1251                 .usage = "[-n] string",
1252         },
1253         {
1254                 .name = "add_help_text",
1255                 .handler = handle_help_add_command,
1256                 .mode = COMMAND_ANY,
1257                 .help = "Add new command help text; "
1258                         "Command can be multiple tokens.",
1259                 .usage = "command_name helptext_string",
1260         },
1261         {
1262                 .name = "add_usage_text",
1263                 .handler = handle_help_add_command,
1264                 .mode = COMMAND_ANY,
1265                 .help = "Add new command usage text; "
1266                         "command can be multiple tokens.",
1267                 .usage = "command_name usage_string",
1268         },
1269         {
1270                 .name = "sleep",
1271                 .handler = handle_sleep_command,
1272                 .mode = COMMAND_ANY,
1273                 .help = "Sleep for specified number of milliseconds.  "
1274                         "\"busy\" will busy wait instead (avoid this).",
1275                 .usage = "milliseconds ['busy']",
1276         },
1277         {
1278                 .name = "help",
1279                 .handler = handle_help_command,
1280                 .mode = COMMAND_ANY,
1281                 .help = "Show full command help; "
1282                         "command can be multiple tokens.",
1283                 .usage = "[command_name]",
1284         },
1285         {
1286                 .name = "usage",
1287                 .handler = handle_help_command,
1288                 .mode = COMMAND_ANY,
1289                 .help = "Show basic command usage; "
1290                         "command can be multiple tokens.",
1291                 .usage = "[command_name]",
1292         },
1293         {
1294                 .name = "command",
1295                 .mode = COMMAND_ANY,
1296                 .help = "core command group (introspection)",
1297                 .chain = command_subcommand_handlers,
1298                 .usage = "",
1299         },
1300         COMMAND_REGISTRATION_DONE
1301 };
1302
1303 struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp)
1304 {
1305         struct command_context *context = calloc(1, sizeof(struct command_context));
1306         const char *HostOs;
1307
1308         context->mode = COMMAND_EXEC;
1309
1310         /* context can be duplicated. Put list head on separate mem-chunk to keep list consistent */
1311         context->help_list = malloc(sizeof(*context->help_list));
1312         INIT_LIST_HEAD(context->help_list);
1313
1314         /* Create a jim interpreter if we were not handed one */
1315         if (interp == NULL) {
1316                 /* Create an interpreter */
1317                 interp = Jim_CreateInterp();
1318                 /* Add all the Jim core commands */
1319                 Jim_RegisterCoreCommands(interp);
1320                 Jim_InitStaticExtensions(interp);
1321         }
1322
1323         context->interp = interp;
1324
1325         /* Stick to lowercase for HostOS strings. */
1326 #if defined(_MSC_VER)
1327         /* WinXX - is generic, the forward
1328          * looking problem is this:
1329          *
1330          *   "win32" or "win64"
1331          *
1332          * "winxx" is generic.
1333          */
1334         HostOs = "winxx";
1335 #elif defined(__linux__)
1336         HostOs = "linux";
1337 #elif defined(__APPLE__) || defined(__DARWIN__)
1338         HostOs = "darwin";
1339 #elif defined(__CYGWIN__)
1340         HostOs = "cygwin";
1341 #elif defined(__MINGW32__)
1342         HostOs = "mingw32";
1343 #elif defined(__ECOS)
1344         HostOs = "ecos";
1345 #elif defined(__FreeBSD__)
1346         HostOs = "freebsd";
1347 #elif defined(__NetBSD__)
1348         HostOs = "netbsd";
1349 #elif defined(__OpenBSD__)
1350         HostOs = "openbsd";
1351 #else
1352 #warning "Unrecognized host OS..."
1353         HostOs = "other";
1354 #endif
1355         Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
1356                 Jim_NewStringObj(interp, HostOs, strlen(HostOs)));
1357
1358         register_commands(context, NULL, command_builtin_handlers);
1359
1360         Jim_SetAssocData(interp, "context", NULL, context);
1361         if (Jim_Eval_Named(interp, startup_tcl, "embedded:startup.tcl", 1) == JIM_ERR) {
1362                 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD)");
1363                 Jim_MakeErrorMessage(interp);
1364                 LOG_USER_N("%s", Jim_GetString(Jim_GetResult(interp), NULL));
1365                 exit(-1);
1366         }
1367         Jim_DeleteAssocData(interp, "context");
1368
1369         return context;
1370 }
1371
1372 void command_exit(struct command_context *context)
1373 {
1374         if (!context)
1375                 return;
1376
1377         Jim_FreeInterp(context->interp);
1378         free(context->help_list);
1379         command_done(context);
1380 }
1381
1382 int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode)
1383 {
1384         if (!cmd_ctx)
1385                 return ERROR_COMMAND_SYNTAX_ERROR;
1386
1387         cmd_ctx->mode = mode;
1388         return ERROR_OK;
1389 }
1390
1391 void process_jim_events(struct command_context *cmd_ctx)
1392 {
1393         static int recursion;
1394         if (recursion)
1395                 return;
1396
1397         recursion++;
1398         Jim_ProcessEvents(cmd_ctx->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
1399         recursion--;
1400 }
1401
1402 #define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \
1403         int parse ## name(const char *str, type * ul) \
1404         { \
1405                 if (!*str) { \
1406                         LOG_ERROR("Invalid command argument"); \
1407                         return ERROR_COMMAND_ARGUMENT_INVALID; \
1408                 } \
1409                 char *end; \
1410                 errno = 0; \
1411                 *ul = func(str, &end, 0); \
1412                 if (*end) { \
1413                         LOG_ERROR("Invalid command argument"); \
1414                         return ERROR_COMMAND_ARGUMENT_INVALID; \
1415                 } \
1416                 if ((max == *ul) && (ERANGE == errno)) { \
1417                         LOG_ERROR("Argument overflow"); \
1418                         return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
1419                 } \
1420                 if (min && (min == *ul) && (ERANGE == errno)) { \
1421                         LOG_ERROR("Argument underflow"); \
1422                         return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
1423                 } \
1424                 return ERROR_OK; \
1425         }
1426 DEFINE_PARSE_NUM_TYPE(_ulong, unsigned long, strtoul, 0, ULONG_MAX)
1427 DEFINE_PARSE_NUM_TYPE(_ullong, unsigned long long, strtoull, 0, ULLONG_MAX)
1428 DEFINE_PARSE_NUM_TYPE(_long, long, strtol, LONG_MIN, LONG_MAX)
1429 DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX)
1430
1431 #define DEFINE_PARSE_WRAPPER(name, type, min, max, functype, funcname) \
1432         int parse ## name(const char *str, type * ul) \
1433         { \
1434                 functype n; \
1435                 int retval = parse ## funcname(str, &n); \
1436                 if (ERROR_OK != retval) \
1437                         return retval; \
1438                 if (n > max) \
1439                         return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
1440                 if (min) \
1441                         return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
1442                 *ul = n; \
1443                 return ERROR_OK; \
1444         }
1445
1446 #define DEFINE_PARSE_ULONGLONG(name, type, min, max) \
1447         DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long long, _ullong)
1448 DEFINE_PARSE_ULONGLONG(_uint, unsigned, 0, UINT_MAX)
1449 DEFINE_PARSE_ULONGLONG(_u64,  uint64_t, 0, UINT64_MAX)
1450 DEFINE_PARSE_ULONGLONG(_u32,  uint32_t, 0, UINT32_MAX)
1451 DEFINE_PARSE_ULONGLONG(_u16,  uint16_t, 0, UINT16_MAX)
1452 DEFINE_PARSE_ULONGLONG(_u8,   uint8_t,  0, UINT8_MAX)
1453
1454 DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX)
1455
1456 #define DEFINE_PARSE_LONGLONG(name, type, min, max) \
1457         DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong)
1458 DEFINE_PARSE_LONGLONG(_int, int,     n < INT_MIN,   INT_MAX)
1459 DEFINE_PARSE_LONGLONG(_s64, int64_t, n < INT64_MIN, INT64_MAX)
1460 DEFINE_PARSE_LONGLONG(_s32, int32_t, n < INT32_MIN, INT32_MAX)
1461 DEFINE_PARSE_LONGLONG(_s16, int16_t, n < INT16_MIN, INT16_MAX)
1462 DEFINE_PARSE_LONGLONG(_s8,  int8_t,  n < INT8_MIN,  INT8_MAX)
1463
1464 static int command_parse_bool(const char *in, bool *out,
1465         const char *on, const char *off)
1466 {
1467         if (strcasecmp(in, on) == 0)
1468                 *out = true;
1469         else if (strcasecmp(in, off) == 0)
1470                 *out = false;
1471         else
1472                 return ERROR_COMMAND_SYNTAX_ERROR;
1473         return ERROR_OK;
1474 }
1475
1476 int command_parse_bool_arg(const char *in, bool *out)
1477 {
1478         if (command_parse_bool(in, out, "on", "off") == ERROR_OK)
1479                 return ERROR_OK;
1480         if (command_parse_bool(in, out, "enable", "disable") == ERROR_OK)
1481                 return ERROR_OK;
1482         if (command_parse_bool(in, out, "true", "false") == ERROR_OK)
1483                 return ERROR_OK;
1484         if (command_parse_bool(in, out, "yes", "no") == ERROR_OK)
1485                 return ERROR_OK;
1486         if (command_parse_bool(in, out, "1", "0") == ERROR_OK)
1487                 return ERROR_OK;
1488         return ERROR_COMMAND_SYNTAX_ERROR;
1489 }
1490
1491 COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
1492 {
1493         switch (CMD_ARGC) {
1494                 case 1: {
1495                         const char *in = CMD_ARGV[0];
1496                         if (command_parse_bool_arg(in, out) != ERROR_OK) {
1497                                 LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
1498                                 return ERROR_COMMAND_SYNTAX_ERROR;
1499                         }
1500                 }
1501                         /* fallthrough */
1502                 case 0:
1503                         LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
1504                         break;
1505                 default:
1506                         return ERROR_COMMAND_SYNTAX_ERROR;
1507         }
1508         return ERROR_OK;
1509 }