Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last version of tesh
authorcherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Mon, 7 Apr 2008 13:26:23 +0000 (13:26 +0000)
committercherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Mon, 7 Apr 2008 13:26:23 +0000 (13:26 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@5326 48e7efb5-ca39-0410-a469-dd3cf9ba447f

31 files changed:
tools/tesh2/include/com.h
tools/tesh2/include/def.h
tools/tesh2/include/directories.h
tools/tesh2/include/directory.h
tools/tesh2/include/error.h
tools/tesh2/include/fstream.h
tools/tesh2/include/global.h
tools/tesh2/include/types.h
tools/tesh2/include/unit.h
tools/tesh2/include/variable.h
tools/tesh2/include/variables.h
tools/tesh2/src/allocator.c
tools/tesh2/src/command.c
tools/tesh2/src/dictionary.c
tools/tesh2/src/directories.c
tools/tesh2/src/directory.c
tools/tesh2/src/error.c
tools/tesh2/src/excludes.c
tools/tesh2/src/fstream.c
tools/tesh2/src/fstreams.c
tools/tesh2/src/htable.c
tools/tesh2/src/lstrings.c
tools/tesh2/src/main.c
tools/tesh2/src/reader.c
tools/tesh2/src/runner.c
tools/tesh2/src/unit.c
tools/tesh2/src/units.c
tools/tesh2/src/variable.c
tools/tesh2/src/variables.c
tools/tesh2/src/vector.c
tools/tesh2/src/writer.c

index 80ff496..8519722 100644 (file)
@@ -49,13 +49,14 @@ units_sem;
 
 /* the dlist of tesh include directories */
 extern vector_t 
-includes;
+include_dirs;
 
 extern int
 interrupted;
 
-extern int
+/*extern int
 exit_code;
+*/
 
 extern int
 want_silent;
@@ -72,6 +73,16 @@ dont_want_display_directory;
 extern directory_t
 root_directory;
 
+extern int
+want_detail_summary;
+
+extern int
+exit_code;
+
+extern pid_t
+pid;
+
+
 
 #ifdef __cplusplus
 }
index d5b45aa..273c02f 100644 (file)
@@ -47,16 +47,17 @@ extern "C" {
 #endif
 
 
-#define INDEFINITE                                     ((int)-1)
-#define INDEFINITE_SIGNAL                      NULL
+#define INDEFINITE                                             ((int)-1)
+#define INDEFINITE_SIGNAL                              NULL
 
-#define DEFAULT_FSTREAMS_CAPACITY      ((int)128)
-#define DEFAULT_INCLUDES_CAPACITY      DEFAULT_FSTREAMS_CAPACITY
-#define DEFAULT_UNITS_CAPACITY         ((int)64)
-#define DEFAULT_COMMANDS_CAPACITY      ((int)1024)
-#define DEFAULT_SUITES_CAPACITY                ((int)128)
+#define DEFAULT_FSTREAMS_CAPACITY              ((int)128)
+#define DEFAULT_INCLUDE_DIRS_CAPACITY  DEFAULT_FSTREAMS_CAPACITY
+#define DEFAULT_UNITS_CAPACITY                 ((int)64)
+#define DEFAULT_INCLUDES                               ((int)8)
+#define DEFAULT_COMMANDS_CAPACITY              ((int)512)
+#define DEFAULT_SUITES_CAPACITY                        ((int)32)
 
-#define                                                                MAX_SUFFIX ((unsigned int)9)
+#define                                                                        MAX_SUFFIX ((unsigned int)9)
 
 #ifdef __cplusplus
 }
index d000f77..223029f 100644 (file)
@@ -23,17 +23,15 @@ directories_load(directories_t directories, fstreams_t fstreams, lstrings_t suff
 int
 directories_free(void** directoriesptr);
 
-directory_t
-directories_get_back(directories_t directories);
+/*directory_t
+directories_get_back(directories_t directories);*/
 
-directory_t
-directories_search_fstream_directory(directories_t directories, const char* name);
 
 int
 directories_get_size(directories_t directories);
 
 int
-directories_has_directories_to_load(directories_t directories);
+directories_is_empty(directories_t directories);
 
 #ifdef __cplusplus
 }
index 42fd920..ff0e057 100644 (file)
@@ -8,7 +8,7 @@ extern "C" {
 #endif
 
 directory_t
-directory_new(const char* name, int load);
+directory_new(const char* name);
 
 int
 directory_open(directory_t directory);
index 6b0eb84..8dba6d7 100644 (file)
@@ -8,39 +8,43 @@ extern "C" {
 
 #include <errno.h>
 
-#define EREAD                          ((int)2000)     /* a read pipe operation failed                                                                                         */
-#define EREADPIPE                      ((int)2001)     /* the pipe used to read from the stdout of the command is broken                       */
-#define ETIMEOUT                       ((int)2002)     /* the command is timeouted                                                                                                     */
-#define EWRITE                         ((int)2003)     /* a write operation failed                                                                                                     */
-#define EWRITEPIPE                     ((int)2004)     /* the pipe used to write to the stdin of the command is broken                         */
-#define EEXEC                          ((int)2005)     /* can't execute the command                                                                                            */
-#define EWAIT                          ((int)2006)     /* the wait function failed                                                                                                     */
-#define ECMDNOTFOUND           ((int)2007)     /* the command is not found                                                                                                     */
-#define EEXITCODENOTMATCH      ((int)2008)     /* the exit codes don't match                                                                                           */
-#define EOUTPUTNOTMATCH                ((int)2009)     /* the outputs don't match                                                                                                      */
-#define ESIGNOTMATCH           ((int)2010)     /* the signals don't match                                                                                                      */
-#define EUNEXPECTEDSIG         ((int)2011)     /* unexpected signal caught                                                                                                     */
-#define ESIGNOTRECEIPT         ((int)2012)     /* the expected signal is not receipt                                                                           */
-#define EFILENOTFOUND          ((int)2013)     /* the specified tesh file is not found                                                                         */
-#define EGETCWD                                ((int)2014)     /* this is a system error : the getcwd() function failed (impossible)           */
-#define EDIRNOTFOUND           ((int)2015)     /* the specified directory is not found                                                                         */
-#define ECHDIR                         ((int)2016)     /* this is a system error : the chdir() function failed (impossible)            */
-#define EPROCESSCMDLINE                ((int)2017)     /* this is an internal error : the process_command_line() function failed       */
-#define EARGNOTSPEC                    ((int)2018)     /* a none optional argument is not specified in the command line                        */
-#define ENOTPOSITIVENUM                ((int)2019)     /* the argument of the option is not strictly positive                                          */
-#define ESYNTAX                                ((int)2020)     /* syntax error                                                                                                                         */
-#define EINVALIDTIMEOUT                ((int)2021)     /* the timeout value specified by the metacommand is invalid                            */
-#define EINVALIDEXITCODE       ((int)2022)     /* the expected exit code value specified by the metacommand is invalid         */
-#define ESIGNOTSUPP                    ((int)2023)     /* the signal specified by the metacommand is not supported                                     */
-#define ELEADTIME                      ((int)2024)     /* global timeout                                                                                                                       */
-#define EREADMENOTFOUND                ((int)2025)     /* unable to locate the README.txt file                                                                         */
-#define EINCLUDENOTFOUND       ((int)2026)     /* the include file specified by a metacommand is not found                                     */
-#define ESUFFIXTOOLONG         ((int)2027)     /* the suffix is too long                                                                                                       */
-#define EFILENOTINSPECDIR      ((int)2028) /* file not found in the specified directories                                                              */
-#define EFILENOTINCURDIR       ((int)2029) /* file not found in the current directory                                                                  */
+#define EREAD                          ((int)100)      /* a read pipe operation failed                                                                                         */
+#define EREADPIPE                      ((int)101)      /* the pipe used to read from the stdout of the command is broken                       */
+#define ETIMEOUT                       ((int)102)      /* the command is timeouted                                                                                                     */
+#define EWRITE                         ((int)103)      /* a write operation failed                                                                                                     */
+#define EWRITEPIPE                     ((int)104)      /* the pipe used to write to the stdin of the command is broken                         */
+#define EEXEC                          ((int)105)      /* can't execute the command                                                                                            */
+#define EWAIT                          ((int)106)      /* the wait function failed                                                                                                     */
+#define ECMDNOTFOUND           ((int)107)      /* the command is not found                                                                                                     */
+#define EEXITCODENOTMATCH      ((int)108)      /* the exit codes don't match                                                                                           */
+#define EOUTPUTNOTMATCH                ((int)109)      /* the outputs don't match                                                                                                      */
+#define ESIGNOTMATCH           ((int)110)      /* the signals don't match                                                                                                      */
+#define EUNEXPECTEDSIG         ((int)111)      /* unexpected signal caught                                                                                                     */
+#define ESIGNOTRECEIPT         ((int)112)      /* the expected signal is not receipt                                                                           */
+#define EFILENOTFOUND          ((int)113)      /* the specified tesh file is not found                                                                         */
+#define EGETCWD                                ((int)114)      /* this is a system error : the getcwd() function failed (impossible)           */
+#define EDIRNOTFOUND           ((int)115)      /* the specified directory is not found                                                                         */
+#define ECHDIR                         ((int)116)      /* this is a system error : the chdir() function failed (impossible)            */
+#define EPROCCMDLINE           ((int)117)      /* this is an internal error : the process_command_line() function failed       */
+#define ENOARG                         ((int)118)      /* a none optional argument is not specified in the command line                        */
+#define ENOTPOSITIVENUM                ((int)119)      /* the argument of the option is not strictly positive                                          */
+#define ESYNTAX                                ((int)120)      /* syntax error                                                                                                                         */
+#define EINVALIDTIMEOUT                ((int)121)      /* the timeout value specified by the metacommand is invalid                            */
+#define EINVALIDEXITCODE       ((int)122)      /* the expected exit code value specified by the metacommand is invalid         */
+#define ESIGNOTSUPP                    ((int)123)      /* the signal specified by the metacommand is not supported                                     */
+#define ELEADTIME                      ((int)124)      /* global timeout                                                                                                                       */
+#define EREADMENOTFOUND                ((int)125)      /* unable to locate the README.txt file                                                                         */
+#define EINCLUDENOTFOUND       ((int)126)      /* the include file specified by a metacommand is not found                                     */
+#define ESUFFIXTOOLONG         ((int)127)      /* the suffix is too long                                                                                                       */
+#define EFILENOTINSPECDIR      ((int)128) /* file not found in the specified directories                                                               */
+#define EFILENOTINCURDIR       ((int)129) /* file not found in the current directory                                                                   */
+
+
+const char*
+error_get_at(int pos, int* code);
 
 const char*
-error_to_string(int error);
+error_to_string(int errcode);
 
 #ifdef __cplusplus
 }
index 689d1cc..4c1c0fc 100644 (file)
@@ -20,7 +20,7 @@ int
 fstream_free(void** fstreamptr);
 
 void
-fstream_parse(fstream_t fstream, unit_t unit);
+fstream_parse(fstream_t fstream, unit_t unit, xbt_os_mutex_t mutex);
 
 #ifdef __cplusplus
 }
index aca4c0b..5d1416d 100644 (file)
@@ -47,7 +47,7 @@ units_sem;
 
 /* the dlist of tesh include directories */
 extern vector_t 
-includes;
+include_dirs;
 
 extern int
 interrupted;
index 6c4cff8..86d9082 100644 (file)
@@ -71,6 +71,10 @@ struct s_writer;
 struct s_reader;
 struct s_timer;
 struct s_context;
+struct s_command;
+struct s_variable;
+struct s_variables;
+
 
 
 /* 
@@ -111,11 +115,19 @@ typedef enum e_command_status_raison
        csr_pipe_function_failed                = 16            /* the function pipe() or CreatePipe() fails                                            */
 }cs_reason_t;
 
+typedef struct s_variable
+{
+       char* name;
+       char* val;
+       int used:1;
+       int env:1;
+       int err:1;
+}s_variable_t,* variable_t;
 
-struct s_command;
-struct s_variable;
-struct s_variables;
-
+typedef struct s_variables
+{
+       dictionary_t items;
+}s_variables_t,* variables_t;
 
 /* 
  * declaration of the tesh timer type 
@@ -137,6 +149,7 @@ typedef struct s_reader
        struct s_command* command;                                      /* the command of the reader                                                                                    */
        int failed;                                                     /* if 1, the reader failed                                                                                              */
        int broken_pipe;                                        /* if 1, the pipe used by the reader is broken                                                  */
+       int done;
        xbt_os_sem_t started;
 }s_reader_t,* reader_t;
 
@@ -149,9 +162,12 @@ typedef struct s_writer
        struct s_command* command;                                      /* the command of the writer                                                                                    */
        int failed;                                                     /* if 1, the writer failed                                                                                              */
        int broken_pipe;                                        /* if 1, the pipe used by the writer is broken                                                  */
-       xbt_os_sem_t started;
+       xbt_os_sem_t written;
+       xbt_os_sem_t can_write;
+       int done;
 }s_writer_t,* writer_t;
 
+
 typedef struct s_units
 {
        vector_t items;                                 /* used to store the units                                                                                              */
@@ -165,6 +181,8 @@ typedef struct s_units
  */
 typedef struct s_unit
 {
+       char* description;
+       int is_suite;
        struct s_fstream* fstream;
        struct s_runner* runner;                                        /* the runner of the unit                                                                                           */
        vector_t commands;
@@ -174,6 +192,7 @@ typedef struct s_unit
        int number_of_failed_commands;          /* number of failed commands of the unit                                                                */
        int number_of_successeded_commands;     /* number of successeded commands of the unit                                                   */
        int number_of_terminated_commands;      /* number of ended commands                                                                                             */
+       int number_of_waiting_commands;
        xbt_os_thread_t thread;                         /* all the units run in its own thread                                                                  */
        xbt_os_sem_t sem;                                       /* used by the commands of the unit to signal the end of the unit               */
        xbt_os_mutex_t mutex;                           /* used to synchronously access to the properties of the runner                 */
@@ -183,14 +202,18 @@ typedef struct s_unit
        int parsed;                                                     /* if 1, the tesh file of the unit is parsed                                                    */
        int released;
        int parsing_include_file;
-       struct s_suite* owner;                                          /* the suite containing the unit if any                                                                 */
+       struct s_unit* owner;                           /* the unit containing the unit if any                                                                  */
+       struct s_unit* root;
        vector_t suites;
        int number;                                                     /* the number of suites                                                                                                 */
        int capacity;                                           /* the number of suites that the unit can contain                                               */
-       int running_suite;                                      /* if 1, the suite running a suite                                                                              */                                                                      
+       int running_suite;                                      /* if 1, the suite running a suite                                                                              */
+       vector_t includes;                                                              
 }s_unit_t,* unit_t;
 
 
+
+
 /* 
  * declaration of tesh suite type
  */
@@ -211,7 +234,7 @@ typedef struct s_suite
 typedef struct s_runner
 {
        
-       /*vector_t units;*/                                             /* the vector containing all the units launched by the runner                   */
+       /*vector_t units;*/                                     /* the vector containing all the units launched by the runner                   */
        struct s_units* units;
        int timeouted;                                          /* if 1, the runner is timeouted                                                                                */
        int timeout;                                            /* the timeout of the runner                                                                                    */
@@ -220,6 +243,22 @@ typedef struct s_runner
        int number_of_ended_units;                      /* the number of ended units                                                                                    */
        int waiting;                                            /* if 1, the runner is waiting the end of all the units                                 */
        xbt_os_thread_t thread;                         /* the timer thread                                                                                                             */
+       vector_t variables;
+
+       int total_of_tests;
+       int total_of_successeded_tests;
+       int total_of_failed_tests;
+       int total_of_interrupted_tests;
+       
+       int total_of_units;
+       int total_of_successeded_units;
+       int total_of_failed_units;
+       int total_of_interrupted_units;
+       
+       int total_of_suites;
+       int total_of_successeded_suites;
+       int total_of_failed_suites;
+       int total_of_interrupted_suites;
 }s_runner_t,* runner_t;
 
 
@@ -245,7 +284,6 @@ typedef struct s_directory
 {
        char* name;
        DIR* stream;
-       int load;
 }s_directory_t,* directory_t;
 
 typedef struct s_directories
@@ -276,6 +314,8 @@ typedef struct s_context
        int async;                                                      /* if 1, the command is asynchronous                                                                    */
 }s_context_t,* context_t;
 
+
+typedef void (*fn_sig_io_handler_t)(int);
 /* 
  * declaration of the tesh command type 
  */
@@ -307,6 +347,8 @@ typedef struct s_command
        #ifndef WIN32
        int killed;                                                     /* if 1, the command was killed                                                                                 */
        #endif
+       
+       fn_sig_io_handler_t fn_sig_io_handler;
 }s_command_t,* command_t;
 
 #ifdef _cplusplus
index 3eb17f3..8f7ddbe 100644 (file)
@@ -8,7 +8,7 @@ extern "C" {
 #endif
 
 unit_t
-unit_new(runner_t runner, suite_t owner, fstream_t fstream);
+unit_new(runner_t runner, unit_t root, unit_t owner, fstream_t fstream);
 
 int
 unit_free(void** unitptr);
@@ -36,7 +36,7 @@ void
 unit_pushline(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* filepos, char kind, char *line);
 
 void
-unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name);
+unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description);
 
 void
 unit_parse(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name, FILE* stream);
@@ -44,6 +44,9 @@ unit_parse(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* fil
 void
 unit_handle_suite(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* description);
 
+void 
+display_title(const char* description);
+
 #ifdef __cplusplus
 }
 #endif
index bd3e5ac..7f3dbc0 100644 (file)
@@ -1,12 +1,23 @@
 #ifndef __VARIABLE_H
 #define __VARIABLE_H
 
-#include <global.h>
+#include <com.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+variable_t
+variable_new(const char* name, const char* val);
+
+int
+variable_free(variable_t* variableptr);
+
+int
+variable_is_used(variable_t variable);
+
+int
+variable_set_used(variable_t variable);
 
 
 #ifdef __cplusplus
@@ -14,4 +25,5 @@ extern "C" {
 #endif
 
 
-#endif /*!__VARIABLE_H */
\ No newline at end of file
+#endif /*!__VARIABLE_H */
+
index 1b522ec..2bc50ca 100644 (file)
@@ -1,13 +1,17 @@
 #ifndef __VARIABLES_H
 #define __VARIABLES_H
 
-#include <global.h>
+#include <com.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+variables_t
+variables_new(void);
 
+int
+variables_free(variables_t* variablesptr);
 
 
 #ifdef __cplusplus
index 7121ba6..125cd8e 100644 (file)
@@ -69,7 +69,7 @@ allocator_new(int block_capacity, int type_size, fn_finalize_t fn_finalize)
        
        /* first block allocation */
        
-       if((errno = resize(allocator)))
+       if(resize(allocator))
        {
                free(allocator);
                return NULL;
@@ -88,6 +88,7 @@ allocator_free(allocator_t* allocator_ptr)
        int pos, node_size;
        fn_finalize_t fn_finalize;
        void* type;
+       int rv;
        
        if(!(*allocator_ptr))
                return EINVAL;
@@ -113,8 +114,8 @@ allocator_free(allocator_t* allocator_ptr)
                        
                                /* apply the fn_finalize function to the first type */
                                
-                               if((errno = (*fn_finalize)(&type)))
-                                       return errno;
+                               if((rv = (*fn_finalize)(&type)))
+                                       return rv;
                        }
                        
                        /*clear all the other types */
@@ -128,8 +129,8 @@ allocator_free(allocator_t* allocator_ptr)
                                
                                        /* apply the fn_finalize function to the first type */
                                        
-                                       if((errno = (*fn_finalize)(&type)))
-                                               return errno;
+                                       if((rv = (*fn_finalize)(&type)))
+                                               return rv;
                                }
                        }
                        
@@ -182,6 +183,7 @@ allocator_alloc(allocator_t allocator)
 int
 allocator_dealloc(allocator_t allocator, void* block)
 {
+       int rv;
        allocator_node_t node;
        
        if(!allocator || !block)
@@ -189,8 +191,8 @@ allocator_dealloc(allocator_t allocator, void* block)
        
        if(allocator->fn_finalize)
        {
-               if((errno = (*(allocator->fn_finalize))(&block)))
-                       return errno;
+               if((rv = (*(allocator->fn_finalize))(&block)))
+                       return rv;
                        
                memset(block, 0, allocator->type_size);
                node->is_allocated = 0;
@@ -304,6 +306,7 @@ allocator_clear(allocator_t allocator)
        fn_finalize_t fn_finalize;
        void* type;
        register int pos;
+       int rv;
        
        
        if(!allocator)
@@ -331,8 +334,8 @@ allocator_clear(allocator_t allocator)
                        
                                /* apply the fn_finalize function to the first type */
                                
-                               if((errno = (*fn_finalize)(&type)))
-                                       return errno;
+                               if((rv = (*fn_finalize)(&type)))
+                                       return rv;
                                
                                memset(type, 0, type_size);
                                node->is_allocated = 0;
@@ -349,8 +352,8 @@ allocator_clear(allocator_t allocator)
                                
                                        /* apply the fn_finalize function to the first type */
                                        
-                                       if((errno = (*fn_finalize)(&type)))
-                                               return errno;
+                                       if((rv = (*fn_finalize)(&type)))
+                                               return rv;
                                
                                        memset(type, 0, type_size);
                                        node->is_allocated = 0;
index 15cc6eb..7d27d54 100644 (file)
 #include "../include/_signal.h"
 
 
+
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
 
+static void sig_io_handler(int status)
+{
+       INFO0("*************************Got a SIGIO**************************************");    
+}
+
 static void*
 command_start(void* p);
 
-
 command_t
 command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
 {
@@ -50,7 +55,7 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
        command->stat_val = -1;
        
        /* set the unit of the command */
-       command->unit = unit; 
+       command->unit = unit->root ? unit->root : unit
        
        /* all the commands are runned in a thread */
        command->thread = NULL;
@@ -81,14 +86,20 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
        
        /* register the command */
        xbt_os_mutex_acquire(mutex);
-       /*unit->commands[(unit->number_of_commands)++] = command;*/
+       
        vector_push_back(unit->commands, command);
-       (unit->number_of_commands)++;
+       
+       (command->unit->number_of_commands)++;
+       
        xbt_os_mutex_release(mutex);
        
+       command->fn_sig_io_handler = sig_io_handler;
+       
        #ifndef WIN32
        command->killed = 0;
        #endif
+       
+       
 
        return command;
 }
@@ -365,7 +376,7 @@ command_exec(command_t command, const char* command_line)
        }
        
        command->pid= fork();
-       
+                               
        if(command->pid < 0) 
        {
                close(child_stdin_fd[0]);
@@ -381,12 +392,18 @@ command_exec(command_t command, const char* command_line)
        {
                if(command->pid) 
                {/* father */
+                       
+                       
                        close(child_stdin_fd[0]);
                        close(child_stdout_fd[1]);
                        
                        command->stdin_fd = child_stdin_fd[1];
+                       
                        command->stdout_fd = child_stdout_fd[0];
-
+                       
+                       /* on indique que c'est le processus parent qui doit recevoir le signal */
+                       /*fcntl(command->stdin_fd,F_SETOWN, pid);*/
+                       
                        if(command->reader)
                        {
                                /* launch the reader */
@@ -411,31 +428,58 @@ command_exec(command_t command, const char* command_line)
                } 
                else 
                {/* child */
-               
+                       
+                       
                        close(child_stdin_fd[1]);
+                       close(child_stdout_fd[0]);
                        
-                       dup2(child_stdin_fd[0],0);
+                       if(dup2(child_stdin_fd[0],STDIN_FILENO/*0*/) < 0)
+                       {
+                               exit_code = EEXEC;
+                               ERROR1("dup2() failed (%d)",errno);
+                               command_handle_failure(command,csr_exec_failure);
+                       }
                        
-                       close(child_stdin_fd[0]);
+                       /*close(child_stdin_fd[0]);
+                       */
                        
-                       close(child_stdout_fd[0]);
+                       if(dup2(child_stdout_fd[1],STDOUT_FILENO/*1*/) < 0)
+                       {
+                               exit_code = EEXEC;
+                               ERROR1("dup2() failed (%d)",errno);
+                               command_handle_failure(command,csr_exec_failure);
+                       }
                        
-                       dup2(child_stdout_fd[1],1);
+                       if(dup2(child_stdout_fd[1], STDERR_FILENO/*2*/) < 0)
+                       {
+                               exit_code = EEXEC;
+                               ERROR1("dup2() failed (%d)",errno);
+                               command_handle_failure(command,csr_exec_failure);
+                       }
                        
-                       dup2(child_stdout_fd[1],2);
+                       fcntl(command->stdin_fd, F_SETFL, fcntl(command->stdin_fd, F_GETFL) | O_NONBLOCK);
+                       
+                       
+                       if(command->writer)
+                               xbt_os_sem_release(command->writer->can_write);
                        
-                       close(child_stdout_fd[1]);
+                       /*close(child_stdout_fd[1]);*/
                        
                        if(command->reader)
                                xbt_os_sem_acquire(command->reader->started);
                        
                        if(command->writer)
-                               xbt_os_sem_acquire(command->writer->started);
+                               xbt_os_sem_acquire(command->writer->written);
                                
                        if(command->timer)
-                               xbt_os_sem_acquire(command->timer->started);    
+                               xbt_os_sem_acquire(command->timer->started);
                        
-                       execlp ("/bin/sh", "sh", "-c", command->context->command_line, NULL);
+                       if(execlp("/bin/sh", "sh", "-c", command->context->command_line, NULL) < 0)
+                       {
+                               exit_code = EEXEC;
+                               ERROR1("execlp() failed (%d)",errno);
+                               command_handle_failure(command,csr_exec_failure);
+                       }
                }
        }
 }
@@ -477,8 +521,18 @@ command_wait(command_t command)
        
        /* let this thread wait for the child so that the main thread can detect the timeout without blocking on the wait */
        
+       
+       xbt_os_mutex_acquire(command->unit->mutex);
+       command->unit->number_of_waiting_commands++;
+       xbt_os_mutex_release(command->unit->mutex);
+       
        pid = waitpid(command->pid, &(command->stat_val), 0);
        
+       
+       xbt_os_mutex_acquire(command->unit->mutex);
+       command->unit->number_of_waiting_commands--;
+       xbt_os_mutex_release(command->unit->mutex);
+       
        /*printf("The %p command ended\n",command);*/
        if(pid != command->pid) 
        {
@@ -491,6 +545,8 @@ command_wait(command_t command)
                if(WIFEXITED(command->stat_val))
                        command->exit_code = WEXITSTATUS(command->stat_val);    
        }
+       
+       
 }
 #endif
 
@@ -504,7 +560,7 @@ command_check(command_t command)
        if(WIFSIGNALED(command->stat_val))
        {
                command->signal = strdup(signal_name(WTERMSIG(command->stat_val),command->context->signal));
-               INFO3("the command -PID %d %s receive the signal : %s",command->pid, command->context->command_line, command->signal);
+               /*INFO3("the command -PID %d %s receive the signal : %s",command->pid, command->context->command_line, command->signal);*/
        }
        
        /* we have a signal and not signal is expected */
@@ -547,20 +603,23 @@ command_check(command_t command)
        if(success && oh_check == command->context->output_handling && command->reader)
        {
                /* make sure the reader done */
-               while(!command->reader->broken_pipe)
+               while(!command->reader->done)
                        xbt_os_thread_yield();
+                       
+               close(command->stdout_fd);
+               command->stdout_fd = INDEFINITE_FD;
 
-                       xbt_strbuff_chomp(command->output);
-                       xbt_strbuff_chomp(command->context->output);
-                       xbt_strbuff_trim(command->output);
-                       xbt_strbuff_trim(command->context->output);
+               xbt_strbuff_chomp(command->output);
+               xbt_strbuff_chomp(command->context->output);
+               xbt_strbuff_trim(command->output);
+               xbt_strbuff_trim(command->context->output);
 
-                       if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
-                       {
-                               success = 0;
-                               exit_code = EOUTPUTNOTMATCH;
-                               reason = csr_outputs_dont_match;
-                       }
+               if(command->output->used != command->context->output->used || strcmp(command->output->data, command->context->output->data))
+               {
+                       success = 0;
+                       exit_code = EOUTPUTNOTMATCH;
+                       reason = csr_outputs_dont_match;
+               }
        }
        
        if(success)
@@ -650,34 +709,15 @@ command_interrupt(command_t command)
 void
 command_display_status(command_t command)
 {
-       #ifdef WIN32
-       printf("\nCommand : PID - %p\n%s\n",command->pid,command->context->command_line);
-       #else
-       printf("\nCommand : PID - %d\n%s\n",command->pid,command->context->command_line);
-       #endif
-       printf("Status informations :\n");
-       printf("    position in the tesh file   : %s\n",command->context->line);
        
-       /* the command successeded */
-       if(cs_successeded == command->status)
-       {
-               /* status */
-               printf("    status                      : success\n");
-       }
-       else
+       /*printf("\033[1m");*/
+       
+       if(cs_successeded != command->status)
        {
-               
-               /* display if the command is interrupted, failed or in a unknown status */
-               if(cs_interrupted == command->status)
-                       printf("    status                      : interrupted\n");
-               else if(cs_failed == command->status)
-                       printf("    status                      : failed\n");
-               else
-                       printf("    status                      : unknown\n");
                        
                #ifndef WIN32
                if(command->killed)
-                       printf("    <killed command>\n");
+                       printf("          <killed command>\n");
                #endif
                
                /* display the reason of the status of the command */
@@ -685,83 +725,83 @@ command_display_status(command_t command)
                {
                        /* the function pipe or CreatePipe() fails */
                        case csr_pipe_function_failed :
-                       printf("    reason                      : pipe() or CreatePipe() function failed (system error)\n");
+                       printf("          reason                      : pipe() or CreatePipe() function failed (system error)\n");
                        break;
                        
                        /* reader failure reasons*/
                        case csr_read_pipe_broken :
-                       printf("    reason                      : command read pipe broken\n");
+                       printf("          reason                      : command read pipe broken\n");
                        break;
 
                        case csr_read_failure :
-                       printf("    reason                      : command stdout read failed\n");
+                       printf("          reason                      : command stdout read failed\n");
                        break;
        
                        /* writer failure reasons */
                        case csr_write_failure :
-                       printf("    reason                      : command stdin write failed\n");
+                       printf("          reason                      : command stdin write failed\n");
                        break;
 
                        case csr_write_pipe_broken :
-                       printf("    reason                      : command write pipe broken\n");
+                       printf("          reason                      : command write pipe broken\n");
                        break;
                        
                        /* timer reason */
                        case csr_timeout :
-                       printf("    reason                      : command timeouted\n");
+                       printf("          reason                      : command timeouted\n");
                        break;
                        
                        /* command failure reason */
                        case csr_command_not_found :
-                       printf("    reason                      : command not found\n");
+                       printf("          reason                      : command not found\n");
                        break;
                        
                        /* context failure reasons */
                        case csr_exit_codes_dont_match :
-                       printf("    reason                      : exit codes don't match\n");
+                       printf("          reason                      : exit codes don't match\n");
                        
                        break;
 
                        case csr_outputs_dont_match :
                        {
                                char *diff;
-                               printf("    reason                      : ouputs don't match\n");
+                               printf("          reason                      : ouputs don't match\n");
                                diff = xbt_str_diff(command->context->output->data,command->output->data);              
-                               printf("    output diff :\n%s\n",diff);
+                               printf("          output diff :\n%s\n",diff);
                                free(diff);
                        }     
 
                        break;
 
                        case csr_signals_dont_match :
-                       printf("    reason                      : signals don't match\n"); 
+                       printf("          reason                      : signals don't match\n"); 
                        break;
                        
                        case csr_unexpected_signal_caught:
-                       printf("    reason                      : unexpected signal caught\n");
+                       printf("                reason                      : unexpected signal caught\n");
                        break;
                        
                        case csr_expected_signal_not_receipt :
-                       printf("    reason                      : expected signal not receipt\n");
+                       printf("          reason                      : expected signal not receipt\n");
                        break;
 
                        /* system failure reasons */
                        case csr_exec_failure :
-                       printf("    reason                      : can't excute the command\n");
+                       printf("          reason                      : can't excute the command\n");
                        break;
                        
                        case csr_wait_failure :
-                       printf("    reason                      : wait command failure\n");
+                       printf("          reason                      : wait command failure\n");
                        break;
                        
                        /* global/local interruption */
                        case csr_interruption_request :
-                       printf("    reason                      : the command receive a interruption request\n");
+                       printf("          reason                      : the command receive a interruption request\n");
                        break;
                        
                        /* unknown ? */
                        case csr_unknown :
-                       printf("    reason                      : unknown \n");
+                       printf("          reason                      : unknown \n");
                }
        }
 
@@ -769,23 +809,23 @@ command_display_status(command_t command)
        {
                if(INDEFINITE != command->exit_code)
                        /* the command exit code */
-                       printf("    exit code                   : %d\n",command->exit_code);
+                       printf("          exit code                   : %d\n",command->exit_code);
                
                /* if an expected exit code was specified display it */
                if(INDEFINITE != command->context->exit_code)
-                       printf("    expected exit code          : %d\n",command->context->exit_code);
+                       printf("          expected exit code          : %d\n",command->context->exit_code);
                else
-                       printf("    no expected exit code specified\n");
+                       printf("          no expected exit code specified\n");
                
                /* if an expected exit code was specified display it */
                if(NULL == command->context->signal)
-                       printf("    no expected signal specified\n");
+                       printf("          no expected signal specified\n");
                else
                {
                        if(NULL != command->signal)
-                               printf("    signal                      : %s\n",command->signal);
+                               printf("          signal                      : %s\n",command->signal);
                        
-                       printf("    expected signal             : %s\n",command->context->signal);
+                       printf("          expected signal             : %s\n",command->context->signal);
                }
                
                /* if the command has out put and the metacommand display output is specified display it  */
@@ -794,16 +834,21 @@ command_display_status(command_t command)
                        xbt_dynar_t a = xbt_str_split(command->output->data, "\n");
                        char *out = xbt_str_join(a,"\n||");
                        xbt_dynar_free(&a);
-                       printf("    output :\n||%s",out);
+                       printf("          output :\n||%s",out);
                        free(out);
                }
        }
 
        printf("\n");
+       
+       /*printf("\033[0m");*/
                
 
 }
 
+
+
+
 void
 command_handle_failure(command_t command, cs_reason_t reason)
 {
index 8c0c5b6..9e5f99b 100644 (file)
@@ -76,11 +76,13 @@ dictionary_get(dictionary_t dictionary, const char* key)
 int
 dictionary_free(dictionary_t* dictionaryptr)
 {
+       int rv;
+       
        if(!(*dictionaryptr))
                return EINVAL;
        
-       if((errno = htable_free(&((*dictionaryptr)->htable))))
-               return errno;
+       if((rv = htable_free(&((*dictionaryptr)->htable))))
+               return rv;
        
        free(*dictionaryptr);
        *dictionaryptr = NULL;
index 83726a7..3afc543 100644 (file)
@@ -29,6 +29,18 @@ directories_get_size(directories_t directories)
        return vector_get_size(directories->items);
 }
 
+int
+directories_is_empty(directories_t directories)
+{
+       if(!directories)
+       {
+               errno = EINVAL;
+               return -1;
+       }
+       
+       return vector_is_empty(directories->items);
+}
+
 int
 directories_add(directories_t directories, directory_t directory)
 {
@@ -71,48 +83,11 @@ directories_contains(directories_t directories, directory_t directory)
        return 0;
 }
 
-directory_t
-directories_search_fstream_directory(directories_t directories, const char* name)
-{
-       
-       struct stat buffer = {0};
-       char* prev;
-       directory_t directory;
-       
-       if(!directories)
-       {
-               errno = EINVAL;
-               return NULL;
-       }
-       
-       prev = getcwd(NULL, 0);
-       
-       vector_rewind(directories->items);
-       
-       while((directory = vector_get(directories->items)))
-       {
-               chdir(directory->name);
-               
-               if(!stat(name, &buffer) || S_ISREG(buffer.st_mode))
-               {
-                       chdir(prev);
-                       free(prev);
-                       return directory;
-               }
-               
-               vector_move_next(directories->items);
-       }
-       
-       chdir(prev);
-       free(prev);
-       errno = ESRCH;
-       return NULL;    
-}
-
 int
 directories_load(directories_t directories, fstreams_t fstreams, lstrings_t suffixes)
 {
        directory_t directory;
+       int rv;
        
        if(!directories || !fstreams || !suffixes)
                return EINVAL;
@@ -121,21 +96,14 @@ directories_load(directories_t directories, fstreams_t fstreams, lstrings_t suff
        
        while((directory = vector_get(directories->items)))
        {
-               if(directory->load)
-               {
-                       if((errno = directory_open(directory)))
-                               return errno;
-                       
-                       chdir(directory->name);
-                       
-                       if((errno = directory_load(directory, fstreams, suffixes)))
-                               return errno;
-                               
-                       if((errno = directory_close(directory)))
-                               return errno;
+               if((rv = directory_open(directory)))
+                       return rv;
+               
+               if((rv = directory_load(directory, fstreams, suffixes)))
+                       return rv;
                        
-                       chdir(root_directory->name);
-               }
+               if((rv = directory_close(directory)))
+                       return rv;
                        
                vector_move_next(directories->items);
                
@@ -145,51 +113,16 @@ directories_load(directories_t directories, fstreams_t fstreams, lstrings_t suff
        return 0;
 }
 
-int
-directories_has_directories_to_load(directories_t directories)
-{
-       directory_t directory;
-       
-       if(!directories)
-       {
-               errno = EINVAL;
-               return 0;
-       }
-       
-       vector_rewind(directories->items);
-       
-       while((directory = vector_get(directories->items)))
-       {
-               if(directory->load)
-                       return 1;
-                       
-               vector_move_next(directories->items);
-               
-       }
-       
-       return 0;
-}
-
-directory_t
-directories_get_back(directories_t directories)
-{
-       if(!directories)
-       {
-               errno = EINVAL;
-               return NULL;
-       }
-       
-       return vector_get_back(directories->items);     
-}
-
 int
 directories_free(void** directoriesptr)
 {
+       int rv;
+       
        if(!(*directoriesptr))
                return EINVAL;
                
-       if((errno = vector_free(&((*((directories_t*)directoriesptr))->items))))
-               return errno;
+       if((rv = vector_free(&((*((directories_t*)directoriesptr))->items))))
+               return rv;
        
        free(*directoriesptr);
        *directoriesptr = NULL;
index 6033aa0..ea93e7f 100644 (file)
@@ -5,10 +5,9 @@
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
 
 directory_t
-directory_new(const char* name, int load)
+directory_new(const char* name)
 {
        directory_t directory;
-       struct stat buffer = {0};
        
        if(!name)
        {
@@ -16,37 +15,13 @@ directory_new(const char* name, int load)
                return NULL;
        }
        
-       if(stat(name, &buffer))
-               return NULL;
-               
-       if(!S_ISDIR(buffer.st_mode))
-       {
-               errno = ENOTDIR;
-               return NULL;
-       }
-       
        directory = xbt_new0(s_directory_t, 1);
        
-       if(!strcmp(".",name))
-       {
-               directory->name = getcwd(NULL, 0);
-       }
-       else if(!strcmp("..",name))
-       {
-               char* buffer = getcwd(NULL, 0);
-               chdir(name);
-               directory->name = getcwd(NULL, 0);
-               chdir(buffer);
-               free(buffer);
-       }
-       else
-       {
-               directory->name = strdup(name); 
-       }
-               
        
+       directory->name = strdup(name); 
+       
+               
        directory->stream = NULL;
-       directory->load = load;
        
        return directory;
 }
@@ -88,6 +63,7 @@ directory_load(directory_t directory, fstreams_t fstreams, lstrings_t suffixes)
        const char* suffix;
        int has_valid_suffix;
        int is_empty = 1;
+       int rv;
        
        if(!directory || !fstreams)
                return EINVAL;
@@ -128,12 +104,12 @@ directory_load(directory_t directory, fstreams_t fstreams, lstrings_t suffixes)
                }
                
                /* add the fstream to the list of file streams to run */
-               if((errno = fstreams_add(fstreams, fstream_new(directory->name, entry->d_name))))
+               if((rv = fstreams_add(fstreams, fstream_new(directory->name, entry->d_name))))
                {
                        INFO0("fstreams_add() failed");
                        free(sfstream.directory);
                        free(sfstream.name);
-                       return errno;
+                       return rv;
                }
                        
                is_empty = 0;
index 1f7a795..c7fcf6b 100644 (file)
@@ -1,57 +1,76 @@
-#include <error.h>\r
-\r
-typedef struct s_entry\r
-{\r
-       int code;\r
-       const char* string;\r
-}entry_t;\r
-\r
-static const\r
-entry_t err[] =\r
-{\r
-       {EREAD, "a read pipe operation failed"},\r
-       {EREADPIPE, "a pipe used to read from the stdout of a command is broken"},\r
-       {ETIMEOUT, "a command is timeouted"},\r
-       {EWRITE, "a write operation failed"},\r
-       {EWRITEPIPE, "a pipe used to write to the stdin of a command is broken"},\r
-       {EEXEC, "can't execute a command"},\r
-       {EWAIT, "wait function failed"},\r
-       {ECMDNOTFOUND, "command is not found"},\r
-       {EEXITCODENOTMATCH, "exit codes don't match"},\r
-       {EOUTPUTNOTMATCH, "outputs don't match"},\r
-       {ESIGNOTMATCH, "signals don't match"},\r
-       {EUNEXPECTEDSIG, "unexpected signal caught"},\r
-       {ESIGNOTRECEIPT, "expected signal not receipt"},\r
-       {EFILENOTFOUND, "specified tesh file not found"},\r
-       {EGETCWD, "system error : the getcwd() function failed"},\r
-       {EDIRNOTFOUND, "specified directory not found"},\r
-       {ECHDIR, "system error : the chdir() function failed"},\r
-       {EPROCESSCMDLINE, "internal error : the process_command_line() function failed"},\r
-       {EARGNOTSPEC, "none optional argument not specified in the command line"},\r
-       {ENOTPOSITIVENUM, "argument option not strictly positive"},\r
-       {ESYNTAX, "syntax error"},\r
-       {EINVALIDTIMEOUT, "timeout value specified by metacommand invalid"},\r
-       {EINVALIDEXITCODE, "expected exit code value specified by the metacommand invalid"},\r
-       {ESIGNOTSUPP, "signal specified by the metacommand not supported (Windows specific)"},\r
-       {ELEADTIME, "lead time"},\r
-       {EREADMENOTFOUND, "unable to locate the README.txt file"},\r
-       {EINCLUDENOTFOUND, "include file specified by a metacommand is not found"},\r
-       {ESUFFIXTOOLONG, "suffix is too long"},\r
-       {EFILENOTINSPECDIR,"file not found in the specified directories"},\r
-       {EFILENOTINCURDIR,"file not found in the current directory"},\r
-       {-1, "unknown"}\r
-};\r
-\r
-const char*\r
-error_to_string(int error)\r
-{\r
-       int i;\r
-       \r
-       for(i = 0; error >= 0 && err[i].code != -1; i++)\r
-       {\r
-               if(err[i].code == error)\r
-                       return err[i].string;\r
-       } \r
-       \r
-       return "unknow error";  \r
-}\r
+#include <error.h>
+
+typedef struct s_entry
+{
+       const char* name;
+       int code;
+       const char* string;
+}entry_t;
+
+
+static const
+entry_t err[] =
+{
+       {"ENOENT", ENOENT, "No such file of directory."},
+       {"ENOMEM", ENOMEM,"Insufficient memory is available."},
+       {"EACCES", EACCES, "Read or search permission was denied for a component of the pathname."},
+       {"ENOTDIR", ENOTDIR, "Not a directory."},
+       {"EREAD", EREAD, "a read pipe operation failed"},
+       {"EREADPIPE", EREADPIPE, "a pipe used to read from the stdout of a command is broken"},
+       {"ETIMEOUT", ETIMEOUT, "a command is timeouted"},
+       {"EWRITE", EWRITE, "a write operation failed"},
+       {"EWRITEPIPE", EWRITEPIPE, "a pipe used to write to the stdin of a command is broken"},
+       {"EEXEC", EEXEC, "can't execute a command"},
+       {"EWAIT", EWAIT, "wait function failed"},
+       {"ECMDNOTFOUND", ECMDNOTFOUND, "command is not found"},
+       {"EEXITCODENOTMATCH", EEXITCODENOTMATCH, "exit codes don't match"},
+       {"EOUTPUTNOTMATCH", EOUTPUTNOTMATCH, "outputs don't match"},
+       {"ESIGNOTMATCH", ESIGNOTMATCH, "signals don't match"},
+       {"EUNEXPECTEDSIG", EUNEXPECTEDSIG, "unexpected signal caught"},
+       {"ESIGNOTRECEIPT", ESIGNOTRECEIPT, "expected signal not receipt"},
+       {"EFILENOTFOUND", EFILENOTFOUND, "specified tesh file not found"},
+       {"EGETCWD", EGETCWD, "system error : the getcwd() function failed"},
+       {"EDIRNOTFOUND", EDIRNOTFOUND, "specified directory not found"},
+       {"ECHDIR", ECHDIR, "system error : the chdir() function failed"},
+       {"EPROCCMDLINE", EPROCCMDLINE, "process_command_line() failed : internal error"},
+       {"ENOARG", ENOARG, "none optional argument not specified"},
+       {"ENOTPOSITIVENUM", ENOTPOSITIVENUM, "argument option not strictly positive"},
+       {"ESYNTAX", ESYNTAX, "syntax error"},
+       {"EINVALIDTIMEOUT", EINVALIDTIMEOUT, "timeout value specified by metacommand invalid"},
+       {"EINVALIDEXITCODE", EINVALIDEXITCODE, "expected exit code value specified by the metacommand invalid"},
+       {"ESIGNOTSUPP", ESIGNOTSUPP, "signal specified by the metacommand not supported (Windows specific)"},
+       {"ELEADTIME", ELEADTIME, "lead time"},
+       {"EREADMENOTFOUND", EREADMENOTFOUND, "unable to locate the README.txt file"},
+       {"EINCLUDENOTFOUND", EINCLUDENOTFOUND, "include file specified by a metacommand is not found"},
+       {"ESUFFIXTOOLONG", ESUFFIXTOOLONG, "suffix is too long"},
+       {"EFILENOTINSPECDIR", EFILENOTINSPECDIR,"file not found in the specified directories"},
+       {"EFILENOTINCURDIR", EFILENOTINCURDIR,"file not found in the current directory"},
+       {"unkwown", -1, "unknown"}
+};
+
+#include <stdio.h>
+
+const char*
+error_to_string(int errcode)
+{
+       int i;
+       
+       for(i = 0; err[i].code != -1; i++)
+               if(err[i].code == errcode)
+                       return err[i].string;
+       
+       return "unknow error";  
+}
+
+const char*
+error_get_at(int pos, int* code)
+{
+       if(pos < 0 || (pos > (sizeof(err)/sizeof(entry_t)) - 2))
+       {
+               errno = ERANGE;
+               return NULL;
+       }
+       
+       *code = err[pos].code;
+       return err[pos].name;
+}
index 3329974..e2a33cb 100644 (file)
@@ -110,11 +110,13 @@ excludes_check(excludes_t excludes, fstreams_t fstreams)
 int
 excludes_free(void** excludesptr)
 {
+       int rv;
+       
        if(!(*excludesptr))
                return EINVAL;
                
-       if((errno =vector_free((&(*((excludes_t*)excludesptr))->items))))
-               return errno;
+       if((rv =vector_free((&(*((excludes_t*)excludesptr))->items))))
+               return rv;
                
        free(*excludesptr);
        *excludesptr = NULL;    
index 1349a98..18d3c1a 100644 (file)
@@ -10,8 +10,7 @@ fstream_t
 fstream_new(const char* directory, const char* name)
 {
        fstream_t fstream;
-       /*struct stat buffer = {0};*/
-               
+       
        if(!name)
        {
                errno = EINVAL;
@@ -30,15 +29,6 @@ fstream_new(const char* directory, const char* name)
                return NULL;
        }
        
-       /*if(stat(name, &buffer))
-               return NULL;
-       
-       if(!S_ISREG(buffer.st_mode))
-       {
-               errno = ENOENT;
-               return NULL;
-       }*/
-       
        fstream = xbt_new0(s_fstream_t, 1);
        
        fstream->name = strdup(name);
@@ -53,6 +43,8 @@ fstream_new(const char* directory, const char* name)
 int
 fstream_open(fstream_t fstream)
 {
+       char path[MAX_PATH] = {0};
+       
        if(!fstream || fstream->stream)
                return EINVAL;
                
@@ -62,7 +54,9 @@ fstream_open(fstream_t fstream)
                return 0;
        }
        
-       if(!(fstream->stream = fopen(fstream->name, "r")))
+       sprintf(path,"%s/%s",fstream->directory, fstream->name);
+       
+       if(!(fstream->stream = fopen(path, "r")))
                return errno;
        
        return 0;
@@ -105,7 +99,7 @@ fstream_free(void** fstreamptr)
 }
 
 void
-fstream_parse( fstream_t fstream, unit_t unit)
+fstream_parse(fstream_t fstream, unit_t unit, xbt_os_mutex_t mutex)
 {
        size_t len;
        char * line = NULL;
@@ -114,7 +108,6 @@ fstream_parse( fstream_t fstream, unit_t unit)
        xbt_strbuff_t buff;
        int buffbegin = 0; 
        context_t context;
-       xbt_os_mutex_t mutex = unit->mutex;
        
        /* Count the line length while checking wheather it's blank */
        int blankline;
@@ -125,8 +118,9 @@ fstream_parse( fstream_t fstream, unit_t unit)
        buff=xbt_strbuff_new();
        context = context_new();
        
-       while(!unit->interrupted  && getline(&line, &len, fstream->stream) != -1)
+       while(!(unit->root->interrupted)  && getline(&line, &len, fstream->stream) != -1)
        {
+               
                blankline=1;
                linelen = 0;    
                to_be_continued = 0;
@@ -146,16 +140,16 @@ fstream_parse( fstream_t fstream, unit_t unit)
                        if(!context->command_line && (context->input->used || context->output->used))
                        {
                                ERROR1("[%d] Error: no command found in this chunk of lines.",buffbegin);
-                               
-                               if(unit->parsing_include_file)
-                                       ERROR1("Unit `%s': NOK (syntax error)", fstream->name);
-                               else
-                                       ERROR2("Unit `%s' inclued in `%s' : NOK (syntax error)", fstream->name, fstream->name); 
+                               ERROR1("Unit `%s': NOK (syntax error)", fstream->name);
+                       
                                
                                exit_code = ESYNTAX;
                                unit_handle_failure(unit);
                                break;
                        }
+                       else if(unit->running_suite)
+                               unit->running_suite = 0;
+                               
                        
                        if(context->command_line)
                        {
@@ -163,19 +157,18 @@ fstream_parse( fstream_t fstream, unit_t unit)
                                {
                                        command_t command = command_new(unit, context, mutex);
                                        command_run(command);
+                                       
                                }
                                
                                context_reset(context);
                        }
                
-               
                        continue;
-                       
                }
                
                if(linelen>1 && line[linelen-2]=='\\') 
                {
-                       if (linelen>2 && line[linelen-3] == '\\') 
+                       if(linelen>2 && line[linelen-3] == '\\') 
                        {
                                /* Damn. Escaped \ */
                                line[linelen-2] = '\n';
@@ -210,6 +203,8 @@ fstream_parse( fstream_t fstream, unit_t unit)
                }
        }
        
+       
+       
        /* Check that last command of the file ran well */
        if(context->command_line)
        {
@@ -221,12 +216,15 @@ fstream_parse( fstream_t fstream, unit_t unit)
                
                context_reset(context);
        }
+       
+       
 
        /* Clear buffers */
        if (line)
                free(line);
                
        xbt_strbuff_free(buff); 
+       context_free(&context);
 }
 
 
index 27905ee..510121a 100644 (file)
@@ -8,7 +8,9 @@ fstreams_t
 fstreams_new(int capacity, fn_finalize_t fn_finalize)
 {
        fstreams_t fstreams;
-       fstreams = xbt_new0(s_fstreams_t, 1);
+       
+       if(!(fstreams = (fstreams_t) calloc(1, sizeof(s_fstreams_t))))
+               return NULL;
        
        if(!(fstreams->items = vector_new(capacity, fn_finalize)))
        {
@@ -34,8 +36,6 @@ fstreams_exclude(fstreams_t fstreams, excludes_t excludes)
        if(!(to_erase = vector_new(8, NULL)))
                return errno;
        
-       INFO0("excluding file streams");
-       
        /* collecte the file streams to exclude */
        vector_rewind(fstreams->items);
        
@@ -93,8 +93,6 @@ int
 fstreams_load(fstreams_t fstreams)
 {
        register fstream_t fstream;
-       const char* directory = NULL;
-       
        
        if(!fstreams )
                return EINVAL;
@@ -103,24 +101,11 @@ fstreams_load(fstreams_t fstreams)
        
        while((fstream = vector_get(fstreams->items)))
        {
-               chdir(root_directory->name);
-               
-               if(!directory || strcmp(directory, fstream->directory))
-               {
-                       directory = fstream->directory; 
-                       
-                       if(!dont_want_display_directory)
-                               INFO1("entering directory \"%s\"",directory);
-                               
-               }
-               
-               chdir(fstream->directory);
-               
                fstream_open(fstream);
-               
                vector_move_next(fstreams->items);
        }
        
+       
        return 0;
 }
 
@@ -140,12 +125,13 @@ fstreams_add(fstreams_t fstreams, fstream_t fstream)
 int
 fstreams_free(void** fstreamsptr)
 {
+       int rv;
+       
        if(!(* fstreamsptr))
                return EINVAL;
-               
        
-       if((errno = vector_free(&((*((fstreams_t*)fstreamsptr))->items))))
-               return errno;
+       if(EAGAIN != (rv = vector_free(&((*((fstreams_t*)fstreamsptr))->items))))
+               return rv;
                
        free(*fstreamsptr);
        
index 5b7cb60..5c1abeb 100644 (file)
@@ -141,7 +141,7 @@ htable_remove(htable_t htable, const void* key)
                        *prev = hassoc->next;  
                        val = (void*)hassoc->val;
                        
-                       if((errno = allocator_dealloc(htable->allocator,hassoc)))
+                       if(allocator_dealloc(htable->allocator,hassoc))
                                return NULL;
                                
                        return val;
@@ -162,6 +162,7 @@ htable_erase(htable_t htable, const void* key)
        hassoc_t* prev;
        fn_cmp_key_t fn_cmp_key;
        void* val;
+       int rv;
        
        if(!htable || !key)
                return EINVAL;
@@ -177,13 +178,13 @@ htable_erase(htable_t htable, const void* key)
                        *prev = hassoc->next;  
                        val = (void*)hassoc->val;
                        
-                       if((errno = allocator_dealloc(htable->allocator,hassoc)))
-                               return errno;
+                       if((rv = allocator_dealloc(htable->allocator,hassoc)))
+                               return rv;
                                
                        if(htable->fn_finalize)
                        {       
-                               if((errno = (*(htable->fn_finalize))(&val)))
-                                       return errno;
+                               if((rv = (*(htable->fn_finalize))(&val)))
+                                       return rv;
                        }
                        
                        return 0;
@@ -199,6 +200,7 @@ int
 htable_free(htable_t* htableptr)
 {
        htable_t htable;
+       int rv;
        
        if(!(*htableptr))
                return EINVAL;
@@ -221,16 +223,16 @@ htable_free(htable_t* htableptr)
                        for(hassoc = content[pos]; hassoc; hassoc = hassoc->next)
                        {
                                val = (void*)hassoc->val;
-                               if((errno = (*(htable->fn_finalize))(&val)))
-                                       return errno;
+                               if((rv = (*(htable->fn_finalize))(&val)))
+                                       return rv;
                        }
                }
        }
        
        free(htable->content);
        
-       if((errno = allocator_free(&(htable->allocator))))
-               return errno;
+       if((rv = allocator_free(&(htable->allocator))))
+               return rv;
                
        free(*htableptr);
        *htableptr = NULL;
@@ -246,6 +248,7 @@ htable_clear(htable_t htable)
        register int pos;
        int size;
        void* val;
+       int rv;
        
        if(!htable)
                return EINVAL;
@@ -261,8 +264,8 @@ htable_clear(htable_t htable)
                        for(hassoc = content[pos]; hassoc; hassoc = hassoc->next)
                        {
                                val = (void*)hassoc->val;
-                               if((errno = (*(htable->fn_finalize))(&val)))
-                                       return errno;
+                               if((rv = (*(htable->fn_finalize))(&val)))
+                                       return rv;
                        }
                        
                        content[pos] = NULL;
index b87f2bf..1d5c6d9 100644 (file)
@@ -140,9 +140,10 @@ lstrings_clear(lstrings_t lstrings)
                return EINVAL;
        
        if(!lstrings->size)
-               return EAGAIN;
+               return 0;
        
-       while(lstrings_pop_back(lstrings));
+       while(lstrings->size)
+               lstrings_pop_back(lstrings);
        
        return 0;
 }
index 94e9599..135e328 100644 (file)
@@ -8,6 +8,7 @@
 #include <error.h>
 
 #include <getopt.h>
+#include <getpath.h>
 
 /*
  * entry used to define the parameter of a tesh option.
@@ -44,8 +45,12 @@ prev_error_mode = 0;
 directory_t
 root_directory = NULL;
 
-int
+/*int
 exit_code = 0;
+*/
+
+int 
+want_detail_summary = 0;
 
 /* the current version of tesh                                                                 */
 static const char* 
@@ -86,7 +91,7 @@ directories = NULL;
 
 /* the include directories : see the !i metacommand                            */
 vector_t 
-includes = NULL;
+include_dirs = NULL;
 
 /* the list of tesh files to run                                                               */
 static fstreams_t 
@@ -133,12 +138,6 @@ want_display_version = 0;
 static int
 want_check_syntax = 0;
 
-/* if 1, all the tesh file of the current directory
- * are runned
- */ 
-static int
-want_load_directory = 0;
-
 /* if 1, the status of all the units is display at
  * the end.
  */
@@ -183,25 +182,31 @@ xbt_os_sem_t
 units_sem = NULL;
 
 static int
-prepared = 0;
-
+loaded = 0;
 
 int 
-interrupted = 0; 
+interrupted = 0;
+
+int
+exit_code = 0; 
+
+pid_t
+pid =0;
 
 /* the table of the entries of the options */ 
 static const struct s_optentry opt_entries[] =
 {
-       { 'C', string, (byte*)&directories, 0, "directory" },
+       { 'C', string, (byte*)NULL, 0, "directory" },
        { 'x', string, (byte*)&suffixes, 0, "suffix" },
        { 'e', flag, (byte*)&env_overrides, 0, "environment-overrides", },
        { 'f', string, (byte*)&fstreams, 0, "file" },
        { 'h', flag, (byte*)&want_display_usage, 0, "help" },
        { 'a', flag, (byte*)&want_display_semantic, 0, "semantic" },
        { 'i', flag, (byte*)&want_keep_going_unit, 0, "keep-going-unit" },
-       { 'I', string, (byte*)&includes, 0, "include-dir" },
+       { 'I', string, (byte*)&include_dirs, 0, "include-dir" },
        { 'j', number, (byte*)&number_of_jobs, (byte*) &optional_number_of_jobs, "jobs" },
        { 'k', flag, (byte*)&want_keep_going, 0, "keep-going" },
+       { 'm', flag, (byte*)&want_detail_summary, 0, "detail-summary" },
        { 'c', flag, (byte*)&want_just_display, 0, "just-display" },
        { 'd', flag, (byte*)&display_data_base, 0,"display-data-base" },
        { 'q', flag, (byte*)&question, 0, "question" },
@@ -211,7 +216,7 @@ static const struct s_optentry opt_entries[] =
        { 'n', flag, (byte*)&want_dry_run, 0, "dry-run"},
        { 't', number, (byte*)&timeout, 0, "timeout" },
        { 'S', flag, (byte*)&want_check_syntax, 0, "check-syntax"},
-       { 'r', flag, (byte*)&want_load_directory, 0, "load-directory"},
+       { 'r', string, (byte*)&directories, 0, "load-directory"},
        { 'v', flag, (byte*)&want_verbose, 0, "verbose"},
        { 'F', string,(byte*)&excludes, 0, "exclude"},
        { 'l', string,(byte*)&logs,0,"log"},
@@ -259,6 +264,7 @@ static const char* usage[] =
        " -b, --build-file                       Build a tesh file.\n",
        " -r, --load-directory                   Run all the tesh files located in the directories specified by the option --directory.\n",
        " -v, --verbose                          Display the status of the commands.\n",
+       " -m, --detail-summary                   Detail the summary of the run.\n",
        " -F file , --exclude=FILE               Ignore the tesh file FILE.\n",
        " -l format, --log                       Format of the xbt logs.\n",
        NULL
@@ -278,11 +284,11 @@ init_options(void);
 static int
 process_command_line(int argc, char** argv);
 
-static int
+static void
 load(void);
 
 static void
-display_usage(int exit_code);
+display_usage(void);
 
 static void
 display_version(void);
@@ -301,16 +307,21 @@ init(void);
 int
 main(int argc, char* argv[])
 {
-       init();
-       
+       if(init() < 0)
+               finalize();
+               
        /* process the command line */
-       if((exit_code = process_command_line(argc, argv)))
+       if(process_command_line(argc, argv) < 0)
                finalize();
+       
+       /* move to the root directory (the directory may change during the command line processing) */
+       chdir(root_directory->name);
                
        /* initialize the xbt library 
         * for thread portability layer
         */
         
+       /* xbt initialization */
        if(!lstrings_is_empty(logs))
        {
                int size = lstrings_get_size(logs);
@@ -342,16 +353,12 @@ main(int argc, char* argv[])
                finalize();
        }
        
-       if(!directories_has_directories_to_load(directories) && want_load_directory)
-               WARN0("--load-directory specified but no directory specified");
+       /* load tesh files */
+       load();
        
-       excludes_check(excludes, fstreams);
        
-       /* load tesh */
-       if((exit_code = load()))
-               finalize();
-               
-       prepared = 1;
+       /* use by the finalize function to known if it must display the tesh usage */   
+       loaded = 1;
 
        if(-2 == number_of_jobs)
        {/* --jobs is not specified (use the default value) */
@@ -365,27 +372,22 @@ main(int argc, char* argv[])
        if(number_of_jobs > fstreams_get_size(fstreams))
        {/* --jobs = N is specified and N is more than the number of tesh files */
                
-               WARN0("number of requested jobs exceed the number of files");
+               WARN0("Number of requested jobs exceed the number of files to run");
                
                /* assume one job per file */
                number_of_jobs = fstreams_get_size(fstreams);
        }
 
-       /* initialize the semaphore used to synchronize the jobs */
+       /* initialize the semaphore used to synchronize all the units */
        jobs_sem = xbt_os_sem_init(number_of_jobs);
 
        /* initialize the semaphore used by the runner to wait for the end of all units */
        units_sem = xbt_os_sem_init(0);
        
        /* initialize the runner */
-       if((0 != (exit_code = runner_init(
-                                                                       want_check_syntax, 
-                                                                       timeout, 
-                                                                       fstreams))))
-       {
+       if(runner_init(want_check_syntax, timeout, fstreams))
                finalize();
-       }
-       
+               
        if(want_just_display && want_silent)
                want_silent = 0;
                
@@ -393,17 +395,17 @@ main(int argc, char* argv[])
                WARN0("mismatch in the syntax : --just-check-syntax and --just-display options at same time");
        
        /* run all the units */
-       runner_run(); 
+       runner_run();
+       
        
        /* show the result of the units */
        if(want_verbose || want_dry_run)
                runner_display_status();
                
-
        /* all the test are runned, destroy the runner */
        runner_destroy();
        
-       /* then, finalize tesh */
+       /* then, finalize tesh (release all the allocated memory and exits) */
        finalize();
        
        #ifndef WIN32
@@ -412,10 +414,21 @@ main(int argc, char* argv[])
        
 }
 
+/* init --     initialize tesh : allocated all the objects needed by tesh to run
+ *                     the tesh files specified in the command line.
+ *
+ * return      If successful the function returns zero. Otherwise the function returns
+ *                     -1 and sets the global variable errno to the appropriate error code.
+ */
+
+
+
 static int
 init(void)
 {
-       char* buffer = getcwd(NULL, 0);
+       char* buffer;
+       
+       
        
        #ifdef WIN32
        /* Windows specific : don't display the general-protection-fault message box and
@@ -425,99 +438,176 @@ init(void)
        prev_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
        #endif
        
-       /* used to store the file streams to run */
-       fstreams = fstreams_new(DEFAULT_FSTREAMS_CAPACITY, fstream_free);
+       /* used to store the files to run */
+       if(!(fstreams = fstreams_new(DEFAULT_FSTREAMS_CAPACITY, fstream_free)))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
+       
+       /* register the current directory */
+       if(!(buffer  = getcwd(NULL, 0)))
+       {
+               exit_code = errno;
+               
+               if(EACCES == errno)
+                       ERROR0("tesh initialization failed - Insufficient permission to read the current directory");
+               else
+                       ERROR0("Insufficient memory is available to initialize tesh : system error");   
+               
+               return -1;
+       }
+       
+       /* save the root directory */
+       if(!(root_directory = directory_new(buffer)))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
        
-       root_directory = directory_new(buffer,want_load_directory);
        free(buffer);
-       /* used to store the directories to loads */
-       directories = directories_new(); 
        
-       /* register the current directory */
-       directories_add(directories, root_directory);
+       /* the directories to loads */
+       if(!(directories = directories_new()))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
        
-       /* used to store the includes directories */
-       includes = vector_new(DEFAULT_INCLUDES_CAPACITY, directory_free);
+       /* the include directories */
+       if(!(include_dirs = vector_new(DEFAULT_INCLUDE_DIRS_CAPACITY, directory_free)))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
        
-       /* xbt logs */
-       logs = lstrings_new();
+       /* xbt logs option */
+       if(!(logs = lstrings_new()))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
        
-       /* used to to store all the excluded file streams */
-       excludes = excludes_new();
+       /* the excluded files */
+       if(!(excludes = excludes_new()))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
        
-       /* list of file streams suffixes */
-       suffixes = lstrings_new();
+       /* the suffixes */
+       if(!(suffixes = lstrings_new()))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
        
-       lstrings_push_back(suffixes,".tesh");
+       /* register the default suffix ".tesh" */
+       if(lstrings_push_back(suffixes,".tesh"))
+       {
+               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               return -1;
+       }
+       
+       pid = getpid();
        
        return 0;
 }
 
-static int
+/* load -- load the tesh files to run */
+static void
 load(void)
 {
-       chdir(directory_get_name(root_directory));
        
-       if(want_load_directory)
+       /* if the directories object is not empty load all the tesh files contained in
+        * the directories specified in the command line (this tesh files must have the
+        * a suffix specified in the suffixes object.
+        */
+       if(!directories_is_empty(directories))
                directories_load(directories, fstreams, suffixes);
        
-       /* on a aucun fichier specifie dans la ligne de commande
-        * l'option --run-current-directory n'a pas ete specifie ou aucun fichier ne se trouve dans le repertoire a charger
+       /* if no tesh file has been specified in the command line try to load the default tesh file
+        * teshfile from the current directory
         */
        if(fstreams_is_empty(fstreams))
        {
                struct stat buffer = {0};
                
-               /* add the default tesh file if it exists */
+               /* add the default tesh file if it exists in the current directory */
                if(!stat("teshfile", &buffer) && S_ISREG(buffer.st_mode))
                        fstreams_add(fstreams, fstream_new(getcwd(NULL, 0), "teshfile"));
        }
        
+       /* excludes the files specified in the command line and stored in the excludes object */
        if(!excludes_is_empty(excludes) && !fstreams_is_empty(fstreams))
+       {
+               /* check the files to excludes before */        
+               excludes_check(excludes, fstreams);
+               
+               /* exclude the specified tesh files */
                fstreams_exclude(fstreams, excludes);
+       }
        
+       /* if the fstreams object is empty use the stdin */
        if(fstreams_is_empty(fstreams))
                fstreams_add(fstreams, fstream_new(NULL, "stdin"));     
        
+       /* load the tesh files (open them) */
        fstreams_load(fstreams);
        
-       return 0;
 }
 
+/* finalize -- cleanup all the allocated objects and display the tesh usage if needed */
 static void
 finalize(void)
 {
-       if((!exit_code && want_display_usage) || (!exit_code && !prepared))
-               display_usage(exit_code);
+       /* if there is not an error and the user wants display the usage or
+        * if there is an error and all the files to load are loaded, display the usage
+        */
+       if((!exit_code && want_display_usage) || (!exit_code && !loaded))
+               display_usage();
        
+       /* delete the fstreams object */
        if(fstreams)
                fstreams_free((void**)&fstreams);
        
+       /* delete the excludes object */
        if(excludes)    
                excludes_free((void**)&excludes);
        
+       /* delete the directories object */
        if(directories)
                directories_free((void**)&directories);
-       
-       if(includes)
-               vector_free(&includes);
                
+       /* delete the root directory object */
+       if(root_directory)
+               directory_free((void**)&root_directory);
+       
+       /* delete the include directories object */
+       if(include_dirs)
+               vector_free(&include_dirs);
+       
+       /* delete the list of tesh files suffixes */    
        if(suffixes)
                lstrings_free(&suffixes);
        
+       /* delete the xbt log options list */
        if(logs)
                lstrings_free(&logs);
+               
        
-       /* destroy the semaphore used to synchronize the jobs */
+       /* destroy the semaphore used to synchronize the units */
        if(jobs_sem)
                xbt_os_sem_destroy(jobs_sem);
-
+       
+       /* destroy the semaphore used by the runner used to wait for the end of the units */
        if(units_sem)
                xbt_os_sem_destroy(units_sem);
        
        /* exit from the xbt framework */
        xbt_exit();
        
+       /* Windows specific (restore the previouse error mode */
        #ifdef WIN32
        SetErrorMode(prev_error_mode);
        #endif
@@ -525,56 +615,50 @@ finalize(void)
        if(!want_verbose && !want_dry_run && !want_silent && !want_just_display)
                INFO2("tesh terminated with exit code %d : %s",exit_code, (!exit_code ? "success" : error_to_string(exit_code)));
        
+       /* exit with the last error code */
        exit(exit_code);
 }
 
+/* init_options -- initialize the options string */
 static void
 init_options (void)
 {
        char *p;
        unsigned int i;
        
+       /* the function has been already called */
        if(optstring[0] != '\0')
-       /* déjà traité.  */
                return;
        
        p = optstring;
        
-       /* Return switch and non-switch args in order, regardless of
-       POSIXLY_CORRECT.  Non-switch args are returned as option 1.  */
        
-       /* le premier caractère de la chaîne d'options vaut -.
-        * les arguments ne correspondant pas à une option sont 
-        * manipulés comme s'ils étaient des arguments d'une option
-        *  dont le caractère est le caractère de code 1
-        */
        *p++ = '-';
        
        for (i = 0; opt_entries[i].c != '\0'; ++i)
        {
-               /* initialize le nom de l'option longue*/
+               /* initialize the long name of the option*/
                longopts[i].name = (opt_entries[i].long_name == 0 ? "" : opt_entries[i].long_name);
                
-               /* getopt_long() retourne la valeur de val */
+               /* getopt_long returns the value of val */
                longopts[i].flag = 0;
                
-               /* la valeur de l'option courte est le caractère spécifié dans  opt_entries[i].c */
+               /* the short option */
                longopts[i].val = opt_entries[i].c;
                
-               /* on l'ajoute à la chaine des optstring */
+               /* add the short option in the options string */
                *p++ = opt_entries[i].c;
                
                switch (opt_entries[i].type)
                {
-                       /* si c'est une option qui sert a positionner un flag ou que l'on doit ignorée, elle n'a pas d'argument */
+                       /* if this option is used to set a flag or if the argument must be ignored
+                        * the option has no argument
+                        */
                        case flag:
                        longopts[i].has_arg = no_argument;
                        break;
                
-                       /* c'est une option qui attent un argument : 
-                        * une chaine de caractères, un nombre flottant, 
-                        * ou un entier positif
-                        */
+                       /* the option has an argument */
                        case string:
                        case number:
                        
@@ -597,6 +681,18 @@ init_options (void)
        longopts[i].name = 0;
 }
 
+/* process_command_line --     process the command line
+ *
+ * param                                       argc the number of the arguments contained by the command line.
+ * param                                       The array of C strings containing all the arguments of the command 
+ *                                                     line.
+ *
+ * return                                      If successful, the function returns 0. Otherwise -1 is returned
+ *                                                     and sets the global variable errno to indicate the error.
+ *
+ * errors      [ENOENT]                A file name specified in the command line does not exist
+ */    
+
 static int
 process_command_line(int argc, char** argv)
 {
@@ -605,17 +701,18 @@ process_command_line(int argc, char** argv)
        directory_t directory;
        fstream_t fstream;
        
-       /* initialize the options table of tesh */
+       /* initialize the options string of tesh */
        init_options();
        
-       /* display the errors of the function getopt_long() */
+       /* let the function getopt_long display the errors if any */
        opterr = 1;
        
+       /* set option index to zero */
        optind = 0;
        
        while (optind < argc)
        {
-               c = getopt_long (argc, argv, optstring, longopts, (int *) 0);
+               c = getopt_long(argc, argv, optstring, longopts, (int *) 0);
                
                if(c == EOF)
                {
@@ -624,72 +721,54 @@ process_command_line(int argc, char** argv)
                }
                else if (c == 1)
                {
-                       /* the argument of the command line is not an option (no "-"), assume it's a tesh file */
-                       /*struct stat buffer = {0};
-                       char* prev = getcwd(NULL, 0);
+                       /* no option specified, assume it's a tesh file to run */
+                       char* path;
+                       char* delimiter;
                        
-                       directory = directories_get_back(directories);
-                       
-                       chdir(directory->name);
-                       
-                       if(stat(optarg, &buffer) || !S_ISREG(buffer.st_mode))
+                       /* getpath returns -1 when the file to get the path doesn't exist */
+                       if(getpath(optarg, &path) < 0)
                        {
-                               chdir(prev);
-                               free(prev);
-                               ERROR1("file %s not found", optarg);
-                               return EFILENOTFOUND;
+                               exit_code = errno;
+                               
+                               if(ENOENT == errno)
+                                       ERROR1("File %s does not exist", optarg);
+                               else
+                                       ERROR0("Insufficient memory is available to parse the command line : system error");
+                                       
+                               return -1;
                        }
                        
-                       chdir(prev);
-                       free(prev);*/
+                       /* get to the last / (if any) to get the short name of the file */
+                       delimiter = strrchr(optarg,'/');
                        
-                       directory = directories_search_fstream_directory(directories, optarg);
+                       /* create a new file stream which represents the tesh file to run */
+                       fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
                        
-                       if(!directory)
-                       {
-                               if(1 == directories_get_size(directories))
-                               {
-                                       ERROR1("file %s not found in the current directory",optarg);
-                                       return EFILENOTINCURDIR;
-                               }
-                               else
-                               {
-                                       ERROR1("file %s not found in the specified directories",optarg);
-                                       return EFILENOTINSPECDIR;
-                               }
-                       }
+                       free(path);
                        
-                       if(!(fstream = fstream_new(directory_get_name(directory), optarg)))
+                       /* if the list of all tesh files to run already contains this file
+                        * destroy it and display a warning, otherwise add it in the list.
+                        */
+                       if(fstreams_contains(fstreams, fstream))
                        {
-                               ERROR1("command line processing failed with the error code %d", errno);
-                               return EPROCESSCMDLINE;
+                               fstream_free((void**)&fstream);
+                               WARN1("File %s already specified to be run", optarg);
                        }
                        else
-                       {
-                               if(fstreams_contains(fstreams, fstream))
-                               {
-                                       fstream_free((void**)&fstream);
-                                       WARN1("file %s already specified", optarg);
-                               }
-                               else
-                               {
-                                       if((errno = fstreams_add(fstreams, fstream)))
-                                       {
-                                               fstream_free((void**)&fstream);
-                                               ERROR1("command line processing failed with the error code %d", errno);
-                                               return EPROCESSCMDLINE;
-                                       }
-                               }
-                       }                                       
+                               fstreams_add(fstreams, fstream);
+                               
+                       
+                               
+                       
                }
                else if (c == '?')
                {
-                       /* unknown option, getopt_long() displays the error */
-                       return 1;
+                       /* unknown option, let getopt_long() displays the error */
+                       return -1;
                }
                else
                {
-                       for (entry = opt_entries; entry->c != '\0'; ++entry)
+                       for(entry = opt_entries; entry->c != '\0'; ++entry)
                                
                                if(c == entry->c)
                                {
@@ -698,8 +777,9 @@ process_command_line(int argc, char** argv)
                                        {
                                                /* impossible */
                                                default:
-                                               ERROR0("command line processing failed : internal error");
-                                               return EPROCESSCMDLINE;
+                                               ERROR0("Command line processing failed : internal error");
+                                               exit_code = EPROCCMDLINE;
+                                               return -1;
                                                
                                                
                                                /* flag options */
@@ -720,51 +800,79 @@ process_command_line(int argc, char** argv)
                                                else if (*optarg == '\0')
                                                {
                                                        /* a non optional argument is not specified */
-                                                       ERROR2("the option %c \"%s\"requires an argument",entry->c,entry->long_name);
-                                                       return EARGNOTSPEC;
+                                                       ERROR2("Option %c \"%s\"requires an argument",entry->c,entry->long_name);
+                                                       exit_code = ENOARG;
+                                                       return -1;
                                                }
                                                
-                                               /* --directory option */
-                                               if(!strcmp(entry->long_name,"directory"))
+                                               /* --load-directory option */
+                                               if(!strcmp(entry->long_name,"load-directory"))
                                                {
-                                                       if(!(directory = directory_new(optarg, want_load_directory)))
+                                                       char* path;
+                                                       
+                                                       if(translatepath(optarg, &path) < 0)
                                                        {
+                                                               exit_code = errno;
+                                                               
                                                                if(ENOTDIR == errno)
-                                                               {
-                                                                       ERROR1("directory %s not found",optarg);
-                                                                       return EDIRNOTFOUND;
-                                                               }
+                                                                       ERROR1("%s is not a directory",optarg);
                                                                else
-                                                               {
-                                                                       ERROR1("command line processing failed with the error code %d", errno);
-                                                                       return EPROCESSCMDLINE;
-                                                               }
+                                                                       ERROR0("Insufficient memory is available to process the command line - system error");
+                                                                       
+                                                               return -1;
+                                                               
                                                        }
                                                        else
                                                        {
+                                                               directory = directory_new(path);
+                                                               free(path);
+                                               
                                                                if(directories_contains(directories, directory))
                                                                {
                                                                        directory_free((void**)&directory);
-                                                                       WARN1("directory %s already specified",optarg);
+                                                                       WARN1("Directory %s already specified to be load",optarg);
                                                                }
                                                                else
-                                                               {
-                                                                       if((errno = directories_add(directories, directory)))
-                                                                       {
-                                                                               directory_free((void**)&directory);
-                                                                               ERROR1("command line processing failed with the error code %d", errno);
-                                                                               return EPROCESSCMDLINE;
-                                                                       }
-                                                               }
+                                                                        directories_add(directories, directory);
+                                                                        
+                                                               
                                                        }                       
                                                }
+                                               else if(!strcmp(entry->long_name,"directory"))
+                                               {
+                                                       char* path ;
+                                                       
+                                                       if(translatepath(optarg, &path) < 0)
+                                                       {
+                                                               exit_code = errno;
+                                                               
+                                                               if(ENOTDIR == errno)
+                                                                       ERROR1("%s is not a directory",optarg);
+                                                               else
+                                                                       ERROR0("Insufficient memory is available to process the command line - system error");
+                                                                       
+                                                               return -1;
+                                                       }
+                                                       else
+                                                       {
+                                                               if(!dont_want_display_directory)
+                                                                       INFO1("Entering directory \"%s\"",path);
+                                                               
+                                                               chdir(path);
+                                                               free(path);
+                                                               
+                                                               
+                                                       }       
+                                               }
+                                               
                                                /* --suffix option */
                                                else if(!strcmp(entry->long_name,"suffix"))
                                                {
                                                        if(strlen(optarg) > MAX_SUFFIX)
                                                        {
-                                                               ERROR1("suffix %s too long",optarg);
-                                                               return ESUFFIXTOOLONG;  
+                                                               ERROR1("Suffix %s too long",optarg);
+                                                               exit_code = ESUFFIXTOOLONG;     
+                                                               return -1;
                                                        }
                                                        
                                                        if(optarg[0] == '.')
@@ -773,14 +881,14 @@ process_command_line(int argc, char** argv)
                                                                sprintf(suffix,".%s",optarg);
                                                                
                                                                if(lstrings_contains(suffixes, suffix))
-                                                                       WARN1("suffix %s already specified", optarg);
+                                                                       WARN1("Suffix %s already specified to be used", optarg);
                                                                else
                                                                        lstrings_push_back(suffixes, suffix);
                                                        }
                                                        else
                                                        {
                                                                if(lstrings_contains(suffixes, optarg))
-                                                                       WARN1("suffix %s already specified", optarg);
+                                                                       WARN1("Suffix %s already specified to be used", optarg);
                                                                else
                                                                        lstrings_push_back(suffixes, optarg);   
                                                        }
@@ -788,135 +896,100 @@ process_command_line(int argc, char** argv)
                                                /* --file option */
                                                else if(!strcmp(entry->long_name,"file"))
                                                {
+                                                       char* path;
+                                                       char* delimiter;
                                                        
-                                                       /* the argument of the command line is not an option (no "-"), assume it's a tesh file */
-                                                       /*struct stat buffer = {0};
-                                                       char* prev = getcwd(NULL, 0);
-                                                       
-                                                       directory = directories_get_back(directories);
-                                                       
-                                                       chdir(directory->name);
-                       
-                                                       if(stat(optarg, &buffer) || !S_ISREG(buffer.st_mode))
+                                                       if(getpath(optarg, &path) < 0)
                                                        {
-                                                               chdir(prev);
-                                                               free(prev);
-                                                               ERROR1("file %s not found", optarg);
-                                                               return EFILENOTFOUND;
+                                                               exit_code = errno;
+                                                               
+                                                               if(ENOENT == errno)
+                                                                       ERROR1("File %s does not exist", optarg);
+                                                               else
+                                                                       ERROR0("Insufficient memory is available to process the command line - system error");
+                                                               
+                                                               return -1;
                                                        }
                                                        
-                                                       chdir(prev);
-                                                       free(prev);*/
+                                                       delimiter = strrchr(optarg,'/');
                                                        
-                                                       directory = directories_search_fstream_directory(directories, optarg);
-                       
-                                                       if(!directory)
-                                                       {
-                                                               if(1 == directories_get_size(directories))
-                                                               {
-                                                                       ERROR1("file %s not found in the current directory",optarg);
-                                                                       return EFILENOTINCURDIR;
-                                                               }
-                                                               else
-                                                               {
-                                                                       ERROR1("file %s not found in the specified directories",optarg);
-                                                                       return EFILENOTINSPECDIR;
-                                                               }
-                                                       }
+                                                       fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
                                                        
-                                                       if(!(fstream = fstream_new(directory_get_name(directory),optarg)))
+                                                       free(path);
+                                                       
+                                                       if(fstreams_contains(fstreams, fstream))
                                                        {
-                                                               ERROR1("command line processing failed with the error code %d", errno);
-                                                               return EPROCESSCMDLINE;
+                                                               fstream_free((void**)&fstream);
+                                                               WARN1("File %s already specified to run", optarg);
                                                        }
                                                        else
-                                                       {
-                                                               if(fstreams_contains(fstreams, fstream))
-                                                               {
-                                                                       fstream_free((void**)&fstream);
-                                                                       WARN1("file %s already specified", optarg);
-                                                               }
-                                                               else
-                                                               {
-                                                                       if((errno = fstreams_add(fstreams, fstream)))
-                                                                       {
-                                                                               fstream_free((void**)&fstream);
-                                                                               ERROR1("command line processing failed with the error code %d", errno);
-                                                                               return EPROCESSCMDLINE;
-                                                                       }
-                                                               }
-                                                       }               
+                                                               fstreams_add(fstreams, fstream);
                                                }
                                                /* --include-dir option */
                                                else if(!strcmp(entry->long_name,"include-dir"))
                                                {
-                                                       if(!(directory = directory_new(optarg, want_load_directory)))
+                                                       
+                                                       char* path ;
+                                                       
+                                                       if(translatepath(optarg, &path) < 0)
                                                        {
+                                                               exit_code = errno;
+                                                               
                                                                if(ENOTDIR == errno)
-                                                               {
                                                                        ERROR1("%s is not a directory",optarg);
-                                                                       return EDIRNOTFOUND;
-                                                               }
                                                                else
-                                                               {
-                                                                       ERROR1("command line processing failed with the error code %d", errno);
-                                                                       return EPROCESSCMDLINE;
-                                                               }
+                                                                       ERROR0("Insufficient memory is available to process the command line - system error");
+                                                                       
+                                                               return -1;
                                                        }
                                                        else
                                                        {
-                                                               if(vector_contains(includes, directory))
+                                                       
+                                                               directory = directory_new(path);
+                                                               free(path);
+                                                       
+                                                               if(vector_contains(include_dirs, directory))
                                                                {
                                                                        directory_free((void**)&directory);
-                                                                       WARN1("include directory %s already specified",optarg);
+                                                                       WARN1("Include directory %s already specified to be used",optarg);
                                                                        
                                                                }
                                                                else
-                                                               {
-                                                                       if((errno = vector_push_back(includes, directory)))
-                                                                       {
-                                                                               directory_free((void**)&directory);
-                                                                               ERROR1("command line processing failed with the error code %d", errno);
-                                                                               return EPROCESSCMDLINE;
-                                                                       }
-                                                               }
+                                                                       vector_push_back(include_dirs, directory);
                                                        }
                                                }
                                                /* --exclude option */ 
                                                else if(!strcmp(entry->long_name,"exclude"))
                                                {
-                                                       directory = directories_get_back(directories);
                                                        
-                                                       if(!(fstream = fstream_new(directory_get_name(directory), optarg)))
+                                                       char* path;
+                                                       char* delimiter;
+                       
+                                                       if(getpath(optarg, &path) < 0)
                                                        {
+                                                               exit_code = errno;
+                                                               
                                                                if(ENOENT == errno)
-                                                               {
-                                                                       ERROR1("file to exclude %s not found", optarg);
-                                                                       return EFILENOTFOUND;
-                                                               }
+                                                                       ERROR1("file %s does not exist", optarg);
                                                                else
-                                                               {
-                                                                       ERROR1("command line processing failed with the error code %d", errno);
-                                                                       return EPROCESSCMDLINE;
-                                                               }
+                                                                       ERROR0("Insufficient memory is available to process the command line - system error");
+                                                                       
+                                                               return -1;
                                                        }
-                                                       else
+                       
+                                                       delimiter = strrchr(optarg,'/');
+                       
+                                                       fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
+                                                       free(path);
+                       
+                                                       if(excludes_contains(excludes, fstream))
                                                        {
-                                                               if(excludes_contains(excludes, fstream))
-                                                               {
-                                                                       fstream_free((void**)&fstream);
-                                                                       WARN1("file to exclude %s already specified", optarg);
-                                                               }
-                                                               else
-                                                               {
-                                                                       if((errno = excludes_add(excludes, fstream)))
-                                                                       {
-                                                                               fstream_free((void**)&fstream);
-                                                                               ERROR1("command line processing failed with the error code %d", errno);
-                                                                               return EPROCESSCMDLINE;
-                                                                       }
-                                                               }
-                                                       }                               
+                                                               fstream_free((void**)&fstream);
+                                                               WARN1("File %s already specified to be exclude", optarg);
+                                                       }
+                                                       else
+                                                               excludes_add(excludes, fstream);
+                                                                       
                                                }
                                                /* --log option */
                                                else if(!strcmp(entry->long_name,"log"))
@@ -925,7 +998,8 @@ process_command_line(int argc, char** argv)
                                                }
                                                else
                                                {
-                                                       /* TODO */
+                                                       INFO1("Unexpected option %s", optarg);
+                                                       return -1;
                                                }
                                                
                                                
@@ -953,8 +1027,9 @@ process_command_line(int argc, char** argv)
                
                                                        if (i < 1 || cp[0] != '\0')
                                                        {
-                                                               ERROR2("option %c \"%s\" requires an strictly positive integer as argument",entry->c, entry->long_name);
-                                                               return ENOTPOSITIVENUM;
+                                                               ERROR2("Option %c \"%s\" requires an strictly positive integer as argument",entry->c, entry->long_name);
+                                                               exit_code = ENOTPOSITIVENUM;
+                                                               return -1;
                                                        }
                                                        else
                                                                *(int*)entry->value = i;
@@ -975,7 +1050,7 @@ process_command_line(int argc, char** argv)
 }
 
 static void
-display_usage(int exit_code)
+display_usage(void)
 {
        const char **cpp;
        FILE* stream;
index 29b1c95..4b962a7 100644 (file)
@@ -15,6 +15,7 @@ reader_new(command_t command)
        reader->command = command;
        reader->broken_pipe = 0;
        reader->failed = 0;
+       reader->done = 0;
        
        reader->started = xbt_os_sem_init(0);
        
@@ -127,9 +128,7 @@ reader_start_routine(void* p)
                command_handle_failure(command, csr_read_failure);
        }
        
-       reader->broken_pipe = 1;
-       
-       /*printf("the reader of the command %p is ended\n",command);*/
+       reader->done = 1;
        
        return NULL;
 } 
index aeec092..d71d459 100644 (file)
@@ -1,13 +1,20 @@
 #include <runner.h>
 #include <units.h>
+#include <unit.h>
 #include <error.h>
+#include <variable.h>
 
 #include <errno.h>     /* for error code       */
 #include <stdlib.h>    /* for calloc()         */
-#include <stdio.h>     
+#include <stdio.h>
+
+#include <sys/resource.h>      
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
 
+extern char**
+environ;
+
 /* the unique tesh runner */
 static runner_t
 runner = NULL;
@@ -24,7 +31,7 @@ runner_start_routine(void* p);
  * the want_check_syntax is specified. Returns
  * 0 if the syntax is clean.
  */
-static int
+static void
 check_syntax(void);
 
 #ifdef WIN32
@@ -96,19 +103,19 @@ int
 runner_init(int want_check_syntax, int timeout, fstreams_t fstreams)
 {
        
-       if(runner)
-       {
-               ERROR0("Runner is already initialized");
-               return EEXIST;
-       }
-               
+       int i;
+       char* val;
+       char buffer[MAX_PATH + 1] = {0};
+       int code;
+       const char* cstr;
+       variable_t variable;
                
-       runner = xbt_new0(s_runner_t, 1);
+       if(!(runner = (runner_t)calloc(1, sizeof(s_runner_t))))
+               return errno;
+       
        
        if(!(runner->units = units_new(runner, fstreams)))
        {
-               ERROR0("Runner initialization failed");
-               
                free(runner);
                runner = NULL;
                return errno;
@@ -121,13 +128,60 @@ runner_init(int want_check_syntax, int timeout, fstreams_t fstreams)
        runner->number_of_runned_units = 0;
        runner->waiting = 0;
        
-       if(want_check_syntax)
+       runner->total_of_tests = 0;
+       runner->total_of_successeded_tests = 0;
+       runner->total_of_failed_tests = 0;
+       runner->total_of_interrupted_tests = 0;
+       
+       runner->total_of_units = 0;
+       runner->total_of_successeded_units = 0;
+       runner->total_of_failed_units = 0;
+       runner->total_of_interrupted_units = 0;
+       
+       runner->total_of_suites = 0;
+       runner->total_of_successeded_suites = 0;
+       runner->total_of_failed_suites = 0;
+       runner->total_of_interrupted_suites = 0;
+       
+       /* initialize the vector of variables */
+       runner->variables = vector_new(32, (fn_finalize_t)variable_free);
+       
+       
+       for(i = 0; environ[i] != NULL; i++)
+       {
+               val = strchr(environ[i], '=');
+               
+               if(val)
+               {
+                       val++;
+                               
+                       if(val[0] != '\0')
+                               strncpy(buffer, environ[i], (val - environ[i] -1));
+                       
+                       variable = variable_new(buffer, val);
+                       variable->env = 1;
+                       
+                       /*printf("Add the environment variable %s %s\n", variable->name, variable->val);*/
+                       
+                       vector_push_back(runner->variables, variable);
+               }
+       }
+       
+       i = 0;
+       
+       while((cstr = error_get_at(i++, &code)))
        {
-               if((errno = check_syntax()))
-                       return errno;           
+               sprintf(buffer,"%d",code);
+               variable = variable_new(cstr, buffer);
+               variable->err = 1;
+               vector_push_back(runner->variables, variable);
        }
+       
+       
+       if(want_check_syntax)
+               check_syntax();
                
-       return 0;
+       return exit_code;
                
 }
 
@@ -135,6 +189,8 @@ void
 runner_destroy(void)
 {
        units_free((void**)(&(runner->units)));
+       vector_free(&runner->variables);
+       
 
        #ifdef WIN32
        CloseHandle(timer_handle);
@@ -202,29 +258,85 @@ runner_interrupt(void)
 void
 runner_display_status(void)
 {
+       
        if(!want_dry_run)
        {
+               struct rusage r_usage;
                
-               /*unit_t unit;*/
-       
-               printf("Runner\n");
-               printf("Status informations :\n");
-       
-               printf("    number of units     %d\n",units_get_size(runner->units));
-               printf("    exit code           %d (%s)\n",exit_code, exit_code ? error_to_string(exit_code) : "success");
+               /*printf("\033[1m");*/
+               printf("\n  TEst SHell utility - mini shell specialized in running test units.\n");
+               printf(" =============================================================================\n");
+               /*printf("\033[0m");*/
                
                units_verbose(runner->units);
+               
+               /*printf("\033[1m");*/
+               printf(" =====================================================================%s\n",
+               runner->total_of_failed_tests ? "== FAILED": (runner->total_of_interrupted_tests || runner->total_of_interrupted_units) ? "==== INTR" : "====== OK");
+               
+               printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",
+               (runner->total_of_suites ? (1-((double)runner->total_of_failed_suites + (double)runner->total_of_interrupted_suites)/(double)runner->total_of_suites)*100.0 : 100.0),
+               runner->total_of_suites, runner->total_of_successeded_suites);
+               
+               if(runner->total_of_failed_suites > 0)
+                       printf(", %d failed", runner->total_of_failed_suites);
+               
+               if(runner->total_of_interrupted_suites > 0)
+                       printf(", %d interrupted)", runner->total_of_interrupted_suites);
+               
+               printf(")\n");  
+               
+               printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",
+               (runner->total_of_units ? (1-((double)runner->total_of_failed_units + (double)runner->total_of_interrupted_units)/(double)runner->total_of_units)*100.0 : 100.0),
+               runner->total_of_units, runner->total_of_successeded_units);
+               
+               if(runner->total_of_failed_units > 0)
+                       printf(", %d failed", runner->total_of_failed_units);
+               
+               if(runner->total_of_interrupted_units > 0)
+                       printf(", %d interrupted)", runner->total_of_interrupted_units);
+               
+               printf(")\n");
+               
+               printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",
+               (runner->total_of_tests ? (1-((double)runner->total_of_failed_tests + (double)runner->total_of_interrupted_tests)/(double)runner->total_of_tests)*100.0 : 100.0),
+               runner->total_of_tests, runner->total_of_successeded_tests); 
+               
+               if(runner->total_of_failed_tests > 0)
+                       printf(", %d failed", runner->total_of_failed_tests);
+               
+               if(runner->total_of_interrupted_tests > 0)
+                       printf(", %d interrupted)", runner->total_of_interrupted_tests);
+               
+               printf(")\n\n");
+               
+               
+               if(!getrusage(RUSAGE_SELF, &r_usage))
+               {
+               
+                       printf("         Total tesh user time used:       %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
+                       printf("         Total tesh system time used:     %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
+               
+                       if(!getrusage(RUSAGE_CHILDREN, &r_usage))
+                       {
+                               printf("         Total children user time used:   %ld second(s) %ld microsecond(s)\n", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec);
+                               printf("         Total children system time used: %ld second(s) %ld microsecond(s)\n\n", r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec);
+               
+                       }       
+               }
+               
+               /*printf("\033[0m");*/
        }
        else
        {
                if(exit_code)
                        ERROR0("Syntax error detected");
-               else if(exit_code == 0)
+               else if(!exit_code)
                        INFO0("Syntax 0K");
        }
 }
 
-static int
+static void
 check_syntax(void)
 {
        if(!want_dry_run)
@@ -235,7 +347,7 @@ check_syntax(void)
        
                want_dry_run = 0;
                
-               if(0 == exit_code)
+               if(!exit_code)
                {
                        if(!want_silent)
                                INFO0("syntax checked (OK)");
@@ -250,5 +362,4 @@ check_syntax(void)
                WARN0("mismatch in the syntax : --just-check-syntax and --check-syntax options at same time");
        }
 
-       return exit_code;
 }
index 1f540d6..fefd585 100644 (file)
@@ -3,18 +3,49 @@
 #include <command.h>
 #include <context.h>
 #include <fstream.h>
-
-
+#include <variable.h>
+#include <str_replace.h>
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
 
+static void
+replace_variables(unit_t unit, char** line)
+{
+       variable_t variable;
+       char name[MAX_PATH + 1] = {0};
+       
+       /* check if some commands have setted some environment variables */
+       /* TODO */
+       
+       /*printf("repalce all the variables of the line %s\n", *line);*/
+       
+       
+       xbt_os_mutex_acquire(unit->mutex);
+       
+       vector_rewind(unit->runner->variables);
+       
+       while((variable = vector_get(unit->runner->variables)))
+       {
+               sprintf(name, "$%s", variable->name);
+               /*printf("try to replace all the variable %s\n",name);*/
+               str_replace_all(line, name, variable->val);
+               
+               vector_move_next(unit->runner->variables);
+               memset(name, 0, MAX_PATH + 1);
+       }
+       
+       xbt_os_mutex_release(unit->mutex);
+       
+       /*printf("line after the variables replacement %s\n",*line);*/
+       
+}
 
 /* the unit thread start routine */
 static void*
 unit_start(void* p);
 
 unit_t
-unit_new(runner_t runner, suite_t owner, fstream_t fstream)
+unit_new(runner_t runner, unit_t root, unit_t owner, fstream_t fstream)
 {
        unit_t unit = xbt_new0(s_unit_t, 1);
 
@@ -26,6 +57,7 @@ unit_new(runner_t runner, suite_t owner, fstream_t fstream)
        unit->sem = NULL;
 
        unit->commands = vector_new(DEFAULT_COMMANDS_CAPACITY, (fn_finalize_t)command_free);
+       unit->includes = vector_new(DEFAULT_INCLUDES, (fn_finalize_t)unit_free);
        
        unit->thread = NULL;
 
@@ -34,6 +66,7 @@ unit_new(runner_t runner, suite_t owner, fstream_t fstream)
        unit->number_of_failed_commands = 0;
        unit->number_of_successeded_commands = 0;
        unit->number_of_terminated_commands = 0;
+       unit->number_of_waiting_commands = 0;
        unit->interrupted = 0;
        unit->failed = 0;
        unit->successeded = 0;
@@ -43,21 +76,27 @@ unit_new(runner_t runner, suite_t owner, fstream_t fstream)
        
        
        unit->owner = owner;
+       
+       unit->root = root ?  root : unit;
+       
+       
        unit->number = 0;
-       unit->suites = vector_new(DEFAULT_COMMANDS_CAPACITY, (fn_finalize_t)suite_free);
+       unit->suites = vector_new(DEFAULT_SUITES_CAPACITY, (fn_finalize_t)unit_free);
        unit->owner = owner;
        
        unit->running_suite = 0;
+       unit->is_suite = 0;
+       unit->description = NULL;
 
        return unit;
 
 }
 
-void
+/*void
 unit_add_suite(unit_t unit, suite_t suite)
 {
        vector_push_back(unit->suites, suite);
-}
+}*/
 
 int
 unit_free(void** unitptr)
@@ -66,13 +105,17 @@ unit_free(void** unitptr)
        
        vector_free(&((*__unitptr)->commands));
        
+       vector_free(&((*__unitptr)->includes));
+       
        vector_free(&((*__unitptr)->suites));
        
        /* if the unit is interrupted during its run, the semaphore is NULL */
        if((*__unitptr)->sem)
                xbt_os_sem_destroy((*__unitptr)->sem);
                
-               
+       if((*__unitptr)->description)
+               free((*__unitptr)->description);
+       
        free((*__unitptr)->suites);
 
        free(*__unitptr);
@@ -88,10 +131,11 @@ unit_start(void* p)
        
        xbt_os_thread_t thread;
        xbt_os_mutex_t mutex;
-       context_t context;
-       int i;
+       /*context_t context;*/
+       int i, j;
 
        unit_t unit = (unit_t)p;
+       unit_t include;
        
        xbt_os_mutex_acquire(unit->mutex);
        unit->runner->number_of_runned_units++;
@@ -101,17 +145,22 @@ unit_start(void* p)
        xbt_os_sem_acquire(jobs_sem);
        
        mutex = xbt_os_mutex_init();
-       context = context_new();
+       /*context = context_new();*/
        
        if(want_dry_run)
                INFO1("checking unit %s...",unit->fstream->name); 
        
        /* parse the file */
-       unit_parse(unit, context, mutex, unit->fstream->name, unit->fstream->stream);
+       /*unit_parse(unit, context, mutex, unit->fstream->name, unit->fstream->stream);*/
+       
+       fstream_parse(unit->fstream, unit, mutex);
+       
        
        /* if the unit is not interrupted and not failed the unit, all the file is parsed
         * so all the command are launched
         */
+        
+       
        if(!unit->interrupted)
        {
                unit->parsed = 1;
@@ -120,37 +169,86 @@ unit_start(void* p)
                 * so the unit release the semaphore itself
                 */
                if(!unit->released && (unit->number_of_started_commands == (unit->number_of_failed_commands + unit->number_of_interrupted_commands + unit->number_of_successeded_commands)))
+               {
+                       /*INFO1("the unit %s is released", unit->fstream->name);*/
                        xbt_os_sem_release(unit->sem);  
+               }
+               else
+               {
+                       
+                       INFO1("the unit %s is not released", unit->fstream->name);
+                       INFO1("number of started commands %d", unit->number_of_started_commands);
+                       INFO1("number of failed commands %d", unit->number_of_failed_commands);
+                       INFO1("number of interrupted commands %d", unit->number_of_interrupted_commands);
+                       INFO1("number of successeded commands %d", unit->number_of_successeded_commands);
+                       INFO1("number of waiting commands %d", unit->number_of_waiting_commands);
+                       
+                       
+                       if(unit->number_of_waiting_commands)
+                       {
+                               command_t command;
+                               int i, j;
+       
+                               for(i = 0; i < vector_get_size(unit->includes) ; i++)
+                               {
+                                       include = vector_get_at(unit->includes, i);
+                               
+                                       for(j = 0; j < vector_get_size(include->commands); j++)
+                                       {
+                                               command = vector_get_at(include->commands, j);
+                                               
+                                               if(command->status == cs_in_progress)
+                                               {
+                                                       INFO2("the command %s PID %d is in process", command->context->command_line, command->pid);
+                                                       
+                                                       if(command->writer->done)
+                                                               INFO2("the writer of the command %s PID %d done", command->context->command_line, command->pid);        
+                                                       else
+                                                               INFO2("the writer of the command %s PID %d  doesn't done", command->context->command_line, command->pid);
+                                               }
+                                       }
+                                       
+                               }
+                       }
+               }
                
        }
        
        /* wait the end of all the commands or a command failure or an interruption */
-       
-       
        xbt_os_sem_acquire(unit->sem);
        
+       
        if(unit->interrupted)
        {
                command_t command;
-
+               
                /* interrupt all the running commands of the unit */ 
-               for(i = 0; i < unit->number_of_commands; i++)
+               for(i = 0; i < vector_get_size(unit->commands); i++)
                {
-                       /*command = unit->commands[i];*/
                        command = vector_get_at(unit->commands, i);
 
                        if(command->status == cs_in_progress)
-                               /*command_interrupt(unit->commands[i]);*/
                                command_interrupt(command);
                }
+               
+               for(i = 0; i < vector_get_size(unit->includes); i++)
+               {
+                       include = vector_get_at(unit->includes, i);
+                       
+                       for(j = 0; j < vector_get_size(include->commands); j++)
+                       {
+                               command = vector_get_at(include->commands, j);
+
+                               if(command->status == cs_in_progress)
+                                       command_interrupt(command);
+                       }
+               }
+               
        }
        
-
        /* wait the end of the threads */
-       for(i = 0; i < unit->number_of_commands; i++)
+       for(i = 0; i < vector_get_size(unit->commands); i++)
        {
-               /*thread = unit->commands[i]->thread;*/
-               
                command_t command = vector_get_at(unit->commands, i);
                thread = command->thread;
                
@@ -158,10 +256,25 @@ unit_start(void* p)
                        xbt_os_thread_join(thread,NULL);
        }
        
-       context_free(&context);
-
+       for(i = 0; i < vector_get_size(unit->includes); i++)
+       {
+               include = vector_get_at(unit->includes, i);
+               
+               for(j = 0; j < vector_get_size(include->commands); j++)
+               {
+                       command_t command = vector_get_at(include->commands, j);
+                       thread = command->thread;
+               
+                       if(thread)
+                               xbt_os_thread_join(thread,NULL);
+               }
+       }
+       
+       /*context_free(&context);*/
+       
        xbt_os_mutex_destroy(mutex);
        
+       
        xbt_os_mutex_acquire(unit->mutex);
 
        /* increment the number of ended units */
@@ -175,11 +288,12 @@ unit_start(void* p)
 
                /* first release the mutex */
                xbt_os_mutex_release(unit->mutex);
+               
                xbt_os_sem_release(units_sem);
        }
        else
                xbt_os_mutex_release(unit->mutex);
-
+       
        /* release the jobs semaphore, then the next unit can start */
        xbt_os_sem_release(jobs_sem);
        
@@ -236,6 +350,11 @@ unit_parse(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* fil
                                unit_handle_failure(unit);
                                break;
                        }
+                       else if(unit->running_suite)
+                       {
+                               /* TODO */
+                       }
+                                       
                        
                        if(context->command_line)
                        {
@@ -309,13 +428,20 @@ unit_parse(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* fil
        xbt_strbuff_free(buff); 
 }
 
+
+
 void 
 unit_handle_line(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char * filepos, char *line) 
 {
+       char* line2;
        /* Search end */
        xbt_str_rtrim(line+2,"\n");
        
-       switch (line[0]) 
+       line2 = strdup(line);
+       
+       replace_variables(unit, &line2);
+       
+       switch (line2[0]) 
        {
                case '#': 
                break;
@@ -323,17 +449,18 @@ unit_handle_line(unit_t unit, context_t context, xbt_os_mutex_t mutex, const cha
                case '$':
                case '&':
                        
-               context->async = (line[0] == '&');
+               context->async = (line2[0] == '&');
                
                /* further trim useless chars which are significant for in/output */
-               xbt_str_rtrim(line+2," \t");
+               xbt_str_rtrim(line2+2," \t");
                
                /* Deal with CD commands here, not in rctx */
-               if (!strncmp("cd ",line+2,3)) 
+               if(!strncmp("cd ",line2 + 2, 3)) 
                {
-                       char *dir=line+4;
-               
-                       if (context->command_line)
+                       /*char *dir=line2+4; */
+                       char* dir = strdup(line2 + 4);
+                       
+                       if(context->command_line)
                        {
                                if(!want_dry_run)
                                {
@@ -351,12 +478,10 @@ unit_handle_line(unit_t unit, context_t context, xbt_os_mutex_t mutex, const cha
                        
                        VERB1("Saw cd '%s'",dir);
                        
-                       /*if(want_dry_run)
-                       {
-                               unit->number_of_successeded_commands++;
-                       }*/
+                       
                        if(!want_dry_run)
                        {
+                       
                                if(chdir(dir))
                                {
                                        ERROR2("Chdir to %s failed: %s",dir,strerror(errno));
@@ -364,39 +489,50 @@ unit_handle_line(unit_t unit, context_t context, xbt_os_mutex_t mutex, const cha
                                        exit_code = ECHDIR;
                                        unit_handle_failure(unit);
                                }
+                               
+                               
                        }
                        
                        break;
                } /* else, pushline */
                else
                {
-                       unit_pushline(unit, context, mutex, filepos, line[0], line+2 /* pass '$ ' stuff*/);
+                       unit_pushline(unit, context, mutex, filepos, line2[0], line2+2 /* pass '$ ' stuff*/);
                        break;
                }
                
                case '<':
                case '>':
                case '!':
-               unit_pushline(unit, context, mutex, filepos, line[0], line+2 /* pass '$ ' stuff*/);    
+               unit_pushline(unit, context, mutex, filepos, line2[0], line2+2 /* pass '$ ' stuff*/);    
                break;
                
                case 'p':
                if(!want_dry_run)
-                       INFO2("[%s] %s",filepos,line+2);
+                       INFO2("[%s] %s",filepos,line2+2);
                break;
                
                case 'P':
                if(!want_dry_run)
-                       CRITICAL2("[%s] %s",filepos,line+2);
+                       CRITICAL2("[%s] %s",filepos,line2+2);
+               break;
+               
+               case 'D':
+                       if(unit->description)
+                               WARN2("description already specified %s %s", filepos, line2); 
+                       else
+                               unit->description = strdup(line2 + 2);
                break;
                
                default:
-               ERROR2("[%s] Syntax error: %s",filepos, line);
+               ERROR2("[%s] Syntax error: %s",filepos, line2);
                ERROR1("Test suite `%s': NOK (syntax error)",unit->fstream->name);
                exit_code = ESYNTAX;
                unit_handle_failure(unit);
                break;
        }
+       
+       free(line2);
 }
 
 void 
@@ -540,23 +676,292 @@ unit_pushline(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char*
                        VERB1("[%s] (ignore output of next command)", filepos);
                
                } 
-               else if(!strncmp(line,"include", strlen("include")))
+               else if(!strncmp(line,"include ", strlen("include ")))
                {
-                       unit_handle_include(unit, context, mutex, line + strlen("include "));
+                       char* p1;
+                       char* p2;
+                       
+                       p1 = line + strlen("include");
+                       
+                       while(*p1 == ' ' || *p1 == '\t')
+                               p1++;
+                               
+                       
+                       if(p1[0] == '\0')
+                       {
+                               
+                               exit_code = ESYNTAX;
+                               ERROR1("include file not specified %s ", filepos);
+                               unit_handle_failure(unit);
+                       }
+                       else
+                       {
+                               char file_name[MAX_PATH + 1] = {0};
+                               
+                               /*INFO1("p1 is %s",p1);*/
+                               
+                               p2 = p1;
+                               
+                               while(*p2 != '\0' && *p2 != ' ' && *p2 != '\t')
+                               {
+                                       /*INFO1("p2 is %s",p2);*/
+                                       p2++;
+                                       
+                               }
+                               /*INFO1("p2 is %s",p2);*/
+                                       
+                               strncpy(file_name, p1, p2 - p1);
+                               
+                               /*INFO1("filename is %s", file_name);*/
+                               
+                               if(p2[0] != '\0')
+                                       while(*p2 == ' ' || *p2 == '\t')
+                                               p2++;
+                                       
+                               unit_handle_include(unit, context, mutex, file_name, p2[0] != '\0' ? p2 : NULL);
+                               
+                       }
                }
-               
-               else if(!strncmp(line,"suite", strlen("suite")))
+               else if(!strncmp(line,"suite ", strlen("suite ")))
                {
                        unit_handle_suite(unit, context, mutex, line + strlen("suite "));
                }
-               else 
+               else if(!strncmp(line,"unsetenv ", strlen("unsetenv ")))
+               {
+                       int i;
+                       int number_of_variables;
+                       int exists = 0;
+                       int env;
+                       variable_t variable;
+                       char* name = line + strlen("unsetenv ");
+                       
+                       xbt_os_mutex_acquire(unit->mutex);
+                       
+                       number_of_variables = vector_get_size(unit->runner->variables);
+                       
+                       for(i = 0; i < number_of_variables; i++)
+                       {
+                               variable = vector_get_at(unit->runner->variables, i);
+                               
+                               if(!strcmp(variable->name, name))
+                               {
+                                       env = variable->env;
+                                       exists = 1;
+                                       break;
+                               }
+                       }
+                               
+                       if(env)
+                       {
+                               if(exists)
+                                       vector_erase_at(unit->runner->variables, i);
+                               else
+                                       WARN3("environment variable %s not found %s %s", name, line, filepos);  
+                       }
+                       else
+                       {
+                               if(exists)
+                                       WARN3("%s is an not environment variable use unset metacommand to delete it %s %s", name, line, filepos);
+                               else
+                                       WARN3("%s environment variable not found %s %s", name, line, filepos);
+                       }
+                       
+                       xbt_os_mutex_release(unit->mutex);      
+                       
+                               
+               }
+               else if(!strncmp(line,"setenv ", strlen("setenv ")))
+               {
+                       char* val;
+                       char name[MAX_PATH + 1] = {0};
+                       char* p;
+                       
+                       p = line + strlen("setenv ");
+                       
+                       val = strchr(p, '=');
+                       
+                       if(val)
+                       {
+                               variable_t variable;
+                               int exists = 0;
+                               int env = 0;
+                               val++;
+                               
+                               /* syntax error */
+                               if(val[0] == '\0')
+                               {
+                                       
+                                       exit_code = ESYNTAX;
+                                       ERROR2("indefinite variable value %s %s", line, filepos);
+                                       unit_handle_failure(unit);      
+                               }
+                               
+                               
+                               
+                               strncpy(name, p, (val - p -1));
+                               
+                               /* test if the variable is already registred */
+                               
+                               xbt_os_mutex_acquire(unit->mutex);
+                               
+                               vector_rewind(unit->runner->variables);
+                               
+                               while((variable = vector_get(unit->runner->variables)))
+                               {
+                                       
+                                       if(!strcmp(variable->name, name))
+                                       {
+                                               variable->env = 1;
+                                               exists = 1;
+                                               break;
+                                       }
+                                       
+                                       vector_move_next(unit->runner->variables);
+                               }
+                               
+                               /* if the variable is already registred, update its value;
+                                * otherwise register it.
+                                */
+                               if(exists)
+                               {
+                                       if(env)
+                                       {
+                                               free(variable->val);
+                                               variable->val = strdup(val);
+                                               setenv(variable->name, variable->val, 1);
+                                       }
+                                       else
+                                               WARN3("%s variable already exists %s %s", name, line, filepos); 
+                               }
+                               else
+                               {
+                                       variable = variable_new(name, val);
+                                       variable->env = 1;
+                                       
+                                       vector_push_back(unit->runner->variables, variable);
+                                       
+                                       setenv(variable->name, variable->val, 0);
+                               }
+                               
+                               xbt_os_mutex_release(unit->mutex);
+                               
+                       }
+               }
+               else if(!strncmp(line,"unset ", strlen("unset ")))
                {
-                       ERROR2("%s: Malformed metacommand: %s",filepos,line);
-                       ERROR1("Test suite `%s': NOK (syntax error)",unit->fstream->name);
-                       exit_code = ESYNTAX;
-                       unit_handle_failure(unit);
-                       return;
+                       int i;
+                       int number_of_variables;
+                       int exists = 0;
+                       int env;
+                       int err;
+                       variable_t variable;
+                       char* name = line + strlen("unset ");
+                       
+                       xbt_os_mutex_acquire(unit->mutex);
+                       
+                       number_of_variables = vector_get_size(unit->runner->variables);
+                       
+                       for(i = 0; i < number_of_variables; i++)
+                       {
+                               variable = vector_get_at(unit->runner->variables, i);
+                               
+                               if(!strcmp(variable->name, name))
+                               {
+                                       env = variable->env;
+                                       err = variable->err;
+                                       exists = 1;
+                                       break;
+                               }
+                       }
+                               
+                       if(!env)
+                       {
+                               if(exists)
+                                       vector_erase_at(unit->runner->variables, i);
+                               else
+                                       WARN3("variable %s not found %s %s", name, line, filepos);      
+                       }
+                       else if(env)
+                       {
+                               WARN3("%s is an environment variable use unsetenv metacommand to delete it %s %s", name, line, filepos);        
+                       }
+                       else
+                       {
+                               WARN3("%s is an error variable : you are not allowed to delete it %s %s", name, line, filepos);
+                       }
+                       xbt_os_mutex_release(unit->mutex);
+                               
                }
+               else
+               {
+                       /* may be a variable */
+                       char* val;
+                       char name[MAX_PATH + 1] = {0};
+                       
+                       val = strchr(line, '=');
+                       
+                       if(val)
+                       {
+                               variable_t variable;
+                               int exists = 0;
+                               val++;
+                               
+                               /* syntax error */
+                               if(val[0] == '\0')
+                               {
+                                       
+                                       exit_code = ESYNTAX;
+                                       ERROR2("indefinite variable value %s %s", line, filepos);
+                                       unit_handle_failure(unit);      
+                               }
+                               
+                               
+                               /* assume it's a varibale */
+                               strncpy(name, line, (val - line -1));
+                               
+                               xbt_os_mutex_acquire(unit->mutex);
+                               
+                               /* test if the variable is already registred */
+                               
+                               vector_rewind(unit->runner->variables);
+                               
+                               while((variable = vector_get(unit->runner->variables)))
+                               {
+                                       
+                                       if(!strcmp(variable->name, name))
+                                       {
+                                               exists = 1;
+                                               break;
+                                       }
+                                       
+                                       vector_move_next(unit->runner->variables);
+                               }
+                               
+                               /* if the variable is already registred, update its value;
+                                * otherwise register it.
+                                */
+                               if(exists)
+                               {
+                                       free(variable->val);
+                                       variable->val = strdup(val);
+                               }
+                               else
+                                       vector_push_back(unit->runner->variables,variable_new(name, val));
+                                       
+                               xbt_os_mutex_release(unit->mutex);
+                               
+                       }
+                       else 
+                       {
+                               ERROR2("%s: Malformed metacommand: %s",filepos,line);
+                               ERROR1("Test suite `%s': NOK (syntax error)",unit->fstream->name);
+                               
+                               exit_code = ESYNTAX;
+                               unit_handle_failure(unit);
+                               return;
+                       }
+               }
+               
                
                break;
        }
@@ -566,15 +971,18 @@ unit_pushline(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char*
 void
 unit_handle_failure(unit_t unit)
 {
+       
        if(!want_keep_going_unit)
        {
-               if(!unit->interrupted)
+               unit_t root = unit->root ? unit->root : unit;
+                       
+               if(!root->interrupted)
                {
                        /* the unit interrupted (exit for the loop) */
-                       unit->interrupted = 1;
+                       root->interrupted = 1;
 
                        /* release the unit */
-                       xbt_os_sem_release(unit->sem);
+                       xbt_os_sem_release(root->sem);
                }
 
                /* if the --keep-going option is not specified */
@@ -622,59 +1030,466 @@ unit_interrupt(unit_t unit)
        xbt_os_sem_release(unit->sem);
 }
 
+void 
+display_title(const char* description)
+{
+       int i;
+       char title[80];
+       int len = strlen(description);
+               
+       title[0]=' ';
+               
+       for (i = 1; i < 79; i++)
+               title[i]='=';
+               
+       title[i++]='\n';
+       title[79]='\0';
+       
+       sprintf(title + 40 - (len + 4)/2, "[ %s ]",description);
+       title[40 + (len + 5 ) / 2] = '=';
+               
+       printf("\n%s\n",title); 
+}
+
 void
 unit_verbose(unit_t unit)
 {
-       int i, test_count;
+       int i, j, k;
        command_t command;
-
-       printf("\nUnit : %s (%s)\n", unit->fstream->name, unit->fstream->directory);
-       printf("Status informations :");
-
-       if(unit->parsed && unit->number_of_successeded_commands == unit->number_of_started_commands)
-               printf(" - (success)"); 
+       unit_t include;
+       unit_t suite;
+       char* p;
+       char title[MAX_PATH + 1] = {0};
+       
+       int number_of_tests = 0;                                                /* number of tests of a unit contained by this unit                                     */
+       int number_of_failed_tests = 0;                                 /* number of failed test of a unit contained by this unit                       */
+       int number_of_successeded_tests = 0;                    /* number of successeded tests of a unit contained by this unit         */
+       int number_of_interrupted_tests = 0;                    /* number of interrupted tests of a unit contained by this unit         */
+       
+       int number_of_tests_of_suite = 0;                               /* number of tests of a suite contained by this unit                            */
+       int number_of_interrupted_tests_of_suite = 0;   /* number of interrupted tests of a suite contained by this unit        */      
+       int number_of_failed_tests_of_suite = 0;                /* number of failed tests of a suite contained by this unit                                     */
+       int number_of_successeded_tests_of_suite = 0;   /* number of successeded tests of a suite contained by this                     */
+       
+       int number_of_units = 0;                                                /* number of units contained by a suite                                                         */
+       int number_of_failed_units = 0;                                 /* number of failed units contained by a suite                                          */
+       int number_of_successeded_units = 0;                    /* number of successeded units contained by a suite                                     */
+       int number_of_interrupted_units = 0;                    /* number of interrupted units contained by a suite                                     */
+       
+       int total_of_tests = 0;                                                 /* total of the tests contained by this unit                                            */
+       int total_of_failed_tests = 0;                                  /* total of failed tests contained by this unit                                         */
+       int total_of_successeded_tests = 0;                     /* total of successeded tests contained by this unit                            */
+       int total_of_interrupted_tests = 0;                             /* total of interrupted tests contained by this unit                            */
+       
+       int total_of_units = 0;                                                 /* total of units contained by this unit                                                        */
+       int total_of_failed_units = 0;                                  /* total of failed units contained by this unit                                         */
+       int total_of_successeded_units = 0;                             /* total of successeded units contained by this unit                            */
+       int total_of_interrupted_units = 0;                             /* total of interrutped units contained by this unit                            */
+       
+       int total_of_suites = 0;                                                /* total of suites contained by this unit                                                       */
+       int total_of_failed_suites = 0;                                 /* total of failed suites contained by this unit                                        */
+       int total_of_successeded_suites = 0;                    /* total of successeded suites contained by this unit                           */ 
+       int total_of_interrupted_suites = 0;                    /* total of interrupted suites contained by this unit                           */
+       
+       
+       if(unit->description)
+               strcpy(title, unit->description);
        else
+               sprintf(title, "file : %s",unit->fstream->name);
+               
+       if(unit->interrupted)
+               strcat(title, " (interrupted)");
+               
+       display_title(title);
+       
+       number_of_tests = vector_get_size(unit->commands);
+       
+       
+       /* tests */
+       for(i = 0; i < number_of_tests; i++)
        {
-               if(unit->interrupted)
-                       printf(" - (interruped)");
-               else
-                       printf(" - (failed)");
+               command = vector_get_at(unit->commands, i);
+               
+               if(command->status == cs_interrupted)
+                       number_of_interrupted_tests++;
+               else if(command->status == cs_failed)
+                       number_of_failed_tests++;
+               else if(command->status == cs_successeded)
+                       number_of_successeded_tests++;
+                       
        }
        
-       printf("\n");
-
-       printf("    number of commands               : %d\n", unit->number_of_commands);
-       printf("    number of runned commands        : %d\n", unit->number_of_started_commands);
-       printf("    number of successeded commands   : %d\n", unit->number_of_successeded_commands);
-       printf("    number of failed commands        : %d\n", unit->number_of_failed_commands);
-       printf("    number of interrupted commands   : %d\n", unit->number_of_interrupted_commands);
+       if(number_of_tests)
+       {
+               asprintf(&p," Test(s): .........................................................................");
+                       
+               p[70] = '\0';
+               printf("%s", p);
+               free(p);        
+       
+               if(number_of_failed_tests > 0) 
+                       printf(".. failed\n");
+               else if(number_of_interrupted_tests > 0) 
+                       printf("interrupt\n");
+               else 
+                       printf(".... ..ok\n"); 
+       
+       
+               for(i = 0; i < number_of_tests; i++)
+               {
+                       command = vector_get_at(unit->commands, i);
+                               
+                       printf("        %s: %s [%s]\n", 
+                               command->status == cs_interrupted ? "INTR  " 
+                               : command->status == cs_failed ? "FAILED" 
+                               : command->status == cs_successeded ? "PASS  " 
+                               : "UNKNWN",
+                               command->context->command_line, 
+                               command->context->line);
+                               
+                       if(want_detail_summary)
+                               command_display_status(command);
+                               
+               }
+       
+               printf(" =====================================================================%s\n",
+               number_of_failed_tests ? "== FAILED": number_of_interrupted_tests ? "==== INTR" : "====== OK");
+               
+               printf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",
+               ((1-((double)number_of_failed_tests + (double)number_of_interrupted_tests)/(double)number_of_tests)*100.0),
+                number_of_tests, number_of_successeded_tests);
+               
+               if(number_of_failed_tests > 0)
+                       printf(", %d failed", number_of_failed_tests);
+               
+               if(number_of_interrupted_tests > 0)
+                       printf(", %d interrupted)", number_of_interrupted_tests);
+                       
+                printf(")\n\n");
+                               
+               total_of_tests = number_of_tests;
+               total_of_failed_tests = number_of_failed_tests;
+               total_of_interrupted_tests = number_of_interrupted_tests;
+               total_of_successeded_tests = number_of_successeded_tests;
+       }
        
-       test_count = unit->number_of_commands;
        
        
-       for(i = 0; i < test_count; i++)
+       /* includes */
+       
+       total_of_failed_units = total_of_interrupted_units = total_of_successeded_units = 0;
+       
+       number_of_failed_units = number_of_successeded_units = number_of_interrupted_units = 0;
+       
+       number_of_units = vector_get_size(unit->includes);
+       
+       for(i = 0; i < number_of_units ; i++)
        {
-               command = vector_get_at(unit->commands, i);
+               include = vector_get_at(unit->includes, i);
+               
+               number_of_interrupted_tests = number_of_failed_tests = number_of_successeded_tests = 0;
+               
+               number_of_tests = vector_get_size(include->commands);
+               
+               for(j = 0; j < number_of_tests; j++)
+               {
+                       command = vector_get_at(include->commands, j);
+                       
+                       if(command->status == cs_interrupted)
+                               number_of_interrupted_tests++;
+                       else if(command->status == cs_failed)
+                               number_of_failed_tests++;
+                       else if(command->status == cs_successeded)
+                               number_of_successeded_tests++;  
+               }
+               
+               asprintf(&p," Unit: %s ............................................................................", include->description ? include->description : include->fstream->name);
+                       
+               p[70] = '\0';
+               printf("%s", p);
+               free(p);        
+               
+               
+               if(number_of_failed_tests > 0) 
+               {
+                       total_of_failed_units++;
+                       printf(".. failed\n");
+               }
+               else if(number_of_interrupted_tests > 0) 
+               {
+                       total_of_interrupted_units++;
+                       printf("interrupt\n");
+               }
+               else 
+               {
+                       total_of_successeded_units++;
+                       printf(".... ..ok\n"); 
+               }
+               
+               if(want_detail_summary)
+               {               
+       
+                       for(j = 0; j < vector_get_size(include->commands); j++)
+                       {
+                               command = vector_get_at(include->commands, j);
+                               
+                               printf("        %s: %s [%s]\n", 
+                               command->status == cs_interrupted ? "INTR  " 
+                               : command->status == cs_failed ? "FAILED" 
+                               : command->status == cs_successeded ? "PASS  " 
+                               : "UNKNWN",
+                               command->context->command_line, 
+                               command->context->line);
+                               
+                               command_display_status(command);
+                       }
+                       
+                                       
+               }
                
-               /*command_display_status(unit->commands[i]);*/
-               command_display_status(command);
+               printf(" =====================================================================%s\n",
+               number_of_failed_tests ? "== FAILED": number_of_interrupted_tests ? "==== INTR" : "====== OK");
+       
+               
+               printf("    Summary: Test(s): %.0f%% ok (%d test(s): %d ok",
+               (number_of_tests ? (1-((double)number_of_failed_tests + (double)number_of_interrupted_tests)/(double)number_of_tests)*100.0 : 100.0),
+                number_of_tests, number_of_successeded_tests);
+               
+               if(number_of_failed_tests > 0)
+                       printf(", %d failed", number_of_failed_tests);
+               
+               if(number_of_interrupted_tests > 0)
+                       printf(", %d interrupted)", number_of_interrupted_tests);
+                       
+                printf(")\n\n");       
+                
+               
+               total_of_tests += number_of_tests;
+               total_of_failed_tests += number_of_failed_tests;
+               total_of_interrupted_tests += number_of_interrupted_tests;
+               total_of_successeded_tests += number_of_successeded_tests;
+       }
+       
+       /* suites */
+       
+       total_of_units = number_of_units;
+       
+       total_of_failed_suites = total_of_successeded_suites = total_of_interrupted_suites = 0;
+       
+       total_of_suites = vector_get_size(unit->suites);
+       
+       for(k = 0; k < total_of_suites; k++)
+       {
+               suite = vector_get_at(unit->suites, k);
+               
+               display_title(suite->description);
+               
+               number_of_tests_of_suite = number_of_interrupted_tests_of_suite = number_of_failed_tests_of_suite = number_of_successeded_tests_of_suite = 0;
+               
+               number_of_interrupted_units = number_of_failed_units = number_of_successeded_units = 0;
+               
+               number_of_units = vector_get_size(suite->includes);
+               
+               for(i = 0; i < number_of_units; i++)
+               {
+                       number_of_interrupted_tests = number_of_failed_tests = number_of_successeded_tests = 0;
+                       
+                       number_of_tests = vector_get_size(include->commands);
+                       
+                       for(j = 0; j < vector_get_size(include->commands); j++)
+                       {
+                               command = vector_get_at(include->commands, j);
+                               
+                               if(command->status == cs_interrupted)
+                                       number_of_interrupted_tests++;
+                               else if(command->status == cs_failed)
+                                       number_of_failed_tests++;
+                               else if(command->status == cs_successeded)
+                                       number_of_successeded_tests++;
+                                       
+                       }
+                       
+                       
+                       include = vector_get_at(suite->includes, i);
+                       asprintf(&p," Unit: %s ............................................................................", include->description ? include->description : include->fstream->name);
+                       
+                       p[70] = '\0';
+                       printf("%s", p);
+                       free(p);        
+               
+                       if(number_of_failed_tests > 0) 
+                       {
+                               number_of_failed_units++;
+                               printf(".. failed\n");
+                       }
+                       else if(number_of_interrupted_tests > 0) 
+                       {
+                               number_of_interrupted_units++;
+                               printf("interrupt\n");
+                       }
+                       else 
+                       {
+                               number_of_successeded_units++;
+                               printf(".... ..ok\n"); 
+                       } 
+                       
+                       number_of_interrupted_tests_of_suite += number_of_interrupted_tests;
+                       number_of_failed_tests_of_suite += number_of_failed_tests;
+                       number_of_successeded_tests_of_suite += number_of_successeded_tests;
+                       
+                       number_of_tests_of_suite += number_of_tests;
+                       
+                       total_of_tests += number_of_tests;
+                       total_of_failed_tests += number_of_failed_tests;
+                       total_of_interrupted_tests += number_of_interrupted_tests;
+                       total_of_successeded_tests += number_of_successeded_tests;
+                       
+                       if(want_detail_summary)
+                       {
+                               for(j = 0; j < vector_get_size(include->commands); j++)
+                               {
+                                       command = vector_get_at(include->commands, j);
+                                       
+                                       printf("        %s: %s [%s]\n", 
+                                       command->status == cs_interrupted ? "INTR  " 
+                                       : command->status == cs_failed ? "FAILED" 
+                                       : command->status == cs_successeded ? "PASS  " 
+                                       : "UNKNWN",
+                                       command->context->command_line, 
+                                       command->context->line);
+                                       
+                                       command_display_status(command);
+                                               
+                               }
+                               
+                               
+                       }
+                               
+               }
+               
+               
+               
+               printf(" =====================================================================%s\n",
+               number_of_failed_tests_of_suite ? "== FAILED": number_of_interrupted_tests_of_suite ? "==== INTR" : "====== OK");
+               
+               if(number_of_failed_tests_of_suite > 0)
+                       total_of_failed_suites++;
+               else if(number_of_interrupted_tests_of_suite)
+                       total_of_interrupted_suites++;
+               else
+                       total_of_successeded_suites++;
+                       
+               total_of_failed_units += number_of_failed_units;
+               total_of_interrupted_units += number_of_interrupted_units;
+               total_of_successeded_units += number_of_successeded_units;
+                       
+               total_of_units += number_of_units;
+               
+               printf("    Summary: Unit(s): %.0f%% ok (%d unit(s): %d ok",
+               (number_of_units ? (1-((double)number_of_failed_units + (double)number_of_interrupted_units)/(double)number_of_units)*100.0 : 100.0),
+                number_of_units, number_of_successeded_units);
+                
+               if(number_of_failed_units > 0)
+                       printf(", %d failed", number_of_failed_units);
+               
+               if(number_of_interrupted_units > 0)
+                       printf(", %d interrupted)", number_of_interrupted_units);
+                       
+               printf(")\n");  
+               
+               printf("             Test(s): %.0f%% ok (%d test(s): %d ok",
+               (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),
+               number_of_tests_of_suite, number_of_successeded_tests_of_suite);
+                
+               if(number_of_failed_tests_of_suite > 0)
+                       printf(", %d failed", number_of_failed_tests_of_suite);
+               
+               if(number_of_interrupted_tests_of_suite > 0)
+                       printf(", %d interrupted)", number_of_interrupted_tests_of_suite);
+                       
+                printf(")\n\n");       
        }
+       
+       printf(" TOTAL : Suite(s): %.0f%% ok (%d suite(s): %d ok",
+               (total_of_suites ? (1-((double)total_of_failed_suites + (double)total_of_interrupted_suites)/(double)total_of_suites)*100.0 : 100.0),
+                total_of_suites, total_of_successeded_suites);
+       
+       if(total_of_failed_suites > 0)
+                       printf(", %d failed", total_of_failed_suites);
+               
+       if(total_of_interrupted_suites > 0)
+               printf(", %d interrupted)", total_of_interrupted_suites);
+               
+       printf(")\n");  
+       
+       printf("         Unit(s):  %.0f%% ok (%d unit(s): %d ok",
+               (total_of_units ? (1-((double)total_of_failed_units + (double)total_of_interrupted_units)/(double)total_of_units)*100.0 : 100.0),
+                total_of_units, total_of_successeded_units);
+       
+       if(total_of_failed_units > 0)
+                       printf(", %d failed", total_of_failed_units);
+               
+       if(total_of_interrupted_units > 0)
+               printf(", %d interrupted)", total_of_interrupted_units);
+               
+       printf(")\n");
+       
+       printf("         Test(s):  %.0f%% ok (%d test(s): %d ok",
+               (total_of_tests ? (1-((double)total_of_failed_tests + (double)total_of_interrupted_tests)/(double)total_of_tests)*100.0 : 100.0),
+                total_of_tests, total_of_successeded_tests); 
+                
+       if(total_of_failed_tests > 0)
+                       printf(", %d failed", total_of_failed_tests);
+               
+       if(total_of_interrupted_tests > 0)
+               printf(", %d interrupted)", total_of_interrupted_tests);
+               
+       printf(")\n\n");
+       
+       
+       if(unit->interrupted)
+               unit->runner->total_of_interrupted_units++;
+       else if(total_of_failed_tests > 0)
+               unit->runner->total_of_failed_units++;
+       else
+               unit->runner->total_of_successeded_units++;
+       
+       
+       unit->runner->total_of_tests += total_of_tests;
+       unit->runner->total_of_failed_tests += total_of_failed_tests;
+       unit->runner->total_of_successeded_tests += total_of_successeded_tests;
+       unit->runner->total_of_interrupted_tests += total_of_interrupted_tests;
+       
+       
+       unit->runner->total_of_units += total_of_units + 1;
+       unit->runner->total_of_successeded_units += total_of_successeded_units;
+       unit->runner->total_of_failed_units += total_of_failed_units;
+       unit->runner->total_of_interrupted_units += total_of_interrupted_units;
+       
+       
+       unit->runner->total_of_suites += total_of_suites;
+       unit->runner->total_of_successeded_suites += total_of_successeded_suites;
+       unit->runner->total_of_failed_suites += total_of_failed_suites;
+       unit->runner->total_of_interrupted_suites += total_of_interrupted_suites;
+       
+       
+       
+}
+
 
 
-}
 
 void
-unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name)
+unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* file_name, const char* description)
 {
-       directory_t include;
+       directory_t dir;
        char* prev_directory = NULL;
        fstream_t fstream = NULL;
        struct stat buffer = {0};
        
-       
        if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
        {
-               INFO1("the file stream %s is in the current directory", file_name);
+               /* the file is in the current directory */
                
                fstream = fstream_new(getcwd(NULL, 0), file_name);
                fstream_open(fstream);
@@ -684,21 +1499,21 @@ unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const
        {
                prev_directory = getcwd(NULL, 0);
                
-               vector_rewind(includes);
+               vector_rewind(include_dirs);
                
-               while((include = vector_get(includes)))
+               while((dir = vector_get(include_dirs)))
                {
-                       chdir(include->name);
+                       chdir(dir->name);
                        
                        if(!stat(file_name, &buffer) && S_ISREG(buffer.st_mode))
                        {
-                               fstream = fstream_new(include->name, file_name);
+                               fstream = fstream_new(dir->name, file_name);
                                fstream_open(fstream);
                                break;
                        }
                        
                        
-                       vector_move_next(includes);
+                       vector_move_next(include_dirs);
                }
                
                chdir(prev_directory);
@@ -716,34 +1531,53 @@ unit_handle_include(unit_t unit, context_t context, xbt_os_mutex_t mutex, const
        }
        else
        {
-               /* parse the include file */
-               
-               /*unit_t __unit = unit_new(unit->runner, NULL, fstream);*/
-               unit->parsing_include_file = 1;
                
-               /* add the unit to the list of the runned units */
+               if(!unit->running_suite)
+               {/* it's the unit of a suite */
+                       unit_t include = unit_new(unit->runner,unit->root, unit, fstream);
+                       
+                       include->mutex = unit->root->mutex;
                
-               /*xbt_os_mutex_acquire(unit->mutex);
-               vector_push_back(__unit->runner->units->items, __unit);
-               xbt_os_mutex_release(unit->mutex);*/
+                       if(description)
+                               include->description = strdup(description);
                
+                       vector_push_back(unit->includes, include);
                
-               if(want_dry_run)
-                       INFO2("checking unit %s including in %s...",fstream->name, unit->fstream->name); 
+                       fstream_parse(fstream, include, mutex);
+               }
+               else
+               {/* it's a include */
+                       unit_t owner = vector_get_back(unit->suites);
+                       unit_t include = unit_new(unit->runner,unit->root, owner, fstream);
+                       
+                       include->mutex = unit->root->mutex;
+                       
+                       if(description)
+                               include->description = strdup(description);
                
-               unit_parse(unit, context_new(), mutex, fstream->name, fstream->stream);
+                       vector_push_back(owner->includes, include);
                
-               fstream_free((void**)&fstream);
-               unit->parsing_include_file = 0;
+                       fstream_parse(fstream, include, mutex); 
+               }
        }
 }
 
 void
 unit_handle_suite(unit_t unit, context_t context, xbt_os_mutex_t mutex, const char* description)
 {
-       suite_t suite = suite_new(unit, description);
-       unit_add_suite(unit, suite);
-       unit->running_suite = 1;
+       if(unit->running_suite)
+       {
+               exit_code = ESYNTAX;
+               unit_handle_failure(unit);
+       }
+       else
+       {
+               unit_t suite = unit_new(unit->runner, unit->root, unit, NULL);
+               suite->is_suite = 1;
+               suite->description = strdup(description);
+               vector_push_back(unit->suites, suite);
+               unit->running_suite = 1;
+       }
 }
 
 int
index 500846f..6ed01b4 100644 (file)
@@ -22,7 +22,7 @@ units_new(runner_t runner, fstreams_t fstreams)
        
        while((fstream = vector_get(fstreams->items)))
        {
-               if((errno = vector_push_back(units->items, unit_new(runner, NULL, fstream))))
+               if(vector_push_back(units->items, unit_new(runner, NULL, NULL, fstream)))
                {
                        vector_free(&(units->items));
                        free(units);
@@ -191,11 +191,13 @@ units_reset_all(units_t units)
 int
 units_free(void** unitsptr)
 {
+       int rv;
+       
        if(!(*unitsptr))
                return EINVAL;
        
-       if((errno = vector_free(&((*((units_t*)unitsptr))->items))))
-               return errno;
+       if((rv = vector_free(&((*((units_t*)unitsptr))->items))))
+               return rv;
                
        free(*unitsptr);
        *unitsptr = NULL;
index e2f66a7..229ab7e 100644 (file)
@@ -1,8 +1,67 @@
-#include <variable.h>\r
-\r
-typedef struct s_variable\r
-{\r
-       char* name;\r
-       char* val;\r
-       int used;\r
-}s_variable_t;
\ No newline at end of file
+#include <variable.h>
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
+
+variable_t
+variable_new(const char* name, const char* val)
+{
+       variable_t variable;
+       
+       if(!name || !val)
+       {
+               errno = EINVAL;
+               return NULL;
+       }
+       
+       if(!(variable = (variable_t)calloc(1, sizeof(s_variable_t))))
+               return NULL;
+       
+       variable->name = strdup(name);
+       variable->val = strdup(val);
+       variable->used = 0;
+       variable->env = 0;
+       variable->err = 0;
+       
+       return variable;
+       
+}
+
+int
+variable_free(variable_t* variableptr)
+{
+       if(!(*variableptr))
+               return EINVAL;
+               
+       free((*((variable_t*)(variableptr)))->name);
+       free((*((variable_t*)(variableptr)))->val);
+       
+       free(*variableptr);
+       
+       *variableptr = NULL;
+       return 0;
+}
+
+
+int
+variable_is_used(variable_t variable)
+{
+       if(!variable)
+       {
+               errno = EINVAL;
+               return 0;
+       }
+               
+       return variable->used;
+}
+
+
+int
+variable_set_used(variable_t variable)
+{
+       if(!variable)
+               return EINVAL;
+       
+       variable->used = 1;
+       
+       return 0;
+}
index dff1472..164d199 100644 (file)
@@ -1,6 +1 @@
-#include <variables.h>\r
-\r
-typedef struct s_variables\r
-{\r
-       dictionary_t items;\r
-}s_variables_t;
\ No newline at end of file
+#include <com.h>
\ No newline at end of file
index ca8f890..a9c6766 100644 (file)
@@ -5,6 +5,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <stdio.h>
+
 #ifdef _MSC_VER
 #define inline _inline
 #endif
@@ -54,11 +56,13 @@ vector_new(int capacity, fn_finalize_t fn_finalize)
 int 
 vector_clear(vector_t vector)
 {
+       int rv;
+       
        if(!vector)
            return EINVAL;
            
        if(!vector->size)
-               return EAGAIN;
+               return 0;
        
        if(vector->fn_finalize)
        {
@@ -69,8 +73,8 @@ vector_clear(vector_t vector)
                
                for(pos = 0; pos < size; pos++)
                {
-                       if((errno = (*(fn_finalize))(&(items[pos]))))
-                               return errno;
+                       if((rv = (*(fn_finalize))(&(items[pos]))))
+                               return rv;
                        else
                                vector->size--;
                }
@@ -88,11 +92,13 @@ vector_clear(vector_t vector)
 int 
 vector_free(vector_t* vector_ptr)
 {
+       int rv;
+       
     if(!(*vector_ptr))
         return EINVAL;
        
-       if((errno = vector_clear(*vector_ptr)))
-               return errno;
+       if((rv = vector_clear(*vector_ptr)))
+               return rv;
 
        free(*vector_ptr);
        *vector_ptr = NULL;
@@ -175,15 +181,16 @@ vector_get_capacity_available(vector_t vector)
 int
 vector_push_back(vector_t vector, void* item)
 {
+       int rv;
+       
        if(!vector || !item)
        return EINVAL;
     
-    
        /* if all capacity is used, resize the vector */
        if(vector->capacity <= vector->size)
        {
-               if(!resize(vector))
-                       return errno;
+               if((rv = resize(vector)))
+                       return rv;
        }
        
        /* increment the item count and push the new item at the end of the vector */
@@ -191,6 +198,7 @@ vector_push_back(vector_t vector, void* item)
        
        vector->pos = -1;
        
+       
        return 0;       
 }
 
@@ -263,6 +271,8 @@ vector_set_at(vector_t vector, int pos, void* item)
 int 
 vector_insert(vector_t vector, int pos, void* item)
 {
+       int rv;
+       
        if(!vector)
         return EINVAL;
    
@@ -280,8 +290,8 @@ vector_insert(vector_t vector, int pos, void* item)
     
        if(vector->size >= vector->capacity)
        {
-               if(!resize(vector))
-                       return errno;
+               if((rv = resize(vector)))
+                       return rv;
        }               
        
        if(vector->size)
@@ -300,6 +310,8 @@ vector_insert(vector_t vector, int pos, void* item)
 int 
 vector_erase_at(vector_t vector, int pos)
 {
+       int rv;
+       
        if(!vector)
         return EINVAL;
     
@@ -317,8 +329,8 @@ vector_erase_at(vector_t vector, int pos)
 
        if(vector->fn_finalize)
        {
-               if((errno = (*(vector->fn_finalize))(&(vector->items[pos]))))
-                       return errno;
+               if((rv = (*(vector->fn_finalize))(&(vector->items[pos]))))
+                       return rv;
        }
 
        if(pos != (vector->size - 1))
@@ -336,7 +348,7 @@ vector_erase_at(vector_t vector, int pos)
 int 
 vector_erase(vector_t vector, void* item)
 {
-       int pos;
+       int pos, rv;
        
        if(!vector || !item)
                return EINVAL;
@@ -349,8 +361,8 @@ vector_erase(vector_t vector, void* item)
                
        if(vector->fn_finalize)
        {
-               if((errno = (*(vector->fn_finalize))(&item)))
-                       return errno;   
+               if((rv = (*(vector->fn_finalize))(&item)))
+                       return rv;      
        }
        
        if(pos != (vector->size - 1))
@@ -368,7 +380,8 @@ int
 vector_erase_range(vector_t vector, int first, int last)
 {
        register int width;
-
+       int rv;
+       
        if(!vector || first >= last)
                return EINVAL;
        
@@ -382,8 +395,8 @@ vector_erase_range(vector_t vector, int first, int last)
 
        while(width--)
        {
-               if((errno = vector_erase_at(vector,first)))
-                       return errno;
+               if((rv = vector_erase_at(vector,first)))
+                       return rv;
        }
                
        return 0;
@@ -454,6 +467,7 @@ vector_assign(vector_t dst,vector_t src)
        register int pos;
        int size;
        void** items;
+       int rv;
 
        
        if(!dst || !src ||(dst == src))
@@ -467,13 +481,13 @@ vector_assign(vector_t dst,vector_t src)
        /* if the destination vector has not enough capacity resize it */
        if(size > dst->capacity)
        {
-               if((errno = vector_reserve(dst, size - dst->capacity)))
-                       return errno;
+               if((rv = vector_reserve(dst, size - dst->capacity)))
+                       return rv;
        }
 
        /* clear the destination vector */
-       if((errno = vector_clear(dst)))
-               return errno;
+       if((rv = vector_clear(dst)))
+               return rv;
 
        dst->fn_finalize = NULL;
                
@@ -481,8 +495,8 @@ vector_assign(vector_t dst,vector_t src)
        
        /* file the destination vector */
        for(pos = 0; pos < size; pos++)
-                if((errno = vector_push_back(dst,items[pos])))
-                       return errno;
+                if((rv = vector_push_back(dst,items[pos])))
+                       return rv;
                        
        dst->pos = -1;
                 
@@ -613,6 +627,7 @@ vector_reserve(vector_t vector, int size)
        if(!(items = (void**)realloc(vector->items, size * sizeof(void*))))
                return errno;
        
+       
        vector->capacity = size;
        vector->items = items;
        
index 97aa2dc..c3ba975 100644 (file)
@@ -13,7 +13,10 @@ writer_new(command_t command)
 
        writer->thread = NULL;
        writer->command = command;
-       writer->started = xbt_os_sem_init(0);
+       writer->written = xbt_os_sem_init(0);
+       writer->can_write = xbt_os_sem_init(0);
+       
+       writer->done = 0;
 
        return writer;
 }
@@ -21,6 +24,10 @@ writer_new(command_t command)
 void
 writer_free(writer_t* writer)
 {
+       
+       /*xbt_os_sem_destroy((*writer)->started);
+       xbt_os_sem_destroy((*writer)->can_write);*/
+       
        free(*writer);
        *writer = NULL;
 }
@@ -145,21 +152,33 @@ writer_start_routine(void* p)
 {
        writer_t writer = (writer_t)p;
        command_t command = writer->command;
-       long number_of_bytes_to_write = command->context->input->used;
+       int number_of_bytes_to_write = command->context->input->used;
        char* input = (char*)(command->context->input->data);
        int got;
+       int released = 0;
+       
+       
+       xbt_os_sem_acquire(writer->can_write);
        
-       xbt_os_sem_release(writer->started);
        
        while(!command->failed && !command->interrupted && !command->successeded && number_of_bytes_to_write > 0)
        {
-               got = number_of_bytes_to_write > SSIZE_MAX ? SSIZE_MAX : number_of_bytes_to_write;
-               got = write( writer->command->stdin_fd, input, got );
-                       
+               got = number_of_bytes_to_write > PIPE_BUF ? PIPE_BUF : number_of_bytes_to_write;
+               got = write(writer->command->stdin_fd, input, got );
+               
                if(got < 0) 
                {
-                       if(EINTR == errno || EAGAIN == errno)
-                       {
+                       if(EINTR == errno)
+                               continue;
+                               
+                       else if(EAGAIN == errno)
+                       {/* the pipe is full */
+                               if(!released)
+                               {
+                                       xbt_os_sem_release(writer->written);
+                                       released = 1;
+                               }
+                               
                                continue;
                        }
                        else if(EPIPE == errno) 
@@ -179,9 +198,20 @@ writer_start_routine(void* p)
                input += got;
                
                if(got == 0)
-                       usleep(100);
+                       xbt_os_thread_yield();
+               
+       }
+       
+       if(!released)
+       {
+               xbt_os_sem_release(writer->written);
+               released = 1;
        }
        
+
+       close(command->stdin_fd);
+       command->stdin_fd = INDEFINITE_FD;
+       
        command->context->input->data[0]='\0';
        command->context->input->used=0;
        
@@ -198,9 +228,7 @@ writer_start_routine(void* p)
                command_handle_failure(command, csr_write_pipe_broken);
        }
        
-       
-       close(command->stdin_fd);
-       command->stdin_fd = INDEFINITE_FD;
+       writer->done = 1;
        
        return NULL;