You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/08/03 00:06:16 UTC

svn commit: r428171 - in /incubator/stdcxx/trunk/util: cmdopt.cpp cmdopt.h exec.cpp exec.h

Author: sebor
Date: Wed Aug  2 15:06:16 2006
New Revision: 428171

URL: http://svn.apache.org/viewvc?rev=428171&view=rev
Log:
2006-08-01 Andrew Black <ab...@roguewave.com>

	* exec.h (get_signo): Declared.
	* exec.cpp (get_signo): Defined.
	* exec.cpp (signal_names): Moved lookup table out of get_signame
        to file scope.
	* cmdopt.h (verbose): Declared global.
	* cmdopt.cpp (verbose): Defined global.
	* cmdopt.cpp (get_short_val, get_long_val, bad_option): Added
        helper functions for option parsing.
	* cmdopt.cpp (eval_options): Used new functions, add -v, -q,
        --exit, --sleep, --signal, --ignore switches.

Modified:
    incubator/stdcxx/trunk/util/cmdopt.cpp
    incubator/stdcxx/trunk/util/cmdopt.h
    incubator/stdcxx/trunk/util/exec.cpp
    incubator/stdcxx/trunk/util/exec.h

Modified: incubator/stdcxx/trunk/util/cmdopt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/cmdopt.cpp?rev=428171&r1=428170&r2=428171&view=diff
==============================================================================
--- incubator/stdcxx/trunk/util/cmdopt.cpp (original)
+++ incubator/stdcxx/trunk/util/cmdopt.cpp Wed Aug  2 15:06:16 2006
@@ -26,16 +26,21 @@
 
 #include <assert.h>
 #include <ctype.h> /* for isspace */
+#include <errno.h> /* for errno */
+#include <signal.h> /* for kill, SIG_IGN */
 #include <stdio.h> /* for *printf, fputs */
-#include <stdlib.h> /* for atoi, exit */
+#include <stdlib.h> /* for exit */
 #include <string.h> /* for str* */
+#include <unistd.h> /* for getpid */
 
+#include "exec.h"
 #include "util.h"
 
 #include "cmdopt.h"
 
 int timeout = 10; /**< Child process timeout.  Default 10. */
 int compat = 0; /**< Test compatability mode switch.  Defaults to 0 (off). */
+unsigned verbose = 0;
 const char* exe_opts = ""; /**< Global command line switches for child 
                                 processes. */
 const char* in_root = ""; /**< Root directory for input/reference files. */
@@ -58,17 +63,87 @@
            "processed after termination.  If\n  execution takes longer "
            "than a certain (configurable) period of time, the\n  process is "
            "killed\n\n", stderr);
-    fputs ("    -d dir      Root directory for output reference files\n"
-           "    -h, -?      Display usage information and exit\n"
-           "    -t seconds  Watchdog timeout before killing target (default is "
-"10 \n                seconds)\n"
-           "    -x opts     Command line options to pass to targets\n"
-           "    --          Terminate option processing and treat all "
-           "following arguments\n                as targets\n", stderr);
+    fputs ("    -d dir       Root directory for output reference files\n"
+           "    -h, -?       Display usage information and exit\n"
+           "    -t seconds   Watchdog timeout before killing target (default "
+           "is 10 \n                 seconds)\n"
+           "    -q           Set verbosity level to 0 (default)\n"
+           "    -v           Increase verbosity of output\n"
+           "    -x opts      Command line options to pass to targets\n", 
+           stderr);
+    fputs ("    --           Terminate option processing and treat all "
+           "following arguments\n                 as targets\n"
+           "    --compat     Use compatability mode test output parsing\n"
+           "    --nocompat   Use standard test output parsing (default)\n"
+           "    --exit=val   Exit (now) with a return code of val\n"
+           "    --sleep=sec  sleep() (now) for sec seconds\n"
+           "    --signal=sig Send self signal sig (now)\n"
+           "    --ignore=sig Ignore signal sig\n", stderr);
+    fputs ("\n"
+           "  All short (single dash) options must be specified seperately.\n"
+           "  If a short option takes a value, it may either be provided like"
+           "\n  '-sval' or  '-s val'\n"
+           "  If a long option take a value, it may either be provided like\n"
+           "  '--option=value' or '--option value'\n", stderr);
+          
     exit (status);
 }
 
 /**
+    Helper function to read the value for a short option
+    
+    @param argv argument array
+    @param idx reference to index for option
+*/
+static char*
+get_short_val (char* const* argv, int* idx)
+{
+    assert (0 != argv);
+    assert (0 != idx);
+
+    if ('\0' == argv [*idx][2])
+        return argv [++(*idx)];
+    else
+        return argv [*idx] + 2;
+}
+
+/**
+    Helper function to read the value for a long option
+    
+    @param argv argument array
+    @param idx reference to index for option
+    @param offset length of option name (including leading --)
+*/
+static char*
+get_long_val (char* const* argv, int* idx, unsigned offset)
+{
+    assert (0 != argv);
+    assert (0 != idx);
+
+    if ('\0' == argv [*idx][offset])
+        return argv [++(*idx)];
+    else if ('=' == argv [*idx][offset])
+        return argv [*idx] + offset + 1;
+    else
+        return (char*)0;
+}
+
+/**
+    Helper function to produce 'Unknown option' error message.
+    
+    Terminates via show_usage.
+    
+    @param opt name of option encountered
+*/
+static void
+bad_option (char* const opt)
+{
+    assert (0 != opt);
+    warn ("Unknown option: %s\n", opt);
+    show_usage (1);
+}
+
+/**
    Parses command line arguments for switches and options.
 
    @param argc number of command line arguments
@@ -101,28 +176,22 @@
             ++i; /* Ignore -r option (makefile compat) */
             break;
         case 't':
-            if ('\0' == argv [i][2])
-                val = argv [++i];
-            else
-                val = argv [i] + 2;
-
-            timeout = atoi (val);
+            val = get_short_val (argv, &i);
+            timeout = strtol (val, &val, 10);
+            if (*val || errno)
+                terminate (1, "Unknown value for -t: %s\n", val);
             break;
         case 'd':
-            if ('\0' == argv [i][2])
-                val = argv [++i];
-            else
-                val = argv [i] + 2;
-
-            in_root = val;
+            in_root = get_short_val (argv, &i);
             break;
         case 'x':
-            if ('\0' == argv [i][2])
-                val = argv [++i];
-            else
-                val = argv [i] + 2;
-
-            exe_opts = val;
+            exe_opts = get_short_val (argv, &i);
+            break;
+        case 'v':
+            ++verbose;
+            break;
+        case 'q':
+            verbose = 0;
             break;
         case '-':
         {
@@ -132,19 +201,80 @@
             if ('\0' == argv [i][2])
                 return i+1;
 
-            if (8 == arglen && 0 == memcmp ("--compat", argv [i], 8)) {
+            if (8 == arglen && 0 == memcmp ("--compat\0", argv [i], 9)) {
                 compat = 1;
                 break;
             }
-            else if (10 == arglen && 0 == memcmp ("--nocompat", argv [i], 10)) {
+            else if (10 == arglen && 0 == memcmp ("--nocompat\0", argv [i], 
+                                                  11)) {
                 compat = 0;
                 break;
             }
+            else if (6 <= arglen && 0 == memcmp ("--exit", argv [i], 6)) {
+                val = get_long_val (argv, &i, 6);
+                if (val) {
+                    int code = strtol (val, &val, 10);
+                    if (*val || errno)
+                        terminate (1, "Unknown value for --exit: %s\n", val);
+                    exit (code);
+                }
+                else
+                    bad_option (argv [i]);
+            }
+            else if (7 <= arglen && 0 == memcmp ("--sleep", argv [i], 7)) {
+                val = get_long_val (argv, &i, 7);
+                if (val) {
+                    int duration = strtol (val, &val, 10);
+                    if (*val || errno)
+                        terminate (1, "Unknown value for --sleep: %s\n", val);
+                    sleep (duration);
+                    break;
+                }
+                else
+                    bad_option (argv [i]);
+            }
+            else if (8 <= arglen && 0 == memcmp ("--signal", argv [i], 8)) {
+                val = get_long_val (argv, &i, 8);
+                if (val) {
+                    int sig = get_signo (val);
+                    if (0 > sig)
+                        terminate (1, "Unknown signal name for --signal: "
+                                   "%s\n", val);
+                    
+                    /* Ignore kill errors (what should we do with them?) */
+                    (void)kill (getpid (), sig);
+
+                    /* Not certain what we should do if we don't terminate by 
+                       signal */
+                    break;
+                }
+                else
+                    bad_option (argv [i]);
+            }
+            else if (8 <= arglen && 0 == memcmp ("--ignore", argv [i], 8)) {
+                val = get_long_val (argv, &i, 8);
+                if (val) {
+                    struct sigaction act;
+                    int sig = get_signo (val);
+                    if (0 > sig)
+                        terminate (1, "Unknown signal name for --ignore: "
+                                   "%s\n", val);
+                    
+                    memset (&act, 0, sizeof act);
+                    act.sa_handler = SIG_IGN;
+                    (void)sigaction (sig, &act, 0);
+                    /* Ignore sigaction errors (what should we do with them?) 
+                     */
+                    break;
+                }
+                else
+                    bad_option (argv [i]);
+            }
+            else
+                bad_option (argv [i]);
         }
-            /* Intentionally falling through */
         default:
-            fprintf (stderr, "Unknown option: %s\n", argv [i]);
-            show_usage (1);
+            bad_option (argv [i]);
         }
     }
 

Modified: incubator/stdcxx/trunk/util/cmdopt.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/cmdopt.h?rev=428171&r1=428170&r2=428171&view=diff
==============================================================================
--- incubator/stdcxx/trunk/util/cmdopt.h (original)
+++ incubator/stdcxx/trunk/util/cmdopt.h Wed Aug  2 15:06:16 2006
@@ -29,6 +29,7 @@
 
 extern int timeout;
 extern int compat;
+extern unsigned verbose; /**< Verbose output mode switch.  Defaults to 0 (off) */
 extern const char* exe_opts;
 extern const char* in_root;
 extern const char* exe_name;

Modified: incubator/stdcxx/trunk/util/exec.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.cpp?rev=428171&r1=428170&r2=428171&view=diff
==============================================================================
--- incubator/stdcxx/trunk/util/exec.cpp (original)
+++ incubator/stdcxx/trunk/util/exec.cpp Wed Aug  2 15:06:16 2006
@@ -29,6 +29,7 @@
 #undef __PURE_CNAME
 
 #include <assert.h> /* for assert */
+#include <ctype.h> /* for tolower */
 #include <errno.h> /* for errno */
 #include <fcntl.h> /* for O_*, */
 #include <signal.h>
@@ -58,192 +59,292 @@
 static int alarm_timeout;
 
 /**
-   Translates a signal number into a human understandable name
-
-   @param signo a signal number
-   @returns the human understandable name for the signal (minus the SIG 
-   prefix), or "#n" if the the name for the number is unknown to the 
-   function, where n is signo
+    Utility macro to generate a signal number/name pair.
+    
+    @parm val 'short' signal name (no leading SIG) to generate pair for.
+    @see signal_names []
 */
-const char* 
-get_signame (int signo)
-{
-    static const struct {
-        int         val;
-        const char* str;
-    } names [] = {
-
 #undef SIGNAL
 #define SIGNAL(val)   { SIG ## val, #val }
 
+/**
+    Signal name/number translation table.
+    
+    This table is populated using the SIGNAL helper macro to translate system SIG* macro values into name/value pairs.
+    
+    @see SIGNAL ()
+*/
+static const struct {
+    int         val; /**< Signal value for lookup pair */
+    const char* str; /**< Signal name for lookup pair */
+} signal_names [] = {
 #ifdef SIGABRT
-        SIGNAL (ABRT),
+    SIGNAL (ABRT),
 #endif   /* SIGABRT */
 #ifdef SIGALRM
-        SIGNAL (ALRM),
+    SIGNAL (ALRM),
 #endif   /* SIGALRM */
 #ifdef SIGBUS
-        SIGNAL (BUS),
+    SIGNAL (BUS),
 #endif   /* SIGBUS */
 #ifdef SIGCANCEL
-        SIGNAL (CANCEL),
+    SIGNAL (CANCEL),
 #endif   /* SIGCANCEL */
 #ifdef SIGCHLD
-        SIGNAL (CHLD),
+    SIGNAL (CHLD),
 #endif   /* SIGCHLD */
 #ifdef SIGCKPT
-        SIGNAL (CKPT),
+    SIGNAL (CKPT),
 #endif   /* SIGCKPT */
 #ifdef SIGCLD
-        SIGNAL (CLD),
+    SIGNAL (CLD),
 #endif   /* SIGCLD */
 #ifdef SIGCONT
-        SIGNAL (CONT),
+    SIGNAL (CONT),
 #endif   /* SIGCONT */
 #ifdef SIGDIL
-        SIGNAL (DIL),
+    SIGNAL (DIL),
 #endif   /* SIGDIL */
 #ifdef SIGEMT
-        SIGNAL (EMT),
+    SIGNAL (EMT),
 #endif   /* SIGEMT */
 #ifdef SIGFPE
-        SIGNAL (FPE),
+    SIGNAL (FPE),
 #endif   /* SIGFPE */
 #ifdef SIGFREEZE
-        SIGNAL (FREEZE),
+    SIGNAL (FREEZE),
 #endif   /* SIGFREEZE */
 #ifdef SIGGFAULT
-        SIGNAL (GFAULT),
+    SIGNAL (GFAULT),
 #endif   /* SIGGFAULT */
 #ifdef SIGHUP
-        SIGNAL (HUP),
+    SIGNAL (HUP),
 #endif   /* SIGHUP */
 #ifdef SIGILL
-        SIGNAL (ILL),
+    SIGNAL (ILL),
 #endif   /* SIGILL */
 #ifdef SIGINFO
-        SIGNAL (INFO),
+    SIGNAL (INFO),
 #endif   /* SIGINFO */
 #ifdef SIGINT
-        SIGNAL (INT),
+    SIGNAL (INT),
 #endif   /* SIGINT */
 #ifdef SIGIO
-        SIGNAL (IO),
+    SIGNAL (IO),
 #endif   /* SIGIO */
 #ifdef SIGIOT
-        SIGNAL (IOT),
+    SIGNAL (IOT),
 #endif   /* SIGIOT */
 #ifdef SIGK32
-        SIGNAL (K32),
+    SIGNAL (K32),
 #endif   /* SIGK32 */
 #ifdef SIGKILL
-        SIGNAL (KILL),
+    SIGNAL (KILL),
 #endif   /* SIGKILL */
 #ifdef SIGLOST
-        SIGNAL (LOST),
+    SIGNAL (LOST),
 #endif   /* SIGLOST */
 #ifdef SIGLWP
-        SIGNAL (LWP),
+    SIGNAL (LWP),
 #endif   /* SIGLWP */
 #ifdef SIGPIPE
-        SIGNAL (PIPE),
+    SIGNAL (PIPE),
 #endif   /* SIGPIPE */
 #ifdef SIGPOLL
-        SIGNAL (POLL),
+    SIGNAL (POLL),
 #endif   /* SIGPOLL */
 #ifdef SIGPROF
-        SIGNAL (PROF),
+    SIGNAL (PROF),
 #endif   /* SIGPROF */
 #ifdef SIGPTINTR
-        SIGNAL (PTINTR),
+    SIGNAL (PTINTR),
 #endif   /* SIGPTINTR */
 #ifdef SIGPTRESCHED
-        SIGNAL (PTRESCHED),
+    SIGNAL (PTRESCHED),
 #endif   /* SIGPTRESCHED */
 #ifdef SIGPWR
-        SIGNAL (PWR),
+    SIGNAL (PWR),
 #endif   /* SIGPWR */
 #ifdef SIGQUIT
-        SIGNAL (QUIT),
+    SIGNAL (QUIT),
 #endif   /* SIGQUIT */
 #ifdef SIGRESTART
-        SIGNAL (RESTART),
+    SIGNAL (RESTART),
 #endif   /* SIGRESTART */
 #ifdef SIGRESV
-        SIGNAL (RESV),
+    SIGNAL (RESV),
 #endif   /* SIGRESV */
 #ifdef SIGSEGV
-        SIGNAL (SEGV),
+    SIGNAL (SEGV),
 #endif   /* SIGSEGV */
 #ifdef SIGSTKFLT
-        SIGNAL (STKFLT),
+    SIGNAL (STKFLT),
 #endif   /* SIGSTKFLT */
 #ifdef SIGSTOP
-        SIGNAL (STOP),
+    SIGNAL (STOP),
 #endif   /* SIGSTOP */
 #ifdef SIGSYS
-        SIGNAL (SYS),
+    SIGNAL (SYS),
 #endif   /* SIGSYS */
 #ifdef SIGTERM
-        SIGNAL (TERM),
+    SIGNAL (TERM),
 #endif   /* SIGTERM */
 #ifdef SIGTHAW
-        SIGNAL (THAW),
+    SIGNAL (THAW),
 #endif   /* SIGTHAW */
 #ifdef SIGTRAP
-        SIGNAL (TRAP),
+    SIGNAL (TRAP),
 #endif   /* SIGTRAP */
 #ifdef SIGTSTP
-        SIGNAL (TSTP),
+    SIGNAL (TSTP),
 #endif   /* SIGTSTP */
 #ifdef SIGTTIN
-        SIGNAL (TTIN),
+    SIGNAL (TTIN),
 #endif   /* SIGTTIN */
 #ifdef SIGTTOU
-        SIGNAL (TTOU),
+    SIGNAL (TTOU),
 #endif   /* SIGTTOU */
 #ifdef SIGUNUSED
-        SIGNAL (UNUSED),
+    SIGNAL (UNUSED),
 #endif   /* SIGUNUSED */
 #ifdef SIGURG
-        SIGNAL (URG),
+    SIGNAL (URG),
 #endif   /* SIGURG */
 #ifdef SIGUSR1
-        SIGNAL (USR1),
+    SIGNAL (USR1),
 #endif   /* SIGUSR1 */
 #ifdef SIGUSR2
-        SIGNAL (USR2),
+    SIGNAL (USR2),
 #endif   /* SIGUSR2 */
 #ifdef SIGVTALRM
-        SIGNAL (VTALRM),
+    SIGNAL (VTALRM),
 #endif   /* SIGVTALRM */
 #ifdef SIGWAITING
-        SIGNAL (WAITING),
+    SIGNAL (WAITING),
 #endif   /* SIGWAITING */
 #ifdef SIGWINCH
-        SIGNAL (WINCH),
+    SIGNAL (WINCH),
 #endif   /* SIGWINCH */
 #ifdef SIGWINDOW
-        SIGNAL (WINDOW),
+    SIGNAL (WINDOW),
 #endif   /* SIGWINDOW */
 #ifdef SIGXCPU
-        SIGNAL (XCPU),
+    SIGNAL (XCPU),
 #endif   /* SIGXCPU */
 #ifdef SIGXFSZ
-        SIGNAL (XFSZ),
+    SIGNAL (XFSZ),
 #endif   /* SIGXFSZ */
 #ifdef SIGXRES
-        SIGNAL (XRES),
+    SIGNAL (XRES),
 #endif   /* SIGXRES */
-        { -1, 0 }
-    };
+    { -1, 0 }
+};
+
+/**
+   Compare two characters in a case-insensitive manner
+
+   @param c1 first character to compare
+   @param c2 second character to compare
+   @return an integer less than, equal to, or greater than 0, coresponding
+   to whether c1 is less than, equal to, or greater than c2 when compared
+   in a case insensitive manner.
+*/
+static int
+rw_charcasecmp (char c1, char c2)
+{
+    typedef unsigned char UChar; 
+    return tolower ((UChar)c1) - tolower ((UChar)c2);
+}
+
+/**
+   Reimplementation of the POSIX strcasecmp function.
+
+   This is a simplistic (re)implementation of the strcasecmp function
+   specified in the XSI extension to the IEEE Std 1003.1 (POSIX) standard.
+
+   @param s1 pointer to first string to compare
+   @param s2 pointer to second string to compare
+   @return an integer less than, equal to, or greater than 0, coresponding
+   to whether s1 is less than, equal to, or greater than s2 when compared
+   in a case insensitive manner.
+*/
+static int
+rw_strcasecmp (const char* s1, const char* s2)
+{
+    int delta;
+
+    assert (0 != s1);
+    assert (0 != s2);
 
+    for (delta = rw_charcasecmp (*s1, *s2); 
+         *s1 && *s2 && 0 == delta; 
+         delta = rw_charcasecmp (*(++s1), *(++s2)));
+    return delta;
+}
+
+/**
+   Translates a human understandable signal name into a number usable by kill ().
+
+   This method understands several formats for signal names.  They are as follows:
+   - n
+   - SIGFOO
+   - FOO
+   In this list, n denotes a number and FOO denotes a short signal name.
+
+   @param signame a signal name to decode
+   @returns the signal number or -1 if a number couldn't be determined
+   @see signal_names []
+*/
+const int
+get_signo (const char* signame)
+{
+    size_t i;
+    typedef unsigned char UChar; 
+
+    assert (0 != signame);
+
+    if (isdigit (signame [0])){
+        char *junk;
+        int trans = strtol (signame, &junk, 10);
+
+        if (0 == *junk && 0 == errno)
+            return trans;
+        else
+            return -1;
+    }
+
+    if (   's' == tolower ((UChar)signame [0]) 
+        && 'i' == tolower ((UChar)signame [1]) 
+        && 'g' == tolower ((UChar)signame [2]))
+        signame += 3;
+    
+    for (i = 0; signal_names [i].str; ++i) {
+        if (0 == rw_strcasecmp (signal_names [i].str, signame)) {
+            return signal_names [i].val;
+        }
+    }
+    
+    return -1;
+}
+
+/**
+   Translates a signal number into a human understandable name
+
+   @param signo a signal number
+   @returns the human understandable name for the signal (minus the SIG 
+   prefix), or "#n" if the the name for the number is unknown to the 
+   function, where n is signo
+   @see signal_names []
+*/
+const char* 
+get_signame (int signo)
+{
     size_t i;
     static char def [16];
 
-    for (i = 0; i < sizeof names / sizeof *names; ++i) {
-        if (names [i].val == signo) {
-            return names [i].str;
+    for (i = 0; signal_names [i].str; ++i) {
+        if (signal_names [i].val == signo) {
+            return signal_names [i].str;
         }
     }
 
@@ -621,7 +722,7 @@
               strerror (errno));
         return state;
     }
-
+    
     /* parent */
     return wait_for_child (child_pid);
 }

Modified: incubator/stdcxx/trunk/util/exec.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.h?rev=428171&r1=428170&r2=428171&view=diff
==============================================================================
--- incubator/stdcxx/trunk/util/exec.h (original)
+++ incubator/stdcxx/trunk/util/exec.h Wed Aug  2 15:06:16 2006
@@ -32,6 +32,8 @@
     int killed;
 };
 
+const int get_signo (const char* signame);
+
 const char* get_signame (int signo);
 
 struct exec_attrs exec_file (char** argv);