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: 212 325 65.2 %
Date: 2014-12-13 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-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Marcus Boerger <helly@php.net>                               |
      16             :    +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : /* This is the spprintf implementation.
      22             :  * It has emerged from apache snprintf. See original header:
      23             :  */
      24             : 
      25             : /* ====================================================================
      26             :  * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
      27             :  *
      28             :  * Redistribution and use in source and binary forms, with or without
      29             :  * modification, are permitted provided that the following conditions
      30             :  * are met:
      31             :  *
      32             :  * 1. Redistributions of source code must retain the above copyright
      33             :  *    notice, this list of conditions and the following disclaimer.
      34             :  *
      35             :  * 2. Redistributions in binary form must reproduce the above copyright
      36             :  *    notice, this list of conditions and the following disclaimer in
      37             :  *    the documentation and/or other materials provided with the
      38             :  *    distribution.
      39             :  *
      40             :  * 3. All advertising materials mentioning features or use of this
      41             :  *    software must display the following acknowledgment:
      42             :  *    "This product includes software developed by the Apache Group
      43             :  *    for use in the Apache HTTP server project (http://www.apache.org/)."
      44             :  *
      45             :  * 4. The names "Apache Server" and "Apache Group" must not be used to
      46             :  *    endorse or promote products derived from this software without
      47             :  *    prior written permission.
      48             :  *
      49             :  * 5. Redistributions of any form whatsoever must retain the following
      50             :  *    acknowledgment:
      51             :  *    "This product includes software developed by the Apache Group
      52             :  *    for use in the Apache HTTP server project (http://www.apache.org/)."
      53             :  *
      54             :  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
      55             :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      56             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      57             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
      58             :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      59             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      60             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      61             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      62             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      63             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      64             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      65             :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      66             :  * ====================================================================
      67             :  *
      68             :  * This software consists of voluntary contributions made by many
      69             :  * individuals on behalf of the Apache Group and was originally based
      70             :  * on public domain software written at the National Center for
      71             :  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
      72             :  * For more information on the Apache Group and the Apache HTTP server
      73             :  * project, please see <http://www.apache.org/>.
      74             :  *
      75             :  * This code is based on, and used with the permission of, the
      76             :  * SIO stdio-replacement strx_* functions by Panos Tsirigotis
      77             :  * <panos@alumni.cs.colorado.edu> for xinetd.
      78             :  */
      79             : #define _GNU_SOURCE
      80             : #include "php.h"
      81             : 
      82             : #include <stddef.h>
      83             : #include <stdio.h>
      84             : #include <ctype.h>
      85             : #include <sys/types.h>
      86             : #include <stdarg.h>
      87             : #include <string.h>
      88             : #include <stdlib.h>
      89             : #include <math.h>
      90             : #ifdef HAVE_INTTYPES_H
      91             : #include <inttypes.h>
      92             : #endif
      93             : 
      94             : #ifdef HAVE_LOCALE_H
      95             : #include <locale.h>
      96             : #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     3212297 : static void xbuf_format_converter(void *xbuf, zend_bool is_char, const char *fmt, va_list ap) /* {{{ */
     204             : {
     205     3212297 :         char *s = NULL;
     206             :         size_t s_len;
     207             :         int free_zcopy;
     208             :         zval *zvp, zcopy;
     209             : 
     210     3212297 :         int min_width = 0;
     211     3212297 :         int precision = 0;
     212             :         enum {
     213             :                 LEFT, RIGHT
     214             :         } adjust;
     215             :         char pad_char;
     216             :         char prefix_char;
     217             : 
     218             :         double fp_num;
     219     3212297 :         wide_int i_num = (wide_int) 0;
     220     3212297 :         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     3212297 :         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    23513074 :         while (*fmt) {
     245    17088480 :                 if (*fmt != '%') {
     246    11108075 :                         INS_CHAR(xbuf, *fmt, is_char);
     247             :                 } else {
     248             :                         /*
     249             :                          * Default variable settings
     250             :                          */
     251     5980405 :                         adjust = RIGHT;
     252     5980405 :                         alternate_form = print_sign = print_blank = NO;
     253     5980405 :                         pad_char = ' ';
     254     5980405 :                         prefix_char = NUL;
     255     5980405 :                         free_zcopy = 0;
     256             : 
     257     5980405 :                         fmt++;
     258             : 
     259             :                         /*
     260             :                          * Try to avoid checking for flags, width or precision
     261             :                          */
     262     6215381 :                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
     263             :                                 /*
     264             :                                  * Recognize flags: -, #, BLANK, +
     265             :                                  */
     266       67964 :                                 for (;; fmt++) {
     267      302940 :                                         if (*fmt == '-')
     268          59 :                                                 adjust = LEFT;
     269      302881 :                                         else if (*fmt == '+')
     270           0 :                                                 print_sign = YES;
     271      302881 :                                         else if (*fmt == '#')
     272           0 :                                                 alternate_form = YES;
     273      302881 :                                         else if (*fmt == ' ')
     274           0 :                                                 print_blank = YES;
     275      302881 :                                         else if (*fmt == '0')
     276       67905 :                                                 pad_char = '0';
     277             :                                         else
     278      234976 :                                                 break;
     279       67964 :                                 }
     280             : 
     281             :                                 /*
     282             :                                  * Check if a width was specified
     283             :                                  */
     284      234976 :                                 if (isdigit((int)*fmt)) {
     285       67743 :                                         STR_TO_DEC(fmt, min_width);
     286       67743 :                                         adjust_width = YES;
     287      167233 :                                 } else if (*fmt == '*') {
     288      149325 :                                         min_width = va_arg(ap, int);
     289      149325 :                                         fmt++;
     290      149325 :                                         adjust_width = YES;
     291      149325 :                                         if (min_width < 0) {
     292           0 :                                                 adjust = LEFT;
     293           0 :                                                 min_width = -min_width;
     294             :                                         }
     295             :                                 } else
     296       17908 :                                         adjust_width = NO;
     297             : 
     298             :                                 /*
     299             :                                  * Check if a precision was specified
     300             :                                  */
     301      234976 :                                 if (*fmt == '.') {
     302       17901 :                                         adjust_precision = YES;
     303       17901 :                                         fmt++;
     304       17901 :                                         if (isdigit((int)*fmt)) {
     305         474 :                                                 STR_TO_DEC(fmt, precision);
     306       17427 :                                         } else if (*fmt == '*') {
     307       17427 :                                                 precision = va_arg(ap, int);
     308       17427 :                                                 fmt++;
     309       17427 :                                                 if (precision < 0)
     310           0 :                                                         precision = 0;
     311             :                                         } else
     312           0 :                                                 precision = 0;
     313             :                                         
     314       17901 :                                         if (precision > FORMAT_CONV_MAX_PRECISION) {
     315         576 :                                                 precision = FORMAT_CONV_MAX_PRECISION;
     316             :                                         }
     317             :                                 } else
     318      217075 :                                         adjust_precision = NO;
     319             :                         } else
     320     5745429 :                                 adjust_precision = adjust_width = NO;
     321             : 
     322             :                         /*
     323             :                          * Modifier check
     324             :                          */
     325     5980405 :                         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      152945 :                                         fmt++;
     351             : #if SIZEOF_LONG_LONG
     352      152945 :                                         if (*fmt == 'l') {
     353           0 :                                                 fmt++;
     354           0 :                                                 modifier = LM_LONG_LONG;
     355             :                                         } else
     356             : #endif
     357      152945 :                                                 modifier = LM_LONG;
     358      152945 :                                         break;
     359             :                                 case 'z':
     360         137 :                                         fmt++;
     361         137 :                                         modifier = LM_SIZE_T;
     362         137 :                                         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        2180 :                                                 char __next = *(fmt+1);
     381        3222 :                                                 if ('d' == __next || 'u' == __next || 'x' == __next || 'o' == __next) { 
     382        1042 :                                                         fmt++;
     383        1042 :                                                         modifier = LM_PHP_INT_T;
     384             :                                                 } else {
     385        1138 :                                                         modifier = LM_STD;
     386             :                                                 }
     387             :                                         }
     388        2180 :                                         break;
     389             :                                 case 'h':
     390           0 :                                         fmt++;
     391           0 :                                         if (*fmt == 'h') {
     392           0 :                                                 fmt++;
     393             :                                         }
     394             :                                         /* these are promoted to int, so no break */
     395             :                                 default:
     396     5825143 :                                         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     5980405 :                         switch (*fmt) {
     412             :                                 case 'Z': {
     413             :                                         TSRMLS_FETCH();
     414           0 :                                         zvp = (zval*) va_arg(ap, zval*);
     415           0 :                                         free_zcopy = zend_make_printable_zval(zvp, &zcopy TSRMLS_CC);
     416           0 :                                         if (free_zcopy) {
     417           0 :                                                 zvp = &zcopy;
     418             :                                         }
     419           0 :                                         s_len = Z_STRLEN_P(zvp);
     420           0 :                                         s = Z_STRVAL_P(zvp);
     421           0 :                                         if (adjust_precision && precision < s_len) {
     422           0 :                                                 s_len = precision;
     423             :                                         }
     424           0 :                                         break;
     425             :                                 }
     426             :                                 case 'u':
     427         816 :                                         switch(modifier) {
     428             :                                                 default:
     429         659 :                                                         i_num = (wide_int) va_arg(ap, unsigned int);
     430         659 :                                                         break;
     431             :                                                 case LM_LONG_DOUBLE:
     432           0 :                                                         goto fmt_error;
     433             :                                                 case LM_LONG:
     434          28 :                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
     435          28 :                                                         break;
     436             :                                                 case LM_SIZE_T:
     437         127 :                                                         i_num = (wide_int) va_arg(ap, size_t);
     438         127 :                                                         break;
     439             : #if SIZEOF_LONG_LONG
     440             :                                                 case LM_LONG_LONG:
     441           0 :                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
     442           0 :                                                         break;
     443             : #endif
     444             : #if SIZEOF_INTMAX_T
     445             :                                                 case LM_INTMAX_T:
     446           0 :                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
     447           0 :                                                         break;
     448             : #endif
     449             : #if SIZEOF_PTRDIFF_T
     450             :                                                 case LM_PTRDIFF_T:
     451           0 :                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
     452           0 :                                                         break;
     453             : #endif
     454             :                                                 case LM_PHP_INT_T:
     455           2 :                                                         i_num = (wide_int) va_arg(ap, zend_ulong);
     456             :                                                         break;
     457             :                                         }
     458             :                                         /*
     459             :                                          * The rest also applies to other integer formats, so fall
     460             :                                          * into that case.
     461             :                                          */
     462             :                                 case 'd':
     463             :                                 case 'i':
     464             :                                         /*
     465             :                                          * Get the arg if we haven't already.
     466             :                                          */
     467      251645 :                                         if ((*fmt) != 'u') {
     468      250829 :                                                 switch(modifier) {
     469             :                                                         default:
     470      136926 :                                                                 i_num = (wide_int) va_arg(ap, int);
     471      136926 :                                                                 break;
     472             :                                                         case LM_LONG_DOUBLE:
     473           0 :                                                                 goto fmt_error;
     474             :                                                         case LM_LONG:
     475      112853 :                                                                 i_num = (wide_int) va_arg(ap, long int);
     476      112853 :                                                                 break;
     477             :                                                         case LM_SIZE_T:
     478             : #if SIZEOF_SSIZE_T
     479          10 :                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
     480             : #else
     481             :                                                                 i_num = (wide_int) va_arg(ap, size_t);
     482             : #endif
     483          10 :                                                                 break;
     484             : #if SIZEOF_LONG_LONG
     485             :                                                         case LM_LONG_LONG:
     486           0 :                                                                 i_num = (wide_int) va_arg(ap, wide_int);
     487           0 :                                                                 break;
     488             : #endif
     489             : #if SIZEOF_INTMAX_T
     490             :                                                         case LM_INTMAX_T:
     491           0 :                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
     492           0 :                                                                 break;
     493             : #endif
     494             : #if SIZEOF_PTRDIFF_T
     495             :                                                         case LM_PTRDIFF_T:
     496           0 :                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
     497           0 :                                                                 break;
     498             : #endif
     499             :                                                         case LM_PHP_INT_T:
     500        1040 :                                                                 i_num = (wide_int) va_arg(ap, zend_long);
     501             :                                                                 break;
     502             :                                                 }
     503             :                                         }
     504      251645 :                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
     505             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     506      251645 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     507             : 
     508      251645 :                                         if (*fmt != 'u') {
     509      250829 :                                                 if (is_negative)
     510        2939 :                                                         prefix_char = '-';
     511      247890 :                                                 else if (print_sign)
     512           0 :                                                         prefix_char = '+';
     513      247890 :                                                 else if (print_blank)
     514           0 :                                                         prefix_char = ' ';
     515             :                                         }
     516      251645 :                                         break;
     517             : 
     518             : 
     519             :                                 case 'o':
     520           2 :                                         switch(modifier) {
     521             :                                                 default:
     522           2 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     523           2 :                                                         break;
     524             :                                                 case LM_LONG_DOUBLE:
     525           0 :                                                         goto fmt_error;
     526             :                                                 case LM_LONG:
     527           0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     528           0 :                                                         break;
     529             :                                                 case LM_SIZE_T:
     530           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     531           0 :                                                         break;
     532             : #if SIZEOF_LONG_LONG
     533             :                                                 case LM_LONG_LONG:
     534           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     535           0 :                                                         break;
     536             : #endif
     537             : #if SIZEOF_INTMAX_T
     538             :                                                 case LM_INTMAX_T:
     539           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     540           0 :                                                         break;
     541             : #endif
     542             : #if SIZEOF_PTRDIFF_T
     543             :                                                 case LM_PTRDIFF_T:
     544           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     545           0 :                                                         break;
     546             : #endif
     547             :                                                 case LM_PHP_INT_T:
     548           0 :                                                         ui_num = (u_wide_int) va_arg(ap, zend_ulong);
     549             :                                                         break;
     550             :                                         }
     551           2 :                                         s = ap_php_conv_p2(ui_num, 3, *fmt,
     552             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     553           2 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     554           2 :                                         if (alternate_form && *s != '0') {
     555           0 :                                                 *--s = '0';
     556           0 :                                                 s_len++;
     557             :                                         }
     558           2 :                                         break;
     559             : 
     560             : 
     561             :                                 case 'x':
     562             :                                 case 'X':
     563       67010 :                                         switch(modifier) {
     564             :                                                 default:
     565       26946 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     566       26946 :                                                         break;
     567             :                                                 case LM_LONG_DOUBLE:
     568           0 :                                                         goto fmt_error;
     569             :                                                 case LM_LONG:
     570       40064 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     571       40064 :                                                         break;
     572             :                                                 case LM_SIZE_T:
     573           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     574           0 :                                                         break;
     575             : #if SIZEOF_LONG_LONG
     576             :                                                 case LM_LONG_LONG:
     577           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     578           0 :                                                         break;
     579             : #endif
     580             : #if SIZEOF_INTMAX_T
     581             :                                                 case LM_INTMAX_T:
     582           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     583           0 :                                                         break;
     584             : #endif
     585             : #if SIZEOF_PTRDIFF_T
     586             :                                                 case LM_PTRDIFF_T:
     587           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     588           0 :                                                         break;
     589             : #endif
     590             :                                                 case LM_PHP_INT_T:
     591           0 :                                                         ui_num = (u_wide_int) va_arg(ap, zend_ulong);
     592             :                                                         break;
     593             :                                         }
     594       67010 :                                         s = ap_php_conv_p2(ui_num, 4, *fmt,
     595             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     596       67010 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     597       67010 :                                         if (alternate_form && ui_num != 0) {
     598           0 :                                                 *--s = *fmt;    /* 'x' or 'X' */
     599           0 :                                                 *--s = '0';
     600           0 :                                                 s_len += 2;
     601             :                                         }
     602       67010 :                                         break;
     603             : 
     604             : 
     605             :                                 case 's':
     606             :                                 case 'v':
     607     5485132 :                                         s = va_arg(ap, char *);
     608     5485132 :                                         if (s != NULL) {
     609     5485115 :                                                 if (!adjust_precision) {
     610     5484813 :                                                         s_len = strlen(s);
     611             :                                                 } else {
     612         302 :                                                         s_len = strnlen(s, precision);
     613             :                                                 }
     614             :                                         } else {
     615          17 :                                                 s = S_NULL;
     616          17 :                                                 s_len = S_NULL_LEN;
     617             :                                         }
     618     5485132 :                                         pad_char = ' ';
     619     5485132 :                                         break;
     620             : 
     621             : 
     622             :                                 case 'f':
     623             :                                 case 'F':
     624             :                                 case 'e':
     625             :                                 case 'E':
     626        1606 :                                         switch(modifier) {
     627             :                                                 case LM_LONG_DOUBLE:
     628           0 :                                                         fp_num = (double) va_arg(ap, long double);
     629           0 :                                                         break;
     630             :                                                 case LM_STD:
     631        1606 :                                                         fp_num = va_arg(ap, double);
     632        1606 :                                                         break;
     633             :                                                 default:
     634           0 :                                                         goto fmt_error;
     635             :                                         }
     636             : 
     637        1606 :                                         if (zend_isnan(fp_num)) {
     638           0 :                                                 s = "nan";
     639           0 :                                                 s_len = 3;
     640        1606 :                                         } else if (zend_isinf(fp_num)) {
     641           2 :                                                 s = "inf";
     642           2 :                                                 s_len = 3;
     643             :                                         } else {
     644             : #ifdef HAVE_LOCALE_H
     645             : #ifdef ZTS
     646             :                                                 localeconv_r(&lconv);
     647             : #else
     648        1604 :                                                 if (!lconv) {
     649        1604 :                                                         lconv = localeconv();
     650             :                                                 }
     651             : #endif
     652             : #endif
     653        1604 :                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
     654             :                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
     655        1604 :                                                  (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     656             :                                                                         &is_negative, &num_buf[1], &s_len);
     657        1604 :                                                 if (is_negative)
     658           0 :                                                         prefix_char = '-';
     659        1604 :                                                 else if (print_sign)
     660           0 :                                                         prefix_char = '+';
     661        1604 :                                                 else if (print_blank)
     662           0 :                                                         prefix_char = ' ';
     663             :                                         }
     664        1606 :                                         break;
     665             : 
     666             : 
     667             :                                 case 'g':
     668             :                                 case 'k':
     669             :                                 case 'G':
     670             :                                 case 'H':
     671       15995 :                                         switch(modifier) {
     672             :                                                 case LM_LONG_DOUBLE:
     673           0 :                                                         fp_num = (double) va_arg(ap, long double);
     674           0 :                                                         break;
     675             :                                                 case LM_STD:
     676       15995 :                                                         fp_num = va_arg(ap, double);
     677       15995 :                                                         break;
     678             :                                                 default:
     679           0 :                                                         goto fmt_error;
     680             :                                         }
     681             : 
     682       15995 :                                         if (zend_isnan(fp_num)) {
     683         236 :                                                 s = "NAN";
     684         236 :                                                 s_len = 3;
     685         236 :                                                 break;
     686       15759 :                                         } else if (zend_isinf(fp_num)) {
     687         237 :                                                 if (fp_num > 0) {
     688         190 :                                                         s = "INF";
     689         190 :                                                         s_len = 3;
     690             :                                                 } else {
     691          47 :                                                         s = "-INF";
     692          47 :                                                         s_len = 4;
     693             :                                                 }
     694         237 :                                                 break;
     695             :                                         }
     696             : 
     697       15522 :                                         if (adjust_precision == NO)
     698           0 :                                                 precision = FLOAT_DIGITS;
     699       15522 :                                         else if (precision == 0)
     700           0 :                                                 precision = 1;
     701             :                                         /*
     702             :                                          * * We use &num_buf[ 1 ], so that we have room for the sign
     703             :                                          */
     704             : #ifdef HAVE_LOCALE_H
     705             : #ifdef ZTS
     706             :                                         localeconv_r(&lconv);
     707             : #else
     708       15522 :                                         if (!lconv) {
     709       15522 :                                                 lconv = localeconv();
     710             :                                         }
     711             : #endif
     712             : #endif
     713       15522 :                                         s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
     714       15522 :                                         if (*s == '-')
     715        3250 :                                                 prefix_char = *s++;
     716       12272 :                                         else if (print_sign)
     717           0 :                                                 prefix_char = '+';
     718       12272 :                                         else if (print_blank)
     719           0 :                                                 prefix_char = ' ';
     720             : 
     721       15522 :                                         s_len = strlen(s);
     722             : 
     723       15522 :                                         if (alternate_form && (strchr(s, '.')) == NULL)
     724           0 :                                                 s[s_len++] = '.';
     725       15522 :                                         break;
     726             : 
     727             : 
     728             :                                 case 'c':
     729      157872 :                                         char_buf[0] = (char) (va_arg(ap, int));
     730      157872 :                                         s = &char_buf[0];
     731      157872 :                                         s_len = 1;
     732      157872 :                                         pad_char = ' ';
     733      157872 :                                         break;
     734             : 
     735             : 
     736             :                                 case '%':
     737           5 :                                         char_buf[0] = '%';
     738           5 :                                         s = &char_buf[0];
     739           5 :                                         s_len = 1;
     740           5 :                                         pad_char = ' ';
     741           5 :                                         break;
     742             : 
     743             : 
     744             :                                 case 'n':
     745           0 :                                         *(va_arg(ap, int *)) = is_char? (int)((smart_string *)xbuf)->len : (int)((smart_str *)xbuf)->s->len;
     746           0 :                                         goto skip_output;
     747             : 
     748             :                                         /*
     749             :                                          * Always extract the argument as a "char *" pointer. We
     750             :                                          * should be using "void *" but there are still machines
     751             :                                          * that don't understand it.
     752             :                                          * If the pointer size is equal to the size of an unsigned
     753             :                                          * integer we convert the pointer to a hex number, otherwise
     754             :                                          * we print "%p" to indicate that we don't handle "%p".
     755             :                                          */
     756             :                                 case 'p':
     757             :                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
     758        1138 :                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
     759        1138 :                                                 s = ap_php_conv_p2(ui_num, 4, 'x',
     760             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     761        1138 :                                                 if (ui_num != 0) {
     762        1138 :                                                         *--s = 'x';
     763        1138 :                                                         *--s = '0';
     764        1138 :                                                         s_len += 2;
     765             :                                                 }
     766             :                                         } else {
     767             :                                                 s = "%p";
     768             :                                                 s_len = 2;
     769             :                                         }
     770        1138 :                                         pad_char = ' ';
     771        1138 :                                         break;
     772             : 
     773             : 
     774             :                                 case NUL:
     775             :                                         /*
     776             :                                          * The last character of the format string was %.
     777             :                                          * We ignore it.
     778             :                                          */
     779           0 :                                         continue;
     780             : 
     781             : 
     782             : fmt_error:
     783           0 :                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
     784             :                                         /*
     785             :                                          * The default case is for unrecognized %'s.
     786             :                                          * We print %<char> to help the user identify what
     787             :                                          * option is not understood.
     788             :                                          * This is also useful in case the user wants to pass
     789             :                                          * the output of format_converter to another function
     790             :                                          * that understands some other %<char> (like syslog).
     791             :                                          * Note that we can't point s inside fmt because the
     792             :                                          * unknown <char> could be preceded by width etc.
     793             :                                          */
     794             :                                 default:
     795           0 :                                         char_buf[0] = '%';
     796           0 :                                         char_buf[1] = *fmt;
     797           0 :                                         s = char_buf;
     798           0 :                                         s_len = 2;
     799           0 :                                         pad_char = ' ';
     800             :                                         break;
     801             :                         }
     802             : 
     803     5980405 :                         if (prefix_char != NUL) {
     804        6189 :                                 *--s = prefix_char;
     805        6189 :                                 s_len++;
     806             :                         }
     807     5980405 :                         if (adjust_width && adjust == RIGHT && min_width > s_len) {
     808      190645 :                                 if (pad_char == '0' && prefix_char != NUL) {
     809           0 :                                         INS_CHAR(xbuf, *s, is_char);
     810           0 :                                         s++;
     811           0 :                                         s_len--;
     812           0 :                                         min_width--;
     813             :                                 }
     814      231713 :                                 PAD_CHAR(xbuf, pad_char, min_width - s_len, is_char);
     815             :                         }
     816             :                         /*
     817             :                          * Print the string s.
     818             :                          */
     819     5980405 :                         INS_STRING(xbuf, s, s_len, is_char);
     820             : 
     821     5980405 :                         if (adjust_width && adjust == LEFT && min_width > s_len) {
     822          59 :                                 PAD_CHAR(xbuf, pad_char, min_width - s_len, is_char);
     823             :                         }
     824             : 
     825     5980405 :                         if (free_zcopy) {
     826             :                                 zval_dtor(&zcopy);
     827             :                         }
     828             :                 }
     829             : skip_output:
     830    17088480 :                 fmt++;
     831             :         }
     832     3212297 :         return;
     833             : }
     834             : /* }}} */
     835             : 
     836             : /*
     837             :  * This is the general purpose conversion function.
     838             :  */
     839     3166446 : PHPAPI size_t vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) /* {{{ */
     840             : {
     841     3166446 :         smart_string buf = {0};
     842             :         size_t result;
     843             : 
     844     3166446 :         xbuf_format_converter(&buf, 1, format, ap);
     845             : 
     846     3166446 :         if (max_len && buf.len > max_len) {
     847           0 :                 buf.len = max_len;
     848             :         }
     849             : 
     850     3166446 :         smart_string_0(&buf);
     851             : 
     852     3166446 :         if (buf.c) {
     853     3166402 :                 *pbuf = buf.c;
     854     3166402 :                 result = buf.len;
     855             :         } else {
     856          44 :                 *pbuf = NULL;
     857          44 :                 result = 0;
     858             :         }
     859             : 
     860     3166446 :         return result;
     861             : }
     862             : /* }}} */
     863             : 
     864     2141838 : PHPAPI size_t spprintf(char **pbuf, size_t max_len, const char *format, ...) /* {{{ */
     865             : {
     866             :         size_t cc;
     867             :         va_list ap;
     868             : 
     869     2141838 :         va_start(ap, format);
     870     2141838 :         cc = vspprintf(pbuf, max_len, format, ap);
     871     2141838 :         va_end(ap);
     872     2141838 :         return (cc);
     873             : }
     874             : /* }}} */
     875             : 
     876       45851 : PHPAPI zend_string *vstrpprintf(size_t max_len, const char *format, va_list ap) /* {{{ */
     877             : {
     878       45851 :         smart_str buf = {0};
     879             : 
     880       45851 :         xbuf_format_converter(&buf, 0, format, ap);
     881             : 
     882       45851 :         if (max_len && buf.s && buf.s->len > max_len) {
     883           0 :                 buf.s->len = max_len;
     884             :         }
     885             :         smart_str_0(&buf);
     886             : 
     887       45851 :         return buf.s;
     888             : }
     889             : /* }}} */
     890             : 
     891       36056 : PHPAPI zend_string *strpprintf(size_t max_len, const char *format, ...) /* {{{ */
     892             : {
     893             :         va_list ap;
     894             :         zend_string *str;
     895             : 
     896       36056 :         va_start(ap, format);
     897       36056 :         str = vstrpprintf(max_len, format, ap);
     898       36056 :         va_end(ap);
     899       36056 :         return str;
     900             : }
     901             : /* }}} */
     902             : 
     903             : /*
     904             :  * Local variables:
     905             :  * tab-width: 4
     906             :  * c-basic-offset: 4
     907             :  * End:
     908             :  * vim600: sw=4 ts=4 fdm=marker
     909             :  * vim<600: sw=4 ts=4
     910             :  */

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:27 +0000 (9 days ago)

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