stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r425242 - in /incubator/stdcxx/trunk: ./ etc/config/ util/
Date Tue, 25 Jul 2006 00:59:05 GMT
Author: sebor
Date: Mon Jul 24 17:59:04 2006
New Revision: 425242

URL: http://svn.apache.org/viewvc?rev=425242&view=rev
Log:
2006-07-23 Andrew Black <ablack@roguewave.com>
	   Martin Sebor <sebor@apache.org>

	* GNUmakefile (BINDIR): Add and use convenience variable referencing
	the bin/ subdirectory of the buildspace.
	* GNUmakefile.exm (RUNFLAGS): Change command line switch used to
	specify input/output file directory to match switch expected by
	the utility.
	* GNUmakefile.bin (exec): Add rule to build the new exec utility.
	* GNUmakefile.tst (RUNFLAGS): Removed additional switches as unneeded.
	* makefile.rules (run runall run_all): Add dependency on exec utility.
	* GNUmakefile.exm, GNUmakefile.tst: Add rule to build the exec utility.
	* run_locale_utils.sh: Change default output file to /dev/stdout, add
	test driver style assertion count summary.
	* cmdopt.h: New. Declared command line parsing function(s).
	* cmdopt.cpp: Definition(s) of the above.
	* exec.h: New. Declared helper to execute program(s).
	* exec.cpp: Definition(s) of the above.
	* output.h: New. Declarations of functions for program (test,
	example, etc.) output processing.
	* output.cpp: Defintions of the above.
	* runall.cpp: Defintion of main and helpers.
	* util.h: New. Declared helper functions.
	* util.cpp: Definitions of the above.

Added:
    incubator/stdcxx/trunk/util/cmdopt.cpp   (with props)
    incubator/stdcxx/trunk/util/cmdopt.h   (with props)
    incubator/stdcxx/trunk/util/exec.cpp   (with props)
    incubator/stdcxx/trunk/util/exec.h   (with props)
    incubator/stdcxx/trunk/util/output.cpp   (with props)
    incubator/stdcxx/trunk/util/output.h   (with props)
    incubator/stdcxx/trunk/util/runall.cpp   (with props)
    incubator/stdcxx/trunk/util/util.cpp   (with props)
    incubator/stdcxx/trunk/util/util.h   (with props)
Modified:
    incubator/stdcxx/trunk/GNUmakefile
    incubator/stdcxx/trunk/etc/config/GNUmakefile.bin
    incubator/stdcxx/trunk/etc/config/GNUmakefile.exm
    incubator/stdcxx/trunk/etc/config/GNUmakefile.tst
    incubator/stdcxx/trunk/etc/config/makefile.rules
    incubator/stdcxx/trunk/etc/config/run_locale_utils.sh

Modified: incubator/stdcxx/trunk/GNUmakefile
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/GNUmakefile?rev=425242&r1=425241&r2=425242&view=diff
==============================================================================
--- incubator/stdcxx/trunk/GNUmakefile (original)
+++ incubator/stdcxx/trunk/GNUmakefile Mon Jul 24 17:59:04 2006
@@ -190,14 +190,15 @@
 
 INCDIR      = $(buildpath)/include
 LIBDIR      = $(buildpath)/lib
+BINDIR      = $(buildpath)/bin
 EXMDIR      = $(buildpath)/examples
 TSTDIR      = $(buildpath)/tests
 PHTSTDIR    = $(buildpath)/plumhall
-MAKEDIRS    = $(buildpath)           \
+MAKEDIRS    = $(buildpath)          \
               $(LIBDIR)             \
-              $(buildpath)/rwtest    \
-              $(buildpath)/bin       \
-              $(buildpath)/nls       \
+              $(buildpath)/rwtest   \
+              $(BINDIR)             \
+              $(buildpath)/nls      \
               $(TSTDIR)             \
               $(PHTSTDIR)           \
               $(EXMDIR)             \
@@ -542,16 +543,16 @@
     ln -sf $(ETCDIR)/GNUmakefile.exm     $(EXMDIR)/GNUmakefile;              \
     ln -sf $(ETCDIR)/GNUmakefile.tst     $(TSTDIR)/GNUmakefile;              \
     ln -sf $(ETCDIR)/GNUmakefile.ph      $(PHTSTDIR)/GNUmakefile;            \
-    ln -sf $(ETCDIR)/GNUmakefile.bin     $(buildpath)/bin/GNUmakefile;       \
+    ln -sf $(ETCDIR)/GNUmakefile.bin     $(BINDIR)/GNUmakefile;              \
     ln -sf $(ETCDIR)/makefile.common     $(buildpath);                       \
     ln -sf $(ETCDIR)/makefile.rules      $(buildpath);                       \
     ln -sf $(ETCDIR)/configure.sh        $(buildpath)/include/configure;     \
-    ln -sf $(ETCDIR)/runall.sh           $(buildpath)/run;                   \
-    ln -sf $(ETCDIR)/runall.sh           $(buildpath)/bin/run;               \
-    ln -sf $(ETCDIR)/run_locale_utils.sh $(buildpath)/bin/run_utils;         \
-    ln -sf $(ETCDIR)/runall.sh           $(TSTDIR)/run;                      \
-    ln -sf $(ETCDIR)/runall.sh           $(PHTSTDIR)/run;                    \
-    ln -sf $(ETCDIR)/runall.sh           $(EXMDIR)/run
+    ln -sf $(BINDIR)/exec                $(buildpath)/run;                   \
+    ln -sf $(BINDIR)/exec                $(BINDIR)/run;                      \
+    ln -sf $(ETCDIR)/run_locale_utils.sh $(BINDIR)/run_utils;                \
+    ln -sf $(BINDIR)/exec                $(TSTDIR)/run;                      \
+    ln -sf $(BINDIR)/exec                $(PHTSTDIR)/run;                    \
+    ln -sf $(BINDIR)/exec                $(EXMDIR)/run
 endef   # make-builddir
 
 
@@ -581,6 +582,7 @@
           || echo "MAPFILE    = $$""(TOPDIR)/$(MAPFILE)" >> $(MAKEFILE_IN)  \
           && echo "RUNFLAGS   = -t 180"                  >> $(MAKEFILE_IN)  \
           && echo "LIBDIR     = $$""(BUILDDIR)/lib"      >> $(MAKEFILE_IN)  \
+          && echo "BINDIR     = $$""(BUILDDIR)/bin"      >> $(MAKEFILE_IN)  \
           && echo "DEPENDDIR  = $(DEPENDDIR)"            >> $(MAKEFILE_IN)  \
           && echo "PHDIR      = $(PHDIR)"                >> $(MAKEFILE_IN)  \
           && echo "PHWARNFLAGS = $(PHWARNFLAGS)"         >> $(MAKEFILE_IN)  \
@@ -632,7 +634,7 @@
 
 # build utilities
 util:
-	@$(MAKE) -C$(BUILDDIR)/bin
+	@$(MAKE) -C$(BINDIR)
 
 # build library
 lib:

Modified: incubator/stdcxx/trunk/etc/config/GNUmakefile.bin
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/GNUmakefile.bin?rev=425242&r1=425241&r2=425242&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/GNUmakefile.bin (original)
+++ incubator/stdcxx/trunk/etc/config/GNUmakefile.bin Mon Jul 24 17:59:04 2006
@@ -15,7 +15,7 @@
 include ../makefile.common
 
 INCLUDES += -I$(TOPDIR)/include/loc
-TARGET    = localedef locale
+TARGET    = exec localedef locale
 
 # locale sources and related 
 NLSDIR = $(TOPDIR)/etc/nls
@@ -52,6 +52,11 @@
 
 $(LIBDIR)/$(LIBNAME):
 	@$(MAKE) -C $(LIBDIR) 
+
+# link the run utility
+exec: runall.o cmdopt.o output.o util.o exec.o
+	@echo "$(LD) $^ -o $@ $(LDFLAGS) $(LDLIBS)" >> $(LOGFILE)
+	$(LD) $^ -o $@ $(LDFLAGS) $(LDLIBS) $(TEEOPTS)
 
 # link the localedef utility
 localedef: localedef.o aliases.o charmap.o codecvt.o collate.o ctype.o \

Modified: incubator/stdcxx/trunk/etc/config/GNUmakefile.exm
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/GNUmakefile.exm?rev=425242&r1=425241&r2=425242&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/GNUmakefile.exm (original)
+++ incubator/stdcxx/trunk/etc/config/GNUmakefile.exm Mon Jul 24 17:59:04 2006
@@ -21,7 +21,7 @@
 
 INCLUDES += -I$(EXMDIR)/include
 
-RUNFLAGS += -x $(EXMDIR)
+RUNFLAGS += -d $(EXMDIR)
 
 ##############################################################################
 #  TARGETS
@@ -36,6 +36,9 @@
 
 $(LIBDIR)/$(LIBNAME):
 	@$(MAKE) -C $(LIBDIR) 
+
+$(BINDIR)/runutil:
+	@$(MAKE) -C $(BINDIR) runutil
 
 # do any directory specific cleanup using the realclean target
 realclean: dependclean clean

Modified: incubator/stdcxx/trunk/etc/config/GNUmakefile.tst
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/GNUmakefile.tst?rev=425242&r1=425241&r2=425242&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/GNUmakefile.tst (original)
+++ incubator/stdcxx/trunk/etc/config/GNUmakefile.tst Mon Jul 24 17:59:04 2006
@@ -67,8 +67,6 @@
 # add to targets objects for any sources in the current working directory
 TARGET += $(patsubst %.cpp,%.o,$(wildcard *.cpp))
 
-RUNFLAGS += -X "--compat -C $(CXX)-$(CCVER)" 
-
 ##############################################################################
 #  TARGETS
 ##############################################################################
@@ -82,6 +80,9 @@
 
 $(BUILDDIR)/rwtest/$(RWTLIBNAME):
 	@$(MAKE) -C $(BUILDDIR)/rwtest MAKEOVERRIDES=
+
+$(BINDIR)/runutil:
+	@$(MAKE) -C $(BINDIR) runutil
 
 # do any directory specific cleanup using the realclean target
 realclean: clean dependclean

Modified: incubator/stdcxx/trunk/etc/config/makefile.rules
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/makefile.rules?rev=425242&r1=425241&r2=425242&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/makefile.rules (original)
+++ incubator/stdcxx/trunk/etc/config/makefile.rules Mon Jul 24 17:59:04 2006
@@ -109,7 +109,7 @@
 # PlumHall specific:
 # for all "top level" tests that failed to build, find and build all
 # subtests (the little tests the main test consists of)
-run runall run_all:
+run runall run_all: $(BINDIR)/exec
 	@(LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(LIBDIR);                    \
         PATH=$$PATH:.;                                                    \
         TOPDIR=$(TOPDIR);                                                 \

Modified: incubator/stdcxx/trunk/etc/config/run_locale_utils.sh
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/etc/config/run_locale_utils.sh?rev=425242&r1=425241&r2=425242&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/run_locale_utils.sh (original)
+++ incubator/stdcxx/trunk/etc/config/run_locale_utils.sh Mon Jul 24 17:59:04 2006
@@ -317,7 +317,7 @@
 locdir=""
 
 ## output stream
-out="/dev/null"
+out="/dev/stdout"
 dbgout="/dev/null"
 
 ## Get the options from the command line
@@ -378,7 +378,12 @@
     exit 2
 fi
 
-
+pcnt=`expr 100 \* \( $assertions - $failedassertions \) / $assertions`
+echo "# +-----------------------+--------+--------+--------+" >> $out
+echo "# | DIAGNOSTIC            | ACTIVE |  TOTAL |INACTIVE|" >> $out
+echo "# +-----------------------+--------+--------+--------+" >> $out
+printf "# | (S7) ASSERTION        | %6d | %6d | %5d%% |\n"  $failedassertions $assertions $pcnt >> $out
+echo "# +-----------------------+--------+--------+--------+" >> $out
 echo >> $out
 echo "## Assertions = "$assertions >> $out
 echo "## FailedAssertions = "$failedassertions >> $out

Added: incubator/stdcxx/trunk/util/cmdopt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/cmdopt.cpp?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/cmdopt.cpp (added)
+++ incubator/stdcxx/trunk/util/cmdopt.cpp Mon Jul 24 17:59:04 2006
@@ -0,0 +1,247 @@
+/************************************************************************
+ *
+ * cmdopt.cpp - Definitions of the option parsing subsystem
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <ctype.h> /* for isspace */
+#include <stdio.h> /* for *printf, fputs */
+#include <stdlib.h> /* for atoi, exit */
+#include <string.h> /* for str* */
+
+#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) */
+const char* exe_opts = ""; /**< Command line switches for child processes */
+const char* in_root = ""; /**< Root directory for input/reference files */
+const char* exe_name; /**< Alias for process argv[0]. */
+
+/**
+   Display command line switches for program and terminate.
+
+   @param status status code to exit with.
+*/
+void 
+show_usage (int status)
+{
+    assert (0 != exe_name);
+    fprintf (stderr, "Usage: %s [OPTIONS] [targets]\n", exe_name);
+    fputs ("\n"
+           "  Treats each token in targets as the path to an executable.  "
+           "Each target\n  enumerated is executed, and the output is "
+           "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);
+    exit (status);
+}
+
+/**
+   Parses command line arguments for switches and options.
+
+   @param argc number of command line arguments
+   @param argv command line arguments
+   @return number of command line arguments parsed.
+   @see timeout
+   @see in_root
+   @see exe_opts
+*/
+int 
+eval_options (const int argc, /* const */ char* const argv[])
+{
+    int i;
+
+    char* val;
+
+    assert (0 != argv);
+
+    if (1 == argc || '-' != argv [1][0])
+        return 1;
+
+    for (i = 1; i < argc && '-' == argv [i][0]; ++i) {
+
+        switch (argv [i][1]) {
+        case '?':
+        case 'h':
+            show_usage (0);
+        case 'r':
+            ++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);
+            break;
+        case 'd':
+            if ('\0' == argv [i][2])
+                val = argv [++i];
+            else
+                val = argv [i] + 2;
+
+            in_root = val;
+            break;
+        case 'x':
+            if ('\0' == argv [i][2])
+                val = argv [++i];
+            else
+                val = argv [i] + 2;
+
+            exe_opts = val;
+            break;
+        case '-':
+        {
+            const size_t arglen = strlen (argv [i]);
+
+            /* abort processing on --, eat token */
+            if ('\0' == argv [i][2])
+                return i+1;
+
+            if (8 == arglen && 0 == memcmp ("--compat", argv [i], 8)){
+                compat = 1;
+                break;
+            }
+            else if (10 == arglen && 0 == memcmp ("--nocompat", argv [i], 10)){
+                compat = 0;
+                break;
+            }
+        }
+            /* Intentionally falling through */
+        default:
+            printf ("Unknown option: %s\n", argv [i]);
+            show_usage (1);
+        }
+    }
+
+    return i;
+}
+
+/**
+   Translates exe_opts into an array that can be passed to exec ().
+
+   This method malloc ()s two blocks of memory.  The first block is the argv
+   index array.  This is the return value of this method.  The second block
+   is the parsed and split string contents the index referenced.  This block
+   is stored in subscript 1 of the return array.  It is the responsibility of
+   the calling method to free () both blocks.
+
+   @warning this logic is UTF-8 unsafe
+   @warning I/O redirection command piping isn't supported in the parse logic
+   @return the parsed argv array
+   @see exe_opts
+*/
+char**
+split_child_opts ()
+{
+    char in_quote = 0;
+    int in_escape = 0;
+    int in_token = 0;
+    const char *pos;
+    char *target, *last;
+    char **table_pos, **argv;
+
+    assert (0 != exe_opts);
+
+    if (0 == strlen (exe_opts)) {
+        /* Alloc a an index array to hold the program name  */
+        argv = (char**)RW_MALLOC (2 * sizeof (char*));
+
+        /* And tie the two together */
+        argv [1] = (char*)0;
+        return argv;
+    }
+
+    table_pos = argv = (char**)RW_MALLOC (
+        (strlen (exe_opts) + 5) * sizeof (char*) / 2);
+    /* (strlen (exe_opts)+5)/2 is overkill for the most situations, 
+       but it is just large enough to handle the worst case scenario
+       (worst case is similar to 'x y' or 'x y z', requiring lengths
+       of 4 and 5 respectively.)
+    */
+
+    last = target = argv[1] = (char*)RW_MALLOC (strlen (exe_opts) + 1);
+
+    /* Transcribe the contents, handling escaping and splitting */
+    for (pos = exe_opts; *pos; ++pos) {
+        if (in_escape) {
+            *(target++) = *pos;
+            in_escape = 0;
+            continue;
+        }
+        if (isspace (*pos)) {
+            if (in_quote) {
+                *(target++) = *pos;
+            }
+            else {
+                if (in_token) {
+                    *(target++) = '\0';
+                    *(++table_pos) = last;
+                    in_token = 0;
+                }
+                last = target;
+            }
+            continue;
+        }
+        in_token = 1;
+        switch (*pos) {
+        case '\\':
+            in_escape = 1;
+            break;
+        case '"':
+        case '\'':
+            if (*pos == in_quote) {
+                in_quote = 0;
+                break;
+            }
+            else if (0 == in_quote) {
+                in_quote = *pos;
+                break;
+            }
+            /* intentionally falling through (in a quote and quote didn't 
+               match opening quote.
+            */
+        default:
+            *(target++) = *pos;
+        }
+    }
+
+    if (in_token) { /* close and record the final token */
+        *(target++) = '\0';
+        *(++table_pos) = last;
+    }
+    *(++table_pos) = (char*)0;/*And terminate the array*/
+
+    return argv;
+}

Propchange: incubator/stdcxx/trunk/util/cmdopt.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/cmdopt.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/cmdopt.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/cmdopt.h?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/cmdopt.h (added)
+++ incubator/stdcxx/trunk/util/cmdopt.h Mon Jul 24 17:59:04 2006
@@ -0,0 +1,45 @@
+/************************************************************************
+ *
+ * cmdopt.h - Interface declaration for the option parsing subsystem
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_PARSE_OPTS_H
+#define RW_PARSE_OPTS_H
+
+extern int timeout;
+extern int compat;
+extern const char* exe_opts;
+extern const char* in_root;
+extern const char* exe_name;
+
+void 
+show_usage(const int status);
+
+int 
+eval_options (const int argc, /* const */ char* const argv[]);
+
+char**
+split_child_opts();
+
+#endif   // RW_PARSE_OPTS_H

Propchange: incubator/stdcxx/trunk/util/cmdopt.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/cmdopt.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/exec.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.cpp?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/exec.cpp (added)
+++ incubator/stdcxx/trunk/util/exec.cpp Mon Jul 24 17:59:04 2006
@@ -0,0 +1,621 @@
+/************************************************************************
+ *
+ * exec.cpp - Definitions of the child process subsystem
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#include <assert.h> /* for assert */
+#include <errno.h> /* for errno */
+#include <fcntl.h> /* for O_*,  */
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h> /* for str*, mem* */
+
+#include <unistd.h> /* for close, dup, exec, fork */
+#include <sys/stat.h> /* for S_* */
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "cmdopt.h"
+#include "util.h"
+
+#include "exec.h"
+
+/**
+   Status flag used to comunicate that an alarm has triggered
+   @see handle_alrm
+   @see open_input
+*/
+static int
+alarm_timeout;   /* set to a non-zero value when a non-zero timeout expires */
+
+
+/**
+   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
+*/
+const char* 
+get_signame (int signo)
+{
+    static const struct {
+        int         val;
+        const char* str;
+    } names[] = {
+
+#undef SIGNAL
+#define SIGNAL(val)   { SIG ## val, #val }
+
+#ifdef SIGABRT
+        SIGNAL (ABRT),
+#endif   /* SIGABRT */
+#ifdef SIGALRM
+        SIGNAL (ALRM),
+#endif   /* SIGALRM */
+#ifdef SIGBUS
+        SIGNAL (BUS),
+#endif   /* SIGBUS */
+#ifdef SIGCANCEL
+        SIGNAL (CANCEL),
+#endif   /* SIGCANCEL */
+#ifdef SIGCHLD
+        SIGNAL (CHLD),
+#endif   /* SIGCHLD */
+#ifdef SIGCKPT
+        SIGNAL (CKPT),
+#endif   /* SIGCKPT */
+#ifdef SIGCLD
+        SIGNAL (CLD),
+#endif   /* SIGCLD */
+#ifdef SIGCONT
+        SIGNAL (CONT),
+#endif   /* SIGCONT */
+#ifdef SIGDIL
+        SIGNAL (DIL),
+#endif   /* SIGDIL */
+#ifdef SIGEMT
+        SIGNAL (EMT),
+#endif   /* SIGEMT */
+#ifdef SIGFPE
+        SIGNAL (FPE),
+#endif   /* SIGFPE */
+#ifdef SIGFREEZE
+        SIGNAL (FREEZE),
+#endif   /* SIGFREEZE */
+#ifdef SIGGFAULT
+        SIGNAL (GFAULT),
+#endif   /* SIGGFAULT */
+#ifdef SIGHUP
+        SIGNAL (HUP),
+#endif   /* SIGHUP */
+#ifdef SIGILL
+        SIGNAL (ILL),
+#endif   /* SIGILL */
+#ifdef SIGINFO
+        SIGNAL (INFO),
+#endif   /* SIGINFO */
+#ifdef SIGINT
+        SIGNAL (INT),
+#endif   /* SIGINT */
+#ifdef SIGIO
+        SIGNAL (IO),
+#endif   /* SIGIO */
+#ifdef SIGIOT
+        SIGNAL (IOT),
+#endif   /* SIGIOT */
+#ifdef SIGK32
+        SIGNAL (K32),
+#endif   /* SIGK32 */
+#ifdef SIGKILL
+        SIGNAL (KILL),
+#endif   /* SIGKILL */
+#ifdef SIGLOST
+        SIGNAL (LOST),
+#endif   /* SIGLOST */
+#ifdef SIGLWP
+        SIGNAL (LWP),
+#endif   /* SIGLWP */
+#ifdef SIGPIPE
+        SIGNAL (PIPE),
+#endif   /* SIGPIPE */
+#ifdef SIGPOLL
+        SIGNAL (POLL),
+#endif   /* SIGPOLL */
+#ifdef SIGPROF
+        SIGNAL (PROF),
+#endif   /* SIGPROF */
+#ifdef SIGPTINTR
+        SIGNAL (PTINTR),
+#endif   /* SIGPTINTR */
+#ifdef SIGPTRESCHED
+        SIGNAL (PTRESCHED),
+#endif   /* SIGPTRESCHED */
+#ifdef SIGPWR
+        SIGNAL (PWR),
+#endif   /* SIGPWR */
+#ifdef SIGQUIT
+        SIGNAL (QUIT),
+#endif   /* SIGQUIT */
+#ifdef SIGRESTART
+        SIGNAL (RESTART),
+#endif   /* SIGRESTART */
+#ifdef SIGRESV
+        SIGNAL (RESV),
+#endif   /* SIGRESV */
+#ifdef SIGSEGV
+        SIGNAL (SEGV),
+#endif   /* SIGSEGV */
+#ifdef SIGSTKFLT
+        SIGNAL (STKFLT),
+#endif   /* SIGSTKFLT */
+#ifdef SIGSTOP
+        SIGNAL (STOP),
+#endif   /* SIGSTOP */
+#ifdef SIGSYS
+        SIGNAL (SYS),
+#endif   /* SIGSYS */
+#ifdef SIGTERM
+        SIGNAL (TERM),
+#endif   /* SIGTERM */
+#ifdef SIGTHAW
+        SIGNAL (THAW),
+#endif   /* SIGTHAW */
+#ifdef SIGTRAP
+        SIGNAL (TRAP),
+#endif   /* SIGTRAP */
+#ifdef SIGTSTP
+        SIGNAL (TSTP),
+#endif   /* SIGTSTP */
+#ifdef SIGTTIN
+        SIGNAL (TTIN),
+#endif   /* SIGTTIN */
+#ifdef SIGTTOU
+        SIGNAL (TTOU),
+#endif   /* SIGTTOU */
+#ifdef SIGUNUSED
+        SIGNAL (UNUSED),
+#endif   /* SIGUNUSED */
+#ifdef SIGURG
+        SIGNAL (URG),
+#endif   /* SIGURG */
+#ifdef SIGUSR1
+        SIGNAL (USR1),
+#endif   /* SIGUSR1 */
+#ifdef SIGUSR2
+        SIGNAL (USR2),
+#endif   /* SIGUSR2 */
+#ifdef SIGVTALRM
+        SIGNAL (VTALRM),
+#endif   /* SIGVTALRM */
+#ifdef SIGWAITING
+        SIGNAL (WAITING),
+#endif   /* SIGWAITING */
+#ifdef SIGWINCH
+        SIGNAL (WINCH),
+#endif   /* SIGWINCH */
+#ifdef SIGWINDOW
+        SIGNAL (WINDOW),
+#endif   /* SIGWINDOW */
+#ifdef SIGXCPU
+        SIGNAL (XCPU),
+#endif   /* SIGXCPU */
+#ifdef SIGXFSZ
+        SIGNAL (XFSZ),
+#endif   /* SIGXFSZ */
+#ifdef SIGXRES
+        SIGNAL (XRES),
+#endif   /* SIGXRES */
+        { -1, 0 }
+    };
+
+    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;
+        }
+    }
+
+    /* We've run out of known signal numbers, so use a default name */
+    snprintf (def, sizeof(def), "SIG#%d", signo);
+    return def;
+}
+
+/**
+   Callback used to set the alarm_timeout flag in response to recieving
+   the signal SIGALRM
+
+   @param signo the signal recieved (should be SIGALRM)
+   @see alarm_timeout
+*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static void
+handle_alrm (int signo)
+{
+    if (SIGALRM == signo)
+        alarm_timeout = 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+   Monitors child_pid and determines how/when terminated.
+
+   This method is built around a waitpid loop, which is responsible for
+   determining the status of child_pid.  This loop breaks when we've detected
+   that the child process has terminated, or when we conclude it won't 
+   terminate.  To prevent the child process from running forever, we set 
+   handle_alrm as the handler for SIGALRM using the sigaction system call and 
+   set a timeout using the alarm() system call.  If this timeout expires, we 
+   try to kill the child process using several different signals.
+
+   @todo add better handling for corner conditions
+
+   @param child_pid process ID number for the child process to monitor
+   @return structure describing how the child procees exited
+   @see handle_alrm
+   @see alarm_timeout
+*/
+static struct exec_attrs
+wait_for_child (pid_t child_pid)
+{
+    static const int signals[] = {
+        SIGHUP, SIGINT, SIGTERM, SIGKILL, SIGKILL
+    };
+
+    static const unsigned sigcount = sizeof (signals) / sizeof (int);
+
+    struct sigaction act;
+
+    struct exec_attrs state = {-1, 0};
+
+    unsigned siginx = 0;
+
+    int stopped = 0;
+
+#ifdef WCONTINUED
+    int waitopts = WUNTRACED | WCONTINUED;
+#else
+    int waitopts = WUNTRACED;
+#endif
+    assert ( 1 < child_pid );
+
+    /* Clear timeout */
+    alarm_timeout = 0;
+
+    /* Set handler (if needed).  Need to use sigaction rather than signal due
+       to linux glitch
+    */
+    memset (&act, 0, sizeof act);
+    act.sa_handler = handle_alrm;
+    sigaction (SIGALRM, &act, 0);
+    
+    if (timeout>0)
+        alarm (timeout);
+
+    while (1) {
+        const pid_t wait_pid = waitpid (child_pid, &state.status, waitopts);
+        if (child_pid == wait_pid) {
+            if (WIFEXITED (state.status) || WIFSIGNALED (state.status))
+                break; /*we've got an exit state, so let's bail*/
+            else if (WIFSTOPPED (state.status))
+                stopped = state.status;
+#ifdef WIFCONTINUED /*Perhaps we should guard WIFSTOPPED with this guard also */
+            else if (WIFCONTINUED (state.status))
+                stopped = 0;
+#endif
+            else
+                ;   /* huh? */
+        }
+        else if ((pid_t)-1 == wait_pid) {
+            if (EINTR == errno && alarm_timeout) {
+                /* timeout elapsed, so send a signal to the child */
+                if (stopped) {
+                    /* If the child process is stopped, it is incapable of
+                       recieving signals.  Therefore, we'll record this
+                       and break out of the loop.
+                    */
+                    state.status = stopped;
+                    break;
+                }
+
+                /* ignore kill errors (perhaps should record them)*/
+                (void)kill (child_pid, signals [siginx]);
+
+                /* Record the signal used*/
+                state.killed = signals [siginx];
+
+                ++siginx;
+
+                /* Step to the next signal */
+                if (siginx > sigcount ) {
+                    /* Still running, but we've run out of signals to try
+                       Therefore, we'll set error flags and break out of 
+                       the loop.
+                    */
+                    state.status = -1;
+                    state.killed = -1;
+                    break;
+                }
+
+                /* Reset the alarm */
+                alarm_timeout = 0;
+                alarm (1);
+            }
+            else if (EINTR == errno && !alarm_timeout) {
+                /* continue iterating */
+            }
+            else if (EINVAL == errno) {
+                if (waitopts)
+                    /* bad waitpid options, reset to 0 and try again */
+                    waitopts = 0;
+                else
+                    ; /* Now what? */
+            }
+            else if (ECHILD == errno) {
+                /* should not happen */
+                fprintf (stderr, "waitpid(%d) error: %s\n",
+                         (int)child_pid, strerror (errno));
+            }
+            else {
+                /* waitpid() error */
+                fprintf (stderr, "waitpid(%d) error: %s\n",
+                         (int)child_pid, strerror (errno));
+            }
+        }
+        else if ((pid_t)0 == wait_pid) {
+            /* should not happen */
+        }
+        else {
+            /* what the heck? */
+        }
+    }
+
+    /* Clear alarm */
+    alarm (0);
+
+    return state;
+}
+
+/**
+   Opens an input file, based on exec_name
+
+   Takes an executable name, and tries to open an input file based on this 
+   name and the value of the in_root global variable.  If a file is found in 
+   neither of two locattions derived from these variables, this method tries
+   to fall back on /dev/null.
+
+   Source file locations:
+     - [in_root]/manual/in/[exec_name].in
+     - [in_root]/tutorial/in/[exec_name].in
+     - /dev/null
+
+   @param exec_name the name of executable being run
+   @returns the file descriptor of the opened file
+   @see in_root
+*/
+static int
+open_input (const char* exec_name)
+{
+    const size_t root_len = strlen (in_root);
+    int intermit = -1;
+
+    assert (0 != exec_name);
+    assert (0 != in_root);
+
+    if (root_len) {
+        const size_t out_len = root_len + strlen (exec_name) + 17;
+    
+        char* const tmp_name = (char*)RW_MALLOC (out_len);
+
+        /* Try in_root/manual/in/exec_name.in */
+        memcpy (tmp_name, in_root, root_len+1);
+        strcat (tmp_name, "/manual/in/");
+        strcat (tmp_name, exec_name);
+        strcat (tmp_name, ".in");
+        intermit = open (tmp_name, O_RDONLY);
+    
+        /* If we opened the file, return the descriptor */
+        if (0 <= intermit) {
+            free (tmp_name);
+            return intermit;
+        }
+
+        /* If the file exists (errno isn't ENOENT), exit */
+        if (ENOENT != errno)
+            terminate ( 1, "open(%s) failed: %s\n", tmp_name, 
+                        strerror (errno));
+
+        /* Try in_root/tutorial/in/exec_name.in */
+        memcpy (tmp_name, in_root, root_len+1);
+        strcat (tmp_name, "/tutorial/in/");
+        strcat (tmp_name, exec_name);
+        strcat (tmp_name, ".in");
+        intermit = open (tmp_name, O_RDONLY);
+
+        /* If we opened the file, return the descriptor */
+        if (0 <= intermit) {
+            free (tmp_name);
+            return intermit;
+        }
+
+        /* If the file exists (errno isn't ENOENT), exit */
+        if (-1 == intermit && ENOENT != errno)
+            terminate ( 1, "open(%s) failed: %s\n", tmp_name, 
+                        strerror (errno));
+
+        free(tmp_name);
+    }
+
+    /* If we didn't find a source file, open /dev/null */
+
+    intermit = open("/dev/null", O_RDONLY);
+
+    /* If we opened the file, return the descriptor */
+    if (0 <= intermit)
+        return intermit;
+
+    /* otherwise, print an error message and exit */
+    terminate ( 1, "open(/dev/null) failed: %s\n", strerror (errno));
+    return -1; /* silence a compiler warning */
+}
+
+/**
+   Replaces one file descriptor with a second, closing second after replacing
+   the first.
+
+   @param source file descriptor to copy
+   @param dest file descriptor to replace
+   @param name human understanable name for dest, used in error messages
+*/
+static void
+replace_file (int source, int dest, const char* name)
+{
+    int result;
+
+    assert (source != dest);
+    assert (0 <= source);
+    assert (0 <= dest);
+    assert (0 != name);
+
+    result = dup2 (source, dest);
+    if (-1 == result)
+        terminate ( 1,  "redirecting to %s failed: %s\n", name, 
+                    strerror (errno));
+
+    result = close (source);
+    if (-1 == result)
+        terminate ( 1,  "closing source for %s redirection failed: %s\n", 
+                    name, strerror (errno));
+}
+
+/**
+   Entry point to the watchdog subsystem.
+
+   This method fork()s, creating a child process.  This child process becomes
+   a process group leader, redirects input and output files, then exec()s
+   the target specified in argv[0], providing it with argv to use as its argv 
+   array.  Meanwhile, the parent process calls the wait_for_child method to
+   monitor the child process, passing the return value back to the calling
+   method.
+
+   @param exec_name name of the child executable
+   @param argv argv array for child process
+   @return structure describing how the child procees exited
+   @see wait_for_child()
+*/
+struct exec_attrs 
+exec_file (const char* exec_name, char** argv)
+{
+    const pid_t child_pid = fork ();
+
+    if (0 == child_pid) {   /* child */
+        FILE* error_file;
+
+        assert (0 != argv);
+        assert (0 != argv[0]);
+        assert (0 != exec_name);
+
+        /* Set process group ID (so entire group can be killed)*/
+        {
+            const pid_t pgroup = setsid();
+            if ( getpid() != pgroup )
+                terminate ( 1, "Error setting process group: %s\n",
+                            strerror (errno));
+        }
+
+        /* Cache stdout for use if execv() fails */
+        {
+            const int error_cache = dup (2);
+            if (-1 == error_cache)
+                terminate ( 1,  "Error duplicating stderr: %s\n", 
+                            strerror (errno));
+
+            error_file = fdopen (error_cache,"a");
+            if (0 == error_file)
+                terminate ( 1,  "Error opening file handle  from cloned "
+                            "stderr file descriptor: %s\n", strerror (errno));
+        }
+
+        /* Redirect stdin */
+        {
+            const int intermit = open_input (exec_name);
+            replace_file(intermit, 0, "stdin");
+        }
+
+        /* Redirect stdout */
+        {
+            const size_t exelen = strlen (argv[0]);
+            const size_t outlen = exelen + 5;
+            char* const tmp_name = (char*)RW_MALLOC (outlen);
+            int intermit;
+
+            /* Redirect stdout */
+            memcpy (tmp_name, argv[0], exelen + 1);
+            strcat (tmp_name, ".out");
+            intermit = open (tmp_name, O_WRONLY | O_CREAT | O_TRUNC, 
+                             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+            if (-1 == intermit)
+                terminate( 1,  "Error opening %s for output redirection: "
+                           "%s\n", tmp_name, strerror (errno));
+
+            replace_file(intermit, 1, "stdout");
+
+            free (tmp_name);
+        }
+
+        /* Redirect stderr */
+        if (-1 == dup2(1, 2))
+            terminate ( 1,  "Redirection of stderr to stdout failed: %s\n", 
+                        strerror (errno));
+
+        execv (argv [0], argv);
+
+        fprintf (error_file, "execv (\"%s\", ...) error: %s\n",
+                 argv [0], strerror (errno));
+
+        exit (1);
+    }
+
+    if (-1 == child_pid){
+        /* Fake a failue to execute status return structure */
+        struct exec_attrs state = {127, -1};
+        fprintf (stderr, "Unable to create child process for %s: %s\n",
+                 argv[0], strerror (errno));
+        return state;
+    }
+
+    /* parent */
+    return wait_for_child ( child_pid );
+}

Propchange: incubator/stdcxx/trunk/util/exec.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/exec.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/exec.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.h?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/exec.h (added)
+++ incubator/stdcxx/trunk/util/exec.h Mon Jul 24 17:59:04 2006
@@ -0,0 +1,41 @@
+/************************************************************************
+ *
+ * exec.h - Interface declaration for the child process subsystem
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_EXEC_H
+#define RW_EXEC_H
+
+struct exec_attrs {
+    int status;
+    int killed;
+};
+
+const char* 
+get_signame (int);
+
+struct exec_attrs 
+exec_file (const char*, char**);
+
+#endif   // RW_EXEC

Propchange: incubator/stdcxx/trunk/util/exec.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/exec.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/output.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/output.cpp?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/output.cpp (added)
+++ incubator/stdcxx/trunk/util/output.cpp Mon Jul 24 17:59:04 2006
@@ -0,0 +1,406 @@
+/************************************************************************
+ *
+ * output.cpp - Definitions of the result parsing subsystem
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h> /* for printf, puts, FILE, f* */
+#include <stdlib.h> /* for exit, free */
+#include <string.h> /* for str* */
+
+#include <unistd.h>
+    /* for close, dup, exec, fork - remove when removing diff dependancy*/
+#include <sys/types.h>
+#include <sys/wait.h> /* for waitpid, W* */
+
+#include <sys/stat.h>
+
+#include "cmdopt.h"
+#include "exec.h"
+    /* for get_signame - remove when removing diff dependancy */
+#include "util.h"
+
+#include "output.h"
+
+#ifndef ENOENT
+#  define ENOENT 2
+#endif   // ENOENT
+
+
+/**
+   Parses output file out_name for test exec_name.
+   
+   This method tries to open out_name.  If this succedes, it then searches
+   the file for a result summary as produced by the rwtest driver.
+   If a result summary is found, it then parses the result and displays the
+   result of the parsing.  Otherwise, and appropriate error messages is 
+   displayed.
+
+   Output messages produced:
+     - OUTPUT\n
+       Output file couldn't be opened
+     - OFLOW\n
+       Assertions counted overflows the (internal)storage variable
+     - FORMAT\n
+       Result summary can't be found in output file
+     - 0 [assertion count] [failed assertion count] [pass rate]\n
+       Parsed results
+
+   @param exec_name the name of the executable that generated the output file
+   @param out_name the name of the output file being parsed
+*/
+static void
+check_test (const char* exec_name, const char* out_name)
+{
+    FILE* data = fopen (out_name, "r");
+    unsigned r_lvl = 0, r_active = 0, r_total = 0;
+    unsigned asserts = 0, failed = 0;
+    int fmt_ok = 0;
+    unsigned fsm = 0;
+    char tok;
+
+    assert ( 0 != exec_name );
+    assert ( 0 != out_name );
+
+    if (0 == data) {
+        if (ENOENT != errno) {
+            printf ("Error opening %s: %s\n", out_name, strerror (errno));
+            return;
+        }
+        puts ("OUTPUT");
+        return;
+    }
+
+    for (tok = fgetc (data); fsm < 6 && !feof (data); tok = fgetc (data)) {
+        switch (tok) {
+        case '\n':
+            fsm = 1;
+            break;
+        case '#':
+            fsm = ( 1 == fsm ) ? 2 : 0;
+            break;
+        case ' ':
+            fsm = ( 2 == fsm ) ? 3 : ( ( 4 == fsm ) ? 5 : 0 );
+            break;
+        case '|':
+            fsm = ( 3 == fsm ) ? 4 : 0;
+            break;
+        case '(':
+            if ( 5 == fsm ) {
+                fseek (data, -6, SEEK_CUR);
+                fsm++;
+                break;
+            }
+        default:
+            fsm = 0;
+        }
+    }
+
+    if (!feof(data)) {
+        while (3 == fscanf(data, "# | (S%u) %*s | %u | %u | %*u%% |\n", 
+                        &r_lvl, &r_active, &r_total)) {
+            if (6 < r_lvl) {
+                /* The 0.new tests produces errors, and are all 
+                   expected to be active, so invert the total */
+                if (8 == r_lvl && 0 == strcmp(exec_name,"0.new"))
+                    r_active = r_total-r_active;
+                failed += r_active;
+                asserts += r_total;
+                if (failed < r_active || asserts < r_total) {
+                    puts(" OFLOW");
+                    return;
+                }
+            }
+            /* else if (1 < r_lvl) warning*/
+            fmt_ok = 1;
+        }
+    }
+    
+    if (fmt_ok) {
+        unsigned pcnt = 0;
+        if (asserts) {
+            pcnt = 100 * ( asserts - failed ) / asserts;
+        }
+        printf("     0 %6d %6d %5d%%\n", asserts, failed, pcnt);
+    }
+    else {
+        puts("FORMAT");
+    }
+
+    fclose(data);
+}
+
+/**
+   Parses output file out_name for test exec_name.
+   
+   This method is a reimplementation of check_test().  The difference between
+   this method and check_test() is how it parses the results.  This version
+   parses compatability layer output, rather than the test driver output.
+
+   @param exec_name the name of the executable that generated the output file
+   @param out_name the name of the output file being parsed
+   @see check_test()
+*/
+static void
+check_compat_test (const char* out_name)
+{
+    FILE* data = fopen (out_name, "r");
+    unsigned asserts = 0, failed = 0;
+    int read = 0;
+    unsigned fsm = 0;
+    char tok;
+
+    assert ( 0 != out_name );
+
+    if (0 == data) {
+        if (ENOENT != errno) {
+            printf ("Error opening %s: %s\n", out_name, strerror (errno));
+            return;
+        }
+        puts ("OUTPUT");
+        return;
+    }
+
+    fseek (data, -64, SEEK_END); /* Seek near the end of the file */
+
+    for (tok = fgetc (data); fsm < 4 && !feof (data); tok = fgetc (data)) {
+        switch (tok) {
+        case '\n':
+            fsm = 1;
+            break;
+        case '#':
+            if ( 1 == fsm || 2 == fsm )
+                ++fsm;
+            else
+                fsm = 0;
+            break;
+        case ' ':
+            if ( 3 == fsm ) {
+                ++fsm;
+                break;
+            }
+        default:
+            fsm = 0;
+        }
+    }
+
+    if (!feof(data)) { /* leading "## A" eaten above */
+        read = fscanf(data, "ssertions = %u\n## FailedAssertions = %u",
+                        &asserts, &failed);
+    }
+
+    if (2 == read) {
+        unsigned pcnt = 0;
+        if (asserts) {
+            pcnt = 100 * ( asserts - failed ) / asserts;
+        }
+        printf("     0 %6d %6d %5d%%\n", asserts, failed, pcnt);
+    }
+    else {
+        puts("FORMAT");
+    }
+
+    fclose(data);
+}
+
+/**
+   Sanity test macro for file descriptor operations.
+   
+   @killme this should be removed after removing the dependancy on the
+   posix diff utility
+   
+   @param op human understandable name for operation
+   @param x variable to test the result for
+   @see check_example
+*/
+#define FILE_TEST(op, x)                                                \
+    if (-1==(x))                                                        \
+        terminate ( 2, op " failed: %s\n", strerror (errno) )
+
+/**
+   Parses output file out_name for the example exec_name.
+   
+   This method tries to compare out_name against a reference output file and
+   displays a result code.  The reference file is determined by exec_name and
+   the in_root global variable.
+   This method relies on the POSIX diff utility at this time.  This dependancy
+   needs to be removed, though doing so will require a rewrite of the method.
+
+   Reference file locations:
+     - [in_root]/manual/out/[exec_name].out
+     - [in_root]/tutorial/out/[exec_name].out
+
+   Output messages produced:
+     - NOREF\n
+       No reference file could be found
+     - OUTPUT\n
+       Output file differs from the reference file
+     - 0\n
+       Output file matches the reference file (check passes)
+
+   @param exec_name the name of the executable that generated the output file
+   @param out_name the name of the output file being parsed
+   @see in_root
+   @see FILE_TEST()
+   @todo remove dependancy on POSIX diff utility
+*/
+static void
+check_example(const char* const exec_name, const char* const out_name)
+{
+    struct stat file_info;
+    const size_t root_len = strlen(in_root);
+    char* const ref_name = (char*)RW_MALLOC(root_len 
+                                           + strlen(exec_name) + 19);
+    int state = -1;
+
+    assert (0 != in_root);
+    assert (0 < root_len);
+    assert (0 != exec_name);
+    assert (0 != out_name);
+
+    /* Try in_root/manual/out/exec_name.out */
+    memcpy (ref_name, in_root, root_len+1);
+    strcat (ref_name, "/manual/out/");
+    strcat (ref_name, exec_name);
+    strcat (ref_name, ".out");
+
+    if (0 > stat(ref_name, &file_info)) {
+        if (ENOENT != errno) {
+            printf("stat(%s) error: %s\n", ref_name, 
+                   strerror (errno));
+            free(ref_name);
+            return;
+        }
+                        
+        /* If that doesn't exist, try 
+           in_root/tutorial/out/exec_name.out */
+        memcpy (ref_name, in_root, root_len+1);
+        strcat (ref_name, "/tutorial/out/");
+        strcat (ref_name, exec_name);
+        strcat (ref_name, ".out");
+
+        if (0 > stat(ref_name, &file_info)) {
+            if (ENOENT != errno) {
+                printf("stat(%s) error: %s\n", ref_name, 
+                       strerror (errno));
+            }
+            else {
+                puts(" NOREF");
+            }
+            free(ref_name);
+            return;
+        }
+    }
+
+    const pid_t child_pid = fork ();
+
+    if (0 == child_pid) {   /* child */
+        /* Cache stdout (hopefully) for use if execv() fails */
+        int error_cache = dup(2);
+        FILE* error_file;
+        FILE_TEST("dup(stderr)", error_cache);
+
+        FILE_TEST("close(stdin)",close(0));
+        FILE_TEST("close(stdin)",close(1));
+        FILE_TEST("close(stderr)",close(2));
+
+        /* Todo: diff with --strip-trailing-cr on windows */
+        execlp ("diff", "diff", ref_name, out_name, (char *)0);
+
+        if ((error_file = fdopen (error_cache, "a")))
+            fprintf (error_file, "execlp(\"diff\", ...) error: %s\n",
+                     strerror (errno));
+
+        exit(2);
+    }
+
+    while (1) {
+        const pid_t wait_pid = waitpid (child_pid, &state, 0);
+
+        if (child_pid == wait_pid) {
+
+            if (WIFEXITED (state)) {
+                const int retcode = WEXITSTATUS (state);                
+                switch ( retcode ) {
+                case 0:
+                    puts("     0");
+                    break;
+                case 1:
+                    puts("OUTPUT");
+                    break;
+                default:
+                    printf("diff returned %d\n", retcode);
+                }
+                break;
+            }
+            else if (WIFSIGNALED (state)) {
+                printf("diff exited with %s\n", 
+                       get_signame (WTERMSIG (state)));
+                break;
+            }
+/*
+            else if (WIFSTOPPED (state)) {
+                printf ("process %d stopped\n", (int)child_pid);
+            }
+            else if (WIFCONTINUED (state)) {
+                printf ("process %d continued\n", (int)child_pid);
+            }
+*/
+        }
+    }
+
+    free(ref_name);
+}
+
+/**
+   Dispatch method that invoks another method to parse the output file.
+
+   @param target the path to the executable that generated the output file
+   @param exec_name the name of the executable that generated the output file
+   @see check_test()
+   @see check_compat_test()
+   @see check_example()
+*/
+void
+parse_output (const char* target, const char* exec_name)
+{
+    const size_t path_len = strlen ( target );
+    char* const out_name = (char*)RW_MALLOC ( path_len + 5);
+    memcpy (out_name, target, path_len + 1);
+    strcat (out_name,".out");
+
+    if (!strlen (in_root)) {
+        /* If there is not an input directory, look at the assertion tags */
+        if (!compat)
+            check_test (exec_name, out_name);
+        else
+            check_compat_test (out_name);
+    }
+    else{
+        /* Otherwise, diff against the output file */
+        check_example (exec_name, out_name);
+    }
+    free(out_name);
+}

Propchange: incubator/stdcxx/trunk/util/output.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/output.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/output.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/output.h?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/output.h (added)
+++ incubator/stdcxx/trunk/util/output.h Mon Jul 24 17:59:04 2006
@@ -0,0 +1,33 @@
+/************************************************************************
+ *
+ * output.h - Interface declaration for the result parsing subsystem
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+
+void
+parse_output (const char*, const char*);
+
+#endif   // OUTPUT_H

Propchange: incubator/stdcxx/trunk/util/output.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/output.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/runall.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/runall.cpp?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/runall.cpp (added)
+++ incubator/stdcxx/trunk/util/runall.cpp Mon Jul 24 17:59:04 2006
@@ -0,0 +1,300 @@
+/************************************************************************
+ *
+ * runall.cpp - Core logic for the exec utility
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h> /* for printf, puts, FILE, f* */
+#include <stdlib.h> /* for exit, free */
+#include <string.h> /* for str* */
+
+#include <unistd.h>
+    /* for close, dup, exec, fork - remove when removing diff dependancy*/
+#include <sys/types.h>
+#include <sys/wait.h> /* for waitpid, W* */
+
+#include <sys/stat.h>
+
+#include "cmdopt.h"
+#include "exec.h"
+#include "output.h"
+#include "util.h"
+
+#ifndef ENOENT
+#  define ENOENT 2
+#endif   // ENOENT
+
+/**
+   Preflight check to ensure that target is something that should be run.
+
+   This method checks to see if target exists and is theoretically executable.
+   A special case is the situation where the target name ends in .o, 
+   indicating that the target only needed to compile, and doesn't need to
+   be run.  If there are problems, or the target is a .o file, a result is 
+   displayed and 0 is returned.
+
+   Output messages produced:
+     - COMP\n
+       Target failed to compile
+     - LINK\n
+       Target failed to link
+     - XPERM\n
+       Target lacks execute permissions
+     - 0\n
+       Target .o file exists (check passes)
+
+   @param target the path to the executable to check
+   @return 1 if valid target to run, 0 otherwise.
+*/
+static int
+check_target_ok (const char* target)
+{
+    struct stat file_info;
+    int exists = 1;
+
+    if (0 > stat (target, &file_info)) {
+        if (ENOENT != errno) {
+            printf ("Stat error: %s\n", strerror (errno));
+            return 0;
+        }
+        file_info.st_mode = 0; /* force mode on non-existant file to 0 */
+        exists = 0; /* note that it doesn't exist */
+    }
+    if (0 == (file_info.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
+        /* This is roughly equivlent to the -x bash operator.
+           It checks if the file can be run, /not/ if we can run it
+        */
+        const size_t path_len = strlen ( target );
+        char* tmp_name;
+
+        /* If target is a .o file, check if it exists */
+        if ( '.' == target [path_len-1] && 'o' == target [path_len] ){
+            if (exists)
+                puts ("     0");
+            else
+                puts ("  COMP");
+            return 0;
+        }
+            
+        /* If the target exists, it doesn't have valid permissions */
+        if (exists) {
+            puts (" XPERM");
+            return 0;
+        }
+
+        /* Otherwise, check for the .o file */
+        tmp_name = (char*)RW_MALLOC ( path_len + 3 );
+        memcpy (tmp_name, target, path_len + 1);
+        strcat (tmp_name,".o");
+
+        if (0 > stat(tmp_name, &file_info)) {
+            if (ENOENT != errno) {
+                printf ("stat(%s) error: %s\n", tmp_name, 
+                        strerror (errno));
+            }
+            else {
+                puts ("  COMP");
+            }
+        }
+        else {
+            puts ("  LINK");
+        }
+                
+        free(tmp_name);
+        return 0;
+    }
+    return 1;
+}
+
+/**
+   Post target execution result analysis.
+
+   This method examines the content of result, dispatching the processing
+   to check_test() or check_example() if target had a return code of 0.
+   Otherwise, this method determines why target terminated, based on the
+   return code and outputs that reason.
+
+   Output messages produced:
+     - EXIST\n
+       Return code 126 (target doesn't exist?)
+     - EXEC\n
+       Return code 127 (target couldn't be run?)
+     - NKILL\n
+       Couldn't kill the child executable
+     - n\n
+       Child exited with the non-zero return code n
+     - name\n
+       Child terminated upon recieving the signal SIGname
+
+   @param target the path to the executable that was run
+   @param exec_name the short name of the executable
+   @param result the return code data from running the target
+   @see check_test()
+   @see check_example()
+*/
+static void
+process_results (const char* target, const char* exec_name, 
+                 const struct exec_attrs* result)
+{
+    if (0 == result->status) {
+        parse_output(target, exec_name);
+    } 
+    else if (WIFEXITED (result->status)) {
+        const int retcode = WEXITSTATUS (result->status);
+        switch (retcode) {
+        case 126:
+            puts (" EXIST");
+            break;
+        case 127:
+            puts ("  EXEC");
+            break;
+        default:
+            printf ("%6d\n", retcode);
+        }
+    }
+    else if (WIFSIGNALED (result->status)) {
+        printf("%6s\n", get_signame (WTERMSIG (result->status)));
+    }
+    else if (WIFSTOPPED (result->status)) {
+        printf("%6s\n", get_signame (WSTOPSIG (result->status)));
+    }
+    else if (-1 == result->status && -1 == result->killed) {
+        puts (" NKILL");
+    }
+    else {
+        printf ("(%d|%d)\n", result->status, result->killed);
+    }
+}
+
+/**
+   (Re)implementation of the POSIX basename function.
+
+   This is a simplistic (re)implementation of the basename function
+   specified in the XSI extension to the IEEE Std 1003.1 (POSIX) standard.
+
+   @warning this method is UTF-8 unsafe
+   @warning this method assumes there are no trailing slashes in the path name
+   @warning this method retuns a pointer referencing a position inside the 
+   provided path.  As such, the returned string isn't a new string, but rather 
+   an alias to the provided string.
+   @param path path name to determine the basename for
+   @return final element in path name
+*/
+static const char*
+rw_basename (const char* path)
+{
+    const char *pos, *mark;
+
+    assert (0 != path);
+
+    for (mark = pos = path; '\0' != *(pos); ++pos)
+        mark = ( '/' == *(pos) || '\\' == *(pos) ) ? pos+1 : mark;
+
+    return mark;
+}
+
+/**
+   High level method to run target, using childargv as arguments.
+
+   This method preflights the execution of target, runs it using the watchdog
+   subsystem, then processes the results from that subsystem.
+
+   @param target path to target executable
+   @param null ((char*)0) terminated array of parameters to be passed to 
+   target when it is run
+   @see check_target_ok
+   @see exec_file
+   @see process_results
+*/
+static void
+run_target (char* target, char** childargv)
+{
+    struct exec_attrs status;
+    const char* const exec_name = rw_basename (target);
+
+    assert (0 != target);
+    assert (0 != childargv);
+
+    childargv [0] = target;
+
+    printf ( "%-18.18s ", exec_name );
+    fflush ( stdout );
+
+    if ( !check_target_ok (target))
+        return;
+
+    status = exec_file (exec_name, childargv);
+
+    process_results (target, exec_name, &status);
+}
+
+/**
+   Entry point to the application.
+
+   Passes arguments to the option processing subsystem, then processes all
+   remaing arguments as targets using run_target
+
+   @param argc number of arguments recieved
+   @param argv array of arguments recieved
+   @return 0 upon successfull completeion of execution
+*/
+
+int
+main (int argc, char *argv[])
+{
+    exe_name = argv[0];
+
+    if (1 < argc && '-' == argv [1][0]) {
+        const int nopts = eval_options (argc, argv);
+
+        if (0 > nopts)
+            return 1;
+
+        argc -= nopts;
+        argv += nopts;
+    }
+    else {
+        --argc;
+        ++argv;
+    }
+
+    if (0 < argc) {
+        int i;
+        char** childargv = split_child_opts();
+
+        assert ( 0 != childargv );
+        puts("NAME               STATUS ASSRTS FAILED PERCNT");
+
+        for ( i = 0; i < argc; ++i ) {
+            run_target ( argv [i], childargv );
+        }
+
+        if (childargv [1])
+            free (childargv [1]);
+        free (childargv);
+    }
+
+    return 0;
+}

Propchange: incubator/stdcxx/trunk/util/runall.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/runall.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/util.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/util.cpp?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/util.cpp (added)
+++ incubator/stdcxx/trunk/util/util.cpp Mon Jul 24 17:59:04 2006
@@ -0,0 +1,75 @@
+/************************************************************************
+ *
+ * util.cpp - Utility function definitions for the runall utility
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ **************************************************************************/
+
+#include <assert.h> /* for assert */
+#include <errno.h> /* for errno */
+#include <stdio.h> /* for vfprintf */
+#include <stdlib.h> /* for exit, malloc */
+#include <stdarg.h> /* for va_* */
+#include <string.h> /* for strerror */
+#include <sys/types.h> /* for size_t */
+
+#include "util.h"
+
+/**
+   Wrapper for exit(), providing a terminal error message on stderr.
+
+   @param state non-zero status code to exit() with
+   @param format printf() format string to display on stderr
+*/
+void
+terminate ( const int state, const char* const format, ... )
+{
+    va_list args;
+
+    assert (0 != format);
+    assert (0 != state);
+
+    va_start ( args, format );
+    vfprintf ( stderr, format, args );
+    va_end ( args );
+
+    exit ( state );
+}
+
+/**
+   Wrapper for malloc(), providing return value checking.
+
+   @param size number of bytes of memory to allocate
+   @param file name of file calling method
+   @param line line number in file method was called from
+   @return (non-null) pointer to allocated bock of memory
+*/
+void*
+guarded_malloc (const size_t size, const char* const file, const unsigned line)
+{
+    void* const alloc = malloc(size);
+
+    assert (0 != file);
+    assert (0 < size);
+
+    if ( 0 == alloc )
+        terminate ( 1, "malloc(%lu) at line %u of %s failed: %s\n", 
+                 (unsigned long)size, line, file, strerror (errno));
+
+    return alloc;
+}

Propchange: incubator/stdcxx/trunk/util/util.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/util.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/util/util.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/util.h?rev=425242&view=auto
==============================================================================
--- incubator/stdcxx/trunk/util/util.h (added)
+++ incubator/stdcxx/trunk/util/util.h Mon Jul 24 17:59:04 2006
@@ -0,0 +1,43 @@
+/************************************************************************
+ *
+ * util.h - Utility macros / prototypes for the runall utility
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_UTIL_H
+#define RW_UTIL_H
+
+void terminate ( const int state, const char* const format, ... );
+
+/* Note: RW_MALLOC should be used rather than malloc within the runall 
+   utility.  This macro calls the guarded_malloc function which performs 
+   validation on inputs and outputs.  guarded_malloc shouldn't be called 
+   directly, as it needs file and line information, provided by RW_MALLOC.
+*/
+
+#define RW_MALLOC(size)                             \
+    guarded_malloc(size, __FILE__, __LINE__)
+void* guarded_malloc (const size_t size, const char* const file, 
+                      const unsigned line);
+
+#endif   // RW_UTIL_H

Propchange: incubator/stdcxx/trunk/util/util.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/util/util.h
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message