Annotation of embedaddon/php/ext/standard/formatted_print.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 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: formatted_print.c 321634 2012-01-01 13:15:04Z felipe $ */
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
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
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
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
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
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
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
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 *
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:
383: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
384: return NULL;
385: }
386:
387: /* verify the number of args */
388: if ((use_array && argc != (2 + format_offset))
389: || (!use_array && argc < (1 + format_offset))) {
390: efree(args);
391: WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
392: }
393:
394: if (use_array) {
395: int i = 1;
396: zval ***newargs;
397: zval **array;
398:
399: z_format = args[format_offset];
400: array = args[1 + format_offset];
401:
402: SEPARATE_ZVAL(array);
403: convert_to_array_ex(array);
404:
405: argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
406: newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
407: newargs[0] = z_format;
408:
409: for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
410: zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
411: zend_hash_move_forward(Z_ARRVAL_PP(array)));
412:
413: efree(args);
414: args = newargs;
415: format_offset = 0;
416: }
417:
418: convert_to_string_ex(args[format_offset]);
419: format = Z_STRVAL_PP(args[format_offset]);
420: result = emalloc(size);
421:
422: currarg = 1;
423:
424: while (inpos<Z_STRLEN_PP(args[format_offset])) {
425: int expprec = 0, multiuse = 0;
426: zval *tmp;
427:
428: PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
429: PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
430: if (format[inpos] != '%') {
431: php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
432: } else if (format[inpos + 1] == '%') {
433: php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
434: inpos += 2;
435: } else {
436: /* starting a new format specifier, reset variables */
437: alignment = ALIGN_RIGHT;
438: adjusting = 0;
439: padding = ' ';
440: always_sign = 0;
441: inpos++; /* skip the '%' */
442:
443: PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
444: format[inpos], inpos));
445: if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
446: /* first look for argnum */
447: temppos = inpos;
448: while (isdigit((int)format[temppos])) temppos++;
449: if (format[temppos] == '$') {
450: argnum = php_sprintf_getnumber(format, &inpos);
451:
452: if (argnum <= 0) {
453: efree(result);
454: efree(args);
455: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
456: return NULL;
457: }
458:
459: multiuse = 1;
460: inpos++; /* skip the '$' */
461: } else {
462: argnum = currarg++;
463: }
464:
465: argnum += format_offset;
466:
467: /* after argnum comes modifiers */
468: PRINTF_DEBUG(("sprintf: looking for modifiers\n"
469: "sprintf: now looking at '%c', inpos=%d\n",
470: format[inpos], inpos));
471: for (;; inpos++) {
472: if (format[inpos] == ' ' || format[inpos] == '0') {
473: padding = format[inpos];
474: } else if (format[inpos] == '-') {
475: alignment = ALIGN_LEFT;
476: /* space padding, the default */
477: } else if (format[inpos] == '+') {
478: always_sign = 1;
479: } else if (format[inpos] == '\'') {
480: padding = format[++inpos];
481: } else {
482: PRINTF_DEBUG(("sprintf: end of modifiers\n"));
483: break;
484: }
485: }
486: PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
487: PRINTF_DEBUG(("sprintf: alignment=%s\n",
488: (alignment == ALIGN_LEFT) ? "left" : "right"));
489:
490:
491: /* after modifiers comes width */
492: if (isdigit((int)format[inpos])) {
493: PRINTF_DEBUG(("sprintf: getting width\n"));
494: if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
495: efree(result);
496: efree(args);
497: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
498: return NULL;
499: }
500: adjusting |= ADJ_WIDTH;
501: } else {
502: width = 0;
503: }
504: PRINTF_DEBUG(("sprintf: width=%d\n", width));
505:
506: /* after width and argnum comes precision */
507: if (format[inpos] == '.') {
508: inpos++;
509: PRINTF_DEBUG(("sprintf: getting precision\n"));
510: if (isdigit((int)format[inpos])) {
511: if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
512: efree(result);
513: efree(args);
514: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
515: return NULL;
516: }
517: adjusting |= ADJ_PRECISION;
518: expprec = 1;
519: } else {
520: precision = 0;
521: }
522: } else {
523: precision = 0;
524: }
525: PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
526: } else {
527: width = precision = 0;
528: argnum = currarg++ + format_offset;
529: }
530:
531: if (argnum >= argc) {
532: efree(result);
533: efree(args);
534: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
535: return NULL;
536: }
537:
538: if (format[inpos] == 'l') {
539: inpos++;
540: }
541: PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
542: /* now we expect to find a type specifier */
543: if (multiuse) {
544: MAKE_STD_ZVAL(tmp);
545: *tmp = **(args[argnum]);
546: INIT_PZVAL(tmp);
547: zval_copy_ctor(tmp);
548: } else {
549: SEPARATE_ZVAL(args[argnum]);
550: tmp = *(args[argnum]);
551: }
552:
553: switch (format[inpos]) {
554: case 's': {
555: zval *var, var_copy;
556: int use_copy;
557:
558: zend_make_printable_zval(tmp, &var_copy, &use_copy);
559: if (use_copy) {
560: var = &var_copy;
561: } else {
562: var = tmp;
563: }
564: php_sprintf_appendstring(&result, &outpos, &size,
565: Z_STRVAL_P(var),
566: width, precision, padding,
567: alignment,
568: Z_STRLEN_P(var),
569: 0, expprec, 0);
570: if (use_copy) {
571: zval_dtor(&var_copy);
572: }
573: break;
574: }
575:
576: case 'd':
577: convert_to_long(tmp);
578: php_sprintf_appendint(&result, &outpos, &size,
579: Z_LVAL_P(tmp),
580: width, padding, alignment,
581: always_sign);
582: break;
583:
584: case 'u':
585: convert_to_long(tmp);
586: php_sprintf_appenduint(&result, &outpos, &size,
587: Z_LVAL_P(tmp),
588: width, padding, alignment);
589: break;
590:
591: case 'g':
592: case 'G':
593: case 'e':
594: case 'E':
595: case 'f':
596: case 'F':
597: convert_to_double(tmp);
598: php_sprintf_appenddouble(&result, &outpos, &size,
599: Z_DVAL_P(tmp),
600: width, padding, alignment,
601: precision, adjusting,
602: format[inpos], always_sign
603: TSRMLS_CC);
604: break;
605:
606: case 'c':
607: convert_to_long(tmp);
608: php_sprintf_appendchar(&result, &outpos, &size,
609: (char) Z_LVAL_P(tmp) TSRMLS_CC);
610: break;
611:
612: case 'o':
613: convert_to_long(tmp);
614: php_sprintf_append2n(&result, &outpos, &size,
615: Z_LVAL_P(tmp),
616: width, padding, alignment, 3,
617: hexchars, expprec);
618: break;
619:
620: case 'x':
621: convert_to_long(tmp);
622: php_sprintf_append2n(&result, &outpos, &size,
623: Z_LVAL_P(tmp),
624: width, padding, alignment, 4,
625: hexchars, expprec);
626: break;
627:
628: case 'X':
629: convert_to_long(tmp);
630: php_sprintf_append2n(&result, &outpos, &size,
631: Z_LVAL_P(tmp),
632: width, padding, alignment, 4,
633: HEXCHARS, expprec);
634: break;
635:
636: case 'b':
637: convert_to_long(tmp);
638: php_sprintf_append2n(&result, &outpos, &size,
639: Z_LVAL_P(tmp),
640: width, padding, alignment, 1,
641: hexchars, expprec);
642: break;
643:
644: case '%':
645: php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
646:
647: break;
648: default:
649: break;
650: }
651: if (multiuse) {
652: zval_ptr_dtor(&tmp);
653: }
654: inpos++;
655: }
656: }
657:
658: efree(args);
659:
660: /* possibly, we have to make sure we have room for the terminating null? */
661: result[outpos]=0;
662: *len = outpos;
663: return result;
664: }
665: /* }}} */
666:
667: /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
668: Return a formatted string */
669: PHP_FUNCTION(user_sprintf)
670: {
671: char *result;
672: int len;
673:
674: if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
675: RETURN_FALSE;
676: }
677: RETVAL_STRINGL(result, len, 0);
678: }
679: /* }}} */
680:
681: /* {{{ proto string vsprintf(string format, array args)
682: Return a formatted string */
683: PHP_FUNCTION(vsprintf)
684: {
685: char *result;
686: int len;
687:
688: if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
689: RETURN_FALSE;
690: }
691: RETVAL_STRINGL(result, len, 0);
692: }
693: /* }}} */
694:
695: /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
696: Output a formatted string */
697: PHP_FUNCTION(user_printf)
698: {
699: char *result;
700: int len, rlen;
701:
702: if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
703: RETURN_FALSE;
704: }
705: rlen = PHPWRITE(result, len);
706: efree(result);
707: RETURN_LONG(rlen);
708: }
709: /* }}} */
710:
711: /* {{{ proto int vprintf(string format, array args)
712: Output a formatted string */
713: PHP_FUNCTION(vprintf)
714: {
715: char *result;
716: int len, rlen;
717:
718: if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
719: RETURN_FALSE;
720: }
721: rlen = PHPWRITE(result, len);
722: efree(result);
723: RETURN_LONG(rlen);
724: }
725: /* }}} */
726:
727: /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
728: Output a formatted string into a stream */
729: PHP_FUNCTION(fprintf)
730: {
731: php_stream *stream;
732: zval *arg1;
733: char *result;
734: int len;
735:
736: if (ZEND_NUM_ARGS() < 2) {
737: WRONG_PARAM_COUNT;
738: }
739:
740: if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
741: RETURN_FALSE;
742: }
743:
744: php_stream_from_zval(stream, &arg1);
745:
746: if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) {
747: RETURN_FALSE;
748: }
749:
750: php_stream_write(stream, result, len);
751:
752: efree(result);
753:
754: RETURN_LONG(len);
755: }
756: /* }}} */
757:
758: /* {{{ proto int vfprintf(resource stream, string format, array args)
759: Output a formatted string into a stream */
760: PHP_FUNCTION(vfprintf)
761: {
762: php_stream *stream;
763: zval *arg1;
764: char *result;
765: int len;
766:
767: if (ZEND_NUM_ARGS() != 3) {
768: WRONG_PARAM_COUNT;
769: }
770:
771: if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
772: RETURN_FALSE;
773: }
774:
775: php_stream_from_zval(stream, &arg1);
776:
777: if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) {
778: RETURN_FALSE;
779: }
780:
781: php_stream_write(stream, result, len);
782:
783: efree(result);
784:
785: RETURN_LONG(len);
786: }
787: /* }}} */
788:
789: /*
790: * Local variables:
791: * tab-width: 4
792: * c-basic-offset: 4
793: * End:
794: * vim600: sw=4 ts=4 fdm=marker
795: * vim<600: sw=4 ts=4
796: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>