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