From 67e0aea25850b8286f750e6458e5de741e6cb3b5 Mon Sep 17 00:00:00 2001 From: oharboe Date: Fri, 29 Feb 2008 11:16:38 +0000 Subject: 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 +- 4 files changed, 91 insertions(+), 124 deletions(-) (limited to 'src/helper') diff --git a/src/helper/command.c b/src/helper/command.c index 0ec54216..aa71f0ba 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 a3e8e816..7abebc29 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 a53b7f5e..c4078447 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 6e1f10b7..35ab0f5d 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; } -- cgit v1.2.3