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 - snprintf.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 349 520 67.1 %
Date: 2016-09-27 Functions: 13 15 86.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2016 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author:                                                              |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #define _GNU_SOURCE
      22             : #include "php.h"
      23             : 
      24             : #include <zend_strtod.h>
      25             : 
      26             : #include <stddef.h>
      27             : #include <stdio.h>
      28             : #include <ctype.h>
      29             : #include <sys/types.h>
      30             : #include <stdarg.h>
      31             : #include <string.h>
      32             : #include <stdlib.h>
      33             : #include <math.h>
      34             : 
      35             : #ifdef HAVE_INTTYPES_H
      36             : #include <inttypes.h>
      37             : #endif
      38             : 
      39             : #ifdef HAVE_LOCALE_H
      40             : #include <locale.h>
      41             : #ifdef ZTS
      42             : #include "ext/standard/php_string.h"
      43             : #define LCONV_DECIMAL_POINT (*lconv.decimal_point)
      44             : #else
      45             : #define LCONV_DECIMAL_POINT (*lconv->decimal_point)
      46             : #endif
      47             : #else
      48             : #define LCONV_DECIMAL_POINT '.'
      49             : #endif
      50             : 
      51             : /*
      52             :  * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
      53             :  *
      54             :  * Permission to use, copy, modify, and distribute this software for any
      55             :  * purpose with or without fee is hereby granted, provided that the above
      56             :  * copyright notice and this permission notice appear in all copies.
      57             :  *
      58             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      59             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      60             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      61             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      62             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      63             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      64             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      65             :  *
      66             :  * Sponsored in part by the Defense Advanced Research Projects
      67             :  * Agency (DARPA) and Air Force Research Laboratory, Air Force
      68             :  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
      69             :  */
      70             : 
      71      105664 : static char * __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) /* {{{ */
      72             : {
      73      105664 :         register char *s = NULL;
      74             :         char *p, *rve, c;
      75             :         size_t siz;
      76             : 
      77      105664 :         if (ndigit < 0) {
      78           0 :                 siz = -ndigit + 1;
      79             :         } else {
      80      105664 :                 siz = ndigit + 1;
      81             :         }
      82             : 
      83             :         /* __dtoa() doesn't allocate space for 0 so we do it by hand */
      84      105664 :         if (value == 0.0) {
      85         506 :                 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
      86         506 :                 *sign = 0;
      87         506 :                 if ((rve = s = (char *)malloc(ndigit?siz:2)) == NULL) {
      88           0 :                         return(NULL);
      89             :                 }
      90         506 :                 *rve++ = '0';
      91         506 :                 *rve = '\0';
      92         506 :                 if (!ndigit) {
      93           7 :                         return(s);
      94             :                 }
      95             :         } else {
      96      105158 :                 p = zend_dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
      97      105158 :                 if (*decpt == 9999) {
      98             :                         /* Infinity or Nan, convert to inf or nan like printf */
      99           0 :                         *decpt = 0;
     100           0 :                         c = *p;
     101           0 :                         zend_freedtoa(p);
     102           0 :                         return strdup((c == 'I' ? "INF" : "NAN"));
     103             :                 }
     104             :                 /* Make a local copy and adjust rve to be in terms of s */
     105      105158 :                 if (pad && fmode) {
     106      104406 :                         siz += *decpt;
     107             :                 }
     108      105158 :                 if ((s = (char *)malloc(siz+1)) == NULL) {
     109           0 :                         zend_freedtoa(p);
     110           0 :                         return(NULL);
     111             :                 }
     112      105158 :                 (void) strlcpy(s, p, siz);
     113      105158 :                 rve = s + (rve - p);
     114      105158 :                 zend_freedtoa(p);
     115             :         }
     116             : 
     117             :         /* Add trailing zeros */
     118      105657 :         if (pad) {
     119      105657 :                 siz -= rve - s;
     120      443925 :                 while (--siz) {
     121      232611 :                         *rve++ = '0';
     122             :                 }
     123      105657 :                 *rve = '\0';
     124             :         }
     125             : 
     126      105657 :         return(s);
     127             : }
     128             : /* }}} */
     129             : 
     130         983 : static inline char *php_ecvt(double value, int ndigit, int *decpt, int *sign) /* {{{ */
     131             : {
     132         983 :         return(__cvt(value, ndigit, decpt, sign, 0, 1));
     133             : }
     134             : /* }}} */
     135             : 
     136      104681 : static inline char *php_fcvt(double value, int ndigit, int *decpt, int *sign) /* {{{ */
     137             : {
     138      104681 :     return(__cvt(value, ndigit, decpt, sign, 1, 1));
     139             : }
     140             : /* }}} */
     141             : 
     142       14695 : PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */
     143             : {
     144             :         char *digits, *dst, *src;
     145             :         int i, decpt, sign;
     146       14695 :         int mode = ndigit >= 0 ? 2 : 0;
     147             : 
     148       14695 :         if (mode == 0) {
     149         135 :                 ndigit = 17;
     150             :         }
     151       14695 :         digits = zend_dtoa(value, mode, ndigit, &decpt, &sign, NULL);
     152       14695 :         if (decpt == 9999) {
     153             :                 /*
     154             :                  * Infinity or NaN, convert to inf or nan with sign.
     155             :                  * We assume the buffer is at least ndigit long.
     156             :                  */
     157          20 :                 snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
     158          20 :                 zend_freedtoa(digits);
     159          20 :                 return (buf);
     160             :         }
     161             : 
     162       14675 :         dst = buf;
     163       14675 :         if (sign) {
     164        3349 :                 *dst++ = '-';
     165             :         }
     166             : 
     167       17110 :         if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
     168             :                 /* exponential format (e.g. 1.2345e+13) */
     169        2435 :                 if (--decpt < 0) {
     170        1227 :                         sign = 1;
     171        1227 :                         decpt = -decpt;
     172             :                 } else {
     173        1208 :                         sign = 0;
     174             :                 }
     175        2435 :                 src = digits;
     176        2435 :                 *dst++ = *src++;
     177        2435 :                 *dst++ = dec_point;
     178        2435 :                 if (*src == '\0') {
     179         161 :                         *dst++ = '0';
     180             :                 } else {
     181             :                         do {
     182      309683 :                                 *dst++ = *src++;
     183      309683 :                         } while (*src != '\0');
     184             :                 }
     185        2435 :                 *dst++ = exponent;
     186        2435 :                 if (sign) {
     187        1227 :                         *dst++ = '-';
     188             :                 } else {
     189        1208 :                         *dst++ = '+';
     190             :                 }
     191        2435 :                 if (decpt < 10) {
     192         444 :                         *dst++ = '0' + decpt;
     193         444 :                         *dst = '\0';
     194             :                 } else {
     195             :                         /* XXX - optimize */
     196        4630 :                         for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
     197        2639 :                                 continue;
     198        1991 :                         dst[i + 1] = '\0';
     199        8612 :                         while (decpt != 0) {
     200        4630 :                                 dst[i--] = '0' + decpt % 10;
     201        4630 :                                 decpt /= 10;
     202             :                         }
     203             :                 }
     204       12240 :         } else if (decpt < 0) {
     205             :                 /* standard format 0. */
     206         249 :                 *dst++ = '0';   /* zero before decimal point */
     207         249 :                 *dst++ = dec_point;
     208             :                 do {
     209         435 :                         *dst++ = '0';
     210         435 :                 } while (++decpt < 0);
     211         249 :                 src = digits;
     212        2078 :                 while (*src != '\0') {
     213        1580 :                         *dst++ = *src++;
     214             :                 }
     215         249 :                 *dst = '\0';
     216             :         } else {
     217             :                 /* standard format */
     218       43424 :                 for (i = 0, src = digits; i < decpt; i++) {
     219       31433 :                         if (*src != '\0') {
     220       27318 :                                 *dst++ = *src++;
     221             :                         } else {
     222        4115 :                                 *dst++ = '0';
     223             :                         }
     224             :                 }
     225       11991 :                 if (*src != '\0') {
     226        8279 :                         if (src == digits) {
     227         953 :                                 *dst++ = '0';   /* zero before decimal point */
     228             :                         }
     229        8279 :                         *dst++ = dec_point;
     230       36783 :                         for (i = decpt; digits[i] != '\0'; i++) {
     231       28504 :                 *dst++ = digits[i];
     232             :             }
     233             :         }
     234       11991 :         *dst = '\0';
     235             :     }
     236       14675 :     zend_freedtoa(digits);
     237       14675 :     return (buf);
     238             : }
     239             : /* }}} */
     240             : 
     241             : /* {{{ Apache license */
     242             : /* ====================================================================
     243             :  * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
     244             :  *
     245             :  * Redistribution and use in source and binary forms, with or without
     246             :  * modification, are permitted provided that the following conditions
     247             :  * are met:
     248             :  *
     249             :  * 1. Redistributions of source code must retain the above copyright
     250             :  *    notice, this list of conditions and the following disclaimer.
     251             :  *
     252             :  * 2. Redistributions in binary form must reproduce the above copyright
     253             :  *    notice, this list of conditions and the following disclaimer in
     254             :  *    the documentation and/or other materials provided with the
     255             :  *    distribution.
     256             :  *
     257             :  * 3. All advertising materials mentioning features or use of this
     258             :  *    software must display the following acknowledgment:
     259             :  *    "This product includes software developed by the Apache Group
     260             :  *    for use in the Apache HTTP server project (http://www.apache.org/)."
     261             :  *
     262             :  * 4. The names "Apache Server" and "Apache Group" must not be used to
     263             :  *    endorse or promote products derived from this software without
     264             :  *    prior written permission.
     265             :  *
     266             :  * 5. Redistributions of any form whatsoever must retain the following
     267             :  *    acknowledgment:
     268             :  *    "This product includes software developed by the Apache Group
     269             :  *    for use in the Apache HTTP server project (http://www.apache.org/)."
     270             :  *
     271             :  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
     272             :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     273             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     274             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
     275             :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     276             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     277             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     278             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     279             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     280             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     281             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     282             :  * OF THE POSSIBILITY OF SUCH DAMAGE.
     283             :  * ====================================================================
     284             :  *
     285             :  * This software consists of voluntary contributions made by many
     286             :  * individuals on behalf of the Apache Group and was originally based
     287             :  * on public domain software written at the National Center for
     288             :  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
     289             :  * For more information on the Apache Group and the Apache HTTP server
     290             :  * project, please see <http://www.apache.org/>.
     291             :  *
     292             :  * This code is based on, and used with the permission of, the
     293             :  * SIO stdio-replacement strx_* functions by Panos Tsirigotis
     294             :  * <panos@alumni.cs.colorado.edu> for xinetd.
     295             :  */
     296             : /* }}} */
     297             : 
     298             : #define FALSE                   0
     299             : #define TRUE                    1
     300             : #define NUL                     '\0'
     301             : #define INT_NULL                ((int *)0)
     302             : 
     303             : #define S_NULL                  "(null)"
     304             : #define S_NULL_LEN              6
     305             : 
     306             : #define FLOAT_DIGITS            6
     307             : #define EXPONENT_LENGTH         10
     308             : 
     309             : 
     310             : /*
     311             :  * Convert num to its decimal format.
     312             :  * Return value:
     313             :  *   - a pointer to a string containing the number (no sign)
     314             :  *   - len contains the length of the string
     315             :  *   - is_negative is set to TRUE or FALSE depending on the sign
     316             :  *     of the number (always set to FALSE if is_unsigned is TRUE)
     317             :  *
     318             :  * The caller provides a buffer for the string: that is the buf_end argument
     319             :  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
     320             :  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
     321             :  */
     322             : /* char * ap_php_conv_10() {{{ */
     323      949802 : PHPAPI char * ap_php_conv_10(register wide_int num, register bool_int is_unsigned,
     324             :            register bool_int * is_negative, char *buf_end, register size_t *len)
     325             : {
     326      949802 :         register char *p = buf_end;
     327             :         register u_wide_int magnitude;
     328             : 
     329      949802 :         if (is_unsigned) {
     330        3891 :                 magnitude = (u_wide_int) num;
     331        3891 :                 *is_negative = FALSE;
     332             :         } else {
     333      945911 :                 *is_negative = (num < 0);
     334             : 
     335             :                 /*
     336             :                  * On a 2's complement machine, negating the most negative integer
     337             :                  * results in a number that cannot be represented as a signed integer.
     338             :                  * Here is what we do to obtain the number's magnitude:
     339             :                  *      a. add 1 to the number
     340             :                  *      b. negate it (becomes positive)
     341             :                  *      c. convert it to unsigned
     342             :                  *      d. add 1
     343             :                  */
     344      945911 :                 if (*is_negative) {
     345        3611 :                         wide_int t = num + 1;
     346        3611 :                         magnitude = ((u_wide_int) - t) + 1;
     347             :                 } else {
     348      942300 :                         magnitude = (u_wide_int) num;
     349             :                 }
     350             :         }
     351             : 
     352             :         /*
     353             :          * We use a do-while loop so that we write at least 1 digit
     354             :          */
     355             :         do {
     356     2200738 :                 register u_wide_int new_magnitude = magnitude / 10;
     357             : 
     358     2200738 :                 *--p = (char)(magnitude - new_magnitude * 10 + '0');
     359     2200738 :                 magnitude = new_magnitude;
     360             :         }
     361     2200738 :         while (magnitude);
     362             : 
     363      949802 :         *len = buf_end - p;
     364      949802 :         return (p);
     365             : }
     366             : /* }}} */
     367             : 
     368             : /* If you change this value then also change bug24640.phpt.
     369             :  * Also NDIG must be reasonable smaller than NUM_BUF_SIZE.
     370             :  */
     371             : #define NDIG    320
     372             : 
     373             : 
     374             : /*
     375             :  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
     376             :  * The result is placed in buf, and len denotes the length of the string
     377             :  * The sign is returned in the is_negative argument (and is not placed
     378             :  * in buf).
     379             :  */
     380             : /* PHPAPI char * php_conv_fp() {{{ */
     381      105664 : PHPAPI char * php_conv_fp(register char format, register double num,
     382             :                  boolean_e add_dp, int precision, char dec_point, bool_int * is_negative, char *buf, size_t *len)
     383             : {
     384      105664 :         register char *s = buf;
     385             :         register char *p, *p_orig;
     386             :         int decimal_point;
     387             : 
     388      105664 :         if (precision >= NDIG - 1) {
     389           2 :                 precision = NDIG - 2;
     390             :         }
     391             : 
     392      105664 :         if (format == 'F') {
     393      104681 :                 p_orig = p = php_fcvt(num, precision, &decimal_point, is_negative);
     394             :         } else {                                                /* either e or E format */
     395         983 :                 p_orig = p = php_ecvt(num, precision + 1, &decimal_point, is_negative);
     396             :         }
     397             : 
     398             :         /*
     399             :          * Check for Infinity and NaN
     400             :          */
     401      105664 :         if (isalpha((int)*p)) {
     402           0 :                 *len = strlen(p);
     403           0 :                 memcpy(buf, p, *len + 1);
     404           0 :                 *is_negative = FALSE;
     405           0 :                 free(p_orig);
     406           0 :                 return (buf);
     407             :         }
     408      105664 :         if (format == 'F') {
     409      104681 :                 if (decimal_point <= 0) {
     410      100891 :                         if (num != 0 || precision > 0) {
     411      100884 :                                 *s++ = '0';
     412      100884 :                                 if (precision > 0) {
     413      100884 :                                         *s++ = dec_point;
     414      213632 :                                         while (decimal_point++ < 0) {
     415       11864 :                                                 *s++ = '0';
     416             :                                         }
     417           0 :                                 } else if (add_dp) {
     418           0 :                                         *s++ = dec_point;
     419             :                                 }
     420             :                         }
     421             :                 } else {
     422        3790 :                         int addz = decimal_point >= NDIG ? decimal_point - NDIG + 1 : 0;
     423        3790 :                         decimal_point -= addz;
     424       24916 :                         while (decimal_point-- > 0) {
     425       17336 :                                 *s++ = *p++;
     426             :                         }
     427        7580 :                         while (addz-- > 0) {
     428           0 :                                 *s++ = '0';
     429             :                         }
     430        3790 :                         if (precision > 0 || add_dp) {
     431        2456 :                                 *s++ = dec_point;
     432             :                         }
     433             :                 }
     434             :         } else {
     435         983 :                 *s++ = *p++;
     436         983 :                 if (precision > 0 || add_dp) {
     437         982 :                         *s++ = '.';
     438             :                 }
     439             :         }
     440             : 
     441             :         /*
     442             :          * copy the rest of p, the NUL is NOT copied
     443             :          */
     444     1025695 :         while (*p) {
     445      814367 :                 *s++ = *p++;
     446             :         }
     447             : 
     448      105664 :         if (format != 'F') {
     449             :                 char temp[EXPONENT_LENGTH];             /* for exponent conversion */
     450             :                 size_t t_len;
     451             :                 bool_int exponent_is_negative;
     452             : 
     453         983 :                 *s++ = format;                  /* either e or E */
     454         983 :                 decimal_point--;
     455         983 :                 if (decimal_point != 0) {
     456         449 :                         p = ap_php_conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, &temp[EXPONENT_LENGTH], &t_len);
     457         449 :                         *s++ = exponent_is_negative ? '-' : '+';
     458             : 
     459             :                         /*
     460             :                          * Make sure the exponent has at least 2 digits
     461             :                          */
     462        1397 :                         while (t_len--) {
     463         499 :                                 *s++ = *p++;
     464             :                         }
     465             :                 } else {
     466         534 :                         *s++ = '+';
     467         534 :                         *s++ = '0';
     468             :                 }
     469             :         }
     470      105664 :         *len = s - buf;
     471      105664 :         free(p_orig);
     472      105664 :         return (buf);
     473             : }
     474             : /* }}} */
     475             : 
     476             : /*
     477             :  * Convert num to a base X number where X is a power of 2. nbits determines X.
     478             :  * For example, if nbits is 3, we do base 8 conversion
     479             :  * Return value:
     480             :  *      a pointer to a string containing the number
     481             :  *
     482             :  * The caller provides a buffer for the string: that is the buf_end argument
     483             :  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
     484             :  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
     485             :  */
     486       73030 : PHPAPI char * ap_php_conv_p2(register u_wide_int num, register int nbits, char format, char *buf_end, register size_t *len) /* {{{ */
     487             : {
     488       73030 :         register int mask = (1 << nbits) - 1;
     489       73030 :         register char *p = buf_end;
     490             :         static char low_digits[] = "0123456789abcdef";
     491             :         static char upper_digits[] = "0123456789ABCDEF";
     492       73030 :         register char *digits = (format == 'X') ? upper_digits : low_digits;
     493             : 
     494             :         do {
     495      528605 :                 *--p = digits[num & mask];
     496      528605 :                 num >>= nbits;
     497             :         }
     498      528605 :         while (num);
     499             : 
     500       73030 :         *len = buf_end - p;
     501       73030 :         return (p);
     502             : }
     503             : /* }}} */
     504             : 
     505             : /*
     506             :  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
     507             :  *
     508             :  * XXX: this is a magic number; do not decrease it
     509             :  * Emax = 1023
     510             :  * NDIG = 320
     511             :  * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1;
     512             :  */
     513             : #define NUM_BUF_SIZE            2048
     514             : 
     515             : 
     516             : /*
     517             :  * Descriptor for buffer area
     518             :  */
     519             : struct buf_area {
     520             :         char *buf_end;
     521             :         char *nextb;                            /* pointer to next byte to read/write   */
     522             : };
     523             : 
     524             : typedef struct buf_area buffy;
     525             : 
     526             : /*
     527             :  * The INS_CHAR macro inserts a character in the buffer and writes
     528             :  * the buffer back to disk if necessary
     529             :  * It uses the char pointers sp and bep:
     530             :  *      sp points to the next available character in the buffer
     531             :  *      bep points to the end-of-buffer+1
     532             :  * While using this macro, note that the nextb pointer is NOT updated.
     533             :  *
     534             :  * NOTE: Evaluation of the c argument should not have any side-effects
     535             :  */
     536             : #define INS_CHAR(c, sp, bep, cc) \
     537             :         {                            \
     538             :                 if (sp < bep)            \
     539             :                 {                        \
     540             :                         *sp++ = c;           \
     541             :                 }                        \
     542             :                 cc++;                    \
     543             :         }
     544             : 
     545             : #define NUM( c )                        ( c - '0' )
     546             : 
     547             : #define STR_TO_DEC( str, num )          \
     548             :     num = NUM( *str++ ) ;               \
     549             :     while ( isdigit((int)*str ) )               \
     550             :     {                                   \
     551             :         num *= 10 ;                     \
     552             :         num += NUM( *str++ ) ;          \
     553             :     }
     554             : 
     555             : /*
     556             :  * This macro does zero padding so that the precision
     557             :  * requirement is satisfied. The padding is done by
     558             :  * adding '0's to the left of the string that is going
     559             :  * to be printed.
     560             :  */
     561             : #define FIX_PRECISION( adjust, precision, s, s_len )    \
     562             :     if ( adjust )                                               \
     563             :         while ( s_len < (size_t)precision )  \
     564             :         {                                                                       \
     565             :             *--s = '0' ;                                        \
     566             :             s_len++ ;                                           \
     567             :         }
     568             : 
     569             : /*
     570             :  * Macro that does padding. The padding is done by printing
     571             :  * the character ch.
     572             :  */
     573             : #define PAD( width, len, ch )   do              \
     574             :         {                                       \
     575             :             INS_CHAR( ch, sp, bep, cc ) ;       \
     576             :             width-- ;                           \
     577             :         }                                       \
     578             :         while ( width > len )
     579             : 
     580             : /*
     581             :  * Prefix the character ch to the string str
     582             :  * Increase length
     583             :  * Set the has_prefix flag
     584             :  */
     585             : #define PREFIX( str, length, ch )        *--str = ch ; length++ ; has_prefix = YES
     586             : 
     587             : 
     588             : /*
     589             :  * Do format conversion placing the output in buffer
     590             :  */
     591     1477201 : static int format_converter(register buffy * odp, const char *fmt, va_list ap) /* {{{ */
     592             : {
     593             :         char *sp;
     594             :         char *bep;
     595     1477201 :         int cc = 0;
     596             :         size_t i;
     597             : 
     598     1477201 :         char *s = NULL;
     599             :         size_t s_len;
     600             :         int free_zcopy;
     601             :         zval *zvp, zcopy;
     602             : 
     603     1477201 :         int min_width = 0;
     604     1477201 :         int precision = 0;
     605             :         enum {
     606             :                 LEFT, RIGHT
     607             :         } adjust;
     608             :         char pad_char;
     609             :         char prefix_char;
     610             : 
     611             :         double fp_num;
     612     1477201 :         wide_int i_num = (wide_int) 0;
     613             :         u_wide_int ui_num;
     614             : 
     615             :         char num_buf[NUM_BUF_SIZE];
     616             :         char char_buf[2];                       /* for printing %% and %<unknown> */
     617             : 
     618             : #ifdef HAVE_LOCALE_H
     619             : #ifdef ZTS
     620             :         struct lconv lconv;
     621             : #else
     622     1477201 :         struct lconv *lconv = NULL;
     623             : #endif
     624             : #endif
     625             : 
     626             :         /*
     627             :          * Flag variables
     628             :          */
     629             :         length_modifier_e modifier;
     630             :         boolean_e alternate_form;
     631             :         boolean_e print_sign;
     632             :         boolean_e print_blank;
     633             :         boolean_e adjust_precision;
     634             :         boolean_e adjust_width;
     635             :         bool_int is_negative;
     636             : 
     637     1477201 :         sp = odp->nextb;
     638     1477201 :         bep = odp->buf_end;
     639             : 
     640     9323285 :         while (*fmt) {
     641     6368883 :                 if (*fmt != '%') {
     642     4716681 :                         INS_CHAR(*fmt, sp, bep, cc);
     643             :                 } else {
     644             :                         /*
     645             :                          * Default variable settings
     646             :                          */
     647     1652202 :                         adjust = RIGHT;
     648     1652202 :                         alternate_form = print_sign = print_blank = NO;
     649     1652202 :                         pad_char = ' ';
     650     1652202 :                         prefix_char = NUL;
     651     1652202 :                         free_zcopy = 0;
     652             : 
     653     1652202 :                         fmt++;
     654             : 
     655             :                         /*
     656             :                          * Try to avoid checking for flags, width or precision
     657             :                          */
     658     1793982 :                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
     659             :                                 /*
     660             :                                  * Recognize flags: -, #, BLANK, +
     661             :                                  */
     662       40136 :                                 for (;; fmt++) {
     663      181916 :                                         if (*fmt == '-')
     664           1 :                                                 adjust = LEFT;
     665      181915 :                                         else if (*fmt == '+')
     666           5 :                                                 print_sign = YES;
     667      181910 :                                         else if (*fmt == '#')
     668           0 :                                                 alternate_form = YES;
     669      181910 :                                         else if (*fmt == ' ')
     670           0 :                                                 print_blank = YES;
     671      181910 :                                         else if (*fmt == '0')
     672       40130 :                                                 pad_char = '0';
     673             :                                         else
     674      141780 :                                                 break;
     675       40136 :                                 }
     676             : 
     677             :                                 /*
     678             :                                  * Check if a width was specified
     679             :                                  */
     680      141780 :                                 if (isdigit((int)*fmt)) {
     681       39929 :                                         STR_TO_DEC(fmt, min_width);
     682       39929 :                                         adjust_width = YES;
     683      101851 :                                 } else if (*fmt == '*') {
     684          99 :                                         min_width = va_arg(ap, int);
     685          99 :                                         fmt++;
     686          99 :                                         adjust_width = YES;
     687          99 :                                         if (min_width < 0) {
     688           0 :                                                 adjust = LEFT;
     689           0 :                                                 min_width = -min_width;
     690             :                                         }
     691             :                                 } else
     692      101752 :                                         adjust_width = NO;
     693             : 
     694             :                                 /*
     695             :                                  * Check if a precision was specified
     696             :                                  */
     697      141780 :                                 if (*fmt == '.') {
     698      101748 :                                         adjust_precision = YES;
     699      101748 :                                         fmt++;
     700      101748 :                                         if (isdigit((int)*fmt)) {
     701      100660 :                                                 STR_TO_DEC(fmt, precision);
     702        1088 :                                         } else if (*fmt == '*') {
     703        1088 :                                                 precision = va_arg(ap, int);
     704        1088 :                                                 fmt++;
     705        1088 :                                                 if (precision < 0)
     706           0 :                                                         precision = 0;
     707             :                                         } else
     708           0 :                                                 precision = 0;
     709             : 
     710      101748 :                                         if (precision > FORMAT_CONV_MAX_PRECISION) {
     711           0 :                                                 precision = FORMAT_CONV_MAX_PRECISION;
     712             :                                         }
     713             :                                 } else
     714       40032 :                                         adjust_precision = NO;
     715             :                         } else
     716     1510422 :                                 adjust_precision = adjust_width = NO;
     717             : 
     718             :                         /*
     719             :                          * Modifier check
     720             :                          */
     721     1652202 :                         switch (*fmt) {
     722             :                                 case 'L':
     723           0 :                                         fmt++;
     724           0 :                                         modifier = LM_LONG_DOUBLE;
     725           0 :                                         break;
     726             :                                 case 'I':
     727           2 :                                         fmt++;
     728             : #if SIZEOF_LONG_LONG
     729           4 :                                         if (*fmt == '6' && *(fmt+1) == '4') {
     730           2 :                                                 fmt += 2;
     731           2 :                                                 modifier = LM_LONG_LONG;
     732             :                                         } else
     733             : #endif
     734           0 :                                                 if (*fmt == '3' && *(fmt+1) == '2') {
     735           0 :                                                         fmt += 2;
     736           0 :                                                         modifier = LM_LONG;
     737             :                                                 } else {
     738             : #ifdef _WIN64
     739             :                                                         modifier = LM_LONG_LONG;
     740             : #else
     741           0 :                                                         modifier = LM_LONG;
     742             : #endif
     743             :                                                 }
     744           2 :                                         break;
     745             :                                 case 'l':
     746      120222 :                                         fmt++;
     747             : #if SIZEOF_LONG_LONG
     748      120222 :                                         if (*fmt == 'l') {
     749        5808 :                                                 fmt++;
     750        5808 :                                                 modifier = LM_LONG_LONG;
     751             :                                         } else
     752             : #endif
     753      114414 :                                                 modifier = LM_LONG;
     754      120222 :                                         break;
     755             :                                 case 'z':
     756          13 :                                         fmt++;
     757          13 :                                         modifier = LM_SIZE_T;
     758          13 :                                         break;
     759             :                                 case 'j':
     760           0 :                                         fmt++;
     761             : #if SIZEOF_INTMAX_T
     762           0 :                                         modifier = LM_INTMAX_T;
     763             : #else
     764             :                                         modifier = LM_SIZE_T;
     765             : #endif
     766           0 :                                         break;
     767             :                                 case 't':
     768           0 :                                         fmt++;
     769             : #if SIZEOF_PTRDIFF_T
     770           0 :                                         modifier = LM_PTRDIFF_T;
     771             : #else
     772             :                                         modifier = LM_SIZE_T;
     773             : #endif
     774           0 :                                         break;
     775             :                                 case 'p':
     776           0 :                                         fmt++;
     777           0 :                                         modifier = LM_PHP_INT_T;
     778           0 :                                         break;
     779             :                                 case 'h':
     780           0 :                                         fmt++;
     781           0 :                                         if (*fmt == 'h') {
     782           0 :                                                 fmt++;
     783             :                                         }
     784             :                                         /* these are promoted to int, so no break */
     785             :                                 default:
     786     1531965 :                                         modifier = LM_STD;
     787             :                                         break;
     788             :                         }
     789             : 
     790             :                         /*
     791             :                          * Argument extraction and printing.
     792             :                          * First we determine the argument type.
     793             :                          * Then, we convert the argument to a string.
     794             :                          * On exit from the switch, s points to the string that
     795             :                          * must be printed, s_len has the length of the string
     796             :                          * The precision requirements, if any, are reflected in s_len.
     797             :                          *
     798             :                          * NOTE: pad_char may be set to '0' because of the 0 flag.
     799             :                          *   It is reset to ' ' by non-numeric formats
     800             :                          */
     801     1652202 :                         switch (*fmt) {
     802             :                                 case 'Z': {
     803           0 :                                         zvp = (zval*) va_arg(ap, zval*);
     804           0 :                                         free_zcopy = zend_make_printable_zval(zvp, &zcopy);
     805           0 :                                         if (free_zcopy) {
     806           0 :                                                 zvp = &zcopy;
     807             :                                         }
     808           0 :                                         s_len = Z_STRLEN_P(zvp);
     809           0 :                                         s = Z_STRVAL_P(zvp);
     810           0 :                                         if (adjust_precision && (size_t)precision < s_len) {
     811           0 :                                                 s_len = precision;
     812             :                                         }
     813           0 :                                         break;
     814             :                                 }
     815             :                                 case 'u':
     816        2493 :                                         switch(modifier) {
     817             :                                                 default:
     818         799 :                                                         i_num = (wide_int) va_arg(ap, unsigned int);
     819         799 :                                                         break;
     820             :                                                 case LM_LONG_DOUBLE:
     821           0 :                                                         goto fmt_error;
     822             :                                                 case LM_LONG:
     823        1681 :                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
     824        1681 :                                                         break;
     825             :                                                 case LM_SIZE_T:
     826          13 :                                                         i_num = (wide_int) va_arg(ap, size_t);
     827          13 :                                                         break;
     828             : #if SIZEOF_LONG_LONG
     829             :                                                 case LM_LONG_LONG:
     830           0 :                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
     831           0 :                                                         break;
     832             : #endif
     833             : #if SIZEOF_INTMAX_T
     834             :                                                 case LM_INTMAX_T:
     835           0 :                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
     836           0 :                                                         break;
     837             : #endif
     838             : #if SIZEOF_PTRDIFF_T
     839             :                                                 case LM_PTRDIFF_T:
     840           0 :                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
     841           0 :                                                         break;
     842             : #endif
     843             :                                                 case LM_PHP_INT_T:
     844           0 :                                                         i_num = (wide_int) va_arg(ap, zend_ulong);
     845             :                                                         break;
     846             :                                         }
     847             :                                         /*
     848             :                                          * The rest also applies to other integer formats, so fall
     849             :                                          * into that case.
     850             :                                          */
     851             :                                 case 'd':
     852             :                                 case 'i':
     853             :                                         /*
     854             :                                          * Get the arg if we haven't already.
     855             :                                          */
     856      685728 :                                         if ((*fmt) != 'u') {
     857      683235 :                                                 switch(modifier) {
     858             :                                                         default:
     859      564704 :                                                                 i_num = (wide_int) va_arg(ap, int);
     860      564704 :                                                                 break;
     861             :                                                         case LM_LONG_DOUBLE:
     862           0 :                                                                 goto fmt_error;
     863             :                                                         case LM_LONG:
     864      112721 :                                                                 i_num = (wide_int) va_arg(ap, long int);
     865      112721 :                                                                 break;
     866             :                                                         case LM_SIZE_T:
     867             : #if SIZEOF_SSIZE_T
     868           0 :                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
     869             : #else
     870             :                                                                 i_num = (wide_int) va_arg(ap, size_t);
     871             : #endif
     872           0 :                                                                 break;
     873             : #if SIZEOF_LONG_LONG
     874             :                                                         case LM_LONG_LONG:
     875        5810 :                                                                 i_num = (wide_int) va_arg(ap, wide_int);
     876        5810 :                                                                 break;
     877             : #endif
     878             : #if SIZEOF_INTMAX_T
     879             :                                                         case LM_INTMAX_T:
     880           0 :                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
     881           0 :                                                                 break;
     882             : #endif
     883             : #if SIZEOF_PTRDIFF_T
     884             :                                                         case LM_PTRDIFF_T:
     885           0 :                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
     886           0 :                                                                 break;
     887             : #endif
     888             :                                                         case LM_PHP_INT_T:
     889           0 :                                                                 i_num = (wide_int) va_arg(ap, zend_long);
     890             :                                                                 break;
     891             :                                                 }
     892             :                                         }
     893      685728 :                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
     894             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     895      685728 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     896             : 
     897      685728 :                                         if (*fmt != 'u') {
     898      683235 :                                                 if (is_negative) {
     899         575 :                                                         prefix_char = '-';
     900      682660 :                                                 } else if (print_sign) {
     901           4 :                                                         prefix_char = '+';
     902      682656 :                                                 } else if (print_blank) {
     903           0 :                                                         prefix_char = ' ';
     904             :                                                 }
     905             :                                         }
     906      685728 :                                         break;
     907             : 
     908             : 
     909             :                                 case 'o':
     910           0 :                                         switch(modifier) {
     911             :                                                 default:
     912           0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     913           0 :                                                         break;
     914             :                                                 case LM_LONG_DOUBLE:
     915           0 :                                                         goto fmt_error;
     916             :                                                 case LM_LONG:
     917           0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     918           0 :                                                         break;
     919             :                                                 case LM_SIZE_T:
     920           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     921           0 :                                                         break;
     922             : #if SIZEOF_LONG_LONG
     923             :                                                 case LM_LONG_LONG:
     924           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     925           0 :                                                         break;
     926             : #endif
     927             : #if SIZEOF_INTMAX_T
     928             :                                                 case LM_INTMAX_T:
     929           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     930           0 :                                                         break;
     931             : #endif
     932             : #if SIZEOF_PTRDIFF_T
     933             :                                                 case LM_PTRDIFF_T:
     934           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     935           0 :                                                         break;
     936             : #endif
     937             :                                                 case LM_PHP_INT_T:
     938           0 :                                                         ui_num = (u_wide_int) va_arg(ap, zend_ulong);
     939             :                                                         break;
     940             :                                         }
     941           0 :                                         s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
     942           0 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     943           0 :                                         if (alternate_form && *s != '0') {
     944           0 :                                                 *--s = '0';
     945           0 :                                                 s_len++;
     946             :                                         }
     947           0 :                                         break;
     948             : 
     949             : 
     950             :                                 case 'x':
     951             :                                 case 'X':
     952         493 :                                         switch(modifier) {
     953             :                                                 default:
     954         481 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     955         481 :                                                         break;
     956             :                                                 case LM_LONG_DOUBLE:
     957           0 :                                                         goto fmt_error;
     958             :                                                 case LM_LONG:
     959          12 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     960          12 :                                                         break;
     961             :                                                 case LM_SIZE_T:
     962           0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     963           0 :                                                         break;
     964             : #if SIZEOF_LONG_LONG
     965             :                                                 case LM_LONG_LONG:
     966           0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     967           0 :                                                         break;
     968             : #endif
     969             : #if SIZEOF_INTMAX_T
     970             :                                                 case LM_INTMAX_T:
     971           0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     972           0 :                                                         break;
     973             : #endif
     974             : #if SIZEOF_PTRDIFF_T
     975             :                                                 case LM_PTRDIFF_T:
     976           0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     977           0 :                                                         break;
     978             : #endif
     979             :                                                 case LM_PHP_INT_T:
     980           0 :                                                         ui_num = (u_wide_int) va_arg(ap, zend_ulong);
     981             :                                                         break;
     982             :                                         }
     983         493 :                                         s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
     984         493 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     985         493 :                                         if (alternate_form && i_num != 0) {
     986           0 :                                                 *--s = *fmt;    /* 'x' or 'X' */
     987           0 :                                                 *--s = '0';
     988           0 :                                                 s_len += 2;
     989             :                                         }
     990         493 :                                         break;
     991             : 
     992             : 
     993             :                                 case 's':
     994             :                                 case 'v':
     995      862615 :                                         s = va_arg(ap, char *);
     996      862615 :                                         if (s != NULL) {
     997      862615 :                                                 s_len = strlen(s);
     998      862615 :                                                 if (adjust_precision && (size_t)precision < s_len) {
     999          23 :                                                         s_len = precision;
    1000             :                                                 }
    1001             :                                         } else {
    1002           0 :                                                 s = S_NULL;
    1003           0 :                                                 s_len = S_NULL_LEN;
    1004             :                                         }
    1005      862615 :                                         pad_char = ' ';
    1006      862615 :                                         break;
    1007             : 
    1008             : 
    1009             :                                 case 'f':
    1010             :                                 case 'F':
    1011             :                                 case 'e':
    1012             :                                 case 'E':
    1013      100528 :                                         switch(modifier) {
    1014             :                                                 case LM_LONG_DOUBLE:
    1015           0 :                                                         fp_num = (double) va_arg(ap, long double);
    1016           0 :                                                         break;
    1017             :                                                 case LM_STD:
    1018      100528 :                                                         fp_num = va_arg(ap, double);
    1019      100528 :                                                         break;
    1020             :                                                 default:
    1021           0 :                                                         goto fmt_error;
    1022             :                                         }
    1023             : 
    1024      100528 :                                         if (zend_isnan(fp_num)) {
    1025           0 :                                                 s = "NAN";
    1026           0 :                                                 s_len = 3;
    1027      100528 :                                         } else if (zend_isinf(fp_num)) {
    1028           0 :                                                 s = "INF";
    1029           0 :                                                 s_len = 3;
    1030             :                                         } else {
    1031             : #ifdef HAVE_LOCALE_H
    1032             : #ifdef ZTS
    1033             :                                                 localeconv_r(&lconv);
    1034             : #else
    1035      100528 :                                                 if (!lconv) {
    1036      100528 :                                                         lconv = localeconv();
    1037             :                                                 }
    1038             : #endif
    1039             : #endif
    1040      100541 :                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
    1041             :                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
    1042      100541 :                                                  (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
    1043             :                                                                         &is_negative, &num_buf[1], &s_len);
    1044      100528 :                                                 if (is_negative)
    1045           0 :                                                         prefix_char = '-';
    1046      100528 :                                                 else if (print_sign)
    1047           0 :                                                         prefix_char = '+';
    1048      100528 :                                                 else if (print_blank)
    1049           0 :                                                         prefix_char = ' ';
    1050             :                                         }
    1051      100528 :                                         break;
    1052             : 
    1053             : 
    1054             :                                 case 'g':
    1055             :                                 case 'k':
    1056             :                                 case 'G':
    1057             :                                 case 'H':
    1058           3 :                                         switch(modifier) {
    1059             :                                                 case LM_LONG_DOUBLE:
    1060           0 :                                                         fp_num = (double) va_arg(ap, long double);
    1061           0 :                                                         break;
    1062             :                                                 case LM_STD:
    1063           3 :                                                         fp_num = va_arg(ap, double);
    1064           3 :                                                         break;
    1065             :                                                 default:
    1066           0 :                                                         goto fmt_error;
    1067             :                                         }
    1068             : 
    1069           3 :                                         if (zend_isnan(fp_num)) {
    1070           0 :                                                 s = "NAN";
    1071           0 :                                                 s_len = 3;
    1072           0 :                                                 break;
    1073           3 :                                         } else if (zend_isinf(fp_num)) {
    1074           0 :                                                 if (fp_num > 0) {
    1075           0 :                                                         s = "INF";
    1076           0 :                                                         s_len = 3;
    1077             :                                                 } else {
    1078           0 :                                                         s = "-INF";
    1079           0 :                                                         s_len = 4;
    1080             :                                                 }
    1081           0 :                                                 break;
    1082             :                                         }
    1083             : 
    1084           3 :                                         if (adjust_precision == NO) {
    1085           0 :                                                 precision = FLOAT_DIGITS;
    1086           3 :                                         } else if (precision == 0) {
    1087           0 :                                                 precision = 1;
    1088             :                                         }
    1089             :                                         /*
    1090             :                                          * * We use &num_buf[ 1 ], so that we have room for the sign
    1091             :                                          */
    1092             : #ifdef HAVE_LOCALE_H
    1093             : #ifdef ZTS
    1094             :                                         localeconv_r(&lconv);
    1095             : #else
    1096           3 :                                         if (!lconv) {
    1097           3 :                                                 lconv = localeconv();
    1098             :                                         }
    1099             : #endif
    1100             : #endif
    1101           3 :                                         s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
    1102           3 :                                         if (*s == '-') {
    1103           1 :                                                 prefix_char = *s++;
    1104           2 :                                         } else if (print_sign) {
    1105           0 :                                                 prefix_char = '+';
    1106           2 :                                         } else if (print_blank) {
    1107           0 :                                                 prefix_char = ' ';
    1108             :                                         }
    1109             : 
    1110           3 :                                         s_len = strlen(s);
    1111             : 
    1112           3 :                                         if (alternate_form && (strchr(s, '.')) == NULL) {
    1113           0 :                                                 s[s_len++] = '.';
    1114             :                                         }
    1115           3 :                                         break;
    1116             : 
    1117             : 
    1118             :                                 case 'c':
    1119        2834 :                                         char_buf[0] = (char) (va_arg(ap, int));
    1120        2834 :                                         s = &char_buf[0];
    1121        2834 :                                         s_len = 1;
    1122        2834 :                                         pad_char = ' ';
    1123        2834 :                                         break;
    1124             : 
    1125             : 
    1126             :                                 case '%':
    1127           1 :                                         char_buf[0] = '%';
    1128           1 :                                         s = &char_buf[0];
    1129           1 :                                         s_len = 1;
    1130           1 :                                         pad_char = ' ';
    1131           1 :                                         break;
    1132             : 
    1133             : 
    1134             :                                 case 'n':
    1135           0 :                                         *(va_arg(ap, int *)) = cc;
    1136           0 :                                         goto skip_output;
    1137             : 
    1138             :                                         /*
    1139             :                                          * Always extract the argument as a "char *" pointer. We
    1140             :                                          * should be using "void *" but there are still machines
    1141             :                                          * that don't understand it.
    1142             :                                          * If the pointer size is equal to the size of an unsigned
    1143             :                                          * integer we convert the pointer to a hex number, otherwise
    1144             :                                          * we print "%p" to indicate that we don't handle "%p".
    1145             :                                          */
    1146             :                                 case 'p':
    1147             :                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
    1148           0 :                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
    1149           0 :                                                 s = ap_php_conv_p2(ui_num, 4, 'x',
    1150             :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
    1151           0 :                                                 if (ui_num != 0) {
    1152           0 :                                                         *--s = 'x';
    1153           0 :                                                         *--s = '0';
    1154           0 :                                                         s_len += 2;
    1155             :                                                 }
    1156             :                                         } else {
    1157             :                                                 s = "%p";
    1158             :                                                 s_len = 2;
    1159             :                                         }
    1160           0 :                                         pad_char = ' ';
    1161           0 :                                         break;
    1162             : 
    1163             : 
    1164             :                                 case NUL:
    1165             :                                         /*
    1166             :                                          * The last character of the format string was %.
    1167             :                                          * We ignore it.
    1168             :                                          */
    1169           0 :                                         continue;
    1170             : 
    1171             : 
    1172             : fmt_error:
    1173           0 :                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
    1174             :                                         /*
    1175             :                                          * The default case is for unrecognized %'s.
    1176             :                                          * We print %<char> to help the user identify what
    1177             :                                          * option is not understood.
    1178             :                                          * This is also useful in case the user wants to pass
    1179             :                                          * the output of format_converter to another function
    1180             :                                          * that understands some other %<char> (like syslog).
    1181             :                                          * Note that we can't point s inside fmt because the
    1182             :                                          * unknown <char> could be preceded by width etc.
    1183             :                                          */
    1184             :                                 default:
    1185           0 :                                         char_buf[0] = '%';
    1186           0 :                                         char_buf[1] = *fmt;
    1187           0 :                                         s = char_buf;
    1188           0 :                                         s_len = 2;
    1189           0 :                                         pad_char = ' ';
    1190             :                                         break;
    1191             :                         }
    1192             : 
    1193     1652202 :                         if (prefix_char != NUL) {
    1194         580 :                                 *--s = prefix_char;
    1195         580 :                                 s_len++;
    1196             :                         }
    1197     1652202 :                         if (adjust_width && adjust == RIGHT && (size_t)min_width > s_len) {
    1198       19973 :                                 if (pad_char == '0' && prefix_char != NUL) {
    1199           5 :                                         INS_CHAR(*s, sp, bep, cc)
    1200           5 :                                                 s++;
    1201           5 :                                         s_len--;
    1202           5 :                                         min_width--;
    1203             :                                 }
    1204       24077 :                                 PAD((size_t)min_width, s_len, pad_char);
    1205             :                         }
    1206             :                         /*
    1207             :                          * Print the string s.
    1208             :                          */
    1209    10255000 :                         for (i = s_len; i != 0; i--) {
    1210     8602798 :                                 INS_CHAR(*s, sp, bep, cc);
    1211     8602798 :                                 s++;
    1212             :                         }
    1213             : 
    1214     1652202 :                         if (adjust_width && adjust == LEFT && (size_t)min_width > s_len)
    1215           0 :                                 PAD((size_t)min_width, s_len, pad_char);
    1216     1652202 :                         if (free_zcopy) {
    1217             :                                 zval_dtor(&zcopy);
    1218             :                         }
    1219             :                 }
    1220             : skip_output:
    1221     6368883 :                 fmt++;
    1222             :         }
    1223     1477201 :         odp->nextb = sp;
    1224     1477201 :         return (cc);
    1225             : }
    1226             : /* }}} */
    1227             : 
    1228             : /*
    1229             :  * This is the general purpose conversion function.
    1230             :  */
    1231     1477201 : static void strx_printv(int *ccp, char *buf, size_t len, const char *format, va_list ap) /* {{{ */
    1232             : {
    1233             :         buffy od;
    1234             :         int cc;
    1235             : 
    1236             :         /*
    1237             :          * First initialize the descriptor
    1238             :          * Notice that if no length is given, we initialize buf_end to the
    1239             :          * highest possible address.
    1240             :          */
    1241     1477201 :         if (len == 0) {
    1242           0 :                 od.buf_end = (char *) ~0;
    1243           0 :                 od.nextb   = (char *) ~0;
    1244             :         } else {
    1245     1477201 :                 od.buf_end = &buf[len-1];
    1246     1477201 :                 od.nextb   = buf;
    1247             :         }
    1248             : 
    1249             :         /*
    1250             :          * Do the conversion
    1251             :          */
    1252     1477201 :         cc = format_converter(&od, format, ap);
    1253     1477201 :         if (len != 0 && od.nextb <= od.buf_end) {
    1254     1477201 :                 *(od.nextb) = '\0';
    1255             :         }
    1256     1477201 :         if (ccp) {
    1257     1477201 :                 *ccp = cc;
    1258             :         }
    1259     1477201 : }
    1260             : /* }}} */
    1261             : 
    1262     1315975 : PHPAPI int ap_php_slprintf(char *buf, size_t len, const char *format,...) /* {{{ */
    1263             : {
    1264             :         int cc;
    1265             :         va_list ap;
    1266             : 
    1267     1315975 :         va_start(ap, format);
    1268     1315975 :         strx_printv(&cc, buf, len, format, ap);
    1269     1315975 :         va_end(ap);
    1270     1315975 :         if ((size_t)cc >= len) {
    1271           0 :                 cc = (int)len -1;
    1272           0 :                 buf[cc] = '\0';
    1273             :         }
    1274     1315975 :         return cc;
    1275             : }
    1276             : /* }}} */
    1277             : 
    1278          13 : PHPAPI int ap_php_vslprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
    1279             : {
    1280             :         int cc;
    1281             : 
    1282          13 :         strx_printv(&cc, buf, len, format, ap);
    1283          13 :         if ((size_t)cc >= len) {
    1284           0 :                 cc = (int)len -1;
    1285           0 :                 buf[cc] = '\0';
    1286             :         }
    1287          13 :         return cc;
    1288             : }
    1289             : /* }}} */
    1290             : 
    1291      161182 : PHPAPI int ap_php_snprintf(char *buf, size_t len, const char *format,...) /* {{{ */
    1292             : {
    1293             :         int cc;
    1294             :         va_list ap;
    1295             : 
    1296      161182 :         va_start(ap, format);
    1297      161182 :         strx_printv(&cc, buf, len, format, ap);
    1298      161182 :         va_end(ap);
    1299      161182 :         return (cc);
    1300             : }
    1301             : /* }}} */
    1302             : 
    1303          31 : PHPAPI int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
    1304             : {
    1305             :         int cc;
    1306             : 
    1307          31 :         strx_printv(&cc, buf, len, format, ap);
    1308          31 :         return (cc);
    1309             : }
    1310             : /* }}} */
    1311             : 
    1312           0 : PHPAPI int ap_php_vasprintf(char **buf, const char *format, va_list ap) /* {{{ */
    1313             : {
    1314             :         va_list ap2;
    1315             :         int cc;
    1316             : 
    1317           0 :         va_copy(ap2, ap);
    1318           0 :         cc = ap_php_vsnprintf(NULL, 0, format, ap2);
    1319           0 :         va_end(ap2);
    1320             : 
    1321           0 :         *buf = NULL;
    1322             : 
    1323           0 :         if (cc >= 0) {
    1324           0 :                 if ((*buf = malloc(++cc)) != NULL) {
    1325           0 :                         if ((cc = ap_php_vsnprintf(*buf, cc, format, ap)) < 0) {
    1326           0 :                                 free(*buf);
    1327           0 :                                 *buf = NULL;
    1328             :                         }
    1329             :                 }
    1330             :         }
    1331             : 
    1332           0 :         return cc;
    1333             : }
    1334             : /* }}} */
    1335             : 
    1336           0 : PHPAPI int ap_php_asprintf(char **buf, const char *format, ...) /* {{{ */
    1337             : {
    1338             :         int cc;
    1339             :         va_list ap;
    1340             : 
    1341           0 :         va_start(ap, format);
    1342           0 :         cc = vasprintf(buf, format, ap);
    1343           0 :         va_end(ap);
    1344           0 :         return cc;
    1345             : }
    1346             : /* }}} */
    1347             : 
    1348             : /*
    1349             :  * Local variables:
    1350             :  * tab-width: 4
    1351             :  * c-basic-offset: 4
    1352             :  * End:
    1353             :  * vim600: sw=4 ts=4 fdm=marker
    1354             :  * vim<600: sw=4 ts=4
    1355             :  */

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:12 +0000 (4 days ago)

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