command.c 39.8 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
 *   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     *
25
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
26
 ***************************************************************************/
27

28 29 30 31
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

Spencer Oliver's avatar
Spencer Oliver committed
32
/* see Embedded-HOWTO.txt in Jim Tcl project hosted on BerliOS*/
33 34
#define JIM_EMBEDDED

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 41
#include "log.h"
#include "time_support.h"
42
#include "jim-eventloop.h"
43

44 45 46
/* nice short description of source file */
#define __THIS__FILE__ "command.c"

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

50 51 52 53 54
struct log_capture_state {
	Jim_Interp *interp;
	Jim_Obj *output;
};

55
static void tcl_output(void *privData, const char *file, unsigned line,
56
	const char *function, const char *string)
57
{
Andreas Fritiofson's avatar
Andreas Fritiofson committed
58
	struct log_capture_state *state = privData;
59
	Jim_AppendString(state->interp, state->output, string, strlen(string));
60 61
}

62
static struct log_capture_state *command_log_capture_start(Jim_Interp *interp)
63 64 65 66 67 68
{
	/* 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;
69 70 71 72 73 74

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

	state->interp = interp;
75
	Jim_IncrRefCount(tclOutput);
76 77 78 79 80
	state->output = tclOutput;

	log_add_callback(tcl_output, state);

	return state;
81 82
}

83 84 85 86 87 88 89 90 91 92 93 94
/* 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.
 */
Spencer Oliver's avatar
Spencer Oliver committed
95
static void command_log_capture_finish(struct log_capture_state *state)
96
{
97 98 99 100 101
	if (NULL == state)
		return;

	log_remove_callback(tcl_output, state);

102 103 104 105 106
	int length;
	Jim_GetString(state->output, &length);

	if (length > 0)
		Jim_SetResult(state->interp, state->output);
107
	else {
108 109 110
		/* No output captured, use tcl return value (which could
		 * be empty too). */
	}
111 112 113
	Jim_DecrRefCount(state->interp, state->output);

	free(state);
114 115 116 117 118
}

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

122
	return (retval == ERROR_OK) ? JIM_OK : retval;
123 124
}

125
extern struct command_context *global_cmd_ctx;
126

127 128
/* dump a single line to the log for the command.
 * Do nothing in case we are not at debug level 3 */
129
void script_debug(Jim_Interp *interp, const char *name,
130
	unsigned argc, Jim_Obj * const *argv)
zwelch's avatar
zwelch committed
131
{
132 133 134
	if (debug_level < LOG_LVL_DEBUG)
		return;

135 136
	char *dbg = alloc_printf("command - %s", name);
	for (unsigned i = 0; i < argc; i++) {
zwelch's avatar
zwelch committed
137 138
		int len;
		const char *w = Jim_GetString(argv[i], &len);
139 140
		char *t = alloc_printf("%s %s", dbg, w);
		free(dbg);
141
		dbg = t;
zwelch's avatar
zwelch committed
142
	}
143 144
	LOG_DEBUG("%s", dbg);
	free(dbg);
zwelch's avatar
zwelch committed
145 146
}

147
static void script_command_args_free(char **words, unsigned nwords)
148 149
{
	for (unsigned i = 0; i < nwords; i++)
150
		free(words[i]);
151 152
	free(words);
}
Spencer Oliver's avatar
Spencer Oliver committed
153

154
static char **script_command_args_alloc(
155
	unsigned argc, Jim_Obj * const *argv, unsigned *nwords)
156
{
157
	char **words = malloc(argc * sizeof(char *));
158 159 160 161
	if (NULL == words)
		return NULL;

	unsigned i;
162
	for (i = 0; i < argc; i++) {
163 164 165
		int len;
		const char *w = Jim_GetString(argv[i], &len);
		words[i] = strdup(w);
166
		if (words[i] == NULL) {
167 168 169 170 171 172 173 174
			script_command_args_free(words, i);
			return NULL;
		}
	}
	*nwords = i;
	return words;
}

175
struct command_context *current_command_context(Jim_Interp *interp)
176 177 178
{
	/* grab the command context from the associated data */
	struct command_context *cmd_ctx = Jim_GetAssocData(interp, "context");
179
	if (NULL == cmd_ctx) {
180
		/* Tcl can invoke commands directly instead of via command_run_line(). This would
181 182 183 184 185
		 * 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.
186 187 188 189 190 191
		 */
		cmd_ctx = global_cmd_ctx;
	}
	return cmd_ctx;
}

192
static int script_command_run(Jim_Interp *interp,
193
	int argc, Jim_Obj * const *argv, struct command *c, bool capture)
194 195
{
	target_call_timer_callbacks_now();
196
	LOG_USER_N("%s", "");	/* Keep GDB connection alive*/
197

198
	unsigned nwords;
199
	char **words = script_command_args_alloc(argc, argv, &nwords);
200 201
	if (NULL == words)
		return JIM_ERR;
202

203
	struct log_capture_state *state = NULL;
204
	if (capture)
205
		state = command_log_capture_start(interp);
206

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

210
	command_log_capture_finish(state);
211

212
	script_command_args_free(words, nwords);
213
	return command_retval_set(interp, retval);
214
}
215

216 217 218 219 220 221 222 223 224 225
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);
}

226 227 228 229 230 231
static struct command *command_root(struct command *c)
{
	while (NULL != c->parent)
		c = c->parent;
	return c;
}
oharboe's avatar
oharboe committed
232

Zachary T Welch's avatar
Zachary T Welch committed
233 234
/**
 * Find a command by name from a list of commands.
235 236
 * @returns Returns the named command if it exists in the list.
 * Returns NULL otherwise.
Zachary T Welch's avatar
Zachary T Welch committed
237
 */
238
static struct command *command_find(struct command *head, const char *name)
239
{
240
	for (struct command *cc = head; cc; cc = cc->next) {
Zachary T Welch's avatar
Zachary T Welch committed
241 242 243 244 245
		if (strcmp(cc->name, name) == 0)
			return cc;
	}
	return NULL;
}
Spencer Oliver's avatar
Spencer Oliver committed
246

247
struct command *command_find_in_context(struct command_context *cmd_ctx,
248
	const char *name)
249 250 251 252
{
	return command_find(cmd_ctx->commands, name);
}
struct command *command_find_in_parent(struct command *parent,
253
	const char *name)
254 255 256
{
	return command_find(parent->children, name);
}
257

Zachary T Welch's avatar
Zachary T Welch committed
258
/**
259 260 261 262
 * 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
263
 */
Zachary T Welch's avatar
Zachary T Welch committed
264
static void command_add_child(struct command **head, struct command *c)
Zachary T Welch's avatar
Zachary T Welch committed
265 266
{
	assert(head);
267
	if (NULL == *head) {
Zachary T Welch's avatar
Zachary T Welch committed
268 269 270
		*head = c;
		return;
	}
271 272 273 274 275 276 277 278 279 280 281

	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
282 283
}

284
static struct command **command_list_for_parent(
285
	struct command_context *cmd_ctx, struct command *parent)
Zachary T Welch's avatar
Zachary T Welch committed
286
{
287 288
	return parent ? &parent->children : &cmd_ctx->commands;
}
289

290 291
static void command_free(struct command *c)
{
292
	/** @todo if command has a handler, unregister its jim command! */
293

294
	while (NULL != c->children) {
295 296 297 298 299
		struct command *tmp = c->children;
		c->children = tmp->next;
		command_free(tmp);
	}

300 301 302
	free(c->name);
	free(c->help);
	free(c->usage);
303 304 305
	free(c);
}

306
static struct command *command_new(struct command_context *cmd_ctx,
307
	struct command *parent, const struct command_registration *cr)
308
{
309
	assert(cr->name);
Zachary T Welch's avatar
Zachary T Welch committed
310

311
	/*
312 313 314 315 316
	 * If it is a non-jim command with no .usage specified,
	 * log an error.
	 *
	 * strlen(.usage) == 0 means that the command takes no
	 * arguments.
317
	*/
318
	if ((cr->jim_handler == NULL) && (cr->usage == NULL)) {
319 320 321 322 323 324 325
		LOG_DEBUG("BUG: command '%s%s%s' does not have the "
			"'.usage' field filled out",
			parent && parent->name ? parent->name : "",
			parent && parent->name ? " " : "",
			cr->name);
	}

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
static int register_command_handler(struct command_context *cmd_ctx,
357
	struct command *c)
358
{
359
	Jim_Interp *interp = cmd_ctx->interp;
360
	char *ocd_name = alloc_printf("ocd_%s", c->name);
Zachary T Welch's avatar
Zachary T Welch committed
361 362
	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

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

	/* we now need to add an overrideable proc */
373
	char *override_name = alloc_printf(
374
			"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
	free(override_name);
381 382 383 384

	return retval;
}

385 386
struct command *register_command(struct command_context *context,
	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
	struct command **head = command_list_for_parent(context, parent);
	struct command *c = command_find(*head, name);
394
	if (NULL != c) {
Spencer Oliver's avatar
Spencer Oliver committed
395 396 397 398
		/* 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",
399
			name, parent ? parent->name : "<global>");
400 401 402
		return c;
	}

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

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

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

421
int register_commands(struct command_context *cmd_ctx, struct command *parent,
422
	const struct command_registration *cmds)
423
{
424
	int retval = ERROR_OK;
425
	unsigned i;
426
	for (i = 0; cmds[i].name || cmds[i].chain; i++) {
427
		const struct command_registration *cr = cmds + i;
428

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

451
int unregister_all_commands(struct command_context *context,
452
	struct command *parent)
453 454 455
{
	if (context == NULL)
		return ERROR_OK;
456

457
	struct command **head = command_list_for_parent(context, parent);
458
	while (NULL != *head) {
459 460 461
		struct command *tmp = *head;
		*head = tmp->next;
		command_free(tmp);
462
	}
463

464 465 466
	return ERROR_OK;
}

467
int unregister_command(struct command_context *context,
468
	struct command *parent, const char *name)
469 470
{
	if ((!context) || (!name))
471
		return ERROR_COMMAND_SYNTAX_ERROR;
472

473 474
	struct command *p = NULL;
	struct command **head = command_list_for_parent(context, parent);
475
	for (struct command *c = *head; NULL != c; p = c, c = c->next) {
476 477
		if (strcmp(name, c->name) != 0)
			continue;
478

479 480 481 482 483 484 485
		if (p)
			p->next = c->next;
		else
			*head = c->next;

		command_free(c);
		return ERROR_OK;
486
	}
487

488 489 490
	return ERROR_OK;
}

491 492 493 494 495 496 497 498
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);
}

499
void command_output_text(struct command_context *context, const char *data)
oharboe's avatar
oharboe committed
500
{
501
	if (context && context->output_handler && data)
502
		context->output_handler(context, data);
oharboe's avatar
oharboe committed
503 504
}

505
void command_print_sameline(struct command_context *context, const char *format, ...)
506
{
507
	char *string;
508

509 510 511
	va_list ap;
	va_start(ap, format);

oharboe's avatar
oharboe committed
512
	string = alloc_vprintf(format, ap);
513
	if (string != NULL) {
514 515
		/* we want this collected in the log + we also want to pick it up as a tcl return
		 * value.
516
		 *
517 518 519
		 * The latter bit isn't precisely neat, but will do for now.
		 */
		LOG_USER_N("%s", string);
520 521
		/* We already printed it above
		 * command_output_text(context, string); */
522
		free(string);
523 524
	}

525 526
	va_end(ap);
}
527

528
void command_print(struct command_context *context, const char *format, ...)
529
{
530 531
	char *string;

532 533
	va_list ap;
	va_start(ap, format);
534

oharboe's avatar
oharboe committed
535
	string = alloc_vprintf(format, ap);
536 537 538
	if (string != NULL) {
		strcat(string, "\n");	/* alloc_vprintf guaranteed the buffer to be at least one
					 *char longer */
539 540
		/* we want this collected in the log + we also want to pick it up as a tcl return
		 * value.
541
		 *
542 543 544
		 * The latter bit isn't precisely neat, but will do for now.
		 */
		LOG_USER_N("%s", string);
545 546
		/* We already printed it above
		 * command_output_text(context, string); */
547 548 549
		free(string);
	}

550
	va_end(ap);
551 552
}

Zachary T Welch's avatar
Zachary T Welch committed
553
static char *__command_name(struct command *c, char delim, unsigned extra)
Zachary T Welch's avatar
Zachary T Welch committed
554 555 556 557
{
	char *name;
	unsigned len = strlen(c->name);
	if (NULL == c->parent) {
558
		/* allocate enough for the name, child names, and '\0' */
Zachary T Welch's avatar
Zachary T Welch committed
559
		name = malloc(len + extra + 1);
560 561 562 563
		if (!name) {
			LOG_ERROR("Out of memory");
			return NULL;
		}
Zachary T Welch's avatar
Zachary T Welch committed
564 565
		strcpy(name, c->name);
	} else {
566
		/* parent's extra must include both the space and name */
Zachary T Welch's avatar
Zachary T Welch committed
567 568 569 570 571 572 573
		name = __command_name(c->parent, delim, 1 + len + extra);
		char dstr[2] = { delim, 0 };
		strcat(name, dstr);
		strcat(name, c->name);
	}
	return name;
}
Spencer Oliver's avatar
Spencer Oliver committed
574

Zachary T Welch's avatar
Zachary T Welch committed
575
char *command_name(struct command *c, char delim)
Zachary T Welch's avatar
Zachary T Welch committed
576 577 578 579
{
	return __command_name(c, delim, 0);
}

580 581
static bool command_can_run(struct command_context *cmd_ctx, struct command *c)
{
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
	if (c->mode == COMMAND_ANY || c->mode == cmd_ctx->mode)
		return true;

	/* 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;
	}
	char *full_name = command_name(c, ' ');
	LOG_ERROR("The '%s' command must be used %s 'init'.",
			full_name ? full_name : c->name, when);
	free(full_name);
	return false;
604 605
}

606
static int run_command(struct command_context *context,
607
	struct command *c, const char *words[], unsigned num_words)
608
{
609
	if (!command_can_run(context, c))
610
		return ERROR_FAIL;
611

612
	struct command_invocation cmd = {
613 614 615 616 617 618
		.ctx = context,
		.current = c,
		.name = c->name,
		.argc = num_words - 1,
		.argv = words + 1,
	};
619 620 621 622 623 624 625 626 627 628 629 630
	/* Black magic of overridden current target:
	 * If the command we are going to handle has a target prefix,
	 * override the current target temporarily for the time
	 * of processing the command.
	 * current_target_override is used also for event handlers
	 * therefore we prevent touching it if command has no prefix.
	 * Previous override is saved and restored back to ensure
	 * correct work when run_command() is re-entered. */
	struct target *saved_target_override = context->current_target_override;
	if (c->jim_handler_data)
		context->current_target_override = c->jim_handler_data;

631
	int retval = c->handler(&cmd);
632 633 634 635

	if (c->jim_handler_data)
		context->current_target_override = saved_target_override;

636
	if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
637
		/* Print help for command */
Zachary T Welch's avatar
Zachary T Welch committed
638 639
		char *full_name = command_name(c, ' ');
		if (NULL != full_name) {
640
			command_run_linef(context, "usage %s", full_name);
Zachary T Welch's avatar
Zachary T Welch committed
641
			free(full_name);
642
		}
643
	} else if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
644
		/* just fall through for a shutdown request */
645
	} else if (retval != ERROR_OK) {
646 647 648
		/* we do not print out an error message because the command *should*
		 * have printed out an error
		 */
649 650 651 652
		char *full_name = command_name(c, ' ');
		LOG_DEBUG("Command '%s' failed with error code %d",
					full_name ? full_name : c->name, retval);
		free(full_name);
653
	}
654 655

	return retval;
656 657
}

658
int command_run_line(struct command_context *context, char *line)
659
{
660 661 662 663 664
	/* 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
665
	int retval = ERROR_FAIL;
666
	int retcode;
667 668 669 670 671
	/* 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.
	 */
672 673
	context->current_target_override = NULL;

674
	Jim_Interp *interp = context->interp;
675
	Jim_DeleteAssocData(interp, "context");
676
	retcode = Jim_SetAssocData(interp, "context", NULL, context);
677
	if (retcode == JIM_OK) {
678 679 680
		/* associated the return value */
		Jim_DeleteAssocData(interp, "retval");
		retcode = Jim_SetAssocData(interp, "retval", NULL, &retval);
681
		if (retcode == JIM_OK) {
682
			retcode = Jim_Eval_Named(interp, line, 0, 0);
683

684
			Jim_DeleteAssocData(interp, "retval");
685
		}
686 687
		Jim_DeleteAssocData(interp, "context");
	}
688
	if (retcode == JIM_OK) {
689 690 691 692
		const char *result;
		int reslen;

		result = Jim_GetString(Jim_GetResult(interp), &reslen);
693
		if (reslen > 0) {
oharboe's avatar
oharboe committed
694
			int i;
zwelch's avatar
zwelch committed
695
			char buff[256 + 1];
696
			for (i = 0; i < reslen; i += 256) {
oharboe's avatar
oharboe committed
697 698 699 700
				int chunk;
				chunk = reslen - i;
				if (chunk > 256)
					chunk = 256;
zwelch's avatar
zwelch committed
701
				strncpy(buff, result + i, chunk);
oharboe's avatar
oharboe committed
702 703 704
				buff[chunk] = 0;
				LOG_USER_N("%s", buff);
			}
Eric Wetzel's avatar
Eric Wetzel committed
705
			LOG_USER_N("\n");
706
		}
zwelch's avatar
zwelch committed
707
		retval = ERROR_OK;
708 709 710 711 712 713 714 715 716 717 718 719 720 721
	} else if (retcode == JIM_EXIT) {
		/* ignore.
		 * exit(Jim_GetExitCode(interp)); */
	} else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) {
		return retcode;
	} else {
		Jim_MakeErrorMessage(interp);
		LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));

		if (retval == ERROR_OK) {
			/* It wasn't a low level OpenOCD command that failed */
			return ERROR_FAIL;
		}
		return retval;
ntfreak's avatar
ntfreak committed
722
	}
723

724 725 726
	return retval;
}

727
int command_run_linef(struct command_context *context, const char *format, ...)
oharboe's avatar
oharboe committed
728
{
zwelch's avatar
zwelch committed
729
	int retval = ERROR_FAIL;
oharboe's avatar
oharboe committed
730 731 732 733
	char *string;
	va_list ap;
	va_start(ap, format);
	string = alloc_vprintf(format, ap);
734
	if (string != NULL) {
zwelch's avatar
zwelch committed
735
		retval = command_run_line(context, string);
736
		free(string);
oharboe's avatar
oharboe committed
737 738 739 740 741
	}
	va_end(ap);
	return retval;
}

742 743
void command_set_output_handler(struct command_context *context,
	command_output_handler_t output_handler, void *priv)
744 745 746 747 748
{
	context->output_handler = output_handler;
	context->output_handler_priv = priv;
}

749
struct command_context *copy_command_context(struct command_context *context)
750
{
751
	struct command_context *copy_context = malloc(sizeof(struct command_context));
752 753

	*copy_context = *context;
754

755 756 757
	return copy_context;
}

758
void command_done(struct command_context *cmd_ctx)
759
{
760 761
	if (NULL == cmd_ctx)
		return;
762

763
	free(cmd_ctx);
764 765
}

766 767 768 769 770 771 772 773 774 775 776
/* 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);
777

778 779 780 781
	Jim_SetResult(interp, result);
	return JIM_OK;
}

Antonio Borneo's avatar
Antonio Borneo committed
782
COMMAND_HANDLER(jim_echo)
783
{
784
	if (CMD_ARGC == 2 && !strcmp(CMD_ARGV[0], "-n")) {
Antonio Borneo's avatar
Antonio Borneo committed
785
		LOG_USER_N("%s", CMD_ARGV[1]);
786 787
		return JIM_OK;
	}
Antonio Borneo's avatar
Antonio Borneo committed
788
	if (CMD_ARGC != 1)
789
		return JIM_ERR;
Antonio Borneo's avatar
Antonio Borneo committed
790
	LOG_USER("%s", CMD_ARGV[0]);
791 792 793
	return JIM_OK;
}

794 795 796
/* Capture progress output and return as tcl return value. If the
 * progress output was empty, return tcl return value.
 */
797 798 799 800 801
static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
	if (argc != 2)
		return JIM_ERR;

802
	struct log_capture_state *state = command_log_capture_start(interp);
803

804 805 806
	/* disable polling during capture. This avoids capturing output
	 * from polling.
	 *
Spencer Oliver's avatar
Spencer Oliver committed
807
	 * This is necessary in order to avoid accidentally getting a non-empty