- convert all files to unix line-ending
[fw/openocd] / src / helper / command.c
index 9f756d412a102afea06307ec3101b392dcf1bba1..15cddcdc40d197650a8896d934f14b9c7a8e22d9 100644 (file)
@@ -29,6 +29,7 @@
 #include "command.h"
 
 #include "log.h"
+#include "time_support.h"
 
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
 
+void command_print_help_line(command_context_t* context, struct command_s *command, int indent);
+
 int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 int build_unique_lengths(command_context_t *context, command_t *commands)
 {
@@ -258,27 +262,34 @@ int parse_line(char *line, char *words[], int max_words)
 
 void command_print(command_context_t *context, char *format, ...)
 {
-       va_list ap;
        char *buffer = NULL;
        int n, size = 0;
        char *p;
 
-       va_start(ap, format);
-       
        /* process format string */
-       /* TODO: possible bug. va_list is undefined after the first call to vsnprintf */
-       while (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)
-               {
-               /* increase buffer until it fits the whole string */
-               if (!(p = realloc(buffer, size += 4096)))
+       for (;;)
+       {
+               va_list ap;
+               va_start(ap, format);
+               if (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)
                {
-                       /* gotta free up */
-                       if (buffer)
-                               free(buffer);
-                       return;
+                       /* increase buffer until it fits the whole string */
+                       if (!(p = realloc(buffer, size += 4096)))
+                       {
+                               /* gotta free up */
+                               if (buffer)
+                                       free(buffer);
+                               va_end(ap);
+                               return;
+                       }
+       
+                       buffer = p;
+                       
+                       va_end(ap);
+                       continue;
                }
-
-               buffer = p;
+               va_end(ap);
+               break;
        }
        
        /* vsnprintf failed */
@@ -306,8 +317,6 @@ void command_print(command_context_t *context, char *format, ...)
        
        if (buffer)
                free(buffer);
-       
-       va_end(ap);
 }
 
 int find_and_run_command(command_context_t *context, command_t *commands, char *words[], int num_words, int start_word)
@@ -329,7 +338,7 @@ int find_and_run_command(command_context_t *context, command_t *commands, char *
                if (strncasecmp(c->name, words[start_word], strlen(words[start_word])))
                        continue;
                
-               if ((c->mode == context->mode) || (c->mode == COMMAND_ANY))
+               if ((context->mode == COMMAND_CONFIG) || (c->mode == COMMAND_ANY) || (c->mode == context->mode) )
                {
                        if (!c->children)
                        {
@@ -340,7 +349,13 @@ int find_and_run_command(command_context_t *context, command_t *commands, char *
                                }
                                else
                                {
-                                       return c->handler(context, c->name, words + start_word + 1, num_words - start_word - 1);
+                                       int retval = c->handler(context, c->name, words + start_word + 1, num_words - start_word - 1);
+                                       if (retval == ERROR_COMMAND_SYNTAX_ERROR)
+                                       {
+                                               command_print(context, "Syntax error:");
+                                               command_print_help_line(context, c, 0);
+                                       }
+                                       return retval; 
                                }
                        }
                        else
@@ -359,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};
@@ -399,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;
@@ -452,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;
        }
        
@@ -479,15 +483,12 @@ void command_print_help_line(command_context_t* context, struct command_s *comma
        }
        indents[i*2] = 0;
        
-       if ((command->mode == COMMAND_EXEC) || (command->mode == COMMAND_ANY))
-       {
-               if (command->help)
-                       help = command->help;
+       if (command->help)
+               help = command->help;
                
-               snprintf(name_buf, 64, command->name);
-               strncat(name_buf, indents, 64);
-               command_print(context, "%20s\t%s", name_buf, help);
-       }
+       snprintf(name_buf, 64, command->name);
+       strncat(name_buf, indents, 64);
+       command_print(context, "%20s\t%s", name_buf, help);
        
        if (command->children)
        {
@@ -559,6 +560,9 @@ command_context_t* command_init()
        register_command(context, NULL, "sleep", handle_sleep_command,
                                         COMMAND_ANY, "sleep for <n> milliseconds");
        
+       register_command(context, NULL, "time", handle_time_command,
+                                        COMMAND_ANY, "time <cmd + args> - execute <cmd + args> and print time it took");
+       
        return context;
 }
 
@@ -577,3 +581,27 @@ int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **ar
 
        return ERROR_OK;
 }
+
+int handle_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc<1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       
+       duration_t duration;
+       char *duration_text;
+       int retval;
+       
+       duration_start_measure(&duration);
+       
+       retval = find_and_run_command(cmd_ctx, cmd_ctx->commands, args, argc, 0);
+       
+       duration_stop_measure(&duration, &duration_text);
+       
+       float t=duration.duration.tv_sec;
+       t+=((float)duration.duration.tv_usec / 1000000.0);
+       command_print(cmd_ctx, "%s took %fs", args[0], t);
+       
+       free(duration_text);
+
+       return retval;
+}