cvs: php-src(PHP_4_3) /main snprintf.c snprintf.h spprintf.c

From: Date: Fri, 08 Apr 2005 05:44:54 +0000
Subject: cvs: php-src(PHP_4_3) /main snprintf.c snprintf.h spprintf.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-31306@lists.php.net to get a copy of this message
sniper Fri Apr 8 01:44:54 2005 EDT Modified files: (Branch: PHP_4_3) /php-src/main snprintf.c snprintf.h spprintf.c Log: MFH and Fixes bug #32482 (ap_php_snprintf broken)

http://cvs.php.net/diff.php/php-src/main/snprintf.c?r1=1.17.4.11&r2=1.17.4.12&ty=u Index: php-src/main/snprintf.c diff -u php-src/main/snprintf.c:1.17.4.11 php-src/main/snprintf.c:1.17.4.12 --- php-src/main/snprintf.c:1.17.4.11 Mon Nov 15 18:27:26 2004 +++ php-src/main/snprintf.c Fri Apr 8 01:44:53 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: snprintf.c,v 1.17.4.11 2004/11/15 23:27:26 fmk Exp $ */ +/* $Id: snprintf.c,v 1.17.4.12 2005/04/08 05:44:53 sniper Exp $ */ /* ==================================================================== * Copyright (c) 1995-1998 The Apache Group. All rights reserved. @@ -75,6 +75,7 @@ #include "php.h" +#include <stddef.h> #include <stdio.h> #include <ctype.h> #include <sys/types.h> @@ -82,6 +83,9 @@ #include <string.h> #include <stdlib.h> #include <math.h> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif #define FALSE 0 #define TRUE 1 @@ -575,7 +579,7 @@ /* * Flag variables */ - boolean_e is_long; + length_modifier_e modifier; boolean_e alternate_form; boolean_e print_sign; boolean_e print_blank; @@ -666,11 +670,51 @@ /* * Modifier check */ - if (*fmt == 'l') { - is_long = YES; - fmt++; - } else - is_long = NO; + switch (*fmt) { + case 'L': + fmt++; + modifier = LM_LONG_DOUBLE; + 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. @@ -685,10 +729,34 @@ */ switch (*fmt) { case 'u': - if (is_long) - i_num = va_arg(ap, u_wide_int); - else - i_num = (wide_int) va_arg(ap, unsigned int); + 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. @@ -699,11 +767,39 @@ * Get the arg if we haven't already. */ if ((*fmt) != 'u') { - if (is_long) - i_num = va_arg(ap, wide_int); - else - i_num = (wide_int) va_arg(ap, int); - }; + 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); @@ -720,10 +816,34 @@ case 'o': - if (is_long) - ui_num = va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); + 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); @@ -736,10 +856,34 @@ case 'x': case 'X': - if (is_long) - ui_num = (u_wide_int) va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); + 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); @@ -768,7 +912,16 @@ case 'f': case 'e': case 'E': - fp_num = va_arg(ap, double); + 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"; @@ -792,22 +945,31 @@ case 'g': case 'G': - fp_num = va_arg(ap, double); + 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; - } + 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; @@ -816,7 +978,8 @@ /* * * We use &num_buf[ 1 ], so that we have room for the sign */ - s = ap_php_gcvt(fp_num, precision, &num_buf[1], alternate_form); + s = ap_php_gcvt(fp_num, precision, &num_buf[1], + alternate_form); if (*s == '-') prefix_char = *s++; else if (print_sign) @@ -862,12 +1025,16 @@ * we print "%p" to indicate that we don't handle "%p". */ case 'p': - ui_num = (u_wide_int) va_arg(ap, char *); - - if (sizeof(char *) <= sizeof(u_wide_int)) - s = ap_php_conv_p2(ui_num, 4, 'x', - &num_buf[NUM_BUF_SIZE], &s_len); - else { + 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; } @@ -883,6 +1050,8 @@ 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 http://cvs.php.net/diff.php/php-src/main/snprintf.h?r1=1.18.4.6&r2=1.18.4.7&ty=u Index: php-src/main/snprintf.h diff -u php-src/main/snprintf.h:1.18.4.6 php-src/main/snprintf.h:1.18.4.7 --- php-src/main/snprintf.h:1.18.4.6 Thu Mar 31 02:40:30 2005 +++ php-src/main/snprintf.h Fri Apr 8 01:44:53 2005 @@ -12,9 +12,11 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Stig Sæther Bakken <ssb@fast.no> | + | Author: Stig Sæther Bakken <ssb@php.net> | +----------------------------------------------------------------------+ - */ +*/ + +/* $Id: snprintf.h,v 1.18.4.7 2005/04/08 05:44:53 sniper Exp $ */ /* @@ -87,12 +89,36 @@ NO = 0, YES = 1 } boolean_e; +typedef enum { + LM_STD = 0, +#if SIZEOF_INTMAX_T + LM_INTMAX_T, +#endif +#if SIZEOF_PTRDIFF_T + LM_PTRDIFF_T, +#endif +#if SIZEOF_LONG_LONG + LM_LONG_LONG, +#endif + LM_SIZE_T, + LM_LONG, + LM_LONG_DOUBLE +} length_modifier_e; + extern char * ap_php_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf); extern char * ap_php_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf); extern char * ap_php_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf); extern char * ap_php_gcvt(double number, int ndigit, char *buf, boolean_e altform); -#define WIDE_INT long +#if SIZEOF_LONG_LONG_INT +# define WIDE_INT long long int +#elif SIZEOF_LONG_LONG +# define WIDE_INT long long +#elif _WIN64 +# define WIDE_INT __int64 +#else +# define WIDE_INT long +#endif typedef WIDE_INT wide_int; typedef unsigned WIDE_INT u_wide_int; http://cvs.php.net/diff.php/php-src/main/spprintf.c?r1=1.10.4.2&r2=1.10.4.3&ty=u Index: php-src/main/spprintf.c diff -u php-src/main/spprintf.c:1.10.4.2 php-src/main/spprintf.c:1.10.4.3 --- php-src/main/spprintf.c:1.10.4.2 Sun Sep 28 21:09:36 2003 +++ php-src/main/spprintf.c Fri Apr 8 01:44:53 2005 @@ -14,7 +14,9 @@ +----------------------------------------------------------------------+ | Author: Marcus Boerger <helly@php.net> | +----------------------------------------------------------------------+ - */ +*/ + +/* $Id: spprintf.c,v 1.10.4.3 2005/04/08 05:44:53 sniper Exp $ */ /* This is the spprintf implementation. * It has emerged from apache snprintf. See original header: @@ -76,6 +78,19 @@ */ #include "php.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> +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + #include "snprintf.h" #define FALSE 0 @@ -89,6 +104,8 @@ #define FLOAT_DIGITS 6 #define EXPONENT_LENGTH 10 +#include "ext/standard/php_smart_str.h" + /* * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions * @@ -96,113 +113,48 @@ */ #define NUM_BUF_SIZE 512 - -/* - * Size for realloc operations - */ -#define SPPRINTF_BLOCK_SIZE 128 - -/* - * Descriptor for buffer area - */ -struct xbuf_area { - char *buf; /* pointer to buffer */ - size_t size; - size_t max_len; - char *buf_end; /* pointer to buffer end or ~0 */ - char *nextb; /* pointer to next byte to read/write */ -}; - -typedef struct xbuf_area xbuffy; - -/* Resize xbuf so that add bytes can be added. Reallocation is done - * in defined block size to minimize calls to realloc. - */ -static void xbuf_resize(xbuffy *xbuf, size_t add) -{ - char *buf; - size_t size, offset; - - if (xbuf->buf) { - offset = xbuf->nextb - xbuf->buf; - if (offset+add < xbuf->size) { - return; /* do not change size if not necessary */ - } - } else { - offset = 0; - } - if (add<SPPRINTF_BLOCK_SIZE) { - size = xbuf->size + SPPRINTF_BLOCK_SIZE; - } else { - size = xbuf->size + add; - } - if (xbuf->max_len && size > xbuf->max_len) { - size = xbuf->max_len; - } - - buf = erealloc(xbuf->buf, size+1); /* alloc space for NUL */ - - if (buf) { - xbuf->buf = buf; - xbuf->buf_end = xbuf->max_len ? &buf[size] : (char *) ~0; - xbuf->nextb = buf+offset; - xbuf->size = size; - } -} - -/* Initialise xbuffy with size spprintf_BLOCK_SIZE - */ -static char * xbuf_init(xbuffy *xbuf, size_t max_len) -{ - xbuf->buf = NULL; - xbuf->size = 0; - xbuf->max_len = max_len; - xbuf_resize(xbuf, 0); /* NOT max_len */ - return xbuf->buf; -} - /* - * The INS_CHAR macro inserts a character in the buffer and writes - * the buffer back to disk if necessary - * It uses the char pointers sp and bep: - * sp points to the next available character in the buffer - * bep points to the end-of-buffer+1 - * While using this macro, note that the nextb pointer is NOT updated. + * The INS_CHAR macro inserts a character in the buffer. * - * NOTE: Evaluation of the c argument should not have any side-effects + * NOTE: Evaluation of the ch argument should not have any side-effects */ -#define INS_CHAR_NR(xbuf, ch, cc) \ - if (xbuf->nextb < xbuf->buf_end) { \ - *(xbuf->nextb++) = ch; \ - cc++; \ - } +#define INS_CHAR_NR(xbuf, ch) do { \ + smart_str_appendc(xbuf, ch); \ +} while (0) -#define INS_CHAR(xbuf, ch, cc) \ - xbuf_resize(xbuf, 1); \ - INS_CHAR_NR(xbuf, ch, cc) +#define INS_STRING(xbuf, s, slen) do { \ + smart_str_appendl(xbuf, s, slen); \ +} while (0) + +#define INS_CHAR(xbuf, ch) \ + INS_CHAR_NR(xbuf, ch) /* * Macro that does padding. The padding is done by printing * the character ch. */ -#define PAD(xbuf, width, len, ch) \ - if (width > len) { \ - xbuf_resize(xbuf, width-len); \ - do { \ - INS_CHAR_NR(xbuf, ch, cc); \ - width--; \ - } \ - while (width > len);\ - } +#define PAD(xbuf, count, ch) do { \ + if ((count) > 0) { \ + size_t newlen; \ + smart_str_alloc(xbuf, (count), 0); \ + memset(xbuf->c + xbuf->len, ch, (count)); \ + xbuf->len += (count); \ + } \ +} while (0) #define NUM(c) (c - '0') -#define STR_TO_DEC(str, num) \ - num = NUM(*str++); \ - while (isdigit((int)*str)) { \ - num *= 10; \ - num += NUM(*str++); \ - } +#define STR_TO_DEC(str, num) do { \ + num = NUM(*str++); \ + while (isdigit((int)*str)) { \ + num *= 10; \ + num += NUM(*str++); \ + if (num >= INT_MAX / 10) { \ + while (isdigit((int)*str++)); \ + break; \ + } \ + } \ +} while (0) /* * This macro does zero padding so that the precision @@ -210,33 +162,21 @@ * adding '0's to the left of the string that is going * to be printed. */ -#define FIX_PRECISION(adjust, precision, s, s_len) \ - if (adjust) \ - while (s_len < precision) { \ - *--s = '0'; \ - s_len++; \ - } - -/* - * Prefix the character ch to the string str - * Increase length - * Set the has_prefix flag - */ -#define PREFIX(str, length, ch) \ - *--str = ch; \ - length++; \ - has_prefix = YES +#define FIX_PRECISION(adjust, precision, s, s_len) do { \ + if (adjust) \ + while (s_len < precision) { \ + *--s = '0'; \ + s_len++; \ + } \ +} while (0) /* * Do format conversion placing the output in buffer */ -static int xbuf_format_converter(register xbuffy * xbuf, const char *fmt, va_list ap) +static void xbuf_format_converter(smart_str *xbuf, const char *fmt, va_list ap) { - register int cc = 0; - register int i; - register char *s = NULL; char *q; int s_len; @@ -259,7 +199,7 @@ /* * Flag variables */ - boolean_e is_long; + length_modifier_e modifier; boolean_e alternate_form; boolean_e print_sign; boolean_e print_blank; @@ -269,7 +209,7 @@ while (*fmt) { if (*fmt != '%') { - INS_CHAR(xbuf, *fmt, cc); + INS_CHAR(xbuf, *fmt); } else { /* * Default variable settings @@ -347,11 +287,51 @@ /* * Modifier check */ - if (*fmt == 'l') { - is_long = YES; - fmt++; - } else - is_long = NO; + switch (*fmt) { + case 'L': + fmt++; + modifier = LM_LONG_DOUBLE; + 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. @@ -366,10 +346,34 @@ */ switch (*fmt) { case 'u': - if (is_long) - i_num = va_arg(ap, u_wide_int); - else - i_num = (wide_int) va_arg(ap, unsigned int); + 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. @@ -380,11 +384,39 @@ * Get the arg if we haven't already. */ if ((*fmt) != 'u') { - if (is_long) - i_num = va_arg(ap, wide_int); - else - i_num = (wide_int) va_arg(ap, int); - }; + 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); @@ -401,10 +433,34 @@ case 'o': - if (is_long) - ui_num = va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); + 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); @@ -417,10 +473,34 @@ case 'x': case 'X': - if (is_long) - ui_num = (u_wide_int) va_arg(ap, u_wide_int); - else - ui_num = (u_wide_int) va_arg(ap, unsigned int); + 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); @@ -449,7 +529,16 @@ case 'f': case 'e': case 'E': - fp_num = va_arg(ap, double); + 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"; @@ -473,22 +562,31 @@ case 'g': case 'G': - fp_num = va_arg(ap, double); + 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; - } + 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; @@ -497,7 +595,8 @@ /* * * We use &num_buf[ 1 ], so that we have room for the sign */ - s = ap_php_gcvt(fp_num, precision, &num_buf[1], alternate_form); + s = ap_php_gcvt(fp_num, precision, &num_buf[1], + alternate_form); if (*s == '-') prefix_char = *s++; else if (print_sign) @@ -531,7 +630,7 @@ case 'n': - *(va_arg(ap, int *)) = cc; + *(va_arg(ap, int *)) = xbuf->len; break; /* @@ -543,11 +642,16 @@ * we print "%p" to indicate that we don't handle "%p". */ case 'p': - ui_num = (u_wide_int) va_arg(ap, char *); - - if (sizeof(char *) <= sizeof(u_wide_int)) - s = ap_php_conv_p2(ui_num, 4, 'x', &num_buf[NUM_BUF_SIZE], &s_len); - else { + 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; } @@ -563,6 +667,8 @@ 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 @@ -588,28 +694,24 @@ } if (adjust_width && adjust == RIGHT && min_width > s_len) { if (pad_char == '0' && prefix_char != NUL) { - INS_CHAR(xbuf, *s, cc) - s++; + INS_CHAR(xbuf, *s); + s++; s_len--; min_width--; } - PAD(xbuf, min_width, s_len, pad_char); + PAD(xbuf, min_width - s_len, pad_char); } /* * Print the string s. */ - xbuf_resize(xbuf, s_len); - for (i = s_len; i != 0; i--) { - INS_CHAR_NR(xbuf, *s, cc); - s++; - } + INS_STRING(xbuf, s, s_len); if (adjust_width && adjust == LEFT && min_width > s_len) - PAD(xbuf, min_width, s_len, pad_char); + PAD(xbuf, min_width - s_len, pad_char); } fmt++; } - return (cc); + return; } @@ -618,34 +720,18 @@ */ PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap) { - xbuffy xbuf; - int cc; + smart_str xbuf = {0}; - assert(pbuf != NULL); - /* - * First initialize the descriptor - * Notice that if no length is given, we initialize buf_end to the - * highest possible address. - */ - if (!xbuf_init(&xbuf, max_len)) { - if (pbuf) - *pbuf = NULL; - return 0; - } else { - /* - * Do the conversion - */ - cc = xbuf_format_converter(&xbuf, format, ap); - if (xbuf.nextb <= xbuf.buf_end) - *(xbuf.nextb) = '\0'; - else if (xbuf.size) - xbuf.buf[xbuf.size-1] = '\0'; - if (pbuf) - *pbuf = xbuf.buf; - else - efree(pbuf); - return cc; + xbuf_format_converter(&xbuf, format, ap); + + if (max_len && xbuf.len > max_len) { + xbuf.len = max_len; } + smart_str_0(&xbuf); + + *pbuf = xbuf.c; + + return xbuf.len; }
« previous php.cvs (#31306) next »