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

LCOV - code coverage report
Current view: top level - main - spprintf.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 193 296 65.2 %
Date: 2014-08-17 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Marcus Boerger <helly@php.net>                               |
      16             :    +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      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             : #define _GNU_SOURCE
      80             : #include "php.h"
      81             : 
      82             : #include <stddef.h>
      83             : #include <stdio.h>
      84             : #include <ctype.h>
      85             : #include <sys/types.h>
      86             : #include <stdarg.h>
      87             : #include <string.h>
      88             : #include <stdlib.h>
      89             : #include <math.h>
      90             : #ifdef HAVE_INTTYPES_H
      91             : #include <inttypes.h>
      92             : #endif
      93             : 
      94             : #ifdef HAVE_LOCALE_H
      95             : #include <locale.h>
      96             : #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
      97             : #else
      98             : #define LCONV_DECIMAL_POINT '.'
      99             : #endif
     100             : 
     101             : #include "snprintf.h"
     102             : 
     103             : #define FALSE           0
     104             : #define TRUE            1
     105             : #define NUL             '\0'
     106             : #define INT_NULL        ((int *)0)
     107             : 
     108             : #define S_NULL          "(null)"
     109             : #define S_NULL_LEN      6
     110             : 
     111             : #define FLOAT_DIGITS    6
     112             : #define EXPONENT_LENGTH 10
     113             : 
     114             : #include "ext/standard/php_smart_str.h"
     115             : 
     116             : /* {{{ macros */
     117             : 
     118             : /*
     119             :  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
     120             :  *
     121             :  * XXX: this is a magic number; do not decrease it
     122             :  * Emax = 1023
     123             :  * NDIG = 320
     124             :  * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
     125             :  */
     126             : #define NUM_BUF_SIZE            2048
     127             : 
     128             : /*
     129             :  * The INS_CHAR macro inserts a character in the buffer.
     130             :  *
     131             :  * NOTE: Evaluation of the ch argument should not have any side-effects
     132             :  */
     133             : #define INS_CHAR_NR(xbuf, ch) do {      \
     134             :         smart_str_appendc(xbuf, ch);    \
     135             : } while (0)
     136             : 
     137             : #define INS_STRING(xbuf, s, slen) do {  \
     138             :         smart_str_appendl(xbuf, s, slen);       \
     139             : } while (0)
     140             : 
     141             : #define INS_CHAR(xbuf, ch)          \
     142             :         INS_CHAR_NR(xbuf, ch)
     143             : 
     144             : /*
     145             :  * Macro that does padding. The padding is done by printing
     146             :  * the character ch.
     147             :  */
     148             : #define PAD(xbuf, count, ch) do {                                       \
     149             :         if ((count) > 0) {                                   \
     150             :                 size_t newlen;                                                          \
     151             :                 smart_str_alloc(xbuf, (count), 0);                      \
     152             :                 memset(xbuf->c + xbuf->len, ch, (count)); \
     153             :                 xbuf->len += (count);                                \
     154             :         }                                                                                               \
     155             : } while (0)
     156             : 
     157             : #define NUM(c) (c - '0')
     158             : 
     159             : #define STR_TO_DEC(str, num) do {                       \
     160             :         num = NUM(*str++);                      \
     161             :         while (isdigit((int)*str)) {            \
     162             :                 num *= 10;                              \
     163             :                 num += NUM(*str++);                     \
     164             :                 if (num >= INT_MAX / 10) {                   \
     165             :                         while (isdigit((int)*str++));   \
     166             :                         break;                                                  \
     167             :                 }                                                                       \
     168             :     }                                                                           \
     169             : } while (0)
     170             : 
     171             : /*
     172             :  * This macro does zero padding so that the precision
     173             :  * requirement is satisfied. The padding is done by
     174             :  * adding '0's to the left of the string that is going
     175             :  * to be printed.
     176             :  */
     177             : #define FIX_PRECISION(adjust, precision, s, s_len) do { \
     178             :     if (adjust)                                                         \
     179             :                 while (s_len < precision) {                  \
     180             :                         *--s = '0';                                     \
     181             :                         s_len++;                                        \
     182             :                 }                                                                                               \
     183             : } while (0)
     184             : 
     185             : /* }}} */
     186             : 
     187             : 
     188             : #if !HAVE_STRNLEN
     189             : static size_t strnlen(const char *s, size_t maxlen) {
     190             :         char *r = memchr(s, '\0', maxlen);
     191             :         return r ? r-s : maxlen;
     192             : }
     193             : #endif
     194             : 
     195             : /*
     196             :  * Do format conversion placing the output in buffer
     197             :  */
     198     4862515 : static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) /* {{{ */
     199             : {
     200     4862515 :         char *s = NULL;
     201             :         int s_len, free_zcopy;
     202             :         zval *zvp, zcopy;
     203             : 
     204     4862515 :         int min_width = 0;
     205     4862515 :         int precision = 0;
     206             :         enum {
     207             :                 LEFT, RIGHT
     208             :         } adjust;
     209             :         char pad_char;
     210             :         char prefix_char;
     211             : 
     212             :         double fp_num;
     213     4862515 :         wide_int i_num = (wide_int) 0;
     214     4862515 :         u_wide_int ui_num = (u_wide_int) 0;
     215             : 
     216             :         char num_buf[NUM_BUF_SIZE];
     217             :         char char_buf[2];                       /* for printing %% and %<unknown> */
     218             : 
     219             : #ifdef HAVE_LOCALE_H
     220     4862515 :         struct lconv *lconv = NULL;
     221             : #endif
     222             : 
     223             :         /*
     224             :          * Flag variables
     225             :          */
     226             :         length_modifier_e modifier;
     227             :         boolean_e alternate_form;
     228             :         boolean_e print_sign;
     229             :         boolean_e print_blank;
     230             :         boolean_e adjust_precision;
     231             :         boolean_e adjust_width;
     232             :         bool_int is_negative;
     233             : 
     234    27357208 :         while (*fmt) {
     235    17632178 :                 if (*fmt != '%') {
     236     9997667 :                         INS_CHAR(xbuf, *fmt);
     237             :                 } else {
     238             :                         /*
     239             :                          * Default variable settings
     240             :                          */
     241     7634511 :                         adjust = RIGHT;
     242     7634511 :                         alternate_form = print_sign = print_blank = NO;
     243     7634511 :                         pad_char = ' ';
     244     7634511 :                         prefix_char = NUL;
     245     7634511 :                         free_zcopy = 0;
     246             : 
     247     7634511 :                         fmt++;
     248             : 
     249             :                         /*
     250             :                          * Try to avoid checking for flags, width or precision
     251             :                          */
     252     7871161 :                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
     253             :                                 /*
     254             :                                  * Recognize flags: -, #, BLANK, +
     255             :                                  */
     256       67035 :                                 for (;; fmt++) {
     257      303685 :                                         if (*fmt == '-')
     258          55 :                                                 adjust = LEFT;
     259      303630 :                                         else if (*fmt == '+')
     260           0 :                                                 print_sign = YES;
     261      303630 :                                         else if (*fmt == '#')
     262           0 :                                                 alternate_form = YES;
     263      303630 :                                         else if (*fmt == ' ')
     264           0 :                                                 print_blank = YES;
     265      303630 :                                         else if (*fmt == '0')
     266       66980 :                                                 pad_char = '0';
     267             :                                         else
     268      236650 :                                                 break;
     269       67035 :                                 }
     270             : 
     271             :                                 /*
     272             :                                  * Check if a width was specified
     273             :                                  */
     274      236650 :                                 if (isdigit((int)*fmt)) {
     275       66814 :                                         STR_TO_DEC(fmt, min_width);
     276       66814 :                                         adjust_width = YES;
     277      169836 :                                 } else if (*fmt == '*') {
     278      152301 :                                         min_width = va_arg(ap, int);
     279      152301 :                                         fmt++;
     280      152301 :                                         adjust_width = YES;
     281      152301 :                                         if (min_width < 0) {
     282           0 :                                                 adjust = LEFT;
     283           0 :                                                 min_width = -min_width;
     284             :                                         }
     285             :                                 } else
     286       17535 :                                         adjust_width = NO;
     287             : 
     288             :                                 /*
     289             :                                  * Check if a precision was specified
     290             :                                  */
     291      236650 :                                 if (*fmt == '.') {
     292       17528 :                                         adjust_precision = YES;
     293       17528 :                                         fmt++;
     294       17528 :                                         if (isdigit((int)*fmt)) {
     295         454 :                                                 STR_TO_DEC(fmt, precision);
     296       17074 :                                         } else if (*fmt == '*') {
     297       17074 :                                                 precision = va_arg(ap, int);
     298       17074 :                                                 fmt++;
     299       17074 :                                                 if (precision < 0)
     300           0 :                                                         precision = 0;
     301             :                                         } else
     302           0 :                                                 precision = 0;
     303             :                                         
     304       17528 :                                         if (precision > FORMAT_CONV_MAX_PRECISION) {
     305         576 :                                                 precision = FORMAT_CONV_MAX_PRECISION;
     306             :                                         }
     307             :                                 } else
     308      219122 :                                         adjust_precision = NO;
     309             :                         } else
     310     7397861 :                                 adjust_precision = adjust_width = NO;
     311             : 
     312             :                         /*
     313             :                          * Modifier check
     314             :                          */
     315     7634511 :                         switch (*fmt) {
     316             :                                 case 'L':
     317           0 :                                         fmt++;
     318           0 :                                         modifier = LM_LONG_DOUBLE;
     319           0 :                                         break;
     320             :                                 case 'I':
     321           0 :                                         fmt++;
     322             : #if SIZEOF_LONG_LONG
     323           0 :                                         if (*fmt == '6' && *(fmt+1) == '4') {
     324           0 :                                                 fmt += 2;
     325           0 :                                                 modifier = LM_LONG_LONG;
     326             :                                         } else
     327             : #endif
     328           0 :                                                 if (*fmt == '3' && *(fmt+1) == '2') {
     329           0 :                                                         fmt += 2;
     330           0 :                                                         modifier = LM_LONG;
     331             :                                                 } else {
     332             : #ifdef _WIN64
     333             :                                                         modifier = LM_LONG_LONG;
     334             : #else
     335           0 :                                                         modifier = LM_LONG;
     336             : #endif
     337             :                                                 }
     338           0 :                                         break;
     339             :                                 case 'l':
     340     1850846 :                                         fmt++;
     341             : #if SIZEOF_LONG_LONG
     342     1850846 :                                         if (*fmt == 'l') {
     343           7 :                                                 fmt++;
     344           7 :                                                 modifier = LM_LONG_LONG;
     345             :                                         } else
     346             : #endif
     347     1850839 :                                                 modifier = LM_LONG;
     348     1850846 :                                         break;
     349             :                                 case 'z':
     350         129 :                                         fmt++;
     351         129 :                                         modifier = LM_SIZE_T;
     352         129 :                                         break;
     353             :                                 case 'j':
     354           0 :                                         fmt++;
     355             : #if SIZEOF_INTMAX_T
     356           0 :                                         modifier = LM_INTMAX_T;
     357             : #else
     358             :                                         modifier = LM_SIZE_T;
     359             : #endif
     360           0 :                                         break;
     361             :                                 case 't':
     362           0 :                                         fmt++;
     363             : #if SIZEOF_PTRDIFF_T
     364           0 :                                         modifier = LM_PTRDIFF_T;
     365             : #else
     366             :                                         modifier = LM_SIZE_T;
     367             : #endif
     368           0 :                                         break;
     369             :                                 case 'h':
     370           0 :                                         fmt++;
     371           0 :                                         if (*fmt == 'h') {
     372           0 :                                                 fmt++;
     373             :                                         }
     374             :                                         /* these are promoted to int, so no break */
     375             :                                 default:
     376     5783536 :                                         modifier = LM_STD;
     377             :                                         break;
     378             :                         }
     379             : 
     380             :                         /*
     381             :                          * Argument extraction and printing.
     382             :                          * First we determine the argument type.
     383             :                          * Then, we convert the argument to a string.
     384             :                          * On exit from the switch, s points to the string that
     385             :                          * must be printed, s_len has the length of the string
     386             :                          * The precision requirements, if any, are reflected in s_len.
     387             :                          *
     388             :                          * NOTE: pad_char may be set to '0' because of the 0 flag.
     389             :                          *   It is reset to ' ' by non-numeric formats
     390             :                          */
     391     7634511 :                         switch (*fmt) {
     392             :                                 case 'Z':
     393           0 :                                         zvp = (zval*) va_arg(ap, zval*);
     394           0 :                                         zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
     395           0 :                                         if (free_zcopy) {
     396           0 :                                                 zvp = &zcopy;
     397             :                                         }
     398           0 :                                         s_len = Z_STRLEN_P(zvp);
     399           0 :                                         s = Z_STRVAL_P(zvp);
     400           0 :                                         if (adjust_precision && precision < s_len) {
     401           0 :                                                 s_len = precision;
     402             :                                         }
     403           0 :                                         break;
     404             :                                 case 'u':
     405        1210 :                                         switch(modifier) {
     406             :                                                 default:
     407        1079 :                                                         i_num = (wide_int) va_arg(ap, unsigned int);
     408        1079 :                                                         break;
     409             :                                                 case LM_LONG_DOUBLE:
     410           0 :                                                         goto fmt_error;
     411             :                                                 case LM_LONG:
     412           4 :                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
     413           4 :                                                         break;
     414             :                                                 case LM_SIZE_T:
     415         127 :                                                         i_num = (wide_int) va_arg(ap, size_t);
     416         127 :                                                         break;
     417             : #if SIZEOF_LONG_LONG
     418             :                                                 case LM_LONG_LONG:
     419           0 :                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
     420           0 :                                                         break;
     421             : #endif
     422             : #if SIZEOF_INTMAX_T
     423             :                                                 case LM_INTMAX_T:
     424           0 :                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
     425           0 :                                                         break;
     426             : #endif
     427             : #if SIZEOF_PTRDIFF_T
     428             :                                                 case LM_PTRDIFF_T:
     429           0 :                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
     430             :                                                         break;
     431             : #endif
     432             :                                         }
     433             :                                         /*
     434             :                                          * The rest also applies to other integer formats, so fall
     435             :                                          * into that case.
     436             :                                          */
     437             :                                 case 'd':
     438             :                                 case 'i':
     439             :                                         /*
     440             :                                          * Get the arg if we haven't already.
     441             :                                          */
     442     1989966 :                                         if ((*fmt) != 'u') {
     443     1988756 :                                                 switch(modifier) {
     444             :                                                         default:
     445      137919 :                                                                 i_num = (wide_int) va_arg(ap, int);
     446      137919 :                                                                 break;
     447             :                                                         case LM_LONG_DOUBLE:
     448           0 :                                                                 goto fmt_error;
     449             :                                                         case LM_LONG:
     450     1850835 :                                                                 i_num = (wide_int) va_arg(ap, long int);
     451     1850835 :                                                                 break;
     452             :                                                         case LM_SIZE_T:
     453             : #if SIZEOF_SSIZE_T
     454           2 :                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
     455             : #else
     456             :                                                                 i_num = (wide_int) va_arg(ap, size_t);
     457             : #endif
     458           2 :                                                                 break;
     459             : #if SIZEOF_LONG_LONG
     460             :                                                         case LM_LONG_LONG:
     461           0 :                                                                 i_num = (wide_int) va_arg(ap, wide_int);
     462           0 :                                                                 break;
     463             : #endif
     464             : #if SIZEOF_INTMAX_T
     465             :                                                         case LM_INTMAX_T:
     466           0 :                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
     467           0 :                                                                 break;
     468             : #endif
     469             : #if SIZEOF_PTRDIFF_T
     470             :                                                         case LM_PTRDIFF_T:
     471           0 :                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
     472             :                                                                 break;
     473             : #endif
     474             :                                                 }
     475             :                                         }
     476     1989966 :                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
     477             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     478     1989966 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     479             : 
     480     1989966 :                                         if (*fmt != 'u') {
     481     1988756 :                                                 if (is_negative)
     482        8814 :                                                         prefix_char = '-';
     483     1979942 :                                                 else if (print_sign)
     484           0 :                                                         prefix_char = '+';
     485     1979942 :                                                 else if (print_blank)
     486           0 :                                                         prefix_char = ' ';
     487             :                                         }
     488     1989966 :                                         break;
     489             : 
     490             : 
     491             :                                 case 'o':
     492           2 :                                         switch(modifier) {
     493             :                                                 default:
     494           2 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     495           2 :                                                         break;
     496             :                                                 case LM_LONG_DOUBLE:
     497           0 :                                                         goto fmt_error;
     498             :                                                 case LM_LONG:
     499           0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     500           0 :                                                         break;
     501             :                                                 case LM_SIZE_T:
     502           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     503           0 :                                                         break;
     504             : #if SIZEOF_LONG_LONG
     505             :                                                 case LM_LONG_LONG:
     506           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     507           0 :                                                         break;
     508             : #endif
     509             : #if SIZEOF_INTMAX_T
     510             :                                                 case LM_INTMAX_T:
     511           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     512           0 :                                                         break;
     513             : #endif
     514             : #if SIZEOF_PTRDIFF_T
     515             :                                                 case LM_PTRDIFF_T:
     516           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     517             :                                                         break;
     518             : #endif
     519             :                                         }
     520           2 :                                         s = ap_php_conv_p2(ui_num, 3, *fmt,
     521             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     522           2 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     523           2 :                                         if (alternate_form && *s != '0') {
     524           0 :                                                 *--s = '0';
     525           0 :                                                 s_len++;
     526             :                                         }
     527           2 :                                         break;
     528             : 
     529             : 
     530             :                                 case 'x':
     531             :                                 case 'X':
     532       66092 :                                         switch(modifier) {
     533             :                                                 default:
     534       66085 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     535       66085 :                                                         break;
     536             :                                                 case LM_LONG_DOUBLE:
     537           0 :                                                         goto fmt_error;
     538             :                                                 case LM_LONG:
     539           0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     540           0 :                                                         break;
     541             :                                                 case LM_SIZE_T:
     542           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     543           0 :                                                         break;
     544             : #if SIZEOF_LONG_LONG
     545             :                                                 case LM_LONG_LONG:
     546           7 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     547           7 :                                                         break;
     548             : #endif
     549             : #if SIZEOF_INTMAX_T
     550             :                                                 case LM_INTMAX_T:
     551           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     552           0 :                                                         break;
     553             : #endif
     554             : #if SIZEOF_PTRDIFF_T
     555             :                                                 case LM_PTRDIFF_T:
     556           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     557             :                                                         break;
     558             : #endif
     559             :                                         }
     560       66092 :                                         s = ap_php_conv_p2(ui_num, 4, *fmt,
     561             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     562       66092 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     563       66092 :                                         if (alternate_form && ui_num != 0) {
     564           0 :                                                 *--s = *fmt;    /* 'x' or 'X' */
     565           0 :                                                 *--s = '0';
     566           0 :                                                 s_len += 2;
     567             :                                         }
     568       66092 :                                         break;
     569             : 
     570             : 
     571             :                                 case 's':
     572             :                                 case 'v':
     573     5399399 :                                         s = va_arg(ap, char *);
     574     5399399 :                                         if (s != NULL) {
     575     5399384 :                                                 if (!adjust_precision) {
     576     5399105 :                                                         s_len = strlen(s);
     577             :                                                 } else {
     578         279 :                                                         s_len = strnlen(s, precision);
     579             :                                                 }
     580             :                                         } else {
     581          15 :                                                 s = S_NULL;
     582          15 :                                                 s_len = S_NULL_LEN;
     583             :                                         }
     584     5399399 :                                         pad_char = ' ';
     585     5399399 :                                         break;
     586             : 
     587             : 
     588             :                                 case 'f':
     589             :                                 case 'F':
     590             :                                 case 'e':
     591             :                                 case 'E':
     592        1589 :                                         switch(modifier) {
     593             :                                                 case LM_LONG_DOUBLE:
     594           0 :                                                         fp_num = (double) va_arg(ap, long double);
     595           0 :                                                         break;
     596             :                                                 case LM_STD:
     597        1589 :                                                         fp_num = va_arg(ap, double);
     598        1589 :                                                         break;
     599             :                                                 default:
     600           0 :                                                         goto fmt_error;
     601             :                                         }
     602             : 
     603        1589 :                                         if (zend_isnan(fp_num)) {
     604           0 :                                                 s = "nan";
     605           0 :                                                 s_len = 3;
     606        1589 :                                         } else if (zend_isinf(fp_num)) {
     607           2 :                                                 s = "inf";
     608           2 :                                                 s_len = 3;
     609             :                                         } else {
     610             : #ifdef HAVE_LOCALE_H
     611        1587 :                                                 if (!lconv) {
     612        1587 :                                                         lconv = localeconv();
     613             :                                                 }
     614             : #endif
     615        1587 :                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
     616             :                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
     617        1587 :                                                  (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     618             :                                                                         &is_negative, &num_buf[1], &s_len);
     619        1587 :                                                 if (is_negative)
     620           0 :                                                         prefix_char = '-';
     621        1587 :                                                 else if (print_sign)
     622           0 :                                                         prefix_char = '+';
     623        1587 :                                                 else if (print_blank)
     624           0 :                                                         prefix_char = ' ';
     625             :                                         }
     626        1589 :                                         break;
     627             : 
     628             : 
     629             :                                 case 'g':
     630             :                                 case 'k':
     631             :                                 case 'G':
     632             :                                 case 'H':
     633       15662 :                                         switch(modifier) {
     634             :                                                 case LM_LONG_DOUBLE:
     635           0 :                                                         fp_num = (double) va_arg(ap, long double);
     636           0 :                                                         break;
     637             :                                                 case LM_STD:
     638       15662 :                                                         fp_num = va_arg(ap, double);
     639       15662 :                                                         break;
     640             :                                                 default:
     641           0 :                                                         goto fmt_error;
     642             :                                         }
     643             : 
     644       15662 :                                         if (zend_isnan(fp_num)) {
     645         212 :                                                 s = "NAN";
     646         212 :                                                 s_len = 3;
     647         212 :                                                 break;
     648       15450 :                                         } else if (zend_isinf(fp_num)) {
     649         221 :                                                 if (fp_num > 0) {
     650         175 :                                                         s = "INF";
     651         175 :                                                         s_len = 3;
     652             :                                                 } else {
     653          46 :                                                         s = "-INF";
     654          46 :                                                         s_len = 4;
     655             :                                                 }
     656         221 :                                                 break;
     657             :                                         }
     658             : 
     659       15229 :                                         if (adjust_precision == NO)
     660           0 :                                                 precision = FLOAT_DIGITS;
     661       15229 :                                         else if (precision == 0)
     662           0 :                                                 precision = 1;
     663             :                                         /*
     664             :                                          * * We use &num_buf[ 1 ], so that we have room for the sign
     665             :                                          */
     666             : #ifdef HAVE_LOCALE_H
     667       15229 :                                         if (!lconv) {
     668       15229 :                                                 lconv = localeconv();
     669             :                                         }
     670             : #endif
     671       15229 :                                         s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
     672       15229 :                                         if (*s == '-')
     673        3261 :                                                 prefix_char = *s++;
     674       11968 :                                         else if (print_sign)
     675           0 :                                                 prefix_char = '+';
     676       11968 :                                         else if (print_blank)
     677           0 :                                                 prefix_char = ' ';
     678             : 
     679       15229 :                                         s_len = strlen(s);
     680             : 
     681       15229 :                                         if (alternate_form && (strchr(s, '.')) == NULL)
     682           0 :                                                 s[s_len++] = '.';
     683       15229 :                                         break;
     684             : 
     685             : 
     686             :                                 case 'c':
     687      160691 :                                         char_buf[0] = (char) (va_arg(ap, int));
     688      160691 :                                         s = &char_buf[0];
     689      160691 :                                         s_len = 1;
     690      160691 :                                         pad_char = ' ';
     691      160691 :                                         break;
     692             : 
     693             : 
     694             :                                 case '%':
     695           5 :                                         char_buf[0] = '%';
     696           5 :                                         s = &char_buf[0];
     697           5 :                                         s_len = 1;
     698           5 :                                         pad_char = ' ';
     699           5 :                                         break;
     700             : 
     701             : 
     702             :                                 case 'n':
     703           0 :                                         *(va_arg(ap, int *)) = xbuf->len;
     704           0 :                                         goto skip_output;
     705             : 
     706             :                                         /*
     707             :                                          * Always extract the argument as a "char *" pointer. We
     708             :                                          * should be using "void *" but there are still machines
     709             :                                          * that don't understand it.
     710             :                                          * If the pointer size is equal to the size of an unsigned
     711             :                                          * integer we convert the pointer to a hex number, otherwise
     712             :                                          * we print "%p" to indicate that we don't handle "%p".
     713             :                                          */
     714             :                                 case 'p':
     715             :                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
     716        1105 :                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
     717        1105 :                                                 s = ap_php_conv_p2(ui_num, 4, 'x',
     718             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     719        1105 :                                                 if (ui_num != 0) {
     720        1105 :                                                         *--s = 'x';
     721        1105 :                                                         *--s = '0';
     722        1105 :                                                         s_len += 2;
     723             :                                                 }
     724             :                                         } else {
     725             :                                                 s = "%p";
     726             :                                                 s_len = 2;
     727             :                                         }
     728        1105 :                                         pad_char = ' ';
     729        1105 :                                         break;
     730             : 
     731             : 
     732             :                                 case NUL:
     733             :                                         /*
     734             :                                          * The last character of the format string was %.
     735             :                                          * We ignore it.
     736             :                                          */
     737           0 :                                         continue;
     738             : 
     739             : 
     740             : fmt_error:
     741           0 :                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
     742             :                                         /*
     743             :                                          * The default case is for unrecognized %'s.
     744             :                                          * We print %<char> to help the user identify what
     745             :                                          * option is not understood.
     746             :                                          * This is also useful in case the user wants to pass
     747             :                                          * the output of format_converter to another function
     748             :                                          * that understands some other %<char> (like syslog).
     749             :                                          * Note that we can't point s inside fmt because the
     750             :                                          * unknown <char> could be preceded by width etc.
     751             :                                          */
     752             :                                 default:
     753           0 :                                         char_buf[0] = '%';
     754           0 :                                         char_buf[1] = *fmt;
     755           0 :                                         s = char_buf;
     756           0 :                                         s_len = 2;
     757           0 :                                         pad_char = ' ';
     758             :                                         break;
     759             :                         }
     760             : 
     761     7634511 :                         if (prefix_char != NUL) {
     762       12075 :                                 *--s = prefix_char;
     763       12075 :                                 s_len++;
     764             :                         }
     765     7634511 :                         if (adjust_width && adjust == RIGHT && min_width > s_len) {
     766      193599 :                                 if (pad_char == '0' && prefix_char != NUL) {
     767           0 :                                         INS_CHAR(xbuf, *s);
     768           0 :                                         s++;
     769           0 :                                         s_len--;
     770           0 :                                         min_width--;
     771             :                                 }
     772      193599 :                                 PAD(xbuf, min_width - s_len, pad_char);
     773             :                         }
     774             :                         /*
     775             :                          * Print the string s.
     776             :                          */
     777     7634511 :                         INS_STRING(xbuf, s, s_len);
     778             : 
     779     7634511 :                         if (adjust_width && adjust == LEFT && min_width > s_len)
     780          55 :                                 PAD(xbuf, min_width - s_len, pad_char);
     781     7634511 :                         if (free_zcopy) {
     782             :                                 zval_dtor(&zcopy);
     783             :                         }
     784             :                 }
     785             : skip_output:
     786    17632178 :                 fmt++;
     787             :         }
     788     4862515 :         return;
     789             : }
     790             : /* }}} */
     791             : 
     792             : /*
     793             :  * This is the general purpose conversion function.
     794             :  */
     795     4862515 : PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
     796             : {
     797     4862515 :         smart_str xbuf = {0};
     798             : 
     799     4862515 :         xbuf_format_converter(&xbuf, format, ap);
     800             : 
     801     4862515 :         if (max_len && xbuf.len > max_len) {
     802           2 :                 xbuf.len = max_len;
     803             :         }
     804     4862515 :         smart_str_0(&xbuf);
     805             : 
     806     4862515 :         *pbuf = xbuf.c;
     807             : 
     808     4862515 :         return xbuf.len;
     809             : }
     810             : /* }}} */
     811             : 
     812     2144831 : PHPAPI int spprintf(char **pbuf, size_t max_len, const char *format, ...) /* {{{ */
     813             : {
     814             :         int cc;
     815             :         va_list ap;
     816             : 
     817     2144831 :         va_start(ap, format);
     818     2144831 :         cc = vspprintf(pbuf, max_len, format, ap);
     819     2144831 :         va_end(ap);
     820     2144831 :         return (cc);
     821             : }
     822             : /* }}} */
     823             : 
     824             : /*
     825             :  * Local variables:
     826             :  * tab-width: 4
     827             :  * c-basic-offset: 4
     828             :  * End:
     829             :  * vim600: sw=4 ts=4 fdm=marker
     830             :  * vim<600: sw=4 ts=4
     831             :  */

Generated by: LCOV version 1.10

Generated at Sun, 17 Aug 2014 15:22:05 +0000 (4 days ago)

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