2008-05-27  Travis Vitek  <vitek@roguewave.com>

	Merged branches/4.3.x@660567 to trunk



git-svn-id: https://svn.apache.org/repos/asf/stdcxx/trunk@660776 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bin/genxviews b/bin/genxviews
index 87eb1db..cc5a158 100755
--- a/bin/genxviews
+++ b/bin/genxviews
@@ -205,12 +205,14 @@
           <th>Operating System</td>
           <th>Architecture</td>
           <th>Compiler</td>
-          <th>Build Results</td>
-          <th>Logs</td>
-          <th>Time<br>(sec)</td>
+          <th title="Cross-build result page">Build Results</td>
+          <th title="Total number of logs">Logs</td>
+          <th title="Number of logs added since the last run">New</td>
+          <th title="Timestamp of oldest log">Age</td>
+          <th title="Time to process all logs">Time<br>(sec)</td>
         </tr>
-        </thead>
-        <tbody>
+      </thead>
+      <tbody>
 EOF
 
 
@@ -228,10 +230,10 @@
     fi
 
     cat<<EOF | output
-          <tr>
-            <td>$osname</td>
-            <td>$arch</td>
-            <td>$compiler</td>
+        <tr>
+          <td>$osname</td>
+          <td>$arch</td>
+          <td>$compiler</td>
 EOF
 
     # build types:
@@ -247,6 +249,8 @@
     suffixes="a A d D s S"
 
     unset buildlogs
+    unset oldest
+
     count=0
 
     for b in $btypes; do
@@ -261,8 +265,16 @@
         done
     done
 
+    if [ -e $outdir/$xfile ]; then
+        # count the number of logs that are newer than the cross-build file
+        newlogs=`find $logdir/ -name "$alllogs" -newer $outdir/$xfile | wc -l`
+    else
+        # cross-build file doesn't exist yet, all logs are considered new
+        newlogs=$count
+    fi
+
     if [ $verbose -ne 0 ]; then
-        echo "$myname: found $count logs: $buildlogs"
+        echo "$myname: found $count logs ($newlogs new): $buildlogs"
     fi
 
     # create a title for the page
@@ -273,16 +285,26 @@
 
     if [ "$buildlogs" = "" ]; then
         # format missing logs in italics
-        output "            <td><i>$xfile</i></td>"
+        output "          <td><i>$xfile</i></td>"
     else
-        if [ $verbose -ne 0 ]; then
-            echo "$myname: $XBUILDGEN $verarg -s -o$outdir/$xfile -T\"$title\" $buildlogs"
-        fi
+        output "          <td><a href=\"$xfile\">$xfile</a></td>"
 
-        output "            <td><a href=\"$xfile\">$xfile</a></td>"
+        oldest=`  cd $logdir && ls -lrt $buildlogs | head -n 1 \
+                | awk '{ print $6 " " $7 " " $8 }'`
 
-        if [ $dryrun -eq 0 ]; then
-            $XBUILDGEN $verarg -s -o$outdir/$xfile -T"$title" $buildlogs
+        if [ $newlogs -gt 0 ]; then
+
+            # only invoken xbuildgen when there are new logs to proecess
+            # otherwise simply point at the previously generated cross
+            # build file
+
+            if [ $verbose -ne 0 ]; then
+                echo "$myname: $XBUILDGEN $verarg -s -o$outdir/$xfile -T\"$title\" $buildlogs"
+            fi
+
+            if [ $dryrun -eq 0 ]; then
+                $XBUILDGEN $verarg -s -o$outdir/$xfile -T"$title" $buildlogs
+            fi
         fi
     fi
 
@@ -297,9 +319,11 @@
     duration=`expr $end - $duration`
 
     cat<<EOF | output
-        <td>$count</td>
-        <td>$duration</td>
-    </tr>
+          <td>$count</td>
+          <td>$newlogs</td>
+          <td>$oldest</td>
+          <td>$duration</td>
+        </tr>
 EOF
 }
 
diff --git a/etc/config/gcc.config b/etc/config/gcc.config
index e493b1e..59bdd79 100644
--- a/etc/config/gcc.config
+++ b/etc/config/gcc.config
@@ -273,45 +273,47 @@
 SINGL_CPPFLAGS =
 SINGL_LDFLAGS  =
 
-# (try to) determine the architecture via the (non-standard) -p option
-# the option is recognized on at least HP-UX, IRIX, and Linux (are there
-# any other systems running on IA64?)
-arch=$(shell uname -p 2>/dev/null)
+# gcc can generate 32-bit or 64-bit code by default, depending
+# on how it's configured
+# determine whether the default compiler invocation produces
+# wide (64-bit) or narrow (32-bit) code and set compiler,
+# linker, and other options accordingly
+wide = $(shell    cd /tmp; tmpfile=stdcxx-longsize-$$; export tmpfile;  \
+                  echo "int main() { return 8 == sizeof (long); }"      \
+                       > $$tmpfile.c                                    \
+               && $(CXX) $$tmpfile.c >/dev/null 2>&1 -o $$tmpfile;      \
+               ./$$tmpfile; echo $$?; rm -f $$tmpfile.c $$tmpfile)
 
-ifeq ($(arch),ia64)
-    # LP64 is the default (implicit) setting on IA64
+ifeq ($(wide),0)
+    # narrow (32-bit) mode is implicit
+    # use wide (64-bit) flags to explicitly enable LP64 mode
+
     ifeq ($(OSNAME),HP-UX)
-        # -milp32, -mlp64, etc. are options specific to HP-UX
+        # -milp32 and -mlp64 are options specific to HP-UX
+        CXXFLAGS.wide    = -mlp64
+        LDFLAGS.wide     = -mlp64
+        LDSOFLAGS.wide   = -mlp64
+        ARFLAGS.wide     =
+    else
+        CXXFLAGS.wide    = -m64
+        LDFLAGS.wide     = -m64
+        LDSOFLAGS.wide   = -m64
+        ARFLAGS.wide     =
+    endif
+
+else
+    # wide (64-bit) mode is implicit
+    # use narrow (32-bit) flags to explicitly enable ILP32 mode
+
+    ifeq ($(OSNAME),HP-UX)
         CXXFLAGS.narrow  = -milp32
         LDFLAGS.narrow   = -milp32
         LDSOFLAGS.narrow = -milp32
         ARFLAGS.narrow   =
-    endif
-else
-    # determine whether the default compiler invocation produces
-    # wide (64-bit) or narrow (32-bit) code and set compiler,
-    # linker, and other flags accordingly
-    wide = $(shell tmpfile=/tmp/longsize-$$; export tmpfile;           \
-                   echo "int main() { return 8 == sizeof (long); }"    \
-                        > $$tmpfile.c                                  \
-                   && $(CXX) $$tmpfile.c >/dev/null 2>&1 -o $$tmpfile; \
-                   $$tmpfile; echo $$?; rm -f $$tmpfile.c $$tmpfile)
-
-    ifeq ($(wide),0)
-        # wide (64-bit) flags
-        CXXFLAGS.wide  = -m64
-        LDFLAGS.wide   = -m64
-        LDSOFLAGS.wide = -m64
-        ARFLAGS.wide   =
-
-        # narrow (32-bit) mode is implicit
     else
-        # narrow (32-bit) flags
         CXXFLAGS.narrow  = -m32
         LDFLAGS.narrow   = -m32
         LDSOFLAGS.narrow = -m32
         ARFLAGS.narrow   =
-
-        # wide (64-bit) mode is implicit
     endif
 endif
diff --git a/etc/config/src/MBSTATE_T.cpp b/etc/config/src/MBSTATE_T.cpp
index 3938686..59fb1c6 100644
--- a/etc/config/src/MBSTATE_T.cpp
+++ b/etc/config/src/MBSTATE_T.cpp
@@ -18,12 +18,24 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1999-2007 Rogue Wave Software, Inc.
+ * Copyright 1999-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
 #include "config.h"
 
+#if    defined (__EDG__)                \
+    && !defined (__DECCXX)              \
+    && !defined (__HP_aCC)              \
+    && !defined (__INTEL_COMPILER)      \
+    && !defined (_SGI_COMPILER_VERSION)
+   // disable error #450-D: the type "long long" is nonstandard
+   // when using the vanilla EDG eccp in strict mode (i.e., w/o
+   // long long support)
+#  pragma diag_suppress 450
+#endif   // EDG eccp on Linux
+
+
 // defined to get the correct definition of mbstate_t, available on HPUX;
 // once we get the correct size of the struct, _RWSTD_NO_MBSTATE_T is 
 // defined in rw/_config.h and we (and the users of the library) are left 
diff --git a/etc/config/src/MMAP.cpp b/etc/config/src/MMAP.cpp
new file mode 100644
index 0000000..5f168cd
--- /dev/null
+++ b/etc/config/src/MMAP.cpp
@@ -0,0 +1,46 @@
+// checking for mmap() and munmap() in <sys/mman.h>
+
+/***************************************************************************
+ *
+ * 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.
+ *
+ * Copyright 2008 Rogue Wave Software, Inc.
+ * 
+ **************************************************************************/
+
+#include <sys/mman.h>
+#include <sys/types.h>
+
+
+void* map_file (int fd)
+{
+    return mmap (0, 4096, PROT_READ, MAP_PRIVATE, fd, 0);
+}
+
+
+int main (int argc, char *argv[])
+{
+    // avoid executing the code except when one or more command
+    // line arguments have been specified
+    if (argc < 2)
+        return 0;
+
+    void *p = map_file (argc);
+    munmap (p, 0);
+
+    return 0;
+}
diff --git a/etc/config/src/WCTRANS_T.cpp b/etc/config/src/WCTRANS_T.cpp
index 2062d2b..4fdc428 100644
--- a/etc/config/src/WCTRANS_T.cpp
+++ b/etc/config/src/WCTRANS_T.cpp
@@ -18,12 +18,24 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1999-2007 Rogue Wave Software, Inc.
+ * Copyright 1999-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
 #include "config.h"
 
+#if    defined (__EDG__)                \
+    && !defined (__DECCXX)              \
+    && !defined (__HP_aCC)              \
+    && !defined (__INTEL_COMPILER)      \
+    && !defined (_SGI_COMPILER_VERSION)
+   // disable error #450-D: the type "long long" is nonstandard
+   // when using the vanilla EDG eccp in strict mode (i.e., w/o
+   // long long support)
+#  pragma diag_suppress 450
+#endif   // EDG eccp on Linux
+
+
 #ifndef _RWSTD_NO_WCHAR_H
 #  include <wchar.h>
 #endif   // _RWSTD_NO_WCHAR_H
diff --git a/etc/config/src/WCTYPE_T.cpp b/etc/config/src/WCTYPE_T.cpp
index d6afe96..749e726 100644
--- a/etc/config/src/WCTYPE_T.cpp
+++ b/etc/config/src/WCTYPE_T.cpp
@@ -18,12 +18,25 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1999-2007 Rogue Wave Software, Inc.
+ * Copyright 1999-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
 #include "config.h"
 
+
+#if    defined (__EDG__)                \
+    && !defined (__DECCXX)              \
+    && !defined (__HP_aCC)              \
+    && !defined (__INTEL_COMPILER)      \
+    && !defined (_SGI_COMPILER_VERSION)
+   // disable error #450-D: the type "long long" is nonstandard
+   // when using the vanilla EDG eccp in strict mode (i.e., w/o
+   // long long support)
+#  pragma diag_suppress 450
+#endif   // EDG eccp on Linux
+
+
 #ifndef _RWSTD_NO_WCHAR_H
 #  include <wchar.h>
 #endif   // _RWSTD_NO_WCHAR_H
diff --git a/etc/config/src/WINT_T.cpp b/etc/config/src/WINT_T.cpp
index 1053768..1d20c21 100644
--- a/etc/config/src/WINT_T.cpp
+++ b/etc/config/src/WINT_T.cpp
@@ -18,12 +18,24 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1999-2007 Rogue Wave Software, Inc.
+ * Copyright 1999-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
 #include "config.h"
 
+#if    defined (__EDG__)                \
+    && !defined (__DECCXX)              \
+    && !defined (__HP_aCC)              \
+    && !defined (__INTEL_COMPILER)      \
+    && !defined (_SGI_COMPILER_VERSION)
+   // disable error #450-D: the type "long long" is nonstandard
+   // when using the vanilla EDG eccp in strict mode (i.e., w/o
+   // long long support)
+#  pragma diag_suppress 450
+#endif   // EDG eccp on Linux
+
+
 #ifndef _RWSTD_NO_WCHAR_H
 #  include <wchar.h>
 #endif   // _RWSTD_NO_WCHAR_H
diff --git a/etc/config/vacpp.config b/etc/config/vacpp.config
index a39bfda..1b2e43e 100644
--- a/etc/config/vacpp.config
+++ b/etc/config/vacpp.config
@@ -241,10 +241,11 @@
 
 
 # check if the -qtemplateregistry option is recognized
-use_tempinc=$(shell    echo "int i;" >/tmp/foo.$$$$.c              \
+use_tempinc=$(shell    cd $${TMPDIR:=/tmp}                         \
+                    && echo "int i;" >foo.$$$$.c                   \
                     && $(CXX) -c -qmaxerr=1:w -qtemplateregistry   \
-                              /tmp/foo.$$$$.c >/dev/null 2>&1;     \
-                    echo $$?; rm /tmp/foo.$$$$.c)
+                              foo.$$$$.c >/dev/null 2>&1;          \
+                    echo $$?; rm -f foo.$$$$.c foo.$$$$.o)
 
 # template repository/registry name override
 
diff --git a/examples/manual/failure.cpp b/examples/manual/failure.cpp
index f9a1838..4394cfe 100644
--- a/examples/manual/failure.cpp
+++ b/examples/manual/failure.cpp
@@ -1,6 +1,7 @@
 /**************************************************************************
  *
- * failure.cpp - Example program demonstrating ios::failure.
+ * failure.cpp - Example program demonstrating the use of ios::failure
+ *               and its extendsions provided by this implementation.
  *
  * $Id$
  *
@@ -22,7 +23,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -31,39 +32,78 @@
 
 #include <examples.h>
 
+
 #ifndef _RWSTD_NO_EXCEPTIONS
 
 int main ()
 {
-   try {
-       // Enable exceptions in cin.
-       std::cin.exceptions (std::ios::eofbit);
+    const std::ios::iostate allbits =
+        std::ios::badbit | std::ios::eofbit | std::ios::failbit;
+                
+    // Enable all exceptions in cin.
+    std::cin.exceptions (allbits);
 
-       // Clear all bits and set eofbit.
-       std::cin.clear (std::ios::eofbit);
-   }
-   catch (const std::ios::failure &e) {
-       std::cout << "Caught an exception: " << e.what () << std::endl;
-   }
-   catch (const std::exception &e) {
-       std::cout << "Caught an exception: " << e.what () << std::endl;
+    while (!std::cin.eof ()) {
 
-       return 1;   // Indicate failure.
-   }
-   catch (...) {
-       std::cout << "Caught an unknown exception" << std::endl;
+        // Clear state bits.
+        std::cin.clear ();
 
-       return 1;   // Indicate failure.
-   }
+        try {
+            short i;
+            char  ch;
 
-   return 0;
+            // Try to extract a character and an integer.
+            std::cin >> ch >> i;
+
+            std::cout << ch << ' ' << i << '\n';
+        }
+
+#ifndef _RWSTD_NO_EXT_FAILURE
+
+        // Classes badbit_set, eofbit_set, and failbit_set are
+        // derived from failure and are optional extensions of
+        // this implementation.
+
+        catch (const std::ios::badbit_set &e) {
+            std::cout << "Caught std::ios::badbit_set: "
+                      << e.what () << '\n';
+        }
+        catch (const std::ios::eofbit_set &e) {
+            std::cout << "Caught std::ios::eofbit_set: "
+                      << e.what () << '\n';
+        }
+        catch (const std::ios::failbit_set &e) {
+            std::cout << "Caught std::ios::failbit_set: "
+                      << e.what () << '\n';
+        }
+
+#endif   // _RWSTD_NO_EXT_FAILURE
+
+        catch (const std::ios::failure &e) {
+            std::cout << "Caught std::ios::failure: "
+                      << e.what () << '\n';
+        }
+        catch (const std::exception &e) {
+            std::cout << "Caught std::exception: "
+                      << e.what () << '\n';
+
+            return 1;   // Indicate error.
+        }
+        catch (...) {
+            std::cout << "Caught an unknown exception\n";
+
+            return 1;   // Indicate error.
+        }
+    }
+
+    return 0;
 }
 
-#else
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
 
 int main ()
 {
-    std::cout << "Exceptions not supported." << std::endl;
+    std::cout << "Exceptions not supported\n";
 
     return 0;
 }
diff --git a/examples/manual/in/failure.in b/examples/manual/in/failure.in
new file mode 100644
index 0000000..7a3f19b
--- /dev/null
+++ b/examples/manual/in/failure.in
@@ -0,0 +1,4 @@
+a+1234
+b-1234567890
+c+2345
+d-
diff --git a/examples/manual/out/failure.out b/examples/manual/out/failure.out
index 5e895ea..4edab2a 100644
--- a/examples/manual/out/failure.out
+++ b/examples/manual/out/failure.out
@@ -1 +1,5 @@
-Caught an exception: std::cin: stream object has set ios::eofbit
+a 1234
+Caught std::ios::failbit_set: std::cin: stream object has set ios::failbit
+c 2345
+Caught std::ios::failbit_set: std::cin: stream object has set ios::failbit
+Caught std::ios::failure: std::cin: stream object has set failbit, eofbit
diff --git a/include/loc/_ctype.h b/include/loc/_ctype.h
index df1bcdf..d68ea38 100644
--- a/include/loc/_ctype.h
+++ b/include/loc/_ctype.h
@@ -25,7 +25,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 2001-2005 Rogue Wave Software.
+ * Copyright 2001-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -541,7 +541,11 @@
 inline char
 ctype<wchar_t>::narrow (char_type __c, char __dfault) const
 {
-    const _RWSTD_SIZE_T __inx = _RWSTD_STATIC_CAST (_RWSTD_UWCHAR_INT_T, __c);
+    // carefully convert wchar_t to the unsigned form of its
+    // underlying integer type, avoiding sign extension and
+    // similar issues
+    const _RWSTD_UWCHAR_INT_T __inx =
+        _RWSTD_STATIC_CAST (_RWSTD_UWCHAR_INT_T, __c);
 
     // optimize away all but the first call to the virtual do_widen()
     if (   __inx < sizeof _C_narrow_tab / sizeof *_C_narrow_tab
diff --git a/include/rw/_iosfailure.h b/include/rw/_iosfailure.h
index c8f0718..4eed019 100644
--- a/include/rw/_iosfailure.h
+++ b/include/rw/_iosfailure.h
@@ -25,7 +25,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -56,11 +56,25 @@
 };
 
 
-struct _RWSTD_EXPORT __rw_badbit_set: __rw_failure { };
+// (optionally) thrown when stream sets badbit
+struct _RWSTD_EXPORT __rw_badbit_set: __rw_failure
+{
+    virtual ~__rw_badbit_set () _THROWS (());
+};
 
-struct _RWSTD_EXPORT __rw_eofbit_set: __rw_failure { };
 
-struct _RWSTD_EXPORT __rw_failbit_set: __rw_failure { };
+// (optionally) thrown when stream sets eofbit
+struct _RWSTD_EXPORT __rw_eofbit_set: __rw_failure
+{
+    virtual ~__rw_eofbit_set () _THROWS (());
+};
+
+
+// (optionally) thrown when stream sets failbit
+struct _RWSTD_EXPORT __rw_failbit_set: __rw_failure
+{
+    virtual ~__rw_failbit_set () _THROWS (());
+};
 
 }   // namespace __rw
 
diff --git a/src/catalog.cpp b/src/catalog.cpp
index ec64f15..5c24a69 100644
--- a/src/catalog.cpp
+++ b/src/catalog.cpp
@@ -140,6 +140,8 @@
       __rw_catlist[j-1] = __rw_catlist[j];
     if (j < __rw_catlist.size())
       __rw_catlist[j] = 0;
+    else
+      __rw_catlist[__rw_catlist.size () - 1] = 0;
     return 0;
   }
   return -1;
diff --git a/src/exception.cpp b/src/exception.cpp
index 3b75c2b..8adc4e4 100644
--- a/src/exception.cpp
+++ b/src/exception.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -936,8 +936,10 @@
 }
 
 
-// outline to reduce code bloat caused by compilers that emit the vtbl
-// in every translation unit containing the definition of the class
+// trivial dtors outlined to reduce code bloat caused by compilers that
+// emit the vtbl in every translation unit containing the definition of
+// the class
+
 // virtual dtor
 /* virtual */ __rw_failure::~__rw_failure () _THROWS (())
 {
@@ -945,4 +947,22 @@
 }
 
 
+/* virtual */ __rw_badbit_set::~__rw_badbit_set () _THROWS (())
+{
+    // no-op
+}
+
+
+/* virtual */ __rw_eofbit_set::~__rw_eofbit_set () _THROWS (())
+{
+    // no-op
+}
+
+
+/* virtual */ __rw_failbit_set::~__rw_failbit_set () _THROWS (())
+{
+    // no-op
+}
+
+
 }   // namespace __rw
diff --git a/src/fpclass.h b/src/fpclass.h
new file mode 100644
index 0000000..80fdb65
--- /dev/null
+++ b/src/fpclass.h
@@ -0,0 +1,270 @@
+/***************************************************************************
+ *
+ * fpclass.h - definitions of floating point classification functions
+ *             mirrorring those defined by C99 in <math.h>
+ *
+ * $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.
+ *
+ * Copyright 2008 Rogue Wave Software, Inc.
+ * 
+ **************************************************************************/
+
+#ifndef _RWSTD_FPCLASS_H_INCLUDED
+#define _RWSTD_FPCLASS_H_INCLUDED
+
+#include <rw/_defs.h>
+
+#include <float.h>   // for _finite(), _fpclass(), _isnan(), _copysign()
+#include <math.h>    // for isfinite(), isnan(), isinf(), signbit()
+
+#ifndef _RWSTD_NO_IEEEFP_H
+#  include <ieeefp.h>   // for fpclass(), isnan()
+#endif   // _RWSTD_NO_IEEEFP_H
+
+
+#if defined (_MSC_VER)
+
+
+inline bool
+__rw_isfinite (double val)
+{
+    return !!_finite (val);
+}
+
+
+inline bool
+__rw_signbit (double val)
+{
+    return 0 > _copysign (1., val);
+}
+
+
+inline bool
+__rw_isinf (double val)
+{
+    const int fpc = _fpclass (val);
+
+    if (_FPCLASS_NINF == fpc) {
+        // verify that __rw_signbit() correctly determines
+        // the sign of negative infinity
+        _RWSTD_ASSERT (__rw_signbit (val));
+        return true;
+    }
+    else if (_FPCLASS_PINF == fpc) {
+        // verify that __rw_signbit() correctly determines
+        // the sign of positive infinity
+        _RWSTD_ASSERT (!__rw_signbit (val));
+        return true;
+    }
+
+    return false;
+}
+
+
+inline bool
+__rw_isnan (double val)
+{
+    return !!_isnan (val);
+}
+
+
+inline bool __rw_isqnan (double val)
+{
+    return _FPCLASS_QNAN == _fpclass (val);
+}
+
+
+inline bool __rw_issnan (double val)
+{
+    return _FPCLASS_SNAN == _fpclass (val);
+}
+
+
+#elif defined (_RWSTD_OS_SUNOS)
+
+inline bool
+__rw_isfinite (double val)
+{
+    return !!finite (val);
+}
+
+
+inline bool
+__rw_signbit (double val)
+{
+    // implement own signbit() to avoid dragging in libm or libsunmath
+    return _RWSTD_REINTERPRET_CAST (const _RWSTD_UINT64_T&, val) >> 63;
+}
+
+
+inline bool
+__rw_isinf (double val)
+{
+    const int fpc = fpclass (val);
+
+    if (FP_NINF == fpc) {
+        // verify that __rw_signbit() correctly determines
+        // the sign of negative infinity
+        _RWSTD_ASSERT (__rw_signbit (val));
+        return true;
+    }
+    else if (FP_PINF == fpc) {
+        // verify that __rw_signbit() correctly determines
+        // the sign of positive infinity
+        _RWSTD_ASSERT (!__rw_signbit (val));
+        return true;
+    }
+
+    return false;
+}
+
+
+inline bool
+__rw_isnan (double val)
+{
+    return 0 != isnan (val);
+}
+
+
+inline bool
+__rw_isqnan (double val)
+{
+    return FP_QNAN == fpclass (val);
+}
+
+
+inline bool
+__rw_issnan (double val)
+{
+    return FP_SNAN == fpclass (val);
+}
+
+
+#elif defined (fpclassify)
+
+
+inline bool
+__rw_isfinite (double val)
+{
+    return !!isfinite (val);
+}
+
+
+inline bool
+__rw_signbit (double val)
+{
+    return !!signbit (val);
+}
+
+
+inline bool
+__rw_isinf (double val)
+{
+    return !!isinf (val);
+}
+
+
+inline bool
+__rw_isnan (double val)
+{
+    return !!isnan (val);
+}
+
+
+inline bool
+__rw_isqnan (double)
+{
+    return false;
+}
+
+
+inline bool
+__rw_issnan (double)
+{
+    return false;
+}
+
+#else
+
+inline bool __rw_isfinite (double) { return true; }
+
+inline bool __rw_signbit (double) { return false; }
+
+inline bool __rw_isinf (double) { return false; }
+
+inline bool __rw_isnan (double) { return false; }
+
+inline bool __rw_isqnan (double) { return false; }
+
+inline bool __rw_issnan (double) { return false; }
+
+#endif
+
+
+inline bool __rw_isfinite (float) { return true; }
+
+inline bool __rw_signbit (float) { return false; }
+
+inline bool __rw_isinf (float) { return false; }
+
+inline bool __rw_isnan (float) { return false; }
+
+inline bool __rw_isqnan (float) { return false; }
+
+inline bool __rw_issnan (float) { return false; }
+
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+#  if _RWSTD_DBL_SIZE == _RWSTD_LDBL_SIZE
+
+inline bool __rw_isfinite (long double x) { return __rw_isfinite (double (x)); }
+
+inline bool __rw_signbit (long double x) { return __rw_signbit (double (x)); }
+
+inline bool __rw_isinf (long double x) { return __rw_isinf (double (x)); }
+
+inline bool __rw_isnan (long double x) { return __rw_isnan (double (x)); }
+
+inline bool __rw_isqnan (long double x) { return __rw_isqnan (double (x)); }
+
+inline bool __rw_issnan (long double x) { return __rw_issnan (double (x)); }
+
+#  else   // _RWSTD_DBL_SIZE != _RWSTD_LDBL_SIZE
+
+inline bool __rw_isfinite (long double) { return true; }
+
+inline bool __rw_signbit (long double) { return false; }
+
+inline bool __rw_isinf (long double) { return false; }
+
+inline bool __rw_isnan (long double) { return false; }
+
+inline bool __rw_isqnan (long double) { return false; }
+
+inline bool __rw_issnan (long double) { return false; }
+
+#  endif   // _RWSTD_DBL_SIZE == _RWSTD_LDBL_SIZE
+
+#endif   // _RWSTD_NO_LONG_DOUBLE
+
+
+#endif   // _RWSTD_FPCLASS_H_INCLUDED
diff --git a/src/limits.cpp b/src/limits.cpp
index 3c72c34..187617f 100644
--- a/src/limits.cpp
+++ b/src/limits.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -31,12 +31,17 @@
 #include <rw/_defs.h>  
                        
 // define generic template and specializations
-#include <limits>
+// use the quoted form of the #include directive to fool Sun C++
+// otherwise the compiler fails to #include the header twice,
+// most likely because it makes assumptions about headers with
+// (C++) standard names
+#include "limits"
 
 #if _MSC_VER != 1300   // working around an MSVC 7.0 bug (PR #26562)
 #  undef _RWSTD_LIMITS_INCLUDED
 #  define _RWSTD_DEFINE_EXPORTS
 
    // define static data members of specializations
-#  include <limits>
+   // again, use the quoted form of the #include directive
+#  include "limits"
 #endif   // MSVC != 7.0
diff --git a/src/messages.cpp b/src/messages.cpp
index ad91a82..e9866f7 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -70,6 +70,14 @@
     } loc;
 };
 
+struct __rw_open_cat_page
+{
+    static const size_t _C_size = 8;
+
+    __rw_open_cat_page* _C_next; // next page
+    __rw_open_cat_data _C_data [_C_size];
+};
+
 
 // manages a global, per-process repository of open catalogs according
 // to the following table:
@@ -90,21 +98,25 @@
 static __rw_open_cat_data*
 __rw_manage_cat_data (int &cat,  __rw_open_cat_data *pcat_data)
 {
-    // a per-process array of catalog data structs
-    static __rw_open_cat_data  catalog_buf [8];
-    static __rw_open_cat_data* catalogs = catalog_buf;
+    // a per-process array of pointers to catalog data structs
+    static __rw_open_cat_data* catalog_buf [__rw_open_cat_page::_C_size];
+    static __rw_open_cat_data** catalogs = 0;
+
+    // first page of a per-process list of pages of catalog data structs
+    static __rw_open_cat_page  catalog_page;
 
     static size_t n_catalogs      = 0;
     static size_t catalog_bufsize = sizeof catalog_buf / sizeof *catalog_buf;
     static size_t largest_cat     = 0;
-    static int    init            = 0;
 
- 
-    if (0 == init) {
+    if (!catalogs) {
+        
         for (size_t i = 0; i < catalog_bufsize; ++i) {
-            catalogs [i].catd = _RWSTD_BAD_CATD;
+            catalog_page._C_data [i].catd = _RWSTD_BAD_CATD;
+            catalog_buf [i] = &catalog_page._C_data [i];
         }
-        init = 1;
+
+        catalogs = catalog_buf;
     }
 
     if (-1 == cat) {
@@ -115,27 +127,40 @@
         if (pcat_data) {
              if (n_catalogs == catalog_bufsize) {
 
-                // reallocate buffer of facet pointers
-                __rw_open_cat_data* const tmp =
-                    new __rw_open_cat_data[n_catalogs * 2];
+                // allocate new page of catalog data
+                __rw_open_cat_page* const page =
+                    new __rw_open_cat_page;
 
-                memcpy (tmp, catalogs, n_catalogs * sizeof *tmp);
+                // insert new page into singly-linked page list
+                page->_C_next = catalog_page._C_next;
+                catalog_page._C_next = page;
+
+                // initialize new page
+                for (size_t i = 0; i < __rw_open_cat_page::_C_size; ++i) {
+                    page->_C_data [i].catd = _RWSTD_BAD_CATD;
+                }
+
+                // rwallocate buffer of catalog data pointers
+                __rw_open_cat_data** const data =
+                    new __rw_open_cat_data* [n_catalogs + __rw_open_cat_page::_C_size];
+
+                memcpy (data, catalogs, n_catalogs * sizeof *data);
                  
                 if (catalogs != catalog_buf)
                     delete[] catalogs;
 
-                catalogs         = tmp;
-                catalog_bufsize *= 2;
+                catalogs         = data;
+                catalog_bufsize += __rw_open_cat_page::_C_size;
 
-                for (size_t i = n_catalogs; i < catalog_bufsize; ++i) {
-                    catalogs [i].catd = _RWSTD_BAD_CATD;
+                for (size_t i = 0; i < __rw_open_cat_page::_C_size; ++i) {
+                    catalogs [n_catalogs + i] = &page->_C_data [i];
                 }
 
                 cat = int (n_catalogs);
-                memcpy (&catalogs [cat].loc, &pcat_data->loc,
-                        sizeof (_STD::locale));
 
-                catalogs [cat].catd = pcat_data->catd;
+                catalogs [cat]->catd = pcat_data->catd;
+                memcpy (&catalogs [cat]->loc, &pcat_data->loc,
+                        sizeof (_STD::locale));
 
                 if (size_t (cat) > largest_cat)
                     largest_cat = size_t (cat);
@@ -145,38 +170,42 @@
             else {
                 // find the first open slot and use it.
                 cat = 0;
-                while (catalogs [cat].catd != _RWSTD_BAD_CATD) {
+                while (catalogs [cat]->catd != _RWSTD_BAD_CATD) {
                     ++cat;
                 }
 
+                catalogs [cat]->catd = pcat_data->catd;
+                memcpy (&catalogs [cat]->loc, &pcat_data->loc,
+                        sizeof (_STD::locale));
+
                 if (size_t (cat) > largest_cat)
                     largest_cat = size_t (cat);
 
-                memcpy (&catalogs [cat].loc, &pcat_data->loc,
-                        sizeof (_STD::locale));
-
-                catalogs [cat].catd = pcat_data->catd;
                 ++n_catalogs;
             }
         }
     }
     else {
+
         if (0 == pcat_data) {
             // find struct and return it
             if (size_t (cat) < catalog_bufsize)
-                return catalogs + cat;
+                return catalogs [cat];
 
             return 0;
         }
 
         // initialize the struct to an invalid state
         --n_catalogs;
-        catalogs [cat].catd = _RWSTD_BAD_CATD;
+        catalogs [cat]->catd = _RWSTD_BAD_CATD;
+
         if (size_t (cat) == largest_cat) {
 
             // find the next smallest valid slot
+            largest_cat = 0;
+
             for (int i = cat; i >= 0; --i) {
-                if (catalogs [i].catd != _RWSTD_BAD_CATD) {
+                if (catalogs [i]->catd != _RWSTD_BAD_CATD) {
                     largest_cat = size_t (i);
                     break;
                 }
@@ -186,11 +215,9 @@
                 sizeof catalog_buf / sizeof *catalog_buf;
 
             if ((largest_cat < bufsize / 2) && (catalogs != catalog_buf)) {
-
                 // when there are no more open catalogs indexed beyond
-                // second half of the statically allocated repository, copy
-                // the open catalogs back into the statically allocated
-                // repository.
+                // second half of the static pointer repository, copy
+                // the open catalog pointers back into the repository.
 
                 catalog_bufsize = bufsize;
 
@@ -198,7 +225,19 @@
                         catalog_bufsize * sizeof (*catalogs));
 
                 delete[] catalogs;
+
                 catalogs = catalog_buf;
+
+                // remove all pages, they're not in use
+                while (catalog_page._C_next)
+                {
+                    // remove next page from page list
+                    __rw_open_cat_page* page = catalog_page._C_next;
+                    catalog_page._C_next = page->_C_next;
+
+                    // deallocate that page
+                    delete page;
+                }
             }
         }
     }
diff --git a/src/mman.cpp b/src/mman.cpp
index eb42e37..5a3a10c 100644
--- a/src/mman.cpp
+++ b/src/mman.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 2001-2006 Rogue Wave Software.
+ * Copyright 2001-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -36,9 +36,9 @@
 
 #include <sys/stat.h>
 
-#ifndef _MSC_VER
+#ifndef _RWSTD_NO_MMAP
 #  include <sys/mman.h>
-#else
+#elif defined (_WIN32)
 #  include <windows.h>
 #  include <io.h>
 #endif   // _MSC_VER
@@ -69,12 +69,17 @@
 
     *size = sb.st_size;
 
-#if !defined(_MSC_VER)
-    const int fd = open (fname, O_RDONLY);
 
+#ifndef _WIN32
+    const int fd = open (fname, O_RDONLY);
+   
     if (-1 == fd)
         return 0;
 
+#endif   // _WIN32
+
+#ifndef _RWSTD_NO_MMAP
+
     // On HPUX systems MAP_SHARED will prevent a second mapping of the same
     // file if the regions are overlapping; one solution is to make the 
     // mapping private.
@@ -92,7 +97,9 @@
 
     if (MAP_FAILED == data)   // failure
         return 0;
-#else
+
+#elif defined (_WIN32)
+
     HANDLE mmf = 
         CreateFile (fname, GENERIC_READ, FILE_SHARE_READ, NULL,
                     OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -114,6 +121,23 @@
     CloseHandle (mmf);
     CloseHandle (mmfv);
 
+#else   // no mmap() or equivalent
+
+#  ifndef _RWSTD_NO_MUNMAP
+#    define _RWSTD_NO_MUNMAP
+#  endif   // _RWSTD_NO_MUNMAP
+
+    // read() takes a size_t argument, convert off_t to it
+    const size_t mapsize = size_t (sb.st_size);
+
+    void* data = operator new (mapsize);
+    const ssize_t nread = read (fd, data, mapsize);
+
+    if (size_t (nread) != mapsize) {
+        operator delete (data);
+        data = 0;
+    }
+
 #endif  // _MSC_VER
 
     return data;
@@ -128,10 +152,12 @@
     void* pv = _RWSTD_CONST_CAST (void*, pcv);
 
     // POSIX munmap() takes a void*, but not all platforms conform
-#ifndef _MSC_VER
+#ifndef _RWSTD_NO_MUNMAP
     munmap (_RWSTD_STATIC_CAST (_RWSTD_MUNMAP_ARG1_T, pv), size);
-#else
+#elif defined (_WIN32)
     UnmapViewOfFile (pv);
+#else   // no munmap()
+    operator delete (pv);
 #endif  // _MSC_VER
 }
 
diff --git a/src/num_put.cpp b/src/num_put.cpp
index a9d9e5e..5d2e7c4 100644
--- a/src/num_put.cpp
+++ b/src/num_put.cpp
@@ -34,15 +34,9 @@
 #include <stdio.h>    // for snprintf()
 #include <string.h>   // for memmove(), memset()
 
-#include <float.h>   // for _finite(), _fpclass(), _isnan(), _copysign()
-#include <math.h>    // for isfinite(), isnan(), isinf(), signbit()
-
-#ifndef _RWSTD_NO_IEEEFP_H
-#  include <ieeefp.h>   // for fpclass(), isnan()
-#endif   // _RWSTD_NO_IEEEFP_H
-
 #include <loc/_num_put.h>
 
+#include "fpclass.h"  // for __rw_isfinite(), ...
 #include "strtol.h"   // for __rw_digit_map
 #include "punct.h"    // for __rw_get_stdio_fmat
 
@@ -80,161 +74,14 @@
     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
 
-#if defined (_MSC_VER)
-
-inline bool __rw_isfinite (double val) { return !!_finite (val); }
-
-inline bool __rw_signbit (double val) { return 0 > _copysign (1., val); }
-
-inline bool __rw_isinf (double val) {
-    const int fpc = _fpclass (val);
-
-    if (_FPCLASS_NINF == fpc) {
-        // verify that __rw_signbit() correctly determines
-        // the sign of negative infinity
-        _RWSTD_ASSERT (__rw_signbit (val));
-        return true;
-    }
-    else if (_FPCLASS_PINF == fpc) {
-        // verify that __rw_signbit() correctly determines
-        // the sign of positive infinity
-        _RWSTD_ASSERT (!__rw_signbit (val));
-        return true;
-    }
-
-    return false;
-}
-
-inline bool __rw_isnan (double val) { return !!_isnan (val); }
-
-inline bool __rw_isqnan (double val) {
-    return _FPCLASS_QNAN == _fpclass (val);
-}
-
-inline bool __rw_issnan (double val) {
-    return _FPCLASS_SNAN == _fpclass (val);
-}
-
-#elif defined (_RWSTD_OS_SUNOS)
-
-inline bool __rw_isfinite (double val) { return !!finite (val); }
-
-inline bool __rw_signbit (double val)
-{
-    // implement own signbit() to avoid dragging in libm or libsunmath
-    return _RWSTD_REINTERPRET_CAST (const _RWSTD_UINT64_T&, val) >> 63;
-}
-
-inline bool __rw_isinf (double val) {
-    const int fpc = fpclass (val);
-
-    if (FP_NINF == fpc) {
-        // verify that __rw_signbit() correctly determines
-        // the sign of negative infinity
-        _RWSTD_ASSERT (__rw_signbit (val));
-        return true;
-    }
-    else if (FP_PINF == fpc) {
-        // verify that __rw_signbit() correctly determines
-        // the sign of positive infinity
-        _RWSTD_ASSERT (!__rw_signbit (val));
-        return true;
-    }
-
-    return false;
-}
-
-inline bool __rw_isnan (double val) { return 0 != isnan (val); }
-
-inline bool __rw_isqnan (double val) { return FP_QNAN == fpclass (val); }
-
-inline bool __rw_issnan (double val) { return FP_SNAN == fpclass (val); }
-
-#elif defined (fpclassify)
-
-inline bool __rw_isfinite (double val) { return !!isfinite (val); }
-
-inline bool __rw_signbit (double val) { return !!signbit (val); }
-
-inline bool __rw_isinf (double val) { return !!isinf (val); }
-
-inline bool __rw_isnan (double val) { return !!isnan (val); }
-
-inline bool __rw_isqnan (double) { return false; }
-
-inline bool __rw_issnan (double) { return false; }
-
-#else
-
-inline bool __rw_isfinite (double) { return true; }
-
-inline bool __rw_signbit (double) { return false; }
-
-inline bool __rw_isinf (double) { return false; }
-
-inline bool __rw_isnan (double) { return false; }
-
-inline bool __rw_isqnan (double) { return false; }
-
-inline bool __rw_issnan (double) { return false; }
-
-#endif
-
-
-inline bool __rw_isfinite (float) { return true; }
-
-inline bool __rw_signbit (float) { return false; }
-
-inline bool __rw_isinf (float) { return false; }
-
-inline bool __rw_isnan (float) { return false; }
-
-inline bool __rw_isqnan (float) { return false; }
-
-inline bool __rw_issnan (float) { return false; }
-
-
-#ifndef _RWSTD_NO_LONG_DOUBLE
-
-#  if _RWSTD_DBL_SIZE == _RWSTD_LDBL_SIZE
-
-inline bool __rw_isfinite (long double x) { return __rw_isfinite (double (x)); }
-
-inline bool __rw_signbit (long double x) { return __rw_signbit (double (x)); }
-
-inline bool __rw_isinf (long double x) { return __rw_isinf (double (x)); }
-
-inline bool __rw_isnan (long double x) { return __rw_isnan (double (x)); }
-
-inline bool __rw_isqnan (long double x) { return __rw_isqnan (double (x)); }
-
-inline bool __rw_issnan (long double x) { return __rw_issnan (double (x)); }
-
-#  else   // _RWSTD_DBL_SIZE != _RWSTD_LDBL_SIZE
-
-inline bool __rw_isfinite (long double) { return true; }
-
-inline bool __rw_signbit (long double) { return false; }
-
-inline bool __rw_isinf (long double) { return false; }
-
-inline bool __rw_isnan (long double) { return false; }
-
-inline bool __rw_isqnan (long double) { return false; }
-
-inline bool __rw_issnan (long double) { return false; }
-
-#  endif   // _RWSTD_DBL_SIZE == _RWSTD_LDBL_SIZE
-
-#endif   // _RWSTD_NO_LONG_DOUBLE
-
-
 static int
 __rw_fmat_infinite (char *buf, size_t bufsize, double val, unsigned flags)
 {
     _RWSTD_ASSERT (!__rw_isfinite (val));
     _RWSTD_ASSERT (5 <= bufsize);
 
+    _RWSTD_UNUSED (bufsize); 
+
     char* end = buf;
     const bool cap = !!(flags & _RWSTD_IOS_UPPERCASE);
 
diff --git a/src/ti_num_get.cpp b/src/ti_num_get.cpp
index 2105dae..50b114f 100644
--- a/src/ti_num_get.cpp
+++ b/src/ti_num_get.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -47,6 +47,16 @@
 
 #define TARGS_C   <char, _RWSTD_ISTREAMBUF_ITER (char) >
 
+
+#if 6 == _RWSTD_HP_aCC_MAJOR
+   // silence the useless HP aCC 6 remark 4244: extern storage class
+   // used with a function definition on the "extern _RWSTD_EXPORT"
+   // macro argument below where the redundant "extern" is there to
+   // silence HP aCC 3 Warning (suggestion) 933: Null macro argument #1
+#  pragma diag_suppress 4244
+#endif   // aCC 6
+
+
 _RWSTD_SPECIALIZE_FACET_ID (num_get, TARGS_C);
 _RWSTD_DEFINE_FACET_FACTORY (extern _RWSTD_EXPORT, num_get, TARGS_C, num_get);
 _RWSTD_SPECIALIZE_USE_FACET (num_get);
diff --git a/src/ti_num_put.cpp b/src/ti_num_put.cpp
index 53bf9fe..40c477c 100644
--- a/src/ti_num_put.cpp
+++ b/src/ti_num_put.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -45,6 +45,16 @@
 
 #define TARGS_C   <char, _RWSTD_OSTREAMBUF_ITER (char) >
 
+
+#if 6 == _RWSTD_HP_aCC_MAJOR
+   // silence the useless HP aCC 6 remark 4244: extern storage class
+   // used with a function definition on the "extern _RWSTD_EXPORT"
+   // macro argument below where the redundant "extern" is there to
+   // silence HP aCC 3 Warning (suggestion) 933: Null macro argument #1
+#  pragma diag_suppress 4244
+#endif   // aCC 6
+
+
 _RWSTD_SPECIALIZE_FACET_ID (num_put, TARGS_C);
 _RWSTD_DEFINE_FACET_FACTORY (extern _RWSTD_EXPORT, num_put, TARGS_C, num_put);
 _RWSTD_SPECIALIZE_USE_FACET (num_put);
diff --git a/src/ti_numpunct.cpp b/src/ti_numpunct.cpp
index 85ce67c..3240f10 100644
--- a/src/ti_numpunct.cpp
+++ b/src/ti_numpunct.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -45,6 +45,15 @@
 #include "use_facet.h"
 
 
+#if 6 == _RWSTD_HP_aCC_MAJOR
+   // silence the useless HP aCC 6 remark 4244: extern storage class
+   // used with a function definition on the "extern _RWSTD_EXPORT"
+   // macro argument below where the redundant "extern" is there to
+   // silence HP aCC 3 Warning (suggestion) 933: Null macro argument #1
+#  pragma diag_suppress 4244
+#endif   // aCC 6
+
+
 _RWSTD_SPECIALIZE_FACET_ID (numpunct, <char>);
 _RWSTD_DEFINE_FACET_FACTORY (extern _RWSTD_EXPORT, numpunct, <char>, numpunct);
 _RWSTD_SPECIALIZE_USE_FACET (numpunct);
diff --git a/src/version.cpp b/src/version.cpp
index 7127093..d2b14b0 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -35,6 +35,7 @@
 #ifdef _RWSTD_VER_STR
 
 extern const char __rw_ident[] = {
+    // %Z% keyword ("@(#)") retrieved by the POSIX what utility
     "@(#) Apache C++ Standard Library version " _RWSTD_VER_STR
 };
 
diff --git a/tests/include/rw_thread.h b/tests/include/rw_thread.h
index 621a7d6..9a19a80 100644
--- a/tests/include/rw_thread.h
+++ b/tests/include/rw_thread.h
@@ -33,6 +33,8 @@
 
 
 extern "C" {
+    typedef void* rw_thread_proc (void*);
+}    // extern "C"
 
 struct rw_thread_attr_t;
 
@@ -48,7 +50,7 @@
 _TEST_EXPORT int
 rw_thread_create (rw_thread_t*,
                   rw_thread_attr_t*,
-                  void* (*)(void*),
+                  rw_thread_proc*,
                   void*);
 
 
@@ -62,6 +64,13 @@
 // array with their id's; if (tidarray == 0), waits for all
 // threads to join and fills the aragarray with the result
 // returned from each thread
+// if (timeout != 0), then a timer will be started, and the function
+// rw_thread_pool_timeout_expired() will return true after that number
+// of seconds has passed. there is only one timer, so use timeouts
+// with caution. if you provide tidarray, you should join threads
+// before starting another pool, otherwise threads from the first
+// pool may not exit until the threads from a later second pool are
+// signalled to stop.
 // if (nthreads == SIZE_MAX), sets nthreads to the positive result
 // of rw_get_processors() plus 1, or to 2 otherwise
 // returns 0 on success, or a non-zero value indicating the thread
@@ -70,15 +79,20 @@
 rw_thread_pool (rw_thread_t*      /* tidarray */,
                 _RWSTD_SIZE_T     /* nthreads */,
                 rw_thread_attr_t* /* attr */,
-                void* (*)(void*)  /* thr_proc */,
-                void**            /* argarray */);
+                rw_thread_proc*   /* thr_proc */,
+                void**            /* argarray */,
+                _RWSTD_SIZE_T     /* timeout  */ = 0);
+
+// returns non-zero if the thread timeout flag has been set. should
+// be polled periodically by threads created by rw_thread_pool() so
+// that they know that the soft timeout has expired
+// see notes above for details
+_TEST_EXPORT int
+rw_thread_pool_timeout_expired ();
 
 // returns the number of logical processors/cores on the system,
 // or -1 on error
 _TEST_EXPORT int
 rw_get_cpus ();
 
-
-}   // extern "C"
-
 #endif   // RW_RWTHREAD_H_INCLUDED
diff --git a/tests/iostream/27.filebuf.cpp b/tests/iostream/27.filebuf.cpp
new file mode 100644
index 0000000..9765487
--- /dev/null
+++ b/tests/iostream/27.filebuf.cpp
@@ -0,0 +1,2804 @@
+/***************************************************************************
+ *
+ * 27.filebuf.cpp - test exercising class template basic_filebuf
+ *
+ * $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.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ *
+ **************************************************************************/
+
+#include <cerrno>    // for errno
+#include <csignal>   // for signal()
+#include <cstdio>    // for FILE, fopen(), remove()
+#include <cstring>   // for memcmp()
+#include <cwchar>    // for mbstate_t
+
+#include <fstream>
+
+#if !defined (_WIN32) && !defined (_WIN64)
+
+#  ifdef __SUNPRO_CC
+     // working around a SunOS/SunPro bug (PR #26255)
+#    undef _TIME_T
+#  endif
+
+#  include <cstdlib>      // for exit()
+#  include <fcntl.h>      // for open(), O_XXX constants
+#  include <unistd.h>     // for fork()
+#  include <sys/stat.h>   // for mkfifo()
+#  include <sys/types.h>  // for pid_t
+#  include <sys/wait.h>   // for wait()
+#else
+#  include <fcntl.h>      // for O_XXX constants
+#  include <io.h>         // for open()
+#endif   // _WIN{32,64}
+
+#ifndef SIGPIPE
+#  define SIGPIPE   13   /* HP-UX, Linux, and SunOS value */
+#endif   // SIGPIPE
+
+#include <driver.h>
+#include <file.h>
+#include <valcmp.h>
+
+
+#define REMOVE_FILE(tmpfname) \
+    rw_warn (0 == std::remove (tmpfname), __FILE__, __LINE__, \
+             "std::remove(\"%s\") failed: %m", tmpfname)
+
+/**************************************************************************/
+
+
+template <class charT>
+static void
+test_ctors (const char* tname)
+{
+    typedef std::basic_filebuf<charT, std::char_traits<charT> > Filebuf;
+
+    int fdcount [2];
+    int next_fd [2];
+
+    //////////////////////////////////////////////////////////////////
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::basic_filebuf()", tname);
+
+    next_fd [0] = rw_nextfd (fdcount + 0);
+
+    {
+        Filebuf fb;
+
+        // verify the postcondition in 27.8.1.2, p2
+        rw_assert (!fb.is_open (), __FILE__, __LINE__,
+                   "basic_filebuf<%s>::basic_filebuf().is_open() == "
+                   "false, got true", tname);
+
+        // verify that no file descriptor has been allocated
+        next_fd [1] = rw_nextfd (fdcount + 1);
+
+        rw_assert (next_fd [0] == next_fd [1] && fdcount [0] == fdcount [1],
+                   __FILE__, __LINE__,
+                   "%d file descriptor leak(s) detected after construction",
+                   fdcount [1] - fdcount [0]);
+    }
+
+    // verify that no file descriptor has been closed
+    next_fd [1] = rw_nextfd (fdcount + 1);
+
+    //////////////////////////////////////////////////////////////////
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::~basic_filebuf()", tname);
+
+    rw_assert (next_fd [0] == next_fd [1] && fdcount [0] == fdcount [1],
+               __FILE__, __LINE__,
+               "%d file descriptor leak(s) detected after destruction",
+               fdcount [1] - fdcount [0]);
+
+
+    const char* const tmpfname = rw_tmpnam (0);
+    if (!tmpfname) {
+        return;
+    }
+
+    {
+        Filebuf fb;
+
+        next_fd [0] = rw_nextfd (fdcount + 0);
+
+        Filebuf *tmp = fb.open (tmpfname, std::ios::out);
+
+        // verify that open() succeeds and allocates a file descriptor
+        rw_assert (0 != tmp, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::open(\"%s\", std::ios_base::out) "
+                   "failed", tname, tmpfname);
+
+        next_fd [1] = rw_nextfd (fdcount + 1);
+
+        rw_assert (next_fd [0] != next_fd [1]
+                   && fdcount [0] + 1 == fdcount [1], __FILE__, __LINE__,
+                   "%d file descriptor mismatch detected after open()",
+                   fdcount [1] - fdcount [0]);
+    }
+
+    // verify that dtor closes the file descriptor
+    next_fd [1] = rw_nextfd (fdcount + 1);
+
+    rw_assert (next_fd [0] == next_fd [1] && fdcount [0] == fdcount [1],
+               __FILE__, __LINE__,
+               "%d file descriptor leak(s) detected after destruction",
+               fdcount [1] - fdcount [0]);
+
+
+#ifndef _RWSTD_NO_EXT_FILEBUF
+
+    //////////////////////////////////////////////////////////////////
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::basic_filebuf(FILE*) "
+             "[extension]", tname);
+
+#  ifdef stdin
+
+    {
+        std::FILE* const fp = std::fopen (tmpfname, "w");
+
+        next_fd [0] = rw_nextfd (fdcount + 0);
+
+        // object takes over the ownership of the file pointer
+        Filebuf fb (fp);
+
+        rw_assert (fb.is_open (), __FILE__, __LINE__,
+                   "basic_filebuf<%s>::basic_filebuf (FILE*).is_open() "
+                   "== true, got false", tname);
+
+        next_fd [1] = rw_nextfd (fdcount + 1);
+
+        rw_assert (next_fd [0] == next_fd [1] && fdcount [0] == fdcount [1],
+                   __FILE__, __LINE__,
+                   "%d file descriptor mismatch detected after open()",
+                   fdcount [1] - fdcount [0]);
+    }
+
+    // verify that dtor closes the file descriptor
+    next_fd [1] = rw_nextfd (fdcount + 1);
+
+    rw_assert (fdcount [0] == fdcount [1] + 1, __FILE__, __LINE__,
+               "%d file descriptor leak(s) detected after destruction",
+               fdcount [1] - fdcount [0]);
+
+#  else   // if !defined (stdin)
+
+    rw_assert (false, __FILE__, __LINE__,
+               "macro stdin unexpectedly not #defined, "
+               "basic_filebuf<%s>::basic_filebuf (FILE*) "
+               "extension not tested", tname);
+
+#  endif   // stdin
+
+    //////////////////////////////////////////////////////////////////
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::basic_filebuf(int) "
+             "[extension]", tname);
+
+    Filebuf *pfb = 0;
+
+    {
+        std::FILE* const fp = std::fopen (tmpfname, "w");
+
+        // object takes over the ownership of the file pointer
+        pfb = new Filebuf (fp);
+
+        next_fd [0] = rw_nextfd (fdcount + 0);
+
+        // object takes over the ownership of the file descriptor
+        Filebuf fb (pfb->fd ());
+
+        next_fd [1] = rw_nextfd (fdcount + 1);
+
+        rw_assert (fb.is_open (), __FILE__, __LINE__,
+                   "basic_filebuf<%s>::basic_filebuf (int).is_open() "
+                   "== true, got false", tname);
+
+        rw_assert (next_fd [0] == next_fd [1] && fdcount [0] == fdcount [1],
+                   __FILE__, __LINE__,
+                   "%d file descriptor mismatch detected after open()",
+                   fdcount [1] - fdcount [0]);
+    }
+
+    // verify that dtor closes the file descriptor
+    next_fd [1] = rw_nextfd (fdcount + 1);
+
+    rw_assert (fdcount [0] == fdcount [1] + 1, __FILE__, __LINE__,
+               "%d file descriptor leak(s) detected after destruction",
+               fdcount [1] - fdcount [0]);
+
+    delete pfb;
+
+#endif   // _RWSTD_NO_EXT_FILEBUF
+
+    REMOVE_FILE (tmpfname);
+}
+
+/***************************************************************************/
+
+extern "C" {
+
+// instead of calling signal(SIGPIPE, SIG_IGN)
+void ignore_signal (int)
+{
+    std::signal (SIGPIPE, ignore_signal);
+}
+
+}   // extern "C"
+
+
+template <class charT>
+static void
+test_open (const char* tname)
+{
+    typedef std::basic_filebuf<charT, std::char_traits<charT> > Filebuf;
+
+    const char* const tmpfname = rw_tmpnam (0);
+
+    if (!tmpfname) {
+        return;
+    }
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::is_open ()", tname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::open (const char*, "
+             "ios_base::openmode)", tname);
+
+    /*****************************************************************
+
+    Table 92
+
+    +-----+-----+-----+-----+-----+-----+
+    | bin | in  | out |trunc| app |stdio|
+    +=====+=====+=====+=====+=====+=====+
+    |     |     |  +  |     |     | "w" |
+    +-----+-----+-----+-----+-----+-----+
+    |     |     |  +  |     |  +  | "a" |
+    +-----+-----+-----+-----+-----+-----+
+    |     |     |  +  |  +  |     | "w" |
+    +-----+-----+-----+-----+-----+-----+
+    |     |  +  |     |     |     | "r" |
+    +-----+-----+-----+-----+-----+-----+
+    |     |  +  |  +  |     |     |"r+" |
+    +-----+-----+-----+-----+-----+-----+
+    |     |  +  |  +  |  +  |     |"w+" |
+    +=====+=====+=====+=====+=====+=====+
+    |  +  |     |  +  |     |     |"wb" |
+    +-----+-----+-----+-----+-----+-----+
+    |  +  |     |  +  |     |  +  |"ab" |
+    +-----+-----+-----+-----+-----+-----+
+    |  +  |     |  +  |  +  |     |"wb" |
+    +-----+-----+-----+-----+-----+-----+
+    |  +  |  +  |     |     |     |"rb" |
+    +-----+-----+-----+-----+-----+-----+
+    |  +  |  +  |  +  |     |     |"r+b"|
+    +-----+-----+-----+-----+-----+-----+
+    |  +  |  +  |  +  |  +  |     |"w+b"|
+    +-----+-----+-----+-----+-----+-----+
+
+    r          open text file for reading
+    w          truncate to zero length or create text file for writing
+    a          append; open or create text file for writing at EOF
+    rb         open binary file for reading
+    wb         truncate to zero length or create binary file for writing
+    ab         append; open or create binary file for writing at EOF
+    r+         open text file for update (reading and writing)
+    w+         truncate to zero length or create text file for update
+    a+         append; open or create text file for update at EOF
+    r+b or rb+ open binary file for update (reading and writing)
+    w+b or wb+ truncate to zero length or create binary file for update
+    a+b or ab+ append; open or create binary file for update at EOF
+
+    ******************************************************************/
+
+#define BEGIN_MODE(openmode, ext)                                \
+    mode = (openmode),                                           \
+    rw_info (0, __FILE__, __LINE__, "%{Io} %s", mode, ext)
+
+#define ASSERT_OPEN(expr, mode, txt)                             \
+    rw_assert (expr, __FILE__, __LINE__,                         \
+               "basic_filebuf<%s>::open (\"%s\", %{Io}) %s ",    \
+               tname, tmpfname, mode, txt)                       \
+
+    std::ios_base::openmode mode;
+
+    const std::ios::openmode iomodes[] = {
+        std::ios::openmode ()
+
+#ifndef _RWSTD_NO_EXT_STDIO
+
+        , std::ios::stdio
+
+#endif   // _RWSTD_NO_EXT_STDIO
+
+    };
+
+    const std::size_t niomodes = sizeof iomodes / sizeof *iomodes;
+
+    const char* buf  = 0;
+    std::size_t size = 0;
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::out | iomodes [minx], "");
+
+        {
+            Filebuf ().open (tmpfname, mode);
+        }
+
+        buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+        ASSERT_OPEN (0 != buf, mode, "failed to create a new file");
+
+        if (buf)
+            ASSERT_OPEN (!size, mode,
+                         "unexpectedly created a non-empty file");
+
+        rw_fwrite (tmpfname, "foobar");
+
+        {
+            Filebuf ().open (tmpfname, mode);
+        }
+
+        buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+        ASSERT_OPEN (0 != buf, mode, "failed to open an existing file");
+
+        if (buf)
+            ASSERT_OPEN (!size, mode,
+                         "unexpectedly created a non-empty file");
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out | ios::app)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::out | std::ios::app | iomodes [minx], "");
+
+        REMOVE_FILE (tmpfname);
+
+        {
+            Filebuf ().open (tmpfname, mode);
+        }
+
+        buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+        ASSERT_OPEN (0 != buf, mode, "failed to create a new file");
+
+        if (buf)
+            ASSERT_OPEN (!size, mode, "unexpectedly created a non-empty file");
+
+        rw_fwrite (tmpfname, "foobar");
+
+        {
+            Filebuf ().open (tmpfname, mode);
+        }
+
+        buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+        ASSERT_OPEN (0 != buf, mode, "failed to open an existing file");
+
+        if (buf)
+            ASSERT_OPEN (6 == size, mode,
+                         "unexpectedly truncated a non-empty file");
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out | ios::trunc)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::out | std::ios::trunc | iomodes [minx], "");
+
+        rw_fwrite (tmpfname, "foobar");
+
+        {
+            // open a file for writing and truncate it to 0 size
+            Filebuf ().open (tmpfname, mode);
+        }
+
+        // read the contents of the file and verify that they are empty
+        buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+        // file must exist
+        ASSERT_OPEN (0 != buf, mode, "failed to open an existing file");
+
+        // the size of the file must be 0
+        if (buf)
+            ASSERT_OPEN (!size, mode, "failed to truncate a non-empty file");
+    }
+
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::nocreate)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        // ios::nocreate is meaningless by itself
+        BEGIN_MODE (std::ios::nocreate | iomodes [minx], "[extension]");
+
+        Filebuf fb;
+
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "unexpectedly succeeded to open a non-existent file");
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out | ios::nocreate)
+
+    BEGIN_MODE (std::ios::out | std::ios::nocreate, "[extension]");
+
+    // ios::nocreate will prevent the call to open from creating
+    // the file if it doesn't exist
+
+    REMOVE_FILE (tmpfname);
+
+    {
+        Filebuf fb;
+
+        // try to open a file that doesn't exist for output but prevent
+        // the call from creating it by setting the nocreate bit
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "unexpectedly succeeded to open a non-existent file");
+    }
+
+    buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+    ASSERT_OPEN (0 == buf, mode, "unexpectedly created a file");
+
+    // the same as above but with an existing file
+    rw_fwrite (tmpfname, "foobar");
+
+    {
+        Filebuf fb;
+
+        // try to open an existing file
+        fb.open (tmpfname, mode);
+
+        // verify that the call succeeded
+        ASSERT_OPEN (fb.is_open (), mode,
+                     "unexpectedly succeeded to open an existing file");
+    }
+
+    buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+    ASSERT_OPEN (0 != buf, mode, "failed to open an existing file");
+
+#ifndef _RWSTD_NO_EXT_STDIO
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::stdio| ios::out | ios::nocreate)
+
+    BEGIN_MODE (std::ios::stdio | std::ios::out | std::ios::nocreate,
+                "[extension]");
+
+    REMOVE_FILE (tmpfname);
+
+    // ios::nocreate can't be implemented with ios::stdio
+    // and the call must fail
+    {
+        Filebuf fb;
+
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "unexpectedly succeeded to open a non-existent file");
+    }
+
+    // verify that the file wasn't created
+    buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+    ASSERT_OPEN (0 == buf, mode, "unexpectedly created a file");
+
+#endif   // _RWSTD_NO_EXT_STDIO
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out | ios::nocreate | ios::trunc)
+
+    // ios::trunc has no effect on ios::nocreate
+    BEGIN_MODE (std::ios::out | std::ios::nocreate | std::ios::trunc,
+                "[extension]");
+
+    // remove file in case it was unexpectedly created above
+    std::remove (tmpfname);
+
+    {
+        Filebuf fb;
+
+        // try to open a file that doesn't exist for output but prevent
+        // the call from creating it by setting the nocreate bit
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "unexpectedly succeeded to open a non-existent file");
+    }
+
+    buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+    ASSERT_OPEN (0 == buf, mode, "unexpectedly created a file");
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::noreplace)
+
+    // remove file in case it was unexpectedly created above
+    std::remove (tmpfname);
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        // ios::noreplace is meaningless by itself
+        BEGIN_MODE (std::ios::noreplace | iomodes [minx], "[extension]");
+
+        Filebuf fb;
+
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "unexpectedly succeeded to open a non-existent file");
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out | ios::noreplace)
+
+    // ios::noreplace will cause the call to open to succeed only
+    // if the file doesn't exist, otherwise the call will fail
+    BEGIN_MODE (std::ios::out | std::ios::noreplace, "[extension]");
+
+    rw_fwrite (tmpfname, "foobar");
+
+    {
+        Filebuf fb;
+
+        // try to open an existing file for output but prevent
+        // the call from replacing it by setting the noreplace bit
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "unexpectedly succeeded to open an existing file");
+    }
+
+    buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+    ASSERT_OPEN (0 != buf, mode, "unexpectedly removed an existing file");
+
+    if (buf)
+        ASSERT_OPEN (0 != size, mode, "unexpectdly truncated a non-empty file");
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::out | ios::trunc | ios::noreplace)
+
+    BEGIN_MODE (std::ios::out | std::ios::trunc | std::ios::noreplace,
+                "[extension]");
+
+    rw_fwrite (tmpfname, "foobar");
+
+    {
+        Filebuf fb;
+
+        // try to open an existing file for output
+        fb.open (tmpfname, mode);
+
+        // verify that the call failed
+        ASSERT_OPEN (!fb.is_open (), mode,
+                     "failed to open an existing file");
+    }
+
+    buf = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size));
+
+    ASSERT_OPEN (0 != buf, mode, "unexpectedly removed an existing file");
+
+    if (buf)
+        ASSERT_OPEN (0 != size, mode, "failed to truncate a non-empty file");
+
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::in)
+
+    charT readbuf [256];
+    const std::size_t readbuf_size = sizeof readbuf / sizeof *readbuf;
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::in | iomodes [minx], "");
+
+        rw_fwrite (tmpfname, "foobar");
+
+        Filebuf fb;
+
+        const charT foobar[] = { 'f', 'o', 'o', 'b', 'a', 'r' };
+
+        if (fb.open (tmpfname, mode)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            std::memset (readbuf, 0, sizeof readbuf);
+            fb.sgetn (readbuf, readbuf_size);
+
+            ASSERT_OPEN (!std::memcmp (readbuf, foobar, sizeof foobar),
+                         mode, "failed to open an existing file for reading");
+        }
+        else {
+            ASSERT_OPEN (0, mode, "failed to open an existing file");
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::in | ios::out)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::in | std::ios::out | iomodes [minx], "");
+
+        rw_fwrite (tmpfname, "foobar");
+
+        Filebuf fb;
+
+        if (fb.open (tmpfname, mode)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            const charT FOO[] = { 'F', 'O', 'O' };
+            const charT bar[] = { 'b', 'a', 'r' };
+
+            if (3 != fb.sputn (FOO, sizeof FOO / sizeof *FOO))
+                ASSERT_OPEN (false, mode,
+                             "failed to open an existing file for writing "
+                             "(sputn() failed)");
+
+            // an input operation must be separated from a
+            // preceding output operation by a seek() or flush()
+            fb.pubsync ();
+
+            std::memset (readbuf, 0, sizeof readbuf);
+            const std::streamsize got = fb.sgetn (readbuf, readbuf_size);
+
+            if (3 == got) {
+                rw_assert (!std::memcmp (readbuf, bar, sizeof bar),
+                           __FILE__, __LINE__,
+                           "sgetn() retrieved the wrong data)");
+            }
+            else
+                rw_assert (false, __FILE__, __LINE__,
+                           "sgetn() == 3, got %td: %{*.*Ac}, "
+                           "expected %{*.*Ac}",
+                           got, int (sizeof (charT)), got, readbuf,
+                           int (sizeof (charT)),
+                           int (sizeof bar / sizeof *bar), bar);
+        }
+        else {
+            ASSERT_OPEN (0, mode, "failed to open an existing file");
+        }
+    }
+
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::in | ios::out | ios::trunc)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (  std::ios::in | std::ios::out | std::ios::trunc
+                    | iomodes [minx], "");
+
+        rw_fwrite (tmpfname, "foobar");
+
+        Filebuf fb;
+
+        if (fb.open (tmpfname, mode)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            const charT FOO[] = { 'F', 'O', 'O' };
+
+            std::memset (readbuf, 0, sizeof readbuf);
+            if (0 != fb.sgetn (readbuf, readbuf_size))
+                ASSERT_OPEN (false, mode,
+                             "failed to truncate a non-empty file");
+
+            if (3 != fb.sputn (FOO, sizeof FOO / sizeof *FOO))
+                ASSERT_OPEN (false, mode,
+                             "failed to open an existing file for writing "
+                             "(sputn() failed)");
+
+            // an input operation must be separated from a
+            // preceding output operation by a seek() or flush()
+            fb.pubseekoff (0, std::ios::beg);
+
+            std::memset (readbuf, 0, sizeof readbuf);
+            if (3 != fb.sgetn (readbuf, readbuf_size))
+                ASSERT_OPEN (false, mode,
+                             "failed to open an existing file for reading "
+                             "(sgetn() failed after a sputn())");
+
+            ASSERT_OPEN (!std::memcmp (readbuf, FOO, sizeof FOO), mode,
+                         "failed to open an existing file for reading "
+                         "and writing (sgetn() retrieved the wrong data)");
+        }
+        else {
+            ASSERT_OPEN (0, mode, "failed to open an existing file");
+        }
+    }
+
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::binary | ios::in)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::binary | std::ios::in | iomodes [minx], "");
+
+        // create a file containing various combinations of new-line
+        // and line-feed and read the file in using the ios::binary
+        // flag, expecting the original contents of the file on
+        // output (i.e., no CR/LF conversion on Win32)
+        const char bindata[] = "\nf\ro\n\ro\r\n\b\n\ra\r\rr";
+
+        // rw_fwrite() returns the number of bytes successfully written
+        size = rw_fwrite (tmpfname, bindata, sizeof bindata - 1, "wb");
+
+        Filebuf fb;
+
+        if (fb.open (tmpfname, mode)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            std::memset (readbuf, 0, sizeof readbuf);
+            const std::streamsize N = fb.sgetn (readbuf, readbuf_size);
+
+            if (N != std::streamsize (size))
+                rw_assert (false, __FILE__, __LINE__,
+                           "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                           "got %d", tname, readbuf,
+                           readbuf_size, size, N);
+
+            for (std::streamsize i = 0; i != N; ++i) {
+
+                if (char (readbuf [i]) != bindata [i]) {
+
+                    rw_assert (false, __FILE__, __LINE__,
+                               "basic_filebuf<%s>::sgetn() data "
+                               "mismatch: got \"%s\", expected \"%s\"",
+                               tname, readbuf, bindata);
+                    break;
+                }
+            }
+        }
+        else {
+            ASSERT_OPEN (0, mode, "failed to open an existing file");
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::binary | ios::out)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::binary | std::ios::out | iomodes [minx], "");
+
+        Filebuf fb;
+
+        if (fb.open (tmpfname, mode)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            const charT XYZ[] = {
+                '\n', 'X', '\r', 'Y', '\n', '\r', 'Z', '\r', '\n', '\0'
+            };
+
+            const std::streamsize N = sizeof XYZ / sizeof *XYZ - 1;
+
+            if (N != fb.sputn (XYZ, N))
+                ASSERT_OPEN (false, mode,
+                             "failed to open an existing file for writing "
+                             "(sputn() failed)");
+
+            fb.close ();
+
+            size = 0;
+            buf  = _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &size, "rb"));
+
+            rw_assert (std::size_t (N) == size, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sputn() wrote %d bytes, "
+                       "%d expected",
+                       tname, size, N * sizeof (charT));
+
+            for (std::streamsize i = 0; i != N; ++i) {
+
+                if (buf [i] != char (XYZ [i])) {
+
+                    rw_assert (false, __FILE__, __LINE__,
+                               "basic_filebuf<%s>::sputn() data "
+                               "mismatch: wrote \"%s\", expected \"%s\"",
+                               tname, buf, XYZ);
+                    break;
+                }
+            }
+        }
+        else {
+            ASSERT_OPEN (0, mode, "failed to open an existing file");
+        }
+    }
+
+    REMOVE_FILE (tmpfname);
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open ((const char*)0, ios::in)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::in | iomodes [minx],
+                    ", file name = 0 [extension]");
+
+        // verify that open() succeeds when the first argument
+        // is the null pointer (the call creates a temporary
+        // file and opens it for reading -- such a file may not
+        // be very useful but since it's harmless there's no
+        // reason it shouldn't be possible)
+
+        Filebuf fb;
+        fb.open ((const char*)0, mode);
+
+        rw_assert (fb.is_open (), __FILE__, __LINE__,
+                   "basic_filebuf<%s>::is_open()", tname);
+
+        // FIXME: verify that the call to close removes the file
+        fb.close ();
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open ((const char*)0, ios::out)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::out | iomodes [minx],
+                    ", file name = 0 [extension]");
+
+        // verify that open() succeeds when the first argument
+        // is the null pointer (the call creates a temporary
+        // file and opens it for writing)
+
+        Filebuf fb;
+        fb.open ((const char*)0, mode);
+
+        rw_assert (fb.is_open (), __FILE__, __LINE__,
+                   "basic_filebuf<%s>::is_open()", tname);
+
+        // FIXME: verify that the call to close removes the file
+        fb.close ();
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open ((const char*)0, ios::in | ios::out)
+
+    for (std::size_t minx = 0; minx != niomodes; ++minx) {
+
+        BEGIN_MODE (std::ios::in | std::ios::out | iomodes [minx],
+                    ", file name = 0 [extension]");
+
+        Filebuf fb;
+        fb.open ((const char*)0, mode);
+
+        rw_assert (fb.is_open (), __FILE__, __LINE__,
+                   "basic_filebuf<%s>::is_open()", tname);
+
+        // FIXME: verify that the call to close removes the file
+        fb.close ();
+    }
+
+
+#if !defined (_WIN32) && !defined (_WIN64)
+
+    //////////////////////////////////////////////////////////////////
+    // exercise open (..., ios::ate)
+
+    BEGIN_MODE (std::ios::ate | std::ios::out, "");
+
+    std::signal (SIGPIPE, ignore_signal);
+
+    if (mkfifo (tmpfname, S_IRWXU))
+        rw_assert (false, __FILE__, __LINE__,
+                   "mkfifo (\"%s\", S_IRWXU) failed", tmpfname);
+    else {
+
+        const pid_t childpid = fork ();
+
+        if (childpid > 0) {   // parent process
+
+            Filebuf fb;
+
+            const Filebuf* const fbp = fb.open (tmpfname, mode);
+
+            // verify that open(ate) fails for an existing but unseekable file
+            if (fbp) {
+                rw_assert (false, __FILE__, __LINE__,
+                           "basic_filebuf<%s>::open(\"%s\", ios::ate | "
+                           "ios::out) == 0 after a failed seek to end",
+                           tname, tmpfname);
+            }
+
+            // verify that is_open() returns false after a failed open
+            if (fb.is_open ()) {
+                rw_assert (false, __FILE__, __LINE__,
+                           "basic_filebuf<%s>::is_open() == false"
+                           " after a failed call to open", tname);
+            }
+
+            // reap our child's exit status
+            wait (0);
+        }
+        else if (0 == childpid) {   // child process
+
+            Filebuf fb;
+
+            if (fb.open (tmpfname, std::ios::in))
+                fb.sgetc ();
+            else
+                rw_assert (false, __FILE__, __LINE__,
+                           "basic_filebuf<%s>::open(\"%s\", "
+                           "ios::in) failed in child process",
+                           tname, tmpfname);
+
+            std::exit (0);
+        }
+        else
+            rw_assert (false, __FILE__, __LINE__, "fork() failed");
+
+        REMOVE_FILE (tmpfname);
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise close ()
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::close ()", tname);
+
+    std::signal (SIGPIPE, ignore_signal);
+
+    if (mkfifo (tmpfname, S_IRWXU))
+        rw_assert (false, __FILE__, __LINE__,
+                   "mkfifo (\"%s\", S_IRWXU) failed", tmpfname);
+    else {
+
+        // verify that close() returns 0 on failure by opening and
+        // writing into a pipe in the parent process that the child
+        // prematurely closes
+
+        const pid_t childpid = fork ();
+
+        if (childpid > 0) {   // parent process
+
+            Filebuf fb;
+
+            if (fb.open (tmpfname, std::ios::out)) {
+
+                // write into the file buffer
+                fb.sputc (charT ());
+
+                // wait for child to open and close the pipe
+                wait (0);
+
+                // close() will try to flush the contents of the buffer
+                // into the pipe which should fail, since the other end
+                // of the pipe has already been closed
+                if (fb.close ())
+                    rw_assert (false, __FILE__, __LINE__,
+                               "basic_filebuf<%s>::close() unexpectedly "
+                               "suceeded", tname);
+            }
+            else
+                rw_assert (false, __FILE__, __LINE__,
+                           "basic_filebuf<%s>::open (\"%s\", ios::out) "
+                           " != 0; got 0", tname, tmpfname);
+        }
+        else if (0 == childpid) {   // child process
+
+            Filebuf fb;
+
+            if (!fb.open (tmpfname, std::ios::in))
+                rw_assert (false, __FILE__, __LINE__,
+                           "basic_filebuf<%s>::open(\"%s\", "
+                           "ios::in) failed in child process",
+                           tname, tmpfname);
+
+            std::exit (0);
+        }
+        else
+            rw_assert (false, __FILE__, __LINE__, "fork() failed");
+
+        REMOVE_FILE (tmpfname);
+    }
+
+#endif   // _WIN{32,64}
+
+}
+
+/***************************************************************************/
+
+template <class charT>
+static void
+test_sync (const char* tname)
+{
+    typedef std::basic_filebuf<charT, std::char_traits<charT> > Filebuf;
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::sync ()", tname);
+
+    const char* const tmpfname = rw_tmpnam (0);
+    if (!tmpfname) {
+        return;
+    }
+
+    {
+        Filebuf fb;
+
+        static const charT foo[] = { 'f', 'o', 'o' };
+        static const charT BAR[] = { 'B', 'A', 'R' };
+
+        // create a non-empty file
+        rw_fwrite (tmpfname, "foobar");
+
+        if (fb.open (tmpfname, std::ios::in)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            charT readbuf [256] = { 0 };
+
+            // read the first part of the file; filebuf will actually
+            // end up reading and caching the entire contents of the
+            // file
+            std::streamsize got = fb.sgetn (readbuf, 3);
+
+            // verify the contents of buffer match that of the file
+            if (3 != got)
+                rw_assert (false, __FILE__, __LINE__,
+                           "sgetn() == 3, got %d", got);
+
+            rw_assert (!std::memcmp (readbuf, foo, sizeof foo),
+                       __FILE__, __LINE__,
+                       "sgetn() retrieved \"%s\", expected \"%s\")",
+                       readbuf, foo);
+
+            // overwrite the contents of the file
+            rw_fwrite (tmpfname, "FOOBAR");
+
+            // call sync, excpecting filebuf to synchromnize with
+            // the new contents of the file while maintaining
+            // the correct position
+            const int res = fb.pubsync ();
+
+            rw_assert (0 == res, __FILE__, __LINE__,
+                       "pubsync() == 0, got %d", res);
+
+            std::memset (readbuf, 0, sizeof readbuf);
+
+            // continue to read the file where the first sgetn()
+            // call left off
+            got = fb.sgetn (readbuf, 3);
+
+            // verify that the new contents of the file have been read
+            if (3 != got)
+                rw_assert (false, __FILE__, __LINE__,
+                           "sgetn() == 3, got %d", got);
+
+            rw_assert (!std::memcmp (readbuf, BAR, sizeof BAR),
+                       __FILE__, __LINE__,
+                       "sgetn() retrieved \"%s\", expected \"%s\")",
+                       readbuf, BAR);
+        }
+        else {
+            rw_assert (false, __FILE__, __LINE__,
+                       "failed to open an existing file");
+        }
+    }
+
+    {
+        Filebuf fb;
+
+        static const charT foo[] = { 'f', 'o', 'o' };
+
+        // create a non-empty file
+        rw_fwrite (tmpfname, "foobar");
+
+        if (fb.open (tmpfname, std::ios::in)) {
+
+            rw_assert (fb.is_open (), __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open()", tname);
+
+            charT readbuf [256] = { 0 };
+
+            // read the first part of the file; filebuf will actually
+            // end up reading and caching the entire contents of the
+            // file
+            std::streamsize got = fb.sgetn (readbuf, 3);
+
+            // verify the contents of buffer match that of the file
+            if (3 != got)
+                rw_assert (false, __FILE__, __LINE__,
+                           "sgetn() == 3, got %d", got);
+
+            rw_assert (!std::memcmp (readbuf, foo, sizeof foo),
+                       __FILE__, __LINE__,
+                       "sgetn() retrieved \"%s\", expected \"%s\")",
+                       readbuf, foo);
+
+            // overwrite the contents of the file with less data
+            rw_fwrite (tmpfname, "BA");
+
+            // call sync, excpecting filebuf to synchromnize with
+            // the new contents of the file
+            // since there is less data in the file than the current
+            // offset, verify that the offset is adjusted to be the
+            // same as the end of the actual file
+            const int res = fb.pubsync ();
+
+            rw_assert (0 == res, __FILE__, __LINE__,
+                       "pubsync() == 0, got %d", res);
+
+            std::memset (readbuf, 0, sizeof readbuf);
+
+            // try to continue to read the file where the first sgetn()
+            // call left off, expecting a failure
+            got = fb.sgetn (readbuf, 3);
+
+            // verify that nothing has been read
+            if (0 != got)
+                rw_assert (false, __FILE__, __LINE__,
+                           "sgetn() == 0, got %d", got);
+
+            // verify that the end of the file is correctly reported
+            const typename Filebuf::off_type off =
+                fb.pubseekoff (0, std::ios::end);
+
+            rw_assert (off == 2, __FILE__, __LINE__,
+                       "pubseekoff(0, ios::end) == 2, got %d", off);
+        }
+        else {
+            rw_assert (false, __FILE__, __LINE__,
+                       "failed to open an existing file");
+        }
+    }
+}
+
+/***************************************************************************/
+
+
+template <class charT>
+static void
+test_attach (const char* tname)
+{
+#ifndef _RWSTD_NO_EXT_FILEBUF
+
+    //////////////////////////////////////////////////////////////////
+    // exercise attach(int) and fd()
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::attach (int) [extension]", tname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::fd () [extension]", tname);
+
+    typedef std::basic_filebuf<charT, std::char_traits<charT> > Filebuf;
+
+    // Extension:
+    // basic_filebuf* attach(int fd)
+    //   Connects *this to an open file descriptor, fd. Unless detach() is
+    //   called, the file descriptor will be closed during the first call
+    //   to close() or when the object is destroyed. Returns this on success,
+    //   0 on failure (e.g., when this->is_open() evaluates to true).
+
+    int lastfd = -1;
+
+    {
+        Filebuf fb;
+
+        // get a new valid file descriptor
+        const int fd = open (DEV_NULL, O_RDWR);
+
+        if (fd < 0) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "open (\"%s\", O_RDWR) < 0; "
+                       "aborting test", DEV_NULL);
+            return;
+        }
+
+        lastfd = fd;
+
+        // attach the filebuf object to the file descriptor
+        Filebuf *pfb = fb.attach (fd);
+
+        // verify that attach() succeeded
+        if (&fb != pfb)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) == %p, got 0",
+                       tname, fd, &fb);
+
+        // verify that fd() returns the attached file descriptor
+        if (fd != fb.fd ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::fd() == %d, got %d",
+                       tname, fd, fb.fd ());
+
+        // verify that the filebuf object is open
+        if (!fb.is_open ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open() == true, "
+                       "got false after a successful call to attach(%d)",
+                       tname, fd);
+
+        // Filebuf dtor should close the file descriptor (checked below)
+    }
+
+    {
+        Filebuf fb;
+
+        // create a new file descriptor
+        const int fd = open (DEV_NULL, O_RDWR);
+
+        // verify that the dtor in the block above closed the filebuf's fd
+        if (fd != lastfd)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) caused "
+                       "a file descriptor leak after object destruction",
+                       tname, lastfd);
+
+        lastfd = fd;
+
+        // attach this object to the new file descriptor
+        Filebuf *pfb = fb.attach (fd);
+
+        // verify that attach() succeeded
+        if (&fb != pfb)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) == %p, got 0",
+                       tname, fd, &fb);
+
+        // verify that fd() returns the attached file descriptor
+        if (fd != fb.fd ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::fd() == %d, got %d",
+                       tname, fd, fb.fd ());
+
+        // verify that the filebuf object is open
+        if (!fb.is_open ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open() == true, "
+                       "got false after a successful call to attach(%d)",
+                       tname, fd);
+
+        // call close
+        pfb = fb.close ();
+
+        // verify that the call to close() succeeded
+        if (&fb != pfb)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::close() == %p, got 0",
+                       tname, &fb);
+
+        // verify that fd() returns an invalid file descriptor after
+        // a successful call to close()
+        if (0 <= fb.fd ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::fd() < 0, got %d after "
+                       "a call to close()",
+                       tname, fb.fd ());
+
+        // verify that is_open() returns false after the call to close()
+        if (fb.is_open ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open() == false, "
+                       "got true after a successful call to close()",
+                       tname);
+    }
+
+    {
+        Filebuf fb;
+
+        // get a new valid file descriptor
+        const int fd = open (DEV_NULL, O_RDWR);
+
+        // verify that the dtor in the block above closed the filebuf's fd
+        if (fd != lastfd)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) caused "
+                       "a file descriptor leak after object destruction",
+                       tname, lastfd);
+
+        lastfd = fd;
+
+        // attach the filebuf object to the file descriptor
+        Filebuf *pfb = fb.attach (fd);
+
+        // verify that attach() succeeded
+        if (&fb != pfb)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) == %p, got 0",
+                       tname, fd, &fb);
+
+        pfb = fb.attach (fd);
+
+        // verify that a subsequent call to attach() (with the same
+        // or different file descriptor) failed
+        if (&fb == pfb)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) == 0, got %p",
+                       tname, fd, &fb);
+
+        const int new_fd = open (DEV_NULL, O_RDWR);
+
+        pfb = fb.attach (fd);
+
+        if (&fb == pfb)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) == 0, got %p",
+                       tname, fd, &fb);
+
+        close (new_fd);
+
+        // Filebuf dtor should close the file descriptor (checked below)
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise detach()
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s>::detach () [extension]", tname);
+
+    // Extension:
+    // int detach()
+    //   Flushes any waiting output to the file associated with the file
+    //   descriptor, and disconnects the file descriptor from *this so
+    //   that subsequent calls to close() will not close the file
+    //   descriptor. Returns the detached file descriptor on success,
+    //   -1 on failure.
+
+    {
+        Filebuf fb;
+
+        // get a new valid file descriptor
+        const int fd = open (DEV_NULL, O_RDWR);
+
+        // verify that the dtor in the block above closed the filebuf's fd
+        if (fd != lastfd)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::attach(int = %d) caused "
+                       "a file descriptor leak after object destruction",
+                       tname, lastfd);
+
+        lastfd = fd;
+
+        // attach the filebuf object to the file descriptor
+        fb.attach (fd);
+
+        const int old_fd = fb.detach ();
+
+        // verify that detach() returned the original file descriptor
+        if (fd != old_fd)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() == %d, got %d",
+                       tname, fd, old_fd);
+
+        // verify that is_open() returns false after the call to detach()
+        if (fb.is_open ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open() == false, "
+                       "got true after a call to detach()", tname);
+
+        // verify that fd() returns an invalid file descriptor after
+        // a successful call to detach()
+        if (0 <= fb.fd ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::fd() < 0, got %d after "
+                       "a call to detach()()", tname, fb.fd ());
+
+        close (old_fd);
+
+        errno = 0;
+    }
+
+    // verify that the dtor in the block above didn't try to close
+    // the already explicitly closed file descriptor
+    if (errno)
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::~basic_filebuf() attempted to "
+                   "close a detached file descriptor", tname);
+
+    {
+        Filebuf fb;
+
+        if (fb.fd () >= 0)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::fd() < 0, got %d for an "
+                       "object that's not open", tname, fb.fd ());
+
+        const int old_fd = fb.detach ();
+
+        // verify detach() returns an invalid file descriptor when called
+        // on a filebuf object that's not open
+        if (0 <= old_fd)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() < 0, got %d",
+                       tname, old_fd);
+    }
+
+    const char* const tmpfname = rw_tmpnam (0);
+
+    if (!tmpfname) {
+        return;
+    }
+
+    {
+        Filebuf fb;
+
+        // open a writeable file
+        const int fd = open (tmpfname, O_CREAT | O_WRONLY, 0666);
+
+        if (fd < 0) {
+            rw_warn (false, __FILE__, __LINE__,
+                     "open (\"%s\", O_CREAT | O_WRONLY, 0666) "
+                     "failed: %m", tmpfname);
+        }
+
+        // attach filebuf to the file descriptor
+        fb.attach (fd);
+
+        const charT data[] = { '0', '1', '2', '\0' };
+        const std::size_t nelems = sizeof data / sizeof *data - 1;
+
+        // write into the filebuf object
+        const std::size_t wrote = fb.sputn (data, nelems);
+
+        if (wrote != nelems)
+            rw_assert (false, __FILE__, __LINE__,
+                       "sputn(\"%s\", %d) == %d, got %d",
+                       data, nelems, nelems, wrote);
+
+        // and detach
+        const int old_fd = fb.detach ();
+        if (fd != old_fd)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() == %d, got %d",
+                       fd, old_fd);
+
+        // verify by reading the contents of the named file that
+        // the call to detach() wrote the contents of the filebuf
+        // object's data buffer into the file before detaching
+        std::size_t nbytes = 0;
+        const char* const buf =
+            _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, &nbytes));
+
+        if (   !buf || nbytes != nelems
+            || rw_strncmp (buf, data, nelems))
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() failed to flush "
+                       "data to the attached file descriptor; "
+                       "read %lu bytes: %s, expected \"012\"",
+                       tname, nbytes, buf);
+
+        REMOVE_FILE (tmpfname);
+    }
+
+    {
+        Filebuf fb;
+
+        // create a new file and open it for writing
+        const int fd = open (tmpfname, O_CREAT | O_WRONLY, 0666);
+
+        // attach filebuf to the file descriptor (will set mode to ios::out
+        // based on the O_WRONLY open mode of the file descriptor)
+        fb.attach (fd);
+
+        // close and reopen the same file descriptor as read-only
+        close (fd);
+        if (fd != open (tmpfname, O_RDONLY)) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "open (\"%s\", O_RDONLY) != %d; aborting test",
+                       tmpfname, fd);
+            return;
+        }
+
+        static const charT data[] = { '0', '1', '2', '\0' };
+        static const std::size_t nelems = sizeof data / sizeof *data - 1;
+
+        // write into the filebuf object's buffer
+        if (nelems != std::size_t (fb.sputn (data, nelems)))
+            rw_assert (false, __FILE__, __LINE__, "sputn() failed");
+
+        // and try to detach (must try to flush data into file)
+        const int bad_fd = fb.detach ();
+
+        // verify that detach() failed (due to the failure
+        // to write to a read-only file descriptor)
+        if (bad_fd >= 0)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() < 0, got %d after "
+                       "a failure to write to read-only file descriptor",
+                       tname, bad_fd);
+
+        // verify that the call to detach() failed to flush the contents
+        // of the filebuf object's data buffer into a read-only file by
+        // testing that the size of the file is unchanged (i.e., 0)
+        std::size_t nbytes = 0;
+
+        const char* buf  =
+            _RWSTD_STATIC_CAST (char*, rw_fread (tmpfname, 0));
+
+        if (buf && nbytes)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() unexpectedly wrote "
+                       "%u bytes to a read-only file: \"%s\"",
+                       tname, nbytes, buf);
+
+        // close and reopen the same file descriptor as write-only
+        close (fd);
+        if (fd != open (tmpfname, O_WRONLY)) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "open (\"%s\", O_WRONLY) != %d; aborting test",
+                       tmpfname, fd);
+            return;
+        }
+
+        // and detach (must successfully flush data into file)
+        const int good_fd = fb.detach ();
+
+        // verify that the call to detach() was successful
+        if (good_fd < 0)
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() == %d, got %d",
+                       tname, fd, good_fd);
+
+        // verify that the filebuf object is no longer open
+        if (fb.is_open ())
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::is_open() unexpectedly "
+                       "true after a successful call to detach()",
+                       tname);
+
+        // verify that this call to detach() wrote out the contents of the
+        // filebuf object's data buffer into the writeable file by checking
+        // the size and contents of the file
+        buf = (char*)rw_fread (tmpfname, &nbytes);
+
+        if (   !buf || nbytes != nelems
+            || rw_strncmp (buf, data, nelems))
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::detach() failed to flush "
+                       "data to the attached file descriptor; "
+                       "read %lu bytes: %s, expected %s",
+                       tname, nbytes, buf, data);
+
+        // close the file descriptor before removing the file
+        close (good_fd);
+
+        REMOVE_FILE (tmpfname);
+    }
+
+#else   // if defined (_RWSTD_NO_EXT_FILEBUF)
+
+    _RWSTD_UNUSED (tname);
+
+#endif   // _RWSTD_NO_EXT_FILEBUF
+
+}
+
+/***************************************************************************/
+
+// CodeCvt<charT> performs a state-dependent conversion
+// the first byte of the state_type object encodes the state,
+// any remaining bytes must be 0
+// internal characters are externally represented as sequences
+// of 1 to 22 chars, escape sequences are 11 to 13 chars long
+// and all start with the "<ESC-" prefix
+//
+// for example, the string "Hello, World!\n" will be externally
+// represented by the following sequence of narrow characters:
+//
+// "<ESC-UPPER>H<ESC-LOWER>ello<ESC-PUNCT><comma><SP><ESC-UPPER>"
+// "W<ESC-LOWER>orld<ESC-PUNCT><exclamation-mark><ESC-CNTRL>\n"
+
+template <class charT>
+struct CodeCvt: std::codecvt<charT, char, std::mbstate_t>
+{
+    typedef std::codecvt<charT, char, std::mbstate_t> Base;
+
+    enum { cntrl, punct, digit, upper, lower, hexcode };
+
+public:
+
+    typedef typename Base::intern_type intern_type;
+    typedef typename Base::extern_type extern_type;
+    typedef typename Base::state_type  state_type;
+
+    explicit CodeCvt (std::size_t ref = 0)
+        : Base (ref) { }
+
+protected:
+
+    virtual std::codecvt_base::result
+    do_out (state_type&,
+            const intern_type*, const intern_type*, const intern_type*&,
+            extern_type*, extern_type*, extern_type*&) const;
+
+    virtual std::codecvt_base::result
+    do_in (state_type&,
+           const extern_type*, const extern_type*, const extern_type*&,
+           intern_type*, intern_type*, intern_type*&) const;
+
+    virtual std::codecvt_base::result
+    do_unshift (state_type&, extern_type*, extern_type*, extern_type*&) const;
+
+    virtual int do_encoding () const _THROWS (()) {
+        return -1;   // state-dependent encoding
+    }
+
+    virtual bool do_always_noconv () const _THROWS (()) {
+        return false;   // conversion always necessary
+    }
+
+    // returns the maximum `N' of extern chars in the range [from, from_end)
+    // such that N represents max or fewer internal chars
+    virtual int
+    do_length (state_type&, const extern_type*,
+               const extern_type*, std::size_t) const;
+
+    // returns the max value do_length (s, from, from_end, 1) can return
+    // for any valid range [from, from_end) - see LWG issue 74
+    virtual int do_max_length () const _THROWS (()) {
+        return -1;
+    }
+};
+
+
+extern const char* const escapes[] = {
+    "<ESC-CNTRL>", "<ESC-PUNCT>", "<ESC-DIGIT>",
+    "<ESC-UPPER>", "<ESC-LOWER>", "<ESC-HEXCODE>"
+};
+
+
+extern const char* const charnames[] = {
+    // control characters (<ESC-CNTRL>)
+    "<NUL>", "<SOH>", "<STX>", "<ETX>", "<EOT>", "<ENQ>", "<ACK>", "<BEL>",
+    "<BS>", "<HT>", "\n", "<VT>", "<FF>", "<CR>" /* '\r' */, "<SO>", "<SI>",
+    "<DLE>", "<DC1>", "<DC2>", "<DC3>", "<DC4>", "<NAK>", "<SYN>", "<ETB>",
+    "<CAN>", "<EM>", "<SUB>", "<ESC>", "<FS>", "<GS>", "<RS>", "<US>",
+    // punctuators (<ESC-PUNCT>)
+    "<SP>",
+    "<exclamation-mark>",
+    "<quotation-mark>",
+    "<number-sign>",
+    "<dollar-sign>",
+    "<percent-sign>",
+    "<ampersand>",
+    "<apostrophe>",
+    "<left-parenthesis>",
+    "<right-parenthesis>",
+    "<asterisk>",
+    "<plus-sign>",
+    "<comma>",
+    "<hyphen>",
+    "<period>",
+    "<slash>",
+    // digits (<ESC-DIGIT>)
+    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+    // punctuators (<ESC-PUNCT>)
+    "<colon>",
+    "<semicolon>",
+    "<less-than-sign>",
+    "<equals-sign>",
+    "<greater-than-sign>",
+    "<question-mark>",
+    "<commercial-at>",
+    // uppercase letters (<ESC_UPPER>)
+    "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
+    "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
+    // punctuators (<ESC-PUNCT>)
+    "<left-square-bracket>",
+    "<backslash>",
+    "<right-square-bracket>",
+    "<circumflex>",
+    "<underscore>",
+    "<grave-accent>",
+    // lowercase letters (<ESC_LOWER>)
+    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
+    "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
+    // punctuators (<ESC-PUNCT>)
+    "<left-curly-bracket>",
+    "<vertical-line>",
+    "<right-curly-bracket>",
+    "<tilde>",
+    // control characters (<ESC-CNTRL>)
+    "<DEL>"
+    // characters above '\x7f' are represented in hex (<ESC-HEXCODE>)
+};
+
+
+template <class charT>
+std::codecvt_base::result
+CodeCvt<charT>::do_out (      state_type  &state,
+                        const intern_type *from,
+                        const intern_type *from_end,
+                        const intern_type *&from_next,
+                              extern_type *to,
+                              extern_type *to_end,
+                              extern_type *&to_next) const
+{
+    std::codecvt_base::result res = std::codecvt_base::ok;
+
+    char hexbuf [5] = "";
+
+    int int_state = hexcode;
+
+    for (from_next = from, to_next = to; from_next != from_end; ++from_next) {
+
+        typedef std::char_traits<intern_type> Traits;
+
+        const std::size_t uch = std::size_t (Traits::to_int_type (*from_next));
+
+        if (uch < ' ') {
+            int_state = cntrl;
+        }
+        else if (uch >= ' ' && uch <= '/') {
+            int_state = punct;
+        }
+        else if (uch >= '0' && uch <= '9') {
+            int_state = digit;
+        }
+        else if (uch >= ':' && uch <= '@') {
+            int_state = punct;
+        }
+        else if (uch >= 'A' && uch <= 'Z') {
+            int_state = upper;
+        }
+        else if (uch >= '[' && uch <= '`') {
+            int_state = punct;
+        }
+        else if (uch >= 'a' && uch <= 'z') {
+            int_state = lower;
+        }
+        else if (uch >= '{' && uch <= '~') {
+            int_state = punct;
+        }
+        else if (uch == '\x7f') {
+            int_state = cntrl;
+        }
+        else if (uch <= 0xff) {
+            int_state = hexcode;
+
+            if (to_end - to_next < 4) {
+                res = std::codecvt_base::partial;
+                break;
+            }
+
+            // convert `uch' to a hexadecimal escape sequence
+            static const char hexdigits[] = "0123456789abcdef";
+
+            hexbuf [0] = '\\';
+            hexbuf [1] = 'x';
+            hexbuf [2] = hexdigits [uch >> 8];
+            hexbuf [3] = hexdigits [uch & 0x0fU];
+            hexbuf [4] = '\0';
+        }
+        else {
+            res = std::codecvt_base::error;
+            break;
+        }
+
+        if (int (*(char*)&state) != int_state) {
+
+            const std::size_t len = std::strlen (escapes [int_state]);
+
+            if (len > std::size_t (to_end - to_next)) {
+                res = std::codecvt_base::partial;
+                break;
+            }
+
+            std::memcpy (to_next, escapes [int_state], len);
+            to_next += len;
+
+            *(char*)&state = char (int_state);
+        }
+
+        const char* const outs = *hexbuf ? hexbuf : charnames [uch];
+
+        const std::size_t len = std::strlen (outs);
+
+        if (len > std::size_t (to_end - to_next)) {
+            res = std::codecvt_base::partial;
+            break;
+        }
+
+        std::memcpy (to_next, outs, len);
+        to_next += len;
+    }
+
+    return res;
+}
+
+
+// looks for a character whose name starts at `*pbeg' in the table
+// of character names, `chartbl' containing `tblsize' elements
+// if a unique (even partial) match is found, returns the index of
+// the character in the table; if the unique match is complete,
+// also advances `*pbeg' by the length of the match
+std::size_t find_char (const char **pbeg, const char *end,
+                       const char* const chartbl[], std::size_t tblsize)
+{
+    const std::size_t nchars = sizeof charnames / sizeof *charnames;
+
+    std::size_t hits [nchars] = { 0 };
+
+    const char* cur = *pbeg;
+
+    for (; cur != end; ++cur) {
+
+        const std::size_t inx = cur - *pbeg;
+
+        std::size_t nmatches = 0;
+
+        for (std::size_t i = 0; i != tblsize; ++i) {
+            if (hits [i] == inx && chartbl [i] && *cur == chartbl [i][inx]) {
+                ++hits [i];
+                ++nmatches;
+            }
+        }
+
+        if (!nmatches)
+            break;
+    }
+
+    std::size_t nmatches = 0;
+    std::size_t imaxhits = 0;
+    std::size_t inx      = std::size_t (-1);
+
+    for (std::size_t i = 0; i != tblsize; ++i) {
+
+        if (!chartbl [i])
+            continue;
+
+        if (hits [i] > hits [imaxhits])
+            imaxhits = i;
+
+        if (hits [i] == std::strlen (chartbl [i])) {
+
+            if (std::size_t (-1) == inx)
+                inx = 0;
+
+            if (hits [i] == hits [inx]) {
+                ++nmatches;
+                inx = i;
+            }
+            else if (hits [i] > hits [inx]) {
+                nmatches = 1;
+                inx = i;
+            }
+        }
+        else if (std::size_t (-1) != inx && hits [i] > hits [inx]) {
+            nmatches = 0;
+            inx = i;
+        }
+    }
+
+    if (inx != std::size_t (-1) && 1 == nmatches)
+        *pbeg = cur;
+
+    if (hits [imaxhits] == std::size_t (end - *pbeg))
+        inx = imaxhits;
+
+    return inx;
+}
+
+
+template <class charT>
+std::codecvt_base::result
+CodeCvt<charT>::do_in (      state_type  &state,
+                       const extern_type *from,
+                       const extern_type *from_end,
+                       const extern_type *&from_next,
+                             intern_type *to,
+                             intern_type *to_end,
+                             intern_type *&to_next) const
+{
+    std::codecvt_base::result res = std::codecvt_base::ok;
+
+    for (to_next = to, from_next = from; to_next != to_end; ++to_next) {
+
+    top_of_loop:
+
+        if (from_next == from_end)
+            break;
+
+        const std::size_t navail = from_end - from_next;
+
+        // check the beginning of the sequence to see if
+        // it may possibly start with an escape sequence
+
+        if (navail <= 5 && !std::memcmp (from_next, "<ESC-", navail))
+            return std::codecvt_base::partial;
+
+        if (navail > 5 && !std::memcmp (from_next, "<ESC-", 5)) {
+
+            // found the beginning of what might be an escape sequence
+
+            if (navail >= 11) {
+
+                const std::size_t nescapes = sizeof escapes / sizeof *escapes;
+
+                for (std::size_t i = 0; i != nescapes; ++i) {
+
+                    const std::size_t len = std::strlen (escapes [i]);
+
+                    if (!std::memcmp (escapes [i], from_next, len)) {
+
+                        // found an escape sequence
+
+                        // set the state variable
+                        *(char*)&state = char (i);
+
+                        // advance past the escape sequence
+                        from_next += len;
+
+                        // continue iterating over the rest of the sequence
+                        goto top_of_loop;
+                    }
+                }
+            }
+            else {
+                // not enough external elements to convert
+                // to an internal character
+                return std::codecvt_base::partial;
+            }
+        }
+
+        std::size_t chinx = std::size_t (-1);   // character index
+        std::size_t choff = 0;                  // character offset
+
+        const char* const from_next_save = from_next;
+
+        switch (*(char*)&state) {
+
+        case cntrl:
+            chinx = find_char (&from_next, from_end, charnames, ' ' + 1U);
+            if (   std::size_t (-1) == chinx
+                && 5 <= from_end - from_next
+                && !std::memcmp (from_next, "<DEL>", 5)) {
+                chinx = '\x7f';
+                from_next += 5;
+            }
+            break;
+
+        case punct: {
+
+            static const char* const pun[] = {
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                "<SP>",
+                "<exclamation-mark>",
+                "<quotation-mark>",
+                "<number-sign>",
+                "<dollar-sign>",
+                "<percent-sign>",
+                "<ampersand>",
+                "<apostrophe>",
+                "<left-parenthesis>",
+                "<right-parenthesis>",
+                "<asterisk>",
+                "<plus-sign>",
+                "<comma>",
+                "<hyphen>",
+                "<period>",
+                "<slash>",
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                "<colon>",
+                "<semicolon>",
+                "<less-than-sign>",
+                "<equals-sign>",
+                "<greater-than-sign>",
+                "<question-mark>",
+                "<commercial-at>",
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                "<left-square-bracket>",
+                "<backslash>",
+                "<right-square-bracket>",
+                "<circumflex>",
+                "<underscore>",
+                "<grave-accent>",
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                "<left-curly-bracket>",
+                "<vertical-line>",
+                "<right-curly-bracket>",
+                "<tilde>",
+                0
+            };
+
+            chinx = find_char (&from_next, from_end,
+                               pun, sizeof pun / sizeof *pun);
+
+            break;
+        }
+
+        case digit:
+            choff = '0';
+
+            if (*from_next >= '0' && *from_next <= '9')
+                chinx = *from_next++ - '0';
+
+            // commented out code replaced by the above for efficiency
+            // chinx = find_char (&from_next, from_end, charnames + choff, 10);
+            break;
+
+        case lower:
+            choff = 'a';
+
+            // assume ASCII
+            if (*from_next >= 'a' && *from_next <= 'z')
+                chinx = *from_next++ - 'a';
+
+            // commented out code replaced by the above for efficiency
+            // chinx = find_char (&from_next, from_end, charnames + choff, 26);
+            break;
+
+        case upper:
+            choff = 'A';
+
+            // assume ASCII
+            if (*from_next >= 'A' && *from_next <= 'Z')
+                chinx = *from_next++ - 'A';
+
+            // commented out code replaced by the above for efficiency
+            // chinx = find_char (&from_next, from_end, charnames + choff, 26);
+            break;
+
+        case hexcode: {
+            if (from_end - from_next < 4)
+                return std::codecvt_base::partial;
+
+            if (   from_next [0] != '\\' || from_next [1] != 'x'
+                || !(   from_next [2] >= '0' && from_next [2] <= '9'
+                     || from_next [2] >= 'A' && from_next [2] <= 'F'
+                     || from_next [2] >= 'a' && from_next [2] <= 'f')
+                || !(   from_next [3] >= '0' && from_next [3] <= '9'
+                     || from_next [3] >= 'A' && from_next [3] <= 'F'
+                     || from_next [3] >= 'a' && from_next [3] <= 'f'))
+                return std::codecvt_base::error;
+
+            // convert a hex literal to a number
+            chinx = 0;
+            for (unsigned i = 2; i != 4; ++i) {
+                chinx <<= 4;
+                if (from_next [i] >= '0' && from_next [i] <= '9')
+                    chinx += from_next [i] - '0';
+                else if (from_next [i] >= 'A' && from_next [i] <= 'F')
+                    chinx += 10 + (from_next [i] - 'A');
+                else
+                    chinx += 10 + (from_next [i] - 'a');
+            }
+
+            break;
+        }
+
+        default:
+            chinx = std::size_t (-1);
+            break;
+        }
+
+        if (std::size_t (-1) == chinx) {
+            res = std::codecvt_base::error;
+            break;
+        }
+
+        // the combination of a valid `chinx' and an unmodified
+        // `from_next' pointer indicates a partial match
+        if (from_next == from_next_save) {
+            res = std::codecvt_base::partial;
+            break;
+        }
+
+        *to_next = charT (chinx + choff);
+    }
+
+    return res;
+}
+
+
+template <class charT>
+std::codecvt_base::result
+CodeCvt<charT>::
+do_unshift (state_type  &state,
+            extern_type *to,
+            extern_type *to_end,
+            extern_type *&to_next) const
+{
+    to_next = to;
+
+    if (!*(char*)&state)
+        return std::codecvt_base::noconv;
+
+    const std::size_t len = std::strlen (escapes [0]);
+
+    if (len > std::size_t (to_end - to_next))
+        return std::codecvt_base::partial;
+
+    std::memcpy (to_next, escapes [0], len);
+    to_next += len;
+
+    std::memset (&state, 0, sizeof state);
+
+    return std::codecvt_base::ok;
+}
+
+
+template <class charT>
+int
+CodeCvt<charT>::
+do_length (state_type&, const extern_type*,
+           const extern_type*, std::size_t) const
+{
+    return 0;
+}
+
+/***************************************************************************/
+
+static const char*
+get_codecvt_result (std::codecvt_base::result res)
+{
+    switch (res) {
+    case std::codecvt_base::error: return "std::codecvt_base::error";
+    case std::codecvt_base::noconv: return "std::codecvt_base::noconv";
+    case std::codecvt_base::ok: return "std::codecvt_base::ok";
+    case std::codecvt_base::partial: return "std::codecvt_base::partial";
+    }
+
+    return "unknown";
+}
+
+
+template <class charT>
+static void
+test_codecvt (const char* tname)
+{
+    rw_info (0, __FILE__, __LINE__,
+             "std::basic_filebuf<%s> with a state-dependent encoding",
+             tname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "sgetn() with state-dependent code conversion");
+
+    // read in the text of this source file as plain text
+
+    typedef std::basic_filebuf<charT, std::char_traits<charT> > Filebuf;
+    typedef typename Filebuf::off_type                          off_type;
+
+    Filebuf noconv_in;
+
+    // use ios_base::binary to avoid CR/LF conversion issues
+    if (!noconv_in.open (__FILE__, std::ios::binary | std::ios::in)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::open (\"%s\", "
+                   "ios_base::binary | ios_base::in) failed",
+                   tname, __FILE__);
+        return;
+    }
+
+    // seek to the end of the file to get its size in bytes
+    const std::streamsize noconv_fsize =
+        noconv_in.pubseekoff (0, std::ios::end);
+
+    if (noconv_fsize <= 0) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::pubseekoff "
+                   "(0, ios_base::end) >= 0, got %i",
+                   tname, noconv_fsize);
+        return;
+    }
+
+    if (0 != noconv_in.pubseekoff (0, std::ios::beg)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::pubseekoff "
+                   "(0, ios_base::beg) failed", tname);
+        return;
+    }
+
+    const char* const tmpfname = rw_tmpnam (0);
+
+    if (!tmpfname) {
+        return;
+    }
+
+    // allocate a buffer large enough to hold the contents of the
+    // file in internal representation without codeset conversion
+    charT *noconv_intbuf = new charT [noconv_fsize];
+
+    // sgetn() returns the number of internal characters read in
+    // which must equal the number of external characters read by
+    // the `noconv_in' file buffer (since it does no conversion)
+    std::streamsize nread = noconv_in.sgetn (noconv_intbuf, noconv_fsize);
+
+    if (nread != noconv_fsize) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::sgetn (%p, %i) == %i), got %i",
+                   tname, noconv_intbuf,
+                   noconv_fsize, noconv_fsize, nread);
+        delete[] noconv_intbuf;
+        return;
+    }
+
+    const CodeCvt<charT> cvt (1);
+
+    // write out the text of this file using the test codecvt facet
+    // that performs state-dependent encoding
+    Filebuf conv_out;
+
+    conv_out.pubimbue (std::locale (std::locale::classic (), &cvt));
+
+    if (!conv_out.open (tmpfname, std::ios::binary | std::ios::out)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::open (\"%s\", ios_base::out) "
+                   "failed", tname, tmpfname);
+        delete[] noconv_intbuf;
+        return;
+    }
+
+    // sputn() returns the number of internal characters written out
+    // which must equal the number of external characters read by
+    // the `noconv_in' file buffer (since it does no conversion)
+    const std::streamsize nwrote = conv_out.sputn (noconv_intbuf, nread);
+
+    if (nread != nwrote) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::sputn (\"%s\", %i) == %i), "
+                   "got %i", tname,
+                   noconv_intbuf, nread, nread, nwrote);
+        delete[] noconv_intbuf;
+        return;
+    }
+
+    // close file buffer to flush it out
+    if (!conv_out.close ())
+        rw_warn (false, __FILE__, __LINE__,
+                 "basic_filebuf<%s>(\"%s\").close() failed",
+                 tname, tmpfname);
+
+    std::filebuf nin;   // narrow input stream buffer
+
+    if (!nin.open (tmpfname, std::ios::binary | std::ios::in)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::open (\"%s\", ios_base::in) failed",
+                   tname, tmpfname);
+        delete[] noconv_intbuf;
+        return;
+    }
+
+    // get the size of the converted file in external characters
+    const std::streamsize conv_fsize = nin.pubseekoff (0, std::ios::end);
+
+    if (conv_fsize <= noconv_fsize) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "filebuf::pubseekoff (0, ios_base::end) > %i, got %i",
+                   noconv_fsize, conv_fsize);
+        delete[] noconv_intbuf;
+        return;
+    }
+
+    if (0 != nin.pubseekoff (0, std::ios::beg)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "filebuf::pubseekoff (0, ios_base::beg) failed");
+        delete[] noconv_intbuf;
+        return;
+    }
+
+    // allocate a buffer large enough to hold the contents of the
+    // file in external representation without codeset conversion
+    char *noconv_extbuf = new char [conv_fsize];
+    std::memset (noconv_extbuf, 0, conv_fsize);
+
+    // read in the (unconverted) contents of the file
+    nread = nin.sgetn (noconv_extbuf, conv_fsize);
+
+    if (nread != conv_fsize) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "filebuf::sgetn (%p, %i) == %i, got %i",
+                   noconv_extbuf, conv_fsize, conv_fsize, nread);
+        delete[] noconv_intbuf;
+        delete[] noconv_extbuf;
+        return;
+    }
+
+    if (!nin.close ())
+        rw_warn (false, __FILE__, __LINE__,
+                 "basic_filebuf<%s>(\"%s\").close() failed",
+                 tname, tmpfname);
+
+    std::mbstate_t state;
+    std::memset (&state, 0, sizeof state);
+
+    const char *from      = noconv_extbuf;
+    const char *from_end  = noconv_extbuf + nread;
+    const char *from_next = 0;
+
+    // allocate a buffer large enough to hold the contents of the
+    // file in internal representation with codeset conversion
+    charT *conv_intbuf = new charT [noconv_fsize];
+    std::memset (conv_intbuf, 0, noconv_fsize * sizeof *conv_intbuf);
+
+    charT *to      = conv_intbuf;
+    charT *to_end  = conv_intbuf + noconv_fsize;
+    charT *to_next = 0;
+
+    // convert the contents of the file using the test codecvt facet
+    const std::codecvt_base::result cvtres =
+        cvt.in (state, from, from_end, from_next, to, to_end, to_next);
+
+    if (std::codecvt_base::ok != cvtres) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "CodeCvt<%s>::in ({ %d, ... },  %p, %p, %p, %p, %p, %p) "
+                   "== std::codecvt_base::ok, got %s",
+                   tname, *(unsigned char*)&state,
+                   from, from_end, from_next, to, to_end, to_next,
+                   get_codecvt_result (cvtres));
+        delete[] noconv_intbuf;
+        delete[] noconv_extbuf;
+        delete[] conv_intbuf;
+        return;
+    }
+
+    const std::streamsize n_ext_cvt = from_next - from;
+    const std::streamsize n_int_cvt = to_next - to;
+
+    rw_assert (n_ext_cvt == conv_fsize, __FILE__, __LINE__,
+               "CodeCvt<%s>::in() converted %i external characters, "
+               "expected %i", tname, n_ext_cvt, conv_fsize);
+
+    rw_assert (n_int_cvt == noconv_fsize, __FILE__, __LINE__,
+               "CodeCvt<%s>::in() produced %i internal characters, "
+               "expected %i", tname, n_int_cvt, noconv_fsize);
+
+    // verify that the contents of the unconverted internal buffer
+    // (i.e., the text of this file in internal representation) are
+    // the same as the contents of the converted internal buffer
+    // (i.e., the text of this file converted to the external
+    // state-dependent representation and then converted back to
+    // the internal encoding)
+    rw_assert (!std::memcmp (noconv_intbuf, conv_intbuf, n_int_cvt),
+               __FILE__, __LINE__, "code conversion mismatch");
+
+
+    // read in the text of the temporary file encoded in
+    // a state-dependent encoding and convert it to its
+    // internal representation
+    Filebuf conv_in;
+
+    conv_in.pubimbue (std::locale (std::locale::classic (), &cvt));
+
+    conv_in.open (tmpfname, std::ios::in);
+
+    std::memset (conv_intbuf, 0, noconv_fsize * sizeof *conv_intbuf);
+
+    nread = conv_in.sgetn (conv_intbuf, noconv_fsize);
+
+    if (nread != noconv_fsize) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "basic_filebuf<%s>::sgetn (%p, %i) == %i, got %i",
+                   tname, conv_intbuf, noconv_fsize,
+                   noconv_fsize, nread);
+        delete[] noconv_intbuf;
+        delete[] noconv_extbuf;
+        delete[] conv_intbuf;
+        return;
+    }
+
+    rw_assert (!std::memcmp (noconv_intbuf, conv_intbuf,
+                             n_int_cvt * sizeof *noconv_intbuf),
+               __FILE__, __LINE__, "code conversion mismatch");
+
+    if (!noconv_in.close ())
+        rw_warn (false, __FILE__, __LINE__,
+                 "basic_filebuf<%s>(" __FILE__ ").close() failed",
+                 tname);
+
+    if (!conv_in.close ())
+        rw_warn (false, __FILE__, __LINE__,
+                 "basic_filebuf<%s>(\"%s\").close() failed",
+                 tname, tmpfname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "pubseekoff() and pubseekpos() with state-dependent "
+             "code conversion");
+
+    noconv_in.open (__FILE__, std::ios::binary | std::ios::in);
+    conv_in.open (tmpfname, std::ios::binary | std::ios::in);
+
+    for (std::streamsize i = 0; i < noconv_fsize; i += noconv_fsize / 13) {
+
+        typedef typename Filebuf::pos_type pos_type;
+
+        noconv_in.pubseekoff (0, std::ios::beg);
+        conv_in.pubseekoff (0, std::ios::beg);
+
+        std::memset (noconv_intbuf, 0, noconv_fsize * sizeof *noconv_intbuf);
+        std::memset (conv_intbuf, 0, noconv_fsize * sizeof *conv_intbuf);
+
+        nread = noconv_in.sgetn (noconv_intbuf, i);
+
+        if (i != nread) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                       "got %d", tname, noconv_intbuf, i, i, nread);
+            break;
+        }
+
+        nread = conv_in.sgetn (conv_intbuf, i);
+
+        if (i != nread) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                       "got %d", tname, conv_intbuf, i, i, nread);
+            break;
+        }
+
+        if (std::memcmp (noconv_intbuf, conv_intbuf,
+                         i * sizeof *conv_intbuf)) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. code conversion mismatch", i);
+            break;
+        }
+
+        const pos_type noconv_pos =
+            noconv_in.pubseekoff (0, std::ios::cur);
+
+        const pos_type conv_pos =
+            conv_in.pubseekoff (0, std::ios::cur);
+
+        std::memset (noconv_intbuf, 0, noconv_fsize * sizeof *noconv_intbuf);
+        std::memset (conv_intbuf, 0, noconv_fsize * sizeof *conv_intbuf);
+
+        nread = noconv_in.sgetn (noconv_intbuf, noconv_fsize);
+
+        if (noconv_fsize - i != nread) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                       "got %d", tname, noconv_intbuf,
+                       noconv_fsize, noconv_fsize - i, nread);
+            break;
+        }
+
+        nread = conv_in.sgetn (conv_intbuf, noconv_fsize);
+
+        if (noconv_fsize - i != nread) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                       "got %d", tname, conv_intbuf,
+                       noconv_fsize, noconv_fsize - i, nread);
+            break;
+        }
+
+        if (std::memcmp (noconv_intbuf, conv_intbuf,
+                         nread * sizeof *noconv_intbuf)) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. data mismatch after conversion", i);
+            break;
+        }
+
+        if (!noconv_in.close ())
+            rw_warn (false, __FILE__, __LINE__,
+                     "basic_filebuf<%s>(" __FILE__ ").close() failed",
+                     tname);
+
+        if (!conv_in.close ())
+            rw_warn (false, __FILE__, __LINE__,
+                     "basic_filebuf<%s>(\"%s\").close() failed",
+                     tname, tmpfname);
+
+        noconv_in.open (__FILE__, std::ios::binary | std::ios::in);
+        conv_in.open (tmpfname, std::ios::binary | std::ios::in);
+
+        const pos_type noconv_pos_new = noconv_in.pubseekpos (noconv_pos);
+
+        if (noconv_pos_new != noconv_pos) {
+
+            std::mbstate_t noconv_state     = noconv_pos.state ();
+            std::mbstate_t noconv_state_new = noconv_pos_new.state ();
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::pubseekpos ({ %d, %d }, "
+                       "ios_base::cur) == { %d, %d }, got { %d, %d }",
+                       tname,
+                       off_type (noconv_pos), *(char*)&noconv_state,
+                       off_type (noconv_pos), *(char*)&noconv_state,
+                       off_type (noconv_pos_new),
+                       *(char*)&noconv_state_new);
+            break;
+        }
+
+        const pos_type conv_pos_new = conv_in.pubseekpos (conv_pos);
+
+        if (conv_pos_new != conv_pos) {
+            std::mbstate_t conv_state     = noconv_pos.state ();
+            std::mbstate_t conv_state_new = noconv_pos_new.state ();
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::pubseekpos ({ %d, %d }, "
+                       "ios_base::cur) == { %d, %d }, got { %d, %d }",
+                       tname,
+                       off_type (conv_pos), *(char*)&conv_state,
+                       off_type (conv_pos), *(char*)&conv_state,
+                       off_type (conv_pos_new),
+                       *(char*)&conv_state_new);
+            break;
+        }
+
+        std::memset (noconv_intbuf, 0, noconv_fsize * sizeof *noconv_intbuf);
+        nread = noconv_in.sgetn (noconv_intbuf, noconv_fsize);
+
+        if (noconv_fsize - i != nread) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                       "got %d (no code conversion)",
+                       tname, noconv_intbuf,
+                       noconv_fsize, noconv_fsize - i, nread);
+            break;
+        }
+
+        if (std::memcmp (noconv_intbuf, conv_intbuf,
+                         nread * sizeof *noconv_intbuf)) {
+            rw_assert (false, __FILE__, __LINE__,
+                      "data mismatch (no code conversion)");
+            break;
+        }
+
+        std::memset (conv_intbuf, 0, noconv_fsize * sizeof *conv_intbuf);
+        nread = conv_in.sgetn (conv_intbuf, noconv_fsize);
+
+        if (noconv_fsize - i != nread) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "basic_filebuf<%s>::sgetn (%p, %d) == %d, "
+                       "got %d (with code conversion)",
+                       tname, conv_intbuf,
+                       noconv_fsize, noconv_fsize - i, nread);
+            break;
+        }
+
+        if (std::memcmp (noconv_intbuf, conv_intbuf,
+                         nread * sizeof *noconv_intbuf)) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "code conversion mismatch");
+            break;
+        }
+    }
+
+    delete[] noconv_intbuf;
+    delete[] noconv_extbuf;
+    delete[] conv_intbuf;
+
+    if (!noconv_in.close ())
+        rw_warn (false, __FILE__, __LINE__,
+                 "basic_filebuf<%s>(" __FILE__ ").close() failed",
+                 tname);
+
+    if (!conv_in.close ())
+        rw_warn (false, __FILE__, __LINE__,
+                 "basic_filebuf<%s>(\"%s\").close() failed",
+                 tname, tmpfname);
+
+    REMOVE_FILE (tmpfname);
+}
+
+/***************************************************************************/
+
+
+template <class charT>
+static void
+test_codecvt_with_seek ()
+{
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved input, output, and seeks in ios_base::app "
+             "mode with state-dependent code conversion");
+
+    typedef std::basic_filebuf<charT, std::char_traits<charT> > FileBuf;
+
+    FileBuf inbuf;
+
+    // open this source file
+    inbuf.open (__FILE__, std::ios::in);
+
+    const std::streamsize N = 0xfffff;
+    charT *buf = new charT [N];
+
+    // read the text of the file into a local buffer
+    const std::streamsize nchars = inbuf.sgetn (buf, N);
+
+    if (nchars <= 0) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "sgetn(..., %d) > 0, got %d", N, nchars);
+        delete[] buf;
+        return;
+    }
+
+    inbuf.close ();
+
+    FileBuf iobuf;
+
+    // imbue a locale containing a CodeCvt<charT> facet into the filebuf
+    iobuf.pubimbue (std::locale (std::locale::classic (), new CodeCvt<charT>));
+
+    const char* const tmpfname = rw_tmpnam (0);
+
+    if (!tmpfname) {
+        delete[] buf;
+        return;
+    }
+
+    // remove file just in case it exists (it shouldn't)
+    std::remove (tmpfname);
+
+    // open the filebuf on a temporary file
+    if (!iobuf.open (tmpfname, std::ios::in | std::ios::out | std::ios::app)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "open (\"%s\", ios::in | ios::out | ios::app) failed",
+                   tmpfname);
+        delete[] buf;
+        return;
+    }
+
+    charT *pb = buf;
+
+    // alterante writes, seeks, and reads to/from the filebuf
+    for (std::streamsize n = nchars, i = nchars; n; i = n / 2) {
+
+        const std::streamsize nput = iobuf.sputn (pb, n - i);
+
+        iobuf.pubseekoff (0, std::ios::beg);
+
+        charT *localbuf = new charT [N];
+        const std::streamsize nget = iobuf.sgetn (localbuf, n - i);
+
+        // verify the consistency of the read data
+        if (nget != n - i || std::memcmp (buf, localbuf, nget * sizeof *buf)) {
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "sgetn(..., %d) == %d, got %d (or inconsistent data)",
+                       n - i, n - i, nget);
+            delete[] localbuf;
+            break;
+        }
+
+        delete[] localbuf;
+
+        iobuf.pubseekoff (0, std::ios::beg);
+
+        pb += nput;
+        n  -= nput;
+
+    }
+
+    iobuf.close ();
+
+    // imbue the filebuf object with a locale with the conversion facet
+    inbuf.pubimbue (std::locale (std::locale::classic (),
+                                 new CodeCvt<charT>));
+
+    // and open the temporary file one more time
+    if (!inbuf.open (tmpfname, std::ios::in)) {
+        rw_assert (false, __FILE__, __LINE__, "");
+        delete[] buf;
+
+        REMOVE_FILE (tmpfname);
+        return;
+    }
+
+    charT *cvtbuf = new charT [N];
+
+    // read the whole file into a temporary buffer
+    std::streamsize ncvt = inbuf.sgetn (cvtbuf, N);
+
+    // verify that the contents are consistent with the original data
+    if (nchars != ncvt || std::memcmp (buf, cvtbuf, nchars * sizeof *buf)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "sgetn(..., %d) == %d, got %d (or inconsistent data)",
+                   N, nchars, ncvt);
+
+    }
+
+    delete[] buf;
+    delete[] cvtbuf;
+
+    // close file before removing it
+    inbuf.close ();
+
+    REMOVE_FILE (tmpfname);
+}
+
+/***************************************************************************/
+
+
+template <class charT>
+static void
+do_test (const char* tname)
+{
+    rw_info (0, __FILE__, __LINE__, "std::basic_filebuf<%s>", tname);
+
+    // exercise basic_filebuf constructors
+    test_ctors<charT> (tname);
+
+    // exercise basic_filebuf::open()
+    test_open<charT> (tname);
+
+    // exercise basic_filebuf::sync()
+    test_sync<charT> (tname);
+
+    // exercise the basic_filebuf::attach() and detach() extensions
+    test_attach<charT> (tname);
+
+    // exercise basic_filebuf functionality with a non-trivial
+    // codecvt facet that implements stateful conversion
+    test_codecvt<charT> (tname);
+    test_codecvt_with_seek<charT> ();
+}
+
+
+static int
+run_test (int /*argc*/, char* /*argv*/ [])
+{
+    do_test<char> ("char");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    do_test<wchar_t> ("wchar_t");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+
+/*extern*/ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "[lib.filebuf]",
+                    "",   // no comment
+                    run_test, "", 0);
+}
+
diff --git a/tests/iostream/27.ios.members.static.cpp b/tests/iostream/27.ios.members.static.cpp
new file mode 100644
index 0000000..437779e
--- /dev/null
+++ b/tests/iostream/27.ios.members.static.cpp
@@ -0,0 +1,462 @@
+/***************************************************************************
+ *
+ * 27.ios.members.static.cpp - test exercising [lib.ios.members.static]
+ *
+ * $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.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ *
+ **************************************************************************/
+
+// exercise that the default setting of ios_base::sync_with_stdio()
+// produces the expected output, i.e., that the ouptut of the standard
+// iostream objects, std::cout, std::cerr, etc., is properly interleaved
+// with the output produced by interleaving calls to stdio printf()
+// also exercises the ability of buffered standard iostream objects
+// (i.e., cout, wcout, clog, and wclog) to flush output on program exit
+
+#include <cerrno>     // for errno
+#include <cstdio>     // for fprintf, L_tmpnam
+#include <cstdlib>    // for STD{ERR,OUT}_FILENO
+#include <cstring>    // for strerror
+#include <iostream>
+
+// rwtest headers
+#include <driver.h>
+#include <file.h>
+
+#if !defined _WIN32 && !defined _WIN64
+
+#  include <fcntl.h>
+#  include <unistd.h>
+#  include <sys/types.h>
+#  include <sys/wait.h>
+
+#  define DEV_TTY   "/dev/tty"
+
+#else   // if defined _WIN32 || defined _WIN64
+
+#  include <fcntl.h>
+#  include <io.h>
+
+#  ifndef STDIN_FILENO
+#    define STDIN_FILENO  0
+#    define STDOUT_FILENO 1
+#    define STDERR_FILENO 2
+#  endif   // STDIN_FILENO
+
+#  define DEV_TTY   "CON:"
+
+#endif   // _WIN{32,64}
+
+
+// use buffers larger than L_tmpnam with rw_tmpnam()
+char stderr_fname [256];   // name of file to which stderr is redirected
+char stdout_fname [256];   // name of file to which stderr is redirected
+char stdio_fname  [256];   // same as above but for both stderr and stdout
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+test_file (const char* fname, const char* expect)
+{
+    std::FILE* fp = std::fopen (fname, "r");
+
+    if (!fp) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "fopen (\"%s\", \"r\") failed: %s",
+                   fname, std::strerror (errno));
+
+        return;
+    }
+
+    enum { bufsiz = 256 };
+    char buf [bufsiz] = { 0 };
+    std::fgets (buf, bufsiz, fp);
+
+    rw_assert (!std::strcmp (expect, buf), __FILE__, __LINE__,
+               "expected output: \"%s\", got: \"%s\"", expect, buf);
+
+    std::fclose (fp);
+}
+
+/**************************************************************************/
+
+static void
+do_test ()
+{
+    static const char stdout_expect[] = {
+        "[STDOUT_FILENO]"
+        "[cout,1][stdout,1][cout,2][stdout,2]"
+
+#ifndef _RWSTD_NO_WCHAR_T
+        "[wcout,1][stdout,3][wcout,2][stdout,4]"
+#endif   // _RWSTD_NO_WCHAR_T
+    };
+
+    static const char stderr_expect[] = {
+        "[STDERR_FILENO]"
+        "[cerr,1][stderr,1][cerr,2][stderr,2]"
+        "[clog,1][stderr,3][clog,2][stderr,4]"
+
+#ifndef _RWSTD_NO_WCHAR_T
+        "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+        "[wclog,1][stderr,7][wclog,2][stderr,8]"
+#endif   // _RWSTD_NO_WCHAR_T
+    };
+
+    static const char stdio_expect[] = {
+        "[STDOUT_FILENO][STDERR_FILENO]"
+        "[cout,1][stdout,1][cout,2]"   // no [stdout,2] here
+        "[cerr,1][stderr,1][cerr,2][stderr,2]"
+        "[clog,1][stderr,3][clog,2][stderr,4]"
+        "[stdout,2]"   // but [stdout,2] flushed here
+
+#ifndef _RWSTD_NO_WCHAR_T
+        "[wcout,1][stdout,3][wcout,2]"   // no [stdout,2] here
+        "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+        "[wclog,1][stderr,7][wclog,2][stderr,8]"
+        "[stdout,4]"   // but [stdout,2] flushed here
+#endif   // _RWSTD_NO_WCHAR_T
+    };
+
+    rw_info (0, __FILE__, __LINE__,
+             "ios_base::sync_with_stdio (true)");
+
+    // call not necessary, stdio synchronized by default
+    // std::ios_base::sync_with_stdio (true);
+
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved std::cout and stdout output");
+    test_file<char> (stdout_fname, stdout_expect);
+
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved std::cerr and stderr output");
+    test_file<char> (stderr_fname, stderr_expect);
+
+    rw_info (0, __FILE__, __LINE__,
+             "interleaved std::cout/cerr and stdout/stderr output");
+    test_file<char> (stdio_fname,  stdio_expect);
+}
+
+/**************************************************************************/
+
+static int
+redirect_to_file (const char* fname, int fd)
+{
+    static int fd_tty = open (DEV_TTY, O_WRONLY);
+
+    if (fd_tty < 0) {
+        std::fprintf (stderr,
+                      "open (\"" DEV_TTY "\", O_WRONLY) failed: %s\n",
+                      std::strerror (errno));
+
+        fd_tty = STDERR_FILENO;
+    }
+
+    char buf [1024];
+    int n;
+
+    // create a new file and redirect `fd' to it
+    const int fd_tmp =
+        open (fname, O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, 0666);
+
+    if (fd_tmp < 0) {
+        n = std::sprintf (buf,
+                          "open (\"%s\", O_WRONLY | O_CREAT | O_TRUNC, "
+                          "0666) failed: %s\n",
+                          fname, std::strerror (errno));
+        write (fd_tty, buf, n);
+        return -1;   // bail out after a critical error
+    }
+
+    const int fd2 = dup2 (fd_tmp, fd);
+
+    if (0 > fd2) {
+        n = std::sprintf (buf,
+                          "dup2 (%d, %d) failed: %s\n",
+                          fd2, fd, std::strerror (errno));
+        write (fd_tty, buf, n);
+        return -2;   // bail out after a critical error
+    }
+
+    if (fd2 != fd) {
+        n = std::sprintf (buf,
+                          "dup2 (%d, %d) != %d; got %d\n",
+                          fd_tmp, fd, fd, fd2);
+        // should never happen
+        write (fd_tty, buf, n);
+    }
+
+    if (close (fd_tmp)) {
+        n = std::sprintf (buf,
+                          "close (%d) failed: %s\n",
+                          fd_tmp, std::strerror (errno));
+        write (fd_tty, buf, n);
+        // proceed after a benign error
+    }
+
+    return fd2;
+}
+
+
+static int
+exec_stdout_setup ()
+{
+    // create a new file and redirect stdout to it
+    const int fd_stdout = redirect_to_file (stdout_fname, STDOUT_FILENO);
+
+    if (fd_stdout != STDOUT_FILENO)
+        return fd_stdout;
+
+    // expected output (w/o newlines):
+    //     "[STDOUT_FILENO]"
+    //     "[cout,1][stdout,1]"
+    //     "[cout,2][stdout,2]"
+    //     "[wcout,1][stdout,3]"
+    //     "[wcout,2][stdout,4]"
+
+    write (STDOUT_FILENO, "[STDOUT_FILENO]", 15);
+    std::cout << "[cout,1]";
+    std::printf ("[stdout,1]");
+    std::cout << "[cout,2]";      // flushes the printf() above
+    std::printf ("[stdout,2]");
+
+#ifndef _RWSTD_WCHAR_T
+
+    std::wcout << "[wcout,1]";    // flushes the printf() above
+    std::printf ("[stdout,3]");
+    std::wcout << "[wcout,2]";    // flushes the printf() above
+    std::printf ("[stdout,4]");   // flushed during termination
+
+#endif   // _RWSTD_WCHAR_T
+
+    return 0;
+}
+
+
+static int
+exec_stderr_setup ()
+{
+    // create a new file and redirect stderr to it
+    const int fd_stderr = redirect_to_file (stderr_fname, STDERR_FILENO);
+
+    if (fd_stderr != STDERR_FILENO)
+        return fd_stderr;
+
+    // expected output (w/o newlines):
+    //     "[STDERR_FILENO]"
+    //     "[cerr,1][stderr,1][cerr,2][stderr,2]"
+    //     "[clog,1][stderr,3][clog,2][stderr,4]"
+    //     "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+    //     "[wclog,1][stderr,7][wclog,2][stderr,8]"
+
+    write (STDERR_FILENO, "[STDERR_FILENO]", 15);
+    std::cerr << "[cerr,1]";
+    std::fprintf (stderr, "[stderr,1]");
+    std::cerr << "[cerr,2]";
+    std::fprintf (stderr, "[stderr,2]");
+    std::clog << "[clog,1]";
+    std::fprintf (stderr, "[stderr,3]");
+    std::clog << "[clog,2]";
+    std::fprintf (stderr, "[stderr,4]");
+
+#ifndef _RWSTD_WCHAR_T
+
+    std::wcerr << "[wcerr,1]";
+    std::fprintf (stderr, "[stderr,5]");
+    std::wcerr << "[wcerr,2]";
+    std::fprintf (stderr, "[stderr,6]");
+    std::wclog << "[wclog,1]";
+    std::fprintf (stderr, "[stderr,7]");
+    std::wclog << "[wclog,2]";
+    std::fprintf (stderr, "[stderr,8]");
+
+#endif   // _RWSTD_WCHAR_T
+
+    return 0;
+}
+
+
+static int
+exec_stdio_setup ()
+{
+    // create a new file and redirect both stdout and stderr to it
+    const int fd_stdout = redirect_to_file (stdio_fname, STDOUT_FILENO);
+    const int fd_stderr = redirect_to_file (stdio_fname, STDERR_FILENO);
+
+    if (fd_stdout != STDOUT_FILENO)
+        return fd_stdout;
+
+    if (fd_stderr != STDERR_FILENO)
+        return fd_stderr;
+
+    // expected output (w/o newlines):
+    //     "[STDOUT_FILENO][STDERR_FILENO]"
+    //     "[cout,1][stdout,1][cout,2]"
+    //     "[cerr,1][stderr,1][cerr,2][stderr,2]"
+    //     "[clog,1][stderr,3][clog,2][stderr,4]"
+    //     "[stdout,2]"
+    //     "[wcout,1][stdout,3][wcout,2]"
+    //     "[wcerr,1][stderr,5][wcerr,2][stderr,6]"
+    //     "[wclog,1][stderr,7][wclog,2][stderr,8]"
+    //     "[stdout,4]"
+
+    write (STDOUT_FILENO, "[STDOUT_FILENO]", 15);
+    write (STDERR_FILENO, "[STDERR_FILENO]", 15);
+
+    std::cout << "[cout,1]";
+    std::printf ("[stdout,1]");
+    std::cout << "[cout,2]";
+    std::printf ("[stdout,2]");    // flushed after STDERR output below
+
+    std::cerr << "[cerr,1]";
+    std::fprintf (stderr, "[stderr,1]");
+    std::cerr << "[cerr,2]";
+    std::fprintf (stderr, "[stderr,2]");
+    std::clog << "[clog,1]";
+    std::fprintf (stderr, "[stderr,3]");
+    std::clog << "[clog,2]";
+    std::fprintf (stderr, "[stderr,4]");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    std::wcout << "[wcout,1]";
+    std::printf ("[stdout,3]");
+    std::wcout << "[wcout,2]";
+    std::printf ("[stdout,4]");    // flushed after STDERR output below
+
+    std::wcerr << "[wcerr,1]";
+    std::fprintf (stderr, "[stderr,5]");
+    std::wcerr << "[wcerr,2]";
+    std::fprintf (stderr, "[stderr,6]");
+    std::wclog << "[wclog,1]";
+    std::fprintf (stderr, "[stderr,7]");
+    std::wclog << "[wclog,2]";
+    std::fprintf (stderr, "[stderr,8]");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+/**************************************************************************/
+
+struct cleanup
+{
+    int dummy;
+
+    ~cleanup () {
+        if (*stdout_fname)
+            std::remove (stdout_fname);
+        if (*stderr_fname)
+            std::remove (stderr_fname);
+        if (*stdio_fname)
+            std::remove (stdio_fname);
+    }
+};
+
+
+static int
+run_test (int /* unused */, char* /* unused */ [])
+{
+    const cleanup remove_tmp_files = { 0 };
+
+    // prevent unused warnings
+    (void)&remove_tmp_files;
+
+    if (!rw_tmpnam (stdout_fname)) {
+        std::fprintf (stderr,
+                      "rw_tmpnam (%p) failed: %s\n",
+                      stdout_fname, std::strerror (errno));
+        return 1;
+    }
+
+    if (!rw_tmpnam (stderr_fname)) {
+        std::fprintf (stderr,
+                      "rw_tmpnam (%p) failed: %s\n",
+                      stderr_fname, std::strerror (errno));
+        return 1;
+    }
+
+    if (!rw_tmpnam (stdio_fname)) {
+        std::fprintf (stderr,
+                      "rw_tmpnam (%p) failed: %s\n",
+                      stdio_fname, std::strerror (errno));
+        return 1;
+    }
+
+#if !defined (_WIN32) && !defined (_WIN64)
+
+    // create three child process and have each redirect
+    // its stdout, stderr, and both, respectively, to
+    // a file
+    // after all the children exit, the parent will check
+    // the contents of the file to determine whether all
+    // streams have been properly flushed and synchronized
+
+    for (int i = 0; i != 3; ++i) {
+        const pid_t child_pid = fork ();
+
+        if (child_pid < 0) {   // fork error
+
+            std::fprintf (stderr, "fork() failed: %s\n",
+                          std::strerror (errno));
+
+            return 1;
+        }
+        else if (child_pid > 0) {   // parent
+            wait (0);
+        }
+        else {   // child
+
+            int ret = 1;
+
+            switch (i) {
+            case 0: ret = exec_stderr_setup (); break;
+            case 1: ret = exec_stdout_setup (); break;
+            case 2: ret = exec_stdio_setup (); break;
+            }
+
+            // prevent child process from cleaning up files
+            *stdout_fname = *stderr_fname = *stdio_fname = '\0';
+            return ret;
+        }
+    }
+
+#endif   // _WIN{32,64}
+
+    do_test ();
+
+    return 0;
+}
+
+
+/* extern */ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.ios.members.static",
+                    "27.4.2.4 ios_base static members",
+                    run_test, "", 0);
+}
+
diff --git a/tests/iostream/27.istream.get.cpp b/tests/iostream/27.istream.get.cpp
new file mode 100644
index 0000000..806e586
--- /dev/null
+++ b/tests/iostream/27.istream.get.cpp
@@ -0,0 +1,170 @@
+/************************************************************************
+ *
+ * 27.istream.get.cpp - test exercising istream::get()
+ *
+ * $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 <fstream>
+#include <sstream>
+
+#include <cstdio>
+#include <cstring>
+
+#include <driver.h>
+
+
+template <class CharT, class FileStream>
+void test_get (FileStream &f, const char *type,
+                const CharT array [], std::size_t)
+{
+    rw_assert (!!f, 0, __LINE__, "basic_ifstream<%s, Traits>", type);
+
+    const CharT delim = f.widen ('\xff');
+
+    CharT buf [5] = { 0 };   // 4 chars + terminating null
+    const std::size_t bufsize = sizeof buf / sizeof *buf;
+
+    std::size_t n = 0;
+
+    // read chars into character buffer, at most 4 at a time
+    while (f.get (buf, bufsize, delim)) {
+        
+        rw_assert (f.good () && array [n] == *buf, 0, __LINE__,
+		   "%d. basic_ifstream<%s>::get (%p, %d, '\\x%x')",
+                   n, type, buf, bufsize, delim);
+
+        ++n;
+
+	CharT ch;
+	f.get (ch);
+
+        rw_assert (f.good () &&  ch == array [n], 0, __LINE__,
+		   "%d. basic_ifstream<%s>::get ('\\x%x'); expected '\\x%x'",
+                   n, type, ch, array [n]);
+	++n;
+    }
+
+    // reached the end of stream
+    rw_assert ((std::ios::eofbit | std::ios::failbit) == f.rdstate (),
+               0, __LINE__, "basic_ifstream<%s>::get(...)", type);
+}
+
+
+template <class CharT>
+void run_test (CharT, const char *tname)
+{
+    typedef CharT                       char_type;
+    typedef std::char_traits<char_type> traits_type;
+
+    CharT array [256];   // array of chars
+
+    const std::size_t nelems = sizeof array / sizeof *array;
+
+    // use tmpname(buffer) instead of tmpnam(0) because HP-UX returns 0
+    // for tmpnam (0) on MT environments
+    char fname [L_tmpnam];
+    std::tmpnam (fname);
+
+    rw_fatal (0 != fname, 0, __LINE__, "tmpnam(%#p) != 0", fname);
+
+    if (1) {
+        std::basic_ofstream<char_type, traits_type> f (fname);
+
+        rw_assert (!!f, 0, __LINE__,
+                   "basic_ofstream <%s>::basic_ofstream (#%s)",
+                    tname, fname);
+
+        // populate array with some chars with '\xff' interspersed
+
+        CharT *p = array;
+
+        for (std::size_t i = 0; std::size_t (i) < nelems / 2; ++i) {
+            *p++ = char_type (i + 1);
+
+            // separate each character with a `\xff'
+            *p++ = f.widen ('\xff');
+        }
+
+        // write array to stream in one shot
+        f.write (array, nelems);
+
+        rw_assert (f.good (), 0, __LINE__,
+                   "basic_ofstream<%s>::write (%p, %d)",
+                   tname, array, nelems);
+
+        f.close ();
+
+        rw_assert (f.good (), 0, __LINE__,
+                   "basic_ofstream<%s>::close()", tname);
+    }
+
+    if (1) {
+        std::basic_ifstream<char_type, traits_type> f (fname);
+
+        rw_assert (!!f, 0, __LINE__,
+                   "basic_ifstream<%s>::basic_ifstream (%#s)",
+                   tname, fname);
+
+        // see if we can read the whole thing in correctly
+        test_get  (f, tname, array, nelems);
+
+        // should have reached EOF above
+        rw_assert ((std::ios::eofbit | std::ios::failbit) == f.rdstate (),
+                   0, __LINE__,
+                   "basic_ifstream<%s>::get(...)", tname);
+
+        f.close ();
+
+        // successful close should have no effect on rdstate
+        rw_assert ((std::ios::eofbit | std::ios::failbit) == f.rdstate (),
+                   0, __LINE__,
+                   "basic_ifstream<%s>::get(...)", tname);
+    }
+
+    std::remove (fname);
+}
+
+
+static int run_test (int, char**)
+{
+    run_test (char (), "char");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    run_test (wchar_t (), "wchar_t");
+    
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "istream.get",
+                    0 /* no comment */,
+                    run_test,
+                    "", 0);
+}
diff --git a/tests/iostream/27.std.manip.cpp b/tests/iostream/27.std.manip.cpp
new file mode 100644
index 0000000..d071b3e
--- /dev/null
+++ b/tests/iostream/27.std.manip.cpp
@@ -0,0 +1,710 @@
+/***********************************************************************
+ *
+ * 27.std.manip.cpp - test exercising 27.6.3 - Standard manipulators
+ *
+ * $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.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ * 
+ **************************************************************************/
+
+#include <rw/_defs.h>
+
+#if !defined _MSC_VER || _MSC_VER > 1310
+
+   // disabled for MSVC to work around its innumerable bugs
+
+   // prevent the inclusion of non-essential public headers; only headers
+   // necessary to compile each header #included here are #included
+   // will produce errors if any templates defined in the header are
+   // instantiated without the names they use having been completely defined
+#  define _RWSTD_NO_REDUNDANT_DEFINITIONS
+
+   // prevent out-of-line template definitions in .cc files from being
+   // explicitly #included during the processing of library headers (faster
+   // compilation) assumes that the test doesn't instantiate those templates
+   // on types other than those they were explcitly instantiated on (will
+   // have no effect if explicit instantiation is disabled or unsupported)
+#  define _RWSTD_NO_TEMPLATE_DEFINITIONS
+#endif   // !defined _MSC_VER || _MSC_VER > 1310
+
+
+#include <climits>
+#include <iomanip>
+#include <istream>
+#include <ostream>
+#include <sstream>
+
+#include <driver.h>
+
+/***********************************************************************/
+
+// user-defined Traits type exercises the ability to instantiate
+// std::ws and any supporting templates on types other than the
+// default std::char_traits<charT>
+
+template <class charT>
+struct CharTraits: std::char_traits<charT> { /* empty */ };
+
+template < typename T >
+/*static*/ const char* type_name ();
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ const char*
+type_name< char > ()
+{
+    return "char";
+}
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ const char*
+type_name< std::char_traits<char> > ()
+{
+    return "std::char_traits<char>";
+}
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ const char*
+type_name< CharTraits<char> > ()
+{
+    return "CharTraits<char>";
+}
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ const char*
+type_name< wchar_t > ()
+{
+    return "wchar_t";
+}
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ const char*
+type_name< std::char_traits<wchar_t> > ()
+{
+    return "std::char_traits<wchar_t>";
+}
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ const char*
+type_name< CharTraits<wchar_t> > ()
+{
+    return "CharTraits<wchar_t>";
+}
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+/***********************************************************************/
+
+enum Manip {
+    resetiosflags,
+    setiosflags,
+    setbase,
+    setfill,
+    setprecision,
+    setw
+};
+
+
+template <class charT, class Traits>
+struct StreamBuf: std::basic_streambuf<charT, Traits> { /* empty */ };
+
+
+template <class charT, class Traits>
+static int
+test (int lineno, Manip m, int iarg, charT carg)
+{
+    static/*?*/ const char* const cname = type_name< charT > ();
+    static/*?*/ const char* const tname = type_name< Traits > ();
+
+    typedef std::ios_base::fmtflags            Fmtflags;
+    typedef std::basic_istream<charT, Traits>  Istream;
+    typedef std::basic_ostream<charT, Traits>  Ostream;
+    typedef std::basic_iostream<charT, Traits> IOstream;
+
+    StreamBuf<charT, Traits> sb;
+
+    // stream objects used to apply manipulators to
+    Istream  in1 (&sb);
+    Ostream  out1 (&sb);
+    IOstream inout1 (&sb);
+
+    // stream objects used to call member functions on
+    Istream  in2 (&sb);
+    Ostream  out2 (&sb);
+    IOstream inout2 (&sb);
+
+    int nfailed = 0;
+
+    switch (m) {
+
+    case resetiosflags: {   // exercise 27.6.3, p3
+
+        Istream &in3 = in1 >> std::resetiosflags (Fmtflags (iarg));
+        in2.setf (Fmtflags (0), Fmtflags (iarg));
+
+        if (in2.flags () != in3.flags ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "in >> std::resetiosflags(%{If}) with basic_istream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        Ostream &out3 = out1 << std::resetiosflags (Fmtflags (iarg));
+        out2.setf (Fmtflags (0), Fmtflags (iarg));
+
+        if (out2.flags () != out3.flags ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "out << std::resetiosflags(%{If}) with basic_ostream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        Ostream &inout3 = inout1 << std::resetiosflags (Fmtflags (iarg));
+        inout2.setf (Fmtflags (0), Fmtflags (iarg));
+
+        if (inout2.flags () != inout3.flags ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "io << std::resetiosflags(%{If}) with basic_iostream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        break;
+    }
+        
+    case setiosflags: {   // exercise 27.6.3, p3
+
+        Istream &in3 = in1 >> std::setiosflags (Fmtflags (iarg));
+        in2.setf (Fmtflags (iarg));
+
+        if (in2.flags () != in3.flags ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setiosflags (%s) with basic_istream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        Ostream &out3 = out1 << std::setiosflags (Fmtflags (iarg));
+        out2.setf (Fmtflags (iarg));
+
+        if (out2.flags () != out3.flags ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setiosflags (%s) with basic_ostream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        Ostream &inout3 = inout1 << std::setiosflags (Fmtflags (iarg));
+        inout2.setf (Fmtflags (iarg));
+
+        if (inout2.flags () != inout3.flags ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setiosflags (%s) with basic_iostream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        break;
+    }
+
+    case setbase: {   // exercise 27.6.3, p5
+
+        out1 << std::setbase (iarg);
+
+        if (0 == iarg || 2 == iarg || 8 == iarg || 10 ==iarg || 16 == iarg) {
+            out2.setf (   8 == iarg ? std::ios_base::oct
+#ifndef _RWSTD_NO_EXT_BIN_IO
+                          :  2 == iarg ? std::ios_base::bin
+#endif   // _RWSTD_NO_EXT_BIN_IO
+                          : 10 == iarg ? std::ios_base::dec
+                          : 16 == iarg ? std::ios_base::hex
+                          : Fmtflags (0),
+                            std::ios_base::basefield);
+
+            if (out1.flags () != out2.flags ()) {
+                ++nfailed;
+                rw_assert (0, __FILE__, lineno,
+                           "std::setbase (%d)", iarg);
+            }
+        }
+
+        std::basic_ostringstream<charT, std::char_traits<charT> > ostrm;
+
+        static const struct {
+            charT str[12];
+        } num[] = {
+            { { '1', '2', '3', '4', '\0' } },   // dec
+            { { 'm', 'c', 'c', 'x', 'x', 'x', 'i', 'v', '\0' } },   // roman
+            { { '1', '0', '0', '1', '1', '0', '1', '0', '0', '1', '0', '\0' } },
+            { { '1', '2', '0', '0', '2', '0', '1', '\0' } },   // 3
+            { { '1', '0', '3', '1', '0', '2', '\0' } },        // 4
+            { { '1', '4', '4', '1', '4', '\0' } },             // 5
+            { { '5', '4', '1', '4', '\0' } },   // 6
+            { { '3', '4', '1', '2', '\0' } },   // 7
+            { { '2', '3', '2', '2', '\0' } },   // oct
+            { { '1', '6', '2', '1', '\0' } },   // 9
+            { { '1', '2', '3', '4', '\0' } },   // dec
+            { { 'a', '2', '2', '\0' } },        // 11
+            { { '8', '6', 'a', '\0' } },        // 12
+            { { '7', '3', 'c', '\0' } },        // 13
+            { { '6', '4', '2', '\0' } },        // 14
+            { { '5', '7', '4', '\0' } },        // 15
+            { { '4', 'd', '2', '\0' } },        // hex
+            { { '4', '4', 'a', '\0' } },        // 17
+            { { '3', 'e', 'a', '\0' } },        // 18
+            { { '3', '7', 'i', '\0' } },        // 19
+            { { '3', '1', 'e', '\0' } },        // 20
+            { { '2', 'g', 'g', '\0' } },        // 21
+            { { '2', 'c', '2', '\0' } },        // 22
+            { { '2', '7', 'f', '\0' } },        // 23
+            { { '2', '3', 'a', '\0' } },        // 24
+            { { '1', 'o', '9', '\0' } },        // 25
+            { { '1', 'l', 'c', '\0' } },        // 26
+            { { '1', 'i', 'j', '\0' } },        // 27
+            { { '1', 'g', '2', '\0' } },        // 28
+            { { '1', 'd', 'g', '\0' } },        // 29
+            { { '1', 'b', '4', '\0' } },        // 30
+            { { '1', '8', 'p', '\0' } },        // 31
+            { { '1', '6', 'i', '\0' } },        // 32
+            { { '1', '4', 'd', '\0' } },        // 33
+            { { '1', '2', 'a', '\0' } },        // 34
+            { { '1', '0', '9', '\0' } },        // 35
+            { { 'y', 'a', '\0' } }              // 36
+        };
+
+        ostrm << std::setbase (iarg);
+        ostrm << 1234;
+
+        const int inx = iarg >= 0 && iarg <= 36 ? iarg : 0;
+
+        if (ostrm.str () != num [inx].str) {
+            ++nfailed;
+            rw_assert (0, __FILE__, __LINE__,
+                       "std::setbase (%d) inserted 1234 as \"%s\"; "
+                       "expected \"%s\"", iarg,
+                       ostrm.str ().data (), num [inx].str);
+        }
+
+        break;
+    }
+
+    case setfill: {   // exercise 27.6.3, p6
+        Istream &in3 = in1 >> std::setfill (carg);
+        in2.fill (carg);
+
+        if (in2.fill () != in3.fill ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "in >> std::setfill('%c') with basic_istream"
+                       "<%s, %s >", carg, cname, tname);
+        }
+
+        Ostream &out3 = out1 << std::setfill (carg);
+        out2.fill (carg);
+
+        if (out2.fill () != out3.fill ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "out << std::setfill('%c') with basic_ostream"
+                       "<%s, %s >", carg, cname, tname);
+        }
+
+        Ostream &inout3 = inout1 << std::setfill (carg);
+        inout2.fill (carg);
+
+        if (inout2.fill () != inout3.fill ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "io << std::setfill('%c') with basic_iostream"
+                       "<%s, %s >", carg, cname, tname);
+        }
+
+        break;
+    }
+
+    case setprecision: {   // exercise 27.6.3, p7
+
+        Istream &in3 = in1 >> std::setprecision (iarg);
+        in2.precision (std::streamsize (iarg));
+
+        if (in2.precision () != in3.precision ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setprecision (%d) with basic_istream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        Ostream &out3 = out1 << std::setprecision (iarg);
+        out2.precision (std::streamsize (iarg));
+
+        if (out2.precision () != out3.precision ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setprecision (%d) with basic_ostream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        Ostream &inout3 = inout1 << std::setprecision (iarg);
+        inout2.precision (std::streamsize (iarg));
+
+        if (inout2.precision () != inout3.precision ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setprecision (%d) with basic_iostream "
+                       "<%s, %s >", iarg, cname, tname);
+        }
+
+        break;
+    }
+
+    case setw: {   // exercise 27.6.3, p8
+
+        Istream &in3 = in1 >> std::setw (iarg);
+        in2.width (std::streamsize (iarg));
+
+        if (in2.width () != in3.width ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setw (%d) with basic_istream<%s, %s >",
+                       iarg, cname, tname);
+        }
+
+        Ostream &out3 = out1 << std::setw (iarg);
+        out2.width (std::streamsize (iarg));
+
+        if (out2.width () != out3.width ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setw (%d) with basic_ostream<%s, %s >",
+                       iarg, cname, tname);
+        }
+
+        Ostream &inout3 = inout1 << std::setw (iarg);
+        inout2.width (std::streamsize (iarg));
+
+        if (inout2.width () != inout3.width ()) {
+            ++nfailed;
+            rw_assert (0, __FILE__, lineno,
+                       "std::setw (%d) with basic_iostream<%s, %s >",
+                       iarg, cname, tname);
+        }
+
+        break;
+    }
+
+    }
+
+    return nfailed;
+}
+
+/***********************************************************************/
+
+// for convenience
+#define Boolalpha   std::ios_base::boolalpha
+#define Dec         std::ios_base::dec
+#define Fixed       std::ios_base::fixed
+#define Hex         std::ios_base::hex
+#define Internal    std::ios_base::internal
+#define Left        std::ios_base::left
+#define Oct         std::ios_base::oct
+#define Right       std::ios_base::right
+#define Scientific  std::ios_base::scientific
+#define Showbase    std::ios_base::showbase
+#define Showpoint   std::ios_base::showpoint
+#define Showpos     std::ios_base::showpos
+#define Skipws      std::ios_base::skipws
+#define Unitbuf     std::ios_base::unitbuf
+#define Uppercase   std::ios_base::uppercase
+#define Bin         std::ios_base::bin
+#define Adjustfield std::ios_base::adjustfield
+#define Basefield   std::ios_base::basefield
+#define Floatfield  std::ios_base::floatfield
+#define Nolock      std::ios_base::nolock
+#define Nolockbuf   std::ios_base::nolockbuf
+
+
+template <class charT, class Traits>
+static void do_test ()
+{
+#define TEST(M, V, C) \
+    ++ntried; nfailed += test< charT, Traits > (__LINE__, M, V, C)
+
+    int ntried  = 0;
+    int nfailed = 0;
+
+    /////////////////////////////////////////////////////////////////////
+    // exercise std::resetiosflags
+
+    const char* const cname = type_name< charT > ();
+    const char* const tname = type_name< Traits > ();
+
+    rw_info (0, __FILE__, __LINE__,
+             "27.6.3, p3 - std::resetiosflags(ios_base::"
+             "fmtflags) with basic_{i,o,io}stream<%s, %s >",
+             cname, tname);
+
+    TEST (resetiosflags, Boolalpha, charT ());
+    TEST (resetiosflags, Dec, charT ());
+    TEST (resetiosflags, Fixed, charT ());
+    TEST (resetiosflags, Hex, charT ());
+    TEST (resetiosflags, Internal, charT ());
+    TEST (resetiosflags, Left, charT ());
+    TEST (resetiosflags, Oct, charT ());
+    TEST (resetiosflags, Right, charT ());
+    TEST (resetiosflags, Scientific, charT ());
+    TEST (resetiosflags, Showbase, charT ());
+    TEST (resetiosflags, Showpoint, charT ());
+    TEST (resetiosflags, Showpos, charT ());
+    TEST (resetiosflags, Skipws, charT ());
+    TEST (resetiosflags, Unitbuf, charT ());
+    TEST (resetiosflags, Uppercase, charT ());
+
+#ifndef _RWSTD_NO_EXT_BIN_IO
+
+    TEST (resetiosflags, Bin, charT ());
+
+#endif   // _RWSTD_NO_EXT_BIN_IO
+
+    TEST (resetiosflags, Adjustfield, charT ());
+    TEST (resetiosflags, Basefield, charT ());
+    TEST (resetiosflags, Floatfield, charT ());
+
+#ifndef _RWSTD_NO_EXT_REENTRANT_IO
+
+    TEST (resetiosflags, Nolock, charT ());
+    TEST (resetiosflags, Nolockbuf, charT ());
+
+#endif   // _RWSTD_NO_EXT_REENTRANT_IO
+
+
+    TEST (resetiosflags, Oct | Dec,       charT ());
+    TEST (resetiosflags, Oct | Hex,       charT ());
+    TEST (resetiosflags, Dec | Hex,       charT ());
+    TEST (resetiosflags, Oct | Dec | Hex, charT ());
+    
+    TEST (resetiosflags, Left | Internal,         charT ());
+    TEST (resetiosflags, Left | Right,            charT ());
+    TEST (resetiosflags, Right | Internal,        charT ());
+    TEST (resetiosflags, Left | Right | Internal, charT ());
+
+    TEST (resetiosflags, Showbase | Showpoint,           charT ());
+    TEST (resetiosflags, Showbase | Showpos,             charT ());
+    TEST (resetiosflags, Showbase | Showpoint | Showpos, charT ());
+
+    if (!nfailed)
+        rw_assert (true, __FILE__, __LINE__,
+                   "std::resetiosflags failed %d out "
+                   "of %d assertions", nfailed, ntried);
+
+    /////////////////////////////////////////////////////////////////////
+    // exercise std::setiosflags
+
+    rw_info (0, __FILE__, __LINE__,
+             "27.6.3, p4 - std::setiosflags(ios_base::"
+             "fmtflags) with basic_{i,o,io}stream<%s, %s >",
+             cname, tname);
+
+    ntried = nfailed = 0;
+
+    TEST (setiosflags, Boolalpha, charT ());
+    TEST (setiosflags, Dec, charT ());
+    TEST (setiosflags, Fixed, charT ());
+    TEST (setiosflags, Hex, charT ());
+    TEST (setiosflags, Internal, charT ());
+    TEST (setiosflags, Left, charT ());
+    TEST (setiosflags, Oct, charT ());
+    TEST (setiosflags, Right, charT ());
+    TEST (setiosflags, Scientific, charT ());
+    TEST (setiosflags, Showbase, charT ());
+    TEST (setiosflags, Showpoint, charT ());
+    TEST (setiosflags, Showpos, charT ());
+    TEST (setiosflags, Skipws, charT ());
+    TEST (setiosflags, Unitbuf, charT ());
+    TEST (setiosflags, Uppercase, charT ());
+
+#ifndef _RWSTD_NO_EXT_BIN_IO
+
+    TEST (setiosflags, Bin, charT ());
+
+#endif   // _RWSTD_NO_EXT_BIN_IO
+
+    TEST (setiosflags, Adjustfield, charT ());
+    TEST (setiosflags, Basefield, charT ());
+    TEST (setiosflags, Floatfield, charT ());
+    TEST (setiosflags, Nolock, charT ());
+    TEST (setiosflags, Nolockbuf, charT ());
+
+    if (!nfailed)
+        rw_assert (true, __FILE__, __LINE__,
+                   "std::setiosflags failed %d out "
+                   "of %d assertions", nfailed, ntried);
+
+    /////////////////////////////////////////////////////////////////////
+    // exercise std::setbase
+
+    rw_info (0, __FILE__, __LINE__,
+             "27.6.3, p5 - std::setbase(int) with "
+             "basic_{i,o,io}stream<%s, %s >", cname, tname);
+
+    ntried = nfailed = 0;
+
+    TEST (setbase,  0, charT ());
+    TEST (setbase,  8, charT ());
+    TEST (setbase, 10, charT ());
+    TEST (setbase, 16, charT ());
+
+#ifndef _RWSTD_NO_EXT_BIN_IO
+
+    TEST (setbase, 2, charT ());
+
+#endif   // _RWSTD_NO_EXT_BIN_IO
+
+#ifndef _RWSTD_NO_EXT_SETBASE
+
+    TEST (setbase,  0, charT ());   // autodetect
+    TEST (setbase,  1, charT ());   // roman
+    TEST (setbase,  2, charT ());   // bin
+    TEST (setbase,  3, charT ());
+    TEST (setbase,  4, charT ());
+    TEST (setbase,  5, charT ());
+    TEST (setbase,  6, charT ());
+    TEST (setbase,  7, charT ());
+    TEST (setbase,  8, charT ());   // oct
+    TEST (setbase,  9, charT ());
+    TEST (setbase, 10, charT ());   // dec
+    TEST (setbase, 11, charT ());
+    TEST (setbase, 12, charT ());
+    TEST (setbase, 16, charT ());   // hex
+    TEST (setbase, 17, charT ());
+    TEST (setbase, 36, charT ());   // 0-9, a-z
+    TEST (setbase, -1, charT ());
+    TEST (setbase, -2, charT ());
+
+#endif   // _RWSTD_NO_EXT_SETBASE
+
+    if (!nfailed)
+        rw_assert (true, __FILE__, __LINE__,
+                   "std::setbase failed %d out "
+                   "of %d assertions", nfailed, ntried);
+
+    /////////////////////////////////////////////////////////////////////
+    // exercise std::setfill
+
+    rw_info (0, __FILE__, __LINE__,
+             "27.6.3, p6 - std::setfill(%s) with "
+             "basic_{i,o,io}stream<%s, %s >", cname, cname, tname);
+
+    ntried = nfailed = 0;
+
+    TEST (setfill, 0, charT ('\0'));
+    TEST (setfill, 0, charT ('\a'));
+    TEST (setfill, 0, charT ('\n'));
+    TEST (setfill, 0, charT ('\r'));
+    TEST (setfill, 0, charT ('\t'));
+    TEST (setfill, 0, charT ('\v'));
+    TEST (setfill, 0, charT (' '));
+    TEST (setfill, 0, charT ('*'));
+    TEST (setfill, 0, charT ('#'));
+
+    if (!nfailed)
+        rw_assert (true, __FILE__, __LINE__,
+                   "std::setfill failed %d out "
+                   "of %d assertions", nfailed, ntried);
+    
+    /////////////////////////////////////////////////////////////////////
+    // exercise std::setprecision
+
+    rw_info (0, __FILE__, __LINE__,
+             "27.6.3, p7 - std::setprecision(int) with "
+             "basic_{i,o,io}stream<%s, %s >", cname, tname);
+
+    ntried = nfailed = 0;
+
+    TEST (setprecision, 0,         charT ());
+    TEST (setprecision, 1,         charT ());
+    TEST (setprecision, 2,         charT ());
+    TEST (setprecision, SHRT_MAX,  charT ());
+    TEST (setprecision, INT_MAX,   charT ());
+    TEST (setprecision, -1,        charT ());
+    TEST (setprecision, -2,        charT ());
+    TEST (setprecision, SHRT_MIN,  charT ());
+    TEST (setprecision, INT_MIN,   charT ());
+
+    if (!nfailed)
+        rw_assert (true, __FILE__, __LINE__,
+                   "std::setprecision failed %d out "
+                   "of %d assertions", nfailed, ntried);
+
+    /////////////////////////////////////////////////////////////////////
+    // exercise std::setw
+
+    rw_info (0, __FILE__, __LINE__,
+             "27.6.3, p8 - std::setw(int) with "
+             "basic_{i,o,io}stream<%s, %s >", cname, tname);
+
+    ntried = nfailed = 0;
+
+    TEST (setw, 0,         charT ());
+    TEST (setw, 1,         charT ());
+    TEST (setw, 2,         charT ());
+    TEST (setw, SHRT_MAX,  charT ());
+    TEST (setw, INT_MAX,   charT ());
+    TEST (setw, -1,        charT ());
+    TEST (setw, -2,        charT ());
+    TEST (setw, SHRT_MIN,  charT ());
+    TEST (setw, INT_MIN,   charT ());
+
+    if (!nfailed)
+        rw_assert (true, __FILE__, __LINE__,
+                   "std::setw failed %d out "
+                   "of %d assertions", nfailed, ntried);
+}
+
+/***********************************************************************/
+
+static int
+run_test (int /*argc*/, char* /*argv*/ [])
+{
+    do_test<char, std::char_traits<char> > ();
+    do_test<char, CharTraits<char> > ();
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    do_test<wchar_t, std::char_traits<wchar_t> > ();
+    do_test<wchar_t, CharTraits<wchar_t> > ();
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+
+/*extern*/ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "[lib.std.manip]",
+                    "27.6.3 Standard manipulators",
+                    run_test, "", 0);
+}
+
diff --git a/tests/localization/22.locale.codecvt.cpp b/tests/localization/22.locale.codecvt.cpp
new file mode 100644
index 0000000..cdb192a
--- /dev/null
+++ b/tests/localization/22.locale.codecvt.cpp
@@ -0,0 +1,2610 @@
+/***************************************************************************
+ *
+ * 22.locale.codecvt.cpp - test exercising the std::codecvt<> facets
+ *
+ * $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.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ *
+ **************************************************************************/
+
+#ifdef __SUNPRO_CC
+    // working around a SunPro/SunOS 5.8 bug (PR #26255)
+#  include <time.h>
+#endif   // __SUNPRO_CC
+
+#include <locale>
+
+#include <cassert>
+#include <climits>
+#include <clocale>
+#include <csetjmp>   // for longjmp(), setjmp(), ...
+#include <csignal>   // for SIGABRT, signal()
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cwchar>    // for mbstate_t
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef _MSC_VER
+#  include <iconv.h>      // for iconv(), iconv_open(), iconv_close()
+#  include <langinfo.h>   // for CODESET, nl_langinfo()
+#  include <unistd.h>
+#else
+#  include <direct.h>
+#endif
+
+#define DEFINE_REPLACEMENT_NEW_AND_DELETE
+#include <driver.h>
+#include <file.h>
+#include <rw_locale.h>
+
+#ifndef PATH_MAX
+#  define PATH_MAX 1024
+#endif
+
+// No dependency on C library min/max
+#undef min
+#define min(a, b)   ((a) < (b) ? (a) : (b))
+
+/****************************************************************************/
+
+// mbs/wcs helper functions
+#if !defined _RWSTD_NO_WCHAR_T
+
+template <class T>
+/*static*/ std::size_t
+rwtest_mbstowcs (std::mbstate_t& state, T* pi,
+                 const char* pe, std::size_t srclen)
+{
+#  ifndef _RWSTD_NO_MBSRTOWCS
+
+    return std::mbsrtowcs (pi, &pe, srclen, &state);
+
+#  else   // if defined _RWSTD_NO_MBSRTOWCS
+
+    _RWSTD_UNUSED (state);
+    return std::mbstowcs (pi, pe, srclen);
+
+#  endif   // _RWSTD_NO_MBSRTOWCS
+}
+
+
+_RWSTD_SPECIALIZED_FUNCTION
+/*static*/ std::size_t
+rwtest_mbstowcs<char> (std::mbstate_t& /*unused*/, char* /*unused*/,
+                       const char* /*unused*/, std::size_t /*unused*/)
+{
+    return 0;
+}
+
+template <class charT>
+inline std::size_t
+rwtest_wcstombs (std::mbstate_t& state, const charT* pi,
+                 char* pe, std::size_t srclen)
+{
+#  ifndef _RWSTD_NO_WCSRTOMBS
+
+    return std::wcsrtombs (pe, &pi, srclen, &state);
+
+#  else   // if defined _RWSTD_NO_WCSRTOMBS)
+
+    _RWSTD_UNUSED (state);
+    return std::wcstombs (pe, pi, srclen);
+
+#  endif   // _RWSTD_NO_WCSRTOMBS
+}
+
+_RWSTD_SPECIALIZED_FUNCTION
+inline std::size_t
+rwtest_wcstombs<char>(std::mbstate_t& /*unused*/, const char* /*unused*/,
+                      char* /*unused*/, std::size_t /*unused*/)
+{
+    return 0;
+}
+
+#endif // !defined _RWSTD_NO_WCHAR_T
+
+
+static std::size_t
+rwtest_mbslen (std::mbstate_t& state,
+               const char*     pe,
+               const char*     limit,
+               std::size_t     cmax)
+{
+    std::size_t total = 0;
+    std::size_t ret   = 0;
+
+    while (total < cmax && pe < limit)
+    {
+#ifndef _RWSTD_NO_MBRLEN
+
+        ret = std::mbrlen (pe, min (_RWSTD_MB_LEN_MAX, limit - pe), &state);
+
+#else   // if defined _RWSTD_NO_MBRLEN
+
+        _RWSTD_UNUSED (state);
+        ret = std::mblen (pe, min (_RWSTD_MB_LEN_MAX, limit - pe));
+
+#endif   // _RWSTD_NO_MBRLEN
+
+        if (ret >= std::size_t (-2))
+            break;
+
+        pe += ret;
+        ++total;
+    }
+
+    return total;
+}
+
+/****************************************************************************/
+
+// The codecvt facets and their required specializations
+typedef std::codecvt_base::result                         CodecvtResult;
+typedef std::codecvt<char,char,std::mbstate_t>            Codecvt;
+typedef std::codecvt_byname<char,char,std::mbstate_t>     CodecvtBn;
+
+#ifndef _RWSTD_NO_WCHAR_T
+typedef std::codecvt<wchar_t,char,std::mbstate_t>         CodecvtW;
+typedef std::codecvt_byname<wchar_t,char,std::mbstate_t>  CodecvtBnW;
+#endif   // _RWSTD_NO_WCHAR_T
+
+
+// Type names used in assertion messages
+template <class T>
+struct TypeName
+{
+    static const char* name;
+};
+
+_RWSTD_SPECIALIZED_CLASS const char*
+TypeName<char>::name = "char";
+
+_RWSTD_SPECIALIZED_CLASS const char*
+TypeName<Codecvt>::name = "std::codecvt<char, char, std::mbstate_t>";
+
+_RWSTD_SPECIALIZED_CLASS const char*
+TypeName<CodecvtBn>::name = "std::codecvt_byname<char, char, std::mbstate_t>";
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+_RWSTD_SPECIALIZED_CLASS const char*
+TypeName<wchar_t>::name = "wchar_t";
+
+_RWSTD_SPECIALIZED_CLASS const char*
+TypeName<CodecvtW>::name = "std::codecvt<wchar_t, char, std::mbstate_t>";
+
+_RWSTD_SPECIALIZED_CLASS const char*
+TypeName<CodecvtBnW>::name =
+    "std::codecvt_byname<wchar_t, char, std::mbstate_t>";
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+/****************************************************************************/
+
+// bitmasks for calls to virtual functions
+enum {
+    dtor                = 1 << 0,
+    do_out              = 1 << 1,
+    do_in               = 1 << 2,
+    do_unshift          = 1 << 3,
+    do_encoding         = 1 << 4,
+    do_always_noconv    = 1 << 5,
+    do_length           = 1 << 6,
+    do_max_length       = 1 << 7
+};
+
+// bitset for all virtual function calls
+int call = 0;
+
+// template class for testing virtual calls
+template <class Base>
+struct CodecvtDerived: Base
+{
+    typedef Base                                base_type;
+    typedef typename base_type::intern_type     itype;
+    typedef typename base_type::extern_type     etype;
+    typedef typename base_type::state_type      stype;
+    typedef typename std::codecvt_base::result  result;
+
+    CodecvtDerived (const char*);
+
+    virtual ~CodecvtDerived () {
+        call |= ::dtor;
+    }
+
+    result
+    do_out (stype&, const itype*, const itype*, const itype*&,
+            etype*, etype*, etype*&) const {
+        call |= ::do_out;
+        return result ();
+    }
+
+    result
+    do_in (stype&, const etype*, const etype*, const etype*&,
+           itype*, itype*, itype*&) const {
+        call |= ::do_in;
+        return result ();
+    }
+
+    result
+    do_unshift (stype&, etype*, etype*, etype*&) const {
+        call |= ::do_unshift;
+        return result ();
+    }
+
+    int do_encoding () const _THROWS (()) {
+        call |= ::do_encoding;
+        return 0;
+    }
+
+    bool do_always_noconv () const _THROWS (()) {
+        call |= ::do_always_noconv;
+        return false;
+    }
+
+    int do_length (stype&, const etype*, const etype*,
+                           std::size_t) const {
+        call |= ::do_length;
+        return 0;
+    }
+
+    int do_max_length () const _THROWS (()) {
+        call |= ::do_max_length;
+        return 0;
+    }
+};
+
+
+// specialization for the class constructor in CodecvtDerived
+_RWSTD_SPECIALIZED_CLASS
+CodecvtDerived<Codecvt>::CodecvtDerived (const char* /*unused*/)
+    : Codecvt () { }
+
+_RWSTD_SPECIALIZED_CLASS
+CodecvtDerived<CodecvtBn>::CodecvtDerived (const char* name)
+    : CodecvtBn (name) { }
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+_RWSTD_SPECIALIZED_CLASS
+CodecvtDerived<CodecvtW>::CodecvtDerived (const char* /*unused*/)
+    : CodecvtW () { }
+
+_RWSTD_SPECIALIZED_CLASS
+CodecvtDerived<CodecvtBnW>::CodecvtDerived (const char* name)
+    : CodecvtBnW (name) { }
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+
+//  Tests the call of virtual member functions in codecvt facets
+template <class CodeCvtT>
+static void
+test_virtuals (const char* locale_name)
+{
+    rw_info (0, __FILE__, __LINE__,
+             "%s virtual functions", TypeName<CodeCvtT>::name);
+
+    CodecvtDerived<CodeCvtT> pccvt (locale_name);
+    CodeCvtT& cc = pccvt;
+
+    typedef typename CodeCvtT::intern_type intern_type;
+    typedef typename CodeCvtT::extern_type extern_type;
+
+    const extern_type* pce = 0;
+    extern_type*       pe  = 0;
+    const intern_type* pci = 0;
+    intern_type*       pi  = 0;
+
+    std::mbstate_t st = std::mbstate_t ();
+
+    // verify 22.2.1.5.1, p1
+    cc.out (st, pci, pci, pci, pe, pe, pe );
+    rw_assert ((call & do_out) != 0, __FILE__, __LINE__,
+               "%s::do_out call failed.",  TypeName<CodeCvtT>::name);
+
+    // verify 22.2.1.5.1, p2
+    cc.in (st, pce, pce, pce, pi, pi, pi );
+    rw_assert ((call & do_in) != 0, __FILE__, __LINE__,
+               "%s::do_in call failed.",  TypeName<CodeCvtT>::name);
+
+    // verify 22.2.1.5.1, p3
+    cc.unshift (st, pe, pe, pe);
+    rw_assert ((call & do_unshift) != 0, __FILE__, __LINE__,
+               "%s::do_unshift call failed.",  TypeName<CodeCvtT>::name);
+
+    // verify 22.2.1.5.1, p4
+    cc.encoding ();
+    rw_assert ((call & do_encoding) != 0, __FILE__, __LINE__,
+               "%s::do_encoding call failed.",  TypeName<CodeCvtT>::name);
+
+    // verify 22.2.1.5.1, p5
+    cc.always_noconv ();
+    rw_assert ((call & do_always_noconv) != 0, __FILE__, __LINE__,
+               "%s::do_always_noconv call failed.",  TypeName<CodeCvtT>::name);
+
+    // verify 22.2.1.5.1, p6
+    cc.length (st, pce, pce, 0);
+    rw_assert ((call & do_length) != 0, __FILE__, __LINE__,
+               "%s::do_length call failed.",  TypeName<CodeCvtT>::name);
+
+    // verify 22.2.1.5.1, p7
+    cc.max_length ();
+    rw_assert ((call & do_max_length) != 0, __FILE__, __LINE__,
+               "%s::do_max_length call failed.",  TypeName<CodeCvtT>::name);
+}
+
+/****************************************************************************/
+
+const Codecvt& create_Codecvt (const std::locale&)
+{
+    static Codecvt cc;
+    return cc;
+}
+
+const CodecvtBn& create_CodecvtBn (const std::locale& loc)
+{
+    return _STD_USE_FACET (CodecvtBn, loc);
+}
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+const CodecvtW& create_CodecvtW (const std::locale&)
+{
+    static CodecvtW cc;
+    return cc;
+}
+
+const CodecvtBnW& create_CodecvtBnW (const std::locale& loc)
+{
+    return _STD_USE_FACET (CodecvtBnW, loc);
+}
+
+#endif // !defined _RWSTD_NO_WCHAR_T
+
+
+// facet operations results
+static const char*
+rwtest_codecvt_result (int res)
+{
+    // allow the function to be called up to 8 times in the same expression
+    // without overwriting the static buffer (each call will return a pointer
+    // to a new array)
+    static char buf [8][16];
+
+    static std::size_t index;
+
+    std::size_t inx = index;
+
+    index = (index + 1) % sizeof buf / sizeof *buf;
+
+    std::sprintf (buf [inx], "%#x", res);
+
+    return buf [inx];
+}
+
+static const char*
+rwtest_codecvt_result (CodecvtResult res)
+{
+    static const struct {
+        CodecvtResult res;
+        const char*   str;
+    } results [] = {
+        { std::codecvt_base::ok,      "std::codecvt_base::ok" },
+        { std::codecvt_base::partial, "std::codecvt_base::partial" },
+        { std::codecvt_base::noconv,  "std::codecvt_base::noconv" },
+        { std::codecvt_base::error,   "std::codecvt_base::error" }
+    };
+
+    for (unsigned i = 0; i != sizeof results / sizeof *results; ++i)
+        if (res == results [i].res)
+            return results [i].str;
+
+    return rwtest_codecvt_result (int (res));
+}
+
+/****************************************************************************/
+
+static bool
+rwtest_is_C_locale (const char* s)
+{
+    const char* old = std::setlocale (LC_ALL, s);
+    if (old == 0)
+        return false;
+
+    std::setlocale (LC_ALL, old);
+    return true;
+}
+
+/****************************************************************************/
+
+// Test custom locales, built on the fly
+template <class CodeCvtT>
+static void
+test_libstd_do_in (const char* locale_name, const CodeCvtT& cc,
+                   const typename CodeCvtT::extern_type*  buffe,
+                   typename CodeCvtT::intern_type*& buffi,
+                   std::size_t sze, std::size_t& szi,
+                   bool skip_C,
+                   CodecvtResult& res, std::size_t& sz)
+{
+    // buffers types
+    typedef typename CodeCvtT::intern_type      intern_t;
+    typedef typename CodeCvtT::extern_type      extern_t;
+
+    const extern_t* pe   = buffe;
+    const extern_t* pen  = buffe;
+    const extern_t* pe_limit = buffe + sze;
+
+    szi = sze;
+    buffi = new intern_t [szi];
+    std::memset (buffi, 0, szi * sizeof (intern_t));
+
+    intern_t* pi  = buffi;
+    intern_t* pin = pi;
+    intern_t* pi_limit = pi + sze;
+
+    // the state
+    std::mbstate_t state = std::mbstate_t ();
+
+    // do the conversion and store results
+    res = cc.in ( state, pe, pe_limit, pen, pi, pi_limit, pin );
+    szi = sz = pin - pi;
+
+    // if C library locale is available, then perform conversion and
+    // compare the results
+    if (skip_C || std::setlocale (LC_CTYPE, locale_name) == 0)
+        return;
+
+    intern_t* C_buffer = new intern_t [sze];
+    std::memset (C_buffer, 0, sze * sizeof (intern_t));
+
+    intern_t* C_pi = C_buffer;
+
+    std::mbstate_t C_state = std::mbstate_t ();
+
+    pen = pe;
+    std::size_t C_res =
+        rwtest_mbstowcs<intern_t> (C_state, C_pi, pen, sze);
+    if (res != std::codecvt_base::ok || C_res == std::size_t(-1)) {
+        delete [] C_buffer;
+        return;
+    }
+
+    // test against C library results - length and content
+    rw_assert (C_res == std::size_t(pin - pi), __FILE__, __LINE__,
+               "(%s) %s::do_in Clib length check:\n"
+               "  C   library conversion size : %d\n"
+               "  std library conversion size : %d\n",
+               locale_name, TypeName<CodeCvtT>::name, C_res, pin - pi);
+
+    rw_assert (0 == std::memcmp (pi, C_pi, C_res), __FILE__, __LINE__,
+               "(%s) %s::do_in data check failed against C library conversion",
+               locale_name, TypeName<CodeCvtT>::name);
+
+    // clean up the allocations
+    delete [] C_buffer;
+}
+
+#define CCVT_MAX_LOCALE     5    // Max. number of locale to test
+#define CCVT_MB_CUR_MIN     1    // Minimum and maximum no. of
+#define CCVT_MB_CUR_MAX     6    // bytes per character
+
+template <class CodeCvtT>
+static void
+test_libstd_do_out (const char* locale_name, const CodeCvtT& cc,
+                    typename CodeCvtT::extern_type*& buffe,
+                    const typename CodeCvtT::intern_type* buffi,
+                    std::size_t& sze, std::size_t szi,
+                    bool skip_C,
+                    CodecvtResult& res, std::size_t& sz)
+{
+    // buffers types
+    typedef typename CodeCvtT::intern_type      intern_t;
+    typedef typename CodeCvtT::extern_type      extern_t;
+
+    // the state
+    std::mbstate_t state = std::mbstate_t ();
+
+    buffe = new extern_t [CCVT_MB_CUR_MAX * szi];
+    std::memset (buffe, 0, CCVT_MB_CUR_MAX * szi);
+    extern_t* pe  = buffe;
+    extern_t* pen = pe;
+    extern_t* pe_limit = pe + CCVT_MB_CUR_MAX * szi;
+
+    const intern_t* pi  = buffi;
+    const intern_t* pin = buffi;
+    const intern_t* pi_limit = pi + szi;
+
+    // perform the conversion
+    res = cc.out ( state, pi, pi_limit, pin, pe, pe_limit, pen );
+    sze = sz = pen - pe;
+
+    if (skip_C || std::setlocale (LC_CTYPE, locale_name) == 0) {
+        return;
+    }
+
+    extern_t* C_buffer = new extern_t [CCVT_MB_CUR_MAX * szi];
+    std::memset (C_buffer, 0, CCVT_MB_CUR_MAX * szi);
+    extern_t* C_pe = C_buffer;
+
+    std::mbstate_t C_state = std::mbstate_t ();
+
+    std::size_t C_res =
+        rwtest_wcstombs<intern_t> (C_state, pi, C_pe, CCVT_MB_CUR_MAX * szi);
+    if (C_res == std::size_t(-1)) {
+        delete [] C_buffer;
+        return;
+    }
+
+    // test results against C library
+    rw_assert (C_res == std::size_t(pen - pe), __FILE__, __LINE__,
+               "(%s) %s::do_out Clib length check\n"
+               "    C   library conversion size : %d\n"
+               "    std library conversion size : %d\n",
+               locale_name, TypeName<CodecvtBnW>::name,
+               C_res, (pen - pe));
+
+    rw_assert (0 == std::memcmp (pe, C_pe, C_res), __FILE__, __LINE__,
+               "(%s) %s::do_out Clib data check failed "
+               "against C library conversion",
+               locale_name, TypeName<CodecvtBnW>::name);
+
+    delete [] C_buffer;
+}
+
+template <class CodeCvtT>
+static void
+test_libstd_do_unshift (const CodeCvtT& cc,
+                        std::mbstate_t& state,
+                        typename CodeCvtT::extern_type* buffe,
+                        std::size_t& sze,
+                        CodecvtResult& res)
+{
+    // buffers types
+    typedef typename CodeCvtT::intern_type      intern_t;
+    typedef typename CodeCvtT::extern_type      extern_t;
+
+    extern_t* pe  = buffe;
+    extern_t* pen = buffe;
+    extern_t* pe_limit = buffe + sze;
+
+    res = cc.unshift (state, pe, pe_limit, pen);
+    sze = pen - pe;
+}
+
+template <class CodeCvtT>
+static void
+test_libstd_do_always_noconv (const CodeCvtT& cc, bool& res)
+{
+    res = cc.always_noconv ();
+}
+
+// check do_max_length operation in facet
+template <class CodeCvtT>
+static void
+test_libstd_do_max_length (const CodeCvtT& cc, std::size_t& res )
+{
+    res = cc.max_length ();
+}
+
+// check do_length operation in facet
+template <class CodeCvtT>
+static void
+test_libstd_do_length (const char* locale_name, const CodeCvtT& cc,
+                       const typename CodeCvtT::extern_type* buffe,
+                       std::size_t& sze, bool skip_C)
+{
+    // buffers types
+    typedef CodecvtBnW::intern_type     intern_t;
+    typedef CodecvtBnW::extern_type     extern_t;
+
+    // the state
+    std::mbstate_t state = std::mbstate_t ();
+
+    extern_t* pe       = _RWSTD_CONST_CAST(extern_t*, buffe);
+    extern_t* pe_limit = _RWSTD_CONST_CAST(extern_t*, buffe + sze);
+
+    sze = cc.length ( state, pe, pe_limit, sze );
+
+    if (skip_C)
+        return;
+
+    std::mbstate_t C_state = std::mbstate_t ();
+
+    std::size_t C_res =
+        rwtest_mbslen ( C_state, pe, pe_limit, sze );
+    // test the result against C library
+    rw_assert (sze == C_res, __FILE__, __LINE__,
+               "(%s) %s::do_length; "
+               "check against C library result failed :\n"
+               "   C   library result : %d\n"
+               "   std library result : %d",
+               locale_name, TypeName<CodeCvtT>::name,
+               C_res, sze);
+}
+
+template <class CodeCvtT>
+static void
+test_libstd_do_encoding (const CodeCvtT& cc, std::size_t& sze)
+{
+    sze = cc.encoding ();
+}
+
+/****************************************************************************/
+
+// Primary template for checking libstd locale codecvt facets
+template <class CodeCvtT>
+static void
+test_libstd_codecvt (const char* locale_name, const CodeCvtT& cc,
+                     const char* fname, bool skip_C,
+                     CodecvtResult in_res,  std::size_t in_res_sz,
+                     CodecvtResult out_res, std::size_t out_res_sz,
+                     CodecvtResult unshift_res,
+                     bool always_noconv_res,
+                     std::size_t encoding_res,
+                     std::size_t length_res,
+                     std::size_t max_length_res)
+{
+    // buffers types
+    typedef typename CodeCvtT::intern_type      intern_t;
+    typedef typename CodeCvtT::extern_type      extern_t;
+
+    // create a state object
+    std::mbstate_t state = std::mbstate_t ();
+
+    // pointers to buffers
+    extern_t*  ebuffer   = 0;
+    intern_t*  ibuffer   = 0;
+    extern_t*  eebuffer  = 0;
+
+    std::size_t elength  = 0;
+    std::size_t ilength  = 0;
+    std::size_t eelength = 0;
+
+    // read source file
+    ebuffer = _RWSTD_STATIC_CAST (extern_t*, rw_fread (fname, &elength, "rb"));
+
+    if (!ebuffer || !elength) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "failed to read from %s", fname);
+        return;
+    }
+
+    // operations results
+    CodecvtResult res;
+    bool          bres;
+    std::size_t   ires;
+    std::size_t   res_sz;
+
+    char fcall [256];
+    std::sprintf (fcall, "%s::in(..., %p, %p, 0, %p, %p, 0)",
+                  TypeName<CodeCvtT>::name,
+                  (const void*)ebuffer, (const void*)(ebuffer + elength),
+                  (const void*)ibuffer, (const void*)(ibuffer + ilength));
+
+    // Test do_in conversion result and size
+    test_libstd_do_in<CodeCvtT> (locale_name, cc,
+                                 ebuffer, ibuffer, elength, ilength,
+                                 skip_C, res, res_sz);
+
+    // 22.2.1.5 p3, 22.2.1.5.2 p2 - test operation result
+    rw_assert (res == in_res, __FILE__, __LINE__,
+               "%s == %s, got %s in locale(\"%s\")",
+               fcall,
+               rwtest_codecvt_result (in_res),
+               rwtest_codecvt_result (res),
+               locale_name);
+
+    // test the length of the internal buffer is correct; noconv does not do
+    // any copying of the data
+    if (res == std::codecvt_base::noconv) {
+        rw_assert (res_sz == 0, __FILE__, __LINE__,
+                   "%s expected size 0 for %s, got %d instead "
+                   "in locale(\"%s\")", fcall,
+                   rwtest_codecvt_result (res), res_sz, locale_name);
+
+        // so copy all content from external buffer to internal buffer
+        ilength = elength;
+        for (std::size_t i = 0; i < elength; i++)
+            ibuffer [i] = intern_t (ebuffer [i]);
+
+    }
+    else {
+        rw_assert (ilength == in_res_sz && ilength == res_sz,
+                   __FILE__, __LINE__,
+                   "%s: conversion size: expected %d, got %d in locale(\"%s\")",
+                   fcall, in_res_sz, ilength, locale_name);
+    }
+
+    // Test do_out conversion result and size
+    test_libstd_do_out<CodeCvtT> (locale_name, cc,
+                                  eebuffer, ibuffer, eelength, ilength,
+                                  skip_C, res, res_sz);
+
+    // 22.2.1.5 p3, 22.2.1.5.2 p2 - test operation result
+    rw_assert (res == out_res, __FILE__, __LINE__,
+               "(%s) %s::do_out() == %s, got %s",
+               locale_name, TypeName<CodecvtBnW>::name,
+               rwtest_codecvt_result (out_res), rwtest_codecvt_result (res));
+
+    if (res == std::codecvt_base::noconv) {
+        rw_assert (res_sz == 0, __FILE__, __LINE__,
+                   "(%s) %s::do_out expected size 0 for %s, got %d instead",
+                   locale_name, TypeName<CodeCvtT>::name,
+                   rwtest_codecvt_result (res), res_sz);
+
+        // so copy all content from internal buffer to external buffer
+        eelength = ilength;
+        for (std::size_t i = 0; i < eelength; i++)
+            eebuffer [i] = extern_t (ibuffer [i]);
+
+    } else {
+        rw_assert (eelength == out_res_sz && eelength == res_sz,
+                   __FILE__, __LINE__,
+                   "(%s) %s::do_out conversion size: expected %d, got %d",
+                   locale_name, TypeName<CodeCvtT>::name,
+                   in_res_sz, ilength);
+    }
+
+    // Test the roundtrip conversion content and size
+    std::size_t cmp = 0;
+    if (std::memcmp (ebuffer, eebuffer, min (elength, eelength))) {
+        for (cmp = 0; cmp < min (elength, eelength); cmp++)
+            if (ebuffer [cmp] != eebuffer [cmp])
+                break;
+    }
+
+    rw_assert (elength == eelength, __FILE__, __LINE__,
+               "(%s) %s round-trip check size mismatch    : "
+               " expected size %d , got size %d",
+               locale_name, TypeName<CodeCvtT>::name,
+               elength, eelength);
+
+    rw_assert (0 == std::memcmp (ebuffer, eebuffer,
+                                 min (elength, eelength)),
+               __FILE__, __LINE__,
+               "(%s) %s round-trip check content mismatch : at index %d",
+               locale_name, TypeName<CodeCvtT>::name, cmp);
+
+    // Test unshift operation
+    extern_t    tmp [16];
+    std::size_t tmp_len = 16;
+    state = std::mbstate_t ();
+
+    test_libstd_do_unshift<CodeCvtT> (cc, state, tmp, tmp_len, res);
+
+    // 22.2.1.5.2 p5-6
+    rw_assert (res == unshift_res, __FILE__, __LINE__,
+               "(%s) %s::do_unshift; expected %s, got %s",
+               locale_name, TypeName<CodeCvtT>::name,
+               rwtest_codecvt_result (unshift_res),
+               rwtest_codecvt_result (res));
+
+    rw_assert (tmp_len == 0, __FILE__, __LINE__,
+               "(%s) %s::do_unshift; expected 0 length unshift sequence, "
+               "got %d", locale_name, TypeName<CodeCvtT>::name, tmp_len);
+
+    // Test do_always_noconv operation
+    test_libstd_do_always_noconv<CodeCvtT> (cc, bres);
+    rw_assert (bres == always_noconv_res, __FILE__, __LINE__,
+               "(%s) %s::do_always_noconv expected %s, got %s",
+               locale_name, TypeName<CodeCvtT>::name,
+               always_noconv_res?"true":"false", bres?"true":"false");
+
+    // Test do_max_length operation
+    test_libstd_do_max_length<CodeCvtT> (cc, ires);
+    // 22.2.1.5.2 p11
+    rw_assert (ires == max_length_res, __FILE__, __LINE__,
+               "(%s) %s::do_max_length expected %d, got %d",
+               locale_name, TypeName<CodeCvtT>::name,
+               max_length_res, ires);
+
+    // Test do_length operation
+    ires = elength;
+    test_libstd_do_length<CodeCvtT> (locale_name, cc,
+                                     ebuffer, ires, skip_C);
+    // 22.2.1.5.2 p10
+    rw_assert (ires == length_res, __FILE__, __LINE__,
+               "(%s) %s::do_length expected %d, got %d",
+               locale_name, TypeName<CodeCvtT>::name,
+               length_res, ires);
+
+    ires = 0;
+    test_libstd_do_encoding<CodeCvtT> (cc, ires);
+    // 22.2.1.5.2 p6
+    rw_assert (ires == encoding_res, __FILE__, __LINE__,
+               "(%s) %s::do_encoding expected %d, got %d",
+               locale_name, TypeName<CodeCvtT>::name,
+               encoding_res, ires);
+
+    delete [] ibuffer;
+    delete [] eebuffer;
+    // delete [] ebuffer;
+}
+
+/****************************************************************************/
+
+#if !defined _MSC_VER
+
+static unsigned int endian_test = 1;
+static bool big_endian = *(unsigned char*)&endian_test == 0;
+
+static iconv_t
+rwtest_iconv_open (bool ucs4, const char* enc)
+{
+    static const char* const ucs4_aliases [] = {
+        "UCS-4LE", "UCS-4", "UCS4", "ucs4", 0
+    };
+
+    static const char* const ucs2_aliases [] = {
+        "UCS-2LE", "UCS-2", "UCS2", "ucs2", 0
+    };
+
+    const char* const* pucs = ucs4 ? ucs4_aliases : ucs2_aliases;
+
+    // that accomodates Linux with its extra modifiers LE and BE
+    // (UCS-4 is synonym with UCS-4BE)
+    if (big_endian)
+        pucs++;
+
+    iconv_t id = iconv_t (-1);
+
+    for (; id == iconv_t (-1) && *pucs && **pucs; pucs++)
+        id = iconv_open (*pucs, enc);
+
+    return id;
+}
+
+
+static void
+rwtest_iconv_convert (iconv_t      fd,
+                      const char*  in,  std::size_t  in_sz,
+                      wchar_t*     out, std::size_t& out_sz)
+{
+    out_sz *= sizeof (wchar_t);
+
+    // Two issues:
+    //  - iconv shipped with the C library on RedHat 6.2 if reaches the end of
+    //  the input  buffer (out_sz  == 0) reports  E2BIG as  if it has  had not
+    //  enuff space to store the result of the conversion
+    //  - iconv shipped with C library on RedHat 6.2 apparently uses UCS-4 big
+    //  endian on little endian machines too
+    std::size_t tmp = out_sz++ + 1;
+
+#  if defined _RWSTD_NO_ICONV_CONST_CHAR
+    char* par1 = _RWSTD_CONST_CAST (char*, in);
+#  else
+    const char* par1 = in;
+#  endif //  defined _RWSTD_NO_ICONV_CONST_CHAR
+    char* par2 = _RWSTD_REINTERPRET_CAST (char*, out);
+
+    std::size_t res = iconv (fd, &par1, &in_sz, &par2, &out_sz);
+    if (res == std::size_t (-1))
+        out_sz = 0;
+    else
+        out_sz = (tmp + 1 - out_sz) / sizeof (wchar_t);
+}
+
+#endif // defined _MSC_VER
+
+
+enum InternalEncoding {
+    use_libc,   // use libc's native internal wchar_t encoding
+    use_UCS4,   // use UCS-4 as the internal wchar_t encoding
+    use_UCS2    // use UCS-2 as the internal wchar_t encoding
+};
+
+
+static bool
+rwtest_convert_to_internal (InternalEncoding conv,
+                            const char*      native_locname,
+                            const char*      ebuffer, std::size_t  elength,
+                            wchar_t*         ibuffer, std::size_t& ilength)
+{
+    ilength = 0;
+
+    if (!native_locname)
+        return false;
+
+    const char* const old_locale = std::setlocale (LC_CTYPE, native_locname);
+
+    if (!old_locale)
+        return false;
+
+    switch (conv) {
+
+#ifdef _MSC_VER
+
+    case use_UCS2:
+        // fall through...
+
+#endif   // _MSC_VER
+
+    case use_libc: {
+
+        std::mbstate_t state = std::mbstate_t ();
+
+        ilength = rwtest_mbstowcs (state, ibuffer, ebuffer, elength);
+
+        break;
+    }
+
+#ifndef _MSC_VER
+
+    case use_UCS2:
+    case use_UCS4: {
+        // use iconv
+
+        const char* const codeset = nl_langinfo (CODESET);
+        if (!codeset) {
+            ilength = std::size_t (-1);
+            break;
+        }
+
+        const iconv_t id = rwtest_iconv_open (true, codeset);
+
+        if (iconv_t (-1) == id)
+            ilength = std::size_t (-1);
+        else {
+            rwtest_iconv_convert (id, ebuffer, elength, ibuffer, ilength);
+
+            iconv_close (id);
+        }
+
+        break;
+    }
+
+#endif   // _MSC_VER
+
+    }
+
+    // restore the previous locale
+    std::setlocale (LC_CTYPE, old_locale);
+
+    if (std::size_t (-1) == ilength) {
+        ilength = 0;
+        return false;
+    }
+
+    return true;
+}
+
+
+static const char*
+rwtest_internal_type (InternalEncoding enc)
+{
+    static const char* const encs []  = {
+        "native", "UCS-4", "UCS-2", "invalid"
+    };
+
+    switch (enc) {
+    case use_libc:
+        return encs [0];
+    case use_UCS4:
+        return encs [1];
+    case use_UCS2:
+        return encs [2];
+    default:
+        return encs [3];
+    }
+}
+
+
+static std::size_t
+bmatch (const char* mem1, const char* mem2, std::size_t nchars)
+{
+    if (std::memcmp (mem1, mem2, nchars)) {
+
+        for (std::size_t i = 0; i != nchars; ++i)
+            if (mem1 [i] != mem2 [i])
+                return i;
+    }
+    return nchars;
+}
+
+
+static std::size_t
+bmatch (const wchar_t* mem1, const wchar_t* mem2, std::size_t nchars)
+{
+    if (std::size_t (-1) == nchars) {
+        // avoid warnings about unused overload above
+        return bmatch ((char*)0, (char*)0, 0);
+    }
+
+    if (std::memcmp (mem1, mem2, nchars * sizeof *mem1)) {
+
+        for (std::size_t i = 0; i != nchars; ++i)
+            if (mem1 [i] != mem2 [i])
+                return i;
+    }
+    return nchars;
+}
+
+
+static void
+test_ucs_modifier (const char*       locale_name,
+                   InternalEncoding  conv,
+                   const char*       native_locname,
+                   const CodecvtBnW& cc,
+                   const char*       fname,
+                   CodecvtResult     in_res,
+                   std::size_t       in_res_sz)
+{
+    // pointers to buffers
+    char*    ebuf        = 0;
+    wchar_t* ibuf        = 0;
+    wchar_t* ibuf_native = 0;
+
+    // buffer sizes
+    std::size_t elen   = 0;
+    std::size_t ilen   = 0;
+    std::size_t ilen_native = 0;
+
+    // read source file
+    ebuf = _RWSTD_STATIC_CAST (char*, rw_fread (fname, &elen, "rb"));
+    if (!ebuf || !elen)
+        return;
+
+    // allocate and zero the internal buffer
+    ilen = elen;
+    ibuf = new wchar_t [ilen];
+    std::memset (ibuf, 0, ilen * sizeof *ibuf);
+
+    ilen_native = elen;
+
+    // to accommodate iconv shipped with RedHat 6.2, allocate one more wchar_t
+    ibuf_native = new wchar_t [ilen_native + 1];
+    std::memset (ibuf_native, 0, (ilen_native + 1) * sizeof *ibuf_native);
+
+    const char* from       = ebuf;
+    const char* from_next  = ebuf;
+    const char* from_limit = ebuf + elen;
+    wchar_t*    to         = ibuf;
+    wchar_t*    to_next    = ibuf;
+    wchar_t*    to_limit   = ibuf + elen;
+
+    // create a state object
+    std::mbstate_t state = std::mbstate_t ();
+
+    rw_info (0, __FILE__, __LINE__, "locale(\"%s\")", locale_name);
+
+    const std::codecvt_base::result res =
+        cc.in (state, from, from_limit, from_next, to, to_limit, to_next);
+
+    ilen = to_next - to;
+
+    if (res != in_res || in_res_sz != std::size_t (to_next - to)) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "(%s) EXT -> INT conversion using codecvt failed:\n"
+                   "  result : %s\n  expected size %d, got %d",
+                   locale_name, rwtest_codecvt_result (res),
+                   in_res_sz, to_next - to);
+
+        delete [] ibuf_native;
+        delete [] ibuf;
+        return;
+
+    }
+
+    // test against the libc mbstowcs() or iconv() conversion
+    if (!rwtest_convert_to_internal (conv, native_locname, ebuf, elen,
+                                     ibuf_native, ilen_native)) {
+        delete [] ibuf_native;
+        delete [] ibuf;
+        return;
+    }
+
+    if (!ilen_native) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "(%s) EXT -> INT conversion using %s "
+                   "(%s internally) failed",
+                   locale_name,
+                   (conv == use_libc) ? "mbstowcs()" : "iconv()",
+                   rwtest_internal_type (conv));
+
+        delete [] ibuf_native;
+        delete [] ibuf;
+        return;
+    }
+
+    // Conversion and check against mbstowcs / iconv
+    rw_assert (ilen_native == ilen, __FILE__, __LINE__,
+               "(%s) EXT -> INT length check (%s internally):\n"
+               "  size of native encoding: %d\n"
+               "  size of codecvt encoding: %d\n",
+               locale_name, rwtest_internal_type (conv),
+               ilen, ilen_native);
+
+    if (ilen_native == ilen) {
+        const std::size_t diff = bmatch (to, ibuf_native, ilen);
+
+        rw_assert (diff >= ilen, __FILE__, __LINE__,
+                   "codecvt<wchar_t, char, mbstate_t>::in() mismatch "
+                   "at character %u of %u: '%s' != '%s'; in locale(\"%s\")",
+                   diff, ilen, ibuf_native [diff],
+                   to [diff], locale_name);
+    }
+
+    delete [] ibuf_native;
+    delete [] ibuf;
+}
+
+/****************************************************************************/
+
+std::jmp_buf jmp_env;
+
+// called in response to abort() or failed assertions
+extern "C"
+void SIGABRT_handler (int /*unused*/)
+{
+    std::longjmp (jmp_env, 1);
+}
+
+
+// exercise the facets' treatment of an invalid mbstate_t argument
+template <class CodeCvtT>
+static void
+test_mbstate_t (const CodeCvtT*, const char* name)
+{
+    const std::locale loc (name);
+
+    const CodeCvtT &cvt = _STD_USE_FACET (CodeCvtT, loc);
+
+    typedef typename CodeCvtT::intern_type intern_type;
+    typedef typename CodeCvtT::extern_type extern_type;
+    typedef typename CodeCvtT::state_type  state_type;
+
+    state_type state;
+
+    // initialize `state' to an invalid value
+    std::memset (&state, -1, sizeof state);
+
+    intern_type in = intern_type ();
+    intern_type* in_0 = &in;
+    intern_type* in_1 = &in + 1;
+    intern_type* in_2 = 0;
+    const intern_type* const_in_2 = 0;
+
+    extern_type ext = extern_type ();
+    extern_type* ext_0 = &ext;
+    extern_type* ext_1 = &ext + 1;
+    extern_type* ext_2 = 0;
+    const extern_type* const_ext_2 = 0;
+
+#ifndef _RWSTDDEBUG
+    // when debugging is disabled, expect member functions to
+    // detect and indicate an invalid argument by setting the
+    // return value to codecvt_base::error
+    const bool expect_abort = false;
+#else
+    // when debugging is enabled, expect member functions to
+    // detect and indicate an invalid argument by calling abort()
+    const bool expect_abort = true;
+#endif
+
+#undef TEST
+#define TEST(resultT, result, fname, args)                                \
+    if (0 == setjmp (jmp_env)) {                                          \
+        std::signal (SIGABRT, SIGABRT_handler);                           \
+        const resultT res = cvt.fname args;                               \
+        rw_assert (!expect_abort && result == res, __FILE__, __LINE__,    \
+                   "%s::%s (state_type&, ...) failed to "                 \
+                   "detect an invalid state argument",                    \
+                   TypeName<CodeCvtT>::name, #fname);                     \
+    } else                                                                \
+        rw_assert (expect_abort, __FILE__, __LINE__,                      \
+                   "%s::%s (state_type&, ...) called abort() instead "    \
+                   "of gracefully indicating an invalid state argument",  \
+                   TypeName<CodeCvtT>::name, #fname)
+
+    const std::codecvt_base::result error = std::codecvt_base::error;
+
+    TEST (std::codecvt_base::result, error,
+          in, (state, ext_0, ext_1, const_ext_2, in_0, in_1, in_2));
+
+    TEST (std::codecvt_base::result, error,
+          out, (state, in_0, in_1, const_in_2, ext_0, ext_1, ext_2));
+
+    TEST (std::codecvt_base::result, error,
+          unshift, (state, ext_0, ext_1, ext_2));
+
+    TEST (int, 0,
+          length,  (state, ext_0, ext_1, 0));
+
+    // verify that functions gracefully handle null pointers
+#undef TEST
+#define TEST(resultT, result, fname, args)                                \
+    if (0 == setjmp (jmp_env)) {                                          \
+        std::signal (SIGABRT, SIGABRT_handler);                           \
+        const resultT res = cvt.fname args;                               \
+        rw_assert (result == res, __FILE__, __LINE__,                     \
+                   "%s::%s (state_type&, (char_type*)0, ...) == %s, "     \
+                   "got %s (NULL pointer test)",                          \
+                   TypeName<CodeCvtT>::name, #fname,                      \
+                   rwtest_codecvt_result (result),                        \
+                   rwtest_codecvt_result (res));                          \
+    } else                                                                \
+        rw_assert (expect_abort, __FILE__, __LINE__,                      \
+                   "%s::%s (state_type&, (char_type*)0, ...) "            \
+                   "unexpectedly called abort() (NULL pointer test)",     \
+                   TypeName<CodeCvtT>::name, #fname)
+
+    // initialize `state' to a valid value
+    std::memset (&state, 0, sizeof state);
+
+    // const below commented out to work around an HP aCC bug (PR #29666)
+    /* const */ std::codecvt_base::result result =
+          sizeof (intern_type) == sizeof (char)
+        ? std::codecvt_base::noconv : std::codecvt_base::ok;
+
+    TEST (std::codecvt_base::result, result,
+          in, (state, 0, 0, const_ext_2, 0, 0, in_2));
+
+    TEST (std::codecvt_base::result, result,
+          out, (state, 0, 0, const_in_2, 0, 0, ext_2));
+
+    TEST (std::codecvt_base::result, std::codecvt_base::noconv,
+          unshift, (state, 0, 0, ext_2));
+
+    TEST (int, 0,
+          length,  (state, 0, 0, 0));
+}
+
+/****************************************************************************/
+
+static void
+test_invalid_args (const char* locname)
+{
+    // exercise the behavior of the base facets
+    rw_info (0, __FILE__, __LINE__,
+             "Testing %s with invalid arguments", TypeName<Codecvt>::name);
+    test_mbstate_t ((Codecvt*)0, "C");
+
+    rw_info (0, __FILE__, __LINE__,
+             "Testing %s with invalid arguments", TypeName<CodecvtW>::name);
+    test_mbstate_t ((CodecvtW*)0, "C");
+
+    char non_c_locname [256];
+    *non_c_locname = '\0';
+
+    for (const char *loc = rw_locale_query (); *loc;
+         loc += std::strlen (loc) + 1) {
+        if (   std::strcmp ("C", loc) && std::strcmp ("POSIX", loc)
+            && std::setlocale (LC_ALL, loc)) {
+            std::setlocale (LC_ALL, "C");
+            std::strcpy (non_c_locname, loc);
+            break;
+        }
+    }
+
+    if (*non_c_locname) {
+        // exercise the behavior of the derived facets when using
+        // libc locale names other than "C" or "POSIX"
+
+        rw_info (0, __FILE__, __LINE__,
+                 "Testing libc based %s with invalid arguments "
+                 "in locale(\"%s\")",
+                 TypeName<CodecvtBn>::name, non_c_locname);
+
+        test_mbstate_t ((CodecvtBn*)0, non_c_locname);
+
+        rw_info (0, __FILE__, __LINE__,
+                 "Testing libc based %s with invalid arguments "
+                 "in locale(\"%s\")",
+                 TypeName<CodecvtBnW>::name, non_c_locname);
+        test_mbstate_t ((CodecvtBnW*)0, non_c_locname);
+    }
+
+    if (locname) {
+
+        // exercise the behavior of the byname facets when using own
+        // locale databases and when passed an invalid mbstate_t object
+        rw_info (0, __FILE__, __LINE__,
+                 "Testing libstd %s with invalid arguments",
+                 TypeName<CodecvtBn>::name);
+
+        test_mbstate_t ((CodecvtBn*)0, locname);
+
+        rw_info (0, __FILE__, __LINE__,
+                 "Testing libstd %s with invalid arguments",
+                 TypeName<CodecvtBnW>::name);
+
+        test_mbstate_t ((CodecvtBnW*)0, locname);
+    }
+}
+
+/****************************************************************************/
+
+template <class internT>
+static void
+test_inout (int which, int line, const char* name,
+            const char*    sext, std::size_t ext_len, std::size_t ext_num,
+            const internT* sint, std::size_t int_len, std::size_t int_num,
+            std::codecvt_base::result expect)
+{
+    _RWSTD_UNUSED (line);
+
+    char namebuf [256];
+    assert (255 >= std::strlen (name));
+    std::strcpy (namebuf, name);
+
+    // when non-0, the name the locale object is constructed with
+    const char* locale_name = 0;
+
+    // when non-0, the name the codevt_byname facet is constructed
+    // with before being installed in the locale object
+    const char* codecvt_name = 0;
+
+    // look for a locale name modifier
+    const char* const mod = std::strrchr (name, '@');
+
+    if (mod && 'U' == mod [1] && 'C' == mod [2] && 'S' == mod [3]) {
+
+        namebuf [mod - name] = '\0';
+        locale_name  = namebuf;
+        codecvt_name = namebuf + (mod - name) + 1;
+    }
+
+    // check for the special names "UTF-8" and "utf-8" indicating
+    // a codecvt_byname facet with UTF-8 as the external encoding
+    // and UCS (either UCS-4 or UCS-2, depending on the width of
+    // wchar_t) as the internal encoding (i.e., synonyms for
+    // "UTF-8@UCS" and "utf-8@UCS" respectively)
+    if (   !std::strcmp (namebuf, "UTF-8")
+        || !std::strcmp (namebuf, "utf-8")) {
+        codecvt_name = namebuf;
+        locale_name  = 0;
+    }
+    else
+        locale_name = namebuf;
+
+    typedef std::codecvt<internT, char, std::mbstate_t>        Cvt;
+    typedef std::codecvt_byname<internT, char, std::mbstate_t> CvtByname;
+
+    std::locale loc;
+
+    // try to construct a locale with the given name
+    if (locale_name) {
+        _TRY {
+            loc = std::locale (locale_name);
+        }
+        _CATCH (...) {
+            const char* const envvar = std::getenv (LOCALE_ROOT_ENVAR);
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "locale(\"%s\") unexpectedly threw an exception; "
+                       LOCALE_ROOT_ENVAR "=%s", locale_name,
+                       envvar ? envvar : "(null)");
+
+            return;
+        }
+    }
+
+    // if `codecvt_name' is non-0, try to construct a codecvt_byname
+    // facet with that name and install it in the locale object
+    // constructed above
+    if (codecvt_name) {
+
+        const Cvt* pcvt = 0;
+
+        _TRY {
+            // first try to construct the facet
+            pcvt = new CvtByname (codecvt_name);
+        }
+        _CATCH (...) {
+            const char* const envvar = std::getenv (LOCALE_ROOT_ENVAR);
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "codecvt_byname<%s, char, mbstate_t>(\"%s\") "
+                       "unexpectedly threw an exception; "
+                       LOCALE_ROOT_ENVAR "=%s", TypeName<internT>::name,
+                       codecvt_name, envvar ? envvar : "(null)");
+
+            return;
+        }
+        _TRY {
+            // next try to install the facet in the locale object
+            loc = std::locale (loc, pcvt);
+        }
+        _CATCH (...) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "locale combining ctor unexpectedly threw "
+                       "an exception; ");
+            delete pcvt;
+            return;
+        }
+    }
+
+    // compute the length of the source sequence if it isn't specified
+    if (std::size_t (-1) == ext_len)
+        ext_len = sext ? std::strlen (sext) : 0;
+
+    // compute the length of the destination sequence if it isn't specified
+    if (std::size_t (-1) == int_len)
+        int_len = sint ? std::char_traits<internT>::length (sint) : 0;
+
+    // retrieve the codecvt or codecvt_byname facet from the locale object
+    const Cvt &cvt = std::use_facet<Cvt>(loc);
+
+    std::mbstate_t state;
+    std::memset (&state, 0, sizeof state);
+
+    // for convenience: fully qualified name of the function,
+    // including the values of function arguments
+    static char fcall [4096];
+
+    if (   ('I' == which || 'i' == which
+        || 'o' == which) && std::codecvt_base::ok == expect) {
+        // exercise do_in():
+        // *  the type of `sext' is char
+        // *  ext_len is the number of bytes in the external sequence
+        // *  the type of `sint' is internT (i.e., char or wchar_t)
+        // *  int_len is the number of internT characters
+        //    in the expected internal sequence
+
+        const char* ext_lo  = sext;
+        const char* ext_hi  = sext + ext_len;
+        const char* ext_nxt = 0;
+
+        internT* int_lo  = new internT [int_len + 1];
+        internT* int_hi  = int_lo + int_len;
+        internT* int_nxt = 0;
+
+        std::memset (int_lo, 0, (int_len + 1) * sizeof *int_lo);
+
+        // is the `sext' array is not NUL-terminated, create a copy
+        // and NUL-terminate it
+        const char* pextstr = sext;
+        if (sext [ext_len]) {
+            char* const tmp = new char [ext_len + 1];
+            std::memcpy (tmp, sext, ext_len);
+            tmp [ext_len] = '\0';
+            pextstr = tmp;
+        }
+
+        std::sprintf (fcall, "codecvt<%s, char, mbstate_t>::in"
+                      "(..., %p = %s, %p, %p, %p, %p, %p)",
+                      TypeName<internT>::name,
+                      (const void*)ext_lo, pextstr,
+                      (const void*)ext_hi, (const void*)ext_nxt,
+                      (const void*)int_lo, (const void*)int_hi,
+                      (const void*)int_nxt);
+
+        if (pextstr != sext) {
+            // const_cast works around an MSVC 6.0 bug (PR #30092)
+            delete[] _RWSTD_CONST_CAST (char*, pextstr);
+        }
+
+        std::codecvt_base::result res;
+
+        _TRY {
+            res = cvt.in (state,
+                          ext_lo, ext_hi, ext_nxt,
+                          int_lo, int_hi, int_nxt);
+        }
+        _CATCH (...) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s unexpectedly threw an exception",
+                       __LINE__, fcall);
+        }
+
+        // verify the value returned from the function
+        if (expect != res) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s == %s, got %s", __LINE__, fcall,
+                       rwtest_codecvt_result (expect),
+                       rwtest_codecvt_result (res));
+        }
+
+        // verify the value of the from_next pointer modified by the function
+        if (ext_nxt != ext_lo + ext_num) {
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s; from_next == %p, got %p (at offset %d)",
+                       __LINE__, fcall, ext_lo + ext_num, ext_nxt,
+                       ext_nxt - ext_lo);
+        }
+
+        // verify the value of the to_next pointer modified by the function
+        if (int_nxt != int_lo + int_num) {
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s; to_next == %p, got %p (at offset %d)",
+                       __LINE__, fcall, int_lo + int_num, int_nxt,
+                       int_nxt - int_lo);
+        }
+
+        if (std::codecvt_base::error != res) {
+
+            // verify that the contents of the destination sequence
+            // matches the expected sequence
+            const int cmp = std::memcmp (int_lo, sint, int_len);
+
+            if (cmp) {
+                rw_assert (false, __FILE__, __LINE__,
+                           "%d. %s -> %s, expected %s", __LINE__, fcall,
+                           int_lo, sint);
+            }
+        }
+
+        delete[] int_lo;
+    }
+
+    if (   ('O' == which || 'o' == which
+        || 'i' == which) && std::codecvt_base::ok == expect) {
+        // exercise do_out():
+        // *  the type of `sint' is internT (i.e., either char or wchar_t)
+        // *  int_len is the number of internT characters
+        // *  the type of `ext' is char
+        // *  ext_len is the number of bytes in the expected sequence
+        //    of external characters
+
+        char* ext_lo  = new char [ext_len + 1];
+        char* ext_hi  = ext_lo + ext_len;
+        char* ext_nxt = 0;
+
+        std::memset (ext_lo, 0, ext_len + 1);
+
+        const internT* int_lo  = sint;
+        const internT* int_hi  = int_lo + int_len;
+        const internT* int_nxt = 0;
+
+        const char* fmt;
+        if (sizeof (internT) == sizeof (char))
+            fmt = "codecvt<char, char, mbstate_t>::out"
+                  "(..., %p = %s, %p, %p, %p, %p, %p)";
+        else if (sizeof (internT) == sizeof (wchar_t))
+            fmt = "codecvt<wchar_t, char, mbstate_t>::out"
+                  "(..., %p = L%ls, %p, %p, %p, %p, %p)";
+
+        std::sprintf (fcall, fmt, (const void*)int_lo,
+                      int_lo, (const void*)int_hi,
+                      (const void*)int_nxt, (const void*)ext_lo,
+                      (const void*)ext_hi, (const void*)ext_nxt);
+
+        std::codecvt_base::result res;
+
+        _TRY {
+            res = cvt.out (state,
+                           int_lo, int_hi, int_nxt,
+                           ext_lo, ext_hi, ext_nxt);
+        }
+        _CATCH (...) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s unexpectedly threw an exception",
+                       __LINE__, fcall);
+        }
+
+        // verify the value returned from the function
+        if (expect != res) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s == %s, got %s", __LINE__, fcall,
+                       rwtest_codecvt_result (expect),
+                       rwtest_codecvt_result (res));
+        }
+
+        // verify the value of the from_next pointer modified by the function
+        if (int_nxt != int_lo + int_num) {
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s; from_next == %p, got %p (at offset %d)",
+                       __LINE__, fcall, int_lo + int_num, int_nxt,
+                       int_nxt - int_lo);
+        }
+
+        // verify the value of the to_next pointer modified by the function
+        if (ext_nxt != ext_lo + ext_num) {
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "%d. %s; to_next == %p, got %p (at offset %d)",
+                       __LINE__, fcall, ext_lo + ext_num, ext_nxt,
+                       ext_nxt - ext_lo);
+        }
+
+        if (std::codecvt_base::error != res) {
+
+            // verify that the contents of the destination sequence
+            // matches the expected sequence
+            const int cmp = std::memcmp (ext_lo, sext, ext_len);
+
+            if (cmp) {
+
+                rw_assert (false, __FILE__, __LINE__,
+                           "%d. %s -> %s, expected %s", __LINE__, fcall,
+                           ext_lo, sext);
+            }
+        }
+
+        delete[] ext_lo;
+    }
+}
+
+
+// the root of the locale directory (RWSTD_LOCALE_ROOT)
+// set in main() instead of here to avoid Solaris 7 putenv() bug (PR #30017)
+const char* locale_root;
+
+
+// creates a codecvt database from `charmap'
+static const char*
+create_codecvt (unsigned    mb_min,
+                unsigned    mb_max,
+                const char* charmap,
+                const char* charset_name = 0)
+{
+    // keeps track of successful calls and generates a unique
+    // name for each codeset conversion database and locale
+    static int call_no;
+
+    // construct the absolute pathname of a charmap file
+    char cm_pathname [PATH_MAX];
+
+    if (charset_name)
+        std::sprintf (cm_pathname, "%s" SLASH "%s.cm",
+                      locale_root, charset_name);
+    else
+        std::sprintf (cm_pathname,
+                      "%s" SLASH "codecvt-%u-%u.%d.cm",
+                      locale_root, mb_min, mb_max, call_no);
+
+    // create the charmap file
+    std::FILE* pf = std::fopen (cm_pathname, "w");
+    if (!pf)
+        return 0;
+
+    if (charset_name)
+        std::fprintf (pf, "<code_set_name> %s\n", charset_name);
+    else
+        std::fprintf (pf, "<code_set_name> codecvt-%u-%u.%d\n",
+                      mb_min, mb_max, call_no);
+
+    std::fprintf (pf, "<escape_char>   /\n");
+
+    std::fprintf (pf, "<mb_cur_min>    %u\n", mb_min);
+    std::fprintf (pf, "<mb_cur_max>    %u\n\n\n", mb_max);
+    std::fprintf (pf, "CHARMAP\n");
+    std::fprintf (pf, charmap);
+    std::fprintf (pf, "\nEND CHARMAP\n");
+
+    std::fclose (pf);
+
+    // construct the absolute pathname of a dummy locale definition file
+    char src_pathname [PATH_MAX];
+    std::strcpy (src_pathname, locale_root);
+    std::strcat (src_pathname, SLASH "dummy.src");
+
+    // create the locale definition file
+    if (!(pf = std::fopen (src_pathname, "w")))
+        return 0;
+
+    // dummy source file must contain the LC_CTYPE section
+    // in order for localedef to generate the codecvt database
+    std::fprintf (pf, "LC_CTYPE\nEND LC_CTYPE\n");
+
+    std::fclose (pf);
+
+    // construct the filename of the locale
+    char locale_fname[32];
+    std::sprintf (locale_fname,
+                  "locale-%u.%u-%d",
+                  mb_min, mb_max, call_no);
+
+    // invoke localedef to create the named locale from the dummy
+    // locale definition file and the character set description file
+    // silence the following warnings:
+    // 701: no compatible locale found
+    // 702: member of portable character set <x> not found
+    //      in the character map
+    // 706: iconv_open() failed
+    // : unknown symbol found in LC_COLLATE definition
+    // : some characters in the codeset were not explicitly
+    //   given a collation value
+    const char* const locname =
+        rw_localedef ("-w701 -w702 -w706",
+                      src_pathname, cm_pathname, locale_fname);
+
+    call_no += !!locname;
+
+    return locname;
+}
+
+
+// given a canonical locale name, `locname', tries to find a platform
+// specific locale name that corresponds to the name; when `codeset'
+// is non-0, also checks to see that the platform-specific locale's
+// codeset is the same as that specified by the argument
+// on success, returns the name of the platform-specific locale,
+// otherwise 0
+static const char*
+find_locale (const char* locname, const char* codeset)
+{
+    static const struct {
+        const char* locnames [16];
+        const char* codesets [16];
+    } aliases [] = {
+        { {
+            // canonical locale name, followed by its common aliases
+            "de_DE.ISO-8859-1",
+            "de_DE.iso88591", "de_DE.ISO8859-1", "de_DE", "DEU", "de", 0
+        }, {
+            // well-known codeset name, followed by its common aliases
+            "ISO-8859-1",
+            "ISO-88591", "ISO_8859-1", "ISO8859-1", "iso88591", "iso1", 0
+            // Windows Codepage 1252 (Latin I)
+            // http://www.microsoft.com/globaldev/reference/sbcs/1252.htm
+        } },
+        { {
+            "fr_FR.ISO-8859-1",
+            "fr_FR.iso88591", "fr_FR.ISO8859-1", "fr_FR", "FRA", "fr", 0
+        }, {
+            "ISO-8859-1",
+            "ISO-88591", "ISO_8859-1", "ISO8859-1", "iso88591", "iso1", 0
+        } },
+        { {
+            "ja_JP.Shift_JIS",
+            "ja_JP.SJIS", "japanese.sjis", "JPN", 0
+        }, {
+            "Shift_JIS",
+            "Shift-JIS", "SJIS", "SHIFT-JIS", "SHIFT_JIS", "shift-jis",
+            "sjis", 0
+            // Windows Codepage 932 (Japanese Shift-JIS)
+            // http://www.microsoft.com/globaldev/reference/dbcs/932.htm
+        } },
+        { {
+            "ja_JP.EUC-JP",
+            "ja_JP.eucJP", "ja_JP.EUC", "ja_JP.eucjp", 0
+        }, {
+            "EUC-JP",
+            "eucjp", "eucJP", "euc_jp", "euc", "ujis", 0
+        } },
+        { { 0 }, { 0 } }
+    };
+
+    const char* name = std::setlocale (LC_ALL, locname);
+
+    std::size_t inx = std::size_t (-1);
+
+    if (!name) {
+
+        // find the index, `inx', of `locname' in the table
+        for (std::size_t i = 0; i != sizeof aliases / sizeof *aliases; ++i) {
+            if (!aliases [i].locnames [0])
+                break;
+
+            if (!std::strcmp (locname, aliases [i].locnames [0])) {
+                inx = i;
+                break;
+            }
+        }
+
+        if (std::size_t (-1) != inx) {
+
+            // go through the locale name's aliases until one
+            // that's a valid argument to setlocale() is found
+            for (std::size_t j = 1; aliases [inx].locnames [j]; ++j) {
+                if (!aliases [inx].locnames [j])
+                    break;
+
+                if (std::setlocale (LC_ALL, aliases [inx].locnames [j])) {
+                    name = aliases [inx].locnames [j];
+                    break;
+                }
+            }
+        }
+    }
+
+#ifndef _RWSTD_NO_NL_LANGINFO
+
+    if (name) {
+        const char* const cset = nl_langinfo (CODESET);
+
+        if (codeset && std::strcmp (codeset, cset)) {
+
+            // if `codeset' is specified, verify that it matches
+            // the codeset used to encode the libc locale found
+            // and set above
+
+            for (std::size_t j = 0; aliases [inx].codesets [j]; ++j) {
+
+                if (!std::strcmp (aliases [inx].codesets [j], cset)) {
+                    std::setlocale (LC_ALL, "C");
+                    return name;
+                }
+            }
+            name = 0;
+        }
+
+        std::setlocale (LC_ALL, "C");
+    }
+
+#endif   // _RWSTD_NO_NL_LANGINFO
+
+    return name;
+}
+
+
+const char ext_ascii[] = {
+    // basic ASCII
+    "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+    "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+    "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+    "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+    "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+    "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+    "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+    "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+    // extended ASCII
+    "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+    "\x90\x91\x92\x93\x94\x95\x96\x97\x89\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+    "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+    "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+    "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+    "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+    "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+    "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+};
+
+
+// tries to find a locale whose internal (wchar_t) representation
+// of the Extended ASCII character set does not match the ASCII
+// character values; if such locale is found, fills up to `bufsize'
+// elements of the `buf' array with such characters and returns
+// the name of the locale
+static const char*
+find_interesting_locale (char* buf, std::size_t bufsize)
+{
+    std::memset (buf, 0, bufsize);
+
+    const char* name = 0;
+
+    const char* const buf_save = buf;
+
+    for (name = rw_locale_query (); *name; name += std::strlen (name) + 1) {
+
+        if (!std::setlocale (LC_ALL, name))
+            continue;
+
+        wchar_t wide_ascii [sizeof ext_ascii] = { 0 };
+
+        // convert the array of narrow Extended ASCII characters
+        // to their corresponding wchar_t values using mbstowcs()
+        const std::size_t nchars =
+            std::mbstowcs (wide_ascii + 1, ext_ascii + 1, sizeof ext_ascii - 2);
+
+        // continue on error
+        if (!nchars || nchars > sizeof ext_ascii - 2)
+            continue;
+
+        // look for a wide character with value different
+        // from the narrow single-byte character
+        for (std::size_t i = 0; i != nchars; ++i) {
+
+            typedef unsigned char UChar;
+
+            // convert to unsigned char before comparing
+            const UChar uc = UChar (ext_ascii [i]);
+
+            if (unsigned (uc) != unsigned (wide_ascii [i])) {
+                if (bufsize) {
+                    *buf++ = ext_ascii [i];
+                    --bufsize;
+                }
+            }
+        }
+
+        if (buf != buf_save)
+            break;
+    }
+
+    return name;
+}
+
+
+template <class internT>
+static void
+test_inout (const char* tname)
+{
+    // for convenience
+    const std::codecvt_base::result error   = std::codecvt_base::error;
+    const std::codecvt_base::result noconv  = std::codecvt_base::noconv;
+    const std::codecvt_base::result ok      = std::codecvt_base::ok;
+    const std::codecvt_base::result partial = std::codecvt_base::partial;
+
+    _RWSTD_UNUSED (noconv);
+
+    const char* locname = 0;
+
+    //////////////////////////////////////////////////////////////////
+    // exercise both codecvt::in() and codecvt::out()
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::codecvt<%s, char, mbstate_t>::in() "
+             "in a generated locale", tname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::codecvt<%s, char, mbstate_t>::out() "
+             "in a generated locale", tname);
+
+    // exercise a single-byte external encoding
+
+    rw_info (0, __FILE__, __LINE__, "<mb_cur_max> 1");
+
+    locname = create_codecvt (1, 1,   // MB_CUR_MAX = 1 (min = 1)
+        //        internal     external (single-byte)
+        /* NUL */ "<U0000>     /x30\n"   // L"\0" <-> "0"
+        /* <A> */ "<U0041>     /x31\n"   // L"A"  <-> "1"
+        /* <B> */ "<U0042>     /x32\n"   // L"B"  <-> "2"
+        /* <C> */ "<U0043>     /x33\n"   // L"C"  <-> "3"
+        /* <D> */ "<U0044>     /x34\n"   // L"D"  <-> "4"
+        /* <E> */ "<U0045>     /x35\n"   // L"E"  <-> "5"
+        /* <F> */ "<U0046>     /x36\n"   // L"F"  <-> "6"
+        /* <Z> */ "<U005A>     /x00\n"   // L"Z"  <-> "\0"
+
+#if _RWSTD_WCHAR_T_MAX > 0xffffU
+                  "<U12345678> /x78\n"   // 0x12345678 <-> "x"
+                  "<U0DEDBEEF> /x79\n"   // 0x0dedbeef <-> "y"
+#else   // if (WCHAR_T_MAX <= 0xffffU)
+                  "<U1234> /x78\n"   // 0x1234 <-> "x"
+                  "<UBEEF> /x79\n"   // 0xbeef <-> "y"
+#endif   // _RWSTD_WCHAR_T_MAX > 0xffffU
+        );
+
+    if (!locname) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "failed to generate locale");
+        return;
+    }
+
+#define DO_TEST(io, src, ext_len, ext_num, dst, int_len, int_num, res)  \
+    test_inout (io, __LINE__, locname, src, ext_len, ext_num,           \
+                dst, int_len, int_num, res)
+
+// TEST_IN: tests only codecvt::in()
+#define TEST_IN(src, ext_len, ext_num, dst, int_len, int_num, res)  \
+    DO_TEST ('I', src, ext_len, ext_num, dst, int_len, int_num, res)
+
+// TEST_OUT: tests only codecvt::out()
+#define TEST_OUT(src, ext_len, ext_num, dst, int_len, int_num, res)  \
+    DO_TEST ('O', src, ext_len, ext_num, dst, int_len, int_num, res)
+
+// TEST_IN_OUT: tests codecvt::in() and codecvt::out() only
+//              if the expected result is codecvt_base::ok
+#define TEST_IN_OUT(src, ext_len, ext_num, dst, int_len, int_num, res)  \
+    DO_TEST ('i', src, ext_len, ext_num, dst, int_len, int_num, res)
+
+// TEST_OUT_IN: tests codecvt::out() and codecvt::in() only
+//              if the expected result is codecvt_base::ok
+#define TEST_OUT_IN(src, ext_len, ext_num, dst, int_len, int_num, res)  \
+    DO_TEST ('o', src, ext_len, ext_num, dst, int_len, int_num, res)
+
+    //           +------------------------- contents of external (source) buffer
+    //           |    +-------------------- size of external (source) sequence
+    //           |    |  +----------------- expected size of consumed input
+    //           |    |  |  +-------------- expected contents of internal buffer
+    //           |    |  |  |     +-------- size of dest. buffer (in chars)
+    //           |    |  |  |     |  +----- expected size of output (in chars)
+    //           |    |  |  |     |  |  +-- expected result
+    //           V    V  V  V     V  V  V
+    TEST_IN_OUT ("",  0, 0, L"",  0, 0, ok);
+    TEST_IN_OUT ("0", 1, 1, L"",  1, 1, ok);   // "0" maps to wchar_t (0)
+    TEST_IN_OUT ("1", 1, 1, L"A", 1, 1, ok);
+    TEST_IN_OUT ("2", 1, 1, L"B", 1, 1, ok);
+    TEST_IN_OUT ("3", 1, 1, L"C", 1, 1, ok);
+    TEST_IN_OUT ("4", 1, 1, L"D", 1, 1, ok);
+    TEST_IN_OUT ("5", 1, 1, L"E", 1, 1, ok);
+    TEST_IN_OUT ("6", 1, 1, L"F", 1, 1, ok);
+    TEST_IN_OUT ("7", 1, 0, L"",  1, 0, error);
+    TEST_IN_OUT ("0", 1, 0, L"",  0, 0, partial);   // not enough space
+
+    TEST_IN_OUT ("12",    2, 2, L"AB",              2, 2, ok);
+    TEST_IN_OUT ("123",   3, 3, L"ABC",             3, 3, ok);
+    TEST_IN_OUT ("0123",  4, 4, L"\0ABC",           4, 4, ok);
+    TEST_IN_OUT ("0123Z", 5, 4, L"\0ABC",           5, 4, error);
+    TEST_IN_OUT ("01234", 5, 4, L"\0ABC",           4, 4, partial);
+
+#if _RWSTD_WCHAR_T_MAX > 0xffffU
+
+    TEST_IN_OUT ("x", 1, 1, L"\x12345678", 1, 1, ok);
+    TEST_IN_OUT ("y", 1, 1, L"\x0dedbeef", 1, 1, ok);
+
+    TEST_IN_OUT ("0123x", 5, 5, L"\0ABC\x12345678", 5, 5, ok);
+    TEST_IN_OUT ("123y",  4, 4, L"ABC\x0dedbeef",   4, 4, ok);
+
+#else
+
+    TEST_IN_OUT ("x", 1, 1, L"\x1234", 1, 1, ok);
+    TEST_IN_OUT ("y", 1, 1, L"\xbeef", 1, 1, ok);
+
+    TEST_IN_OUT ("0123x", 5, 5, L"\0ABC\x1234", 5, 5, ok);
+    TEST_IN_OUT ("123y",  4, 4, L"ABC\xbeef",   4, 4, ok);
+
+#endif   // _RWSTD_WCHAR_T_MAX > 0xffffU
+
+
+    // exercise multi-byte external encodings
+
+    rw_info (0, __FILE__, __LINE__, "<mb_cur_max> 2");
+
+    locname = create_codecvt (1, 2,   // MB_CUR_MAX = 2 (min = 1)
+        //        internal     external (multi-byte)
+        /* NUL */ "<U0000>     /x30\n"        // '\0' <-> "0"
+        /* <A> */ "<U0041>     /x31/x61\n"    // "A" <--> "1a"
+        /* <B> */ "<U0042>     /x32\n"        // "B" <--> "2"
+        /* <C> */ "<U0043>     /x33/x62\n"    // "C" <--> "3b"
+        /* <D> */ "<U0044>     /x34\n"        // "D" <--> "4"
+        /* <E> */ "<U0045>     /x35/x63\n"    // "E" <--> "3c"
+        /* <F> */ "<U0046>     /x36\n"        // "F" <--> "4"
+        /* <Z> */ "<U005A>     /x00/x00");    // "Z" <--> "\0\0"
+
+    if (!locname) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "failed to generate locale");
+        return;
+    }
+
+    TEST_IN_OUT ("",   0, 0, L"",  0, 0, ok);
+    TEST_IN_OUT ("0",  1, 1, L"",  1, 1, ok);   // "0" maps to wchar_t (0)
+    TEST_IN_OUT ("1a", 2, 2, L"A", 1, 1, ok);
+    TEST_IN_OUT ("2",  1, 1, L"B", 1, 1, ok);
+    TEST_IN_OUT ("3b", 2, 2, L"C", 1, 1, ok);
+    TEST_IN_OUT ("4",  1, 1, L"D", 1, 1, ok);
+    TEST_IN_OUT ("5c", 2, 2, L"E", 1, 1, ok);
+    TEST_IN_OUT ("6",  1, 1, L"F", 1, 1, ok);
+    TEST_IN_OUT ("7",  1, 0, L"",  1, 0, error);
+    TEST_IN_OUT ("1",  1, 0, L"",  0, 0, partial);   // not enough space
+
+    // exercise only in()
+    // result is partial due to the incomplete multibyte character
+    TEST_IN ("3",  1, 0, L"",  1, 0, partial);
+
+    TEST_IN_OUT ("01a23b",    6, 6, L"\0ABC",   4, 4, ok);
+    TEST_IN_OUT ("01a23b4",   7, 7, L"\0ABCD",  5, 5, ok);
+    TEST_IN_OUT ("01a23b45",  8, 7, L"\0ABCD",  5, 5, partial);
+    TEST_IN_OUT ("01a23b45c", 9, 9, L"\0ABCDE", 6, 6, ok);
+    TEST_IN_OUT ("01a23c45c", 9, 4, L"\0ABCDE", 6, 3, error);
+
+
+    rw_info (0, __FILE__, __LINE__, "<mb_cur_max> 6");
+
+    locname = create_codecvt (1, 6,   // MB_CUR_MAX = 6 (min = 1)
+        //        internal     external (multi-byte)
+        /* NUL */ "<U0000>  /x35\n"                       // "\0" <-> "5"
+        /* <A> */ "<U0041>  /x30/x31\n"                   // "A" <--> "01"
+        /* <B> */ "<U0042>  /x31/x32/x33\n"               // "B" <--> "123"
+        /* <C> */ "<U0043>  /x32/x33/x34/x35\n"           // "C" <--> "2345"
+        /* <D> */ "<U0044>  /x33/x34/x35/x36/x37\n"       // "D" <--> "34567"
+        /* <E> */ "<U0045>  /x34/x35/x36/x37/x38/x39\n"   // "E" <--> "456789"
+        /* <Z> */ "<U005A>  /x00/x00/x00");               // "Z" <--> "\0\0\0"
+
+    if (!locname) {
+        rw_assert (false, __FILE__, __LINE__, "failed to generate locale");
+        return;
+    }
+
+    TEST_IN_OUT ("",              0,  0, L"",    0, 0, ok);
+    TEST_IN_OUT ("01",            2,  2, L"A",   1, 1, ok);
+    TEST_IN_OUT ("012",           3,  2, L"A",   1, 1, partial);
+    TEST_IN_OUT ("0123",          4,  2, L"A",   1, 1, partial);
+    TEST_IN_OUT ("01234",         5,  2, L"A",   1, 1, partial);
+    TEST_IN_OUT ("012345",        6,  6, L"AC",  2, 2, ok);
+    TEST_IN_OUT ("123456789",     9,  9, L"BE",  3, 2, ok);
+    TEST_IN_OUT ("456789012345", 12, 12, L"EAC", 3, 3, ok);
+
+    // the first one below is partial even though the external sequence
+    // ends in the invalid byte '6' since there is no room in the dest.
+    // buffer (this could be either partial or error, the latter if the
+    // function verifies the validity of the character before checking
+    // whether there is sufficient room in the destination buffer)
+    TEST_IN_OUT ("0123456", 7, 6, L"AC", 2, 2, partial /* or error */);
+    TEST_IN_OUT ("0123456", 7, 6, L"AC", 3, 2, error);
+
+#ifndef _RWSTD_NO_NL_LANGINFO
+
+    char chars [256];
+    const char* const interesting_locale_name =
+        find_interesting_locale (chars, sizeof chars);
+
+    if (interesting_locale_name) {
+
+        std::setlocale (LC_ALL, interesting_locale_name);
+        const char* const codeset = nl_langinfo (CODESET);
+
+        rw_info (0, __FILE__, __LINE__,
+                 "<code_set_name> %s (locale(\"%s\"))",
+                 codeset, interesting_locale_name);
+
+        typedef unsigned char UChar;
+
+        char charmap [sizeof chars * 40];
+
+        charmap [0] = '\0';
+
+        for (const char* pc = chars; *pc; ++pc) {
+            std::sprintf (charmap + std::strlen (charmap),
+                          "<U%04X> /x%02x\n", UChar (*pc), UChar (*pc));
+        }
+
+        locname = create_codecvt (1, 1, charmap, codeset);
+
+        if (!locname) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "failed to generate locale");
+            return;
+        }
+
+        wchar_t wchars [sizeof chars];
+        std::mbstowcs (wchars, chars, std::strlen (chars));
+
+        std::setlocale (LC_ALL, "C");
+
+        for (std::size_t i = 0; chars [i]; ++i) {
+
+            const char    cs [] = { chars [i], '\0' };
+            const wchar_t ws [] = { wchars [i], 0 };
+
+            TEST_IN_OUT (cs, 1, 1, ws, 1, 1, ok);
+        }
+    }
+
+#endif   // _RWSTD_NO_NL_LANGINFO
+
+    // exercise codecvt_byname constructed with the special names below
+    const char* const names[] = {
+        // "UTF" prefix in all caps causes strict checking of UTF
+        // sequences at some loss in performance; "utf" prefix (all
+        // lowercase) allows for a faster implementation but accepts
+        // some sequences that are strictly speaking invalid (see
+        // below)
+
+        "UTF-8", "UTF-8@UCS",
+
+#if _RWSTD_WCHAR_T_MAX > 0xffffU
+        "UTF-8@UCS-4",
+#else   // if _RWSTD_WCHAR_T_MAX <= 0xffffU
+        "UTF-8@UCS-2",
+#endif   // WCHAR_T_MAX > 0xffffU
+
+        "utf-8", "utf-8@UCS",
+
+#if _RWSTD_WCHAR_T_MAX > 0xffffU
+        "utf-8@UCS-4",
+#else   // if _RWSTD_WCHAR_T_MAX <= 0xffffU
+        "utf-8@UCS-2",
+#endif   // WCHAR_T_MAX > 0xffffU
+    };
+
+    for (std::size_t i = 0; i != sizeof names / sizeof *names; ++i) {
+        locname = names [i];
+
+        rw_info (0, __FILE__, __LINE__,
+                 "codecvt_byname<wchar_t, char, mbstate_t>"
+                 "(\"%s\")", locname);
+
+        // strict conformance mode
+        const bool strict_mode = 'U' == *locname;
+
+        TEST_IN_OUT ("",     0, 0, L"",     0, 0, ok);
+        TEST_IN_OUT ("\0",   1, 1, L"\0",   1, 1, ok);
+        TEST_IN_OUT ("a",    1, 1, L"a",    1, 1, ok);
+        TEST_IN_OUT ("b",    1, 1, L"b",    1, 1, ok);
+        TEST_IN_OUT ("z",    1, 1, L"z",    1, 1, ok);
+        TEST_IN_OUT ("\x7f", 1, 1, L"\x7f", 1, 1, ok);
+
+        TEST_IN     ("\x80", 1, 0, L"",     1, 0, error);
+        TEST_IN     ("\x81", 1, 0, L"",     1, 0, error);
+        TEST_IN     ("\x82", 1, 0, L"",     1, 0, error);
+        TEST_IN     ("\xc1", 1, 0, L"",     1, 0, error);
+
+        TEST_IN_OUT ("\xc2\x80", 2, 2, L"\x80", 1, 1, ok);
+        TEST_IN_OUT ("\xc2\x81", 2, 2, L"\x81", 1, 1, ok);
+        TEST_IN_OUT ("\xc2\x82", 2, 2, L"\x82", 1, 1, ok);
+        TEST_IN_OUT ("\xc2\xbf", 2, 2, L"\xbf", 1, 1, ok);
+
+        TEST_IN_OUT ("\xc3\x80", 2, 2, L"\xc0", 1, 1, ok);
+        TEST_IN_OUT ("\xc3\x81", 2, 2, L"\xc1", 1, 1, ok);
+
+        TEST_IN_OUT ("\xde\xb0", 2, 2, L"\x07b0", 1, 1, ok);
+
+        TEST_IN_OUT ("\xe0\xa4\x81", 3, 3, L"\x0901", 1, 1, ok);
+        TEST_IN_OUT ("\xe3\x8f\xbe", 3, 3, L"\x33fe", 1, 1, ok);
+        TEST_IN_OUT ("\xe3\x90\x80", 3, 3, L"\x3400", 1, 1, ok);
+        TEST_IN_OUT ("\xe3\x91\x80", 3, 3, L"\x3440", 1, 1, ok);
+
+        if (strict_mode) {
+            // otherwise benign invalid patterns detected only in strict mode
+
+            // test the ability to detect and diagnose overlong sequences
+
+            // exercise, e.g., alternative encodings of U+0000 (i.e., <NUL>)
+            TEST_IN ("\xc0\x80",                 2, 0, L"", 1, 0, error);
+            TEST_IN ("\xe0\x80\x80",             3, 0, L"", 1, 0, error);
+            TEST_IN ("\xf0\x80\x80\x80",         4, 0, L"", 1, 0, error);
+            TEST_IN ("\xf8\x80\x80\x80\x80",     5, 0, L"", 1, 0, error);
+            TEST_IN ("\xfc\x80\x80\x80\x80\x80", 6, 0, L"", 1, 0, error);
+
+            // exercise, e.g., alternative encodings of U+000A (i.e., <LF>)
+            TEST_IN ("\xc0\x8a",                 2, 0, L"", 1, 0, error);
+            TEST_IN ("\xe0\x80\x8a",             3, 0, L"", 1, 0, error);
+            TEST_IN ("\xf0\x80\x80\x8a",         4, 0, L"", 1, 0, error);
+            TEST_IN ("\xf8\x80\x80\x80\x8a",     5, 0, L"", 1, 0, error);
+            TEST_IN ("\xfc\x80\x80\x80\x80\x8a", 6, 0, L"", 1, 0, error);
+
+            // test the ability to detect and diagnose UTF-16 surrogate
+            // pairs and the special code points U+FFFE and U+FFFF
+
+            TEST_OUT ("", 8, 0, L"\xd800", 1, 0, error);
+            TEST_OUT ("", 8, 0, L"\xd801", 1, 0, error);
+            TEST_OUT ("", 8, 0, L"\xdffe", 1, 0, error);
+            TEST_OUT ("", 8, 0, L"\xdfff", 1, 0, error);
+            TEST_OUT ("", 8, 0, L"\xfffe", 1, 0, error);
+            TEST_OUT ("", 8, 0, L"\xffff", 1, 0, error);
+
+            // the second and subsequent bytes of a multibyte UTF-8
+            // sequence must have the following bit pattern: 10xxxxxx
+            TEST_IN ("\xc2\x01", 2, 0, L"", 1, 0, error);
+            TEST_IN ("\xc2\xff", 2, 0, L"", 1, 0, error);
+
+        }
+        else {
+            // in relaxed mode the UTF-8 sequences below convert
+            // into the UCS characters U+3081 and U+30BF even
+            // though the UCS characters convert into 3-byte
+            // UTF-8 characters each (see below)
+            TEST_IN ("\xc2\x01", 2, 2, L"\x3081", 1, 1, ok);
+            TEST_IN ("\xc2\xff", 2, 2, L"\x30bf", 1, 1, ok);
+        }
+
+        TEST_OUT ("\xe3\x82\x81", 3, 3, L"\x3081", 1, 1, ok);
+        TEST_OUT ("\xe3\x82\xbf", 3, 3, L"\x30bf", 1, 1, ok);
+
+        TEST_IN_OUT ("\x00",      1, 1, L"\x00000000", 1, 1, ok);
+        TEST_IN_OUT ("\x7f",      1, 1, L"\x0000007f", 1, 1, ok);
+
+        TEST_IN_OUT ("\xc2\x80",  2, 2, L"\x00000080", 1, 1, ok);
+        TEST_IN_OUT ("\xdf\xbf",  2, 2, L"\x000007ff", 1, 1, ok);
+
+        TEST_IN_OUT ("\xe0\xa0\x80", 3, 3, L"\x00000800", 1, 1, ok);
+
+#if _RWSTD_WCHAR_T_MAX > 0xffffU
+
+        TEST_IN_OUT ("\xf0\x90\x8c\x80", 4, 4, L"\x00010300", 1, 1, ok);
+        TEST_IN_OUT ("\xf0\x90\x8c\x81", 4, 4, L"\x00010301", 1, 1, ok);
+        TEST_IN_OUT ("\xf4\x8f\xbf\x80", 4, 4, L"\x0010ffc0", 1, 1, ok);
+
+        TEST_IN_OUT ("\xf0\x90\x80\x80",         4, 4, L"\x0010000", 1, 1, ok);
+        TEST_IN_OUT ("\xf8\x88\x80\x80\x80",     5, 5, L"\x0200000", 1, 1, ok);
+        TEST_IN_OUT ("\xfc\x84\x80\x80\x80\x80", 6, 6, L"\x4000000", 1, 1, ok);
+
+#endif   // _RWSTD_WCHAR_T_MAX > 0xffffU
+    }
+}
+
+/****************************************************************************/
+
+static void
+test_ascii (const char *locname, const char* native_locname)
+{
+    _RWSTD_ASSERT (0 != locname);
+    _RWSTD_ASSERT (0 != native_locname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "Testing conversion of Extended ASCII range in "
+             "locale(\"%s\") against the native locale \"%s\"",
+             locname, native_locname);
+
+    wchar_t wascii [sizeof ext_ascii];
+
+    const std::size_t ext_num = sizeof ext_ascii - 2;
+          std::size_t int_num = ext_num;
+
+    // try to convert the whole extended ascii range
+    if (rwtest_convert_to_internal (use_libc, native_locname,
+                                    ext_ascii + 1, ext_num,
+                                    wascii, int_num)) {
+
+        wascii [int_num] = L'\0';
+
+        test_inout ('i', __LINE__, locname,
+                    ext_ascii + 1, ext_num, ext_num, wascii, int_num, int_num,
+                    std::codecvt_base::ok);
+
+        return;
+    }
+
+    // conversion of the whole range failed,
+    // convert one character at a time
+
+    for (std::size_t i = 1; i != UCHAR_MAX + 1; ++i) {
+
+        if (rwtest_convert_to_internal (use_libc, native_locname,
+                                        ext_ascii + i, 1,
+                                        wascii, int_num)) {
+            wascii [int_num] = L'\0';
+
+            test_inout ('i', __LINE__, locname,
+                        ext_ascii + i, 1, 1,
+                        wascii, int_num, int_num,
+                        std::codecvt_base::ok);
+        }
+    }
+}
+
+/****************************************************************************/
+ 
+// - checks the conversion for each the locales in the locales array
+static int
+run_test (int /*unused*/, char* /*unused*/ [])
+{
+    // set up RWSTD_LOCALE_ROOT and other environment variables
+    // here as opposed to at program startup to work around a
+    // SunOS 5.7 bug in putenv() (PR ##30017)
+    locale_root = rw_set_locale_root ();
+
+#if 0   // FIXME
+
+    // codecvt_byname<char, char, mbstate_t> behaves just like
+    // the base, codecvt<char, char, mbstate_t>, i.e., it does
+    // no conversion
+    test_inout (*this, char ());
+
+#endif   // 0/1
+
+    test_inout<wchar_t> ("wchar_t");
+
+    test_virtuals<Codecvt> (0);
+    test_virtuals<CodecvtW> ("C");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    test_virtuals<CodecvtBn> ("C");
+    test_virtuals<CodecvtBnW> ("C");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+#define TEST_UCS_MODIFIER(T, mod, enc, locname, f, i, is)                    \
+    do {                                                                     \
+        char locname_mod [256];   /* <locale-name>@<modifier>*/              \
+        if (*(mod))                                                          \
+            std::sprintf (locname_mod, "%s@%s", locname, (mod));             \
+        else                                                                 \
+            std::sprintf (locname_mod, "%s", locname);                       \
+                                                                             \
+        _TRY {                                                               \
+            const CodecvtBnW cc (locname_mod, 1);                            \
+            std::locale loc = std::locale (std::locale::classic (), &cc);    \
+                                                                             \
+            cc._C_opts |= cc._C_use_libstd;                                  \
+            cc._C_opts &= ~cc._C_use_libc;                                   \
+            test_ucs_modifier (locname_mod, enc, s, cc, f, i, is);           \
+                                                                             \
+        } _CATCH (...) {                                                     \
+            rw_assert (false, __FILE__, __LINE__,                            \
+                       "unexpected exception in locale test %s",             \
+                       locname_mod);                                         \
+        }                                                                    \
+    } while (0)
+
+#define TEST_LIBSTD(L,T,C,c,f,s,i,is,o,os,ur,ar,er,lr,mr)                  \
+    _TRY {                                                                 \
+        test_libstd_codecvt<T>(L,c,f,s,i,is,o,os,ur,ar,er,lr,mr);          \
+    } _CATCH (...) {                                                       \
+            rw_assert (false, __FILE__, __LINE__,                          \
+                       "unexpected exception in conversion using %s "      \
+                       "(locale %s)", C ? "C library" : "std library", L); \
+    }
+
+#define TEST_CONVERSION(T,L,C,f,s,i,is,o,os,ur,er,ar,lr,mr)             \
+    do {                                                                \
+        std::locale loc;                                                \
+        _TRY {                                                          \
+            loc = std::locale (L);                                      \
+        } _CATCH (...) {                                                \
+            rw_assert (false, __FILE__, __LINE__,                       \
+                       "locale(\"%s\") unexpectedly threw an "          \
+                       "exception; " LOCALE_ROOT_ENVAR " = %s", L,      \
+                       locale_root);                                    \
+            break;                                                      \
+        }                                                               \
+        _TRY {                                                          \
+            const T &cc = create_##T (loc);                             \
+                                                                        \
+            cc._C_opts |=  cc._C_use_libstd;                            \
+            cc._C_opts &= ~cc._C_use_libc;                              \
+            TEST_LIBSTD (L,T,C,cc,f,s,i,is,o,os,ur,ar,er,lr,mr);        \
+                                                                        \
+            if (C == true && rwtest_is_C_locale (f)) {                  \
+                cc._C_opts &= ~cc._C_use_libstd;                        \
+                cc._C_opts |=  cc._C_use_libc;                          \
+                TEST_LIBSTD(L,T,C,cc,f,s,i,is,o,os,ur,ar,er,lr,mr);     \
+            }                                                           \
+        } _CATCH (...) {                                                \
+            rw_assert (false, __FILE__, __LINE__,                       \
+                       "unexpected exception in locale test %s", L);    \
+        }                                                               \
+    } while (0)
+
+
+    static const struct {
+        const char* src_name;     // locale definition file name
+        const char* charmap_name; // charset description file name
+        const char* locale_name;  // name of the locale database
+        std::size_t nbytes;       // size of test buffer
+        std::size_t nchars;       // number of characters in buffer
+        std::size_t encoding;     // result of codecvt::encoding()
+        std::size_t max_length;   // result of codecvt::max_length()
+    } locales [] = {
+        // single-width encodings where the number of characters
+        // equals the number of bytes (and max_length == 1)
+        { "de_DE", "ISO-8859-1", "de_DE.ISO-8859-1",  6826,  6826, 1, 1 },
+        { "fr_FR", "ISO-8859-1", "fr_FR.ISO-8859-1",  3920,  3920, 1, 1 },
+        // multi-byte encodings (variable width, and max_length > 1)
+        { "ja_JP", "Shift_JIS" , "ja_JP.Shift_JIS", 25115, 13001, 0, 2 },
+#if !defined _MSC_VER
+        { "ja_JP", "EUC-JP"    , "ja_JP.EUC-JP",    20801, 14299, 0, 3 },
+        { "ja_JP", "UTF-8"     , "ja_JP.UTF-8",     25056, 12000, 0, 6 },
+#endif // !defined _MSC_VER
+
+        // terminate the array
+        { 0, 0, 0, 0, 0, 0, 0 }
+    };
+
+
+    // Testing actual locale databases with input files
+    rw_info (0, __FILE__, __LINE__,
+             "Testing locale databases - file conversions.");
+
+    // index of the first successfully built locale database
+    int first_good_locale = -1;
+
+    const char* const topdir = std::getenv ("TOPDIR");
+    if (!topdir || !*topdir) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "environment variable TOPDIR not set or empty");
+    }
+
+    for (std::size_t i = 0; locales [i].src_name; i++) {
+
+        // Testing actual locale databases with input files
+
+        // try to build a locale database and get its name
+        const char* const locname =
+            rw_localedef ("-w",
+                          locales [i].src_name,
+                          locales [i].charmap_name,
+                          locales [i].locale_name);
+
+        if (!locname)
+            continue;
+
+        // find the native locale name correspomding to the canonical
+        // locale name hardcoded in the table above
+        const char* const native_locname =
+            find_locale (locales [i].locale_name, locales [i].charmap_name);
+
+        if (native_locname)
+            test_ascii (locales [i].locale_name, native_locname);
+        else {
+            std::fprintf (stderr, "*** failed to find a native locale to match"
+                          " locale(\"%s\"), skipping Extended ASCII conversion"
+                          " test\n", locales [i].locale_name);
+        }
+
+#define TESTS_ETC_PATH  "tests" SLASH "etc"
+
+        // determine the full pathname of test files in the source tree
+        char pathname [PATH_MAX];
+        std::strcpy (pathname, topdir);
+        std::strcat (pathname, SLASH TESTS_ETC_PATH SLASH "codecvt.");
+        std::strcat (pathname, locales [i].locale_name);
+        std::strcat (pathname, ".in");
+
+        const char* const s = pathname;
+
+        // exercise the behavior of codecvt<char, char, mbstate_t>
+        TEST_CONVERSION (Codecvt, locales [i].locale_name, true, s, true,
+                         std::codecvt_base::noconv, locales [i].nbytes,
+                         std::codecvt_base::noconv, locales [i].nbytes,
+                         std::codecvt_base::noconv, 1,
+                         true, locales [i].nbytes, 1);
+
+        // exercise the behavior of codecvt_byname<char, char, mbstate_t>
+        TEST_CONVERSION (CodecvtBn, locales [i].locale_name, true, s, true,
+                         std::codecvt_base::noconv, locales [i].nbytes,
+                         std::codecvt_base::noconv, locales [i].nbytes,
+                         std::codecvt_base::noconv, 1,
+                         true, locales [i].nbytes, 1);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+        // exercise the behavior of codecvt<wchar_t, char, mbstate_t>
+        TEST_CONVERSION (CodecvtW, locales [i].locale_name, true, s, true,
+                         std::codecvt_base::ok, locales [i].nbytes,
+                         std::codecvt_base::ok, locales [i].nbytes,
+                         std::codecvt_base::noconv, 1,
+                         false, locales [i].nbytes, 1);
+
+        // exercise the behavior of codecvt_byname<wchar_t, char, mbstate_t>
+        TEST_CONVERSION (CodecvtBnW, locales [i].locale_name, true, s, false,
+                         std::codecvt_base::ok,  locales [i].nchars,
+                         std::codecvt_base::ok,  locales [i].nbytes,
+                         std::codecvt_base::noconv, locales [i].encoding,
+                         false, locales [i].nchars, locales [i].max_length);
+
+
+
+        // save the index of the first locale database successfully built
+        if (-1 == first_good_locale)
+            first_good_locale = _RWSTD_STATIC_CAST (int, i);
+
+        // FIXME: Until the LE (little endian) and BE (big endian) extra
+        // modifiers are implemented, the test is skipped for Linux distros
+        // such as Red Hat 6.2 that ship with glibc 2.1.1-6
+
+#  if !defined __GLIBC__ \
+      || __GLIBC__ == 2 && __GLIBC_MINOR__ > 1 \
+      || __GLIBC__ > 2
+
+        // exercise the behavior of codecvt_byname<wchar_t, char, mbstate_t>
+        // in constructed with one of the additional @UCS name modifiers
+        TEST_UCS_MODIFIER (CodecvtBnW, "", use_libc,
+                           locales [i].locale_name, s, std::codecvt_base::ok,
+                           locales [i].nchars);
+
+        const InternalEncoding which_ucs =
+            sizeof (wchar_t) == 4 ? use_UCS4 : use_UCS2;
+
+        TEST_UCS_MODIFIER (CodecvtBnW,
+                           use_UCS4 == which_ucs ? "UCS-4" : "UCS-2", which_ucs,
+                           locales [i].locale_name, s, std::codecvt_base::ok,
+                           locales [i].nchars);
+
+        TEST_UCS_MODIFIER (CodecvtBnW, "UCS", which_ucs,
+                           locales [i].locale_name, s, std::codecvt_base::ok,
+                           locales [i].nchars);
+
+#  endif   // GLIBC version > 2.1
+#endif   // _RWSTD_NO_WCHAR_T
+
+    }
+
+    // exercise the behavior of the facets when passed
+    // an uninitialized or corrupt mbstate_t object
+    test_invalid_args (-1 == first_good_locale ?
+                       (char*)0 : locales [first_good_locale].locale_name);
+
+    return 0;
+}
+
+
+/*extern*/ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "[lib.locale.codecvt]",
+                    "",   // no comment
+                    run_test, "", 0);
+}
+
diff --git a/tests/localization/22.locale.codecvt.mt.cpp b/tests/localization/22.locale.codecvt.mt.cpp
index 9b3cc26..55f071d 100644
--- a/tests/localization/22.locale.codecvt.mt.cpp
+++ b/tests/localization/22.locale.codecvt.mt.cpp
@@ -45,18 +45,21 @@
 
 // default number of threads (will be adjusted to the number
 // of processors/cores later)
-int rw_opt_nthreads = 1;
+int opt_nthreads = 1;
 
 // the number of times each thread should iterate (unless specified
 // otherwise on the command line)
-int rw_opt_nloops = 5000;
+int opt_nloops = 5000;
 
 // number of locales to use
-int rw_opt_nlocales = MAX_THREADS;
+int opt_nlocales = MAX_THREADS;
 
 // should all threads share the same set of locale objects instead
 // of creating their own?
-int rw_opt_shared_locale;
+int opt_shared_locale;
+
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
 
 /**************************************************************************/
 
@@ -314,7 +317,10 @@
     const int ni = RW_COUNT_OF (nsrc);
     const int wi = RW_COUNT_OF (wsrc);
 
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    for (int i = 0; i != opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
 
         const int inx = i % nlocales;
         const MyCodecvtData& data = my_codecvt_data [inx];
@@ -322,8 +328,8 @@
         // construct a named locale, get a reference to the codecvt
         // facet from it and use it to format a random money value
         const std::locale loc =
-            rw_opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+            opt_shared_locale ? data.locale_
+                              : std::locale (data.locale_name_);
 
         const MyCodecvtData::CvtId op =
             MyCodecvtData::CvtId (i % MyCodecvtData::cvt_max);
@@ -460,7 +466,7 @@
             run_test_fill<wchar_t>
                 (loc, wsrc [inx % wi], nsrc [inx % ni], data.wchar_data_);
 
-            if (rw_opt_shared_locale)
+            if (opt_shared_locale)
                 data.locale_ = loc;
 
             nlocales += 1;
@@ -471,7 +477,7 @@
                      "failed to create locale(%#s)", name);
         }
 
-        if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
+        if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
             break;
     }
 
@@ -482,8 +488,8 @@
     rw_info (0, 0, 0,
              "testing std::codecvt<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
-             rw_opt_nthreads, 1 != rw_opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops,
+             opt_nthreads, 1 != opt_nthreads,
+             opt_nloops, 1 != opt_nloops,
              nlocales, int (nlocales), "%#s", locales);
 
     ///////////////////////////////////////////////////////////////////////
@@ -495,11 +501,12 @@
 
     // create and start a pool of threads and wait for them to finish
     int result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -509,11 +516,12 @@
     test_wchar  = true;
 
     result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -524,11 +532,12 @@
     test_wchar  = true;
 
     result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     return result;
 }
@@ -541,24 +550,26 @@
 
     // set nthreads to the greater of the number of processors
     // and 2 (for uniprocessor systems) by default
-    rw_opt_nthreads = rw_get_cpus ();
-    if (rw_opt_nthreads < 2)
-        rw_opt_nthreads = 2;
+    opt_nthreads = rw_get_cpus ();
+    if (opt_nthreads < 2)
+        opt_nthreads = 2;
 
 #endif   // _RWSTD_REENTRANT
 
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.codecvt",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // must be non-negative
                     "|-nthreads#0-* "    // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "      // arg must be non-negative
                     "|-locales= "        // must be provided
                     "|-shared-locale# ",
-                    &rw_opt_nloops,
+                    &opt_timeout,
+                    &opt_nloops,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads,
-                    &rw_opt_nlocales,
+                    &opt_nthreads,
+                    &opt_nlocales,
                     &rw_opt_setlocales,
-                    &rw_opt_shared_locale);
+                    &opt_shared_locale);
 }
diff --git a/tests/localization/22.locale.codecvt.out.cpp b/tests/localization/22.locale.codecvt.out.cpp
index 5599c15..bb331fb 100644
--- a/tests/localization/22.locale.codecvt.out.cpp
+++ b/tests/localization/22.locale.codecvt.out.cpp
@@ -197,7 +197,7 @@
 struct WideCode
 {
     wchar_t wchar;
-    char    mbchar [MB_LEN_MAX];
+    char    mbchar [MB_LEN_MAX + 1];
 };
 
 typedef WideCode mb_char_array_t [MB_LEN_MAX];
diff --git a/tests/localization/22.locale.collate.cpp b/tests/localization/22.locale.collate.cpp
new file mode 100644
index 0000000..f922d3c
--- /dev/null
+++ b/tests/localization/22.locale.collate.cpp
@@ -0,0 +1,1118 @@
+/***************************************************************************
+ *
+ * 22.locale.collate.cpp -- tests for collate-facet member functions
+ *
+ * $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.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ *
+ **************************************************************************/
+
+#include <locale>     // for collate, locale
+#include <string>     // for string
+
+#include <algorithm>  // for sort and unique
+#include <climits>    // for UCHAR_MAX
+#include <clocale>    // for LC_COLLATE, setlocale
+#include <cstdlib>    // for exit()
+#include <cstdio>     // for fprintf()
+#include <cstring>    // for strcmp(), strcoll(), ...
+#include <cwchar>     // for wcscoll()
+
+#include <driver.h>
+#include <environ.h>
+#include <file.h>
+#include <rw_locale.h>
+#include <rw_process.h>
+
+
+#if _RWSTD_PATH_SEP == '/'
+#  define SLASH                 "/"
+#else
+#  define SLASH                 "\\"
+#endif
+
+// strings declared extern to work around a SunPro bug (PR #28124)
+// get the source root
+#define RELPATH                 "etc" SLASH "nls"
+#define TESTS_ETC_PATH          "tests" SLASH "etc"
+
+// the root of the locale directory (RWSTD_LOCALE_ROOT)
+#define LOCALE_ROOT             "RWSTD_LOCALE_ROOT"
+const char* locale_root;
+
+#define LC_COLLATE_SRC          "LC_COLLATE.src"
+#define LC_COLLATE_CM           "LC_COLLATE.cm"
+#define TEST_LOCALE_NAME        "test.locale"
+
+/**************************************************************************/
+
+// These overloads are necessary in our template
+// functions so that we can make a single function call reguardless
+// of the charT we are using
+
+int c_strcoll (const char* s1, const char* s2)
+{
+    const int ret = std::strcoll(s1, s2);
+    return ret ? ret > 0 ? 1 : -1 : 0;
+}
+
+std::size_t c_xfrm (char* to, const char* from, std::size_t size)
+{
+    char safety_buf [8];
+    if (0 == to && 0 == size) {
+        // prevent buggy implementations (such as MSVC 8) from trying
+        // to write to the destination buffer even though it's 0 and
+        // its size is zero (see stdcxx-69)
+        to = safety_buf;
+        *to = '\0';
+    }
+
+    std::size_t n = std::strxfrm (to, from, size);
+
+    if (to)
+        n = std::strlen (to);
+
+    return n;
+}
+
+std::size_t c_strlen (const char* s1)
+{
+    return std::strlen (s1);
+}
+
+const char* narrow (char* dst, const char* src)
+{
+    if (src == dst || !src || !dst)
+        return src;
+
+    std::memcpy (dst, src, std::strlen (src) + 1);
+    return dst;
+}
+
+const char* widen (char* dst, const char* src)
+{
+    if (src == dst || !src || !dst)
+        return src;
+
+    std::memcpy (dst, src, std::strlen (src) + 1);
+    return dst;
+}
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+int c_strcoll (const wchar_t* s1, const wchar_t* s2)
+{
+    const int ret = std::wcscoll(s1, s2);
+    return ret ? ret > 0 ? 1 : -1 : 0;
+}
+
+std::size_t c_xfrm (wchar_t* to, const wchar_t* from, std::size_t size)
+{
+#if !defined (_MSC_VER) || _MSC_VER > 1200
+
+    wchar_t safety_buf [8];
+    if (0 == to && 0 == size) {
+        // prevent buggy implementations (such as MSVC 8) from trying
+        // to write to the destination buffer even though it's 0 and
+        // its size is zero (see stdcxx-69)
+        to = safety_buf;
+        *to = L'\0';
+    }
+
+    std::size_t n = std::wcsxfrm (to, from, size);
+
+    if (to)
+        n = std::wcslen (to);
+
+#else   // MSVC 6 and prior
+
+    // working around an MSVC 6.0 libc bug (PR #26437)
+
+    if (to) {
+        std::size_t n = std::wcsxfrm (to, from, size);
+
+        n = std::wcslen (to);
+
+        return n;
+    }
+
+    wchar_t tmp [1024];
+
+    std::size_t n = std::wcslen (from);
+
+    _RWSTD_ASSERT (n < sizeof tmp / sizeof *tmp);
+
+    std::wcscpy (tmp, from);
+
+    std::wcsxfrm (tmp, from, sizeof tmp / sizeof *tmp);
+
+    n = std::wcslen (tmp);
+
+#endif   // MSVC 6
+
+    return n;
+}
+
+std::size_t c_strlen (const wchar_t* s1)
+{
+    return std::wcslen (s1);
+}
+
+const wchar_t* widen (wchar_t* dst, const char* src)
+{
+    static wchar_t buf [4096];
+
+    if (!src)
+        return 0;
+
+    if (!dst)
+        dst = buf;
+
+    std::size_t len = std::strlen (src);
+
+    _RWSTD_ASSERT (len < sizeof buf /sizeof *buf);
+
+    len = std::mbstowcs (dst, src, sizeof buf / sizeof *buf);
+
+    if (std::size_t (-1) == len)
+        *dst = 0;
+
+    return dst;
+}
+
+const char* narrow (char* dst, const wchar_t* src)
+{
+    static char buf [4096];
+
+    if (!src)
+        return 0;
+
+    if (!dst)
+        dst = buf;
+
+    std::size_t len = std::wcslen (src);
+
+    _RWSTD_ASSERT (len < sizeof buf);
+
+    len = std::wcstombs (dst, src, sizeof buf / sizeof *buf);
+
+    if (std::size_t (-1) == len)
+        *dst = 0;
+
+    return dst;
+}
+
+#endif   //_RWSTD_NO_WCHAR_T
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+gen_str (charT* str, std::size_t size)
+{
+    // generate a random string with the given size
+    if (!size)
+        return;
+
+    // use ASCII characters in the printable range
+    for (std::size_t i = 0; i != size - 1; ++i)
+        str [i] = ' ' + std::rand () % ('~' - ' ');
+
+    str [size - 1] = charT ();
+}
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+check_libc (const char* charTname)
+{
+    // the libc implementation of the library should act the same as
+    // the c-library.  Go through all the locales, generate some random
+    // strings and make sure that the following holds true:
+    // transform acts like strxfrm and wcsxfrm,
+    // compare acts like strcoll and wcscoll
+
+    int nfail [3] = { 0 };
+
+    rw_info (0, __FILE__, __LINE__,
+             "libc std::collate<%s>::transform ()", charTname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "libc std::collate<%s>::compare ()", charTname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "std::collate<%s>::hash ()", charTname);
+
+    for (const char* locname = rw_locales (LC_COLLATE);
+         *locname; locname += std::strlen (locname) + 1) {
+
+        _TRY {
+            std::setlocale (LC_COLLATE, locname);
+            int max = MB_CUR_MAX;
+            if (max > 1)
+                continue;
+
+            std::locale loc;
+
+            _TRY {
+                loc = std::locale (locname);
+            }
+            _CATCH (...) {
+                rw_assert (false, __FILE__, __LINE__,
+                           "std::locale(\"%s\") unexpectedly threw "
+                           "an exception", locname);
+                continue;
+            }
+
+            const std::collate<charT> &co =
+                _STD_USE_FACET (std::collate<charT>, loc);
+            co._C_opts |= co._C_use_libc;
+            co._C_opts &= ~co._C_use_libstd;
+
+            // now the locale is set up so lets test the transform and
+            // compare functions
+
+            for (int loop_cntrl = 0; loop_cntrl < 10; loop_cntrl++) {
+
+#define STR_SIZE 16
+
+                charT str1 [STR_SIZE] = { 0 };
+                charT str2 [STR_SIZE] = { 0 };
+
+                // generate two random NUL-terminated strings
+                gen_str (str1, sizeof str1 / sizeof *str1);
+                gen_str (str2, sizeof str2 / sizeof *str2);
+
+                // call transform on the generated string
+                // not including the terminating NUL
+                const std::basic_string <charT, std::char_traits<charT>,
+                    std::allocator<charT> > out =
+                    co.transform (str1, str1 + sizeof str1 / sizeof *str1 - 1);
+
+                // get the size of the buffer needed to hold the
+                // transformed string (with the terminating NUL)
+                std::size_t size = 1U + c_xfrm (0, str1, 0);
+
+                // prevent errors caused by huge return values (e.g., MSVC)
+                if (size > STR_SIZE * 64)
+                    size = 0;
+
+                std::basic_string <charT, std::char_traits<charT>,
+                    std::allocator<charT> > c_out;
+
+                if (size) {
+                    c_out.resize (size);
+
+                    // call the C-library transform function
+                    size = c_xfrm (&c_out [0], str1, size);
+
+                    if (size > STR_SIZE * 64)
+                        size = 0;
+
+                    // shrink to fit (chop off the terminating NUL)
+                    c_out.resize (size);
+                }
+
+                // make sure the output is the same
+                if (out != c_out) {
+                    nfail[0]++;
+                    rw_assert (false, __FILE__, __LINE__,
+                               "%d. collate<%s>::transform(%s, ...) "
+                               "== %{S}, got %{S} in locale(\"%s\")",
+                               loop_cntrl, charTname, str1,
+                               &c_out, &out, locname);
+                }
+
+                // now call compare on the two generated strings
+                int ret1 = co.compare (str1, str1 + sizeof str1 / sizeof *str1,
+                                       str2, str2 + sizeof str2 / sizeof *str2);
+
+                // call the C-library comparison function
+                int ret2 = c_strcoll (str1, str2);
+
+                // make sure the results are the same
+                if (ret1 != ret2) {
+                    nfail [1]++;
+                    rw_assert (false, __FILE__, __LINE__,
+                               "%d. collate<%s>::compare(%s, ..., %s, ...) "
+                               "== %d, got %d in locale(\"%s\")",
+                               loop_cntrl, charTname, str1,
+                               str2, ret2, ret1, locname);
+                }
+
+                // two strings that compare identically must hash
+                // identically as well.  Calling hash on the same string is
+                // not very conclusive but generating strings that have exactly
+                // the same weights is not possible without knowing all the
+                // weight orderings
+                const long hashNum1 =
+                    co.hash (str1, str1 + sizeof str1 / sizeof *str1);
+
+                const long hashNum2 =
+                    co.hash (str1, str1 + sizeof str1 / sizeof *str1);
+
+                if (hashNum1 != hashNum2) {
+                    nfail[2]++;
+                    rw_assert (false, __FILE__, __LINE__,
+                               "%d. collate<%s>::hash(%s, ...) == %d, "
+                               "got %d in locale(\"%s\")",
+                               loop_cntrl, charTname, str1,
+                               hashNum1, hashNum2, locname);
+                }
+
+
+            }
+        }
+        _CATCH (...) {
+            rw_assert (false, __FILE__, __LINE__,
+                       "locale(\"%s\") threw an exception", locname);
+        }
+    }
+
+    rw_assert (0 == nfail [0], __FILE__, __LINE__,
+               "collate<%s>::transform () failed %d times",
+               charTname, nfail [0]);
+
+    rw_assert (0 == nfail [1], __FILE__, __LINE__,
+               "collate<%s>::compare () failed %d times",
+               charTname, nfail [1]);
+
+    rw_assert (0 == nfail [2], __FILE__, __LINE__,
+               "collate<%s>::hash () failed %d times",
+               charTname, nfail [2]);
+}
+
+/**************************************************************************/
+
+static const char*
+make_test_locale ()
+{
+    // create a temporary locale definition file that exercises as
+    // many different parts of the collate standard as possible
+
+    char lc_collate_src_path [L_tmpnam + sizeof LC_COLLATE_SRC + 2];
+    std::strcpy (lc_collate_src_path, locale_root);
+    std::strcat (lc_collate_src_path, SLASH);
+    std::strcat (lc_collate_src_path, LC_COLLATE_SRC);
+
+    std::FILE *fout = std::fopen (lc_collate_src_path, "w");
+
+    const char lc_collate_file[] = {
+        "LC_COLLATE\n"
+        "script <ALL_FORWARD>\n"
+        "collating-element <er> from \"<e><r>\"\n"
+        "collating-element <ic> from \"ic\"\n"
+        "collating-symbol <LETTER>\n"
+        "collating-symbol <COLLATING_ELEMENT>\n"
+        "collating-symbol <DIGIT>\n"
+
+        "order_start forward;backward;forward,position\n"
+        "<LETTER>\n"
+        "<COLLATING_ELEMENT>\n"
+        "<DIGIT>\n"
+
+        "<a> <a> <LETTER> IGNORE\n"
+        "<b> <b> <LETTER> IGNORE\n"
+
+        // "<c>" will have a non-ignored position ordering
+        "<c> <c> <LETTER> <c>\n"
+
+        // try giving "<d>" a many-to-one weight
+        "<d> \"<d><a>\" <LETTER> IGNORE\n"
+
+        // try giving "<e>" a decimal value weight
+        "<e> \\d139 <LETTER> IGNORE\n"
+
+        // try giving "<f>" an octal value weight
+        "<f> \\36 <LETTER> IGNORE\n"
+
+        // try giving "<g>" a hex value weight
+        "<g> \\x3A <LETTER> IGNORE\n"
+
+        "<zero> <zero> <DIGIT> IGNORE\n"
+        "<one> <one> <DIGIT> <zero>\n"
+        "<two> <two> <DIGIT> IGNORE\n"
+        "<three> <three> <DIGIT> IGNORE\n"
+        "<er> <a> <COLLATING_ELEMENT> IGNORE\n"
+
+        // the <ic> collating element will be equivalent to the letter <c>
+        "<ic> <c> <LETTER> <c>\n"
+        "UNDEFINED IGNORE IGNORE IGNORE\n"
+
+        "order_end\n"
+
+        // define a section in which all of the orders are forward orders
+        "order_start <ALL_FORWARD>;forward;forward;forward\n"
+        "<h>\n<i>\n<j>\n<k>\n"
+        "order_end\n"
+
+        // reorder the elementes in the <ALL_FORWARD> section to appear
+        // after the letter "<g>"
+        "reorder-after <g>\n"
+        "<h>\n<i>\n<j>\n<k>\n"
+
+        // try to reorder "<a>" after "<b>"
+        "reorder-after <b>\n"
+        "<a> <a> <LETTER> IGNORE\n"
+        "reorder-end\n"
+
+        "\nEND LC_COLLATE\n"
+    };
+
+    std::fputs (lc_collate_file, fout);
+
+    std::fclose (fout);
+
+    // create a temporary character map file
+
+    char lc_collate_cm_path [L_tmpnam + sizeof LC_COLLATE_CM + 2];
+    std::strcpy (lc_collate_cm_path, locale_root);
+    std::strcat (lc_collate_cm_path, SLASH);
+    std::strcat (lc_collate_cm_path, LC_COLLATE_CM);
+
+    fout = std::fopen (lc_collate_cm_path, "w");
+    pcs_write (fout, 0);
+
+    std::fclose (fout);
+
+    return rw_localedef ("-w", lc_collate_src_path,
+                         lc_collate_cm_path,
+                         TEST_LOCALE_NAME);
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+/*static*/ void
+check_libstd_test_locale (const char* charTname)
+{
+    rw_info (0, __FILE__, __LINE__,
+             "libstd std::collate<%s>::transform () "
+             "collate test database", charTname);
+    rw_info (0, __FILE__, __LINE__,
+             "libstd std::collate<%s>::compare () collate test "
+             "database", charTname);
+    rw_info (0, __FILE__, __LINE__,
+             "libstd std::collate<%s>::hash () collate test "
+             "database", charTname);
+
+    const char* const locname = make_test_locale ();
+    if (locname) {
+
+        std::locale loc;
+
+        _TRY {
+            loc = std::locale (locname);
+        }
+        _CATCH (...) {
+            const char* const var = std::getenv (LOCALE_ROOT);
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "std::locale(\"%s\") unexpectedly threw "
+                       "an exception; " LOCALE_ROOT "=%s",
+                       locname, var ? var : "(null)");
+            return;
+        }
+
+        const std::collate<charT> &co =
+            _STD_USE_FACET (std::collate<charT>, loc);
+        co._C_opts |=  co._C_use_libstd;
+        co._C_opts &= ~co._C_use_libc;
+
+#define IGNORE 0
+
+        // first lets make sure that each character was given the
+        // correct weight for each level.
+
+#undef TEST
+#define TEST(ch, w0, w1, w2, w3, w3_is_fp)   \
+  test_weight_val (charTname, co, charT (ch), w0, w1, w2, w3, w3_is_fp)
+
+        TEST ('a',       6, IGNORE,      2, IGNORE, true);
+        TEST ('b',       5, IGNORE,      2, IGNORE, true);
+        TEST ('c',       7, IGNORE,      2,      7, true);
+        TEST ('d',       8,      6,      2, IGNORE, true);
+        TEST ('e',     139, IGNORE,      2, IGNORE, true);
+        TEST ('f',      30, IGNORE,      2, IGNORE, true);
+        TEST ('g',      58, IGNORE,      2, IGNORE, true);
+        TEST ('h',      12, IGNORE,     12,     12, false);
+        TEST ('i',      13, IGNORE,     13,     13, false);
+        TEST ('j',      14, IGNORE,     14,     14, false);
+        TEST ('k',      15, IGNORE,     15,     15, false);
+        TEST ('0',      16, IGNORE,      4, IGNORE, true);
+        TEST ('1',      17, IGNORE,      4,     16, true);
+        TEST ('2',      18, IGNORE,      4, IGNORE, true);
+        TEST ('3',      19, IGNORE,      4, IGNORE, true);
+        TEST ('l',  IGNORE, IGNORE, IGNORE, IGNORE, true);
+
+        // make sure that strings collate the way we expect them to
+
+        // a should collate greater then b
+        test_string (charTname, co, "a", "b", 1) ;
+
+        // the collating element "er" should collate after 'a' and 'b'
+        // but before 'c'
+        test_string (charTname, co, "er", "a", 1);
+        test_string (charTname, co, "er", "b", 1);
+        test_string (charTname, co, "er", "c", -1);
+
+        // the collating element "ic" should be equivalent to the letter 'c'
+        test_string (charTname, co, "ic", "c", 0);
+
+
+        // two strings that compare identically must hash
+        // identically as well.
+        // since ic and c are equivalent elements string they should hash
+        // the same
+        test_hash (charTname, co, "c", "ic");
+    }
+    else
+        rw_assert (false, __FILE__, __LINE__,
+                   "unable to create a locale database");
+}
+
+/**************************************************************************/
+
+enum { bufsiz = 256 };
+
+template <class charT>
+/*static*/ void
+test_hash (const char* charTname, const std::collate<charT>& co,
+           const char* str1, const char* str2)
+{
+    // convert narrow string to a (possibly) wide representation
+    charT wstrbuf [bufsiz];
+    charT wstrbuf2 [bufsiz];
+
+    const charT* const wstr = widen (wstrbuf, str1);
+    const charT* const wstr2 = widen (wstrbuf2, str2);
+
+    long hashNum1 = co.hash (wstr, wstr + c_strlen (wstr));
+    long hashNum2 = co.hash (wstr2, wstr2 + c_strlen (wstr2));
+
+    if (hashNum1 != hashNum2) {
+        rw_assert (false, __FILE__, __LINE__,
+                   "collate<%s>::hash(%s, ...) returned %d and\n "
+                   "collate<%s>::hash(%s, ...) returned %d",
+                   charTname, str1,
+                   hashNum1, charTname, str2, hashNum2);
+    }
+}
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+test_string (const char* charTname, const std::collate<charT>& co,
+             const char* str1, const char* str2,
+             int expected_val)
+{
+    // convert narrow string to a (possibly) wide representation
+    charT wstrbuf [bufsiz];
+    charT wstrbuf2 [bufsiz];
+
+    const charT* const wstr = widen (wstrbuf, str1);
+    const charT* const wstr2 = widen (wstrbuf2, str2);
+
+    int ret = co.compare (wstr, wstr + c_strlen (wstr),
+                          wstr2, wstr2 +  c_strlen(wstr2));
+    if (ret != expected_val)
+        rw_assert (false, __FILE__, __LINE__,
+                   "libstd std::collate<%s>::compare"
+                   "(%s, ..., %s, ...) == %d, got %d",
+                   charTname, str1, str2, expected_val, ret);
+}
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+test_weight_val (const char* charTname, const std::collate<charT>& co,
+                 charT ch, int w1a, int w1b, int w2, int w3, bool w3_is_fp)
+{
+    int w [3][2] = { { w1a, w1b }, { w2, IGNORE }, { w3, IGNORE } };
+
+    typedef std::char_traits<charT>                  Traits;
+    typedef std::allocator<charT>                    Alloc;
+    typedef std::basic_string <charT, Traits, Alloc> String;
+
+    // construct an expected transformed string out of the weight arguments
+    String expected;
+
+    if (sizeof (charT) == sizeof (char)) {
+        for (int i = 0; i < 3; ++i) {
+            for (int k = 0; k < 2; ++k) {
+                if (w [i][k] != IGNORE) {
+                    while (w [i][k] > _RWSTD_CHAR_MAX) {
+                        expected += charT (_RWSTD_CHAR_MAX);
+                        w [i][k] -= _RWSTD_CHAR_MAX;
+                    }
+                    expected += charT (w [i][k]);
+                }
+                else if (i == 2 && k == 0 && w3_is_fp)
+                    expected += charT (_RWSTD_CHAR_MAX);
+            }
+
+            // mark the end of the pass
+            expected += charT (1);
+        }
+    }
+    else {
+        for (int i = 0; i < 3; ++i) {
+            for (int k = 0; k < 2; ++k) {
+                if (w [i][k] != IGNORE) {
+                    expected += charT (w [i][k]);
+                }
+                else if (i == 2 && k == 0 && w3_is_fp)
+                    expected += charT (_RWSTD_WCHAR_MAX);
+            }
+
+            expected += charT (1);
+        }
+    }
+
+    // get the transformed string
+    const String actual = co.transform (&ch, &ch + 1);
+
+    // make sure the strings are equal
+    rw_assert (expected != actual, __FILE__, __LINE__,
+               "collate<%s>::transform (\"%c\", ...) == %{S}, "
+               "got %{S}", charTname, ch, &expected, &actual);
+}
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+check_libstd (const char* charTname)
+{
+    rw_info (0, __FILE__, __LINE__,
+             "libstd std::collate<%s>::transform () sorting "
+             "file test", charTname);
+
+    rw_info (0, __FILE__, __LINE__,
+             "libstd std::collate<%s>::compare () sorting "
+             "file test", charTname);
+
+
+    // This test works by using a series of sorted input files
+    // we randomize the words in the input files and sort them using
+    // the proper locale's collate facet.  This test will automatically
+    // generate the required locales.
+
+    static const char* const locales[][3] = {
+        //
+        // +-- locale name
+        // |        +-- character set
+        // |        |             +-- input file name
+        // |        |             |
+        // V        V             V
+        { "cs_CZ", "ISO-8859-2", "collate.cs_CZ.in" },   // Czech, Czech Rep.
+        { "da_DK", "ISO-8859-1", "collate.da_DK.in" },   // Danish, Denmark
+        { "en_US", "ISO-8859-1", "collate.en_US.in" },   // English, US
+        { "hr_HR", "ISO-8859-2", "collate.hr_HR.in" },   // Hungarian, Hungary
+        { "sv_SE", "ISO-8859-1", "collate.sv_SE.in" },   // Swedish, Sweden
+        { "th_TH", "TIS-620",    "collate.th_TH.in" }    // Thai, Thailand
+    };
+
+    const std::size_t nlocales = sizeof locales / sizeof *locales;
+
+    typedef std::char_traits<charT>                     Traits;
+    typedef std::allocator<charT>                       Allocator;
+    typedef std::basic_string<charT, Traits, Allocator> String;
+
+    for (std::size_t i = 0; i < nlocales; ++i) {
+
+        const char* const locname =
+            rw_localedef ("-w --no_position",
+                          locales [i][0], locales [i][1], 0);
+
+        if (locname) {
+
+            std::locale loc;
+
+            _TRY {
+                loc = std::locale (locname);
+            }
+            _CATCH (...) {
+                const char* const var = std::getenv (LOCALE_ROOT);
+
+                rw_assert (false, __FILE__, __LINE__,
+                           "std::locale(\"%s\") unexpectedly threw "
+                           "an exception; " LOCALE_ROOT "=%s",
+                           locname, var ? var : "(null)");
+                continue;
+            }
+
+            const std::collate<charT> &co =
+                _STD_USE_FACET (std::collate<charT>, loc);
+
+            co._C_opts |= co._C_use_libstd;
+            co._C_opts &= ~co._C_use_libc;
+
+            typedef std::codecvt<charT, char, std::mbstate_t> CodeCvt;
+
+            const CodeCvt &cvt = _STD_USE_FACET (CodeCvt, loc);
+
+            cvt._C_opts |= cvt._C_use_libstd;
+            cvt._C_opts &= ~cvt._C_use_libc;
+
+            // 'in' holds the strings from the input file and is there
+            // sorting will take place.
+            String in [1000];
+
+            // out holds the strings located in the output file
+            String out [1000];
+
+#define TOPDIR   "TOPDIR"   /* the TOPDIR environment variable */
+
+            const char* in_path = std::getenv (TOPDIR);
+            if (!in_path || !*in_path) {
+                std::fprintf (stderr, "TOPDIR not defined or empty");
+
+                std::exit (1);
+            }
+
+            std::string path (in_path);
+            path += SLASH TESTS_ETC_PATH SLASH;
+            path += locales [i][2];
+
+            std::FILE* const f = std::fopen (path.c_str (), "r");
+            if (!f) {
+                rw_assert (false, __FILE__, __LINE__,
+                           "file \"%s\" could not be opened", path.c_str ());
+                break;
+            }
+
+            std::size_t j = 0;
+            while (1) {
+                char next_line [bufsiz];
+
+                if (0 != std::fgets (next_line, bufsiz, f)) {
+
+                    std::size_t line_len = std::strlen (next_line);
+
+                    // get rid of the newline character
+                    next_line [--line_len] = '\0';
+
+                    // convert from external to internal encoding
+                    // (both of which might be the same type)
+                    charT to [bufsiz];
+                    const char* from_next;
+                    charT*      to_next;
+
+                    static std::mbstate_t initial;
+                    std::mbstate_t mbs = initial;
+
+                    const std::codecvt_base::result res =
+                        cvt.in (mbs,
+                                next_line, next_line + line_len + 1,
+                                from_next,
+                                to, to + sizeof to / sizeof *to,
+                                to_next);
+
+                    if (cvt.ok == res) {
+                        in [j]  = to;
+                        out [j] = to;
+                    }
+                    else if (cvt.noconv == res) {
+                        in [j]  = (charT*)next_line;
+                        out [j] = (charT*)next_line;
+                    }
+
+                    j++;
+                }
+                else
+                    break;
+            }
+            // close the file
+            std::fclose (f);
+
+            // now bubble sort the items in the array
+            std::size_t idx;
+            std::size_t idx2;
+            String tmp;
+            String tmp2;
+
+            bool flipped;
+
+            if (j > 1) {
+                idx = 1;
+                do {
+                    flipped = false;
+                    for (idx2 = j - 1; idx2 >= idx; --idx2) {
+
+                        const std::size_t idx1 = idx2 - 1;
+
+                        if (co.compare (in [idx1].c_str (),
+                                        in [idx1].c_str () + in [idx1].size (),
+                                        in [idx2].c_str (),
+                                        in [idx2].c_str () + in [idx2].size ())
+                            > 0) {
+                            in [idx1].swap (in [idx2]);
+                            flipped = true;
+                        }
+                    }
+                } while (++idx < j && flipped);
+            }
+
+            // the items are sorted now lets make sure that they are sorted
+            // the same way they are sorted in the output file.
+            std::size_t nfail = 0;
+
+            for (std::size_t k = 0; k < j; ++k) {
+
+                if (in [k] != out [k]) {
+
+                    nfail++;
+
+                    rw_assert (false, __FILE__, __LINE__,
+                               "%{S} != %{S} at line %u of %s",
+                               &out [k], &in [k],
+                               k + 1, locales [i][2]);
+
+                }
+            }
+
+            rw_assert (!nfail, __FILE__, __LINE__,
+                       "collate<%s>::compare() failed %d times",
+                       charTname, nfail);
+        }
+    }
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+/*static*/ void
+check_hash_eff (const char* charTname)
+{
+    // test effectiveness of hash function
+    rw_info (0, __FILE__, __LINE__,
+             "std::collate<%s>::hash () -- effectiveness", charTname);
+
+    // since the same hash algorithm is used for both byname and non-byname
+    // facets, simply set up a std::locale that uses the "C" locale
+    std::locale loc ("C");
+    const std::collate<charT> &co =
+        _STD_USE_FACET (std::collate<charT>, loc);
+
+
+    int nfail = 0;
+
+    charT s[100];
+    bool next = true;
+
+    // generate `N' unique strings and hash them, storing each value
+    static const std::size_t N = 100;
+    long hashed [N] = { 0 };
+
+    std::size_t k;
+    for (k = 1; k != N && next; ++k) {
+        // generate a unique string
+        gen_str (s, k);
+
+        // compute hash value
+        hashed [k] = co.hash (s, s + std::char_traits<charT>::length(s));
+    }
+
+    // sort hashed values, then remove all duplicates
+    std::sort (hashed, hashed + k);
+    k = std::unique (hashed, hashed + k) - hashed;
+
+    // assert that the probability of a collision is less than 1%
+    // according to 22.2.4.1, p3, the likelihood should be very small,
+    // approaching 1.0 / numeric_limits<unsigned long>::max()
+    if (N - k > N /100) {
+        nfail++;
+        rw_assert (false, __FILE__, __LINE__,
+                   "collate<%s>::do_hash (const char_type*, "
+                   "const char_type*); "
+                   "probability of collision %f",
+                   charTname, double (N - k) / N);
+    }
+
+    rw_assert (!nfail, __FILE__, __LINE__,
+               "collate<%s>::do_hash () failed %d times", charTname,
+               nfail);
+
+}
+
+/**************************************************************************/
+
+
+template <class charT>
+/*static*/ void
+check_NUL (const char* charTname)
+{
+    rw_info (0, __FILE__, __LINE__,
+             "std::collate<%s>::compare() with embedded NULs", charTname);
+
+    // verify that the collate facet correctly handles
+    // character sequences with embedded NULs
+
+    charT buf_1 [STR_SIZE];
+    charT buf_2 [STR_SIZE];
+
+    bool fail = false;
+
+    unsigned i = 0;
+
+    for (const char* locname = rw_locales (LC_COLLATE);
+         *locname && !fail; locname += std::strlen (locname) + 1, ++i) {
+
+        std::locale loc;
+
+        _TRY {
+            loc = std::locale (locname);
+        }
+        _CATCH (...) {
+            continue;
+        }
+
+        const std::size_t buflen = sizeof buf_1 / sizeof *buf_1 - 1;
+
+        gen_str (buf_1, sizeof buf_1 / sizeof *buf_1);
+        std::memcpy (buf_2, buf_1, sizeof buf_2);
+
+        // compute a random index into the character buffers
+        // at which to set the element to NUL; the indices
+        // are such that (inx_1 > inx_2) always holds
+        const std::size_t inx_2 = std::rand () % (buflen - 1);
+        const std::size_t inx_1 =
+            inx_2 + 1 + std::rand () % (buflen - inx_2 - 1);
+
+        buf_2 [inx_2] = charT ();
+
+        typedef std::collate<charT> CollateT;
+
+        const CollateT &col = std::use_facet<CollateT>(loc);
+
+        int cmp = col.compare (buf_1, buf_1 + buflen, buf_2, buf_2 + buflen);
+
+        if (!cmp) {
+            typedef typename CollateT::string_type StringT;
+
+            const StringT str_1 (buf_1, buflen);
+            const StringT str_2 (buf_2, buflen);
+
+            fail = true;
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "collate<%s>::compare(%{S}, ..., %{S}, ...) "
+                       "!= 0, got 0 in locale(\"%s\")", charTname,
+                       &str_1, &str_2, locname);
+        }
+
+        // set the character at the smaller index in both buffers to
+        // NUL, then set a character at the larger index in the first
+        // buffer to NUL, compare the two, and verify that the buffers
+        // compare unequal (buf_1 probably less)
+        buf_1 [inx_1] = charT ();
+        buf_1 [inx_2] = charT ();
+
+        cmp = col.compare (buf_1, buf_1 + buflen, buf_2, buf_2 + buflen);
+
+        if (!cmp) {
+            typedef typename CollateT::string_type StringT;
+
+            const StringT str_1 (buf_1, buflen);
+            const StringT str_2 (buf_2, buflen);
+
+            fail = true;
+
+            rw_assert (false, __FILE__, __LINE__,
+                       "collate<%s>::compare(%{S}, ..., %{S}, ...) "
+                       "!= 0, got 0 in locale(\"%s\")", charTname,
+                       &str_1, &str_2, locname);
+        }
+    }
+}
+
+/**************************************************************************/
+
+template <class charT>
+/*static*/ void
+do_test (const char* charTname)
+{
+    check_libstd_test_locale<charT> (charTname);
+    check_libstd<charT> (charTname);
+    check_libc<charT> (charTname);
+    check_NUL<charT> (charTname);
+    check_hash_eff<charT> (charTname);
+}
+
+
+#if _RWSTD_PATH_SEP == '/'
+#  define RM_RF    "rm -rf "
+#else
+#  define RM_RF    "rmdir /Q /S "
+#endif   // _RWSTD_PATH_SEP == '/'
+
+
+static int
+run_test (int /*argc*/, char* /*argv*/ [])
+{
+    // set any additional environment variables defined in
+    // the RW_PUTENV environment variable (if it exists)
+    rw_putenv (0);
+
+    // create a temporary directory for files created by the test
+    char namebuf [L_tmpnam];
+    locale_root = std::tmpnam (namebuf);
+
+    char envvar [sizeof LOCALE_ROOT + L_tmpnam] = LOCALE_ROOT "=";
+    std::strcat (envvar, locale_root);
+
+    rw_system ("mkdir %s", locale_root);
+
+    // set the LOCALE_ROOT variable where std::locale looks
+    // for locale database files
+    rw_putenv (envvar);
+
+    do_test<char> ("char");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    do_test<wchar_t> ("wchar_t");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    // remove temporary locale databases created by the test
+    rw_system (RM_RF "%s", locale_root);
+
+    return 0;
+}
+
+
+/*extern*/ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "[lib.category.collate]",
+                    "22.2.4 The collate category",
+                    run_test, "", 0);
+}
+
diff --git a/tests/localization/22.locale.cons.mt.cpp b/tests/localization/22.locale.cons.mt.cpp
index 69992b1..480e2d2 100644
--- a/tests/localization/22.locale.cons.mt.cpp
+++ b/tests/localization/22.locale.cons.mt.cpp
@@ -50,6 +50,9 @@
 // command line option
 int opt_combine;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -85,6 +88,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         // compute an index into the array of locales
         const std::size_t linx = i % nlocales;
 
@@ -183,7 +189,7 @@
 
     // create and start a pool of threads and wait for them to finish
     result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
-                                 test_ctors, 0);
+                             test_ctors, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -210,10 +216,12 @@
                     "lib.locale.cons",
                     "thread safety", run_test,
                     "|-combine~ "
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // must be non-negative
                     "|-nthreads#0-* "    // must be in [0, MAX_THREADS]
                     "|-locales=",        // must be provided
                     &opt_combine,
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.ctype.mt.cpp b/tests/localization/22.locale.ctype.mt.cpp
index cbe1c56..bf5b021 100644
--- a/tests/localization/22.locale.ctype.mt.cpp
+++ b/tests/localization/22.locale.ctype.mt.cpp
@@ -66,6 +66,9 @@
 // of creating their own?
 int opt_shared_locale;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -118,6 +121,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         const std::size_t inx = std::size_t (i) % nlocales;
 
         // save the name of the locale
@@ -260,7 +266,8 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -276,7 +283,8 @@
     // start a pool of threads to exercise the thread safety
     // of the wchar_t specialization
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -293,7 +301,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -321,11 +330,13 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.ctype",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // arg must be non-negative
                     "|-nthreads#0-* "    // arg must be in [0, MAX_THREADS]
                     "|-nlocales#0 "      // arg must be non-negative
                     "|-locales= "        // arg must be provided
                     "|-shared-locale# ",
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.ctype.widen.cpp b/tests/localization/22.locale.ctype.widen.cpp
new file mode 100644
index 0000000..be80f2e
--- /dev/null
+++ b/tests/localization/22.locale.ctype.widen.cpp
@@ -0,0 +1,152 @@
+/***************************************************************************
+ *
+ * 22.locale.ctype.widen.cpp - tests exercising std::ctype<charT>::widen()
+ *
+ * $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.
+ *
+ * Copyright 1994-2008 Rogue Wave Software.
+ * 
+ **************************************************************************/
+
+#include <locale>
+
+#include <driver.h>
+
+typedef unsigned char UChar;
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+typedef std::ctype<wchar_t> WCtype;
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+/**************************************************************************/
+
+static void
+test_char ()
+{
+    rw_info (0, __FILE__, __LINE__, "std::ctype<char>::widen(char)");
+
+    const std::locale loc;
+
+    const WCtype& ctp = std::use_facet<WCtype> (loc);
+
+    for (int i = 0; i != int (_RWSTD_UCHAR_MAX) + 1; ++i) {
+
+        // compute the argument, and the expected and actual results
+        const char narrow = char (i);
+        const char expect = narrow;
+        const char wide   = ctp.widen (narrow);
+
+        rw_assert (expect == wide, __FILE__, __LINE__,
+                   "std::ctype<char>::widen(%#c) == %#c, got %#c",
+                   narrow, expect, wide);
+    }
+}
+
+/**************************************************************************/
+
+// will leave this here for now since it appears to be a placeholder
+// for further testing
+
+static void
+test_byname_char ()
+{
+    rw_info (0, __FILE__, __LINE__,
+             "std::ctype_byname<char>::widen(char)");
+
+    rw_warn (false, __FILE__, __LINE__,
+             "ctype_byname<char>::widen() not exercised");
+}
+
+/**************************************************************************/
+
+static void
+test_wchar_t ()
+{
+    rw_info (0, __FILE__, __LINE__,
+             "std::ctype<wchar_t>::widen(char)");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    const std::locale loc;
+
+    const WCtype& ctp = std::use_facet<WCtype> (loc);
+
+    for (int i = 0; i != int (_RWSTD_UCHAR_MAX) + 1; ++i) {
+
+        // compute the argument, and the expected and actual results
+        const char    narrow = char (i);
+        const wchar_t expect = wchar_t (UChar (narrow));
+        const wchar_t wide   = ctp.widen (narrow);
+
+        rw_assert (expect == wide, __FILE__, __LINE__,
+                   "std::ctype<wchar_t>::widen(%#c) == %#Lc, got %#Lc",
+                   narrow, expect, wide);
+    }
+
+#else   // if defined (_RWSTD_NO_WCHAR_T)
+
+    rw_warn (false, __FILE__, __LINE__,
+             "ctype<wchar_t>::widen() not exercised: "
+             "macro _RWSTD_NO_WCHAR_T defined");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+}
+
+/**************************************************************************/
+
+// another placeholder for further testing?
+
+static void
+test_byname_wchar_t ()
+{
+    rw_info (0, __FILE__, __LINE__,
+             "std::ctype_byname<wchar_t>::widen(char)");
+
+    rw_warn (false, __FILE__, __LINE__,
+             "ctype_byname<wchar_t>::widen() not exercised");
+}
+
+/**************************************************************************/
+
+static int
+run_test (int /*unused*/, char* /*unused*/ [])
+{
+    test_char ();
+    test_byname_char ();
+
+    test_wchar_t ();
+    test_byname_wchar_t ();
+
+    return 0;
+}
+
+/*extern*/ int
+main (int argc, char* argv [])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.locale.ctype.widen",
+                    0,   // no comment
+                    run_test, "", 0);
+}
+
diff --git a/tests/localization/22.locale.globals.mt.cpp b/tests/localization/22.locale.globals.mt.cpp
index 3a06939..ebf5dad 100644
--- a/tests/localization/22.locale.globals.mt.cpp
+++ b/tests/localization/22.locale.globals.mt.cpp
@@ -73,6 +73,9 @@
 // disable exceptions?
 int opt_no_exceptions;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -149,6 +152,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         // save the name of the locale
         const char* const locale_name = locales [i % nlocales];
 
@@ -395,6 +401,10 @@
     const std::locale classic (std::locale::classic ());
 
     for (int i = 0; i != opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         try {
             use_facet_loop (classic, i);
         }
@@ -510,7 +520,7 @@
 
         // create and start a pool of threads and wait for them to finish
         result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
-                                 test_has_facet, 0);
+                                 test_has_facet, 0, std::size_t (opt_timeout));
 
         rw_error (result == 0, 0, __LINE__,
                   "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -554,7 +564,7 @@
 
         // create and start a pool of threads and wait for them to finish
         result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
-                                 test_use_facet, 0);
+                                 test_use_facet, 0, std::size_t (opt_timeout));
 
         rw_error (result == 0, 0, __LINE__,
                   "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -586,6 +596,7 @@
                     "thread safety", run_test,
                     "|-has_facet~ "
                     "|-use_facet~ "
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // arg must be non-negative
                     "|-nthreads#0-* "    // arg must be in [0, MAX_THREADS]
                     "|-locales= "        // argument must be provided
@@ -605,6 +616,7 @@
                     "|-time_put~ ",
                     &opt_has_facet,
                     &opt_use_facet,
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.messages.mt.cpp b/tests/localization/22.locale.messages.mt.cpp
index f5a78fe..7b6c68e 100644
--- a/tests/localization/22.locale.messages.mt.cpp
+++ b/tests/localization/22.locale.messages.mt.cpp
@@ -30,44 +30,76 @@
 
 #include <driver.h>      // for rw_test()
 #include <rw_locale.h>   // for rw_create_catalog()
-#include <rw_thread.h>
+#include <rw_thread.h>   // for rw_thread_pool()
+#include <rw_process.h>  // for rw_system()
+#include <file.h>        // for SHELL_RM_F
 #include <valcmp.h>      // for rw_strncmp ()
 
 #include <cstring>   // for strlen()
 #include <cstdio>    // for remove()
 
 // maximum number of threads allowed by the command line interface
+#define MAX_CATALOGS     32
 #define MAX_THREADS      32
 #define MAX_LOOPS    100000
 
+// deault number of catalogs
+int opt_ncatalogs = 11;
+
 // default number of threads (will be adjusted to the number
 // of processors/cores later)
-int rw_opt_nthreads = 1;
+int opt_nthreads = 1;
 
 // the number of times each thread should iterate (unless specified
 // otherwise on the command line)
-int rw_opt_nloops = 100000;
+int opt_nloops = 10000;
 
-// locale for threads to share
-static const
-std::locale locale;
+#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
 
-// message catalog for threads to share
-static
-std::messages_base::catalog catalog;
+// number of locales to use
+int opt_nlocales = MAX_THREADS;
 
-static
-std::messages_base::catalog wcatalog;
+#else   // HP-UX in LP64 mode
+
+// work around a small cache size on HP-UX in LP64 mode
+// in LP64 mode (see STDCXX-812)
+int opt_nlocales = 9;
+
+#endif   // HP-UX 32/64 bit mode
+
+// should all threads share the same set of locale objects instead
+// of creating their own?
+int opt_shared_locale;
+
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
 
 /**************************************************************************/
 
-#ifndef _WIN32
-#  define CAT_NAME "./rwstdmessages.cat"
-#  define MSG_NAME "rwstdmessages.msg"
-#else
-#  define CAT_NAME "rwstdmessages.dll"
-#  define MSG_NAME "rwstdmessages.rc"
-#endif
+// array of locale names to use for testing
+static const char*
+locales [MAX_THREADS];
+
+// number of locale names in the array
+static std::size_t
+nlocales;
+
+/**************************************************************************/
+
+//
+struct MyMessageData
+{
+    // name of the locale the data corresponds to
+    const char* locale_name_;
+
+    // optionally set to the named locale for threads to share
+    std::locale locale_;
+
+} my_message_data [MAX_THREADS];
+
+char my_catalog_names [64][MAX_CATALOGS];
+
+/**************************************************************************/
 
 #define MAX_SETS 5
 #define MAX_MESSAGES  5
@@ -123,38 +155,6 @@
     }
 };
 
-static std::string str_messages;
-
-/**************************************************************************/
-
-template <class T>
-void test_open_close (const std::locale& loc,
-                      const std::messages<T>& msgs,
-                      const std::string& name)
-{
-    std::messages_base::catalog cat =
-        (msgs.open) (name, loc);
-
-    RW_ASSERT (! (cat < 0));
-
-    (msgs.close) (cat);
-}
-
-template <class T>
-void test_get (const std::messages<T>& msgs,
-               const std::messages_base::catalog cat,
-               int set, int msgid,
-               const std::basic_string<T>& dflt)
-{
-    // the msg_id() thing seems like a bug to me. if anything, the user
-    // should never need to write or call msg_id().
-
-    const typename std::messages<T>::string_type res =
-        msgs.get (cat, set, msg_id (set, msgid), dflt);
-
-    RW_ASSERT (!rw_strncmp (messages [set-1][msgid-1], res.c_str ()));
-}
-
 /**************************************************************************/
 
 extern "C" {
@@ -165,50 +165,146 @@
 static void*
 thread_func (void*)
 {
-    const std::string name (CAT_NAME);
-
-    const std::messages<char>& nmsgs =
-        std::use_facet<std::messages<char> >(locale);
-
     const std::string ndflt ("\1\2\3\4");
 
+    struct {
+        std::messages_base::catalog cat;
+        std::locale loc;
+    } ncatalogs [4];
+
+    const unsigned n_ncatalogs = sizeof (ncatalogs) / sizeof (*ncatalogs);
+
+    // 22.2.7.1.2 says values less than 0 returned if catalog can't
+    // be opened, so we use -1 as a sentinel.
+    for (unsigned c = 0; c < n_ncatalogs; ++c)
+        ncatalogs [c].cat = -1;
+
 #ifndef _RWSTD_NO_WCHAR_T
-    const std::messages<wchar_t>& wmsgs =
-        std::use_facet<std::messages<wchar_t> >(locale);
 
     const std::wstring wdflt (L"\1\2\3\4");
-#endif // _RWSTD_NO_WCHAR_T
 
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    struct {
+        std::messages_base::catalog cat;
+        std::locale loc;
+    } wcatalogs [5];
 
-        int set   = 1 + i % MAX_SETS;
-        int msgid = 1 + i % MAX_MESSAGES;
+    const unsigned n_wcatalogs = sizeof (wcatalogs) / sizeof (*wcatalogs);
+
+    for (unsigned c = 0; c < n_wcatalogs; ++c)
+        wcatalogs [c].cat = -1;
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    ///////////////////////////////////////////////////////////////////////
+
+    for (int i = 0; i < opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
+        const MyMessageData& data = my_message_data [i % nlocales];
+
+        // construct a named locale, get a reference to the money_get
+        // facet from it and use it to format a random money value
+        const std::locale loc = 
+            opt_shared_locale ? data.locale_
+                              : std::locale (data.locale_name_);
+
+        const int set   = 1 + i % MAX_SETS;
+        const int msgid = 1 + i % MAX_MESSAGES;
 
         if (test_char) {
-            if (i & 1) {
-                test_get<char>(nmsgs, catalog, set, msgid, ndflt);
+            // exercise the narrow char specialization of the facet
+
+            const std::messages<char> &nm =
+                std::use_facet<std::messages<char> >(loc);
+
+            const unsigned cat_idx = i % n_ncatalogs;
+            if (! (ncatalogs [cat_idx].cat < 0)) {
+                (nm.close)(ncatalogs [cat_idx].cat);
             }
-            else {
-                test_open_close<char>(locale, nmsgs, name);
+
+            const unsigned name_idx = i % opt_ncatalogs;
+
+            const std::messages_base::catalog cat = 
+                (nm.open)(my_catalog_names [name_idx], loc);
+
+            ncatalogs [cat_idx].cat = cat;
+            ncatalogs [cat_idx].loc = loc;
+
+            if (i & 1) {
+
+                // get a message from the catalog every odd iteration
+                const std::messages<char>::string_type res =
+                        nm.get (cat, set, msg_id (set, msgid), ndflt);
+
             }
         }
 
-        if (test_wchar) {
-
 #ifndef _RWSTD_NO_WCHAR_T
 
-            if (i & 1) {
-                test_get<wchar_t>(wmsgs, wcatalog, set, msgid, wdflt);
-            }
-            else {
-                test_open_close<wchar_t>(locale, wmsgs, name);
+        if (test_wchar) {
+            // exercise the wide char specialization of the facet
+
+            const std::messages<wchar_t> &wm =
+                std::use_facet<std::messages<wchar_t> >(loc);
+
+            const unsigned cat_idx = i % n_wcatalogs;
+            if (! (wcatalogs [cat_idx].cat < 0)) {
+                (wm.close)(wcatalogs [cat_idx].cat);
             }
 
-#endif // _RWSTD_NO_WCHAR_T
+            const unsigned name_idx = i % opt_ncatalogs;
 
+            const std::messages_base::catalog cat = 
+                (wm.open)(my_catalog_names [name_idx], loc);
+
+            RW_ASSERT (! (cat < 0));
+
+            wcatalogs [cat_idx].cat = cat;
+            wcatalogs [cat_idx].loc = loc;
+
+            if (! (i & 1)) {
+
+                // get a message from the catalog every even iteration
+                const std::messages<wchar_t>::string_type res =
+                        wm.get (cat, set, msg_id (set, msgid), wdflt);
+
+            }
+        }
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    }
+
+    ///////////////////////////////////////////////////////////////////////
+
+    // close any catalogs that are still open
+
+    for (unsigned c = 0; c < n_ncatalogs; ++c) {
+        if (! (ncatalogs [c].cat < 0)) {
+
+            const std::messages<char> &nm =
+                std::use_facet<std::messages<char> >(ncatalogs[c].loc);
+
+            (nm.close)(ncatalogs [c].cat);
         }
     }
 
+#ifndef _RWSTD_NO_WCHAR_T
+
+    for (unsigned c = 0; c < n_wcatalogs; ++c) {
+        if (! (wcatalogs [c].cat < 0)) {
+
+            const std::messages<wchar_t> &wm =
+                std::use_facet<std::messages<wchar_t> >(wcatalogs[c].loc);
+
+            (wm.close)(wcatalogs [c].cat);
+        }
+    }
+
+#endif   // _RWSTD_NO_WCHAR_T
+
     return 0;
 }
 
@@ -219,36 +315,96 @@
 static int
 run_test (int, char**)
 {
-    for (int i = 0; i < MAX_SETS; ++i) {
-        for (int j = 0; j < MAX_MESSAGES; ++j)
-            str_messages.append (messages [i][j], std::strlen (messages [i][j]) + 1);
+    std::string catalog;
 
-        str_messages.append (1, '\0');
+    // initialize the catalog data
+    for (int i = 0; i < MAX_SETS; ++i) {
+
+        for (int j = 0; j < MAX_MESSAGES; ++j) {
+            catalog.append (messages [i][j],
+                            std::strlen (messages [i][j]) + 1);
+        }
+
+        catalog.append (1, '\0');
     }
 
-    // generate a message catalog
-    rw_create_catalog (MSG_NAME, str_messages.c_str ());
-    const std::string name (CAT_NAME);
+    ///////////////////////////////////////////////////////////////////////
 
-    const std::messages<char>& nmsgs =
-        std::use_facet<std::messages<char> >(locale);
+    // create the catalogs and initialize array of catalog names
+    for (int i = 0; i < opt_ncatalogs; ++i) {
 
-    catalog = (nmsgs.open) (name, locale);
+        char* msg_name = my_catalog_names [i];
 
-#ifndef _RWSTD_NO_WCHAR_T
-
-    const std::messages<wchar_t>& wmsgs =
-        std::use_facet<std::messages<wchar_t> >(locale);
-
-    wcatalog = (wmsgs.open) (name, locale);
-
+#ifndef _WIN32
+        std::sprintf (msg_name, "rwstdmessages_%d.msg", i);
+#else
+        std::sprintf (msg_name, "rwstdmessages_%d.rc", i);
 #endif
 
+        const int failed = rw_create_catalog (msg_name, catalog.c_str ());
+        rw_fatal (!failed, 0, __LINE__,
+                  "failed to create message catalog from %s",
+                  msg_name);
+
+#ifndef _WIN32
+        std::sprintf (msg_name, "./rwstdmessages_%d.cat", i);
+#else
+        std::sprintf (msg_name, "rwstdmessages_%d.dll", i);
+#endif
+    }
+
+    ///////////////////////////////////////////////////////////////////////
+
+    // find all installed locales for which setlocale (LC_ALL) succeeds
+    const char* const locale_list =
+        rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
+
+    const std::size_t maxinx = RW_COUNT_OF (locales);
+
+    for (const char* name = locale_list;
+         *name;
+         name += std::strlen (name) + 1) {
+
+        const std::size_t inx = nlocales;
+        locales [inx] = name;
+
+        // fill in the money and results for this locale
+        MyMessageData& data = my_message_data [inx];
+        data.locale_name_ = name;
+
+        try {
+            const std::locale loc (data.locale_name_);
+
+            const std::messages<char>& nm =
+                std::use_facet<std::messages<char> >(loc);
+
+#ifdef _RWSTD_NO_WCHAR_T
+
+            const std::messages<wchar_t>& nm =
+                std::use_facet<std::messages<wchar_t> >(loc);
+
+#endif // _RWSTD_NO_WCHAR_T
+
+            if (opt_shared_locale)
+                data.locale_ = loc;
+
+            nlocales += 1;
+
+        }
+        catch (...) {
+            rw_warn (!rw_opt_locales, 0, __LINE__,
+                     "unable to use locale(%#s)", name);
+        }
+
+        if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
+            break;
+    }
+
     rw_info (0, 0, 0,
              "testing std::messages<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each",
-             rw_opt_nthreads, 1 != rw_opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops);
+             opt_nthreads, 1 != opt_nthreads,
+             opt_nloops, 1 != opt_nloops);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -258,12 +414,12 @@
     rw_info (0, 0, 0, "exercising std::messages<char>");
 
     int result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
-                        thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -275,12 +431,12 @@
     rw_info (0, 0, 0, "exercising std::messages<wchar_t>");
 
     result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
-                        thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -291,26 +447,18 @@
                       "std::messages<wchar_t>");
 
     result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
-                        thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #endif // _RWSTD_NO_WCHAR_T
 
     ///////////////////////////////////////////////////////////////////////
 
-    (nmsgs.close) (catalog);
-
-#ifndef _RWSTD_NO_WCHAR_T
-
-    (wmsgs.close) (wcatalog);
-    
-#endif // _RWSTD_NO_WCHAR_T
-
-    std::remove (CAT_NAME);
+    rw_system (SHELL_RM_F "rwstdmessages_*");
 
     return result;
 }
@@ -323,18 +471,23 @@
 
     // set nthreads to the greater of the number of processors
     // and 2 (for uniprocessor systems) by default
-    rw_opt_nthreads = rw_get_cpus ();
-    if (rw_opt_nthreads < 2)
-        rw_opt_nthreads = 2;
+    opt_nthreads = rw_get_cpus ();
+    if (opt_nthreads < 2)
+        opt_nthreads = 2;
 
 #endif   // _RWSTD_REENTRANT
 
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.messages",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // must be non-negative
+                    "|-ncatalogs#0-* "   // must be non-negative
                     "|-nthreads#0-* ",    // must be in [0, MAX_THREADS]
-                    &rw_opt_nloops,
+                    &opt_timeout,
+                    &opt_nloops,
+                    int (MAX_CATALOGS),
+                    &opt_ncatalogs,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads);
+                    &opt_nthreads);
 }
diff --git a/tests/localization/22.locale.money.get.mt.cpp b/tests/localization/22.locale.money.get.mt.cpp
index 624d0fa..dbf5248 100644
--- a/tests/localization/22.locale.money.get.mt.cpp
+++ b/tests/localization/22.locale.money.get.mt.cpp
@@ -67,6 +67,9 @@
 // of creating their own?
 int opt_shared_locale;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -176,6 +179,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         // save the name of the locale
         const MyMoneyData& data = my_money_data [i % nlocales];
 
@@ -183,7 +189,7 @@
         // facet from it and use it to format a random money value
         const std::locale loc =
             opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -403,7 +409,8 @@
 
     // create and start a pool of threads and wait for them to finish
     int result = 
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -418,7 +425,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -436,7 +444,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -464,11 +473,13 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.money.get",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // must be non-negative
                     "|-nthreads#0-* "    // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "      // arg must be non-negative
                     "|-locales= "        // must be provided
                     "|-shared-locale# ",
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.money.put.mt.cpp b/tests/localization/22.locale.money.put.mt.cpp
index 190c615..1e7e926 100644
--- a/tests/localization/22.locale.money.put.mt.cpp
+++ b/tests/localization/22.locale.money.put.mt.cpp
@@ -67,6 +67,9 @@
 // of creating their own?
 int opt_shared_locale;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -184,6 +187,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         // save the name of the locale
         const MyMoneyData& data = my_money_data [i % nlocales];
 
@@ -191,7 +197,7 @@
         // facet from it and use it to format a random money value
         const std::locale loc =
             opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -409,7 +415,8 @@
 
     // create and start a pool of threads and wait for them to finish
     int result = 
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -424,7 +431,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -442,7 +450,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -470,11 +479,13 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.money.put",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // must be non-negative
                     "|-nthreads#0-* "    // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "      // arg must be non-negative
                     "|-locales= "        // must be provided
                     "|-shared-locale# ",
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.moneypunct.mt.cpp b/tests/localization/22.locale.moneypunct.mt.cpp
index d3c54ba..6227e45 100644
--- a/tests/localization/22.locale.moneypunct.mt.cpp
+++ b/tests/localization/22.locale.moneypunct.mt.cpp
@@ -43,14 +43,17 @@
 
 // default number of threads (will be adjusted to the number
 // of processors/cores later)
-int rw_opt_nthreads = 1;
+int opt_nthreads = 1;
 
 // the default number of times for each thread to iterate
 #define DFLT_LOOPS   10000
 
 // the number of times each thread should iterate (will be set to
 // DFLT_LOOPS unless explicitly specified on the command line)
-int rw_opt_nloops = -1;
+int opt_nloops = -1;
+
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
 
 /**************************************************************************/
 
@@ -240,7 +243,10 @@
 static void*
 thread_func (void*)
 {
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    for (int i = 0; i != opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
 
         thread_loop_body (std::size_t (i));
     }
@@ -388,13 +394,13 @@
     // unless the number of iterations was explicitly specified
     // on the command line, decrease the number to equal the number
     // of excericsed locales when only one thread is being tested
-    if (1 == rw_opt_nthreads && rw_opt_nloops < 0)
-        rw_opt_nloops = int (nlocales);
+    if (1 == opt_nthreads && opt_nloops < 0)
+        opt_nloops = int (nlocales);
 
     // when the number of iterations wasn't explicitly specified
     // on the command line set it to the default value
-    if (rw_opt_nloops < 0)
-        rw_opt_nloops = DFLT_LOOPS;
+    if (opt_nloops < 0)
+        opt_nloops = DFLT_LOOPS;
 
     rw_fatal (0 < nlocales, 0, __LINE__,
               "must have at least one valid locale to test");
@@ -402,8 +408,8 @@
     rw_info (0, 0, 0,
              "testing std::moneypunct<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
-             rw_opt_nthreads, 1 != rw_opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops,
+             opt_nthreads, 1 != opt_nthreads,
+             opt_nloops, 1 != opt_nloops,
              nlocales, int (nlocales), "%#s", locales);
 
     rw_info (0, 0, 0, "exercising std::moneypunct<char>");
@@ -413,11 +419,12 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #ifndef _RWSTD_NO_WCHAR_T
 
@@ -429,11 +436,12 @@
     // start a pool of threads to exercise the thread safety
     // of the wchar_t specialization
     result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     // exercise both the char and the wchar_t specializations
     // at the same time
@@ -447,11 +455,12 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #endif   // _RWSTD_NO_WCHAR_T
 
@@ -466,20 +475,22 @@
 
     // set nthreads to the greater of the number of processors
     // and 2 (for uniprocessor systems) by default
-    rw_opt_nthreads = rw_get_cpus ();
-    if (rw_opt_nthreads < 2)
-        rw_opt_nthreads = 2;
+    opt_nthreads = rw_get_cpus ();
+    if (opt_nthreads < 2)
+        opt_nthreads = 2;
 
 #endif   // _RWSTD_REENTRANT
 
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.moneypunct",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "       // must be non-negative
                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
                     "|-locales=",       // must be provided
-                    &rw_opt_nloops,
+                    &opt_timeout,
+                    &opt_nloops,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads,
+                    &opt_nthreads,
                     &rw_opt_setlocales);
 }
diff --git a/tests/localization/22.locale.num.get.cpp b/tests/localization/22.locale.num.get.cpp
index fba54b4..13a0b48 100644
--- a/tests/localization/22.locale.num.get.cpp
+++ b/tests/localization/22.locale.num.get.cpp
@@ -235,6 +235,13 @@
 
 /**************************************************************************/
 
+// if non-zero expected to point to a maximum valid value
+// of type T that's being tested below (used for floating
+// point ranges)
+// on function return, the pointed to value is overwritten
+// with the actual extracted value
+void *pmax = 0;
+
 
 enum IterType { iter_pointer, iter_istreambuf, iter_input };
 
@@ -244,7 +251,6 @@
              const char *cname,           // name of character type
              IterType    itype,           // type of input iterator
              const char *iname,           // name of input iterator
-             void       *pmax,
              nativeT     val,             // value expected to be extracted
              const char *str,             // input sequence
              int         eat_expect = -1, // number of consumed characters
@@ -438,7 +444,6 @@
              const char *cname,           // name of character type
              IterType    itype,           // iterator type
              const char *iname,           // name of iterator type
-             void       *pmax,
              nativeT     val,             // value expected to be extracted
              const char *str,             // input sequence
              int         eat_expect = -1, // number of consumed characters
@@ -449,15 +454,15 @@
     switch (ctype) {
     case narrow_char:
         return do_test (lineno, (char*)0, cname, itype, iname,
-                        pmax, val, str, eat_expect, flags, err_expect, grouping);
+                        val, str, eat_expect, flags, err_expect, grouping);
     case wide_char:
         return do_test (lineno, (wchar_t*)0, cname, itype, iname,
-                        pmax, val, str, eat_expect, flags, err_expect, grouping);
+                        val, str, eat_expect, flags, err_expect, grouping);
     case user_char:
         break;
 #if 0   // disabled
         return do_test (lineno, (UserChar*)0, cname, itype, iname,
-                        pmax, val, str, eat_expect, flags, err_expect, grouping);
+                        val, str, eat_expect, flags, err_expect, grouping);
 #endif   // disabled
     }
 
@@ -497,8 +502,7 @@
 /*************************************************************************/
 
 #define TEST   do_test
-#define T      __LINE__, ctype, cname, itype, iname, 0
-#define T_MAX  __LINE__, ctype, cname, itype, iname, &val
+#define T      __LINE__, ctype, cname, itype, iname
 
 
 template <class numT>
@@ -2441,7 +2445,8 @@
              cname, iname);
 
     // exercise bahvior on underflow
-    float val = 0;
+    static float val = 0;
+    pmax = &val;
 
     // on underflow, get() follows C99 requirements on strtof()
     // i.e., it stores a value in the range [0, +/-FLT_MIN]
@@ -2452,34 +2457,35 @@
     //     normalized positive number in the return type; whether
     //     errno acquires the value ERANGE is implementation-defined.
 
-    TEST (T_MAX, (val = FLT_MIN, 0.0f), "1.111111e-9999", 14, 0, Eof);
+    TEST (T, (val = FLT_MIN, 0.0f), "1.111111e-9999", 14, 0, Eof);
     rw_assert (!(val < 0.0), 0, __LINE__,
                "correct sign after positive underflow");
 
-    TEST (T_MAX, (val = 0.0f, -FLT_MIN), "-1.111111e-9999", 15, 0, Eof);
+    TEST (T, (val = 0.0f, -FLT_MIN), "-1.111111e-9999", 15, 0, Eof);
     rw_assert (!(val > 0.0), 0, __LINE__,
                "correct sign after negative underflow");
 
     if (1.234567e-39 < FLT_MIN) {
-        TEST (T_MAX, (val = FLT_MIN, 0.0f),   "1.234567e-39", 12, 0, Eof);
-        TEST (T_MAX, (val = 0.0f, -FLT_MIN), "-1.234567e-39", 13, 0, Eof);
+        TEST (T, (val = FLT_MIN, 0.0f),   "1.234567e-39", 12, 0, Eof);
+        TEST (T, (val = 0.0f, -FLT_MIN), "-1.234567e-39", 13, 0, Eof);
     }
 
     if (1.234567e-49 < FLT_MIN) {
-        TEST (T_MAX, (val = FLT_MIN, 0.0f),   "1.234567e-49", 12, 0, Eof);
-        TEST (T_MAX, (val = 0.0f, -FLT_MIN), "-1.234567e-49", 13, 0, Eof);
+        TEST (T, (val = FLT_MIN, 0.0f),   "1.234567e-49", 12, 0, Eof);
+        TEST (T, (val = 0.0f, -FLT_MIN), "-1.234567e-49", 13, 0, Eof);
     }
 
     if (1.234567e-99 < FLT_MIN) {
-        TEST (T_MAX, (val = FLT_MIN, 0.0f),   "1.234567e-99", 12, 0, Eof);
-        TEST (T_MAX, (val = 0.0f, -FLT_MIN), "-1.234567e-99", 13, 0, Eof);
+        TEST (T, (val = FLT_MIN, 0.0f),   "1.234567e-99", 12, 0, Eof);
+        TEST (T, (val = 0.0f, -FLT_MIN), "-1.234567e-99", 13, 0, Eof);
     }
 
     // exercise facet's behavior on underflow:
     //   parsing succeeds (fail is clear), +/-min is stored
-    TEST (T_MAX,  FLT_MIN, _RWSTD_STRSTR ( _RWSTD_DBL_MIN), -1, 0, Eof);
-    TEST (T_MAX, -FLT_MIN, _RWSTD_STRSTR (-_RWSTD_DBL_MIN), -1, 0, Eof);
+    TEST (T,  FLT_MIN, _RWSTD_STRSTR ( _RWSTD_DBL_MIN), -1, 0, Eof);
+    TEST (T, -FLT_MIN, _RWSTD_STRSTR (-_RWSTD_DBL_MIN), -1, 0, Eof);
 
+    pmax = 0;   // reset before next test
 
 
     rw_info (0, 0, 0, "std::num_get<%s, %s>::get (..., float&) on overflow",
@@ -2610,7 +2616,8 @@
              cname, iname);
 
     // exercise bahvior on underflow
-    double val = DBL_MIN;
+    static double val = DBL_MIN;
+    pmax = &val;
 
     // on underflow, get() follows C99 requirements on strtod()
     // i.e., it stores a value in the range [0, +/-DBL_MIN]
@@ -2621,24 +2628,25 @@
     //     normalized positive number in the return type; whether
     //     errno acquires the value ERANGE is implementation-defined.
 
-    TEST (T_MAX, (val = DBL_MIN, 0.0),   "1.111111e-9999", 14, 0, Eof);
-    TEST (T_MAX, (val = 0.0, -DBL_MIN), "-1.111111e-9999", 15, 0, Eof);
+    TEST (T, (val = DBL_MIN, 0.0),   "1.111111e-9999", 14, 0, Eof);
+    TEST (T, (val = 0.0, -DBL_MIN), "-1.111111e-9999", 15, 0, Eof);
 
     if (1.23456789e-309L < DBL_MIN) {
-        TEST (T_MAX, (val = DBL_MIN, 0.0),   "1.23456789e-309", 15, 0, Eof);
-        TEST (T_MAX, (val = 0.0, -DBL_MIN), "-1.23456789e-309", 16, 0, Eof);
+        TEST (T, (val = DBL_MIN, 0.0),   "1.23456789e-309", 15, 0, Eof);
+        TEST (T, (val = 0.0, -DBL_MIN), "-1.23456789e-309", 16, 0, Eof);
     }
 
     if (1.234567e-409L < DBL_MIN) {
-        TEST (T_MAX, (val = DBL_MIN, 0.0),   "1.23456789e-409", 15, 0, Eof);
-        TEST (T_MAX, (val = 0.0, -DBL_MIN), "-1.23456789e-409", 16, 0, Eof);
+        TEST (T, (val = DBL_MIN, 0.0),   "1.23456789e-409", 15, 0, Eof);
+        TEST (T, (val = 0.0, -DBL_MIN), "-1.23456789e-409", 16, 0, Eof);
     }
 
     if (1.234567e-999L < DBL_MIN) {
-        TEST (T_MAX, (val = DBL_MIN, 0.0),   "1.23456789e-999", 15, 0, Eof);
-        TEST (T_MAX, (val = 0.0, -DBL_MIN), "-1.23456789e-999", 16, 0, Eof);
+        TEST (T, (val = DBL_MIN, 0.0),   "1.23456789e-999", 15, 0, Eof);
+        TEST (T, (val = 0.0, -DBL_MIN), "-1.23456789e-999", 16, 0, Eof);
     }
 
+    pmax = 0;   // reset before next test
 
 
 #  ifdef _RWSTD_LDBL_MAX
@@ -2731,7 +2739,8 @@
              cname, iname);
 
     // exercise bahvior on underflow
-    long double val = LDBL_MIN;
+    static long double val = LDBL_MIN;
+    pmax = &val;
 
     // on underflow, get() follows C99 requirements on strtold()
     // i.e., it stores a value in the range [0, +/-LDBL__MIN]
@@ -2742,22 +2751,23 @@
     //     normalized positive number in the return type; whether
     //     errno acquires the value ERANGE is implementation-defined.
 
-    TEST (T_MAX, (val = LDBL_MIN, 0.0L),   "1.987654321e-99999", 18, 0, Eof);
-    TEST (T_MAX, (val = 0.0L, -LDBL_MIN), "-1.987654321e-99999", 19, 0, Eof);
+    TEST (T, (val = LDBL_MIN, 0.0L),   "1.987654321e-99999", 18, 0, Eof);
+    TEST (T, (val = 0.0L, -LDBL_MIN), "-1.987654321e-99999", 19, 0, Eof);
 
     const char fmt[] = "%Lg";
 
     long double ld = 0.0;
     if (1 == std::sscanf ("3.456789e-4932", fmt, &ld) && ld < LDBL_MIN) {
-        TEST (T_MAX, (val = LDBL_MIN, 0.0L),   "3.456789e-4932", 14, 0, Eof);
-        TEST (T_MAX, (val = 0.0L, -LDBL_MIN), "-3.456789e-4932", 15, 0, Eof);
+        TEST (T, (val = LDBL_MIN, 0.0L),   "3.456789e-4932", 14, 0, Eof);
+        TEST (T, (val = 0.0L, -LDBL_MIN), "-3.456789e-4932", 15, 0, Eof);
     }
 
     if (1 == std::sscanf ("3.456789e-9999", fmt, &ld) && ld < LDBL_MIN) {
-        TEST (T_MAX, (val = LDBL_MIN, 0.0L),   "3.456789e-9999", 14, 0, Eof);
-        TEST (T_MAX, (val = 0.0L, -LDBL_MIN), "-3.456789e-9999", 15, 0, Eof);
+        TEST (T, (val = LDBL_MIN, 0.0L),   "3.456789e-9999", 14, 0, Eof);
+        TEST (T, (val = 0.0L, -LDBL_MIN), "-3.456789e-9999", 15, 0, Eof);
     }
 
+    pmax = 0;   // reset before next test
 
 
 #  ifdef _RWSTD_LDBL_MAX
diff --git a/tests/localization/22.locale.num.get.mt.cpp b/tests/localization/22.locale.num.get.mt.cpp
index 5bdd3d4..467a782 100644
--- a/tests/localization/22.locale.num.get.mt.cpp
+++ b/tests/localization/22.locale.num.get.mt.cpp
@@ -42,10 +42,10 @@
 
 // default number of threads (will be adjusted to the number
 // of processors/cores later)
-int rw_opt_nthreads = 1;
+int opt_nthreads = 1;
 
 // the number of times each thread should iterate
-int rw_opt_nloops = MAX_LOOPS;
+int opt_nloops = MAX_LOOPS;
 
 #if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
 
@@ -62,7 +62,10 @@
 
 // should all threads share the same set of locale objects instead
 // of creating their own?
-int rw_opt_shared_locale;
+int opt_shared_locale;
+
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
 
 /**************************************************************************/
 
@@ -117,11 +120,13 @@
 
     // holds the narrow/wide character representation of value_ and
     // the number of used 'charT' in each buffer.
-    char    ncs_ [BufferSize];
+    char        ncs_ [BufferSize];
+    std::size_t nlen_;   // number of valid characters in buffer
 
 #ifndef _RWSTD_NO_WCHAR_T
 
-    wchar_t wcs_ [BufferSize];
+    wchar_t     wcs_ [BufferSize];
+    std::size_t wlen_;   // number of valid characters in buffer
 
 #endif  // _RWSTD_NO_WCHAR_T
 
@@ -338,7 +343,10 @@
     wio.rdbuf (&wsb);
 #endif // _RWSTD_NO_WCHAR_T
 
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    for (int i = 0; i != opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
 
         // fill in the value and results for this locale
         const MyNumData& data = my_num_data [i % nlocales];
@@ -346,8 +354,8 @@
         // construct a named locale and imbue it in the ios object
         // so that the locale is used not only by the num_put facet
         const std::locale loc =
-            rw_opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+            opt_shared_locale ? data.locale_
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -356,7 +364,7 @@
                 std::use_facet<std::num_get<char> >(loc);
 
             nio.imbue (loc);
-            nsb.pubsetg (data.ncs_, Traits::length (data.ncs_));
+            nsb.pubsetg (data.ncs_, data.nlen_);
 
             test_get_data (data, ng,
                            std::istreambuf_iterator<char>(&nsb),
@@ -377,7 +385,7 @@
                 std::use_facet<std::num_get<wchar_t> >(loc);
 
             wio.imbue (loc);
-            wsb.pubsetg (data.wcs_, WTraits::length (data.wcs_));
+            wsb.pubsetg (data.wcs_, data.wlen_);
 
             test_get_data (data, wp,
                            std::istreambuf_iterator<wchar_t>(&wsb),
@@ -445,6 +453,8 @@
             test_put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
                            nio, ' ', '\0');
 
+            data.nlen_ = std::char_traits<char>::length (data.ncs_);
+
             rw_fatal (!nio.fail (), __FILE__, __LINE__,
                       "num_put<char>::put(...) failed for locale(%#s)",
                       data.locale_name_);
@@ -460,13 +470,15 @@
             test_put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
                            wio, L' ', L'\0');
 
+            data.wlen_ = std::char_traits<wchar_t>::length (data.wcs_);
+
             rw_fatal (!wio.fail (), __FILE__, __LINE__,
                       "num_put<wchar_t>::put(...) failed for locale(%#s)",
                       data.locale_name_);
 
 #endif // _RWSTD_NO_WCHAR_T
 
-            if (rw_opt_shared_locale)
+            if (opt_shared_locale)
                 data.locale_ = loc;
 
             nlocales += 1;
@@ -487,8 +499,8 @@
     rw_info (0, 0, 0,
              "testing std::num_get<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
-             rw_opt_nthreads, 1 != rw_opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops,
+             opt_nthreads, 1 != opt_nthreads,
+             opt_nloops, 1 != opt_nloops,
              nlocales, int (nlocales), "%#s", locales);
 
     rw_info (0, 0, 0, "exercising std::num_get<char>");
@@ -498,11 +510,12 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #ifndef _RWSTD_NO_WCHAR_T
 
@@ -513,11 +526,12 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     // exercise both the char and the wchar_t specializations
     // at the same time
@@ -530,11 +544,12 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #endif   // _RWSTD_NO_WCHAR_T
 
@@ -549,24 +564,26 @@
 
     // set nthreads to the greater of the number of processors
     // and 2 (for uniprocessor systems) by default
-    rw_opt_nthreads = rw_get_cpus ();
-    if (rw_opt_nthreads < 2)
-        rw_opt_nthreads = 2;
+    opt_nthreads = rw_get_cpus ();
+    if (opt_nthreads < 2)
+        opt_nthreads = 2;
 
 #endif   // _RWSTD_REENTRANT
 
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.num.get",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "       // must be non-negative
                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "     // arg must be non-negative
                     "|-locales= "       // must be provided
                     "|-shared-locale# ",
-                    &rw_opt_nloops,
+                    &opt_timeout,
+                    &opt_nloops,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads,
+                    &opt_nthreads,
                     &opt_nlocales,
                     &rw_opt_setlocales,
-                    &rw_opt_shared_locale);
+                    &opt_shared_locale);
 }
diff --git a/tests/localization/22.locale.num.put.mt.cpp b/tests/localization/22.locale.num.put.mt.cpp
index 73c9fd1..3fe4992 100644
--- a/tests/localization/22.locale.num.put.mt.cpp
+++ b/tests/localization/22.locale.num.put.mt.cpp
@@ -64,6 +64,9 @@
 // of creating their own?
 int opt_shared_locale;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -238,6 +241,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         // fill in the value and results for this locale
         const MyNumData& data = my_num_data [i % nlocales];
 
@@ -245,7 +251,7 @@
         // so that the locale is used not only by the num_put facet
         const std::locale loc =
             opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -394,7 +400,8 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -409,7 +416,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -426,7 +434,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -454,11 +463,13 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.num.put",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "       // must be non-negative
                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "     // arg must be non-negative
                     "|-locales= "       // must be provided
                     "|-shared-locale# ",
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.numpunct.mt.cpp b/tests/localization/22.locale.numpunct.mt.cpp
index 3be343b..cc5399c 100644
--- a/tests/localization/22.locale.numpunct.mt.cpp
+++ b/tests/localization/22.locale.numpunct.mt.cpp
@@ -47,7 +47,7 @@
 
 // the number of times each thread should iterate (unless specified
 // otherwise on the command line)
-int rw_opt_nloops = 200000;
+int opt_nloops = 200000;
 
 #if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
 
@@ -66,6 +66,9 @@
 // of creating their own?
 int opt_shared_locale;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -111,7 +114,10 @@
 static void*
 thread_func (void*)
 {
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    for (int i = 0; i != opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
 
         const std::size_t inx = std::size_t (i) % nlocales;
 
@@ -120,7 +126,7 @@
         // construct a named locale
         const std::locale loc =
             opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -250,7 +256,7 @@
              "testing std::numpunct<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
              opt_nthreads, 1 != opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops,
+             opt_nloops, 1 != opt_nloops,
              nlocales, int (nlocales), "%#s", locales);
 
     rw_info (0, 0, 0, "exercising std::numpunct<char>");
@@ -260,7 +266,8 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -276,7 +283,8 @@
     // start a pool of threads to exercise the thread safety
     // of the wchar_t specialization
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -293,7 +301,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -321,12 +330,14 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.numpunct",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "       // must be non-negative
                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "     // arg must be non-negative
                     "|-locales= "       // must be provided
                     "|-shared-locale# ",
-                    &rw_opt_nloops,
+                    &opt_timeout,
+                    &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
                     &opt_nlocales,
diff --git a/tests/localization/22.locale.statics.mt.cpp b/tests/localization/22.locale.statics.mt.cpp
index 2a4261e..e112d43 100644
--- a/tests/localization/22.locale.statics.mt.cpp
+++ b/tests/localization/22.locale.statics.mt.cpp
@@ -50,6 +50,9 @@
 int opt_classic;
 int opt_global;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale objects to use for testing
@@ -92,6 +95,9 @@
 {
     for (std::size_t i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         const std::size_t inx = i % nlocales;
 
         const std::locale last (std::locale::global (locales [inx]));
@@ -125,7 +131,7 @@
 
         // create and start a pool of threads and wait for them to finish
         result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
-                                 test_classic, 0);
+                                 test_classic, 0, std::size_t (opt_timeout));
     }
 
     if (rw_note (0 <= opt_global, 0, __LINE__,
@@ -161,7 +167,7 @@
 
         // create and start a pool of threads and wait for them to finish
         result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
-                                 test_global, 0);
+                                 test_global, 0, std::size_t (opt_timeout));
     }
 
     return result;
@@ -187,11 +193,13 @@
                     run_test,
                     "|-classic~ "
                     "|-global~ "
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "        // arg must be non-negative
                     "|-nthreads#0-* "    // arg must be in [0, MAX_THREADS]
                     "|-locales= ",       // argument must be provided
                     &opt_classic,
                     &opt_global,
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/localization/22.locale.time.get.mt.cpp b/tests/localization/22.locale.time.get.mt.cpp
index 94e8285..72ffc24 100644
--- a/tests/localization/22.locale.time.get.mt.cpp
+++ b/tests/localization/22.locale.time.get.mt.cpp
@@ -43,17 +43,20 @@
 
 // default number of threads (will be adjusted to the number
 // of processors/cores later)
-int rw_opt_nthreads = 1;
+int opt_nthreads = 1;
 
 // the number of times each thread should iterate
-int rw_opt_nloops = 50000;
+int opt_nloops = 50000;
 
 // number of locales to use
-int rw_opt_nlocales = MAX_THREADS;
+int opt_nlocales = MAX_THREADS;
 
 // should all threads share the same set of locale objects instead
 // of creating their own?
-int rw_opt_shared_locale;
+int opt_shared_locale;
+
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
 
 /**************************************************************************/
 
@@ -162,7 +165,10 @@
     std::ios_base::iostate state = std::ios_base::goodbit;
 
     std::tm local;
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    for (int i = 0; i != opt_nloops; ++i) {
+
+        if (rw_thread_pool_timeout_expired ())
+            break;
 
         // save the name of the locale
         const MyTimeData& data = my_time_data [i % nlocales];
@@ -171,8 +177,8 @@
         // facet from it and use it to format a random time value
         // using a random conversion specifier
         const std::locale loc =
-            rw_opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+            opt_shared_locale ? data.locale_
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -420,7 +426,7 @@
 
 #endif // _RWSTD_NO_WCHAR_T
 
-            if (rw_opt_shared_locale)
+            if (opt_shared_locale)
                 data.locale_ = loc;
 
             nlocales += 1;
@@ -431,7 +437,7 @@
                      "failed to create locale(%#s)", name);
         }
 
-        if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
+        if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
             break;
     }
 
@@ -442,8 +448,8 @@
     rw_info (0, 0, 0,
              "testing std::time_get<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
-             rw_opt_nthreads, 1 != rw_opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops,
+             opt_nthreads, 1 != opt_nthreads,
+             opt_nloops, 1 != opt_nloops,
              nlocales, int (nlocales), "%#s", locales);
 
     rw_info (0, 0, 0, "exercising std::time_get<char>");
@@ -453,11 +459,12 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #ifndef _RWSTD_NO_WCHAR_T
 
@@ -468,11 +475,12 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     // exercise both the char and the wchar_t specializations
     // at the same time
@@ -485,11 +493,12 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #endif   // _RWSTD_NO_WCHAR_T
 
@@ -504,24 +513,26 @@
 
     // set nthreads to the greater of the number of processors
     // and 2 (for uniprocessor systems) by default
-    rw_opt_nthreads = rw_get_cpus ();
-    if (rw_opt_nthreads < 2)
-        rw_opt_nthreads = 2;
+    opt_nthreads = rw_get_cpus ();
+    if (opt_nthreads < 2)
+        opt_nthreads = 2;
 
 #endif   // _RWSTD_REENTRANT
 
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.time.get",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "       // must be non-negative
                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "     // arg must be non-negative
                     "|-locales= "       // must be provided
                     "|-shared-locale# ",
-                    &rw_opt_nloops,
+                    &opt_timeout,
+                    &opt_nloops,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads,
-                    &rw_opt_nlocales,
+                    &opt_nthreads,
+                    &opt_nlocales,
                     &rw_opt_setlocales,
-                    &rw_opt_shared_locale);
+                    &opt_shared_locale);
 }
diff --git a/tests/localization/22.locale.time.put.cpp b/tests/localization/22.locale.time.put.cpp
index 5bca51c..6268a27 100644
--- a/tests/localization/22.locale.time.put.cpp
+++ b/tests/localization/22.locale.time.put.cpp
@@ -405,10 +405,15 @@
 
     std::ostreambuf_iterator<charT> it (&sb);
 
+    // convert the narrow fill character to the generic charT
+    // being careful to avoid (potential) sign extension
+    typedef unsigned char UChar;
+    const charT wfill = charT (UChar (fill));
+
     if (patend - pat == 2 && '%' == pat [0]) {
 
         // format character, no modifier
-        *tp.put (it, ios, fill, tmb, char (wpat [1])) = charT ();
+        *tp.put (it, ios, wfill, tmb, char (wpat [1])) = charT ();
 
         const bool success = 0 == rw_strncmp (buf, result);
 
@@ -425,7 +430,7 @@
     else if (patend - pat == 3 && '%' == pat [0]) {
 
         // format character preceded by a format modifier
-        *tp.put (it, ios, fill, tmb, char (wpat [2]), char (wpat [1])) =
+        *tp.put (it, ios, wfill, tmb, char (wpat [2]), char (wpat [1])) =
             charT ();
 
         const bool success = 0 == rw_strncmp (buf, result);
@@ -442,7 +447,7 @@
     sb.pubsetp (buf, buf + sizeof buf / sizeof *buf);
 
     // format string
-    *tp.put (it, ios, fill, tmb, wpat, wpat + (patend - pat)) = charT ();
+    *tp.put (it, ios, wfill, tmb, wpat, wpat + (patend - pat)) = charT ();
 
     const bool success = 0 == rw_strncmp (buf, result);
 
@@ -507,6 +512,8 @@
         return 0;
 
     std::FILE *fout = std::fopen (srcfname, "w");
+    if (0 == fout)
+        return 0;
 
     std::fprintf (fout, "LC_TIME\n");
 
@@ -643,6 +650,9 @@
         return 0;
 
     fout = std::fopen (cmfname, "w");
+    if (0 == fout)
+        return 0;
+
     pcs_write (fout, 0);
 
     std::fclose (fout);
diff --git a/tests/localization/22.locale.time.put.mt.cpp b/tests/localization/22.locale.time.put.mt.cpp
index 717de55..d55f744 100644
--- a/tests/localization/22.locale.time.put.mt.cpp
+++ b/tests/localization/22.locale.time.put.mt.cpp
@@ -67,6 +67,9 @@
 // of creating their own?
 int opt_shared_locale;
 
+// default timeout used by each threaded section of this test
+int opt_timeout = 60;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -157,6 +160,9 @@
 
     for (int i = 0; i != opt_nloops; ++i) {
 
+        if (rw_thread_pool_timeout_expired ())
+            break;
+
         // save the name of the locale
         const MyTimeData& data = my_time_data [i % nlocales];
 
@@ -165,7 +171,7 @@
         // using a random conversion specifier
         const std::locale loc =
             opt_shared_locale ? data.locale_
-                                 : std::locale (data.locale_name_);
+                              : std::locale (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
@@ -331,7 +337,8 @@
 
     // create and start a pool of threads and wait for them to finish
     int result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -346,7 +353,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -363,7 +371,8 @@
 
     // start a pool of threads to exercise wstring thread safety
     result =
-        rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0);
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
+                        thread_func, 0, std::size_t (opt_timeout));
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
@@ -391,11 +400,13 @@
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.time.put",
                     "thread safety", run_test,
+                    "|-soft-timeout#0 "  // must be non-negative
                     "|-nloops#0 "       // must be non-negative
                     "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
                     "|-nlocales#0 "     // arg must be non-negative
                     "|-locales= "       // must be provided
                     "|-shared-locale# ",
+                    &opt_timeout,
                     &opt_nloops,
                     int (MAX_THREADS),
                     &opt_nthreads,
diff --git a/tests/numerics/26.valarray.cassign.cpp b/tests/numerics/26.valarray.cassign.cpp
index 4d48ad9..7693b80 100644
--- a/tests/numerics/26.valarray.cassign.cpp
+++ b/tests/numerics/26.valarray.cassign.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright (C) 2007 Rogue Wave Software, Inc.
+ * Copyright (C) 2007-2008 Rogue Wave Software, Inc.
  *
  **************************************************************************/
 
@@ -805,15 +805,15 @@
     TEST (int);
     TEST (double);
 
-#if 0x04020000 >= _RWSTD_VER
+#if 0x04020100 >= _RWSTD_VER
 
-    // test fails to compile with stdcxx 4.2.0 and prior due to
+    // test fails to compile with stdcxx 4.2.1 and prior due to
     // STDCXX-512: http://issues.apache.org/jira/browse/STDCXX-512
     rw_warn (0, 0, __LINE__,
              "test of UserClass disabled in stdcxx 4.2.0 and prior "
              "due to STDCXX-512");
 
-#else   // stdcxx > 4.2.0
+#else   // stdcxx >= 4.2.1
 
     TEST (UserClass);
 
diff --git a/tests/regress/18.limits.stdcxx-937.cpp b/tests/regress/18.limits.stdcxx-937.cpp
new file mode 100644
index 0000000..d04c2f1
--- /dev/null
+++ b/tests/regress/18.limits.stdcxx-937.cpp
@@ -0,0 +1,135 @@
+/************************************************************************
+ *
+ * 18.limits.stdcxx-937.cpp - test case for STDCXX-937
+ *
+ * $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 <cassert>
+#include <limits>
+
+int main()
+{
+    // work extra hard to prevent aggressive optimizers from
+    // optimizing the code away on the assumption that no
+    // object has a null address
+    const void* const fmemaddr[] = {
+        &std::numeric_limits<float>::is_specialized,
+        &std::numeric_limits<float>::digits,
+        &std::numeric_limits<float>::digits10,
+
+        &std::numeric_limits<float>::is_signed,
+        &std::numeric_limits<float>::is_integer,
+        &std::numeric_limits<float>::is_exact,
+        &std::numeric_limits<float>:: radix,
+
+        &std::numeric_limits<float>::min_exponent,
+        &std::numeric_limits<float>::min_exponent10,
+        &std::numeric_limits<float>::max_exponent,
+        &std::numeric_limits<float>::max_exponent10,
+
+        &std::numeric_limits<float>::has_infinity,
+        &std::numeric_limits<float>::has_quiet_NaN,
+        &std::numeric_limits<float>::has_signaling_NaN,
+        &std::numeric_limits<float>::has_denorm,
+        &std::numeric_limits<float>::has_denorm_loss,
+
+        &std::numeric_limits<float>::is_iec559,
+        &std::numeric_limits<float>::is_bounded,
+        &std::numeric_limits<float>::is_modulo,
+
+        &std::numeric_limits<float>::traps,
+        &std::numeric_limits<float>::tinyness_before,
+
+        &std::numeric_limits<float>::round_style
+    };
+
+    const void* const memaddr[] = {
+        &std::numeric_limits<double>::is_specialized,
+        &std::numeric_limits<double>::digits,
+        &std::numeric_limits<double>::digits10,
+
+        &std::numeric_limits<double>::is_signed,
+        &std::numeric_limits<double>::is_integer,
+        &std::numeric_limits<double>::is_exact,
+        &std::numeric_limits<double>:: radix,
+
+        &std::numeric_limits<double>::min_exponent,
+        &std::numeric_limits<double>::min_exponent10,
+        &std::numeric_limits<double>::max_exponent,
+        &std::numeric_limits<double>::max_exponent10,
+
+        &std::numeric_limits<double>::has_infinity,
+        &std::numeric_limits<double>::has_quiet_NaN,
+        &std::numeric_limits<double>::has_signaling_NaN,
+        &std::numeric_limits<double>::has_denorm,
+        &std::numeric_limits<double>::has_denorm_loss,
+
+        &std::numeric_limits<double>::is_iec559,
+        &std::numeric_limits<double>::is_bounded,
+        &std::numeric_limits<double>::is_modulo,
+
+        &std::numeric_limits<double>::traps,
+        &std::numeric_limits<double>::tinyness_before,
+
+        &std::numeric_limits<double>::round_style
+    };
+
+    const void* const ldmemaddr[] = {
+        &std::numeric_limits<long double>::is_specialized,
+        &std::numeric_limits<long double>::digits,
+        &std::numeric_limits<long double>::digits10,
+
+        &std::numeric_limits<long double>::is_signed,
+        &std::numeric_limits<long double>::is_integer,
+        &std::numeric_limits<long double>::is_exact,
+        &std::numeric_limits<long double>:: radix,
+
+        &std::numeric_limits<long double>::min_exponent,
+        &std::numeric_limits<long double>::min_exponent10,
+        &std::numeric_limits<long double>::max_exponent,
+        &std::numeric_limits<long double>::max_exponent10,
+
+        &std::numeric_limits<long double>::has_infinity,
+        &std::numeric_limits<long double>::has_quiet_NaN,
+        &std::numeric_limits<long double>::has_signaling_NaN,
+        &std::numeric_limits<long double>::has_denorm,
+        &std::numeric_limits<long double>::has_denorm_loss,
+
+        &std::numeric_limits<long double>::is_iec559,
+        &std::numeric_limits<long double>::is_bounded,
+        &std::numeric_limits<long double>::is_modulo,
+
+        &std::numeric_limits<long double>::traps,
+        &std::numeric_limits<long double>::tinyness_before,
+
+        &std::numeric_limits<long double>::round_style
+    };
+
+    for (unsigned i = 0; i != sizeof memaddr / sizeof *memaddr; ++i) {
+        assert (fmemaddr [i] != 0);
+        assert (memaddr [i] != 0);
+        assert (ldmemaddr [i] != 0);
+    }
+
+    return 0;
+}
diff --git a/tests/regress/27.ostream.inserters.stdcxx-51.cpp b/tests/regress/27.ostream.inserters.stdcxx-51.cpp
new file mode 100644
index 0000000..052b3a2
--- /dev/null
+++ b/tests/regress/27.ostream.inserters.stdcxx-51.cpp
@@ -0,0 +1,126 @@
+/**************************************************************************
+ *
+ * 27.stream.inserters.stdcxx-51.cpp - regression test for STDCXX-51
+ *
+ * http://issues.apache.org/jira/browse/STDCXX-51
+ *
+ * $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 <cassert>
+#include <cstdio>
+#include <limits>
+#include <sstream>
+
+
+template <class FloatT>
+bool test (const char *tname)
+{
+    // zero and one used to verify sanity
+    const FloatT zero =  FloatT ();
+    const FloatT pone = +FloatT (1);
+    const FloatT none = -FloatT (1);
+
+    // positive and negative Infinity
+    const FloatT pinf = +std::numeric_limits<FloatT>::infinity ();
+    const FloatT ninf = -std::numeric_limits<FloatT>::infinity ();
+
+    // positive and negative Quiet NaN
+    const FloatT pqnan = +std::numeric_limits<FloatT>::quiet_NaN ();
+    const FloatT nqnan = -std::numeric_limits<FloatT>::quiet_NaN ();
+
+    // positive and negative Signaling NaN
+    const FloatT psnan = +std::numeric_limits<FloatT>::signaling_NaN ();
+    const FloatT nsnan = -std::numeric_limits<FloatT>::signaling_NaN ();
+
+    std::ostringstream out;
+
+    out << "     0.0:  " << zero  << '\n'
+        << "  +/-1.0:  " << pone  << ' ' << none  << '\n'
+        << "  +/-INF:  " << pinf  << ' ' << ninf  << '\n'
+        << "  +/-QNAN: " << pqnan << ' ' << nqnan << '\n'
+        << "  +/-SNAN: " << psnan << ' ' << nsnan << '\n';
+
+    // expected output
+    const char expect[] = {
+        "     0.0:  0\n"
+        "  +/-1.0:  1 -1\n"
+        "  +/-INF:  inf -inf\n"
+        "  +/-QNAN: qnan -qnan\n"
+        "  +/-SNAN: snan -snan\n"
+    };
+
+    bool pass = true;
+
+    if (expect != out.str ()) {
+        std::fprintf (stderr, "Expected (%s):\n%s\nGot:\n%s\n",
+                      tname, expect, out.str ().c_str ());
+        pass = false;
+    }
+
+    // clear string and set the uppercase bit in flags
+    out.str ("");
+    out.setf (out.uppercase);
+
+    out << "     0.0:  " << zero  << '\n'
+        << "  +/-1.0:  " << pone  << ' ' << none  << '\n'
+        << "  +/-INF:  " << pinf  << ' ' << ninf  << '\n'
+        << "  +/-QNAN: " << pqnan << ' ' << nqnan << '\n'
+        << "  +/-SNAN: " << psnan << ' ' << nsnan << '\n';
+
+    // expected output
+    const char EXPECT[] = {
+        "     0.0:  0\n"
+        "  +/-1.0:  1 -1\n"
+        "  +/-INF:  INF -INF\n"
+        "  +/-QNAN: QNAN -QNAN\n"
+        "  +/-SNAN: SNAN -SNAN\n"
+    };
+
+    if (EXPECT != out.str ()) {
+        std::fprintf (stderr, "Expected (%s):\n%s\nGot:\n%s\n",
+                      tname, EXPECT, out.str ().c_str ());
+        pass = false;
+    }
+
+    return pass;
+}
+
+
+int main ()
+{
+    bool pass;
+
+    // exercise the formatting of Infinities and NaNs
+    pass = test<float>("float");
+    pass = test<double>("double") && pass;
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+    pass = test<long double>("long double") && pass;
+
+#endif   // _RWSTD_NO_LONG_DOUBLE
+
+    assert (pass);
+
+    return 0;
+}
diff --git a/tests/self/0.locale.cpp b/tests/self/0.locale.cpp
new file mode 100644
index 0000000..5310b81
--- /dev/null
+++ b/tests/self/0.locale.cpp
@@ -0,0 +1,115 @@
+/************************************************************************
+ *
+ * 0.locale.cpp - test exercising the test driver locale helpers
+ *
+ * $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.
+ *
+ * Copyright 2008 Rogue Wave Software, Inc.
+ * 
+ **************************************************************************/
+
+#include <cstdio>        // for remove()
+#include <cstdlib>       // for getenv()
+
+#include <environ.h>     // for rw_putenv()
+#include <file.h>        // for rw_fwrite()
+#include <driver.h>      // for rw_test(), etc.
+#include <rw_locale.h>   // for rw_localedef()
+#include <rw_printf.h>   // for rw_fprintf()
+
+/**************************************************************************/
+
+static int
+test_localedef ()
+{
+    // the root of the locale directory (RWSTD_LOCALE_ROOT)
+    static const char* const locale_root = rw_set_locale_root ();
+
+    static int inx;
+
+    const int id = inx++;
+
+    // create a temporary locale definition file
+    char srcfname [1024];
+    if (rw_snprintf (srcfname, sizeof srcfname, "%s%c%s.%d",
+                     locale_root, _RWSTD_PATH_SEP, "locale", id) < 0)
+        return -1;
+
+    // create a temporary character map file
+    char cmfname [1024];
+    if (rw_snprintf (cmfname, sizeof cmfname, "%s%c%s.%d.src",
+                     locale_root, _RWSTD_PATH_SEP, "charmap", id) < 0)
+        return -1;
+
+    rw_fwrite (srcfname, "LC_CTYPE\nEND LC_CTYPE\n");
+    rw_fwrite (cmfname, "CHARMAP\nEND CHARMAP\n");
+
+    const char opts[]    = "-w";
+    char locname[40];
+    rw_snprintf (locname, sizeof locname, "%s.%d", "locale", id);
+
+    // try to create the locale
+    const char* const ret =
+        rw_localedef (opts, srcfname, cmfname, locname);
+
+    const char* const topdir = std::getenv ("TOPDIR");
+
+    rw_assert (0 != ret, 0, __LINE__,
+               "rw_localedef(%s, %#s, %#s, %#s) failed with TOPDIR=%#s",
+               opts, srcfname, cmfname, locname, topdir);
+
+    // remove temporary files
+    std::remove (cmfname);
+    std::remove (srcfname);
+
+    return 0;
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char*[])
+{
+    // exercise with the default setting of TOPDIR
+    rw_error (0 == test_localedef (), 0, __LINE__, "");
+
+    // exercise with TOPDIR set but empty
+    rw_putenv ("TOPDIR=");
+    rw_error (0 == test_localedef (), 0, __LINE__, "");
+
+    // exercise with TOPDIR unset
+    rw_putenv ("TOPDIR");
+    rw_error (0 == test_localedef (), 0, __LINE__, "");
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    0 /* no section */,
+                    0 /* no comment */,
+                    run_test,
+                    "",
+                    0);
+}
diff --git a/tests/src/alarm.cpp b/tests/src/alarm.cpp
index f7f0c65..7df7ea5 100644
--- a/tests/src/alarm.cpp
+++ b/tests/src/alarm.cpp
@@ -44,16 +44,16 @@
 // exported/imported
 
 /* extern _TEST_EXPORT */ rw_signal_handler_t* const
-rw_sig_dfl = (rw_signal_handler_t*)-1;
+rw_sig_dfl = (rw_signal_handler_t*)0;
 
 /* extern _TEST_EXPORT */ rw_signal_handler_t* const
-rw_sig_ign = (rw_signal_handler_t*)-2;
+rw_sig_ign = (rw_signal_handler_t*)1;
 
 /* extern _TEST_EXPORT */ rw_signal_handler_t* const
-rw_sig_hold = (rw_signal_handler_t*)-3;
+rw_sig_hold = (rw_signal_handler_t*)2;
 
 /* extern _TEST_EXPORT */ rw_signal_handler_t* const
-rw_sig_restore = (rw_signal_handler_t*)-4;
+rw_sig_restore = (rw_signal_handler_t*)3;
 
 
 // may point to a user-defined handler for the alarm
@@ -133,7 +133,7 @@
 #  endif
 
 #  ifndef SIG_DFL
-#    define SIG_IGN (rw_signal_handler_t*)0
+#    define SIG_DFL (rw_signal_handler_t*)0
 #  endif   // SIG_DFL
 
 #  ifndef SIG_IGN
diff --git a/tests/src/cmdopt.cpp b/tests/src/cmdopt.cpp
index cbdb185..6ec1cf3 100644
--- a/tests/src/cmdopt.cpp
+++ b/tests/src/cmdopt.cpp
@@ -20,7 +20,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 2005-2006 Rogue Wave Software.
+ * Copyright 2005-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -518,6 +518,8 @@
                 lopt = lastopt->loptbuf_;
             else {
                 lopt = (char*)malloc (optlen + 1);
+                if (0 == lopt)
+                    return -1;   // error
                 lastopt->lopt_ = lopt;
             }
 
@@ -534,6 +536,8 @@
 
         int arg_is_callback = true;
 
+        RW_ASSERT (0 != next);
+
         if ('#' == *next) {
             // examples of option specification:
             //   --foo#     option takes an optional numeric argument
diff --git a/tests/src/locale.cpp b/tests/src/locale.cpp
index f93480c..8ec8dbd 100644
--- a/tests/src/locale.cpp
+++ b/tests/src/locale.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 2001-2007 Rogue Wave Software, Inc.
+ * Copyright 2001-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -215,8 +215,22 @@
 
     // otherwise, try to create the locale database
 
+    // fallback for when TOPDIR is unset or empty
+    char topdir_path_buf [] = __FILE__;
+
     // use TOPDIR to determine the root of the source tree
-    const char* const topdir = getenv (TOPDIR);
+    const char* topdir = getenv (TOPDIR);
+    if (!topdir || !*topdir) {
+
+        // try to get TOPDIR from __FILE__
+        char* const slash = strrchr (topdir_path_buf, _RWSTD_PATH_SEP);
+
+        if (slash) {
+            slash [-1] = '\0';
+            topdir     = topdir_path_buf;
+        }
+    }
+
     if (!topdir || !*topdir) {
         rw_error (0, __FILE__, __LINE__,
                   "the environment variable %s is %s",
@@ -1097,8 +1111,22 @@
         _rw_lookup_table_t countries_map;
         _rw_lookup_table_t encodings_map;
 
+        // fallback for when TOPDIR is unset or empty
+        char topdir_path_buf [] = __FILE__;
+
         // use TOPDIR to determine the root of the source tree
-        const char* const topdir = getenv (TOPDIR);
+        const char* topdir = getenv (TOPDIR);
+        if (!topdir || !*topdir) {
+
+            // try to get TOPDIR from __FILE__
+            char* const slash = strrchr (topdir_path_buf, _RWSTD_PATH_SEP);
+
+            if (slash) {
+                slash [-1] = '\0';
+                topdir     = topdir_path_buf;
+            }
+        }
+
         if (!topdir || !*topdir) {
             rw_error (0, __FILE__, __LINE__,
                       "the environment variable %s is %s",
diff --git a/tests/src/opt_diags.cpp b/tests/src/opt_diags.cpp
index e6fce5f..342a622 100644
--- a/tests/src/opt_diags.cpp
+++ b/tests/src/opt_diags.cpp
@@ -22,7 +22,7 @@
  * implied.   See  the License  for  the  specific language  governing
  * permissions and limitations under the License.
  *
- * Copyright 1994-2006 Rogue Wave Software.
+ * Copyright 1994-2008 Rogue Wave Software, Inc.
  * 
  **************************************************************************/
 
@@ -282,6 +282,8 @@
             break;
         }
 
+        RW_ASSERT (0 != end);
+
         if (':' == *end || '\0' == *end) {
             parg = end + (0 != *end);
             end  = strpbrk (parg, ":,");
@@ -299,6 +301,8 @@
                 break;
             }
 
+            RW_ASSERT (0 != end);
+
             if (':' == *end || '\0' == *end) {
                 parg = end + ('\0' != *end);
                 end  = strpbrk (parg, ":,");
@@ -317,6 +321,8 @@
                     break;
                 }
 
+                RW_ASSERT (0 != end);
+
                 if (':' == *end || '\0' == *end) {
                     parg = end + (0 != *end);
                     end  = strpbrk (parg, ":,");
diff --git a/tests/src/printf.cpp b/tests/src/printf.cpp
index 7c23f8e..872617f 100644
--- a/tests/src/printf.cpp
+++ b/tests/src/printf.cpp
@@ -1424,13 +1424,6 @@
     if (spec.fl_zero)
         *pf++ = '0';
 
-    if (spec.mod != spec.mod_ext_A && 0 <= spec.width) {
-        pf += sprintf (pf, "%i", spec.width);
-    }
-
-    if (0 <= spec.prec)
-        pf += sprintf (pf, ".%i", spec.prec);
-
     if (spec.mod == spec.mod_h)
         *pf++ = 'h';
     else if (spec.mod == spec.mod_hh) {
@@ -1458,6 +1451,13 @@
         pf += strlen (pf);
     }
 
+    if (spec.mod != spec.mod_ext_A && 0 <= spec.width) {
+        pf += sprintf (pf, "%i", spec.width);
+    }
+
+    if (0 <= spec.prec)
+        pf += sprintf (pf, ".%i", spec.prec);
+
     *pf++ = char (spec.cvtspec);
     *pf   = '\0';
 
@@ -1499,7 +1499,6 @@
             buffer [len - 3] = buffer [len - 2];
             buffer [len - 2] = buffer [len - 1];
             buffer [len - 1] = buffer [len];
-            --len;
         }
     }
 
diff --git a/tests/src/thread.cpp b/tests/src/thread.cpp
index d2864d7..562b9d7 100644
--- a/tests/src/thread.cpp
+++ b/tests/src/thread.cpp
@@ -30,6 +30,7 @@
 #define _RWSTD_TEST_SRC
 
 #include <rw_thread.h>
+#include <rw_alarm.h>   // for rw_alarm()
 #include <stddef.h>     // for size_t
 #include <string.h>     // for memset()
 
@@ -52,16 +53,41 @@
 
 static long maxthreads;
 
+/************************************************************************/
+
+static volatile int
+_rw_timeout_expired = 0;
+
+/************************************************************************/
+
+_TEST_EXPORT int
+rw_thread_pool_timeout_expired ()
+{
+    return _rw_timeout_expired != 0;
+}
+
+/************************************************************************/
+
+extern "C" {
+
+static void
+_rw_timeout_handler (int)
+{
+    _rw_timeout_expired = 1;
+}
+
+}    // extern "C"
+
+/************************************************************************/
+
 
 #if defined (_RWSTD_POSIX_THREADS)
 #  include <pthread.h>
 
-extern "C" {
-
 _TEST_EXPORT int
 rw_thread_create (rw_thread_t *thr_id,
                   rw_thread_attr_t*,
-                  void* (*thr_proc)(void*),
+                  rw_thread_proc *thr_proc,
                   void *thr_arg)
 {
 #ifdef _RWSTD_OS_SUNOS
@@ -109,19 +135,15 @@
     return result;
 }
 
-}   // extern "C"
-
 /**************************************************************************/
 
 #elif defined (_RWSTD_SOLARIS_THREADS)
 #  include <thread.h>
 
-extern "C" {
-
 _TEST_EXPORT int
 rw_thread_create (rw_thread_t *thr_id,
                   rw_thread_attr_t*,
-                  void* (*thr_proc)(void*),
+                  rw_thread_proc *thr_proc,
                   void *thr_arg)
 {
     static int concurrency_set;
@@ -170,8 +192,6 @@
     return result;
 }
 
-}   // extern "C"
-
 /**************************************************************************/
 
 #elif defined (_RWSTD_DEC_THREADS)
@@ -179,13 +199,10 @@
 #  include <setjmp.h>
 #  include <cma.h>
 
-
-extern "C" {
-
 _TEST_EXPORT int
 rw_thread_create (rw_thread_t *thr_id,
                   rw_thread_attr_t*,
-                  void* (*thr_proc)(void*),
+                  rw_thread_proc *thr_proc,
                   void *thr_arg)
 {
     rw_thread_t tmpid;
@@ -244,19 +261,15 @@
     return status;
 }
 
-}   // extern "C"
-
 /**************************************************************************/
 
 #elif defined (_WIN32) && defined (_MT)
 #  include <process.h>    // for _beginthreadex()
 
-extern "C" {
-
 _TEST_EXPORT int
 rw_thread_create (rw_thread_t *thr_id,
                   rw_thread_attr_t*,
-                  void* (*thr_proc)(void*),
+                  rw_thread_proc *thr_proc,
                   void *thr_arg)
 {
     int result = 0;
@@ -324,8 +337,6 @@
     return result;
 }
 
-}   // extern "C"
-
 /**************************************************************************/
 
 #else   // unknown/missing threads environment
@@ -352,12 +363,10 @@
 #    endif
 #  endif   // ENOTSUP
 
-extern "C" {
-
 _TEST_EXPORT int
 rw_thread_create (rw_thread_t*,
                   rw_thread_attr_t*,
-                  void* (*)(void*),
+                  rw_thread_proc*,
                   void*)
 {
     _RWSTD_UNUSED (maxthreads);
@@ -372,8 +381,6 @@
     return ENOTSUP;
 }
 
-}   // extern "C"
-
 #endif   // threads environment
 
 /**************************************************************************/
@@ -471,16 +478,20 @@
 
 /**************************************************************************/
 
-extern "C" {
-
-
 _TEST_EXPORT int
 rw_thread_pool (rw_thread_t        *thr_id,
                 size_t              nthrs,
                 rw_thread_attr_t*,
-                void*             (*thr_proc)(void*),
-                void*              *thr_arg)
+                rw_thread_proc     *thr_proc,
+                void*              *thr_arg,
+                size_t              timeout)
 {
+    // apply timeout if one was specified
+    if (0 != timeout) {
+        _rw_timeout_expired = 0;
+        rw_alarm (timeout, _rw_timeout_handler);
+    }
+
     // small buffer for thread ids when invoked with (thr_id == 0)
     rw_thread_t id_buf [16];
 
@@ -575,5 +586,3 @@
 
     return 0;
 }
-
-}   // extern "C"
diff --git a/tests/strings/21.cwctype.cpp b/tests/strings/21.cwctype.cpp
index 0457237..6199088 100644
--- a/tests/strings/21.cwctype.cpp
+++ b/tests/strings/21.cwctype.cpp
@@ -82,7 +82,6 @@
     "iswlower",
 #else
     "",
-#endif
 
 #ifdef iswprint
 #  undef iswprint
@@ -119,6 +118,8 @@
     "",
 #endif
 
+#endif
+
 #ifdef tolower
 #  undef tolower
     "tolower",