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"
24 #define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
25 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
26 #define EXTENDSIGN(n, l) (((~0 << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0 << (n)))
28 static void fmt_setup(char*,int,int,int,int);
31 remove_sign_bits(char *str
, int base
)
43 *t
|= EXTENDSIGN(3, strlen(t
));
58 sign_bits(int base
, const char *p
)
64 if (*p
== 'X') c
= 'F';
85 #define CHECK(l) do {\
86 while (blen + (l) >= bsiz) {\
89 rb_str_resize(result, bsiz);\
90 buf = RSTRING_PTR(result);\
93 #define PUSH(s, l) do { \
95 memcpy(&buf[blen], s, l);\
99 #define FILL(c, l) do { \
101 memset(&buf[blen], c, l);\
105 #define GETARG() (nextvalue != Qundef ? nextvalue : \
107 (rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg), 0) : \
108 (posarg = nextarg++, GETNTHARG(posarg)))
110 #define GETPOSARG(n) (posarg > 0 ? \
111 (rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg), 0) : \
112 ((n < 1) ? (rb_raise(rb_eArgError, "invalid index - %d$", n), 0) : \
113 (posarg = -1, GETNTHARG(n))))
115 #define GETNTHARG(nth) \
116 ((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[nth])
118 #define GETNUM(n, val) \
119 for (; p < end && rb_enc_isdigit(*p, enc); p++) { \
120 int next_n = 10 * n + (*p - '0'); \
121 if (next_n / 10 != n) {\
122 rb_raise(rb_eArgError, #val " too big"); \
127 rb_raise(rb_eArgError, "malformed format string - %%*[0-9]"); \
130 #define GETASTER(val) do { \
135 tmp = GETPOSARG(n); \
141 val = NUM2INT(tmp); \
147 * format(format_string [, arguments...] ) => string
148 * sprintf(format_string [, arguments...] ) => string
150 * Returns the string resulting from applying <i>format_string</i> to
151 * any additional arguments. Within the format string, any characters
152 * other than format sequences are copied to the result.
154 * The syntax of a format sequence is follows.
156 * %[flags][width][.precision]type
159 * sequence consists of a percent sign, followed by optional flags,
160 * width, and precision indicators, then terminated with a field type
161 * character. The field type controls how the corresponding
162 * <code>sprintf</code> argument is to be interpreted, while the flags
163 * modify that interpretation.
165 * The field type characters are:
167 * Field | Integer Format
168 * ------+--------------------------------------------------------------
169 * b | Convert argument as a binary number.
170 * | Negative numbers will be displayed as a two's complement
171 * | prefixed with `..1'.
172 * B | Equivalent to `b', but uses an uppercase 0B for prefix
173 * | in the alternative format by #.
174 * d | Convert argument as a decimal number.
175 * i | Identical to `d'.
176 * o | Convert argument as an octal number.
177 * | Negative numbers will be displayed as a two's complement
178 * | prefixed with `..7'.
179 * u | Identical to `d'.
180 * x | Convert argument as a hexadecimal number.
181 * | Negative numbers will be displayed as a two's complement
182 * | prefixed with `..f' (representing an infinite string of
184 * X | Equivalent to `x', but uses uppercase letters.
186 * Field | Float Format
187 * ------+--------------------------------------------------------------
188 * e | Convert floating point argument into exponential notation
189 * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
190 * | The precision specifies the number of digits after the decimal
191 * | point (defaulting to six).
192 * E | Equivalent to `e', but uses an uppercase E to indicate
194 * f | Convert floating point argument as [-]ddd.dddddd,
195 * | where the precision specifies the number of digits after
196 * | the decimal point.
197 * g | Convert a floating point number using exponential form
198 * | if the exponent is less than -4 or greater than or
199 * | equal to the precision, or in dd.dddd form otherwise.
200 * | The precision specifies the number of significant digits.
201 * G | Equivalent to `g', but use an uppercase `E' in exponent form.
203 * Field | Other Format
204 * ------+--------------------------------------------------------------
205 * c | Argument is the numeric code for a single character or
206 * | a single character string itself.
207 * p | The valuing of argument.inspect.
208 * s | Argument is a string to be substituted. If the format
209 * | sequence contains a precision, at most that many characters
211 * % | A percent sign itself will be displayed. No argument taken.
213 * The flags modifies the behavior of the formats.
214 * The flag characters are:
216 * Flag | Applies to | Meaning
217 * ---------+---------------+-----------------------------------------
218 * space | bBdiouxX | Leave a space at the start of
219 * | eEfgG | non-negative numbers.
220 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
221 * | | a minus sign with absolute value for
222 * | | negative values.
223 * ---------+---------------+-----------------------------------------
224 * (digit)$ | all | Specifies the absolute argument number
225 * | | for this field. Absolute and relative
226 * | | argument numbers cannot be mixed in a
227 * | | sprintf string.
228 * ---------+---------------+-----------------------------------------
229 * # | bBoxX | Use an alternative format.
230 * | eEfgG | For the conversions `o', increase the precision
231 * | | until the first digit will be `0' if
232 * | | it is not formatted as complements.
233 * | | For the conversions `x', `X', `b' and `B'
234 * | | on non-zero, prefix the result with ``0x'',
235 * | | ``0X'', ``0b'' and ``0B'', respectively.
236 * | | For `e', `E', `f', `g', and 'G',
237 * | | force a decimal point to be added,
238 * | | even if no digits follow.
239 * | | For `g' and 'G', do not remove trailing zeros.
240 * ---------+---------------+-----------------------------------------
241 * + | bBdiouxX | Add a leading plus sign to non-negative
243 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
244 * | | a minus sign with absolute value for
245 * | | negative values.
246 * ---------+---------------+-----------------------------------------
247 * - | all | Left-justify the result of this conversion.
248 * ---------+---------------+-----------------------------------------
249 * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
250 * | eEfgG | For `o', `x', `X', `b' and `B', radix-1
251 * | (numeric fmt) | is used for negative numbers formatted as
253 * ---------+---------------+-----------------------------------------
254 * * | all | Use the next argument as the field width.
255 * | | If negative, left-justify the result. If the
256 * | | asterisk is followed by a number and a dollar
257 * | | sign, use the indicated argument as the width.
261 * # `+' and space flag specifies the sign of non-negative numbers.
262 * sprintf("%d", 123) #=> "123"
263 * sprintf("%+d", 123) #=> "+123"
264 * sprintf("% d", 123) #=> " 123"
266 * # `#' flag for `o' increases number of digits to show `0'.
267 * # `+' and space flag changes format of negative numbers.
268 * sprintf("%o", 123) #=> "173"
269 * sprintf("%#o", 123) #=> "0173"
270 * sprintf("%+o", -123) #=> "-173"
271 * sprintf("%o", -123) #=> "..7605"
272 * sprintf("%#o", -123) #=> "..7605"
274 * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
275 * # `+' and space flag disables complements for negative numbers.
276 * sprintf("%x", 123) #=> "7b"
277 * sprintf("%#x", 123) #=> "0x7b"
278 * sprintf("%+x", -123) #=> "-7b"
279 * sprintf("%x", -123) #=> "..f85"
280 * sprintf("%#x", -123) #=> "0x..f85"
281 * sprintf("%#x", 0) #=> "0"
283 * # `#' for `X' uses the prefix `0X'.
284 * sprintf("%X", 123) #=> "7B"
285 * sprintf("%#X", 123) #=> "0X7B"
287 * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
288 * # `+' and space flag disables complements for negative numbers.
289 * sprintf("%b", 123) #=> "1111011"
290 * sprintf("%#b", 123) #=> "0b1111011"
291 * sprintf("%+b", -123) #=> "-1111011"
292 * sprintf("%b", -123) #=> "..10000101"
293 * sprintf("%#b", -123) #=> "0b..10000101"
294 * sprintf("%#b", 0) #=> "0"
296 * # `#' for `B' uses the prefix `0B'.
297 * sprintf("%B", 123) #=> "1111011"
298 * sprintf("%#B", 123) #=> "0B1111011"
300 * # `#' for `e' forces to show the decimal point.
301 * sprintf("%.0e", 1) #=> "1e+00"
302 * sprintf("%#.0e", 1) #=> "1.e+00"
304 * # `#' for `f' forces to show the decimal point.
305 * sprintf("%.0f", 1234) #=> "1234"
306 * sprintf("%#.0f", 1234) #=> "1234."
308 * # `#' for `g' forces to show the decimal point.
309 * # It also disables stripping lowest zeros.
310 * sprintf("%g", 123.4) #=> "123.4"
311 * sprintf("%#g", 123.4) #=> "123.400"
312 * sprintf("%g", 123456) #=> "123456"
313 * sprintf("%#g", 123456) #=> "123456."
315 * The field width is an optional integer, followed optionally by a
316 * period and a precision. The width specifies the minimum number of
317 * characters that will be written to the result for this field.
321 * # padding is done by spaces, width=20
322 * # 0 or radix-1. <------------------>
323 * sprintf("%20d", 123) #=> " 123"
324 * sprintf("%+20d", 123) #=> " +123"
325 * sprintf("%020d", 123) #=> "00000000000000000123"
326 * sprintf("%+020d", 123) #=> "+0000000000000000123"
327 * sprintf("% 020d", 123) #=> " 0000000000000000123"
328 * sprintf("%-20d", 123) #=> "123 "
329 * sprintf("%-+20d", 123) #=> "+123 "
330 * sprintf("%- 20d", 123) #=> " 123 "
331 * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
334 * numeric fields, the precision controls the number of decimal places
335 * displayed. For string fields, the precision determines the maximum
336 * number of characters to be copied from the string. (Thus, the format
337 * sequence <code>%10.10s</code> will always contribute exactly ten
338 * characters to the result.)
340 * Examples of precisions:
342 * # precision for `d', 'o', 'x' and 'b' is
343 * # minimum number of digits <------>
344 * sprintf("%20.8d", 123) #=> " 00000123"
345 * sprintf("%20.8o", 123) #=> " 00000173"
346 * sprintf("%20.8x", 123) #=> " 0000007b"
347 * sprintf("%20.8b", 123) #=> " 01111011"
348 * sprintf("%20.8d", -123) #=> " -00000123"
349 * sprintf("%20.8o", -123) #=> " ..777605"
350 * sprintf("%20.8x", -123) #=> " ..ffff85"
351 * sprintf("%20.8b", -11) #=> " ..110101"
353 * # "0x" and "0b" for `#x' and `#b' is not counted for
354 * # precision but "0" for `#o' is counted. <------>
355 * sprintf("%#20.8d", 123) #=> " 00000123"
356 * sprintf("%#20.8o", 123) #=> " 00000173"
357 * sprintf("%#20.8x", 123) #=> " 0x0000007b"
358 * sprintf("%#20.8b", 123) #=> " 0b01111011"
359 * sprintf("%#20.8d", -123) #=> " -00000123"
360 * sprintf("%#20.8o", -123) #=> " ..777605"
361 * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
362 * sprintf("%#20.8b", -11) #=> " 0b..110101"
364 * # precision for `e' is number of
365 * # digits after the decimal point <------>
366 * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
368 * # precision for `f' is number of
369 * # digits after the decimal point <------>
370 * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
372 * # precision for `g' is number of
373 * # significant digits <------->
374 * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
377 * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
379 * # precision for `s' is
380 * # maximum number of characters <------>
381 * sprintf("%20.8s", "string test") #=> " string t"
385 * sprintf("%d %04x", 123, 123) #=> "123 007b"
386 * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
387 * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
388 * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
389 * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
390 * sprintf("%u", -123) #=> "-123"
394 rb_f_sprintf(int argc
, const VALUE
*argv
)
396 return rb_str_format(argc
- 1, argv
+ 1, GETNTHARG(0));
400 rb_str_format(int argc
, const VALUE
*argv
, VALUE fmt
)
408 int width
, prec
, flags
= FNONE
;
416 #define CHECK_FOR_WIDTH(f) \
417 if ((f) & FWIDTH) { \
418 rb_raise(rb_eArgError, "width given twice"); \
420 if ((f) & FPREC0) { \
421 rb_raise(rb_eArgError, "width after precision"); \
423 #define CHECK_FOR_FLAGS(f) \
424 if ((f) & FWIDTH) { \
425 rb_raise(rb_eArgError, "flag after width"); \
427 if ((f) & FPREC0) { \
428 rb_raise(rb_eArgError, "flag after precision"); \
433 if (OBJ_TAINTED(fmt
)) tainted
= 1;
435 enc
= rb_enc_get(fmt
);
436 fmt
= rb_str_new4(fmt
);
437 p
= RSTRING_PTR(fmt
);
438 end
= p
+ RSTRING_LEN(fmt
);
441 result
= rb_str_buf_new(bsiz
);
442 rb_enc_copy(result
, fmt
);
443 buf
= RSTRING_PTR(result
);
444 memset(buf
, 0, bsiz
);
446 for (; p
< end
; p
++) {
450 for (t
= p
; t
< end
&& *t
!= '%'; t
++) ;
453 /* end of fmt string */
456 p
= t
+ 1; /* skip `%' */
463 if (rb_enc_isprint(*p
, enc
))
464 rb_raise(rb_eArgError
, "malformed format string - %%%c", *p
);
466 rb_raise(rb_eArgError
, "malformed format string");
470 CHECK_FOR_FLAGS(flags
);
476 CHECK_FOR_FLAGS(flags
);
482 CHECK_FOR_FLAGS(flags
);
488 CHECK_FOR_FLAGS(flags
);
494 CHECK_FOR_FLAGS(flags
);
499 case '1': case '2': case '3': case '4':
500 case '5': case '6': case '7': case '8': case '9':
504 if (nextvalue
!= Qundef
) {
505 rb_raise(rb_eArgError
, "value given twice - %d$", n
);
507 nextvalue
= GETPOSARG(n
);
511 CHECK_FOR_WIDTH(flags
);
517 CHECK_FOR_WIDTH(flags
);
528 if (flags
& FPREC0
) {
529 rb_raise(rb_eArgError
, "precision given twice");
531 flags
|= FPREC
|FPREC0
;
537 if (prec
< 0) { /* ignore negative precision */
544 GETNUM(prec
, precision
);
551 if (flags
!= FNONE
) {
552 rb_raise(rb_eArgError
, "invalid format character - %%");
559 VALUE val
= GETARG();
563 tmp
= rb_check_string_type(val
);
565 if (rb_enc_strlen(RSTRING_PTR(tmp
),RSTRING_END(tmp
),enc
) != 1) {
566 rb_raise(rb_eArgError
, "%%c requires a character");
568 c
= rb_enc_codepoint(RSTRING_PTR(tmp
), RSTRING_END(tmp
), enc
);
573 n
= rb_enc_codelen(c
, enc
);
575 rb_raise(rb_eArgError
, "invalid character");
577 if (!(flags
& FWIDTH
)) {
579 rb_enc_mbcput(c
, &buf
[blen
], enc
);
582 else if ((flags
& FMINUS
)) {
584 rb_enc_mbcput(c
, &buf
[blen
], enc
);
591 rb_enc_mbcput(c
, &buf
[blen
], enc
);
600 VALUE arg
= GETARG();
603 if (*p
== 'p') arg
= rb_inspect(arg
);
604 str
= rb_obj_as_string(arg
);
605 if (OBJ_TAINTED(str
)) tainted
= 1;
606 len
= RSTRING_LEN(str
);
607 enc
= rb_enc_check(result
, str
);
608 if (flags
&(FPREC
|FWIDTH
)) {
609 slen
= rb_enc_strlen(RSTRING_PTR(str
),RSTRING_END(str
),enc
);
611 rb_raise(rb_eArgError
, "invalid mbstring sequence");
613 if ((flags
&FPREC
) && (prec
< slen
)) {
614 char *p
= rb_enc_nth(RSTRING_PTR(str
), RSTRING_END(str
),
617 len
= p
- RSTRING_PTR(str
);
619 /* need to adjust multi-byte string pos */
620 if ((flags
&FWIDTH
) && (width
> slen
)) {
622 if (!(flags
&FMINUS
)) {
629 memcpy(&buf
[blen
], RSTRING_PTR(str
), len
);
637 rb_enc_associate(result
, enc
);
641 PUSH(RSTRING_PTR(str
), len
);
642 rb_enc_associate(result
, enc
);
656 volatile VALUE val
= GETARG();
657 char fbuf
[32], nbuf
[64], *s
;
658 const char *prefix
= 0;
659 int sign
= 0, dots
= 0;
662 int base
, bignum
= 0;
675 if (flags
&(FPLUS
|FSPACE
)) sign
= 1;
678 if (flags
& FSHARP
) {
683 prefix
= "0x"; break;
685 prefix
= "0X"; break;
687 prefix
= "0b"; break;
689 prefix
= "0B"; break;
696 if (FIXABLE(RFLOAT_VALUE(val
))) {
697 val
= LONG2FIX((long)RFLOAT_VALUE(val
));
700 val
= rb_dbl2big(RFLOAT_VALUE(val
));
701 if (FIXNUM_P(val
)) goto bin_retry
;
705 val
= rb_str_to_inum(val
, 0, Qtrue
);
714 val
= rb_Integer(val
);
741 if (c
== 'i') c
= 'd'; /* %d and %i are identical */
747 else if (flags
& FPLUS
) {
751 else if (flags
& FSPACE
) {
755 sprintf(fbuf
, "%%l%c", c
);
756 sprintf(nbuf
, fbuf
, v
);
764 sprintf(fbuf
, "%%l%c", *p
== 'X' ? 'x' : *p
);
765 sprintf(++s
, fbuf
, v
);
769 s
= remove_sign_bits(s
, base
);
784 tmp
= rb_big2str(val
, base
);
785 s
= RSTRING_PTR(tmp
);
791 else if (flags
& FPLUS
) {
795 else if (flags
& FSPACE
) {
801 if (!RBIGNUM_SIGN(val
)) {
802 val
= rb_big_clone(val
);
805 tmp1
= tmp
= rb_big2str0(val
, base
, RBIGNUM_SIGN(val
));
806 s
= RSTRING_PTR(tmp
);
810 rb_warning("negative number for %%u specifier");
812 s
= remove_sign_bits(++s
, base
);
815 if (s
[0] != 'f') *--s
= 'f'; break;
817 if (s
[0] != '7') *--s
= '7'; break;
819 if (s
[0] != '1') *--s
= '1'; break;
835 while ((c
= (int)(unsigned char)*pp
) != 0) {
836 *pp
= rb_enc_toupper(c
, enc
);
840 if (prefix
&& !prefix
[1]) { /* octal */
844 else if (len
== 1 && *s
== '0') {
846 if (flags
& FPREC
) prec
--;
848 else if ((flags
& FPREC
) && (prec
> len
)) {
852 else if (len
== 1 && *s
== '0') {
856 width
-= strlen(prefix
);
858 if ((flags
& (FZERO
|FMINUS
|FPREC
)) == FZERO
) {
864 if (!prefix
&& prec
== 0 && len
== 1 && *s
== '0') len
= 0;
869 if (!(flags
&FMINUS
)) {
871 while (width
-- > 0) {
875 if (sc
) PUSH(&sc
, 1);
877 int plen
= strlen(prefix
);
881 if (dots
) PUSH("..", 2);
882 if (!bignum
&& v
< 0) {
883 char c
= sign_bits(base
, p
);
884 while (len
< prec
--) {
888 else if ((flags
& (FMINUS
|FPREC
)) != FMINUS
) {
891 if (!sign
&& bignum
&& !RBIGNUM_SIGN(val
))
892 c
= sign_bits(base
, p
);
895 while (len
< prec
--) {
901 while (width
-- > 0) {
913 VALUE val
= GETARG();
918 fval
= RFLOAT_VALUE(rb_Float(val
));
919 if (isnan(fval
) || isinf(fval
)) {
929 if ((!isnan(fval
) && fval
< 0.0) || (flags
& FPLUS
))
931 if ((flags
& FWIDTH
) && need
< width
)
935 sprintf(&buf
[blen
], "%*s", need
, "");
936 if (flags
& FMINUS
) {
937 if (!isnan(fval
) && fval
< 0.0)
939 else if (flags
& FPLUS
)
941 else if (flags
& FSPACE
)
943 strncpy(&buf
[blen
], expr
, strlen(expr
));
946 if (!isnan(fval
) && fval
< 0.0)
947 buf
[blen
+ need
- strlen(expr
) - 1] = '-';
948 else if (flags
& FPLUS
)
949 buf
[blen
+ need
- strlen(expr
) - 1] = '+';
950 else if ((flags
& FSPACE
) && need
> width
)
952 strncpy(&buf
[blen
+ need
- strlen(expr
)], expr
,
955 blen
+= strlen(&buf
[blen
]);
959 fmt_setup(fbuf
, *p
, flags
, width
, prec
);
961 if (*p
!= 'e' && *p
!= 'E') {
965 need
= BIT_DIGITS(i
);
967 need
+= (flags
&FPREC
) ? prec
: 6;
968 if ((flags
&FWIDTH
) && need
< width
)
973 sprintf(&buf
[blen
], fbuf
, fval
);
974 blen
+= strlen(&buf
[blen
]);
982 /* XXX - We cannot validate the number of arguments if (digit)$ style used.
984 if (posarg
>= 0 && nextarg
< argc
) {
985 const char *mesg
= "too many arguments for format string";
986 if (RTEST(ruby_debug
)) rb_raise(rb_eArgError
, "%s", mesg
);
987 if (RTEST(ruby_verbose
)) rb_warn("%s", mesg
);
989 rb_str_resize(result
, blen
);
991 if (tainted
) OBJ_TAINT(result
);
996 fmt_setup(char *buf
, int c
, int flags
, int width
, int prec
)
999 if (flags
& FSHARP
) *buf
++ = '#';
1000 if (flags
& FPLUS
) *buf
++ = '+';
1001 if (flags
& FMINUS
) *buf
++ = '-';
1002 if (flags
& FZERO
) *buf
++ = '0';
1003 if (flags
& FSPACE
) *buf
++ = ' ';
1005 if (flags
& FWIDTH
) {
1006 sprintf(buf
, "%d", width
);
1010 if (flags
& FPREC
) {
1011 sprintf(buf
, ".%d", prec
);
1020 #define FILE rb_printf_buffer
1021 #define __sbuf rb_printf_sbuf
1022 #define __sFILE rb_printf_sfile
1027 #if SIZEOF_LONG < SIZEOF_VOIDP
1028 # if SIZEOF_LONG_LONG == SIZEOF_VOIDP
1029 # define _HAVE_SANE_QUAD_
1030 # define _HAVE_LLP64_
1031 # define quad_t LONG_LONG
1032 # define u_quad_t unsigned LONG_LONG
1037 #define FLOATING_POINT 1
1038 #define BSD__dtoa dtoa
1039 #include "missing/vsnprintf.c"
1042 ruby__sfvwrite(register rb_printf_buffer
*fp
, register struct __suio
*uio
)
1045 VALUE result
= (VALUE
)fp
->_bf
._base
;
1046 char *buf
= (char*)fp
->_p
;
1048 size_t blen
= buf
- RSTRING_PTR(result
), bsiz
= fp
->_w
;
1050 if (RBASIC(result
)->klass
) {
1051 rb_raise(rb_eRuntimeError
, "rb_vsprintf reentered");
1053 if ((len
= uio
->uio_resid
) == 0)
1058 for (iov
= uio
->uio_iov
; len
> 0; ++iov
) {
1059 MEMCPY(buf
, iov
->iov_base
, char, n
= iov
->iov_len
);
1063 fp
->_p
= (unsigned char *)buf
;
1068 rb_enc_vsprintf(rb_encoding
*enc
, const char *fmt
, va_list ap
)
1073 f
._flags
= __SWR
| __SSTR
;
1076 result
= rb_str_buf_new(f
._w
);
1077 if (enc
) rb_enc_associate(result
, enc
);
1078 f
._bf
._base
= (unsigned char *)result
;
1079 f
._p
= (unsigned char *)RSTRING_PTR(result
);
1080 RBASIC(result
)->klass
= 0;
1081 f
.vwrite
= ruby__sfvwrite
;
1082 BSD_vfprintf(&f
, fmt
, ap
);
1083 RBASIC(result
)->klass
= rb_cString
;
1084 rb_str_resize(result
, (char *)f
._p
- RSTRING_PTR(result
));
1090 rb_enc_sprintf(rb_encoding
*enc
, const char *format
, ...)
1095 va_start(ap
, format
);
1096 result
= rb_enc_vsprintf(enc
, format
, ap
);
1103 rb_vsprintf(const char *fmt
, va_list ap
)
1105 return rb_enc_vsprintf(NULL
, fmt
, ap
);
1109 rb_sprintf(const char *format
, ...)
1114 va_start(ap
, format
);
1115 result
= rb_vsprintf(format
, ap
);
1122 rb_str_vcatf(VALUE str
, const char *fmt
, va_list ap
)
1129 f
._flags
= __SWR
| __SSTR
;
1131 f
._w
= rb_str_capacity(str
);
1132 f
._bf
._base
= (unsigned char *)str
;
1133 f
._p
= (unsigned char *)RSTRING_END(str
);
1134 klass
= RBASIC(str
)->klass
;
1135 RBASIC(str
)->klass
= 0;
1136 f
.vwrite
= ruby__sfvwrite
;
1137 BSD_vfprintf(&f
, fmt
, ap
);
1138 RBASIC(str
)->klass
= klass
;
1139 rb_str_resize(str
, (char *)f
._p
- RSTRING_PTR(str
));
1145 rb_str_catf(VALUE str
, const char *format
, ...)
1149 va_start(ap
, format
);
1150 str
= rb_str_vcatf(str
, format
, ap
);