provides a better impeadance match for debug output char fn's, e.g. eCos. - Line endings are now added at the caller site of command_print*(). command_print() still adds a line ending - echo of commands in scripts are now available via debug_level instead of forced echo - Added a USER_SAMELINE() for printing without a lineend. git-svn-id: svn://svn.berlios.de/openocd/trunk@364 b42882b7-edfa-0310-969c-e2dbd0fdcd60tags/v0.1.0
@@ -260,7 +260,7 @@ int parse_line(char *line, char *words[], int max_words) | |||||
return nwords; | return nwords; | ||||
} | } | ||||
void command_print(command_context_t *context, char *format, ...) | |||||
static void command_printv(command_context_t *context, char *format, va_list ap) | |||||
{ | { | ||||
char *buffer = NULL; | char *buffer = NULL; | ||||
int n, size = 0; | int n, size = 0; | ||||
@@ -269,8 +269,6 @@ void command_print(command_context_t *context, char *format, ...) | |||||
/* process format string */ | /* process format string */ | ||||
for (;;) | for (;;) | ||||
{ | { | ||||
va_list ap; | |||||
va_start(ap, format); | |||||
if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size) | if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size) | ||||
{ | { | ||||
/* increase buffer until it fits the whole string */ | /* increase buffer until it fits the whole string */ | ||||
@@ -279,16 +277,13 @@ void command_print(command_context_t *context, char *format, ...) | |||||
/* gotta free up */ | /* gotta free up */ | ||||
if (buffer) | if (buffer) | ||||
free(buffer); | free(buffer); | ||||
va_end(ap); | |||||
return; | return; | ||||
} | } | ||||
buffer = p; | buffer = p; | ||||
va_end(ap); | |||||
continue; | continue; | ||||
} | } | ||||
va_end(ap); | |||||
break; | break; | ||||
} | } | ||||
@@ -300,23 +295,31 @@ void command_print(command_context_t *context, char *format, ...) | |||||
return; | return; | ||||
} | } | ||||
p = buffer; | |||||
context->output_handler(context, buffer); | |||||
/* process lines in buffer */ | |||||
do { | |||||
char *next = strchr(p, '\n'); | |||||
if (next) | |||||
*next++ = 0; | |||||
if (buffer) | |||||
free(buffer); | |||||
} | |||||
if (context->output_handler) | |||||
context->output_handler(context, p); | |||||
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); | |||||
} | |||||
p = next; | |||||
} while (p); | |||||
void command_print(command_context_t *context, char *format, ...) | |||||
{ | |||||
char *t=malloc(strlen(format)+2); | |||||
strcpy(t, format); | |||||
strcat(t, "\n"); | |||||
va_list ap; | |||||
va_start(ap, format); | |||||
command_printv(context, t, ap); | |||||
va_end(ap); | |||||
free(t); | |||||
if (buffer) | |||||
free(buffer); | |||||
} | } | ||||
int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word) | int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word) | ||||
@@ -396,10 +399,7 @@ int command_run_line(command_context_t *context, char *line) | |||||
if (*line && (line[0] == '#')) | if (*line && (line[0] == '#')) | ||||
return ERROR_OK; | return ERROR_OK; | ||||
if (context->echo) | |||||
{ | |||||
command_print(context, "%s", line); | |||||
} | |||||
DEBUG("%s", line); | |||||
nwords = parse_line(line, words, sizeof(words) / sizeof(words[0])); | nwords = parse_line(line, words, sizeof(words) / sizeof(words[0])); | ||||
@@ -550,7 +550,6 @@ command_context_t* command_init() | |||||
context->mode = COMMAND_EXEC; | context->mode = COMMAND_EXEC; | ||||
context->commands = NULL; | context->commands = NULL; | ||||
context->current_target = 0; | context->current_target = 0; | ||||
context->echo = 0; | |||||
context->output_handler = NULL; | context->output_handler = NULL; | ||||
context->output_handler_priv = NULL; | context->output_handler_priv = NULL; | ||||
@@ -34,7 +34,6 @@ typedef struct command_context_s | |||||
enum command_mode mode; | enum command_mode mode; | ||||
struct command_s *commands; | struct command_s *commands; | ||||
int current_target; | int current_target; | ||||
int echo; | |||||
int (*output_handler)(struct command_context_s *context, char* line); | int (*output_handler)(struct command_context_s *context, char* line); | ||||
void *output_handler_priv; | void *output_handler_priv; | ||||
} command_context_t; | } command_context_t; | ||||
@@ -58,6 +57,7 @@ extern command_context_t* copy_command_context(command_context_t* context); | |||||
extern command_context_t* command_init(); | extern command_context_t* command_init(); | ||||
extern int command_done(command_context_t *context); | extern int command_done(command_context_t *context); | ||||
extern void command_print(command_context_t *context, char *format, ...); | extern void command_print(command_context_t *context, char *format, ...); | ||||
extern void command_print_sameline(command_context_t *context, char *format, ...); | |||||
extern int command_run_line(command_context_t *context, char *line); | extern int command_run_line(command_context_t *context, char *line); | ||||
extern int command_run_file(command_context_t *context, FILE *file, enum command_mode mode); | extern int command_run_file(command_context_t *context, FILE *file, enum command_mode mode); | ||||
@@ -217,7 +217,6 @@ int handle_field_command(struct command_context_s *cmd_ctx, char *cmd, char **ar | |||||
int handle_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | int handle_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) | ||||
{ | { | ||||
FILE *script_file; | FILE *script_file; | ||||
int echo; | |||||
if (argc != 1) | if (argc != 1) | ||||
return ERROR_COMMAND_SYNTAX_ERROR; | return ERROR_COMMAND_SYNTAX_ERROR; | ||||
@@ -229,14 +228,9 @@ int handle_script_command(struct command_context_s *cmd_ctx, char *cmd, char **a | |||||
command_print(cmd_ctx, "couldn't open script file %s", args[0]); | command_print(cmd_ctx, "couldn't open script file %s", args[0]); | ||||
return ERROR_OK; | return ERROR_OK; | ||||
} | } | ||||
echo = cmd_ctx->echo; | |||||
cmd_ctx->echo = 1; | |||||
command_run_file(cmd_ctx, script_file, cmd_ctx->mode); | command_run_file(cmd_ctx, script_file, cmd_ctx->mode); | ||||
cmd_ctx->echo = echo; | |||||
fclose(script_file); | fclose(script_file); | ||||
return ERROR_OK; | return ERROR_OK; | ||||
@@ -46,20 +46,14 @@ static char *log_strings[5] = | |||||
"Debug: " | "Debug: " | ||||
}; | }; | ||||
void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) | |||||
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 int count = 0; | |||||
count++; | |||||
va_list args; | |||||
char buffer[512]; | char buffer[512]; | ||||
log_callback_t *cb; | log_callback_t *cb; | ||||
if (level > debug_level) | |||||
return; | |||||
va_start(args, format); | |||||
vsnprintf(buffer, 512, format, args); | vsnprintf(buffer, 512, format, args); | ||||
va_end(args); | |||||
if (level == LOG_OUTPUT) | if (level == LOG_OUTPUT) | ||||
{ | { | ||||
@@ -76,8 +70,8 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f | |||||
if (debug_level >= LOG_DEBUG) | if (debug_level >= LOG_DEBUG) | ||||
{ | { | ||||
/* print with count and time information */ | /* print with count and time information */ | ||||
time_t t=time(NULL)-start; | |||||
fprintf(log_output, "%s %d %ld %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer); | |||||
int t=(int)(time(NULL)-start); | |||||
fprintf(log_output, "%s %d %d %s:%d %s(): %s\n", log_strings[level+1], count, t, file, line, function, buffer); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -92,13 +86,40 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f | |||||
{ | { | ||||
for (cb = log_callbacks; cb; cb = cb->next) | for (cb = log_callbacks; cb; cb = cb->next) | ||||
{ | { | ||||
va_start(args, format); | |||||
cb->fn(cb->priv, file, line, function, format, args); | cb->fn(cb->priv, file, line, function, format, args); | ||||
va_end(args); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
void log_printf(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) | |||||
{ | |||||
count++; | |||||
if (level > debug_level) | |||||
return; | |||||
va_list args; | |||||
va_start(args, format); | |||||
log_printfv(level, file, line, function, format, args); | |||||
va_end(args); | |||||
} | |||||
void log_printfnl(enum log_levels level, const char *file, int line, const char *function, const char *format, ...) | |||||
{ | |||||
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); | |||||
} | |||||
/* change the current debug level on the fly | /* change the current debug level on the fly | ||||
* 0: only ERRORS | * 0: only ERRORS | ||||
* 1: + WARNINGS | * 1: + WARNINGS | ||||
@@ -46,7 +46,10 @@ enum log_levels | |||||
extern void log_printf(enum log_levels level, const char *file, int line, | extern void log_printf(enum log_levels level, const char *file, int line, | ||||
const char *function, const char *format, ...) | const char *function, const char *format, ...) | ||||
__attribute__ ((format (printf, 5, 6))); | |||||
__attribute__ ((format (printf, 5, 6))); | |||||
extern void log_printfnl(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 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); | ||||
@@ -71,34 +74,40 @@ extern int debug_level; | |||||
/* Avoid fn call and building parameter list if we're not outputting the information. | /* Avoid fn call and building parameter list if we're not outputting the information. | ||||
* Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */ | * Matters on feeble CPUs for DEBUG/INFO statements that are involved frequently */ | ||||
#define DEBUG(expr ...) \ | #define DEBUG(expr ...) \ | ||||
do { if (debug_level >= LOG_DEBUG) \ | do { if (debug_level >= LOG_DEBUG) \ | ||||
log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
log_printfnl (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
} while(0) | } while(0) | ||||
#define INFO(expr ...) \ | #define INFO(expr ...) \ | ||||
do { if (debug_level >= LOG_INFO) \ | do { if (debug_level >= LOG_INFO) \ | ||||
log_printf (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
log_printfnl (LOG_INFO, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
} while(0) | } while(0) | ||||
#define WARNING(expr ...) \ | #define WARNING(expr ...) \ | ||||
do { \ | do { \ | ||||
log_printf (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
log_printfnl (LOG_WARNING, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
} while(0) | } while(0) | ||||
#define ERROR(expr ...) \ | #define ERROR(expr ...) \ | ||||
do { \ | do { \ | ||||
log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
log_printfnl (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
} while(0) | } while(0) | ||||
#define USER(expr ...) \ | #define USER(expr ...) \ | ||||
do { \ | |||||
log_printfnl (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
} while(0) | |||||
#define USER_SAMELINE(expr ...) \ | |||||
do { \ | do { \ | ||||
log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \ | log_printf (LOG_USER, __FILE__, __LINE__, __FUNCTION__, expr); \ | ||||
} while(0) | } while(0) | ||||
#define OUTPUT(expr ...) \ | #define OUTPUT(expr ...) \ | ||||
do { \ | do { \ | ||||
log_printf (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
log_printfnl (LOG_OUTPUT, __FILE__, __LINE__, __FUNCTION__, expr); \ | |||||
} while(0) | } while(0) | ||||
@@ -511,16 +511,14 @@ int gdb_output_con(connection_t *connection, char* line) | |||||
bin_size = strlen(line); | bin_size = strlen(line); | ||||
hex_buffer = malloc(bin_size*2 + 4); | |||||
hex_buffer = malloc(bin_size*2 + 2); | |||||
hex_buffer[0] = 'O'; | hex_buffer[0] = 'O'; | ||||
for (i=0; i<bin_size; i++) | for (i=0; i<bin_size; i++) | ||||
snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]); | snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]); | ||||
hex_buffer[bin_size*2+1] = '0'; | |||||
hex_buffer[bin_size*2+2] = 'a'; | |||||
hex_buffer[bin_size*2+3] = 0x0; | |||||
hex_buffer[bin_size*2+1] = 0; | |||||
gdb_put_packet(connection, hex_buffer, bin_size*2 + 3); | |||||
gdb_put_packet(connection, hex_buffer, bin_size*2 + 1); | |||||
free(hex_buffer); | free(hex_buffer); | ||||
return ERROR_OK; | return ERROR_OK; | ||||
@@ -529,7 +527,7 @@ int gdb_output_con(connection_t *connection, char* line) | |||||
int gdb_output(struct command_context_s *context, char* line) | 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 */ | /* this will be dumped to the log and also sent as an O packet if possible */ | ||||
USER(line); | |||||
USER_SAMELINE(line); | |||||
return ERROR_OK; | return ERROR_OK; | ||||
} | } | ||||
@@ -605,7 +603,8 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event | |||||
return ERROR_OK; | return ERROR_OK; | ||||
} | } | ||||
int gdb_new_connection(connection_t *connection) | int gdb_new_connection(connection_t *connection) | ||||
{ | { | ||||
gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t)); | gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t)); | ||||
@@ -77,8 +77,26 @@ int telnet_prompt(connection_t *connection) | |||||
int telnet_outputline(connection_t *connection, char* line) | int telnet_outputline(connection_t *connection, char* line) | ||||
{ | { | ||||
telnet_write(connection, line, strlen(line)); | |||||
return telnet_write(connection, "\r\n\0", 3); | |||||
/* process lines in buffer */ | |||||
char *p=line; | |||||
do { | |||||
char *next = strchr(p, '\n'); | |||||
if (next) | |||||
*next++ = 0; | |||||
telnet_write(connection, p, strlen(p)); | |||||
if (next) | |||||
{ | |||||
telnet_write(connection, "\r\n\0", 3); | |||||
} | |||||
p = next; | |||||
} while (p); | |||||
return ERROR_OK; | |||||
} | } | ||||
int telnet_output(struct command_context_s *cmd_ctx, char* line) | int telnet_output(struct command_context_s *cmd_ctx, char* line) | ||||
@@ -93,20 +111,9 @@ void telnet_log_callback(void *priv, const char *file, int line, | |||||
{ | { | ||||
connection_t *connection = priv; | connection_t *connection = priv; | ||||
char *t = alloc_printf(format, args); | char *t = alloc_printf(format, args); | ||||
char *t2; | |||||
if (t == NULL) | if (t == NULL) | ||||
return; | return; | ||||
t2=t; | |||||
char *endline; | |||||
do | |||||
{ | |||||
if ((endline=strchr(t2, '\n'))!=NULL) | |||||
{ | |||||
*endline=0; | |||||
} | |||||
telnet_outputline(connection, t2); | |||||
t2=endline+1; | |||||
} while (endline); | |||||
telnet_outputline(connection, t); | |||||
free(t); | free(t); | ||||
} | } | ||||
@@ -53,6 +53,13 @@ int target_asciimsg(target_t *target, u32 length) | |||||
return ERROR_OK; | return ERROR_OK; | ||||
} | } | ||||
int target_charmsg(target_t *target, u8 msg) | |||||
{ | |||||
USER_SAMELINE("%c", msg); | |||||
return ERROR_OK; | |||||
} | |||||
int target_hexmsg(target_t *target, int size, u32 length) | int target_hexmsg(target_t *target, int size, u32 length) | ||||
{ | { | ||||
u8 *data = malloc(CEIL(length * size, 4) * 4); | u8 *data = malloc(CEIL(length * size, 4) * 4); | ||||
@@ -122,6 +129,9 @@ int target_request(target_t *target, u32 request) | |||||
target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16); | target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16); | ||||
} | } | ||||
break; | break; | ||||
case TARGET_REQ_DEBUGCHAR: | |||||
target_charmsg(target, (request & 0x00ff0000) >> 16); | |||||
break; | |||||
/* case TARGET_REQ_SEMIHOSTING: | /* case TARGET_REQ_SEMIHOSTING: | ||||
* break; | * break; | ||||
*/ | */ | ||||
@@ -26,6 +26,7 @@ typedef enum target_req_cmd | |||||
{ | { | ||||
TARGET_REQ_TRACEMSG, | TARGET_REQ_TRACEMSG, | ||||
TARGET_REQ_DEBUGMSG, | TARGET_REQ_DEBUGMSG, | ||||
TARGET_REQ_DEBUGCHAR, | |||||
/* TARGET_REQ_SEMIHOSTING, */ | /* TARGET_REQ_SEMIHOSTING, */ | ||||
} target_req_cmd_t; | } target_req_cmd_t; | ||||