1
/* FIXME: to be removed one day; for now we explicitly are not
2
* prepared to support the POSIX-XSI additions to the C99 standard.
4
#undef WITH_XSI_FEATURES
8
* $Id: pformat.c,v 1.4 2008/12/31 15:34:09 keithmarshall Exp $
10
* Provides a core implementation of the formatting capabilities
11
* common to the entire `printf()' family of functions; it conforms
12
* generally to C99 and SUSv3/POSIX specifications, with extensions
13
* to support Microsoft's non-standard format specifications.
15
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
17
* This is free software. You may redistribute and/or modify it as you
18
* see fit, without restriction of copyright.
20
* This software is provided "as is", in the hope that it may be useful,
21
* but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
22
* MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
23
* time will the author accept any form of liability for any damages,
24
* however caused, resulting from the use of this software.
26
* The elements of this implementation which deal with the formatting
27
* of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g'
28
* and `%G' format specifiers, but excluding the hexadecimal floating
29
* point `%a' and `%A' specifiers), make use of the `__gdtoa' function
30
* written by David M. Gay, and are modelled on his sample code, which
31
* has been deployed under its accompanying terms of use:--
33
******************************************************************
34
* Copyright (C) 1997, 1999, 2001 Lucent Technologies
37
* Permission to use, copy, modify, and distribute this software and
38
* its documentation for any purpose and without fee is hereby
39
* granted, provided that the above copyright notice appear in all
40
* copies and that both that the copyright notice and this
41
* permission notice and warranty disclaimer appear in supporting
42
* documentation, and that the name of Lucent or any of its entities
43
* not be used in advertising or publicity pertaining to
44
* distribution of the software without specific, written prior
47
* LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
48
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
49
* IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
50
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
51
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
52
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
53
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
55
******************************************************************
69
/* FIXME: The following belongs in values.h, but current MinGW
70
* has nothing useful there! OTOH, values.h is not a standard
71
* header, and it's use may be considered obsolete; perhaps it
72
* is better to just keep these definitions here.
83
#define _TYPEBITS(type) (sizeof(type) * CHAR_BIT)
85
#define LLONGBITS _TYPEBITS(long long)
87
#endif /* !defined _VALUES_H -- end of file */
89
#include "mingw_pformat.h"
91
/* Bit-map constants, defining the internal format control
92
* states, which propagate through the flags.
94
#define PFORMAT_HASHED 0x0800
95
#define PFORMAT_LJUSTIFY 0x0400
96
#define PFORMAT_ZEROFILL 0x0200
98
#define PFORMAT_JUSTIFY (PFORMAT_LJUSTIFY | PFORMAT_ZEROFILL)
99
#define PFORMAT_IGNORE -1
101
#define PFORMAT_SIGNED 0x01C0
102
#define PFORMAT_POSITIVE 0x0100
103
#define PFORMAT_NEGATIVE 0x0080
104
#define PFORMAT_ADDSPACE 0x0040
106
#define PFORMAT_XCASE 0x0020
108
#define PFORMAT_LDOUBLE 0x0004
110
/* `%o' format digit extraction mask, and shift count...
111
* (These are constant, and do not propagate through the flags).
113
#define PFORMAT_OMASK 0x0007
114
#define PFORMAT_OSHIFT 0x0003
116
/* `%x' and `%X' format digit extraction mask, and shift count...
117
* (These are constant, and do not propagate through the flags).
119
#define PFORMAT_XMASK 0x000F
120
#define PFORMAT_XSHIFT 0x0004
122
/* The radix point character, used in floating point formats, is
123
* localised on the basis of the active LC_NUMERIC locale category.
124
* It is stored locally, as a `wchar_t' entity, which is converted
125
* to a (possibly multibyte) character on output. Initialisation
126
* of the stored `wchar_t' entity, together with a record of its
127
* effective multibyte character length, is required each time
128
* `__pformat()' is entered, (static storage would not be thread
129
* safe), but this initialisation is deferred until it is actually
130
* needed; on entry, the effective character length is first set to
131
* the following value, (and the `wchar_t' entity is zeroed), to
132
* indicate that a call of `localeconv()' is needed, to complete
133
* the initialisation.
135
#define PFORMAT_RPINIT -3
137
/* The floating point format handlers return the following value
138
* for the radix point position index, when the argument value is
139
* infinite, or not a number.
141
#define PFORMAT_INFNAN -32768
145
* The Microsoft standard for printing `%e' format exponents is
146
* with a minimum of three digits, unless explicitly set otherwise,
147
* by a prior invocation of the `_set_output_format()' function.
149
* The following macro allows us to replicate this behaviour.
151
# define PFORMAT_MINEXP __pformat_exponent_digits()
153
* However, this feature is unsupported for versions of the
154
* MSVC runtime library prior to msvcr80.dll, and by default,
155
* MinGW uses an earlier version, (equivalent to msvcr60.dll),
156
* for which `_TWO_DIGIT_EXPONENT' will be undefined.
158
# ifndef _TWO_DIGIT_EXPONENT
159
# define _TWO_DIGIT_EXPONENT 1
162
* Irrespective of the MSVCRT version supported, *we* will add
163
* an additional capability, through the following inline function,
164
* which will allow the user to choose his own preferred default
165
* for `PRINTF_EXPONENT_DIGITS', through the simple expedient
166
* of defining it as an environment variable.
168
static __inline__ __attribute__((__always_inline__))
169
int __pformat_exponent_digits( void )
171
char *exponent_digits = getenv( "PRINTF_EXPONENT_DIGITS" );
172
return ((exponent_digits != NULL) && ((unsigned)(*exponent_digits - '0') < 3))
173
|| (_get_output_format() & _TWO_DIGIT_EXPONENT)
180
* When we don't care to mimic Microsoft's standard behaviour,
181
* we adopt the C99/POSIX standard of two digit exponents.
183
# define PFORMAT_MINEXP 2
188
/* A data type agnostic representation,
189
* for printf arguments of any integral data type...
191
signed long __pformat_long_t;
192
signed long long __pformat_llong_t;
193
unsigned long __pformat_ulong_t;
194
unsigned long long __pformat_ullong_t;
195
unsigned short __pformat_ushort_t;
196
unsigned char __pformat_uchar_t;
197
signed short __pformat_short_t;
198
signed char __pformat_char_t;
199
void * __pformat_ptr_t;
200
} __pformat_intarg_t;
204
/* Format interpreter state indices...
205
* (used to identify the active phase of format string parsing).
209
PFORMAT_GET_PRECISION,
210
PFORMAT_SET_PRECISION,
216
/* Argument length classification indices...
217
* (used for arguments representing integer data types).
219
PFORMAT_LENGTH_INT = 0,
220
PFORMAT_LENGTH_SHORT,
222
PFORMAT_LENGTH_LLONG,
224
} __pformat_length_t;
226
* And a macro to map any arbitrary data type to an appropriate
227
* matching index, selected from those above; the compiler should
228
* collapse this to a simple assignment.
230
#define __pformat_arg_length( type ) \
231
sizeof( type ) == sizeof( long long ) ? PFORMAT_LENGTH_LLONG : \
232
sizeof( type ) == sizeof( long ) ? PFORMAT_LENGTH_LONG : \
233
sizeof( type ) == sizeof( short ) ? PFORMAT_LENGTH_SHORT : \
234
sizeof( type ) == sizeof( char ) ? PFORMAT_LENGTH_CHAR : \
235
/* should never need this default */ PFORMAT_LENGTH_INT
239
/* Formatting and output control data...
240
* An instance of this control block is created, (on the stack),
241
* for each call to `__pformat()', and is passed by reference to
242
* each of the output handlers, as required.
256
void __pformat_putc( int c, __pformat_t *stream )
258
/* Place a single character into the `__pformat()' output queue,
259
* provided any specified output quota has not been exceeded.
261
if( (stream->flags & PFORMAT_NOLIMIT) || (stream->quota > stream->count) )
263
/* Either there was no quota specified,
264
* or the active quota has not yet been reached.
266
if( stream->flags & PFORMAT_TO_FILE )
268
* This is single character output to a FILE stream...
270
fputc( c, (FILE *)(stream->dest) );
273
/* Whereas, this is to an internal memory buffer...
275
((char *)(stream->dest))[stream->count] = c;
281
void __pformat_putchars( const char *s, int count, __pformat_t *stream )
283
/* Handler for `%c' and (indirectly) `%s' conversion specifications.
285
* Transfer characters from the string buffer at `s', character by
286
* character, up to the number of characters specified by `count', or
287
* if `precision' has been explicitly set to a value less than `count',
288
* stopping after the number of characters specified for `precision',
289
* to the `__pformat()' output stream.
291
* Characters to be emitted are passed through `__pformat_putc()', to
292
* ensure that any specified output quota is honoured.
294
if( (stream->precision >= 0) && (count > stream->precision) )
296
* Ensure that the maximum number of characters transferred doesn't
297
* exceed any explicitly set `precision' specification.
299
count = stream->precision;
301
/* Establish the width of any field padding required...
303
if( stream->width > count )
305
* as the number of spaces equivalent to the number of characters
306
* by which those to be emitted is fewer than the field width...
308
stream->width -= count;
311
/* ignoring any width specification which is insufficient.
313
stream->width = PFORMAT_IGNORE;
315
if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
317
* When not doing flush left justification, (i.e. the `-' flag
318
* is not set), any residual unreserved field width must appear
319
* as blank padding, to the left of the output string.
321
while( stream->width-- )
322
__pformat_putc( '\x20', stream );
328
* copying the requisite number of characters from the input.
330
__pformat_putc( *s++, stream );
332
/* If we still haven't consumed the entire specified field width,
333
* we must be doing flush left justification; any residual width
334
* must be filled with blanks, to the right of the output value.
336
while( stream->width-- > 0 )
337
__pformat_putc( '\x20', stream );
341
void __pformat_puts( const char *s, __pformat_t *stream )
343
/* Handler for `%s' conversion specifications.
345
* Transfer a NUL terminated character string, character by character,
346
* stopping when the end of the string is encountered, or if `precision'
347
* has been explicitly set, when the specified number of characters has
348
* been emitted, if that is less than the length of the input string,
349
* to the `__pformat()' output stream.
351
* This is implemented as a trivial call to `__pformat_putchars()',
352
* passing the length of the input string as the character count,
353
* (after first verifying that the input pointer is not NULL).
355
if( s == NULL ) s = "(null)";
356
__pformat_putchars( s, strlen( s ), stream );
360
void __pformat_wputchars( const wchar_t *s, int count, __pformat_t *stream )
362
/* Handler for `%C'(`%lc') and `%S'(`%ls') conversion specifications;
363
* (this is a wide character variant of `__pformat_putchars()').
365
* Each multibyte character sequence to be emitted is passed, byte
366
* by byte, through `__pformat_putc()', to ensure that any specified
367
* output quota is honoured.
369
char buf[16]; mbstate_t state; int len = wcrtomb( buf, L'\0', &state );
371
if( (stream->precision >= 0) && (count > stream->precision) )
373
* Ensure that the maximum number of characters transferred doesn't
374
* exceed any explicitly set `precision' specification.
376
count = stream->precision;
378
/* Establish the width of any field padding required...
380
if( stream->width > count )
382
* as the number of spaces equivalent to the number of characters
383
* by which those to be emitted is fewer than the field width...
385
stream->width -= count;
388
/* ignoring any width specification which is insufficient.
390
stream->width = PFORMAT_IGNORE;
392
if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
394
* When not doing flush left justification, (i.e. the `-' flag
395
* is not set), any residual unreserved field width must appear
396
* as blank padding, to the left of the output string.
398
while( stream->width-- )
399
__pformat_putc( '\x20', stream );
401
/* Emit the data, converting each character from the wide
402
* to the multibyte domain as we go...
404
while( (count-- > 0) && ((len = wcrtomb( buf, *s++, &state )) > 0) )
408
__pformat_putc( *p++, stream );
411
/* If we still haven't consumed the entire specified field width,
412
* we must be doing flush left justification; any residual width
413
* must be filled with blanks, to the right of the output value.
415
while( stream->width-- > 0 )
416
__pformat_putc( '\x20', stream );
419
static __inline__ __attribute__((__always_inline__))
420
void __pformat_wcputs( const wchar_t *s, __pformat_t *stream )
422
/* Handler for `%S' (`%ls') conversion specifications.
424
* Transfer a NUL terminated wide character string, character by
425
* character, converting to its equivalent multibyte representation
426
* on output, and stopping when the end of the string is encountered,
427
* or if `precision' has been explicitly set, when the specified number
428
* of characters has been emitted, if that is less than the length of
429
* the input string, to the `__pformat()' output stream.
431
* This is implemented as a trivial call to `__pformat_wputchars()',
432
* passing the length of the input string as the character count,
433
* (after first verifying that the input pointer is not NULL).
435
if( s == NULL ) s = L"(null)";
436
__pformat_wputchars( s, wcslen( s ), stream );
440
int __pformat_int_bufsiz( int bias, int size, __pformat_t *stream )
442
/* Helper to establish the size of the internal buffer, which
443
* is required to queue the ASCII decomposition of an integral
444
* data value, prior to transfer to the output stream.
446
size = ((size - 1 + LLONGBITS) / size) + bias;
447
size += (stream->precision > 0) ? stream->precision : 0;
448
return (size > stream->width) ? size : stream->width;
452
void __pformat_int( __pformat_intarg_t value, __pformat_t *stream )
454
/* Handler for `%d', `%i' and `%u' conversion specifications.
456
* Transfer the ASCII representation of an integer value parameter,
457
* formatted as a decimal number, to the `__pformat()' output queue;
458
* output will be truncated, if any specified quota is exceeded.
460
char buf[__pformat_int_bufsiz(1, PFORMAT_OSHIFT, stream)];
461
char *p = buf; int precision;
463
if( stream->flags & PFORMAT_NEGATIVE )
465
/* The input value might be negative, (i.e. it is a signed value)...
467
if( value.__pformat_llong_t < 0LL )
469
* It IS negative, but we want to encode it as unsigned,
470
* displayed with a leading minus sign, so convert it...
472
value.__pformat_llong_t = -value.__pformat_llong_t;
475
/* It is unequivocally a POSITIVE value, so turn off the
476
* request to prefix it with a minus sign...
478
stream->flags &= ~PFORMAT_NEGATIVE;
481
/* Encode the input value for display...
483
while( value.__pformat_ullong_t )
485
/* decomposing it into its constituent decimal digits,
486
* in order from least significant to most significant, using
487
* the local buffer as a LIFO queue in which to store them.
489
*p++ = '0' + (unsigned char)(value.__pformat_ullong_t % 10LL);
490
value.__pformat_ullong_t /= 10LL;
493
if( (stream->precision > 0)
494
&& ((precision = stream->precision - (p - buf)) > 0) )
496
* We have not yet queued sufficient digits to fill the field width
497
* specified for minimum `precision'; pad with zeros to achieve this.
499
while( precision-- > 0 )
502
if( (p == buf) && (stream->precision != 0) )
504
* Input value was zero; make sure we print at least one digit,
505
* unless the precision is also explicitly zero.
509
if( (stream->width > 0) && ((stream->width -= p - buf) > 0) )
511
/* We have now queued sufficient characters to display the input value,
512
* at the desired precision, but this will not fill the output field...
514
if( stream->flags & PFORMAT_SIGNED )
516
* We will fill one additional space with a sign...
520
if( (stream->precision < 0)
521
&& ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
523
* and the `0' flag is in effect, so we pad the remaining spaces,
524
* to the left of the displayed value, with zeros.
526
while( stream->width-- > 0 )
529
else if( (stream->flags & PFORMAT_LJUSTIFY) == 0 )
531
* the `0' flag is not in effect, and neither is the `-' flag,
532
* so we pad to the left of the displayed value with spaces, so that
533
* the value appears right justified within the output field.
535
while( stream->width-- > 0 )
536
__pformat_putc( '\x20', stream );
539
if( stream->flags & PFORMAT_NEGATIVE )
541
* A negative value needs a sign...
545
else if( stream->flags & PFORMAT_POSITIVE )
547
* A positive value may have an optionally displayed sign...
551
else if( stream->flags & PFORMAT_ADDSPACE )
553
* Space was reserved for displaying a sign, but none was emitted...
559
* Emit the accumulated constituent digits,
560
* in order from most significant to least significant...
562
__pformat_putc( *--p, stream );
564
while( stream->width-- > 0 )
566
* The specified output field has not yet been completely filled;
567
* the `-' flag must be in effect, resulting in a displayed value which
568
* appears left justified within the output field; we must pad the field
569
* to the right of the displayed value, by emitting additional spaces,
570
* until we reach the rightmost field boundary.
572
__pformat_putc( '\x20', stream );
576
void __pformat_xint( int fmt, __pformat_intarg_t value, __pformat_t *stream )
578
/* Handler for `%o', `%p', `%x' and `%X' conversions.
580
* These can be implemented using a simple `mask and shift' strategy;
581
* set up the mask and shift values appropriate to the conversion format,
582
* and allocate a suitably sized local buffer, in which to queue encoded
583
* digits of the formatted value, in preparation for output.
586
int mask = (fmt == 'o') ? PFORMAT_OMASK : PFORMAT_XMASK;
587
int shift = (fmt == 'o') ? PFORMAT_OSHIFT : PFORMAT_XSHIFT;
588
char buf[__pformat_int_bufsiz(2, shift, stream)];
591
while( value.__pformat_ullong_t )
593
/* Encode the specified non-zero input value as a sequence of digits,
594
* in the appropriate `base' encoding and in reverse digit order, each
595
* encoded in its printable ASCII form, with no leading zeros, using
596
* the local buffer as a LIFO queue in which to store them.
599
if( (*(q = p++) = '0' + (value.__pformat_ullong_t & mask)) > '9' )
600
*q = (*q + 'A' - '9' - 1) | (fmt & PFORMAT_XCASE);
601
value.__pformat_ullong_t >>= shift;
606
* Nothing was queued; input value must be zero, which should never be
607
* emitted in the `alternative' PFORMAT_HASHED style.
609
stream->flags &= ~PFORMAT_HASHED;
611
if( ((width = stream->precision) > 0) && ((width -= p - buf) > 0) )
613
* We have not yet queued sufficient digits to fill the field width
614
* specified for minimum `precision'; pad with zeros to achieve this.
619
else if( (fmt == 'o') && (stream->flags & PFORMAT_HASHED) )
621
* The field width specified for minimum `precision' has already
622
* been filled, but the `alternative' PFORMAT_HASHED style for octal
623
* output requires at least one initial zero; that will not have
624
* been queued, so add it now.
628
if( (p == buf) && (stream->precision != 0) )
630
* Still nothing queued for output, but the `precision' has not been
631
* explicitly specified as zero, (which is necessary if no output for
632
* an input value of zero is desired); queue exactly one zero digit.
636
if( stream->width > (width = p - buf) )
638
* Specified field width exceeds the minimum required...
639
* Adjust so that we retain only the additional padding width.
641
stream->width -= width;
644
/* Ignore any width specification which is insufficient.
646
stream->width = PFORMAT_IGNORE;
648
if( ((width = stream->width) > 0)
649
&& (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
651
* For `%#x' or `%#X' formats, (which have the `#' flag set),
652
* further reduce the padding width to accommodate the radix
657
if( (width > 0) && (stream->precision < 0)
658
&& ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
660
* When the `0' flag is set, and not overridden by the `-' flag,
661
* or by a specified precision, add sufficient leading zeros to
662
* consume the remaining field width.
667
if( (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
669
/* For formats other than octal, the PFORMAT_HASHED output style
670
* requires the addition of a two character radix indicator, as a
671
* prefix to the actual encoded numeric value.
677
if( (width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
679
* When not doing flush left justification, (i.e. the `-' flag
680
* is not set), any residual unreserved field width must appear
681
* as blank padding, to the left of the output value.
684
__pformat_putc( '\x20', stream );
688
* Move the queued output from the local buffer to the ultimate
689
* destination, in LIFO order.
691
__pformat_putc( *--p, stream );
693
/* If we still haven't consumed the entire specified field width,
694
* we must be doing flush left justification; any residual width
695
* must be filled with blanks, to the right of the output value.
698
__pformat_putc( '\x20', stream );
703
/* A multifaceted representation of an IEEE extended precision,
704
* (80-bit), floating point number, facilitating access to its
707
double __pformat_fpreg_double_t;
708
long double __pformat_fpreg_ldouble_t;
710
{ unsigned long long __pformat_fpreg_mantissa;
711
signed short __pformat_fpreg_exponent;
713
unsigned short __pformat_fpreg_bitmap[5];
714
unsigned long __pformat_fpreg_bits;
718
/* TODO: make this unconditional in final release...
719
* (see note at head of associated `#else' block.
721
#include "../gdtoa/gdtoa.h"
724
char *__pformat_cvt( int mode, __pformat_fpreg_t x, int nd, int *dp, int *sign )
726
/* Helper function, derived from David M. Gay's `g_xfmt()', calling
727
* his `__gdtoa()' function in a manner to provide extended precision
728
* replacements for `ecvt()' and `fcvt()'.
730
unsigned int k, e = 0; char *ep;
731
static FPI fpi = { 64, 1-16383-64+1, 32766-16383-64+1, FPI_Round_near, 0 };
733
/* Classify the argument into an appropriate `__gdtoa()' category...
735
if( (k = __fpclassifyl( x.__pformat_fpreg_ldouble_t )) & FP_NAN )
737
* identifying infinities or not-a-number...
739
k = (k & FP_NORMAL) ? STRTOG_Infinite : STRTOG_NaN;
741
else if( k & FP_NORMAL )
743
/* normal and near-zero `denormals'...
747
/* with appropriate exponent adjustment for a `denormal'...
754
/* or with `normal' exponent adjustment...
757
e = (x.__pformat_fpreg_exponent & 0x7FFF) - 0x3FFF - 63;
762
/* or, if none of the above, it's a zero, (positive or negative).
766
/* Check for negative values, always treating NaN as unsigned...
767
* (return value is zero for positive/unsigned; non-zero for negative).
769
*sign = (k == STRTOG_NaN) ? 0 : x.__pformat_fpreg_exponent & 0x8000;
771
/* Finally, get the raw digit string, and radix point position index.
773
return __gdtoa( &fpi, e, &x.__pformat_fpreg_bits, (int *) &k, mode, nd, dp, &ep );
776
static __inline__ __attribute__((__always_inline__))
777
char *__pformat_ecvt( long double x, int precision, int *dp, int *sign )
779
/* A convenience wrapper for the above...
780
* it emulates `ecvt()', but takes a `long double' argument.
782
__pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
783
return __pformat_cvt( 2, z, precision, dp, sign );
786
static __inline__ __attribute__((__always_inline__))
787
char *__pformat_fcvt( long double x, int precision, int *dp, int *sign )
789
/* A convenience wrapper for the above...
790
* it emulates `fcvt()', but takes a `long double' argument.
792
__pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
793
return __pformat_cvt( 3, z, precision, dp, sign );
796
/* The following are required, to clean up the `__gdtoa()' memory pool,
797
* after processing the data returned by the above.
799
#define __pformat_ecvt_release( value ) __freedtoa( value )
800
#define __pformat_fcvt_release( value ) __freedtoa( value )
804
* TODO: remove this before final release; it is included here as a
805
* convenience for testing, without requiring a working `__gdtoa()'.
808
char *__pformat_ecvt( long double x, int precision, int *dp, int *sign )
810
/* Define in terms of `ecvt()'...
812
char *retval = ecvt( (double)(x), precision, dp, sign );
813
if( isinf( x ) || isnan( x ) )
815
/* emulating `__gdtoa()' reporting for infinities and NaN.
817
*dp = PFORMAT_INFNAN;
820
/* Need to force the `sign' flag, (particularly for NaN).
829
char *__pformat_fcvt( long double x, int precision, int *dp, int *sign )
831
/* Define in terms of `fcvt()'...
833
char *retval = fcvt( (double)(x), precision, dp, sign );
834
if( isinf( x ) || isnan( x ) )
836
/* emulating `__gdtoa()' reporting for infinities and NaN.
838
*dp = PFORMAT_INFNAN;
841
/* Need to force the `sign' flag, (particularly for NaN).
849
/* No memory pool clean up needed, for these emulated cases...
851
#define __pformat_ecvt_release( value ) /* nothing to be done */
852
#define __pformat_fcvt_release( value ) /* nothing to be done */
854
/* TODO: end of conditional to be removed. */
857
/* Can't be inlined, as it uses alloca. */
859
void __pformat_emit_radix_point( __pformat_t *stream )
861
/* Helper to place a localised representation of the radix point
862
* character at the ultimate destination, when formatting fixed or
863
* floating point numbers.
865
if( stream->rplen == PFORMAT_RPINIT )
867
/* Radix point initialisation not yet completed;
868
* establish a multibyte to `wchar_t' converter...
870
int len; wchar_t rpchr; mbstate_t state;
872
/* Initialise the conversion state...
874
memset( &state, 0, sizeof( state ) );
876
/* Fetch and convert the localised radix point representation...
878
if( (len = mbrtowc( &rpchr, localeconv()->decimal_point, 16, &state )) > 0 )
880
* and store it, if valid.
882
stream->rpchr = rpchr;
884
/* In any case, store the reported effective multibyte length,
885
* (or the error flag), marking initialisation as `done'.
890
if( stream->rpchr != (wchar_t)(0) )
892
/* We have a localised radix point mark;
893
* establish a converter to make it a multibyte character...
895
int len; char buf[len = stream->rplen]; mbstate_t state;
897
/* Initialise the conversion state...
899
memset( &state, 0, sizeof( state ) );
901
/* Convert the `wchar_t' representation to multibyte...
903
if( (len = wcrtomb( buf, stream->rpchr, &state )) > 0 )
905
/* and copy to the output destination, when valid...
909
__pformat_putc( *p++, stream );
913
/* otherwise fall back to plain ASCII '.'...
915
__pformat_putc( '.', stream );
919
/* No localisation: just use ASCII '.'...
921
__pformat_putc( '.', stream );
924
static __inline__ __attribute__((__always_inline__))
925
void __pformat_emit_numeric_value( int c, __pformat_t *stream )
927
/* Convenience helper to transfer numeric data from an internal
928
* formatting buffer to the ultimate destination...
932
* converting this internal representation of the the radix
933
* point to the appropriately localised representation...
935
__pformat_emit_radix_point( stream );
938
/* and passing all other characters through, unmodified.
940
__pformat_putc( c, stream );
944
void __pformat_emit_inf_or_nan( int sign, char *value, __pformat_t *stream )
946
/* Helper to emit INF or NAN where a floating point value
947
* resolves to one of these special states.
953
/* We use the string formatting helper to display INF/NAN,
954
* but we don't want truncation if the precision set for the
955
* original floating point output request was insufficient;
958
stream->precision = PFORMAT_IGNORE;
962
* Negative infinity: emit the sign...
966
else if( stream->flags & PFORMAT_POSITIVE )
968
* Not negative infinity, but '+' flag is in effect;
969
* thus, we emit a positive sign...
973
else if( stream->flags & PFORMAT_ADDSPACE )
975
* No sign required, but space was reserved for it...
979
/* Copy the appropriate status indicator, up to a maximum of
980
* three characters, transforming to the case corresponding to
981
* the format specification...
983
for( i = 3; i > 0; --i )
984
*p++ = (*value++ & ~PFORMAT_XCASE) | (stream->flags & PFORMAT_XCASE);
986
/* and emit the result.
988
__pformat_putchars( buf, p - buf, stream );
992
void __pformat_emit_float( int sign, char *value, int len, __pformat_t *stream )
994
/* Helper to emit a fixed point representation of numeric data,
995
* as encoded by a prior call to `ecvt()' or `fcvt()'; (this does
996
* NOT include the exponent, for floating point format).
1000
/* The magnitude of `x' is greater than or equal to 1.0...
1001
* reserve space in the output field, for the required number of
1002
* decimal digits to be placed before the decimal point...
1004
if( stream->width > len )
1006
* adjusting as appropriate, when width is sufficient...
1008
stream->width -= len;
1011
/* or simply ignoring the width specification, if not.
1013
stream->width = PFORMAT_IGNORE;
1016
else if( stream->width > 0 )
1018
* The magnitude of `x' is less than 1.0...
1019
* reserve space for exactly one zero before the decimal point.
1023
/* Reserve additional space for the digits which will follow the
1026
if( (stream->width >= 0) && (stream->width > stream->precision) )
1028
* adjusting appropriately, when sufficient width remains...
1029
* (note that we must check both of these conditions, because
1030
* precision may be more negative than width, as a result of
1031
* adjustment to provide extra padding when trailing zeros
1032
* are to be discarded from "%g" format conversion with a
1033
* specified field width, but if width itself is negative,
1034
* then there is explicitly to be no padding anyway).
1036
stream->width -= stream->precision;
1039
/* or again, ignoring the width specification, if not.
1041
stream->width = PFORMAT_IGNORE;
1043
/* Reserve space in the output field, for display of the decimal point,
1044
* unless the precision is explicity zero, with the `#' flag not set.
1046
if( (stream->width > 0)
1047
&& ((stream->precision > 0) || (stream->flags & PFORMAT_HASHED)) )
1050
/* Reserve space in the output field, for display of the sign of the
1051
* formatted value, if required; (i.e. if the value is negative, or if
1052
* either the `space' or `+' formatting flags are set).
1054
if( (stream->width > 0) && (sign || (stream->flags & PFORMAT_SIGNED)) )
1057
/* Emit any padding space, as required to correctly right justify
1058
* the output within the alloted field width.
1060
if( (stream->width > 0) && ((stream->flags & PFORMAT_JUSTIFY) == 0) )
1061
while( stream->width-- > 0 )
1062
__pformat_putc( '\x20', stream );
1064
/* Emit the sign indicator, as appropriate...
1068
* mandatory, for negative values...
1070
__pformat_putc( '-', stream );
1072
else if( stream->flags & PFORMAT_POSITIVE )
1074
* optional, for positive values...
1076
__pformat_putc( '+', stream );
1078
else if( stream->flags & PFORMAT_ADDSPACE )
1080
* or just fill reserved space, when the space flag is in effect.
1082
__pformat_putc( '\x20', stream );
1084
/* If the `0' flag is in effect, and not overridden by the `-' flag,
1085
* then zero padding, to fill out the field, goes here...
1087
if( (stream->width > 0)
1088
&& ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
1089
while( stream->width-- > 0 )
1090
__pformat_putc( '0', stream );
1092
/* Emit the digits of the encoded numeric value...
1096
* ...beginning with those which precede the radix point,
1097
* and appending any necessary significant trailing zeros.
1099
do __pformat_putc( *value ? *value++ : '0', stream );
1103
/* The magnitude of the encoded value is less than 1.0, so no
1104
* digits precede the radix point; we emit a mandatory initial
1105
* zero, followed immediately by the radix point.
1107
__pformat_putc( '0', stream );
1109
/* Unless the encoded value is integral, AND the radix point
1110
* is not expressly demanded by the `#' flag, we must insert
1111
* the appropriately localised radix point mark here...
1113
if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1114
__pformat_emit_radix_point( stream );
1116
/* When the radix point offset, `len', is negative, this implies
1117
* that additional zeros must appear, following the radix point,
1118
* and preceding the first significant digit...
1122
/* To accommodate these, we adjust the precision, (reducing it
1123
* by adding a negative value), and then we emit as many zeros
1126
stream->precision += len;
1127
do __pformat_putc( '0', stream );
1131
/* Now we emit any remaining significant digits, or trailing zeros,
1132
* until the required precision has been achieved.
1134
while( stream->precision-- > 0 )
1135
__pformat_putc( *value ? *value++ : '0', stream );
1139
void __pformat_emit_efloat( int sign, char *value, int e, __pformat_t *stream )
1141
/* Helper to emit a floating point representation of numeric data,
1142
* as encoded by a prior call to `ecvt()' or `fcvt()'; (this DOES
1143
* include the following exponent).
1146
__pformat_intarg_t exponent; exponent.__pformat_llong_t = e -= 1;
1148
/* Determine how many digit positions are required for the exponent.
1150
while( (e /= 10) != 0 )
1153
/* Ensure that this is at least as many as the standard requirement.
1155
if( exp_width < stream->expmin )
1156
exp_width = stream->expmin;
1158
/* Adjust the residual field width allocation, to allow for the
1159
* number of exponent digits to be emitted, together with a sign
1160
* and exponent separator...
1162
if( stream->width > (exp_width += 2) )
1163
stream->width -= exp_width;
1166
/* ignoring the field width specification, if insufficient.
1168
stream->width = PFORMAT_IGNORE;
1170
/* Emit the significand, as a fixed point value with one digit
1171
* preceding the radix point.
1173
__pformat_emit_float( sign, value, 1, stream );
1175
/* Reset precision, to ensure the mandatory minimum number of
1176
* exponent digits will be emitted, and set the flags to ensure
1177
* the sign is displayed.
1179
stream->precision = stream->expmin;
1180
stream->flags |= PFORMAT_SIGNED;
1182
/* Emit the exponent separator.
1184
__pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream );
1186
/* Readjust the field width setting, such that it again allows
1187
* for the digits of the exponent, (which had been discounted when
1188
* computing any left side padding requirement), so that they are
1189
* correctly included in the computation of any right side padding
1190
* requirement, (but here we exclude the exponent separator, which
1191
* has been emitted, and so counted already).
1193
stream->width += exp_width - 1;
1195
/* And finally, emit the exponent itself, as a signed integer,
1196
* with any padding required to achieve flush left justification,
1197
* (which will be added automatically, by `__pformat_int()').
1199
__pformat_int( exponent, stream );
1203
void __pformat_float( long double x, __pformat_t *stream )
1205
/* Handler for `%f' and `%F' format specifiers.
1207
* This wraps calls to `__pformat_cvt()', `__pformat_emit_float()'
1208
* and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1209
* output in fixed point format.
1211
int sign, intlen; char *value;
1213
/* Establish the precision for the displayed value, defaulting to six
1214
* digits following the decimal point, if not explicitly specified.
1216
if( stream->precision < 0 )
1217
stream->precision = 6;
1219
/* Encode the input value as ASCII, for display...
1221
value = __pformat_fcvt( x, stream->precision, &intlen, &sign );
1223
if( intlen == PFORMAT_INFNAN )
1225
* handle cases of `infinity' or `not-a-number'...
1227
__pformat_emit_inf_or_nan( sign, value, stream );
1230
{ /* or otherwise, emit the formatted result.
1232
__pformat_emit_float( sign, value, intlen, stream );
1234
/* and, if there is any residual field width as yet unfilled,
1235
* then we must be doing flush left justification, so pad out to
1236
* the right hand field boundary.
1238
while( stream->width-- > 0 )
1239
__pformat_putc( '\x20', stream );
1242
/* Clean up `__pformat_fcvt()' memory allocation for `value'...
1244
__pformat_fcvt_release( value );
1248
void __pformat_efloat( long double x, __pformat_t *stream )
1250
/* Handler for `%e' and `%E' format specifiers.
1252
* This wraps calls to `__pformat_cvt()', `__pformat_emit_efloat()'
1253
* and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1254
* output in floating point format.
1256
int sign, intlen; char *value;
1258
/* Establish the precision for the displayed value, defaulting to six
1259
* digits following the decimal point, if not explicitly specified.
1261
if( stream->precision < 0 )
1262
stream->precision = 6;
1264
/* Encode the input value as ASCII, for display...
1266
value = __pformat_ecvt( x, stream->precision + 1, &intlen, &sign );
1268
if( intlen == PFORMAT_INFNAN )
1270
* handle cases of `infinity' or `not-a-number'...
1272
__pformat_emit_inf_or_nan( sign, value, stream );
1275
/* or otherwise, emit the formatted result.
1277
__pformat_emit_efloat( sign, value, intlen, stream );
1279
/* Clean up `__pformat_ecvt()' memory allocation for `value'...
1281
__pformat_ecvt_release( value );
1285
void __pformat_gfloat( long double x, __pformat_t *stream )
1287
/* Handler for `%g' and `%G' format specifiers.
1289
* This wraps calls to `__pformat_cvt()', `__pformat_emit_float()',
1290
* `__pformat_emit_efloat()' and `__pformat_emit_inf_or_nan()', as
1291
* appropriate, to achieve output in the more suitable of either
1292
* fixed or floating point format.
1294
int sign, intlen; char *value;
1296
/* Establish the precision for the displayed value, defaulting to
1297
* six significant digits, if not explicitly specified...
1299
if( stream->precision < 0 )
1300
stream->precision = 6;
1302
/* or to a minimum of one digit, otherwise...
1304
else if( stream->precision == 0 )
1305
stream->precision = 1;
1307
/* Encode the input value as ASCII, for display.
1309
value = __pformat_ecvt( x, stream->precision, &intlen, &sign );
1311
if( intlen == PFORMAT_INFNAN )
1313
* Handle cases of `infinity' or `not-a-number'.
1315
__pformat_emit_inf_or_nan( sign, value, stream );
1317
else if( (-4 < intlen) && (intlen <= stream->precision) )
1319
/* Value lies in the acceptable range for fixed point output,
1320
* (i.e. the exponent is no less than minus four, and the number
1321
* of significant digits which precede the radix point is fewer
1322
* than the least number which would overflow the field width,
1323
* specified or implied by the established precision).
1325
if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1327
* The `#' flag is in effect...
1328
* Adjust precision to retain the specified number of significant
1329
* digits, with the proper number preceding the radix point, and
1330
* the balance following it...
1332
stream->precision -= intlen;
1335
/* The `#' flag is not in effect...
1336
* Here we adjust the precision to accommodate all digits which
1337
* precede the radix point, but we truncate any balance following
1338
* it, to suppress output of non-significant trailing zeros...
1340
if( ((stream->precision = strlen( value ) - intlen) < 0)
1342
* This may require a compensating adjustment to the field
1343
* width, to accommodate significant trailing zeros, which
1344
* precede the radix point...
1346
&& (stream->width > 0) )
1347
stream->width += stream->precision;
1349
/* Now, we format the result as any other fixed point value.
1351
__pformat_emit_float( sign, value, intlen, stream );
1353
/* If there is any residual field width as yet unfilled, then
1354
* we must be doing flush left justification, so pad out to the
1355
* right hand field boundary.
1357
while( stream->width-- > 0 )
1358
__pformat_putc( '\x20', stream );
1362
{ /* Value lies outside the acceptable range for fixed point;
1363
* one significant digit will precede the radix point, so we
1364
* decrement the precision to retain only the appropriate number
1365
* of additional digits following it, when we emit the result
1366
* in floating point format.
1368
if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1370
* The `#' flag is in effect...
1371
* Adjust precision to emit the specified number of significant
1372
* digits, with one preceding the radix point, and the balance
1373
* following it, retaining any non-significant trailing zeros
1374
* which are required to exactly match the requested precision...
1376
stream->precision--;
1379
/* The `#' flag is not in effect...
1380
* Adjust precision to emit only significant digits, with one
1381
* preceding the radix point, and any others following it, but
1382
* suppressing non-significant trailing zeros...
1384
stream->precision = strlen( value ) - 1;
1386
/* Now, we format the result as any other floating point value.
1388
__pformat_emit_efloat( sign, value, intlen, stream );
1391
/* Clean up `__pformat_ecvt()' memory allocation for `value'.
1393
__pformat_ecvt_release( value );
1397
void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream )
1399
/* Helper for emitting floating point data, originating as
1400
* either `double' or `long double' type, as a hexadecimal
1401
* representation of the argument value.
1403
char buf[18], *p = buf;
1404
__pformat_intarg_t exponent; short exp_width = 2;
1406
/* The mantissa field of the argument value representation can
1407
* accommodate at most 16 hexadecimal digits, of which one will
1408
* be placed before the radix point, leaving at most 15 digits
1409
* to satisfy any requested precision; thus...
1411
if( (stream->precision >= 0) && (stream->precision < 15) )
1413
/* When the user specifies a precision within this range,
1414
* we want to adjust the mantissa, to retain just the number
1415
* of digits required, rounding up when the high bit of the
1416
* leftmost discarded digit is set; (mask of 0x08 accounts
1417
* for exactly one digit discarded, shifting 4 bits per
1418
* digit, with up to 14 additional digits, to consume the
1419
* full availability of 15 precision digits).
1421
* However, before we perform the rounding operation, we
1422
* normalise the mantissa, shifting it to the left by as many
1423
* bit positions may be necessary, until its highest order bit
1424
* is set, thus preserving the maximum number of bits in the
1425
* rounded result as possible.
1427
while( value.__pformat_fpreg_mantissa < (LLONG_MAX + 1ULL) )
1428
value.__pformat_fpreg_mantissa <<= 1;
1430
/* We then shift the mantissa one bit position back to the
1431
* right, to guard against possible overflow when the rounding
1432
* adjustment is added.
1434
value.__pformat_fpreg_mantissa >>= 1;
1436
/* We now add the rounding adjustment, noting that to keep the
1437
* 0x08 mask aligned with the shifted mantissa, we also need to
1438
* shift it right by one bit initially, changing its starting
1441
value.__pformat_fpreg_mantissa += 0x04LL << (4 * (14 - stream->precision));
1442
if( (value.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0ULL )
1444
* When the rounding adjustment would not have overflowed,
1445
* then we shift back to the left again, to fill the vacated
1446
* bit we reserved to accommodate the carry.
1448
value.__pformat_fpreg_mantissa <<= 1;
1451
/* Otherwise the rounding adjustment would have overflowed,
1452
* so the carry has already filled the vacated bit; the effect
1453
* of this is equivalent to an increment of the exponent.
1455
value.__pformat_fpreg_exponent++;
1457
/* We now complete the rounding to the required precision, by
1458
* shifting the unwanted digits out, from the right hand end of
1461
value.__pformat_fpreg_mantissa >>= 4 * (15 - stream->precision);
1464
/* Encode the significant digits of the mantissa in hexadecimal
1465
* ASCII notation, ready for transfer to the output stream...
1467
while( value.__pformat_fpreg_mantissa )
1469
/* taking the rightmost digit in each pass...
1471
int c = value.__pformat_fpreg_mantissa & 0xF;
1472
if( c == (int) value.__pformat_fpreg_mantissa )
1474
/* inserting the radix point, when we reach the last,
1475
* (i.e. the most significant digit), unless we found no
1476
* less significant digits, with no mandatory radix point
1477
* inclusion, and no additional required precision...
1480
|| (stream->flags & PFORMAT_HASHED) || (stream->precision > 0) )
1482
* Internally, we represent the radix point as an ASCII '.';
1483
* we will replace it with any locale specific alternative,
1484
* at the time of transfer to the ultimate destination.
1488
/* If the most significant hexadecimal digit of the encoded
1489
* output value is greater than one, then the indicated value
1490
* will appear too large, by an additional binary exponent
1491
* corresponding to the number of higher order bit positions
1492
* which it occupies...
1494
while( value.__pformat_fpreg_mantissa > 1 )
1496
/* so reduce the exponent value to compensate...
1498
value.__pformat_fpreg_exponent--;
1499
value.__pformat_fpreg_mantissa >>= 1;
1503
else if( stream->precision > 0 )
1505
* we have not yet fulfilled the desired precision,
1506
* and we have not yet found the most significant digit,
1507
* so account for the current digit, within the field
1508
* width required to meet the specified precision.
1510
stream->precision--;
1512
if( (c > 0) || (p > buf) || (stream->precision >= 0) )
1514
* Ignoring insignificant trailing zeros, (unless required to
1515
* satisfy specified precision), store the current encoded digit
1516
* into the pending output buffer, in LIFO order, and using the
1517
* appropriate case for digits in the `A'..`F' range.
1519
*p++ = c > 9 ? (c - 10 + 'A') | (stream->flags & PFORMAT_XCASE) : c + '0';
1521
/* Shift out the current digit, (4-bit logical shift right),
1522
* to align the next more significant digit to be extracted,
1523
* and encoded in the next pass.
1525
value.__pformat_fpreg_mantissa >>= 4;
1530
/* Nothing has been queued for output...
1531
* We need at least one zero, and possibly a radix point.
1533
if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1539
if( stream->width > 0 )
1541
/* Adjust the user specified field width, to account for the
1542
* number of digits minimally required, to display the encoded
1543
* value, at the requested precision.
1545
* FIXME: this uses the minimum number of digits possible for
1546
* representation of the binary exponent, in strict conformance
1547
* with C99 and POSIX specifications. Although there appears to
1548
* be no Microsoft precedent for doing otherwise, we may wish to
1549
* relate this to the `_get_output_format()' result, to maintain
1550
* consistency with `%e', `%f' and `%g' styles.
1552
int min_width = p - buf;
1553
int expo = value.__pformat_fpreg_exponent;
1555
/* If we have not yet queued sufficient digits to fulfil the
1556
* requested precision, then we must adjust the minimum width
1557
* specification, to accommodate the additional digits which
1558
* are required to do so.
1560
if( stream->precision > 0 )
1561
min_width += stream->precision;
1563
/* Adjust the minimum width requirement, to accomodate the
1564
* sign, radix indicator and at least one exponent digit...
1566
min_width += stream->flags & PFORMAT_SIGNED ? 6 : 5;
1567
while( (expo = expo / 10) != 0 )
1569
/* and increase as required, if additional exponent digits
1570
* are needed, also saving the exponent field width adjustment,
1571
* for later use when that is emitted.
1577
if( stream->width > min_width )
1579
/* When specified field width exceeds the minimum required,
1580
* adjust to retain only the excess...
1582
stream->width -= min_width;
1584
/* and then emit any required left side padding spaces.
1586
if( (stream->flags & PFORMAT_JUSTIFY) == 0 )
1587
while( stream->width-- > 0 )
1588
__pformat_putc( '\x20', stream );
1592
/* Specified field width is insufficient; just ignore it!
1594
stream->width = PFORMAT_IGNORE;
1597
/* Emit the sign of the encoded value, as required...
1599
if( stream->flags & PFORMAT_NEGATIVE )
1601
* this is mandatory, to indicate a negative value...
1603
__pformat_putc( '-', stream );
1605
else if( stream->flags & PFORMAT_POSITIVE )
1607
* but this is optional, for a positive value...
1609
__pformat_putc( '+', stream );
1611
else if( stream->flags & PFORMAT_ADDSPACE )
1613
* with this optional alternative.
1615
__pformat_putc( '\x20', stream );
1617
/* Prefix a `0x' or `0X' radix indicator to the encoded value,
1618
* with case appropriate to the format specification.
1620
__pformat_putc( '0', stream );
1621
__pformat_putc( 'X' | (stream->flags & PFORMAT_XCASE), stream );
1623
/* If the `0' flag is in effect...
1624
* Zero padding, to fill out the field, goes here...
1626
if( (stream->width > 0) && (stream->flags & PFORMAT_ZEROFILL) )
1627
while( stream->width-- > 0 )
1628
__pformat_putc( '0', stream );
1630
/* Next, we emit the encoded value, without its exponent...
1633
__pformat_emit_numeric_value( *--p, stream );
1635
/* followed by any additional zeros needed to satisfy the
1636
* precision specification...
1638
while( stream->precision-- > 0 )
1639
__pformat_putc( '0', stream );
1641
/* then the exponent prefix, (C99 and POSIX specify `p'),
1642
* in the case appropriate to the format specification...
1644
__pformat_putc( 'P' | (stream->flags & PFORMAT_XCASE), stream );
1646
/* and finally, the decimal representation of the binary exponent,
1647
* as a signed value with mandatory sign displayed, in a field width
1648
* adjusted to accommodate it, LEFT justified, with any additional
1649
* right side padding remaining from the original field width.
1651
stream->width += exp_width;
1652
stream->flags |= PFORMAT_SIGNED;
1653
exponent.__pformat_llong_t = value.__pformat_fpreg_exponent;
1654
__pformat_int( exponent, stream );
1658
void __pformat_xdouble( double x, __pformat_t *stream )
1660
/* Handler for `%a' and `%A' format specifiers, (with argument
1661
* value specified as `double' type).
1663
unsigned sign_bit = 0;
1664
__pformat_fpreg_t z; z.__pformat_fpreg_double_t = x;
1666
/* First check for NaN; it is emitted unsigned...
1669
__pformat_emit_inf_or_nan( sign_bit, "NaN", stream );
1672
{ /* Capture the sign bit up-front, so we can show it correctly
1673
* even when the argument value is zero or infinite.
1675
if( (sign_bit = (z.__pformat_fpreg_bitmap[3] & 0x8000)) != 0 )
1676
stream->flags |= PFORMAT_NEGATIVE;
1678
/* Check for infinity, (positive or negative)...
1682
* displaying the appropriately signed indicator,
1685
__pformat_emit_inf_or_nan( sign_bit, "Inf", stream );
1688
{ /* The argument value is a representable number...
1689
* first move its exponent into the appropriate field...
1691
z.__pformat_fpreg_bitmap[4] = (z.__pformat_fpreg_bitmap[3] >> 4) & 0x7FF;
1693
/* Realign the mantissa, leaving space for a
1694
* normalised most significant digit...
1696
z.__pformat_fpreg_mantissa <<= 8;
1697
z.__pformat_fpreg_bitmap[3] = (z.__pformat_fpreg_bitmap[3] & 0x0FFF);
1699
/* Check for zero value...
1701
if( z.__pformat_fpreg_exponent || z.__pformat_fpreg_mantissa )
1703
/* and only when the value is non-zero,
1704
* eliminate the bias from the exponent...
1706
z.__pformat_fpreg_exponent -= 0x3FF;
1708
/* Check for a possible denormalised value...
1710
if( z.__pformat_fpreg_exponent > -126 )
1712
* and normalise when it isn't.
1714
z.__pformat_fpreg_bitmap[3] += 0x1000;
1717
/* Finally, hand the adjusted representation off to the generalised
1718
* hexadecimal floating point format handler...
1720
__pformat_emit_xfloat( z, stream );
1726
void __pformat_xldouble( long double x, __pformat_t *stream )
1728
/* Handler for `%La' and `%LA' format specifiers, (with argument
1729
* value specified as `long double' type).
1731
unsigned sign_bit = 0;
1732
__pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
1734
/* First check for NaN; it is emitted unsigned...
1737
__pformat_emit_inf_or_nan( sign_bit, "NaN", stream );
1740
{ /* Capture the sign bit up-front, so we can show it correctly
1741
* even when the argument value is zero or infinite.
1743
if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 )
1744
stream->flags |= PFORMAT_NEGATIVE;
1746
/* Check for infinity, (positive or negative)...
1750
* displaying the appropriately signed indicator,
1753
__pformat_emit_inf_or_nan( sign_bit, "Inf", stream );
1756
{ /* The argument value is a representable number...
1757
* extract the effective value of the biased exponent...
1759
z.__pformat_fpreg_exponent &= 0x7FFF;
1760
if( z.__pformat_fpreg_exponent || z.__pformat_fpreg_mantissa )
1762
* and if the argument value itself is non-zero,
1763
* eliminate the bias from the exponent...
1765
z.__pformat_fpreg_exponent -= 0x3FFF;
1767
/* Finally, hand the adjusted representation off to the
1768
* generalised hexadecimal floating point format handler...
1770
__pformat_emit_xfloat( z, stream );
1775
int __pformat( int flags, void *dest, int max, const char *fmt, va_list argv )
1779
__pformat_t stream =
1781
/* Create and initialise a format control block
1782
* for this output request.
1784
dest, /* output goes to here */
1785
flags &= PFORMAT_TO_FILE | PFORMAT_NOLIMIT, /* only these valid initially */
1786
PFORMAT_IGNORE, /* no field width yet */
1787
PFORMAT_IGNORE, /* nor any precision spec */
1788
PFORMAT_RPINIT, /* radix point uninitialised */
1789
(wchar_t)(0), /* leave it unspecified */
1790
0, /* zero output char count */
1791
max, /* establish output limit */
1792
PFORMAT_MINEXP /* exponent chars preferred */
1795
format_scan: while( (c = *fmt++) != 0 )
1797
/* Format string parsing loop...
1798
* The entry point is labelled, so that we can return to the start state
1799
* from within the inner `conversion specification' interpretation loop,
1800
* as soon as a conversion specification has been resolved.
1804
/* Initiate parsing of a `conversion specification'...
1806
__pformat_intarg_t argval;
1807
__pformat_state_t state = PFORMAT_INIT;
1808
__pformat_length_t length = PFORMAT_LENGTH_INT;
1810
/* Save the current format scan position, so that we can backtrack
1811
* in the event of encountering an invalid format specification...
1813
const char *backtrack = fmt;
1815
/* Restart capture for dynamic field width and precision specs...
1817
int *width_spec = &stream.width;
1819
/* Reset initial state for flags, width and precision specs...
1821
stream.flags = flags;
1822
stream.width = stream.precision = PFORMAT_IGNORE;
1826
switch( c = *fmt++ )
1828
/* Data type specifiers...
1829
* All are terminal, so exit the conversion spec parsing loop
1830
* with a `goto format_scan', thus resuming at the outer level
1831
* in the regular format string parser.
1835
* Not strictly a data type specifier...
1836
* it simply converts as a literal `%' character.
1838
* FIXME: should we require this to IMMEDIATELY follow the
1839
* initial `%' of the "conversion spec"? (glibc `printf()'
1840
* on GNU/Linux does NOT appear to require this, but POSIX
1841
* and SUSv3 do seem to demand it).
1843
__pformat_putc( c, &stream );
1848
* Equivalent to `%lc'; set `length' accordingly,
1849
* and simply fall through.
1851
length = PFORMAT_LENGTH_LONG;
1855
* Single, (or single multibyte), character output...
1857
* We handle these by copying the argument into our local
1858
* `argval' buffer, and then we pass the address of that to
1859
* either `__pformat_putchars()' or `__pformat_wputchars()',
1860
* as appropriate, effectively formatting it as a string of
1861
* the appropriate type, with a length of one.
1863
* A side effect of this method of handling character data
1864
* is that, if the user sets a precision of zero, then no
1865
* character is actually emitted; we don't want that, so we
1866
* forcibly override any user specified precision.
1868
stream.precision = PFORMAT_IGNORE;
1870
/* Now we invoke the appropriate format handler...
1872
if( (length == PFORMAT_LENGTH_LONG)
1873
|| (length == PFORMAT_LENGTH_LLONG) )
1875
/* considering any `long' type modifier as a reference to
1876
* `wchar_t' data, (which is promoted to an `int' argument)...
1878
argval.__pformat_ullong_t = (wchar_t)(va_arg( argv, int ));
1879
__pformat_wputchars( (wchar_t *)(&argval), 1, &stream );
1883
{ /* while anything else is simply taken as `char', (which
1884
* is also promoted to an `int' argument)...
1886
argval.__pformat_uchar_t = (unsigned char)(va_arg( argv, int ));
1887
__pformat_putchars( (char *)(&argval), 1, &stream );
1893
* Equivalent to `%ls'; set `length' accordingly,
1894
* and simply fall through.
1896
length = PFORMAT_LENGTH_LONG;
1899
if( (length == PFORMAT_LENGTH_LONG)
1900
|| (length == PFORMAT_LENGTH_LLONG) )
1902
/* considering any `long' type modifier as a reference to
1903
* a `wchar_t' string...
1905
__pformat_wcputs( va_arg( argv, wchar_t * ), &stream );
1909
/* This is normal string output;
1910
* we simply invoke the appropriate handler...
1912
__pformat_puts( va_arg( argv, char * ), &stream );
1921
* Unsigned integer values; octal, decimal or hexadecimal format...
1923
if( length == PFORMAT_LENGTH_LLONG )
1925
* with an `unsigned long long' argument, which we
1926
* process `as is'...
1928
argval.__pformat_ullong_t = va_arg( argv, unsigned long long );
1930
else if( length == PFORMAT_LENGTH_LONG )
1932
* or with an `unsigned long', which we promote to
1933
* `unsigned long long'...
1935
argval.__pformat_ullong_t = va_arg( argv, unsigned long );
1938
{ /* or for any other size, which will have been promoted
1939
* to `unsigned int', we select only the appropriately sized
1940
* least significant segment, and again promote to the same
1941
* size as `unsigned long long'...
1943
argval.__pformat_ullong_t = va_arg( argv, unsigned int );
1944
if( length == PFORMAT_LENGTH_SHORT )
1946
* from `unsigned short'...
1948
argval.__pformat_ullong_t = argval.__pformat_ushort_t;
1950
else if( length == PFORMAT_LENGTH_CHAR )
1952
* or even from `unsigned char'...
1954
argval.__pformat_ullong_t = argval.__pformat_uchar_t;
1957
/* so we can pass any size of argument to either of two
1958
* common format handlers...
1962
* depending on whether output is to be encoded in
1965
__pformat_int( argval, &stream );
1968
/* or in octal or hexadecimal format...
1970
__pformat_xint( c, argval, &stream );
1977
* Signed integer values; decimal format...
1978
* This is similar to `u', but must process `argval' as signed,
1979
* and be prepared to handle negative numbers.
1981
stream.flags |= PFORMAT_NEGATIVE;
1983
if( length == PFORMAT_LENGTH_LLONG )
1985
* The argument is a `long long' type...
1987
argval.__pformat_llong_t = va_arg( argv, long long );
1989
else if( length == PFORMAT_LENGTH_LONG )
1991
* or here, a `long' type...
1993
argval.__pformat_llong_t = va_arg( argv, long );
1996
{ /* otherwise, it's an `int' type...
1998
argval.__pformat_llong_t = va_arg( argv, int );
1999
if( length == PFORMAT_LENGTH_SHORT )
2001
* but it was promoted from a `short' type...
2003
argval.__pformat_llong_t = argval.__pformat_short_t;
2004
else if( length == PFORMAT_LENGTH_CHAR )
2006
* or even from a `char' type...
2008
argval.__pformat_llong_t = argval.__pformat_char_t;
2011
/* In any case, all share a common handler...
2013
__pformat_int( argval, &stream );
2018
* Pointer argument; format as hexadecimal, with `0x' prefix...
2020
stream.flags |= PFORMAT_HASHED;
2021
argval.__pformat_ullong_t = va_arg( argv, uintptr_t );
2022
__pformat_xint( 'x', argval, &stream );
2027
* Floating point format, with lower case exponent indicator
2028
* and lower case `inf' or `nan' representation when required;
2029
* select lower case mode, and simply fall through...
2031
stream.flags |= PFORMAT_XCASE;
2035
* Floating point format, with upper case exponent indicator
2036
* and upper case `INF' or `NAN' representation when required,
2037
* (or lower case for all of these, on fall through from above);
2038
* select lower case mode, and simply fall through...
2040
if( stream.flags & PFORMAT_LDOUBLE )
2042
* for a `long double' argument...
2044
__pformat_efloat( va_arg( argv, long double ), &stream );
2047
/* or just a `double', which we promote to `long double',
2048
* so the two may share a common format handler.
2050
__pformat_efloat( (long double)(va_arg( argv, double )), &stream );
2056
* Fixed point format, using lower case for `inf' and
2057
* `nan', when appropriate; select lower case mode, and
2058
* simply fall through...
2060
stream.flags |= PFORMAT_XCASE;
2064
* Fixed case format using upper case, or lower case on
2065
* fall through from above, for `INF' and `NAN'...
2067
if( stream.flags & PFORMAT_LDOUBLE )
2069
* for a `long double' argument...
2071
__pformat_float( va_arg( argv, long double ), &stream );
2074
/* or just a `double', which we promote to `long double',
2075
* so the two may share a common format handler.
2077
__pformat_float( (long double)(va_arg( argv, double )), &stream );
2083
* Generalised floating point format, with lower case
2084
* exponent indicator when required; select lower case
2085
* mode, and simply fall through...
2087
stream.flags |= PFORMAT_XCASE;
2091
* Generalised floating point format, with upper case,
2092
* or on fall through from above, with lower case exponent
2093
* indicator when required...
2095
if( stream.flags & PFORMAT_LDOUBLE )
2097
* for a `long double' argument...
2099
__pformat_gfloat( va_arg( argv, long double ), &stream );
2102
/* or just a `double', which we promote to `long double',
2103
* so the two may share a common format handler.
2105
__pformat_gfloat( (long double)(va_arg( argv, double )), &stream );
2111
* Hexadecimal floating point format, with lower case radix
2112
* and exponent indicators; select the lower case mode, and
2115
stream.flags |= PFORMAT_XCASE;
2119
* Hexadecimal floating point format; handles radix and
2120
* exponent indicators in either upper or lower case...
2122
if( stream.flags & PFORMAT_LDOUBLE )
2124
* with a `long double' argument...
2126
__pformat_xldouble( va_arg( argv, long double ), &stream );
2129
/* or just a `double'.
2131
__pformat_xdouble( va_arg( argv, double ), &stream );
2137
* Save current output character count...
2139
if( length == PFORMAT_LENGTH_CHAR )
2141
* to a signed `char' destination...
2143
*va_arg( argv, char * ) = stream.count;
2145
else if( length == PFORMAT_LENGTH_SHORT )
2147
* or to a signed `short'...
2149
*va_arg( argv, short * ) = stream.count;
2151
else if( length == PFORMAT_LENGTH_LONG )
2153
* or to a signed `long'...
2155
*va_arg( argv, long * ) = stream.count;
2157
else if( length == PFORMAT_LENGTH_LLONG )
2159
* or to a signed `long long'...
2161
*va_arg( argv, long long * ) = stream.count;
2165
* or, by default, to a signed `int'.
2167
*va_arg( argv, int * ) = stream.count;
2171
/* Argument length modifiers...
2172
* These are non-terminal; each sets the format parser
2173
* into the PFORMAT_END state, and ends with a `break'.
2177
* Interpret the argument as explicitly of a `short'
2178
* or `char' data type, truncated from the standard
2179
* length defined for integer promotion.
2183
/* Modifier is `hh'; data type is `char' sized...
2184
* Skip the second `h', and set length accordingly.
2187
length = PFORMAT_LENGTH_CHAR;
2191
/* Modifier is `h'; data type is `short' sized...
2193
length = PFORMAT_LENGTH_SHORT;
2195
state = PFORMAT_END;
2200
* Interpret the argument as being of the same size as
2201
* a `intmax_t' entity...
2203
length = __pformat_arg_length( intmax_t );
2204
state = PFORMAT_END;
2211
* The MSVCRT implementation of the printf() family of
2212
* functions explicitly uses...
2214
if( (fmt[0] == '6') && (fmt[1] == '4') )
2216
/* I64' instead of `ll',
2217
* when referring to `long long' integer types...
2219
length = PFORMAT_LENGTH_LLONG;
2223
else if( (fmt[0] == '3') && (fmt[1] == '2') )
2225
/* and `I32' instead of `l',
2226
* when referring to `long' integer types...
2228
length = PFORMAT_LENGTH_LONG;
2233
/* or unqualified `I' instead of `t' or `z',
2234
* when referring to `ptrdiff_t' or `size_t' entities;
2235
* (we will choose to map it to `ptrdiff_t').
2237
length = __pformat_arg_length( ptrdiff_t );
2239
state = PFORMAT_END;
2246
* Interpret the argument as explicitly of a
2247
* `long' or `long long' data type.
2251
/* Modifier is `ll'; data type is `long long' sized...
2252
* Skip the second `l', and set length accordingly.
2255
length = PFORMAT_LENGTH_LLONG;
2259
/* Modifier is `l'; data type is `long' sized...
2261
length = PFORMAT_LENGTH_LONG;
2265
* Microsoft's MSVCRT implementation also uses `l'
2266
* as a modifier for `long double'; if we don't want
2267
* to support that, we end this case here...
2269
state = PFORMAT_END;
2272
/* otherwise, we simply fall through...
2278
* Identify the appropriate argument as a `long double',
2279
* when associated with `%a', `%A', `%e', `%E', `%f', `%F',
2280
* `%g' or `%G' format specifications.
2282
stream.flags |= PFORMAT_LDOUBLE;
2283
state = PFORMAT_END;
2288
* Interpret the argument as being of the same size as
2289
* a `ptrdiff_t' entity...
2291
length = __pformat_arg_length( ptrdiff_t );
2292
state = PFORMAT_END;
2297
* Interpret the argument as being of the same size as
2298
* a `size_t' entity...
2300
length = __pformat_arg_length( size_t );
2301
state = PFORMAT_END;
2304
/* Precision indicator...
2305
* May appear once only; it must precede any modifier
2306
* for argument length, or any data type specifier.
2309
if( state < PFORMAT_GET_PRECISION )
2311
/* We haven't seen a precision specification yet,
2312
* so initialise it to zero, (in case no digits follow),
2313
* and accept any following digits as the precision.
2315
stream.precision = 0;
2316
width_spec = &stream.precision;
2317
state = PFORMAT_GET_PRECISION;
2321
/* We've already seen a precision specification,
2322
* so this is just junk; proceed to end game.
2324
state = PFORMAT_END;
2326
/* Either way, we must not fall through here.
2330
/* Variable field width, or precision specification,
2331
* derived from the argument list...
2335
* When this appears...
2338
&& ((state == PFORMAT_INIT) || (state == PFORMAT_GET_PRECISION)) )
2340
/* in proper context; assign to field width
2341
* or precision, as appropriate.
2343
if( (*width_spec = va_arg( argv, int )) < 0 )
2345
/* Assigned value was negative...
2347
if( state == PFORMAT_INIT )
2349
/* For field width, this is equivalent to
2350
* a positive value with the `-' flag...
2352
stream.flags |= PFORMAT_LJUSTIFY;
2353
stream.width = -stream.width;
2357
/* while as a precision specification,
2358
* it should simply be ignored.
2360
stream.precision = PFORMAT_IGNORE;
2365
/* out of context; give up on width and precision
2366
* specifications for this conversion.
2368
state = PFORMAT_END;
2370
/* Mark as processed...
2371
* we must not see `*' again, in this context.
2376
/* Formatting flags...
2377
* Must appear while in the PFORMAT_INIT state,
2378
* and are non-terminal, so again, end with `break'.
2382
* Select alternate PFORMAT_HASHED output style.
2384
if( state == PFORMAT_INIT )
2385
stream.flags |= PFORMAT_HASHED;
2390
* Print a leading sign with numeric output,
2391
* for both positive and negative values.
2393
if( state == PFORMAT_INIT )
2394
stream.flags |= PFORMAT_POSITIVE;
2399
* Select left justification of displayed output
2400
* data, within the output field width, instead of
2401
* the default flush right justification.
2403
if( state == PFORMAT_INIT )
2404
stream.flags |= PFORMAT_LJUSTIFY;
2407
# ifdef WITH_XSI_FEATURES
2411
* This is an XSI extension to the POSIX standard,
2412
* which we do not support, at present.
2414
if( state == PFORMAT_INIT )
2415
stream.flags |= PFORMAT_GROUPED;
2422
* Reserve a single space, within the output field,
2423
* for display of the sign of signed data; this will
2424
* be occupied by the minus sign, if the data value
2425
* is negative, or by a plus sign if the data value
2426
* is positive AND the `+' flag is also present, or
2427
* by a space otherwise. (Technically, this flag
2428
* is redundant, if the `+' flag is present).
2430
if( state == PFORMAT_INIT )
2431
stream.flags |= PFORMAT_ADDSPACE;
2436
* May represent a flag, to activate the `pad with zeros'
2437
* option, or it may simply be a digit in a width or in a
2438
* precision specification...
2440
if( state == PFORMAT_INIT )
2442
/* This is the flag usage...
2444
stream.flags |= PFORMAT_ZEROFILL;
2450
* If we didn't match anything above, then we will check
2451
* for digits, which we may accumulate to generate field
2452
* width or precision specifications...
2454
if( (state < PFORMAT_END) && ('9' >= c) && (c >= '0') )
2456
if( state == PFORMAT_INIT )
2458
* Initial digits explicitly relate to field width...
2460
state = PFORMAT_SET_WIDTH;
2462
else if( state == PFORMAT_GET_PRECISION )
2464
* while those following a precision indicator
2465
* explicitly relate to precision.
2467
state = PFORMAT_SET_PRECISION;
2471
/* We are accepting a width or precision specification...
2473
if( *width_spec < 0 )
2475
* and accumulation hasn't started yet; we simply
2476
* initialise the accumulator with the current digit
2477
* value, converting from ASCII to decimal.
2479
*width_spec = c - '0';
2482
/* Accumulation has already started; we perform a
2483
* `leftwise decimal digit shift' on the accumulator,
2484
* (i.e. multiply it by ten), then add the decimal
2485
* equivalent value of the current digit.
2487
*width_spec = *width_spec * 10 + c - '0';
2493
/* We found a digit out of context, or some other character
2494
* with no designated meaning; reject this format specification,
2495
* backtrack, and emit it as literal text...
2498
__pformat_putc( '%', &stream );
2506
/* We just parsed a character which is not included within any format
2507
* specification; we simply emit it as a literal.
2509
__pformat_putc( c, &stream );
2512
/* When we have fully dispatched the format string, the return value is the
2513
* total number of bytes we transferred to the output destination.
2515
return stream.count;