Fix bug 5411
[lyx.git] / intl / printf.c
blob004c66f783d1914199507d4c0ce78a879364d84d
1 /* Formatted output to strings, using POSIX/XSI format strings with positions.
2 Copyright (C) 2003, 2006 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published
7 by the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 USA. */
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #ifdef __GNUC__
25 # define alloca __builtin_alloca
26 # define HAVE_ALLOCA 1
27 #else
28 # ifdef _MSC_VER
29 # include <malloc.h>
30 # define alloca _alloca
31 # else
32 # if defined HAVE_ALLOCA_H || defined _LIBC
33 # include <alloca.h>
34 # else
35 # ifdef _AIX
36 #pragma alloca
37 # else
38 # ifndef alloca
39 char *alloca ();
40 # endif
41 # endif
42 # endif
43 # endif
44 #endif
46 #include <stdio.h>
48 #if !HAVE_POSIX_PRINTF
50 #include <errno.h>
51 #include <limits.h>
52 #include <stdlib.h>
53 #include <string.h>
55 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
56 #ifndef EOVERFLOW
57 # define EOVERFLOW E2BIG
58 #endif
60 /* When building a DLL, we must export some functions. Note that because
61 the functions are only defined for binary backward compatibility, we
62 don't need to use __declspec(dllimport) in any case. */
63 #if defined _MSC_VER && BUILDING_DLL
64 # define DLL_EXPORTED __declspec(dllexport)
65 #else
66 # define DLL_EXPORTED
67 #endif
69 #define STATIC static
71 /* This needs to be consistent with libgnuintl.h.in. */
72 #if defined __NetBSD__ || defined __CYGWIN__ || defined __MINGW32__
73 /* Don't break __attribute__((format(printf,M,N))).
74 This redefinition is only possible because the libc in NetBSD, Cygwin,
75 mingw does not have a function __printf__. */
76 # define libintl_printf __printf__
77 #endif
79 /* Define auxiliary functions declared in "printf-args.h". */
80 #include "printf-args.c"
82 /* Define auxiliary functions declared in "printf-parse.h". */
83 #include "printf-parse.c"
85 /* Define functions declared in "vasnprintf.h". */
86 #define vasnprintf libintl_vasnprintf
87 #include "vasnprintf.c"
88 #if 0 /* not needed */
89 #define asnprintf libintl_asnprintf
90 #include "asnprintf.c"
91 #endif
93 DLL_EXPORTED
94 int
95 libintl_vfprintf (FILE *stream, const char *format, va_list args)
97 if (strchr (format, '$') == NULL)
98 return vfprintf (stream, format, args);
99 else
101 size_t length;
102 char *result = libintl_vasnprintf (NULL, &length, format, args);
103 int retval = -1;
104 if (result != NULL)
106 size_t written = fwrite (result, 1, length, stream);
107 free (result);
108 if (written == length)
110 if (length > INT_MAX)
111 errno = EOVERFLOW;
112 else
113 retval = length;
116 return retval;
120 DLL_EXPORTED
122 libintl_fprintf (FILE *stream, const char *format, ...)
124 va_list args;
125 int retval;
127 va_start (args, format);
128 retval = libintl_vfprintf (stream, format, args);
129 va_end (args);
130 return retval;
133 DLL_EXPORTED
135 libintl_vprintf (const char *format, va_list args)
137 return libintl_vfprintf (stdout, format, args);
140 DLL_EXPORTED
142 libintl_printf (const char *format, ...)
144 va_list args;
145 int retval;
147 va_start (args, format);
148 retval = libintl_vprintf (format, args);
149 va_end (args);
150 return retval;
153 DLL_EXPORTED
155 libintl_vsprintf (char *resultbuf, const char *format, va_list args)
157 if (strchr (format, '$') == NULL)
158 return vsprintf (resultbuf, format, args);
159 else
161 size_t length = (size_t) ~0 / (4 * sizeof (char));
162 char *result = libintl_vasnprintf (resultbuf, &length, format, args);
163 if (result != resultbuf)
165 free (result);
166 return -1;
168 if (length > INT_MAX)
170 errno = EOVERFLOW;
171 return -1;
173 else
174 return length;
178 DLL_EXPORTED
180 libintl_sprintf (char *resultbuf, const char *format, ...)
182 va_list args;
183 int retval;
185 va_start (args, format);
186 retval = libintl_vsprintf (resultbuf, format, args);
187 va_end (args);
188 return retval;
191 #if HAVE_SNPRINTF
193 # if HAVE_DECL__SNPRINTF
194 /* Windows. */
195 # define system_vsnprintf _vsnprintf
196 # else
197 /* Unix. */
198 # define system_vsnprintf vsnprintf
199 # endif
201 DLL_EXPORTED
203 libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
205 if (strchr (format, '$') == NULL)
206 return system_vsnprintf (resultbuf, length, format, args);
207 else
209 size_t maxlength = length;
210 char *result = libintl_vasnprintf (resultbuf, &length, format, args);
211 if (result != resultbuf)
213 if (maxlength > 0)
215 size_t pruned_length =
216 (length < maxlength ? length : maxlength - 1);
217 memcpy (resultbuf, result, pruned_length);
218 resultbuf[pruned_length] = '\0';
220 free (result);
222 if (length > INT_MAX)
224 errno = EOVERFLOW;
225 return -1;
227 else
228 return length;
232 DLL_EXPORTED
234 libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
236 va_list args;
237 int retval;
239 va_start (args, format);
240 retval = libintl_vsnprintf (resultbuf, length, format, args);
241 va_end (args);
242 return retval;
245 #endif
247 #if HAVE_ASPRINTF
249 DLL_EXPORTED
251 libintl_vasprintf (char **resultp, const char *format, va_list args)
253 size_t length;
254 char *result = libintl_vasnprintf (NULL, &length, format, args);
255 if (result == NULL)
256 return -1;
257 if (length > INT_MAX)
259 free (result);
260 errno = EOVERFLOW;
261 return -1;
263 *resultp = result;
264 return length;
267 DLL_EXPORTED
269 libintl_asprintf (char **resultp, const char *format, ...)
271 va_list args;
272 int retval;
274 va_start (args, format);
275 retval = libintl_vasprintf (resultp, format, args);
276 va_end (args);
277 return retval;
280 #endif
282 #if HAVE_FWPRINTF
284 #include <wchar.h>
286 #define WIDE_CHAR_VERSION 1
288 /* Define auxiliary functions declared in "wprintf-parse.h". */
289 #include "printf-parse.c"
291 /* Define functions declared in "vasnprintf.h". */
292 #define vasnwprintf libintl_vasnwprintf
293 #include "vasnprintf.c"
294 #if 0 /* not needed */
295 #define asnwprintf libintl_asnwprintf
296 #include "asnprintf.c"
297 #endif
299 # if HAVE_DECL__SNWPRINTF
300 /* Windows. */
301 # define system_vswprintf _vsnwprintf
302 # else
303 /* Unix. */
304 # define system_vswprintf vswprintf
305 # endif
307 DLL_EXPORTED
309 libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
311 if (wcschr (format, '$') == NULL)
312 return vfwprintf (stream, format, args);
313 else
315 size_t length;
316 wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
317 int retval = -1;
318 if (result != NULL)
320 size_t i;
321 for (i = 0; i < length; i++)
322 if (fputwc (result[i], stream) == WEOF)
323 break;
324 free (result);
325 if (i == length)
327 if (length > INT_MAX)
328 errno = EOVERFLOW;
329 else
330 retval = length;
333 return retval;
337 DLL_EXPORTED
339 libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
341 va_list args;
342 int retval;
344 va_start (args, format);
345 retval = libintl_vfwprintf (stream, format, args);
346 va_end (args);
347 return retval;
350 DLL_EXPORTED
352 libintl_vwprintf (const wchar_t *format, va_list args)
354 return libintl_vfwprintf (stdout, format, args);
357 DLL_EXPORTED
359 libintl_wprintf (const wchar_t *format, ...)
361 va_list args;
362 int retval;
364 va_start (args, format);
365 retval = libintl_vwprintf (format, args);
366 va_end (args);
367 return retval;
370 DLL_EXPORTED
372 libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
374 if (wcschr (format, '$') == NULL)
375 return system_vswprintf (resultbuf, length, format, args);
376 else
378 size_t maxlength = length;
379 wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
380 if (result != resultbuf)
382 if (maxlength > 0)
384 size_t pruned_length =
385 (length < maxlength ? length : maxlength - 1);
386 memcpy (resultbuf, result, pruned_length * sizeof (wchar_t));
387 resultbuf[pruned_length] = 0;
389 free (result);
390 /* Unlike vsnprintf, which has to return the number of character that
391 would have been produced if the resultbuf had been sufficiently
392 large, the vswprintf function has to return a negative value if
393 the resultbuf was not sufficiently large. */
394 if (length >= maxlength)
395 return -1;
397 if (length > INT_MAX)
399 errno = EOVERFLOW;
400 return -1;
402 else
403 return length;
407 DLL_EXPORTED
409 libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
411 va_list args;
412 int retval;
414 va_start (args, format);
415 retval = libintl_vswprintf (resultbuf, length, format, args);
416 va_end (args);
417 return retval;
420 #endif
422 #endif