Back to index

php5  5.3.10
Classes | Defines | Typedefs | Functions
snprintf.c File Reference
#include "php.h"
#include <zend_strtod.h>
#include <stddef.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

Go to the source code of this file.

Classes

struct  buf_area

Defines

#define LCONV_DECIMAL_POINT   '.'
#define FALSE   0
#define TRUE   1
#define NUL   '\0'
#define INT_NULL   ((int *)0)
#define S_NULL   "(null)"
#define S_NULL_LEN   6
#define FLOAT_DIGITS   6
#define EXPONENT_LENGTH   10
#define NDIG   320
#define NUM_BUF_SIZE   2048
#define INS_CHAR(c, sp, bep, cc)
#define NUM(c)   ( c - '0' )
#define STR_TO_DEC(str, num)
#define FIX_PRECISION(adjust, precision, s, s_len)
#define PAD(width, len, ch)
#define PREFIX(str, length, ch)   *--str = ch ; length++ ; has_prefix = YES

Typedefs

typedef struct buf_area

Functions

static char * __cvt (double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
static char * php_ecvt (double value, int ndigit, int *decpt, int *sign)
static char * php_fcvt (double value, int ndigit, int *decpt, int *sign)
PHPAPI char * php_gcvt (double value, int ndigit, char dec_point, char exponent, char *buf)
char * ap_php_conv_10 (register wide_int num, register bool_int is_unsigned, register bool_int *is_negative, char *buf_end, register int *len)
PHPAPI char * php_conv_fp (register char format, register double num, boolean_e add_dp, int precision, char dec_point, bool_int *is_negative, char *buf, int *len)
char * ap_php_conv_p2 (register u_wide_int num, register int nbits, char format, char *buf_end, register int *len)
static int format_converter (register buffy *odp, const char *fmt, va_list ap)
static void strx_printv (int *ccp, char *buf, size_t len, const char *format, va_list ap)
PHPAPI int ap_php_slprintf (char *buf, size_t len, const char *format,...)
PHPAPI int ap_php_vslprintf (char *buf, size_t len, const char *format, va_list ap)
PHPAPI int ap_php_snprintf (char *buf, size_t len, const char *format,...)
PHPAPI int ap_php_vsnprintf (char *buf, size_t len, const char *format, va_list ap)
PHPAPI int ap_php_vasprintf (char **buf, const char *format, va_list ap)
PHPAPI int ap_php_asprintf (char **buf, const char *format,...)

Class Documentation

struct buf_area

Definition at line 510 of file snprintf.c.

Class Members
char * buf_end
char * nextb

Define Documentation

#define EXPONENT_LENGTH   10

Definition at line 298 of file snprintf.c.

#define FALSE   0

Definition at line 289 of file snprintf.c.

#define FIX_PRECISION (   adjust,
  precision,
  s,
  s_len 
)
Value:
if ( adjust )                             \
       while ( s_len < precision )               \
       {                                         \
           *--s = '0' ;                          \
           s_len++ ;                             \
       }

Definition at line 552 of file snprintf.c.

#define FLOAT_DIGITS   6

Definition at line 297 of file snprintf.c.

#define INS_CHAR (   c,
  sp,
  bep,
  cc 
)
Value:
{                            \
              if (sp < bep)            \
              {                        \
                     *sp++ = c;           \
              }                        \
              cc++;                    \
       }

Definition at line 527 of file snprintf.c.

#define INT_NULL   ((int *)0)

Definition at line 292 of file snprintf.c.

#define LCONV_DECIMAL_POINT   '.'

Definition at line 43 of file snprintf.c.

#define NDIG   320

Definition at line 362 of file snprintf.c.

#define NUL   '\0'

Definition at line 291 of file snprintf.c.

#define NUM (   c)    ( c - '0' )

Definition at line 536 of file snprintf.c.

#define NUM_BUF_SIZE   2048

Definition at line 504 of file snprintf.c.

#define PAD (   width,
  len,
  ch 
)
Value:
do            \
       {                                  \
           INS_CHAR( ch, sp, bep, cc ) ;  \
           width-- ;                      \
       }                                  \
       while ( width > len )

Definition at line 564 of file snprintf.c.

#define PREFIX (   str,
  length,
  ch 
)    *--str = ch ; length++ ; has_prefix = YES

Definition at line 576 of file snprintf.c.

#define S_NULL   "(null)"

Definition at line 294 of file snprintf.c.

#define S_NULL_LEN   6

Definition at line 295 of file snprintf.c.

#define STR_TO_DEC (   str,
  num 
)
Value:
num = NUM( *str++ ) ;              \
    while ( isdigit((int)*str ) )         \
    {                              \
       num *= 10 ;                 \
       num += NUM( *str++ ) ;             \
    }

Definition at line 538 of file snprintf.c.

#define TRUE   1

Definition at line 290 of file snprintf.c.


Typedef Documentation

typedef struct buf_area

Definition at line 515 of file snprintf.c.


Function Documentation

static char* __cvt ( double  value,
int  ndigit,
int decpt,
int sign,
int  fmode,
int  pad 
) [static]

Definition at line 66 of file snprintf.c.

{
       register char *s = NULL;
       char *p, *rve, c;
       size_t siz;

       if (ndigit < 0) {
              siz = -ndigit + 1;
       } else {
              siz = ndigit + 1;
       }

       /* __dtoa() doesn't allocate space for 0 so we do it by hand */
       if (value == 0.0) {
              *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
              *sign = 0;
              if ((rve = s = (char *)malloc(ndigit?siz:2)) == NULL) {
                     return(NULL);
              }
              *rve++ = '0';
              *rve = '\0';
              if (!ndigit) {
                     return(s);
              }
       } else {
              p = zend_dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
              if (*decpt == 9999) {
                     /* Infinity or Nan, convert to inf or nan like printf */
                     *decpt = 0;
                     c = *p;
                     zend_freedtoa(p);
                     return(c == 'I' ? "INF" : "NAN");
              }
              /* Make a local copy and adjust rve to be in terms of s */
              if (pad && fmode) {
                     siz += *decpt;
              }
              if ((s = (char *)malloc(siz+1)) == NULL) {
                     zend_freedtoa(p);
                     return(NULL);
              }
              (void) strlcpy(s, p, siz);
              rve = s + (rve - p);
              zend_freedtoa(p);
       }

       /* Add trailing zeros */
       if (pad) {
              siz -= rve - s;
              while (--siz) {
                     *rve++ = '0';
              }
              *rve = '\0';
       }

       return(s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI int ap_php_asprintf ( char **  buf,
const char *  format,
  ... 
)

Definition at line 1297 of file snprintf.c.

{
       int cc;
       va_list ap;

       va_start(ap, format);
       cc = vasprintf(buf, format, ap);
       va_end(ap);
       return cc;
}
char* ap_php_conv_10 ( register wide_int  num,
register bool_int  is_unsigned,
register bool_int is_negative,
char *  buf_end,
register int len 
)

Definition at line 314 of file snprintf.c.

{
       register char *p = buf_end;
       register u_wide_int magnitude;

       if (is_unsigned) {
              magnitude = (u_wide_int) num;
              *is_negative = FALSE;
       } else {
              *is_negative = (num < 0);

              /*
               * On a 2's complement machine, negating the most negative integer
               * results in a number that cannot be represented as a signed integer.
               * Here is what we do to obtain the number's magnitude:
               *      a. add 1 to the number
               *      b. negate it (becomes positive)
               *      c. convert it to unsigned
               *      d. add 1
               */
              if (*is_negative) {
                     wide_int t = num + 1;
                     magnitude = ((u_wide_int) - t) + 1;
              } else {
                     magnitude = (u_wide_int) num;
              }
       }

       /*
        * We use a do-while loop so that we write at least 1 digit
        */
       do {
              register u_wide_int new_magnitude = magnitude / 10;

              *--p = (char)(magnitude - new_magnitude * 10 + '0');
              magnitude = new_magnitude;
       }
       while (magnitude);

       *len = buf_end - p;
       return (p);
}

Here is the caller graph for this function:

char* ap_php_conv_p2 ( register u_wide_int  num,
register int  nbits,
char  format,
char *  buf_end,
register int len 
)

Definition at line 477 of file snprintf.c.

{
       register int mask = (1 << nbits) - 1;
       register char *p = buf_end;
       static char low_digits[] = "0123456789abcdef";
       static char upper_digits[] = "0123456789ABCDEF";
       register char *digits = (format == 'X') ? upper_digits : low_digits;

       do {
              *--p = digits[num & mask];
              num >>= nbits;
       }
       while (num);

       *len = buf_end - p;
       return (p);
}

Here is the caller graph for this function:

PHPAPI int ap_php_slprintf ( char *  buf,
size_t  len,
const char *  format,
  ... 
)

Definition at line 1223 of file snprintf.c.

{
       int cc;
       va_list ap;

       va_start(ap, format);
       strx_printv(&cc, buf, len, format, ap);
       va_end(ap);
       if (cc >= len) {
              cc = len -1;
              buf[cc] = '\0';
       }
       return cc;
}

Here is the call graph for this function:

PHPAPI int ap_php_snprintf ( char *  buf,
size_t  len,
const char *  format,
  ... 
)

Definition at line 1252 of file snprintf.c.

{
       int cc;
       va_list ap;

       va_start(ap, format);
       strx_printv(&cc, buf, len, format, ap);
       va_end(ap);
       return (cc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI int ap_php_vasprintf ( char **  buf,
const char *  format,
va_list  ap 
)

Definition at line 1273 of file snprintf.c.

{
       va_list ap2;
       int cc;

       va_copy(ap2, ap);
       cc = ap_php_vsnprintf(NULL, 0, format, ap2);
       va_end(ap2);

       *buf = NULL;

       if (cc >= 0) {
              if ((*buf = malloc(++cc)) != NULL) {
                     if ((cc = ap_php_vsnprintf(*buf, cc, format, ap)) < 0) {
                            free(*buf);
                            *buf = NULL;
                     }
              }
       }

       return cc;
}

Here is the call graph for this function:

PHPAPI int ap_php_vslprintf ( char *  buf,
size_t  len,
const char *  format,
va_list  ap 
)

Definition at line 1239 of file snprintf.c.

{
       int cc;

       strx_printv(&cc, buf, len, format, ap);
       if (cc >= len) {
              cc = len -1;
              buf[cc] = '\0';
       }
       return cc;
}

Here is the call graph for this function:

PHPAPI int ap_php_vsnprintf ( char *  buf,
size_t  len,
const char *  format,
va_list  ap 
)

Definition at line 1264 of file snprintf.c.

{
       int cc;

       strx_printv(&cc, buf, len, format, ap);
       return (cc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int format_converter ( register buffy *  odp,
const char *  fmt,
va_list  ap 
) [static]

Definition at line 582 of file snprintf.c.

{
       char *sp;
       char *bep;
       int cc = 0;
       int i;

       char *s = NULL;
       int s_len, free_zcopy;
       zval *zvp, zcopy;

       int min_width = 0;
       int precision = 0;
       enum {
              LEFT, RIGHT
       } adjust;
       char pad_char;
       char prefix_char;

       double fp_num;
       wide_int i_num = (wide_int) 0;
       u_wide_int ui_num;

       char num_buf[NUM_BUF_SIZE];
       char char_buf[2];                  /* for printing %% and %<unknown> */

#ifdef HAVE_LOCALE_H
       struct lconv *lconv = NULL;
#endif

       /*
        * Flag variables
        */
       length_modifier_e modifier;
       boolean_e alternate_form;
       boolean_e print_sign;
       boolean_e print_blank;
       boolean_e adjust_precision;
       boolean_e adjust_width;
       bool_int is_negative;

       sp = odp->nextb;
       bep = odp->buf_end;

       while (*fmt) {
              if (*fmt != '%') {
                     INS_CHAR(*fmt, sp, bep, cc);
              } else {
                     /*
                      * Default variable settings
                      */
                     adjust = RIGHT;
                     alternate_form = print_sign = print_blank = NO;
                     pad_char = ' ';
                     prefix_char = NUL;
                     free_zcopy = 0;

                     fmt++;

                     /*
                      * Try to avoid checking for flags, width or precision
                      */
                     if (isascii((int)*fmt) && !islower((int)*fmt)) {
                            /*
                             * Recognize flags: -, #, BLANK, +
                             */
                            for (;; fmt++) {
                                   if (*fmt == '-')
                                          adjust = LEFT;
                                   else if (*fmt == '+')
                                          print_sign = YES;
                                   else if (*fmt == '#')
                                          alternate_form = YES;
                                   else if (*fmt == ' ')
                                          print_blank = YES;
                                   else if (*fmt == '0')
                                          pad_char = '0';
                                   else
                                          break;
                            }

                            /*
                             * Check if a width was specified
                             */
                            if (isdigit((int)*fmt)) {
                                   STR_TO_DEC(fmt, min_width);
                                   adjust_width = YES;
                            } else if (*fmt == '*') {
                                   min_width = va_arg(ap, int);
                                   fmt++;
                                   adjust_width = YES;
                                   if (min_width < 0) {
                                          adjust = LEFT;
                                          min_width = -min_width;
                                   }
                            } else
                                   adjust_width = NO;

                            /*
                             * Check if a precision was specified
                             */
                            if (*fmt == '.') {
                                   adjust_precision = YES;
                                   fmt++;
                                   if (isdigit((int)*fmt)) {
                                          STR_TO_DEC(fmt, precision);
                                   } else if (*fmt == '*') {
                                          precision = va_arg(ap, int);
                                          fmt++;
                                          if (precision < 0)
                                                 precision = 0;
                                   } else
                                          precision = 0;
                                   
                                   if (precision > FORMAT_CONV_MAX_PRECISION) {
                                          precision = FORMAT_CONV_MAX_PRECISION;
                                   }
                            } else
                                   adjust_precision = NO;
                     } else
                            adjust_precision = adjust_width = NO;

                     /*
                      * Modifier check
                      */
                     switch (*fmt) {
                            case 'L':
                                   fmt++;
                                   modifier = LM_LONG_DOUBLE;
                                   break;
                            case 'I':
                                   fmt++;
#if SIZEOF_LONG_LONG
                                   if (*fmt == '6' && *(fmt+1) == '4') {
                                          fmt += 2;
                                          modifier = LM_LONG_LONG;
                                   } else
#endif
                                          if (*fmt == '3' && *(fmt+1) == '2') {
                                                 fmt += 2;
                                                 modifier = LM_LONG;
                                          } else {
#ifdef _WIN64
                                                 modifier = LM_LONG_LONG;
#else
                                                 modifier = LM_LONG;
#endif
                                          }
                                   break;
                            case 'l':
                                   fmt++;
#if SIZEOF_LONG_LONG
                                   if (*fmt == 'l') {
                                          fmt++;
                                          modifier = LM_LONG_LONG;
                                   } else
#endif
                                          modifier = LM_LONG;
                                   break;
                            case 'z':
                                   fmt++;
                                   modifier = LM_SIZE_T;
                                   break;
                            case 'j':
                                   fmt++;
#if SIZEOF_INTMAX_T
                                   modifier = LM_INTMAX_T;
#else
                                   modifier = LM_SIZE_T;
#endif
                                   break;
                            case 't':
                                   fmt++;
#if SIZEOF_PTRDIFF_T
                                   modifier = LM_PTRDIFF_T;
#else
                                   modifier = LM_SIZE_T;
#endif
                                   break;
                            case 'h':
                                   fmt++;
                                   if (*fmt == 'h') {
                                          fmt++;
                                   }
                                   /* these are promoted to int, so no break */
                            default:
                                   modifier = LM_STD;
                                   break;
                     }

                     /*
                      * Argument extraction and printing.
                      * First we determine the argument type.
                      * Then, we convert the argument to a string.
                      * On exit from the switch, s points to the string that
                      * must be printed, s_len has the length of the string
                      * The precision requirements, if any, are reflected in s_len.
                      *
                      * NOTE: pad_char may be set to '0' because of the 0 flag.
                      *   It is reset to ' ' by non-numeric formats
                      */
                     switch (*fmt) {
                            case 'Z':
                                   zvp = (zval*) va_arg(ap, zval*);
                                   zend_make_printable_zval(zvp, &zcopy, &free_zcopy);
                                   if (free_zcopy) {
                                          zvp = &zcopy;
                                   }
                                   s_len = Z_STRLEN_P(zvp);
                                   s = Z_STRVAL_P(zvp);
                                   if (adjust_precision && precision < s_len) {
                                          s_len = precision;
                                   }
                                   break;
                            case 'u':
                                   switch(modifier) {
                                          default:
                                                 i_num = (wide_int) va_arg(ap, unsigned int);
                                                 break;
                                          case LM_LONG_DOUBLE:
                                                 goto fmt_error;
                                          case LM_LONG:
                                                 i_num = (wide_int) va_arg(ap, unsigned long int);
                                                 break;
                                          case LM_SIZE_T:
                                                 i_num = (wide_int) va_arg(ap, size_t);
                                                 break;
#if SIZEOF_LONG_LONG
                                          case LM_LONG_LONG:
                                                 i_num = (wide_int) va_arg(ap, u_wide_int);
                                                 break;
#endif
#if SIZEOF_INTMAX_T
                                          case LM_INTMAX_T:
                                                 i_num = (wide_int) va_arg(ap, uintmax_t);
                                                 break;
#endif
#if SIZEOF_PTRDIFF_T
                                          case LM_PTRDIFF_T:
                                                 i_num = (wide_int) va_arg(ap, ptrdiff_t);
                                                 break;
#endif
                                   }
                                   /*
                                    * The rest also applies to other integer formats, so fall
                                    * into that case.
                                    */
                            case 'd':
                            case 'i':
                                   /*
                                    * Get the arg if we haven't already.
                                    */
                                   if ((*fmt) != 'u') {
                                          switch(modifier) {
                                                 default:
                                                        i_num = (wide_int) va_arg(ap, int);
                                                        break;
                                                 case LM_LONG_DOUBLE:
                                                        goto fmt_error;
                                                 case LM_LONG:
                                                        i_num = (wide_int) va_arg(ap, long int);
                                                        break;
                                                 case LM_SIZE_T:
#if SIZEOF_SSIZE_T
                                                        i_num = (wide_int) va_arg(ap, ssize_t);
#else
                                                        i_num = (wide_int) va_arg(ap, size_t);
#endif
                                                        break;
#if SIZEOF_LONG_LONG
                                                 case LM_LONG_LONG:
                                                        i_num = (wide_int) va_arg(ap, wide_int);
                                                        break;
#endif
#if SIZEOF_INTMAX_T
                                                 case LM_INTMAX_T:
                                                        i_num = (wide_int) va_arg(ap, intmax_t);
                                                        break;
#endif
#if SIZEOF_PTRDIFF_T
                                                 case LM_PTRDIFF_T:
                                                        i_num = (wide_int) va_arg(ap, ptrdiff_t);
                                                        break;
#endif
                                          }
                                   }
                                   s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative,
                                                        &num_buf[NUM_BUF_SIZE], &s_len);
                                   FIX_PRECISION(adjust_precision, precision, s, s_len);

                                   if (*fmt != 'u') {
                                          if (is_negative) {
                                                 prefix_char = '-';
                                          } else if (print_sign) {
                                                 prefix_char = '+';
                                          } else if (print_blank) {
                                                 prefix_char = ' ';
                                          }
                                   }
                                   break;


                            case 'o':
                                   switch(modifier) {
                                          default:
                                                 ui_num = (u_wide_int) va_arg(ap, unsigned int);
                                                 break;
                                          case LM_LONG_DOUBLE:
                                                 goto fmt_error;
                                          case LM_LONG:
                                                 ui_num = (u_wide_int) va_arg(ap, unsigned long int);
                                                 break;
                                          case LM_SIZE_T:
                                                 ui_num = (u_wide_int) va_arg(ap, size_t);
                                                 break;
#if SIZEOF_LONG_LONG
                                          case LM_LONG_LONG:
                                                 ui_num = (u_wide_int) va_arg(ap, u_wide_int);
                                                 break;
#endif
#if SIZEOF_INTMAX_T
                                          case LM_INTMAX_T:
                                                 ui_num = (u_wide_int) va_arg(ap, uintmax_t);
                                                 break;
#endif
#if SIZEOF_PTRDIFF_T
                                          case LM_PTRDIFF_T:
                                                 ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
                                                 break;
#endif
                                   }
                                   s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
                                   FIX_PRECISION(adjust_precision, precision, s, s_len);
                                   if (alternate_form && *s != '0') {
                                          *--s = '0';
                                          s_len++;
                                   }
                                   break;


                            case 'x':
                            case 'X':
                                   switch(modifier) {
                                          default:
                                                 ui_num = (u_wide_int) va_arg(ap, unsigned int);
                                                 break;
                                          case LM_LONG_DOUBLE:
                                                 goto fmt_error;
                                          case LM_LONG:
                                                 ui_num = (u_wide_int) va_arg(ap, unsigned long int);
                                                 break;
                                          case LM_SIZE_T:
                                                 ui_num = (u_wide_int) va_arg(ap, size_t);
                                                 break;
#if SIZEOF_LONG_LONG
                                          case LM_LONG_LONG:
                                                 ui_num = (u_wide_int) va_arg(ap, u_wide_int);
                                                 break;
#endif
#if SIZEOF_INTMAX_T
                                          case LM_INTMAX_T:
                                                 ui_num = (u_wide_int) va_arg(ap, uintmax_t);
                                                 break;
#endif
#if SIZEOF_PTRDIFF_T
                                          case LM_PTRDIFF_T:
                                                 ui_num = (u_wide_int) va_arg(ap, ptrdiff_t);
                                                 break;
#endif
                                   }
                                   s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len);
                                   FIX_PRECISION(adjust_precision, precision, s, s_len);
                                   if (alternate_form && i_num != 0) {
                                          *--s = *fmt;  /* 'x' or 'X' */
                                          *--s = '0';
                                          s_len += 2;
                                   }
                                   break;


                            case 's':
                            case 'v':
                                   s = va_arg(ap, char *);
                                   if (s != NULL) {
                                          s_len = strlen(s);
                                          if (adjust_precision && precision < s_len) {
                                                 s_len = precision;
                                          }
                                   } else {
                                          s = S_NULL;
                                          s_len = S_NULL_LEN;
                                   }
                                   pad_char = ' ';
                                   break;


                            case 'f':
                            case 'F':
                            case 'e':
                            case 'E':
                                   switch(modifier) {
                                          case LM_LONG_DOUBLE:
                                                 fp_num = (double) va_arg(ap, long double);
                                                 break;
                                          case LM_STD:
                                                 fp_num = va_arg(ap, double);
                                                 break;
                                          default:
                                                 goto fmt_error;
                                   }

                                   if (zend_isnan(fp_num)) {
                                          s = "NAN";
                                          s_len = 3;
                                   } else if (zend_isinf(fp_num)) {
                                          s = "INF";
                                          s_len = 3;
                                   } else {
#ifdef HAVE_LOCALE_H
                                          if (!lconv) {
                                                 lconv = localeconv();
                                          }
#endif
                                          s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form,
                                           (adjust_precision == NO) ? FLOAT_DIGITS : precision,
                                           (*fmt == 'f')?LCONV_DECIMAL_POINT:'.',
                                                               &is_negative, &num_buf[1], &s_len);
                                          if (is_negative)
                                                 prefix_char = '-';
                                          else if (print_sign)
                                                 prefix_char = '+';
                                          else if (print_blank)
                                                 prefix_char = ' ';
                                   }
                                   break;


                            case 'g':
                            case 'k':
                            case 'G':
                            case 'H':
                                   switch(modifier) {
                                          case LM_LONG_DOUBLE:
                                                 fp_num = (double) va_arg(ap, long double);
                                                 break;
                                          case LM_STD:
                                                 fp_num = va_arg(ap, double);
                                                 break;
                                          default:
                                                 goto fmt_error;
                                   }

                                   if (zend_isnan(fp_num)) {
                                          s = "NAN";
                                          s_len = 3;
                                          break;
                                   } else if (zend_isinf(fp_num)) {
                                          if (fp_num > 0) {
                                                 s = "INF";
                                                 s_len = 3;
                                          } else {
                                                 s = "-INF";
                                                 s_len = 4;
                                          }
                                          break;
                                   }

                                   if (adjust_precision == NO) {
                                          precision = FLOAT_DIGITS;
                                   } else if (precision == 0) {
                                          precision = 1;
                                   }
                                   /*
                                    * * We use &num_buf[ 1 ], so that we have room for the sign
                                    */
#ifdef HAVE_LOCALE_H
                                   if (!lconv) {
                                          lconv = localeconv();
                                   }
#endif
                                   s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]);
                                   if (*s == '-') {
                                          prefix_char = *s++;
                                   } else if (print_sign) {
                                          prefix_char = '+';
                                   } else if (print_blank) {
                                          prefix_char = ' ';
                                   }

                                   s_len = strlen(s);

                                   if (alternate_form && (strchr(s, '.')) == NULL) {
                                          s[s_len++] = '.';
                                   }
                                   break;


                            case 'c':
                                   char_buf[0] = (char) (va_arg(ap, int));
                                   s = &char_buf[0];
                                   s_len = 1;
                                   pad_char = ' ';
                                   break;


                            case '%':
                                   char_buf[0] = '%';
                                   s = &char_buf[0];
                                   s_len = 1;
                                   pad_char = ' ';
                                   break;


                            case 'n':
                                   *(va_arg(ap, int *)) = cc;
                                   goto skip_output;

                                   /*
                                    * Always extract the argument as a "char *" pointer. We
                                    * should be using "void *" but there are still machines
                                    * that don't understand it.
                                    * If the pointer size is equal to the size of an unsigned
                                    * integer we convert the pointer to a hex number, otherwise
                                    * we print "%p" to indicate that we don't handle "%p".
                                    */
                            case 'p':
                                   if (sizeof(char *) <= sizeof(u_wide_int)) {
                                          ui_num = (u_wide_int)((size_t) va_arg(ap, char *));
                                          s = ap_php_conv_p2(ui_num, 4, 'x',
                                                        &num_buf[NUM_BUF_SIZE], &s_len);
                                          if (ui_num != 0) {
                                                 *--s = 'x';
                                                 *--s = '0';
                                                 s_len += 2;
                                          }
                                   } else {
                                          s = "%p";
                                          s_len = 2;
                                   }
                                   pad_char = ' ';
                                   break;


                            case NUL:
                                   /*
                                    * The last character of the format string was %.
                                    * We ignore it.
                                    */
                                   continue;


fmt_error:
                            php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt);
                                   /*
                                    * The default case is for unrecognized %'s.
                                    * We print %<char> to help the user identify what
                                    * option is not understood.
                                    * This is also useful in case the user wants to pass
                                    * the output of format_converter to another function
                                    * that understands some other %<char> (like syslog).
                                    * Note that we can't point s inside fmt because the
                                    * unknown <char> could be preceded by width etc.
                                    */
                            default:
                                   char_buf[0] = '%';
                                   char_buf[1] = *fmt;
                                   s = char_buf;
                                   s_len = 2;
                                   pad_char = ' ';
                                   break;
                     }

                     if (prefix_char != NUL) {
                            *--s = prefix_char;
                            s_len++;
                     }
                     if (adjust_width && adjust == RIGHT && min_width > s_len) {
                            if (pad_char == '0' && prefix_char != NUL) {
                                   INS_CHAR(*s, sp, bep, cc)
                                          s++;
                                   s_len--;
                                   min_width--;
                            }
                            PAD(min_width, s_len, pad_char);
                     }
                     /*
                      * Print the string s.
                      */
                     for (i = s_len; i != 0; i--) {
                            INS_CHAR(*s, sp, bep, cc);
                            s++;
                     }

                     if (adjust_width && adjust == LEFT && min_width > s_len)
                            PAD(min_width, s_len, pad_char);
                     if (free_zcopy) {
                            zval_dtor(&zcopy);
                     }
              }
skip_output:
              fmt++;
       }
       odp->nextb = sp;
       return (cc);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI char* php_conv_fp ( register char  format,
register double  num,
boolean_e  add_dp,
int  precision,
char  dec_point,
bool_int is_negative,
char *  buf,
int len 
)

Definition at line 372 of file snprintf.c.

{
       register char *s = buf;
       register char *p, *p_orig;
       int decimal_point;

       if (precision >= NDIG - 1) {
              precision = NDIG - 2;
       }

       if (format == 'F') {
              p_orig = p = php_fcvt(num, precision, &decimal_point, is_negative);
       } else {                                         /* either e or E format */
              p_orig = p = php_ecvt(num, precision + 1, &decimal_point, is_negative);
       }

       /*
        * Check for Infinity and NaN
        */
       if (isalpha((int)*p)) {
              *len = strlen(p);
              memcpy(buf, p, *len + 1);
              *is_negative = FALSE;
              free(p_orig);
              return (buf);
       }
       if (format == 'F') {
              if (decimal_point <= 0) {
                     if (num != 0 || precision > 0) {
                            *s++ = '0';
                            if (precision > 0) {
                                   *s++ = dec_point;
                                   while (decimal_point++ < 0) {
                                          *s++ = '0';
                                   }
                            } else if (add_dp) {
                                   *s++ = dec_point;
                            }
                     }
              } else {
                     int addz = decimal_point >= NDIG ? decimal_point - NDIG + 1 : 0;
                     decimal_point -= addz;
                     while (decimal_point-- > 0) {
                            *s++ = *p++;
                     }
                     while (addz-- > 0) {
                            *s++ = '0';
                     }
                     if (precision > 0 || add_dp) {
                            *s++ = dec_point;
                     }
              }
       } else {
              *s++ = *p++;
              if (precision > 0 || add_dp) {
                     *s++ = '.';
              }
       }

       /*
        * copy the rest of p, the NUL is NOT copied
        */
       while (*p) {
              *s++ = *p++;
       }

       if (format != 'F') {
              char temp[EXPONENT_LENGTH];        /* for exponent conversion */
              int t_len;
              bool_int exponent_is_negative;

              *s++ = format;                     /* either e or E */
              decimal_point--;
              if (decimal_point != 0) {
                     p = ap_php_conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, &temp[EXPONENT_LENGTH], &t_len);
                     *s++ = exponent_is_negative ? '-' : '+';

                     /*
                      * Make sure the exponent has at least 2 digits
                      */
                     while (t_len--) {
                            *s++ = *p++;
                     }
              } else {
                     *s++ = '+';
                     *s++ = '0';
              }
       }
       *len = s - buf;
       free(p_orig);
       return (buf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* php_ecvt ( double  value,
int  ndigit,
int decpt,
int sign 
) [inline, static]

Definition at line 125 of file snprintf.c.

{
       return(__cvt(value, ndigit, decpt, sign, 0, 1));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* php_fcvt ( double  value,
int  ndigit,
int decpt,
int sign 
) [inline, static]

Definition at line 131 of file snprintf.c.

{
    return(__cvt(value, ndigit, decpt, sign, 1, 1));
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI char* php_gcvt ( double  value,
int  ndigit,
char  dec_point,
char  exponent,
char *  buf 
)

Definition at line 137 of file snprintf.c.

{
       char *digits, *dst, *src;
       int i, decpt, sign;

       digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL);
       if (decpt == 9999) {
              /*
               * Infinity or NaN, convert to inf or nan with sign.
               * We assume the buffer is at least ndigit long.
               */
              snprintf(buf, ndigit + 1, "%s%s", (sign && *digits == 'I') ? "-" : "", *digits == 'I' ? "INF" : "NAN");
              zend_freedtoa(digits);
              return (buf);
       }

       dst = buf;
       if (sign) {
              *dst++ = '-';
       }

       if ((decpt >= 0 && decpt > ndigit) || decpt < -3) { /* use E-style */
              /* exponential format (e.g. 1.2345e+13) */
              if (--decpt < 0) {
                     sign = 1;
                     decpt = -decpt;
              } else {
                     sign = 0;
              }
              src = digits;
              *dst++ = *src++;
              *dst++ = dec_point;
              if (*src == '\0') {
                     *dst++ = '0';
              } else {
                     do {
                            *dst++ = *src++;
                     } while (*src != '\0');
              }
              *dst++ = exponent;
              if (sign) {
                     *dst++ = '-';
              } else {
                     *dst++ = '+';
              }
              if (decpt < 10) {
                     *dst++ = '0' + decpt;
                     *dst = '\0';
              } else {
                     /* XXX - optimize */
                     for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
                            continue;
                     dst[i + 1] = '\0';
                     while (decpt != 0) {
                            dst[i--] = '0' + decpt % 10;
                            decpt /= 10;
                     }
              }
       } else if (decpt < 0) {
              /* standard format 0. */
              *dst++ = '0';   /* zero before decimal point */
              *dst++ = dec_point;
              do {
                     *dst++ = '0';
              } while (++decpt < 0);
              src = digits;
              while (*src != '\0') {
                     *dst++ = *src++;
              }
              *dst = '\0';
       } else {
              /* standard format */
              for (i = 0, src = digits; i < decpt; i++) {
                     if (*src != '\0') {
                            *dst++ = *src++;
                     } else {
                            *dst++ = '0';
                     }
              }
              if (*src != '\0') {
                     if (src == digits) {
                            *dst++ = '0';   /* zero before decimal point */
                     }
                     *dst++ = dec_point;
                     for (i = decpt; digits[i] != '\0'; i++) {
                *dst++ = digits[i];
            }
        }
        *dst = '\0';
    }
    zend_freedtoa(digits);
    return (buf);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void strx_printv ( int ccp,
char *  buf,
size_t  len,
const char *  format,
va_list  ap 
) [static]

Definition at line 1192 of file snprintf.c.

{
       buffy od;
       int cc;

       /*
        * First initialize the descriptor
        * Notice that if no length is given, we initialize buf_end to the
        * highest possible address.
        */
       if (len == 0) {
              od.buf_end = (char *) ~0;
              od.nextb   = (char *) ~0;
       } else {
              od.buf_end = &buf[len-1];
              od.nextb   = buf;
       }

       /*
        * Do the conversion
        */
       cc = format_converter(&od, format, ap);
       if (len != 0 && od.nextb <= od.buf_end) {
              *(od.nextb) = '\0';
       }
       if (ccp) {
              *ccp = cc;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function: