1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Stig S�ther Bakken <ssb@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21 #include <math.h> /* modf() */
22 #include "php.h"
23 #include "ext/standard/head.h"
24 #include "php_string.h"
25 #include "zend_execute.h"
26 #include <stdio.h>
27
28 #ifdef HAVE_LOCALE_H
29 #include <locale.h>
30 #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
31 #else
32 #define LCONV_DECIMAL_POINT '.'
33 #endif
34
35 #define ALIGN_LEFT 0
36 #define ALIGN_RIGHT 1
37 #define ADJ_WIDTH 1
38 #define ADJ_PRECISION 2
39 #define NUM_BUF_SIZE 500
40 #define NDIG 80
41 #define FLOAT_DIGITS 6
42 #define FLOAT_PRECISION 6
43 #define MAX_FLOAT_DIGITS 38
44 #define MAX_FLOAT_PRECISION 53
45
46 #if 0
47 /* trick to control varargs functions through cpp */
48 # define PRINTF_DEBUG(arg) php_printf arg
49 #else
50 # define PRINTF_DEBUG(arg)
51 #endif
52
53 static char hexchars[] = "0123456789abcdef";
54 static char HEXCHARS[] = "0123456789ABCDEF";
55
56 /* php_spintf_appendchar() {{{ */
57 inline static void
php_sprintf_appendchar(char ** buffer,int * pos,int * size,char add TSRMLS_DC)58 php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
59 {
60 if ((*pos + 1) >= *size) {
61 *size <<= 1;
62 PRINTF_DEBUG(("%s(): ereallocing buffer to %d bytes\n", get_active_function_name(TSRMLS_C), *size));
63 *buffer = erealloc(*buffer, *size);
64 }
65 PRINTF_DEBUG(("sprintf: appending '%c', pos=\n", add, *pos));
66 (*buffer)[(*pos)++] = add;
67 }
68 /* }}} */
69
70 /* php_spintf_appendstring() {{{ */
71 inline static void
php_sprintf_appendstring(char ** buffer,int * pos,int * size,char * add,int min_width,int max_width,char padding,int alignment,int len,int neg,int expprec,int always_sign)72 php_sprintf_appendstring(char **buffer, int *pos, int *size, char *add,
73 int min_width, int max_width, char padding,
74 int alignment, int len, int neg, int expprec, int always_sign)
75 {
76 register int npad;
77 int req_size;
78 int copy_len;
79 int m_width;
80
81 copy_len = (expprec ? MIN(max_width, len) : len);
82 npad = min_width - copy_len;
83
84 if (npad < 0) {
85 npad = 0;
86 }
87
88 PRINTF_DEBUG(("sprintf: appendstring(%x, %d, %d, \"%s\", %d, '%c', %d)\n",
89 *buffer, *pos, *size, add, min_width, padding, alignment));
90 m_width = MAX(min_width, copy_len);
91
92 if(m_width > INT_MAX - *pos - 1) {
93 zend_error_noreturn(E_ERROR, "Field width %d is too long", m_width);
94 }
95
96 req_size = *pos + m_width + 1;
97
98 if (req_size > *size) {
99 while (req_size > *size) {
100 if(*size > INT_MAX/2) {
101 zend_error_noreturn(E_ERROR, "Field width %d is too long", req_size);
102 }
103 *size <<= 1;
104 }
105 PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", *size));
106 *buffer = erealloc(*buffer, *size);
107 }
108 if (alignment == ALIGN_RIGHT) {
109 if ((neg || always_sign) && padding=='0') {
110 (*buffer)[(*pos)++] = (neg) ? '-' : '+';
111 add++;
112 len--;
113 copy_len--;
114 }
115 while (npad-- > 0) {
116 (*buffer)[(*pos)++] = padding;
117 }
118 }
119 PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
120 memcpy(&(*buffer)[*pos], add, copy_len + 1);
121 *pos += copy_len;
122 if (alignment == ALIGN_LEFT) {
123 while (npad--) {
124 (*buffer)[(*pos)++] = padding;
125 }
126 }
127 }
128 /* }}} */
129
130 /* php_spintf_appendint() {{{ */
131 inline static void
php_sprintf_appendint(char ** buffer,int * pos,int * size,long number,int width,char padding,int alignment,int always_sign)132 php_sprintf_appendint(char **buffer, int *pos, int *size, long number,
133 int width, char padding, int alignment,
134 int always_sign)
135 {
136 char numbuf[NUM_BUF_SIZE];
137 register unsigned long magn, nmagn;
138 register unsigned int i = NUM_BUF_SIZE - 1, neg = 0;
139
140 PRINTF_DEBUG(("sprintf: appendint(%x, %x, %x, %d, %d, '%c', %d)\n",
141 *buffer, pos, size, number, width, padding, alignment));
142 if (number < 0) {
143 neg = 1;
144 magn = ((unsigned long) -(number + 1)) + 1;
145 } else {
146 magn = (unsigned long) number;
147 }
148
149 /* Can't right-pad 0's on integers */
150 if(alignment==0 && padding=='0') padding=' ';
151
152 numbuf[i] = '\0';
153
154 do {
155 nmagn = magn / 10;
156
157 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
158 magn = nmagn;
159 }
160 while (magn > 0 && i > 0);
161 if (neg) {
162 numbuf[--i] = '-';
163 } else if (always_sign) {
164 numbuf[--i] = '+';
165 }
166 PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n",
167 number, &numbuf[i], i));
168 php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
169 padding, alignment, (NUM_BUF_SIZE - 1) - i,
170 neg, 0, always_sign);
171 }
172 /* }}} */
173
174 /* php_spintf_appenduint() {{{ */
175 inline static void
php_sprintf_appenduint(char ** buffer,int * pos,int * size,unsigned long number,int width,char padding,int alignment)176 php_sprintf_appenduint(char **buffer, int *pos, int *size,
177 unsigned long number,
178 int width, char padding, int alignment)
179 {
180 char numbuf[NUM_BUF_SIZE];
181 register unsigned long magn, nmagn;
182 register unsigned int i = NUM_BUF_SIZE - 1;
183
184 PRINTF_DEBUG(("sprintf: appenduint(%x, %x, %x, %d, %d, '%c', %d)\n",
185 *buffer, pos, size, number, width, padding, alignment));
186 magn = (unsigned long) number;
187
188 /* Can't right-pad 0's on integers */
189 if (alignment == 0 && padding == '0') padding = ' ';
190
191 numbuf[i] = '\0';
192
193 do {
194 nmagn = magn / 10;
195
196 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
197 magn = nmagn;
198 } while (magn > 0 && i > 0);
199
200 PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
201 php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
202 padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
203 }
204 /* }}} */
205
206 /* php_spintf_appenddouble() {{{ */
207 inline static void
php_sprintf_appenddouble(char ** buffer,int * pos,int * size,double number,int width,char padding,int alignment,int precision,int adjust,char fmt,int always_sign TSRMLS_DC)208 php_sprintf_appenddouble(char **buffer, int *pos,
209 int *size, double number,
210 int width, char padding,
211 int alignment, int precision,
212 int adjust, char fmt,
213 int always_sign
214 TSRMLS_DC)
215 {
216 char num_buf[NUM_BUF_SIZE];
217 char *s = NULL;
218 int s_len = 0, is_negative = 0;
219 #ifdef HAVE_LOCALE_H
220 struct lconv *lconv;
221 #endif
222
223 PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
224 *buffer, pos, size, number, width, padding, alignment, fmt));
225 if ((adjust & ADJ_PRECISION) == 0) {
226 precision = FLOAT_PRECISION;
227 } else if (precision > MAX_FLOAT_PRECISION) {
228 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Requested precision of %d digits was truncated to PHP maximum of %d digits", precision, MAX_FLOAT_PRECISION);
229 precision = MAX_FLOAT_PRECISION;
230 }
231
232 if (zend_isnan(number)) {
233 is_negative = (number<0);
234 php_sprintf_appendstring(buffer, pos, size, "NaN", 3, 0, padding,
235 alignment, 3, is_negative, 0, always_sign);
236 return;
237 }
238
239 if (zend_isinf(number)) {
240 is_negative = (number<0);
241 php_sprintf_appendstring(buffer, pos, size, "INF", 3, 0, padding,
242 alignment, 3, is_negative, 0, always_sign);
243 return;
244 }
245
246 switch (fmt) {
247 case 'e':
248 case 'E':
249 case 'f':
250 case 'F':
251 #ifdef HAVE_LOCALE_H
252 lconv = localeconv();
253 #endif
254 s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
255 (fmt == 'f')?LCONV_DECIMAL_POINT:'.',
256 &is_negative, &num_buf[1], &s_len);
257 if (is_negative) {
258 num_buf[0] = '-';
259 s = num_buf;
260 s_len++;
261 } else if (always_sign) {
262 num_buf[0] = '+';
263 s = num_buf;
264 s_len++;
265 }
266 break;
267
268 case 'g':
269 case 'G':
270 if (precision == 0)
271 precision = 1;
272 /*
273 * * We use &num_buf[ 1 ], so that we have room for the sign
274 */
275 #ifdef HAVE_LOCALE_H
276 lconv = localeconv();
277 #endif
278 s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
279 is_negative = 0;
280 if (*s == '-') {
281 is_negative = 1;
282 s = &num_buf[1];
283 } else if (always_sign) {
284 num_buf[0] = '+';
285 s = num_buf;
286 }
287
288 s_len = strlen(s);
289 break;
290 }
291
292 php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding,
293 alignment, s_len, is_negative, 0, always_sign);
294 }
295 /* }}} */
296
297 /* php_spintf_appendd2n() {{{ */
298 inline static void
php_sprintf_append2n(char ** buffer,int * pos,int * size,long number,int width,char padding,int alignment,int n,char * chartable,int expprec)299 php_sprintf_append2n(char **buffer, int *pos, int *size, long number,
300 int width, char padding, int alignment, int n,
301 char *chartable, int expprec)
302 {
303 char numbuf[NUM_BUF_SIZE];
304 register unsigned long num;
305 register unsigned int i = NUM_BUF_SIZE - 1;
306 register int andbits = (1 << n) - 1;
307
308 PRINTF_DEBUG(("sprintf: append2n(%x, %x, %x, %d, %d, '%c', %d, %d, %x)\n",
309 *buffer, pos, size, number, width, padding, alignment, n,
310 chartable));
311 PRINTF_DEBUG(("sprintf: append2n 2^%d andbits=%x\n", n, andbits));
312
313 num = (unsigned long) number;
314 numbuf[i] = '\0';
315
316 do {
317 numbuf[--i] = chartable[(num & andbits)];
318 num >>= n;
319 }
320 while (num > 0);
321
322 php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
323 padding, alignment, (NUM_BUF_SIZE - 1) - i,
324 0, expprec, 0);
325 }
326 /* }}} */
327
328 /* php_spintf_getnumber() {{{ */
329 inline static int
php_sprintf_getnumber(char * buffer,int * pos)330 php_sprintf_getnumber(char *buffer, int *pos)
331 {
332 char *endptr;
333 register long num = strtol(&buffer[*pos], &endptr, 10);
334 register int i = 0;
335
336 if (endptr != NULL) {
337 i = (endptr - &buffer[*pos]);
338 }
339 PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i));
340 *pos += i;
341
342 if (num >= INT_MAX || num < 0) {
343 return -1;
344 } else {
345 return (int) num;
346 }
347 }
348 /* }}} */
349
350 /* php_formatted_print() {{{
351 * New sprintf implementation for PHP.
352 *
353 * Modifiers:
354 *
355 * " " pad integers with spaces
356 * "-" left adjusted field
357 * n field size
358 * "."n precision (floats only)
359 * "+" Always place a sign (+ or -) in front of a number
360 *
361 * Type specifiers:
362 *
363 * "%" literal "%", modifiers are ignored.
364 * "b" integer argument is printed as binary
365 * "c" integer argument is printed as a single character
366 * "d" argument is an integer
367 * "f" the argument is a float
368 * "o" integer argument is printed as octal
369 * "s" argument is a string
370 * "x" integer argument is printed as lowercase hexadecimal
371 * "X" integer argument is printed as uppercase hexadecimal
372 *
373 */
374 static char *
php_formatted_print(int ht,int * len,int use_array,int format_offset TSRMLS_DC)375 php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC)
376 {
377 zval ***args, **z_format;
378 int argc, size = 240, inpos = 0, outpos = 0, temppos;
379 int alignment, currarg, adjusting, argnum, width, precision;
380 char *format, *result, padding;
381 int always_sign;
382 int format_len;
383
384 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
385 return NULL;
386 }
387
388 /* verify the number of args */
389 if ((use_array && argc != (2 + format_offset))
390 || (!use_array && argc < (1 + format_offset))) {
391 efree(args);
392 WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
393 }
394
395 if (use_array) {
396 int i = 1;
397 zval ***newargs;
398 zval **array;
399
400 z_format = args[format_offset];
401 array = args[1 + format_offset];
402
403 SEPARATE_ZVAL(array);
404 convert_to_array_ex(array);
405
406 argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
407 newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
408 newargs[0] = z_format;
409
410 for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
411 zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
412 zend_hash_move_forward(Z_ARRVAL_PP(array)));
413
414 efree(args);
415 args = newargs;
416 format_offset = 0;
417 }
418
419 convert_to_string_ex(args[format_offset]);
420 format = Z_STRVAL_PP(args[format_offset]);
421 format_len = Z_STRLEN_PP(args[format_offset]);
422 result = emalloc(size);
423
424 currarg = 1;
425
426 while (inpos<format_len) {
427 int expprec = 0, multiuse = 0;
428 zval *tmp;
429
430 PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
431 PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
432 if (format[inpos] != '%') {
433 php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
434 } else if (format[inpos + 1] == '%') {
435 php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
436 inpos += 2;
437 } else {
438 /* starting a new format specifier, reset variables */
439 alignment = ALIGN_RIGHT;
440 adjusting = 0;
441 padding = ' ';
442 always_sign = 0;
443 inpos++; /* skip the '%' */
444
445 PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
446 format[inpos], inpos));
447 if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
448 /* first look for argnum */
449 temppos = inpos;
450 while (isdigit((int)format[temppos])) temppos++;
451 if (format[temppos] == '$') {
452 argnum = php_sprintf_getnumber(format, &inpos);
453
454 if (argnum <= 0) {
455 efree(result);
456 efree(args);
457 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
458 return NULL;
459 }
460
461 multiuse = 1;
462 inpos++; /* skip the '$' */
463 } else {
464 argnum = currarg++;
465 }
466
467 argnum += format_offset;
468
469 /* after argnum comes modifiers */
470 PRINTF_DEBUG(("sprintf: looking for modifiers\n"
471 "sprintf: now looking at '%c', inpos=%d\n",
472 format[inpos], inpos));
473 for (;; inpos++) {
474 if (format[inpos] == ' ' || format[inpos] == '0') {
475 padding = format[inpos];
476 } else if (format[inpos] == '-') {
477 alignment = ALIGN_LEFT;
478 /* space padding, the default */
479 } else if (format[inpos] == '+') {
480 always_sign = 1;
481 } else if (format[inpos] == '\'' && inpos+1<format_len) {
482 padding = format[++inpos];
483 } else {
484 PRINTF_DEBUG(("sprintf: end of modifiers\n"));
485 break;
486 }
487 }
488 PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
489 PRINTF_DEBUG(("sprintf: alignment=%s\n",
490 (alignment == ALIGN_LEFT) ? "left" : "right"));
491
492
493 /* after modifiers comes width */
494 if (isdigit((int)format[inpos])) {
495 PRINTF_DEBUG(("sprintf: getting width\n"));
496 if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
497 efree(result);
498 efree(args);
499 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
500 return NULL;
501 }
502 adjusting |= ADJ_WIDTH;
503 } else {
504 width = 0;
505 }
506 PRINTF_DEBUG(("sprintf: width=%d\n", width));
507
508 /* after width and argnum comes precision */
509 if (format[inpos] == '.') {
510 inpos++;
511 PRINTF_DEBUG(("sprintf: getting precision\n"));
512 if (isdigit((int)format[inpos])) {
513 if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
514 efree(result);
515 efree(args);
516 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
517 return NULL;
518 }
519 adjusting |= ADJ_PRECISION;
520 expprec = 1;
521 } else {
522 precision = 0;
523 }
524 } else {
525 precision = 0;
526 }
527 PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
528 } else {
529 width = precision = 0;
530 argnum = currarg++ + format_offset;
531 }
532
533 if (argnum >= argc) {
534 efree(result);
535 efree(args);
536 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
537 return NULL;
538 }
539
540 if (format[inpos] == 'l') {
541 inpos++;
542 }
543 PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
544 /* now we expect to find a type specifier */
545 if (multiuse) {
546 MAKE_STD_ZVAL(tmp);
547 *tmp = **(args[argnum]);
548 INIT_PZVAL(tmp);
549 zval_copy_ctor(tmp);
550 } else {
551 SEPARATE_ZVAL(args[argnum]);
552 tmp = *(args[argnum]);
553 }
554
555 switch (format[inpos]) {
556 case 's': {
557 zval *var, var_copy;
558 int use_copy;
559
560 zend_make_printable_zval(tmp, &var_copy, &use_copy);
561 if (use_copy) {
562 var = &var_copy;
563 } else {
564 var = tmp;
565 }
566 php_sprintf_appendstring(&result, &outpos, &size,
567 Z_STRVAL_P(var),
568 width, precision, padding,
569 alignment,
570 Z_STRLEN_P(var),
571 0, expprec, 0);
572 if (use_copy) {
573 zval_dtor(&var_copy);
574 }
575 break;
576 }
577
578 case 'd':
579 convert_to_long(tmp);
580 php_sprintf_appendint(&result, &outpos, &size,
581 Z_LVAL_P(tmp),
582 width, padding, alignment,
583 always_sign);
584 break;
585
586 case 'u':
587 convert_to_long(tmp);
588 php_sprintf_appenduint(&result, &outpos, &size,
589 Z_LVAL_P(tmp),
590 width, padding, alignment);
591 break;
592
593 case 'g':
594 case 'G':
595 case 'e':
596 case 'E':
597 case 'f':
598 case 'F':
599 convert_to_double(tmp);
600 php_sprintf_appenddouble(&result, &outpos, &size,
601 Z_DVAL_P(tmp),
602 width, padding, alignment,
603 precision, adjusting,
604 format[inpos], always_sign
605 TSRMLS_CC);
606 break;
607
608 case 'c':
609 convert_to_long(tmp);
610 php_sprintf_appendchar(&result, &outpos, &size,
611 (char) Z_LVAL_P(tmp) TSRMLS_CC);
612 break;
613
614 case 'o':
615 convert_to_long(tmp);
616 php_sprintf_append2n(&result, &outpos, &size,
617 Z_LVAL_P(tmp),
618 width, padding, alignment, 3,
619 hexchars, expprec);
620 break;
621
622 case 'x':
623 convert_to_long(tmp);
624 php_sprintf_append2n(&result, &outpos, &size,
625 Z_LVAL_P(tmp),
626 width, padding, alignment, 4,
627 hexchars, expprec);
628 break;
629
630 case 'X':
631 convert_to_long(tmp);
632 php_sprintf_append2n(&result, &outpos, &size,
633 Z_LVAL_P(tmp),
634 width, padding, alignment, 4,
635 HEXCHARS, expprec);
636 break;
637
638 case 'b':
639 convert_to_long(tmp);
640 php_sprintf_append2n(&result, &outpos, &size,
641 Z_LVAL_P(tmp),
642 width, padding, alignment, 1,
643 hexchars, expprec);
644 break;
645
646 case '%':
647 php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
648
649 break;
650 default:
651 break;
652 }
653 if (multiuse) {
654 zval_ptr_dtor(&tmp);
655 }
656 inpos++;
657 }
658 }
659
660 efree(args);
661
662 /* possibly, we have to make sure we have room for the terminating null? */
663 result[outpos]=0;
664 *len = outpos;
665 return result;
666 }
667 /* }}} */
668
669 /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
670 Return a formatted string */
PHP_FUNCTION(user_sprintf)671 PHP_FUNCTION(user_sprintf)
672 {
673 char *result;
674 int len;
675
676 if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
677 RETURN_FALSE;
678 }
679 RETVAL_STRINGL(result, len, 0);
680 }
681 /* }}} */
682
683 /* {{{ proto string vsprintf(string format, array args)
684 Return a formatted string */
PHP_FUNCTION(vsprintf)685 PHP_FUNCTION(vsprintf)
686 {
687 char *result;
688 int len;
689
690 if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
691 RETURN_FALSE;
692 }
693 RETVAL_STRINGL(result, len, 0);
694 }
695 /* }}} */
696
697 /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
698 Output a formatted string */
PHP_FUNCTION(user_printf)699 PHP_FUNCTION(user_printf)
700 {
701 char *result;
702 int len, rlen;
703
704 if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
705 RETURN_FALSE;
706 }
707 rlen = PHPWRITE(result, len);
708 efree(result);
709 RETURN_LONG(rlen);
710 }
711 /* }}} */
712
713 /* {{{ proto int vprintf(string format, array args)
714 Output a formatted string */
PHP_FUNCTION(vprintf)715 PHP_FUNCTION(vprintf)
716 {
717 char *result;
718 int len, rlen;
719
720 if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
721 RETURN_FALSE;
722 }
723 rlen = PHPWRITE(result, len);
724 efree(result);
725 RETURN_LONG(rlen);
726 }
727 /* }}} */
728
729 /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
730 Output a formatted string into a stream */
PHP_FUNCTION(fprintf)731 PHP_FUNCTION(fprintf)
732 {
733 php_stream *stream;
734 zval *arg1;
735 char *result;
736 int len;
737
738 if (ZEND_NUM_ARGS() < 2) {
739 WRONG_PARAM_COUNT;
740 }
741
742 if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
743 RETURN_FALSE;
744 }
745
746 php_stream_from_zval(stream, &arg1);
747
748 if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) {
749 RETURN_FALSE;
750 }
751
752 php_stream_write(stream, result, len);
753
754 efree(result);
755
756 RETURN_LONG(len);
757 }
758 /* }}} */
759
760 /* {{{ proto int vfprintf(resource stream, string format, array args)
761 Output a formatted string into a stream */
PHP_FUNCTION(vfprintf)762 PHP_FUNCTION(vfprintf)
763 {
764 php_stream *stream;
765 zval *arg1;
766 char *result;
767 int len;
768
769 if (ZEND_NUM_ARGS() != 3) {
770 WRONG_PARAM_COUNT;
771 }
772
773 if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
774 RETURN_FALSE;
775 }
776
777 php_stream_from_zval(stream, &arg1);
778
779 if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) {
780 RETURN_FALSE;
781 }
782
783 php_stream_write(stream, result, len);
784
785 efree(result);
786
787 RETURN_LONG(len);
788 }
789 /* }}} */
790
791 /*
792 * Local variables:
793 * tab-width: 4
794 * c-basic-offset: 4
795 * End:
796 * vim600: sw=4 ts=4 fdm=marker
797 * vim<600: sw=4 ts=4
798 */
799