Annotation of embedaddon/php/ext/standard/formatted_print.c, revision 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>