X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fvasnprintf.c;h=74b30374cb446a842f7142cff9ae2a284abd850f;hb=a5c02266250d51d94c137f4fca8bec8e7654ff8c;hp=1a74a44b540a1edb68c4fb4ea1cc62c8b7a5f479;hpb=e302472df8a44f1e282de6307f25d796ad8a7415;p=gnulib.git diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 1a74a44b5..74b30374c 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -117,11 +117,6 @@ # include "fpucw.h" #endif -/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ -#ifndef EOVERFLOW -# define EOVERFLOW E2BIG -#endif - #if HAVE_WCHAR_T # if HAVE_WCSLEN # define local_wcslen wcslen @@ -3566,7 +3561,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; -#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int has_width; size_t width; #endif @@ -3579,7 +3574,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #else # define prec_ourselves 0 #endif -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if NEED_PRINTF_FLAG_LEFTADJUST +# define pad_ourselves 1 +#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int pad_ourselves; #else # define pad_ourselves 0 @@ -3593,7 +3590,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, TCHAR_T *tmp; #endif -#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION has_width = 0; width = 0; if (dp->width_start != dp->width_end) @@ -3659,6 +3656,44 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif + /* Decide whether to handle the precision ourselves. */ +#if NEED_PRINTF_UNBOUNDED_PRECISION + switch (dp->conversion) + { + case 'd': case 'i': case 'u': + case 'o': + case 'x': case 'X': case 'p': + prec_ourselves = has_precision && (precision > 0); + break; + default: + prec_ourselves = 0; + break; + } +#endif + + /* Decide whether to perform the padding ourselves. */ +#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) + switch (dp->conversion) + { +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need + to perform the padding after this conversion. Functions + with unistdio extensions perform the padding based on + character count rather than element count. */ + case 'c': case 's': +# endif +# if NEED_PRINTF_FLAG_ZERO + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': +# endif + pad_ourselves = 1; + break; + default: + pad_ourselves = prec_ourselves; + break; + } +#endif + #if !USE_SNPRINTF /* Allocate a temporary buffer of sufficient size for calling sprintf. */ @@ -3835,18 +3870,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, abort (); } + if (!pad_ourselves) + { # if ENABLE_UNISTDIO - /* Padding considers the number of characters, therefore the - number of elements after padding may be - > max (tmp_length, width) - but is certainly - <= tmp_length + width. */ - tmp_length = xsum (tmp_length, width); + /* Padding considers the number of characters, therefore + the number of elements after padding may be + > max (tmp_length, width) + but is certainly + <= tmp_length + width. */ + tmp_length = xsum (tmp_length, width); # else - /* Padding considers the number of elements, says POSIX. */ - if (tmp_length < width) - tmp_length = width; + /* Padding considers the number of elements, + says POSIX. */ + if (tmp_length < width) + tmp_length = width; # endif + } tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ } @@ -3867,44 +3906,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif - /* Decide whether to handle the precision ourselves. */ -#if NEED_PRINTF_UNBOUNDED_PRECISION - switch (dp->conversion) - { - case 'd': case 'i': case 'u': - case 'o': - case 'x': case 'X': case 'p': - prec_ourselves = has_precision && (precision > 0); - break; - default: - prec_ourselves = 0; - break; - } -#endif - - /* Decide whether to perform the padding ourselves. */ -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION - switch (dp->conversion) - { -# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO - /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need - to perform the padding after this conversion. Functions - with unistdio extensions perform the padding based on - character count rather than element count. */ - case 'c': case 's': -# endif -# if NEED_PRINTF_FLAG_ZERO - case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': -# endif - pad_ourselves = 1; - break; - default: - pad_ourselves = prec_ourselves; - break; - } -#endif - /* Construct the format string for calling snprintf or sprintf. */ fbp = buf; @@ -4008,7 +4009,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #endif *fbp = dp->conversion; #if USE_SNPRINTF -# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) +# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) fbp[1] = '%'; fbp[2] = 'n'; fbp[3] = '\0'; @@ -4021,6 +4022,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, in format strings in writable memory may crash the program (if compiled with _FORTIFY_SOURCE=2), so we should avoid it in this situation. */ + /* On native Win32 systems (such as mingw), we can avoid using + %n because: + - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, + snprintf does not write more than the specified number + of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes + '4', '5', '6' into buf, not '4', '5', '\0'.) + - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf + allows us to recognize the case of an insufficient + buffer size: it returns -1 in this case. + On native Win32 systems (such as mingw) where the OS is + Windows Vista, the use of %n in format strings by default + crashes the program. See + and + + So we should avoid %n in this situation. */ fbp[1] = '\0'; # endif #else @@ -4386,14 +4402,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if !DCHAR_IS_TCHAR -# if !USE_SNPRINTF +#if !USE_SNPRINTF if (count >= tmp_length) /* tmp_length was incorrectly calculated - fix the code above! */ abort (); -# endif +#endif +#if !DCHAR_IS_TCHAR /* Convert from TCHAR_T[] to DCHAR_T[]. */ if (dp->conversion == 'c' || dp->conversion == 's') { @@ -4494,7 +4510,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Here count <= allocated - length. */ /* Perform padding. */ -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION if (pad_ourselves && has_width) { size_t w; @@ -4511,7 +4527,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (w < width) { size_t pad = width - w; -# if USE_SNPRINTF + /* Make room for the result. */ if (xsum (count, pad) > allocated - length) { @@ -4521,12 +4537,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, xmax (xsum3 (length, count, pad), xtimes (allocated, 2)); +# if USE_SNPRINTF length += count; ENSURE_ALLOCATION (n); length -= count; +# else + ENSURE_ALLOCATION (n); +# endif } /* Here count + pad <= allocated - length. */ -# endif + { # if !DCHAR_IS_TCHAR || USE_SNPRINTF DCHAR_T * const rp = result + length; @@ -4536,7 +4556,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, DCHAR_T *p = rp + count; DCHAR_T *end = p + pad; DCHAR_T *pad_ptr; -# if !DCHAR_IS_TCHAR +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO if (dp->conversion == 'c' || dp->conversion == 's') /* No zero-padding for string directives. */ @@ -4587,13 +4607,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif -#if DCHAR_IS_TCHAR && !USE_SNPRINTF - if (count >= tmp_length) - /* tmp_length was incorrectly calculated - fix the - code above! */ - abort (); -#endif - /* Here still count <= allocated - length. */ #if !DCHAR_IS_TCHAR || USE_SNPRINTF