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 / unit.c
index 49282e4..566c6e4 100644 (file)
@@ -10,8 +10,8 @@
  *             This file contains all the definitions of the functions related with\r
  *             the tesh unit concept.\r
  *\r
- */\r
\r
+ */  \r
+    \r
 #include <unit.h>\r
 #include <command.h>\r
 #include <context.h>\r
 #include <variable.h>\r
 #include <str_replace.h>\r
 #include <xerrno.h>\r
-\r
-\r
-\r
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);\r
-\r
+    \r\r\rXBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
+\r\r
 /*! \brief unit_start - start the processing of the tesh file representing by the unit\r
  *\r
  * \param p            A void pointer to the unit representing the tesh file to process.\r
@@ -47,889 +44,817 @@ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
  *     6) Its release the next waiting unit (if any) by releasing the jobs semaphore.\r
  *     7) If its the last unit, it release the runner by releasing the semaphore used to wait for the end of all the units.\r
  *         \r
- */\r
-static void*\r
-unit_start(void* p) \r
-{\r
-       xbt_os_thread_t thread;\r
-       xbt_os_mutex_t mutex;\r
-       unit_t include, suite;\r
-       unsigned int itc, itu, its;\r
-       int include_nb, suite_nb;\r
-       command_t command;\r
-       \r
-       unit_t root = (unit_t)p;\r
-       \r
-       /* increment the number of running units */\r
-       xbt_os_mutex_acquire(root->mutex);\r
-       root->runner->number_of_runned_units++;\r
-       xbt_os_mutex_release(root->mutex);\r
-\r
-       /* must acquire the jobs semaphore to start */\r
-       /*xbt_os_sem_acquire(jobs_sem);*/\r
-       \r
-       /* initialize the mutex used to synchronize the access to the properties of this unit */\r
-       mutex = xbt_os_mutex_init();\r
-       \r
-       if(!dry_run_flag)\r
-               INFO1("Test unit from %s",root->fstream->name);\r
-       else\r
-               INFO1("Checking unit %s...",root->fstream->name); \r
-       \r
-       /* launch the parsing of the unit */\r
-       fstream_parse(root->fstream, mutex);\r
-       \r
-       /* if the unit is not interrupted and not failed the unit, all the file is parsed\r
-        * so all the command are launched\r
-        */\r
-       if(!root->interrupted)\r
-       {\r
-               root->parsed = 1;\r
-               \r
-               /* all the commands have terminated before the end of the parsing of the tesh file\r
-                * so the unit release the semaphore itself\r
-                */\r
-               if(!root->released && (root->started_cmd_nb == (root->failed_cmd_nb + root->interrupted_cmd_nb + root->successeded_cmd_nb)))\r
-                       xbt_os_sem_release(root->sem);  \r
-       }\r
-       \r
-       /* wait the end of all the commands or a command failure or an interruption */\r
-\r
-       xbt_os_sem_acquire(root->sem);\r
-       \r
-\r
-       if(root->interrupted)\r
-       {\r
-\r
-               xbt_dynar_foreach(root->commands, itc , command)\r
-               {\r
-                       if(command->status == cs_in_progress)\r
-                               command_interrupt(command);\r
-               }\r
-\r
-               /* interrupt all the running commands of the included units */\r
-               include_nb = xbt_dynar_length(root->includes);\r
-               \r
-               xbt_dynar_foreach(root->includes, itu, include)\r
-               {\r
-                       xbt_dynar_foreach(include->commands, itc, command)\r
-                       {\r
-                               if(command->status == cs_in_progress)\r
-                                       command_interrupt(command);\r
-                       }\r
-               }\r
-               \r
-               /* interrupt all the running commands of the unit */\r
-               suite_nb = xbt_dynar_length(root->suites);\r
-               \r
-               xbt_dynar_foreach(root->suites, its, suite)\r
-               {\r
-                       include_nb = xbt_dynar_length(suite->includes);\r
-\r
-                       xbt_dynar_foreach(suite->includes, itu, include)\r
-                       {\r
-                               xbt_dynar_foreach(include->commands, itc, command)\r
-                               {\r
-                                       if(command->status == cs_in_progress)\r
-                                               command_interrupt(command);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* wait the end of the command threads of the unit */\r
-       xbt_dynar_foreach(root->commands, itc, command)\r
-       {\r
-               thread = command->thread;\r
-               \r
-               if(thread)\r
-                       xbt_os_thread_join(thread,NULL);\r
-       }\r
-       \r
-       /* wait the end of the command threads of the included units of the unit */\r
-       include_nb = xbt_dynar_length(root->includes);\r
-        \r
-       xbt_dynar_foreach(root->includes, itu, include)\r
-       {\r
-               xbt_dynar_foreach(include->commands, itc, command)\r
-               {\r
-                       thread = command->thread;\r
-               \r
-                       if(thread)\r
-                               xbt_os_thread_join(thread,NULL);\r
-               }\r
-\r
-               if(!dry_run_flag)\r
-               {\r
-                       if(!include->exit_code && !include->interrupted)\r
-                               INFO1("Include from %s OK",include->fstream->name);\r
-                       else if(include->exit_code)\r
-                               ERROR3("Include `%s' NOK : (<%s> %s)", include->fstream->name, command->context->line, error_to_string(include->exit_code, include->err_kind));\r
-                       else if(include->interrupted && !include->exit_code)\r
-                               INFO1("Include `(%s)' INTR",include->fstream->name);\r
-               }\r
-       }\r
-       \r
-       /* interrupt all the running commands of the unit */\r
-       suite_nb = xbt_dynar_length(root->suites);\r
-       \r
-       xbt_dynar_foreach(root->suites, its, suite)\r
-       {\r
-               include_nb = xbt_dynar_length(suite->includes);\r
-\r
-               if(!include_nb)\r
-               {\r
-                       if(!suite->exit_code)\r
-                       {\r
-                               unit_set_error(suite, ESYNTAX, 1, suite->filepos);\r
-                               ERROR2("[%s] Empty suite `(%s)' detected (no includes added)", suite->filepos, suite->description);\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
-               xbt_dynar_foreach(suite->includes, itu, include)\r
-               {\r
-                       xbt_dynar_foreach(include->commands, itc, command)\r
-                       {\r
-                               thread = command->thread;\r
-               \r
-                               if(thread)\r
-                                       xbt_os_thread_join(thread,NULL);\r
-                       }\r
-                       \r
-                       if(!include->exit_code && !include->interrupted)\r
-                       {\r
-                               if(!dry_run_flag)\r
-                                       INFO1("Include from %s OK",include->fstream->name);\r
-                       }\r
-                       else if(include->exit_code)\r
-                       {\r
-                               if(!dry_run_flag)\r
-                                       ERROR3("Include `%s' NOK : (<%s> %s)", include->fstream->name, command->context->pos, error_to_string(include->exit_code, include->err_kind));\r
-\r
-                               suite->exit_code = include->exit_code;\r
-                               suite->err_kind = include->err_kind;\r
-                               suite->err_line = strdup(include->err_line);\r
-                       }\r
-                       else if(include->interrupted && !include->exit_code)\r
-                       {\r
-                               if(!dry_run_flag)\r
-                                       INFO1("Include `(%s)' INTR",include->fstream->name);\r
-\r
-                               suite->interrupted = 1;\r
-                       }\r
-                       \r
-               }\r
-               \r
-               if(!dry_run_flag )\r
-               {\r
-                       if(!suite->exit_code && !suite->interrupted)\r
-                               INFO1("Test suite from %s OK",suite->description);\r
-                       else if(suite->exit_code)\r
-                               ERROR3("Test suite `%s' NOK : (<%s> %s) ", suite->description, suite->err_line, error_to_string(suite->exit_code, suite->err_kind));\r
-                       else if(suite->interrupted && !suite->exit_code)\r
-                               INFO1("Test suite `(%s)' INTR",suite->description);\r
-               }\r
-       }\r
-       \r
-       /* you can now destroy the mutex used to synchrone the command accesses to the properties of the unit */\r
-       xbt_os_mutex_destroy(mutex);\r
-\r
-       /* update the number of ended units of the runner */\r
-       xbt_os_mutex_acquire(root->mutex);\r
-       \r
-       /* increment the number of ended units */\r
-       root->runner->number_of_ended_units++;\r
-       \r
-       if(!dry_run_flag )\r
-       {\r
-               if(root->interrupted && !root->exit_code)\r
-                       INFO1("Test unit from %s INTR",root->fstream->name);\r
-               else if(!root->exit_code)\r
-                               INFO1("Test unit from %s OK",root->fstream->name);\r
-               else if(root->exit_code)\r
-                       ERROR3("Test unit `%s': NOK (<%s> %s)",root->fstream->name, root->err_line, error_to_string(root->exit_code, root->err_kind));  \r
-       }\r
-       \r
-       /* if it's the last unit, release the runner */\r
-       if((root->runner->number_of_runned_units == root->runner->number_of_ended_units))\r
-       {\r
-               /* if all the commands of the unit are successeded itc's a successeded unit */\r
-               if(root->successeded_cmd_nb == root->cmd_nb && !root->exit_code /* case of only one cd : nb = successeded = 0)*/)\r
-                       root->successeded = 1; \r
-                       \r
-               /* first release the mutex */\r
-               xbt_os_mutex_release(root->mutex);\r
-               \r
-               /* release the runner */\r
-               xbt_os_sem_release(units_sem);\r
-       }\r
-       else\r
-               xbt_os_mutex_release(root->mutex);\r
-       \r
-       /* release the jobs semaphore, then the next waiting unit can start */\r
-       xbt_os_sem_release(jobs_sem);\r
-       \r
-       return NULL;\r
-\r
-}\r
-\r
-\r
-unit_t\r
-unit_new(runner_t runner, unit_t root, unit_t owner, fstream_t fstream)\r
-{\r
-       unit_t unit;\r
-       \r
-       unit = xbt_new0(s_unit_t, 1);\r
-       \r
-       /* instantiate the vector used to store all the commands of the unit */\r
-       unit->commands = xbt_dynar_new(sizeof(command_t), (void_f_pvoid_t)command_free);\r
-       \r
-       /* instantiate the vector used to store all the included units */\r
-       unit->includes = xbt_dynar_new(sizeof(unit_t), (void_f_pvoid_t)unit_free);\r
-       \r
-       /* instantiate the vector used to store all the included suites */\r
-       unit->suites = xbt_dynar_new(sizeof(unit_t), (void_f_pvoid_t)unit_free);\r
-       \r
-       /* the runner used to launch the tesh unit */\r
-       unit->runner = runner;\r
-       \r
-       /* the file stream object to use to parse the tesh file */\r
-       unit->fstream = fstream;\r
-       \r
-       if(fstream)\r
-               fstream->unit = unit;\r
-       \r
-       /* if no root parameter specified assume that itc's the root of all the units */\r
-       unit->root = root ?  root : unit;\r
-       \r
-       /* the owner of the suite */\r
-       unit->owner = owner;\r
-       \r
-       unit->thread = NULL;\r
-       unit->started_cmd_nb = 0;\r
-       unit->interrupted_cmd_nb = 0;\r
-       unit->failed_cmd_nb = 0;\r
-       unit->successeded_cmd_nb = 0;\r
-       unit->terminated_cmd_nb = 0;\r
-       unit->waiting_cmd_nb = 0;\r
-       unit->interrupted = 0;\r
-       unit->failed = 0;\r
-       unit->successeded = 0;\r
-       unit->parsed = 0;\r
-       unit->released = 0;\r
-       unit->owner = owner;\r
-       unit->is_running_suite = 0;\r
-       unit->description = NULL;\r
-       unit->sem = NULL;\r
-       unit->exit_code = 0;\r
-       unit->err_kind = 0;\r
-       unit->err_line = NULL;\r
-       unit->filepos = NULL;\r
-       \r
-       \r
-\r
-       return unit;\r
-}\r
-\r
-void\r
-unit_set_error(unit_t unit, int errcode, int kind, const char* line)\r
-{\r
-       if(!unit->exit_code)\r
-       {\r
-               unit->exit_code = errcode;\r
-               unit->err_kind = kind;\r
-               unit->err_line = strdup(line);\r
-\r
-               if(unit->root && !unit->root->exit_code)\r
-               {\r
-                       unit->root->exit_code = errcode;\r
-                       unit->root->err_kind = kind;\r
-                       unit->root->err_line = strdup(line);\r
-               }\r
-               \r
-               if(!exit_code)\r
-               {\r
-               \r
-                       exit_code = errcode;\r
-                       err_kind = kind;\r
-                       err_line = strdup(line);\r
-               }\r
-       }\r
-       \r
-}\r
-\r
-int\r
-unit_free(unit_t* ptr)\r
-{\r
-       if(!(*ptr))\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
-       \r
-       if((*ptr)->commands)\r
-               xbt_dynar_free(&((*ptr)->commands));\r
-       \r
-       if((*ptr)->includes)\r
-               xbt_dynar_free(&((*ptr)->includes));\r
-       \r
-       if((*ptr)->suites)\r
-               xbt_dynar_free(&((*ptr)->suites));\r
-       \r
-       /* if the unit is interrupted during its run, the semaphore is NULL */\r
-       if((*ptr)->sem)\r
-               xbt_os_sem_destroy((*ptr)->sem);\r
-               \r
-       if((*ptr)->description)\r
-               free((*ptr)->description);\r
-\r
-       if((*ptr)->err_line)\r
-               free((*ptr)->err_line);\r
-\r
-       if((*ptr)->filepos)\r
-               free((*ptr)->filepos);\r
-\r
-       free(*ptr);\r
-       *ptr = NULL;\r
-       \r
-       return 0;\r
-}\r
-\r
-int\r
-unit_run(unit_t unit, xbt_os_mutex_t mutex)\r
-{\r
-       /* check the parameters */\r
-       if(!(unit) || !mutex)\r
-    {\r
-        errno = EINVAL;\r
-               xbt_os_sem_release(jobs_sem);\r
-        return -1;\r
-               \r
-    }\r
-\r
-       if(!interrupted)\r
-       {\r
-               unit->mutex = mutex;\r
-               \r
-               unit->sem = xbt_os_sem_init(0);\r
-\r
-               /* start the unit */\r
-               unit->thread = xbt_os_thread_create("", unit_start, unit);\r
-       }\r
-       else\r
-       {\r
-               /* the unit is interrupted by the runner before its starting \r
-                * in this case the unit semaphore is NULL take care of that\r
-                * in the function unit_free()\r
-                */\r
-               unit->interrupted = 1;\r
-               xbt_os_sem_release(jobs_sem);\r
-       }\r
-               \r
-       return 0;\r
-       \r
-}\r
-\r
-int\r
-unit_interrupt(unit_t unit)\r
-{\r
-       /* check the parameter */\r
-       if(!(unit))\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
+ */ \r
+static void *\r unit_start(void *p) \r
+{
+  \rxbt_os_thread_t thread;
+  \rxbt_os_mutex_t mutex;
+  \runit_t include, suite;
+  \runsigned int itc, itu, its;
+  \rint include_nb, suite_nb;
+  \rcommand_t command;
+  \r\runit_t root = (unit_t) p;
+  \r\r
+      /* increment the number of running units */ \r
+      xbt_os_mutex_acquire(root->mutex);
+  \rroot->runner->number_of_runned_units++;
+  \rxbt_os_mutex_release(root->mutex);
+  \r\r
+      /* must acquire the jobs semaphore to start */ \r
+      /*xbt_os_sem_acquire(jobs_sem); */ \r
+      \r
+      /* initialize the mutex used to synchronize the access to the properties of this unit */ \r
+      mutex = xbt_os_mutex_init();
+  \r\rif (!dry_run_flag)
+    \rINFO1("Test unit from %s", root->fstream->name);
+  \r
+  else
+    \rINFO1("Checking unit %s...", root->fstream->name);
+  \r\r
+      /* launch the parsing of the unit */ \r
+      fstream_parse(root->fstream, mutex);
+  \r\r
+      /* if the unit is not interrupted and not failed the unit, all the file is parsed\r
+       * so all the command are launched\r
+       */ \r
+      if (!root->interrupted)
+    \r {
+    \rroot->parsed = 1;
+    \r\r
+        /* all the commands have terminated before the end of the parsing of the tesh file\r
+         * so the unit release the semaphore itself\r
+         */ \r
+        if (!root->released
+            && (root->started_cmd_nb ==
+                (root->failed_cmd_nb + root->interrupted_cmd_nb +
+                 root->successeded_cmd_nb)))
+      \rxbt_os_sem_release(root->sem);
+    \r}
+  \r\r
+      /* wait the end of all the commands or a command failure or an interruption */ \r
+      \rxbt_os_sem_acquire(root->sem);
+  \r\r\rif (root->interrupted)
+    \r {
+    \r\rxbt_dynar_foreach(root->commands, itc, command) \r {
+      \rif (command->status == cs_in_progress)
+        \rcommand_interrupt(command);
+    \r}
+    \r\r
+        /* interrupt all the running commands of the included units */ \r
+        include_nb = xbt_dynar_length(root->includes);
+    \r\rxbt_dynar_foreach(root->includes, itu, include) \r {
+      \rxbt_dynar_foreach(include->commands, itc, command) \r {
+        \rif (command->status == cs_in_progress)
+          \rcommand_interrupt(command);
+      \r}
+    \r}
+    \r\r
+        /* interrupt all the running commands of the unit */ \r
+        suite_nb = xbt_dynar_length(root->suites);
+    \r\rxbt_dynar_foreach(root->suites, its, suite) \r {
+      \rinclude_nb = xbt_dynar_length(suite->includes);
+      \r\rxbt_dynar_foreach(suite->includes, itu, include) \r {
+        \rxbt_dynar_foreach(include->commands, itc, command) \r {
+          \rif (command->status == cs_in_progress)
+            \rcommand_interrupt(command);
+        \r}
+      \r}
+    \r}
+    \r}
+  \r\r
+      /* wait the end of the command threads of the unit */ \r
+      xbt_dynar_foreach(root->commands, itc, command) \r {
+    \rthread = command->thread;
+    \r\rif (thread)
+      \rxbt_os_thread_join(thread, NULL);
+  \r}
+  \r\r
+      /* wait the end of the command threads of the included units of the unit */ \r
+      include_nb = xbt_dynar_length(root->includes);
+  \r\rxbt_dynar_foreach(root->includes, itu, include) \r {
+    \rxbt_dynar_foreach(include->commands, itc, command) \r {
+      \rthread = command->thread;
+      \r\rif (thread)
+        \rxbt_os_thread_join(thread, NULL);
+    \r}
+    \r\rif (!dry_run_flag)
+      \r {
+      \rif (!include->exit_code && !include->interrupted)
+        \rINFO1("Include from %s OK", include->fstream->name);
+      \r
+      else if (include->exit_code)
+        \rERROR3("Include `%s' NOK : (<%s> %s)", include->fstream->name,
+                include->err_line, error_to_string(include->exit_code,
+                                                   include->err_kind));
+      \r
+      else if (include->interrupted && !include->exit_code)
+        \rINFO1("Include `(%s)' INTR", include->fstream->name);
+      \r}
+  \r}
+  \r\r
+      /* interrupt all the running commands of the unit */ \r
+      suite_nb = xbt_dynar_length(root->suites);
+  \r\rxbt_dynar_foreach(root->suites, its, suite) \r {
+    \rinclude_nb = xbt_dynar_length(suite->includes);
+    \r\rif (!include_nb)
+      \r {
+      \rif (!suite->exit_code)
+        \r {
+        \runit_set_error(suite, ESYNTAX, 1, suite->filepos);
+        \rERROR2("[%s] Empty suite `(%s)' detected (no includes added)",
+                suite->filepos, suite->description);
+        \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\rxbt_dynar_foreach(suite->includes, itu, include) \r {
+      \rxbt_dynar_foreach(include->commands, itc, command) \r {
+        \rthread = command->thread;
+        \r\rif (thread)
+          \rxbt_os_thread_join(thread, NULL);
+      \r}
+      \r\rif (!include->exit_code && !include->interrupted)
+        \r {
+        \rif (!dry_run_flag)
+          \rINFO1("Include from %s OK", include->fstream->name);
+        \r}
+      \r
+      else if (include->exit_code)
+        \r {
+        \rif (!dry_run_flag)
+          \rERROR3("Include `%s' NOK : (<%s> %s)", include->fstream->name,
+                  command->context->pos,
+                  error_to_string(include->exit_code, include->err_kind));
+        \r\rsuite->exit_code = include->exit_code;
+        \rsuite->err_kind = include->err_kind;
+        \rsuite->err_line = strdup(include->err_line);
+        \r}
+      \r
+      else if (include->interrupted && !include->exit_code)
+        \r {
+        \rif (!dry_run_flag)
+          \rINFO1("Include `(%s)' INTR", include->fstream->name);
+        \r\rsuite->interrupted = 1;
+        \r}
+    \r\r}
+    \r\rif (!dry_run_flag)
+      \r {
+      \rif (!suite->exit_code && !suite->interrupted)
+        \rINFO1("Test suite from %s OK", suite->description);
+      \r
+      else if (suite->exit_code)
+        \rERROR3("Test suite `%s' NOK : (<%s> %s) ", suite->description,
+                suite->err_line, error_to_string(suite->exit_code,
+                                                 suite->err_kind));
+      \r
+      else if (suite->interrupted && !suite->exit_code)
+        \rINFO1("Test suite `(%s)' INTR", suite->description);
+      \r}
+  \r}
+  \r\r
+      /* you can now destroy the mutex used to synchrone the command accesses to the properties of the unit */ \r
+      xbt_os_mutex_destroy(mutex);
+  \r\r
+      /* update the number of ended units of the runner */ \r
+      xbt_os_mutex_acquire(root->mutex);
+  \r\r
+      /* increment the number of ended units */ \r
+      root->runner->number_of_ended_units++;
+  \r\rif (!dry_run_flag)
+    \r {
+    \rif (root->interrupted && !root->exit_code)
+      \rINFO1("Test unit from %s INTR", root->fstream->name);
     \r
-    /* if the unit is already interrupted, signal the error */\r
-    if(unit->interrupted)\r
-    {\r
-       errno = EALREADY;\r
-       return -1;\r
-    }\r
+    else if (!root->exit_code)
+      \rINFO1("Test unit from %s OK", root->fstream->name);
     \r
-       /* interrupt the run of the specified unit */\r
-       unit->interrupted = 1;\r
-       xbt_os_sem_release(unit->sem);\r
-       \r
-       return 0;\r
-}\r
-\r
-/* just print the title of the root unit or a suite (if any) */\r
-static void \r
-print_title(const char* description)\r
-{\r
-       register int i;\r
-       char title[80];\r
-       size_t len = strlen(description);\r
-               \r
-       title[0]=' ';\r
-               \r
-       for (i = 1; i < 79; i++)\r
-               title[i]='=';\r
-               \r
-       title[i++]='\n';\r
-       title[79]='\0';\r
-       \r
-       sprintf(title + 40 - (len + 4)/2, "[ %s ]",description);\r
-       title[40 + (len + 5 ) / 2] = '=';\r
-               \r
-       printf("\n%s\n",title); \r
-}\r
-\r
-int\r
-unit_summuarize(unit_t unit)\r
-{\r
-       command_t command;\r
-       unsigned int itc, itu, its;\r
-       unit_t include;\r
-       unit_t suite;\r
-       char* p;\r
-       char title[PATH_MAX + 1] = {0};\r
-       \r
-       int number_of_tests = 0;                                                /* number of tests of a unit contained by this unit                                     */\r
-       int number_of_failed_tests = 0;                                 /* number of failed test of a unit contained by this unit                       */\r
-       int number_of_successeded_tests = 0;                    /* number of successeded tests of a unit contained by this unit         */\r
-       int number_of_interrupted_tests = 0;                    /* number of interrupted tests of a unit contained by this unit         */\r
-       \r
-       int number_of_tests_of_suite = 0;                               /* number of tests of a suite contained by this unit                            */\r
-       int number_of_interrupted_tests_of_suite = 0;   /* number of interrupted tests of a suite contained by this unit        */      \r
-       int number_of_failed_tests_of_suite = 0;                /* number of failed tests of a suite contained by this unit                                     */\r
-       int number_of_successeded_tests_of_suite = 0;   /* number of successeded tests of a suite contained by this                     */\r
-       \r
-       int number_of_units = 0;                                                /* number of units contained by a suite                                                         */\r
-       int number_of_failed_units = 0;                                 /* number of failed units contained by a suite                                          */\r
-       int number_of_successeded_units = 0;                    /* number of successeded units contained by a suite                                     */\r
-       int number_of_interrupted_units = 0;                    /* number of interrupted units contained by a suite                                     */\r
-       \r
-       int total_of_tests = 0;                                                 /* total of the tests contained by this unit                                            */\r
-       int total_of_failed_tests = 0;                                  /* total of failed tests contained by this unit                                         */\r
-       int total_of_successeded_tests = 0;                     /* total of successeded tests contained by this unit                            */\r
-       int total_of_interrupted_tests = 0;                             /* total of interrupted tests contained by this unit                            */\r
-       \r
-       int total_of_units = 0;                                                 /* total of units contained by this unit                                                        */\r
-       int total_of_failed_units = 0;                                  /* total of failed units contained by this unit                                         */\r
-       int total_of_successeded_units = 0;                             /* total of successeded units contained by this unit                            */\r
-       int total_of_interrupted_units = 0;                             /* total of interrutped units contained by this unit                            */\r
-       \r
-       int total_of_suites = 0;                                                /* total of suites contained by this unit                                                       */\r
-       int total_of_failed_suites = 0;                                 /* total of failed suites contained by this unit                                        */\r
-       int total_of_successeded_suites = 0;                    /* total of successeded suites contained by this unit                           */ \r
-       int total_of_interrupted_suites = 0;                    /* total of interrupted suites contained by this unit                           */\r
-       \r
-       /* check the parameter */\r
-       if(!(unit))\r
-    {\r
-        errno = EINVAL;\r
-        return -1;\r
-    }\r
-       \r
-       if((unit->description) && strlen(unit->description) < 78)\r
-               strcpy(title, unit->description);\r
-       else\r
-               sprintf(title, "file : %s",unit->fstream->name);\r
-               \r
-       if(unit->interrupted)\r
-               strcat(title, " (interrupted)");\r
-               \r
-       print_title(title);\r
-       \r
-       number_of_tests = xbt_dynar_length(unit->commands);\r
-       \r
-       /* tests */\r
-       xbt_dynar_foreach(unit->commands, itc, command)\r
-       {\r
-               if(command->status == cs_interrupted)\r
-                       number_of_interrupted_tests++;\r
-               else if(command->status == cs_failed)\r
-                       number_of_failed_tests++;\r
-               else if(command->status == cs_successeded)\r
-                       number_of_successeded_tests++;\r
-       }\r
-\r
-       \r
-       if(number_of_tests)\r
-       {\r
-               asprintf(&p," Test(s): .........................................................................");\r
-                       \r
-               p[70] = '\0';\r
-               printf("%s", p);\r
-               free(p);        \r
-       \r
-               if(number_of_failed_tests > 0) \r
-                       printf(".. failed\n");\r
-               else if(number_of_interrupted_tests > 0) \r
-                       printf("interrupt\n");\r
-               else \r
-                       printf(".... ..ok\n"); \r
-\r
-               xbt_dynar_foreach(unit->commands, itc, command)\r
-               {\r
-                       printf("        %s: %s [%s]\n", \r
-                               command->status == cs_interrupted ? "INTR  " \r
-                               : command->status == cs_failed ? "FAILED" \r
-                               : command->status == cs_successeded ? "PASS  " \r
-                               : "UNKNWN",\r
-                               command->context->command_line, \r
-                               command->context->pos);\r
-                               \r
-                       if(detail_summary_flag)\r
-                               command_summarize(command);\r
-               }\r
-       \r
-               printf(" =====================================================================%s\n",\r
-               number_of_failed_tests ? "== FAILED": number_of_interrupted_tests ? "==== INTR" : "====== OK");\r
-               \r
-               printf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",\r
-               ((1-((double)number_of_failed_tests + (double)number_of_interrupted_tests)/(double)number_of_tests)*100.0),\r
-                number_of_tests, number_of_successeded_tests);\r
-               \r
-               if(number_of_failed_tests > 0)\r
-                       printf(", %d failed", number_of_failed_tests);\r
-               \r
-               if(number_of_interrupted_tests > 0)\r
-                       printf(", %d interrupted)", number_of_interrupted_tests);\r
-                       \r
-                printf(")\n\n");\r
-                               \r
-               total_of_tests = number_of_tests;\r
-               total_of_failed_tests = number_of_failed_tests;\r
-               total_of_interrupted_tests = number_of_interrupted_tests;\r
-               total_of_successeded_tests = number_of_successeded_tests;\r
-       }\r
-       \r
-       \r
-       \r
-       /* includes */\r
-       total_of_failed_units = total_of_interrupted_units = total_of_successeded_units = 0;\r
-       number_of_failed_units = number_of_successeded_units = number_of_interrupted_units = 0;\r
-       number_of_units = xbt_dynar_length(unit->includes);\r
-       \r
-       xbt_dynar_foreach(unit->includes, itu, include)\r
-       {\r
-               \r
-               number_of_interrupted_tests = number_of_failed_tests = number_of_successeded_tests = 0;\r
-               \r
-               number_of_tests = xbt_dynar_length(include->commands);\r
-\r
-               xbt_dynar_foreach(include->commands, itc, command)\r
-               {\r
-                       if(command->status == cs_interrupted)\r
-                               number_of_interrupted_tests++;\r
-                       else if(command->status == cs_failed)\r
-                               number_of_failed_tests++;\r
-                       else if(command->status == cs_successeded)\r
-                               number_of_successeded_tests++;  \r
-               }\r
-               \r
-               asprintf(&p," Unit: %s ............................................................................", include->description && strlen(include->description) < 60 ? include->description : include->fstream->name);\r
-                       \r
-               p[70] = '\0';\r
-               printf("%s", p);\r
-               free(p);        \r
-               \r
-               if(number_of_failed_tests > 0) \r
-               {\r
-                       total_of_failed_units++;\r
-                       printf(".. failed\n");\r
-               }\r
-               else if(number_of_interrupted_tests > 0) \r
-               {\r
-                       total_of_interrupted_units++;\r
-                       printf("interrupt\n");\r
-               }\r
-               else \r
-               {\r
-                       total_of_successeded_units++;\r
-                       printf(".... ..ok\n"); \r
-               }\r
-               \r
-               if(detail_summary_flag)\r
-               {               \r
-\r
-                       xbt_dynar_foreach(include->commands, itc, command)\r
-                       {\r
-                               printf("        %s: %s [%s]\n", \r
-                               command->status == cs_interrupted ? "INTR  " \r
-                               : command->status == cs_failed ? "FAILED" \r
-                               : command->status == cs_successeded ? "PASS  " \r
-                               : "UNKNWN",\r
-                               command->context->command_line, \r
-                               command->context->pos);\r
-                               \r
-                               command_summarize(command);\r
-                       }\r
-                       \r
-                                       \r
-               }\r
-               \r
-               printf(" =====================================================================%s\n",\r
-               number_of_failed_tests ? "== FAILED": number_of_interrupted_tests ? "==== INTR" : "====== OK");\r
-       \r
-               \r
-               printf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",\r
-               (number_of_tests ? (1-((double)number_of_failed_tests + (double)number_of_interrupted_tests)/(double)number_of_tests)*100.0 : 100.0),\r
-                number_of_tests, number_of_successeded_tests);\r
-               \r
-               if(number_of_failed_tests > 0)\r
-                       printf(", %d failed", number_of_failed_tests);\r
-               \r
-               if(number_of_interrupted_tests > 0)\r
-                       printf(", %d interrupted)", number_of_interrupted_tests);\r
-                       \r
-                printf(")\n\n");       \r
-                \r
-               \r
-               total_of_tests += number_of_tests;\r
-               total_of_failed_tests += number_of_failed_tests;\r
-               total_of_interrupted_tests += number_of_interrupted_tests;\r
-               total_of_successeded_tests += number_of_successeded_tests;\r
-       }\r
-       \r
-       /* suites */\r
-       total_of_units = number_of_units;\r
-       \r
-       total_of_failed_suites = total_of_successeded_suites = total_of_interrupted_suites = 0;\r
-       \r
-       total_of_suites = xbt_dynar_length(unit->suites);\r
-\r
-       xbt_dynar_foreach(unit->suites, its, suite)\r
-       {\r
-               print_title(suite->description);\r
-               \r
-               number_of_tests_of_suite = number_of_interrupted_tests_of_suite = number_of_failed_tests_of_suite = number_of_successeded_tests_of_suite = 0;\r
-               \r
-               number_of_interrupted_units = number_of_failed_units = number_of_successeded_units = 0;\r
-               \r
-               number_of_units = xbt_dynar_length(suite->includes);\r
-               \r
-               xbt_dynar_foreach(suite->includes, itu, include)\r
-               {\r
-                       number_of_interrupted_tests = number_of_failed_tests = number_of_successeded_tests = 0;\r
-                       \r
-                       number_of_tests = xbt_dynar_length(include->commands);\r
-                       \r
-                       \r
-                       xbt_dynar_foreach(include->commands, itc, command)\r
-                       {\r
-                               if(command->status == cs_interrupted)\r
-                                       number_of_interrupted_tests++;\r
-                               else if(command->status == cs_failed)\r
-                                       number_of_failed_tests++;\r
-                               else if(command->status == cs_successeded)\r
-                                       number_of_successeded_tests++;\r
-                       }\r
-                       \r
-                       asprintf(&p," Unit: %s ............................................................................", include->description && strlen(include->description) < 60 ? include->description : include->fstream->name);\r
-                       \r
-                       p[70] = '\0';\r
-                       printf("%s", p);\r
-                       free(p);        \r
-               \r
-                       if(number_of_failed_tests > 0) \r
-                       {\r
-                               number_of_failed_units++;\r
-                               printf(".. failed\n");\r
-                       }\r
-                       else if(number_of_interrupted_tests > 0) \r
-                       {\r
-                               number_of_interrupted_units++;\r
-                               printf("interrupt\n");\r
-                       }\r
-                       else \r
-                       {\r
-                               number_of_successeded_units++;\r
-                               printf(".... ..ok\n"); \r
-                       } \r
-                       \r
-                       number_of_interrupted_tests_of_suite += number_of_interrupted_tests;\r
-                       number_of_failed_tests_of_suite += number_of_failed_tests;\r
-                       number_of_successeded_tests_of_suite += number_of_successeded_tests;\r
-                       \r
-                       number_of_tests_of_suite += number_of_tests;\r
-                       \r
-                       total_of_tests += number_of_tests;\r
-                       total_of_failed_tests += number_of_failed_tests;\r
-                       total_of_interrupted_tests += number_of_interrupted_tests;\r
-                       total_of_successeded_tests += number_of_successeded_tests;\r
-                       \r
-                       if(detail_summary_flag)\r
-                       {\r
-\r
-                               xbt_dynar_foreach(include->commands, itc, command)\r
-                               {\r
-                                       printf("        %s: %s [%s]\n", \r
-                                       command->status == cs_interrupted ? "INTR  " \r
-                                       : command->status == cs_failed ? "FAILED" \r
-                                       : command->status == cs_successeded ? "PASS  " \r
-                                       : "UNKNWN",\r
-                                       command->context->command_line, \r
-                                       command->context->pos);\r
-                                       \r
-                                       command_summarize(command);\r
-                               }\r
-                               \r
-                               \r
-                       }\r
-                               \r
-               }\r
-               \r
-               printf(" =====================================================================%s\n",\r
-               number_of_failed_tests_of_suite ? "== FAILED": number_of_interrupted_tests_of_suite ? "==== INTR" : "====== OK");\r
-               \r
-               if(number_of_failed_tests_of_suite > 0)\r
-                       total_of_failed_suites++;\r
-               else if(number_of_interrupted_tests_of_suite)\r
-                       total_of_interrupted_suites++;\r
-               else\r
-                       total_of_successeded_suites++;\r
-                       \r
-               total_of_failed_units += number_of_failed_units;\r
-               total_of_interrupted_units += number_of_interrupted_units;\r
-               total_of_successeded_units += number_of_successeded_units;\r
-                       \r
-               total_of_units += number_of_units;\r
-               \r
-               printf("    Summary: Unit(s): %.0f%% ok (%d unit(s): %d ok",\r
-               (number_of_units ? (1-((double)number_of_failed_units + (double)number_of_interrupted_units)/(double)number_of_units)*100.0 : 100.0),\r
-                number_of_units, number_of_successeded_units);\r
-                \r
-               if(number_of_failed_units > 0)\r
-                       printf(", %d failed", number_of_failed_units);\r
-               \r
-               if(number_of_interrupted_units > 0)\r
-                       printf(", %d interrupted)", number_of_interrupted_units);\r
-                       \r
-               printf(")\n");  \r
-               \r
-               printf("             Test(s): %.0f%% ok (%d test(s): %d ok",\r
-               (number_of_tests_of_suite ? (1-((double)number_of_failed_tests_of_suite + (double)number_of_interrupted_tests_of_suite)/(double)number_of_tests_of_suite)*100.0 : 100.0),\r
-               number_of_tests_of_suite, number_of_successeded_tests_of_suite);\r
-                \r
-               if(number_of_failed_tests_of_suite > 0)\r
-                       printf(", %d failed", number_of_failed_tests_of_suite);\r
-               \r
-               if(number_of_interrupted_tests_of_suite > 0)\r
-                       printf(", %d interrupted)", number_of_interrupted_tests_of_suite);\r
-                       \r
-                printf(")\n\n");       \r
-       }\r
-       \r
-       printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",\r
-               (total_of_suites ? (1-((double)total_of_failed_suites + (double)total_of_interrupted_suites)/(double)total_of_suites)*100.0 : 100.0),\r
-                total_of_suites, total_of_successeded_suites);\r
-       \r
-       if(total_of_failed_suites > 0)\r
-                       printf(", %d failed", total_of_failed_suites);\r
-               \r
-       if(total_of_interrupted_suites > 0)\r
-               printf(", %d interrupted)", total_of_interrupted_suites);\r
-               \r
-       printf(")\n");  \r
-       \r
-       printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",\r
-               (total_of_units ? (1-((double)total_of_failed_units + (double)total_of_interrupted_units)/(double)total_of_units)*100.0 : 100.0),\r
-                total_of_units, total_of_successeded_units);\r
-       \r
-       if(total_of_failed_units > 0)\r
-                       printf(", %d failed", total_of_failed_units);\r
-               \r
-       if(total_of_interrupted_units > 0)\r
-               printf(", %d interrupted)", total_of_interrupted_units);\r
-               \r
-       printf(")\n");\r
-       \r
-       printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",\r
-               (total_of_tests ? (1-((double)total_of_failed_tests + (double)total_of_interrupted_tests)/(double)total_of_tests)*100.0 : 100.0),\r
-                total_of_tests, total_of_successeded_tests); \r
-                \r
-       if(total_of_failed_tests > 0)\r
-                       printf(", %d failed", total_of_failed_tests);\r
-               \r
-       if(total_of_interrupted_tests > 0)\r
-               printf(", %d interrupted)", total_of_interrupted_tests);\r
-               \r
-       printf(")\n\n");\r
-       \r
-       if(unit->interrupted)\r
-               unit->runner->total_of_interrupted_units++;\r
-       else if(total_of_failed_tests > 0)\r
-               unit->runner->total_of_failed_units++;\r
-       else\r
-               unit->runner->total_of_successeded_units++;\r
-       \r
-       unit->runner->total_of_tests += total_of_tests;\r
-       unit->runner->total_of_failed_tests += total_of_failed_tests;\r
-       unit->runner->total_of_successeded_tests += total_of_successeded_tests;\r
-       unit->runner->total_of_interrupted_tests += total_of_interrupted_tests;\r
-       \r
-       unit->runner->total_of_units += total_of_units + 1;\r
-       unit->runner->total_of_successeded_units += total_of_successeded_units;\r
-       unit->runner->total_of_failed_units += total_of_failed_units;\r
-       unit->runner->total_of_interrupted_units += total_of_interrupted_units;\r
-       \r
-       unit->runner->total_of_suites += total_of_suites;\r
-       unit->runner->total_of_successeded_suites += total_of_successeded_suites;\r
-       unit->runner->total_of_failed_suites += total_of_failed_suites;\r
-       unit->runner->total_of_interrupted_suites += total_of_interrupted_suites;\r
-       \r
-       return 0;\r
-}\r
-\r
-int\r
-unit_reset(unit_t unit)\r
-{\r
-       unit_t cur;\r
-       unsigned int i;\r
-\r
-       /* reset all the suites of the unit */\r
-       xbt_dynar_foreach(unit->suites, i, cur)\r
-       {\r
-               unit_reset(cur);\r
-       }\r
-\r
-\r
-       /* reset all the includes of the unit */\r
-       xbt_dynar_foreach(unit->includes, i, cur)\r
-       {\r
-               unit_reset(cur);\r
-       }\r
-\r
-       fseek(unit->fstream->stream,0L, SEEK_SET);\r
-       unit->parsed = 0;\r
-       unit->cmd_nb = 0;\r
-       unit->started_cmd_nb = 0;\r
-       unit->interrupted_cmd_nb = 0;\r
-       unit->failed_cmd_nb = 0;\r
-       unit->successeded_cmd_nb = 0;\r
-       unit->terminated_cmd_nb = 0;\r
-       unit->waiting_cmd_nb = 0;\r
-       unit->interrupted = 0;\r
-       unit->failed = 0;\r
-       unit->successeded = 0;\r
-       unit->parsed = 0;\r
-       unit->released = 0;\r
-       unit->is_running_suite = 0;\r
-       \r
-       if(unit->description)\r
-       {\r
-               free(unit->description);\r
-               unit->description = NULL;\r
-       }\r
+    else if (root->exit_code)
+      \rERROR3("Test unit `%s': NOK (<%s> %s)", root->fstream->name,
+              root->err_line, error_to_string(root->exit_code,
+                                              root->err_kind));
+    \r}
+  \r\r
+      /* if it's the last unit, release the runner */ \r
+      if ((root->runner->number_of_runned_units ==
+           root->runner->number_of_ended_units))
+    \r {
+    \r
+        /* if all the commands of the unit are successeded itc's a successeded unit */ \r
+        if (root->successeded_cmd_nb == root->cmd_nb
+            && !root->
+            exit_code /* case of only one cd : nb = successeded = 0) */ )
+      \rroot->successeded = 1;
+    \r\r
+        /* first release the mutex */ \r
+        xbt_os_mutex_release(root->mutex);
+    \r\r
+        /* release the runner */ \r
+        xbt_os_sem_release(units_sem);
+    \r}
+  \r
+  else
+    \rxbt_os_mutex_release(root->mutex);
+  \r\r
+      /* release the jobs semaphore, then the next waiting unit can start */ \r
+      xbt_os_sem_release(jobs_sem);
+  \r\rreturn NULL;
+\r\r}
+
+\r\r\runit_t \r
+unit_new(runner_t runner, unit_t root, unit_t owner, fstream_t fstream) \r
+{
+  \runit_t unit;
+  \r\runit = xbt_new0(s_unit_t, 1);
+  \r\r
+      /* instantiate the vector used to store all the commands of the unit */ \r
+      unit->commands =
+      xbt_dynar_new(sizeof(command_t), (void_f_pvoid_t) command_free);
+  \r\r
+      /* instantiate the vector used to store all the included units */ \r
+      unit->includes =
+      xbt_dynar_new(sizeof(unit_t), (void_f_pvoid_t) unit_free);
+  \r\r
+      /* instantiate the vector used to store all the included suites */ \r
+      unit->suites =
+      xbt_dynar_new(sizeof(unit_t), (void_f_pvoid_t) unit_free);
+  \r\r
+      /* the runner used to launch the tesh unit */ \r
+      unit->runner = runner;
+  \r\r
+      /* the file stream object to use to parse the tesh file */ \r
+      unit->fstream = fstream;
+  \r\rif (fstream)
+    \rfstream->unit = unit;
+  \r\r
+      /* if no root parameter specified assume that itc's the root of all the units */ \r
+      unit->root = root ? root : unit;
+  \r\r
+      /* the owner of the suite */ \r
+      unit->owner = owner;
+  \r\runit->thread = NULL;
+  \runit->started_cmd_nb = 0;
+  \runit->interrupted_cmd_nb = 0;
+  \runit->failed_cmd_nb = 0;
+  \runit->successeded_cmd_nb = 0;
+  \runit->terminated_cmd_nb = 0;
+  \runit->waiting_cmd_nb = 0;
+  \runit->interrupted = 0;
+  \runit->failed = 0;
+  \runit->successeded = 0;
+  \runit->parsed = 0;
+  \runit->released = 0;
+  \runit->owner = owner;
+  \runit->is_running_suite = 0;
+  \runit->description = NULL;
+  \runit->sem = NULL;
+  \runit->exit_code = 0;
+  \runit->err_kind = 0;
+  \runit->err_line = NULL;
+  \runit->filepos = NULL;
+  \r\r\r\rreturn unit;
+\r}
+
+\r\rvoid \r
+unit_set_error(unit_t unit, int errcode, int kind, const char *line) \r
+{
+  \rif (!unit->exit_code)
+    \r {
+    \runit->exit_code = errcode;
+    \runit->err_kind = kind;
+    \runit->err_line = strdup(line);
+    \r\rif (unit->root && !unit->root->exit_code)
+      \r {
+      \runit->root->exit_code = errcode;
+      \runit->root->err_kind = kind;
+      \runit->root->err_line = strdup(line);
+      \r}
+    \r\rif (!exit_code)
+      \r {
+      \r\rexit_code = errcode;
+      \rerr_kind = kind;
+      \rerr_line = strdup(line);
+      \r}
+    \r}
+\r\r}
+
+\r\rint \r unit_free(unit_t * ptr) \r
+{
+  \rif (!(*ptr))
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\rif ((*ptr)->commands)
+    \rxbt_dynar_free(&((*ptr)->commands));
+  \r\rif ((*ptr)->includes)
+    \rxbt_dynar_free(&((*ptr)->includes));
+  \r\rif ((*ptr)->suites)
+    \rxbt_dynar_free(&((*ptr)->suites));
+  \r\r
+      /* if the unit is interrupted during its run, the semaphore is NULL */ \r
+      if ((*ptr)->sem)
+    \rxbt_os_sem_destroy((*ptr)->sem);
+  \r\rif ((*ptr)->description)
+    \rfree((*ptr)->description);
+  \r\rif ((*ptr)->err_line)
+    \rfree((*ptr)->err_line);
+  \r\rif ((*ptr)->filepos)
+    \rfree((*ptr)->filepos);
+  \r\rfree(*ptr);
+  \r*ptr = NULL;
+  \r\rreturn 0;
+\r}
+
+\r\rint \r unit_run(unit_t unit, xbt_os_mutex_t mutex) \r
+{
+  \r
+      /* check the parameters */ \r
+      if (!(unit) || !mutex)
+    \r {
+    \rerrno = EINVAL;
+    \rxbt_os_sem_release(jobs_sem);
+    \rreturn -1;
+    \r\r}
+  \r\rif (!interrupted)
+    \r {
+    \runit->mutex = mutex;
+    \r\runit->sem = xbt_os_sem_init(0);
+    \r\r
+        /* start the unit */ \r
+        unit->thread = xbt_os_thread_create("", unit_start, unit);
+    \r}
+  \r
+  else
+    \r {
+    \r
+        /* the unit is interrupted by the runner before its starting \r
+         * in this case the unit semaphore is NULL take care of that\r
+         * in the function unit_free()\r
+         */ \r
+        unit->interrupted = 1;
+    \rxbt_os_sem_release(jobs_sem);
+    \r}
+  \r\rreturn 0;
+\r\r}
+
+\r\rint \r unit_interrupt(unit_t unit) \r
+{
+  \r
+      /* check the parameter */ \r
+      if (!(unit))
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\r
+      /* if the unit is already interrupted, signal the error */ \r
+      if (unit->interrupted)
+    \r {
+    \rerrno = EALREADY;
+    \rreturn -1;
+    \r}
+  \r\r
+      /* interrupt the run of the specified unit */ \r
+      unit->interrupted = 1;
+  \rxbt_os_sem_release(unit->sem);
+  \r\rreturn 0;
+\r}
+
+\r\r
+/* just print the title of the root unit or a suite (if any) */ \r
+static void \r print_title(const char *description) \r
+{
+  \rregister int i;
+  \rchar title[80];
+  \rsize_t len = strlen(description);
+  \r\rtitle[0] = ' ';
+  \r\rfor (i = 1; i < 79; i++)
+    \rtitle[i] = '=';
+  \r\rtitle[i++] = '\n';
+  \rtitle[79] = '\0';
+  \r\rsprintf(title + 40 - (len + 4) / 2, "[ %s ]", description);
+  \rtitle[40 + (len + 5) / 2] = '=';
+  \r\rprintf("\n%s\n", title);
+\r}
+
+\r\rint \r unit_summuarize(unit_t unit) \r
+{
+  \rcommand_t command;
+  \runsigned int itc, itu, its;
+  \runit_t include;
+  \runit_t suite;
+  \rchar *p;
+  \rchar title[PATH_MAX + 1] = { 0 };
+  \r\rint number_of_tests = 0;    /* number of tests of a unit contained by this unit                                     */
+  \rint number_of_failed_tests = 0;      /* number of failed test of a unit contained by this unit                       */
+  \rint number_of_successeded_tests = 0; /* number of successeded tests of a unit contained by this unit         */
+  \rint number_of_interrupted_tests = 0; /* number of interrupted tests of a unit contained by this unit         */
+  \r\rint number_of_tests_of_suite = 0;   /* number of tests of a suite contained by this unit                            */
+  \rint number_of_interrupted_tests_of_suite = 0;        /* number of interrupted tests of a suite contained by this unit        */
+  \rint number_of_failed_tests_of_suite = 0;     /* number of failed tests of a suite contained by this unit                                     */
+  \rint number_of_successeded_tests_of_suite = 0;        /* number of successeded tests of a suite contained by this                     */
+  \r\rint number_of_units = 0;    /* number of units contained by a suite                                                         */
+  \rint number_of_failed_units = 0;      /* number of failed units contained by a suite                                          */
+  \rint number_of_successeded_units = 0; /* number of successeded units contained by a suite                                     */
+  \rint number_of_interrupted_units = 0; /* number of interrupted units contained by a suite                                     */
+  \r\rint total_of_tests = 0;     /* total of the tests contained by this unit                                            */
+  \rint total_of_failed_tests = 0;       /* total of failed tests contained by this unit                                         */
+  \rint total_of_successeded_tests = 0;  /* total of successeded tests contained by this unit                            */
+  \rint total_of_interrupted_tests = 0;  /* total of interrupted tests contained by this unit                            */
+  \r\rint total_of_units = 0;     /* total of units contained by this unit                                                        */
+  \rint total_of_failed_units = 0;       /* total of failed units contained by this unit                                         */
+  \rint total_of_successeded_units = 0;  /* total of successeded units contained by this unit                            */
+  \rint total_of_interrupted_units = 0;  /* total of interrutped units contained by this unit                            */
+  \r\rint total_of_suites = 0;    /* total of suites contained by this unit                                                       */
+  \rint total_of_failed_suites = 0;      /* total of failed suites contained by this unit                                        */
+  \rint total_of_successeded_suites = 0; /* total of successeded suites contained by this unit                           */
+  \rint total_of_interrupted_suites = 0; /* total of interrupted suites contained by this unit                           */
+  \r\r
+      /* check the parameter */ \r
+      if (!(unit))
+    \r {
+    \rerrno = EINVAL;
+    \rreturn -1;
+    \r}
+  \r\rif ((unit->description) && strlen(unit->description) < 76)
+    \rstrcpy(title, unit->description);
+  \r
+  else
+    \rsprintf(title, "file : %s", unit->fstream->name);
+  \r\rif (unit->interrupted)
+    \r {
+    \rif (strlen(title) + strlen(" (interrupted)") < 76)
+      \rstrcat(title, " (interrupted)");
+    \r
+    else
+      \r {
+      \rmemset(title, 0, PATH_MAX + 1);
+      \rsprintf(title, "file : %s", unit->fstream->name);
+      \rstrcat(title, " (interrupted)");
+      \r\r}
+    \r}
+  \r\rprint_title(title);
+  \r\rnumber_of_tests = xbt_dynar_length(unit->commands);
+  \r\r
+      /* tests */ \r
+      xbt_dynar_foreach(unit->commands, itc, command) \r {
+    \rif (command->status == cs_interrupted)
+      \rnumber_of_interrupted_tests++;
+    \r
+    else if (command->status == cs_failed)
+      \rnumber_of_failed_tests++;
+    \r
+    else if (command->status == cs_successeded)
+      \rnumber_of_successeded_tests++;
+  \r}
+  \r\r\rif (number_of_tests)
+    \r {
+    \rasprintf(&p,
+              " Test(s): .........................................................................");
+    \r\rp[70] = '\0';
+    \rprintf("%s", p);
+    \rfree(p);
+    \r\rif (number_of_failed_tests > 0)
+      \rprintf(".. failed\n");
+    \r
+    else if (number_of_interrupted_tests > 0)
+      \rprintf("interrupt\n");
+    \r
+    else
+      \rprintf(".... ..ok\n");
+    \r\rxbt_dynar_foreach(unit->commands, itc, command) \r {
+      \rprintf("        %s: %s [%s]\n",
+              \rcommand->status ==
+              cs_interrupted ? "INTR  " \r : command->status ==
+              cs_failed ? "FAILED" \r : command->status ==
+              cs_successeded ? "PASS  " \r : "UNKNWN",
+              \rcommand->context->command_line, \rcommand->context->pos);
+      \r\rif (detail_summary_flag)
+        \rcommand_summarize(command);
+    \r}
+    \r\rprintf
+        (" =====================================================================%s\n",
+         \rnumber_of_failed_tests ? "== FAILED" :
+         number_of_interrupted_tests ? "==== INTR" : "====== OK");
+    \r\rprintf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",
+             \r((1 -
+                ((double) number_of_failed_tests +
+                 (double) number_of_interrupted_tests) /
+                (double) number_of_tests) * 100.0), \rnumber_of_tests,
+             number_of_successeded_tests);
+    \r\rif (number_of_failed_tests > 0)
+      \rprintf(", %d failed", number_of_failed_tests);
+    \r\rif (number_of_interrupted_tests > 0)
+      \rprintf(", %d interrupted)", number_of_interrupted_tests);
+    \r\rprintf(")\n\n");
+    \r\rtotal_of_tests = number_of_tests;
+    \rtotal_of_failed_tests = number_of_failed_tests;
+    \rtotal_of_interrupted_tests = number_of_interrupted_tests;
+    \rtotal_of_successeded_tests = number_of_successeded_tests;
+    \r}
+  \r\r\r\r
+      /* includes */ \r
+      total_of_failed_units = total_of_interrupted_units =
+      total_of_successeded_units = 0;
+  \rnumber_of_failed_units = number_of_successeded_units =
+      number_of_interrupted_units = 0;
+  \rnumber_of_units = xbt_dynar_length(unit->includes);
+  \r\rxbt_dynar_foreach(unit->includes, itu, include) \r {
+    \r\rnumber_of_interrupted_tests = number_of_failed_tests =
+        number_of_successeded_tests = 0;
+    \r\rnumber_of_tests = xbt_dynar_length(include->commands);
+    \r\rxbt_dynar_foreach(include->commands, itc, command) \r {
+      \rif (command->status == cs_interrupted)
+        \rnumber_of_interrupted_tests++;
+      \r
+      else if (command->status == cs_failed)
+        \rnumber_of_failed_tests++;
+      \r
+      else if (command->status == cs_successeded)
+        \rnumber_of_successeded_tests++;
+    \r}
+    \r\rasprintf(&p,
+               " Unit: %s ............................................................................",
+               include->description
+               && strlen(include->description) <
+               60 ? include->description : include->fstream->name);
+    \r\rp[70] = '\0';
+    \rprintf("%s", p);
+    \rfree(p);
+    \r\rif (number_of_failed_tests > 0)
+      \r {
+      \rtotal_of_failed_units++;
+      \rprintf(".. failed\n");
+      \r}
+    \r
+    else if (number_of_interrupted_tests > 0)
+      \r {
+      \rtotal_of_interrupted_units++;
+      \rprintf("interrupt\n");
+      \r}
+    \r
+    else
+      \r {
+      \rtotal_of_successeded_units++;
+      \rprintf(".... ..ok\n");
+      \r}
+    \r\rif (detail_summary_flag)
+      \r {
+      \r\rxbt_dynar_foreach(include->commands, itc, command) \r {
+        \rprintf("        %s: %s [%s]\n",
+                \rcommand->status ==
+                cs_interrupted ? "INTR  " \r : command->status ==
+                cs_failed ? "FAILED" \r : command->status ==
+                cs_successeded ? "PASS  " \r : "UNKNWN",
+                \rcommand->context->command_line, \rcommand->context->pos);
+        \r\rcommand_summarize(command);
+      \r}
+      \r\r\r}
+    \r\rprintf
+        (" =====================================================================%s\n",
+         \rnumber_of_failed_tests ? "== FAILED" :
+         number_of_interrupted_tests ? "==== INTR" : "====== OK");
+    \r\r\rprintf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",
+              \r(number_of_tests
+                ? (1 -
+                   ((double) number_of_failed_tests +
+                    (double) number_of_interrupted_tests) /
+                   (double) number_of_tests) * 100.0 : 100.0),
+              \rnumber_of_tests, number_of_successeded_tests);
+    \r\rif (number_of_failed_tests > 0)
+      \rprintf(", %d failed", number_of_failed_tests);
+    \r\rif (number_of_interrupted_tests > 0)
+      \rprintf(", %d interrupted)", number_of_interrupted_tests);
+    \r\rprintf(")\n\n");
+    \r\r\rtotal_of_tests += number_of_tests;
+    \rtotal_of_failed_tests += number_of_failed_tests;
+    \rtotal_of_interrupted_tests += number_of_interrupted_tests;
+    \rtotal_of_successeded_tests += number_of_successeded_tests;
+  \r}
+  \r\r
+      /* suites */ \r
+      total_of_units = number_of_units;
+  \r\rtotal_of_failed_suites = total_of_successeded_suites =
+      total_of_interrupted_suites = 0;
+  \r\rtotal_of_suites = xbt_dynar_length(unit->suites);
+  \r\rxbt_dynar_foreach(unit->suites, its, suite) \r {
+    \rprint_title(suite->description);
+    \r\rnumber_of_tests_of_suite = number_of_interrupted_tests_of_suite =
+        number_of_failed_tests_of_suite =
+        number_of_successeded_tests_of_suite = 0;
+    \r\rnumber_of_interrupted_units = number_of_failed_units =
+        number_of_successeded_units = 0;
+    \r\rnumber_of_units = xbt_dynar_length(suite->includes);
+    \r\rxbt_dynar_foreach(suite->includes, itu, include) \r {
+      \rnumber_of_interrupted_tests = number_of_failed_tests =
+          number_of_successeded_tests = 0;
+      \r\rnumber_of_tests = xbt_dynar_length(include->commands);
+      \r\r\rxbt_dynar_foreach(include->commands, itc, command) \r {
+        \rif (command->status == cs_interrupted)
+          \rnumber_of_interrupted_tests++;
+        \r
+        else if (command->status == cs_failed)
+          \rnumber_of_failed_tests++;
+        \r
+        else if (command->status == cs_successeded)
+          \rnumber_of_successeded_tests++;
+      \r}
+      \r\rasprintf(&p,
+                 " Unit: %s ............................................................................",
+                 include->description
+                 && strlen(include->description) <
+                 60 ? include->description : include->fstream->name);
+      \r\rp[70] = '\0';
+      \rprintf("%s", p);
+      \rfree(p);
+      \r\rif (number_of_failed_tests > 0)
+        \r {
+        \rnumber_of_failed_units++;
+        \rprintf(".. failed\n");
+        \r}
+      \r
+      else if (number_of_interrupted_tests > 0)
+        \r {
+        \rnumber_of_interrupted_units++;
+        \rprintf("interrupt\n");
+        \r}
+      \r
+      else
+        \r {
+        \rnumber_of_successeded_units++;
+        \rprintf(".... ..ok\n");
+        \r}
+      \r\rnumber_of_interrupted_tests_of_suite +=
+          number_of_interrupted_tests;
+      \rnumber_of_failed_tests_of_suite += number_of_failed_tests;
+      \rnumber_of_successeded_tests_of_suite += number_of_successeded_tests;
+      \r\rnumber_of_tests_of_suite += number_of_tests;
+      \r\rtotal_of_tests += number_of_tests;
+      \rtotal_of_failed_tests += number_of_failed_tests;
+      \rtotal_of_interrupted_tests += number_of_interrupted_tests;
+      \rtotal_of_successeded_tests += number_of_successeded_tests;
+      \r\rif (detail_summary_flag)
+        \r {
+        \r\rxbt_dynar_foreach(include->commands, itc, command) \r {
+          \rprintf("        %s: %s [%s]\n",
+                  \rcommand->status ==
+                  cs_interrupted ? "INTR  " \r : command->status ==
+                  cs_failed ? "FAILED" \r : command->status ==
+                  cs_successeded ? "PASS  " \r : "UNKNWN",
+                  \rcommand->context->command_line, \rcommand->context->pos);
+          \r\rcommand_summarize(command);
+        \r}
+        \r\r\r}
+    \r\r}
+    \r\rprintf
+        (" =====================================================================%s\n",
+         \rnumber_of_failed_tests_of_suite ? "== FAILED" :
+         number_of_interrupted_tests_of_suite ? "==== INTR" : "====== OK");
+    \r\rif (number_of_failed_tests_of_suite > 0)
+      \rtotal_of_failed_suites++;
+    \r
+    else if (number_of_interrupted_tests_of_suite)
+      \rtotal_of_interrupted_suites++;
+    \r
+    else
+      \rtotal_of_successeded_suites++;
+    \r\rtotal_of_failed_units += number_of_failed_units;
+    \rtotal_of_interrupted_units += number_of_interrupted_units;
+    \rtotal_of_successeded_units += number_of_successeded_units;
+    \r\rtotal_of_units += number_of_units;
+    \r\rprintf("    Summary: Unit(s): %.0f%% ok (%d unit(s): %d ok", \r
+             (number_of_units
+              ? (1 -
+                 ((double) number_of_failed_units +
+                  (double) number_of_interrupted_units) /
+                 (double) number_of_units) * 100.0 : 100.0),
+             \rnumber_of_units, number_of_successeded_units);
+    \r\rif (number_of_failed_units > 0)
+      \rprintf(", %d failed", number_of_failed_units);
+    \r\rif (number_of_interrupted_units > 0)
+      \rprintf(", %d interrupted)", number_of_interrupted_units);
+    \r\rprintf(")\n");
+    \r\rprintf("             Test(s): %.0f%% ok (%d test(s): %d ok", \r
+             (number_of_tests_of_suite
+              ? (1 -
+                 ((double) number_of_failed_tests_of_suite +
+                  (double) number_of_interrupted_tests_of_suite) /
+                 (double) number_of_tests_of_suite) * 100.0 : 100.0),
+             \rnumber_of_tests_of_suite,
+             number_of_successeded_tests_of_suite);
+    \r\rif (number_of_failed_tests_of_suite > 0)
+      \rprintf(", %d failed", number_of_failed_tests_of_suite);
+    \r\rif (number_of_interrupted_tests_of_suite > 0)
+      \rprintf(", %d interrupted)", number_of_interrupted_tests_of_suite);
+    \r\rprintf(")\n\n");
+  \r}
+  \r\rprintf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok", \r
+           (total_of_suites
+            ? (1 -
+               ((double) total_of_failed_suites +
+                (double) total_of_interrupted_suites) /
+               (double) total_of_suites) * 100.0 : 100.0),
+           \rtotal_of_suites, total_of_successeded_suites);
+  \r\rif (total_of_failed_suites > 0)
+    \rprintf(", %d failed", total_of_failed_suites);
+  \r\rif (total_of_interrupted_suites > 0)
+    \rprintf(", %d interrupted)", total_of_interrupted_suites);
+  \r\rprintf(")\n");
+  \r\rprintf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok", \r
+           (total_of_units
+            ? (1 -
+               ((double) total_of_failed_units +
+                (double) total_of_interrupted_units) /
+               (double) total_of_units) * 100.0 : 100.0), \rtotal_of_units,
+           total_of_successeded_units);
+  \r\rif (total_of_failed_units > 0)
+    \rprintf(", %d failed", total_of_failed_units);
+  \r\rif (total_of_interrupted_units > 0)
+    \rprintf(", %d interrupted)", total_of_interrupted_units);
+  \r\rprintf(")\n");
+  \r\rprintf("         Test(s):  %.0f%% ok (%d test(s): %d ok", \r
+           (total_of_tests
+            ? (1 -
+               ((double) total_of_failed_tests +
+                (double) total_of_interrupted_tests) /
+               (double) total_of_tests) * 100.0 : 100.0), \rtotal_of_tests,
+           total_of_successeded_tests);
+  \r\rif (total_of_failed_tests > 0)
+    \rprintf(", %d failed", total_of_failed_tests);
+  \r\rif (total_of_interrupted_tests > 0)
+    \rprintf(", %d interrupted)", total_of_interrupted_tests);
+  \r\rprintf(")\n\n");
+  \r\rif (unit->interrupted)
+    \runit->runner->total_of_interrupted_units++;
+  \r
+  else if (total_of_failed_tests > 0)
+    \runit->runner->total_of_failed_units++;
+  \r
+  else
+    \runit->runner->total_of_successeded_units++;
+  \r\runit->runner->total_of_tests += total_of_tests;
+  \runit->runner->total_of_failed_tests += total_of_failed_tests;
+  \runit->runner->total_of_successeded_tests += total_of_successeded_tests;
+  \runit->runner->total_of_interrupted_tests += total_of_interrupted_tests;
+  \r\runit->runner->total_of_units += total_of_units + 1;
+  \runit->runner->total_of_successeded_units += total_of_successeded_units;
+  \runit->runner->total_of_failed_units += total_of_failed_units;
+  \runit->runner->total_of_interrupted_units += total_of_interrupted_units;
+  \r\runit->runner->total_of_suites += total_of_suites;
+  \runit->runner->total_of_successeded_suites +=
+      total_of_successeded_suites;
+  \runit->runner->total_of_failed_suites += total_of_failed_suites;
+  \runit->runner->total_of_interrupted_suites +=
+      total_of_interrupted_suites;
+  \r\rreturn 0;
+\r}
+
+\r\rint \r unit_reset(unit_t unit) \r
+{
+  \runit_t cur;
+  \runsigned int i;
+  \r\r
+      /* reset all the suites of the unit */ \r
+      xbt_dynar_foreach(unit->suites, i, cur) \r {
+    \runit_reset(cur);
+  \r\r\r\r
+      /* reset all the includes of the unit */ \r
+      xbt_dynar_foreach(unit->includes, i, cur) \r {
+    \runit_reset(cur);
+  \r\r\rfseek(unit->fstream->stream, 0L, SEEK_SET);
+  \runit->parsed = 0;
+  \runit->cmd_nb = 0;
+  \runit->started_cmd_nb = 0;
+  \runit->interrupted_cmd_nb = 0;
+  \runit->failed_cmd_nb = 0;
+  \runit->successeded_cmd_nb = 0;
+  \runit->terminated_cmd_nb = 0;
+  \runit->waiting_cmd_nb = 0;
+  \runit->interrupted = 0;
+  \runit->failed = 0;
+  \runit->successeded = 0;
+  \runit->parsed = 0;
+  \runit->released = 0;
+  \runit->is_running_suite = 0;
+  \r\rif (unit->description)
+    \r {
+    \rfree(unit->description);
+    \runit->description = NULL;
+    \r}
+  \r\runit->exit_code = 0;
+  \r\rreturn 0;
+\r}
+
 \r
-       unit->exit_code = 0;\r
-       \r
-       return 0;\r
-}\r