fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / machine / powerpc / vfprintf.c
blobb5168122d765af4b41b8966fc988b7572f62e529
1 /*
2 FUNCTION
3 <<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
5 INDEX
6 vprintf
7 INDEX
8 vfprintf
9 INDEX
10 vsprintf
11 INDEX
12 vsnprintf
14 ANSI_SYNOPSIS
15 #include <stdio.h>
16 #include <stdarg.h>
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]>,
23 va_list <[list]>);
24 int _vfprintf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
25 va_list <[list]>);
26 int _vsprintf_r(void *<[reent]>, char *<[str]>, const char *<[fmt]>,
27 va_list <[list]>);
28 int _vsnprintf_r(void *<[reent]>, char *<[str]>, size_t <[size]>, const char *<[fmt]>,
29 va_list <[list]>);
31 TRAD_SYNOPSIS
32 #include <stdio.h>
33 #include <varargs.h>
34 int vprintf( <[fmt]>, <[list]>)
35 char *<[fmt]>;
36 va_list <[list]>;
38 int vfprintf(<[fp]>, <[fmt]>, <[list]>)
39 FILE *<[fp]>;
40 char *<[fmt]>;
41 va_list <[list]>;
43 int vsprintf(<[str]>, <[fmt]>, <[list]>)
44 char *<[str]>;
45 char *<[fmt]>;
46 va_list <[list]>;
48 int vsnprintf(<[str]>, <[size]>, <[fmt]>, <[list]>)
49 char *<[str]>;
50 size_t <[size]>;
51 char *<[fmt]>;
52 va_list <[list]>;
54 int _vprintf_r(<[reent]>, <[fmt]>, <[list]>)
55 char *<[reent]>;
56 char *<[fmt]>;
57 va_list <[list]>;
59 int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
60 char *<[reent]>;
61 FILE *<[fp]>;
62 char *<[fmt]>;
63 va_list <[list]>;
65 int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
66 char *<[reent]>;
67 char *<[str]>;
68 char *<[fmt]>;
69 va_list <[list]>;
71 int _vsnprintf_r(<[reent]>, <[str]>, <[size]>, <[fmt]>, <[list]>)
72 char *<[reent]>;
73 char *<[str]>;
74 size_t <[size]>;
75 char *<[fmt]>;
76 va_list <[list]>;
78 DESCRIPTION
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.
85 RETURNS
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>>.
93 PORTABILITY
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
105 * Chris Torek.
107 * Redistribution and use in source and binary forms, with or without
108 * modification, are permitted provided that the following conditions
109 * are met:
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
133 * SUCH DAMAGE.
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...
147 #ifdef INTEGER_ONLY
148 #define VFPRINTF vfiprintf
149 #define _VFPRINTF_R _vfiprintf_r
150 #else
151 #define VFPRINTF vfprintf
152 #define _VFPRINTF_R _vfprintf_r
153 #ifndef NO_FLOATING_POINT
154 #define FLOATING_POINT
155 #endif
156 #endif
158 #define _NO_LONGLONG
159 #if defined WANT_PRINTF_LONG_LONG && defined __GNUC__
160 # undef _NO_LONGLONG
161 #endif
163 #include <_ansi.h>
164 #include <limits.h>
165 #include <stdio.h>
166 #include <stdlib.h>
167 #include <string.h>
168 #include <reent.h>
169 #include <wchar.h>
170 #include <string.h>
171 #ifdef __ALTIVEC__
172 #include <altivec.h>
173 #endif
175 #ifdef _HAVE_STDC
176 #include <stdarg.h>
177 #else
178 #include <varargs.h>
179 #endif
181 #include "local.h"
182 #include "fvwrite.h"
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. */
188 #define _NO_LONGDBL
189 #if defined WANT_IO_LONG_DBL && (LDBL_MANT_DIG > DBL_MANT_DIG)
190 #undef _NO_LONGDBL
191 #endif
193 #ifdef __ALTIVEC__
194 typedef union
196 vector int v;
197 float f[4];
198 int i[16 / sizeof(int)];
199 long l[4];
200 short s[8];
201 signed char c[16];
202 } vec_16_byte_union;
203 #endif /* __ALTIVEC__ */
206 * Flush out all the vectors defined by the given uio,
207 * then reset it so that it can be reused.
209 static int
210 __sprint(fp, uio)
211 FILE *fp;
212 register struct __suio *uio;
214 register int err;
216 if (uio->uio_resid == 0) {
217 uio->uio_iovcnt = 0;
218 return (0);
220 err = __sfvwrite(fp, uio);
221 uio->uio_resid = 0;
222 uio->uio_iovcnt = 0;
223 return (err);
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.
231 static int
232 __sbprintf(fp, fmt, ap)
233 register FILE *fp;
234 const char *fmt;
235 va_list ap;
237 int ret;
238 FILE fake;
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))
256 ret = EOF;
257 if (fake._flags & __SERR)
258 fp->_flags |= __SERR;
259 return (ret);
263 #ifdef FLOATING_POINT
264 #include <locale.h>
265 #include <math.h>
266 #include "floatio.h"
268 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
269 #define DEFPREC 6
271 #ifdef _NO_LONGDBL
272 static char *cvt _PARAMS((struct _reent *, double, int, int, char *, int *, int, int *));
273 #else
274 static char *cvt _PARAMS((struct _reent *, _LONG_DOUBLE, int, int, char *, int *, int, int *));
275 extern int _ldcheck _PARAMS((_LONG_DOUBLE *));
276 #endif
278 static int exponent _PARAMS((char *, int, int));
280 #ifdef __SPE__
281 static char *cvt_ufix64 _PARAMS((struct _reent *, unsigned long long, int, int *, int *));
282 #endif /* __SPE__ */
284 #else /* no FLOATING_POINT */
286 #define BUF 40
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 */
306 #ifndef _NO_LONGLONG
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
312 #endif
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 */
319 int
320 _DEFUN (VFPRINTF, (fp, fmt0, ap),
321 FILE * fp _AND
322 _CONST char *fmt0 _AND
323 va_list ap)
325 CHECK_INIT (fp);
326 return _VFPRINTF_R (fp->_data, fp, fmt0, ap);
329 int
330 _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap),
331 struct _reent *data _AND
332 FILE * fp _AND
333 _CONST char *fmt0 _AND
334 va_list ap)
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 */
349 wchar_t wc;
350 #ifdef FLOATING_POINT
351 char *decimal_point = localeconv()->decimal_point;
352 char softsign; /* temporary negative sign for floats */
353 #ifdef _NO_LONGDBL
354 union { int i; double d; } _double_ = {0};
355 #define _fpvalue (_double_.d)
356 #else
357 union { int i; _LONG_DOUBLE ld; } _long_double_ = {0};
358 #define _fpvalue (_long_double_.ld)
359 int tmp;
360 #endif
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 */
365 #endif
367 #ifndef _NO_LONGLONG
368 #define quad_t long long
369 #define u_quad_t unsigned long long
370 #endif
372 #ifndef _NO_LONGLONG
373 u_quad_t _uquad; /* integer arguments %[diouxX] */
374 #else
375 u_long _uquad;
376 #endif
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 */
382 #define NIOV 8
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 */
387 #ifdef __ALTIVEC__
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
397 * below longer.
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); \
412 iovp++; \
413 if (++uio.uio_iovcnt >= NIOV) { \
414 if (__sprint(fp, &uio)) \
415 goto error; \
416 iovp = iov; \
419 #define PAD(howmany, with) { \
420 if ((n = (howmany)) > 0) { \
421 while (n > PADSIZE) { \
422 PRINT(with, PADSIZE); \
423 n -= PADSIZE; \
425 PRINT(with, n); \
428 #define FLUSH() { \
429 if (uio.uio_resid && __sprint(fp, &uio)) \
430 goto error; \
431 uio.uio_iovcnt = 0; \
432 iovp = iov; \
435 #ifdef __ALTIVEC__
436 #define GET_SHORT(ap) \
437 (flags&VECTOR ? \
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) \
442 (flags&VECTOR ? \
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) \
448 (flags&VECTOR ? \
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) \
453 (flags&VECTOR ? \
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) \
459 (flags&VECTOR ? \
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])) : \
463 va_arg(ap, int))
464 #define GET_UINT(ap) \
465 (flags&VECTOR ? \
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__ */
479 #ifndef _NO_LONGLONG
480 #define SARG() \
481 (flags&QUADINT ? va_arg(ap, quad_t) : \
482 flags&LONGINT ? GET_LONG(ap) : \
483 flags&SHORTINT ? (long)GET_SHORT(ap) : \
484 (long)GET_INT(ap))
485 #define UARG() \
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))
490 #ifdef __SPE__
491 #define SFPARG() \
492 (flags&LONGINT ? va_arg(ap, quad_t) : \
493 flags&SHORTINT ? (long)GET_SHORT(ap) : \
494 (long)va_arg(ap, int))
495 #define UFPARG() \
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))
499 #endif /* __SPE__ */
500 #else
501 #define SARG() \
502 (flags&LONGINT ? GET_LONG(ap) : \
503 flags&SHORTINT ? (long)GET_SHORT(ap) : \
504 (long)GET_INT(ap))
505 #define UARG() \
506 (flags&LONGINT ? GET_ULONG(ap) : \
507 flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
508 (u_long)GET_UINT(ap))
509 #ifdef __SPE__
510 #define SFPARG() \
511 (flags&LONGINT ? (va_arg(ap, long) << 32) : \
512 flags&SHORTINT ? (long)GET_SHORT(ap) : \
513 (long)va_arg(ap, int))
514 #define UFPARG() \
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))
518 #endif /* __SPE__ */
519 #endif
521 memset (&state, '\0', sizeof (state));
523 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
524 if (cantwrite(fp))
525 return (EOF);
527 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
528 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
529 fp->_file >= 0)
530 return (__sbprintf(fp, fmt0, ap));
532 fmt = (char *)fmt0;
533 uio.uio_iov = iovp = iov;
534 uio.uio_resid = 0;
535 uio.uio_iovcnt = 0;
536 ret = 0;
539 * Scan the format for conversions (`%' character).
541 for (;;) {
542 cp = fmt;
543 while ((n = _mbtowc_r(_REENT, &wc, fmt, MB_CUR_MAX, &state)) > 0) {
544 fmt += n;
545 if (wc == '%') {
546 fmt--;
547 break;
550 if ((m = fmt - cp) != 0) {
551 PRINT(cp, m);
552 ret += m;
554 if (n <= 0)
555 goto done;
556 fmt++; /* skip over '%' */
558 flags = 0;
559 dprec = 0;
560 width = 0;
561 prec = -1;
562 sign = '\0';
563 old_sign = '\0';
564 #ifdef __ALTIVEC__
565 vec_print_count = 0;
566 vec_sep = ' ';
567 #endif /* __ALTIVEC__ */
569 format_anchor = fmt;
570 rflag: ch = *fmt++;
571 old_ch = ch;
572 reswitch: switch (ch) {
573 case ' ':
575 * ``If the space and + flags both appear, the space
576 * flag will be ignored.''
577 * -- ANSI X3J11
579 if (!sign)
580 sign = ' ';
581 goto rflag;
582 case '#':
583 flags |= ALT;
584 goto rflag;
585 case '*':
587 * ``A negative field width argument is taken as a
588 * - flag followed by a positive field width.''
589 * -- ANSI X3J11
590 * They don't exclude field widths read from args.
592 if ((width = va_arg(ap, int)) >= 0)
593 goto rflag;
594 width = -width;
595 /* FALLTHROUGH */
596 case '-':
597 flags |= LADJUST;
598 goto rflag;
599 case '+':
600 sign = '+';
601 goto rflag;
602 #ifdef __ALTIVEC__
603 case ',':
604 case ';':
605 case ':':
606 case '_':
607 if (vec_sep != ' ')
609 fmt = format_anchor;
610 continue;
612 vec_sep = ch;
613 goto rflag;
614 #endif /* __ALTIVEC__ */
615 case '.':
616 if ((ch = *fmt++) == '*') {
617 n = va_arg(ap, int);
618 prec = n < 0 ? -1 : n;
619 goto rflag;
621 n = 0;
622 while (is_digit(ch)) {
623 n = 10 * n + to_digit(ch);
624 ch = *fmt++;
626 prec = n < 0 ? -1 : n;
627 goto reswitch;
628 case '0':
630 * ``Note that 0 is taken as a flag, not as the
631 * beginning of a field width.''
632 * -- ANSI X3J11
634 flags |= ZEROPAD;
635 goto rflag;
636 case '1': case '2': case '3': case '4':
637 case '5': case '6': case '7': case '8': case '9':
638 n = 0;
639 do {
640 n = 10 * n + to_digit(ch);
641 ch = *fmt++;
642 } while (is_digit(ch));
643 width = n;
644 goto reswitch;
645 #ifdef FLOATING_POINT
646 case 'L':
647 #ifdef __ALTIVEC__
648 if (flags & VECTOR)
650 fmt = format_anchor;
651 continue;
653 #endif /* __ALTIVEC__ */
654 flags |= LONGDBL;
655 goto rflag;
656 #endif
657 case 'h':
658 if (flags & LONGINT)
660 fmt = format_anchor;
661 continue;
663 flags |= SHORTINT;
664 #ifdef __ALTIVEC__
665 if (flags & VECTOR)
666 vec_print_count = 8;
667 #endif
668 goto rflag;
669 case 'l':
670 if (flags & SHORTINT)
672 fmt = format_anchor;
673 continue;
675 if (*fmt == 'l') {
676 fmt++;
677 flags |= QUADINT;
678 flags &= ~VECTOR;
679 } else {
680 flags |= LONGINT;
681 #ifdef __ALTIVEC__
682 if (flags & VECTOR)
683 vec_print_count = 4;
684 #endif
686 goto rflag;
687 #ifdef __ALTIVEC__
688 case 'v':
689 if (flags & VECTOR)
691 fmt = format_anchor;
692 continue;
694 flags |= VECTOR;
695 vec_print_count = (flags & SHORTINT) ? 8 :
696 ((flags & LONGINT) ? 4 : 16);
697 goto rflag;
698 #endif
699 case 'q':
700 #ifdef __ALTIVEC__
701 if (flags & VECTOR)
703 fmt = format_anchor;
704 continue;
706 #endif /* __ALTIVEC__ */
707 flags |= QUADINT;
708 goto rflag;
709 case 'c':
710 #ifdef __ALTIVEC__
711 if (flags & VECTOR)
713 int k;
714 vec_16_byte_union tmp;
715 if (flags & (SHORTINT | LONGINT))
717 fmt = format_anchor;
718 continue;
720 tmp.v = va_arg(ap, vector int);
721 cp = buf;
722 for (k = 0; k < 15; ++k)
724 *cp++ = tmp.c[k];
725 if (vec_sep != ' ')
726 *cp++ = vec_sep;
728 *cp++ = tmp.c[15];
729 size = cp - buf;
730 cp = buf;
731 vec_print_count = 0;
733 else
734 #endif /* __ALTIVEC__ */
736 *(cp = buf) = va_arg(ap, int);
737 size = 1;
739 sign = '\0';
740 break;
741 case 'D':
742 flags |= LONGINT;
743 /*FALLTHROUGH*/
744 case 'd':
745 case 'i':
746 #ifdef __ALTIVEC__
747 if (!(flags & VECTOR) && vec_sep != ' ')
749 fmt = format_anchor;
750 continue;
752 #endif /* __ALTIVEC__ */
753 _uquad = SARG();
754 #ifndef _NO_LONGLONG
755 if ((quad_t)_uquad < 0)
756 #else
757 if ((long) _uquad < 0)
758 #endif
761 _uquad = -_uquad;
762 old_sign = sign;
763 sign = '-';
765 base = DEC;
766 goto number;
767 #ifdef FLOATING_POINT
768 case 'e':
769 case 'E':
770 case 'f':
771 case 'g':
772 case 'G':
773 if (prec == -1) {
774 prec = DEFPREC;
775 } else if ((ch == 'g' || ch == 'G') && prec == 0) {
776 prec = 1;
779 #ifdef _NO_LONGDBL
780 if (flags & LONGDBL) {
781 _fpvalue = (double) va_arg(ap, _LONG_DOUBLE);
782 #ifdef __ALTIVEC__
783 } else if (flags & VECTOR) {
784 if (vec_print_count >= 4)
786 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 != ' ') {
791 fmt = format_anchor;
792 continue;
794 #endif /* __ALTIVEC__ */
795 } else {
796 _fpvalue = va_arg(ap, double);
799 /* do this before tricky precision changes */
800 if (isinf(_fpvalue)) {
801 if (_fpvalue < 0)
803 old_sign = sign;
804 sign = '-';
807 cp = "Inf";
808 size = 3;
809 break;
811 if (isnan(_fpvalue)) {
812 cp = "NaN";
813 size = 3;
814 break;
817 #else /* !_NO_LONGDBL */
819 if (flags & LONGDBL) {
820 _fpvalue = va_arg(ap, _LONG_DOUBLE);
821 #ifdef __ALTIVEC__
822 } else if (flags & VECTOR) {
823 if (vec_print_count >= 4)
825 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__ */
830 } else {
831 _fpvalue = (_LONG_DOUBLE)va_arg(ap, double);
834 /* do this before tricky precision changes */
835 tmp = _ldcheck (&_fpvalue);
836 if (tmp == 2) {
837 if (_fpvalue < 0)
839 old_sign = sign;
840 sign = '-';
842 cp = "Inf";
843 size = 3;
844 break;
846 if (tmp == 1) {
847 cp = "NaN";
848 size = 3;
849 break;
851 #endif /* !_NO_LONGDBL */
853 flags |= FPT;
855 cp = cvt(data, _fpvalue, prec, flags, &softsign,
856 &expt, ch, &ndig);
858 if (ch == 'g' || ch == 'G') {
859 if (expt <= -4 || expt > prec)
861 old_ch = ch;
862 ch = (ch == 'g') ? 'e' : 'E';
864 else
865 ch = 'g';
867 if (ch <= 'e') { /* 'e' or 'E' fmt */
868 --expt;
869 expsize = exponent(expstr, expt, ch);
870 size = expsize + ndig;
871 if (ndig > 1 || flags & ALT)
872 ++size;
873 } else if (ch == 'f') { /* f fmt */
874 if (expt > 0) {
875 size = expt;
876 if (prec || flags & ALT)
877 size += prec + 1;
878 } else /* "0.X" */
879 size = prec + 2;
880 } else if (expt >= ndig) { /* fixed g fmt */
881 size = expt;
882 if (flags & ALT)
883 ++size;
884 } else
885 size = ndig + (expt > 0 ?
886 1 : 2 - expt);
888 if (softsign)
890 old_sign = sign;
891 sign = '-';
893 break;
894 #endif /* FLOATING_POINT */
895 #ifdef __SPE__
896 case 'r':
897 flags |= FIXEDPOINT;
898 _uquad = SFPARG();
899 if ((quad_t)_uquad < 0)
901 sign = '-';
902 _uquad = -(quad_t)_uquad;
904 if (flags & SHORTINT)
905 _uquad <<= 49;
906 else if (flags & LONGINT)
907 _uquad <<= 1;
908 else
909 _uquad <<= 33;
911 if (_uquad == 0 && sign)
913 /* we have -1.0 which has to be handled special */
914 cp = "100000";
915 expt = 1;
916 ndig = 6;
917 break;
920 goto fixed_nosign;
921 case 'R':
922 flags |= FIXEDPOINT;
923 _uquad = UFPARG();
924 if (flags & SHORTINT)
925 _uquad <<= 48;
926 else if (!(flags & LONGINT))
927 _uquad <<= 32;
929 fixed_nosign:
930 if (prec == -1)
931 prec = DEFPREC;
933 cp = cvt_ufix64 (data, _uquad, prec, &expt, &ndig);
935 /* act like %f of format "0.X" */
936 size = prec + 2;
938 break;
939 #endif /* __SPE__ */
940 case 'n':
941 #ifdef __ALTIVEC__
942 if (flags & VECTOR)
944 fmt = format_anchor;
945 continue;
947 #endif /* __ALTIVEC__ */
948 #ifndef _NO_LONGLONG
949 if (flags & QUADINT)
950 *va_arg(ap, quad_t *) = ret;
951 else
952 #endif
953 if (flags & LONGINT)
954 *va_arg(ap, long *) = ret;
955 else if (flags & SHORTINT)
956 *va_arg(ap, short *) = ret;
957 else
958 *va_arg(ap, int *) = ret;
959 continue; /* no output */
960 case 'O':
961 flags |= LONGINT;
962 /*FALLTHROUGH*/
963 case 'o':
964 #ifdef __ALTIVEC__
965 if (!(flags & VECTOR) && vec_sep != ' ')
967 fmt = format_anchor;
968 continue;
970 #endif /* __ALTIVEC__ */
971 _uquad = UARG();
972 base = OCT;
973 goto nosign;
974 case 'p':
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-
979 * defined manner.''
980 * -- ANSI X3J11
982 /* NOSTRICT */
983 #ifdef __ALTIVEC__
984 if (flags & VECTOR)
985 _uquad = UARG();
986 else if (vec_sep != ' ')
988 fmt = format_anchor;
989 continue;
991 else
992 #endif /* __ALTIVEC__ */
993 _uquad = (u_long)(unsigned _POINTER_INT)va_arg(ap, void *);
994 base = HEX;
995 xdigs = "0123456789abcdef";
996 flags |= HEXPREFIX;
997 ch = 'x';
998 goto nosign;
999 case 's':
1000 #ifdef __ALTIVEC__
1001 if (flags & VECTOR)
1003 fmt = format_anchor;
1004 continue;
1006 #endif /* __ALTIVEC__ */
1007 if ((cp = va_arg(ap, char *)) == NULL)
1008 cp = "(null)";
1009 if (prec >= 0) {
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);
1017 if (p != NULL) {
1018 size = p - cp;
1019 if (size > prec)
1020 size = prec;
1021 } else
1022 size = prec;
1023 } else
1024 size = strlen(cp);
1025 sign = '\0';
1026 break;
1027 case 'U':
1028 flags |= LONGINT;
1029 /*FALLTHROUGH*/
1030 case 'u':
1031 #ifdef __ALTIVEC__
1032 if (!(flags & VECTOR) && vec_sep != ' ')
1034 fmt = format_anchor;
1035 continue;
1037 #endif /* __ALTIVEC__ */
1038 _uquad = UARG();
1039 base = DEC;
1040 goto nosign;
1041 case 'X':
1042 xdigs = "0123456789ABCDEF";
1043 goto hex;
1044 case 'x':
1045 xdigs = "0123456789abcdef";
1046 #ifdef __ALTIVEC__
1047 if (!(flags & VECTOR) && vec_sep != ' ')
1049 fmt = format_anchor;
1050 continue;
1052 #endif /* __ALTIVEC__ */
1053 hex: _uquad = UARG();
1054 base = HEX;
1055 /* leading 0x/X only if non-zero */
1056 if (flags & ALT && _uquad != 0)
1057 flags |= HEXPREFIX;
1059 /* unsigned conversions */
1060 nosign: sign = '\0';
1062 * ``... diouXx conversions ... if a precision is
1063 * specified, the 0 flag will be ignored.''
1064 * -- ANSI X3J11
1066 number: if ((dprec = prec) >= 0)
1067 flags &= ~ZEROPAD;
1070 * ``The result of converting a zero value with an
1071 * explicit precision of zero is no characters.''
1072 * -- ANSI X3J11
1074 cp = buf + BUF;
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.
1081 switch (base) {
1082 case OCT:
1083 do {
1084 *--cp = to_char(_uquad & 7);
1085 _uquad >>= 3;
1086 } while (_uquad);
1087 /* handle octal leading 0 */
1088 if (flags & ALT && *cp != '0')
1089 *--cp = '0';
1090 break;
1092 case DEC:
1093 /* many numbers are 1 digit */
1094 while (_uquad >= 10) {
1095 *--cp = to_char(_uquad % 10);
1096 _uquad /= 10;
1098 *--cp = to_char(_uquad);
1099 break;
1101 case HEX:
1102 do {
1103 *--cp = xdigs[_uquad & 15];
1104 _uquad >>= 4;
1105 } while (_uquad);
1106 break;
1108 default:
1109 cp = "bug in vfprintf: bad base";
1110 size = strlen(cp);
1111 goto skipsize;
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."
1118 * -- ANSI X3J11
1120 * To demonstrate this case, compile and run:
1121 * printf ("%#.0o",0);
1123 else if (base == OCT && (flags & ALT))
1124 *--cp = '0';
1126 size = buf + BUF - cp;
1127 skipsize:
1128 break;
1129 default: /* "%?" prints ?, unless ? is NUL */
1130 flags &= ~VECTOR;
1131 if (ch == '\0')
1132 goto done;
1133 /* pretend it was %c with argument ch */
1134 cp = buf;
1135 *cp = ch;
1136 size = 1;
1137 sign = '\0';
1138 break;
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;
1156 if (sign)
1157 realsz++;
1158 else if (flags & HEXPREFIX)
1159 realsz+= 2;
1161 /* right-adjusting blank padding */
1162 if ((flags & (LADJUST|ZEROPAD)) == 0)
1163 PAD(width - realsz, blanks);
1165 /* prefix */
1166 if (sign) {
1167 PRINT(&sign, 1);
1168 } else if (flags & HEXPREFIX) {
1169 ox[0] = '0';
1170 ox[1] = ch;
1171 PRINT(ox, 2);
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) {
1184 #ifdef __SPE__
1185 if (flags & FIXEDPOINT) {
1186 if (_uquad == 0 && !sign) {
1187 /* kludge for __dtoa irregularity */
1188 PRINT("0", 1);
1189 if (expt < ndig || (flags & ALT) != 0) {
1190 PRINT(decimal_point, 1);
1191 PAD(ndig - 1, zeroes);
1193 } else if (expt <= 0) {
1194 PRINT("0", 1);
1195 if(expt || ndig) {
1196 PRINT(decimal_point, 1);
1197 PAD(-expt, zeroes);
1198 PRINT(cp, ndig);
1200 } else if (expt >= ndig) {
1201 PRINT(cp, ndig);
1202 PAD(expt - ndig, zeroes);
1203 if (flags & ALT)
1204 PRINT(".", 1);
1205 } else {
1206 PRINT(cp, expt);
1207 cp += expt;
1208 PRINT(".", 1);
1209 PRINT(cp, ndig-expt);
1211 } else
1212 #endif /* __SPE__ */
1213 PRINT(cp, size);
1214 } else { /* glue together f_p fragments */
1215 if (ch >= 'f') { /* 'f' or 'g' */
1216 if (_fpvalue == 0) {
1217 /* kludge for __dtoa irregularity */
1218 PRINT("0", 1);
1219 if (expt < ndig || (flags & ALT) != 0) {
1220 PRINT(decimal_point, 1);
1221 PAD(ndig - 1, zeroes);
1223 } else if (expt <= 0) {
1224 PRINT("0", 1);
1225 if(expt || ndig) {
1226 PRINT(decimal_point, 1);
1227 PAD(-expt, zeroes);
1228 PRINT(cp, ndig);
1230 } else if (expt >= ndig) {
1231 PRINT(cp, ndig);
1232 PAD(expt - ndig, zeroes);
1233 if (flags & ALT)
1234 PRINT(".", 1);
1235 } else {
1236 PRINT(cp, expt);
1237 cp += expt;
1238 PRINT(".", 1);
1239 PRINT(cp, ndig-expt);
1241 } else { /* 'e' or 'E' */
1242 if (ndig > 1 || flags & ALT) {
1243 ox[0] = *cp++;
1244 ox[1] = '.';
1245 PRINT(ox, 2);
1246 if (_fpvalue) {
1247 PRINT(cp, ndig-1);
1248 } else /* 0.[0..] */
1249 /* __dtoa irregularity */
1250 PAD(ndig - 1, zeroes);
1251 } else /* XeYYY */
1252 PRINT(cp, 1);
1253 PRINT(expstr, expsize);
1256 #else
1257 PRINT(cp, size);
1258 #endif
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;
1266 #ifdef __ALTIVEC__
1267 if ((flags & VECTOR) && vec_print_count-- > 1)
1269 /* add vector separator */
1270 if (ch != 'c' || vec_sep != ' ')
1272 PRINT(&vec_sep, 1);
1273 ret += 1;
1275 FLUSH();
1276 sign = old_sign;
1277 ch = old_ch;
1278 goto reswitch;
1280 #endif /* __ALTIVEC__ */
1281 FLUSH(); /* copy out the I/O vectors */
1283 done:
1284 FLUSH();
1285 error:
1286 return (__sferror(fp) ? EOF : ret);
1287 /* NOTREACHED */
1290 #ifdef FLOATING_POINT
1292 #ifdef _NO_LONGDBL
1293 extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
1294 int, int *, int *, char **));
1295 #else
1296 extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
1297 int, int *, int *, char **));
1298 #undef word0
1299 #define word0(x) ldword0(x)
1300 #endif
1302 static char *
1303 cvt(data, value, ndigits, flags, sign, decpt, ch, length)
1304 struct _reent *data;
1305 #ifdef _NO_LONGDBL
1306 double value;
1307 #else
1308 _LONG_DOUBLE value;
1309 #endif
1310 int ndigits, flags, *decpt, ch, *length;
1311 char *sign;
1313 int mode, dsgn;
1314 char *digits, *bp, *rve;
1315 #ifdef _NO_LONGDBL
1316 union double_union tmp;
1317 #else
1318 struct ldieee *ldptr;
1319 #endif
1321 if (ch == 'f') {
1322 mode = 3; /* ndigits after the decimal point */
1323 } else {
1324 /* To obtain ndigits after the decimal point for the 'e'
1325 * and 'E' formats, round to ndigits + 1 significant
1326 * figures.
1328 if (ch == 'e' || ch == 'E') {
1329 ndigits++;
1331 mode = 2; /* ndigits significant digits */
1334 #ifdef _NO_LONGDBL
1335 tmp.d = value;
1337 if (word0(tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1338 value = -value;
1339 *sign = '-';
1340 } else
1341 *sign = '\000';
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 */
1347 value = -value;
1348 *sign = '-';
1349 } else
1350 *sign = '\000';
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;
1357 if (ch == 'f') {
1358 if (*digits == '0' && value)
1359 *decpt = -ndigits + 1;
1360 bp += *decpt;
1362 if (value == 0) /* kludge for __dtoa irregularity */
1363 rve = bp;
1364 while (rve < bp)
1365 *rve++ = '0';
1367 *length = rve - digits;
1368 return (digits);
1371 static int
1372 exponent(p0, exp, fmtch)
1373 char *p0;
1374 int exp, fmtch;
1376 register char *p, *t;
1377 char expbuf[40];
1379 p = p0;
1380 *p++ = fmtch;
1381 if (exp < 0) {
1382 exp = -exp;
1383 *p++ = '-';
1385 else
1386 *p++ = '+';
1387 t = expbuf + 40;
1388 if (exp > 9) {
1389 do {
1390 *--t = to_char(exp % 10);
1391 } while ((exp /= 10) > 9);
1392 *--t = to_char(exp);
1393 for (; t < expbuf + 40; *p++ = *t++);
1395 else {
1396 *p++ = '0';
1397 *p++ = to_char(exp);
1399 return (p - p0);
1401 #endif /* FLOATING_POINT */
1403 #ifdef __SPE__
1404 extern char *_ufix64toa_r _PARAMS((struct _reent *, unsigned long long, int,
1405 int, int *, int *, char **));
1406 static char *
1407 cvt_ufix64 (data, value, ndigits, decpt, length)
1408 struct _reent *data;
1409 unsigned long long value;
1410 int ndigits, *decpt, *length;
1412 int dsgn;
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;
1422 bp += *decpt;
1423 if (value == 0) /* kludge for __dtoa irregularity */
1424 rve = bp;
1425 while (rve < bp)
1426 *rve++ = '0';
1427 *length = rve - digits;
1428 return (digits);
1430 #endif /* __SPE__ */