Pavel Chromy

- multiple log listeners
- added OUTPUT() to replace printf
- fix formatting

git-svn-id: svn://svn.berlios.de/openocd/trunk@346 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
oharboe 2008-02-25 17:32:53 +00:00
parent 375c5f85d2
commit 7f1944a478
7 changed files with 3684 additions and 3635 deletions

View File

@ -374,7 +374,7 @@ int find_and_run_command(command_context_t *context, command_t *commands, char *
return ERROR_OK; return ERROR_OK;
} }
static int command_run_line_inner(command_context_t *context, char *line) int command_run_line(command_context_t *context, char *line)
{ {
int nwords; int nwords;
char *words[128] = {0}; char *words[128] = {0};
@ -414,17 +414,6 @@ static int command_run_line_inner(command_context_t *context, char *line)
return retval; return retval;
} }
int command_run_line(command_context_t *context, char *line)
{
int retval=command_run_line_inner(context, line);
// we don't want any dangling callbacks!
//
// Capturing output from logging is *very* loosly modeled on C/C++ exceptions.
// the capture must be set up at function entry and
// stops when the function call returns
log_setCallback(NULL, NULL);
return retval;
}
int command_run_file(command_context_t *context, FILE *file, enum command_mode mode) int command_run_file(command_context_t *context, FILE *file, enum command_mode mode)
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
@ -467,7 +456,7 @@ int command_run_file(command_context_t *context, FILE *file, enum command_mode m
break; break;
/* run line */ /* run line */
if ((retval = command_run_line_inner(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION) if ((retval = command_run_line(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)
break; break;
} }

View File

@ -33,17 +33,10 @@
int debug_level = -1; int debug_level = -1;
static FILE* log_output; static FILE* log_output;
static log_callback_t *log_callbacks = NULL;
static void *privData;
static logCallback callback;
static time_t start; 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: ", "User: ",
@ -59,12 +52,22 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f
count++; count++;
va_list args; va_list args;
char buffer[512]; char buffer[512];
log_callback_t *cb;
if (level > debug_level) if (level > debug_level)
return; return;
va_start(args, format); va_start(args, format);
vsnprintf(buffer, 512, format, args); 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, '/'); char *f = strrchr(file, '/');
if (f != NULL) if (f != NULL)
@ -84,16 +87,17 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f
fflush(log_output); fflush(log_output);
va_end(args);
/* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ /* 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)
{
for (cb = log_callbacks; cb; cb = cb->next)
{ {
va_start(args, format); va_start(args, format);
callback(privData, file, line, function, format, args); cb->fn(cb->priv, file, line, function, format, args);
va_end(args); va_end(args);
} }
} }
}
/* change the current debug level on the fly /* change the current debug level on the fly
* 0: only ERRORS * 0: only ERRORS
@ -164,8 +168,51 @@ int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
return ERROR_OK; 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 */ /* 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; char *string = NULL;

View File

@ -36,6 +36,7 @@
*/ */
enum log_levels enum log_levels
{ {
LOG_OUTPUT = -2,
LOG_USER = -1, LOG_USER = -1,
LOG_ERROR = 0, LOG_ERROR = 0,
LOG_WARNING = 1, LOG_WARNING = 1,
@ -50,10 +51,20 @@ extern int log_register_commands(struct command_context_s *cmd_ctx);
extern int log_init(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); extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
typedef void (*logCallback)(void *priv, const char *file, int line, typedef void (*log_callback_fn)(void *priv, const char *file, int line,
const char *function, const char *format, va_list args); const char *function, const char *format, va_list args);
extern void log_setCallback(logCallback callback, void *priv); 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; extern int debug_level;
@ -85,6 +96,11 @@ extern int debug_level;
log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \ log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \
} while(0) } while(0)
#define OUTPUT(expr ...) \
do { \
log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \
} while(0)
/* general failures /* general failures
* error codes < 100 * error codes < 100
@ -94,6 +110,4 @@ extern int debug_level;
#define ERROR_NO_CONFIG_FILE (-2) #define ERROR_NO_CONFIG_FILE (-2)
#define ERROR_BUF_TOO_SMALL (-3) #define ERROR_BUF_TOO_SMALL (-3)
char *allocPrintf(const char *fmt, va_list ap);
#endif /* LOG_H */ #endif /* LOG_H */

View File

@ -113,13 +113,13 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
if (help_flag) if (help_flag)
{ {
printf("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n"); OUTPUT("Open On-Chip Debugger\n(c) 2005 by Dominic Rath\n\n");
printf("--help | -h\tdisplay this help\n"); OUTPUT("--help | -h\tdisplay this help\n");
printf("--file | -f\tuse configuration file <name>\n"); OUTPUT("--file | -f\tuse configuration file <name>\n");
printf("--search | -s\tdir to search for config files and scripts.\n"); OUTPUT("--search | -s\tdir to search for config files and scripts.\n");
printf("--debug | -d\tset debug level <0-3>\n"); OUTPUT("--debug | -d\tset debug level <0-3>\n");
printf("--log_output | -l\tredirect log output to file <name>\n"); OUTPUT("--log_output | -l\tredirect log output to file <name>\n");
printf("--command | -c\trun <command>\n"); OUTPUT("--command | -c\trun <command>\n");
exit(-1); exit(-1);
} }

View File

@ -303,7 +303,7 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
else if (reply == '-') else if (reply == '-')
{ {
/* Stop sending output packets for now */ /* Stop sending output packets for now */
log_setCallback(NULL, NULL); log_remove_callback(gdb_log_callback, connection);
WARNING("negative reply, retrying"); WARNING("negative reply, retrying");
} }
else if (reply == 0x3) else if (reply == 0x3)
@ -316,7 +316,7 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
else if (reply == '-') else if (reply == '-')
{ {
/* Stop sending output packets for now */ /* Stop sending output packets for now */
log_setCallback(NULL, NULL); log_remove_callback(gdb_log_callback, connection);
WARNING("negative reply, retrying"); WARNING("negative reply, retrying");
} }
else else
@ -579,7 +579,7 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
if (gdb_connection->frontend_state == TARGET_RUNNING) if (gdb_connection->frontend_state == TARGET_RUNNING)
{ {
/* stop forwarding log packets! */ /* stop forwarding log packets! */
log_setCallback(NULL, NULL); log_remove_callback(gdb_log_callback, connection);
if (gdb_connection->ctrl_c) if (gdb_connection->ctrl_c)
{ {
@ -678,7 +678,7 @@ int gdb_connection_closed(connection_t *connection)
} }
target_unregister_event_callback(gdb_target_callback_event_handler, connection); target_unregister_event_callback(gdb_target_callback_event_handler, connection);
log_setCallback(NULL, NULL); log_remove_callback(gdb_log_callback, connection);
return ERROR_OK; return ERROR_OK;
} }
@ -1459,7 +1459,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
cmd[(packet_size - 6)/2] = 0x0; cmd[(packet_size - 6)/2] = 0x0;
/* We want to print all debug output to GDB connection */ /* We want to print all debug output to GDB connection */
log_setCallback(gdb_log_callback, connection); log_add_callback(gdb_log_callback, connection);
target_call_timer_callbacks(); target_call_timer_callbacks();
command_run_line(cmd_ctx, cmd); command_run_line(cmd_ctx, cmd);
free(cmd); free(cmd);
@ -1808,7 +1808,7 @@ static void gdb_log_callback(void *priv, const char *file, int line,
return; return;
} }
char *t = allocPrintf(format, args); char *t = alloc_printf(format, args);
if (t == NULL) if (t == NULL)
return; return;
@ -1886,7 +1886,7 @@ int gdb_input_inner(connection_t *connection)
* forward log output until the target is halted */ * forward log output until the target is halted */
gdb_connection_t *gdb_con = connection->priv; gdb_connection_t *gdb_con = connection->priv;
gdb_con->frontend_state = TARGET_RUNNING; gdb_con->frontend_state = TARGET_RUNNING;
log_setCallback(gdb_log_callback, connection); log_add_callback(gdb_log_callback, connection);
gdb_step_continue_packet(connection, target, packet, packet_size); gdb_step_continue_packet(connection, target, packet, packet_size);
} }
break; break;

View File

@ -92,7 +92,7 @@ void telnet_log_callback(void *priv, const char *file, int line,
const char *function, const char *format, va_list args) const char *function, const char *format, va_list args)
{ {
connection_t *connection = priv; connection_t *connection = priv;
char *t = allocPrintf(format, args); char *t = alloc_printf(format, args);
char *t2; char *t2;
if (t == NULL) if (t == NULL)
return; return;
@ -108,7 +108,6 @@ void telnet_log_callback(void *priv, const char *file, int line,
t2=endline+1; t2=endline+1;
} while (endline); } while (endline);
free(t); free(t);
} }
@ -292,18 +291,18 @@ int telnet_input(connection_t *connection)
continue; continue;
} }
log_setCallback(telnet_log_callback, connection); log_add_callback(telnet_log_callback, connection);
t_con->suppress_prompt = 1; t_con->suppress_prompt = 1;
if ((retval = command_run_line(command_context, t_con->line)) != ERROR_OK) retval = command_run_line(command_context, t_con->line);
{
log_remove_callback(telnet_log_callback, connection);
t_con->suppress_prompt = 0;
if (retval == ERROR_COMMAND_CLOSE_CONNECTION) if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
{ {
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
} }
}
t_con->suppress_prompt = 0;
/* Save only non-blank lines in the history */ /* Save only non-blank lines in the history */
if (t_con->line_size > 0) if (t_con->line_size > 0)