LTP GCOV extension - code coverage report
Current view: directory - ext/standard - formatted_print.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 302
Code covered: 48.0 % Executed lines: 145
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5