Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
convert svn logs into ChangeLog (up to r7858 for now)
[simgrid.git] / tools / tesh2 / src / main.c
index 135e328..9bcd3ed 100644 (file)
@@ -1,60 +1,58 @@
-
+/*
+ * 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.
  */
-typedef struct s_optentry
-{
-       int c;                                                          /* the character of the option                                                                                  */
-       
-       /* 
-        * the type of the argument of the option 
-        */
-       enum                                            
-       {
-               flag,                                                   /* it's a flag option, by default the flag is set to zero                               */                                              
-               string,                                                 /* the option has strings as argument                                                                   */                                      
-               number                                                  /* the option has an integral positive number as argument                               */                      
-       }type;
-       
-       byte* value;                                            /* the value of the option                                                                                              */                      
-       byte* optional_value;                           /* the optional value of the option if not specified                                    */
-       const char * long_name;                         /* the long name of the command                                                                                 */
-}s_optentry_t,* optentry_t;
-
-
-
-XBT_LOG_NEW_DEFAULT_CATEGORY(tesh,"TEst SHell utility");
-
-#ifdef WIN32
-/* Windows specific : the previous process error mode                  */
-static UINT 
-prev_error_mode = 0;
-#endif
+typedef struct s_optentry {
+  int c;                        /* the character of the option                                                                                  */
+
+  /* 
+   * the type of the argument of the option 
+   */
+  enum {
+    flag,                       /* it's a flag option, by default the flag is set to zero                               */
+    string,                     /* the option has strings as argument                                                                   */
+    number                      /* the option has an integral positive number as argument                               */
+  } type;
 
-directory_t
-root_directory = NULL;
+  byte *value;                  /* the value of the option                                                                                              */
+  byte *optional_value;         /* the optional value of the option if not specified                                    */
+  const char *long_name;        /* the long name of the command                                                                                 */
+} s_optentry_t, *optentry_t;
 
-/*int
-exit_code = 0;
-*/
 
-int 
-want_detail_summary = 0;
+/* logs */
+XBT_LOG_NEW_DEFAULT_CATEGORY(tesh, "TEst SHell utility");
+
+#ifdef _XBT_WIN32
+/* Windows specific : the previous process error mode                  */
+static UINT prev_error_mode = 0;
+#endif
+
+/* this object represents the root directory */
+directory_t root_directory = NULL;
 
 /* the current version of tesh                                                                 */
-static const char* 
-version = "1.0";
+static const char *version = "1.0";
 
 /* ------------------------------------------------------------ */
 /* options                                                                                                             */
@@ -66,47 +64,39 @@ version = "1.0";
 
 
 /* --jobs is specified with arg                                                                        */
-static int 
-number_of_jobs = -2;
+static int
+ jobs_nb = -2;
 
 /* --jobs option is not specified (use the default job count)  */
-static int 
-default_number_of_jobs = 1;
+static int
+ default_jobs_nb = 1;
 
 /* --jobs is specified but has no arg (one job per unit)               */
-static int 
-optional_number_of_jobs = -1;
+static int
+ optional_jobs_nb = -1;
 
 /* the global timeout                                                                                  */
 static int
-timeout = INDEFINITE;
+ timeout = INDEFINITE;
 
 /* ------------------------------------------------------------ */
-/* strings dlists                                                                                              */
+/* strings                                                                                     */
 /* ------------------------------------------------------------ */
 
 /* --C change the directory before running the units                   */
-static directories_t 
-directories = NULL;
+static directories_t directories = NULL;
 
 /* the include directories : see the !i metacommand                            */
-vector_t 
-include_dirs = NULL;
+xbt_dynar_t include_dirs = NULL;
 
 /* the list of tesh files to run                                                               */
-static fstreams_t 
-fstreams = NULL;
+static fstreams_t fstreams = NULL;
 
-/* xbt logs                                                                                                            */
-static lstrings_t
-logs = NULL;
+/* the list of tesh file suffixes                                                              */
+static xbt_dynar_t suffixes = NULL;
 
-static excludes_t
-excludes = NULL;
+static excludes_t excludes = NULL;
 
-/* the ddlist of tesh file suffixes                                                            */
-static lstrings_t
-suffixes = NULL;
 
 /* ------------------------------------------------------------ */
 /* flags                                                                                                               */
@@ -115,303 +105,295 @@ suffixes = NULL;
 /* if 1, keep going when some commands can't be found
  * default value 0 : not keep going
  */
-int 
-want_keep_going = 0;
+int
+ keep_going_flag = 0;
 
 /* if 1, ignore failures from commands
  * default value : do not ignore failures
  */
-int 
-want_keep_going_unit = 0;
+int
+ keep_going_unit_flag = 0;
 
 /* if 1, display tesh usage                                                                            */
-static int 
-want_display_usage = 0;
+static int
+ print_usage_flag = 0;
 
 /* if 1, display the tesh version                                                              */
-static int 
-want_display_version = 0;
-
-/* if 1, the syntax of all tesh files is checked 
- * before running them
- */
 static int
-want_check_syntax = 0;
+ print_version_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;
+int
+ 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;
-
-int 
-want_silent = 0;
+ print_readme_flag = 0;
 
-int 
-want_just_display = 0;
-
-static int 
-env_overrides  = 0;
-
-static int 
-display_data_base = 0;
+int
+ silent_flag = 0;
 
-static int 
-question = 0;
+int
+ just_print_flag = 0;
 
 /* the semaphore used to synchronize the jobs */
-xbt_os_sem_t
-jobs_sem = NULL;
+xbt_os_sem_t jobs_sem = NULL;
 
 /* the semaphore used by the runner to wait the end of all the units */
-xbt_os_sem_t
-units_sem = NULL;
+xbt_os_sem_t units_sem = NULL;
 
 static int
-loaded = 0;
+ loaded = 0;
 
-int 
-interrupted = 0;
+int
+ interrupted = 0;
 
 int
-exit_code = 0; 
+ exit_code = 0;
 
-pid_t
-pid =0;
+int
+ err_kind = 0;
 
-/* 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", },
-       { '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*)&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"},
-       { 't', number, (byte*)&timeout, 0, "timeout" },
-       { 'S', flag, (byte*)&want_check_syntax, 0, "check-syntax"},
-       { '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"},
-       { 0, 0, 0, 0, 0}
-       
+char *err_line = NULL;
+
+
+pid_t pid = 0;
+
+int
+ is_tesh_root = 1;
+
+/* 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"},
+  {'f', string, (byte *) & fstreams, 0, "file"},
+  {'h', flag, (byte *) & print_usage_flag, 0, "help"},
+  {'a', flag, (byte *) & print_readme_flag, 0, "README"},
+  {'k', flag, (byte *) & keep_going_flag, 0, "keep-going"},
+  {'i', flag, (byte *) & keep_going_unit_flag, 0, "keep-going-unit"},
+  {'I', string, (byte *) & include_dirs, 0, "include-dir"},
+  {'j', number, (byte *) & jobs_nb, (byte *) & optional_jobs_nb, "jobs"},
+  {'m', flag, (byte *) & detail_summary_flag, 0, "detail-summary"},
+  {'c', flag, (byte *) & just_print_flag, 0, "just-print"},
+  {'s', flag, (byte *) & silent_flag, 0, "silent"},
+  {'V', flag, (byte *) & print_version_flag, 0, "version"},
+  {'w', flag, (byte *) & print_directory_flag, 0, "dont-print-directory"},
+  {'n', flag, (byte *) & dry_run_flag, 0, "dry-run"},
+  {'t', number, (byte *) & timeout, 0, "timeout"},
+  {'r', string, (byte *) & directories, 0, "load-directory"},
+  {'v', flag, (byte *) & summary_flag, 0, "summary"},
+  {'F', string, (byte *) & excludes, 0, "exclude"},
+  {'l', string, (byte *) NULL, 0, "log"},
+  {0, 0, 0, 0, 0}
 };
 
 /* the tesh usage                                                                                              */
-static const char* usage[] =
-{
-       "Options:\n",
-       "  -C DIRECTORY, --directory=DIRECTORY   Change to DIRECTORY before running any commands.\n",
-       "  -e, --environment-overrides           Environment variables override files.\n",
-       "  -f FILE, --file=FILE                  Read FILE as a teshfile.\n",
-       "                                           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",
-       "  -i, --keep-going-unit                 Ignore failures from commands.\n",
-       "                                        The possible failures are :\n",
-       "                                         - the exit code differ from the expected\n",
-       "                                         - the signal throw differ from the expected\n",
-       "                                         - the output differ from the expected\n",
-       "                                         - the read pipe is broken\n",
-       "                                         - the write pipe is broken\n",
-       "                                         - the command assigned delay is outdated\n",
-       "  -I DIRECTORY, --include-dir=DIRECTORY Search DIRECTORY for included files.\n",
-       "  -j [N], --jobs[=N]                    Allow N commands at once; infinite commands with\n"
-       "                                        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",
-       "  -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",
-       "  -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",
-       " -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
+static const char *usage[] = {
+  "Options:\n",
+  "  -C DIRECTORY, --directory=DIRECTORY   Change to DIRECTORY before running any commands.\n",
+  "  -e, --environment-overrides           Environment variables override files.\n",
+  "  -f FILE, --file=FILE                  Read FILE as a teshfile.\n",
+  "                                           remark :\n",
+  "                                           all argument of the command line without\n",
+  "                                           option is dealed as a tesh file.\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",
+  "                                         - the signal throw differ from the expected\n",
+  "                                         - the output differ from the expected\n",
+  "                                         - the read pipe is broken\n",
+  "                                         - the write pipe is broken\n",
+  "                                         - the command assigned delay is outdated\n",
+  "  -I DIRECTORY, --include-dir=DIRECTORY Search DIRECTORY for included files.\n",
+  "  -j [N], --jobs[=N]                    Allow N units at once; infinite units with\n"
+      "                                        no arg.\n",
+  "  -k, --keep-going                      Keep going when some commands can't be made or\n",
+  "                                        failed.\n",
+  "  -c, --just-print                      Don't actually run any commands; just print them.\n",
+  "  -s, --silent,                         Don't echo commands.\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",
+  "  -x, --suffix                          Consider the new suffix for the tesh files.\n"
+      "                                           remark :\n",
+  "                                           the default suffix for the tesh files is \".tesh\".\n",
+  " -a, --README                           Print the read me file and exit.\n",
+  " -r, --load-directory                   Run all the tesh files located in the directories specified by the option --directory.\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",
+  NULL
 };
 
-/* the string of options of tesh                                                               */                                                              
-static char 
-optstring[1 + sizeof (opt_entries) / sizeof (opt_entries[0]) * 3];
+/* the string of options of tesh                                                               */
+static char
+ optstring[1 + sizeof(opt_entries) / sizeof(opt_entries[0]) * 3];
 
 /* the option table of tesh                                                                            */
-static struct 
-option longopts[(sizeof (opt_entries) / sizeof (s_optentry_t))];
+static struct
+option longopts[(sizeof(opt_entries) / sizeof(s_optentry_t))];
 
-static void
-init_options(void);
+static void init_options(void);
 
-static int
-process_command_line(int argc, char** argv);
+static int process_command_line(int argc, char **argv);
 
-static void
-load(void);
+static void load(void);
 
-static void
-display_usage(void);
+static void print_usage(void);
 
-static void
-display_version(void);
+static void print_version(void);
 
-static void
-finalize(void);
+static void finalize(void);
 
-static void
-display_semantic(void);
+static void print_readme(void);
 
-static int
-init(void);
+static int init(void);
 
+static int screen_cleaned;
 
+static int finalized = 0;
 
-int
-main(int argc, char* argv[])
+static int sig_int = 0;
+
+#ifdef _XBT_WIN32
+static void sig_int_handler(int signum)
 {
-       if(init() < 0)
-               finalize();
-               
-       /* process the command line */
-       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);
-               char** cstr = lstrings_to_cstr(logs);
-               
-               xbt_init(&size, cstr);
-               
-               free(cstr);
-               
-       }
-       else
-               xbt_init(&argc, argv);
-       
-       /* the user wants to display the usage of tesh */
-       if(want_display_usage)
-               finalize();
-       
-       /* the user wants to display the version of tesh */
-       if(want_display_version)
-       {
-               display_version();
-               finalize();
-       }
-       
-       /* the user wants to display the semantic of the tesh file metacommands */
-       if(want_display_semantic)
-       {
-               display_semantic();
-               finalize();
-       }
-       
-       /* load tesh files */
-       load();
-       
-       
-       /* 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) */
-               number_of_jobs = default_number_of_jobs;
-       }
-       else if(optional_number_of_jobs == number_of_jobs)
-       {/* --jobs option is specified with no args (use one job per unit) */
-               number_of_jobs = fstreams_get_size(fstreams);
-       }
-
-       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 to run");
-               
-               /* assume one job per file */
-               number_of_jobs = fstreams_get_size(fstreams);
-       }
-
-       /* 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(runner_init(want_check_syntax, timeout, fstreams))
-               finalize();
-               
-       if(want_just_display && want_silent)
-               want_silent = 0;
-               
-       if(want_just_display && want_dry_run)
-               WARN0("mismatch in the syntax : --just-check-syntax and --just-display options at same time");
-       
-       /* run all the units */
-       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 (release all the allocated memory and exits) */
-       finalize();
-       
-       #ifndef WIN32
-       return exit_code;
-       #endif
-       
+
+  if (!finalized) {
+    sig_int = 1;
+    runner_interrupt();
+    while (!finalized);
+  }
+
+}
+#endif
+
+static void free_string(void *str)
+{
+  free(*(void **) str);
+}
+
+int main(int argc, char *argv[])
+{
+  /* set the locale to the default */
+  setlocale(LC_ALL, "");
+
+  /* xbt initialization */
+  xbt_init(&argc, argv);
+
+  /* initialize tesh */
+  if (init() < 0)
+    finalize();
+
+  /* process the command line */
+  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);
+
+  /* the user wants to display the usage of tesh */
+  if (print_version_flag) {
+    print_version();
+
+    if (!print_usage_flag)
+      finalize();
+  }
+
+  /* the user wants to display the usage of tesh */
+  if (print_usage_flag) {
+    print_usage();
+    finalize();
+  }
+
+  /* the user wants to display the semantic of the tesh file metacommands */
+  if (print_readme_flag) {
+    print_readme();
+    finalize();
+  }
+
+  /* load tesh files */
+  load();
+
+
+  /* use by the finalize function to known if it must display the tesh usage */
+  loaded = 1;
+
+  if (-2 == jobs_nb) {          /* --jobs is not specified (use the default value) */
+    jobs_nb = default_jobs_nb;
+  } else if (optional_jobs_nb == jobs_nb) {     /* --jobs option is specified with no args (use one job per unit) */
+    jobs_nb = 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 */
+    jobs_nb = fstreams_get_size(fstreams);
+  }
+
+  if (jobs_nb != 1 && dry_run_flag) {
+    jobs_nb = 1;
+    INFO0("Dry run specified : force jobs count to 1");
+  }
+
+  /* initialize the semaphore used to synchronize all the units */
+  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( /*check_syntax_flag, */ timeout, fstreams) < 0)
+    finalize();
+
+  if (just_print_flag && silent_flag)
+    silent_flag = 0;
+
+  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 */
+  runner_run();
+
+  if (runner_is_timedout())
+    ERROR1("Tesh timed out after `(%d)' seconds", timeout);
+
+  /* show the result of the units */
+  if (detail_summary_flag || summary_flag || dry_run_flag)
+    runner_summarize();
+
+  /* all the test are runned, destroy the runner */
+  runner_destroy();
+
+  /* then, finalize tesh (release all the allocated memory and exits) */
+  finalize();
+
+#ifndef _XBT_WIN32
+  return exit_code;
+#endif
+
 }
 
 /* init --     initialize tesh : allocated all the objects needed by tesh to run
@@ -423,262 +405,252 @@ main(int argc, char* argv[])
 
 
 
-static int
-init(void)
+static int init(void)
 {
-       char* buffer;
-       
-       
-       
-       #ifdef WIN32
-       /* Windows specific : don't display the general-protection-fault message box and
-        * the the critical-error-handler message box (instead the system send the error
-        * to the calling process : tesh)
-        */
-       prev_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
-       #endif
-       
-       /* 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;
-       }
-       
-       free(buffer);
-       
-       /* the directories to loads */
-       if(!(directories = directories_new()))
-       {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
-               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;
-       }
-       
-       /* xbt logs option */
-       if(!(logs = lstrings_new()))
-       {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
-               return -1;
-       }
-       
-       /* the excluded files */
-       if(!(excludes = excludes_new()))
-       {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
-               return -1;
-       }
-       
-       /* the suffixes */
-       if(!(suffixes = lstrings_new()))
-       {
-               ERROR0("Insufficient memory is available to initialize tesh : system error");
-               return -1;
-       }
-       
-       /* 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;
+  char *buffer;
+  char *suffix = strdup(".tesh");
+
+#ifdef _XBT_WIN32
+  /* Windows specific : don't display the general-protection-fault message box and
+   * the the critical-error-handler message box (instead the system send the error
+   * to the calling process : tesh)
+   */
+  prev_error_mode =
+      SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+
+  /* handle the interrupt signal */
+  signal(SIGINT, sig_int_handler);
+#else
+  /* 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 
+   */
+  /*
+     struct sigaction act;
+     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_int_handler;
+     sigaction(SIGINT, &act, NULL); */
+
+#endif
+
+
+
+
+  /* used to store the files to run */
+  if (!(fstreams = fstreams_new((void_f_pvoid_t) fstream_free))) {
+    ERROR1("(system error) %s", strerror(errno));
+    return -1;
+  }
+
+  /* register the current directory */
+  if (!(buffer = getcwd(NULL, 0))) {
+    ERROR1("(system error) %s", strerror(errno));
+    return -1;
+  }
+
+  /* save the root directory */
+  if (!(root_directory = directory_new(buffer))) {
+    ERROR1("(system error) %s", strerror(errno));
+    return -1;
+  }
+
+  free(buffer);
+
+  /* the directories to loads */
+  if (!(directories = directories_new())) {
+    ERROR1("(system error) %s", strerror(errno));
+    return -1;
+  }
+
+  /* the include directories */
+  include_dirs =
+      xbt_dynar_new(sizeof(directory_t), (void_f_pvoid_t) directory_free);
+
+  /* the excluded files */
+  if (!(excludes = excludes_new())) {
+    ERROR1("(system error) %s", strerror(errno));
+    return -1;
+  }
+
+  /* the suffixes */
+  suffixes = xbt_dynar_new(sizeof(char *), free_string);
+
+  /* register the default suffix ".tesh" */
+  xbt_dynar_push(suffixes, &suffix);
+
+  return 0;
 }
 
 /* load -- load the tesh files to run */
-static void
-load(void)
+static void load(void)
 {
-       
-       /* 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);
-       
-       /* 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 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);
-       
+
+  /* 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);
+
+  /* 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 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);
+
 }
 
 /* finalize -- cleanup all the allocated objects and display the tesh usage if needed */
-static void
-finalize(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();
-       
-       /* 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);
-               
-       /* 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 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
-       
-       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);
+  /* 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);
+
+  /* delete the root directory object */
+  if (root_directory)
+    directory_free((void **) &root_directory);
+
+  /* delete the include directories object */
+  if (include_dirs)
+    xbt_dynar_free(&include_dirs);
+
+  /* delete the list of tesh files suffixes */
+  if (suffixes)
+    xbt_dynar_free(&suffixes);
+
+  /* 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);
+
+  /* Windows specific (restore the previouse error mode */
+#ifdef _XBT_WIN32
+  SetErrorMode(prev_error_mode);
+#endif
+
+  if (sig_int)
+    INFO0("Tesh interrupted (receive a SIGINT)");
+  else if (!summary_flag && !detail_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 {
+      if (err_line)
+        ERROR3("Tesh terminated with exit code `(<%s> %s)' (%d)", err_line,
+               error_to_string(exit_code, err_kind), exit_code);
+      else
+        ERROR2("Tesh terminated with exit code `(%s)' (%d)",
+               error_to_string(exit_code, err_kind), exit_code);
+
+    }
+  }
+
+  if (err_line)
+    free(err_line);
+
+  /* exit from the xbt framework */
+
+  finalized = 1;
+
+  /* exit with the last error code */
+  if (!sig_int)
+    exit(exit_code);
 }
 
 /* init_options -- initialize the options string */
-static void
-init_options (void)
+static void init_options(void)
 {
-       char *p;
-       unsigned int i;
-       
-       /* the function has been already called */
-       if(optstring[0] != '\0')
-               return;
-       
-       p = optstring;
-       
-       
-       *p++ = '-';
-       
-       for (i = 0; opt_entries[i].c != '\0'; ++i)
-       {
-               /* initialize the long name of the option*/
-               longopts[i].name = (opt_entries[i].long_name == 0 ? "" : opt_entries[i].long_name);
-               
-               /* getopt_long returns the value of val */
-               longopts[i].flag = 0;
-               
-               /* the short option */
-               longopts[i].val = opt_entries[i].c;
-               
-               /* add the short option in the options string */
-               *p++ = opt_entries[i].c;
-               
-               switch (opt_entries[i].type)
-               {
-                       /* 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;
-               
-                       /* the option has an argument */
-                       case string:
-                       case number:
-                       
-                       *p++ = ':';
-                       
-                       if(opt_entries[i].optional_value != 0)
-                       {
-                               *p++ = ':';
-                               
-                               longopts[i].has_arg = optional_argument;
-                       }
-                       else
-                               longopts[i].has_arg = required_argument;
-                       
-                       break;
-               }
-       }
-       
-       *p = '\0';
-       longopts[i].name = 0;
+  char *p;
+  unsigned int i;
+
+  /* the function has been already called */
+  if (optstring[0] != '\0')
+    return;
+
+  p = optstring;
+
+  *p++ = '-';
+
+  for (i = 0; opt_entries[i].c != '\0'; ++i) {
+    /* initialize the long name of the option */
+    longopts[i].name =
+        (opt_entries[i].long_name == 0 ? "" : opt_entries[i].long_name);
+
+    /* getopt_long returns the value of val */
+    longopts[i].flag = 0;
+
+    /* the short option */
+    longopts[i].val = opt_entries[i].c;
+
+    /* add the short option in the options string */
+    *p++ = opt_entries[i].c;
+
+    switch (opt_entries[i].type) {
+      /* 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;
+
+      /* the option has an argument */
+    case string:
+    case number:
+
+      *p++ = ':';
+
+      if (opt_entries[i].optional_value != 0) {
+        *p++ = ':';
+
+        longopts[i].has_arg = optional_argument;
+      } else
+        longopts[i].has_arg = required_argument;
+
+      break;
+    }
+  }
+
+  *p = '\0';
+  longopts[i].name = 0;
 }
 
 /* process_command_line --     process the command line
@@ -691,418 +663,457 @@ init_options (void)
  *                                                     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)
+static int process_command_line(int argc, char **argv)
 {
-       register const struct s_optentry* entry;
-       register int c;
-       directory_t directory;
-       fstream_t fstream;
-       
-       /* initialize the options string of tesh */
-       init_options();
-       
-       /* 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);
-               
-               if(c == EOF)
-               {
-                       /* end of the command line or "--".  */
-                       break;
-               }
-               else if (c == 1)
-               {
-                       /* no option specified, assume it's a tesh file to run */
-                       char* path;
-                       char* delimiter;
-                       
-                       /* getpath returns -1 when the file to get the path doesn't exist */
-                       if(getpath(optarg, &path) < 0)
-                       {
-                               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;
-                       }
-                       
-                       /* get to the last / (if any) to get the short name of the file */
-                       delimiter = strrchr(optarg,'/');
-                       
-                       /* create a new file stream which represents the tesh file to run */
-                       fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
-                       
-                       free(path);
-                       
-                       /* 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))
-                       {
-                               fstream_free((void**)&fstream);
-                               WARN1("File %s already specified to be run", optarg);
-                       }
-                       else
-                               fstreams_add(fstreams, fstream);
-                               
-                       
-                               
-                       
-               }
-               else if (c == '?')
-               {
-                       /* unknown option, let getopt_long() displays the error */
-                       return -1;
-               }
-               else
-               {
-                       for(entry = opt_entries; entry->c != '\0'; ++entry)
-                               
-                               if(c == entry->c)
-                               {
-               
-                                       switch (entry->type)
-                                       {
-                                               /* impossible */
-                                               default:
-                                               ERROR0("Command line processing failed : internal error");
-                                               exit_code = EPROCCMDLINE;
-                                               return -1;
-                                               
-                                               
-                                               /* flag options */
-                                               case flag:
-                                               /* set the flag to one */
-                                               *(int*) entry->value = 1;
-                                               
-                                               break;
-                                               
-                                               /* string options */
-                                               case string:
-               
-                                               if(!optarg)
-                                               {
-                                                       /* an option with a optional arg is specified use the entry->optional_value */
-                                                       optarg = (char*)entry->optional_value;
-                                               }
-                                               else if (*optarg == '\0')
-                                               {
-                                                       /* a non optional argument is not specified */
-                                                       ERROR2("Option %c \"%s\"requires an argument",entry->c,entry->long_name);
-                                                       exit_code = ENOARG;
-                                                       return -1;
-                                               }
-                                               
-                                               /* --load-directory option */
-                                               if(!strcmp(entry->long_name,"load-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
-                                                       {
-                                                               directory = directory_new(path);
-                                                               free(path);
-                                               
-                                                               if(directories_contains(directories, directory))
-                                                               {
-                                                                       directory_free((void**)&directory);
-                                                                       WARN1("Directory %s already specified to be load",optarg);
-                                                               }
-                                                               else
-                                                                        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);
-                                                               exit_code = ESUFFIXTOOLONG;     
-                                                               return -1;
-                                                       }
-                                                       
-                                                       if(optarg[0] == '.')
-                                                       {
-                                                               char suffix[MAX_SUFFIX + 2] = {0};
-                                                               sprintf(suffix,".%s",optarg);
-                                                               
-                                                               if(lstrings_contains(suffixes, suffix))
-                                                                       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 to be used", optarg);
-                                                               else
-                                                                       lstrings_push_back(suffixes, optarg);   
-                                                       }
-                                               }
-                                               /* --file option */
-                                               else if(!strcmp(entry->long_name,"file"))
-                                               {
-                                                       char* path;
-                                                       char* delimiter;
-                                                       
-                                                       if(getpath(optarg, &path) < 0)
-                                                       {
-                                                               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;
-                                                       }
-                                                       
-                                                       delimiter = strrchr(optarg,'/');
-                                                       
-                                                       fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
-                                                       
-                                                       free(path);
-                                                       
-                                                       if(fstreams_contains(fstreams, fstream))
-                                                       {
-                                                               fstream_free((void**)&fstream);
-                                                               WARN1("File %s already specified to run", optarg);
-                                                       }
-                                                       else
-                                                               fstreams_add(fstreams, fstream);
-                                               }
-                                               /* --include-dir option */
-                                               else if(!strcmp(entry->long_name,"include-dir"))
-                                               {
-                                                       
-                                                       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
-                                                       {
-                                                       
-                                                               directory = directory_new(path);
-                                                               free(path);
-                                                       
-                                                               if(vector_contains(include_dirs, directory))
-                                                               {
-                                                                       directory_free((void**)&directory);
-                                                                       WARN1("Include directory %s already specified to be used",optarg);
-                                                                       
-                                                               }
-                                                               else
-                                                                       vector_push_back(include_dirs, directory);
-                                                       }
-                                               }
-                                               /* --exclude option */ 
-                                               else if(!strcmp(entry->long_name,"exclude"))
-                                               {
-                                                       
-                                                       char* path;
-                                                       char* delimiter;
-                       
-                                                       if(getpath(optarg, &path) < 0)
-                                                       {
-                                                               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;
-                                                       }
-                       
-                                                       delimiter = strrchr(optarg,'/');
-                       
-                                                       fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
-                                                       free(path);
-                       
-                                                       if(excludes_contains(excludes, fstream))
-                                                       {
-                                                               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"))
-                                               {
-                                                       lstrings_push_back(logs, optarg);
-                                               }
-                                               else
-                                               {
-                                                       INFO1("Unexpected option %s", optarg);
-                                                       return -1;
-                                               }
-                                               
-                                               
-                                               break;
-                                               
-                                               /* strictly positve number options */
-                                               case number:
-                                                       
-                                               if ((NULL == optarg) && (argc > optind))
-                                               {
-                                                       const char* cp;
-                                                       
-                                                       for (cp = argv[optind]; isdigit(cp[0]); ++cp)
-                                                               if(cp[0] == '\0')
-                                                                       optarg = argv[optind++];
-                                               }
-               
-                                               /* the number option is specified */
-                                               if(NULL != optarg)
-                                               {
-                                                       int i = atoi(optarg);
-                                                       const char *cp;
-
-                                                       for (cp = optarg; isdigit(cp[0]); ++cp);
-               
-                                                       if (i < 1 || cp[0] != '\0')
-                                                       {
-                                                               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;
-                                               }
-                                               /* the number option is specified but has no arg, use the optional value*/
-                                               else
-                                                       *(int*)entry->value = *(int*) entry->optional_value;
-                                               
-                                               break;
-               
-                               }
-                               break;
-                       }
-               }
-       }
-
-       return 0;
+  register const struct s_optentry *entry;
+  register int c;
+  directory_t directory;
+  fstream_t fstream;
+
+  /* initialize the options string of tesh */
+  init_options();
+
+  /* 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);
+
+    if (c == EOF) {
+      /* end of the command line or "--".  */
+      break;
+    } else if (c == 1) {
+      /* no option specified, assume it's a tesh file to run */
+      char *path;
+      char *delimiter;
+
+      /* getpath returns -1 when the file to get the path doesn't exist */
+      if (getpath(optarg, &path) < 0) {
+        exit_code = errno;
+        err_kind = 0;
+
+        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;
+      }
+
+      /* get to the last / (if any) to get the short name of the file */
+      delimiter = strrchr(optarg, '/');
+
+#ifdef _XBT_WIN32
+      if (!delimiter)
+        delimiter = strrchr(optarg, '\\');
+#endif
+
+      /* create a new file stream which represents the tesh file to run */
+      fstream = fstream_new(path, delimiter ? delimiter + 1 : optarg);
+
+      free(path);
+
+      /* 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)) {
+        fstream_free(&fstream);
+        WARN1("File %s already specified to be run", optarg);
+      } else
+        fstreams_add(fstreams, fstream);
+
+    } else if (c == '?') {
+      /* unknown option, let getopt_long() displays the error */
+      ERROR0("Command line processing failed : invalid command line");
+      exit_code = EINVCMDLINE;
+      err_kind = 1;
+      return -1;
+    } else {
+      for (entry = opt_entries; entry->c != '\0'; ++entry)
+
+        if (c == entry->c) {
+
+          switch (entry->type) {
+            /* impossible */
+          default:
+            ERROR0("Command line processing failed : internal error");
+            exit_code = EPROCCMDLINE;
+            err_kind = 1;
+            return -1;
+
+
+            /* flag options */
+          case flag:
+            /* set the flag to one */
+            *(int *) entry->value = 1;
+
+            break;
+
+            /* string options */
+          case string:
+
+            if (!optarg) {
+              /* an option with a optional arg is specified use the entry->optional_value */
+              optarg = (char *) entry->optional_value;
+            } else if (*optarg == '\0') {
+              /* a non optional argument is not specified */
+              ERROR2("Option %c \"%s\"requires an argument", entry->c,
+                     entry->long_name);
+              exit_code = ENOARG;
+              err_kind = 1;
+              return -1;
+            }
+
+            /* --load-directory option */
+            if (!strcmp(entry->long_name, "load-directory")) {
+              char *path;
+
+              if (translatepath(optarg, &path) < 0) {
+                exit_code = errno;
+                err_kind = 0;
+
+                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 {
+
+                directory = directory_new(path);
+                free(path);
+
+                if (directories_contains(directories, directory)) {
+                  directory_free((void **) &directory);
+                  WARN1("Directory %s already specified to be load",
+                        optarg);
+                } else
+                  directories_add(directories, directory);
+
+
+              }
+            } else if (!strcmp(entry->long_name, "directory")) {
+              char *path;
+
+              if (translatepath(optarg, &path) < 0) {
+                exit_code = errno;
+                err_kind = 0;
+
+                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 {
+                char *buffer = getcwd(NULL, 0);
+
+
+                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);
+
+                free(buffer);
+              }
+            }
+
+            /* --suffix option */
+            else if (!strcmp(entry->long_name, "suffix")) {
+              if (strlen(optarg) > MAX_SUFFIX) {
+                ERROR1("Suffix %s too long", optarg);
+                exit_code = ESUFFIXTOOLONG;
+                err_kind = 1;
+                return -1;
+              }
+
+              if (optarg[0] == '.') {
+                char *cur;
+                unsigned int i;
+                int exists = 0;
+
+                char *suffix = xbt_new0(char, MAX_SUFFIX + 2);
+                sprintf(suffix, ".%s", optarg);
+
+                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
+                  xbt_dynar_push(suffixes, &suffix);
+              } else {
+                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 {
+                  char *suffix = strdup(optarg);
+                  xbt_dynar_push(suffixes, &suffix);
+                }
+              }
+            }
+            /* --file option */
+            else if (!strcmp(entry->long_name, "file")) {
+              char *path;
+              char *delimiter;
+
+              if (getpath(optarg, &path) < 0) {
+                exit_code = errno;
+                err_kind = 0;
+
+                if (ENOENT == errno)
+                  ERROR1("File %s does not exist", optarg);
+                else
+                  ERROR1("System error :`(%s)'", strerror(errno));
+
+                return -1;
+              }
+
+              delimiter = strrchr(optarg, '/');
+
+#ifdef _XBT_WIN32
+              if (!delimiter)
+                delimiter = strrchr(optarg, '\\');
+#endif
+
+              fstream =
+                  fstream_new(path, delimiter ? delimiter + 1 : optarg);
+
+              free(path);
+
+              if (fstreams_contains(fstreams, fstream)) {
+                fstream_free(&fstream);
+                WARN1("File %s already specified to run", optarg);
+              } else
+                fstreams_add(fstreams, fstream);
+            }
+            /* --include-dir option */
+            else if (!strcmp(entry->long_name, "include-dir")) {
+
+              char *path;
+
+              if (translatepath(optarg, &path) < 0) {
+                exit_code = errno;
+                err_kind = 0;
+
+                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 {
+                int exists = 0;
+                unsigned int i;
+                directory_t cur;
+                directory = directory_new(path);
+                free(path);
+
+                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
+                  xbt_dynar_push(include_dirs, &directory);
+
+              }
+            }
+            /* --exclude option */
+            else if (!strcmp(entry->long_name, "exclude")) {
+              char *path;
+              char *delimiter;
+
+              if (getpath(optarg, &path) < 0) {
+                exit_code = errno;
+                err_kind = 0;
+
+                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;
+              }
+
+              delimiter = strrchr(optarg, '/');
+
+#ifdef _XBT_WIN32
+              if (!delimiter)
+                delimiter = strrchr(optarg, '\\');
+#endif
+
+              fstream =
+                  fstream_new(path, delimiter ? delimiter + 1 : optarg);
+              free(path);
+
+              if (excludes_contains(excludes, fstream)) {
+                fstream_free(&fstream);
+                WARN1("File %s already specified to be exclude", optarg);
+              } else
+                excludes_add(excludes, fstream);
+
+            } else if (!strcmp(entry->long_name, "log")) {
+              /* NOTHING TODO : log for xbt */
+            } else {
+              INFO1("Unexpected option %s", optarg);
+              return -1;
+            }
+
+
+            break;
+
+            /* strictly positve number options */
+          case number:
+
+            if ((NULL == optarg) && (argc > optind)) {
+              const char *cp;
+
+              for (cp = argv[optind]; isdigit(cp[0]); ++cp)
+                if (cp[0] == '\0')
+                  optarg = argv[optind++];
+            }
+
+            /* the number option is specified */
+            if (NULL != optarg) {
+              int i = atoi(optarg);
+              const char *cp;
+
+              for (cp = optarg; isdigit(cp[0]); ++cp);
+
+              if (i < 1 || cp[0] != '\0') {
+                ERROR2
+                    ("Option %c \"%s\" requires an strictly positive integer as argument",
+                     entry->c, entry->long_name);
+                exit_code = ENOTPOSITIVENUM;
+                err_kind = 1;
+                return -1;
+              } else
+                *(int *) entry->value = i;
+            }
+            /* the number option is specified but has no arg, use the optional value */
+            else
+              *(int *) entry->value = *(int *) entry->optional_value;
+
+            break;
+
+          }
+          break;
+        }
+    }
+  }
+
+  return 0;
 }
 
-static void
-display_usage(void)
+static 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");
-       
-       for (cpp = usage; *cpp; ++cpp)
-               fputs (*cpp, stream);
-       
-       fprintf(stream, "\nReport bugs to <martin.quinson@loria.fr | malek.cherier@loria.fr>\n");
+  const char **cpp;
+  FILE *stream;
+
+  stream = exit_code ? stderr : stdout;
+
+  if (!screen_cleaned) {
+#ifdef _XBT_WIN32
+    system("cls");
+#else
+    system("clear");
+#endif
+    screen_cleaned = 1;
+  }
+
+  fprintf(stream, "Usage: tesh [options] [file] ...\n");
+
+  for (cpp = usage; *cpp; ++cpp)
+    fputs(*cpp, stream);
+
+  fprintf(stream,
+          "\nReport bugs to <martin.quinson@loria.fr | malek.cherier@loria.fr>\n");
 }
 
-static void
-display_version(void)
+static void print_version(void)
 {
-       /* TODO : display the version of tesh */
-       printf("Version :\n");
-       printf("  tesh version %s : Mini shell specialized in running test units by Martin Quinson \n", version);
-       printf("  and Malek Cherier\n");
-       printf("  Copyright (c) 2007, 2008 Martin Quinson, Malek Cherier\n");
-       printf("  All rights reserved\n");
-       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)
-               printf("Report bugs to <martin.quinson@loria.fr | malek.cherier@loria.fr>");
+  if (!screen_cleaned) {
+#ifdef _XBT_WIN32
+    system("cls");
+#else
+    system("clear");
+#endif
+    screen_cleaned = 1;
+  }
+
+  /* TODO : display the version of tesh */
+  printf("Version :\n");
+  printf
+      ("  tesh version %s : Mini shell specialized in running test units by Martin Quinson \n",
+       version);
+  printf("  and Malek Cherier\n");
+  printf("  Copyright (c) 2007, 2008 Martin Quinson, Malek Cherier\n");
+  printf("  All rights reserved\n");
+  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 (!print_usage_flag)
+    printf
+        ("Report bugs to <martin.quinson@loria.fr | malek.cherier@loria.fr>");
 }
 
-static void
-display_semantic(void)
+static void print_readme(void)
 {
-       size_t len;
-       char * line = NULL;
-       
-       FILE* stream = fopen("README.txt", "r");
-       
-       if(!stream)
-       {
-               ERROR0("Unable to locate the README.txt file");
-               exit_code = EREADMENOTFOUND;
-               return;
-       }
-       
-       while(getline(&line, &len, stream) != -1)
-               printf("%s",line);
-               
-       fclose(stream);
-}
+  size_t len;
+  char *line = NULL;
+
+  FILE *stream = fopen("examples/README.tesh", "r");
 
+  if (!stream) {
+    ERROR0("Unable to locate the README.txt file");
+    exit_code = EREADMENOTFOUND;
+    err_kind = 1;
+    return;
+  }
 
+  while (getline(&line, &len, stream) != -1)
+    printf("%s", line);
+
+  fclose(stream);
+}