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: 215 327 65.7 %
Date: 2015-07-05 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2015 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             : #ifdef ZTS
      97             : #include "ext/standard/php_string.h"
      98             : #define LCONV_DECIMAL_POINT (*lconv.decimal_point)
      99             : #else
     100             : #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
     101             : #endif
     102             : #else
     103             : #define LCONV_DECIMAL_POINT '.'
     104             : #endif
     105             : 
     106             : #include "snprintf.h"
     107             : 
     108             : #define FALSE           0
     109             : #define TRUE            1
     110             : #define NUL             '\0'
     111             : #define INT_NULL        ((int *)0)
     112             : 
     113             : #define S_NULL          "(null)"
     114             : #define S_NULL_LEN      6
     115             : 
     116             : #define FLOAT_DIGITS    6
     117             : #define EXPONENT_LENGTH 10
     118             : 
     119             : #include "zend_smart_str.h"
     120             : #include "ext/standard/php_smart_string.h"
     121             : 
     122             : /* {{{ macros */
     123             : 
     124             : #define INS_CHAR(xbuf, ch, is_char) do { \
     125             :         if ((is_char)) { \
     126             :                 smart_string_appendc((smart_string *)(xbuf), (ch)); \
     127             :         } else { \
     128             :                 smart_str_appendc((smart_str *)(xbuf), (ch)); \
     129             :         } \
     130             : } while (0);
     131             : 
     132             : #define INS_STRING(xbuf, str, len, is_char) do { \
     133             :         if ((is_char)) { \
     134             :                 smart_string_appendl((smart_string *)(xbuf), (str), (len)); \
     135             :         } else { \
     136             :                 smart_str_appendl((smart_str *)(xbuf), (str), (len)); \
     137             :         } \
     138             : } while (0);
     139             : 
     140             : #define PAD_CHAR(xbuf, ch, count, is_char) do { \
     141             :         size_t newlen; \
     142             :         if ((is_char)) { \
     143             :                 smart_string_alloc(((smart_string *)(xbuf)), (count), 0); \
     144             :                 memset(((smart_string *)(xbuf))->c + ((smart_string *)(xbuf))->len, (ch), (count)); \
     145             :                 ((smart_string *)(xbuf))->len += (count); \
     146             :         } else { \
     147             :                 smart_str_alloc(((smart_str *)(xbuf)), (count), 0); \
     148             :                 memset(((smart_str *)(xbuf))->s->val + ((smart_str *)(xbuf))->s->len, (ch), (count)); \
     149             :                 ((smart_str *)(xbuf))->s->len += (count); \
     150             :         } \
     151             : } while (0);
     152             : 
     153             : /*
     154             :  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
     155             :  *
     156             :  * XXX: this is a magic number; do not decrease it
     157             :  * Emax = 1023
     158             :  * NDIG = 320
     159             :  * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
     160             :  */
     161             : #define NUM_BUF_SIZE            2048
     162             : 
     163             : #define NUM(c) (c - '0')
     164             : 
     165             : #define STR_TO_DEC(str, num) do {                       \
     166             :         num = NUM(*str++);                      \
     167             :         while (isdigit((int)*str)) {            \
     168             :                 num *= 10;                              \
     169             :                 num += NUM(*str++);                     \
     170             :                 if (num >= INT_MAX / 10) {                   \
     171             :                         while (isdigit((int)*str++));   \
     172             :                         break;                                                  \
     173             :                 }                                                                       \
     174             :     }                                                                           \
     175             : } while (0)
     176             : 
     177             : /*
     178             :  * This macro does zero padding so that the precision
     179             :  * requirement is satisfied. The padding is done by
     180             :  * adding '0's to the left of the string that is going
     181             :  * to be printed.
     182             :  */
     183             : #define FIX_PRECISION(adjust, precision, s, s_len) do { \
     184             :     if (adjust)                                                         \
     185             :                 while (s_len < precision) {                  \
     186             :                         *--s = '0';                                     \
     187             :                         s_len++;                                        \
     188             :                 }                                                                                               \
     189             : } while (0)
     190             : 
     191             : /* }}} */
     192             : 
     193             : #if !HAVE_STRNLEN
     194             : static size_t strnlen(const char *s, size_t maxlen) {
     195             :         char *r = memchr(s, '\0', maxlen);
     196             :         return r ? r-s : maxlen;
     197             : }
     198             : #endif
     199             : 
     200             : /*
     201             :  * Do format conversion placing the output in buffer
     202             :  */
     203     3268510 : static void xbuf_format_converter(void *xbuf, zend_bool is_char, const char *fmt, va_list ap) /* {{{ */
     204             : {
     205     3268510 :         char *s = NULL;
     206             :         size_t s_len;
     207             :         int free_zcopy;
     208             :         zval *zvp, zcopy;
     209             : 
     210     3268510 :         int min_width = 0;
     211     3268510 :         int precision = 0;
     212             :         enum {
     213             :                 LEFT, RIGHT
     214             :         } adjust;
     215             :         char pad_char;
     216             :         char prefix_char;
     217             : 
     218             :         double fp_num;
     219     3268510 :         wide_int i_num = (wide_int) 0;
     220     3268510 :         u_wide_int ui_num = (u_wide_int) 0;
     221             : 
     222             :         char num_buf[NUM_BUF_SIZE];
     223             :         char char_buf[2];                       /* for printing %% and %<unknown> */
     224             : 
     225             : #ifdef HAVE_LOCALE_H
     226             : #ifdef ZTS
     227             :         struct lconv lconv;
     228             : #else
     229     3268510 :         struct lconv *lconv = NULL;
     230             : #endif
     231             : #endif
     232             : 
     233             :         /*
     234             :          * Flag variables
     235             :          */
     236             :         length_modifier_e modifier;
     237             :         boolean_e alternate_form;
     238             :         boolean_e print_sign;
     239             :         boolean_e print_blank;
     240             :         boolean_e adjust_precision;
     241             :         boolean_e adjust_width;
     242             :         bool_int is_negative;
     243             : 
     244    24239563 :         while (*fmt) {
     245    17702543 :                 if (*fmt != '%') {
     246    11635191 :                         INS_CHAR(xbuf, *fmt, is_char);
     247             :                 } else {
     248             :                         /*
     249             :                          * Default variable settings
     250             :                          */
     251     6067352 :                         adjust = RIGHT;
     252     6067352 :                         alternate_form = print_sign = print_blank = NO;
     253     6067352 :                         pad_char = ' ';
     254     6067352 :                         prefix_char = NUL;
     255     6067352 :                         free_zcopy = 0;
     256             : 
     257     6067352 :                         fmt++;
     258             : 
     259             :                         /*
     260             :                          * Try to avoid checking for flags, width or precision
     261             :                          */
     262     6298489 :                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
     263             :                                 /*
     264             :                                  * Recognize flags: -, #, BLANK, +
     265             :                                  */
     266       68582 :                                 for (;; fmt++) {
     267      299719 :                                         if (*fmt == '-')
     268          70 :                                                 adjust = LEFT;
     269      299649 :                                         else if (*fmt == '+')
     270           0 :                                                 print_sign = YES;
     271      299649 :                                         else if (*fmt == '#')
     272           0 :                                                 alternate_form = YES;
     273      299649 :                                         else if (*fmt == ' ')
     274           0 :                                                 print_blank = YES;
     275      299649 :                                         else if (*fmt == '0')
     276       68512 :                                                 pad_char = '0';
     277             :                                         else
     278      231137 :                                                 break;
     279       68582 :                                 }
     280             : 
     281             :                                 /*
     282             :                                  * Check if a width was specified
     283             :                                  */
     284      231137 :                                 if (isdigit((int)*fmt)) {
     285       68379 :                                         STR_TO_DEC(fmt, min_width);
     286       68379 :                                         adjust_width = YES;
     287      162758 :                                 } else if (*fmt == '*') {
     288      146577 :                                         min_width = va_arg(ap, int);
     289      146577 :                                         fmt++;
     290      146577 :                                         adjust_width = YES;
     291      146577 :                                         if (min_width < 0) {
     292           0 :                                                 adjust = LEFT;
     293           0 :                                                 min_width = -min_width;
     294             :                                         }
     295             :                                 } else
     296       16181 :                                         adjust_width = NO;
     297             : 
     298             :                                 /*
     299             :                                  * Check if a precision was specified
     300             :                                  */
     301      231137 :                                 if (*fmt == '.') {
     302       16174 :                                         adjust_precision = YES;
     303       16174 :                                         fmt++;
     304       16174 :                                         if (isdigit((int)*fmt)) {
     305         438 :                                                 STR_TO_DEC(fmt, precision);
     306       15736 :                                         } else if (*fmt == '*') {
     307       15736 :                                                 precision = va_arg(ap, int);
     308       15736 :                                                 fmt++;
     309       15736 :                                                 if (precision < 0)
     310           0 :                                                         precision = 0;
     311             :                                         } else
     312           0 :                                                 precision = 0;
     313             : 
     314       16174 :                                         if (precision > FORMAT_CONV_MAX_PRECISION) {
     315         576 :                                                 precision = FORMAT_CONV_MAX_PRECISION;
     316             :                                         }
     317             :                                 } else
     318      214963 :                                         adjust_precision = NO;
     319             :                         } else
     320     5836215 :                                 adjust_precision = adjust_width = NO;
     321             : 
     322             :                         /*
     323             :                          * Modifier check
     324             :                          */
     325     6067352 :                         switch (*fmt) {
     326             :                                 case 'L':
     327           0 :                                         fmt++;
     328           0 :                                         modifier = LM_LONG_DOUBLE;
     329           0 :                                         break;
     330             :                                 case 'I':
     331           0 :                                         fmt++;
     332             : #if SIZEOF_LONG_LONG
     333           0 :                                         if (*fmt == '6' && *(fmt+1) == '4') {
     334           0 :                                                 fmt += 2;
     335           0 :                                                 modifier = LM_LONG_LONG;
     336             :                                         } else
     337             : #endif
     338           0 :                                                 if (*fmt == '3' && *(fmt+1) == '2') {
     339           0 :                                                         fmt += 2;
     340           0 :                                                         modifier = LM_LONG;
     341             :                                                 } else {
     342             : #ifdef _WIN64
     343             :                                                         modifier = LM_LONG_LONG;
     344             : #else
     345           0 :                                                         modifier = LM_LONG;
     346             : #endif
     347             :                                                 }
     348           0 :                                         break;
     349             :                                 case 'l':
     350      152664 :                                         fmt++;
     351             : #if SIZEOF_LONG_LONG
     352      152664 :                                         if (*fmt == 'l') {
     353           0 :                                                 fmt++;
     354           0 :                                                 modifier = LM_LONG_LONG;
     355             :                                         } else
     356             : #endif
     357      152664 :                                                 modifier = LM_LONG;
     358      152664 :                                         break;
     359             :                                 case 'z':
     360         145 :                                         fmt++;
     361         145 :                                         modifier = LM_SIZE_T;
     362         145 :                                         break;
     363             :                                 case 'j':
     364           0 :                                         fmt++;
     365             : #if SIZEOF_INTMAX_T
     366           0 :                                         modifier = LM_INTMAX_T;
     367             : #else
     368             :                                         modifier = LM_SIZE_T;
     369             : #endif
     370           0 :                                         break;
     371             :                                 case 't':
     372           0 :                                         fmt++;
     373             : #if SIZEOF_PTRDIFF_T
     374           0 :                                         modifier = LM_PTRDIFF_T;
     375             : #else
     376             :                                         modifier = LM_SIZE_T;
     377             : #endif
     378           0 :                                         break;
     379             :                                 case 'p': {
     380        2160 :                                                 char __next = *(fmt+1);
     381        3192 :                                                 if ('d' == __next || 'u' == __next || 'x' == __next || 'o' == __next) {
     382        1032 :                                                         fmt++;
     383        1032 :                                                         modifier = LM_PHP_INT_T;
     384             :                                                 } else {
     385        1128 :                                                         modifier = LM_STD;
     386             :                                                 }
     387             :                                         }
     388        2160 :                                         break;
     389             :                                 case 'h':
     390           1 :                                         fmt++;
     391           1 :                                         if (*fmt == 'h') {
     392           0 :                                                 fmt++;
     393             :                                         }
     394             :                                         /* these are promoted to int, so no break */
     395             :                                 default:
     396     5912383 :                                         modifier = LM_STD;
     397             :                                         break;
     398             :                         }
     399             : 
     400             :                         /*
     401             :                          * Argument extraction and printing.
     402             :                          * First we determine the argument type.
     403             :                          * Then, we convert the argument to a string.
     404             :                          * On exit from the switch, s points to the string that
     405             :                          * must be printed, s_len has the length of the string
     406             :                          * The precision requirements, if any, are reflected in s_len.
     407             :                          *
     408             :                          * NOTE: pad_char may be set to '0' because of the 0 flag.
     409             :                          *   It is reset to ' ' by non-numeric formats
     410             :                          */
     411     6067352 :                         switch (*fmt) {
     412             :                                 case 'Z': {
     413           0 :                                                                         zvp = (zval*) va_arg(ap, zval*);
     414           0 :                                         free_zcopy = zend_make_printable_zval(zvp, &zcopy);
     415           0 :                                         if (free_zcopy) {
     416           0 :                                                 zvp = &zcopy;
     417             :                                         }
     418           0 :                                         s_len = Z_STRLEN_P(zvp);
     419           0 :                                         s = Z_STRVAL_P(zvp);
     420           0 :                                         if (adjust_precision && precision < s_len) {
     421           0 :                                                 s_len = precision;
     422             :                                         }
     423           0 :                                         break;
     424             :                                 }
     425             :                                 case 'u':
     426         799 :                                         switch(modifier) {
     427             :                                                 default:
     428         651 :                                                         i_num = (wide_int) va_arg(ap, unsigned int);
     429         651 :                                                         break;
     430             :                                                 case LM_LONG_DOUBLE:
     431           0 :                                                         goto fmt_error;
     432             :                                                 case LM_LONG:
     433          12 :                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
     434          12 :                                                         break;
     435             :                                                 case LM_SIZE_T:
     436         135 :                                                         i_num = (wide_int) va_arg(ap, size_t);
     437         135 :                                                         break;
     438             : #if SIZEOF_LONG_LONG
     439             :                                                 case LM_LONG_LONG:
     440           0 :                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
     441           0 :                                                         break;
     442             : #endif
     443             : #if SIZEOF_INTMAX_T
     444             :                                                 case LM_INTMAX_T:
     445           0 :                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
     446           0 :                                                         break;
     447             : #endif
     448             : #if SIZEOF_PTRDIFF_T
     449             :                                                 case LM_PTRDIFF_T:
     450           0 :                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
     451           0 :                                                         break;
     452             : #endif
     453             :                                                 case LM_PHP_INT_T:
     454           1 :                                                         i_num = (wide_int) va_arg(ap, zend_ulong);
     455             :                                                         break;
     456             :                                         }
     457             :                                         /*
     458             :                                          * The rest also applies to other integer formats, so fall
     459             :                                          * into that case.
     460             :                                          */
     461             :                                 case 'd':
     462             :                                 case 'i':
     463             :                                         /*
     464             :                                          * Get the arg if we haven't already.
     465             :                                          */
     466      249290 :                                         if ((*fmt) != 'u') {
     467      248491 :                                                 switch(modifier) {
     468             :                                                         default:
     469      134862 :                                                                 i_num = (wide_int) va_arg(ap, int);
     470      134862 :                                                                 break;
     471             :                                                         case LM_LONG_DOUBLE:
     472           0 :                                                                 goto fmt_error;
     473             :                                                         case LM_LONG:
     474      112588 :                                                                 i_num = (wide_int) va_arg(ap, long int);
     475      112588 :                                                                 break;
     476             :                                                         case LM_SIZE_T:
     477             : #if SIZEOF_SSIZE_T
     478          10 :                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
     479             : #else
     480             :                                                                 i_num = (wide_int) va_arg(ap, size_t);
     481             : #endif
     482          10 :                                                                 break;
     483             : #if SIZEOF_LONG_LONG
     484             :                                                         case LM_LONG_LONG:
     485           0 :                                                                 i_num = (wide_int) va_arg(ap, wide_int);
     486           0 :                                                                 break;
     487             : #endif
     488             : #if SIZEOF_INTMAX_T
     489             :                                                         case LM_INTMAX_T:
     490           0 :                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
     491           0 :                                                                 break;
     492             : #endif
     493             : #if SIZEOF_PTRDIFF_T
     494             :                                                         case LM_PTRDIFF_T:
     495           0 :                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
     496           0 :                                                                 break;
     497             : #endif
     498             :                                                         case LM_PHP_INT_T:
     499        1031 :                                                                 i_num = (wide_int) va_arg(ap, zend_long);
     500             :                                                                 break;
     501             :                                                 }
     502             :                                         }
     503      249290 :                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
     504             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     505      249290 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     506             : 
     507      249290 :                                         if (*fmt != 'u') {
     508      248491 :                                                 if (is_negative)
     509        2906 :                                                         prefix_char = '-';
     510      245585 :                                                 else if (print_sign)
     511           0 :                                                         prefix_char = '+';
     512      245585 :                                                 else if (print_blank)
     513           0 :                                                         prefix_char = ' ';
     514             :                                         }
     515      249290 :                                         break;
     516             : 
     517             : 
     518             :                                 case 'o':
     519           2 :                                         switch(modifier) {
     520             :                                                 default:
     521           2 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     522           2 :                                                         break;
     523             :                                                 case LM_LONG_DOUBLE:
     524           0 :                                                         goto fmt_error;
     525             :                                                 case LM_LONG:
     526           0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     527           0 :                                                         break;
     528             :                                                 case LM_SIZE_T:
     529           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     530           0 :                                                         break;
     531             : #if SIZEOF_LONG_LONG
     532             :                                                 case LM_LONG_LONG:
     533           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     534           0 :                                                         break;
     535             : #endif
     536             : #if SIZEOF_INTMAX_T
     537             :                                                 case LM_INTMAX_T:
     538           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     539           0 :                                                         break;
     540             : #endif
     541             : #if SIZEOF_PTRDIFF_T
     542             :                                                 case LM_PTRDIFF_T:
     543           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     544           0 :                                                         break;
     545             : #endif
     546             :                                                 case LM_PHP_INT_T:
     547           0 :                                                         ui_num = (u_wide_int) va_arg(ap, zend_ulong);
     548             :                                                         break;
     549             :                                         }
     550           2 :                                         s = ap_php_conv_p2(ui_num, 3, *fmt,
     551             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     552           2 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     553           2 :                                         if (alternate_form && *s != '0') {
     554           0 :                                                 *--s = '0';
     555           0 :                                                 s_len++;
     556             :                                         }
     557           2 :                                         break;
     558             : 
     559             : 
     560             :                                 case 'x':
     561             :                                 case 'X':
     562       67650 :                                         switch(modifier) {
     563             :                                                 default:
     564       27586 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     565       27586 :                                                         break;
     566             :                                                 case LM_LONG_DOUBLE:
     567           0 :                                                         goto fmt_error;
     568             :                                                 case LM_LONG:
     569       40064 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     570       40064 :                                                         break;
     571             :                                                 case LM_SIZE_T:
     572           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     573           0 :                                                         break;
     574             : #if SIZEOF_LONG_LONG
     575             :                                                 case LM_LONG_LONG:
     576           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     577           0 :                                                         break;
     578             : #endif
     579             : #if SIZEOF_INTMAX_T
     580             :                                                 case LM_INTMAX_T:
     581           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     582           0 :                                                         break;
     583             : #endif
     584             : #if SIZEOF_PTRDIFF_T
     585             :                                                 case LM_PTRDIFF_T:
     586           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     587           0 :                                                         break;
     588             : #endif
     589             :                                                 case LM_PHP_INT_T:
     590           0 :                                                         ui_num = (u_wide_int) va_arg(ap, zend_ulong);
     591             :                                                         break;
     592             :                                         }
     593       67650 :                                         s = ap_php_conv_p2(ui_num, 4, *fmt,
     594             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     595       67650 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     596       67650 :                                         if (alternate_form && ui_num != 0) {
     597           0 :                                                 *--s = *fmt;    /* 'x' or 'X' */
     598           0 :                                                 *--s = '0';
     599           0 :                                                 s_len += 2;
     600             :                                         }
     601       67650 :                                         break;
     602             : 
     603             : 
     604             :                                 case 's':
     605             :                                 case 'v':
     606     5564095 :                                         s = va_arg(ap, char *);
     607     5564095 :                                         if (s != NULL) {
     608     5564079 :                                                 if (!adjust_precision) {
     609     5563792 :                                                         s_len = strlen(s);
     610             :                                                 } else {
     611         287 :                                                         s_len = strnlen(s, precision);
     612             :                                                 }
     613             :                                         } else {
     614          16 :                                                 s = S_NULL;
     615          16 :                                                 s_len = S_NULL_LEN;
     616             :                                         }
     617     5564095 :                                         pad_char = ' ';
     618     5564095 :                                         break;
     619             : 
     620             : 
     621             :                                 case 'f':
     622             :                                 case 'F':
     623             :                                 case 'e':
     624             :                                 case 'E':
     625        1588 :                                         switch(modifier) {
     626             :                                                 case LM_LONG_DOUBLE:
     627           0 :                                                         fp_num = (double) va_arg(ap, long double);
     628           0 :                                                         break;
     629             :                                                 case LM_STD:
     630        1588 :                                                         fp_num = va_arg(ap, double);
     631        1588 :                                                         break;
     632             :                                                 default:
     633           0 :                                                         goto fmt_error;
     634             :                                         }
     635             : 
     636        1588 :                                         if (zend_isnan(fp_num)) {
     637           0 :                                                 s = "nan";
     638           0 :                                                 s_len = 3;
     639        1588 :                                         } else if (zend_isinf(fp_num)) {
     640           2 :                                                 s = "inf";
     641           2 :                                                 s_len = 3;
     642             :                                         } else {
     643             : #ifdef HAVE_LOCALE_H
     644             : #ifdef ZTS
     645             :                                                 localeconv_r(&lconv);
     646             : #else
     647        1586 :                                                 if (!lconv) {
     648        1586 :                                                         lconv = localeconv();
     649             :                                                 }
     650             : #endif
     651             : #endif
     652        1586 :                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
     653             :                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
     654        1586 :                                                  (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     655             :                                                                         &is_negative, &num_buf[1], &s_len);
     656        1586 :                                                 if (is_negative)
     657           0 :                                                         prefix_char = '-';
     658        1586 :                                                 else if (print_sign)
     659           0 :                                                         prefix_char = '+';
     660        1586 :                                                 else if (print_blank)
     661           0 :                                                         prefix_char = ' ';
     662             :                                         }
     663        1588 :                                         break;
     664             : 
     665             : 
     666             :                                 case 'g':
     667             :                                 case 'k':
     668             :                                 case 'G':
     669             :                                 case 'H':
     670       14301 :                                         switch(modifier) {
     671             :                                                 case LM_LONG_DOUBLE:
     672           0 :                                                         fp_num = (double) va_arg(ap, long double);
     673           0 :                                                         break;
     674             :                                                 case LM_STD:
     675       14301 :                                                         fp_num = va_arg(ap, double);
     676       14301 :                                                         break;
     677             :                                                 default:
     678           0 :                                                         goto fmt_error;
     679             :                                         }
     680             : 
     681       14301 :                                         if (zend_isnan(fp_num)) {
     682         222 :                                                 s = "NAN";
     683         222 :                                                 s_len = 3;
     684         222 :                                                 break;
     685       14079 :                                         } else if (zend_isinf(fp_num)) {
     686         243 :                                                 if (fp_num > 0) {
     687         184 :                                                         s = "INF";
     688         184 :                                                         s_len = 3;
     689             :                                                 } else {
     690          59 :                                                         s = "-INF";
     691          59 :                                                         s_len = 4;
     692             :                                                 }
     693         243 :                                                 break;
     694             :                                         }
     695             : 
     696       13836 :                                         if (adjust_precision == NO)
     697           0 :                                                 precision = FLOAT_DIGITS;
     698       13836 :                                         else if (precision == 0)
     699           0 :                                                 precision = 1;
     700             :                                         /*
     701             :                                          * * We use &num_buf[ 1 ], so that we have room for the sign
     702             :                                          */
     703             : #ifdef HAVE_LOCALE_H
     704             : #ifdef ZTS
     705             :                                         localeconv_r(&lconv);
     706             : #else
     707       13836 :                                         if (!lconv) {
     708       13836 :                                                 lconv = localeconv();
     709             :                                         }
     710             : #endif
     711             : #endif
     712       13836 :                                         s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
     713       13836 :                                         if (*s == '-')
     714        3182 :                                                 prefix_char = *s++;
     715       10654 :                                         else if (print_sign)
     716           0 :                                                 prefix_char = '+';
     717       10654 :                                         else if (print_blank)
     718           0 :                                                 prefix_char = ' ';
     719             : 
     720       13836 :                                         s_len = strlen(s);
     721             : 
     722       13836 :                                         if (alternate_form && (strchr(s, '.')) == NULL)
     723           0 :                                                 s[s_len++] = '.';
     724       13836 :                                         break;
     725             : 
     726             : 
     727             :                                 case 'c':
     728      169293 :                                         char_buf[0] = (char) (va_arg(ap, int));
     729      169293 :                                         s = &char_buf[0];
     730      169293 :                                         s_len = 1;
     731      169293 :                                         pad_char = ' ';
     732      169293 :                                         break;
     733             : 
     734             : 
     735             :                                 case '%':
     736           5 :                                         char_buf[0] = '%';
     737           5 :                                         s = &char_buf[0];
     738           5 :                                         s_len = 1;
     739           5 :                                         pad_char = ' ';
     740           5 :                                         break;
     741             : 
     742             : 
     743             :                                 case 'n':
     744           0 :                                         *(va_arg(ap, int *)) = is_char? (int)((smart_string *)xbuf)->len : (int)((smart_str *)xbuf)->s->len;
     745           0 :                                         goto skip_output;
     746             : 
     747             :                                         /*
     748             :                                          * Always extract the argument as a "char *" pointer. We
     749             :                                          * should be using "void *" but there are still machines
     750             :                                          * that don't understand it.
     751             :                                          * If the pointer size is equal to the size of an unsigned
     752             :                                          * integer we convert the pointer to a hex number, otherwise
     753             :                                          * we print "%p" to indicate that we don't handle "%p".
     754             :                                          */
     755             :                                 case 'p':
     756             :                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
     757        1128 :                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
     758        1128 :                                                 s = ap_php_conv_p2(ui_num, 4, 'x',
     759             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     760        1128 :                                                 if (ui_num != 0) {
     761        1128 :                                                         *--s = 'x';
     762        1128 :                                                         *--s = '0';
     763        1128 :                                                         s_len += 2;
     764             :                                                 }
     765             :                                         } else {
     766             :                                                 s = "%p";
     767             :                                                 s_len = 2;
     768             :                                         }
     769        1128 :                                         pad_char = ' ';
     770        1128 :                                         break;
     771             : 
     772             : 
     773             :                                 case NUL:
     774             :                                         /*
     775             :                                          * The last character of the format string was %.
     776             :                                          * We ignore it.
     777             :                                          */
     778           0 :                                         continue;
     779             : 
     780             : 
     781             : fmt_error:
     782           0 :                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
     783             :                                         /*
     784             :                                          * The default case is for unrecognized %'s.
     785             :                                          * We print %<char> to help the user identify what
     786             :                                          * option is not understood.
     787             :                                          * This is also useful in case the user wants to pass
     788             :                                          * the output of format_converter to another function
     789             :                                          * that understands some other %<char> (like syslog).
     790             :                                          * Note that we can't point s inside fmt because the
     791             :                                          * unknown <char> could be preceded by width etc.
     792             :                                          */
     793             :                                 default:
     794           0 :                                         char_buf[0] = '%';
     795           0 :                                         char_buf[1] = *fmt;
     796           0 :                                         s = char_buf;
     797           0 :                                         s_len = 2;
     798           0 :                                         pad_char = ' ';
     799             :                                         break;
     800             :                         }
     801             : 
     802     6067352 :                         if (prefix_char != NUL) {
     803        6088 :                                 *--s = prefix_char;
     804        6088 :                                 s_len++;
     805             :                         }
     806     6067352 :                         if (adjust_width && adjust == RIGHT && min_width > s_len) {
     807      187958 :                                 if (pad_char == '0' && prefix_char != NUL) {
     808           0 :                                         INS_CHAR(xbuf, *s, is_char);
     809           0 :                                         s++;
     810           0 :                                         s_len--;
     811           0 :                                         min_width--;
     812             :                                 }
     813      229028 :                                 PAD_CHAR(xbuf, pad_char, min_width - s_len, is_char);
     814             :                         }
     815             :                         /*
     816             :                          * Print the string s.
     817             :                          */
     818     6067352 :                         INS_STRING(xbuf, s, s_len, is_char);
     819             : 
     820     6067352 :                         if (adjust_width && adjust == LEFT && min_width > s_len) {
     821          70 :                                 PAD_CHAR(xbuf, pad_char, min_width - s_len, is_char);
     822             :                         }
     823             : 
     824     6067352 :                         if (free_zcopy) {
     825             :                                 zval_dtor(&zcopy);
     826             :                         }
     827             :                 }
     828             : skip_output:
     829    17702543 :                 fmt++;
     830             :         }
     831     3268510 :         return;
     832             : }
     833             : /* }}} */
     834             : 
     835             : /*
     836             :  * This is the general purpose conversion function.
     837             :  */
     838     3223405 : PHPAPI size_t vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
     839             : {
     840     3223405 :         smart_string buf = {0};
     841             :         size_t result;
     842             : 
     843             :         /* since there are places where (v)spprintf called without checking for null,
     844             :            a bit of defensive coding here */
     845     3223405 :         if(!pbuf) {
     846           0 :                 return 0;
     847             :         }
     848     3223405 :         xbuf_format_converter(&buf, 1, format, ap);
     849             : 
     850     3223405 :         if (max_len && buf.len > max_len) {
     851           0 :                 buf.len = max_len;
     852             :         }
     853             : 
     854     3223405 :         smart_string_0(&buf);
     855             : 
     856     3223405 :         if (buf.c) {
     857     3223354 :                 *pbuf = buf.c;
     858     3223354 :                 result = buf.len;
     859             :         } else {
     860          51 :                 *pbuf = NULL;
     861          51 :                 result = 0;
     862             :         }
     863             : 
     864     3223405 :         return result;
     865             : }
     866             : /* }}} */
     867             : 
     868     2183308 : PHPAPI size_t spprintf(char **pbuf, size_t max_len, const char *format, ...) /* {{{ */
     869             : {
     870             :         size_t cc;
     871             :         va_list ap;
     872             : 
     873     2183308 :         va_start(ap, format);
     874     2183308 :         cc = vspprintf(pbuf, max_len, format, ap);
     875     2183308 :         va_end(ap);
     876     2183308 :         return (cc);
     877             : }
     878             : /* }}} */
     879             : 
     880       45105 : PHPAPI zend_string *vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */
     881             : {
     882       45105 :         smart_str buf = {0};
     883             : 
     884       45105 :         xbuf_format_converter(&buf, 0, format, ap);
     885             : 
     886       45105 :         if (max_len && buf.s && buf.s->len > max_len) {
     887           0 :                 buf.s->len = max_len;
     888             :         }
     889             :         smart_str_0(&buf);
     890             : 
     891       45105 :         return buf.s;
     892             : }
     893             : /* }}} */
     894             : 
     895       36640 : PHPAPI zend_string *strpprintf(size_t max_len, const char *format, ...) /* {{{ */
     896             : {
     897             :         va_list ap;
     898             :         zend_string *str;
     899             : 
     900       36640 :         va_start(ap, format);
     901       36640 :         str = vstrpprintf(max_len, format, ap);
     902       36640 :         va_end(ap);
     903       36640 :         return str;
     904             : }
     905             : /* }}} */
     906             : 
     907             : /*
     908             :  * Local variables:
     909             :  * tab-width: 4
     910             :  * c-basic-offset: 4
     911             :  * End:
     912             :  * vim600: sw=4 ts=4 fdm=marker
     913             :  * vim<600: sw=4 ts=4
     914             :  */

Generated by: LCOV version 1.10

Generated at Sun, 05 Jul 2015 15:45:01 +0000 (3 hours ago)

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