1 /**********************************************************************
6 created at: Fri Oct 15 10:39:26 JST 1993
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
12 **********************************************************************/
14 #include "ruby/ruby.h"
16 #include "ruby/encoding.h"
20 #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
21 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
22 #define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n)))
24 static void fmt_setup(char*,int,int,int,int);
27 remove_sign_bits(char *str
, int base
)
39 *t
|= EXTENDSIGN(3, strlen(t
));
54 sign_bits(int base
, const char *p
)
60 if (*p
== 'X') c
= 'F';
81 #define CHECK(l) do {\
82 while (blen + (l) >= bsiz) {\
85 rb_str_resize(result, bsiz);\
86 buf = RSTRING_PTR(result);\
89 #define PUSH(s, l) do { \
91 memcpy(&buf[blen], s, l);\
95 #define FILL(c, l) do { \
97 memset(&buf[blen], c, l);\
101 #define GETARG() (nextvalue != Qundef ? nextvalue : \
103 (rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg), 0) : \
104 (posarg = nextarg++, GETNTHARG(posarg)))
106 #define GETPOSARG(n) (posarg > 0 ? \
107 (rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg), 0) : \
108 ((n < 1) ? (rb_raise(rb_eArgError, "invalid index - %d$", n), 0) : \
109 (posarg = -1, GETNTHARG(n))))
111 #define GETNTHARG(nth) \
112 ((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[nth])
114 #define GETNUM(n, val) \
115 for (; p < end && rb_enc_isdigit(*p, enc); p++) { \
116 int next_n = 10 * n + (*p - '0'); \
117 if (next_n / 10 != n) {\
118 rb_raise(rb_eArgError, #val " too big"); \
123 rb_raise(rb_eArgError, "malformed format string - %%*[0-9]"); \
126 #define GETASTER(val) do { \
131 tmp = GETPOSARG(n); \
137 val = NUM2INT(tmp); \
143 * format(format_string [, arguments...] ) => string
144 * sprintf(format_string [, arguments...] ) => string
146 * Returns the string resulting from applying <i>format_string</i> to
147 * any additional arguments. Within the format string, any characters
148 * other than format sequences are copied to the result.
150 * The syntax of a format sequence is follows.
152 * %[flags][width][.precision]type
155 * sequence consists of a percent sign, followed by optional flags,
156 * width, and precision indicators, then terminated with a field type
157 * character. The field type controls how the corresponding
158 * <code>sprintf</code> argument is to be interpreted, while the flags
159 * modify that interpretation.
161 * The field type characters are:
163 * Field | Integer Format
164 * ------+--------------------------------------------------------------
165 * b | Convert argument as a binary number.
166 * | Negative numbers will be displayed as a two's complement
167 * | prefixed with `..1'.
168 * B | Equivalent to `b', but uses an uppercase 0B for prefix
169 * | in the alternative format by #.
170 * d | Convert argument as a decimal number.
171 * i | Identical to `d'.
172 * o | Convert argument as an octal number.
173 * | Negative numbers will be displayed as a two's complement
174 * | prefixed with `..7'.
175 * u | Identical to `d'.
176 * x | Convert argument as a hexadecimal number.
177 * | Negative numbers will be displayed as a two's complement
178 * | prefixed with `..f' (representing an infinite string of
180 * X | Equivalent to `x', but uses uppercase letters.
182 * Field | Float Format
183 * ------+--------------------------------------------------------------
184 * e | Convert floating point argument into exponential notation
185 * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
186 * | The precision specifies the number of digits after the decimal
187 * | point (defaulting to six).
188 * E | Equivalent to `e', but uses an uppercase E to indicate
190 * f | Convert floating point argument as [-]ddd.dddddd,
191 * | where the precision specifies the number of digits after
192 * | the decimal point.
193 * g | Convert a floating point number using exponential form
194 * | if the exponent is less than -4 or greater than or
195 * | equal to the precision, or in dd.dddd form otherwise.
196 * | The precision specifies the number of significant digits.
197 * G | Equivalent to `g', but use an uppercase `E' in exponent form.
199 * Field | Other Format
200 * ------+--------------------------------------------------------------
201 * c | Argument is the numeric code for a single character or
202 * | a single character string itself.
203 * p | The valuing of argument.inspect.
204 * s | Argument is a string to be substituted. If the format
205 * | sequence contains a precision, at most that many characters
208 * The flags modifies the behavior of the formats.
209 * The flag characters are:
211 * Flag | Applies to | Meaning
212 * ---------+---------------+-----------------------------------------
213 * space | bBdiouxX | Leave a space at the start of
214 * | eEfgG | non-negative numbers.
215 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
216 * | | a minus sign with absolute value for
217 * | | negative values.
218 * ---------+---------------+-----------------------------------------
219 * (digit)$ | all | Specifies the absolute argument number
220 * | | for this field. Absolute and relative
221 * | | argument numbers cannot be mixed in a
222 * | | sprintf string.
223 * ---------+---------------+-----------------------------------------
224 * # | bBoxX | Use an alternative format.
225 * | eEfgG | For the conversions `o', increase the precision
226 * | | until the first digit will be `0' if
227 * | | it is not formatted as complements.
228 * | | For the conversions `x', `X', `b' and `B'
229 * | | on non-zero, prefix the result with ``0x'',
230 * | | ``0X'', ``0b'' and ``0B'', respectively.
231 * | | For `e', `E', `f', `g', and 'G',
232 * | | force a decimal point to be added,
233 * | | even if no digits follow.
234 * | | For `g' and 'G', do not remove trailing zeros.
235 * ---------+---------------+-----------------------------------------
236 * + | bBdiouxX | Add a leading plus sign to non-negative
238 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
239 * | | a minus sign with absolute value for
240 * | | negative values.
241 * ---------+---------------+-----------------------------------------
242 * - | all | Left-justify the result of this conversion.
243 * ---------+---------------+-----------------------------------------
244 * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
245 * | eEfgG | For `o', `x', `X', `b' and `B', radix-1
246 * | (numeric fmt) | is used for negative numbers formatted as
248 * ---------+---------------+-----------------------------------------
249 * * | all | Use the next argument as the field width.
250 * | | If negative, left-justify the result. If the
251 * | | asterisk is followed by a number and a dollar
252 * | | sign, use the indicated argument as the width.
256 * # `+' and space flag specifies the sign of non-negative numbers.
257 * sprintf("%d", 123) #=> "123"
258 * sprintf("%+d", 123) #=> "+123"
259 * sprintf("% d", 123) #=> " 123"
261 * # `#' flag for `o' increases number of digits to show `0'.
262 * # `+' and space flag changes format of negative numbers.
263 * sprintf("%o", 123) #=> "173"
264 * sprintf("%#o", 123) #=> "0173"
265 * sprintf("%+o", -123) #=> "-173"
266 * sprintf("%o", -123) #=> "..7605"
267 * sprintf("%#o", -123) #=> "..7605"
269 * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
270 * # `+' and space flag disables complements for negative numbers.
271 * sprintf("%x", 123) #=> "7b"
272 * sprintf("%#x", 123) #=> "0x7b"
273 * sprintf("%+x", -123) #=> "-7b"
274 * sprintf("%x", -123) #=> "..f85"
275 * sprintf("%#x", -123) #=> "0x..f85"
276 * sprintf("%#x", 0) #=> "0"
278 * # `#' for `X' uses the prefix `0X'.
279 * sprintf("%X", 123) #=> "7B"
280 * sprintf("%#X", 123) #=> "0X7B"
282 * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
283 * # `+' and space flag disables complements for negative numbers.
284 * sprintf("%b", 123) #=> "1111011"
285 * sprintf("%#b", 123) #=> "0b1111011"
286 * sprintf("%+b", -123) #=> "-1111011"
287 * sprintf("%b", -123) #=> "..10000101"
288 * sprintf("%#b", -123) #=> "0b..10000101"
289 * sprintf("%#b", 0) #=> "0"
291 * # `#' for `B' uses the prefix `0B'.
292 * sprintf("%B", 123) #=> "1111011"
293 * sprintf("%#B", 123) #=> "0B1111011"
295 * # `#' for `e' forces to show the decimal point.
296 * sprintf("%.0e", 1) #=> "1e+00"
297 * sprintf("%#.0e", 1) #=> "1.e+00"
299 * # `#' for `f' forces to show the decimal point.
300 * sprintf("%.0f", 1234) #=> "1234"
301 * sprintf("%#.0f", 1234) #=> "1234."
303 * # `#' for `g' forces to show the decimal point.
304 * # It also disables stripping lowest zeros.
305 * sprintf("%g", 123.4) #=> "123.4"
306 * sprintf("%#g", 123.4) #=> "123.400"
307 * sprintf("%g", 123456) #=> "123456"
308 * sprintf("%#g", 123456) #=> "123456."
310 * The field width is an optional integer, followed optionally by a
311 * period and a precision. The width specifies the minimum number of
312 * characters that will be written to the result for this field.
316 * # padding is done by spaces, width=20
317 * # 0 or radix-1. <------------------>
318 * sprintf("%20d", 123) #=> " 123"
319 * sprintf("%+20d", 123) #=> " +123"
320 * sprintf("%020d", 123) #=> "00000000000000000123"
321 * sprintf("%+020d", 123) #=> "+0000000000000000123"
322 * sprintf("% 020d", 123) #=> " 0000000000000000123"
323 * sprintf("%-20d", 123) #=> "123 "
324 * sprintf("%-+20d", 123) #=> "+123 "
325 * sprintf("%- 20d", 123) #=> " 123 "
326 * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
329 * numeric fields, the precision controls the number of decimal places
330 * displayed. For string fields, the precision determines the maximum
331 * number of characters to be copied from the string. (Thus, the format
332 * sequence <code>%10.10s</code> will always contribute exactly ten
333 * characters to the result.)
335 * Examples of precisions:
337 * # precision for `d', 'o', 'x' and 'b' is
338 * # minimum number of digits <------>
339 * sprintf("%20.8d", 123) #=> " 00000123"
340 * sprintf("%20.8o", 123) #=> " 00000173"
341 * sprintf("%20.8x", 123) #=> " 0000007b"
342 * sprintf("%20.8b", 123) #=> " 01111011"
343 * sprintf("%20.8d", -123) #=> " -00000123"
344 * sprintf("%20.8o", -123) #=> " ..777605"
345 * sprintf("%20.8x", -123) #=> " ..ffff85"
346 * sprintf("%20.8b", -11) #=> " ..110101"
348 * # "0x" and "0b" for `#x' and `#b' is not counted for
349 * # precision but "0" for `#o' is counted. <------>
350 * sprintf("%#20.8d", 123) #=> " 00000123"
351 * sprintf("%#20.8o", 123) #=> " 00000173"
352 * sprintf("%#20.8x", 123) #=> " 0x0000007b"
353 * sprintf("%#20.8b", 123) #=> " 0b01111011"
354 * sprintf("%#20.8d", -123) #=> " -00000123"
355 * sprintf("%#20.8o", -123) #=> " ..777605"
356 * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
357 * sprintf("%#20.8b", -11) #=> " 0b..110101"
359 * # precision for `e' is number of
360 * # digits after the decimal point <------>
361 * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
363 * # precision for `f' is number of
364 * # digits after the decimal point <------>
365 * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
367 * # precision for `g' is number of
368 * # significant digits <------->
369 * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
372 * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
374 * # precision for `s' is
375 * # maximum number of characters <------>
376 * sprintf("%20.8s", "string test") #=> " string t"
380 * sprintf("%d %04x", 123, 123) #=> "123 007b"
381 * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
382 * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
383 * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
384 * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
385 * sprintf("%u", -123) #=> "-123"
389 rb_f_sprintf(int argc
, const VALUE
*argv
)
391 return rb_str_format(argc
- 1, argv
+ 1, GETNTHARG(0));
395 rb_str_format(int argc
, const VALUE
*argv
, VALUE fmt
)
403 int width
, prec
, flags
= FNONE
;
411 #define CHECK_FOR_WIDTH(f) \
412 if ((f) & FWIDTH) { \
413 rb_raise(rb_eArgError, "width given twice"); \
415 if ((f) & FPREC0) { \
416 rb_raise(rb_eArgError, "width after precision"); \
418 #define CHECK_FOR_FLAGS(f) \
419 if ((f) & FWIDTH) { \
420 rb_raise(rb_eArgError, "flag after width"); \
422 if ((f) & FPREC0) { \
423 rb_raise(rb_eArgError, "flag after precision"); \
428 if (OBJ_TAINTED(fmt
)) tainted
= 1;
430 enc
= rb_enc_get(fmt
);
431 fmt
= rb_str_new4(fmt
);
432 p
= RSTRING_PTR(fmt
);
433 end
= p
+ RSTRING_LEN(fmt
);
436 result
= rb_str_buf_new(bsiz
);
437 rb_enc_copy(result
, fmt
);
438 buf
= RSTRING_PTR(result
);
439 memset(buf
, 0, bsiz
);
441 for (; p
< end
; p
++) {
445 for (t
= p
; t
< end
&& *t
!= '%'; t
++) ;
448 /* end of fmt string */
451 p
= t
+ 1; /* skip `%' */
458 if (rb_enc_isprint(*p
, enc
))
459 rb_raise(rb_eArgError
, "malformed format string - %%%c", *p
);
461 rb_raise(rb_eArgError
, "malformed format string");
465 CHECK_FOR_FLAGS(flags
);
471 CHECK_FOR_FLAGS(flags
);
477 CHECK_FOR_FLAGS(flags
);
483 CHECK_FOR_FLAGS(flags
);
489 CHECK_FOR_FLAGS(flags
);
494 case '1': case '2': case '3': case '4':
495 case '5': case '6': case '7': case '8': case '9':
499 if (nextvalue
!= Qundef
) {
500 rb_raise(rb_eArgError
, "value given twice - %d$", n
);
502 nextvalue
= GETPOSARG(n
);
506 CHECK_FOR_WIDTH(flags
);
512 CHECK_FOR_WIDTH(flags
);
523 if (flags
& FPREC0
) {
524 rb_raise(rb_eArgError
, "precision given twice");
526 flags
|= FPREC
|FPREC0
;
532 if (prec
< 0) { /* ignore negative precision */
539 GETNUM(prec
, precision
);
546 if (flags
!= FNONE
) {
547 rb_raise(rb_eArgError
, "invalid format character - %%");
554 VALUE val
= GETARG();
558 tmp
= rb_check_string_type(val
);
560 if (rb_enc_strlen(RSTRING_PTR(tmp
),RSTRING_END(tmp
),enc
) != 1) {
561 rb_raise(rb_eArgError
, "%%c requires a character");
563 c
= rb_enc_codepoint(RSTRING_PTR(tmp
), RSTRING_END(tmp
), enc
);
568 n
= rb_enc_codelen(c
, enc
);
570 rb_raise(rb_eArgError
, "invalid character");
572 if (!(flags
& FWIDTH
)) {
574 rb_enc_mbcput(c
, &buf
[blen
], enc
);
577 else if ((flags
& FMINUS
)) {
579 rb_enc_mbcput(c
, &buf
[blen
], enc
);
586 rb_enc_mbcput(c
, &buf
[blen
], enc
);
595 VALUE arg
= GETARG();
598 if (*p
== 'p') arg
= rb_inspect(arg
);
599 str
= rb_obj_as_string(arg
);
600 if (OBJ_TAINTED(str
)) tainted
= 1;
601 len
= RSTRING_LEN(str
);
602 enc
= rb_enc_check(result
, str
);
603 if (flags
&(FPREC
|FWIDTH
)) {
604 slen
= rb_enc_strlen(RSTRING_PTR(str
),RSTRING_END(str
),enc
);
606 rb_raise(rb_eArgError
, "invalid mbstring sequence");
608 if ((flags
&FPREC
) && (prec
< slen
)) {
609 char *p
= rb_enc_nth(RSTRING_PTR(str
), RSTRING_END(str
),
612 len
= p
- RSTRING_PTR(str
);
614 /* need to adjust multi-byte string pos */
615 if ((flags
&FWIDTH
) && (width
> slen
)) {
617 if (!(flags
&FMINUS
)) {
624 memcpy(&buf
[blen
], RSTRING_PTR(str
), len
);
632 rb_enc_associate(result
, enc
);
636 PUSH(RSTRING_PTR(str
), len
);
637 rb_enc_associate(result
, enc
);
651 volatile VALUE val
= GETARG();
652 char fbuf
[32], nbuf
[64], *s
;
653 const char *prefix
= 0;
654 int sign
= 0, dots
= 0;
657 int base
, bignum
= 0;
670 if (flags
&(FPLUS
|FSPACE
)) sign
= 1;
673 if (flags
& FSHARP
) {
678 prefix
= "0x"; break;
680 prefix
= "0X"; break;
682 prefix
= "0b"; break;
684 prefix
= "0B"; break;
691 if (FIXABLE(RFLOAT_VALUE(val
))) {
692 val
= LONG2FIX((long)RFLOAT_VALUE(val
));
695 val
= rb_dbl2big(RFLOAT_VALUE(val
));
696 if (FIXNUM_P(val
)) goto bin_retry
;
700 val
= rb_str_to_inum(val
, 0, Qtrue
);
709 val
= rb_Integer(val
);
736 if (c
== 'i') c
= 'd'; /* %d and %i are identical */
742 else if (flags
& FPLUS
) {
746 else if (flags
& FSPACE
) {
750 sprintf(fbuf
, "%%l%c", c
);
751 sprintf(nbuf
, fbuf
, v
);
759 sprintf(fbuf
, "%%l%c", *p
== 'X' ? 'x' : *p
);
760 sprintf(++s
, fbuf
, v
);
764 s
= remove_sign_bits(s
, base
);
779 tmp
= rb_big2str(val
, base
);
780 s
= RSTRING_PTR(tmp
);
786 else if (flags
& FPLUS
) {
790 else if (flags
& FSPACE
) {
796 if (!RBIGNUM_SIGN(val
)) {
797 val
= rb_big_clone(val
);
800 tmp1
= tmp
= rb_big2str0(val
, base
, RBIGNUM_SIGN(val
));
801 s
= RSTRING_PTR(tmp
);
805 rb_warning("negative number for %%u specifier");
807 s
= remove_sign_bits(++s
, base
);
810 if (s
[0] != 'f') *--s
= 'f'; break;
812 if (s
[0] != '7') *--s
= '7'; break;
814 if (s
[0] != '1') *--s
= '1'; break;
830 while ((c
= (int)(unsigned char)*pp
) != 0) {
831 *pp
= rb_enc_toupper(c
, enc
);
835 if (prefix
&& !prefix
[1]) { /* octal */
839 else if (len
== 1 && *s
== '0') {
841 if (flags
& FPREC
) prec
--;
843 else if ((flags
& FPREC
) && (prec
> len
)) {
847 else if (len
== 1 && *s
== '0') {
851 width
-= strlen(prefix
);
853 if ((flags
& (FZERO
|FMINUS
|FPREC
)) == FZERO
) {
859 if (!prefix
&& prec
== 0 && len
== 1 && *s
== '0') len
= 0;
864 if (!(flags
&FMINUS
)) {
866 while (width
-- > 0) {
870 if (sc
) PUSH(&sc
, 1);
872 int plen
= strlen(prefix
);
876 if (dots
) PUSH("..", 2);
877 if (!bignum
&& v
< 0) {
878 char c
= sign_bits(base
, p
);
879 while (len
< prec
--) {
883 else if ((flags
& (FMINUS
|FPREC
)) != FMINUS
) {
886 if (!sign
&& bignum
&& !RBIGNUM_SIGN(val
))
887 c
= sign_bits(base
, p
);
890 while (len
< prec
--) {
896 while (width
-- > 0) {
908 VALUE val
= GETARG();
913 fval
= RFLOAT_VALUE(rb_Float(val
));
914 if (isnan(fval
) || isinf(fval
)) {
924 if ((!isnan(fval
) && fval
< 0.0) || (flags
& FPLUS
))
926 if ((flags
& FWIDTH
) && need
< width
)
930 sprintf(&buf
[blen
], "%*s", need
, "");
931 if (flags
& FMINUS
) {
932 if (!isnan(fval
) && fval
< 0.0)
934 else if (flags
& FPLUS
)
936 else if (flags
& FSPACE
)
938 strncpy(&buf
[blen
], expr
, strlen(expr
));
941 if (!isnan(fval
) && fval
< 0.0)
942 buf
[blen
+ need
- strlen(expr
) - 1] = '-';
943 else if (flags
& FPLUS
)
944 buf
[blen
+ need
- strlen(expr
) - 1] = '+';
945 else if ((flags
& FSPACE
) && need
> width
)
947 strncpy(&buf
[blen
+ need
- strlen(expr
)], expr
,
950 blen
+= strlen(&buf
[blen
]);
954 fmt_setup(fbuf
, *p
, flags
, width
, prec
);
956 if (*p
!= 'e' && *p
!= 'E') {
960 need
= BIT_DIGITS(i
);
962 need
+= (flags
&FPREC
) ? prec
: 6;
963 if ((flags
&FWIDTH
) && need
< width
)
968 sprintf(&buf
[blen
], fbuf
, fval
);
969 blen
+= strlen(&buf
[blen
]);
977 /* XXX - We cannot validate the number of arguments if (digit)$ style used.
979 if (posarg
>= 0 && nextarg
< argc
) {
980 const char *mesg
= "too many arguments for format string";
981 if (RTEST(ruby_debug
)) rb_raise(rb_eArgError
, mesg
);
982 if (RTEST(ruby_verbose
)) rb_warn(mesg
);
984 rb_str_resize(result
, blen
);
986 if (tainted
) OBJ_TAINT(result
);
991 fmt_setup(char *buf
, int c
, int flags
, int width
, int prec
)
994 if (flags
& FSHARP
) *buf
++ = '#';
995 if (flags
& FPLUS
) *buf
++ = '+';
996 if (flags
& FMINUS
) *buf
++ = '-';
997 if (flags
& FZERO
) *buf
++ = '0';
998 if (flags
& FSPACE
) *buf
++ = ' ';
1000 if (flags
& FWIDTH
) {
1001 sprintf(buf
, "%d", width
);
1005 if (flags
& FPREC
) {
1006 sprintf(buf
, ".%d", prec
);
1015 #define FILE rb_printf_buffer
1016 #define __sbuf rb_printf_sbuf
1017 #define __sFILE rb_printf_sfile
1022 #if SIZEOF_LONG < SIZEOF_VOIDP
1023 # if SIZEOF_LONG_LONG == SIZEOF_VOIDP
1024 # define _HAVE_SANE_QUAD_
1025 # define _HAVE_LLP64_
1026 # define quad_t LONG_LONG
1027 # define u_quad_t unsigned LONG_LONG
1032 #include "missing/vsnprintf.c"
1035 ruby__sfvwrite(register rb_printf_buffer
*fp
, register struct __suio
*uio
)
1038 VALUE result
= (VALUE
)fp
->_bf
._base
;
1039 char *buf
= (char*)fp
->_p
;
1041 int blen
= buf
- RSTRING_PTR(result
), bsiz
= fp
->_w
;
1043 if (RBASIC(result
)->klass
) {
1044 rb_raise(rb_eRuntimeError
, "rb_vsprintf reentered");
1046 if ((len
= uio
->uio_resid
) == 0)
1051 for (iov
= uio
->uio_iov
; len
> 0; ++iov
) {
1052 MEMCPY(buf
, iov
->iov_base
, char, n
= iov
->iov_len
);
1056 fp
->_p
= (unsigned char *)buf
;
1061 rb_enc_vsprintf(rb_encoding
*enc
, const char *fmt
, va_list ap
)
1066 f
._flags
= __SWR
| __SSTR
;
1069 result
= rb_str_buf_new(f
._w
);
1070 if (enc
) rb_enc_associate(result
, enc
);
1071 f
._bf
._base
= (unsigned char *)result
;
1072 f
._p
= (unsigned char *)RSTRING_PTR(result
);
1073 RBASIC(result
)->klass
= 0;
1074 f
.vwrite
= ruby__sfvwrite
;
1075 BSD_vfprintf(&f
, fmt
, ap
);
1076 RBASIC(result
)->klass
= rb_cString
;
1077 rb_str_resize(result
, (char *)f
._p
- RSTRING_PTR(result
));
1083 rb_enc_sprintf(rb_encoding
*enc
, const char *format
, ...)
1088 va_start(ap
, format
);
1089 result
= rb_enc_vsprintf(enc
, format
, ap
);
1096 rb_vsprintf(const char *fmt
, va_list ap
)
1098 return rb_enc_vsprintf(NULL
, fmt
, ap
);
1102 rb_sprintf(const char *format
, ...)
1107 va_start(ap
, format
);
1108 result
= rb_vsprintf(format
, ap
);