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

Generated by: LCOV version 1.10

Generated at Wed, 24 Aug 2016 12:20:35 +0000 (2 days ago)

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