command.c 38.2 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
6
 *   oyvind.harboe@zylin.com                                               *
7
 *                                                                         *
8
9
 *   Copyright (C) 2008, Duane Ellis                                       *
 *   openocd@duaneeellis.com                                               *
10
 *                                                                         *
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *   part of this file is taken from libcli (libcli.sourceforge.net)       *
 *   Copyright (C) David Parrish (david@dparrish.com)                      *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

33
34
35
36
37
#if !BUILD_ECOSBOARD
/* see Embedder-HOWTO.txt in Jim Tcl project hosted on BerliOS*/
#define JIM_EMBEDDED
#endif

38
// @todo the inclusion of target.h here is a layering violation
39
#include <jtag/jtag.h>
40
#include <target/target.h>
41
#include "command.h"
42
#include "configuration.h"
43
44
#include "log.h"
#include "time_support.h"
45
#include "jim-eventloop.h"
46

oharboe's avatar
oharboe committed
47

48
49
50
/* nice short description of source file */
#define __THIS__FILE__ "command.c"

oharboe's avatar
oharboe committed
51

52
static int run_command(struct command_context *context,
Zachary T Welch's avatar
Zachary T Welch committed
53
		struct command *c, const char *words[], unsigned num_words);
54

55
56
57
58
59
struct log_capture_state {
	Jim_Interp *interp;
	Jim_Obj *output;
};

60
61
static void tcl_output(void *privData, const char *file, unsigned line,
		const char *function, const char *string)
62
{
63
64
	struct log_capture_state *state = (struct log_capture_state *)privData;
	Jim_AppendString(state->interp, state->output, string, strlen(string));
65
66
}

67
static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
68
69
70
71
72
73
{
	/* capture log output and return it. A garbage collect can
	 * happen, so we need a reference count to this object */
	Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
	if (NULL == tclOutput)
		return NULL;
74
75
76
77
78
79

	struct log_capture_state *state = malloc(sizeof(*state));
	if (NULL == state)
		return NULL;

	state->interp = interp;
80
	Jim_IncrRefCount(tclOutput);
81
82
83
84
85
	state->output = tclOutput;

	log_add_callback(tcl_output, state);

	return state;
86
87
}

88
89
90
91
92
93
94
95
96
97
98
99
100
/* Classic openocd commands provide progress output which we
 * will capture and return as a Tcl return value.
 *
 * However, if a non-openocd command has been invoked, then it
 * makes sense to return the tcl return value from that command.
 *
 * The tcl return value is empty for openocd commands that provide
 * progress output.
 *
 * Therefore we set the tcl return value only if we actually
 * captured output.
 */
static void command_log_capture_finish(struct log_capture_state *state) 
101
{
102
103
104
105
106
	if (NULL == state)
		return;

	log_remove_callback(tcl_output, state);

107
108
109
110
111
112
113
114
115
116
117
	int length;
	Jim_GetString(state->output, &length);

	if (length > 0)
	{
		Jim_SetResult(state->interp, state->output);
	} else
	{
		/* No output captured, use tcl return value (which could
		 * be empty too). */
	}
118
119
120
	Jim_DecrRefCount(state->interp, state->output);

	free(state);
121
122
123
124
125
126
127
128
129
130
131
}

static int command_retval_set(Jim_Interp *interp, int retval)
{
	int *return_retval = Jim_GetAssocData(interp, "retval");
	if (return_retval != NULL)
		*return_retval = retval;

	return (retval == ERROR_OK) ? JIM_OK : JIM_ERR;
}

132
extern struct command_context *global_cmd_ctx;
133

134
135
/* dump a single line to the log for the command.
 * Do nothing in case we are not at debug level 3 */
136
137
void script_debug(Jim_Interp *interp, const char *name,
		unsigned argc, Jim_Obj *const *argv)
zwelch's avatar
zwelch committed
138
{
139
140
141
142
	if (debug_level < LOG_LVL_DEBUG)
		return;

	char * dbg = alloc_printf("command - %s", name);
143
144
	for (unsigned i = 0; i < argc; i++)
	{
zwelch's avatar
zwelch committed
145
146
		int len;
		const char *w = Jim_GetString(argv[i], &len);
147
148
149
		char * t = alloc_printf("%s %s", dbg, w);
		free (dbg);
		dbg = t;
zwelch's avatar
zwelch committed
150
	}
151
152
	LOG_DEBUG("%s", dbg);
	free(dbg);
zwelch's avatar
zwelch committed
153
154
}

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
static void script_command_args_free(const char **words, unsigned nwords)
{
	for (unsigned i = 0; i < nwords; i++)
		free((void *)words[i]);
	free(words);
}
static const char **script_command_args_alloc(
		unsigned argc, Jim_Obj *const *argv, unsigned *nwords)
{
	const char **words = malloc(argc * sizeof(char *));
	if (NULL == words)
		return NULL;

	unsigned i;
	for (i = 0; i < argc; i++)
	{
		int len;
		const char *w = Jim_GetString(argv[i], &len);
		words[i] = strdup(w);
		if (words[i] == NULL)
		{
			script_command_args_free(words, i);
			return NULL;
		}
	}
	*nwords = i;
	return words;
}

184
struct command_context *current_command_context(Jim_Interp *interp)
185
186
187
188
189
190
{
	/* grab the command context from the associated data */
	struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
	if (NULL == cmd_ctx)
	{
		/* Tcl can invoke commands directly instead of via command_run_line(). This would
191
192
193
194
195
		 * happen when the Jim Tcl interpreter is provided by eCos or if we are running
		 * commands in a startup script.
		 *
		 * A telnet or gdb server would provide a non-default command context to
		 * handle piping of error output, have a separate current target, etc.
196
197
198
199
200
201
		 */
		cmd_ctx = global_cmd_ctx;
	}
	return cmd_ctx;
}

202
203
static int script_command_run(Jim_Interp *interp,
		int argc, Jim_Obj *const *argv, struct command *c, bool capture)
204
205
{
	target_call_timer_callbacks_now();
206
207
	LOG_USER_N("%s", ""); /* Keep GDB connection alive*/

208
209
210
211
	unsigned nwords;
	const char **words = script_command_args_alloc(argc, argv, &nwords);
	if (NULL == words)
		return JIM_ERR;
212

213
	struct log_capture_state *state = NULL;
214
	if (capture)
215
		state = command_log_capture_start(interp);
216

217
	struct command_context *cmd_ctx = current_command_context(interp);
218
	int retval = run_command(cmd_ctx, c, (const char **)words, nwords);
ntfreak's avatar
ntfreak committed
219

220
	command_log_capture_finish(state);
221

222
	script_command_args_free(words, nwords);
223
	return command_retval_set(interp, retval);
224
}
225

226
227
228
229
230
231
232
233
234
235
static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	/* the private data is stashed in the interp structure */

	struct command *c = interp->cmdPrivData;
	assert(c);
	script_debug(interp, c->name, argc, argv);
	return script_command_run(interp, argc, argv, c, true);
}

236
237
238
239
240
241
static struct command *command_root(struct command *c)
{
	while (NULL != c->parent)
		c = c->parent;
	return c;
}
oharboe's avatar
oharboe committed
242

Zachary T Welch's avatar
Zachary T Welch committed
243
244
/**
 * Find a command by name from a list of commands.
245
246
 * @returns Returns the named command if it exists in the list.
 * Returns NULL otherwise.
Zachary T Welch's avatar
Zachary T Welch committed
247
 */
248
static struct command *command_find(struct command *head, const char *name)
249
{
250
	for (struct command *cc = head; cc; cc = cc->next)
Zachary T Welch's avatar
Zachary T Welch committed
251
252
253
254
255
256
	{
		if (strcmp(cc->name, name) == 0)
			return cc;
	}
	return NULL;
}
257
258
259
260
261
262
263
264
265
266
struct command *command_find_in_context(struct command_context *cmd_ctx,
		const char *name)
{
	return command_find(cmd_ctx->commands, name);
}
struct command *command_find_in_parent(struct command *parent,
		const char *name)
{
	return command_find(parent->children, name);
}
267

Zachary T Welch's avatar
Zachary T Welch committed
268
/**
269
270
271
272
 * Add the command into the linked list, sorted by name.
 * @param head Address to head of command list pointer, which may be
 * updated if @c c gets inserted at the beginning of the list.
 * @param c The command to add to the list pointed to by @c head.
Zachary T Welch's avatar
Zachary T Welch committed
273
 */
Zachary T Welch's avatar
Zachary T Welch committed
274
static void command_add_child(struct command **head, struct command *c)
Zachary T Welch's avatar
Zachary T Welch committed
275
276
277
278
279
280
281
{
	assert(head);
	if (NULL == *head)
	{
		*head = c;
		return;
	}
282
283
284
285
286
287
288
289
290
291
292

	while ((*head)->next && (strcmp(c->name, (*head)->name) > 0))
		head = &(*head)->next;

	if (strcmp(c->name, (*head)->name) > 0) {
		c->next = (*head)->next;
		(*head)->next = c;
	} else {
		c->next = *head;
		*head = c;
	}
Zachary T Welch's avatar
Zachary T Welch committed
293
294
}

295
296
static struct command **command_list_for_parent(
		struct command_context *cmd_ctx, struct command *parent)
Zachary T Welch's avatar
Zachary T Welch committed
297
{
298
299
	return parent ? &parent->children : &cmd_ctx->commands;
}
300

301
302
303
304
305
306
307
308
309
310
311
312
static void command_free(struct command *c)
{
	/// @todo if command has a handler, unregister its jim command!

	while (NULL != c->children)
	{
		struct command *tmp = c->children;
		c->children = tmp->next;
		command_free(tmp);
	}

	if (c->name)
313
		free((void *)c->name);
314
315
316
317
318
319
320
	if (c->help)
		free((void*)c->help);
	if (c->usage)
		free((void*)c->usage);
	free(c);
}

321
static struct command *command_new(struct command_context *cmd_ctx,
322
		struct command *parent, const struct command_registration *cr)
323
{
324
	assert(cr->name);
Zachary T Welch's avatar
Zachary T Welch committed
325

326
327
328
	struct command *c = calloc(1, sizeof(struct command));
	if (NULL == c)
		return NULL;
329

330
331
332
333
334
	c->name = strdup(cr->name);
	if (cr->help)
		c->help = strdup(cr->help);
	if (cr->usage)
		c->usage = strdup(cr->usage);
335
336
337
338

	if (!c->name || (cr->help && !c->help) || (cr->usage && !c->usage))
		goto command_new_error;

339
	c->parent = parent;
340
	c->handler = cr->handler;
341
342
	c->jim_handler = cr->jim_handler;
	c->jim_handler_data = cr->jim_handler_data;
343
	c->mode = cr->mode;
344

345
	command_add_child(command_list_for_parent(cmd_ctx, parent), c);
346

347
348
	return c;

349
350
351
command_new_error:
	command_free(c);
	return NULL;
352
353
}

Zachary T Welch's avatar
Zachary T Welch committed
354
355
static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv);

356
357
static int register_command_handler(struct command_context *cmd_ctx,
		struct command *c)
358
{
359
	Jim_Interp *interp = cmd_ctx->interp;
Zachary T Welch's avatar
Zachary T Welch committed
360
361
362
	const char *ocd_name = alloc_printf("ocd_%s", c->name);
	if (NULL == ocd_name)
		return JIM_ERR;
363

Zachary T Welch's avatar
Zachary T Welch committed
364
	LOG_DEBUG("registering '%s'...", ocd_name);
365

Zachary T Welch's avatar
Zachary T Welch committed
366
367
368
369
370
	Jim_CmdProc func = c->handler ? &script_command : &command_unknown;
	int retval = Jim_CreateCommand(interp, ocd_name, func, c, NULL);
	free((void *)ocd_name);
	if (JIM_OK != retval)
		return retval;
371
372

	/* we now need to add an overrideable proc */
373
374
	const char *override_name = alloc_printf(
			"proc %s {args} {eval ocd_bouncer %s $args}",
Zachary T Welch's avatar
Zachary T Welch committed
375
			c->name, c->name);
376
	if (NULL == override_name)
Zachary T Welch's avatar
Zachary T Welch committed
377
		return JIM_ERR;
378

379
	retval = Jim_Eval_Named(interp, override_name, 0, 0);
380
381
382
383
384
	free((void *)override_name);

	return retval;
}

385
struct command* register_command(struct command_context *context,
386
		struct command *parent, const struct command_registration *cr)
387
{
388
	if (!context || !cr->name)
389
390
		return NULL;

391
	const char *name = cr->name;
392
393
394
395
	struct command **head = command_list_for_parent(context, parent);
	struct command *c = command_find(*head, name);
	if (NULL != c)
	{
Spencer Oliver's avatar
Spencer Oliver committed
396
397
398
399
		/* TODO: originally we treated attempting to register a cmd twice as an error
		 * Sometimes we need this behaviour, such as with flash banks.
		 * http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */
		LOG_DEBUG("command '%s' is already registered in '%s' context",
400
401
402
403
				name, parent ? parent->name : "<global>");
		return c;
	}

404
	c = command_new(context, parent, cr);
405
406
	if (NULL == c)
		return NULL;
407

Zachary T Welch's avatar
Zachary T Welch committed
408
409
	int retval = ERROR_OK;
	if (NULL != cr->jim_handler && NULL == parent)
410
	{
411
		retval = Jim_CreateCommand(context->interp, cr->name,
Zachary T Welch's avatar
Zachary T Welch committed
412
				cr->jim_handler, cr->jim_handler_data, NULL);
413
	}
Zachary T Welch's avatar
Zachary T Welch committed
414
	else if (NULL != cr->handler || NULL != parent)
415
		retval = register_command_handler(context, command_root(c));
416

Zachary T Welch's avatar
Zachary T Welch committed
417
418
419
420
421
	if (ERROR_OK != retval)
	{
		unregister_command(context, parent, name);
		c = NULL;
	}
422
423
424
	return c;
}

425
426
427
int register_commands(struct command_context *cmd_ctx, struct command *parent,
		const struct command_registration *cmds)
{
428
	int retval = ERROR_OK;
429
	unsigned i;
430
	for (i = 0; cmds[i].name || cmds[i].chain; i++)
431
	{
432
		const struct command_registration *cr = cmds + i;
433

434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
		struct command *c = NULL;
		if (NULL != cr->name)
		{
			c = register_command(cmd_ctx, parent, cr);
			if (NULL == c)
			{
				retval = ERROR_FAIL;
				break;
			}
		}
		if (NULL != cr->chain)
		{
			struct command *p = c ? : parent;
			retval = register_commands(cmd_ctx, p, cr->chain);
			if (ERROR_OK != retval)
				break;
		}
	}
	if (ERROR_OK != retval)
	{
454
455
456
		for (unsigned j = 0; j < i; j++)
			unregister_command(cmd_ctx, parent, cmds[j].name);
	}
457
	return retval;
458
459
}

460
461
int unregister_all_commands(struct command_context *context,
		struct command *parent)
462
463
464
{
	if (context == NULL)
		return ERROR_OK;
465

466
467
	struct command **head = command_list_for_parent(context, parent);
	while (NULL != *head)
468
	{
469
470
471
		struct command *tmp = *head;
		*head = tmp->next;
		command_free(tmp);
472
	}
473

474
475
476
	return ERROR_OK;
}

477
478
int unregister_command(struct command_context *context,
		struct command *parent, const char *name)
479
480
481
{
	if ((!context) || (!name))
		return ERROR_INVALID_ARGUMENTS;
482

483
484
485
	struct command *p = NULL;
	struct command **head = command_list_for_parent(context, parent);
	for (struct command *c = *head; NULL != c; p = c, c = c->next)
486
	{
487
488
		if (strcmp(name, c->name) != 0)
			continue;
489

490
491
492
493
494
495
496
		if (p)
			p->next = c->next;
		else
			*head = c->next;

		command_free(c);
		return ERROR_OK;
497
	}
498

499
500
501
	return ERROR_OK;
}

502
503
504
505
506
507
508
509
void command_set_handler_data(struct command *c, void *p)
{
	if (NULL != c->handler || NULL != c->jim_handler)
		c->jim_handler_data = p;
	for (struct command *cc = c->children; NULL != cc; cc = cc->next)
		command_set_handler_data(cc, p);
}

510
void command_output_text(struct command_context *context, const char *data)
oharboe's avatar
oharboe committed
511
{
zwelch's avatar
zwelch committed
512
	if (context && context->output_handler && data) {
513
		context->output_handler(context, data);
oharboe's avatar
oharboe committed
514
515
516
	}
}

517
void command_print_sameline(struct command_context *context, const char *format, ...)
518
{
519
	char *string;
520

521
522
523
	va_list ap;
	va_start(ap, format);

oharboe's avatar
oharboe committed
524
	string = alloc_vprintf(format, ap);
525
	if (string != NULL)
526
	{
527
528
		/* we want this collected in the log + we also want to pick it up as a tcl return
		 * value.
529
		 *
530
531
532
		 * The latter bit isn't precisely neat, but will do for now.
		 */
		LOG_USER_N("%s", string);
533
534
		/* We already printed it above */
		/* command_output_text(context, string); */
535
		free(string);
536
537
	}

538
539
	va_end(ap);
}
540

541
void command_print(struct command_context *context, const char *format, ...)
542
{
543
544
	char *string;

545
546
	va_list ap;
	va_start(ap, format);
547

oharboe's avatar
oharboe committed
548
	string = alloc_vprintf(format, ap);
549
550
	if (string != NULL)
	{
oharboe's avatar
oharboe committed
551
		strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one char longer */
552
553
		/* we want this collected in the log + we also want to pick it up as a tcl return
		 * value.
554
		 *
555
556
557
		 * The latter bit isn't precisely neat, but will do for now.
		 */
		LOG_USER_N("%s", string);
558
559
		/* We already printed it above */
		/* command_output_text(context, string); */
560
561
562
		free(string);
	}

563
	va_end(ap);
564
565
}

Zachary T Welch's avatar
Zachary T Welch committed
566
static char *__command_name(struct command *c, char delim, unsigned extra)
Zachary T Welch's avatar
Zachary T Welch committed
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
{
	char *name;
	unsigned len = strlen(c->name);
	if (NULL == c->parent) {
		// allocate enough for the name, child names, and '\0'
		name = malloc(len + extra + 1);
		strcpy(name, c->name);
	} else {
		// parent's extra must include both the space and name
		name = __command_name(c->parent, delim, 1 + len + extra);
		char dstr[2] = { delim, 0 };
		strcat(name, dstr);
		strcat(name, c->name);
	}
	return name;
}
Zachary T Welch's avatar
Zachary T Welch committed
583
char *command_name(struct command *c, char delim)
Zachary T Welch's avatar
Zachary T Welch committed
584
585
586
587
{
	return __command_name(c, delim, 0);
}

588
589
590
591
592
static bool command_can_run(struct command_context *cmd_ctx, struct command *c)
{
	return c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode;
}

593
static int run_command(struct command_context *context,
Zachary T Welch's avatar
Zachary T Welch committed
594
		struct command *c, const char *words[], unsigned num_words)
595
{
596
	if (!command_can_run(context, c))
597
	{
598
599
600
601
602
603
604
605
606
607
		/* Many commands may be run only before/after 'init' */
		const char *when;
		switch (c->mode) {
		case COMMAND_CONFIG: when = "before"; break;
		case COMMAND_EXEC: when = "after"; break;
		// handle the impossible with humor; it guarantees a bug report!
		default: when = "if Cthulhu is summoned by"; break;
		}
		LOG_ERROR("The '%s' command must be used %s 'init'.",
				c->name, when);
608
		return ERROR_FAIL;
609
	}
610

611
612
	struct command_invocation cmd = {
			.ctx = context,
613
			.current = c,
614
			.name = c->name,
615
616
			.argc = num_words - 1,
			.argv = words + 1,
617
618
		};
	int retval = c->handler(&cmd);
619
620
	if (retval == ERROR_COMMAND_SYNTAX_ERROR)
	{
621
		/* Print help for command */
Zachary T Welch's avatar
Zachary T Welch committed
622
623
		char *full_name = command_name(c, ' ');
		if (NULL != full_name) {
624
			command_run_linef(context, "usage %s", full_name);
Zachary T Welch's avatar
Zachary T Welch committed
625
626
627
			free(full_name);
		} else
			retval = -ENOMEM;
628
629
630
631
632
633
634
635
636
637
	}
	else if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
	{
		/* just fall through for a shutdown request */
	}
	else if (retval != ERROR_OK)
	{
		/* we do not print out an error message because the command *should*
		 * have printed out an error
		 */
638
		LOG_DEBUG("Command failed with error code %d", retval);
639
	}
640
641

	return retval;
642
643
}

644
int command_run_line(struct command_context *context, char *line)
645
{
646
647
648
649
650
	/* all the parent commands have been registered with the interpreter
	 * so, can just evaluate the line as a script and check for
	 * results
	 */
	/* run the line thru a script engine */
zwelch's avatar
zwelch committed
651
	int retval = ERROR_FAIL;
652
	int retcode;
653
654
655
656
657
	/* Beware! This code needs to be reentrant. It is also possible
	 * for OpenOCD commands to be invoked directly from Tcl. This would
	 * happen when the Jim Tcl interpreter is provided by eCos for
	 * instance.
	 */
658
	Jim_Interp *interp = context->interp;
659
	Jim_DeleteAssocData(interp, "context");
660
	retcode = Jim_SetAssocData(interp, "context", NULL, context);
661
662
663
664
665
666
667
	if (retcode == JIM_OK)
	{
		/* associated the return value */
		Jim_DeleteAssocData(interp, "retval");
		retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
		if (retcode == JIM_OK)
		{
668
			retcode = Jim_Eval_Named(interp, line, 0, 0);
669

670
			Jim_DeleteAssocData(interp, "retval");
671
		}
672
673
		Jim_DeleteAssocData(interp, "context");
	}
674
	if (retcode == JIM_ERR) {
zwelch's avatar
zwelch committed
675
		if (retval != ERROR_COMMAND_CLOSE_CONNECTION)
676
677
		{
			/* We do not print the connection closed error message */
Øyvind Harboe's avatar
Øyvind Harboe committed
678
			Jim_MakeErrorMessage(interp);
Eric Wetzel's avatar
Eric Wetzel committed
679
			LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
680
		}
zwelch's avatar
zwelch committed
681
		if (retval == ERROR_OK)
682
683
		{
			/* It wasn't a low level OpenOCD command that failed */
684
			return ERROR_FAIL;
685
686
		}
		return retval;
687
688
689
690
691
692
693
694
	} else if (retcode == JIM_EXIT) {
		/* ignore. */
		/* exit(Jim_GetExitCode(interp)); */
	} else {
		const char *result;
		int reslen;

		result = Jim_GetString(Jim_GetResult(interp), &reslen);
zwelch's avatar
zwelch committed
695
		if (reslen > 0)
696
		{
oharboe's avatar
oharboe committed
697
			int i;
zwelch's avatar
zwelch committed
698
			char buff[256 + 1];
oharboe's avatar
oharboe committed
699
700
701
702
703
704
			for (i = 0; i < reslen; i += 256)
			{
				int chunk;
				chunk = reslen - i;
				if (chunk > 256)
					chunk = 256;
zwelch's avatar
zwelch committed
705
				strncpy(buff, result + i, chunk);
oharboe's avatar
oharboe committed
706
707
708
				buff[chunk] = 0;
				LOG_USER_N("%s", buff);
			}
Eric Wetzel's avatar
Eric Wetzel committed
709
			LOG_USER_N("\n");
710
		}
zwelch's avatar
zwelch committed
711
		retval = ERROR_OK;
ntfreak's avatar
ntfreak committed
712
	}
713
714
715
	return retval;
}

716
int command_run_linef(struct command_context *context, const char *format, ...)
oharboe's avatar
oharboe committed
717
{
zwelch's avatar
zwelch committed
718
	int retval = ERROR_FAIL;
oharboe's avatar
oharboe committed
719
720
721
722
	char *string;
	va_list ap;
	va_start(ap, format);
	string = alloc_vprintf(format, ap);
zwelch's avatar
zwelch committed
723
	if (string != NULL)
oharboe's avatar
oharboe committed
724
	{
zwelch's avatar
zwelch committed
725
		retval = command_run_line(context, string);
oharboe's avatar
oharboe committed
726
727
728
729
730
	}
	va_end(ap);
	return retval;
}

731
void command_set_output_handler(struct command_context* context,
Zachary T Welch's avatar
Zachary T Welch committed
732
		command_output_handler_t output_handler, void *priv)
733
734
735
736
737
{
	context->output_handler = output_handler;
	context->output_handler_priv = priv;
}

738
struct command_context* copy_command_context(struct command_context* context)
739
{
740
	struct command_context* copy_context = malloc(sizeof(struct command_context));
741
742

	*copy_context = *context;
743

744
745
746
	return copy_context;
}

747
void command_done(struct command_context *cmd_ctx)
748
{
749
750
	if (NULL == cmd_ctx)
		return;
751

752
	free(cmd_ctx);
753
754
}

755
756
757
758
759
760
761
762
763
764
765
/* find full path to file */
static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 2)
		return JIM_ERR;
	const char *file = Jim_GetString(argv[1], NULL);
	char *full_path = find_file(file);
	if (full_path == NULL)
		return JIM_ERR;
	Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
	free(full_path);
766

767
768
769
770
	Jim_SetResult(interp, result);
	return JIM_OK;
}

Antonio Borneo's avatar
Antonio Borneo committed
771
COMMAND_HANDLER(jim_echo)
772
{
Antonio Borneo's avatar
Antonio Borneo committed
773
	if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n"))
774
	{
Antonio Borneo's avatar
Antonio Borneo committed
775
		LOG_USER_N("%s", CMD_ARGV[1]);
776
777
		return JIM_OK;
	}
Antonio Borneo's avatar
Antonio Borneo committed
778
	if (CMD_ARGC != 1)
779
		return JIM_ERR;
Antonio Borneo's avatar
Antonio Borneo committed
780
	LOG_USER("%s", CMD_ARGV[0]);
781
782
783
	return JIM_OK;
}

784
785
786
/* Capture progress output and return as tcl return value. If the
 * progress output was empty, return tcl return value.
 */
787
788
789
790
791
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 2)
		return JIM_ERR;

792
	struct log_capture_state *state = command_log_capture_start(interp);
793

794
795
796
797
798
799
800
801
802
803
	/* disable polling during capture. This avoids capturing output
	 * from polling.
	 *
	 * This is necessary in order to avoid accidentially getting a non-empty
	 * string for tcl fn's.
	 */
	bool save_poll = jtag_poll_get_enabled();

	jtag_poll_set_enabled(false);

804
805
	const char *str = Jim_GetString(argv[1], NULL);
	int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__);
806

807
808
	jtag_poll_set_enabled(save_poll);

809
	command_log_capture_finish(state);
810
811
812
813

	return retcode;
}

Zachary T Welch's avatar
Zachary T Welch committed
814
815
816
817
818
819
static COMMAND_HELPER(command_help_find, struct command *head,
		struct command **out)
{
	if (0 == CMD_ARGC)
		return ERROR_INVALID_ARGUMENTS;
	*out = command_find(head, CMD_ARGV[0]);
820
821
	if (NULL == *out && strncmp(CMD_ARGV[0], "ocd_", 4) == 0)
		*out = command_find(head, CMD_ARGV[0] + 4);
Zachary T Welch's avatar
Zachary T Welch committed
822
823
824
825
826
827
828
829
	if (NULL == *out)
		return ERROR_INVALID_ARGUMENTS;
	if (--CMD_ARGC == 0)
		return ERROR_OK;
	CMD_ARGV++;
	return CALL_COMMAND_HANDLER(command_help_find, (*out)->children, out);
}

830
static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
831
		bool show_help, const char *match);
Zachary T Welch's avatar
Zachary T Welch committed
832

833
static COMMAND_HELPER(command_help_show_list, struct command *head, unsigned n,
834
		bool show_help, const char *match)
Zachary T Welch's avatar
Zachary T Welch committed
835
836
{
	for (struct command *c = head; NULL != c; c = c->next)
837
		CALL_COMMAND_HANDLER(command_help_show, c, n, show_help, match);
Zachary T Welch's avatar
Zachary T Welch committed
838
839
	return ERROR_OK;
}
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

#define HELP_LINE_WIDTH(_n) (int)(76 - (2 * _n))

static void command_help_show_indent(unsigned n)
{
	for (unsigned i = 0; i < n; i++)
		LOG_USER_N("  ");
}
static void command_help_show_wrap(const char *str, unsigned n, unsigned n2)
{
	const char *cp = str, *last = str;
	while (*cp)
	{
		const char *next = last;
		do {
			cp = next;
			do {
				next++;
			} while (*next != ' ' && *next != '\t' && *next != '\0');
		} while ((next - last < HELP_LINE_WIDTH(n)) && *next != '\0');
		if (next - last < HELP_LINE_WIDTH(n))
			cp = next;
		command_help_show_indent(n);
Eric Wetzel's avatar
Eric Wetzel committed
863
		LOG_USER("%.*s", (int)(cp - last), last);
864
865
866
867
		last = cp + 1;
		n = n2;
	}
}
868
static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
869
		bool show_help, const char *match)
Zachary T Welch's avatar
Zachary T Welch committed
870
{
871
872
873
874
	char *cmd_name = command_name(c, ' ');
	if (NULL == cmd_name)
		return -ENOMEM;

875
876
877
878
879
	/* If the match string occurs anywhere, we print out
	 * stuff for this command. */
	bool is_match = (strstr(cmd_name, match) != NULL) ||
	((c->usage != NULL) && (strstr(c->usage, match) != NULL)) ||
	((c->help != NULL) && (strstr(c->help, match) != NULL));
880

881
882
883
884
885
	if (is_match)
	{
		command_help_show_indent(n);
		LOG_USER_N("%s", cmd_name);
	}
886
887
	free(cmd_name);

888
889
890
891
892
893
894
895
	if (is_match)
	{
		if (c->usage) {
			LOG_USER_N(" ");
			command_help_show_wrap(c->usage, 0, n + 5);
		}
		else
			LOG_USER_N("\n");
896
	}
897

898
	if (is_match && show_help)
899
	{
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
		char *msg;

		/* Normal commands are runtime-only; highlight exceptions */
		if (c->mode != COMMAND_EXEC) {
			const char *stage_msg = "";

			switch (c->mode) {
			case COMMAND_CONFIG:
				stage_msg = " (configuration command)";
				break;
			case COMMAND_ANY:
				stage_msg = " (command valid any time)";
				break;
			default:
				stage_msg = " (?mode error?)";
				break;
			}
			msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
		} else
			msg = alloc_printf("%s", c->help ? : "");

921
922
923
924
925
926
927
928
		if (NULL != msg)
		{
			command_help_show_wrap(msg, n + 3, n + 3);
			free(msg);
		} else
			return -ENOMEM;
	}

Zachary T Welch's avatar
Zachary T Welch committed
929
930
931
	if (++n >= 2)
		return ERROR_OK;

932
	return CALL_COMMAND_HANDLER(command_help_show_list,
933
			c->children, n, show_help, match);
Zachary T Welch's avatar
Zachary T Welch committed
934
935
936
}
COMMAND_HANDLER(handle_help_command)
{
937
	bool full = strcmp(CMD_NAME, "help") == 0;
938
	int retval;
939
	struct command *c = CMD_CTX->commands;
940
	char *match = NULL;
941

942
943
	if (CMD_ARGC == 0)
		match = "";
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
	else if (CMD_ARGC >= 1) {
		unsigned i;

		for (i = 0; i < CMD_ARGC; ++i) {
			if (NULL != match) {
				char *prev = match;

				match = alloc_printf("%s %s", match,
						CMD_ARGV[i]);
				free(prev);
				if (NULL == match) {
					LOG_ERROR("unable to build "
							"search string");
					return -ENOMEM;
				}
			} else {
				match = alloc_printf("%s", CMD_ARGV[i]);
				if (NULL == match) {
					LOG_ERROR("unable to build "
							"search string");
					return -ENOMEM;
				}
			}
		}
	} else
969
		return ERROR_COMMAND_SYNTAX_ERROR;
970
971
972
973
974
975
976

	retval = CALL_COMMAND_HANDLER(command_help_show_list,
			c, 0, full, match);

	if (CMD_ARGC >= 1)
		free(match);
	return retval;
Zachary T Welch's avatar
Zachary T Welch committed
977
978
}

979
static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
980
		struct command *head, struct command **out, bool top_level)
981
982
983
{
	if (0 == argc)
		return argc;
984
985
986
987
	const char *cmd_name = Jim_GetString(argv[0], NULL);
	struct command *c = command_find(head, cmd_name);
	if (NULL == c && top_level && strncmp(cmd_name, "ocd_", 4) == 0)
		c = command_find(head, cmd_name + 4);
988
989
990
	if (NULL == c)
		return argc;
	*out = c;
991
	return command_unknown_find(--argc, ++argv, (*out)->children, out, false);
992
993
}

994

995
996
997
static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	const char *cmd_name = Jim_GetString(argv[0], NULL);
Zachary T Welch's avatar
Zachary T Welch committed
998
999
1000
	if (strcmp(cmd_name, "unknown") == 0)
	{
		if (argc == 1)
For faster browsing, not all history is shown. View entire blame