Return-Path: Delivered-To: apmail-incubator-stdcxx-commits-archive@www.apache.org Received: (qmail 80433 invoked from network); 14 Feb 2007 02:34:03 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 14 Feb 2007 02:34:03 -0000 Received: (qmail 34819 invoked by uid 500); 14 Feb 2007 02:34:11 -0000 Delivered-To: apmail-incubator-stdcxx-commits-archive@incubator.apache.org Received: (qmail 34796 invoked by uid 500); 14 Feb 2007 02:34:10 -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 34785 invoked by uid 99); 14 Feb 2007 02:34:10 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Feb 2007 18:34:10 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME 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; Tue, 13 Feb 2007 18:34:01 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id A0E461A981A; Tue, 13 Feb 2007 18:33:41 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r507360 - in /incubator/stdcxx/trunk/tests: self/0.printf.cpp src/printf.cpp Date: Wed, 14 Feb 2007 02:33:41 -0000 To: stdcxx-commits@incubator.apache.org From: sebor@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070214023341.A0E461A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sebor Date: Tue Feb 13 18:33:40 2007 New Revision: 507360 URL: http://svn.apache.org/viewvc?view=rev&rev=507360 Log: 2007-02-13 Martin Sebor * src/printf.cpp (_rw_fmtnested): New function to handle nested formatting directives (%{@} et al) extended to format arrays of values of arbitrary types, including structures. (VarArgs): New stuct to encapsulate variable arguments and arrays. (VA_ARG): New macro to extract arguments from VarArgs. (_rw_fmtinteger, _rw_vasnprintf_ext, _rw_fmtspec): Used VarArgs. (PARAM): Changed it to use VarArgs. * test/printf.cpp (test_nested_format): Exercised the above. Modified: incubator/stdcxx/trunk/tests/self/0.printf.cpp incubator/stdcxx/trunk/tests/src/printf.cpp Modified: incubator/stdcxx/trunk/tests/self/0.printf.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/self/0.printf.cpp?view=diff&rev=507360&r1=507359&r2=507360 ============================================================================== --- incubator/stdcxx/trunk/tests/self/0.printf.cpp (original) +++ incubator/stdcxx/trunk/tests/self/0.printf.cpp Tue Feb 13 18:33:40 2007 @@ -100,7 +100,7 @@ } fprintf (stderr, "# Assertion failed on line %d: " - "rw_sprintf(%c%s%c, ...) == %c%s%c got %c%s%c\n", + "rw_printf(%c%s%c, ...) == %c%s%c got %c%s%c\n", line, q_fmt [0], fmt, q_fmt [1], q_expect [0], expect, q_expect [1], q_result [0], result, q_result [1]); @@ -135,7 +135,7 @@ ++nfailures; \ fprintf (stderr, \ "# Assertion failed on line %d: " \ - "rw_sprintf(\"%s\", %ld, %ld, %ld) " \ + "rw_printf(\"%s\", %ld, %ld, %ld) " \ "== \"%s\", got \"%s\"\n", \ __LINE__, fmt, \ (long)a1, (long)a2, (long)a3, buf, s0); \ @@ -2827,6 +2827,58 @@ TEST ("A%{@}C%{@}E", "B", "%s", "D", "ABCDE"); TEST ("ABC%sGHI%{@}XYZ", "DEF", "%s%1$s", "JKL", "ABCDEFGHIJKLJKLXYZ"); + + // exercise arrays + + TEST ("%{.0@}", "%i", 0, 0, ""); + TEST ("%{.1@}", "%i", 1, 0, "1"); + TEST ("%{.2@}", "%i", 2, 3, "23"); + + TEST ("%{ .0@}", "%i", 3, 0, ""); + TEST ("%{ .1@}", "%i", 4, 5, "4"); + TEST ("%{ .2@}", "%i", 5, 6, "5 6"); + TEST ("[ %{.2@}]", "%i ", 6, 7, "[ 6 7 ]"); + + const int ia[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + // + // +---- (width: ???) + // | +-- precision: number of elements in array + // | | + // v v + TEST ("%{.0A@}", "%i", ia, 0, ""); + TEST ("%{.1A@}", "%i", ia, 0, "9"); + TEST ("%{.2A@}", "%i", ia, 0, "98"); + TEST ("%{.3A@}", "%i", ia, 0, "987"); + TEST ("%{.4A@}", "%i", ia, 0, "9876"); + TEST ("%{.5A@}", "%i", ia, 0, "98765"); + TEST ("%{.6A@}", "%i", ia, 0, "987654"); + TEST ("%{.7A@}", "%i", ia, 0, "9876543"); + TEST ("%{.8A@}", "%i", ia, 0, "98765432"); + TEST ("%{.9A@}", "%i", ia, 0, "987654321"); + TEST ("%{.*A@}", 10, "%i", ia, "9876543210"); + TEST ("[%{ .*A@}]", 9, "%i", ia, "[9 8 7 6 5 4 3 2 1]"); + TEST ("[%{ .*A@}]", 8, "%i", ia, "[9 8 7 6 5 4 3 2]"); + TEST ("[%{ .*A@}]", 7, "%i", ia, "[9 8 7 6 5 4 3]"); + TEST ("[%{ .*A@}]", 6, "%i", ia, "[9 8 7 6 5 4]"); + TEST ("[%{ .*A@}]", 5, "%i", ia, "[9 8 7 6 5]"); + TEST ("[%{ .*A@}]", 4, "%i", ia, "[9 8 7 6]"); + TEST ("[%{ .*A@}]", 3, "%i", ia, "[9 8 7]"); + TEST ("[%{ .*A@}]", 2, "%i", ia, "[9 8]"); + TEST ("[%{ .*A@}]", 1, "%i", ia, "[9]"); + TEST ("[%{ .*A@}]", 0, "%i", ia, "[]"); + + static const struct { + size_t i; const char *s; + } sa[] = { + { 1, "foo" }, { 2, "bar" }, { 3, "foobar" } + }; + + // members must be packed with no padding + RW_ASSERT (sizeof *sa == sizeof sa->i + sizeof sa->s); + + TEST ("{%{ .*A@}}", 3, "(%i, %#s)", sa, + "{(1, \"foo\") (2, \"bar\") (3, \"foobar\")}"); } /***********************************************************************/ Modified: incubator/stdcxx/trunk/tests/src/printf.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/printf.cpp?view=diff&rev=507360&r1=507359&r2=507360 ============================================================================== --- incubator/stdcxx/trunk/tests/src/printf.cpp (original) +++ incubator/stdcxx/trunk/tests/src/printf.cpp Tue Feb 13 18:33:40 2007 @@ -102,8 +102,24 @@ #endif // _RWSTD_LONG_LONG +struct VarArgs { + union { + va_list *pva_; + const void *pargs_; + } arg_; + + enum { + VA_list, VA_array + } kind_; +}; + +#define VA_ARG(va, T) \ + (VarArgs::VA_list == (va).kind_ ? va_arg (*(va).arg_.pva_, T) \ + : *((const T*&)(va).arg_.pargs_)++) + + static int -_rw_fmtinteger (FmtSpec*, size_t, Buffer&, va_list*); +_rw_fmtinteger (FmtSpec*, size_t, Buffer&, VarArgs*); static int _rw_fmtfloating (const FmtSpec&, Buffer&, const void*); @@ -140,11 +156,15 @@ // format an expression (parameter/environment variable) static int -_rw_fmtexpr (FmtSpec&, Buffer&, va_list*); +_rw_fmtexpr (FmtSpec&, Buffer&, VarArgs*); + +// format a nested parametrized directive (%{@}, %{*.*@}, etc.) +static int +_rw_fmtnested (const FmtSpec&, Buffer&, const char*, VarArgs*); // format an extension static int -_rw_vasnprintf_ext (FmtSpec*, size_t, Buffer&, const char*, va_list*); +_rw_vasnprintf_ext (FmtSpec*, size_t, Buffer&, const char*, VarArgs*); /********************************************************************/ @@ -181,7 +201,7 @@ */ static int -_rw_fmtspec (FmtSpec *pspec, bool ext, const char *fmt, va_list *pva) +_rw_fmtspec (FmtSpec *pspec, bool ext, const char *fmt, VarArgs *pva) { RW_ASSERT (0 != pspec); RW_ASSERT (0 != fmt); @@ -276,7 +296,7 @@ fmt = end; } else if ('*' == *fmt) { - pspec->base = va_arg (*pva, int); + pspec->base = VA_ARG (*pva, int); ++fmt; } @@ -292,7 +312,7 @@ fmt = end; } else if ('*' == *fmt) { - pspec->width = va_arg (*pva, int); + pspec->width = VA_ARG (*pva, int); if (pspec->width < 0) { // 7.19.6.1, p5 of ISO/IEC 9899:1999: @@ -317,7 +337,7 @@ fmt = end; } else if ('*' == *fmt) { - pspec->prec = va_arg (*pva, int); + pspec->prec = VA_ARG (*pva, int); ++fmt; } } @@ -490,7 +510,7 @@ _rw_vasnprintf_c99 (FmtSpec *pspec, // array of processed parameters size_t paramno, // index of current parameter Buffer &buf, - va_list *pva) // parameter list + VarArgs *pva) // parameter list { _RWSTD_UNUSED (paramno); @@ -500,9 +520,13 @@ FmtSpec &spec = pspec [paramno]; -#define PARAM(name) \ - (0 < spec.paramno ? pspec [spec.paramno - 1].param.name \ - : va_arg (*pva, FmtSpec::name ## t)) +// retreve paramater either from the argument list (or array), +// or from the array of previously saved parameters in the case +// of a positional parameter +#define PARAM(name, pva) \ + (0 < spec.paramno \ + ? pspec [spec.paramno - 1].param.name \ + : VA_ARG (*pva, FmtSpec::name ## t)) switch (spec.cvtspec) { @@ -523,11 +547,11 @@ case 'g': case 'G': if (spec.mod == spec.mod_L) { - spec.param.ldbl_ = PARAM (ldbl_); + spec.param.ldbl_ = PARAM (ldbl_, pva); len = _rw_fmtfloating (spec, buf, &spec.param.ldbl_); } else { - spec.param.dbl_ = PARAM (dbl_); + spec.param.dbl_ = PARAM (dbl_, pva); len = _rw_fmtfloating (spec, buf, &spec.param.dbl_); } break; @@ -551,24 +575,24 @@ // character. if (spec.mod == spec.mod_l) { // wint_t argument formatted as wchar_t (no escapes) - spec.param.wint_ = PARAM (wint_); + spec.param.wint_ = PARAM (wint_, pva); len = _rw_fmtwchr (spec, buf, spec.param.wint_, 1); } else { // int argument formatted as char (no escapes) - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtchr (spec, buf, spec.param.int_, 1); } break; case 's': if (spec.mod == spec.mod_l) { - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const wchar_t* const str = (wchar_t*)spec.param.ptr_; len = _rw_fmtwstr (spec, buf, str, _RWSTD_SIZE_MAX); } else { - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const char* const str = (char*)spec.param.ptr_; len = _rw_fmtstr (spec, buf, str, _RWSTD_SIZE_MAX); } @@ -578,7 +602,7 @@ // The argument shall be a pointer to void. The value of the pointer // is converted to a sequence of printing characters, in an // implementation-defined manner. - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); len = _rw_fmtptr (spec, buf, spec.param.ptr_); break; } @@ -603,7 +627,7 @@ // len = int (strlen (*buf.pbuf)); len = buf.endoff; - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); if (spec.mod == spec.mod_hh) { UChar* const ptr = (UChar*)spec.param.ptr_; @@ -665,7 +689,7 @@ // implements rw_vasnprintf, but may be called recursively static int -_rw_pvasnprintf (Buffer &buf, const char *fmt, va_list *pva) +_rw_pvasnprintf (Buffer &buf, const char *fmt, VarArgs *pva) { // save the length of the initial subsequence already // in the buffer @@ -982,7 +1006,11 @@ } // format buffer w/o appending terminating NUL - const int len = _rw_pvasnprintf (buf, fmt, pva); + VarArgs args; + args.kind_ = VarArgs::VA_list; + args.arg_.pva_ = pva; + + const int len = _rw_pvasnprintf (buf, fmt, &args); // append terminating NUL if (len < 0 || !_rw_bufcat (buf, "", 1)) { @@ -1220,7 +1248,7 @@ /********************************************************************/ static int -_rw_fmtinteger (FmtSpec *pspec, size_t paramno, Buffer &buf, va_list *pva) +_rw_fmtinteger (FmtSpec *pspec, size_t paramno, Buffer &buf, VarArgs *pva) { int len = -1; @@ -1228,7 +1256,7 @@ switch (spec.cvtspec) { case 'b': // extension: int argument formatted as bool - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtstr (spec, buf, spec.param.int_ ? "true" : "false", _RWSTD_SIZE_MAX); @@ -1238,27 +1266,27 @@ case 'i': if (spec.mod == spec.mod_hh) { // promoted signed char argument - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const signed char val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (spec.mod == spec.mod_h) { // promoted signed short argument - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const short val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (spec.mod == spec.mod_l) { // %li - spec.param.long_ = PARAM (long_); + spec.param.long_ = PARAM (long_, pva); len = rw_fmtinteger (spec, buf, spec.param.long_); } else if (spec.mod == spec.mod_ll) { // %lli #ifdef _RWSTD_LONG_LONG - spec.param.llong_ = PARAM (llong_); + spec.param.llong_ = PARAM (llong_, pva); len = rw_fmtinteger (spec, buf, spec.param.llong_); #elif 8 == _RWSTD_LONG_SIZE - spec.param.long_ = PARAM (long_); + spec.param.long_ = PARAM (long_, pva); len = rw_fmtinteger (spec, buf, spec.param.long_); #else RW_ASSERT (!"%lld, %lli: long long not supported"); @@ -1266,28 +1294,28 @@ #endif // _RWSTD_LONG_LONG } else if (spec.mod == spec.mod_t) { - spec.param.diff_ = PARAM (diff_); + spec.param.diff_ = PARAM (diff_, pva); len = rw_fmtinteger (spec, buf, spec.param.diff_); } else if (1 == spec.iwidth) { - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const _RWSTD_INT8_T val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (2 == spec.iwidth) { - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const _RWSTD_INT16_T val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (3 == spec.iwidth) { - spec.param.i32_ = PARAM (i32_); + spec.param.i32_ = PARAM (i32_, pva); const long val = long (spec.param.i32_); len = rw_fmtinteger (spec, buf, val); } else if (4 == spec.iwidth) { #ifdef _RWSTD_INT64_T - spec.param.i64_ = PARAM (i64_); + spec.param.i64_ = PARAM (i64_, pva); #else // if !defined (_RWSTD_INT64_T) RW_ASSERT (!"%I64d, %I64i: 64-bit types not supported"); #endif // _RWSTD_INT64_T @@ -1303,7 +1331,7 @@ #endif } else { // %i - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = rw_fmtinteger (spec, buf, spec.param.int_); } break; @@ -1325,23 +1353,23 @@ case 'u': if (spec.mod == spec.mod_hh) { // promoted unsigned char argument - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const UChar val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (spec.mod == spec.mod_h) { // promoted unsigned short argument - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const UShrt val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (spec.mod == spec.mod_ll) { #ifdef _RWSTD_LONG_LONG - spec.param.llong_ = PARAM (llong_); + spec.param.llong_ = PARAM (llong_, pva); const unsigned _RWSTD_LONG_LONG val = spec.param.llong_; len = rw_fmtinteger (spec, buf, val); #elif 8 == _RWSTD_LONG_SIZE - spec.param.long_ = PARAM (long_); + spec.param.long_ = PARAM (long_, pva); const ULong val = spec.param.long_; len = rw_fmtinteger (spec, buf, val); #else @@ -1350,32 +1378,32 @@ } else if (spec.mod == spec.mod_l) { - spec.param.long_ = PARAM (long_); + spec.param.long_ = PARAM (long_, pva); const ULong val = spec.param.long_; len = rw_fmtinteger (spec, buf, val); } else if (spec.mod == spec.mod_t) { - spec.param.size_ = PARAM (size_); + spec.param.size_ = PARAM (size_, pva); len = rw_fmtinteger (spec, buf, spec.param.size_); } else if (1 == spec.iwidth) { - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const _RWSTD_UINT8_T val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } else if (2 == spec.iwidth) { - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const long val = UShrt (spec.param.int_); len = rw_fmtinteger (spec, buf, val); } else if (3 == spec.iwidth) { - spec.param.i32_ = PARAM (i32_); + spec.param.i32_ = PARAM (i32_, pva); const long val = long (unsigned (spec.param.int_)); len = rw_fmtinteger (spec, buf, val); } else if (4 == spec.iwidth) { #ifdef _RWSTD_INT64_T - spec.param.i64_ = PARAM (i64_); + spec.param.i64_ = PARAM (i64_, pva); #else // if defined 9_RWSTD_INT64_T) RW_ASSERT (!"%I64o, %I64u, %I64x: 64-bit types not supported"); #endif // _RWSTD_INT64_T @@ -1391,7 +1419,7 @@ #endif } else { - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); const unsigned val = spec.param.int_; len = rw_fmtinteger (spec, buf, val); } @@ -2161,7 +2189,7 @@ /********************************************************************/ static int -_rw_fmtarray (FmtSpec *pspec, size_t paramno, Buffer &buf, va_list *pva) +_rw_fmtarray (FmtSpec *pspec, size_t paramno, Buffer &buf, VarArgs *pva) { RW_ASSERT (0 != pspec); @@ -2191,7 +2219,7 @@ // precision the number of elements (when negative the array is taken // to extend up to but not including the first 0 element) if (-1 == width || 1 == width) { - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const _RWSTD_UINT8_T* const array = (_RWSTD_UINT8_T*)spec.param.ptr_; // note that when no precision is specified in the format string // (e.g., "%{Ac}") its value will be -1 and the function will format @@ -2199,12 +2227,12 @@ len = _rw_fmtarray (spec, buf, array, nelems, flags); } else if (2 == width) { - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const _RWSTD_UINT16_T* const array = (_RWSTD_UINT16_T*)spec.param.ptr_; len = _rw_fmtarray (spec, buf, array, nelems, flags); } else if (4 == width) { - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const _RWSTD_UINT32_T* const array = (_RWSTD_UINT32_T*)spec.param.ptr_; len = _rw_fmtarray (spec, buf, array, nelems, flags); } @@ -2212,7 +2240,7 @@ #ifdef _RWSTD_UINT64_T else if (8 == width) { - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const _RWSTD_UINT64_T* const array = (_RWSTD_UINT64_T*)spec.param.ptr_; len = _rw_fmtarray (spec, buf, array, nelems, flags); } @@ -2487,7 +2515,7 @@ size_t paramno, Buffer &buf, const char *fmt, - va_list *pva) + VarArgs *pva) { RW_ASSERT (0 != pva); RW_ASSERT (0 != pspec); @@ -2519,8 +2547,8 @@ else { // pass the address of the variable argument list // followed by the address of the current parameter - len = (_rw_usr_fun [i])(buf.pbuf, buf.pbufsize, fmt, pva, - &spec.param); + len = (_rw_usr_fun [i])(buf.pbuf, buf.pbufsize, fmt, + pva->arg_.pva_, &spec.param); } // special value indicating that the user-defined function @@ -2542,7 +2570,7 @@ // set a user-defined formatting function if (spec.fl_plus) { // push a new user-defined handler on top of the stack - spec.param.funptr_ = PARAM (funptr_); + spec.param.funptr_ = PARAM (funptr_, pva); _rw_usr_fun [_rw_usr_inx++] = (_rw_usr_cb_t*)spec.param.funptr_; } if (spec.fl_minus) { @@ -2556,7 +2584,7 @@ if (0 == _rw_usr_inx) ++_rw_usr_inx; - spec.param.funptr_ = PARAM (funptr_); + spec.param.funptr_ = PARAM (funptr_, pva); _rw_usr_fun [_rw_usr_inx - 1] = (_rw_usr_cb_t*)spec.param.funptr_; } @@ -2564,16 +2592,16 @@ break; case '@': { // %{@} - // user-defined formatting string - spec.param.ptr_ = PARAM (ptr_); + // parametrized (nested) formatting directive + spec.param.ptr_ = PARAM (ptr_, pva); const char* const tmp_fmt = (const char*)spec.param.ptr_; - len = _rw_pvasnprintf (buf, tmp_fmt, pva); + len = _rw_fmtnested (spec, buf, tmp_fmt, pva); break; } case '?': // %{?} // beginning of an if clause - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); spec.cond = 1; spec.cond_begin = 1; spec.cond_true = 0 != spec.param.int_; @@ -2611,7 +2639,7 @@ case 'B': // %{B} // std::bitset - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); if ( 0 == spec.param.ptr_ || 0 > _RW::__rw_memattr (spec.param.ptr_, spec.prec, -1)) len = _rw_fmtbadaddr (spec, buf, spec.param.ptr_, sizeof (long)); @@ -2620,7 +2648,7 @@ break; case 'b': // %{b} - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); if ( 0 == spec.param.ptr_ || 0 > _RW::__rw_memattr (spec.param.ptr_, spec.prec, -1)) len = _rw_fmtbadaddr (spec, buf, spec.param.ptr_); @@ -2634,21 +2662,21 @@ } else if (spec.mod == spec.mod_L) { // locale category or LC_XXX constant - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtlc (spec, buf, spec.param.int_); } else if (spec.mod == spec.mod_l) { // wint_t argument formatted as wchar_t with non-printable // characters represented using traditional C escape // sequences - spec.param.wint_ = PARAM (wint_); + spec.param.wint_ = PARAM (wint_, pva); return _rw_fmtwchr (spec, buf, spec.param.wint_, 0); } else { // int argument formatted as char with non-printable // characters represented using traditional C escape // sequences - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); return _rw_fmtchr (spec, buf, spec.param.int_, 0); } break; @@ -2656,45 +2684,45 @@ case 'C': // %{C}, %{LC} if (spec.mod == spec.mod_L) { // ctype_base::mask value - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtmask (spec, buf, spec.param.int_); } else { // ctype_base::mask of a character - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtcharmask (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_); + spec.param.ptr_ = PARAM (ptr_, pva); len = _rw_fmtfloating (spec, buf, spec.param.ptr_); } else if (spec.mod == spec.mod_ext_I) { // ios::copyfmt_event - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtevent (spec, buf, spec.param.int_); } break; case 'f': // %{f}, %{Af}, %{If} if (spec.mod == spec.mod_ext_A) { // array of floating point values - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); len = _rw_fmtfloating (spec, buf, spec.param.ptr_); } else if (spec.mod == spec.mod_ext_I) { // ios::fmtflags - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtflags (spec, buf, spec.param.int_); } else { // function pointer - spec.param.funptr_ = PARAM (funptr_); + spec.param.funptr_ = PARAM (funptr_, pva); len = _rw_fmtfunptr (spec, buf, spec.param.funptr_); } break; case 'g': // %{g}, %{Ag} if (spec.mod == spec.mod_ext_A) { // array of floating point values - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); len = _rw_fmtfloating (spec, buf, spec.param.ptr_); } else { @@ -2710,7 +2738,7 @@ case 'o': // %{Io} if (spec.mod == spec.mod_ext_I) { // ios::openmode - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtopenmode (spec, buf, spec.param.int_); break; } @@ -2738,7 +2766,7 @@ break; case 'K': // %{K} -- signal - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtsignal (spec, buf, spec.param.int_); break; @@ -2748,11 +2776,11 @@ case 'M': // %{M}, %{LM} if (spec.mod == spec.mod_L) { // money_base::pattern - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); len = _rw_fmtmonpat (spec, buf, (char*)spec.param.ptr_); } else { // member pointer - spec.param.memptr_ = PARAM (memptr_); + spec.param.memptr_ = PARAM (memptr_, pva); len = _rw_fmtmemptr (spec, buf, spec.param.memptr_); } break; @@ -2770,7 +2798,7 @@ const size_t nbytes = *buf.pbufsize; - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); if (spec.mod == spec.mod_hh) { UChar* const ptr = (UChar*)spec.param.ptr_; @@ -2824,29 +2852,29 @@ case 'P': // %{P} // rw_pid_t is _RWSTD_SSIZE_T which is equal to _RWSTD_PTRDIFF_T - spec.param.diff_ = PARAM (diff_); + spec.param.diff_ = PARAM (diff_, pva); len = rw_fmtinteger (spec, buf, spec.param.diff_); break; case 's': // %{s}, %{As}, %{Is}, %{ls} if (spec.mod == spec.mod_ext_A) { // array of strings - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const char* const* const argv = (char**)spec.param.ptr_; len = _rw_fmtstrarray (pspec, paramno, buf, argv); } else if (spec.mod == spec.mod_ext_I) { // ios::iostate - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtiostate (spec, buf, spec.param.int_); } else if (spec.mod == spec.mod_l) { // wchar_t* - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const wchar_t* const wstr = (wchar_t*)spec.param.ptr_; const size_t wstr_len = spec.width < 0 ? _RWSTD_SIZE_MAX : size_t (spec.width); len = _rw_fmtarray (spec, buf, wstr, wstr_len, A_WCHAR | A_ESC); } else { // char* - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const char* const str = (char*)spec.param.ptr_; const size_t str_len = spec.width < 0 ? _RWSTD_SIZE_MAX : size_t (spec.width); @@ -2858,7 +2886,7 @@ if ( spec.mod == spec.mod_l || !spec.mod && spec.fl_pound && sizeof (wchar_t) == spec.width) { // std::wstring - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const std::wstring* const pstr = (std::wstring*)spec.param.ptr_; @@ -2875,7 +2903,7 @@ } } else { // std::string - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const std::string* const pstr = (std::string*)spec.param.ptr_; @@ -2893,7 +2921,7 @@ break; case 't': { // %{t} - spec.param.ptr_ = PARAM (ptr_); + spec.param.ptr_ = PARAM (ptr_, pva); const tm* const tmb = (tm*)spec.param.ptr_; @@ -2904,7 +2932,7 @@ case 'w': { // %{Iw} if (spec.mod == spec.mod_ext_I) { // ios::seekdir - spec.param.int_ = PARAM (int_); + spec.param.int_ = PARAM (int_, pva); len = _rw_fmtseekdir (spec, buf, spec.param.int_); break; } @@ -2928,7 +2956,7 @@ /********************************************************************/ static int -_rw_fmtexpr (FmtSpec &spec, Buffer &buf, va_list *pva) +_rw_fmtexpr (FmtSpec &spec, Buffer &buf, VarArgs *pva) { RW_ASSERT (0 != spec.strarg); @@ -2968,19 +2996,19 @@ if ('*' == *param) { // extract the name of the parameter from the argument list - param = va_arg (*pva, char*); + param = _RWSTD_CONST_CAST (char*, VA_ARG (*pva, const char*)); } char* fmtword = 0; if ('*' == *word) { // extract "word" from the argument list - word = va_arg (*pva, char*); + word = _RWSTD_CONST_CAST (char*, VA_ARG (*pva, const char*)); } else if ('@' == *word) { // extract formatting directive from the argument list // and set word to the result of processing it - const char* const fmt = va_arg (*pva, char*); + const char* const fmt = VA_ARG (*pva, char*); size_t dummy_size = 0; // unused Buffer tmpbuf = { &fmtword, &dummy_size, _RWSTD_SIZE_MAX, 0 }; @@ -3145,6 +3173,48 @@ free (spec.strarg); spec.strarg = 0; spec.param.ptr_ = _RWSTD_CONST_CAST (char*, val); + + return len; +} + +/********************************************************************/ + +static int +_rw_fmtnested (const FmtSpec &spec, + Buffer &buf, + const char *fmt, + VarArgs *pva) +{ + RW_ASSERT ('@' == spec.cvtspec); + + // optional precision specifies the number of times + // for the directive to be applied + const int nelems = spec.prec < 0 ? 1 : spec.prec; + + // separator between array elements + const char *sepstr = ""; + size_t seplen = 0; + + if (spec.fl_space) { + sepstr = " "; + seplen = 1; + } + + VarArgs tmparg (*pva); + + if (spec.mod_ext_A == spec.mod) { + tmparg.kind_ = VarArgs::VA_array; + tmparg.arg_.pargs_ = VA_ARG (*pva, const void*); + } + + int len = 0; + + for (int i = 0; i != nelems; ++i) { + len += _rw_pvasnprintf (buf, fmt, &tmparg); + + if (seplen && i + 1 < nelems && 0 == _rw_bufcat (buf, sepstr, seplen)) + return -1; + } return len; }