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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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