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