stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r278837 [1/4] - in /incubator/stdcxx/trunk: etc/config/ tests/ tests/include/ tests/localization/ tests/src/
Date Mon, 05 Sep 2005 20:57:48 GMT
Author: sebor
Date: Mon Sep  5 13:57:44 2005
New Revision: 278837

URL: http://svn.apache.org/viewcvs?rev=278837&view=rev
Log:
2005-09-05  Martin Sebor  <sebor@roguewave.com>
	
        STDCXX-3
	* tests/include/driver.h: New. Declarations of test suite driver
	functions.
	* tests/include/testdefs.h: New. Definitions of test suite macros.
	* tests/include/printf.h: New. Declarations of the rw_sprintf()
	family of testsuite helper functions for formatted output.
	* tests/include/valcmp.h: New. Declarations of the rw_valcmp()
	family of testsuite helper functions for comparing arrays of
	heterogeneous integral objects.
	* tests/include/cmdopt.h: New. Declarations of the rw_runopts()
	and rw_setopts() helper functions for the processing of command
	line options.
	* tests/src/valcmp.cpp: New. Implementation of the above.
	* tests/src/printf.cpp: Ditto.
	* tests/src/cmdopt.cpp: Ditto.
	* tests/src/driver.cpp: Ditto.
	* etc/config/GNUmakefile.tst: Partially reverted r225375
	and renamed the test/ subdirectory back to tests/.
	* etc/config/GNUmakefile.rwt: Ditto.

Added:
    incubator/stdcxx/trunk/tests/
    incubator/stdcxx/trunk/tests/include/
    incubator/stdcxx/trunk/tests/include/cmdopt.h   (with props)
    incubator/stdcxx/trunk/tests/include/driver.h   (with props)
    incubator/stdcxx/trunk/tests/include/printf.h   (with props)
    incubator/stdcxx/trunk/tests/include/testdefs.h   (with props)
    incubator/stdcxx/trunk/tests/include/valcmp.h   (with props)
    incubator/stdcxx/trunk/tests/localization/
    incubator/stdcxx/trunk/tests/localization/22.locale.money.put.cpp   (with props)
    incubator/stdcxx/trunk/tests/src/
    incubator/stdcxx/trunk/tests/src/cmdopt.cpp   (with props)
    incubator/stdcxx/trunk/tests/src/driver.cpp   (with props)
    incubator/stdcxx/trunk/tests/src/printf.cpp   (with props)
    incubator/stdcxx/trunk/tests/src/valcmp.cpp   (with props)
Modified:
    incubator/stdcxx/trunk/etc/config/GNUmakefile.rwt
    incubator/stdcxx/trunk/etc/config/GNUmakefile.tst

Modified: incubator/stdcxx/trunk/etc/config/GNUmakefile.rwt
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/etc/config/GNUmakefile.rwt?rev=278837&r1=278836&r2=278837&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/GNUmakefile.rwt (original)
+++ incubator/stdcxx/trunk/etc/config/GNUmakefile.rwt Mon Sep  5 13:57:44 2005
@@ -18,7 +18,7 @@
 
 # The place where the sources are looked for;
 # used in the variables setup in makefile.common
-TESTDIR      = $(TOPDIR)/test
+TESTDIR      = $(TOPDIR)/tests
 SRCDIRS      = $(TESTDIR)/src
 
 TARGET       = $(TESTDIR)/$(TESTLIB)

Modified: incubator/stdcxx/trunk/etc/config/GNUmakefile.tst
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/etc/config/GNUmakefile.tst?rev=278837&r1=278836&r2=278837&view=diff
==============================================================================
--- incubator/stdcxx/trunk/etc/config/GNUmakefile.tst (original)
+++ incubator/stdcxx/trunk/etc/config/GNUmakefile.tst Mon Sep  5 13:57:44 2005
@@ -8,7 +8,7 @@
 #
 #   $ make
 #
-#   To make all tests uder $(TOPDIR)/test. Will generate a .d file
+#   To make all tests uder $(TOPDIR)/tests. Will generate a .d file
 #   an place in the directory $(DEPENDDIR) for every source file.
 #
 #   $ make [ tagets ] run | runall | run_all
@@ -31,7 +31,7 @@
 include ../makefile.in
 
 # tests & test library directories
-TESTDIR      = $(TOPDIR)/test
+TESTDIR      = $(TOPDIR)/tests
 SRCDIRS      = $(TESTDIR)
 
 # get the test suite subdirectories

Added: incubator/stdcxx/trunk/tests/include/cmdopt.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/cmdopt.h?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/cmdopt.h (added)
+++ incubator/stdcxx/trunk/tests/include/cmdopt.h Mon Sep  5 13:57:44 2005
@@ -0,0 +1,44 @@
+/***************************************************************************
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#ifndef CMDOPT_H_INCLUDED
+#define CMDOPT_H_INCLUDED
+
+
+#include <rw/_defs.h>   // for libstd config macros
+#include <testdefs.h>   // for test config macros
+
+
+_TEST_EXPORT int
+rw_setopts (const char*, ...);
+
+_TEST_EXPORT int
+rw_runopts (int, char*[]);
+
+_TEST_EXPORT int
+rw_runopts (const char*);
+
+_TEST_EXPORT int
+rw_enabled (const char*);
+
+_TEST_EXPORT int
+rw_enabled (int);
+
+
+#endif   // CMDOPT_H_INCLUDED

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

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

Added: incubator/stdcxx/trunk/tests/include/driver.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/driver.h?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/driver.h (added)
+++ incubator/stdcxx/trunk/tests/include/driver.h Mon Sep  5 13:57:44 2005
@@ -0,0 +1,57 @@
+/************************************************************************
+ *
+ * driver.h - testsuite driver declarations
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_DRIVER_H_INCLUDED
+#define RW_DRIVER_H_INCLUDED
+
+#include <rw/_defs.h>   // for libstd config macros
+#include <testdefs.h>   // for test config macros
+
+
+_TEST_EXPORT int
+rw_test (int, char*[], const char*, const char*, const char*,
+         int (*)(int, char**), const char*, ...);
+
+_TEST_EXPORT int
+rw_fatal (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_error (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_assert (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_warn (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_note (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_info (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_debug (int, const char*, int, const char*, ...);
+
+_TEST_EXPORT int
+rw_trace (int, const char*, int, const char*, ...);
+
+#endif   // RW_DRIVER_H_INCLUDED

Propchange: incubator/stdcxx/trunk/tests/include/driver.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/include/driver.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/include/printf.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/printf.h?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/printf.h (added)
+++ incubator/stdcxx/trunk/tests/include/printf.h Mon Sep  5 13:57:44 2005
@@ -0,0 +1,148 @@
+/************************************************************************
+ *
+ * printf.h - declarations of the rw_printf family of functions
+ *
+ * $Id:$
+ *
+ ************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_PRINTF_H_INCLUDED
+#define RW_PRINTF_H_INCLUDED
+
+#include <testdefs.h>
+
+struct rw_file;
+
+// the equivalent of stdout and stderr
+extern _TEST_EXPORT rw_file* const rw_stdout;
+extern _TEST_EXPORT rw_file* const rw_stderr;
+
+
+/************************************************************************
+ * Formatted file output.
+ ************************************************************************/
+
+/**
+ *  Prints to rw_stdout.
+ */
+_TEST_EXPORT int
+rw_printf (const char*, ...);
+
+/**
+ * Prints to a file.
+ */
+_TEST_EXPORT int
+rw_fprintf (rw_file*, const char*, ...);
+
+
+/************************************************************************
+ * Formatted string output.
+ ************************************************************************/
+
+/**
+ * Prints to a character buffer.
+ */
+_TEST_EXPORT int
+rw_sprintf (char*, const char*, ...);
+
+/**
+ * Prints to a character buffer of given size.
+ */
+_TEST_EXPORT int
+rw_snprintf (char*, _RWSTD_SIZE_T, const char*, ...);
+
+
+/************************************************************************
+ * Formatted string output into a dynamically allocated buffer.
+ ************************************************************************/
+
+/**
+ * Prints to a dynamically allocated character buffer.
+ *
+ * @param fmt  Format specifier.
+ *
+ * @return  On success, returns a pointer to the dynamically allocated
+ *          character buffer. Otherwise, returns 0.
+ */
+_TEST_EXPORT char*
+rw_sprintfa (const char* fmt, ...);
+
+
+/**
+ * Prints to a dynamically allocated character buffer.
+ *
+ * @param buf  A pointer to character buffer where the function should
+ *        store its output.
+ * @param bufise  The size of the character buffer in bytes.
+ *
+ * @return  On success, if the size of the supplied buffer was sufficient
+ *          to format all characters including the terminating NUL, returns
+ *          buf. Otherwise, if the size of the supplied buffer was not
+ *          sufficient, returns a pointer to the newly allocated character
+ *          buffer of sufficient size. Returns 0 on failure.
+ */
+_TEST_EXPORT char*
+rw_snprintfa (char *buf, _RWSTD_SIZE_T bufsize, const char* fmt, ...);
+
+
+/**
+ * Prints to a dynamically allocated character buffer of sufficient size.
+ * Provided for portability with the BSD and GNU C libraries:
+ *
+ * http://www.freebsd.org/cgi/man.cgi?query=asprintf
+ * http://www.openbsd.org/cgi-bin/man.cgi?query=asprintf
+ * http://netbsd.gw.com/cgi-bin/man-cgi?asprintf++NetBSD-current
+ * http://www.gnu.org/software/libc/manual/html_node/Dynamic-Output.html
+ *
+ * @param pbuf  Pointer to a pointer to character set by the caller to
+ *        to address of the inital character buffer, or 0 of no such
+ *        buffer exists. The function sets the pointer to a the address
+ *        of the dynamically allocated character buffer, or leaves it
+ *        unchanged if it doesn't allocate any buffer.
+ * @param pbufsize  Pointer to a size_t set by the caller to the size of
+ *        the inital character buffer. The function sets the value pointed
+ *        to by this argument to the size of the dynamically allocated
+ *        character buffer, or leaves it unchanged if it doesn't allocate
+ *        any buffer.
+ * @param fmt  Format specifier.
+ *        The format specifier string has the same syntax as C99 sprintf
+ *        (see 7.19.6.1 of ISO/IEC 9899:1999) with the following extensions:
+ *
+ *        %n$          where n is a integer (see IEEE Std 1003.1)
+ *        %m           the value of strerror(errno)
+ *
+ *        %{?}         if clause (extracts an int)
+ *        %{:}         else clause
+ *        %{;}         end of if/else clause
+ *        %{#s}        quoted narrow character string
+ *        %{#ls}       quoted wide character string
+ *        %{$envvar}   value of an environment variable envvar
+ *        %{f}         function pointer
+ *        %{M}         member pointer
+ *        %{#m}        name of the errno constant (such as EINVAL)
+ *        %{n}         buffer size
+ *        %{S}         pointer to std::string
+ *        %{lS}        pointer to std::wstring
+ *        %{tm}        pointer to struct tm
+ *        %{InJ}       where n is one of { 8, 16, 32, 64 } and J { d, o, x, X }
+ *
+ * @return  On success, returns the number of characters formatted into
+ *          the buffer, otherwise -1.
+ */
+_TEST_EXPORT int
+rw_asnprintf (char** pbuf, _RWSTD_SIZE_T *pbufsize, const char *fmt, ...);
+
+#endif   // RW_PRINTF_H_INCLUDED

Propchange: incubator/stdcxx/trunk/tests/include/printf.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/include/printf.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/include/testdefs.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/testdefs.h?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/testdefs.h (added)
+++ incubator/stdcxx/trunk/tests/include/testdefs.h Mon Sep  5 13:57:44 2005
@@ -0,0 +1,62 @@
+/************************************************************************
+ *
+ * testdefs.h - common testsuite definitions
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_TESTDEFS_H_INCLUDED
+#define RW_TESTDEFS_H_INCLUDED
+
+
+#include <rw/_defs.h>
+
+
+#if    (defined (_WIN32) || defined (_WIN64)) \
+    && (defined (RWDLL) || defined (_RWSHARED))
+#  ifndef _RWSTD_TEST_SRC
+     // using a shared lib, import names
+#    define _TEST_EXPORT   __declspec (dllimport)
+#  else
+     // building a shared (test) lib, export names
+#    define _TEST_EXPORT   __declspec (dllexport)
+#  endif   // _RWSTD_LIB_SRC
+#else
+#    define _TEST_EXPORT
+#endif   // archive/shared library
+
+
+#if defined (_RWSTD_NO_TYPENAME) && !defined (typename)
+#  define typename /* ignore */
+#endif   // _RWSTD_NO_TYPENAME && !typename
+
+
+#ifndef _RWSTD_NO_FOR_INIT_SCOPE
+#  if defined (__GNUG__) && __GNUG__ < 3
+#    define _RWSTD_NO_FOR_INIT_SCOPE
+#  endif   // gcc < 3.0
+#  if defined (_MSC_VER) && _MSC_VER < 1300
+#    define _RWSTD_NO_FOR_INIT_SCOPE
+#  endif   // MSVC < 7.0
+#endif   // _RWSTD_NO_FOR_INIT_SCOPE
+
+#ifdef _RWSTD_NO_FOR_INIT_SCOPE
+#  define for   if (0) ; else for
+#endif   // _RWSTD_NO_FOR_INIT_SCOPE
+
+
+#endif   // RW_TESTDEFS_H_INCLUDED

Propchange: incubator/stdcxx/trunk/tests/include/testdefs.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/include/testdefs.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/include/valcmp.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/valcmp.h?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/include/valcmp.h (added)
+++ incubator/stdcxx/trunk/tests/include/valcmp.h Mon Sep  5 13:57:44 2005
@@ -0,0 +1,82 @@
+/************************************************************************
+ *
+ * valcmp.h - declarations of the rw_valcmp() family of helper functions
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#ifndef RW_VALCMP_H_INCLUDED
+#define RW_VALCMP_H_INCLUDED
+
+#include <testdefs.h>
+
+
+#define CMP_NULTERM   1   /* the first 0 terminates processing */
+#define CMP_RETOFF    2   /* return offset of the first mismatch */
+#define CMP_NOCASE    4   /* case-insensitive character comparison */
+
+
+_TEST_EXPORT int
+rw_valcmp (const void*, const void*,
+           _RWSTD_SIZE_T, _RWSTD_SIZE_T, _RWSTD_SIZE_T, int);
+
+/**
+ * Compares the contents of two arrays of objects of integral types,
+ * possibly of different sizes, for equality, in a strncmp/memcmp
+ * way.
+ *
+ * @param buf1  Pointer to an array of 0 or more objects of integral type.
+ * @param buf2  Pointer to an array of 0 or more objects of integral type.
+ * @param nelems  The maximum number of elements to compare.
+ * @param flags  Bitmap of flags that determine how the objects are
+ *               compared.
+ * @return  Returns -1, 0, or +1, depending on whether the first array
+ *          is less than, equal to, or greater than the second array.
+ */
+
+template <class T, class U>
+inline int
+rw_valcmp (const T*      buf1,
+           const U*      buf2,
+           _RWSTD_SIZE_T nelems,
+           int           flags = 0)
+{
+    return rw_valcmp (buf1, buf2, nelems, sizeof (T), sizeof (U), flags);
+}
+
+
+_TEST_EXPORT int
+rw_strncmp (const char*, const char*,
+            _RWSTD_SIZE_T = _RWSTD_SIZE_MAX, int = CMP_NULTERM);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+_TEST_EXPORT int
+rw_strncmp (const char*, const wchar_t*,
+            _RWSTD_SIZE_T = _RWSTD_SIZE_MAX, int = CMP_NULTERM);
+
+_TEST_EXPORT int
+rw_strncmp (const wchar_t*, const char*,
+            _RWSTD_SIZE_T = _RWSTD_SIZE_MAX, int = CMP_NULTERM);
+
+_TEST_EXPORT int
+rw_strncmp (const wchar_t*, const wchar_t*,
+            _RWSTD_SIZE_T = _RWSTD_SIZE_MAX, int = CMP_NULTERM);
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+#endif   // RW_VALCMP_H_INCLUDED

Propchange: incubator/stdcxx/trunk/tests/include/valcmp.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/include/valcmp.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/localization/22.locale.money.put.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/localization/22.locale.money.put.cpp?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/localization/22.locale.money.put.cpp (added)
+++ incubator/stdcxx/trunk/tests/localization/22.locale.money.put.cpp Mon Sep  5 13:57:44 2005
@@ -0,0 +1,854 @@
+/***************************************************************************
+ *
+ * locale.money.put.cpp - tests exercising the std::money_put facet
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#include <ios>
+#include <locale>
+#include <cstdio>     // for sprintf()
+
+#include <cmdopt.h>   // for rw_enabled()
+#include <driver.h>   // for rw_test()
+#include <valcmp.h>   // for rw_valcmp()
+
+/**************************************************************************/
+
+// set to non-zero value when grouping shouldn't be exercised
+static int no_grouping;
+
+// set to non-zero value when the basic_string overloads
+// of moneY-put::put() shouldn't be exercised
+static int no_basic_string;
+
+/**************************************************************************/
+
+template <class charT, bool Intl>
+struct Punct: std::moneypunct<charT, Intl>
+{
+    typedef typename std::moneypunct<charT>::char_type   char_type;
+    typedef typename std::moneypunct<charT>::string_type string_type;
+
+    static char_type                 decimal_point_;
+    static char_type                 thousands_sep_;
+    static const char               *grouping_;
+    static const char_type          *curr_symbol_;
+    static const char_type          *positive_sign_;
+    static const char_type          *negative_sign_;
+    static std::money_base::pattern  pos_format_;
+    static std::money_base::pattern  neg_format_;
+    static int                       frac_digits_;
+
+    static int n_thousands_sep_;   // number of calls to do_thousands_sep()
+
+    Punct (): std::moneypunct<charT>(1) { }
+
+    char_type do_decimal_point () const {
+        return decimal_point_;
+    }
+
+    int do_frac_digits () const {
+        return frac_digits_;
+    }
+
+    virtual string_type do_curr_symbol () const {
+        return curr_symbol_ ? curr_symbol_ : string_type ();
+    }
+
+    virtual std::string do_grouping () const {
+        return grouping_;
+    }
+
+    virtual char_type do_thousands_sep () const {
+        ++n_thousands_sep_;
+        return thousands_sep_;
+    }
+
+    virtual string_type do_positive_sign () const {
+        return positive_sign_ ? positive_sign_ : string_type ();
+    }
+
+    virtual string_type do_negative_sign () const {
+        return negative_sign_ ? negative_sign_ : string_type ();
+    }
+
+    virtual std::money_base::pattern do_pos_format () const {
+        return pos_format_;
+    }
+
+    virtual std::money_base::pattern do_neg_format () const {
+        return neg_format_;
+    }
+};
+
+template <class charT, bool Intl>
+const char*
+Punct<charT, Intl>::grouping_ = "";
+
+template <class charT, bool Intl>
+typename Punct<charT, Intl>::char_type
+Punct<charT, Intl>::decimal_point_ = ':';
+
+template <class charT, bool Intl>
+typename Punct<charT, Intl>::char_type
+Punct<charT, Intl>::thousands_sep_ = ';';
+
+template <class charT, bool Intl>
+const typename Punct<charT, Intl>::char_type*
+Punct<charT, Intl>::curr_symbol_;
+
+template <class charT, bool Intl>
+const typename Punct<charT, Intl>::char_type*
+Punct<charT, Intl>::positive_sign_;
+
+template <class charT, bool Intl>
+const typename Punct<charT, Intl>::char_type*
+Punct<charT, Intl>::negative_sign_;
+
+template <class charT, bool Intl>
+std::money_base::pattern
+Punct<charT, Intl>::pos_format_ = { {
+    std::money_base::symbol,
+    std::money_base::sign,
+    std::money_base::none,
+    std::money_base::value
+} };
+
+template <class charT, bool Intl>
+std::money_base::pattern
+Punct<charT, Intl>::neg_format_ = { {
+    std::money_base::symbol,
+    std::money_base::sign,
+    std::money_base::none,
+    std::money_base::value
+} };
+
+template <class charT, bool Intl>
+int
+Punct<charT, Intl>::n_thousands_sep_;
+
+template <class charT, bool Intl>
+int
+Punct<charT, Intl>::frac_digits_;
+
+/**************************************************************************/
+
+template <class charT>
+struct Ios: std::basic_ios<charT>
+{
+    Ios () { this->init (0); }
+};
+
+template <class charT>
+struct MoneyPut: std::money_put<charT, charT*> { };
+
+/**************************************************************************/
+
+bool test_neg_zero;
+
+/**************************************************************************/
+
+std::money_base::pattern
+set_pattern (const char *format)
+{
+    std::money_base::pattern pat;
+
+    for (unsigned i = 0; i != sizeof pat.field / sizeof *pat.field; ++i) {
+        switch (format [i]) {
+        case '\0': case '@': pat.field [i] = std::money_base::none; break;
+        case '\1': case ' ': pat.field [i] = std::money_base::space; break;
+        case '\2': case '$': pat.field [i] = std::money_base::symbol; break;
+        case '\3': case '-': pat.field [i] = std::money_base::sign; break;
+        case '\4': case '1': pat.field [i] = std::money_base::value; break;
+        default:
+            _RWSTD_ASSERT (!!"bad format specifier");
+        }
+    }
+
+    return pat;
+}
+
+
+template <class charT>
+int type_test (int         lineno,
+               charT       /* unused */,
+               long double val /* value to format */,
+               const char *str /* expected result */,
+               char        fill        = ' ',
+               int         flags       = 0,
+               int         frac_digits = 0,
+               int         width       = 0,
+               const char *format      = 0 /* pattern or printf() format */,
+               const char *grouping    = 0)
+{
+    if (!rw_enabled (lineno)) {
+        rw_note (0, __FILE__, __LINE__, "test on line %d disabled", lineno);
+        return 0;
+    }
+
+    static const char* const cname = 1 < sizeof (charT) ? "wchar_t" : "char";
+
+    static int i = 0;   // assertion number per specialization of type_test()
+
+    if (!i) {
+        rw_info (0, 0, 0, "std::money_put<%s>::put(ostreambuf_iterator"
+                 "<%s>, bool, ios_base, %s, long double)",
+                 cname, cname, cname);
+
+        rw_info (0, 0, 0, "std::money_put<%s>::put(ostreambuf_iterator"
+                 "<%s>, bool, ios_base, %s, "
+                 "const basic_string<%s>&))",
+                 cname, cname, cname, cname);
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise put (..., long double) overload
+
+    int nfail = 0;   // number of failed assertions
+
+    // unless 0, or unless it starts with '%', the `format' argument
+    // is treated as a money_base::pattern string; otherwise the
+    // default pattern is used
+
+    // default format as in locale ("C")
+    const char *fmt_pat = !format || *format == '%' ? "\2\3\4\0" : format;
+
+    if (!grouping) {
+        // default grouping as in locale ("C")
+        grouping = "";
+    }
+
+    const Punct<charT, false> pun;
+
+    // take care to initialize Punct static data before installing
+    // the facet in case locale or the base facet calls the overridden
+    // virtuals early to cache the results
+    pun.grouping_    = grouping;
+    pun.frac_digits_ = frac_digits;
+
+    if (val < 0.0) {
+        pun.neg_format_ = set_pattern (fmt_pat);
+        pun.pos_format_ = std::money_base::pattern ();
+    }
+    else if (val > 0.0) {
+        pun.neg_format_ = std::money_base::pattern ();
+        pun.pos_format_ = set_pattern (fmt_pat);
+    }
+    else {
+        // 0.0 and -0.0
+        pun.neg_format_ = set_pattern (fmt_pat);
+        pun.pos_format_ = pun.neg_format_;
+    }
+
+    // ios-derived object to pass to the facet
+    Ios<charT> ios;
+
+    // money_put-derived object
+    const MoneyPut<charT> mp;
+
+    // install the moneypunct facet in a locale and imbue the latter
+    // in the ios-derived object used by money_put
+    std::locale loc (ios.getloc (), (const std::moneypunct<charT>*)&pun);
+    ios.imbue (loc);
+
+    // set the formatting flags and the width
+    ios.flags (std::ios_base::fmtflags (flags));
+    ios.width (std::streamsize (width));
+
+    bool success;
+
+    charT buf [256] = { 0 };
+
+    if (rw_enabled ("long double")) {
+
+        // exercise 22.2.6.2.1, long double overload
+        *mp.put (buf, false, ios, charT (fill), val) = charT ();
+
+        rw_assert (0 == ios.width (), __FILE__, lineno,
+                   "money_put<%s>::put (%#p, false, const ios_base&, "
+                   "%{#c}, %LfL) reset width from %d",
+                   cname, buf, fill, val, width);
+
+        success = 0 == rw_strncmp (buf, str);
+
+        if (!success)
+            ++nfail;
+
+        rw_assert (success, __FILE__, lineno,
+                   "money_put<%s>::put (%#p, false, "
+                   "const ios_base&, %{#c}, %LfL) == %{#s} got %{#s}; "
+                   "flags = %{If}, grouping = %{#s}",
+                   cname, buf,
+                   fill, val, str, buf,
+                   flags, grouping);
+    }
+    else {
+        static int msg_issued;
+
+        rw_note (msg_issued++, __FILE__, 0, "long double test disabled");
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise put (..., const basic_string&) overload
+
+    if (frac_digits < 0) {
+        // do not perform string test(s) for negative values of frac_digits
+        // (extension implemented only for the long double overload of put())
+        ++i;
+        return nfail;
+    }
+
+    if (no_basic_string) {
+        rw_note (0, __FILE__, __LINE__,
+                 "basic_string<%s> test on line %d disabled", lineno, cname);
+        return nfail;
+    }
+
+    // zero out buffer
+    std::char_traits<charT>::assign (buf, sizeof buf / sizeof *buf, charT ());
+
+    // if the format string starts with a '%',
+    // use it to format the floating point value
+    if (!format || *format != '%')
+        format = "%.0" _RWSTD_LDBL_PRINTF_PREFIX "f";
+
+    char valbuf [256] = "";
+    const std::size_t valbuflen = sprintf (valbuf, format, val);
+
+    typedef std::char_traits<charT> Traits;
+    typedef std::allocator<charT>   Allocator;
+
+    const std::basic_string<charT, Traits, Allocator>
+        valstr (valbuf, valbuf + valbuflen);
+
+    // set width (reset by a previous call)
+    ios.width (std::streamsize (width));
+
+    // exercise 22.2.6.2.1, basic_string overload
+    *mp.put (buf, false, ios, charT (fill), valstr) = charT ();
+    
+    success = 0 == rw_strncmp (buf, str);
+
+    if (!success)
+        ++nfail;
+
+    rw_assert (success, __FILE__, lineno,
+               "money_put<%s>::put (%#p, false, "
+               "const ios_base&, %{#S}) == %{#s} got %{#s}; "
+               "flags = %{If}, grouping = %{#s}",
+               cname, fill, &valstr, buf, str,
+               flags, grouping);
+
+    ++i;
+
+    return nfail;
+}
+
+/**************************************************************************/
+
+// 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
+
+#define Eofbit      std::ios_base::eofbit
+#define Failbit     std::ios_base::failbit
+#define Goodbit     std::ios_base::goodbit
+
+
+template <class charT>
+void ldbl_test (charT)
+{
+    static const charT curr_symbol1 [8] = { '$', '\0' };
+    Punct<charT, false>::curr_symbol_   = curr_symbol1;
+
+    Punct<charT, false>::decimal_point_ = ':';
+    Punct<charT, false>::thousands_sep_ = ';';
+
+    static const charT signs1[][4] = {
+        // negative            positive
+        { '~', '\0' }, { '\0', },
+    };
+
+    Punct<charT, false>::negative_sign_ = signs1 [0];
+    Punct<charT, false>::positive_sign_ = signs1 [1];
+
+    int ntried  = 0;
+    int nfailed = 0;
+
+#define T      __LINE__, charT ()
+#define TEST   ++ntried, nfailed += type_test
+
+    // enum part { none, space, symbol, sign, value };
+
+    // no symbol, empty sign, default format
+    TEST (T,         0.,         "0", ' ');
+    TEST (T,         1.,         "1", ' ');
+    TEST (T,        12.,        "12", ' ');
+    TEST (T,       123.,       "123", ' ');
+    TEST (T,      1234.,      "1234", ' ');
+    TEST (T,     12345.,     "12345", ' ');
+    TEST (T,    123456.,    "123456", ' ');
+    TEST (T,   1234567.,   "1234567", ' ');
+    TEST (T,  12345678.,  "12345678", ' ');
+    TEST (T, 123456789., "123456789", ' ');
+
+    TEST (T, 12345678.9,  "12345679", ' ');
+    TEST (T, 1234567.89,   "1234568", ' ');
+    TEST (T, 123456.789,    "123457", ' ');
+    TEST (T, 12345.6789,     "12346", ' ');
+    TEST (T, 1234.56789,      "1235", ' ');
+    TEST (T, 123.456789,       "123", ' ');
+    TEST (T, 12.3456789,        "12", ' ');
+    TEST (T, 1.23456789,         "1", ' ');
+    TEST (T, .123456789,         "0", ' ');
+
+    // exercise correct handling of frac_digits
+    TEST (T, 9876543210.,  "987654321:0", ' ', 0, 1);
+    TEST (T,  876543210.,   "8765432:10", ' ', 0, 2);
+    TEST (T,   76543210.,    "76543:210", ' ', 0, 3);
+    TEST (T,    6543210.,     "654:3210", ' ', 0, 4);
+    TEST (T,     543210.,      "5:43210", ' ', 0, 5);
+    TEST (T,      43210.,     "0:043210", ' ', 0, 6);
+    TEST (T,       3210.,    "0:0003210", ' ', 0, 7);
+    TEST (T,        210.,   "0:00000210", ' ', 0, 8);
+    TEST (T,         10.,  "0:000000010", ' ', 0, 9);
+    TEST (T,          1.,  "0:000000001", ' ', 0, 9);
+    TEST (T,          0.,  "0:000000000", ' ', 0, 9);
+    TEST (T,        200.,  "0:000000200", ' ', 0, 9);
+    TEST (T,       3000.,  "0:000003000", ' ', 0, 9);
+    TEST (T,      40000.,  "0:000040000", ' ', 0, 9);
+    TEST (T,     500000.,  "0:000500000", ' ', 0, 9);
+    TEST (T,    6000000.,  "0:006000000", ' ', 0, 9);
+    TEST (T,   70000000.,  "0:070000000", ' ', 0, 9);
+    TEST (T,  800000000.,  "0:800000000", ' ', 0, 9);
+    TEST (T, -900000000., "~0:900000000", ' ', 0, 9);
+    TEST (T,  -80000000., "~0:080000000", ' ', 0, 9);
+    TEST (T,   -7000000., "~0:007000000", ' ', 0, 9);
+    TEST (T,    -600000., "~0:000600000", ' ', 0, 9);
+    TEST (T,     -50000., "~0:000050000", ' ', 0, 9);
+    TEST (T,      -4000., "~0:000004000", ' ', 0, 9);
+    TEST (T,       -300., "~0:000000300", ' ', 0, 9);
+    TEST (T,        -20., "~0:000000020", ' ', 0, 9);
+    TEST (T,         -1., "~0:000000001", ' ', 0, 9);
+
+    if (test_neg_zero)
+        TEST (T, -0., "~0:000000000", ' ', 0, 9);
+
+    // extension: fixed and negative frac_digits
+    TEST (T,   1.0,       "1:0",      ' ', Fixed, -1);
+    TEST (T,   2.0,       "2:00",     ' ', Fixed, -2);
+    TEST (T,   3.0,       "3:000",    ' ', Fixed, -3);
+    TEST (T,   4.1,       "4:1000",   ' ', Fixed, -4);
+    TEST (T,  52.34,     "52:34000",  ' ', Fixed, -5);
+    TEST (T, 634.56789, "634:5679",   ' ', Fixed, -4);
+
+
+    // exhaustively exercise valid permutations of format patterns
+    // (`none' allowed in all but the first position by 22.2.6.3, p1)
+    TEST (T,   12,   "12", '\0', 0, 0, 0, "\3\0\4\2", "");
+    TEST (T,  123,  "123", '\0', 0, 0, 0, "\3\0\2\4", "");
+    TEST (T, 1234, "1234", '\0', 0, 0, 0, "\3\2\4\0", "");
+    TEST (T, 2345, "2345", '\0', 0, 0, 0, "\3\4\2\0", "");
+    TEST (T, 3456, "3456", '\0', 0, 0, 0, "\3\4\0\2", "");
+    TEST (T, 4567, "4567", '\0', 0, 0, 0, "\4\0\2\3", "");
+    TEST (T, 5678, "5678", '\0', 0, 0, 0, "\4\2\0\3", "");
+    TEST (T, 6789, "6789", '\0', 0, 0, 0, "\4\2\3\0", "");
+    TEST (T, 7890, "7890", '\0', 0, 0, 0, "\4\0\3\2", "");
+    TEST (T, 8901, "8901", '\0', 0, 0, 0, "\2\4\0\3", "");
+    TEST (T, 9012, "9012", '\0', 0, 0, 0, "\2\0\4\3", "");
+    TEST (T,  123,  "123", '\0', 0, 0, 0, "\2\0\3\4", "");
+
+    // format using `space' in valid positions (all but
+    // the first and last as specified by 22.2.6.3, p1)
+    // the actual space character (not the fill char)
+    // is required
+    TEST (T,   9,   " 9", '*', 0, 0, 0, "\3\1\4\2", "");
+    TEST (T,  98,  " 98", '*', 0, 0, 0, "\3\1\2\4", "");
+    TEST (T, 987, "987 ", '*', 0, 0, 0, "\3\4\1\2", "");
+    TEST (T, 876, "876 ", '*', 0, 0, 0, "\4\1\2\3", "");
+    TEST (T, 765, "765 ", '*', 0, 0, 0, "\4\2\1\3", "");
+    TEST (T, 654, "654 ", '*', 0, 0, 0, "\4\1\3\2", "");
+    TEST (T, 543, "543 ", '*', 0, 0, 0, "\2\4\1\3", "");
+    TEST (T, 432, " 432", '*', 0, 0, 0, "\2\1\4\3", "");
+    TEST (T, 321, " 321", '*', 0, 0, 0, "\2\1\3\4", "");
+
+    TEST (T,        0,        "$0", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,        1,        "$1", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,       12,       "$12", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,      123,      "$123", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,     1234,     "$1234", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,    12345,    "$12345", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,   123456,   "$123456", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T,  1234567,  "$1234567", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+    TEST (T, 12345678, "$12345678", '\0', Showbase, 0, 0, "\2\3\4\0", "");
+
+    TEST (T,         0,             "$0", '\0', Showbase, 0, 0, 0, "\2");
+    TEST (T,         1,             "$1", '\0', Showbase, 0, 0, 0, "\2\2");
+    TEST (T,        12,            "$12", '\0', Showbase, 0, 0, 0, "\2");
+    TEST (T,       123,          "$1;23", '\0', Showbase, 0, 0, 0, "\2\2");
+    TEST (T,      1234,         "$12;34", '\0', Showbase, 0, 0, 0, "\2");
+    TEST (T,     12345,       "$1;23;45", '\0', Showbase, 0, 0, 0, "\2\2");
+    TEST (T,    123456,      "$12;34;56", '\0', Showbase, 0, 0, 0, "\2");
+    TEST (T,   1234567,    "$1;23;45;67", '\0', Showbase, 0, 0, 0, "\2\2");
+    TEST (T,  12345678,   "$12;34;56;78", '\0', Showbase, 0, 0, 0, "\2");
+    TEST (T, 123456789, "$1;23;45;67;89", '\0', Showbase, 0, 0, 0, "\2\2");
+
+    if (test_neg_zero)
+        TEST (T, -0.0, "$~0", '\0', Showbase, 0, 0, 0, "\3\3");
+
+    TEST (T,         -1,           "$~1", '\0', Showbase, 0, 0, 0, "\3");
+    TEST (T,        -12,          "$~12", '\0', Showbase, 0, 0, 0, "\3\3");
+    TEST (T,       -123,         "$~123", '\0', Showbase, 0, 0, 0, "\3");
+    TEST (T,      -1234,       "$~1;234", '\0', Showbase, 0, 0, 0, "\3\3");
+    TEST (T,     -12345,      "$~12;345", '\0', Showbase, 0, 0, 0, "\3");
+    TEST (T,    -123456,     "$~123;456", '\0', Showbase, 0, 0, 0, "\3\3");
+    TEST (T,   -1234567,   "$~1;234;567", '\0', Showbase, 0, 0, 0, "\3");
+    TEST (T,  -12345678,  "$~12;345;678", '\0', Showbase, 0, 0, 0, "\3\3");
+    TEST (T, -123456789, "$~123;456;789", '\0', Showbase, 0, 0, 0, "\3");
+
+    // for convenience
+    const char *f = "\3\2\4\0";   // { sign, symbol, value, none }
+
+    TEST (T,       -321,           "~$32;1", '\0', Showbase, 0, 0, f, "\1\2");
+    TEST (T,      -4322,          "~$432;2", '\0', Showbase, 0, 0, f, "\1\3");
+    TEST (T,     -54323,      "~$5;4;3;2;3", '\0', Showbase, 0, 0, f, "\1\1");
+    TEST (T,    -654324,    "~$6;5;4;3;2;4", '\0', Showbase, 0, 0, f, "\1\1");
+    TEST (T,   -7654325,      "~$765;432;5", '\0', Showbase, 0, 0, f, "\1\3");
+    TEST (T,  -87654326, "~$8;7;6;5;4;3;26", '\0', Showbase, 0, 0, f, "\2\1");
+    TEST (T, -987654327,  "~$98;76;54;32;7", '\0', Showbase, 0, 0, f, "\1\2");
+
+    static const charT curr_symbol2 [8] = { 'X', 'Y', '\0' };
+    Punct<charT, false>::curr_symbol_   = curr_symbol2;
+
+    static const charT signs2[][8] = {
+        // negative            positive
+        { '(', ')', '\0' }, { '{', '}', '\0' }
+    };
+
+    Punct<charT, false>::negative_sign_ = signs2 [0];
+    Punct<charT, false>::positive_sign_ = signs2 [1];
+    Punct<charT, false>::thousands_sep_ = '.';
+    Punct<charT, false>::decimal_point_ = '.';
+
+    f = "\3\4\1\2";   // { sign, value, space, symbol }
+
+    TEST (T, -1357911, "(1.3.5.7.9.1.1 XY)", '*', Showbase, 0, 0, f, "\1");
+    TEST (T, -2468012,    "(2.46.80.12 XY)", '-', Showbase, 0, 0, f, "\2");
+    TEST (T, -3692513,     "(3.692.513 XY)", ' ', Showbase, 0, 0, f, "\3");
+    TEST (T, -9999914,      "(999.9914 XY)", '@', Showbase, 0, 0, f, "\4");
+    TEST (T, -1000015,      "(10.00015 XY)", '#', Showbase, 0, 0, f, "\5");
+    TEST (T,      -16,            "(16 XY)", ')', Showbase, 0, 0, f, "\6");
+
+    TEST (T, +1357917, "{1.3.5.7.9.1.7 XY}", ',',  Showbase, 0, 0, f, "\1");
+    TEST (T, +2468018,    "{2.46.80.18 XY}", '+',  Showbase, 0, 0, f, "\2");
+    TEST (T, +3692519,     "{3.692.519 XY}", '0',  Showbase, 0, 0, f, "\3");
+    TEST (T, +9999920,      "{999.9920 XY}", '1',  Showbase, 0, 0, f, "\4");
+    TEST (T, +1000021,      "{10.00021 XY}", '\0', Showbase, 0, 0, f, "\5");
+    TEST (T,      +22,            "{22 XY}", '{',  Showbase, 0, 0, f, "\6");
+    TEST (T,     +123,             "{123 }", '_',  0,        0, 0, f, "\6");
+    TEST (T,     -224,             "(224 )", '_',  0,        0, 0, f, "\7");
+
+    TEST (T,  +325,  "{ XY325}", ' ', Showbase, 0, 0, "\3\1\2\4", "\xa");
+    TEST (T,  -426,  "( XY426)", ' ', Showbase, 0, 0, "\3\1\2\4", "\xb");
+    TEST (T,  +527,  "{XY 527}", ' ', Showbase, 0, 0, "\3\2\1\4", "\xc");
+    TEST (T,  -628,  "(XY 628)", ' ', Showbase, 0, 0, "\3\2\1\4", "\xd");
+    TEST (T,  +729,   "{XY729}", ' ', Showbase, 0, 0, "\3\2\0\4", "\xe");
+    TEST (T,  -830,   "(XY830)", ' ', Showbase, 0, 0, "\3\2\0\4", "\xf");
+    TEST (T,  +931,   "{XY931}", ' ', Showbase, 0, 0, "\3\0\2\4", "\x10");
+    TEST (T, -1032,  "(XY1032)", ' ', Showbase, 0, 0, "\3\0\2\4");
+    TEST (T, +1133,  "1133{XY}", ' ', Showbase, 0, 0, "\4\3\2\0");
+    TEST (T, -1234,  "1234XY()", ' ', Showbase, 0, 0, "\4\2\3\0");
+    TEST (T, +1335,  "1335XY{}", ' ', Showbase, 0, 0, "\4\2\0\3");
+    TEST (T, -1436, "1436XY ()", ' ', Showbase, 0, 0, "\4\2\1\3");
+    TEST (T, +1537,  "1537XY{}", ' ', Showbase, 0, 0, "\4\0\2\3");
+    TEST (T, -1638, "1638 XY()", ' ', Showbase, 0, 0, "\4\1\2\3");
+    TEST (T, +1739,  "XY1739{}", ' ', Showbase, 0, 0, "\2\4\0\3");
+    TEST (T, -1840, "XY1840 ()", ' ', Showbase, 0, 0, "\2\4\1\3");
+    TEST (T, +1941,  "XY1941{}", ' ', Showbase, 0, 0, "\2\0\4\3");
+    TEST (T, -2042, "XY 2042()", ' ', Showbase, 0, 0, "\2\1\4\3");
+    TEST (T, +2143,  "XY{2143}", ' ', Showbase, 0, 0, "\2\3\4\0");
+    TEST (T, -2244,  "XY(2244)", ' ', Showbase, 0, 0, "\2\3\0\4");
+    TEST (T, +2345, "XY{ 2345}", ' ', Showbase, 0, 0, "\2\3\1\4");
+
+    // 22.2.6.2, p2:
+    //   ...copies of `fill' are inserted as necessary to pad to the
+    //   specified width. For the value `af' equal to (str.flags()
+    //   & str.adjustfield), if (af == str.internal) is true, the fill
+    //   characters are placed where `none' or `space' appears in the
+    //   formatting pattern; otherwise if (af == str.left) is true, they
+    //   are placed after the other characters; otherwise, they are
+    //   placed before the other characters.
+
+    TEST (T, -2446, "___XY( 2446)", '_', Showbase, 0, 12, "\2\3\1\4");
+    TEST (T, +2547, "____XY{2547}", '_', Showbase, 0, 12, "\2\3\0\4");
+
+    TEST (T, -2648, "___XY( 2648)", '_', Showbase | Right, 0, 12, "\2\3\1\4");
+    TEST (T, +2749, "____XY{2749}", '_', Showbase | Right, 0, 12, "\2\3\0\4");
+
+    TEST (T, -2850, "XY( 2850)___", '_', Showbase | Left, 0, 12, "\2\3\1\4");
+    TEST (T, +2951, "XY{2951}____", '_', Showbase | Left, 0, 12, "\2\3\0\4");
+
+    TEST (T, -3052, "___XY( 3052)", '_',
+          Showbase | Left | Right, 0, 12, "\2\3\1\4");
+
+    TEST (T, +3153, "____XY{3153}", '_',
+          Showbase | Left | Right, 0, 12, "\2\3\0\4");
+
+    TEST (T, -3254, "___XY( 3254)", '_',
+          Showbase | Left | Right | Internal, 0, 12, "\2\3\1\4");
+
+    TEST (T, +3355, "____XY{3355}", '_',
+          Showbase | Left | Right | Internal, 0, 12, "\2\3\0\4");
+
+    TEST (T, -3456, "XY( ___3456)", '_',
+          Showbase | Internal, 0, 12, "\2\3\1\4");
+
+    TEST (T, +3557, "XY{____3557}", '_',
+          Showbase | Internal, 0, 12, "\2\3\0\4");
+
+    TEST (T, -3658, "XY____(3658)", '_',
+          Showbase | Internal, 0, 12, "\2\0\3\4");
+
+    TEST (T, +3759, "XY{3759____}", '_',
+          Showbase | Internal, 0, 12, "\2\3\4\0");
+
+    TEST (T, 3759, "XY{37.59}", '_',
+          Showbase | Internal, 0, 8, "\2\3\4\0", "\2");
+
+    TEST (T, 3760, "XY{ 37.60}", '_',
+          Showbase | Internal, 0, 8, "\2\3\1\4", "\2");
+
+    TEST (T, 12345678900000000000.0, "XY{ ........1.23.45678.9000.00.000.0.00}",
+          '.', Showbase | Internal, 0, 40, "\2\3\1\4", "\2\1\3\2\4\5\2");
+
+    TEST (T, 1234567890000000000.0, "{ ...........1234.56789.0000.000.00.0XY}",
+          '.', Showbase | Internal, 0, 40, "\3\1\4\2", "\1\2\3\4\5\6");
+
+    // exercise justification with non-zero frac_digits
+    TEST (T,    1,  "_____{0.1}", '_', 0,        1, 10, "-@1$");
+    TEST (T,   12,  "_____{1.2}", '_', 0,        1, 10, "-@1$");
+    TEST (T,  123,  "____{1.23}", '_', 0,        2, 10, "-@1$");
+    TEST (T, 1234,  "_{12.34XY}", '_', Showbase, 2, 10, "-@1$");
+    TEST (T, 1235, "_{ 12.35XY}", '_', Showbase, 2, 11, "- 1$");
+
+    TEST (T,    2,  "******{0.2}", '*', Right,            1, 11, "-@1$");
+    TEST (T,   23,  "******{2.3}", '*', Right,            1, 11, "-@1$");
+    TEST (T,  234,  "*****{2.34}", '*', Right,            2, 11, "-@1$");
+    TEST (T, 2345,  "**{23.45XY}", '*', Right | Showbase, 2, 11, "-@1$");
+    TEST (T, 2346, "**{ 23.46XY}", '*', Right | Showbase, 2, 12, "- 1$");
+
+    TEST (T,    3,  "{0.3}#######", '#', Left,             1, 12, "-@1$");
+    TEST (T,   34,  "{3.4}#######", '#', Left,             1, 12, "-@1$");
+    TEST (T,  345,  "{3.45}######", '#', Left,             2, 12, "-@1$");
+    TEST (T, 3456,  "{34.56XY}###", '#', Left | Showbase,  2, 12, "-@1$");
+    TEST (T, 3457, "{ 34.57XY}###", '#', Left | Showbase,  2, 13, "- 1$");
+
+    TEST (T,    4,  "{=====0.4}", '=', Internal,            1, 10, "-@1$");
+    TEST (T,   45,  "{=====4.5}", '=', Internal,            1, 10, "-@1$");
+    TEST (T,  456,  "{====4.56}", '=', Internal,            2, 10, "-@1$");
+    TEST (T, 4567,  "{=45.67XY}", '=', Internal | Showbase, 2, 10, "-@1$");
+    TEST (T, 4568, "{ =45.68XY}", '=', Internal | Showbase, 2, 11, "- 1$");
+
+    Punct<charT, false>::thousands_sep_ = ',';
+    Punct<charT, false>::decimal_point_ = '.';
+
+    // justification with grouping
+    TEST (T,    105,   "====={1,0.5}", '=', 0,        1, 12, "-@1$", "\1");
+    TEST (T,   1056,   "===={1,05.6}", '=', 0,        1, 12, "-@1$", "\2");
+    TEST (T,  10567,   "==={1,05.67}", '=', 0,        2, 12, "-@1$", "\2");
+    TEST (T, 105678, "=={10,56.78XY}", '=', Showbase, 2, 14, "-@1$", "\2");
+    TEST (T, 105679, "={ 10,56.79XY}", '=', Showbase, 2, 14, "- 1$", "\2");
+    TEST (T, 105680, "={ 1,056,80XY}", '=', Showbase, 0, 14, "- 1$", "\2\3");
+
+    int flags = Right | Showbase;
+    TEST (T,    106,   ">>>>>{1,0.6}", '>', Right, 1, 12, "-@1$", "\1");
+    TEST (T,   1057,   ">>>>{1,05.7}", '>', Right, 1, 12, "-@1$", "\2");
+    TEST (T,  10568,   ">>>{1,05.68}", '>', Right, 2, 12, "-@1$", "\2");
+    TEST (T, 105679, ">>{10,56.79XY}", '>', flags, 2, 14, "-@1$", "\2");
+    TEST (T, 105680, ">{ 10,56.80XY}", '>', flags, 2, 14, "- 1$", "\2");
+    TEST (T, 105681, ">{ 1,056,81XY}", '>', flags, 0, 14, "- 1$", "\2\3");
+
+    flags = Left | Showbase;
+    TEST (T,    107,   "{1,0.7}<<<<<", '<', Left,  1, 12, "-@1$", "\1");
+    TEST (T,   1058,   "{1,05.8}<<<<", '<', Left,  1, 12, "-@1$", "\2");
+    TEST (T,  10569,   "{1,05.69}<<<", '<', Left,  2, 12, "-@1$", "\2");
+    TEST (T, 105680, "{10,56.80XY}<<", '<', flags, 2, 14, "-@1$", "\2");
+    TEST (T, 105681, "{ 10,56.81XY}<", '<', flags, 2, 14, "- 1$", "\2");
+    TEST (T, 105682, "{ 1,056,82XY}<", '<', flags, 0, 14, "- 1$", "\2\3");
+
+    flags = Internal | Showbase;
+    TEST (T,    108,   "{^^^^^1,0.8}", '^', Internal, 1, 12, "-@1$", "\1");
+    TEST (T,   1059,   "{^^^^1,05.9}", '^', Internal, 1, 12, "-@1$", "\2");
+    TEST (T,  10570,   "{^^^1,05.70}", '^', Internal, 2, 12, "-@1$", "\2");
+    TEST (T, 105681, "{^^10,56.81XY}", '^', flags,    2, 14, "-@1$", "\2");
+    TEST (T, 105682, "{ ^10,56.82XY}", '^', flags,    2, 14, "- 1$", "\2");
+    TEST (T, 105683, "{ ^1,056,83XY}", '^', flags,    0, 14, "- 1$", "\2\3");
+
+    flags = Left | Right | Showbase;
+    TEST (T,    109,   "#####{1,0.9}", '#', Left | Right, 1, 12, "-@1$", "\1");
+    TEST (T,   1060,   "####{1,06.0}", '#', Left | Right, 1, 12, "-@1$", "\2");
+    TEST (T,  10571,   "###{1,05.71}", '#', Left | Right, 2, 12, "-@1$", "\2");
+    TEST (T, 105682, "##{10,56.82XY}", '#', flags,        2, 14, "-@1$", "\2");
+    TEST (T, 105683, "#{ 10,56.83XY}", '#', flags,        2, 14, "- 1$", "\2");
+    TEST (T, 105684, "#{ 10,56,84XY}", '#', flags,        0, 14, "- 1$", "\2");
+
+
+    // verify that mon_put (..., const basic_string&) ignores the part
+    // of the string starting with the first non-numeric character
+#undef FMT
+#define FMT(fmt) "%.0" _RWSTD_LDBL_PRINTF_PREFIX "f" fmt
+
+    // using default format "\2\3\4\0": {symbol, sign, value, none}
+    TEST (T,   10, "{1.0}", ' ', 0, 1, -1, FMT (" "));
+    TEST (T,   10, "{1.0}", ' ', 0, 1, -1, FMT ("."));
+
+    TEST (T,  -11, "(1.1)", ' ', 0, 1, -1, FMT (" "));
+    TEST (T,  -11, "(1.1)", ' ', 0, 1, -1, FMT ("."));
+
+    TEST (T,  101, "{1.01}", ' ', 0, 2, -1, FMT (" "));
+    TEST (T,  101, "{1.01}", ' ', 0, 2, -1, FMT ("."));
+
+    Punct<charT, false>::negative_sign_ = signs1 [0];
+    Punct<charT, false>::positive_sign_ = signs1 [1];
+
+    TEST (T,  1012, "1,0.12", ' ', 0, 2, -1, FMT (" 0"), "\1");
+    TEST (T,  1013, "1,0.13", ' ', 0, 2, -1, FMT (".1"), "\1");
+
+    TEST (T, -1014, "~1,01.4", ' ', 0, 1, -1, FMT ("~2"), "\2");
+    TEST (T, -1015, "~1,01.5", ' ', 0, 1, -1, FMT (",3"), "\2");
+}
+
+/**************************************************************************/
+
+void grouping_test ()
+{
+    if (!rw_enabled ("char")) {
+        rw_note (0, __FILE__, __LINE__, "char test disabled");
+        return;
+    }
+    
+    rw_info (0, 0, 0, "std::money_put<%s>::put(ostreambuf_iterator"
+             "<%s>, bool, ios_base, %s, long double); correct use of "
+             "moneypunct<%s, false>::grouping() and thousands_sep()",
+             "char", "char", "char", "char");
+
+    typedef Punct<char, false> PunctT;
+
+    // construct a "replacement" moneypunct-derived facet
+    const PunctT pun;
+
+    // group after every digit
+    PunctT::grouping_ = "\1";
+
+    // reset the do_thousands_sep()-call counter
+    PunctT::thousands_sep_   = ';';
+    PunctT::decimal_point_   = ':';
+    PunctT::n_thousands_sep_ = 0;
+
+    // construct and initialize a basic_ios-derived object
+    struct Ios: std::basic_ios<char> { Ios () { this->init (0); } } ios;
+
+    // construct a money_put-derived facet to exercise
+    struct MoneyPut: std::money_put<char, char*> { } mp;
+
+    // imbue a stream object with a custom locale
+    // containing the replacement punctuation facet
+    std::locale l;
+    std::locale loc (l, (const std::moneypunct<char>*)&pun);
+    ios.imbue (loc);
+
+    // decimal output, no special formatting
+    ios.setf (std::ios::fmtflags ());
+
+    char buf [40] = "";
+
+    *mp.put (buf, false, ios, '\0', 123456789.0L) = '\0';
+
+    // verify that the number was formatted correctly
+    rw_assert (0 == rw_strncmp (buf, "1;2;3;4;5;6;7;8;9"), __FILE__, __LINE__,
+               "money_put<char, char*>::do_put(..., 123456789.0L) "
+               "== %#s, got %#s", "1;2;3;4;5;6;7;8;9", buf);
+
+    // verify that do_thousands_sep() was called at least once
+    // (but not necessarily for each thousands separator inserted
+    // into the output, since the value is allowed to be cached)
+    rw_assert (0 != PunctT::n_thousands_sep_, __FILE__, __LINE__,
+               "money_put<char, char*>::do_put(..., 123456789.0L) "
+               "called moneypunct<char>::do_thousands_sep()");
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char*[])
+{
+    // check to see if we can test -0.0
+    static double d = -0.0;
+    test_neg_zero = 1.0 / d < d;
+    
+    if (no_grouping)
+        rw_note (0, __FILE__, __LINE__, "grouping test disabled");
+    else
+        grouping_test ();
+
+    if (rw_enabled ("char"))
+        ldbl_test (char ());
+    else
+        rw_note (0, __FILE__, __LINE__, "char test disabled");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    if (rw_enabled ("wchar_t"))
+        ldbl_test (wchar_t ());
+    else
+        rw_note (0, __FILE__, __LINE__, "wchar_t test disabled");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.locale.money.put",
+                    0 /* no comment */, run_test,
+                    "|-no-grouping# |-no-basic_string#",
+                    &no_grouping, &no_basic_string);
+}

Propchange: incubator/stdcxx/trunk/tests/localization/22.locale.money.put.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/stdcxx/trunk/tests/src/cmdopt.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/src/cmdopt.cpp?rev=278837&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/src/cmdopt.cpp (added)
+++ incubator/stdcxx/trunk/tests/src/cmdopt.cpp Mon Sep  5 13:57:44 2005
@@ -0,0 +1,1053 @@
+/***************************************************************************
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+#include <cmdopt.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef EINVAL
+#  define EINVAL   22   /* e.g., HP-UX, Linux, Solaris */
+#endif   // EINVAL
+
+/**************************************************************************/
+
+typedef int (optcallback_t)(int, char*[]);
+
+struct cmdopts_t
+{
+    char           loptbuf_ [32];   // buffer for long option name
+    optcallback_t *callback_;       // function to call to process option
+    int           *pcntr_;          // counter to increment for each occurrence
+
+    char          *lopt_;           // long option name
+    char           sopt_;           // short option name
+
+    size_t         maxcalls_;       // how many times option can be invoked
+    size_t         ncalls_;         // how many times it has been invoked
+
+    bool           arg_ : 1;        // option takes an argument?
+    bool           inv_ : 1;        // callback invocation inverted
+    bool           envseen_ : 1;    // environment option already processed
+
+};
+
+
+// total number of registered options
+static size_t ncmdopts;
+
+// number of default (always defined) options
+static size_t ndefopts;
+static cmdopts_t cmdoptbuf [32];
+static cmdopts_t *cmdopts = cmdoptbuf;
+static size_t optbufsize = sizeof cmdoptbuf / sizeof *cmdoptbuf;
+
+enum {
+    rw_bool, rw_char, rw_uchar, rw_schar, rw_ushrt, rw_shrt,
+    rw_uint, rw_int, rw_ulong, rw_long, rw_ullong, rw_llong,
+    rw_flt, rw_dbl, rw_ldbl, rw_wchar, rw_pvoid
+};
+
+static int rw_disabled_types = 0;
+static int rw_enabled_types  = 0;
+
+struct linerange_t {
+    int first;
+    int last;
+};
+
+static size_t nlineranges;
+static linerange_t *lineranges;
+static size_t rangebufsize;
+
+/**************************************************************************/
+
+static int
+rw_print_help (int argc, char *argv[])
+{
+    if (1 == argc && argv && 0 == argv [0]) {
+        static const char helpstr[] = {
+            "Without an argument, prints this help to stdout and exits with\n"
+            "a status of 0 without further processing.\n"
+            "With the optional argument prints help on the option with that\n"
+            "name, if one exists, and exits with a status of 0. If an option\n"
+            "with the specified name does not exist, prints an error message\n"
+            "to stderr and exits with a status of 1.\n"
+            "The leading underscores in the name of an option are optional.\n"
+        };
+
+        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
+
+        return 0;
+    }
+
+    // the option name to get help on, if any
+    const char* opthelp = 1 < argc ? argv [1] : 0;
+
+    // remove the optional one or two leading underscores
+    if (opthelp && '-' == opthelp [0] && opthelp [1])
+        opthelp += 1 + ('-' == opthelp [1]);
+
+    if (0 == opthelp)
+        printf ("OPTIONS\n");
+
+    // set to a non-zero when the specified option is found
+    int option_found = 0;
+
+    for (size_t i = 0; i != ncmdopts; ++i) {
+
+        if (opthelp && *opthelp) {
+
+            if (   cmdopts [i].sopt_ == opthelp [0] && '\0' == opthelp [1]
+                || cmdopts [i].lopt_
+                && 0 == strcmp (cmdopts [i].lopt_ + 1, opthelp)) {
+
+                // remember that we found the option whose (short
+                // or long) name we're to give help on; after printing
+                // the help text on the option keep looping in case
+                // there is another option and callback with the same
+                // name (unlikely but possible)
+                option_found = 1;
+            }
+            else {
+                // the option doesn't match, continue searching
+                continue;
+            }
+        }
+
+        printf ("     ");
+
+        if (cmdopts [i].sopt_) {
+            printf ("-%c", cmdopts [i].sopt_);
+
+            if (cmdopts [i].lopt_)
+                printf (" | ");
+        }
+
+        const char *pfx = "";
+        const char *sfx = pfx;
+
+        if (cmdopts [i].lopt_) {
+            printf ("-%s", cmdopts [i].lopt_);
+            if (   cmdopts [i].arg_
+                && '=' != cmdopts [i].lopt_ [strlen (cmdopts [i].lopt_) - 1]) {
+                pfx = " [ ";
+                sfx = " ]";
+            }
+        }
+
+        printf ("%s%s%s", pfx, cmdopts [i].arg_ ? "<arg>" : "", sfx);
+
+        if (_RWSTD_SIZE_MAX == cmdopts [i].maxcalls_)
+            printf (" (each occurrence evaluated)\n");
+        else if (1 < cmdopts [i].maxcalls_)
+            printf (" (at most %lu occurrences evaluated)\n",
+                    cmdopts [i].maxcalls_);
+        else
+            printf (" (only the first occurrence evaluated)\n");
+
+        // invoke callback with the "--help" option
+        if (cmdopts [i].callback_) {
+
+            char* help [2] = { 0, 0 };
+
+            cmdopts [i].callback_ (1, help);
+
+            for (const char *line = help [0]; line; ) {
+
+                const char* const nl = strchr (line, '\n');
+                const int len = nl ? int (nl - line) : int (strlen (line));
+
+                printf ("       %.*s\n", len, line);
+
+                line = nl;
+                if (nl)
+                    ++line;
+            }
+        }
+    }
+
+    if (opthelp && !option_found) {
+        fprintf (stderr, "Unknown option \"%s\".\n", opthelp);
+        exit (1);
+    }
+
+    exit (0);
+
+    return 0;
+}
+
+
+static int
+rw_set_ignenv (int argc, char *argv[])
+{
+    if (1 == argc && argv && 0 == argv [0]) {
+        static const char helpstr[] = {
+            "Prevents options specified in the RWSTD_TESTOPTS environment\n"
+            "variable from taking effect.\n"
+            "Unless this option is specified, the RWSTD_TESTOPTS environment\n"
+            "variable is processed as if its value were specified on the \n"
+            "command line.\n"
+            "For example, setting the value of the variable to the string\n"
+            "\"--verbose --no-wchar\" and invoking this program with no\n"
+            "command line arguments will have the same effect as invoking\n"
+            "it with the two arguments on the command line.\n"
+        };
+
+        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
+
+        return 0;
+    }
+
+    return 0;
+}
+
+static int rw_enable_type (int bit, bool enable)
+{
+    const int set_mask = 1 << bit;
+
+    if (enable)
+        rw_enabled_types |= set_mask;
+    else
+        rw_disabled_types |= set_mask;
+
+    return 0;
+}
+
+#define DEFINE_HANDLERS(T)                               \
+        static int rw_no_ ## T (int, char *[]) {         \
+            return rw_enable_type (rw_ ## T, false);     \
+        }                                                \
+        static int rw_en_ ## T (int, char *[]) {         \
+            return rw_enable_type (rw_ ## T, true);      \
+        }                                                \
+        typedef void unused_type /* allow a semicolon */
+
+
+DEFINE_HANDLERS (bool);
+DEFINE_HANDLERS (char);
+DEFINE_HANDLERS (schar);
+DEFINE_HANDLERS (uchar);
+DEFINE_HANDLERS (shrt);
+DEFINE_HANDLERS (ushrt);
+DEFINE_HANDLERS (int);
+DEFINE_HANDLERS (uint);
+DEFINE_HANDLERS (long);
+DEFINE_HANDLERS (ulong);
+DEFINE_HANDLERS (llong);
+DEFINE_HANDLERS (ullong);
+DEFINE_HANDLERS (flt);
+DEFINE_HANDLERS (dbl);
+DEFINE_HANDLERS (ldbl);
+DEFINE_HANDLERS (wchar);
+DEFINE_HANDLERS (pvoid);
+
+static int
+rw_enable_lines (int first, int last, bool enable)
+{
+    if (nlineranges == rangebufsize) {
+        const size_t newbufsize = 2 * nlineranges + 1;
+            
+        linerange_t* const newranges =
+            (linerange_t*)malloc (newbufsize * sizeof (linerange_t));
+
+        if (0 == newranges) {
+            abort ();
+        }
+
+        memcpy (newranges, lineranges, nlineranges * sizeof (linerange_t));
+
+        free (lineranges);
+
+        lineranges   = newranges;
+        rangebufsize = newbufsize;
+    }
+
+    if (enable) {
+        lineranges [nlineranges].first = first;
+        lineranges [nlineranges].last  = last;
+    }
+    else {
+        lineranges [nlineranges].first = -first;
+        lineranges [nlineranges].last  = -last;
+    }
+
+    ++nlineranges;
+
+    return 0;
+}
+
+
+static int
+rw_enable_line (int argc, char *argv[], bool enable)
+{
+    if (1 == argc && argv && 0 == argv [0]) {
+
+        static const char helpstr[] = {
+            "Enables or disables the lines specified by <arg>.\n"
+            "The syntax of <arg> is as follows: \n"
+            "<arg>   ::= <range> [ , <range> ]\n"
+            "<range> ::= [ - ] <number> | <number> - [ <number> ]\n"
+        };
+
+        argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
+
+        return 0;
+    }
+
+    char *parg = strchr (argv [0], '=');
+    assert (0 != parg);
+
+    const char* const argbeg = ++parg;
+
+    // the lower bound of a range of lines to be enabled or disabled
+    // negative values are not valid and denote an implicit lower bound
+    // of 1 (such as in "-3" which is a shorthand for "1-3")
+    long first = -1;
+
+    for ( ; '\0' != *parg ; ) {
+
+        printf ("%s (%ld)\n", parg, first);
+
+        // skip any leading whitespace
+        for ( ; ' ' == *parg; ++parg);
+
+        if ('-' == *parg) {
+            if (first < 0) {
+                first = 0;
+                ++parg;
+            }
+            else {
+                fprintf (stderr,
+                         "invalid character '%c' at position %d: \"%s\"\n",
+                         *parg, int (parg - argbeg), argv [0]);
+                return 2;
+            }
+        }
+
+        // parse a numeric argument
+        char *end;
+        long line = strtol (parg, &end, 0);
+
+        // skip any trailing whitespace
+        for ( ; ' ' == *end; ++end);
+
+        if (end == parg || '-' != *end && ',' != *end && '\0' != *end) {
+            fprintf (stderr,
+                     "invalid character '%c' at position %d: \"%s\"\n",
+                     *end, int (parg - argbeg), argv [0]);
+            return 2;
+        }
+
+        if (0 <= first) {
+            if (line < 0) {
+                fprintf (stderr,
+                         "invalid value %ld at position %d: \"%s\"\n",
+                         line, int (parg - argbeg), argv [0]);
+                return 2;
+            }
+
+            ++line;
+
+            if ((',' == *end || '-' == *end) && end [1])
+                ++end;
+        }
+        else if (',' == *end) {
+            first = line++;
+            if ('\0' == end [1]) {
+                fprintf (stderr,
+                         "invalid character '%c' at position %d: \"%s\"\n",
+                         *end, int (parg - argbeg), argv [0]);
+                return 2;
+            }
+
+            ++end;
+        }
+        else if ('-' == *end) {
+            first = line;
+            while (' ' == *++end);
+            if ('\0' == *end) {
+                line = _RWSTD_INT_MAX;
+            }
+            else if  (',' == *end) {
+                line = _RWSTD_INT_MAX;
+                ++end;
+            }
+            else
+                line = -1;
+        }
+        else if ('\0' == *end) {
+            first = line++;
+        }
+        else {
+            fprintf (stderr,
+                     "invalid character '%c' at position %d: \"%s\"\n",
+                     *end, int (parg - argbeg), argv [0]);
+            return 2;
+        }
+
+        parg = end;
+
+        if (0 <= first && first < line) {
+            printf ("  [%ld, %ld)\n", first, line);
+            rw_enable_lines (first, line, enable);
+            first = -1;
+        }
+    }
+
+    for (size_t i = 0; i != nlineranges; ++i) {
+        printf ("[%d, %d)\n", lineranges [i].first, lineranges [i].last);
+    }
+
+    return 0;
+}
+
+static int rw_en_line (int argc, char *argv[])
+{
+    return rw_enable_line (argc, argv, true);
+}
+
+static int rw_no_line (int argc, char *argv[])
+{
+    return rw_enable_line (argc, argv, false);
+}
+
+static void rw_set_myopts ()
+{
+    if (0 != ncmdopts)
+        return;
+
+    static bool recursive;
+
+    if (recursive)
+        return;
+
+    recursive = true;
+
+    rw_setopts ("|-help: "   // argument optional
+                "|-ignenv "
+                // options to disable fundamental types
+                "|-no-bool |-no-char |-no-schar |-no-uchar "
+                "|-no-shrt |-no-ushrt "
+                "|-no-int |-no-uint "
+                "|-no-long |-no-ulong "
+                "|-no-llong |-no-ullong "
+                "|-no-flt |-no-dbl |-no-ldbl "
+                "|-no-wchar |-no-pvoid "
+                // option to disable ranges of lines
+                "|-no-line= "
+                // options to enable fundamental types
+                "|-enable-bool |-enable-char |-enable-schar |-enable-uchar "
+                "|-enable-shrt |-enable-ushrt "
+                "|-enable-int |-enable-uint "
+                "|-enable-long |-enable-ulong "
+                "|-enable-llong |-enable-ullong "
+                "|-enable-flt |-enable-dbl |-enable-ldbl "
+                "|-enable-wchar |-enable-pvoid "
+                // option to enable ranges of lines
+                "|-enable-line= ",
+                //
+                rw_print_help,
+                rw_set_ignenv,
+                // handlers to disable fundamental types
+                rw_no_bool, rw_no_char, rw_no_schar, rw_no_uchar,
+                rw_no_shrt, rw_no_ushrt,
+                rw_no_int, rw_no_uint,
+                rw_no_long, rw_no_ulong,
+                rw_no_llong, rw_no_ullong,
+                rw_no_flt, rw_no_dbl, rw_no_ldbl,
+                rw_no_wchar, rw_no_pvoid,
+                rw_no_line,
+                // handlers to enable fundamental types
+                rw_en_bool, rw_en_char, rw_en_schar, rw_en_uchar,
+                rw_en_shrt, rw_en_ushrt,
+                rw_en_int, rw_en_uint,
+                rw_en_long, rw_en_ulong,
+                rw_en_llong, rw_en_ullong,
+                rw_en_flt, rw_en_dbl, rw_en_ldbl,
+                rw_en_wchar, rw_en_pvoid,
+                rw_en_line,
+                (optcallback_t*)0);
+
+    ndefopts = ncmdopts;
+
+    recursive = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// syntax of the option description string:
+//
+// opts ::= opt [ ':' | '=' | '#' ] [ @N | @* | '!' ] [ opts ]
+// opt  ::= <sopt> [ '|' <lopt>]
+//      ::= '|' <lopt>
+// sopt ::= char
+// lopt ::= char char*
+// char ::= any character other than a space (' '), bar ('|'),
+//          colon (':') and the equals sign ('=')
+
+_TEST_EXPORT int
+rw_vsetopts (const char *opts, va_list va)
+{
+    if (0 == opts) {
+
+        // reset to 0
+
+        for (size_t i = 0; i != ncmdopts; ++i) {
+            if (cmdopts [i].lopt_ != cmdopts [i].loptbuf_)
+                free (cmdopts [i].lopt_);
+        }
+
+        if (cmdopts != cmdoptbuf)
+            free (cmdopts);
+
+        cmdopts  = cmdoptbuf;
+        ncmdopts = 0;
+
+        return 0;
+    }
+
+    rw_set_myopts ();
+
+    const char *next = opts;
+
+    for ( ; ; ++ncmdopts) {
+
+        while (' ' == *next)
+            ++next;
+
+        if ('\0' == *next) {
+            break;
+        }
+
+        if (ncmdopts == optbufsize) {
+
+            const size_t newbufsize = 2 * ncmdopts + 1;
+            
+            cmdopts_t* const newopts =
+                (cmdopts_t*)malloc (newbufsize * sizeof (cmdopts_t));
+
+            if (0 == newopts) {
+                abort ();
+            }
+
+            memcpy (newopts, cmdopts, ncmdopts * sizeof (cmdopts_t));
+
+            if (cmdopts != cmdoptbuf)
+                free (cmdopts);
+
+            cmdopts    = newopts;
+            optbufsize = newbufsize;
+        }
+
+        memset (cmdopts + ncmdopts, 0, sizeof *cmdopts);
+
+        if ('|' != *next)
+            cmdopts [ncmdopts].sopt_ = *next++;
+
+        if ('|' == *next) {
+            const char* end = strpbrk (++next, "|@:=*!# ");
+            if (0 == end)
+                end = next + strlen (next);
+
+            // copy the option name up to but not including the delimiter
+            // (except when the delimiter is the equals sign ('='), which
+            // becomes the last character of the option name
+            const size_t optlen = size_t (end - next) + ('=' == *end);
+
+            if (optlen < sizeof cmdopts [ncmdopts].loptbuf_)
+                cmdopts [ncmdopts].lopt_ = cmdopts [ncmdopts].loptbuf_;
+            else
+                cmdopts [ncmdopts].lopt_ = (char*)malloc (optlen + 1);
+
+            memcpy (cmdopts [ncmdopts].lopt_, next, optlen);
+            cmdopts [ncmdopts].lopt_ [optlen] = '\0';
+
+            next = end;
+        }
+
+        // only the first occurrence of each command line option
+        // causes an invocation of the callback, all subsequent
+        // ones will be ignored by default
+        cmdopts [ncmdopts].maxcalls_ = 1;
+
+        bool arg_is_callback = true;
+
+        if (':' == *next || '=' == *next) {
+            // ':' : argument optional
+            // '=' : argument required
+            cmdopts [ncmdopts].arg_ = true;
+            ++next;
+        }
+        else if ('#' == *next) {
+            // insead of a pointer to a callback, the argument
+            // is a pointer to an int counter that is to be
+            // incremented for each occurrence of the option
+            // during processing
+            arg_is_callback = false;
+            ++next;
+            
+            // an unlimited number of occurrences of the option
+            // are allowed and will be counted
+            cmdopts [ncmdopts].maxcalls_ = _RWSTD_SIZE_MAX;
+        }
+
+        if ('@' == *next) {
+
+            ++next;
+
+            // at most how many occurrences of an option can be processed?
+            if ('*' == *next) {
+                // unlimited
+                cmdopts [ncmdopts].maxcalls_ = _RWSTD_SIZE_MAX;
+                ++next;
+            }
+            else {
+                // at most this many
+                char *end;
+                cmdopts [ncmdopts].maxcalls_ = strtoul (next, &end, 10);
+                next = end;
+            }
+        }
+        else if ('!' == *next) {
+            cmdopts [ncmdopts].inv_ = true;
+            ++next;
+        }
+
+        if (arg_is_callback) {
+            // retrieve the callback and verify it's not null
+            // (null callback is permitted in the special case when
+            // the short option is '-', i.e., when setting up or
+            // resetting an "unknown option" handler)
+            cmdopts [ncmdopts].callback_ = va_arg (va, optcallback_t*);
+        }
+        else {
+            // retrieve the address of the int counter where to keep
+            // track of the number of occurrences of the option
+            cmdopts [ncmdopts].pcntr_ = va_arg (va, int*);
+        }
+
+        if (   '-' != cmdopts [ncmdopts].sopt_
+            && 0 == cmdopts [ncmdopts].callback_
+            && 0 == cmdopts [ncmdopts].pcntr_) {
+
+            if (cmdopts [ncmdopts].lopt_)
+                fprintf (stderr, "null handler for option -%s\n",
+                         cmdopts [ncmdopts].lopt_);
+            else
+                fprintf (stderr, "null handler for option -%c\n",
+                         cmdopts [ncmdopts].sopt_);
+                
+            abort ();
+        }
+    }
+
+    return int (ncmdopts - ndefopts);
+}
+
+
+_TEST_EXPORT int
+rw_setopts (const char *opts, ...)
+{
+    va_list va;
+    va_start (va, opts);
+    const int result = rw_vsetopts (opts, va);
+    va_end (va);
+    return result;
+}
+
+
+_TEST_EXPORT int
+rw_runopts (int argc, char *argv[])
+{
+    rw_set_myopts ();
+
+    static bool recursive = false;
+
+    // ignore options set in the environment?
+    bool ignenv = recursive;
+
+    // return status
+    int status = 0;
+
+    // number of options processed
+    int nopts = 0;
+
+    // index of registered option whose callback should be invoked
+    // for command line options that do not match any other
+    size_t not_found_inx = _RWSTD_SIZE_MAX;
+
+    // iterate over the command line arguments until a callback
+    // returns a non-zero value or until all options have been
+    // successfully processed
+    for (int i = 0; i < argc && argv [i] && 0 == status; ++i) {
+
+        if (0 == strcmp ("--ignore-environment", argv [i])) {
+            // ignore options set in the environment
+            ignenv = true;
+            continue;
+        }
+
+        if (0 == strcmp ("--", argv [i])) {
+            // "--" terminates options, everything
+            // after it is treated as an argument
+            break;
+        }
+
+        bool found = false;
+
+        // look up each command line option (i.e., a string that starts
+        // with a dash ('-')) and invoke the callback associated with it
+        for (size_t j = 0; j != ncmdopts; ++j) {
+
+            if ('-' == cmdopts [j].sopt_)
+                not_found_inx = j;
+
+            if ('-' == argv [i][0]) {
+
+                // the name of the option without the leading dash
+                const char* const optname = argv [i] + 1;
+
+                // look for the first equals sign
+                const char* const eq = strchr (optname, '=');
+
+                // compute the length of the ooption including the equals
+                // sign (if any)
+                const size_t optlen =
+                    eq ? size_t (eq - optname + 1) : strlen (optname);
+
+                // try to match the long option first, and only if it
+                // doesn't match try the short single-character option
+                if (   cmdopts [j].lopt_
+                    && optlen == strlen (cmdopts [j].lopt_)
+                    && 0 == memcmp (optname, cmdopts [j].lopt_, optlen)
+                    || cmdopts [j].sopt_
+                    && optname [0] == cmdopts [j].sopt_
+                    && (1 == optlen || cmdopts [j].arg_)) {
+
+                    // matching option has been found
+                    found = true;
+
+                    // ignore the option if invoked recursively (by processing
+                    // options set in the environment) and the option has
+                    // already been seen (this prevents duplicate processing
+                    // of options that are set both on the command line and
+                    // in the environment and allows option with an argument
+                    // set on the command line to override those set in the
+                    // environment)
+
+                    if (cmdopts [j].ncalls_ && recursive)
+                        continue;
+
+                    // if the option has been evaluated the maximum number
+                    // of times, avoid evaluating it and continue processing
+                    if (cmdopts [j].maxcalls_ <= cmdopts [j].ncalls_)
+                        continue;
+
+                    if (cmdopts [j].callback_) {
+                        if (!cmdopts [j].inv_) {
+                            // when the command line argument matched
+                            // the option,  invoke the callback function
+                            status = cmdopts [j].callback_ (argc - i, argv + i);
+                        }
+                    }
+                    else {
+                        assert (0 != cmdopts [j].pcntr_);
+                        ++*cmdopts [j].pcntr_;
+                    }
+
+                    ++cmdopts [j].ncalls_;
+
+                    if (recursive)
+                        cmdopts [j].envseen_ = true;
+
+                    ++nopts;
+
+                    if (status) {
+                        // when the status returned from the last callback
+                        // is non-0 stop further processing (including
+                        // any options set in the environment) and return
+                        // status to the caller
+                        ignenv = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (!found && '-' == argv [i][0]) {
+
+            // invoke the appropriate error handler for an option
+            // that was not found
+            if (_RWSTD_SIZE_MAX != not_found_inx) {
+
+                // invoke the error handler set up through rw_setopts()
+                // and let the handler decide whether to go on processing
+                // other options or whether to abort
+                status = cmdopts [not_found_inx].callback_ (argc - i, argv + i);
+                if (status) {
+                    // no further processing done
+                    ignenv = true;
+                    break;
+                }
+            }
+            else {
+                // print an error message to stderr when no error
+                // handler has been set up
+                fprintf (stderr, "unknown option: %s\n", argv [i]);
+                ignenv = true;
+                errno  = EINVAL;
+                status = 1;
+                break;
+            }
+        }
+    }
+
+    if (!ignenv) {
+        // process options from the environment
+        const char* const envar = getenv ("RWSTD_TESTOPTS");
+        if (envar) {
+            recursive = true;
+            rw_runopts (envar);
+            recursive = false;
+        }
+    }
+
+    // invoke any inverted callbacks or bump their user-specified counters,
+    // and reset internal counters indicating if/how many times each option
+    // has been processed
+    for (size_t j = 0; j != ncmdopts; ++j) {
+
+        if (cmdopts [j].inv_ && 0 == cmdopts [j].ncalls_ && 0 == status) {
+
+            if (cmdopts [j].callback_)
+                status = cmdopts [j].callback_ (0, 0);
+            else {
+                assert (0 != cmdopts [j].pcntr_);
+                ++*cmdopts [j].pcntr_;
+            }
+        }
+
+        cmdopts [j].ncalls_  = 0;
+        cmdopts [j].envseen_ = false;
+    }
+
+    return status;
+}
+
+
+_TEST_EXPORT int
+rw_runopts (const char *str)
+{
+    assert (0 != str);
+
+    rw_set_myopts ();
+
+    char buf [80];      // fixed size buffer to copy `str' into
+    char *pbuf = buf;   // a modifiable copy of `str'
+
+    size_t len = strlen (str);
+    if (len >= sizeof buf) {
+        // allocate if necessary
+        pbuf = (char*)malloc (len + 1);
+        if (!pbuf)
+            return -1;
+    }
+
+    // copy `str' to modifiable buffer
+    memcpy (pbuf, str, len + 1);
+
+    char *tmp_argv_buf [32] = { 0 };   // fixed size argv buffer
+    char **argv = tmp_argv_buf;        // array of arguments
+
+    // initial size of argument array (will grow as necessary)
+    size_t argv_size = sizeof tmp_argv_buf / sizeof *tmp_argv_buf;
+    size_t argc = 0;   // number of arguments in array
+
+    int in_quotes = 0;   // quoted argument being processed
+
+    for (char *s = pbuf; *s; ++s) {
+        if ('"' == *s) {
+            in_quotes = !in_quotes;
+            continue;
+        }
+
+        if (in_quotes)
+            continue;
+
+        // split up unquoted space-separated arguments
+        if (argc == 0 || ' ' == *s) {
+            if (argc > 0) 
+                *s = 0;
+
+            // skip over leading spaces
+            if (argc > 0 || ' ' == *s)
+                while (' ' == *++s);
+
+            if (*s) {
+                if (argc == argv_size) {
+                    // grow `argv' as necessary
+                    char **tmp = (char**)malloc (sizeof *tmp * argv_size * 2);
+                    if (!tmp) {
+                        if (argv != tmp_argv_buf)
+                            free (argv);
+                        return -1;
+                    }
+
+                    // copy existing elementes and zero out any new entries
+                    memcpy (tmp, argv, sizeof *tmp * argv_size);
+                    memset (tmp + argv_size, 0, sizeof *tmp * argv_size);
+
+                    // free existing buffer if necessary
+                    if (argv != tmp_argv_buf)
+                        free (argv);
+
+                    // reassign buffer and increase size
+                    argv       = tmp;
+                    argv_size *= 2;
+                }
+
+                // add argument to array
+                argv [argc++] = s;
+            }
+        }
+    }
+
+    // process `argc' options pointed to by `argv'
+    const int status = rw_runopts (int (argc), argv);
+
+    // free buffers if necessary
+    if (argv != tmp_argv_buf)
+        free (argv);
+
+    if (pbuf != buf)
+        free (pbuf);
+
+    return status;
+
+}
+
+
+_TEST_EXPORT int
+rw_enabled (const char *name)
+{
+    int enabled = -1;
+
+    static const struct {
+        int bit;
+        const char *name;
+    } types[] = {
+        { rw_bool, "bool" },
+
+        { rw_char, "char" },
+
+        { rw_schar, "schar" },
+        { rw_schar, "signed char" },
+        { rw_uchar, "uchar" },
+        { rw_uchar, "unsigned char" },
+
+        { rw_shrt, "shrt" },
+        { rw_shrt, "short" },
+        { rw_shrt, "signed short" },
+        { rw_ushrt, "ushrt" },
+        { rw_ushrt, "unsigned short" },
+
+        { rw_int, "int" },
+        { rw_int, "signed int" },
+        { rw_uint, "uint" },
+        { rw_uint, "unsigned int" },
+
+        { rw_long, "long" },
+        { rw_long, "signed long" },
+        { rw_ulong, "ulong" },
+        { rw_ulong, "unsigned long" },
+
+        { rw_llong, "llong" },
+        { rw_llong, "long long" },
+        { rw_llong, "signed long long" },
+        { rw_ullong, "ullong" },
+        { rw_ullong, "unsigned long long" },
+
+        { rw_flt, "flt" },
+        { rw_flt, "float" },
+
+        { rw_dbl, "dbl" },
+        { rw_dbl, "double" },
+
+        { rw_ldbl, "ldbl" },
+        { rw_ldbl, "long double" },
+
+        { rw_wchar, "wchar" },
+        { rw_wchar, "wchar_t" },
+
+        { rw_pvoid, "pvoid" },
+        { rw_pvoid, "void*" }
+    };
+
+    for (size_t i = 0; i != sizeof types / sizeof *types; ++i) {
+        if (0 == strcmp (types [i].name, name)) {
+            const int mask = 1 << types [i].bit;
+
+            enabled = !(rw_disabled_types & mask);
+
+            if (rw_enabled_types)
+                enabled = enabled && (rw_enabled_types & mask);
+
+            break;
+        }
+    }
+
+    return enabled;
+}
+
+
+_TEST_EXPORT int
+rw_enabled (int line)
+{
+    int nenabled = 0;
+    int ndisabled = 0;
+
+    int line_enabled = -1;
+
+    for (size_t i = 0; i != nlineranges; ++i) {
+
+        const int first = lineranges [i].first;
+        const int last  = lineranges [i].last;
+
+        if (first < 0) {
+            line = -line;
+            ++ndisabled;
+        }
+        else {
+            ++nenabled;
+        }
+
+        if (lineranges [i].first <= line && line < lineranges [i].last)
+            line_enabled = 0 < line;
+    }
+
+    if (nenabled && -1 == line_enabled)
+        line_enabled = 0;
+
+    return line_enabled;
+}

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

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



Mime
View raw message