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: 334 506 66.0 %
Date: 2014-11-15 Functions: 13 15 86.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 15 Nov 2014 06:19:45 +0000 (9 days ago)

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