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]>,
34 int vprintf( <[fmt]>, <[list]>)
38 int vfprintf(<[fp]>, <[fmt]>, <[list]>)
43 int vsprintf(<[str]>, <[fmt]>, <[list]>)
48 int vsnprintf(<[str]>, <[size]>, <[fmt]>, <[list]>)
54 int _vprintf_r(<[reent]>, <[fmt]>, <[list]>)
59 int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
65 int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
71 int _vsnprintf_r(<[reent]>, <[str]>, <[size]>, <[fmt]>, <[list]>)
79 <<vprintf>>, <<vfprintf>>, <<vsprintf>> and <<vsnprintf>> are (respectively)
80 variants of <<printf>>, <<fprintf>>, <<sprintf>> and <<snprintf>>. They differ
81 only in allowing their caller to pass the variable argument list as a
82 <<va_list>> object (initialized by <<va_start>>) rather than directly
83 accepting a variable number of arguments.
86 The return values are consistent with the corresponding functions:
87 <<vsprintf>> returns the number of bytes in the output string,
88 save that the concluding <<NULL>> is not counted.
89 <<vprintf>> and <<vfprintf>> return the number of characters transmitted.
90 If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>>. No
91 error returns occur for <<vsprintf>>.
94 ANSI C requires all three functions.
96 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
97 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
101 * Copyright (c) 1990 The Regents of the University of California.
102 * All rights reserved.
104 * This code is derived from software contributed to Berkeley by
107 * Redistribution and use in source and binary forms, with or without
108 * modification, are permitted provided that the following conditions
110 * 1. Redistributions of source code must retain the above copyright
111 * notice, this list of conditions and the following disclaimer.
112 * 2. Redistributions in binary form must reproduce the above copyright
113 * notice, this list of conditions and the following disclaimer in the
114 * documentation and/or other materials provided with the distribution.
115 * 3. All advertising materials mentioning features or use of this software
116 * must display the following acknowledgement:
117 * This product includes software developed by the University of
118 * California, Berkeley and its contributors.
119 * 4. Neither the name of the University nor the names of its contributors
120 * may be used to endorse or promote products derived from this software
121 * without specific prior written permission.
123 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
124 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
125 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
126 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
127 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
128 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
129 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
130 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
131 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
132 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
136 #if defined(LIBC_SCCS) && !defined(lint)
137 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
138 static char *rcsid
= "$Id: vfprintf.c 135 2004-10-08 10:01:07Z oyvind $";
139 #endif /* LIBC_SCCS and not lint */
142 * Actual printf innards.
144 * This code is large and complicated...
148 #define VFPRINTF vfiprintf
149 #define _VFPRINTF_R _vfiprintf_r
151 #define VFPRINTF vfprintf
152 #define _VFPRINTF_R _vfprintf_r
153 #ifndef NO_FLOATING_POINT
154 #define FLOATING_POINT
159 #if defined WANT_PRINTF_LONG_LONG && defined __GNUC__
183 #include "vfieeefp.h"
185 /* Currently a test is made to see if long double processing is warranted.
186 This could be changed in the future should the _ldtoa_r code be
187 preferred over _dtoa_r. */
189 #if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG)
198 int i
[16 / sizeof(int)];
203 #endif /* __ALTIVEC__ */
206 * Flush out all the vectors defined by the given uio,
207 * then reset it so that it can be reused.
212 register struct __suio
*uio
;
216 if (uio
->uio_resid
== 0) {
220 err
= __sfvwrite(fp
, uio
);
227 * Helper function for `fprintf to unbuffered unix file': creates a
228 * temporary buffer. We only work on write-only files; this avoids
229 * worries about ungetc buffers and so forth.
232 __sbprintf(fp
, fmt
, ap
)
239 unsigned char buf
[BUFSIZ
];
241 /* copy the important variables */
242 fake
._data
= fp
->_data
;
243 fake
._flags
= fp
->_flags
& ~__SNBF
;
244 fake
._file
= fp
->_file
;
245 fake
._cookie
= fp
->_cookie
;
246 fake
._write
= fp
->_write
;
248 /* set up the buffer */
249 fake
._bf
._base
= fake
._p
= buf
;
250 fake
._bf
._size
= fake
._w
= sizeof(buf
);
251 fake
._lbfsize
= 0; /* not actually used, but Just In Case */
253 /* do the work, then copy any error status */
254 ret
= VFPRINTF(&fake
, fmt
, ap
);
255 if (ret
>= 0 && fflush(&fake
))
257 if (fake
._flags
& __SERR
)
258 fp
->_flags
|= __SERR
;
263 #ifdef FLOATING_POINT
268 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
272 static char *cvt
_PARAMS((struct _reent
*, double, int, int, char *, int *, int, int *));
274 static char *cvt
_PARAMS((struct _reent
*, _LONG_DOUBLE
, int, int, char *, int *, int, int *));
275 extern int _ldcheck
_PARAMS((_LONG_DOUBLE
*));
278 static int exponent
_PARAMS((char *, int, int));
281 static char *cvt_ufix64
_PARAMS((struct _reent
*, unsigned long long, int, int *, int *));
284 #else /* no FLOATING_POINT */
288 #endif /* FLOATING_POINT */
292 * Macros for converting digits to letters and vice versa
294 #define to_digit(c) ((c) - '0')
295 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
296 #define to_char(n) ((n) + '0')
299 * Flags used during conversion.
301 #define ALT 0x001 /* alternate form */
302 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
303 #define LADJUST 0x004 /* left adjustment */
304 #define LONGDBL 0x008 /* long double */
305 #define LONGINT 0x010 /* long integer */
307 #define QUADINT 0x020 /* quad integer */
308 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
309 that %lld behaves the same as %ld, not as %d, as expected if:
310 sizeof (long long) = sizeof long > sizeof int */
311 #define QUADINT LONGINT
313 #define SHORTINT 0x040 /* short integer */
314 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
315 #define FPT 0x100 /* Floating point number */
316 #define VECTOR 0x200 /* vector */
317 #define FIXEDPOINT 0x400 /* fixed-point */
320 _DEFUN (VFPRINTF
, (fp
, fmt0
, ap
),
322 _CONST
char *fmt0 _AND
326 return _VFPRINTF_R (fp
->_data
, fp
, fmt0
, ap
);
330 _DEFUN (_VFPRINTF_R
, (data
, fp
, fmt0
, ap
),
331 struct _reent
*data _AND
333 _CONST
char *fmt0 _AND
336 register char *fmt
; /* format string */
337 register int ch
; /* character from fmt */
338 register int n
, m
; /* handy integers (short term usage) */
339 register char *cp
; /* handy char pointer (short term usage) */
340 register struct __siov
*iovp
;/* for PRINT macro */
341 register int flags
; /* flags as above */
342 int ret
; /* return value accumulator */
343 int width
; /* width from format (%8d), or 0 */
344 int prec
; /* precision from format (%.3d), or -1 */
345 char sign
; /* sign prefix (' ', '+', '-', or \0) */
346 char old_sign
; /* saved value of sign when looping for vectors */
347 int old_ch
; /* saved value of ch when looping for vectors */
348 char *format_anchor
; /* start of format to process */
350 #ifdef FLOATING_POINT
351 char *decimal_point
= localeconv()->decimal_point
;
352 char softsign
; /* temporary negative sign for floats */
354 union { int i
; double d
; } _double_
= {0};
355 #define _fpvalue (_double_.d)
357 union { int i
; _LONG_DOUBLE ld
; } _long_double_
= {0};
358 #define _fpvalue (_long_double_.ld)
361 int expt
; /* integer value of exponent */
362 int expsize
= 0; /* character count for expstr */
363 int ndig
; /* actual number of digits returned by cvt */
364 char expstr
[7]; /* buffer for exponent string */
368 #define quad_t long long
369 #define u_quad_t unsigned long long
373 u_quad_t _uquad
; /* integer arguments %[diouxX] */
377 enum { OCT
, DEC
, HEX
} base
;/* base for [diouxX] conversion */
378 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
379 int realsz
; /* field size expanded by dprec */
380 int size
; /* size of converted field or string */
381 char *xdigs
= NULL
; /* digits for [xX] conversion */
383 struct __suio uio
; /* output information: summary */
384 struct __siov iov
[NIOV
];/* ... and individual io vectors */
385 char buf
[BUF
]; /* space for %c, %[diouxX], %[eEfgG] */
386 char ox
[2]; /* space for 0x hex-prefix */
388 char vec_sep
; /* vector separator char */
389 int vec_print_count
; /* number of vector chunks remaining */
390 vec_16_byte_union vec_tmp
;
391 #endif /* __ALTIVEC__ */
392 mbstate_t state
; /* mbtowc calls from library must not change state */
395 * Choose PADSIZE to trade efficiency vs. size. If larger printf
396 * fields occur frequently, increase PADSIZE and make the initialisers
399 #define PADSIZE 16 /* pad chunk size */
400 static _CONST
char blanks
[PADSIZE
] =
401 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
402 static _CONST
char zeroes
[PADSIZE
] =
403 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
406 * BEWARE, these `goto error' on error, and PAD uses `n'.
408 #define PRINT(ptr, len) { \
409 iovp->iov_base = (ptr); \
410 iovp->iov_len = (len); \
411 uio.uio_resid += (len); \
413 if (++uio.uio_iovcnt >= NIOV) { \
414 if (__sprint(fp, &uio)) \
419 #define PAD(howmany, with) { \
420 if ((n = (howmany)) > 0) { \
421 while (n > PADSIZE) { \
422 PRINT(with, PADSIZE); \
429 if (uio.uio_resid && __sprint(fp, &uio)) \
431 uio.uio_iovcnt = 0; \
436 #define GET_SHORT(ap) \
438 (vec_print_count < 8 ? (short)vec_tmp.s[8 - vec_print_count] : \
439 (vec_tmp.v = va_arg(ap, vector int), (short)vec_tmp.s[0])) : \
440 (short)va_arg(ap, int))
441 #define GET_USHORT(ap) \
443 (vec_print_count < 8 ? (u_short)vec_tmp.s[8 - vec_print_count] : \
444 (vec_tmp.v = va_arg(ap, vector int), (u_short)vec_tmp.s[0])) : \
445 (u_short)va_arg(ap, int))
447 #define GET_LONG(ap) \
449 (vec_print_count < 4 ? (long)vec_tmp.l[4 - vec_print_count] : \
450 (vec_tmp.v = va_arg(ap, vector int), vec_tmp.l[0])) : \
451 va_arg(ap, long int))
452 #define GET_ULONG(ap) \
454 (vec_print_count < 4 ? (u_long)vec_tmp.l[4 - vec_print_count] : \
455 (vec_tmp.v = va_arg(ap, vector int), (u_long)vec_tmp.l[0])) : \
456 (u_long)va_arg(ap, unsigned long int))
458 #define GET_INT(ap) \
460 (vec_print_count < 16 ? \
461 vec_tmp.c[16 - vec_print_count] : \
462 (vec_tmp.v = va_arg(ap, vector int), (int)vec_tmp.c[0])) : \
464 #define GET_UINT(ap) \
466 (vec_print_count < 16 ? \
467 (u_int)((unsigned char)vec_tmp.c[16 - vec_print_count]) : \
468 (vec_tmp.v = va_arg(ap, vector int), (u_int)((unsigned char)vec_tmp.c[0]))) : \
469 (u_int)va_arg(ap, unsigned int))
470 #else /* !__ALTIVEC__ */
471 #define GET_SHORT(ap) ((short)va_arg(ap, int))
472 #define GET_USHORT(ap) ((u_short)va_arg(ap, int))
473 #define GET_LONG(ap) (va_arg(ap, long int))
474 #define GET_ULONG(ap) ((u_long)va_arg(ap, unsigned long int))
475 #define GET_INT(ap) ((int)va_arg(ap, int))
476 #define GET_UINT(ap) ((u_int)va_arg(ap, unsigned int))
477 #endif /* !__ALTIVEC__ */
481 (flags&QUADINT ? va_arg(ap, quad_t) : \
482 flags&LONGINT ? GET_LONG(ap) : \
483 flags&SHORTINT ? (long)GET_SHORT(ap) : \
486 (flags&QUADINT ? va_arg(ap, u_quad_t) : \
487 flags&LONGINT ? GET_ULONG(ap) : \
488 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
489 (u_long)GET_UINT(ap))
492 (flags&LONGINT ? va_arg(ap, quad_t) : \
493 flags&SHORTINT ? (long)GET_SHORT(ap) : \
494 (long)va_arg(ap, int))
496 (flags&LONGINT ? va_arg(ap, u_quad_t) : \
497 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
498 (u_long)va_arg(ap, u_int))
502 (flags&LONGINT ? GET_LONG(ap) : \
503 flags&SHORTINT ? (long)GET_SHORT(ap) : \
506 (flags&LONGINT ? GET_ULONG(ap) : \
507 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
508 (u_long)GET_UINT(ap))
511 (flags&LONGINT ? (va_arg(ap, long) << 32) : \
512 flags&SHORTINT ? (long)GET_SHORT(ap) : \
513 (long)va_arg(ap, int))
515 (flags&LONGINT ? (va_arg(ap, u_long) <<32) : \
516 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
517 (u_long)va_arg(ap, u_int))
521 memset (&state
, '\0', sizeof (state
));
523 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
527 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
528 if ((fp
->_flags
& (__SNBF
|__SWR
|__SRW
)) == (__SNBF
|__SWR
) &&
530 return (__sbprintf(fp
, fmt0
, ap
));
533 uio
.uio_iov
= iovp
= iov
;
539 * Scan the format for conversions (`%' character).
543 while ((n
= _mbtowc_r(_REENT
, &wc
, fmt
, MB_CUR_MAX
, &state
)) > 0) {
550 if ((m
= fmt
- cp
) != 0) {
556 fmt
++; /* skip over '%' */
567 #endif /* __ALTIVEC__ */
572 reswitch
: switch (ch
) {
575 * ``If the space and + flags both appear, the space
576 * flag will be ignored.''
587 * ``A negative field width argument is taken as a
588 * - flag followed by a positive field width.''
590 * They don't exclude field widths read from args.
592 if ((width
= va_arg(ap
, int)) >= 0)
614 #endif /* __ALTIVEC__ */
616 if ((ch
= *fmt
++) == '*') {
618 prec
= n
< 0 ? -1 : n
;
622 while (is_digit(ch
)) {
623 n
= 10 * n
+ to_digit(ch
);
626 prec
= n
< 0 ? -1 : n
;
630 * ``Note that 0 is taken as a flag, not as the
631 * beginning of a field width.''
636 case '1': case '2': case '3': case '4':
637 case '5': case '6': case '7': case '8': case '9':
640 n
= 10 * n
+ to_digit(ch
);
642 } while (is_digit(ch
));
645 #ifdef FLOATING_POINT
653 #endif /* __ALTIVEC__ */
670 if (flags
& SHORTINT
)
695 vec_print_count
= (flags
& SHORTINT
) ? 8 :
696 ((flags
& LONGINT
) ? 4 : 16);
706 #endif /* __ALTIVEC__ */
714 vec_16_byte_union tmp
;
715 if (flags
& (SHORTINT
| LONGINT
))
720 tmp
.v
= va_arg(ap
, vector
int);
722 for (k
= 0; k
< 15; ++k
)
734 #endif /* __ALTIVEC__ */
736 *(cp
= buf
) = va_arg(ap
, int);
747 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
752 #endif /* __ALTIVEC__ */
755 if ((quad_t
)_uquad
< 0)
757 if ((long) _uquad
< 0)
767 #ifdef FLOATING_POINT
775 } else if ((ch
== 'g' || ch
== 'G') && prec
== 0) {
780 if (flags
& LONGDBL
) {
781 _fpvalue
= (double) va_arg(ap
, _LONG_DOUBLE
);
783 } else if (flags
& VECTOR
) {
784 if (vec_print_count
>= 4)
787 vec_tmp
.v
= va_arg(ap
, vector
int);
789 _fpvalue
= (double)vec_tmp
.f
[4 - vec_print_count
];
790 } else if (vec_sep
!= ' ') {
794 #endif /* __ALTIVEC__ */
796 _fpvalue
= va_arg(ap
, double);
799 /* do this before tricky precision changes */
800 if (isinf(_fpvalue
)) {
811 if (isnan(_fpvalue
)) {
817 #else /* !_NO_LONGDBL */
819 if (flags
& LONGDBL
) {
820 _fpvalue
= va_arg(ap
, _LONG_DOUBLE
);
822 } else if (flags
& VECTOR
) {
823 if (vec_print_count
>= 4)
826 vec_tmp
.v
= va_arg(ap
, vector
int);
828 _fpvalue
= (_LONG_DOUBLE
)k
.f
[4 - vec_print_count
];
829 #endif /* __ALTIVEC__ */
831 _fpvalue
= (_LONG_DOUBLE
)va_arg(ap
, double);
834 /* do this before tricky precision changes */
835 tmp
= _ldcheck (&_fpvalue
);
851 #endif /* !_NO_LONGDBL */
855 cp
= cvt(data
, _fpvalue
, prec
, flags
, &softsign
,
858 if (ch
== 'g' || ch
== 'G') {
859 if (expt
<= -4 || expt
> prec
)
862 ch
= (ch
== 'g') ? 'e' : 'E';
867 if (ch
<= 'e') { /* 'e' or 'E' fmt */
869 expsize
= exponent(expstr
, expt
, ch
);
870 size
= expsize
+ ndig
;
871 if (ndig
> 1 || flags
& ALT
)
873 } else if (ch
== 'f') { /* f fmt */
876 if (prec
|| flags
& ALT
)
880 } else if (expt
>= ndig
) { /* fixed g fmt */
885 size
= ndig
+ (expt
> 0 ?
894 #endif /* FLOATING_POINT */
899 if ((quad_t
)_uquad
< 0)
902 _uquad
= -(quad_t
)_uquad
;
904 if (flags
& SHORTINT
)
906 else if (flags
& LONGINT
)
911 if (_uquad
== 0 && sign
)
913 /* we have -1.0 which has to be handled special */
924 if (flags
& SHORTINT
)
926 else if (!(flags
& LONGINT
))
933 cp
= cvt_ufix64 (data
, _uquad
, prec
, &expt
, &ndig
);
935 /* act like %f of format "0.X" */
947 #endif /* __ALTIVEC__ */
950 *va_arg(ap
, quad_t
*) = ret
;
954 *va_arg(ap
, long *) = ret
;
955 else if (flags
& SHORTINT
)
956 *va_arg(ap
, short *) = ret
;
958 *va_arg(ap
, int *) = ret
;
959 continue; /* no output */
965 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
970 #endif /* __ALTIVEC__ */
976 * ``The argument shall be a pointer to void. The
977 * value of the pointer is converted to a sequence
978 * of printable characters, in an implementation-
986 else if (vec_sep
!= ' ')
992 #endif /* __ALTIVEC__ */
993 _uquad
= (u_long
)(unsigned _POINTER_INT
)va_arg(ap
, void *);
995 xdigs
= "0123456789abcdef";
1003 fmt
= format_anchor
;
1006 #endif /* __ALTIVEC__ */
1007 if ((cp
= va_arg(ap
, char *)) == NULL
)
1011 * can't use strlen; can only look for the
1012 * NUL in the first `prec' characters, and
1013 * strlen() will go further.
1015 char *p
= memchr(cp
, 0, prec
);
1032 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
1034 fmt
= format_anchor
;
1037 #endif /* __ALTIVEC__ */
1042 xdigs
= "0123456789ABCDEF";
1045 xdigs
= "0123456789abcdef";
1047 if (!(flags
& VECTOR
) && vec_sep
!= ' ')
1049 fmt
= format_anchor
;
1052 #endif /* __ALTIVEC__ */
1053 hex
: _uquad
= UARG();
1055 /* leading 0x/X only if non-zero */
1056 if (flags
& ALT
&& _uquad
!= 0)
1059 /* unsigned conversions */
1060 nosign
: sign
= '\0';
1062 * ``... diouXx conversions ... if a precision is
1063 * specified, the 0 flag will be ignored.''
1066 number
: if ((dprec
= prec
) >= 0)
1070 * ``The result of converting a zero value with an
1071 * explicit precision of zero is no characters.''
1075 if (_uquad
!= 0 || prec
!= 0) {
1077 * Unsigned mod is hard, and unsigned mod
1078 * by a constant is easier than that by
1079 * a variable; hence this switch.
1084 *--cp
= to_char(_uquad
& 7);
1087 /* handle octal leading 0 */
1088 if (flags
& ALT
&& *cp
!= '0')
1093 /* many numbers are 1 digit */
1094 while (_uquad
>= 10) {
1095 *--cp
= to_char(_uquad
% 10);
1098 *--cp
= to_char(_uquad
);
1103 *--cp
= xdigs
[_uquad
& 15];
1109 cp
= "bug in vfprintf: bad base";
1115 * ...result is to be converted to an 'alternate form'.
1116 * For o conversion, it increases the precision to force
1117 * the first digit of the result to be a zero."
1120 * To demonstrate this case, compile and run:
1121 * printf ("%#.0o",0);
1123 else if (base
== OCT
&& (flags
& ALT
))
1126 size
= buf
+ BUF
- cp
;
1129 default: /* "%?" prints ?, unless ? is NUL */
1133 /* pretend it was %c with argument ch */
1142 * All reasonable formats wind up here. At this point, `cp'
1143 * points to a string which (if not flags&LADJUST) should be
1144 * padded out to `width' places. If flags&ZEROPAD, it should
1145 * first be prefixed by any sign or other prefix; otherwise,
1146 * it should be blank padded before the prefix is emitted.
1147 * After any left-hand padding and prefixing, emit zeroes
1148 * required by a decimal [diouxX] precision, then print the
1149 * string proper, then emit zeroes required by any leftover
1150 * floating precision; finally, if LADJUST, pad with blanks.
1152 * Compute actual size, so we know how much to pad.
1153 * size excludes decimal prec; realsz includes it.
1155 realsz
= dprec
> size
? dprec
: size
;
1158 else if (flags
& HEXPREFIX
)
1161 /* right-adjusting blank padding */
1162 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
1163 PAD(width
- realsz
, blanks
);
1168 } else if (flags
& HEXPREFIX
) {
1174 /* right-adjusting zero padding */
1175 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
1176 PAD(width
- realsz
, zeroes
);
1178 /* leading zeroes from decimal precision */
1179 PAD(dprec
- size
, zeroes
);
1181 /* the string or number proper */
1182 #ifdef FLOATING_POINT
1183 if ((flags
& FPT
) == 0) {
1185 if (flags
& FIXEDPOINT
) {
1186 if (_uquad
== 0 && !sign
) {
1187 /* kludge for __dtoa irregularity */
1189 if (expt
< ndig
|| (flags
& ALT
) != 0) {
1190 PRINT(decimal_point
, 1);
1191 PAD(ndig
- 1, zeroes
);
1193 } else if (expt
<= 0) {
1196 PRINT(decimal_point
, 1);
1200 } else if (expt
>= ndig
) {
1202 PAD(expt
- ndig
, zeroes
);
1209 PRINT(cp
, ndig
-expt
);
1212 #endif /* __SPE__ */
1214 } else { /* glue together f_p fragments */
1215 if (ch
>= 'f') { /* 'f' or 'g' */
1216 if (_fpvalue
== 0) {
1217 /* kludge for __dtoa irregularity */
1219 if (expt
< ndig
|| (flags
& ALT
) != 0) {
1220 PRINT(decimal_point
, 1);
1221 PAD(ndig
- 1, zeroes
);
1223 } else if (expt
<= 0) {
1226 PRINT(decimal_point
, 1);
1230 } else if (expt
>= ndig
) {
1232 PAD(expt
- ndig
, zeroes
);
1239 PRINT(cp
, ndig
-expt
);
1241 } else { /* 'e' or 'E' */
1242 if (ndig
> 1 || flags
& ALT
) {
1248 } else /* 0.[0..] */
1249 /* __dtoa irregularity */
1250 PAD(ndig
- 1, zeroes
);
1253 PRINT(expstr
, expsize
);
1259 /* left-adjusting padding (always blank) */
1260 if (flags
& LADJUST
)
1261 PAD(width
- realsz
, blanks
);
1263 /* finally, adjust ret */
1264 ret
+= width
> realsz
? width
: realsz
;
1267 if ((flags
& VECTOR
) && vec_print_count
-- > 1)
1269 /* add vector separator */
1270 if (ch
!= 'c' || vec_sep
!= ' ')
1280 #endif /* __ALTIVEC__ */
1281 FLUSH(); /* copy out the I/O vectors */
1286 return (__sferror(fp
) ? EOF
: ret
);
1290 #ifdef FLOATING_POINT
1293 extern char *_dtoa_r
_PARAMS((struct _reent
*, double, int,
1294 int, int *, int *, char **));
1296 extern char *_ldtoa_r
_PARAMS((struct _reent
*, _LONG_DOUBLE
, int,
1297 int, int *, int *, char **));
1299 #define word0(x) ldword0(x)
1303 cvt(data
, value
, ndigits
, flags
, sign
, decpt
, ch
, length
)
1304 struct _reent
*data
;
1310 int ndigits
, flags
, *decpt
, ch
, *length
;
1314 char *digits
, *bp
, *rve
;
1316 union double_union tmp
;
1318 struct ldieee
*ldptr
;
1322 mode
= 3; /* ndigits after the decimal point */
1324 /* To obtain ndigits after the decimal point for the 'e'
1325 * and 'E' formats, round to ndigits + 1 significant
1328 if (ch
== 'e' || ch
== 'E') {
1331 mode
= 2; /* ndigits significant digits */
1337 if (word0(tmp
) & Sign_bit
) { /* this will check for < 0 and -0.0 */
1343 digits
= _dtoa_r(data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1344 #else /* !_NO_LONGDBL */
1345 ldptr
= (struct ldieee
*)&value
;
1346 if (ldptr
->sign
) { /* this will check for < 0 and -0.0 */
1352 digits
= _ldtoa_r(data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1353 #endif /* !_NO_LONGDBL */
1355 if ((ch
!= 'g' && ch
!= 'G') || flags
& ALT
) { /* Print trailing zeros */
1356 bp
= digits
+ ndigits
;
1358 if (*digits
== '0' && value
)
1359 *decpt
= -ndigits
+ 1;
1362 if (value
== 0) /* kludge for __dtoa irregularity */
1367 *length
= rve
- digits
;
1372 exponent(p0
, exp
, fmtch
)
1376 register char *p
, *t
;
1390 *--t
= to_char(exp
% 10);
1391 } while ((exp
/= 10) > 9);
1392 *--t
= to_char(exp
);
1393 for (; t
< expbuf
+ 40; *p
++ = *t
++);
1397 *p
++ = to_char(exp
);
1401 #endif /* FLOATING_POINT */
1404 extern char *_ufix64toa_r
_PARAMS((struct _reent
*, unsigned long long, int,
1405 int, int *, int *, char **));
1407 cvt_ufix64 (data
, value
, ndigits
, decpt
, length
)
1408 struct _reent
*data
;
1409 unsigned long long value
;
1410 int ndigits
, *decpt
, *length
;
1413 char *digits
, *bp
, *rve
;
1415 /* treat the same as %f format and use mode=3 */
1416 digits
= _ufix64toa_r (data
, value
, 3, ndigits
, decpt
, &dsgn
, &rve
);
1418 /* print trailing zeroes */
1419 bp
= digits
+ ndigits
;
1420 if (*digits
== '0' && value
)
1421 *decpt
= -ndigits
+ 1;
1423 if (value
== 0) /* kludge for __dtoa irregularity */
1427 *length
= rve
- digits
;
1430 #endif /* __SPE__ */