3 <<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
17 int vprintf(const char *<[fmt]>, va_list <[list]>);
18 int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
19 int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
20 int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
22 int _vprintf_r(void *<[reent]>, const char *<[fmt]>,
24 int _vfprintf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
26 int _vsprintf_r(void *<[reent]>, char *<[str]>, const char *<[fmt]>,
28 int _vsnprintf_r(void *<[reent]>, char *<[str]>, size_t <[size]>, const char *<[fmt]>,
32 <<vprintf>>, <<vfprintf>>, <<vsprintf>> and <<vsnprintf>> are (respectively)
33 variants of <<printf>>, <<fprintf>>, <<sprintf>> and <<snprintf>>. They differ
34 only in allowing their caller to pass the variable argument list as a
35 <<va_list>> object (initialized by <<va_start>>) rather than directly
36 accepting a variable number of arguments.
39 The return values are consistent with the corresponding functions:
40 <<vsprintf>> returns the number of bytes in the output string,
41 save that the concluding <<NULL>> is not counted.
42 <<vprintf>> and <<vfprintf>> return the number of characters transmitted.
43 If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>>. No
44 error returns occur for <<vsprintf>>.
47 ANSI C requires all three functions.
49 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
50 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
54 * Copyright (c) 1990 The Regents of the University of California.
55 * All rights reserved.
57 * This code is derived from software contributed to Berkeley by
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
63 * 1. Redistributions of source code must retain the above copyright
64 * notice, this list of conditions and the following disclaimer.
65 * 2. Redistributions in binary form must reproduce the above copyright
66 * notice, this list of conditions and the following disclaimer in the
67 * documentation and/or other materials provided with the distribution.
68 * 3. Neither the name of the University nor the names of its contributors
69 * may be used to endorse or promote products derived from this software
70 * without specific prior written permission.
72 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
73 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
76 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
77 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
78 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
80 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
81 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85 #if defined(LIBC_SCCS) && !defined(lint)
86 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
87 static char *rcsid
= "$Id$";
88 #endif /* LIBC_SCCS and not lint */
91 * Actual printf innards.
93 * This code is large and complicated...
97 #define VFPRINTF vfiprintf
98 #define _VFPRINTF_R _vfiprintf_r
100 #define VFPRINTF vfprintf
101 #define _VFPRINTF_R _vfprintf_r
102 #ifndef NO_FLOATING_POINT
103 #define FLOATING_POINT
123 #include "vfieeefp.h"
125 /* Currently a test is made to see if long double processing is warranted.
126 This could be changed in the future should the _ldtoa_r code be
127 preferred over _dtoa_r. */
129 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
134 #if defined _WANT_IO_LONG_LONG && defined __GNUC__
143 int i
[16 / sizeof(int)];
148 #endif /* __ALTIVEC__ */
151 * Flush out all the vectors defined by the given uio,
152 * then reset it so that it can be reused.
155 __sprint_r(rptr
, fp
, uio
)
158 register struct __suio
*uio
;
162 if (uio
->uio_resid
== 0) {
166 err
= __sfvwrite_r(rptr
, fp
, uio
);
173 * Helper function for `fprintf to unbuffered unix file': creates a
174 * temporary buffer. We only work on write-only files; this avoids
175 * worries about ungetc buffers and so forth.
178 __sbprintf_r(rptr
, fp
, fmt
, ap
)
186 unsigned char buf
[BUFSIZ
];
188 /* copy the important variables */
189 fake
._flags
= fp
->_flags
& ~__SNBF
;
190 fake
._file
= fp
->_file
;
191 fake
._cookie
= fp
->_cookie
;
192 fake
._write
= fp
->_write
;
194 /* set up the buffer */
195 fake
._bf
._base
= fake
._p
= buf
;
196 fake
._bf
._size
= fake
._w
= sizeof(buf
);
197 fake
._lbfsize
= 0; /* not actually used, but Just In Case */
199 /* do the work, then copy any error status */
200 ret
= _VFPRINTF_R(rptr
, &fake
, fmt
, ap
);
201 if (ret
>= 0 && _fflush_r(rptr
, &fake
))
203 if (fake
._flags
& __SERR
)
204 fp
->_flags
|= __SERR
;
209 #ifdef FLOATING_POINT
214 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
218 static char *cvt (struct _reent
*, double, int, int, char *, int *, int, int *);
220 static char *cvt (struct _reent
*, _LONG_DOUBLE
, int, int, char *, int *, int, int *);
221 extern int _ldcheck (_LONG_DOUBLE
*);
224 static int exponent (char *, int, int);
227 static char *cvt_ufix64 (struct _reent
*, unsigned long long, int, int *, int *);
230 #else /* no FLOATING_POINT */
234 #endif /* FLOATING_POINT */
238 * Macros for converting digits to letters and vice versa
240 #define to_digit(c) ((c) - '0')
241 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
242 #define to_char(n) ((n) + '0')
245 * Flags used during conversion.
247 #define ALT 0x001 /* alternate form */
248 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
249 #define LADJUST 0x004 /* left adjustment */
250 #define LONGDBL 0x008 /* long double */
251 #define LONGINT 0x010 /* long integer */
253 #define QUADINT 0x020 /* quad integer */
254 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
255 that %lld behaves the same as %ld, not as %d, as expected if:
256 sizeof (long long) = sizeof long > sizeof int */
257 #define QUADINT LONGINT
259 #define SHORTINT 0x040 /* short integer */
260 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
261 #define FPT 0x100 /* Floating point number */
262 #define VECTOR 0x200 /* vector */
263 #define FIXEDPOINT 0x400 /* fixed-point */
270 CHECK_INIT (_REENT
, fp
);
271 return _VFPRINTF_R (_REENT
, fp
, fmt0
, ap
);
275 _VFPRINTF_R (struct _reent
*data
,
280 register char *fmt
; /* format string */
281 register int ch
; /* character from fmt */
282 register int n
, m
; /* handy integers (short term usage) */
283 register char *cp
; /* handy char pointer (short term usage) */
284 register struct __siov
*iovp
;/* for PRINT macro */
285 register int flags
; /* flags as above */
286 int ret
; /* return value accumulator */
287 int width
; /* width from format (%8d), or 0 */
288 int prec
; /* precision from format (%.3d), or -1 */
289 char sign
; /* sign prefix (' ', '+', '-', or \0) */
290 char old_sign
; /* saved value of sign when looping for vectors */
291 int old_ch
; /* saved value of ch when looping for vectors */
292 char *format_anchor
; /* start of format to process */
294 #ifdef FLOATING_POINT
295 char *decimal_point
= localeconv()->decimal_point
;
296 char softsign
; /* temporary negative sign for floats */
298 union { int i
; double d
; } _double_
= {0};
299 #define _fpvalue (_double_.d)
301 union { int i
; _LONG_DOUBLE ld
; } _long_double_
= {0};
302 #define _fpvalue (_long_double_.ld)
305 int expt
; /* integer value of exponent */
306 int expsize
= 0; /* character count for expstr */
307 int ndig
; /* actual number of digits returned by cvt */
308 char expstr
[7]; /* buffer for exponent string */
312 #define quad_t long long
313 #define u_quad_t unsigned long long
316 #define u_quad_t u_long
319 u_quad_t _uquad
; /* integer arguments %[diouxX] */
320 enum { OCT
, DEC
, HEX
} base
;/* base for [diouxX] conversion */
321 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
322 int realsz
; /* field size expanded by dprec */
323 int size
; /* size of converted field or string */
324 char *xdigs
= NULL
; /* digits for [xX] conversion */
326 struct __suio uio
; /* output information: summary */
327 struct __siov iov
[NIOV
];/* ... and individual io vectors */
328 char buf
[BUF
]; /* space for %c, %[diouxX], %[eEfgG] */
329 char ox
[2]; /* space for 0x hex-prefix */
331 char vec_sep
; /* vector separator char */
332 int vec_print_count
; /* number of vector chunks remaining */
333 vec_16_byte_union vec_tmp
;
334 #endif /* __ALTIVEC__ */
335 mbstate_t state
; /* mbtowc calls from library must not change state */
338 * Choose PADSIZE to trade efficiency vs. size. If larger printf
339 * fields occur frequently, increase PADSIZE and make the initialisers
342 #define PADSIZE 16 /* pad chunk size */
343 static const char blanks
[PADSIZE
] =
344 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
345 static const char zeroes
[PADSIZE
] =
346 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
349 * BEWARE, these `goto error' on error, and PAD uses `n'.
351 #define PRINT(ptr, len) { \
352 iovp->iov_base = (ptr); \
353 iovp->iov_len = (len); \
354 uio.uio_resid += (len); \
356 if (++uio.uio_iovcnt >= NIOV) { \
357 if (__sprint_r(data, fp, &uio)) \
362 #define PAD(howmany, with) { \
363 if ((n = (howmany)) > 0) { \
364 while (n > PADSIZE) { \
365 PRINT(with, PADSIZE); \
372 if (uio.uio_resid && __sprint_r(data, fp, &uio)) \
374 uio.uio_iovcnt = 0; \
379 #define GET_SHORT(ap) \
381 (vec_print_count < 8 ? (short)vec_tmp.s[8 - vec_print_count] : \
382 (vec_tmp.v = va_arg(ap, vector int), (short)vec_tmp.s[0])) : \
383 (short)va_arg(ap, int))
384 #define GET_USHORT(ap) \
386 (vec_print_count < 8 ? (u_short)vec_tmp.s[8 - vec_print_count] : \
387 (vec_tmp.v = va_arg(ap, vector int), (u_short)vec_tmp.s[0])) : \
388 (u_short)va_arg(ap, int))
390 #define GET_LONG(ap) \
392 (vec_print_count < 4 ? (long)vec_tmp.l[4 - vec_print_count] : \
393 (vec_tmp.v = va_arg(ap, vector int), vec_tmp.l[0])) : \
394 va_arg(ap, long int))
395 #define GET_ULONG(ap) \
397 (vec_print_count < 4 ? (u_long)vec_tmp.l[4 - vec_print_count] : \
398 (vec_tmp.v = va_arg(ap, vector int), (u_long)vec_tmp.l[0])) : \
399 (u_long)va_arg(ap, unsigned long int))
401 #define GET_INT(ap) \
403 (vec_print_count < 16 ? \
404 vec_tmp.c[16 - vec_print_count] : \
405 (vec_tmp.v = va_arg(ap, vector int), (int)vec_tmp.c[0])) : \
407 #define GET_UINT(ap) \
409 (vec_print_count < 16 ? \
410 (u_int)((unsigned char)vec_tmp.c[16 - vec_print_count]) : \
411 (vec_tmp.v = va_arg(ap, vector int), (u_int)((unsigned char)vec_tmp.c[0]))) : \
412 (u_int)va_arg(ap, unsigned int))
413 #else /* !__ALTIVEC__ */
414 #define GET_SHORT(ap) ((short)va_arg(ap, int))
415 #define GET_USHORT(ap) ((u_short)va_arg(ap, int))
416 #define GET_LONG(ap) (va_arg(ap, long int))
417 #define GET_ULONG(ap) ((u_long)va_arg(ap, unsigned long int))
418 #define GET_INT(ap) ((int)va_arg(ap, int))
419 #define GET_UINT(ap) ((u_int)va_arg(ap, unsigned int))
420 #endif /* !__ALTIVEC__ */
424 (flags&QUADINT ? va_arg(ap, quad_t) : \
425 flags&LONGINT ? GET_LONG(ap) : \
426 flags&SHORTINT ? (long)GET_SHORT(ap) : \
429 (flags&QUADINT ? va_arg(ap, u_quad_t) : \
430 flags&LONGINT ? GET_ULONG(ap) : \
431 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
432 (u_long)GET_UINT(ap))
435 (flags&LONGINT ? va_arg(ap, quad_t) : \
436 flags&SHORTINT ? (long)GET_SHORT(ap) : \
437 (long)va_arg(ap, int))
439 (flags&LONGINT ? va_arg(ap, u_quad_t) : \
440 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
441 (u_long)va_arg(ap, u_int))
445 (flags&LONGINT ? GET_LONG(ap) : \
446 flags&SHORTINT ? (long)GET_SHORT(ap) : \
449 (flags&LONGINT ? GET_ULONG(ap) : \
450 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
451 (u_long)GET_UINT(ap))
454 (flags&LONGINT ? (va_arg(ap, long) << 32) : \
455 flags&SHORTINT ? (long)GET_SHORT(ap) : \
456 (long)va_arg(ap, int))
458 (flags&LONGINT ? (va_arg(ap, u_long) <<32) : \
459 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
460 (u_long)va_arg(ap, u_int))
464 memset (&state
, '\0', sizeof (state
));
466 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
467 if (cantwrite (data
, fp
)) {
472 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
473 if ((fp
->_flags
& (__SNBF
|__SWR
|__SRW
)) == (__SNBF
|__SWR
) &&
475 return (__sbprintf_r(data
, fp
, fmt0
, ap
));
478 uio
.uio_iov
= iovp
= iov
;
484 * Scan the format for conversions (`%' character).
489 while ((n
= _mbtowc_r(data
, &wc
, fmt
, MB_CUR_MAX
, &state
)) > 0) {
496 if ((m
= fmt
- cp
) != 0) {
502 fmt
++; /* skip over '%' */
513 #endif /* __ALTIVEC__ */
518 reswitch
: switch (ch
) {
521 * ``If the space and + flags both appear, the space
522 * flag will be ignored.''
533 * ``A negative field width argument is taken as a
534 * - flag followed by a positive field width.''
536 * They don't exclude field widths read from args.
538 if ((width
= va_arg(ap
, int)) >= 0)
560 #endif /* __ALTIVEC__ */
562 if ((ch
= *fmt
++) == '*') {
564 prec
= n
< 0 ? -1 : n
;
568 while (is_digit(ch
)) {
569 n
= 10 * n
+ to_digit(ch
);
572 prec
= n
< 0 ? -1 : n
;
576 * ``Note that 0 is taken as a flag, not as the
577 * beginning of a field width.''
582 case '1': case '2': case '3': case '4':
583 case '5': case '6': case '7': case '8': case '9':
586 n
= 10 * n
+ to_digit(ch
);
588 } while (is_digit(ch
));
591 #ifdef FLOATING_POINT
599 #endif /* __ALTIVEC__ */
616 if (flags
& SHORTINT
)
641 vec_print_count
= (flags
& SHORTINT
) ? 8 :
642 ((flags
& LONGINT
) ? 4 : 16);
652 #endif /* __ALTIVEC__ */
660 vec_16_byte_union tmp
;
661 if (flags
& (SHORTINT
| LONGINT
))
666 tmp
.v
= va_arg(ap
, vector
int);
668 for (k
= 0; k
< 15; ++k
)
680 #endif /* __ALTIVEC__ */
682 *(cp
= buf
) = va_arg(ap
, int);
693 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
698 #endif /* __ALTIVEC__ */
700 if ((quad_t
)_uquad
< 0)
702 _uquad
= -(quad_t
)_uquad
;
708 #ifdef FLOATING_POINT
716 } else if ((ch
== 'g' || ch
== 'G') && prec
== 0) {
721 if (flags
& LONGDBL
) {
722 _fpvalue
= (double) va_arg(ap
, _LONG_DOUBLE
);
724 } else if (flags
& VECTOR
) {
725 if (vec_print_count
>= 4)
728 vec_tmp
.v
= va_arg(ap
, vector
int);
730 _fpvalue
= (double)vec_tmp
.f
[4 - vec_print_count
];
731 } else if (vec_sep
!= ' ') {
735 #endif /* __ALTIVEC__ */
737 _fpvalue
= va_arg(ap
, double);
740 /* do this before tricky precision changes */
741 if (isinf(_fpvalue
)) {
752 if (isnan(_fpvalue
)) {
758 #else /* !_NO_LONGDBL */
760 if (flags
& LONGDBL
) {
761 _fpvalue
= va_arg(ap
, _LONG_DOUBLE
);
763 } else if (flags
& VECTOR
) {
764 if (vec_print_count
>= 4)
767 vec_tmp
.v
= va_arg(ap
, vector
int);
769 _fpvalue
= (_LONG_DOUBLE
)k
.f
[4 - vec_print_count
];
770 #endif /* __ALTIVEC__ */
772 _fpvalue
= (_LONG_DOUBLE
)va_arg(ap
, double);
775 /* do this before tricky precision changes */
776 tmp
= _ldcheck (&_fpvalue
);
792 #endif /* !_NO_LONGDBL */
796 cp
= cvt(data
, _fpvalue
, prec
, flags
, &softsign
,
799 if (ch
== 'g' || ch
== 'G') {
800 if (expt
<= -4 || expt
> prec
)
803 ch
= (ch
== 'g') ? 'e' : 'E';
808 if (ch
<= 'e') { /* 'e' or 'E' fmt */
810 expsize
= exponent(expstr
, expt
, ch
);
811 size
= expsize
+ ndig
;
812 if (ndig
> 1 || flags
& ALT
)
814 } else if (ch
== 'f') { /* f fmt */
817 if (prec
|| flags
& ALT
)
820 size
= (prec
|| flags
& ALT
)
823 } else if (expt
>= ndig
) { /* fixed g fmt */
828 size
= ndig
+ (expt
> 0 ?
837 #endif /* FLOATING_POINT */
842 if ((quad_t
)_uquad
< 0)
845 _uquad
= -(quad_t
)_uquad
;
847 if (flags
& SHORTINT
)
848 _uquad
<<= (sizeof(quad_t
) - sizeof(short)) * 8 + 1;
849 else if (flags
& LONGINT
)
852 _uquad
<<= (sizeof(quad_t
) - sizeof(long)) * 8 + 1;
854 if (_uquad
== 0 && sign
)
856 /* we have -1.0 which has to be handled special */
867 if (flags
& SHORTINT
)
868 _uquad
<<= (sizeof(quad_t
) - sizeof(short)) * 8;
869 else if (!(flags
& LONGINT
))
870 _uquad
<<= (sizeof(quad_t
) - sizeof(long)) * 8;
877 cp
= cvt_ufix64 (data
, _uquad
, prec
, &expt
, &ndig
);
879 cp
= cvs_ufix32 (data
, _uquad
, prec
, &expt
, &ndig
);
882 /* act like %f of format "0.X" */
894 #endif /* __ALTIVEC__ */
897 *va_arg(ap
, quad_t
*) = ret
;
901 *va_arg(ap
, long *) = ret
;
902 else if (flags
& SHORTINT
)
903 *va_arg(ap
, short *) = ret
;
905 *va_arg(ap
, int *) = ret
;
906 continue; /* no output */
912 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
917 #endif /* __ALTIVEC__ */
923 * ``The argument shall be a pointer to void. The
924 * value of the pointer is converted to a sequence
925 * of printable characters, in an implementation-
933 else if (vec_sep
!= ' ')
939 #endif /* __ALTIVEC__ */
940 _uquad
= (u_long
)(unsigned _POINTER_INT
)va_arg(ap
, void *);
942 xdigs
= "0123456789abcdef";
953 #endif /* __ALTIVEC__ */
954 if ((cp
= va_arg(ap
, char *)) == NULL
)
958 * can't use strlen; can only look for the
959 * NUL in the first `prec' characters, and
960 * strlen() will go further.
962 char *p
= memchr(cp
, 0, prec
);
979 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
984 #endif /* __ALTIVEC__ */
989 xdigs
= "0123456789ABCDEF";
992 xdigs
= "0123456789abcdef";
994 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
999 #endif /* __ALTIVEC__ */
1000 hex
: _uquad
= UARG();
1002 /* leading 0x/X only if non-zero */
1003 if (flags
& ALT
&& _uquad
!= 0)
1006 /* unsigned conversions */
1007 nosign
: sign
= '\0';
1009 * ``... diouXx conversions ... if a precision is
1010 * specified, the 0 flag will be ignored.''
1013 number
: if ((dprec
= prec
) >= 0)
1017 * ``The result of converting a zero value with an
1018 * explicit precision of zero is no characters.''
1022 if (_uquad
!= 0 || prec
!= 0) {
1024 * Unsigned mod is hard, and unsigned mod
1025 * by a constant is easier than that by
1026 * a variable; hence this switch.
1031 *--cp
= to_char(_uquad
& 7);
1034 /* handle octal leading 0 */
1035 if (flags
& ALT
&& *cp
!= '0')
1040 /* many numbers are 1 digit */
1041 while (_uquad
>= 10) {
1042 *--cp
= to_char(_uquad
% 10);
1045 *--cp
= to_char(_uquad
);
1050 *--cp
= xdigs
[_uquad
& 15];
1056 cp
= "bug in vfprintf: bad base";
1062 * ...result is to be converted to an 'alternate form'.
1063 * For o conversion, it increases the precision to force
1064 * the first digit of the result to be a zero."
1067 * To demonstrate this case, compile and run:
1068 * printf ("%#.0o",0);
1070 else if (base
== OCT
&& (flags
& ALT
))
1073 size
= buf
+ BUF
- cp
;
1076 default: /* "%?" prints ?, unless ? is NUL */
1080 /* pretend it was %c with argument ch */
1089 * All reasonable formats wind up here. At this point, `cp'
1090 * points to a string which (if not flags&LADJUST) should be
1091 * padded out to `width' places. If flags&ZEROPAD, it should
1092 * first be prefixed by any sign or other prefix; otherwise,
1093 * it should be blank padded before the prefix is emitted.
1094 * After any left-hand padding and prefixing, emit zeroes
1095 * required by a decimal [diouxX] precision, then print the
1096 * string proper, then emit zeroes required by any leftover
1097 * floating precision; finally, if LADJUST, pad with blanks.
1099 * Compute actual size, so we know how much to pad.
1100 * size excludes decimal prec; realsz includes it.
1102 realsz
= dprec
> size
? dprec
: size
;
1105 else if (flags
& HEXPREFIX
)
1108 /* right-adjusting blank padding */
1109 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
1110 PAD(width
- realsz
, blanks
);
1115 } else if (flags
& HEXPREFIX
) {
1121 /* right-adjusting zero padding */
1122 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
1123 PAD(width
- realsz
, zeroes
);
1125 /* leading zeroes from decimal precision */
1126 PAD(dprec
- size
, zeroes
);
1128 /* the string or number proper */
1129 #ifdef FLOATING_POINT
1130 if ((flags
& FPT
) == 0) {
1132 if (flags
& FIXEDPOINT
) {
1133 if (_uquad
== 0 && !sign
) {
1134 /* kludge for __dtoa irregularity */
1136 if (expt
< ndig
|| (flags
& ALT
) != 0) {
1137 PRINT(decimal_point
, 1);
1138 PAD(ndig
- 1, zeroes
);
1140 } else if (expt
<= 0) {
1143 PRINT(decimal_point
, 1);
1147 } else if (expt
>= ndig
) {
1149 PAD(expt
- ndig
, zeroes
);
1156 PRINT(cp
, ndig
-expt
);
1159 #endif /* __SPE__ */
1161 } else { /* glue together f_p fragments */
1162 if (ch
>= 'f') { /* 'f' or 'g' */
1163 if (_fpvalue
== 0) {
1164 /* kludge for __dtoa irregularity */
1166 if (expt
< ndig
|| (flags
& ALT
) != 0) {
1167 PRINT(decimal_point
, 1);
1168 PAD(ndig
- 1, zeroes
);
1170 } else if (expt
<= 0) {
1173 PRINT(decimal_point
, 1);
1177 } else if (expt
>= ndig
) {
1179 PAD(expt
- ndig
, zeroes
);
1186 PRINT(cp
, ndig
-expt
);
1188 } else { /* 'e' or 'E' */
1189 if (ndig
> 1 || flags
& ALT
) {
1195 } else /* 0.[0..] */
1196 /* __dtoa irregularity */
1197 PAD(ndig
- 1, zeroes
);
1200 PRINT(expstr
, expsize
);
1206 /* left-adjusting padding (always blank) */
1207 if (flags
& LADJUST
)
1208 PAD(width
- realsz
, blanks
);
1210 /* finally, adjust ret */
1211 ret
+= width
> realsz
? width
: realsz
;
1214 if ((flags
& VECTOR
) && vec_print_count
-- > 1)
1216 /* add vector separator */
1217 if (ch
!= 'c' || vec_sep
!= ' ')
1227 #endif /* __ALTIVEC__ */
1228 FLUSH(); /* copy out the I/O vectors */
1233 return (__sferror(fp
) ? EOF
: ret
);
1237 #ifdef FLOATING_POINT
1240 extern char *_dtoa_r (struct _reent
*, double, int,
1241 int, int *, int *, char **);
1243 extern char *_ldtoa_r (struct _reent
*, _LONG_DOUBLE
, int,
1244 int, int *, int *, char **);
1246 #define word0(x) ldword0(x)
1250 cvt(data
, value
, ndigits
, flags
, sign
, decpt
, ch
, length
)
1251 struct _reent
*data
;
1257 int ndigits
, flags
, *decpt
, ch
, *length
;
1261 char *digits
, *bp
, *rve
;
1263 union double_union tmp
;
1265 struct ldieee
*ldptr
;
1269 mode
= 3; /* ndigits after the decimal point */
1271 /* To obtain ndigits after the decimal point for the 'e'
1272 * and 'E' formats, round to ndigits + 1 significant
1275 if (ch
== 'e' || ch
== 'E') {
1278 mode
= 2; /* ndigits significant digits */
1284 if (word0(tmp
) & Sign_bit
) { /* this will check for < 0 and -0.0 */
1290 digits
= _dtoa_r(data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1291 #else /* !_NO_LONGDBL */
1292 ldptr
= (struct ldieee
*)&value
;
1293 if (ldptr
->sign
) { /* this will check for < 0 and -0.0 */
1299 digits
= _ldtoa_r(data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1300 #endif /* !_NO_LONGDBL */
1302 if ((ch
!= 'g' && ch
!= 'G') || flags
& ALT
) { /* Print trailing zeros */
1303 bp
= digits
+ ndigits
;
1305 if (*digits
== '0' && value
)
1306 *decpt
= -ndigits
+ 1;
1309 if (value
== 0) /* kludge for __dtoa irregularity */
1314 *length
= rve
- digits
;
1319 exponent(p0
, exp
, fmtch
)
1323 register char *p
, *t
;
1337 *--t
= to_char(exp
% 10);
1338 } while ((exp
/= 10) > 9);
1339 *--t
= to_char(exp
);
1340 for (; t
< expbuf
+ 40; *p
++ = *t
++);
1344 *p
++ = to_char(exp
);
1348 #endif /* FLOATING_POINT */
1351 extern char *_ufix64toa_r (struct _reent
*, unsigned long long, int,
1352 int, int *, int *, char **);
1354 cvt_ufix64 (data
, value
, ndigits
, decpt
, length
)
1355 struct _reent
*data
;
1356 unsigned long long value
;
1357 int ndigits
, *decpt
, *length
;
1360 char *digits
, *bp
, *rve
;
1362 /* treat the same as %f format and use mode=3 */
1363 digits
= _ufix64toa_r (data
, value
, 3, ndigits
, decpt
, &dsgn
, &rve
);
1365 /* print trailing zeroes */
1366 bp
= digits
+ ndigits
;
1367 if (*digits
== '0' && value
)
1368 *decpt
= -ndigits
+ 1;
1370 if (value
== 0) /* kludge for __dtoa irregularity */
1374 *length
= rve
- digits
;
1377 #endif /* __SPE__ */