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:
parent
375c5f85d2
commit
7f1944a478
|
@ -374,7 +374,7 @@ int find_and_run_command(command_context_t *context, command_t *commands, char *
|
|||
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;
|
||||
char *words[128] = {0};
|
||||
|
@ -414,17 +414,6 @@ static int command_run_line_inner(command_context_t *context, char *line)
|
|||
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 retval = ERROR_OK;
|
||||
|
@ -467,7 +456,7 @@ int command_run_file(command_context_t *context, FILE *file, enum command_mode m
|
|||
break;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,17 +33,10 @@
|
|||
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] =
|
||||
{
|
||||
"User: ",
|
||||
|
@ -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,16 +87,17 @@ 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)
|
||||
{
|
||||
for (cb = log_callbacks; cb; cb = cb->next)
|
||||
{
|
||||
va_start(args, format);
|
||||
callback(privData, file, line, function, format, args);
|
||||
cb->fn(cb->priv, file, line, function, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* change the current debug level on the fly
|
||||
* 0: only ERRORS
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
*/
|
||||
enum log_levels
|
||||
{
|
||||
LOG_OUTPUT = -2,
|
||||
LOG_USER = -1,
|
||||
LOG_ERROR = 0,
|
||||
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 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);
|
||||
|
||||
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;
|
||||
|
||||
|
@ -85,6 +96,11 @@ extern int debug_level;
|
|||
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
|
||||
|
@ -94,6 +110,4 @@ extern int debug_level;
|
|||
#define ERROR_NO_CONFIG_FILE (-2)
|
||||
#define ERROR_BUF_TOO_SMALL (-3)
|
||||
|
||||
char *allocPrintf(const char *fmt, va_list ap);
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
|
|||
else if (reply == '-')
|
||||
{
|
||||
/* Stop sending output packets for now */
|
||||
log_setCallback(NULL, NULL);
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
WARNING("negative reply, retrying");
|
||||
}
|
||||
else if (reply == 0x3)
|
||||
|
@ -316,7 +316,7 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
|
|||
else if (reply == '-')
|
||||
{
|
||||
/* Stop sending output packets for now */
|
||||
log_setCallback(NULL, NULL);
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
WARNING("negative reply, retrying");
|
||||
}
|
||||
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)
|
||||
{
|
||||
/* stop forwarding log packets! */
|
||||
log_setCallback(NULL, NULL);
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
|
||||
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);
|
||||
log_setCallback(NULL, NULL);
|
||||
log_remove_callback(gdb_log_callback, connection);
|
||||
|
||||
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;
|
||||
|
||||
/* 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();
|
||||
command_run_line(cmd_ctx, cmd);
|
||||
free(cmd);
|
||||
|
@ -1808,7 +1808,7 @@ static void gdb_log_callback(void *priv, const char *file, int line,
|
|||
return;
|
||||
}
|
||||
|
||||
char *t = allocPrintf(format, args);
|
||||
char *t = alloc_printf(format, args);
|
||||
if (t == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1886,7 +1886,7 @@ int gdb_input_inner(connection_t *connection)
|
|||
* forward log output until the target is halted */
|
||||
gdb_connection_t *gdb_con = connection->priv;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -92,7 +92,7 @@ void telnet_log_callback(void *priv, const char *file, int line,
|
|||
const char *function, const char *format, va_list args)
|
||||
{
|
||||
connection_t *connection = priv;
|
||||
char *t = allocPrintf(format, args);
|
||||
char *t = alloc_printf(format, args);
|
||||
char *t2;
|
||||
if (t == NULL)
|
||||
return;
|
||||
|
@ -108,7 +108,6 @@ void telnet_log_callback(void *priv, const char *file, int line,
|
|||
t2=endline+1;
|
||||
} while (endline);
|
||||
|
||||
|
||||
free(t);
|
||||
}
|
||||
|
||||
|
@ -292,18 +291,18 @@ int telnet_input(connection_t *connection)
|
|||
continue;
|
||||
}
|
||||
|
||||
log_setCallback(telnet_log_callback, connection);
|
||||
log_add_callback(telnet_log_callback, connection);
|
||||
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)
|
||||
{
|
||||
return ERROR_SERVER_REMOTE_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
t_con->suppress_prompt = 0;
|
||||
|
||||
/* Save only non-blank lines in the history */
|
||||
if (t_con->line_size > 0)
|
||||
|
|
Loading…
Reference in New Issue