Ruby  2.5.0dev(2017-10-22revision60238)
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 "internal.h"
15 #include "ruby/re.h"
16 #include "id.h"
17 #include <math.h>
18 #include <stdarg.h>
19 
20 #ifdef HAVE_IEEEFP_H
21 #include <ieeefp.h>
22 #endif
23 
24 #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
25 
26 static char *fmt_setup(char*,size_t,int,int,int,int);
27 static char *ruby_ultoa(unsigned long val, char *endp, int base, int octzero);
28 
29 static char
30 sign_bits(int base, const char *p)
31 {
32  char c = '.';
33 
34  switch (base) {
35  case 16:
36  if (*p == 'X') c = 'F';
37  else c = 'f';
38  break;
39  case 8:
40  c = '7'; break;
41  case 2:
42  c = '1'; break;
43  }
44  return c;
45 }
46 
47 #define FNONE 0
48 #define FSHARP 1
49 #define FMINUS 2
50 #define FPLUS 4
51 #define FZERO 8
52 #define FSPACE 16
53 #define FWIDTH 32
54 #define FPREC 64
55 #define FPREC0 128
56 
57 #define CHECK(l) do {\
58  int cr = ENC_CODERANGE(result);\
59  while ((l) >= bsiz - blen) {\
60  bsiz*=2;\
61  if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
62  }\
63  rb_str_resize(result, bsiz);\
64  ENC_CODERANGE_SET(result, cr);\
65  buf = RSTRING_PTR(result);\
66 } while (0)
67 
68 #define PUSH(s, l) do { \
69  CHECK(l);\
70  PUSH_(s, l);\
71 } while (0)
72 
73 #define PUSH_(s, l) do { \
74  memcpy(&buf[blen], (s), (l));\
75  blen += (l);\
76 } while (0)
77 
78 #define FILL(c, l) do { \
79  if ((l) <= 0) break;\
80  CHECK(l);\
81  FILL_(c, l);\
82 } while (0)
83 
84 #define FILL_(c, l) do { \
85  memset(&buf[blen], (c), (l));\
86  blen += (l);\
87 } while (0)
88 
89 #define GETARG() (nextvalue != Qundef ? nextvalue : \
90  GETNEXTARG())
91 
92 #define GETNEXTARG() ( \
93  check_next_arg(posarg, nextarg), \
94  (posarg = nextarg++, GETNTHARG(posarg)))
95 
96 #define GETPOSARG(n) ( \
97  check_pos_arg(posarg, (n)), \
98  (posarg = -1, GETNTHARG(n)))
99 
100 #define GETNTHARG(nth) \
101  (((nth) >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[(nth)])
102 
103 #define CHECKNAMEARG(name, len, enc) ( \
104  check_name_arg(posarg, name, len, enc), \
105  posarg = -2)
106 
107 #define GETNUM(n, val) \
108  (!(p = get_num(p, end, enc, &(n))) ? \
109  rb_raise(rb_eArgError, #val " too big") : (void)0)
110 
111 #define GETASTER(val) do { \
112  t = p++; \
113  n = 0; \
114  GETNUM(n, val); \
115  if (*p == '$') { \
116  tmp = GETPOSARG(n); \
117  } \
118  else { \
119  tmp = GETNEXTARG(); \
120  p = t; \
121  } \
122  (val) = NUM2INT(tmp); \
123 } while (0)
124 
125 static const char *
126 get_num(const char *p, const char *end, rb_encoding *enc, int *valp)
127 {
128  int next_n = *valp;
129  for (; p < end && rb_enc_isdigit(*p, enc); p++) {
130  if (MUL_OVERFLOW_INT_P(10, next_n))
131  return NULL;
132  next_n *= 10;
133  if (INT_MAX - (*p - '0') < next_n)
134  return NULL;
135  next_n += *p - '0';
136  }
137  if (p >= end) {
138  rb_raise(rb_eArgError, "malformed format string - %%*[0-9]");
139  }
140  *valp = next_n;
141  return p;
142 }
143 
144 static void
145 check_next_arg(int posarg, int nextarg)
146 {
147  switch (posarg) {
148  case -1:
149  rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg);
150  case -2:
151  rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg);
152  }
153 }
154 
155 static void
156 check_pos_arg(int posarg, int n)
157 {
158  if (posarg > 0) {
159  rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg);
160  }
161  if (posarg == -2) {
162  rb_raise(rb_eArgError, "numbered(%d) after named", n);
163  }
164  if (n < 1) {
165  rb_raise(rb_eArgError, "invalid index - %d$", n);
166  }
167 }
168 
169 static void
170 check_name_arg(int posarg, const char *name, int len, rb_encoding *enc)
171 {
172  if (posarg > 0) {
173  rb_enc_raise(enc, rb_eArgError, "named%.*s after unnumbered(%d)", len, name, posarg);
174  }
175  if (posarg == -1) {
176  rb_enc_raise(enc, rb_eArgError, "named%.*s after numbered", len, name);
177  }
178 }
179 
180 static VALUE
181 get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
182 {
183  VALUE tmp;
184 
185  if (*hash != Qundef) return *hash;
186  if (argc != 2) {
187  rb_raise(rb_eArgError, "one hash required");
188  }
189  tmp = rb_check_hash_type(argv[1]);
190  if (NIL_P(tmp)) {
191  rb_raise(rb_eArgError, "one hash required");
192  }
193  return (*hash = tmp);
194 }
195 
196 /*
197  * call-seq:
198  * format(format_string [, arguments...] ) -> string
199  * sprintf(format_string [, arguments...] ) -> string
200  *
201  * Returns the string resulting from applying <i>format_string</i> to
202  * any additional arguments. Within the format string, any characters
203  * other than format sequences are copied to the result.
204  *
205  * The syntax of a format sequence is follows.
206  *
207  * %[flags][width][.precision]type
208  *
209  * A format
210  * sequence consists of a percent sign, followed by optional flags,
211  * width, and precision indicators, then terminated with a field type
212  * character. The field type controls how the corresponding
213  * <code>sprintf</code> argument is to be interpreted, while the flags
214  * modify that interpretation.
215  *
216  * The field type characters are:
217  *
218  * Field | Integer Format
219  * ------+--------------------------------------------------------------
220  * b | Convert argument as a binary number.
221  * | Negative numbers will be displayed as a two's complement
222  * | prefixed with `..1'.
223  * B | Equivalent to `b', but uses an uppercase 0B for prefix
224  * | in the alternative format by #.
225  * d | Convert argument as a decimal number.
226  * i | Identical to `d'.
227  * o | Convert argument as an octal number.
228  * | Negative numbers will be displayed as a two's complement
229  * | prefixed with `..7'.
230  * u | Identical to `d'.
231  * x | Convert argument as a hexadecimal number.
232  * | Negative numbers will be displayed as a two's complement
233  * | prefixed with `..f' (representing an infinite string of
234  * | leading 'ff's).
235  * X | Equivalent to `x', but uses uppercase letters.
236  *
237  * Field | Float Format
238  * ------+--------------------------------------------------------------
239  * e | Convert floating point argument into exponential notation
240  * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
241  * | The precision specifies the number of digits after the decimal
242  * | point (defaulting to six).
243  * E | Equivalent to `e', but uses an uppercase E to indicate
244  * | the exponent.
245  * f | Convert floating point argument as [-]ddd.dddddd,
246  * | where the precision specifies the number of digits after
247  * | the decimal point.
248  * g | Convert a floating point number using exponential form
249  * | if the exponent is less than -4 or greater than or
250  * | equal to the precision, or in dd.dddd form otherwise.
251  * | The precision specifies the number of significant digits.
252  * G | Equivalent to `g', but use an uppercase `E' in exponent form.
253  * a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
254  * | which is consisted from optional sign, "0x", fraction part
255  * | as hexadecimal, "p", and exponential part as decimal.
256  * A | Equivalent to `a', but use uppercase `X' and `P'.
257  *
258  * Field | Other Format
259  * ------+--------------------------------------------------------------
260  * c | Argument is the numeric code for a single character or
261  * | a single character string itself.
262  * p | The valuing of argument.inspect.
263  * s | Argument is a string to be substituted. If the format
264  * | sequence contains a precision, at most that many characters
265  * | will be copied.
266  * % | A percent sign itself will be displayed. No argument taken.
267  *
268  * The flags modifies the behavior of the formats.
269  * The flag characters are:
270  *
271  * Flag | Applies to | Meaning
272  * ---------+---------------+-----------------------------------------
273  * space | bBdiouxX | Leave a space at the start of
274  * | aAeEfgG | non-negative numbers.
275  * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
276  * | | a minus sign with absolute value for
277  * | | negative values.
278  * ---------+---------------+-----------------------------------------
279  * (digit)$ | all | Specifies the absolute argument number
280  * | | for this field. Absolute and relative
281  * | | argument numbers cannot be mixed in a
282  * | | sprintf string.
283  * ---------+---------------+-----------------------------------------
284  * # | bBoxX | Use an alternative format.
285  * | aAeEfgG | For the conversions `o', increase the precision
286  * | | until the first digit will be `0' if
287  * | | it is not formatted as complements.
288  * | | For the conversions `x', `X', `b' and `B'
289  * | | on non-zero, prefix the result with ``0x'',
290  * | | ``0X'', ``0b'' and ``0B'', respectively.
291  * | | For `a', `A', `e', `E', `f', `g', and 'G',
292  * | | force a decimal point to be added,
293  * | | even if no digits follow.
294  * | | For `g' and 'G', do not remove trailing zeros.
295  * ---------+---------------+-----------------------------------------
296  * + | bBdiouxX | Add a leading plus sign to non-negative
297  * | aAeEfgG | numbers.
298  * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
299  * | | a minus sign with absolute value for
300  * | | negative values.
301  * ---------+---------------+-----------------------------------------
302  * - | all | Left-justify the result of this conversion.
303  * ---------+---------------+-----------------------------------------
304  * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
305  * | aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
306  * | (numeric fmt) | is used for negative numbers formatted as
307  * | | complements.
308  * ---------+---------------+-----------------------------------------
309  * * | all | Use the next argument as the field width.
310  * | | If negative, left-justify the result. If the
311  * | | asterisk is followed by a number and a dollar
312  * | | sign, use the indicated argument as the width.
313  *
314  * Examples of flags:
315  *
316  * # `+' and space flag specifies the sign of non-negative numbers.
317  * sprintf("%d", 123) #=> "123"
318  * sprintf("%+d", 123) #=> "+123"
319  * sprintf("% d", 123) #=> " 123"
320  *
321  * # `#' flag for `o' increases number of digits to show `0'.
322  * # `+' and space flag changes format of negative numbers.
323  * sprintf("%o", 123) #=> "173"
324  * sprintf("%#o", 123) #=> "0173"
325  * sprintf("%+o", -123) #=> "-173"
326  * sprintf("%o", -123) #=> "..7605"
327  * sprintf("%#o", -123) #=> "..7605"
328  *
329  * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
330  * # `+' and space flag disables complements for negative numbers.
331  * sprintf("%x", 123) #=> "7b"
332  * sprintf("%#x", 123) #=> "0x7b"
333  * sprintf("%+x", -123) #=> "-7b"
334  * sprintf("%x", -123) #=> "..f85"
335  * sprintf("%#x", -123) #=> "0x..f85"
336  * sprintf("%#x", 0) #=> "0"
337  *
338  * # `#' for `X' uses the prefix `0X'.
339  * sprintf("%X", 123) #=> "7B"
340  * sprintf("%#X", 123) #=> "0X7B"
341  *
342  * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
343  * # `+' and space flag disables complements for negative numbers.
344  * sprintf("%b", 123) #=> "1111011"
345  * sprintf("%#b", 123) #=> "0b1111011"
346  * sprintf("%+b", -123) #=> "-1111011"
347  * sprintf("%b", -123) #=> "..10000101"
348  * sprintf("%#b", -123) #=> "0b..10000101"
349  * sprintf("%#b", 0) #=> "0"
350  *
351  * # `#' for `B' uses the prefix `0B'.
352  * sprintf("%B", 123) #=> "1111011"
353  * sprintf("%#B", 123) #=> "0B1111011"
354  *
355  * # `#' for `e' forces to show the decimal point.
356  * sprintf("%.0e", 1) #=> "1e+00"
357  * sprintf("%#.0e", 1) #=> "1.e+00"
358  *
359  * # `#' for `f' forces to show the decimal point.
360  * sprintf("%.0f", 1234) #=> "1234"
361  * sprintf("%#.0f", 1234) #=> "1234."
362  *
363  * # `#' for `g' forces to show the decimal point.
364  * # It also disables stripping lowest zeros.
365  * sprintf("%g", 123.4) #=> "123.4"
366  * sprintf("%#g", 123.4) #=> "123.400"
367  * sprintf("%g", 123456) #=> "123456"
368  * sprintf("%#g", 123456) #=> "123456."
369  *
370  * The field width is an optional integer, followed optionally by a
371  * period and a precision. The width specifies the minimum number of
372  * characters that will be written to the result for this field.
373  *
374  * Examples of width:
375  *
376  * # padding is done by spaces, width=20
377  * # 0 or radix-1. <------------------>
378  * sprintf("%20d", 123) #=> " 123"
379  * sprintf("%+20d", 123) #=> " +123"
380  * sprintf("%020d", 123) #=> "00000000000000000123"
381  * sprintf("%+020d", 123) #=> "+0000000000000000123"
382  * sprintf("% 020d", 123) #=> " 0000000000000000123"
383  * sprintf("%-20d", 123) #=> "123 "
384  * sprintf("%-+20d", 123) #=> "+123 "
385  * sprintf("%- 20d", 123) #=> " 123 "
386  * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
387  *
388  * For
389  * numeric fields, the precision controls the number of decimal places
390  * displayed. For string fields, the precision determines the maximum
391  * number of characters to be copied from the string. (Thus, the format
392  * sequence <code>%10.10s</code> will always contribute exactly ten
393  * characters to the result.)
394  *
395  * Examples of precisions:
396  *
397  * # precision for `d', 'o', 'x' and 'b' is
398  * # minimum number of digits <------>
399  * sprintf("%20.8d", 123) #=> " 00000123"
400  * sprintf("%20.8o", 123) #=> " 00000173"
401  * sprintf("%20.8x", 123) #=> " 0000007b"
402  * sprintf("%20.8b", 123) #=> " 01111011"
403  * sprintf("%20.8d", -123) #=> " -00000123"
404  * sprintf("%20.8o", -123) #=> " ..777605"
405  * sprintf("%20.8x", -123) #=> " ..ffff85"
406  * sprintf("%20.8b", -11) #=> " ..110101"
407  *
408  * # "0x" and "0b" for `#x' and `#b' is not counted for
409  * # precision but "0" for `#o' is counted. <------>
410  * sprintf("%#20.8d", 123) #=> " 00000123"
411  * sprintf("%#20.8o", 123) #=> " 00000173"
412  * sprintf("%#20.8x", 123) #=> " 0x0000007b"
413  * sprintf("%#20.8b", 123) #=> " 0b01111011"
414  * sprintf("%#20.8d", -123) #=> " -00000123"
415  * sprintf("%#20.8o", -123) #=> " ..777605"
416  * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
417  * sprintf("%#20.8b", -11) #=> " 0b..110101"
418  *
419  * # precision for `e' is number of
420  * # digits after the decimal point <------>
421  * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
422  *
423  * # precision for `f' is number of
424  * # digits after the decimal point <------>
425  * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
426  *
427  * # precision for `g' is number of
428  * # significant digits <------->
429  * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
430  *
431  * # <------->
432  * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
433  *
434  * # precision for `s' is
435  * # maximum number of characters <------>
436  * sprintf("%20.8s", "string test") #=> " string t"
437  *
438  * Examples:
439  *
440  * sprintf("%d %04x", 123, 123) #=> "123 007b"
441  * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
442  * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
443  * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
444  * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
445  * sprintf("%u", -123) #=> "-123"
446  *
447  * For more complex formatting, Ruby supports a reference by name.
448  * %<name>s style uses format style, but %{name} style doesn't.
449  *
450  * Examples:
451  * sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 })
452  * #=> 1 : 2.000000
453  * sprintf("%{foo}f", { :foo => 1 })
454  * # => "1f"
455  */
456 
457 VALUE
458 rb_f_sprintf(int argc, const VALUE *argv)
459 {
460  return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
461 }
462 
463 VALUE
464 rb_str_format(int argc, const VALUE *argv, VALUE fmt)
465 {
466  enum {default_float_precision = 6};
467  rb_encoding *enc;
468  const char *p, *end;
469  char *buf;
470  long blen, bsiz;
471  VALUE result;
472 
473  long scanned = 0;
474  int coderange = ENC_CODERANGE_7BIT;
475  int width, prec, flags = FNONE;
476  int nextarg = 1;
477  int posarg = 0;
478  int tainted = 0;
479  VALUE nextvalue;
480  VALUE tmp;
481  VALUE orig;
482  VALUE str;
483  volatile VALUE hash = Qundef;
484 
485 #define CHECK_FOR_WIDTH(f) \
486  if ((f) & FWIDTH) { \
487  rb_raise(rb_eArgError, "width given twice"); \
488  } \
489  if ((f) & FPREC0) { \
490  rb_raise(rb_eArgError, "width after precision"); \
491  }
492 #define CHECK_FOR_FLAGS(f) \
493  if ((f) & FWIDTH) { \
494  rb_raise(rb_eArgError, "flag after width"); \
495  } \
496  if ((f) & FPREC0) { \
497  rb_raise(rb_eArgError, "flag after precision"); \
498  }
499 
500  ++argc;
501  --argv;
502  if (OBJ_TAINTED(fmt)) tainted = 1;
503  StringValue(fmt);
504  enc = rb_enc_get(fmt);
505  orig = fmt;
506  fmt = rb_str_tmp_frozen_acquire(fmt);
507  p = RSTRING_PTR(fmt);
508  end = p + RSTRING_LEN(fmt);
509  blen = 0;
510  bsiz = 120;
511  result = rb_str_buf_new(bsiz);
512  rb_enc_copy(result, fmt);
513  buf = RSTRING_PTR(result);
514  memset(buf, 0, bsiz);
515  ENC_CODERANGE_SET(result, coderange);
516 
517  for (; p < end; p++) {
518  const char *t;
519  int n;
520  VALUE sym = Qnil;
521 
522  for (t = p; t < end && *t != '%'; t++) ;
523  if (t + 1 == end) {
524  rb_raise(rb_eArgError, "incomplete format specifier; use %%%% (double %%) instead");
525  }
526  PUSH(p, t - p);
527  if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
528  scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &coderange);
529  ENC_CODERANGE_SET(result, coderange);
530  }
531  if (t >= end) {
532  /* end of fmt string */
533  goto sprint_exit;
534  }
535  p = t + 1; /* skip `%' */
536 
537  width = prec = -1;
538  nextvalue = Qundef;
539  retry:
540  switch (*p) {
541  default:
542  if (rb_enc_isprint(*p, enc))
543  rb_raise(rb_eArgError, "malformed format string - %%%c", *p);
544  else
545  rb_raise(rb_eArgError, "malformed format string");
546  break;
547 
548  case ' ':
549  CHECK_FOR_FLAGS(flags);
550  flags |= FSPACE;
551  p++;
552  goto retry;
553 
554  case '#':
555  CHECK_FOR_FLAGS(flags);
556  flags |= FSHARP;
557  p++;
558  goto retry;
559 
560  case '+':
561  CHECK_FOR_FLAGS(flags);
562  flags |= FPLUS;
563  p++;
564  goto retry;
565 
566  case '-':
567  CHECK_FOR_FLAGS(flags);
568  flags |= FMINUS;
569  p++;
570  goto retry;
571 
572  case '0':
573  CHECK_FOR_FLAGS(flags);
574  flags |= FZERO;
575  p++;
576  goto retry;
577 
578  case '1': case '2': case '3': case '4':
579  case '5': case '6': case '7': case '8': case '9':
580  n = 0;
581  GETNUM(n, width);
582  if (*p == '$') {
583  if (nextvalue != Qundef) {
584  rb_raise(rb_eArgError, "value given twice - %d$", n);
585  }
586  nextvalue = GETPOSARG(n);
587  p++;
588  goto retry;
589  }
590  CHECK_FOR_WIDTH(flags);
591  width = n;
592  flags |= FWIDTH;
593  goto retry;
594 
595  case '<':
596  case '{':
597  {
598  const char *start = p;
599  char term = (*p == '<') ? '>' : '}';
600  int len;
601 
602  for (; p < end && *p != term; ) {
603  p += rb_enc_mbclen(p, end, enc);
604  }
605  if (p >= end) {
606  rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
607  }
608 #if SIZEOF_INT < SIZEOF_SIZE_T
609  if ((size_t)(p - start) >= INT_MAX) {
610  const int message_limit = 20;
611  len = (int)(rb_enc_right_char_head(start, start + message_limit, p, enc) - start);
613  "too long name (%"PRIuSIZE" bytes) - %.*s...%c",
614  (size_t)(p - start - 2), len, start, term);
615  }
616 #endif
617  len = (int)(p - start + 1); /* including parenthesis */
618  if (sym != Qnil) {
619  rb_enc_raise(enc, rb_eArgError, "named%.*s after <%"PRIsVALUE">",
620  len, start, rb_sym2str(sym));
621  }
622  CHECKNAMEARG(start, len, enc);
623  get_hash(&hash, argc, argv);
624  sym = rb_check_symbol_cstr(start + 1,
625  len - 2 /* without parenthesis */,
626  enc);
627  if (!NIL_P(sym)) nextvalue = rb_hash_lookup2(hash, sym, Qundef);
628  if (nextvalue == Qundef) {
629  if (NIL_P(sym)) {
630  sym = rb_sym_intern(start + 1,
631  len - 2 /* without parenthesis */,
632  enc);
633  }
634  nextvalue = rb_hash_default_value(hash, sym);
635  if (NIL_P(nextvalue)) {
636  rb_key_err_raise(rb_enc_sprintf(enc, "key%.*s not found", len, start), hash, sym);
637  }
638  }
639  if (term == '}') goto format_s;
640  p++;
641  goto retry;
642  }
643 
644  case '*':
645  CHECK_FOR_WIDTH(flags);
646  flags |= FWIDTH;
647  GETASTER(width);
648  if (width < 0) {
649  flags |= FMINUS;
650  width = -width;
651  if (width < 0) rb_raise(rb_eArgError, "width too big");
652  }
653  p++;
654  goto retry;
655 
656  case '.':
657  if (flags & FPREC0) {
658  rb_raise(rb_eArgError, "precision given twice");
659  }
660  flags |= FPREC|FPREC0;
661 
662  prec = 0;
663  p++;
664  if (*p == '*') {
665  GETASTER(prec);
666  if (prec < 0) { /* ignore negative precision */
667  flags &= ~FPREC;
668  }
669  p++;
670  goto retry;
671  }
672 
673  GETNUM(prec, precision);
674  goto retry;
675 
676  case '\n':
677  case '\0':
678  p--;
679  case '%':
680  if (flags != FNONE) {
681  rb_raise(rb_eArgError, "invalid format character - %%");
682  }
683  PUSH("%", 1);
684  break;
685 
686  case 'c':
687  {
688  VALUE val = GETARG();
689  VALUE tmp;
690  unsigned int c;
691  int n;
692 
693  tmp = rb_check_string_type(val);
694  if (!NIL_P(tmp)) {
695  if (rb_enc_strlen(RSTRING_PTR(tmp),RSTRING_END(tmp),enc) != 1) {
696  rb_raise(rb_eArgError, "%%c requires a character");
697  }
698  c = rb_enc_codepoint_len(RSTRING_PTR(tmp), RSTRING_END(tmp), &n, enc);
699  RB_GC_GUARD(tmp);
700  }
701  else {
702  c = NUM2INT(val);
703  n = rb_enc_codelen(c, enc);
704  }
705  if (n <= 0) {
706  rb_raise(rb_eArgError, "invalid character");
707  }
708  if (!(flags & FWIDTH)) {
709  CHECK(n);
710  rb_enc_mbcput(c, &buf[blen], enc);
711  blen += n;
712  }
713  else if ((flags & FMINUS)) {
714  CHECK(n);
715  rb_enc_mbcput(c, &buf[blen], enc);
716  blen += n;
717  if (width > 1) FILL(' ', width-1);
718  }
719  else {
720  if (width > 1) FILL(' ', width-1);
721  CHECK(n);
722  rb_enc_mbcput(c, &buf[blen], enc);
723  blen += n;
724  }
725  }
726  break;
727 
728  case 's':
729  case 'p':
730  format_s:
731  {
732  VALUE arg = GETARG();
733  long len, slen;
734 
735  if (*p == 'p') {
736  str = rb_inspect(arg);
737  }
738  else {
739  str = rb_obj_as_string(arg);
740  }
741  if (OBJ_TAINTED(str)) tainted = 1;
742  len = RSTRING_LEN(str);
743  rb_str_set_len(result, blen);
744  if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) {
745  int cr = coderange;
746  scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr);
747  ENC_CODERANGE_SET(result,
748  (cr == ENC_CODERANGE_UNKNOWN ?
749  ENC_CODERANGE_BROKEN : (coderange = cr)));
750  }
751  enc = rb_enc_check(result, str);
752  if (flags&(FPREC|FWIDTH)) {
753  slen = rb_enc_strlen(RSTRING_PTR(str),RSTRING_END(str),enc);
754  if (slen < 0) {
755  rb_raise(rb_eArgError, "invalid mbstring sequence");
756  }
757  if ((flags&FPREC) && (prec < slen)) {
758  char *p = rb_enc_nth(RSTRING_PTR(str), RSTRING_END(str),
759  prec, enc);
760  slen = prec;
761  len = p - RSTRING_PTR(str);
762  }
763  /* need to adjust multi-byte string pos */
764  if ((flags&FWIDTH) && (width > slen)) {
765  width -= (int)slen;
766  if (!(flags&FMINUS)) {
767  FILL(' ', width);
768  width = 0;
769  }
770  CHECK(len);
771  memcpy(&buf[blen], RSTRING_PTR(str), len);
772  RB_GC_GUARD(str);
773  blen += len;
774  if (flags&FMINUS) {
775  FILL(' ', width);
776  }
777  rb_enc_associate(result, enc);
778  break;
779  }
780  }
781  PUSH(RSTRING_PTR(str), len);
782  RB_GC_GUARD(str);
783  rb_enc_associate(result, enc);
784  }
785  break;
786 
787  case 'd':
788  case 'i':
789  case 'o':
790  case 'x':
791  case 'X':
792  case 'b':
793  case 'B':
794  case 'u':
795  {
796  volatile VALUE val = GETARG();
797  int valsign;
798  char nbuf[BIT_DIGITS(SIZEOF_LONG*CHAR_BIT)+2], *s;
799  const char *prefix = 0;
800  int sign = 0, dots = 0;
801  char sc = 0;
802  long v = 0;
803  int base, bignum = 0;
804  int len;
805 
806  switch (*p) {
807  case 'd':
808  case 'i':
809  case 'u':
810  sign = 1; break;
811  case 'o':
812  case 'x':
813  case 'X':
814  case 'b':
815  case 'B':
816  if (flags&(FPLUS|FSPACE)) sign = 1;
817  break;
818  }
819  if (flags & FSHARP) {
820  switch (*p) {
821  case 'o':
822  prefix = "0"; break;
823  case 'x':
824  prefix = "0x"; break;
825  case 'X':
826  prefix = "0X"; break;
827  case 'b':
828  prefix = "0b"; break;
829  case 'B':
830  prefix = "0B"; break;
831  }
832  }
833 
834  bin_retry:
835  switch (TYPE(val)) {
836  case T_FLOAT:
837  if (FIXABLE(RFLOAT_VALUE(val))) {
838  val = LONG2FIX((long)RFLOAT_VALUE(val));
839  goto bin_retry;
840  }
841  val = rb_dbl2big(RFLOAT_VALUE(val));
842  if (FIXNUM_P(val)) goto bin_retry;
843  bignum = 1;
844  break;
845  case T_STRING:
846  val = rb_str_to_inum(val, 0, TRUE);
847  goto bin_retry;
848  case T_BIGNUM:
849  bignum = 1;
850  break;
851  case T_FIXNUM:
852  v = FIX2LONG(val);
853  break;
854  default:
855  val = rb_Integer(val);
856  goto bin_retry;
857  }
858 
859  switch (*p) {
860  case 'o':
861  base = 8; break;
862  case 'x':
863  case 'X':
864  base = 16; break;
865  case 'b':
866  case 'B':
867  base = 2; break;
868  case 'u':
869  case 'd':
870  case 'i':
871  default:
872  base = 10; break;
873  }
874 
875  if (base != 10) {
876  int numbits = ffs(base)-1;
877  size_t abs_nlz_bits;
878  size_t numdigits = rb_absint_numwords(val, numbits, &abs_nlz_bits);
879  long i;
880  if (INT_MAX-1 < numdigits) /* INT_MAX is used because rb_long2int is used later. */
881  rb_raise(rb_eArgError, "size too big");
882  if (sign) {
883  if (numdigits == 0)
884  numdigits = 1;
885  tmp = rb_str_new(NULL, numdigits);
886  valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
887  1, CHAR_BIT-numbits, INTEGER_PACK_BIG_ENDIAN);
888  for (i = 0; i < RSTRING_LEN(tmp); i++)
889  RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
890  s = RSTRING_PTR(tmp);
891  if (valsign < 0) {
892  sc = '-';
893  width--;
894  }
895  else if (flags & FPLUS) {
896  sc = '+';
897  width--;
898  }
899  else if (flags & FSPACE) {
900  sc = ' ';
901  width--;
902  }
903  }
904  else {
905  /* Following conditional "numdigits++" guarantees the
906  * most significant digit as
907  * - '1'(bin), '7'(oct) or 'f'(hex) for negative numbers
908  * - '0' for zero
909  * - not '0' for positive numbers.
910  *
911  * It also guarantees the most significant two
912  * digits will not be '11'(bin), '77'(oct), 'ff'(hex)
913  * or '00'. */
914  if (numdigits == 0 ||
915  ((abs_nlz_bits != (size_t)(numbits-1) ||
916  !rb_absint_singlebit_p(val)) &&
917  (!bignum ? v < 0 : BIGNUM_NEGATIVE_P(val))))
918  numdigits++;
919  tmp = rb_str_new(NULL, numdigits);
920  valsign = rb_integer_pack(val, RSTRING_PTR(tmp), RSTRING_LEN(tmp),
921  1, CHAR_BIT-numbits, INTEGER_PACK_2COMP | INTEGER_PACK_BIG_ENDIAN);
922  for (i = 0; i < RSTRING_LEN(tmp); i++)
923  RSTRING_PTR(tmp)[i] = ruby_digitmap[((unsigned char *)RSTRING_PTR(tmp))[i]];
924  s = RSTRING_PTR(tmp);
925  dots = valsign < 0;
926  }
927  len = rb_long2int(RSTRING_END(tmp) - s);
928  }
929  else if (!bignum) {
930  valsign = 1;
931  if (v < 0) {
932  v = -v;
933  sc = '-';
934  width--;
935  valsign = -1;
936  }
937  else if (flags & FPLUS) {
938  sc = '+';
939  width--;
940  }
941  else if (flags & FSPACE) {
942  sc = ' ';
943  width--;
944  }
945  s = ruby_ultoa((unsigned long)v, nbuf + sizeof(nbuf), 10, 0);
946  len = (int)(nbuf + sizeof(nbuf) - s);
947  }
948  else {
949  tmp = rb_big2str(val, 10);
950  s = RSTRING_PTR(tmp);
951  valsign = 1;
952  if (s[0] == '-') {
953  s++;
954  sc = '-';
955  width--;
956  valsign = -1;
957  }
958  else if (flags & FPLUS) {
959  sc = '+';
960  width--;
961  }
962  else if (flags & FSPACE) {
963  sc = ' ';
964  width--;
965  }
966  len = rb_long2int(RSTRING_END(tmp) - s);
967  }
968 
969  if (dots) {
970  prec -= 2;
971  width -= 2;
972  }
973 
974  if (*p == 'X') {
975  char *pp = s;
976  int c;
977  while ((c = (int)(unsigned char)*pp) != 0) {
978  *pp = rb_enc_toupper(c, enc);
979  pp++;
980  }
981  }
982  if (prefix && !prefix[1]) { /* octal */
983  if (dots) {
984  prefix = 0;
985  }
986  else if (len == 1 && *s == '0') {
987  len = 0;
988  if (flags & FPREC) prec--;
989  }
990  else if ((flags & FPREC) && (prec > len)) {
991  prefix = 0;
992  }
993  }
994  else if (len == 1 && *s == '0') {
995  prefix = 0;
996  }
997  if (prefix) {
998  width -= (int)strlen(prefix);
999  }
1000  if ((flags & (FZERO|FMINUS|FPREC)) == FZERO) {
1001  prec = width;
1002  width = 0;
1003  }
1004  else {
1005  if (prec < len) {
1006  if (!prefix && prec == 0 && len == 1 && *s == '0') len = 0;
1007  prec = len;
1008  }
1009  width -= prec;
1010  }
1011  if (!(flags&FMINUS)) {
1012  FILL(' ', width);
1013  width = 0;
1014  }
1015  if (sc) PUSH(&sc, 1);
1016  if (prefix) {
1017  int plen = (int)strlen(prefix);
1018  PUSH(prefix, plen);
1019  }
1020  if (dots) PUSH("..", 2);
1021  if (prec > len) {
1022  CHECK(prec - len);
1023  if (!sign && valsign < 0) {
1024  char c = sign_bits(base, p);
1025  FILL_(c, prec - len);
1026  }
1027  else if ((flags & (FMINUS|FPREC)) != FMINUS) {
1028  FILL_('0', prec - len);
1029  }
1030  }
1031  PUSH(s, len);
1032  RB_GC_GUARD(tmp);
1033  FILL(' ', width);
1034  }
1035  break;
1036 
1037  case 'f':
1038  {
1039  VALUE val = GETARG(), num, den;
1040  int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
1041  long len, fill;
1042  if (RB_INTEGER_TYPE_P(val)) {
1043  den = INT2FIX(1);
1044  num = val;
1045  }
1046  else if (RB_TYPE_P(val, T_RATIONAL)) {
1047  den = rb_rational_den(val);
1048  num = rb_rational_num(val);
1049  }
1050  else {
1051  nextvalue = val;
1052  goto float_value;
1053  }
1054  if (!(flags&FPREC)) prec = default_float_precision;
1055  if (FIXNUM_P(num)) {
1056  if ((SIGNED_VALUE)num < 0) {
1057  long n = -FIX2LONG(num);
1058  num = LONG2FIX(n);
1059  sign = -1;
1060  }
1061  }
1062  else if (BIGNUM_NEGATIVE_P(num)) {
1063  sign = -1;
1064  num = rb_big_uminus(num);
1065  }
1066  if (den != INT2FIX(1)) {
1067  num = rb_int_mul(num, rb_int_positive_pow(10, prec));
1068  num = rb_int_plus(num, rb_int_idiv(den, INT2FIX(2)));
1069  num = rb_int_idiv(num, den);
1070  }
1071  else if (prec >= 0) {
1072  zero = prec;
1073  }
1074  val = rb_int2str(num, 10);
1075  len = RSTRING_LEN(val) + zero;
1076  if (prec >= len) len = prec + 1; /* integer part 0 */
1077  if (sign || (flags&FSPACE)) ++len;
1078  if (prec > 0) ++len; /* period */
1079  fill = width > len ? width - len : 0;
1080  CHECK(fill + len);
1081  if (fill && !(flags&(FMINUS|FZERO))) {
1082  FILL_(' ', fill);
1083  }
1084  if (sign || (flags&FSPACE)) {
1085  buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
1086  }
1087  if (fill && (flags&(FMINUS|FZERO)) == FZERO) {
1088  FILL_('0', fill);
1089  }
1090  len = RSTRING_LEN(val) + zero;
1091  t = RSTRING_PTR(val);
1092  if (len > prec) {
1093  PUSH_(t, len - prec);
1094  }
1095  else {
1096  buf[blen++] = '0';
1097  }
1098  if (prec > 0) {
1099  buf[blen++] = '.';
1100  }
1101  if (zero) {
1102  FILL_('0', zero);
1103  }
1104  else if (prec > len) {
1105  FILL_('0', prec - len);
1106  PUSH_(t, len);
1107  }
1108  else if (prec > 0) {
1109  PUSH_(t + len - prec, prec);
1110  }
1111  if (fill && (flags&FMINUS)) {
1112  FILL_(' ', fill);
1113  }
1114  RB_GC_GUARD(val);
1115  break;
1116  }
1117  case 'g':
1118  case 'G':
1119  case 'e':
1120  case 'E':
1121  /* TODO: rational support */
1122  case 'a':
1123  case 'A':
1124  float_value:
1125  {
1126  VALUE val = GETARG();
1127  double fval;
1128 
1129  fval = RFLOAT_VALUE(rb_Float(val));
1130  if (isnan(fval) || isinf(fval)) {
1131  const char *expr;
1132  int need;
1133  int elen;
1134  char sign = '\0';
1135 
1136  if (isnan(fval)) {
1137  expr = "NaN";
1138  }
1139  else {
1140  expr = "Inf";
1141  }
1142  need = (int)strlen(expr);
1143  elen = need;
1144  if (!isnan(fval) && fval < 0.0)
1145  sign = '-';
1146  else if (flags & (FPLUS|FSPACE))
1147  sign = (flags & FPLUS) ? '+' : ' ';
1148  if (sign)
1149  ++need;
1150  if ((flags & FWIDTH) && need < width)
1151  need = width;
1152 
1153  FILL(' ', need);
1154  if (flags & FMINUS) {
1155  if (sign)
1156  buf[blen - need--] = sign;
1157  memcpy(&buf[blen - need], expr, elen);
1158  }
1159  else {
1160  if (sign)
1161  buf[blen - elen - 1] = sign;
1162  memcpy(&buf[blen - elen], expr, elen);
1163  }
1164  break;
1165  }
1166  else {
1167  int cr = ENC_CODERANGE(result);
1168  char fbuf[2*BIT_DIGITS(SIZEOF_INT*CHAR_BIT)+10];
1169  char *fmt = fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
1170  rb_str_set_len(result, blen);
1171  rb_str_catf(result, fmt, fval);
1172  ENC_CODERANGE_SET(result, cr);
1173  bsiz = rb_str_capacity(result);
1174  RSTRING_GETMEM(result, buf, blen);
1175  }
1176  }
1177  break;
1178  }
1179  flags = FNONE;
1180  }
1181 
1182  sprint_exit:
1183  rb_str_tmp_frozen_release(orig, fmt);
1184  /* XXX - We cannot validate the number of arguments if (digit)$ style used.
1185  */
1186  if (posarg >= 0 && nextarg < argc) {
1187  const char *mesg = "too many arguments for format string";
1188  if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
1189  if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
1190  }
1191  rb_str_resize(result, blen);
1192 
1193  if (tainted) OBJ_TAINT(result);
1194  return result;
1195 }
1196 
1197 static char *
1198 fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
1199 {
1200  buf += size;
1201  *--buf = '\0';
1202  *--buf = c;
1203 
1204  if (flags & FPREC) {
1205  buf = ruby_ultoa(prec, buf, 10, 0);
1206  *--buf = '.';
1207  }
1208 
1209  if (flags & FWIDTH) {
1210  buf = ruby_ultoa(width, buf, 10, 0);
1211  }
1212 
1213  if (flags & FSPACE) *--buf = ' ';
1214  if (flags & FZERO) *--buf = '0';
1215  if (flags & FMINUS) *--buf = '-';
1216  if (flags & FPLUS) *--buf = '+';
1217  if (flags & FSHARP) *--buf = '#';
1218  *--buf = '%';
1219  return buf;
1220 }
1221 
1222 #undef FILE
1223 #define FILE rb_printf_buffer
1224 #define __sbuf rb_printf_sbuf
1225 #define __sFILE rb_printf_sfile
1226 #undef feof
1227 #undef ferror
1228 #undef clearerr
1229 #undef fileno
1230 #if SIZEOF_LONG < SIZEOF_VOIDP
1231 # if SIZEOF_LONG_LONG == SIZEOF_VOIDP
1232 # define _HAVE_SANE_QUAD_
1233 # define _HAVE_LLP64_
1234 # define quad_t LONG_LONG
1235 # define u_quad_t unsigned LONG_LONG
1236 # endif
1237 #elif SIZEOF_LONG != SIZEOF_LONG_LONG && SIZEOF_LONG_LONG == 8
1238 # define _HAVE_SANE_QUAD_
1239 # define quad_t LONG_LONG
1240 # define u_quad_t unsigned LONG_LONG
1241 #endif
1242 #define FLOATING_POINT 1
1243 #define BSD__dtoa ruby_dtoa
1244 #define BSD__hdtoa ruby_hdtoa
1245 #ifdef RUBY_PRI_VALUE_MARK
1246 # define PRI_EXTRA_MARK RUBY_PRI_VALUE_MARK
1247 #endif
1248 #define lower_hexdigits (ruby_hexdigits+0)
1249 #define upper_hexdigits (ruby_hexdigits+16)
1250 #if defined RUBY_USE_SETJMPEX && RUBY_USE_SETJMPEX
1251 # undef MAYBE_UNUSED
1252 # define MAYBE_UNUSED(x) x = 0
1253 #endif
1254 #include "vsnprintf.c"
1255 
1256 static char *
1257 ruby_ultoa(unsigned long val, char *endp, int base, int flags)
1258 {
1259  const char *xdigs = lower_hexdigits;
1260  int octzero = flags & FSHARP;
1261  return BSD__ultoa(val, endp, base, octzero, xdigs);
1262 }
1263 
1264 static int ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
1265 
1266 int
1267 ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
1268 {
1269  if (str && (ssize_t)n < 1)
1270  return (EOF);
1271  return ruby_do_vsnprintf(str, n, fmt, ap);
1272 }
1273 
1274 static int
1275 ruby_do_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
1276 {
1277  int ret;
1278  rb_printf_buffer f;
1279 
1280  f._flags = __SWR | __SSTR;
1281  f._bf._base = f._p = (unsigned char *)str;
1282  f._bf._size = f._w = str ? (n - 1) : 0;
1283  f.vwrite = BSD__sfvwrite;
1284  f.vextra = 0;
1285  ret = (int)BSD_vfprintf(&f, fmt, ap);
1286  if (str) *f._p = 0;
1287  return ret;
1288 }
1289 
1290 int
1291 ruby_snprintf(char *str, size_t n, char const *fmt, ...)
1292 {
1293  int ret;
1294  va_list ap;
1295 
1296  if (str && (ssize_t)n < 1)
1297  return (EOF);
1298 
1299  va_start(ap, fmt);
1300  ret = ruby_do_vsnprintf(str, n, fmt, ap);
1301  va_end(ap);
1302  return ret;
1303 }
1304 
1305 typedef struct {
1306  rb_printf_buffer base;
1307  volatile VALUE value;
1309 
1310 static int
1311 ruby__sfvwrite(register rb_printf_buffer *fp, register struct __suio *uio)
1312 {
1313  struct __siov *iov;
1314  VALUE result = (VALUE)fp->_bf._base;
1315  char *buf = (char*)fp->_p;
1316  long len, n;
1317  long blen = buf - RSTRING_PTR(result), bsiz = fp->_w;
1318 
1319  if (RBASIC(result)->klass) {
1320  rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
1321  }
1322  if (uio->uio_resid == 0)
1323  return 0;
1324 #if SIZE_MAX > LONG_MAX
1325  if (uio->uio_resid >= LONG_MAX)
1326  rb_raise(rb_eRuntimeError, "too big string");
1327 #endif
1328  len = (long)uio->uio_resid;
1329  CHECK(len);
1330  buf += blen;
1331  fp->_w = bsiz;
1332  for (iov = uio->uio_iov; len > 0; ++iov) {
1333  MEMCPY(buf, iov->iov_base, char, n = iov->iov_len);
1334  buf += n;
1335  len -= n;
1336  }
1337  fp->_p = (unsigned char *)buf;
1338  rb_str_set_len(result, buf - RSTRING_PTR(result));
1339  return 0;
1340 }
1341 
1342 static const char *
1343 ruby__sfvextra(rb_printf_buffer *fp, size_t valsize, void *valp, long *sz, int sign)
1344 {
1345  VALUE value, result = (VALUE)fp->_bf._base;
1346  rb_encoding *enc;
1347  char *cp;
1348 
1349  if (valsize != sizeof(VALUE)) return 0;
1350  value = *(VALUE *)valp;
1351  if (RBASIC(result)->klass) {
1352  rb_raise(rb_eRuntimeError, "rb_vsprintf reentered");
1353  }
1354  if (sign == '+') {
1355  if (RB_TYPE_P(value, T_CLASS)) {
1356 # define LITERAL(str) (*sz = rb_strlen_lit(str), str)
1357 
1358  if (value == rb_cNilClass) {
1359  return LITERAL("nil");
1360  }
1361  else if (value == rb_cInteger) {
1362  return LITERAL("Integer");
1363  }
1364  else if (value == rb_cSymbol) {
1365  return LITERAL("Symbol");
1366  }
1367  else if (value == rb_cTrueClass) {
1368  return LITERAL("true");
1369  }
1370  else if (value == rb_cFalseClass) {
1371  return LITERAL("false");
1372  }
1373 # undef LITERAL
1374  }
1375  value = rb_inspect(value);
1376  }
1377  else {
1378  value = rb_obj_as_string(value);
1379  if (sign == ' ') value = QUOTE(value);
1380  }
1381  enc = rb_enc_compatible(result, value);
1382  if (enc) {
1383  rb_enc_associate(result, enc);
1384  }
1385  else {
1386  enc = rb_enc_get(result);
1387  value = rb_str_conv_enc_opts(value, rb_enc_get(value), enc,
1389  Qnil);
1390  *(volatile VALUE *)valp = value;
1391  }
1392  StringValueCStr(value);
1393  RSTRING_GETMEM(value, cp, *sz);
1394  ((rb_printf_buffer_extra *)fp)->value = value;
1395  OBJ_INFECT(result, value);
1396  return cp;
1397 }
1398 
1399 VALUE
1400 rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
1401 {
1402  rb_printf_buffer_extra buffer;
1403 #define f buffer.base
1404  VALUE result;
1405 
1406  f._flags = __SWR | __SSTR;
1407  f._bf._size = 0;
1408  f._w = 120;
1409  result = rb_str_buf_new(f._w);
1410  if (enc) {
1411  if (rb_enc_mbminlen(enc) > 1) {
1412  /* the implementation deeply depends on plain char */
1413  rb_raise(rb_eArgError, "cannot construct wchar_t based encoding string: %s",
1414  rb_enc_name(enc));
1415  }
1416  rb_enc_associate(result, enc);
1417  }
1418  f._bf._base = (unsigned char *)result;
1419  f._p = (unsigned char *)RSTRING_PTR(result);
1420  RBASIC_CLEAR_CLASS(result);
1421  f.vwrite = ruby__sfvwrite;
1422  f.vextra = ruby__sfvextra;
1423  buffer.value = 0;
1424  BSD_vfprintf(&f, fmt, ap);
1426  rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
1427 #undef f
1428 
1429  return result;
1430 }
1431 
1432 VALUE
1433 rb_enc_sprintf(rb_encoding *enc, const char *format, ...)
1434 {
1435  VALUE result;
1436  va_list ap;
1437 
1438  va_start(ap, format);
1439  result = rb_enc_vsprintf(enc, format, ap);
1440  va_end(ap);
1441 
1442  return result;
1443 }
1444 
1445 VALUE
1446 rb_vsprintf(const char *fmt, va_list ap)
1447 {
1448  return rb_enc_vsprintf(NULL, fmt, ap);
1449 }
1450 
1451 VALUE
1452 rb_sprintf(const char *format, ...)
1453 {
1454  VALUE result;
1455  va_list ap;
1456 
1457  va_start(ap, format);
1458  result = rb_vsprintf(format, ap);
1459  va_end(ap);
1460 
1461  return result;
1462 }
1463 
1464 VALUE
1465 rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
1466 {
1467  rb_printf_buffer_extra buffer;
1468 #define f buffer.base
1469  VALUE klass;
1470 
1471  StringValue(str);
1472  rb_str_modify(str);
1473  f._flags = __SWR | __SSTR;
1474  f._bf._size = 0;
1475  f._w = rb_str_capacity(str);
1476  f._bf._base = (unsigned char *)str;
1477  f._p = (unsigned char *)RSTRING_END(str);
1478  klass = RBASIC(str)->klass;
1479  RBASIC_CLEAR_CLASS(str);
1480  f.vwrite = ruby__sfvwrite;
1481  f.vextra = ruby__sfvextra;
1482  buffer.value = 0;
1483  BSD_vfprintf(&f, fmt, ap);
1484  RBASIC_SET_CLASS_RAW(str, klass);
1485  rb_str_resize(str, (char *)f._p - RSTRING_PTR(str));
1486 #undef f
1487 
1488  return str;
1489 }
1490 
1491 VALUE
1492 rb_str_catf(VALUE str, const char *format, ...)
1493 {
1494  va_list ap;
1495 
1496  va_start(ap, format);
1497  str = rb_str_vcatf(str, format, ap);
1498  va_end(ap);
1499 
1500  return str;
1501 }
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1927
int ruby_snprintf(char *str, size_t n, char const *fmt,...)
Definition: sprintf.c:1291
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3519
#define BIT_DIGITS(N)
Definition: sprintf.c:24
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1469
int rb_enc_codelen(int c, rb_encoding *enc)
Definition: encoding.c:1077
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3529
void rb_warn(const char *fmt,...)
Definition: error.c:246
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
Definition: encoding.c:879
RUBY_EXTERN VALUE rb_cFalseClass
Definition: ruby.h:1903
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:978
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:531
size_t strlen(const char *)
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:1022
#define GETNUM(n, val)
Definition: sprintf.c:107
#define T_FIXNUM
Definition: ruby.h:503
#define NUM2INT(x)
Definition: ruby.h:684
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1183
#define __SSTR
Definition: vsnprintf.c:196
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define FPREC
Definition: sprintf.c:54
const char ruby_digitmap[]
Definition: bignum.c:38
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:106
#define T_RATIONAL
Definition: ruby.h:509
#define FILL(c, l)
Definition: sprintf.c:78
#define rb_long2int(n)
Definition: ruby.h:319
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
Definition: zonetab.h:883
rb_encoding * rb_enc_compatible(VALUE str1, VALUE str2)
Definition: encoding.c:962
void rb_str_set_len(VALUE, long)
Definition: string.c:2627
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3608
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
Definition: encoding.c:1056
const void * iov_base
Definition: vsnprintf.c:227
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:984
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:854
#define RB_GC_GUARD(v)
Definition: ruby.h:552
#define FNONE
Definition: sprintf.c:47
VALUE rb_Integer(VALUE)
Equivalent to Kernel#Integer in Ruby.
Definition: object.c:3148
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1008
VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
Definition: sprintf.c:1400
#define FIXNUM_P(f)
Definition: ruby.h:365
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
#define GETARG()
Definition: sprintf.c:89
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Definition: string.c:885
#define INTEGER_PACK_2COMP
Definition: intern.h:143
#define ENC_CODERANGE_7BIT
Definition: encoding.h:100
VALUE rb_enc_sprintf(rb_encoding *enc, const char *format,...)
Definition: sprintf.c:1433
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Definition: sprintf.c:464
#define FSPACE
Definition: sprintf.c:52
const char term
Definition: id.c:37
char * rb_enc_nth(const char *, const char *, long, rb_encoding *)
Definition: string.c:2320
int rb_enc_toupper(int c, rb_encoding *enc)
Definition: encoding.c:1094
VALUE rb_eArgError
Definition: error.c:802
#define sym(x)
Definition: date_core.c:3721
VALUE rb_hash_default_value(VALUE hash, VALUE key)
Definition: hash.c:803
int rb_absint_singlebit_p(VALUE val)
Definition: bignum.c:3428
#define RBASIC_SET_CLASS_RAW(obj, cls)
Definition: internal.h:1470
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE rb_int_idiv(VALUE x, VALUE y)
Definition: numeric.c:3753
#define FMINUS
Definition: sprintf.c:49
VALUE rb_dbl2big(double d)
Definition: bignum.c:5214
#define val
#define LITERAL(str)
#define FSHARP
Definition: sprintf.c:48
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Definition: bignum.c:4226
#define RSTRING_END(str)
Definition: ruby.h:979
#define ECONV_INVALID_REPLACE
Definition: encoding.h:388
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1410
#define rb_key_err_raise(mesg, recv, name)
Definition: internal.h:1171
#define NIL_P(v)
Definition: ruby.h:451
RUBY_EXTERN VALUE rb_cTrueClass
Definition: ruby.h:1932
VALUE rb_int2str(VALUE num, int base)
Definition: numeric.c:3471
#define CHECK(l)
Definition: sprintf.c:57
#define __SWR
Definition: vsnprintf.c:189
#define T_FLOAT
Definition: ruby.h:495
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
#define FZERO
Definition: sprintf.c:51
VALUE rb_vsprintf(const char *fmt, va_list ap)
Definition: sprintf.c:1446
#define BIGNUM_NEGATIVE_P(b)
Definition: internal.h:604
#define T_BIGNUM
Definition: ruby.h:501
#define ENC_CODERANGE_UNKNOWN
Definition: encoding.h:99
#define LONG_MAX
Definition: ruby.h:189
#define rb_enc_isprint(c, enc)
Definition: encoding.h:230
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1661
RUBY_EXTERN int isinf(double)
Definition: isinf.c:56
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:102
VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc)
Definition: symbol.c:995
#define rb_enc_mbminlen(enc)
Definition: encoding.h:174
#define CHECK_FOR_WIDTH(f)
VALUE rb_big2str(VALUE x, int base)
Definition: bignum.c:5062
#define GETASTER(val)
Definition: sprintf.c:111
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:3942
#define EOF
Definition: vsnprintf.c:203
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2644
#define RSTRING_LEN(str)
Definition: ruby.h:971
#define TRUE
Definition: nkf.h:175
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Definition: sprintf.c:458
volatile VALUE value
Definition: sprintf.c:1307
#define rb_enc_name(enc)
Definition: encoding.h:171
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:722
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
#define PRIsVALUE
Definition: ruby.h:135
size_t uio_resid
Definition: vsnprintf.c:233
#define rb_enc_isdigit(c, enc)
Definition: encoding.h:232
#define Qnil
Definition: ruby.h:438
#define PUSH(s, l)
Definition: sprintf.c:68
unsigned long VALUE
Definition: ruby.h:85
#define OBJ_TAINTED(x)
Definition: ruby.h:1296
#define RBASIC(obj)
Definition: ruby.h:1197
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1912
VALUE rb_rational_den(VALUE rat)
Definition: rational.c:1994
struct __siov * uio_iov
Definition: vsnprintf.c:231
#define isnan(x)
Definition: win32.h:346
#define FIXABLE(f)
Definition: ruby.h:368
#define FPREC0
Definition: sprintf.c:55
#define CHAR_BIT
Definition: ruby.h:196
#define FPLUS
Definition: sprintf.c:50
#define INTEGER_PACK_BIG_ENDIAN
Definition: intern.h:152
register unsigned int len
Definition: zonetab.h:51
#define StringValueCStr(v)
Definition: ruby.h:571
#define lower_hexdigits
Definition: sprintf.c:1248
#define RSTRING_PTR(str)
Definition: ruby.h:975
rb_printf_buffer base
Definition: sprintf.c:1306
#define rb_enc_right_char_head(s, p, e, enc)
Definition: encoding.h:217
#define ECONV_UNDEF_REPLACE
Definition: encoding.h:390
void rb_str_modify(VALUE)
Definition: string.c:2046
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:860
VALUE rb_big_uminus(VALUE x)
Definition: bignum.c:5502
RUBY_EXTERN int ffs(int)
Definition: ffs.c:6
#define RFLOAT_VALUE(v)
Definition: ruby.h:933
int size
Definition: encoding.c:57
#define f
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:842
#define INT2FIX(i)
Definition: ruby.h:232
long rb_enc_strlen(const char *, const char *, rb_encoding *)
Definition: string.c:1700
VALUE rb_rational_num(VALUE rat)
Definition: rational.c:1988
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
Definition: object.c:3398
VALUE rb_eRuntimeError
Definition: error.c:800
VALUE rb_str_vcatf(VALUE str, const char *fmt, va_list ap)
Definition: sprintf.c:1465
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1492
#define ENC_CODERANGE(obj)
Definition: encoding.h:104
VALUE rb_check_string_type(VALUE)
Definition: string.c:2246
#define LONG2FIX(i)
Definition: ruby.h:234
#define RTEST(v)
Definition: ruby.h:450
#define T_STRING
Definition: ruby.h:496
#define GETPOSARG(n)
Definition: sprintf.c:96
#define PRIuSIZE
Definition: ruby.h:177
size_t rb_str_capacity(VALUE str)
Definition: string.c:675
#define OBJ_INFECT(x, s)
Definition: ruby.h:1302
void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt,...)
Definition: error.c:2271
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
Definition: bignum.c:3364
#define CHECKNAMEARG(name, len, enc)
Definition: sprintf.c:103
#define T_CLASS
Definition: ruby.h:492
#define CHECK_FOR_FLAGS(f)
#define PUSH_(s, l)
Definition: sprintf.c:73
#define ruby_debug
Definition: ruby.h:1814
const char * name
Definition: nkf.c:208
#define GETNTHARG(nth)
Definition: sprintf.c:100
#define QUOTE(str)
Definition: internal.h:1635
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1170
int ruby_vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
Definition: sprintf.c:1267
RUBY_EXTERN VALUE rb_cSymbol
Definition: ruby.h:1929
#define rb_enc_mbcput(c, buf, enc)
Definition: encoding.h:211
VALUE rb_str_buf_new(long)
Definition: string.c:1282
#define MUL_OVERFLOW_INT_P(a, b)
Definition: internal.h:132
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
#define FWIDTH
Definition: sprintf.c:53
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:363
#define Qundef
Definition: ruby.h:439
#define FILL_(c, l)
Definition: sprintf.c:84
#define OBJ_TAINT(x)
Definition: ruby.h:1298
#define ruby_verbose
Definition: ruby.h:1813
RUBY_EXTERN VALUE rb_cNilClass
Definition: ruby.h:1918
char ** argv
Definition: ruby.c:188
#define StringValue(v)
Definition: ruby.h:569
size_t iov_len
Definition: vsnprintf.c:228
#define rb_sym2str(sym)
Definition: console.c:107
VALUE rb_str_new(const char *, long)
Definition: string.c:737
#define SIGNED_VALUE
Definition: ruby.h:87