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