Skip to content
Newer
Older
100644 849 lines (793 sloc) 25.1 KB
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
1 /*
2 * MacRuby implementation of Ruby 1.9's sprintf.c.
3 *
4 * This file is covered by the Ruby license. See COPYING for more details.
5 *
4aca101 @drernie Added 2010 Copyrights
drernie authored Jan 20, 2010
6 * Copyright (C) 2007-2010, Apple Inc. All rights reserved.
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
7 * Copyright (C) 1993-2007 Yukihiro Matsumoto
8 * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
9 * Copyright (C) 2000 Information-technology Promotion Agency, Japan
10 */
11
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
12 #include <stdarg.h>
13
468a2ea Move Obj-C related headers around.
Thibault Martin-Lagardette authored Jul 8, 2010
14 #include "ruby/macruby.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
15 #include "ruby/encoding.h"
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
16 #include "encoding.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
17
18 /*
19 * call-seq:
20 * format(format_string [, arguments...] ) => string
21 * sprintf(format_string [, arguments...] ) => string
22 *
23 * Returns the string resulting from applying <i>format_string</i> to
24 * any additional arguments. Within the format string, any characters
25 * other than format sequences are copied to the result.
26 *
27 * The syntax of a format sequence is follows.
28 *
29 * %[flags][width][.precision]type
30 *
31 * A format
32 * sequence consists of a percent sign, followed by optional flags,
33 * width, and precision indicators, then terminated with a field type
34 * character. The field type controls how the corresponding
35 * <code>sprintf</code> argument is to be interpreted, while the flags
36 * modify that interpretation.
37 *
38 * The field type characters are:
39 *
40 * Field | Integer Format
41 * ------+--------------------------------------------------------------
42 * b | Convert argument as a binary number.
43 * | Negative numbers will be displayed as a two's complement
44 * | prefixed with `..1'.
45 * B | Equivalent to `b', but uses an uppercase 0B for prefix
46 * | in the alternative format by #.
47 * d | Convert argument as a decimal number.
48 * i | Identical to `d'.
49 * o | Convert argument as an octal number.
50 * | Negative numbers will be displayed as a two's complement
51 * | prefixed with `..7'.
52 * u | Identical to `d'.
53 * x | Convert argument as a hexadecimal number.
54 * | Negative numbers will be displayed as a two's complement
55 * | prefixed with `..f' (representing an infinite string of
56 * | leading 'ff's).
57 * X | Equivalent to `x', but uses uppercase letters.
58 *
59 * Field | Float Format
60 * ------+--------------------------------------------------------------
61 * e | Convert floating point argument into exponential notation
62 * | with one digit before the decimal point as [-]d.dddddde[+-]dd.
63 * | The precision specifies the number of digits after the decimal
64 * | point (defaulting to six).
65 * E | Equivalent to `e', but uses an uppercase E to indicate
66 * | the exponent.
67 * f | Convert floating point argument as [-]ddd.dddddd,
68 * | where the precision specifies the number of digits after
69 * | the decimal point.
70 * g | Convert a floating point number using exponential form
71 * | if the exponent is less than -4 or greater than or
72 * | equal to the precision, or in dd.dddd form otherwise.
73 * | The precision specifies the number of significant digits.
74 * G | Equivalent to `g', but use an uppercase `E' in exponent form.
75 *
76 * Field | Other Format
77 * ------+--------------------------------------------------------------
78 * c | Argument is the numeric code for a single character or
79 * | a single character string itself.
80 * p | The valuing of argument.inspect.
81 * s | Argument is a string to be substituted. If the format
82 * | sequence contains a precision, at most that many characters
83 * | will be copied.
84 *
85 * The flags modifies the behavior of the formats.
86 * The flag characters are:
87 *
88 * Flag | Applies to | Meaning
89 * ---------+---------------+-----------------------------------------
90 * space | bBdiouxX | Leave a space at the start of
91 * | eEfgG | non-negative numbers.
92 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
93 * | | a minus sign with absolute value for
94 * | | negative values.
95 * ---------+---------------+-----------------------------------------
96 * (digit)$ | all | Specifies the absolute argument number
97 * | | for this field. Absolute and relative
98 * | | argument numbers cannot be mixed in a
99 * | | sprintf string.
100 * ---------+---------------+-----------------------------------------
101 * # | bBoxX | Use an alternative format.
102 * | eEfgG | For the conversions `o', increase the precision
103 * | | until the first digit will be `0' if
104 * | | it is not formatted as complements.
105 * | | For the conversions `x', `X', `b' and `B'
106 * | | on non-zero, prefix the result with ``0x'',
107 * | | ``0X'', ``0b'' and ``0B'', respectively.
108 * | | For `e', `E', `f', `g', and 'G',
109 * | | force a decimal point to be added,
110 * | | even if no digits follow.
111 * | | For `g' and 'G', do not remove trailing zeros.
112 * ---------+---------------+-----------------------------------------
113 * + | bBdiouxX | Add a leading plus sign to non-negative
114 * | eEfgG | numbers.
115 * | (numeric fmt) | For `o', `x', `X', `b' and `B', use
116 * | | a minus sign with absolute value for
117 * | | negative values.
118 * ---------+---------------+-----------------------------------------
119 * - | all | Left-justify the result of this conversion.
120 * ---------+---------------+-----------------------------------------
121 * 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
122 * | eEfgG | For `o', `x', `X', `b' and `B', radix-1
123 * | (numeric fmt) | is used for negative numbers formatted as
124 * | | complements.
125 * ---------+---------------+-----------------------------------------
126 * * | all | Use the next argument as the field width.
127 * | | If negative, left-justify the result. If the
128 * | | asterisk is followed by a number and a dollar
129 * | | sign, use the indicated argument as the width.
130 *
131 * Examples of flags:
132 *
133 * # `+' and space flag specifies the sign of non-negative numbers.
134 * sprintf("%d", 123) #=> "123"
135 * sprintf("%+d", 123) #=> "+123"
136 * sprintf("% d", 123) #=> " 123"
137 *
138 * # `#' flag for `o' increases number of digits to show `0'.
139 * # `+' and space flag changes format of negative numbers.
140 * sprintf("%o", 123) #=> "173"
141 * sprintf("%#o", 123) #=> "0173"
142 * sprintf("%+o", -123) #=> "-173"
143 * sprintf("%o", -123) #=> "..7605"
144 * sprintf("%#o", -123) #=> "..7605"
145 *
146 * # `#' flag for `x' add a prefix `0x' for non-zero numbers.
147 * # `+' and space flag disables complements for negative numbers.
148 * sprintf("%x", 123) #=> "7b"
149 * sprintf("%#x", 123) #=> "0x7b"
150 * sprintf("%+x", -123) #=> "-7b"
151 * sprintf("%x", -123) #=> "..f85"
152 * sprintf("%#x", -123) #=> "0x..f85"
153 * sprintf("%#x", 0) #=> "0"
154 *
155 * # `#' for `X' uses the prefix `0X'.
156 * sprintf("%X", 123) #=> "7B"
157 * sprintf("%#X", 123) #=> "0X7B"
158 *
159 * # `#' flag for `b' add a prefix `0b' for non-zero numbers.
160 * # `+' and space flag disables complements for negative numbers.
161 * sprintf("%b", 123) #=> "1111011"
162 * sprintf("%#b", 123) #=> "0b1111011"
163 * sprintf("%+b", -123) #=> "-1111011"
164 * sprintf("%b", -123) #=> "..10000101"
165 * sprintf("%#b", -123) #=> "0b..10000101"
166 * sprintf("%#b", 0) #=> "0"
167 *
168 * # `#' for `B' uses the prefix `0B'.
169 * sprintf("%B", 123) #=> "1111011"
170 * sprintf("%#B", 123) #=> "0B1111011"
171 *
172 * # `#' for `e' forces to show the decimal point.
173 * sprintf("%.0e", 1) #=> "1e+00"
174 * sprintf("%#.0e", 1) #=> "1.e+00"
175 *
176 * # `#' for `f' forces to show the decimal point.
177 * sprintf("%.0f", 1234) #=> "1234"
178 * sprintf("%#.0f", 1234) #=> "1234."
179 *
180 * # `#' for `g' forces to show the decimal point.
181 * # It also disables stripping lowest zeros.
182 * sprintf("%g", 123.4) #=> "123.4"
183 * sprintf("%#g", 123.4) #=> "123.400"
184 * sprintf("%g", 123456) #=> "123456"
185 * sprintf("%#g", 123456) #=> "123456."
186 *
187 * The field width is an optional integer, followed optionally by a
188 * period and a precision. The width specifies the minimum number of
189 * characters that will be written to the result for this field.
190 *
191 * Examples of width:
192 *
193 * # padding is done by spaces, width=20
194 * # 0 or radix-1. <------------------>
195 * sprintf("%20d", 123) #=> " 123"
196 * sprintf("%+20d", 123) #=> " +123"
197 * sprintf("%020d", 123) #=> "00000000000000000123"
198 * sprintf("%+020d", 123) #=> "+0000000000000000123"
199 * sprintf("% 020d", 123) #=> " 0000000000000000123"
200 * sprintf("%-20d", 123) #=> "123 "
201 * sprintf("%-+20d", 123) #=> "+123 "
202 * sprintf("%- 20d", 123) #=> " 123 "
203 * sprintf("%020x", -123) #=> "..ffffffffffffffff85"
204 *
205 * For
206 * numeric fields, the precision controls the number of decimal places
207 * displayed. For string fields, the precision determines the maximum
208 * number of characters to be copied from the string. (Thus, the format
209 * sequence <code>%10.10s</code> will always contribute exactly ten
210 * characters to the result.)
211 *
212 * Examples of precisions:
213 *
214 * # precision for `d', 'o', 'x' and 'b' is
215 * # minimum number of digits <------>
216 * sprintf("%20.8d", 123) #=> " 00000123"
217 * sprintf("%20.8o", 123) #=> " 00000173"
218 * sprintf("%20.8x", 123) #=> " 0000007b"
219 * sprintf("%20.8b", 123) #=> " 01111011"
220 * sprintf("%20.8d", -123) #=> " -00000123"
221 * sprintf("%20.8o", -123) #=> " ..777605"
222 * sprintf("%20.8x", -123) #=> " ..ffff85"
223 * sprintf("%20.8b", -11) #=> " ..110101"
224 *
225 * # "0x" and "0b" for `#x' and `#b' is not counted for
226 * # precision but "0" for `#o' is counted. <------>
227 * sprintf("%#20.8d", 123) #=> " 00000123"
228 * sprintf("%#20.8o", 123) #=> " 00000173"
229 * sprintf("%#20.8x", 123) #=> " 0x0000007b"
230 * sprintf("%#20.8b", 123) #=> " 0b01111011"
231 * sprintf("%#20.8d", -123) #=> " -00000123"
232 * sprintf("%#20.8o", -123) #=> " ..777605"
233 * sprintf("%#20.8x", -123) #=> " 0x..ffff85"
234 * sprintf("%#20.8b", -11) #=> " 0b..110101"
235 *
236 * # precision for `e' is number of
237 * # digits after the decimal point <------>
238 * sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
239 *
240 * # precision for `f' is number of
241 * # digits after the decimal point <------>
242 * sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
243 *
244 * # precision for `g' is number of
245 * # significant digits <------->
246 * sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
247 *
248 * # <------->
249 * sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
250 *
251 * # precision for `s' is
252 * # maximum number of characters <------>
253 * sprintf("%20.8s", "string test") #=> " string t"
254 *
255 * Examples:
256 *
257 * sprintf("%d %04x", 123, 123) #=> "123 007b"
258 * sprintf("%08b '%4s'", 123, 123) #=> "01111011 ' 123'"
259 * sprintf("%1$*2$s %2$d %1$s", "hello", 8) #=> " hello 8 hello"
260 * sprintf("%1$*2$s %2$d", "hello", -8) #=> "hello -8"
261 * sprintf("%+g:% g:%-g", 1.23, 1.23, 1.23) #=> "+1.23: 1.23:1.23"
262 * sprintf("%u", -123) #=> "-123"
263 */
264
265 #define GETNTHARG(nth) \
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
266 ((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : \
267 argv[nth])
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
268
269 VALUE
270 rb_f_sprintf_imp(VALUE recv, SEL sel, int argc, VALUE *argv)
271 {
272 return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
273 }
274
275 VALUE
276 rb_f_sprintf(int argc, const VALUE *argv)
277 {
278 return rb_str_format(argc - 1, argv + 1, GETNTHARG(0));
279 }
280
281 VALUE
282 rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
283 {
284 char buffer[512];
285 int n;
286 n = vsnprintf(buffer, sizeof buffer, fmt, ap);
287 return rb_enc_str_new(buffer, n, enc);
288 }
289
290 VALUE
291 rb_enc_sprintf(rb_encoding *enc, const char *format, ...)
292 {
293 va_list ap;
294 va_start(ap, format);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
295 VALUE result = rb_enc_vsprintf(enc, format, ap);
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
296 va_end(ap);
297 return result;
298 }
299
300 VALUE
301 rb_vsprintf(const char *fmt, va_list ap)
302 {
303 return rb_enc_vsprintf(NULL, fmt, ap);
304 }
305
306 VALUE
307 rb_sprintf(const char *format, ...)
308 {
309 va_list ap;
310 va_start(ap, format);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
311 VALUE result = rb_vsprintf(format, ap);
9c1d230 committing experimental branch content
Laurent Sansonetti authored Mar 11, 2009
312 va_end(ap);
313 return result;
314 }
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
315
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
316 #define IS_NEG(num) RBIGNUM_NEGATIVE_P(num)
317 #define REL_REF 1
318 #define ABS_REF 2
319 #define NAMED_REF 3
320
321 #define REF_NAME(type) \
322 ((type) == REL_REF ? "relative" : (type) == ABS_REF ? "absolute" : "named")
323
324 #define SET_REF_TYPE(type) \
325 if (ref_type != 0 && (type) != ref_type) { \
326 rb_raise(rb_eArgError, "can't mix %s references with %s references", \
327 REF_NAME(type), REF_NAME(ref_type)); \
328 } \
329 ref_type = (type);
330
331 #define GET_ARG() \
332 if (arg == 0) { \
333 SET_REF_TYPE(REL_REF); \
334 arg = GETNTHARG(j); \
335 j++; \
336 }
337
338 #define isprenum(ch) ((ch) == '-' || (ch) == ' ' || (ch) == '+')
339
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
340 static void
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
341 pad_format_value(VALUE arg, long start, long width, VALUE pad)
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
342 {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
343 const long slen = rb_str_chars_len(arg);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
344 if (width <= slen) {
345 return;
346 }
347 if (start < 0) {
348 start += slen + 1;
349 }
350 width -= slen;
351 do {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
352 rb_str_update(arg, start, 0, pad);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
353 }
354 while (--width > 0);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
355 }
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
356
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
357 static long
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
358 cstr_update(UChar **str, long *str_len, long start, long num, VALUE replace)
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
359 {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
360 const long len = *str_len;
361 long replace_len = replace == 0 ? 0 : rb_str_chars_len(replace);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
362 if (start + num > len) {
363 num = len - start;
364 }
365 if (replace_len >= num) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
366 *str_len = len + replace_len - num;
367 *str = (UChar *)xrealloc(*str,
368 sizeof(UChar) * (len + replace_len - num));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
369 }
370 if (replace_len != num) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
371 bcopy(*str + start + num, *str + start + replace_len,
372 sizeof(UChar) * (len - start - num));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
373 }
374 if (replace_len > 0) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
375 UChar *replace_chars = NULL;
376 bool need_free = false;
377 rb_str_get_uchars(replace, &replace_chars, &replace_len, &need_free);
378 assert(replace_len > 0);
379 bcopy(replace_chars, *str + start, sizeof(UChar) * replace_len);
380 if (need_free) {
381 free(replace_chars);
382 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
383 }
384 return replace_len - num;
385 }
386
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
387 static VALUE
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
388 get_named_arg(UChar *format_str, long format_len, long *i, VALUE hash)
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
389 {
390 if (TYPE(hash) != T_HASH) {
391 rb_raise(rb_eArgError,
392 "hash required for named references");
393 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
394 UChar closing = format_str[(*i)++] + 2;
395 UChar *str_ptr = &format_str[*i];
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
396 while (*i < format_len && format_str[*i] != closing) {
397 (*i)++;
398 }
399 if (*i == format_len) {
400 rb_raise(rb_eArgError,
401 "malformed name - unmatched parenthesis");
402 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
403 VALUE substr = rb_unicode_str_new(str_ptr, str_ptr - format_str);
404 hash = rb_hash_aref(hash, ID2SYM(rb_intern_str(substr)));
405 return hash;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
406 }
407
408 // XXX look for arguments that are altered but not duped
409 VALUE
410 rb_str_format(int argc, const VALUE *argv, VALUE fmt)
411 {
412 bool tainted = OBJ_TAINTED(fmt);
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
413
414 UChar *format_str = NULL;
415 long format_len = 0;
416 bool need_free = false;
417 rb_str_get_uchars(fmt, &format_str, &format_len, &need_free);
418 if (format_len == 0) {
419 goto bail;
420 }
421 UChar *tmp = (UChar *)xmalloc(format_len * sizeof(UChar));
422 memcpy(tmp, format_str, format_len * sizeof(UChar));
423 if (need_free) {
424 free(format_str);
425 }
426 format_str = tmp;
427
428 long num, pos;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
429 int j = 0;
430 int ref_type = 0;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
431 long format_str_capa = format_len;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
432
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
433 for (long i = 0; i < format_len; i++) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
434 if (format_str[i] != '%') {
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
435 continue;
436 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
437 if (format_str[i + 1] == '%') {
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored Mar 19, 2010
438 num = cstr_update(&format_str, &format_str_capa, i, 1, 0);
439 format_len += num;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
440 continue;
441 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
442
443 bool sharp_flag = false;
444 bool space_flag = false;
445 bool plus_flag = false;
446 bool minus_flag = false;
447 bool zero_flag = false;
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored Nov 23, 2010
448 bool width_flag = false;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
449 bool precision_flag = false;
450 bool complete = false;
451 VALUE arg = 0;
452 long width = 0;
453 long precision = 0;
454 int base = 0;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
455 VALUE negative_pad = 0;
456 VALUE sharp_pad = rb_str_new2("");
457 const long start = i;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
458
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored Nov 23, 2010
459 #define CHECK_FOR_WIDTH() \
460 if (width_flag) { \
461 rb_raise(rb_eArgError, "width given twice"); \
462 }
463
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
464 while (i++ < format_len) {
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
465 switch (format_str[i]) {
466 case '#':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
467 sharp_flag = true;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
468 break;
469
470 case '*':
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored Nov 23, 2010
471 CHECK_FOR_WIDTH();
472 width_flag = true;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
473 if (format_str[++i] == '<' || format_str[i] == '{') {
474 SET_REF_TYPE(NAMED_REF);
475 width = NUM2LONG(rb_Integer(get_named_arg(format_str,
476 format_len, &i, GETNTHARG(0))));
477 }
478 else {
479 if (isprenum(format_str[i])) {
480 i--;
481 break;
482 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
483
484 num = rb_uchar_strtol(format_str, format_len, i, &pos);
485 if (pos == i--) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
486 SET_REF_TYPE(REL_REF);
487 width = NUM2LONG(rb_Integer(GETNTHARG(j)));
488 j++;
489 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
490 else if (format_str[pos] == '$') {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
491 SET_REF_TYPE(ABS_REF);
492 width = NUM2LONG(rb_Integer(GETNTHARG(num - 1)));
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
493 i = pos;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
494 }
495 }
496 if (width < 0) {
497 minus_flag = true;
498 width = -width;
499 }
500 break;
501
502 case ' ':
503 if (!plus_flag) {
504 space_flag = true;
505 }
506 break;
507
508 case '+':
509 plus_flag = true;
510 space_flag = false;
511 break;
512
513 case '-':
514 zero_flag = false;
515 minus_flag = true;
516 break;
517
518 case '0':
519 if (!precision_flag && !minus_flag) {
520 zero_flag = true;
521 }
522 break;
523
524 case '1':
525 case '2':
526 case '3':
527 case '4':
528 case '5':
529 case '6':
530 case '7':
531 case '8':
532 case '9':
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
533 num = rb_uchar_strtol(format_str, format_len, i, &pos);
534 i = pos;
535 if (format_str[pos] == '$') {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
536 if (num == 0) {
537 rb_raise(rb_eArgError, "invalid absolute argument");
538 }
539 SET_REF_TYPE(ABS_REF);
540 arg = GETNTHARG(num - 1);
541 }
542 else {
543 SET_REF_TYPE(REL_REF);
544 width = num;
545 i--;
42f22c9 @Watson1978 sprintf() will throw an exception when was given width format twice.
Watson1978 authored Nov 23, 2010
546 CHECK_FOR_WIDTH();
547 width_flag = true;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
548 }
549 break;
550
551 case '.':
552 zero_flag = false;
553 precision_flag = true;
554 if (format_str[++i] == '*') {
555 if (format_str[++i] == '<' || format_str[i] == '{') {
556 SET_REF_TYPE(NAMED_REF);
557 precision = NUM2LONG(rb_Integer(get_named_arg(
558 format_str, format_len, &i, GETNTHARG(0))));
559 }
560 else {
561 if (isprenum(format_str[i])) {
562 i--;
563 break;
564 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
565
566 num = rb_uchar_strtol(format_str, format_len,
567 i, &pos);
568 if (num == i--) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
569 SET_REF_TYPE(REL_REF);
570 precision = NUM2LONG(rb_Integer(GETNTHARG(j)));
571 j++;
572 }
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
573 else if (format_str[pos] == '$') {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
574 SET_REF_TYPE(ABS_REF);
575 precision = NUM2LONG(rb_Integer(GETNTHARG(
576 num - 1)));
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
577 i = pos;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
578 }
579 }
580 }
581 else if (isdigit(format_str[i])) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
582 precision = rb_uchar_strtol(format_str, format_len,
583 i, &pos);
584 i = pos - 1;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
585 }
586 else {
587 rb_raise(rb_eArgError, "invalid precision");
588 }
589
590 if (precision < 0) {
591 precision = 0;
592 }
593 break;
594
595 case '<':
596 case '{':
597 SET_REF_TYPE(NAMED_REF);
598 arg = get_named_arg(format_str, format_len, &i,
599 GETNTHARG(0));
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
600 break;
601
602 case 'd':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
603 case 'D':
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
604 case 'i':
605 case 'u':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
606 case 'U':
607 base = 10;
608 complete = true;
609 break;
610
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
611 case 'x':
612 case 'X':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
613 base = 16;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
614 negative_pad = rb_str_new2("f");
615 sharp_pad = rb_str_new2("0x");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
616 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
617 break;
618
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
619 case 'o':
620 case 'O':
621 base = 8;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
622 negative_pad = rb_str_new2("7");
623 sharp_pad = rb_str_new2("0");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
624 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
625 break;
626
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
627 case 'B':
628 case 'b':
629 base = 2;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
630 negative_pad = rb_str_new2("1");
631 sharp_pad = rb_str_new2("0b");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
632 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
633 break;
634
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
635 case 'c':
636 case 'C':
637 GET_ARG();
638 if (TYPE(arg) == T_STRING) {
639 arg = rb_str_substr(arg, 0, 1);
640 }
641 else {
110e345 fixed some bugs in Numeric#chr
Laurent Sansonetti authored Mar 18, 2010
642 long num = NUM2LONG(arg);
643 if (num < 0 || i > 0xff) {
644 rb_raise(rb_eRangeError, "%ld out of char range",
645 num);
646 }
647 char c = (char)num;
648 arg = rb_str_new(&c, 1);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
649 }
650 complete = true;
651 break;
652
653 case 'f':
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
654 case 'F':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
655 case 'e':
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
656 case 'E':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
657 case 'g':
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
658 case 'G':
659 case 'a':
660 case 'A':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
661 {
662 // here we construct a new format str and then use
663 // c's sprintf. why? because floats are retarded
664 GET_ARG();
665 double value = RFLOAT_VALUE(rb_Float(arg));
666 complete = true;
667
668 if (isnan(value) || isinf(value)) {
669 arg = rb_str_new2((char *)(isnan(value) ? "NaN" :
670 value < 0 ? "-Inf" : "Inf"));
671 if (isnan(value) || value > 0) {
672 if (plus_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
673 rb_str_update(arg, 0, 0, rb_str_new2("+"));
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
674 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
675 else if (space_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
676 rb_str_update(arg, 0, 0, rb_str_new2(" "));
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
677 }
678 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
679 break;
680 }
681
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
682 arg = rb_unicode_str_new(&format_str[i], 1);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
683 if (precision_flag) {
684 rb_str_update(arg, 0, 0, rb_big2str(LONG2NUM(precision),
685 10));
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
686 rb_str_update(arg, 0, 0, rb_str_new2("."));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
687 }
688 rb_str_update(arg, 0, 0, rb_big2str(LONG2NUM(width), 10));
689 if (minus_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
690 rb_str_update(arg, 0, 0, rb_str_new2("-"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
691 }
692 else if (zero_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
693 rb_str_update(arg, 0, 0, rb_str_new2("0"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
694 }
695 if (plus_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
696 rb_str_update(arg, 0, 0, rb_str_new2("+"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
697 }
698 else if (space_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
699 rb_str_update(arg, 0, 0, rb_str_new2(" "));
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
700 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
701 if (sharp_flag) {
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
702 rb_str_update(arg, 0, 0, rb_str_new2("#"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
703 }
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
704 rb_str_update(arg, 0, 0, rb_str_new2("%"));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
705
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
706 char *ptr;
707 asprintf(&ptr, RSTRING_PTR(arg), value);
708 arg = rb_str_new2(ptr);
709 free(ptr);
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
710 break;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
711 }
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
712
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
713 case 's':
714 case 'S':
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
715 case 'p':
716 case '@':
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
717 GET_ARG();
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
718 arg = (tolower(format_str[i]) != 's'
719 ? rb_inspect(arg) : TYPE(arg) == T_STRING
720 ? rb_str_new3(arg) : rb_obj_as_string(arg));
721 if (precision_flag && precision < rb_str_chars_len(arg)) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
722 CFStringPad((CFMutableStringRef)arg, NULL, precision,
723 0);
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
724 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
725 complete = true;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
726 break;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
727
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored Nov 22, 2010
728 case '\n':
729 case '\0':
730 if (format_str[i - 1] == '%') {
421ab55 @Watson1978 sprintf() will not throw exception when passed the format of single %…
Watson1978 authored Nov 22, 2010
731 if (format_str[i] == '\n') {
732 arg = rb_str_new("%\n", 2);
733 }
734 else {
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored Nov 22, 2010
735 if (format_len > i) {
736 arg = rb_str_new("%\0", 2);
737 }
738 else {
739 arg = rb_str_new("%", 1);
740 }
421ab55 @Watson1978 sprintf() will not throw exception when passed the format of single %…
Watson1978 authored Nov 22, 2010
741 }
742 complete = true;
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored Nov 22, 2010
743 break;
421ab55 @Watson1978 sprintf() will not throw exception when passed the format of single %…
Watson1978 authored Nov 22, 2010
744 }
b62b438 @Watson1978 modified the style of r4928.
Watson1978 authored Nov 22, 2010
745 rb_raise(rb_eArgError, "malformed format string - %%%c",
746 format_str[i]);
747 break;
748
749 default:
750 rb_raise(rb_eArgError, "malformed format string - %%%c",
751 format_str[i]);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
752 }
753 if (!complete) {
754 continue;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
755 }
756
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
757 GET_ARG();
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
758
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
759 if (base != 0) {
760 bool sign_pad = false;
761 unsigned long num_index = 0;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
762 VALUE zero_pad = rb_str_new2("0");
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
763
764 VALUE num = rb_Integer(arg);
765 if (TYPE(num) == T_FIXNUM) {
766 num = rb_int2big(FIX2LONG(num));
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
767 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
768 if (plus_flag || space_flag) {
769 sign_pad = 1;
770 }
771 if (IS_NEG(num)) {
772 num_index = 1;
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
773 if (!sign_pad && negative_pad != 0) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
774 zero_pad = negative_pad;
775 num = rb_big_clone(num);
776 rb_big_2comp(num);
777 }
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
778 }
779
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
780 arg = rb_big2str(num, base);
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
781 if (!sign_pad && IS_NEG(num) && negative_pad != 0) {
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored Mar 19, 2010
782 UChar neg = rb_str_get_uchar(negative_pad, 0);
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
783 if (base == 8) {
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored Mar 19, 2010
784 UChar c = rb_str_get_uchar(arg, 1);
785 const long len = rb_str_chars_len(arg) - 1;
786 c |= ((~0 << 3) >> ((3 * len)
787 % (sizeof(BDIGIT) * 8))) & ~(~0 << 3);
788 rb_str_update(arg, 1, 1, rb_unicode_str_new(&c, 1));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
789 }
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored Mar 19, 2010
790 for (int i = 1, count = rb_str_chars_len(arg); i < count;
791 i++) {
792 if (rb_str_get_uchar(arg, i) != neg) {
793 break;
794 }
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
795 num_index++;
796 }
a539763 fixed a few bugs in #sprintf
Laurent Sansonetti authored Mar 19, 2010
797 rb_str_update(arg, 0, num_index, negative_pad);
798 rb_str_update(arg, 0, 0, rb_str_new2(".."));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
799 num_index = 2;
800 }
801 if (precision_flag) {
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
802 pad_format_value(arg, num_index,
803 precision + (IS_NEG(num)
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
804 && (sign_pad || negative_pad == 0) ? 1 : 0),
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
805 zero_pad);
806 }
e9d7b0c sprintf can now be free of C++ evil
Laurent Sansonetti authored Feb 11, 2010
807 if (sharp_flag && rb_cmpint(num, Qfalse, Qfalse) != 0) {
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
808 rb_str_update(arg, sign_pad, 0, (VALUE)sharp_pad);
809 num_index += 2;
810 }
811 if (sign_pad && RBIGNUM_POSITIVE_P(num)) {
812 rb_str_update(arg, 0, 0, (VALUE)(plus_flag ?
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
813 rb_str_new2("+") : rb_str_new2(" ")));
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
814 num_index++;
815 }
816 if (zero_flag) {
817 pad_format_value(arg, num_index, width, zero_pad);
818 }
819 if (ISUPPER(format_str[i])) {
820 CFStringUppercase((CFMutableStringRef)arg, NULL);
821 }
822 }
823
824 if (OBJ_TAINTED(arg)) {
825 tainted = true;
826 }
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
827
d6e38f5 #sprintf: don't try to mutate symbols
Laurent Sansonetti authored Aug 30, 2010
828 if (TYPE(arg) == T_SYMBOL) {
829 // Because symbols are not mutable and pad_format_value()
830 // mutates its first argument.
831 arg = rb_sym_to_s(arg);
832 }
87717e7 some sprintf fixes
Laurent Sansonetti authored Mar 6, 2010
833 pad_format_value(arg, minus_flag ? -1 : 0, width, rb_str_new2(" "));
834 num = cstr_update(&format_str, &format_str_capa, start,
835 i - start + 1, arg);
836 format_len += num;
77a4b42 new sprintf implementation (thanks Daniel Cavanagh)
Laurent Sansonetti authored Feb 11, 2010
837 i += num;
838 break;
839 }
840 }
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
841
4cecb13 unicode string formats (a work in progress)
Laurent Sansonetti authored Mar 2, 2010
842 bail:
843 fmt = rb_unicode_str_new(format_str, format_len);
844 if (tainted) {
845 OBJ_TAINT(fmt);
846 }
847 return fmt;
cb65416 the great schism, part I
Laurent Sansonetti authored May 23, 2009
848 }
Something went wrong with that request. Please try again.