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