diff options
author | Holger Weiss <holger@zedat.fu-berlin.de> | 2009-05-20 00:32:10 +0200 |
---|---|---|
committer | Holger Weiss <holger@zedat.fu-berlin.de> | 2009-05-20 00:32:10 +0200 |
commit | 50b3ff7b91e78a61aca93247bee586d6d7eb27c8 (patch) | |
tree | db4c7eee24479ac7ee6888ce1562facf60159b71 /gl/vasnprintf.c | |
parent | 2701ccd500e60537a8c2977a81549ff33eeaef3f (diff) | |
download | monitoring-plugins-50b3ff7b91e78a61aca93247bee586d6d7eb27c8.tar.gz |
Sync with the latest Gnulib code (cb75dc5)
Signed-off-by: Holger Weiss <holger@zedat.fu-berlin.de>
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r-- | gl/vasnprintf.c | 714 |
1 files changed, 657 insertions, 57 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c index 93aef6f2..7ac9f436 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 | ||
130 | static size_t | ||
131 | local_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 | ||
203 | static size_t | ||
204 | local_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 | ||
223 | static size_t | ||
224 | local_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 | ||
242 | static size_t | ||
243 | local_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)) |