Newer gettext
[gliv.git] / intl / printf.c
blobb7cdc5d82a0f7a865886db4305c6d9d9f70aed67
1 /* Formatted output to strings, using POSIX/XSI format strings with positions.
2 Copyright (C) 2003, 2006-2007, 2009 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 HAVE_VISIBILITY && BUILDING_DLL
64 # define DLL_EXPORTED __attribute__((__visibility__("default")))
65 #elif defined _MSC_VER && BUILDING_DLL
66 # define DLL_EXPORTED __declspec(dllexport)
67 #else
68 # define DLL_EXPORTED
69 #endif
71 #define STATIC static
73 /* This needs to be consistent with libgnuintl.h.in. */
74 #if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__
75 /* Don't break __attribute__((format(printf,M,N))).
76 This redefinition is only possible because the libc in NetBSD, Cygwin,
77 mingw does not have a function __printf__. */
78 # define libintl_printf __printf__
79 #endif
81 /* Define auxiliary functions declared in "printf-args.h". */
82 #include "printf-args.c"
84 /* Define auxiliary functions declared in "printf-parse.h". */
85 #include "printf-parse.c"
87 /* Define functions declared in "vasnprintf.h". */
88 #define vasnprintf libintl_vasnprintf
89 #include "vasnprintf.c"
90 #if 0 /* not needed */
91 #define asnprintf libintl_asnprintf
92 #include "asnprintf.c"
93 #endif
95 DLL_EXPORTED
96 int
97 libintl_vfprintf (FILE *stream, const char *format, va_list args)
99 if (strchr (format, '$') == NULL)
100 return vfprintf (stream, format, args);
101 else
103 size_t length;
104 char *result = libintl_vasnprintf (NULL, &length, format, args);
105 int retval = -1;
106 if (result != NULL)
108 size_t written = fwrite (result, 1, length, stream);
109 free (result);
110 if (written == length)
112 if (length > INT_MAX)
113 errno = EOVERFLOW;
114 else
115 retval = length;
118 return retval;
122 DLL_EXPORTED
124 libintl_fprintf (FILE *stream, const char *format, ...)
126 va_list args;
127 int retval;
129 va_start (args, format);
130 retval = libintl_vfprintf (stream, format, args);
131 va_end (args);
132 return retval;
135 DLL_EXPORTED
137 libintl_vprintf (const char *format, va_list args)
139 return libintl_vfprintf (stdout, format, args);
142 DLL_EXPORTED
144 libintl_printf (const char *format, ...)
146 va_list args;
147 int retval;
149 va_start (args, format);
150 retval = libintl_vprintf (format, args);
151 va_end (args);
152 return retval;
155 DLL_EXPORTED
157 libintl_vsprintf (char *resultbuf, const char *format, va_list args)
159 if (strchr (format, '$') == NULL)
160 return vsprintf (resultbuf, format, args);
161 else
163 size_t length = (size_t) ~0 / (4 * sizeof (char));
164 char *result = libintl_vasnprintf (resultbuf, &length, format, args);
165 if (result != resultbuf)
167 free (result);
168 return -1;
170 if (length > INT_MAX)
172 errno = EOVERFLOW;
173 return -1;
175 else
176 return length;
180 DLL_EXPORTED
182 libintl_sprintf (char *resultbuf, const char *format, ...)
184 va_list args;
185 int retval;
187 va_start (args, format);
188 retval = libintl_vsprintf (resultbuf, format, args);
189 va_end (args);
190 return retval;
193 #if HAVE_SNPRINTF
195 # if HAVE_DECL__SNPRINTF
196 /* Windows. */
197 # define system_vsnprintf _vsnprintf
198 # else
199 /* Unix. */
200 # define system_vsnprintf vsnprintf
201 # endif
203 DLL_EXPORTED
205 libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
207 if (strchr (format, '$') == NULL)
208 return system_vsnprintf (resultbuf, length, format, args);
209 else
211 size_t maxlength = length;
212 char *result = libintl_vasnprintf (resultbuf, &length, format, args);
213 if (result != resultbuf)
215 if (maxlength > 0)
217 size_t pruned_length =
218 (length < maxlength ? length : maxlength - 1);
219 memcpy (resultbuf, result, pruned_length);
220 resultbuf[pruned_length] = '\0';
222 free (result);
224 if (length > INT_MAX)
226 errno = EOVERFLOW;
227 return -1;
229 else
230 return length;
234 DLL_EXPORTED
236 libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
238 va_list args;
239 int retval;
241 va_start (args, format);
242 retval = libintl_vsnprintf (resultbuf, length, format, args);
243 va_end (args);
244 return retval;
247 #endif
249 #if HAVE_ASPRINTF
251 DLL_EXPORTED
253 libintl_vasprintf (char **resultp, const char *format, va_list args)
255 size_t length;
256 char *result = libintl_vasnprintf (NULL, &length, format, args);
257 if (result == NULL)
258 return -1;
259 if (length > INT_MAX)
261 free (result);
262 errno = EOVERFLOW;
263 return -1;
265 *resultp = result;
266 return length;
269 DLL_EXPORTED
271 libintl_asprintf (char **resultp, const char *format, ...)
273 va_list args;
274 int retval;
276 va_start (args, format);
277 retval = libintl_vasprintf (resultp, format, args);
278 va_end (args);
279 return retval;
282 #endif
284 #if HAVE_FWPRINTF
286 #include <wchar.h>
288 #define WIDE_CHAR_VERSION 1
290 #include "wprintf-parse.h"
291 /* Define auxiliary functions declared in "wprintf-parse.h". */
292 #define CHAR_T wchar_t
293 #define DIRECTIVE wchar_t_directive
294 #define DIRECTIVES wchar_t_directives
295 #define PRINTF_PARSE wprintf_parse
296 #include "printf-parse.c"
298 /* Define functions declared in "vasnprintf.h". */
299 #define vasnwprintf libintl_vasnwprintf
300 #include "vasnprintf.c"
301 #if 0 /* not needed */
302 #define asnwprintf libintl_asnwprintf
303 #include "asnprintf.c"
304 #endif
306 # if HAVE_DECL__SNWPRINTF
307 /* Windows. */
308 # define system_vswprintf _vsnwprintf
309 # else
310 /* Unix. */
311 # define system_vswprintf vswprintf
312 # endif
314 DLL_EXPORTED
316 libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
318 if (wcschr (format, '$') == NULL)
319 return vfwprintf (stream, format, args);
320 else
322 size_t length;
323 wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
324 int retval = -1;
325 if (result != NULL)
327 size_t i;
328 for (i = 0; i < length; i++)
329 if (fputwc (result[i], stream) == WEOF)
330 break;
331 free (result);
332 if (i == length)
334 if (length > INT_MAX)
335 errno = EOVERFLOW;
336 else
337 retval = length;
340 return retval;
344 DLL_EXPORTED
346 libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
348 va_list args;
349 int retval;
351 va_start (args, format);
352 retval = libintl_vfwprintf (stream, format, args);
353 va_end (args);
354 return retval;
357 DLL_EXPORTED
359 libintl_vwprintf (const wchar_t *format, va_list args)
361 return libintl_vfwprintf (stdout, format, args);
364 DLL_EXPORTED
366 libintl_wprintf (const wchar_t *format, ...)
368 va_list args;
369 int retval;
371 va_start (args, format);
372 retval = libintl_vwprintf (format, args);
373 va_end (args);
374 return retval;
377 DLL_EXPORTED
379 libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
381 if (wcschr (format, '$') == NULL)
382 return system_vswprintf (resultbuf, length, format, args);
383 else
385 size_t maxlength = length;
386 wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
387 if (result != resultbuf)
389 if (maxlength > 0)
391 size_t pruned_length =
392 (length < maxlength ? length : maxlength - 1);
393 memcpy (resultbuf, result, pruned_length * sizeof (wchar_t));
394 resultbuf[pruned_length] = 0;
396 free (result);
397 /* Unlike vsnprintf, which has to return the number of character that
398 would have been produced if the resultbuf had been sufficiently
399 large, the vswprintf function has to return a negative value if
400 the resultbuf was not sufficiently large. */
401 if (length >= maxlength)
402 return -1;
404 if (length > INT_MAX)
406 errno = EOVERFLOW;
407 return -1;
409 else
410 return length;
414 DLL_EXPORTED
416 libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
418 va_list args;
419 int retval;
421 va_start (args, format);
422 retval = libintl_vswprintf (resultbuf, length, format, args);
423 va_end (args);
424 return retval;
427 #endif
429 #endif