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)
 
 
 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;
        }
        {
                /* 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);
        /* 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
 /* 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;
 }
 
 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);
 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);
 
 
 #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
 
 
 int configuration_output_handler(struct command_context_s *context, char* line)
 {
-       INFO_SAMELINE(line);
+       INFO_N(line);
 
        return ERROR_OK;
 }
 
 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
 {
        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;
        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; i<bin_size; i++)
 int gdb_output(struct command_context_s *context, char* line)
 {
        /* this will be dumped to the log and also sent as an O packet if possible */
-       USER_SAMELINE(line);
+       USER_N(line);
        return ERROR_OK;
 }
 
 }
 
 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)
 {
        connection_t *connection = priv;
        gdb_connection_t *gdb_con = connection->priv;
                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)
 
  * 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)
        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;
 }
 }
 
 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)
 
 
 int target_charmsg(target_t *target, u8 msg)
 {
-       USER_SAMELINE("%c", msg);
+       USER_N("%c", msg);
        
        return ERROR_OK;
 }