Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last modification of the tesh2 files (variable extend and some corrections)
authorcherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 19 Jun 2008 19:25:28 +0000 (19:25 +0000)
committercherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 19 Jun 2008 19:25:28 +0000 (19:25 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@5772 48e7efb5-ca39-0410-a469-dd3cf9ba447f

13 files changed:
tools/tesh2/examples/catch-return.tesh
tools/tesh2/examples/var.tesh
tools/tesh2/include/str_replace.h
tools/tesh2/include/types.h
tools/tesh2/src/command.c
tools/tesh2/src/context.c
tools/tesh2/src/fstream.c
tools/tesh2/src/getpath.c
tools/tesh2/src/reader.c
tools/tesh2/src/runner.c
tools/tesh2/src/str_replace.c
tools/tesh2/src/variable.c
tools/tesh2/tesh/tesh.vcproj

index 50d48ae..6411ec9 100644 (file)
@@ -1 +1 @@
-#! ./tesh\r# This suite builds and uses a program returning 1.\r# tesh must detect this condition and report the issue.\r\r$ rm -rf temp_testdir\r$ mkdir temp_testdir\r\r$ cd temp_testdir\r\r< #include <stdlib.h>\r< int main(void) {\r<   exit(1);\r< }\r$ cat > return1.c\r\r$ gcc -o return1 return1.c\r\r\r\r! expect return $EEXITCODENOTMATCH\r< $ ./return1\r$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"\r> Test unit from stdin\r> [stdin:1] ./return1\r> [stdin:1] ./return1 : NOK (returned code `1' instead `0')\r> Output of <stdin:1> so far: \r> ||\r> Test unit `stdin': NOK (<stdin:1> exit code mismatch)\r\r\r\r$ cd ..\r$ rm -rf temp_testdir\r
\ No newline at end of file
+#! ./tesh\r# This suite builds and uses a program returning 1.\r# tesh must detect this condition and report the issue.\r\r$ rm -rf temp_testdir\r$ mkdir temp_testdir\r\r$ cd temp_testdir\r\r< #include <stdlib.h>\r< int main(void) {\r<   exit(1);\r< }\r$ cat > return1.c\r\r$ gcc -o return1 return1.c\r\r! expect return $EEXITCODENOTMATCH\r< $ ./return1\r$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"\r> Test unit from stdin\r> [stdin:1] ./return1\r> [stdin:1] ./return1 : NOK (returned code `1' instead `0')\r> Output of <stdin:1> so far: \r> ||\r> Test unit `stdin': NOK (<stdin:1> exit code mismatch)\r\r\r\r$ cd ..\r$ rm -rf temp_testdir\r
\ No newline at end of file
index 7b42d40..31000bc 100644 (file)
@@ -105,27 +105,62 @@ $ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 > [stdin:1] A system variable named `(ENOENT)' already exists
 > Test unit `stdin': NOK (<stdin:1> syntax error)
 
+# Substitution usage
 
+! new=1
 
+p new is `$new ' or `${new}'
 
+p the len of new is : ${#new}
 
+! unset new
 
+p new is empty <$new> and is len is <${#new}>
 
+# display 66 and assign 6 to the value 66 of the variable new
 
+p ${new:=66}
 
+p new is `$new ' or `${new}'
 
+p the len of new is : ${#new}
 
+# display 66 and do not assign the value 69 to the variable
 
+p ${new:=69}
 
+p new is `$new ' or `${new}'
 
+p the len of new is : ${#new}
 
+! unset new
 
+# display 79 and do not assigne the value 79 to the variable
+# new is empty
+p ${new:-79}
 
+p new is `$new ' or `${new}'
 
+p the len of new is : ${#new}
 
+# display nothing and do not assigne the value 89 to the variable
+# new is empty
+p is empty ${new:+89}
 
+p new is `$new ' or `${new}'
 
+p the len of new is : ${#new}
 
+! set new=999
 
+# display 99 and do not assigne the value 99 to the variable (do not dispaly the value of new)
+# new is empty
+p is empty ${new:+99}
 
+p new is `$new ' or `${new}'
 
+p the len of new is : ${#new}
+
+! unset new
+
+# p ${new:?new is empty}
index c58242a..4c18e35 100644 (file)
@@ -1,14 +1,16 @@
 #ifndef __STR_REPLACE_H\r
 #define __STR_REPLACE_H\r
 \r
+#include <com.h>\r
+\r
 #ifdef __cplusplus\r
 extern "C" {\r
 #endif\r
 int\r
-str_replace(char** str, const char *what, const char *with);\r
+str_replace(char** str, const char *what, const char *with, const char* delimiters);\r
 \r
 int\r
-str_replace_all(char** str, const char* what, const char* with);\r
+str_replace_all(char** str, const char* what, const char* with, const char* delimiters);\r
 \r
 #ifdef __cplusplus\r
 }\r
index f3edcb1..ae5fcc4 100644 (file)
@@ -315,6 +315,11 @@ typedef struct s_context
        xbt_strbuff_t output;                           /* the expected output of the command of the test                                               */
        output_handling_t output_handling;
        int async;                                                      /* if 1, the command is asynchronous                                                                    */
+       
+       #ifdef WIN32
+       char* t_command_line;                           /* translate the command line on Windows                                                                */
+       #endif
+
 }s_context_t,* context_t;
 
 /* 
index 3e11849..958c0f4 100644 (file)
@@ -162,7 +162,7 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
 int\r
 command_run(command_t command)\r
 {\r
-       if(!silent_flag)\r
+       if(!silent_flag && !interrupted)\r
                INFO2("[%s] %s",command->context->pos, command->context->command_line);\r
        \r
        if(!just_print_flag)\r
@@ -208,7 +208,13 @@ command_start(void* p)
        xbt_os_mutex_release(command->mutex);\r
        \r
        /* execute the command of the test */\r
+\r
+       #ifndef WIN32\r
        command_exec(command, command->context->command_line);\r
+       #else\r
+       /* play the translated command line on Windows */\r
+       command_exec(command, command->context->t_command_line);\r
+       #endif\r
        \r
        if(cs_in_progress == command->status)\r
        {\r
@@ -816,7 +822,7 @@ command_check(command_t command)
        xbt_strbuff_trim(command->output);\r
        xbt_strbuff_trim(command->context->output);\r
 \r
-       if(!success)\r
+       if(!success &&  !strcmp(command->output->data, command->context->output->data))\r
        {\r
                xbt_dynar_t a = xbt_str_split(command->output->data, "\n");\r
                char *out = xbt_str_join(a,"\n||");\r
@@ -830,6 +836,7 @@ command_check(command_t command)
                if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))\r
                {\r
                        char *diff;\r
+\r
                        \r
                        ERROR2("[%s] `%s' : NOK (outputs mismatch):", command->context->pos, command->context->command_line);\r
                        \r
index 22a44fc..877ffc2 100644 (file)
@@ -34,6 +34,10 @@ context_new(void)
        context->signal = INDEFINITE_SIGNAL;\r
        context->output_handling = oh_check;\r
        context->async = 0;\r
+\r
+       #ifdef WIN32\r
+       context->t_command_line = NULL;\r
+       #endif\r
        \r
        return context;\r
 }\r
@@ -56,6 +60,11 @@ context_free(context_t* ptr)
        if((*ptr)->signal)\r
                free((*ptr)->signal);\r
 \r
+       #ifdef WIN32\r
+       if((*ptr)->t_command_line)\r
+               free((*ptr)->t_command_line);\r
+       #endif\r
+\r
        *ptr = NULL;\r
        \r
        return 0;\r
@@ -73,6 +82,14 @@ context_reset(context_t context)
                context->command_line = NULL;\r
        }\r
 \r
+       #ifdef WIN32\r
+       if(context->t_command_line)\r
+       {\r
+               free(context->t_command_line);\r
+               context->t_command_line = NULL;\r
+       }\r
+       #endif\r
+\r
        if(context->pos)\r
        {\r
                free(context->pos);\r
@@ -111,6 +128,12 @@ context_dup(context_t context)
        dup->line = context->line;\r
        dup->pos = strdup(context->pos);\r
        dup->command_line = strdup(context->command_line);\r
+\r
+       \r
+       #ifdef WIN32\r
+       dup->t_command_line = strdup(context->t_command_line);\r
+       #endif\r
+\r
        dup->exit_code = context->exit_code;\r
        dup->timeout = context->timeout;\r
        dup->output = NULL;\r
@@ -158,6 +181,14 @@ context_clear(context_t context)
                context->command_line = NULL;\r
        }\r
 \r
+       #ifdef WIN32\r
+       if(context->t_command_line)\r
+       {\r
+               free(context->t_command_line);\r
+               context->t_command_line = NULL;\r
+       }\r
+       #endif\r
+\r
        if(context->pos)\r
        {\r
                free(context->pos);\r
index 5d10d82..36bb0f1 100644 (file)
 #include <readline.h>\r
 \r
 #include <is_cmd.h>\r
+#include <getpath.h>\r
 \r
 #ifndef WIN32\r
 #include <xsignal.h>\r
 #endif\r
 \r
+#ifdef WIN32\r
+static int\r
+is_w32_cmd(const char* cmd, char** path)\r
+{\r
+       size_t i = 0;\r
+       struct stat stat_buff = {0};\r
+       char buff[PATH_MAX + 1] = {0};\r
+       \r
 \r
 \r
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
+       if(!cmd)\r
+       {\r
+               errno = EINVAL;\r
+               return 0;\r
+       }\r
+       \r
+       if(stat(cmd, &stat_buff) || !S_ISREG(stat_buff.st_mode))\r
+       {\r
+               if(path)\r
+               {\r
+                       for (i = 0; path[i] != NULL; i++)\r
+                       {\r
+                               \r
+                               sprintf(buff,"%s\\%s",path[i], cmd);\r
+                               \r
+                               if(!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))\r
+                                       return 1;\r
+                       }\r
+               }\r
+       }\r
+       else\r
+               return 1;\r
+               \r
+\r
+       return 0;\r
+}\r
+#endif\r
 \r
 \r
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
 \r
 \r
 long fstream_getline(fstream_t fstream, char **buf, size_t *n) {\r
@@ -360,9 +396,20 @@ fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, con
        char* line2;\r
        variable_t variable;\r
        unsigned int i;\r
-       char name[VAR_NAME_MAX + 1] = {0};\r
+       char exp[VAR_NAME_MAX + 1] = {0};\r
        unit_t unit = fstream->unit;\r
        xbt_dynar_t variables = unit->runner->variables;\r
+       char* p= NULL;\r
+       char* end = NULL;\r
+       char* val = NULL;\r
+       char buff[VAR_NAME_MAX + 1] = {0}; \r
+       size_t len;\r
+       char delimiters[4] = {' ', '\t', '\n', '\0'}; \r
+       \r
+       int j;\r
+       \r
+       if(line[0] == '#')\r
+               return;\r
 \r
        if(unit->is_running_suite && strncmp(line, "! include", strlen("! include")))\r
        {/* it's the end of a suite */\r
@@ -377,35 +424,605 @@ fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, con
                unit_set_error(*current_suite, ESYNTAX, 1, filepos);\r
 \r
                failure(fstream->unit);\r
-                       \r
-               \r
        }\r
        \r
        context->line = strdup(filepos);\r
        \r
-       \r
        /* search end */\r
        xbt_str_rtrim(line + 2,"\n");\r
        \r
        line2 = strdup(line);\r
-       \r
+\r
+       len = strlen(line2 + 2) + 1;\r
+\r
        /* replace each variable by its value */\r
        xbt_os_mutex_acquire(unit->mutex);\r
+       \r
+\r
+       /* replace all existing\r
+          ${var}\r
+          ${var:=val}\r
+          ${var:+val}\r
+          ${var:-val}\r
+          ${var:?val}\r
+          ${#var}\r
+   */\r
+       \r
+       xbt_dynar_foreach(variables, i, variable)\r
+       {\r
+               if(!(p = strstr(line2 + 2, "${")))\r
+                       break;\r
+\r
+               memset(buff, 0, len);\r
+\r
+               sprintf(buff,"${%s",variable->name);\r
+               \r
+               /* FALSE */\r
+               if((p = strstr(line2 + 2, buff)))\r
+               {\r
+                       memset(buff, 0, len);\r
+                       p--;\r
+                       j = 0;\r
+\r
+                       while(*(p++) != '\0')\r
+                       {\r
+                               buff[j++] = *p;\r
+\r
+                               if(*p == '}')\r
+                                       break;\r
+                       }\r
+\r
+                       if(buff[j - 1] != '}')\r
+                       {\r
+                               xbt_os_mutex_release(unit->mutex);      \r
+                               \r
+                               \r
+                               ERROR2("[%s] Syntax error : `%s'.",filepos, p - j);\r
+                               \r
+                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                               failure(fstream->unit);\r
+                               return;\r
+                       }\r
+\r
+                       if((p = strstr(buff , ":=")))\r
+                       {\r
+                               /* ${var:=val} */\r
+                               \r
+                               /* if the value of the variable is empty, update its value by the value*/\r
+                               p += 2;\r
+                               \r
+                               end = strchr(p, '}');\r
+\r
+                               if(!end || (end == p))\r
+                               {\r
+                                       xbt_os_mutex_release(unit->mutex);      \r
+                               \r
+                               \r
+                                       ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(buff, "${"));\r
+                               \r
+                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                       failure(fstream->unit);\r
+                                       return;\r
+                               }\r
+\r
+                               val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
+\r
+                               strncpy(val, p,(end - p));\r
+                               \r
+                               \r
+                               /* replace the expression by the expression of the value of the variable*/\r
+                               sprintf(exp, "${%s:=%s}", variable->name, val);\r
+\r
+                               if(variable->val)\r
+                                       str_replace_all(&line2, exp, variable->val, NULL);\r
+                               else\r
+                               {\r
+                                       str_replace_all(&line2, exp, val, NULL);\r
+\r
+                                       variable->val = strdup(val);\r
+                               }\r
+\r
+                               memset(exp, 0, VAR_NAME_MAX + 1);\r
+\r
+                               if(val)\r
+                               {\r
+                                       free(val);\r
+                                       val = NULL;\r
+                               }\r
+\r
+                       }\r
+                       else if((p = strstr(buff, ":-")))\r
+                       {\r
+                               /* ${var:-val} */\r
+                               \r
+                               /* if the value of the variable is empty, replace the expression by the value */\r
+                               p += 2;\r
+                               end = strchr(p, '}');\r
+\r
+                               if(!end || (end == p))\r
+                               {\r
+                                       xbt_os_mutex_release(unit->mutex);      \r
+                               \r
+                                       ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
+                               \r
+                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                       failure(fstream->unit);\r
+                                       return;\r
+                               }\r
+\r
+                               val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
+\r
+                               strncpy(val, p,(end - p)); \r
+\r
+                               sprintf(exp, "${%s:-%s}", variable->name, val);\r
+                               \r
+                               str_replace_all(&line2, exp, variable->val ? variable->val : val, NULL);\r
+                               \r
+\r
+                               memset(exp, 0, VAR_NAME_MAX + 1);\r
+                               \r
+                               if(val)\r
+                               {\r
+                                       free(val);\r
+                                       val = NULL;\r
+                               }\r
+\r
+                       }\r
+                       else if((p = strstr(buff, ":+")))\r
+                       {\r
+                               /* ${var:+val} */\r
+       \r
+                               /* if the value of the variable is not empty, replace the expression by the value */\r
+                               p += 2;\r
+\r
+                               end = strchr(p, '}');\r
+\r
+                               if(!end || (end == p))\r
+                               {\r
+                                       xbt_os_mutex_release(unit->mutex);      \r
+                               \r
+                               \r
+                                       ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
+                               \r
+                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                       failure(fstream->unit);\r
+                                       return;\r
+                               }\r
+\r
+                               val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
+\r
+                               strncpy(val, p,(end - p));\r
+\r
+                               sprintf(exp, "${%s:+%s}", variable->name, val);\r
+\r
+                               if(variable->val)\r
+                               {\r
+                                       str_replace_all(&line2, exp, val, NULL);\r
+                               }\r
+                               else\r
+                               {\r
+                                       str_replace_all(&line2, exp, NULL , NULL);\r
+                                       variable->val = strdup(val);\r
+                               }\r
+                               \r
+                               memset(exp, 0, VAR_NAME_MAX + 1);\r
+                               \r
+                               if(val)\r
+                               {\r
+                                       free(val);\r
+                                       val = NULL;\r
+                               }\r
+                       }\r
+                       else if((p = strstr(buff, ":?")))\r
+                       {\r
+                               /*  ${var:?val} */\r
+       \r
+                               /* if the value of the variable is not empty, replace the expression by the value */\r
+                               p += 2;\r
+                               end = strchr(p, '}');\r
+\r
+                               if(!end || (end == p))\r
+                               {\r
+                                       xbt_os_mutex_release(unit->mutex);      \r
+                               \r
+                                       ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
+                               \r
+                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                       failure(fstream->unit);\r
+                                       return;\r
+                               }\r
+\r
+                               val = (char*) calloc((size_t)(end - p) + 1, sizeof(char));\r
+\r
+                               strncpy(val, p,(end - p));\r
+\r
+                               sprintf(exp, "${%s:?%s}", variable->name, val);\r
+                               \r
+                               if(variable->val)\r
+                                       str_replace_all(&line2, exp, variable->val, NULL);\r
+                               else\r
+                               {\r
+\r
+                                       xbt_os_mutex_release(unit->mutex);      \r
+\r
+                                       ERROR2("[%s] %s.",filepos, val);\r
+\r
+                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                       failure(fstream->unit);\r
+                                       return;\r
+                               }\r
+                               \r
+                               memset(exp, 0, VAR_NAME_MAX + 1);\r
+                               \r
+                               if(val)\r
+                               {\r
+                                       free(val);\r
+                                       val = NULL;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
 \r
+       /* replace all existing $var */\r
        xbt_dynar_foreach(variables, i, variable)\r
        {\r
-               sprintf(name, "$%s", variable->name);\r
-               str_replace_all(&line2, name, variable->val);\r
-               memset(name, 0, VAR_NAME_MAX + 1);\r
+               if(!strchr(line2 + 2, '$'))\r
+                       break;\r
+\r
+               if(strstr(line2 + 2, variable->name))\r
+               {\r
+\r
+                       sprintf(exp, "${#%s}", variable->name);\r
+                       \r
+                       if(strstr(line2 + 2, exp))\r
+                       {\r
+\r
+                               if(variable->val)\r
+                               {\r
+                                       char slen[4] = {0};\r
+                                       sprintf(slen,"%d", (int)strlen(variable->val));\r
+                                       str_replace_all(&line2, exp, slen, NULL);\r
+                               }\r
+                               else\r
+                                       str_replace_all(&line2, exp, "0", NULL);\r
+                       }\r
+\r
+                       memset(exp, 0, VAR_NAME_MAX + 1);\r
+\r
+                       sprintf(exp, "${%s}", variable->name);\r
+\r
+                       if(strstr(line2 + 2, exp))\r
+                       {\r
+                               if(variable->val)\r
+                                       str_replace_all(&line2, exp, variable->val, NULL);\r
+                               else\r
+                                       str_replace_all(&line2, exp, NULL, NULL);\r
+                       }\r
+\r
+                       memset(exp, 0, VAR_NAME_MAX + 1);\r
+\r
+                       sprintf(exp, "$%s", variable->name);\r
+                       \r
+                       if((p = strstr(line2 + 2, exp)))\r
+                       {\r
+                               if((p + strlen(variable->name) + 1)[0] != '\0')\r
+                                       delimiters[0] = (p + strlen(variable->name) + 1)[0];\r
+\r
+                               if(variable->val)\r
+                                       str_replace_all(&line2, exp, variable->val,  delimiters);\r
+                               else\r
+                                       str_replace_all(&line2, exp, NULL, delimiters);\r
+                       }\r
+\r
+                       memset(exp, 0, VAR_NAME_MAX + 1);\r
+\r
+               }\r
+       }\r
+\r
+       while((p = strstr(line2 + 2, "${")))\r
+       {\r
+               /*if(*(p+1) != '{')\r
+               {\r
+                       j = 0;\r
+                       p --;\r
+\r
+                       while(*(p++) != '\0')\r
+                       {\r
+                               if(*p != ' ' && *p !='\t')\r
+                                       exp[j++] = *p;\r
+                               else\r
+                                       break;\r
+\r
+                       }\r
+                       \r
+                       str_replace_all(&line2, exp, NULL, " \t\n\r");\r
+                       memset(exp, 0, VAR_NAME_MAX + 1);\r
+               }.\r
+               else\r
+               */\r
+               {\r
+                       char* begin = NULL;\r
+                       \r
+                       j = 0;\r
+                       p --;\r
+\r
+                       while(*(p++) != '\0')\r
+                       {\r
+                               if((!begin && *p != ' ' && *p !='\t') || begin)\r
+                               {\r
+                                       /* `:' must be before this caracter, bad substitution : exit loop \r
+                                           ||\r
+                                               the current character is already present, bad substitution : exit loop\r
+                                               */\r
+                                       if(\r
+                                                       (\r
+                                                               *(p - 1) != ':' && (\r
+                                                                                                               (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')\r
+                                                                                                       )\r
+                                                       )\r
+                                               || \r
+                                                       (\r
+                                                               begin &&        (\r
+                                                                                               (*p == ':') || (*p == '=') || (*p == '-') || (*p == '+') || (*p == '?')\r
+                                                                                       )\r
+                                                       )\r
+                                               )\r
+                                               break;\r
+                                       else\r
+                                               exp[j++] = *p;\r
+\r
+                                       if(*p == ':')\r
+                                       {\r
+                                               /* save the begining of the value */\r
+                                               if((*(p+1) == '=') || (*(p+1) == '-') || (*(p+1) == '+') || (*(p+1) == '?'))\r
+                                               {\r
+                                                       begin = p + 2;\r
+                                                       exp[j++] = *(p+1);\r
+                                                       p++;\r
+                                                       continue;\r
+\r
+                                               }\r
+                                               else\r
+                                               /* the current char is `:' but the next is invalid, bad substitution : exit loop */\r
+                                                       break;\r
+                                       }\r
+                                       /* end of the substitution : exit loop */\r
+                                       else if(*p == '}')\r
+                                               break;\r
+                               }\r
+                               else\r
+                                       break;\r
+                       }\r
+                       \r
+                       if(exp[j - 1] == '}')\r
+                       {\r
+                               if(exp[2] == '#')\r
+                               {\r
+                                       /* ${#var} */\r
+\r
+\r
+                                       if(4 == strlen(exp))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+                                       \r
+                                       str_replace_all(&line2, exp, "0", NULL);        \r
+                               }\r
+                               else if(strstr(exp,":="))\r
+                               {\r
+                                       /* ${var:=value} */     \r
+                                       \r
+                                       end = strchr(p, '}');\r
+\r
+                                       if(!end || (end == begin))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+\r
+                                       variable = xbt_new0(s_variable_t, 1);\r
+\r
+                                       variable->val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
+\r
+                                       strncpy(variable->val, begin ,(end - begin));\r
+\r
+                                       begin = exp + 2;\r
+                                       end = strchr(exp, ':');\r
+\r
+                                       if(!end || (end == begin))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+\r
+                                       variable->name = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
+\r
+                                       strncpy(variable->name, exp + 2 ,(end - begin));\r
+\r
+                                       str_replace_all(&line2, exp, variable->val, NULL);\r
+\r
+                                       xbt_dynar_push(variables, &variable);\r
+\r
+                               }\r
+                               else if(strstr(exp,":-"))\r
+                               {\r
+                                       /* ${var:-value} */     \r
+\r
+                                       \r
+                                       end = strchr(p, '}');\r
+\r
+                                       if(!end || (end == begin))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+\r
+                                       val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
+\r
+                                       strncpy(val, begin ,(end - begin));\r
+\r
+                                       str_replace_all(&line2, exp, val, NULL);\r
+\r
+                                       if(val)\r
+                                               free(val);\r
+\r
+                               }\r
+                               else if(strstr(exp,":+"))\r
+                               {\r
+                                       /* ${var:+value} */     \r
+\r
+                                       end = strchr(p, '}');\r
+\r
+                                       if(!end || (end == begin))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+\r
+                                       str_replace_all(&line2, exp, NULL, NULL);\r
+                               }\r
+                               else if(strstr(exp,":?"))\r
+                               {\r
+                                       /* ${var:?value} */\r
+                                       \r
+                                       end = strchr(p, '}');\r
+\r
+                                       if(!end || (end == begin))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+\r
+                                       val = (char*) calloc((size_t)(end - begin) + 1, sizeof(char));\r
+\r
+                                       strncpy(val, begin ,(end - begin));\r
+\r
+                                       xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                       ERROR2("[%s] : `%s'.",filepos, val);\r
+\r
+                                       if(val)\r
+                                               free(val);\r
+                                       \r
+                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                       failure(fstream->unit);\r
+\r
+                                       return;\r
+                                       \r
+                               }\r
+                               else\r
+                               {\r
+                                       /* ${var} */\r
+\r
+                                       if(3 == strlen(exp))\r
+                                       {\r
+                                               xbt_os_mutex_release(unit->mutex);      \r
+                                       \r
+                                               ERROR2("[%s] Bad substitution : `%s'.",filepos, strchr(line2 + 2, '$'));\r
+                                       \r
+                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                                               failure(fstream->unit);\r
+                                               return;\r
+                                       }\r
+\r
+                                       str_replace_all(&line2, exp, NULL, NULL);\r
+                                       \r
+                               }\r
+\r
+                               memset(exp, 0, VAR_NAME_MAX + 1);\r
+                       }\r
+                       else\r
+                       {\r
+                               xbt_os_mutex_release(unit->mutex);      \r
+                               \r
+                               if(strstr(line2 + 2, "${"))\r
+                                       ERROR2("[%s] Bad substitution : `%s'.",filepos, strstr(line2, "${"));\r
+                               else\r
+                                       ERROR2("[%s] Syntax error : `%s'.",filepos, strstr(line2, "${"));\r
+\r
+                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
+                               failure(fstream->unit);\r
+                               return;\r
+                       }\r
+\r
+               }\r
+               \r
        }\r
        \r
-       xbt_os_mutex_release(unit->mutex);\r
+       p = line2 + 2;\r
+       \r
+       while(p && 1)\r
+       {\r
+               if((p = strchr(p, '$')))\r
+               {\r
+                       if(*(p+1) != ' ')\r
+                       {\r
+                               j = 0;\r
+                               p --;\r
+\r
+                               while(*(p++) != '\0')\r
+                               {\r
+                                       if(*p != ' ' && *p !='\t')\r
+                                               exp[j++] = *p;\r
+                                       else\r
+                                               break;\r
+\r
+                               }\r
+                               \r
+                               str_replace_all(&line2, exp, NULL, " \t\n\r");\r
+                               memset(exp, 0, VAR_NAME_MAX + 1);\r
+                       }\r
+                       else\r
+                       {\r
+                               /* maybe < $ cmd */\r
+                               p++;\r
+                       }\r
+               }\r
+               else\r
+                       break;\r
+       }\r
 \r
+       xbt_os_mutex_release(unit->mutex);      \r
        \r
        switch(line2[0]) \r
        {\r
-               case '#': \r
+               /*case '#': \r
                break;\r
+               */\r
                \r
                case '$':\r
                case '&':\r
@@ -496,9 +1113,14 @@ fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, con
                        \r
                        char* prompt = line2 + 2;\r
 \r
-                       for(j = 0; j < strlen(prompt); j++) \r
+                       for(j = 0; j < strlen(prompt); j++)\r
+                       {\r
                                if (prompt[j] != ' ' && prompt[j] != '\t')\r
+                               {\r
                                        is_blank = 0;\r
+                                       break;\r
+                               }\r
+                       }\r
 \r
                        if(is_blank)\r
                        {\r
@@ -634,8 +1256,106 @@ fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex
                }\r
                \r
                context->command_line = strdup(line);\r
+\r
+               xbt_str_ltrim(context->command_line," ");\r
+               \r
                context->line = /*strdup(filepos)*/ filepos;\r
                context->pos = strdup(filepos);\r
+               \r
+               #ifdef WIN32\r
+               {\r
+\r
+               /* translate the command line */\r
+\r
+               char* path;\r
+               char* delimiter;\r
+               char command_line[PATH_MAX + 1] = {0};\r
+               size_t i = 0;\r
+               char* args = NULL;\r
+\r
+               \r
+\r
+               if(strstr(context->command_line,".exe"))\r
+                       strcpy(command_line,context->command_line);\r
+               else\r
+               {\r
+                       size_t len;\r
+                       \r
+                       size_t j = 0;\r
+       \r
+                       len = strlen(context->command_line);\r
+                       \r
+                       while(i < len)\r
+                       {\r
+                               if(context->command_line[i] != ' ' && context->command_line[i] != '\t' && context->command_line[i] != '>')\r
+                                       command_line[j++] = context->command_line[i];\r
+                               else\r
+                                       break;\r
+                                       \r
+                               i++;\r
+                       }\r
+\r
+                       strcat(command_line,".exe");\r
+\r
+                       args = strdup(context->command_line + i);\r
+               }\r
+               \r
+               if(getpath(command_line, &path) && !is_w32_cmd(command_line, fstream->unit->runner->path))\r
+               {\r
+                       ERROR3("[%s] `%s' : NOK (%s)", filepos, context->command_line, error_to_string(ECMDNOTFOUND, 1));\r
+                       unit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);\r
+                       failure(unit);\r
+                       return;\r
+               }\r
+               \r
+               delimiter = strrchr(command_line,'/');\r
+\r
+               if(!delimiter)\r
+                       delimiter = strrchr(command_line,'\\');\r
+               \r
+               /*free(context->command_line);*/\r
+               \r
+               \r
+               if(path)\r
+               {\r
+                       if(args)\r
+                       {\r
+                               context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + strlen(args) + 2, sizeof(char));\r
+                               sprintf(context->t_command_line,"%s\\%s%s",path,delimiter ? delimiter + 1 : command_line, args);\r
+\r
+                               free(args);\r
+\r
+                       }\r
+                       else\r
+                       {\r
+                               context->t_command_line = (char*)calloc(strlen(path) + strlen(delimiter ? delimiter + 1 : command_line) + 2, sizeof(char));\r
+                               sprintf(context->t_command_line,"%s\\%s",path,delimiter ? delimiter + 1 : command_line);\r
+                       }\r
+               \r
+                       free(path);\r
+               }\r
+               else\r
+               {\r
+                       if(args)\r
+                       {\r
+                               context->t_command_line = (char*)calloc(strlen(command_line) + strlen(args) + 1, sizeof(char));\r
+                               sprintf(context->t_command_line,"%s%s",command_line, args);\r
+\r
+                               free(args);\r
+\r
+                       }\r
+                       else\r
+                       {\r
+                               context->t_command_line = (char*)calloc(strlen(command_line) + 1, sizeof(char));\r
+                               strcpy(context->t_command_line,command_line);\r
+                       }\r
+               }\r
+\r
+\r
+               }\r
+               #endif\r
+\r
+\r
                break;\r
                \r
                case '<':\r
@@ -1163,8 +1883,19 @@ fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex
                        if(!env && !err)\r
                        {\r
                                if(exists)\r
+                               {\r
                                        /*xbt_dynar_remove_at(unit->runner->variables, i, NULL);*/\r
-                                       xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
+                                       /*xbt_dynar_cursor_rm(unit->runner->variables, &i);*/\r
+                                       if(variable->val)\r
+                                       {\r
+                                               free(variable->val);\r
+                                               variable->val = NULL;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               WARN2("[%s] Variable `(%s)' already unseted",filepos, variable->name);\r
+                                       }\r
+                               }       \r
                                else\r
                                {\r
                                        ERROR2("[%s] `(%s)' variable not found",filepos, name); \r
index 54d1a24..40b9880 100644 (file)
@@ -1,5 +1,7 @@
 #include <com.h>\r
 \r
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
+\r
 /*#include <stdlib.h>\r
 #include <string.h>\r
 \r
@@ -300,13 +302,14 @@ translatepath(const char* totranslate, char** translated)
        return len;\r
 }\r
 #else\r
-int\r
+/*int\r
 getpath(const char* file, char** path)\r
 {\r
        DWORD len;\r
        char* part = NULL;\r
        char buffer[PATH_MAX + 1] = {0}; \r
        struct stat info = {0};\r
+\r
        \r
        len = GetFullPathName(file, PATH_MAX, buffer, &part );\r
        \r
@@ -315,7 +318,6 @@ getpath(const char* file, char** path)
                *path = NULL;\r
                return -1;\r
        }\r
-\r
        \r
        if(stat(buffer, &info) || !S_ISREG(info.st_mode))\r
        {\r
@@ -330,8 +332,54 @@ getpath(const char* file, char** path)
        *path = strncpy(*path, buffer, strlen(buffer) - strlen(part) - 1);\r
 \r
        return (int)(strlen(buffer) - strlen(part) -1);\r
+}*/\r
+\r
+int\r
+getpath(const char* file, char** path)\r
+{\r
+       char buf1[PATH_MAX + 1] = {0};\r
+       char buf2[PATH_MAX + 1] = {0};\r
+       struct stat info = {0};\r
+\r
+       char* delimiter;
+       
+       if(!file)\r
+       {\r
+               *path = NULL;\r
+               return -1;\r
+       }
+
+       delimiter = strrchr(file,'/');
+
+       if(!delimiter)
+               delimiter = strrchr(file,'\\');\r
+\r
+       if(!delimiter)\r
+       {\r
+               *path = getcwd(NULL,0);\r
+       }\r
+       else\r
+       {\r
+               strncpy(buf2, file, (delimiter - file));\r
+\r
+               if(translatepath(buf2, path) < 0)\r
+                       return -1;\r
+       }\r
+\r
+       sprintf(buf1,"%s\\%s", *path, delimiter ? delimiter + 1 : file);\r
+       \r
+       if(stat(buf1, &info) || !S_ISREG(info.st_mode))\r
+       {\r
+               free(*path);\r
+               *path = NULL;\r
+               errno = ENOENT;\r
+               return -1;\r
+       }               \r
+       \r
+       return (int) strlen(*path);\r
 }\r
 \r
+\r
 int\r
 translatepath(const char* totranslate, char** translated)\r
 {\r
@@ -363,6 +411,7 @@ translatepath(const char* totranslate, char** translated)
        {\r
                *translated = getcwd(NULL,0);\r
                (*translated)[2] = '\0';\r
+\r
                return (int)strlen(*translated);\r
        }\r
        /* it's a relative directory name build the full directory name */\r
@@ -401,7 +450,7 @@ translatepath(const char* totranslate, char** translated)
                                break;\r
                }\r
        }\r
-       \r
+\r
        if(j == 1 && buffer1[i - 1] == '/')\r
        {\r
                /* perhaps it's a relative directory : `dir/' */\r
@@ -412,7 +461,7 @@ translatepath(const char* totranslate, char** translated)
                        getcwd(buffer1, PATH_MAX + 1);\r
                        strcat(buffer1,"\\");\r
                        strcat(buffer1,buffer2);\r
-                       \r
+\r
                        *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char));\r
                        strcpy(*translated, buffer1);\r
 \r
@@ -447,6 +496,7 @@ translatepath(const char* totranslate, char** translated)
        len = (int)strlen(buffer2);\r
        \r
        *translated = (char*) calloc(len + 1, sizeof(char));\r
+       strcpy(*translated, buffer2);\r
        \r
        if(!(*translated))\r
        {\r
index 851fcad..ddff421 100644 (file)
@@ -96,7 +96,7 @@ reader_start_routine(void* p)
                        if(number_of_bytes_readed > 0) \r
                        {\r
                                for(i= 0, j= 0; i < number_of_bytes_readed; i++)\r
-                                       if((int)(buffer[i]) != 13)\r
+                                       if((buffer[i]) != '\r')\r
                                                clean[j++] = buffer[i];\r
 \r
                                xbt_strbuff_append(output,clean);\r
index 7c6b6ae..075c765 100644 (file)
-/*
- * src/runner.c - type representing the runner.
- *
- * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. 
- *
- * This program is free software; you can redistribute it and/or modify it 
- * under the terms of the license (GNU LGPL) which comes with this package.
- *
- * Purpose:
- *             This file contains all the definitions of the functions related with
- *             the tesh runner type.
- *
- */
-#include <runner.h>
-#include <units.h>
-#include <unit.h>
-#include <xerrno.h>
-#include <variable.h>
-
-#include <errno.h>     /* for error code       */
-#include <stdlib.h>    /* for calloc()         */
-#include <stdio.h>
-
-#include <readline.h>
-
-#ifndef WIN32
-#include <sys/resource.h>
-#include <explode.h>
-#endif
-
-
-
-
-#define _RUNNER_HASHCODE               0xFEFEAAAA      
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
-
-#if (!defined(__BUILTIN) && defined(__CHKCMD) && !defined(WIN32))
-static const char* builtin[] =
-{
-       "alias",
-       "bind",
-       "builtin",
-       "caller",
-       "cd",
-       "command",
-       "compgen",
-       "complete",
-       "declare",
-       "disown",
-       "echo",
-       "enable",
-       "eval",
-       "exec",
-       "export",
-       "false",
-       "fc",
-       "function",
-       "getopts",
-       "hash",
-       "history",
-       "jobs",
-       "let",
-       "logout",
-       "printf",
-       "pwd",
-       "readonly",
-       "shift",
-       "shopt",
-       "source",
-       "suspend",
-       "test",
-       "time",
-       "times",
-       "trap",
-       "true",
-       "type",
-       "typeset",
-       "ulimit",
-       "umask",
-       "unalias",
-       "unset",
-       NULL
-};
-
-#define __BUILTIN_MAX ((size_t)42)
-#endif
-
-#ifndef WIN32
-extern char**
-environ;
-#endif
-
-/* the unique tesh runner */
-static runner_t
-runner = NULL;
-
-/* wait for the tesh runner terminaison        */
-static void
-runner_wait(void);
-
-static void*
-runner_start_routine(void* p);
-
-
-/* check the syntax of the tesh files if 
- * the check_syntax_flag is specified. Returns
- * 0 if the syntax is clean.
- */
-/*static void
-check_syntax(void);*/
-
-#ifdef WIN32
-
-static HANDLE 
-timer_handle = NULL;
-
-
-static void*
-runner_start_routine(void* p)
-{
-       
-    LARGE_INTEGER li;
-
-    li.QuadPart=- runner->timeout * 10000000;  /* 10000000 = 10 000 000 * 100 nanoseconds = 1 second */
-
-    /* create the waitable timer */
-    timer_handle = CreateWaitableTimer(NULL, TRUE, NULL);
-
-    /* set a timer to wait for timeout seconds */
-    SetWaitableTimer(timer_handle, &li, 0, NULL, NULL, 0);
-    
-    /* wait for the timer */
-    WaitForSingleObject(timer_handle, INFINITE);
-
-       if(runner->waiting)
-       {
-               exit_code = ELEADTIME;
-               err_kind = 1;
-               runner->timeouted = 1;
-               xbt_os_sem_release(units_sem);
-       }
-
-       return NULL;
-}
-
-#else
-static void*
-runner_start_routine(void* p)
-{
-       struct timespec ts;
-       int timeout = runner->timeout;
-       
-       
-       while(timeout-- && runner->waiting)
-       {
-               ts.tv_sec = 1;
-               ts.tv_nsec = 0L;
-
-               do
-               {
-                       nanosleep(&ts, &ts);
-               }while(EINTR == errno);
-       }
-       
-       if(errno)
-       {
-               /* TODO process the error */
-       }
-       else
-       {
-               if(runner->waiting)
-               {
-                       exit_code = ELEADTIME;
-                       err_kind = 1;
-                       runner->timeouted = 1;
-                       xbt_os_sem_release(units_sem);
-               }
-       }
-       
-       return NULL;
-}
-#endif
-
-
-int
-runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
-{
-       
-       int i;
-       char* val;
-       char buffer[PATH_MAX + 1] = {0};
-
-       int code;
-       const char* cstr;
-       variable_t variable;
-       
-       #if (defined(__CHKCMD) && defined(__BUILTIN) && !defined(WIN32))
-       FILE* s;
-       int n = 0;
-       size_t len;
-       char* line = NULL;
-       int is_blank;
-       #endif
-       
-       
-       if(runner)
-       {
-               ERROR0("The runner is already initialized");
-               return -1;
-       }
-               
-       runner = xbt_new0(s_runner_t, 1);
-       
-       runner->path = NULL;
-       runner->builtin = NULL;
-       
-       if(!(runner->units = units_new(runner, fstreams)))
-       {
-               free(runner);
-               runner = NULL;
-               return -1;
-       }
-
-       runner->timeout = timeout;
-       runner->timeouted = 0;
-       runner->interrupted = 0;
-       runner->number_of_ended_units = 0;
-       runner->number_of_runned_units = 0;
-       runner->waiting = 0;
-       
-       runner->total_of_tests = 0;
-       runner->total_of_successeded_tests = 0;
-       runner->total_of_failed_tests = 0;
-       runner->total_of_interrupted_tests = 0;
-       
-       runner->total_of_units = 0;
-       runner->total_of_successeded_units = 0;
-       runner->total_of_failed_units = 0;
-       runner->total_of_interrupted_units = 0;
-       
-       runner->total_of_suites = 0;
-       runner->total_of_successeded_suites = 0;
-       runner->total_of_failed_suites = 0;
-       runner->total_of_interrupted_suites = 0;
-       
-       /* initialize the vector of variables */
-       runner->variables = xbt_dynar_new(sizeof(variable_t), (void_f_pvoid_t)variable_free);
-       
-       /* add the environment variables in the vector */
-       for(i = 0; environ[i] != NULL; i++)
-       {
-               val = strchr(environ[i], '=');
-               
-               if(val)
-               {
-                       val++;
-                               
-                       if(val[0] != '\0')
-                               strncpy(buffer, environ[i], (val - environ[i] -1));
-                               
-                       if(!strcmp("TESH_PPID", buffer))
-                               is_tesh_root = 0;
-                       
-                       variable = variable_new(buffer, val);
-                       variable->env = 1;
-                       xbt_dynar_push(runner->variables, &variable);
-                       
-                       #ifndef WIN32
-                       if(!strcmp("PATH", buffer))
-                       {
-                               char* p;
-                               size_t j,k, len;
-                               
-                               /* get the list of paths */
-                               
-                               runner->path = explode(':', val);
-
-                               /* remove spaces and backslahes at the end of the path */
-                               for (k = 0; runner->path[k] != NULL; k++)
-                               {
-                               p = runner->path[k];
-                               
-                               len = strlen(p);
-                               
-                               for(j = len - 1; p[j] == '/' || p[j] == ' '; j--)
-                                       
-                                       p[j] = '\0';
-                               }
-                       }
-                       #endif
-                               
-                       memset(buffer, 0, PATH_MAX + 1);
-               }
-       }
-       
-       if(is_tesh_root)
-       {
-               char* tesh_dir = getcwd(NULL, 0);
-               
-               sprintf(buffer,"%d",getpid());
-               
-               #ifndef WIN32
-               setenv("TESH_PPID", buffer, 0);
-               setenv("TESH_DIR", tesh_dir, 0);
-               #else
-               SetEnvironmentVariable("TESH_PPID", buffer);
-               SetEnvironmentVariable("TESH_DIR", tesh_dir);
-               #endif
-               
-               variable = variable_new("TESH_PPID", buffer);
-               variable->err = 1;
-                       
-               xbt_dynar_push(runner->variables, &variable);
-
-               variable = variable_new("TESH_DIR", tesh_dir);
-               variable->err = 1;
-                       
-               xbt_dynar_push(runner->variables, &variable);
-               
-               free(tesh_dir);
-       }
-       
-       variable = variable_new("EXIT_SUCCESS", "0");
-       variable->err = 1;
-                       
-       xbt_dynar_push(runner->variables, &variable);
-
-       variable = variable_new("EXIT_FAILURE", "1");
-       variable->err = 1;
-                       
-       xbt_dynar_push(runner->variables, &variable);
-
-       variable = variable_new("TRUE", "0");
-       variable->err = 1;
-                       
-       xbt_dynar_push(runner->variables, &variable);
-
-       variable = variable_new("FALSE", "1");
-       variable->err = 1;
-                       
-       xbt_dynar_push(runner->variables, &variable);
-
-       i = 0;
-       
-       /* add the errors variables */
-       while((cstr = error_get_at(i++, &code)))
-       {
-               sprintf(buffer,"%d",code);
-               variable = variable_new(cstr, buffer);
-               variable->err = 1;
-               xbt_dynar_push(runner->variables, &variable);
-       }
-       
-       /* if the user want check the syntax, check it */
-       /*if(check_syntax_flag)
-               check_syntax();
-       */
-       
-       #if (!defined(WIN32) && defined(__CHKCMD))
-       #if defined(__BUILTIN)
-       
-       if(!is_tesh_root)
-       {
-               /* compute the full path the builtin.def file */
-               sprintf(buffer,"%s/builtin.def",getenv("TESH_DIR"));
-               
-               if(!(s = fopen(buffer, "r")))   
-               {
-                       ERROR1("File `(%s)' not found", buffer);
-                       return -1;
-               }
-               
-       }
-       else
-       {
-               if(!(s = fopen("builtin.def", "r")))    
-               {
-                       ERROR0("File `(builtin.def)' not found");
-                       return -1;
-               }
-       }
-       
-       if(s)
-       {
-               fpos_t begin;
-
-               fgetpos(s, &begin);
-
-               while(readline(s, &line, &len) != -1)
-               {
-                       i = 0;
-                       is_blank = 1;
-                       
-
-                       while(line[i] != '\0') 
-                       {
-                               if (line[i] != ' ' && line[i] != '\t' && line[i]!='\n' && line[i]!='\r')
-                               {
-                                       is_blank = 0;
-                                       break;
-                               }
-                               
-                               i++;
-                       }
-
-                       if(!is_blank)
-                               n++;
-               }
-
-               fsetpos(s, &begin);
-               free(line);
-               line = NULL;
-
-               if(n)
-               {
-                       char* l;
-                       
-                       runner->builtin = xbt_new0(char*, n + 1); /* (char**) calloc(n + 1, sizeof(char*));*/
-                       
-                       n = 0;
-                       
-                       while(readline(s, &line, &len) != -1)
-                       {
-                               i = 0;
-                               is_blank = 1;
-
-                               while(line[i] != '\0') 
-                               {
-                                       if (line[i] != ' ' && line[i] != '\t' && line[i]!='\n' && line[i]!='\r')
-                                       {
-                                               is_blank = 0;
-                                               break;
-                                       }
-                                       
-                                       i++;
-                               }
-
-                               if(!is_blank)
-                               {
-                                       l = strdup(line);
-
-                                       l[strlen(l) - 1] = '\0';
-
-                                       (runner->builtin)[n++] = l;
-                                       
-                               }
-                       }
-                       
-               }
-               else
-               {
-                       WARN0("The file `(builtin.def)' is empty");
-                       free(runner->builtin);
-                       runner->builtin = NULL;
-               }
-               
-
-               fclose(s);
-               
-               if(line)
-                       free(line);
-               
-       }
-       
-       #else
-               runner->builtin = xbt_new0(char*, __BUILTIN_MAX + 1); /* (char**) calloc(__BUILTIN_MAX + 1, sizeof(char*));*/
-               
-               for(i = 0; i < __BUILTIN_MAX; i++)
-                       runner->builtin[i] = strdup(builtin[i]);        
-       #endif
-       #endif
-
-       return exit_code ? -1 : 0;
-}
-
-void
-runner_destroy(void)
-{
-       int i;
-       
-       if(runner->units)
-               units_free((void**)(&(runner->units)));
-       
-       if(runner->variables)
-               xbt_dynar_free(&runner->variables);
-       
-       #ifdef WIN32
-       CloseHandle(timer_handle);
-       #endif
-
-       if(runner->thread)
-               xbt_os_thread_join(runner->thread, NULL);
-       
-       if(runner->path)
-       {
-               for (i = 0; runner->path[i] != NULL; i++)
-                       free(runner->path[i]);
-               
-               free(runner->path);
-       }
-
-       if(runner->builtin)
-       {
-               for (i = 0; runner->builtin[i] != NULL; i++)
-                       free(runner->builtin[i]);
-               
-               free(runner->builtin);
-       }
-
-       free(runner);
-       
-
-       runner = NULL;
-}
-
-void
-runner_run(void)
-{
-       /* allocate the mutex used by the units to asynchronously access 
-        * to the properties of the runner.
-        */
-       xbt_os_mutex_t mutex = xbt_os_mutex_init();
-       
-       /* run all the units */
-       units_run_all(runner->units, mutex);
-       
-       
-       if(!interrupted)
-               runner_wait();
-
-       
-       /* if the runner is timeouted or receive a interruption request
-        * , interrupt all the active units.
-        */
-       if(runner->timeouted || interrupted)
-               runner_interrupt();
-       
-       /* joins all the units */
-       units_join_all(runner->units);
-       
-       /* release the mutex resource */
-       xbt_os_mutex_destroy(mutex);
-
-}
-
-static void
-runner_wait(void)
-{
-       if(runner->timeout > 0)
-               runner->thread = xbt_os_thread_create("", runner_start_routine, NULL);
-       
-       /* signal that the runner is waiting */
-       runner->waiting = 1;
-       
-       /* wait for the end of all the units */
-       xbt_os_sem_acquire(units_sem);
-
-       
-       runner->waiting = 0;
-}
-
-
-
-/*
- * interrupt all the active units.
- * this function is called when the lead time of the execution is reached
- * or when a failed unit requests an interruption of the execution.
- */
-void
-runner_interrupt(void)
-{
-       units_interrupt_all(runner->units);
-}
-
-void
-runner_summarize(void)
-{
-       
-       if(!dry_run_flag)
-       {
-               #ifndef WIN32
-               struct rusage r_usage;
-               #else
-               FILETIME start_time;
-               FILETIME exit_time;
-               FILETIME kernel_time;
-               FILETIME user_time;
-               SYSTEMTIME si;
-               #endif
-               
-               printf("\n  TEst SHell utility - mini shell specialized in running test units.\n");
-               printf(" =============================================================================\n");
-               
-               units_summuarize(runner->units);
-               
-               printf(" =====================================================================%s\n",
-               runner->total_of_failed_tests ? "== FAILED": (runner->total_of_interrupted_tests || runner->total_of_interrupted_units) ? "==== INTR" : "====== OK");
-               
-               printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",
-               (runner->total_of_suites ? (1-((double)runner->total_of_failed_suites + (double)runner->total_of_interrupted_suites)/(double)runner->total_of_suites)*100.0 : 100.0),
-               runner->total_of_suites, runner->total_of_successeded_suites);
-               
-               if(runner->total_of_failed_suites > 0)
-                       printf(", %d failed", runner->total_of_failed_suites);
-               
-               if(runner->total_of_interrupted_suites > 0)
-                       printf(", %d interrupted)", runner->total_of_interrupted_suites);
-               
-               printf(")\n");  
-               
-               printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",
-               (runner->total_of_units ? (1-((double)runner->total_of_failed_units + (double)runner->total_of_interrupted_units)/(double)runner->total_of_units)*100.0 : 100.0),
-               runner->total_of_units, runner->total_of_successeded_units);
-               
-               if(runner->total_of_failed_units > 0)
-                       printf(", %d failed", runner->total_of_failed_units);
-               
-               if(runner->total_of_interrupted_units > 0)
-                       printf(", %d interrupted)", runner->total_of_interrupted_units);
-               
-               printf(")\n");
-               
-               printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",
-               (runner->total_of_tests ? (1-((double)runner->total_of_failed_tests + (double)runner->total_of_interrupted_tests)/(double)runner->total_of_tests)*100.0 : 100.0),
-               runner->total_of_tests, runner->total_of_successeded_tests);
-               
-               if(runner->total_of_failed_tests > 0)
-                       printf(", %d failed", runner->total_of_failed_tests);
-               
-               if(runner->total_of_interrupted_tests > 0)
-                       printf(", %d interrupted)", runner->total_of_interrupted_tests);
-               
-               printf(")\n\n");
-               
-               #ifndef WIN32
-               if(!getrusage(RUSAGE_SELF, &r_usage))
-               {
-               
-                       printf("         Total tesh user time used:       %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
-                       printf("         Total tesh system time used:     %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
-               
-                       if(!getrusage(RUSAGE_CHILDREN, &r_usage))
-                       {
-                               printf("         Total children user time used:   %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
-                               printf("         Total children system time used: %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
-               
-                       }       
-               }
-               #else
-       
-               if(GetProcessTimes(GetCurrentProcess(), &start_time, &exit_time, &kernel_time, &user_time))
-               {
-                       FileTimeToSystemTime(&user_time, &si);
-                       
-                       printf("         Total tesh user time used:       %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );
-                       
-                       FileTimeToSystemTime(&kernel_time, &si);
-                       
-                       printf("         Total tesh kernel time used:     %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );
-               }
-
-
-
-               #endif
-       }
-       else
-       {
-               if(exit_code)
-                       ERROR0("Syntax NOK");
-               else if(!exit_code)
-                       INFO0("Syntax 0K");
-       }
-}
-
-int
-runner_is_timedout(void)
-{
-       return runner->timeouted;
-}
-
+/*\r
+ * src/runner.c - type representing the runner.\r
+ *\r
+ * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. \r
+ *\r
+ * This program is free software; you can redistribute it and/or modify it \r
+ * under the terms of the license (GNU LGPL) which comes with this package.\r
+ *\r
+ * Purpose:\r
+ *             This file contains all the definitions of the functions related with\r
+ *             the tesh runner type.\r
+ *\r
+ */\r
+#include <runner.h>\r
+#include <units.h>\r
+#include <unit.h>\r
+#include <xerrno.h>\r
+#include <variable.h>\r
+\r
+#include <errno.h>     /* for error code       */\r
+#include <stdlib.h>    /* for calloc()         */\r
+#include <stdio.h>\r
+\r
+#include <readline.h>\r
+#include <explode.h>\r
+\r
+#ifndef WIN32\r
+#include <sys/resource.h>\r
+#endif\r
+\r
+\r
+\r
+\r
+\r
+#define _RUNNER_HASHCODE               0xFEFEAAAA      \r
+\r
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
+\r
+#if (!defined(__BUILTIN) && defined(__CHKCMD) && !defined(WIN32))\r
+static const char* builtin[] =\r
+{\r
+       "alias",\r
+       "bind",\r
+       "builtin",\r
+       "caller",\r
+       "cd",\r
+       "command",\r
+       "compgen",\r
+       "complete",\r
+       "declare",\r
+       "disown",\r
+       "echo",\r
+       "enable",\r
+       "eval",\r
+       "exec",\r
+       "export",\r
+       "false",\r
+       "fc",\r
+       "function",\r
+       "getopts",\r
+       "hash",\r
+       "history",\r
+       "jobs",\r
+       "let",\r
+       "logout",\r
+       "printf",\r
+       "pwd",\r
+       "readonly",\r
+       "shift",\r
+       "shopt",\r
+       "source",\r
+       "suspend",\r
+       "test",\r
+       "time",\r
+       "times",\r
+       "trap",\r
+       "true",\r
+       "type",\r
+       "typeset",\r
+       "ulimit",\r
+       "umask",\r
+       "unalias",\r
+       "unset",\r
+       NULL\r
+};\r
+\r
+#define __BUILTIN_MAX ((size_t)42)\r
+#endif\r
+\r
+\r
+# ifdef __APPLE__\r
+/* under darwin, the environment gets added to the process at startup time. So, it's not defined at library link time, forcing us to extra tricks */\r
+# include <crt_externs.h>\r
+# define environ (*_NSGetEnviron())\r
+# elif !defined(WIN32)\r
+ /* the environment, as specified by the opengroup, used to initialize the process properties */\r
+ extern char **environ;\r
+# endif\r
+\r
+#ifndef WIN32\r
+extern char**\r
+environ;\r
+#endif\r
+\r
+/* the unique tesh runner */\r
+static runner_t\r
+runner = NULL;\r
+\r
+/* wait for the tesh runner terminaison        */\r
+static void\r
+runner_wait(void);\r
+\r
+static void*\r
+runner_start_routine(void* p);\r
+\r
+\r
+/* check the syntax of the tesh files if \r
+ * the check_syntax_flag is specified. Returns\r
+ * 0 if the syntax is clean.\r
+ */\r
+/*static void\r
+check_syntax(void);*/\r
+\r
+#ifdef WIN32\r
+\r
+static HANDLE \r
+timer_handle = NULL;\r
+\r
+\r
+static void*\r
+runner_start_routine(void* p)\r
+{\r
+       \r
+    LARGE_INTEGER li;\r
+\r
+    li.QuadPart=- runner->timeout * 10000000;  /* 10000000 = 10 000 000 * 100 nanoseconds = 1 second */\r
+\r
+    /* create the waitable timer */\r
+    timer_handle = CreateWaitableTimer(NULL, TRUE, NULL);\r
+\r
+    /* set a timer to wait for timeout seconds */\r
+    SetWaitableTimer(timer_handle, &li, 0, NULL, NULL, 0);\r
+    \r
+    /* wait for the timer */\r
+    WaitForSingleObject(timer_handle, INFINITE);\r
+\r
+       if(runner->waiting)\r
+       {\r
+               exit_code = ELEADTIME;\r
+               err_kind = 1;\r
+               runner->timeouted = 1;\r
+               xbt_os_sem_release(units_sem);\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+#else\r
+static void*\r
+runner_start_routine(void* p)\r
+{\r
+       struct timespec ts;\r
+       int timeout = runner->timeout;\r
+       \r
+       \r
+       while(timeout-- && runner->waiting)\r
+       {\r
+               ts.tv_sec = 1;\r
+               ts.tv_nsec = 0L;\r
+\r
+               do\r
+               {\r
+                       nanosleep(&ts, &ts);\r
+               }while(EINTR == errno);\r
+       }\r
+       \r
+       if(errno)\r
+       {\r
+               /* TODO process the error */\r
+       }\r
+       else\r
+       {\r
+               if(runner->waiting)\r
+               {\r
+                       exit_code = ELEADTIME;\r
+                       err_kind = 1;\r
+                       runner->timeouted = 1;\r
+                       xbt_os_sem_release(units_sem);\r
+               }\r
+       }\r
+       \r
+       return NULL;\r
+}\r
+#endif\r
+\r
+\r
+int\r
+runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)\r
+{\r
+       \r
+       int i;\r
+       char* val;\r
+       char buffer[PATH_MAX + 1] = {0};\r
+\r
+       int code;\r
+       const char* cstr;\r
+       variable_t variable;\r
+       \r
+       #if (defined(__CHKCMD) && defined(__BUILTIN) && !defined(WIN32))\r
+       FILE* s;\r
+       int n = 0;\r
+       size_t len;\r
+       char* line = NULL;\r
+       int is_blank;\r
+       #endif\r
+       \r
+       \r
+       if(runner)\r
+       {\r
+               ERROR0("The runner is already initialized");\r
+               return -1;\r
+       }\r
+               \r
+       runner = xbt_new0(s_runner_t, 1);\r
+       \r
+       runner->path = NULL;\r
+       runner->builtin = NULL;\r
+       \r
+       if(!(runner->units = units_new(runner, fstreams)))\r
+       {\r
+               free(runner);\r
+               runner = NULL;\r
+               return -1;\r
+       }\r
+\r
+       runner->timeout = timeout;\r
+       runner->timeouted = 0;\r
+       runner->interrupted = 0;\r
+       runner->number_of_ended_units = 0;\r
+       runner->number_of_runned_units = 0;\r
+       runner->waiting = 0;\r
+       \r
+       runner->total_of_tests = 0;\r
+       runner->total_of_successeded_tests = 0;\r
+       runner->total_of_failed_tests = 0;\r
+       runner->total_of_interrupted_tests = 0;\r
+       \r
+       runner->total_of_units = 0;\r
+       runner->total_of_successeded_units = 0;\r
+       runner->total_of_failed_units = 0;\r
+       runner->total_of_interrupted_units = 0;\r
+       \r
+       runner->total_of_suites = 0;\r
+       runner->total_of_successeded_suites = 0;\r
+       runner->total_of_failed_suites = 0;\r
+       runner->total_of_interrupted_suites = 0;\r
+       \r
+       /* initialize the vector of variables */\r
+       runner->variables = xbt_dynar_new(sizeof(variable_t), (void_f_pvoid_t)variable_free);\r
+       \r
+       /* add the environment variables in the vector */\r
+       for(i = 0; environ[i] != NULL; i++)\r
+       {\r
+               val = strchr(environ[i], '=');\r
+               \r
+               if(val)\r
+               {\r
+                       val++;\r
+                               \r
+                       if(val[0] != '\0')\r
+                               strncpy(buffer, environ[i], (val - environ[i] -1));\r
+                               \r
+                       if(!strcmp("TESH_PPID", buffer))\r
+                               is_tesh_root = 0;\r
+                       \r
+                       variable = variable_new(buffer, val);\r
+                       variable->env = 1;\r
+                       xbt_dynar_push(runner->variables, &variable);\r
+                       \r
+                       #ifndef WIN32\r
+                       if(!strcmp("PATH", buffer))\r
+                       #else\r
+                       if(!strcmp("Path", buffer) || !strcmp("PATH", buffer))\r
+                       #endif\r
+                       {\r
+                               char* p;\r
+                               size_t j,k, len;\r
+                               \r
+                               /* get the list of paths */\r
+                               \r
+                               #ifdef WIN32\r
+                               runner->path = explode(';', val);\r
+                               #else\r
+                               runner->path = explode(':', val);\r
+                               #endif\r
+\r
+                               /* remove spaces and backslahes at the end of the path */\r
+                               for (k = 0; runner->path[k] != NULL; k++)\r
+                               {\r
+                               p = runner->path[k];\r
+                               \r
+                               len = strlen(p);\r
+                               \r
+                                       #ifndef WIN32\r
+                               for(j = len - 1; p[j] == '/' || p[j] == ' '; j--)\r
+                                       #else\r
+                                       for(j = len - 1; p[j] == '\\' || p[j] == ' '; j--)\r
+                                       #endif\r
+                                       p[j] = '\0';\r
+                               }\r
+                       }\r
+                       \r
+                               \r
+                       memset(buffer, 0, PATH_MAX + 1);\r
+               }\r
+       }\r
+       \r
+       if(is_tesh_root)\r
+       {\r
+               char* tesh_dir = getcwd(NULL, 0);\r
+               \r
+               sprintf(buffer,"%d",getpid());\r
+               \r
+               #ifndef WIN32\r
+               setenv("TESH_PPID", buffer, 0);\r
+               setenv("TESH_DIR", tesh_dir, 0);\r
+               #else\r
+               SetEnvironmentVariable("TESH_PPID", buffer);\r
+               SetEnvironmentVariable("TESH_DIR", tesh_dir);\r
+               #endif\r
+               \r
+               variable = variable_new("TESH_PPID", buffer);\r
+               variable->err = 1;\r
+                       \r
+               xbt_dynar_push(runner->variables, &variable);\r
+\r
+               variable = variable_new("TESH_DIR", tesh_dir);\r
+               variable->err = 1;\r
+                       \r
+               xbt_dynar_push(runner->variables, &variable);\r
+               \r
+               free(tesh_dir);\r
+       }\r
+       \r
+       variable = variable_new("EXIT_SUCCESS", "0");\r
+       variable->err = 1;\r
+                       \r
+       xbt_dynar_push(runner->variables, &variable);\r
+\r
+       variable = variable_new("EXIT_FAILURE", "1");\r
+       variable->err = 1;\r
+                       \r
+       xbt_dynar_push(runner->variables, &variable);\r
+\r
+       variable = variable_new("TRUE", "0");\r
+       variable->err = 1;\r
+                       \r
+       xbt_dynar_push(runner->variables, &variable);\r
+\r
+       variable = variable_new("FALSE", "1");\r
+       variable->err = 1;\r
+                       \r
+       xbt_dynar_push(runner->variables, &variable);\r
+\r
+       i = 0;\r
+       \r
+       /* add the errors variables */\r
+       while((cstr = error_get_at(i++, &code)))\r
+       {\r
+               sprintf(buffer,"%d",code);\r
+               variable = variable_new(cstr, buffer);\r
+               variable->err = 1;\r
+               xbt_dynar_push(runner->variables, &variable);\r
+       }\r
+       \r
+       /* if the user want check the syntax, check it */\r
+       /*if(check_syntax_flag)\r
+               check_syntax();\r
+       */\r
+       \r
+       #if (!defined(WIN32) && defined(__CHKCMD))\r
+       #if defined(__BUILTIN)\r
+       \r
+       if(!is_tesh_root)\r
+       {\r
+               /* compute the full path the builtin.def file */\r
+               sprintf(buffer,"%s/builtin.def",getenv("TESH_DIR"));\r
+               \r
+               if(!(s = fopen(buffer, "r")))   \r
+               {\r
+                       ERROR1("File `(%s)' not found", buffer);\r
+                       return -1;\r
+               }\r
+               \r
+       }\r
+       else\r
+       {\r
+               if(!(s = fopen("builtin.def", "r")))    \r
+               {\r
+                       ERROR0("File `(builtin.def)' not found");\r
+                       return -1;\r
+               }\r
+       }\r
+       \r
+       if(s)\r
+       {\r
+               fpos_t begin;\r
+\r
+               fgetpos(s, &begin);\r
+\r
+               while(readline(s, &line, &len) != -1)\r
+               {\r
+                       i = 0;\r
+                       is_blank = 1;\r
+                       \r
+\r
+                       while(line[i] != '\0') \r
+                       {\r
+                               if (line[i] != ' ' && line[i] != '\t' && line[i]!='\n' && line[i]!='\r')\r
+                               {\r
+                                       is_blank = 0;\r
+                                       break;\r
+                               }\r
+                               \r
+                               i++;\r
+                       }\r
+\r
+                       if(!is_blank)\r
+                               n++;\r
+               }\r
+\r
+               fsetpos(s, &begin);\r
+               free(line);\r
+               line = NULL;\r
+\r
+               if(n)\r
+               {\r
+                       char* l;\r
+                       \r
+                       runner->builtin = xbt_new0(char*, n + 1); /* (char**) calloc(n + 1, sizeof(char*));*/\r
+                       \r
+                       n = 0;\r
+                       \r
+                       while(readline(s, &line, &len) != -1)\r
+                       {\r
+                               i = 0;\r
+                               is_blank = 1;\r
+\r
+                               while(line[i] != '\0') \r
+                               {\r
+                                       if (line[i] != ' ' && line[i] != '\t' && line[i]!='\n' && line[i]!='\r')\r
+                                       {\r
+                                               is_blank = 0;\r
+                                               break;\r
+                                       }\r
+                                       \r
+                                       i++;\r
+                               }\r
+\r
+                               if(!is_blank)\r
+                               {\r
+                                       l = strdup(line);\r
+\r
+                                       l[strlen(l) - 1] = '\0';\r
+\r
+                                       (runner->builtin)[n++] = l;\r
+                                       \r
+                               }\r
+                       }\r
+                       \r
+               }\r
+               else\r
+               {\r
+                       WARN0("The file `(builtin.def)' is empty");\r
+                       free(runner->builtin);\r
+                       runner->builtin = NULL;\r
+               }\r
+               \r
+\r
+               fclose(s);\r
+               \r
+               if(line)\r
+                       free(line);\r
+               \r
+       }\r
+       \r
+       #else\r
+               runner->builtin = xbt_new0(char*, __BUILTIN_MAX + 1); /* (char**) calloc(__BUILTIN_MAX + 1, sizeof(char*));*/\r
+               \r
+               for(i = 0; i < __BUILTIN_MAX; i++)\r
+                       runner->builtin[i] = strdup(builtin[i]);        \r
+       #endif\r
+       #endif\r
+\r
+       return exit_code ? -1 : 0;\r
+}\r
+\r
+void\r
+runner_destroy(void)\r
+{\r
+       int i;\r
+       \r
+       if(runner->units)\r
+               units_free((void**)(&(runner->units)));\r
+       \r
+       if(runner->variables)\r
+               xbt_dynar_free(&runner->variables);\r
+       \r
+       #ifdef WIN32\r
+       CloseHandle(timer_handle);\r
+       #endif\r
+\r
+       if(runner->thread)\r
+               xbt_os_thread_join(runner->thread, NULL);\r
+       \r
+       if(runner->path)\r
+       {\r
+               for (i = 0; runner->path[i] != NULL; i++)\r
+                       free(runner->path[i]);\r
+               \r
+               free(runner->path);\r
+       }\r
+\r
+       if(runner->builtin)\r
+       {\r
+               for (i = 0; runner->builtin[i] != NULL; i++)\r
+                       free(runner->builtin[i]);\r
+               \r
+               free(runner->builtin);\r
+       }\r
+\r
+       free(runner);\r
+       \r
+\r
+       runner = NULL;\r
+}\r
+\r
+void\r
+runner_run(void)\r
+{\r
+       /* allocate the mutex used by the units to asynchronously access \r
+        * to the properties of the runner.\r
+        */\r
+       xbt_os_mutex_t mutex = xbt_os_mutex_init();\r
+       \r
+       /* run all the units */\r
+       units_run_all(runner->units, mutex);\r
+       \r
+       \r
+       if(!interrupted)\r
+               runner_wait();\r
+\r
+       \r
+       /* if the runner is timeouted or receive a interruption request\r
+        * , interrupt all the active units.\r
+        */\r
+       if(runner->timeouted || interrupted)\r
+               runner_interrupt();\r
+       \r
+       /* joins all the units */\r
+       units_join_all(runner->units);\r
+       \r
+       /* release the mutex resource */\r
+       xbt_os_mutex_destroy(mutex);\r
+\r
+}\r
+\r
+static void\r
+runner_wait(void)\r
+{\r
+       if(runner->timeout > 0)\r
+               runner->thread = xbt_os_thread_create("", runner_start_routine, NULL);\r
+       \r
+       /* signal that the runner is waiting */\r
+       runner->waiting = 1;\r
+       \r
+       /* wait for the end of all the units */\r
+       xbt_os_sem_acquire(units_sem);\r
+\r
+       \r
+       runner->waiting = 0;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * interrupt all the active units.\r
+ * this function is called when the lead time of the execution is reached\r
+ * or when a failed unit requests an interruption of the execution.\r
+ */\r
+void\r
+runner_interrupt(void)\r
+{\r
+       units_interrupt_all(runner->units);\r
+}\r
+\r
+void\r
+runner_summarize(void)\r
+{\r
+       \r
+       if(!dry_run_flag)\r
+       {\r
+               #ifndef WIN32\r
+               struct rusage r_usage;\r
+               #else\r
+               FILETIME start_time;\r
+               FILETIME exit_time;\r
+               FILETIME kernel_time;\r
+               FILETIME user_time;\r
+               SYSTEMTIME si;\r
+               #endif\r
+               \r
+               printf("\n  TEst SHell utility - mini shell specialized in running test units.\n");\r
+               printf(" =============================================================================\n");\r
+               \r
+               units_summuarize(runner->units);\r
+               \r
+               printf(" =====================================================================%s\n",\r
+               runner->total_of_failed_tests ? "== FAILED": (runner->total_of_interrupted_tests || runner->total_of_interrupted_units) ? "==== INTR" : "====== OK");\r
+               \r
+               printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",\r
+               (runner->total_of_suites ? (1-((double)runner->total_of_failed_suites + (double)runner->total_of_interrupted_suites)/(double)runner->total_of_suites)*100.0 : 100.0),\r
+               runner->total_of_suites, runner->total_of_successeded_suites);\r
+               \r
+               if(runner->total_of_failed_suites > 0)\r
+                       printf(", %d failed", runner->total_of_failed_suites);\r
+               \r
+               if(runner->total_of_interrupted_suites > 0)\r
+                       printf(", %d interrupted)", runner->total_of_interrupted_suites);\r
+               \r
+               printf(")\n");  \r
+               \r
+               printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",\r
+               (runner->total_of_units ? (1-((double)runner->total_of_failed_units + (double)runner->total_of_interrupted_units)/(double)runner->total_of_units)*100.0 : 100.0),\r
+               runner->total_of_units, runner->total_of_successeded_units);\r
+               \r
+               if(runner->total_of_failed_units > 0)\r
+                       printf(", %d failed", runner->total_of_failed_units);\r
+               \r
+               if(runner->total_of_interrupted_units > 0)\r
+                       printf(", %d interrupted)", runner->total_of_interrupted_units);\r
+               \r
+               printf(")\n");\r
+               \r
+               printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",\r
+               (runner->total_of_tests ? (1-((double)runner->total_of_failed_tests + (double)runner->total_of_interrupted_tests)/(double)runner->total_of_tests)*100.0 : 100.0),\r
+               runner->total_of_tests, runner->total_of_successeded_tests);\r
+               \r
+               if(runner->total_of_failed_tests > 0)\r
+                       printf(", %d failed", runner->total_of_failed_tests);\r
+               \r
+               if(runner->total_of_interrupted_tests > 0)\r
+                       printf(", %d interrupted)", runner->total_of_interrupted_tests);\r
+               \r
+               printf(")\n\n");\r
+               \r
+               #ifndef WIN32\r
+               if(!getrusage(RUSAGE_SELF, &r_usage))\r
+               {\r
+               \r
+                       printf("         Total tesh user time used:       %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);\r
+                       printf("         Total tesh system time used:     %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);\r
+               \r
+                       if(!getrusage(RUSAGE_CHILDREN, &r_usage))\r
+                       {\r
+                               printf("         Total children user time used:   %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);\r
+                               printf("         Total children system time used: %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);\r
+               \r
+                       }       \r
+               }\r
+               #else\r
+       \r
+               if(GetProcessTimes(GetCurrentProcess(), &start_time, &exit_time, &kernel_time, &user_time))\r
+               {\r
+                       FileTimeToSystemTime(&user_time, &si);\r
+                       \r
+                       printf("         Total tesh user time used:       %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );\r
+                       \r
+                       FileTimeToSystemTime(&kernel_time, &si);\r
+                       \r
+                       printf("         Total tesh kernel time used:     %uhour(s) %uminute(s) %usecond(s) %millisecond(s)\n", si.wHour, si.wMinute, si.wSecond, si.wMilliseconds );\r
+               }\r
+\r
+\r
+\r
+               #endif\r
+       }\r
+       else\r
+       {\r
+               if(exit_code)\r
+                       ERROR0("Syntax NOK");\r
+               else if(!exit_code)\r
+                       INFO0("Syntax 0K");\r
+       }\r
+}\r
+\r
+int\r
+runner_is_timedout(void)\r
+{\r
+       return runner->timeouted;\r
+}\r
+\r
index 5c86833..e53c505 100644 (file)
@@ -5,7 +5,7 @@
 \r
 #include <stdio.h>\r
 \r
-int\r
+/*int\r
 str_replace(char** str, const char* what, const char* with)\r
 {\r
        size_t pos, i;\r
@@ -53,8 +53,187 @@ str_replace(char** str, const char* what, const char* with)
        return 0;\r
  \r
 } \r
+*/\r
+\r
+/* last version int\r
+str_replace(char** str, const char* what, const char* with, const char* delimiters)\r
+{\r
+       size_t pos, i, len;\r
+       char* begin;\r
+       char* buf;\r
+       char* delimited;\r
+       int size;\r
+\r
+       if(!*str || !what || !with || !delimiters)\r
+       {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       \r
+       if(!(delimited = (char*) calloc((strlen(what) + 2) , sizeof(char))))\r
+               return -1;\r
+\r
+       len = strlen(delimiters);\r
+\r
+       for(i = 0; i < len; i++)\r
+       {\r
+               memset(delimited, 0, (strlen(what) + 2));\r
+\r
+               sprintf(delimited,"%s%c", what, delimiters[i]);\r
+               \r
+               if((begin = strstr(*str, delimited)))\r
+                       break;\r
+       }\r
+       \r
+       free(delimited);\r
+       \r
+       \r
+       if(!begin && (size = (int)strlen(*str) - (int)strlen(what)) >= 0 && !strcmp(*str + size, what))\r
+               begin = strstr(*str, what);\r
+       \r
+       if(!begin)\r
+       {\r
+               errno = ESRCH;\r
+               return -1;\r
+       }\r
+       \r
+       pos = begin - *str;\r
+       \r
+       i = 0;\r
+       \r
+       pos += strlen(what);\r
+\r
+       if(begin == *str)\r
+       {\r
+               \r
+\r
+               if(!(buf = (char*) calloc(strlen(with) + ((pos < strlen(*str)) ? strlen(*str + pos) : 0) + 1, sizeof(char))))\r
+                       return -1;\r
+                       \r
+               strcpy(buf, with);\r
+               \r
+               if(pos < strlen(*str))\r
+                       strcpy(buf + strlen(with), *str + pos);\r
+       }\r
+       else\r
+       {\r
+               if(!(buf = (char*) calloc((begin - *str) + strlen(with) + ((pos < strlen(*str)) ? strlen(*str + pos) : 0) + 1, sizeof(char))))\r
+                       return -1;\r
+               \r
+               strncpy(buf, *str,  (begin - *str));\r
+               strcpy(buf + (begin - *str) , with);\r
+\r
+               if(pos < strlen(*str))\r
+                       strcpy(buf + (begin - *str) + strlen(with), *str + pos);\r
+       }       \r
+       \r
+       free(*str);;\r
+       *str = buf;\r
+       \r
+       return 0;\r
\r
+}*/\r
 \r
 int\r
+str_replace(char** str, const char* what, const char* with, const char* delimiters)\r
+{\r
+       size_t pos, i, len;\r
+       char* begin;\r
+       char* buf;\r
+       int size;\r
+\r
+       if(!*str || !what)\r
+       {\r
+               errno = EINVAL;\r
+               return -1;\r
+       }\r
+\r
+       if(delimiters)\r
+       {\r
+               char* delimited;\r
+\r
+               if(!(delimited = (char*) calloc((strlen(what) + 2) , sizeof(char))))\r
+                       return -1;\r
+\r
+               len = strlen(delimiters);\r
+\r
+               for(i = 0; i < len; i++)\r
+               {\r
+                       memset(delimited, 0, (strlen(what) + 2));\r
+\r
+                       sprintf(delimited,"%s%c", what, delimiters[i]);\r
+                       \r
+                       if((begin = strstr(*str, delimited)))\r
+                               break;\r
+               }\r
+               \r
+               free(delimited);\r
+       }\r
+       else\r
+               begin = strstr(*str, what);\r
+       \r
+       \r
+       if(!begin && (size = (int)strlen(*str) - (int)strlen(what)) >= 0 && !strcmp(*str + size, what))\r
+               begin = strstr(*str, what);\r
+       \r
+       if(!begin)\r
+       {\r
+               errno = ESRCH;\r
+               return -1;\r
+       }\r
+       \r
+       pos = begin - *str;\r
+       \r
+       i = 0;\r
+       \r
+       pos += strlen(what);\r
+\r
+       if(begin == *str)\r
+       {\r
+               if(!(buf = (char*) calloc((with ? strlen(with) : 0) + ((pos < strlen(*str)) ? strlen(*str + pos) : 0) + 1, sizeof(char))))\r
+                       return -1;\r
+                       \r
+               if(with)\r
+                       strcpy(buf, with);\r
+               \r
+               if(pos < strlen(*str))\r
+                       strcpy(buf + (with ? strlen(with) : 0), *str + pos);\r
+       }\r
+       else\r
+       {\r
+               if(!(buf = (char*) calloc((begin - *str) + (with ? strlen(with) : 0) + ((pos < strlen(*str)) ? strlen(*str + pos) : 0) + 1, sizeof(char))))\r
+                       return -1;\r
+               \r
+               strncpy(buf, *str,  (begin - *str));\r
+               \r
+               if(with)\r
+                       strcpy(buf + (begin - *str) , with);\r
+\r
+               if(pos < strlen(*str))\r
+                       strcpy(buf + (begin - *str) + (with ? strlen(with) : 0), *str + pos);\r
+       }       \r
+       \r
+       free(*str);\r
+\r
+       *str = buf;\r
+       \r
+       return 0;\r
\r
+} \r
+\r
+int\r
+str_replace_all(char** str, const char* what, const char* with, const char* delimiters)\r
+{\r
+       int rv;\r
+       \r
+       while(!(rv = str_replace(str, what, with, delimiters)));\r
+       \r
+       return (errno == ESRCH) ? 0 : -1;\r
+}\r
+\r
+\r
+/*int\r
 str_replace_all(char** str, const char* what, const char* with)\r
 {\r
        int rv;\r
@@ -62,6 +241,7 @@ str_replace_all(char** str, const char* what, const char* with)
        while(!(rv = str_replace(str, what, with)));\r
        \r
        return (errno == ESRCH) ? 0 : -1;\r
-}\r
+}*/\r
+\r
 \r
 \r
index d89983c..77268da 100644 (file)
@@ -7,7 +7,7 @@ variable_new(const char* name, const char* val)
 {\r
        variable_t variable;\r
        \r
-       if(!name || !val)\r
+       if(!name)\r
        {\r
                errno = EINVAL;\r
                return NULL;\r
@@ -16,7 +16,10 @@ variable_new(const char* name, const char* val)
        variable = xbt_new0(s_variable_t, 1);\r
        \r
        variable->name = strdup(name);\r
-       variable->val = strdup(val);\r
+\r
+       if(val)\r
+               variable->val = strdup(val);\r
+\r
        variable->used = 0;\r
        variable->env = 0;\r
        variable->err = 0;\r
index e765046..2c6d457 100644 (file)
@@ -44,6 +44,7 @@
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="2"\r
+                               BufferSecurityCheck="true"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="3"\r
                                Detect64BitPortabilityProblems="true"\r
                        <File\r
                                RelativePath="..\src\main.c"\r
                                >\r
+                               <FileConfiguration\r
+                                       Name="Debug|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               BufferSecurityCheck="false"\r
+                                       />\r
+                               </FileConfiguration>\r
                        </File>\r
                        <File\r
                                RelativePath="..\src\reader.c"\r