os/ossrv/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/printf.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/************************************************************************
sl@0
     2
 *
sl@0
     3
 * printf.cpp - definitions of the rw_printf family of functions
sl@0
     4
 *
sl@0
     5
 * $Id: printf.cpp 351515 2005-12-01 23:19:44Z sebor $
sl@0
     6
 *
sl@0
     7
 ************************************************************************
sl@0
     8
 *
sl@0
     9
 * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
sl@0
    10
 * Software division. Licensed under the Apache License, Version 2.0 (the
sl@0
    11
 * "License");  you may  not use this file except  in compliance with the
sl@0
    12
 * License.    You    may   obtain   a   copy   of    the   License    at
sl@0
    13
 * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
sl@0
    14
 * applicable law  or agreed to  in writing,  software  distributed under
sl@0
    15
 * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
sl@0
    16
 * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
sl@0
    17
 * for the specific language governing permissions  and limitations under
sl@0
    18
 * the License.
sl@0
    19
 * 
sl@0
    20
 **************************************************************************/
sl@0
    21
sl@0
    22
// expand _TEST_EXPORT macros
sl@0
    23
#define _RWSTD_TEST_SRC
sl@0
    24
#include <testdefs.h>
sl@0
    25
#include <printf.h>
sl@0
    26
sl@0
    27
#include <assert.h>   // for assert
sl@0
    28
#include <errno.h>    // for errno, errno constants
sl@0
    29
#include <float.h>    // for floating point macros
sl@0
    30
#include <locale.h>
sl@0
    31
#ifndef __SYMBIAN32__
sl@0
    32
#include <signal.h>   // for signal constant
sl@0
    33
#endif
sl@0
    34
#include <stdarg.h>   // for va_list, va_start, ...
sl@0
    35
#include <stddef.h>
sl@0
    36
#include <stdio.h>
sl@0
    37
#include <stdlib.h>
sl@0
    38
#include <string.h>
sl@0
    39
#include <wchar.h>
sl@0
    40
sl@0
    41
#if (defined (_WIN32) || defined (_WIN64)) && !defined(__SYMBIAN32__)
sl@0
    42
   // define macros to enable Win98 + WinNT support in <windows.h>
sl@0
    43
#  define _WIN32_WINNT 0x0410
sl@0
    44
#  define WINVER       0x400
sl@0
    45
#  include <windows.h>   // for IsDebuggerPresent()
sl@0
    46
#else
sl@0
    47
#  include <dlfcn.h>
sl@0
    48
#endif   // _WIN{32,64}
sl@0
    49
sl@0
    50
#include <ios>
sl@0
    51
#include <iostream>
sl@0
    52
#include <locale>
sl@0
    53
//#include <string>
sl@0
    54
#include <string.h>
sl@0
    55
sl@0
    56
#ifdef __ARMCC__
sl@0
    57
#pragma diag_suppress 61
sl@0
    58
#pragma diag_suppress 63
sl@0
    59
#endif
sl@0
    60
sl@0
    61
#define _RWSTD_NO_EXT_BIN_IO
sl@0
    62
#define _RWSTD_NO_EXT_REENTRANT_IO
sl@0
    63
sl@0
    64
#ifndef __SYMBIAN32__
sl@0
    65
sl@0
    66
_RWSTD_NAMESPACE (__rw) {
sl@0
    67
sl@0
    68
_RWSTD_EXPORT _RWSTD_SSIZE_T
sl@0
    69
 __rw_memattr (const void*, size_t, int);
sl@0
    70
sl@0
    71
}
sl@0
    72
sl@0
    73
#endif
sl@0
    74
sl@0
    75
/********************************************************************/
sl@0
    76
sl@0
    77
static const union {
sl@0
    78
    int           ival;
sl@0
    79
    unsigned char bytes [sizeof (int)];
sl@0
    80
} _rw_one = { 1 };
sl@0
    81
sl@0
    82
static const int
sl@0
    83
_rw_big_endian = '\0' == _rw_one.bytes [0];
sl@0
    84
sl@0
    85
sl@0
    86
/********************************************************************/
sl@0
    87
sl@0
    88
struct FmtSpec;
sl@0
    89
sl@0
    90
static int
sl@0
    91
_rw_fmtlong (const FmtSpec&, char**, size_t*, long);
sl@0
    92
sl@0
    93
#ifdef _RWSTD_LONG_LONG
sl@0
    94
sl@0
    95
static int
sl@0
    96
_rw_fmtllong (const FmtSpec&, char**, size_t*, _RWSTD_LONG_LONG);
sl@0
    97
sl@0
    98
#endif   // _RWSTD_LONG_LONG
sl@0
    99
sl@0
   100
static int
sl@0
   101
_rw_fmtinteger (FmtSpec*, size_t, char**, size_t*, va_list*);
sl@0
   102
sl@0
   103
static int
sl@0
   104
_rw_fmtfloating (const FmtSpec&, char**, size_t*, const void*);
sl@0
   105
sl@0
   106
_RWSTD_INTERNAL int
sl@0
   107
_rw_fmtptr (const FmtSpec&, char**, size_t*, const void*);
sl@0
   108
sl@0
   109
typedef void (*funptr_t)();
sl@0
   110
sl@0
   111
static int
sl@0
   112
_rw_fmtfunptr (const FmtSpec&, char**, size_t*, funptr_t);
sl@0
   113
sl@0
   114
struct DummyStruct;
sl@0
   115
typedef void (DummyStruct::*memptr_t)() const;
sl@0
   116
sl@0
   117
static int
sl@0
   118
_rw_fmtmemptr (const FmtSpec&, char**, size_t*, memptr_t);
sl@0
   119
sl@0
   120
static int
sl@0
   121
_rw_fmtstr (const FmtSpec&, char**, size_t*, const char*, size_t);
sl@0
   122
sl@0
   123
static int
sl@0
   124
_rw_fmtchr (const FmtSpec&, char**, size_t*, int);
sl@0
   125
sl@0
   126
static int
sl@0
   127
_rw_fmtwchr (const FmtSpec&, char**, size_t*, wint_t);
sl@0
   128
sl@0
   129
static int
sl@0
   130
_rw_fmtwstr (const FmtSpec&, char**, size_t*, const wchar_t*, size_t);
sl@0
   131
sl@0
   132
static int
sl@0
   133
_rw_fmterrno (const FmtSpec&, char**, size_t*, int);
sl@0
   134
sl@0
   135
static int
sl@0
   136
_rw_fmtopenmode (const FmtSpec&, char**, size_t*, int);
sl@0
   137
sl@0
   138
static int
sl@0
   139
_rw_fmtevent (const FmtSpec&, char**, size_t*, int);
sl@0
   140
sl@0
   141
static int
sl@0
   142
_rw_fmtmonpat (const FmtSpec&, char**, size_t*, const char [4]);
sl@0
   143
sl@0
   144
static int
sl@0
   145
_rw_fmtsignal (const FmtSpec&, char**, size_t*, int);
sl@0
   146
sl@0
   147
/********************************************************************/
sl@0
   148
sl@0
   149
struct FmtSpec
sl@0
   150
{
sl@0
   151
    // optional flags
sl@0
   152
    unsigned fl_minus  : 1;
sl@0
   153
    unsigned fl_plus   : 1;
sl@0
   154
    unsigned fl_pound  : 1;
sl@0
   155
    unsigned fl_space  : 1;
sl@0
   156
    unsigned fl_zero   : 1;
sl@0
   157
sl@0
   158
    // optional modifiers
sl@0
   159
    unsigned mod_A     : 1;    // extension (Arrays)
sl@0
   160
    unsigned mod_h     : 1;    // short modifier
sl@0
   161
    unsigned mod_hh    : 1;    // char modifier
sl@0
   162
    unsigned mod_l     : 1;    // long modifier
sl@0
   163
    unsigned mod_ll    : 1;    // long long modifier
sl@0
   164
    unsigned mod_j     : 1;    // intmax_t modifier
sl@0
   165
    unsigned mod_z     : 1;    // size_t modifier
sl@0
   166
    unsigned mod_t     : 1;    // ptrdiff_t modifier
sl@0
   167
    unsigned mod_L     : 1;    // long double modifier
sl@0
   168
    unsigned mod_I     : 1;    // extension
sl@0
   169
sl@0
   170
    unsigned cond       : 1;   // have an if/else clause
sl@0
   171
    unsigned cond_true  : 1;   // if/else clause is active (true)
sl@0
   172
    unsigned cond_begin : 1;   // beginning of an if/else clause
sl@0
   173
    unsigned cond_end   : 1;   // end of an if/else clause
sl@0
   174
sl@0
   175
    // note that the signedness of a bitfield is implementation-defined
sl@0
   176
    // unless explicitly declared signed or unsigned
sl@0
   177
sl@0
   178
    // extension: 8, 16, 32, and 64 bit integer width modifier
sl@0
   179
    signed int iwidth : 4;
sl@0
   180
sl@0
   181
    // extension: optional numerical base 2 - 36
sl@0
   182
    signed int base   : 7;
sl@0
   183
sl@0
   184
    // extension: optional parameter number
sl@0
   185
    long paramno;
sl@0
   186
sl@0
   187
    // optional width and precision
sl@0
   188
    int width;
sl@0
   189
    int prec;
sl@0
   190
sl@0
   191
    // extension: string argument
sl@0
   192
    char *strarg;
sl@0
   193
sl@0
   194
    // required conversion specifier
sl@0
   195
    int cvtspec;
sl@0
   196
sl@0
   197
    // extension: fill character
sl@0
   198
    int fill;
sl@0
   199
sl@0
   200
    union {
sl@0
   201
sl@0
   202
#ifndef _RWSTD_NO_LONG_DOUBLE
sl@0
   203
sl@0
   204
        long double      ldbl;
sl@0
   205
sl@0
   206
#endif   // _RWSTD_NO_LONG_DOUBLE
sl@0
   207
sl@0
   208
#ifdef _RWSTD_LONG_LONG
sl@0
   209
sl@0
   210
        _RWSTD_LONG_LONG llong;
sl@0
   211
sl@0
   212
#endif   // _RWSTD_LONG_LONG
sl@0
   213
sl@0
   214
        void*            ptr;
sl@0
   215
sl@0
   216
        int              i;
sl@0
   217
        long             lng;
sl@0
   218
sl@0
   219
        _RWSTD_INT32_T   i32;
sl@0
   220
sl@0
   221
#ifdef _RWSTD_INT64_T
sl@0
   222
        _RWSTD_INT64_T   i64;
sl@0
   223
#endif   // _RWSTD_INT64_T
sl@0
   224
sl@0
   225
        ptrdiff_t        diff;
sl@0
   226
        size_t           size;
sl@0
   227
        wint_t           wi;
sl@0
   228
sl@0
   229
        double           dbl;
sl@0
   230
        memptr_t         memptr;
sl@0
   231
        funptr_t         funptr;
sl@0
   232
    } param;
sl@0
   233
};
sl@0
   234
sl@0
   235
/********************************************************************/
sl@0
   236
sl@0
   237
/*
sl@0
   238
sl@0
   239
  C99 format specifier:
sl@0
   240
sl@0
   241
  % flags width [ . prec ] mod cvtspec
sl@0
   242
sl@0
   243
sl@0
   244
  GNU glibc format specifier:
sl@0
   245
sl@0
   246
  % [ paramno $] flags width [ . prec ] mod cvtspec
sl@0
   247
  or
sl@0
   248
  % [ paramno $] flags width . * [ paramno $] mod cvtspec
sl@0
   249
sl@0
   250
sl@0
   251
  Extended format specifier:
sl@0
   252
sl@0
   253
  % { [ paramno $] [ flags ] [ width [. prec ]] mod cvtspec }
sl@0
   254
  or
sl@0
   255
  % { [ paramno $] [ flags ] [@ base [. width [. prec ]]] mod cvtspec }
sl@0
   256
  or
sl@0
   257
  % { $ envvar }
sl@0
   258
sl@0
   259
sl@0
   260
*/
sl@0
   261
sl@0
   262
static int
sl@0
   263
_rw_fmtspec (FmtSpec *pspec, bool ext, const char *fmt, va_list *pva)
sl@0
   264
{
sl@0
   265
    assert (0 != pspec);
sl@0
   266
    assert (0 != fmt);
sl@0
   267
    assert (0 != pva);
sl@0
   268
sl@0
   269
    memset (pspec, 0, sizeof *pspec);
sl@0
   270
sl@0
   271
    pspec->iwidth  = -1;   // integer width not specified
sl@0
   272
    pspec->width   = -1;   // width not specified
sl@0
   273
    pspec->prec    = -1;   // precision not specified
sl@0
   274
    pspec->base    = -1;   // base not specified
sl@0
   275
    pspec->paramno = -1;   // paramno not specified
sl@0
   276
sl@0
   277
    const char* const fmtbeg = fmt;
sl@0
   278
sl@0
   279
    if (ext) {
sl@0
   280
        if ('$' == *fmt) {
sl@0
   281
sl@0
   282
            ++fmt;
sl@0
   283
sl@0
   284
            const char *str;
sl@0
   285
            if ('*' == *fmt) {
sl@0
   286
                str = va_arg (*pva, char*);
sl@0
   287
                if (!str)
sl@0
   288
                    str = "";
sl@0
   289
                ++fmt;
sl@0
   290
            }
sl@0
   291
            else {
sl@0
   292
                str  = fmt;
sl@0
   293
                fmt += strlen (fmt);
sl@0
   294
            }
sl@0
   295
sl@0
   296
            char *tmp = (char*)malloc (strlen (str));
sl@0
   297
            pspec->strarg = strcpy (tmp, str);
sl@0
   298
sl@0
   299
            return int (fmt - fmtbeg);
sl@0
   300
        }
sl@0
   301
    }
sl@0
   302
sl@0
   303
    // extension: extract the parameter number (if followed by '$')
sl@0
   304
    if ('1' <= *fmt && *fmt <= '9') {
sl@0
   305
        char *end;
sl@0
   306
        const long tmp = strtol (fmt, &end, 10);
sl@0
   307
sl@0
   308
        fmt = end;
sl@0
   309
sl@0
   310
        if ('$' == *fmt) {
sl@0
   311
            pspec->paramno = tmp;
sl@0
   312
            ++fmt;
sl@0
   313
        }
sl@0
   314
        else {
sl@0
   315
            // when not followed by '$' interpret the number
sl@0
   316
            // as the width (i.e., that follows the empty set
sl@0
   317
            // of flags)
sl@0
   318
            pspec->width = int (tmp);
sl@0
   319
        }
sl@0
   320
    }
sl@0
   321
sl@0
   322
    if (-1 == pspec->width) {
sl@0
   323
        // extract any number of optional flags
sl@0
   324
        for ( ; ; ++fmt) {
sl@0
   325
            switch (*fmt) {
sl@0
   326
            case '-': pspec->fl_minus = true; continue;
sl@0
   327
            case '+': pspec->fl_plus = true; continue;
sl@0
   328
            case '#': pspec->fl_pound = true; continue;
sl@0
   329
            case ' ': pspec->fl_space = true; continue;
sl@0
   330
            case '0': pspec->fl_zero = true; continue;
sl@0
   331
            }
sl@0
   332
            break;
sl@0
   333
        }
sl@0
   334
    }
sl@0
   335
sl@0
   336
    if (ext && '@' == *fmt) {
sl@0
   337
sl@0
   338
        ++fmt;
sl@0
   339
sl@0
   340
        // extract the numerical base
sl@0
   341
        if ('0' <= fmt [1] && fmt [1] <= '9') {
sl@0
   342
            char *end;
sl@0
   343
            pspec->base = int (strtol (fmt, &end, 10));
sl@0
   344
            fmt         = end;
sl@0
   345
        }
sl@0
   346
        else if ('*' == *fmt) {
sl@0
   347
            pspec->base = va_arg (*pva, int);
sl@0
   348
            ++fmt;
sl@0
   349
        }
sl@0
   350
sl@0
   351
        if ('.' == *fmt)
sl@0
   352
            ++fmt;
sl@0
   353
    }
sl@0
   354
sl@0
   355
    if (-1 == pspec->width) {
sl@0
   356
        // extract the optional width
sl@0
   357
        if ('0' <= *fmt && *fmt <= '9') {
sl@0
   358
            char *end;
sl@0
   359
            pspec->width = int (strtol (fmt, &end, 10));
sl@0
   360
            fmt          = end;
sl@0
   361
        }
sl@0
   362
        else if ('*' == *fmt) {
sl@0
   363
            pspec->width = va_arg (*pva, int);
sl@0
   364
sl@0
   365
            if (pspec->width < 0) {
sl@0
   366
                // 7.19.6.1, p5 of ISO/IEC 9899:1999:
sl@0
   367
                //   A negative field width argument is taken
sl@0
   368
                //   as a - flag followed by a positive field width.
sl@0
   369
                pspec->width    = -pspec->width;
sl@0
   370
                pspec->fl_minus = true;
sl@0
   371
            }
sl@0
   372
sl@0
   373
            ++fmt;
sl@0
   374
        }
sl@0
   375
    }
sl@0
   376
sl@0
   377
    // extract the optional precision
sl@0
   378
    if ('.' == *fmt) {
sl@0
   379
sl@0
   380
        ++fmt;
sl@0
   381
sl@0
   382
        if ('0' <= *fmt && *fmt <= '9') {
sl@0
   383
            char *end;
sl@0
   384
            pspec->prec = int (strtol (fmt, &end, 10));
sl@0
   385
            fmt         = end;
sl@0
   386
        }
sl@0
   387
        else if ('*' == *fmt) {
sl@0
   388
            pspec->prec = va_arg (*pva, int);
sl@0
   389
            ++fmt;
sl@0
   390
        }
sl@0
   391
    }
sl@0
   392
sl@0
   393
    // extract an optional modifier
sl@0
   394
    switch (*fmt) {
sl@0
   395
    case 'A':
sl@0
   396
        if (ext) {
sl@0
   397
            ++fmt;
sl@0
   398
            pspec->mod_A = true;
sl@0
   399
            break;
sl@0
   400
        }
sl@0
   401
        // fall thru
sl@0
   402
sl@0
   403
    case 'h':
sl@0
   404
        if ('h' == fmt [1]) {
sl@0
   405
            ++fmt;
sl@0
   406
            pspec->mod_hh = true;
sl@0
   407
        }
sl@0
   408
        else
sl@0
   409
            pspec->mod_h = true;
sl@0
   410
        ++fmt;
sl@0
   411
        break;
sl@0
   412
sl@0
   413
    case 'l':
sl@0
   414
        if ('l' == fmt [1]) {
sl@0
   415
            ++fmt;
sl@0
   416
            pspec->mod_ll = true;
sl@0
   417
        }
sl@0
   418
        else
sl@0
   419
            pspec->mod_l = true;
sl@0
   420
        ++fmt;
sl@0
   421
        break;
sl@0
   422
sl@0
   423
    case 'j': pspec->mod_j = true; ++fmt; break;
sl@0
   424
    case 'z': pspec->mod_z = true; ++fmt; break;
sl@0
   425
    case 't': pspec->mod_t = true; ++fmt; break;
sl@0
   426
    case 'L': pspec->mod_L = true; ++fmt; break;
sl@0
   427
sl@0
   428
    case 'I':
sl@0
   429
        if (ext) {
sl@0
   430
sl@0
   431
            ++fmt;
sl@0
   432
sl@0
   433
            if ('8' == *fmt) {
sl@0
   434
                pspec->iwidth = 1;
sl@0
   435
                ++fmt;
sl@0
   436
            }
sl@0
   437
            else if ('1' == fmt [0] && '6' == fmt [1]) {
sl@0
   438
                pspec->iwidth = 2;
sl@0
   439
                fmt += 2;
sl@0
   440
            }
sl@0
   441
            else if ('3' == fmt [0] && '2' == fmt [1]) {
sl@0
   442
                pspec->iwidth = 3;
sl@0
   443
                fmt += 2;
sl@0
   444
            }
sl@0
   445
            else if ('6' == fmt [0] && '4' == fmt [1]) {
sl@0
   446
                pspec->iwidth = 4;
sl@0
   447
                fmt += 2;
sl@0
   448
            }
sl@0
   449
            else {
sl@0
   450
                pspec->mod_I = true;
sl@0
   451
            }
sl@0
   452
            break;
sl@0
   453
        }
sl@0
   454
    }
sl@0
   455
sl@0
   456
    pspec->cvtspec = *fmt;
sl@0
   457
sl@0
   458
    if (pspec->cvtspec)
sl@0
   459
        ++fmt;
sl@0
   460
sl@0
   461
    return int (fmt - fmtbeg);
sl@0
   462
}
sl@0
   463
sl@0
   464
/********************************************************************/
sl@0
   465
sl@0
   466
_RWSTD_INTERNAL char*
sl@0
   467
_rw_bufcat (char **pbuf, size_t *pbufsize, const char *str, size_t len)
sl@0
   468
{
sl@0
   469
    assert (0 != pbuf);
sl@0
   470
    assert (0 != pbufsize);
sl@0
   471
sl@0
   472
          size_t buflen = *pbuf ? strlen (*pbuf) : 0;
sl@0
   473
    const size_t bufree = *pbuf ? *pbufsize - buflen : 0;
sl@0
   474
sl@0
   475
    if (bufree <= len || !*pbuf) {
sl@0
   476
sl@0
   477
        // for guard block
sl@0
   478
        static const char deadbeef[] = "\xde\xad\xbe\xef";
sl@0
   479
sl@0
   480
        size_t newbufsize = *pbufsize * 2 + 4;
sl@0
   481
sl@0
   482
        if (newbufsize <= buflen + len + 4)
sl@0
   483
            newbufsize = 2 * (buflen + len + 1) + 4;
sl@0
   484
sl@0
   485
        char* const newbuf = (char*)malloc (newbufsize);
sl@0
   486
sl@0
   487
        // return 0 on failure to allocate, let caller deal with it
sl@0
   488
        if (0 == newbuf)
sl@0
   489
            return 0;
sl@0
   490
sl@0
   491
        memcpy (newbuf, *pbuf, buflen);
sl@0
   492
sl@0
   493
        // append a guard block to the end of the buffer
sl@0
   494
        memcpy (newbuf + newbufsize - 4, deadbeef, 4);
sl@0
   495
sl@0
   496
        if (*pbuf) {
sl@0
   497
            // verify that we didn't write past the end of the buffer
sl@0
   498
            assert (0 == memcmp (*pbuf + *pbufsize, deadbeef, 4));
sl@0
   499
            free (*pbuf);
sl@0
   500
        }
sl@0
   501
sl@0
   502
        *pbuf     = newbuf;
sl@0
   503
        *pbufsize = newbufsize - 4;
sl@0
   504
sl@0
   505
        (*pbuf)[buflen] = '\0';
sl@0
   506
    }
sl@0
   507
sl@0
   508
    if (0 != str) {
sl@0
   509
        memcpy (*pbuf + buflen, str, len);
sl@0
   510
        buflen += len;
sl@0
   511
        (*pbuf)[buflen] = '\0';
sl@0
   512
    }
sl@0
   513
sl@0
   514
    return *pbuf + buflen;
sl@0
   515
}
sl@0
   516
sl@0
   517
/********************************************************************/
sl@0
   518
sl@0
   519
// rw_asnprintf_cb is called to format a character string according
sl@0
   520
// to the single format specifier `fmt' to the end of the provided
sl@0
   521
// buffer `*pbuf'; the function can reallocate the buffer
sl@0
   522
// returns the number of characters appended to the buffer
sl@0
   523
extern int
sl@0
   524
(*rw_vasnprintf_cb)(FmtSpec*, size_t, char**, size_t*, const char*, va_list*);
sl@0
   525
sl@0
   526
/********************************************************************/
sl@0
   527
sl@0
   528
static int
sl@0
   529
_rw_vasnprintf_c99 (FmtSpec *pspec, size_t paramno,
sl@0
   530
                    char **pbuf, size_t *pbufsize, va_list *pva)
sl@0
   531
{
sl@0
   532
    _RWSTD_UNUSED (paramno);
sl@0
   533
sl@0
   534
    _RWSTD_ASSERT (0 != pspec);
sl@0
   535
sl@0
   536
    int len = -1;
sl@0
   537
sl@0
   538
    FmtSpec &spec = pspec [paramno];
sl@0
   539
sl@0
   540
#define PARAM(T, name)   \
sl@0
   541
  (0 < spec.paramno ? pspec [spec.paramno - 1].param.name : va_arg (*pva, T))
sl@0
   542
sl@0
   543
    switch (spec.cvtspec) {
sl@0
   544
sl@0
   545
    case 'd':
sl@0
   546
    case 'i':
sl@0
   547
    case 'o':
sl@0
   548
    case 'x':
sl@0
   549
    case 'X':
sl@0
   550
    case 'u':
sl@0
   551
        len = _rw_fmtinteger (pspec, paramno, pbuf, pbufsize, pva);
sl@0
   552
        break;
sl@0
   553
sl@0
   554
    case 'e':
sl@0
   555
    case 'E':
sl@0
   556
    case 'f':
sl@0
   557
    case 'F':
sl@0
   558
    case 'g':
sl@0
   559
    case 'G':
sl@0
   560
        if (spec.mod_L) {
sl@0
   561
            spec.param.ldbl = PARAM (long double, ldbl);
sl@0
   562
            len = _rw_fmtfloating (spec, pbuf, pbufsize, &spec.param.ldbl);
sl@0
   563
        }
sl@0
   564
        else {
sl@0
   565
            spec.param.dbl = PARAM (double, dbl);
sl@0
   566
            len = _rw_fmtfloating (spec, pbuf, pbufsize, &spec.param.dbl);
sl@0
   567
        }
sl@0
   568
        break;
sl@0
   569
sl@0
   570
    case 'a':
sl@0
   571
        assert (!"%a not implemented");
sl@0
   572
        break;
sl@0
   573
sl@0
   574
    case 'A':
sl@0
   575
        assert (!"%A not implemented");
sl@0
   576
        break;
sl@0
   577
sl@0
   578
    case 'c':
sl@0
   579
        // If no l length modifier is present, the int argument is converted
sl@0
   580
        // to an unsigned char, and the resulting character is written. If
sl@0
   581
        // an l length modifier is present, the wint_t argument is converted
sl@0
   582
        // as if by an ls conversion specification with no precision and an
sl@0
   583
        // argument that points to the initial element of a two-element array
sl@0
   584
        // of wchar_t, the first element containing the wint_t argument to
sl@0
   585
        // the lc conversion specification and the second a null wide
sl@0
   586
        // character.
sl@0
   587
        if (spec.mod_l) {
sl@0
   588
            spec.param.wi = PARAM (wint_t, wi);
sl@0
   589
            len = _rw_fmtwchr (spec, pbuf, pbufsize, spec.param.wi);
sl@0
   590
        }
sl@0
   591
        else {
sl@0
   592
            spec.param.i = PARAM (int, i);
sl@0
   593
            len = _rw_fmtchr (spec, pbuf, pbufsize, spec.param.i);
sl@0
   594
        }
sl@0
   595
        break;
sl@0
   596
sl@0
   597
    case 's':
sl@0
   598
        if (spec.mod_l) {
sl@0
   599
            spec.param.ptr = PARAM (wchar_t*, ptr);
sl@0
   600
            const wchar_t* const str = (wchar_t*)spec.param.ptr;
sl@0
   601
            len = _rw_fmtwstr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX);
sl@0
   602
        }
sl@0
   603
        else {
sl@0
   604
            spec.param.ptr = PARAM (char*, ptr);
sl@0
   605
            const char* const str = (char*)spec.param.ptr;
sl@0
   606
            len = _rw_fmtstr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX);
sl@0
   607
        }
sl@0
   608
        break;
sl@0
   609
sl@0
   610
    case 'p': {
sl@0
   611
        // The argument shall be a pointer to void. The value of the pointer
sl@0
   612
        // is converted to a sequence of printing characters, in an
sl@0
   613
        // implementation-defined manner.
sl@0
   614
        spec.param.ptr = PARAM (char*, ptr);
sl@0
   615
        len = _rw_fmtptr (spec, pbuf, pbufsize, spec.param.ptr);
sl@0
   616
        break;
sl@0
   617
    }
sl@0
   618
sl@0
   619
    case 'm': {   // %m (popular extension)
sl@0
   620
        spec.param.i = errno;
sl@0
   621
        len = _rw_fmterrno (spec, pbuf, pbufsize, spec.param.i);
sl@0
   622
        break;
sl@0
   623
    }
sl@0
   624
sl@0
   625
    case 'n': {
sl@0
   626
        // The argument shall be a pointer to signed integer into which
sl@0
   627
        // is written the number of characters written to the output
sl@0
   628
        // stream so far by this call to fprintf. No argument is converted,
sl@0
   629
        // but one is consumed. If the conversion specification includes
sl@0
   630
        // any flags, a field width, or a precision, the behavior is
sl@0
   631
        // undefined.
sl@0
   632
sl@0
   633
        assert (0 != pbuf);
sl@0
   634
        assert (0 != *pbuf);
sl@0
   635
sl@0
   636
        len = int (strlen (*pbuf));
sl@0
   637
sl@0
   638
        spec.param.ptr = PARAM (void*, ptr);
sl@0
   639
sl@0
   640
        if (spec.mod_hh) {
sl@0
   641
            unsigned char* const ptr = (unsigned char*)spec.param.ptr;
sl@0
   642
sl@0
   643
            assert (0 != ptr);
sl@0
   644
sl@0
   645
            *ptr = len;
sl@0
   646
        }
sl@0
   647
        else if (spec.mod_h) {
sl@0
   648
            short* const ptr = (short*)spec.param.ptr;
sl@0
   649
sl@0
   650
            assert (0 != ptr);
sl@0
   651
sl@0
   652
            *ptr = len;
sl@0
   653
        }
sl@0
   654
        else if (spec.mod_L) {
sl@0
   655
#ifdef _RWSTD_LONG_LONG
sl@0
   656
            _RWSTD_LONG_LONG* const ptr = (_RWSTD_LONG_LONG*)spec.param.ptr;
sl@0
   657
sl@0
   658
            assert (0 != ptr);
sl@0
   659
sl@0
   660
            *ptr = len;
sl@0
   661
#else   // if !defined (_RWSTD_LONG_LONG)
sl@0
   662
            assert (!"%Ln not implemented");
sl@0
   663
#endif   // _RWSTD_LONG_LONG
sl@0
   664
        }
sl@0
   665
        else if (spec.mod_l) {
sl@0
   666
            long* const ptr = (long*)spec.param.ptr;
sl@0
   667
sl@0
   668
            assert (0 != ptr);
sl@0
   669
sl@0
   670
            *ptr = len;
sl@0
   671
        }
sl@0
   672
        else if (spec.mod_t) {
sl@0
   673
            ptrdiff_t* const ptr = (ptrdiff_t*)spec.param.ptr;
sl@0
   674
sl@0
   675
            assert (0 != ptr);
sl@0
   676
sl@0
   677
            *ptr = ptrdiff_t (unsigned (len));
sl@0
   678
        }
sl@0
   679
        else {
sl@0
   680
            int* const ptr = (int*)spec.param.ptr;
sl@0
   681
sl@0
   682
            assert (0 != ptr);
sl@0
   683
sl@0
   684
            *ptr = len;
sl@0
   685
        }
sl@0
   686
        break;
sl@0
   687
    }
sl@0
   688
sl@0
   689
    case '%':
sl@0
   690
        break;
sl@0
   691
    }
sl@0
   692
sl@0
   693
    return len;
sl@0
   694
}
sl@0
   695
sl@0
   696
/********************************************************************/
sl@0
   697
sl@0
   698
_TEST_EXPORT int
sl@0
   699
rw_vasnprintf (char **pbuf, size_t *pbufsize, const char *fmt, va_list varg)
sl@0
   700
{
sl@0
   701
    va_list *pva;
sl@0
   702
sl@0
   703
#ifdef va_copy
sl@0
   704
    // create a copy of va whose address can be passed to a function
sl@0
   705
    // taking a va_list* so that it can modify the original; note that
sl@0
   706
    // passing &va is not portable since when declared as a function
sl@0
   707
    // argument, va_list that is an array type decays into a pointer
sl@0
   708
    // and the address of the pointer will not match va_list* (as is
sl@0
   709
    // the case on EM64T)
sl@0
   710
    va_list vacpy;
sl@0
   711
    va_copy (vacpy, varg);
sl@0
   712
    pva = &vacpy;
sl@0
   713
sl@0
   714
#else   // if !defined (va_copy)
sl@0
   715
sl@0
   716
#  if 2 < __GNUG__
sl@0
   717
sl@0
   718
    // use the gcc 3.x builtin when the va_copy macro is not defined
sl@0
   719
    // (e.g., with gcc -ansi or Intel C++ icc -ansi or -strict_ansi)
sl@0
   720
    va_list vacpy;
sl@0
   721
    __builtin_va_copy (vacpy, varg);
sl@0
   722
    pva = &vacpy;
sl@0
   723
sl@0
   724
#  else   // if !defined (__GNUG__)
sl@0
   725
sl@0
   726
    // use varg (in)directly and assume it's safe (e.g., HP aCC on PA)
sl@0
   727
    pva = &varg;
sl@0
   728
sl@0
   729
#  endif   // 2 < __GNUG__
sl@0
   730
sl@0
   731
#endif   // va_copy
sl@0
   732
sl@0
   733
// do not use varg of vacpy below this point -- use *pva instead
sl@0
   734
#define varg  DONT_TOUCH_ME
sl@0
   735
#define vacpy DONT_TOUCH_ME
sl@0
   736
sl@0
   737
    assert (0 != pbuf);
sl@0
   738
sl@0
   739
    // save the initial value of `pbuf'
sl@0
   740
    char* const pbuf_save = *pbuf;
sl@0
   741
sl@0
   742
    if (*pbuf)
sl@0
   743
        **pbuf = '\0';
sl@0
   744
sl@0
   745
    // local buffer for a small number of conversion specifiers
sl@0
   746
    // will grow dynamically if their number exceeds its capacity
sl@0
   747
    FmtSpec specbuf [32];
sl@0
   748
    FmtSpec *pspec = specbuf;
sl@0
   749
sl@0
   750
    // local buffer for backtrack offsets implementing conditionals
sl@0
   751
    int backtrack [32];
sl@0
   752
    int nextoff = 0;
sl@0
   753
sl@0
   754
    size_t default_bufsize = 1024;
sl@0
   755
sl@0
   756
    if (0 == pbufsize)
sl@0
   757
        pbufsize = &default_bufsize;
sl@0
   758
sl@0
   759
    char fmtspec [64];
sl@0
   760
sl@0
   761
    char *next = *pbuf;
sl@0
   762
sl@0
   763
    size_t spec_bufsize = sizeof specbuf / sizeof *specbuf;
sl@0
   764
    size_t paramno = 0;
sl@0
   765
sl@0
   766
    for (const char *fc = fmt; *fc; ) {
sl@0
   767
sl@0
   768
        const char* const pcnt = strchr (fc, '%');
sl@0
   769
sl@0
   770
        size_t nchars = pcnt ? pcnt - fmt : strlen (fc);
sl@0
   771
sl@0
   772
        next = _rw_bufcat (pbuf, pbufsize, fmt, nchars);
sl@0
   773
        if (0 == next)
sl@0
   774
            goto fail;
sl@0
   775
sl@0
   776
        assert (0 != *pbuf);
sl@0
   777
        assert (0 != *pbufsize);
sl@0
   778
sl@0
   779
        if (0 == pcnt)
sl@0
   780
            break;
sl@0
   781
sl@0
   782
        fc = pcnt + 1;
sl@0
   783
sl@0
   784
        if ('%' == *fc) {
sl@0
   785
            // handle "%%"
sl@0
   786
            next = _rw_bufcat (pbuf, pbufsize, "%", 1);
sl@0
   787
            if (0 == next)
sl@0
   788
                goto fail;
sl@0
   789
sl@0
   790
            fmt = ++fc;
sl@0
   791
            continue;
sl@0
   792
        }
sl@0
   793
sl@0
   794
        if (spec_bufsize == paramno) {
sl@0
   795
            // grow the buffer of conversion specifiers
sl@0
   796
            FmtSpec *tmp = (FmtSpec*)malloc (spec_bufsize * 2);
sl@0
   797
            if (tmp) {
sl@0
   798
                memcpy (tmp, pspec, spec_bufsize);
sl@0
   799
                if (pspec != specbuf)
sl@0
   800
                    free (pspec);
sl@0
   801
                pspec = tmp;
sl@0
   802
            }
sl@0
   803
            else
sl@0
   804
                goto fail;
sl@0
   805
        }
sl@0
   806
sl@0
   807
        if ('{' == *fc) {
sl@0
   808
            const char* const endbrace = strchr (++fc, '}');
sl@0
   809
sl@0
   810
            assert (0 != endbrace);
sl@0
   811
sl@0
   812
            const size_t fmtlen = endbrace - fc;
sl@0
   813
sl@0
   814
            memcpy (fmtspec, fc, fmtlen);
sl@0
   815
            fmtspec [fmtlen] = '\0';
sl@0
   816
sl@0
   817
            // compute the length of the buffer so far
sl@0
   818
            const size_t buflen = next - *pbuf;
sl@0
   819
sl@0
   820
            assert (0 != rw_vasnprintf_cb);
sl@0
   821
sl@0
   822
            // initiaze the current format specification, setting
sl@0
   823
            // all unused bits to 0
sl@0
   824
            const int speclen =
sl@0
   825
                _rw_fmtspec (pspec + paramno, true, fc, pva);
sl@0
   826
sl@0
   827
            _RWSTD_UNUSED (speclen);
sl@0
   828
sl@0
   829
            // copy the current backtrack offset if one exists
sl@0
   830
            // and set the condition and condition true bits
sl@0
   831
            if (nextoff) {
sl@0
   832
sl@0
   833
                // set the condition valid bit
sl@0
   834
                pspec [paramno].cond = 1;
sl@0
   835
sl@0
   836
                if (backtrack [nextoff - 1] < 0) {
sl@0
   837
                    // negative offset indicates an active clause
sl@0
   838
                    pspec [paramno].cond_true = 1;
sl@0
   839
                }
sl@0
   840
                else {
sl@0
   841
                    // non-negative offset indicates an inactive clause
sl@0
   842
                    // no-op
sl@0
   843
                }
sl@0
   844
            }
sl@0
   845
sl@0
   846
            // append formatted string to the end of the buffer
sl@0
   847
            // reallocating it if necessary; callee may change
sl@0
   848
            // the specification as necessary (e.g., based on
sl@0
   849
            // the if/else clause)
sl@0
   850
sl@0
   851
            int len =
sl@0
   852
                rw_vasnprintf_cb (pspec, paramno, pbuf, pbufsize,
sl@0
   853
                                  fmtspec, pva);
sl@0
   854
sl@0
   855
            // the callback returns a negative value on error
sl@0
   856
            if (len < 0)
sl@0
   857
                goto fail;
sl@0
   858
sl@0
   859
            assert (size_t (len) < *pbufsize);
sl@0
   860
            assert (strlen (*pbuf) < *pbufsize);
sl@0
   861
sl@0
   862
            const size_t offinx = nextoff - 1;
sl@0
   863
sl@0
   864
            if (pspec [paramno].cond_end && pspec [paramno].cond_begin) {
sl@0
   865
                // change from an if to an else clause
sl@0
   866
sl@0
   867
                assert (0 < nextoff);
sl@0
   868
                assert (0 == len);
sl@0
   869
sl@0
   870
                if (pspec [paramno].cond_true) {
sl@0
   871
                    // change from an inactive if to an active else
sl@0
   872
                    // (same as the end of an inactive clause)
sl@0
   873
sl@0
   874
                    assert (0 <= backtrack [offinx]);
sl@0
   875
sl@0
   876
                    // set the length so as to backtrack to the position
sl@0
   877
                    // saved on the top of the backtrack stack 
sl@0
   878
                    len = -int (buflen) + backtrack [offinx];
sl@0
   879
sl@0
   880
                    // invert the offset to indicate an active clause
sl@0
   881
                    backtrack [offinx] = ~backtrack [offinx];
sl@0
   882
                }
sl@0
   883
                else {
sl@0
   884
                    // change from an active if to an inactive else
sl@0
   885
                    assert (backtrack [offinx] < 0);
sl@0
   886
sl@0
   887
                    // save the current length of the buffer
sl@0
   888
                    // as the new backtrack offset
sl@0
   889
                    backtrack [offinx] = int (buflen);
sl@0
   890
                }
sl@0
   891
            }
sl@0
   892
            else if (pspec [paramno].cond_begin) {
sl@0
   893
                // start of a new if clause
sl@0
   894
sl@0
   895
                // push it on the stack of backtracking offsets using
sl@0
   896
                // negative values to indicate active clauses and
sl@0
   897
                // non-negative values inactive ones
sl@0
   898
                if (pspec [paramno].cond_true)
sl@0
   899
                    backtrack [nextoff++] = ~int (buflen);
sl@0
   900
                else
sl@0
   901
                    backtrack [nextoff++] = int (buflen);
sl@0
   902
            }
sl@0
   903
            else if (pspec [paramno].cond_end) {
sl@0
   904
                // the end of an if/else clause
sl@0
   905
sl@0
   906
                if (!pspec [paramno].cond_true) {
sl@0
   907
                    // the end of an inactive clause
sl@0
   908
sl@0
   909
                    assert (backtrack [offinx] <= int (buflen));
sl@0
   910
sl@0
   911
                    // set the length so as to backtrack to the position
sl@0
   912
                    // saved on the top of the backtrack stack 
sl@0
   913
                    len = -int (buflen) + backtrack [offinx];
sl@0
   914
                }
sl@0
   915
sl@0
   916
                // pop it off the top of the stack
sl@0
   917
                --nextoff;
sl@0
   918
            }
sl@0
   919
sl@0
   920
            assert (len + buflen < *pbufsize);
sl@0
   921
sl@0
   922
            // adjust the next pointer to point to the terminating
sl@0
   923
            // NUL in the (possibly reallocated) buffer
sl@0
   924
            next  = *pbuf + buflen + len;
sl@0
   925
            *next = '\0';
sl@0
   926
            fc    = endbrace + 1;
sl@0
   927
        }
sl@0
   928
        else {
sl@0
   929
            const int speclen =
sl@0
   930
                _rw_fmtspec (pspec + paramno, false, fc, pva);
sl@0
   931
sl@0
   932
            if (speclen) {
sl@0
   933
sl@0
   934
                const int len =
sl@0
   935
                    _rw_vasnprintf_c99 (pspec, paramno, pbuf, pbufsize, pva);
sl@0
   936
sl@0
   937
                if (-1 == len)
sl@0
   938
                    goto fail;
sl@0
   939
sl@0
   940
                // discard positional specifiers
sl@0
   941
                if (-1 == pspec [paramno].paramno)
sl@0
   942
                    ++paramno;
sl@0
   943
sl@0
   944
                next = _rw_bufcat (pbuf, pbufsize, 0, size_t (len));
sl@0
   945
                if (0 == next)
sl@0
   946
                    goto fail;
sl@0
   947
sl@0
   948
                next += len;
sl@0
   949
                fc   += speclen;
sl@0
   950
            }
sl@0
   951
            else {
sl@0
   952
                next = _rw_bufcat (pbuf, pbufsize, "%", 1);
sl@0
   953
                if (0 == next)
sl@0
   954
                    goto fail;
sl@0
   955
            }
sl@0
   956
        }
sl@0
   957
sl@0
   958
        fmt = fc;
sl@0
   959
    }
sl@0
   960
sl@0
   961
    // deallocate if dynamically allocated
sl@0
   962
    if (pspec != specbuf)
sl@0
   963
        free (pspec);
sl@0
   964
sl@0
   965
    return int (next - *pbuf);
sl@0
   966
sl@0
   967
fail: // function failed
sl@0
   968
sl@0
   969
    fprintf (stderr, "%s:%d: rw_vasnprintf(%p, %p, \"%s\", va_list) "
sl@0
   970
             "error: errno = %d: %s\n",
sl@0
   971
             __FILE__, __LINE__, (void*)pbuf, (void*)pbufsize, fmt,
sl@0
   972
             errno, strerror (errno));
sl@0
   973
sl@0
   974
    if (pspec != specbuf)
sl@0
   975
        free (pspec);
sl@0
   976
sl@0
   977
    if (*pbuf != pbuf_save) {
sl@0
   978
        // free any allocated memory
sl@0
   979
        free (*pbuf);
sl@0
   980
        *pbuf = 0;
sl@0
   981
    }
sl@0
   982
sl@0
   983
    return -1;
sl@0
   984
sl@0
   985
#undef varg
sl@0
   986
#undef vacpy
sl@0
   987
sl@0
   988
}
sl@0
   989
sl@0
   990
/********************************************************************/
sl@0
   991
sl@0
   992
static const char _rw_digits[] = {
sl@0
   993
    "0123456789abcdefghijklmnopqrstuvwxyz"
sl@0
   994
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
sl@0
   995
};
sl@0
   996
sl@0
   997
static int
sl@0
   998
_rw_fmtlong (const FmtSpec &spec, char **pbuf, size_t *pbufsize, long val)
sl@0
   999
{
sl@0
  1000
    char buffer [130];   // big enough for a 128-bit long in base 2
sl@0
  1001
    char *end = buffer;
sl@0
  1002
sl@0
  1003
    long upoff = 0;
sl@0
  1004
    const char *pfx = 0;
sl@0
  1005
sl@0
  1006
    if ('X' == spec.cvtspec)
sl@0
  1007
        upoff  = 36;
sl@0
  1008
sl@0
  1009
    if (spec.fl_pound) {
sl@0
  1010
        if (16 == spec.base)
sl@0
  1011
            pfx = upoff ? "0X" : "0x";
sl@0
  1012
        else if (8 == spec.base && val)
sl@0
  1013
            pfx = "0";
sl@0
  1014
    }
sl@0
  1015
sl@0
  1016
    const int base = 1 < spec.base && spec.base < 37 ? spec.base : 10;
sl@0
  1017
sl@0
  1018
    typedef unsigned long ULong;
sl@0
  1019
sl@0
  1020
    ULong uval;
sl@0
  1021
sl@0
  1022
    bool neg;
sl@0
  1023
sl@0
  1024
    if (val < 0) {
sl@0
  1025
        neg  = 'd' == spec.cvtspec || 'i' == spec.cvtspec;
sl@0
  1026
        uval = ULong (neg ? -val : val);
sl@0
  1027
    }
sl@0
  1028
    else {
sl@0
  1029
        neg  = false;
sl@0
  1030
        uval = ULong (val);
sl@0
  1031
    }
sl@0
  1032
sl@0
  1033
    do {
sl@0
  1034
        *end++ = _rw_digits [upoff + uval % base];
sl@0
  1035
    } while (uval /= base);
sl@0
  1036
sl@0
  1037
    int size = int (end - buffer);
sl@0
  1038
sl@0
  1039
    // insert as many zeros as specified by precision
sl@0
  1040
    if (-1 < spec.prec && size < spec.prec) {
sl@0
  1041
        // FIXME: prevent buffer overrun
sl@0
  1042
        for (int i = size; i != spec.prec; ++i)
sl@0
  1043
            *end++ = '0';
sl@0
  1044
    }
sl@0
  1045
sl@0
  1046
    // insert octal or hex prefix for non-zero values
sl@0
  1047
    if (pfx && val) {
sl@0
  1048
        if (pfx [1])
sl@0
  1049
            *end++ = pfx [1];
sl@0
  1050
        *end++ = pfx [0];
sl@0
  1051
    }
sl@0
  1052
sl@0
  1053
    if (neg)
sl@0
  1054
        *end++ = '-';
sl@0
  1055
    else if (spec.fl_plus && ('d' == spec.cvtspec || 'i' == spec.cvtspec))
sl@0
  1056
        *end++ = '+';
sl@0
  1057
sl@0
  1058
    if (0 == spec.prec && 0 == val) {
sl@0
  1059
        // 7.19.6.1 of ISO/IEC 9899:1999:
sl@0
  1060
        //   The result of converting a zero value with a precision
sl@0
  1061
        //   of zero is no characters.
sl@0
  1062
        end = buffer;
sl@0
  1063
    }
sl@0
  1064
sl@0
  1065
    *end = '\0';
sl@0
  1066
sl@0
  1067
    size = int (end - buffer);
sl@0
  1068
sl@0
  1069
    for (char *pc = buffer; pc < end; ++pc) {
sl@0
  1070
        const char tmp = *pc;
sl@0
  1071
        *pc = *--end;
sl@0
  1072
        *end = tmp;
sl@0
  1073
    }
sl@0
  1074
sl@0
  1075
    // reset precision to -1 (already handled above)
sl@0
  1076
    FmtSpec newspec (spec);
sl@0
  1077
    newspec.fl_pound = 0;
sl@0
  1078
    newspec.prec = -1;
sl@0
  1079
sl@0
  1080
    // handle justification by formatting the resulting string
sl@0
  1081
    return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (size));
sl@0
  1082
}
sl@0
  1083
sl@0
  1084
/********************************************************************/
sl@0
  1085
sl@0
  1086
#ifdef _RWSTD_LONG_LONG
sl@0
  1087
sl@0
  1088
static int
sl@0
  1089
_rw_fmtllong (const FmtSpec &spec,
sl@0
  1090
             char **pbuf, size_t *pbufsize, _RWSTD_LONG_LONG val)
sl@0
  1091
{
sl@0
  1092
    char buffer [130];   // big enough for a 128-bit long long in base 2
sl@0
  1093
    char *end = buffer;
sl@0
  1094
sl@0
  1095
    long upoff = 0;
sl@0
  1096
    const char *pfx = 0;
sl@0
  1097
sl@0
  1098
    if ('X' == spec.cvtspec)
sl@0
  1099
        upoff  = 36;
sl@0
  1100
sl@0
  1101
    if (spec.fl_pound) {
sl@0
  1102
        if (16 == spec.base)
sl@0
  1103
            pfx = upoff ? "0X" : "0x";
sl@0
  1104
        else if (8 == spec.base && val)
sl@0
  1105
            pfx = "0";
sl@0
  1106
    }
sl@0
  1107
sl@0
  1108
    const int base = 1 < spec.base && spec.base < 37 ? spec.base : 10;
sl@0
  1109
sl@0
  1110
    typedef unsigned _RWSTD_LONG_LONG ULLong;
sl@0
  1111
sl@0
  1112
    ULLong uval;
sl@0
  1113
sl@0
  1114
    bool neg;
sl@0
  1115
sl@0
  1116
    if (val < 0) {
sl@0
  1117
        neg  = 'd' == spec.cvtspec || 'i' == spec.cvtspec;
sl@0
  1118
        uval = ULLong (neg ? -val : val);
sl@0
  1119
    }
sl@0
  1120
    else {
sl@0
  1121
        neg  = false;
sl@0
  1122
        uval = ULLong (val);
sl@0
  1123
    }
sl@0
  1124
sl@0
  1125
    do {
sl@0
  1126
        *end++ = _rw_digits [upoff + uval % base];
sl@0
  1127
    } while (uval /= base);
sl@0
  1128
sl@0
  1129
    if (pfx) {
sl@0
  1130
        if (pfx [1])
sl@0
  1131
            *end++ = pfx [1];
sl@0
  1132
        *end++ = pfx [0];
sl@0
  1133
    }
sl@0
  1134
sl@0
  1135
    char sign;
sl@0
  1136
sl@0
  1137
    if (neg)
sl@0
  1138
        sign = '-';
sl@0
  1139
    else if (spec.fl_plus && ('d' == spec.cvtspec || 'i' == spec.cvtspec))
sl@0
  1140
        sign= '+';
sl@0
  1141
    else
sl@0
  1142
        sign = '\0';
sl@0
  1143
sl@0
  1144
    assert (buffer < end);
sl@0
  1145
    size_t size = size_t (end - buffer);
sl@0
  1146
sl@0
  1147
    // FIXME: prevent buffer overrun
sl@0
  1148
    if (0 < spec.prec && size < size_t (spec.prec)) {
sl@0
  1149
        for (size_t i = size; i != size_t (spec.prec); ++i)
sl@0
  1150
            *end++ = '0';
sl@0
  1151
    }
sl@0
  1152
sl@0
  1153
    if (sign)
sl@0
  1154
        *end++ = sign;
sl@0
  1155
sl@0
  1156
    *end = '\0';
sl@0
  1157
sl@0
  1158
    assert (buffer < end);
sl@0
  1159
    size = size_t (end - buffer);
sl@0
  1160
sl@0
  1161
    for (char *pc = buffer; pc < end; ++pc) {
sl@0
  1162
        const char tmp = *pc;
sl@0
  1163
        *pc = *--end;
sl@0
  1164
        *end = tmp;
sl@0
  1165
    }
sl@0
  1166
sl@0
  1167
    // handle justification by formatting the resulting string
sl@0
  1168
    return _rw_fmtstr (spec, pbuf, pbufsize, buffer, size);
sl@0
  1169
}
sl@0
  1170
sl@0
  1171
#endif   // _RWSTD_LONG_LONG
sl@0
  1172
sl@0
  1173
/********************************************************************/
sl@0
  1174
sl@0
  1175
static int
sl@0
  1176
_rw_fmtinteger (FmtSpec *pspec, size_t paramno,
sl@0
  1177
               char **pbuf, size_t *pbufsize, va_list *pva)
sl@0
  1178
{
sl@0
  1179
    int len = -1;
sl@0
  1180
sl@0
  1181
    FmtSpec &spec = pspec [paramno];
sl@0
  1182
sl@0
  1183
    switch (spec.cvtspec) {
sl@0
  1184
    case 'd':
sl@0
  1185
    case 'i':
sl@0
  1186
        if (spec.mod_hh) {
sl@0
  1187
            // promoted signed char argument
sl@0
  1188
            spec.param.i = PARAM (int, i);
sl@0
  1189
            const signed char val = spec.param.i;
sl@0
  1190
            len = _rw_fmtlong (spec, pbuf, pbufsize, long (val));
sl@0
  1191
        }
sl@0
  1192
        else if (spec.mod_h) {
sl@0
  1193
            // promoted signed short argument
sl@0
  1194
            spec.param.i = PARAM (int, i);
sl@0
  1195
            const short val = spec.param.i;
sl@0
  1196
            len = _rw_fmtlong (spec, pbuf, pbufsize, long (val));
sl@0
  1197
        }
sl@0
  1198
        else if (spec.mod_l) {   // %li
sl@0
  1199
            spec.param.lng = PARAM (long, lng);
sl@0
  1200
            len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.lng);
sl@0
  1201
        }
sl@0
  1202
        else if (spec.mod_ll) {   // %lli
sl@0
  1203
sl@0
  1204
#ifdef _RWSTD_LONG_LONG
sl@0
  1205
            spec.param.llong = PARAM (_RWSTD_LONG_LONG, llong);
sl@0
  1206
            len = _rw_fmtllong (spec, pbuf, pbufsize, spec.param.llong);
sl@0
  1207
#elif 8 == _RWSTD_LONG_SIZE
sl@0
  1208
            spec.param.llong = PARAM (long, lnng);
sl@0
  1209
            len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.llong);
sl@0
  1210
#else
sl@0
  1211
            assert (!"%lld, %lli: long long not supported");
sl@0
  1212
sl@0
  1213
#endif   // _RWSTD_LONG_LONG
sl@0
  1214
        }
sl@0
  1215
        else if (spec.mod_t) {
sl@0
  1216
            spec.param.diff = PARAM (ptrdiff_t, diff);
sl@0
  1217
            if (sizeof (ptrdiff_t) == sizeof (long)) {
sl@0
  1218
                len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.diff);
sl@0
  1219
            }
sl@0
  1220
            else {
sl@0
  1221
#ifdef _RWSTD_LONG_LONG
sl@0
  1222
                len = _rw_fmtllong (spec, pbuf, pbufsize, spec.param.diff);
sl@0
  1223
#else   // if !defined (_RWSTD_LONG_LONG)
sl@0
  1224
                assert (!"%td, %ti: 64-bit types not supported");
sl@0
  1225
#endif   // _RWSTD_LONG_LONG
sl@0
  1226
            }
sl@0
  1227
        }
sl@0
  1228
        else if (1 == spec.iwidth) {
sl@0
  1229
            spec.param.i = PARAM (int, i);
sl@0
  1230
            const _RWSTD_INT8_T val = spec.param.i;
sl@0
  1231
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1232
        }
sl@0
  1233
        else if (2 == spec.iwidth) {
sl@0
  1234
            spec.param.i = PARAM (int, i);
sl@0
  1235
            const _RWSTD_INT16_T val = spec.param.i;
sl@0
  1236
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1237
        }
sl@0
  1238
        else if (3 == spec.iwidth) {
sl@0
  1239
            spec.param.i32 = PARAM (_RWSTD_INT32_T, i32);
sl@0
  1240
            const long val = long (spec.param.i32);
sl@0
  1241
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1242
        }
sl@0
  1243
        else if (4 == spec.iwidth) {
sl@0
  1244
sl@0
  1245
#ifdef _RWSTD_INT64_T
sl@0
  1246
            spec.param.i64 = PARAM (_RWSTD_INT64_T, i64);
sl@0
  1247
#else   // if !defined (_RWSTD_INT64_T)
sl@0
  1248
            assert (!"%I64d, %I64i: 64-bit types not supported");
sl@0
  1249
#endif   // _RWSTD_INT64_T
sl@0
  1250
sl@0
  1251
#if 8 == _RWSTD_LONG_SIZE
sl@0
  1252
            const long val = spec.param.i64;
sl@0
  1253
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1254
#elif defined (_RWSTD_LONG_LONG)
sl@0
  1255
            const _RWSTD_LONG_LONG val = spec.param.i64;
sl@0
  1256
            len = _rw_fmtllong (spec, pbuf, pbufsize, val);
sl@0
  1257
#else
sl@0
  1258
            assert (!"%I64d, %I64i: 64-bit types not supported");
sl@0
  1259
#endif
sl@0
  1260
        }
sl@0
  1261
        else {   // %i
sl@0
  1262
            spec.param.i = PARAM (int, i);
sl@0
  1263
            len = _rw_fmtlong (spec, pbuf, pbufsize, long (spec.param.i));
sl@0
  1264
        }
sl@0
  1265
        break;
sl@0
  1266
sl@0
  1267
    case 'o':
sl@0
  1268
        assert (-1 == spec.base);
sl@0
  1269
        spec.base = 8;
sl@0
  1270
        // fall thru
sl@0
  1271
sl@0
  1272
    case 'x':
sl@0
  1273
        if (-1 == spec.base)
sl@0
  1274
            spec.base = 16;
sl@0
  1275
        // fall thru
sl@0
  1276
sl@0
  1277
    case 'X':
sl@0
  1278
        if (-1 == spec.base)
sl@0
  1279
            spec.base = 16;
sl@0
  1280
sl@0
  1281
    case 'u':
sl@0
  1282
        if (spec.mod_hh) {
sl@0
  1283
            // promoted unsigned char argument
sl@0
  1284
            spec.param.i = PARAM (unsigned, i);
sl@0
  1285
            const unsigned char val = spec.param.i;
sl@0
  1286
            len = _rw_fmtlong (spec, pbuf, pbufsize, (unsigned long)val);
sl@0
  1287
        }
sl@0
  1288
        else if (spec.mod_h) {
sl@0
  1289
            // promoted unsigned short argument
sl@0
  1290
            spec.param.i = PARAM (unsigned, i);
sl@0
  1291
            const unsigned short val = spec.param.i;
sl@0
  1292
            len = _rw_fmtlong (spec, pbuf, pbufsize, (unsigned long)val);
sl@0
  1293
        }
sl@0
  1294
        else if (spec.mod_ll) {
sl@0
  1295
#ifdef _RWSTD_LONG_LONG
sl@0
  1296
            spec.param.llong = PARAM (unsigned _RWSTD_LONG_LONG, llong);
sl@0
  1297
            const unsigned _RWSTD_LONG_LONG val = spec.param.llong;
sl@0
  1298
            len = _rw_fmtllong (spec, pbuf, pbufsize, val);
sl@0
  1299
#elif 8 == _RWSTD_LONG_SIZE
sl@0
  1300
            spec.param.lng = PARAM (unsigned long, lng);
sl@0
  1301
            const unsigned long val = spec.param.lng;
sl@0
  1302
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1303
#else
sl@0
  1304
            assert (!"long long not supported");
sl@0
  1305
#endif   // _RWSTD_LONG_LONG
sl@0
  1306
sl@0
  1307
        }
sl@0
  1308
        else if (spec.mod_l) {
sl@0
  1309
            spec.param.lng = PARAM (unsigned long, lng);
sl@0
  1310
            const unsigned long val = spec.param.lng;
sl@0
  1311
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1312
        }
sl@0
  1313
        else if (spec.mod_t) {
sl@0
  1314
            spec.param.lng = PARAM (size_t, size);
sl@0
  1315
            if (sizeof (size_t) == sizeof (unsigned long)) {
sl@0
  1316
                len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.size);
sl@0
  1317
            }
sl@0
  1318
            else {
sl@0
  1319
#ifdef _RWSTD_LONG_LONG
sl@0
  1320
                len = _rw_fmtllong (spec, pbuf, pbufsize, spec.param.size);
sl@0
  1321
#else   // if defined (_RWSTD_LONG_LONG)
sl@0
  1322
                assert (!"%to, %tu, %tx: 64-bit types not implemented");
sl@0
  1323
#endif   // _RWSTD_LONG_LONG
sl@0
  1324
            }
sl@0
  1325
        }
sl@0
  1326
        else if (1 == spec.iwidth) {
sl@0
  1327
            spec.param.i = PARAM (int, i);
sl@0
  1328
            const _RWSTD_UINT8_T val = spec.param.i;
sl@0
  1329
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1330
        }
sl@0
  1331
        else if (2 == spec.iwidth) {
sl@0
  1332
            spec.param.i = PARAM (int, i);
sl@0
  1333
            const long val = (unsigned short)spec.param.i;
sl@0
  1334
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1335
        }
sl@0
  1336
        else if (3 == spec.iwidth) {
sl@0
  1337
            spec.param.i32 = PARAM (_RWSTD_INT32_T, i32);
sl@0
  1338
            const long val = long (unsigned (spec.param.i));
sl@0
  1339
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1340
        }
sl@0
  1341
        else if (4 == spec.iwidth) {
sl@0
  1342
#ifdef _RWSTD_INT64_T
sl@0
  1343
            spec.param.i64 = PARAM (_RWSTD_INT64_T, i64);
sl@0
  1344
#else   // if defined 9_RWSTD_INT64_T)
sl@0
  1345
            assert (!"%I64o, %I64u, %I64x: 64-bit types not supported");
sl@0
  1346
#endif   // _RWSTD_INT64_T
sl@0
  1347
sl@0
  1348
#if 8 == _RWSTD_LONG_SIZE
sl@0
  1349
            const unsigned long val = spec.param.i64;
sl@0
  1350
            len = _rw_fmtlong (spec, pbuf, pbufsize, val);
sl@0
  1351
#elif defined (_RWSTD_LONG_LONG)
sl@0
  1352
            const unsigned _RWSTD_LONG_LONG val = spec.param.i64;
sl@0
  1353
            len = _rw_fmtllong (spec, pbuf, pbufsize, val);
sl@0
  1354
#else
sl@0
  1355
            assert (!"%I64o, %I64u, %I64x: 64-bit types not supported");
sl@0
  1356
#endif
sl@0
  1357
        }
sl@0
  1358
        else {
sl@0
  1359
            spec.param.i = PARAM (unsigned, i);
sl@0
  1360
            const unsigned val = spec.param.i;
sl@0
  1361
            len = _rw_fmtlong (spec, pbuf, pbufsize, long (val));
sl@0
  1362
        }
sl@0
  1363
        
sl@0
  1364
        break;
sl@0
  1365
    }
sl@0
  1366
sl@0
  1367
    return len;
sl@0
  1368
}
sl@0
  1369
sl@0
  1370
/********************************************************************/
sl@0
  1371
sl@0
  1372
static int
sl@0
  1373
_rw_fmtfloating (const FmtSpec &spec,
sl@0
  1374
                char **pbuf, size_t *pbufsize, const void *pval)
sl@0
  1375
{
sl@0
  1376
    char fmt [128];
sl@0
  1377
    char *pf = fmt;
sl@0
  1378
sl@0
  1379
    *pf++ = '%';
sl@0
  1380
sl@0
  1381
    if (spec.fl_minus)
sl@0
  1382
        *pf++ = '-';
sl@0
  1383
sl@0
  1384
    if (spec.fl_plus)
sl@0
  1385
        *pf++ = '+';
sl@0
  1386
        
sl@0
  1387
    if (spec.fl_pound)
sl@0
  1388
        *pf++ = '#';
sl@0
  1389
sl@0
  1390
    if (spec.fl_space)
sl@0
  1391
        *pf++ = ' ';
sl@0
  1392
sl@0
  1393
    if (spec.fl_zero)
sl@0
  1394
        *pf++ = '0';
sl@0
  1395
sl@0
  1396
    if (spec.mod_h)
sl@0
  1397
        *pf++ = 'h';
sl@0
  1398
    else if (spec.mod_hh) {
sl@0
  1399
        *pf++ = 'h';
sl@0
  1400
        *pf++ = 'h';
sl@0
  1401
    }
sl@0
  1402
    else if (spec.mod_l)
sl@0
  1403
        *pf++ = 'l';
sl@0
  1404
    else if (spec.mod_ll) {
sl@0
  1405
        *pf++ = 'l';
sl@0
  1406
        *pf++ = 'l';
sl@0
  1407
    }
sl@0
  1408
    else if (spec.mod_j)
sl@0
  1409
        *pf++ = 'j';
sl@0
  1410
    else if (spec.mod_z)
sl@0
  1411
        *pf++ = 'z';
sl@0
  1412
    else if (spec.mod_t)
sl@0
  1413
        *pf++ = 't';
sl@0
  1414
    else if (spec.mod_L) {
sl@0
  1415
        strcpy (pf, _RWSTD_LDBL_PRINTF_PREFIX);
sl@0
  1416
        for ( ; *pf; ++pf);
sl@0
  1417
    }
sl@0
  1418
    else if (spec.mod_A && _RWSTD_LDBL_SIZE == spec.width) {
sl@0
  1419
        strcpy (pf, _RWSTD_LDBL_PRINTF_PREFIX);
sl@0
  1420
        for ( ; *pf; ++pf);
sl@0
  1421
    }
sl@0
  1422
sl@0
  1423
    if (!spec.mod_A && 0 <= spec.width) {
sl@0
  1424
        pf += sprintf (pf, "%i", spec.width);
sl@0
  1425
    }
sl@0
  1426
sl@0
  1427
    if (0 <= spec.prec)
sl@0
  1428
        pf += sprintf (pf, ".%i", spec.prec);
sl@0
  1429
sl@0
  1430
    *pf++ = char (spec.cvtspec);
sl@0
  1431
    *pf   = '\0';
sl@0
  1432
sl@0
  1433
    // verify that the format buffer hasn't overflowed
sl@0
  1434
    assert (size_t (pf - fmt) + 1 < sizeof fmt);
sl@0
  1435
sl@0
  1436
    // this might make the buffer almost 5KB
sl@0
  1437
    char buffer [_RWSTD_LDBL_MAX_10_EXP + _RWSTD_LDBL_DIG + 3];
sl@0
  1438
    int len = -1;
sl@0
  1439
sl@0
  1440
    if (spec.mod_A) {
sl@0
  1441
sl@0
  1442
        if (_RWSTD_FLT_SIZE == spec.width) {
sl@0
  1443
            len = sprintf (buffer, fmt, *(const float*)pval);
sl@0
  1444
        }
sl@0
  1445
        else if (_RWSTD_DBL_SIZE == spec.width) {
sl@0
  1446
            len = sprintf (buffer, fmt, *(const double*)pval);
sl@0
  1447
        }
sl@0
  1448
        else if (_RWSTD_LDBL_SIZE == spec.width) {
sl@0
  1449
            len = sprintf (buffer, fmt, *(const long double*)pval);
sl@0
  1450
        }
sl@0
  1451
        else {
sl@0
  1452
            assert (!"unknown floating point size");
sl@0
  1453
        }
sl@0
  1454
    }
sl@0
  1455
    else if (spec.mod_L)
sl@0
  1456
        len = sprintf (buffer, fmt, *(const long double*)pval);
sl@0
  1457
    else
sl@0
  1458
        len = sprintf (buffer, fmt, *(const double*)pval);
sl@0
  1459
sl@0
  1460
    assert (size_t (len) < sizeof buffer);
sl@0
  1461
sl@0
  1462
#ifdef _MSC_VER
sl@0
  1463
sl@0
  1464
    if (5 < len) {
sl@0
  1465
        // remove redundant zeros from the exponent (if present)
sl@0
  1466
        if (   ('e' == buffer [len - 5] || 'E' == buffer [len - 5])
sl@0
  1467
            && '0' == buffer [len - 3]) {
sl@0
  1468
            buffer [len - 3] = buffer [len - 2];
sl@0
  1469
            buffer [len - 2] = buffer [len - 1];
sl@0
  1470
            buffer [len - 1] = buffer [len];
sl@0
  1471
        }
sl@0
  1472
    }
sl@0
  1473
sl@0
  1474
#endif   // _MSC_VER
sl@0
  1475
sl@0
  1476
sl@0
  1477
    if (-1 < len && 0 == _rw_bufcat (pbuf, pbufsize, buffer, size_t (len)))
sl@0
  1478
        return -1;
sl@0
  1479
sl@0
  1480
    return len;
sl@0
  1481
}
sl@0
  1482
sl@0
  1483
/********************************************************************/
sl@0
  1484
sl@0
  1485
// formats a data, function, or class member pointer as follows
sl@0
  1486
//     0x<hex-long-0>[:<hex-long-1>[:...[:<hex-long-N>]]]
sl@0
  1487
// where N is the size of the pointer in long ints
sl@0
  1488
sl@0
  1489
sl@0
  1490
static int
sl@0
  1491
_rw_fmtpointer (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
sl@0
  1492
                const void *pptr, size_t nelems)
sl@0
  1493
{
sl@0
  1494
    FmtSpec newspec (spec);
sl@0
  1495
sl@0
  1496
    // always format data pointers in hexadecimal
sl@0
  1497
    newspec.base = 16;
sl@0
  1498
sl@0
  1499
    // set the number of digits
sl@0
  1500
    newspec.prec = _RWSTD_LONG_SIZE * 2;
sl@0
  1501
sl@0
  1502
    const union {
sl@0
  1503
        const void          *ptr;
sl@0
  1504
        const unsigned long *lptr;
sl@0
  1505
    } uptr = { pptr };
sl@0
  1506
sl@0
  1507
    int len = 0;
sl@0
  1508
sl@0
  1509
    if (newspec.fl_pound) {
sl@0
  1510
        // prepend the 0x prefix even to null pointers
sl@0
  1511
        if (0 == _rw_bufcat (pbuf, pbufsize, "0x", len = 2)) {
sl@0
  1512
            return -1;
sl@0
  1513
        }
sl@0
  1514
sl@0
  1515
        // reset the pound flag to prevent the integer formatter
sl@0
  1516
        // from inserting it again
sl@0
  1517
        newspec.fl_pound  = 0;
sl@0
  1518
    }
sl@0
  1519
sl@0
  1520
    for (size_t i = 0; i != nelems; ++i) {
sl@0
  1521
        const size_t inx = _rw_big_endian ? nelems - i - 1 : i;
sl@0
  1522
sl@0
  1523
        len += _rw_fmtlong (newspec, pbuf, pbufsize, uptr.lptr [inx]);
sl@0
  1524
sl@0
  1525
        if (len < 0) {
sl@0
  1526
            break;
sl@0
  1527
        }
sl@0
  1528
sl@0
  1529
        // separate pointer components with colons
sl@0
  1530
        int n = 0;
sl@0
  1531
        if (i + 1 < nelems) {
sl@0
  1532
            if (0 == _rw_bufcat (pbuf, pbufsize, ":", n = 1)) {
sl@0
  1533
                len = -1;
sl@0
  1534
                break;
sl@0
  1535
            }
sl@0
  1536
        }
sl@0
  1537
sl@0
  1538
        len += n;
sl@0
  1539
    }
sl@0
  1540
sl@0
  1541
    return len;
sl@0
  1542
}
sl@0
  1543
sl@0
  1544
/********************************************************************/
sl@0
  1545
sl@0
  1546
_RWSTD_INTERNAL int
sl@0
  1547
_rw_fmtptr (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
sl@0
  1548
            const void *val)
sl@0
  1549
{
sl@0
  1550
    return _rw_fmtpointer (spec, pbuf, pbufsize, &val,
sl@0
  1551
                           sizeof val / sizeof (long));
sl@0
  1552
}
sl@0
  1553
sl@0
  1554
/********************************************************************/
sl@0
  1555
sl@0
  1556
static int
sl@0
  1557
_rw_fmtfunptr (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
sl@0
  1558
              funptr_t val)
sl@0
  1559
{
sl@0
  1560
    if (spec.mod_l) {
sl@0
  1561
sl@0
  1562
#if 0   // disabled until this is implemented on other platforms
sl@0
  1563
#ifdef _RWSTD_OS_SUNOS
sl@0
  1564
sl@0
  1565
        char buffer [256];
sl@0
  1566
sl@0
  1567
        Dl_info dli;
sl@0
  1568
sl@0
  1569
        // find the symbol corresponding to the address
sl@0
  1570
        if (dladdr ((void*)val, &dli)) {
sl@0
  1571
            if (!dli.dli_sname)
sl@0
  1572
                dli.dli_fname = "unknown";
sl@0
  1573
sl@0
  1574
            const size_t sym_off = size_t (dli.dli_saddr);
sl@0
  1575
sl@0
  1576
            // compute the offset of the address from the address
sl@0
  1577
            // of the symbol dladdr() found in the address space
sl@0
  1578
            // of the calling process
sl@0
  1579
            const size_t addr_off = size_t (val) < sym_off ?
sl@0
  1580
                sym_off - size_t (val) : size_t (val) - sym_off;
sl@0
  1581
sl@0
  1582
            // format the address folowed by the name of the symbol
sl@0
  1583
            // followed by the offset
sl@0
  1584
            const int len = sprintf (buffer, "%#x=%s%c%lu",
sl@0
  1585
                                     size_t (val), dli.dli_sname,
sl@0
  1586
                                     size_t (val) < sym_off ? '-' : '+',
sl@0
  1587
                                     addr_off);
sl@0
  1588
            
sl@0
  1589
            FmtSpec newspec (spec);
sl@0
  1590
            newspec.mod_l = false;
sl@0
  1591
sl@0
  1592
            return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (len));
sl@0
  1593
        }
sl@0
  1594
sl@0
  1595
#endif   // _RWSTD_OS_SUNOS
sl@0
  1596
#endif   // 0/1
sl@0
  1597
    }
sl@0
  1598
sl@0
  1599
    return _rw_fmtpointer (spec, pbuf, pbufsize, &val,
sl@0
  1600
                           sizeof val / sizeof (long));
sl@0
  1601
}
sl@0
  1602
sl@0
  1603
/********************************************************************/
sl@0
  1604
sl@0
  1605
static int
sl@0
  1606
_rw_fmtmemptr (const FmtSpec &spec, char **pbuf, size_t *pbufsize, memptr_t val)
sl@0
  1607
{
sl@0
  1608
    return _rw_fmtpointer (spec, pbuf, pbufsize, &val,
sl@0
  1609
                           sizeof val / sizeof (long));
sl@0
  1610
}
sl@0
  1611
sl@0
  1612
/********************************************************************/
sl@0
  1613
sl@0
  1614
static int
sl@0
  1615
_rw_fmterrno (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
sl@0
  1616
{
sl@0
  1617
    static const struct {
sl@0
  1618
        int         val;
sl@0
  1619
        const char* str;
sl@0
  1620
    } names[] = {
sl@0
  1621
sl@0
  1622
#undef ERRNO
sl@0
  1623
#define ERRNO(val)   { val, #val }
sl@0
  1624
sl@0
  1625
#ifdef EPERM
sl@0
  1626
        ERRNO (EPERM),
sl@0
  1627
#endif   // EPERM
sl@0
  1628
#ifdef ENOENT
sl@0
  1629
        ERRNO (ENOENT),
sl@0
  1630
#endif   // ENOENT
sl@0
  1631
#ifdef ESRCH
sl@0
  1632
        ERRNO (ESRCH),
sl@0
  1633
#endif   // ESRCH
sl@0
  1634
#ifdef EINTR
sl@0
  1635
        ERRNO (EINTR),
sl@0
  1636
#endif   // EINTR
sl@0
  1637
#ifdef EIO
sl@0
  1638
        ERRNO (EIO),
sl@0
  1639
#endif   // EIO
sl@0
  1640
#ifdef ENXIO
sl@0
  1641
        ERRNO (ENXIO),
sl@0
  1642
#endif   // ENXIO
sl@0
  1643
#ifdef E2BIG
sl@0
  1644
        ERRNO (E2BIG),
sl@0
  1645
#endif   // E2BIG
sl@0
  1646
#ifdef ENOEXEC
sl@0
  1647
        ERRNO (ENOEXEC),
sl@0
  1648
#endif   // ENOEXEC
sl@0
  1649
#ifdef EBADF
sl@0
  1650
        ERRNO (EBADF),
sl@0
  1651
#endif   // EBADF
sl@0
  1652
#ifdef ECHILD
sl@0
  1653
        ERRNO (ECHILD),
sl@0
  1654
#endif   // ECHILD
sl@0
  1655
#ifdef EAGAIN
sl@0
  1656
        ERRNO (EAGAIN),
sl@0
  1657
#endif   // EAGAIN
sl@0
  1658
#ifdef ENOMEM
sl@0
  1659
        ERRNO (ENOMEM),
sl@0
  1660
#endif   // ENOMEM
sl@0
  1661
#ifdef EACCES
sl@0
  1662
        ERRNO (EACCES),
sl@0
  1663
#endif   // EACCES
sl@0
  1664
#ifdef EFAULT
sl@0
  1665
        ERRNO (EFAULT),
sl@0
  1666
#endif   // EFAULT
sl@0
  1667
#ifdef ENOTBLK
sl@0
  1668
        ERRNO (ENOTBLK),
sl@0
  1669
#endif   // ENOTBLK
sl@0
  1670
#ifdef EBUSY
sl@0
  1671
        ERRNO (EBUSY),
sl@0
  1672
#endif   // EBUSY
sl@0
  1673
#ifdef EEXIST
sl@0
  1674
        ERRNO (EEXIST),
sl@0
  1675
#endif   // EEXIST
sl@0
  1676
#ifdef EXDEV
sl@0
  1677
        ERRNO (EXDEV),
sl@0
  1678
#endif   // EXDEV
sl@0
  1679
#ifdef ENODEV
sl@0
  1680
        ERRNO (ENODEV),
sl@0
  1681
#endif   // ENODEV
sl@0
  1682
#ifdef ENOTDIR
sl@0
  1683
        ERRNO (ENOTDIR),
sl@0
  1684
#endif   // ENOTDIR
sl@0
  1685
#ifdef EISDIR
sl@0
  1686
        ERRNO (EISDIR),
sl@0
  1687
#endif   // EISDIR
sl@0
  1688
#ifdef EINVAL
sl@0
  1689
        ERRNO (EINVAL),
sl@0
  1690
#endif   // EINVAL
sl@0
  1691
#ifdef ENFILE
sl@0
  1692
        ERRNO (ENFILE),
sl@0
  1693
#endif   // ENFILE
sl@0
  1694
#ifdef EMFILE
sl@0
  1695
        ERRNO (EMFILE),
sl@0
  1696
#endif   // EMFILE
sl@0
  1697
#ifdef ENOTTY
sl@0
  1698
        ERRNO (ENOTTY),
sl@0
  1699
#endif   // ENOTTY
sl@0
  1700
#ifdef ETXTBSY
sl@0
  1701
        ERRNO (ETXTBSY),
sl@0
  1702
#endif   // ETXTBSY
sl@0
  1703
#ifdef EFBIG
sl@0
  1704
        ERRNO (EFBIG),
sl@0
  1705
#endif   // EFBIG
sl@0
  1706
#ifdef ENOSPC
sl@0
  1707
        ERRNO (ENOSPC),
sl@0
  1708
#endif   // ENOSPC
sl@0
  1709
#ifdef ESPIPE
sl@0
  1710
        ERRNO (ESPIPE),
sl@0
  1711
#endif   // ESPIPE
sl@0
  1712
#ifdef EROFS
sl@0
  1713
        ERRNO (EROFS),
sl@0
  1714
#endif   // EROFS
sl@0
  1715
#ifdef EMLINK
sl@0
  1716
        ERRNO (EMLINK),
sl@0
  1717
#endif   // EMLINK
sl@0
  1718
#ifdef EPIPE
sl@0
  1719
        ERRNO (EPIPE),
sl@0
  1720
#endif   // EPIPE
sl@0
  1721
#ifdef EDOM
sl@0
  1722
        ERRNO (EDOM),
sl@0
  1723
#endif   // EDOM
sl@0
  1724
#ifdef ERANGE
sl@0
  1725
        ERRNO (ERANGE),
sl@0
  1726
#endif   // ERANGE
sl@0
  1727
#ifdef ENOMSG
sl@0
  1728
        ERRNO (ENOMSG),
sl@0
  1729
#endif   // ENOMSG
sl@0
  1730
#ifdef EIDRM
sl@0
  1731
        ERRNO (EIDRM),
sl@0
  1732
#endif   // EIDRM
sl@0
  1733
#ifdef ECHRNG
sl@0
  1734
        ERRNO (ECHRNG),
sl@0
  1735
#endif   // ECHRNG
sl@0
  1736
#ifdef EL2NSYNC
sl@0
  1737
        ERRNO (EL2NSYNC),
sl@0
  1738
#endif   // EL2NSYNC
sl@0
  1739
#ifdef EL3HLT
sl@0
  1740
        ERRNO (EL3HLT),
sl@0
  1741
#endif   // EL3HLT
sl@0
  1742
#ifdef EL3RST
sl@0
  1743
        ERRNO (EL3RST),
sl@0
  1744
#endif   // EL3RST
sl@0
  1745
#ifdef ELNRNG
sl@0
  1746
        ERRNO (ELNRNG),
sl@0
  1747
#endif   // ELNRNG
sl@0
  1748
#ifdef EUNATCH
sl@0
  1749
        ERRNO (EUNATCH),
sl@0
  1750
#endif   // EUNATCH
sl@0
  1751
#ifdef ENOCSI
sl@0
  1752
        ERRNO (ENOCSI),
sl@0
  1753
#endif   // ENOCSI
sl@0
  1754
#ifdef EL2HLT
sl@0
  1755
        ERRNO (EL2HLT),
sl@0
  1756
#endif   // EL2HLT
sl@0
  1757
#ifdef EDEADLK
sl@0
  1758
        ERRNO (EDEADLK),
sl@0
  1759
#endif   // EDEADLK
sl@0
  1760
#ifdef ENOLCK
sl@0
  1761
        ERRNO (ENOLCK),
sl@0
  1762
#endif   // ENOLCK
sl@0
  1763
#ifdef ECANCELED
sl@0
  1764
        ERRNO (ECANCELED),
sl@0
  1765
#endif   // ECANCELED
sl@0
  1766
#ifdef ENOTSUP
sl@0
  1767
        ERRNO (ENOTSUP),
sl@0
  1768
#endif   // ENOTSUP
sl@0
  1769
#ifdef EDQUOT
sl@0
  1770
        ERRNO (EDQUOT),
sl@0
  1771
#endif   // EDQUOT
sl@0
  1772
#ifdef EBADE
sl@0
  1773
        ERRNO (EBADE),
sl@0
  1774
#endif   // EBADE
sl@0
  1775
#ifdef EBADR
sl@0
  1776
        ERRNO (EBADR),
sl@0
  1777
#endif   // EBADR
sl@0
  1778
#ifdef EXFULL
sl@0
  1779
        ERRNO (EXFULL),
sl@0
  1780
#endif   // EXFULL
sl@0
  1781
#ifdef ENOANO
sl@0
  1782
        ERRNO (ENOANO),
sl@0
  1783
#endif   // ENOANO
sl@0
  1784
#ifdef EBADRQC
sl@0
  1785
        ERRNO (EBADRQC),
sl@0
  1786
#endif   // EBADRQC
sl@0
  1787
#ifdef EBADSLT
sl@0
  1788
        ERRNO (EBADSLT),
sl@0
  1789
#endif   // EBADSLT
sl@0
  1790
#ifdef EDEADLOCK
sl@0
  1791
        ERRNO (EDEADLOCK),
sl@0
  1792
#endif   // EDEADLOCK
sl@0
  1793
#ifdef EBFONT
sl@0
  1794
        ERRNO (EBFONT),
sl@0
  1795
#endif   // EBFONT
sl@0
  1796
#ifdef EOWNERDEAD
sl@0
  1797
        ERRNO (EOWNERDEAD),
sl@0
  1798
#endif   // EOWNERDEAD
sl@0
  1799
#ifdef ENOTRECOVERABLE
sl@0
  1800
        ERRNO (ENOTRECOVERABLE),
sl@0
  1801
#endif   // ENOTRECOVERABLE
sl@0
  1802
#ifdef ENOSTR
sl@0
  1803
        ERRNO (ENOSTR),
sl@0
  1804
#endif   // ENOSTR
sl@0
  1805
#ifdef ENODATA
sl@0
  1806
        ERRNO (ENODATA),
sl@0
  1807
#endif   // ENODATA
sl@0
  1808
#ifdef ETIME
sl@0
  1809
        ERRNO (ETIME),
sl@0
  1810
#endif   // ETIME
sl@0
  1811
#ifdef ENOSR
sl@0
  1812
        ERRNO (ENOSR),
sl@0
  1813
#endif   // ENOSR
sl@0
  1814
#ifdef ENONET
sl@0
  1815
        ERRNO (ENONET),
sl@0
  1816
#endif   // ENONET
sl@0
  1817
#ifdef ENOPKG
sl@0
  1818
        ERRNO (ENOPKG),
sl@0
  1819
#endif   // ENOPKG
sl@0
  1820
#ifdef EREMOTE
sl@0
  1821
        ERRNO (EREMOTE),
sl@0
  1822
#endif   // EREMOTE
sl@0
  1823
#ifdef ENOLINK
sl@0
  1824
        ERRNO (ENOLINK),
sl@0
  1825
#endif   // ENOLINK
sl@0
  1826
#ifdef EADV
sl@0
  1827
        ERRNO (EADV),
sl@0
  1828
#endif   // EADV
sl@0
  1829
#ifdef ESRMNT
sl@0
  1830
        ERRNO (ESRMNT),
sl@0
  1831
#endif   // ESRMNT
sl@0
  1832
#ifdef ECOMM
sl@0
  1833
        ERRNO (ECOMM),
sl@0
  1834
#endif   // ECOMM
sl@0
  1835
#ifdef ELOCKUNMAPPED
sl@0
  1836
        ERRNO (ELOCKUNMAPPED),
sl@0
  1837
#endif   // ELOCKUNMAPPED
sl@0
  1838
#ifdef ENOTACTIVE
sl@0
  1839
        ERRNO (ENOTACTIVE),
sl@0
  1840
#endif   // ENOTACTIVE
sl@0
  1841
#ifdef EMULTIHOP
sl@0
  1842
        ERRNO (EMULTIHOP),
sl@0
  1843
#endif   // EMULTIHOP
sl@0
  1844
#ifdef EBADMSG
sl@0
  1845
        ERRNO (EBADMSG),
sl@0
  1846
#endif   // EBADMSG
sl@0
  1847
#ifdef ENAMETOOLONG
sl@0
  1848
        ERRNO (ENAMETOOLONG),
sl@0
  1849
#endif   // ENAMETOOLONG
sl@0
  1850
#ifdef EOVERFLOW
sl@0
  1851
        ERRNO (EOVERFLOW),
sl@0
  1852
#endif   // EOVERFLOW
sl@0
  1853
#ifdef ENOTUNIQ
sl@0
  1854
        ERRNO (ENOTUNIQ),
sl@0
  1855
#endif   // ENOTUNIQ
sl@0
  1856
#ifdef EBADFD
sl@0
  1857
        ERRNO (EBADFD),
sl@0
  1858
#endif   // EBADFD
sl@0
  1859
#ifdef EREMCHG
sl@0
  1860
        ERRNO (EREMCHG),
sl@0
  1861
#endif   // EREMCHG
sl@0
  1862
#ifdef ELIBACC
sl@0
  1863
        ERRNO (ELIBACC),
sl@0
  1864
#endif   // ELIBACC
sl@0
  1865
#ifdef ELIBBAD
sl@0
  1866
        ERRNO (ELIBBAD),
sl@0
  1867
#endif   // ELIBBAD
sl@0
  1868
#ifdef ELIBSCN
sl@0
  1869
        ERRNO (ELIBSCN),
sl@0
  1870
#endif   // ELIBSCN
sl@0
  1871
#ifdef ELIBMAX
sl@0
  1872
        ERRNO (ELIBMAX),
sl@0
  1873
#endif   // ELIBMAX
sl@0
  1874
#ifdef ELIBEXEC
sl@0
  1875
        ERRNO (ELIBEXEC),
sl@0
  1876
#endif   // ELIBEXEC
sl@0
  1877
#ifdef EILSEQ
sl@0
  1878
        ERRNO (EILSEQ),
sl@0
  1879
#endif   // EILSEQ
sl@0
  1880
#ifdef ENOSYS
sl@0
  1881
        ERRNO (ENOSYS),
sl@0
  1882
#endif   // ENOSYS
sl@0
  1883
#ifdef ELOOP
sl@0
  1884
        ERRNO (ELOOP),
sl@0
  1885
#endif   // ELOOP
sl@0
  1886
#ifdef ERESTART
sl@0
  1887
        ERRNO (ERESTART),
sl@0
  1888
#endif   // ERESTART
sl@0
  1889
#ifdef ESTRPIPE
sl@0
  1890
        ERRNO (ESTRPIPE),
sl@0
  1891
#endif   // ESTRPIPE
sl@0
  1892
#ifdef ENOTEMPTY
sl@0
  1893
        ERRNO (ENOTEMPTY),
sl@0
  1894
#endif   // ENOTEMPTY
sl@0
  1895
#ifdef EUSERS
sl@0
  1896
        ERRNO (EUSERS),
sl@0
  1897
#endif   // EUSERS
sl@0
  1898
#ifdef ENOTSOCK
sl@0
  1899
        ERRNO (ENOTSOCK),
sl@0
  1900
#endif   // ENOTSOCK
sl@0
  1901
#ifdef EDESTADDRREQ
sl@0
  1902
        ERRNO (EDESTADDRREQ),
sl@0
  1903
#endif   // EDESTADDRREQ
sl@0
  1904
#ifdef EMSGSIZE
sl@0
  1905
        ERRNO (EMSGSIZE),
sl@0
  1906
#endif   // EMSGSIZE
sl@0
  1907
#ifdef EPROTOTYPE
sl@0
  1908
        ERRNO (EPROTOTYPE),
sl@0
  1909
#endif   // EPROTOTYPE
sl@0
  1910
#ifdef ENOPROTOOPT
sl@0
  1911
        ERRNO (ENOPROTOOPT),
sl@0
  1912
#endif   // ENOPROTOOPT
sl@0
  1913
#ifdef EPROTONOSUPPORT
sl@0
  1914
        ERRNO (EPROTONOSUPPORT),
sl@0
  1915
#endif   // EPROTONOSUPPORT
sl@0
  1916
#ifdef ESOCKTNOSUPPORT
sl@0
  1917
        ERRNO (ESOCKTNOSUPPORT),
sl@0
  1918
#endif   // ESOCKTNOSUPPORT
sl@0
  1919
#ifdef EOPNOTSUPP
sl@0
  1920
        ERRNO (EOPNOTSUPP),
sl@0
  1921
#endif   // EOPNOTSUPP
sl@0
  1922
#ifdef EPFNOSUPPORT
sl@0
  1923
        ERRNO (EPFNOSUPPORT),
sl@0
  1924
#endif   // EPFNOSUPPORT
sl@0
  1925
#ifdef EAFNOSUPPORT
sl@0
  1926
        ERRNO (EAFNOSUPPORT),
sl@0
  1927
#endif   // EAFNOSUPPORT
sl@0
  1928
#ifdef EADDRINUSE
sl@0
  1929
        ERRNO (EADDRINUSE),
sl@0
  1930
#endif   // EADDRINUSE
sl@0
  1931
#ifdef EADDRNOTAVAIL
sl@0
  1932
        ERRNO (EADDRNOTAVAIL),
sl@0
  1933
#endif   // EADDRNOTAVAIL
sl@0
  1934
#ifdef ENETDOWN
sl@0
  1935
        ERRNO (ENETDOWN),
sl@0
  1936
#endif   // ENETDOWN
sl@0
  1937
#ifdef ENETUNREACH
sl@0
  1938
        ERRNO (ENETUNREACH),
sl@0
  1939
#endif   // ENETUNREACH
sl@0
  1940
#ifdef ENETRESET
sl@0
  1941
        ERRNO (ENETRESET),
sl@0
  1942
#endif   // ENETRESET
sl@0
  1943
#ifdef ECONNABORTED
sl@0
  1944
        ERRNO (ECONNABORTED),
sl@0
  1945
#endif   // ECONNABORTED
sl@0
  1946
#ifdef ECONNRESET
sl@0
  1947
        ERRNO (ECONNRESET),
sl@0
  1948
#endif   // ECONNRESET
sl@0
  1949
#ifdef ENOBUFS
sl@0
  1950
        ERRNO (ENOBUFS),
sl@0
  1951
#endif   // ENOBUFS
sl@0
  1952
#ifdef EISCONN
sl@0
  1953
        ERRNO (EISCONN),
sl@0
  1954
#endif   // EISCONN
sl@0
  1955
#ifdef ENOTCONN
sl@0
  1956
        ERRNO (ENOTCONN),
sl@0
  1957
#endif   // ENOTCONN
sl@0
  1958
#ifdef ESHUTDOWN
sl@0
  1959
        ERRNO (ESHUTDOWN),
sl@0
  1960
#endif   // ESHUTDOWN
sl@0
  1961
#ifdef ETOOMANYREFS
sl@0
  1962
        ERRNO (ETOOMANYREFS),
sl@0
  1963
#endif   // ETOOMANYREFS
sl@0
  1964
#ifdef ETIMEDOUT
sl@0
  1965
        ERRNO (ETIMEDOUT),
sl@0
  1966
#endif   // ETIMEDOUT
sl@0
  1967
#ifdef ECONNREFUSED
sl@0
  1968
        ERRNO (ECONNREFUSED),
sl@0
  1969
#endif   // ECONNREFUSED
sl@0
  1970
#ifdef EHOSTDOWN
sl@0
  1971
        ERRNO (EHOSTDOWN),
sl@0
  1972
#endif   // EHOSTDOWN
sl@0
  1973
#ifdef EHOSTUNREACH
sl@0
  1974
        ERRNO (EHOSTUNREACH),
sl@0
  1975
#endif   // EHOSTUNREACH
sl@0
  1976
#ifdef EWOULDBLOCK
sl@0
  1977
        ERRNO (EWOULDBLOCK),
sl@0
  1978
#endif   // EWOULDBLOCK
sl@0
  1979
#ifdef EALREADY
sl@0
  1980
        ERRNO (EALREADY),
sl@0
  1981
#endif   // EALREADY
sl@0
  1982
#ifdef EINPROGRESS
sl@0
  1983
        ERRNO (EINPROGRESS),
sl@0
  1984
#endif   // EINPROGRESS
sl@0
  1985
#ifdef ESTALE
sl@0
  1986
        ERRNO (ESTALE),
sl@0
  1987
#endif   // ESTALE
sl@0
  1988
        { -1, 0 }
sl@0
  1989
    };
sl@0
  1990
sl@0
  1991
    if (spec.fl_pound) {
sl@0
  1992
sl@0
  1993
        char buffer [64];
sl@0
  1994
        const char *name = 0;
sl@0
  1995
sl@0
  1996
        for (size_t i = 0; i != sizeof names / sizeof *names; ++i) {
sl@0
  1997
            if (names [i].val == val) {
sl@0
  1998
                name = names [i].str;
sl@0
  1999
                break;
sl@0
  2000
            }
sl@0
  2001
        }
sl@0
  2002
sl@0
  2003
        int len;
sl@0
  2004
sl@0
  2005
        if (0 == name) {
sl@0
  2006
            len = sprintf (buffer, "E#%d", val);
sl@0
  2007
            name = buffer;
sl@0
  2008
        }
sl@0
  2009
        else
sl@0
  2010
            len = int (strlen (name));
sl@0
  2011
sl@0
  2012
        if (0 == _rw_bufcat (pbuf, pbufsize, name, size_t (len)))
sl@0
  2013
            return -1;
sl@0
  2014
sl@0
  2015
        return len;
sl@0
  2016
    }
sl@0
  2017
sl@0
  2018
    const char* const str = strerror (val);
sl@0
  2019
    const size_t len = strlen (str);
sl@0
  2020
sl@0
  2021
    if (0 == _rw_bufcat (pbuf, pbufsize, str, len))
sl@0
  2022
        return -1;
sl@0
  2023
sl@0
  2024
    return int (len);
sl@0
  2025
}
sl@0
  2026
sl@0
  2027
/********************************************************************/
sl@0
  2028
sl@0
  2029
static int
sl@0
  2030
_rw_fmtsignal (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
sl@0
  2031
{
sl@0
  2032
    static const struct {
sl@0
  2033
        int         val;
sl@0
  2034
        const char* str;
sl@0
  2035
    } names[] = {
sl@0
  2036
sl@0
  2037
#undef SIGNAL
sl@0
  2038
#define SIGNAL(val)   { val, #val }
sl@0
  2039
sl@0
  2040
#ifdef SIGABRT
sl@0
  2041
        SIGNAL (SIGABRT),
sl@0
  2042
#endif   // SIGABRT
sl@0
  2043
#ifdef SIGALRM
sl@0
  2044
        SIGNAL (SIGALRM),
sl@0
  2045
#endif   // SIGALRM
sl@0
  2046
#ifdef SIGBUS
sl@0
  2047
        SIGNAL (SIGBUS),
sl@0
  2048
#endif   // SIGBUS
sl@0
  2049
#ifdef SIGCANCEL
sl@0
  2050
        SIGNAL (SIGCANCEL),
sl@0
  2051
#endif   // SIGCANCEL
sl@0
  2052
#ifdef SIGCHLD
sl@0
  2053
        SIGNAL (SIGCHLD),
sl@0
  2054
#endif   // SIGCHLD
sl@0
  2055
#ifdef SIGCKPT
sl@0
  2056
        SIGNAL (SIGCKPT),
sl@0
  2057
#endif   // SIGCKPT
sl@0
  2058
#ifdef SIGCLD
sl@0
  2059
        SIGNAL (SIGCLD),
sl@0
  2060
#endif   // SIGCLD
sl@0
  2061
#ifdef SIGCONT
sl@0
  2062
        SIGNAL (SIGCONT),
sl@0
  2063
#endif   // SIGCONT
sl@0
  2064
#ifdef SIGDIL
sl@0
  2065
        SIGNAL (SIGDIL),
sl@0
  2066
#endif   // SIGDIL
sl@0
  2067
#ifdef SIGEMT
sl@0
  2068
        SIGNAL (SIGEMT),
sl@0
  2069
#endif   // SIGEMT
sl@0
  2070
#ifdef SIGFPE
sl@0
  2071
        SIGNAL (SIGFPE),
sl@0
  2072
#endif   // SIGFPE
sl@0
  2073
#ifdef SIGFREEZE
sl@0
  2074
        SIGNAL (SIGFREEZE),
sl@0
  2075
#endif   // SIGFREEZE
sl@0
  2076
#ifdef SIGGFAULT
sl@0
  2077
        SIGNAL (SIGGFAULT),
sl@0
  2078
#endif   // SIGGFAULT
sl@0
  2079
#ifdef SIGHUP
sl@0
  2080
        SIGNAL (SIGHUP),
sl@0
  2081
#endif   // SIGHUP
sl@0
  2082
#ifdef SIGILL
sl@0
  2083
        SIGNAL (SIGILL),
sl@0
  2084
#endif   // SIGILL
sl@0
  2085
#ifdef SIGINFO
sl@0
  2086
        SIGNAL (SIGINFO),
sl@0
  2087
#endif   // SIGINFO
sl@0
  2088
#ifdef SIGINT
sl@0
  2089
        SIGNAL (SIGINT),
sl@0
  2090
#endif   // SIGINT
sl@0
  2091
#ifdef SIGIO
sl@0
  2092
        SIGNAL (SIGIO),
sl@0
  2093
#endif   // SIGIO
sl@0
  2094
#ifdef SIGIOT
sl@0
  2095
        SIGNAL (SIGIOT),
sl@0
  2096
#endif   // SIGIOT
sl@0
  2097
#ifdef SIGK32
sl@0
  2098
        SIGNAL (SIGK32),
sl@0
  2099
#endif   // SIGK32
sl@0
  2100
#ifdef SIGKILL
sl@0
  2101
        SIGNAL (SIGKILL),
sl@0
  2102
#endif   // SIGKILL
sl@0
  2103
#ifdef SIGLOST
sl@0
  2104
        SIGNAL (SIGLOST),
sl@0
  2105
#endif   // SIGLOST
sl@0
  2106
#ifdef SIGLWP
sl@0
  2107
        SIGNAL (SIGLWP),
sl@0
  2108
#endif   // SIGLWP
sl@0
  2109
#ifdef SIGPIPE
sl@0
  2110
        SIGNAL (SIGPIPE),
sl@0
  2111
#endif   // SIGPIPE
sl@0
  2112
#ifdef SIGPOLL
sl@0
  2113
        SIGNAL (SIGPOLL),
sl@0
  2114
#endif   // SIGPOLL
sl@0
  2115
#ifdef SIGPROF
sl@0
  2116
        SIGNAL (SIGPROF),
sl@0
  2117
#endif   // SIGPROF
sl@0
  2118
#ifdef SIGPTINTR
sl@0
  2119
        SIGNAL (SIGPTINTR),
sl@0
  2120
#endif   // SIGPTINTR
sl@0
  2121
#ifdef SIGPTRESCHED
sl@0
  2122
        SIGNAL (SIGPTRESCHED),
sl@0
  2123
#endif   // SIGPTRESCHED
sl@0
  2124
#ifdef SIGPWR
sl@0
  2125
        SIGNAL (SIGPWR),
sl@0
  2126
#endif   // SIGPWR
sl@0
  2127
#ifdef SIGQUIT
sl@0
  2128
        SIGNAL (SIGQUIT),
sl@0
  2129
#endif   // SIGQUIT
sl@0
  2130
#ifdef SIGRESTART
sl@0
  2131
        SIGNAL (SIGRESTART),
sl@0
  2132
#endif   // SIGRESTART
sl@0
  2133
#ifdef SIGRESV
sl@0
  2134
        SIGNAL (SIGRESV),
sl@0
  2135
#endif   // SIGRESV
sl@0
  2136
#ifdef SIGSEGV
sl@0
  2137
        SIGNAL (SIGSEGV),
sl@0
  2138
#endif   // SIGSEGV
sl@0
  2139
#ifdef SIGSTKFLT
sl@0
  2140
        SIGNAL (SIGSTKFLT),
sl@0
  2141
#endif   // SIGSTKFLT
sl@0
  2142
#ifdef SIGSTOP
sl@0
  2143
        SIGNAL (SIGSTOP),
sl@0
  2144
#endif   // SIGSTOP
sl@0
  2145
#ifdef SIGSYS
sl@0
  2146
        SIGNAL (SIGSYS),
sl@0
  2147
#endif   // SIGSYS
sl@0
  2148
#ifdef SIGTERM
sl@0
  2149
        SIGNAL (SIGTERM),
sl@0
  2150
#endif   // SIGTERM
sl@0
  2151
#ifdef SIGTHAW
sl@0
  2152
        SIGNAL (SIGTHAW),
sl@0
  2153
#endif   // SIGTHAW
sl@0
  2154
#ifdef SIGTRAP
sl@0
  2155
        SIGNAL (SIGTRAP),
sl@0
  2156
#endif   // SIGTRAP
sl@0
  2157
#ifdef SIGTSTP
sl@0
  2158
        SIGNAL (SIGTSTP),
sl@0
  2159
#endif   // SIGTSTP
sl@0
  2160
#ifdef SIGTTIN
sl@0
  2161
        SIGNAL (SIGTTIN),
sl@0
  2162
#endif   // SIGTTIN
sl@0
  2163
#ifdef SIGTTOU
sl@0
  2164
        SIGNAL (SIGTTOU),
sl@0
  2165
#endif   // SIGTTOU
sl@0
  2166
#ifdef SIGUNUSED
sl@0
  2167
        SIGNAL (SIGUNUSED),
sl@0
  2168
#endif   // SIGUNUSED
sl@0
  2169
#ifdef SIGURG
sl@0
  2170
        SIGNAL (SIGURG),
sl@0
  2171
#endif   // SIGURG
sl@0
  2172
#ifdef SIGUSR1
sl@0
  2173
        SIGNAL (SIGUSR1),
sl@0
  2174
#endif   // SIGUSR1
sl@0
  2175
#ifdef SIGUSR2
sl@0
  2176
        SIGNAL (SIGUSR2),
sl@0
  2177
#endif   // SIGUSR2
sl@0
  2178
#ifdef SIGVTALRM
sl@0
  2179
        SIGNAL (SIGVTALRM),
sl@0
  2180
#endif   // SIGVTALRM
sl@0
  2181
#ifdef SIGWAITING
sl@0
  2182
        SIGNAL (SIGWAITING),
sl@0
  2183
#endif   // SIGWAITING
sl@0
  2184
#ifdef SIGWINCH
sl@0
  2185
        SIGNAL (SIGWINCH),
sl@0
  2186
#endif   // SIGWINCH
sl@0
  2187
#ifdef SIGWINDOW
sl@0
  2188
        SIGNAL (SIGWINDOW),
sl@0
  2189
#endif   // SIGWINDOW
sl@0
  2190
#ifdef SIGXCPU
sl@0
  2191
        SIGNAL (SIGXCPU),
sl@0
  2192
#endif   // SIGXCPU
sl@0
  2193
#ifdef SIGXFSZ
sl@0
  2194
        SIGNAL (SIGXFSZ),
sl@0
  2195
#endif   // SIGXFSZ
sl@0
  2196
#ifdef SIGXRES
sl@0
  2197
        SIGNAL (SIGXRES),
sl@0
  2198
#endif   // SIGXRES
sl@0
  2199
        { -1, 0 }
sl@0
  2200
    };
sl@0
  2201
sl@0
  2202
    char buffer [64];
sl@0
  2203
    const char *name = 0;
sl@0
  2204
sl@0
  2205
    for (size_t i = 0; i != sizeof names / sizeof *names; ++i) {
sl@0
  2206
        if (names [i].val == val) {
sl@0
  2207
            name = names [i].str;
sl@0
  2208
            break;
sl@0
  2209
        }
sl@0
  2210
    }
sl@0
  2211
sl@0
  2212
    if (0 == name) {
sl@0
  2213
        sprintf (buffer, "SIG#%d", val);
sl@0
  2214
        name = buffer;
sl@0
  2215
    }
sl@0
  2216
sl@0
  2217
    return _rw_fmtstr (spec, pbuf, pbufsize, name, _RWSTD_SIZE_MAX);
sl@0
  2218
}
sl@0
  2219
sl@0
  2220
/********************************************************************/
sl@0
  2221
sl@0
  2222
template <class charT>
sl@0
  2223
int rw_quotechar (char *buf, charT wc, int noesc)
sl@0
  2224
{
sl@0
  2225
#if _RWSTD_WCHAR_T_MIN < 0
sl@0
  2226
sl@0
  2227
    // wchar_t is signed, convert its value to unsigned long
sl@0
  2228
    // without widening (i.e., treat it as an unsigned type)
sl@0
  2229
sl@0
  2230
#  if _RWSTD_WCHAR_T_MIN == _RWSTD_SHRT_MIN
sl@0
  2231
    const unsigned long wi = (unsigned short)wc;
sl@0
  2232
#  elif _RWSTD_WCHAR_T_MIN ==_RWSTD_INT_MIN
sl@0
  2233
    const unsigned long wi = (unsigned int)wc;
sl@0
  2234
#  elif _RWSTD_WCHAR_T_MIN == _RWSTD_LONG_MIN
sl@0
  2235
    const unsigned long wi = (unsigned long)wc;
sl@0
  2236
#  endif
sl@0
  2237
sl@0
  2238
#else   // if _RWSTD_WCHAR_T_MIN >= 0
sl@0
  2239
sl@0
  2240
    // wchar_t is unsigned
sl@0
  2241
    const unsigned long wi = (unsigned long)wc;
sl@0
  2242
sl@0
  2243
#endif   // _RWSTD_WCHAR_T_MIN < 0
sl@0
  2244
sl@0
  2245
    if ((1 == sizeof wc || wi < 0x100) && noesc) {
sl@0
  2246
        buf [0] = char (wc);
sl@0
  2247
        buf [1] = '\0';
sl@0
  2248
        return 1;
sl@0
  2249
    }
sl@0
  2250
sl@0
  2251
    int len = 3;
sl@0
  2252
sl@0
  2253
    buf [0] = '\\';
sl@0
  2254
    buf [2] = '\0';
sl@0
  2255
sl@0
  2256
    switch (wc) {
sl@0
  2257
    case '\a': buf [1] = 'a';  buf [len = 2] = '\0'; break;
sl@0
  2258
    case '\b': buf [1] = 'b';  buf [len = 2] = '\0'; break;
sl@0
  2259
    case '\f': buf [1] = 'f';  buf [len = 2] = '\0'; break;
sl@0
  2260
    case '\n': buf [1] = 'n';  buf [len = 2] = '\0'; break;
sl@0
  2261
    case '\r': buf [1] = 'r';  buf [len = 2] = '\0'; break;
sl@0
  2262
    case '\t': buf [1] = 't';  buf [len = 2] = '\0'; break;
sl@0
  2263
    case '\v': buf [1] = 'v';  buf [len = 2] = '\0'; break;
sl@0
  2264
    case '\\': buf [1] = '\\'; buf [len = 2] = '\0'; break;
sl@0
  2265
    case '"' : buf [1] = '"';  buf [len = 2] = '\0'; break;
sl@0
  2266
    default:
sl@0
  2267
        if (wc < ' ' || wc > '~') {
sl@0
  2268
sl@0
  2269
            if (0 == wc) {
sl@0
  2270
                buf [1] = '0';
sl@0
  2271
                buf [2] = '\0';
sl@0
  2272
                len = 2;
sl@0
  2273
            }
sl@0
  2274
            else if (1 == sizeof wc) {
sl@0
  2275
                len = 1 + sprintf (buf + 1, "x%02x", (unsigned char)wc);
sl@0
  2276
            }
sl@0
  2277
            else {
sl@0
  2278
sl@0
  2279
                const int width =
sl@0
  2280
                      wi > 0xfffffffUL ? 8 : wi > 0xffffffUL ? 7
sl@0
  2281
                    : wi > 0xfffffUL   ? 6 : wi > 0xffffUL   ? 5
sl@0
  2282
                    : wi > 0xfffUL     ? 4 : wi > 0xffUL     ? 3
sl@0
  2283
                    : wi > 0xfUL       ? 2 : 2;
sl@0
  2284
sl@0
  2285
                len = 1 + sprintf (buf + 1, "x%0*lx", width, (unsigned long)wi);
sl@0
  2286
            }
sl@0
  2287
        }
sl@0
  2288
        else {
sl@0
  2289
            buf [0] = wc;
sl@0
  2290
            buf [1] = '\0';
sl@0
  2291
            len = 1;
sl@0
  2292
        }
sl@0
  2293
    }
sl@0
  2294
sl@0
  2295
    return len;
sl@0
  2296
}
sl@0
  2297
sl@0
  2298
sl@0
  2299
template <class charT>
sl@0
  2300
int rw_quotestr (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
sl@0
  2301
                 const charT *wstr, size_t nchars, int noesc)
sl@0
  2302
{
sl@0
  2303
	assert(1);
sl@0
  2304
	return 0;
sl@0
  2305
#if 0	
sl@0
  2306
    assert (0 != pbuf);
sl@0
  2307
sl@0
  2308
    if (!wstr) {
sl@0
  2309
        static const charT null[] = { '(', 'n', 'u', 'l', 'l', ')', '\0' };
sl@0
  2310
        wstr   = null;
sl@0
  2311
        nchars = sizeof null / sizeof *null - 1;
sl@0
  2312
    }
sl@0
  2313
sl@0
  2314
    if (0 > _RW::__rw_memattr (wstr, _RWSTD_SIZE_MAX, 0)) {
sl@0
  2315
sl@0
  2316
        const size_t buflen = *pbuf ? strlen (*pbuf) : 0;
sl@0
  2317
sl@0
  2318
        if (0 == _rw_bufcat (pbuf, pbufsize, "(invalid address ", 18))
sl@0
  2319
            return -1;
sl@0
  2320
sl@0
  2321
        FmtSpec newspec (spec);
sl@0
  2322
        newspec.fl_pound = 1;
sl@0
  2323
        if (-1 == ::_rw_fmtptr (newspec, pbuf, pbufsize, wstr))
sl@0
  2324
            return -1;
sl@0
  2325
        if (0 == _rw_bufcat (pbuf, pbufsize, ")", 2))
sl@0
  2326
            return -1;
sl@0
  2327
sl@0
  2328
        return int (strlen (*pbuf) - buflen);
sl@0
  2329
    }
sl@0
  2330
sl@0
  2331
    if (_RWSTD_SIZE_MAX == nchars) {
sl@0
  2332
        // compute the length of the NUL-terminate string
sl@0
  2333
        nchars = 0;
sl@0
  2334
        for (const charT *pc = wstr; *pc; ++pc, ++nchars);
sl@0
  2335
    }
sl@0
  2336
sl@0
  2337
    char *next = _rw_bufcat (pbuf, pbufsize, 0, (nchars + 1) * 12 + 3);
sl@0
  2338
    const char* const bufend = next;
sl@0
  2339
sl@0
  2340
    if (0 == next)
sl@0
  2341
        return -1;
sl@0
  2342
sl@0
  2343
    if (0 == nchars) {
sl@0
  2344
        if (noesc) {
sl@0
  2345
sl@0
  2346
#if 0   // width handling disabled (width used for array formatting)
sl@0
  2347
            for (int w = 0; w < spec.width; ++w)
sl@0
  2348
                *next++ = ' ';
sl@0
  2349
#endif   // 0/1
sl@0
  2350
sl@0
  2351
        }
sl@0
  2352
        else {
sl@0
  2353
            if (_RWSTD_WCHAR_T_SIZE == sizeof (charT))
sl@0
  2354
                *next++ = 'L';
sl@0
  2355
sl@0
  2356
            *next++ = '"';
sl@0
  2357
#if 0   // width handling disabled (width used for array formatting)
sl@0
  2358
            for (int w = 0; w < spec.width; ++w)
sl@0
  2359
                 *next++ = ' ';
sl@0
  2360
#endif   // 0/1
sl@0
  2361
            *next++ = '"';
sl@0
  2362
        }
sl@0
  2363
        *next++ = '\0';
sl@0
  2364
        return int (next - bufend);
sl@0
  2365
    }
sl@0
  2366
sl@0
  2367
    char *s = next;
sl@0
  2368
sl@0
  2369
    const charT *last = wstr;
sl@0
  2370
sl@0
  2371
    bool any_repeats = false;
sl@0
  2372
    long last_repeat = noesc ? 0L : -1L;
sl@0
  2373
sl@0
  2374
    char chstr [16];
sl@0
  2375
sl@0
  2376
    const ptrdiff_t N = ptrdiff_t (noesc ? 0 : 20);
sl@0
  2377
sl@0
  2378
    for (const charT *pwc = last + 1; ; ++pwc) {
sl@0
  2379
sl@0
  2380
        if (*pwc == *last && size_t (pwc - wstr) < nchars) {
sl@0
  2381
            // if the last processed character repeats, continue
sl@0
  2382
            // until a different character is encountered
sl@0
  2383
            continue;
sl@0
  2384
        }
sl@0
  2385
sl@0
  2386
        if (N > 1 && pwc - last > N) {
sl@0
  2387
sl@0
  2388
            // if the last processed character repeats N or more
sl@0
  2389
            // times, format the repeat count instead of all the
sl@0
  2390
            // repeated occurrences of the character to conserve
sl@0
  2391
            // space and make the string more readable
sl@0
  2392
sl@0
  2393
            const long repeat = pwc - last;
sl@0
  2394
sl@0
  2395
            rw_quotechar (chstr, *last, noesc);
sl@0
  2396
sl@0
  2397
            s += sprintf (s, "%s'%s' <repeats %ld times>",
sl@0
  2398
                            -1 == last_repeat ? ""
sl@0
  2399
                          :  0 == last_repeat ? "\", " : ", ",
sl@0
  2400
                          chstr, repeat);
sl@0
  2401
sl@0
  2402
            last = pwc;
sl@0
  2403
sl@0
  2404
            any_repeats = true;
sl@0
  2405
            last_repeat = repeat;
sl@0
  2406
        }
sl@0
  2407
        else {
sl@0
  2408
            // otherwise (if the last processed character repeats
sl@0
  2409
            // fewer than N times) format the character that many
sl@0
  2410
            // times
sl@0
  2411
sl@0
  2412
            if (last_repeat < 0) {
sl@0
  2413
                // opening quote
sl@0
  2414
                if (_RWSTD_WCHAR_T_SIZE == sizeof (charT)) {
sl@0
  2415
                    *s++ = 'L';
sl@0
  2416
                }
sl@0
  2417
                *s++ = '\"';
sl@0
  2418
            }
sl@0
  2419
            else if (last_repeat > 0) {
sl@0
  2420
                *s++ = ',';
sl@0
  2421
                *s++ = ' ';
sl@0
  2422
                *s++ = '\"';
sl@0
  2423
            }
sl@0
  2424
sl@0
  2425
            rw_quotechar (chstr, *last, noesc);
sl@0
  2426
sl@0
  2427
            while (last != pwc) {
sl@0
  2428
                s += sprintf (s, "%s", chstr);
sl@0
  2429
                ++last;
sl@0
  2430
            }
sl@0
  2431
sl@0
  2432
            last_repeat = 0;
sl@0
  2433
sl@0
  2434
            if (size_t (pwc - wstr) == nchars) {
sl@0
  2435
                if (!noesc)
sl@0
  2436
                    *s++ = '\"';
sl@0
  2437
                *s = '\0';
sl@0
  2438
                break;
sl@0
  2439
            }
sl@0
  2440
        }
sl@0
  2441
sl@0
  2442
        if (size_t (pwc - wstr) == nchars)
sl@0
  2443
            break;
sl@0
  2444
    }
sl@0
  2445
sl@0
  2446
    if (any_repeats) {
sl@0
  2447
        const size_t len = strlen (next);
sl@0
  2448
        memmove (next + 2, next, len);
sl@0
  2449
        next [0] = '{';
sl@0
  2450
        next [1] = ' ';
sl@0
  2451
        next [len + 2] = ' ';
sl@0
  2452
        next [len + 3] = '}';
sl@0
  2453
        next [len + 4] = '\0';
sl@0
  2454
        s = next + len + 4;
sl@0
  2455
    }
sl@0
  2456
sl@0
  2457
    return int (s - bufend);
sl@0
  2458
#endif    
sl@0
  2459
}
sl@0
  2460
sl@0
  2461
/********************************************************************/
sl@0
  2462
sl@0
  2463
static int
sl@0
  2464
_rw_fmtchr (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
sl@0
  2465
{
sl@0
  2466
    typedef unsigned char UChar;
sl@0
  2467
    const UChar uc = UChar (val);
sl@0
  2468
sl@0
  2469
    char buffer [8];
sl@0
  2470
    int len = rw_quotechar (buffer + spec.fl_pound, uc, !spec.fl_pound);
sl@0
  2471
    if (spec.fl_pound) {
sl@0
  2472
        buffer [0] = buffer [len + 1] = '\'';
sl@0
  2473
        buffer [len + 2] = '\0';
sl@0
  2474
        len += 2;
sl@0
  2475
    }
sl@0
  2476
sl@0
  2477
    FmtSpec newspec (spec);
sl@0
  2478
    newspec.fl_pound = 0;
sl@0
  2479
    return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (len));
sl@0
  2480
}
sl@0
  2481
sl@0
  2482
/********************************************************************/
sl@0
  2483
sl@0
  2484
static int
sl@0
  2485
_rw_fmtwchr (const FmtSpec &spec, char **pbuf, size_t *pbufsize, wint_t val)
sl@0
  2486
{
sl@0
  2487
    const wchar_t wc = wchar_t (val);
sl@0
  2488
sl@0
  2489
    char buffer [16];
sl@0
  2490
    int len = rw_quotechar (buffer + 2 * spec.fl_pound, wc, !spec.fl_pound);
sl@0
  2491
    if (spec.fl_pound) {
sl@0
  2492
        buffer [0] = 'L';
sl@0
  2493
        buffer [1] = buffer [len + 2] = '\'';
sl@0
  2494
        buffer [len + 3] = '\0';
sl@0
  2495
        len += 3;
sl@0
  2496
    }
sl@0
  2497
sl@0
  2498
    FmtSpec newspec (spec);
sl@0
  2499
    newspec.fl_pound = 0;
sl@0
  2500
    return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (len));
sl@0
  2501
}
sl@0
  2502
sl@0
  2503
/********************************************************************/
sl@0
  2504
sl@0
  2505
static int
sl@0
  2506
_rw_fmtstr (const FmtSpec &spec,
sl@0
  2507
           char **pbuf, size_t *pbufsize, const char *str, size_t len)
sl@0
  2508
{
sl@0
  2509
	assert (1);
sl@0
  2510
	return 0;
sl@0
  2511
#if 0	
sl@0
  2512
    if (spec.fl_pound)
sl@0
  2513
        return rw_quotestr (spec, pbuf, pbufsize, str, len, 0);
sl@0
  2514
sl@0
  2515
    if (0 == str)
sl@0
  2516
        str = "(null)";
sl@0
  2517
sl@0
  2518
    if (0 > _RW::__rw_memattr (str, _RWSTD_SIZE_MAX, 0)) {
sl@0
  2519
sl@0
  2520
        const size_t buflen = *pbuf ? strlen (*pbuf) : 0;
sl@0
  2521
sl@0
  2522
        if (0 == _rw_bufcat (pbuf, pbufsize, "(invalid address ", 18))
sl@0
  2523
            return -1;
sl@0
  2524
sl@0
  2525
        FmtSpec newspec (spec);
sl@0
  2526
        newspec.fl_pound = 1;
sl@0
  2527
sl@0
  2528
        if (-1 == _rw_fmtptr (newspec, pbuf, pbufsize, str))
sl@0
  2529
            return -1;
sl@0
  2530
sl@0
  2531
        if (0 == _rw_bufcat (pbuf, pbufsize, ")", 2))
sl@0
  2532
            return -1;
sl@0
  2533
sl@0
  2534
        return int (strlen (*pbuf) - buflen);
sl@0
  2535
    }
sl@0
  2536
sl@0
  2537
    if (_RWSTD_SIZE_MAX == len)
sl@0
  2538
        len = strlen (str);
sl@0
  2539
sl@0
  2540
    // compute the minimum number of characters to be generated
sl@0
  2541
    if (-1 < spec.prec && size_t (spec.prec) < len)
sl@0
  2542
        len = size_t (spec.prec);
sl@0
  2543
sl@0
  2544
    // the number of generated characters depends on three variables:
sl@0
  2545
    // --  the optional field width,
sl@0
  2546
    // --  the optional precision, and
sl@0
  2547
    // --  the length of the argument
sl@0
  2548
sl@0
  2549
    // compute the field width
sl@0
  2550
    const size_t width =
sl@0
  2551
        -1 < spec.width && len < size_t (spec.width) ?
sl@0
  2552
        size_t (spec.width) : len;
sl@0
  2553
sl@0
  2554
    // compute the size of padding
sl@0
  2555
    const size_t pad = len < width ? width - len : 0;
sl@0
  2556
sl@0
  2557
    // [re]allocate enough space in the buffer
sl@0
  2558
    if (0 == _rw_bufcat (pbuf, pbufsize, 0, pad + len))
sl@0
  2559
        return -1;
sl@0
  2560
sl@0
  2561
    assert (0 != *pbuf);
sl@0
  2562
    char *next = *pbuf + strlen (*pbuf);
sl@0
  2563
sl@0
  2564
    if (!spec.fl_minus) {
sl@0
  2565
        for (size_t i = 0; i != pad; ++i)
sl@0
  2566
            *next++ = ' ';
sl@0
  2567
    }
sl@0
  2568
sl@0
  2569
    memcpy (next, str, len);
sl@0
  2570
    next += len;
sl@0
  2571
sl@0
  2572
    if (spec.fl_minus) {
sl@0
  2573
        for (size_t i = 0; i != pad; ++i)
sl@0
  2574
            *next++ = ' ';
sl@0
  2575
    }
sl@0
  2576
sl@0
  2577
    *next++ = '\0';
sl@0
  2578
sl@0
  2579
    return int (pad + len);
sl@0
  2580
#endif    
sl@0
  2581
}
sl@0
  2582
sl@0
  2583
/********************************************************************/
sl@0
  2584
sl@0
  2585
static int
sl@0
  2586
_rw_fmtwstr (const FmtSpec &spec,
sl@0
  2587
            char **pbuf, size_t *pbufsize, const wchar_t *wstr, size_t len)
sl@0
  2588
{
sl@0
  2589
    return rw_quotestr (spec, pbuf, pbufsize, wstr, len, 1);
sl@0
  2590
}
sl@0
  2591
sl@0
  2592
/********************************************************************/
sl@0
  2593
sl@0
  2594
struct Bitnames
sl@0
  2595
{
sl@0
  2596
    const char *longname;
sl@0
  2597
    const char *name;
sl@0
  2598
    int         bits;
sl@0
  2599
};
sl@0
  2600
sl@0
  2601
#define BITNAME(qual, name)   { #qual "::" #name, #name, qual::name }
sl@0
  2602
sl@0
  2603
static int
sl@0
  2604
rw_bmpfmt (const FmtSpec&, char **pbuf, size_t *pbufsize,
sl@0
  2605
           const Bitnames bmap[], size_t size, int bits)
sl@0
  2606
{
sl@0
  2607
    assert (0 != pbuf);
sl@0
  2608
sl@0
  2609
    char buffer [1024];
sl@0
  2610
    *buffer = '\0';
sl@0
  2611
sl@0
  2612
    // string to use when no bits are set
sl@0
  2613
    const char* all_clear = "0";
sl@0
  2614
sl@0
  2615
    for (size_t i = 0; i != size; ++i) {
sl@0
  2616
        if (bmap [i].bits) {
sl@0
  2617
            if ((bits & bmap [i].bits) == bmap [i].bits) {
sl@0
  2618
                strcat (*buffer ? strcat (buffer, " | ") : buffer,
sl@0
  2619
                        bmap [i].name);
sl@0
  2620
                bits &= ~bmap [i].bits;
sl@0
  2621
            }
sl@0
  2622
        }
sl@0
  2623
        else {
sl@0
  2624
            // save the name of the constant to use for 0
sl@0
  2625
            all_clear = bmap [i].name;
sl@0
  2626
        }
sl@0
  2627
    }
sl@0
  2628
sl@0
  2629
    size_t buffersize;
sl@0
  2630
sl@0
  2631
    if ('\0' == *buffer) {
sl@0
  2632
        // no constant matched, format teh value either as a number
sl@0
  2633
        // or, when 0, using the all_clear name (see above)
sl@0
  2634
        if (bits)
sl@0
  2635
            sprintf (buffer, "%#x", bits);
sl@0
  2636
        else
sl@0
  2637
            strcpy (buffer, all_clear);
sl@0
  2638
sl@0
  2639
        buffersize = strlen (buffer) + 1;
sl@0
  2640
    }
sl@0
  2641
    else if (bits) {
sl@0
  2642
        buffersize = strlen (buffer) + 1;
sl@0
  2643
sl@0
  2644
        // verify that buffer wasn't overflowed
sl@0
  2645
        assert (buffersize <= sizeof buffer);
sl@0
  2646
sl@0
  2647
        char bitstr [32];
sl@0
  2648
        const int n = sprintf (bitstr, "%#x | ", bits);
sl@0
  2649
sl@0
  2650
        assert (0 < n);
sl@0
  2651
sl@0
  2652
        memmove (buffer + n, buffer, buffersize);
sl@0
  2653
        memcpy (buffer, bitstr, size_t (n));
sl@0
  2654
sl@0
  2655
        buffersize += n;
sl@0
  2656
    }
sl@0
  2657
    else {
sl@0
  2658
        buffersize = strlen (buffer) + 1;
sl@0
  2659
    }
sl@0
  2660
sl@0
  2661
    // verify that buffer wasn't overflowed
sl@0
  2662
    assert (buffersize <= sizeof buffer);
sl@0
  2663
sl@0
  2664
    if (0 == _rw_bufcat (pbuf, pbufsize, buffer, buffersize))
sl@0
  2665
        return -1;
sl@0
  2666
sl@0
  2667
    return int (buffersize);
sl@0
  2668
}
sl@0
  2669
sl@0
  2670
/********************************************************************/
sl@0
  2671
sl@0
  2672
static int
sl@0
  2673
rw_fmtflags (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int bits)
sl@0
  2674
{
sl@0
  2675
    static const Bitnames names [] = {
sl@0
  2676
        BITNAME (std::ios, adjustfield),
sl@0
  2677
        BITNAME (std::ios, basefield),
sl@0
  2678
        BITNAME (std::ios, boolalpha),
sl@0
  2679
        BITNAME (std::ios, dec),
sl@0
  2680
        BITNAME (std::ios, fixed),
sl@0
  2681
        BITNAME (std::ios, hex),
sl@0
  2682
        BITNAME (std::ios, internal),
sl@0
  2683
        BITNAME (std::ios, left),
sl@0
  2684
        BITNAME (std::ios, oct),
sl@0
  2685
        BITNAME (std::ios, right),
sl@0
  2686
        BITNAME (std::ios, scientific),
sl@0
  2687
        BITNAME (std::ios, showbase),
sl@0
  2688
        BITNAME (std::ios, showpoint),
sl@0
  2689
        BITNAME (std::ios, showpos),
sl@0
  2690
        BITNAME (std::ios, skipws),
sl@0
  2691
        BITNAME (std::ios, unitbuf),
sl@0
  2692
        BITNAME (std::ios, uppercase),
sl@0
  2693
sl@0
  2694
#ifndef _RWSTD_NO_EXT_BIN_IO
sl@0
  2695
sl@0
  2696
        // extension: produce binary output (similar to oct, dec, and hex)
sl@0
  2697
        BITNAME (std::ios, bin),
sl@0
  2698
sl@0
  2699
#endif   // _RWSTD_NO_EXT_BIN_IO
sl@0
  2700
sl@0
  2701
#ifndef _RWSTD_NO_EXT_REENTRANT_IO
sl@0
  2702
sl@0
  2703
        // extension: allow unsychronized access to stream and/or its buffer
sl@0
  2704
        BITNAME (std::ios, nolock),
sl@0
  2705
        BITNAME (std::ios, nolockbuf)
sl@0
  2706
sl@0
  2707
#endif   // _RWSTD_NO_EXT_REENTRANT_IO
sl@0
  2708
sl@0
  2709
    };
sl@0
  2710
sl@0
  2711
    static const size_t count = sizeof names / sizeof *names;
sl@0
  2712
sl@0
  2713
    const int base = (bits >> _RWSTD_IOS_BASEOFF) & _RWSTD_IOS_BASEMASK;
sl@0
  2714
sl@0
  2715
    // zero out bits representingthe numeric base
sl@0
  2716
    bits &= ~(_RWSTD_IOS_BASEMASK << _RWSTD_IOS_BASEOFF);
sl@0
  2717
sl@0
  2718
    int len = rw_bmpfmt (spec, pbuf, pbufsize, names, count, bits);
sl@0
  2719
sl@0
  2720
    if (base && base != 8 && base != 10 && base != 16) {
sl@0
  2721
sl@0
  2722
        // for numeric bases other than those required by the standard,
sl@0
  2723
        // use the text "base (%d)" to show the extended numeric base
sl@0
  2724
sl@0
  2725
#ifndef _RWSTD_NO_EXT_BIN_IO
sl@0
  2726
sl@0
  2727
        if (bits & std::ios::bin)
sl@0
  2728
            return len;
sl@0
  2729
sl@0
  2730
#endif   // _RWSTD_NO_EXT_BIN_IO
sl@0
  2731
sl@0
  2732
        char basestr [64];
sl@0
  2733
        sprintf (basestr, " | std::ios::base(%d)", base);
sl@0
  2734
sl@0
  2735
        strcat (*pbuf, basestr);
sl@0
  2736
        
sl@0
  2737
        len = int (strlen (*pbuf));
sl@0
  2738
    }
sl@0
  2739
sl@0
  2740
    return len;
sl@0
  2741
}
sl@0
  2742
sl@0
  2743
/********************************************************************/
sl@0
  2744
sl@0
  2745
static int
sl@0
  2746
rw_fmtiostate (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int bits)
sl@0
  2747
{
sl@0
  2748
    static const Bitnames names [] = {
sl@0
  2749
        BITNAME (std::ios, goodbit),
sl@0
  2750
        BITNAME (std::ios, badbit),
sl@0
  2751
        BITNAME (std::ios, eofbit),
sl@0
  2752
        BITNAME (std::ios, failbit)
sl@0
  2753
    };
sl@0
  2754
sl@0
  2755
    static const size_t count = sizeof names / sizeof *names;
sl@0
  2756
sl@0
  2757
    return rw_bmpfmt (spec, pbuf, pbufsize, names, count, bits);
sl@0
  2758
}
sl@0
  2759
sl@0
  2760
/********************************************************************/
sl@0
  2761
sl@0
  2762
static int
sl@0
  2763
_rw_fmtopenmode (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int bits)
sl@0
  2764
{
sl@0
  2765
    static const Bitnames names [] = {
sl@0
  2766
sl@0
  2767
#ifndef __SYMBIAN32__
sl@0
  2768
sl@0
  2769
#ifndef _RWSTD_NO_EXTENSIONS
sl@0
  2770
sl@0
  2771
        { "std::ios::nocreate", "nocreate", std::ios::nocreate },
sl@0
  2772
        { "std::ios::noreplace", "noreplace", std::ios::noreplace },
sl@0
  2773
sl@0
  2774
#else   // if defined (_RWSTD_NO_EXTENSIONS)
sl@0
  2775
sl@0
  2776
        { "__rw:::__rw_nocreate", "__rw_nocreate", _RW::__rw_nocreate },
sl@0
  2777
        { "__rw::__rw_noreplace", "__rw_noreplace", _RW::__rw_noreplace },
sl@0
  2778
sl@0
  2779
#endif   // _RWSTD_NO_EXTENSIONS
sl@0
  2780
sl@0
  2781
#ifndef _RWSTD_NO_EXT_STDIO
sl@0
  2782
sl@0
  2783
        { "std::ios::stdio", "stdio", std::ios::stdio },
sl@0
  2784
        { "std::ios::native", "native", std::ios::native },
sl@0
  2785
sl@0
  2786
#else   // if defined (_RWSTD_NO_EXT_STDIO)
sl@0
  2787
sl@0
  2788
        { "__rw::__rw_stdio", "__rw_stdio", _RW::__rw_stdio },
sl@0
  2789
        { "__rw::__rw_native", "__rw_native", _RW::__rw_native },
sl@0
  2790
sl@0
  2791
#endif   // _RWSTD_NO_EXT_STDIO
sl@0
  2792
#endif
sl@0
  2793
        BITNAME (std::ios, app),
sl@0
  2794
        BITNAME (std::ios, binary),
sl@0
  2795
        BITNAME (std::ios, in),
sl@0
  2796
        BITNAME (std::ios, out),
sl@0
  2797
        BITNAME (std::ios, trunc),
sl@0
  2798
        BITNAME (std::ios, ate)
sl@0
  2799
    };
sl@0
  2800
sl@0
  2801
    static const size_t count = sizeof names / sizeof *names;
sl@0
  2802
sl@0
  2803
    return rw_bmpfmt (spec, pbuf, pbufsize, names, count, bits);
sl@0
  2804
}
sl@0
  2805
sl@0
  2806
/********************************************************************/
sl@0
  2807
sl@0
  2808
static int
sl@0
  2809
_rw_fmtevent (const FmtSpec&, char **pbuf, size_t *pbufsize, int event)
sl@0
  2810
{
sl@0
  2811
    const char* str =
sl@0
  2812
          std::ios::copyfmt_event == event ? "copyfmt_event"
sl@0
  2813
        : std::ios::imbue_event   == event ? "imbue_event"
sl@0
  2814
        : std::ios::erase_event   == event ? "erase_event"
sl@0
  2815
        : 0;
sl@0
  2816
sl@0
  2817
    char buffer [64];
sl@0
  2818
sl@0
  2819
    if (!str) {
sl@0
  2820
        sprintf (buffer, "copyfmt_event(%d)", event);
sl@0
  2821
        str = buffer;
sl@0
  2822
    }
sl@0
  2823
sl@0
  2824
    const size_t len = strlen (str);
sl@0
  2825
sl@0
  2826
    if (0 == _rw_bufcat (pbuf, pbufsize, str, len))
sl@0
  2827
        return -1;
sl@0
  2828
sl@0
  2829
    return int (len);
sl@0
  2830
}
sl@0
  2831
sl@0
  2832
/********************************************************************/
sl@0
  2833
sl@0
  2834
static int
sl@0
  2835
rw_fmtlc (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
sl@0
  2836
{
sl@0
  2837
    const char *str = 0;
sl@0
  2838
sl@0
  2839
    switch (val) {
sl@0
  2840
    case LC_ALL:      str = "LC_ALL"; break;
sl@0
  2841
    case LC_COLLATE:  str = "LC_COLLATE"; break;
sl@0
  2842
    case LC_CTYPE:    str = "LC_CTYPE"; break;
sl@0
  2843
    case LC_MONETARY: str = "LC_MONETARY"; break;
sl@0
  2844
    case LC_NUMERIC:  str = "LC_NUMERIC"; break;
sl@0
  2845
    case LC_TIME:     str = "LC_TIME"; break;
sl@0
  2846
sl@0
  2847
#ifdef LC_MESSAGES
sl@0
  2848
    case LC_MESSAGES: str = "LC_MESSAGES"; break;
sl@0
  2849
#endif   // LC_MESSAGES
sl@0
  2850
sl@0
  2851
    }
sl@0
  2852
sl@0
  2853
    if (str) {
sl@0
  2854
        const std::size_t len = strlen (str);
sl@0
  2855
sl@0
  2856
        if (0 == _rw_bufcat (pbuf, pbufsize, str, len))
sl@0
  2857
            return -1;
sl@0
  2858
sl@0
  2859
        return int (len);
sl@0
  2860
    }
sl@0
  2861
sl@0
  2862
    static const Bitnames names [] = {
sl@0
  2863
        BITNAME (std::locale, all),
sl@0
  2864
        BITNAME (std::locale, none),
sl@0
  2865
        BITNAME (std::locale, collate),
sl@0
  2866
        BITNAME (std::locale, ctype),
sl@0
  2867
        BITNAME (std::locale, monetary),
sl@0
  2868
        BITNAME (std::locale, numeric),
sl@0
  2869
        BITNAME (std::locale, messages),
sl@0
  2870
        BITNAME (std::locale, time)
sl@0
  2871
    };
sl@0
  2872
sl@0
  2873
    static const size_t count = sizeof names / sizeof *names;
sl@0
  2874
sl@0
  2875
    return rw_bmpfmt (spec, pbuf, pbufsize, names, count, val);
sl@0
  2876
}
sl@0
  2877
sl@0
  2878
/********************************************************************/
sl@0
  2879
sl@0
  2880
static int
sl@0
  2881
_rw_fmtmonpat (const FmtSpec&,
sl@0
  2882
              char **pbuf, size_t *pbufsize, const char pat [4])
sl@0
  2883
{
sl@0
  2884
    char buffer [80];
sl@0
  2885
sl@0
  2886
    buffer [0] = '\0';
sl@0
  2887
sl@0
  2888
    for (int i = 0; i != 4; ++i) {
sl@0
  2889
        switch (pat [i]) {
sl@0
  2890
        case std::money_base::symbol:
sl@0
  2891
            strcat (buffer, "symbol ");
sl@0
  2892
            break;
sl@0
  2893
sl@0
  2894
        case std::money_base::sign:
sl@0
  2895
            strcat (buffer, "sign ");
sl@0
  2896
            break;
sl@0
  2897
sl@0
  2898
        case std::money_base::none:
sl@0
  2899
            strcat (buffer, "none ");
sl@0
  2900
            break;
sl@0
  2901
sl@0
  2902
        case std::money_base::value:
sl@0
  2903
            strcat (buffer, "value ");
sl@0
  2904
            break;
sl@0
  2905
sl@0
  2906
        case std::money_base::space:
sl@0
  2907
            strcat (buffer, "space ");
sl@0
  2908
            break;
sl@0
  2909
sl@0
  2910
        default:
sl@0
  2911
            sprintf (buffer + strlen (buffer), "\\%03o", pat [i]);
sl@0
  2912
            break;
sl@0
  2913
        }
sl@0
  2914
    }
sl@0
  2915
sl@0
  2916
    const size_t len = strlen (buffer);
sl@0
  2917
sl@0
  2918
    if (0 == _rw_bufcat (pbuf, pbufsize, buffer, len))
sl@0
  2919
        return -1;
sl@0
  2920
sl@0
  2921
    return int (len);
sl@0
  2922
}
sl@0
  2923
sl@0
  2924
/********************************************************************/
sl@0
  2925
sl@0
  2926
static int
sl@0
  2927
libstd_vasnprintf (FmtSpec *pspec, size_t paramno,
sl@0
  2928
                   char **pbuf, size_t *pbufsize,
sl@0
  2929
                   const char *fmt, va_list *pva)
sl@0
  2930
{
sl@0
  2931
    assert (0 != pva);
sl@0
  2932
    assert (0 != pspec);
sl@0
  2933
sl@0
  2934
    _RWSTD_UNUSED (fmt);
sl@0
  2935
sl@0
  2936
    FmtSpec &spec = pspec [paramno];
sl@0
  2937
sl@0
  2938
    // the length of the sequence appended to the buffer to return
sl@0
  2939
    // to the caller, or a negative value (such as -1) on error
sl@0
  2940
    int len = -1;
sl@0
  2941
sl@0
  2942
    switch (spec.cvtspec) {
sl@0
  2943
sl@0
  2944
    case '?':   // %{?}
sl@0
  2945
        // beginning of an if clause
sl@0
  2946
        spec.cond       = 1;
sl@0
  2947
        spec.cond_begin = 1;
sl@0
  2948
        spec.cond_true  = 0 != va_arg (*pva, int);
sl@0
  2949
        len             = 0;
sl@0
  2950
        break;
sl@0
  2951
sl@0
  2952
    case ':':   // %{:}
sl@0
  2953
        if (spec.cond) {
sl@0
  2954
            // end of an active if clause and the beginning
sl@0
  2955
            // of an inactive else clause
sl@0
  2956
sl@0
  2957
            spec.cond_begin = 1;   // beginning of an else clause
sl@0
  2958
            spec.cond_end   = 1;   // end of an if clause
sl@0
  2959
            spec.cond_true  = !spec.cond_true;
sl@0
  2960
            len             = 0;
sl@0
  2961
        }
sl@0
  2962
        else {
sl@0
  2963
            // misplaced "%{:}"?
sl@0
  2964
            static const char str[] = "%{:}";
sl@0
  2965
            len = rw_quotestr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX, 0);
sl@0
  2966
        }
sl@0
  2967
        break;
sl@0
  2968
sl@0
  2969
    case ';':   // %{;}
sl@0
  2970
        if (spec.cond) {
sl@0
  2971
            spec.cond_end = 1;   // end of an if or else clause
sl@0
  2972
            len           = 0;
sl@0
  2973
        }
sl@0
  2974
        else {
sl@0
  2975
            // misplaced "%{;}"?
sl@0
  2976
            static const char str[] = "%{;}";
sl@0
  2977
            len = rw_quotestr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX, 0);
sl@0
  2978
        }
sl@0
  2979
        break;
sl@0
  2980
sl@0
  2981
    case 'c':   // %{c}, %{Ac}, %{Lc}, %{lc}
sl@0
  2982
        if (spec.mod_A) {
sl@0
  2983
            if (-1 == spec.width || 1 == spec.width) {
sl@0
  2984
                spec.param.ptr = PARAM (_RWSTD_UINT8_T*, ptr);
sl@0
  2985
                const _RWSTD_UINT8_T* const array =
sl@0
  2986
                    (_RWSTD_UINT8_T*)spec.param.ptr;
sl@0
  2987
                len = rw_quotestr (spec, pbuf, pbufsize, array,
sl@0
  2988
                                   _RWSTD_SIZE_MAX, 0);
sl@0
  2989
            }
sl@0
  2990
            else if (2 == spec.width) {
sl@0
  2991
                spec.param.ptr = PARAM (_RWSTD_UINT16_T*, ptr);
sl@0
  2992
                const _RWSTD_UINT16_T* const array =
sl@0
  2993
                    (_RWSTD_UINT16_T*)spec.param.ptr;
sl@0
  2994
                len = rw_quotestr (spec, pbuf, pbufsize, array,
sl@0
  2995
                                   _RWSTD_SIZE_MAX, 0);
sl@0
  2996
            }
sl@0
  2997
            else if (4 == spec.width) {
sl@0
  2998
                spec.param.ptr = PARAM (_RWSTD_UINT32_T*, ptr);
sl@0
  2999
                const _RWSTD_UINT32_T* const array =
sl@0
  3000
                    (_RWSTD_UINT32_T*)spec.param.ptr;
sl@0
  3001
                len = rw_quotestr (spec, pbuf, pbufsize, array,
sl@0
  3002
                                   _RWSTD_SIZE_MAX, 0);
sl@0
  3003
            }
sl@0
  3004
sl@0
  3005
#ifdef _RWSTD_UINT64_T
sl@0
  3006
sl@0
  3007
            else if (8 == spec.width) {
sl@0
  3008
                spec.param.ptr = PARAM (_RWSTD_UINT64_T*, ptr);
sl@0
  3009
                const _RWSTD_UINT64_T* const array =
sl@0
  3010
                    (_RWSTD_UINT64_T*)spec.param.ptr;
sl@0
  3011
                len = rw_quotestr (spec, pbuf, pbufsize, array,
sl@0
  3012
                                   _RWSTD_SIZE_MAX, 0);
sl@0
  3013
            }
sl@0
  3014
sl@0
  3015
#endif   // _RWSTD_UINT64_T
sl@0
  3016
sl@0
  3017
            else {
sl@0
  3018
                assert (!"%{Ac} not implemented for this character size");
sl@0
  3019
            }
sl@0
  3020
        }
sl@0
  3021
        else if (spec.mod_L) {   // locale category or LC_XXX constant
sl@0
  3022
            spec.param.i = PARAM (int, i);
sl@0
  3023
            len = rw_fmtlc (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3024
        }
sl@0
  3025
        else if (spec.mod_l) {   // wchar_t
sl@0
  3026
            spec.param.wi = PARAM (wint_t, i);
sl@0
  3027
            return _rw_fmtwchr (spec, pbuf, pbufsize, spec.param.wi);
sl@0
  3028
        }
sl@0
  3029
        else {   // char
sl@0
  3030
            spec.param.i = PARAM (int, i);
sl@0
  3031
            return _rw_fmtchr (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3032
        }
sl@0
  3033
        break;
sl@0
  3034
sl@0
  3035
    case 'e':   // %{e}, %{Ae}
sl@0
  3036
        if (spec.mod_A) {   // array of floating point values
sl@0
  3037
            spec.param.ptr = PARAM (void*, ptr);
sl@0
  3038
            len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr);
sl@0
  3039
        }
sl@0
  3040
        else if (spec.mod_I) {   // ios::copyfmt_event
sl@0
  3041
            spec.param.i = PARAM (int, i);
sl@0
  3042
            len = _rw_fmtevent (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3043
        }
sl@0
  3044
        break;
sl@0
  3045
sl@0
  3046
    case 'f':   // %{f}, %{Af}, %{If}
sl@0
  3047
        if (spec.mod_A) {   // array of floating point values
sl@0
  3048
            spec.param.ptr = PARAM (void*, ptr);
sl@0
  3049
            len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr);
sl@0
  3050
        }
sl@0
  3051
        if (spec.mod_I) {   // ios::fmtflags
sl@0
  3052
            spec.param.i = PARAM (int, i);
sl@0
  3053
            len = rw_fmtflags (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3054
        }
sl@0
  3055
        else {   // function pointer
sl@0
  3056
            spec.param.funptr = PARAM (funptr_t, funptr);
sl@0
  3057
            len = _rw_fmtfunptr (spec, pbuf, pbufsize, spec.param.funptr);
sl@0
  3058
        }
sl@0
  3059
        break;
sl@0
  3060
sl@0
  3061
    case 'g':   // %{g}, %{Ag}
sl@0
  3062
        if (spec.mod_A) {   // array of floating point values
sl@0
  3063
            spec.param.ptr = PARAM (void*, ptr);
sl@0
  3064
            len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr);
sl@0
  3065
        }
sl@0
  3066
        else {
sl@0
  3067
            assert (!"%{g} not implemented");
sl@0
  3068
        }
sl@0
  3069
sl@0
  3070
    case 'd':   // %{Id}
sl@0
  3071
    case 'i':   // %{Ii}
sl@0
  3072
    case 'o':   // %{Io}
sl@0
  3073
        if (spec.mod_I) {   // ios::openmode
sl@0
  3074
            spec.param.i = PARAM (int, i);
sl@0
  3075
            len = _rw_fmtopenmode (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3076
            break;
sl@0
  3077
        }
sl@0
  3078
    case 'x':   // %{x}
sl@0
  3079
    case 'X':   // %{X}
sl@0
  3080
    case 'u':   // %{u}
sl@0
  3081
        len = _rw_fmtinteger (pspec, paramno, pbuf, pbufsize, pva);
sl@0
  3082
        break;
sl@0
  3083
sl@0
  3084
    case 'K':   // %{K} -- signal
sl@0
  3085
        spec.param.i = PARAM (int, i);
sl@0
  3086
        len = _rw_fmtsignal (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3087
        break;
sl@0
  3088
sl@0
  3089
    case 'm':   // %{m} -- errno
sl@0
  3090
        if (-1 == spec.width)
sl@0
  3091
            len = _rw_fmterrno (spec, pbuf, pbufsize, errno);
sl@0
  3092
        else
sl@0
  3093
            len = _rw_fmterrno (spec, pbuf, pbufsize, spec.width);
sl@0
  3094
        break;
sl@0
  3095
sl@0
  3096
    case 'M':   // %{M}, %{LM}
sl@0
  3097
        if (spec.mod_L) {   // money_base::pattern
sl@0
  3098
            spec.param.ptr = PARAM (char*, ptr);
sl@0
  3099
            len = _rw_fmtmonpat (spec, pbuf, pbufsize, (char*)spec.param.ptr);
sl@0
  3100
        }
sl@0
  3101
        else {   // member pointer
sl@0
  3102
            spec.param.memptr = PARAM (memptr_t, memptr);
sl@0
  3103
            len = _rw_fmtmemptr (spec, pbuf, pbufsize, spec.param.memptr);
sl@0
  3104
        }
sl@0
  3105
        break;
sl@0
  3106
sl@0
  3107
    case 'n': {   // %{n}
sl@0
  3108
        // The argument shall be a pointer to signed integer into which
sl@0
  3109
        // is written the size of the buffer allocated by this call to
sl@0
  3110
        // fprintf. No argument is converted, but one is consumed. If
sl@0
  3111
        // the conversion specification includes any flags, a field
sl@0
  3112
        // width, or a precision, the behavior is undefined.
sl@0
  3113
sl@0
  3114
        assert (0 != pbuf);
sl@0
  3115
        assert (0 != *pbuf);
sl@0
  3116
sl@0
  3117
        const size_t nbytes = pbufsize ? *pbufsize : 0;
sl@0
  3118
sl@0
  3119
        spec.param.ptr = PARAM (void*, ptr);
sl@0
  3120
sl@0
  3121
        if (spec.mod_hh) {
sl@0
  3122
            unsigned char* const ptr = (unsigned char*)spec.param.ptr;
sl@0
  3123
sl@0
  3124
            assert (0 != ptr);
sl@0
  3125
sl@0
  3126
            *ptr = (unsigned char)nbytes;
sl@0
  3127
        }
sl@0
  3128
        else if (spec.mod_h) {
sl@0
  3129
            short* const ptr = (short*)spec.param.ptr;
sl@0
  3130
sl@0
  3131
            assert (0 != ptr);
sl@0
  3132
sl@0
  3133
            *ptr = short (nbytes);
sl@0
  3134
        }
sl@0
  3135
        else if (spec.mod_L) {
sl@0
  3136
#ifdef _RWSTD_LONG_LONG
sl@0
  3137
            _RWSTD_LONG_LONG* const ptr = (_RWSTD_LONG_LONG*)spec.param.ptr;
sl@0
  3138
sl@0
  3139
            assert (0 != ptr);
sl@0
  3140
sl@0
  3141
            *ptr = (_RWSTD_LONG_LONG)(nbytes);
sl@0
  3142
#else   // if !defined (_RWSTD_LONG_LONG)
sl@0
  3143
            assert (!"%{Ln} not implemented");
sl@0
  3144
#endif   // _RWSTD_LONG_LONG
sl@0
  3145
        }
sl@0
  3146
        else if (spec.mod_l) {
sl@0
  3147
            long* const ptr = (long*)spec.param.ptr;
sl@0
  3148
sl@0
  3149
            assert (0 != ptr);
sl@0
  3150
sl@0
  3151
            *ptr = long (nbytes);
sl@0
  3152
        }
sl@0
  3153
        else if (spec.mod_t) {
sl@0
  3154
            ptrdiff_t* const ptr = (ptrdiff_t*)spec.param.ptr;
sl@0
  3155
sl@0
  3156
            assert (0 != ptr);
sl@0
  3157
sl@0
  3158
            *ptr = ptrdiff_t (nbytes);
sl@0
  3159
        }
sl@0
  3160
        else {
sl@0
  3161
            int* const ptr = (int*)spec.param.ptr;
sl@0
  3162
sl@0
  3163
            assert (0 != ptr);
sl@0
  3164
sl@0
  3165
            *ptr = int (nbytes);
sl@0
  3166
        }
sl@0
  3167
        len = 0;
sl@0
  3168
        break;
sl@0
  3169
    }
sl@0
  3170
sl@0
  3171
    case 's':   // %{s}, %{Is}, %{ls}
sl@0
  3172
        if (spec.mod_I) {   // ios::iostate
sl@0
  3173
            spec.param.i = PARAM (int, i);
sl@0
  3174
            len = rw_fmtiostate (spec, pbuf, pbufsize, spec.param.i);
sl@0
  3175
        }
sl@0
  3176
        else if (spec.mod_l) {   // wchar_t*
sl@0
  3177
            spec.param.ptr = PARAM (wchar_t*, ptr);
sl@0
  3178
            const wchar_t* const wstr = (wchar_t*)spec.param.ptr;
sl@0
  3179
            len = rw_quotestr (spec, pbuf, pbufsize, wstr, _RWSTD_SIZE_MAX, 0);
sl@0
  3180
        }
sl@0
  3181
        else {   // char*
sl@0
  3182
            spec.param.ptr = PARAM (char*, ptr);
sl@0
  3183
            const char* const str = (char*)spec.param.ptr;
sl@0
  3184
            len = rw_quotestr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX, 0);
sl@0
  3185
        }
sl@0
  3186
        break;
sl@0
  3187
sl@0
  3188
    case 'S':   // %{S}, %{lS}
sl@0
  3189
        if (spec.mod_l) {   // std::wstring
sl@0
  3190
            spec.param.ptr = PARAM (std::wstring*, ptr);
sl@0
  3191
sl@0
  3192
            const std::wstring* const pstr = (std::wstring*)spec.param.ptr;
sl@0
  3193
            const wchar_t* const wstr = pstr->data ();
sl@0
  3194
            const std::wstring::size_type size = pstr->size ();
sl@0
  3195
sl@0
  3196
            len = _rw_fmtwstr (spec, pbuf, pbufsize, wstr, size);
sl@0
  3197
        }
sl@0
  3198
        else {   // std::string
sl@0
  3199
            spec.param.ptr = PARAM (std::string*, ptr);
sl@0
  3200
sl@0
  3201
            const std::string* const pstr = (std::string*)spec.param.ptr;
sl@0
  3202
            const char* const str = pstr->data ();
sl@0
  3203
            const std::string::size_type size = pstr->size ();
sl@0
  3204
sl@0
  3205
            len = _rw_fmtstr (spec, pbuf, pbufsize, str, size);
sl@0
  3206
        }
sl@0
  3207
        break;
sl@0
  3208
sl@0
  3209
    default:
sl@0
  3210
        if (spec.strarg) {
sl@0
  3211
            // environment variable
sl@0
  3212
            const char* val = getenv (spec.strarg);
sl@0
  3213
sl@0
  3214
            if (!val)
sl@0
  3215
                val = "";
sl@0
  3216
sl@0
  3217
            len = int (strlen (val));
sl@0
  3218
sl@0
  3219
            if (0 == _rw_bufcat (pbuf, pbufsize, val, size_t (len)))
sl@0
  3220
                return -1;
sl@0
  3221
sl@0
  3222
            free (spec.strarg);
sl@0
  3223
        }
sl@0
  3224
        else {
sl@0
  3225
            assert (!"not implemented");
sl@0
  3226
        }
sl@0
  3227
    }
sl@0
  3228
sl@0
  3229
    return len;
sl@0
  3230
}
sl@0
  3231
sl@0
  3232
/********************************************************************/
sl@0
  3233
sl@0
  3234
/* extern */ int
sl@0
  3235
(*rw_vasnprintf_cb)(FmtSpec*, size_t, char**, size_t*, const char*, va_list*)
sl@0
  3236
    = libstd_vasnprintf;
sl@0
  3237
sl@0
  3238
/********************************************************************/
sl@0
  3239
sl@0
  3240
_TEST_EXPORT int
sl@0
  3241
rw_asnprintf (char **pbuf, size_t *pbufsize, const char *fmt, ...)
sl@0
  3242
{
sl@0
  3243
    assert (0 == pbuf || 0 == *pbuf || pbufsize);
sl@0
  3244
sl@0
  3245
    va_list va;
sl@0
  3246
    va_start (va, fmt);
sl@0
  3247
sl@0
  3248
    char* buf = 0;
sl@0
  3249
    size_t bufsize = 0;
sl@0
  3250
sl@0
  3251
    if (0 == pbuf) {
sl@0
  3252
        // if pbyf is 0 (i.e., this is a request for the size of the
sl@0
  3253
        // buffer necessary to format all the arguments), set pbuf to
sl@0
  3254
        // point to a local buf
sl@0
  3255
        pbuf = &buf;
sl@0
  3256
    }
sl@0
  3257
sl@0
  3258
    if (0 == pbufsize) {
sl@0
  3259
        // pbuf may be 0 regardless of the value of pbuf
sl@0
  3260
        pbufsize = &bufsize;
sl@0
  3261
    }
sl@0
  3262
sl@0
  3263
    const int nchars = rw_vasnprintf (pbuf, pbufsize, fmt, va);
sl@0
  3264
sl@0
  3265
    va_end (va);
sl@0
  3266
sl@0
  3267
    // verify that the length of the fomatted buffer is less than
sl@0
  3268
    // its size (this test is unreliable if there are any embedded
sl@0
  3269
    // NULs in the output)
sl@0
  3270
    assert (nchars < 0 || strlen (*pbuf) < *pbufsize);
sl@0
  3271
sl@0
  3272
    if (pbuf == &buf) {
sl@0
  3273
        // free the character buffer if pbuf was initially 0
sl@0
  3274
        free (pbuf);
sl@0
  3275
    }
sl@0
  3276
sl@0
  3277
    return nchars;
sl@0
  3278
}
sl@0
  3279
sl@0
  3280
/********************************************************************/
sl@0
  3281
sl@0
  3282
_TEST_EXPORT char*
sl@0
  3283
rw_snprintfa (char *buf, size_t bufsize, const char* fmt, ...)
sl@0
  3284
{
sl@0
  3285
    if (buf)
sl@0
  3286
        *buf = '\0';
sl@0
  3287
sl@0
  3288
    va_list va;
sl@0
  3289
    va_start (va, fmt);
sl@0
  3290
sl@0
  3291
    const int nchars = rw_vasnprintf (&buf, &bufsize, fmt, va);
sl@0
  3292
sl@0
  3293
    va_end (va);
sl@0
  3294
sl@0
  3295
    // verify that the length of the fomatted buffer is less than
sl@0
  3296
    // its size (this test is unreliable if there are any embedded
sl@0
  3297
    // NULs in the output)
sl@0
  3298
    assert (nchars < 0 || strlen (buf) < bufsize);
sl@0
  3299
sl@0
  3300
    _RWSTD_UNUSED (nchars);
sl@0
  3301
sl@0
  3302
    return buf;
sl@0
  3303
}
sl@0
  3304
sl@0
  3305
/********************************************************************/
sl@0
  3306
sl@0
  3307
_TEST_EXPORT char*
sl@0
  3308
rw_sprintfa (const char *fmt, ...)
sl@0
  3309
{
sl@0
  3310
    char* buf = 0;
sl@0
  3311
    size_t bufsize = 0;
sl@0
  3312
sl@0
  3313
    va_list va;
sl@0
  3314
    va_start (va, fmt);
sl@0
  3315
sl@0
  3316
    const int nchars = rw_vasnprintf (&buf, &bufsize, fmt, va);
sl@0
  3317
sl@0
  3318
    va_end (va);
sl@0
  3319
sl@0
  3320
    // verify that the length of the fomatted buffer is less than
sl@0
  3321
    // its size (this test is unreliable if there are any embedded
sl@0
  3322
    // NULs in the output)
sl@0
  3323
    assert (nchars < 0 || strlen (buf) < bufsize);
sl@0
  3324
sl@0
  3325
    _RWSTD_UNUSED (nchars);
sl@0
  3326
sl@0
  3327
    return buf;
sl@0
  3328
}
sl@0
  3329
sl@0
  3330
sl@0
  3331
/********************************************************************/
sl@0
  3332
sl@0
  3333
// avoid re-declaring these as exported here and instead rely on the
sl@0
  3334
// declaration in the header #included above in order to prevent the
sl@0
  3335
// bogus MSVC error:
sl@0
  3336
// error C2201: 'rw_stdout' : must have external linkage in order to
sl@0
  3337
// be exported/imported
sl@0
  3338
sl@0
  3339
/* _TEST_EXPORT */ rw_file* const
sl@0
  3340
rw_stdout = _RWSTD_REINTERPRET_CAST (rw_file*, stdout);
sl@0
  3341
sl@0
  3342
/* _TEST_EXPORT */ rw_file* const
sl@0
  3343
rw_stderr = _RWSTD_REINTERPRET_CAST (rw_file*, stderr);
sl@0
  3344
sl@0
  3345
/********************************************************************/
sl@0
  3346
sl@0
  3347
static int
sl@0
  3348
_rw_vfprintf (rw_file *file, const char *fmt, va_list va)
sl@0
  3349
{
sl@0
  3350
    assert (0 != file);
sl@0
  3351
sl@0
  3352
    char* buf = 0;
sl@0
  3353
    size_t bufsize = 0;
sl@0
  3354
sl@0
  3355
    const int nchars = rw_vasnprintf (&buf, &bufsize, fmt, va);
sl@0
  3356
sl@0
  3357
    // FIXME: implement this in terms of POSIX write()
sl@0
  3358
    //        for async-signal safety
sl@0
  3359
    FILE* const stdio_file = _RWSTD_REINTERPRET_CAST (FILE*, file);
sl@0
  3360
sl@0
  3361
    const int nwrote = 0 < nchars ?
sl@0
  3362
        fwrite (buf, 1, nchars, stdio_file) : nchars;
sl@0
  3363
sl@0
  3364
    // flush in case stderr isn't line-buffered (e.g., when
sl@0
  3365
    // it's determined not to refer to a terminal device,
sl@0
  3366
    // for example after it has been redirected to a file)
sl@0
  3367
    fflush (stdio_file);
sl@0
  3368
sl@0
  3369
#ifdef _MSC_VER
sl@0
  3370
sl@0
  3371
    // IsDebuggerPresent() depends on the macros _WIN32_WINNT and WINVER
sl@0
  3372
    // being appropriately #defined prior to the #inclusion of <windows.h>
sl@0
  3373
    if (IsDebuggerPresent ()) {
sl@0
  3374
sl@0
  3375
        // write string to the attached debugger (if any)
sl@0
  3376
        OutputDebugString (buf);
sl@0
  3377
    }
sl@0
  3378
sl@0
  3379
#endif   // _MSC_VER
sl@0
  3380
sl@0
  3381
    free (buf);
sl@0
  3382
sl@0
  3383
    return nwrote;
sl@0
  3384
}
sl@0
  3385
sl@0
  3386
/********************************************************************/
sl@0
  3387
sl@0
  3388
_TEST_EXPORT int
sl@0
  3389
rw_fprintf (rw_file *file, const char *fmt, ...)
sl@0
  3390
{
sl@0
  3391
    va_list va;
sl@0
  3392
    va_start (va, fmt);
sl@0
  3393
sl@0
  3394
    const int nchars = _rw_vfprintf (file, fmt, va);
sl@0
  3395
sl@0
  3396
    va_end (va);
sl@0
  3397
sl@0
  3398
    return nchars;
sl@0
  3399
}
sl@0
  3400
sl@0
  3401
/********************************************************************/
sl@0
  3402
sl@0
  3403
_TEST_EXPORT int
sl@0
  3404
rw_printf (const char *fmt, ...)
sl@0
  3405
{
sl@0
  3406
    va_list va;
sl@0
  3407
    va_start (va, fmt);
sl@0
  3408
sl@0
  3409
    const int nchars = _rw_vfprintf (rw_stdout, fmt, va);
sl@0
  3410
sl@0
  3411
    va_end (va);
sl@0
  3412
sl@0
  3413
    return nchars;
sl@0
  3414
}