From 3d6bcf07921753141a3905ee5619724573460cb3 Mon Sep 17 00:00:00 2001 From: drath Date: Mon, 25 Feb 2008 17:48:04 +0000 Subject: - convert all files to unix line-ending git-svn-id: svn://svn.berlios.de/openocd/trunk@347 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/helper/command.c | 1214 ++++++++++++++++++++++---------------------- src/helper/configuration.c | 208 ++++---- src/helper/log.c | 496 +++++++++--------- src/helper/log.h | 226 ++++----- src/helper/options.c | 306 +++++------ src/helper/replacements.h | 58 +-- 6 files changed, 1254 insertions(+), 1254 deletions(-) (limited to 'src/helper') 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 -#include -#include -#include -#include -#include - -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_start0) - { - /* 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 milliseconds"); - - register_command(context, NULL, "time", handle_time_command, - COMMAND_ANY, "time - execute and print time it took"); - - return context; -} - -/* sleep command sleeps for 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 +#include +#include +#include +#include +#include + +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_start0) + { + /* 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 milliseconds"); + + register_command(context, NULL, "time", handle_time_command, + COMMAND_ANY, "time - execute and print time it took"); + + return context; +} + +/* sleep command sleeps for 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 -#include -#include - -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 +#include +#include + +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 -#include -#include -#include -#include - -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 (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 +#include +#include +#include +#include + +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 (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 - -/* 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 + +/* 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 -#include -#include -#include - - -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 \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 \n"); - OUTPUT("--command | -c\trun \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 +#include +#include +#include + + +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 \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 \n"); + OUTPUT("--command | -c\trun \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) -- cgit v1.2.3