summaryrefslogtreecommitdiff
path: root/src/helper
diff options
context:
space:
mode:
Diffstat (limited to 'src/helper')
-rw-r--r--src/helper/command.c1214
-rw-r--r--src/helper/configuration.c208
-rw-r--r--src/helper/log.c496
-rw-r--r--src/helper/log.h226
-rw-r--r--src/helper/options.c306
-rw-r--r--src/helper/replacements.h58
6 files changed, 1254 insertions, 1254 deletions
diff --git a/src/helper/command.c b/src/helper/command.c
index f13a86c1..15cddcdc 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -1,607 +1,607 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * 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
-
-#include "replacements.h"
-
-#include "command.h"
-
-#include "log.h"
-#include "time_support.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <unistd.h>
-
-void command_print_help_line(command_context_t* context, struct command_s *command, int indent);
-
-int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int build_unique_lengths(command_context_t *context, command_t *commands)
-{
- command_t *c, *p;
-
- /* iterate through all commands */
- for (c = commands; c; c = c->next)
- {
- /* find out how many characters are required to uniquely identify a command */
- for (c->unique_len = 1; c->unique_len <= strlen(c->name); c->unique_len++)
- {
- int foundmatch = 0;
-
- /* for every command, see if the current length is enough */
- for (p = commands; p; p = p->next)
- {
- /* ignore the command itself */
- if (c == p)
- continue;
-
- /* compare commands up to the current length */
- if (strncmp(p->name, c->name, c->unique_len) == 0)
- foundmatch++;
- }
-
- /* when none of the commands matched, we've found the minimum length required */
- if (!foundmatch)
- break;
- }
-
- /* if the current command has children, build the unique lengths for them */
- if (c->children)
- build_unique_lengths(context, c->children);
- }
-
- return ERROR_OK;
-}
-
-/* Avoid evaluating this each time we add a command. Reduces overhead from O(n^2) to O(n).
- * Makes a difference on ARM7 types machines and is not observable on GHz machines.
- */
-static int unique_length_dirty = 1;
-
-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)
-{
- command_t *c, *p;
- unique_length_dirty = 1;
-
- if (!context || !name)
- return NULL;
-
- c = malloc(sizeof(command_t));
-
- c->name = strdup(name);
- c->parent = parent;
- c->children = NULL;
- c->handler = handler;
- c->mode = mode;
- if (help)
- c->help = strdup(help);
- else
- c->help = NULL;
- c->unique_len = 0;
- c->next = NULL;
-
- /* place command in tree */
- if (parent)
- {
- if (parent->children)
- {
- /* find last child */
- for (p = parent->children; p && p->next; p = p->next);
- if (p)
- p->next = c;
- }
- else
- {
- parent->children = c;
- }
- }
- else
- {
- if (context->commands)
- {
- /* find last command */
- for (p = context->commands; p && p->next; p = p->next);
- if (p)
- p->next = c;
- }
- else
- {
- context->commands = c;
- }
- }
-
- return c;
-}
-
-int unregister_command(command_context_t *context, char *name)
-{
- unique_length_dirty = 1;
-
- command_t *c, *p = NULL, *c2;
-
- if ((!context) || (!name))
- return ERROR_INVALID_ARGUMENTS;
-
- /* find command */
- for (c = context->commands; c; c = c->next)
- {
- if (strcmp(name, c->name) == 0)
- {
- /* unlink command */
- if (p)
- {
- p->next = c->next;
- }
- else
- {
- context->commands = c->next;
- }
-
- /* unregister children */
- if (c->children)
- {
- for (c2 = c->children; c2; c2 = c2->next)
- {
- free(c2->name);
- if (c2->help)
- free(c2->help);
- free(c2);
- }
- }
-
- /* delete command */
- free(c->name);
- if (c->help)
- free(c->help);
- free(c);
- }
-
- /* remember the last command for unlinking */
- p = c;
- }
-
- return ERROR_OK;
-}
-
-int parse_line(char *line, char *words[], int max_words)
-{
- int nwords = 0;
- char *p = line;
- char *word_start = line;
- int inquote = 0;
-
- while (nwords < max_words - 1)
- {
- /* check if we reached
- * a terminating NUL
- * a matching closing quote character " or '
- * we're inside a word but not a quote, and the current character is whitespace
- */
- if (!*p || *p == inquote || (word_start && !inquote && isspace(*p)))
- {
- /* we're inside a word or quote, and reached its end*/
- if (word_start)
- {
- int len;
- char *word_end=p;
-
- /* This will handle extra whitespace within quotes */
- while (isspace(*word_start)&&(word_start<word_end))
- word_start++;
- while (isspace(*(word_end-1))&&(word_start<word_end))
- word_end--;
- len = word_end - word_start;
-
- if (len>0)
- {
- /* copy the word */
- memcpy(words[nwords] = malloc(len + 1), word_start, len);
- /* add terminating NUL */
- words[nwords++][len] = 0;
- }
- }
- /* we're done parsing the line */
- if (!*p)
- break;
-
- /* skip over trailing quote or whitespace*/
- if (inquote || isspace(*p))
- p++;
- while (isspace(*p))
- p++;
-
- inquote = 0;
- word_start = 0;
- }
- else if (*p == '"' || *p == '\'')
- {
- /* we've reached the beginning of a quote */
- inquote = *p++;
- word_start = p;
- }
- else
- {
- /* we've reached the beginning of a new word */
- if (!word_start)
- word_start = p;
-
- /* normal character, skip */
- p++;
- }
- }
-
- return nwords;
-}
-
-void command_print(command_context_t *context, char *format, ...)
-{
- char *buffer = NULL;
- int n, size = 0;
- char *p;
-
- /* process format string */
- for (;;)
- {
- va_list ap;
- va_start(ap, format);
- if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)
- {
- /* increase buffer until it fits the whole string */
- if (!(p = realloc(buffer, size += 4096)))
- {
- /* gotta free up */
- if (buffer)
- free(buffer);
- va_end(ap);
- return;
- }
-
- buffer = p;
-
- va_end(ap);
- continue;
- }
- va_end(ap);
- break;
- }
-
- /* vsnprintf failed */
- if (n < 0)
- {
- if (buffer)
- free(buffer);
- return;
- }
-
- p = buffer;
-
- /* process lines in buffer */
- do {
- char *next = strchr(p, '\n');
-
- if (next)
- *next++ = 0;
-
- if (context->output_handler)
- context->output_handler(context, p);
-
- p = next;
- } while (p);
-
- if (buffer)
- free(buffer);
-}
-
-int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word)
-{
- command_t *c;
-
- if (unique_length_dirty)
- {
- unique_length_dirty = 0;
- /* update unique lengths */
- build_unique_lengths(context, context->commands);
- }
-
- for (c = commands; c; c = c->next)
- {
- if (strncasecmp(c->name, words[start_word], c->unique_len))
- continue;
-
- if (strncasecmp(c->name, words[start_word], strlen(words[start_word])))
- continue;
-
- if ((context->mode == COMMAND_CONFIG) || (c->mode == COMMAND_ANY) || (c->mode == context->mode) )
- {
- if (!c->children)
- {
- if (!c->handler)
- {
- command_print(context, "No handler for command");
- break;
- }
- else
- {
- int retval = c->handler(context, c->name, words + start_word + 1, num_words - start_word - 1);
- if (retval == ERROR_COMMAND_SYNTAX_ERROR)
- {
- command_print(context, "Syntax error:");
- command_print_help_line(context, c, 0);
- }
- return retval;
- }
- }
- else
- {
- if (start_word == num_words - 1)
- {
- command_print(context, "Incomplete command");
- break;
- }
- return find_and_run_command(context, c->children, words, num_words, start_word + 1);
- }
- }
- }
-
- command_print(context, "Command %s not found", words[start_word]);
- return ERROR_OK;
-}
-
-int command_run_line(command_context_t *context, char *line)
-{
- int nwords;
- char *words[128] = {0};
- int retval;
- int i;
-
- if ((!context) || (!line))
- return ERROR_INVALID_ARGUMENTS;
-
- /* skip preceding whitespace */
- while (isspace(*line))
- line++;
-
- /* empty line, ignore */
- if (!*line)
- return ERROR_OK;
-
- /* ignore comments */
- if (*line && (line[0] == '#'))
- return ERROR_OK;
-
- if (context->echo)
- {
- command_print(context, "%s", line);
- }
-
- nwords = parse_line(line, words, sizeof(words) / sizeof(words[0]));
-
- if (nwords > 0)
- retval = find_and_run_command(context, context->commands, words, nwords, 0);
- else
- return ERROR_INVALID_ARGUMENTS;
-
- for (i = 0; i < nwords; i++)
- free(words[i]);
-
- return retval;
-}
-
-int command_run_file(command_context_t *context, FILE *file, enum command_mode mode)
-{
- int retval = ERROR_OK;
- int old_command_mode;
- char *buffer=malloc(4096);
- if (buffer==NULL)
- {
- return ERROR_INVALID_ARGUMENTS;
- }
-
- old_command_mode = context->mode;
- context->mode = mode;
-
- while (fgets(buffer, 4096, file))
- {
- char *p;
- char *cmd, *end;
-
- /* stop processing line after a comment (#, !) or a LF, CR were encountered */
- if ((p = strpbrk(buffer, "#!\r\n")))
- *p = 0;
-
- /* skip over leading whitespace */
- cmd = buffer;
- while (isspace(*cmd))
- cmd++;
-
- /* empty (all whitespace) line? */
- if (!*cmd)
- continue;
-
- /* search the end of the current line, ignore trailing whitespace */
- for (p = end = cmd; *p; p++)
- if (!isspace(*p))
- end = p;
-
- /* terminate end */
- *++end = 0;
- if (strcasecmp(cmd, "quit") == 0)
- break;
-
- /* run line */
- if ((retval = command_run_line(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)
- break;
- }
-
- context->mode = old_command_mode;
-
-
- free(buffer);
-
- return retval;
-}
-
-void command_print_help_line(command_context_t* context, struct command_s *command, int indent)
-{
- command_t *c;
- char indents[32] = {0};
- char *help = "no help available";
- char name_buf[64];
- int i;
-
- for (i = 0; i < indent; i+=2)
- {
- indents[i*2] = ' ';
- indents[i*2+1] = '-';
- }
- indents[i*2] = 0;
-
- if (command->help)
- help = command->help;
-
- snprintf(name_buf, 64, command->name);
- strncat(name_buf, indents, 64);
- command_print(context, "%20s\t%s", name_buf, help);
-
- if (command->children)
- {
- for (c = command->children; c; c = c->next)
- {
- command_print_help_line(context, c, indent + 1);
- }
- }
-}
-
-int command_print_help(command_context_t* context, char* name, char** args, int argc)
-{
- command_t *c;
-
- for (c = context->commands; c; c = c->next)
- {
- if (argc == 1)
- {
- if (strncasecmp(c->name, args[0], c->unique_len))
- continue;
-
- if (strncasecmp(c->name, args[0], strlen(args[0])))
- continue;
- }
-
- command_print_help_line(context, c, 0);
- }
-
- return ERROR_OK;
-}
-
-void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, char* line), void *priv)
-{
- context->output_handler = output_handler;
- context->output_handler_priv = priv;
-}
-
-command_context_t* copy_command_context(command_context_t* context)
-{
- command_context_t* copy_context = malloc(sizeof(command_context_t));
-
- *copy_context = *context;
-
- return copy_context;
-}
-
-int command_done(command_context_t *context)
-{
- free(context);
- context = NULL;
-
- return ERROR_OK;
-}
-
-command_context_t* command_init()
-{
- command_context_t* context = malloc(sizeof(command_context_t));
-
- context->mode = COMMAND_EXEC;
- context->commands = NULL;
- context->current_target = 0;
- context->echo = 0;
- context->output_handler = NULL;
- context->output_handler_priv = NULL;
-
- register_command(context, NULL, "help", command_print_help,
- COMMAND_EXEC, "display this help");
-
- register_command(context, NULL, "sleep", handle_sleep_command,
- COMMAND_ANY, "sleep for <n> milliseconds");
-
- register_command(context, NULL, "time", handle_time_command,
- COMMAND_ANY, "time <cmd + args> - execute <cmd + args> and print time it took");
-
- return context;
-}
-
-/* sleep command sleeps for <n> miliseconds
- * this is useful in target startup scripts
- */
-int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
- unsigned long duration = 0;
-
- if (argc == 1)
- {
- duration = strtoul(args[0], NULL, 0);
- usleep(duration * 1000);
- }
-
- return ERROR_OK;
-}
-
-int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
- if (argc<1)
- return ERROR_COMMAND_SYNTAX_ERROR;
-
- duration_t duration;
- char *duration_text;
- int retval;
-
- duration_start_measure(&duration);
-
- retval = find_and_run_command(cmd_ctx, cmd_ctx->commands, args, argc, 0);
-
- duration_stop_measure(&duration, &duration_text);
-
- float t=duration.duration.tv_sec;
- t+=((float)duration.duration.tv_usec / 1000000.0);
- command_print(cmd_ctx, "%s took %fs", args[0], t);
-
- free(duration_text);
-
- return retval;
-}
+/***************************************************************************
+ * Copyright (C) 2005 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * 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
+
+#include "replacements.h"
+
+#include "command.h"
+
+#include "log.h"
+#include "time_support.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+
+void command_print_help_line(command_context_t* context, struct command_s *command, int indent);
+
+int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int build_unique_lengths(command_context_t *context, command_t *commands)
+{
+ command_t *c, *p;
+
+ /* iterate through all commands */
+ for (c = commands; c; c = c->next)
+ {
+ /* find out how many characters are required to uniquely identify a command */
+ for (c->unique_len = 1; c->unique_len <= strlen(c->name); c->unique_len++)
+ {
+ int foundmatch = 0;
+
+ /* for every command, see if the current length is enough */
+ for (p = commands; p; p = p->next)
+ {
+ /* ignore the command itself */
+ if (c == p)
+ continue;
+
+ /* compare commands up to the current length */
+ if (strncmp(p->name, c->name, c->unique_len) == 0)
+ foundmatch++;
+ }
+
+ /* when none of the commands matched, we've found the minimum length required */
+ if (!foundmatch)
+ break;
+ }
+
+ /* if the current command has children, build the unique lengths for them */
+ if (c->children)
+ build_unique_lengths(context, c->children);
+ }
+
+ return ERROR_OK;
+}
+
+/* Avoid evaluating this each time we add a command. Reduces overhead from O(n^2) to O(n).
+ * Makes a difference on ARM7 types machines and is not observable on GHz machines.
+ */
+static int unique_length_dirty = 1;
+
+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)
+{
+ command_t *c, *p;
+ unique_length_dirty = 1;
+
+ if (!context || !name)
+ return NULL;
+
+ c = malloc(sizeof(command_t));
+
+ c->name = strdup(name);
+ c->parent = parent;
+ c->children = NULL;
+ c->handler = handler;
+ c->mode = mode;
+ if (help)
+ c->help = strdup(help);
+ else
+ c->help = NULL;
+ c->unique_len = 0;
+ c->next = NULL;
+
+ /* place command in tree */
+ if (parent)
+ {
+ if (parent->children)
+ {
+ /* find last child */
+ for (p = parent->children; p && p->next; p = p->next);
+ if (p)
+ p->next = c;
+ }
+ else
+ {
+ parent->children = c;
+ }
+ }
+ else
+ {
+ if (context->commands)
+ {
+ /* find last command */
+ for (p = context->commands; p && p->next; p = p->next);
+ if (p)
+ p->next = c;
+ }
+ else
+ {
+ context->commands = c;
+ }
+ }
+
+ return c;
+}
+
+int unregister_command(command_context_t *context, char *name)
+{
+ unique_length_dirty = 1;
+
+ command_t *c, *p = NULL, *c2;
+
+ if ((!context) || (!name))
+ return ERROR_INVALID_ARGUMENTS;
+
+ /* find command */
+ for (c = context->commands; c; c = c->next)
+ {
+ if (strcmp(name, c->name) == 0)
+ {
+ /* unlink command */
+ if (p)
+ {
+ p->next = c->next;
+ }
+ else
+ {
+ context->commands = c->next;
+ }
+
+ /* unregister children */
+ if (c->children)
+ {
+ for (c2 = c->children; c2; c2 = c2->next)
+ {
+ free(c2->name);
+ if (c2->help)
+ free(c2->help);
+ free(c2);
+ }
+ }
+
+ /* delete command */
+ free(c->name);
+ if (c->help)
+ free(c->help);
+ free(c);
+ }
+
+ /* remember the last command for unlinking */
+ p = c;
+ }
+
+ return ERROR_OK;
+}
+
+int parse_line(char *line, char *words[], int max_words)
+{
+ int nwords = 0;
+ char *p = line;
+ char *word_start = line;
+ int inquote = 0;
+
+ while (nwords < max_words - 1)
+ {
+ /* check if we reached
+ * a terminating NUL
+ * a matching closing quote character " or '
+ * we're inside a word but not a quote, and the current character is whitespace
+ */
+ if (!*p || *p == inquote || (word_start && !inquote && isspace(*p)))
+ {
+ /* we're inside a word or quote, and reached its end*/
+ if (word_start)
+ {
+ int len;
+ char *word_end=p;
+
+ /* This will handle extra whitespace within quotes */
+ while (isspace(*word_start)&&(word_start<word_end))
+ word_start++;
+ while (isspace(*(word_end-1))&&(word_start<word_end))
+ word_end--;
+ len = word_end - word_start;
+
+ if (len>0)
+ {
+ /* copy the word */
+ memcpy(words[nwords] = malloc(len + 1), word_start, len);
+ /* add terminating NUL */
+ words[nwords++][len] = 0;
+ }
+ }
+ /* we're done parsing the line */
+ if (!*p)
+ break;
+
+ /* skip over trailing quote or whitespace*/
+ if (inquote || isspace(*p))
+ p++;
+ while (isspace(*p))
+ p++;
+
+ inquote = 0;
+ word_start = 0;
+ }
+ else if (*p == '"' || *p == '\'')
+ {
+ /* we've reached the beginning of a quote */
+ inquote = *p++;
+ word_start = p;
+ }
+ else
+ {
+ /* we've reached the beginning of a new word */
+ if (!word_start)
+ word_start = p;
+
+ /* normal character, skip */
+ p++;
+ }
+ }
+
+ return nwords;
+}
+
+void command_print(command_context_t *context, char *format, ...)
+{
+ char *buffer = NULL;
+ int n, size = 0;
+ char *p;
+
+ /* process format string */
+ for (;;)
+ {
+ va_list ap;
+ va_start(ap, format);
+ if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)
+ {
+ /* increase buffer until it fits the whole string */
+ if (!(p = realloc(buffer, size += 4096)))
+ {
+ /* gotta free up */
+ if (buffer)
+ free(buffer);
+ va_end(ap);
+ return;
+ }
+
+ buffer = p;
+
+ va_end(ap);
+ continue;
+ }
+ va_end(ap);
+ break;
+ }
+
+ /* vsnprintf failed */
+ if (n < 0)
+ {
+ if (buffer)
+ free(buffer);
+ return;
+ }
+
+ p = buffer;
+
+ /* process lines in buffer */
+ do {
+ char *next = strchr(p, '\n');
+
+ if (next)
+ *next++ = 0;
+
+ if (context->output_handler)
+ context->output_handler(context, p);
+
+ p = next;
+ } while (p);
+
+ if (buffer)
+ free(buffer);
+}
+
+int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word)
+{
+ command_t *c;
+
+ if (unique_length_dirty)
+ {
+ unique_length_dirty = 0;
+ /* update unique lengths */
+ build_unique_lengths(context, context->commands);
+ }
+
+ for (c = commands; c; c = c->next)
+ {
+ if (strncasecmp(c->name, words[start_word], c->unique_len))
+ continue;
+
+ if (strncasecmp(c->name, words[start_word], strlen(words[start_word])))
+ continue;
+
+ if ((context->mode == COMMAND_CONFIG) || (c->mode == COMMAND_ANY) || (c->mode == context->mode) )
+ {
+ if (!c->children)
+ {
+ if (!c->handler)
+ {
+ command_print(context, "No handler for command");
+ break;
+ }
+ else
+ {
+ int retval = c->handler(context, c->name, words + start_word + 1, num_words - start_word - 1);
+ if (retval == ERROR_COMMAND_SYNTAX_ERROR)
+ {
+ command_print(context, "Syntax error:");
+ command_print_help_line(context, c, 0);
+ }
+ return retval;
+ }
+ }
+ else
+ {
+ if (start_word == num_words - 1)
+ {
+ command_print(context, "Incomplete command");
+ break;
+ }
+ return find_and_run_command(context, c->children, words, num_words, start_word + 1);
+ }
+ }
+ }
+
+ command_print(context, "Command %s not found", words[start_word]);
+ return ERROR_OK;
+}
+
+int command_run_line(command_context_t *context, char *line)
+{
+ int nwords;
+ char *words[128] = {0};
+ int retval;
+ int i;
+
+ if ((!context) || (!line))
+ return ERROR_INVALID_ARGUMENTS;
+
+ /* skip preceding whitespace */
+ while (isspace(*line))
+ line++;
+
+ /* empty line, ignore */
+ if (!*line)
+ return ERROR_OK;
+
+ /* ignore comments */
+ if (*line && (line[0] == '#'))
+ return ERROR_OK;
+
+ if (context->echo)
+ {
+ command_print(context, "%s", line);
+ }
+
+ nwords = parse_line(line, words, sizeof(words) / sizeof(words[0]));
+
+ if (nwords > 0)
+ retval = find_and_run_command(context, context->commands, words, nwords, 0);
+ else
+ return ERROR_INVALID_ARGUMENTS;
+
+ for (i = 0; i < nwords; i++)
+ free(words[i]);
+
+ return retval;
+}
+
+int command_run_file(command_context_t *context, FILE *file, enum command_mode mode)
+{
+ int retval = ERROR_OK;
+ int old_command_mode;
+ char *buffer=malloc(4096);
+ if (buffer==NULL)
+ {
+ return ERROR_INVALID_ARGUMENTS;
+ }
+
+ old_command_mode = context->mode;
+ context->mode = mode;
+
+ while (fgets(buffer, 4096, file))
+ {
+ char *p;
+ char *cmd, *end;
+
+ /* stop processing line after a comment (#, !) or a LF, CR were encountered */
+ if ((p = strpbrk(buffer, "#!\r\n")))
+ *p = 0;
+
+ /* skip over leading whitespace */
+ cmd = buffer;
+ while (isspace(*cmd))
+ cmd++;
+
+ /* empty (all whitespace) line? */
+ if (!*cmd)
+ continue;
+
+ /* search the end of the current line, ignore trailing whitespace */
+ for (p = end = cmd; *p; p++)
+ if (!isspace(*p))
+ end = p;
+
+ /* terminate end */
+ *++end = 0;
+ if (strcasecmp(cmd, "quit") == 0)
+ break;
+
+ /* run line */
+ if ((retval = command_run_line(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)
+ break;
+ }
+
+ context->mode = old_command_mode;
+
+
+ free(buffer);
+
+ return retval;
+}
+
+void command_print_help_line(command_context_t* context, struct command_s *command, int indent)
+{
+ command_t *c;
+ char indents[32] = {0};
+ char *help = "no help available";
+ char name_buf[64];
+ int i;
+
+ for (i = 0; i < indent; i+=2)
+ {
+ indents[i*2] = ' ';
+ indents[i*2+1] = '-';
+ }
+ indents[i*2] = 0;
+
+ if (command->help)
+ help = command->help;
+
+ snprintf(name_buf, 64, command->name);
+ strncat(name_buf, indents, 64);
+ command_print(context, "%20s\t%s", name_buf, help);
+
+ if (command->children)
+ {
+ for (c = command->children; c; c = c->next)
+ {
+ command_print_help_line(context, c, indent + 1);
+ }
+ }
+}
+
+int command_print_help(command_context_t* context, char* name, char** args, int argc)
+{
+ command_t *c;
+
+ for (c = context->commands; c; c = c->next)
+ {
+ if (argc == 1)
+ {
+ if (strncasecmp(c->name, args[0], c->unique_len))
+ continue;
+
+ if (strncasecmp(c->name, args[0], strlen(args[0])))
+ continue;
+ }
+
+ command_print_help_line(context, c, 0);
+ }
+
+ return ERROR_OK;
+}
+
+void command_set_output_handler(command_context_t* context, int (*output_handler)(struct command_context_s *context, char* line), void *priv)
+{
+ context->output_handler = output_handler;
+ context->output_handler_priv = priv;
+}
+
+command_context_t* copy_command_context(command_context_t* context)
+{
+ command_context_t* copy_context = malloc(sizeof(command_context_t));
+
+ *copy_context = *context;
+
+ return copy_context;
+}
+
+int command_done(command_context_t *context)
+{
+ free(context);
+ context = NULL;
+
+ return ERROR_OK;
+}
+
+command_context_t* command_init()
+{
+ command_context_t* context = malloc(sizeof(command_context_t));
+
+ context->mode = COMMAND_EXEC;
+ context->commands = NULL;
+ context->current_target = 0;
+ context->echo = 0;
+ context->output_handler = NULL;
+ context->output_handler_priv = NULL;
+
+ register_command(context, NULL, "help", command_print_help,
+ COMMAND_EXEC, "display this help");
+
+ register_command(context, NULL, "sleep", handle_sleep_command,
+ COMMAND_ANY, "sleep for <n> milliseconds");
+
+ register_command(context, NULL, "time", handle_time_command,
+ COMMAND_ANY, "time <cmd + args> - execute <cmd + args> and print time it took");
+
+ return context;
+}
+
+/* sleep command sleeps for <n> miliseconds
+ * this is useful in target startup scripts
+ */
+int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ unsigned long duration = 0;
+
+ if (argc == 1)
+ {
+ duration = strtoul(args[0], NULL, 0);
+ usleep(duration * 1000);
+ }
+
+ return ERROR_OK;
+}
+
+int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ if (argc<1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ duration_t duration;
+ char *duration_text;
+ int retval;
+
+ duration_start_measure(&duration);
+
+ retval = find_and_run_command(cmd_ctx, cmd_ctx->commands, args, argc, 0);
+
+ duration_stop_measure(&duration, &duration_text);
+
+ float t=duration.duration.tv_sec;
+ t+=((float)duration.duration.tv_usec / 1000000.0);
+ command_print(cmd_ctx, "%s took %fs", args[0], t);
+
+ free(duration_text);
+
+ return retval;
+}
diff --git a/src/helper/configuration.c b/src/helper/configuration.c
index 1bed1e06..9b9c1816 100644
--- a/src/helper/configuration.c
+++ b/src/helper/configuration.c
@@ -1,104 +1,104 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * 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
-
-#include "types.h"
-#include "command.h"
-#include "configuration.h"
-#include "log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static size_t num_config_files;
-static char** config_file_names;
-
-static size_t num_script_dirs;
-static char** script_search_dirs;
-
-
-void add_script_search_dir (const char *dir)
-{
- num_script_dirs++;
- script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));
-
- script_search_dirs[num_script_dirs-1] = strdup(dir);
- script_search_dirs[num_script_dirs] = NULL;
-}
-
-void add_config_file_name (const char *cfg)
-{
- num_config_files++;
- config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));
-
- config_file_names[num_config_files-1] = strdup(cfg);
- config_file_names[num_config_files] = NULL;
-}
-
-FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)
-{
- FILE *fp = NULL;
- char **search_dirs = script_search_dirs;
- char *dir;
- char full_path[1024];
-
- /* Check absolute and relative to current working dir first.
- * This keeps full_path reporting belowing working. */
- snprintf(full_path, 1024, "%s", file);
- fp = fopen(full_path, mode);
-
- while (!fp)
- {
- dir = *search_dirs++;
-
- if (!dir)
- break;
-
- snprintf(full_path, 1024, "%s/%s", dir, file);
- fp = fopen(full_path, mode);
- }
-
- if (fp)
- command_print(cmd_ctx, "opened %s", full_path);
-
- return fp;
-}
-
-int parse_config_file(struct command_context_s *cmd_ctx)
-{
- char **cfg;
- FILE *config_file;
-
- if (!config_file_names)
- add_config_file_name ("script openocd.cfg");
-
- cfg = config_file_names;
-
- while (*cfg)
- {
- command_run_line(cmd_ctx, *cfg);
- cfg++;
- }
-
- return ERROR_OK;
-}
+/***************************************************************************
+ * Copyright (C) 2004, 2005 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * 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
+
+#include "types.h"
+#include "command.h"
+#include "configuration.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static size_t num_config_files;
+static char** config_file_names;
+
+static size_t num_script_dirs;
+static char** script_search_dirs;
+
+
+void add_script_search_dir (const char *dir)
+{
+ num_script_dirs++;
+ script_search_dirs = (char **)realloc(script_search_dirs, (num_script_dirs+1) * sizeof (char *));
+
+ script_search_dirs[num_script_dirs-1] = strdup(dir);
+ script_search_dirs[num_script_dirs] = NULL;
+}
+
+void add_config_file_name (const char *cfg)
+{
+ num_config_files++;
+ config_file_names = (char **)realloc(config_file_names, (num_config_files+1) * sizeof (char *));
+
+ config_file_names[num_config_files-1] = strdup(cfg);
+ config_file_names[num_config_files] = NULL;
+}
+
+FILE *open_file_from_path (command_context_t *cmd_ctx, char *file, char *mode)
+{
+ FILE *fp = NULL;
+ char **search_dirs = script_search_dirs;
+ char *dir;
+ char full_path[1024];
+
+ /* Check absolute and relative to current working dir first.
+ * This keeps full_path reporting belowing working. */
+ snprintf(full_path, 1024, "%s", file);
+ fp = fopen(full_path, mode);
+
+ while (!fp)
+ {
+ dir = *search_dirs++;
+
+ if (!dir)
+ break;
+
+ snprintf(full_path, 1024, "%s/%s", dir, file);
+ fp = fopen(full_path, mode);
+ }
+
+ if (fp)
+ command_print(cmd_ctx, "opened %s", full_path);
+
+ return fp;
+}
+
+int parse_config_file(struct command_context_s *cmd_ctx)
+{
+ char **cfg;
+ FILE *config_file;
+
+ if (!config_file_names)
+ add_config_file_name ("script openocd.cfg");
+
+ cfg = config_file_names;
+
+ while (*cfg)
+ {
+ command_run_line(cmd_ctx, *cfg);
+ cfg++;
+ }
+
+ return ERROR_OK;
+}
diff --git a/src/helper/log.c b/src/helper/log.c
index 90077ea3..861e4b37 100644
--- a/src/helper/log.c
+++ b/src/helper/log.c
@@ -1,248 +1,248 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * 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
-
-#include "log.h"
-#include "configuration.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
-
-int debug_level = -1;
-
-static FILE* log_output;
-static log_callback_t *log_callbacks = NULL;
-
-static time_t start;
-
-static char *log_strings[5] =
-{
- "User: ",
- "Error: ",
- "Warning:",
- "Info: ",
- "Debug: "
-};
-
-void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
-{
- static int count = 0;
- count++;
- va_list args;
- char buffer[512];
- log_callback_t *cb;
-
- if (level > debug_level)
- return;
-
- va_start(args, format);
- vsnprintf(buffer, 512, format, args);
- va_end(args);
-
- if (level == LOG_OUTPUT)
- {
- /* do not prepend any headers, just print out what we were given and return */
- fputs(buffer, log_output);
- fflush(log_output);
- return;
- }
-
- char *f = strrchr(file, '/');
- if (f != NULL)
- file = f + 1;
-
- if (debug_level >= LOG_DEBUG)
- {
- /* print with count and time information */
- time_t t=time(NULL)-start;
- fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
- }
- else
- {
- /* do not print count and time */
- fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer);
- }
-
- fflush(log_output);
-
- /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */
- if (level <= LOG_INFO)
- {
- for (cb = log_callbacks; cb; cb = cb->next)
- {
- va_start(args, format);
- cb->fn(cb->priv, file, line, function, format, args);
- va_end(args);
- }
- }
-}
-
-/* change the current debug level on the fly
- * 0: only ERRORS
- * 1: + WARNINGS
- * 2: + INFORMATIONAL MSGS
- * 3: + DEBUG MSGS
- */
-int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
- if (argc == 0)
- command_print(cmd_ctx, "debug_level: %i", debug_level);
-
- if (argc > 0)
- debug_level = strtoul(args[0], NULL, 0);
-
- if (debug_level < 0)
- debug_level = 0;
-
- if (debug_level > 3)
- debug_level = 3;
-
- return ERROR_OK;
-}
-
-int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
- if (argc == 1)
- {
- FILE* file = fopen(args[0], "w");
-
- if (file)
- {
- log_output = file;
- }
- }
-
- return ERROR_OK;
-}
-
-int log_register_commands(struct command_context_s *cmd_ctx)
-{
- start = time(NULL);
- register_command(cmd_ctx, NULL, "log_output", handle_log_output_command,
- COMMAND_ANY, "redirect logging to <file> (default: stderr)");
- register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command,
- COMMAND_ANY, "adjust debug level <0-3>");
-
- return ERROR_OK;
-}
-
-int log_init(struct command_context_s *cmd_ctx)
-{
- /* set defaults for daemon configuration, if not set by cmdline or cfgfile */
- if (debug_level == -1)
- debug_level = LOG_INFO;
-
- if (log_output == NULL)
- {
- log_output = stderr;
- }
-
- return ERROR_OK;
-}
-
-int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
-{
- log_output = output;
- return ERROR_OK;
-}
-
-/* add/remove log callback handler */
-int log_add_callback(log_callback_fn fn, void *priv)
-{
- log_callback_t *cb;
-
- /* prevent the same callback to be registered more than once, just for sure */
- for (cb = log_callbacks; cb; cb = cb->next)
- {
- if (cb->fn == fn && cb->priv == priv)
- return ERROR_INVALID_ARGUMENTS;
- }
-
- /* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */
- if ((cb = malloc(sizeof(log_callback_t))) == NULL)
- return ERROR_BUF_TOO_SMALL;
-
- /* add item to the beginning of the linked list */
- cb->fn = fn;
- cb->priv = priv;
- cb->next = log_callbacks;
- log_callbacks = cb;
-
- return ERROR_OK;
-}
-
-int log_remove_callback(log_callback_fn fn, void *priv)
-{
- log_callback_t *cb, **p;
-
- for (p = &log_callbacks; cb = *p; p = &(*p)->next)
- {
- if (cb->fn == fn && cb->priv == priv)
- {
- *p = cb->next;
- free(cb);
- return ERROR_OK;
- }
- }
-
- /* no such item */
- return ERROR_INVALID_ARGUMENTS;
-}
-
-/* return allocated string w/printf() result */
-char *alloc_printf(const char *fmt, va_list ap)
-{
- char *string = NULL;
-
- /* start by 0 to exercise all the code paths. Need minimum 2 bytes to
- * fit 1 char and 0 terminator. */
- int size = 0;
- int first = 1;
- for (;;)
- {
- if ((string == NULL) || (!first))
- {
- size = size * 2 + 2;
- char *t = string;
- string = realloc(string, size);
- if (string == NULL)
- {
- if (t != NULL)
- free(t);
- return NULL;
- }
- }
-
- int ret;
- ret = vsnprintf(string, size, fmt, ap);
- /* NB! The result of the vsnprintf() might be an *EMPTY* string! */
- if ((ret >= 0) && ((ret + 1) < size))
- {
- return string;
- }
- /* there was just enough or not enough space, allocate more. */
- first = 0;
- }
-}
+/***************************************************************************
+ * Copyright (C) 2005 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * 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
+
+#include "log.h"
+#include "configuration.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+int debug_level = -1;
+
+static FILE* log_output;
+static log_callback_t *log_callbacks = NULL;
+
+static time_t start;
+
+static char *log_strings[5] =
+{
+ "User: ",
+ "Error: ",
+ "Warning:",
+ "Info: ",
+ "Debug: "
+};
+
+void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...)
+{
+ static int count = 0;
+ count++;
+ va_list args;
+ char buffer[512];
+ log_callback_t *cb;
+
+ if (level > debug_level)
+ return;
+
+ va_start(args, format);
+ vsnprintf(buffer, 512, format, args);
+ va_end(args);
+
+ if (level == LOG_OUTPUT)
+ {
+ /* do not prepend any headers, just print out what we were given and return */
+ fputs(buffer, log_output);
+ fflush(log_output);
+ return;
+ }
+
+ char *f = strrchr(file, '/');
+ if (f != NULL)
+ file = f + 1;
+
+ if (debug_level >= LOG_DEBUG)
+ {
+ /* print with count and time information */
+ time_t t=time(NULL)-start;
+ fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer);
+ }
+ else
+ {
+ /* do not print count and time */
+ fprintf(log_output, "%s %s:%d %s(): %s\n", log_strings[level+1], file, line, function, buffer);
+ }
+
+ fflush(log_output);
+
+ /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */
+ if (level <= LOG_INFO)
+ {
+ for (cb = log_callbacks; cb; cb = cb->next)
+ {
+ va_start(args, format);
+ cb->fn(cb->priv, file, line, function, format, args);
+ va_end(args);
+ }
+ }
+}
+
+/* change the current debug level on the fly
+ * 0: only ERRORS
+ * 1: + WARNINGS
+ * 2: + INFORMATIONAL MSGS
+ * 3: + DEBUG MSGS
+ */
+int handle_debug_level_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ if (argc == 0)
+ command_print(cmd_ctx, "debug_level: %i", debug_level);
+
+ if (argc > 0)
+ debug_level = strtoul(args[0], NULL, 0);
+
+ if (debug_level < 0)
+ debug_level = 0;
+
+ if (debug_level > 3)
+ debug_level = 3;
+
+ return ERROR_OK;
+}
+
+int handle_log_output_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ if (argc == 1)
+ {
+ FILE* file = fopen(args[0], "w");
+
+ if (file)
+ {
+ log_output = file;
+ }
+ }
+
+ return ERROR_OK;
+}
+
+int log_register_commands(struct command_context_s *cmd_ctx)
+{
+ start = time(NULL);
+ register_command(cmd_ctx, NULL, "log_output", handle_log_output_command,
+ COMMAND_ANY, "redirect logging to <file> (default: stderr)");
+ register_command(cmd_ctx, NULL, "debug_level", handle_debug_level_command,
+ COMMAND_ANY, "adjust debug level <0-3>");
+
+ return ERROR_OK;
+}
+
+int log_init(struct command_context_s *cmd_ctx)
+{
+ /* set defaults for daemon configuration, if not set by cmdline or cfgfile */
+ if (debug_level == -1)
+ debug_level = LOG_INFO;
+
+ if (log_output == NULL)
+ {
+ log_output = stderr;
+ }
+
+ return ERROR_OK;
+}
+
+int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
+{
+ log_output = output;
+ return ERROR_OK;
+}
+
+/* add/remove log callback handler */
+int log_add_callback(log_callback_fn fn, void *priv)
+{
+ log_callback_t *cb;
+
+ /* prevent the same callback to be registered more than once, just for sure */
+ for (cb = log_callbacks; cb; cb = cb->next)
+ {
+ if (cb->fn == fn && cb->priv == priv)
+ return ERROR_INVALID_ARGUMENTS;
+ }
+
+ /* alloc memory, it is safe just to return in case of an error, no need for the caller to check this */
+ if ((cb = malloc(sizeof(log_callback_t))) == NULL)
+ return ERROR_BUF_TOO_SMALL;
+
+ /* add item to the beginning of the linked list */
+ cb->fn = fn;
+ cb->priv = priv;
+ cb->next = log_callbacks;
+ log_callbacks = cb;
+
+ return ERROR_OK;
+}
+
+int log_remove_callback(log_callback_fn fn, void *priv)
+{
+ log_callback_t *cb, **p;
+
+ for (p = &log_callbacks; cb = *p; p = &(*p)->next)
+ {
+ if (cb->fn == fn && cb->priv == priv)
+ {
+ *p = cb->next;
+ free(cb);
+ return ERROR_OK;
+ }
+ }
+
+ /* no such item */
+ return ERROR_INVALID_ARGUMENTS;
+}
+
+/* return allocated string w/printf() result */
+char *alloc_printf(const char *fmt, va_list ap)
+{
+ char *string = NULL;
+
+ /* start by 0 to exercise all the code paths. Need minimum 2 bytes to
+ * fit 1 char and 0 terminator. */
+ int size = 0;
+ int first = 1;
+ for (;;)
+ {
+ if ((string == NULL) || (!first))
+ {
+ size = size * 2 + 2;
+ char *t = string;
+ string = realloc(string, size);
+ if (string == NULL)
+ {
+ if (t != NULL)
+ free(t);
+ return NULL;
+ }
+ }
+
+ int ret;
+ ret = vsnprintf(string, size, fmt, ap);
+ /* NB! The result of the vsnprintf() might be an *EMPTY* string! */
+ if ((ret >= 0) && ((ret + 1) < size))
+ {
+ return string;
+ }
+ /* there was just enough or not enough space, allocate more. */
+ first = 0;
+ }
+}
diff --git a/src/helper/log.h b/src/helper/log.h
index 61050009..6c7c3de6 100644
--- a/src/helper/log.h
+++ b/src/helper/log.h
@@ -1,113 +1,113 @@
-/***************************************************************************
- * Copyright (C) 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * 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. *
- ***************************************************************************/
-#ifndef ERROR_H
-#define ERROR_H
-
-#include "replacements.h"
-#include "command.h"
-
-#include <stdarg.h>
-
-/* logging priorities
- * LOG_USER - user messages. Could be anything from information
- * to progress messags. These messages do not represent
- * incorrect or unexpected behaviour, just normal execution.
- * LOG_ERROR - fatal errors, that are likely to cause program abort
- * LOG_WARNING - non-fatal errors, that may be resolved later
- * LOG_INFO - state information, etc.
- * LOG_DEBUG - debug statements, execution trace
- */
-enum log_levels
-{
- LOG_OUTPUT = -2,
- LOG_USER = -1,
- LOG_ERROR = 0,
- LOG_WARNING = 1,
- LOG_INFO = 2,
- LOG_DEBUG = 3
-};
-
-extern void log_printf(enum log_levels level, const char *file, int line,
- const char *function, const char *format, ...)
- __attribute__ ((format (printf, 5, 6)));
-extern int log_register_commands(struct command_context_s *cmd_ctx);
-extern int log_init(struct command_context_s *cmd_ctx);
-extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
-
-typedef void (*log_callback_fn)(void *priv, const char *file, int line,
- const char *function, const char *format, va_list args);
-
-typedef struct log_callback_s
-{
- log_callback_fn fn;
- void *priv;
- struct log_callback_s *next;
-} log_callback_t;
-
-extern int log_add_callback(log_callback_fn fn, void *priv);
-extern int log_remove_callback(log_callback_fn fn, void *priv);
-
-char *alloc_printf(const char *fmt, va_list ap);
-
-extern int debug_level;
-
-/* Avoid fn call and building parameter list if we're not outputting the information.
- * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */
-
-#define DEBUG(expr ...) \
- do { if (debug_level >= LOG_DEBUG) \
- log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
- } while(0)
-
-#define INFO(expr ...) \
- do { if (debug_level >= LOG_INFO) \
- log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \
- } while(0)
-
-#define WARNING(expr ...) \
- do { \
- log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \
- } while(0)
-
-#define ERROR(expr ...) \
- do { \
- log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \
- } while(0)
-
-#define USER(expr ...) \
- do { \
- log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \
- } while(0)
-
-#define OUTPUT(expr ...) \
- do { \
- log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \
- } while(0)
-
-
-/* general failures
- * error codes < 100
- */
-#define ERROR_OK (0)
-#define ERROR_INVALID_ARGUMENTS (-1)
-#define ERROR_NO_CONFIG_FILE (-2)
-#define ERROR_BUF_TOO_SMALL (-3)
-
-#endif /* LOG_H */
+/***************************************************************************
+ * Copyright (C) 2005 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * 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. *
+ ***************************************************************************/
+#ifndef ERROR_H
+#define ERROR_H
+
+#include "replacements.h"
+#include "command.h"
+
+#include <stdarg.h>
+
+/* logging priorities
+ * LOG_USER - user messages. Could be anything from information
+ * to progress messags. These messages do not represent
+ * incorrect or unexpected behaviour, just normal execution.
+ * LOG_ERROR - fatal errors, that are likely to cause program abort
+ * LOG_WARNING - non-fatal errors, that may be resolved later
+ * LOG_INFO - state information, etc.
+ * LOG_DEBUG - debug statements, execution trace
+ */
+enum log_levels
+{
+ LOG_OUTPUT = -2,
+ LOG_USER = -1,
+ LOG_ERROR = 0,
+ LOG_WARNING = 1,
+ LOG_INFO = 2,
+ LOG_DEBUG = 3
+};
+
+extern void log_printf(enum log_levels level, const char *file, int line,
+ const char *function, const char *format, ...)
+ __attribute__ ((format (printf, 5, 6)));
+extern int log_register_commands(struct command_context_s *cmd_ctx);
+extern int log_init(struct command_context_s *cmd_ctx);
+extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
+
+typedef void (*log_callback_fn)(void *priv, const char *file, int line,
+ const char *function, const char *format, va_list args);
+
+typedef struct log_callback_s
+{
+ log_callback_fn fn;
+ void *priv;
+ struct log_callback_s *next;
+} log_callback_t;
+
+extern int log_add_callback(log_callback_fn fn, void *priv);
+extern int log_remove_callback(log_callback_fn fn, void *priv);
+
+char *alloc_printf(const char *fmt, va_list ap);
+
+extern int debug_level;
+
+/* Avoid fn call and building parameter list if we're not outputting the information.
+ * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */
+
+#define DEBUG(expr ...) \
+ do { if (debug_level >= LOG_DEBUG) \
+ log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
+ } while(0)
+
+#define INFO(expr ...) \
+ do { if (debug_level >= LOG_INFO) \
+ log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \
+ } while(0)
+
+#define WARNING(expr ...) \
+ do { \
+ log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \
+ } while(0)
+
+#define ERROR(expr ...) \
+ do { \
+ log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \
+ } while(0)
+
+#define USER(expr ...) \
+ do { \
+ log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \
+ } while(0)
+
+#define OUTPUT(expr ...) \
+ do { \
+ log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \
+ } while(0)
+
+
+/* general failures
+ * error codes < 100
+ */
+#define ERROR_OK (0)
+#define ERROR_INVALID_ARGUMENTS (-1)
+#define ERROR_NO_CONFIG_FILE (-2)
+#define ERROR_BUF_TOO_SMALL (-3)
+
+#endif /* LOG_H */
diff --git a/src/helper/options.c b/src/helper/options.c
index 4232cb44..89bf1f9b 100644
--- a/src/helper/options.c
+++ b/src/helper/options.c
@@ -1,153 +1,153 @@
-/***************************************************************************
- * Copyright (C) 2004, 2005 by Dominic Rath *
- * Dominic.Rath@gmx.de *
- * *
- * 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
-
-#include "types.h"
-#include "command.h"
-#include "configuration.h"
-#include "log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-
-
-static int help_flag;
-
-static struct option long_options[] =
-{
- {"help", no_argument, &help_flag, 1},
-
- {"debug", optional_argument, 0, 'd'},
- {"file", required_argument, 0, 'f'},
- {"search", required_argument, 0, 's'},
- {"log_output", required_argument, 0, 'l'},
- {"command", required_argument, 0, 'c'},
-
- {0, 0, 0, 0}
-};
-
-
-
-int configuration_output_handler(struct command_context_s *context, char* line)
-{
- INFO(line);
-
- return ERROR_OK;
-}
-
-
-int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
-{
- int c;
- char command_buffer[128];
-
- while (1)
- {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long(argc, argv, "hd::l:f:s:c:", long_options, &option_index);
-
- /* Detect the end of the options. */
- if (c == -1)
- break;
-
- switch (c)
- {
- case 0:
- break;
- case 'h': /* --help | -h */
- help_flag = 1;
- break;
- case 'f': /* --file | -f */
- snprintf(command_buffer, 128, "script %s", optarg);
- add_config_file_name(command_buffer);
- break;
- case 's': /* --search | -s */
- add_script_search_dir(optarg);
- break;
- case 'd': /* --debug | -d */
- if (optarg)
- snprintf(command_buffer, 128, "debug_level %s", optarg);
- else
- snprintf(command_buffer, 128, "debug_level 3");
- command_run_line(cmd_ctx, command_buffer);
- break;
- case 'l': /* --log_output | -l */
- if (optarg)
- {
- snprintf(command_buffer, 128, "log_output %s", optarg);
- command_run_line(cmd_ctx, command_buffer);
- }
- break;
- case 'c': /* --command | -c */
- if (optarg)
- {
- add_config_file_name(optarg);
- }
- break;
-
- }
- }
-
- if (help_flag)
- {
- OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
- OUTPUT("--help | -h\tdisplay this help\n");
- OUTPUT("--file | -f\tuse configuration file <name>\n");
- OUTPUT("--search | -s\tdir to search for config files and scripts.\n");
- OUTPUT("--debug | -d\tset debug level <0-3>\n");
- OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
- OUTPUT("--command | -c\trun <command>\n");
- exit(-1);
- }
-
-#ifdef _WIN32
- /* Add the parent of the directory where openocd.exe resides to the
- * config script search path.
- * Directory layout:
- * bin\openocd.exe
- * lib\openocd
- * event\at91eb40a_reset.cfg
- * target\at91eb40a.cfg
- */
- {
- char strExePath [MAX_PATH];
- GetModuleFileName (NULL, strExePath, MAX_PATH);
- /* Either this code will *always* work or it will SEGFAULT giving
- * excellent information on the culprit.
- */
- *strrchr(strExePath, '\\')=0;
- strcat(strExePath, "\\..");
- add_script_search_dir(strExePath);
- }
-#else
- /* Add dir for openocd supplied scripts last so that user can over
- ride those scripts if desired. */
- add_script_search_dir(PKGDATADIR);
- add_script_search_dir(PKGLIBDIR);
-#endif
-
- return ERROR_OK;
-}
+/***************************************************************************
+ * Copyright (C) 2004, 2005 by Dominic Rath *
+ * Dominic.Rath@gmx.de *
+ * *
+ * 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
+
+#include "types.h"
+#include "command.h"
+#include "configuration.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+
+
+static int help_flag;
+
+static struct option long_options[] =
+{
+ {"help", no_argument, &help_flag, 1},
+
+ {"debug", optional_argument, 0, 'd'},
+ {"file", required_argument, 0, 'f'},
+ {"search", required_argument, 0, 's'},
+ {"log_output", required_argument, 0, 'l'},
+ {"command", required_argument, 0, 'c'},
+
+ {0, 0, 0, 0}
+};
+
+
+
+int configuration_output_handler(struct command_context_s *context, char* line)
+{
+ INFO(line);
+
+ return ERROR_OK;
+}
+
+
+int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[])
+{
+ int c;
+ char command_buffer[128];
+
+ while (1)
+ {
+ /* getopt_long stores the option index here. */
+ int option_index = 0;
+
+ c = getopt_long(argc, argv, "hd::l:f:s:c:", long_options, &option_index);
+
+ /* Detect the end of the options. */
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ break;
+ case 'h': /* --help | -h */
+ help_flag = 1;
+ break;
+ case 'f': /* --file | -f */
+ snprintf(command_buffer, 128, "script %s", optarg);
+ add_config_file_name(command_buffer);
+ break;
+ case 's': /* --search | -s */
+ add_script_search_dir(optarg);
+ break;
+ case 'd': /* --debug | -d */
+ if (optarg)
+ snprintf(command_buffer, 128, "debug_level %s", optarg);
+ else
+ snprintf(command_buffer, 128, "debug_level 3");
+ command_run_line(cmd_ctx, command_buffer);
+ break;
+ case 'l': /* --log_output | -l */
+ if (optarg)
+ {
+ snprintf(command_buffer, 128, "log_output %s", optarg);
+ command_run_line(cmd_ctx, command_buffer);
+ }
+ break;
+ case 'c': /* --command | -c */
+ if (optarg)
+ {
+ add_config_file_name(optarg);
+ }
+ break;
+
+ }
+ }
+
+ if (help_flag)
+ {
+ OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
+ OUTPUT("--help | -h\tdisplay this help\n");
+ OUTPUT("--file | -f\tuse configuration file <name>\n");
+ OUTPUT("--search | -s\tdir to search for config files and scripts.\n");
+ OUTPUT("--debug | -d\tset debug level <0-3>\n");
+ OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
+ OUTPUT("--command | -c\trun <command>\n");
+ exit(-1);
+ }
+
+#ifdef _WIN32
+ /* Add the parent of the directory where openocd.exe resides to the
+ * config script search path.
+ * Directory layout:
+ * bin\openocd.exe
+ * lib\openocd
+ * event\at91eb40a_reset.cfg
+ * target\at91eb40a.cfg
+ */
+ {
+ char strExePath [MAX_PATH];
+ GetModuleFileName (NULL, strExePath, MAX_PATH);
+ /* Either this code will *always* work or it will SEGFAULT giving
+ * excellent information on the culprit.
+ */
+ *strrchr(strExePath, '\\')=0;
+ strcat(strExePath, "\\..");
+ add_script_search_dir(strExePath);
+ }
+#else
+ /* Add dir for openocd supplied scripts last so that user can over
+ ride those scripts if desired. */
+ add_script_search_dir(PKGDATADIR);
+ add_script_search_dir(PKGLIBDIR);
+#endif
+
+ return ERROR_OK;
+}
diff --git a/src/helper/replacements.h b/src/helper/replacements.h
index 84705c52..296afdb6 100644
--- a/src/helper/replacements.h
+++ b/src/helper/replacements.h
@@ -67,38 +67,38 @@ struct timezone {
};
extern int gettimeofday(struct timeval *tv, struct timezone *tz);
-#endif
-
+#endif
+
/**** clear_malloc & fill_malloc ****/
void *clear_malloc(size_t size);
void *fill_malloc(size_t size);
-
-/*
- * Now you have 3 ways for the malloc function:
- *
- * 1. Do not change anything, use the original malloc
- *
- * 2. Use the clear_malloc function instead of the original malloc.
- * In this case you must use the following define:
- * #define malloc((_a)) clear_malloc((_a))
- *
- * 3. Use the fill_malloc function instead of the original malloc.
- * In this case you must use the following define:
- * #define malloc((_a)) fill_malloc((_a))
- *
- * We have figured out that there could exist some malloc problems
- * where variables are using without to be initialise. To find this
- * places, use the fill_malloc function. With this function we want
- * to initialize memory to some known bad state. This is quite easily
- * spotted in the debugger and will trap to an invalid address.
- *
- * clear_malloc can be used if you want to set not initialise
- * variable to 0.
- *
- * If you do not want to change the malloc function, to not use one of
- * the following macros. Which is the default way.
- */
-
+
+/*
+ * Now you have 3 ways for the malloc function:
+ *
+ * 1. Do not change anything, use the original malloc
+ *
+ * 2. Use the clear_malloc function instead of the original malloc.
+ * In this case you must use the following define:
+ * #define malloc((_a)) clear_malloc((_a))
+ *
+ * 3. Use the fill_malloc function instead of the original malloc.
+ * In this case you must use the following define:
+ * #define malloc((_a)) fill_malloc((_a))
+ *
+ * We have figured out that there could exist some malloc problems
+ * where variables are using without to be initialise. To find this
+ * places, use the fill_malloc function. With this function we want
+ * to initialize memory to some known bad state. This is quite easily
+ * spotted in the debugger and will trap to an invalid address.
+ *
+ * clear_malloc can be used if you want to set not initialise
+ * variable to 0.
+ *
+ * If you do not want to change the malloc function, to not use one of
+ * the following macros. Which is the default way.
+ */
+
//#define malloc(_a) clear_malloc(_a)
//#define malloc(_a) fill_malloc(_a)