rewrite 'unknown' command dispatching in C
[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, write to the                         *
26  *   Free Software Foundation, Inc.,                                       *
27  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
28  ***************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #if !BUILD_ECOSBOARD
34 /* see Embedder-HOWTO.txt in Jim Tcl project hosted on BerliOS*/
35 #define JIM_EMBEDDED
36 #endif
37
38 // @todo the inclusion of target.h here is a layering violation
39 #include "target.h"
40 #include "command.h"
41 #include "configuration.h"
42 #include "log.h"
43 #include "time_support.h"
44 #include "jim-eventloop.h"
45
46
47 Jim_Interp *interp = NULL;
48
49 static int run_command(struct command_context *context,
50                 struct command *c, const char *words[], unsigned num_words);
51
52 static void tcl_output(void *privData, const char *file, unsigned line,
53                 const char *function, const char *string)
54 {
55         Jim_Obj *tclOutput = (Jim_Obj *)privData;
56         Jim_AppendString(interp, tclOutput, string, strlen(string));
57 }
58
59 extern struct command_context *global_cmd_ctx;
60
61 void script_debug(Jim_Interp *interp, const char *name,
62                 unsigned argc, Jim_Obj *const *argv)
63 {
64         LOG_DEBUG("command - %s", name);
65         for (unsigned i = 0; i < argc; i++)
66         {
67                 int len;
68                 const char *w = Jim_GetString(argv[i], &len);
69
70                 /* end of line comment? */
71                 if (*w == '#')
72                         break;
73
74                 LOG_DEBUG("%s - argv[%d]=%s", name, i, w);
75         }
76 }
77
78 static void script_command_args_free(const char **words, unsigned nwords)
79 {
80         for (unsigned i = 0; i < nwords; i++)
81                 free((void *)words[i]);
82         free(words);
83 }
84 static const char **script_command_args_alloc(
85                 unsigned argc, Jim_Obj *const *argv, unsigned *nwords)
86 {
87         const char **words = malloc(argc * sizeof(char *));
88         if (NULL == words)
89                 return NULL;
90
91         unsigned i;
92         for (i = 0; i < argc; i++)
93         {
94                 int len;
95                 const char *w = Jim_GetString(argv[i], &len);
96                 /* a comment may end the line early */
97                 if (*w == '#')
98                         break;
99
100                 words[i] = strdup(w);
101                 if (words[i] == NULL)
102                 {
103                         script_command_args_free(words, i);
104                         return NULL;
105                 }
106         }
107         *nwords = i;
108         return words;
109 }
110
111 static struct command_context *current_command_context(void)
112 {
113         /* grab the command context from the associated data */
114         struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
115         if (NULL == cmd_ctx)
116         {
117                 /* Tcl can invoke commands directly instead of via command_run_line(). This would
118                  * happen when the Jim Tcl interpreter is provided by eCos.
119                  */
120                 cmd_ctx = global_cmd_ctx;
121         }
122         return cmd_ctx;
123 }
124
125 static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
126 {
127         /* the private data is stashed in the interp structure */
128         struct command *c;
129         int retval;
130
131         /* DANGER!!!! be careful what we invoke here, since interp->cmdPrivData might
132          * get overwritten by running other Jim commands! Treat it as an
133          * emphemeral global variable that is used in lieu of an argument
134          * to the fn and fish it out manually.
135          */
136         c = interp->cmdPrivData;
137         if (c == NULL)
138         {
139                 LOG_ERROR("BUG: interp->cmdPrivData == NULL");
140                 return JIM_ERR;
141         }
142         target_call_timer_callbacks_now();
143         LOG_USER_N("%s", ""); /* Keep GDB connection alive*/
144
145         script_debug(interp, c->name, argc, argv);
146
147         unsigned nwords;
148         const char **words = script_command_args_alloc(argc, argv, &nwords);
149         if (NULL == words)
150                 return JIM_ERR;
151
152         /* capture log output and return it */
153         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
154         /* a garbage collect can happen, so we need a reference count to this object */
155         Jim_IncrRefCount(tclOutput);
156
157         log_add_callback(tcl_output, tclOutput);
158
159         struct command_context *cmd_ctx = current_command_context();
160         retval = run_command(cmd_ctx, c, (const char **)words, nwords);
161
162         log_remove_callback(tcl_output, tclOutput);
163
164         /* We dump output into this local variable */
165         Jim_SetResult(interp, tclOutput);
166         Jim_DecrRefCount(interp, tclOutput);
167
168         script_command_args_free(words, nwords);
169
170         int *return_retval = Jim_GetAssocData(interp, "retval");
171         if (return_retval != NULL)
172         {
173                 *return_retval = retval;
174         }
175
176         return (retval == ERROR_OK)?JIM_OK:JIM_ERR;
177 }
178
179 /* nice short description of source file */
180 #define __THIS__FILE__ "command.c"
181
182 /**
183  * Find a command by name from a list of commands.
184  * @returns Returns the named command if it exists in the list.
185  * Returns NULL otherwise.
186  */
187 static struct command *command_find(struct command *head, const char *name)
188 {
189         for (struct command *cc = head; cc; cc = cc->next)
190         {
191                 if (strcmp(cc->name, name) == 0)
192                         return cc;
193         }
194         return NULL;
195 }
196 struct command *command_find_in_context(struct command_context *cmd_ctx,
197                 const char *name)
198 {
199         return command_find(cmd_ctx->commands, name);
200 }
201 struct command *command_find_in_parent(struct command *parent,
202                 const char *name)
203 {
204         return command_find(parent->children, name);
205 }
206
207 /**
208  * Add the command into the linked list, sorted by name.
209  * @param head Address to head of command list pointer, which may be
210  * updated if @c c gets inserted at the beginning of the list.
211  * @param c The command to add to the list pointed to by @c head.
212  */
213 static void command_add_child(struct command **head, struct command *c)
214 {
215         assert(head);
216         if (NULL == *head)
217         {
218                 *head = c;
219                 return;
220         }
221
222         while ((*head)->next && (strcmp(c->name, (*head)->name) > 0))
223                 head = &(*head)->next;
224
225         if (strcmp(c->name, (*head)->name) > 0) {
226                 c->next = (*head)->next;
227                 (*head)->next = c;
228         } else {
229                 c->next = *head;
230                 *head = c;
231         }
232 }
233
234 static struct command **command_list_for_parent(
235                 struct command_context *cmd_ctx, struct command *parent)
236 {
237         return parent ? &parent->children : &cmd_ctx->commands;
238 }
239
240 static struct command *command_new(struct command_context *cmd_ctx,
241                 struct command *parent, const char *name,
242                 command_handler_t handler, enum command_mode mode,
243                 const char *help, const char *usage)
244 {
245         assert(name);
246
247         struct command *c = malloc(sizeof(struct command));
248         memset(c, 0, sizeof(struct command));
249
250         c->name = strdup(name);
251         if (help)
252                 c->help = strdup(help);
253         if (usage)
254                 c->usage = strdup(usage);
255         c->parent = parent;
256         c->handler = handler;
257         c->mode = mode;
258
259         command_add_child(command_list_for_parent(cmd_ctx, parent), c);
260
261         return c;
262 }
263 static void command_free(struct command *c)
264 {
265         /// @todo if command has a handler, unregister its jim command!
266
267         while (NULL != c->children)
268         {
269                 struct command *tmp = c->children;
270                 c->children = tmp->next;
271                 command_free(tmp);
272         }
273
274         if (c->name)
275                 free(c->name);
276         if (c->help)
277                 free((void*)c->help);
278         if (c->usage)
279                 free((void*)c->usage);
280         free(c);
281 }
282
283 static int register_command_handler(struct command *c)
284 {
285         int retval = -ENOMEM;
286         const char *full_name = command_name(c, '_');
287         if (NULL == full_name)
288                 return retval;
289
290         const char *ocd_name = alloc_printf("ocd_%s", full_name);
291         if (NULL == full_name)
292                 goto free_full_name;
293
294         Jim_CreateCommand(interp, ocd_name, script_command, c, NULL);
295         free((void *)ocd_name);
296
297         /* we now need to add an overrideable proc */
298         const char *override_name = alloc_printf("proc %s {args} {"
299                         "if {[catch {eval ocd_%s $args}] == 0} "
300                         "{return \"\"} else {return -code error}}",
301                         full_name, full_name);
302         if (NULL == full_name)
303                 goto free_full_name;
304
305         Jim_Eval_Named(interp, override_name, __THIS__FILE__, __LINE__);
306         free((void *)override_name);
307
308         retval = ERROR_OK;
309
310 free_full_name:
311         free((void *)full_name);
312         return retval;
313 }
314
315 struct command* register_command(struct command_context *context,
316                 struct command *parent, const struct command_registration *cr)
317 {
318         if (!context || !cr->name)
319                 return NULL;
320
321         const char *name = cr->name;
322         struct command **head = command_list_for_parent(context, parent);
323         struct command *c = command_find(*head, name);
324         if (NULL != c)
325         {
326                 LOG_ERROR("command '%s' is already registered in '%s' context",
327                                 name, parent ? parent->name : "<global>");
328                 return c;
329         }
330
331         c = command_new(context, parent, name, cr->handler, cr->mode, cr->help, cr->usage);
332         /* if allocation failed or it is a placeholder (no handler), we're done */
333         if (NULL == c || NULL == c->handler)
334                 return c;
335
336         int retval = register_command_handler(c);
337         if (ERROR_OK != retval)
338         {
339                 unregister_command(context, parent, name);
340                 c = NULL;
341         }
342         return c;
343 }
344
345 int register_commands(struct command_context *cmd_ctx, struct command *parent,
346                 const struct command_registration *cmds)
347 {
348         int retval = ERROR_OK;
349         unsigned i;
350         for (i = 0; cmds[i].name || cmds[i].chain; i++)
351         {
352                 const struct command_registration *cr = cmds + i;
353
354                 struct command *c = NULL;
355                 if (NULL != cr->name)
356                 {
357                         c = register_command(cmd_ctx, parent, cr);
358                         if (NULL == c)
359                         {
360                                 retval = ERROR_FAIL;
361                                 break;
362                         }
363                 }
364                 if (NULL != cr->chain)
365                 {
366                         struct command *p = c ? : parent;
367                         retval = register_commands(cmd_ctx, p, cr->chain);
368                         if (ERROR_OK != retval)
369                                 break;
370                 }
371         }
372         if (ERROR_OK != retval)
373         {
374                 for (unsigned j = 0; j < i; j++)
375                         unregister_command(cmd_ctx, parent, cmds[j].name);
376         }
377         return retval;
378 }
379
380 int unregister_all_commands(struct command_context *context,
381                 struct command *parent)
382 {
383         if (context == NULL)
384                 return ERROR_OK;
385
386         struct command **head = command_list_for_parent(context, parent);
387         while (NULL != *head)
388         {
389                 struct command *tmp = *head;
390                 *head = tmp->next;
391                 command_free(tmp);
392         }
393
394         return ERROR_OK;
395 }
396
397 int unregister_command(struct command_context *context,
398                 struct command *parent, const char *name)
399 {
400         if ((!context) || (!name))
401                 return ERROR_INVALID_ARGUMENTS;
402
403         struct command *p = NULL;
404         struct command **head = command_list_for_parent(context, parent);
405         for (struct command *c = *head; NULL != c; p = c, c = c->next)
406         {
407                 if (strcmp(name, c->name) != 0)
408                         continue;
409
410                 if (p)
411                         p->next = c->next;
412                 else
413                         *head = c->next;
414
415                 command_free(c);
416                 return ERROR_OK;
417         }
418
419         return ERROR_OK;
420 }
421
422 void command_output_text(struct command_context *context, const char *data)
423 {
424         if (context && context->output_handler && data) {
425                 context->output_handler(context, data);
426         }
427 }
428
429 void command_print_sameline(struct command_context *context, const char *format, ...)
430 {
431         char *string;
432
433         va_list ap;
434         va_start(ap, format);
435
436         string = alloc_vprintf(format, ap);
437         if (string != NULL)
438         {
439                 /* we want this collected in the log + we also want to pick it up as a tcl return
440                  * value.
441                  *
442                  * The latter bit isn't precisely neat, but will do for now.
443                  */
444                 LOG_USER_N("%s", string);
445                 /* We already printed it above */
446                 /* command_output_text(context, string); */
447                 free(string);
448         }
449
450         va_end(ap);
451 }
452
453 void command_print(struct command_context *context, const char *format, ...)
454 {
455         char *string;
456
457         va_list ap;
458         va_start(ap, format);
459
460         string = alloc_vprintf(format, ap);
461         if (string != NULL)
462         {
463                 strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one char longer */
464                 /* we want this collected in the log + we also want to pick it up as a tcl return
465                  * value.
466                  *
467                  * The latter bit isn't precisely neat, but will do for now.
468                  */
469                 LOG_USER_N("%s", string);
470                 /* We already printed it above */
471                 /* command_output_text(context, string); */
472                 free(string);
473         }
474
475         va_end(ap);
476 }
477
478 static char *__command_name(struct command *c, char delim, unsigned extra)
479 {
480         char *name;
481         unsigned len = strlen(c->name);
482         if (NULL == c->parent) {
483                 // allocate enough for the name, child names, and '\0'
484                 name = malloc(len + extra + 1);
485                 strcpy(name, c->name);
486         } else {
487                 // parent's extra must include both the space and name
488                 name = __command_name(c->parent, delim, 1 + len + extra);
489                 char dstr[2] = { delim, 0 };
490                 strcat(name, dstr);
491                 strcat(name, c->name);
492         }
493         return name;
494 }
495 char *command_name(struct command *c, char delim)
496 {
497         return __command_name(c, delim, 0);
498 }
499
500 static int run_command(struct command_context *context,
501                 struct command *c, const char *words[], unsigned num_words)
502 {
503         if (!((context->mode == COMMAND_CONFIG) || (c->mode == COMMAND_ANY) || (c->mode == context->mode)))
504         {
505                 /* Config commands can not run after the config stage */
506                 LOG_ERROR("Command '%s' only runs during configuration stage", c->name);
507                 return ERROR_FAIL;
508         }
509
510         struct command_invocation cmd = {
511                         .ctx = context,
512                         .name = c->name,
513                         .argc = num_words - 1,
514                         .argv = words + 1,
515                 };
516         int retval = c->handler(&cmd);
517         if (retval == ERROR_COMMAND_SYNTAX_ERROR)
518         {
519                 /* Print help for command */
520                 char *full_name = command_name(c, ' ');
521                 if (NULL != full_name) {
522                         command_run_linef(context, "help %s", full_name);
523                         free(full_name);
524                 } else
525                         retval = -ENOMEM;
526         }
527         else if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
528         {
529                 /* just fall through for a shutdown request */
530         }
531         else if (retval != ERROR_OK)
532         {
533                 /* we do not print out an error message because the command *should*
534                  * have printed out an error
535                  */
536                 LOG_DEBUG("Command failed with error code %d", retval);
537         }
538
539         return retval;
540 }
541
542 int command_run_line(struct command_context *context, char *line)
543 {
544         /* all the parent commands have been registered with the interpreter
545          * so, can just evaluate the line as a script and check for
546          * results
547          */
548         /* run the line thru a script engine */
549         int retval = ERROR_FAIL;
550         int retcode;
551         /* Beware! This code needs to be reentrant. It is also possible
552          * for OpenOCD commands to be invoked directly from Tcl. This would
553          * happen when the Jim Tcl interpreter is provided by eCos for
554          * instance.
555          */
556         Jim_DeleteAssocData(interp, "context");
557         retcode = Jim_SetAssocData(interp, "context", NULL, context);
558         if (retcode == JIM_OK)
559         {
560                 /* associated the return value */
561                 Jim_DeleteAssocData(interp, "retval");
562                 retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
563                 if (retcode == JIM_OK)
564                 {
565                         retcode = Jim_Eval_Named(interp, line, __THIS__FILE__, __LINE__);
566
567                         Jim_DeleteAssocData(interp, "retval");
568                 }
569                 Jim_DeleteAssocData(interp, "context");
570         }
571         if (retcode == JIM_ERR) {
572                 if (retval != ERROR_COMMAND_CLOSE_CONNECTION)
573                 {
574                         /* We do not print the connection closed error message */
575                         Jim_PrintErrorMessage(interp);
576                 }
577                 if (retval == ERROR_OK)
578                 {
579                         /* It wasn't a low level OpenOCD command that failed */
580                         return ERROR_FAIL;
581                 }
582                 return retval;
583         } else if (retcode == JIM_EXIT) {
584                 /* ignore. */
585                 /* exit(Jim_GetExitCode(interp)); */
586         } else {
587                 const char *result;
588                 int reslen;
589
590                 result = Jim_GetString(Jim_GetResult(interp), &reslen);
591                 if (reslen > 0)
592                 {
593                         int i;
594                         char buff[256 + 1];
595                         for (i = 0; i < reslen; i += 256)
596                         {
597                                 int chunk;
598                                 chunk = reslen - i;
599                                 if (chunk > 256)
600                                         chunk = 256;
601                                 strncpy(buff, result + i, chunk);
602                                 buff[chunk] = 0;
603                                 LOG_USER_N("%s", buff);
604                         }
605                         LOG_USER_N("%s", "\n");
606                 }
607                 retval = ERROR_OK;
608         }
609         return retval;
610 }
611
612 int command_run_linef(struct command_context *context, const char *format, ...)
613 {
614         int retval = ERROR_FAIL;
615         char *string;
616         va_list ap;
617         va_start(ap, format);
618         string = alloc_vprintf(format, ap);
619         if (string != NULL)
620         {
621                 retval = command_run_line(context, string);
622         }
623         va_end(ap);
624         return retval;
625 }
626
627 void command_set_output_handler(struct command_context* context,
628                 command_output_handler_t output_handler, void *priv)
629 {
630         context->output_handler = output_handler;
631         context->output_handler_priv = priv;
632 }
633
634 struct command_context* copy_command_context(struct command_context* context)
635 {
636         struct command_context* copy_context = malloc(sizeof(struct command_context));
637
638         *copy_context = *context;
639
640         return copy_context;
641 }
642
643 int command_done(struct command_context *context)
644 {
645         free(context);
646         context = NULL;
647
648         return ERROR_OK;
649 }
650
651 /* find full path to file */
652 static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
653 {
654         if (argc != 2)
655                 return JIM_ERR;
656         const char *file = Jim_GetString(argv[1], NULL);
657         char *full_path = find_file(file);
658         if (full_path == NULL)
659                 return JIM_ERR;
660         Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
661         free(full_path);
662
663         Jim_SetResult(interp, result);
664         return JIM_OK;
665 }
666
667 static int jim_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
668 {
669         if (argc != 2)
670                 return JIM_ERR;
671         const char *str = Jim_GetString(argv[1], NULL);
672         LOG_USER("%s", str);
673         return JIM_OK;
674 }
675
676 static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
677 {
678         size_t nbytes;
679         const char *ptr;
680         Jim_Interp *interp;
681
682         /* make it a char easier to read code */
683         ptr = _ptr;
684         interp = cookie;
685         nbytes = size * n;
686         if (ptr == NULL || interp == NULL || nbytes == 0) {
687                 return 0;
688         }
689
690         /* do we have to chunk it? */
691         if (ptr[nbytes] == 0)
692         {
693                 /* no it is a C style string */
694                 LOG_USER_N("%s", ptr);
695                 return strlen(ptr);
696         }
697         /* GRR we must chunk - not null terminated */
698         while (nbytes) {
699                 char chunk[128 + 1];
700                 int x;
701
702                 x = nbytes;
703                 if (x > 128) {
704                         x = 128;
705                 }
706                 /* copy it */
707                 memcpy(chunk, ptr, x);
708                 /* terminate it */
709                 chunk[n] = 0;
710                 /* output it */
711                 LOG_USER_N("%s", chunk);
712                 ptr += x;
713                 nbytes -= x;
714         }
715
716         return n;
717 }
718
719 static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie)
720 {
721         /* TCL wants to read... tell him no */
722         return 0;
723 }
724
725 static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
726 {
727         char *cp;
728         int n;
729         Jim_Interp *interp;
730
731         n = -1;
732         interp = cookie;
733         if (interp == NULL)
734                 return n;
735
736         cp = alloc_vprintf(fmt, ap);
737         if (cp)
738         {
739                 LOG_USER_N("%s", cp);
740                 n = strlen(cp);
741                 free(cp);
742         }
743         return n;
744 }
745
746 static int openocd_jim_fflush(void *cookie)
747 {
748         /* nothing to flush */
749         return 0;
750 }
751
752 static char* openocd_jim_fgets(char *s, int size, void *cookie)
753 {
754         /* not supported */
755         errno = ENOTSUP;
756         return NULL;
757 }
758
759 static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
760 {
761         if (argc != 2)
762                 return JIM_ERR;
763         int retcode;
764         const char *str = Jim_GetString(argv[1], NULL);
765
766         /* capture log output and return it */
767         Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
768         /* a garbage collect can happen, so we need a reference count to this object */
769         Jim_IncrRefCount(tclOutput);
770
771         log_add_callback(tcl_output, tclOutput);
772
773         retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
774
775         log_remove_callback(tcl_output, tclOutput);
776
777         /* We dump output into this local variable */
778         Jim_SetResult(interp, tclOutput);
779         Jim_DecrRefCount(interp, tclOutput);
780
781         return retcode;
782 }
783
784 static COMMAND_HELPER(command_help_find, struct command *head,
785                 struct command **out)
786 {
787         if (0 == CMD_ARGC)
788                 return ERROR_INVALID_ARGUMENTS;
789         *out = command_find(head, CMD_ARGV[0]);
790         if (NULL == *out)
791                 return ERROR_INVALID_ARGUMENTS;
792         if (--CMD_ARGC == 0)
793                 return ERROR_OK;
794         CMD_ARGV++;
795         return CALL_COMMAND_HANDLER(command_help_find, (*out)->children, out);
796 }
797
798 static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
799                 bool show_help);
800
801 static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n,
802                 bool show_help)
803 {
804         for (struct command *c = head; NULL != c; c = c->next)
805                 CALL_COMMAND_HANDLER(command_help_show, c, n, show_help);
806         return ERROR_OK;
807 }
808 static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
809                 bool show_help)
810 {
811         const char *usage = c->usage ? : "";
812         const char *help = "";
813         const char *sep = "";
814         if (show_help && c->help)
815         {
816                 help = c->help ? : "";
817                 sep = c->usage ? " | " : "";
818         }
819         command_run_linef(CMD_CTX, "cmd_help {%s} {%s%s%s} %d",
820                         command_name(c, ' '), usage, sep, help, n);
821
822         if (++n >= 2)
823                 return ERROR_OK;
824
825         return CALL_COMMAND_HANDLER(command_help_show_list,
826                         c->children, n, show_help);
827 }
828 COMMAND_HANDLER(handle_help_command)
829 {
830         struct command *c = CMD_CTX->commands;
831
832         if (0 == CMD_ARGC)
833                 return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, true);
834
835         int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c);
836         if (ERROR_OK != retval)
837                 return retval;
838
839         return CALL_COMMAND_HANDLER(command_help_show, c, 0, true);
840 }
841
842 COMMAND_HANDLER(handle_usage_command)
843 {
844         struct command *c = CMD_CTX->commands;
845
846         if (0 == CMD_ARGC)
847                 return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, false);
848
849         int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c);
850         if (ERROR_OK != retval)
851                 return retval;
852
853         return CALL_COMMAND_HANDLER(command_help_show, c, 0, false);
854 }
855
856 static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
857                 struct command *head, struct command **out)
858 {
859         if (0 == argc)
860                 return argc;
861         struct command *c = command_find(head, Jim_GetString(argv[0], NULL));
862         if (NULL == c)
863                 return argc;
864         *out = c;
865         return command_unknown_find(--argc, ++argv, (*out)->children, out);
866 }
867
868 static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
869 {
870         const char *cmd_name = Jim_GetString(argv[0], NULL);
871         script_debug(interp, cmd_name, argc - 1, argv + 1);
872
873         struct command_context *cmd_ctx = current_command_context();
874         struct command *c = cmd_ctx->commands;
875         int remaining = command_unknown_find(argc - 1, argv + 1, c, &c);
876         // if nothing could be consumed, then it's really an unknown command
877         if (remaining == argc - 1)
878         {
879                 const char *cmd = Jim_GetString(argv[1], NULL);
880                 LOG_ERROR("Unknown command:\n  %s", cmd);
881                 return JIM_OK;
882         }
883
884         bool found = true;
885         Jim_Obj *const *start;
886         unsigned count;
887         if (c->handler)
888         {
889                 // include the command name in the list
890                 count = remaining + 1;
891                 start = argv + (argc - remaining - 1);
892         }
893         else
894         {
895                 c = command_find(cmd_ctx->commands, "help");
896                 if (NULL == c)
897                 {
898                         LOG_ERROR("unknown command, but help is missing too");
899                         return JIM_ERR;
900                 }
901                 count = argc - remaining;
902                 start = argv;
903                 found = false;
904         }
905
906         unsigned nwords;
907         const char **words = script_command_args_alloc(count, start, &nwords);
908         if (NULL == words)
909                 return JIM_ERR;
910
911         int retval = run_command(cmd_ctx, c, words, nwords);
912
913         script_command_args_free(words, nwords);
914
915         if (!found && ERROR_OK == retval)
916                 retval = ERROR_FAIL;
917
918         return retval;
919 }
920
921 int help_add_command(struct command_context *cmd_ctx, struct command *parent,
922                 const char *cmd_name, const char *help_text, const char *usage)
923 {
924         struct command **head = command_list_for_parent(cmd_ctx, parent);
925         struct command *nc = command_find(*head, cmd_name);
926         if (NULL == nc)
927         {
928                 // add a new command with help text
929                 struct command_registration cr = {
930                                 .name = cmd_name,
931                                 .mode = COMMAND_ANY,
932                                 .help = help_text,
933                                 .usage = usage,
934                         };
935                 nc = register_command(cmd_ctx, parent, &cr);
936                 if (NULL == nc)
937                 {
938                         LOG_ERROR("failed to add '%s' help text", cmd_name);
939                         return ERROR_FAIL;
940                 }
941                 LOG_DEBUG("added '%s' help text", cmd_name);
942         }
943         else
944         {
945                 bool replaced = false;
946                 if (nc->help)
947                 {
948                         free((void *)nc->help);
949                         replaced = true;
950                 }
951                 nc->help = strdup(help_text);
952
953                 if (replaced)
954                         LOG_INFO("replaced existing '%s' help", cmd_name);
955                 else
956                         LOG_DEBUG("added '%s' help text", cmd_name);
957         }
958         return ERROR_OK;
959 }
960
961 COMMAND_HANDLER(handle_help_add_command)
962 {
963         if (CMD_ARGC < 2)
964         {
965                 LOG_ERROR("%s: insufficient arguments", CMD_NAME);
966                 return ERROR_INVALID_ARGUMENTS;
967         }
968
969         // save help text and remove it from argument list
970         const char *help_text = CMD_ARGV[--CMD_ARGC];
971         // likewise for the leaf command name
972         const char *cmd_name = CMD_ARGV[--CMD_ARGC];
973
974         struct command *c = NULL;
975         if (CMD_ARGC > 0)
976         {
977                 c = CMD_CTX->commands;
978                 int retval = CALL_COMMAND_HANDLER(command_help_find, c, &c);
979                 if (ERROR_OK != retval)
980                         return retval;
981         }
982         return help_add_command(CMD_CTX, c, cmd_name, help_text, NULL);
983 }
984
985 /* sleep command sleeps for <n> miliseconds
986  * this is useful in target startup scripts
987  */
988 COMMAND_HANDLER(handle_sleep_command)
989 {
990         bool busy = false;
991         if (CMD_ARGC == 2)
992         {
993                 if (strcmp(CMD_ARGV[1], "busy") == 0)
994                         busy = true;
995                 else
996                         return ERROR_COMMAND_SYNTAX_ERROR;
997         }
998         else if (CMD_ARGC < 1 || CMD_ARGC > 2)
999                 return ERROR_COMMAND_SYNTAX_ERROR;
1000
1001         unsigned long duration = 0;
1002         int retval = parse_ulong(CMD_ARGV[0], &duration);
1003         if (ERROR_OK != retval)
1004                 return retval;
1005
1006         if (!busy)
1007         {
1008                 long long then = timeval_ms();
1009                 while (timeval_ms() - then < (long long)duration)
1010                 {
1011                         target_call_timer_callbacks_now();
1012                         usleep(1000);
1013                 }
1014         }
1015         else
1016                 busy_sleep(duration);
1017
1018         return ERROR_OK;
1019 }
1020
1021 static const struct command_registration command_builtin_handlers[] = {
1022         {
1023                 .name = "add_help_text",
1024                 .handler = &handle_help_add_command,
1025                 .mode = COMMAND_ANY,
1026                 .help = "add new command help text",
1027                 .usage = "<command> [...] <help_text>]",
1028         },
1029         {
1030                 .name = "sleep",
1031                 .handler = &handle_sleep_command,
1032                 .mode = COMMAND_ANY,
1033                 .help = "sleep for n milliseconds.  "
1034                         "\"busy\" will busy wait",
1035                 .usage = "<n> [busy]",
1036         },
1037         {
1038                 .name = "help",
1039                 .handler = &handle_help_command,
1040                 .mode = COMMAND_ANY,
1041                 .help = "show built-in command help",
1042                 .usage = "[<command_name> ...]",
1043         },
1044         {
1045                 .name = "usage",
1046                 .handler = &handle_usage_command,
1047                 .mode = COMMAND_ANY,
1048                 .help = "show command usage",
1049                 .usage = "[<command_name> ...]",
1050         },
1051         COMMAND_REGISTRATION_DONE
1052 };
1053
1054 struct command_context* command_init(const char *startup_tcl)
1055 {
1056         struct command_context* context = malloc(sizeof(struct command_context));
1057         const char *HostOs;
1058
1059         context->mode = COMMAND_EXEC;
1060         context->commands = NULL;
1061         context->current_target = 0;
1062         context->output_handler = NULL;
1063         context->output_handler_priv = NULL;
1064
1065 #if !BUILD_ECOSBOARD
1066         Jim_InitEmbedded();
1067         /* Create an interpreter */
1068         interp = Jim_CreateInterp();
1069         /* Add all the Jim core commands */
1070         Jim_RegisterCoreCommands(interp);
1071 #endif
1072
1073 #if defined(_MSC_VER)
1074         /* WinXX - is generic, the forward
1075          * looking problem is this:
1076          *
1077          *   "win32" or "win64"
1078          *
1079          * "winxx" is generic.
1080          */
1081         HostOs = "winxx";
1082 #elif defined(__linux__)
1083         HostOs = "linux";
1084 #elif defined(__DARWIN__)
1085         HostOs = "darwin";
1086 #elif defined(__CYGWIN__)
1087         HostOs = "cygwin";
1088 #elif defined(__MINGW32__)
1089         HostOs = "mingw32";
1090 #elif defined(__ECOS)
1091         HostOs = "ecos";
1092 #else
1093 #warn unrecognized host OS...
1094         HostOs = "other";
1095 #endif
1096         Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
1097                         Jim_NewStringObj(interp, HostOs , strlen(HostOs)));
1098
1099         Jim_CreateCommand(interp, "unknown", &command_unknown, NULL, NULL);
1100         Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL);
1101         Jim_CreateCommand(interp, "echo", jim_echo, NULL, NULL);
1102         Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL);
1103
1104         /* Set Jim's STDIO */
1105         interp->cookie_stdin = interp;
1106         interp->cookie_stdout = interp;
1107         interp->cookie_stderr = interp;
1108         interp->cb_fwrite = openocd_jim_fwrite;
1109         interp->cb_fread = openocd_jim_fread ;
1110         interp->cb_vfprintf = openocd_jim_vfprintf;
1111         interp->cb_fflush = openocd_jim_fflush;
1112         interp->cb_fgets = openocd_jim_fgets;
1113
1114         register_commands(context, NULL, command_builtin_handlers);
1115
1116 #if !BUILD_ECOSBOARD
1117         Jim_EventLoopOnLoad(interp);
1118 #endif
1119         Jim_SetAssocData(interp, "context", NULL, context);
1120         if (Jim_Eval_Named(interp, startup_tcl, "embedded:startup.tcl",1) == JIM_ERR)
1121         {
1122                 LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD)");
1123                 Jim_PrintErrorMessage(interp);
1124                 exit(-1);
1125         }
1126         Jim_DeleteAssocData(interp, "context");
1127
1128         return context;
1129 }
1130
1131 int command_context_mode(struct command_context *cmd_ctx, enum command_mode mode)
1132 {
1133         if (!cmd_ctx)
1134                 return ERROR_INVALID_ARGUMENTS;
1135
1136         cmd_ctx->mode = mode;
1137         return ERROR_OK;
1138 }
1139
1140 void process_jim_events(void)
1141 {
1142 #if !BUILD_ECOSBOARD
1143         static int recursion = 0;
1144
1145         if (!recursion)
1146         {
1147                 recursion++;
1148                 Jim_ProcessEvents (interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
1149                 recursion--;
1150         }
1151 #endif
1152 }
1153
1154 void register_jim(struct command_context *cmd_ctx, const char *name,
1155                 Jim_CmdProc cmd, const char *help)
1156 {
1157         Jim_CreateCommand(interp, name, cmd, NULL, NULL);
1158
1159         Jim_Obj *cmd_list = Jim_NewListObj(interp, NULL, 0);
1160         Jim_ListAppendElement(interp, cmd_list,
1161                         Jim_NewStringObj(interp, name, -1));
1162
1163         help_add_command(cmd_ctx, NULL, name, help, NULL);
1164 }
1165
1166 #define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \
1167         int parse##name(const char *str, type *ul) \
1168         { \
1169                 if (!*str) \
1170                 { \
1171                         LOG_ERROR("Invalid command argument"); \
1172                         return ERROR_COMMAND_ARGUMENT_INVALID; \
1173                 } \
1174                 char *end; \
1175                 *ul = func(str, &end, 0); \
1176                 if (*end) \
1177                 { \
1178                         LOG_ERROR("Invalid command argument"); \
1179                         return ERROR_COMMAND_ARGUMENT_INVALID; \
1180                 } \
1181                 if ((max == *ul) && (ERANGE == errno)) \
1182                 { \
1183                         LOG_ERROR("Argument overflow"); \
1184                         return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
1185                 } \
1186                 if (min && (min == *ul) && (ERANGE == errno)) \
1187                 { \
1188                         LOG_ERROR("Argument underflow"); \
1189                         return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
1190                 } \
1191                 return ERROR_OK; \
1192         }
1193 DEFINE_PARSE_NUM_TYPE(_ulong, unsigned long , strtoul, 0, ULONG_MAX)
1194 DEFINE_PARSE_NUM_TYPE(_ullong, unsigned long long, strtoull, 0, ULLONG_MAX)
1195 DEFINE_PARSE_NUM_TYPE(_long, long , strtol, LONG_MIN, LONG_MAX)
1196 DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX)
1197
1198 #define DEFINE_PARSE_WRAPPER(name, type, min, max, functype, funcname) \
1199         int parse##name(const char *str, type *ul) \
1200         { \
1201                 functype n; \
1202                 int retval = parse##funcname(str, &n); \
1203                 if (ERROR_OK != retval) \
1204                         return retval; \
1205                 if (n > max) \
1206                         return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
1207                 if (min) \
1208                         return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
1209                 *ul = n; \
1210                 return ERROR_OK; \
1211         }
1212
1213 #define DEFINE_PARSE_ULONG(name, type, min, max) \
1214         DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long, _ulong)
1215 DEFINE_PARSE_ULONG(_uint, unsigned, 0, UINT_MAX)
1216 DEFINE_PARSE_ULONG(_u32, uint32_t, 0, UINT32_MAX)
1217 DEFINE_PARSE_ULONG(_u16, uint16_t, 0, UINT16_MAX)
1218 DEFINE_PARSE_ULONG(_u8, uint8_t, 0, UINT8_MAX)
1219
1220 #define DEFINE_PARSE_LONG(name, type, min, max) \
1221         DEFINE_PARSE_WRAPPER(name, type, min, max, long, _long)
1222 DEFINE_PARSE_LONG(_int, int, n < INT_MIN, INT_MAX)
1223 DEFINE_PARSE_LONG(_s32, int32_t, n < INT32_MIN, INT32_MAX)
1224 DEFINE_PARSE_LONG(_s16, int16_t, n < INT16_MIN, INT16_MAX)
1225 DEFINE_PARSE_LONG(_s8, int8_t, n < INT8_MIN, INT8_MAX)
1226
1227 static int command_parse_bool(const char *in, bool *out,
1228                 const char *on, const char *off)
1229 {
1230         if (strcasecmp(in, on) == 0)
1231                 *out = true;
1232         else if (strcasecmp(in, off) == 0)
1233                 *out = false;
1234         else
1235                 return ERROR_COMMAND_SYNTAX_ERROR;
1236         return  ERROR_OK;
1237 }
1238
1239 int command_parse_bool_arg(const char *in, bool *out)
1240 {
1241         if (command_parse_bool(in, out, "on", "off") == ERROR_OK)
1242                 return ERROR_OK;
1243         if (command_parse_bool(in, out, "enable", "disable") == ERROR_OK)
1244                 return ERROR_OK;
1245         if (command_parse_bool(in, out, "true", "false") == ERROR_OK)
1246                 return ERROR_OK;
1247         if (command_parse_bool(in, out, "yes", "no") == ERROR_OK)
1248                 return ERROR_OK;
1249         if (command_parse_bool(in, out, "1", "0") == ERROR_OK)
1250                 return ERROR_OK;
1251         return ERROR_INVALID_ARGUMENTS;
1252 }
1253
1254 COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
1255 {
1256         switch (CMD_ARGC) {
1257         case 1: {
1258                 const char *in = CMD_ARGV[0];
1259                 if (command_parse_bool_arg(in, out) != ERROR_OK)
1260                 {
1261                         LOG_ERROR("%s: argument '%s' is not valid", CMD_NAME, in);
1262                         return ERROR_INVALID_ARGUMENTS;
1263                 }
1264                 // fall through
1265         }
1266         case 0:
1267                 LOG_INFO("%s is %s", label, *out ? "enabled" : "disabled");
1268                 break;
1269         default:
1270                 return ERROR_INVALID_ARGUMENTS;
1271         }
1272         return ERROR_OK;
1273 }