OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [stdio/] [vfprintf.c] - Blame information for rev 171

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/*
2
 * Copyright (c) 1990 The Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * This code is derived from software contributed to Berkeley by
6
 * Chris Torek.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. All advertising materials mentioning features or use of this software
17
 *    must display the following acknowledgement:
18
 *      This product includes software developed by the University of
19
 *      California, Berkeley and its contributors.
20
 * 4. Neither the name of the University nor the names of its contributors
21
 *    may be used to endorse or promote products derived from this software
22
 *    without specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
35
 */
36
 
37
/*
38
FUNCTION
39
<<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
40
 
41
INDEX
42
        vfprintf
43
INDEX
44
        _vfprintf_r
45
INDEX
46
        vprintf
47
INDEX
48
        _vprintf_r
49
INDEX
50
        vsprintf
51
INDEX
52
        _vsprintf_r
53
INDEX
54
        vsnprintf
55
INDEX
56
        _vsnprintf_r
57
INDEX
58
        vasprintf
59
INDEX
60
        _vasprintf_r
61
INDEX
62
        vasnprintf
63
INDEX
64
        _vasnprintf_r
65
 
66
ANSI_SYNOPSIS
67
        #include <stdio.h>
68
        #include <stdarg.h>
69
        int vprintf(const char *<[fmt]>, va_list <[list]>);
70
        int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
71
        int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
72
        int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
73
                      va_list <[list]>);
74
        int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
75
        char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
76
                         va_list <[list]>);
77
 
78
        int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
79
                        va_list <[list]>);
80
        int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
81
                        const char *<[fmt]>, va_list <[list]>);
82
        int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
83
                        const char *<[fmt]>, va_list <[list]>);
84
        int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
85
                         const char *<[fmt]>, va_list <[list]>);
86
        int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
87
                         size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
88
        char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
89
                            size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
90
 
91
DESCRIPTION
92
<<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>>, <<vsnprintf>>,
93
and <<vasnprintf>> are (respectively) variants of <<printf>>,
94
<<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>, and
95
<<asnprintf>>.  They differ only in allowing their caller to pass the
96
variable argument list as a <<va_list>> object (initialized by
97
<<va_start>>) rather than directly accepting a variable number of
98
arguments.  The caller is responsible for calling <<va_end>>.
99
 
100
<<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
101
<<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
102
above.
103
 
104
RETURNS
105
The return values are consistent with the corresponding functions.
106
 
107
PORTABILITY
108
ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
109
<<vsnprintf>>.  The remaining functions are newlib extensions.
110
 
111
Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
112
<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
113
*/
114
 
115
#if defined(LIBC_SCCS) && !defined(lint)
116
/*static char *sccsid = "from: @(#)vfprintf.c   5.50 (Berkeley) 12/16/92";*/
117
static char *rcsid = "$Id: vfprintf.c 148 2010-06-30 19:21:22Z jeremybennett $";
118
#endif /* LIBC_SCCS and not lint */
119
 
120
/*
121
 * Actual printf innards.
122
 *
123
 * This code is large and complicated...
124
 */
125
#include <newlib.h>
126
 
127
#ifdef INTEGER_ONLY
128
# define VFPRINTF vfiprintf
129
# ifdef STRING_ONLY
130
#   define _VFPRINTF_R _svfiprintf_r
131
# else
132
#   define _VFPRINTF_R _vfiprintf_r
133
# endif
134
#else
135
# define VFPRINTF vfprintf
136
# ifdef STRING_ONLY
137
#   define _VFPRINTF_R _svfprintf_r
138
# else
139
#   define _VFPRINTF_R _vfprintf_r
140
# endif
141
# ifndef NO_FLOATING_POINT
142
#  define FLOATING_POINT
143
# endif
144
#endif
145
 
146
#define _NO_POS_ARGS
147
#ifdef _WANT_IO_POS_ARGS
148
# undef _NO_POS_ARGS
149
#endif
150
 
151
#include <_ansi.h>
152
#include <reent.h>
153
#include <stdio.h>
154
#include <stdlib.h>
155
#include <string.h>
156
#include <limits.h>
157
#include <stdint.h>
158
#include <wchar.h>
159
#include <sys/lock.h>
160
#include <stdarg.h>
161
#include "local.h"
162
#include "fvwrite.h"
163
#include "vfieeefp.h"
164
 
165
/* Currently a test is made to see if long double processing is warranted.
166
   This could be changed in the future should the _ldtoa_r code be
167
   preferred over _dtoa_r.  */
168
#define _NO_LONGDBL
169
#if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
170
#undef _NO_LONGDBL
171
#endif
172
 
173
#define _NO_LONGLONG
174
#if defined _WANT_IO_LONG_LONG \
175
        && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
176
# undef _NO_LONGLONG
177
#endif
178
 
179
#ifdef STRING_ONLY
180
static int
181
_DEFUN(__sprint_r, (ptr, fp, uio),
182
       struct _reent *ptr _AND
183
       FILE *fp _AND
184
       register struct __suio *uio)
185
{
186
        register size_t len;
187
        register int w;
188
        register struct __siov *iov;
189
        register _CONST char *p = NULL;
190
 
191
        iov = uio->uio_iov;
192
        len = 0;
193
 
194
        if (uio->uio_resid == 0) {
195
                uio->uio_iovcnt = 0;
196
                return (0);
197
        }
198
 
199
        do {
200
                while (len == 0) {
201
                        p = iov->iov_base;
202
                        len = iov->iov_len;
203
                        iov++;
204
                }
205
                w = fp->_w;
206
                if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
207
                        /* must be asprintf family */
208
                        unsigned char *str;
209
                        int curpos = (fp->_p - fp->_bf._base);
210
                        /* Choose a geometric growth factor to avoid
211
                         * quadratic realloc behavior, but use a rate less
212
                         * than (1+sqrt(5))/2 to accomodate malloc
213
                         * overhead. asprintf EXPECTS us to overallocate, so
214
                         * that it can add a trailing \0 without
215
                         * reallocating.  The new allocation should thus be
216
                         * max(prev_size*1.5, curpos+len+1). */
217
                        int newsize = fp->_bf._size * 3 / 2;
218
                        if (newsize < curpos + len + 1)
219
                                newsize = curpos + len + 1;
220
                        if (fp->_flags & __SOPT)
221
                        {
222
                                /* asnprintf leaves original buffer alone.  */
223
                                str = (unsigned char *)_malloc_r (ptr, newsize);
224
                                if (!str)
225
                                {
226
                                        ptr->_errno = ENOMEM;
227
                                        goto err;
228
                                }
229
                                memcpy (str, fp->_bf._base, curpos);
230
                                fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
231
                        }
232
                        else
233
                        {
234
                                str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
235
                                                newsize);
236
                                if (!str) {
237
                                        /* Free unneeded buffer.  */
238
                                        _free_r (ptr, fp->_bf._base);
239
                                        /* Ensure correct errno, even if free
240
                                         * changed it.  */
241
                                        ptr->_errno = ENOMEM;
242
                                        goto err;
243
                                }
244
                        }
245
                        fp->_bf._base = str;
246
                        fp->_p = str + curpos;
247
                        fp->_bf._size = newsize;
248
                        w = len;
249
                        fp->_w = newsize - curpos;
250
                }
251
                if (len < w)
252
                        w = len;
253
                (void)memmove ((_PTR) fp->_p, (_PTR) p, (size_t) (w));
254
                fp->_w -= w;
255
                fp->_p += w;
256
                w = len;          /* pretend we copied all */
257
                p += w;
258
                len -= w;
259
        } while ((uio->uio_resid -= w) != 0);
260
 
261
        uio->uio_resid = 0;
262
        uio->uio_iovcnt = 0;
263
        return 0;
264
 
265
err:
266
  fp->_flags |= __SERR;
267
  uio->uio_resid = 0;
268
  uio->uio_iovcnt = 0;
269
  return EOF;
270
}
271
 
272
#else /* !STRING_ONLY */
273
/*
274
 * Flush out all the vectors defined by the given uio,
275
 * then reset it so that it can be reused.
276
 */
277
static int
278
_DEFUN(__sprint_r, (ptr, fp, uio),
279
       struct _reent *ptr _AND
280
       FILE *fp _AND
281
       register struct __suio *uio)
282
{
283
        register int err;
284
 
285
        if (uio->uio_resid == 0) {
286
                uio->uio_iovcnt = 0;
287
                return (0);
288
        }
289
        err = __sfvwrite_r(ptr, fp, uio);
290
        uio->uio_resid = 0;
291
        uio->uio_iovcnt = 0;
292
        return (err);
293
}
294
 
295
/*
296
 * Helper function for `fprintf to unbuffered unix file': creates a
297
 * temporary buffer.  We only work on write-only files; this avoids
298
 * worries about ungetc buffers and so forth.
299
 */
300
static int
301
_DEFUN(__sbprintf, (rptr, fp, fmt, ap),
302
       struct _reent *rptr _AND
303
       register FILE *fp   _AND
304
       _CONST char *fmt  _AND
305
       va_list ap)
306
{
307
        int ret;
308
        FILE fake;
309
        unsigned char buf[BUFSIZ];
310
 
311
        /* copy the important variables */
312
        fake._flags = fp->_flags & ~__SNBF;
313
        fake._file = fp->_file;
314
        fake._cookie = fp->_cookie;
315
        fake._write = fp->_write;
316
 
317
        /* set up the buffer */
318
        fake._bf._base = fake._p = buf;
319
        fake._bf._size = fake._w = sizeof (buf);
320
        fake._lbfsize = 0;       /* not actually used, but Just In Case */
321
#ifndef __SINGLE_THREAD__
322
        __lock_init_recursive (fake._lock);
323
#endif
324
 
325
        /* do the work, then copy any error status */
326
        ret = _VFPRINTF_R (rptr, &fake, fmt, ap);
327
        if (ret >= 0 && _fflush_r (rptr, &fake))
328
                ret = EOF;
329
        if (fake._flags & __SERR)
330
                fp->_flags |= __SERR;
331
 
332
#ifndef __SINGLE_THREAD__
333
        __lock_close_recursive (fake._lock);
334
#endif
335
        return (ret);
336
}
337
#endif /* !STRING_ONLY */
338
 
339
 
340
#ifdef FLOATING_POINT
341
# include <locale.h>
342
# include <math.h>
343
 
344
/* For %La, an exponent of 15 bits occupies the exponent character, a
345
   sign, and up to 5 digits.  */
346
# define MAXEXPLEN              7
347
# define DEFPREC                6
348
 
349
# ifdef _NO_LONGDBL
350
 
351
extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
352
                              int, int *, int *, char **));
353
 
354
#  define _PRINTF_FLOAT_TYPE double
355
#  define _DTOA_R _dtoa_r
356
#  define FREXP frexp
357
 
358
# else /* !_NO_LONGDBL */
359
 
360
extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
361
                              int, int *, int *, char **));
362
 
363
extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
364
 
365
#  define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
366
#  define _DTOA_R _ldtoa_r
367
/* FIXME - frexpl is not yet supported; and cvt infloops if (double)f
368
   converts a finite value into infinity.  */
369
/* #  define FREXP frexpl */
370
#  define FREXP(f,e) ((_LONG_DOUBLE) frexp ((double)f, e))
371
# endif /* !_NO_LONGDBL */
372
 
373
static char *cvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, char *, int *,
374
                 int, int *, char *);
375
 
376
static int exponent(char *, int, int);
377
 
378
#endif /* FLOATING_POINT */
379
 
380
/* BUF must be big enough for the maximum %#llo (assuming long long is
381
   at most 64 bits, this would be 23 characters), the maximum
382
   multibyte character %C, and the maximum default precision of %La
383
   (assuming long double is at most 128 bits with 113 bits of
384
   mantissa, this would be 29 characters).  %e, %f, and %g use
385
   reentrant storage shared with mprec.  All other formats that use
386
   buf get by with fewer characters.  Making BUF slightly bigger
387
   reduces the need for malloc in %.*a and %S, when large precision or
388
   long strings are processed.  */
389
#define BUF             40
390
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
391
# undef BUF
392
# define BUF MB_LEN_MAX
393
#endif
394
 
395
#ifndef _NO_LONGLONG
396
# define quad_t long long
397
# define u_quad_t unsigned long long
398
#else
399
# define quad_t long
400
# define u_quad_t unsigned long
401
#endif
402
 
403
typedef quad_t * quad_ptr_t;
404
typedef _PTR     void_ptr_t;
405
typedef char *   char_ptr_t;
406
typedef long *   long_ptr_t;
407
typedef int  *   int_ptr_t;
408
typedef short *  short_ptr_t;
409
 
410
#ifndef _NO_POS_ARGS
411
# ifdef NL_ARGMAX
412
#  define MAX_POS_ARGS NL_ARGMAX
413
# else
414
#  define MAX_POS_ARGS 32
415
# endif
416
 
417
union arg_val
418
{
419
  int val_int;
420
  u_int val_u_int;
421
  long val_long;
422
  u_long val_u_long;
423
  float val_float;
424
  double val_double;
425
  _LONG_DOUBLE val__LONG_DOUBLE;
426
  int_ptr_t val_int_ptr_t;
427
  short_ptr_t val_short_ptr_t;
428
  long_ptr_t val_long_ptr_t;
429
  char_ptr_t val_char_ptr_t;
430
  quad_ptr_t val_quad_ptr_t;
431
  void_ptr_t val_void_ptr_t;
432
  quad_t val_quad_t;
433
  u_quad_t val_u_quad_t;
434
  wint_t val_wint_t;
435
};
436
 
437
static union arg_val *
438
_EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
439
                 va_list *ap, int *numargs, union arg_val *args,
440
                 int *arg_type, char **last_fmt));
441
#endif /* !_NO_POS_ARGS */
442
 
443
/*
444
 * Macros for converting digits to letters and vice versa
445
 */
446
#define to_digit(c)     ((c) - '0')
447
#define is_digit(c)     ((unsigned)to_digit (c) <= 9)
448
#define to_char(n)      ((n) + '0')
449
 
450
/*
451
 * Flags used during conversion.
452
 */
453
#define ALT             0x001           /* alternate form */
454
#define HEXPREFIX       0x002           /* add 0x or 0X prefix */
455
#define LADJUST         0x004           /* left adjustment */
456
#define LONGDBL         0x008           /* long double */
457
#define LONGINT         0x010           /* long integer */
458
#ifndef _NO_LONGLONG
459
# define QUADINT        0x020           /* quad integer */
460
#else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
461
         that %lld behaves the same as %ld, not as %d, as expected if:
462
         sizeof (long long) = sizeof long > sizeof int  */
463
# define QUADINT        LONGINT
464
#endif
465
#define SHORTINT        0x040           /* short integer */
466
#define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
467
#define FPT             0x100           /* Floating point number */
468
#ifdef _WANT_IO_C99_FORMATS
469
# define CHARINT        0x200           /* char as integer */
470
#else /* define as 0, to make SARG and UARG occupy fewer instructions  */
471
# define CHARINT        0
472
#endif
473
 
474
int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
475
 
476
#ifndef STRING_ONLY
477
int
478
_DEFUN(VFPRINTF, (fp, fmt0, ap),
479
       FILE * fp         _AND
480
       _CONST char *fmt0 _AND
481
       va_list ap)
482
{
483
  int result;
484
  result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
485
  return result;
486
}
487
#endif /* STRING_ONLY */
488
 
489
int
490
_DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
491
       struct _reent *data _AND
492
       FILE * fp           _AND
493
       _CONST char *fmt0   _AND
494
       va_list ap)
495
{
496
        register char *fmt;     /* format string */
497
        register int ch;        /* character from fmt */
498
        register int n, m;      /* handy integers (short term usage) */
499
        register char *cp;      /* handy char pointer (short term usage) */
500
        register struct __siov *iovp;/* for PRINT macro */
501
        register int flags;     /* flags as above */
502
        char *fmt_anchor;       /* current format spec being processed */
503
#ifndef _NO_POS_ARGS
504
        int N;                  /* arg number */
505
        int arg_index;          /* index into args processed directly */
506
        int numargs;            /* number of varargs read */
507
        char *saved_fmt;        /* saved fmt pointer */
508
        union arg_val args[MAX_POS_ARGS];
509
        int arg_type[MAX_POS_ARGS];
510
        int is_pos_arg;         /* is current format positional? */
511
        int old_is_pos_arg;     /* is current format positional? */
512
#endif
513
        int ret;                /* return value accumulator */
514
        int width;              /* width from format (%8d), or 0 */
515
        int prec;               /* precision from format (%.3d), or -1 */
516
        char sign;              /* sign prefix (' ', '+', '-', or \0) */
517
#ifdef FLOATING_POINT
518
        char *decimal_point = _localeconv_r (data)->decimal_point;
519
        char softsign;          /* temporary negative sign for floats */
520
        union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
521
# define _fpvalue (_double_.fp)
522
        int expt;               /* integer value of exponent */
523
        int expsize = 0; /* character count for expstr */
524
        int ndig = 0;            /* actual number of digits returned by cvt */
525
        char expstr[MAXEXPLEN]; /* buffer for exponent string */
526
#endif /* FLOATING_POINT */
527
        u_quad_t _uquad;        /* integer arguments %[diouxX] */
528
        enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
529
        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
530
        int realsz;             /* field size expanded by dprec */
531
        int size;               /* size of converted field or string */
532
        char *xdigs = NULL;     /* digits for [xX] conversion */
533
#define NIOV 8
534
        struct __suio uio;      /* output information: summary */
535
        struct __siov iov[NIOV];/* ... and individual io vectors */
536
        char buf[BUF];          /* space for %c, %S, %[diouxX], %[aA] */
537
        char ox[2];             /* space for 0x hex-prefix */
538
#ifdef _MB_CAPABLE
539
        wchar_t wc;
540
        mbstate_t state;        /* mbtowc calls from library must not change state */
541
#endif
542
        char *malloc_buf = NULL;/* handy pointer for malloced buffers */
543
 
544
        /*
545
         * Choose PADSIZE to trade efficiency vs. size.  If larger printf
546
         * fields occur frequently, increase PADSIZE and make the initialisers
547
         * below longer.
548
         */
549
#define PADSIZE 16              /* pad chunk size */
550
        static _CONST char blanks[PADSIZE] =
551
         {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
552
        static _CONST char zeroes[PADSIZE] =
553
         {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
554
 
555
#ifdef _MB_CAPABLE
556
        memset (&state, '\0', sizeof (state));
557
#endif
558
        /*
559
         * BEWARE, these `goto error' on error, and PAD uses `n'.
560
         */
561
#define PRINT(ptr, len) { \
562
        iovp->iov_base = (ptr); \
563
        iovp->iov_len = (len); \
564
        uio.uio_resid += (len); \
565
        iovp++; \
566
        if (++uio.uio_iovcnt >= NIOV) { \
567
                if (__sprint_r(data, fp, &uio)) \
568
                        goto error; \
569
                iovp = iov; \
570
        } \
571
}
572
#define PAD(howmany, with) { \
573
        if ((n = (howmany)) > 0) { \
574
                while (n > PADSIZE) { \
575
                        PRINT (with, PADSIZE); \
576
                        n -= PADSIZE; \
577
                } \
578
                PRINT (with, n); \
579
        } \
580
}
581
#define FLUSH() { \
582
        if (uio.uio_resid && __sprint_r(data, fp, &uio)) \
583
                goto error; \
584
        uio.uio_iovcnt = 0; \
585
        iovp = iov; \
586
}
587
 
588
        /* Macros to support positional arguments */
589
#ifndef _NO_POS_ARGS
590
# define GET_ARG(n, ap, type)                                           \
591
        (is_pos_arg                                                     \
592
         ? (n < numargs                                                 \
593
            ? args[n].val_##type                                        \
594
            : get_arg (data, n, fmt_anchor, &ap, &numargs, args,        \
595
                       arg_type, &saved_fmt)->val_##type)               \
596
         : (arg_index++ < numargs                                       \
597
            ? args[n].val_##type                                        \
598
            : (numargs < MAX_POS_ARGS                                   \
599
               ? args[numargs++].val_##type = va_arg (ap, type)         \
600
               : va_arg (ap, type))))
601
#else
602
# define GET_ARG(n, ap, type) (va_arg (ap, type))
603
#endif
604
 
605
        /*
606
         * To extend shorts properly, we need both signed and unsigned
607
         * argument extraction methods.
608
         */
609
#ifndef _NO_LONGLONG
610
#define SARG() \
611
        (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
612
            flags&LONGINT ? GET_ARG (N, ap, long) : \
613
            flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
614
            flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
615
            (long)GET_ARG (N, ap, int))
616
#define UARG() \
617
        (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
618
            flags&LONGINT ? GET_ARG (N, ap, u_long) : \
619
            flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
620
            flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
621
            (u_long)GET_ARG (N, ap, u_int))
622
#else
623
#define SARG() \
624
        (flags&LONGINT ? GET_ARG (N, ap, long) : \
625
            flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
626
            flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
627
            (long)GET_ARG (N, ap, int))
628
#define UARG() \
629
        (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
630
            flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
631
            flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
632
            (u_long)GET_ARG (N, ap, u_int))
633
#endif
634
 
635
#ifndef STRING_ONLY
636
        /* Initialize std streams if not dealing with sprintf family.  */
637
        CHECK_INIT (data, fp);
638
        _flockfile (fp);
639
 
640
        ORIENT(fp, -1);
641
 
642
        /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
643
        if (cantwrite (data, fp)) {
644
                _funlockfile (fp);
645
                return (EOF);
646
        }
647
 
648
        /* optimise fprintf(stderr) (and other unbuffered Unix files) */
649
        if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
650
            fp->_file >= 0) {
651
                _funlockfile (fp);
652
                return (__sbprintf (data, fp, fmt0, ap));
653
        }
654
#else /* STRING_ONLY */
655
        /* Create initial buffer if we are called by asprintf family.  */
656
        if (fp->_flags & __SMBF && !fp->_bf._base)
657
        {
658
                fp->_bf._base = fp->_p = _malloc_r (data, 64);
659
                if (!fp->_p)
660
                {
661
                        data->_errno = ENOMEM;
662
                        return EOF;
663
                }
664
                fp->_bf._size = 64;
665
        }
666
#endif /* STRING_ONLY */
667
 
668
        fmt = (char *)fmt0;
669
        uio.uio_iov = iovp = iov;
670
        uio.uio_resid = 0;
671
        uio.uio_iovcnt = 0;
672
        ret = 0;
673
#ifndef _NO_POS_ARGS
674
        arg_index = 0;
675
        saved_fmt = NULL;
676
        arg_type[0] = -1;
677
        numargs = 0;
678
        is_pos_arg = 0;
679
#endif
680
 
681
        /*
682
         * Scan the format for conversions (`%' character).
683
         */
684
        for (;;) {
685
                cp = fmt;
686
#ifdef _MB_CAPABLE
687
                while ((n = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &state)) > 0) {
688
                    if (wc == '%')
689
                        break;
690
                    fmt += n;
691
                }
692
#else
693
                while (*fmt != '\0' && *fmt != '%')
694
                    fmt += 1;
695
#endif
696
                if ((m = fmt - cp) != 0) {
697
                        PRINT (cp, m);
698
                        ret += m;
699
                }
700
#ifdef _MB_CAPABLE
701
                if (n <= 0)
702
                    goto done;
703
#else
704
                if (*fmt == '\0')
705
                    goto done;
706
#endif
707
                fmt_anchor = fmt;
708
                fmt++;          /* skip over '%' */
709
 
710
                flags = 0;
711
                dprec = 0;
712
                width = 0;
713
                prec = -1;
714
                sign = '\0';
715
#ifndef _NO_POS_ARGS
716
                N = arg_index;
717
                is_pos_arg = 0;
718
#endif
719
 
720
rflag:          ch = *fmt++;
721
reswitch:       switch (ch) {
722
#ifdef _WANT_IO_C99_FORMATS
723
                case '\'':
724
                  /* The ' flag is required by POSIX, but not C99.
725
                     In the C locale, LC_NUMERIC requires
726
                     thousands_sep to be the empty string.  And since
727
                     no other locales are supported (yet), this flag
728
                     is currently a no-op.  */
729
                  goto rflag;
730
#endif
731
                case ' ':
732
                        /*
733
                         * ``If the space and + flags both appear, the space
734
                         * flag will be ignored.''
735
                         *      -- ANSI X3J11
736
                         */
737
                        if (!sign)
738
                                sign = ' ';
739
                        goto rflag;
740
                case '#':
741
                        flags |= ALT;
742
                        goto rflag;
743
                case '*':
744
#ifndef _NO_POS_ARGS
745
                        /* we must check for positional arg used for dynamic width */
746
                        n = N;
747
                        old_is_pos_arg = is_pos_arg;
748
                        is_pos_arg = 0;
749
                        if (is_digit (*fmt)) {
750
                                char *old_fmt = fmt;
751
 
752
                                n = 0;
753
                                ch = *fmt++;
754
                                do {
755
                                        n = 10 * n + to_digit (ch);
756
                                        ch = *fmt++;
757
                                } while (is_digit (ch));
758
 
759
                                if (ch == '$') {
760
                                        if (n <= MAX_POS_ARGS) {
761
                                                n -= 1;
762
                                                is_pos_arg = 1;
763
                                        }
764
                                        else
765
                                                goto error;
766
                                }
767
                                else {
768
                                        fmt = old_fmt;
769
                                        goto rflag;
770
                                }
771
                        }
772
#endif /* !_NO_POS_ARGS */
773
 
774
                        /*
775
                         * ``A negative field width argument is taken as a
776
                         * - flag followed by a positive field width.''
777
                         *      -- ANSI X3J11
778
                         * They don't exclude field widths read from args.
779
                         */
780
                        width = GET_ARG (n, ap, int);
781
#ifndef _NO_POS_ARGS
782
                        is_pos_arg = old_is_pos_arg;
783
#endif
784
                        if (width >= 0)
785
                                goto rflag;
786
                        width = -width;
787
                        /* FALLTHROUGH */
788
                case '-':
789
                        flags |= LADJUST;
790
                        goto rflag;
791
                case '+':
792
                        sign = '+';
793
                        goto rflag;
794
                case '.':
795
                        if ((ch = *fmt++) == '*') {
796
#ifndef _NO_POS_ARGS
797
                                /* we must check for positional arg used for dynamic width */
798
                                n = N;
799
                                old_is_pos_arg = is_pos_arg;
800
                                is_pos_arg = 0;
801
                                if (is_digit (*fmt)) {
802
                                        char *old_fmt = fmt;
803
 
804
                                        n = 0;
805
                                        ch = *fmt++;
806
                                        do {
807
                                                n = 10 * n + to_digit (ch);
808
                                                ch = *fmt++;
809
                                        } while (is_digit (ch));
810
 
811
                                        if (ch == '$') {
812
                                                if (n <= MAX_POS_ARGS) {
813
                                                        n -= 1;
814
                                                        is_pos_arg = 1;
815
                                                }
816
                                                else
817
                                                        goto error;
818
                                        }
819
                                        else {
820
                                                fmt = old_fmt;
821
                                                goto rflag;
822
                                        }
823
                                }
824
#endif /* !_NO_POS_ARGS */
825
                                prec = GET_ARG (n, ap, int);
826
#ifndef _NO_POS_ARGS
827
                                is_pos_arg = old_is_pos_arg;
828
#endif
829
                                if (prec < 0)
830
                                        prec = -1;
831
                                goto rflag;
832
                        }
833
                        n = 0;
834
                        while (is_digit (ch)) {
835
                                n = 10 * n + to_digit (ch);
836
                                ch = *fmt++;
837
                        }
838
                        prec = n < 0 ? -1 : n;
839
                        goto reswitch;
840
                case '0':
841
                        /*
842
                         * ``Note that 0 is taken as a flag, not as the
843
                         * beginning of a field width.''
844
                         *      -- ANSI X3J11
845
                         */
846
                        flags |= ZEROPAD;
847
                        goto rflag;
848
                case '1': case '2': case '3': case '4':
849
                case '5': case '6': case '7': case '8': case '9':
850
                        n = 0;
851
                        do {
852
                                n = 10 * n + to_digit (ch);
853
                                ch = *fmt++;
854
                        } while (is_digit (ch));
855
#ifndef _NO_POS_ARGS
856
                        if (ch == '$') {
857
                                if (n <= MAX_POS_ARGS) {
858
                                        N = n - 1;
859
                                        is_pos_arg = 1;
860
                                        goto rflag;
861
                                }
862
                                else
863
                                        goto error;
864
                        }
865
#endif /* !_NO_POS_ARGS */
866
                        width = n;
867
                        goto reswitch;
868
#ifdef FLOATING_POINT
869
                case 'L':
870
                        flags |= LONGDBL;
871
                        goto rflag;
872
#endif
873
                case 'h':
874
#ifdef _WANT_IO_C99_FORMATS
875
                        if (*fmt == 'h') {
876
                                fmt++;
877
                                flags |= CHARINT;
878
                        } else
879
#endif
880
                                flags |= SHORTINT;
881
                        goto rflag;
882
                case 'l':
883
#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
884
                        if (*fmt == 'l') {
885
                                fmt++;
886
                                flags |= QUADINT;
887
                        } else
888
#endif
889
                                flags |= LONGINT;
890
                        goto rflag;
891
                case 'q': /* extension */
892
                        flags |= QUADINT;
893
                        goto rflag;
894
#ifdef _WANT_IO_C99_FORMATS
895
                case 'j':
896
                  if (sizeof (intmax_t) == sizeof (long))
897
                    flags |= LONGINT;
898
                  else
899
                    flags |= QUADINT;
900
                  goto rflag;
901
                case 'z':
902
                  if (sizeof (size_t) < sizeof (int))
903
                    /* POSIX states size_t is 16 or more bits, as is short.  */
904
                    flags |= SHORTINT;
905
                  else if (sizeof (size_t) == sizeof (int))
906
                    /* no flag needed */;
907
                  else if (sizeof (size_t) <= sizeof (long))
908
                    flags |= LONGINT;
909
                  else
910
                    /* POSIX states that at least one programming
911
                       environment must support size_t no wider than
912
                       long, but that means other environments can
913
                       have size_t as wide as long long.  */
914
                    flags |= QUADINT;
915
                  goto rflag;
916
                case 't':
917
                  if (sizeof (ptrdiff_t) < sizeof (int))
918
                    /* POSIX states ptrdiff_t is 16 or more bits, as
919
                       is short.  */
920
                    flags |= SHORTINT;
921
                  else if (sizeof (ptrdiff_t) == sizeof (int))
922
                    /* no flag needed */;
923
                  else if (sizeof (ptrdiff_t) <= sizeof (long))
924
                    flags |= LONGINT;
925
                  else
926
                    /* POSIX states that at least one programming
927
                       environment must support ptrdiff_t no wider than
928
                       long, but that means other environments can
929
                       have ptrdiff_t as wide as long long.  */
930
                    flags |= QUADINT;
931
                  goto rflag;
932
                case 'C':
933
#endif /* _WANT_IO_C99_FORMATS */
934
                case 'c':
935
                        cp = buf;
936
#ifdef _MB_CAPABLE
937
                        if (ch == 'C' || (flags & LONGINT)) {
938
                                mbstate_t ps;
939
 
940
                                memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
941
                                if ((size = (int)_wcrtomb_r (data, cp,
942
                                               (wchar_t)GET_ARG (N, ap, wint_t),
943
                                                &ps)) == -1) {
944
                                        fp->_flags |= __SERR;
945
                                        goto error;
946
                                }
947
                        }
948
                        else
949
#endif /* _MB_CAPABLE */
950
                        {
951
                                *cp = GET_ARG (N, ap, int);
952
                                size = 1;
953
                        }
954
                        sign = '\0';
955
                        break;
956
                case 'D':  /* extension */
957
                        flags |= LONGINT;
958
                        /*FALLTHROUGH*/
959
                case 'd':
960
                case 'i':
961
                        _uquad = SARG ();
962
#ifndef _NO_LONGLONG
963
                        if ((quad_t)_uquad < 0)
964
#else
965
                        if ((long) _uquad < 0)
966
#endif
967
                        {
968
 
969
                                _uquad = -_uquad;
970
                                sign = '-';
971
                        }
972
                        base = DEC;
973
                        goto number;
974
#ifdef FLOATING_POINT
975
# ifdef _WANT_IO_C99_FORMATS
976
                case 'a':
977
                case 'A':
978
                case 'F':
979
# endif
980
                case 'e':
981
                case 'E':
982
                case 'f':
983
                case 'g':
984
                case 'G':
985
# ifdef _NO_LONGDBL
986
                        if (flags & LONGDBL) {
987
                                _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
988
                        } else {
989
                                _fpvalue = GET_ARG (N, ap, double);
990
                        }
991
 
992
                        /* do this before tricky precision changes
993
 
994
                           If the output is infinite or NaN, leading
995
                           zeros are not permitted.  Otherwise, scanf
996
                           could not read what printf wrote.
997
                         */
998
                        if (isinf (_fpvalue)) {
999
                                if (_fpvalue < 0)
1000
                                        sign = '-';
1001
                                if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1002
                                        cp = "INF";
1003
                                else
1004
                                        cp = "inf";
1005
                                size = 3;
1006
                                flags &= ~ZEROPAD;
1007
                                break;
1008
                        }
1009
                        if (isnan (_fpvalue)) {
1010
                                if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1011
                                        cp = "NAN";
1012
                                else
1013
                                        cp = "nan";
1014
                                size = 3;
1015
                                flags &= ~ZEROPAD;
1016
                                break;
1017
                        }
1018
 
1019
# else /* !_NO_LONGDBL */
1020
 
1021
                        if (flags & LONGDBL) {
1022
                                _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1023
                        } else {
1024
                                _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1025
                        }
1026
 
1027
                        /* do this before tricky precision changes */
1028
                        expt = _ldcheck (&_fpvalue);
1029
                        if (expt == 2) {
1030
                                if (_fpvalue < 0)
1031
                                        sign = '-';
1032
                                if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1033
                                        cp = "INF";
1034
                                else
1035
                                        cp = "inf";
1036
                                size = 3;
1037
                                flags &= ~ZEROPAD;
1038
                                break;
1039
                        }
1040
                        if (expt == 1) {
1041
                                if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1042
                                        cp = "NAN";
1043
                                else
1044
                                        cp = "nan";
1045
                                size = 3;
1046
                                flags &= ~ZEROPAD;
1047
                                break;
1048
                        }
1049
# endif /* !_NO_LONGDBL */
1050
 
1051
# ifdef _WANT_IO_C99_FORMATS
1052
                        if (ch == 'a' || ch == 'A') {
1053
                                ox[0] = '0';
1054
                                ox[1] = ch == 'a' ? 'x' : 'X';
1055
                                flags |= HEXPREFIX;
1056
                                if (prec >= BUF)
1057
                                  {
1058
                                    if ((malloc_buf =
1059
                                         (char *)_malloc_r (data, prec + 1))
1060
                                        == NULL)
1061
                                      {
1062
                                        fp->_flags |= __SERR;
1063
                                        goto error;
1064
                                      }
1065
                                    cp = malloc_buf;
1066
                                  }
1067
                                else
1068
                                  cp = buf;
1069
                        } else
1070
# endif /* _WANT_IO_C99_FORMATS */
1071
                        if (prec == -1) {
1072
                                prec = DEFPREC;
1073
                        } else if ((ch == 'g' || ch == 'G') && prec == 0) {
1074
                                prec = 1;
1075
                        }
1076
 
1077
                        flags |= FPT;
1078
 
1079
                        cp = cvt (data, _fpvalue, prec, flags, &softsign,
1080
                                  &expt, ch, &ndig, cp);
1081
 
1082
                        if (ch == 'g' || ch == 'G') {
1083
                                if (expt <= -4 || expt > prec)
1084
                                        ch -= 2; /* 'e' or 'E' */
1085
                                else
1086
                                        ch = 'g';
1087
                        }
1088
# ifdef _WANT_IO_C99_FORMATS
1089
                        else if (ch == 'F')
1090
                                ch = 'f';
1091
# endif
1092
                        if (ch <= 'e') {        /* 'a', 'A', 'e', or 'E' fmt */
1093
                                --expt;
1094
                                expsize = exponent (expstr, expt, ch);
1095
                                size = expsize + ndig;
1096
                                if (ndig > 1 || flags & ALT)
1097
                                        ++size;
1098
                        } else if (ch == 'f') {         /* f fmt */
1099
                                if (expt > 0) {
1100
                                        size = expt;
1101
                                        if (prec || flags & ALT)
1102
                                                size += prec + 1;
1103
                                } else  /* "0.X" */
1104
                                        size = (prec || flags & ALT)
1105
                                                  ? prec + 2
1106
                                                  : 1;
1107
                        } else if (expt >= ndig) {      /* fixed g fmt */
1108
                                size = expt;
1109
                                if (flags & ALT)
1110
                                        ++size;
1111
                        } else
1112
                                size = ndig + (expt > 0 ?
1113
                                        1 : 2 - expt);
1114
 
1115
                        if (softsign)
1116
                                sign = '-';
1117
                        break;
1118
#endif /* FLOATING_POINT */
1119
                case 'n':
1120
#ifndef _NO_LONGLONG
1121
                        if (flags & QUADINT)
1122
                                *GET_ARG (N, ap, quad_ptr_t) = ret;
1123
                        else
1124
#endif
1125
                        if (flags & LONGINT)
1126
                                *GET_ARG (N, ap, long_ptr_t) = ret;
1127
                        else if (flags & SHORTINT)
1128
                                *GET_ARG (N, ap, short_ptr_t) = ret;
1129
#ifdef _WANT_IO_C99_FORMATS
1130
                        else if (flags & CHARINT)
1131
                                *GET_ARG (N, ap, char_ptr_t) = ret;
1132
#endif
1133
                        else
1134
                                *GET_ARG (N, ap, int_ptr_t) = ret;
1135
                        continue;       /* no output */
1136
                case 'O': /* extension */
1137
                        flags |= LONGINT;
1138
                        /*FALLTHROUGH*/
1139
                case 'o':
1140
                        _uquad = UARG ();
1141
                        base = OCT;
1142
                        goto nosign;
1143
                case 'p':
1144
                        /*
1145
                         * ``The argument shall be a pointer to void.  The
1146
                         * value of the pointer is converted to a sequence
1147
                         * of printable characters, in an implementation-
1148
                         * defined manner.''
1149
                         *      -- ANSI X3J11
1150
                         */
1151
                        /* NOSTRICT */
1152
                        _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1153
                        base = HEX;
1154
                        xdigs = "0123456789abcdef";
1155
                        flags |= HEXPREFIX;
1156
                        ox[0] = '0';
1157
                        ox[1] = ch = 'x';
1158
                        goto nosign;
1159
                case 's':
1160
#ifdef _WANT_IO_C99_FORMATS
1161
                case 'S':
1162
#endif
1163
                        sign = '\0';
1164
                        cp = GET_ARG (N, ap, char_ptr_t);
1165
#ifndef __OPTIMIZE_SIZE__
1166
                        /* Behavior is undefined if the user passed a
1167
                           NULL string when precision is not 0.
1168
                           However, if we are not optimizing for size,
1169
                           we might as well mirror glibc behavior.  */
1170
                        if (cp == NULL) {
1171
                                cp = "(null)";
1172
                                size = ((unsigned) prec > 6U) ? 6 : prec;
1173
                        }
1174
                        else
1175
#endif /* __OPTIMIZE_SIZE__ */
1176
#ifdef _MB_CAPABLE
1177
                        if (ch == 'S' || (flags & LONGINT)) {
1178
                                mbstate_t ps;
1179
                                _CONST wchar_t *wcp;
1180
 
1181
                                wcp = (_CONST wchar_t *)cp;
1182
                                size = m = 0;
1183
                                memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1184
 
1185
                                /* Count number of bytes needed for multibyte
1186
                                   string that will be produced from widechar
1187
                                   string.  */
1188
                                if (prec >= 0) {
1189
                                        while (1) {
1190
                                                if (wcp[m] == L'\0')
1191
                                                        break;
1192
                                                if ((n = (int)_wcrtomb_r (data,
1193
                                                     buf, wcp[m], &ps)) == -1) {
1194
                                                        fp->_flags |= __SERR;
1195
                                                        goto error;
1196
                                                }
1197
                                                if (n + size > prec)
1198
                                                        break;
1199
                                                m += 1;
1200
                                                size += n;
1201
                                                if (size == prec)
1202
                                                        break;
1203
                                        }
1204
                                }
1205
                                else {
1206
                                        if ((size = (int)_wcsrtombs_r (data,
1207
                                                   NULL, &wcp, 0, &ps)) == -1) {
1208
                                                fp->_flags |= __SERR;
1209
                                                goto error;
1210
                                        }
1211
                                        wcp = (_CONST wchar_t *)cp;
1212
                                }
1213
 
1214
                                if (size == 0)
1215
                                        break;
1216
 
1217
                                if (size >= BUF) {
1218
                                        if ((malloc_buf =
1219
                                             (char *)_malloc_r (data, size + 1))
1220
                                            == NULL) {
1221
                                                fp->_flags |= __SERR;
1222
                                                goto error;
1223
                                        }
1224
                                        cp = malloc_buf;
1225
                                } else
1226
                                        cp = buf;
1227
 
1228
                                /* Convert widechar string to multibyte string. */
1229
                                memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1230
                                if (_wcsrtombs_r (data, cp, &wcp, size, &ps)
1231
                                    != size) {
1232
                                        fp->_flags |= __SERR;
1233
                                        goto error;
1234
                                }
1235
                                cp[size] = '\0';
1236
                        }
1237
                        else
1238
#endif /* _MB_CAPABLE */
1239
                        if (prec >= 0) {
1240
                                /*
1241
                                 * can't use strlen; can only look for the
1242
                                 * NUL in the first `prec' characters, and
1243
                                 * strlen () will go further.
1244
                                 */
1245
                                char *p = memchr (cp, 0, prec);
1246
 
1247
                                if (p != NULL) {
1248
                                        size = p - cp;
1249
                                        if (size > prec)
1250
                                                size = prec;
1251
                                } else
1252
                                        size = prec;
1253
                        } else
1254
                                size = strlen (cp);
1255
 
1256
                        break;
1257
                case 'U': /* extension */
1258
                        flags |= LONGINT;
1259
                        /*FALLTHROUGH*/
1260
                case 'u':
1261
                        _uquad = UARG ();
1262
                        base = DEC;
1263
                        goto nosign;
1264
                case 'X':
1265
                        xdigs = "0123456789ABCDEF";
1266
                        goto hex;
1267
                case 'x':
1268
                        xdigs = "0123456789abcdef";
1269
hex:                    _uquad = UARG ();
1270
                        base = HEX;
1271
                        /* leading 0x/X only if non-zero */
1272
                        if (flags & ALT && _uquad != 0) {
1273
                                ox[0] = '0';
1274
                                ox[1] = ch;
1275
                                flags |= HEXPREFIX;
1276
                        }
1277
 
1278
                        /* unsigned conversions */
1279
nosign:                 sign = '\0';
1280
                        /*
1281
                         * ``... diouXx conversions ... if a precision is
1282
                         * specified, the 0 flag will be ignored.''
1283
                         *      -- ANSI X3J11
1284
                         */
1285
number:                 if ((dprec = prec) >= 0)
1286
                                flags &= ~ZEROPAD;
1287
 
1288
                        /*
1289
                         * ``The result of converting a zero value with an
1290
                         * explicit precision of zero is no characters.''
1291
                         *      -- ANSI X3J11
1292
                         */
1293
                        cp = buf + BUF;
1294
                        if (_uquad != 0 || prec != 0) {
1295
                                /*
1296
                                 * Unsigned mod is hard, and unsigned mod
1297
                                 * by a constant is easier than that by
1298
                                 * a variable; hence this switch.
1299
                                 */
1300
                                switch (base) {
1301
                                case OCT:
1302
                                        do {
1303
                                                *--cp = to_char (_uquad & 7);
1304
                                                _uquad >>= 3;
1305
                                        } while (_uquad);
1306
                                        /* handle octal leading 0 */
1307
                                        if (flags & ALT && *cp != '0')
1308
                                                *--cp = '0';
1309
                                        break;
1310
 
1311
                                case DEC:
1312
                                        /* many numbers are 1 digit */
1313
                                        while (_uquad >= 10) {
1314
                                                *--cp = to_char (_uquad % 10);
1315
                                                _uquad /= 10;
1316
                                        }
1317
                                        *--cp = to_char (_uquad);
1318
                                        break;
1319
 
1320
                                case HEX:
1321
                                        do {
1322
                                                *--cp = xdigs[_uquad & 15];
1323
                                                _uquad >>= 4;
1324
                                        } while (_uquad);
1325
                                        break;
1326
 
1327
                                default:
1328
                                        cp = "bug in vfprintf: bad base";
1329
                                        size = strlen (cp);
1330
                                        goto skipsize;
1331
                                }
1332
                        }
1333
                       /*
1334
                        * ...result is to be converted to an 'alternate form'.
1335
                        * For o conversion, it increases the precision to force
1336
                        * the first digit of the result to be a zero."
1337
                        *     -- ANSI X3J11
1338
                        *
1339
                        * To demonstrate this case, compile and run:
1340
                        *    printf ("%#.0o",0);
1341
                        */
1342
                       else if (base == OCT && (flags & ALT))
1343
                         *--cp = '0';
1344
 
1345
                        size = buf + BUF - cp;
1346
                skipsize:
1347
                        break;
1348
                default:        /* "%?" prints ?, unless ? is NUL */
1349
                        if (ch == '\0')
1350
                                goto done;
1351
                        /* pretend it was %c with argument ch */
1352
                        cp = buf;
1353
                        *cp = ch;
1354
                        size = 1;
1355
                        sign = '\0';
1356
                        break;
1357
                }
1358
 
1359
                /*
1360
                 * All reasonable formats wind up here.  At this point, `cp'
1361
                 * points to a string which (if not flags&LADJUST) should be
1362
                 * padded out to `width' places.  If flags&ZEROPAD, it should
1363
                 * first be prefixed by any sign or other prefix; otherwise,
1364
                 * it should be blank padded before the prefix is emitted.
1365
                 * After any left-hand padding and prefixing, emit zeroes
1366
                 * required by a decimal [diouxX] precision, then print the
1367
                 * string proper, then emit zeroes required by any leftover
1368
                 * floating precision; finally, if LADJUST, pad with blanks.
1369
                 * If flags&FPT, ch must be in [aAeEfg].
1370
                 *
1371
                 * Compute actual size, so we know how much to pad.
1372
                 * size excludes decimal prec; realsz includes it.
1373
                 */
1374
                realsz = dprec > size ? dprec : size;
1375
                if (sign)
1376
                        realsz++;
1377
                if (flags & HEXPREFIX)
1378
                        realsz+= 2;
1379
 
1380
                /* right-adjusting blank padding */
1381
                if ((flags & (LADJUST|ZEROPAD)) == 0)
1382
                        PAD (width - realsz, blanks);
1383
 
1384
                /* prefix */
1385
                if (sign)
1386
                        PRINT (&sign, 1);
1387
                if (flags & HEXPREFIX)
1388
                        PRINT (ox, 2);
1389
 
1390
                /* right-adjusting zero padding */
1391
                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1392
                        PAD (width - realsz, zeroes);
1393
 
1394
                /* leading zeroes from decimal precision */
1395
                PAD (dprec - size, zeroes);
1396
 
1397
                /* the string or number proper */
1398
#ifdef FLOATING_POINT
1399
                if ((flags & FPT) == 0) {
1400
                        PRINT (cp, size);
1401
                } else {        /* glue together f_p fragments */
1402
                        if (ch >= 'f') {        /* 'f' or 'g' */
1403
                                if (_fpvalue == 0) {
1404
                                        /* kludge for __dtoa irregularity */
1405
                                        PRINT ("0", 1);
1406
                                        if (expt < ndig || flags & ALT) {
1407
                                                PRINT (decimal_point, 1);
1408
                                                PAD (ndig - 1, zeroes);
1409
                                        }
1410
                                } else if (expt <= 0) {
1411
                                        PRINT ("0", 1);
1412
                                        if (expt || ndig || flags & ALT) {
1413
                                                PRINT (decimal_point, 1);
1414
                                                PAD (-expt, zeroes);
1415
                                                PRINT (cp, ndig);
1416
                                        }
1417
                                } else if (expt >= ndig) {
1418
                                        PRINT (cp, ndig);
1419
                                        PAD (expt - ndig, zeroes);
1420
                                        if (flags & ALT)
1421
                                                PRINT (decimal_point, 1);
1422
                                } else {
1423
                                        PRINT (cp, expt);
1424
                                        cp += expt;
1425
                                        PRINT (decimal_point, 1);
1426
                                        PRINT (cp, ndig - expt);
1427
                                }
1428
                        } else {        /* 'a', 'A', 'e', or 'E' */
1429
                                if (ndig > 1 || flags & ALT) {
1430
                                        PRINT (cp, 1);
1431
                                        cp++;
1432
                                        PRINT (decimal_point, 1);
1433
                                        if (_fpvalue) {
1434
                                                PRINT (cp, ndig - 1);
1435
                                        } else  /* 0.[0..] */
1436
                                                /* __dtoa irregularity */
1437
                                                PAD (ndig - 1, zeroes);
1438
                                } else  /* XeYYY */
1439
                                        PRINT (cp, 1);
1440
                                PRINT (expstr, expsize);
1441
                        }
1442
                }
1443
#else /* !FLOATING_POINT */
1444
                PRINT (cp, size);
1445
#endif
1446
                /* left-adjusting padding (always blank) */
1447
                if (flags & LADJUST)
1448
                        PAD (width - realsz, blanks);
1449
 
1450
                /* finally, adjust ret */
1451
                ret += width > realsz ? width : realsz;
1452
 
1453
                FLUSH ();       /* copy out the I/O vectors */
1454
 
1455
                if (malloc_buf != NULL) {
1456
                        _free_r (data, malloc_buf);
1457
                        malloc_buf = NULL;
1458
                }
1459
        }
1460
done:
1461
        FLUSH ();
1462
error:
1463
        if (malloc_buf != NULL)
1464
                _free_r (data, malloc_buf);
1465
#ifndef STRING_ONLY
1466
        _funlockfile (fp);
1467
#endif
1468
        return (__sferror (fp) ? EOF : ret);
1469
        /* NOTREACHED */
1470
}
1471
 
1472
#ifdef FLOATING_POINT
1473
 
1474
/* Using reentrant DATA, convert finite VALUE into a string of digits
1475
   with no decimal point, using NDIGITS precision and FLAGS as guides
1476
   to whether trailing zeros must be included.  Set *SIGN to nonzero
1477
   if VALUE was negative.  Set *DECPT to the exponent plus one.  Set
1478
   *LENGTH to the length of the returned string.  CH must be one of
1479
   [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1480
   otherwise the return value shares the mprec reentrant storage.  */
1481
static char *
1482
cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1483
    char *sign, int *decpt, int ch, int *length, char *buf)
1484
{
1485
        int mode, dsgn;
1486
        char *digits, *bp, *rve;
1487
# ifdef _NO_LONGDBL
1488
        union double_union tmp;
1489
 
1490
        tmp.d = value;
1491
        if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1492
                value = -value;
1493
                *sign = '-';
1494
        } else
1495
                *sign = '\000';
1496
# else /* !_NO_LONGDBL */
1497
        union
1498
        {
1499
          struct ldieee ieee;
1500
          _LONG_DOUBLE val;
1501
        } ld;
1502
 
1503
        ld.val = value;
1504
        if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1505
                value = -value;
1506
                *sign = '-';
1507
        } else
1508
                *sign = '\000';
1509
# endif /* !_NO_LONGDBL */
1510
 
1511
# ifdef _WANT_IO_C99_FORMATS
1512
        if (ch == 'a' || ch == 'A') {
1513
                /* This code assumes FLT_RADIX is a power of 2.  The initial
1514
                   division ensures the digit before the decimal will be less
1515
                   than FLT_RADIX (unless it is rounded later).  There is no
1516
                   loss of precision in these calculations.  */
1517
                value = FREXP (value, decpt) / 8;
1518
                if (!value)
1519
                        *decpt = 1;
1520
                digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1521
                bp = buf;
1522
                do {
1523
                        value *= 16;
1524
                        mode = (int) value;
1525
                        value -= mode;
1526
                        *bp++ = digits[mode];
1527
                } while (ndigits-- && value);
1528
                if (value > 0.5 || (value == 0.5 && mode & 1)) {
1529
                        /* round to even */
1530
                        rve = bp;
1531
                        while (*--rve == digits[0xf]) {
1532
                                *rve = '0';
1533
                        }
1534
                        *rve = *rve == '9' ? digits[0xa] : *rve + 1;
1535
                } else {
1536
                        while (ndigits-- >= 0) {
1537
                                *bp++ = '0';
1538
                        }
1539
                }
1540
                *length = bp - buf;
1541
                return buf;
1542
        }
1543
# endif /* _WANT_IO_C99_FORMATS */
1544
        if (ch == 'f' || ch == 'F') {
1545
                mode = 3;               /* ndigits after the decimal point */
1546
        } else {
1547
                /* To obtain ndigits after the decimal point for the 'e'
1548
                 * and 'E' formats, round to ndigits + 1 significant
1549
                 * figures.
1550
                 */
1551
                if (ch == 'e' || ch == 'E') {
1552
                        ndigits++;
1553
                }
1554
                mode = 2;               /* ndigits significant digits */
1555
        }
1556
 
1557
        digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve);
1558
 
1559
        if ((ch != 'g' && ch != 'G') || flags & ALT) {  /* Print trailing zeros */
1560
                bp = digits + ndigits;
1561
                if (ch == 'f' || ch == 'F') {
1562
                        if (*digits == '0' && value)
1563
                                *decpt = -ndigits + 1;
1564
                        bp += *decpt;
1565
                }
1566
                if (value == 0)  /* kludge for __dtoa irregularity */
1567
                        rve = bp;
1568
                while (rve < bp)
1569
                        *rve++ = '0';
1570
        }
1571
        *length = rve - digits;
1572
        return (digits);
1573
}
1574
 
1575
static int
1576
exponent(char *p0, int exp, int fmtch)
1577
{
1578
        register char *p, *t;
1579
        char expbuf[MAXEXPLEN];
1580
# ifdef _WANT_IO_C99_FORMATS
1581
        int isa = fmtch == 'a' || fmtch == 'A';
1582
# else
1583
#  define isa 0
1584
# endif
1585
 
1586
        p = p0;
1587
        *p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1588
        if (exp < 0) {
1589
                exp = -exp;
1590
                *p++ = '-';
1591
        }
1592
        else
1593
                *p++ = '+';
1594
        t = expbuf + MAXEXPLEN;
1595
        if (exp > 9) {
1596
                do {
1597
                        *--t = to_char (exp % 10);
1598
                } while ((exp /= 10) > 9);
1599
                *--t = to_char (exp);
1600
                for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1601
        }
1602
        else {
1603
                if (!isa)
1604
                        *p++ = '0';
1605
                *p++ = to_char (exp);
1606
        }
1607
        return (p - p0);
1608
}
1609
#endif /* FLOATING_POINT */
1610
 
1611
 
1612
#ifndef _NO_POS_ARGS
1613
 
1614
/* Positional argument support.
1615
   Written by Jeff Johnston
1616
 
1617
   Copyright (c) 2002 Red Hat Incorporated.
1618
   All rights reserved.
1619
 
1620
   Redistribution and use in source and binary forms, with or without
1621
   modification, are permitted provided that the following conditions are met:
1622
 
1623
      Redistributions of source code must retain the above copyright
1624
      notice, this list of conditions and the following disclaimer.
1625
 
1626
      Redistributions in binary form must reproduce the above copyright
1627
      notice, this list of conditions and the following disclaimer in the
1628
      documentation and/or other materials provided with the distribution.
1629
 
1630
      The name of Red Hat Incorporated may not be used to endorse
1631
      or promote products derived from this software without specific
1632
      prior written permission.
1633
 
1634
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1635
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1636
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1637
   DISCLAIMED.  IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1638
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1639
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1640
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1641
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1642
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1643
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1644
 
1645
typedef enum {
1646
  ZERO,   /* '0' */
1647
  DIGIT,  /* '1-9' */
1648
  DOLLAR, /* '$' */
1649
  MODFR,  /* spec modifier */
1650
  SPEC,   /* format specifier */
1651
  DOT,    /* '.' */
1652
  STAR,   /* '*' */
1653
  FLAG,   /* format flag */
1654
  OTHER,  /* all other chars */
1655
  MAX_CH_CLASS /* place-holder */
1656
} CH_CLASS;
1657
 
1658
typedef enum {
1659
  START,  /* start */
1660
  SFLAG,  /* seen a flag */
1661
  WDIG,   /* seen digits in width area */
1662
  WIDTH,  /* processed width */
1663
  SMOD,   /* seen spec modifier */
1664
  SDOT,   /* seen dot */
1665
  VARW,   /* have variable width specifier */
1666
  VARP,   /* have variable precision specifier */
1667
  PREC,   /* processed precision */
1668
  VWDIG,  /* have digits in variable width specification */
1669
  VPDIG,  /* have digits in variable precision specification */
1670
  DONE,   /* done */
1671
  MAX_STATE, /* place-holder */
1672
} STATE;
1673
 
1674
typedef enum {
1675
  NOOP,  /* do nothing */
1676
  NUMBER, /* build a number from digits */
1677
  SKIPNUM, /* skip over digits */
1678
  GETMOD,  /* get and process format modifier */
1679
  GETARG,  /* get and process argument */
1680
  GETPW,   /* get variable precision or width */
1681
  GETPWB,  /* get variable precision or width and pushback fmt char */
1682
  GETPOS,  /* get positional parameter value */
1683
  PWPOS,   /* get positional parameter value for variable width or precision */
1684
} ACTION;
1685
 
1686
_CONST static CH_CLASS chclass[256] = {
1687
  /* 00-07 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1688
  /* 08-0f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1689
  /* 10-17 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1690
  /* 18-1f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1691
  /* 20-27 */  FLAG,    OTHER,   OTHER,   FLAG,    DOLLAR,  OTHER,   OTHER,   FLAG,
1692
  /* 28-2f */  OTHER,   OTHER,   STAR,    FLAG,    OTHER,   FLAG,    DOT,     OTHER,
1693
  /* 30-37 */  ZERO,    DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,   DIGIT,
1694
  /* 38-3f */  DIGIT,   DIGIT,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1695
  /* 40-47 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1696
  /* 48-4f */  OTHER,   OTHER,   OTHER,   OTHER,   MODFR,   OTHER,   OTHER,   SPEC,
1697
  /* 50-57 */  OTHER,   OTHER,   OTHER,   SPEC,    OTHER,   SPEC,    OTHER,   OTHER,
1698
  /* 58-5f */  SPEC,    OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1699
  /* 60-67 */  OTHER,   SPEC,    OTHER,   SPEC,    SPEC,    SPEC,    SPEC,    SPEC,
1700
  /* 68-6f */  MODFR,   SPEC,    MODFR,   OTHER,   MODFR,   OTHER,   SPEC,    SPEC,
1701
  /* 70-77 */  SPEC,    MODFR,   OTHER,   SPEC,    MODFR,   SPEC,    OTHER,   OTHER,
1702
  /* 78-7f */  SPEC,    OTHER,   MODFR,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1703
  /* 80-87 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1704
  /* 88-8f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1705
  /* 90-97 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1706
  /* 98-9f */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1707
  /* a0-a7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1708
  /* a8-af */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1709
  /* b0-b7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1710
  /* b8-bf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1711
  /* c0-c7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1712
  /* c8-cf */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1713
  /* d0-d7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1714
  /* d8-df */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1715
  /* e0-e7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1716
  /* e8-ef */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1717
  /* f0-f7 */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1718
  /* f8-ff */  OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,   OTHER,
1719
};
1720
 
1721
_CONST static STATE state_table[MAX_STATE][MAX_CH_CLASS] = {
1722
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
1723
  /* START */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
1724
  /* SFLAG */  { SFLAG,   WDIG,    DONE,   SMOD,    DONE,   SDOT,  VARW,   SFLAG,  DONE },
1725
  /* WDIG  */  { DONE,    DONE,    WIDTH,  SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
1726
  /* WIDTH */  { DONE,    DONE,    DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
1727
  /* SMOD  */  { DONE,    DONE,    DONE,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
1728
  /* SDOT  */  { SDOT,    PREC,    DONE,   SMOD,    DONE,   DONE,  VARP,   DONE,   DONE },
1729
  /* VARW  */  { DONE,    VWDIG,   DONE,   SMOD,    DONE,   SDOT,  DONE,   DONE,   DONE },
1730
  /* VARP  */  { DONE,    VPDIG,   DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
1731
  /* PREC  */  { DONE,    DONE,    DONE,   SMOD,    DONE,   DONE,  DONE,   DONE,   DONE },
1732
  /* VWDIG */  { DONE,    DONE,    WIDTH,  DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
1733
  /* VPDIG */  { DONE,    DONE,    PREC,   DONE,    DONE,   DONE,  DONE,   DONE,   DONE },
1734
};
1735
 
1736
_CONST static ACTION action_table[MAX_STATE][MAX_CH_CLASS] = {
1737
  /*             '0'     '1-9'     '$'     MODFR    SPEC    '.'     '*'    FLAG    OTHER */
1738
  /* START */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1739
  /* SFLAG */  { NOOP,    NUMBER,  NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1740
  /* WDIG  */  { NOOP,    NOOP,    GETPOS, GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1741
  /* WIDTH */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1742
  /* SMOD  */  { NOOP,    NOOP,    NOOP,   NOOP,    GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1743
  /* SDOT  */  { NOOP,    SKIPNUM, NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1744
  /* VARW  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, GETPW, NOOP,   NOOP,   NOOP },
1745
  /* VARP  */  { NOOP,    NUMBER,  NOOP,   GETPW,   GETPWB, NOOP,  NOOP,   NOOP,   NOOP },
1746
  /* PREC  */  { NOOP,    NOOP,    NOOP,   GETMOD,  GETARG, NOOP,  NOOP,   NOOP,   NOOP },
1747
  /* VWDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
1748
  /* VPDIG */  { NOOP,    NOOP,    PWPOS,  NOOP,    NOOP,   NOOP,  NOOP,   NOOP,   NOOP },
1749
};
1750
 
1751
/* function to get positional parameter N where n = N - 1 */
1752
static union arg_val *
1753
_DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
1754
       struct _reent *data _AND
1755
       int n               _AND
1756
       char *fmt           _AND
1757
       va_list *ap         _AND
1758
       int *numargs_p      _AND
1759
       union arg_val *args _AND
1760
       int *arg_type       _AND
1761
       char **last_fmt)
1762
{
1763
  int ch;
1764
  int number, flags;
1765
  int spec_type;
1766
  int numargs = *numargs_p;
1767
  CH_CLASS chtype;
1768
  STATE state, next_state;
1769
  ACTION action;
1770
  int pos, last_arg;
1771
  int max_pos_arg = n;
1772
  /* Only need types that can be reached via vararg promotions.  */
1773
  enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
1774
# ifdef _MB_CAPABLE
1775
  wchar_t wc;
1776
  mbstate_t wc_state;
1777
  int nbytes;
1778
# endif
1779
 
1780
  /* if this isn't the first call, pick up where we left off last time */
1781
  if (*last_fmt != NULL)
1782
    fmt = *last_fmt;
1783
 
1784
# ifdef _MB_CAPABLE
1785
  memset (&wc_state, '\0', sizeof (wc_state));
1786
# endif
1787
 
1788
  /* we need to process either to end of fmt string or until we have actually
1789
     read the desired parameter from the vararg list. */
1790
  while (*fmt && n >= numargs)
1791
    {
1792
# ifdef _MB_CAPABLE
1793
      while ((nbytes = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0)
1794
        {
1795
          fmt += nbytes;
1796
          if (wc == '%')
1797
            break;
1798
        }
1799
 
1800
      if (nbytes <= 0)
1801
        break;
1802
# else
1803
      while (*fmt != '\0' && *fmt != '%')
1804
        fmt += 1;
1805
 
1806
      if (*fmt == '\0')
1807
        break;
1808
# endif /* ! _MB_CAPABLE */
1809
      state = START;
1810
      flags = 0;
1811
      pos = -1;
1812
      number = 0;
1813
      spec_type = INT;
1814
 
1815
      /* Use state/action table to process format specifiers.  We ignore invalid
1816
         formats and we are only interested in information that tells us how to
1817
         read the vararg list. */
1818
      while (state != DONE)
1819
        {
1820
          ch = *fmt++;
1821
          chtype = chclass[ch];
1822
          next_state = state_table[state][chtype];
1823
          action = action_table[state][chtype];
1824
          state = next_state;
1825
 
1826
          switch (action)
1827
            {
1828
            case GETMOD:  /* we have format modifier */
1829
              switch (ch)
1830
                {
1831
                case 'h':
1832
                  /* No flag needed, since short and char promote to int.  */
1833
                  break;
1834
                case 'L':
1835
                  flags |= LONGDBL;
1836
                  break;
1837
                case 'q':
1838
                  flags |= QUADINT;
1839
                  break;
1840
# ifdef _WANT_IO_C99_FORMATS
1841
                case 'j':
1842
                  if (sizeof (intmax_t) == sizeof (long))
1843
                    flags |= LONGINT;
1844
                  else
1845
                    flags |= QUADINT;
1846
                  break;
1847
                case 'z':
1848
                  if (sizeof (size_t) <= sizeof (int))
1849
                    /* no flag needed */;
1850
                  else if (sizeof (size_t) <= sizeof (long))
1851
                    flags |= LONGINT;
1852
                  else
1853
                    /* POSIX states that at least one programming
1854
                       environment must support size_t no wider than
1855
                       long, but that means other environments can
1856
                       have size_t as wide as long long.  */
1857
                    flags |= QUADINT;
1858
                  break;
1859
                case 't':
1860
                  if (sizeof (ptrdiff_t) <= sizeof (int))
1861
                    /* no flag needed */;
1862
                  else if (sizeof (ptrdiff_t) <= sizeof (long))
1863
                    flags |= LONGINT;
1864
                  else
1865
                    /* POSIX states that at least one programming
1866
                       environment must support ptrdiff_t no wider than
1867
                       long, but that means other environments can
1868
                       have ptrdiff_t as wide as long long.  */
1869
                    flags |= QUADINT;
1870
                  break;
1871
# endif /* _WANT_IO_C99_FORMATS */
1872
                case 'l':
1873
                default:
1874
# if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1875
                  if (*fmt == 'l')
1876
                    {
1877
                      flags |= QUADINT;
1878
                      ++fmt;
1879
                    }
1880
                  else
1881
# endif
1882
                    flags |= LONGINT;
1883
                  break;
1884
                }
1885
              break;
1886
            case GETARG: /* we have format specifier */
1887
              {
1888
                numargs &= (MAX_POS_ARGS - 1);
1889
                /* process the specifier and translate it to a type to fetch from varargs */
1890
                switch (ch)
1891
                  {
1892
                  case 'd':
1893
                  case 'i':
1894
                  case 'o':
1895
                  case 'x':
1896
                  case 'X':
1897
                  case 'u':
1898
                    if (flags & LONGINT)
1899
                      spec_type = LONG_INT;
1900
# ifndef _NO_LONGLONG
1901
                    else if (flags & QUADINT)
1902
                      spec_type = QUAD_INT;
1903
# endif
1904
                    else
1905
                      spec_type = INT;
1906
                    break;
1907
                  case 'D':
1908
                  case 'U':
1909
                  case 'O':
1910
                    spec_type = LONG_INT;
1911
                    break;
1912
# ifdef _WANT_IO_C99_FORMATS
1913
                  case 'a':
1914
                  case 'A':
1915
                  case 'F':
1916
# endif
1917
                  case 'f':
1918
                  case 'g':
1919
                  case 'G':
1920
                  case 'E':
1921
                  case 'e':
1922
# ifndef _NO_LONGDBL
1923
                    if (flags & LONGDBL)
1924
                      spec_type = LONG_DOUBLE;
1925
                    else
1926
# endif
1927
                      spec_type = DOUBLE;
1928
                    break;
1929
                  case 's':
1930
# ifdef _WANT_IO_C99_FORMATS
1931
                  case 'S':
1932
# endif
1933
                  case 'p':
1934
                  case 'n':
1935
                    spec_type = CHAR_PTR;
1936
                    break;
1937
                  case 'c':
1938
# ifdef _WANT_IO_C99_FORMATS
1939
                    if (flags & LONGINT)
1940
                      spec_type = WIDE_CHAR;
1941
                    else
1942
# endif
1943
                      spec_type = INT;
1944
                    break;
1945
# ifdef _WANT_IO_C99_FORMATS
1946
                  case 'C':
1947
                    spec_type = WIDE_CHAR;
1948
                    break;
1949
# endif
1950
                  }
1951
 
1952
                /* if we have a positional parameter, just store the type, otherwise
1953
                   fetch the parameter from the vararg list */
1954
                if (pos != -1)
1955
                  arg_type[pos] = spec_type;
1956
                else
1957
                  {
1958
                    switch (spec_type)
1959
                      {
1960
                      case LONG_INT:
1961
                        args[numargs++].val_long = va_arg (*ap, long);
1962
                        break;
1963
                      case QUAD_INT:
1964
                        args[numargs++].val_quad_t = va_arg (*ap, quad_t);
1965
                        break;
1966
                      case WIDE_CHAR:
1967
                        args[numargs++].val_wint_t = va_arg (*ap, wint_t);
1968
                        break;
1969
                      case INT:
1970
                        args[numargs++].val_int = va_arg (*ap, int);
1971
                        break;
1972
                      case CHAR_PTR:
1973
                        args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
1974
                        break;
1975
                      case DOUBLE:
1976
                        args[numargs++].val_double = va_arg (*ap, double);
1977
                        break;
1978
                      case LONG_DOUBLE:
1979
                        args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
1980
                        break;
1981
                      }
1982
                  }
1983
              }
1984
              break;
1985
            case GETPOS: /* we have positional specifier */
1986
              if (arg_type[0] == -1)
1987
                memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
1988
              pos = number - 1;
1989
              max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
1990
              break;
1991
            case PWPOS:  /* we have positional specifier for width or precision */
1992
              if (arg_type[0] == -1)
1993
                memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
1994
              number -= 1;
1995
              arg_type[number] = INT;
1996
              max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
1997
              break;
1998
            case GETPWB: /* we require format pushback */
1999
              --fmt;
2000
              /* fallthrough */
2001
            case GETPW:  /* we have a variable precision or width to acquire */
2002
              args[numargs++].val_int = va_arg (*ap, int);
2003
              break;
2004
            case NUMBER: /* we have a number to process */
2005
              number = (ch - '0');
2006
              while ((ch = *fmt) != '\0' && is_digit (ch))
2007
                {
2008
                  number = number * 10 + (ch - '0');
2009
                  ++fmt;
2010
                }
2011
              break;
2012
            case SKIPNUM: /* we have a number to skip */
2013
              while ((ch = *fmt) != '\0' && is_digit (ch))
2014
                ++fmt;
2015
              break;
2016
            case NOOP:
2017
            default:
2018
              break; /* do nothing */
2019
            }
2020
        }
2021
    }
2022
 
2023
  /* process all arguments up to at least the one we are looking for and if we
2024
     have seen the end of the string, then process up to the max argument needed */
2025
  if (*fmt == '\0')
2026
    last_arg = max_pos_arg;
2027
  else
2028
    last_arg = n;
2029
 
2030
  while (numargs <= last_arg)
2031
    {
2032
      switch (arg_type[numargs])
2033
        {
2034
        case LONG_INT:
2035
          args[numargs++].val_long = va_arg (*ap, long);
2036
          break;
2037
        case QUAD_INT:
2038
          args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2039
          break;
2040
        case CHAR_PTR:
2041
          args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2042
          break;
2043
        case DOUBLE:
2044
          args[numargs++].val_double = va_arg (*ap, double);
2045
          break;
2046
        case LONG_DOUBLE:
2047
          args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2048
          break;
2049
        case WIDE_CHAR:
2050
          args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2051
          break;
2052
        case INT:
2053
        default:
2054
          args[numargs++].val_int = va_arg (*ap, int);
2055
          break;
2056
        }
2057
    }
2058
 
2059
  /* alter the global numargs value and keep a reference to the last bit of the fmt
2060
     string we processed here because the caller will continue processing where we started */
2061
  *numargs_p = numargs;
2062
  *last_fmt = fmt;
2063
  return &args[n];
2064
}
2065
#endif /* !_NO_POS_ARGS */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.