Ruby 2.0.0p247(2013-06-27revision41674)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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