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-23 Instrumented lines: 611
Code covered: 52.4 % Executed lines: 320
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       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                 : #define PHP_OUTPUT 0
      47                 : #define PHP_RUNTIME 1
      48                 : 
      49                 : #if 0
      50                 : /* trick to control varargs functions through cpp */
      51                 : # define PRINTF_DEBUG(arg) php_printf arg
      52                 : #else
      53                 : # define PRINTF_DEBUG(arg)
      54                 : #endif
      55                 : 
      56                 : static char hexchars[] = "0123456789abcdef";
      57                 : static char HEXCHARS[] = "0123456789ABCDEF";
      58                 : 
      59                 : static UChar u_hexchars[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
      60                 : static UChar u_HEXCHARS[] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
      61                 : 
      62                 : /* php_sprintf_appendchar() {{{ */
      63                 : inline static void
      64                 : php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
      65               0 : {
      66               0 :         if ((*pos + 1) >= *size) {
      67               0 :                 *size <<= 1;
      68                 :                 PRINTF_DEBUG(("%s(): ereallocing buffer to %d bytes\n", get_active_function_name(TSRMLS_C), *size));
      69               0 :                 *buffer = erealloc(*buffer, *size);
      70                 :         }
      71                 :         PRINTF_DEBUG(("sprintf: appending '%c', pos=\n", add, *pos));
      72               0 :         (*buffer)[(*pos)++] = add;
      73               0 : }
      74                 : /* }}} */
      75                 : 
      76                 : /* php_u_sprintf_appendchar() {{{ */
      77                 : inline static void
      78                 : php_u_sprintf_appendchar(UChar **buffer, int *pos, int *size, UChar add TSRMLS_DC)
      79          857101 : {
      80          857101 :         if ((*pos + 1) >= *size) {
      81               0 :                 *size <<= 1;
      82               0 :                 *buffer = eurealloc(*buffer, *size);
      83                 :         }
      84          857101 :         (*buffer)[(*pos)++] = add;
      85          857101 : }
      86                 : /* }}} */
      87                 : 
      88                 : /* php_sprintf_appendstring() {{{ */
      89                 : inline static void
      90                 : php_sprintf_appendstring(char **buffer, int *pos, int *size, char *add,
      91                 :                                                    int min_width, int max_width, char padding,
      92                 :                                                    int alignment, int len, int neg, int expprec, int always_sign)
      93               0 : {
      94                 :         register int npad;
      95                 :         int req_size;
      96                 :         int copy_len;
      97                 :         int m_width;
      98                 : 
      99               0 :         copy_len = (expprec ? MIN(max_width, len) : len);
     100               0 :         npad = min_width - copy_len;
     101                 : 
     102               0 :         if (npad < 0) {
     103               0 :                 npad = 0;
     104                 :         }
     105                 :         
     106                 :         PRINTF_DEBUG(("sprintf: appendstring(%x, %d, %d, \"%s\", %d, '%c', %d)\n",
     107                 :                                   *buffer, *pos, *size, add, min_width, padding, alignment));
     108               0 :         m_width = MAX(min_width, copy_len);
     109                 : 
     110               0 :         if(m_width > INT_MAX - *pos - 1) {
     111               0 :                 zend_error_noreturn(E_ERROR, "Field width %d is too long", m_width);
     112                 :         }
     113                 : 
     114               0 :         req_size = *pos + m_width + 1;
     115                 : 
     116               0 :         if (req_size > *size) {
     117               0 :                 while (req_size > *size) {
     118               0 :                         if(*size > INT_MAX/2) {
     119               0 :                                 zend_error_noreturn(E_ERROR, "Field width %d is too long", req_size); 
     120                 :                         }
     121               0 :                         *size <<= 1;
     122                 :                 }
     123                 :                 PRINTF_DEBUG(("sprintf ereallocing buffer to %d bytes\n", *size));
     124               0 :                 *buffer = erealloc(*buffer, *size);
     125                 :         }
     126               0 :         if (alignment == ALIGN_RIGHT) {
     127               0 :                 if ((neg || always_sign) && padding=='0') {
     128               0 :                         (*buffer)[(*pos)++] = (neg) ? '-' : '+';
     129               0 :                         add++;
     130               0 :                         len--;
     131               0 :                         copy_len--;
     132                 :                 }
     133               0 :                 while (npad-- > 0) {
     134               0 :                         (*buffer)[(*pos)++] = padding;
     135                 :                 }
     136                 :         }
     137                 :         PRINTF_DEBUG(("sprintf: appending \"%s\"\n", add));
     138               0 :         memcpy(&(*buffer)[*pos], add, copy_len + 1);
     139               0 :         *pos += copy_len;
     140               0 :         if (alignment == ALIGN_LEFT) {
     141               0 :                 while (npad--) {
     142               0 :                         (*buffer)[(*pos)++] = padding;
     143                 :                 }
     144                 :         }
     145               0 : }
     146                 : /* }}} */
     147                 : 
     148                 : /* php_u_sprintf_appendstring() {{{ */
     149                 : inline static void
     150                 : php_u_sprintf_appendstring(UChar **buffer, int *pos, int *size, UChar *add,
     151                 :                                                    int min_width, int max_width, UChar padding,
     152                 :                                                    int alignment, int len, int neg, int expprec, int always_sign)
     153          109656 : {
     154                 :         register int npad;
     155                 :         int req_size;
     156                 :         int copy_len;
     157                 : 
     158          109656 :         copy_len = (expprec ? MIN(max_width, len) : len);
     159          109656 :         npad = min_width - copy_len;
     160                 : 
     161          109656 :         if (npad < 0) {
     162           70874 :                 npad = 0;
     163                 :         }
     164                 :         
     165          109656 :         req_size = *pos + MAX(min_width, copy_len) + 1;
     166                 : 
     167          109656 :         if (req_size > *size) {
     168            6335 :                 while (req_size > *size) {
     169            2147 :                         *size <<= 1;
     170                 :                 }
     171            2094 :                 *buffer = eurealloc(*buffer, *size);
     172                 :         }
     173          109656 :         if (alignment == ALIGN_RIGHT) {
     174          108301 :                 if ((neg || always_sign) && padding == 0x30 /* '0' */) {
     175              36 :                         (*buffer)[(*pos)++] = (neg) ? 0x2D /* '-' */ : 0x2B /* '+' */;
     176              36 :                         add++;
     177              36 :                         len--;
     178              36 :                         copy_len--;
     179                 :                 }
     180          255412 :                 while (npad-- > 0) {
     181           38810 :                         (*buffer)[(*pos)++] = padding;
     182                 :                 }
     183                 :         }
     184          109656 :         u_memcpy(&(*buffer)[*pos], add, copy_len + 1);
     185          109656 :         *pos += copy_len;
     186          109656 :         if (alignment == ALIGN_LEFT) {
     187            6478 :                 while (npad--) {
     188            3768 :                         (*buffer)[(*pos)++] = padding;
     189                 :                 }
     190                 :         }
     191          109656 : }
     192                 : /* }}} */
     193                 : 
     194                 : /* php_sprintf_appendint() {{{ */ 
     195                 : inline static void
     196                 : php_sprintf_appendint(char **buffer, int *pos, int *size, long number, 
     197                 :                                                 int width, char padding, int alignment, 
     198                 :                                                 int always_sign)
     199               0 : {
     200                 :         char numbuf[NUM_BUF_SIZE];
     201                 :         register unsigned long magn, nmagn;
     202               0 :         register unsigned int i = NUM_BUF_SIZE - 1, neg = 0;
     203                 : 
     204                 :         PRINTF_DEBUG(("sprintf: appendint(%x, %x, %x, %d, %d, '%c', %d)\n",
     205                 :                                   *buffer, pos, size, number, width, padding, alignment));
     206               0 :         if (number < 0) {
     207               0 :                 neg = 1;
     208               0 :                 magn = ((unsigned long) -(number + 1)) + 1;
     209                 :         } else {
     210               0 :                 magn = (unsigned long) number;
     211                 :         }
     212                 : 
     213                 :         /* Can't right-pad 0's on integers */
     214               0 :         if(alignment==0 && padding=='0') padding=' ';
     215                 : 
     216               0 :         numbuf[i] = '\0';
     217                 : 
     218                 :         do {
     219               0 :                 nmagn = magn / 10;
     220                 : 
     221               0 :                 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
     222               0 :                 magn = nmagn;
     223                 :         }
     224               0 :         while (magn > 0 && i > 0);
     225               0 :         if (neg) {
     226               0 :                 numbuf[--i] = '-';
     227               0 :         } else if (always_sign) {
     228               0 :                 numbuf[--i] = '+';
     229                 :         }
     230                 :         PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n",
     231                 :                                   number, &numbuf[i], i));
     232               0 :         php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     233                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     234                 :                                                          neg, 0, always_sign);
     235               0 : }
     236                 : /* }}} */
     237                 : 
     238                 : /* php_u_sprintf_appendint() {{{ */ 
     239                 : inline static void
     240                 : php_u_sprintf_appendint(UChar **buffer, int *pos, int *size, long number, 
     241                 :                                                 int width, UChar padding, int alignment, 
     242                 :                                                 int always_sign)
     243           76152 : {
     244                 :         UChar numbuf[NUM_BUF_SIZE];
     245                 :         register unsigned long magn, nmagn;
     246           76152 :         register unsigned int i = NUM_BUF_SIZE - 1, neg = 0;
     247                 : 
     248           76152 :         if (number < 0) {
     249             699 :                 neg = 1;
     250             699 :                 magn = ((unsigned long) -(number + 1)) + 1;
     251                 :         } else {
     252           75453 :                 magn = (unsigned long) number;
     253                 :         }
     254                 : 
     255                 :         /* Can't right-pad 0's on integers */
     256           76152 :         if (alignment==0 && padding== 0x30 /* '0' */) padding = 0x20 /* ' ' */;
     257                 : 
     258           76152 :         numbuf[i] = 0x0A /* '\0' */;
     259                 : 
     260                 :         do {
     261          235451 :                 nmagn = magn / 10;
     262                 : 
     263          235451 :                 numbuf[--i] = (UChar)(magn - (nmagn * 10)) + 0x30 /* '0' */;
     264          235451 :                 magn = nmagn;
     265                 :         }
     266          235451 :         while (magn > 0 && i > 0);
     267           76152 :         if (neg) {
     268             699 :                 numbuf[--i] = 0x2D /* '-' */;
     269           75453 :         } else if (always_sign) {
     270              24 :                 numbuf[--i] = 0x2B /* '+' */;
     271                 :         }
     272           76152 :         php_u_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     273                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     274                 :                                                          neg, 0, always_sign);
     275           76152 : }
     276                 : /* }}} */
     277                 : 
     278                 : /* php_sprintf_appenduint() {{{ */
     279                 : inline static void
     280                 : php_sprintf_appenduint(char **buffer, int *pos, int *size,
     281                 :                                            unsigned long number,
     282                 :                                            int width, char padding, int alignment)
     283               0 : {
     284                 :         char numbuf[NUM_BUF_SIZE];
     285                 :         register unsigned long magn, nmagn;
     286               0 :         register unsigned int i = NUM_BUF_SIZE - 1;
     287                 : 
     288                 :         PRINTF_DEBUG(("sprintf: appenduint(%x, %x, %x, %d, %d, '%c', %d)\n",
     289                 :                                   *buffer, pos, size, number, width, padding, alignment));
     290               0 :         magn = (unsigned long) number;
     291                 : 
     292                 :         /* Can't right-pad 0's on integers */
     293               0 :         if (alignment == 0 && padding == '0') padding = ' ';
     294                 : 
     295               0 :         numbuf[i] = '\0';
     296                 : 
     297                 :         do {
     298               0 :                 nmagn = magn / 10;
     299                 : 
     300               0 :                 numbuf[--i] = (unsigned char)(magn - (nmagn * 10)) + '0';
     301               0 :                 magn = nmagn;
     302               0 :         } while (magn > 0 && i > 0);
     303                 : 
     304                 :         PRINTF_DEBUG(("sprintf: appending %d as \"%s\", i=%d\n", number, &numbuf[i], i));
     305               0 :         php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     306                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
     307               0 : }
     308                 : /* }}} */
     309                 : 
     310                 : /* php_u_sprintf_appenduint() {{{ */
     311                 : inline static void
     312                 : php_u_sprintf_appenduint(UChar **buffer, int *pos, int *size,
     313                 :                                            unsigned long number,
     314                 :                                            int width, UChar padding, int alignment)
     315             927 : {
     316                 :         UChar numbuf[NUM_BUF_SIZE];
     317                 :         register unsigned long magn, nmagn;
     318             927 :         register unsigned int i = NUM_BUF_SIZE - 1;
     319                 : 
     320             927 :         magn = (unsigned long) number;
     321                 : 
     322                 :         /* Can't right-pad 0's on integers */
     323             927 :         if (alignment == 0 && padding == 0x30 /* '0' */) padding = 0x20 /* ' ' */;
     324                 : 
     325             927 :         numbuf[i] = 0x0A /* '\0' */;
     326                 : 
     327                 :         do {
     328            3300 :                 nmagn = magn / 10;
     329                 : 
     330            3300 :                 numbuf[--i] = (UChar)(magn - (nmagn * 10)) + 0x30 /* '0' */;
     331            3300 :                 magn = nmagn;
     332            3300 :         } while (magn > 0 && i > 0);
     333                 : 
     334             927 :         php_u_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     335                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i, 0, 0, 0);
     336             927 : }
     337                 : /* }}} */
     338                 : 
     339                 : /* php_sprintf_appenddouble() {{{ */
     340                 : inline static void
     341                 : php_sprintf_appenddouble(char **buffer, int *pos,
     342                 :                                                  int *size, double number,
     343                 :                                                  int width, char padding,
     344                 :                                                  int alignment, int precision,
     345                 :                                                  int adjust, char fmt,
     346                 :                                                  int always_sign
     347                 :                                                  TSRMLS_DC)
     348               0 : {
     349                 :         char num_buf[NUM_BUF_SIZE];
     350               0 :         char *s = NULL;
     351               0 :         int s_len = 0, is_negative = 0;
     352                 : #ifdef HAVE_LOCALE_H
     353                 :         struct lconv *lconv;
     354                 : #endif
     355                 : 
     356                 :         PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
     357                 :                                   *buffer, pos, size, number, width, padding, alignment, fmt));
     358               0 :         if ((adjust & ADJ_PRECISION) == 0) {
     359               0 :                 precision = FLOAT_PRECISION;
     360               0 :         } else if (precision > MAX_FLOAT_PRECISION) {
     361               0 :                 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);
     362               0 :                 precision = MAX_FLOAT_PRECISION;
     363                 :         }
     364                 :         
     365               0 :         if (zend_isnan(number)) {
     366               0 :                 is_negative = (number<0);
     367               0 :                 php_sprintf_appendstring(buffer, pos, size, "NaN", 3, 0, padding,
     368                 :                                                                  alignment, 3, is_negative, 0, always_sign);
     369               0 :                 return;
     370                 :         }
     371                 : 
     372               0 :         if (zend_isinf(number)) {
     373               0 :                 is_negative = (number<0);
     374               0 :                 php_sprintf_appendstring(buffer, pos, size, "INF", 3, 0, padding,
     375                 :                                                                  alignment, 3, is_negative, 0, always_sign);
     376               0 :                 return;
     377                 :         }
     378                 : 
     379               0 :         switch (fmt) {          
     380                 :                 case 'e':
     381                 :                 case 'E':
     382                 :                 case 'f':
     383                 :                 case 'F':
     384                 : #ifdef HAVE_LOCALE_H
     385               0 :                         lconv = localeconv();
     386                 : #endif
     387               0 :                         s = php_conv_fp((fmt == 'f')?'F':fmt, number, NO, precision,
     388                 :                                                         (fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     389                 :                                                         &is_negative, &num_buf[1], &s_len);
     390               0 :                         if (is_negative) {
     391               0 :                                 num_buf[0] = '-';
     392               0 :                                 s = num_buf;
     393               0 :                                 s_len++;
     394               0 :                         } else if (always_sign) {
     395               0 :                                 num_buf[0] = '+';
     396               0 :                                 s = num_buf;
     397               0 :                                 s_len++;
     398                 :                         }
     399               0 :                         break;
     400                 : 
     401                 :                 case 'g':
     402                 :                 case 'G':
     403               0 :                         if (precision == 0)
     404               0 :                                 precision = 1;
     405                 :                         /*
     406                 :                          * * We use &num_buf[ 1 ], so that we have room for the sign
     407                 :                          */
     408                 : #ifdef HAVE_LOCALE_H
     409               0 :                         lconv = localeconv();
     410                 : #endif
     411               0 :                         s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (fmt == 'G')?'E':'e', &num_buf[1]);
     412               0 :                         is_negative = 0;
     413               0 :                         if (*s == '-') {
     414               0 :                                 is_negative = 1;
     415               0 :                                 s = &num_buf[1];
     416               0 :                         } else if (always_sign) {
     417               0 :                                 num_buf[0] = '+';
     418               0 :                                 s = num_buf;
     419                 :                         }
     420                 : 
     421               0 :                         s_len = strlen(s);
     422                 :                         break;
     423                 :         }
     424                 : 
     425               0 :         php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding,
     426                 :                                                          alignment, s_len, is_negative, 0, always_sign);
     427                 : }
     428                 : /* }}} */
     429                 : 
     430                 : /* php_u_sprintf_appenddouble() {{{ */
     431                 : inline static void
     432                 : php_u_sprintf_appenddouble(UChar **buffer, int *pos,
     433                 :                                                  int *size, double number,
     434                 :                                                  int width, UChar padding,
     435                 :                                                  int alignment, int precision,
     436                 :                                                  int adjust, UChar fmt,
     437                 :                                                  int always_sign
     438                 :                                                  TSRMLS_DC)
     439            3776 : {
     440                 :         char num_buf[NUM_BUF_SIZE];
     441            3776 :         char *s = NULL, s_fmt;
     442                 :         UChar *uni_s;
     443            3776 :         int s_len = 0, is_negative = 0;
     444                 : #ifdef HAVE_LOCALE_H
     445                 :         struct lconv *lconv;
     446                 : #endif
     447                 : 
     448            3776 :         if ((adjust & ADJ_PRECISION) == 0) {
     449            3463 :                 precision = FLOAT_PRECISION;
     450             313 :         } else if (precision > MAX_FLOAT_PRECISION) {
     451               2 :                 precision = MAX_FLOAT_PRECISION;
     452                 :         }
     453                 :         
     454            3776 :         if (zend_isnan(number)) {
     455              40 :                 UChar *nan = USTR_MAKE("NaN");
     456              40 :                 is_negative = (number<0);
     457              40 :                 php_u_sprintf_appendstring(buffer, pos, size, nan, 3, 0, padding,
     458                 :                                                                  alignment, 3, is_negative, 0, always_sign);
     459              40 :                 efree(nan);
     460              40 :                 return;
     461                 :         }
     462                 : 
     463            3736 :         if (zend_isinf(number)) {
     464               0 :                 UChar *inf = USTR_MAKE("INF");
     465               0 :                 is_negative = (number<0);
     466               0 :                 php_u_sprintf_appendstring(buffer, pos, size, inf, 3, 0, padding,
     467                 :                                                                  alignment, 3, is_negative, 0, always_sign);
     468               0 :                 efree(inf);
     469               0 :                 return;
     470                 :         }
     471                 : 
     472            3736 :         switch (fmt) {
     473                 :                 case 0x66 /* 'f' */:
     474            2691 :                         s_fmt = 'f';
     475            2691 :                         break;
     476                 :                 case 0x46 /* 'F' */:
     477              51 :                         s_fmt = 'F';
     478              51 :                         break;
     479                 :                 case 0x65 /* 'e' */:
     480             953 :                         s_fmt = 'e';
     481             953 :                         break;
     482                 :                 case 0x45 /* 'E' */:
     483              17 :                         s_fmt = 'E';
     484              17 :                         break;
     485                 :                 case 0x67 /* 'g' */:
     486              12 :                         s_fmt = 'g';
     487              12 :                         break;
     488                 :                 case 0x47 /* 'G' */:
     489              12 :                         s_fmt = 'G';
     490                 :                         break;
     491                 :         }
     492                 : 
     493            3736 :         switch (fmt) {          
     494                 :                 case 0x65 /* 'e' */:
     495                 :                 case 0x45 /* 'E' */:
     496                 :                 case 0x46 /* 'F' */:
     497                 :                 case 0x66 /* 'f' */:
     498                 : #ifdef HAVE_LOCALE_H
     499            3712 :                         lconv = localeconv();
     500                 : #endif
     501            3712 :                         s = php_conv_fp((s_fmt == 'f')?'F':s_fmt, number, NO, precision,
     502                 :                                                         (s_fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     503                 :                                                         &is_negative, &num_buf[1], &s_len);
     504            3712 :                         if (is_negative) {
     505             872 :                                 num_buf[0] = '-';
     506             872 :                                 s = num_buf;
     507             872 :                                 s_len++;
     508            2840 :                         } else if (always_sign) {
     509              36 :                                 num_buf[0] = '+';
     510              36 :                                 s = num_buf;
     511              36 :                                 s_len++;
     512                 :                         }
     513            3712 :                         break;
     514                 : 
     515                 :                 case 0x67 /* 'g' */:
     516                 :                 case 0x47 /* 'G' */:
     517              24 :                         if (precision == 0)
     518               4 :                                 precision = 1;
     519                 :                         /*
     520                 :                          * * We use &num_buf[ 1 ], so that we have room for the sign
     521                 :                          */
     522                 : #ifdef HAVE_LOCALE_H
     523              24 :                         lconv = localeconv();
     524                 : #endif
     525              24 :                         s = php_gcvt(number, precision, LCONV_DECIMAL_POINT, (s_fmt == 'G')?'E':'e', &num_buf[1]);
     526              24 :                         is_negative = 0;
     527              24 :                         if (*s == '-') {
     528              12 :                                 is_negative = 1;
     529              12 :                                 s = &num_buf[1];
     530              12 :                         } else if (always_sign) {
     531               4 :                                 num_buf[0] = '+';
     532               4 :                                 s = num_buf;
     533                 :                         }
     534                 : 
     535              24 :                         s_len = strlen(s);
     536                 :                         break;
     537                 :         }
     538                 : 
     539            3736 :         uni_s = zend_ascii_to_unicode(s, s_len + 1 ZEND_FILE_LINE_CC);
     540            3736 :         php_u_sprintf_appendstring(buffer, pos, size, uni_s, width, 0, padding,
     541                 :                                                          alignment, s_len, is_negative, 0, always_sign);
     542            3736 :         efree(uni_s);
     543                 : }
     544                 : /* }}} */
     545                 : 
     546                 : /* php_sprintf_append2n() {{{ */
     547                 : inline static void
     548                 : php_sprintf_append2n(char **buffer, int *pos, int *size, long number,
     549                 :                                          int width, char padding, int alignment, int n,
     550                 :                                          char *chartable, int expprec)
     551               0 : {
     552                 :         char numbuf[NUM_BUF_SIZE];
     553                 :         register unsigned long num;
     554               0 :         register unsigned int  i = NUM_BUF_SIZE - 1;
     555               0 :         register int andbits = (1 << n) - 1;
     556                 : 
     557                 :         PRINTF_DEBUG(("sprintf: append2n(%x, %x, %x, %d, %d, '%c', %d, %d, %x)\n",
     558                 :                                   *buffer, pos, size, number, width, padding, alignment, n,
     559                 :                                   chartable));
     560                 :         PRINTF_DEBUG(("sprintf: append2n 2^%d andbits=%x\n", n, andbits));
     561                 : 
     562               0 :         num = (unsigned long) number;
     563               0 :         numbuf[i] = '\0';
     564                 : 
     565                 :         do {
     566               0 :                 numbuf[--i] = chartable[(num & andbits)];
     567               0 :                 num >>= n;
     568                 :         }
     569               0 :         while (num > 0);
     570                 : 
     571               0 :         php_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     572                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     573                 :                                                          0, expprec, 0);
     574               0 : }
     575                 : /* }}} */
     576                 : 
     577                 : /* php_u_sprintf_append2n() {{{ */
     578                 : inline static void
     579                 : php_u_sprintf_append2n(UChar **buffer, int *pos, int *size, long number,
     580                 :                                          int width, UChar padding, int alignment, int n,
     581                 :                                          UChar *chartable, int expprec)
     582            5435 : {
     583                 :         UChar numbuf[NUM_BUF_SIZE];
     584                 :         register unsigned long num;
     585            5435 :         register unsigned int  i = NUM_BUF_SIZE - 1;
     586            5435 :         register int andbits = (1 << n) - 1;
     587                 : 
     588            5435 :         num = (unsigned long) number;
     589            5435 :         numbuf[i] = '\0';
     590                 : 
     591                 :         do {
     592           21912 :                 numbuf[--i] = chartable[(num & andbits)];
     593           21912 :                 num >>= n;
     594                 :         }
     595           21912 :         while (num > 0);
     596                 : 
     597            5435 :         php_u_sprintf_appendstring(buffer, pos, size, &numbuf[i], width, 0,
     598                 :                                                          padding, alignment, (NUM_BUF_SIZE - 1) - i,
     599                 :                                                          0, expprec, 0);
     600            5435 : }
     601                 : /* }}} */
     602                 : 
     603                 : /* php_sprintf_getnumber() {{{ */
     604                 : inline static int
     605                 : php_sprintf_getnumber(char *buffer, int *pos)
     606               0 : {
     607                 :         char *endptr;
     608               0 :         register long num = strtol(&buffer[*pos], &endptr, 10);
     609               0 :         register int i = 0;
     610                 : 
     611               0 :         if (endptr != NULL) {
     612               0 :                 i = (endptr - &buffer[*pos]);
     613                 :         }
     614                 :         PRINTF_DEBUG(("sprintf_getnumber: number was %d bytes long\n", i));
     615               0 :         *pos += i;
     616                 : 
     617               0 :         if (num >= INT_MAX || num < 0) {
     618               0 :                 return -1;
     619                 :         } else {
     620               0 :                 return (int) num;
     621                 :         }
     622                 : }
     623                 : /* }}} */
     624                 : 
     625                 : /* php_u_sprintf_getnumber() {{{ */
     626                 : inline static long
     627                 : php_u_sprintf_getnumber(UChar *buffer, int *pos) 
     628           60579 : {
     629                 :         UChar *endptr;
     630           60579 :         register long num = zend_u_strtol(&buffer[*pos], &endptr, 10);
     631           60579 :         register int i = 0;
     632                 : 
     633           60579 :         if (endptr != NULL) {
     634           60579 :                 i = (endptr - &buffer[*pos]);
     635                 :         }
     636           60579 :         *pos += i;
     637           60579 :         return num;
     638                 : }
     639                 : /* }}} */
     640                 : 
     641                 : /* {{{ php_formatted_print()
     642                 :  * New sprintf implementation for PHP.
     643                 :  *
     644                 :  * Modifiers:
     645                 :  *
     646                 :  *  " "   pad integers with spaces
     647                 :  *  "-"   left adjusted field
     648                 :  *   n    field size
     649                 :  *  "."n  precision (floats only)
     650                 :  *  "+"   Always place a sign (+ or -) in front of a number
     651                 :  *
     652                 :  * Type specifiers:
     653                 :  *
     654                 :  *  "%"   literal "%", modifiers are ignored.
     655                 :  *  "b"   integer argument is printed as binary
     656                 :  *  "c"   integer argument is printed as a single character
     657                 :  *  "d"   argument is an integer
     658                 :  *  "f"   the argument is a float
     659                 :  *  "o"   integer argument is printed as octal
     660                 :  *  "s"   argument is a string
     661                 :  *  "x"   integer argument is printed as lowercase hexadecimal
     662                 :  *  "X"   integer argument is printed as uppercase hexadecimal
     663                 :  *
     664                 :  */
     665                 : static char * php_formatted_print(int ht, int *len, int use_array, int format_offset, int type TSRMLS_DC)
     666               0 : {
     667                 :         zval ***args, **z_format;
     668               0 :         int argc, size = 240, inpos = 0, outpos = 0, temppos;
     669                 :         int alignment, currarg, adjusting, argnum, width, precision;
     670                 :         char *format, *result, padding;
     671                 :         int always_sign;
     672                 : 
     673               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
     674               0 :                 return NULL;
     675                 :         }
     676                 : 
     677                 :         /* verify the number of args */
     678               0 :         if ((use_array && argc != (2 + format_offset)) 
     679                 :                         || (!use_array && argc < (1 + format_offset))) {
     680               0 :                 efree(args);
     681               0 :                 WRONG_PARAM_COUNT_WITH_RETVAL(NULL);
     682                 :         }
     683                 :         
     684               0 :         if (use_array) {
     685               0 :                 int i = 1;
     686                 :                 zval ***newargs;
     687                 :                 zval **array;
     688                 : 
     689               0 :                 z_format = args[format_offset];
     690               0 :                 array = args[1 + format_offset];
     691                 :                 
     692               0 :                 SEPARATE_ZVAL(array);
     693               0 :                 convert_to_array_ex(array);
     694                 :                 
     695               0 :                 argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
     696               0 :                 newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
     697               0 :                 newargs[0] = z_format;
     698                 :                 
     699               0 :                 for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
     700               0 :                          zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
     701               0 :                          zend_hash_move_forward(Z_ARRVAL_PP(array)));
     702                 : 
     703               0 :                 efree(args);
     704               0 :                 args = newargs;
     705               0 :                 format_offset = 0;
     706                 :         }
     707                 :         
     708               0 :         convert_to_string_ex(args[format_offset]);
     709               0 :         format = Z_STRVAL_PP(args[format_offset]);
     710               0 :         result = emalloc(size);
     711                 : 
     712               0 :         currarg = 1;
     713                 : 
     714               0 :         while (inpos<Z_STRLEN_PP(args[format_offset])) {
     715               0 :                 int expprec = 0, multiuse = 0;
     716                 :                 zval *tmp;
     717                 : 
     718                 :                 PRINTF_DEBUG(("sprintf: format[%d]='%c'\n", inpos, format[inpos]));
     719                 :                 PRINTF_DEBUG(("sprintf: outpos=%d\n", outpos));
     720               0 :                 if (format[inpos] != '%') {
     721               0 :                         php_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
     722               0 :                 } else if (format[inpos + 1] == '%') {
     723               0 :                         php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
     724               0 :                         inpos += 2;
     725                 :                 } else {
     726                 :                         /* starting a new format specifier, reset variables */
     727               0 :                         alignment = ALIGN_RIGHT;
     728               0 :                         adjusting = 0;
     729               0 :                         padding = ' ';
     730               0 :                         always_sign = 0;
     731               0 :                         inpos++;                        /* skip the '%' */
     732                 : 
     733                 :                         PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n",
     734                 :                                                   format[inpos], inpos));
     735               0 :                         if (isascii((int)format[inpos]) && !isalpha((int)format[inpos])) {
     736                 :                                 /* first look for argnum */
     737               0 :                                 temppos = inpos;
     738               0 :                                 while (isdigit((int)format[temppos])) temppos++;
     739               0 :                                 if (format[temppos] == '$') {
     740               0 :                                         argnum = php_sprintf_getnumber(format, &inpos);
     741                 : 
     742               0 :                                         if (argnum <= 0) {
     743               0 :                                                 efree(result);
     744               0 :                                                 efree(args);
     745               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument number must be greater than zero");
     746               0 :                                                 return NULL;
     747                 :                                         }
     748                 : 
     749               0 :                                         multiuse = 1;
     750               0 :                                         inpos++;  /* skip the '$' */
     751                 :                                 } else {
     752               0 :                                         argnum = currarg++;
     753                 :                                 }
     754                 : 
     755               0 :                                 argnum += format_offset;
     756                 : 
     757                 :                                 /* after argnum comes modifiers */
     758                 :                                 PRINTF_DEBUG(("sprintf: looking for modifiers\n"
     759                 :                                                           "sprintf: now looking at '%c', inpos=%d\n",
     760                 :                                                           format[inpos], inpos));
     761               0 :                                 for (;; inpos++) {
     762               0 :                                         if (format[inpos] == ' ' || format[inpos] == '0') {
     763               0 :                                                 padding = format[inpos];
     764               0 :                                         } else if (format[inpos] == '-') {
     765               0 :                                                 alignment = ALIGN_LEFT;
     766                 :                                                 /* space padding, the default */
     767               0 :                                         } else if (format[inpos] == '+') {
     768               0 :                                                 always_sign = 1;
     769               0 :                                         } else if (format[inpos] == '\'') {
     770               0 :                                                 padding = format[++inpos];
     771                 :                                         } else {
     772                 :                                                 PRINTF_DEBUG(("sprintf: end of modifiers\n"));
     773               0 :                                                 break;
     774                 :                                         }
     775               0 :                                 }
     776                 :                                 PRINTF_DEBUG(("sprintf: padding='%c'\n", padding));
     777                 :                                 PRINTF_DEBUG(("sprintf: alignment=%s\n",
     778                 :                                                           (alignment == ALIGN_LEFT) ? "left" : "right"));
     779                 : 
     780                 : 
     781                 :                                 /* after modifiers comes width */
     782               0 :                                 if (isdigit((int)format[inpos])) {
     783                 :                                         PRINTF_DEBUG(("sprintf: getting width\n"));
     784               0 :                                         if ((width = php_sprintf_getnumber(format, &inpos)) < 0) {
     785               0 :                                                 efree(result);
     786               0 :                                                 efree(args);
     787               0 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX);
     788               0 :                                                 return NULL;
     789                 :                                         }
     790               0 :                                         adjusting |= ADJ_WIDTH;
     791                 :                                 } else {
     792               0 :                                         width = 0;
     793                 :                                 }
     794                 :                                 PRINTF_DEBUG(("sprintf: width=%d\n", width));
     795                 : 
     796                 :                                 /* after width and argnum comes precision */
     797               0 :                                 if (format[inpos] == '.') {
     798               0 :                                         inpos++;
     799                 :                                         PRINTF_DEBUG(("sprintf: getting precision\n"));
     800               0 :                                         if (isdigit((int)format[inpos])) {
     801               0 :                                                 if ((precision = php_sprintf_getnumber(format, &inpos)) < 0) {
     802               0 :                                                         efree(result);
     803               0 :                                                         efree(args);
     804               0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX);
     805               0 :                                                         return NULL;
     806                 :                                                 }
     807               0 :                                                 adjusting |= ADJ_PRECISION;
     808               0 :                                                 expprec = 1;
     809                 :                                         } else {
     810               0 :                                                 precision = 0;
     811                 :                                         }
     812                 :                                 } else {
     813               0 :                                         precision = 0;
     814                 :                                 }
     815                 :                                 PRINTF_DEBUG(("sprintf: precision=%d\n", precision));
     816                 :                         } else {
     817               0 :                                 width = precision = 0;
     818               0 :                                 argnum = currarg++ + format_offset;
     819                 :                         }
     820                 : 
     821               0 :                         if (argnum >= argc) {
     822               0 :                                 efree(result);
     823               0 :                                 efree(args);
     824               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
     825               0 :                                 return NULL;
     826                 :                         }
     827                 : 
     828               0 :                         if (format[inpos] == 'l') {
     829               0 :                                 inpos++;
     830                 :                         }
     831                 :                         PRINTF_DEBUG(("sprintf: format character='%c'\n", format[inpos]));
     832                 :                         /* now we expect to find a type specifier */
     833               0 :                         if (multiuse) {
     834               0 :                                 MAKE_STD_ZVAL(tmp);
     835               0 :                                 *tmp = **(args[argnum]);
     836               0 :                                 INIT_PZVAL(tmp);
     837               0 :                                 zval_copy_ctor(tmp);
     838                 :                         } else {
     839               0 :                                 SEPARATE_ZVAL(args[argnum]);
     840               0 :                                 tmp = *(args[argnum]);
     841                 :                         }
     842                 : 
     843               0 :                         switch (format[inpos]) {
     844                 :                                 case 's': {
     845                 :                                         zval *var, var_copy;
     846               0 :                                         int use_copy = 0;
     847                 : 
     848               0 :                                         if (Z_TYPE_P(tmp) != IS_UNICODE) {
     849               0 :                                                 zend_make_string_zval(tmp, &var_copy, &use_copy);
     850                 :                                         } else {
     851               0 :                                                 var_copy = *tmp;
     852               0 :                                                 zval_copy_ctor(&var_copy);
     853               0 :                                                 INIT_PZVAL(&var_copy);
     854               0 :                                                 use_copy = 1;
     855                 : 
     856               0 :                                                 switch (type) {
     857                 :                                                         case PHP_OUTPUT:
     858               0 :                                                                 convert_to_string_with_converter(&var_copy, ZEND_U_CONVERTER(UG(output_encoding_conv)));
     859               0 :                                                                 break;
     860                 :                                                         case PHP_RUNTIME:
     861                 :                                                         default:
     862               0 :                                                                 convert_to_string_with_converter(&var_copy, ZEND_U_CONVERTER(UG(runtime_encoding_conv)));
     863                 :                                                                 break;
     864                 :                                                 }
     865                 :                                         }
     866               0 :                                         if (use_copy) {
     867               0 :                                                 var = &var_copy;
     868                 :                                         } else {
     869               0 :                                                 var = tmp;
     870                 :                                         }
     871               0 :                                         php_sprintf_appendstring(&result, &outpos, &size,
     872                 :                                                                                          Z_STRVAL_P(var),
     873                 :                                                                                          width, precision, padding,
     874                 :                                                                                          alignment,
     875                 :                                                                                          Z_STRLEN_P(var),
     876                 :                                                                                          0, expprec, 0);
     877               0 :                                         if (use_copy) {
     878               0 :                                                 zval_dtor(&var_copy);
     879                 :                                         }
     880               0 :                                         break;
     881                 :                                 }
     882                 : 
     883                 :                                 case 'd':
     884               0 :                                         convert_to_long(tmp);
     885               0 :                                         php_sprintf_appendint(&result, &outpos, &size,
     886                 :                                                                                   Z_LVAL_P(tmp),
     887                 :                                                                                   width, padding, alignment,
     888                 :                                                                                   always_sign);
     889               0 :                                         break;
     890                 : 
     891                 :                                 case 'u':
     892               0 :                                         convert_to_long(tmp);
     893               0 :                                         php_sprintf_appenduint(&result, &outpos, &size,
     894                 :                                                                                   Z_LVAL_P(tmp),
     895                 :                                                                                   width, padding, alignment);
     896               0 :                                         break;
     897                 : 
     898                 :                                 case 'g':
     899                 :                                 case 'G':
     900                 :                                 case 'e':
     901                 :                                 case 'E':
     902                 :                                 case 'f':
     903                 :                                 case 'F':
     904               0 :                                         convert_to_double(tmp);
     905               0 :                                         php_sprintf_appenddouble(&result, &outpos, &size,
     906                 :                                                                                          Z_DVAL_P(tmp),
     907                 :                                                                                          width, padding, alignment,
     908                 :                                                                                          precision, adjusting,
     909                 :                                                                                          format[inpos], always_sign
     910                 :                                                                                          TSRMLS_CC);
     911               0 :                                         break;
     912                 :                                         
     913                 :                                 case 'c':
     914               0 :                                         convert_to_long(tmp);
     915               0 :                                         php_sprintf_appendchar(&result, &outpos, &size,
     916                 :                                                                                 (char) Z_LVAL_P(tmp) TSRMLS_CC);
     917               0 :                                         break;
     918                 : 
     919                 :                                 case 'o':
     920               0 :                                         convert_to_long(tmp);
     921               0 :                                         php_sprintf_append2n(&result, &outpos, &size,
     922                 :                                                                                  Z_LVAL_P(tmp),
     923                 :                                                                                  width, padding, alignment, 3,
     924                 :                                                                                  hexchars, expprec);
     925               0 :                                         break;
     926                 : 
     927                 :                                 case 'x':
     928               0 :                                         convert_to_long(tmp);
     929               0 :                                         php_sprintf_append2n(&result, &outpos, &size,
     930                 :                                                                                  Z_LVAL_P(tmp),
     931                 :                                                                                  width, padding, alignment, 4,
     932                 :                                                                                  hexchars, expprec);
     933               0 :                                         break;
     934                 : 
     935                 :                                 case 'X':
     936               0 :                                         convert_to_long(tmp);
     937               0 :                                         php_sprintf_append2n(&result, &outpos, &size,
     938                 :                                                                                  Z_LVAL_P(tmp),
     939                 :                                                                                  width, padding, alignment, 4,
     940                 :                                                                                  HEXCHARS, expprec);
     941               0 :                                         break;
     942                 : 
     943                 :                                 case 'b':
     944               0 :                                         convert_to_long(tmp);
     945               0 :                                         php_sprintf_append2n(&result, &outpos, &size,
     946                 :                                                                                  Z_LVAL_P(tmp),
     947                 :                                                                                  width, padding, alignment, 1,
     948                 :                                                                                  hexchars, expprec);
     949               0 :                                         break;
     950                 : 
     951                 :                                 case '%':
     952               0 :                                         php_sprintf_appendchar(&result, &outpos, &size, '%' TSRMLS_CC);
     953                 : 
     954                 :                                         break;
     955                 :                                 default:
     956                 :                                         break;
     957                 :                         }
     958               0 :                         if (multiuse) {
     959               0 :                                 zval_ptr_dtor(&tmp);
     960                 :                         }
     961               0 :                         inpos++;
     962                 :                 }
     963                 :         }
     964                 :         
     965               0 :         efree(args);
     966                 :         
     967                 :         /* possibly, we have to make sure we have room for the terminating null? */
     968               0 :         result[outpos]=0;
     969               0 :         *len = outpos;  
     970               0 :         return result;
     971                 : }
     972                 : /* }}} */
     973                 : 
     974                 : /* php_u_formatted_print() {{{ */
     975                 : static zstr php_u_formatted_print(int ht, int *len, int use_array, int format_offset, int type TSRMLS_DC)
     976           85617 : {
     977                 :         zval ***args, **z_format;
     978           85617 :         int argc, size = 240, inpos = 0, outpos = 0, temppos;
     979                 :         int alignment, width, precision, currarg, adjusting, argnum;
     980                 :         UChar *format, *result, padding;
     981                 :         int always_sign;
     982                 :         zstr result_str;
     983                 : 
     984           85617 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
     985               5 :                 return NULL_ZSTR;
     986                 :         }
     987                 : 
     988                 :         /* verify the number of args */
     989           85612 :         if ((use_array && argc != (2 + format_offset)) 
     990                 :                         || (!use_array && argc < (1 + format_offset))) {
     991               4 :                 efree(args);
     992               4 :                 WRONG_PARAM_COUNT_WITH_RETVAL(NULL_ZSTR);
     993                 :         }
     994                 :         
     995           85608 :         if (use_array) {
     996             589 :                 int i = 1;
     997                 :                 zval ***newargs;
     998                 :                 zval **array;
     999                 : 
    1000             589 :                 z_format = args[format_offset];
    1001             589 :                 array = args[1 + format_offset];
    1002                 :                 
    1003             589 :                 SEPARATE_ZVAL(array);
    1004             589 :                 convert_to_array_ex(array);
    1005                 :                 
    1006             589 :                 argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(array));
    1007             589 :                 newargs = (zval ***)safe_emalloc(argc, sizeof(zval *), 0);
    1008             589 :                 newargs[0] = z_format;
    1009                 :                 
    1010             589 :                 for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(array));
    1011            4382 :                          zend_hash_get_current_data(Z_ARRVAL_PP(array), (void **)&newargs[i++]) == SUCCESS;
    1012            3204 :                          zend_hash_move_forward(Z_ARRVAL_PP(array)));
    1013                 : 
    1014             589 :                 efree(args);
    1015             589 :                 args = newargs;
    1016             589 :                 format_offset = 0;
    1017                 :         }
    1018                 :         
    1019           85608 :         convert_to_unicode_ex(args[format_offset]);
    1020           85608 :         format = Z_USTRVAL_PP(args[format_offset]);
    1021           85608 :         result = eumalloc(size);
    1022                 : 
    1023           85608 :         currarg = 1;
    1024                 : 
    1025         1140413 :         while (inpos<Z_USTRLEN_PP(args[format_offset])) {
    1026          969227 :                 int expprec = 0, multiuse = 0;
    1027                 :                 zval *tmp;
    1028                 : 
    1029          969227 :                 if (format[inpos] != 0x25 /* '%' */) {
    1030          856079 :                         php_u_sprintf_appendchar(&result, &outpos, &size, format[inpos++] TSRMLS_CC);
    1031          113148 :                 } else if (format[inpos + 1] == 0x25 /* '%' */) {
    1032              46 :                         php_u_sprintf_appendchar(&result, &outpos, &size, 0x25 /* '%' */ TSRMLS_CC);
    1033              46 :                         inpos += 2;
    1034                 :                 } else {
    1035                 :                         /* starting a new format specifier, reset variables */
    1036          113102 :                         alignment = ALIGN_RIGHT;
    1037          113102 :                         adjusting = 0;
    1038          113102 :                         padding = 0x20 /* ' ' */;
    1039          113102 :                         always_sign = 0;
    1040          113102 :                         inpos++;                        /* skip the '%' */
    1041                 : 
    1042          174941 :                         if ((format[inpos] < 0x7f) && !u_isalpha(format[inpos])) {
    1043                 :                                 /* first look for argnum */
    1044           61840 :                                 temppos = inpos;
    1045           61840 :                                 while (format[temppos] >= 0x30 /* '0' */ && format[temppos] <= 0x39 /* '9' */) temppos++;
    1046           61840 :                                 if (format[temppos] == 0x24 /* '$' */) {
    1047             545 :                                         argnum = php_u_sprintf_getnumber(format, &inpos);
    1048                 : 
    1049             545 :                                         if (argnum == 0) {
    1050               1 :                                                 efree(result);
    1051               1 :                                                 efree(args);
    1052               1 :                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero is not a valid argument number");
    1053               1 :                                                 return NULL_ZSTR;
    1054                 :                                         }
    1055                 : 
    1056             544 :                                         multiuse = 1;
    1057             544 :                                         inpos++;  /* skip the '$' */
    1058                 :                                 } else {
    1059           61295 :                                         argnum = currarg++;
    1060                 :                                 }
    1061                 : 
    1062           61839 :                                 argnum += format_offset;
    1063                 : 
    1064                 :                                 /* after argnum comes modifiers */
    1065           57099 :                                 for (;; inpos++) {
    1066          173892 :                                         if (u_isspace(format[inpos]) || format[inpos] == 0x30 /* '0' */) {
    1067           54954 :                                                 padding = format[inpos];
    1068           63984 :                                         } else if (format[inpos] == 0x2D /* '-' */) {
    1069            1409 :                                                 alignment = ALIGN_LEFT;
    1070                 :                                                 /* space padding, the default */
    1071           62575 :                                         } else if (format[inpos] == 0x2B /* '+' */) {
    1072             179 :                                                 always_sign = 1;
    1073           62396 :                                         } else if (format[inpos] == 0x27 /* '\'' */) {
    1074             557 :                                                 padding = format[++inpos];
    1075                 :                                         } else {
    1076           61839 :                                                 break;
    1077                 :                                         }
    1078           57099 :                                 }
    1079                 : 
    1080                 :                                 /* after modifiers comes width */
    1081           61839 :                                 if (isdigit((int)format[inpos])) {
    1082           59328 :                                         width = php_u_sprintf_getnumber(format, &inpos);
    1083           59328 :                                         adjusting |= ADJ_WIDTH;
    1084                 :                                 } else {
    1085            2511 :                                         width = 0;
    1086                 :                                 }
    1087                 : 
    1088                 :                                 /* after width and argnum comes precision */
    1089           61839 :                                 if (format[inpos] == 0x2E /* '.' */) {
    1090             708 :                                         inpos++;
    1091            1414 :                                         if (format[inpos] >= 0x30 /* '0' */ && format[inpos] <= 0x39 /* '9' */) {
    1092             706 :                                                 precision = php_u_sprintf_getnumber(format, &inpos);
    1093             706 :                                                 adjusting |= ADJ_PRECISION;
    1094             706 :                                                 expprec = 1;
    1095                 :                                         } else {
    1096               2 :                                                 precision = 0;
    1097                 :                                         }
    1098                 :                                 } else {
    1099           61131 :                                         precision = 0;
    1100                 :                                 }
    1101                 :                         } else {
    1102           51262 :                                 width = precision = 0;
    1103           51262 :                                 argnum = currarg++ + format_offset;
    1104                 :                         }
    1105                 : 
    1106          113101 :                         if (argnum >= argc) {
    1107              29 :                                 efree(result);
    1108              29 :                                 efree(args);
    1109              29 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too few arguments");
    1110              29 :                                 return NULL_ZSTR;
    1111                 :                         }
    1112                 : 
    1113          113072 :                         if (format[inpos] == 0x6C /* 'l' */) {
    1114             713 :                                 inpos++;
    1115                 :                         }
    1116                 :                         /* now we expect to find a type specifier */
    1117          113072 :                         if (multiuse) {
    1118             544 :                                 MAKE_STD_ZVAL(tmp);
    1119             544 :                                 *tmp = **(args[argnum]);
    1120             544 :                                 INIT_PZVAL(tmp);
    1121             544 :                                 zval_copy_ctor(tmp);
    1122                 :                         } else {
    1123          112528 :                                 SEPARATE_ZVAL(args[argnum]);
    1124          112528 :                                 tmp = *(args[argnum]);
    1125                 :                         }
    1126                 : 
    1127          113072 :                         switch (format[inpos]) {
    1128                 :                                 case 0x73 /* 's' */: {
    1129                 :                                         zval *var, var_copy;
    1130                 :                                         int use_copy;
    1131                 : 
    1132           23366 :                                         zend_make_unicode_zval(tmp, &var_copy, &use_copy);
    1133           23366 :                                         if (use_copy) {
    1134            7238 :                                                 var = &var_copy;
    1135                 :                                         } else {
    1136           16128 :                                                 var = tmp;
    1137                 :                                         }
    1138           23366 :                                         php_u_sprintf_appendstring(&result, &outpos, &size,
    1139                 :                                                                                          Z_USTRVAL_P(var),
    1140                 :                                                                                          width, precision, padding,
    1141                 :                                                                                          alignment,
    1142                 :                                                                                          Z_USTRLEN_P(var),
    1143                 :                                                                                          0, expprec, 0);
    1144           23366 :                                         if (use_copy) {
    1145            7238 :                                                 zval_dtor(&var_copy);
    1146                 :                                         }
    1147           23366 :                                         break;
    1148                 :                                 }
    1149                 : 
    1150                 :                                 case 0x64 /* 'd' */:
    1151           76152 :                                         convert_to_long(tmp);
    1152           76152 :                                         php_u_sprintf_appendint(&result, &outpos, &size,
    1153                 :                                                                                   Z_LVAL_P(tmp),
    1154                 :                                                                                   width, padding, alignment,
    1155                 :                                                                                   always_sign);
    1156           76152 :                                         break;
    1157                 : 
    1158                 :                                 case 0x75 /* 'u' */:
    1159             927 :                                         convert_to_long(tmp);
    1160             927 :                                         php_u_sprintf_appenduint(&result, &outpos, &size,
    1161                 :                                                                                   Z_LVAL_P(tmp),
    1162                 :                                                                                   width, padding, alignment);
    1163             927 :                                         break;
    1164                 : 
    1165                 :                                 case 0x67 /* 'g' */:
    1166                 :                                 case 0x47 /* 'G' */:
    1167                 :                                 case 0x65 /* 'e' */:
    1168                 :                                 case 0x45 /* 'E' */:
    1169                 :                                 case 0x66 /* 'f' */:
    1170                 :                                 case 0x46 /* 'F' */:
    1171            3776 :                                         convert_to_double(tmp);
    1172            3776 :                                         php_u_sprintf_appenddouble(&result, &outpos, &size,
    1173                 :                                                                                          Z_DVAL_P(tmp),
    1174                 :                                                                                          width, padding, alignment,
    1175                 :                                                                                          precision, adjusting,
    1176                 :                                                                                          format[inpos], always_sign
    1177                 :                                                                                          TSRMLS_CC);
    1178            3776 :                                         break;
    1179                 :                                         
    1180                 :                                 case 0x63 /* 'c' */:
    1181             964 :                                         convert_to_long(tmp);
    1182             964 :                                         php_u_sprintf_appendchar(&result, &outpos, &size,
    1183                 :                                                                                 (char) Z_LVAL_P(tmp) TSRMLS_CC);
    1184             964 :                                         break;
    1185                 : 
    1186                 :                                 case 0x6F /* 'o' */:
    1187            4058 :                                         convert_to_long(tmp);
    1188            4058 :                                         php_u_sprintf_append2n(&result, &outpos, &size,
    1189                 :                                                                                  Z_LVAL_P(tmp),
    1190                 :                                                                                  width, padding, alignment, 3,
    1191                 :                                                                                  u_hexchars, expprec);
    1192            4058 :                                         break;
    1193                 : 
    1194                 :                                 case 0x78 /* 'x' */:
    1195             997 :                                         convert_to_long(tmp);
    1196             997 :                                         php_u_sprintf_append2n(&result, &outpos, &size,
    1197                 :                                                                                  Z_LVAL_P(tmp),
    1198                 :                                                                                  width, padding, alignment, 4,
    1199                 :                                                                                  u_hexchars, expprec);
    1200             997 :                                         break;
    1201                 : 
    1202                 :                                 case 0x58 /* 'X' */:
    1203             316 :                                         convert_to_long(tmp);
    1204             316 :                                         php_u_sprintf_append2n(&result, &outpos, &size,
    1205                 :                                                                                  Z_LVAL_P(tmp),
    1206                 :                                                                                  width, padding, alignment, 4,
    1207                 :                                                                                  u_HEXCHARS, expprec);
    1208             316 :                                         break;
    1209                 : 
    1210                 :                                 case 0x62 /* 'b' */:
    1211              64 :                                         convert_to_long(tmp);
    1212              64 :                                         php_u_sprintf_append2n(&result, &outpos, &size,
    1213                 :                                                                                  Z_LVAL_P(tmp),
    1214                 :                                                                                  width, padding, alignment, 1,
    1215                 :                                                                                  u_hexchars, expprec);
    1216              64 :                                         break;
    1217                 : 
    1218                 :                                 case 0x25 /* '%' */:
    1219              12 :                                         php_u_sprintf_appendchar(&result, &outpos, &size, 0x25 /* '%' */ TSRMLS_CC);
    1220                 : 
    1221                 :                                         break;
    1222                 :                                 default:
    1223                 :                                         break;
    1224                 :                         }
    1225          113072 :                         if (multiuse) {
    1226             544 :                                 zval_ptr_dtor(&tmp);
    1227                 :                         }
    1228          113072 :                         inpos++;
    1229                 :                 }
    1230                 :         }
    1231                 :         
    1232           85578 :         efree(args);
    1233                 :         
    1234                 :         /* possibly, we have to make sure we have room for the terminating null? */
    1235           85578 :         result[outpos] = 0;
    1236           85578 :         *len = outpos;  
    1237           85578 :         result_str.u = result;
    1238                 : 
    1239           85578 :         switch (type) {
    1240                 :                 case PHP_OUTPUT: 
    1241                 :                 {
    1242            9247 :                         UErrorCode status = U_ZERO_ERROR;
    1243                 :                         char *s;
    1244                 :                         int s_len;
    1245                 : 
    1246            9247 :                         zend_unicode_to_string_ex(ZEND_U_CONVERTER(UG(output_encoding_conv)), &s, &s_len, result, outpos, &status);
    1247            9247 :                         if(U_FAILURE(status)) {
    1248               0 :                                 efree(s);
    1249               0 :                                 efree(result);
    1250               0 :                                 return NULL_ZSTR;
    1251                 :                         }
    1252                 : 
    1253            9247 :                         efree(result_str.v);
    1254            9247 :                         result_str.s = s;
    1255            9247 :                         *len = s_len;
    1256                 :                         break;
    1257                 :                 }
    1258                 :                 case PHP_RUNTIME:
    1259                 :                 default:
    1260                 :                         /* nothing to be done */
    1261                 :                         break;
    1262                 :         }
    1263                 : 
    1264           85578 :         return result_str;
    1265                 : }
    1266                 : /* }}} */
    1267                 : 
    1268                 : /* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]]) U
    1269                 :    Return a formatted string */
    1270                 : PHP_FUNCTION(user_sprintf)
    1271           74186 : {
    1272                 :         int len;
    1273                 :         zstr result;
    1274                 : 
    1275           74186 :         result = php_u_formatted_print(ht, &len, 0, 0, PHP_RUNTIME TSRMLS_CC);
    1276           74186 :         if (result.v == NULL) {
    1277               7 :                 RETURN_FALSE;
    1278                 :         }
    1279           74179 :         RETVAL_UNICODEL(result.u, len, 0);
    1280                 : }
    1281                 : /* }}} */
    1282                 : 
    1283                 : /* {{{ proto string vsprintf(string format, array args) U
    1284                 :    Return a formatted string */
    1285                 : PHP_FUNCTION(vsprintf)
    1286             204 : {
    1287                 :         int len;
    1288                 :         zstr result;
    1289                 : 
    1290             204 :         result = php_u_formatted_print(ht, &len, 1, 0, PHP_RUNTIME TSRMLS_CC);
    1291             204 :         if (result.v == NULL) {
    1292               8 :                 RETURN_FALSE;
    1293                 :         }
    1294             196 :         RETVAL_UNICODEL(result.u, len, 0);
    1295                 : }
    1296                 : /* }}} */
    1297                 : 
    1298                 : /* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]]) U
    1299                 :    Output a formatted string */
    1300                 : PHP_FUNCTION(user_printf)
    1301            9076 : {
    1302                 :         int len, rlen;
    1303                 :         zstr result;
    1304                 : 
    1305            9076 :         result = php_u_formatted_print(ht, &len, 0, 0, PHP_OUTPUT TSRMLS_CC);
    1306            9076 :         if (result.v == NULL) {
    1307               9 :                 RETURN_FALSE;
    1308                 :         }
    1309                 :         
    1310            9067 :         rlen = PHPWRITE(result.s, len);
    1311            9067 :         efree(result.v);
    1312            9067 :         RETURN_LONG(rlen);
    1313                 : }
    1314                 : /* }}} */
    1315                 : 
    1316                 : /* {{{ proto int vprintf(string format, array args) U
    1317                 :    Output a formatted string */
    1318                 : PHP_FUNCTION(vprintf)
    1319             188 : {
    1320                 :         int len, rlen;
    1321                 :         zstr result;
    1322                 : 
    1323             188 :         result = php_u_formatted_print(ht, &len, 1, 0, PHP_OUTPUT TSRMLS_CC);
    1324             188 :         if (result.v == NULL) {
    1325               8 :                 RETURN_FALSE;
    1326                 :         }
    1327                 : 
    1328             180 :         rlen = PHPWRITE(result.s, len);
    1329             180 :         efree(result.v);
    1330             180 :         RETURN_LONG(rlen);
    1331                 : }
    1332                 : /* }}} */
    1333                 : 
    1334                 : /* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]]) U
    1335                 :    Output a formatted string into a stream */
    1336                 : PHP_FUNCTION(fprintf)
    1337            1763 : {
    1338                 :         php_stream *stream;
    1339                 :         zval *arg1, **arg2;
    1340                 :         zstr result;
    1341                 :         int len, ret;
    1342                 :         
    1343            1763 :         if (ZEND_NUM_ARGS() < 2) {
    1344               3 :                 WRONG_PARAM_COUNT;
    1345                 :         }
    1346                 : 
    1347            1760 :         if (zend_parse_parameters(2 TSRMLS_CC, "rZ", &arg1, &arg2) == FAILURE) {
    1348               0 :                 RETURN_FALSE;
    1349                 :         }
    1350                 :         
    1351            1760 :         php_stream_from_zval(stream, &arg1);
    1352                 : 
    1353            1760 :         if (Z_TYPE_PP(arg2) != IS_STRING && Z_TYPE_PP(arg2) != IS_UNICODE) {
    1354             436 :                 convert_to_unicode_ex(arg2);
    1355                 :         }
    1356                 : 
    1357            1760 :         if (Z_TYPE_PP(arg2) == IS_STRING) {
    1358               0 :                 if ((result.s = php_formatted_print(ht, &len, 0, 1, PHP_RUNTIME TSRMLS_CC))==NULL) {
    1359               0 :                         RETURN_FALSE;
    1360                 :                 }
    1361               0 :                 ret = php_stream_write(stream, result.s, len);
    1362                 :         } else {
    1363            1760 :                 result = php_u_formatted_print(ht, &len, 0, 1, PHP_RUNTIME TSRMLS_CC);
    1364            1760 :                 if (result.v == NULL) {
    1365               1 :                         RETURN_FALSE;
    1366                 :                 }
    1367            1759 :                 ret = php_stream_write_unicode(stream, result.u, len);
    1368                 :         }
    1369                 :         
    1370            1759 :         efree(result.v);
    1371                 : 
    1372            1759 :         RETURN_LONG(ret);
    1373                 : }
    1374                 : /* }}} */
    1375                 : 
    1376                 : /* {{{ proto int vfprintf(resource stream, string format, array args) U
    1377                 :    Output a formatted string into a stream */
    1378                 : PHP_FUNCTION(vfprintf)
    1379             211 : {
    1380                 :         php_stream *stream;
    1381                 :         zval *arg1, **arg2;
    1382                 :         zstr result;
    1383                 :         int len, ret;
    1384                 :         
    1385             211 :         if (ZEND_NUM_ARGS() != 3) {
    1386               5 :                 WRONG_PARAM_COUNT;
    1387                 :         }
    1388                 :         
    1389             206 :         if (zend_parse_parameters(2 TSRMLS_CC, "rZ", &arg1, &arg2) == FAILURE) {
    1390               3 :                 RETURN_FALSE;
    1391                 :         }
    1392                 :         
    1393             203 :         php_stream_from_zval(stream, &arg1);
    1394                 : 
    1395             203 :         if (Z_TYPE_PP(arg2) != IS_STRING && Z_TYPE_PP(arg2) != IS_UNICODE) {
    1396              25 :                 convert_to_unicode_ex(arg2);
    1397                 :         }
    1398                 : 
    1399             203 :         if (Z_TYPE_PP(arg2) == IS_STRING) {
    1400               0 :                 if ((result.s = php_formatted_print(ht, &len, 1, 1, PHP_RUNTIME TSRMLS_CC))==NULL) {
    1401               0 :                         RETURN_FALSE;
    1402                 :                 }
    1403               0 :                 ret = php_stream_write(stream, result.s, len);
    1404                 :         } else {
    1405             203 :                 result = php_u_formatted_print(ht, &len, 1, 1, PHP_RUNTIME TSRMLS_CC);
    1406             203 :                 if (result.v == NULL) {
    1407               6 :                         RETURN_FALSE;
    1408                 :                 }
    1409             197 :                 ret = php_stream_write_unicode(stream, result.u, len);
    1410                 :         }
    1411                 : 
    1412             197 :         efree(result.v);
    1413                 : 
    1414             197 :         RETURN_LONG(ret);
    1415                 : }
    1416                 : /* }}} */
    1417                 : 
    1418                 : 
    1419                 : /*
    1420                 :  * Local variables:
    1421                 :  * tab-width: 4
    1422                 :  * c-basic-offset: 4
    1423                 :  * End:
    1424                 :  * vim600: sw=4 ts=4 fdm=marker
    1425                 :  * vim<600: sw=4 ts=4
    1426                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:42 +0000 (36 hours ago)

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