Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last change of Tesh2
authorcherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Fri, 6 Jun 2008 15:55:38 +0000 (15:55 +0000)
committercherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Fri, 6 Jun 2008 15:55:38 +0000 (15:55 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@5561 48e7efb5-ca39-0410-a469-dd3cf9ba447f

27 files changed:
tools/tesh2/examples/IO-orders.tesh
tools/tesh2/examples/background.tesh
tools/tesh2/examples/catch-global-timeout.tesh
tools/tesh2/examples/catch-return.tesh
tools/tesh2/examples/catch-signal.tesh
tools/tesh2/examples/catch-timeout.tesh
tools/tesh2/examples/catch-wrong-output.tesh
tools/tesh2/examples/cd.tesh
tools/tesh2/examples/jobs.tesh
tools/tesh2/examples/keep-going-unit.tesh
tools/tesh2/examples/keep-going.tesh
tools/tesh2/examples/set-ignore-output.tesh
tools/tesh2/examples/suite-usage.tesh
tools/tesh2/examples/var.tesh
tools/tesh2/src/command.c
tools/tesh2/src/fstream.c
tools/tesh2/src/getpath.c
tools/tesh2/src/is_cmd.c
tools/tesh2/src/main.c
tools/tesh2/src/reader.c
tools/tesh2/src/runner.c
tools/tesh2/src/unit.c
tools/tesh2/src/units.c
tools/tesh2/src/writer.c
tools/tesh2/tesh/tesh.vcproj
tools/tesh2/w32/Cat/Cat.vcproj
tools/tesh2/w32/src/getopt.c

index ab0c9f3..3cc8033 100644 (file)
@@ -8,7 +8,7 @@ p Order: in, out, cmd
 > Test unit from stdin
 > [stdin:3] cat
 > Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 
 p Order: out, in, cmd
 < > TOTO
@@ -17,7 +17,7 @@ p Order: out, in, cmd
 > Test unit from stdin
 > [stdin:3] cat
 > Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 
 p Order: out, cmd, in
 < > TOTO
@@ -26,7 +26,7 @@ p Order: out, cmd, in
 > Test unit from stdin
 > [stdin:2] cat
 > Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 
 p Order: in, cmd, out
 < < TOTO
@@ -35,5 +35,5 @@ p Order: in, cmd, out
 > Test unit from stdin
 > [stdin:2] cat
 > Test unit from stdin OK
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 
index a416496..6838a01 100644 (file)
@@ -9,6 +9,10 @@ $ cd temp_testdir
 < #include <sys/types.h>
 < #include <sys/stat.h>
 < #include <fcntl.h>
+< 
+< #ifdef __MINGW32__
+< #define sleep        _sleep
+< #endif
 <                   
 < int main() {
 <   char buff[2048];
index 15285c4..c361e93 100644 (file)
@@ -3,9 +3,9 @@
 \r
 ! expect return $ELEADTIME\r
 \r
-< $ sleep 30\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --timeout=3\r
+< $ sleep 10\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --timeout=1\r
 > Test unit from stdin\r
-> [stdin:1] sleep 30\r
+> [stdin:1] sleep 10\r
 > Test unit from stdin INTR\r
-> Tesh timed out after `(3)' seconds\r
+> Tesh timed out after `(1)' seconds\r
index 41d8433..00a3750 100644 (file)
@@ -1 +1 @@
-#! ./tesh\r# This suite builds and uses a program returning 1.\r# tesh must detect this condition and report the issue.\r\r$ rm -rf temp_testdir\r$ mkdir temp_testdir\r\r$ cd temp_testdir\r\r< #include <stdlib.h>\r< int main(void) {\r<   exit(1);\r< }\r$ cat > return1.c\r\r$ gcc -o return1 return1.c\r\r\r\r! expect return $EEXITCODENOTMATCH\r< $ ./return1\r$ ../tesh --log='log.thresh:info tesh.fmt:%m%n'\r> Test unit from stdin\r> [stdin:1] ./return1\r> [stdin:1] ./return1 : NOK (returned code `1' instead `0')\r> Output of <stdin:1> so far: \r> ||\r> Test unit `(stdin)' : NOK (exit code mismatch)\r\r\r\r$ cd ..\r$ rm -rf temp_testdir\r
\ No newline at end of file
+#! ./tesh\r# This suite builds and uses a program returning 1.\r# tesh must detect this condition and report the issue.\r\r$ rm -rf temp_testdir\r$ mkdir temp_testdir\r\r$ cd temp_testdir\r\r< #include <stdlib.h>\r< int main(void) {\r<   exit(1);\r< }\r$ cat > return1.c\r\r$ gcc -o return1 return1.c\r\r\r\r! expect return $EEXITCODENOTMATCH\r< $ ./return1\r$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"\r> Test unit from stdin\r> [stdin:1] ./return1\r> [stdin:1] ./return1 : NOK (returned code `1' instead `0')\r> Output of <stdin:1> so far: \r> ||\r> Test unit `(stdin)' : NOK (exit code mismatch)\r\r\r\r$ cd ..\r$ rm -rf temp_testdir\r
\ No newline at end of file
index 5a11512..b633b8a 100644 (file)
@@ -17,7 +17,7 @@ $ gcc -o segfault segfault.c
 
 ! expect return $EUNXPSIG
 < $ ./segfault
-$ ../tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"
 > Test unit from stdin
 > [stdin:1] ./segfault
 > [stdin:1] `./segfault' : NOK (unexpected signal `SIGSEGV' caught)
index 8a16fb5..d2a669e 100644 (file)
@@ -12,4 +12,4 @@
 > [stdin:2] Kill the process `sleep 6'
 > [stdin:2] No output before timeout
 > Test unit `(stdin)' : NOK (command timed out)
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
index 8774a77..3883f26 100644 (file)
@@ -6,7 +6,7 @@ p This tests whether TESH detects wrong outputs
 < > TOTO
 < < TUTU
 < $ cat
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 > Test unit from stdin
 > [stdin:3] cat
 > [stdin:3] `cat' : NOK (outputs mismatch):
index c1e52c9..6b804a1 100644 (file)
@@ -16,11 +16,11 @@ $ ls
 > [stdin:1] cd toto
 > [stdin:1] Chdir to toto failed: no such file or directory
 > Test unit `(stdin)' : NOK (no such file or directory)
-$ ../tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ../tesh --log="log.thresh:info tesh.fmt:%m%n"
 
 # The next command checks that there is a testdir_temp in the upper directory, 
 # ie that mkdir and cd both worked.
-$ test -e ../testdir_temp
+#$ test -e ../testdir_temp
 
 $ cd ..
 $ rmdir testdir_temp
index 4e9a0da..4198bb3 100644 (file)
@@ -20,7 +20,7 @@ $ gcc -o job job.c
 # Ignore output of the command because we can't known the order of the execution of the Tesh files.\r
 ! output ignore\r
 \r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' --silent --jobs --directory=examples jobs1.tesh jobs2.tesh jobs3.tesh jobs4.tesh jobs5.tesh jobs6.tesh jobs7.tesh jobs8.tesh jobs9.tesh \r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" --silent --jobs --directory=examples jobs1.tesh jobs2.tesh jobs3.tesh jobs4.tesh jobs5.tesh jobs6.tesh jobs7.tesh jobs8.tesh jobs9.tesh \r
 \r
 \r
 $ rm -f job\r
index 22ce9dc..61f179d 100644 (file)
@@ -39,7 +39,7 @@ $ gcc -o job job.c
 < ! expect return 0\r
 < > Hello Tesh\r
 < $ ./job\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"\r
 > Test unit from stdin\r
 > [stdin:3] ./job\r
 > [stdin:3] ./job : NOK (returned code `0' instead `1')\r
@@ -71,7 +71,7 @@ $ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
 < ! expect return 0\r
 < > Hello Tesh\r
 < $ ./job\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'  --keep-going-unit\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"  --keep-going-unit\r
 > Test unit from stdin\r
 > [stdin:3] ./job\r
 > [stdin:3] ./job : NOK (returned code `0' instead `1')\r
index a1a2032..345ec50 100644 (file)
@@ -63,7 +63,7 @@ $ cat > file2.tesh
 ! expect return $EEXITCODENOTMATCH\r
 \r
 # in this case the option `keep-going' is not specified so Tesh detects the error and interrupt all the folowing units.\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" file1.tesh file2.tesh\r
 > Test unit from file1.tesh\r
 > [file1.tesh:3] ./job\r
 > [file1.tesh:3] ./job : NOK (returned code `0' instead `1')\r
@@ -71,8 +71,6 @@ $ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh
 > ||Hello Tesh\r
 > ||\r
 > Test unit `(file1.tesh)' : NOK (exit code mismatch)\r
-> Test unit from file2.tesh\r
-> Test unit from file2.tesh INTR\r
 \r
 < ! expect return 1\r
 < > Hello Tesh\r
@@ -119,7 +117,7 @@ $ cat > file2.tesh
 ! expect return $EEXITCODENOTMATCH\r
 \r
 # in this case the option `keep-going' is specified so, Tesh execute all the other units.\r
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n' file1.tesh file2.tesh  --keep-going\r
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n" file1.tesh file2.tesh  --keep-going\r
 > Test unit from file1.tesh\r
 > [file1.tesh:3] ./job\r
 > [file1.tesh:3] ./job : NOK (returned code `0' instead `1')\r
index 285bd3a..818cf38 100644 (file)
@@ -6,7 +6,7 @@ p This tests whether TESH accepts to ignore command output
 < > TOTO
 < < TUTU
 < $ cat
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 > Test unit from stdin
 > [stdin:4] cat
 > (ignoring the output of <stdin:4> as requested)
index 140234b..bc0465b 100644 (file)
@@ -9,11 +9,6 @@
 ! include catch-signal.tesh
 ! include set-timeout.tesh
 
-
-# a command
-$ echo Hello Tesh
->  Hello Tesh
-
 # some includes
 ! include catch-wrong-output.tesh
 
index 631d608..bcf40a3 100644 (file)
@@ -23,7 +23,7 @@ D Usage of tesh variables
 ! expect return $ESYNTAX
 < ! include-file=
 < ! include $include-file
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 > Test unit from stdin
 > [stdin:1] Undefined variable `(include-file)'
 > Test unit `(stdin)' : NOK (syntax error)
@@ -100,7 +100,7 @@ p On this platform ENOENT is: $ENOENT
 ! expect return $ESYNTAX
 < ! ENOENT=300
 < $ echo $ENOENT
-$ ./tesh --log='log.thresh:info tesh.fmt:%m%n'
+$ ./tesh --log="log.thresh:info tesh.fmt:%m%n"
 > Test unit from stdin
 > [stdin:1] A system variable named `(ENOENT)' already exists
 > Test unit `(stdin)' : NOK (syntax error)
index bb78758..ab86d56 100644 (file)
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#else
+char *\r
+tow32cmd(const char* cmd)\r
+{\r
+       static char w32cmd[PATH_MAX + 1] = {0};\r
+       char cmd_buf[PATH_MAX + 1] = {0};\r
+    size_t i,j, len;\r
+    \r
+    if(!cmd)\r
+    {\r
+       errno = EINVAL;\r
+               return NULL;\r
+       }\r
+       \r
+       /* TODO : if ~*/\r
+       if(cmd[0] != '.')\r
+       {\r
+               strcpy(w32cmd, cmd);\r
+               return w32cmd;\r
+       }\r
+       \r
+       i = j = 0;\r
+       len = strlen(cmd);\r
+       \r
+       while(i < len)\r
+       {\r
+               if(cmd[i] != ' ' && cmd[i] != '\t' && cmd[i] != '>')\r
+                       cmd_buf[j++] = cmd[i];\r
+               else\r
+                       break;\r
+                       \r
+               i++;\r
+       }\r
+\r
+   _fullpath(w32cmd, cmd_buf, sizeof(w32cmd));\r
+   \r
+   if(!strstr(w32cmd, ".exe"))\r
+               strcat(w32cmd, ".exe ");\r
+   \r
+   strcat(w32cmd, cmd + i);\r
+   \r
+   \r
+   /*printf("w32cmd : %s", w32cmd);*/\r
+\r
+   return w32cmd;\r
+}
 #endif
 
 #include <com.h>
@@ -116,7 +162,6 @@ command_new(unit_t unit, context_t context, xbt_os_mutex_t mutex)
 int
 command_run(command_t command)
 {
-       
        if(!silent_flag)
                INFO2("[%s] %s",command->context->pos, command->context->command_line);
        
@@ -140,6 +185,8 @@ command_run(command_t command)
                {
                        command_interrupt(command);             
                }
+
+               
        }
        
        return 0;
@@ -205,6 +252,10 @@ command_start(void* p)
 }
 
 #ifdef WIN32
+
+#ifndef BUFSIZE
+#define BUFSIZE        4096\r
+#endif
 void
 command_exec(command_t command, const char* command_line)
 {
@@ -216,6 +267,7 @@ command_exec(command_t command, const char* command_line)
        HANDLE child_stdout_handle[2] = {NULL}; /* child_stdout_handle[0]       <-> stdin of the child process  */
        HANDLE child_stderr = NULL;
        
+
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
     sa.lpSecurityDescriptor = NULL;                    /* use default security for the pipe handles                            */
        
@@ -300,10 +352,10 @@ command_exec(command_t command, const char* command_line)
 
                return;
     }
-
        
        CloseHandle(child_stdin_handle[0]);
        CloseHandle(child_stdout_handle[1]);
+
        
        if(command->timer)
        {
@@ -324,6 +376,18 @@ command_exec(command_t command, const char* command_line)
                writer_write(command->writer);
        }
 
+       /* if there is a reader wait for its starting */
+       if(command->reader)
+               xbt_os_sem_acquire(command->reader->started);
+       
+       /* if there is a reader wait for its ending */
+       if(command->writer)
+               xbt_os_sem_acquire(command->writer->written);
+       
+       /* if there is a reader wait for its starting */
+       if(command->timer)
+               xbt_os_sem_acquire(command->timer->started);
+
     si.cb = sizeof(STARTUPINFO);
        
        si.dwFlags |= STARTF_USESTDHANDLES;
@@ -334,7 +398,7 @@ command_exec(command_t command, const char* command_line)
        /* launch the process */
        if(!CreateProcess(
                                                NULL,
-                                               (char*)command_line,
+                                               tow32cmd(command_line),
                                                NULL,
                                                NULL,
                                                TRUE,
@@ -345,11 +409,21 @@ command_exec(command_t command, const char* command_line)
                                                &pi)
        )
        {
-               ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
 
-               command_handle_failure(command,csr_create_process_function_failure);
+               if(ERROR_FILE_NOT_FOUND == GetLastError())
+               {
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string(ECMDNOTFOUND, 1));
+                       unit_set_error(command->unit, ECMDNOTFOUND, 1);
+                       command_handle_failure(command, csr_command_not_found);
+               }
+               else
+               {
+                       ERROR3("[%s] `%s' : NOK (%s)", command->context->pos, command->context->command_line, error_to_string((int)GetLastError(), 0));
 
-               unit_set_error(command->unit, (int)GetLastError(), 0);
+                       unit_set_error(command->unit, (int)GetLastError(), 0);
+                       command_handle_failure(command, csr_create_process_function_failure);
+               }
+               
     }
        else
        {
@@ -968,7 +1042,7 @@ command_summarize(command_t command)
                        break;
                        
                        case csr_unexpected_signal_caught:
-                       printf("                reason                      : unexpected signal caught\n");
+                       printf("          reason                      : unexpected signal caught\n");
                        break;
                        
                        case csr_expected_signal_not_receipt :
@@ -1007,15 +1081,22 @@ command_summarize(command_t command)
                else
                        printf("          no expected exit code specified\n");
                
-               /* if an expected exit code was specified display it */
+               /* no expected signal expected */
                if(NULL == command->context->signal)
+               {
                        printf("          no expected signal specified\n");
+
+                       if(command->signal)
+                               printf("          but got signal              : %s\n",command->signal);
+                               
+               }
+               /* if an expected exit code was specified display it */
                else
                {
                        if(NULL != command->signal)
                                printf("          signal                      : %s\n",command->signal);
-                       
-                       printf("          expected signal             : %s\n",command->context->signal);
+                       else
+                               printf("          no signal caugth\n");
                }
                
                /* if the command has out put and the metacommand display output is specified display it  */
@@ -1035,7 +1116,6 @@ command_summarize(command_t command)
 void
 command_handle_failure(command_t command, cs_reason_t reason)
 {
-       
        unit_t root = command->root;
        
        xbt_os_mutex_acquire(command->mutex);
index 403d184..166e256 100644 (file)
@@ -149,7 +149,9 @@ fstream_open(fstream_t fstream)
     #endif\r
 \r
        if(!(fstream->stream = fopen(path, "r")))\r
+       {\r
                return -1;\r
+       }\r
        \r
        return 0;\r
 }\r
index fc40068..a46c4fe 100644 (file)
@@ -335,10 +335,127 @@ getpath(const char* file, char** path)
 int\r
 translatepath(const char* totranslate, char** translated)\r
 {\r
-\r
-       return 0;\r
+       char buffer1[PATH_MAX + 1] = {0};               \r
+       char buffer2[PATH_MAX + 1] = {0};\r
+       char *p1;\r
+       int i, j, len;\r
+       \r
+       struct stat stat_buf = {0};\r
+       \r
+       /* return the current directory */\r
+       if(!strcmp(totranslate,".") || !strcmp(totranslate,"./"))\r
+       {\r
+               *translated = getcwd(NULL,0);\r
+               return (int)strlen(*translated);\r
+       }\r
+       /* return the previous directory */\r
+       else if(!strcmp(totranslate,"..") || !strcmp(totranslate,"../"))\r
+       {\r
+               getcwd(buffer1, PATH_MAX + 1);\r
+               p1 = strrchr(buffer1, '\\');\r
+               *translated = (char*) calloc((p1 - buffer1) + 1, sizeof(char));\r
+               strncpy(*translated, buffer1, (p1 - buffer1));\r
+               \r
+               return (int)strlen(*translated);\r
+       }\r
+       /* return the root directory */\r
+       else if(!strcmp(totranslate, "/"))\r
+       {\r
+               *translated = getcwd(NULL,0);\r
+               (*translated)[2] = '\0';\r
+               return (int)strlen(*translated);\r
+       }\r
+       /* it's a relative directory name build the full directory name */\r
+       else if(!strchr(totranslate, '/') && !strchr(totranslate, '\\') && !stat(totranslate, &stat_buf) || S_ISDIR(stat_buf.st_mode))\r
+       {\r
+               getcwd(buffer1, PATH_MAX + 1);\r
+               strcat(buffer1,"\\");\r
+               strcat(buffer1,totranslate);\r
+               \r
+               *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char));\r
+               strcpy(*translated, buffer1);\r
+               return (int)strlen(*translated);\r
+       }\r
+       \r
+       len = (int)strlen(totranslate);                                         \r
+       \r
+       strncpy(buffer1, totranslate, len);     \r
+       \r
+       if(buffer1[strlen(buffer1) - 1] == '/' || buffer1[strlen(buffer1) - 1] == '\\')\r
+               buffer1[strlen(buffer1) - 1] = '\0';\r
+       \r
+       while((p1 = strstr(buffer1, "//"))) \r
+               if(p1[2]) \r
+                       strcpy(p1, p1 + 1); \r
+               else \r
+                       p1[1] = '\0';\r
+       \r
+       for(i = 0, j = 0; buffer1[i] !='\0'; i++)\r
+       {\r
+               if(buffer1[i] == '/')\r
+               {\r
+                       j++;\r
+                       \r
+                       if(j > 1)\r
+                               break;\r
+               }\r
+       }\r
+       \r
+       if(j == 1 && buffer1[i - 1] == '/')\r
+       {\r
+               /* perhaps it's a relative directory : `dir/' */\r
+               strncpy(buffer2, buffer1, strlen(buffer1) - 1);\r
+               \r
+               if(!stat(buffer2, &stat_buf) || S_ISDIR(stat_buf.st_mode))\r
+               {\r
+                       getcwd(buffer1, PATH_MAX + 1);\r
+                       strcat(buffer1,"\\");\r
+                       strcat(buffer1,buffer2);\r
+                       \r
+                       *translated = (char*) calloc(strlen(buffer1) + 1, sizeof(char));\r
+                       strcpy(*translated, buffer1);\r
+                       return (int)strlen(*translated);\r
+               }\r
+               else\r
+                       memset(buffer2, 0, PATH_MAX + 1);\r
+               \r
+       }\r
+       \r
+       if(buffer1[0] == '~') \r
+       {\r
+               /* TODO */\r
+               *translated = NULL;\r
+               errno = ENOSYS;\r
+               return -1;\r
+       }\r
+       else if (*buffer1 == '.') \r
+       {\r
+               _fullpath(buffer2, buffer1, sizeof(buffer1));   \r
+       } \r
+       else \r
+               strcpy(buffer2, buffer1);                       \r
+       \r
+       if(stat(buffer2, &stat_buf) || !S_ISDIR(stat_buf.st_mode))\r
+       {\r
+               *translated = NULL;\r
+               errno = ENOTDIR;\r
+               return -1;\r
+       }\r
+                                \r
+       len = (int)strlen(buffer2);\r
+       \r
+       *translated = (char*) calloc(len + 1, sizeof(char));\r
+       \r
+       if(!(*translated))\r
+       {\r
+               *translated = NULL;\r
+               return -1;\r
+       }\r
+       \r
+       strncpy(*translated, buffer2, len);\r
+       \r
+       return len;\r
 }\r
-\r
 #endif\r
 \r
 \r
index fd46515..528bc50 100644 (file)
@@ -2,20 +2,6 @@
 
 #include <explode.h>
 
-#ifdef WIN32
-static int is_w32_binary(const char* cmd)
-{
-       DWORD binary_type;
-
-       GetBinaryType(cmd, &binary_type);
-
-       if(SCS_32BIT_BINARY == binary_type || SCS_64BIT_BINARY == binary_type || SCS_64BIT_BINARY == binary_type)
-               return 1;
-
-       return 0;
-}
-#endif
-
 int
 is_cmd(char** path, char** builtin, const char* p)
 {
@@ -26,12 +12,12 @@ is_cmd(char** path, char** builtin, const char* p)
        struct stat stat_buff = {0};
        char command[PATH_MAX + 1] = {0};
        char buff[PATH_MAX + 1] = {0};
-       
-       size_t len = strlen(p);
-       
+       size_t len;
+
        if(!p)
                return EINVAL;
        
+       len = strlen(p);
        while(i < len)
        {
                if(p[i] != ' ' && p[i] != '\t' && p[i] != '>')
@@ -42,6 +28,7 @@ is_cmd(char** path, char** builtin, const char* p)
                i++;
        }
        
+       
        /* check first if it's a shell buitin */
        
        if(builtin)
@@ -59,34 +46,26 @@ is_cmd(char** path, char** builtin, const char* p)
                {
                        for (i = 0; path[i] != NULL; i++)
                        {
+                               
                                sprintf(buff,"%s/%s",path[i], command);
                                
                                if(!stat(buff, &stat_buff) && S_ISREG(stat_buff.st_mode))
                                {
-                                       #ifdef WIN32
-                                       if(is_w32_binary(buff))
-                                               yes = 1;
-                                               break;
-                                       #else
+                                       
                                        if(!access(buff, X_OK))
                                        {
                                                yes = 1;
                                                break;
                                        }
-                                       #endif
                                }
                        }
                }
        }
        else
        {
-               #ifdef WIN32
-               if(is_w32_binary(command))
-                       yes = 1;                        
-               #else
+               
                if(!access(command, X_OK))
                        yes = 1;
-               #endif
        }
                
        return yes ? 0 : ECMDNOTFOUND;  
index cc4bcae..c171590 100644 (file)
@@ -197,10 +197,10 @@ static const struct s_optentry opt_entries[] =
        { 'f', string, (byte*)&fstreams, 0, "file" },
        { 'h', flag, (byte*)&print_usage_flag, 0, "help" },
        { 'a', flag, (byte*)&print_readme_flag, 0, "README" },
-       { 'i', flag, (byte*)&keep_going_unit_flag, 0, "keep-going-unit" },
+       { '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" },
-       { '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" },
        { 's', flag, (byte*)&silent_flag, 0, "silent" },
@@ -289,20 +289,29 @@ print_readme(void);
 static int
 init(void);
 
+static int
+screen_cleaned;
 
-static void 
-sig_abort_handler(int signum)
-{
-       /* TODO : implement this function */
-       INFO0("sig_abort_handler() called");
-}
+static int
+finalized = 0;
+
+static int 
+sig_int = 0;
 
+#ifdef WIN32
 static void 
 sig_int_handler(int signum)
 {
-       /* TODO : implement this function */
-       INFO0("sig_int_handler() called");
+
+       if(!finalized)
+       {
+               sig_int = 1;
+               runner_interrupt();
+               while(!finalized);
+       }
+       
 }
+#endif
 
 static void 
 free_string(void* str)
@@ -443,33 +452,28 @@ init(void)
         * to the calling process : tesh)
         */
        prev_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+       
+       /* handle the interrupt signal */
+       signal(SIGINT, sig_int_handler);
        #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));
+       /*
+       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_abort_handler;
-       sigaction(SIGABRT, &act, NULL);
-       
        memset(&act,0, sizeof(struct sigaction));
        act.sa_handler = sig_int_handler;
-       sigaction(SIGINT, &act, NULL);
+       sigaction(SIGINT, &act, NULL);*/
        
        #endif
        
        
-       /* 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((void_f_pvoid_t)fstream_free)))
@@ -567,7 +571,6 @@ load(void)
 static void
 finalize(void)
 {
-       
        /* delete the fstreams object */
        if(fstreams)
                fstreams_free((void**)&fstreams);
@@ -604,8 +607,10 @@ finalize(void)
        #ifdef WIN32
        SetErrorMode(prev_error_mode);
        #endif
-       
-       if(!summary_flag && !dry_run_flag && !silent_flag && !just_print_flag && !print_version_flag && !print_usage_flag && is_tesh_root)
+
+       if(sig_int)
+               INFO0("Tesh interrupted (receive a SIGINT)");
+       else 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");
@@ -615,9 +620,12 @@ finalize(void)
        
        /* exit from the xbt framework */
        xbt_exit();
+
+       finalized = 1;
        
        /* exit with the last error code */
-       exit(exit_code);
+       if(!sig_int)
+               exit(exit_code);
 }
 
 /* init_options -- initialize the options string */
@@ -816,17 +824,6 @@ 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;
-                                                               err_kind = 0;
-                                                               return -1;
-                                                       }       
-
-                                                       #else
                                                        char* path;
                                                        
                                                        if(translatepath(optarg, &path) < 0)
@@ -842,15 +839,11 @@ 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))
                                                                {
@@ -865,17 +858,6 @@ 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;
-                                                               err_kind = 0;
-                                                               return -1;
-                                                       }       
-
-                                                       #else
                                                        char* path ;
                                                        
                                                        if(translatepath(optarg, &path) < 0)
@@ -890,20 +872,10 @@ process_command_line(int argc, char** argv)
                                                                        
                                                                return -1;
                                                        }
-                                                       #endif
                                                        else
                                                        {
                                                                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);
@@ -912,11 +884,8 @@ process_command_line(int argc, char** argv)
 
                                                                chdir(path);
                                                                free(path);
-                                                               #endif
-
+                                               
                                                                free(buffer);
-                                                               
-                                                               
                                                        }       
                                                }
                                                
@@ -1019,17 +988,7 @@ 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;
-                                                               err_kind = 0;
-                                                               return -1;
-                                                       }       
-
-                                                       #else
+                                                       
                                                        char* path ;
                                                        
                                                        if(translatepath(optarg, &path) < 0)
@@ -1044,18 +1003,14 @@ 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);
-                                                               #endif
 
                                                                xbt_dynar_foreach(include_dirs, i , cur)
                                                                {
@@ -1180,6 +1135,16 @@ print_usage(void)
        FILE* stream;
        
        stream = exit_code ? stderr : stdout;
+
+       if(!screen_cleaned)
+       {
+               #ifdef WIN32
+               system("cls");
+               #else
+               system("clear");
+               #endif
+               screen_cleaned = 1;
+       }
        
        fprintf (stream, "Usage: tesh [options] [file] ...\n");
        
@@ -1192,6 +1157,16 @@ print_usage(void)
 static void
 print_version(void)
 {
+       if(!screen_cleaned)
+       {
+               #ifdef 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);
index b3fcb1b..291d058 100644 (file)
@@ -79,6 +79,8 @@ reader_start_routine(void* p)
        char* clean = (char*)calloc(number_of_bytes_to_read + 1,sizeof(char));\r
        size_t i, j;\r
 \r
+       xbt_os_sem_release(reader->started);\r
+\r
        while(!command->failed && !command->interrupted && !command->successeded && !reader->failed && !reader->broken_pipe)\r
        {\r
                if(!ReadFile(stdout_fd, buffer, number_of_bytes_to_read, &number_of_bytes_readed, NULL) || (0 == number_of_bytes_readed))\r
index 80b2a5f..098efe8 100644 (file)
 #include <explode.h>
 #endif
 
+
+
+
 #define _RUNNER_HASHCODE               0xFEFEAAAA      
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(tesh);
 
-#if (!defined(__BUILTIN) && defined(__CHKCMD))
+#if (!defined(__BUILTIN) && defined(__CHKCMD) && !defined(WIN32))
 static const char* builtin[] =
 {
        "alias",
@@ -129,7 +132,7 @@ runner_start_routine(void* p)
     
     /* wait for the timer */
     WaitForSingleObject(timer_handle, INFINITE);
-       
+
        if(runner->waiting)
        {
                exit_code = ELEADTIME;
@@ -187,11 +190,12 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
        int i;
        char* val;
        char buffer[PATH_MAX + 1] = {0};
+
        int code;
        const char* cstr;
        variable_t variable;
        
-       #if (defined(__CHKCMD) && defined(__BUILTIN))
+       #if (defined(__CHKCMD) && defined(__BUILTIN) && !defined(WIN32))
        FILE* s;
        int n = 0;
        size_t len;
@@ -246,13 +250,10 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
        /* add the environment variables in the vector */
        for(i = 0; environ[i] != NULL; i++)
        {
-               
                val = strchr(environ[i], '=');
                
                if(val)
                {
-                       
-                       
                        val++;
                                
                        if(val[0] != '\0')
@@ -269,9 +270,10 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
                        if(!strcmp("PATH", buffer))
                        {
                                char* p;
-                               int j,k,  len;
+                               size_t j,k, len;
                                
                                /* get the list of paths */
+                               
                                runner->path = explode(':', val);
 
                                /* remove spaces and backslahes at the end of the path */
@@ -282,6 +284,7 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
                                len = strlen(p);
                                
                                for(j = len - 1; p[j] == '/' || p[j] == ' '; j--)
+                                       
                                        p[j] = '\0';
                                }
                        }
@@ -308,6 +311,11 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
                variable = variable_new("TESH_PPID", buffer);
                variable->err = 1;
                        
+               xbt_dynar_push(runner->variables, &variable);
+
+               variable = variable_new("TESH_DIR", tesh_dir);
+               variable->err = 1;
+                       
                xbt_dynar_push(runner->variables, &variable);
                
                free(tesh_dir);
@@ -333,7 +341,6 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
                        
        xbt_dynar_push(runner->variables, &variable);
 
-       
        i = 0;
        
        /* add the errors variables */
@@ -350,24 +357,28 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
                check_syntax();
        */
        
-       
-       #if defined(__CHKCMD)
+       #if (!defined(WIN32) && defined(__CHKCMD))
        #if defined(__BUILTIN)
+       
        if(!is_tesh_root)
        {
                /* compute the full path the builtin.def file */
-               #ifndef WIN32
                sprintf(buffer,"%s/builtin.def",getenv("TESH_DIR"));
-               #else
-               GetEnvironmentVariable("TESH_DIR",buffer,PATH_MAX + 1);
-               #endif
                
-               s = fopen(buffer, "r"); 
+               if(!(s = fopen(buffer, "r")))   
+               {
+                       ERROR1("File `(%s)' not found", buffer);
+                       return -1;
+               }
                
        }
        else
        {
-               s = fopen("builtin.def", "r");
+               if(!(s = fopen("builtin.def", "r")))    
+               {
+                       ERROR0("File `(builtin.def)' not found");
+                       return -1;
+               }
        }
        
        if(s)
@@ -395,8 +406,6 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
 
                        if(!is_blank)
                                n++;
-                               
-                       
                }
 
                fsetpos(s, &begin);
@@ -453,13 +462,8 @@ runner_init(/*int check_syntax_flag, */int timeout, fstreams_t fstreams)
                        free(line);
                
        }
-       else
-       {
-               ERROR0("File `(builtin.def)' not found");
-               return -1;
-       }
-       #else
        
+       #else
                runner->builtin = xbt_new0(char*, __BUILTIN_MAX + 1); /* (char**) calloc(__BUILTIN_MAX + 1, sizeof(char*));*/
                
                for(i = 0; i < __BUILTIN_MAX; i++)
index ddd362a..06a276b 100644 (file)
@@ -66,7 +66,7 @@ unit_start(void* p)
        xbt_os_mutex_release(root->mutex);\r
 \r
        /* must acquire the jobs semaphore to start */\r
-       xbt_os_sem_acquire(jobs_sem);\r
+       /*xbt_os_sem_acquire(jobs_sem);*/\r
        \r
        /* initialize the mutex used to synchronize the access to the properties of this unit */\r
        mutex = xbt_os_mutex_init();\r
@@ -409,7 +409,7 @@ unit_run(unit_t unit, xbt_os_mutex_t mutex)
         errno = EINVAL;\r
         return -1;\r
     }\r
-    \r
+\r
        if(!interrupted)\r
        {\r
                unit->mutex = mutex;\r
index a9f67c9..b590f22 100644 (file)
@@ -64,6 +64,7 @@ units_run_all(units_t units, xbt_os_mutex_t mutex)
 \r
        xbt_dynar_foreach(units->items, i, unit)\r
        {\r
+               xbt_os_sem_acquire(jobs_sem);\r
                unit_run(unit, mutex);\r
        }\r
 \r
index bb9b445..5d632ac 100644 (file)
@@ -74,6 +74,8 @@ writer_start_routine(void* p)
        DWORD number_of_bytes_to_write = command->context->input->used;\r
        DWORD number_of_bytes_written = 0;\r
 \r
+       xbt_os_sem_release(writer->written);\r
+\r
        while(!command->failed && !command->interrupted && !command->successeded && ! writer->failed && ! writer->broken_pipe && number_of_bytes_to_write)\r
        {\r
                if(!WriteFile(writer->command->stdin_fd, input, number_of_bytes_to_write, &number_of_bytes_written, NULL))\r
@@ -108,7 +110,7 @@ writer_start_routine(void* p)
                command_kill(command);\r
                command_handle_failure(command, csr_write_pipe_broken);\r
        }*/\r
-       \r
+\r
        CloseHandle(command->stdin_fd);\r
        command->stdin_fd = INDEFINITE_FD;\r
 \r
index 8c7fe76..e765046 100644 (file)
@@ -40,7 +40,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;__CHKCMD;__BUILTIN"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                RuntimeLibrary="2"\r
@@ -63,6 +63,7 @@
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="simgrid.lib"\r
+                               OutputFile="../$(ProjectName).exe"\r
                                LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
                                RelativePath="..\src\getpath.c"\r
                                >\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\src\is_cmd.c"\r
-                               >\r
-                       </File>\r
                        <File\r
                                RelativePath="..\src\main.c"\r
                                >\r
                                RelativePath="..\include\getpath.h"\r
                                >\r
                        </File>\r
-                       <File\r
-                               RelativePath="..\include\is_cmd.h"\r
-                               >\r
-                       </File>\r
                        <File\r
                                RelativePath="..\include\reader.h"\r
                                >\r
index 1459f09..b1d1d30 100644 (file)
@@ -62,7 +62,7 @@
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="..\..\tesh\Debug\cat.exe"\r
+                               OutputFile="..\..\$(ProjectName).exe"\r
                                LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
index 2b3d251..4525144 100644 (file)
@@ -51,17 +51,22 @@ getopt (int argc, char * const argv[], const char *optstring)
 static const char *\r
 __getopt_initialize (const char *optstring)\r
 {\r
+       /* Start processing options with ARGV-element 1 (since ARGV-element 0\r
+       is the program name); the sequence of previously skipped\r
+       non-option ARGV-elements is empty.  */\r
+       \r
        first_nonopt = last_nonopt = optind = 1;\r
        nextchar = NULL;\r
        \r
+       /* Determine how to handle the ordering of options and nonoptions.  */\r
+       \r
        if (optstring[0] == '-')\r
        {\r
                ordering = RETURN_IN_ORDER;\r
                ++optstring;\r
        }\r
-       \r
-       /* if the optstring begining with the character +, the getopt() function\r
-        * stop when an argument of the command line is not an option.\r
+       /* si la chaîne d'options commence par un + alors la fonction getopt() s'arrête\r
+        * dès qu'un argument de la ligne de commande n'est pas une option\r
         */\r
        else if (optstring[0] == '+')\r
        {\r
@@ -86,21 +91,31 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
        \r
        if (nextchar == NULL || *nextchar == '\0')\r
        {\r
+               /* Advance to the next ARGV-element.  */\r
+       \r
                if (ordering == PERMUTE)\r
                {\r
+                       /* If we have just processed some options following some non-options,\r
+                       __exchange them so that the options come first.  */\r
+       \r
                        if (first_nonopt != last_nonopt && last_nonopt != optind)\r
                                __exchange ((char **) argv);\r
                        else if (last_nonopt != optind)\r
                                first_nonopt = optind;\r
        \r
-                       \r
+                       /* Skip any additional non-options\r
+                       and extend the range of non-options previously skipped.  */\r
        \r
                        while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0'))\r
                                optind++;\r
                        \r
                        last_nonopt = optind;\r
                }\r
-\r
+       \r
+               /* The special ARGV-element `--' means premature end of options.\r
+               Skip it like a null option,\r
+               then __exchange with previous non-options as if it were an option,\r
+               then skip everything else like a non-option.  */\r
        \r
                if (optind != argc && !strcmp (argv[optind], "--"))\r
                {\r
@@ -116,14 +131,22 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                        optind = argc;\r
                }\r
        \r
+               /* If we have done all the ARGV-elements, stop the scan\r
+               and back over any non-options that we skipped and permuted.  */\r
+       \r
                if (optind == argc)\r
                {\r
+                       /* Set the next-arg-index to point at the non-options\r
+                       that we previously skipped, so the caller will digest them.  */\r
                        if (first_nonopt != last_nonopt)\r
                                optind = first_nonopt;\r
                        \r
                        return EOF;\r
                }\r
        \r
+               /* If we have come to a non-option and did not permute it,\r
+               either stop the scan or describe it to the caller and pass it by.  */\r
+       \r
                if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))\r
                {\r
                        if (ordering == REQUIRE_ORDER)\r
@@ -132,9 +155,27 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                                return 1;\r
                }\r
        \r
+               /* We have found another option-ARGV-element.\r
+               Skip the initial punctuation.  */\r
+       \r
                nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-'));\r
        }\r
        \r
+       /* Decode the current option-ARGV-element.  */\r
+       \r
+       /* Check whether the ARGV-element is a long option.\r
+       \r
+       If long_only and the ARGV-element has the form "-f", where f is\r
+       a valid short option, don't consider it an abbreviated form of\r
+       a long option that starts with f.  Otherwise there would be no\r
+       way to give the -f short option.\r
+       \r
+       On the other hand, if there's a long option "fubar" and\r
+       the ARGV-element is "-fu", do consider that an abbreviation of\r
+       the long option, just like "--fu", and not "-f" with arg "u".\r
+       \r
+       This distinction seems to be the most useful approach.  */\r
+       \r
        if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !strchr (optstring, argv[optind][1])))))\r
        {\r
                char *nameend;\r
@@ -146,14 +187,18 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                int option_index;\r
        \r
                for (nameend = nextchar; *nameend !='\0' && *nameend != '='; nameend++)\r
-                       \r
+                       /* Do nothing.  */ ;\r
+       \r
+               /* Test all long options for either exact match\r
+               or abbreviated matches.  */\r
                for (p = longopts, option_index = 0; p->name; p++, option_index++)\r
                {\r
                        if(!strncmp (p->name, nextchar, nameend - nextchar))\r
                        {\r
 \r
-                               if ((nameend - nextchar) == strlen (p->name))\r
+                               if (nameend - nextchar == strlen (p->name))\r
                                {\r
+                                       /* Exact match found.  */\r
                                        pfound = p;\r
                                        indfound = option_index;\r
                                        exact = 1;\r
@@ -161,19 +206,27 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                                }\r
                                else if (pfound == NULL)\r
                                {\r
+                                       /* First nonexact match found.  */\r
                                        exact = 0;\r
+                                       /* begin change\r
+                                       pfound = p;\r
+                                       indfound = option_index;\r
+                                       end change */\r
                                        break;\r
                                }\r
                                else\r
+                               {\r
+\r
+                                       /* Second or later nonexact match found.  */\r
                                        ambig = 1;\r
-                               \r
+                               }\r
                        }\r
                }\r
        \r
                if (ambig && !exact)\r
                {\r
                        if (opterr)\r
-                               fprintf (stderr, "ERROR   : %s: option `%s' is ambiguous\n",argv[0], argv[optind]);\r
+                               fprintf (stderr, "error   : %s: option `%s' is ambiguous\n",argv[0], argv[optind]);\r
                        \r
                        nextchar += strlen (nextchar);\r
                        optind++;\r
@@ -187,6 +240,8 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                        \r
                        if (*nameend)\r
                        {\r
+                               /* Don't test has_arg with >, because some C compilers don't\r
+                               allow it to be used on enums.  */\r
                                if (pfound->has_arg)\r
                                        optarg = nameend + 1;\r
                                else\r
@@ -233,6 +288,10 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                        return pfound->val;\r
                }\r
        \r
+               /* Can't find it as a long option.  If this is not getopt_long_only,\r
+               or the option starts with '--' or is not a valid short\r
+               option, then it's an error.\r
+               Otherwise interpret it as a short option.  */\r
                if (!long_only || argv[optind][1] == '-'|| strchr (optstring, *nextchar) == NULL)\r
                {\r
                        if (opterr)\r
@@ -251,6 +310,8 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                }\r
        }\r
        \r
+       /* Look at and handle the next short option-character.  */\r
+       \r
        {\r
                char c = *nextchar++;\r
                char *temp = strchr (optstring, c);\r
@@ -272,7 +333,7 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                {\r
                        if (temp[2] == ':')\r
                        {\r
-                               /* it's an option that accepts an argument optionally.  */\r
+                               /* This is an option that accepts an argument optionally.  */\r
                                if (*nextchar != '\0')\r
                                {\r
                                        optarg = nextchar;\r
@@ -285,10 +346,12 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                        }\r
                        else\r
                        {\r
-                               /* it's an option that requires an argument.  */\r
+                               /* This is an option that requires an argument.  */\r
                                if (*nextchar != '\0')\r
                                {\r
                                        optarg = nextchar;\r
+                                       /* If we end this ARGV-element by taking the rest as an arg,\r
+                                       we must advance to the next element now.  */\r
                                        optind++;\r
                                }\r
                                else if (optind == argc)\r
@@ -296,7 +359,7 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                                        if (opterr)\r
                                        {\r
                                                /* 1003.2 specifies the format of this message.  */\r
-                                               fprintf (stderr, "ERROR   : %s: option requires an argument -- %c\n",argv[0], c);\r
+                                               fprintf (stderr, "error   : %s: option requires an argument -- %c\n",argv[0], c);\r
                                        }\r
                                        optopt = c;\r
                                        \r
@@ -306,6 +369,8 @@ __getopt_internal (int argc, char *const *argv, const char* optstring, const str
                                                c = '?';\r
                                }\r
                                else\r
+                                       /* We already incremented `optind' once;\r
+                                       increment it again when taking next ARGV-elt as argument.  */\r
                                        optarg = argv[optind++];\r
                                \r
                                nextchar = NULL;\r
@@ -325,38 +390,49 @@ __exchange (char **argv)
        int top = optind;\r
        char *tem;\r
        \r
+       /* Exchange the shorter segment with the far end of the longer segment.\r
+       That puts the shorter segment into the right place.\r
+       It leaves the longer segment in the right place overall,\r
+       but it consists of two parts that need to be swapped next.  */\r
+       \r
        while (top > middle && middle > bottom)\r
        {\r
                if (top - middle > middle - bottom)\r
                {\r
+                       /* Bottom segment is the short one.  */\r
                        int len = middle - bottom;\r
                        register int i;\r
        \r
+                       /* Swap it with the top part of the top segment.  */\r
                        for (i = 0; i < len; i++)\r
                        {\r
                                tem = argv[bottom + i];\r
                                argv[bottom + i] = argv[top - (middle - bottom) + i];\r
                                argv[top - (middle - bottom) + i] = tem;\r
                        }\r
+                       /* Exclude the moved bottom segment from further swapping.  */\r
                        \r
                        top -= len;\r
                }\r
                else\r
                {\r
+                       /* Top segment is the short one.  */\r
                        int len = top - middle;\r
                        register int i;\r
                \r
+                       /* Swap it with the bottom part of the bottom segment.  */\r
                        for (i = 0; i < len; i++)\r
                        {\r
                                tem = argv[bottom + i];\r
                                argv[bottom + i] = argv[middle + i];\r
                                argv[middle + i] = tem;\r
                        }\r
-\r
+                       /* Exclude the moved top segment from further swapping.  */\r
                        bottom += len;\r
                }\r
        }\r
        \r
+       /* Update records for the slots the non-options now occupy.  */\r
        \r
        first_nonopt += (optind - last_nonopt);\r
        last_nonopt = optind;\r