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 int fast_and_dangerous
= 0;
43 void command_print_help_line(command_context_t
* context
, struct command_s
*command
, int indent
);
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
);
69 c
->help
= strdup(help
);
74 /* place command in tree */
80 for (p
= parent
->children
; p
&& p
->next
; p
= p
->next
);
91 if (context
->commands
)
93 /* find last command */
94 for (p
= context
->commands
; p
&& p
->next
; p
= p
->next
);
100 context
->commands
= c
;
107 int unregister_all_commands(command_context_t
*context
)
115 while(NULL
!= context
->commands
)
117 c
= context
->commands
;
119 while(NULL
!= c
->children
)
122 c
->children
= c
->children
->next
;
131 context
->commands
= context
->commands
->next
;
144 int unregister_command(command_context_t
*context
, char *name
)
146 command_t
*c
, *p
= NULL
, *c2
;
148 if ((!context
) || (!name
))
149 return ERROR_INVALID_ARGUMENTS
;
152 for (c
= context
->commands
; c
; c
= c
->next
)
154 if (strcmp(name
, c
->name
) == 0)
163 context
->commands
= c
->next
;
166 /* unregister children */
169 for (c2
= c
->children
; c2
; c2
= c2
->next
)
185 /* remember the last command for unlinking */
192 int parse_line(char *line
, char *words
[], int max_words
)
196 char *word_start
= line
;
199 while (nwords
< max_words
- 1)
201 /* check if we reached
203 * a matching closing quote character " or '
204 * we're inside a word but not a quote, and the current character is whitespace
206 if (!*p
|| *p
== inquote
|| (word_start
&& !inquote
&& isspace(*p
)))
208 /* we're inside a word or quote, and reached its end*/
214 /* This will handle extra whitespace within quotes */
215 while (isspace(*word_start
)&&(word_start
<word_end
))
217 while (isspace(*(word_end
-1))&&(word_start
<word_end
))
219 len
= word_end
- word_start
;
224 memcpy(words
[nwords
] = malloc(len
+ 1), word_start
, len
);
225 /* add terminating NUL */
226 words
[nwords
++][len
] = 0;
229 /* we're done parsing the line */
233 /* skip over trailing quote or whitespace*/
234 if (inquote
|| isspace(*p
))
242 else if (*p
== '"' || *p
== '\'')
244 /* we've reached the beginning of a quote */
250 /* we've reached the beginning of a new word */
254 /* normal character, skip */
262 void command_output_text(command_context_t
*context
, const char *data
)
264 if( context
&& context
->output_handler
&& data
){
265 context
->output_handler( context
, data
);
269 void command_print_n(command_context_t
*context
, char *format
, ...)
274 va_start(ap
, format
);
276 string
= alloc_vprintf(format
, ap
);
279 context
->output_handler(context
, string
);
286 void command_print(command_context_t
*context
, char *format
, ...)
291 va_start(ap
, format
);
293 string
= alloc_vprintf(format
, ap
);
296 strcat(string
, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one char longer */
297 context
->output_handler(context
, string
);
304 command_t
*find_command(command_context_t
*context
, command_t
*commands
, char *words
[], int num_words
, int start_word
, int *new_start_word
)
308 for (c
= commands
; c
; c
= c
->next
)
310 if (strcasecmp(c
->name
, words
[start_word
]))
313 if ((context
->mode
== COMMAND_CONFIG
) || (c
->mode
== COMMAND_ANY
) || (c
->mode
== context
->mode
) )
323 *new_start_word
=start_word
;
329 if (start_word
== num_words
- 1)
333 return find_command(context
, c
->children
, words
, num_words
, start_word
+ 1, new_start_word
);
340 int find_and_run_command(command_context_t
*context
, command_t
*commands
, char *words
[], int num_words
)
344 c
= find_command(context
, commands
, words
, num_words
, start_word
, &start_word
);
347 /* just return command not found */
348 return ERROR_COMMAND_NOTFOUND
;
351 int retval
= c
->handler(context
, c
->name
, words
+ start_word
+ 1, num_words
- start_word
- 1);
352 if (retval
== ERROR_COMMAND_SYNTAX_ERROR
)
354 command_print(context
, "Syntax error:");
355 command_print_help_line(context
, c
, 0);
357 else if (retval
== ERROR_COMMAND_CLOSE_CONNECTION
)
359 /* just fall through for a shutdown request */
361 else if (retval
!= ERROR_OK
)
363 /* we do not print out an error message because the command *should*
364 * have printed out an error
366 LOG_DEBUG("Command failed with error code %d", retval
);
372 int command_run_line_internal(command_context_t
*context
, char *line
)
374 LOG_USER_N("%s", ""); /* Keep GDB connection alive*/
377 char *words
[128] = {0};
381 /* skip preceding whitespace */
382 while (isspace(*line
))
385 /* empty line, ignore */
389 /* ignore comments */
390 if (*line
&& (line
[0] == '#'))
393 LOG_DEBUG("%s", line
);
395 nwords
= parse_line(line
, words
, sizeof(words
) / sizeof(words
[0]));
399 retval
= find_and_run_command(context
, context
->commands
, words
, nwords
);
402 return ERROR_INVALID_ARGUMENTS
;
404 for (i
= 0; i
< nwords
; i
++)
410 int command_run_line(command_context_t
*context
, char *line
)
412 /* if a command is unknown to the "unknown" proc in tcl/commands.tcl will
413 * redirect it to OpenOCD.
415 * This avoids having to type the "openocd" prefix and makes OpenOCD
416 * commands "native" to Tcl.
418 return jim_command(context
, line
);
422 int command_run_linef(command_context_t
*context
, char *format
, ...)
424 int retval
=ERROR_FAIL
;
427 va_start(ap
, format
);
428 string
= alloc_vprintf(format
, ap
);
431 retval
=command_run_line(context
, string
);
437 void command_print_help_line(command_context_t
* context
, struct command_s
*command
, int indent
)
440 char *indent_text
=malloc(indent
+ 2);
442 char *help
= "no help available";
447 indent_text
[0] = ' ';
448 memset(indent_text
+ 1, '-', indent
);
449 indent_text
[indent
+ 1] = 0;
453 help
= command
->help
;
455 snprintf(name_buf
, 64, command
->name
);
458 strncat(name_buf
, indent_text
, 64);
460 command_print(context
, "%20s\t%s", name_buf
, help
, indent
);
462 if (command
->children
)
464 for (c
= command
->children
; c
; c
= c
->next
)
466 command_print_help_line(context
, c
, indent
+ 1);
472 int command_print_help_match(command_context_t
* context
, command_t
* c_first
, char* name
, char** args
, int argc
)
476 for (c
= c_first
; c
; c
= c
->next
)
480 if (strcasecmp(c
->name
, args
[0]))
485 command_print_help_match(context
, c
->children
, name
, args
+ 1, argc
- 1);
490 command_print_help_line(context
, c
, 0);
496 int command_print_help(command_context_t
* context
, char* name
, char** args
, int argc
)
498 return command_print_help_match(context
, context
->commands
, name
, args
, argc
);
501 void command_set_output_handler(command_context_t
* context
, int (*output_handler
)(struct command_context_s
*context
, const char* line
), void *priv
)
503 context
->output_handler
= output_handler
;
504 context
->output_handler_priv
= priv
;
507 command_context_t
* copy_command_context(command_context_t
* context
)
509 command_context_t
* copy_context
= malloc(sizeof(command_context_t
));
511 *copy_context
= *context
;
516 int command_done(command_context_t
*context
)
524 command_context_t
* command_init()
526 command_context_t
* context
= malloc(sizeof(command_context_t
));
528 context
->mode
= COMMAND_EXEC
;
529 context
->commands
= NULL
;
530 context
->current_target
= 0;
531 context
->output_handler
= NULL
;
532 context
->output_handler_priv
= NULL
;
534 register_command(context
, NULL
, "help", command_print_help
,
535 COMMAND_EXEC
, "display this help");
537 register_command(context
, NULL
, "sleep", handle_sleep_command
,
538 COMMAND_ANY
, "sleep for <n> milliseconds");
540 register_command(context
, NULL
, "time", handle_time_command
,
541 COMMAND_ANY
, "time <cmd + args> - execute <cmd + args> and print time it took");
543 register_command(context
, NULL
, "fast", handle_fast_command
,
544 COMMAND_ANY
, "fast <enable/disable> - place at beginning of config files. Sets defaults to fast and dangerous.");
549 /* sleep command sleeps for <n> miliseconds
550 * this is useful in target startup scripts
552 int handle_sleep_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
554 unsigned long duration
= 0;
558 duration
= strtoul(args
[0], NULL
, 0);
559 usleep(duration
* 1000);
565 int handle_fast_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
568 return ERROR_COMMAND_SYNTAX_ERROR
;
570 fast_and_dangerous
= strcmp("enable", args
[0])==0;
576 int handle_time_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
584 return ERROR_COMMAND_SYNTAX_ERROR
;
586 duration_start_measure(&duration
);
588 retval
= find_and_run_command(cmd_ctx
, cmd_ctx
->commands
, args
, argc
);
589 if (retval
== ERROR_COMMAND_NOTFOUND
)
591 command_print(cmd_ctx
, "Command %s not found", args
[0]);
594 duration_stop_measure(&duration
, &duration_text
);
596 t
=duration
.duration
.tv_sec
;
597 t
+=((float)duration
.duration
.tv_usec
/ 1000000.0);
598 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)