Return to formatted_print.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard |
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: */