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

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:25:03 +0000 (27 hours ago)

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