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          |
    | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
-   | Author: Stig S�ther Bakken <[EMAIL PROTECTED]>                            
 |
+   | Author: Stig S�ther Bakken <[EMAIL PROTECTED]>                            
 |
    +----------------------------------------------------------------------+
- */
+*/
+
+/* $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 <[EMAIL PROTECTED]>                               |
    +----------------------------------------------------------------------+
- */
+*/
+
+/* $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;
 }
 
 

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to