PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/main - snprintf.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 477
Code covered: 66.2 % Executed lines: 316
Legend: not executed executed

       1                 : /*
       2                 :   +----------------------------------------------------------------------+
       3                 :   | PHP Version 5                                                        |
       4                 :   +----------------------------------------------------------------------+
       5                 :   | Copyright (c) 1997-2009 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: snprintf.c 272374 2008-12-31 11:17:49Z sebastian $ */
      20                 : 
      21                 : 
      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                 : static char * __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) /* {{{ */
      67          102751 : {
      68          102751 :         register char *s = NULL;
      69                 :         char *p, *rve, c;
      70                 :         size_t siz;
      71                 : 
      72          102751 :         if (ndigit < 0) {
      73               0 :                 siz = -ndigit + 1;
      74                 :         } else {
      75          102751 :                 siz = ndigit + 1;
      76                 :         }
      77                 : 
      78                 :         /* __dtoa() doesn't allocate space for 0 so we do it by hand */
      79          102751 :         if (value == 0.0) {
      80             491 :                 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
      81             491 :                 *sign = 0;
      82             491 :                 if ((rve = s = (char *)malloc(ndigit?siz:2)) == NULL) {
      83               0 :                         return(NULL);
      84                 :                 }
      85             491 :                 *rve++ = '0';
      86             491 :                 *rve = '\0';
      87             491 :                 if (!ndigit) {
      88               3 :                         return(s);
      89                 :                 }
      90                 :         } else {
      91          102260 :                 p = zend_dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
      92          102260 :                 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(c == 'I' ? "INF" : "NAN");
      98                 :                 }
      99                 :                 /* Make a local copy and adjust rve to be in terms of s */
     100          102260 :                 if (pad && fmode) {
     101          101520 :                         siz += *decpt;
     102                 :                 }
     103          102260 :                 if ((s = (char *)malloc(siz+1)) == NULL) {
     104               0 :                         zend_freedtoa(p);
     105               0 :                         return(NULL);
     106                 :                 }
     107          102260 :                 (void) strlcpy(s, p, siz);
     108          102260 :                 rve = s + (rve - p);
     109          102260 :                 zend_freedtoa(p);
     110                 :         }
     111                 : 
     112                 :         /* Add trailing zeros */
     113          102748 :         if (pad) {
     114          102748 :                 siz -= rve - s;
     115          428508 :                 while (--siz) {
     116          223012 :                         *rve++ = '0';
     117                 :                 }
     118          102748 :                 *rve = '\0';
     119                 :         }
     120                 : 
     121          102748 :         return(s);
     122                 : }
     123                 : /* }}} */
     124                 : 
     125                 : static inline char *php_ecvt(double value, int ndigit, int *decpt, int *sign) /* {{{ */
     126             970 : {
     127             970 :         return(__cvt(value, ndigit, decpt, sign, 0, 1));
     128                 : }
     129                 : /* }}} */
     130                 : 
     131                 : static inline char *php_fcvt(double value, int ndigit, int *decpt, int *sign) /* {{{ */
     132          101781 : {
     133          101781 :     return(__cvt(value, ndigit, decpt, sign, 1, 1));
     134                 : }
     135                 : /* }}} */
     136                 : 
     137                 : PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf) /* {{{ */
     138           21751 : {
     139                 :         char *digits, *dst, *src;
     140                 :         int i, decpt, sign;
     141                 : 
     142           21751 :         digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL);
     143           21751 :         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           21739 :         dst = buf;
     154           21739 :         if (sign) {
     155            2358 :                 *dst++ = '-';
     156                 :         }
     157                 : 
     158           22416 :         if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
     159                 :                 /* exponential format (e.g. 1.2345e+13) */
     160             677 :                 if (--decpt < 0) {
     161             568 :                         sign = 1;
     162             568 :                         decpt = -decpt;
     163                 :                 } else {
     164             109 :                         sign = 0;
     165                 :                 }
     166             677 :                 src = digits;
     167             677 :                 *dst++ = *src++;
     168             677 :                 *dst++ = dec_point;
     169             677 :                 if (*src == '\0') {
     170             165 :                         *dst++ = '0';
     171                 :                 } else {
     172                 :                         do {
     173            4309 :                                 *dst++ = *src++;
     174            4309 :                         } while (*src != '\0');
     175                 :                 }
     176             677 :                 *dst++ = exponent;
     177             677 :                 if (sign) {
     178             568 :                         *dst++ = '-';
     179                 :                 } else {
     180             109 :                         *dst++ = '+';
     181                 :                 }
     182             677 :                 if (decpt < 10) {
     183             470 :                         *dst++ = '0' + decpt;
     184             470 :                         *dst = '\0';
     185                 :                 } else {
     186                 :                         /* XXX - optimize */
     187             207 :                         for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
     188                 :                                 continue;
     189             207 :                         dst[i + 1] = '\0';
     190             848 :                         while (decpt != 0) {
     191             434 :                                 dst[i--] = '0' + decpt % 10;
     192             434 :                                 decpt /= 10;
     193                 :                         }
     194                 :                 }
     195           21062 :         } else if (decpt < 0) {
     196                 :                 /* standard format 0. */
     197             297 :                 *dst++ = '0';   /* zero before decimal point */
     198             297 :                 *dst++ = dec_point;
     199                 :                 do {
     200             504 :                         *dst++ = '0';
     201             504 :                 } while (++decpt < 0);
     202             297 :                 src = digits;
     203            2144 :                 while (*src != '\0') {
     204            1550 :                         *dst++ = *src++;
     205                 :                 }
     206             297 :                 *dst = '\0';
     207                 :         } else {
     208                 :                 /* standard format */
     209           62147 :                 for (i = 0, src = digits; i < decpt; i++) {
     210           41382 :                         if (*src != '\0') {
     211           36751 :                                 *dst++ = *src++;
     212                 :                         } else {
     213            4631 :                                 *dst++ = '0';
     214                 :                         }
     215                 :                 }
     216           20765 :                 if (*src != '\0') {
     217           16520 :                         if (src == digits) {
     218            2715 :                                 *dst++ = '0';   /* zero before decimal point */
     219                 :                         }
     220           16520 :                         *dst++ = dec_point;
     221          153844 :                         for (i = decpt; digits[i] != '\0'; i++) {
     222          137324 :                 *dst++ = digits[i];
     223                 :             }
     224                 :         }
     225           20765 :         *dst = '\0';
     226                 :     }
     227           21739 :     zend_freedtoa(digits);
     228           21739 :     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                 : 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         4547166 : {
     317         4547166 :         register char *p = buf_end;
     318                 :         register u_wide_int magnitude;
     319                 : 
     320         4547166 :         if (is_unsigned) {
     321             901 :                 magnitude = (u_wide_int) num;
     322             901 :                 *is_negative = FALSE;
     323                 :         } else {
     324         4546265 :                 *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         4546265 :                 if (*is_negative) {
     336            4536 :                         wide_int t = num + 1;
     337            4536 :                         magnitude = ((u_wide_int) - t) + 1;
     338                 :                 } else {
     339         4541729 :                         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        17653864 :                 register u_wide_int new_magnitude = magnitude / 10;
     348                 : 
     349        17653864 :                 *--p = (char)(magnitude - new_magnitude * 10 + '0');
     350        17653864 :                 magnitude = new_magnitude;
     351                 :         }
     352        17653864 :         while (magnitude);
     353                 : 
     354         4547166 :         *len = buf_end - p;
     355         4547166 :         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                 : 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          102751 : {
     375          102751 :         register char *s = buf;
     376                 :         register char *p, *p_orig;
     377                 :         int decimal_point;
     378                 : 
     379          102751 :         if (precision >= NDIG - 1) {
     380               1 :                 precision = NDIG - 2;
     381                 :         }
     382                 : 
     383          102751 :         if (format == 'F') {
     384          101781 :                 p_orig = p = php_fcvt(num, precision, &decimal_point, is_negative);
     385                 :         } else {                                                /* either e or E format */
     386             970 :                 p_orig = p = php_ecvt(num, precision + 1, &decimal_point, is_negative);
     387                 :         }
     388                 : 
     389                 :         /*
     390                 :          * Check for Infinity and NaN
     391                 :          */
     392          102751 :         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          102751 :         if (format == 'F') {
     400          101781 :                 if (decimal_point <= 0) {
     401          100429 :                         if (num != 0 || precision > 0) {
     402          100426 :                                 *s++ = '0';
     403          100426 :                                 if (precision > 0) {
     404          100426 :                                         *s++ = dec_point;
     405          212165 :                                         while (decimal_point++ < 0) {
     406           11313 :                                                 *s++ = '0';
     407                 :                                         }
     408               0 :                                 } else if (add_dp) {
     409               0 :                                         *s++ = dec_point;
     410                 :                                 }
     411                 :                         }
     412                 :                 } else {
     413            1352 :                         int addz = decimal_point >= NDIG ? decimal_point - NDIG + 1 : 0;
     414            1352 :                         decimal_point -= addz;
     415            9981 :                         while (decimal_point-- > 0) {
     416            7277 :                                 *s++ = *p++;
     417                 :                         }
     418            2704 :                         while (addz-- > 0) {
     419               0 :                                 *s++ = '0';
     420                 :                         }
     421            1352 :                         if (precision > 0 || add_dp) {
     422            1206 :                                 *s++ = dec_point;
     423                 :                         }
     424                 :                 }
     425                 :         } else {
     426             970 :                 *s++ = *p++;
     427             970 :                 if (precision > 0 || add_dp) {
     428             969 :                         *s++ = '.';
     429                 :                 }
     430                 :         }
     431                 : 
     432                 :         /*
     433                 :          * copy the rest of p, the NUL is NOT copied
     434                 :          */
     435         1009547 :         while (*p) {
     436          804045 :                 *s++ = *p++;
     437                 :         }
     438                 : 
     439          102751 :         if (format != 'F') {
     440                 :                 char temp[EXPONENT_LENGTH];             /* for exponent conversion */
     441                 :                 int t_len;
     442                 :                 bool_int exponent_is_negative;
     443                 : 
     444             970 :                 *s++ = format;                  /* either e or E */
     445             970 :                 decimal_point--;
     446             970 :                 if (decimal_point != 0) {
     447             437 :                         p = ap_php_conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, &temp[EXPONENT_LENGTH], &t_len);
     448             437 :                         *s++ = exponent_is_negative ? '-' : '+';
     449                 : 
     450                 :                         /*
     451                 :                          * Make sure the exponent has at least 2 digits
     452                 :                          */
     453            1341 :                         while (t_len--) {
     454             467 :                                 *s++ = *p++;
     455                 :                         }
     456                 :                 } else {
     457             533 :                         *s++ = '+';
     458             533 :                         *s++ = '0';
     459                 :                 }
     460                 :         }
     461          102751 :         *len = s - buf;
     462          102751 :         free(p_orig);
     463          102751 :         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                 : char * ap_php_conv_p2(register u_wide_int num, register int nbits, char format, char *buf_end, register int *len) /* {{{ */
     478           17982 : {
     479           17982 :         register int mask = (1 << nbits) - 1;
     480           17982 :         register char *p = buf_end;
     481                 :         static char low_digits[] = "0123456789abcdef";
     482                 :         static char upper_digits[] = "0123456789ABCDEF";
     483           17982 :         register char *digits = (format == 'X') ? upper_digits : low_digits;
     484                 : 
     485                 :         do {
     486          115496 :                 *--p = digits[num & mask];
     487          115496 :                 num >>= nbits;
     488                 :         }
     489          115496 :         while (num);
     490                 : 
     491           17982 :         *len = buf_end - p;
     492           17982 :         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                 :  */
     501                 : #define NUM_BUF_SIZE            512
     502                 : 
     503                 : 
     504                 : /*
     505                 :  * Descriptor for buffer area
     506                 :  */
     507                 : struct buf_area {
     508                 :         char *buf_end;
     509                 :         char *nextb;                            /* pointer to next byte to read/write   */
     510                 : };
     511                 : 
     512                 : typedef struct buf_area buffy;
     513                 : 
     514                 : /*
     515                 :  * The INS_CHAR macro inserts a character in the buffer and writes
     516                 :  * the buffer back to disk if necessary
     517                 :  * It uses the char pointers sp and bep:
     518                 :  *      sp points to the next available character in the buffer
     519                 :  *      bep points to the end-of-buffer+1
     520                 :  * While using this macro, note that the nextb pointer is NOT updated.
     521                 :  *
     522                 :  * NOTE: Evaluation of the c argument should not have any side-effects
     523                 :  */
     524                 : #define INS_CHAR(c, sp, bep, cc) \
     525                 :         {                            \
     526                 :                 if (sp < bep)            \
     527                 :                 {                        \
     528                 :                         *sp++ = c;           \
     529                 :                 }                        \
     530                 :                 cc++;                    \
     531                 :         }
     532                 : 
     533                 : #define NUM( c )                        ( c - '0' )
     534                 : 
     535                 : #define STR_TO_DEC( str, num )          \
     536                 :     num = NUM( *str++ ) ;               \
     537                 :     while ( isdigit((int)*str ) )               \
     538                 :     {                                   \
     539                 :         num *= 10 ;                     \
     540                 :         num += NUM( *str++ ) ;          \
     541                 :     }
     542                 : 
     543                 : /*
     544                 :  * This macro does zero padding so that the precision
     545                 :  * requirement is satisfied. The padding is done by
     546                 :  * adding '0's to the left of the string that is going
     547                 :  * to be printed.
     548                 :  */
     549                 : #define FIX_PRECISION( adjust, precision, s, s_len )    \
     550                 :     if ( adjust )                                       \
     551                 :         while ( s_len < precision )                  \
     552                 :         {                                               \
     553                 :             *--s = '0' ;                                \
     554                 :             s_len++ ;                                   \
     555                 :         }
     556                 : 
     557                 : /*
     558                 :  * Macro that does padding. The padding is done by printing
     559                 :  * the character ch.
     560                 :  */
     561                 : #define PAD( width, len, ch )   do              \
     562                 :         {                                       \
     563                 :             INS_CHAR( ch, sp, bep, cc ) ;       \
     564                 :             width-- ;                           \
     565                 :         }                                       \
     566                 :         while ( width > len )
     567                 : 
     568                 : /*
     569                 :  * Prefix the character ch to the string str
     570                 :  * Increase length
     571                 :  * Set the has_prefix flag
     572                 :  */
     573                 : #define PREFIX( str, length, ch )        *--str = ch ; length++ ; has_prefix = YES
     574                 : 
     575                 : 
     576                 : /*
     577                 :  * Do format conversion placing the output in buffer
     578                 :  */
     579                 : static int format_converter(register buffy * odp, const char *fmt, va_list ap) /* {{{ */
     580          557740 : {
     581                 :         register char *sp;
     582                 :         register char *bep;
     583          557740 :         register int cc = 0;
     584                 :         register int i;
     585                 : 
     586          557740 :         register char *s = NULL;
     587                 :         char *q;
     588                 :         int s_len;
     589                 : 
     590          557740 :         register int min_width = 0;
     591          557740 :         int precision = 0;
     592                 :         enum {
     593                 :                 LEFT, RIGHT
     594                 :         } adjust;
     595                 :         char pad_char;
     596                 :         char prefix_char;
     597                 : 
     598                 :         double fp_num;
     599          557740 :         wide_int i_num = (wide_int) 0;
     600                 :         u_wide_int ui_num;
     601                 : 
     602                 :         char num_buf[NUM_BUF_SIZE];
     603                 :         char char_buf[2];                       /* for printing %% and %<unknown> */
     604                 : 
     605                 : #ifdef HAVE_LOCALE_H
     606          557740 :         struct lconv *lconv = NULL;
     607                 : #endif
     608                 : 
     609                 :         /*
     610                 :          * Flag variables
     611                 :          */
     612                 :         length_modifier_e modifier;
     613                 :         boolean_e alternate_form;
     614                 :         boolean_e print_sign;
     615                 :         boolean_e print_blank;
     616                 :         boolean_e adjust_precision;
     617                 :         boolean_e adjust_width;
     618                 :         bool_int is_negative;
     619                 : 
     620          557740 :         sp = odp->nextb;
     621          557740 :         bep = odp->buf_end;
     622                 : 
     623         2056407 :         while (*fmt) {
     624          940927 :                 if (*fmt != '%') {
     625          200447 :                         INS_CHAR(*fmt, sp, bep, cc);
     626                 :                 } else {
     627                 :                         /*
     628                 :                          * Default variable settings
     629                 :                          */
     630          740480 :                         adjust = RIGHT;
     631          740480 :                         alternate_form = print_sign = print_blank = NO;
     632          740480 :                         pad_char = ' ';
     633          740480 :                         prefix_char = NUL;
     634                 : 
     635          740480 :                         fmt++;
     636                 : 
     637                 :                         /*
     638                 :                          * Try to avoid checking for flags, width or precision
     639                 :                          */
     640          853424 :                         if (isascii((int)*fmt) && !islower((int)*fmt)) {
     641                 :                                 /*
     642                 :                                  * Recognize flags: -, #, BLANK, +
     643                 :                                  */
     644           12685 :                                 for (;; fmt++) {
     645          125629 :                                         if (*fmt == '-')
     646              33 :                                                 adjust = LEFT;
     647          125596 :                                         else if (*fmt == '+')
     648               0 :                                                 print_sign = YES;
     649          125596 :                                         else if (*fmt == '#')
     650               0 :                                                 alternate_form = YES;
     651          125596 :                                         else if (*fmt == ' ')
     652               0 :                                                 print_blank = YES;
     653          125596 :                                         else if (*fmt == '0')
     654           12652 :                                                 pad_char = '0';
     655                 :                                         else
     656          112944 :                                                 break;
     657           12685 :                                 }
     658                 : 
     659                 :                                 /*
     660                 :                                  * Check if a width was specified
     661                 :                                  */
     662          112944 :                                 if (isdigit((int)*fmt)) {
     663           12678 :                                         STR_TO_DEC(fmt, min_width);
     664           12678 :                                         adjust_width = YES;
     665          100266 :                                 } else if (*fmt == '*') {
     666               0 :                                         min_width = va_arg(ap, int);
     667               0 :                                         fmt++;
     668               0 :                                         adjust_width = YES;
     669               0 :                                         if (min_width < 0) {
     670               0 :                                                 adjust = LEFT;
     671               0 :                                                 min_width = -min_width;
     672                 :                                         }
     673                 :                                 } else
     674          100266 :                                         adjust_width = NO;
     675                 : 
     676                 :                                 /*
     677                 :                                  * Check if a precision was specified
     678                 :                                  *
     679                 :                                  * XXX: an unreasonable amount of precision may be specified
     680                 :                                  * resulting in overflow of num_buf. Currently we
     681                 :                                  * ignore this possibility.
     682                 :                                  */
     683          112944 :                                 if (*fmt == '.') {
     684          100221 :                                         adjust_precision = YES;
     685          100221 :                                         fmt++;
     686          100221 :                                         if (isdigit((int)*fmt)) {
     687          100116 :                                                 STR_TO_DEC(fmt, precision);
     688             105 :                                         } else if (*fmt == '*') {
     689             105 :                                                 precision = va_arg(ap, int);
     690             105 :                                                 fmt++;
     691             105 :                                                 if (precision < 0)
     692               0 :                                                         precision = 0;
     693                 :                                         } else
     694               0 :                                                 precision = 0;
     695                 :                                 } else
     696           12723 :                                         adjust_precision = NO;
     697                 :                         } else
     698          627536 :                                 adjust_precision = adjust_width = NO;
     699                 : 
     700                 :                         /*
     701                 :                          * Modifier check
     702                 :                          */
     703          740480 :                         switch (*fmt) {
     704                 :                                 case 'L':
     705               0 :                                         fmt++;
     706               0 :                                         modifier = LM_LONG_DOUBLE;
     707               0 :                                         break;
     708                 :                                 case 'I':
     709               0 :                                         fmt++;
     710                 : #if SIZEOF_LONG_LONG
     711               0 :                                         if (*fmt == '6' && *(fmt+1) == '4') {
     712               0 :                                                 fmt += 2;
     713               0 :                                                 modifier = LM_LONG_LONG;
     714                 :                                         } else
     715                 : #endif
     716               0 :                                                 if (*fmt == '3' && *(fmt+1) == '2') {
     717               0 :                                                         fmt += 2;
     718               0 :                                                         modifier = LM_LONG;
     719                 :                                                 } else {
     720                 : #ifdef _WIN64
     721                 :                                                         modifier = LM_LONG_LONG;
     722                 : #else
     723               0 :                                                         modifier = LM_LONG;
     724                 : #endif
     725                 :                                                 }
     726               0 :                                         break;
     727                 :                                 case 'l':
     728          462443 :                                         fmt++;
     729                 : #if SIZEOF_LONG_LONG
     730          462443 :                                         if (*fmt == 'l') {
     731            1532 :                                                 fmt++;
     732            1532 :                                                 modifier = LM_LONG_LONG;
     733                 :                                         } else
     734                 : #endif
     735          460911 :                                                 modifier = LM_LONG;
     736          462443 :                                         break;
     737                 :                                 case 'z':
     738               0 :                                         fmt++;
     739               0 :                                         modifier = LM_SIZE_T;
     740               0 :                                         break;
     741                 :                                 case 'j':
     742               0 :                                         fmt++;
     743                 : #if SIZEOF_INTMAX_T
     744               0 :                                         modifier = LM_INTMAX_T;
     745                 : #else
     746                 :                                         modifier = LM_SIZE_T;
     747                 : #endif
     748               0 :                                         break;
     749                 :                                 case 't':
     750               0 :                                         fmt++;
     751                 : #if SIZEOF_PTRDIFF_T
     752               0 :                                         modifier = LM_PTRDIFF_T;
     753                 : #else
     754                 :                                         modifier = LM_SIZE_T;
     755                 : #endif
     756               0 :                                         break;
     757                 :                                 case 'h':
     758               0 :                                         fmt++;
     759               0 :                                         if (*fmt == 'h') {
     760               0 :                                                 fmt++;
     761                 :                                         }
     762                 :                                         /* these are promoted to int, so no break */
     763                 :                                 default:                                
     764          278037 :                                         modifier = LM_STD;
     765                 :                                         break;
     766                 :                         }
     767                 : 
     768                 :                         /*
     769                 :                          * Argument extraction and printing.
     770                 :                          * First we determine the argument type.
     771                 :                          * Then, we convert the argument to a string.
     772                 :                          * On exit from the switch, s points to the string that
     773                 :                          * must be printed, s_len has the length of the string
     774                 :                          * The precision requirements, if any, are reflected in s_len.
     775                 :                          *
     776                 :                          * NOTE: pad_char may be set to '0' because of the 0 flag.
     777                 :                          *   It is reset to ' ' by non-numeric formats
     778                 :                          */
     779          740480 :                         switch (*fmt) {
     780                 :                                 case 'u':
     781             249 :                                         switch(modifier) {
     782                 :                                                 default:
     783             243 :                                                         i_num = (wide_int) va_arg(ap, unsigned int);
     784             243 :                                                         break;
     785                 :                                                 case LM_LONG_DOUBLE:
     786               0 :                                                         goto fmt_error;
     787                 :                                                 case LM_LONG:
     788               0 :                                                         i_num = (wide_int) va_arg(ap, unsigned long int);
     789               0 :                                                         break;
     790                 :                                                 case LM_SIZE_T:
     791               0 :                                                         i_num = (wide_int) va_arg(ap, size_t);
     792               0 :                                                         break;
     793                 : #if SIZEOF_LONG_LONG
     794                 :                                                 case LM_LONG_LONG:
     795               6 :                                                         i_num = (wide_int) va_arg(ap, u_wide_int);
     796               6 :                                                         break;
     797                 : #endif
     798                 : #if SIZEOF_INTMAX_T
     799                 :                                                 case LM_INTMAX_T:
     800               0 :                                                         i_num = (wide_int) va_arg(ap, uintmax_t);
     801               0 :                                                         break;
     802                 : #endif
     803                 : #if SIZEOF_PTRDIFF_T
     804                 :                                                 case LM_PTRDIFF_T:
     805               0 :                                                         i_num = (wide_int) va_arg(ap, ptrdiff_t);
     806                 :                                                         break;
     807                 : #endif
     808                 :                                         }
     809                 :                                         /*
     810                 :                                          * The rest also applies to other integer formats, so fall
     811                 :                                          * into that case.
     812                 :                                          */
     813                 :                                 case 'd':
     814                 :                                 case 'i':
     815                 :                                         /*
     816                 :                                          * Get the arg if we haven't already.
     817                 :                                          */
     818          476638 :                                         if ((*fmt) != 'u') {
     819          476389 :                                                 switch(modifier) {
     820                 :                                                         default:
     821           13956 :                                                                 i_num = (wide_int) va_arg(ap, int);
     822           13956 :                                                                 break;
     823                 :                                                         case LM_LONG_DOUBLE:
     824               0 :                                                                 goto fmt_error;
     825                 :                                                         case LM_LONG:
     826          460907 :                                                                 i_num = (wide_int) va_arg(ap, long int);
     827          460907 :                                                                 break;
     828                 :                                                         case LM_SIZE_T:
     829                 : #if SIZEOF_SSIZE_T
     830               0 :                                                                 i_num = (wide_int) va_arg(ap, ssize_t);
     831                 : #else
     832                 :                                                                 i_num = (wide_int) va_arg(ap, size_t);
     833                 : #endif
     834               0 :                                                                 break;
     835                 : #if SIZEOF_LONG_LONG
     836                 :                                                         case LM_LONG_LONG:
     837            1526 :                                                                 i_num = (wide_int) va_arg(ap, wide_int);
     838            1526 :                                                                 break;
     839                 : #endif
     840                 : #if SIZEOF_INTMAX_T
     841                 :                                                         case LM_INTMAX_T:
     842               0 :                                                                 i_num = (wide_int) va_arg(ap, intmax_t);
     843               0 :                                                                 break;
     844                 : #endif
     845                 : #if SIZEOF_PTRDIFF_T
     846                 :                                                         case LM_PTRDIFF_T:
     847               0 :                                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
     848                 :                                                                 break;
     849                 : #endif
     850                 :                                                 }
     851                 :                                         }
     852          476638 :                                         s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
     853                 :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
     854          476638 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     855                 : 
     856          476638 :                                         if (*fmt != 'u') {
     857          476389 :                                                 if (is_negative) {
     858              24 :                                                         prefix_char = '-';
     859          476365 :                                                 } else if (print_sign) {
     860               0 :                                                         prefix_char = '+';
     861          476365 :                                                 } else if (print_blank) {
     862               0 :                                                         prefix_char = ' ';
     863                 :                                                 }
     864                 :                                         }
     865          476638 :                                         break;
     866                 : 
     867                 : 
     868                 :                                 case 'o':
     869               0 :                                         switch(modifier) {
     870                 :                                                 default:
     871               0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     872               0 :                                                         break;
     873                 :                                                 case LM_LONG_DOUBLE:
     874               0 :                                                         goto fmt_error;
     875                 :                                                 case LM_LONG:
     876               0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     877               0 :                                                         break;
     878                 :                                                 case LM_SIZE_T:
     879               0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     880               0 :                                                         break;
     881                 : #if SIZEOF_LONG_LONG
     882                 :                                                 case LM_LONG_LONG:
     883               0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     884               0 :                                                         break;
     885                 : #endif
     886                 : #if SIZEOF_INTMAX_T
     887                 :                                                 case LM_INTMAX_T:
     888               0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     889               0 :                                                         break;
     890                 : #endif
     891                 : #if SIZEOF_PTRDIFF_T
     892                 :                                                 case LM_PTRDIFF_T:
     893               0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     894                 :                                                         break;
     895                 : #endif
     896                 :                                         }
     897               0 :                                         s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
     898               0 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     899               0 :                                         if (alternate_form && *s != '0') {
     900               0 :                                                 *--s = '0';
     901               0 :                                                 s_len++;
     902                 :                                         }
     903               0 :                                         break;
     904                 : 
     905                 : 
     906                 :                                 case 'x':
     907                 :                                 case 'X':
     908               4 :                                         switch(modifier) {
     909                 :                                                 default:
     910               0 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned int);
     911               0 :                                                         break;
     912                 :                                                 case LM_LONG_DOUBLE:
     913               0 :                                                         goto fmt_error;
     914                 :                                                 case LM_LONG:
     915               4 :                                                         ui_num = (u_wide_int) va_arg(ap, unsigned long int);
     916               4 :                                                         break;
     917                 :                                                 case LM_SIZE_T:
     918               0 :                                                         ui_num = (u_wide_int) va_arg(ap, size_t);
     919               0 :                                                         break;
     920                 : #if SIZEOF_LONG_LONG
     921                 :                                                 case LM_LONG_LONG:
     922               0 :                                                         ui_num = (u_wide_int) va_arg(ap, u_wide_int);
     923               0 :                                                         break;
     924                 : #endif
     925                 : #if SIZEOF_INTMAX_T
     926                 :                                                 case LM_INTMAX_T:
     927               0 :                                                         ui_num = (u_wide_int) va_arg(ap, uintmax_t);
     928               0 :                                                         break;
     929                 : #endif
     930                 : #if SIZEOF_PTRDIFF_T
     931                 :                                                 case LM_PTRDIFF_T:
     932               0 :                                                         ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
     933                 :                                                         break;
     934                 : #endif
     935                 :                                         }
     936               4 :                                         s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
     937               4 :                                         FIX_PRECISION(adjust_precision, precision, s, s_len);
     938               4 :                                         if (alternate_form && i_num != 0) {
     939               0 :                                                 *--s = *fmt;    /* 'x' or 'X' */
     940               0 :                                                 *--s = '0';
     941               0 :                                                 s_len += 2;
     942                 :                                         }
     943               4 :                                         break;
     944                 : 
     945                 : 
     946                 :                                 case 's':
     947                 :                                 case 'v':
     948          162542 :                                         s = va_arg(ap, char *);
     949          162542 :                                         if (s != NULL) {
     950          162542 :                                                 s_len = strlen(s);
     951          162542 :                                                 if (adjust_precision && precision < s_len) {
     952               0 :                                                         s_len = precision;
     953                 :                                                 }
     954                 :                                         } else {
     955               0 :                                                 s = S_NULL;
     956               0 :                                                 s_len = S_NULL_LEN;
     957                 :                                         }
     958          162542 :                                         pad_char = ' ';
     959          162542 :                                         break;
     960                 : 
     961                 :                                 
     962                 :                                 case 'f':
     963                 :                                 case 'F':
     964                 :                                 case 'e':
     965                 :                                 case 'E':
     966          100115 :                                         switch(modifier) {
     967                 :                                                 case LM_LONG_DOUBLE:
     968               0 :                                                         fp_num = (double) va_arg(ap, long double);
     969               0 :                                                         break;
     970                 :                                                 case LM_STD:
     971          100115 :                                                         fp_num = va_arg(ap, double);
     972          100115 :                                                         break;
     973                 :                                                 default:
     974               0 :                                                         goto fmt_error;
     975                 :                                         }
     976                 : 
     977          100115 :                                         if (zend_isnan(fp_num)) {
     978               0 :                                                 s = "NAN";
     979               0 :                                                 s_len = 3;
     980          100115 :                                         } else if (zend_isinf(fp_num)) {
     981               0 :                                                 s = "INF";
     982               0 :                                                 s_len = 3;
     983                 :                                         } else {
     984                 : #ifdef HAVE_LOCALE_H
     985          100115 :                                                 if (!lconv) {
     986          100115 :                                                         lconv = localeconv();
     987                 :                                                 }
     988                 : #endif
     989          100115 :                                                 s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
     990                 :                                                  (adjust_precision == NO) ? FLOAT_DIGITS : precision,
     991                 :                                                  (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
     992                 :                                                                         &is_negative, &num_buf[1], &s_len);
     993          100115 :                                                 if (is_negative)
     994               0 :                                                         prefix_char = '-';
     995          100115 :                                                 else if (print_sign)
     996               0 :                                                         prefix_char = '+';
     997          100115 :                                                 else if (print_blank)
     998               0 :                                                         prefix_char = ' ';
     999                 :                                         }
    1000          100115 :                                         break;
    1001                 : 
    1002                 : 
    1003                 :                                 case 'g':
    1004                 :                                 case 'k':
    1005                 :                                 case 'G':
    1006                 :                                 case 'H':
    1007               2 :                                         switch(modifier) {
    1008                 :                                                 case LM_LONG_DOUBLE:
    1009               0 :                                                         fp_num = (double) va_arg(ap, long double);
    1010               0 :                                                         break;
    1011                 :                                                 case LM_STD:
    1012               2 :                                                         fp_num = va_arg(ap, double);
    1013               2 :                                                         break;
    1014                 :                                                 default:
    1015               0 :                                                         goto fmt_error;
    1016                 :                                         }
    1017                 : 
    1018               2 :                                         if (zend_isnan(fp_num)) {
    1019               0 :                                                 s = "NAN";
    1020               0 :                                                 s_len = 3;
    1021               0 :                                                 break;
    1022               2 :                                         } else if (zend_isinf(fp_num)) {
    1023               0 :                                                 if (fp_num > 0) {
    1024               0 :                                                         s = "INF";
    1025               0 :                                                         s_len = 3;
    1026                 :                                                 } else {
    1027               0 :                                                         s = "-INF";
    1028               0 :                                                         s_len = 4;
    1029                 :                                                 }
    1030               0 :                                                 break;
    1031                 :                                         }
    1032                 : 
    1033               2 :                                         if (adjust_precision == NO) {
    1034               0 :                                                 precision = FLOAT_DIGITS;
    1035               2 :                                         } else if (precision == 0) {
    1036               0 :                                                 precision = 1;
    1037                 :                                         }
    1038                 :                                         /*
    1039                 :                                          * * We use &num_buf[ 1 ], so that we have room for the sign
    1040                 :                                          */
    1041                 : #ifdef HAVE_LOCALE_H
    1042               2 :                                         if (!lconv) {
    1043               2 :                                                 lconv = localeconv();
    1044                 :                                         }
    1045                 : #endif
    1046               2 :                                         s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
    1047               2 :                                         if (*s == '-') {
    1048               0 :                                                 prefix_char = *s++;
    1049               2 :                                         } else if (print_sign) {
    1050               0 :                                                 prefix_char = '+';
    1051               2 :                                         } else if (print_blank) {
    1052               0 :                                                 prefix_char = ' ';
    1053                 :                                         }
    1054                 : 
    1055               2 :                                         s_len = strlen(s);
    1056                 : 
    1057               2 :                                         if (alternate_form && (q = strchr(s, '.')) == NULL) {
    1058               0 :                                                 s[s_len++] = '.';
    1059                 :                                         }
    1060               2 :                                         break;
    1061                 : 
    1062                 : 
    1063                 :                                 case 'c':
    1064            1134 :                                         char_buf[0] = (char) (va_arg(ap, int));
    1065            1134 :                                         s = &char_buf[0];
    1066            1134 :                                         s_len = 1;
    1067            1134 :                                         pad_char = ' ';
    1068            1134 :                                         break;
    1069                 : 
    1070                 : 
    1071                 :                                 case '%':
    1072              45 :                                         char_buf[0] = '%';
    1073              45 :                                         s = &char_buf[0];
    1074              45 :                                         s_len = 1;
    1075              45 :                                         pad_char = ' ';
    1076              45 :                                         break;
    1077                 : 
    1078                 : 
    1079                 :                                 case 'n':
    1080               0 :                                         *(va_arg(ap, int *)) = cc;
    1081               0 :                                         goto skip_output;
    1082                 : 
    1083                 :                                         /*
    1084                 :                                          * Always extract the argument as a "char *" pointer. We 
    1085                 :                                          * should be using "void *" but there are still machines 
    1086                 :                                          * that don't understand it.
    1087                 :                                          * If the pointer size is equal to the size of an unsigned
    1088                 :                                          * integer we convert the pointer to a hex number, otherwise 
    1089                 :                                          * we print "%p" to indicate that we don't handle "%p".
    1090                 :                                          */
    1091                 :                                 case 'p':
    1092                 :                                         if (sizeof(char *) <= sizeof(u_wide_int)) {
    1093               0 :                                                 ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
    1094               0 :                                                 s = ap_php_conv_p2(ui_num, 4, 'x', 
    1095                 :                                                                 &num_buf[NUM_BUF_SIZE], &s_len);
    1096               0 :                                                 if (ui_num != 0) {
    1097               0 :                                                         *--s = 'x';
    1098               0 :                                                         *--s = '0';
    1099               0 :                                                         s_len += 2;
    1100                 :                                                 }
    1101                 :                                         } else {
    1102                 :                                                 s = "%p";
    1103                 :                                                 s_len = 2;
    1104                 :                                         }
    1105               0 :                                         pad_char = ' ';
    1106               0 :                                         break;
    1107                 : 
    1108                 : 
    1109                 :                                 case NUL:
    1110                 :                                         /*
    1111                 :                                          * The last character of the format string was %.
    1112                 :                                          * We ignore it.
    1113                 :                                          */
    1114               0 :                                         continue;
    1115                 : 
    1116                 : 
    1117               0 : fmt_error:
    1118               0 :                                 php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
    1119                 :                                         /*
    1120                 :                                          * The default case is for unrecognized %'s.
    1121                 :                                          * We print %<char> to help the user identify what
    1122                 :                                          * option is not understood.
    1123                 :                                          * This is also useful in case the user wants to pass
    1124                 :                                          * the output of format_converter to another function
    1125                 :                                          * that understands some other %<char> (like syslog).
    1126                 :                                          * Note that we can't point s inside fmt because the
    1127                 :                                          * unknown <char> could be preceded by width etc.
    1128                 :                                          */
    1129                 :                                 default:
    1130               0 :                                         char_buf[0] = '%';
    1131               0 :                                         char_buf[1] = *fmt;
    1132               0 :                                         s = char_buf;
    1133               0 :                                         s_len = 2;
    1134               0 :                                         pad_char = ' ';
    1135                 :                                         break;
    1136                 :                         }
    1137                 : 
    1138          740480 :                         if (prefix_char != NUL) {
    1139              24 :                                 *--s = prefix_char;
    1140              24 :                                 s_len++;
    1141                 :                         }
    1142          740480 :                         if (adjust_width && adjust == RIGHT && min_width > s_len) {
    1143            7516 :                                 if (pad_char == '0' && prefix_char != NUL) {
    1144               0 :                                         INS_CHAR(*s, sp, bep, cc)
    1145               0 :                                                 s++;
    1146               0 :                                         s_len--;
    1147               0 :                                         min_width--;
    1148                 :                                 }
    1149            7548 :                                 PAD(min_width, s_len, pad_char);
    1150                 :                         }
    1151                 :                         /*
    1152                 :                          * Print the string s. 
    1153                 :                          */
    1154         5465521 :                         for (i = s_len; i != 0; i--) {
    1155         4725041 :                                 INS_CHAR(*s, sp, bep, cc);
    1156         4725041 :                                 s++;
    1157                 :                         }
    1158                 : 
    1159          740480 :                         if (adjust_width && adjust == LEFT && min_width > s_len)
    1160            1304 :                                 PAD(min_width, s_len, pad_char);
    1161                 :                 }
    1162          940927 : skip_output:
    1163          940927 :                 fmt++;
    1164                 :         }
    1165          557740 :         odp->nextb = sp;
    1166          557740 :         return (cc);
    1167                 : }
    1168                 : /* }}} */
    1169                 : 
    1170                 : /*
    1171                 :  * This is the general purpose conversion function.
    1172                 :  */
    1173                 : static void strx_printv(int *ccp, char *buf, size_t len, const char *format, va_list ap) /* {{{ */
    1174          557740 : {
    1175                 :         buffy od;
    1176                 :         int cc;
    1177                 : 
    1178                 :         /*
    1179                 :          * First initialize the descriptor
    1180                 :          * Notice that if no length is given, we initialize buf_end to the
    1181                 :          * highest possible address.
    1182                 :          */
    1183          557740 :         if (len == 0) {
    1184               0 :                 od.buf_end = (char *) ~0;
    1185               0 :                 od.nextb   = (char *) ~0;
    1186                 :         } else {
    1187          557740 :                 od.buf_end = &buf[len-1];
    1188          557740 :                 od.nextb   = buf;
    1189                 :         }
    1190                 : 
    1191                 :         /*
    1192                 :          * Do the conversion
    1193                 :          */
    1194          557740 :         cc = format_converter(&od, format, ap);
    1195          557740 :         if (len != 0 && od.nextb <= od.buf_end) {
    1196          557740 :                 *(od.nextb) = '\0';
    1197                 :         }
    1198          557740 :         if (ccp) {
    1199          557740 :                 *ccp = cc;
    1200                 :         }
    1201          557740 : }
    1202                 : /* }}} */
    1203                 : 
    1204                 : PHPAPI int ap_php_slprintf(char *buf, size_t len, const char *format,...) /* {{{ */
    1205          379219 : {
    1206                 :         int cc;
    1207                 :         va_list ap;
    1208                 : 
    1209          379219 :         va_start(ap, format);
    1210          379219 :         strx_printv(&cc, buf, len, format, ap);
    1211          379219 :         va_end(ap);
    1212          379219 :         if (cc >= len) {
    1213               0 :                 cc = len -1;
    1214               0 :                 buf[cc] = '\0';
    1215                 :         }
    1216          379219 :         return cc;
    1217                 : }
    1218                 : /* }}} */
    1219                 : 
    1220                 : PHPAPI int ap_php_vslprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
    1221              11 : {
    1222                 :         int cc;
    1223                 : 
    1224              11 :         strx_printv(&cc, buf, len, format, ap);
    1225              11 :         if (cc >= len) {
    1226               0 :                 cc = len -1;
    1227               0 :                 buf[cc] = '\0';
    1228                 :         }
    1229              11 :         return cc;
    1230                 : }
    1231                 : /* }}} */
    1232                 : 
    1233                 : PHPAPI int ap_php_snprintf(char *buf, size_t len, const char *format,...) /* {{{ */
    1234          178510 : {
    1235                 :         int cc;
    1236                 :         va_list ap;
    1237                 : 
    1238          178510 :         va_start(ap, format);
    1239          178510 :         strx_printv(&cc, buf, len, format, ap);
    1240          178510 :         va_end(ap);
    1241          178510 :         return (cc);
    1242                 : }
    1243                 : /* }}} */
    1244                 : 
    1245                 : PHPAPI int ap_php_vsnprintf(char *buf, size_t len, const char *format, va_list ap) /* {{{ */
    1246               0 : {
    1247                 :         int cc;
    1248                 : 
    1249               0 :         strx_printv(&cc, buf, len, format, ap);
    1250               0 :         return (cc);
    1251                 : }
    1252                 : /* }}} */
    1253                 : 
    1254                 : /*
    1255                 :  * Local variables:
    1256                 :  * tab-width: 4
    1257                 :  * c-basic-offset: 4
    1258                 :  * End:
    1259                 :  * vim600: sw=4 ts=4 fdm=marker
    1260                 :  * vim<600: sw=4 ts=4
    1261                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:28 +0000 (5 days ago)

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