- multiple log listeners - added OUTPUT() to replace printf - fix formatting git-svn-id: svn://svn.berlios.de/openocd/trunk@346 b42882b7-edfa-0310-969c-e2dbd0fdcd60tags/v0.1.0
@@ -33,18 +33,11 @@ | |||
int debug_level = -1; | |||
static FILE* log_output; | |||
static log_callback_t *log_callbacks = NULL; | |||
static void *privData; | |||
static logCallback callback; | |||
static time_t start; | |||
void log_setCallback(logCallback c, void *p) | |||
{ | |||
callback = c; | |||
privData = p; | |||
} | |||
static char *log_strings[5] = | |||
static char *log_strings[5] = | |||
{ | |||
"User: ", | |||
"Error: ", | |||
@@ -59,12 +52,22 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f | |||
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) | |||
@@ -84,14 +87,15 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f | |||
fflush(log_output); | |||
va_end(args); | |||
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ | |||
if (callback && (level <= LOG_INFO)) | |||
if (level <= LOG_INFO) | |||
{ | |||
va_start(args, format); | |||
callback(privData, file, line, function, format, args); | |||
va_end(args); | |||
for (cb = log_callbacks; cb; cb = cb->next) | |||
{ | |||
va_start(args, format); | |||
cb->fn(cb->priv, file, line, function, format, args); | |||
va_end(args); | |||
} | |||
} | |||
} | |||
@@ -164,8 +168,51 @@ int set_log_output(struct command_context_s *cmd_ctx, FILE *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 *allocPrintf(const char *fmt, va_list ap) | |||
char *alloc_printf(const char *fmt, va_list ap) | |||
{ | |||
char *string = NULL; | |||
@@ -1,99 +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_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 (*logCallback)(void *priv, const char *file, int line, | |||
const char *function, const char *format, va_list args); | |||
extern void log_setCallback(logCallback callback, void *priv); | |||
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) | |||
/* 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) | |||
char *allocPrintf(const char *fmt, va_list ap); | |||
#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 */ |
@@ -113,13 +113,13 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[] | |||
if (help_flag) | |||
{ | |||
printf("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n"); | |||
printf("--help | -h\tdisplay this help\n"); | |||
printf("--file | -f\tuse configuration file <name>\n"); | |||
printf("--search | -s\tdir to search for config files and scripts.\n"); | |||
printf("--debug | -d\tset debug level <0-3>\n"); | |||
printf("--log_output | -l\tredirect log output to file <name>\n"); | |||
printf("--command | -c\trun <command>\n"); | |||
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); | |||
} | |||
@@ -1,157 +1,157 @@ | |||
/*************************************************************************** | |||
* 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. * | |||
***************************************************************************/ | |||
#define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include "log.h" | |||
#include "types.h" | |||
#include "jtag.h" | |||
#include "configuration.h" | |||
#include "interpreter.h" | |||
#include "xsvf.h" | |||
#include "target.h" | |||
#include "flash.h" | |||
#include "nand.h" | |||
#include "pld.h" | |||
#include "command.h" | |||
#include "server.h" | |||
#include "telnet_server.h" | |||
#include "gdb_server.h" | |||
#include <sys/time.h> | |||
#include <sys/types.h> | |||
#include <strings.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
/* Give TELNET a way to find out what version this is */ | |||
int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | |||
{ | |||
command_print(cmd_ctx, OPENOCD_VERSION); | |||
return ERROR_OK; | |||
} | |||
void exit_handler(void) | |||
{ | |||
/* close JTAG interface */ | |||
if (jtag && jtag->quit) | |||
jtag->quit(); | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | |||
/* initialize commandline interface */ | |||
command_context_t *cmd_ctx, *cfg_cmd_ctx; | |||
cmd_ctx = command_init(); | |||
register_command(cmd_ctx, NULL, "version", handle_version_command, | |||
COMMAND_EXEC, "show OpenOCD version"); | |||
/* register subsystem commands */ | |||
server_register_commands(cmd_ctx); | |||
telnet_register_commands(cmd_ctx); | |||
gdb_register_commands(cmd_ctx); | |||
log_register_commands(cmd_ctx); | |||
jtag_register_commands(cmd_ctx); | |||
interpreter_register_commands(cmd_ctx); | |||
xsvf_register_commands(cmd_ctx); | |||
target_register_commands(cmd_ctx); | |||
flash_register_commands(cmd_ctx); | |||
nand_register_commands(cmd_ctx); | |||
pld_register_commands(cmd_ctx); | |||
if (log_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("log init complete"); | |||
printf( OPENOCD_VERSION ); | |||
printf( "\n$URL$\n"); | |||
DEBUG( OPENOCD_VERSION ); | |||
/*************************************************************************** | |||
* 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. * | |||
***************************************************************************/ | |||
#define OPENOCD_VERSION "Open On-Chip Debugger " VERSION " (" PKGBLDDATE ") svn:" PKGBLDREV | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include "log.h" | |||
#include "types.h" | |||
#include "jtag.h" | |||
#include "configuration.h" | |||
#include "interpreter.h" | |||
#include "xsvf.h" | |||
#include "target.h" | |||
#include "flash.h" | |||
#include "nand.h" | |||
#include "pld.h" | |||
#include "command.h" | |||
#include "server.h" | |||
#include "telnet_server.h" | |||
#include "gdb_server.h" | |||
#include <sys/time.h> | |||
#include <sys/types.h> | |||
#include <strings.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <errno.h> | |||
/* Give TELNET a way to find out what version this is */ | |||
int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | |||
{ | |||
command_print(cmd_ctx, OPENOCD_VERSION); | |||
return ERROR_OK; | |||
} | |||
void exit_handler(void) | |||
{ | |||
/* close JTAG interface */ | |||
if (jtag && jtag->quit) | |||
jtag->quit(); | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | |||
/* initialize commandline interface */ | |||
command_context_t *cmd_ctx, *cfg_cmd_ctx; | |||
cmd_ctx = command_init(); | |||
register_command(cmd_ctx, NULL, "version", handle_version_command, | |||
COMMAND_EXEC, "show OpenOCD version"); | |||
/* register subsystem commands */ | |||
server_register_commands(cmd_ctx); | |||
telnet_register_commands(cmd_ctx); | |||
gdb_register_commands(cmd_ctx); | |||
log_register_commands(cmd_ctx); | |||
jtag_register_commands(cmd_ctx); | |||
interpreter_register_commands(cmd_ctx); | |||
xsvf_register_commands(cmd_ctx); | |||
target_register_commands(cmd_ctx); | |||
flash_register_commands(cmd_ctx); | |||
nand_register_commands(cmd_ctx); | |||
pld_register_commands(cmd_ctx); | |||
if (log_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("log init complete"); | |||
printf( OPENOCD_VERSION ); | |||
printf( "\n$URL$\n"); | |||
DEBUG( OPENOCD_VERSION ); | |||
DEBUG( "$URL$"); | |||
cfg_cmd_ctx = copy_command_context(cmd_ctx); | |||
cfg_cmd_ctx->mode = COMMAND_CONFIG; | |||
command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL); | |||
if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
if (parse_config_file(cfg_cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
command_done(cfg_cmd_ctx); | |||
command_set_output_handler(cmd_ctx, configuration_output_handler, NULL); | |||
atexit(exit_handler); | |||
if (jtag_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("jtag init complete"); | |||
if (target_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("target init complete"); | |||
if (flash_init_drivers(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("flash init complete"); | |||
if (nand_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("NAND init complete"); | |||
if (pld_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("pld init complete"); | |||
/* initialize tcp server */ | |||
server_init(); | |||
/* initialize telnet subsystem */ | |||
telnet_init("Open On-Chip Debugger"); | |||
gdb_init(); | |||
/* call any target resets */ | |||
if (target_init_reset(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("target init reset complete"); | |||
/* handle network connections */ | |||
server_loop(cmd_ctx); | |||
/* shut server down */ | |||
server_quit(); | |||
/* free commandline interface */ | |||
command_done(cmd_ctx); | |||
return EXIT_SUCCESS; | |||
} | |||
cfg_cmd_ctx = copy_command_context(cmd_ctx); | |||
cfg_cmd_ctx->mode = COMMAND_CONFIG; | |||
command_set_output_handler(cfg_cmd_ctx, configuration_output_handler, NULL); | |||
if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
if (parse_config_file(cfg_cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
command_done(cfg_cmd_ctx); | |||
command_set_output_handler(cmd_ctx, configuration_output_handler, NULL); | |||
atexit(exit_handler); | |||
if (jtag_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("jtag init complete"); | |||
if (target_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("target init complete"); | |||
if (flash_init_drivers(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("flash init complete"); | |||
if (nand_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("NAND init complete"); | |||
if (pld_init(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("pld init complete"); | |||
/* initialize tcp server */ | |||
server_init(); | |||
/* initialize telnet subsystem */ | |||
telnet_init("Open On-Chip Debugger"); | |||
gdb_init(); | |||
/* call any target resets */ | |||
if (target_init_reset(cmd_ctx) != ERROR_OK) | |||
return EXIT_FAILURE; | |||
DEBUG("target init reset complete"); | |||
/* handle network connections */ | |||
server_loop(cmd_ctx); | |||
/* shut server down */ | |||
server_quit(); | |||
/* free commandline interface */ | |||
command_done(cmd_ctx); | |||
return EXIT_SUCCESS; | |||
} |