Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
change the free function by a free_error function to clean all the tesh errors from...
[simgrid.git] / tools / tesh2 / src / main.c
index 135e328..01aac05 100644 (file)
@@ -1,15 +1,24 @@
-
+/*
+ * src/main.c - this file contains the main function of tesh.
+ *
+ * Copyright 2008,2009 Martin Quinson, Malek Cherier All right reserved. 
+ *
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of the license (GNU LGPL) which comes with this package.
+ *
+ *
+ */
 #include <runner.h>
 #include <fstream.h>
 #include <fstreams.h>
 #include <directory.h>
 #include <directories.h>
 #include <excludes.h>
-#include <error.h>
-
 #include <getopt.h>
 #include <getpath.h>
 
+#include <locale.h>
+
 /*
  * entry used to define the parameter of a tesh option.
  */
@@ -33,7 +42,7 @@ typedef struct s_optentry
 }s_optentry_t,* optentry_t;
 
 
-
+/* logs */
 XBT_LOG_NEW_DEFAULT_CATEGORY(tesh,"TEst SHell utility");
 
 #ifdef WIN32
@@ -42,16 +51,10 @@ static UINT
 prev_error_mode = 0;
 #endif
 
+/* this object represents the root directory */
 directory_t
 root_directory = NULL;
 
-/*int
-exit_code = 0;
-*/
-
-int 
-want_detail_summary = 0;
-
 /* the current version of tesh                                                                 */
 static const char* 
 version = "1.0";
@@ -67,22 +70,22 @@ version = "1.0";
 
 /* --jobs is specified with arg                                                                        */
 static int 
-number_of_jobs = -2;
+jobs_nb = -2;
 
 /* --jobs option is not specified (use the default job count)  */
 static int 
-default_number_of_jobs = 1;
+default_jobs_nb = 1;
 
 /* --jobs is specified but has no arg (one job per unit)               */
 static int 
-optional_number_of_jobs = -1;
+optional_jobs_nb = -1;
 
 /* the global timeout                                                                                  */
 static int
 timeout = INDEFINITE;
 
 /* ------------------------------------------------------------ */
-/* strings dlists                                                                                              */
+/* strings                                                                                     */
 /* ------------------------------------------------------------ */
 
 /* --C change the directory before running the units                   */
@@ -90,7 +93,9 @@ static directories_t
 directories = NULL;
 
 /* the include directories : see the !i metacommand                            */
-vector_t 
+/*vector_t 
+include_dirs = NULL;*/
+xbt_dynar_t
 include_dirs = NULL;
 
 /* the list of tesh files to run                                                               */
@@ -98,15 +103,17 @@ static fstreams_t
 fstreams = NULL;
 
 /* xbt logs                                                                                                            */
-static lstrings_t
+static xbt_dynar_t
 logs = NULL;
 
+/* the list of tesh file suffixes                                                              */
+static xbt_dynar_t
+suffixes = NULL;
+
+
 static excludes_t
 excludes = NULL;
 
-/* the ddlist of tesh file suffixes                                                            */
-static lstrings_t
-suffixes = NULL;
 
 /* ------------------------------------------------------------ */
 /* flags                                                                                                               */
@@ -116,62 +123,66 @@ suffixes = NULL;
  * default value 0 : not keep going
  */
 int 
-want_keep_going = 0;
+keep_going_flag = 0;
 
 /* if 1, ignore failures from commands
  * default value : do not ignore failures
  */
 int 
-want_keep_going_unit = 0;
+keep_going_unit_flag = 0;
 
 /* if 1, display tesh usage                                                                            */
 static int 
-want_display_usage = 0;
+print_usage_flag = 0;
 
 /* if 1, display the tesh version                                                              */
 static int 
-want_display_version = 0;
+print_version_flag = 0;
 
 /* if 1, the syntax of all tesh files is checked 
  * before running them
  */
 static int
-want_check_syntax = 0;
+check_syntax_flag = 0;
 
 /* if 1, the status of all the units is display at
  * the end.
  */
 static int
-want_verbose = 0;
+summary_flag = 0;
+
+/* if 1 and the flag want_summay is set to 1 tesh display the detailed summary of the run */
+int 
+detail_summary_flag = 0;
 
 /* if 1, the directories are displayed                                                 */
 int 
-dont_want_display_directory = 0;
+print_directory_flag = 0;
 
 /* if 1, just check the syntax of all the tesh files
  * do not run them.
  */
 int
-want_dry_run = 0;
+dry_run_flag = 0;
 
 /* if 1, display the tesh files syntax and exit                                        */
 static int
-want_display_semantic = 0;
+print_readme_flag = 0;
 
 int 
-want_silent = 0;
+silent_flag = 0;
 
 int 
-want_just_display = 0;
+just_print_flag = 0;
 
 static int 
-env_overrides  = 0;
+env_overrides_flag  = 0;
 
 static int 
-display_data_base = 0;
+print_database_flag = 0;
 
 static int 
-question = 0;
+question_flag = 0;
 
 /* the semaphore used to synchronize the jobs */
 xbt_os_sem_t
@@ -193,35 +204,43 @@ exit_code = 0;
 pid_t
 pid =0;
 
+int 
+is_tesh_root = 1;
+
+xbt_dynar_t
+errors = NULL;
+
+xbt_os_mutex_t
+err_mutex = NULL;
+
 /* the table of the entries of the options */ 
 static const struct s_optentry opt_entries[] =
 {
        { 'C', string, (byte*)NULL, 0, "directory" },
        { 'x', string, (byte*)&suffixes, 0, "suffix" },
-       { 'e', flag, (byte*)&env_overrides, 0, "environment-overrides", },
+       { 'e', flag, (byte*)&env_overrides_flag, 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" },
+       { 'h', flag, (byte*)&print_usage_flag, 0, "help" },
+       { 'a', flag, (byte*)&print_readme_flag, 0, "semantic" },
+       { 'i', flag, (byte*)&keep_going_unit_flag, 0, "keep-going-unit" },
        { '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" },
-       { 's', flag, (byte*)&want_silent, 0, "silent" },
-       { 'V', flag, (byte*)&want_display_version, 0, "version" },
-       { 'w', flag, (byte*)&dont_want_display_directory, 0,"dont-display-directory" },
-       { 'n', flag, (byte*)&want_dry_run, 0, "dry-run"},
+       { 'j', number, (byte*)&jobs_nb, (byte*) &optional_jobs_nb, "jobs" },
+       { 'k', flag, (byte*)&keep_going_flag, 0, "keep-going" },
+       { 'm', flag, (byte*)&detail_summary_flag, 0, "detail-summary" },
+       { 'c', flag, (byte*)&just_print_flag, 0, "just-print" },
+       { 'd', flag, (byte*)&print_database_flag, 0,"display-data-base" },
+       { 'q', flag, (byte*)&question_flag, 0, "question_flag" },
+       { 's', flag, (byte*)&silent_flag, 0, "silent" },
+       { 'V', flag, (byte*)&print_version_flag, 0, "version" },
+       { 'w', flag, (byte*)&print_directory_flag, 0,"dont-display-directory" },
+       { 'n', flag, (byte*)&dry_run_flag, 0, "dry-run"},
        { 't', number, (byte*)&timeout, 0, "timeout" },
-       { 'S', flag, (byte*)&want_check_syntax, 0, "check-syntax"},
+       { 'S', flag, (byte*)&check_syntax_flag, 0, "check-syntax"},
        { 'r', string, (byte*)&directories, 0, "load-directory"},
-       { 'v', flag, (byte*)&want_verbose, 0, "verbose"},
+       { 'v', flag, (byte*)&summary_flag, 0, "summary"},
        { 'F', string,(byte*)&excludes, 0, "exclude"},
        { 'l', string,(byte*)&logs,0,"log"},
        { 0, 0, 0, 0, 0}
-       
 };
 
 /* the tesh usage                                                                                              */
@@ -234,7 +253,7 @@ static const char* usage[] =
        "                                           remark :\n",
        "                                           all argument of the command line without\n",
        "                                           option is dealed as a tesh file.\n",
-       "  -h, --help                            Display this message and exit.\n",
+       "  -h, --help                            Print this message and exit.\n",
        "  -i, --keep-going-unit                 Ignore failures from commands.\n",
        "                                        The possible failures are :\n",
        "                                         - the exit code differ from the expected\n",
@@ -248,22 +267,22 @@ static const char* usage[] =
        "                                        no arg.\n",
        "  -k, --keep-going                      Keep going when some commands can't be made or\n",
        "                                        failed.\n",
-       "  -c, --just-display                    Don't actually run any commands; just display them.\n",
-       "  -p, --display-data-base               Display tesh's internal database.\n",
+       "  -c, --just-print                      Don't actually run any commands; just print them.\n",
+       "  -p, --print-data-base                 Display tesh's internal database.\n",
        "  -q, --question                        Run no commands; exit status says if up to date.\n",
        "  -s, --silent,                         Don't echo commands.\n",
-       "  -V, --version                         Display the version number of tesh and exit.\n",
-       "  -d, --dont-display-directory          Don't display the current directory.\n",
+       "  -V, --version                         Print the version number of tesh and exit.\n",
+       "  -d, --dont-print-directory            Don't display the current directory.\n",
        "  -n, --dry-run                         Check the syntax of the specified tesh files, display the result and exit.\n",
        "  -t, --timeout                         Wait the end of the commands at most timeout seconds.\n",
        "  -S, --check-syntax                    Check the syntax of the tesh files before run them. \n",
        "  -x, --suffix                          Consider the new suffix for the tesh files.\n"
        "                                           remark :\n",
        "                                           the default suffix for the tesh files is \".tesh\".\n",
-       " -a, --semantic                         Display the tesh file metacommands syntax and exit.\n",
+       " -a, --read-me                          Print the read me file and exit.\n",
        " -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",
+       " -v, --summary                          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",
@@ -288,25 +307,56 @@ static void
 load(void);
 
 static void
-display_usage(void);
+print_usage(void);
 
 static void
-display_version(void);
+print_version(void);
 
 static void
 finalize(void);
 
 static void
-display_semantic(void);
+print_readme(void);
 
 static int
 init(void);
 
 
+static void 
+sig_abort_handler(int signum)
+{
+       /* TODO : implement this function */
+       INFO0("sig_abort_handler() called");
+}
+
+static void 
+sig_int_handler(int signum)
+{
+       /* TODO : implement this function */
+       INFO0("sig_int_handler() called");
+}
+
+static void 
+free_string(void* str)
+{
+       free(*(void**)str);
+}
+
+static void 
+free_error(void* e)
+{
+       free(*(void**)e);
+}
 
 int
 main(int argc, char* argv[])
 {
+       int _argc;
+
+       /* set the locale to the default*/
+       setlocale(LC_ALL,"");
+       
+       /* initialize tesh */
        if(init() < 0)
                finalize();
                
@@ -322,34 +372,46 @@ main(int argc, char* argv[])
         */
         
        /* xbt initialization */
-       if(!lstrings_is_empty(logs))
+
+       if((_argc = xbt_dynar_length(logs)))
        {
-               int size = lstrings_get_size(logs);
-               char** cstr = lstrings_to_cstr(logs);
-               
-               xbt_init(&size, cstr);
-               
-               free(cstr);
+               int i;
+
+               char** _argv = (char**)calloc(_argc, sizeof(char*));
                
+               for(i = 0; i < _argc; i++)
+                       xbt_dynar_pop(logs, &(_argv[i]));
+
+               xbt_init(&_argc, _argv);
+
+               while(--i)
+                       free(_argv[i]);
+
+               free(_argv);
        }
        else
                xbt_init(&argc, argv);
-       
+               
        /* the user wants to display the usage of tesh */
-       if(want_display_usage)
-               finalize();
+       if(print_version_flag)
+       {
+               print_version();
+
+               if(!print_usage_flag)
+                       finalize();
+       }
        
-       /* the user wants to display the version of tesh */
-       if(want_display_version)
+       /* the user wants to display the usage of tesh */
+       if(print_usage_flag)
        {
-               display_version();
+               print_usage();
                finalize();
        }
        
        /* the user wants to display the semantic of the tesh file metacommands */
-       if(want_display_semantic)
+       if(print_readme_flag)
        {
-               display_semantic();
+               print_readme();
                finalize();
        }
        
@@ -360,38 +422,38 @@ main(int argc, char* argv[])
        /* use by the finalize function to known if it must display the tesh usage */   
        loaded = 1;
 
-       if(-2 == number_of_jobs)
+       if(-2 == jobs_nb)
        {/* --jobs is not specified (use the default value) */
-               number_of_jobs = default_number_of_jobs;
+               jobs_nb = default_jobs_nb;
        }
-       else if(optional_number_of_jobs == number_of_jobs)
+       else if(optional_jobs_nb == jobs_nb)
        {/* --jobs option is specified with no args (use one job per unit) */
-               number_of_jobs = fstreams_get_size(fstreams);
+               jobs_nb = fstreams_get_size(fstreams);
        }
 
-       if(number_of_jobs > fstreams_get_size(fstreams))
+       if(jobs_nb > 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 to run");
                
                /* assume one job per file */
-               number_of_jobs = fstreams_get_size(fstreams);
+               jobs_nb = fstreams_get_size(fstreams);
        }
 
        /* initialize the semaphore used to synchronize all the units */
-       jobs_sem = xbt_os_sem_init(number_of_jobs);
+       jobs_sem = xbt_os_sem_init(jobs_nb);
 
        /* 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(runner_init(want_check_syntax, timeout, fstreams))
+       if(runner_init(check_syntax_flag, timeout, fstreams) < 0)
                finalize();
                
-       if(want_just_display && want_silent)
-               want_silent = 0;
+       if(just_print_flag && silent_flag)
+               silent_flag = 0;
                
-       if(want_just_display && want_dry_run)
+       if(just_print_flag && dry_run_flag)
                WARN0("mismatch in the syntax : --just-check-syntax and --just-display options at same time");
        
        /* run all the units */
@@ -399,8 +461,8 @@ main(int argc, char* argv[])
        
        
        /* show the result of the units */
-       if(want_verbose || want_dry_run)
-               runner_display_status();
+       if(summary_flag || dry_run_flag)
+               runner_summarize();
                
        /* all the test are runned, destroy the runner */
        runner_destroy();
@@ -427,8 +489,7 @@ static int
 init(void)
 {
        char* buffer;
-       
-       
+       char* suffix = strdup(".tesh");
        
        #ifdef WIN32
        /* Windows specific : don't display the general-protection-fault message box and
@@ -436,80 +497,90 @@ init(void)
         * to the calling process : tesh)
         */
        prev_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
-       #endif
+       #else
+       struct sigaction act;
+       /* Ignore pipe issues.
+        * They will show up when we try to send data to dead buddies, 
+     * but we will stop doing so when we're done with provided input 
+     */
+       memset(&act,0, sizeof(struct sigaction));
+       act.sa_handler = SIG_IGN;
+       sigaction(SIGPIPE, &act, NULL);
+       
+       
+       memset(&act,0, sizeof(struct sigaction));
+       act.sa_handler = sig_abort_handler;
+       sigaction(SIGABRT, &act, NULL);
+       
+       memset(&act,0, sizeof(struct sigaction));
+       act.sa_handler = sig_int_handler;
+       sigaction(SIGINT, &act, NULL);
+       
+       #endif
+       
+       err_mutex = xbt_os_mutex_init();
+       
+       /* handle the abort signal */
+       /*signal(SIGABRT, sig_abort_handler);*/
+       
+       /* handle the interrupt signal */
+       /*signal(SIGINT, sig_int_handler);*/
        
        /* used to store the files to run */
-       if(!(fstreams = fstreams_new(DEFAULT_FSTREAMS_CAPACITY, fstream_free)))
+       if(!(fstreams = fstreams_new(DEFAULT_FSTREAMS_CAPACITY, (void_f_pvoid_t)fstream_free)))
        {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               ERROR1("(system error) %s", strerror(errno));
                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");   
-               
+               ERROR1("(system error) %s", strerror(errno));
                return -1;
        }
        
        /* save the root directory */
        if(!(root_directory = directory_new(buffer)))
        {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               ERROR1("(system error) %s", strerror(errno));
                return -1;
        }
        
        free(buffer);
        
+       /* this vector contains all the errors of the run */
+       errors = xbt_dynar_new(sizeof(xerror_t), free_error);
+       
        /* the directories to loads */
        if(!(directories = directories_new()))
        {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               ERROR1("(system error) %s", strerror(errno));
                return -1;
        }
        
        /* 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;
-       }
+       include_dirs = xbt_dynar_new(sizeof(directory_t), (void_f_pvoid_t)directory_free);
        
        /* xbt logs option */
-       if(!(logs = lstrings_new()))
+       if(!(logs = xbt_dynar_new(sizeof(char*), free_string)))
        {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               ERROR1("(system error) %s", strerror(errno));
                return -1;
        }
        
        /* the excluded files */
        if(!(excludes = excludes_new()))
        {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
+               ERROR1("(system error) %s", strerror(errno));
                return -1;
        }
        
        /* the suffixes */
-       if(!(suffixes = lstrings_new()))
-       {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
-               return -1;
-       }
+       suffixes = xbt_dynar_new(sizeof(char*),free_string);
        
        /* 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();
+       xbt_dynar_push(suffixes, &suffix);
        
        return 0;
 }
@@ -550,7 +621,7 @@ load(void)
        
        /* if the fstreams object is empty use the stdin */
        if(fstreams_is_empty(fstreams))
-               fstreams_add(fstreams, fstream_new(NULL, "stdin"));     
+               fstreams_add(fstreams, fstream_new(NULL, "stdin"));
        
        /* load the tesh files (open them) */
        fstreams_load(fstreams);
@@ -561,11 +632,32 @@ load(void)
 static void
 finalize(void)
 {
-       /* 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();
+       
+       if(is_tesh_root && !summary_flag)
+       {
+               xerror_t error;
+               unsigned int i;
+
+               xbt_dynar_foreach(errors, i, error)
+               {
+                       if(error->command)
+                               fprintf(stderr, "[tesh/ERROR] %s : <Command `%s'> <Unit `%s'> <C%d (%s)>\n", error->reason, error->command, error->unit, error->errcode, error_to_string(error->errcode));
+                       else if(!error->command && error->unit)
+                               fprintf(stderr, "[tesh/ERROR] %s : Unit `%s' - C%d (%s)\n", error->reason, error->unit, error->errcode, error_to_string(error->errcode));
+                       else if(!error->command && !error->unit && error->reason)
+                               fprintf(stderr, "[tesh/ERROR] %s : C%d (%s)\n", error->reason, error->errcode, error_to_string(error->errcode));                
+                       else if(!error->command && !error->unit && !error->reason)
+                               fprintf(stderr, "[tesh/ERROR] C%d (%s)\n", error->errcode, error_to_string(error->errcode));            
+                       
+               }
+       }
+       
+       
+       /* delete vector of errors */
+       if(errors)
+               xbt_dynar_free(&errors);
+               
+       xbt_os_mutex_destroy(err_mutex);
        
        /* delete the fstreams object */
        if(fstreams)
@@ -585,17 +677,17 @@ finalize(void)
        
        /* delete the include directories object */
        if(include_dirs)
-               vector_free(&include_dirs);
+               xbt_dynar_free(&include_dirs);
        
        /* delete the list of tesh files suffixes */    
        if(suffixes)
-               lstrings_free(&suffixes);
+               xbt_dynar_free(&suffixes);
        
        /* delete the xbt log options list */
        if(logs)
-               lstrings_free(&logs);
+               xbt_dynar_free(&logs);
+               
                
-       
        /* destroy the semaphore used to synchronize the units */
        if(jobs_sem)
                xbt_os_sem_destroy(jobs_sem);
@@ -612,8 +704,14 @@ finalize(void)
        SetErrorMode(prev_error_mode);
        #endif
        
-       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)));
+       if(!summary_flag && !dry_run_flag && !silent_flag && !just_print_flag && !print_version_flag && !print_usage_flag && is_tesh_root)
+       {
+               if(!exit_code)
+                       INFO2("tesh terminated with exit code %d : %s",exit_code, "success");
+               else
+                       ERROR2("tesh terminated with exit code %d : %s",exit_code, error_to_string(exit_code));
+       }
+       
        
        /* exit with the last error code */
        exit(exit_code);
@@ -632,7 +730,6 @@ init_options (void)
        
        p = optstring;
        
-       
        *p++ = '-';
        
        for (i = 0; opt_entries[i].c != '\0'; ++i)
@@ -751,7 +848,7 @@ process_command_line(int argc, char** argv)
                         */
                        if(fstreams_contains(fstreams, fstream))
                        {
-                               fstream_free((void**)&fstream);
+                               fstream_free(&fstream);
                                WARN1("File %s already specified to be run", optarg);
                        }
                        else
@@ -764,6 +861,8 @@ process_command_line(int argc, char** argv)
                else if (c == '?')
                {
                        /* unknown option, let getopt_long() displays the error */
+                       ERROR0("Command line processing failed : invalid command line");
+                       exit_code = EINVCMDLINE;
                        return -1;
                }
                else
@@ -808,6 +907,16 @@ process_command_line(int argc, char** argv)
                                                /* --load-directory option */
                                                if(!strcmp(entry->long_name,"load-directory"))
                                                {
+                                                       #ifdef WIN32
+                                                       struct stat info = {0};
+                                                       if(stat(optarg, &info) || !S_ISDIR(info.st_mode))
+                                                       {
+                                                               ERROR1("%s is not a directory",optarg);
+                                                               exit_code = ENOTDIR;
+                                                               return -1;
+                                                       }       
+
+                                                       #else
                                                        char* path;
                                                        
                                                        if(translatepath(optarg, &path) < 0)
@@ -822,10 +931,15 @@ process_command_line(int argc, char** argv)
                                                                return -1;
                                                                
                                                        }
+                                                       #endif
                                                        else
                                                        {
+                                                               #ifdef WIN32
+                                                               directory = directory_new(optarg);
+                                                               #else
                                                                directory = directory_new(path);
                                                                free(path);
+                                                               #endif
                                                
                                                                if(directories_contains(directories, directory))
                                                                {
@@ -840,6 +954,16 @@ process_command_line(int argc, char** argv)
                                                }
                                                else if(!strcmp(entry->long_name,"directory"))
                                                {
+                                                       #ifdef WIN32
+                                                       struct stat info = {0};
+                                                       if(stat(optarg, &info) || !S_ISDIR(info.st_mode))
+                                                       {
+                                                               ERROR1("%s is not a directory",optarg);
+                                                               exit_code = ENOTDIR;
+                                                               return -1;
+                                                       }       
+
+                                                       #else
                                                        char* path ;
                                                        
                                                        if(translatepath(optarg, &path) < 0)
@@ -853,13 +977,31 @@ process_command_line(int argc, char** argv)
                                                                        
                                                                return -1;
                                                        }
+                                                       #endif
                                                        else
                                                        {
-                                                               if(!dont_want_display_directory)
-                                                                       INFO1("Entering directory \"%s\"",path);
+                                                               char* buffer = getcwd(NULL, 0);
+
+                                                               #ifdef WIN32
+                                                               
+                                                               if(!strcmp(buffer, optarg))
+                                                                       WARN1("Already in the directory %s", optarg);
+                                                               else if(!print_directory_flag)
+                                                                       INFO1("Entering directory \"%s\"",optarg);
                                                                
+                                                               chdir(optarg);
+                                                               #else
+                                                               
+                                                               if(!strcmp(buffer, path))
+                                                                       WARN1("Already in the directory %s", optarg);
+                                                               else if(!print_directory_flag)
+                                                                       INFO1("Entering directory \"%s\"",path);
+
                                                                chdir(path);
                                                                free(path);
+                                                               #endif
+
+                                                               free(buffer);
                                                                
                                                                
                                                        }       
@@ -877,20 +1019,46 @@ process_command_line(int argc, char** argv)
                                                        
                                                        if(optarg[0] == '.')
                                                        {
+                                                               char* cur;
+                                                               unsigned int i;
+                                                               int exists = 0;
+
                                                                char suffix[MAX_SUFFIX + 2] = {0};
                                                                sprintf(suffix,".%s",optarg);
                                                                
-                                                               if(lstrings_contains(suffixes, suffix))
+                                                               xbt_dynar_foreach(suffixes, i, cur)
+                                                               {
+                                                                       if(!strcmp(suffix, cur))
+                                                                       {
+                                                                               exists = 1;
+                                                                               break;
+                                                                       }
+                                                               }
+
+                                                               if(exists)
                                                                        WARN1("Suffix %s already specified to be used", optarg);
                                                                else
-                                                                       lstrings_push_back(suffixes, suffix);
+                                                                       xbt_dynar_push(suffixes, &suffix);
                                                        }
                                                        else
                                                        {
-                                                               if(lstrings_contains(suffixes, optarg))
+                                                               char* cur;
+                                                               unsigned int i;
+                                                               int exists = 0;
+
+                                                               xbt_dynar_foreach(suffixes, i, cur)
+                                                               {
+                                                                       if(!strcmp(optarg, cur))
+                                                                       {
+                                                                               exists = 1;
+                                                                               break;
+                                                                       }
+                                                               }
+
+                                                               if(exists)
                                                                        WARN1("Suffix %s already specified to be used", optarg);
                                                                else
-                                                                       lstrings_push_back(suffixes, optarg);   
+                                                                       xbt_dynar_push(suffixes, &optarg);      
                                                        }
                                                }
                                                /* --file option */
@@ -919,7 +1087,7 @@ process_command_line(int argc, char** argv)
                                                        
                                                        if(fstreams_contains(fstreams, fstream))
                                                        {
-                                                               fstream_free((void**)&fstream);
+                                                               fstream_free(&fstream);
                                                                WARN1("File %s already specified to run", optarg);
                                                        }
                                                        else
@@ -928,7 +1096,16 @@ process_command_line(int argc, char** argv)
                                                /* --include-dir option */
                                                else if(!strcmp(entry->long_name,"include-dir"))
                                                {
-                                                       
+                                                       #ifdef WIN32
+                                                       struct stat info = {0};
+                                                       if(stat(optarg, &info) || !S_ISDIR(info.st_mode))
+                                                       {
+                                                               ERROR1("%s is not a directory",optarg);
+                                                               exit_code = ENOTDIR;
+                                                               return -1;
+                                                       }       
+
+                                                       #else
                                                        char* path ;
                                                        
                                                        if(translatepath(optarg, &path) < 0)
@@ -942,26 +1119,42 @@ process_command_line(int argc, char** argv)
                                                                        
                                                                return -1;
                                                        }
+                                                       #endif
                                                        else
                                                        {
-                                                       
+                                                               int exists = 0;
+                                                               unsigned int i;
+                                                               directory_t cur;
+                                                               #ifdef WIN32
+                                                               directory = directory_new(optarg);
+                                                               #else
                                                                directory = directory_new(path);
                                                                free(path);
-                                                       
-                                                               if(vector_contains(include_dirs, directory))
+                                                               #endif
+
+                                                               xbt_dynar_foreach(include_dirs, i , cur)
+                                                               {
+                                                                       if(!strcmp(cur->name, optarg))
+                                                                       {
+                                                                               exists = 1;
+                                                                               break;
+                                                                       }
+                                                               }
+
+                                                               if(exists)
                                                                {
                                                                        directory_free((void**)&directory);
                                                                        WARN1("Include directory %s already specified to be used",optarg);
                                                                        
                                                                }
                                                                else
-                                                                       vector_push_back(include_dirs, directory);
+                                                                       xbt_dynar_push(include_dirs, &directory);
+
                                                        }
                                                }
                                                /* --exclude option */ 
                                                else if(!strcmp(entry->long_name,"exclude"))
                                                {
-                                                       
                                                        char* path;
                                                        char* delimiter;
                        
@@ -984,7 +1177,7 @@ process_command_line(int argc, char** argv)
                        
                                                        if(excludes_contains(excludes, fstream))
                                                        {
-                                                               fstream_free((void**)&fstream);
+                                                               fstream_free(&fstream);
                                                                WARN1("File %s already specified to be exclude", optarg);
                                                        }
                                                        else
@@ -994,7 +1187,7 @@ process_command_line(int argc, char** argv)
                                                /* --log option */
                                                else if(!strcmp(entry->long_name,"log"))
                                                {
-                                                       lstrings_push_back(logs, optarg);
+                                                       xbt_dynar_push(logs, &optarg);
                                                }
                                                else
                                                {
@@ -1050,14 +1243,11 @@ process_command_line(int argc, char** argv)
 }
 
 static void
-display_usage(void)
+print_usage(void)
 {
        const char **cpp;
        FILE* stream;
        
-       if (want_display_version)
-               display_version();
-       
        stream = exit_code ? stderr : stdout;
        
        fprintf (stream, "Usage: tesh [options] [file] ...\n");
@@ -1069,7 +1259,7 @@ display_usage(void)
 }
 
 static void
-display_version(void)
+print_version(void)
 {
        /* TODO : display the version of tesh */
        printf("Version :\n");
@@ -1080,12 +1270,12 @@ display_version(void)
        printf("  This program is free software; you can redistribute it and/or modify it\n");
        printf("  under the terms of the license (GNU LGPL) which comes with this package.\n\n");
        
-       if(!want_display_usage)
+       if(!print_usage_flag)
                printf("Report bugs to <martin.quinson@loria.fr | malek.cherier@loria.fr>");
 }
 
 static void
-display_semantic(void)
+print_readme(void)
 {
        size_t len;
        char * line = NULL;