PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/standard - formatted_print.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 273 294 92.9 %
Date: 2014-12-13 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 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     1230122 : php_sprintf_appendchar(zend_string **buffer, size_t *pos, char add TSRMLS_DC)
      61             : {
      62     1230122 :         if (!*buffer || (*pos + 1) >= (*buffer)->len) {
      63             :                 PRINTF_DEBUG(("%s(): ereallocing buffer to %d bytes\n", get_active_function_name(TSRMLS_C), (*buffer)->len));
      64           2 :                 *buffer = zend_string_realloc(*buffer, (*buffer)->len << 1, 0);
      65             :         }
      66             :         PRINTF_DEBUG(("sprintf: appending '%c', pos=\n", add, *pos));
      67     1230122 :         (*buffer)->val[(*pos)++] = add;
      68     1230122 : }
      69             : /* }}} */
      70             : 
      71             : /* php_spintf_appendstring() {{{ */
      72             : inline static void
      73      103107 : 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      103107 :         copy_len = (expprec ? MIN(max_width, len) : len);
      83      103107 :         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, (*buffer)->len, add, min_width, padding, alignment));
      87      103107 :         m_width = MAX(min_width, copy_len);
      88             : 
      89      103107 :         if(m_width > INT_MAX - *pos - 1) {
      90           0 :                 zend_error_noreturn(E_ERROR, "Field width %d is too long", m_width);
      91             :         }
      92             : 
      93      103107 :         req_size = *pos + m_width + 1;
      94             : 
      95      103107 :         if (!*buffer || req_size > (*buffer)->len) {
      96       12080 :                 size_t size = (*buffer)->len;
      97       36253 :                 while (req_size > size) {
      98       12093 :                         if (size > ZEND_SIZE_MAX/2) {
      99           0 :                                 zend_error_noreturn(E_ERROR, "Field width %zd is too long", req_size); 
     100             :                         }
     101       12093 :                         size <<= 1;
     102             :                 }
     103             :                 PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", size));
     104       24160 :                 *buffer = zend_string_realloc(*buffer, size, 0);
     105             :         }
     106      103107 :         if (alignment == ALIGN_RIGHT) {
     107      101695 :                 if ((neg || always_sign) && padding=='0') {
     108          36 :                         (*buffer)->val[(*pos)++] = (neg) ? '-' : '+';
     109          36 :                         add++;
     110          36 :                         len--;
     111          36 :                         copy_len--;
     112             :                 }
     113      230475 :                 while (npad-- > 0) {
     114       27085 :                         (*buffer)->val[(*pos)++] = padding;
     115             :                 }
     116             :         }
     117             :         PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
     118      103107 :         memcpy(&(*buffer)->val[*pos], add, copy_len + 1);
     119      103107 :         *pos += copy_len;
     120      103107 :         if (alignment == ALIGN_LEFT) {
     121        6816 :                 while (npad--) {
     122        3992 :                         (*buffer)->val[(*pos)++] = padding;
     123             :                 }
     124             :         }
     125      103107 : }
     126             : /* }}} */
     127             : 
     128             : /* php_spintf_appendint() {{{ */
     129             : inline static void
     130       37984 : 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       37984 :         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, &(*buffer)->len, number, width, padding, alignment));
     140       37984 :         if (number < 0) {
     141         766 :                 neg = 1;
     142         766 :                 magn = ((zend_ulong) -(number + 1)) + 1;
     143             :         } else {
     144       37218 :                 magn = (zend_ulong) number;
     145             :         }
     146             : 
     147             :         /* Can't right-pad 0's on integers */
     148       37984 :         if(alignment==0 && padding=='0') padding=' ';
     149             : 
     150       37984 :         numbuf[i] = '\0';
     151             : 
     152             :         do {
     153      128611 :                 nmagn = magn / 10;
     154             : 
     155      128611 :                 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
     156      128611 :                 magn = nmagn;
     157             :         }
     158      128611 :         while (magn > 0 && i > 0);
     159       37984 :         if (neg) {
     160         766 :                 numbuf[--i] = '-';
     161       37218 :         } else if (always_sign) {
     162          36 :                 numbuf[--i] = '+';
     163             :         }
     164             :         PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n",
     165             :                                   number, &numbuf[i], i));
     166       75968 :         php_sprintf_appendstring(buffer, pos, &numbuf[i], width, 0,
     167       37984 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     168             :                                                          neg, 0, always_sign);
     169       37984 : }
     170             : /* }}} */
     171             : 
     172             : /* php_spintf_appenduint() {{{ */
     173             : inline static void
     174         921 : 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         921 :         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, &(*buffer)->len, number, width, padding, alignment));
     184         921 :         magn = (zend_ulong) number;
     185             : 
     186             :         /* Can't right-pad 0's on integers */
     187         921 :         if (alignment == 0 && padding == '0') padding = ' ';
     188             : 
     189         921 :         numbuf[i] = '\0';
     190             : 
     191             :         do {
     192        4555 :                 nmagn = magn / 10;
     193             : 
     194        4555 :                 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
     195        4555 :                 magn = nmagn;
     196        4555 :         } while (magn > 0 && i > 0);
     197             : 
     198             :         PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
     199         921 :         php_sprintf_appendstring(buffer, pos, &numbuf[i], width, 0,
     200         921 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
     201         921 : }
     202             : /* }}} */
     203             : 
     204             : /* php_spintf_appenddouble() {{{ */
     205             : inline static void
     206        3806 : 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             :                                                  TSRMLS_DC)
     213             : {
     214             :         char num_buf[NUM_BUF_SIZE];
     215        3806 :         char *s = NULL;
     216        3806 :         size_t s_len = 0;
     217        3806 :         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, &(*buffer)->len, number, width, padding, alignment, fmt));
     228        3806 :         if ((adjust & ADJ_PRECISION) == 0) {
     229        3474 :                 precision = FLOAT_PRECISION;
     230         332 :         } else if (precision > MAX_FLOAT_PRECISION) {
     231           2 :                 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);
     232           2 :                 precision = MAX_FLOAT_PRECISION;
     233             :         }
     234             :         
     235        3806 :         if (zend_isnan(number)) {
     236          40 :                 is_negative = (number<0);
     237          40 :                 php_sprintf_appendstring(buffer, pos, "NaN", 3, 0, padding,
     238             :                                                                  alignment, 3, is_negative, 0, always_sign);
     239          40 :                 return;
     240             :         }
     241             : 
     242        3766 :         if (zend_isinf(number)) {
     243           0 :                 is_negative = (number<0);
     244           0 :                 php_sprintf_appendstring(buffer, pos, "INF", 3, 0, padding,
     245             :                                                                  alignment, 3, is_negative, 0, always_sign);
     246           0 :                 return;
     247             :         }
     248             : 
     249        3766 :         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        3742 :                         lconv = localeconv();
     259             : #endif
     260             : #endif
     261        6450 :                         s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
     262        2708 :                                                 (fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     263             :                                                 &is_negative, &num_buf[1], &s_len);
     264        3742 :                         if (is_negative) {
     265         842 :                                 num_buf[0] = '-';
     266         842 :                                 s = num_buf;
     267         842 :                                 s_len++;
     268        2900 :                         } else if (always_sign) {
     269          36 :                                 num_buf[0] = '+';
     270          36 :                                 s = num_buf;
     271          36 :                                 s_len++;
     272             :                         }
     273        3742 :                         break;
     274             : 
     275             :                 case 'g':
     276             :                 case 'G':
     277          24 :                         if (precision == 0)
     278           4 :                                 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          24 :                         lconv = localeconv();
     287             : #endif
     288             : #endif
     289          24 :                         s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
     290          24 :                         is_negative = 0;
     291          24 :                         if (*s == '-') {
     292          12 :                                 is_negative = 1;
     293          12 :                                 s = &num_buf[1];
     294          12 :                         } else if (always_sign) {
     295           4 :                                 num_buf[0] = '+';
     296           4 :                                 s = num_buf;
     297             :                         }
     298             : 
     299          24 :                         s_len = strlen(s);
     300             :                         break;
     301             :         }
     302             : 
     303        3766 :         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       10854 : 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       10854 :         register zend_ulong  i = NUM_BUF_SIZE - 1;
     317       10854 :         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, &(*buffer)->len, number, width, padding, alignment, n,
     321             :                                   chartable));
     322             :         PRINTF_DEBUG(("sprintf: append2n 2^%d andbits=%x\n", n, andbits));
     323             : 
     324       10854 :         num = (zend_ulong) number;
     325       10854 :         numbuf[i] = '\0';
     326             : 
     327             :         do {
     328       40545 :                 numbuf[--i] = chartable[(num & andbits)];
     329       40545 :                 num >>= n;
     330             :         }
     331       40545 :         while (num > 0);
     332             : 
     333       10854 :         php_sprintf_appendstring(buffer, pos, &numbuf[i], width, 0,
     334             :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     335             :                                                          0, expprec, 0);
     336       10854 : }
     337             : /* }}} */
     338             : 
     339             : /* php_spintf_getnumber() {{{ */
     340             : inline static int
     341       16263 : php_sprintf_getnumber(char *buffer, size_t *pos)
     342             : {
     343             :         char *endptr;
     344       16263 :         register zend_long num = ZEND_STRTOL(&buffer[*pos], &endptr, 10);
     345       16263 :         register size_t i = 0;
     346             : 
     347       16263 :         if (endptr != NULL) {
     348       16263 :                 i = (endptr - &buffer[*pos]);
     349             :         }
     350             :         PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i));
     351       16263 :         *pos += i;
     352             : 
     353       16263 :         if (num >= INT_MAX || num < 0) {
     354           0 :                 return -1;
     355             :         } else {
     356       16263 :                 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       64621 : php_formatted_print(int param_count, int use_array, int format_offset TSRMLS_DC)
     387             : {
     388       64621 :         zval *newargs = NULL;
     389             :         zval *args, *z_format;
     390             :         int argc;
     391       64621 :         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       64621 :         if (zend_parse_parameters(param_count TSRMLS_CC, "+", &args, &argc) == FAILURE) {
     399           5 :                 return NULL;
     400             :         }
     401             : 
     402             :         /* verify the number of args */
     403      128638 :         if ((use_array && argc != (2 + format_offset)) 
     404       64022 :                         || (!use_array && argc < (1 + format_offset))) {
     405           4 :                 WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
     406             :         }
     407             :         
     408      130056 :         convert_to_string_ex(&args[format_offset]);
     409       64612 :         if (use_array) {
     410         590 :                 int i = 1;
     411             :                 zval *zv;
     412             :                 zval *array;
     413             : 
     414         590 :                 z_format = &args[format_offset];
     415         590 :                 array = &args[1 + format_offset];
     416         590 :                 if (Z_TYPE_P(array) != IS_ARRAY) {
     417          84 :                         SEPARATE_ZVAL(array);
     418          72 :                         convert_to_array(array);
     419             :                 }
     420             :                 
     421         590 :                 argc = 1 + zend_hash_num_elements(Z_ARRVAL_P(array));
     422         590 :                 newargs = (zval *)safe_emalloc(argc, sizeof(zval), 0);
     423         590 :                 ZVAL_COPY_VALUE(&newargs[0], z_format);
     424             :                 
     425        7002 :                 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), zv) {
     426        3206 :                         ZVAL_COPY_VALUE(&newargs[i], zv);
     427        3206 :                         i++;
     428             :                 } ZEND_HASH_FOREACH_END();
     429         590 :                 args = newargs;
     430         590 :                 format_offset = 0;
     431             :         }
     432             :         
     433       64612 :         format = Z_STRVAL(args[format_offset]);
     434       64612 :         format_len = Z_STRLEN(args[format_offset]);
     435       64612 :         result = zend_string_alloc(size, 0);
     436             : 
     437       64612 :         currarg = 1;
     438             : 
     439     1464894 :         while (inpos < Z_STRLEN(args[format_offset])) {
     440     1335701 :                 int expprec = 0;
     441             :                 zval *tmp;
     442             : 
     443             :                 PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
     444             :                 PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
     445     1335701 :                 if (format[inpos] != '%') {
     446     1229067 :                         php_sprintf_appendchar(&result, &outpos, format[inpos++] TSRMLS_CC);
     447      106634 :                 } else if (format[inpos + 1] == '%') {
     448          46 :                         php_sprintf_appendchar(&result, &outpos, '%' TSRMLS_CC);
     449          46 :                         inpos += 2;
     450             :                 } else {
     451             :                         /* starting a new format specifier, reset variables */
     452      106588 :                         alignment = ALIGN_RIGHT;
     453      106588 :                         adjusting = 0;
     454      106588 :                         padding = ' ';
     455      106588 :                         always_sign = 0;
     456      106588 :                         inpos++;                        /* skip the '%' */
     457             : 
     458             :                         PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
     459             :                                                   format[inpos], inpos));
     460      124100 :                         if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
     461             :                                 /* first look for argnum */
     462       17514 :                                 temppos = inpos;
     463       17514 :                                 while (isdigit((int)format[temppos])) temppos++;
     464       17514 :                                 if (format[temppos] == '$') {
     465         555 :                                         argnum = php_sprintf_getnumber(format, &inpos);
     466             : 
     467         555 :                                         if (argnum <= 0) {
     468           2 :                                                 efree(result);
     469           2 :                                                 if (newargs) {
     470           1 :                                                         efree(newargs);
     471             :                                                 }
     472           2 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
     473           2 :                                                 return NULL;
     474             :                                         }
     475             : 
     476         553 :                                         inpos++;  /* skip the '$' */
     477             :                                 } else {
     478       16959 :                                         argnum = currarg++;
     479             :                                 }
     480             : 
     481       17512 :                                 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       12724 :                                 for (;; inpos++) {
     488       40735 :                                         if (format[inpos] == ' ' || format[inpos] == '0') {
     489       10499 :                                                 padding = format[inpos];
     490       19737 :                                         } else if (format[inpos] == '-') {
     491        1466 :                                                 alignment = ALIGN_LEFT;
     492             :                                                 /* space padding, the default */
     493       18271 :                                         } else if (format[inpos] == '+') {
     494         202 :                                                 always_sign = 1;
     495       18069 :                                         } else if (format[inpos] == '\'' && inpos+1<format_len) {
     496         557 :                                                 padding = format[++inpos];
     497             :                                         } else {
     498             :                                                 PRINTF_DEBUG(("sprintf: end of modifiers\n"));
     499             :                                                 break;
     500             :                                         }
     501       12724 :                                 }
     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       17512 :                                 if (isdigit((int)format[inpos])) {
     509             :                                         PRINTF_DEBUG(("sprintf: getting width\n"));
     510       14981 :                                         if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
     511           0 :                                                 efree(result);
     512           0 :                                                 if (newargs) {
     513           0 :                                                         efree(newargs);
     514             :                                                 }
     515           0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
     516           0 :                                                 if (newargs) {
     517           0 :                                                         efree(newargs);
     518             :                                                 }
     519           0 :                                                 return NULL;
     520             :                                         }
     521       14981 :                                         adjusting |= ADJ_WIDTH;
     522             :                                 } else {
     523        2531 :                                         width = 0;
     524             :                                 }
     525             :                                 PRINTF_DEBUG(("sprintf: width=%d\n", width));
     526             : 
     527             :                                 /* after width and argnum comes precision */
     528       17512 :                                 if (format[inpos] == '.') {
     529         729 :                                         inpos++;
     530             :                                         PRINTF_DEBUG(("sprintf: getting precision\n"));
     531         729 :                                         if (isdigit((int)format[inpos])) {
     532         727 :                                                 if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
     533           0 :                                                         efree(result);
     534           0 :                                                         if (newargs) {
     535           0 :                                                                 efree(newargs);
     536             :                                                         }
     537           0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
     538           0 :                                                         if (newargs) {
     539           0 :                                                                 efree(newargs);
     540             :                                                         }
     541           0 :                                                         return NULL;
     542             :                                                 }
     543         727 :                                                 adjusting |= ADJ_PRECISION;
     544         727 :                                                 expprec = 1;
     545             :                                         } else {
     546           2 :                                                 precision = 0;
     547             :                                         }
     548             :                                 } else {
     549       16783 :                                         precision = 0;
     550             :                                 }
     551             :                                 PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
     552             :                         } else {
     553       89074 :                                 width = precision = 0;
     554       89074 :                                 argnum = currarg++ + format_offset;
     555             :                         }
     556             : 
     557      106586 :                         if (argnum >= argc) {
     558          29 :                                 efree(result);
     559          29 :                                 if (newargs) {
     560          15 :                                         efree(newargs);
     561             :                                 }
     562          29 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
     563          29 :                                 return NULL;
     564             :                         }
     565             : 
     566      106557 :                         if (format[inpos] == 'l') {
     567        1711 :                                 inpos++;
     568             :                         }
     569             :                         PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
     570             :                         /* now we expect to find a type specifier */
     571      106557 :                         tmp = &args[argnum];
     572      106557 :                         switch (format[inpos]) {
     573             :                                 case 's': {
     574       49542 :                                         zend_string *str = zval_get_string(tmp);
     575       49542 :                                         php_sprintf_appendstring(&result, &outpos,
     576             :                                                                                          str->val,
     577             :                                                                                          width, precision, padding,
     578             :                                                                                          alignment,
     579             :                                                                                          str->len,
     580             :                                                                                          0, expprec, 0);
     581             :                                         zend_string_release(str);
     582       49542 :                                         break;
     583             :                                 }
     584             : 
     585             :                                 case 'd':
     586       75968 :                                         php_sprintf_appendint(&result, &outpos,
     587             :                                                                                   zval_get_long(tmp),
     588             :                                                                                   width, padding, alignment,
     589             :                                                                                   always_sign);
     590       37984 :                                         break;
     591             : 
     592             :                                 case 'u':
     593        1842 :                                         php_sprintf_appenduint(&result, &outpos,
     594             :                                                                                   zval_get_long(tmp),
     595             :                                                                                   width, padding, alignment);
     596         921 :                                         break;
     597             : 
     598             :                                 case 'g':
     599             :                                 case 'G':
     600             :                                 case 'e':
     601             :                                 case 'E':
     602             :                                 case 'f':
     603             :                                 case 'F':
     604        7612 :                                         php_sprintf_appenddouble(&result, &outpos,
     605             :                                                                                          zval_get_double(tmp),
     606             :                                                                                          width, padding, alignment,
     607             :                                                                                          precision, adjusting,
     608        3806 :                                                                                          format[inpos], always_sign
     609             :                                                                                          TSRMLS_CC);
     610        3806 :                                         break;
     611             :                                         
     612             :                                 case 'c':
     613         997 :                                         php_sprintf_appendchar(&result, &outpos,
     614         997 :                                                                                 (char) zval_get_long(tmp) TSRMLS_CC);
     615         997 :                                         break;
     616             : 
     617             :                                 case 'o':
     618        8098 :                                         php_sprintf_append2n(&result, &outpos,
     619             :                                                                                  zval_get_long(tmp),
     620             :                                                                                  width, padding, alignment, 3,
     621             :                                                                                  hexchars, expprec);
     622        4049 :                                         break;
     623             : 
     624             :                                 case 'x':
     625        5714 :                                         php_sprintf_append2n(&result, &outpos,
     626             :                                                                                  zval_get_long(tmp),
     627             :                                                                                  width, padding, alignment, 4,
     628             :                                                                                  hexchars, expprec);
     629        2857 :                                         break;
     630             : 
     631             :                                 case 'X':
     632        7762 :                                         php_sprintf_append2n(&result, &outpos,
     633             :                                                                                  zval_get_long(tmp),
     634             :                                                                                  width, padding, alignment, 4,
     635             :                                                                                  HEXCHARS, expprec);
     636        3881 :                                         break;
     637             : 
     638             :                                 case 'b':
     639         134 :                                         php_sprintf_append2n(&result, &outpos,
     640             :                                                                                  zval_get_long(tmp),
     641             :                                                                                  width, padding, alignment, 1,
     642             :                                                                                  hexchars, expprec);
     643          67 :                                         break;
     644             : 
     645             :                                 case '%':
     646          12 :                                         php_sprintf_appendchar(&result, &outpos, '%' TSRMLS_CC);
     647             : 
     648             :                                         break;
     649             :                                 default:
     650             :                                         break;
     651             :                         }
     652      106557 :                         inpos++;
     653             :                 }
     654             :         }
     655             : 
     656       64581 :         if (newargs) {
     657         574 :                 efree(newargs);
     658             :         }
     659             : 
     660             :         /* possibly, we have to make sure we have room for the terminating null? */
     661       64581 :         result->val[outpos]=0;
     662       64581 :         result->len = outpos;        
     663       64581 :         return result;
     664             : }
     665             : /* }}} */
     666             : 
     667             : /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
     668             :    Return a formatted string */
     669       49817 : PHP_FUNCTION(user_sprintf)
     670             : {
     671             :         zend_string *result;
     672             :         
     673       49817 :         if ((result=php_formatted_print(ZEND_NUM_ARGS(), 0, 0 TSRMLS_CC))==NULL) {
     674           7 :                 RETURN_FALSE;
     675             :         }
     676       49810 :         RETVAL_STR(result);
     677             : }
     678             : /* }}} */
     679             : 
     680             : /* {{{ proto string vsprintf(string format, array args)
     681             :    Return a formatted string */
     682         204 : PHP_FUNCTION(vsprintf)
     683             : {
     684             :         zend_string *result;
     685             :         
     686         204 :         if ((result=php_formatted_print(ZEND_NUM_ARGS(), 1, 0 TSRMLS_CC))==NULL) {
     687           8 :                 RETURN_FALSE;
     688             :         }
     689         196 :         RETVAL_STR(result);
     690             : }
     691             : /* }}} */
     692             : 
     693             : /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
     694             :    Output a formatted string */
     695       12670 : PHP_FUNCTION(user_printf)
     696             : {
     697             :         zend_string *result;
     698             :         size_t rlen;
     699             :         
     700       12670 :         if ((result=php_formatted_print(ZEND_NUM_ARGS(), 0, 0 TSRMLS_CC))==NULL) {
     701          10 :                 RETURN_FALSE;
     702             :         }
     703       12660 :         rlen = PHPWRITE(result->val, result->len);
     704             :         zend_string_free(result);
     705       12660 :         RETURN_LONG(rlen);
     706             : }
     707             : /* }}} */
     708             : 
     709             : /* {{{ proto int vprintf(string format, array args)
     710             :    Output a formatted string */
     711         189 : PHP_FUNCTION(vprintf)
     712             : {
     713             :         zend_string *result;
     714             :         size_t rlen;
     715             :         
     716         189 :         if ((result=php_formatted_print(ZEND_NUM_ARGS(), 1, 0 TSRMLS_CC))==NULL) {
     717           8 :                 RETURN_FALSE;
     718             :         }
     719         181 :         rlen = PHPWRITE(result->val, result->len);
     720             :         zend_string_free(result);
     721         181 :         RETURN_LONG(rlen);
     722             : }
     723             : /* }}} */
     724             : 
     725             : /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
     726             :    Output a formatted string into a stream */
     727        1541 : PHP_FUNCTION(fprintf)
     728             : {
     729             :         php_stream *stream;
     730             :         zval *arg1;
     731             :         zend_string *result;
     732             :         
     733        1541 :         if (ZEND_NUM_ARGS() < 2) {
     734           3 :                 WRONG_PARAM_COUNT;
     735             :         }
     736             :         
     737        1538 :         if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
     738           0 :                 RETURN_FALSE;
     739             :         }
     740             :         
     741        1538 :         php_stream_from_zval(stream, arg1);
     742             : 
     743        1538 :         if ((result=php_formatted_print(ZEND_NUM_ARGS(), 0, 1 TSRMLS_CC))==NULL) {
     744           1 :                 RETURN_FALSE;
     745             :         }
     746             : 
     747        1537 :         php_stream_write(stream, result->val, result->len);
     748             : 
     749        1537 :         RETVAL_LONG(result->len);
     750             :         zend_string_free(result);
     751             : }
     752             : /* }}} */
     753             : 
     754             : /* {{{ proto int vfprintf(resource stream, string format, array args)
     755             :    Output a formatted string into a stream */
     756         211 : PHP_FUNCTION(vfprintf)
     757             : {
     758             :         php_stream *stream;
     759             :         zval *arg1;
     760             :         zend_string *result;
     761             :         
     762         211 :         if (ZEND_NUM_ARGS() != 3) {
     763           5 :                 WRONG_PARAM_COUNT;
     764             :         }
     765             :         
     766         206 :         if (zend_parse_parameters(1 TSRMLS_CC, "r", &arg1) == FAILURE) {
     767           3 :                 RETURN_FALSE;
     768             :         }
     769             :         
     770         203 :         php_stream_from_zval(stream, arg1);
     771             : 
     772         203 :         if ((result=php_formatted_print(ZEND_NUM_ARGS(), 1, 1 TSRMLS_CC))==NULL) {
     773           6 :                 RETURN_FALSE;
     774             :         }
     775             : 
     776         197 :         php_stream_write(stream, result->val, result->len);
     777             : 
     778         197 :         RETVAL_LONG(result->len);
     779             :         zend_string_free(result);
     780             : }
     781             : /* }}} */
     782             : 
     783             : /*
     784             :  * Local variables:
     785             :  * tab-width: 4
     786             :  * c-basic-offset: 4
     787             :  * End:
     788             :  * vim600: sw=4 ts=4 fdm=marker
     789             :  * vim<600: sw=4 ts=4
     790             :  */

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:23 +0000 (8 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.