source: trunk/libs/newlib/src/newlib/libc/machine/powerpc/vfprintf.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 33.8 KB
Line 
1/*
2FUNCTION
3<<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
4
5INDEX
6        vprintf
7INDEX
8        vfprintf
9INDEX
10        vsprintf
11INDEX
12        vsnprintf
13
14SYNOPSIS
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]>);
21
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]>);
30
31DESCRIPTION
32<<vprintf>>, <<vfprintf>>, <<vsprintf>> and <<vsnprintf>> are (respectively)
33variants of <<printf>>, <<fprintf>>, <<sprintf>> and <<snprintf>>.  They differ
34only in allowing their caller to pass the variable argument list as a
35<<va_list>> object (initialized by <<va_start>>) rather than directly
36accepting a variable number of arguments.
37
38RETURNS
39The return values are consistent with the corresponding functions:
40<<vsprintf>> returns the number of bytes in the output string,
41save that the concluding <<NULL>> is not counted.
42<<vprintf>> and <<vfprintf>> return the number of characters transmitted.
43If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>>. No
44error returns occur for <<vsprintf>>.
45
46PORTABILITY
47ANSI C requires all three functions.
48
49Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
50<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
51*/
52
53/*-
54 * Copyright (c) 1990 The Regents of the University of California.
55 * All rights reserved.
56 *
57 * This code is derived from software contributed to Berkeley by
58 * Chris Torek.
59 *
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
62 * are met:
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. All advertising materials mentioning features or use of this software
69 *    must display the following acknowledgement:
70 *      This product includes software developed by the University of
71 *      California, Berkeley and its contributors.
72 * 4. Neither the name of the University nor the names of its contributors
73 *    may be used to endorse or promote products derived from this software
74 *    without specific prior written permission.
75 *
76 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
79 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 * SUCH DAMAGE.
87 */
88
89#if defined(LIBC_SCCS) && !defined(lint)
90/*static char *sccsid = "from: @(#)vfprintf.c   5.50 (Berkeley) 12/16/92";*/
91static char *rcsid = "$Id$";
92#endif /* LIBC_SCCS and not lint */
93
94/*
95 * Actual printf innards.
96 *
97 * This code is large and complicated...
98 */
99
100#ifdef INTEGER_ONLY
101#define VFPRINTF vfiprintf
102#define _VFPRINTF_R _vfiprintf_r
103#else
104#define VFPRINTF vfprintf
105#define _VFPRINTF_R _vfprintf_r
106#ifndef NO_FLOATING_POINT
107#define FLOATING_POINT
108#endif
109#endif
110
111#include <_ansi.h>
112#include <limits.h>
113#include <stdio.h>
114#include <stdlib.h>
115#include <string.h>
116#include <reent.h>
117#include <wchar.h>
118#include <string.h>
119#ifdef __ALTIVEC__
120#include <altivec.h>
121#endif
122
123#include <stdarg.h>
124
125#include "local.h"
126#include "fvwrite.h"
127#include "vfieeefp.h"
128
129/* Currently a test is made to see if long double processing is warranted.
130   This could be changed in the future should the _ldtoa_r code be
131   preferred over _dtoa_r.  */
132#define _NO_LONGDBL
133#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
134#undef _NO_LONGDBL
135#endif
136
137#define _NO_LONGLONG
138#if defined _WANT_IO_LONG_LONG && defined __GNUC__
139# undef _NO_LONGLONG
140#endif
141
142#ifdef __ALTIVEC__
143typedef union
144{
145  vector int v;
146  float f[4];
147  int   i[16 / sizeof(int)];
148  long  l[4];
149  short s[8];
150  signed char c[16];
151} vec_16_byte_union;
152#endif /* __ALTIVEC__ */
153
154/*
155 * Flush out all the vectors defined by the given uio,
156 * then reset it so that it can be reused.
157 */
158static int
159__sprint_r(rptr, fp, uio)
160        struct _reent *rptr;
161        FILE *fp;
162        register struct __suio *uio;
163{
164        register int err;
165
166        if (uio->uio_resid == 0) {
167                uio->uio_iovcnt = 0;
168                return (0);
169        }
170        err = __sfvwrite_r(rptr, fp, uio);
171        uio->uio_resid = 0;
172        uio->uio_iovcnt = 0;
173        return (err);
174}
175
176/*
177 * Helper function for `fprintf to unbuffered unix file': creates a
178 * temporary buffer.  We only work on write-only files; this avoids
179 * worries about ungetc buffers and so forth.
180 */
181static int
182__sbprintf_r(rptr, fp, fmt, ap)
183        struct _reent *rptr;
184        register FILE *fp;
185        const char *fmt;
186        va_list ap;
187{
188        int ret;
189        FILE fake;
190        unsigned char buf[BUFSIZ];
191
192        /* copy the important variables */
193        fake._flags = fp->_flags & ~__SNBF;
194        fake._file = fp->_file;
195        fake._cookie = fp->_cookie;
196        fake._write = fp->_write;
197
198        /* set up the buffer */
199        fake._bf._base = fake._p = buf;
200        fake._bf._size = fake._w = sizeof(buf);
201        fake._lbfsize = 0;      /* not actually used, but Just In Case */
202
203        /* do the work, then copy any error status */
204        ret = _VFPRINTF_R(rptr, &fake, fmt, ap);
205        if (ret >= 0 && _fflush_r(rptr, &fake))
206                ret = EOF;
207        if (fake._flags & __SERR)
208                fp->_flags |= __SERR;
209        return (ret);
210}
211
212
213#ifdef FLOATING_POINT
214#include <locale.h>
215#include <math.h>
216#include "floatio.h"
217
218#define BUF             (MAXEXP+MAXFRACT+1)     /* + decimal point */
219#define DEFPREC         6
220
221#ifdef _NO_LONGDBL
222static char *cvt (struct _reent *, double, int, int, char *, int *, int, int *);
223#else
224static char *cvt (struct _reent *, _LONG_DOUBLE, int, int, char *, int *, int, int *);
225extern int  _ldcheck (_LONG_DOUBLE *);
226#endif
227
228static int exponent (char *, int, int);
229
230#ifdef __SPE__
231static char *cvt_ufix64 (struct _reent *, unsigned long long, int,  int *, int *);
232#endif /* __SPE__ */
233
234#else /* no FLOATING_POINT */
235
236#define BUF             40
237
238#endif /* FLOATING_POINT */
239
240
241/*
242 * Macros for converting digits to letters and vice versa
243 */
244#define to_digit(c)     ((c) - '0')
245#define is_digit(c)     ((unsigned)to_digit(c) <= 9)
246#define to_char(n)      ((n) + '0')
247
248/*
249 * Flags used during conversion.
250 */
251#define ALT             0x001           /* alternate form */
252#define HEXPREFIX       0x002           /* add 0x or 0X prefix */
253#define LADJUST         0x004           /* left adjustment */
254#define LONGDBL         0x008           /* long double */
255#define LONGINT         0x010           /* long integer */
256#ifndef _NO_LONGLONG
257#define QUADINT         0x020           /* quad integer */
258#else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
259         that %lld behaves the same as %ld, not as %d, as expected if:
260         sizeof (long long) = sizeof long > sizeof int  */
261#define QUADINT         LONGINT
262#endif
263#define SHORTINT        0x040           /* short integer */
264#define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
265#define FPT             0x100           /* Floating point number */
266#define VECTOR          0x200           /* vector */
267#define FIXEDPOINT      0x400           /* fixed-point */
268
269int 
270VFPRINTF (FILE * fp,
271        const char *fmt0,
272        va_list ap)
273{
274  CHECK_INIT (_REENT, fp);
275  return _VFPRINTF_R (_REENT, fp, fmt0, ap);
276}
277
278int 
279_VFPRINTF_R (struct _reent *data,
280        FILE * fp,
281        const char *fmt0,
282        va_list ap)
283{
284        register char *fmt;     /* format string */
285        register int ch;        /* character from fmt */
286        register int n, m;      /* handy integers (short term usage) */
287        register char *cp;      /* handy char pointer (short term usage) */
288        register struct __siov *iovp;/* for PRINT macro */
289        register int flags;     /* flags as above */
290        int ret;                /* return value accumulator */
291        int width;              /* width from format (%8d), or 0 */
292        int prec;               /* precision from format (%.3d), or -1 */
293        char sign;              /* sign prefix (' ', '+', '-', or \0) */
294        char old_sign;          /* saved value of sign when looping for vectors */
295        int old_ch;             /* saved value of ch when looping for vectors */
296        char *format_anchor;    /* start of format to process */
297        wchar_t wc;
298#ifdef FLOATING_POINT
299        char *decimal_point = localeconv()->decimal_point;
300        char softsign;          /* temporary negative sign for floats */
301#ifdef _NO_LONGDBL
302        union { int i; double d; } _double_ = {0};
303        #define _fpvalue (_double_.d)
304#else
305        union { int i; _LONG_DOUBLE ld; } _long_double_ = {0};
306        #define _fpvalue (_long_double_.ld)
307        int tmp; 
308#endif
309        int expt;               /* integer value of exponent */
310        int expsize = 0;        /* character count for expstr */
311        int ndig;               /* actual number of digits returned by cvt */
312        char expstr[7];         /* buffer for exponent string */
313#endif
314
315#ifndef _NO_LONGLONG
316#define quad_t    long long
317#define u_quad_t  unsigned long long
318#else
319#define quad_t    long
320#define u_quad_t  u_long
321#endif
322
323        u_quad_t _uquad;        /* integer arguments %[diouxX] */
324        enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
325        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
326        int realsz;             /* field size expanded by dprec */
327        int size;               /* size of converted field or string */
328        char *xdigs = NULL;     /* digits for [xX] conversion */
329#define NIOV 8
330        struct __suio uio;      /* output information: summary */
331        struct __siov iov[NIOV];/* ... and individual io vectors */
332        char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
333        char ox[2];             /* space for 0x hex-prefix */
334#ifdef __ALTIVEC__
335        char vec_sep;           /* vector separator char */
336        int vec_print_count;    /* number of vector chunks remaining */
337        vec_16_byte_union vec_tmp;
338#endif /* __ALTIVEC__ */ 
339        mbstate_t state;          /* mbtowc calls from library must not change state */
340
341        /*
342         * Choose PADSIZE to trade efficiency vs. size.  If larger printf
343         * fields occur frequently, increase PADSIZE and make the initialisers
344         * below longer.
345         */
346#define PADSIZE 16              /* pad chunk size */
347        static const char blanks[PADSIZE] =
348         {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
349        static const char zeroes[PADSIZE] =
350         {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
351
352        /*
353         * BEWARE, these `goto error' on error, and PAD uses `n'.
354         */
355#define PRINT(ptr, len) { \
356        iovp->iov_base = (ptr); \
357        iovp->iov_len = (len); \
358        uio.uio_resid += (len); \
359        iovp++; \
360        if (++uio.uio_iovcnt >= NIOV) { \
361                if (__sprint_r(data, fp, &uio)) \
362                        goto error; \
363                iovp = iov; \
364        } \
365}
366#define PAD(howmany, with) { \
367        if ((n = (howmany)) > 0) { \
368                while (n > PADSIZE) { \
369                        PRINT(with, PADSIZE); \
370                        n -= PADSIZE; \
371                } \
372                PRINT(with, n); \
373        } \
374}
375#define FLUSH() { \
376        if (uio.uio_resid && __sprint_r(data, fp, &uio)) \
377                goto error; \
378        uio.uio_iovcnt = 0; \
379        iovp = iov; \
380}
381
382#ifdef __ALTIVEC__
383#define GET_SHORT(ap) \
384        (flags&VECTOR ? \
385            (vec_print_count < 8 ? (short)vec_tmp.s[8 - vec_print_count] : \
386                (vec_tmp.v = va_arg(ap, vector int), (short)vec_tmp.s[0])) : \
387            (short)va_arg(ap, int))
388#define GET_USHORT(ap) \
389        (flags&VECTOR ? \
390            (vec_print_count < 8 ? (u_short)vec_tmp.s[8 - vec_print_count] : \
391                (vec_tmp.v = va_arg(ap, vector int), (u_short)vec_tmp.s[0])) : \
392            (u_short)va_arg(ap, int))
393
394#define GET_LONG(ap) \
395        (flags&VECTOR ? \
396            (vec_print_count < 4 ? (long)vec_tmp.l[4 - vec_print_count] : \
397                (vec_tmp.v = va_arg(ap, vector int), vec_tmp.l[0])) : \
398            va_arg(ap, long int))
399#define GET_ULONG(ap) \
400        (flags&VECTOR ? \
401            (vec_print_count < 4 ? (u_long)vec_tmp.l[4 - vec_print_count] : \
402                (vec_tmp.v = va_arg(ap, vector int), (u_long)vec_tmp.l[0])) : \
403            (u_long)va_arg(ap, unsigned long int))
404
405#define GET_INT(ap) \
406        (flags&VECTOR ? \
407            (vec_print_count < 16 ? \
408                vec_tmp.c[16 - vec_print_count] : \
409                (vec_tmp.v = va_arg(ap, vector int), (int)vec_tmp.c[0])) : \
410            va_arg(ap, int))
411#define GET_UINT(ap) \
412        (flags&VECTOR ? \
413            (vec_print_count < 16 ? \
414                (u_int)((unsigned char)vec_tmp.c[16 - vec_print_count]) : \
415                (vec_tmp.v = va_arg(ap, vector int), (u_int)((unsigned char)vec_tmp.c[0]))) : \
416            (u_int)va_arg(ap, unsigned int))
417#else /* !__ALTIVEC__ */
418#define GET_SHORT(ap) ((short)va_arg(ap, int))
419#define GET_USHORT(ap) ((u_short)va_arg(ap, int))
420#define GET_LONG(ap) (va_arg(ap, long int))
421#define GET_ULONG(ap) ((u_long)va_arg(ap, unsigned long int))
422#define GET_INT(ap) ((int)va_arg(ap, int))
423#define GET_UINT(ap) ((u_int)va_arg(ap, unsigned int))
424#endif /* !__ALTIVEC__ */
425
426#ifndef _NO_LONGLONG
427#define SARG() \
428        (flags&QUADINT ? va_arg(ap, quad_t) : \
429            flags&LONGINT ? GET_LONG(ap) : \
430            flags&SHORTINT ? (long)GET_SHORT(ap) : \
431            (long)GET_INT(ap))
432#define UARG() \
433        (flags&QUADINT ? va_arg(ap, u_quad_t) : \
434            flags&LONGINT ? GET_ULONG(ap) : \
435            flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
436            (u_long)GET_UINT(ap))
437#ifdef __SPE__
438#define SFPARG() \
439        (flags&LONGINT ? va_arg(ap, quad_t) : \
440            flags&SHORTINT ? (long)GET_SHORT(ap) : \
441            (long)va_arg(ap, int))
442#define UFPARG() \
443        (flags&LONGINT ? va_arg(ap, u_quad_t) : \
444            flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
445            (u_long)va_arg(ap, u_int))
446#endif /* __SPE__ */
447#else
448#define SARG() \
449        (flags&LONGINT ? GET_LONG(ap) : \
450            flags&SHORTINT ? (long)GET_SHORT(ap) : \
451            (long)GET_INT(ap))
452#define UARG() \
453        (flags&LONGINT ? GET_ULONG(ap) : \
454            flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
455            (u_long)GET_UINT(ap))
456#ifdef __SPE__
457#define SFPARG() \
458        (flags&LONGINT ? (va_arg(ap, long) << 32) : \
459            flags&SHORTINT ? (long)GET_SHORT(ap) : \
460            (long)va_arg(ap, int))
461#define UFPARG() \
462        (flags&LONGINT ? (va_arg(ap, u_long) <<32) : \
463            flags&SHORTINT ? (u_long)GET_USHORT(ap) : \
464            (u_long)va_arg(ap, u_int))
465#endif /* __SPE__ */
466#endif
467
468        memset (&state, '\0', sizeof (state));
469
470        /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
471        if (cantwrite (data, fp)) {
472                _funlockfile (fp);     
473                return (EOF);
474        }
475
476        /* optimise fprintf(stderr) (and other unbuffered Unix files) */
477        if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
478            fp->_file >= 0)
479                return (__sbprintf_r(data, fp, fmt0, ap));
480
481        fmt = (char *)fmt0;
482        uio.uio_iov = iovp = iov;
483        uio.uio_resid = 0;
484        uio.uio_iovcnt = 0;
485        ret = 0;
486
487        /*
488         * Scan the format for conversions (`%' character).
489         */
490
491        for (;;) {
492                cp = fmt;
493                while ((n = _mbtowc_r(data, &wc, fmt, MB_CUR_MAX, &state)) > 0) {
494                        fmt += n;
495                        if (wc == '%') {
496                                fmt--;
497                                break;
498                        }
499                }
500                if ((m = fmt - cp) != 0) {
501                        PRINT(cp, m);
502                        ret += m;
503                }
504                if (n <= 0)
505                        goto done;
506                fmt++;          /* skip over '%' */
507
508                flags = 0;
509                dprec = 0;
510                width = 0;
511                prec = -1;
512                sign = '\0';
513                old_sign = '\0';
514#ifdef __ALTIVEC__
515                vec_print_count = 0;
516                vec_sep = ' ';
517#endif /* __ALTIVEC__ */
518
519                format_anchor = fmt;
520rflag:          ch = *fmt++;
521                old_ch = ch;
522reswitch:       switch (ch) {
523                case ' ':
524                        /*
525                         * ``If the space and + flags both appear, the space
526                         * flag will be ignored.''
527                         *      -- ANSI X3J11
528                         */
529                        if (!sign)
530                                sign = ' ';
531                        goto rflag;
532                case '#':
533                        flags |= ALT;
534                        goto rflag;
535                case '*':
536                        /*
537                         * ``A negative field width argument is taken as a
538                         * - flag followed by a positive field width.''
539                         *      -- ANSI X3J11
540                         * They don't exclude field widths read from args.
541                         */
542                        if ((width = va_arg(ap, int)) >= 0)
543                                goto rflag;
544                        width = -width;
545                        /* FALLTHROUGH */
546                case '-':
547                        flags |= LADJUST;
548                        goto rflag;
549                case '+':
550                        sign = '+';
551                        goto rflag;
552#ifdef __ALTIVEC__
553                case ',':
554                case ';':
555                case ':':
556                case '_':
557                        if (vec_sep != ' ')
558                          {
559                            fmt = format_anchor;
560                            continue;
561                          }
562                        vec_sep = ch;
563                        goto rflag;
564#endif /* __ALTIVEC__ */
565                case '.':
566                        if ((ch = *fmt++) == '*') {
567                                n = va_arg(ap, int);
568                                prec = n < 0 ? -1 : n;
569                                goto rflag;
570                        }
571                        n = 0;
572                        while (is_digit(ch)) {
573                                n = 10 * n + to_digit(ch);
574                                ch = *fmt++;
575                        }
576                        prec = n < 0 ? -1 : n;
577                        goto reswitch;
578                case '0':
579                        /*
580                         * ``Note that 0 is taken as a flag, not as the
581                         * beginning of a field width.''
582                         *      -- ANSI X3J11
583                         */
584                        flags |= ZEROPAD;
585                        goto rflag;
586                case '1': case '2': case '3': case '4':
587                case '5': case '6': case '7': case '8': case '9':
588                        n = 0;
589                        do {
590                                n = 10 * n + to_digit(ch);
591                                ch = *fmt++;
592                        } while (is_digit(ch));
593                        width = n;
594                        goto reswitch;
595#ifdef FLOATING_POINT
596                case 'L':
597#ifdef __ALTIVEC__
598                        if (flags & VECTOR) 
599                          {
600                            fmt = format_anchor;
601                            continue;
602                          }
603#endif /* __ALTIVEC__ */
604                        flags |= LONGDBL;
605                        goto rflag;
606#endif
607                case 'h':
608                        if (flags & LONGINT)
609                          {
610                            fmt = format_anchor;
611                            continue;
612                          }
613                        flags |= SHORTINT;
614#ifdef __ALTIVEC__
615                        if (flags & VECTOR)
616                          vec_print_count = 8;
617#endif
618                        goto rflag;
619                case 'l':
620                        if (flags & SHORTINT)
621                          {
622                            fmt = format_anchor;
623                            continue;
624                          }
625                        if (*fmt == 'l') {
626                                fmt++;
627                                flags |= QUADINT;
628                                flags &= ~VECTOR;
629                        } else {
630                                flags |= LONGINT;
631#ifdef __ALTIVEC__
632                                if (flags & VECTOR)
633                                  vec_print_count = 4;
634#endif
635                        }
636                        goto rflag;
637#ifdef __ALTIVEC__
638                case 'v':
639                        if (flags & VECTOR) 
640                          {
641                            fmt = format_anchor;
642                            continue;
643                          }
644                        flags |= VECTOR;
645                        vec_print_count = (flags & SHORTINT) ? 8 : 
646                          ((flags & LONGINT) ? 4 : 16);
647                        goto rflag;
648#endif
649                case 'q':
650#ifdef __ALTIVEC__
651                        if (flags & VECTOR) 
652                          {
653                            fmt = format_anchor;
654                            continue;
655                          }
656#endif /* __ALTIVEC__ */
657                        flags |= QUADINT;
658                        goto rflag;
659                case 'c':
660#ifdef __ALTIVEC__
661                        if (flags & VECTOR)
662                          {
663                            int k;
664                            vec_16_byte_union tmp;
665                            if (flags & (SHORTINT | LONGINT))
666                              {
667                                fmt = format_anchor;
668                                continue;
669                              }
670                            tmp.v = va_arg(ap, vector int);
671                            cp = buf;
672                            for (k = 0; k < 15; ++k)
673                              {
674                                *cp++ = tmp.c[k];
675                                if (vec_sep != ' ')
676                                  *cp++ = vec_sep;
677                              }
678                            *cp++ = tmp.c[15];
679                            size = cp - buf;
680                            cp = buf;
681                            vec_print_count = 0;
682                          }
683                        else
684#endif /* __ALTIVEC__ */
685                          {
686                            *(cp = buf) = va_arg(ap, int);
687                            size = 1;
688                          }
689                        sign = '\0';
690                        break;
691                case 'D':
692                        flags |= LONGINT;
693                        /*FALLTHROUGH*/
694                case 'd':
695                case 'i':
696#ifdef __ALTIVEC__
697                        if (!(flags & VECTOR) && vec_sep != ' ') 
698                          {
699                            fmt = format_anchor;
700                            continue;
701                          }
702#endif /* __ALTIVEC__ */
703                        _uquad = SARG();
704                        if ((quad_t)_uquad < 0)
705                        {
706                                _uquad = -(quad_t)_uquad;
707                                old_sign = sign;
708                                sign = '-';
709                        }
710                        base = DEC;
711                        goto number;
712#ifdef FLOATING_POINT
713                case 'e':
714                case 'E':
715                case 'f':
716                case 'g':
717                case 'G':
718                        if (prec == -1) {
719                                prec = DEFPREC;
720                        } else if ((ch == 'g' || ch == 'G') && prec == 0) {
721                                prec = 1;
722                        }
723
724#ifdef _NO_LONGDBL
725                        if (flags & LONGDBL) {
726                                _fpvalue = (double) va_arg(ap, _LONG_DOUBLE);
727#ifdef __ALTIVEC__
728                        } else if (flags & VECTOR) {
729                                if (vec_print_count >= 4)
730                                  {
731                                    vec_print_count = 4;
732                                    vec_tmp.v = va_arg(ap, vector int);
733                                  }
734                                _fpvalue = (double)vec_tmp.f[4 - vec_print_count];
735                        } else if (vec_sep != ' ') {
736                                 fmt = format_anchor;
737                                 continue;
738                       
739#endif /* __ALTIVEC__ */
740                        } else {
741                                _fpvalue = va_arg(ap, double);
742                        }
743
744                        /* do this before tricky precision changes */
745                        if (isinf(_fpvalue)) {
746                                if (_fpvalue < 0)
747                                  {
748                                    old_sign = sign;
749                                    sign = '-';
750                                  }
751                                   
752                                cp = "Inf";
753                                size = 3;
754                                break;
755                        }
756                        if (isnan(_fpvalue)) {
757                                cp = "NaN";
758                                size = 3;
759                                break;
760                        }
761
762#else /* !_NO_LONGDBL */
763                       
764                        if (flags & LONGDBL) {
765                                _fpvalue = va_arg(ap, _LONG_DOUBLE);
766#ifdef __ALTIVEC__
767                        } else if (flags & VECTOR) {
768                                if (vec_print_count >= 4)
769                                  {
770                                    vec_print_count = 4;
771                                    vec_tmp.v = va_arg(ap, vector int);
772                                  }
773                                _fpvalue = (_LONG_DOUBLE)k.f[4 - vec_print_count];
774#endif /* __ALTIVEC__ */
775                        } else {
776                                _fpvalue = (_LONG_DOUBLE)va_arg(ap, double);
777                        }
778
779                        /* do this before tricky precision changes */
780                        tmp = _ldcheck (&_fpvalue);
781                        if (tmp == 2) {
782                                if (_fpvalue < 0)
783                                  {
784                                    old_sign = sign;
785                                    sign = '-';
786                                  }
787                                cp = "Inf";
788                                size = 3;
789                                break;
790                        }
791                        if (tmp == 1) {
792                                cp = "NaN";
793                                size = 3;
794                                break;
795                        }
796#endif /* !_NO_LONGDBL */
797
798                        flags |= FPT;
799
800                        cp = cvt(data, _fpvalue, prec, flags, &softsign,
801                                &expt, ch, &ndig);
802
803                        if (ch == 'g' || ch == 'G') {
804                                if (expt <= -4 || expt > prec)
805                                  {
806                                    old_ch = ch;
807                                    ch = (ch == 'g') ? 'e' : 'E';
808                                  }
809                                else
810                                        ch = 'g';
811                        } 
812                        if (ch <= 'e') {        /* 'e' or 'E' fmt */
813                                --expt;
814                                expsize = exponent(expstr, expt, ch);
815                                size = expsize + ndig;
816                                if (ndig > 1 || flags & ALT)
817                                        ++size;
818                        } else if (ch == 'f') {         /* f fmt */
819                                if (expt > 0) {
820                                        size = expt;
821                                        if (prec || flags & ALT)
822                                                size += prec + 1;
823                                } else  /* "0.X" */
824                                        size = (prec || flags & ALT)
825                                                  ? prec + 2
826                                                  : 1;
827                        } else if (expt >= ndig) {      /* fixed g fmt */
828                                size = expt;
829                                if (flags & ALT)
830                                        ++size;
831                        } else
832                                size = ndig + (expt > 0 ?
833                                        1 : 2 - expt);
834
835                        if (softsign)
836                          {
837                            old_sign = sign;
838                            sign = '-';
839                          }
840                        break;
841#endif /* FLOATING_POINT */
842#ifdef __SPE__
843                case 'r':
844                        flags |= FIXEDPOINT;
845                        _uquad = SFPARG();
846                        if ((quad_t)_uquad < 0)
847                          {
848                            sign = '-';
849                            _uquad = -(quad_t)_uquad;
850                          }
851                        if (flags & SHORTINT)
852                          _uquad <<= (sizeof(quad_t) - sizeof(short)) * 8 + 1;
853                        else if (flags & LONGINT)
854                          _uquad <<= 1;
855                        else
856                          _uquad <<= (sizeof(quad_t) - sizeof(long)) * 8 + 1;
857
858                        if (_uquad == 0 && sign)
859                          {
860                            /* we have -1.0 which has to be handled special */
861                            cp = "100000";
862                            expt = 1;
863                            ndig = 6;
864                            break;
865                          }
866
867                        goto fixed_nosign;
868                case 'R':
869                        flags |= FIXEDPOINT;
870                        _uquad = UFPARG();
871                        if (flags & SHORTINT)
872                          _uquad <<= (sizeof(quad_t) - sizeof(short)) * 8;
873                        else if (!(flags & LONGINT))
874                          _uquad <<= (sizeof(quad_t) - sizeof(long)) * 8;
875       
876fixed_nosign:
877                        if (prec == -1)
878                          prec = DEFPREC;
879
880#ifndef _NO_LONGLONG
881                        cp = cvt_ufix64 (data, _uquad, prec, &expt, &ndig);
882#else
883                        cp = cvs_ufix32 (data, _uquad, prec, &expt, &ndig);
884#endif
885
886                        /* act like %f of format "0.X" */
887                        size = prec + 2;
888
889                        break;
890#endif /* __SPE__ */
891                case 'n':
892#ifdef __ALTIVEC__
893                        if (flags & VECTOR)
894                          {
895                            fmt = format_anchor;
896                            continue;
897                          }
898#endif /* __ALTIVEC__ */
899#ifndef _NO_LONGLONG
900                        if (flags & QUADINT)
901                                *va_arg(ap, quad_t *) = ret;
902                        else 
903#endif
904                        if (flags & LONGINT)
905                                *va_arg(ap, long *) = ret;
906                        else if (flags & SHORTINT)
907                                *va_arg(ap, short *) = ret;
908                        else
909                                *va_arg(ap, int *) = ret;
910                        continue;       /* no output */
911                case 'O':
912                        flags |= LONGINT;
913                        /*FALLTHROUGH*/
914                case 'o':
915#ifdef __ALTIVEC__
916                        if (!(flags & VECTOR) && vec_sep != ' ') 
917                          {
918                            fmt = format_anchor;
919                            continue;
920                          }
921#endif /* __ALTIVEC__ */
922                        _uquad = UARG();
923                        base = OCT;
924                        goto nosign;
925                case 'p':
926                        /*
927                         * ``The argument shall be a pointer to void.  The
928                         * value of the pointer is converted to a sequence
929                         * of printable characters, in an implementation-
930                         * defined manner.''
931                         *      -- ANSI X3J11
932                         */
933                        /* NOSTRICT */
934#ifdef __ALTIVEC__
935                        if (flags & VECTOR)
936                          _uquad = UARG();
937                        else if (vec_sep != ' ')
938                          {
939                            fmt = format_anchor;
940                            continue;
941                          }
942                        else
943#endif /* __ALTIVEC__ */
944                          _uquad = (u_long)(unsigned _POINTER_INT)va_arg(ap, void *);
945                        base = HEX;
946                        xdigs = "0123456789abcdef";
947                        flags |= HEXPREFIX;
948                        ch = 'x';
949                        goto nosign;
950                case 's':
951#ifdef __ALTIVEC__
952                        if (flags & VECTOR)
953                          {
954                            fmt = format_anchor;
955                            continue;
956                          }
957#endif /* __ALTIVEC__ */
958                        if ((cp = va_arg(ap, char *)) == NULL)
959                                cp = "(null)";
960                        if (prec >= 0) {
961                                /*
962                                 * can't use strlen; can only look for the
963                                 * NUL in the first `prec' characters, and
964                                 * strlen() will go further.
965                                 */
966                                char *p = memchr(cp, 0, prec);
967
968                                if (p != NULL) {
969                                        size = p - cp;
970                                        if (size > prec)
971                                                size = prec;
972                                } else
973                                        size = prec;
974                        } else
975                                size = strlen(cp);
976                        sign = '\0';
977                        break;
978                case 'U':
979                        flags |= LONGINT;
980                        /*FALLTHROUGH*/
981                case 'u':
982#ifdef __ALTIVEC__
983                        if (!(flags & VECTOR) && vec_sep != ' ') 
984                          {
985                            fmt = format_anchor;
986                            continue;
987                          }
988#endif /* __ALTIVEC__ */
989                        _uquad = UARG();
990                        base = DEC;
991                        goto nosign;
992                case 'X':
993                        xdigs = "0123456789ABCDEF";
994                        goto hex;
995                case 'x':
996                        xdigs = "0123456789abcdef";
997#ifdef __ALTIVEC__
998                        if (!(flags & VECTOR) && vec_sep != ' ') 
999                          {
1000                            fmt = format_anchor;
1001                            continue;
1002                          }
1003#endif /* __ALTIVEC__ */
1004hex:                    _uquad = UARG();
1005                        base = HEX;
1006                        /* leading 0x/X only if non-zero */
1007                        if (flags & ALT && _uquad != 0)
1008                                flags |= HEXPREFIX;
1009
1010                        /* unsigned conversions */
1011nosign:                 sign = '\0';
1012                        /*
1013                         * ``... diouXx conversions ... if a precision is
1014                         * specified, the 0 flag will be ignored.''
1015                         *      -- ANSI X3J11
1016                         */
1017number:                 if ((dprec = prec) >= 0)
1018                                flags &= ~ZEROPAD;
1019
1020                        /*
1021                         * ``The result of converting a zero value with an
1022                         * explicit precision of zero is no characters.''
1023                         *      -- ANSI X3J11
1024                         */
1025                        cp = buf + BUF;
1026                        if (_uquad != 0 || prec != 0) {
1027                                /*
1028                                 * Unsigned mod is hard, and unsigned mod
1029                                 * by a constant is easier than that by
1030                                 * a variable; hence this switch.
1031                                 */
1032                                switch (base) {
1033                                case OCT:
1034                                        do {
1035                                                *--cp = to_char(_uquad & 7);
1036                                                _uquad >>= 3;
1037                                        } while (_uquad);
1038                                        /* handle octal leading 0 */
1039                                        if (flags & ALT && *cp != '0')
1040                                                *--cp = '0';
1041                                        break;
1042
1043                                case DEC:
1044                                        /* many numbers are 1 digit */
1045                                        while (_uquad >= 10) {
1046                                                *--cp = to_char(_uquad % 10);
1047                                                _uquad /= 10;
1048                                        }
1049                                        *--cp = to_char(_uquad);
1050                                        break;
1051
1052                                case HEX:
1053                                        do {
1054                                                *--cp = xdigs[_uquad & 15];
1055                                                _uquad >>= 4;
1056                                        } while (_uquad);
1057                                        break;
1058
1059                                default:
1060                                        cp = "bug in vfprintf: bad base";
1061                                        size = strlen(cp);
1062                                        goto skipsize;
1063                                }
1064                        }
1065                       /*
1066                        * ...result is to be converted to an 'alternate form'.
1067                        * For o conversion, it increases the precision to force
1068                        * the first digit of the result to be a zero."
1069                        *     -- ANSI X3J11
1070                        *
1071                        * To demonstrate this case, compile and run:
1072                        *    printf ("%#.0o",0);
1073                        */
1074                       else if (base == OCT && (flags & ALT))
1075                         *--cp = '0';
1076
1077                        size = buf + BUF - cp;
1078                skipsize:
1079                        break;
1080                default:        /* "%?" prints ?, unless ? is NUL */
1081                        flags &= ~VECTOR;
1082                        if (ch == '\0')
1083                                goto done;
1084                        /* pretend it was %c with argument ch */
1085                        cp = buf;
1086                        *cp = ch;
1087                        size = 1;
1088                        sign = '\0';
1089                        break;
1090                }
1091
1092                /*
1093                 * All reasonable formats wind up here.  At this point, `cp'
1094                 * points to a string which (if not flags&LADJUST) should be
1095                 * padded out to `width' places.  If flags&ZEROPAD, it should
1096                 * first be prefixed by any sign or other prefix; otherwise,
1097                 * it should be blank padded before the prefix is emitted.
1098                 * After any left-hand padding and prefixing, emit zeroes
1099                 * required by a decimal [diouxX] precision, then print the
1100                 * string proper, then emit zeroes required by any leftover
1101                 * floating precision; finally, if LADJUST, pad with blanks.
1102                 *
1103                 * Compute actual size, so we know how much to pad.
1104                 * size excludes decimal prec; realsz includes it.
1105                 */
1106                realsz = dprec > size ? dprec : size;
1107                if (sign)
1108                        realsz++;
1109                else if (flags & HEXPREFIX)
1110                        realsz+= 2;
1111
1112                /* right-adjusting blank padding */
1113                if ((flags & (LADJUST|ZEROPAD)) == 0)
1114                        PAD(width - realsz, blanks);
1115
1116                /* prefix */
1117                if (sign) {
1118                        PRINT(&sign, 1);
1119                } else if (flags & HEXPREFIX) {
1120                        ox[0] = '0';
1121                        ox[1] = ch;
1122                        PRINT(ox, 2);
1123                }
1124
1125                /* right-adjusting zero padding */
1126                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1127                        PAD(width - realsz, zeroes);
1128
1129                /* leading zeroes from decimal precision */
1130                PAD(dprec - size, zeroes);
1131
1132                /* the string or number proper */
1133#ifdef FLOATING_POINT
1134                if ((flags & FPT) == 0) {
1135#ifdef __SPE__
1136                        if (flags & FIXEDPOINT) {
1137                                if (_uquad == 0 && !sign) {
1138                                        /* kludge for __dtoa irregularity */
1139                                        PRINT("0", 1);
1140                                        if (expt < ndig || (flags & ALT) != 0) {
1141                                                PRINT(decimal_point, 1);
1142                                                PAD(ndig - 1, zeroes);
1143                                        }
1144                                } else if (expt <= 0) {
1145                                        PRINT("0", 1);
1146                                        if(expt || ndig) {
1147                                                PRINT(decimal_point, 1);
1148                                                PAD(-expt, zeroes);
1149                                                PRINT(cp, ndig);
1150                                        }
1151                                } else if (expt >= ndig) {
1152                                        PRINT(cp, ndig);
1153                                        PAD(expt - ndig, zeroes);
1154                                        if (flags & ALT)
1155                                                PRINT(".", 1);
1156                                } else {
1157                                        PRINT(cp, expt);
1158                                        cp += expt;
1159                                        PRINT(".", 1);
1160                                        PRINT(cp, ndig-expt);
1161                                }
1162                        } else
1163#endif /* __SPE__ */
1164                                PRINT(cp, size);
1165                } else {        /* glue together f_p fragments */
1166                        if (ch >= 'f') {        /* 'f' or 'g' */
1167                                if (_fpvalue == 0) {
1168                                        /* kludge for __dtoa irregularity */
1169                                        PRINT("0", 1);
1170                                        if (expt < ndig || (flags & ALT) != 0) {
1171                                                PRINT(decimal_point, 1);
1172                                                PAD(ndig - 1, zeroes);
1173                                        }
1174                                } else if (expt <= 0) {
1175                                        PRINT("0", 1);
1176                                        if(expt || ndig) {
1177                                                PRINT(decimal_point, 1);
1178                                                PAD(-expt, zeroes);
1179                                                PRINT(cp, ndig);
1180                                        }
1181                                } else if (expt >= ndig) {
1182                                        PRINT(cp, ndig);
1183                                        PAD(expt - ndig, zeroes);
1184                                        if (flags & ALT)
1185                                                PRINT(".", 1);
1186                                } else {
1187                                        PRINT(cp, expt);
1188                                        cp += expt;
1189                                        PRINT(".", 1);
1190                                        PRINT(cp, ndig-expt);
1191                                }
1192                        } else {        /* 'e' or 'E' */
1193                                if (ndig > 1 || flags & ALT) {
1194                                        ox[0] = *cp++;
1195                                        ox[1] = '.';
1196                                        PRINT(ox, 2);
1197                                       if (_fpvalue) {
1198                                                PRINT(cp, ndig-1);
1199                                        } else  /* 0.[0..] */
1200                                                /* __dtoa irregularity */
1201                                                PAD(ndig - 1, zeroes);
1202                                } else  /* XeYYY */
1203                                        PRINT(cp, 1);
1204                                PRINT(expstr, expsize);
1205                        }
1206                }
1207#else
1208                PRINT(cp, size);
1209#endif
1210                /* left-adjusting padding (always blank) */
1211                if (flags & LADJUST)
1212                        PAD(width - realsz, blanks);
1213
1214                /* finally, adjust ret */
1215                ret += width > realsz ? width : realsz;
1216
1217#ifdef __ALTIVEC__             
1218                if ((flags & VECTOR) && vec_print_count-- > 1)
1219                  {
1220                    /* add vector separator */
1221                    if (ch != 'c' || vec_sep != ' ')
1222                      {
1223                        PRINT(&vec_sep, 1);
1224                        ret += 1;
1225                      }
1226                    FLUSH();
1227                    sign = old_sign;
1228                    ch = old_ch;
1229                    goto reswitch;
1230                  }
1231#endif /* __ALTIVEC__ */
1232                FLUSH();        /* copy out the I/O vectors */
1233        }
1234done:
1235        FLUSH();
1236error:
1237        return (__sferror(fp) ? EOF : ret);
1238        /* NOTREACHED */
1239}
1240
1241#ifdef FLOATING_POINT
1242
1243#ifdef _NO_LONGDBL
1244extern char *_dtoa_r (struct _reent *, double, int,
1245                              int, int *, int *, char **);
1246#else
1247extern char *_ldtoa_r (struct _reent *, _LONG_DOUBLE, int,
1248                              int, int *, int *, char **);
1249#undef word0
1250#define word0(x) ldword0(x)
1251#endif
1252
1253static char *
1254cvt(data, value, ndigits, flags, sign, decpt, ch, length)
1255        struct _reent *data;
1256#ifdef _NO_LONGDBL
1257        double value;
1258#else
1259        _LONG_DOUBLE value;
1260#endif
1261        int ndigits, flags, *decpt, ch, *length;
1262        char *sign;
1263{
1264        int mode, dsgn;
1265        char *digits, *bp, *rve;
1266#ifdef _NO_LONGDBL
1267        union double_union tmp;
1268#else
1269        struct ldieee *ldptr;
1270#endif
1271
1272        if (ch == 'f') {
1273                mode = 3;               /* ndigits after the decimal point */
1274        } else {
1275                /* To obtain ndigits after the decimal point for the 'e'
1276                 * and 'E' formats, round to ndigits + 1 significant
1277                 * figures.
1278                 */
1279                if (ch == 'e' || ch == 'E') {
1280                        ndigits++;
1281                }
1282                mode = 2;               /* ndigits significant digits */
1283        }
1284
1285#ifdef _NO_LONGDBL
1286        tmp.d = value;
1287
1288        if (word0(tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1289                value = -value;
1290                *sign = '-';
1291        } else
1292                *sign = '\000';
1293
1294        digits = _dtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);
1295#else /* !_NO_LONGDBL */
1296        ldptr = (struct ldieee *)&value;
1297        if (ldptr->sign) { /* this will check for < 0 and -0.0 */
1298                value = -value;
1299                *sign = '-';
1300        } else
1301                *sign = '\000';
1302
1303        digits = _ldtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);
1304#endif /* !_NO_LONGDBL */
1305
1306        if ((ch != 'g' && ch != 'G') || flags & ALT) {  /* Print trailing zeros */
1307                bp = digits + ndigits;
1308                if (ch == 'f') {
1309                        if (*digits == '0' && value)
1310                                *decpt = -ndigits + 1;
1311                        bp += *decpt;
1312                }
1313                if (value == 0) /* kludge for __dtoa irregularity */
1314                        rve = bp;
1315                while (rve < bp)
1316                        *rve++ = '0';
1317        }
1318        *length = rve - digits;
1319        return (digits);
1320}
1321
1322static int
1323exponent(p0, exp, fmtch)
1324        char *p0;
1325        int exp, fmtch;
1326{
1327        register char *p, *t;
1328        char expbuf[40];
1329
1330        p = p0;
1331        *p++ = fmtch;
1332        if (exp < 0) {
1333                exp = -exp;
1334                *p++ = '-';
1335        }
1336        else
1337                *p++ = '+';
1338        t = expbuf + 40;
1339        if (exp > 9) {
1340                do {
1341                        *--t = to_char(exp % 10);
1342                } while ((exp /= 10) > 9);
1343                *--t = to_char(exp);
1344                for (; t < expbuf + 40; *p++ = *t++);
1345        }
1346        else {
1347                *p++ = '0';
1348                *p++ = to_char(exp);
1349        }
1350        return (p - p0);
1351}
1352#endif /* FLOATING_POINT */
1353
1354#ifdef __SPE__
1355extern char *_ufix64toa_r (struct _reent *, unsigned long long, int,
1356                                   int, int *, int *, char **);
1357static char *
1358cvt_ufix64 (data, value, ndigits, decpt, length)
1359        struct _reent *data;
1360        unsigned long long value;
1361        int ndigits, *decpt, *length;
1362{
1363        int dsgn;
1364        char *digits, *bp, *rve;
1365
1366        /* treat the same as %f format and use mode=3 */
1367        digits = _ufix64toa_r (data, value, 3, ndigits, decpt, &dsgn, &rve);
1368
1369        /* print trailing zeroes */
1370        bp = digits + ndigits;
1371        if (*digits == '0' && value)
1372          *decpt = -ndigits + 1;
1373        bp += *decpt;
1374        if (value == 0) /* kludge for __dtoa irregularity */
1375          rve = bp;
1376        while (rve < bp)
1377          *rve++ = '0';
1378        *length = rve - digits;
1379        return (digits);
1380}
1381#endif /* __SPE__ */
Note: See TracBrowser for help on using the repository browser.