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

Generated by: LCOV version 1.10

Generated at Thu, 10 Apr 2014 08:53:58 +0000 (7 days ago)

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