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);