stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r580483 [40/42] - in /incubator/stdcxx/branches/4.2.0: ./ bin/ doc/ doc/stdlibref/ doc/stdlibug/ etc/config/ etc/config/src/ etc/config/windows/ etc/nls/charmaps/ etc/nls/posix/charmaps/ etc/nls/posix/src/ etc/nls/src/ examples/manual/ exam...
Date Fri, 28 Sep 2007 20:57:41 GMT
Modified: incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.get.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.get.cpp?rev=580483&r1=580482&r2=580483&view=diff
==============================================================================
--- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.get.cpp (original)
+++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.get.cpp Fri Sep 28 13:55:52 2007
@@ -241,8 +241,30 @@
 
 /**************************************************************************/
 
+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>
-void do_test (charT       which,   // which overload to exercise
+void do_test (bool        intl,    // international?
+              charT       which,   // which overload to exercise
               const char *cname,   // the name of the charT type
               const char *tname,   // the name of the floating point type
               int         lineno,  // line number
@@ -254,8 +276,7 @@
               int         frac_digits = 0, // fractional digits
               const char *fmat = 0,        // money_base::pattern
               const char *cursym = 0,      // currency symbol
-              const char *grouping = "",   // grouping string
-              bool intl = false)           // international?
+              const char *grouping = "")   // grouping string
 {
     if (!rw_enabled (lineno)) {
         rw_note (0, __FILE__, __LINE__, "test on line %d disabled", lineno);
@@ -271,6 +292,8 @@
 
         fmat = pat.field;
     }
+    else
+        fmat = set_pattern (fmat).field;
 
     // local format? (the opposite of interantional)
     const bool locl = !intl;
@@ -448,11 +471,13 @@
 
 
 template <class charT>
-void test_get (charT opt, const char *cname, const char *tname)
+void test_get (charT opt, const char *cname, const char *tname, bool intl)
 {
-#define T      opt, cname, tname, __LINE__
+#define T      intl, opt, cname, tname, __LINE__
 #define TEST   do_test
 
+    const bool locl = !intl;
+
     rw_info (0, 0, 0,
              "money_get<%s, istreambuf_iterator<%s> >::get "
              "(..., %s&) const", cname, cname, tname);
@@ -466,12 +491,12 @@
     // by decimal_point(). The other symbols are defined as follows:
     //     units ::= digits [ thousandssep units ] digits ::= adigit [ digits ]
 
-    PunctData<charT>::positive_sign_ [0] = 0;
-    PunctData<charT>::positive_sign_ [1] = 0;
-    PunctData<charT>::negative_sign_ [0] = 0;
-    PunctData<charT>::negative_sign_ [1] = 0;
-    PunctData<charT>::thousands_sep_ [0] = '\0';
-    PunctData<charT>::thousands_sep_ [1] = '\0';
+    PunctData<charT>::positive_sign_ [intl] = 0;
+    PunctData<charT>::positive_sign_ [locl] = 0;
+    PunctData<charT>::negative_sign_ [intl] = 0;
+    PunctData<charT>::negative_sign_ [locl] = 0;
+    PunctData<charT>::thousands_sep_ [intl] = '\0';
+    PunctData<charT>::thousands_sep_ [locl] = '\0';
 
     // parsing zero, no curr_symbol or sign, default pattern, 0 frac_digits
     TEST (T, 0.0, "0",   1, 0, eofbit);
@@ -539,8 +564,8 @@
     TEST (T,  54321098.0, "5432.1098", 9, 0, eofbit, 4);
     TEST (T, 432109870.0, "43210.987", 9, 0, eofbit, 4);
 
-    PunctData<charT>::thousands_sep_ [0] = ',';
-    PunctData<charT>::thousands_sep_ [1] = ';';
+    PunctData<charT>::thousands_sep_ [intl] = ',';
+    PunctData<charT>::thousands_sep_ [locl] = ';';
 
     // parsing with thousands_sep and/or grouping
     TEST (T,      0.0, "0",        1, 0, eofbit,  0, 0, "", "\1");
@@ -614,10 +639,10 @@
     static const charT plus[][2]  = { { '+', '\0' }, { '\0' } };
     static const charT minus[][2] = { { '-', '\0' }, { '\0' } };
 
-    PunctData<charT>::positive_sign_ [0] = plus [0];
-    PunctData<charT>::negative_sign_ [0] = minus [0];
-    PunctData<charT>::positive_sign_ [1] = plus [1];
-    PunctData<charT>::negative_sign_ [1] = minus [1];
+    PunctData<charT>::positive_sign_ [intl] = plus [0];
+    PunctData<charT>::negative_sign_ [intl] = minus [0];
+    PunctData<charT>::positive_sign_ [locl] = plus [1];
+    PunctData<charT>::negative_sign_ [locl] = minus [1];
 
     TEST (T,  15.0, "+15",     3, 0, eofbit,  0, 0, "");
     TEST (T,  16.0, "+ 16",    4, 0, eofbit,  0, 0, "");
@@ -647,10 +672,10 @@
     static const charT plus_plus[][3]   = { { '+', '+', '\0' }, { '\0' } };
     static const charT minus_minus[][3] = { { '-', '-', '\0' }, { '\0' } };
 
-    PunctData<charT>::positive_sign_ [0] = plus_plus [0];
-    PunctData<charT>::negative_sign_ [0] = minus_minus [0];
-    PunctData<charT>::positive_sign_ [1] = plus_plus [1];
-    PunctData<charT>::negative_sign_ [1] = minus_minus [1];
+    PunctData<charT>::positive_sign_ [intl] = plus_plus [0];
+    PunctData<charT>::negative_sign_ [intl] = minus_minus [0];
+    PunctData<charT>::positive_sign_ [locl] = plus_plus [1];
+    PunctData<charT>::negative_sign_ [locl] = minus_minus [1];
 
     TEST (T,  27.0, "+27+",    4, 0, eofbit, 0, 0, "");
     TEST (T,  28.0, "+  28+",  6, 0, eofbit, 0, 0, "");
@@ -683,10 +708,10 @@
 
     static const charT plus_minus[][3] = { { '+', '-', '\0' }, { '\0' } };
 
-    PunctData<charT>::positive_sign_ [0] = plus_plus [0];
-    PunctData<charT>::positive_sign_ [1] = plus_plus [1];
-    PunctData<charT>::negative_sign_ [0] = plus_minus [0];
-    PunctData<charT>::negative_sign_ [1] = plus_minus [1];
+    PunctData<charT>::positive_sign_ [intl] = plus_plus [0];
+    PunctData<charT>::positive_sign_ [locl] = plus_plus [1];
+    PunctData<charT>::negative_sign_ [intl] = plus_minus [0];
+    PunctData<charT>::negative_sign_ [locl] = plus_minus [1];
 
     // 22.2.6.1.2, p3: if the first character of positive
     // and negative sign is the same, the result is positive
@@ -694,98 +719,98 @@
     TEST (T, 41.0,   "+41-", 4, 0,        eofbit,  0, 0, "");
     TEST (T, 42.0,  "+42+ ", 4, 0,        goodbit, 0, 0, "");
     TEST (T, 43.0,  "+43- ", 4, 0,        goodbit, 0, 0, "");
-    TEST (T, 44.0, "+44 $+", 6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T, 45.0, "+45 $-", 6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T, 46.0, "+46$+ ", 5, showbase, goodbit, 0, "\3\4\2\0", "$");
-    TEST (T, 47.0, "+47$- ", 5, showbase, goodbit, 0, "\3\4\2\0", "$");
+    TEST (T, 44.0, "+44 $+", 6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T, 45.0, "+45 $-", 6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T, 46.0, "+46$+ ", 5, showbase, goodbit, 0, "-1$@", "$");
+    TEST (T, 47.0, "+47$- ", 5, showbase, goodbit, 0, "-1$@", "$");
 
     // none = 0, space = 1, symbol = 2, sign = 3, value = 4
 
     // test various patterns
-    PunctData<charT>::positive_sign_ [0] = plus [0];
-    PunctData<charT>::positive_sign_ [1] = plus [1];
-    PunctData<charT>::negative_sign_ [0] = minus [0];
-    PunctData<charT>::negative_sign_ [1] = minus [1];
+    PunctData<charT>::positive_sign_ [intl] = plus [0];
+    PunctData<charT>::positive_sign_ [locl] = plus [1];
+    PunctData<charT>::negative_sign_ [intl] = minus [0];
+    PunctData<charT>::negative_sign_ [locl] = minus [1];
 
-    TEST (T,  -100.0, "$-1",   3, showbase, eofbit,  2, "\2\3\4\0", "$");
-    TEST (T,  -200.0, "$-2 ",  3, showbase, goodbit, 2, "\2\3\4\0", "$");
+    TEST (T,  -100.0, "$-1",   3, showbase, eofbit,  2, "$-1@", "$");
+    TEST (T,  -200.0, "$-2 ",  3, showbase, goodbit, 2, "$-1@", "$");
     // where none appears in the pattern, whitespace is optional
-    TEST (T,  -300.0, "-3$",   3, showbase, eofbit,  2, "\3\4\0\2", "$");
-    TEST (T,  -400.0, "-4 $",  4, showbase, eofbit,  2, "\3\4\0\2", "$");
+    TEST (T,  -300.0, "-3$",   3, showbase, eofbit,  2, "-1@$", "$");
+    TEST (T,  -400.0, "-4 $",  4, showbase, eofbit,  2, "-1@$", "$");
     // where space appears in the pattern, a whitespace character is required
-    TEST (T,    0.0, "-5$",    2, showbase, failbit, 2, "\3\4\1\2", "$");
-    TEST (T,  -600.0, "-6 $",  4, showbase, eofbit,  2, "\3\4\1\2", "$");
-    TEST (T,  -700.0, "-7\t$", 4, showbase, eofbit,  2, "\3\4\1\2", "$");
-
-    TEST (T,     0.0, "-8$",   1, showbase, failbit, 2, "\3\1\4\2", "$");
-    TEST (T,  -900.0, "-\n9$", 4, showbase, eofbit,  2, "\3\1\4\2", "$");
-    TEST (T, -1000.0, "- 10$", 5, showbase, eofbit,  2, "\3\1\4\2", "$");
+    TEST (T,    0.0, "-5$",    2, showbase, failbit, 2, "-1 $", "$");
+    TEST (T,  -600.0, "-6 $",  4, showbase, eofbit,  2, "-1 $", "$");
+    TEST (T,  -700.0, "-7\t$", 4, showbase, eofbit,  2, "-1 $", "$");
+
+    TEST (T,     0.0, "-8$",   1, showbase, failbit, 2, "- 1$", "$");
+    TEST (T,  -900.0, "-\n9$", 4, showbase, eofbit,  2, "- 1$", "$");
+    TEST (T, -1000.0, "- 10$", 5, showbase, eofbit,  2, "- 1$", "$");
     // white space is required even at the beginning of input
     // (if the optional sign or symbol is missing)
-    TEST (T,     0.0, "11$",   0, showbase, failbit, 2, "\3\1\4\2", "$");
+    TEST (T,     0.0, "11$",   0, showbase, failbit, 2, "- 1$", "$");
 
-    TEST (T, -1200.0, "12$-",  4, showbase, eofbit,  2, "\4\0\2\3", "$");
-    TEST (T, -1300.0, "13 $-", 5, showbase, eofbit,  2, "\4\0\2\3", "$");
-    TEST (T,     0.0, "14$-",  2, showbase, failbit, 2, "\4\1\2\3", "$");
-    TEST (T, -1500.0, "15 $-", 5, showbase, eofbit,  2, "\4\1\2\3", "$");
+    TEST (T, -1200.0, "12$-",  4, showbase, eofbit,  2, "1@$-", "$");
+    TEST (T, -1300.0, "13 $-", 5, showbase, eofbit,  2, "1@$-", "$");
+    TEST (T,     0.0, "14$-",  2, showbase, failbit, 2, "1 $-", "$");
+    TEST (T, -1500.0, "15 $-", 5, showbase, eofbit,  2, "1 $-", "$");
 
     const charT parens[][3] = { { '(', ')', '\0' }, { '\0' } };
-    PunctData<charT>::negative_sign_ [0] = parens [0];
-    PunctData<charT>::negative_sign_ [1] = parens [1];
+    PunctData<charT>::negative_sign_ [intl] = parens [0];
+    PunctData<charT>::negative_sign_ [locl] = parens [1];
 
     // { sign, space, value, symbol }, with symbol required
-    TEST (T, -90.0, "( 9$)",    5, showbase, eofbit, 1, "\3\1\4\2", "$");
-    TEST (T, -80.0, "( 8SIT)",  7, showbase, eofbit, 1, "\3\1\4\2", "SIT");
-    TEST (T, -81.0, "( 8.1Fr)", 8, showbase, eofbit, 1, "\3\1\4\2", "Fr");
-    TEST (T,  70.0, " 7Ptas",   6, showbase, eofbit, 1, "\3\1\4\2", "Ptas");
-    TEST (T,  61.0, " 6.1Lek",  7, showbase, eofbit, 1, "\3\1\4\2", "Lek");
+    TEST (T, -90.0, "( 9$)",    5, showbase, eofbit, 1, "- 1$", "$");
+    TEST (T, -80.0, "( 8SIT)",  7, showbase, eofbit, 1, "- 1$", "SIT");
+    TEST (T, -81.0, "( 8.1Fr)", 8, showbase, eofbit, 1, "- 1$", "Fr");
+    TEST (T,  70.0, " 7Ptas",   6, showbase, eofbit, 1, "- 1$", "Ptas");
+    TEST (T,  61.0, " 6.1Lek",  7, showbase, eofbit, 1, "- 1$", "Lek");
 
     // { sign, value, none, symbol }
-    TEST (T,  101.0, "101    ", 3, 0,        goodbit, 0, "\3\4\0\2", "");
+    TEST (T,  101.0, "101    ", 3, 0,        goodbit, 0, "-1@$", "");
     // trailing space not extracted since currency symbol is optional
-    TEST (T,  102.0, "102 ", 3, 0, goodbit, 0, "\3\4\0\2", " ");
+    TEST (T,  102.0, "102 ", 3, 0, goodbit, 0, "-1@$", " ");
     // all spaces extracted since currency symbol (last) is mandatory
     // verify that the facet doesn't extract too many optional spaces
     // leaving none for the final required currency symbol
-    TEST (T,  103.0, "103 ", 4, showbase, eofbit, 0, "\3\4\0\2", " ");
+    TEST (T,  103.0, "103 ", 4, showbase, eofbit, 0, "-1@$", " ");
 
     // 22.2.6.1.2, p3: [Example: If showbase is off, then for
     // a negative sign value of "()" and a currency symbol of "L",
     // in "(100 L)" the "L" is consumed; but if negative sign is "­",
     // the "L" in "­100 L" is not consumed. ]
-    TEST (T, -104.0, "(104 L)", 7, 0,        eofbit,  0, "\3\4\0\2", "L");
-    TEST (T, -105.0, "(105 L)", 7, showbase, eofbit,  0, "\3\4\0\2", "L");
+    TEST (T, -104.0, "(104 L)", 7, 0,        eofbit,  0, "-1@$", "L");
+    TEST (T, -105.0, "(105 L)", 7, showbase, eofbit,  0, "-1@$", "L");
 
-    PunctData<charT>::positive_sign_ [0] = plus [0];
-    PunctData<charT>::negative_sign_ [0] = minus [0];
-    PunctData<charT>::positive_sign_ [1] = plus [1];
-    PunctData<charT>::negative_sign_ [1] = minus [1];
+    PunctData<charT>::positive_sign_ [intl] = plus [0];
+    PunctData<charT>::negative_sign_ [intl] = minus [0];
+    PunctData<charT>::positive_sign_ [locl] = plus [1];
+    PunctData<charT>::negative_sign_ [locl] = minus [1];
 
     // { sign, value, none, symbol }
     // trailing optional curr_symbol or whitespace preceding it (regardless
     // of whether the latter is required or optional) is not consumed)
-    TEST (T, -101.0, "-101 $", 4, 0,        goodbit, 0, "\3\4\0\2", "$");
-    TEST (T, -102.0, "-102 $", 6, showbase, eofbit, 0, "\3\4\0\2", "$");
+    TEST (T, -101.0, "-101 $", 4, 0,        goodbit, 0, "-1@$", "$");
+    TEST (T, -102.0, "-102 $", 6, showbase, eofbit, 0, "-1@$", "$");
 
-    TEST (T, -103.0, "-103 $", 4, 0,        goodbit, 0, "\3\4\1\2", "$");
-    TEST (T, -104.0, "-104 $", 6, showbase, eofbit, 0, "\3\4\1\2", "$");
+    TEST (T, -103.0, "-103 $", 4, 0,        goodbit, 0, "-1 $", "$");
+    TEST (T, -104.0, "-104 $", 6, showbase, eofbit, 0, "-1 $", "$");
 
     // { sign, value, symbol, none }
-    TEST (T, -105.0, "-105 $", 4, 0,        goodbit, 0, "\3\4\2\0", "$");
-    TEST (T, -106.0, "-106$ ", 5, showbase, goodbit, 0, "\3\4\2\0", "$");
+    TEST (T, -105.0, "-105 $", 4, 0,        goodbit, 0, "-1$@", "$");
+    TEST (T, -106.0, "-106$ ", 5, showbase, goodbit, 0, "-1$@", "$");
 
     // { value, none, sign, symbol }
     // trailing whitespace may need to be extracted if characters may
     // be needed to complete the pattern (e.g., sign or symbol)
-    TEST (T,  107.0, "107 $",  4, 0,        goodbit, 0, "\4\0\3\2", "$");
+    TEST (T,  107.0, "107 $",  4, 0,        goodbit, 0, "1@-$", "$");
     // trailing optional curr_symbol is not consumed
-    TEST (T, -108.0, "108-$",  4, 0,        goodbit, 0, "\4\0\3\2", "$");
+    TEST (T, -108.0, "108-$",  4, 0,        goodbit, 0, "1@-$", "$");
     // trailing required curr_symbol is consumed
-    TEST (T, -109.0, "109-$",  5, showbase, eofbit,  0, "\4\0\3\2", "$");
+    TEST (T, -109.0, "109-$",  5, showbase, eofbit,  0, "1@-$", "$");
 
     const charT minus_space[][3] = { { '-', ' ', '\0' }, { '\0' } };
-    PunctData<charT>::negative_sign_ [0] = minus_space [0];
-    PunctData<charT>::negative_sign_ [1] = minus_space [1];
+    PunctData<charT>::negative_sign_ [intl] = minus_space [0];
+    PunctData<charT>::negative_sign_ [locl] = minus_space [1];
 
     // { sign, value, none, symbol }
     // negative_sign is "- ", (note the single trailing space)
@@ -793,70 +818,70 @@
     // specifier that's last in the pattern doesn't confuse the facet into
     // extracting all the optional whitespace, leaving none to complete
     // the negative_sign
-    TEST (T, -109.1, "-109  ", 6, 0, eofbit, 0, "\3\4\0\2", "");
+    TEST (T, -109.1, "-109  ", 6, 0, eofbit, 0, "-1@$", "");
 
     // verify that optional space after value and before currency
     // symbol is treated correctly
-    PunctData<charT>::positive_sign_ [0] = plus_plus [0];
-    PunctData<charT>::positive_sign_ [1] = 0;
-    PunctData<charT>::negative_sign_ [0] = 0;
-    PunctData<charT>::negative_sign_ [1] = 0;
+    PunctData<charT>::positive_sign_ [intl] = plus_plus [0];
+    PunctData<charT>::positive_sign_ [locl] = 0;
+    PunctData<charT>::negative_sign_ [intl] = 0;
+    PunctData<charT>::negative_sign_ [locl] = 0;
 
     // { sign, value, none, symbol }
-    TEST (T,  1090.0, "1090 $",   6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T,  1091.0, "1091 $",   6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T, +1092.0, "+1092 $+", 8, showbase, eofbit,  0, "\3\4\0\2", "$");
-
-    PunctData<charT>::positive_sign_ [0] = 0;
-    PunctData<charT>::positive_sign_ [1] = 0;
-    PunctData<charT>::negative_sign_ [0] = parens [0];
-    PunctData<charT>::negative_sign_ [1] = 0;
-
-    TEST (T,  1093.0, "1093 $",   6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T,  1094.0, "1094 $",   6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T, -1095.0, "(1095 $)", 8, showbase, eofbit,  0, "\3\4\0\2", "$");
+    TEST (T,  1090.0, "1090 $",   6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T,  1091.0, "1091 $",   6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T, +1092.0, "+1092 $+", 8, showbase, eofbit,  0, "-1@$", "$");
+
+    PunctData<charT>::positive_sign_ [intl] = 0;
+    PunctData<charT>::positive_sign_ [locl] = 0;
+    PunctData<charT>::negative_sign_ [intl] = parens [0];
+    PunctData<charT>::negative_sign_ [locl] = 0;
+
+    TEST (T,  1093.0, "1093 $",   6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T,  1094.0, "1094 $",   6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T, -1095.0, "(1095 $)", 8, showbase, eofbit,  0, "-1@$", "$");
 
     // verify a single-char sign with a multichar one (see bug #428)
-    PunctData<charT>::positive_sign_ [0] = plus [0];
-    PunctData<charT>::positive_sign_ [1] = 0;
-    PunctData<charT>::negative_sign_ [0] = parens [0];
-    PunctData<charT>::negative_sign_ [1] = 0;
+    PunctData<charT>::positive_sign_ [intl] = plus [0];
+    PunctData<charT>::positive_sign_ [locl] = 0;
+    PunctData<charT>::negative_sign_ [intl] = parens [0];
+    PunctData<charT>::negative_sign_ [locl] = 0;
 
     // { sign, value, none, symbol }
-    TEST (T,  1096.0, "1096 $",   6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T,  1097.0, "1097 $",   6, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T, +1098.0, "+1098 $",  7, showbase, eofbit,  0, "\3\4\0\2", "$");
-    TEST (T, -1099.0, "(1099 $)", 8, showbase, eofbit,  0, "\3\4\0\2", "$");
-
-    PunctData<charT>::positive_sign_ [0] = 0;
-    PunctData<charT>::positive_sign_ [1] = 0;
-    PunctData<charT>::negative_sign_ [0] = 0;
-    PunctData<charT>::negative_sign_ [1] = 0;
+    TEST (T,  1096.0, "1096 $",   6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T,  1097.0, "1097 $",   6, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T, +1098.0, "+1098 $",  7, showbase, eofbit,  0, "-1@$", "$");
+    TEST (T, -1099.0, "(1099 $)", 8, showbase, eofbit,  0, "-1@$", "$");
+
+    PunctData<charT>::positive_sign_ [intl] = 0;
+    PunctData<charT>::positive_sign_ [locl] = 0;
+    PunctData<charT>::negative_sign_ [intl] = 0;
+    PunctData<charT>::negative_sign_ [locl] = 0;
 
     // { value, none, symbol, sign }
     // trailing whitespace is not extracted (even if required by the format)
     // if it can be determined that no other characters can possibly complete
     // the format (e.g., if both signs and symbol are empty or if signs are
     // empty and symbol is optional)
-    TEST (T,  110.0, "110 $",  3, 0,        goodbit, 0, "\4\0\3\2", "$");
-    TEST (T,  111.0, "111 $",  3, 0,        goodbit, 0, "\4\1\3\2", "$");
-    TEST (T,  112.0, "112$",   4, showbase, eofbit,  0, "\4\0\3\2", "$");
-    TEST (T,  113.0, "113$",   4, showbase, eofbit,  0, "\4\0\3\2", "$");
-    TEST (T,  114.0, "114 $",  5, showbase, eofbit,  0, "\4\1\3\2", "$");
-
-    TEST (T,  115.0, "115 $",  3, 0,        goodbit, 0, "\4\0\2\3", "$");
-    TEST (T,  116.0, "116 $",  3, 0,        goodbit, 0, "\4\1\2\3", "$");
-    TEST (T,  117.0, "117$",   4, showbase, eofbit,  0, "\4\0\2\3", "$");
-    TEST (T,  118.0, "118$",   4, showbase, eofbit,  0, "\4\0\2\3", "$");
-    TEST (T,  119.0, "119 $",  5, showbase, eofbit,  0, "\4\1\2\3", "$");
-
-
-    PunctData<charT>::positive_sign_ [0] = plus [0];
-    PunctData<charT>::positive_sign_ [1] = plus [1];
-    PunctData<charT>::negative_sign_ [0] = minus [0];
-    PunctData<charT>::negative_sign_ [1] = minus [1];
-    PunctData<charT>::thousands_sep_ [0] = ';';
-    PunctData<charT>::thousands_sep_ [1] = '*';
+    TEST (T,  110.0, "110 $",  3, 0,        goodbit, 0, "1@-$", "$");
+    TEST (T,  111.0, "111 $",  3, 0,        goodbit, 0, "1 -$", "$");
+    TEST (T,  112.0, "112$",   4, showbase, eofbit,  0, "1@-$", "$");
+    TEST (T,  113.0, "113$",   4, showbase, eofbit,  0, "1@-$", "$");
+    TEST (T,  114.0, "114 $",  5, showbase, eofbit,  0, "1 -$", "$");
+
+    TEST (T,  115.0, "115 $",  3, 0,        goodbit, 0, "1@$-", "$");
+    TEST (T,  116.0, "116 $",  3, 0,        goodbit, 0, "1 $-", "$");
+    TEST (T,  117.0, "117$",   4, showbase, eofbit,  0, "1@$-", "$");
+    TEST (T,  118.0, "118$",   4, showbase, eofbit,  0, "1@$-", "$");
+    TEST (T,  119.0, "119 $",  5, showbase, eofbit,  0, "1 $-", "$");
+
+
+    PunctData<charT>::positive_sign_ [intl] = plus [0];
+    PunctData<charT>::positive_sign_ [locl] = plus [1];
+    PunctData<charT>::negative_sign_ [intl] = minus [0];
+    PunctData<charT>::negative_sign_ [locl] = minus [1];
+    PunctData<charT>::thousands_sep_ [intl] = ';';
+    PunctData<charT>::thousands_sep_ [locl] = '*';
 
     // test grouping, default pattern { symbol sign none value }
     TEST (T, 0.0, "$0",     2, 0, eofbit, 0, 0, "$", "\1");
@@ -943,6 +968,19 @@
 
 #undef T
 
+}
+
+/**************************************************************************/
+
+template <class charT>
+void
+test_get (charT opt, const char *cname, const char *tname)
+{
+    // test local money format
+    test_get (opt, cname, tname, false);
+
+    // test international money format
+    test_get (opt, cname, tname, true);
 }
 
 /**************************************************************************/

Modified: incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.put.mt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.put.mt.cpp?rev=580483&r1=580482&r2=580483&view=diff
==============================================================================
--- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.put.mt.cpp (original)
+++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.money.put.mt.cpp Fri Sep 28 13:55:52 2007
@@ -35,23 +35,28 @@
 #include <rw_locale.h>
 #include <rw_thread.h>
 #include <driver.h>
+#include <valcmp.h>    // for rw_strncmp ()
 
 
 // maximum number of threads allowed by the command line interface
-#define MAX_THREADS   32
+#define MAX_THREADS      32
+#define MAX_LOOPS    100000
 
-
-#ifdef _RWSTD_REENTRANT
-int rw_opt_nthreads = 4;
-#else   // if !defined (_RWSTD_REENTRANT)
-// in non-threaded builds use just one thread
+// default number of threads (will be adjusted to the number
+// of processors/cores later)
 int rw_opt_nthreads = 1;
-#endif   // _RWSTD_REENTRANT
 
 // the number of times each thread should iterate (unless specified
 // otherwise on the command line)
 int rw_opt_nloops = 100000;
 
+// number of locales to use
+int rw_opt_nlocales = MAX_THREADS;
+
+// should all threads share the same set of locale objects instead
+// of creating their own?
+int rw_opt_shared_locale;
+
 /**************************************************************************/
 
 // array of locale names to use for testing
@@ -64,6 +69,88 @@
 
 /**************************************************************************/
 
+static const char n_money_vals[][20] = {
+    "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678",
+    "-9", "-98", "-987", "-9876", "-98765", "-987654", "-9876543",
+    "1.9", "-12.89", "123.789", "-1234.6789", "-12345.56789"
+};
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+static const wchar_t w_money_vals[][20] = {
+    L"1", L"12", L"123", L"1234", L"12345", L"123456", L"1234567",
+    L"-9", L"-98", L"-987", L"-9876", L"-98765", L"-987654", L"-9876543",
+    L"1.9", L"-12.89", L"123.789", L"-1234.6789", L"-12345.56789"
+};
+
+#endif  // _RWSTD_NO_WCHAR_T
+
+//
+struct MyMoneyData
+{
+    enum { BufferSize = 16 };
+
+    enum PutId {
+        put_ldbl,
+        put_string,
+        put_max
+    };
+
+    // 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_;
+
+    // international or domestic format flag
+    bool intl_;
+
+    // the time struct used to generate strings below
+    double money_value_;
+
+    // type of the data we created string from
+    PutId type_;
+
+    // index into string array [n,w]_money_vals
+    unsigned money_index_;
+
+    // narrow representations of money_
+    char ncs_ [BufferSize];
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    // wide representations of money_
+    wchar_t wcs_ [BufferSize];
+
+#endif // _RWSTD_NO_WCHAR_T
+
+} my_money_data [MAX_THREADS];
+
+
+template <class charT, class Traits>
+struct MyIos: std::basic_ios<charT, Traits>
+{
+    MyIos () {
+        this->init (0);
+    }
+};
+
+
+template <class charT, class Traits>
+struct MyStreambuf: std::basic_streambuf<charT, Traits>
+{
+    typedef std::basic_streambuf<charT, Traits> Base;
+
+    MyStreambuf ()
+        : Base () {
+    }
+
+    void pubsetp (charT *pbeg, std::streamsize n) {
+        this->setp (pbeg, pbeg + n);
+    }
+};
+
+
 extern "C" {
 
 bool test_char;    // exercise money_put<char>
@@ -73,88 +160,57 @@
 static void*
 thread_func (void*)
 {
-    // dummy streambuf-derived object the doesn't do anything
-    // but allows ostreambuf_iterator to "think" it can write
-    // to it
-    struct NarrowBuf: std::streambuf {
-        int_type overflow (int_type c) { return c; }
-    } sb;
-
-    const char str_vals[][20] = {
-        "1", "12", "123", "1234", "12345", "123456", "1234567", "12345678",
-        "-9", "-98", "-987", "-9876", "-98765", "-987654", "-9876543",
-        "1.9", "-12.89", "123.789", "-1234.6789", "-12345.56789"
-    };
+    char             ncs [MyMoneyData::BufferSize];
+    MyIos<char, std::char_traits<char> >       nio;
+    MyStreambuf<char, std::char_traits<char> > nsb;
+    nio.rdbuf (&nsb);
 
 #ifndef _RWSTD_NO_WCHAR_T
-
-    struct WideBuf: std::wstreambuf {
-        int_type overflow (int_type c) { return c; }
-    } wb;
-
-    const wchar_t wstr_vals[][20] = {
-        L"1", L"12", L"123", L"1234", L"12345", L"123456", L"1234567",
-        L"-9", L"-98", L"-987", L"-9876", L"-98765", L"-987654", L"-9876543",
-        L"1.9", L"-12.89", L"123.789", L"-1234.6789", L"-12345.56789"
-    };
-
-#endif   // _RWSTD_NO_WCHAR_T
-
-    struct Ios: std::ios {
-        Ios () { this->init (0); }
-    } io;
+    wchar_t                wcs [MyMoneyData::BufferSize];
+    MyIos<wchar_t, std::char_traits<wchar_t> >       wio;
+    MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+    wio.rdbuf (&wsb);
+#endif // _RWSTD_NO_WCHAR_T
 
     for (int i = 0; i != rw_opt_nloops; ++i) {
 
         // save the name of the locale
-        const char* const locale_name = locales [i % nlocales];
+        const MyMoneyData& data = my_money_data [i % nlocales];
 
-        // construct a named locale and imbue it in the ios object
-        // so that the locale is used not only by the money_put facet
-        // but also by the numpunct facet
-        const std::locale loc (locale_name);
-        io.imbue (loc);
-
-        enum PutId {
-            put_ldbl,
-            put_string,
-            put_max
-        };
-
-        io.width (i % 16);
-
-        // exercise postive and negative values
-        long double ldval = i & 1 ? -i : i;
-
-        // add some random fractional digits
-        if (i & 2)
-            ldval += ldval / 3.14;
-
-        // exercise domestic formats every other iteration
-        // and international formats the rest
-        const bool intl = 0 == (i & 1);
+        // construct a named locale, get a reference to the money_put
+        // 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_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
 
-            const std::money_put<char> &mp =
+            const std::money_put<char> &np =
                 std::use_facet<std::money_put<char> >(loc);
 
-            const std::ostreambuf_iterator<char> iter (&sb);
+            nio.imbue (loc);
+            nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
 
-            switch (PutId (i % put_max)) {
-            case put_ldbl:
-                mp.put (iter, intl, io, ' ', ldval);
+            switch (data.type_) {
+            case MyMoneyData::put_ldbl:
+                *np.put (std::ostreambuf_iterator<char>(&nsb),
+                         data.intl_, nio, ' ', data.money_value_) = '\0';
                 break;
-
-            case put_string: {
-                const char* const strval =
-                    str_vals [i % sizeof str_vals / sizeof *str_vals];
-
-                mp.put (iter, intl, io, ' ', strval);
+            case MyMoneyData::put_string:
+                *np.put (std::ostreambuf_iterator<char>(&nsb),
+                         data.intl_, nio, ' ',
+                         n_money_vals [data.money_index_]) = '\0';
+                break;
+            case MyMoneyData::put_max:
+                // avoid enumeration value `put_max' not handled in switch
+                // this case should never happen
                 break;
             }
-            }
+
+            RW_ASSERT (!nio.fail ());
+            RW_ASSERT (!rw_strncmp (ncs, data.ncs_));
+
         }
 
         // both specializations may be tested at the same time
@@ -164,24 +220,30 @@
 
 #ifndef _RWSTD_NO_WCHAR_T
 
-            const std::money_put<wchar_t> &mp =
+            const std::money_put<wchar_t> &wp =
                 std::use_facet<std::money_put<wchar_t> >(loc);
 
-            const std::ostreambuf_iterator<wchar_t> iter (&wb);
+            wio.imbue (loc);
+            wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
 
-            switch (PutId (i % put_max)) {
-            case put_ldbl:
-                mp.put (iter, intl, io, ' ', ldval);
+            switch (data.type_) {
+            case MyMoneyData::put_ldbl:
+                *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+                         data.intl_, wio, ' ', data.money_value_) = L'\0';
                 break;
-
-            case put_string: {
-                const wchar_t* const strval =
-                    wstr_vals [i % sizeof wstr_vals / sizeof *wstr_vals];
-
-                mp.put (iter, intl, io, ' ', strval);
+            case MyMoneyData::put_string:
+                *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+                         data.intl_, wio, ' ',
+                         w_money_vals [data.money_index_]) = L'\0';
+                break;
+            case MyMoneyData::put_max:
+                // avoid enumeration value `put_max' not handled in switch
+                // this case should never happen
                 break;
             }
-            }
+
+            RW_ASSERT (!wio.fail ());
+            RW_ASSERT (!rw_strncmp (wcs, data.wcs_));
 
 #endif   // _RWSTD_NO_WCHAR_T
 
@@ -198,23 +260,137 @@
 static int
 run_test (int, char**)
 {
-    char* const locale_list = rw_locales ();
+    MyIos<char, std::char_traits<char> >       nio;
+    MyStreambuf<char, std::char_traits<char> > nsb;
+    nio.rdbuf (&nsb);
+
+#ifndef _RWSTD_NO_WCHAR_T
+    MyIos<wchar_t, std::char_traits<wchar_t> >       wio;
+    MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+    wio.rdbuf (&wsb);
+#endif // _RWSTD_NO_WCHAR_T
+
+    // 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
+        MyMoneyData& data = my_money_data [inx];
+        data.locale_name_ = name;
+
+        try {
+            const std::locale loc (data.locale_name_);
+
+            // initialize with random but valid values
+
+            data.money_value_ = inx;
+            data.type_ = MyMoneyData::PutId (nlocales % MyMoneyData::put_max);
+            data.money_index_ = inx % RW_COUNT_OF (n_money_vals);
+
+            // exercise domestic formats every other iteration
+            // and international formats the rest
+            data.intl_ = 0 == (inx & 1);
+
+            // exercise postive and negative values
+            if (inx & 1)
+                data.money_value_ *= -1.;
+
+            // add some random fractional digits
+            if (inx & 2)
+                data.money_value_ += data.money_value_ / 3.14;
+
+            const std::money_put<char> &np =
+                std::use_facet<std::money_put<char> >(loc);
+
+            nio.imbue (loc);
+            nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
+            
+            switch (data.type_) {
+            case MyMoneyData::put_ldbl:
+                *np.put (std::ostreambuf_iterator<char>(&nsb),
+                         data.intl_, nio, ' ', data.money_value_) = '\0';
+                break;
+            case MyMoneyData::put_string:
+                *np.put (std::ostreambuf_iterator<char>(&nsb),
+                         data.intl_, nio, ' ',
+                         n_money_vals [data.money_index_]) = '\0';
+                break;
+            case MyMoneyData::put_max:
+                // avoid enumeration value `put_max' not handled in switch
+                // this case should never happen
+                break;
+            }
+
+            rw_assert (!nio.fail (), __FILE__, __LINE__,
+                       "money_put<char>::put(...) "
+                       "failed for locale(%#s)",
+                       data.locale_name_);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+            const std::money_put<wchar_t> &wp =
+                std::use_facet<std::money_put<wchar_t> >(loc);
+
+            wio.imbue (loc);
+            wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
+
+            switch (data.type_) {
+            case MyMoneyData::put_ldbl:
+                *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+                         data.intl_, wio, L' ', data.money_value_) = '\0';
+                break;
+            case MyMoneyData::put_string:
+                *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+                         data.intl_, wio, L' ',
+                         w_money_vals [data.money_index_]) = L'\0';
+                break;
+            case MyMoneyData::put_max:
+                // avoid enumeration value `put_max' not handled in switch
+                // this case should never happen
+                break;
+            }
+
+            rw_assert (!nio.fail (), __FILE__, __LINE__,
+                       "money_put<wchar_t>::put(...) "
+                       "failed for locale(%#s)",
+                       data.locale_name_);
+
+#endif // _RWSTD_NO_WCHAR_T
 
-    const std::size_t maxinx = sizeof locales / sizeof *locales;
+            if (rw_opt_shared_locale)
+                data.locale_ = loc;
 
-    for (char *name = locale_list; *name; name += std::strlen (name) + 1) {
-        locales [nlocales++] = name;
+            nlocales += 1;
+
+        }
+        catch (...) {
+            rw_warn (!rw_opt_locales, 0, __LINE__,
+                     "failed to create locale(%#s)", name);
+        }
 
-        if (nlocales == maxinx)
+        if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales))
             break;
     }
 
+    // avoid divide by zero in thread if there are no locales to test
+    rw_fatal (nlocales != 0, 0, __LINE__,
+              "failed to create one or more usable locales!");
+
     rw_info (0, 0, 0,
              "testing std::money_put<charT> with %d thread%{?}s%{;}, "
-             "%zu iteration%{?}s%{;} each, in locales { %{ .*A@} }",
+             "%zu iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
              rw_opt_nthreads, 1 != rw_opt_nthreads,
              rw_opt_nloops, 1 != rw_opt_nloops,
-             int (nlocales), "%#s", locales);
+             nlocales, int (nlocales), "%#s", locales);
 
     rw_info (0, 0, 0, "exercising std::money_put<char>");
 
@@ -222,7 +398,7 @@
     test_wchar = false;
 
     // create and start a pool of threads and wait for them to finish
-    int result =
+    int result = 
         rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0);
 
     rw_error (result == 0, 0, __LINE__,
@@ -244,7 +420,7 @@
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
               rw_opt_nthreads, thread_func);
 
-    // exercise bothe the char and the wchar_t specializations
+    // exercise both the char and the wchar_t specializations
     // at the same time
 
     rw_info (0, 0, 0,
@@ -271,12 +447,28 @@
 
 int main (int argc, char *argv[])
 {
+#ifdef _RWSTD_REENTRANT
+
+    // 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;
+
+#endif   // _RWSTD_REENTRANT
+
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.money.put",
                     "thread safety", run_test,
-                    "|-nloops#0 "       // must be non-negative
-                    "|-nthreads#0-*",   // must be in [0, MAX_THREADS]
+                    "|-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,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads);
+                    &rw_opt_nthreads,
+                    &rw_opt_nlocales,
+                    &rw_opt_setlocales,
+                    &rw_opt_shared_locale);
 }

Modified: incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.moneypunct.mt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.moneypunct.mt.cpp?rev=580483&r1=580482&r2=580483&view=diff
==============================================================================
--- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.moneypunct.mt.cpp (original)
+++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.moneypunct.mt.cpp Fri Sep 28 13:55:52 2007
@@ -29,9 +29,8 @@
 #include <ios>        // for ios
 #include <locale>     // for locale, moneypunct
 
-#include <clocale>    // for lconv, localeconv()
-#include <cstdlib>    // for mbstowcs()
-#include <cstring>    // for size_t, strcpy()
+#include <cstdlib>    // for mbstowcs(), size_t
+#include <cstring>    // for strcpy()
 
 #include <rw_locale.h>
 #include <rw_thread.h>
@@ -42,17 +41,16 @@
 // maximum number of threads allowed by the command line interface
 #define MAX_THREADS   32
 
-
-#ifdef _RWSTD_REENTRANT
-int rw_opt_nthreads = 4;
-#else   // if !defined (_RWSTD_REENTRANT)
-// in non-threaded builds use just one thread
+// default number of threads (will be adjusted to the number
+// of processors/cores later)
 int rw_opt_nthreads = 1;
-#endif   // _RWSTD_REENTRANT
 
-// the number of times each thread should iterate (unless specified
-// otherwise on the command line)
-int rw_opt_nloops = 200000;
+// 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;
 
 /**************************************************************************/
 
@@ -97,147 +95,154 @@
 
 } punct_data [MAX_THREADS];
 
-
-extern "C" {
+/**************************************************************************/
 
 bool test_char;    // exercise num_put<char>
 bool test_wchar;   // exercise num_put<wchar_t>
 
-
-static void*
-thread_func (void*)
+static void
+thread_loop_body (std::size_t i)
 {
-    for (int i = 0; i != rw_opt_nloops; ++i) {
-
-        const std::size_t inx = std::size_t (i) % nlocales;
-
-        const MoneypunctData* const data = punct_data + inx;
-
-        // construct a named locale
-        const std::locale loc (data->locale_name_);
-
-        if (test_char) {
-            // exercise the narrow char, local specialization of the facet
+    const std::size_t inx = std::size_t (i) % (nlocales ? nlocales : 1);
 
-            typedef std::moneypunct<char, false> Punct;
+    const MoneypunctData* const data = punct_data + inx;
 
-            const Punct &mp = std::use_facet<Punct>(loc);
+    // construct a named locale
+    const std::locale loc (data->locale_name_);
 
-            const char           dp  = mp.decimal_point ();
-            const char           ts  = mp.thousands_sep ();
-            const std::string    grp = mp.grouping ();
-            const std::string    cur = mp.curr_symbol ();
-            const std::string    pos = mp.positive_sign ();
-            const std::string    neg = mp.negative_sign ();
-            const int            fd  = mp.frac_digits ();
-            const Punct::pattern pfm = mp.pos_format ();
-            const Punct::pattern nfm = mp.neg_format ();
+    if (test_char) {
+        // exercise the narrow char, local specialization of the facet
+
+        typedef std::moneypunct<char, false> Punct;
+
+        const Punct &mp = std::use_facet<Punct>(loc);
+
+        const char           dp  = mp.decimal_point ();
+        const char           ts  = mp.thousands_sep ();
+        const std::string    grp = mp.grouping ();
+        const std::string    cur = mp.curr_symbol ();
+        const std::string    pos = mp.positive_sign ();
+        const std::string    neg = mp.negative_sign ();
+        const int            fd  = mp.frac_digits ();
+        const Punct::pattern pfm = mp.pos_format ();
+        const Punct::pattern nfm = mp.neg_format ();
+
+        RW_ASSERT (dp == data->decimal_point_);
+        RW_ASSERT (ts == data->thousands_sep_);
+        RW_ASSERT (fd == data->frac_digits_);
+        RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
+        RW_ASSERT (!rw_strncmp (cur.c_str (), data->curr_symbol_));
+        RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
+        RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
 
-            RW_ASSERT (dp == data->decimal_point_);
-            RW_ASSERT (ts == data->thousands_sep_);
-            RW_ASSERT (fd == data->frac_digits_);
-            RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
-            RW_ASSERT (!rw_strncmp (cur.c_str (), data->curr_symbol_));
-            RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
-            RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
+        RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
+        RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
+    }
 
-            RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
-            RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
-        }
+    if (test_char) {
+        // exercise the narrow char, international specialization
 
-        if (test_char) {
-            // exercise the narrow char, international specialization
+        typedef std::moneypunct<char, true> Punct;
 
-            typedef std::moneypunct<char, true> Punct;
+        const Punct &mp = std::use_facet<Punct>(loc);
 
-            const Punct &mp = std::use_facet<Punct>(loc);
+        const char           dp  = mp.decimal_point ();
+        const char           ts  = mp.thousands_sep ();
+        const std::string    grp = mp.grouping ();
+        const std::string    cur = mp.curr_symbol ();
+        const std::string    pos = mp.positive_sign ();
+        const std::string    neg = mp.negative_sign ();
+        const int            fd  = mp.frac_digits ();
+        const Punct::pattern pfm = mp.pos_format ();
+        const Punct::pattern nfm = mp.neg_format ();
+
+        RW_ASSERT (dp == data->decimal_point_);
+        RW_ASSERT (ts == data->thousands_sep_);
+        RW_ASSERT (fd == data->frac_digits_);
+        RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
+        RW_ASSERT (!rw_strncmp (cur.c_str (), data->int_curr_symbol_));
+        RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
+        RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
 
-            const char           dp  = mp.decimal_point ();
-            const char           ts  = mp.thousands_sep ();
-            const std::string    grp = mp.grouping ();
-            const std::string    cur = mp.curr_symbol ();
-            const std::string    pos = mp.positive_sign ();
-            const std::string    neg = mp.negative_sign ();
-            const int            fd  = mp.frac_digits ();
-            const Punct::pattern pfm = mp.pos_format ();
-            const Punct::pattern nfm = mp.neg_format ();
+        RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
+        RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
+    }
 
-            RW_ASSERT (dp == data->decimal_point_);
-            RW_ASSERT (ts == data->thousands_sep_);
-            RW_ASSERT (fd == data->frac_digits_);
-            RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
-            RW_ASSERT (!rw_strncmp (cur.c_str (), data->int_curr_symbol_));
-            RW_ASSERT (!rw_strncmp (pos.c_str (), data->positive_sign_));
-            RW_ASSERT (!rw_strncmp (neg.c_str (), data->negative_sign_));
+    // both specializations may be tested at the same time
 
-            RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
-            RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
-        }
+#ifndef _RWSTD_NO_WCHAR_T
 
-        // both specializations may be tested at the same time
+    if (test_wchar) {
+        // exercise the wide char, local specialization of the facet
 
-#ifndef _RWSTD_NO_WCHAR_T
+        typedef std::moneypunct<wchar_t, false> Punct;
 
-        if (test_wchar) {
-            // exercise the wide char, local specialization of the facet
+        const Punct &mp = std::use_facet<Punct>(loc);
 
-            typedef std::moneypunct<wchar_t, false> Punct;
+        const wchar_t        dp  = mp.decimal_point ();
+        const wchar_t        ts  = mp.thousands_sep ();
+        const std::string    grp = mp.grouping ();
+        const std::wstring   cur = mp.curr_symbol ();
+        const std::wstring   pos = mp.positive_sign ();
+        const std::wstring   neg = mp.negative_sign ();
+        const int            fd  = mp.frac_digits ();
+        const Punct::pattern pfm = mp.pos_format ();
+        const Punct::pattern nfm = mp.neg_format ();
+
+        RW_ASSERT (dp == data->wdecimal_point_);
+        RW_ASSERT (ts == data->wthousands_sep_);
+        RW_ASSERT (fd == data->frac_digits_);
+        RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
+        RW_ASSERT (!rw_strncmp (cur.c_str (), data->wcurr_symbol_));
+        RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
+        RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
 
-            const Punct &mp = std::use_facet<Punct>(loc);
+        RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
+        RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
+    }
 
-            const char           dp  = mp.decimal_point ();
-            const char           ts  = mp.thousands_sep ();
-            const std::string    grp = mp.grouping ();
-            const std::wstring   cur = mp.curr_symbol ();
-            const std::wstring   pos = mp.positive_sign ();
-            const std::wstring   neg = mp.negative_sign ();
-            const int            fd  = mp.frac_digits ();
-            const Punct::pattern pfm = mp.pos_format ();
-            const Punct::pattern nfm = mp.neg_format ();
+    if (test_wchar) {
+        // exercise the wide char, international specialization
 
-            RW_ASSERT (dp == data->wdecimal_point_);
-            RW_ASSERT (ts == data->wthousands_sep_);
-            RW_ASSERT (fd == data->frac_digits_);
-            RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
-            RW_ASSERT (!rw_strncmp (cur.c_str (), data->wcurr_symbol_));
-            RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
-            RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
+        typedef std::moneypunct<wchar_t, true> Punct;
 
-            RW_ASSERT (!std::memcmp (&pfm, data->pos_format_, 4));
-            RW_ASSERT (!std::memcmp (&nfm, data->neg_format_, 4));
-        }
+        const Punct &mp = std::use_facet<Punct>(loc);
 
-        if (test_wchar) {
-            // exercise the wide char, international specialization
+        const wchar_t        dp  = mp.decimal_point ();
+        const wchar_t        ts  = mp.thousands_sep ();
+        const std::string    grp = mp.grouping ();
+        const std::wstring   cur = mp.curr_symbol ();
+        const std::wstring   pos = mp.positive_sign ();
+        const std::wstring   neg = mp.negative_sign ();
+        const int            fd  = mp.frac_digits ();
+        const Punct::pattern pfm = mp.pos_format ();
+        const Punct::pattern nfm = mp.neg_format ();
+
+        RW_ASSERT (dp == data->wdecimal_point_);
+        RW_ASSERT (ts == data->wthousands_sep_);
+        RW_ASSERT (fd == data->frac_digits_);
+        RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
+        RW_ASSERT (!rw_strncmp (cur.c_str (), data->wint_curr_symbol_));
+        RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
+        RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
 
-            typedef std::moneypunct<wchar_t, true> Punct;
+        RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
+        RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
+    }
 
-            const Punct &mp = std::use_facet<Punct>(loc);
+#endif   // _RWSTD_NO_WCHAR_T
 
-            const char           dp  = mp.decimal_point ();
-            const char           ts  = mp.thousands_sep ();
-            const std::string    grp = mp.grouping ();
-            const std::wstring   cur = mp.curr_symbol ();
-            const std::wstring   pos = mp.positive_sign ();
-            const std::wstring   neg = mp.negative_sign ();
-            const int            fd  = mp.frac_digits ();
-            const Punct::pattern pfm = mp.pos_format ();
-            const Punct::pattern nfm = mp.neg_format ();
+}
 
-            RW_ASSERT (dp == data->wdecimal_point_);
-            RW_ASSERT (ts == data->wthousands_sep_);
-            RW_ASSERT (fd == data->frac_digits_);
-            RW_ASSERT (!rw_strncmp (grp.c_str (), data->grouping_));
-            RW_ASSERT (!rw_strncmp (cur.c_str (), data->wint_curr_symbol_));
-            RW_ASSERT (!rw_strncmp (pos.c_str (), data->wpositive_sign_));
-            RW_ASSERT (!rw_strncmp (neg.c_str (), data->wnegative_sign_));
 
-            RW_ASSERT (!std::memcmp (&pfm, data->int_pos_format_, 4));
-            RW_ASSERT (!std::memcmp (&nfm, data->int_neg_format_, 4));
-        }
+extern "C" {
 
-#endif   // _RWSTD_NO_WCHAR_T
+static void*
+thread_func (void*)
+{
+    for (int i = 0; i != rw_opt_nloops; ++i) {
 
+        thread_loop_body (std::size_t (i));
     }
 
     return 0;
@@ -247,154 +252,12 @@
 
 /**************************************************************************/
 
-static void
-get_format (MoneypunctData *pdata, const std::lconv *pconv)
-{
-    // code copied from src/punct.cpp
-
-    enum {
-        // for syntactic convenience
-        none   = std::money_base::none,
-        space  = std::money_base::space,
-        symbol = std::money_base::symbol,
-        sign   = std::money_base::sign,
-        value  = std::money_base::value
-    };
-
-    static const std::money_base::pattern pat[] = {
-
-        // cs_precedes [0..1]:
-        //
-        // An integer set to 1 if the currency_symbol precedes the value
-        // for a monetary value, and set to 0 if the symbol succeeds
-        // the value.
-
-        // sep_by_space [0..2]:
-        //
-        // 0  No space separates the currency_symbol from the value for
-        //    a monetary value.
-        // 1  If the currency symbol and sign string are adjacent, a space
-        //    separates them from the value; otherwise, a space separates
-        //    the currency symbol from the value.
-        // 2  If the currency symbol and sign string are adjacent, a space
-        //    separates them; otherwise, a space separates the sign string
-        //    from the value.
-
-        // sign_posn [0..4]:
-        //
-        // An integer set to a value indicating the positioning of the
-        // positive_sign for a monetary value. The following integer
-        // values shall be recognized:
-        //
-        // 0  Parentheses enclose the value and the currency_symbol.
-        // 1  The sign string precedes the value and the currency_symbol.
-        // 2  The sign string succeeds the value and the currency_symbol.
-        // 3  The sign string immediately precedes the currency_symbol.
-        // 4  The sign string immediately succeeds the currency_symbol.
-
-        // +-------- cs_precedes
-        // |+----- sep_by_space
-        // ||+-- sign_posn
-        // |||
-        // VVV  ....        -     1      $       .           // pattern
-        /* 000: -1$. */ { { sign, value, symbol, none } },   // "\3\4\2\0"
-        /* 001: -1$. */ { { sign, value, symbol, none } },   // "\3\4\2\0"
-        /* 002: 1$-. */ { { value, symbol, sign, none } },   // "\4\2\3\0"
-        /* 003: 1-$. */ { { value, sign, symbol, none } },   // "\4\3\2\0"
-        /* 004: 1$-. */ { { value, symbol, sign, none } },   // "\4\2\3\0"
-
-        /* 010: -1 $ */ { { sign, value, space, symbol } },  // "\3\4\1\2"
-        /* 011: -1 $ */ { { sign, value, space, symbol } },  // "\3\4\1\2"
-        /* 012: 1 $- */ { { value, space, symbol, sign } },  // "\4\1\2\3"
-        /* 013: 1 -$ */ { { value, space, sign, symbol } },  // "\4\3\3\2"
-        /* 014: 1 $- */ { { value, space, symbol, sign } },  // "\4\1\2\3"
-
-        /* 020: - 1$ */ { { sign, space, value, symbol } },  // "\3\1\4\2"
-        /* 021: - 1$ */ { { sign, space, value, symbol } },  // "\3\1\4\2"
-        /* 022: 1$ - */ { { value, symbol, space, sign } },  // "\4\2\1\3"
-        /* 023: 1- $ */ { { value, sign, space, symbol } },  // "\4\3\1\2"
-        /* 024: 1$ - */ { { value, symbol, space, sign } },  // "\4\2\1\3"
-
-        /* 100: -$1. */ { { sign, symbol, value, none } },   // "\3\2\4\0"
-        /* 101: -$1. */ { { sign, symbol, value, none } },   // "\3\2\4\0"
-        /* 102: $1-. */ { { symbol, value, sign, none } },   // "\2\4\3\0"
-        /* 103: -$1. */ { { sign, symbol, value, none } },   // "\3\2\4\0"
-        /* 104: $-1. */ { { symbol, sign, value, none } },   // "\2\3\4\0"
-
-        /* 110: -$ 1 */ { { sign, symbol, space, value } },  // "\3\2\1\4"
-        /* 111: -$ 1 */ { { sign, symbol, space, value } },  // "\3\2\1\4"
-        /* 112: $ 1- */ { { symbol, space, value, sign } },  // "\2\1\4\3"
-        /* 113: -$ 1 */ { { sign, symbol, space, value } },  // "\3\2\1\4"
-        /* 114: $- 1 */ { { symbol, sign, space, value } },  // "\2\3\1\4"
-
-        /* 120: - $1 */ { { sign, space, symbol, value } },  // "\3\1\2\4"
-        /* 121: - $1 */ { { sign, space, symbol, value } },  // "\3\1\2\4"
-        /* 122: $1 - */ { { symbol, value, space, sign } },  // "\2\4\1\3"
-        /* 123: - $1 */ { { sign, space, symbol, value } },  // "\3\1\2\4"
-        /* 124: $ -1 */ { { symbol, space, sign, value } }   // "\2\1\3\4"
-    };
-
-    std::size_t inx;
-
-    inx =   std::size_t (pconv->p_cs_precedes) * (3U * 5U)
-          + std::size_t (pconv->p_sep_by_space) * 5U
-          + std::size_t (pconv->p_sign_posn);
-
-    if (inx < sizeof pat / sizeof *pat)
-        std::memcpy (pdata->pos_format_, pat + inx, sizeof *pat);
-    else
-        std::memset (pdata->pos_format_, none, sizeof *pat);
-
-    inx =   std::size_t (pconv->n_cs_precedes) * (3U * 5U)
-          + std::size_t (pconv->n_sep_by_space) * 5U
-          + std::size_t (pconv->n_sign_posn);
-
-    if (inx < sizeof pat / sizeof *pat)
-        std::memcpy (pdata->neg_format_, pat + inx, sizeof *pat);
-    else
-        std::memset (pdata->neg_format_, none, sizeof *pat);
-
-
-#ifndef _RWSTD_NO_LCONV_INT_FMAT
-
-    inx =   std::size_t (pconv->int_p_cs_precedes) * (3U * 5U)
-          + std::size_t (pconv->int_p_sep_by_space) * 5U
-          + std::size_t (pconv->int_p_sign_posn);
-
-    if (inx < sizeof pat / sizeof *pat)
-        std::memcpy (pdata->int_pos_format_, pat + inx, sizeof *pat);
-    else
-        std::memset (pdata->int_pos_format_, none, sizeof *pat);
-
-    inx =   std::size_t (pconv->int_n_cs_precedes) * (3U * 5U)
-          + std::size_t (pconv->int_n_sep_by_space) * 5U
-          + std::size_t (pconv->int_n_sign_posn);
-
-    if (inx < sizeof pat / sizeof *pat)
-        memcpy (pdata->int_neg_format_, pat + inx, sizeof *pat);
-    else
-        memset (pdata->int_neg_format_, none, sizeof *pat);
-
-    std::strcpy (pdata->int_curr_symbol_, pconv->int_curr_symbol);
-
-    pdata->int_frac_digits_ = pconv->int_frac_digits;
-
-#else   // if defined (_RWSTD_NO_LCONV_INT_FMAT)
-
-    std::strcpy (pdata->int_curr_symbol_, pconv->curr_symbol);
-
-    pdata->int_frac_digits_ = pconv->frac_digits;
-
-#endif   // _RWSTD_NO_LCONV_INT_FMAT
-
-}
-
-
 static int
 run_test (int, char**)
 {
-    // get a NUL-separated list of names of installed locales
-    char* const locale_list = rw_locales ();
+    // 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);
 
     // array of locale names to use for testing
     const char* locales [sizeof punct_data / sizeof *punct_data];
@@ -402,78 +265,146 @@
     const std::size_t maxinx = sizeof locales / sizeof *locales;
 
     // iterate over locales, initializing a global punct_data array
-    for (char *name = locale_list; *name; name += std::strlen (name) + 1) {
+    for (const char *name = locale_list; *name; name += std::strlen (name) +1) {
 
-        const std::size_t inx = nlocales;
+        std::locale loc;
 
-        // set LC_NUMERIC and LC_CTYPE to be able to use mbstowcs()
-        if (std::setlocale (LC_ALL, name)) {
+        MoneypunctData* const pdata = punct_data + nlocales;
 
-            const std::lconv* const pconv = std::localeconv ();
-            MoneypunctData* const pdata = punct_data + inx;
+        pdata->locale_name_ = name;
+        locales [nlocales]  = name;
 
-            locales [inx] = pdata->locale_name_ = name;
+        try {
+            loc = std::locale (name);
 
-            // assign just the first character of the (potentially)
-            // multibyte decimal_point and thousands_sep (C++ locale
-            // can't deal with more)
-            pdata->decimal_point_ = *pconv->mon_decimal_point;
-            pdata->thousands_sep_ = *pconv->mon_thousands_sep;
+            typedef std::moneypunct<char, false> Punct;
 
-            pdata->frac_digits_   = pconv->frac_digits;
+            const Punct &mp = std::use_facet<Punct>(loc);
 
-            // simply copy the narrow grouping, currency symbols,
-            // and signs
-            std::strcpy (pdata->grouping_,      pconv->mon_grouping);
-            std::strcpy (pdata->curr_symbol_,   pconv->currency_symbol);
-            std::strcpy (pdata->negative_sign_, pconv->negative_sign);
-            std::strcpy (pdata->positive_sign_, pconv->positive_sign);
-            std::strcpy (pdata->grouping_,      pconv->mon_grouping);
+            const char           dp  = mp.decimal_point ();
+            const char           ts  = mp.thousands_sep ();
+            const std::string    grp = mp.grouping ();
+            const std::string    cur = mp.curr_symbol ();
+            const std::string    pos = mp.positive_sign ();
+            const std::string    neg = mp.negative_sign ();
+            const int            fd  = mp.frac_digits ();
+            const Punct::pattern pfm = mp.pos_format ();
+            const Punct::pattern nfm = mp.neg_format ();
 
-            get_format (pdata, pconv);
+            pdata->decimal_point_ = dp;
+            pdata->thousands_sep_ = ts;
+            pdata->frac_digits_   = fd;
+
+            std::strcpy (pdata->grouping_, grp.c_str ());
+            std::strcpy (pdata->curr_symbol_, cur.c_str ());
+            std::strcpy (pdata->positive_sign_, pos.c_str ());
+            std::strcpy (pdata->negative_sign_, neg.c_str ());
+            std::memcpy (pdata->pos_format_, &pfm, sizeof pfm);
+            std::memcpy (pdata->neg_format_, &nfm, sizeof nfm);
+        }
+        catch (...) {
+            rw_warn (0, 0, __LINE__,
+                     "std::locale(%#s) threw an exception, skipping", name);
+            continue;
+        }
 
-#ifndef _RWSTD_WCHAR_T
+        try {
+            typedef std::moneypunct<char, true> Punct;
 
-            wchar_t tmp [2];
+            const Punct &mp = std::use_facet<Punct>(loc);
 
-            // convert multibyte decimal point and thousands separator
-            // to wide characters (assumes they are single character
-            // each -- C++ locale can't handle more)
-            std::mbstowcs (tmp, pconv->mon_decimal_point, 2);
-            pdata->wdecimal_point_ = tmp [0];
+            const std::string    cur = mp.curr_symbol ();
+            const int            fd  = mp.frac_digits ();
+            const Punct::pattern pfm = mp.pos_format ();
+            const Punct::pattern nfm = mp.neg_format ();
 
-            std::mbstowcs (tmp, pconv->mon_thousands_sep, 2);
-            pdata->wthousands_sep_ = tmp [0];
+            pdata->int_frac_digits_ = fd;
 
-            const std::size_t n =
-                sizeof pdata->wcurr_symbol_ / sizeof (wchar_t);
+            std::strcpy (pdata->int_curr_symbol_, cur.c_str ());
+            std::memcpy (pdata->int_pos_format_, &pfm, sizeof pfm);
+            std::memcpy (pdata->int_neg_format_, &nfm, sizeof nfm);
+        }
+        catch (...) {
+            rw_warn (0, 0, __LINE__,
+                     "std::locale(%#s) threw an exception, skipping", name);
+            continue;
+        }
 
-            std::mbstowcs (pdata->wcurr_symbol_,   pdata->curr_symbol_,   n);
-            std::mbstowcs (pdata->wnegative_sign_, pdata->negative_sign_, n);
-            std::mbstowcs (pdata->wpositive_sign_, pdata->positive_sign_, n);
+#ifndef _RWSTD_NO_WCHAR_T
 
-            std::mbstowcs (pdata->wint_curr_symbol_,
-                           pdata->int_curr_symbol_,
-                           n);
+        try {
+            typedef std::moneypunct<wchar_t, false> Punct;
 
-#endif   // _RWSTD_WCHAR_T
+            const Punct &mp = std::use_facet<Punct>(loc);
 
-            ++nlocales;
+            const wchar_t      dp  = mp.decimal_point ();
+            const wchar_t      ts  = mp.thousands_sep ();
+            const std::wstring cur = mp.curr_symbol ();
+            const std::wstring pos = mp.positive_sign ();
+            const std::wstring neg = mp.negative_sign ();
+
+            pdata->wdecimal_point_ = dp;
+            pdata->wthousands_sep_ = ts;
+
+            typedef std::wstring::traits_type Traits;
+
+            Traits::copy (pdata->wcurr_symbol_,   cur.data (), cur.size ());
+            Traits::copy (pdata->wpositive_sign_, pos.data (), pos.size ());
+            Traits::copy (pdata->wnegative_sign_, neg.data (), neg.size ());
         }
+        catch (...) {
+            rw_warn (0, 0, __LINE__,
+                     "std::locale(%#s) threw an exception, skipping", name);
+            continue;
+        }
+
+        try {
+            typedef std::moneypunct<wchar_t, true> Punct;
+
+            const Punct &mp = std::use_facet<Punct>(loc);
+
+            const std::wstring cur = mp.curr_symbol ();
+            const std::wstring pos = mp.positive_sign ();
+            const std::wstring neg = mp.negative_sign ();
+
+            typedef std::wstring::traits_type Traits;
+
+            Traits::copy (pdata->wint_curr_symbol_, cur.data (), cur.size ());
+        }
+        catch (...) {
+            rw_warn (0, 0, __LINE__,
+                     "std::locale(%#s) threw an exception, skipping", name);
+            continue;
+        }
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+        ++nlocales;
 
         if (nlocales == maxinx)
             break;
     }
 
-    // reset the global locale
-    std::setlocale (LC_ALL, "C");
+    // 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);
+
+    // 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;
+
+    rw_fatal (0 < nlocales, 0, __LINE__,
+              "must have at least one valid locale to test");
 
     rw_info (0, 0, 0,
              "testing std::moneypunct<charT> with %d thread%{?}s%{;}, "
-             "%zu iteration%{?}s%{;} each, in locales { %{ .*A@} }",
+             "%zu iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
              rw_opt_nthreads, 1 != rw_opt_nthreads,
              rw_opt_nloops, 1 != rw_opt_nloops,
-             int (nlocales), "%#s", locales);
+             nlocales, int (nlocales), "%#s", locales);
 
     rw_info (0, 0, 0, "exercising std::moneypunct<char>");
 
@@ -531,12 +462,24 @@
 
 int main (int argc, char *argv[])
 {
+#ifdef _RWSTD_REENTRANT
+
+    // 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;
+
+#endif   // _RWSTD_REENTRANT
+
     return rw_test (argc, argv, __FILE__,
                     "lib.locale.moneypunct",
                     "thread safety", run_test,
                     "|-nloops#0 "       // must be non-negative
-                    "|-nthreads#0-*",   // must be in [0, MAX_THREADS]
+                    "|-nthreads#0-* "   // must be in [0, MAX_THREADS]
+                    "|-locales=",       // must be provided
                     &rw_opt_nloops,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads);
+                    &rw_opt_nthreads,
+                    &rw_opt_setlocales);
 }

Modified: incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.cpp?rev=580483&r1=580482&r2=580483&view=diff
==============================================================================
--- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.cpp (original)
+++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.cpp Fri Sep 28 13:55:52 2007
@@ -1428,6 +1428,286 @@
 #endif   // _RWSTD_NO_LONG_LONG
 }
 
+/**************************************************************************/
+
+// use a volatile variable to fool optimizers into not issuing
+// warnings about division by zero
+volatile double zero;
+
+
+template <class charT, class floatT>
+void inf_nan_test (charT, floatT, const char *cname, const char *tname)
+{
+    rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) formatting "
+             "infinities", cname, tname);
+
+    // compute infinity
+    const floatT inf = 1 / zero;
+
+    //////////////////////////////////////////////////////////////////
+    // exercise the formatting of positive and negative infinities
+
+    //        +-- value to format
+    //        |    +-- fmtflags
+    //        |    |                    +-- precision
+    //        |    |                    |  +-- field width
+    //        |    |                    |  |   +-- fill character
+    //        |    |                    |  |   |   +-- grouping
+    //        |    |                    |  |   |   |   +-- expected output
+    //        |    |                    |  |   |   |   |
+    //        V    V                    V  V   V   V   V
+    TEST (T,  inf, 0,                   0, 0, ' ', "", "inf");
+    TEST (T,  inf, showpos,             0, 0, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           0, 0, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 0, 0, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   0, 0, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             0, 0, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           0, 0, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 0, 0, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   1, 0, ' ', "", "inf");
+    TEST (T,  inf, showpos,             1, 0, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           1, 0, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 1, 0, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   1, 0, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             1, 0, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           1, 0, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 1, 0, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   3, 0, ' ', "", "inf");
+    TEST (T,  inf, showpos,             3, 0, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           3, 0, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 3, 0, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   3, 0, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             3, 0, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           3, 0, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 3, 0, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   4, 0, ' ', "", "inf");
+    TEST (T,  inf, showpos,             4, 0, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           4, 0, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 4, 0, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   4, 0, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             4, 0, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           4, 0, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 4, 0, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   9, 0, ' ', "", "inf");
+    TEST (T,  inf, showpos,             9, 0, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           9, 0, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 9, 0, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   9, 0, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             9, 0, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           9, 0, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 9, 0, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   0, 1, ' ', "", "inf");
+    TEST (T,  inf, showpos,             0, 1, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           0, 1, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 0, 1, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   0, 1, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             0, 1, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           0, 1, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 0, 1, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   0, 3, ' ', "", "inf");
+    TEST (T,  inf, showpos,             0, 3, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           0, 3, ' ', "", "INF");
+    TEST (T,  inf, showpos | uppercase, 0, 3, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   0, 3, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             0, 3, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           0, 3, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 0, 3, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   0, 4, ' ', "", " inf");
+    TEST (T,  inf, showpos,             0, 4, ' ', "", "+inf");
+    TEST (T,  inf, uppercase,           0, 4, ' ', "", " INF");
+    TEST (T,  inf, showpos | uppercase, 0, 4, ' ', "", "+INF");
+
+    TEST (T, -inf, 0,                   0, 4, ' ', "", "-inf");
+    TEST (T, -inf, showpos,             0, 4, ' ', "", "-inf");
+    TEST (T, -inf, uppercase,           0, 4, ' ', "", "-INF");
+    TEST (T, -inf, showpos | uppercase, 0, 4, ' ', "", "-INF");
+
+    TEST (T,  inf, 0,                   0, 8, ' ', "", "     inf");
+    TEST (T,  inf, showpos,             0, 8, ' ', "", "    +inf");
+    TEST (T,  inf, uppercase,           0, 8, ' ', "", "     INF");
+    TEST (T,  inf, showpos | uppercase, 0, 8, ' ', "", "    +INF");
+
+    TEST (T, -inf, 0,                   0, 8, ' ', "", "    -inf");
+    TEST (T, -inf, showpos,             0, 8, ' ', "", "    -inf");
+    TEST (T, -inf, uppercase,           0, 8, ' ', "", "    -INF");
+    TEST (T, -inf, showpos | uppercase, 0, 8, ' ', "", "    -INF");
+
+    TEST (T,  inf, left,                        0, 9, ' ', "", "inf      ");
+    TEST (T,  inf, left | showpos,              0, 9, ' ', "", "+inf     ");
+    TEST (T,  inf, left | uppercase,            0, 9, ' ', "", "INF      ");
+    TEST (T,  inf, left | showpos | uppercase,  0, 9, ' ', "", "+INF     ");
+
+    TEST (T, -inf, left,                        0, 9, ' ', "", "-inf     ");
+    TEST (T, -inf, left | showpos,              0, 9, ' ', "", "-inf     ");
+    TEST (T, -inf, left | uppercase,            0, 9, ' ', "", "-INF     ");
+    TEST (T, -inf, left | showpos | uppercase,  0, 9, ' ', "", "-INF     ");
+
+    TEST (T,  inf, right,                       0, 9, ' ', "", "      inf");
+    TEST (T,  inf, right | showpos,             0, 9, ' ', "", "     +inf");
+    TEST (T,  inf, right | uppercase,           0, 9, ' ', "", "      INF");
+    TEST (T,  inf, right | showpos | uppercase, 0, 9, ' ', "", "     +INF");
+
+    TEST (T, -inf, right,                       0, 9, ' ', "", "     -inf");
+    TEST (T, -inf, right | showpos,             0, 9, ' ', "", "     -inf");
+    TEST (T, -inf, right | uppercase,           0, 9, ' ', "", "     -INF");
+    TEST (T, -inf, right | showpos | uppercase, 0, 9, ' ', "", "     -INF");
+
+    //////////////////////////////////////////////////////////////////
+    // exercise the formatting of positive and negative (quiet) NaNs
+
+    rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) formatting "
+             "NaN's", cname, tname);
+
+    // compute a quiet NaN
+#if 0
+
+    // temporarily disabled (NAN format is platform specific
+    // and subject to bugs -- see for example STDCXX-460)
+
+    const floatT nan = 0 / zero;
+
+    TEST (T,  nan, 0,                   0, 0, ' ', "", "nan");
+    TEST (T,  nan, showpos,             0, 0, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           0, 0, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 0, 0, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   0, 0, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             0, 0, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           0, 0, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 0, 0, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   1, 0, ' ', "", "nan");
+    TEST (T,  nan, showpos,             1, 0, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           1, 0, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 1, 0, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   1, 0, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             1, 0, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           1, 0, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 1, 0, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   3, 0, ' ', "", "nan");
+    TEST (T,  nan, showpos,             3, 0, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           3, 0, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 3, 0, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   3, 0, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             3, 0, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           3, 0, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 3, 0, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   4, 0, ' ', "", "nan");
+    TEST (T,  nan, showpos,             4, 0, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           4, 0, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 4, 0, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   4, 0, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             4, 0, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           4, 0, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 4, 0, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   9, 0, ' ', "", "nan");
+    TEST (T,  nan, showpos,             9, 0, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           9, 0, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 9, 0, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   9, 0, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             9, 0, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           9, 0, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 9, 0, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   0, 1, ' ', "", "nan");
+    TEST (T,  nan, showpos,             0, 1, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           0, 1, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 0, 1, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   0, 1, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             0, 1, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           0, 1, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 0, 1, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   0, 3, ' ', "", "nan");
+    TEST (T,  nan, showpos,             0, 3, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           0, 3, ' ', "", "NAN");
+    TEST (T,  nan, showpos | uppercase, 0, 3, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   0, 3, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             0, 3, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           0, 3, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 0, 3, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   0, 4, ' ', "", " nan");
+    TEST (T,  nan, showpos,             0, 4, ' ', "", "+nan");
+    TEST (T,  nan, uppercase,           0, 4, ' ', "", " NAN");
+    TEST (T,  nan, showpos | uppercase, 0, 4, ' ', "", "+NAN");
+
+    TEST (T, -nan, 0,                   0, 4, ' ', "", "-nan");
+    TEST (T, -nan, showpos,             0, 4, ' ', "", "-nan");
+    TEST (T, -nan, uppercase,           0, 4, ' ', "", "-NAN");
+    TEST (T, -nan, showpos | uppercase, 0, 4, ' ', "", "-NAN");
+
+    TEST (T,  nan, 0,                   0, 5, ' ', "", "  nan");
+    TEST (T,  nan, showpos,             0, 5, ' ', "", " +nan");
+    TEST (T,  nan, uppercase,           0, 5, ' ', "", "  NAN");
+    TEST (T,  nan, showpos | uppercase, 0, 5, ' ', "", " +NAN");
+
+    TEST (T, -nan, 0,                   0, 5, ' ', "", " -nan");
+    TEST (T, -nan, showpos,             0, 5, ' ', "", " -nan");
+    TEST (T, -nan, uppercase,           0, 5, ' ', "", " -NAN");
+    TEST (T, -nan, showpos | uppercase, 0, 5, ' ', "", " -NAN");
+
+    TEST (T,  nan, 0,                   0, 8, ' ', "", "     nan");
+    TEST (T,  nan, showpos,             0, 8, ' ', "", "    +nan");
+    TEST (T,  nan, uppercase,           0, 8, ' ', "", "     NAN");
+    TEST (T,  nan, showpos | uppercase, 0, 8, ' ', "", "    +NAN");
+
+    TEST (T, -nan, 0,                   0, 8, ' ', "", "    -nan");
+    TEST (T, -nan, showpos,             0, 8, ' ', "", "    -nan");
+    TEST (T, -nan, uppercase,           0, 8, ' ', "", "    -NAN");
+    TEST (T, -nan, showpos | uppercase, 0, 8, ' ', "", "    -NAN");
+
+    TEST (T,  nan, left,                        0, 9, ' ', "", "nan      ");
+    TEST (T,  nan, left | showpos,              0, 9, ' ', "", "+nan     ");
+    TEST (T,  nan, left | uppercase,            0, 9, ' ', "", "NAN      ");
+    TEST (T,  nan, left | showpos | uppercase,  0, 9, ' ', "", "+NAN     ");
+
+    TEST (T, -nan, left,                        0, 9, ' ', "", "-nan     ");
+    TEST (T, -nan, left | showpos,              0, 9, ' ', "", "-nan     ");
+    TEST (T, -nan, left | uppercase,            0, 9, ' ', "", "-NAN     ");
+    TEST (T, -nan, left | showpos | uppercase,  0, 9, ' ', "", "-NAN     ");
+
+    TEST (T,  nan, right,                       0, 9, ' ', "", "      nan");
+    TEST (T,  nan, right | showpos,             0, 9, ' ', "", "     +nan");
+    TEST (T,  nan, right | uppercase,           0, 9, ' ', "", "      NAN");
+    TEST (T,  nan, right | showpos | uppercase, 0, 9, ' ', "", "     +NAN");
+
+    TEST (T, -nan, right,                       0, 9, ' ', "", "     -nan");
+    TEST (T, -nan, right | showpos,             0, 9, ' ', "", "     -nan");
+    TEST (T, -nan, right | uppercase,           0, 9, ' ', "", "     -NAN");
+    TEST (T, -nan, right | showpos | uppercase, 0, 9, ' ', "", "     -NAN");
+
+#else
+
+    rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) formatting "
+             "NaN's disabled due to platform bugs", cname, tname);
+
+#endif   // 0/1
+
+}
 
 /**************************************************************************/
 
@@ -1511,8 +1791,9 @@
         // reset the global locale
         std::setlocale (LC_NUMERIC, "C");
     }
-}
 
+    inf_nan_test (charT (), double (), cname, tname);
+}
 
 /**************************************************************************/
 
@@ -1680,6 +1961,8 @@
     TEST (T, Pi, scientific, 12, 0, ' ', "", "%.12Le", Eof, 3.14159265359L);
     TEST (T, Pi, scientific, -3, 0, ' ', "", "%Le");
     TEST (T, Pi, scientific, -7, 0, ' ', "", "%Le");
+
+    inf_nan_test (charT (), (long double)0, cname, tname);
 
 #endif   // _RWSTD_NO_LONG_DOUBLE
 }



Mime
View raw message