Back to index

php5  5.3.10
formatted_print.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Stig Sæther Bakken <ssb@php.net>                             |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: formatted_print.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include <math.h>                         /* modf() */
00022 #include "php.h"
00023 #include "ext/standard/head.h"
00024 #include "php_string.h"
00025 #include "zend_execute.h"
00026 #include <stdio.h>
00027 
00028 #ifdef HAVE_LOCALE_H
00029 #include <locale.h>
00030 #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
00031 #else
00032 #define LCONV_DECIMAL_POINT '.'
00033 #endif
00034 
00035 #define ALIGN_LEFT 0
00036 #define ALIGN_RIGHT 1
00037 #define ADJ_WIDTH 1
00038 #define ADJ_PRECISION 2
00039 #define NUM_BUF_SIZE 500
00040 #define       NDIG 80
00041 #define FLOAT_DIGITS 6
00042 #define FLOAT_PRECISION 6
00043 #define MAX_FLOAT_DIGITS 38
00044 #define MAX_FLOAT_PRECISION 53
00045 
00046 #if 0
00047 /* trick to control varargs functions through cpp */
00048 # define PRINTF_DEBUG(arg) php_printf arg
00049 #else
00050 # define PRINTF_DEBUG(arg)
00051 #endif
00052 
00053 static char hexchars[] = "0123456789abcdef";
00054 static char HEXCHARS[] = "0123456789ABCDEF";
00055 
00056 /* php_spintf_appendchar() {{{ */
00057 inline static void
00058 php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
00059 {
00060        if ((*pos + 1) >= *size) {
00061               *size <<= 1;
00062               PRINTF_DEBUG(("%s(): ereallocing buffer to %d bytes\n", get_active_function_name(TSRMLS_C), *size));
00063               *buffer = erealloc(*buffer, *size);
00064        }
00065        PRINTF_DEBUG(("sprintf: appending '%c', pos=\n", add, *pos));
00066        (*buffer)[(*pos)++] = add;
00067 }
00068 /* }}} */
00069 
00070 /* php_spintf_appendstring() {{{ */
00071 inline static void
00072 php_sprintf_appendstring(char **buffer, int *pos, int *size, char *add,
00073                                              int min_width, int max_width, char padding,
00074                                              int alignment, int len, int neg, int expprec, int always_sign)
00075 {
00076        register int npad;
00077        int req_size;
00078        int copy_len;
00079        int m_width;
00080 
00081        copy_len = (expprec ? MIN(max_width, len) : len);
00082        npad = min_width - copy_len;
00083 
00084        if (npad < 0) {
00085               npad = 0;
00086        }
00087        
00088        PRINTF_DEBUG(("sprintf: appendstring(%x, %d, %d, \"%s\", %d, '%c', %d)\n",
00089                               *buffer, *pos, *size, add, min_width, padding, alignment));
00090        m_width = MAX(min_width, copy_len);
00091 
00092        if(m_width > INT_MAX - *pos - 1) {
00093               zend_error_noreturn(E_ERROR, "Field width %d is too long", m_width);
00094        }
00095 
00096        req_size = *pos + m_width + 1;
00097 
00098        if (req_size > *size) {
00099               while (req_size > *size) {
00100                      if(*size > INT_MAX/2) {
00101                             zend_error_noreturn(E_ERROR, "Field width %d is too long", req_size); 
00102                      }
00103                      *size <<= 1;
00104               }
00105               PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", *size));
00106               *buffer = erealloc(*buffer, *size);
00107        }
00108        if (alignment == ALIGN_RIGHT) {
00109               if ((neg || always_sign) && padding=='0') {
00110                      (*buffer)[(*pos)++] = (neg) ? '-' : '+';
00111                      add++;
00112                      len--;
00113                      copy_len--;
00114               }
00115               while (npad-- > 0) {
00116                      (*buffer)[(*pos)++] = padding;
00117               }
00118        }
00119        PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
00120        memcpy(&(*buffer)[*pos], add, copy_len + 1);
00121        *pos += copy_len;
00122        if (alignment == ALIGN_LEFT) {
00123               while (npad--) {
00124                      (*buffer)[(*pos)++] = padding;
00125               }
00126        }
00127 }
00128 /* }}} */
00129 
00130 /* php_spintf_appendint() {{{ */
00131 inline static void
00132 php_sprintf_appendint(char **buffer, int *pos, int *size, long number,
00133                                           int width, char padding, int alignment, 
00134                                           int always_sign)
00135 {
00136        char numbuf[NUM_BUF_SIZE];
00137        register unsigned long magn, nmagn;
00138        register unsigned int i = NUM_BUF_SIZE - 1, neg = 0;
00139 
00140        PRINTF_DEBUG(("sprintf: appendint(%x, %x, %x, %d, %d, '%c', %d)\n",
00141                               *buffer, pos, size, number, width, padding, alignment));
00142        if (number < 0) {
00143               neg = 1;
00144               magn = ((unsigned long) -(number + 1)) + 1;
00145        } else {
00146               magn = (unsigned long) number;
00147        }
00148 
00149        /* Can't right-pad 0's on integers */
00150        if(alignment==0 && padding=='0') padding=' ';
00151 
00152        numbuf[i] = '\0';
00153 
00154        do {
00155               nmagn = magn / 10;
00156 
00157               numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
00158               magn = nmagn;
00159        }
00160        while (magn > 0 && i > 0);
00161        if (neg) {
00162               numbuf[--i] = '-';
00163        } else if (always_sign) {
00164               numbuf[--i] = '+';
00165        }
00166        PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n",
00167                               number, &numbuf[i], i));
00168        php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
00169                                                   padding, alignment, (NUM_BUF_SIZE - 1) - i,
00170                                                   neg, 0, always_sign);
00171 }
00172 /* }}} */
00173 
00174 /* php_spintf_appenduint() {{{ */
00175 inline static void
00176 php_sprintf_appenduint(char **buffer, int *pos, int *size,
00177                                       unsigned long number,
00178                                       int width, char padding, int alignment)
00179 {
00180        char numbuf[NUM_BUF_SIZE];
00181        register unsigned long magn, nmagn;
00182        register unsigned int i = NUM_BUF_SIZE - 1;
00183 
00184        PRINTF_DEBUG(("sprintf: appenduint(%x, %x, %x, %d, %d, '%c', %d)\n",
00185                               *buffer, pos, size, number, width, padding, alignment));
00186        magn = (unsigned long) number;
00187 
00188        /* Can't right-pad 0's on integers */
00189        if (alignment == 0 && padding == '0') padding = ' ';
00190 
00191        numbuf[i] = '\0';
00192 
00193        do {
00194               nmagn = magn / 10;
00195 
00196               numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
00197               magn = nmagn;
00198        } while (magn > 0 && i > 0);
00199 
00200        PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
00201        php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
00202                                                   padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
00203 }
00204 /* }}} */
00205 
00206 /* php_spintf_appenddouble() {{{ */
00207 inline static void
00208 php_sprintf_appenddouble(char **buffer, int *pos,
00209                                            int *size, double number,
00210                                            int width, char padding,
00211                                            int alignment, int precision,
00212                                            int adjust, char fmt,
00213                                            int always_sign
00214                                            TSRMLS_DC)
00215 {
00216        char num_buf[NUM_BUF_SIZE];
00217        char *s = NULL;
00218        int s_len = 0, is_negative = 0;
00219 #ifdef HAVE_LOCALE_H
00220        struct lconv *lconv;
00221 #endif
00222 
00223        PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
00224                               *buffer, pos, size, number, width, padding, alignment, fmt));
00225        if ((adjust & ADJ_PRECISION) == 0) {
00226               precision = FLOAT_PRECISION;
00227        } else if (precision > MAX_FLOAT_PRECISION) {
00228               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);
00229               precision = MAX_FLOAT_PRECISION;
00230        }
00231        
00232        if (zend_isnan(number)) {
00233               is_negative = (number<0);
00234               php_sprintf_appendstring(buffer, pos, size, "NaN", 3, 0, padding,
00235                                                          alignment, 3, is_negative, 0, always_sign);
00236               return;
00237        }
00238 
00239        if (zend_isinf(number)) {
00240               is_negative = (number<0);
00241               php_sprintf_appendstring(buffer, pos, size, "INF", 3, 0, padding,
00242                                                          alignment, 3, is_negative, 0, always_sign);
00243               return;
00244        }
00245 
00246        switch (fmt) {                     
00247               case 'e':
00248               case 'E':
00249               case 'f':
00250               case 'F':
00251 #ifdef HAVE_LOCALE_H
00252                      lconv = localeconv();
00253 #endif
00254                      s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
00255                                           (fmt == 'f')?LCONV_DECIMAL_POINT:'.',
00256                                           &is_negative, &num_buf[1], &s_len);
00257                      if (is_negative) {
00258                             num_buf[0] = '-';
00259                             s = num_buf;
00260                             s_len++;
00261                      } else if (always_sign) {
00262                             num_buf[0] = '+';
00263                             s = num_buf;
00264                             s_len++;
00265                      }
00266                      break;
00267 
00268               case 'g':
00269               case 'G':
00270                      if (precision == 0)
00271                             precision = 1;
00272                      /*
00273                       * * We use &num_buf[ 1 ], so that we have room for the sign
00274                       */
00275 #ifdef HAVE_LOCALE_H
00276                      lconv = localeconv();
00277 #endif
00278                      s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
00279                      is_negative = 0;
00280                      if (*s == '-') {
00281                             is_negative = 1;
00282                             s = &num_buf[1];
00283                      } else if (always_sign) {
00284                             num_buf[0] = '+';
00285                             s = num_buf;
00286                      }
00287 
00288                      s_len = strlen(s);
00289                      break;
00290        }
00291 
00292        php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding,
00293                                                   alignment, s_len, is_negative, 0, always_sign);
00294 }
00295 /* }}} */
00296 
00297 /* php_spintf_appendd2n() {{{ */
00298 inline static void
00299 php_sprintf_append2n(char **buffer, int *pos, int *size, long number,
00300                                     int width, char padding, int alignment, int n,
00301                                     char *chartable, int expprec)
00302 {
00303        char numbuf[NUM_BUF_SIZE];
00304        register unsigned long num;
00305        register unsigned int  i = NUM_BUF_SIZE - 1;
00306        register int andbits = (1 << n) - 1;
00307 
00308        PRINTF_DEBUG(("sprintf: append2n(%x, %x, %x, %d, %d, '%c', %d, %d, %x)\n",
00309                               *buffer, pos, size, number, width, padding, alignment, n,
00310                               chartable));
00311        PRINTF_DEBUG(("sprintf: append2n 2^%d andbits=%x\n", n, andbits));
00312 
00313        num = (unsigned long) number;
00314        numbuf[i] = '\0';
00315 
00316        do {
00317               numbuf[--i] = chartable[(num & andbits)];
00318               num >>= n;
00319        }
00320        while (num > 0);
00321 
00322        php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
00323                                                   padding, alignment, (NUM_BUF_SIZE - 1) - i,
00324                                                   0, expprec, 0);
00325 }
00326 /* }}} */
00327 
00328 /* php_spintf_getnumber() {{{ */
00329 inline static int
00330 php_sprintf_getnumber(char *buffer, int *pos)
00331 {
00332        char *endptr;
00333        register long num = strtol(&buffer[*pos], &endptr, 10);
00334        register int i = 0;
00335 
00336        if (endptr != NULL) {
00337               i = (endptr - &buffer[*pos]);
00338        }
00339        PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i));
00340        *pos += i;
00341 
00342        if (num >= INT_MAX || num < 0) {
00343               return -1;
00344        } else {
00345               return (int) num;
00346        }
00347 }
00348 /* }}} */
00349 
00350 /* php_formatted_print() {{{
00351  * New sprintf implementation for PHP.
00352  *
00353  * Modifiers:
00354  *
00355  *  " "   pad integers with spaces
00356  *  "-"   left adjusted field
00357  *   n    field size
00358  *  "."n  precision (floats only)
00359  *  "+"   Always place a sign (+ or -) in front of a number
00360  *
00361  * Type specifiers:
00362  *
00363  *  "%"   literal "%", modifiers are ignored.
00364  *  "b"   integer argument is printed as binary
00365  *  "c"   integer argument is printed as a single character
00366  *  "d"   argument is an integer
00367  *  "f"   the argument is a float
00368  *  "o"   integer argument is printed as octal
00369  *  "s"   argument is a string
00370  *  "x"   integer argument is printed as lowercase hexadecimal
00371  *  "X"   integer argument is printed as uppercase hexadecimal
00372  *
00373  */
00374 static char *
00375 php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC)
00376 {
00377        zval ***args, **z_format;
00378        int argc, size = 240, inpos = 0, outpos = 0, temppos;
00379        int alignment, currarg, adjusting, argnum, width, precision;
00380        char *format, *result, padding;
00381        int always_sign;
00382 
00383        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
00384               return NULL;
00385        }
00386 
00387        /* verify the number of args */
00388        if ((use_array && argc != (2 + format_offset)) 
00389                      || (!use_array && argc < (1 + format_offset))) {
00390               efree(args);
00391               WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
00392        }
00393        
00394        if (use_array) {
00395               int i = 1;
00396               zval ***newargs;
00397               zval **array;
00398 
00399               z_format = args[format_offset];
00400               array = args[1 + format_offset];
00401               
00402               SEPARATE_ZVAL(array);
00403               convert_to_array_ex(array);
00404               
00405               argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
00406               newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
00407               newargs[0] = z_format;
00408               
00409               for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
00410                       zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
00411                       zend_hash_move_forward(Z_ARRVAL_PP(array)));
00412 
00413               efree(args);
00414               args = newargs;
00415               format_offset = 0;
00416        }
00417        
00418        convert_to_string_ex(args[format_offset]);
00419        format = Z_STRVAL_PP(args[format_offset]);
00420        result = emalloc(size);
00421 
00422        currarg = 1;
00423 
00424        while (inpos<Z_STRLEN_PP(args[format_offset])) {
00425               int expprec = 0, multiuse = 0;
00426               zval *tmp;
00427 
00428               PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
00429               PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
00430               if (format[inpos] != '%') {
00431                      php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
00432               } else if (format[inpos + 1] == '%') {
00433                      php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
00434                      inpos += 2;
00435               } else {
00436                      /* starting a new format specifier, reset variables */
00437                      alignment = ALIGN_RIGHT;
00438                      adjusting = 0;
00439                      padding = ' ';
00440                      always_sign = 0;
00441                      inpos++;                    /* skip the '%' */
00442 
00443                      PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
00444                                             format[inpos], inpos));
00445                      if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
00446                             /* first look for argnum */
00447                             temppos = inpos;
00448                             while (isdigit((int)format[temppos])) temppos++;
00449                             if (format[temppos] == '$') {
00450                                    argnum = php_sprintf_getnumber(format, &inpos);
00451 
00452                                    if (argnum <= 0) {
00453                                           efree(result);
00454                                           efree(args);
00455                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
00456                                           return NULL;
00457                                    }
00458 
00459                                    multiuse = 1;
00460                                    inpos++;  /* skip the '$' */
00461                             } else {
00462                                    argnum = currarg++;
00463                             }
00464 
00465                             argnum += format_offset;
00466 
00467                             /* after argnum comes modifiers */
00468                             PRINTF_DEBUG(("sprintf: looking for modifiers\n"
00469                                                    "sprintf: now looking at '%c', inpos=%d\n",
00470                                                    format[inpos], inpos));
00471                             for (;; inpos++) {
00472                                    if (format[inpos] == ' ' || format[inpos] == '0') {
00473                                           padding = format[inpos];
00474                                    } else if (format[inpos] == '-') {
00475                                           alignment = ALIGN_LEFT;
00476                                           /* space padding, the default */
00477                                    } else if (format[inpos] == '+') {
00478                                           always_sign = 1;
00479                                    } else if (format[inpos] == '\'') {
00480                                           padding = format[++inpos];
00481                                    } else {
00482                                           PRINTF_DEBUG(("sprintf: end of modifiers\n"));
00483                                           break;
00484                                    }
00485                             }
00486                             PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
00487                             PRINTF_DEBUG(("sprintf: alignment=%s\n",
00488                                                    (alignment == ALIGN_LEFT) ? "left" : "right"));
00489 
00490 
00491                             /* after modifiers comes width */
00492                             if (isdigit((int)format[inpos])) {
00493                                    PRINTF_DEBUG(("sprintf: getting width\n"));
00494                                    if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
00495                                           efree(result);
00496                                           efree(args);
00497                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
00498                                           return NULL;
00499                                    }
00500                                    adjusting |= ADJ_WIDTH;
00501                             } else {
00502                                    width = 0;
00503                             }
00504                             PRINTF_DEBUG(("sprintf: width=%d\n", width));
00505 
00506                             /* after width and argnum comes precision */
00507                             if (format[inpos] == '.') {
00508                                    inpos++;
00509                                    PRINTF_DEBUG(("sprintf: getting precision\n"));
00510                                    if (isdigit((int)format[inpos])) {
00511                                           if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
00512                                                  efree(result);
00513                                                  efree(args);
00514                                                  php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
00515                                                  return NULL;
00516                                           }
00517                                           adjusting |= ADJ_PRECISION;
00518                                           expprec = 1;
00519                                    } else {
00520                                           precision = 0;
00521                                    }
00522                             } else {
00523                                    precision = 0;
00524                             }
00525                             PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
00526                      } else {
00527                             width = precision = 0;
00528                             argnum = currarg++ + format_offset;
00529                      }
00530 
00531                      if (argnum >= argc) {
00532                             efree(result);
00533                             efree(args);
00534                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
00535                             return NULL;
00536                      }
00537 
00538                      if (format[inpos] == 'l') {
00539                             inpos++;
00540                      }
00541                      PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
00542                      /* now we expect to find a type specifier */
00543                      if (multiuse) {
00544                             MAKE_STD_ZVAL(tmp);
00545                             *tmp = **(args[argnum]);
00546                             INIT_PZVAL(tmp);
00547                             zval_copy_ctor(tmp);
00548                      } else {
00549                             SEPARATE_ZVAL(args[argnum]);
00550                             tmp = *(args[argnum]);
00551                      }
00552 
00553                      switch (format[inpos]) {
00554                             case 's': {
00555                                    zval *var, var_copy;
00556                                    int use_copy;
00557 
00558                                    zend_make_printable_zval(tmp, &var_copy, &use_copy);
00559                                    if (use_copy) {
00560                                           var = &var_copy;
00561                                    } else {
00562                                           var = tmp;
00563                                    }
00564                                    php_sprintf_appendstring(&result, &outpos, &size,
00565                                                                               Z_STRVAL_P(var),
00566                                                                               width, precision, padding,
00567                                                                               alignment,
00568                                                                               Z_STRLEN_P(var),
00569                                                                               0, expprec, 0);
00570                                    if (use_copy) {
00571                                           zval_dtor(&var_copy);
00572                                    }
00573                                    break;
00574                             }
00575 
00576                             case 'd':
00577                                    convert_to_long(tmp);
00578                                    php_sprintf_appendint(&result, &outpos, &size,
00579                                                                         Z_LVAL_P(tmp),
00580                                                                         width, padding, alignment,
00581                                                                         always_sign);
00582                                    break;
00583 
00584                             case 'u':
00585                                    convert_to_long(tmp);
00586                                    php_sprintf_appenduint(&result, &outpos, &size,
00587                                                                         Z_LVAL_P(tmp),
00588                                                                         width, padding, alignment);
00589                                    break;
00590 
00591                             case 'g':
00592                             case 'G':
00593                             case 'e':
00594                             case 'E':
00595                             case 'f':
00596                             case 'F':
00597                                    convert_to_double(tmp);
00598                                    php_sprintf_appenddouble(&result, &outpos, &size,
00599                                                                               Z_DVAL_P(tmp),
00600                                                                               width, padding, alignment,
00601                                                                               precision, adjusting,
00602                                                                               format[inpos], always_sign
00603                                                                               TSRMLS_CC);
00604                                    break;
00605                                    
00606                             case 'c':
00607                                    convert_to_long(tmp);
00608                                    php_sprintf_appendchar(&result, &outpos, &size,
00609                                                                       (char) Z_LVAL_P(tmp) TSRMLS_CC);
00610                                    break;
00611 
00612                             case 'o':
00613                                    convert_to_long(tmp);
00614                                    php_sprintf_append2n(&result, &outpos, &size,
00615                                                                        Z_LVAL_P(tmp),
00616                                                                        width, padding, alignment, 3,
00617                                                                        hexchars, expprec);
00618                                    break;
00619 
00620                             case 'x':
00621                                    convert_to_long(tmp);
00622                                    php_sprintf_append2n(&result, &outpos, &size,
00623                                                                        Z_LVAL_P(tmp),
00624                                                                        width, padding, alignment, 4,
00625                                                                        hexchars, expprec);
00626                                    break;
00627 
00628                             case 'X':
00629                                    convert_to_long(tmp);
00630                                    php_sprintf_append2n(&result, &outpos, &size,
00631                                                                        Z_LVAL_P(tmp),
00632                                                                        width, padding, alignment, 4,
00633                                                                        HEXCHARS, expprec);
00634                                    break;
00635 
00636                             case 'b':
00637                                    convert_to_long(tmp);
00638                                    php_sprintf_append2n(&result, &outpos, &size,
00639                                                                        Z_LVAL_P(tmp),
00640                                                                        width, padding, alignment, 1,
00641                                                                        hexchars, expprec);
00642                                    break;
00643 
00644                             case '%':
00645                                    php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
00646 
00647                                    break;
00648                             default:
00649                                    break;
00650                      }
00651                      if (multiuse) {
00652                             zval_ptr_dtor(&tmp);
00653                      }
00654                      inpos++;
00655               }
00656        }
00657        
00658        efree(args);
00659        
00660        /* possibly, we have to make sure we have room for the terminating null? */
00661        result[outpos]=0;
00662        *len = outpos;       
00663        return result;
00664 }
00665 /* }}} */
00666 
00667 /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
00668    Return a formatted string */
00669 PHP_FUNCTION(user_sprintf)
00670 {
00671        char *result;
00672        int len;
00673        
00674        if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
00675               RETURN_FALSE;
00676        }
00677        RETVAL_STRINGL(result, len, 0);
00678 }
00679 /* }}} */
00680 
00681 /* {{{ proto string vsprintf(string format, array args)
00682    Return a formatted string */
00683 PHP_FUNCTION(vsprintf)
00684 {
00685        char *result;
00686        int len;
00687        
00688        if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
00689               RETURN_FALSE;
00690        }
00691        RETVAL_STRINGL(result, len, 0);
00692 }
00693 /* }}} */
00694 
00695 /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
00696    Output a formatted string */
00697 PHP_FUNCTION(user_printf)
00698 {
00699        char *result;
00700        int len, rlen;
00701        
00702        if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
00703               RETURN_FALSE;
00704        }
00705        rlen = PHPWRITE(result, len);
00706        efree(result);
00707        RETURN_LONG(rlen);
00708 }
00709 /* }}} */
00710 
00711 /* {{{ proto int vprintf(string format, array args)
00712    Output a formatted string */
00713 PHP_FUNCTION(vprintf)
00714 {
00715        char *result;
00716        int len, rlen;
00717        
00718        if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
00719               RETURN_FALSE;
00720        }
00721        rlen = PHPWRITE(result, len);
00722        efree(result);
00723        RETURN_LONG(rlen);
00724 }
00725 /* }}} */
00726 
00727 /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
00728    Output a formatted string into a stream */
00729 PHP_FUNCTION(fprintf)
00730 {
00731        php_stream *stream;
00732        zval *arg1;
00733        char *result;
00734        int len;
00735        
00736        if (ZEND_NUM_ARGS() < 2) {
00737               WRONG_PARAM_COUNT;
00738        }
00739        
00740        if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
00741               RETURN_FALSE;
00742        }
00743        
00744        php_stream_from_zval(stream, &arg1);
00745 
00746        if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) {
00747               RETURN_FALSE;
00748        }
00749 
00750        php_stream_write(stream, result, len);
00751 
00752        efree(result);
00753 
00754        RETURN_LONG(len);
00755 }
00756 /* }}} */
00757 
00758 /* {{{ proto int vfprintf(resource stream, string format, array args)
00759    Output a formatted string into a stream */
00760 PHP_FUNCTION(vfprintf)
00761 {
00762        php_stream *stream;
00763        zval *arg1;
00764        char *result;
00765        int len;
00766        
00767        if (ZEND_NUM_ARGS() != 3) {
00768               WRONG_PARAM_COUNT;
00769        }
00770        
00771        if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
00772               RETURN_FALSE;
00773        }
00774        
00775        php_stream_from_zval(stream, &arg1);
00776 
00777        if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) {
00778               RETURN_FALSE;
00779        }
00780 
00781        php_stream_write(stream, result, len);
00782 
00783        efree(result);
00784 
00785        RETURN_LONG(len);
00786 }
00787 /* }}} */
00788 
00789 /*
00790  * Local variables:
00791  * tab-width: 4
00792  * c-basic-offset: 4
00793  * End:
00794  * vim600: sw=4 ts=4 fdm=marker
00795  * vim<600: sw=4 ts=4
00796  */