LTP GCOV extension - code coverage report
Current view: directory - main - spprintf.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 257
Code covered: 56.8 % Executed lines: 146
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: Marcus Boerger <helly@php.net>                               |
      16                 :    +----------------------------------------------------------------------+
      17                 : */
      18                 : 
      19                 : /* $Id: spprintf.c,v 1.25.2.2.2.5 2007/01/01 09:36:11 sebastian Exp $ */
      20                 : 
      21                 : /* This is the spprintf implementation.
      22                 :  * It has emerged from apache snprintf. See original header:
      23                 :  */
      24                 : 
      25                 : /* ====================================================================
      26                 :  * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
      27                 :  *
      28                 :  * Redistribution and use in source and binary forms, with or without
      29                 :  * modification, are permitted provided that the following conditions
      30                 :  * are met:
      31                 :  *
      32                 :  * 1. Redistributions of source code must retain the above copyright
      33                 :  *    notice, this list of conditions and the following disclaimer. 
      34                 :  *
      35                 :  * 2. Redistributions in binary form must reproduce the above copyright
      36                 :  *    notice, this list of conditions and the following disclaimer in
      37                 :  *    the documentation and/or other materials provided with the
      38                 :  *    distribution.
      39                 :  *
      40                 :  * 3. All advertising materials mentioning features or use of this
      41                 :  *    software must display the following acknowledgment:
      42                 :  *    "This product includes software developed by the Apache Group
      43                 :  *    for use in the Apache HTTP server project (http://www.apache.org/)."
      44                 :  *
      45                 :  * 4. The names "Apache Server" and "Apache Group" must not be used to
      46                 :  *    endorse or promote products derived from this software without
      47                 :  *    prior written permission.
      48                 :  *
      49                 :  * 5. Redistributions of any form whatsoever must retain the following
      50                 :  *    acknowledgment:
      51                 :  *    "This product includes software developed by the Apache Group
      52                 :  *    for use in the Apache HTTP server project (http://www.apache.org/)."
      53                 :  *
      54                 :  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
      55                 :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      56                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      57                 :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
      58                 :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      59                 :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      60                 :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      61                 :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      62                 :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      63                 :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      64                 :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      65                 :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      66                 :  * ====================================================================
      67                 :  *
      68                 :  * This software consists of voluntary contributions made by many
      69                 :  * individuals on behalf of the Apache Group and was originally based
      70                 :  * on public domain software written at the National Center for
      71                 :  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
      72                 :  * For more information on the Apache Group and the Apache HTTP server
      73                 :  * project, please see <http://www.apache.org/>.
      74                 :  *
      75                 :  * This code is based on, and used with the permission of, the
      76                 :  * SIO stdio-replacement strx_* functions by Panos Tsirigotis
      77                 :  * <panos@alumni.cs.colorado.edu> for xinetd.
      78                 :  */
      79                 : #include "php.h"
      80                 : 
      81                 : #include <stddef.h>
      82                 : #include <stdio.h>
      83                 : #include <ctype.h>
      84                 : #include <sys/types.h>
      85                 : #include <stdarg.h>
      86                 : #include <string.h>
      87                 : #include <stdlib.h>
      88                 : #include <math.h>
      89                 : #ifdef HAVE_INTTYPES_H
      90                 : #include <inttypes.h>
      91                 : #endif
      92                 : 
      93                 : #ifdef HAVE_LOCALE_H
      94                 : #include <locale.h>
      95                 : #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
      96                 : #else
      97                 : #define LCONV_DECIMAL_POINT '.'
      98                 : #endif
      99                 : 
     100                 : #include "snprintf.h"
     101                 : 
     102                 : #define FALSE           0
     103                 : #define TRUE            1
     104                 : #define NUL             '\0'
     105                 : #define INT_NULL        ((int *)0)
     106                 : 
     107                 : #define S_NULL          "(null)"
     108                 : #define S_NULL_LEN      6
     109                 : 
     110                 : #define FLOAT_DIGITS    6
     111                 : #define EXPONENT_LENGTH 10
     112                 : 
     113                 : #include "ext/standard/php_smart_str.h"
     114                 : 
     115                 : /*
     116                 :  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
     117                 :  *
     118                 :  * XXX: this is a magic number; do not decrease it
     119                 :  */
     120                 : #define NUM_BUF_SIZE    512
     121                 : 
     122                 : /*
     123                 :  * The INS_CHAR macro inserts a character in the buffer.
     124                 :  *
     125                 :  * NOTE: Evaluation of the ch argument should not have any side-effects
     126                 :  */
     127                 : #define INS_CHAR_NR(xbuf, ch) do {      \
     128                 :         smart_str_appendc(xbuf, ch);    \
     129                 : } while (0)
     130                 : 
     131                 : #define INS_STRING(xbuf, s, slen) do {  \
     132                 :         smart_str_appendl(xbuf, s, slen);       \
     133                 : } while (0)
     134                 :         
     135                 : #define INS_CHAR(xbuf, ch)          \
     136                 :         INS_CHAR_NR(xbuf, ch)
     137                 : 
     138                 : /*
     139                 :  * Macro that does padding. The padding is done by printing
     140                 :  * the character ch.
     141                 :  */
     142                 : #define PAD(xbuf, count, ch) do {                                       \
     143                 :         if ((count) > 0) {                                   \
     144                 :                 size_t newlen;                                                          \
     145                 :                 smart_str_alloc(xbuf, (count), 0);                      \
     146                 :                 memset(xbuf->c + xbuf->len, ch, (count)); \
     147                 :                 xbuf->len += (count);                                \
     148                 :         }                                                                                               \
     149                 : } while (0)
     150                 : 
     151                 : #define NUM(c) (c - '0')
     152                 : 
     153                 : #define STR_TO_DEC(str, num) do {                       \
     154                 :         num = NUM(*str++);                      \
     155                 :         while (isdigit((int)*str)) {            \
     156                 :                 num *= 10;                              \
     157                 :                 num += NUM(*str++);                     \
     158                 :                 if (num >= INT_MAX / 10) {                   \
     159                 :                         while (isdigit((int)*str++));   \
     160                 :                         break;                                                  \
     161                 :                 }                                                                       \
     162                 :     }                                                                           \
     163                 : } while (0)
     164                 : 
     165                 : /*
     166                 :  * This macro does zero padding so that the precision
     167                 :  * requirement is satisfied. The padding is done by
     168                 :  * adding '0's to the left of the string that is going
     169                 :  * to be printed.
     170                 :  */
     171                 : #define FIX_PRECISION(adjust, precision, s, s_len) do { \
     172                 :     if (adjust)                                                         \
     173                 :                 while (s_len < precision) {                  \
     174                 :                         *--s = '0';                                     \
     175                 :                         s_len++;                                        \
     176                 :                 }                                                                                               \
     177                 : } while (0)
     178                 : 
     179                 : 
     180                 : 
     181                 : /*
     182                 :  * Do format conversion placing the output in buffer
     183                 :  */
     184                 : static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap)
     185           20607 : {
     186           20607 :         register char *s = NULL;
     187                 :         char *q;
     188                 :         int s_len;
     189                 : 
     190           20607 :         register int min_width = 0;
     191           20607 :         int precision = 0;
     192                 :         enum {
     193                 :                 LEFT, RIGHT
     194                 :         } adjust;
     195                 :         char pad_char;
     196                 :         char prefix_char;
     197                 : 
     198                 :         double fp_num;
     199           20607 :         wide_int i_num = (wide_int) 0;
     200                 :         u_wide_int ui_num;
     201                 : 
     202                 :         char num_buf[NUM_BUF_SIZE];
     203                 :         char char_buf[2];                       /* for printing %% and %<unknown> */
     204                 : 
     205                 : #ifdef HAVE_LOCALE_H
     206           20607 :         struct lconv *lconv = NULL;
     207                 : #endif
     208                 : 
     209                 :         /*
     210                 :          * Flag variables
     211                 :          */
     212                 :         length_modifier_e modifier;
     213                 :         boolean_e alternate_form;
     214                 :         boolean_e print_sign;
     215                 :         boolean_e print_blank;
     216                 :         boolean_e adjust_precision;
     217                 :         boolean_e adjust_width;
     218                 :         bool_int is_negative;
     219                 : 
     220          290439 :         while (*fmt) {
     221          249225 :                 if (*fmt != '%') {
     222          197754 :                         INS_CHAR(xbuf, *fmt);
     223                 :                 } else {
     224                 :                         /*
     225                 :                          * Default variable settings
     226                 :                          */
     227           51471 :                         adjust = RIGHT;
     228           51471 :                         alternate_form = print_sign = print_blank = NO;
     229           51471 :                         pad_char = ' ';
     230           51471 :                         prefix_char = NUL;
     231                 : 
     232           51471 :                         fmt++;
     233                 : 
     234                 :                         /*
     235                 :                          * Try to avoid checking for flags, width or precision
     236                 :                          */
     237           52245 :                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
     238                 :                                 /*
     239                 :                                  * Recognize flags: -, #, BLANK, +
     240                 :                                  */
     241             264 :                                 for (;; fmt++) {
     242            1038 :                                         if (*fmt == '-')
     243               0 :                                                 adjust = LEFT;
     244            1038 :                                         else if (*fmt == '+')
     245               0 :                                                 print_sign = YES;
     246            1038 :                                         else if (*fmt == '#')
     247               0 :                                                 alternate_form = YES;
     248            1038 :                                         else if (*fmt == ' ')
     249               0 :                                                 print_blank = YES;
     250            1038 :                                         else if (*fmt == '0')
     251             264 :                                                 pad_char = '0';
     252                 :                                         else
     253             774 :                                                 break;
     254             264 :                                 }
     255                 : 
     256                 :                                 /*
     257                 :                                  * Check if a width was specified
     258                 :                                  */
     259             774 :                                 if (isdigit((int)*fmt)) {
     260             313 :                                         STR_TO_DEC(fmt, min_width);
     261             313 :                                         adjust_width = YES;
     262             461 :                                 } else if (*fmt == '*') {
     263             406 :                                         min_width = va_arg(ap, int);
     264             406 :                                         fmt++;
     265             406 :                                         adjust_width = YES;
     266             406 :                                         if (min_width < 0) {
     267               0 :                                                 adjust = LEFT;
     268               0 :                                                 min_width = -min_width;
     269                 :                                         }
     270                 :                                 } else
     271              55 :                                         adjust_width = NO;
     272                 : 
     273                 :                                 /*
     274                 :                                  * Check if a precision was specified
     275                 :                                  *
     276                 :                                  * XXX: an unreasonable amount of precision may be specified
     277                 :                                  * resulting in overflow of num_buf. Currently we
     278                 :                                  * ignore this possibility.
     279                 :                                  */
     280             774 :                                 if (*fmt == '.') {
     281             105 :                                         adjust_precision = YES;
     282             105 :                                         fmt++;
     283             105 :                                         if (isdigit((int)*fmt)) {
     284              53 :                                                 STR_TO_DEC(fmt, precision);
     285              52 :                                         } else if (*fmt == '*') {
     286              52 :                                                 precision = va_arg(ap, int);
     287              52 :                                                 fmt++;
     288              52 :                                                 if (precision < 0)
     289               0 :                                                         precision = 0;
     290                 :                                         } else
     291               0 :                                                 precision = 0;
     292                 :                                 } else
     293             669 :                                         adjust_precision = NO;
     294                 :                         } else
     295           50697 :                                 adjust_precision = adjust_width = NO;
     296                 : 
     297                 :                         /*
     298                 :                          * Modifier check
     299                 :                          */
     300           51471 :                         switch (*fmt) {
     301                 :                                 case 'L':
     302               0 :                                         fmt++;
     303               0 :                                         modifier = LM_LONG_DOUBLE;
     304               0 :                                         break;
     305                 :                                 case 'l':
     306            5256 :                                         fmt++;
     307                 : #if SIZEOF_LONG_LONG
     308            5256 :                                         if (*fmt == 'l') {
     309               0 :                                                 fmt++;
     310               0 :                                                 modifier = LM_LONG_LONG;
     311                 :                                         } else
     312                 : #endif
     313            5256 :                                                 modifier = LM_LONG;
     314            5256 :                                         break;
     315                 :                                 case 'z':
     316              38 :                                         fmt++;
     317              38 :                                         modifier = LM_SIZE_T;
     318              38 :                                         break;
     319                 :                                 case 'j':
     320               0 :                                         fmt++;
     321                 : #if SIZEOF_INTMAX_T
     322                 :                                         modifier = LM_INTMAX_T;
     323                 : #else
     324               0 :                                         modifier = LM_SIZE_T;
     325                 : #endif
     326               0 :                                         break;
     327                 :                                 case 't':
     328               1 :                                         fmt++;
     329                 : #if SIZEOF_PTRDIFF_T
     330                 :                                         modifier = LM_PTRDIFF_T;
     331                 : #else
     332               1 :                                         modifier = LM_SIZE_T;
     333                 : #endif
     334               1 :                                         break;
     335                 :                                 case 'h':
     336               0 :                                         fmt++;
     337               0 :                                         if (*fmt == 'h') {
     338               0 :                                                 fmt++;
     339                 :                                         }
     340                 :                                         /* these are promoted to int, so no break */
     341                 :                                 default:                                
     342           46176 :                                         modifier = LM_STD;
     343                 :                                         break;
     344                 :                         }
     345                 : 
     346                 :                         /*
     347                 :                          * Argument extraction and printing.
     348                 :                          * First we determine the argument type.
     349                 :                          * Then, we convert the argument to a string.
     350                 :                          * On exit from the switch, s points to the string that
     351                 :                          * must be printed, s_len has the length of the string
     352                 :                          * The precision requirements, if any, are reflected in s_len.
     353                 :                          *
     354                 :                          * NOTE: pad_char may be set to '0' because of the 0 flag.
     355                 :                          *   It is reset to ' ' by non-numeric formats
     356                 :                          */
     357           51471 :                         switch (*fmt) {
     358                 :                                 case 'u':
     359              41 :                                         switch(modifier) {
     360                 :                                                 default:
     361               0 :                                                         i_num = (wide_int) va_arg(ap, unsigned int);
     362               0 :                                                         break;
     363                 :                                                 case LM_LONG_DOUBLE:
     364               0 :                                                         goto fmt_error;
     365                 :                                                 case LM_LONG:
     366               2 :                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
     367               2 :                                                         break;
     368                 :                                                 case LM_SIZE_T:
     369              39 :                                                         i_num = (wide_int) va_arg(ap, size_t);
     370              39 :                                                         break;
     371                 : #if SIZEOF_LONG_LONG
     372                 :                                                 case LM_LONG_LONG:
     373               0 :                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
     374                 :                                                         break;
     375                 : #endif
     376                 : #if SIZEOF_INTMAX_T
     377                 :                                                 case LM_INTMAX_T:
     378                 :                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
     379                 :                                                         break;
     380                 : #endif
     381                 : #if SIZEOF_PTRDIFF_T
     382                 :                                                 case LM_PTRDIFF_T:
     383                 :                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
     384                 :                                                         break;
     385                 : #endif
     386                 :                                         }
     387                 :                                         /*
     388                 :                                          * The rest also applies to other integer formats, so fall
     389                 :                                          * into that case.
     390                 :                                          */
     391                 :                                 case 'd':
     392                 :                                 case 'i':
     393                 :                                         /*
     394                 :                                          * Get the arg if we haven't already.
     395                 :                                          */
     396           11005 :                                         if ((*fmt) != 'u') {
     397           10964 :                                                 switch(modifier) {
     398                 :                                                         default:
     399            5710 :                                                                 i_num = (wide_int) va_arg(ap, int);
     400            5710 :                                                                 break;
     401                 :                                                         case LM_LONG_DOUBLE:
     402               0 :                                                                 goto fmt_error;
     403                 :                                                         case LM_LONG:
     404            5254 :                                                                 i_num = (wide_int) va_arg(ap, long int);
     405            5254 :                                                                 break;
     406                 :                                                         case LM_SIZE_T:
     407                 : #if SIZEOF_SSIZE_T
     408               0 :                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
     409                 : #else
     410                 :                                                                 i_num = (wide_int) va_arg(ap, size_t);
     411                 : #endif
     412               0 :                                                                 break;
     413                 : #if SIZEOF_LONG_LONG
     414                 :                                                         case LM_LONG_LONG:
     415               0 :                                                                 i_num = (wide_int) va_arg(ap, wide_int);
     416                 :                                                                 break;
     417                 : #endif
     418                 : #if SIZEOF_INTMAX_T
     419                 :                                                         case LM_INTMAX_T:
     420                 :                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
     421                 :                                                                 break;
     422                 : #endif
     423                 : #if SIZEOF_PTRDIFF_T
     424                 :                                                         case LM_PTRDIFF_T:
     425                 :                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
     426                 :                                                                 break;
     427                 : #endif
     428                 :                                                 }
     429                 :                                         }
     430           11005 :                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
     431                 :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     432           11005 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     433                 : 
     434           11005 :                                         if (*fmt != 'u') {
     435           10964 :                                                 if (is_negative)
     436               1 :                                                         prefix_char = '-';
     437           10963 :                                                 else if (print_sign)
     438               0 :                                                         prefix_char = '+';
     439           10963 :                                                 else if (print_blank)
     440               0 :                                                         prefix_char = ' ';
     441                 :                                         }
     442           11005 :                                         break;
     443                 : 
     444                 : 
     445                 :                                 case 'o':
     446               0 :                                         switch(modifier) {
     447                 :                                                 default:
     448               0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     449               0 :                                                         break;
     450                 :                                                 case LM_LONG_DOUBLE:
     451               0 :                                                         goto fmt_error;
     452                 :                                                 case LM_LONG:
     453               0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     454               0 :                                                         break;
     455                 :                                                 case LM_SIZE_T:
     456               0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     457               0 :                                                         break;
     458                 : #if SIZEOF_LONG_LONG
     459                 :                                                 case LM_LONG_LONG:
     460               0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     461                 :                                                         break;
     462                 : #endif
     463                 : #if SIZEOF_INTMAX_T
     464                 :                                                 case LM_INTMAX_T:
     465                 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     466                 :                                                         break;
     467                 : #endif
     468                 : #if SIZEOF_PTRDIFF_T
     469                 :                                                 case LM_PTRDIFF_T:
     470                 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     471                 :                                                         break;
     472                 : #endif
     473                 :                                         }
     474               0 :                                         s = ap_php_conv_p2(ui_num, 3, *fmt,
     475                 :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     476               0 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     477               0 :                                         if (alternate_form && *s != '0') {
     478               0 :                                                 *--s = '0';
     479               0 :                                                 s_len++;
     480                 :                                         }
     481               0 :                                         break;
     482                 : 
     483                 : 
     484                 :                                 case 'x':
     485                 :                                 case 'X':
     486             255 :                                         switch(modifier) {
     487                 :                                                 default:
     488             255 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     489             255 :                                                         break;
     490                 :                                                 case LM_LONG_DOUBLE:
     491               0 :                                                         goto fmt_error;
     492                 :                                                 case LM_LONG:
     493               0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     494               0 :                                                         break;
     495                 :                                                 case LM_SIZE_T:
     496               0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     497               0 :                                                         break;
     498                 : #if SIZEOF_LONG_LONG
     499                 :                                                 case LM_LONG_LONG:
     500               0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     501                 :                                                         break;
     502                 : #endif
     503                 : #if SIZEOF_INTMAX_T
     504                 :                                                 case LM_INTMAX_T:
     505                 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     506                 :                                                         break;
     507                 : #endif
     508                 : #if SIZEOF_PTRDIFF_T
     509                 :                                                 case LM_PTRDIFF_T:
     510                 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     511                 :                                                         break;
     512                 : #endif
     513                 :                                         }
     514             255 :                                         s = ap_php_conv_p2(ui_num, 4, *fmt,
     515                 :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     516             255 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     517             255 :                                         if (alternate_form && i_num != 0) {
     518               0 :                                                 *--s = *fmt;    /* 'x' or 'X' */
     519               0 :                                                 *--s = '0';
     520               0 :                                                 s_len += 2;
     521                 :                                         }
     522             255 :                                         break;
     523                 : 
     524                 : 
     525                 :                                 case 's':
     526                 :                                 case 'v':
     527           38796 :                                         s = va_arg(ap, char *);
     528           38796 :                                         if (s != NULL) {
     529           38791 :                                                 s_len = strlen(s);
     530           38791 :                                                 if (adjust_precision && precision < s_len)
     531               0 :                                                         s_len = precision;
     532                 :                                         } else {
     533               5 :                                                 s = S_NULL;
     534               5 :                                                 s_len = S_NULL_LEN;
     535                 :                                         }
     536           38796 :                                         pad_char = ' ';
     537           38796 :                                         break;
     538                 : 
     539                 : 
     540                 :                                 case 'f':
     541                 :                                 case 'F':
     542                 :                                 case 'e':
     543                 :                                 case 'E':
     544              52 :                                         switch(modifier) {
     545                 :                                                 case LM_LONG_DOUBLE:
     546               0 :                                                         fp_num = (double) va_arg(ap, long double);
     547               0 :                                                         break;
     548                 :                                                 case LM_STD:
     549              52 :                                                         fp_num = va_arg(ap, double);
     550              52 :                                                         break;
     551                 :                                                 default:
     552               0 :                                                         goto fmt_error;
     553                 :                                         }
     554                 : 
     555              52 :                                         if (zend_isnan(fp_num)) {
     556               0 :                                                 s = "nan";
     557               0 :                                                 s_len = 3;
     558              52 :                                         } else if (zend_isinf(fp_num)) {
     559               0 :                                                 s = "inf";
     560               0 :                                                 s_len = 3;
     561                 :                                         } else {
     562                 : #ifdef HAVE_LOCALE_H
     563              52 :                                                 if (!lconv) {
     564              52 :                                                         lconv = localeconv();
     565                 :                                                 }
     566                 : #endif
     567              52 :                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
     568                 :                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
     569                 :                                                  (*fmt == 'f')?(*lconv->decimal_point):'.',
     570                 :                                                                         &is_negative, &num_buf[1], &s_len);
     571              52 :                                                 if (is_negative)
     572               0 :                                                         prefix_char = '-';
     573              52 :                                                 else if (print_sign)
     574               0 :                                                         prefix_char = '+';
     575              52 :                                                 else if (print_blank)
     576               0 :                                                         prefix_char = ' ';
     577                 :                                         }
     578              52 :                                         break;
     579                 : 
     580                 : 
     581                 :                                 case 'g':
     582                 :                                 case 'G':
     583              46 :                                         switch(modifier) {
     584                 :                                                 case LM_LONG_DOUBLE:
     585               0 :                                                         fp_num = (double) va_arg(ap, long double);
     586               0 :                                                         break;
     587                 :                                                 case LM_STD:
     588              46 :                                                         fp_num = va_arg(ap, double);
     589              46 :                                                         break;
     590                 :                                                 default:
     591               0 :                                                         goto fmt_error;
     592                 :                                         }
     593                 : 
     594              46 :                                         if (zend_isnan(fp_num)) {
     595               0 :                                                 s = "NAN";
     596               0 :                                                 s_len = 3;
     597               0 :                                                 break;
     598              46 :                                         } else if (zend_isinf(fp_num)) {
     599               0 :                                                 if (fp_num > 0) {
     600               0 :                                                         s = "INF";
     601               0 :                                                         s_len = 3;
     602                 :                                                 } else {
     603               0 :                                                         s = "-INF";
     604               0 :                                                         s_len = 4;
     605                 :                                                 }
     606               0 :                                                 break;
     607                 :                                         }
     608                 : 
     609              46 :                                         if (adjust_precision == NO)
     610               0 :                                                 precision = FLOAT_DIGITS;
     611              46 :                                         else if (precision == 0)
     612               0 :                                                 precision = 1;
     613                 :                                         /*
     614                 :                                          * * We use &num_buf[ 1 ], so that we have room for the sign
     615                 :                                          */
     616                 : #ifdef HAVE_LOCALE_H
     617              46 :                                         if (!lconv) {
     618              46 :                                                 lconv = localeconv();
     619                 :                                         }
     620                 : #endif
     621              46 :                                         s = php_gcvt(fp_num, precision, *lconv->decimal_point, (*fmt == 'G')?'E':'e', &num_buf[1]);
     622              46 :                                         if (*s == '-')
     623               0 :                                                 prefix_char = *s++;
     624              46 :                                         else if (print_sign)
     625               0 :                                                 prefix_char = '+';
     626              46 :                                         else if (print_blank)
     627               0 :                                                 prefix_char = ' ';
     628                 : 
     629              46 :                                         s_len = strlen(s);
     630                 : 
     631              46 :                                         if (alternate_form && (q = strchr(s, '.')) == NULL)
     632               0 :                                                 s[s_len++] = '.';
     633              46 :                                         break;
     634                 : 
     635                 : 
     636                 :                                 case 'c':
     637            1317 :                                         char_buf[0] = (char) (va_arg(ap, int));
     638            1317 :                                         s = &char_buf[0];
     639            1317 :                                         s_len = 1;
     640            1317 :                                         pad_char = ' ';
     641            1317 :                                         break;
     642                 : 
     643                 : 
     644                 :                                 case '%':
     645               0 :                                         char_buf[0] = '%';
     646               0 :                                         s = &char_buf[0];
     647               0 :                                         s_len = 1;
     648               0 :                                         pad_char = ' ';
     649               0 :                                         break;
     650                 : 
     651                 : 
     652                 :                                 case 'n':
     653               0 :                                         *(va_arg(ap, int *)) = xbuf->len;
     654               0 :                                         goto skip_output;
     655                 : 
     656                 :                                         /*
     657                 :                                          * Always extract the argument as a "char *" pointer. We 
     658                 :                                          * should be using "void *" but there are still machines 
     659                 :                                          * that don't understand it.
     660                 :                                          * If the pointer size is equal to the size of an unsigned
     661                 :                                          * integer we convert the pointer to a hex number, otherwise 
     662                 :                                          * we print "%p" to indicate that we don't handle "%p".
     663                 :                                          */
     664                 :                                 case 'p':
     665                 :                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
     666               0 :                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
     667               0 :                                                 s = ap_php_conv_p2(ui_num, 4, 'x', 
     668                 :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     669               0 :                                                 if (ui_num != 0) {
     670               0 :                                                         *--s = 'x';
     671               0 :                                                         *--s = '0';
     672               0 :                                                         s_len += 2;
     673                 :                                                 }
     674                 :                                         } else {
     675                 :                                                 s = "%p";
     676                 :                                                 s_len = 2;
     677                 :                                         }
     678               0 :                                         pad_char = ' ';
     679               0 :                                         break;
     680                 : 
     681                 : 
     682                 :                                 case NUL:
     683                 :                                         /*
     684                 :                                          * The last character of the format string was %.
     685                 :                                          * We ignore it.
     686                 :                                          */
     687               0 :                                         continue;
     688                 : 
     689                 : 
     690               0 : fmt_error:
     691               0 :                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
     692                 :                                         /*
     693                 :                                          * The default case is for unrecognized %'s.
     694                 :                                          * We print %<char> to help the user identify what
     695                 :                                          * option is not understood.
     696                 :                                          * This is also useful in case the user wants to pass
     697                 :                                          * the output of format_converter to another function
     698                 :                                          * that understands some other %<char> (like syslog).
     699                 :                                          * Note that we can't point s inside fmt because the
     700                 :                                          * unknown <char> could be preceded by width etc.
     701                 :                                          */
     702                 :                                 default:
     703               0 :                                         char_buf[0] = '%';
     704               0 :                                         char_buf[1] = *fmt;
     705               0 :                                         s = char_buf;
     706               0 :                                         s_len = 2;
     707               0 :                                         pad_char = ' ';
     708                 :                                         break;
     709                 :                         }
     710                 : 
     711           51471 :                         if (prefix_char != NUL) {
     712               1 :                                 *--s = prefix_char;
     713               1 :                                 s_len++;
     714                 :                         }
     715           51471 :                         if (adjust_width && adjust == RIGHT && min_width > s_len) {
     716             425 :                                 if (pad_char == '0' && prefix_char != NUL) {
     717               0 :                                         INS_CHAR(xbuf, *s);
     718               0 :                                         s++;
     719               0 :                                         s_len--;
     720               0 :                                         min_width--;
     721                 :                                 }
     722             425 :                                 PAD(xbuf, min_width - s_len, pad_char);
     723                 :                         }
     724                 :                         /*
     725                 :                          * Print the string s. 
     726                 :                          */
     727           51471 :                         INS_STRING(xbuf, s, s_len);
     728                 : 
     729           51471 :                         if (adjust_width && adjust == LEFT && min_width > s_len)
     730               0 :                                 PAD(xbuf, min_width - s_len, pad_char);
     731                 :                 }
     732          249225 : skip_output:
     733          249225 :                 fmt++;
     734                 :         }
     735                 :         return;
     736                 : }
     737                 : 
     738                 : 
     739                 : /*
     740                 :  * This is the general purpose conversion function.
     741                 :  */
     742                 : PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap)
     743           20607 : {
     744           20607 :         smart_str xbuf = {0};
     745                 : 
     746           20607 :         xbuf_format_converter(&xbuf, format, ap);
     747                 :         
     748           20607 :         if (max_len && xbuf.len > max_len) {
     749               0 :                 xbuf.len = max_len;
     750                 :         }
     751           20607 :         smart_str_0(&xbuf);
     752                 :                 
     753           20607 :         *pbuf = xbuf.c;
     754                 :         
     755           20607 :         return xbuf.len;
     756                 : }
     757                 : 
     758                 : 
     759                 : PHPAPI int spprintf(char **pbuf, size_t max_len, const char *format, ...)
     760            4662 : {
     761                 :         int cc;
     762                 :         va_list ap;
     763                 : 
     764            4662 :         va_start(ap, format);
     765            4662 :         cc = vspprintf(pbuf, max_len, format, ap);
     766            4662 :         va_end(ap);
     767            4662 :         return (cc);
     768                 : }
     769                 : /*
     770                 :  * Local variables:
     771                 :  * tab-width: 4
     772                 :  * c-basic-offset: 4
     773                 :  * End:
     774                 :  * vim600: sw=4 ts=4 fdm=marker
     775                 :  * vim<600: sw=4 ts=4
     776                 :  */

Generated by: LTP GCOV extension version 1.5