Return-Path: Delivered-To: apmail-incubator-stdcxx-commits-archive@www.apache.org Received: (qmail 21992 invoked from network); 28 Sep 2007 21:04:51 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 28 Sep 2007 21:04:51 -0000 Received: (qmail 16290 invoked by uid 500); 28 Sep 2007 21:04:33 -0000 Delivered-To: apmail-incubator-stdcxx-commits-archive@incubator.apache.org Received: (qmail 16276 invoked by uid 500); 28 Sep 2007 21:04:33 -0000 Mailing-List: contact stdcxx-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-commits@incubator.apache.org Received: (qmail 16260 invoked by uid 99); 28 Sep 2007 21:04:33 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 28 Sep 2007 14:04:33 -0700 X-ASF-Spam-Status: No, hits=-98.8 required=10.0 tests=ALL_TRUSTED,DNS_FROM_DOB,RCVD_IN_DOB X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 28 Sep 2007 21:04:41 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id A80191A988E; Fri, 28 Sep 2007 14:03:15 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r580483 [41/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 -0000 To: stdcxx-commits@incubator.apache.org From: sebor@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070928210315.A80191A988E@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.mt.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.mt.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.mt.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.num.put.mt.cpp Fri Sep 28 13:55:52 2007 @@ -33,24 +33,26 @@ #include // for strlen() #include -#include +#include // for rw_get_processors (), rw_thread_pool() #include +#include +#define MAX_THREADS 32 +#define MAX_LOOPS 100000 -// maximum number of threads allowed by the command line interface -#define MAX_THREADS 32 +// default number of threads (will be adjusted to the number +// of processors/cores later) +int rw_opt_nthreads = 1; +// the number of times each thread should iterate +int rw_opt_nloops = MAX_LOOPS; -#ifdef _RWSTD_REENTRANT -int rw_opt_nthreads = 4; -#else // if !defined (_RWSTD_REENTRANT) -// in non-threaded builds use just one thread -int rw_opt_nthreads = 1; -#endif // _RWSTD_REENTRANT +// number of locales to use +int rw_opt_nlocales = MAX_THREADS; -// the number of times each thread should iterate (unless specified -// otherwise on the command line) -int rw_opt_nloops = 200000; +// should all threads share the same set of locale objects instead +// of creating their own? +int rw_opt_shared_locale; /**************************************************************************/ @@ -62,99 +64,178 @@ static std::size_t nlocales; -/**************************************************************************/ -extern "C" { +struct MyNumData { -bool test_char; // exercise num_put -bool test_wchar; // exercise num_put + enum { BufferSize = 32 }; + enum PutId { + put_bool, + put_long, + put_ulong, -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; +#ifndef _RWSTD_NO_LONG_LONG -#ifndef _RWSTD_NO_WCHAR_T + put_llong, + put_ullong, - struct WideBuf: std::wstreambuf { - int_type overflow (int_type c) { return c; } - } wb; +#endif // _RWSTD_NO_LONG_LONG -#endif // _RWSTD_NO_WCHAR_T + put_dbl, - struct Ios: std::ios { - Ios () { this->init (0); } - } io; - - const std::ios::fmtflags baseflags[] = { - std::ios::oct, - std::ios::dec, - std::ios::hex - }; +#ifndef _RWSTD_NO_LONG_DOUBLE - const std::ios::fmtflags fmtflags[] = { - std::ios::showpos, - std::ios::showpoint, - std::ios::fixed, - std::ios::scientific - }; + put_ldbl, + +#endif // _RWSTD_NO_LONG_DOUBLE - const std::ios::fmtflags adjustflags[] = { - std::ios::internal, - std::ios::left, - std::ios::right + put_ptr, + put_max }; - for (int i = 0; i != rw_opt_nloops; ++i) { + // name of the locale the data corresponds to + const char* locale_name_; - // save the name of the locale - const char* const locale_name = locales [i % nlocales]; + // optionally set to the named locale for threads to share + std::locale locale_; - // construct a named locale and imbue it in the ios object - // so that the locale is used not only by the num_put facet - // but also by the numpunct facet - const std::locale loc (locale_name); - io.imbue (loc); - - enum PutId { - put_bool, - put_long, - put_ulong, + // the value that we will be formatting + double value_; + + // the type of the data we put + PutId type_; + + // holds the narrow/wide character representation of value_ and + // the number of used 'charT' in each buffer. + char ncs_ [BufferSize]; + +#ifndef _RWSTD_NO_WCHAR_T + + wchar_t wcs_ [BufferSize]; + +#endif // _RWSTD_NO_WCHAR_T + +} my_num_data [MAX_THREADS]; + +/**************************************************************************/ + +template +struct MyIos: std::basic_ios +{ + MyIos () { + this->init (0); + } +}; + +template +struct MyStreambuf: std::basic_streambuf +{ + typedef std::basic_streambuf Base; + + MyStreambuf () + : Base () { + } + + void pubsetp (charT *pbeg, std::streamsize n) { + this->setp (pbeg, pbeg + n); + } +}; + +template +void +put_data (const MyNumData &data, + const std::num_put &np, + const std::ostreambuf_iterator &iter, + std::basic_ios &io, + charT fill, + charT term) +{ + switch (data.type_) { + case MyNumData::put_bool: + *np.put (iter, io, fill, + data.value_ < 1.f) = term; + break; + case MyNumData::put_long: + *np.put (iter, io, fill, + (long)data.value_) = term; + break; + case MyNumData::put_ulong: + *np.put (iter, io, fill, + (unsigned long)data.value_) = term; + break; #ifndef _RWSTD_NO_LONG_LONG - put_llong, - put_ullong, + case MyNumData::put_llong: + *np.put (iter, io, fill, + (_RWSTD_LONG_LONG)data.value_) = term; + break; + case MyNumData::put_ullong: + *np.put (iter, io, fill, + (unsigned _RWSTD_LONG_LONG)data.value_) = term; + break; #endif // _RWSTD_NO_LONG_LONG - put_dbl, - put_ldbl, - put_ptr, - put_max - }; + case MyNumData::put_dbl: + *np.put (iter, io, fill, + (double)data.value_) = term; + + break; + +#ifndef _RWSTD_NO_LONG_DOUBLE + + case MyNumData::put_ldbl: + *np.put (iter, io, fill, + (long double)data.value_) = term; + break; + +#endif // _RWSTD_NO_LONG_DOUBLE + + case MyNumData::put_ptr: + *np.put (iter, io, fill, + (const void*)&data.value_) = term; + break; + + case MyNumData::put_max: + // avoid enumeration value `put_max' not handled in switch + // this case should never happen + break; + } + +} + +extern "C" { + +bool test_char; // exercise num_put +bool test_wchar; // exercise num_put - const std::ios::fmtflags base = - baseflags [i % (sizeof baseflags / sizeof *baseflags)]; - const std::ios::fmtflags fmt = - fmtflags [i % (sizeof baseflags / sizeof *baseflags)]; +static void* +thread_func (void*) +{ + char ncs [MyNumData::BufferSize]; + MyIos > nio; + MyStreambuf > nsb; + nio.rdbuf (&nsb); - const std::ios::fmtflags adjust = - adjustflags [i % (sizeof baseflags / sizeof *baseflags)]; +#ifndef _RWSTD_NO_WCHAR_T + wchar_t wcs [MyNumData::BufferSize]; + MyIos > wio; + MyStreambuf > wsb; + wio.rdbuf (&wsb); +#endif // _RWSTD_NO_WCHAR_T - io.flags (base | fmt | adjust); + for (int i = 0; i != rw_opt_nloops; ++i) { - io.width (i % 16); + // fill in the value and results for this locale + const MyNumData& data = my_num_data [i % nlocales]; - // exercise postive and negative values - const int ival = i & 1 ? -i : i; + // construct a named locale and imbue it in the ios object + // so that the locale is used not only by the num_put facet + const std::locale loc = + rw_opt_shared_locale ? data.locale_ + : std::locale (data.locale_name_); if (test_char) { // exercise the narrow char specialization of the facet @@ -162,50 +243,14 @@ const std::num_put &np = std::use_facet >(loc); - const std::ostreambuf_iterator iter (&sb); + nio.imbue (loc); + nsb.pubsetp (ncs, RW_COUNT_OF (ncs)); - switch (PutId (i % put_max)) { - case put_bool: - if (i & 2) - io.setf (std::ios::boolalpha); - else - io.unsetf (std::ios::boolalpha); - - np.put (iter, io, ' ', bool (ival)); - break; - - case put_long: - np.put (iter, io, ' ', long (ival)); - break; - - case put_ulong: - np.put (iter, io, ' ', (unsigned long)ival); - break; + put_data (data, np, std::ostreambuf_iterator(&nsb), + nio, ' ', '\0'); -#ifndef _RWSTD_NO_LONG_LONG - - case put_llong: - np.put (iter, io, ' ', (_RWSTD_LONG_LONG)ival); - break; - -#endif // _RWSTD_NO_LONG_LONG - - case put_ullong: - np.put (iter, io, ' ', (unsigned _RWSTD_LONG_LONG)ival); - break; - - case put_dbl: - np.put (iter, io, ' ', double (ival)); - break; - - case put_ldbl: - np.put (iter, io, ' ', (long double)ival); - break; - - case put_ptr: - np.put (iter, io, ' ', (void*)ival); - break; - } + RW_ASSERT (!nio.fail ()); + RW_ASSERT (!rw_strncmp (ncs, data.ncs_)); } // both specializations may be tested at the same time @@ -215,48 +260,17 @@ #ifndef _RWSTD_NO_WCHAR_T - const std::num_put &np = + const std::num_put &wp = std::use_facet >(loc); - const std::ostreambuf_iterator iter (&wb); + wio.imbue (loc); + wsb.pubsetp (wcs, RW_COUNT_OF (wcs)); - switch (PutId (i % put_max)) { - case put_bool: - np.put (iter, io, L' ', bool (ival)); - break; - - case put_long: - np.put (iter, io, L' ', long (ival)); - break; - - case put_ulong: - np.put (iter, io, L' ', (unsigned long)ival); - break; + put_data (data, wp, std::ostreambuf_iterator(&wsb), + wio, L' ', L'\0'); -#ifndef _RWSTD_NO_LONG_LONG - - case put_llong: - np.put (iter, io, L' ', (_RWSTD_LONG_LONG)ival); - break; - - case put_ullong: - np.put (iter, io, L' ', (unsigned _RWSTD_LONG_LONG)ival); - break; - -#endif // _RWSTD_NO_LONG_LONG - - case put_dbl: - np.put (iter, io, L' ', double (ival)); - break; - - case put_ldbl: - np.put (iter, io, L' ', (long double)ival); - break; - - case put_ptr: - np.put (iter, io, L' ', (void*)ival); - break; - } + RW_ASSERT (!wio.fail ()); + RW_ASSERT (!rw_strncmp (wcs, data.wcs_)); #endif // _RWSTD_NO_WCHAR_T @@ -270,26 +284,98 @@ /**************************************************************************/ + static int run_test (int, char**) { - char* const locale_list = rw_locales (); + MyIos > nio; + MyStreambuf > nsb; + nio.rdbuf (&nsb); + +#ifndef _RWSTD_NO_WCHAR_T + MyIos > wio; + MyStreambuf > 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 value and results for this locale + MyNumData& data = my_num_data [nlocales]; + data.locale_name_ = name; - const std::size_t maxinx = sizeof locales / sizeof *locales; + try { + const std::locale loc (data.locale_name_); - for (char *name = locale_list; *name; name += std::strlen (name) + 1) { - locales [nlocales++] = name; + data.value_ = nlocales & 1 ? -1 * nlocales : nlocales; + data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max); - if (nlocales == maxinx) + // format data into buffers + const std::num_put &np = + std::use_facet >(loc); + + nio.imbue (loc); + nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); + + put_data (data, np, std::ostreambuf_iterator(&nsb), + nio, ' ', '\0'); + + rw_fatal (!nio.fail (), __FILE__, __LINE__, + "num_put::put(...) failed for locale(%#s)", + data.locale_name_); + +#ifndef _RWSTD_NO_WCHAR_T + + const std::num_put &wp = + std::use_facet >(loc); + + wio.imbue (loc); + wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); + + put_data (data, wp, std::ostreambuf_iterator(&wsb), + wio, L' ', L'\0'); + + rw_fatal (!wio.fail (), __FILE__, __LINE__, + "num_put::put(...) failed for locale(%#s)", + data.locale_name_); + +#endif // _RWSTD_NO_WCHAR_T + + if (rw_opt_shared_locale) + data.locale_ = loc; + + nlocales += 1; + } + catch (...) { + rw_warn (!rw_opt_locales, 0, __LINE__, + "failed to create locale(%#s)", name); + } + + 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::num_put 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::num_put"); @@ -319,7 +405,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, @@ -345,12 +431,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.num.put", "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] + "|-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.numpunct.mt.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.numpunct.mt.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.numpunct.mt.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.numpunct.mt.cpp Fri Sep 28 13:55:52 2007 @@ -41,18 +41,21 @@ // 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; +// 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 @@ -67,18 +70,22 @@ struct NumPunctData { + const char* locale_name_; + std::locale locale_; + + std::string grouping_; + char decimal_point_; char thousands_sep_; - char grouping_ [32]; - char truename_ [32]; - char falsename_ [32]; + std::string truename_; + std::string falsename_; #ifndef _RWSTD_NO_WCHAR_T wchar_t wdecimal_point_; wchar_t wthousands_sep_; - wchar_t wtruename_ [32]; - wchar_t wfalsename_ [32]; + std::wstring wtruename_; + std::wstring wfalsename_; #endif // _RWSTD_NO_WCHAR_T @@ -98,16 +105,12 @@ const std::size_t inx = std::size_t (i) % nlocales; - // save the name of the locale - const char* const locale_name = locales [inx]; - - const NumPunctData* const data = punct_data + inx; + const NumPunctData& data = punct_data[inx]; // construct a named locale - const std::locale loc (locale_name); - - // exercise postive and negative values - const int ival = i & 1 ? -i : i; + 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 @@ -121,11 +124,14 @@ const std::string tn = np.truename (); const std::string fn = np.falsename (); - RW_ASSERT (dp == data->decimal_point_); - RW_ASSERT (ts == data->thousands_sep_); - RW_ASSERT (0 == rw_strncmp (grp.c_str (), data->grouping_)); - RW_ASSERT (0 == rw_strncmp (tn.c_str (), data->truename_)); - RW_ASSERT (0 == rw_strncmp (fn.c_str (), data->falsename_)); + RW_ASSERT (dp == data.decimal_point_); + RW_ASSERT (ts == data.thousands_sep_); + RW_ASSERT (0 == rw_strncmp (grp.c_str (), + data.grouping_.c_str ())); + RW_ASSERT (0 == rw_strncmp (tn.c_str (), + data.truename_.c_str ())); + RW_ASSERT (0 == rw_strncmp (fn.c_str (), + data.falsename_.c_str ())); } // both specializations may be tested at the same time @@ -135,20 +141,23 @@ #ifndef _RWSTD_NO_WCHAR_T - const std::numpunct &np = + const std::numpunct &wp = std::use_facet >(loc); - const wchar_t dp = np.decimal_point (); - const wchar_t ts = np.thousands_sep (); - const std::string grp = np.grouping (); - const std::wstring tn = np.truename (); - const std::wstring fn = np.falsename (); - - RW_ASSERT (dp == data->wdecimal_point_); - RW_ASSERT (ts == data->wthousands_sep_); - RW_ASSERT (0 == rw_strncmp (grp.c_str (), data->grouping_)); - RW_ASSERT (0 == rw_strncmp (tn.c_str (), data->wtruename_)); - RW_ASSERT (0 == rw_strncmp (fn.c_str (), data->wfalsename_)); + const wchar_t dp = wp.decimal_point (); + const wchar_t ts = wp.thousands_sep (); + const std::string grp = wp.grouping (); + const std::wstring tn = wp.truename (); + const std::wstring fn = wp.falsename (); + + RW_ASSERT (dp == data.wdecimal_point_); + RW_ASSERT (ts == data.wthousands_sep_); + RW_ASSERT (0 == rw_strncmp (grp.c_str (), + data.grouping_.c_str ())); + RW_ASSERT (0 == rw_strncmp (tn.c_str (), + data.wtruename_.c_str ())); + RW_ASSERT (0 == rw_strncmp (fn.c_str (), + data.wfalsename_.c_str ())); #endif // _RWSTD_NO_WCHAR_T @@ -165,64 +174,67 @@ 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); - const std::size_t maxinx = sizeof locales / sizeof *locales; + const std::size_t maxinx = sizeof punct_data / sizeof *punct_data; // 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; - locales [inx] = name; - // set LC_NUMERIC and LC_CTYPE to be able to use mbstowcs() - if (std::setlocale (LC_ALL, name)) { + NumPunctData& data = punct_data [inx]; + + try { + std::locale loc(name); + data.locale_name_ = name; - const std::lconv* const pconv = std::localeconv (); - NumPunctData* const pdata = punct_data + inx; + const std::numpunct &np = + std::use_facet >(loc); + + data.grouping_ = np.grouping (); - // 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->decimal_point; - pdata->thousands_sep_ = *pconv->thousands_sep; + data.decimal_point_ = np.decimal_point (); + data.thousands_sep_ = np.thousands_sep (); - // simply copy the narrow grouping - std::strcpy (pdata->grouping_, pconv->grouping); + data.truename_ = np.truename (); + data.falsename_ = np.falsename (); - // FIXME: this will need to change once useful truename - // and falsename has been implemented - std::strcpy (pdata->truename_, "true"); - std::strcpy (pdata->falsename_, "false"); +#ifndef _RWSTD_NO_WCHAR_T - wchar_t tmp [2]; + const std::numpunct &wp = + std::use_facet >(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->decimal_point, 2); - pdata->wdecimal_point_ = tmp [0]; + data.wdecimal_point_ = wp.decimal_point (); + data.wthousands_sep_ = wp.thousands_sep (); - std::mbstowcs (tmp, pconv->thousands_sep, 2); - pdata->wthousands_sep_ = tmp [0]; + data.wtruename_ = wp.truename (); + data.wfalsename_ = wp.falsename (); - const std::size_t n = - sizeof pdata->wtruename_ / sizeof (wchar_t); +#endif - std::mbstowcs (pdata->wtruename_, pdata->truename_, n); - std::mbstowcs (pdata->wfalsename_, pdata->falsename_, n); + if (rw_opt_shared_locale) + data.locale_ = loc; - ++nlocales; + 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; } - // reset the global locale - std::setlocale (LC_ALL, "C"); + // 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::numpunct with %d thread%{?}s%{;}, " @@ -286,12 +298,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.numpunct", "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] + "|-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.time.put.mt.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.time.put.mt.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.time.put.mt.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/localization/22.locale.time.put.mt.cpp Fri Sep 28 13:55:52 2007 @@ -32,28 +32,31 @@ #include // for ostreambuf_iterator #include // for locale, time_put -#include // for strlen() +#include // for strlen () #include // for tm #include #include -#include - +#include // for rw_assert () +#include // for rw_strncmp () #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 int rw_opt_nloops = MAX_LOOPS; +// 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 @@ -66,67 +69,93 @@ /**************************************************************************/ -extern "C" { +// +struct MyTimeData +{ + enum { BufferSize = 64 }; -bool test_char; // exercise time_put -bool test_wchar; // exercise time_put + // 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_; -static void* -thread_func (void *arg) + // the time struct used to generate strings below + std::tm time_; + + // the format specifier + char format_; + + // narrow representations of time_ given the + // locale_name_ and the format_ + char ncs_ [BufferSize]; + +#ifndef _RWSTD_NO_WCHAR_T + + // wide representations of time_ + wchar_t wcs_ [BufferSize]; + +#endif // _RWSTD_NO_WCHAR_T + +} my_time_data [MAX_THREADS]; + + +template +struct MyIos: std::basic_ios { - const rw_thread_t* const pthread = (rw_thread_t*)arg; + MyIos () { + this->init (0); + } +}; - // get the 0-based thread number - const std::size_t threadno = std::size_t (pthread->threadno); - std::tm tmb = std::tm (); +template +struct MyStreambuf: std::basic_streambuf +{ + typedef std::basic_streambuf Base; - const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%"; + MyStreambuf () + : Base () { + } - // 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; + void pubsetp (charT *pbeg, std::streamsize n) { + this->setp (pbeg, pbeg + n); + } +}; -#ifndef _RWSTD_NO_WCHAR_T - struct WideBuf: std::wstreambuf { - int_type overflow (int_type c) { return c; } - } wsb; +extern "C" { -#endif // _RWSTD_NO_WCHAR_T +bool test_char; // exercise time_put +bool test_wchar; // exercise time_put - struct Ios: std::ios { - Ios () { this->init (0); } - } io; - int j = 0; +static void* +thread_func (void*) +{ + char ncs [MyTimeData::BufferSize]; + MyIos > nio; + MyStreambuf > nsb; + nio.rdbuf (&nsb); - for (int i = 0; i != rw_opt_nloops; ++i, ++j) { +#ifndef _RWSTD_NO_WCHAR_T + wchar_t wcs [MyTimeData::BufferSize]; + MyIos > wio; + MyStreambuf > wsb; + wio.rdbuf (&wsb); +#endif // _RWSTD_NO_WCHAR_T - // initialize tm with random but valid values - tmb.tm_sec = ++j % 61; - tmb.tm_min = ++j % 60; - tmb.tm_min = ++j % 60; - tmb.tm_wday = ++j % 7; - tmb.tm_mon = ++j % 12; - tmb.tm_year = ++j; - - // generate a "random" conversion specifier from the set - // of valid specifiers recognized by the facet to exercise - // all (or most) code paths - const char cvt = cvtspecs [i % (sizeof cvtspecs - 1)]; + for (int i = 0; i != rw_opt_nloops; ++i) { // save the name of the locale - const char* const locale_name = locales [i % nlocales]; + const MyTimeData& data = my_time_data [i % nlocales]; // construct a named locale, get a reference to the time_put // facet from it and use it to format a random time value // using a random conversion specifier - const std::locale loc (locale_name); + 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 @@ -134,10 +163,15 @@ const std::time_put &tp = std::use_facet >(loc); - // format a "random" but valid tm value using the random - // format specifier - tp.put (std::ostreambuf_iterator(&sb), - io, ' ', &tmb, cvt); + nio.imbue (loc); + nsb.pubsetp (ncs, RW_COUNT_OF (ncs)); + + // format time using provided format specifier + *tp.put (std::ostreambuf_iterator(&nsb), + nio, ' ', &data.time_, data.format_) = '\0'; + + RW_ASSERT (!nio.fail ()); + RW_ASSERT (!rw_strncmp(ncs, data.ncs_)); } @@ -148,13 +182,19 @@ #ifndef _RWSTD_NO_WCHAR_T - const std::time_put &wtp = + const std::time_put &wp = std::use_facet >(loc); - wtp.put (std::ostreambuf_iterator(&wsb), - io, L' ', &tmb, cvt); + wio.imbue (loc); + wsb.pubsetp (wcs, RW_COUNT_OF (wcs)); -#endif // _RWSTD_NO_WCHAR_T + *wp.put (std::ostreambuf_iterator(&wsb), + wio, L' ', &data.time_, data.format_) = L'\0'; + + RW_ASSERT (!wio.fail ()); + RW_ASSERT (!rw_strncmp(wcs, data.wcs_)); + +#endif // _RWSTD_NO_WCHAR_T } } @@ -169,23 +209,110 @@ static int run_test (int, char**) { - char* const locale_list = rw_locales (); + MyIos > nio; + MyStreambuf > nsb; + nio.rdbuf (&nsb); + +#ifndef _RWSTD_NO_WCHAR_T + MyIos > wio; + MyStreambuf > 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 = sizeof locales / sizeof *locales; + const std::size_t maxinx = RW_COUNT_OF (locales); - for (char *name = locale_list; *name; name += std::strlen (name) + 1) { - locales [nlocales++] = name; + int j = 0; + for (const char* name = locale_list; + *name; + name += std::strlen (name) + 1) { + + const std::size_t inx = nlocales; + locales [inx] = name; + + // fill in the time and results for this locale + MyTimeData& data = my_time_data [inx]; + data.locale_name_ = name; + + // initialize tm with random but valid values + data.time_.tm_sec = ++j % 61; + data.time_.tm_min = ++j % 60; + data.time_.tm_hour = ++j % 12; + data.time_.tm_wday = ++j % 7; + data.time_.tm_mon = ++j % 12; + data.time_.tm_mday = ++j % 31; + data.time_.tm_yday = ++j % 366; + data.time_.tm_year = ++j; + + const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%"; + + // get the "random" conversion specifier used to generate + // the result string + data.format_ = cvtspecs [nlocales % (sizeof cvtspecs - 1)]; + + try { + const std::locale loc (data.locale_name_); + + const std::time_put &np = + std::use_facet >(loc); + + nio.imbue (loc); + nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); + + *np.put (std::ostreambuf_iterator(&nsb), + nio, ' ', &data.time_, data.format_) = '\0'; + + rw_fatal (!nio.fail (), __FILE__, __LINE__, + "time_put::put(..., %c) " + "failed for locale(%#s)", + data.format_, data.locale_name_); + +#ifndef _RWSTD_NO_WCHAR_T - if (nlocales == maxinx) + const std::time_put &wp = + std::use_facet >(loc); + + wio.imbue (loc); + wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); + + *wp.put (std::ostreambuf_iterator(&wsb), + wio, L' ', &data.time_, data.format_) = L'\0'; + + rw_fatal (!wio.fail (), __FILE__, __LINE__, + "time_put::put(..., %c) " + "failed for locale(%#s)", + data.format_, data.locale_name_); + +#endif // _RWSTD_NO_WCHAR_T + + if (rw_opt_shared_locale) + data.locale_ = loc; + + nlocales += 1; + + } + catch (...) { + rw_warn (!rw_opt_locales, 0, __LINE__, + "failed to create locale(%#s)", name); + } + + 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::time_put 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::time_put"); @@ -215,7 +342,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, @@ -241,12 +368,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.time.put", "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] + "|-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/self/0.char.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/self/0.char.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/self/0.char.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/self/0.char.cpp Fri Sep 28 13:55:52 2007 @@ -394,7 +394,7 @@ rw_assert (cdst == ret, 0, __LINE__, "rw_widen(char*, %{#s}%{?}, %zu%{;})", - src, i < nsrc); + src, i < nsrc, i); rw_assert (0 == memcmp (cdst, src, i) && '\0' == cdst [i], 0, __LINE__, @@ -638,7 +638,7 @@ rw_assert (cdst == ret, 0, __LINE__, "rw_narrow(char*, %{#s}%{?}, %zu%{;})", - src, i < nsrc); + src, i < nsrc, i); rw_assert (0 == memcmp (cdst, src, i) && '\0' == cdst [i], 0, __LINE__, Modified: incubator/stdcxx/branches/4.2.0/tests/self/0.new.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/self/0.new.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/self/0.new.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/self/0.new.cpp Fri Sep 28 13:55:52 2007 @@ -467,13 +467,14 @@ int run_test (int, char**) { -#define TEST(name) \ +#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE + +# define TEST(name) \ if (rw_opt_no_ ## name) \ rw_note (0, 0, __LINE__, "%s test disabled", #name); \ -else \ + else \ test_ ## name () - TEST (bad_alloc); TEST (mismatch); TEST (double_delete); @@ -482,11 +483,22 @@ TEST (leaks); TEST (stress); +#else // _RWSTD_NO_REPLACEABLE_NEW_DELETE + + rw_note (0, 0, __LINE__, "Test disabled"); + +#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE + return 0; } /**************************************************************************/ - +/* +void* operator new (size_t n) throw (std::bad_alloc) +{ + return 0; +} +*/ int main (int argc, char** argv) { return rw_test (argc, argv, __FILE__, Modified: incubator/stdcxx/branches/4.2.0/tests/self/0.printf.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/self/0.printf.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/self/0.printf.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/self/0.printf.cpp Fri Sep 28 13:55:52 2007 @@ -22,10 +22,14 @@ * implied. See the License for the specific language governing * permissions and limitations under the License. * - * Copyright 2005-2006 Rogue Wave Software. + * Copyright 2005-2007 Rogue Wave Software, Inc. * **************************************************************************/ +// tell Compaq C++ we need ENOMEM (defined by POSIX +// but not in the compiler's pure C++ libc headers) +#undef __PURE_CNAME + #include #include // for rw_pid_t #include // for rw_putenv() @@ -126,9 +130,9 @@ sprintf (fmt, "%s%c", pfx, spec); \ char* const s0 = rw_sprintfa (fmt, a1, a2, a3); \ char buf [256]; \ - /* variable below avoids warnings about controlling */ \ - /* expression being constant */ \ - const char* const expect_var = (expect); \ + /* non-const variable below avoids warnings about */ \ + /* controlling expression being constant */ \ + const char* /* const */ expect_var = (expect); \ if (expect_var) \ strcpy (buf, expect_var ? expect_var : ""); \ else \ @@ -763,7 +767,7 @@ TEST ("%{#1S}", S ("a\0\0"), 0, 0, "\"a\\0\\0\""); TEST ("%{#1S}", S ("\0\0\0"), 0, 0, "\"\\0\\0\\0\""); -#if 2 == _RWSTD_WCHAR_T_SIZE +#if 2 == _RWSTD_WCHAR_SIZE TEST ("%{#2S}", 0, 0, 0, "(null)"); TEST ("%{#2S}", WS (""), 0, 0, "L\"\""); @@ -777,7 +781,7 @@ TEST ("%{#2S}", WS ("a\0\0"), 0, 0, "L\"a\\0\\0\""); TEST ("%{#2S}", WS ("\0\0\0"), 0, 0, "L\"\\0\\0\\0\""); -#elif 4 == _RWSTD_WCHAR_T_SIZE +#elif 4 == _RWSTD_WCHAR_SIZE TEST ("%{#4S}", 0, 0, 0, "(null)"); TEST ("%{#4S}", WS (""), 0, 0, "L\"\""); @@ -791,7 +795,7 @@ TEST ("%{#4S}", WS ("a\0\0"), 0, 0, "L\"a\\0\\0\""); TEST ("%{#4S}", WS ("\0\0\0"), 0, 0, "L\"\\0\\0\\0\""); -#endif // _RWSTD_WCHAR_T_SIZE +#endif // _RWSTD_WCHAR_SIZE } @@ -2256,6 +2260,12 @@ printf ("%s\n", "extension: \"%{#m}\": errno"); int count = 0; + + errno = 0; + TEST ("%{#m}", 0, 0, 0, "E#0"); + + errno = 0; + TEST ("%{#*m}", 0, 0, 0, "E#0"); #ifdef EDOM Modified: incubator/stdcxx/branches/4.2.0/tests/self/0.process.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/self/0.process.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/self/0.process.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/self/0.process.cpp Fri Sep 28 13:55:52 2007 @@ -25,8 +25,11 @@ * **************************************************************************/ +// tell Compaq C++ we need POSIX errno constants that are otherwise +// guarded (not defined) in the compiler's pure C++ libc headers +#undef __PURE_CNAME +#include // for ENOENT, ECHILD, ESRCH, errno #include // for strcmp() -#include // for errno #include // for rw_process_create(), rw_waitpid() #include // for rw_test() Modified: incubator/stdcxx/branches/4.2.0/tests/src/char.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/char.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/char.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/char.cpp Fri Sep 28 13:55:52 2007 @@ -501,7 +501,7 @@ { // compute the length of src if not specified if (_RWSTD_SIZE_MAX == len) - len = src ? strlen (src) + 1 : 0; + len = src ? strlen (src) : 0; if (len) { RW_ASSERT (0 != dst); @@ -851,7 +851,7 @@ { // compute the length of src if not specified if (_RWSTD_SIZE_MAX == len) - len = src ? strlen (src) + 1 : 0; + len = src ? strlen (src) : 0; // if len is non-zero dst must be non-0 as well RW_ASSERT (0 == len || 0 != dst); @@ -999,7 +999,7 @@ { // compute the length of src if not specified if (_RWSTD_SIZE_MAX == len) - len = src ? strlen (src) + 1 : 0; + len = src ? strlen (src) : 0; // if len is non-zero dst must be non-0 as well RW_ASSERT (0 == len || 0 != dst); @@ -1287,7 +1287,7 @@ nbytes = rw_asnprintf (pbuf, pbufsize, "%{+}%{#*s}", nelems, beg.pc); } - else if (_RWSTD_WCHAR_T_SIZE == elemsize) { + else if (_RWSTD_WCHAR_SIZE == elemsize) { if (nelems < 0) nbytes = rw_asnprintf (pbuf, pbufsize, "%{+}%{#ls}", beg.pwc); else Modified: incubator/stdcxx/branches/4.2.0/tests/src/ctype.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/ctype.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/ctype.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/ctype.cpp Fri Sep 28 13:55:52 2007 @@ -829,9 +829,11 @@ break; } } + + return dfault; } - return dfault; + return ch; } @@ -1235,9 +1237,11 @@ break; } } + + return dfault; } - return dfault; + return char (uch); } @@ -1646,9 +1650,11 @@ break; } } + + return dfault; } - return dfault; + return char (uch); } Modified: incubator/stdcxx/branches/4.2.0/tests/src/driver.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/driver.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/driver.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/driver.cpp Fri Sep 28 13:55:52 2007 @@ -182,6 +182,12 @@ #ifndef RW_TEST_HARDWARE # if defined (__alpha__) || defined (__alpha) # define RW_TEST_ARCH "alpha" +# elif defined (__x86_64__) || defined (__x86_64) +# if defined (__LP64__) || defined (_LP64) +# define RW_TEST_ARCH "x86_64/LP64" +# else +# define RW_TEST_ARCH "x86_64/ILP32" +# endif # elif defined (__amd64__) || defined (__amd64) # if defined (__LP64__) || defined (_LP64) # define RW_TEST_ARCH "amd64/LP64" @@ -240,12 +246,6 @@ # define RW_TEST_ARCH "ia64" # elif defined (_WIN32) # define RW_TEST_ARCH "i86" -# elif defined (__x86_64__) || defined (__x86_64) -# if defined (__LP64__) || defined (_LP64) -# define RW_TEST_ARCH "x86_64/LP64" -# else -# define RW_TEST_ARCH "x86_64/ILP32" -# endif # else # define RW_TEST_ARCH "unknown" # endif @@ -276,23 +276,15 @@ # elif defined (__sgi) && defined (__mips) # define RW_TEST_OS "irix" # elif defined (__linux__) || defined (__linux) - - // get Linux release string (UTS_RELEASE) -# include - -# ifndef UTS_RELEASE -# define UTS_RELEASE "(unknown release)" -# endif // UTS_RELEASE - # if defined (__ELF__) # define LINUX_TYPE "linux-elf" # else # define LINUX_TYPE "linux" # endif -# define RW_TEST_OS LINUX_TYPE " " \ - UTS_RELEASE " with glibc " \ - RW_TEST_STR (__GLIBC__) "." \ +# define RW_TEST_OS LINUX_TYPE " (" \ + _RWSTD_LINUX_RELEASE ") with glibc " \ + RW_TEST_STR (__GLIBC__) "." \ RW_TEST_STR (__GLIBC_MINOR__) # elif defined (__SunOS_5_10) Modified: incubator/stdcxx/branches/4.2.0/tests/src/fmt_bits.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/fmt_bits.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/fmt_bits.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/fmt_bits.cpp Fri Sep 28 13:55:52 2007 @@ -48,6 +48,10 @@ # include // for iswalpha(), ... #endif // _RWSTD_NO_WCTYPE_H +#ifdef _WIN32 +# include // for FormatMessage() +#endif // _WIN32 + #include #include #include @@ -1000,6 +1004,42 @@ newspec.fl_pound = 0; return _rw_fmtstr (newspec, buf, str, _RWSTD_SIZE_MAX); +} + +/********************************************************************/ + +/* extern */ int +_rw_fmtlasterror (const FmtSpec &spec, Buffer &buf, int val) +{ +#ifdef _WIN32 + + LPVOID pmsg; + FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, (DWORD)val, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&pmsg, + 0, 0); + + FmtSpec newspec (spec); + newspec.width = 0; + newspec.fl_pound = 0; + + const int result = _rw_fmtstr (newspec, buf, + _RWSTD_STATIC_CAST (const char*, pmsg), + _RWSTD_SIZE_MAX); + + LocalFree (pmsg); + + return result; + +#else // if !defined (_WIN32) + + return _rw_fmterrno (spec, buf, val); + +#endif // _WIN32 + } /********************************************************************/ Modified: incubator/stdcxx/branches/4.2.0/tests/src/fmt_defs.h URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/fmt_defs.h?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/fmt_defs.h (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/fmt_defs.h Fri Sep 28 13:55:52 2007 @@ -186,6 +186,10 @@ extern int _rw_fmterrno (const FmtSpec&, Buffer&, int); +// format Windows GetLastError(), or errno value/name +extern int +_rw_fmtlasterror (const FmtSpec&, Buffer&, int); + // format the name/value of an LC_XXX constant/environment variable extern int _rw_fmtlc (const FmtSpec&, Buffer&, int); Modified: incubator/stdcxx/branches/4.2.0/tests/src/locale.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/locale.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/locale.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/locale.cpp Fri Sep 28 13:55:52 2007 @@ -22,7 +22,7 @@ * implied. See the License for the specific language governing * permissions and limitations under the License. * - * Copyright 2001-2006 Rogue Wave Software. + * Copyright 2001-2007 Rogue Wave Software. * **************************************************************************/ @@ -34,10 +34,8 @@ #include // for rw_putenv() #include // for SHELL_RM_RF, rw_tmpnam -#include // for rw_fprintf() #include // for rw_system() -#include - +#include // for rw_error() #if defined (_RWSTD_OS_LINUX) && !defined (_XOPEN_SOURCE) // on Linux define _XOPEN_SOURCE to get CODESET defined in @@ -62,9 +60,7 @@ #include // for money_base::pattern #include // for assert -#include // for EBADF -#include // for {FLT,DBL,LDBL}_DIG -#include // for CHAR_BIT, MB_LEN_MAX, PATH_MAX +#include // for PATH_MAX #include // for LC_XXX macros, setlocale #include // for va_copy, va_list, ... #include // for fgets, remove, sprintf, ... @@ -73,10 +69,6 @@ #include #include // for wcslen, ... -#ifndef PATH_MAX -# define PATH_MAX 1024 -#endif - #ifndef _MSC_VER # include # ifndef LC_MESSAGES @@ -89,6 +81,13 @@ #endif // _MSC_VER +#if !defined (PATH_MAX) || PATH_MAX < 128 || 4096 < PATH_MAX + // deal with undefined, bogus, or excessive values +# undef PATH_MAX +# define PATH_MAX 1024 +#endif + + #define TOPDIR "TOPDIR" /* the TOPDIR environment variable */ #define BINDIR "BINDIR" /* the BINDIR environment variable */ @@ -109,13 +108,20 @@ #define RELPATH "etc" SLASH "nls" #define TESTS_ETC_PATH "tests" SLASH "etc" +// extension of the catalog file +#ifndef _WIN32 +# define RW_CAT_EXT ".cat" +#else +# define RW_CAT_EXT ".dll" +#endif + /**************************************************************************/ _TEST_EXPORT int rw_locale (const char *args, const char *fname) { // use BINDIR to determine the location of the locale command - const char* bindir = getenv ("BINDIR"); + const char* bindir = getenv (BINDIR); if (!bindir) bindir = ".." SLASH "bin"; @@ -202,13 +208,14 @@ // use TOPDIR to determine the root of the source tree const char* const topdir = getenv (TOPDIR); if (!topdir || !*topdir) { - fprintf (stderr, "%s:%d: the environment variable %s is %s\n", - __FILE__, __LINE__, TOPDIR, topdir ? "empty" : "undefined"); + rw_error (0, __FILE__, __LINE__, + "the environment variable %s is %s", + TOPDIR, topdir ? "empty" : "undefined"); return 0; } // use BINDIR to determine the location of the localedef command - const char* bindir = getenv ("BINDIR"); + const char* bindir = getenv (BINDIR); if (!bindir) bindir = ".." SLASH "bin"; @@ -272,7 +279,7 @@ extern "C" { -static char rw_locale_root [256]; +static char rw_locale_root [PATH_MAX]; static void atexit_rm_locale_root () { @@ -318,8 +325,8 @@ // where std::locale looks for locale database files rw_putenv (envvar); - if (atexit (atexit_rm_locale_root)) - perror ("atexit(atexit_rm_locale_root) failed"); + rw_error (0 == atexit (atexit_rm_locale_root), __FILE__, __LINE__, + "atexit(atexit_rm_locale_root) failed: %m"); return locale_root; } @@ -327,8 +334,9 @@ /**************************************************************************/ _TEST_EXPORT char* -rw_locales (int loc_cat, const char* grep_exp) +rw_locales (int loc_cat, const char* grep_exp, bool prepend_c_loc) { + static char deflocname [3] = "C\0"; static char* slocname = 0; static size_t size = 0; // the number of elements in the array @@ -360,7 +368,7 @@ char* locname = slocname; char* save_localename = 0; - char namebuf [256]; + char namebuf [PATH_MAX]; if (loc_cat != _UNUSED_CAT) { // copy the locale name, the original may be overwitten by libc @@ -370,7 +378,7 @@ const char* const fname = rw_tmpnam (0); if (!fname) { - return 0; // error + return deflocname; // error } // make sure that grep_exp is <= 80 @@ -385,7 +393,7 @@ : rw_system ("locale -a > %s", fname); if (exit_status) { - return 0; // error + return deflocname; // error } // open file containing the list of installed locales @@ -401,15 +409,33 @@ char last_name [256]; *last_name = '\0'; + // put the C locale at the front + if (prepend_c_loc) { + strcpy (locname, deflocname); + locname += strlen (deflocname) + 1; + } + // if successful, construct a char array with the locales while (fgets (linebuf, sizeof linebuf, file)) { - linebuf [strlen (linebuf) - 1] = '\0'; + const size_t linelen = strlen (linebuf); + + linebuf [linelen ? linelen - 1 : 0] = '\0'; + + // don't allow C locale to be in the list again + // if we put it at the front of the locale list + if (prepend_c_loc && !strcmp (linebuf, deflocname)) + continue; #ifdef _RWSTD_OS_SUNOS - // avoid the bad locale named iso_8859_1 on SunOS - if (!strcmp ("iso_8859_1", linebuf)) + const char iso_8859_pfx[] = "iso_8859_"; + + // avoid locales named common and iso_8859_* on SunOS + // since they are known to cause setlocale() to fail + if ( !strcmp ("common", linebuf) + || sizeof iso_8859_pfx <= linelen + && !memcmp (iso_8859_pfx, linebuf, sizeof iso_8859_pfx - 1)) continue; #endif // _RWSTD_OS_SUNOS @@ -422,7 +448,12 @@ _RWSTD_STATIC_CAST (char*, malloc (total_size)); memcpy (tmp, slocname, total_size - 5120); + +#ifndef _MSC_VER free (slocname); +#else + _free_dbg (slocname, _CLIENT_BLOCK); +#endif slocname = tmp; locname = slocname + size - strlen (linebuf) - 1; @@ -470,7 +501,7 @@ remove (fname); - return slocname; + return *slocname ? slocname : deflocname; } /**************************************************************************/ @@ -508,7 +539,7 @@ *buf = '\0'; } -#if 2 < _RWSTD_WCHAR_T_SIZE +#if 2 < _RWSTD_WCHAR_SIZE // if a multibyte character of the requested size is not found // in the low 64K range, try to find one using a random search @@ -551,12 +582,11 @@ const char* mbc = _get_mb_char (mb_chars [0], size_t (-1)); - if (!mbc) { - rw_fprintf (rw_stderr, "*** failed to find any multibyte characters " - "in locale \"%s\" with MB_CUR_MAX = %u\n", - setlocale (LC_CTYPE, 0), MB_CUR_MAX); + if (0 == rw_note (0 != mbc, __FILE__, __LINE__, + "failed to find any multibyte characters " + "in locale \"%s\" with MB_CUR_MAX = %u", + setlocale (LC_CTYPE, 0), MB_CUR_MAX)) return 0; - } size_t mb_cur_max = strlen (mbc); @@ -571,10 +601,13 @@ mbc = _get_mb_char (mb_chars [i - 1], i); if (0 == mbc) { - if (i < mb_cur_max) { - rw_fprintf (rw_stderr, "*** failed to find %u-byte characters " - "in locale \"%s\" with MB_CUR_MAX = %u\n", - i + 1, setlocale (LC_CTYPE, 0), MB_CUR_MAX); + // zh_CN.gb18030 and zh_TW.euctw on Linux are examples + // of multibyte locales where MB_CUR_MAX == 4 but, + // apparently, no 3-byte characters + if (0 == rw_note (mb_cur_max <= i, __FILE__, __LINE__, + "failed to find %u-byte characters " + "in locale \"%s\" with MB_CUR_MAX = %u", + i, setlocale (LC_CTYPE, 0), MB_CUR_MAX)) { mb_cur_max = 0; break; } @@ -586,6 +619,67 @@ } +_TEST_EXPORT size_t +rw_get_wchars (wchar_t *wbuf, size_t bufsize, int nbytes /* = 0 */) +{ + if (0 == bufsize) + return 0; + + char tmp [_RWSTD_MB_LEN_MAX]; + + size_t nchars = 0; + + for (int i = 0; i != 65536; ++i) { + + // determine whether the wide character is valid + // and if so, the length of the multibyte character + // that corresponds to it + const int len = wctomb (tmp, wchar_t (i)); + + if (nbytes == 0 && 0 < len || nbytes != 0 && nbytes == len) { + // if the requested length is 0 (i.e., the caller doesn't + // care) and the character is valid, store it + // if the requested length is non-zero (including -1), + // and the value returned from mblen() is the same, store + // it (this makes it possible to find invalid characters + // as well as valid ones) + wbuf [nchars++]; + if (nchars == bufsize) + return nchars; + } + } + +#if 2 < _RWSTD_WCHAR_SIZE + + // try to find the remaining wide characters by a random + // search, iterating only so many times to prevent an + // infinite loop + for (int i = 0; i != 0x100000; ++i) { + + // make a wide character with a random bit pattern + wchar_t wc = wchar_t (rand ()); + + if (RAND_MAX < 0x10000) { + wc <<= 16; + wc |= wchar_t (rand ()); + } + + const int len = wctomb (tmp, wchar_t (i)); + + if (nbytes == 0 && 0 < len || nbytes != 0 && nbytes == len) { + wbuf [nchars++]; + if (nchars == bufsize) + return nchars; + } + } + +#endif // 2 < _RWSTD_WCHAR_SIZE + + return nchars; + +} + + _TEST_EXPORT const char* rw_find_mb_locale (size_t *mb_cur_max, rw_mbchar_array_t mb_chars) @@ -594,8 +688,8 @@ _RWSTD_ASSERT (0 != mb_chars); if (2 > _RWSTD_MB_LEN_MAX) { - rw_fprintf (rw_stderr, "MB_LEN_MAX = %d, giving up\n", - _RWSTD_MB_LEN_MAX); + rw_warn (0, __FILE__, __LINE__, "MB_LEN_MAX = %d, giving up", + _RWSTD_MB_LEN_MAX); return 0; } @@ -631,9 +725,10 @@ } if (*mb_cur_max < 2) { - rw_fprintf (rw_stderr, "*** failed to find a full set of multibyte " - "characters in locale \"%s\" with MB_CUR_MAX = %u " - "(computed)", mb_locale_name, *mb_cur_max); + rw_warn (0, __FILE__, __LINE__, + "failed to find a full set of multibyte " + "characters in locale \"%s\" with MB_CUR_MAX = %u " + "(computed)", mb_locale_name, *mb_cur_max); mb_locale_name = 0; } else { @@ -671,36 +766,36 @@ // create a temporary locale definition file that exercises as // many different parts of the collate standard as possible - char srcfname [256]; - std::sprintf (srcfname, "%s%slocale.src", locale_root, SLASH); + char srcfname [PATH_MAX]; + sprintf (srcfname, "%s%slocale.src", locale_root, SLASH); - std::FILE *fout = std::fopen (srcfname, "w"); + FILE *fout = fopen (srcfname, "w"); if (!fout) { - std::fprintf (stderr, "%s:%d: fopen(\"%s\", \"w\") failed\n", - __FILE__, __LINE__, srcfname); + rw_error (0, __FILE__, __LINE__, + "fopen(#%s, \"w\") failed: %m", srcfname); return 0; } - std::fprintf (fout, "%s", locale); + fprintf (fout, "%s", locale); - std::fclose (fout); + fclose (fout); // create a temporary character map file - char cmfname [256]; - std::sprintf (cmfname, "%s%scharmap.src", locale_root, SLASH); + char cmfname [PATH_MAX]; + sprintf (cmfname, "%s%scharmap.src", locale_root, SLASH); - fout = std::fopen (cmfname, "w"); + fout = fopen (cmfname, "w"); if (!fout) { - std::fprintf (stderr, "%s:%d: fopen(\"%s\", \"w\") failed\n", - __FILE__, __LINE__, cmfname); + rw_error (0, __FILE__, __LINE__, + "fopen(%#s, \"w\") failed: %m", cmfname); return 0; } - std::fprintf (fout, "%s", charmap); + fprintf (fout, "%s", charmap); - std::fclose (fout); + fclose (fout); locname = "test-locale"; @@ -709,4 +804,116 @@ locname = 0; return locname; +} + + +/**************************************************************************/ + +static const char* +_rw_locale_names; + +_TEST_EXPORT const char* const& +rw_opt_locales = _rw_locale_names; + + +_TEST_EXPORT int +rw_opt_setlocales (int argc, char* argv[]) +{ + if (1 == argc && argv && 0 == argv [0]) { + static const char helpstr[] = { + "Use the locales specified by the space-parated list of locale" + "names given by .\n" + }; + + argv [0] = _RWSTD_CONST_CAST (char*, helpstr); + + return 0; + } + + // the option requires an equals sign followed by an optional argument + char *args = strchr (argv [0], '='); + + RW_ASSERT (0 != args); + + // small static buffer should be sufficient in most cases + static char buffer [256]; + + const size_t len = strlen (++args); + + // dynamically allocate a bigger buffer when the small buffer + // isn't big enough (let the dynamically allocated buffer leak) + char* const locale_names = + sizeof buffer < len + 2 ? (char*)malloc (len + 2) : buffer; + + if (0 == locale_names) + return 1; + + locale_names [len] = '\0'; + locale_names [len + 1] = '\0'; + + memcpy (locale_names, args, len); + + for (char *next = locale_names; ; ) { + next = strpbrk (next, ", "); + if (next) + *next++ = '\0'; + else + break; + } + + _rw_locale_names = locale_names; + + // return 0 on success + return 0; +} + + +/**************************************************************************/ + +_TEST_EXPORT int +rw_create_catalog (const char * catname, const char * catalog) +{ + RW_ASSERT (catname && catalog); + + FILE* const f = fopen (catname, "w"); + + if (!f) + return -1; + +#ifndef _WIN32 + + for (int i = 1; *catalog; ++catalog, ++i) { + fprintf (f, "$set %d This is Set %d\n", i, i); + for (int j = 1; *catalog; catalog += strlen (catalog) + 1, ++j) + fprintf (f, "%d %s\n", j, catalog); + } + +#else // if defined (_WIN32) + + fprintf (f, "STRINGTABLE\nBEGIN\n"); + + for (int i = 1; *catalog; ++catalog) { + for (; *catalog; catalog += strlen (catalog) + 1, ++i) + fprintf (f, "%d \"%s\"\n", i, catalog); + } + + fprintf (f, "END\n"); + +#endif // _WIN32 + + fclose (f); + + char *cat_name = new char [strlen (catname) + 1]; + strcpy (cat_name, catname); + if (char *dot = strrchr (cat_name, '.')) + *dot = '\0'; + + const int ret = rw_system ("gencat %s" RW_CAT_EXT " %s", + cat_name, catname); + + delete[] cat_name; + + remove (catname); + + return ret; } Modified: incubator/stdcxx/branches/4.2.0/tests/src/printf.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/printf.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/printf.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/printf.cpp Fri Sep 28 13:55:52 2007 @@ -57,7 +57,7 @@ // define macros to enable Win98 + WinNT support in # define _WIN32_WINNT 0x0410 # define WINVER 0x400 -# include // for IsDebuggerPresent() +# include // for GetLastError(), IsDebuggerPresent() #else # include #endif // _WIN{32,64} @@ -1843,25 +1843,25 @@ template int _rw_quotechar (char *buf, charT wc, int noesc) { -#if _RWSTD_WCHAR_T_MIN < 0 +#if _RWSTD_WCHAR_MIN < 0 // wchar_t is signed, convert its value to unsigned long // without widening (i.e., treat it as an unsigned type) -# if _RWSTD_WCHAR_T_MIN == _RWSTD_SHRT_MIN +# if _RWSTD_WCHAR_MIN == _RWSTD_SHRT_MIN const ULong wi = UShrt (wc); -# elif _RWSTD_WCHAR_T_MIN ==_RWSTD_INT_MIN +# elif _RWSTD_WCHAR_MIN ==_RWSTD_INT_MIN const ULong wi = UInt (wc); -# elif _RWSTD_WCHAR_T_MIN == _RWSTD_LONG_MIN +# elif _RWSTD_WCHAR_MIN == _RWSTD_LONG_MIN const ULong wi = ULong (wc); # endif -#else // if _RWSTD_WCHAR_T_MIN >= 0 +#else // if _RWSTD_WCHAR_MIN >= 0 // wchar_t is unsigned const ULong wi = ULong (wc); -#endif // _RWSTD_WCHAR_T_MIN < 0 +#endif // _RWSTD_WCHAR_MIN < 0 if ((1 == sizeof wc || wi < 0x100) && noesc) { buf [0] = char (wc); @@ -1978,7 +1978,7 @@ // wchar_t (bot not for an array of wchar_t's being // formatted using the {%ls} directive -- the caller // can easily stick the 'L' there themselves) - if (flags & A_ARRAY && _RWSTD_WCHAR_T_SIZE == sizeof (elemT)) + if (flags & A_ARRAY && _RWSTD_WCHAR_SIZE == sizeof (elemT)) *next++ = 'L'; *next++ = '"'; @@ -2067,7 +2067,7 @@ if (last_repeat < 0) { if (flags & (A_CHAR | A_WCHAR)) { if ( (flags & A_ARRAY) - && _RWSTD_WCHAR_T_SIZE == sizeof (elemT)) + && _RWSTD_WCHAR_SIZE == sizeof (elemT)) *s++ = 'L'; // insert an opening quote @@ -2694,6 +2694,15 @@ } break; + case 'E': // %{E} -- Windows GetLastError(), errno elsewhere +#ifdef _WIN32 + spec.param.int_ = -1 == spec.width ? GetLastError () : spec.width; +#else // if !defined (_WIN32) + spec.param.int_ = -1 == spec.width ? errno : spec.width; +#endif // _WIN32 + len = _rw_fmtlasterror (spec, buf, spec.param.int_); + break; + case 'e': // %{e}, %{Ae} if (spec.mod == spec.mod_ext_A) { // array of floating point values spec.param.ptr_ = PARAM (ptr_, pva); @@ -2771,7 +2780,8 @@ break; case 'm': // %{m} -- errno - len = _rw_fmterrno (spec, buf, -1 == spec.width ? errno : spec.width); + spec.param.int_ = -1 == spec.width ? errno : spec.width; + len = _rw_fmterrno (spec, buf, spec.param.int_); break; case 'M': // %{M}, %{LM} @@ -3329,7 +3339,7 @@ va_end (va); if (-1 < nchars) - memcpy (buf, tmpbuf, size_t (nchars)); + memcpy (buf, tmpbuf, size_t (nchars + 1 /* NUL */)); free (tmpbuf); Modified: incubator/stdcxx/branches/4.2.0/tests/src/process.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/process.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/process.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/process.cpp Fri Sep 28 13:55:52 2007 @@ -27,10 +27,6 @@ // expand _TEST_EXPORT macros #define _RWSTD_TEST_SRC -// disable Compaq/HP C++ pure libc headers to allow POSIX symbols -// such as E2BIG to be defined -#undef __PURE_CNAME - #include #include // for isspace() Modified: incubator/stdcxx/branches/4.2.0/tests/src/thread.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/src/thread.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/src/thread.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/src/thread.cpp Fri Sep 28 13:55:52 2007 @@ -33,6 +33,13 @@ #include // for size_t #include // for memset() +#ifndef _WIN32 +# include // for FILE, fscanf(), popen() +# include // for sysconf(), _SC_NPROCESSORS_{CONF,ONLN} +#else +# include // for GetSystemInfo() +#endif // _WIN32 + /**************************************************************************/ static long maxthreads; @@ -167,13 +174,6 @@ extern "C" { -# ifdef __PURE_CNAME - -extern int sigsetjmp (jmp_buf, int); - -# endif - - _TEST_EXPORT int rw_thread_create (rw_thread_t *thr_id, rw_thread_attr_t*, @@ -240,8 +240,8 @@ /**************************************************************************/ -#elif defined (_WIN32) || defined (_WIN64) -# include +#elif defined (_WIN32) && defined (_MT) +# include // for _beginthreadex() extern "C" { @@ -258,34 +258,33 @@ if (0 == thr_id) thr_id = &tmpid; - DWORD nid; // numerical id - - typedef DWORD ThreadProc (LPVOID); + unsigned nid; // numerical id - LPTHREAD_START_ROUTINE win32_thr_proc = - _RWSTD_REINTERPRET_CAST (LPTHREAD_START_ROUTINE, thr_proc); + typedef unsigned int (__stdcall *win32_thr_proc_t)(void *); + win32_thr_proc_t win32_thr_proc = + _RWSTD_REINTERPRET_CAST (win32_thr_proc_t, thr_proc); // set the thread number *before* creating the thread // so that it's visible in thr_proc when it starts to // run even before CreateThread returns thr_id->threadno = maxthreads; - const HANDLE hthread = - CreateThread (0, // lpThreadAttributes - 0, // dwStackSize - win32_thr_proc, // lpStartAddress - thr_arg, // lpParameter - 0, // dwCreationFlags - &nid); // lpThreadId + const uintptr_t hthread = + _beginthreadex (0, // lpThreadAttributes + 0, // dwStackSize + win32_thr_proc, // lpStartAddress + thr_arg, // lpParameter + 0, // dwCreationFlags + &nid); // lpThreadId - if (INVALID_HANDLE_VALUE == hthread) { + if (!hthread) { thr_id->id = -1; thr_id->handle = 0; result = -1; } else { thr_id->id = nid; - thr_id->handle = hthread; + thr_id->handle = _RWSTD_REINTERPRET_CAST (void*, hthread); ++maxthreads; } @@ -369,22 +368,132 @@ #endif // threads environment +/**************************************************************************/ + +// retrieves the number of processors/cores on the system +_TEST_EXPORT int +rw_get_cpus () +{ +#ifndef _WIN32 + + const char* const cmd = { + // shell command(s) to obtain the number of processors + +# ifdef _RWSTD_OS_AIX + // AIX: /etc/lsdev -Cc processor | wc -l + "/etc/lsdev -Cc processor | /usr/bin/wc -l" +# elif defined (_RWSTD_OS_LINUX) + // Linux: cat /proc/cpuinfo | grep processor | wc -l + "cat /proc/cpuinfo " + " | grep processor " + " | wc -l" +# elif defined (_RWSTD_OS_FREEBSD) + // FreeBSD: /sbin/sysctl -n hw.ncpu + "/sbin/sysctl -n hw.ncpu" +# elif defined (_RWSTD_OS_HP_UX) + // HP-UX: /etc/ioscan -k -C processor | grep processor | wc -l + "/etc/ioscan -k -C processor " + " | /usr/bin/grep processor " + " | /usr/bin/wc -l" +# elif defined (_RWSTD_OS_IRIX64) + // IRIX: hinv | /usr/bin/grep "^[1-9][0-9]* .* Processor" + "/sbin/hinv " + " | /usr/bin/grep \"^[1-9][0-9]* .* Processor\"" +# elif defined (_RWSTD_OS_OSF1) + // Tru64 UNIX: /usr/sbin/psrinfo | grep online | wc -l + "/usr/sbin/psrinfo " + " | /usr/bin/grep on[-]*line " + " | /usr/bin wc -l" +# elif defined (_RWSTD_OS_SUNOS) + // Solaris: /usr/bin/mpstat | wc -l + "/usr/bin/mpstat " + " | /usr/bin/grep -v \"^CPU\" " + " | /usr/bin/wc -l" +# else + 0 +# endif + + }; + + int ncpus = -1; + +# ifdef _SC_NPROCESSORS_ONLN + // try to obtain the number of processors that are currently online + // programmatically and fall back on the shell script above if it + // fails + ncpus = int (sysconf (_SC_NPROCESSORS_ONLN)); + +# elif defined (_SC_NPROCESSORS_CONF) + + // try to obtain the number of processors the system is configured + // with (not all of them are necessarily online) programmatically + // and fall back on the shell script above if it fails + ncpus = int (sysconf (_SC_NPROCESSORS_CONF)); + +# endif // _SC_NPROCESSORS_CONF + + if (ncpus < 1 && cmd) { + // if the number of processors couldn't be determined using + // sysconf() above, open and read the output of the command + // from a pipe + FILE* const fp = popen (cmd, "r"); + + if (fp) { + int tmp = 0; + + int n = fscanf (fp, "%d", &tmp); + + if (1 == n) + ncpus = tmp; + + fclose (fp); + } + } + + return ncpus; + +#else // _WIN32 + + SYSTEM_INFO info; + GetSystemInfo (&info); + return int (info.dwNumberOfProcessors); + +#endif // _WIN32 +} + +/**************************************************************************/ extern "C" { _TEST_EXPORT int -rw_thread_pool (rw_thread_t *thr_id, size_t nthrs, +rw_thread_pool (rw_thread_t *thr_id, + size_t nthrs, rw_thread_attr_t*, - void* (*thr_proc)(void*), - void **thr_arg) + void* (*thr_proc)(void*), + void* *thr_arg) { // small buffer for thread ids when invoked with (thr_id == 0) rw_thread_t id_buf [16]; const bool join = 0 == thr_id; -#ifndef _RWSTD_REENTRANT +#ifdef _RWSTD_REENTRANT + + if (_RWSTD_SIZE_MAX == nthrs) { + // when the number of threads is -1 use the number + // of processors plus 1 (in case it's 1 to begin + // with) + + const int ncpus = rw_get_cpus (); + + if (0 < ncpus) + nthrs = size_t (ncpus) + 1; + else + nthrs = 2; + } + +#else // when not reentrant/thread safe emulate the creation // of a single thread and then waiting for it to finish @@ -408,7 +517,6 @@ return 0; } - #endif // !_RWSTD_REENTRANT bool delete_ids = false; Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.cwchar.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.cwchar.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.cwchar.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.cwchar.cpp Fri Sep 28 13:55:52 2007 @@ -87,10 +87,6 @@ /**************************************************************************/ -#ifdef _MSC_VER -#include // for _CrtSetReportMode() -#endif - #include #include // for rw_any_t #include // for rw_test(), ... @@ -822,6 +818,11 @@ GET_TYPE_NAME (unsigned long); GET_TYPE_NAME (double); +#ifndef _RWSTD_NO_LONG_LONG +GET_TYPE_NAME (_RWSTD_LONG_LONG); +GET_TYPE_NAME (unsigned _RWSTD_LONG_LONG); +#endif + #ifndef _RWSTD_NO_NATIVE_WCHAR_T GET_TYPE_NAME (wchar_t); #endif @@ -926,16 +927,16 @@ const test_tm* tmb = (const test_tm*)&tm_buf; #ifdef _MSC_VER - // disable GUI window with error: - // Assertion failed: ("Zero length output buffer passed to strftime",0) - int oldmode = _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_DEBUG); + // prevent MSVC parameter validation error: + // "Zero length output buffer passed to strftime" + size = 1; #endif TEST (test_size_t, wcsftime, (wstr, size, L"", tmb), WCSFTIME, -1); #ifdef _MSC_VER - // restore error report mode - _CrtSetReportMode (_CRT_ASSERT, oldmode); + // restore size + size = 0; #endif TEST (test_wint_t, btowc, (i), BTOWC, -1); Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.string.access.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.string.access.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.string.access.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.string.access.cpp Fri Sep 28 13:55:52 2007 @@ -266,10 +266,12 @@ return; } - const char exp_res = - NPOS != tcase.nres ? char (tcase.nres) : char (); + const char exp_res [2] = { + NPOS != tcase.nres ? char (tcase.nres) : char (), + char () + }; - const bool success = 1 == rw_match (&exp_res, pres, 1); + const bool success = 1 == rw_match (exp_res, pres, 1); rw_assert (success, 0, tcase.line, "line %d. %{$FUNCALL} == %{#c}, got %{#c}", Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.string.cons.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.string.cons.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.string.cons.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.string.cons.cpp Fri Sep 28 13:55:52 2007 @@ -699,11 +699,11 @@ break; case Cons (size_val): - ret_ptr = new String (tcase.size, arg_val); + ret_ptr = new String (arg_size, arg_val); break; case Cons (size_val_alloc): - ret_ptr = new String (tcase.size, arg_val, arg_alc); + ret_ptr = new String (arg_size, arg_val, arg_alc); break; case Cons (range): Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.string.copy.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.string.copy.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.string.copy.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.string.copy.cpp Fri Sep 28 13:55:52 2007 @@ -187,11 +187,12 @@ std::size_t res = 0; // create destination array and initialize it with garbage - charT* const s_res = new charT [min_len + 1]; + charT* const s_res = new charT [min_len + 2]; - char cgb = '#'; - charT wcgb = make_char (cgb, (charT*)0); + const char cgb [2] = "#"; + const charT wcgb = make_char (cgb [0], (charT*)0); Traits::assign (s_res, min_len + 1, wcgb); + s_res [min_len + 1] = charT (); // save the state of the string object before the call // to detect wxception safety violations (changes to @@ -247,7 +248,7 @@ __LINE__, int (tcase.nres), tcase.res, int (sizeof (charT)), int (res), s_res, match); - success = 1 == rw_match (&cgb, &s_res [min_len], 1); + success = 1 == rw_match (cgb, s_res + min_len, 1); rw_assert (success, 0, tcase.line, "line %d. %{$FUNCALL} detected writing past the end of " "the provided buffer", __LINE__); Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.not.of.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.not.of.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.not.of.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.not.of.cpp Fri Sep 28 13:55:52 2007 @@ -396,14 +396,7 @@ TEST ("abcdefghij", "abc", 10, 3, NPOS, 0), TEST ("abcdefghij", "cba", 10, 1, NPOS, 0), -#ifndef _RWSTD_NO_EXCEPTIONS - - TEST ("", "cba", 0, -1, 0, 1), - TEST ("abcdefghij", "cba", 0, -1, 0, 1), - TEST ("x@4096", "xxx", 0, -1, 0, 1), - TEST ("abcdefghij", "x@4096", 0, -1, 0, 1), - -#endif // _RWSTD_NO_EXCEPTIONS + TEST ("", "cba", 0, -1, NPOS, 0), TEST ("last test", "test", 0, 4, 0, 0) }; Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.of.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.of.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.of.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.first.of.cpp Fri Sep 28 13:55:52 2007 @@ -404,10 +404,10 @@ TEST ("abcdefghij", "abc", 10, 3, NPOS, 0), TEST ("abcdefghij", "cba", 10, 1, NPOS, 0), - TEST ("", "cba", 0, -1, 0, 1), - TEST ("abcdefghij", "cba", 0, -1, 0, 1), - TEST ("x@4096", "xxx", 0, -1, 0, 1), - TEST ("abcdefghij", "x@4096", 0, -1, 0, 1), + TEST ("", "cba", 0, -1, NPOS, 0), + TEST ("abcdefghij", "cba", 0, -1, 0, 0), + TEST ("x@4096", "xxx", 0, -1, 0, 0), + TEST ("abcdefghij", "ax@4096", 0, -1, 0, 0), TEST ("last test", "test", 0, 4, 2, 0) }; Modified: incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.last.not.of.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.last.not.of.cpp?rev=580483&r1=580482&r2=580483&view=diff ============================================================================== --- incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.last.not.of.cpp (original) +++ incubator/stdcxx/branches/4.2.0/tests/strings/21.string.find.last.not.of.cpp Fri Sep 28 13:55:52 2007 @@ -404,10 +404,7 @@ TEST ("defghijabc", "abc", 15, 3, 6, 0), TEST ("defghijabc", "cba", 15, 1, 8, 0), - TEST ("", "cba", 0, -1, 0, 1), - TEST ("abcdefghij", "cba", 0, -1, 0, 1), - TEST ("x@4096", "xxx", 0, -1, 0, 1), - TEST ("abcdefghij", "x@4096", 0, -1, 0, 1), + TEST ("", "cba", 0, -1, NPOS, 0), TEST ("last test", "test", 9, 4, 4, 0) };