Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Indent the rest of the code (examples, buildtools, doc...) except for examples/SMPI...
[simgrid.git] / tools / tesh2 / src / fstream.c
index 0a8ef5e..a0b2dd8 100644 (file)
@@ -10,8 +10,8 @@
  *             This file contains all the definitions of the functions related with\r
  *             the tesh file stream type.\r
  *\r
- */\r
-\r
+ */  \r
+    \r
 #include <fstream.h>\r
 #include <xerrno.h>\r
 #include <context.h>\r
 #include <unit.h>\r
 #include <str_replace.h>\r
 #include <variable.h>\r
-\r
+    \r
 #include <readline.h>\r
-\r
+    \r
 #include <is_cmd.h>\r
 #include <getpath.h>\r
-\r
-#ifndef WIN32\r
+    \r
+#ifndef _XBT_WIN32\r
 #include <xsignal.h>\r
-#endif\r
-\r
-#ifdef WIN32\r
-static int\r
-is_w32_cmd(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
-       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
-                               /* use Cat.exe on Windows */\r
-                               if(!strcmp(cmd, "cat"))\r
-                                       cmd[0] = 'C';\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
-\r
-       return readline(fstream->stream, buf, n);\r
-       \r
-}\r
-\r
-static void\r
-failure(unit_t unit)\r
-{\r
-       if(!keep_going_unit_flag)\r
-       {\r
-               unit_t root = unit->root ? unit->root : unit;\r
-                       \r
-               if(!root->interrupted)\r
-               {\r
-                       /* the unit interrupted (exit for the loop) */\r
-                       root->interrupted = 1;\r
-\r
-                       /* release the unit */\r
-                       xbt_os_sem_release(root->sem);\r
-               }\r
-\r
-               /* if the --keep-going option is not specified */\r
-               if(!keep_going_flag)\r
-               {\r
-                       if(!interrupted)\r
-                       {\r
-                               /* request an global interruption by the runner */\r
-                               interrupted = 1;\r
-\r
-                               /* release the runner */\r
-                               xbt_os_sem_release(units_sem);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-fstream_t\r
-fstream_new(const char* directory, const char* name)\r
-{\r
-       fstream_t fstream;\r
-       \r
-       if(!name)\r
-       {\r
-               errno = EINVAL;\r
-               return NULL;\r
-       }\r
-       \r
-       if(!directory && !strcmp("stdin", name))\r
-       {\r
-               fstream = xbt_new0(s_fstream_t, 1);\r
-               fstream->name = strdup("stdin");\r
-               return fstream;\r
-       }\r
-       else if(!directory)\r
-       {\r
-               errno = EINVAL;\r
-               return NULL;\r
-       }\r
-       \r
-       fstream = xbt_new0(s_fstream_t, 1);\r
-       \r
-       if(!(fstream->name = strdup(name)))\r
-       {\r
-               free(fstream);\r
-               return NULL;\r
-       }\r
-       \r
-       if(!(fstream->directory = strdup(directory)))\r
-       {\r
-               free(fstream->name);\r
-               free(fstream);\r
-               return NULL;\r
-       }\r
-       \r
-       fstream->stream = NULL;\r
-       fstream->unit = NULL;\r
-       fstream->parsed = 0;\r
-       \r
-       \r
-       return fstream;\r
-}\r
-\r
-int\r
-fstream_open(fstream_t fstream)\r
-{\r
-       char path[PATH_MAX + 1] = {0};\r
-       \r
-       /* check the parameter */\r
-       if(!(fstream))\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
-       \r
-       if(!fstream || fstream->stream)\r
-       {\r
-               errno = EALREADY;\r
-               return -1;\r
-       }\r
-               \r
-       if(!strcmp(fstream->name, "stdin"))\r
-       {\r
-               fstream->stream = stdin;\r
-               return 0;\r
-       }\r
-       \r
-       #ifndef WIN32\r
-       sprintf(path,"%s/%s",fstream->directory, fstream->name);\r
-       #else\r
-       sprintf(path,"%s\\%s",fstream->directory, fstream->name);\r
-    #endif\r
-\r
-       if(!(fstream->stream = fopen(path, "r")))\r
-       {\r
-               return -1;\r
-       }\r
-       \r
-       return 0;\r
-}\r
-\r
-int\r
-fstream_close(fstream_t fstream)\r
-{\r
-       /* check the parameter */\r
-       if(!(fstream) || !strcmp(fstream->name, "stdin") )\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
-               \r
-       if(!fstream->stream)\r
-               return EBADF;   \r
-       \r
-       if(EOF == fclose(fstream->stream))\r
-               return -1;\r
-               \r
-       fstream->stream = NULL;\r
-       \r
-       return 0;\r
-}\r
-\r
-int\r
-fstream_free(fstream_t* ptr)\r
-{\r
-       \r
-       /* check the parameter */\r
-       if(!(*ptr))\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
+#endif  /* \r */
     \r
-       if(!(*ptr))\r
-               return EINVAL;\r
-               \r
-       if((*ptr)->stream)\r
-               fclose((*ptr)->stream);\r
-       \r
-       if((*ptr)->name)\r
-               free((*ptr)->name);\r
-       \r
-       if((*ptr)->directory)\r
-               free((*ptr)->directory);\r
-               \r
-       free(*ptr);\r
-\r
-       *ptr = NULL;\r
-       \r
-       return 0;\r
-               \r
-}\r
-\r
-int\r
-fstream_parse(fstream_t fstream, xbt_os_mutex_t mutex)\r
-{\r
-       size_t len;\r
-       char * line = NULL;\r
-       int line_num = 0;\r
-       char file_pos[256];\r
-       xbt_strbuff_t buff;\r
-       int buffbegin = 0; \r
-       context_t context;\r
-       unit_t unit;\r
-       \r
-       /* Count the line length while checking wheather it's blank */\r
-       int blankline;\r
-       int linelen;    \r
-       /* Deal with \ at the end of the line, and call handle_line on result */\r
-       int to_be_continued;\r
-       \r
-       /* check the parameter */\r
-       if(!(fstream) || !mutex)\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
+#ifdef _XBT_WIN32\r
+static int \r is_w32_cmd(char *cmd, char **path) \r
+{
+  \rsize_t i = 0;
+  \rstruct stat stat_buff = { 0 };
+  \rchar buff[PATH_MAX + 1] = { 0 };
+  \r\r\r\rif (!cmd)
+    \r {
+    \rerrno = EINVAL;
+    \rreturn 0;
+    \r}
+  \r\rif (stat(cmd, &stat_buff) || !S_ISREG(stat_buff.st_mode))
+    \r {
+    \rif (path)
+      \r {
+      \rfor (i = 0; path[i] != NULL; i++)
+        \r {
+        \r
+            /* use Cat.exe on Windows */ \r
+            if (!strcmp(cmd, "cat"))
+          \rcmd[0] = 'C';
+        \r\rsprintf(buff, "%s\\%s", path[i], cmd);
+        \r\rif (!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))
+          \rreturn 1;
+        \r}
+      \r}
+    \r}
+  \r
+  else
+    \rreturn 1;
+  \r\r\rreturn 0;
+\r}
+
+\r
+#endif  /* \r */
+    \r\rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
+\r\r\rlong fstream_getline(fstream_t fstream, char **buf, size_t * n)
+{
+  \r\rreturn readline(fstream->stream, buf, n);
+\r\r}
+
+\r\rstatic void \r failure(unit_t unit) \r
+{
+  \rif (!keep_going_unit_flag)
+    \r {
+    \runit_t root = unit->root ? unit->root : unit;
+    \r\rif (!root->interrupted)
+      \r {
+      \r
+          /* the unit interrupted (exit for the loop) */ \r
+          root->interrupted = 1;
+      \r\r
+          /* release the unit */ \r
+          xbt_os_sem_release(root->sem);
+      \r}
+    \r\r
+        /* if the --keep-going option is not specified */ \r
+        if (!keep_going_flag)
+      \r {
+      \rif (!interrupted)
+        \r {
+        \r
+            /* request an global interruption by the runner */ \r
+            interrupted = 1;
+        \r\r
+            /* release the runner */ \r
+            xbt_os_sem_release(units_sem);
+        \r}
+      \r}
+    \r}
+\r}
+
+\r\rfstream_t \r fstream_new(const char *directory, const char *name) \r
+{
+  \rfstream_t fstream;
+  \r\rif (!name)
+    \r {
+    \rerrno = EINVAL;
+    \rreturn NULL;
+    \r}
+  \r\rif (!directory && !strcmp("stdin", name))
+    \r {
+    \rfstream = xbt_new0(s_fstream_t, 1);
+    \rfstream->name = strdup("stdin");
+    \rreturn fstream;
+    \r}
+  \r
+  else if (!directory)
+    \r {
+    \rerrno = EINVAL;
+    \rreturn NULL;
+    \r}
+  \r\rfstream = xbt_new0(s_fstream_t, 1);
+  \r\rif (!(fstream->name = strdup(name)))
+    \r {
+    \rfree(fstream);
+    \rreturn NULL;
+    \r}
+  \r\rif (!(fstream->directory = strdup(directory)))
+    \r {
+    \rfree(fstream->name);
+    \rfree(fstream);
+    \rreturn NULL;
+    \r}
+  \r\rfstream->stream = NULL;
+  \rfstream->unit = NULL;
+  \rfstream->parsed = 0;
+  \r\r\rreturn fstream;
+\r}
+
+\r\rint \r fstream_open(fstream_t fstream) \r
+{
+  \rchar path[PATH_MAX + 1] = { 0 };
+  \r\r
+      /* check the parameter */ \r
+      if (!(fstream))
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\rif (!fstream || fstream->stream)
+    \r {
+    \rerrno = EALREADY;
+    \rreturn -1;
+    \r}
+  \r\rif (!strcmp(fstream->name, "stdin"))
+    \r {
+    \rfstream->stream = stdin;
+    \rreturn 0;
+    \r}
+  \r\r
+#ifndef _XBT_WIN32\r
+      sprintf(path, "%s/%s", fstream->directory, fstream->name);
+  \r
+#else   /* \r */
+      sprintf(path, "%s\\%s", fstream->directory, fstream->name);
+  \r
+#endif  /* \r */
+      \rif (!(fstream->stream = fopen(path, "r")))
+    \r {
+    \rreturn -1;
+    \r}
+  \r\rreturn 0;
+\r}
+
+\r\rint \r fstream_close(fstream_t fstream) \r
+{
+  \r
+      /* check the parameter */ \r
+      if (!(fstream) || !strcmp(fstream->name, "stdin"))
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\rif (!fstream->stream)
+    \rreturn EBADF;
+  \r\rif (EOF == fclose(fstream->stream))
+    \rreturn -1;
+  \r\rfstream->stream = NULL;
+  \r\rreturn 0;
+\r}
+
+\r\rint \r fstream_free(fstream_t * ptr) \r
+{
+  \r\r
+      /* check the parameter */ \r
+      if (!(*ptr))
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\rif (!(*ptr))
+    \rreturn EINVAL;
+  \r\rif ((*ptr)->stream)
+    \rfclose((*ptr)->stream);
+  \r\rif ((*ptr)->name)
+    \rfree((*ptr)->name);
+  \r\rif ((*ptr)->directory)
+    \rfree((*ptr)->directory);
+  \r\rfree(*ptr);
+  \r\r*ptr = NULL;
+  \r\rreturn 0;
+\r\r}
+
+\r\rint \r fstream_parse(fstream_t fstream, xbt_os_mutex_t mutex) \r
+{
+  \rsize_t len;
+  \rchar *line = NULL;
+  \rint line_num = 0;
+  \rchar file_pos[256];
+  \rxbt_strbuff_t buff;
+  \rint buffbegin = 0;
+  \rcontext_t context;
+  \runit_t unit;
+  \r\r
+      /* Count the line length while checking wheather it's blank */ \r
+  int blankline;
+  \rint linelen;
+  \r
+      /* Deal with \ at the end of the line, and call handle_line on result */ \r
+  int to_be_continued;
+  \r\r
+      /* check the parameter */ \r
+      if (!(fstream) || !mutex)
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\rbuff = xbt_strbuff_new();
+  \r\rif (!(context = context_new()))
+    \rreturn -1;
+  \r\runit = fstream->unit;
+  \r\r
+      /*while(!(unit->root->interrupted)  && getline(&line, &len, fstream->stream) != -1) */ \r
+      while (!(unit->root->interrupted)
+             && fstream_getline(fstream, &line, &len) != -1)
+    \r {
+    \r\rblankline = 1;
+    \rlinelen = 0;
+    \rto_be_continued = 0;
+    \r\rline_num++;
+    \r\rwhile (line[linelen] != '\0')
+      \r {
+      \rif (line[linelen] != ' ' && line[linelen] != '\t'
+           && line[linelen] != '\n' && line[linelen] != '\r')
+        \rblankline = 0;
+      \r\rlinelen++;
+      \r}
+    \r\rif (blankline)
+      \r {
+      \rif (!context->command_line
+           && (context->input->used || context->output->used))
+        \r {
+        \rsnprintf(file_pos, 256, "%s:%d", fstream->name, line_num);
+        \rERROR1("[%s] Error : no command found in the last chunk of lines",
+                file_pos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, file_pos);
+        \r\rfailure(unit);
+        \rbreak;
+        \r}
+      \r
+      else if (unit->is_running_suite)
+        \r {                     /* it's the end of a suite */
+        \r\runit_t * current_suite =
+            xbt_dynar_get_ptr(unit->suites,
+                              xbt_dynar_length(unit->suites) - 1);
+        \r\rif (!xbt_dynar_length((*current_suite)->includes))
+          \r {
+          \rERROR2("[%s] Malformated suite `(%s)' : include missing",
+                  file_pos, (*current_suite)->description);
+          \r\runit_set_error(*current_suite, ESYNTAX, 1, file_pos);
+          \r\rfailure(unit);
+          \r\r}
+        \r\runit->is_running_suite = 0;
+        \r}
+      \r\rif (context->command_line)
+        \r {
+        \r
+#ifdef _XBT_WIN32\r
+            if (!context->is_not_found)
+          \r {
+          \r
+#endif  /* \r */
+              if (fstream_launch_command(fstream, context, mutex) < 0)
+            \rbreak;
+          \r\r
+#ifdef _XBT_WIN32\r
+          }
+        \r
+#endif  /* \r */
+        }
+      \r\rcontinue;
+      \r}
+    \r\rif (linelen > 1 && line[linelen - 2] == '\\')
+      \r {
+      \rif (linelen > 2 && line[linelen - 3] == '\\')
+        \r {
+        \r
+            /* Damn. Escaped \ */ \r
+            line[linelen - 2] = '\n';
+        \rline[linelen - 1] = '\0';
+        \r}
+      \r
+      else
+        \r {
+        \rto_be_continued = 1;
+        \rline[linelen - 2] = '\0';
+        \rlinelen -= 2;
+        \r\rif (!buff->used)
+          \rbuffbegin = line_num;
+        \r}
+      \r}
+    \r\rif (buff->used || to_be_continued)
+      \r {
+      \rxbt_strbuff_append(buff, line);
+      \r\rif (!to_be_continued)
+        \r {
+        \rsnprintf(file_pos, 256, "%s:%d", fstream->name, buffbegin);
+        \rfstream_lex_line(fstream, context, mutex, file_pos, buff->data);
+        \rxbt_strbuff_empty(buff);
+        \r}
+      \r}
     \r
-       buff = xbt_strbuff_new();\r
-       \r
-       if(!(context = context_new()))\r
-               return -1;\r
-               \r
-       unit = fstream->unit;\r
-       \r
-       /*while(!(unit->root->interrupted)  && getline(&line, &len, fstream->stream) != -1)*/\r
-       while(!(unit->root->interrupted)  && fstream_getline(fstream, &line, &len) != -1)\r
-       {\r
-               \r
-               blankline=1;\r
-               linelen = 0;    \r
-               to_be_continued = 0;\r
-\r
-               line_num++;\r
-               \r
-               while(line[linelen] != '\0') \r
-               {\r
-                       if (line[linelen] != ' ' && line[linelen] != '\t' && line[linelen]!='\n' && line[linelen]!='\r')\r
-                               blankline = 0;\r
-                       \r
-                       linelen++;\r
-               }\r
-       \r
-               if(blankline) \r
-               {\r
-                       if(!context->command_line && (context->input->used || context->output->used))\r
-                       {\r
-                               snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
-                               ERROR1("[%s] Error : no command found in the last chunk of lines", file_pos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, file_pos);\r
-\r
-                               failure(unit);\r
-                               break;\r
-                       }\r
-                       else if(unit->is_running_suite)\r
-                       {/* it's the end of a suite */\r
-                               \r
-                               unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
-\r
-                               if(!xbt_dynar_length((*current_suite)->includes))\r
-                               {\r
-                                       ERROR2("[%s] Malformated suite `(%s)' : include missing", file_pos, (*current_suite)->description);\r
-                               \r
-                                       unit_set_error(*current_suite, ESYNTAX, 1, file_pos);\r
-\r
-                                       failure(unit);\r
-                                       \r
-                               }\r
-                       \r
-                               unit->is_running_suite = 0;\r
-                       }\r
-                               \r
-                       if(context->command_line)\r
-                       {\r
-                               if(fstream_launch_command(fstream, context, mutex) < 0)\r
-                                               break;\r
-                       }\r
-               \r
-                       continue;\r
-               }\r
-               \r
-               if(linelen>1 && line[linelen-2]=='\\') \r
-               {\r
-                       if(linelen>2 && line[linelen-3] == '\\') \r
-                       {\r
-                               /* Damn. Escaped \ */\r
-                               line[linelen-2] = '\n';\r
-                               line[linelen-1] = '\0';\r
-                       } \r
-                       else \r
-                       {\r
-                               to_be_continued = 1;\r
-                               line[linelen-2] = '\0';\r
-                               linelen -= 2;  \r
-                               \r
-                               if (!buff->used)\r
-                                       buffbegin = line_num;\r
-                       }\r
-               }\r
-       \r
-               if(buff->used || to_be_continued) \r
-               { \r
-                       xbt_strbuff_append(buff,line);\r
-       \r
-                       if (!to_be_continued) \r
-                       {\r
-                               snprintf(file_pos,256,"%s:%d",fstream->name, buffbegin);\r
-                               fstream_lex_line(fstream, context, mutex, file_pos, buff->data);    \r
-                               xbt_strbuff_empty(buff);\r
-                       }\r
-               } \r
-               else \r
-               {\r
-                       snprintf(file_pos,256,"%s:%d",fstream->name, line_num);\r
-                       fstream_lex_line(fstream, context, mutex, file_pos, line);      \r
-               }\r
-       }\r
-       \r
-       /* Check that last command of the file ran well */\r
-       if(context->command_line)\r
-       {\r
-               if(fstream_launch_command(fstream, context, mutex) < 0)\r
-                       return -1;\r
-       }\r
-       \r
-       /* clear buffers */\r
-       if(line)\r
-               free(line);\r
-               \r
-       xbt_strbuff_free(buff); \r
-       \r
-       if(context_free(&context) < 0)\r
-               return -1;\r
-       \r
-       return (exit_code || errno) ? -1 : 0;\r
-}\r
-\r
-\r
-void \r
-fstream_lex_line(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line) \r
-{\r
-       char* line2;\r
-       variable_t variable;\r
-       unsigned int i;\r
-       char exp[PATH_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[PATH_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
-               \r
-               unit_t* current_suite = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
-\r
-               if(!xbt_dynar_length((*current_suite)->includes))\r
-                       ERROR2("[%s] Malformated suite `(%s)': include missing", filepos, (*current_suite)->description);\r
-               else\r
-                       ERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos, (*current_suite)->description);\r
-               \r
-               unit_set_error(*current_suite, ESYNTAX, 1, filepos);\r
-\r
-               failure(fstream->unit);\r
-       }\r
-       \r
-       context->line = strdup(filepos);\r
-       \r
-       /* search end */\r
-       xbt_str_rtrim(line + 2,"\n");\r
-       \r
-       line2 = strdup(line);\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
-               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' && !(isalpha((p + strlen(variable->name) + 1)[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
-       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
-               break;\r
-               */\r
-               \r
-               case '$':\r
-               case '&':\r
-\r
-               if(line[1] != ' ')\r
-               {\r
-                       \r
-                       if(line2[0] == '$')\r
-                               ERROR1("[%s] Missing space after `$' `(usage : $ <command>)'", filepos);\r
-                       else\r
-                               ERROR1("[%s] Missing space after & `(usage : & <command>)'", filepos);\r
-               \r
-                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                       failure(unit);\r
-                       return;\r
-               }\r
-                       \r
-               context->async = (line2[0] == '&');\r
-\r
-               \r
-               /* further trim useless chars which are significant for in/output */\r
-               xbt_str_rtrim(line2 + 2," \t");\r
-               \r
-               /* deal with CD commands here, not in context */\r
-               if(!strncmp("cd ",line2 + 2, 3)) \r
-               {\r
-                       char* dir = strdup(line2 + 4);\r
-                       \r
-                       if(context->command_line)\r
-                       {\r
-                               if(fstream_launch_command(fstream, context, mutex) < 0)\r
-                                       return;\r
-                       }\r
-               \r
-                       /* search begining */\r
-                       while(*(dir++) == ' ');\r
-                       \r
-                       dir--;\r
-                       \r
-                       if(!dry_run_flag)\r
-                       {\r
-                               if(!silent_flag)\r
-                                       INFO2("[%s] cd %s", filepos, dir);\r
-                               \r
-                               if(!just_print_flag)\r
-                               {\r
-                                       if(chdir(dir))\r
-                                       {\r
-                                               ERROR3("[%s] Chdir to %s failed: %s",filepos, dir,error_to_string(errno, 0));\r
-                                               unit_set_error(fstream->unit, errno, 0, filepos);\r
-\r
-                                               failure(unit);\r
-                                       }\r
-                               }\r
-                       }\r
-                       \r
-                       break;\r
-               }\r
-               else\r
-               {\r
-                       fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);\r
-                       break;\r
-               }\r
-               \r
-               case '<':\r
-               case '>':\r
-               case '!':\r
-               \r
-               if(line[0] == '!' && line[1] != ' ')\r
-               {\r
-                       ERROR1("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'", filepos);\r
-               \r
-                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                       failure(unit);\r
-                       return;\r
-               }\r
-\r
-               fstream_process_token(fstream, context, mutex, filepos, line2[0], line2 + 2);    \r
-               break;\r
-               \r
-               case 'p':\r
-               \r
-               {\r
-                       unsigned int j;\r
-                       int is_blank = 1;\r
-                       \r
-                       char* prompt = line2 + 2;\r
-\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
-                               ERROR1("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-\r
-                       if(!dry_run_flag)\r
-                               INFO2("[%s] %s",filepos,prompt);\r
-               }\r
-\r
-               \r
-               break;\r
-               \r
-               case 'P':\r
-               \r
-               {\r
-                       unsigned int j;\r
-                       int is_blank = 1;\r
-                               \r
-                       char* prompt = line2 + 2;\r
-\r
-                       for(j = 0; j < strlen(prompt); j++) \r
-                               if (prompt[j] != ' ' && prompt[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               ERROR1("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-\r
-                       if(!dry_run_flag)               \r
-                               CRITICAL2("[%s] %s",filepos, prompt);\r
-               }\r
-\r
-               break;\r
-               \r
-               case 'D':\r
-                       if(unit->description)\r
-                               WARN2("[%s] Description already specified `%s'",filepos, line2 + 2); \r
-                       else\r
-                       {\r
-                               unsigned int j;\r
-                               int is_blank = 1;\r
-                               \r
-                               char* desc = line2 + 2;\r
-\r
-                               for(j = 0; j < strlen(desc); j++) \r
-                                       if (desc[j] != ' ' && desc[j] != '\t')\r
-                                               is_blank = 0;\r
-\r
-                               if(is_blank)\r
-                               {\r
-                                       ERROR1("[%s] Bad usage of the metacommand D `(usage : D <Description>)'", filepos);\r
-                                       \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-\r
-                               unit->description = strdup(desc);\r
-                       }\r
-               break;\r
-               \r
-               default:\r
-               ERROR2("[%s] Syntax error `%s'", filepos, line2);\r
-               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-               failure(unit);\r
-               break;\r
-       }\r
-       \r
-       free(line2);\r
-}\r
-\r
-void \r
-fstream_process_token(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* filepos, char token, char *line) \r
-{\r
-       unit_t unit = fstream->unit;\r
-       \r
-       switch (token) \r
-       {\r
-               case '$':\r
-               case '&':\r
-               \r
-               if(context->command_line) \r
-               {\r
-                       \r
-                       if(context->output->used || context->input->used) \r
-                       {\r
-                               ERROR2("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",filepos, context->command_line);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       \r
-                       if(fstream_launch_command(fstream, context, mutex) < 0)\r
-                                       return;\r
-                       \r
-                       VERB1("[%s] More than one command in this chunk of lines",filepos);\r
-               }\r
-               \r
-               {\r
-                       size_t j,\r
-                       is_blank = 1;\r
-\r
-                       for(j = 0; j < strlen(line); j++) \r
-                               if (line[j] != ' ' && line[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               if(token == '$')\r
-                               ERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'", filepos);\r
-                               else\r
-                               ERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'", filepos);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-               }\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 = NULL;\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
-               \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
-                       if(!strstr(context->command_line,".exe"))\r
-                               strcat(command_line,".exe");\r
-\r
-                       args = strdup(context->command_line + i);\r
-               }\r
-               \r
-               if(!is_w32_cmd(command_line, fstream->unit->runner->path) && getpath(command_line, &path) < 0)\r
-               {\r
-                       ERROR3("[%s] `%s' : NOK (%s)", filepos, 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
-\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
-                       \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
-               xbt_strbuff_append(context->input,line);\r
-               xbt_strbuff_append(context->input,"\n");\r
-               break;\r
-               \r
-               case '>':\r
-               xbt_strbuff_append(context->output,line);\r
-               xbt_strbuff_append(context->output,"\n");\r
-               break;\r
-               \r
-               case '!':\r
-               \r
-               if(context->command_line)\r
-               {\r
-                       if(fstream_launch_command(fstream, context, mutex) < 0)\r
-                                       return;\r
-               }\r
-               \r
-               if(!strncmp(line,"timeout no",strlen("timeout no"))) \r
-               {\r
-                       VERB1("[%s] (disable timeout)", filepos);\r
-                       context->timeout = INDEFINITE;\r
-               } \r
-               else if(!strncmp(line,"timeout ",strlen("timeout "))) \r
-               {\r
-                       int i = 0;\r
-                       unsigned int j;\r
-                       int is_blank = 1;\r
-                       char* p = line + strlen("timeout ");\r
-\r
-\r
-                       for(j = 0; j < strlen(p); j++) \r
-                               if (p[j] != ' ' && p[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               ERROR1("[%s] Undefinite timeout value `(usage :timeout <seconds>)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-       \r
-                       while(p[i] != '\0')\r
-                       {\r
-                               if(!isdigit(p[i]))\r
-                               {\r
-                                       ERROR2("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'", filepos, line + strlen("timeout "));\r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-\r
-                               i++;\r
-                       }\r
-                       \r
-                       context->timeout = atoi(line + strlen("timeout"));\r
-                       VERB2("[%s] (new timeout value: %d)",filepos,context->timeout);\r
-               \r
-               } \r
-               else if (!strncmp(line,"expect signal ",strlen("expect signal "))) \r
-               {\r
-                       unsigned int j;\r
-                       int is_blank = 1;\r
-\r
-                       \r
-                       char* p = line + strlen("expect signal ");\r
-\r
-\r
-                       for(j = 0; j < strlen(p); j++) \r
-                               if (p[j] != ' ' && p[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               ERROR1("[%s] Undefinite signal name `(usage :expect signal <signal name>)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-\r
-                       context->signal = strdup(line + strlen("expect signal "));\r
-                       \r
-                       xbt_str_trim(context->signal," \n");\r
-\r
-                       #ifdef WIN32\r
-                       if(!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))\r
-                       {\r
-                               ERROR2("[%s] Signal `%s' not supported by this platform", filepos, context->signal);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       #else\r
-                       if(!sig_exists(context->signal))\r
-                       {\r
-                               ERROR2("[%s] Signal `%s' not supported by Tesh", filepos, context->signal);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-\r
-                       #endif\r
-\r
-                       \r
-                       VERB2("[%s] (next command must raise signal %s)", filepos, context->signal);\r
-               \r
-               } \r
-               else if (!strncmp(line,"expect return ",strlen("expect return "))) \r
-               {\r
-\r
-                       int i = 0;\r
-                       unsigned int j;\r
-                       int is_blank = 1;\r
-                       char* p = line + strlen("expect return ");\r
-\r
-\r
-                       for(j = 0; j < strlen(p); j++) \r
-                               if (p[j] != ' ' && p[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               ERROR1("[%s] Undefinite return value `(usage :expect return <return value>)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       \r
-                       while(p[i] != '\0')\r
-                       {\r
-                               if(!isdigit(p[i]))\r
-                               {\r
-                                       ERROR2("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255",  filepos, line + strlen("expect return "));\r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-\r
-                               i++;\r
-                       }\r
-\r
-                       context->exit_code = atoi(line+strlen("expect return "));\r
-                       VERB2("[%s] (next command must return code %d)",filepos, context->exit_code);\r
-               \r
-               } \r
-               else if (!strncmp(line,"output ignore",strlen("output ignore"))) \r
-               {\r
-                       context->output_handling = oh_ignore;\r
-                       VERB1("[%s] (ignore output of next command)", filepos);\r
-               \r
-               } \r
-               else if (!strncmp(line,"output display",strlen("output display"))) \r
-               {\r
-                       context->output_handling = oh_display;\r
-                       VERB1("[%s] (ignore output of next command)", filepos);\r
-               \r
-               } \r
-               else if(!strncmp(line,"include ", strlen("include ")))\r
-               {\r
-                       char* p1;\r
-                       char* p2;\r
-                       \r
-                       p1 = line + strlen("include");\r
-                       \r
-                       while(*p1 == ' ' || *p1 == '\t')\r
-                               p1++;\r
-                               \r
-                       \r
-                       if(p1[0] == '\0')\r
-                       {\r
-                               ERROR1("[%s] no file specified : `(usage : include <file> [<description>])'", filepos);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       else\r
-                       {\r
-                               char file_name[PATH_MAX + 1] = {0};\r
-                               \r
-                               p2 = p1;\r
-                               \r
-                               while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')\r
-                                       p2++;\r
-                                       \r
-                               strncpy(file_name, p1, p2 - p1);\r
-                               \r
-                               \r
-                               if(p2[0] != '\0')\r
-                                       while(*p2 == ' ' || *p2 == '\t')\r
-                                               p2++;\r
-                                       \r
-                               fstream_handle_include(fstream, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);\r
-                               \r
-                       }\r
-               }\r
-               else if(!strncmp(line,"suite ", strlen("suite ")))\r
-               {\r
-                       unsigned int j;\r
-                       int is_blank = 1;\r
-                       char* p = line + strlen("suite ");\r
-\r
-\r
-                       for(j = 0; j < strlen(p); j++) \r
-                               if (p[j] != ' ' && p[j] != '\t')\r
-                                       is_blank = 0;\r
-                       \r
-                       if(is_blank)\r
-                       {\r
-                               ERROR1("[%s] Undefinite suit description : `(usage : suite <description>)", filepos);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-\r
-                       if(unit->is_running_suite)\r
-                       {\r
-                               ERROR1("[%s] Suite already in progress", filepos);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       \r
-                       fstream_handle_suite(fstream, line + strlen("suite "), filepos);\r
-               }\r
-               else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))\r
-               {\r
-                       unsigned int i, j;\r
-                       int exists = 0;\r
-                       int env = 0;\r
-                       int err = 0;\r
-                       variable_t variable;\r
-                       int is_blank;\r
-\r
-                       char* name = line + strlen("unsetenv ");\r
-\r
-                       is_blank = 1;\r
-\r
-                       for(j = 0; j < strlen(name); j++) \r
-                               if (name[j] != ' ' && name[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       \r
-                       xbt_os_mutex_acquire(unit->mutex);\r
-                       \r
-\r
-                       xbt_dynar_foreach(unit->runner->variables, i, variable)\r
-                       {\r
-                               if(!strcmp(variable->name, name))\r
-                               {\r
-                                       env = variable->env;\r
-                                       err = variable->err;\r
-                                       exists = 1;\r
-                                       break;\r
-                               }\r
-                       }\r
-                               \r
-                       if(env)\r
-                       {\r
-                               if(exists)\r
-                               {\r
-                                       #ifndef WIN32\r
-                                       unsetenv(name);\r
-                                       #else\r
-                                       SetEnvironmentVariable(name, NULL);\r
-                                       #endif\r
-                                       xbt_dynar_cursor_rm(unit->runner->variables, &i);\r
-                               }\r
-                               else\r
-                               {\r
-                                       ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);    \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                       xbt_os_mutex_release(unit->mutex);\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               if(exists)\r
-                               {\r
-                                       if(!err)\r
-                                       {\r
-                                               ERROR2("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",filepos, name);    \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               failure(unit);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-                                               return;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               ERROR2("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",filepos, name);   \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       ERROR2("[%s] `(%s)' environment variable not found : impossible to unset it",filepos, name);    \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                       xbt_os_mutex_release(unit->mutex);\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                       }\r
-                       \r
-                       xbt_os_mutex_release(unit->mutex);      \r
-                       \r
-                               \r
-               }\r
-               else if(!strncmp(line,"setenv ", strlen("setenv ")))\r
-               {\r
-                       char* val;\r
-                       char name[PATH_MAX + 1] = {0};\r
-                       char* p;\r
-                       unsigned int i;\r
-                       int is_blank;\r
-                       unsigned int j;\r
-                       \r
-                       p = line + strlen("setenv ");\r
-                       \r
-                       val = strchr(p, '=');\r
-                       \r
-                       if(val)\r
-                       {\r
-                               variable_t variable;\r
-                               int exists = 0;\r
-                               int env = 0;\r
-                               int err = 0;\r
-                               val++;\r
-                               \r
-                               /* syntax error */\r
-                               if(val[0] == '\0' || val[0] ==' ' || val[0] =='\t')\r
-                               {\r
-                                       ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);  \r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               \r
-                               \r
-                               \r
-                               strncpy(name, p, (val - p -1));\r
-\r
-                               is_blank = 1;\r
-\r
-                               for(j = 0; j < strlen(name); j++) \r
-                                       if (name[j] != ' ' && name[j] != '\t')\r
-                                               is_blank = 0;\r
-\r
-                               if(is_blank)\r
-                               {\r
-                                       \r
-                                       ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
-                                       \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               \r
-                               /* test if the variable is already registred */\r
-                               xbt_os_mutex_acquire(unit->mutex);\r
-\r
-                               xbt_dynar_foreach(unit->runner->variables, i, variable)\r
-                               {\r
-                                       if(!strcmp(variable->name, name))\r
-                                       {\r
-                                               env = variable->env;\r
-                                               err = variable->err;\r
-                                               exists = 1;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               \r
-                               /* if the variable is already registred, update its value;\r
-                                * otherwise register it.\r
-                                */\r
-                               if(exists)\r
-                               {\r
-                                       if(env)\r
-                                       {\r
-                                               if(!strcmp(val, variable->val))\r
-                                                       WARN3("[%s] This environment variable `(%s)' is already set with the value `(%s)'", filepos, name, val);\r
-\r
-                                               free(variable->val);\r
-                                               variable->val = strdup(val);\r
-\r
-                                               #ifdef WIN32\r
-                                               SetEnvironmentVariable(variable->name, variable->val);\r
-                                               #else\r
-                                               setenv(variable->name, variable->val, 1);\r
-                                               #endif\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               if(err)\r
-                                                       ERROR2("[%s] Conflict : a system variable `(%s)' already exists", filepos, name);\r
-                                               else\r
-                                                       ERROR2("[%s] Conflict : (none environment) variable `(%s)' already exists", filepos, name);     \r
-\r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       if(err)\r
-                                       {\r
-                                               ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
-                                       \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               variable = variable_new(name, val);\r
-                                               variable->env = 1;\r
-                                               \r
-                                               xbt_dynar_push(unit->runner->variables, &variable);\r
-                                               \r
-                                               #ifdef WIN32\r
-                                               SetEnvironmentVariable(variable->name, variable->val);\r
-                                               #else\r
-                                               setenv(variable->name, variable->val, 0);\r
-                                               #endif\r
-                                       }\r
-                               }\r
-                               \r
-                               xbt_os_mutex_release(unit->mutex);\r
-                               \r
-                       }\r
-                       else\r
-                       {\r
-                               ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
-                                       \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-               }\r
-               else if(!strncmp(line,"unset ", strlen("unset ")))\r
-               {\r
-                       unsigned int i, j;\r
-                       int exists = 0;\r
-                       int env = 0;\r
-                       int err = 0;\r
-                       variable_t variable;\r
-                       int is_blank;\r
-\r
-                       char* name = line + strlen("unset ");\r
-\r
-                       is_blank = 1;\r
-\r
-                       for(j = 0; j < strlen(name); j++) \r
-                               if (name[j] != ' ' && name[j] != '\t')\r
-                                       is_blank = 0;\r
-\r
-                       if(is_blank)\r
-                       {\r
-                               \r
-                               ERROR1("[%s] Bad usage of the metacommand unset `(usage : unset variable)'", filepos);\r
-                               \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-\r
-                       \r
-                       xbt_os_mutex_acquire(unit->mutex);\r
-\r
-                       xbt_dynar_foreach(unit->runner->variables, i, variable)\r
-                       {\r
-                               if(!strcmp(variable->name, name))\r
-                               {\r
-                                       env = variable->env;\r
-                                       err = variable->err;\r
-                                       exists = 1;\r
-                                       break;\r
-                               }\r
-                       }\r
-                               \r
-                       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
-                                       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
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                       xbt_os_mutex_release(unit->mutex);\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                       }\r
-                       else if(env)\r
-                       {\r
-                               ERROR2("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",filepos, name);  \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                               xbt_os_mutex_release(unit->mutex);\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       else if(err)\r
-                       {\r
-                               ERROR2("[%s] `(%s)' is system variable : you can unset it",filepos, name);      \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                               xbt_os_mutex_release(unit->mutex);\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-                       \r
-                       xbt_os_mutex_release(unit->mutex);\r
-                               \r
-               }\r
-               else if(!strncmp(line,"set ", strlen("set ")))\r
-               {\r
-                       char* val;\r
-                       char name[PATH_MAX + 1] = {0};\r
-                       unsigned int j; \r
-                       int is_blank;\r
-                       \r
-                       val = strchr(line + strlen("set "), '=');\r
-                       \r
-                       if(val)\r
-                       {\r
-                               variable_t variable;\r
-                               int exists = 0;\r
-                               unsigned int i;\r
-                               int err;\r
-                               int env;\r
-\r
-                               val++;\r
-                               \r
-                               \r
-                               /* syntax error */\r
-                               if(val[0] == '\0')\r
-                               {\r
-                                       ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
-                                       \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               else if(val[0] ==' ' || val[0] =='\t')\r
-                               {\r
-                                       strncpy(name, line + strlen("set "), (val - (line + strlen("set "))));\r
-\r
-                                       ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               \r
-                               \r
-                               /* assume it's a varibale */\r
-                               \r
-                               strncpy(name, line + strlen("set "), (val - (line + strlen("set ")) -1));\r
-                               \r
-                               is_blank = 1;\r
-\r
-                               for(j = 0; j < strlen(name); j++) \r
-                                       if (name[j] != ' ' && name[j] != '\t')\r
-                                               is_blank = 0;\r
-\r
-                               if(is_blank)\r
-                               {\r
-                                       \r
-                                       ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
-                                       \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-\r
-                               xbt_os_mutex_acquire(unit->mutex);\r
-                               \r
-                               /* test if the variable is already registred */\r
-                               xbt_dynar_foreach(unit->runner->variables, i, variable)\r
-                               {\r
-                                       if(!strcmp(variable->name, name))\r
-                                       {\r
-                                               exists = 1;\r
-                                               err = variable->err;\r
-                                               env = variable->env;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               \r
-                               /* if the variable is already registred, update its value (if same value warns);\r
-                                * otherwise register it.\r
-                                */\r
-                               if(exists)\r
-                               {\r
-                                       if(err)\r
-                                       {\r
-                                               ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
-                                       \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                                       if(env)\r
-                                       {\r
-                                               ERROR2("[%s] `(%s)' is an environment variable use `setenv' instead `set'", filepos, name);\r
-                                       \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               if(!strcmp(val, variable->val))\r
-                                                       WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
-\r
-                                               free(variable->val);\r
-                                               variable->val = strdup(val);\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       variable_t new_var = variable_new(name, val);\r
-                                       xbt_dynar_push(unit->runner->variables, &new_var);\r
-                               }\r
-\r
-                                       \r
-                               xbt_os_mutex_release(unit->mutex);\r
-                       }\r
-                       else\r
-                       {\r
-                               ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
-                                       \r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-               }\r
-               else\r
-               {/* assume it's a variable */\r
-                       char* val;\r
-                       char name[PATH_MAX + 1] = {0};\r
-                       unsigned int i, j; \r
-                       int is_blank;\r
-                       \r
-                       val = strchr(line, '=');\r
-\r
-                       if(val)\r
-                       {\r
-                               variable_t variable;\r
-                               int exists = 0;\r
-                               int err;\r
-                               int env;\r
-                               val++;\r
-                               \r
-                               \r
-                               /* syntax error */\r
-                               if(val[0] == '\0')\r
-                               {\r
-                                       strncpy(name, line, (val - line -1));\r
-\r
-                                       is_blank = 1;\r
-\r
-                                       for(j = 0; j < strlen(name); j++) \r
-                                               if (name[j] != ' ' && name[j] != '\t')\r
-                                                       is_blank = 0;\r
-\r
-                                       if(is_blank)\r
-                                               ERROR1("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'", filepos);\r
-                                       else if(!strcmp("setenv", name))\r
-                                               ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
-                                       else if(!strcmp("set", name))\r
-                                               ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
-                                       else\r
-                                               ERROR2("[%s] Undefined variable `(%s)'", filepos, name);\r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               else if(val[0] ==' ' || val[0] =='\t')\r
-                               {\r
-                                       strncpy(name, line, (val - line));\r
-\r
-                                       ERROR2("[%s] No space avaible after`(%s)'", filepos, name);\r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);   \r
-                               }\r
-                               \r
-                               \r
-                               /* assume it's a varibale */\r
-                               \r
-                               strncpy(name, line, (val - line -1));\r
-\r
-                               is_blank = 1;\r
-\r
-                               for(j = 0; j < strlen(name); j++) \r
-                                       if (name[j] != ' ' && name[j] != '\t')\r
-                                               is_blank = 0;\r
-\r
-                               if(is_blank)\r
-                               {\r
-                                       \r
-                                       ERROR1("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'", filepos);\r
-\r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               \r
-                               if(!strcmp("set", name))\r
-                               {\r
-                                       ERROR1("[%s] Bad usage of the metacommand set `(usage : set variable=value)'", filepos);\r
-                                       \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-                               else if(!strcmp("setenv", name))\r
-                               {\r
-                                       ERROR1("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'", filepos);\r
-                                       \r
-                                       unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                       failure(unit);\r
-                                       return;\r
-                               }\r
-\r
-                               xbt_os_mutex_acquire(unit->mutex);\r
-                               \r
-                               /* test if the variable is already registred */\r
-                               xbt_dynar_foreach(unit->runner->variables, i, variable)\r
-                               {\r
-                                       if(!strcmp(variable->name, name))\r
-                                       {\r
-                                               exists = 1;\r
-                                               err = variable->err;\r
-                                               env = variable->env;\r
-                                               break;\r
-                                       }\r
-                               }\r
-                               \r
-                               /* if the variable is already registred, update its value (if same value warns);\r
-                                * otherwise register it.\r
-                                */\r
-                               if(exists)\r
-                               {\r
-                                       if(err)\r
-                                       {\r
-                                               ERROR2("[%s] A system variable named `(%s)' already exists", filepos, name);\r
-                                       \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                                       if(env)\r
-                                       {\r
-                                               ERROR2("[%s] `(%s)' is an environment variable use `setenv' metacommand", filepos, name);\r
-                                       \r
-                                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-                                               xbt_os_mutex_release(unit->mutex);\r
-\r
-                                               failure(unit);\r
-                                               return;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               if(!strcmp(val, variable->val))\r
-                                                       WARN3("[%s] Variable `(%s)' already contains value `<%s>'",filepos, variable->name, val);\r
-\r
-                                               free(variable->val);\r
-                                               variable->val = strdup(val);\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       variable_t new_var = variable_new(name, val);\r
-                                       xbt_dynar_push(unit->runner->variables, &new_var);\r
-                               }\r
-\r
-                                       \r
-                               xbt_os_mutex_release(unit->mutex);\r
-                               \r
-                       }\r
-                       else \r
-                       {\r
-                               if(!strncmp("setenv", line, strlen("setenv")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'", filepos);\r
-                               else if(!strncmp("set", line, strlen("set")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'", filepos);\r
-                               else if(!strncmp("unsetenv", line, strlen("unsetenv")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'", filepos);\r
-                               else if(!strncmp("unset", line, strlen("unset")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'", filepos);\r
-                               else if(!strncmp("timeout", line, strlen("timeout")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'", filepos);\r
-                               else if(!strncmp("expect signal", line, strlen("expect signal")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'", filepos);\r
-                               else if(!strncmp("expect return", line, strlen("expect return")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'", filepos);\r
-                               else if(!strncmp("include", line, strlen("include")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand include  :`(usage : include <file> [<description>])'", filepos);\r
-                               else if(!strncmp("suite", line, strlen("suite")))\r
-                                       ERROR1("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'", filepos);\r
-                               else\r
-                                       ERROR2("[%s] Unknown metacommand: `%s'",filepos,line);\r
-\r
-                               unit_set_error(fstream->unit, ESYNTAX, 1, filepos);\r
-\r
-                               failure(unit);\r
-                               return;\r
-                       }\r
-               }\r
-               \r
-               break;\r
-       }\r
-}\r
-\r
-void\r
-fstream_handle_include(fstream_t fstream, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)\r
-{\r
-       directory_t dir;\r
-       char* prev_directory = NULL;\r
-       fstream_t _fstream = NULL;\r
-       struct stat buffer = {0};\r
-       unit_t unit = fstream->unit;\r
-       \r
-       if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
-       {\r
-               /* the file is in the current directory */\r
-               _fstream = fstream_new(getcwd(NULL, 0), file_name);\r
-               fstream_open(_fstream);\r
-       }\r
-       /* the file to include is not in the current directory, check if it is in a include directory */\r
-       else\r
-       {\r
-               unsigned int i;\r
-               prev_directory = getcwd(NULL, 0);\r
-               \r
-               xbt_dynar_foreach(include_dirs, i, dir)\r
-               {\r
-                       chdir(dir->name);\r
-                       \r
-                       if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))\r
-                       {\r
-                               _fstream = fstream_new(dir->name, file_name);\r
-                               fstream_open(_fstream);\r
-                               break;\r
-                       }\r
-               }\r
-\r
-               chdir(prev_directory);\r
-               free(prev_directory);\r
-       }\r
-       \r
-       /* the file to include is not found handle the failure */\r
-       if(!_fstream)\r
-       {\r
-               if(file_name[0] == '$')\r
-               {\r
-                       ERROR3("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",context->line, file_name, file_name + 1);\r
-               \r
-               }\r
-               else\r
-               {\r
-                       /* may be a variable */\r
-                       variable_t variable;\r
-                       int exists = 0;\r
-                       unsigned int i;\r
-\r
-                       xbt_dynar_foreach(unit->runner->variables, i, variable)\r
-                       {\r
-                               if(!strcmp(variable->name, file_name))\r
-                               {\r
-                                       exists = 1;\r
-                                       break;\r
-                               }\r
-                       }\r
-\r
-                       if(exists)\r
-                               ERROR3("[%s] Include file `(%s)' not found (if you want to use the variable <%s> add the prefix `$')",context->line, file_name, file_name);\r
-                       else\r
-                               ERROR2("[%s] Include file `(%s)' not found",context->line, file_name);\r
-               }\r
-               \r
-               unit_set_error(fstream->unit, EINCLUDENOTFOUND, 1, context->line);\r
-\r
-               failure(fstream->unit);\r
-\r
-               return;\r
-       }\r
-       else\r
-       {\r
-               if(!unit->is_running_suite)\r
-               {/* it's the unit of a suite */\r
-                       unit_t include = unit_new(unit->runner, unit->root, unit, _fstream);\r
-                       \r
-                       include->mutex = unit->root->mutex;\r
-               \r
-                       if(description)\r
-                               include->description = strdup(description);\r
-               \r
-                       xbt_dynar_push(unit->includes, &include);\r
-                \r
-                       if(!dry_run_flag)\r
-                       {\r
-                               if(description)\r
-                                       INFO2("Include from %s (%s)", _fstream->name, description);\r
-                               else\r
-                                       INFO1("Include from %s", _fstream->name);\r
-\r
-                       }\r
-                       else\r
-                               INFO1("Checking include %s...",_fstream->name);\r
-                       \r
-                       fstream_parse(_fstream, mutex);\r
-               }\r
-               else\r
-               {/* it's a include */\r
-\r
-                       unit_t* owner;\r
-                       unit_t include;\r
-\r
-                       owner = xbt_dynar_get_ptr(unit->suites, xbt_dynar_length(unit->suites) - 1);\r
-                       \r
-                       include = unit_new(unit->runner, unit->root, *owner, _fstream);\r
-                       \r
-                       include->mutex = unit->root->mutex;\r
-                       \r
-                       if(description)\r
-                               include->description = strdup(description);\r
-               \r
-                       xbt_dynar_push((*owner)->includes, &include);\r
-                       \r
-                       if(!dry_run_flag)\r
-                       {\r
-                               if(description)\r
-                                       INFO2("Include from %s (%s)", _fstream->name, description);\r
-                               else\r
-                                       INFO1("Include from %s", _fstream->name);\r
-                       }\r
-                       else\r
-                               INFO1("Checking include %s...",_fstream->name);\r
-                       \r
-                       fstream_parse(_fstream, mutex);\r
-               }\r
-       }\r
-}\r
-\r
-void\r
-fstream_handle_suite(fstream_t fstream, const char* description, const char* filepos)\r
-{\r
-       unit_t unit = fstream->unit;\r
-       unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);\r
-       \r
-       if(description)\r
-               suite->description = strdup(description);\r
-\r
-       suite->filepos = strdup(filepos); \r
-\r
-       xbt_dynar_push(unit->suites, &suite);\r
-       unit->is_running_suite = 1;\r
-       \r
-       if(!dry_run_flag)\r
-               INFO1("Test suite %s", description);\r
-       else\r
-               INFO1("Checking suite %s...",description);\r
-       \r
-}\r
-\r
-int\r
-fstream_launch_command(fstream_t fstream, context_t context, xbt_os_mutex_t mutex)\r
-{\r
-       unit_t unit = fstream->unit;\r
-\r
-       if(!dry_run_flag)\r
-       {\r
-               command_t command;\r
-               \r
-               if(!(command = command_new(unit, context, mutex)))\r
-               {\r
-                       if(EINVAL == errno)\r
-                       {\r
-                               ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);   \r
-\r
-                               unit_set_error(unit, errno, 0, context->pos);\r
-                               failure(unit);\r
-                               return -1;\r
-                       }\r
-                       else if(ENOMEM == errno)\r
-                       {\r
-                               ERROR3("[%s] Cannot instantiate the command `%s' (%d)",context->pos, strerror(errno), errno);\r
-\r
-                               unit_set_error(unit, errno, 0, context->pos);\r
-\r
-                               failure(unit);\r
-                               return -1;\r
-                       }\r
-               }\r
-               \r
-               if(command_run(command) < 0)\r
-               {\r
-                       ERROR3("[%s] Cannot run the command `%s' (%d)",context->pos, strerror(errno), errno);   \r
-                       unit_set_error(unit, errno, 0, context->pos);\r
-                       failure(unit);\r
-                       return -1;      \r
-               }\r
-       }\r
-       \r
-       if(context_reset(context) < 0)\r
-       {\r
-               ERROR3("[%s] Cannot reset the context of the command `%s' (%d)",context->pos, strerror(errno), errno);  \r
-\r
-               unit_set_error(fstream->unit, errno, 0, context->pos);\r
-\r
-               failure(unit);\r
-               return -1;      \r
-       }\r
-       \r
-       return 0;\r
-}\r
-\r
-\r
-\r
-\r
+    else
+      \r {
+      \rsnprintf(file_pos, 256, "%s:%d", fstream->name, line_num);
+      \rfstream_lex_line(fstream, context, mutex, file_pos, line);
+      \r}
+    \r}
+  \r\r
+      /* Check that last command of the file ran well */ \r
+      if (context->command_line)
+    \r {
+    \r
+#ifdef _XBT_WIN32\r
+        if (!context->is_not_found)
+      \r {
+      \r
+#endif  /* \r */
+          \rif (fstream_launch_command(fstream, context, mutex) < 0)
+        \rreturn -1;
+      \r\r
+#ifdef _XBT_WIN32\r
+      }
+    \r
+#endif  /* \r */
+    }
+  \r\r
+      /* clear buffers */ \r
+      if (line)
+    \rfree(line);
+  \r\rxbt_strbuff_free(buff);
+  \r\rif (context_free(&context) < 0)
+    \rreturn -1;
+  \r\rreturn (exit_code || errno) ? -1 : 0;
+\r}
+
+\r\r\rvoid \r
+fstream_lex_line(fstream_t fstream, context_t context,
+                 xbt_os_mutex_t mutex, const char *filepos, char *line) \r
+{
+  \rchar *line2;
+  \rvariable_t variable;
+  \runsigned int i;
+  \rchar exp[PATH_MAX + 1] = { 0 };
+  \runit_t unit = fstream->unit;
+  \rxbt_dynar_t variables = unit->runner->variables;
+  \rchar *p = NULL;
+  \rchar *end = NULL;
+  \rchar *val = NULL;
+  \rchar buff[PATH_MAX + 1] = { 0 };
+  \rsize_t len;
+  \rchar delimiters[4] = { ' ', '\t', '\n', '\0' };
+  \r\rint j;
+  \r\rif (line[0] == '#')
+    \rreturn;
+  \r\rif (unit->is_running_suite
+        && strncmp(line, "! include", strlen("! include")))
+    \r {                         /* it's the end of a suite */
+    \r\runit_t * current_suite =
+        xbt_dynar_get_ptr(unit->suites,
+                          xbt_dynar_length(unit->suites) - 1);
+    \r\rif (!xbt_dynar_length((*current_suite)->includes))
+      \rERROR2("[%s] Malformated suite `(%s)': include missing", filepos,
+              (*current_suite)->description);
+    \r
+    else
+      \rERROR2("[%s] Malformated suite `(%s)': blank line missing", filepos,
+              (*current_suite)->description);
+    \r\runit_set_error(*current_suite, ESYNTAX, 1, filepos);
+    \r\rfailure(fstream->unit);
+    \r}
+  \r\rcontext->line = strdup(filepos);
+  \r\r
+      /* search end */ \r
+      xbt_str_rtrim(line + 2, "\n");
+  \r\rline2 = strdup(line);
+  \r\rlen = 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
+      \rxbt_dynar_foreach(variables, i, variable) \r {
+    \rif (!(p = strstr(line2 + 2, "${")))
+      \rbreak;
+    \r\rmemset(buff, 0, len);
+    \r\rsprintf(buff, "${%s", variable->name);
+    \r\r
+        /* FALSE */ \r
+        if ((p = strstr(line2 + 2, buff)))
+      \r {
+      \rmemset(buff, 0, len);
+      \rp--;
+      \rj = 0;
+      \r\rwhile (*(p++) != '\0')
+        \r {
+        \rbuff[j++] = *p;
+        \r\rif (*p == '}')
+          \rbreak;
+        \r}
+      \r\rif (buff[j - 1] != '}')
+        \r {
+        \rxbt_os_mutex_release(unit->mutex);
+        \r\r\rERROR2("[%s] Syntax error : `%s'.", filepos, p - j);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rfailure(fstream->unit);
+        \rreturn;
+        \r}
+      \r\rif ((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\rend = strchr(p, '}');
+        \r\rif (!end || (end == p))
+          \r {
+          \rxbt_os_mutex_release(unit->mutex);
+          \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                    strstr(buff, "${"));
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(fstream->unit);
+          \rreturn;
+          \r}
+        \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+        \r\rstrncpy(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\rif (variable->val)
+          \rstr_replace_all(&line2, exp, variable->val, NULL);
+        \r
+        else
+          \r {
+          \rstr_replace_all(&line2, exp, val, NULL);
+          \r\rvariable->val = strdup(val);
+          \r}
+        \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+        \r\rif (val)
+          \r {
+          \rfree(val);
+          \rval = 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;
+        \rend = strchr(p, '}');
+        \r\rif (!end || (end == p))
+          \r {
+          \rxbt_os_mutex_release(unit->mutex);
+          \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                   strstr(line2, "${"));
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(fstream->unit);
+          \rreturn;
+          \r}
+        \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+        \r\rstrncpy(val, p, (end - p));
+        \r\rsprintf(exp, "${%s:-%s}", variable->name, val);
+        \r\rstr_replace_all(&line2, exp, variable->val ? variable->val : val,
+                          NULL);
+        \r\r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+        \r\rif (val)
+          \r {
+          \rfree(val);
+          \rval = 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\rend = strchr(p, '}');
+        \r\rif (!end || (end == p))
+          \r {
+          \rxbt_os_mutex_release(unit->mutex);
+          \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                    strstr(line2, "${"));
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(fstream->unit);
+          \rreturn;
+          \r}
+        \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+        \r\rstrncpy(val, p, (end - p));
+        \r\rsprintf(exp, "${%s:+%s}", variable->name, val);
+        \r\rif (variable->val)
+          \r {
+          \rstr_replace_all(&line2, exp, val, NULL);
+          \r}
+        \r
+        else
+          \r {
+          \rstr_replace_all(&line2, exp, NULL, NULL);
+          \rvariable->val = strdup(val);
+          \r}
+        \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+        \r\rif (val)
+          \r {
+          \rfree(val);
+          \rval = 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;
+        \rend = strchr(p, '}');
+        \r\rif (!end || (end == p))
+          \r {
+          \rxbt_os_mutex_release(unit->mutex);
+          \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                   strstr(line2, "${"));
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(fstream->unit);
+          \rreturn;
+          \r}
+        \r\rval = (char *) calloc((size_t) (end - p) + 1, sizeof(char));
+        \r\rstrncpy(val, p, (end - p));
+        \r\rsprintf(exp, "${%s:?%s}", variable->name, val);
+        \r\rif (variable->val)
+          \rstr_replace_all(&line2, exp, variable->val, NULL);
+        \r
+        else
+          \r {
+          \r\rxbt_os_mutex_release(unit->mutex);
+          \r\rERROR2("[%s] %s.", filepos, val);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(fstream->unit);
+          \rreturn;
+          \r}
+        \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+        \r\rif (val)
+          \r {
+          \rfree(val);
+          \rval = NULL;
+          \r}
+        \r}
+      \r}
+  \r}
+  \r\r
+      /* replace all existing $var */ \r
+      xbt_dynar_foreach(variables, i, variable) \r {
+    \rif (!strchr(line2 + 2, '$'))
+      \rbreak;
+    \r\rif (strstr(line2 + 2, variable->name))
+      \r {
+      \r\rsprintf(exp, "${#%s}", variable->name);
+      \r\rif (strstr(line2 + 2, exp))
+        \r {
+        \r\rif (variable->val)
+          \r {
+          \rchar slen[4] = { 0 };
+          \rsprintf(slen, "%d", (int) strlen(variable->val));
+          \rstr_replace_all(&line2, exp, slen, NULL);
+          \r}
+        \r
+        else
+          \rstr_replace_all(&line2, exp, "0", NULL);
+        \r}
+      \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+      \r\rsprintf(exp, "${%s}", variable->name);
+      \r\rif (strstr(line2 + 2, exp))
+        \r {
+        \rif (variable->val)
+          \rstr_replace_all(&line2, exp, variable->val, NULL);
+        \r
+        else
+          \rstr_replace_all(&line2, exp, NULL, NULL);
+        \r}
+      \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+      \r\rsprintf(exp, "$%s", variable->name);
+      \r\rif ((p = strstr(line2 + 2, exp)))
+        \r {
+        \rif ((p + strlen(variable->name) + 1)[0] != '\0'
+             && !(isalpha((p + strlen(variable->name) + 1)[0])))
+          \rdelimiters[0] = (p + strlen(variable->name) + 1)[0];
+        \r\rif (variable->val)
+          \rstr_replace_all(&line2, exp, variable->val, delimiters);
+        \r
+        else
+          \rstr_replace_all(&line2, exp, NULL, delimiters);
+        \r}
+      \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+      \r\r}
+  \r}
+  \r\rwhile ((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
+    {
+      \rchar *begin = NULL;
+      \r\rj = 0;
+      \rp--;
+      \r\rwhile (*(p++) != '\0')
+        \r {
+        \rif ((!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(\rbegin
+                                                                   &&
+                                                                   (\r
+                                                                    (*p ==
+                                                                     ':')
+                                                                    || (*p
+                                                                        ==
+                                                                        '=')
+                                                                    || (*p
+                                                                        ==
+                                                                        '-')
+                                                                    || (*p
+                                                                        ==
+                                                                        '+')
+                                                                    || (*p
+                                                                        ==
+                                                                        '?')
+                                                                    \r\r)
+                  \r)
+            \rbreak;
+          \r
+          else
+            \rexp[j++] = *p;
+          \r\rif (*p == ':')
+            \r {
+            \r
+                /* save the begining of the value */ \r
+                if ((*(p + 1) == '=') || (*(p + 1) == '-')
+                    || (*(p + 1) == '+') || (*(p + 1) == '?'))
+              \r {
+              \rbegin = p + 2;
+              \rexp[j++] = *(p + 1);
+              \rp++;
+              \rcontinue;
+              \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 == '}')
+            \rbreak;
+          \r}
+        \r
+        else
+          \rbreak;
+        \r}
+      \r\rif (exp[j - 1] == '}')
+        \r {
+        \rif (exp[2] == '#')
+          \r {
+          \r
+              /* ${#var} */ \r
+              \r\rif (4 == strlen(exp))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                     strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rstr_replace_all(&line2, exp, "0", NULL);
+          \r}
+        \r
+        else if (strstr(exp, ":="))
+          \r {
+          \r
+              /* ${var:=value} */ \r
+              \rend = strchr(p, '}');
+          \r\rif (!end || (end == begin))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                      strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rvariable = xbt_new0(s_variable_t, 1);
+          \r\rvariable->val =
+              (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+          \r\rstrncpy(variable->val, begin, (end - begin));
+          \r\rbegin = exp + 2;
+          \rend = strchr(exp, ':');
+          \r\rif (!end || (end == begin))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                      strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rvariable->name =
+              (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+          \r\rstrncpy(variable->name, exp + 2, (end - begin));
+          \r\rstr_replace_all(&line2, exp, variable->val, NULL);
+          \r\rxbt_dynar_push(variables, &variable);
+          \r\r}
+        \r
+        else if (strstr(exp, ":-"))
+          \r {
+          \r
+              /* ${var:-value} */ \r
+              \r\rend = strchr(p, '}');
+          \r\rif (!end || (end == begin))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                      strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rval =
+              (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+          \r\rstrncpy(val, begin, (end - begin));
+          \r\rstr_replace_all(&line2, exp, val, NULL);
+          \r\rif (val)
+            \rfree(val);
+          \r\r}
+        \r
+        else if (strstr(exp, ":+"))
+          \r {
+          \r
+              /* ${var:+value} */ \r
+              \rend = strchr(p, '}');
+          \r\rif (!end || (end == begin))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                     strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rstr_replace_all(&line2, exp, NULL, NULL);
+          \r}
+        \r
+        else if (strstr(exp, ":?"))
+          \r {
+          \r
+              /* ${var:?value} */ \r
+              \rend = strchr(p, '}');
+          \r\rif (!end || (end == begin))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                     strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rval =
+              (char *) calloc((size_t) (end - begin) + 1, sizeof(char));
+          \r\rstrncpy(val, begin, (end - begin));
+          \r\rxbt_os_mutex_release(unit->mutex);
+          \r\rERROR2("[%s] : `%s'.", filepos, val);
+          \r\rif (val)
+            \rfree(val);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(fstream->unit);
+          \r\rreturn;
+          \r\r}
+        \r
+        else
+          \r {
+          \r
+              /* ${var} */ \r
+              \rif (3 == strlen(exp))
+            \r {
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                     strchr(line2 + 2, '$'));
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(fstream->unit);
+            \rreturn;
+            \r}
+          \r\rstr_replace_all(&line2, exp, NULL, NULL);
+          \r\r}
+        \r\rmemset(exp, 0, VAR_NAME_MAX + 1);
+        \r}
+      \r
+      else
+        \r {
+        \rxbt_os_mutex_release(unit->mutex);
+        \r\rif (strstr(line2 + 2, "${"))
+          \rERROR2("[%s] Bad substitution : `%s'.", filepos,
+                  strstr(line2, "${"));
+        \r
+        else
+          \rERROR2("[%s] Syntax error : `%s'.", filepos,
+                  strstr(line2, "${"));
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rfailure(fstream->unit);
+        \rreturn;
+        \r}
+    \r\r}
+    \r\r}
+  \r\rwhile (1)
+    \r {
+    \rp = line2 + (line2[0] == '<' ? 4 : 2);
+    \r\rif ((p = strchr(p, '$')))
+      \r {
+      \rif (*(p + 1) != ' ')
+        \r {
+        \rj = 0;
+        \rp--;
+        \r\rwhile (*(p++) != '\0')
+          \r {
+          \rif (*p != ' ' && *p != '\t')
+            \rexp[j++] = *p;
+          \r
+          else
+            \rbreak;
+          \r\r}
+        \r\rstr_replace_all(&line2, exp, NULL, " \t\n\r");
+        \rmemset(exp, 0, VAR_NAME_MAX + 1);
+        \r}
+      \r
+      else
+        \r {
+        \r
+            /* maybe < $ cmd */ \r
+            p++;
+        \r}
+      \r}
+    \r
+    else
+      \rbreak;
+    \r}
+  \r\rxbt_os_mutex_release(unit->mutex);
+  \r\rswitch (line2[0])
+    \r {
+    \r
+        /*case '#': \r
+           break;\r
+         */ \r
+  \rcase '$':
+  \rcase '&':
+    \r\rif (line[1] != ' ')
+      \r {
+      \r\rif (line2[0] == '$')
+        \rERROR1("[%s] Missing space after `$' `(usage : $ <command>)'",
+                filepos);
+      \r
+      else
+        \rERROR1("[%s] Missing space after & `(usage : & <command>)'",
+                filepos);
+      \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+      \r\rfailure(unit);
+      \rreturn;
+      \r}
+    \r\rcontext->async = (line2[0] == '&');
+    \r\r\r
+        /* further trim useless chars which are significant for in/output */ \r
+        xbt_str_rtrim(line2 + 2, " \t");
+    \r\r
+        /* deal with CD commands here, not in context */ \r
+        if (!strncmp("cd ", line2 + 2, 3))
+      \r {
+      \rchar *dir = strdup(line2 + 4);
+      \r\rif (context->command_line)
+        \r {
+        \rif (fstream_launch_command(fstream, context, mutex) < 0)
+          \rreturn;
+        \r}
+      \r\r
+          /* search begining */ \r
+          while (*(dir++) == ' ');
+      \r\rdir--;
+      \r\rif (!dry_run_flag)
+        \r {
+        \rif (!silent_flag)
+          \rINFO2("[%s] cd %s", filepos, dir);
+        \r\rif (!just_print_flag)
+          \r {
+          \rif (chdir(dir))
+            \r {
+            \rERROR3("[%s] Chdir to %s failed: %s", filepos, dir,
+                    error_to_string(errno, 0));
+            \runit_set_error(fstream->unit, errno, 0, filepos);
+            \r\rfailure(unit);
+            \r}
+          \r}
+        \r}
+      \r\rbreak;
+      \r}
+    \r
+    else
+      \r {
+      \rfstream_process_token(fstream, context, mutex, filepos, line2[0],
+                             line2 + 2);
+      \rbreak;
+      \r}
+  \r\rcase '<':
+  \rcase '>':
+  \rcase '!':
+    \r\rif (line[0] == '!' && line[1] != ' ')
+      \r {
+      \rERROR1
+          ("[%s] Missing space after `!' `(usage : ! <command> [[=]value])'",
+           filepos);
+      \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+      \r\rfailure(unit);
+      \rreturn;
+      \r}
+    \r\rfstream_process_token(fstream, context, mutex, filepos, line2[0],
+                            line2 + 2);
+    \rbreak;
+  \r\rcase 'p':
+    \r\r {
+      \runsigned int j;
+      \rint is_blank = 1;
+      \r\rchar *prompt = line2 + 2;
+      \r\rfor (j = 0; j < strlen(prompt); j++)
+        \r {
+        \rif (prompt[j] != ' ' && prompt[j] != '\t')
+          \r {
+          \ris_blank = 0;
+          \rbreak;
+          \r}
+        \r}
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Bad usage of the metacommand p `(usage : p <prompt>)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rif (!dry_run_flag)
+        \rINFO2("[%s] %s", filepos, prompt);
+    \r}
+    \r\r\rbreak;
+  \r\rcase 'P':
+    \r\r {
+      \runsigned int j;
+      \rint is_blank = 1;
+      \r\rchar *prompt = line2 + 2;
+      \r\rfor (j = 0; j < strlen(prompt); j++)
+        \rif (prompt[j] != ' ' && prompt[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Bad usage of the metacommand P `(usage : P <prompt>)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rif (!dry_run_flag)
+        \rCRITICAL2("[%s] %s", filepos, prompt);
+    \r}
+    \r\rbreak;
+  \r\rcase 'D':
+    \rif (unit->description)
+      \rWARN2("[%s] Description already specified `%s'", filepos,
+             line2 + 2);
+    \r
+    else
+      \r {
+      \runsigned int j;
+      \rint is_blank = 1;
+      \r\rchar *desc = line2 + 2;
+      \r\rfor (j = 0; j < strlen(desc); j++)
+        \rif (desc[j] != ' ' && desc[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Bad usage of the metacommand D `(usage : D <Description>)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\runit->description = strdup(desc);
+      \r}
+    \rbreak;
+  \r\rdefault:
+    \rERROR2("[%s] Syntax error `%s'", filepos, line2);
+    \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+    \rfailure(unit);
+    \rbreak;
+    \r}
+  \r\rfree(line2);
+\r}
+
+\r\rvoid \r
+fstream_process_token(fstream_t fstream, context_t context,
+                      xbt_os_mutex_t mutex, const char *filepos,
+                      char token, char *line) \r
+{
+  \runit_t unit = fstream->unit;
+  \r\rswitch (token)
+    \r {
+  \rcase '$':
+  \rcase '&':
+    \r\rif (context->command_line)
+      \r {
+      \r\rif (context->output->used || context->input->used)
+        \r {
+        \rERROR2
+            ("[%s] More than one command in this chunk of lines (previous: %s).\nDunno which input/output belongs to which command.",
+             filepos, context->command_line);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rif (fstream_launch_command(fstream, context, mutex) < 0)
+        \rreturn;
+      \r\rVERB1("[%s] More than one command in this chunk of lines",
+              filepos);
+      \r}
+    \r\r {
+      \rsize_t j, \ris_blank = 1;
+      \r\rfor (j = 0; j < strlen(line); j++)
+        \rif (line[j] != ' ' && line[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rif (token == '$')
+          \rERROR1("[%s] Undefinite command for `$' `(usage: $ <command>)'",
+                  filepos);
+        \r
+        else
+          \rERROR1("[%s] Undefinite command for `&' `(usage: & <command>)'",
+                  filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+    \r}
+    \r\rcontext->command_line = strdup(line);
+    \r\rxbt_str_ltrim(context->command_line, " ");
+    \r\rcontext->line = /*strdup(filepos) */ filepos;
+    \rcontext->pos = strdup(filepos);
+    \r\r
+#ifdef _XBT_WIN32\r
+    {
+      \r\r
+          /* translate the command line */ \r
+      \rchar *path = NULL;
+      \rchar *delimiter;
+      \rchar command_line[PATH_MAX + 1] = { 0 };
+      \rsize_t i = 0;
+      \rchar *args = NULL;
+      \r\r\r\r
+          /*if(strstr(context->command_line,".exe"))\r
+             strcpy(command_line,context->command_line); */ \r
+          \r {
+        \rsize_t len;
+        \r\rsize_t j = 0;
+        \r\rlen = strlen(context->command_line);
+        \r\rwhile (i < len)
+          \r {
+          \rif (context->command_line[i] != ' '
+               && context->command_line[i] != '\t'
+               && context->command_line[i] != '>')
+            \rcommand_line[j++] = context->command_line[i];
+          \r
+          else
+            \rbreak;
+          \r\ri++;
+          \r}
+        \r\rif (!strstr(context->command_line, ".exe"))
+          \rstrcat(command_line, ".exe");
+        \r\rargs = strdup(context->command_line + i);
+      \r}
+      \r\rif (!is_w32_cmd(command_line, fstream->unit->runner->path)
+            && getpath(command_line, &path) < 0)
+        \r {
+        \rcommand_t command;
+        \r\rERROR3("[%s] `%s' : NOK (%s)", filepos, command_line,
+                 error_to_string(ECMDNOTFOUND, 1));
+        \runit_set_error(fstream->unit, ECMDNOTFOUND, 1, filepos);
+        \r\rcontext->is_not_found = 1;
+        \r\rcommand = command_new(fstream->unit, context, mutex);
+        \r\rcommand->status = cs_failed;
+        \rcommand->reason = csr_command_not_found;
+        \r\rfailure(unit);
+        \r\r\rreturn;
+        \r}
+      \r\rdelimiter = strrchr(command_line, '/');
+      \r\rif (!delimiter)
+        \rdelimiter = strrchr(command_line, '\\');
+      \r\r
+          /*free(context->command_line); */ \r
+          \r\rif (path)
+        \r {
+        \rif (args)
+          \r {
+          \rcontext->t_command_line =
+              (char *) calloc(strlen(path) +
+                              strlen(delimiter ? delimiter +
+                                     1 : command_line) + strlen(args) + 2,
+                              sizeof(char));
+          \rsprintf(context->t_command_line, "%s\\%s%s", path,
+                   delimiter ? delimiter + 1 : command_line, args);
+          \r\rfree(args);
+          \r\r}
+        \r
+        else
+          \r {
+          \rcontext->t_command_line =
+              (char *) calloc(strlen(path) +
+                              strlen(delimiter ? delimiter +
+                                     1 : command_line) + 2, sizeof(char));
+          \rsprintf(context->t_command_line, "%s\\%s", path,
+                   delimiter ? delimiter + 1 : command_line);
+          \r\r\rfree(path);
+        \r}
+      \r
+      else
+        \r {
+        \rif (args)
+          \r {
+          \r\rcontext->t_command_line =
+              (char *) calloc(strlen(command_line) + strlen(args) + 1,
+                              sizeof(char));
+          \rsprintf(context->t_command_line, "%s%s", command_line, args);
+          \r\r\rfree(args);
+          \r\r}
+        \r
+        else
+          \r {
+          \rcontext->t_command_line =
+              (char *) calloc(strlen(command_line) + 1, sizeof(char));
+          \rstrcpy(context->t_command_line, command_line);
+    \r\r\r\r\r\r
+#endif  /* \r */
+        \r\rbreak;
+  \r\rcase '<':
+    \rxbt_strbuff_append(context->input, line);
+    \rxbt_strbuff_append(context->input, "\n");
+    \rbreak;
+  \r\rcase '>':
+    \rxbt_strbuff_append(context->output, line);
+    \rxbt_strbuff_append(context->output, "\n");
+    \rbreak;
+  \r\rcase '!':
+    \r\rif (context->command_line)
+      \r {
+      \rif (fstream_launch_command(fstream, context, mutex) < 0)
+        \rreturn;
+      \r}
+    \r\rif (!strncmp(line, "timeout no", strlen("timeout no")))
+      \r {
+      \rVERB1("[%s] (disable timeout)", filepos);
+      \rcontext->timeout = INDEFINITE;
+      \r}
+    \r
+    else if (!strncmp(line, "timeout ", strlen("timeout ")))
+      \r {
+      \rint i = 0;
+      \runsigned int j;
+      \rint is_blank = 1;
+      \rchar *p = line + strlen("timeout ");
+      \r\r\rfor (j = 0; j < strlen(p); j++)
+        \rif (p[j] != ' ' && p[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Undefinite timeout value `(usage :timeout <seconds>)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rwhile (p[i] != '\0')
+        \r {
+        \rif (!isdigit(p[i]))
+          \r {
+          \rERROR2
+              ("[%s] Invalid timeout value `(%s)' : `(usage :timeout <seconds>)'",
+               filepos, line + strlen("timeout "));
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\ri++;
+        \r}
+      \r\rcontext->timeout = atoi(line + strlen("timeout"));
+      \rVERB2("[%s] (new timeout value: %d)", filepos, context->timeout);
+      \r\r}
+    \r
+    else if (!strncmp(line, "expect signal ", strlen("expect signal ")))
+      \r {
+      \runsigned int j;
+      \rint is_blank = 1;
+      \r\r\rchar *p = line + strlen("expect signal ");
+      \r\r\rfor (j = 0; j < strlen(p); j++)
+        \rif (p[j] != ' ' && p[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Undefinite signal name `(usage :expect signal <signal name>)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rcontext->signal = strdup(line + strlen("expect signal "));
+      \r\rxbt_str_trim(context->signal, " \n");
+      \r\r
+#ifdef _XBT_WIN32\r
+          if (!strstr("SIGSEGVSIGTRAPSIGBUSSIGFPESIGILL", context->signal))
+        \r {
+        \rERROR2("[%s] Signal `%s' not supported by this platform", filepos,
+                context->signal);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r
+#else   /* \r */
+          if (!sig_exists(context->signal))
+        \r {
+        \rERROR2("[%s] Signal `%s' not supported by Tesh", filepos,
+                context->signal);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\r
+#endif  /* \r */
+          \r\rVERB2("[%s] (next command must raise signal %s)", filepos,
+                  context->signal);
+      \r\r}
+    \r
+    else if (!strncmp(line, "expect return ", strlen("expect return ")))
+      \r {
+      \r\rint i = 0;
+      \runsigned int j;
+      \rint is_blank = 1;
+      \rchar *p = line + strlen("expect return ");
+      \r\r\rfor (j = 0; j < strlen(p); j++)
+        \rif (p[j] != ' ' && p[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Undefinite return value `(usage :expect return <return value>)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rwhile (p[i] != '\0')
+        \r {
+        \rif (!isdigit(p[i]))
+          \r {
+          \rERROR2
+              ("[%s] Invalid exit code value `(%s)' : must be an integer >= 0 and <=255",
+               filepos, line + strlen("expect return "));
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\ri++;
+        \r}
+      \r\rcontext->exit_code = atoi(line + strlen("expect return "));
+      \rVERB2("[%s] (next command must return code %d)", filepos,
+             context->exit_code);
+      \r\r}
+    \r
+    else if (!strncmp(line, "output ignore", strlen("output ignore")))
+      \r {
+      \rcontext->output_handling = oh_ignore;
+      \rVERB1("[%s] (ignore output of next command)", filepos);
+      \r\r}
+    \r
+    else if (!strncmp(line, "output display", strlen("output display")))
+      \r {
+      \rcontext->output_handling = oh_display;
+      \rVERB1("[%s] (ignore output of next command)", filepos);
+      \r\r}
+    \r
+    else if (!strncmp(line, "include ", strlen("include ")))
+      \r {
+      \rchar *p1;
+      \rchar *p2;
+      \r\rp1 = line + strlen("include");
+      \r\rwhile (*p1 == ' ' || *p1 == '\t')
+        \rp1++;
+      \r\r\rif (p1[0] == '\0')
+        \r {
+        \rERROR1
+            ("[%s] no file specified : `(usage : include <file> [<description>])'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r
+      else
+        \r {
+        \rchar file_name[PATH_MAX + 1] = { 0 };
+        \r\rp2 = p1;
+        \r\rwhile (*p2 != '\0' && *p2 != ' ' && *p2 != '\t')
+          \rp2++;
+        \r\rstrncpy(file_name, p1, p2 - p1);
+        \r\r\rif (p2[0] != '\0')
+          \rwhile (*p2 == ' ' || *p2 == '\t')
+            \rp2++;
+        \r\rfstream_handle_include(fstream, context, mutex, file_name,
+                                 p2[0] != '\0' ? p2 : NULL);
+        \r\r}
+      \r}
+    \r
+    else if (!strncmp(line, "suite ", strlen("suite ")))
+      \r {
+      \runsigned int j;
+      \rint is_blank = 1;
+      \rchar *p = line + strlen("suite ");
+      \r\r\rfor (j = 0; j < strlen(p); j++)
+        \rif (p[j] != ' ' && p[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Undefinite suit description : `(usage : suite <description>)",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rif (unit->is_running_suite)
+        \r {
+        \rERROR1("[%s] Suite already in progress", filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rfstream_handle_suite(fstream, line + strlen("suite "), filepos);
+      \r}
+    \r
+    else if (!strncmp(line, "unsetenv ", strlen("unsetenv ")))
+      \r {
+      \runsigned int i, j;
+      \rint exists = 0;
+      \rint env = 0;
+      \rint err = 0;
+      \rvariable_t variable;
+      \rint is_blank;
+      \r\rchar *name = line + strlen("unsetenv ");
+      \r\ris_blank = 1;
+      \r\rfor (j = 0; j < strlen(name); j++)
+        \rif (name[j] != ' ' && name[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \rERROR1
+            ("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rxbt_os_mutex_acquire(unit->mutex);
+      \r\r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+        \rif (!strcmp(variable->name, name))
+          \r {
+          \renv = variable->env;
+          \rerr = variable->err;
+          \rexists = 1;
+          \rbreak;
+          \r}
+      \r}
+      \r\rif (env)
+        \r {
+        \rif (exists)
+          \r {
+          \r
+#ifndef _XBT_WIN32\r
+              unsetenv(name);
+          \r
+#else   /* \r */
+              SetEnvironmentVariable(name, NULL);
+          \r
+#endif  /* \r */
+              xbt_dynar_cursor_rm(unit->runner->variables, &i);
+          \r}
+        \r
+        else
+          \r {
+          \rERROR2
+              ("[%s] `(%s)' environment variable not found : impossible to unset it",
+               filepos, name);
+          \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rxbt_os_mutex_release(unit->mutex);
+          \rfailure(unit);
+          \rreturn;
+          \r}
+        \r}
+      \r
+      else
+        \r {
+        \rif (exists)
+          \r {
+          \rif (!err)
+            \r {
+            \rERROR2
+                ("[%s] `(%s)' is not an environment variable : use `unset' instead `unsetenv'",
+                 filepos, name);
+            \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rfailure(unit);
+            \rxbt_os_mutex_release(unit->mutex);
+            \rreturn;
+            \r}
+          \r
+          else
+            \r {
+            \rERROR2
+                ("[%s] `(%s)' is not an environment variable (it's a system variable) : impossible to unset it",
+                 filepos, name);
+            \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \rfailure(unit);
+            \rreturn;
+            \r}
+          \r}
+        \r
+        else
+          \r {
+          \rERROR2
+              ("[%s] `(%s)' environment variable not found : impossible to unset it",
+               filepos, name);
+          \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rxbt_os_mutex_release(unit->mutex);
+          \rfailure(unit);
+          \rreturn;
+          \r}
+        \r}
+      \r\rxbt_os_mutex_release(unit->mutex);
+      \r\r\r}
+    \r
+    else if (!strncmp(line, "setenv ", strlen("setenv ")))
+      \r {
+      \rchar *val;
+      \rchar name[PATH_MAX + 1] = { 0 };
+      \rchar *p;
+      \runsigned int i;
+      \rint is_blank;
+      \runsigned int j;
+      \r\rp = line + strlen("setenv ");
+      \r\rval = strchr(p, '=');
+      \r\rif (val)
+        \r {
+        \rvariable_t variable;
+        \rint exists = 0;
+        \rint env = 0;
+        \rint err = 0;
+        \rval++;
+        \r\r
+            /* syntax error */ \r
+            if (val[0] == '\0' || val[0] == ' ' || val[0] == '\t')
+          \r {
+          \rERROR1
+              ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\r\r\rstrncpy(name, p, (val - p - 1));
+        \r\ris_blank = 1;
+        \r\rfor (j = 0; j < strlen(name); j++)
+          \rif (name[j] != ' ' && name[j] != '\t')
+            \ris_blank = 0;
+        \r\rif (is_blank)
+          \r {
+          \r\rERROR1
+              ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\r
+            /* test if the variable is already registred */ \r
+            xbt_os_mutex_acquire(unit->mutex);
+        \r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+          \rif (!strcmp(variable->name, name))
+            \r {
+            \renv = variable->env;
+            \rerr = variable->err;
+            \rexists = 1;
+            \rbreak;
+            \r}
+        \r}
+        \r\r
+            /* if the variable is already registred, update its value;\r
+             * otherwise register it.\r
+             */ \r
+            if (exists)
+          \r {
+          \rif (env)
+            \r {
+            \rif (!strcmp(val, variable->val))
+              \rWARN3
+                  ("[%s] This environment variable `(%s)' is already set with the value `(%s)'",
+                   filepos, name, val);
+            \r\rfree(variable->val);
+            \rvariable->val = strdup(val);
+            \r\r
+#ifdef _XBT_WIN32\r
+                SetEnvironmentVariable(variable->name, variable->val);
+            \r
+#else   /* \r */
+                setenv(variable->name, variable->val, 1);
+            \r
+#endif  /* \r */
+            }
+          \r
+          else
+            \r {
+            \rif (err)
+              \rERROR2
+                  ("[%s] Conflict : a system variable `(%s)' already exists",
+                   filepos, name);
+            \r
+            else
+              \rERROR2
+                  ("[%s] Conflict : (none environment) variable `(%s)' already exists",
+                   filepos, name);
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \rfailure(unit);
+            \rreturn;
+            \r}
+          \r}
+        \r
+        else
+          \r {
+          \rif (err)
+            \r {
+            \rERROR2("[%s] A system variable named `(%s)' already exists",
+                    filepos, name);
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \rfailure(unit);
+            \rreturn;
+            \r}
+          \r
+          else
+            \r {
+            \rvariable = variable_new(name, val);
+            \rvariable->env = 1;
+            \r\rxbt_dynar_push(unit->runner->variables, &variable);
+            \r\r
+#ifdef _XBT_WIN32\r
+                SetEnvironmentVariable(variable->name, variable->val);
+            \r
+#else   /* \r */
+                setenv(variable->name, variable->val, 0);
+            \r
+#endif  /* \r */
+            }
+          \r}
+        \r\rxbt_os_mutex_release(unit->mutex);
+        \r\r}
+      \r
+      else
+        \r {
+        \rERROR1
+            ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rfailure(unit);
+        \rreturn;
+        \r}
+      \r}
+    \r
+    else if (!strncmp(line, "unset ", strlen("unset ")))
+      \r {
+      \runsigned int i, j;
+      \rint exists = 0;
+      \rint env = 0;
+      \rint err = 0;
+      \rvariable_t variable;
+      \rint is_blank;
+      \r\rchar *name = line + strlen("unset ");
+      \r\ris_blank = 1;
+      \r\rfor (j = 0; j < strlen(name); j++)
+        \rif (name[j] != ' ' && name[j] != '\t')
+          \ris_blank = 0;
+      \r\rif (is_blank)
+        \r {
+        \r\rERROR1
+            ("[%s] Bad usage of the metacommand unset `(usage : unset variable)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r\r\rxbt_os_mutex_acquire(unit->mutex);
+      \r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+        \rif (!strcmp(variable->name, name))
+          \r {
+          \renv = variable->env;
+          \rerr = variable->err;
+          \rexists = 1;
+          \rbreak;
+          \r}
+      \r}
+      \r\rif (!env && !err)
+        \r {
+        \rif (exists)
+          \r {
+          \r
+              /*xbt_dynar_remove_at(unit->runner->variables, i, NULL); */ \r
+              /*xbt_dynar_cursor_rm(unit->runner->variables, &i); */ \r
+              if (variable->val)
+            \r {
+            \rfree(variable->val);
+            \rvariable->val = NULL;
+            \r}
+          \r
+          else
+            \r {
+            \rWARN2("[%s] Variable `(%s)' already unseted", filepos,
+                   variable->name);
+            \r}
+          \r}
+        \r
+        else
+          \r {
+          \rERROR2("[%s] `(%s)' variable not found", filepos, name);
+          \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rxbt_os_mutex_release(unit->mutex);
+          \rfailure(unit);
+          \rreturn;
+          \r}
+        \r}
+      \r
+      else if (env)
+        \r {
+        \rERROR2
+            ("[%s] `(%s)' is an environment variable use `unsetenv' instead `unset'",
+             filepos, name);
+        \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rxbt_os_mutex_release(unit->mutex);
+        \rfailure(unit);
+        \rreturn;
+        \r}
+      \r
+      else if (err)
+        \r {
+        \rERROR2("[%s] `(%s)' is system variable : you can unset it",
+                filepos, name);
+        \runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rxbt_os_mutex_release(unit->mutex);
+        \rfailure(unit);
+        \rreturn;
+        \r}
+      \r\rxbt_os_mutex_release(unit->mutex);
+      \r\r}
+    \r
+    else if (!strncmp(line, "set ", strlen("set ")))
+      \r {
+      \rchar *val;
+      \rchar name[PATH_MAX + 1] = { 0 };
+      \runsigned int j;
+      \rint is_blank;
+      \r\rval = strchr(line + strlen("set "), '=');
+      \r\rif (val)
+        \r {
+        \rvariable_t variable;
+        \rint exists = 0;
+        \runsigned int i;
+        \rint err;
+        \rint env;
+        \r\rval++;
+        \r\r\r
+            /* syntax error */ \r
+            if (val[0] == '\0')
+          \r {
+          \rERROR1
+              ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r
+        else if (val[0] == ' ' || val[0] == '\t')
+          \r {
+          \rstrncpy(name, line + strlen("set "),
+                   (val - (line + strlen("set "))));
+          \r\rERROR2("[%s] No space avaible after`(%s)'", filepos, name);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\r\r
+            /* assume it's a varibale */ \r
+            \rstrncpy(name, line + strlen("set "),
+                     (val - (line + strlen("set ")) - 1));
+        \r\ris_blank = 1;
+        \r\rfor (j = 0; j < strlen(name); j++)
+          \rif (name[j] != ' ' && name[j] != '\t')
+            \ris_blank = 0;
+        \r\rif (is_blank)
+          \r {
+          \r\rERROR1
+              ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\rxbt_os_mutex_acquire(unit->mutex);
+        \r\r
+            /* test if the variable is already registred */ \r
+            xbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+          \rif (!strcmp(variable->name, name))
+            \r {
+            \rexists = 1;
+            \rerr = variable->err;
+            \renv = variable->env;
+            \rbreak;
+            \r}
+        \r}
+        \r\r
+            /* if the variable is already registred, update its value (if same value warns);\r
+             * otherwise register it.\r
+             */ \r
+            if (exists)
+          \r {
+          \rif (err)
+            \r {
+            \rERROR2("[%s] A system variable named `(%s)' already exists",
+                    filepos, name);
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rfailure(unit);
+            \rreturn;
+            \r}
+          \rif (env)
+            \r {
+            \rERROR2
+                ("[%s] `(%s)' is an environment variable use `setenv' instead `set'",
+                 filepos, name);
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rfailure(unit);
+            \rreturn;
+            \r}
+          \r
+          else
+            \r {
+            \rif (!strcmp(val, variable->val))
+              \rWARN3("[%s] Variable `(%s)' already contains value `<%s>'",
+                     filepos, variable->name, val);
+            \r\rfree(variable->val);
+            \rvariable->val = strdup(val);
+            \r}
+          \r}
+        \r
+        else
+          \r {
+          \rvariable_t new_var = variable_new(name, val);
+          \rxbt_dynar_push(unit->runner->variables, &new_var);
+          \r}
+        \r\r\rxbt_os_mutex_release(unit->mutex);
+        \r}
+      \r
+      else
+        \r {
+        \rERROR1
+            ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+             filepos);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \rfailure(unit);
+        \rreturn;
+        \r}
+      \r}
+    \r
+    else
+      \r {                       /* assume it's a variable */
+      \rchar *val;
+      \rchar name[PATH_MAX + 1] = { 0 };
+      \runsigned int i, j;
+      \rint is_blank;
+      \r\rval = strchr(line, '=');
+      \r\rif (val)
+        \r {
+        \rvariable_t variable;
+        \rint exists = 0;
+        \rint err;
+        \rint env;
+        \rval++;
+        \r\r\r
+            /* syntax error */ \r
+            if (val[0] == '\0')
+          \r {
+          \rstrncpy(name, line, (val - line - 1));
+          \r\ris_blank = 1;
+          \r\rfor (j = 0; j < strlen(name); j++)
+            \rif (name[j] != ' ' && name[j] != '\t')
+              \ris_blank = 0;
+          \r\rif (is_blank)
+            \rERROR1
+                ("[%s] Bad usage of Tesh variable mechanism `(usage : variable=value)'",
+                 filepos);
+          \r
+          else if (!strcmp("setenv", name))
+            \rERROR1
+                ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+                 filepos);
+          \r
+          else if (!strcmp("set", name))
+            \rERROR1
+                ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+                 filepos);
+          \r
+          else
+            \rERROR2("[%s] Undefined variable `(%s)'", filepos, name);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r
+        else if (val[0] == ' ' || val[0] == '\t')
+          \r {
+          \rstrncpy(name, line, (val - line));
+          \r\rERROR2("[%s] No space avaible after`(%s)'", filepos, name);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \r}
+        \r\r\r
+            /* assume it's a varibale */ \r
+            \rstrncpy(name, line, (val - line - 1));
+        \r\ris_blank = 1;
+        \r\rfor (j = 0; j < strlen(name); j++)
+          \rif (name[j] != ' ' && name[j] != '\t')
+            \ris_blank = 0;
+        \r\rif (is_blank)
+          \r {
+          \r\rERROR1
+              ("[%s] Bad usage of Tesh variable capability `(usage : variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \r\rfailure(unit);
+          \rreturn;
+          \r}
+        \r\rif (!strcmp("set", name))
+          \r {
+          \rERROR1
+              ("[%s] Bad usage of the metacommand set `(usage : set variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(unit);
+          \rreturn;
+          \r}
+        \r
+        else if (!strcmp("setenv", name))
+          \r {
+          \rERROR1
+              ("[%s] Bad usage of the metacommand setenv `(usage : setenv variable=value)'",
+               filepos);
+          \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+          \rfailure(unit);
+          \rreturn;
+          \r}
+        \r\rxbt_os_mutex_acquire(unit->mutex);
+        \r\r
+            /* test if the variable is already registred */ \r
+            xbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+          \rif (!strcmp(variable->name, name))
+            \r {
+            \rexists = 1;
+            \rerr = variable->err;
+            \renv = variable->env;
+            \rbreak;
+            \r}
+        \r}
+        \r\r
+            /* if the variable is already registred, update its value (if same value warns);\r
+             * otherwise register it.\r
+             */ \r
+            if (exists)
+          \r {
+          \rif (err)
+            \r {
+            \rERROR2("[%s] A system variable named `(%s)' already exists",
+                    filepos, name);
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \rfailure(unit);
+            \rreturn;
+            \r}
+          \rif (env)
+            \r {
+            \rERROR2
+                ("[%s] `(%s)' is an environment variable use `setenv' metacommand",
+                 filepos, name);
+            \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+            \rxbt_os_mutex_release(unit->mutex);
+            \r\rfailure(unit);
+            \rreturn;
+            \r}
+          \r
+          else
+            \r {
+            \rif (!strcmp(val, variable->val))
+              \rWARN3("[%s] Variable `(%s)' already contains value `<%s>'",
+                     filepos, variable->name, val);
+            \r\rfree(variable->val);
+            \rvariable->val = strdup(val);
+            \r}
+          \r}
+        \r
+        else
+          \r {
+          \rvariable_t new_var = variable_new(name, val);
+          \rxbt_dynar_push(unit->runner->variables, &new_var);
+          \r}
+        \r\r\rxbt_os_mutex_release(unit->mutex);
+        \r\r}
+      \r
+      else
+        \r {
+        \rif (!strncmp("setenv", line, strlen("setenv")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand setenv : `(usage : setenv variable=value)'",
+               filepos);
+        \r
+        else if (!strncmp("set", line, strlen("set")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand set : `(usage : set variable=value)'",
+               filepos);
+        \r
+        else if (!strncmp("unsetenv", line, strlen("unsetenv")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand unsetenv : `(usage : unsetenv variable)'",
+               filepos);
+        \r
+        else if (!strncmp("unset", line, strlen("unset")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand unset : `(usage : unset variable)'",
+               filepos);
+        \r
+        else if (!strncmp("timeout", line, strlen("timeout")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand timeout : `(usage : timeout <integral positive integer>)'",
+               filepos);
+        \r
+        else if (!strncmp("expect signal", line, strlen("expect signal")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand expect signal : `(usage : expect signal <sig_name>)'",
+               filepos);
+        \r
+        else if (!strncmp("expect return", line, strlen("expect return")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand expect return : `(usage : expect return <return value (>=0 <=255)>)'",
+               filepos);
+        \r
+        else if (!strncmp("include", line, strlen("include")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand include  :`(usage : include <file> [<description>])'",
+               filepos);
+        \r
+        else if (!strncmp("suite", line, strlen("suite")))
+          \rERROR1
+              ("[%s] Bad usage of the metacommand suite : `(usage : suite <description>)'",
+               filepos);
+        \r
+        else
+          \rERROR2("[%s] Unknown metacommand: `%s'", filepos, line);
+        \r\runit_set_error(fstream->unit, ESYNTAX, 1, filepos);
+        \r\rfailure(unit);
+        \rreturn;
+        \r}
+      \r}
+    \r\rbreak;
+    \r}
+\r}
+
+\r\rvoid \r
+fstream_handle_include(fstream_t fstream, context_t context,
+                       xbt_os_mutex_t mutex, const char *file_name,
+                       const char *description) \r
+{
+  \rdirectory_t dir;
+  \rchar *prev_directory = NULL;
+  \rfstream_t _fstream = NULL;
+  \rstruct stat buffer = { 0 };
+  \runit_t unit = fstream->unit;
+  \r\rif (!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
+    \r {
+    \r
+        /* the file is in the current directory */ \r
+        _fstream = fstream_new(getcwd(NULL, 0), file_name);
+    \rfstream_open(_fstream);
+    \r}
+  \r
+      /* the file to include is not in the current directory, check if it is in a include directory */ \r
+      else
+    \r {
+    \runsigned int i;
+    \rprev_directory = getcwd(NULL, 0);
+    \r\rxbt_dynar_foreach(include_dirs, i, dir) \r {
+      \rchdir(dir->name);
+      \r\rif (!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
+        \r {
+        \r_fstream = fstream_new(dir->name, file_name);
+        \rfstream_open(_fstream);
+        \rbreak;
+        \r}
+    \r}
+    \r\rchdir(prev_directory);
+    \rfree(prev_directory);
+    \r}
+  \r\r
+      /* the file to include is not found handle the failure */ \r
+      if (!_fstream)
+    \r {
+    \rif (file_name[0] == '$')
+      \r {
+      \rERROR3
+          ("[%s] Include file `(%s)' not found or variable `(%s)' doesn't exist",
+           context->line, file_name, file_name + 1);
+      \r\r}
+    \r
+    else
+      \r {
+      \r
+          /* may be a variable */ \r
+          variable_t variable;
+      \rint exists = 0;
+      \runsigned int i;
+      \r\rxbt_dynar_foreach(unit->runner->variables, i, variable) \r {
+        \rif (!strcmp(variable->name, file_name))
+          \r {
+          \rexists = 1;
+          \rbreak;
+          \r}
+      \r}
+      \r\rif (exists)
+        \rERROR3
+            ("[%s] Include file `(%s)' not found (if you want to use the variable <%s> add the prefix `$')",
+             context->line, file_name, file_name);
+      \r
+      else
+        \rERROR2("[%s] Include file `(%s)' not found", context->line,
+                file_name);
+      \r}
+    \r\runit_set_error(fstream->unit, EINCLUDENOTFOUND, 1, context->line);
+    \r\rfailure(fstream->unit);
+    \r\rreturn;
+    \r}
+  \r
+  else
+    \r {
+    \rif (!unit->is_running_suite)
+      \r {                       /* it's the unit of a suite */
+      \runit_t include = unit_new(unit->runner, unit->root, unit, _fstream);
+      \r\rinclude->mutex = unit->root->mutex;
+      \r\rif (description)
+        \rinclude->description = strdup(description);
+      \r\rxbt_dynar_push(unit->includes, &include);
+      \r\rif (!dry_run_flag)
+        \r {
+        \rif (description)
+          \rINFO2("Include from %s (%s)", _fstream->name, description);
+        \r
+        else
+          \rINFO1("Include from %s", _fstream->name);
+        \r\r}
+      \r
+      else
+        \rINFO1("Checking include %s...", _fstream->name);
+      \r\rfstream_parse(_fstream, mutex);
+      \r}
+    \r
+    else
+      \r {                       /* it's a include */
+      \r\runit_t * owner;
+      \runit_t include;
+      \r\rowner =
+          xbt_dynar_get_ptr(unit->suites,
+                            xbt_dynar_length(unit->suites) - 1);
+      \r\rinclude = unit_new(unit->runner, unit->root, *owner, _fstream);
+      \r\rinclude->mutex = unit->root->mutex;
+      \r\rif (description)
+        \rinclude->description = strdup(description);
+      \r\rxbt_dynar_push((*owner)->includes, &include);
+      \r\rif (!dry_run_flag)
+        \r {
+        \rif (description)
+          \rINFO2("Include from %s (%s)", _fstream->name, description);
+        \r
+        else
+          \rINFO1("Include from %s", _fstream->name);
+        \r}
+      \r
+      else
+        \rINFO1("Checking include %s...", _fstream->name);
+      \r\rfstream_parse(_fstream, mutex);
+      \r}
+    \r}
+\r}
+
+\r\rvoid \r
+fstream_handle_suite(fstream_t fstream, const char *description,
+                     const char *filepos) \r
+{
+  \runit_t unit = fstream->unit;
+  \runit_t suite = unit_new(unit->runner, unit->root, unit, NULL);
+  \r\rif (description)
+    \rsuite->description = strdup(description);
+  \r\rsuite->filepos = strdup(filepos);
+  \r\rxbt_dynar_push(unit->suites, &suite);
+  \runit->is_running_suite = 1;
+  \r\rif (!dry_run_flag)
+    \rINFO1("Test suite %s", description);
+  \r
+  else
+    \rINFO1("Checking suite %s...", description);
+\r\r}
+
+\r\rint \r
+fstream_launch_command(fstream_t fstream, context_t context,
+                       xbt_os_mutex_t mutex) \r
+{
+  \runit_t unit = fstream->unit;
+  \r\rif (!dry_run_flag)
+    \r {
+    \rcommand_t command;
+    \r\rif (!(command = command_new(unit, context, mutex)))
+      \r {
+      \rif (EINVAL == errno)
+        \r {
+        \rERROR3("[%s] Cannot instantiate the command `%s' (%d)",
+                context->pos, strerror(errno), errno);
+        \r\runit_set_error(unit, errno, 0, context->pos);
+        \rfailure(unit);
+        \rreturn -1;
+        \r}
+      \r
+      else if (ENOMEM == errno)
+        \r {
+        \rERROR3("[%s] Cannot instantiate the command `%s' (%d)",
+                context->pos, strerror(errno), errno);
+        \r\runit_set_error(unit, errno, 0, context->pos);
+        \r\rfailure(unit);
+        \rreturn -1;
+        \r}
+      \r}
+    \r\rif (command_run(command) < 0)
+      \r {
+      \rERROR3("[%s] Cannot run the command `%s' (%d)", context->pos,
+              strerror(errno), errno);
+      \runit_set_error(unit, errno, 0, context->pos);
+      \rfailure(unit);
+      \rreturn -1;
+      \r}
+    \r}
+  \r\rif (context_reset(context) < 0)
+    \r {
+    \rERROR3("[%s] Cannot reset the context of the command `%s' (%d)",
+            context->pos, strerror(errno), errno);
+    \r\runit_set_error(fstream->unit, errno, 0, context->pos);
+    \r\rfailure(unit);
+    \rreturn -1;
+    \r}
+  \r\rreturn 0;
+\r}
+
+\r\r\r\r\r