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

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