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

LTP GCOV extension - code coverage report
Current view: directory - standard - formatted_print.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 308
Code covered: 93.5 % Executed lines: 288
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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: formatted_print.c 290150 2009-11-02 17:37:32Z felipe $ */
      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 40
      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                 : php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
      59          159234 : {
      60          159234 :         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          159234 :         (*buffer)[(*pos)++] = add;
      67          159234 : }
      68                 : /* }}} */
      69                 : 
      70                 : /* php_spintf_appendstring() {{{ */
      71                 : inline static void
      72                 : 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           36542 : {
      76                 :         register int npad;
      77                 :         int req_size;
      78                 :         int copy_len;
      79                 :         int m_width;
      80                 : 
      81           36542 :         copy_len = (expprec ? MIN(max_width, len) : len);
      82           36542 :         npad = min_width - copy_len;
      83                 : 
      84           36542 :         if (npad < 0) {
      85           28552 :                 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           36542 :         m_width = MAX(min_width, copy_len);
      91                 : 
      92           36542 :         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           36542 :         req_size = *pos + m_width + 1;
      97                 : 
      98           36542 :         if (req_size > *size) {
      99              13 :                 while (req_size > *size) {
     100               5 :                         if(*size > INT_MAX/2) {
     101               0 :                                 zend_error_noreturn(E_ERROR, "Field width %d is too long", req_size); 
     102                 :                         }
     103               5 :                         *size <<= 1;
     104                 :                 }
     105                 :                 PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", *size));
     106               4 :                 *buffer = erealloc(*buffer, *size);
     107                 :         }
     108           36542 :         if (alignment == ALIGN_RIGHT) {
     109           35181 :                 if ((neg || always_sign) && padding=='0') {
     110              36 :                         (*buffer)[(*pos)++] = (neg) ? '-' : '+';
     111              36 :                         add++;
     112              36 :                         len--;
     113              36 :                         copy_len--;
     114                 :                 }
     115           87745 :                 while (npad-- > 0) {
     116           17383 :                         (*buffer)[(*pos)++] = padding;
     117                 :                 }
     118                 :         }
     119                 :         PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
     120           36542 :         memcpy(&(*buffer)[*pos], add, copy_len + 1);
     121           36542 :         *pos += copy_len;
     122           36542 :         if (alignment == ALIGN_LEFT) {
     123            6434 :                 while (npad--) {
     124            3712 :                         (*buffer)[(*pos)++] = padding;
     125                 :                 }
     126                 :         }
     127           36542 : }
     128                 : /* }}} */
     129                 : 
     130                 : /* php_spintf_appendint() {{{ */
     131                 : inline static void
     132                 : php_sprintf_appendint(char **buffer, int *pos, int *size, long number,
     133                 :                                                 int width, char padding, int alignment, 
     134                 :                                                 int always_sign)
     135           18735 : {
     136                 :         char numbuf[NUM_BUF_SIZE];
     137                 :         register unsigned long magn, nmagn;
     138           18735 :         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           18735 :         if (number < 0) {
     143             673 :                 neg = 1;
     144             673 :                 magn = ((unsigned long) -(number + 1)) + 1;
     145                 :         } else {
     146           18062 :                 magn = (unsigned long) number;
     147                 :         }
     148                 : 
     149                 :         /* Can't right-pad 0's on integers */
     150           18735 :         if(alignment==0 && padding=='0') padding=' ';
     151                 : 
     152           18735 :         numbuf[i] = '\0';
     153                 : 
     154                 :         do {
     155           60008 :                 nmagn = magn / 10;
     156                 : 
     157           60008 :                 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
     158           60008 :                 magn = nmagn;
     159                 :         }
     160           60008 :         while (magn > 0 && i > 0);
     161           18735 :         if (neg) {
     162             673 :                 numbuf[--i] = '-';
     163           18062 :         } 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           18735 :         php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     169                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     170                 :                                                          neg, 0, always_sign);
     171           18735 : }
     172                 : /* }}} */
     173                 : 
     174                 : /* php_spintf_appenduint() {{{ */
     175                 : inline static void
     176                 : php_sprintf_appenduint(char **buffer, int *pos, int *size,
     177                 :                                            unsigned long number,
     178                 :                                            int width, char padding, int alignment)
     179             927 : {
     180                 :         char numbuf[NUM_BUF_SIZE];
     181                 :         register unsigned long magn, nmagn;
     182             927 :         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             927 :         magn = (unsigned long) number;
     187                 : 
     188                 :         /* Can't right-pad 0's on integers */
     189             927 :         if (alignment == 0 && padding == '0') padding = ' ';
     190                 : 
     191             927 :         numbuf[i] = '\0';
     192                 : 
     193                 :         do {
     194            3300 :                 nmagn = magn / 10;
     195                 : 
     196            3300 :                 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
     197            3300 :                 magn = nmagn;
     198            3300 :         } while (magn > 0 && i > 0);
     199                 : 
     200                 :         PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
     201             927 :         php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     202                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
     203             927 : }
     204                 : /* }}} */
     205                 : 
     206                 : /* php_spintf_appenddouble() {{{ */
     207                 : inline static void
     208                 : 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            2380 : {
     216                 :         char num_buf[NUM_BUF_SIZE];
     217            2380 :         char *s = NULL;
     218            2380 :         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            2380 :         if ((adjust & ADJ_PRECISION) == 0) {
     226            2064 :                 precision = FLOAT_PRECISION;
     227             316 :         } 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            2380 :         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            2340 :         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            2340 :         switch (fmt) {                  
     247                 :                 case 'e':
     248                 :                 case 'E':
     249                 :                 case 'f':
     250                 :                 case 'F':
     251                 : #ifdef HAVE_LOCALE_H
     252            2316 :                         lconv = localeconv();
     253                 : #endif
     254            2316 :                         s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, precision,
     255                 :                                                 (fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     256                 :                                                 &is_negative, &num_buf[1], &s_len);
     257            2316 :                         if (is_negative) {
     258             399 :                                 num_buf[0] = '-';
     259             399 :                                 s = num_buf;
     260             399 :                                 s_len++;
     261            1917 :                         } else if (always_sign) {
     262              36 :                                 num_buf[0] = '+';
     263              36 :                                 s = num_buf;
     264              36 :                                 s_len++;
     265                 :                         }
     266            2316 :                         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            2340 :         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                 : 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            6541 : {
     303                 :         char numbuf[NUM_BUF_SIZE];
     304                 :         register unsigned long num;
     305            6541 :         register unsigned int  i = NUM_BUF_SIZE - 1;
     306            6541 :         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            6541 :         num = (unsigned long) number;
     314            6541 :         numbuf[i] = '\0';
     315                 : 
     316                 :         do {
     317           24142 :                 numbuf[--i] = chartable[(num & andbits)];
     318           24142 :                 num >>= n;
     319                 :         }
     320           24142 :         while (num > 0);
     321                 : 
     322            6541 :         php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     323                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     324                 :                                                          0, expprec, 0);
     325            6541 : }
     326                 : /* }}} */
     327                 : 
     328                 : /* php_spintf_getnumber() {{{ */
     329                 : inline static int
     330                 : php_sprintf_getnumber(char *buffer, int *pos)
     331           10159 : {
     332                 :         char *endptr;
     333           10159 :         register long num = strtol(&buffer[*pos], &endptr, 10);
     334           10159 :         register int i = 0;
     335                 : 
     336           10159 :         if (endptr != NULL) {
     337           10159 :                 i = (endptr - &buffer[*pos]);
     338                 :         }
     339                 :         PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i));
     340           10159 :         *pos += i;
     341                 : 
     342           10159 :         if (num >= INT_MAX || num < 0) {
     343               0 :                 return -1;
     344                 :         } else {
     345           10159 :                 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                 : php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC)
     376           21673 : {
     377                 :         zval ***args, **z_format;
     378           21673 :         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           21673 :         argc = ZEND_NUM_ARGS();
     384                 : 
     385                 :         /* verify the number of args */
     386           21673 :         if ((use_array && argc != (2 + format_offset)) 
     387                 :                         || (!use_array && argc < (1 + format_offset))) {
     388               9 :                 WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
     389                 :         }
     390           21664 :         args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
     391                 : 
     392           21664 :         if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
     393               0 :                 efree(args);
     394               0 :                 WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
     395                 :         }
     396                 :         
     397           21664 :         if (use_array) {
     398             590 :                 int i = 1;
     399                 :                 zval ***newargs;
     400                 :                 zval **array;
     401                 : 
     402             590 :                 z_format = args[format_offset];
     403             590 :                 array = args[1 + format_offset];
     404                 :                 
     405             590 :                 SEPARATE_ZVAL(array);
     406             590 :                 convert_to_array_ex(array);
     407                 :                 
     408             590 :                 argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
     409             590 :                 newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
     410             590 :                 newargs[0] = z_format;
     411                 :                 
     412             590 :                 for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
     413            4386 :                          zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
     414            3206 :                          zend_hash_move_forward(Z_ARRVAL_PP(array)));
     415                 : 
     416             590 :                 efree(args);
     417             590 :                 args = newargs;
     418             590 :                 format_offset = 0;
     419                 :         }
     420                 :         
     421           21664 :         convert_to_string_ex(args[format_offset]);
     422           21664 :         format = Z_STRVAL_PP(args[format_offset]);
     423           21664 :         result = emalloc(size);
     424                 : 
     425           21664 :         currarg = 1;
     426                 : 
     427          241544 :         while (inpos<Z_STRLEN_PP(args[format_offset])) {
     428          198247 :                 int expprec = 0, multiuse = 0;
     429                 :                 zval *tmp;
     430                 : 
     431                 :                 PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
     432                 :                 PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
     433          198247 :                 if (format[inpos] != '%') {
     434          158184 :                         php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
     435           40063 :                 } else if (format[inpos + 1] == '%') {
     436              41 :                         php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
     437              41 :                         inpos += 2;
     438                 :                 } else {
     439                 :                         /* starting a new format specifier, reset variables */
     440           40022 :                         alignment = ALIGN_RIGHT;
     441           40022 :                         adjusting = 0;
     442           40022 :                         padding = ' ';
     443           40022 :                         always_sign = 0;
     444           40022 :                         inpos++;                        /* skip the '%' */
     445                 : 
     446                 :                         PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
     447                 :                                                   format[inpos], inpos));
     448           51432 :                         if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
     449                 :                                 /* first look for argnum */
     450           11412 :                                 temppos = inpos;
     451           11412 :                                 while (isdigit((int)format[temppos])) temppos++;
     452           11412 :                                 if (format[temppos] == '$') {
     453             555 :                                         argnum = php_sprintf_getnumber(format, &inpos);
     454                 : 
     455             555 :                                         if (argnum <= 0) {
     456               2 :                                                 efree(result);
     457               2 :                                                 efree(args);
     458               2 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
     459               2 :                                                 return NULL;
     460                 :                                         }
     461                 : 
     462             553 :                                         multiuse = 1;
     463             553 :                                         inpos++;  /* skip the '$' */
     464                 :                                 } else {
     465           10857 :                                         argnum = currarg++;
     466                 :                                 }
     467                 : 
     468           11410 :                                 argnum += format_offset;
     469                 : 
     470                 :                                 /* after argnum comes modifiers */
     471                 :                                 PRINTF_DEBUG(("sprintf: looking for modifiers\n"
     472                 :                                                           "sprintf: now looking at '%c', inpos=%d\n",
     473                 :                                                           format[inpos], inpos));
     474            6879 :                                 for (;; inpos++) {
     475           23017 :                                         if (format[inpos] == ' ' || format[inpos] == '0') {
     476            4728 :                                                 padding = format[inpos];
     477           13561 :                                         } else if (format[inpos] == '-') {
     478            1415 :                                                 alignment = ALIGN_LEFT;
     479                 :                                                 /* space padding, the default */
     480           12146 :                                         } else if (format[inpos] == '+') {
     481             179 :                                                 always_sign = 1;
     482           11967 :                                         } else if (format[inpos] == '\'') {
     483             557 :                                                 padding = format[++inpos];
     484                 :                                         } else {
     485                 :                                                 PRINTF_DEBUG(("sprintf: end of modifiers\n"));
     486           11410 :                                                 break;
     487                 :                                         }
     488            6879 :                                 }
     489                 :                                 PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
     490                 :                                 PRINTF_DEBUG(("sprintf: alignment=%s\n",
     491                 :                                                           (alignment == ALIGN_LEFT) ? "left" : "right"));
     492                 : 
     493                 : 
     494                 :                                 /* after modifiers comes width */
     495           11410 :                                 if (isdigit((int)format[inpos])) {
     496                 :                                         PRINTF_DEBUG(("sprintf: getting width\n"));
     497            8893 :                                         if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
     498               0 :                                                 efree(result);
     499               0 :                                                 efree(args);
     500               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
     501               0 :                                                 return NULL;
     502                 :                                         }
     503            8893 :                                         adjusting |= ADJ_WIDTH;
     504                 :                                 } else {
     505            2517 :                                         width = 0;
     506                 :                                 }
     507                 :                                 PRINTF_DEBUG(("sprintf: width=%d\n", width));
     508                 : 
     509                 :                                 /* after width and argnum comes precision */
     510           11410 :                                 if (format[inpos] == '.') {
     511             713 :                                         inpos++;
     512                 :                                         PRINTF_DEBUG(("sprintf: getting precision\n"));
     513             713 :                                         if (isdigit((int)format[inpos])) {
     514             711 :                                                 if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
     515               0 :                                                         efree(result);
     516               0 :                                                         efree(args);
     517               0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
     518               0 :                                                         return NULL;
     519                 :                                                 }
     520             711 :                                                 adjusting |= ADJ_PRECISION;
     521             711 :                                                 expprec = 1;
     522                 :                                         } else {
     523               2 :                                                 precision = 0;
     524                 :                                         }
     525                 :                                 } else {
     526           10697 :                                         precision = 0;
     527                 :                                 }
     528                 :                                 PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
     529                 :                         } else {
     530           28610 :                                 width = precision = 0;
     531           28610 :                                 argnum = currarg++ + format_offset;
     532                 :                         }
     533                 : 
     534           40020 :                         if (argnum >= argc) {
     535              29 :                                 efree(result);
     536              29 :                                 efree(args);
     537              29 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
     538              29 :                                 return NULL;
     539                 :                         }
     540                 : 
     541           39991 :                         if (format[inpos] == 'l') {
     542             713 :                                 inpos++;
     543                 :                         }
     544                 :                         PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
     545                 :                         /* now we expect to find a type specifier */
     546           39991 :                         if (multiuse) {
     547             553 :                                 MAKE_STD_ZVAL(tmp);
     548             553 :                                 *tmp = **(args[argnum]);
     549             553 :                                 INIT_PZVAL(tmp);
     550             553 :                                 zval_copy_ctor(tmp);
     551                 :                         } else {
     552           39438 :                                 SEPARATE_ZVAL(args[argnum]);
     553           39438 :                                 tmp = *(args[argnum]);
     554                 :                         }
     555                 : 
     556           39991 :                         switch (format[inpos]) {
     557                 :                                 case 's': {
     558                 :                                         zval *var, var_copy;
     559                 :                                         int use_copy;
     560                 : 
     561            7959 :                                         zend_make_printable_zval(tmp, &var_copy, &use_copy);
     562            7959 :                                         if (use_copy) {
     563             852 :                                                 var = &var_copy;
     564                 :                                         } else {
     565            7107 :                                                 var = tmp;
     566                 :                                         }
     567            7959 :                                         php_sprintf_appendstring(&result, &outpos, &size,
     568                 :                                                                                          Z_STRVAL_P(var),
     569                 :                                                                                          width, precision, padding,
     570                 :                                                                                          alignment,
     571                 :                                                                                          Z_STRLEN_P(var),
     572                 :                                                                                          0, expprec, 0);
     573            7959 :                                         if (use_copy) {
     574             852 :                                                 zval_dtor(&var_copy);
     575                 :                                         }
     576            7959 :                                         break;
     577                 :                                 }
     578                 : 
     579                 :                                 case 'd':
     580           18735 :                                         convert_to_long(tmp);
     581           18735 :                                         php_sprintf_appendint(&result, &outpos, &size,
     582                 :                                                                                   Z_LVAL_P(tmp),
     583                 :                                                                                   width, padding, alignment,
     584                 :                                                                                   always_sign);
     585           18735 :                                         break;
     586                 : 
     587                 :                                 case 'u':
     588             927 :                                         convert_to_long(tmp);
     589             927 :                                         php_sprintf_appenduint(&result, &outpos, &size,
     590                 :                                                                                   Z_LVAL_P(tmp),
     591                 :                                                                                   width, padding, alignment);
     592             927 :                                         break;
     593                 : 
     594                 :                                 case 'g':
     595                 :                                 case 'G':
     596                 :                                 case 'e':
     597                 :                                 case 'E':
     598                 :                                 case 'f':
     599                 :                                 case 'F':
     600            2380 :                                         convert_to_double(tmp);
     601            2380 :                                         php_sprintf_appenddouble(&result, &outpos, &size,
     602                 :                                                                                          Z_DVAL_P(tmp),
     603                 :                                                                                          width, padding, alignment,
     604                 :                                                                                          precision, adjusting,
     605                 :                                                                                          format[inpos], always_sign
     606                 :                                                                                          TSRMLS_CC);
     607            2380 :                                         break;
     608                 :                                         
     609                 :                                 case 'c':
     610             997 :                                         convert_to_long(tmp);
     611             997 :                                         php_sprintf_appendchar(&result, &outpos, &size,
     612                 :                                                                                 (char) Z_LVAL_P(tmp) TSRMLS_CC);
     613             997 :                                         break;
     614                 : 
     615                 :                                 case 'o':
     616            4058 :                                         convert_to_long(tmp);
     617            4058 :                                         php_sprintf_append2n(&result, &outpos, &size,
     618                 :                                                                                  Z_LVAL_P(tmp),
     619                 :                                                                                  width, padding, alignment, 3,
     620                 :                                                                                  hexchars, expprec);
     621            4058 :                                         break;
     622                 : 
     623                 :                                 case 'x':
     624            2097 :                                         convert_to_long(tmp);
     625            2097 :                                         php_sprintf_append2n(&result, &outpos, &size,
     626                 :                                                                                  Z_LVAL_P(tmp),
     627                 :                                                                                  width, padding, alignment, 4,
     628                 :                                                                                  hexchars, expprec);
     629            2097 :                                         break;
     630                 : 
     631                 :                                 case 'X':
     632             319 :                                         convert_to_long(tmp);
     633             319 :                                         php_sprintf_append2n(&result, &outpos, &size,
     634                 :                                                                                  Z_LVAL_P(tmp),
     635                 :                                                                                  width, padding, alignment, 4,
     636                 :                                                                                  HEXCHARS, expprec);
     637             319 :                                         break;
     638                 : 
     639                 :                                 case 'b':
     640              67 :                                         convert_to_long(tmp);
     641              67 :                                         php_sprintf_append2n(&result, &outpos, &size,
     642                 :                                                                                  Z_LVAL_P(tmp),
     643                 :                                                                                  width, padding, alignment, 1,
     644                 :                                                                                  hexchars, expprec);
     645              67 :                                         break;
     646                 : 
     647                 :                                 case '%':
     648              12 :                                         php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
     649                 : 
     650                 :                                         break;
     651                 :                                 default:
     652                 :                                         break;
     653                 :                         }
     654           39991 :                         if (multiuse) {
     655             553 :                                 zval_ptr_dtor(&tmp);
     656                 :                         }
     657           39991 :                         inpos++;
     658                 :                 }
     659                 :         }
     660                 :         
     661           21633 :         efree(args);
     662                 :         
     663                 :         /* possibly, we have to make sure we have room for the terminating null? */
     664           21633 :         result[outpos]=0;
     665           21633 :         *len = outpos;  
     666           21633 :         return result;
     667                 : }
     668                 : /* }}} */
     669                 : 
     670                 : /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]])
     671                 :    Return a formatted string */
     672                 : PHP_FUNCTION(user_sprintf)
     673           11438 : {
     674                 :         char *result;
     675                 :         int len;
     676                 :         
     677           11438 :         if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
     678               7 :                 RETURN_FALSE;
     679                 :         }
     680           11431 :         RETVAL_STRINGL(result, len, 0);
     681                 : }
     682                 : /* }}} */
     683                 : 
     684                 : /* {{{ proto string vsprintf(string format, array args)
     685                 :    Return a formatted string */
     686                 : PHP_FUNCTION(vsprintf)
     687             204 : {
     688                 :         char *result;
     689                 :         int len;
     690                 :         
     691             204 :         if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
     692               8 :                 RETURN_FALSE;
     693                 :         }
     694             196 :         RETVAL_STRINGL(result, len, 0);
     695                 : }
     696                 : /* }}} */
     697                 : 
     698                 : /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]])
     699                 :    Output a formatted string */
     700                 : PHP_FUNCTION(user_printf)
     701            7879 : {
     702                 :         char *result;
     703                 :         int len, rlen;
     704                 :         
     705            7879 :         if ((result=php_formatted_print(ht, &len, 0, 0 TSRMLS_CC))==NULL) {
     706              10 :                 RETURN_FALSE;
     707                 :         }
     708            7869 :         rlen = PHPWRITE(result, len);
     709            7869 :         efree(result);
     710            7869 :         RETURN_LONG(rlen);
     711                 : }
     712                 : /* }}} */
     713                 : 
     714                 : /* {{{ proto int vprintf(string format, array args)
     715                 :    Output a formatted string */
     716                 : PHP_FUNCTION(vprintf)
     717             189 : {
     718                 :         char *result;
     719                 :         int len, rlen;
     720                 :         
     721             189 :         if ((result=php_formatted_print(ht, &len, 1, 0 TSRMLS_CC))==NULL) {
     722               8 :                 RETURN_FALSE;
     723                 :         }
     724             181 :         rlen = PHPWRITE(result, len);
     725             181 :         efree(result);
     726             181 :         RETURN_LONG(rlen);
     727                 : }
     728                 : /* }}} */
     729                 : 
     730                 : /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]])
     731                 :    Output a formatted string into a stream */
     732                 : PHP_FUNCTION(fprintf)
     733            1763 : {
     734                 :         php_stream *stream;
     735                 :         zval **arg1;
     736                 :         char *result;
     737                 :         int len;
     738                 :         
     739            1763 :         if (ZEND_NUM_ARGS() < 2) {
     740               3 :                 WRONG_PARAM_COUNT;
     741                 :         }
     742                 :         
     743            1760 :         if (zend_get_parameters_ex(1, &arg1)==FAILURE) {
     744               0 :                 RETURN_FALSE;
     745                 :         }
     746                 :         
     747            1760 :         php_stream_from_zval(stream, arg1);
     748                 : 
     749            1760 :         if ((result=php_formatted_print(ht, &len, 0, 1 TSRMLS_CC))==NULL) {
     750               1 :                 RETURN_FALSE;
     751                 :         }
     752                 : 
     753            1759 :         php_stream_write(stream, result, len);
     754                 : 
     755            1759 :         efree(result);
     756                 : 
     757            1759 :         RETURN_LONG(len);
     758                 : }
     759                 : /* }}} */
     760                 : 
     761                 : /* {{{ proto int vfprintf(resource stream, string format, array args)
     762                 :    Output a formatted string into a stream */
     763                 : PHP_FUNCTION(vfprintf)
     764             211 : {
     765                 :         php_stream *stream;
     766                 :         zval **arg1;
     767                 :         char *result;
     768                 :         int len;
     769                 :         
     770             211 :         if (ZEND_NUM_ARGS() != 3) {
     771               5 :                 WRONG_PARAM_COUNT;
     772                 :         }
     773                 :         
     774             206 :         if (zend_get_parameters_ex(1, &arg1)==FAILURE) {
     775               0 :                 RETURN_FALSE;
     776                 :         }
     777                 :         
     778             206 :         php_stream_from_zval(stream, arg1);
     779                 : 
     780             203 :         if ((result=php_formatted_print(ht, &len, 1, 1 TSRMLS_CC))==NULL) {
     781               6 :                 RETURN_FALSE;
     782                 :         }
     783                 : 
     784             197 :         php_stream_write(stream, result, len);
     785                 : 
     786             197 :         efree(result);
     787                 : 
     788             197 :         RETURN_LONG(len);
     789                 : }
     790                 : /* }}} */
     791                 : 
     792                 : /*
     793                 :  * Local variables:
     794                 :  * tab-width: 4
     795                 :  * c-basic-offset: 4
     796                 :  * End:
     797                 :  * vim600: sw=4 ts=4 fdm=marker
     798                 :  * vim<600: sw=4 ts=4
     799                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:23 +0000 (5 days ago)

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