~ubuntu-branches/ubuntu/intrepid/ruby1.8/intrepid-updates

« back to all changes in this revision

Viewing changes to missing/vsnprintf.c

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2007-03-13 22:11:58 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070313221158-h3oql37brlaf2go2
Tags: 1.8.6-1
* new upstream version, 1.8.6.
* libruby1.8 conflicts with libopenssl-ruby1.8 (< 1.8.6) (closes: #410018)
* changed packaging style to cdbs from dbs.

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