Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
sprintf.c
Go to the documentation of this file.
1/**********************************************************************
2
3 sprintf.c -
4
5 $Author$
6 created at: Fri Oct 15 10:39:26 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12**********************************************************************/
13
14#include "ruby/encoding.h"
15#include "ruby/re.h"
16#include "internal.h"
17#include "id.h"
18#include <math.h>
19#include <stdarg.h>
20
21#ifdef HAVE_IEEEFP_H
22#include <ieeefp.h>
23#endif
24
25#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
26
27static char *fmt_setup(char*,size_t,int,int,int,int);
28static char *ruby_ultoa(unsigned long val, char *endp, int base, int octzero);
29
30static char
31sign_bits(int base, const char *p)
32{
33 char c = '.';
34
35 switch (base) {
36 case 16:
37 if (*p == 'X') c = 'F';
38 else c = 'f';
39 break;
40 case 8:
41 c = '7'; break;
42 case 2:
43 c = '1'; break;
44 }
45 return c;
46}
47
48#define FNONE 0
49#define FSHARP 1
50#define FMINUS 2
51#define FPLUS 4
52#define FZERO 8
53#define FSPACE 16
54#define FWIDTH 32
55#define FPREC 64
56#define FPREC0 128
57
58#define CHECK(l) do {\
59 int cr = ENC_CODERANGE(result);\
60 while ((l) >= bsiz - blen) {\
61 bsiz*=2;\
62 if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
63 }\
64 rb_str_resize(result, bsiz);\
65 ENC_CODERANGE_SET(result, cr);\
66 buf = RSTRING_PTR(result);\
67} while (0)
68
69#define PUSH(s, l) do { \
70 CHECK(l);\
71 PUSH_(s, l);\
72} while (0)
73
74#define PUSH_(s, l) do { \
75 memcpy(&buf[blen], (s), (l));\
76 blen += (l);\
77} while (0)
78
79#define FILL(c, l) do { \
80 if ((l) <= 0) break;\
81 CHECK(l);\
82 FILL_(c, l);\
83} while (0)
84
85#define FILL_(c, l) do { \
86 memset(&buf[blen], (c), (l));\
87 blen += (l);\
88} while (0)
89
90#define GETARG() (nextvalue != Qundef ? nextvalue : \
91 GETNEXTARG())
92
93#define GETNEXTARG() ( \
94 check_next_arg(posarg, nextarg), \
95 (posarg = nextarg++, GETNTHARG(posarg)))
96
97#define GETPOSARG(n) ( \
98 check_pos_arg(posarg, (n)), \
99 (posarg = -1, GETNTHARG(n)))
100
101#define GETNTHARG(nth) \
102 (((nth) >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[(nth)])
103
104#define CHECKNAMEARG(name, len, enc) ( \
105 check_name_arg(posarg, name, len, enc), \
106 posarg = -2)
107
108#define GETNUM(n, val) \
109 (!(p = get_num(p, end, enc, &(n))) ? \
110 rb_raise(rb_eArgError, #val " too big") : (void)0)
111
112#define GETASTER(val) do { \
113 t = p++; \
114 n = 0; \
115 GETNUM(n, val); \
116 if (*p == '$') { \
117 tmp = GETPOSARG(n); \
118 } \
119 else { \
120 tmp = GETNEXTARG(); \
121 p = t; \
122 } \
123 (val) = NUM2INT(tmp); \
124} while (0)
125
126static const char *
127get_num(const char *p, const char *end, rb_encoding *enc, int *valp)
128{
129 int next_n = *valp;
130 for (; p < end && rb_enc_isdigit(*p, enc); p++) {
131 if (MUL_OVERFLOW_INT_P(10, next_n))
132 return NULL;
133 next_n *= 10;
134 if (INT_MAX - (*p - '0') < next_n)
135 return NULL;
136 next_n += *p - '0';
137 }
138 if (p >= end) {
139 rb_raise(rb_eArgError, "malformed format string - %%*[0-9]");
140 }
141 *valp = next_n;
142 return p;
143}
144
145static void
146check_next_arg(int posarg, int nextarg)
147{
148 switch (posarg) {
149 case -1:
150 rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg);
151 case -2:
152 rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg);
153 }
154}
155
156static void
157check_pos_arg(int posarg, int n)
158{
159 if (posarg > 0) {
160 rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg);
161 }
162 if (posarg == -2) {
163 rb_raise(rb_eArgError, "numbered(%d) after named", n);
164 }
165 if (n < 1) {
166 rb_raise(rb_eArgError, "invalid index - %d$", n);
167 }
168}
169
170static void
171check_name_arg(int posarg, const char *name, int len, rb_encoding *enc)
172{
173 if (posarg > 0) {
174 rb_enc_raise(enc, rb_eArgError, "named%.*s after unnumbered(%d)", len, name, posarg);
175 }
176 if (posarg == -1) {
177 rb_enc_raise(enc, rb_eArgError, "named%.*s after numbered", len, name);
178 }
179}
180
181static VALUE
182get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
183{
184 VALUE tmp;
185
186 if (*hash != Qundef) return *hash;
187 if (argc != 2) {
188 rb_raise(rb_eArgError, "one hash required");
189 }
190 tmp = rb_check_hash_type(argv[1]);
191 if (NIL_P(tmp)) {
192 rb_raise(rb_eArgError, "one hash required");
193 }
194 return (*hash = tmp);
195}
196
197VALUE
199{
200 return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
201}
202
203VALUE
205{
206 enum {default_float_precision = 6};
207 rb_encoding *enc;
208 const char *p, *end;
209 char *buf;
210 long blen, bsiz;
211 VALUE result;
212
213 long scanned = 0;
214 int coderange = ENC_CODERANGE_7BIT;
215 int width, prec, flags = FNONE;
216 int nextarg = 1;
217 int posarg = 0;
218 VALUE nextvalue;
219 VALUE tmp;
220 VALUE orig;
221 VALUE str;
222 volatile VALUE hash = Qundef;
223
224#define CHECK_FOR_WIDTH(f) \
225 if ((f) & FWIDTH) { \
226 rb_raise(rb_eArgError, "width given twice"); \
227 } \
228 if ((f) & FPREC0) { \
229 rb_raise(rb_eArgError, "width after precision"); \
230 }
231#define CHECK_FOR_FLAGS(f) \
232 if ((f) & FWIDTH) { \
233 rb_raise(rb_eArgError, "flag after width"); \
234 } \
235 if ((f) & FPREC0) { \
236 rb_raise(rb_eArgError, "flag after precision"); \
237 }
238
239 ++argc;
240 --argv;
242 enc = rb_enc_get(fmt);
243 orig = fmt;
245 p = RSTRING_PTR(fmt);
246 end = p + RSTRING_LEN(fmt);
247 blen = 0;
248 bsiz = 120;
249 result = rb_str_buf_new(bsiz);
250 rb_enc_copy(result, fmt);
251 buf = RSTRING_PTR(result);
252 memset(buf, 0, bsiz);
253 ENC_CODERANGE_SET(result, coderange);
254
255 for (; p < end; p++) {
256 const char *t;
257 int n;
258 VALUE sym = Qnil;
259
260 for (t = p; t < end && *t != '%'; t++) ;
261 if (t + 1 == end) {
262 rb_raise(rb_eArgError, "incomplete format specifier; use %%%% (double %%) instead");
263 }
264 PUSH(p, t - p);
265 if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
266 scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange);
267 ENC_CODERANGE_SET(result, coderange);
268 }
269 if (t >= end) {
270 /* end of fmt string */
271 goto sprint_exit;
272 }
273 p = t + 1; /* skip `%' */
274
275 width = prec = -1;
276 nextvalue = Qundef;
277 retry:
278 switch (*p) {
279 default:
280 if (rb_enc_isprint(*p, enc))
281 rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
282 else
283 rb_raise(rb_eArgError, "malformed format string");
284 break;
285
286 case ' ':
287 CHECK_FOR_FLAGS(flags);
288 flags |= FSPACE;
289 p++;
290 goto retry;
291
292 case '#':
293 CHECK_FOR_FLAGS(flags);
294 flags |= FSHARP;
295 p++;
296 goto retry;
297
298 case '+':
299 CHECK_FOR_FLAGS(flags);
300 flags |= FPLUS;
301 p++;
302 goto retry;
303
304 case '-':
305 CHECK_FOR_FLAGS(flags);
306 flags |= FMINUS;
307 p++;
308 goto retry;
309
310 case '0':
311 CHECK_FOR_FLAGS(flags);
312 flags |= FZERO;
313 p++;
314 goto retry;
315
316 case '1': case '2': case '3': case '4':
317 case '5': case '6': case '7': case '8': case '9':
318 n = 0;
319 GETNUM(n, width);
320 if (*p == '$') {
321 if (nextvalue != Qundef) {
322 rb_raise(rb_eArgError, "value given twice - %d$", n);
323 }
324 nextvalue = GETPOSARG(n);
325 p++;
326 goto retry;
327 }
328 CHECK_FOR_WIDTH(flags);
329 width = n;
330 flags |= FWIDTH;
331 goto retry;
332
333 case '<':
334 case '{':
335 {
336 const char *start = p;
337 char term = (*p == '<') ? '>' : '}';
338 int len;
339
340 for (; p < end && *p != term; ) {
341 p += rb_enc_mbclen(p, end, enc);
342 }
343 if (p >= end) {
344 rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
345 }
346#if SIZEOF_INT < SIZEOF_SIZE_T
347 if ((size_t)(p - start) >= INT_MAX) {
348 const int message_limit = 20;
349 len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
351 "too long name (%"PRIuSIZE" bytes) - %.*s...%c",
352 (size_t)(p - start - 2), len, start, term);
353 }
354#endif
355 len = (int)(p - start + 1); /* including parenthesis */
356 if (sym != Qnil) {
357 rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
358 len, start, rb_sym2str(sym));
359 }
360 CHECKNAMEARG(start, len, enc);
361 get_hash(&hash, argc, argv);
362 sym = rb_check_symbol_cstr(start + 1,
363 len - 2 /* without parenthesis */,
364 enc);
365 if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
366 if (nextvalue == Qundef) {
367 if (NIL_P(sym)) {
368 sym = rb_sym_intern(start + 1,
369 len - 2 /* without parenthesis */,
370 enc);
371 }
372 nextvalue = rb_hash_default_value(hash, sym);
373 if (NIL_P(nextvalue)) {
374 rb_key_err_raise(rb_enc_sprintf(enc, "key%.*s not found", len, start), hash, sym);
375 }
376 }
377 if (term == '}') goto format_s;
378 p++;
379 goto retry;
380 }
381
382 case '*':
383 CHECK_FOR_WIDTH(flags);
384 flags |= FWIDTH;
385 GETASTER(width);
386 if (width < 0) {
387 flags |= FMINUS;
388 width = -width;
389 if (width < 0) rb_raise(rb_eArgError, "width too big");
390 }
391 p++;
392 goto retry;
393
394 case '.':
395 if (flags & FPREC0) {
396 rb_raise(rb_eArgError, "precision given twice");
397 }
398 flags |= FPREC|FPREC0;
399
400 prec = 0;
401 p++;
402 if (*p == '*') {
403 GETASTER(prec);
404 if (prec < 0) { /* ignore negative precision */
405 flags &= ~FPREC;
406 }
407 p++;
408 goto retry;
409 }
410
411 GETNUM(prec, precision);
412 goto retry;
413
414 case '\n':
415 case '\0':
416 p--;
417 /* fall through */
418 case '%':
419 if (flags != FNONE) {
420 rb_raise(rb_eArgError, "invalid format character - %%");
421 }
422 PUSH("%", 1);
423 break;
424
425 case 'c':
426 {
427 VALUE val = GETARG();
428 VALUE tmp;
429 unsigned int c;
430 int n;
431
432 tmp = rb_check_string_type(val);
433 if (!NIL_P(tmp)) {
434 if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) {
435 rb_raise(rb_eArgError, "%%c requires a character");
436 }
437 c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc);
438 RB_GC_GUARD(tmp);
439 }
440 else {
441 c = NUM2INT(val);
442 n = rb_enc_codelen(c, enc);
443 }
444 if (n <= 0) {
445 rb_raise(rb_eArgError, "invalid character");
446 }
447 if (!(flags & FWIDTH)) {
448 CHECK(n);
449 rb_enc_mbcput(c, &buf[blen], enc);
450 blen += n;
451 }
452 else if ((flags & FMINUS)) {
453 CHECK(n);
454 rb_enc_mbcput(c, &buf[blen], enc);
455 blen += n;
456 if (width > 1) FILL(' ', width-1);
457 }
458 else {
459 if (width > 1) FILL(' ', width-1);
460 CHECK(n);
461 rb_enc_mbcput(c, &buf[blen], enc);
462 blen += n;
463 }
464 }
465 break;
466
467 case 's':
468 case 'p':
469 format_s:
470 {
471 VALUE arg = GETARG();
472 long len, slen;
473
474 if (*p == 'p') {
475 str = rb_inspect(arg);
476 }
477 else {
479 }
481 rb_str_set_len(result, blen);
482 if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
483 int cr = coderange;
484 scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr);
485 ENC_CODERANGE_SET(result,
486 (cr == ENC_CODERANGE_UNKNOWN ?
487 ENC_CODERANGE_BROKEN : (coderange = cr)));
488 }
489 enc = rb_enc_check(result, str);
490 if (flags&(FPREC|FWIDTH)) {
492 if (slen < 0) {
493 rb_raise(rb_eArgError, "invalid mbstring sequence");
494 }
495 if ((flags&FPREC) && (prec < slen)) {
497 prec, enc);
498 slen = prec;
499 len = p - RSTRING_PTR(str);
500 }
501 /* need to adjust multi-byte string pos */
502 if ((flags&FWIDTH) && (width > slen)) {
503 width -= (int)slen;
504 if (!(flags&FMINUS)) {
505 FILL(' ', width);
506 width = 0;
507 }
508 CHECK(len);
509 memcpy(&buf[blen], RSTRING_PTR(str), len);
511 blen += len;
512 if (flags&FMINUS) {
513 FILL(' ', width);
514 }
515 rb_enc_associate(result, enc);
516 break;
517 }
518 }
521 rb_enc_associate(result, enc);
522 }
523 break;
524
525 case 'd':
526 case 'i':
527 case 'o':
528 case 'x':
529 case 'X':
530 case 'b':
531 case 'B':
532 case 'u':
533 {
534 volatile VALUE val = GETARG();
535 int valsign;
536 char nbuf[BIT_DIGITS(SIZEOF_LONG*CHAR_BIT)+2], *s;
537 const char *prefix = 0;
538 int sign = 0, dots = 0;
539 char sc = 0;
540 long v = 0;
541 int base, bignum = 0;
542 int len;
543
544 switch (*p) {
545 case 'd':
546 case 'i':
547 case 'u':
548 sign = 1; break;
549 case 'o':
550 case 'x':
551 case 'X':
552 case 'b':
553 case 'B':
554 if (flags&(FPLUS|FSPACE)) sign = 1;
555 break;
556 }
557 if (flags & FSHARP) {
558 switch (*p) {
559 case 'o':
560 prefix = "0"; break;
561 case 'x':
562 prefix = "0x"; break;
563 case 'X':
564 prefix = "0X"; break;
565 case 'b':
566 prefix = "0b"; break;
567 case 'B':
568 prefix = "0B"; break;
569 }
570 }
571
572 bin_retry:
573 switch (TYPE(val)) {
574 case T_FLOAT:
575 if (FIXABLE(RFLOAT_VALUE(val))) {
576 val = LONG2FIX((long)RFLOAT_VALUE(val));
577 goto bin_retry;
578 }
579 val = rb_dbl2big(RFLOAT_VALUE(val));
580 if (FIXNUM_P(val)) goto bin_retry;
581 bignum = 1;
582 break;
583 case T_STRING:
584 val = rb_str_to_inum(val, 0, TRUE);
585 goto bin_retry;
586 case T_BIGNUM:
587 bignum = 1;
588 break;
589 case T_FIXNUM:
590 v = FIX2LONG(val);
591 break;
592 default:
593 val = rb_Integer(val);
594 goto bin_retry;
595 }
596
597 switch (*p) {
598 case 'o':
599 base = 8; break;
600 case 'x':
601 case 'X':
602 base = 16; break;
603 case 'b':
604 case 'B':
605 base = 2; break;
606 case 'u':
607 case 'd':
608 case 'i':
609 default:
610 base = 10; break;
611 }
612
613 if (base != 10) {
614 int numbits = ffs(base)-1;
615 size_t abs_nlz_bits;
616 size_t numdigits = rb_absint_numwords(val, numbits, &abs_nlz_bits);
617 long i;
618 if (INT_MAX-1 < numdigits) /* INT_MAX is used because rb_long2int is used later. */
619 rb_raise(rb_eArgError, "size too big");
620 if (sign) {
621 if (numdigits == 0)
622 numdigits = 1;
623 tmp = rb_str_new(NULL, numdigits);
624 valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
626 for (i = 0; i < RSTRING_LEN(tmp); i++)
627 RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
628 s = RSTRING_PTR(tmp);
629 if (valsign < 0) {
630 sc = '-';
631 width--;
632 }
633 else if (flags & FPLUS) {
634 sc = '+';
635 width--;
636 }
637 else if (flags & FSPACE) {
638 sc = ' ';
639 width--;
640 }
641 }
642 else {
643 /* Following conditional "numdigits++" guarantees the
644 * most significant digit as
645 * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers
646 * - '0' for zero
647 * - not '0' for positive numbers.
648 *
649 * It also guarantees the most significant two
650 * digits will not be '11'(bin), '77'(oct), 'ff'(hex)
651 * or '00'. */
652 if (numdigits == 0 ||
653 ((abs_nlz_bits != (size_t)(numbits-1) ||
654 !rb_absint_singlebit_p(val)) &&
655 (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val))))
656 numdigits++;
657 tmp = rb_str_new(NULL, numdigits);
658 valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
660 for (i = 0; i < RSTRING_LEN(tmp); i++)
661 RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
662 s = RSTRING_PTR(tmp);
663 dots = valsign < 0;
664 }
665 len = rb_long2int(RSTRING_END(tmp) - s);
666 }
667 else if (!bignum) {
668 valsign = 1;
669 if (v < 0) {
670 v = -v;
671 sc = '-';
672 width--;
673 valsign = -1;
674 }
675 else if (flags & FPLUS) {
676 sc = '+';
677 width--;
678 }
679 else if (flags & FSPACE) {
680 sc = ' ';
681 width--;
682 }
683 s = ruby_ultoa((unsigned long)v, nbuf + sizeof(nbuf), 10, 0);
684 len = (int)(nbuf + sizeof(nbuf) - s);
685 }
686 else {
687 tmp = rb_big2str(val, 10);
688 s = RSTRING_PTR(tmp);
689 valsign = 1;
690 if (s[0] == '-') {
691 s++;
692 sc = '-';
693 width--;
694 valsign = -1;
695 }
696 else if (flags & FPLUS) {
697 sc = '+';
698 width--;
699 }
700 else if (flags & FSPACE) {
701 sc = ' ';
702 width--;
703 }
704 len = rb_long2int(RSTRING_END(tmp) - s);
705 }
706
707 if (dots) {
708 prec -= 2;
709 width -= 2;
710 }
711
712 if (*p == 'X') {
713 char *pp = s;
714 int c;
715 while ((c = (int)(unsigned char)*pp) != 0) {
716 *pp = rb_enc_toupper(c, enc);
717 pp++;
718 }
719 }
720 if (prefix && !prefix[1]) { /* octal */
721 if (dots) {
722 prefix = 0;
723 }
724 else if (len == 1 && *s == '0') {
725 len = 0;
726 if (flags & FPREC) prec--;
727 }
728 else if ((flags & FPREC) && (prec > len)) {
729 prefix = 0;
730 }
731 }
732 else if (len == 1 && *s == '0') {
733 prefix = 0;
734 }
735 if (prefix) {
736 width -= (int)strlen(prefix);
737 }
738 if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
739 prec = width;
740 width = 0;
741 }
742 else {
743 if (prec < len) {
744 if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
745 prec = len;
746 }
747 width -= prec;
748 }
749 if (!(flags&FMINUS)) {
750 FILL(' ', width);
751 width = 0;
752 }
753 if (sc) PUSH(&sc, 1);
754 if (prefix) {
755 int plen = (int)strlen(prefix);
756 PUSH(prefix, plen);
757 }
758 if (dots) PUSH("..", 2);
759 if (prec > len) {
760 CHECK(prec - len);
761 if (!sign && valsign < 0) {
762 char c = sign_bits(base, p);
763 FILL_(c, prec - len);
764 }
765 else if ((flags & (FMINUS|FPREC)) != FMINUS) {
766 FILL_('0', prec - len);
767 }
768 }
769 PUSH(s, len);
770 RB_GC_GUARD(tmp);
771 FILL(' ', width);
772 }
773 break;
774
775 case 'f':
776 {
777 VALUE val = GETARG(), num, den;
778 int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
779 long len, fill;
780 if (RB_INTEGER_TYPE_P(val)) {
781 den = INT2FIX(1);
782 num = val;
783 }
784 else if (RB_TYPE_P(val, T_RATIONAL)) {
785 den = rb_rational_den(val);
786 num = rb_rational_num(val);
787 }
788 else {
789 nextvalue = val;
790 goto float_value;
791 }
792 if (!(flags&FPREC)) prec = default_float_precision;
793 if (FIXNUM_P(num)) {
794 if ((SIGNED_VALUE)num < 0) {
795 long n = -FIX2LONG(num);
796 num = LONG2FIX(n);
797 sign = -1;
798 }
799 }
800 else if (BIGNUM_NEGATIVE_P(num)) {
801 sign = -1;
802 num = rb_big_uminus(num);
803 }
804 if (den != INT2FIX(1)) {
805 num = rb_int_mul(num, rb_int_positive_pow(10, prec));
806 num = rb_int_plus(num, rb_int_idiv(den, INT2FIX(2)));
807 num = rb_int_idiv(num, den);
808 }
809 else if (prec >= 0) {
810 zero = prec;
811 }
812 val = rb_int2str(num, 10);
813 len = RSTRING_LEN(val) + zero;
814 if (prec >= len) len = prec + 1; /* integer part 0 */
815 if (sign || (flags&FSPACE)) ++len;
816 if (prec > 0) ++len; /* period */
817 fill = width > len ? width - len : 0;
818 CHECK(fill + len);
819 if (fill && !(flags&(FMINUS|FZERO))) {
820 FILL_(' ', fill);
821 }
822 if (sign || (flags&FSPACE)) {
823 buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
824 }
825 if (fill && (flags&(FMINUS|FZERO)) == FZERO) {
826 FILL_('0', fill);
827 }
828 len = RSTRING_LEN(val) + zero;
829 t = RSTRING_PTR(val);
830 if (len > prec) {
831 PUSH_(t, len - prec);
832 }
833 else {
834 buf[blen++] = '0';
835 }
836 if (prec > 0) {
837 buf[blen++] = '.';
838 }
839 if (zero) {
840 FILL_('0', zero);
841 }
842 else if (prec > len) {
843 FILL_('0', prec - len);
844 PUSH_(t, len);
845 }
846 else if (prec > 0) {
847 PUSH_(t + len - prec, prec);
848 }
849 if (fill && (flags&FMINUS)) {
850 FILL_(' ', fill);
851 }
852 RB_GC_GUARD(val);
853 break;
854 }
855 case 'g':
856 case 'G':
857 case 'e':
858 case 'E':
859 /* TODO: rational support */
860 case 'a':
861 case 'A':
862 float_value:
863 {
864 VALUE val = GETARG();
865 double fval;
866
867 fval = RFLOAT_VALUE(rb_Float(val));
868 if (isnan(fval) || isinf(fval)) {
869 const char *expr;
870 int need;
871 int elen;
872 char sign = '\0';
873
874 if (isnan(fval)) {
875 expr = "NaN";
876 }
877 else {
878 expr = "Inf";
879 }
880 need = (int)strlen(expr);
881 elen = need;
882 if (!isnan(fval) && fval < 0.0)
883 sign = '-';
884 else if (flags & (FPLUS|FSPACE))
885 sign = (flags & FPLUS) ? '+' : ' ';
886 if (sign)
887 ++need;
888 if ((flags & FWIDTH) && need < width)
889 need = width;
890
891 FILL(' ', need);
892 if (flags & FMINUS) {
893 if (sign)
894 buf[blen - need--] = sign;
895 memcpy(&buf[blen - need], expr, elen);
896 }
897 else {
898 if (sign)
899 buf[blen - elen - 1] = sign;
900 memcpy(&buf[blen - elen], expr, elen);
901 }
902 break;
903 }
904 else {
905 int cr = ENC_CODERANGE(result);
906 char fbuf[2*BIT_DIGITS(SIZEOF_INT*CHAR_BIT)+10];
907 char *fmt = fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
908 rb_str_set_len(result, blen);
909 rb_str_catf(result, fmt, fval);
910 ENC_CODERANGE_SET(result, cr);
911 bsiz = rb_str_capacity(result);
912 RSTRING_GETMEM(result, buf, blen);
913 }
914 }
915 break;
916 }
917 flags = FNONE;
918 }
919
920 sprint_exit:
922 /* XXX - We cannot validate the number of arguments if (digit)$ style used.
923 */
924 if (posarg >= 0 && nextarg < argc) {
925 const char *mesg = "too many arguments for format string";
926 if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
927 if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
928 }
929 rb_str_resize(result, blen);
930
931 return result;
932}
933
934static char *
935fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
936{
937 buf += size;
938 *--buf = '\0';
939 *--buf = c;
940
941 if (flags & FPREC) {
942 buf = ruby_ultoa(prec, buf, 10, 0);
943 *--buf = '.';
944 }
945
946 if (flags & FWIDTH) {
947 buf = ruby_ultoa(width, buf, 10, 0);
948 }
949
950 if (flags & FSPACE) *--buf = ' ';
951 if (flags & FZERO) *--buf = '0';
952 if (flags & FMINUS) *--buf = '-';
953 if (flags & FPLUS) *--buf = '+';
954 if (flags & FSHARP) *--buf = '#';
955 *--buf = '%';
956 return buf;
957}
958
959#undef FILE
960#define FILE rb_printf_buffer
961#define __sbuf rb_printf_sbuf
962#define __sFILE rb_printf_sfile
963#undef feof
964#undef ferror
965#undef clearerr
966#undef fileno
967#if SIZEOF_LONG < SIZEOF_VOIDP
968# if SIZEOF_LONG_LONG == SIZEOF_VOIDP
969# define _HAVE_SANE_QUAD_
970# define _HAVE_LLP64_
971# define quad_t LONG_LONG
972# define u_quad_t unsigned LONG_LONG
973# endif
974#elif SIZEOF_LONG != SIZEOF_LONG_LONG && SIZEOF_LONG_LONG == 8
975# define _HAVE_SANE_QUAD_
976# define quad_t LONG_LONG
977# define u_quad_t unsigned LONG_LONG
978#endif
979#define FLOATING_POINT 1
980#define BSD__dtoa ruby_dtoa
981#define BSD__hdtoa ruby_hdtoa
982#ifdef RUBY_PRI_VALUE_MARK
983# define PRI_EXTRA_MARK RUBY_PRI_VALUE_MARK
984#endif
985#define lower_hexdigits (ruby_hexdigits+0)
986#define upper_hexdigits (ruby_hexdigits+16)
987#if defined RUBY_USE_SETJMPEX && RUBY_USE_SETJMPEX
988# undef MAYBE_UNUSED
989# define MAYBE_UNUSED(x) x = 0
990#endif
991#include "vsnprintf.c"
992
993static char *
994ruby_ultoa(unsigned long val, char *endp, int base, int flags)
995{
996 const char *xdigs = lower_hexdigits;
997 int octzero = flags & FSHARP;
998 return BSD__ultoa(val, endp, base, octzero, xdigs);
999}
1000
1001static int ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
1002
1003int
1004ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
1005{
1006 if (str && (ssize_t)n < 1)
1007 return (EOF);
1008 return ruby_do_vsnprintf(str, n, fmt, ap);
1009}
1010
1011static int
1012ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
1013{
1014 ssize_t ret;
1015 rb_printf_buffer f;
1016
1017 f._flags = __SWR | __SSTR;
1018 f._bf._base = f._p = (unsigned char *)str;
1019 f._bf._size = f._w = str ? (n - 1) : 0;
1020 f.vwrite = BSD__sfvwrite;
1021 f.vextra = 0;
1022 ret = BSD_vfprintf(&f, fmt, ap);
1023 if (str) *f._p = 0;
1024#if SIZEOF_SIZE_T > SIZEOF_INT
1025 if (n > INT_MAX) return INT_MAX;
1026#endif
1027 return (int)ret;
1028}
1029
1030int
1031ruby_snprintf(char *str, size_t n, char const *fmt, ...)
1032{
1033 int ret;
1034 va_list ap;
1035
1036 if (str && (ssize_t)n < 1)
1037 return (EOF);
1038
1039 va_start(ap, fmt);
1040 ret = ruby_do_vsnprintf(str, n, fmt, ap);
1041 va_end(ap);
1042 return ret;
1043}
1044
1045typedef struct {
1046 rb_printf_buffer base;
1047 volatile VALUE value;
1049
1050static int
1051ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
1052{
1053 struct __siov *iov;
1054 VALUE result = (VALUE)fp->_bf._base;
1055 char *buf = (char*)fp->_p;
1056 long len, n;
1057 long blen = buf - RSTRING_PTR(result), bsiz = fp->_w;
1058
1059 if (RBASIC(result)->klass) {
1060 rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
1061 }
1062 if (uio->uio_resid == 0)
1063 return 0;
1064#if SIZE_MAX > LONG_MAX
1065 if (uio->uio_resid >= LONG_MAX)
1066 rb_raise(rb_eRuntimeError, "too big string");
1067#endif
1068 len = (long)uio->uio_resid;
1069 CHECK(len);
1070 buf += blen;
1071 fp->_w = bsiz;
1072 for (iov = uio->uio_iov; len > 0; ++iov) {
1073 MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
1074 buf += n;
1075 len -= n;
1076 }
1077 fp->_p = (unsigned char *)buf;
1078 rb_str_set_len(result, buf - RSTRING_PTR(result));
1079 return 0;
1080}
1081
1082static const char *
1083ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz, int sign)
1084{
1085 VALUE value, result = (VALUE)fp->_bf._base;
1086 rb_encoding *enc;
1087 char *cp;
1088
1089 if (valsize != sizeof(VALUE)) return 0;
1090 value = *(VALUE *)valp;
1091 if (RBASIC(result)->klass) {
1092 rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
1093 }
1094 if (sign == '+') {
1095 if (RB_TYPE_P(value, T_CLASS)) {
1096# define LITERAL(str) (*sz = rb_strlen_lit(str), str)
1097
1098 if (value == rb_cNilClass) {
1099 return LITERAL("nil");
1100 }
1101 else if (value == rb_cInteger) {
1102 return LITERAL("Integer");
1103 }
1104 else if (value == rb_cSymbol) {
1105 return LITERAL("Symbol");
1106 }
1107 else if (value == rb_cTrueClass) {
1108 return LITERAL("true");
1109 }
1110 else if (value == rb_cFalseClass) {
1111 return LITERAL("false");
1112 }
1113# undef LITERAL
1114 }
1115 value = rb_inspect(value);
1116 }
1117 else if (SYMBOL_P(value)) {
1118 value = rb_sym2str(value);
1119 if (sign == ' ' && !rb_str_symname_p(value)) {
1120 value = rb_str_inspect(value);
1121 }
1122 }
1123 else {
1124 value = rb_obj_as_string(value);
1125 if (sign == ' ') value = QUOTE(value);
1126 }
1127 enc = rb_enc_compatible(result, value);
1128 if (enc) {
1129 rb_enc_associate(result, enc);
1130 }
1131 else {
1132 enc = rb_enc_get(result);
1133 value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
1135 Qnil);
1136 *(volatile VALUE *)valp = value;
1137 }
1138 StringValueCStr(value);
1139 RSTRING_GETMEM(value, cp, *sz);
1140 ((rb_printf_buffer_extra *)fp)->value = value;
1141 return cp;
1142}
1143
1144VALUE
1146{
1148#define f buffer.base
1149 VALUE result;
1150
1151 f._flags = __SWR | __SSTR;
1152 f._bf._size = 0;
1153 f._w = 120;
1154 result = rb_str_buf_new(f._w);
1155 if (enc) {
1156 if (rb_enc_mbminlen(enc) > 1) {
1157 /* the implementation deeply depends on plain char */
1158 rb_raise(rb_eArgError, "cannot construct wchar_t based encoding string: %s",
1159 rb_enc_name(enc));
1160 }
1161 rb_enc_associate(result, enc);
1162 }
1163 f._bf._base = (unsigned char *)result;
1164 f._p = (unsigned char *)RSTRING_PTR(result);
1165 RBASIC_CLEAR_CLASS(result);
1166 f.vwrite = ruby__sfvwrite;
1167 f.vextra = ruby__sfvextra;
1168 buffer.value = 0;
1169 BSD_vfprintf(&f, fmt, ap);
1171 rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
1172#undef f
1173
1174 return result;
1175}
1176
1177VALUE
1178rb_enc_sprintf(rb_encoding *enc, const char *format, ...)
1179{
1180 VALUE result;
1181 va_list ap;
1182
1183 va_start(ap, format);
1184 result = rb_enc_vsprintf(enc, format, ap);
1185 va_end(ap);
1186
1187 return result;
1188}
1189
1190VALUE
1191rb_vsprintf(const char *fmt, va_list ap)
1192{
1193 return rb_enc_vsprintf(NULL, fmt, ap);
1194}
1195
1196VALUE
1197rb_sprintf(const char *format, ...)
1198{
1199 VALUE result;
1200 va_list ap;
1201
1202 va_start(ap, format);
1203 result = rb_vsprintf(format, ap);
1204 va_end(ap);
1205
1206 return result;
1207}
1208
1209VALUE
1211{
1213#define f buffer.base
1214 VALUE klass;
1215
1218 f._flags = __SWR | __SSTR;
1219 f._bf._size = 0;
1220 f._w = rb_str_capacity(str);
1221 f._bf._base = (unsigned char *)str;
1222 f._p = (unsigned char *)RSTRING_END(str);
1223 klass = RBASIC(str)->klass;
1225 f.vwrite = ruby__sfvwrite;
1226 f.vextra = ruby__sfvextra;
1227 buffer.value = 0;
1228 BSD_vfprintf(&f, fmt, ap);
1230 rb_str_resize(str, (char *)f._p - RSTRING_PTR(str));
1231#undef f
1232
1233 return str;
1234}
1235
1236VALUE
1237rb_str_catf(VALUE str, const char *format, ...)
1238{
1239 va_list ap;
1240
1241 va_start(ap, format);
1242 str = rb_str_vcatf(str, format, ap);
1243 va_end(ap);
1244
1245 return str;
1246}
#define sym(x)
Definition: date_core.c:3717
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
Definition: encoding.c:1068
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:990
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
Definition: encoding.c:891
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:974
int rb_enc_toupper(int c, rb_encoding *enc)
Definition: encoding.c:1106
int rb_enc_codelen(int c, rb_encoding *enc)
Definition: encoding.c:1089
#define ENC_CODERANGE_7BIT
Definition: encoding.h:104
#define rb_enc_mbcput(c, buf, enc)
Definition: encoding.h:217
#define ECONV_UNDEF_REPLACE
Definition: encoding.h:396
#define ENC_CODERANGE(obj)
Definition: encoding.h:108
#define ENC_CODERANGE_UNKNOWN
Definition: encoding.h:103
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Definition: string.c:914
#define rb_enc_name(enc)
Definition: encoding.h:177
#define ECONV_INVALID_REPLACE
Definition: encoding.h:394
#define rb_enc_isdigit(c, enc)
Definition: encoding.h:238
#define rb_enc_isprint(c, enc)
Definition: encoding.h:236
#define rb_enc_mbminlen(enc)
Definition: encoding.h:180
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:999
long rb_enc_strlen(const char *, const char *, rb_encoding *)
Definition: string.c:1740
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:106
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:567
#define rb_enc_right_char_head(s, p, e, enc)
Definition: encoding.h:223
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:110
char * rb_enc_nth(const char *, const char *, long, rb_encoding *)
Definition: string.c:2388
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_cTrueClass
TrueClass class.
Definition: ruby.h:2051
VALUE rb_cNilClass
NilClass class.
Definition: ruby.h:2038
VALUE rb_cInteger
Definition: ruby.h:2033
VALUE rb_cString
Definition: ruby.h:2046
int ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
Definition: sprintf.c:1004
VALUE rb_cFalseClass
FalseClass class.
Definition: ruby.h:2024
VALUE rb_cSymbol
Definition: ruby.h:2048
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
VALUE rb_eRuntimeError
Definition: error.c:922
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
Definition: error.c:2652
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
Definition: object.c:3493
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
Definition: object.c:3106
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
const char term
Definition: id.c:37
const char * name
Definition: nkf.c:208
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3547
#define ruby_debug
#define MEMCPY(p1, p2, type, n)
#define NULL
VALUE rb_hash_default_value(VALUE hash, VALUE key)
Definition: hash.c:1990
#define RBASIC_CLEAR_CLASS(obj)
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
use StringValue() instead")))
#define RSTRING_LEN(str)
#define RTEST(v)
#define RBASIC(obj)
int rb_str_symname_p(VALUE)
Definition: string.c:10695
size_t strlen(const char *)
#define T_STRING
#define SIZEOF_LONG
#define PRIuSIZE
#define LONG2FIX(i)
#define Qundef
#define CHAR_BIT
VALUE rb_dbl2big(double)
Definition: bignum.c:5249
#define RSTRING_END(str)
#define TYPE(x)
#define T_FLOAT
#define RSTRING_PTR(str)
#define T_BIGNUM
#define SIZEOF_INT
#define rb_str_new(str, len)
#define NIL_P(v)
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
Definition: bignum.c:3382
int rb_absint_singlebit_p(VALUE val)
Definition: bignum.c:3446
#define LONG_MAX
#define T_FIXNUM
VALUE rb_int2str(VALUE num, int base)
Definition: numeric.c:3567
const char size_t n
#define ruby_verbose
#define EOF
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
unsigned long VALUE
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
void rb_str_modify(VALUE)
Definition: string.c:2114
VALUE rb_hash_lookup2(VALUE, VALUE, VALUE)
Definition: hash.c:2050
VALUE rb_str_buf_new(long)
Definition: string.c:1315
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:4038
VALUE rb_str_inspect(VALUE)
Definition: string.c:5930
#define isinf(__x)
#define MUL_OVERFLOW_INT_P(a, b)
uint32_t i
VALUE rb_rational_num(VALUE rat)
Definition: rational.c:1972
#define isnan(__x)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
__inline__ const void *__restrict__ size_t len
const VALUE int int int int int int VALUE char * fmt
#define INTEGER_PACK_BIG_ENDIAN
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1210
#define __SSTR
#define T_RATIONAL
#define va_end(v)
__gnuc_va_list va_list
#define long
#define NUM2INT(x)
VALUE rb_str_to_inum(VALUE, int, int)
Definition: bignum.c:4268
#define rb_long2int(n)
#define RB_GC_GUARD(v)
#define PRIsVALUE
const char ruby_digitmap[]
Definition: bignum.c:38
void * memset(void *, int, size_t)
int VALUE v
int ffs(int) __attribute__((__const__))
Definition: ffs.c:6
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1217
#define INT_MAX
#define va_start(v, l)
#define INTEGER_PACK_2COMP
#define RBASIC_SET_CLASS_RAW(obj, cls)
#define RFLOAT_VALUE(v)
#define rb_key_err_raise(mesg, recv, name)
#define TRUE
unsigned int size
struct rb_call_cache buf
#define Qnil
void * memcpy(void *__restrict__, const void *__restrict__, size_t)
#define SIGNED_VALUE
VALUE rb_check_hash_type(VALUE)
Definition: hash.c:1852
#define FIXABLE(f)
#define RB_TYPE_P(obj, type)
#define INT2FIX(i)
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
#define BIGNUM_NEGATIVE_P(b)
const VALUE * argv
#define SYMBOL_P(x)
_ssize_t ssize_t
__inline__ int
#define FIXNUM_P(f)
#define T_CLASS
VALUE rb_big_uminus(VALUE x)
Definition: bignum.c:5554
if((__builtin_expect(!!(!me), 0)))
#define RB_INTEGER_TYPE_P(obj)
#define QUOTE(str)
VALUE rb_int_idiv(VALUE x, VALUE y)
Definition: numeric.c:3848
VALUE rb_big2str(VALUE, int)
Definition: bignum.c:5091
#define FIX2LONG(x)
#define __SWR
VALUE rb_rational_den(VALUE rat)
Definition: rational.c:1978
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3615
#define StringValueCStr(v)
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3704
#define get_num(num)
Definition: ripper.c:593
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Definition: sprintf.c:204
VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
Definition: sprintf.c:1145
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Definition: sprintf.c:198
#define GETASTER(val)
Definition: sprintf.c:112
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
Definition: sprintf.c:1178
#define FILL(c, l)
Definition: sprintf.c:79
#define CHECK_FOR_FLAGS(f)
#define FZERO
Definition: sprintf.c:52
VALUE rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
Definition: sprintf.c:1210
#define GETNUM(n, val)
Definition: sprintf.c:108
#define FPREC0
Definition: sprintf.c:56
VALUE rb_vsprintf(const char *fmt, va_list ap)
Definition: sprintf.c:1191
#define FWIDTH
Definition: sprintf.c:54
#define GETNTHARG(nth)
Definition: sprintf.c:101
#define f
#define GETPOSARG(n)
Definition: sprintf.c:97
#define PUSH(s, l)
Definition: sprintf.c:69
#define CHECK_FOR_WIDTH(f)
#define CHECKNAMEARG(name, len, enc)
Definition: sprintf.c:104
#define FMINUS
Definition: sprintf.c:50
#define GETARG()
Definition: sprintf.c:90
#define CHECK(l)
Definition: sprintf.c:58
#define LITERAL(str)
#define FSPACE
Definition: sprintf.c:53
#define FNONE
Definition: sprintf.c:48
#define PUSH_(s, l)
Definition: sprintf.c:74
#define FPLUS
Definition: sprintf.c:51
#define FILL_(c, l)
Definition: sprintf.c:85
#define FPREC
Definition: sprintf.c:55
#define FSHARP
Definition: sprintf.c:49
#define lower_hexdigits
Definition: sprintf.c:985
#define BIT_DIGITS(N)
Definition: sprintf.c:25
int ruby_snprintf(char *str, size_t n, char const *fmt,...)
Definition: sprintf.c:1031
size_t rb_str_capacity(VALUE str)
Definition: string.c:712
size_t iov_len
Definition: vsnprintf.c:228
const void * iov_base
Definition: vsnprintf.c:227
struct __siov * uio_iov
Definition: vsnprintf.c:231
size_t uio_resid
Definition: vsnprintf.c:233
volatile VALUE value
Definition: sprintf.c:1047
rb_printf_buffer base
Definition: sprintf.c:1046
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1024