summaryrefslogtreecommitdiffstats
path: root/gl/vasnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r--gl/vasnprintf.c714
1 files changed, 657 insertions, 57 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c
index 93aef6f..7ac9f43 100644
--- a/gl/vasnprintf.c
+++ b/gl/vasnprintf.c
@@ -1,5 +1,5 @@
1/* vsprintf with automatic memory allocation. 1/* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2008 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2002-2009 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
@@ -117,29 +117,6 @@
117# include "fpucw.h" 117# include "fpucw.h"
118#endif 118#endif
119 119
120#if HAVE_WCHAR_T
121# if HAVE_WCSLEN
122# define local_wcslen wcslen
123# else
124 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
125 a dependency towards this library, here is a local substitute.
126 Define this substitute only once, even if this file is included
127 twice in the same compilation unit. */
128# ifndef local_wcslen_defined
129# define local_wcslen_defined 1
130static size_t
131local_wcslen (const wchar_t *s)
132{
133 const wchar_t *ptr;
134
135 for (ptr = s; *ptr != (wchar_t) 0; ptr++)
136 ;
137 return ptr - s;
138}
139# endif
140# endif
141#endif
142
143/* Default parameters. */ 120/* Default parameters. */
144#ifndef VASNPRINTF 121#ifndef VASNPRINTF
145# if WIDE_CHAR_VERSION 122# if WIDE_CHAR_VERSION
@@ -152,6 +129,7 @@ local_wcslen (const wchar_t *s)
152# define DIRECTIVES wchar_t_directives 129# define DIRECTIVES wchar_t_directives
153# define PRINTF_PARSE wprintf_parse 130# define PRINTF_PARSE wprintf_parse
154# define DCHAR_CPY wmemcpy 131# define DCHAR_CPY wmemcpy
132# define DCHAR_SET wmemset
155# else 133# else
156# define VASNPRINTF vasnprintf 134# define VASNPRINTF vasnprintf
157# define FCHAR_T char 135# define FCHAR_T char
@@ -162,6 +140,7 @@ local_wcslen (const wchar_t *s)
162# define DIRECTIVES char_directives 140# define DIRECTIVES char_directives
163# define PRINTF_PARSE printf_parse 141# define PRINTF_PARSE printf_parse
164# define DCHAR_CPY memcpy 142# define DCHAR_CPY memcpy
143# define DCHAR_SET memset
165# endif 144# endif
166#endif 145#endif
167#if WIDE_CHAR_VERSION 146#if WIDE_CHAR_VERSION
@@ -215,6 +194,64 @@ local_wcslen (const wchar_t *s)
215#undef remainder 194#undef remainder
216#define remainder rem 195#define remainder rem
217 196
197#if !USE_SNPRINTF && !WIDE_CHAR_VERSION
198# if (HAVE_STRNLEN && !defined _AIX)
199# define local_strnlen strnlen
200# else
201# ifndef local_strnlen_defined
202# define local_strnlen_defined 1
203static size_t
204local_strnlen (const char *string, size_t maxlen)
205{
206 const char *end = memchr (string, '\0', maxlen);
207 return end ? (size_t) (end - string) : maxlen;
208}
209# endif
210# endif
211#endif
212
213#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T && (WIDE_CHAR_VERSION || DCHAR_IS_TCHAR)
214# if HAVE_WCSLEN
215# define local_wcslen wcslen
216# else
217 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
218 a dependency towards this library, here is a local substitute.
219 Define this substitute only once, even if this file is included
220 twice in the same compilation unit. */
221# ifndef local_wcslen_defined
222# define local_wcslen_defined 1
223static size_t
224local_wcslen (const wchar_t *s)
225{
226 const wchar_t *ptr;
227
228 for (ptr = s; *ptr != (wchar_t) 0; ptr++)
229 ;
230 return ptr - s;
231}
232# endif
233# endif
234#endif
235
236#if !USE_SNPRINTF && HAVE_WCHAR_T && WIDE_CHAR_VERSION
237# if HAVE_WCSNLEN
238# define local_wcsnlen wcsnlen
239# else
240# ifndef local_wcsnlen_defined
241# define local_wcsnlen_defined 1
242static size_t
243local_wcsnlen (const wchar_t *s, size_t maxlen)
244{
245 const wchar_t *ptr;
246
247 for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
248 ;
249 return ptr - s;
250}
251# endif
252# endif
253#endif
254
218#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL 255#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
219/* Determine the decimal-point character according to the current locale. */ 256/* Determine the decimal-point character according to the current locale. */
220# ifndef decimal_point_char_defined 257# ifndef decimal_point_char_defined
@@ -376,7 +413,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
376 Normalise [q[m-1],...,q[0]], yields q. 413 Normalise [q[m-1],...,q[0]], yields q.
377 If m>=n>1, perform a multiple-precision division: 414 If m>=n>1, perform a multiple-precision division:
378 We have a/b < beta^(m-n+1). 415 We have a/b < beta^(m-n+1).
379 s:=intDsize-1-(hightest bit in b[n-1]), 0<=s<intDsize. 416 s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
380 Shift a and b left by s bits, copying them. r:=a. 417 Shift a and b left by s bits, copying them. r:=a.
381 r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2. 418 r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
382 For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).} 419 For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
@@ -1762,18 +1799,18 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
1762 size_t converted_len = allocated - length; 1799 size_t converted_len = allocated - length;
1763# if DCHAR_IS_TCHAR 1800# if DCHAR_IS_TCHAR
1764 /* Convert from UTF-8 to locale encoding. */ 1801 /* Convert from UTF-8 to locale encoding. */
1765 if (u8_conv_to_encoding (locale_charset (), 1802 converted =
1766 iconveh_question_mark, 1803 u8_conv_to_encoding (locale_charset (),
1767 arg, arg_end - arg, NULL, 1804 iconveh_question_mark,
1768 &converted, &converted_len) 1805 arg, arg_end - arg, NULL,
1769 < 0) 1806 converted, &converted_len);
1770# else 1807# else
1771 /* Convert from UTF-8 to UTF-16/UTF-32. */ 1808 /* Convert from UTF-8 to UTF-16/UTF-32. */
1772 converted = 1809 converted =
1773 U8_TO_DCHAR (arg, arg_end - arg, 1810 U8_TO_DCHAR (arg, arg_end - arg,
1774 converted, &converted_len); 1811 converted, &converted_len);
1775 if (converted == NULL)
1776# endif 1812# endif
1813 if (converted == NULL)
1777 { 1814 {
1778 int saved_errno = errno; 1815 int saved_errno = errno;
1779 if (!(result == resultbuf || result == NULL)) 1816 if (!(result == resultbuf || result == NULL))
@@ -1890,18 +1927,18 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
1890 size_t converted_len = allocated - length; 1927 size_t converted_len = allocated - length;
1891# if DCHAR_IS_TCHAR 1928# if DCHAR_IS_TCHAR
1892 /* Convert from UTF-16 to locale encoding. */ 1929 /* Convert from UTF-16 to locale encoding. */
1893 if (u16_conv_to_encoding (locale_charset (), 1930 converted =
1894 iconveh_question_mark, 1931 u16_conv_to_encoding (locale_charset (),
1895 arg, arg_end - arg, NULL, 1932 iconveh_question_mark,
1896 &converted, &converted_len) 1933 arg, arg_end - arg, NULL,
1897 < 0) 1934 converted, &converted_len);
1898# else 1935# else
1899 /* Convert from UTF-16 to UTF-8/UTF-32. */ 1936 /* Convert from UTF-16 to UTF-8/UTF-32. */
1900 converted = 1937 converted =
1901 U16_TO_DCHAR (arg, arg_end - arg, 1938 U16_TO_DCHAR (arg, arg_end - arg,
1902 converted, &converted_len); 1939 converted, &converted_len);
1903 if (converted == NULL)
1904# endif 1940# endif
1941 if (converted == NULL)
1905 { 1942 {
1906 int saved_errno = errno; 1943 int saved_errno = errno;
1907 if (!(result == resultbuf || result == NULL)) 1944 if (!(result == resultbuf || result == NULL))
@@ -2018,18 +2055,18 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2018 size_t converted_len = allocated - length; 2055 size_t converted_len = allocated - length;
2019# if DCHAR_IS_TCHAR 2056# if DCHAR_IS_TCHAR
2020 /* Convert from UTF-32 to locale encoding. */ 2057 /* Convert from UTF-32 to locale encoding. */
2021 if (u32_conv_to_encoding (locale_charset (), 2058 converted =
2022 iconveh_question_mark, 2059 u32_conv_to_encoding (locale_charset (),
2023 arg, arg_end - arg, NULL, 2060 iconveh_question_mark,
2024 &converted, &converted_len) 2061 arg, arg_end - arg, NULL,
2025 < 0) 2062 converted, &converted_len);
2026# else 2063# else
2027 /* Convert from UTF-32 to UTF-8/UTF-16. */ 2064 /* Convert from UTF-32 to UTF-8/UTF-16. */
2028 converted = 2065 converted =
2029 U32_TO_DCHAR (arg, arg_end - arg, 2066 U32_TO_DCHAR (arg, arg_end - arg,
2030 converted, &converted_len); 2067 converted, &converted_len);
2031 if (converted == NULL)
2032# endif 2068# endif
2069 if (converted == NULL)
2033 { 2070 {
2034 int saved_errno = errno; 2071 int saved_errno = errno;
2035 if (!(result == resultbuf || result == NULL)) 2072 if (!(result == resultbuf || result == NULL))
@@ -2066,6 +2103,522 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2066 } 2103 }
2067 } 2104 }
2068#endif 2105#endif
2106#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
2107 else if (dp->conversion == 's'
2108# if WIDE_CHAR_VERSION
2109 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
2110# else
2111 && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
2112# endif
2113 )
2114 {
2115 /* The normal handling of the 's' directive below requires
2116 allocating a temporary buffer. The determination of its
2117 length (tmp_length), in the case when a precision is
2118 specified, below requires a conversion between a char[]
2119 string and a wchar_t[] wide string. It could be done, but
2120 we have no guarantee that the implementation of sprintf will
2121 use the exactly same algorithm. Without this guarantee, it
2122 is possible to have buffer overrun bugs. In order to avoid
2123 such bugs, we implement the entire processing of the 's'
2124 directive ourselves. */
2125 int flags = dp->flags;
2126 int has_width;
2127 size_t width;
2128 int has_precision;
2129 size_t precision;
2130
2131 has_width = 0;
2132 width = 0;
2133 if (dp->width_start != dp->width_end)
2134 {
2135 if (dp->width_arg_index != ARG_NONE)
2136 {
2137 int arg;
2138
2139 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2140 abort ();
2141 arg = a.arg[dp->width_arg_index].a.a_int;
2142 if (arg < 0)
2143 {
2144 /* "A negative field width is taken as a '-' flag
2145 followed by a positive field width." */
2146 flags |= FLAG_LEFT;
2147 width = (unsigned int) (-arg);
2148 }
2149 else
2150 width = arg;
2151 }
2152 else
2153 {
2154 const FCHAR_T *digitp = dp->width_start;
2155
2156 do
2157 width = xsum (xtimes (width, 10), *digitp++ - '0');
2158 while (digitp != dp->width_end);
2159 }
2160 has_width = 1;
2161 }
2162
2163 has_precision = 0;
2164 precision = 6;
2165 if (dp->precision_start != dp->precision_end)
2166 {
2167 if (dp->precision_arg_index != ARG_NONE)
2168 {
2169 int arg;
2170
2171 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2172 abort ();
2173 arg = a.arg[dp->precision_arg_index].a.a_int;
2174 /* "A negative precision is taken as if the precision
2175 were omitted." */
2176 if (arg >= 0)
2177 {
2178 precision = arg;
2179 has_precision = 1;
2180 }
2181 }
2182 else
2183 {
2184 const FCHAR_T *digitp = dp->precision_start + 1;
2185
2186 precision = 0;
2187 while (digitp != dp->precision_end)
2188 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2189 has_precision = 1;
2190 }
2191 }
2192
2193# if WIDE_CHAR_VERSION
2194 /* %s in vasnwprintf. See the specification of fwprintf. */
2195 {
2196 const char *arg = a.arg[dp->arg_index].a.a_string;
2197 const char *arg_end;
2198 size_t characters;
2199
2200 if (has_precision)
2201 {
2202 /* Use only as many bytes as needed to produce PRECISION
2203 wide characters, from the left. */
2204# if HAVE_MBRTOWC
2205 mbstate_t state;
2206 memset (&state, '\0', sizeof (mbstate_t));
2207# endif
2208 arg_end = arg;
2209 characters = 0;
2210 for (; precision > 0; precision--)
2211 {
2212 int count;
2213# if HAVE_MBRTOWC
2214 count = mbrlen (arg_end, MB_CUR_MAX, &state);
2215# else
2216 count = mblen (arg_end, MB_CUR_MAX);
2217# endif
2218 if (count == 0)
2219 /* Found the terminating NUL. */
2220 break;
2221 if (count < 0)
2222 {
2223 /* Invalid or incomplete multibyte character. */
2224 if (!(result == resultbuf || result == NULL))
2225 free (result);
2226 if (buf_malloced != NULL)
2227 free (buf_malloced);
2228 CLEANUP ();
2229 errno = EILSEQ;
2230 return NULL;
2231 }
2232 arg_end += count;
2233 characters++;
2234 }
2235 }
2236 else if (has_width)
2237 {
2238 /* Use the entire string, and count the number of wide
2239 characters. */
2240# if HAVE_MBRTOWC
2241 mbstate_t state;
2242 memset (&state, '\0', sizeof (mbstate_t));
2243# endif
2244 arg_end = arg;
2245 characters = 0;
2246 for (;;)
2247 {
2248 int count;
2249# if HAVE_MBRTOWC
2250 count = mbrlen (arg_end, MB_CUR_MAX, &state);
2251# else
2252 count = mblen (arg_end, MB_CUR_MAX);
2253# endif
2254 if (count == 0)
2255 /* Found the terminating NUL. */
2256 break;
2257 if (count < 0)
2258 {
2259 /* Invalid or incomplete multibyte character. */
2260 if (!(result == resultbuf || result == NULL))
2261 free (result);
2262 if (buf_malloced != NULL)
2263 free (buf_malloced);
2264 CLEANUP ();
2265 errno = EILSEQ;
2266 return NULL;
2267 }
2268 arg_end += count;
2269 characters++;
2270 }
2271 }
2272 else
2273 {
2274 /* Use the entire string. */
2275 arg_end = arg + strlen (arg);
2276 /* The number of characters doesn't matter. */
2277 characters = 0;
2278 }
2279
2280 if (has_width && width > characters
2281 && !(dp->flags & FLAG_LEFT))
2282 {
2283 size_t n = width - characters;
2284 ENSURE_ALLOCATION (xsum (length, n));
2285 DCHAR_SET (result + length, ' ', n);
2286 length += n;
2287 }
2288
2289 if (has_precision || has_width)
2290 {
2291 /* We know the number of wide characters in advance. */
2292 size_t remaining;
2293# if HAVE_MBRTOWC
2294 mbstate_t state;
2295 memset (&state, '\0', sizeof (mbstate_t));
2296# endif
2297 ENSURE_ALLOCATION (xsum (length, characters));
2298 for (remaining = characters; remaining > 0; remaining--)
2299 {
2300 wchar_t wc;
2301 int count;
2302# if HAVE_MBRTOWC
2303 count = mbrtowc (&wc, arg, arg_end - arg, &state);
2304# else
2305 count = mbtowc (&wc, arg, arg_end - arg);
2306# endif
2307 if (count <= 0)
2308 /* mbrtowc not consistent with mbrlen, or mbtowc
2309 not consistent with mblen. */
2310 abort ();
2311 result[length++] = wc;
2312 arg += count;
2313 }
2314 if (!(arg == arg_end))
2315 abort ();
2316 }
2317 else
2318 {
2319# if HAVE_MBRTOWC
2320 mbstate_t state;
2321 memset (&state, '\0', sizeof (mbstate_t));
2322# endif
2323 while (arg < arg_end)
2324 {
2325 wchar_t wc;
2326 int count;
2327# if HAVE_MBRTOWC
2328 count = mbrtowc (&wc, arg, arg_end - arg, &state);
2329# else
2330 count = mbtowc (&wc, arg, arg_end - arg);
2331# endif
2332 if (count <= 0)
2333 /* mbrtowc not consistent with mbrlen, or mbtowc
2334 not consistent with mblen. */
2335 abort ();
2336 ENSURE_ALLOCATION (xsum (length, 1));
2337 result[length++] = wc;
2338 arg += count;
2339 }
2340 }
2341
2342 if (has_width && width > characters
2343 && (dp->flags & FLAG_LEFT))
2344 {
2345 size_t n = width - characters;
2346 ENSURE_ALLOCATION (xsum (length, n));
2347 DCHAR_SET (result + length, ' ', n);
2348 length += n;
2349 }
2350 }
2351# else
2352 /* %ls in vasnprintf. See the specification of fprintf. */
2353 {
2354 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
2355 const wchar_t *arg_end;
2356 size_t characters;
2357# if !DCHAR_IS_TCHAR
2358 /* This code assumes that TCHAR_T is 'char'. */
2359 typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
2360 TCHAR_T *tmpsrc;
2361 DCHAR_T *tmpdst;
2362 size_t tmpdst_len;
2363# endif
2364 size_t w;
2365
2366 if (has_precision)
2367 {
2368 /* Use only as many wide characters as needed to produce
2369 at most PRECISION bytes, from the left. */
2370# if HAVE_WCRTOMB
2371 mbstate_t state;
2372 memset (&state, '\0', sizeof (mbstate_t));
2373# endif
2374 arg_end = arg;
2375 characters = 0;
2376 while (precision > 0)
2377 {
2378 char buf[64]; /* Assume MB_CUR_MAX <= 64. */
2379 int count;
2380
2381 if (*arg_end == 0)
2382 /* Found the terminating null wide character. */
2383 break;
2384# if HAVE_WCRTOMB
2385 count = wcrtomb (buf, *arg_end, &state);
2386# else
2387 count = wctomb (buf, *arg_end);
2388# endif
2389 if (count < 0)
2390 {
2391 /* Cannot convert. */
2392 if (!(result == resultbuf || result == NULL))
2393 free (result);
2394 if (buf_malloced != NULL)
2395 free (buf_malloced);
2396 CLEANUP ();
2397 errno = EILSEQ;
2398 return NULL;
2399 }
2400 if (precision < count)
2401 break;
2402 arg_end++;
2403 characters += count;
2404 precision -= count;
2405 }
2406 }
2407# if DCHAR_IS_TCHAR
2408 else if (has_width)
2409# else
2410 else
2411# endif
2412 {
2413 /* Use the entire string, and count the number of
2414 bytes. */
2415# if HAVE_WCRTOMB
2416 mbstate_t state;
2417 memset (&state, '\0', sizeof (mbstate_t));
2418# endif
2419 arg_end = arg;
2420 characters = 0;
2421 for (;;)
2422 {
2423 char buf[64]; /* Assume MB_CUR_MAX <= 64. */
2424 int count;
2425
2426 if (*arg_end == 0)
2427 /* Found the terminating null wide character. */
2428 break;
2429# if HAVE_WCRTOMB
2430 count = wcrtomb (buf, *arg_end, &state);
2431# else
2432 count = wctomb (buf, *arg_end);
2433# endif
2434 if (count < 0)
2435 {
2436 /* Cannot convert. */
2437 if (!(result == resultbuf || result == NULL))
2438 free (result);
2439 if (buf_malloced != NULL)
2440 free (buf_malloced);
2441 CLEANUP ();
2442 errno = EILSEQ;
2443 return NULL;
2444 }
2445 arg_end++;
2446 characters += count;
2447 }
2448 }
2449# if DCHAR_IS_TCHAR
2450 else
2451 {
2452 /* Use the entire string. */
2453 arg_end = arg + local_wcslen (arg);
2454 /* The number of bytes doesn't matter. */
2455 characters = 0;
2456 }
2457# endif
2458
2459# if !DCHAR_IS_TCHAR
2460 /* Convert the string into a piece of temporary memory. */
2461 tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
2462 if (tmpsrc == NULL)
2463 goto out_of_memory;
2464 {
2465 TCHAR_T *tmpptr = tmpsrc;
2466 size_t remaining;
2467# if HAVE_WCRTOMB
2468 mbstate_t state;
2469 memset (&state, '\0', sizeof (mbstate_t));
2470# endif
2471 for (remaining = characters; remaining > 0; )
2472 {
2473 char buf[64]; /* Assume MB_CUR_MAX <= 64. */
2474 int count;
2475
2476 if (*arg == 0)
2477 abort ();
2478# if HAVE_WCRTOMB
2479 count = wcrtomb (buf, *arg, &state);
2480# else
2481 count = wctomb (buf, *arg);
2482# endif
2483 if (count <= 0)
2484 /* Inconsistency. */
2485 abort ();
2486 memcpy (tmpptr, buf, count);
2487 tmpptr += count;
2488 arg++;
2489 remaining -= count;
2490 }
2491 if (!(arg == arg_end))
2492 abort ();
2493 }
2494
2495 /* Convert from TCHAR_T[] to DCHAR_T[]. */
2496 tmpdst =
2497 DCHAR_CONV_FROM_ENCODING (locale_charset (),
2498 iconveh_question_mark,
2499 tmpsrc, characters,
2500 NULL,
2501 NULL, &tmpdst_len);
2502 if (tmpdst == NULL)
2503 {
2504 int saved_errno = errno;
2505 free (tmpsrc);
2506 if (!(result == resultbuf || result == NULL))
2507 free (result);
2508 if (buf_malloced != NULL)
2509 free (buf_malloced);
2510 CLEANUP ();
2511 errno = saved_errno;
2512 return NULL;
2513 }
2514 free (tmpsrc);
2515# endif
2516
2517 if (has_width)
2518 {
2519# if ENABLE_UNISTDIO
2520 /* Outside POSIX, it's preferrable to compare the width
2521 against the number of _characters_ of the converted
2522 value. */
2523 w = DCHAR_MBSNLEN (result + length, characters);
2524# else
2525 /* The width is compared against the number of _bytes_
2526 of the converted value, says POSIX. */
2527 w = characters;
2528# endif
2529 }
2530 else
2531 /* w doesn't matter. */
2532 w = 0;
2533
2534 if (has_width && width > w
2535 && !(dp->flags & FLAG_LEFT))
2536 {
2537 size_t n = width - w;
2538 ENSURE_ALLOCATION (xsum (length, n));
2539 DCHAR_SET (result + length, ' ', n);
2540 length += n;
2541 }
2542
2543# if DCHAR_IS_TCHAR
2544 if (has_precision || has_width)
2545 {
2546 /* We know the number of bytes in advance. */
2547 size_t remaining;
2548# if HAVE_WCRTOMB
2549 mbstate_t state;
2550 memset (&state, '\0', sizeof (mbstate_t));
2551# endif
2552 ENSURE_ALLOCATION (xsum (length, characters));
2553 for (remaining = characters; remaining > 0; )
2554 {
2555 char buf[64]; /* Assume MB_CUR_MAX <= 64. */
2556 int count;
2557
2558 if (*arg == 0)
2559 abort ();
2560# if HAVE_WCRTOMB
2561 count = wcrtomb (buf, *arg, &state);
2562# else
2563 count = wctomb (buf, *arg);
2564# endif
2565 if (count <= 0)
2566 /* Inconsistency. */
2567 abort ();
2568 memcpy (result + length, buf, count);
2569 length += count;
2570 arg++;
2571 remaining -= count;
2572 }
2573 if (!(arg == arg_end))
2574 abort ();
2575 }
2576 else
2577 {
2578# if HAVE_WCRTOMB
2579 mbstate_t state;
2580 memset (&state, '\0', sizeof (mbstate_t));
2581# endif
2582 while (arg < arg_end)
2583 {
2584 char buf[64]; /* Assume MB_CUR_MAX <= 64. */
2585 int count;
2586
2587 if (*arg == 0)
2588 abort ();
2589# if HAVE_WCRTOMB
2590 count = wcrtomb (buf, *arg, &state);
2591# else
2592 count = wctomb (buf, *arg);
2593# endif
2594 if (count <= 0)
2595 /* Inconsistency. */
2596 abort ();
2597 ENSURE_ALLOCATION (xsum (length, count));
2598 memcpy (result + length, buf, count);
2599 length += count;
2600 arg++;
2601 }
2602 }
2603# else
2604 ENSURE_ALLOCATION (xsum (length, tmpdst_len));
2605 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
2606 free (tmpdst);
2607 length += tmpdst_len;
2608# endif
2609
2610 if (has_width && width > w
2611 && (dp->flags & FLAG_LEFT))
2612 {
2613 size_t n = width - w;
2614 ENSURE_ALLOCATION (xsum (length, n));
2615 DCHAR_SET (result + length, ' ', n);
2616 length += n;
2617 }
2618 }
2619 }
2620# endif
2621#endif
2069#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL 2622#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
2070 else if ((dp->conversion == 'a' || dp->conversion == 'A') 2623 else if ((dp->conversion == 'a' || dp->conversion == 'A')
2071# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE)) 2624# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
@@ -4032,16 +4585,64 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4032# if HAVE_WCHAR_T 4585# if HAVE_WCHAR_T
4033 if (type == TYPE_WIDE_STRING) 4586 if (type == TYPE_WIDE_STRING)
4034 { 4587 {
4035 tmp_length = 4588# if WIDE_CHAR_VERSION
4036 local_wcslen (a.arg[dp->arg_index].a.a_wide_string); 4589 /* ISO C says about %ls in fwprintf:
4037 4590 "If the precision is not specified or is greater
4038# if !WIDE_CHAR_VERSION 4591 than the size of the array, the array shall
4039 tmp_length = xtimes (tmp_length, MB_CUR_MAX); 4592 contain a null wide character."
4593 So if there is a precision, we must not use
4594 wcslen. */
4595 const wchar_t *arg =
4596 a.arg[dp->arg_index].a.a_wide_string;
4597
4598 if (has_precision)
4599 tmp_length = local_wcsnlen (arg, precision);
4600 else
4601 tmp_length = local_wcslen (arg);
4602# else
4603 /* ISO C says about %ls in fprintf:
4604 "If a precision is specified, no more than that
4605 many bytes are written (including shift
4606 sequences, if any), and the array shall contain
4607 a null wide character if, to equal the
4608 multibyte character sequence length given by
4609 the precision, the function would need to
4610 access a wide character one past the end of the
4611 array."
4612 So if there is a precision, we must not use
4613 wcslen. */
4614 /* This case has already been handled above. */
4615 abort ();
4040# endif 4616# endif
4041 } 4617 }
4042 else 4618 else
4043# endif 4619# endif
4044 tmp_length = strlen (a.arg[dp->arg_index].a.a_string); 4620 {
4621# if WIDE_CHAR_VERSION
4622 /* ISO C says about %s in fwprintf:
4623 "If the precision is not specified or is greater
4624 than the size of the converted array, the
4625 converted array shall contain a null wide
4626 character."
4627 So if there is a precision, we must not use
4628 strlen. */
4629 /* This case has already been handled above. */
4630 abort ();
4631# else
4632 /* ISO C says about %s in fprintf:
4633 "If the precision is not specified or greater
4634 than the size of the array, the array shall
4635 contain a null character."
4636 So if there is a precision, we must not use
4637 strlen. */
4638 const char *arg = a.arg[dp->arg_index].a.a_string;
4639
4640 if (has_precision)
4641 tmp_length = local_strnlen (arg, precision);
4642 else
4643 tmp_length = strlen (arg);
4644# endif
4645 }
4045 break; 4646 break;
4046 4647
4047 case 'p': 4648 case 'p':
@@ -4614,14 +5215,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4614# else 5215# else
4615 tmpsrc = tmp; 5216 tmpsrc = tmp;
4616# endif 5217# endif
4617 tmpdst = NULL; 5218 tmpdst =
4618 tmpdst_len = 0; 5219 DCHAR_CONV_FROM_ENCODING (locale_charset (),
4619 if (DCHAR_CONV_FROM_ENCODING (locale_charset (), 5220 iconveh_question_mark,
4620 iconveh_question_mark, 5221 tmpsrc, count,
4621 tmpsrc, count, 5222 NULL,
4622 NULL, 5223 NULL, &tmpdst_len);
4623 &tmpdst, &tmpdst_len) 5224 if (tmpdst == NULL)
4624 < 0)
4625 { 5225 {
4626 int saved_errno = errno; 5226 int saved_errno = errno;
4627 if (!(result == resultbuf || result == NULL)) 5227 if (!(result == resultbuf || result == NULL))