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: 303 320 94.7 %
Date: 2014-07-27 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:37 +0000 (5 days ago)

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