1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/printf.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,3414 @@
1.4 +/************************************************************************
1.5 + *
1.6 + * printf.cpp - definitions of the rw_printf family of functions
1.7 + *
1.8 + * $Id: printf.cpp 351515 2005-12-01 23:19:44Z sebor $
1.9 + *
1.10 + ************************************************************************
1.11 + *
1.12 + * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
1.13 + * Software division. Licensed under the Apache License, Version 2.0 (the
1.14 + * "License"); you may not use this file except in compliance with the
1.15 + * License. You may obtain a copy of the License at
1.16 + * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
1.17 + * applicable law or agreed to in writing, software distributed under
1.18 + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
1.19 + * CONDITIONS OF ANY KIND, either express or implied. See the License
1.20 + * for the specific language governing permissions and limitations under
1.21 + * the License.
1.22 + *
1.23 + **************************************************************************/
1.24 +
1.25 +// expand _TEST_EXPORT macros
1.26 +#define _RWSTD_TEST_SRC
1.27 +#include <testdefs.h>
1.28 +#include <printf.h>
1.29 +
1.30 +#include <assert.h> // for assert
1.31 +#include <errno.h> // for errno, errno constants
1.32 +#include <float.h> // for floating point macros
1.33 +#include <locale.h>
1.34 +#ifndef __SYMBIAN32__
1.35 +#include <signal.h> // for signal constant
1.36 +#endif
1.37 +#include <stdarg.h> // for va_list, va_start, ...
1.38 +#include <stddef.h>
1.39 +#include <stdio.h>
1.40 +#include <stdlib.h>
1.41 +#include <string.h>
1.42 +#include <wchar.h>
1.43 +
1.44 +#if (defined (_WIN32) || defined (_WIN64)) && !defined(__SYMBIAN32__)
1.45 + // define macros to enable Win98 + WinNT support in <windows.h>
1.46 +# define _WIN32_WINNT 0x0410
1.47 +# define WINVER 0x400
1.48 +# include <windows.h> // for IsDebuggerPresent()
1.49 +#else
1.50 +# include <dlfcn.h>
1.51 +#endif // _WIN{32,64}
1.52 +
1.53 +#include <ios>
1.54 +#include <iostream>
1.55 +#include <locale>
1.56 +//#include <string>
1.57 +#include <string.h>
1.58 +
1.59 +#ifdef __ARMCC__
1.60 +#pragma diag_suppress 61
1.61 +#pragma diag_suppress 63
1.62 +#endif
1.63 +
1.64 +#define _RWSTD_NO_EXT_BIN_IO
1.65 +#define _RWSTD_NO_EXT_REENTRANT_IO
1.66 +
1.67 +#ifndef __SYMBIAN32__
1.68 +
1.69 +_RWSTD_NAMESPACE (__rw) {
1.70 +
1.71 +_RWSTD_EXPORT _RWSTD_SSIZE_T
1.72 + __rw_memattr (const void*, size_t, int);
1.73 +
1.74 +}
1.75 +
1.76 +#endif
1.77 +
1.78 +/********************************************************************/
1.79 +
1.80 +static const union {
1.81 + int ival;
1.82 + unsigned char bytes [sizeof (int)];
1.83 +} _rw_one = { 1 };
1.84 +
1.85 +static const int
1.86 +_rw_big_endian = '\0' == _rw_one.bytes [0];
1.87 +
1.88 +
1.89 +/********************************************************************/
1.90 +
1.91 +struct FmtSpec;
1.92 +
1.93 +static int
1.94 +_rw_fmtlong (const FmtSpec&, char**, size_t*, long);
1.95 +
1.96 +#ifdef _RWSTD_LONG_LONG
1.97 +
1.98 +static int
1.99 +_rw_fmtllong (const FmtSpec&, char**, size_t*, _RWSTD_LONG_LONG);
1.100 +
1.101 +#endif // _RWSTD_LONG_LONG
1.102 +
1.103 +static int
1.104 +_rw_fmtinteger (FmtSpec*, size_t, char**, size_t*, va_list*);
1.105 +
1.106 +static int
1.107 +_rw_fmtfloating (const FmtSpec&, char**, size_t*, const void*);
1.108 +
1.109 +_RWSTD_INTERNAL int
1.110 +_rw_fmtptr (const FmtSpec&, char**, size_t*, const void*);
1.111 +
1.112 +typedef void (*funptr_t)();
1.113 +
1.114 +static int
1.115 +_rw_fmtfunptr (const FmtSpec&, char**, size_t*, funptr_t);
1.116 +
1.117 +struct DummyStruct;
1.118 +typedef void (DummyStruct::*memptr_t)() const;
1.119 +
1.120 +static int
1.121 +_rw_fmtmemptr (const FmtSpec&, char**, size_t*, memptr_t);
1.122 +
1.123 +static int
1.124 +_rw_fmtstr (const FmtSpec&, char**, size_t*, const char*, size_t);
1.125 +
1.126 +static int
1.127 +_rw_fmtchr (const FmtSpec&, char**, size_t*, int);
1.128 +
1.129 +static int
1.130 +_rw_fmtwchr (const FmtSpec&, char**, size_t*, wint_t);
1.131 +
1.132 +static int
1.133 +_rw_fmtwstr (const FmtSpec&, char**, size_t*, const wchar_t*, size_t);
1.134 +
1.135 +static int
1.136 +_rw_fmterrno (const FmtSpec&, char**, size_t*, int);
1.137 +
1.138 +static int
1.139 +_rw_fmtopenmode (const FmtSpec&, char**, size_t*, int);
1.140 +
1.141 +static int
1.142 +_rw_fmtevent (const FmtSpec&, char**, size_t*, int);
1.143 +
1.144 +static int
1.145 +_rw_fmtmonpat (const FmtSpec&, char**, size_t*, const char [4]);
1.146 +
1.147 +static int
1.148 +_rw_fmtsignal (const FmtSpec&, char**, size_t*, int);
1.149 +
1.150 +/********************************************************************/
1.151 +
1.152 +struct FmtSpec
1.153 +{
1.154 + // optional flags
1.155 + unsigned fl_minus : 1;
1.156 + unsigned fl_plus : 1;
1.157 + unsigned fl_pound : 1;
1.158 + unsigned fl_space : 1;
1.159 + unsigned fl_zero : 1;
1.160 +
1.161 + // optional modifiers
1.162 + unsigned mod_A : 1; // extension (Arrays)
1.163 + unsigned mod_h : 1; // short modifier
1.164 + unsigned mod_hh : 1; // char modifier
1.165 + unsigned mod_l : 1; // long modifier
1.166 + unsigned mod_ll : 1; // long long modifier
1.167 + unsigned mod_j : 1; // intmax_t modifier
1.168 + unsigned mod_z : 1; // size_t modifier
1.169 + unsigned mod_t : 1; // ptrdiff_t modifier
1.170 + unsigned mod_L : 1; // long double modifier
1.171 + unsigned mod_I : 1; // extension
1.172 +
1.173 + unsigned cond : 1; // have an if/else clause
1.174 + unsigned cond_true : 1; // if/else clause is active (true)
1.175 + unsigned cond_begin : 1; // beginning of an if/else clause
1.176 + unsigned cond_end : 1; // end of an if/else clause
1.177 +
1.178 + // note that the signedness of a bitfield is implementation-defined
1.179 + // unless explicitly declared signed or unsigned
1.180 +
1.181 + // extension: 8, 16, 32, and 64 bit integer width modifier
1.182 + signed int iwidth : 4;
1.183 +
1.184 + // extension: optional numerical base 2 - 36
1.185 + signed int base : 7;
1.186 +
1.187 + // extension: optional parameter number
1.188 + long paramno;
1.189 +
1.190 + // optional width and precision
1.191 + int width;
1.192 + int prec;
1.193 +
1.194 + // extension: string argument
1.195 + char *strarg;
1.196 +
1.197 + // required conversion specifier
1.198 + int cvtspec;
1.199 +
1.200 + // extension: fill character
1.201 + int fill;
1.202 +
1.203 + union {
1.204 +
1.205 +#ifndef _RWSTD_NO_LONG_DOUBLE
1.206 +
1.207 + long double ldbl;
1.208 +
1.209 +#endif // _RWSTD_NO_LONG_DOUBLE
1.210 +
1.211 +#ifdef _RWSTD_LONG_LONG
1.212 +
1.213 + _RWSTD_LONG_LONG llong;
1.214 +
1.215 +#endif // _RWSTD_LONG_LONG
1.216 +
1.217 + void* ptr;
1.218 +
1.219 + int i;
1.220 + long lng;
1.221 +
1.222 + _RWSTD_INT32_T i32;
1.223 +
1.224 +#ifdef _RWSTD_INT64_T
1.225 + _RWSTD_INT64_T i64;
1.226 +#endif // _RWSTD_INT64_T
1.227 +
1.228 + ptrdiff_t diff;
1.229 + size_t size;
1.230 + wint_t wi;
1.231 +
1.232 + double dbl;
1.233 + memptr_t memptr;
1.234 + funptr_t funptr;
1.235 + } param;
1.236 +};
1.237 +
1.238 +/********************************************************************/
1.239 +
1.240 +/*
1.241 +
1.242 + C99 format specifier:
1.243 +
1.244 + % flags width [ . prec ] mod cvtspec
1.245 +
1.246 +
1.247 + GNU glibc format specifier:
1.248 +
1.249 + % [ paramno $] flags width [ . prec ] mod cvtspec
1.250 + or
1.251 + % [ paramno $] flags width . * [ paramno $] mod cvtspec
1.252 +
1.253 +
1.254 + Extended format specifier:
1.255 +
1.256 + % { [ paramno $] [ flags ] [ width [. prec ]] mod cvtspec }
1.257 + or
1.258 + % { [ paramno $] [ flags ] [@ base [. width [. prec ]]] mod cvtspec }
1.259 + or
1.260 + % { $ envvar }
1.261 +
1.262 +
1.263 +*/
1.264 +
1.265 +static int
1.266 +_rw_fmtspec (FmtSpec *pspec, bool ext, const char *fmt, va_list *pva)
1.267 +{
1.268 + assert (0 != pspec);
1.269 + assert (0 != fmt);
1.270 + assert (0 != pva);
1.271 +
1.272 + memset (pspec, 0, sizeof *pspec);
1.273 +
1.274 + pspec->iwidth = -1; // integer width not specified
1.275 + pspec->width = -1; // width not specified
1.276 + pspec->prec = -1; // precision not specified
1.277 + pspec->base = -1; // base not specified
1.278 + pspec->paramno = -1; // paramno not specified
1.279 +
1.280 + const char* const fmtbeg = fmt;
1.281 +
1.282 + if (ext) {
1.283 + if ('$' == *fmt) {
1.284 +
1.285 + ++fmt;
1.286 +
1.287 + const char *str;
1.288 + if ('*' == *fmt) {
1.289 + str = va_arg (*pva, char*);
1.290 + if (!str)
1.291 + str = "";
1.292 + ++fmt;
1.293 + }
1.294 + else {
1.295 + str = fmt;
1.296 + fmt += strlen (fmt);
1.297 + }
1.298 +
1.299 + char *tmp = (char*)malloc (strlen (str));
1.300 + pspec->strarg = strcpy (tmp, str);
1.301 +
1.302 + return int (fmt - fmtbeg);
1.303 + }
1.304 + }
1.305 +
1.306 + // extension: extract the parameter number (if followed by '$')
1.307 + if ('1' <= *fmt && *fmt <= '9') {
1.308 + char *end;
1.309 + const long tmp = strtol (fmt, &end, 10);
1.310 +
1.311 + fmt = end;
1.312 +
1.313 + if ('$' == *fmt) {
1.314 + pspec->paramno = tmp;
1.315 + ++fmt;
1.316 + }
1.317 + else {
1.318 + // when not followed by '$' interpret the number
1.319 + // as the width (i.e., that follows the empty set
1.320 + // of flags)
1.321 + pspec->width = int (tmp);
1.322 + }
1.323 + }
1.324 +
1.325 + if (-1 == pspec->width) {
1.326 + // extract any number of optional flags
1.327 + for ( ; ; ++fmt) {
1.328 + switch (*fmt) {
1.329 + case '-': pspec->fl_minus = true; continue;
1.330 + case '+': pspec->fl_plus = true; continue;
1.331 + case '#': pspec->fl_pound = true; continue;
1.332 + case ' ': pspec->fl_space = true; continue;
1.333 + case '0': pspec->fl_zero = true; continue;
1.334 + }
1.335 + break;
1.336 + }
1.337 + }
1.338 +
1.339 + if (ext && '@' == *fmt) {
1.340 +
1.341 + ++fmt;
1.342 +
1.343 + // extract the numerical base
1.344 + if ('0' <= fmt [1] && fmt [1] <= '9') {
1.345 + char *end;
1.346 + pspec->base = int (strtol (fmt, &end, 10));
1.347 + fmt = end;
1.348 + }
1.349 + else if ('*' == *fmt) {
1.350 + pspec->base = va_arg (*pva, int);
1.351 + ++fmt;
1.352 + }
1.353 +
1.354 + if ('.' == *fmt)
1.355 + ++fmt;
1.356 + }
1.357 +
1.358 + if (-1 == pspec->width) {
1.359 + // extract the optional width
1.360 + if ('0' <= *fmt && *fmt <= '9') {
1.361 + char *end;
1.362 + pspec->width = int (strtol (fmt, &end, 10));
1.363 + fmt = end;
1.364 + }
1.365 + else if ('*' == *fmt) {
1.366 + pspec->width = va_arg (*pva, int);
1.367 +
1.368 + if (pspec->width < 0) {
1.369 + // 7.19.6.1, p5 of ISO/IEC 9899:1999:
1.370 + // A negative field width argument is taken
1.371 + // as a - flag followed by a positive field width.
1.372 + pspec->width = -pspec->width;
1.373 + pspec->fl_minus = true;
1.374 + }
1.375 +
1.376 + ++fmt;
1.377 + }
1.378 + }
1.379 +
1.380 + // extract the optional precision
1.381 + if ('.' == *fmt) {
1.382 +
1.383 + ++fmt;
1.384 +
1.385 + if ('0' <= *fmt && *fmt <= '9') {
1.386 + char *end;
1.387 + pspec->prec = int (strtol (fmt, &end, 10));
1.388 + fmt = end;
1.389 + }
1.390 + else if ('*' == *fmt) {
1.391 + pspec->prec = va_arg (*pva, int);
1.392 + ++fmt;
1.393 + }
1.394 + }
1.395 +
1.396 + // extract an optional modifier
1.397 + switch (*fmt) {
1.398 + case 'A':
1.399 + if (ext) {
1.400 + ++fmt;
1.401 + pspec->mod_A = true;
1.402 + break;
1.403 + }
1.404 + // fall thru
1.405 +
1.406 + case 'h':
1.407 + if ('h' == fmt [1]) {
1.408 + ++fmt;
1.409 + pspec->mod_hh = true;
1.410 + }
1.411 + else
1.412 + pspec->mod_h = true;
1.413 + ++fmt;
1.414 + break;
1.415 +
1.416 + case 'l':
1.417 + if ('l' == fmt [1]) {
1.418 + ++fmt;
1.419 + pspec->mod_ll = true;
1.420 + }
1.421 + else
1.422 + pspec->mod_l = true;
1.423 + ++fmt;
1.424 + break;
1.425 +
1.426 + case 'j': pspec->mod_j = true; ++fmt; break;
1.427 + case 'z': pspec->mod_z = true; ++fmt; break;
1.428 + case 't': pspec->mod_t = true; ++fmt; break;
1.429 + case 'L': pspec->mod_L = true; ++fmt; break;
1.430 +
1.431 + case 'I':
1.432 + if (ext) {
1.433 +
1.434 + ++fmt;
1.435 +
1.436 + if ('8' == *fmt) {
1.437 + pspec->iwidth = 1;
1.438 + ++fmt;
1.439 + }
1.440 + else if ('1' == fmt [0] && '6' == fmt [1]) {
1.441 + pspec->iwidth = 2;
1.442 + fmt += 2;
1.443 + }
1.444 + else if ('3' == fmt [0] && '2' == fmt [1]) {
1.445 + pspec->iwidth = 3;
1.446 + fmt += 2;
1.447 + }
1.448 + else if ('6' == fmt [0] && '4' == fmt [1]) {
1.449 + pspec->iwidth = 4;
1.450 + fmt += 2;
1.451 + }
1.452 + else {
1.453 + pspec->mod_I = true;
1.454 + }
1.455 + break;
1.456 + }
1.457 + }
1.458 +
1.459 + pspec->cvtspec = *fmt;
1.460 +
1.461 + if (pspec->cvtspec)
1.462 + ++fmt;
1.463 +
1.464 + return int (fmt - fmtbeg);
1.465 +}
1.466 +
1.467 +/********************************************************************/
1.468 +
1.469 +_RWSTD_INTERNAL char*
1.470 +_rw_bufcat (char **pbuf, size_t *pbufsize, const char *str, size_t len)
1.471 +{
1.472 + assert (0 != pbuf);
1.473 + assert (0 != pbufsize);
1.474 +
1.475 + size_t buflen = *pbuf ? strlen (*pbuf) : 0;
1.476 + const size_t bufree = *pbuf ? *pbufsize - buflen : 0;
1.477 +
1.478 + if (bufree <= len || !*pbuf) {
1.479 +
1.480 + // for guard block
1.481 + static const char deadbeef[] = "\xde\xad\xbe\xef";
1.482 +
1.483 + size_t newbufsize = *pbufsize * 2 + 4;
1.484 +
1.485 + if (newbufsize <= buflen + len + 4)
1.486 + newbufsize = 2 * (buflen + len + 1) + 4;
1.487 +
1.488 + char* const newbuf = (char*)malloc (newbufsize);
1.489 +
1.490 + // return 0 on failure to allocate, let caller deal with it
1.491 + if (0 == newbuf)
1.492 + return 0;
1.493 +
1.494 + memcpy (newbuf, *pbuf, buflen);
1.495 +
1.496 + // append a guard block to the end of the buffer
1.497 + memcpy (newbuf + newbufsize - 4, deadbeef, 4);
1.498 +
1.499 + if (*pbuf) {
1.500 + // verify that we didn't write past the end of the buffer
1.501 + assert (0 == memcmp (*pbuf + *pbufsize, deadbeef, 4));
1.502 + free (*pbuf);
1.503 + }
1.504 +
1.505 + *pbuf = newbuf;
1.506 + *pbufsize = newbufsize - 4;
1.507 +
1.508 + (*pbuf)[buflen] = '\0';
1.509 + }
1.510 +
1.511 + if (0 != str) {
1.512 + memcpy (*pbuf + buflen, str, len);
1.513 + buflen += len;
1.514 + (*pbuf)[buflen] = '\0';
1.515 + }
1.516 +
1.517 + return *pbuf + buflen;
1.518 +}
1.519 +
1.520 +/********************************************************************/
1.521 +
1.522 +// rw_asnprintf_cb is called to format a character string according
1.523 +// to the single format specifier `fmt' to the end of the provided
1.524 +// buffer `*pbuf'; the function can reallocate the buffer
1.525 +// returns the number of characters appended to the buffer
1.526 +extern int
1.527 +(*rw_vasnprintf_cb)(FmtSpec*, size_t, char**, size_t*, const char*, va_list*);
1.528 +
1.529 +/********************************************************************/
1.530 +
1.531 +static int
1.532 +_rw_vasnprintf_c99 (FmtSpec *pspec, size_t paramno,
1.533 + char **pbuf, size_t *pbufsize, va_list *pva)
1.534 +{
1.535 + _RWSTD_UNUSED (paramno);
1.536 +
1.537 + _RWSTD_ASSERT (0 != pspec);
1.538 +
1.539 + int len = -1;
1.540 +
1.541 + FmtSpec &spec = pspec [paramno];
1.542 +
1.543 +#define PARAM(T, name) \
1.544 + (0 < spec.paramno ? pspec [spec.paramno - 1].param.name : va_arg (*pva, T))
1.545 +
1.546 + switch (spec.cvtspec) {
1.547 +
1.548 + case 'd':
1.549 + case 'i':
1.550 + case 'o':
1.551 + case 'x':
1.552 + case 'X':
1.553 + case 'u':
1.554 + len = _rw_fmtinteger (pspec, paramno, pbuf, pbufsize, pva);
1.555 + break;
1.556 +
1.557 + case 'e':
1.558 + case 'E':
1.559 + case 'f':
1.560 + case 'F':
1.561 + case 'g':
1.562 + case 'G':
1.563 + if (spec.mod_L) {
1.564 + spec.param.ldbl = PARAM (long double, ldbl);
1.565 + len = _rw_fmtfloating (spec, pbuf, pbufsize, &spec.param.ldbl);
1.566 + }
1.567 + else {
1.568 + spec.param.dbl = PARAM (double, dbl);
1.569 + len = _rw_fmtfloating (spec, pbuf, pbufsize, &spec.param.dbl);
1.570 + }
1.571 + break;
1.572 +
1.573 + case 'a':
1.574 + assert (!"%a not implemented");
1.575 + break;
1.576 +
1.577 + case 'A':
1.578 + assert (!"%A not implemented");
1.579 + break;
1.580 +
1.581 + case 'c':
1.582 + // If no l length modifier is present, the int argument is converted
1.583 + // to an unsigned char, and the resulting character is written. If
1.584 + // an l length modifier is present, the wint_t argument is converted
1.585 + // as if by an ls conversion specification with no precision and an
1.586 + // argument that points to the initial element of a two-element array
1.587 + // of wchar_t, the first element containing the wint_t argument to
1.588 + // the lc conversion specification and the second a null wide
1.589 + // character.
1.590 + if (spec.mod_l) {
1.591 + spec.param.wi = PARAM (wint_t, wi);
1.592 + len = _rw_fmtwchr (spec, pbuf, pbufsize, spec.param.wi);
1.593 + }
1.594 + else {
1.595 + spec.param.i = PARAM (int, i);
1.596 + len = _rw_fmtchr (spec, pbuf, pbufsize, spec.param.i);
1.597 + }
1.598 + break;
1.599 +
1.600 + case 's':
1.601 + if (spec.mod_l) {
1.602 + spec.param.ptr = PARAM (wchar_t*, ptr);
1.603 + const wchar_t* const str = (wchar_t*)spec.param.ptr;
1.604 + len = _rw_fmtwstr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX);
1.605 + }
1.606 + else {
1.607 + spec.param.ptr = PARAM (char*, ptr);
1.608 + const char* const str = (char*)spec.param.ptr;
1.609 + len = _rw_fmtstr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX);
1.610 + }
1.611 + break;
1.612 +
1.613 + case 'p': {
1.614 + // The argument shall be a pointer to void. The value of the pointer
1.615 + // is converted to a sequence of printing characters, in an
1.616 + // implementation-defined manner.
1.617 + spec.param.ptr = PARAM (char*, ptr);
1.618 + len = _rw_fmtptr (spec, pbuf, pbufsize, spec.param.ptr);
1.619 + break;
1.620 + }
1.621 +
1.622 + case 'm': { // %m (popular extension)
1.623 + spec.param.i = errno;
1.624 + len = _rw_fmterrno (spec, pbuf, pbufsize, spec.param.i);
1.625 + break;
1.626 + }
1.627 +
1.628 + case 'n': {
1.629 + // The argument shall be a pointer to signed integer into which
1.630 + // is written the number of characters written to the output
1.631 + // stream so far by this call to fprintf. No argument is converted,
1.632 + // but one is consumed. If the conversion specification includes
1.633 + // any flags, a field width, or a precision, the behavior is
1.634 + // undefined.
1.635 +
1.636 + assert (0 != pbuf);
1.637 + assert (0 != *pbuf);
1.638 +
1.639 + len = int (strlen (*pbuf));
1.640 +
1.641 + spec.param.ptr = PARAM (void*, ptr);
1.642 +
1.643 + if (spec.mod_hh) {
1.644 + unsigned char* const ptr = (unsigned char*)spec.param.ptr;
1.645 +
1.646 + assert (0 != ptr);
1.647 +
1.648 + *ptr = len;
1.649 + }
1.650 + else if (spec.mod_h) {
1.651 + short* const ptr = (short*)spec.param.ptr;
1.652 +
1.653 + assert (0 != ptr);
1.654 +
1.655 + *ptr = len;
1.656 + }
1.657 + else if (spec.mod_L) {
1.658 +#ifdef _RWSTD_LONG_LONG
1.659 + _RWSTD_LONG_LONG* const ptr = (_RWSTD_LONG_LONG*)spec.param.ptr;
1.660 +
1.661 + assert (0 != ptr);
1.662 +
1.663 + *ptr = len;
1.664 +#else // if !defined (_RWSTD_LONG_LONG)
1.665 + assert (!"%Ln not implemented");
1.666 +#endif // _RWSTD_LONG_LONG
1.667 + }
1.668 + else if (spec.mod_l) {
1.669 + long* const ptr = (long*)spec.param.ptr;
1.670 +
1.671 + assert (0 != ptr);
1.672 +
1.673 + *ptr = len;
1.674 + }
1.675 + else if (spec.mod_t) {
1.676 + ptrdiff_t* const ptr = (ptrdiff_t*)spec.param.ptr;
1.677 +
1.678 + assert (0 != ptr);
1.679 +
1.680 + *ptr = ptrdiff_t (unsigned (len));
1.681 + }
1.682 + else {
1.683 + int* const ptr = (int*)spec.param.ptr;
1.684 +
1.685 + assert (0 != ptr);
1.686 +
1.687 + *ptr = len;
1.688 + }
1.689 + break;
1.690 + }
1.691 +
1.692 + case '%':
1.693 + break;
1.694 + }
1.695 +
1.696 + return len;
1.697 +}
1.698 +
1.699 +/********************************************************************/
1.700 +
1.701 +_TEST_EXPORT int
1.702 +rw_vasnprintf (char **pbuf, size_t *pbufsize, const char *fmt, va_list varg)
1.703 +{
1.704 + va_list *pva;
1.705 +
1.706 +#ifdef va_copy
1.707 + // create a copy of va whose address can be passed to a function
1.708 + // taking a va_list* so that it can modify the original; note that
1.709 + // passing &va is not portable since when declared as a function
1.710 + // argument, va_list that is an array type decays into a pointer
1.711 + // and the address of the pointer will not match va_list* (as is
1.712 + // the case on EM64T)
1.713 + va_list vacpy;
1.714 + va_copy (vacpy, varg);
1.715 + pva = &vacpy;
1.716 +
1.717 +#else // if !defined (va_copy)
1.718 +
1.719 +# if 2 < __GNUG__
1.720 +
1.721 + // use the gcc 3.x builtin when the va_copy macro is not defined
1.722 + // (e.g., with gcc -ansi or Intel C++ icc -ansi or -strict_ansi)
1.723 + va_list vacpy;
1.724 + __builtin_va_copy (vacpy, varg);
1.725 + pva = &vacpy;
1.726 +
1.727 +# else // if !defined (__GNUG__)
1.728 +
1.729 + // use varg (in)directly and assume it's safe (e.g., HP aCC on PA)
1.730 + pva = &varg;
1.731 +
1.732 +# endif // 2 < __GNUG__
1.733 +
1.734 +#endif // va_copy
1.735 +
1.736 +// do not use varg of vacpy below this point -- use *pva instead
1.737 +#define varg DONT_TOUCH_ME
1.738 +#define vacpy DONT_TOUCH_ME
1.739 +
1.740 + assert (0 != pbuf);
1.741 +
1.742 + // save the initial value of `pbuf'
1.743 + char* const pbuf_save = *pbuf;
1.744 +
1.745 + if (*pbuf)
1.746 + **pbuf = '\0';
1.747 +
1.748 + // local buffer for a small number of conversion specifiers
1.749 + // will grow dynamically if their number exceeds its capacity
1.750 + FmtSpec specbuf [32];
1.751 + FmtSpec *pspec = specbuf;
1.752 +
1.753 + // local buffer for backtrack offsets implementing conditionals
1.754 + int backtrack [32];
1.755 + int nextoff = 0;
1.756 +
1.757 + size_t default_bufsize = 1024;
1.758 +
1.759 + if (0 == pbufsize)
1.760 + pbufsize = &default_bufsize;
1.761 +
1.762 + char fmtspec [64];
1.763 +
1.764 + char *next = *pbuf;
1.765 +
1.766 + size_t spec_bufsize = sizeof specbuf / sizeof *specbuf;
1.767 + size_t paramno = 0;
1.768 +
1.769 + for (const char *fc = fmt; *fc; ) {
1.770 +
1.771 + const char* const pcnt = strchr (fc, '%');
1.772 +
1.773 + size_t nchars = pcnt ? pcnt - fmt : strlen (fc);
1.774 +
1.775 + next = _rw_bufcat (pbuf, pbufsize, fmt, nchars);
1.776 + if (0 == next)
1.777 + goto fail;
1.778 +
1.779 + assert (0 != *pbuf);
1.780 + assert (0 != *pbufsize);
1.781 +
1.782 + if (0 == pcnt)
1.783 + break;
1.784 +
1.785 + fc = pcnt + 1;
1.786 +
1.787 + if ('%' == *fc) {
1.788 + // handle "%%"
1.789 + next = _rw_bufcat (pbuf, pbufsize, "%", 1);
1.790 + if (0 == next)
1.791 + goto fail;
1.792 +
1.793 + fmt = ++fc;
1.794 + continue;
1.795 + }
1.796 +
1.797 + if (spec_bufsize == paramno) {
1.798 + // grow the buffer of conversion specifiers
1.799 + FmtSpec *tmp = (FmtSpec*)malloc (spec_bufsize * 2);
1.800 + if (tmp) {
1.801 + memcpy (tmp, pspec, spec_bufsize);
1.802 + if (pspec != specbuf)
1.803 + free (pspec);
1.804 + pspec = tmp;
1.805 + }
1.806 + else
1.807 + goto fail;
1.808 + }
1.809 +
1.810 + if ('{' == *fc) {
1.811 + const char* const endbrace = strchr (++fc, '}');
1.812 +
1.813 + assert (0 != endbrace);
1.814 +
1.815 + const size_t fmtlen = endbrace - fc;
1.816 +
1.817 + memcpy (fmtspec, fc, fmtlen);
1.818 + fmtspec [fmtlen] = '\0';
1.819 +
1.820 + // compute the length of the buffer so far
1.821 + const size_t buflen = next - *pbuf;
1.822 +
1.823 + assert (0 != rw_vasnprintf_cb);
1.824 +
1.825 + // initiaze the current format specification, setting
1.826 + // all unused bits to 0
1.827 + const int speclen =
1.828 + _rw_fmtspec (pspec + paramno, true, fc, pva);
1.829 +
1.830 + _RWSTD_UNUSED (speclen);
1.831 +
1.832 + // copy the current backtrack offset if one exists
1.833 + // and set the condition and condition true bits
1.834 + if (nextoff) {
1.835 +
1.836 + // set the condition valid bit
1.837 + pspec [paramno].cond = 1;
1.838 +
1.839 + if (backtrack [nextoff - 1] < 0) {
1.840 + // negative offset indicates an active clause
1.841 + pspec [paramno].cond_true = 1;
1.842 + }
1.843 + else {
1.844 + // non-negative offset indicates an inactive clause
1.845 + // no-op
1.846 + }
1.847 + }
1.848 +
1.849 + // append formatted string to the end of the buffer
1.850 + // reallocating it if necessary; callee may change
1.851 + // the specification as necessary (e.g., based on
1.852 + // the if/else clause)
1.853 +
1.854 + int len =
1.855 + rw_vasnprintf_cb (pspec, paramno, pbuf, pbufsize,
1.856 + fmtspec, pva);
1.857 +
1.858 + // the callback returns a negative value on error
1.859 + if (len < 0)
1.860 + goto fail;
1.861 +
1.862 + assert (size_t (len) < *pbufsize);
1.863 + assert (strlen (*pbuf) < *pbufsize);
1.864 +
1.865 + const size_t offinx = nextoff - 1;
1.866 +
1.867 + if (pspec [paramno].cond_end && pspec [paramno].cond_begin) {
1.868 + // change from an if to an else clause
1.869 +
1.870 + assert (0 < nextoff);
1.871 + assert (0 == len);
1.872 +
1.873 + if (pspec [paramno].cond_true) {
1.874 + // change from an inactive if to an active else
1.875 + // (same as the end of an inactive clause)
1.876 +
1.877 + assert (0 <= backtrack [offinx]);
1.878 +
1.879 + // set the length so as to backtrack to the position
1.880 + // saved on the top of the backtrack stack
1.881 + len = -int (buflen) + backtrack [offinx];
1.882 +
1.883 + // invert the offset to indicate an active clause
1.884 + backtrack [offinx] = ~backtrack [offinx];
1.885 + }
1.886 + else {
1.887 + // change from an active if to an inactive else
1.888 + assert (backtrack [offinx] < 0);
1.889 +
1.890 + // save the current length of the buffer
1.891 + // as the new backtrack offset
1.892 + backtrack [offinx] = int (buflen);
1.893 + }
1.894 + }
1.895 + else if (pspec [paramno].cond_begin) {
1.896 + // start of a new if clause
1.897 +
1.898 + // push it on the stack of backtracking offsets using
1.899 + // negative values to indicate active clauses and
1.900 + // non-negative values inactive ones
1.901 + if (pspec [paramno].cond_true)
1.902 + backtrack [nextoff++] = ~int (buflen);
1.903 + else
1.904 + backtrack [nextoff++] = int (buflen);
1.905 + }
1.906 + else if (pspec [paramno].cond_end) {
1.907 + // the end of an if/else clause
1.908 +
1.909 + if (!pspec [paramno].cond_true) {
1.910 + // the end of an inactive clause
1.911 +
1.912 + assert (backtrack [offinx] <= int (buflen));
1.913 +
1.914 + // set the length so as to backtrack to the position
1.915 + // saved on the top of the backtrack stack
1.916 + len = -int (buflen) + backtrack [offinx];
1.917 + }
1.918 +
1.919 + // pop it off the top of the stack
1.920 + --nextoff;
1.921 + }
1.922 +
1.923 + assert (len + buflen < *pbufsize);
1.924 +
1.925 + // adjust the next pointer to point to the terminating
1.926 + // NUL in the (possibly reallocated) buffer
1.927 + next = *pbuf + buflen + len;
1.928 + *next = '\0';
1.929 + fc = endbrace + 1;
1.930 + }
1.931 + else {
1.932 + const int speclen =
1.933 + _rw_fmtspec (pspec + paramno, false, fc, pva);
1.934 +
1.935 + if (speclen) {
1.936 +
1.937 + const int len =
1.938 + _rw_vasnprintf_c99 (pspec, paramno, pbuf, pbufsize, pva);
1.939 +
1.940 + if (-1 == len)
1.941 + goto fail;
1.942 +
1.943 + // discard positional specifiers
1.944 + if (-1 == pspec [paramno].paramno)
1.945 + ++paramno;
1.946 +
1.947 + next = _rw_bufcat (pbuf, pbufsize, 0, size_t (len));
1.948 + if (0 == next)
1.949 + goto fail;
1.950 +
1.951 + next += len;
1.952 + fc += speclen;
1.953 + }
1.954 + else {
1.955 + next = _rw_bufcat (pbuf, pbufsize, "%", 1);
1.956 + if (0 == next)
1.957 + goto fail;
1.958 + }
1.959 + }
1.960 +
1.961 + fmt = fc;
1.962 + }
1.963 +
1.964 + // deallocate if dynamically allocated
1.965 + if (pspec != specbuf)
1.966 + free (pspec);
1.967 +
1.968 + return int (next - *pbuf);
1.969 +
1.970 +fail: // function failed
1.971 +
1.972 + fprintf (stderr, "%s:%d: rw_vasnprintf(%p, %p, \"%s\", va_list) "
1.973 + "error: errno = %d: %s\n",
1.974 + __FILE__, __LINE__, (void*)pbuf, (void*)pbufsize, fmt,
1.975 + errno, strerror (errno));
1.976 +
1.977 + if (pspec != specbuf)
1.978 + free (pspec);
1.979 +
1.980 + if (*pbuf != pbuf_save) {
1.981 + // free any allocated memory
1.982 + free (*pbuf);
1.983 + *pbuf = 0;
1.984 + }
1.985 +
1.986 + return -1;
1.987 +
1.988 +#undef varg
1.989 +#undef vacpy
1.990 +
1.991 +}
1.992 +
1.993 +/********************************************************************/
1.994 +
1.995 +static const char _rw_digits[] = {
1.996 + "0123456789abcdefghijklmnopqrstuvwxyz"
1.997 + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1.998 +};
1.999 +
1.1000 +static int
1.1001 +_rw_fmtlong (const FmtSpec &spec, char **pbuf, size_t *pbufsize, long val)
1.1002 +{
1.1003 + char buffer [130]; // big enough for a 128-bit long in base 2
1.1004 + char *end = buffer;
1.1005 +
1.1006 + long upoff = 0;
1.1007 + const char *pfx = 0;
1.1008 +
1.1009 + if ('X' == spec.cvtspec)
1.1010 + upoff = 36;
1.1011 +
1.1012 + if (spec.fl_pound) {
1.1013 + if (16 == spec.base)
1.1014 + pfx = upoff ? "0X" : "0x";
1.1015 + else if (8 == spec.base && val)
1.1016 + pfx = "0";
1.1017 + }
1.1018 +
1.1019 + const int base = 1 < spec.base && spec.base < 37 ? spec.base : 10;
1.1020 +
1.1021 + typedef unsigned long ULong;
1.1022 +
1.1023 + ULong uval;
1.1024 +
1.1025 + bool neg;
1.1026 +
1.1027 + if (val < 0) {
1.1028 + neg = 'd' == spec.cvtspec || 'i' == spec.cvtspec;
1.1029 + uval = ULong (neg ? -val : val);
1.1030 + }
1.1031 + else {
1.1032 + neg = false;
1.1033 + uval = ULong (val);
1.1034 + }
1.1035 +
1.1036 + do {
1.1037 + *end++ = _rw_digits [upoff + uval % base];
1.1038 + } while (uval /= base);
1.1039 +
1.1040 + int size = int (end - buffer);
1.1041 +
1.1042 + // insert as many zeros as specified by precision
1.1043 + if (-1 < spec.prec && size < spec.prec) {
1.1044 + // FIXME: prevent buffer overrun
1.1045 + for (int i = size; i != spec.prec; ++i)
1.1046 + *end++ = '0';
1.1047 + }
1.1048 +
1.1049 + // insert octal or hex prefix for non-zero values
1.1050 + if (pfx && val) {
1.1051 + if (pfx [1])
1.1052 + *end++ = pfx [1];
1.1053 + *end++ = pfx [0];
1.1054 + }
1.1055 +
1.1056 + if (neg)
1.1057 + *end++ = '-';
1.1058 + else if (spec.fl_plus && ('d' == spec.cvtspec || 'i' == spec.cvtspec))
1.1059 + *end++ = '+';
1.1060 +
1.1061 + if (0 == spec.prec && 0 == val) {
1.1062 + // 7.19.6.1 of ISO/IEC 9899:1999:
1.1063 + // The result of converting a zero value with a precision
1.1064 + // of zero is no characters.
1.1065 + end = buffer;
1.1066 + }
1.1067 +
1.1068 + *end = '\0';
1.1069 +
1.1070 + size = int (end - buffer);
1.1071 +
1.1072 + for (char *pc = buffer; pc < end; ++pc) {
1.1073 + const char tmp = *pc;
1.1074 + *pc = *--end;
1.1075 + *end = tmp;
1.1076 + }
1.1077 +
1.1078 + // reset precision to -1 (already handled above)
1.1079 + FmtSpec newspec (spec);
1.1080 + newspec.fl_pound = 0;
1.1081 + newspec.prec = -1;
1.1082 +
1.1083 + // handle justification by formatting the resulting string
1.1084 + return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (size));
1.1085 +}
1.1086 +
1.1087 +/********************************************************************/
1.1088 +
1.1089 +#ifdef _RWSTD_LONG_LONG
1.1090 +
1.1091 +static int
1.1092 +_rw_fmtllong (const FmtSpec &spec,
1.1093 + char **pbuf, size_t *pbufsize, _RWSTD_LONG_LONG val)
1.1094 +{
1.1095 + char buffer [130]; // big enough for a 128-bit long long in base 2
1.1096 + char *end = buffer;
1.1097 +
1.1098 + long upoff = 0;
1.1099 + const char *pfx = 0;
1.1100 +
1.1101 + if ('X' == spec.cvtspec)
1.1102 + upoff = 36;
1.1103 +
1.1104 + if (spec.fl_pound) {
1.1105 + if (16 == spec.base)
1.1106 + pfx = upoff ? "0X" : "0x";
1.1107 + else if (8 == spec.base && val)
1.1108 + pfx = "0";
1.1109 + }
1.1110 +
1.1111 + const int base = 1 < spec.base && spec.base < 37 ? spec.base : 10;
1.1112 +
1.1113 + typedef unsigned _RWSTD_LONG_LONG ULLong;
1.1114 +
1.1115 + ULLong uval;
1.1116 +
1.1117 + bool neg;
1.1118 +
1.1119 + if (val < 0) {
1.1120 + neg = 'd' == spec.cvtspec || 'i' == spec.cvtspec;
1.1121 + uval = ULLong (neg ? -val : val);
1.1122 + }
1.1123 + else {
1.1124 + neg = false;
1.1125 + uval = ULLong (val);
1.1126 + }
1.1127 +
1.1128 + do {
1.1129 + *end++ = _rw_digits [upoff + uval % base];
1.1130 + } while (uval /= base);
1.1131 +
1.1132 + if (pfx) {
1.1133 + if (pfx [1])
1.1134 + *end++ = pfx [1];
1.1135 + *end++ = pfx [0];
1.1136 + }
1.1137 +
1.1138 + char sign;
1.1139 +
1.1140 + if (neg)
1.1141 + sign = '-';
1.1142 + else if (spec.fl_plus && ('d' == spec.cvtspec || 'i' == spec.cvtspec))
1.1143 + sign= '+';
1.1144 + else
1.1145 + sign = '\0';
1.1146 +
1.1147 + assert (buffer < end);
1.1148 + size_t size = size_t (end - buffer);
1.1149 +
1.1150 + // FIXME: prevent buffer overrun
1.1151 + if (0 < spec.prec && size < size_t (spec.prec)) {
1.1152 + for (size_t i = size; i != size_t (spec.prec); ++i)
1.1153 + *end++ = '0';
1.1154 + }
1.1155 +
1.1156 + if (sign)
1.1157 + *end++ = sign;
1.1158 +
1.1159 + *end = '\0';
1.1160 +
1.1161 + assert (buffer < end);
1.1162 + size = size_t (end - buffer);
1.1163 +
1.1164 + for (char *pc = buffer; pc < end; ++pc) {
1.1165 + const char tmp = *pc;
1.1166 + *pc = *--end;
1.1167 + *end = tmp;
1.1168 + }
1.1169 +
1.1170 + // handle justification by formatting the resulting string
1.1171 + return _rw_fmtstr (spec, pbuf, pbufsize, buffer, size);
1.1172 +}
1.1173 +
1.1174 +#endif // _RWSTD_LONG_LONG
1.1175 +
1.1176 +/********************************************************************/
1.1177 +
1.1178 +static int
1.1179 +_rw_fmtinteger (FmtSpec *pspec, size_t paramno,
1.1180 + char **pbuf, size_t *pbufsize, va_list *pva)
1.1181 +{
1.1182 + int len = -1;
1.1183 +
1.1184 + FmtSpec &spec = pspec [paramno];
1.1185 +
1.1186 + switch (spec.cvtspec) {
1.1187 + case 'd':
1.1188 + case 'i':
1.1189 + if (spec.mod_hh) {
1.1190 + // promoted signed char argument
1.1191 + spec.param.i = PARAM (int, i);
1.1192 + const signed char val = spec.param.i;
1.1193 + len = _rw_fmtlong (spec, pbuf, pbufsize, long (val));
1.1194 + }
1.1195 + else if (spec.mod_h) {
1.1196 + // promoted signed short argument
1.1197 + spec.param.i = PARAM (int, i);
1.1198 + const short val = spec.param.i;
1.1199 + len = _rw_fmtlong (spec, pbuf, pbufsize, long (val));
1.1200 + }
1.1201 + else if (spec.mod_l) { // %li
1.1202 + spec.param.lng = PARAM (long, lng);
1.1203 + len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.lng);
1.1204 + }
1.1205 + else if (spec.mod_ll) { // %lli
1.1206 +
1.1207 +#ifdef _RWSTD_LONG_LONG
1.1208 + spec.param.llong = PARAM (_RWSTD_LONG_LONG, llong);
1.1209 + len = _rw_fmtllong (spec, pbuf, pbufsize, spec.param.llong);
1.1210 +#elif 8 == _RWSTD_LONG_SIZE
1.1211 + spec.param.llong = PARAM (long, lnng);
1.1212 + len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.llong);
1.1213 +#else
1.1214 + assert (!"%lld, %lli: long long not supported");
1.1215 +
1.1216 +#endif // _RWSTD_LONG_LONG
1.1217 + }
1.1218 + else if (spec.mod_t) {
1.1219 + spec.param.diff = PARAM (ptrdiff_t, diff);
1.1220 + if (sizeof (ptrdiff_t) == sizeof (long)) {
1.1221 + len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.diff);
1.1222 + }
1.1223 + else {
1.1224 +#ifdef _RWSTD_LONG_LONG
1.1225 + len = _rw_fmtllong (spec, pbuf, pbufsize, spec.param.diff);
1.1226 +#else // if !defined (_RWSTD_LONG_LONG)
1.1227 + assert (!"%td, %ti: 64-bit types not supported");
1.1228 +#endif // _RWSTD_LONG_LONG
1.1229 + }
1.1230 + }
1.1231 + else if (1 == spec.iwidth) {
1.1232 + spec.param.i = PARAM (int, i);
1.1233 + const _RWSTD_INT8_T val = spec.param.i;
1.1234 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1235 + }
1.1236 + else if (2 == spec.iwidth) {
1.1237 + spec.param.i = PARAM (int, i);
1.1238 + const _RWSTD_INT16_T val = spec.param.i;
1.1239 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1240 + }
1.1241 + else if (3 == spec.iwidth) {
1.1242 + spec.param.i32 = PARAM (_RWSTD_INT32_T, i32);
1.1243 + const long val = long (spec.param.i32);
1.1244 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1245 + }
1.1246 + else if (4 == spec.iwidth) {
1.1247 +
1.1248 +#ifdef _RWSTD_INT64_T
1.1249 + spec.param.i64 = PARAM (_RWSTD_INT64_T, i64);
1.1250 +#else // if !defined (_RWSTD_INT64_T)
1.1251 + assert (!"%I64d, %I64i: 64-bit types not supported");
1.1252 +#endif // _RWSTD_INT64_T
1.1253 +
1.1254 +#if 8 == _RWSTD_LONG_SIZE
1.1255 + const long val = spec.param.i64;
1.1256 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1257 +#elif defined (_RWSTD_LONG_LONG)
1.1258 + const _RWSTD_LONG_LONG val = spec.param.i64;
1.1259 + len = _rw_fmtllong (spec, pbuf, pbufsize, val);
1.1260 +#else
1.1261 + assert (!"%I64d, %I64i: 64-bit types not supported");
1.1262 +#endif
1.1263 + }
1.1264 + else { // %i
1.1265 + spec.param.i = PARAM (int, i);
1.1266 + len = _rw_fmtlong (spec, pbuf, pbufsize, long (spec.param.i));
1.1267 + }
1.1268 + break;
1.1269 +
1.1270 + case 'o':
1.1271 + assert (-1 == spec.base);
1.1272 + spec.base = 8;
1.1273 + // fall thru
1.1274 +
1.1275 + case 'x':
1.1276 + if (-1 == spec.base)
1.1277 + spec.base = 16;
1.1278 + // fall thru
1.1279 +
1.1280 + case 'X':
1.1281 + if (-1 == spec.base)
1.1282 + spec.base = 16;
1.1283 +
1.1284 + case 'u':
1.1285 + if (spec.mod_hh) {
1.1286 + // promoted unsigned char argument
1.1287 + spec.param.i = PARAM (unsigned, i);
1.1288 + const unsigned char val = spec.param.i;
1.1289 + len = _rw_fmtlong (spec, pbuf, pbufsize, (unsigned long)val);
1.1290 + }
1.1291 + else if (spec.mod_h) {
1.1292 + // promoted unsigned short argument
1.1293 + spec.param.i = PARAM (unsigned, i);
1.1294 + const unsigned short val = spec.param.i;
1.1295 + len = _rw_fmtlong (spec, pbuf, pbufsize, (unsigned long)val);
1.1296 + }
1.1297 + else if (spec.mod_ll) {
1.1298 +#ifdef _RWSTD_LONG_LONG
1.1299 + spec.param.llong = PARAM (unsigned _RWSTD_LONG_LONG, llong);
1.1300 + const unsigned _RWSTD_LONG_LONG val = spec.param.llong;
1.1301 + len = _rw_fmtllong (spec, pbuf, pbufsize, val);
1.1302 +#elif 8 == _RWSTD_LONG_SIZE
1.1303 + spec.param.lng = PARAM (unsigned long, lng);
1.1304 + const unsigned long val = spec.param.lng;
1.1305 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1306 +#else
1.1307 + assert (!"long long not supported");
1.1308 +#endif // _RWSTD_LONG_LONG
1.1309 +
1.1310 + }
1.1311 + else if (spec.mod_l) {
1.1312 + spec.param.lng = PARAM (unsigned long, lng);
1.1313 + const unsigned long val = spec.param.lng;
1.1314 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1315 + }
1.1316 + else if (spec.mod_t) {
1.1317 + spec.param.lng = PARAM (size_t, size);
1.1318 + if (sizeof (size_t) == sizeof (unsigned long)) {
1.1319 + len = _rw_fmtlong (spec, pbuf, pbufsize, spec.param.size);
1.1320 + }
1.1321 + else {
1.1322 +#ifdef _RWSTD_LONG_LONG
1.1323 + len = _rw_fmtllong (spec, pbuf, pbufsize, spec.param.size);
1.1324 +#else // if defined (_RWSTD_LONG_LONG)
1.1325 + assert (!"%to, %tu, %tx: 64-bit types not implemented");
1.1326 +#endif // _RWSTD_LONG_LONG
1.1327 + }
1.1328 + }
1.1329 + else if (1 == spec.iwidth) {
1.1330 + spec.param.i = PARAM (int, i);
1.1331 + const _RWSTD_UINT8_T val = spec.param.i;
1.1332 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1333 + }
1.1334 + else if (2 == spec.iwidth) {
1.1335 + spec.param.i = PARAM (int, i);
1.1336 + const long val = (unsigned short)spec.param.i;
1.1337 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1338 + }
1.1339 + else if (3 == spec.iwidth) {
1.1340 + spec.param.i32 = PARAM (_RWSTD_INT32_T, i32);
1.1341 + const long val = long (unsigned (spec.param.i));
1.1342 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1343 + }
1.1344 + else if (4 == spec.iwidth) {
1.1345 +#ifdef _RWSTD_INT64_T
1.1346 + spec.param.i64 = PARAM (_RWSTD_INT64_T, i64);
1.1347 +#else // if defined 9_RWSTD_INT64_T)
1.1348 + assert (!"%I64o, %I64u, %I64x: 64-bit types not supported");
1.1349 +#endif // _RWSTD_INT64_T
1.1350 +
1.1351 +#if 8 == _RWSTD_LONG_SIZE
1.1352 + const unsigned long val = spec.param.i64;
1.1353 + len = _rw_fmtlong (spec, pbuf, pbufsize, val);
1.1354 +#elif defined (_RWSTD_LONG_LONG)
1.1355 + const unsigned _RWSTD_LONG_LONG val = spec.param.i64;
1.1356 + len = _rw_fmtllong (spec, pbuf, pbufsize, val);
1.1357 +#else
1.1358 + assert (!"%I64o, %I64u, %I64x: 64-bit types not supported");
1.1359 +#endif
1.1360 + }
1.1361 + else {
1.1362 + spec.param.i = PARAM (unsigned, i);
1.1363 + const unsigned val = spec.param.i;
1.1364 + len = _rw_fmtlong (spec, pbuf, pbufsize, long (val));
1.1365 + }
1.1366 +
1.1367 + break;
1.1368 + }
1.1369 +
1.1370 + return len;
1.1371 +}
1.1372 +
1.1373 +/********************************************************************/
1.1374 +
1.1375 +static int
1.1376 +_rw_fmtfloating (const FmtSpec &spec,
1.1377 + char **pbuf, size_t *pbufsize, const void *pval)
1.1378 +{
1.1379 + char fmt [128];
1.1380 + char *pf = fmt;
1.1381 +
1.1382 + *pf++ = '%';
1.1383 +
1.1384 + if (spec.fl_minus)
1.1385 + *pf++ = '-';
1.1386 +
1.1387 + if (spec.fl_plus)
1.1388 + *pf++ = '+';
1.1389 +
1.1390 + if (spec.fl_pound)
1.1391 + *pf++ = '#';
1.1392 +
1.1393 + if (spec.fl_space)
1.1394 + *pf++ = ' ';
1.1395 +
1.1396 + if (spec.fl_zero)
1.1397 + *pf++ = '0';
1.1398 +
1.1399 + if (spec.mod_h)
1.1400 + *pf++ = 'h';
1.1401 + else if (spec.mod_hh) {
1.1402 + *pf++ = 'h';
1.1403 + *pf++ = 'h';
1.1404 + }
1.1405 + else if (spec.mod_l)
1.1406 + *pf++ = 'l';
1.1407 + else if (spec.mod_ll) {
1.1408 + *pf++ = 'l';
1.1409 + *pf++ = 'l';
1.1410 + }
1.1411 + else if (spec.mod_j)
1.1412 + *pf++ = 'j';
1.1413 + else if (spec.mod_z)
1.1414 + *pf++ = 'z';
1.1415 + else if (spec.mod_t)
1.1416 + *pf++ = 't';
1.1417 + else if (spec.mod_L) {
1.1418 + strcpy (pf, _RWSTD_LDBL_PRINTF_PREFIX);
1.1419 + for ( ; *pf; ++pf);
1.1420 + }
1.1421 + else if (spec.mod_A && _RWSTD_LDBL_SIZE == spec.width) {
1.1422 + strcpy (pf, _RWSTD_LDBL_PRINTF_PREFIX);
1.1423 + for ( ; *pf; ++pf);
1.1424 + }
1.1425 +
1.1426 + if (!spec.mod_A && 0 <= spec.width) {
1.1427 + pf += sprintf (pf, "%i", spec.width);
1.1428 + }
1.1429 +
1.1430 + if (0 <= spec.prec)
1.1431 + pf += sprintf (pf, ".%i", spec.prec);
1.1432 +
1.1433 + *pf++ = char (spec.cvtspec);
1.1434 + *pf = '\0';
1.1435 +
1.1436 + // verify that the format buffer hasn't overflowed
1.1437 + assert (size_t (pf - fmt) + 1 < sizeof fmt);
1.1438 +
1.1439 + // this might make the buffer almost 5KB
1.1440 + char buffer [_RWSTD_LDBL_MAX_10_EXP + _RWSTD_LDBL_DIG + 3];
1.1441 + int len = -1;
1.1442 +
1.1443 + if (spec.mod_A) {
1.1444 +
1.1445 + if (_RWSTD_FLT_SIZE == spec.width) {
1.1446 + len = sprintf (buffer, fmt, *(const float*)pval);
1.1447 + }
1.1448 + else if (_RWSTD_DBL_SIZE == spec.width) {
1.1449 + len = sprintf (buffer, fmt, *(const double*)pval);
1.1450 + }
1.1451 + else if (_RWSTD_LDBL_SIZE == spec.width) {
1.1452 + len = sprintf (buffer, fmt, *(const long double*)pval);
1.1453 + }
1.1454 + else {
1.1455 + assert (!"unknown floating point size");
1.1456 + }
1.1457 + }
1.1458 + else if (spec.mod_L)
1.1459 + len = sprintf (buffer, fmt, *(const long double*)pval);
1.1460 + else
1.1461 + len = sprintf (buffer, fmt, *(const double*)pval);
1.1462 +
1.1463 + assert (size_t (len) < sizeof buffer);
1.1464 +
1.1465 +#ifdef _MSC_VER
1.1466 +
1.1467 + if (5 < len) {
1.1468 + // remove redundant zeros from the exponent (if present)
1.1469 + if ( ('e' == buffer [len - 5] || 'E' == buffer [len - 5])
1.1470 + && '0' == buffer [len - 3]) {
1.1471 + buffer [len - 3] = buffer [len - 2];
1.1472 + buffer [len - 2] = buffer [len - 1];
1.1473 + buffer [len - 1] = buffer [len];
1.1474 + }
1.1475 + }
1.1476 +
1.1477 +#endif // _MSC_VER
1.1478 +
1.1479 +
1.1480 + if (-1 < len && 0 == _rw_bufcat (pbuf, pbufsize, buffer, size_t (len)))
1.1481 + return -1;
1.1482 +
1.1483 + return len;
1.1484 +}
1.1485 +
1.1486 +/********************************************************************/
1.1487 +
1.1488 +// formats a data, function, or class member pointer as follows
1.1489 +// 0x<hex-long-0>[:<hex-long-1>[:...[:<hex-long-N>]]]
1.1490 +// where N is the size of the pointer in long ints
1.1491 +
1.1492 +
1.1493 +static int
1.1494 +_rw_fmtpointer (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
1.1495 + const void *pptr, size_t nelems)
1.1496 +{
1.1497 + FmtSpec newspec (spec);
1.1498 +
1.1499 + // always format data pointers in hexadecimal
1.1500 + newspec.base = 16;
1.1501 +
1.1502 + // set the number of digits
1.1503 + newspec.prec = _RWSTD_LONG_SIZE * 2;
1.1504 +
1.1505 + const union {
1.1506 + const void *ptr;
1.1507 + const unsigned long *lptr;
1.1508 + } uptr = { pptr };
1.1509 +
1.1510 + int len = 0;
1.1511 +
1.1512 + if (newspec.fl_pound) {
1.1513 + // prepend the 0x prefix even to null pointers
1.1514 + if (0 == _rw_bufcat (pbuf, pbufsize, "0x", len = 2)) {
1.1515 + return -1;
1.1516 + }
1.1517 +
1.1518 + // reset the pound flag to prevent the integer formatter
1.1519 + // from inserting it again
1.1520 + newspec.fl_pound = 0;
1.1521 + }
1.1522 +
1.1523 + for (size_t i = 0; i != nelems; ++i) {
1.1524 + const size_t inx = _rw_big_endian ? nelems - i - 1 : i;
1.1525 +
1.1526 + len += _rw_fmtlong (newspec, pbuf, pbufsize, uptr.lptr [inx]);
1.1527 +
1.1528 + if (len < 0) {
1.1529 + break;
1.1530 + }
1.1531 +
1.1532 + // separate pointer components with colons
1.1533 + int n = 0;
1.1534 + if (i + 1 < nelems) {
1.1535 + if (0 == _rw_bufcat (pbuf, pbufsize, ":", n = 1)) {
1.1536 + len = -1;
1.1537 + break;
1.1538 + }
1.1539 + }
1.1540 +
1.1541 + len += n;
1.1542 + }
1.1543 +
1.1544 + return len;
1.1545 +}
1.1546 +
1.1547 +/********************************************************************/
1.1548 +
1.1549 +_RWSTD_INTERNAL int
1.1550 +_rw_fmtptr (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
1.1551 + const void *val)
1.1552 +{
1.1553 + return _rw_fmtpointer (spec, pbuf, pbufsize, &val,
1.1554 + sizeof val / sizeof (long));
1.1555 +}
1.1556 +
1.1557 +/********************************************************************/
1.1558 +
1.1559 +static int
1.1560 +_rw_fmtfunptr (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
1.1561 + funptr_t val)
1.1562 +{
1.1563 + if (spec.mod_l) {
1.1564 +
1.1565 +#if 0 // disabled until this is implemented on other platforms
1.1566 +#ifdef _RWSTD_OS_SUNOS
1.1567 +
1.1568 + char buffer [256];
1.1569 +
1.1570 + Dl_info dli;
1.1571 +
1.1572 + // find the symbol corresponding to the address
1.1573 + if (dladdr ((void*)val, &dli)) {
1.1574 + if (!dli.dli_sname)
1.1575 + dli.dli_fname = "unknown";
1.1576 +
1.1577 + const size_t sym_off = size_t (dli.dli_saddr);
1.1578 +
1.1579 + // compute the offset of the address from the address
1.1580 + // of the symbol dladdr() found in the address space
1.1581 + // of the calling process
1.1582 + const size_t addr_off = size_t (val) < sym_off ?
1.1583 + sym_off - size_t (val) : size_t (val) - sym_off;
1.1584 +
1.1585 + // format the address folowed by the name of the symbol
1.1586 + // followed by the offset
1.1587 + const int len = sprintf (buffer, "%#x=%s%c%lu",
1.1588 + size_t (val), dli.dli_sname,
1.1589 + size_t (val) < sym_off ? '-' : '+',
1.1590 + addr_off);
1.1591 +
1.1592 + FmtSpec newspec (spec);
1.1593 + newspec.mod_l = false;
1.1594 +
1.1595 + return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (len));
1.1596 + }
1.1597 +
1.1598 +#endif // _RWSTD_OS_SUNOS
1.1599 +#endif // 0/1
1.1600 + }
1.1601 +
1.1602 + return _rw_fmtpointer (spec, pbuf, pbufsize, &val,
1.1603 + sizeof val / sizeof (long));
1.1604 +}
1.1605 +
1.1606 +/********************************************************************/
1.1607 +
1.1608 +static int
1.1609 +_rw_fmtmemptr (const FmtSpec &spec, char **pbuf, size_t *pbufsize, memptr_t val)
1.1610 +{
1.1611 + return _rw_fmtpointer (spec, pbuf, pbufsize, &val,
1.1612 + sizeof val / sizeof (long));
1.1613 +}
1.1614 +
1.1615 +/********************************************************************/
1.1616 +
1.1617 +static int
1.1618 +_rw_fmterrno (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
1.1619 +{
1.1620 + static const struct {
1.1621 + int val;
1.1622 + const char* str;
1.1623 + } names[] = {
1.1624 +
1.1625 +#undef ERRNO
1.1626 +#define ERRNO(val) { val, #val }
1.1627 +
1.1628 +#ifdef EPERM
1.1629 + ERRNO (EPERM),
1.1630 +#endif // EPERM
1.1631 +#ifdef ENOENT
1.1632 + ERRNO (ENOENT),
1.1633 +#endif // ENOENT
1.1634 +#ifdef ESRCH
1.1635 + ERRNO (ESRCH),
1.1636 +#endif // ESRCH
1.1637 +#ifdef EINTR
1.1638 + ERRNO (EINTR),
1.1639 +#endif // EINTR
1.1640 +#ifdef EIO
1.1641 + ERRNO (EIO),
1.1642 +#endif // EIO
1.1643 +#ifdef ENXIO
1.1644 + ERRNO (ENXIO),
1.1645 +#endif // ENXIO
1.1646 +#ifdef E2BIG
1.1647 + ERRNO (E2BIG),
1.1648 +#endif // E2BIG
1.1649 +#ifdef ENOEXEC
1.1650 + ERRNO (ENOEXEC),
1.1651 +#endif // ENOEXEC
1.1652 +#ifdef EBADF
1.1653 + ERRNO (EBADF),
1.1654 +#endif // EBADF
1.1655 +#ifdef ECHILD
1.1656 + ERRNO (ECHILD),
1.1657 +#endif // ECHILD
1.1658 +#ifdef EAGAIN
1.1659 + ERRNO (EAGAIN),
1.1660 +#endif // EAGAIN
1.1661 +#ifdef ENOMEM
1.1662 + ERRNO (ENOMEM),
1.1663 +#endif // ENOMEM
1.1664 +#ifdef EACCES
1.1665 + ERRNO (EACCES),
1.1666 +#endif // EACCES
1.1667 +#ifdef EFAULT
1.1668 + ERRNO (EFAULT),
1.1669 +#endif // EFAULT
1.1670 +#ifdef ENOTBLK
1.1671 + ERRNO (ENOTBLK),
1.1672 +#endif // ENOTBLK
1.1673 +#ifdef EBUSY
1.1674 + ERRNO (EBUSY),
1.1675 +#endif // EBUSY
1.1676 +#ifdef EEXIST
1.1677 + ERRNO (EEXIST),
1.1678 +#endif // EEXIST
1.1679 +#ifdef EXDEV
1.1680 + ERRNO (EXDEV),
1.1681 +#endif // EXDEV
1.1682 +#ifdef ENODEV
1.1683 + ERRNO (ENODEV),
1.1684 +#endif // ENODEV
1.1685 +#ifdef ENOTDIR
1.1686 + ERRNO (ENOTDIR),
1.1687 +#endif // ENOTDIR
1.1688 +#ifdef EISDIR
1.1689 + ERRNO (EISDIR),
1.1690 +#endif // EISDIR
1.1691 +#ifdef EINVAL
1.1692 + ERRNO (EINVAL),
1.1693 +#endif // EINVAL
1.1694 +#ifdef ENFILE
1.1695 + ERRNO (ENFILE),
1.1696 +#endif // ENFILE
1.1697 +#ifdef EMFILE
1.1698 + ERRNO (EMFILE),
1.1699 +#endif // EMFILE
1.1700 +#ifdef ENOTTY
1.1701 + ERRNO (ENOTTY),
1.1702 +#endif // ENOTTY
1.1703 +#ifdef ETXTBSY
1.1704 + ERRNO (ETXTBSY),
1.1705 +#endif // ETXTBSY
1.1706 +#ifdef EFBIG
1.1707 + ERRNO (EFBIG),
1.1708 +#endif // EFBIG
1.1709 +#ifdef ENOSPC
1.1710 + ERRNO (ENOSPC),
1.1711 +#endif // ENOSPC
1.1712 +#ifdef ESPIPE
1.1713 + ERRNO (ESPIPE),
1.1714 +#endif // ESPIPE
1.1715 +#ifdef EROFS
1.1716 + ERRNO (EROFS),
1.1717 +#endif // EROFS
1.1718 +#ifdef EMLINK
1.1719 + ERRNO (EMLINK),
1.1720 +#endif // EMLINK
1.1721 +#ifdef EPIPE
1.1722 + ERRNO (EPIPE),
1.1723 +#endif // EPIPE
1.1724 +#ifdef EDOM
1.1725 + ERRNO (EDOM),
1.1726 +#endif // EDOM
1.1727 +#ifdef ERANGE
1.1728 + ERRNO (ERANGE),
1.1729 +#endif // ERANGE
1.1730 +#ifdef ENOMSG
1.1731 + ERRNO (ENOMSG),
1.1732 +#endif // ENOMSG
1.1733 +#ifdef EIDRM
1.1734 + ERRNO (EIDRM),
1.1735 +#endif // EIDRM
1.1736 +#ifdef ECHRNG
1.1737 + ERRNO (ECHRNG),
1.1738 +#endif // ECHRNG
1.1739 +#ifdef EL2NSYNC
1.1740 + ERRNO (EL2NSYNC),
1.1741 +#endif // EL2NSYNC
1.1742 +#ifdef EL3HLT
1.1743 + ERRNO (EL3HLT),
1.1744 +#endif // EL3HLT
1.1745 +#ifdef EL3RST
1.1746 + ERRNO (EL3RST),
1.1747 +#endif // EL3RST
1.1748 +#ifdef ELNRNG
1.1749 + ERRNO (ELNRNG),
1.1750 +#endif // ELNRNG
1.1751 +#ifdef EUNATCH
1.1752 + ERRNO (EUNATCH),
1.1753 +#endif // EUNATCH
1.1754 +#ifdef ENOCSI
1.1755 + ERRNO (ENOCSI),
1.1756 +#endif // ENOCSI
1.1757 +#ifdef EL2HLT
1.1758 + ERRNO (EL2HLT),
1.1759 +#endif // EL2HLT
1.1760 +#ifdef EDEADLK
1.1761 + ERRNO (EDEADLK),
1.1762 +#endif // EDEADLK
1.1763 +#ifdef ENOLCK
1.1764 + ERRNO (ENOLCK),
1.1765 +#endif // ENOLCK
1.1766 +#ifdef ECANCELED
1.1767 + ERRNO (ECANCELED),
1.1768 +#endif // ECANCELED
1.1769 +#ifdef ENOTSUP
1.1770 + ERRNO (ENOTSUP),
1.1771 +#endif // ENOTSUP
1.1772 +#ifdef EDQUOT
1.1773 + ERRNO (EDQUOT),
1.1774 +#endif // EDQUOT
1.1775 +#ifdef EBADE
1.1776 + ERRNO (EBADE),
1.1777 +#endif // EBADE
1.1778 +#ifdef EBADR
1.1779 + ERRNO (EBADR),
1.1780 +#endif // EBADR
1.1781 +#ifdef EXFULL
1.1782 + ERRNO (EXFULL),
1.1783 +#endif // EXFULL
1.1784 +#ifdef ENOANO
1.1785 + ERRNO (ENOANO),
1.1786 +#endif // ENOANO
1.1787 +#ifdef EBADRQC
1.1788 + ERRNO (EBADRQC),
1.1789 +#endif // EBADRQC
1.1790 +#ifdef EBADSLT
1.1791 + ERRNO (EBADSLT),
1.1792 +#endif // EBADSLT
1.1793 +#ifdef EDEADLOCK
1.1794 + ERRNO (EDEADLOCK),
1.1795 +#endif // EDEADLOCK
1.1796 +#ifdef EBFONT
1.1797 + ERRNO (EBFONT),
1.1798 +#endif // EBFONT
1.1799 +#ifdef EOWNERDEAD
1.1800 + ERRNO (EOWNERDEAD),
1.1801 +#endif // EOWNERDEAD
1.1802 +#ifdef ENOTRECOVERABLE
1.1803 + ERRNO (ENOTRECOVERABLE),
1.1804 +#endif // ENOTRECOVERABLE
1.1805 +#ifdef ENOSTR
1.1806 + ERRNO (ENOSTR),
1.1807 +#endif // ENOSTR
1.1808 +#ifdef ENODATA
1.1809 + ERRNO (ENODATA),
1.1810 +#endif // ENODATA
1.1811 +#ifdef ETIME
1.1812 + ERRNO (ETIME),
1.1813 +#endif // ETIME
1.1814 +#ifdef ENOSR
1.1815 + ERRNO (ENOSR),
1.1816 +#endif // ENOSR
1.1817 +#ifdef ENONET
1.1818 + ERRNO (ENONET),
1.1819 +#endif // ENONET
1.1820 +#ifdef ENOPKG
1.1821 + ERRNO (ENOPKG),
1.1822 +#endif // ENOPKG
1.1823 +#ifdef EREMOTE
1.1824 + ERRNO (EREMOTE),
1.1825 +#endif // EREMOTE
1.1826 +#ifdef ENOLINK
1.1827 + ERRNO (ENOLINK),
1.1828 +#endif // ENOLINK
1.1829 +#ifdef EADV
1.1830 + ERRNO (EADV),
1.1831 +#endif // EADV
1.1832 +#ifdef ESRMNT
1.1833 + ERRNO (ESRMNT),
1.1834 +#endif // ESRMNT
1.1835 +#ifdef ECOMM
1.1836 + ERRNO (ECOMM),
1.1837 +#endif // ECOMM
1.1838 +#ifdef ELOCKUNMAPPED
1.1839 + ERRNO (ELOCKUNMAPPED),
1.1840 +#endif // ELOCKUNMAPPED
1.1841 +#ifdef ENOTACTIVE
1.1842 + ERRNO (ENOTACTIVE),
1.1843 +#endif // ENOTACTIVE
1.1844 +#ifdef EMULTIHOP
1.1845 + ERRNO (EMULTIHOP),
1.1846 +#endif // EMULTIHOP
1.1847 +#ifdef EBADMSG
1.1848 + ERRNO (EBADMSG),
1.1849 +#endif // EBADMSG
1.1850 +#ifdef ENAMETOOLONG
1.1851 + ERRNO (ENAMETOOLONG),
1.1852 +#endif // ENAMETOOLONG
1.1853 +#ifdef EOVERFLOW
1.1854 + ERRNO (EOVERFLOW),
1.1855 +#endif // EOVERFLOW
1.1856 +#ifdef ENOTUNIQ
1.1857 + ERRNO (ENOTUNIQ),
1.1858 +#endif // ENOTUNIQ
1.1859 +#ifdef EBADFD
1.1860 + ERRNO (EBADFD),
1.1861 +#endif // EBADFD
1.1862 +#ifdef EREMCHG
1.1863 + ERRNO (EREMCHG),
1.1864 +#endif // EREMCHG
1.1865 +#ifdef ELIBACC
1.1866 + ERRNO (ELIBACC),
1.1867 +#endif // ELIBACC
1.1868 +#ifdef ELIBBAD
1.1869 + ERRNO (ELIBBAD),
1.1870 +#endif // ELIBBAD
1.1871 +#ifdef ELIBSCN
1.1872 + ERRNO (ELIBSCN),
1.1873 +#endif // ELIBSCN
1.1874 +#ifdef ELIBMAX
1.1875 + ERRNO (ELIBMAX),
1.1876 +#endif // ELIBMAX
1.1877 +#ifdef ELIBEXEC
1.1878 + ERRNO (ELIBEXEC),
1.1879 +#endif // ELIBEXEC
1.1880 +#ifdef EILSEQ
1.1881 + ERRNO (EILSEQ),
1.1882 +#endif // EILSEQ
1.1883 +#ifdef ENOSYS
1.1884 + ERRNO (ENOSYS),
1.1885 +#endif // ENOSYS
1.1886 +#ifdef ELOOP
1.1887 + ERRNO (ELOOP),
1.1888 +#endif // ELOOP
1.1889 +#ifdef ERESTART
1.1890 + ERRNO (ERESTART),
1.1891 +#endif // ERESTART
1.1892 +#ifdef ESTRPIPE
1.1893 + ERRNO (ESTRPIPE),
1.1894 +#endif // ESTRPIPE
1.1895 +#ifdef ENOTEMPTY
1.1896 + ERRNO (ENOTEMPTY),
1.1897 +#endif // ENOTEMPTY
1.1898 +#ifdef EUSERS
1.1899 + ERRNO (EUSERS),
1.1900 +#endif // EUSERS
1.1901 +#ifdef ENOTSOCK
1.1902 + ERRNO (ENOTSOCK),
1.1903 +#endif // ENOTSOCK
1.1904 +#ifdef EDESTADDRREQ
1.1905 + ERRNO (EDESTADDRREQ),
1.1906 +#endif // EDESTADDRREQ
1.1907 +#ifdef EMSGSIZE
1.1908 + ERRNO (EMSGSIZE),
1.1909 +#endif // EMSGSIZE
1.1910 +#ifdef EPROTOTYPE
1.1911 + ERRNO (EPROTOTYPE),
1.1912 +#endif // EPROTOTYPE
1.1913 +#ifdef ENOPROTOOPT
1.1914 + ERRNO (ENOPROTOOPT),
1.1915 +#endif // ENOPROTOOPT
1.1916 +#ifdef EPROTONOSUPPORT
1.1917 + ERRNO (EPROTONOSUPPORT),
1.1918 +#endif // EPROTONOSUPPORT
1.1919 +#ifdef ESOCKTNOSUPPORT
1.1920 + ERRNO (ESOCKTNOSUPPORT),
1.1921 +#endif // ESOCKTNOSUPPORT
1.1922 +#ifdef EOPNOTSUPP
1.1923 + ERRNO (EOPNOTSUPP),
1.1924 +#endif // EOPNOTSUPP
1.1925 +#ifdef EPFNOSUPPORT
1.1926 + ERRNO (EPFNOSUPPORT),
1.1927 +#endif // EPFNOSUPPORT
1.1928 +#ifdef EAFNOSUPPORT
1.1929 + ERRNO (EAFNOSUPPORT),
1.1930 +#endif // EAFNOSUPPORT
1.1931 +#ifdef EADDRINUSE
1.1932 + ERRNO (EADDRINUSE),
1.1933 +#endif // EADDRINUSE
1.1934 +#ifdef EADDRNOTAVAIL
1.1935 + ERRNO (EADDRNOTAVAIL),
1.1936 +#endif // EADDRNOTAVAIL
1.1937 +#ifdef ENETDOWN
1.1938 + ERRNO (ENETDOWN),
1.1939 +#endif // ENETDOWN
1.1940 +#ifdef ENETUNREACH
1.1941 + ERRNO (ENETUNREACH),
1.1942 +#endif // ENETUNREACH
1.1943 +#ifdef ENETRESET
1.1944 + ERRNO (ENETRESET),
1.1945 +#endif // ENETRESET
1.1946 +#ifdef ECONNABORTED
1.1947 + ERRNO (ECONNABORTED),
1.1948 +#endif // ECONNABORTED
1.1949 +#ifdef ECONNRESET
1.1950 + ERRNO (ECONNRESET),
1.1951 +#endif // ECONNRESET
1.1952 +#ifdef ENOBUFS
1.1953 + ERRNO (ENOBUFS),
1.1954 +#endif // ENOBUFS
1.1955 +#ifdef EISCONN
1.1956 + ERRNO (EISCONN),
1.1957 +#endif // EISCONN
1.1958 +#ifdef ENOTCONN
1.1959 + ERRNO (ENOTCONN),
1.1960 +#endif // ENOTCONN
1.1961 +#ifdef ESHUTDOWN
1.1962 + ERRNO (ESHUTDOWN),
1.1963 +#endif // ESHUTDOWN
1.1964 +#ifdef ETOOMANYREFS
1.1965 + ERRNO (ETOOMANYREFS),
1.1966 +#endif // ETOOMANYREFS
1.1967 +#ifdef ETIMEDOUT
1.1968 + ERRNO (ETIMEDOUT),
1.1969 +#endif // ETIMEDOUT
1.1970 +#ifdef ECONNREFUSED
1.1971 + ERRNO (ECONNREFUSED),
1.1972 +#endif // ECONNREFUSED
1.1973 +#ifdef EHOSTDOWN
1.1974 + ERRNO (EHOSTDOWN),
1.1975 +#endif // EHOSTDOWN
1.1976 +#ifdef EHOSTUNREACH
1.1977 + ERRNO (EHOSTUNREACH),
1.1978 +#endif // EHOSTUNREACH
1.1979 +#ifdef EWOULDBLOCK
1.1980 + ERRNO (EWOULDBLOCK),
1.1981 +#endif // EWOULDBLOCK
1.1982 +#ifdef EALREADY
1.1983 + ERRNO (EALREADY),
1.1984 +#endif // EALREADY
1.1985 +#ifdef EINPROGRESS
1.1986 + ERRNO (EINPROGRESS),
1.1987 +#endif // EINPROGRESS
1.1988 +#ifdef ESTALE
1.1989 + ERRNO (ESTALE),
1.1990 +#endif // ESTALE
1.1991 + { -1, 0 }
1.1992 + };
1.1993 +
1.1994 + if (spec.fl_pound) {
1.1995 +
1.1996 + char buffer [64];
1.1997 + const char *name = 0;
1.1998 +
1.1999 + for (size_t i = 0; i != sizeof names / sizeof *names; ++i) {
1.2000 + if (names [i].val == val) {
1.2001 + name = names [i].str;
1.2002 + break;
1.2003 + }
1.2004 + }
1.2005 +
1.2006 + int len;
1.2007 +
1.2008 + if (0 == name) {
1.2009 + len = sprintf (buffer, "E#%d", val);
1.2010 + name = buffer;
1.2011 + }
1.2012 + else
1.2013 + len = int (strlen (name));
1.2014 +
1.2015 + if (0 == _rw_bufcat (pbuf, pbufsize, name, size_t (len)))
1.2016 + return -1;
1.2017 +
1.2018 + return len;
1.2019 + }
1.2020 +
1.2021 + const char* const str = strerror (val);
1.2022 + const size_t len = strlen (str);
1.2023 +
1.2024 + if (0 == _rw_bufcat (pbuf, pbufsize, str, len))
1.2025 + return -1;
1.2026 +
1.2027 + return int (len);
1.2028 +}
1.2029 +
1.2030 +/********************************************************************/
1.2031 +
1.2032 +static int
1.2033 +_rw_fmtsignal (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
1.2034 +{
1.2035 + static const struct {
1.2036 + int val;
1.2037 + const char* str;
1.2038 + } names[] = {
1.2039 +
1.2040 +#undef SIGNAL
1.2041 +#define SIGNAL(val) { val, #val }
1.2042 +
1.2043 +#ifdef SIGABRT
1.2044 + SIGNAL (SIGABRT),
1.2045 +#endif // SIGABRT
1.2046 +#ifdef SIGALRM
1.2047 + SIGNAL (SIGALRM),
1.2048 +#endif // SIGALRM
1.2049 +#ifdef SIGBUS
1.2050 + SIGNAL (SIGBUS),
1.2051 +#endif // SIGBUS
1.2052 +#ifdef SIGCANCEL
1.2053 + SIGNAL (SIGCANCEL),
1.2054 +#endif // SIGCANCEL
1.2055 +#ifdef SIGCHLD
1.2056 + SIGNAL (SIGCHLD),
1.2057 +#endif // SIGCHLD
1.2058 +#ifdef SIGCKPT
1.2059 + SIGNAL (SIGCKPT),
1.2060 +#endif // SIGCKPT
1.2061 +#ifdef SIGCLD
1.2062 + SIGNAL (SIGCLD),
1.2063 +#endif // SIGCLD
1.2064 +#ifdef SIGCONT
1.2065 + SIGNAL (SIGCONT),
1.2066 +#endif // SIGCONT
1.2067 +#ifdef SIGDIL
1.2068 + SIGNAL (SIGDIL),
1.2069 +#endif // SIGDIL
1.2070 +#ifdef SIGEMT
1.2071 + SIGNAL (SIGEMT),
1.2072 +#endif // SIGEMT
1.2073 +#ifdef SIGFPE
1.2074 + SIGNAL (SIGFPE),
1.2075 +#endif // SIGFPE
1.2076 +#ifdef SIGFREEZE
1.2077 + SIGNAL (SIGFREEZE),
1.2078 +#endif // SIGFREEZE
1.2079 +#ifdef SIGGFAULT
1.2080 + SIGNAL (SIGGFAULT),
1.2081 +#endif // SIGGFAULT
1.2082 +#ifdef SIGHUP
1.2083 + SIGNAL (SIGHUP),
1.2084 +#endif // SIGHUP
1.2085 +#ifdef SIGILL
1.2086 + SIGNAL (SIGILL),
1.2087 +#endif // SIGILL
1.2088 +#ifdef SIGINFO
1.2089 + SIGNAL (SIGINFO),
1.2090 +#endif // SIGINFO
1.2091 +#ifdef SIGINT
1.2092 + SIGNAL (SIGINT),
1.2093 +#endif // SIGINT
1.2094 +#ifdef SIGIO
1.2095 + SIGNAL (SIGIO),
1.2096 +#endif // SIGIO
1.2097 +#ifdef SIGIOT
1.2098 + SIGNAL (SIGIOT),
1.2099 +#endif // SIGIOT
1.2100 +#ifdef SIGK32
1.2101 + SIGNAL (SIGK32),
1.2102 +#endif // SIGK32
1.2103 +#ifdef SIGKILL
1.2104 + SIGNAL (SIGKILL),
1.2105 +#endif // SIGKILL
1.2106 +#ifdef SIGLOST
1.2107 + SIGNAL (SIGLOST),
1.2108 +#endif // SIGLOST
1.2109 +#ifdef SIGLWP
1.2110 + SIGNAL (SIGLWP),
1.2111 +#endif // SIGLWP
1.2112 +#ifdef SIGPIPE
1.2113 + SIGNAL (SIGPIPE),
1.2114 +#endif // SIGPIPE
1.2115 +#ifdef SIGPOLL
1.2116 + SIGNAL (SIGPOLL),
1.2117 +#endif // SIGPOLL
1.2118 +#ifdef SIGPROF
1.2119 + SIGNAL (SIGPROF),
1.2120 +#endif // SIGPROF
1.2121 +#ifdef SIGPTINTR
1.2122 + SIGNAL (SIGPTINTR),
1.2123 +#endif // SIGPTINTR
1.2124 +#ifdef SIGPTRESCHED
1.2125 + SIGNAL (SIGPTRESCHED),
1.2126 +#endif // SIGPTRESCHED
1.2127 +#ifdef SIGPWR
1.2128 + SIGNAL (SIGPWR),
1.2129 +#endif // SIGPWR
1.2130 +#ifdef SIGQUIT
1.2131 + SIGNAL (SIGQUIT),
1.2132 +#endif // SIGQUIT
1.2133 +#ifdef SIGRESTART
1.2134 + SIGNAL (SIGRESTART),
1.2135 +#endif // SIGRESTART
1.2136 +#ifdef SIGRESV
1.2137 + SIGNAL (SIGRESV),
1.2138 +#endif // SIGRESV
1.2139 +#ifdef SIGSEGV
1.2140 + SIGNAL (SIGSEGV),
1.2141 +#endif // SIGSEGV
1.2142 +#ifdef SIGSTKFLT
1.2143 + SIGNAL (SIGSTKFLT),
1.2144 +#endif // SIGSTKFLT
1.2145 +#ifdef SIGSTOP
1.2146 + SIGNAL (SIGSTOP),
1.2147 +#endif // SIGSTOP
1.2148 +#ifdef SIGSYS
1.2149 + SIGNAL (SIGSYS),
1.2150 +#endif // SIGSYS
1.2151 +#ifdef SIGTERM
1.2152 + SIGNAL (SIGTERM),
1.2153 +#endif // SIGTERM
1.2154 +#ifdef SIGTHAW
1.2155 + SIGNAL (SIGTHAW),
1.2156 +#endif // SIGTHAW
1.2157 +#ifdef SIGTRAP
1.2158 + SIGNAL (SIGTRAP),
1.2159 +#endif // SIGTRAP
1.2160 +#ifdef SIGTSTP
1.2161 + SIGNAL (SIGTSTP),
1.2162 +#endif // SIGTSTP
1.2163 +#ifdef SIGTTIN
1.2164 + SIGNAL (SIGTTIN),
1.2165 +#endif // SIGTTIN
1.2166 +#ifdef SIGTTOU
1.2167 + SIGNAL (SIGTTOU),
1.2168 +#endif // SIGTTOU
1.2169 +#ifdef SIGUNUSED
1.2170 + SIGNAL (SIGUNUSED),
1.2171 +#endif // SIGUNUSED
1.2172 +#ifdef SIGURG
1.2173 + SIGNAL (SIGURG),
1.2174 +#endif // SIGURG
1.2175 +#ifdef SIGUSR1
1.2176 + SIGNAL (SIGUSR1),
1.2177 +#endif // SIGUSR1
1.2178 +#ifdef SIGUSR2
1.2179 + SIGNAL (SIGUSR2),
1.2180 +#endif // SIGUSR2
1.2181 +#ifdef SIGVTALRM
1.2182 + SIGNAL (SIGVTALRM),
1.2183 +#endif // SIGVTALRM
1.2184 +#ifdef SIGWAITING
1.2185 + SIGNAL (SIGWAITING),
1.2186 +#endif // SIGWAITING
1.2187 +#ifdef SIGWINCH
1.2188 + SIGNAL (SIGWINCH),
1.2189 +#endif // SIGWINCH
1.2190 +#ifdef SIGWINDOW
1.2191 + SIGNAL (SIGWINDOW),
1.2192 +#endif // SIGWINDOW
1.2193 +#ifdef SIGXCPU
1.2194 + SIGNAL (SIGXCPU),
1.2195 +#endif // SIGXCPU
1.2196 +#ifdef SIGXFSZ
1.2197 + SIGNAL (SIGXFSZ),
1.2198 +#endif // SIGXFSZ
1.2199 +#ifdef SIGXRES
1.2200 + SIGNAL (SIGXRES),
1.2201 +#endif // SIGXRES
1.2202 + { -1, 0 }
1.2203 + };
1.2204 +
1.2205 + char buffer [64];
1.2206 + const char *name = 0;
1.2207 +
1.2208 + for (size_t i = 0; i != sizeof names / sizeof *names; ++i) {
1.2209 + if (names [i].val == val) {
1.2210 + name = names [i].str;
1.2211 + break;
1.2212 + }
1.2213 + }
1.2214 +
1.2215 + if (0 == name) {
1.2216 + sprintf (buffer, "SIG#%d", val);
1.2217 + name = buffer;
1.2218 + }
1.2219 +
1.2220 + return _rw_fmtstr (spec, pbuf, pbufsize, name, _RWSTD_SIZE_MAX);
1.2221 +}
1.2222 +
1.2223 +/********************************************************************/
1.2224 +
1.2225 +template <class charT>
1.2226 +int rw_quotechar (char *buf, charT wc, int noesc)
1.2227 +{
1.2228 +#if _RWSTD_WCHAR_T_MIN < 0
1.2229 +
1.2230 + // wchar_t is signed, convert its value to unsigned long
1.2231 + // without widening (i.e., treat it as an unsigned type)
1.2232 +
1.2233 +# if _RWSTD_WCHAR_T_MIN == _RWSTD_SHRT_MIN
1.2234 + const unsigned long wi = (unsigned short)wc;
1.2235 +# elif _RWSTD_WCHAR_T_MIN ==_RWSTD_INT_MIN
1.2236 + const unsigned long wi = (unsigned int)wc;
1.2237 +# elif _RWSTD_WCHAR_T_MIN == _RWSTD_LONG_MIN
1.2238 + const unsigned long wi = (unsigned long)wc;
1.2239 +# endif
1.2240 +
1.2241 +#else // if _RWSTD_WCHAR_T_MIN >= 0
1.2242 +
1.2243 + // wchar_t is unsigned
1.2244 + const unsigned long wi = (unsigned long)wc;
1.2245 +
1.2246 +#endif // _RWSTD_WCHAR_T_MIN < 0
1.2247 +
1.2248 + if ((1 == sizeof wc || wi < 0x100) && noesc) {
1.2249 + buf [0] = char (wc);
1.2250 + buf [1] = '\0';
1.2251 + return 1;
1.2252 + }
1.2253 +
1.2254 + int len = 3;
1.2255 +
1.2256 + buf [0] = '\\';
1.2257 + buf [2] = '\0';
1.2258 +
1.2259 + switch (wc) {
1.2260 + case '\a': buf [1] = 'a'; buf [len = 2] = '\0'; break;
1.2261 + case '\b': buf [1] = 'b'; buf [len = 2] = '\0'; break;
1.2262 + case '\f': buf [1] = 'f'; buf [len = 2] = '\0'; break;
1.2263 + case '\n': buf [1] = 'n'; buf [len = 2] = '\0'; break;
1.2264 + case '\r': buf [1] = 'r'; buf [len = 2] = '\0'; break;
1.2265 + case '\t': buf [1] = 't'; buf [len = 2] = '\0'; break;
1.2266 + case '\v': buf [1] = 'v'; buf [len = 2] = '\0'; break;
1.2267 + case '\\': buf [1] = '\\'; buf [len = 2] = '\0'; break;
1.2268 + case '"' : buf [1] = '"'; buf [len = 2] = '\0'; break;
1.2269 + default:
1.2270 + if (wc < ' ' || wc > '~') {
1.2271 +
1.2272 + if (0 == wc) {
1.2273 + buf [1] = '0';
1.2274 + buf [2] = '\0';
1.2275 + len = 2;
1.2276 + }
1.2277 + else if (1 == sizeof wc) {
1.2278 + len = 1 + sprintf (buf + 1, "x%02x", (unsigned char)wc);
1.2279 + }
1.2280 + else {
1.2281 +
1.2282 + const int width =
1.2283 + wi > 0xfffffffUL ? 8 : wi > 0xffffffUL ? 7
1.2284 + : wi > 0xfffffUL ? 6 : wi > 0xffffUL ? 5
1.2285 + : wi > 0xfffUL ? 4 : wi > 0xffUL ? 3
1.2286 + : wi > 0xfUL ? 2 : 2;
1.2287 +
1.2288 + len = 1 + sprintf (buf + 1, "x%0*lx", width, (unsigned long)wi);
1.2289 + }
1.2290 + }
1.2291 + else {
1.2292 + buf [0] = wc;
1.2293 + buf [1] = '\0';
1.2294 + len = 1;
1.2295 + }
1.2296 + }
1.2297 +
1.2298 + return len;
1.2299 +}
1.2300 +
1.2301 +
1.2302 +template <class charT>
1.2303 +int rw_quotestr (const FmtSpec &spec, char **pbuf, size_t *pbufsize,
1.2304 + const charT *wstr, size_t nchars, int noesc)
1.2305 +{
1.2306 + assert(1);
1.2307 + return 0;
1.2308 +#if 0
1.2309 + assert (0 != pbuf);
1.2310 +
1.2311 + if (!wstr) {
1.2312 + static const charT null[] = { '(', 'n', 'u', 'l', 'l', ')', '\0' };
1.2313 + wstr = null;
1.2314 + nchars = sizeof null / sizeof *null - 1;
1.2315 + }
1.2316 +
1.2317 + if (0 > _RW::__rw_memattr (wstr, _RWSTD_SIZE_MAX, 0)) {
1.2318 +
1.2319 + const size_t buflen = *pbuf ? strlen (*pbuf) : 0;
1.2320 +
1.2321 + if (0 == _rw_bufcat (pbuf, pbufsize, "(invalid address ", 18))
1.2322 + return -1;
1.2323 +
1.2324 + FmtSpec newspec (spec);
1.2325 + newspec.fl_pound = 1;
1.2326 + if (-1 == ::_rw_fmtptr (newspec, pbuf, pbufsize, wstr))
1.2327 + return -1;
1.2328 + if (0 == _rw_bufcat (pbuf, pbufsize, ")", 2))
1.2329 + return -1;
1.2330 +
1.2331 + return int (strlen (*pbuf) - buflen);
1.2332 + }
1.2333 +
1.2334 + if (_RWSTD_SIZE_MAX == nchars) {
1.2335 + // compute the length of the NUL-terminate string
1.2336 + nchars = 0;
1.2337 + for (const charT *pc = wstr; *pc; ++pc, ++nchars);
1.2338 + }
1.2339 +
1.2340 + char *next = _rw_bufcat (pbuf, pbufsize, 0, (nchars + 1) * 12 + 3);
1.2341 + const char* const bufend = next;
1.2342 +
1.2343 + if (0 == next)
1.2344 + return -1;
1.2345 +
1.2346 + if (0 == nchars) {
1.2347 + if (noesc) {
1.2348 +
1.2349 +#if 0 // width handling disabled (width used for array formatting)
1.2350 + for (int w = 0; w < spec.width; ++w)
1.2351 + *next++ = ' ';
1.2352 +#endif // 0/1
1.2353 +
1.2354 + }
1.2355 + else {
1.2356 + if (_RWSTD_WCHAR_T_SIZE == sizeof (charT))
1.2357 + *next++ = 'L';
1.2358 +
1.2359 + *next++ = '"';
1.2360 +#if 0 // width handling disabled (width used for array formatting)
1.2361 + for (int w = 0; w < spec.width; ++w)
1.2362 + *next++ = ' ';
1.2363 +#endif // 0/1
1.2364 + *next++ = '"';
1.2365 + }
1.2366 + *next++ = '\0';
1.2367 + return int (next - bufend);
1.2368 + }
1.2369 +
1.2370 + char *s = next;
1.2371 +
1.2372 + const charT *last = wstr;
1.2373 +
1.2374 + bool any_repeats = false;
1.2375 + long last_repeat = noesc ? 0L : -1L;
1.2376 +
1.2377 + char chstr [16];
1.2378 +
1.2379 + const ptrdiff_t N = ptrdiff_t (noesc ? 0 : 20);
1.2380 +
1.2381 + for (const charT *pwc = last + 1; ; ++pwc) {
1.2382 +
1.2383 + if (*pwc == *last && size_t (pwc - wstr) < nchars) {
1.2384 + // if the last processed character repeats, continue
1.2385 + // until a different character is encountered
1.2386 + continue;
1.2387 + }
1.2388 +
1.2389 + if (N > 1 && pwc - last > N) {
1.2390 +
1.2391 + // if the last processed character repeats N or more
1.2392 + // times, format the repeat count instead of all the
1.2393 + // repeated occurrences of the character to conserve
1.2394 + // space and make the string more readable
1.2395 +
1.2396 + const long repeat = pwc - last;
1.2397 +
1.2398 + rw_quotechar (chstr, *last, noesc);
1.2399 +
1.2400 + s += sprintf (s, "%s'%s' <repeats %ld times>",
1.2401 + -1 == last_repeat ? ""
1.2402 + : 0 == last_repeat ? "\", " : ", ",
1.2403 + chstr, repeat);
1.2404 +
1.2405 + last = pwc;
1.2406 +
1.2407 + any_repeats = true;
1.2408 + last_repeat = repeat;
1.2409 + }
1.2410 + else {
1.2411 + // otherwise (if the last processed character repeats
1.2412 + // fewer than N times) format the character that many
1.2413 + // times
1.2414 +
1.2415 + if (last_repeat < 0) {
1.2416 + // opening quote
1.2417 + if (_RWSTD_WCHAR_T_SIZE == sizeof (charT)) {
1.2418 + *s++ = 'L';
1.2419 + }
1.2420 + *s++ = '\"';
1.2421 + }
1.2422 + else if (last_repeat > 0) {
1.2423 + *s++ = ',';
1.2424 + *s++ = ' ';
1.2425 + *s++ = '\"';
1.2426 + }
1.2427 +
1.2428 + rw_quotechar (chstr, *last, noesc);
1.2429 +
1.2430 + while (last != pwc) {
1.2431 + s += sprintf (s, "%s", chstr);
1.2432 + ++last;
1.2433 + }
1.2434 +
1.2435 + last_repeat = 0;
1.2436 +
1.2437 + if (size_t (pwc - wstr) == nchars) {
1.2438 + if (!noesc)
1.2439 + *s++ = '\"';
1.2440 + *s = '\0';
1.2441 + break;
1.2442 + }
1.2443 + }
1.2444 +
1.2445 + if (size_t (pwc - wstr) == nchars)
1.2446 + break;
1.2447 + }
1.2448 +
1.2449 + if (any_repeats) {
1.2450 + const size_t len = strlen (next);
1.2451 + memmove (next + 2, next, len);
1.2452 + next [0] = '{';
1.2453 + next [1] = ' ';
1.2454 + next [len + 2] = ' ';
1.2455 + next [len + 3] = '}';
1.2456 + next [len + 4] = '\0';
1.2457 + s = next + len + 4;
1.2458 + }
1.2459 +
1.2460 + return int (s - bufend);
1.2461 +#endif
1.2462 +}
1.2463 +
1.2464 +/********************************************************************/
1.2465 +
1.2466 +static int
1.2467 +_rw_fmtchr (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
1.2468 +{
1.2469 + typedef unsigned char UChar;
1.2470 + const UChar uc = UChar (val);
1.2471 +
1.2472 + char buffer [8];
1.2473 + int len = rw_quotechar (buffer + spec.fl_pound, uc, !spec.fl_pound);
1.2474 + if (spec.fl_pound) {
1.2475 + buffer [0] = buffer [len + 1] = '\'';
1.2476 + buffer [len + 2] = '\0';
1.2477 + len += 2;
1.2478 + }
1.2479 +
1.2480 + FmtSpec newspec (spec);
1.2481 + newspec.fl_pound = 0;
1.2482 + return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (len));
1.2483 +}
1.2484 +
1.2485 +/********************************************************************/
1.2486 +
1.2487 +static int
1.2488 +_rw_fmtwchr (const FmtSpec &spec, char **pbuf, size_t *pbufsize, wint_t val)
1.2489 +{
1.2490 + const wchar_t wc = wchar_t (val);
1.2491 +
1.2492 + char buffer [16];
1.2493 + int len = rw_quotechar (buffer + 2 * spec.fl_pound, wc, !spec.fl_pound);
1.2494 + if (spec.fl_pound) {
1.2495 + buffer [0] = 'L';
1.2496 + buffer [1] = buffer [len + 2] = '\'';
1.2497 + buffer [len + 3] = '\0';
1.2498 + len += 3;
1.2499 + }
1.2500 +
1.2501 + FmtSpec newspec (spec);
1.2502 + newspec.fl_pound = 0;
1.2503 + return _rw_fmtstr (newspec, pbuf, pbufsize, buffer, size_t (len));
1.2504 +}
1.2505 +
1.2506 +/********************************************************************/
1.2507 +
1.2508 +static int
1.2509 +_rw_fmtstr (const FmtSpec &spec,
1.2510 + char **pbuf, size_t *pbufsize, const char *str, size_t len)
1.2511 +{
1.2512 + assert (1);
1.2513 + return 0;
1.2514 +#if 0
1.2515 + if (spec.fl_pound)
1.2516 + return rw_quotestr (spec, pbuf, pbufsize, str, len, 0);
1.2517 +
1.2518 + if (0 == str)
1.2519 + str = "(null)";
1.2520 +
1.2521 + if (0 > _RW::__rw_memattr (str, _RWSTD_SIZE_MAX, 0)) {
1.2522 +
1.2523 + const size_t buflen = *pbuf ? strlen (*pbuf) : 0;
1.2524 +
1.2525 + if (0 == _rw_bufcat (pbuf, pbufsize, "(invalid address ", 18))
1.2526 + return -1;
1.2527 +
1.2528 + FmtSpec newspec (spec);
1.2529 + newspec.fl_pound = 1;
1.2530 +
1.2531 + if (-1 == _rw_fmtptr (newspec, pbuf, pbufsize, str))
1.2532 + return -1;
1.2533 +
1.2534 + if (0 == _rw_bufcat (pbuf, pbufsize, ")", 2))
1.2535 + return -1;
1.2536 +
1.2537 + return int (strlen (*pbuf) - buflen);
1.2538 + }
1.2539 +
1.2540 + if (_RWSTD_SIZE_MAX == len)
1.2541 + len = strlen (str);
1.2542 +
1.2543 + // compute the minimum number of characters to be generated
1.2544 + if (-1 < spec.prec && size_t (spec.prec) < len)
1.2545 + len = size_t (spec.prec);
1.2546 +
1.2547 + // the number of generated characters depends on three variables:
1.2548 + // -- the optional field width,
1.2549 + // -- the optional precision, and
1.2550 + // -- the length of the argument
1.2551 +
1.2552 + // compute the field width
1.2553 + const size_t width =
1.2554 + -1 < spec.width && len < size_t (spec.width) ?
1.2555 + size_t (spec.width) : len;
1.2556 +
1.2557 + // compute the size of padding
1.2558 + const size_t pad = len < width ? width - len : 0;
1.2559 +
1.2560 + // [re]allocate enough space in the buffer
1.2561 + if (0 == _rw_bufcat (pbuf, pbufsize, 0, pad + len))
1.2562 + return -1;
1.2563 +
1.2564 + assert (0 != *pbuf);
1.2565 + char *next = *pbuf + strlen (*pbuf);
1.2566 +
1.2567 + if (!spec.fl_minus) {
1.2568 + for (size_t i = 0; i != pad; ++i)
1.2569 + *next++ = ' ';
1.2570 + }
1.2571 +
1.2572 + memcpy (next, str, len);
1.2573 + next += len;
1.2574 +
1.2575 + if (spec.fl_minus) {
1.2576 + for (size_t i = 0; i != pad; ++i)
1.2577 + *next++ = ' ';
1.2578 + }
1.2579 +
1.2580 + *next++ = '\0';
1.2581 +
1.2582 + return int (pad + len);
1.2583 +#endif
1.2584 +}
1.2585 +
1.2586 +/********************************************************************/
1.2587 +
1.2588 +static int
1.2589 +_rw_fmtwstr (const FmtSpec &spec,
1.2590 + char **pbuf, size_t *pbufsize, const wchar_t *wstr, size_t len)
1.2591 +{
1.2592 + return rw_quotestr (spec, pbuf, pbufsize, wstr, len, 1);
1.2593 +}
1.2594 +
1.2595 +/********************************************************************/
1.2596 +
1.2597 +struct Bitnames
1.2598 +{
1.2599 + const char *longname;
1.2600 + const char *name;
1.2601 + int bits;
1.2602 +};
1.2603 +
1.2604 +#define BITNAME(qual, name) { #qual "::" #name, #name, qual::name }
1.2605 +
1.2606 +static int
1.2607 +rw_bmpfmt (const FmtSpec&, char **pbuf, size_t *pbufsize,
1.2608 + const Bitnames bmap[], size_t size, int bits)
1.2609 +{
1.2610 + assert (0 != pbuf);
1.2611 +
1.2612 + char buffer [1024];
1.2613 + *buffer = '\0';
1.2614 +
1.2615 + // string to use when no bits are set
1.2616 + const char* all_clear = "0";
1.2617 +
1.2618 + for (size_t i = 0; i != size; ++i) {
1.2619 + if (bmap [i].bits) {
1.2620 + if ((bits & bmap [i].bits) == bmap [i].bits) {
1.2621 + strcat (*buffer ? strcat (buffer, " | ") : buffer,
1.2622 + bmap [i].name);
1.2623 + bits &= ~bmap [i].bits;
1.2624 + }
1.2625 + }
1.2626 + else {
1.2627 + // save the name of the constant to use for 0
1.2628 + all_clear = bmap [i].name;
1.2629 + }
1.2630 + }
1.2631 +
1.2632 + size_t buffersize;
1.2633 +
1.2634 + if ('\0' == *buffer) {
1.2635 + // no constant matched, format teh value either as a number
1.2636 + // or, when 0, using the all_clear name (see above)
1.2637 + if (bits)
1.2638 + sprintf (buffer, "%#x", bits);
1.2639 + else
1.2640 + strcpy (buffer, all_clear);
1.2641 +
1.2642 + buffersize = strlen (buffer) + 1;
1.2643 + }
1.2644 + else if (bits) {
1.2645 + buffersize = strlen (buffer) + 1;
1.2646 +
1.2647 + // verify that buffer wasn't overflowed
1.2648 + assert (buffersize <= sizeof buffer);
1.2649 +
1.2650 + char bitstr [32];
1.2651 + const int n = sprintf (bitstr, "%#x | ", bits);
1.2652 +
1.2653 + assert (0 < n);
1.2654 +
1.2655 + memmove (buffer + n, buffer, buffersize);
1.2656 + memcpy (buffer, bitstr, size_t (n));
1.2657 +
1.2658 + buffersize += n;
1.2659 + }
1.2660 + else {
1.2661 + buffersize = strlen (buffer) + 1;
1.2662 + }
1.2663 +
1.2664 + // verify that buffer wasn't overflowed
1.2665 + assert (buffersize <= sizeof buffer);
1.2666 +
1.2667 + if (0 == _rw_bufcat (pbuf, pbufsize, buffer, buffersize))
1.2668 + return -1;
1.2669 +
1.2670 + return int (buffersize);
1.2671 +}
1.2672 +
1.2673 +/********************************************************************/
1.2674 +
1.2675 +static int
1.2676 +rw_fmtflags (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int bits)
1.2677 +{
1.2678 + static const Bitnames names [] = {
1.2679 + BITNAME (std::ios, adjustfield),
1.2680 + BITNAME (std::ios, basefield),
1.2681 + BITNAME (std::ios, boolalpha),
1.2682 + BITNAME (std::ios, dec),
1.2683 + BITNAME (std::ios, fixed),
1.2684 + BITNAME (std::ios, hex),
1.2685 + BITNAME (std::ios, internal),
1.2686 + BITNAME (std::ios, left),
1.2687 + BITNAME (std::ios, oct),
1.2688 + BITNAME (std::ios, right),
1.2689 + BITNAME (std::ios, scientific),
1.2690 + BITNAME (std::ios, showbase),
1.2691 + BITNAME (std::ios, showpoint),
1.2692 + BITNAME (std::ios, showpos),
1.2693 + BITNAME (std::ios, skipws),
1.2694 + BITNAME (std::ios, unitbuf),
1.2695 + BITNAME (std::ios, uppercase),
1.2696 +
1.2697 +#ifndef _RWSTD_NO_EXT_BIN_IO
1.2698 +
1.2699 + // extension: produce binary output (similar to oct, dec, and hex)
1.2700 + BITNAME (std::ios, bin),
1.2701 +
1.2702 +#endif // _RWSTD_NO_EXT_BIN_IO
1.2703 +
1.2704 +#ifndef _RWSTD_NO_EXT_REENTRANT_IO
1.2705 +
1.2706 + // extension: allow unsychronized access to stream and/or its buffer
1.2707 + BITNAME (std::ios, nolock),
1.2708 + BITNAME (std::ios, nolockbuf)
1.2709 +
1.2710 +#endif // _RWSTD_NO_EXT_REENTRANT_IO
1.2711 +
1.2712 + };
1.2713 +
1.2714 + static const size_t count = sizeof names / sizeof *names;
1.2715 +
1.2716 + const int base = (bits >> _RWSTD_IOS_BASEOFF) & _RWSTD_IOS_BASEMASK;
1.2717 +
1.2718 + // zero out bits representingthe numeric base
1.2719 + bits &= ~(_RWSTD_IOS_BASEMASK << _RWSTD_IOS_BASEOFF);
1.2720 +
1.2721 + int len = rw_bmpfmt (spec, pbuf, pbufsize, names, count, bits);
1.2722 +
1.2723 + if (base && base != 8 && base != 10 && base != 16) {
1.2724 +
1.2725 + // for numeric bases other than those required by the standard,
1.2726 + // use the text "base (%d)" to show the extended numeric base
1.2727 +
1.2728 +#ifndef _RWSTD_NO_EXT_BIN_IO
1.2729 +
1.2730 + if (bits & std::ios::bin)
1.2731 + return len;
1.2732 +
1.2733 +#endif // _RWSTD_NO_EXT_BIN_IO
1.2734 +
1.2735 + char basestr [64];
1.2736 + sprintf (basestr, " | std::ios::base(%d)", base);
1.2737 +
1.2738 + strcat (*pbuf, basestr);
1.2739 +
1.2740 + len = int (strlen (*pbuf));
1.2741 + }
1.2742 +
1.2743 + return len;
1.2744 +}
1.2745 +
1.2746 +/********************************************************************/
1.2747 +
1.2748 +static int
1.2749 +rw_fmtiostate (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int bits)
1.2750 +{
1.2751 + static const Bitnames names [] = {
1.2752 + BITNAME (std::ios, goodbit),
1.2753 + BITNAME (std::ios, badbit),
1.2754 + BITNAME (std::ios, eofbit),
1.2755 + BITNAME (std::ios, failbit)
1.2756 + };
1.2757 +
1.2758 + static const size_t count = sizeof names / sizeof *names;
1.2759 +
1.2760 + return rw_bmpfmt (spec, pbuf, pbufsize, names, count, bits);
1.2761 +}
1.2762 +
1.2763 +/********************************************************************/
1.2764 +
1.2765 +static int
1.2766 +_rw_fmtopenmode (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int bits)
1.2767 +{
1.2768 + static const Bitnames names [] = {
1.2769 +
1.2770 +#ifndef __SYMBIAN32__
1.2771 +
1.2772 +#ifndef _RWSTD_NO_EXTENSIONS
1.2773 +
1.2774 + { "std::ios::nocreate", "nocreate", std::ios::nocreate },
1.2775 + { "std::ios::noreplace", "noreplace", std::ios::noreplace },
1.2776 +
1.2777 +#else // if defined (_RWSTD_NO_EXTENSIONS)
1.2778 +
1.2779 + { "__rw:::__rw_nocreate", "__rw_nocreate", _RW::__rw_nocreate },
1.2780 + { "__rw::__rw_noreplace", "__rw_noreplace", _RW::__rw_noreplace },
1.2781 +
1.2782 +#endif // _RWSTD_NO_EXTENSIONS
1.2783 +
1.2784 +#ifndef _RWSTD_NO_EXT_STDIO
1.2785 +
1.2786 + { "std::ios::stdio", "stdio", std::ios::stdio },
1.2787 + { "std::ios::native", "native", std::ios::native },
1.2788 +
1.2789 +#else // if defined (_RWSTD_NO_EXT_STDIO)
1.2790 +
1.2791 + { "__rw::__rw_stdio", "__rw_stdio", _RW::__rw_stdio },
1.2792 + { "__rw::__rw_native", "__rw_native", _RW::__rw_native },
1.2793 +
1.2794 +#endif // _RWSTD_NO_EXT_STDIO
1.2795 +#endif
1.2796 + BITNAME (std::ios, app),
1.2797 + BITNAME (std::ios, binary),
1.2798 + BITNAME (std::ios, in),
1.2799 + BITNAME (std::ios, out),
1.2800 + BITNAME (std::ios, trunc),
1.2801 + BITNAME (std::ios, ate)
1.2802 + };
1.2803 +
1.2804 + static const size_t count = sizeof names / sizeof *names;
1.2805 +
1.2806 + return rw_bmpfmt (spec, pbuf, pbufsize, names, count, bits);
1.2807 +}
1.2808 +
1.2809 +/********************************************************************/
1.2810 +
1.2811 +static int
1.2812 +_rw_fmtevent (const FmtSpec&, char **pbuf, size_t *pbufsize, int event)
1.2813 +{
1.2814 + const char* str =
1.2815 + std::ios::copyfmt_event == event ? "copyfmt_event"
1.2816 + : std::ios::imbue_event == event ? "imbue_event"
1.2817 + : std::ios::erase_event == event ? "erase_event"
1.2818 + : 0;
1.2819 +
1.2820 + char buffer [64];
1.2821 +
1.2822 + if (!str) {
1.2823 + sprintf (buffer, "copyfmt_event(%d)", event);
1.2824 + str = buffer;
1.2825 + }
1.2826 +
1.2827 + const size_t len = strlen (str);
1.2828 +
1.2829 + if (0 == _rw_bufcat (pbuf, pbufsize, str, len))
1.2830 + return -1;
1.2831 +
1.2832 + return int (len);
1.2833 +}
1.2834 +
1.2835 +/********************************************************************/
1.2836 +
1.2837 +static int
1.2838 +rw_fmtlc (const FmtSpec &spec, char **pbuf, size_t *pbufsize, int val)
1.2839 +{
1.2840 + const char *str = 0;
1.2841 +
1.2842 + switch (val) {
1.2843 + case LC_ALL: str = "LC_ALL"; break;
1.2844 + case LC_COLLATE: str = "LC_COLLATE"; break;
1.2845 + case LC_CTYPE: str = "LC_CTYPE"; break;
1.2846 + case LC_MONETARY: str = "LC_MONETARY"; break;
1.2847 + case LC_NUMERIC: str = "LC_NUMERIC"; break;
1.2848 + case LC_TIME: str = "LC_TIME"; break;
1.2849 +
1.2850 +#ifdef LC_MESSAGES
1.2851 + case LC_MESSAGES: str = "LC_MESSAGES"; break;
1.2852 +#endif // LC_MESSAGES
1.2853 +
1.2854 + }
1.2855 +
1.2856 + if (str) {
1.2857 + const std::size_t len = strlen (str);
1.2858 +
1.2859 + if (0 == _rw_bufcat (pbuf, pbufsize, str, len))
1.2860 + return -1;
1.2861 +
1.2862 + return int (len);
1.2863 + }
1.2864 +
1.2865 + static const Bitnames names [] = {
1.2866 + BITNAME (std::locale, all),
1.2867 + BITNAME (std::locale, none),
1.2868 + BITNAME (std::locale, collate),
1.2869 + BITNAME (std::locale, ctype),
1.2870 + BITNAME (std::locale, monetary),
1.2871 + BITNAME (std::locale, numeric),
1.2872 + BITNAME (std::locale, messages),
1.2873 + BITNAME (std::locale, time)
1.2874 + };
1.2875 +
1.2876 + static const size_t count = sizeof names / sizeof *names;
1.2877 +
1.2878 + return rw_bmpfmt (spec, pbuf, pbufsize, names, count, val);
1.2879 +}
1.2880 +
1.2881 +/********************************************************************/
1.2882 +
1.2883 +static int
1.2884 +_rw_fmtmonpat (const FmtSpec&,
1.2885 + char **pbuf, size_t *pbufsize, const char pat [4])
1.2886 +{
1.2887 + char buffer [80];
1.2888 +
1.2889 + buffer [0] = '\0';
1.2890 +
1.2891 + for (int i = 0; i != 4; ++i) {
1.2892 + switch (pat [i]) {
1.2893 + case std::money_base::symbol:
1.2894 + strcat (buffer, "symbol ");
1.2895 + break;
1.2896 +
1.2897 + case std::money_base::sign:
1.2898 + strcat (buffer, "sign ");
1.2899 + break;
1.2900 +
1.2901 + case std::money_base::none:
1.2902 + strcat (buffer, "none ");
1.2903 + break;
1.2904 +
1.2905 + case std::money_base::value:
1.2906 + strcat (buffer, "value ");
1.2907 + break;
1.2908 +
1.2909 + case std::money_base::space:
1.2910 + strcat (buffer, "space ");
1.2911 + break;
1.2912 +
1.2913 + default:
1.2914 + sprintf (buffer + strlen (buffer), "\\%03o", pat [i]);
1.2915 + break;
1.2916 + }
1.2917 + }
1.2918 +
1.2919 + const size_t len = strlen (buffer);
1.2920 +
1.2921 + if (0 == _rw_bufcat (pbuf, pbufsize, buffer, len))
1.2922 + return -1;
1.2923 +
1.2924 + return int (len);
1.2925 +}
1.2926 +
1.2927 +/********************************************************************/
1.2928 +
1.2929 +static int
1.2930 +libstd_vasnprintf (FmtSpec *pspec, size_t paramno,
1.2931 + char **pbuf, size_t *pbufsize,
1.2932 + const char *fmt, va_list *pva)
1.2933 +{
1.2934 + assert (0 != pva);
1.2935 + assert (0 != pspec);
1.2936 +
1.2937 + _RWSTD_UNUSED (fmt);
1.2938 +
1.2939 + FmtSpec &spec = pspec [paramno];
1.2940 +
1.2941 + // the length of the sequence appended to the buffer to return
1.2942 + // to the caller, or a negative value (such as -1) on error
1.2943 + int len = -1;
1.2944 +
1.2945 + switch (spec.cvtspec) {
1.2946 +
1.2947 + case '?': // %{?}
1.2948 + // beginning of an if clause
1.2949 + spec.cond = 1;
1.2950 + spec.cond_begin = 1;
1.2951 + spec.cond_true = 0 != va_arg (*pva, int);
1.2952 + len = 0;
1.2953 + break;
1.2954 +
1.2955 + case ':': // %{:}
1.2956 + if (spec.cond) {
1.2957 + // end of an active if clause and the beginning
1.2958 + // of an inactive else clause
1.2959 +
1.2960 + spec.cond_begin = 1; // beginning of an else clause
1.2961 + spec.cond_end = 1; // end of an if clause
1.2962 + spec.cond_true = !spec.cond_true;
1.2963 + len = 0;
1.2964 + }
1.2965 + else {
1.2966 + // misplaced "%{:}"?
1.2967 + static const char str[] = "%{:}";
1.2968 + len = rw_quotestr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX, 0);
1.2969 + }
1.2970 + break;
1.2971 +
1.2972 + case ';': // %{;}
1.2973 + if (spec.cond) {
1.2974 + spec.cond_end = 1; // end of an if or else clause
1.2975 + len = 0;
1.2976 + }
1.2977 + else {
1.2978 + // misplaced "%{;}"?
1.2979 + static const char str[] = "%{;}";
1.2980 + len = rw_quotestr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX, 0);
1.2981 + }
1.2982 + break;
1.2983 +
1.2984 + case 'c': // %{c}, %{Ac}, %{Lc}, %{lc}
1.2985 + if (spec.mod_A) {
1.2986 + if (-1 == spec.width || 1 == spec.width) {
1.2987 + spec.param.ptr = PARAM (_RWSTD_UINT8_T*, ptr);
1.2988 + const _RWSTD_UINT8_T* const array =
1.2989 + (_RWSTD_UINT8_T*)spec.param.ptr;
1.2990 + len = rw_quotestr (spec, pbuf, pbufsize, array,
1.2991 + _RWSTD_SIZE_MAX, 0);
1.2992 + }
1.2993 + else if (2 == spec.width) {
1.2994 + spec.param.ptr = PARAM (_RWSTD_UINT16_T*, ptr);
1.2995 + const _RWSTD_UINT16_T* const array =
1.2996 + (_RWSTD_UINT16_T*)spec.param.ptr;
1.2997 + len = rw_quotestr (spec, pbuf, pbufsize, array,
1.2998 + _RWSTD_SIZE_MAX, 0);
1.2999 + }
1.3000 + else if (4 == spec.width) {
1.3001 + spec.param.ptr = PARAM (_RWSTD_UINT32_T*, ptr);
1.3002 + const _RWSTD_UINT32_T* const array =
1.3003 + (_RWSTD_UINT32_T*)spec.param.ptr;
1.3004 + len = rw_quotestr (spec, pbuf, pbufsize, array,
1.3005 + _RWSTD_SIZE_MAX, 0);
1.3006 + }
1.3007 +
1.3008 +#ifdef _RWSTD_UINT64_T
1.3009 +
1.3010 + else if (8 == spec.width) {
1.3011 + spec.param.ptr = PARAM (_RWSTD_UINT64_T*, ptr);
1.3012 + const _RWSTD_UINT64_T* const array =
1.3013 + (_RWSTD_UINT64_T*)spec.param.ptr;
1.3014 + len = rw_quotestr (spec, pbuf, pbufsize, array,
1.3015 + _RWSTD_SIZE_MAX, 0);
1.3016 + }
1.3017 +
1.3018 +#endif // _RWSTD_UINT64_T
1.3019 +
1.3020 + else {
1.3021 + assert (!"%{Ac} not implemented for this character size");
1.3022 + }
1.3023 + }
1.3024 + else if (spec.mod_L) { // locale category or LC_XXX constant
1.3025 + spec.param.i = PARAM (int, i);
1.3026 + len = rw_fmtlc (spec, pbuf, pbufsize, spec.param.i);
1.3027 + }
1.3028 + else if (spec.mod_l) { // wchar_t
1.3029 + spec.param.wi = PARAM (wint_t, i);
1.3030 + return _rw_fmtwchr (spec, pbuf, pbufsize, spec.param.wi);
1.3031 + }
1.3032 + else { // char
1.3033 + spec.param.i = PARAM (int, i);
1.3034 + return _rw_fmtchr (spec, pbuf, pbufsize, spec.param.i);
1.3035 + }
1.3036 + break;
1.3037 +
1.3038 + case 'e': // %{e}, %{Ae}
1.3039 + if (spec.mod_A) { // array of floating point values
1.3040 + spec.param.ptr = PARAM (void*, ptr);
1.3041 + len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr);
1.3042 + }
1.3043 + else if (spec.mod_I) { // ios::copyfmt_event
1.3044 + spec.param.i = PARAM (int, i);
1.3045 + len = _rw_fmtevent (spec, pbuf, pbufsize, spec.param.i);
1.3046 + }
1.3047 + break;
1.3048 +
1.3049 + case 'f': // %{f}, %{Af}, %{If}
1.3050 + if (spec.mod_A) { // array of floating point values
1.3051 + spec.param.ptr = PARAM (void*, ptr);
1.3052 + len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr);
1.3053 + }
1.3054 + if (spec.mod_I) { // ios::fmtflags
1.3055 + spec.param.i = PARAM (int, i);
1.3056 + len = rw_fmtflags (spec, pbuf, pbufsize, spec.param.i);
1.3057 + }
1.3058 + else { // function pointer
1.3059 + spec.param.funptr = PARAM (funptr_t, funptr);
1.3060 + len = _rw_fmtfunptr (spec, pbuf, pbufsize, spec.param.funptr);
1.3061 + }
1.3062 + break;
1.3063 +
1.3064 + case 'g': // %{g}, %{Ag}
1.3065 + if (spec.mod_A) { // array of floating point values
1.3066 + spec.param.ptr = PARAM (void*, ptr);
1.3067 + len = _rw_fmtfloating (spec, pbuf, pbufsize, spec.param.ptr);
1.3068 + }
1.3069 + else {
1.3070 + assert (!"%{g} not implemented");
1.3071 + }
1.3072 +
1.3073 + case 'd': // %{Id}
1.3074 + case 'i': // %{Ii}
1.3075 + case 'o': // %{Io}
1.3076 + if (spec.mod_I) { // ios::openmode
1.3077 + spec.param.i = PARAM (int, i);
1.3078 + len = _rw_fmtopenmode (spec, pbuf, pbufsize, spec.param.i);
1.3079 + break;
1.3080 + }
1.3081 + case 'x': // %{x}
1.3082 + case 'X': // %{X}
1.3083 + case 'u': // %{u}
1.3084 + len = _rw_fmtinteger (pspec, paramno, pbuf, pbufsize, pva);
1.3085 + break;
1.3086 +
1.3087 + case 'K': // %{K} -- signal
1.3088 + spec.param.i = PARAM (int, i);
1.3089 + len = _rw_fmtsignal (spec, pbuf, pbufsize, spec.param.i);
1.3090 + break;
1.3091 +
1.3092 + case 'm': // %{m} -- errno
1.3093 + if (-1 == spec.width)
1.3094 + len = _rw_fmterrno (spec, pbuf, pbufsize, errno);
1.3095 + else
1.3096 + len = _rw_fmterrno (spec, pbuf, pbufsize, spec.width);
1.3097 + break;
1.3098 +
1.3099 + case 'M': // %{M}, %{LM}
1.3100 + if (spec.mod_L) { // money_base::pattern
1.3101 + spec.param.ptr = PARAM (char*, ptr);
1.3102 + len = _rw_fmtmonpat (spec, pbuf, pbufsize, (char*)spec.param.ptr);
1.3103 + }
1.3104 + else { // member pointer
1.3105 + spec.param.memptr = PARAM (memptr_t, memptr);
1.3106 + len = _rw_fmtmemptr (spec, pbuf, pbufsize, spec.param.memptr);
1.3107 + }
1.3108 + break;
1.3109 +
1.3110 + case 'n': { // %{n}
1.3111 + // The argument shall be a pointer to signed integer into which
1.3112 + // is written the size of the buffer allocated by this call to
1.3113 + // fprintf. No argument is converted, but one is consumed. If
1.3114 + // the conversion specification includes any flags, a field
1.3115 + // width, or a precision, the behavior is undefined.
1.3116 +
1.3117 + assert (0 != pbuf);
1.3118 + assert (0 != *pbuf);
1.3119 +
1.3120 + const size_t nbytes = pbufsize ? *pbufsize : 0;
1.3121 +
1.3122 + spec.param.ptr = PARAM (void*, ptr);
1.3123 +
1.3124 + if (spec.mod_hh) {
1.3125 + unsigned char* const ptr = (unsigned char*)spec.param.ptr;
1.3126 +
1.3127 + assert (0 != ptr);
1.3128 +
1.3129 + *ptr = (unsigned char)nbytes;
1.3130 + }
1.3131 + else if (spec.mod_h) {
1.3132 + short* const ptr = (short*)spec.param.ptr;
1.3133 +
1.3134 + assert (0 != ptr);
1.3135 +
1.3136 + *ptr = short (nbytes);
1.3137 + }
1.3138 + else if (spec.mod_L) {
1.3139 +#ifdef _RWSTD_LONG_LONG
1.3140 + _RWSTD_LONG_LONG* const ptr = (_RWSTD_LONG_LONG*)spec.param.ptr;
1.3141 +
1.3142 + assert (0 != ptr);
1.3143 +
1.3144 + *ptr = (_RWSTD_LONG_LONG)(nbytes);
1.3145 +#else // if !defined (_RWSTD_LONG_LONG)
1.3146 + assert (!"%{Ln} not implemented");
1.3147 +#endif // _RWSTD_LONG_LONG
1.3148 + }
1.3149 + else if (spec.mod_l) {
1.3150 + long* const ptr = (long*)spec.param.ptr;
1.3151 +
1.3152 + assert (0 != ptr);
1.3153 +
1.3154 + *ptr = long (nbytes);
1.3155 + }
1.3156 + else if (spec.mod_t) {
1.3157 + ptrdiff_t* const ptr = (ptrdiff_t*)spec.param.ptr;
1.3158 +
1.3159 + assert (0 != ptr);
1.3160 +
1.3161 + *ptr = ptrdiff_t (nbytes);
1.3162 + }
1.3163 + else {
1.3164 + int* const ptr = (int*)spec.param.ptr;
1.3165 +
1.3166 + assert (0 != ptr);
1.3167 +
1.3168 + *ptr = int (nbytes);
1.3169 + }
1.3170 + len = 0;
1.3171 + break;
1.3172 + }
1.3173 +
1.3174 + case 's': // %{s}, %{Is}, %{ls}
1.3175 + if (spec.mod_I) { // ios::iostate
1.3176 + spec.param.i = PARAM (int, i);
1.3177 + len = rw_fmtiostate (spec, pbuf, pbufsize, spec.param.i);
1.3178 + }
1.3179 + else if (spec.mod_l) { // wchar_t*
1.3180 + spec.param.ptr = PARAM (wchar_t*, ptr);
1.3181 + const wchar_t* const wstr = (wchar_t*)spec.param.ptr;
1.3182 + len = rw_quotestr (spec, pbuf, pbufsize, wstr, _RWSTD_SIZE_MAX, 0);
1.3183 + }
1.3184 + else { // char*
1.3185 + spec.param.ptr = PARAM (char*, ptr);
1.3186 + const char* const str = (char*)spec.param.ptr;
1.3187 + len = rw_quotestr (spec, pbuf, pbufsize, str, _RWSTD_SIZE_MAX, 0);
1.3188 + }
1.3189 + break;
1.3190 +
1.3191 + case 'S': // %{S}, %{lS}
1.3192 + if (spec.mod_l) { // std::wstring
1.3193 + spec.param.ptr = PARAM (std::wstring*, ptr);
1.3194 +
1.3195 + const std::wstring* const pstr = (std::wstring*)spec.param.ptr;
1.3196 + const wchar_t* const wstr = pstr->data ();
1.3197 + const std::wstring::size_type size = pstr->size ();
1.3198 +
1.3199 + len = _rw_fmtwstr (spec, pbuf, pbufsize, wstr, size);
1.3200 + }
1.3201 + else { // std::string
1.3202 + spec.param.ptr = PARAM (std::string*, ptr);
1.3203 +
1.3204 + const std::string* const pstr = (std::string*)spec.param.ptr;
1.3205 + const char* const str = pstr->data ();
1.3206 + const std::string::size_type size = pstr->size ();
1.3207 +
1.3208 + len = _rw_fmtstr (spec, pbuf, pbufsize, str, size);
1.3209 + }
1.3210 + break;
1.3211 +
1.3212 + default:
1.3213 + if (spec.strarg) {
1.3214 + // environment variable
1.3215 + const char* val = getenv (spec.strarg);
1.3216 +
1.3217 + if (!val)
1.3218 + val = "";
1.3219 +
1.3220 + len = int (strlen (val));
1.3221 +
1.3222 + if (0 == _rw_bufcat (pbuf, pbufsize, val, size_t (len)))
1.3223 + return -1;
1.3224 +
1.3225 + free (spec.strarg);
1.3226 + }
1.3227 + else {
1.3228 + assert (!"not implemented");
1.3229 + }
1.3230 + }
1.3231 +
1.3232 + return len;
1.3233 +}
1.3234 +
1.3235 +/********************************************************************/
1.3236 +
1.3237 +/* extern */ int
1.3238 +(*rw_vasnprintf_cb)(FmtSpec*, size_t, char**, size_t*, const char*, va_list*)
1.3239 + = libstd_vasnprintf;
1.3240 +
1.3241 +/********************************************************************/
1.3242 +
1.3243 +_TEST_EXPORT int
1.3244 +rw_asnprintf (char **pbuf, size_t *pbufsize, const char *fmt, ...)
1.3245 +{
1.3246 + assert (0 == pbuf || 0 == *pbuf || pbufsize);
1.3247 +
1.3248 + va_list va;
1.3249 + va_start (va, fmt);
1.3250 +
1.3251 + char* buf = 0;
1.3252 + size_t bufsize = 0;
1.3253 +
1.3254 + if (0 == pbuf) {
1.3255 + // if pbyf is 0 (i.e., this is a request for the size of the
1.3256 + // buffer necessary to format all the arguments), set pbuf to
1.3257 + // point to a local buf
1.3258 + pbuf = &buf;
1.3259 + }
1.3260 +
1.3261 + if (0 == pbufsize) {
1.3262 + // pbuf may be 0 regardless of the value of pbuf
1.3263 + pbufsize = &bufsize;
1.3264 + }
1.3265 +
1.3266 + const int nchars = rw_vasnprintf (pbuf, pbufsize, fmt, va);
1.3267 +
1.3268 + va_end (va);
1.3269 +
1.3270 + // verify that the length of the fomatted buffer is less than
1.3271 + // its size (this test is unreliable if there are any embedded
1.3272 + // NULs in the output)
1.3273 + assert (nchars < 0 || strlen (*pbuf) < *pbufsize);
1.3274 +
1.3275 + if (pbuf == &buf) {
1.3276 + // free the character buffer if pbuf was initially 0
1.3277 + free (pbuf);
1.3278 + }
1.3279 +
1.3280 + return nchars;
1.3281 +}
1.3282 +
1.3283 +/********************************************************************/
1.3284 +
1.3285 +_TEST_EXPORT char*
1.3286 +rw_snprintfa (char *buf, size_t bufsize, const char* fmt, ...)
1.3287 +{
1.3288 + if (buf)
1.3289 + *buf = '\0';
1.3290 +
1.3291 + va_list va;
1.3292 + va_start (va, fmt);
1.3293 +
1.3294 + const int nchars = rw_vasnprintf (&buf, &bufsize, fmt, va);
1.3295 +
1.3296 + va_end (va);
1.3297 +
1.3298 + // verify that the length of the fomatted buffer is less than
1.3299 + // its size (this test is unreliable if there are any embedded
1.3300 + // NULs in the output)
1.3301 + assert (nchars < 0 || strlen (buf) < bufsize);
1.3302 +
1.3303 + _RWSTD_UNUSED (nchars);
1.3304 +
1.3305 + return buf;
1.3306 +}
1.3307 +
1.3308 +/********************************************************************/
1.3309 +
1.3310 +_TEST_EXPORT char*
1.3311 +rw_sprintfa (const char *fmt, ...)
1.3312 +{
1.3313 + char* buf = 0;
1.3314 + size_t bufsize = 0;
1.3315 +
1.3316 + va_list va;
1.3317 + va_start (va, fmt);
1.3318 +
1.3319 + const int nchars = rw_vasnprintf (&buf, &bufsize, fmt, va);
1.3320 +
1.3321 + va_end (va);
1.3322 +
1.3323 + // verify that the length of the fomatted buffer is less than
1.3324 + // its size (this test is unreliable if there are any embedded
1.3325 + // NULs in the output)
1.3326 + assert (nchars < 0 || strlen (buf) < bufsize);
1.3327 +
1.3328 + _RWSTD_UNUSED (nchars);
1.3329 +
1.3330 + return buf;
1.3331 +}
1.3332 +
1.3333 +
1.3334 +/********************************************************************/
1.3335 +
1.3336 +// avoid re-declaring these as exported here and instead rely on the
1.3337 +// declaration in the header #included above in order to prevent the
1.3338 +// bogus MSVC error:
1.3339 +// error C2201: 'rw_stdout' : must have external linkage in order to
1.3340 +// be exported/imported
1.3341 +
1.3342 +/* _TEST_EXPORT */ rw_file* const
1.3343 +rw_stdout = _RWSTD_REINTERPRET_CAST (rw_file*, stdout);
1.3344 +
1.3345 +/* _TEST_EXPORT */ rw_file* const
1.3346 +rw_stderr = _RWSTD_REINTERPRET_CAST (rw_file*, stderr);
1.3347 +
1.3348 +/********************************************************************/
1.3349 +
1.3350 +static int
1.3351 +_rw_vfprintf (rw_file *file, const char *fmt, va_list va)
1.3352 +{
1.3353 + assert (0 != file);
1.3354 +
1.3355 + char* buf = 0;
1.3356 + size_t bufsize = 0;
1.3357 +
1.3358 + const int nchars = rw_vasnprintf (&buf, &bufsize, fmt, va);
1.3359 +
1.3360 + // FIXME: implement this in terms of POSIX write()
1.3361 + // for async-signal safety
1.3362 + FILE* const stdio_file = _RWSTD_REINTERPRET_CAST (FILE*, file);
1.3363 +
1.3364 + const int nwrote = 0 < nchars ?
1.3365 + fwrite (buf, 1, nchars, stdio_file) : nchars;
1.3366 +
1.3367 + // flush in case stderr isn't line-buffered (e.g., when
1.3368 + // it's determined not to refer to a terminal device,
1.3369 + // for example after it has been redirected to a file)
1.3370 + fflush (stdio_file);
1.3371 +
1.3372 +#ifdef _MSC_VER
1.3373 +
1.3374 + // IsDebuggerPresent() depends on the macros _WIN32_WINNT and WINVER
1.3375 + // being appropriately #defined prior to the #inclusion of <windows.h>
1.3376 + if (IsDebuggerPresent ()) {
1.3377 +
1.3378 + // write string to the attached debugger (if any)
1.3379 + OutputDebugString (buf);
1.3380 + }
1.3381 +
1.3382 +#endif // _MSC_VER
1.3383 +
1.3384 + free (buf);
1.3385 +
1.3386 + return nwrote;
1.3387 +}
1.3388 +
1.3389 +/********************************************************************/
1.3390 +
1.3391 +_TEST_EXPORT int
1.3392 +rw_fprintf (rw_file *file, const char *fmt, ...)
1.3393 +{
1.3394 + va_list va;
1.3395 + va_start (va, fmt);
1.3396 +
1.3397 + const int nchars = _rw_vfprintf (file, fmt, va);
1.3398 +
1.3399 + va_end (va);
1.3400 +
1.3401 + return nchars;
1.3402 +}
1.3403 +
1.3404 +/********************************************************************/
1.3405 +
1.3406 +_TEST_EXPORT int
1.3407 +rw_printf (const char *fmt, ...)
1.3408 +{
1.3409 + va_list va;
1.3410 + va_start (va, fmt);
1.3411 +
1.3412 + const int nchars = _rw_vfprintf (rw_stdout, fmt, va);
1.3413 +
1.3414 + va_end (va);
1.3415 +
1.3416 + return nchars;
1.3417 +}