root/ext/standard/formatted_print.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_sprintf_appendchar
  2. php_sprintf_appendstring
  3. php_sprintf_appendint
  4. php_sprintf_appenduint
  5. php_sprintf_appenddouble
  6. php_sprintf_append2n
  7. php_sprintf_getnumber
  8. php_formatted_print
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_FUNCTION
  14. PHP_FUNCTION

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

/* [<][>][^][v][top][bottom][index][help] */