stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r390299 [2/2] - in /incubator/stdcxx/trunk/tests: self/0.printf.cpp src/fmt_bits.cpp src/fmt_defs.h src/printf.cpp
Date Fri, 31 Mar 2006 02:03:10 GMT
Modified: incubator/stdcxx/trunk/tests/src/printf.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/src/printf.cpp?rev=390299&r1=390298&r2=390299&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/printf.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/printf.cpp Thu Mar 30 18:03:09 2006
@@ -27,8 +27,10 @@
 
 // expand _TEST_EXPORT macros
 #define _RWSTD_TEST_SRC
-#include <testdefs.h>
+#include "fmt_defs.h"
+
 #include <rw_printf.h>
+#include <environ.h>
 
 #include <ctype.h>    // for isalpha(), ...
 #include <errno.h>    // for errno, errno constants
@@ -77,20 +79,6 @@
 
 /********************************************************************/
 
-// convenience typedefs
-typedef unsigned char  UChar;
-typedef unsigned short UShrt;
-typedef unsigned int   UInt;
-typedef unsigned long  ULong;
-
-#ifdef _RWSTD_LONG_LONG
-
-typedef unsigned _RWSTD_LONG_LONG ULLong;
-
-#endif   // _RWSTD_LONG_LONG
-
-/********************************************************************/
-
 static const union {
     int   ival;
     UChar bytes [sizeof (int)];
@@ -102,15 +90,6 @@
 
 /********************************************************************/
 
-struct Buffer {
-    char   **pbuf;       // pointer to the output buffer
-    size_t  *pbufsize;   // pointer to the size of the buffer
-    size_t   maxsize;    // maximum not-to-exceed size
-    size_t   endoff;     // offset of the last character
-};
-
-struct FmtSpec;
-
 _RWSTD_INTERNAL int
 _rw_fmtlong (const FmtSpec&, Buffer&, long);
 
@@ -134,21 +113,13 @@
 _RWSTD_INTERNAL int
 _rw_fmtbadaddr (const FmtSpec&, Buffer&, const void*, size_t = 0);
 
-typedef void (*funptr_t)();
-
 static int
 _rw_fmtfunptr (const FmtSpec&, Buffer&, funptr_t);
 
-struct DummyStruct;
-typedef void (DummyStruct::*memptr_t)() const;
-
 static int
 _rw_fmtmemptr (const FmtSpec&, Buffer&, memptr_t);
 
 static int
-_rw_fmtstr (const FmtSpec&, Buffer&, const char*, size_t);
-
-static int
 _rw_fmtchr (const FmtSpec&, Buffer&, int, int);
 
 static int
@@ -157,36 +128,13 @@
 static int
 _rw_fmtwstr (const FmtSpec&, Buffer&, const wchar_t*, size_t);
 
-// format errno value/name
-static int
-_rw_fmterrno (const FmtSpec&, Buffer&, int);
-
-// format a character mask (alpha|alnum|...|xdigit)
-static int
-_rw_fmtmask (const FmtSpec&, Buffer&, int);
-
 // format struct tm
 static int
 _rw_fmttm (const FmtSpec&, Buffer&, const tm*);
 
-// format ios_base::openmode
-static int
-_rw_fmtopenmode (const FmtSpec&, Buffer&, int);
-
-// format ios_base::seekdir
-static int
-_rw_fmtseekdir (const FmtSpec&, Buffer&, int);
-
-// format ios_base::event
+// format an expression (parameter/environment variable)
 static int
-_rw_fmtevent (const FmtSpec&, Buffer&, int);
-
-static int
-_rw_fmtmonpat (const FmtSpec&, Buffer&, const char [4]);
-
-// format a signal value/name
-static int
-_rw_fmtsignal (const FmtSpec&, Buffer&, int);
+_rw_fmtexpr (FmtSpec&, Buffer&, va_list*);
 
 // format an extension
 static int
@@ -201,122 +149,6 @@
 
 /********************************************************************/
 
-struct FmtSpec
-{
-    // optional flags
-    unsigned fl_minus  : 1;
-    unsigned fl_plus   : 1;
-    unsigned fl_pound  : 1;
-    unsigned fl_space  : 1;
-    unsigned fl_zero   : 1;
-
-    // optional length modifier
-    enum Modifier {
-        mod_none = 0,
-        mod_h,       // short modifier
-        mod_hh,      // char modifier
-        mod_l,       // long modifier
-        mod_ll,      // long long modifier
-        mod_j,       // intmax_t modifier
-        mod_z,       // size_t modifier
-        mod_t,       // ptrdiff_t modifier
-        mod_L,       // long double modifier
-        mod_ext_A,   // extension: arrays
-        mod_ext_I    // extension: int as ios::iostate
-    };
-
-    Modifier mod : 5;
-
-    unsigned cond       : 1;   // have an if/else clause
-    unsigned cond_true  : 1;   // if/else clause is active (true)
-    unsigned cond_begin : 1;   // beginning of an if/else clause
-    unsigned cond_end   : 1;   // end of an if/else clause
-
-    // note that the signedness of a bitfield is implementation-defined
-    // unless explicitly declared signed or unsigned
-
-    // extension: 8, 16, 32, and 64 bit integer width modifier
-    signed int iwidth : 4;
-
-    // extension: optional numerical base 2 - 36
-    signed int base   : 7;
-
-    // extension: optional parameter number
-    long paramno;
-
-    // optional field width and precision
-    int width;
-    int prec;
-
-    // extension: string argument
-    char *strarg;
-
-    // required conversion specifier
-    int cvtspec;
-
-    // extension: fill character
-    int fill;
-
-#ifndef _RWSTD_NO_LONG_DOUBLE
-    typedef long double ldbl_t;
-#else
-    typedef double ldbl_t;   // bogus (for convenience)
-#endif   // _RWSTD_NO_LONG_DOUBLE
-
-#ifdef _RWSTD_LONG_LONG
-    typedef _RWSTD_LONG_LONG llong_t;
-#else
-    typedef long llong_t;   // bogus (for convenience)
-#endif   // _RWSTD_LONG_LONG
-
-#ifdef _RWSTD_INT64_T
-    typedef _RWSTD_INT64_T i64_t;
-#else
-    typedef int            i64_t;   // for convenience
-#endif   // _RWSTD_INT64_T
-
-#ifdef _RWSTD_INT32_T
-    typedef _RWSTD_INT32_T i32_t;
-#else
-    typedef int i64_t;
-#endif   // _RWSTD_INT64_T
-
-#ifdef _RWSTD_WINT_T
-    typedef _RWSTD_WINT_T wint_t;
-#else
-    typedef int wint_t;
-#endif
-
-    typedef ::size_t   size_t;
-    typedef ptrdiff_t  diff_t;
-    typedef ::funptr_t funptr_t;
-    typedef ::memptr_t memptr_t;
-
-    typedef int        int_t;
-    typedef long       long_t;
-    typedef void*      ptr_t;
-    typedef double     dbl_t;
-
-    union {
-        ldbl_t    ldbl_;
-        llong_t   llong_;
-        i64_t     i64_;
-        ptr_t     ptr_;
-        long_t    long_;
-        i32_t     i32_;
-        int_t     int_;
-        diff_t    diff_;
-        size_t    size_;
-        wint_t    wint_;
-
-        dbl_t     dbl_;
-        memptr_t  memptr_;
-        funptr_t  funptr_;
-    } param;
-};
-
-/********************************************************************/
-
 /*
 
   C99 format specifier:
@@ -363,26 +195,33 @@
         if ('$' == *fmt) {
 
             // %{$<string>}: introduces the name of an environment
-            // variable (or some other string)
+            // variable (or parameter)
 
             ++fmt;
 
-            const char *str;
-            if ('*' == *fmt) {
-                str = va_arg (*pva, char*);
-                if (!str)
-                    str = "";
-                ++fmt;
-            }
-            else {
-                str  = fmt;
-                fmt += strlen (fmt);
+            const char *str = 0;
+            size_t      len = 0;
+
+            const char* const end = strchr (fmt, '}');
+
+            if (end) {
+                len = end - fmt;
+                str = fmt;
+                fmt = end;
             }
 
-            char* const tmp = (char*)malloc (strlen (str));
-            pspec->strarg = strcpy (tmp, str);
+            if (str) {
+                char* const tmp = (char*)malloc (len + 1);
+                if (tmp) {
+                    memcpy (tmp, str, len);
+                    pspec->strarg = tmp;
+                    pspec->strarg [len] = '\0';
+
+                    return int (fmt - fmtbeg);
+                }
 
-            return int (fmt - fmtbeg);
+                return -1;
+            }
         }
     }
 
@@ -947,7 +786,15 @@
         if ('{' == *fc) {
             const char* const endbrace = strchr (++fc, '}');
 
-            RW_ASSERT (0 != endbrace);
+            if (0 == endbrace) {
+                const size_t flen = strlen (fc -= 2);
+                next = _rw_bufcat (buf, fc, flen);
+                if (0 == next)
+                    goto fail;
+
+                fc += flen;
+                continue;
+            }
 
             const size_t fmtlen = endbrace - fc;
 
@@ -966,8 +813,6 @@
             // all unused bits to 0
             const int speclen = _rw_fmtspec (pspec + paramno, true, fc, pva);
 
-            _RWSTD_UNUSED (speclen);
-
             // copy the current backtrack offset if one exists
             // and set the condition and condition true bits
             if (nextoff) {
@@ -1078,7 +923,9 @@
 
             RW_ASSERT (next == *buf.pbuf + buf.endoff);
 
-            fc = endbrace + 1;
+            fc += speclen + 1;
+            if (fc < endbrace)
+                fc = endbrace + 1;
         }
         else {
             const int speclen =
@@ -1109,6 +956,9 @@
         fmt = fc;
     }
 
+    for (size_t i = 0; i != paramno; ++i)
+        free (pspec [i].strarg);
+
     // deallocate if dynamically allocated
     if (pspec != specbuf)
         free (pspec);
@@ -1129,6 +979,9 @@
              __FILE__, __LINE__, (void*)buf.pbuf, (void*)buf.pbufsize, fmt,
              errno, strerror (errno));
 
+    for (size_t i = 0; i != paramno; ++i)
+        free (pspec [i].strarg);
+
     if (pspec != specbuf)
         free (pspec);
 
@@ -1728,7 +1581,7 @@
     const size_t num_addr = (size_t)addr;
 
     if (objsize && (num_addr & (objsize - 1))) {
-        if (0 == _rw_bufcat (buf, "(unaligned address ", 19))
+        if (0 == _rw_bufcat (buf, "(misaligned address ", 20))
             return -1;
     }
     else if (0 == _rw_bufcat (buf,    "(invalid address ", 17))
@@ -1806,511 +1659,6 @@
 /********************************************************************/
 
 static int
-_rw_fmterrno (const FmtSpec &spec, Buffer &buf, int val)
-{
-    static const struct {
-        int         val;
-        const char* str;
-    } names[] = {
-
-#undef ERRNO
-#define ERRNO(val)   { val, #val }
-
-#ifdef EPERM
-        ERRNO (EPERM),
-#endif   // EPERM
-#ifdef ENOENT
-        ERRNO (ENOENT),
-#endif   // ENOENT
-#ifdef ESRCH
-        ERRNO (ESRCH),
-#endif   // ESRCH
-#ifdef EINTR
-        ERRNO (EINTR),
-#endif   // EINTR
-#ifdef EIO
-        ERRNO (EIO),
-#endif   // EIO
-#ifdef ENXIO
-        ERRNO (ENXIO),
-#endif   // ENXIO
-#ifdef E2BIG
-        ERRNO (E2BIG),
-#endif   // E2BIG
-#ifdef ENOEXEC
-        ERRNO (ENOEXEC),
-#endif   // ENOEXEC
-#ifdef EBADF
-        ERRNO (EBADF),
-#endif   // EBADF
-#ifdef ECHILD
-        ERRNO (ECHILD),
-#endif   // ECHILD
-#ifdef EAGAIN
-        ERRNO (EAGAIN),
-#endif   // EAGAIN
-#ifdef ENOMEM
-        ERRNO (ENOMEM),
-#endif   // ENOMEM
-#ifdef EACCES
-        ERRNO (EACCES),
-#endif   // EACCES
-#ifdef EFAULT
-        ERRNO (EFAULT),
-#endif   // EFAULT
-#ifdef ENOTBLK
-        ERRNO (ENOTBLK),
-#endif   // ENOTBLK
-#ifdef EBUSY
-        ERRNO (EBUSY),
-#endif   // EBUSY
-#ifdef EEXIST
-        ERRNO (EEXIST),
-#endif   // EEXIST
-#ifdef EXDEV
-        ERRNO (EXDEV),
-#endif   // EXDEV
-#ifdef ENODEV
-        ERRNO (ENODEV),
-#endif   // ENODEV
-#ifdef ENOTDIR
-        ERRNO (ENOTDIR),
-#endif   // ENOTDIR
-#ifdef EISDIR
-        ERRNO (EISDIR),
-#endif   // EISDIR
-#ifdef EINVAL
-        ERRNO (EINVAL),
-#endif   // EINVAL
-#ifdef ENFILE
-        ERRNO (ENFILE),
-#endif   // ENFILE
-#ifdef EMFILE
-        ERRNO (EMFILE),
-#endif   // EMFILE
-#ifdef ENOTTY
-        ERRNO (ENOTTY),
-#endif   // ENOTTY
-#ifdef ETXTBSY
-        ERRNO (ETXTBSY),
-#endif   // ETXTBSY
-#ifdef EFBIG
-        ERRNO (EFBIG),
-#endif   // EFBIG
-#ifdef ENOSPC
-        ERRNO (ENOSPC),
-#endif   // ENOSPC
-#ifdef ESPIPE
-        ERRNO (ESPIPE),
-#endif   // ESPIPE
-#ifdef EROFS
-        ERRNO (EROFS),
-#endif   // EROFS
-#ifdef EMLINK
-        ERRNO (EMLINK),
-#endif   // EMLINK
-#ifdef EPIPE
-        ERRNO (EPIPE),
-#endif   // EPIPE
-#ifdef EDOM
-        ERRNO (EDOM),
-#endif   // EDOM
-#ifdef ERANGE
-        ERRNO (ERANGE),
-#endif   // ERANGE
-#ifdef ENOMSG
-        ERRNO (ENOMSG),
-#endif   // ENOMSG
-#ifdef EIDRM
-        ERRNO (EIDRM),
-#endif   // EIDRM
-#ifdef ECHRNG
-        ERRNO (ECHRNG),
-#endif   // ECHRNG
-#ifdef EL2NSYNC
-        ERRNO (EL2NSYNC),
-#endif   // EL2NSYNC
-#ifdef EL3HLT
-        ERRNO (EL3HLT),
-#endif   // EL3HLT
-#ifdef EL3RST
-        ERRNO (EL3RST),
-#endif   // EL3RST
-#ifdef ELNRNG
-        ERRNO (ELNRNG),
-#endif   // ELNRNG
-#ifdef EUNATCH
-        ERRNO (EUNATCH),
-#endif   // EUNATCH
-#ifdef ENOCSI
-        ERRNO (ENOCSI),
-#endif   // ENOCSI
-#ifdef EL2HLT
-        ERRNO (EL2HLT),
-#endif   // EL2HLT
-#ifdef EDEADLK
-        ERRNO (EDEADLK),
-#endif   // EDEADLK
-#ifdef ENOLCK
-        ERRNO (ENOLCK),
-#endif   // ENOLCK
-#ifdef ECANCELED
-        ERRNO (ECANCELED),
-#endif   // ECANCELED
-#ifdef ENOTSUP
-        ERRNO (ENOTSUP),
-#endif   // ENOTSUP
-#ifdef EDQUOT
-        ERRNO (EDQUOT),
-#endif   // EDQUOT
-#ifdef EBADE
-        ERRNO (EBADE),
-#endif   // EBADE
-#ifdef EBADR
-        ERRNO (EBADR),
-#endif   // EBADR
-#ifdef EXFULL
-        ERRNO (EXFULL),
-#endif   // EXFULL
-#ifdef ENOANO
-        ERRNO (ENOANO),
-#endif   // ENOANO
-#ifdef EBADRQC
-        ERRNO (EBADRQC),
-#endif   // EBADRQC
-#ifdef EBADSLT
-        ERRNO (EBADSLT),
-#endif   // EBADSLT
-#ifdef EDEADLOCK
-        ERRNO (EDEADLOCK),
-#endif   // EDEADLOCK
-#ifdef EBFONT
-        ERRNO (EBFONT),
-#endif   // EBFONT
-#ifdef EOWNERDEAD
-        ERRNO (EOWNERDEAD),
-#endif   // EOWNERDEAD
-#ifdef ENOTRECOVERABLE
-        ERRNO (ENOTRECOVERABLE),
-#endif   // ENOTRECOVERABLE
-#ifdef ENOSTR
-        ERRNO (ENOSTR),
-#endif   // ENOSTR
-#ifdef ENODATA
-        ERRNO (ENODATA),
-#endif   // ENODATA
-#ifdef ETIME
-        ERRNO (ETIME),
-#endif   // ETIME
-#ifdef ENOSR
-        ERRNO (ENOSR),
-#endif   // ENOSR
-#ifdef ENONET
-        ERRNO (ENONET),
-#endif   // ENONET
-#ifdef ENOPKG
-        ERRNO (ENOPKG),
-#endif   // ENOPKG
-#ifdef EREMOTE
-        ERRNO (EREMOTE),
-#endif   // EREMOTE
-#ifdef ENOLINK
-        ERRNO (ENOLINK),
-#endif   // ENOLINK
-#ifdef EADV
-        ERRNO (EADV),
-#endif   // EADV
-#ifdef ESRMNT
-        ERRNO (ESRMNT),
-#endif   // ESRMNT
-#ifdef ECOMM
-        ERRNO (ECOMM),
-#endif   // ECOMM
-#ifdef ELOCKUNMAPPED
-        ERRNO (ELOCKUNMAPPED),
-#endif   // ELOCKUNMAPPED
-#ifdef ENOTACTIVE
-        ERRNO (ENOTACTIVE),
-#endif   // ENOTACTIVE
-#ifdef EMULTIHOP
-        ERRNO (EMULTIHOP),
-#endif   // EMULTIHOP
-#ifdef EBADMSG
-        ERRNO (EBADMSG),
-#endif   // EBADMSG
-#ifdef ENAMETOOLONG
-        ERRNO (ENAMETOOLONG),
-#endif   // ENAMETOOLONG
-#ifdef EOVERFLOW
-        ERRNO (EOVERFLOW),
-#endif   // EOVERFLOW
-#ifdef ENOTUNIQ
-        ERRNO (ENOTUNIQ),
-#endif   // ENOTUNIQ
-#ifdef EBADFD
-        ERRNO (EBADFD),
-#endif   // EBADFD
-#ifdef EREMCHG
-        ERRNO (EREMCHG),
-#endif   // EREMCHG
-#ifdef ELIBACC
-        ERRNO (ELIBACC),
-#endif   // ELIBACC
-#ifdef ELIBBAD
-        ERRNO (ELIBBAD),
-#endif   // ELIBBAD
-#ifdef ELIBSCN
-        ERRNO (ELIBSCN),
-#endif   // ELIBSCN
-#ifdef ELIBMAX
-        ERRNO (ELIBMAX),
-#endif   // ELIBMAX
-#ifdef ELIBEXEC
-        ERRNO (ELIBEXEC),
-#endif   // ELIBEXEC
-#ifdef EILSEQ
-        ERRNO (EILSEQ),
-#endif   // EILSEQ
-#ifdef ENOSYS
-        ERRNO (ENOSYS),
-#endif   // ENOSYS
-#ifdef ELOOP
-        ERRNO (ELOOP),
-#endif   // ELOOP
-#ifdef ERESTART
-        ERRNO (ERESTART),
-#endif   // ERESTART
-#ifdef ESTRPIPE
-        ERRNO (ESTRPIPE),
-#endif   // ESTRPIPE
-#ifdef ENOTEMPTY
-        ERRNO (ENOTEMPTY),
-#endif   // ENOTEMPTY
-#ifdef EUSERS
-        ERRNO (EUSERS),
-#endif   // EUSERS
-#ifdef ENOTSOCK
-        ERRNO (ENOTSOCK),
-#endif   // ENOTSOCK
-#ifdef EDESTADDRREQ
-        ERRNO (EDESTADDRREQ),
-#endif   // EDESTADDRREQ
-#ifdef EMSGSIZE
-        ERRNO (EMSGSIZE),
-#endif   // EMSGSIZE
-#ifdef EPROTOTYPE
-        ERRNO (EPROTOTYPE),
-#endif   // EPROTOTYPE
-#ifdef ENOPROTOOPT
-        ERRNO (ENOPROTOOPT),
-#endif   // ENOPROTOOPT
-#ifdef EPROTONOSUPPORT
-        ERRNO (EPROTONOSUPPORT),
-#endif   // EPROTONOSUPPORT
-#ifdef ESOCKTNOSUPPORT
-        ERRNO (ESOCKTNOSUPPORT),
-#endif   // ESOCKTNOSUPPORT
-#ifdef EOPNOTSUPP
-        ERRNO (EOPNOTSUPP),
-#endif   // EOPNOTSUPP
-#ifdef EPFNOSUPPORT
-        ERRNO (EPFNOSUPPORT),
-#endif   // EPFNOSUPPORT
-#ifdef EAFNOSUPPORT
-        ERRNO (EAFNOSUPPORT),
-#endif   // EAFNOSUPPORT
-#ifdef EADDRINUSE
-        ERRNO (EADDRINUSE),
-#endif   // EADDRINUSE
-#ifdef EADDRNOTAVAIL
-        ERRNO (EADDRNOTAVAIL),
-#endif   // EADDRNOTAVAIL
-#ifdef ENETDOWN
-        ERRNO (ENETDOWN),
-#endif   // ENETDOWN
-#ifdef ENETUNREACH
-        ERRNO (ENETUNREACH),
-#endif   // ENETUNREACH
-#ifdef ENETRESET
-        ERRNO (ENETRESET),
-#endif   // ENETRESET
-#ifdef ECONNABORTED
-        ERRNO (ECONNABORTED),
-#endif   // ECONNABORTED
-#ifdef ECONNRESET
-        ERRNO (ECONNRESET),
-#endif   // ECONNRESET
-#ifdef ENOBUFS
-        ERRNO (ENOBUFS),
-#endif   // ENOBUFS
-#ifdef EISCONN
-        ERRNO (EISCONN),
-#endif   // EISCONN
-#ifdef ENOTCONN
-        ERRNO (ENOTCONN),
-#endif   // ENOTCONN
-#ifdef ESHUTDOWN
-        ERRNO (ESHUTDOWN),
-#endif   // ESHUTDOWN
-#ifdef ETOOMANYREFS
-        ERRNO (ETOOMANYREFS),
-#endif   // ETOOMANYREFS
-#ifdef ETIMEDOUT
-        ERRNO (ETIMEDOUT),
-#endif   // ETIMEDOUT
-#ifdef ECONNREFUSED
-        ERRNO (ECONNREFUSED),
-#endif   // ECONNREFUSED
-#ifdef EHOSTDOWN
-        ERRNO (EHOSTDOWN),
-#endif   // EHOSTDOWN
-#ifdef EHOSTUNREACH
-        ERRNO (EHOSTUNREACH),
-#endif   // EHOSTUNREACH
-#ifdef EWOULDBLOCK
-        ERRNO (EWOULDBLOCK),
-#endif   // EWOULDBLOCK
-#ifdef EALREADY
-        ERRNO (EALREADY),
-#endif   // EALREADY
-#ifdef EINPROGRESS
-        ERRNO (EINPROGRESS),
-#endif   // EINPROGRESS
-#ifdef ESTALE
-        ERRNO (ESTALE),
-#endif   // ESTALE
-        { -1, 0 }
-    };
-
-    if (spec.fl_pound) {
-
-        char buffer [64];
-        const char *name = 0;
-
-        for (size_t i = 0; i != sizeof names / sizeof *names; ++i) {
-            if (names [i].val == val) {
-                name = names [i].str;
-                break;
-            }
-        }
-
-        int len;
-
-        if (0 == name) {
-            len = sprintf (buffer, "E#%d", val);
-            name = buffer;
-        }
-        else
-            len = int (strlen (name));
-
-        if (0 == _rw_bufcat (buf, name, size_t (len)))
-            return -1;
-
-        return len;
-    }
-
-    const char* const str = strerror (val);
-    const size_t len = strlen (str);
-
-    if (0 == _rw_bufcat (buf, str, len))
-        return -1;
-
-    return int (len);
-}
-
-/********************************************************************/
-
-static int
-_rw_fmtmask (const FmtSpec &spec, Buffer &buf, int c)
-{
-    enum {
-        bit_alnum  = 1,
-        bit_alpha  = 1 << 1,
-        bit_cntrl  = 1 << 2,
-        bit_digit  = 1 << 3,
-        bit_graph  = 1 << 4,
-        bit_lower  = 1 << 5,
-        bit_print  = 1 << 6,
-        bit_punct  = 1 << 7,
-        bit_space  = 1 << 8,
-        bit_upper  = 1 << 9,
-        bit_xdigit = 1 << 10
-    };
-
-    int mask = 0;
-
-    if (spec.mod == spec.mod_l) {
-
-#ifndef _RWSTD_NO_WCHAR_H
-
-        mask |= iswalnum (c) ? bit_alnum : 0;
-        mask |= iswalpha (c) ? bit_alpha : 0;
-        mask |= iswcntrl (c) ? bit_cntrl : 0;
-        mask |= iswdigit (c) ? bit_digit : 0;
-        mask |= iswgraph (c) ? bit_graph : 0;
-        mask |= iswlower (c) ? bit_lower : 0;
-        mask |= iswprint (c) ? bit_print : 0;
-        mask |= iswpunct (c) ? bit_punct : 0;
-        mask |= iswspace (c) ? bit_space : 0;
-        mask |= iswupper (c) ? bit_upper : 0;
-        mask |= iswxdigit (c) ? bit_xdigit : 0;
-
-#endif   // _RWSTD_NO_WCHAR_H
-
-    }
-    else {
-        const UChar uc = c;
-
-        mask |= isalnum (uc) ? bit_alnum : 0;
-        mask |= isalpha (uc) ? bit_alpha : 0;
-        mask |= iscntrl (uc) ? bit_cntrl : 0;
-        mask |= isdigit (uc) ? bit_digit : 0;
-        mask |= isgraph (uc) ? bit_graph : 0;
-        mask |= islower (uc) ? bit_lower : 0;
-        mask |= isprint (uc) ? bit_print : 0;
-        mask |= ispunct (uc) ? bit_punct : 0;
-        mask |= isspace (uc) ? bit_space : 0;
-        mask |= isupper (uc) ? bit_upper : 0;
-        mask |= isxdigit (uc) ? bit_xdigit : 0;
-    }
-
-    char mask_str [80];
-    char *str = mask_str;
-
-    str [0] = '\0';
-
-#define APPEND(bit)                             \
-    if (mask & bit_ ## bit)                     \
-        strcat (strcat (str, #bit), "|");       \
-    else (void)0
-
-    APPEND (alnum);
-    APPEND (alpha);
-    APPEND (cntrl);
-    APPEND (digit);
-    APPEND (graph);
-    APPEND (lower);
-    APPEND (print);
-    APPEND (punct);
-    APPEND (space);
-    APPEND (upper);
-    APPEND (xdigit);
-
-    if (str == mask_str)
-        *str = '\0';
-    else
-        str [-1] = '\0';
-
-    const size_t len = strlen (str);
-    if (0 == _rw_bufcat (buf, str, len))
-        return -1;
-
-    return int (len);
-}
-
-/********************************************************************/
-
-static int
 _rw_fmttm (const FmtSpec &spec, Buffer &buf, const tm *tmb)
 {
     if (   0 == tmb || 0 > _RW::__rw_memattr (tmb, sizeof *tmb, 0)
@@ -2447,201 +1795,8 @@
 
 /********************************************************************/
 
-static int
-_rw_fmtsignal (const FmtSpec &spec, Buffer &buf, int val)
-{
-    static const struct {
-        int         val;
-        const char* str;
-    } names[] = {
-
-#undef SIGNAL
-#define SIGNAL(val)   { val, #val }
-
-#ifdef SIGABRT
-        SIGNAL (SIGABRT),
-#endif   // SIGABRT
-#ifdef SIGALRM
-        SIGNAL (SIGALRM),
-#endif   // SIGALRM
-#ifdef SIGBUS
-        SIGNAL (SIGBUS),
-#endif   // SIGBUS
-#ifdef SIGCANCEL
-        SIGNAL (SIGCANCEL),
-#endif   // SIGCANCEL
-#ifdef SIGCHLD
-        SIGNAL (SIGCHLD),
-#endif   // SIGCHLD
-#ifdef SIGCKPT
-        SIGNAL (SIGCKPT),
-#endif   // SIGCKPT
-#ifdef SIGCLD
-        SIGNAL (SIGCLD),
-#endif   // SIGCLD
-#ifdef SIGCONT
-        SIGNAL (SIGCONT),
-#endif   // SIGCONT
-#ifdef SIGDIL
-        SIGNAL (SIGDIL),
-#endif   // SIGDIL
-#ifdef SIGEMT
-        SIGNAL (SIGEMT),
-#endif   // SIGEMT
-#ifdef SIGFPE
-        SIGNAL (SIGFPE),
-#endif   // SIGFPE
-#ifdef SIGFREEZE
-        SIGNAL (SIGFREEZE),
-#endif   // SIGFREEZE
-#ifdef SIGGFAULT
-        SIGNAL (SIGGFAULT),
-#endif   // SIGGFAULT
-#ifdef SIGHUP
-        SIGNAL (SIGHUP),
-#endif   // SIGHUP
-#ifdef SIGILL
-        SIGNAL (SIGILL),
-#endif   // SIGILL
-#ifdef SIGINFO
-        SIGNAL (SIGINFO),
-#endif   // SIGINFO
-#ifdef SIGINT
-        SIGNAL (SIGINT),
-#endif   // SIGINT
-#ifdef SIGIO
-        SIGNAL (SIGIO),
-#endif   // SIGIO
-#ifdef SIGIOT
-        SIGNAL (SIGIOT),
-#endif   // SIGIOT
-#ifdef SIGK32
-        SIGNAL (SIGK32),
-#endif   // SIGK32
-#ifdef SIGKILL
-        SIGNAL (SIGKILL),
-#endif   // SIGKILL
-#ifdef SIGLOST
-        SIGNAL (SIGLOST),
-#endif   // SIGLOST
-#ifdef SIGLWP
-        SIGNAL (SIGLWP),
-#endif   // SIGLWP
-#ifdef SIGPIPE
-        SIGNAL (SIGPIPE),
-#endif   // SIGPIPE
-#ifdef SIGPOLL
-        SIGNAL (SIGPOLL),
-#endif   // SIGPOLL
-#ifdef SIGPROF
-        SIGNAL (SIGPROF),
-#endif   // SIGPROF
-#ifdef SIGPTINTR
-        SIGNAL (SIGPTINTR),
-#endif   // SIGPTINTR
-#ifdef SIGPTRESCHED
-        SIGNAL (SIGPTRESCHED),
-#endif   // SIGPTRESCHED
-#ifdef SIGPWR
-        SIGNAL (SIGPWR),
-#endif   // SIGPWR
-#ifdef SIGQUIT
-        SIGNAL (SIGQUIT),
-#endif   // SIGQUIT
-#ifdef SIGRESTART
-        SIGNAL (SIGRESTART),
-#endif   // SIGRESTART
-#ifdef SIGRESV
-        SIGNAL (SIGRESV),
-#endif   // SIGRESV
-#ifdef SIGSEGV
-        SIGNAL (SIGSEGV),
-#endif   // SIGSEGV
-#ifdef SIGSTKFLT
-        SIGNAL (SIGSTKFLT),
-#endif   // SIGSTKFLT
-#ifdef SIGSTOP
-        SIGNAL (SIGSTOP),
-#endif   // SIGSTOP
-#ifdef SIGSYS
-        SIGNAL (SIGSYS),
-#endif   // SIGSYS
-#ifdef SIGTERM
-        SIGNAL (SIGTERM),
-#endif   // SIGTERM
-#ifdef SIGTHAW
-        SIGNAL (SIGTHAW),
-#endif   // SIGTHAW
-#ifdef SIGTRAP
-        SIGNAL (SIGTRAP),
-#endif   // SIGTRAP
-#ifdef SIGTSTP
-        SIGNAL (SIGTSTP),
-#endif   // SIGTSTP
-#ifdef SIGTTIN
-        SIGNAL (SIGTTIN),
-#endif   // SIGTTIN
-#ifdef SIGTTOU
-        SIGNAL (SIGTTOU),
-#endif   // SIGTTOU
-#ifdef SIGUNUSED
-        SIGNAL (SIGUNUSED),
-#endif   // SIGUNUSED
-#ifdef SIGURG
-        SIGNAL (SIGURG),
-#endif   // SIGURG
-#ifdef SIGUSR1
-        SIGNAL (SIGUSR1),
-#endif   // SIGUSR1
-#ifdef SIGUSR2
-        SIGNAL (SIGUSR2),
-#endif   // SIGUSR2
-#ifdef SIGVTALRM
-        SIGNAL (SIGVTALRM),
-#endif   // SIGVTALRM
-#ifdef SIGWAITING
-        SIGNAL (SIGWAITING),
-#endif   // SIGWAITING
-#ifdef SIGWINCH
-        SIGNAL (SIGWINCH),
-#endif   // SIGWINCH
-#ifdef SIGWINDOW
-        SIGNAL (SIGWINDOW),
-#endif   // SIGWINDOW
-#ifdef SIGXCPU
-        SIGNAL (SIGXCPU),
-#endif   // SIGXCPU
-#ifdef SIGXFSZ
-        SIGNAL (SIGXFSZ),
-#endif   // SIGXFSZ
-#ifdef SIGXRES
-        SIGNAL (SIGXRES),
-#endif   // SIGXRES
-        { -1, 0 }
-    };
-
-    char buffer [64];
-    const char *name = 0;
-
-    for (size_t i = 0; i != sizeof names / sizeof *names; ++i) {
-        if (names [i].val == val) {
-            name = names [i].str;
-            break;
-        }
-    }
-
-    if (0 == name) {
-        sprintf (buffer, "SIG#%d", val);
-        name = buffer;
-    }
-
-    return _rw_fmtstr (spec, buf, name, _RWSTD_SIZE_MAX);
-}
-
-/********************************************************************/
-
 template <class charT>
-int rw_quotechar (char *buf, charT wc, int noesc)
+int _rw_quotechar (char *buf, charT wc, int noesc)
 {
 #if _RWSTD_WCHAR_T_MIN < 0
 
@@ -2725,7 +1880,7 @@
 };
 
 template <class elemT>
-int rw_fmtarray (const FmtSpec &spec,
+int _rw_fmtarray (const FmtSpec &spec,
                  Buffer        &buf,
                  const elemT   *array,   // pointer to first element
                  size_t         nelems,  // number of elements
@@ -2823,7 +1978,7 @@
 
             if (flags & (A_CHAR | A_WCHAR)) {
                 // format element into elemstr as a character
-                rw_quotechar (elemstr, *last, !(flags & A_ESC));
+                _rw_quotechar (elemstr, *last, !(flags & A_ESC));
 
                 s += sprintf (s, "%s'%s' <repeats %ld times>",
                                 -1 == last_repeat ? ""
@@ -2886,7 +2041,7 @@
 
             if (flags & (A_CHAR | A_WCHAR)) {
                 // format element into elemstr as a character
-                rw_quotechar (elemstr, *last, !(flags & A_ESC));
+                _rw_quotechar (elemstr, *last, !(flags & A_ESC));
             }
             else {
                 // format element into elemstr as an integer
@@ -2961,23 +2116,23 @@
 
 #ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
 
-template int rw_quotechar (char*, UChar, int);
-template int rw_quotechar (char*, char, int);
-template int rw_quotechar (char*, UShrt, int);
-template int rw_quotechar (char*, UInt, int);
-template int rw_quotechar (char*, ULong, int);
-
-template int rw_fmtarray (const FmtSpec&, Buffer&, const UChar*, size_t, int);
-template int rw_fmtarray (const FmtSpec&, Buffer&, const char*, size_t, int);
-template int rw_fmtarray (const FmtSpec&, Buffer&, const UShrt*, size_t, int);
-template int rw_fmtarray (const FmtSpec&, Buffer&, const UInt*, size_t, int);
-template int rw_fmtarray (const FmtSpec&, Buffer&, const ULong*, size_t, int);
+template int _rw_quotechar (char*, UChar, int);
+template int _rw_quotechar (char*, char, int);
+template int _rw_quotechar (char*, UShrt, int);
+template int _rw_quotechar (char*, UInt, int);
+template int _rw_quotechar (char*, ULong, int);
+
+template int _rw_fmtarray (const FmtSpec&, Buffer&, const UChar*, size_t, int);
+template int _rw_fmtarray (const FmtSpec&, Buffer&, const char*, size_t, int);
+template int _rw_fmtarray (const FmtSpec&, Buffer&, const UShrt*, size_t, int);
+template int _rw_fmtarray (const FmtSpec&, Buffer&, const UInt*, size_t, int);
+template int _rw_fmtarray (const FmtSpec&, Buffer&, const ULong*, size_t, int);
 
 
 #  ifndef _RWSTD_NO_WCHAR_T
 
-template int rw_quotechar (char*, wchar_t, int);
-template int rw_fmtarray (const FmtSpec&, Buffer&, const wchar_t*, size_t, int);
+template int _rw_quotechar (char*, wchar_t, int);
+template int _rw_fmtarray(const FmtSpec&, Buffer&, const wchar_t*, size_t, int);
 
 #  endif   // _RWSTD_NO_WCHAR_T
 
@@ -3021,17 +2176,17 @@
         // note that when no precision is specified in the format string
         // (e.g., "%{Ac}") its value will be -1 and the function will format
         // all elements up to but excluding the terminating 0
-        len = rw_fmtarray (spec, buf, array, nelems, flags);
+        len = _rw_fmtarray (spec, buf, array, nelems, flags);
     }
     else if (2 == width) {
         spec.param.ptr_ = PARAM (ptr_);
         const _RWSTD_UINT16_T* const array = (_RWSTD_UINT16_T*)spec.param.ptr_;
-        len = rw_fmtarray (spec, buf, array, nelems, flags);
+        len = _rw_fmtarray (spec, buf, array, nelems, flags);
     }
     else if (4 == width) {
         spec.param.ptr_ = PARAM (ptr_);
         const _RWSTD_UINT32_T* const array = (_RWSTD_UINT32_T*)spec.param.ptr_;
-        len = rw_fmtarray (spec, buf, array, nelems, flags);
+        len = _rw_fmtarray (spec, buf, array, nelems, flags);
     }
 
 #ifdef _RWSTD_UINT64_T
@@ -3039,7 +2194,7 @@
     else if (8 == width) {
         spec.param.ptr_ = PARAM (ptr_);
         const _RWSTD_UINT64_T* const array = (_RWSTD_UINT64_T*)spec.param.ptr_;
-        len = rw_fmtarray (spec, buf, array, nelems, flags);
+        len = _rw_fmtarray (spec, buf, array, nelems, flags);
     }
 
 #endif   // _RWSTD_UINT64_T
@@ -3067,7 +2222,7 @@
 
     char buffer [8];
 
-    int len = rw_quotechar (buffer + spec.fl_pound, uc, noesc);
+    int len = _rw_quotechar (buffer + spec.fl_pound, uc, noesc);
     if (spec.fl_pound) {
         buffer [0] = buffer [len + 1] = '\'';
         buffer [len + 2] = '\0';
@@ -3101,7 +2256,7 @@
     else {
         const wchar_t wc = wchar_t (val);
 
-        len = rw_quotechar (buffer + spec.fl_pound, wc, noesc);
+        len = _rw_quotechar (buffer + spec.fl_pound, wc, noesc);
         if (spec.fl_pound) {
             buffer [0] = buffer [len + 1] = '\'';
             buffer [len + 2] = '\0';
@@ -3116,11 +2271,11 @@
 
 /********************************************************************/
 
-static int
+extern int
 _rw_fmtstr (const FmtSpec &spec, Buffer &buf, const char *str, size_t len)
 {
     if (spec.fl_pound)
-        return rw_fmtarray (spec, buf, str, len, A_CHAR | A_ESC);
+        return _rw_fmtarray (spec, buf, str, len, A_CHAR | A_ESC);
 
     if (0 == str || 0 > _RW::__rw_memattr (str, _RWSTD_SIZE_MAX, 0))
         return _rw_fmtbadaddr (spec, buf, str);
@@ -3190,7 +2345,7 @@
               ('S' == spec.cvtspec && -1 != spec.width ? A_ARRAY : 0)
             | A_WCHAR | A_ESC;
 
-        return rw_fmtarray (spec, buf, wstr, len, flags);
+        return _rw_fmtarray (spec, buf, wstr, len, flags);
     }
 
     if (   0 == wstr || 0 > _RW::__rw_memattr (wstr, _RWSTD_SIZE_MAX, 0)
@@ -3239,7 +2394,7 @@
 
     // wmemcpy (next, wstr, len);
     for (const wchar_t *pwc = wstr; pwc != wstr + len; ++pwc) {
-        const int n = rw_quotechar (next, *pwc, 0);
+        const int n = _rw_quotechar (next, *pwc, 0);
 
         if (n < 0)
             return n;
@@ -3263,360 +2418,6 @@
 
 /********************************************************************/
 
-struct Bitnames
-{
-    const char *longname;
-    const char *name;
-    int         bits;
-};
-
-#define BITNAME(qual, name)   { #qual "::" #name, #name, qual::name }
-
-static int
-rw_bmpfmt (const FmtSpec &spec, Buffer &buf,
-           const Bitnames bmap[], size_t size, int bits)
-{
-    RW_ASSERT (0 != buf.pbuf);
-
-    char buffer [1024];
-    *buffer = '\0';
-
-    // string to use when no bits are set
-    const char* all_clear = "0";
-
-    for (size_t i = 0; i != size; ++i) {
-        if (bmap [i].bits) {
-            if ((bits & bmap [i].bits) == bmap [i].bits) {
-
-                const char* const name = spec.fl_pound ?
-                    bmap [i].longname : bmap [i].name;
-
-                strcat (*buffer ? strcat (buffer, " | ") : buffer, name);
-
-                bits &= ~bmap [i].bits;
-            }
-        }
-        else {
-            // save the name of the constant to use for 0
-            all_clear = spec.fl_pound ? bmap [i].longname : bmap [i].name;
-        }
-    }
-
-    size_t buffersize;
-
-    if ('\0' == *buffer) {
-        // no constant matched, format teh value either as a number
-        // or, when 0, using the all_clear name (see above)
-        if (bits)
-            sprintf (buffer, "%#x", bits);
-        else
-            strcpy (buffer, all_clear);
-
-        buffersize = strlen (buffer);
-    }
-    else if (bits) {
-        buffersize = strlen (buffer);
-
-        // verify that buffer wasn't overflowed
-        RW_ASSERT (buffersize <= sizeof buffer);
-
-        char bitstr [32];
-        const int n = sprintf (bitstr, "%#x | ", bits);
-
-        RW_ASSERT (0 < n);
-
-        memmove (buffer + n, buffer, buffersize);
-        memcpy (buffer, bitstr, size_t (n));
-
-        buffersize += n;
-    }
-    else {
-        buffersize = strlen (buffer);
-    }
-
-    // verify that buffer wasn't overflowed
-    RW_ASSERT (buffersize <= sizeof buffer);
-
-    if (0 == _rw_bufcat (buf, buffer, buffersize))
-        return -1;
-
-    return int (buffersize);
-}
-
-/********************************************************************/
-
-static int
-_rw_fmtflags (const FmtSpec &spec, Buffer &buf, int bits)
-{
-    static const Bitnames names [] = {
-        BITNAME (std::ios, adjustfield),
-        BITNAME (std::ios, basefield),
-        BITNAME (std::ios, boolalpha),
-        BITNAME (std::ios, dec),
-        BITNAME (std::ios, fixed),
-        BITNAME (std::ios, hex),
-        BITNAME (std::ios, internal),
-        BITNAME (std::ios, left),
-        BITNAME (std::ios, oct),
-        BITNAME (std::ios, right),
-        BITNAME (std::ios, scientific),
-        BITNAME (std::ios, showbase),
-        BITNAME (std::ios, showpoint),
-        BITNAME (std::ios, showpos),
-        BITNAME (std::ios, skipws),
-        BITNAME (std::ios, unitbuf),
-        BITNAME (std::ios, uppercase),
-
-#ifndef _RWSTD_NO_EXT_BIN_IO
-
-        // extension: produce binary output (similar to oct, dec, and hex)
-        BITNAME (std::ios, bin),
-
-#endif   // _RWSTD_NO_EXT_BIN_IO
-
-#ifndef _RWSTD_NO_EXT_REENTRANT_IO
-
-        // extension: allow unsychronized access to stream and/or its buffer
-        BITNAME (std::ios, nolock),
-        BITNAME (std::ios, nolockbuf),
-
-#endif   // _RWSTD_NO_EXT_REENTRANT_IO
-
-        { "std::ios::iostate(0)", "iostate(0)", std::ios::iostate () }
-
-    };
-
-    static const size_t count = sizeof names / sizeof *names;
-
-    const int base = (bits >> _RWSTD_IOS_BASEOFF) & _RWSTD_IOS_BASEMASK;
-
-    // zero out bits representingthe numeric base
-    bits &= ~(_RWSTD_IOS_BASEMASK << _RWSTD_IOS_BASEOFF);
-
-    int len = rw_bmpfmt (spec, buf, names, count, bits);
-
-    if (base && base != 8 && base != 10 && base != 16) {
-
-        // for numeric bases other than those required by the standard,
-        // use the text "base (%d)" to show the extended numeric base
-
-#ifndef _RWSTD_NO_EXT_BIN_IO
-
-        if (bits & std::ios::bin)
-            return len;
-
-#endif   // _RWSTD_NO_EXT_BIN_IO
-
-        char basestr [64];
-        const int n = sprintf (basestr, " | std::ios::base(%d)", base);
-        len += n;
-
-        if (0 == _rw_bufcat (buf, basestr, size_t (n)))
-            return -1;
-    }
-
-    return len;
-}
-
-/********************************************************************/
-
-static int
-rw_fmtiostate (const FmtSpec &spec, Buffer &buf, int bits)
-{
-    static const Bitnames names [] = {
-        BITNAME (std::ios, goodbit),
-        BITNAME (std::ios, badbit),
-        BITNAME (std::ios, eofbit),
-        BITNAME (std::ios, failbit)
-    };
-
-    static const size_t count = sizeof names / sizeof *names;
-
-    return rw_bmpfmt (spec, buf, names, count, bits);
-}
-
-/********************************************************************/
-
-static int
-_rw_fmtopenmode (const FmtSpec &spec, Buffer &buf, int bits)
-{
-    static const Bitnames names [] = {
-
-#ifndef _RWSTD_NO_EXTENSIONS
-
-        { "std::ios::nocreate", "nocreate", std::ios::nocreate },
-        { "std::ios::noreplace", "noreplace", std::ios::noreplace },
-
-#else   // if defined (_RWSTD_NO_EXTENSIONS)
-
-        { "__rw:::__rw_nocreate", "__rw_nocreate", _RW::__rw_nocreate },
-        { "__rw::__rw_noreplace", "__rw_noreplace", _RW::__rw_noreplace },
-
-#endif   // _RWSTD_NO_EXTENSIONS
-
-#ifndef _RWSTD_NO_EXT_STDIO
-
-        { "std::ios::stdio", "stdio", std::ios::stdio },
-        { "std::ios::native", "native", std::ios::native },
-
-#else   // if defined (_RWSTD_NO_EXT_STDIO)
-
-        { "__rw::__rw_stdio", "__rw_stdio", _RW::__rw_stdio },
-        { "__rw::__rw_native", "__rw_native", _RW::__rw_native },
-
-#endif   // _RWSTD_NO_EXT_STDIO
-
-        BITNAME (std::ios, app),
-        BITNAME (std::ios, binary),
-        BITNAME (std::ios, in),
-        BITNAME (std::ios, out),
-        BITNAME (std::ios, trunc),
-        BITNAME (std::ios, ate),
-
-        { "std::ios::openmode(0)", "openmode(0)", std::ios::openmode () }
-    };
-
-    static const size_t count = sizeof names / sizeof *names;
-
-    return rw_bmpfmt (spec, buf, names, count, bits);
-}
-
-/********************************************************************/
-
-static int
-_rw_fmtseekdir (const FmtSpec &spec, Buffer &buf, int bits)
-{
-    static const Bitnames names [] = {
-
-        BITNAME (std::ios, beg),
-        BITNAME (std::ios, cur),
-        BITNAME (std::ios, end)
-    };
-
-    static const size_t count = sizeof names / sizeof *names;
-
-    return rw_bmpfmt (spec, buf, names, count, bits);
-}
-
-/********************************************************************/
-
-static int
-_rw_fmtevent (const FmtSpec&, Buffer &buf, int event)
-{
-    const char* str =
-          std::ios::copyfmt_event == event ? "copyfmt_event"
-        : std::ios::imbue_event   == event ? "imbue_event"
-        : std::ios::erase_event   == event ? "erase_event"
-        : 0;
-
-    char buffer [64];
-
-    if (!str) {
-        sprintf (buffer, "copyfmt_event(%d)", event);
-        str = buffer;
-    }
-
-    const size_t len = strlen (str);
-
-    if (0 == _rw_bufcat (buf, str, len))
-        return -1;
-
-    return int (len);
-}
-
-/********************************************************************/
-
-static int
-rw_fmtlc (const FmtSpec &spec, Buffer &buf, int val)
-{
-    const char *str = 0;
-
-    switch (val) {
-    case LC_ALL:      str = "LC_ALL"; break;
-    case LC_COLLATE:  str = "LC_COLLATE"; break;
-    case LC_CTYPE:    str = "LC_CTYPE"; break;
-    case LC_MONETARY: str = "LC_MONETARY"; break;
-    case LC_NUMERIC:  str = "LC_NUMERIC"; break;
-    case LC_TIME:     str = "LC_TIME"; break;
-
-#ifdef LC_MESSAGES
-    case LC_MESSAGES: str = "LC_MESSAGES"; break;
-#endif   // LC_MESSAGES
-
-    }
-
-    if (str) {
-        const std::size_t len = strlen (str);
-
-        if (0 == _rw_bufcat (buf, str, len))
-            return -1;
-
-        return int (len);
-    }
-
-    static const Bitnames names [] = {
-        BITNAME (std::locale, all),
-        BITNAME (std::locale, none),
-        BITNAME (std::locale, collate),
-        BITNAME (std::locale, ctype),
-        BITNAME (std::locale, monetary),
-        BITNAME (std::locale, numeric),
-        BITNAME (std::locale, messages),
-        BITNAME (std::locale, time)
-    };
-
-    static const size_t count = sizeof names / sizeof *names;
-
-    return rw_bmpfmt (spec, buf, names, count, val);
-}
-
-/********************************************************************/
-
-static int
-_rw_fmtmonpat (const FmtSpec&, Buffer &buf, const char pat [4])
-{
-    char buffer [80];
-
-    buffer [0] = '\0';
-
-    for (int i = 0; i != 4; ++i) {
-        switch (pat [i]) {
-        case std::money_base::symbol:
-            strcat (buffer, "symbol ");
-            break;
-
-        case std::money_base::sign:
-            strcat (buffer, "sign ");
-            break;
-
-        case std::money_base::none:
-            strcat (buffer, "none ");
-            break;
-
-        case std::money_base::value:
-            strcat (buffer, "value ");
-            break;
-
-        case std::money_base::space:
-            strcat (buffer, "space ");
-            break;
-
-        default:
-            sprintf (buffer + strlen (buffer), "\\%03o", pat [i]);
-            break;
-        }
-    }
-
-    const size_t len = strlen (buffer);
-
-    if (0 == _rw_bufcat (buf, buffer, len))
-        return -1;
-
-    return int (len);
-}
-
-/********************************************************************/
-
 static int
 _rw_vasnprintf_ext (FmtSpec    *pspec,
                     size_t      paramno,
@@ -3738,7 +2539,7 @@
         else if (spec.mod == spec.mod_L) {
             // locale category or LC_XXX constant
             spec.param.int_ = PARAM (int_);
-            len = rw_fmtlc (spec, buf, spec.param.int_);
+            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
@@ -3833,10 +2634,7 @@
         break;
 
     case 'm':   // %{m} -- errno
-        if (-1 == spec.width)
-            len = _rw_fmterrno (spec, buf, errno);
-        else
-            len = _rw_fmterrno (spec, buf, spec.width);
+        len = _rw_fmterrno (spec, buf, -1 == spec.width ? errno : spec.width);
         break;
 
     case 'M':   // %{M}, %{LM}
@@ -3918,21 +2716,21 @@
     case 's':   // %{s}, %{Is}, %{ls}
         if (spec.mod == spec.mod_ext_I) {   // ios::iostate
             spec.param.int_ = PARAM (int_);
-            len = rw_fmtiostate (spec, buf, spec.param.int_);
+            len = _rw_fmtiostate (spec, buf, spec.param.int_);
         }
         else if (spec.mod == spec.mod_l) {   // wchar_t*
             spec.param.ptr_ = PARAM (ptr_);
             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);
+            len = _rw_fmtarray (spec, buf, wstr, wstr_len, A_WCHAR | A_ESC);
         }
         else {   // char*
             spec.param.ptr_ = PARAM (ptr_);
             const char* const str = (char*)spec.param.ptr_;
             const size_t str_len =
                 spec.width < 0 ? _RWSTD_SIZE_MAX : size_t (spec.width);
-            len = rw_fmtarray (spec, buf, str, str_len, A_CHAR | A_ESC);
+            len = _rw_fmtarray (spec, buf, str, str_len, A_CHAR | A_ESC);
         }
         break;
 
@@ -3991,32 +2789,190 @@
             break;
         }
     }
-        
 
     default:
         if (spec.strarg) {
-            // environment variable
-            const char* val = getenv (spec.strarg);
+            return _rw_fmtexpr (spec, buf, pva);
+        }
+        else {
+            char text [80];
+            len = sprintf (text, "%%{%.*s}", int (sizeof text - 3), fmt);
+            if (0 == _rw_bufcat (buf, text, size_t (len)))
+                return -1;
+        }
+    }
 
-            if (!val)
-                val = "";
+    return len;
+}
 
-            len = int (strlen (val));
+/********************************************************************/
 
-            if (0 == _rw_bufcat (buf, val, size_t (len)))
-                return -1;
+static int
+_rw_fmtexpr (FmtSpec &spec, Buffer &buf, va_list *pva)
+{
+    RW_ASSERT (0 != spec.strarg);
+
+    char oper [2] = "";
+    char *param = spec.strarg;
 
-            free (spec.strarg);
+    // look for the first operator character (if any)
+    char* word = strpbrk (param, ":+-=?");
+    if (word) {
+        if (':' == *word) {
+            if (   '+' == word [1] || '-' == word [1]
+                || '=' == word [1] || '?' == word [1]) {
+                oper [0] = word [0];
+                oper [1] = word [1];
+                *word    = '\0';
+                word    += 2;
+            }
+            else {
+                // ':' without an immediately following '+', '-',
+                // '=', or '?' is not special
+            }
         }
         else {
-            char text [80];
-            len = sprintf (text, "*** %%{%.*s}: not implemented ***",
-                           int (sizeof fmt - 40), fmt);
+            oper [0] = *word;
+            *word++ = '\0';
+        }
+    }
+    else
+        word = oper;
 
-            if (0 == _rw_bufcat (buf, text, size_t (len)))
-                return -1;
+    if ('*' == *param) {
+        // extract the name of the parameter from the argument list
+        param = va_arg (*pva, char*);
+    }
+
+    if ('*' == *word) {
+        // extract "word" from the argument list
+        word = va_arg (*pva, char*);
+    }
+
+    // retrieve the value of the parameter from the environments
+    const char* val = getenv (param);
+
+    //////////////////////////////////////////////////////////////////
+    // From IEEE Std 1003.1, 2004 Edition:
+    // http://www.opengroup.org/onlinepubs/009695399/utilities/
+    //     xcu_chap02.html#tag_02_06_02
+
+    // +--------------------+-------------+-------------+-------------+
+    // |                    |  parameter  |  parameter  |  parameter  |
+    // |                    +-------------+-------------+-------------+
+    // |                    |Set, Not Null|  Set, Null  |   Unset     |
+    // +--------------------+-------------+-------------+-------------+
+    // | ${parameter:-word} |  parameter  |    word     |    word     |
+    // | ${parameter-word}  |  parameter  |    null     |    word     |
+    // | ${parameter:=word} |  parameter  | assign word | assign word |
+    // | ${parameter=word}  |  parameter  |    null     | assign word |
+    // | ${parameter:?word} |  parameter  |    error    |    error    |
+    // | ${parameter?word}  |  parameter  |    null     |    error    |
+    // | ${parameter:+word} |     word    |    null     |    null     |
+    // | ${parameter+word}  |     word    |    word     |    null     |
+    // +--------------------+-------------+-------------+-------------+
+
+    int assign = 0;
+    int error  = 0;
+
+    switch (oper [0]) {
+    case ':':   // process two-character operators
+        if ('-' == oper [1]) {
+            if (0 == val || '\0' == *val)
+                val = word;
+        }
+        else if ('=' == oper [1]) {
+            if (0 == val || '\0' == *val) {
+                val    = word;
+                assign = 1;
+            }
+        }
+        else if ('?' == oper [1]) {
+            if (0 == val || '\0' == *val) {
+                val   = "";
+                error = 1;
+            }
+        }
+        else if ('+' == oper [1]) {
+            if (0 == val || '\0' == *val)
+                val = "";
+            else
+                val = word;
+        }
+        else {
+            // should never happen
+            RW_ASSERT (!"logic error");
+        }
+        break;
+
+    case '+':
+        val = val ? word : "";
+        break;
+
+    case '-':
+        if (0 == val)
+            val = word;
+        break;
+            
+    case '?':
+        if (0 == val) {
+            val   = "";
+            error = 1;
+        }
+        break;
+
+    case '=':
+        if (0 == val) {
+            val    = word;
+            assign = 1;
         }
+        break;
+
+    default:
+        break;
     }
+
+    RW_ASSERT (0 != val);
+    int len = int (strlen (val));
+
+    if (assign) {
+        // set/assign the specified value to the variable
+        char varbuf [256];
+        char *pbuf = varbuf;
+
+        const size_t varlen = strlen (param) + strlen (val) + 2;
+        if (sizeof varbuf < varlen)
+            pbuf = (char*)malloc (varlen);
+
+        strcpy (pbuf, param);
+        strcat (pbuf, "=");
+        strcat (pbuf, val);
+
+        rw_putenv (pbuf);
+        if (pbuf != varbuf)
+            free (varbuf);
+    }
+
+    if (error) {
+        // on error simply print the directive
+        if (oper [0])
+            spec.strarg [strlen (spec.strarg)] = oper [0];
+
+        char text [256];
+        len = sprintf (text, "%%{$%.*s}", int (sizeof text - 3), spec.strarg);
+        if (0 == _rw_bufcat (buf, text, size_t (len)))
+            return -1;
+    }
+    else {
+        // format the value of the variable (after assignment
+        // if it takes place)
+        if (0 == _rw_bufcat (buf, val, size_t (len)))
+            return -1;
+    }
+
+    free (spec.strarg);
+    spec.strarg     = 0;
+    spec.param.ptr_ = _RWSTD_CONST_CAST (char*, val);
 
     return len;
 }



Mime
View raw message