master
   1/* pformat.c
   2 *
   3 * $Id: pformat.c,v 1.9 2011/01/07 22:57:00 keithmarshall Exp $
   4 *
   5 * Provides a core implementation of the formatting capabilities
   6 * common to the entire `printf()' family of functions; it conforms
   7 * generally to C99 and SUSv3/POSIX specifications, with extensions
   8 * to support Microsoft's non-standard format specifications.
   9 *
  10 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
  11 *
  12 * This is free software.  You may redistribute and/or modify it as you
  13 * see fit, without restriction of copyright.
  14 *
  15 * This software is provided "as is", in the hope that it may be useful,
  16 * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
  17 * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE.  At no
  18 * time will the author accept any form of liability for any damages,
  19 * however caused, resulting from the use of this software.
  20 *
  21 * The elements of this implementation which deal with the formatting
  22 * of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g'
  23 * and `%G' format specifiers, but excluding the hexadecimal floating
  24 * point `%a' and `%A' specifiers), make use of the `__gdtoa' function
  25 * written by David M. Gay, and are modelled on his sample code, which
  26 * has been deployed under its accompanying terms of use:--
  27 *
  28 ******************************************************************
  29 * Copyright (C) 1997, 1999, 2001 Lucent Technologies
  30 * All Rights Reserved
  31 *
  32 * Permission to use, copy, modify, and distribute this software and
  33 * its documentation for any purpose and without fee is hereby
  34 * granted, provided that the above copyright notice appear in all
  35 * copies and that both that the copyright notice and this
  36 * permission notice and warranty disclaimer appear in supporting
  37 * documentation, and that the name of Lucent or any of its entities
  38 * not be used in advertising or publicity pertaining to
  39 * distribution of the software without specific, written prior
  40 * permission.
  41 *
  42 * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  44 * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
  45 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  47 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  48 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
  49 * THIS SOFTWARE.
  50 ******************************************************************
  51 *
  52 */
  53
  54#define __LARGE_MBSTATE_T
  55
  56#ifdef HAVE_CONFIG_H
  57#include "config.h"
  58#endif
  59
  60#include <stdio.h>
  61#include <stdarg.h>
  62#include <stddef.h>
  63#include <stdint.h>
  64#include <stdlib.h>
  65#include <string.h>
  66#include <limits.h>
  67#include <locale.h>
  68#include <wchar.h>
  69
  70#ifdef __ENABLE_DFP
  71#ifndef __STDC_WANT_DEC_FP__
  72#define __STDC_WANT_DEC_FP__ 1
  73#endif
  74
  75#include "../math/DFP/dfp_internal.h"
  76#endif /* __ENABLE_DFP */
  77
  78#include <math.h>
  79
  80/* FIXME: The following belongs in values.h, but current MinGW
  81 * has nothing useful there!  OTOH, values.h is not a standard
  82 * header, and its use may be considered obsolete; perhaps it
  83 * is better to just keep these definitions here.
  84 */
  85
  86#include <pshpack1.h>
  87/* workaround gcc bug */
  88#if defined(__GNUC__) && !defined(__clang__)
  89#define ATTRIB_GCC_STRUCT __attribute__((gcc_struct))
  90#else
  91#define ATTRIB_GCC_STRUCT
  92#endif
  93typedef struct ATTRIB_GCC_STRUCT __tI128 {
  94  int64_t digits[2];
  95} __tI128;
  96
  97typedef struct ATTRIB_GCC_STRUCT __tI128_2 {
  98  uint32_t digits32[4];
  99} __tI128_2;
 100
 101typedef union ATTRIB_GCC_STRUCT __uI128 {
 102  __tI128 t128;
 103  __tI128_2 t128_2;
 104} __uI128;
 105#include <poppack.h>
 106
 107#ifndef _VALUES_H
 108/*
 109 * values.h
 110 *
 111 */
 112#define _VALUES_H
 113
 114#include <limits.h>
 115
 116#define _TYPEBITS(type)     (sizeof(type) * CHAR_BIT)
 117
 118#if defined(__ENABLE_PRINTF128) || defined(__ENABLE_DFP)
 119#define LLONGBITS           _TYPEBITS(__tI128)
 120#else
 121#define LLONGBITS           _TYPEBITS(long long)
 122#endif
 123
 124#endif /* !defined _VALUES_H -- end of file */
 125
 126#include "mingw_pformat.h"
 127
 128/* Bit-map constants, defining the internal format control
 129 * states, which propagate through the flags.
 130 */
 131#define PFORMAT_GROUPED     0x00001000
 132#define PFORMAT_HASHED      0x00000800
 133#define PFORMAT_LJUSTIFY    0x00000400
 134#define PFORMAT_ZEROFILL    0x00000200
 135
 136#define PFORMAT_JUSTIFY    (PFORMAT_LJUSTIFY | PFORMAT_ZEROFILL)
 137#define PFORMAT_IGNORE      -1
 138
 139#define PFORMAT_SIGNED      0x000001C0
 140#define PFORMAT_POSITIVE    0x00000100
 141#define PFORMAT_NEGATIVE    0x00000080
 142#define PFORMAT_ADDSPACE    0x00000040
 143
 144#define PFORMAT_XCASE       0x00000020
 145
 146#define PFORMAT_LDOUBLE     0x00000004
 147
 148#ifdef __ENABLE_DFP
 149#define PFORMAT_DECIM32     0x00020000
 150#define PFORMAT_DECIM64     0x00040000
 151#define PFORMAT_DECIM128    0x00080000
 152#endif
 153
 154/* `%o' format digit extraction mask, and shift count...
 155 * (These are constant, and do not propagate through the flags).
 156 */
 157#define PFORMAT_OMASK       0x00000007
 158#define PFORMAT_OSHIFT      0x00000003
 159
 160/* `%x' and `%X' format digit extraction mask, and shift count...
 161 * (These are constant, and do not propagate through the flags).
 162 */
 163#define PFORMAT_XMASK       0x0000000F
 164#define PFORMAT_XSHIFT      0x00000004
 165
 166/* The radix point character, used in floating point formats, is
 167 * localised on the basis of the active LC_NUMERIC locale category.
 168 * It is stored locally, as a `wchar_t' entity, which is converted
 169 * to a (possibly multibyte) character on output.  Initialisation
 170 * of the stored `wchar_t' entity, together with a record of its
 171 * effective multibyte character length, is required each time
 172 * `__pformat()' is entered, (static storage would not be thread
 173 * safe), but this initialisation is deferred until it is actually
 174 * needed; on entry, the effective character length is first set to
 175 * the following value, (and the `wchar_t' entity is zeroed), to
 176 * indicate that a call of `localeconv()' is needed, to complete
 177 * the initialisation.
 178 */
 179#define PFORMAT_RPINIT      -3
 180
 181/* The floating point format handlers return the following value
 182 * for the radix point position index, when the argument value is
 183 * infinite, or not a number.
 184 */
 185#define PFORMAT_INFNAN      -32768
 186
 187typedef union
 188{
 189  /* A data type agnostic representation,
 190   * for printf arguments of any integral data type...
 191   */
 192  signed long             __pformat_long_t;
 193  signed long long        __pformat_llong_t;
 194  unsigned long           __pformat_ulong_t;
 195  unsigned long long      __pformat_ullong_t;
 196  unsigned short          __pformat_ushort_t;
 197  unsigned char           __pformat_uchar_t;
 198  signed short            __pformat_short_t;
 199  signed char             __pformat_char_t;
 200  void *                  __pformat_ptr_t;
 201  __uI128                 __pformat_u128_t;
 202} __pformat_intarg_t;
 203
 204typedef enum
 205{
 206  /* Format interpreter state indices...
 207   * (used to identify the active phase of format string parsing).
 208   */
 209  PFORMAT_INIT = 0,
 210  PFORMAT_SET_WIDTH,
 211  PFORMAT_GET_PRECISION,
 212  PFORMAT_SET_PRECISION,
 213  PFORMAT_END
 214} __pformat_state_t;
 215
 216typedef enum
 217{
 218  /* Argument length classification indices...
 219   * (used for arguments representing integer data types).
 220   */
 221  PFORMAT_LENGTH_INT = 0,
 222  PFORMAT_LENGTH_SHORT,
 223  PFORMAT_LENGTH_LONG,
 224  PFORMAT_LENGTH_LLONG,
 225  PFORMAT_LENGTH_LLONG128,
 226  PFORMAT_LENGTH_CHAR
 227} __pformat_length_t;
 228/*
 229 * And a macro to map any arbitrary data type to an appropriate
 230 * matching index, selected from those above; the compiler should
 231 * collapse this to a simple assignment.
 232 */
 233
 234#ifdef __GNUC__
 235/* provides for some deadcode elimination via compile time eval */
 236#define __pformat_arg_length(x) \
 237__builtin_choose_expr (                                         \
 238  __builtin_types_compatible_p (typeof (x), __tI128),           \
 239   PFORMAT_LENGTH_LLONG128,                                     \
 240    __builtin_choose_expr (                                     \
 241      __builtin_types_compatible_p (typeof (x), long long),     \
 242        PFORMAT_LENGTH_LLONG,                                   \
 243    __builtin_choose_expr (                                     \
 244      __builtin_types_compatible_p (typeof (x), long),          \
 245        PFORMAT_LENGTH_LONG,                                    \
 246    __builtin_choose_expr (                                     \
 247      __builtin_types_compatible_p (typeof (x), short),         \
 248        PFORMAT_LENGTH_SHORT,                                   \
 249    __builtin_choose_expr (                                     \
 250      __builtin_types_compatible_p (typeof (x), char),          \
 251        PFORMAT_LENGTH_CHAR,                                    \
 252    __builtin_choose_expr (                                     \
 253      __builtin_types_compatible_p (typeof (x), __uI128),       \
 254        PFORMAT_LENGTH_LLONG128,                                \
 255    __builtin_choose_expr (                                              \
 256      __builtin_types_compatible_p (typeof (x), unsigned long),          \
 257        PFORMAT_LENGTH_LONG,                                             \
 258    __builtin_choose_expr (                                              \
 259      __builtin_types_compatible_p (typeof (x), unsigned long long),     \
 260        PFORMAT_LENGTH_LLONG,                                            \
 261    __builtin_choose_expr (                                              \
 262      __builtin_types_compatible_p (typeof (x), unsigned short),         \
 263        PFORMAT_LENGTH_SHORT,                                            \
 264    __builtin_choose_expr (                                              \
 265      __builtin_types_compatible_p (typeof (x), unsigned char),          \
 266        PFORMAT_LENGTH_CHAR,                                             \
 267  PFORMAT_LENGTH_INT))))))))))
 268
 269#else
 270#define __pformat_arg_length( type )    \
 271  sizeof( type ) == sizeof( __tI128 )   ? PFORMAT_LENGTH_LLONG128 : \
 272  sizeof( type ) == sizeof( long long ) ? PFORMAT_LENGTH_LLONG : \
 273  sizeof( type ) == sizeof( long )      ? PFORMAT_LENGTH_LONG  : \
 274  sizeof( type ) == sizeof( short )     ? PFORMAT_LENGTH_SHORT : \
 275  sizeof( type ) == sizeof( char )      ? PFORMAT_LENGTH_CHAR  : \
 276  /* should never need this default */    PFORMAT_LENGTH_INT
 277#endif
 278
 279typedef struct
 280{
 281  /* Formatting and output control data...
 282   * An instance of this control block is created, (on the stack),
 283   * for each call to `__pformat()', and is passed by reference to
 284   * each of the output handlers, as required.
 285   */
 286  void *         dest;
 287  int            flags;
 288  int            width;
 289  int            precision;
 290  int            rplen;
 291  wchar_t        rpchr;
 292  int            thousands_chr_len;
 293  wchar_t        thousands_chr;
 294  int            count;
 295  int            quota;
 296  int            expmin;
 297} __pformat_t;
 298
 299#if defined(__ENABLE_PRINTF128) || defined(__ENABLE_DFP)
 300/* trim leading, leave at least n characters */
 301static char * __bigint_trim_leading_zeroes(char *in, int n){
 302  char *src = in;
 303  int len = strlen(in);
 304  while( len > n && *++src == '0') len--;
 305
 306  /* we want to null terminator too */
 307  memmove(in, src, strlen(src) + 1);
 308  return in;
 309}
 310
 311/* LSB first */
 312static
 313void __bigint_to_string(const uint32_t *digits, const uint32_t digitlen, char *buff, const uint32_t bufflen){
 314  int64_t digitsize = sizeof(*digits) * 8;
 315  int64_t shiftpos = digitlen * digitsize - 1;
 316  memset(buff, 0, bufflen);
 317
 318  while(shiftpos >= 0) {
 319    /* increment */
 320    for(uint32_t i = 0; i < bufflen - 1; i++){
 321      buff[i] += (buff[i] > 4) ? 3 : 0;
 322    }
 323
 324    /* shift left */
 325    for(uint32_t i = 0; i < bufflen - 1; i++)
 326      buff[i] <<= 1;
 327
 328    /* shift in */
 329    buff[bufflen - 2] |= digits[shiftpos / digitsize] & (0x1 << (shiftpos % digitsize)) ? 1 : 0;
 330
 331    /* overflow check */
 332    for(uint32_t i = bufflen - 1; i > 0; i--){
 333      buff[i - 1] |= (buff[i] > 0xf);
 334      buff[i] &= 0x0f;
 335    }
 336    shiftpos--;
 337  }
 338
 339  for(uint32_t i = 0; i < bufflen - 1; i++){
 340    buff[i] += '0';
 341  }
 342  buff[bufflen - 1] = '\0';
 343}
 344
 345#if defined(__ENABLE_PRINTF128)
 346/* LSB first, hex version */
 347static
 348void __bigint_to_stringx(const uint32_t *digits, const uint32_t digitlen, char *buff, const uint32_t bufflen, int upper){
 349  int32_t stride = sizeof(*digits) * 2;
 350  uint32_t lastpos = 0;
 351
 352  for(uint32_t i = 0; i < digitlen * stride; i++){
 353    int32_t buffpos = bufflen - i - 2;
 354    buff[buffpos] = (digits[ i / stride ] & (0xf << 4 * (i % stride))) >> ( 4 * (i % stride));
 355    buff[buffpos] += (buff[buffpos] > 9) ? ((upper) ? 0x7 : 0x27) : 0;
 356    buff[buffpos] += '0';
 357    lastpos = buffpos;
 358    if(buffpos == 0) break; /* sanity check */
 359  }
 360  memset(buff, '0', lastpos);
 361  buff[bufflen - 1] = '\0';
 362}
 363
 364/* LSB first, octet version */
 365static
 366void __bigint_to_stringo(const uint32_t *digits, const uint32_t digitlen, char *buff, const uint32_t bufflen){
 367  const uint32_t digitsize = sizeof(*digits) * 8;
 368  const uint64_t bits = digitsize * digitlen;
 369  uint32_t pos = bufflen - 2;
 370  uint32_t reg = 0;
 371  for(uint32_t i = 0; i <= bits; i++){
 372    reg |= (digits[ i / digitsize] & (0x1 << (i % digitsize))) ? 1 << (i % 3) : 0;
 373    if( (i && ( i + 1) % 3 == 0) || (i + 1) == bits){ /* make sure all is committed after last bit */
 374      buff[pos] = '0' + reg;
 375      reg = 0;
 376      if(!pos) break; /* sanity check */
 377      pos--;
 378    }
 379  }
 380  if(pos < bufflen - 1)
 381    memset(buff,'0', pos + 1);
 382  buff[bufflen - 1] = '\0';
 383}
 384#endif /* defined(__ENABLE_PRINTF128) */
 385#endif /* defined(__ENABLE_PRINTF128) || defined(__ENABLE_DFP) */
 386
 387static
 388void __pformat_putc( int c, __pformat_t *stream )
 389{
 390  /* Place a single character into the `__pformat()' output queue,
 391   * provided any specified output quota has not been exceeded.
 392   */
 393  if( (stream->flags & PFORMAT_NOLIMIT) || (stream->quota > stream->count) )
 394  {
 395    /* Either there was no quota specified,
 396     * or the active quota has not yet been reached.
 397     */
 398    if( stream->flags & PFORMAT_TO_FILE )
 399      /*
 400       * This is single character output to a FILE stream...
 401       */
 402      __fputc(c, (FILE *)(stream->dest));
 403
 404    else
 405      /* Whereas, this is to an internal memory buffer...
 406       */
 407      ((APICHAR *)(stream->dest))[stream->count] = c;
 408  }
 409  ++stream->count;
 410}
 411
 412static
 413void __pformat_putchars( const char *s, int count, __pformat_t *stream )
 414{
 415#ifndef __BUILD_WIDEAPI
 416  /* Handler for `%c' and (indirectly) `%s' conversion specifications.
 417   *
 418   * Transfer characters from the string buffer at `s', character by
 419   * character, up to the number of characters specified by `count', or
 420   * if `precision' has been explicitly set to a value less than `count',
 421   * stopping after the number of characters specified for `precision',
 422   * to the `__pformat()' output stream.
 423   *
 424   * Characters to be emitted are passed through `__pformat_putc()', to
 425   * ensure that any specified output quota is honoured.
 426   */
 427  if( (stream->precision >= 0) && (count > stream->precision) )
 428    /*
 429     * Ensure that the maximum number of characters transferred doesn't
 430     * exceed any explicitly set `precision' specification.
 431     */
 432    count = stream->precision;
 433
 434  /* Establish the width of any field padding required...
 435   */
 436  if( stream->width > count )
 437    /*
 438     * as the number of spaces equivalent to the number of characters
 439     * by which those to be emitted is fewer than the field width...
 440     */
 441    stream->width -= count;
 442
 443  else
 444    /* ignoring any width specification which is insufficient.
 445     */
 446    stream->width = PFORMAT_IGNORE;
 447
 448  if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
 449    /*
 450     * When not doing flush left justification, (i.e. the `-' flag
 451     * is not set), any residual unreserved field width must appear
 452     * as blank padding, to the left of the output string.
 453     */
 454    while( stream->width-- )
 455      __pformat_putc( '\x20', stream );
 456
 457  /* Emit the data...
 458   */
 459  while( count-- )
 460    /*
 461     * copying the requisite number of characters from the input.
 462     */
 463    __pformat_putc( *s++, stream );
 464
 465  /* If we still haven't consumed the entire specified field width,
 466   * we must be doing flush left justification; any residual width
 467   * must be filled with blanks, to the right of the output value.
 468   */
 469  while( stream->width-- > 0 )
 470    __pformat_putc( '\x20', stream );
 471
 472#else  /* __BUILD_WIDEAPI */
 473
 474  int len;
 475
 476  if( (stream->precision >= 0) && (count > stream->precision) )
 477    count = stream->precision;
 478
 479  if( (stream->flags & PFORMAT_TO_FILE) && (stream->flags & PFORMAT_NOLIMIT) )
 480  {
 481    int __cdecl __ms_fwprintf(FILE *, const wchar_t *, ...);
 482
 483    if( stream->width > count )
 484    {
 485      if( (stream->flags & PFORMAT_LJUSTIFY) == 0 )
 486        len = __ms_fwprintf( (FILE *)(stream->dest), L"%*.*S", stream->width, count, s );
 487      else
 488        len = __ms_fwprintf( (FILE *)(stream->dest), L"%-*.*S", stream->width, count, s );
 489    }
 490    else
 491    {
 492      len = __ms_fwprintf( (FILE *)(stream->dest), L"%.*S", count, s );
 493    }
 494    if( len > 0 )
 495      stream->count += len;
 496    stream->width = PFORMAT_IGNORE;
 497    return;
 498  }
 499
 500  if( stream->width > count )
 501    stream->width -= count;
 502  else
 503    stream->width = PFORMAT_IGNORE;
 504
 505  if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
 506    while( stream->width-- )
 507      __pformat_putc( '\x20', stream );
 508
 509  {
 510    /* mbrtowc */
 511    size_t l;
 512    wchar_t w[12], *p;
 513    while( count > 0 )
 514    {
 515      mbstate_t ps = {0};
 516      --count;
 517      p = &w[0];
 518      l = mbrtowc (p, s, strlen (s), &ps);
 519      if (!l)
 520        break;
 521      if ((ssize_t)l < 0)
 522      {
 523        l = 1;
 524        w[0] = (wchar_t) *s;
 525      }
 526      s += l;
 527      __pformat_putc((int)w[0], stream);
 528    }
 529  }
 530
 531  while( stream->width-- > 0 )
 532    __pformat_putc( '\x20', stream );
 533
 534#endif  /* __BUILD_WIDEAPI */
 535}
 536
 537static
 538void __pformat_puts( const char *s, __pformat_t *stream )
 539{
 540  /* Handler for `%s' conversion specifications.
 541   *
 542   * Transfer a NUL terminated character string, character by character,
 543   * stopping when the end of the string is encountered, or if `precision'
 544   * has been explicitly set, when the specified number of characters has
 545   * been emitted, if that is less than the length of the input string,
 546   * to the `__pformat()' output stream.
 547   *
 548   * This is implemented as a trivial call to `__pformat_putchars()',
 549   * passing the length of the input string as the character count,
 550   * (after first verifying that the input pointer is not NULL).
 551   */
 552  if( s == NULL ) s = "(null)";
 553
 554  if( stream->precision >= 0 )
 555    __pformat_putchars( s, strnlen( s, stream->precision ), stream );
 556  else
 557    __pformat_putchars( s, strlen( s ), stream );
 558}
 559
 560static
 561void __pformat_wputchars( const wchar_t *s, int count, __pformat_t *stream )
 562{
 563#ifndef __BUILD_WIDEAPI
 564  /* Handler for `%C'(`%lc') and `%S'(`%ls') conversion specifications;
 565   * (this is a wide character variant of `__pformat_putchars()').
 566   *
 567   * Each multibyte character sequence to be emitted is passed, byte
 568   * by byte, through `__pformat_putc()', to ensure that any specified
 569   * output quota is honoured.
 570   */
 571  char buf[16];
 572  mbstate_t state;
 573  int len = wcrtomb(buf, L'\0', &state);
 574
 575  if( (stream->precision >= 0) && (count > stream->precision) )
 576    /*
 577     * Ensure that the maximum number of characters transferred doesn't
 578     * exceed any explicitly set `precision' specification.
 579     */
 580    count = stream->precision;
 581
 582  /* Establish the width of any field padding required...
 583   */
 584  if( stream->width > count )
 585    /*
 586     * as the number of spaces equivalent to the number of characters
 587     * by which those to be emitted is fewer than the field width...
 588     */
 589    stream->width -= count;
 590
 591  else
 592    /* ignoring any width specification which is insufficient.
 593     */
 594    stream->width = PFORMAT_IGNORE;
 595
 596  if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
 597    /*
 598     * When not doing flush left justification, (i.e. the `-' flag
 599     * is not set), any residual unreserved field width must appear
 600     * as blank padding, to the left of the output string.
 601     */
 602    while( stream->width-- )
 603      __pformat_putc( '\x20', stream );
 604
 605  /* Emit the data, converting each character from the wide
 606   * to the multibyte domain as we go...
 607   */
 608  while( (count-- > 0) && ((len = wcrtomb( buf, *s++, &state )) > 0) )
 609  {
 610    char *p = buf;
 611    while( len-- > 0 )
 612      __pformat_putc( *p++, stream );
 613  }
 614
 615  /* If we still haven't consumed the entire specified field width,
 616   * we must be doing flush left justification; any residual width
 617   * must be filled with blanks, to the right of the output value.
 618   */
 619  while( stream->width-- > 0 )
 620    __pformat_putc( '\x20', stream );
 621
 622#else  /* __BUILD_WIDEAPI */
 623
 624  int len;
 625
 626  if( (stream->precision >= 0) && (count > stream->precision) )
 627    count = stream->precision;
 628
 629  if( (stream->flags & PFORMAT_TO_FILE) && (stream->flags & PFORMAT_NOLIMIT) )
 630  {
 631    int __cdecl __ms_fwprintf(FILE *, const wchar_t *, ...);
 632
 633    if( stream->width > count )
 634    {
 635      if( (stream->flags & PFORMAT_LJUSTIFY) == 0 )
 636        len = __ms_fwprintf( (FILE *)(stream->dest), L"%*.*s", stream->width, count, s );
 637      else
 638        len = __ms_fwprintf( (FILE *)(stream->dest), L"%-*.*s", stream->width, count, s );
 639    }
 640    else
 641    {
 642      len = __ms_fwprintf( (FILE *)(stream->dest), L"%.*s", count, s );
 643    }
 644    if( len > 0 )
 645      stream->count += len;
 646    stream->width = PFORMAT_IGNORE;
 647    return;
 648  }
 649
 650  if( stream->width > count )
 651    stream->width -= count;
 652  else
 653    stream->width = PFORMAT_IGNORE;
 654
 655  if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
 656    while( stream->width-- )
 657      __pformat_putc( '\x20', stream );
 658
 659  len = count;
 660  while(len-- > 0 && *s != 0)
 661  {
 662      __pformat_putc(*s++, stream);
 663  }
 664
 665  while( stream->width-- > 0 )
 666    __pformat_putc( '\x20', stream );
 667
 668#endif  /* __BUILD_WIDEAPI */
 669}
 670
 671static
 672void __pformat_wcputs( const wchar_t *s, __pformat_t *stream )
 673{
 674  /* Handler for `%S' (`%ls') conversion specifications.
 675   *
 676   * Transfer a NUL terminated wide character string, character by
 677   * character, converting to its equivalent multibyte representation
 678   * on output, and stopping when the end of the string is encountered,
 679   * or if `precision' has been explicitly set, when the specified number
 680   * of characters has been emitted, if that is less than the length of
 681   * the input string, to the `__pformat()' output stream.
 682   *
 683   * This is implemented as a trivial call to `__pformat_wputchars()',
 684   * passing the length of the input string as the character count,
 685   * (after first verifying that the input pointer is not NULL).
 686   */
 687  if( s == NULL ) s = L"(null)";
 688
 689  if( stream->precision >= 0 )
 690    __pformat_wputchars( s, wcsnlen( s, stream->precision ), stream );
 691  else
 692    __pformat_wputchars( s, wcslen( s ), stream );
 693}
 694
 695static
 696int __pformat_int_bufsiz( int bias, int size, __pformat_t *stream )
 697{
 698  /* Helper to establish the size of the internal buffer, which
 699   * is required to queue the ASCII decomposition of an integral
 700   * data value, prior to transfer to the output stream.
 701   */
 702  size = ((size - 1 + LLONGBITS) / size) + bias;
 703  size += (stream->precision > 0) ? stream->precision : 0;
 704  if ((stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0)
 705    size += (size / 3);
 706  return (size > stream->width) ? size : stream->width;
 707}
 708
 709static
 710void __pformat_int( __pformat_intarg_t value, __pformat_t *stream )
 711{
 712  /* Handler for `%d', `%i' and `%u' conversion specifications.
 713   *
 714   * Transfer the ASCII representation of an integer value parameter,
 715   * formatted as a decimal number, to the `__pformat()' output queue;
 716   * output will be truncated, if any specified quota is exceeded.
 717   */
 718  int32_t bufflen = __pformat_int_bufsiz(1, PFORMAT_OSHIFT, stream);
 719#ifdef __ENABLE_PRINTF128
 720  char *tmp_buff = NULL;
 721#endif
 722  char *buf = NULL;
 723  char *p;
 724  int precision;
 725
 726  buf = alloca(bufflen);
 727  p = buf;
 728  if( stream->flags & PFORMAT_NEGATIVE )
 729#ifdef __ENABLE_PRINTF128
 730  {
 731    /* The input value might be negative, (i.e. it is a signed value)...
 732     */
 733    if( value.__pformat_u128_t.t128.digits[1] < 0) {
 734      /*
 735       * It IS negative, but we want to encode it as unsigned,
 736       * displayed with a leading minus sign, so convert it...
 737       */
 738      /* two's complement */
 739      value.__pformat_u128_t.t128.digits[0] = ~value.__pformat_u128_t.t128.digits[0];
 740      value.__pformat_u128_t.t128.digits[1] = ~value.__pformat_u128_t.t128.digits[1];
 741      value.__pformat_u128_t.t128.digits[0] += 1;
 742      value.__pformat_u128_t.t128.digits[1] += (!value.__pformat_u128_t.t128.digits[0]) ? 1 : 0;
 743    } else
 744      /* It is unequivocally a POSITIVE value, so turn off the
 745       * request to prefix it with a minus sign...
 746       */
 747      stream->flags &= ~PFORMAT_NEGATIVE;
 748  }
 749
 750  tmp_buff = alloca(bufflen);
 751  /* Encode the input value for display...
 752   */
 753  __bigint_to_string(value.__pformat_u128_t.t128_2.digits32,
 754    4, tmp_buff, bufflen);
 755  __bigint_trim_leading_zeroes(tmp_buff,1);
 756
 757  memset(p,0,bufflen);
 758  for(int32_t i = strlen(tmp_buff) - 1; i >= 0; i--){
 759  if ( i && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
 760        && (i % 4) == 3)
 761      {
 762        *p++ = ',';
 763      }
 764      *p++ = tmp_buff[i];
 765    if( i > bufflen - 1) break; /* sanity chec */
 766    if(  tmp_buff[i] == '\0' ) break; /* end */
 767  }
 768#else
 769  {
 770    /* The input value might be negative, (i.e. it is a signed value)...
 771     */
 772    if( value.__pformat_llong_t < 0LL )
 773      /*
 774       * It IS negative, but we want to encode it as unsigned,
 775       * displayed with a leading minus sign, so convert it...
 776       */
 777      value.__pformat_llong_t = -value.__pformat_llong_t;
 778
 779    else
 780      /* It is unequivocally a POSITIVE value, so turn off the
 781       * request to prefix it with a minus sign...
 782       */
 783      stream->flags &= ~PFORMAT_NEGATIVE;
 784  }
 785while( value.__pformat_ullong_t )
 786  {
 787    /* decomposing it into its constituent decimal digits,
 788     * in order from least significant to most significant, using
 789     * the local buffer as a LIFO queue in which to store them.
 790     */
 791    if (p != buf && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
 792        && ((p - buf) % 4) == 3)
 793      {
 794        *p++ = ',';
 795      }
 796    *p++ = '0' + (unsigned char)(value.__pformat_ullong_t % 10LL);
 797    value.__pformat_ullong_t /= 10LL;
 798  }
 799#endif
 800
 801  if(  (stream->precision > 0)
 802  &&  ((precision = stream->precision - (p - buf)) > 0)  )
 803    /*
 804     * We have not yet queued sufficient digits to fill the field width
 805     * specified for minimum `precision'; pad with zeros to achieve this.
 806     */
 807    while( precision-- > 0 )
 808      *p++ = '0';
 809
 810  if( (p == buf) && (stream->precision != 0) )
 811    /*
 812     * Input value was zero; make sure we print at least one digit,
 813     * unless the precision is also explicitly zero.
 814     */
 815    *p++ = '0';
 816
 817  if( (stream->width > 0) && ((stream->width -= p - buf) > 0) )
 818  {
 819    /* We have now queued sufficient characters to display the input value,
 820     * at the desired precision, but this will not fill the output field...
 821     */
 822    if( stream->flags & PFORMAT_SIGNED )
 823      /*
 824       * We will fill one additional space with a sign...
 825       */
 826      stream->width--;
 827
 828    if(  (stream->precision < 0)
 829    &&  ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL)  )
 830      /*
 831       * and the `0' flag is in effect, so we pad the remaining spaces,
 832       * to the left of the displayed value, with zeros.
 833       */
 834      while( stream->width-- > 0 )
 835        *p++ = '0';
 836
 837    else if( (stream->flags & PFORMAT_LJUSTIFY) == 0 )
 838      /*
 839       * the `0' flag is not in effect, and neither is the `-' flag,
 840       * so we pad to the left of the displayed value with spaces, so that
 841       * the value appears right justified within the output field.
 842       */
 843      while( stream->width-- > 0 )
 844        __pformat_putc( '\x20', stream );
 845  }
 846
 847  if( stream->flags & PFORMAT_NEGATIVE )
 848    /*
 849     * A negative value needs a sign...
 850     */
 851    *p++ = '-';
 852
 853  else if( stream->flags & PFORMAT_POSITIVE )
 854    /*
 855     * A positive value may have an optionally displayed sign...
 856     */
 857    *p++ = '+';
 858
 859  else if( stream->flags & PFORMAT_ADDSPACE )
 860    /*
 861     * Space was reserved for displaying a sign, but none was emitted...
 862     */
 863    *p++ = '\x20';
 864
 865  while( p > buf )
 866    /*
 867     * Emit the accumulated constituent digits,
 868     * in order from most significant to least significant...
 869     */
 870    __pformat_putc( *--p, stream );
 871
 872  while( stream->width-- > 0 )
 873    /*
 874     * The specified output field has not yet been completely filled;
 875     * the `-' flag must be in effect, resulting in a displayed value which
 876     * appears left justified within the output field; we must pad the field
 877     * to the right of the displayed value, by emitting additional spaces,
 878     * until we reach the rightmost field boundary.
 879     */
 880    __pformat_putc( '\x20', stream );
 881}
 882
 883static
 884void __pformat_xint( int fmt, __pformat_intarg_t value, __pformat_t *stream )
 885{
 886  /* Handler for `%o', `%p', `%x' and `%X' conversions.
 887   *
 888   * These can be implemented using a simple `mask and shift' strategy;
 889   * set up the mask and shift values appropriate to the conversion format,
 890   * and allocate a suitably sized local buffer, in which to queue encoded
 891   * digits of the formatted value, in preparation for output.
 892   */
 893  int width;
 894  int shift = (fmt == 'o') ? PFORMAT_OSHIFT : PFORMAT_XSHIFT;
 895  int bufflen = __pformat_int_bufsiz(2, shift, stream);
 896  char *buf = NULL;
 897#ifdef __ENABLE_PRINTF128
 898  char *tmp_buf = NULL;
 899#endif
 900  char *p;
 901  buf = alloca(bufflen);
 902  p = buf;
 903#ifdef __ENABLE_PRINTF128
 904  tmp_buf = alloca(bufflen);
 905  if(fmt == 'o'){
 906    __bigint_to_stringo(value.__pformat_u128_t.t128_2.digits32,4,tmp_buf,bufflen);
 907  } else {
 908    __bigint_to_stringx(value.__pformat_u128_t.t128_2.digits32,4,tmp_buf,bufflen, !(fmt & PFORMAT_XCASE));
 909  }
 910  __bigint_trim_leading_zeroes(tmp_buf,0);
 911
 912  memset(buf,0,bufflen);
 913  for(int32_t i = strlen(tmp_buf); i >= 0; i--)
 914    *p++ = tmp_buf[i];
 915#else
 916  int mask = (fmt == 'o') ? PFORMAT_OMASK : PFORMAT_XMASK;
 917  while( value.__pformat_ullong_t )
 918  {
 919    /* Encode the specified non-zero input value as a sequence of digits,
 920     * in the appropriate `base' encoding and in reverse digit order, each
 921     * encoded in its printable ASCII form, with no leading zeros, using
 922     * the local buffer as a LIFO queue in which to store them.
 923     */
 924    char *q;
 925    if( (*(q = p++) = '0' + (value.__pformat_ullong_t & mask)) > '9' )
 926      *q = (*q + 'A' - '9' - 1) | (fmt & PFORMAT_XCASE);
 927    value.__pformat_ullong_t >>= shift;
 928  }
 929#endif
 930
 931  if( p == buf )
 932    /*
 933     * Nothing was queued; input value must be zero, which should never be
 934     * emitted in the `alternative' PFORMAT_HASHED style.
 935     */
 936    stream->flags &= ~PFORMAT_HASHED;
 937
 938  if( ((width = stream->precision) > 0) && ((width -= p - buf) > 0) )
 939    /*
 940     * We have not yet queued sufficient digits to fill the field width
 941     * specified for minimum `precision'; pad with zeros to achieve this.
 942     */
 943    while( width-- > 0 )
 944      *p++ = '0';
 945
 946  else if( (fmt == 'o') && (stream->flags & PFORMAT_HASHED) )
 947    /*
 948     * The field width specified for minimum `precision' has already
 949     * been filled, but the `alternative' PFORMAT_HASHED style for octal
 950     * output requires at least one initial zero; that will not have
 951     * been queued, so add it now.
 952     */
 953    *p++ = '0';
 954
 955  if( (p == buf) && (stream->precision != 0) )
 956    /*
 957     * Still nothing queued for output, but the `precision' has not been
 958     * explicitly specified as zero, (which is necessary if no output for
 959     * an input value of zero is desired); queue exactly one zero digit.
 960     */
 961    *p++ = '0';
 962
 963  if( stream->width > (width = p - buf) )
 964    /*
 965     * Specified field width exceeds the minimum required...
 966     * Adjust so that we retain only the additional padding width.
 967     */
 968    stream->width -= width;
 969
 970  else
 971    /* Ignore any width specification which is insufficient.
 972     */
 973    stream->width = PFORMAT_IGNORE;
 974
 975  if( ((width = stream->width) > 0)
 976  &&  (fmt != 'o') && (stream->flags & PFORMAT_HASHED)  )
 977    /*
 978     * For `%#x' or `%#X' formats, (which have the `#' flag set),
 979     * further reduce the padding width to accommodate the radix
 980     * indicating prefix.
 981     */
 982    width -= 2;
 983
 984  if(  (width > 0) && (stream->precision < 0)
 985  &&  ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL)  )
 986    /*
 987     * When the `0' flag is set, and not overridden by the `-' flag,
 988     * or by a specified precision, add sufficient leading zeros to
 989     * consume the remaining field width.
 990     */
 991    while( width-- > 0 )
 992      *p++ = '0';
 993
 994  if( (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
 995  {
 996    /* For formats other than octal, the PFORMAT_HASHED output style
 997     * requires the addition of a two character radix indicator, as a
 998     * prefix to the actual encoded numeric value.
 999     */
1000    *p++ = fmt;
1001    *p++ = '0';
1002  }
1003
1004  if( (width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
1005    /*
1006     * When not doing flush left justification, (i.e. the `-' flag
1007     * is not set), any residual unreserved field width must appear
1008     * as blank padding, to the left of the output value.
1009     */
1010    while( width-- > 0 )
1011      __pformat_putc( '\x20', stream );
1012
1013  while( p > buf )
1014    /*
1015     * Move the queued output from the local buffer to the ultimate
1016     * destination, in LIFO order.
1017     */
1018    __pformat_putc( *--p, stream );
1019
1020  /* If we still haven't consumed the entire specified field width,
1021   * we must be doing flush left justification; any residual width
1022   * must be filled with blanks, to the right of the output value.
1023   */
1024  while( width-- > 0 )
1025    __pformat_putc( '\x20', stream );
1026}
1027
1028#include "../gdtoa/gdtoa.h"
1029
1030typedef union
1031{
1032  /* A multifaceted representation of an IEEE extended precision,
1033   * (80-bit), floating point number, facilitating access to its
1034   * component parts.
1035   */
1036  double                 __pformat_fpreg_double_t;
1037  long double            __pformat_fpreg_ldouble_t;
1038  struct
1039  { unsigned long long   __pformat_fpreg_mantissa;
1040    signed short         __pformat_fpreg_exponent;
1041  };
1042  unsigned short         __pformat_fpreg_bitmap[5];
1043  ULong                  __pformat_fpreg_bits;
1044} __pformat_fpreg_t;
1045
1046static __pformat_fpreg_t init_fpreg_ldouble( long double val )
1047{
1048  __pformat_fpreg_t x;
1049  x.__pformat_fpreg_ldouble_t = val;
1050
1051  if( sizeof( double ) == sizeof( long double ) )
1052  {
1053    /* Here, __pformat_fpreg_t expects to be initialized with a 80 bit long
1054     * double, but this platform doesn't have long doubles that differ from
1055     * regular 64 bit doubles. Therefore manually convert the 64 bit float
1056     * value to an 80 bit float value.
1057     */
1058    int exp = (x.__pformat_fpreg_mantissa >> 52) & 0x7ff;
1059    unsigned long long mant = x.__pformat_fpreg_mantissa & 0x000fffffffffffffULL;
1060    int topbit = exp ? 1 : 0;
1061    int signbit = x.__pformat_fpreg_mantissa >> 63;
1062
1063    if (exp == 0x7ff)
1064      exp = 0x7fff;
1065    else if (exp != 0)
1066      exp = exp - 1023 + 16383;
1067    else if (mant != 0) {
1068      /* Denormal when stored as a 64 bit double, but becomes a normal when
1069       * converted to 80 bit long double form. */
1070      exp = 1 - 1023 + 16383;
1071      while (!(mant & 0x0010000000000000ULL)) {
1072        /* Normalize the mantissa. */
1073        mant <<= 1;
1074        exp--;
1075      }
1076      topbit = 1; /* The top bit, which is implicit in the 64 bit form. */
1077    }
1078    x.__pformat_fpreg_mantissa = (mant << 11) | ((unsigned long long)topbit << 63);
1079    x.__pformat_fpreg_exponent = exp | (signbit << 15);
1080  }
1081
1082  return x;
1083}
1084
1085static
1086char *__pformat_cvt( int mode, long double val, int nd, int *dp, int *sign )
1087{
1088  /* Helper function, derived from David M. Gay's `g_xfmt()', calling
1089   * his `__gdtoa()' function in a manner to provide extended precision
1090   * replacements for `ecvt()' and `fcvt()'.
1091   */
1092  int k; unsigned int e = 0; char *ep;
1093  static FPI fpi = { 64, 1-16383-64+1, 32766-16383-64+1, FPI_Round_near, 0, 14 /* Int_max */ };
1094  __pformat_fpreg_t x = init_fpreg_ldouble( val );
1095
1096  k = __fpclassifyl( val );
1097
1098  /* Classify the argument into an appropriate `__gdtoa()' category...
1099   */
1100  if( k & FP_NAN )
1101    /*
1102     * identifying infinities or not-a-number...
1103     */
1104    k = (k & FP_NORMAL) ? STRTOG_Infinite : STRTOG_NaN;
1105
1106  else if( k & FP_NORMAL )
1107  {
1108    /* normal and near-zero `denormals'...
1109     */
1110    if( k & FP_ZERO )
1111    {
1112      /* with appropriate exponent adjustment for a `denormal'...
1113       */
1114      k = STRTOG_Denormal;
1115      e = 1 - 0x3FFF - 63;
1116    }
1117    else
1118    {
1119      /* or with `normal' exponent adjustment...
1120       */
1121      k = STRTOG_Normal;
1122      e = (x.__pformat_fpreg_exponent & 0x7FFF) - 0x3FFF - 63;
1123    }
1124  }
1125
1126  else
1127    /* or, if none of the above, it's a zero, (positive or negative).
1128     */
1129    k = STRTOG_Zero;
1130
1131  /* Check for negative values, always treating NaN as unsigned...
1132   * (return value is zero for positive/unsigned; non-zero for negative).
1133   */
1134  *sign = (k == STRTOG_NaN) ? 0 : x.__pformat_fpreg_exponent & 0x8000;
1135
1136  /* Finally, get the raw digit string, and radix point position index.
1137   */
1138  return __gdtoa( &fpi, e, &x.__pformat_fpreg_bits, &k, mode, nd, dp, &ep );
1139}
1140
1141static
1142char *__pformat_ecvt( long double x, int precision, int *dp, int *sign )
1143{
1144  /* A convenience wrapper for the above...
1145   * it emulates `ecvt()', but takes a `long double' argument.
1146   */
1147  return __pformat_cvt( 2, x, precision, dp, sign );
1148}
1149
1150static
1151char *__pformat_fcvt( long double x, int precision, int *dp, int *sign )
1152{
1153  /* A convenience wrapper for the above...
1154   * it emulates `fcvt()', but takes a `long double' argument.
1155   */
1156  return __pformat_cvt( 3, x, precision, dp, sign );
1157}
1158
1159/* The following are required, to clean up the `__gdtoa()' memory pool,
1160 * after processing the data returned by the above.
1161 */
1162#define __pformat_ecvt_release( value ) __freedtoa( value )
1163#define __pformat_fcvt_release( value ) __freedtoa( value )
1164
1165static
1166void __pformat_emit_radix_point( __pformat_t *stream )
1167{
1168  /* Helper to place a localised representation of the radix point
1169   * character at the ultimate destination, when formatting fixed or
1170   * floating point numbers.
1171   */
1172  if( stream->rplen == PFORMAT_RPINIT )
1173  {
1174    /* Radix point initialisation not yet completed;
1175     * establish a multibyte to `wchar_t' converter...
1176     */
1177    int len; wchar_t rpchr;
1178    mbstate_t state = {0};
1179
1180    /* Fetch and convert the localised radix point representation...
1181     */
1182    if( (len = mbrtowc( &rpchr, localeconv()->decimal_point, 16, &state )) > 0 )
1183      /*
1184       * and store it, if valid.
1185       */
1186      stream->rpchr = rpchr;
1187
1188    /* In any case, store the reported effective multibyte length,
1189     * (or the error flag), marking initialisation as `done'.
1190     */
1191    stream->rplen = len;
1192  }
1193
1194  if( stream->rpchr != (wchar_t)(0) )
1195  {
1196    /* We have a localised radix point mark;
1197     * establish a converter to make it a multibyte character...
1198     */
1199#ifdef __BUILD_WIDEAPI
1200   __pformat_putc (stream->rpchr, stream);
1201#else
1202    int len; char buf[len = stream->rplen];
1203    mbstate_t state = {0};
1204
1205    /* Convert the `wchar_t' representation to multibyte...
1206     */
1207    if( (len = wcrtomb( buf, stream->rpchr, &state )) > 0 )
1208    {
1209      /* and copy to the output destination, when valid...
1210       */
1211      char *p = buf;
1212      while( len-- > 0 )
1213        __pformat_putc( *p++, stream );
1214    }
1215
1216    else
1217      /* otherwise fall back to plain ASCII '.'...
1218       */
1219      __pformat_putc( '.', stream );
1220#endif
1221  }
1222  else
1223    /* No localisation: just use ASCII '.'...
1224     */
1225    __pformat_putc( '.', stream );
1226}
1227
1228static
1229void __pformat_emit_numeric_value( int c, __pformat_t *stream )
1230{
1231  /* Convenience helper to transfer numeric data from an internal
1232   * formatting buffer to the ultimate destination...
1233   */
1234  if( c == '.' )
1235    /*
1236     * converting this internal representation of the the radix
1237     * point to the appropriately localised representation...
1238     */
1239    __pformat_emit_radix_point( stream );
1240  else if (c == ',')
1241    {
1242      wchar_t wcs;
1243      if ((wcs = stream->thousands_chr) != 0)
1244        __pformat_wputchars (&wcs, 1, stream);
1245    }
1246  else
1247    /* and passing all other characters through, unmodified.
1248     */
1249    __pformat_putc( c, stream );
1250}
1251
1252static
1253void __pformat_emit_inf_or_nan( int sign, char *value, __pformat_t *stream )
1254{
1255  /* Helper to emit INF or NAN where a floating point value
1256   * resolves to one of these special states.
1257   */
1258  int i;
1259  char buf[4];
1260  char *p = buf;
1261
1262  /* We use the string formatting helper to display INF/NAN,
1263   * but we don't want truncation if the precision set for the
1264   * original floating point output request was insufficient;
1265   * ignore it!
1266   */
1267  stream->precision = PFORMAT_IGNORE;
1268
1269  if( sign )
1270    /*
1271     * Negative infinity: emit the sign...
1272     */
1273    *p++ = '-';
1274
1275  else if( stream->flags & PFORMAT_POSITIVE )
1276    /*
1277     * Not negative infinity, but '+' flag is in effect;
1278     * thus, we emit a positive sign...
1279     */
1280    *p++ = '+';
1281
1282  else if( stream->flags & PFORMAT_ADDSPACE )
1283    /*
1284     * No sign required, but space was reserved for it...
1285     */
1286    *p++ = '\x20';
1287
1288  /* Copy the appropriate status indicator, up to a maximum of
1289   * three characters, transforming to the case corresponding to
1290   * the format specification...
1291   */
1292  for( i = 3; i > 0; --i )
1293    *p++ = (*value++ & ~PFORMAT_XCASE) | (stream->flags & PFORMAT_XCASE);
1294
1295  /* and emit the result.
1296   */
1297  __pformat_putchars( buf, p - buf, stream );
1298}
1299
1300static
1301void __pformat_emit_float( int sign, char *value, int len, __pformat_t *stream )
1302{
1303  /* Helper to emit a fixed point representation of numeric data,
1304   * as encoded by a prior call to `ecvt()' or `fcvt()'; (this does
1305   * NOT include the exponent, for floating point format).
1306   */
1307  if( len > 0 )
1308  {
1309    /* The magnitude of `x' is greater than or equal to 1.0...
1310     * reserve space in the output field, for the required number of
1311     * decimal digits to be placed before the decimal point...
1312     */
1313    if( stream->width >= len)
1314      /*
1315       * adjusting as appropriate, when width is sufficient...
1316       */
1317      stream->width -= len;
1318
1319    else
1320      /* or simply ignoring the width specification, if not.
1321       */
1322      stream->width = PFORMAT_IGNORE;
1323  }
1324
1325  else if( stream->width > 0 )
1326    /*
1327     * The magnitude of `x' is less than 1.0...
1328     * reserve space for exactly one zero before the decimal point.
1329     */
1330    stream->width--;
1331
1332  /* Reserve additional space for the digits which will follow the
1333   * decimal point...
1334   */
1335  if( (stream->width >= 0) && (stream->width > stream->precision) )
1336    /*
1337     * adjusting appropriately, when sufficient width remains...
1338     * (note that we must check both of these conditions, because
1339     * precision may be more negative than width, as a result of
1340     * adjustment to provide extra padding when trailing zeros
1341     * are to be discarded from "%g" format conversion with a
1342     * specified field width, but if width itself is negative,
1343     * then there is explicitly to be no padding anyway).
1344     */
1345    stream->width -= stream->precision;
1346
1347  else
1348    /* or again, ignoring the width specification, if not.
1349     */
1350    stream->width = PFORMAT_IGNORE;
1351
1352  /* Reserve space in the output field, for display of the decimal point,
1353   * unless the precision is explicity zero, with the `#' flag not set.
1354   */
1355  if ((stream->width > 0)
1356      && ((stream->precision > 0) || (stream->flags & PFORMAT_HASHED)))
1357    stream->width--;
1358
1359  if (len > 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0)
1360    {
1361      int cths = ((len + 2) / 3) - 1;
1362      while (cths > 0 && stream->width > 0)
1363        {
1364          --cths; stream->width--;
1365        }
1366    }
1367
1368  /* Reserve space in the output field, for display of the sign of the
1369   * formatted value, if required; (i.e. if the value is negative, or if
1370   * either the `space' or `+' formatting flags are set).
1371   */
1372  if( (stream->width > 0) && (sign || (stream->flags & PFORMAT_SIGNED)) )
1373    stream->width--;
1374
1375  /* Emit any padding space, as required to correctly right justify
1376   * the output within the alloted field width.
1377   */
1378  if( (stream->width > 0) && ((stream->flags & PFORMAT_JUSTIFY) == 0) )
1379    while( stream->width-- > 0 )
1380      __pformat_putc( '\x20', stream );
1381
1382  /* Emit the sign indicator, as appropriate...
1383   */
1384  if( sign )
1385    /*
1386     * mandatory, for negative values...
1387     */
1388    __pformat_putc( '-', stream );
1389
1390  else if( stream->flags & PFORMAT_POSITIVE )
1391    /*
1392     * optional, for positive values...
1393     */
1394    __pformat_putc( '+', stream );
1395
1396  else if( stream->flags & PFORMAT_ADDSPACE )
1397    /*
1398     * or just fill reserved space, when the space flag is in effect.
1399     */
1400    __pformat_putc( '\x20', stream );
1401
1402  /* If the `0' flag is in effect, and not overridden by the `-' flag,
1403   * then zero padding, to fill out the field, goes here...
1404   */
1405  if(  (stream->width > 0)
1406  &&  ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL)  )
1407    while( stream->width-- > 0 )
1408      __pformat_putc( '0', stream );
1409
1410  /* Emit the digits of the encoded numeric value...
1411   */
1412  if( len > 0 )
1413  {
1414    /*
1415     * ...beginning with those which precede the radix point,
1416     * and appending any necessary significant trailing zeros.
1417     */
1418    do {
1419      __pformat_putc( *value ? *value++ : '0', stream);
1420      --len;
1421      if (len != 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
1422          && (len % 3) == 0)
1423        __pformat_wputchars (&stream->thousands_chr, 1, stream);
1424    }
1425    while (len > 0);
1426  }
1427  else
1428    /* The magnitude of the encoded value is less than 1.0, so no
1429     * digits precede the radix point; we emit a mandatory initial
1430     * zero, followed immediately by the radix point.
1431     */
1432    __pformat_putc( '0', stream );
1433
1434  /* Unless the encoded value is integral, AND the radix point
1435   * is not expressly demanded by the `#' flag, we must insert
1436   * the appropriately localised radix point mark here...
1437   */
1438  if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1439    __pformat_emit_radix_point( stream );
1440
1441  /* When the radix point offset, `len', is negative, this implies
1442   * that additional zeros must appear, following the radix point,
1443   * and preceding the first significant digit...
1444   */
1445  if( len < 0 )
1446  {
1447    /* To accommodate these, we adjust the precision, (reducing it
1448     * by adding a negative value), and then we emit as many zeros
1449     * as are required.
1450     */
1451    stream->precision += len;
1452    do __pformat_putc( '0', stream );
1453       while( ++len < 0 );
1454  }
1455
1456  /* Now we emit any remaining significant digits, or trailing zeros,
1457   * until the required precision has been achieved.
1458   */
1459  while( stream->precision-- > 0 )
1460    __pformat_putc( *value ? *value++ : '0', stream );
1461}
1462
1463static
1464void __pformat_emit_efloat( int sign, char *value, int e, __pformat_t *stream )
1465{
1466  /* Helper to emit a floating point representation of numeric data,
1467   * as encoded by a prior call to `ecvt()' or `fcvt()'; (this DOES
1468   * include the following exponent).
1469   */
1470  int exp_width = 1;
1471  __pformat_intarg_t exponent; exponent.__pformat_llong_t = e -= 1;
1472
1473  /* Determine how many digit positions are required for the exponent.
1474   */
1475  while( (e /= 10) != 0 )
1476    exp_width++;
1477
1478  /* Ensure that this is at least as many as the standard requirement.
1479   * The C99 standard requires the expenent to contain at least two
1480   * digits, unless specified explicitly otherwise.
1481   */
1482  if (stream->expmin == -1)
1483    stream->expmin = 2;
1484  if( exp_width < stream->expmin )
1485    exp_width = stream->expmin;
1486
1487  /* Adjust the residual field width allocation, to allow for the
1488   * number of exponent digits to be emitted, together with a sign
1489   * and exponent separator...
1490   */
1491  if( stream->width > (exp_width += 2) )
1492    stream->width -= exp_width;
1493
1494  else
1495    /* ignoring the field width specification, if insufficient.
1496     */
1497    stream->width = PFORMAT_IGNORE;
1498
1499  /* Emit the significand, as a fixed point value with one digit
1500   * preceding the radix point.
1501   */
1502  __pformat_emit_float( sign, value, 1, stream );
1503
1504  /* Reset precision, to ensure the mandatory minimum number of
1505   * exponent digits will be emitted, and set the flags to ensure
1506   * the sign is displayed.
1507   */
1508  stream->precision = stream->expmin;
1509  stream->flags |= PFORMAT_SIGNED;
1510
1511  /* Emit the exponent separator.
1512   */
1513  __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream );
1514
1515  /* Readjust the field width setting, such that it again allows
1516   * for the digits of the exponent, (which had been discounted when
1517   * computing any left side padding requirement), so that they are
1518   * correctly included in the computation of any right side padding
1519   * requirement, (but here we exclude the exponent separator, which
1520   * has been emitted, and so counted already).
1521   */
1522  stream->width += exp_width - 1;
1523
1524  /* And finally, emit the exponent itself, as a signed integer,
1525   * with any padding required to achieve flush left justification,
1526   * (which will be added automatically, by `__pformat_int()').
1527   */
1528  __pformat_int( exponent, stream );
1529}
1530
1531static
1532void __pformat_float( long double x, __pformat_t *stream )
1533{
1534  /* Handler for `%f' and `%F' format specifiers.
1535   *
1536   * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()'
1537   * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1538   * output in fixed point format.
1539   */
1540  int sign, intlen; char *value;
1541
1542  /* Establish the precision for the displayed value, defaulting to six
1543   * digits following the decimal point, if not explicitly specified.
1544   */
1545  if( stream->precision < 0 )
1546    stream->precision = 6;
1547
1548  /* Encode the input value as ASCII, for display...
1549   */
1550  value = __pformat_fcvt( x, stream->precision, &intlen, &sign );
1551
1552  if( intlen == PFORMAT_INFNAN )
1553    /*
1554     * handle cases of `infinity' or `not-a-number'...
1555     */
1556    __pformat_emit_inf_or_nan( sign, value, stream );
1557
1558  else
1559  { /* or otherwise, emit the formatted result.
1560     */
1561    __pformat_emit_float( sign, value, intlen, stream );
1562
1563    /* and, if there is any residual field width as yet unfilled,
1564     * then we must be doing flush left justification, so pad out to
1565     * the right hand field boundary.
1566     */
1567    while( stream->width-- > 0 )
1568      __pformat_putc( '\x20', stream );
1569  }
1570
1571  /* Clean up `__pformat_fcvt()' memory allocation for `value'...
1572   */
1573  __pformat_fcvt_release( value );
1574}
1575
1576#ifdef __ENABLE_DFP
1577
1578typedef struct decimal128_decode {
1579  int64_t significand[2];
1580  int32_t exponent;
1581  int sig_neg;
1582  int exp_neg;
1583} decimal128_decode;
1584
1585static uint32_t dec128_decode(decimal128_decode *result, const _Decimal128 deci){
1586  int64_t significand2;
1587  int64_t significand1;
1588  int32_t exp_part;
1589  int8_t sig_sign;
1590  ud128 in;
1591  in.d = deci;
1592
1593  if(in.t0.bits == 0x3){ /*case 11 */
1594    /* should not enter here */
1595    sig_sign = in.t2.sign;
1596    exp_part = in.t2.exponent;
1597    significand1 = in.t2.mantissaL;
1598    significand2 = (in.t2.mantissaH | (0x1ULL << 49));
1599  } else {
1600    sig_sign = in.t1.sign;
1601    exp_part = in.t1.exponent;
1602    significand1 = in.t1.mantissaL;
1603    significand2 = in.t1.mantissaH;
1604  }
1605  exp_part -= 6176; /* exp bias */
1606
1607  result->significand[0] = significand1;
1608  result->significand[1] = significand2; /* higher */
1609  result->exponent = exp_part;
1610  result->exp_neg = (exp_part < 0 )? 1 : 0;
1611  result->sig_neg = sig_sign;
1612
1613  return 0;
1614}
1615
1616static
1617void  __pformat_efloat_decimal(_Decimal128 x, __pformat_t *stream ){
1618  decimal128_decode in;
1619  char str_exp[8];
1620  char str_sig[40];
1621  int floatclass = __fpclassifyd128(x);
1622
1623  /* precision control */
1624  int32_t prec = ( (stream->precision < 0) || (stream->precision > 38) ) ?
1625    6 : stream->precision;
1626  int32_t max_prec;
1627  int32_t exp_strlen;
1628
1629  dec128_decode(&in,x);
1630
1631  if((floatclass & FP_INFINITE) == FP_INFINITE){
1632    stream->precision = 3;
1633    if(stream->flags & PFORMAT_SIGNED)
1634      __pformat_putc( in.sig_neg ? '-' : '+', stream );
1635    __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "inf" : "INF", stream);
1636    return;
1637  } else if(floatclass & FP_NAN){
1638    stream->precision = 3;
1639    if(stream->flags & PFORMAT_SIGNED)
1640      __pformat_putc( in.sig_neg ? '-' : '+', stream );
1641    __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "nan" : "NAN", stream);
1642    return;
1643  }
1644
1645  /* Stringify significand */
1646  __bigint_to_string(
1647    (uint32_t[4]){in.significand[0] & 0x0ffffffff, in.significand[0] >> 32, in.significand[1] & 0x0ffffffff, in.significand[1] >> 32 },
1648    4, str_sig, sizeof(str_sig));
1649  __bigint_trim_leading_zeroes(str_sig,1);
1650  max_prec = strlen(str_sig+1);
1651
1652  /* Try to canonize exponent */
1653  in.exponent += max_prec;
1654  in.exp_neg = (in.exponent < 0 ) ? 1 : 0;
1655
1656  /* stringify exponent */
1657  __bigint_to_string(
1658    (uint32_t[1]) { in.exp_neg ? -in.exponent : in.exponent},
1659    1, str_exp, sizeof(str_exp));
1660  exp_strlen = strlen(__bigint_trim_leading_zeroes(str_exp,3));
1661
1662  /* account for dot, +-e */
1663  for(int32_t spacers = 0; spacers < stream->width - max_prec - exp_strlen - 4; spacers++)
1664    __pformat_putc( ' ', stream );
1665
1666  /* optional sign */
1667  if (in.sig_neg || (stream->flags & PFORMAT_SIGNED)) {
1668    __pformat_putc( in.sig_neg ? '-' : '+', stream );
1669  } else if( stream->width - max_prec - exp_strlen - 4 > 0 ) {
1670    __pformat_putc( ' ', stream );
1671  }
1672  stream->width = 0;
1673  /* s.sss form */
1674  __pformat_putc(str_sig[0], stream);
1675  if(prec) {
1676    /* str_sig[prec+1] = '\0';*/
1677    __pformat_emit_radix_point(stream);
1678    __pformat_putchars(str_sig+1, prec, stream);
1679
1680    /* Pad with 0s */
1681    for(int i = max_prec; i < prec; i++)
1682      __pformat_putc('0', stream);
1683  }
1684
1685  stream->precision = exp_strlen; /* force puts to emit */
1686
1687  __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream );
1688  __pformat_putc( in.exp_neg ? '-' : '+', stream );
1689
1690  for(int32_t trailing = 0; trailing < 3 - exp_strlen; trailing++)
1691    __pformat_putc('0', stream);
1692  __pformat_putchars(str_exp, exp_strlen,stream);
1693}
1694
1695static
1696void  __pformat_float_decimal(_Decimal128 x, __pformat_t *stream ){
1697  decimal128_decode in;
1698  char str_exp[8];
1699  char str_sig[40];
1700  int floatclass = __fpclassifyd128(x);
1701
1702  /* precision control */
1703  int prec = ( (stream->precision < 0) || (stream->precision > 38) ) ?
1704    6 : stream->precision;
1705  int max_prec;
1706
1707  dec128_decode(&in,x);
1708
1709  if((floatclass & FP_INFINITE) == FP_INFINITE){
1710    stream->precision = 3;
1711    if(stream->flags & PFORMAT_SIGNED)
1712      __pformat_putc( in.sig_neg ? '-' : '+', stream );
1713    __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "inf" : "INF", stream);
1714    return;
1715  } else if(floatclass & FP_NAN){
1716    stream->precision = 3;
1717    if(stream->flags & PFORMAT_SIGNED)
1718      __pformat_putc( in.sig_neg ? '-' : '+', stream );
1719    __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "nan" : "NAN", stream);
1720    return;
1721  }
1722
1723  /* Stringify significand */
1724  __bigint_to_string(
1725    (uint32_t[4]){in.significand[0] & 0x0ffffffff, in.significand[0] >> 32, in.significand[1] & 0x0ffffffff, in.significand[1] >> 32 },
1726    4, str_sig, sizeof(str_sig));
1727  __bigint_trim_leading_zeroes(str_sig,0);
1728  max_prec = strlen(str_sig);
1729
1730  /* stringify exponent */
1731  __bigint_to_string(
1732    (uint32_t[1]) { in.exp_neg ? -in.exponent : in.exponent},
1733    1, str_exp, sizeof(str_exp));
1734  __bigint_trim_leading_zeroes(str_exp,0);
1735
1736  int32_t decimal_place = max_prec + in.exponent;
1737  int32_t sig_written = 0;
1738
1739  /*account for . +- */
1740  for(int32_t spacers = 0; spacers < stream->width - decimal_place - prec - 2; spacers++)
1741    __pformat_putc( ' ', stream );
1742
1743  if (in.sig_neg || (stream->flags & PFORMAT_SIGNED)) {
1744    __pformat_putc( in.sig_neg ? '-' : '+', stream );
1745  } else if(stream->width - decimal_place - prec - 1 > 0){
1746    __pformat_putc( ' ', stream );
1747  }
1748
1749  if(decimal_place <= 0){ /* easy mode */
1750    __pformat_putc( '0', stream );
1751    points:
1752    __pformat_emit_radix_point(stream);
1753    for(int32_t written = 0; written < prec; written++){
1754      if(decimal_place < 0){ /* leading 0s */
1755        decimal_place++;
1756        __pformat_putc( '0', stream );
1757      /* significand */
1758      } else if ( sig_written < max_prec ){
1759        __pformat_putc( str_sig[sig_written], stream );
1760        sig_written++;
1761      } else { /* trailing 0s */
1762        __pformat_putc( '0', stream );
1763      }
1764    }
1765  } else { /* hard mode */
1766    for(; sig_written < decimal_place; sig_written++){
1767      __pformat_putc( str_sig[sig_written], stream );
1768      if(sig_written == max_prec - 1) break;
1769    }
1770    decimal_place -= sig_written;
1771    for(; decimal_place > 0; decimal_place--)
1772      __pformat_putc( '0', stream );
1773      goto points;
1774  }
1775
1776  return;
1777}
1778
1779static
1780void  __pformat_gfloat_decimal(_Decimal128 x, __pformat_t *stream ){
1781  int prec = ( (stream->precision < 0)) ?
1782    6 : stream->precision;
1783  decimal128_decode in;
1784  dec128_decode(&in,x);
1785  if(in.exponent > prec) __pformat_efloat_decimal(x,stream);
1786  else __pformat_float_decimal(x,stream);
1787}
1788
1789#endif /* __ENABLE_DFP */
1790
1791static
1792void __pformat_efloat( long double x, __pformat_t *stream )
1793{
1794  /* Handler for `%e' and `%E' format specifiers.
1795   *
1796   * This wraps calls to `__pformat_cvt()', `__pformat_emit_efloat()'
1797   * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1798   * output in floating point format.
1799   */
1800  int sign, intlen; char *value;
1801
1802  /* Establish the precision for the displayed value, defaulting to six
1803   * digits following the decimal point, if not explicitly specified.
1804   */
1805  if( stream->precision < 0 )
1806    stream->precision = 6;
1807
1808  /* Encode the input value as ASCII, for display...
1809   */
1810  value = __pformat_ecvt( x, stream->precision + 1, &intlen, &sign );
1811
1812  if( intlen == PFORMAT_INFNAN )
1813    /*
1814     * handle cases of `infinity' or `not-a-number'...
1815     */
1816    __pformat_emit_inf_or_nan( sign, value, stream );
1817
1818  else
1819    /* or otherwise, emit the formatted result.
1820     */
1821    __pformat_emit_efloat( sign, value, intlen, stream );
1822
1823  /* Clean up `__pformat_ecvt()' memory allocation for `value'...
1824   */
1825  __pformat_ecvt_release( value );
1826}
1827
1828static
1829void __pformat_gfloat( long double x, __pformat_t *stream )
1830{
1831  /* Handler for `%g' and `%G' format specifiers.
1832   *
1833   * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()',
1834   * `__pformat_emit_efloat()' and `__pformat_emit_inf_or_nan()', as
1835   * appropriate, to achieve output in the more suitable of either
1836   * fixed or floating point format.
1837   */
1838  int sign, intlen; char *value;
1839
1840  /* Establish the precision for the displayed value, defaulting to
1841   * six significant digits, if not explicitly specified...
1842   */
1843  if( stream->precision < 0 )
1844    stream->precision = 6;
1845
1846  /* or to a minimum of one digit, otherwise...
1847   */
1848  else if( stream->precision == 0 )
1849    stream->precision = 1;
1850
1851  /* Encode the input value as ASCII, for display.
1852   */
1853  value = __pformat_ecvt( x, stream->precision, &intlen, &sign );
1854
1855  if( intlen == PFORMAT_INFNAN )
1856    /*
1857     * Handle cases of `infinity' or `not-a-number'.
1858     */
1859    __pformat_emit_inf_or_nan( sign, value, stream );
1860
1861  else if( (-4 < intlen) && (intlen <= stream->precision) )
1862  {
1863    /* Value lies in the acceptable range for fixed point output,
1864     * (i.e. the exponent is no less than minus four, and the number
1865     * of significant digits which precede the radix point is fewer
1866     * than the least number which would overflow the field width,
1867     * specified or implied by the established precision).
1868     */
1869    if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1870      /*
1871       * The `#' flag is in effect...
1872       * Adjust precision to retain the specified number of significant
1873       * digits, with the proper number preceding the radix point, and
1874       * the balance following it...
1875       */
1876      stream->precision -= intlen;
1877
1878    else
1879      /* The `#' flag is not in effect...
1880       * Here we adjust the precision to accommodate all digits which
1881       * precede the radix point, but we truncate any balance following
1882       * it, to suppress output of non-significant trailing zeros...
1883       */
1884      if( ((stream->precision = strlen( value ) - intlen) < 0)
1885        /*
1886         * This may require a compensating adjustment to the field
1887         * width, to accommodate significant trailing zeros, which
1888         * precede the radix point...
1889         */
1890      && (stream->width > 0)  )
1891        stream->width += stream->precision;
1892
1893    /* Now, we format the result as any other fixed point value.
1894     */
1895    __pformat_emit_float( sign, value, intlen, stream );
1896
1897    /* If there is any residual field width as yet unfilled, then
1898     * we must be doing flush left justification, so pad out to the
1899     * right hand field boundary.
1900     */
1901    while( stream->width-- > 0 )
1902      __pformat_putc( '\x20', stream );
1903  }
1904
1905  else
1906  { /* Value lies outside the acceptable range for fixed point;
1907     * one significant digit will precede the radix point, so we
1908     * decrement the precision to retain only the appropriate number
1909     * of additional digits following it, when we emit the result
1910     * in floating point format.
1911     */
1912    if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1913      /*
1914       * The `#' flag is in effect...
1915       * Adjust precision to emit the specified number of significant
1916       * digits, with one preceding the radix point, and the balance
1917       * following it, retaining any non-significant trailing zeros
1918       * which are required to exactly match the requested precision...
1919       */
1920      stream->precision--;
1921
1922    else
1923      /* The `#' flag is not in effect...
1924       * Adjust precision to emit only significant digits, with one
1925       * preceding the radix point, and any others following it, but
1926       * suppressing non-significant trailing zeros...
1927       */
1928      stream->precision = strlen( value ) - 1;
1929
1930    /* Now, we format the result as any other floating point value.
1931     */
1932    __pformat_emit_efloat( sign, value, intlen, stream );
1933  }
1934
1935  /* Clean up `__pformat_ecvt()' memory allocation for `value'.
1936   */
1937  __pformat_ecvt_release( value );
1938}
1939
1940static
1941void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream )
1942{
1943  /* Helper for emitting floating point data, originating as
1944   * either `double' or `long double' type, as a hexadecimal
1945   * representation of the argument value.
1946   */
1947  char buf[18 + 6], *p = buf;
1948  __pformat_intarg_t exponent; short exp_width = 2;
1949
1950  if (value.__pformat_fpreg_mantissa != 0 ||
1951     value.__pformat_fpreg_exponent != 0)
1952  {
1953    /* Reduce the exponent since the leading digit emited will start at
1954     * the 4th bit from the highest order bit instead, the later being
1955     * the leading digit of the floating point. Don't do this adjustment
1956     * if the value is an actual zero.
1957     */
1958    value.__pformat_fpreg_exponent -= 3;
1959  }
1960
1961  /* The mantissa field of the argument value representation can
1962   * accommodate at most 16 hexadecimal digits, of which one will
1963   * be placed before the radix point, leaving at most 15 digits
1964   * to satisfy any requested precision; thus...
1965   */
1966  if( (stream->precision >= 0) && (stream->precision < 15) )
1967  {
1968    /* When the user specifies a precision within this range,
1969     * we want to adjust the mantissa, to retain just the number
1970     * of digits required, rounding up when the high bit of the
1971     * leftmost discarded digit is set; (mask of 0x08 accounts
1972     * for exactly one digit discarded, shifting 4 bits per
1973     * digit, with up to 14 additional digits, to consume the
1974     * full availability of 15 precision digits).
1975     */
1976
1977    /* We then shift the mantissa one bit position back to the
1978     * right, to guard against possible overflow when the rounding
1979     * adjustment is added.
1980     */
1981    value.__pformat_fpreg_mantissa >>= 1;
1982
1983    /* We now add the rounding adjustment, noting that to keep the
1984     * 0x08 mask aligned with the shifted mantissa, we also need to
1985     * shift it right by one bit initially, changing its starting
1986     * value to 0x04...
1987     */
1988    value.__pformat_fpreg_mantissa += 0x04LL << (4 * (14 - stream->precision));
1989    if( (value.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0ULL )
1990      /*
1991       * When the rounding adjustment would not have overflowed,
1992       * then we shift back to the left again, to fill the vacated
1993       * bit we reserved to accommodate the carry.
1994       */
1995      value.__pformat_fpreg_mantissa <<= 1;
1996
1997    else
1998    {
1999      /* Otherwise the rounding adjustment would have overflowed,
2000       * so the carry has already filled the vacated bit; the effect
2001       * of this is equivalent to an increment of the exponent. We will
2002       * discard a whole digit to match glibc's behavior.
2003       */
2004      value.__pformat_fpreg_exponent += 4;
2005      value.__pformat_fpreg_mantissa >>= 3;
2006    }
2007
2008    /* We now complete the rounding to the required precision, by
2009     * shifting the unwanted digits out, from the right hand end of
2010     * the mantissa.
2011     */
2012    value.__pformat_fpreg_mantissa >>= 4 * (15 - stream->precision);
2013  }
2014
2015  /* Don't print anything if mantissa is zero unless we have to satisfy
2016   * desired precision.
2017   */
2018  if( value.__pformat_fpreg_mantissa || stream->precision > 0 )
2019  {
2020    /* Encode the significant digits of the mantissa in hexadecimal
2021     * ASCII notation, ready for transfer to the output stream...
2022     */
2023    for( int i=stream->precision >= 15 || stream->precision < 0 ? 16 : stream->precision + 1; i>0; --i )
2024    {
2025      /* taking the rightmost digit in each pass...
2026       */
2027      unsigned c = value.__pformat_fpreg_mantissa & 0xF;
2028      if( i == 1 )
2029      {
2030        /* inserting the radix point, when we reach the last,
2031         * (i.e. the most significant digit), unless we found no
2032         * less significant digits, with no mandatory radix point
2033         * inclusion, and no additional required precision...
2034         */
2035        if( (p > buf)
2036        ||  (stream->flags & PFORMAT_HASHED) || (stream->precision > 0)  )
2037        {
2038          /*
2039           * Internally, we represent the radix point as an ASCII '.';
2040           * we will replace it with any locale specific alternative,
2041           * at the time of transfer to the ultimate destination.
2042           */
2043          *p++ = '.';
2044        }
2045      }
2046
2047      else if( stream->precision > 0 )
2048        /*
2049        * we have not yet fulfilled the desired precision,
2050        * and we have not yet found the most significant digit,
2051        * so account for the current digit, within the field
2052        * width required to meet the specified precision.
2053        */
2054        stream->precision--;
2055
2056      if( (c > 0) || (p > buf) || (stream->precision >= 0) )
2057      {
2058        /*
2059         * Ignoring insignificant trailing zeros, (unless required to
2060         * satisfy specified precision), store the current encoded digit
2061         * into the pending output buffer, in LIFO order, and using the
2062         * appropriate case for digits in the `A'..`F' range.
2063         */
2064        *p++ = c > 9 ? (c - 10 + 'A') | (stream->flags & PFORMAT_XCASE) : c + '0';
2065      }
2066      /* Shift out the current digit, (4-bit logical shift right),
2067       * to align the next more significant digit to be extracted,
2068       * and encoded in the next pass.
2069       */
2070      value.__pformat_fpreg_mantissa >>= 4;
2071    }
2072  }
2073
2074  if( p == buf )
2075  {
2076    /* Nothing has been queued for output...
2077     * We need at least one zero, and possibly a radix point.
2078     */
2079    if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
2080      *p++ = '.';
2081
2082    *p++ = '0';
2083  }
2084
2085  if( stream->width > 0 )
2086  {
2087  /* Adjust the user specified field width, to account for the
2088   * number of digits minimally required, to display the encoded
2089   * value, at the requested precision.
2090   *
2091   * FIXME: this uses the minimum number of digits possible for
2092   * representation of the binary exponent, in strict conformance
2093   * with C99 and POSIX specifications.  Although there appears to
2094   * be no Microsoft precedent for doing otherwise, we may wish to
2095   * relate this to the `_get_output_format()' result, to maintain
2096   * consistency with `%e', `%f' and `%g' styles.
2097   */
2098    int min_width = p - buf;
2099    int exponent2 = value.__pformat_fpreg_exponent;
2100
2101    /* If we have not yet queued sufficient digits to fulfil the
2102     * requested precision, then we must adjust the minimum width
2103     * specification, to accommodate the additional digits which
2104     * are required to do so.
2105     */
2106    if( stream->precision > 0 )
2107      min_width += stream->precision;
2108
2109    /* Adjust the minimum width requirement, to accomodate the
2110     * sign, radix indicator and at least one exponent digit...
2111     */
2112    min_width += stream->flags & PFORMAT_SIGNED ? 6 : 5;
2113    while( (exponent2 = exponent2 / 10) != 0 )
2114    {
2115      /* and increase as required, if additional exponent digits
2116       * are needed, also saving the exponent field width adjustment,
2117       * for later use when that is emitted.
2118       */
2119      min_width++;
2120      exp_width++;
2121    }
2122
2123    if( stream->width > min_width )
2124    {
2125      /* When specified field width exceeds the minimum required,
2126       * adjust to retain only the excess...
2127       */
2128      stream->width -= min_width;
2129
2130      /* and then emit any required left side padding spaces.
2131       */
2132      if( (stream->flags & PFORMAT_JUSTIFY) == 0 )
2133        while( stream->width-- > 0 )
2134          __pformat_putc( '\x20', stream );
2135    }
2136
2137    else
2138      /* Specified field width is insufficient; just ignore it!
2139       */
2140      stream->width = PFORMAT_IGNORE;
2141  }
2142
2143  /* Emit the sign of the encoded value, as required...
2144   */
2145  if( stream->flags & PFORMAT_NEGATIVE )
2146    /*
2147     * this is mandatory, to indicate a negative value...
2148     */
2149    __pformat_putc( '-', stream );
2150
2151  else if( stream->flags & PFORMAT_POSITIVE )
2152    /*
2153     * but this is optional, for a positive value...
2154     */
2155    __pformat_putc( '+', stream );
2156
2157  else if( stream->flags & PFORMAT_ADDSPACE )
2158    /*
2159     * with this optional alternative.
2160     */
2161    __pformat_putc( '\x20', stream );
2162
2163  /* Prefix a `0x' or `0X' radix indicator to the encoded value,
2164   * with case appropriate to the format specification.
2165   */
2166  __pformat_putc( '0', stream );
2167  __pformat_putc( 'X' | (stream->flags & PFORMAT_XCASE), stream );
2168
2169  /* If the `0' flag is in effect...
2170   * Zero padding, to fill out the field, goes here...
2171   */
2172  if( (stream->width > 0) && (stream->flags & PFORMAT_ZEROFILL) )
2173    while( stream->width-- > 0 )
2174      __pformat_putc( '0', stream );
2175
2176  /* Next, we emit the encoded value, without its exponent...
2177   */
2178  while( p > buf )
2179    __pformat_emit_numeric_value( *--p, stream );
2180
2181  /* followed by any additional zeros needed to satisfy the
2182   * precision specification...
2183   */
2184  while( stream->precision-- > 0 )
2185    __pformat_putc( '0', stream );
2186
2187  /* then the exponent prefix, (C99 and POSIX specify `p'),
2188   * in the case appropriate to the format specification...
2189   */
2190  __pformat_putc( 'P' | (stream->flags & PFORMAT_XCASE), stream );
2191
2192  /* and finally, the decimal representation of the binary exponent,
2193   * as a signed value with mandatory sign displayed, in a field width
2194   * adjusted to accommodate it, LEFT justified, with any additional
2195   * right side padding remaining from the original field width.
2196   */
2197  stream->width += exp_width;
2198  stream->flags |= PFORMAT_SIGNED;
2199  /* sign extend */
2200  exponent.__pformat_u128_t.t128.digits[1] = (value.__pformat_fpreg_exponent < 0) ? -1 : 0;
2201  exponent.__pformat_u128_t.t128.digits[0] = value.__pformat_fpreg_exponent;
2202  __pformat_int( exponent, stream );
2203}
2204
2205static
2206void __pformat_xldouble( long double x, __pformat_t *stream )
2207{
2208  /* Handler for `%La' and `%LA' format specifiers, (with argument
2209   * value specified as `long double' type).
2210   */
2211  unsigned sign_bit = 0;
2212  __pformat_fpreg_t z = init_fpreg_ldouble( x );
2213
2214  /* First check for NaN; it is emitted unsigned...
2215   */
2216  if( isnan( x ) )
2217    __pformat_emit_inf_or_nan( sign_bit, "NaN", stream );
2218
2219  else
2220  { /* Capture the sign bit up-front, so we can show it correctly
2221     * even when the argument value is zero or infinite.
2222     */
2223    if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 )
2224      stream->flags |= PFORMAT_NEGATIVE;
2225
2226    /* Check for infinity, (positive or negative)...
2227     */
2228    if( isinf( x ) )
2229      /*
2230       * displaying the appropriately signed indicator,
2231       * when appropriate.
2232       */
2233      __pformat_emit_inf_or_nan( sign_bit, "Inf", stream );
2234
2235    else
2236    { /* The argument value is a representable number...
2237       * extract the effective value of the biased exponent...
2238       */
2239      z.__pformat_fpreg_exponent &= 0x7FFF;
2240      if( z.__pformat_fpreg_exponent == 0 )
2241      {
2242        /* A biased exponent value of zero means either a
2243         * true zero value, if the mantissa field also has
2244         * a zero value, otherwise...
2245         */
2246        if( z.__pformat_fpreg_mantissa != 0 )
2247        {
2248          /* ...this mantissa represents a subnormal value.
2249           */
2250          z.__pformat_fpreg_exponent = 1 - 0x3FFF;
2251        }
2252      }
2253      else
2254        /* This argument represents a non-zero normal number;
2255         * eliminate the bias from the exponent...
2256         */
2257        z.__pformat_fpreg_exponent -= 0x3FFF;
2258
2259      /* Finally, hand the adjusted representation off to the
2260       * generalised hexadecimal floating point format handler...
2261       */
2262      __pformat_emit_xfloat( z, stream );
2263    }
2264  }
2265}
2266
2267static
2268void __pformat_xdouble( double x, __pformat_t *stream )
2269{
2270  /* Handler for `%la' and `%lA' format specifiers, (with argument
2271   * value specified as `double' type).
2272   */
2273  unsigned sign_bit = 0;
2274  __pformat_fpreg_t z = init_fpreg_ldouble( (long double)x );
2275
2276  /* First check for NaN; it is emitted unsigned...
2277   */
2278  if( isnan( x ) )
2279    __pformat_emit_inf_or_nan( sign_bit, "NaN", stream );
2280
2281  else
2282  { /* Capture the sign bit up-front, so we can show it correctly
2283     * even when the argument value is zero or infinite.
2284     */
2285    if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 )
2286      stream->flags |= PFORMAT_NEGATIVE;
2287
2288    /* Check for infinity, (positive or negative)...
2289     */
2290    if( isinf( x ) )
2291      /*
2292       * displaying the appropriately signed indicator,
2293       * when appropriate.
2294       */
2295      __pformat_emit_inf_or_nan( sign_bit, "Inf", stream );
2296
2297    else
2298    { /* The argument value is a representable number...
2299       * extract the effective value of the biased exponent...
2300       */
2301      z.__pformat_fpreg_exponent &= 0x7FFF;
2302
2303      /* If the double value was a denormalized number, it might have been renormalized by
2304       * the conversion to long double. We will redenormalize it.
2305       */
2306      if( z.__pformat_fpreg_exponent != 0 && z.__pformat_fpreg_exponent <= (0x3FFF - 0x3FF) )
2307      {
2308        int shifted = (0x3FFF - 0x3FF) - z.__pformat_fpreg_exponent + 1;
2309        z.__pformat_fpreg_mantissa >>= shifted;
2310        z.__pformat_fpreg_exponent += shifted;
2311      }
2312
2313      if( z.__pformat_fpreg_exponent == 0 )
2314      {
2315        /* A biased exponent value of zero means either a
2316         * true zero value, if the mantissa field also has
2317         * a zero value, otherwise...
2318         */
2319        if( z.__pformat_fpreg_mantissa != 0 )
2320        {
2321          /* ...this mantissa represents a subnormal value.
2322           */
2323          z.__pformat_fpreg_exponent = 1 - 0x3FF + 3;
2324        }
2325      }
2326      else
2327        /* This argument represents a non-zero normal number;
2328         * eliminate the bias from the exponent...
2329         */
2330        z.__pformat_fpreg_exponent -= 0x3FFF - 3;
2331
2332      /* Shift the mantissa so the leading 4 bits digit is 0 or 1.
2333       * The exponent was also adjusted by 3 previously.
2334       */
2335      z.__pformat_fpreg_mantissa >>= 3;
2336
2337      /* Finally, hand the adjusted representation off to the
2338       * generalised hexadecimal floating point format handler...
2339       */
2340      __pformat_emit_xfloat( z, stream );
2341    }
2342  }
2343}
2344
2345int
2346__pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv)
2347{
2348  int c;
2349  int saved_errno = errno;
2350
2351  __pformat_t stream =
2352  {
2353    /* Create and initialise a format control block
2354     * for this output request.
2355     */
2356    dest,                                       /* output goes to here        */
2357    flags &= PFORMAT_TO_FILE | PFORMAT_NOLIMIT, /* only these valid initially */
2358    PFORMAT_IGNORE,                             /* no field width yet         */
2359    PFORMAT_IGNORE,                             /* nor any precision spec     */
2360    PFORMAT_RPINIT,                             /* radix point uninitialised  */
2361    (wchar_t)(0),                               /* leave it unspecified       */
2362    0,
2363    (wchar_t)(0),                               /* leave it unspecified       */
2364    0,                                          /* zero output char count     */
2365    max,                                        /* establish output limit     */
2366    -1                                          /* exponent chars preferred;
2367                                                   -1 means to be determined. */
2368  };
2369
2370#ifdef __BUILD_WIDEAPI
2371  const APICHAR *literal_string_start = NULL;
2372#endif
2373
2374  format_scan: while( (c = *fmt++) != 0 )
2375  {
2376    /* Format string parsing loop...
2377     * The entry point is labelled, so that we can return to the start state
2378     * from within the inner `conversion specification' interpretation loop,
2379     * as soon as a conversion specification has been resolved.
2380     */
2381    if( c == '%' )
2382    {
2383      /* Initiate parsing of a `conversion specification'...
2384       */
2385      __pformat_intarg_t argval;
2386      __pformat_state_t  state = PFORMAT_INIT;
2387      __pformat_length_t length = PFORMAT_LENGTH_INT;
2388
2389      /* Save the current format scan position, so that we can backtrack
2390       * in the event of encountering an invalid format specification...
2391       */
2392      const APICHAR *backtrack = fmt;
2393
2394      /* Restart capture for dynamic field width and precision specs...
2395       */
2396      int *width_spec = &stream.width;
2397
2398  #ifdef __BUILD_WIDEAPI
2399      if (literal_string_start)
2400      {
2401        stream.width = stream.precision = PFORMAT_IGNORE;
2402        __pformat_wputchars( literal_string_start, fmt - literal_string_start - 1, &stream );
2403        literal_string_start = NULL;
2404      }
2405  #endif
2406
2407      /* Reset initial state for flags, width and precision specs...
2408       */
2409      stream.flags = flags;
2410      stream.width = stream.precision = PFORMAT_IGNORE;
2411
2412      while( *fmt )
2413      {
2414        switch( c = *fmt++ )
2415        {
2416          /* Data type specifiers...
2417           * All are terminal, so exit the conversion spec parsing loop
2418           * with a `goto format_scan', thus resuming at the outer level
2419           * in the regular format string parser.
2420           */
2421          case '%':
2422            /*
2423             * Not strictly a data type specifier...
2424             * it simply converts as a literal `%' character.
2425             *
2426             * FIXME: should we require this to IMMEDIATELY follow the
2427             * initial `%' of the "conversion spec"?  (glibc `printf()'
2428             * on GNU/Linux does NOT appear to require this, but POSIX
2429             * and SUSv3 do seem to demand it).
2430             */
2431    #ifndef __BUILD_WIDEAPI
2432            __pformat_putc( c, &stream );
2433    #else
2434        stream.width = stream.precision = PFORMAT_IGNORE;
2435        __pformat_wputchars( L"%", 1, &stream );
2436    #endif
2437            goto format_scan;
2438
2439          case 'C':
2440            /*
2441             * Equivalent to `%lc'; set `length' accordingly,
2442             * and simply fall through.
2443             */
2444            length = PFORMAT_LENGTH_LONG;
2445
2446            /* fallthrough */
2447
2448          case 'c':
2449            /*
2450             * Single, (or single multibyte), character output...
2451             *
2452             * We handle these by copying the argument into our local
2453             * `argval' buffer, and then we pass the address of that to
2454             * either `__pformat_putchars()' or `__pformat_wputchars()',
2455             * as appropriate, effectively formatting it as a string of
2456             * the appropriate type, with a length of one.
2457             *
2458             * A side effect of this method of handling character data
2459             * is that, if the user sets a precision of zero, then no
2460             * character is actually emitted; we don't want that, so we
2461             * forcibly override any user specified precision.
2462             */
2463            stream.precision = PFORMAT_IGNORE;
2464
2465            /* Now we invoke the appropriate format handler...
2466             */
2467            if( (length == PFORMAT_LENGTH_LONG)
2468            ||  (length == PFORMAT_LENGTH_LLONG)  )
2469            {
2470              /* considering any `long' type modifier as a reference to
2471               * `wchar_t' data, (which is promoted to an `int' argument)...
2472               */
2473              wchar_t iargval = (wchar_t)(va_arg( argv, int ));
2474              __pformat_wputchars( &iargval, 1, &stream );
2475            }
2476            else
2477            { /* while anything else is simply taken as `char', (which
2478               * is also promoted to an `int' argument)...
2479               */
2480              argval.__pformat_uchar_t = (unsigned char)(va_arg( argv, int ));
2481              __pformat_putchars( (char *)(&argval), 1, &stream );
2482            }
2483            goto format_scan;
2484
2485          case 'S':
2486            /*
2487             * Equivalent to `%ls'; set `length' accordingly,
2488             * and simply fall through.
2489             */
2490            length = PFORMAT_LENGTH_LONG;
2491
2492            /* fallthrough */
2493
2494          case 's':
2495            if( (length == PFORMAT_LENGTH_LONG)
2496                 || (length == PFORMAT_LENGTH_LLONG))
2497            {
2498              /* considering any `long' type modifier as a reference to
2499               * a `wchar_t' string...
2500               */
2501              __pformat_wcputs( va_arg( argv, wchar_t * ), &stream );
2502            }
2503            else
2504              /* This is normal string output;
2505               * we simply invoke the appropriate handler...
2506               */
2507              __pformat_puts( va_arg( argv, char * ), &stream );
2508            goto format_scan;
2509          case 'm': /* strerror (errno)  */
2510            __pformat_puts (strerror (saved_errno), &stream);
2511            goto format_scan;
2512
2513          case 'o':
2514          case 'u':
2515          case 'x':
2516          case 'X':
2517            /*
2518             * Unsigned integer values; octal, decimal or hexadecimal format...
2519             */
2520            stream.flags &= ~PFORMAT_POSITIVE;
2521#if __ENABLE_PRINTF128
2522        argval.__pformat_u128_t.t128.digits[1] = 0LL; /* no sign extend needed */
2523            if( length == PFORMAT_LENGTH_LLONG128 )
2524              argval.__pformat_u128_t.t128 = va_arg( argv, __tI128 );
2525            else
2526#endif
2527        if( length == PFORMAT_LENGTH_LLONG ) {
2528              /*
2529               * with an `unsigned long long' argument, which we
2530               * process `as is'...
2531               */
2532              argval.__pformat_ullong_t = va_arg( argv, unsigned long long );
2533
2534            } else if( length == PFORMAT_LENGTH_LONG ) {
2535              /*
2536               * or with an `unsigned long', which we promote to
2537               * `unsigned long long'...
2538               */
2539              argval.__pformat_ullong_t = va_arg( argv, unsigned long );
2540
2541            } else
2542            { /* or for any other size, which will have been promoted
2543               * to `unsigned int', we select only the appropriately sized
2544               * least significant segment, and again promote to the same
2545               * size as `unsigned long long'...
2546               */
2547              argval.__pformat_ullong_t = va_arg( argv, unsigned int );
2548              if( length == PFORMAT_LENGTH_SHORT )
2549                /*
2550                 * from `unsigned short'...
2551                 */
2552                argval.__pformat_ullong_t = argval.__pformat_ushort_t;
2553
2554              else if( length == PFORMAT_LENGTH_CHAR )
2555                /*
2556                 * or even from `unsigned char'...
2557                 */
2558                argval.__pformat_ullong_t = argval.__pformat_uchar_t;
2559            }
2560
2561            /* so we can pass any size of argument to either of two
2562             * common format handlers...
2563             */
2564            if( c == 'u' )
2565              /*
2566               * depending on whether output is to be encoded in
2567               * decimal format...
2568               */
2569              __pformat_int( argval, &stream );
2570
2571            else
2572              /* or in octal or hexadecimal format...
2573               */
2574              __pformat_xint( c, argval, &stream );
2575
2576            goto format_scan;
2577
2578          case 'd':
2579          case 'i':
2580            /*
2581             * Signed integer values; decimal format...
2582             * This is similar to `u', but must process `argval' as signed,
2583             * and be prepared to handle negative numbers.
2584             */
2585            stream.flags |= PFORMAT_NEGATIVE;
2586#if __ENABLE_PRINTF128
2587            if( length == PFORMAT_LENGTH_LLONG128 ) {
2588              argval.__pformat_u128_t.t128 = va_arg( argv, __tI128 );
2589          goto skip_sign; /* skip sign extend */
2590            } else
2591#endif
2592            if( length == PFORMAT_LENGTH_LLONG ){
2593              /*
2594               * The argument is a `long long' type...
2595               */
2596              argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, long long );
2597            } else if( length == PFORMAT_LENGTH_LONG ) {
2598              /*
2599               * or here, a `long' type...
2600               */
2601              argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, long );
2602            } else
2603            { /* otherwise, it's an `int' type...
2604               */
2605              argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, int );
2606              if( length == PFORMAT_LENGTH_SHORT )
2607                /*
2608                 * but it was promoted from a `short' type...
2609                 */
2610                argval.__pformat_u128_t.t128.digits[0] = argval.__pformat_short_t;
2611              else if( length == PFORMAT_LENGTH_CHAR )
2612                /*
2613                 * or even from a `char' type...
2614                 */
2615                argval.__pformat_u128_t.t128.digits[0] = argval.__pformat_char_t;
2616            }
2617
2618            /* In any case, all share a common handler...
2619             */
2620        argval.__pformat_u128_t.t128.digits[1] = (argval.__pformat_llong_t < 0) ? -1LL : 0LL;
2621#if __ENABLE_PRINTF128
2622        skip_sign:
2623#endif
2624            __pformat_int( argval, &stream );
2625            goto format_scan;
2626
2627          case 'p':
2628            /*
2629             * Pointer argument; format as hexadecimal, subject to...
2630             */
2631            if( (state == PFORMAT_INIT) && (stream.flags == flags) )
2632            {
2633              /* Here, the user didn't specify any particular
2634               * formatting attributes.  We must choose a default
2635               * which will be compatible with Microsoft's (broken)
2636               * scanf() implementation, (i.e. matching the default
2637               * used by MSVCRT's printf(), which appears to resemble
2638               * "%0.8X" for 32-bit pointers); in particular, we MUST
2639               * NOT adopt a GNU-like format resembling "%#x", because
2640               * Microsoft's scanf() will choke on the "0x" prefix.
2641               */
2642              stream.flags |= PFORMAT_ZEROFILL;
2643              stream.precision = 2 * sizeof( uintptr_t );
2644            }
2645            argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, uintptr_t );
2646            argval.__pformat_u128_t.t128.digits[1] = 0;
2647            __pformat_xint( 'x', argval, &stream );
2648            goto format_scan;
2649
2650          case 'e':
2651            /*
2652             * Floating point format, with lower case exponent indicator
2653             * and lower case `inf' or `nan' representation when required;
2654             * select lower case mode, and simply fall through...
2655             */
2656            stream.flags |= PFORMAT_XCASE;
2657
2658            /* fallthrough */
2659
2660          case 'E':
2661            /*
2662             * Floating point format, with upper case exponent indicator
2663             * and upper case `INF' or `NAN' representation when required,
2664             * (or lower case for all of these, on fall through from above);
2665             * select lower case mode, and simply fall through...
2666             */
2667#ifdef __ENABLE_DFP
2668            if( stream.flags & PFORMAT_DECIM32 )
2669              /* Is a 32bit decimal float */
2670              __pformat_efloat_decimal((_Decimal128)va_arg( argv, _Decimal32 ), &stream );
2671            else if( stream.flags & PFORMAT_DECIM64 )
2672              /*
2673               * Is a 64bit decimal float
2674               */
2675              __pformat_efloat_decimal((_Decimal128)va_arg( argv, _Decimal64 ), &stream );
2676            else if( stream.flags & PFORMAT_DECIM128 )
2677              /*
2678               * Is a 128bit decimal float
2679               */
2680              __pformat_efloat_decimal(va_arg( argv, _Decimal128 ), &stream );
2681            else
2682#endif /* __ENABLE_DFP */
2683            if( stream.flags & PFORMAT_LDOUBLE )
2684              /*
2685               * for a `long double' argument...
2686               */
2687              __pformat_efloat( va_arg( argv, long double ), &stream );
2688
2689            else
2690              /* or just a `double', which we promote to `long double',
2691               * so the two may share a common format handler.
2692               */
2693              __pformat_efloat( (long double)(va_arg( argv, double )), &stream );
2694
2695            goto format_scan;
2696
2697          case 'f':
2698            /*
2699             * Fixed point format, using lower case for `inf' and
2700             * `nan', when appropriate; select lower case mode, and
2701             * simply fall through...
2702             */
2703            stream.flags |= PFORMAT_XCASE;
2704
2705            /* fallthrough */
2706
2707          case 'F':
2708            /*
2709             * Fixed case format using upper case, or lower case on
2710             * fall through from above, for `INF' and `NAN'...
2711             */
2712#ifdef __ENABLE_DFP
2713            if( stream.flags & PFORMAT_DECIM32 )
2714              /* Is a 32bit decimal float */
2715              __pformat_float_decimal((_Decimal128)va_arg( argv, _Decimal32 ), &stream );
2716            else if( stream.flags & PFORMAT_DECIM64 )
2717              /*
2718               * Is a 64bit decimal float
2719               */
2720              __pformat_float_decimal((_Decimal128)va_arg( argv, _Decimal64 ), &stream );
2721            else if( stream.flags & PFORMAT_DECIM128 )
2722              /*
2723               * Is a 128bit decimal float
2724               */
2725              __pformat_float_decimal(va_arg( argv, _Decimal128 ), &stream );
2726            else
2727#endif /* __ENABLE_DFP */
2728            if( stream.flags & PFORMAT_LDOUBLE )
2729              /*
2730               * for a `long double' argument...
2731               */
2732              __pformat_float( va_arg( argv, long double ), &stream );
2733
2734            else
2735              /* or just a `double', which we promote to `long double',
2736               * so the two may share a common format handler.
2737               */
2738              __pformat_float( (long double)(va_arg( argv, double )), &stream );
2739
2740            goto format_scan;
2741
2742          case 'g':
2743            /*
2744             * Generalised floating point format, with lower case
2745             * exponent indicator when required; select lower case
2746             * mode, and simply fall through...
2747             */
2748            stream.flags |= PFORMAT_XCASE;
2749
2750            /* fallthrough */
2751
2752          case 'G':
2753            /*
2754             * Generalised floating point format, with upper case,
2755             * or on fall through from above, with lower case exponent
2756             * indicator when required...
2757             */
2758#ifdef __ENABLE_DFP
2759            if( stream.flags & PFORMAT_DECIM32 )
2760              /* Is a 32bit decimal float */
2761              __pformat_gfloat_decimal((_Decimal128)va_arg( argv, _Decimal32 ), &stream );
2762            else if( stream.flags & PFORMAT_DECIM64 )
2763              /*
2764               * Is a 64bit decimal float
2765               */
2766              __pformat_gfloat_decimal((_Decimal128)va_arg( argv, _Decimal64 ), &stream );
2767            else if( stream.flags & PFORMAT_DECIM128 )
2768              /*
2769               * Is a 128bit decimal float
2770               */
2771              __pformat_gfloat_decimal(va_arg( argv, _Decimal128 ), &stream );
2772            else
2773#endif /* __ENABLE_DFP */
2774           if( stream.flags & PFORMAT_LDOUBLE )
2775              /*
2776               * for a `long double' argument...
2777               */
2778              __pformat_gfloat( va_arg( argv, long double ), &stream );
2779
2780            else
2781              /* or just a `double', which we promote to `long double',
2782               * so the two may share a common format handler.
2783               */
2784              __pformat_gfloat( (long double)(va_arg( argv, double )), &stream );
2785
2786            goto format_scan;
2787
2788          case 'a':
2789            /*
2790             * Hexadecimal floating point format, with lower case radix
2791             * and exponent indicators; select the lower case mode, and
2792             * fall through...
2793             */
2794            stream.flags |= PFORMAT_XCASE;
2795
2796            /* fallthrough */
2797
2798          case 'A':
2799            /*
2800             * Hexadecimal floating point format; handles radix and
2801             * exponent indicators in either upper or lower case...
2802             */
2803            if( sizeof( double ) != sizeof( long double ) && stream.flags & PFORMAT_LDOUBLE )
2804              /*
2805               * with a `long double' argument...
2806               */
2807              __pformat_xldouble( va_arg( argv, long double ), &stream );
2808
2809            else
2810              /* or just a `double'.
2811               */
2812              __pformat_xdouble( va_arg( argv, double ), &stream );
2813
2814            goto format_scan;
2815
2816          case 'n':
2817            /*
2818             * Save current output character count...
2819             */
2820            if( length == PFORMAT_LENGTH_CHAR )
2821              /*
2822               * to a signed `char' destination...
2823               */
2824              *va_arg( argv, char * ) = stream.count;
2825
2826            else if( length == PFORMAT_LENGTH_SHORT )
2827              /*
2828               * or to a signed `short'...
2829               */
2830              *va_arg( argv, short * ) = stream.count;
2831
2832            else if( length == PFORMAT_LENGTH_LONG )
2833              /*
2834               * or to a signed `long'...
2835               */
2836              *va_arg( argv, long * ) = stream.count;
2837
2838            else if( length == PFORMAT_LENGTH_LLONG )
2839              /*
2840               * or to a signed `long long'...
2841               */
2842              *va_arg( argv, long long * ) = stream.count;
2843
2844            else
2845              /*
2846               * or, by default, to a signed `int'.
2847               */
2848              *va_arg( argv, int * ) = stream.count;
2849
2850            goto format_scan;
2851
2852          /* Argument length modifiers...
2853           * These are non-terminal; each sets the format parser
2854           * into the PFORMAT_END state, and ends with a `break'.
2855           */
2856          case 'h':
2857            /*
2858             * Interpret the argument as explicitly of a `short'
2859             * or `char' data type, truncated from the standard
2860             * length defined for integer promotion.
2861             */
2862            if( *fmt == 'h' )
2863            {
2864              /* Modifier is `hh'; data type is `char' sized...
2865               * Skip the second `h', and set length accordingly.
2866               */
2867              ++fmt;
2868              length = PFORMAT_LENGTH_CHAR;
2869            }
2870
2871            else
2872              /* Modifier is `h'; data type is `short' sized...
2873               */
2874              length = PFORMAT_LENGTH_SHORT;
2875
2876            state = PFORMAT_END;
2877            break;
2878
2879          case 'j':
2880            /*
2881             * Interpret the argument as being of the same size as
2882             * a `intmax_t' entity...
2883             */
2884            length = __pformat_arg_length( intmax_t );
2885            state = PFORMAT_END;
2886            break;
2887
2888#         ifdef _WIN32
2889
2890            case 'I':
2891              /*
2892               * The MSVCRT implementation of the printf() family of
2893               * functions explicitly uses...
2894               */
2895#ifdef __ENABLE_PRINTF128
2896              if( (fmt[0] == '1') && (fmt[1] == '2') && (fmt[2] == '8')){
2897                length = PFORMAT_LENGTH_LLONG128;
2898                fmt += 3;
2899              } else
2900#endif
2901              if( (fmt[0] == '6') && (fmt[1] == '4') )
2902              {
2903                /* I64' instead of `ll',
2904                 * when referring to `long long' integer types...
2905                 */
2906                length = PFORMAT_LENGTH_LLONG;
2907                fmt += 2;
2908              } else
2909              if( (fmt[0] == '3') && (fmt[1] == '2') )
2910              {
2911                /* and `I32' instead of `l',
2912                 * when referring to `long' integer types...
2913                 */
2914                length = PFORMAT_LENGTH_LONG;
2915                fmt += 2;
2916              }
2917
2918              else
2919                /* or unqualified `I' instead of `t' or `z',
2920                 * when referring to `ptrdiff_t' or `size_t' entities;
2921                 * (we will choose to map it to `ptrdiff_t').
2922                 */
2923                length = __pformat_arg_length( ptrdiff_t );
2924
2925              state = PFORMAT_END;
2926              break;
2927
2928#         endif
2929
2930#ifdef __ENABLE_DFP
2931          case 'H':
2932              stream.flags |= PFORMAT_DECIM32;
2933              state = PFORMAT_END;
2934              break;
2935
2936          case 'D':
2937            /*
2938             * Interpret the argument as explicitly of a
2939             * `_Decimal64' or `_Decimal128' data type.
2940             */
2941            if( *fmt == 'D' )
2942            {
2943              /* Modifier is `DD'; data type is `_Decimal128' sized...
2944               * Skip the second `D', and set length accordingly.
2945               */
2946              ++fmt;
2947              stream.flags |= PFORMAT_DECIM128;
2948            }
2949
2950            else
2951              /* Modifier is `D'; data type is `_Decimal64' sized...
2952               */
2953              stream.flags |= PFORMAT_DECIM64;
2954
2955              state = PFORMAT_END;
2956              break;
2957#endif /* __ENABLE_DFP */
2958          case 'l':
2959            /*
2960             * Interpret the argument as explicitly of a
2961             * `long' or `long long' data type.
2962             */
2963            if( *fmt == 'l' )
2964            {
2965              /* Modifier is `ll'; data type is `long long' sized...
2966               * Skip the second `l', and set length accordingly.
2967               */
2968              ++fmt;
2969              length = PFORMAT_LENGTH_LLONG;
2970            }
2971
2972            else
2973              /* Modifier is `l'; data type is `long' sized...
2974               */
2975              length = PFORMAT_LENGTH_LONG;
2976
2977            state = PFORMAT_END;
2978            break;
2979
2980          case 'L':
2981            /*
2982             * Identify the appropriate argument as a `long double',
2983             * when associated with `%a', `%A', `%e', `%E', `%f', `%F',
2984             * `%g' or `%G' format specifications.
2985             */
2986            stream.flags |= PFORMAT_LDOUBLE;
2987            state = PFORMAT_END;
2988            break;
2989
2990          case 't':
2991            /*
2992             * Interpret the argument as being of the same size as
2993             * a `ptrdiff_t' entity...
2994             */
2995            length = __pformat_arg_length( ptrdiff_t );
2996            state = PFORMAT_END;
2997            break;
2998
2999          case 'z':
3000            /*
3001             * Interpret the argument as being of the same size as
3002             * a `size_t' entity...
3003             */
3004            length = __pformat_arg_length( size_t );
3005            state = PFORMAT_END;
3006            break;
3007
3008          /* Precision indicator...
3009           * May appear once only; it must precede any modifier
3010           * for argument length, or any data type specifier.
3011           */
3012          case '.':
3013            if( state < PFORMAT_GET_PRECISION )
3014            {
3015              /* We haven't seen a precision specification yet,
3016               * so initialise it to zero, (in case no digits follow),
3017               * and accept any following digits as the precision.
3018               */
3019              stream.precision = 0;
3020              width_spec = &stream.precision;
3021              state = PFORMAT_GET_PRECISION;
3022            }
3023
3024            else
3025              /* We've already seen a precision specification,
3026               * so this is just junk; proceed to end game.
3027               */
3028              state = PFORMAT_END;
3029
3030            /* Either way, we must not fall through here.
3031             */
3032            break;
3033
3034          /* Variable field width, or precision specification,
3035           * derived from the argument list...
3036           */
3037          case '*':
3038            /*
3039             * When this appears...
3040             */
3041            if(   width_spec
3042            &&  ((state == PFORMAT_INIT) || (state == PFORMAT_GET_PRECISION)) )
3043            {
3044              /* in proper context; assign to field width
3045               * or precision, as appropriate.
3046               */
3047              if( (*width_spec = va_arg( argv, int )) < 0 )
3048              {
3049                /* Assigned value was negative...
3050                 */
3051                if( state == PFORMAT_INIT )
3052                {
3053                  /* For field width, this is equivalent to
3054                   * a positive value with the `-' flag...
3055                   */
3056                  stream.flags |= PFORMAT_LJUSTIFY;
3057                  stream.width = -stream.width;
3058                }
3059
3060                else
3061                  /* while as a precision specification,
3062                   * it should simply be ignored.
3063                   */
3064                  stream.precision = PFORMAT_IGNORE;
3065              }
3066            }
3067
3068            else
3069              /* out of context; give up on width and precision
3070               * specifications for this conversion.
3071               */
3072              state = PFORMAT_END;
3073
3074            /* Mark as processed...
3075             * we must not see `*' again, in this context.
3076             */
3077            width_spec = NULL;
3078            break;
3079
3080          /* Formatting flags...
3081           * Must appear while in the PFORMAT_INIT state,
3082           * and are non-terminal, so again, end with `break'.
3083           */
3084          case '#':
3085            /*
3086             * Select alternate PFORMAT_HASHED output style.
3087             */
3088            if( state == PFORMAT_INIT )
3089              stream.flags |= PFORMAT_HASHED;
3090            break;
3091
3092          case '+':
3093            /*
3094             * Print a leading sign with numeric output,
3095             * for both positive and negative values.
3096             */
3097            if( state == PFORMAT_INIT )
3098              stream.flags |= PFORMAT_POSITIVE;
3099            break;
3100
3101          case '-':
3102            /*
3103             * Select left justification of displayed output
3104             * data, within the output field width, instead of
3105             * the default flush right justification.
3106             */
3107            if( state == PFORMAT_INIT )
3108              stream.flags |= PFORMAT_LJUSTIFY;
3109            break;
3110
3111            case '\'':
3112              /*
3113               * This is an XSI extension to the POSIX standard,
3114               * which we do not support, at present.
3115               */
3116              if (state == PFORMAT_INIT)
3117              {
3118                stream.flags |= PFORMAT_GROUPED; /* $$$$ */
3119                int len; wchar_t rpchr;
3120                mbstate_t cstate = {0};
3121                if ((len = mbrtowc( &rpchr, localeconv()->thousands_sep, 16, &cstate)) > 0)
3122                    stream.thousands_chr = rpchr;
3123                stream.thousands_chr_len = len;
3124              }
3125              break;
3126
3127          case '\x20':
3128            /*
3129             * Reserve a single space, within the output field,
3130             * for display of the sign of signed data; this will
3131             * be occupied by the minus sign, if the data value
3132             * is negative, or by a plus sign if the data value
3133             * is positive AND the `+' flag is also present, or
3134             * by a space otherwise.  (Technically, this flag
3135             * is redundant, if the `+' flag is present).
3136             */
3137            if( state == PFORMAT_INIT )
3138              stream.flags |= PFORMAT_ADDSPACE;
3139            break;
3140
3141          case '0':
3142            /*
3143             * May represent a flag, to activate the `pad with zeros'
3144             * option, or it may simply be a digit in a width or in a
3145             * precision specification...
3146             */
3147            if( state == PFORMAT_INIT )
3148            {
3149              /* This is the flag usage...
3150               */
3151              stream.flags |= PFORMAT_ZEROFILL;
3152              break;
3153            }
3154
3155            /* fallthrough */
3156
3157          default:
3158            /*
3159             * If we didn't match anything above, then we will check
3160             * for digits, which we may accumulate to generate field
3161             * width or precision specifications...
3162             */
3163            if( (state < PFORMAT_END) && ('9' >= c) && (c >= '0') )
3164            {
3165              if( state == PFORMAT_INIT )
3166                /*
3167                 * Initial digits explicitly relate to field width...
3168                 */
3169                state = PFORMAT_SET_WIDTH;
3170
3171              else if( state == PFORMAT_GET_PRECISION )
3172                /*
3173                 * while those following a precision indicator
3174                 * explicitly relate to precision.
3175                 */
3176                state = PFORMAT_SET_PRECISION;
3177
3178              if( width_spec )
3179              {
3180                /* We are accepting a width or precision specification...
3181                 */
3182                if( *width_spec < 0 )
3183                  /*
3184                   * and accumulation hasn't started yet; we simply
3185                   * initialise the accumulator with the current digit
3186                   * value, converting from ASCII to decimal.
3187                   */
3188                  *width_spec = c - '0';
3189
3190                else
3191                  /* Accumulation has already started; we perform a
3192                   * `leftwise decimal digit shift' on the accumulator,
3193                   * (i.e. multiply it by ten), then add the decimal
3194                   * equivalent value of the current digit.
3195                   */
3196                  *width_spec = *width_spec * 10 + c - '0';
3197              }
3198            }
3199
3200            else
3201            {
3202              /* We found a digit out of context, or some other character
3203               * with no designated meaning; reject this format specification,
3204               * backtrack, and emit it as literal text...
3205               */
3206              fmt = backtrack;
3207      #ifndef __BUILD_WIDEAPI
3208              __pformat_putc( '%', &stream );
3209      #else
3210          stream.width = stream.precision = PFORMAT_IGNORE;
3211          __pformat_wputchars( L"%", 1, &stream );
3212      #endif
3213              goto format_scan;
3214            }
3215        }
3216      }
3217    }
3218
3219    else
3220      /* We just parsed a character which is not included within any format
3221       * specification; we simply emit it as a literal.
3222       */
3223  #ifndef __BUILD_WIDEAPI
3224      __pformat_putc( c, &stream );
3225  #else
3226      if (literal_string_start == NULL)
3227        literal_string_start = fmt - 1;
3228  #endif
3229  }
3230
3231  /* When we have fully dispatched the format string, the return value is the
3232   * total number of bytes we transferred to the output destination.
3233   */
3234#ifdef __BUILD_WIDEAPI
3235  if (literal_string_start)
3236  {
3237    stream.width = stream.precision = PFORMAT_IGNORE;
3238    __pformat_wputchars( literal_string_start, fmt - literal_string_start - 1, &stream );
3239  }
3240#endif
3241
3242  return stream.count;
3243}
3244
3245/* $RCSfile: pformat.c,v $Revision: 1.9 $: end of file */
3246