~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to vsnprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2010-07-31 17:08:39 UTC
  • mfrom: (1.1.4 upstream) (8.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100731170839-j034dmpdqt1cc4p6
Tags: 1.9.2~svn28788-1
* New release based on upstream snapshot from the 1.9.2 branch,
  after 1.9.2 RC2. That branch is (supposed to be) binary-compatible
  with the 1.9.1 branch.
  + Builds fine on i386. Closes: #580852.
* Upgrade to Standards-Version: 3.9.1. No changes needed.
* Updated generated incs.
* Patches that still need work:
  + Unclear status, need more investigation:
   090729_fix_Makefile_deps.dpatch
   090803_exclude_rdoc.dpatch
   203_adjust_base_of_search_path.dpatch
   902_define_YAML_in_yaml_stringio.rb.dpatch
   919_common.mk_tweaks.dpatch
   931_libruby_suffix.dpatch
   940_test_thread_mutex_sync_shorter.dpatch
  + Maybe not needed anymore, keeping but not applying.
   102_skip_test_copy_stream.dpatch (test doesn't block anymore?)
   104_skip_btest_io.dpatch (test doesn't block anymore?)
   201_gem_prelude.dpatch (we don't use that rubygems anyway?)
   202_gem_default_dir.dpatch (we don't use that rubygems anyway?)
   940_test_file_exhaustive_fails_as_root.dpatch
   940_test_priority_fails.dpatch
   100518_load_libc_libm.dpatch
* Add disable-tests.diff: disable some tests that cause failures on FreeBSD.
  Closes: #590002, #543805, #542927.
* However, many new failures on FreeBSD. Since that version is still an
  improvement, add the check that makes test suite failures non-fatal on
  FreeBSD again. That still needs to be investigated.
* Re-add 903_skip_base_ruby_check.dpatch
* Add build-dependency on ruby1.8 and drop all pre-generated files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 1990, 1993
 
3
 *      The Regents of the University of California.  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. Neither the name of the University nor the names of its contributors
 
17
 *    may be used to endorse or promote products derived from this software
 
18
 *    without specific prior written permission.
 
19
 *
 
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
30
 * SUCH DAMAGE.
 
31
 */
 
32
 
 
33
/*
 
34
 * IMPORTANT NOTE:
 
35
 * --------------
 
36
 * From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
 
37
 * paragraph 3 above is now null and void.
 
38
 */
 
39
 
 
40
/* SNPRINTF.C
 
41
 * fjc 7-31-97 Modified by Mib Software to be a standalone snprintf.c module.
 
42
 *      http://www.mibsoftware.com
 
43
 * Mib Software does not warrant this software any differently than the
 
44
 * University of California, Berkeley as described above.  All warranties
 
45
 * are disclaimed.  Use this software at your own risk.
 
46
 *
 
47
 *      All code referencing FILE * functions was eliminated, since it could
 
48
 *      never be called.  All header files and necessary files are collapsed
 
49
 *      into one file, internal functions are declared static.  This should
 
50
 *      allow inclusion into libraries with less chance of namespace collisions.
 
51
 *
 
52
 *      snprintf should be the only externally visible item.
 
53
 *
 
54
 *      As of 7-31-97 FLOATING_POINT is NOT provided.  The code is somewhat
 
55
 *        non-portable, so it is disabled.
 
56
 */
 
57
 
 
58
/* Define FLOATING_POINT to get floating point. */
 
59
/*
 
60
#define FLOATING_POINT
 
61
*/
 
62
 
 
63
#include <sys/types.h>
 
64
#define u_long unsigned long
 
65
#define u_short unsigned short
 
66
#define u_int unsigned int
 
67
 
 
68
#if !defined(HAVE_STDARG_PROTOTYPES)
 
69
#if defined(__STDC__)
 
70
#define HAVE_STDARG_PROTOTYPES 1
 
71
#endif
 
72
#endif
 
73
 
 
74
#undef __P
 
75
#if defined(HAVE_STDARG_PROTOTYPES)
 
76
# include <stdarg.h>
 
77
# if !defined(__P)
 
78
#  define __P(x) x
 
79
# endif
 
80
#else
 
81
# define __P(x) ()
 
82
# if !defined(const)
 
83
#  define const
 
84
# endif
 
85
# include <varargs.h>
 
86
#endif
 
87
#ifndef _BSD_VA_LIST_
 
88
#define _BSD_VA_LIST_ va_list
 
89
#endif
 
90
 
 
91
#ifdef __STDC__
 
92
# include <limits.h>
 
93
#else
 
94
# ifndef LONG_MAX
 
95
#  ifdef HAVE_LIMITS_H
 
96
#   include <limits.h>
 
97
#  else
 
98
    /* assuming 32bit(2's compliment) long */
 
99
#   define LONG_MAX 2147483647
 
100
#  endif
 
101
# endif
 
102
#endif
 
103
 
 
104
#if defined(__hpux) && !defined(__GNUC__) && !defined(__STDC__)
 
105
#define const
 
106
#endif
 
107
 
 
108
#if defined(sgi)
 
109
#undef __const
 
110
#define __const
 
111
#endif /* People who don't like const sys_error */
 
112
 
 
113
#include <stddef.h>
 
114
#if defined(__hpux) && !defined(__GNUC__) || defined(__DECC)
 
115
#include <string.h>
 
116
#endif
 
117
 
 
118
#if !defined(__CYGWIN32__) && defined(__hpux) && !defined(__GNUC__)
 
119
#include <stdlib.h>
 
120
#endif
 
121
 
 
122
#ifndef NULL
 
123
#define NULL    0
 
124
#endif
 
125
 
 
126
#if SIZEOF_LONG > SIZEOF_INT
 
127
# include <errno.h>
 
128
#endif
 
129
 
 
130
/*
 
131
 * NB: to fit things in six character monocase externals, the stdio
 
132
 * code uses the prefix `__s' for stdio objects, typically followed
 
133
 * by a three-character attempt at a mnemonic.
 
134
 */
 
135
 
 
136
/* stdio buffers */
 
137
struct __sbuf {
 
138
        unsigned char *_base;
 
139
        size_t  _size;
 
140
};
 
141
 
 
142
 
 
143
/*
 
144
 * stdio state variables.
 
145
 *
 
146
 * The following always hold:
 
147
 *
 
148
 *      if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
 
149
 *              _lbfsize is -_bf._size, else _lbfsize is 0
 
150
 *      if _flags&__SRD, _w is 0
 
151
 *      if _flags&__SWR, _r is 0
 
152
 *
 
153
 * This ensures that the getc and putc macros (or inline functions) never
 
154
 * try to write or read from a file that is in `read' or `write' mode.
 
155
 * (Moreover, they can, and do, automatically switch from read mode to
 
156
 * write mode, and back, on "r+" and "w+" files.)
 
157
 *
 
158
 * _lbfsize is used only to make the inline line-buffered output stream
 
159
 * code as compact as possible.
 
160
 *
 
161
 * _ub, _up, and _ur are used when ungetc() pushes back more characters
 
162
 * than fit in the current _bf, or when ungetc() pushes back a character
 
163
 * that does not match the previous one in _bf.  When this happens,
 
164
 * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
 
165
 * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
 
166
 *
 
167
 * NB: see WARNING above before changing the layout of this structure!
 
168
 */
 
169
typedef struct __sFILE {
 
170
        unsigned char *_p;      /* current position in (some) buffer */
 
171
#if 0
 
172
        size_t  _r;             /* read space left for getc() */
 
173
#endif
 
174
        size_t  _w;             /* write space left for putc() */
 
175
        short   _flags;         /* flags, below; this FILE is free if 0 */
 
176
        short   _file;          /* fileno, if Unix descriptor, else -1 */
 
177
        struct  __sbuf _bf;     /* the buffer (at least 1 byte, if !NULL) */
 
178
        size_t  _lbfsize;       /* 0 or -_bf._size, for inline putc */
 
179
        int     (*vwrite)(/* struct __sFILE*, struct __suio * */);
 
180
} FILE;
 
181
 
 
182
 
 
183
#define __SLBF  0x0001          /* line buffered */
 
184
#define __SNBF  0x0002          /* unbuffered */
 
185
#define __SRD   0x0004          /* OK to read */
 
186
#define __SWR   0x0008          /* OK to write */
 
187
        /* RD and WR are never simultaneously asserted */
 
188
#define __SRW   0x0010          /* open for reading & writing */
 
189
#define __SEOF  0x0020          /* found EOF */
 
190
#define __SERR  0x0040          /* found error */
 
191
#define __SMBF  0x0080          /* _buf is from malloc */
 
192
#define __SAPP  0x0100          /* fdopen()ed in append mode */
 
193
#define __SSTR  0x0200          /* this is an sprintf/snprintf string */
 
194
#define __SOPT  0x0400          /* do fseek() optimisation */
 
195
#define __SNPT  0x0800          /* do not do fseek() optimisation */
 
196
#define __SOFF  0x1000          /* set iff _offset is in fact correct */
 
197
#define __SMOD  0x2000          /* true => fgetln modified _p text */
 
198
 
 
199
 
 
200
#define EOF     (-1)
 
201
 
 
202
 
 
203
#define __sfeof(p)      (((p)->_flags & __SEOF) != 0)
 
204
#define __sferror(p)    (((p)->_flags & __SERR) != 0)
 
205
#define __sclearerr(p)  ((void)((p)->_flags &= ~(__SERR|__SEOF)))
 
206
#define __sfileno(p)    ((p)->_file)
 
207
 
 
208
#undef feof
 
209
#undef ferror
 
210
#undef clearerr
 
211
#define feof(p)         __sfeof(p)
 
212
#define ferror(p)       __sferror(p)
 
213
#define clearerr(p)     __sclearerr(p)
 
214
 
 
215
#ifndef _ANSI_SOURCE
 
216
#define fileno(p)       __sfileno(p)
 
217
#endif
 
218
 
 
219
 
 
220
/*
 
221
 * I/O descriptors for __sfvwrite().
 
222
 */
 
223
struct __siov {
 
224
        const void *iov_base;
 
225
        size_t  iov_len;
 
226
};
 
227
struct __suio {
 
228
        struct  __siov *uio_iov;
 
229
        int     uio_iovcnt;
 
230
        size_t  uio_resid;
 
231
};
 
232
 
 
233
/*
 
234
 * Write some memory regions.  Return zero on success, EOF on error.
 
235
 *
 
236
 * This routine is large and unsightly, but most of the ugliness due
 
237
 * to the three different kinds of output buffering is handled here.
 
238
 */
 
239
static int BSD__sfvwrite(fp, uio)
 
240
        register FILE *fp;
 
241
        register struct __suio *uio;
 
242
{
 
243
        register size_t len;
 
244
        register const char *p;
 
245
        register struct __siov *iov;
 
246
        register size_t w;
 
247
 
 
248
        if ((len = uio->uio_resid) == 0)
 
249
                return (0);
 
250
#ifndef __hpux
 
251
#define MIN(a, b) ((a) < (b) ? (a) : (b))
 
252
#endif
 
253
#define COPY(n)   (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
 
254
 
 
255
        iov = uio->uio_iov;
 
256
        p = iov->iov_base;
 
257
        len = iov->iov_len;
 
258
        iov++;
 
259
#define GETIOV(extra_work) \
 
260
        while (len == 0) { \
 
261
                extra_work; \
 
262
                p = iov->iov_base; \
 
263
                len = iov->iov_len; \
 
264
                iov++; \
 
265
        }
 
266
        if (fp->_flags & __SNBF) {
 
267
        /* fjc 7-31-97 Will never happen.  We are working with
 
268
                                           strings only
 
269
        */
 
270
        } else if ((fp->_flags & __SLBF) == 0) {
 
271
        /*
 
272
                 * Fully buffered: fill partially full buffer, if any,
 
273
                 * and then flush.  If there is no partial buffer, write
 
274
                 * one _bf._size byte chunk directly (without copying).
 
275
                 *
 
276
                 * String output is a special case: write as many bytes
 
277
                 * as fit, but pretend we wrote everything.  This makes
 
278
                 * snprintf() return the number of bytes needed, rather
 
279
                 * than the number used, and avoids its write function
 
280
                 * (so that the write function can be invalid).
 
281
                 */
 
282
                do {
 
283
                        GETIOV(;);
 
284
                        w = fp->_w;
 
285
                        if (fp->_flags & __SSTR) {
 
286
                                if (len < w)
 
287
                                        w = len;
 
288
                                COPY(w);        /* copy MIN(fp->_w,len), */
 
289
                                fp->_w -= w;
 
290
                                fp->_p += w;
 
291
                                w = len;        /* but pretend copied all */
 
292
                        } else {
 
293
                                /* fjc 7-31-97 Will never happen.  We are working with
 
294
                                                                   strings only
 
295
                                */
 
296
                        }
 
297
                        p += w;
 
298
                        len -= w;
 
299
                } while ((uio->uio_resid -= w) != 0);
 
300
        } else {
 
301
                /* fjc 7-31-97 Will never happen.  We are working with
 
302
                                                   strings only
 
303
                */
 
304
        }
 
305
        return (0);
 
306
}
 
307
 
 
308
/*
 
309
 * Actual printf innards.
 
310
 *
 
311
 * This code is large and complicated...
 
312
 */
 
313
 
 
314
/*
 
315
 * Flush out all the vectors defined by the given uio,
 
316
 * then reset it so that it can be reused.
 
317
 */
 
318
static int
 
319
BSD__sprint(FILE *fp, register struct __suio *uio)
 
320
{
 
321
        register int err;
 
322
 
 
323
        if (uio->uio_resid == 0) {
 
324
                uio->uio_iovcnt = 0;
 
325
                return (0);
 
326
        }
 
327
        err = (*fp->vwrite)(fp, uio);
 
328
        uio->uio_resid = 0;
 
329
        uio->uio_iovcnt = 0;
 
330
        return (err);
 
331
}
 
332
 
 
333
 
 
334
/*
 
335
 * Helper function for `fprintf to unbuffered unix file': creates a
 
336
 * temporary buffer.  We only work on write-only files; this avoids
 
337
 * worries about ungetc buffers and so forth.
 
338
 */
 
339
static int
 
340
BSD__sbprintf(register FILE *fp, const char *fmt, va_list ap)
 
341
{
 
342
/* We don't support files. */
 
343
        return 0;
 
344
}
 
345
 
 
346
 
 
347
/*
 
348
 * Macros for converting digits to letters and vice versa
 
349
 */
 
350
#define to_digit(c)     ((c) - '0')
 
351
#define is_digit(c)     ((unsigned)to_digit(c) <= 9)
 
352
#define to_char(n)      (char)((n) + '0')
 
353
 
 
354
#ifdef _HAVE_SANE_QUAD_
 
355
/*
 
356
 * Convert an unsigned long long to ASCII for printf purposes, returning
 
357
 * a pointer to the first character of the string representation.
 
358
 * Octal numbers can be forced to have a leading zero; hex numbers
 
359
 * use the given digits.
 
360
 */
 
361
static char *
 
362
BSD__uqtoa(register u_quad_t val, char *endp, int base, int octzero, const char *xdigs)
 
363
{
 
364
        register char *cp = endp;
 
365
        register long sval;
 
366
 
 
367
        /*
 
368
         * Handle the three cases separately, in the hope of getting
 
369
         * better/faster code.
 
370
         */
 
371
        switch (base) {
 
372
        case 10:
 
373
                if (val < 10) { /* many numbers are 1 digit */
 
374
                        *--cp = to_char(val);
 
375
                        return (cp);
 
376
                }
 
377
                /*
 
378
                 * On many machines, unsigned arithmetic is harder than
 
379
                 * signed arithmetic, so we do at most one unsigned mod and
 
380
                 * divide; this is sufficient to reduce the range of
 
381
                 * the incoming value to where signed arithmetic works.
 
382
                 */
 
383
                if (val > LLONG_MAX) {
 
384
                        *--cp = to_char(val % 10);
 
385
                        sval = val / 10;
 
386
                } else
 
387
                        sval = val;
 
388
                do {
 
389
                        *--cp = to_char(sval % 10);
 
390
                        sval /= 10;
 
391
                } while (sval != 0);
 
392
                break;
 
393
 
 
394
        case 8:
 
395
                do {
 
396
                        *--cp = to_char(val & 7);
 
397
                        val >>= 3;
 
398
                } while (val);
 
399
                if (octzero && *cp != '0')
 
400
                        *--cp = '0';
 
401
                break;
 
402
 
 
403
        case 16:
 
404
                do {
 
405
                        *--cp = xdigs[val & 15];
 
406
                        val >>= 4;
 
407
                } while (val);
 
408
                break;
 
409
 
 
410
        default:                        /* oops */
 
411
                /*
 
412
                abort();
 
413
                */
 
414
                break;  /* fjc 7-31-97.  Don't reference abort() here */
 
415
        }
 
416
        return (cp);
 
417
}
 
418
#endif /* _HAVE_SANE_QUAD_ */
 
419
 
 
420
/*
 
421
 * Convert an unsigned long to ASCII for printf purposes, returning
 
422
 * a pointer to the first character of the string representation.
 
423
 * Octal numbers can be forced to have a leading zero; hex numbers
 
424
 * use the given digits.
 
425
 */
 
426
static char *
 
427
BSD__ultoa(register u_long val, char *endp, int base, int octzero, const char *xdigs)
 
428
{
 
429
        register char *cp = endp;
 
430
        register long sval;
 
431
 
 
432
        /*
 
433
         * Handle the three cases separately, in the hope of getting
 
434
         * better/faster code.
 
435
         */
 
436
        switch (base) {
 
437
        case 10:
 
438
                if (val < 10) { /* many numbers are 1 digit */
 
439
                        *--cp = to_char(val);
 
440
                        return (cp);
 
441
                }
 
442
                /*
 
443
                 * On many machines, unsigned arithmetic is harder than
 
444
                 * signed arithmetic, so we do at most one unsigned mod and
 
445
                 * divide; this is sufficient to reduce the range of
 
446
                 * the incoming value to where signed arithmetic works.
 
447
                 */
 
448
                if (val > LONG_MAX) {
 
449
                        *--cp = to_char(val % 10);
 
450
                        sval = val / 10;
 
451
                } else
 
452
                        sval = val;
 
453
                do {
 
454
                        *--cp = to_char(sval % 10);
 
455
                        sval /= 10;
 
456
                } while (sval != 0);
 
457
                break;
 
458
 
 
459
        case 8:
 
460
                do {
 
461
                        *--cp = to_char(val & 7);
 
462
                        val >>= 3;
 
463
                } while (val);
 
464
                if (octzero && *cp != '0')
 
465
                        *--cp = '0';
 
466
                break;
 
467
 
 
468
        case 16:
 
469
                do {
 
470
                        *--cp = xdigs[val & 15];
 
471
                        val >>= 4;
 
472
                } while (val);
 
473
                break;
 
474
 
 
475
        default:                        /* oops */
 
476
                /*
 
477
                abort();
 
478
                */
 
479
                break;  /* fjc 7-31-97.  Don't reference abort() here */
 
480
        }
 
481
        return (cp);
 
482
}
 
483
 
 
484
#ifdef FLOATING_POINT
 
485
#include <math.h>
 
486
/* #include "floatio.h" */
 
487
 
 
488
#ifndef MAXEXP
 
489
# define MAXEXP 1024
 
490
#endif
 
491
 
 
492
#ifndef MAXFRACT
 
493
# define MAXFRACT 64
 
494
#endif
 
495
 
 
496
#define BUF             (MAXEXP+MAXFRACT+1)     /* + decimal point */
 
497
#define DEFPREC         6
 
498
 
 
499
static char *cvt __P((double, int, int, char *, int *, int, int *, char *));
 
500
static int exponent __P((char *, int, int));
 
501
 
 
502
#else /* no FLOATING_POINT */
 
503
 
 
504
#define BUF             68
 
505
 
 
506
#endif /* FLOATING_POINT */
 
507
 
 
508
 
 
509
/*
 
510
 * Flags used during conversion.
 
511
 */
 
512
#define ALT             0x001           /* alternate form */
 
513
#define HEXPREFIX       0x002           /* add 0x or 0X prefix */
 
514
#define LADJUST         0x004           /* left adjustment */
 
515
#define LONGDBL         0x008           /* long double; unimplemented */
 
516
#define LONGINT         0x010           /* long integer */
 
517
 
 
518
#ifdef _HAVE_SANE_QUAD_
 
519
#define QUADINT         0x020           /* quad integer */
 
520
#endif /* _HAVE_SANE_QUAD_ */
 
521
 
 
522
#define SHORTINT        0x040           /* short integer */
 
523
#define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
 
524
#define FPT             0x100           /* Floating point number */
 
525
static ssize_t
 
526
BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
 
527
{
 
528
        register const char *fmt; /* format string */
 
529
        register int ch;        /* character from fmt */
 
530
        register int n;         /* handy integer (short term usage) */
 
531
        register const char *cp;/* handy char pointer (short term usage) */
 
532
        register struct __siov *iovp;/* for PRINT macro */
 
533
        register int flags;     /* flags as above */
 
534
        ssize_t ret;            /* return value accumulator */
 
535
        int width;              /* width from format (%8d), or 0 */
 
536
        int prec;               /* precision from format (%.3d), or -1 */
 
537
        char sign;              /* sign prefix (' ', '+', '-', or \0) */
 
538
#ifdef FLOATING_POINT
 
539
        char softsign;          /* temporary negative sign for floats */
 
540
        double _double = 0;     /* double precision arguments %[eEfgG] */
 
541
        int expt;               /* integer value of exponent */
 
542
        int expsize = 0;        /* character count for expstr */
 
543
        int ndig = 0;           /* actual number of digits returned by cvt */
 
544
        char expstr[7];         /* buffer for exponent string */
 
545
#endif
 
546
        u_long  ulval;          /* integer arguments %[diouxX] */
 
547
#ifdef _HAVE_SANE_QUAD_
 
548
        u_quad_t uqval;         /* %q integers */
 
549
#endif /* _HAVE_SANE_QUAD_ */
 
550
        int base;               /* base for [diouxX] conversion */
 
551
        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
 
552
        long fieldsz;           /* field size expanded by sign, etc */
 
553
        long realsz;            /* field size expanded by dprec */
 
554
        int size;               /* size of converted field or string */
 
555
        const char *xdigs = 0;  /* digits for [xX] conversion */
 
556
#define NIOV 8
 
557
        struct __suio uio;      /* output information: summary */
 
558
        struct __siov iov[NIOV];/* ... and individual io vectors */
 
559
        char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
 
560
        char ox[4];             /* space for 0x hex-prefix, hexadecimal's 1. */
 
561
        char *const ebuf = buf + sizeof(buf);
 
562
#if SIZEOF_LONG > SIZEOF_INT
 
563
        long ln;
 
564
#endif
 
565
 
 
566
        /*
 
567
         * Choose PADSIZE to trade efficiency vs. size.  If larger printf
 
568
         * fields occur frequently, increase PADSIZE and make the initializers
 
569
         * below longer.
 
570
         */
 
571
#define PADSIZE 16              /* pad chunk size */
 
572
        static const char blanks[PADSIZE] =
 
573
         {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
 
574
        static const char zeroes[PADSIZE] =
 
575
         {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
 
576
 
 
577
        /*
 
578
         * BEWARE, these `goto error' on error, and PAD uses `n'.
 
579
         */
 
580
#define PRINT(ptr, len) { \
 
581
        iovp->iov_base = (ptr); \
 
582
        iovp->iov_len = (len); \
 
583
        uio.uio_resid += (len); \
 
584
        iovp++; \
 
585
        if (++uio.uio_iovcnt >= NIOV) { \
 
586
                if (BSD__sprint(fp, &uio)) \
 
587
                        goto error; \
 
588
                iovp = iov; \
 
589
        } \
 
590
}
 
591
#define PAD(howmany, with) { \
 
592
        if ((n = (howmany)) > 0) { \
 
593
                while (n > PADSIZE) { \
 
594
                        PRINT(with, PADSIZE); \
 
595
                        n -= PADSIZE; \
 
596
                } \
 
597
                PRINT(with, n); \
 
598
        } \
 
599
}
 
600
#if SIZEOF_LONG > SIZEOF_INT
 
601
        /* abandon if too larger padding */
 
602
#define PAD_L(howmany, with) { \
 
603
        ln = (howmany); \
 
604
        if ((long)((int)ln) != ln) { \
 
605
            errno = ENOMEM; \
 
606
            goto error; \
 
607
        } \
 
608
        if (ln > 0) PAD((int)ln, with); \
 
609
}
 
610
#else
 
611
#define PAD_L(howmany, with) PAD(howmany, with)
 
612
#endif
 
613
#define FLUSH() { \
 
614
        if (uio.uio_resid && BSD__sprint(fp, &uio)) \
 
615
                goto error; \
 
616
        uio.uio_iovcnt = 0; \
 
617
        iovp = iov; \
 
618
}
 
619
 
 
620
        /*
 
621
         * To extend shorts properly, we need both signed and unsigned
 
622
         * argument extraction methods.
 
623
         */
 
624
#define SARG() \
 
625
        (flags&LONGINT ? va_arg(ap, long) : \
 
626
            flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
 
627
            (long)va_arg(ap, int))
 
628
#define UARG() \
 
629
        (flags&LONGINT ? va_arg(ap, u_long) : \
 
630
            flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
 
631
            (u_long)va_arg(ap, u_int))
 
632
 
 
633
        /* optimise fprintf(stderr) (and other unbuffered Unix files) */
 
634
        if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
 
635
            fp->_file >= 0)
 
636
                return (BSD__sbprintf(fp, fmt0, ap));
 
637
 
 
638
        fmt = fmt0;
 
639
        uio.uio_iov = iovp = iov;
 
640
        uio.uio_resid = 0;
 
641
        uio.uio_iovcnt = 0;
 
642
        ret = 0;
 
643
        xdigs = 0;
 
644
 
 
645
        /*
 
646
         * Scan the format for conversions (`%' character).
 
647
         */
 
648
        for (;;) {
 
649
                size_t nc;
 
650
                for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
 
651
                        /* void */;
 
652
                if ((nc = fmt - cp) != 0) {
 
653
                        PRINT(cp, nc);
 
654
                        ret += nc;
 
655
                }
 
656
                if (ch == '\0')
 
657
                        goto done;
 
658
                fmt++;          /* skip over '%' */
 
659
 
 
660
                flags = 0;
 
661
                dprec = 0;
 
662
                width = 0;
 
663
                prec = -1;
 
664
                sign = '\0';
 
665
 
 
666
rflag:          ch = *fmt++;
 
667
reswitch:       switch (ch) {
 
668
                case ' ':
 
669
                        /*
 
670
                         * ``If the space and + flags both appear, the space
 
671
                         * flag will be ignored.''
 
672
                         *      -- ANSI X3J11
 
673
                         */
 
674
                        if (!sign)
 
675
                                sign = ' ';
 
676
                        goto rflag;
 
677
                case '#':
 
678
                        flags |= ALT;
 
679
                        goto rflag;
 
680
                case '*':
 
681
                        /*
 
682
                         * ``A negative field width argument is taken as a
 
683
                         * - flag followed by a positive field width.''
 
684
                         *      -- ANSI X3J11
 
685
                         * They don't exclude field widths read from args.
 
686
                         */
 
687
                        if ((width = va_arg(ap, int)) >= 0)
 
688
                                goto rflag;
 
689
                        width = -width;
 
690
                        /* FALLTHROUGH */
 
691
                case '-':
 
692
                        flags |= LADJUST;
 
693
                        goto rflag;
 
694
                case '+':
 
695
                        sign = '+';
 
696
                        goto rflag;
 
697
                case '.':
 
698
                        if ((ch = *fmt++) == '*') {
 
699
                                n = va_arg(ap, int);
 
700
                                prec = n < 0 ? -1 : n;
 
701
                                goto rflag;
 
702
                        }
 
703
                        n = 0;
 
704
                        while (is_digit(ch)) {
 
705
                                n = 10 * n + to_digit(ch);
 
706
                                ch = *fmt++;
 
707
                        }
 
708
                        prec = n < 0 ? -1 : n;
 
709
                        goto reswitch;
 
710
                case '0':
 
711
                        /*
 
712
                         * ``Note that 0 is taken as a flag, not as the
 
713
                         * beginning of a field width.''
 
714
                         *      -- ANSI X3J11
 
715
                         */
 
716
                        flags |= ZEROPAD;
 
717
                        goto rflag;
 
718
                case '1': case '2': case '3': case '4':
 
719
                case '5': case '6': case '7': case '8': case '9':
 
720
                        n = 0;
 
721
                        do {
 
722
                                n = 10 * n + to_digit(ch);
 
723
                                ch = *fmt++;
 
724
                        } while (is_digit(ch));
 
725
                        width = n;
 
726
                        goto reswitch;
 
727
#ifdef FLOATING_POINT
 
728
                case 'L':
 
729
                        flags |= LONGDBL;
 
730
                        goto rflag;
 
731
#endif
 
732
                case 'h':
 
733
                        flags |= SHORTINT;
 
734
                        goto rflag;
 
735
#if SIZEOF_PTRDIFF_T == SIZEOF_LONG
 
736
                case 't':
 
737
#endif
 
738
#if SIZEOF_SIZE_T == SIZEOF_LONG
 
739
                case 'z':
 
740
#endif
 
741
                case 'l':
 
742
                        flags |= LONGINT;
 
743
                        goto rflag;
 
744
#ifdef _HAVE_SANE_QUAD_
 
745
#if SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
 
746
                case 't':
 
747
#endif
 
748
#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
 
749
                case 'z':
 
750
#endif
 
751
                case 'q':
 
752
                        flags |= QUADINT;
 
753
                        goto rflag;
 
754
#endif /* _HAVE_SANE_QUAD_ */
 
755
                case 'c':
 
756
                        cp = buf;
 
757
                        *buf = (char)va_arg(ap, int);
 
758
                        size = 1;
 
759
                        sign = '\0';
 
760
                        break;
 
761
                case 'D':
 
762
                        flags |= LONGINT;
 
763
                        /*FALLTHROUGH*/
 
764
                case 'd':
 
765
                case 'i':
 
766
#ifdef _HAVE_SANE_QUAD_
 
767
                        if (flags & QUADINT) {
 
768
                                uqval = va_arg(ap, quad_t);
 
769
                                if ((quad_t)uqval < 0) {
 
770
                                        uqval = -(quad_t)uqval;
 
771
                                        sign = '-';
 
772
                                }
 
773
                        } else
 
774
#endif /* _HAVE_SANE_QUAD_ */
 
775
                        {
 
776
                                ulval = SARG();
 
777
                                if ((long)ulval < 0) {
 
778
                                        ulval = (u_long)(-(long)ulval);
 
779
                                        sign = '-';
 
780
                                }
 
781
                        }
 
782
                        base = 10;
 
783
                        goto number;
 
784
#ifdef FLOATING_POINT
 
785
                case 'a':
 
786
                case 'A':
 
787
                        if (prec >= 0)
 
788
                                prec++;
 
789
                        goto fp_begin;
 
790
                case 'e':               /* anomalous precision */
 
791
                case 'E':
 
792
                        if (prec != 0)
 
793
                                flags |= ALT;
 
794
                        prec = (prec == -1) ?
 
795
                                DEFPREC + 1 : prec + 1;
 
796
                        /* FALLTHROUGH */
 
797
                        goto fp_begin;
 
798
                case 'f':               /* always print trailing zeroes */
 
799
                        if (prec != 0)
 
800
                                flags |= ALT;
 
801
                case 'g':
 
802
                case 'G':
 
803
                        if (prec == -1)
 
804
                                prec = DEFPREC;
 
805
fp_begin:               _double = va_arg(ap, double);
 
806
                        /* do this before tricky precision changes */
 
807
                        if (isinf(_double)) {
 
808
                                if (_double < 0)
 
809
                                        sign = '-';
 
810
                                cp = "Inf";
 
811
                                size = 3;
 
812
                                break;
 
813
                        }
 
814
                        if (isnan(_double)) {
 
815
                                cp = "NaN";
 
816
                                size = 3;
 
817
                                break;
 
818
                        }
 
819
                        flags |= FPT;
 
820
                        cp = cvt(_double, prec, flags, &softsign,
 
821
                                &expt, ch, &ndig, buf);
 
822
                        if (ch == 'g' || ch == 'G') {
 
823
                                if (expt <= -4 || (expt > prec && expt > 1))
 
824
                                        ch = (ch == 'g') ? 'e' : 'E';
 
825
                                else
 
826
                                        ch = 'g';
 
827
                        }
 
828
                        if (ch == 'a' || ch == 'A') {
 
829
                                --expt;
 
830
                                expsize = exponent(expstr, expt, ch + 'p' - 'a');
 
831
                                size = expsize + ndig;
 
832
                        }
 
833
                        else if (ch <= 'e') {   /* 'e' or 'E' fmt */
 
834
                                --expt;
 
835
                                expsize = exponent(expstr, expt, ch);
 
836
                                size = expsize + ndig;
 
837
                                if (ndig > 1 || flags & ALT)
 
838
                                        ++size;
 
839
                        } else if (ch == 'f') {         /* f fmt */
 
840
                                if (expt > 0) {
 
841
                                        size = expt;
 
842
                                        if (prec || flags & ALT)
 
843
                                                size += prec + 1;
 
844
                                } else if (!prec) { /* "0" */
 
845
                                        size = 1;
 
846
                                } else  /* "0.X" */
 
847
                                        size = prec + 2;
 
848
                        } else if (expt >= ndig) {      /* fixed g fmt */
 
849
                                size = expt;
 
850
                                if (flags & ALT)
 
851
                                        ++size;
 
852
                        } else
 
853
                                size = ndig + (expt > 0 ?
 
854
                                        1 : 2 - expt);
 
855
 
 
856
                        if (softsign)
 
857
                                sign = '-';
 
858
                        break;
 
859
#endif /* FLOATING_POINT */
 
860
                case 'n':
 
861
#ifdef _HAVE_SANE_QUAD_
 
862
                        if (flags & QUADINT)
 
863
                                *va_arg(ap, quad_t *) = ret;
 
864
                        else if (flags & LONGINT)
 
865
#else /* _HAVE_SANE_QUAD_ */
 
866
                        if (flags & LONGINT)
 
867
#endif /* _HAVE_SANE_QUAD_ */
 
868
                                *va_arg(ap, long *) = ret;
 
869
                        else if (flags & SHORTINT)
 
870
                                *va_arg(ap, short *) = (short)ret;
 
871
                        else
 
872
                                *va_arg(ap, int *) = (int)ret;
 
873
                        continue;       /* no output */
 
874
                case 'O':
 
875
                        flags |= LONGINT;
 
876
                        /*FALLTHROUGH*/
 
877
                case 'o':
 
878
#ifdef _HAVE_SANE_QUAD_
 
879
                        if (flags & QUADINT)
 
880
                                uqval = va_arg(ap, u_quad_t);
 
881
                        else
 
882
#endif /* _HAVE_SANE_QUAD_ */
 
883
                                ulval = UARG();
 
884
                        base = 8;
 
885
                        goto nosign;
 
886
                case 'p':
 
887
                        /*
 
888
                         * ``The argument shall be a pointer to void.  The
 
889
                         * value of the pointer is converted to a sequence
 
890
                         * of printable characters, in an implementation-
 
891
                         * defined manner.''
 
892
                         *      -- ANSI X3J11
 
893
                         */
 
894
                        prec = (int)(sizeof(void*)*CHAR_BIT/4);
 
895
#ifdef _HAVE_LLP64_
 
896
                        uqval = (u_long)va_arg(ap, void *);
 
897
                        flags = (flags) | QUADINT | HEXPREFIX;
 
898
#else
 
899
                        ulval = (u_long)va_arg(ap, void *);
 
900
#ifdef _HAVE_SANE_QUAD_
 
901
                        flags = (flags & ~QUADINT) | HEXPREFIX;
 
902
#else /* _HAVE_SANE_QUAD_ */
 
903
                        flags = (flags) | HEXPREFIX;
 
904
#endif /* _HAVE_SANE_QUAD_ */
 
905
#endif
 
906
                        base = 16;
 
907
                        xdigs = "0123456789abcdef";
 
908
                        ch = 'x';
 
909
                        goto nosign;
 
910
                case 's':
 
911
                        if ((cp = va_arg(ap, char *)) == NULL)
 
912
                                cp = "(null)";
 
913
                        if (prec >= 0) {
 
914
                                /*
 
915
                                 * can't use strlen; can only look for the
 
916
                                 * NUL in the first `prec' characters, and
 
917
                                 * strlen() will go further.
 
918
                                 */
 
919
                                const char *p = (char *)memchr(cp, 0, prec);
 
920
 
 
921
                                if (p != NULL && (p - cp) > prec)
 
922
                                        size = (int)(p - cp);
 
923
                                else
 
924
                                        size = prec;
 
925
                        }
 
926
                        else {
 
927
                                fieldsz = strlen(cp);
 
928
                                goto long_len;
 
929
                        }
 
930
                        sign = '\0';
 
931
                        break;
 
932
                case 'U':
 
933
                        flags |= LONGINT;
 
934
                        /*FALLTHROUGH*/
 
935
                case 'u':
 
936
#ifdef _HAVE_SANE_QUAD_
 
937
                        if (flags & QUADINT)
 
938
                                uqval = va_arg(ap, u_quad_t);
 
939
                        else
 
940
#endif /* _HAVE_SANE_QUAD_ */
 
941
                                ulval = UARG();
 
942
                        base = 10;
 
943
                        goto nosign;
 
944
                case 'X':
 
945
                        xdigs = "0123456789ABCDEF";
 
946
                        goto hex;
 
947
                case 'x':
 
948
                        xdigs = "0123456789abcdef";
 
949
hex:
 
950
#ifdef _HAVE_SANE_QUAD_
 
951
                        if (flags & QUADINT)
 
952
                                uqval = va_arg(ap, u_quad_t);
 
953
                        else
 
954
#endif /* _HAVE_SANE_QUAD_ */
 
955
                                ulval = UARG();
 
956
                        base = 16;
 
957
                        /* leading 0x/X only if non-zero */
 
958
                        if (flags & ALT &&
 
959
#ifdef _HAVE_SANE_QUAD_
 
960
                            (flags & QUADINT ? uqval != 0 : ulval != 0)
 
961
#else /* _HAVE_SANE_QUAD_ */
 
962
                            ulval != 0
 
963
#endif /* _HAVE_SANE_QUAD_ */
 
964
                            )
 
965
                                flags |= HEXPREFIX;
 
966
 
 
967
                        /* unsigned conversions */
 
968
nosign:                 sign = '\0';
 
969
                        /*
 
970
                         * ``... diouXx conversions ... if a precision is
 
971
                         * specified, the 0 flag will be ignored.''
 
972
                         *      -- ANSI X3J11
 
973
                         */
 
974
number:                 if ((dprec = prec) >= 0)
 
975
                                flags &= ~ZEROPAD;
 
976
 
 
977
                        /*
 
978
                         * ``The result of converting a zero value with an
 
979
                         * explicit precision of zero is no characters.''
 
980
                         *      -- ANSI X3J11
 
981
                         */
 
982
#ifdef _HAVE_SANE_QUAD_
 
983
                        if (flags & QUADINT) {
 
984
                                if (uqval != 0 || prec != 0)
 
985
                                        cp = BSD__uqtoa(uqval, ebuf, base,
 
986
                                            flags & ALT, xdigs);
 
987
                        } else
 
988
#else /* _HAVE_SANE_QUAD_ */
 
989
#endif /* _HAVE_SANE_QUAD_ */
 
990
                        {
 
991
                                if (ulval != 0 || prec != 0)
 
992
                                        cp = BSD__ultoa(ulval, ebuf, base,
 
993
                                            flags & ALT, xdigs);
 
994
                        }
 
995
                        size = (int)(ebuf - cp);
 
996
                        break;
 
997
                default:        /* "%?" prints ?, unless ? is NUL */
 
998
                        if (ch == '\0')
 
999
                                goto done;
 
1000
                        /* pretend it was %c with argument ch */
 
1001
                        cp = buf;
 
1002
                        *buf = ch;
 
1003
                        size = 1;
 
1004
                        sign = '\0';
 
1005
                        break;
 
1006
                }
 
1007
 
 
1008
                /*
 
1009
                 * All reasonable formats wind up here.  At this point, `cp'
 
1010
                 * points to a string which (if not flags&LADJUST) should be
 
1011
                 * padded out to `width' places.  If flags&ZEROPAD, it should
 
1012
                 * first be prefixed by any sign or other prefix; otherwise,
 
1013
                 * it should be blank padded before the prefix is emitted.
 
1014
                 * After any left-hand padding and prefixing, emit zeroes
 
1015
                 * required by a decimal [diouxX] precision, then print the
 
1016
                 * string proper, then emit zeroes required by any leftover
 
1017
                 * floating precision; finally, if LADJUST, pad with blanks.
 
1018
                 *
 
1019
                 * Compute actual size, so we know how much to pad.
 
1020
                 * fieldsz excludes decimal prec; realsz includes it.
 
1021
                 */
 
1022
                fieldsz = size;
 
1023
long_len:
 
1024
                if (sign)
 
1025
                        fieldsz++;
 
1026
                else if (flags & HEXPREFIX)
 
1027
                        fieldsz += 2;
 
1028
                realsz = dprec > fieldsz ? dprec : fieldsz;
 
1029
 
 
1030
                /* right-adjusting blank padding */
 
1031
                if ((flags & (LADJUST|ZEROPAD)) == 0)
 
1032
                        PAD_L(width - realsz, blanks);
 
1033
 
 
1034
                /* prefix */
 
1035
                if (sign) {
 
1036
                        PRINT(&sign, 1);
 
1037
                } else if (flags & HEXPREFIX) {
 
1038
                        ox[0] = '0';
 
1039
                        ox[1] = ch;
 
1040
                        PRINT(ox, 2);
 
1041
                }
 
1042
 
 
1043
                /* right-adjusting zero padding */
 
1044
                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
 
1045
                        PAD_L(width - realsz, zeroes);
 
1046
 
 
1047
                /* leading zeroes from decimal precision */
 
1048
                PAD_L(dprec - fieldsz, zeroes);
 
1049
                if (sign)
 
1050
                        fieldsz--;
 
1051
                else if (flags & HEXPREFIX)
 
1052
                        fieldsz -= 2;
 
1053
 
 
1054
                /* the string or number proper */
 
1055
#ifdef FLOATING_POINT
 
1056
                if ((flags & FPT) == 0) {
 
1057
                        PRINT(cp, fieldsz);
 
1058
                } else {        /* glue together f_p fragments */
 
1059
                        if (ch == 'a' || ch == 'A') {
 
1060
                                ox[0] = '0';
 
1061
                                ox[1] = ch + ('x' - 'a');
 
1062
                                PRINT(ox, 2);
 
1063
                                if (ndig > 1 || flags & ALT) {
 
1064
                                        ox[2] = *cp++;
 
1065
                                        ox[3] = '.';
 
1066
                                        PRINT(ox+2, 2);
 
1067
                                        PRINT(cp, ndig-1);
 
1068
                                } else  /* XpYYY */
 
1069
                                        PRINT(cp, 1);
 
1070
                                PRINT(expstr, expsize);
 
1071
                        }
 
1072
                        else if (ch >= 'f') {   /* 'f' or 'g' */
 
1073
                                if (_double == 0) {
 
1074
                                /* kludge for __dtoa irregularity */
 
1075
                                        if (ndig <= 1 &&
 
1076
                                            (flags & ALT) == 0) {
 
1077
                                                PRINT("0", 1);
 
1078
                                        } else {
 
1079
                                                PRINT("0.", 2);
 
1080
                                                PAD(ndig - 1, zeroes);
 
1081
                                        }
 
1082
                                } else if (expt == 0 && ndig == 0 && (flags & ALT) == 0) {
 
1083
                                        PRINT("0", 1);
 
1084
                                } else if (expt <= 0) {
 
1085
                                        PRINT("0.", 2);
 
1086
                                        PAD(-expt, zeroes);
 
1087
                                        PRINT(cp, ndig);
 
1088
                                } else if (expt >= ndig) {
 
1089
                                        PRINT(cp, ndig);
 
1090
                                        PAD(expt - ndig, zeroes);
 
1091
                                        if (flags & ALT)
 
1092
                                                PRINT(".", 1);
 
1093
                                } else {
 
1094
                                        PRINT(cp, expt);
 
1095
                                        cp += expt;
 
1096
                                        PRINT(".", 1);
 
1097
                                        PRINT(cp, ndig-expt);
 
1098
                                }
 
1099
                        } else {        /* 'e' or 'E' */
 
1100
                                if (ndig > 1 || flags & ALT) {
 
1101
                                        ox[0] = *cp++;
 
1102
                                        ox[1] = '.';
 
1103
                                        PRINT(ox, 2);
 
1104
                                        if (_double /*|| flags & ALT == 0*/) {
 
1105
                                                PRINT(cp, ndig-1);
 
1106
                                        } else  /* 0.[0..] */
 
1107
                                                /* __dtoa irregularity */
 
1108
                                                PAD(ndig - 1, zeroes);
 
1109
                                } else  /* XeYYY */
 
1110
                                        PRINT(cp, 1);
 
1111
                                PRINT(expstr, expsize);
 
1112
                        }
 
1113
                }
 
1114
#else
 
1115
                PRINT(cp, fieldsz);
 
1116
#endif
 
1117
                /* left-adjusting padding (always blank) */
 
1118
                if (flags & LADJUST)
 
1119
                        PAD_L(width - realsz, blanks);
 
1120
 
 
1121
                /* finally, adjust ret */
 
1122
                ret += width > realsz ? width : realsz;
 
1123
 
 
1124
                FLUSH();        /* copy out the I/O vectors */
 
1125
        }
 
1126
done:
 
1127
        FLUSH();
 
1128
error:
 
1129
        return (__sferror(fp) ? EOF : ret);
 
1130
        /* NOTREACHED */
 
1131
}
 
1132
 
 
1133
#ifdef FLOATING_POINT
 
1134
 
 
1135
extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
 
1136
extern char *BSD__hdtoa(double, const char *, int, int *, int *, char **);
 
1137
 
 
1138
static char *
 
1139
cvt(value, ndigits, flags, sign, decpt, ch, length, buf)
 
1140
        double value;
 
1141
        int ndigits, flags, *decpt, ch, *length;
 
1142
        char *sign, *buf;
 
1143
{
 
1144
        int mode, dsgn;
 
1145
        char *digits, *bp, *rve;
 
1146
 
 
1147
        if (ch == 'f')
 
1148
                mode = 3;
 
1149
        else {
 
1150
                mode = 2;
 
1151
        }
 
1152
        if (value < 0) {
 
1153
                value = -value;
 
1154
                *sign = '-';
 
1155
        } else if (value == 0.0 && 1.0/value < 0) {
 
1156
            *sign = '-';
 
1157
        } else {
 
1158
            *sign = '\000';
 
1159
        }
 
1160
        if (ch == 'a' || ch =='A') {
 
1161
            digits = BSD__hdtoa(value,
 
1162
                    ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF",
 
1163
                    ndigits, decpt, &dsgn, &rve);
 
1164
        }
 
1165
        else {
 
1166
            digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
 
1167
        }
 
1168
        memcpy(buf, digits, rve - digits);
 
1169
        xfree(digits);
 
1170
        rve = buf + (rve - digits);
 
1171
        digits = buf;
 
1172
        if (flags & ALT) {      /* Print trailing zeros */
 
1173
                bp = digits + ndigits;
 
1174
                if (ch == 'f') {
 
1175
                        if (*digits == '0' && value)
 
1176
                                *decpt = -ndigits + 1;
 
1177
                        bp += *decpt;
 
1178
                }
 
1179
                if (value == 0) /* kludge for __dtoa irregularity */
 
1180
                        rve = bp;
 
1181
                while (rve < bp)
 
1182
                        *rve++ = '0';
 
1183
        }
 
1184
        *length = (int)(rve - digits);
 
1185
        return (digits);
 
1186
}
 
1187
 
 
1188
static int
 
1189
exponent(p0, exp, fmtch)
 
1190
        char *p0;
 
1191
        int exp, fmtch;
 
1192
{
 
1193
        register char *p, *t;
 
1194
        char expbuf[MAXEXP];
 
1195
 
 
1196
        p = p0;
 
1197
        *p++ = fmtch;
 
1198
        if (exp < 0) {
 
1199
                exp = -exp;
 
1200
                *p++ = '-';
 
1201
        }
 
1202
        else
 
1203
                *p++ = '+';
 
1204
        t = expbuf + MAXEXP;
 
1205
        if (exp > 9) {
 
1206
                do {
 
1207
                        *--t = to_char(exp % 10);
 
1208
                } while ((exp /= 10) > 9);
 
1209
                *--t = to_char(exp);
 
1210
                for (; t < expbuf + MAXEXP; *p++ = *t++);
 
1211
        }
 
1212
        else {
 
1213
                if (fmtch & 15) *p++ = '0'; /* other than p or P */
 
1214
                *p++ = to_char(exp);
 
1215
        }
 
1216
        return (int)(p - p0);
 
1217
}
 
1218
#endif /* FLOATING_POINT */
 
1219
 
 
1220
int
 
1221
ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
 
1222
{
 
1223
        int ret;
 
1224
        FILE f;
 
1225
 
 
1226
        if ((int)n < 1)
 
1227
                return (EOF);
 
1228
        f._flags = __SWR | __SSTR;
 
1229
        f._bf._base = f._p = (unsigned char *)str;
 
1230
        f._bf._size = f._w = n - 1;
 
1231
        f.vwrite = BSD__sfvwrite;
 
1232
        ret = (int)BSD_vfprintf(&f, fmt, ap);
 
1233
        *f._p = 0;
 
1234
        return (ret);
 
1235
}
 
1236
 
 
1237
int
 
1238
ruby_snprintf(char *str, size_t n, char const *fmt, ...)
 
1239
{
 
1240
        int ret;
 
1241
        va_list ap;
 
1242
        FILE f;
 
1243
 
 
1244
        if ((int)n < 1)
 
1245
                return (EOF);
 
1246
 
 
1247
        va_start(ap, fmt);
 
1248
        f._flags = __SWR | __SSTR;
 
1249
        f._bf._base = f._p = (unsigned char *)str;
 
1250
        f._bf._size = f._w = n - 1;
 
1251
        f.vwrite = BSD__sfvwrite;
 
1252
        ret = (int)BSD_vfprintf(&f, fmt, ap);
 
1253
        *f._p = 0;
 
1254
        va_end(ap);
 
1255
        return (ret);
 
1256
}