stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r507360 - in /incubator/stdcxx/trunk/tests: self/0.printf.cpp src/printf.cpp
Date Wed, 14 Feb 2007 02:33:41 GMT
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  <sebor@roguewave.com>

	* 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;
 }



Mime
View raw message