From 67e0aea25850b8286f750e6458e5de741e6cb3b5 Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 29 Feb 2008 11:16:38 +0000 Subject: [PATCH] Summary: passing of variable argument list reduced, strings sent to logging are now formatted just once - more efficient. As a result, ugly string malloc+strcpy are not needed anymore. git-svn-id: svn://svn.berlios.de/openocd/trunk@386 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/helper/command.c | 67 +++++++---------------- src/helper/log.c | 102 ++++++++++++++++++++---------------- src/helper/log.h | 44 +++++----------- src/helper/options.c | 2 +- src/server/gdb_server.c | 18 +++---- src/server/telnet_server.c | 39 +++++++------- src/target/target_request.c | 2 +- 7 files changed, 118 insertions(+), 156 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 0ec54216b5..aa71f0ba18 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -260,66 +260,39 @@ int parse_line(char *line, char *words[], int max_words) return nwords; } -static void command_printv(command_context_t *context, char *format, va_list ap) +void command_print_n(command_context_t *context, char *format, ...) { - char *buffer = NULL; - int n, size = 0; - char *p; - - /* process format string */ - for (;;) - { - 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); - return; - } + char *string; - buffer = p; - - continue; - } - break; - } - - /* vsnprintf failed */ - if (n < 0) + va_list ap; + va_start(ap, format); + + string = alloc_printf(format, ap); + if (string != NULL) { - if (buffer) - free(buffer); - return; + context->output_handler(context, string); + free(string); } - context->output_handler(context, buffer); - - if (buffer) - free(buffer); -} - -void command_print_sameline(command_context_t *context, char *format, ...) -{ - va_list ap; - va_start(ap, format); - command_printv(context, format, ap); va_end(ap); } void command_print(command_context_t *context, char *format, ...) { - char *t=malloc(strlen(format)+2); - strcpy(t, format); - strcat(t, "\n"); + char *string; + va_list ap; va_start(ap, format); - command_printv(context, t, ap); + + string = alloc_printf(format, ap); + if (string != NULL) + { + strcat(string, "\n"); /* alloc_printf guaranteed the buffer to be at least one char longer */ + context->output_handler(context, string); + free(string); + } + va_end(ap); - free(t); - } int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word) diff --git a/src/helper/log.c b/src/helper/log.c index a3e8e816e0..7abebc297c 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -48,17 +48,15 @@ static char *log_strings[5] = static int count = 0; -static void log_printfv(enum log_levels level, const char *file, int line, const char *function, const char *format, va_list args) + +static void log_puts(enum log_levels level, const char *file, int line, const char *function, const char *string) { - char buffer[512]; log_callback_t *cb; - vsnprintf(buffer, 512, format, args); - if (level == LOG_OUTPUT) { /* do not prepend any headers, just print out what we were given and return */ - fputs(buffer, log_output); + fputs(string, log_output); fflush(log_output); return; } @@ -71,12 +69,12 @@ static void log_printfv(enum log_levels level, const char *file, int line, const { /* print with count and time information */ int t=(int)(time(NULL)-start); - fprintf(log_output, "%s %d %d %s:%d %s(): %s", log_strings[level+1], count, t, file, line, function, buffer); + fprintf(log_output, "%s %d %d %s:%d %s(): %s", log_strings[level+1], count, t, file, line, function, string); } else { /* do not print count and time */ - fprintf(log_output, "%s %s:%d %s(): %s", log_strings[level+1], file, line, function, buffer); + fprintf(log_output, "%s %s:%d %s(): %s", log_strings[level+1], file, line, function, string); } fflush(log_output); @@ -84,42 +82,55 @@ static void log_printfv(enum log_levels level, const char *file, int line, const /* Never forward LOG_DEBUG, too verbose and they can be found in the log if need be */ if (level <= LOG_INFO) { + log_callback_t *cb; for (cb = log_callbacks; cb; cb = cb->next) { - cb->fn(cb->priv, file, line, function, format, args); + cb->fn(cb->priv, file, line, function, string); } } } void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) { + char *string; + count++; if (level > debug_level) return; - va_list args; - va_start(args, format); - log_printfv(level, file, line, function, format, args); - va_end(args); - + va_list ap; + va_start(ap, format); + + string = alloc_printf(format, ap); + if (string != NULL) + { + log_puts(level, file, line, function, string); + free(string); + } + + va_end(ap); } -void log_printfnl(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) +void log_printf_lf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) { + char *string; + count++; if (level > debug_level) return; - - char *t=malloc(strlen(format)+2); - strcpy(t, format); - strcat(t, "\n"); - - va_list args; - va_start(args, format); - log_printfv(level, file, line, function, t, args); - va_end(args); - - free(t); + + va_list ap; + va_start(ap, format); + + string = alloc_printf(format, ap); + if (string != NULL) + { + strcat(string, "\n"); /* alloc_printf guaranteed the buffer to be at least one char longer */ + log_puts(level, file, line, function, string); + free(string); + } + + va_end(ap); } /* change the current debug level on the fly @@ -237,35 +248,34 @@ int log_remove_callback(log_callback_fn fn, void *priv) /* return allocated string w/printf() result */ char *alloc_printf(const char *fmt, va_list ap) { + /* no buffer at the beginning, force realloc to do the job */ 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; + /* start with minimal length to exercise all the code paths */ + int size = 1; + for (;;) { - if ((string == NULL) || (!first)) + size *= 2; /* double the buffer size */ + + char *t = string; + string = realloc(string, size); + if (string == NULL) { - size = size * 2 + 2; - char *t = string; - string = realloc(string, size); - if (string == NULL) - { - if (t != NULL) - free(t); - return NULL; - } + if (t != NULL) + free(t); + return NULL; } - + int ret; - ret = vsnprintf(string, size, fmt, ap); + 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; + break; + + /* there was just enough or not enough space, allocate more in the next round */ } + + /* the returned buffer is by principle guaranteed to be at least one character longer */ + return string; } diff --git a/src/helper/log.h b/src/helper/log.h index a53b7f5ed1..c40784474e 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -47,7 +47,7 @@ enum log_levels 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 void log_printfnl(enum log_levels level, const char *file, int line, +extern void log_printf_lf(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); @@ -55,13 +55,13 @@ 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); + const char *function, const char *string); typedef struct log_callback_s { - log_callback_fn fn; + log_callback_fn fn; void *priv; - struct log_callback_s *next; + struct log_callback_s *next; } log_callback_t; extern int log_add_callback(log_callback_fn fn, void *priv); @@ -76,44 +76,28 @@ extern int debug_level; #define DEBUG(expr ...) \ - do { if (debug_level >= LOG_DEBUG) \ - log_printfnl (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) + log_printf_lf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr) #define INFO(expr ...) \ - do { if (debug_level >= LOG_INFO) \ - log_printfnl (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) + log_printf_lf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr) -#define INFO_SAMELINE(expr ...) \ - do { if (debug_level >= LOG_INFO) \ - log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) +#define INFO_N(expr ...) \ + log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr) #define WARNING(expr ...) \ - do { \ - log_printfnl (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) + log_printf_lf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr) #define ERROR(expr ...) \ - do { \ - log_printfnl (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) + log_printf_lf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr) #define USER(expr ...) \ - do { \ - log_printfnl (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) + log_printf_lf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr) -#define USER_SAMELINE(expr ...) \ - do { \ - log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) +#define USER_N(expr ...) \ + log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr) #define OUTPUT(expr ...) \ - do { \ - log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \ - } while(0) + log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr) /* general failures diff --git a/src/helper/options.c b/src/helper/options.c index 6e1f10b779..35ab0f5dfd 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -48,7 +48,7 @@ static struct option long_options[] = int configuration_output_handler(struct command_context_s *context, char* line) { - INFO_SAMELINE(line); + INFO_N(line); return ERROR_OK; } diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index d06c7a0750..57ba280627 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -47,7 +47,7 @@ static unsigned short gdb_port; static const char *DIGITS = "0123456789abcdef"; static void gdb_log_callback(void *priv, const char *file, int line, - const char *function, const char *format, va_list args); + const char *function, const char *string); enum gdb_detach_mode { @@ -504,7 +504,7 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len) return retval; } -int gdb_output_con(connection_t *connection, char* line) +int gdb_output_con(connection_t *connection, const char* line) { char *hex_buffer; int i, bin_size; @@ -512,6 +512,8 @@ int gdb_output_con(connection_t *connection, char* line) bin_size = strlen(line); hex_buffer = malloc(bin_size*2 + 2); + if (hex_buffer == NULL) + return ERROR_GDB_BUFFER_TOO_SMALL; hex_buffer[0] = 'O'; for (i=0; ipriv; @@ -1807,13 +1809,7 @@ static void gdb_log_callback(void *priv, const char *file, int line, return; } - char *t = alloc_printf(format, args); - if (t == NULL) - return; - - gdb_output_con(connection, t); - - free(t); + gdb_output_con(connection, string); } int gdb_input_inner(connection_t *connection) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index ea5ec57548..e2f0e019cc 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -54,7 +54,7 @@ static char *negotiate = * we write to it, we will fail. Subsequent write operations will * succeed. Shudder! */ -int telnet_write(connection_t *connection, void *data, int len) +int telnet_write(connection_t *connection, const void *data, int len) { telnet_connection_t *t_con = connection->priv; if (t_con->closed) @@ -75,26 +75,30 @@ int telnet_prompt(connection_t *connection) return telnet_write(connection, t_con->prompt, strlen(t_con->prompt)); } -int telnet_outputline(connection_t *connection, char* line) +int telnet_outputline(connection_t *connection, const char *line) { + int len; /* process lines in buffer */ - char *p=line; - do { - char *next = strchr(p, '\n'); + while (*line) { + char *line_end = strchr(line, '\n'); - if (next) - *next++ = 0; + if (line_end) + len = line_end-line; + else + len = strlen(line); - - telnet_write(connection, p, strlen(p)); - if (next) + telnet_write(connection, line, len); + if (line_end) { telnet_write(connection, "\r\n\0", 3); + line += len+1; } - - p = next; - } while (p); + else + { + line += len; + } + } return ERROR_OK; } @@ -107,15 +111,10 @@ int telnet_output(struct command_context_s *cmd_ctx, char* line) } 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 *string) { connection_t *connection = priv; - char *t = alloc_printf(format, args); - if (t == NULL) - return; - telnet_outputline(connection, t); - - free(t); + telnet_outputline(connection, string); } int telnet_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv) diff --git a/src/target/target_request.c b/src/target/target_request.c index 020ee790e8..e168d944c2 100644 --- a/src/target/target_request.c +++ b/src/target/target_request.c @@ -55,7 +55,7 @@ int target_asciimsg(target_t *target, u32 length) int target_charmsg(target_t *target, u8 msg) { - USER_SAMELINE("%c", msg); + USER_N("%c", msg); return ERROR_OK; } -- 2.30.2