1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * part of this file is taken from libcli (libcli.sourceforge.net) *
6 * Copyright (C) David Parrish (david@dparrish.com) *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
27 #include "replacements.h"
32 #include "time_support.h"
41 #include <openocd_tcl.h>
43 int fast_and_dangerous
= 0;
45 int handle_sleep_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
46 int handle_time_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
47 int handle_fast_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
49 /* forward declaration of jim_command */
50 extern int jim_command(command_context_t
*context
, char *line
);
54 command_t
* register_command(command_context_t
*context
, command_t
*parent
, char *name
, int (*handler
)(struct command_context_s
*context
, char* name
, char** args
, int argc
), enum command_mode mode
, char *help
)
58 if (!context
|| !name
)
61 c
= malloc(sizeof(command_t
));
63 c
->name
= strdup(name
);
72 /* place command in tree */
78 for (p
= parent
->children
; p
&& p
->next
; p
= p
->next
);
89 if (context
->commands
)
91 /* find last command */
92 for (p
= context
->commands
; p
&& p
->next
; p
= p
->next
);
98 context
->commands
= c
;
101 /* accumulate help text in Tcl helptext list. */
102 Jim_Obj
*helptext
=Jim_GetGlobalVariableStr(interp
, "ocd_helptext", JIM_ERRMSG
);
103 Jim_Obj
*cmd_entry
=Jim_NewListObj(interp
, NULL
, 0);
105 Jim_Obj
*cmd_list
=Jim_NewListObj(interp
, NULL
, 0);
107 /* maximum of two levels :-) */
110 Jim_ListAppendElement(interp
, cmd_list
, Jim_NewStringObj(interp
, c
->parent
->name
, -1));
112 Jim_ListAppendElement(interp
, cmd_list
, Jim_NewStringObj(interp
, c
->name
, -1));
114 Jim_ListAppendElement(interp
, cmd_entry
, cmd_list
);
115 Jim_ListAppendElement(interp
, cmd_entry
, Jim_NewStringObj(interp
, help
, -1));
116 Jim_ListAppendElement(interp
, helptext
, cmd_entry
);
120 int unregister_all_commands(command_context_t
*context
)
128 while(NULL
!= context
->commands
)
130 c
= context
->commands
;
132 while(NULL
!= c
->children
)
135 c
->children
= c
->children
->next
;
142 context
->commands
= context
->commands
->next
;
153 int unregister_command(command_context_t
*context
, char *name
)
155 command_t
*c
, *p
= NULL
, *c2
;
157 if ((!context
) || (!name
))
158 return ERROR_INVALID_ARGUMENTS
;
161 for (c
= context
->commands
; c
; c
= c
->next
)
163 if (strcmp(name
, c
->name
) == 0)
172 context
->commands
= c
->next
;
175 /* unregister children */
178 for (c2
= c
->children
; c2
; c2
= c2
->next
)
190 /* remember the last command for unlinking */
197 int parse_line(char *line
, char *words
[], int max_words
)
201 char *word_start
= line
;
204 while (nwords
< max_words
- 1)
206 /* check if we reached
208 * a matching closing quote character " or '
209 * we're inside a word but not a quote, and the current character is whitespace
211 if (!*p
|| *p
== inquote
|| (word_start
&& !inquote
&& isspace(*p
)))
213 /* we're inside a word or quote, and reached its end*/
219 /* This will handle extra whitespace within quotes */
220 while (isspace(*word_start
)&&(word_start
<word_end
))
222 while (isspace(*(word_end
-1))&&(word_start
<word_end
))
224 len
= word_end
- word_start
;
229 memcpy(words
[nwords
] = malloc(len
+ 1), word_start
, len
);
230 /* add terminating NUL */
231 words
[nwords
++][len
] = 0;
234 /* we're done parsing the line */
238 /* skip over trailing quote or whitespace*/
239 if (inquote
|| isspace(*p
))
247 else if (*p
== '"' || *p
== '\'')
249 /* we've reached the beginning of a quote */
255 /* we've reached the beginning of a new word */
259 /* normal character, skip */
267 void command_output_text(command_context_t
*context
, const char *data
)
269 if( context
&& context
->output_handler
&& data
){
270 context
->output_handler( context
, data
);
274 void command_print_n(command_context_t
*context
, char *format
, ...)
279 va_start(ap
, format
);
281 string
= alloc_vprintf(format
, ap
);
284 context
->output_handler(context
, string
);
291 void command_print(command_context_t
*context
, char *format
, ...)
296 va_start(ap
, format
);
298 string
= alloc_vprintf(format
, ap
);
301 strcat(string
, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one char longer */
302 context
->output_handler(context
, string
);
309 command_t
*find_command(command_context_t
*context
, command_t
*commands
, char *words
[], int num_words
, int start_word
, int *new_start_word
)
313 for (c
= commands
; c
; c
= c
->next
)
315 if (strcasecmp(c
->name
, words
[start_word
]))
318 if ((context
->mode
== COMMAND_CONFIG
) || (c
->mode
== COMMAND_ANY
) || (c
->mode
== context
->mode
) )
328 *new_start_word
=start_word
;
334 if (start_word
== num_words
- 1)
338 return find_command(context
, c
->children
, words
, num_words
, start_word
+ 1, new_start_word
);
345 int find_and_run_command(command_context_t
*context
, command_t
*commands
, char *words
[], int num_words
)
349 c
= find_command(context
, commands
, words
, num_words
, start_word
, &start_word
);
352 /* just return command not found */
353 return ERROR_COMMAND_NOTFOUND
;
356 int retval
= c
->handler(context
, c
->name
, words
+ start_word
+ 1, num_words
- start_word
- 1);
357 if (retval
== ERROR_COMMAND_SYNTAX_ERROR
)
361 else if (retval
== ERROR_COMMAND_CLOSE_CONNECTION
)
363 /* just fall through for a shutdown request */
365 else if (retval
!= ERROR_OK
)
367 /* we do not print out an error message because the command *should*
368 * have printed out an error
370 LOG_DEBUG("Command failed with error code %d", retval
);
376 int command_run_line_internal(command_context_t
*context
, char *line
)
378 LOG_USER_N("%s", ""); /* Keep GDB connection alive*/
381 char *words
[128] = {0};
385 /* skip preceding whitespace */
386 while (isspace(*line
))
389 /* empty line, ignore */
393 /* ignore comments */
394 if (*line
&& (line
[0] == '#'))
397 LOG_DEBUG("%s", line
);
399 nwords
= parse_line(line
, words
, sizeof(words
) / sizeof(words
[0]));
403 retval
= find_and_run_command(context
, context
->commands
, words
, nwords
);
406 return ERROR_INVALID_ARGUMENTS
;
408 for (i
= 0; i
< nwords
; i
++)
414 int command_run_line(command_context_t
*context
, char *line
)
416 /* if a command is unknown to the "unknown" proc in tcl/commands.tcl will
417 * redirect it to OpenOCD.
419 * This avoids having to type the "openocd" prefix and makes OpenOCD
420 * commands "native" to Tcl.
422 return jim_command(context
, line
);
426 int command_run_linef(command_context_t
*context
, char *format
, ...)
428 int retval
=ERROR_FAIL
;
431 va_start(ap
, format
);
432 string
= alloc_vprintf(format
, ap
);
435 retval
=command_run_line(context
, string
);
443 void command_set_output_handler(command_context_t
* context
, int (*output_handler
)(struct command_context_s
*context
, const char* line
), void *priv
)
445 context
->output_handler
= output_handler
;
446 context
->output_handler_priv
= priv
;
449 command_context_t
* copy_command_context(command_context_t
* context
)
451 command_context_t
* copy_context
= malloc(sizeof(command_context_t
));
453 *copy_context
= *context
;
458 int command_done(command_context_t
*context
)
466 command_context_t
* command_init()
468 command_context_t
* context
= malloc(sizeof(command_context_t
));
470 context
->mode
= COMMAND_EXEC
;
471 context
->commands
= NULL
;
472 context
->current_target
= 0;
473 context
->output_handler
= NULL
;
474 context
->output_handler_priv
= NULL
;
476 register_command(context
, NULL
, "sleep", handle_sleep_command
,
477 COMMAND_ANY
, "sleep for <n> milliseconds");
479 register_command(context
, NULL
, "time", handle_time_command
,
480 COMMAND_ANY
, "time <cmd + args> - execute <cmd + args> and print time it took");
482 register_command(context
, NULL
, "fast", handle_fast_command
,
483 COMMAND_ANY
, "fast <enable/disable> - place at beginning of config files. Sets defaults to fast and dangerous.");
488 /* sleep command sleeps for <n> miliseconds
489 * this is useful in target startup scripts
491 int handle_sleep_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
493 unsigned long duration
= 0;
497 duration
= strtoul(args
[0], NULL
, 0);
498 usleep(duration
* 1000);
504 int handle_fast_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
507 return ERROR_COMMAND_SYNTAX_ERROR
;
509 fast_and_dangerous
= strcmp("enable", args
[0])==0;
515 int handle_time_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
523 return ERROR_COMMAND_SYNTAX_ERROR
;
525 duration_start_measure(&duration
);
527 retval
= find_and_run_command(cmd_ctx
, cmd_ctx
->commands
, args
, argc
);
528 if (retval
== ERROR_COMMAND_NOTFOUND
)
530 command_print(cmd_ctx
, "Command %s not found", args
[0]);
533 duration_stop_measure(&duration
, &duration_text
);
535 t
=duration
.duration
.tv_sec
;
536 t
+=((float)duration
.duration
.tv_usec
/ 1000000.0);
537 command_print(cmd_ctx
, "%s took %fs", args
[0], t
);
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)