update gettext copy.
[apps/madmutt.git] / intl / printf.c
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.
4
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.
9
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.
14
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.  */
19
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
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
45
46 #include <stdio.h>
47
48 #if !HAVE_POSIX_PRINTF
49
50 #include <stdlib.h>
51 #include <string.h>
52
53 /* When building a DLL, we must export some functions.  Note that because
54    the functions are only defined for binary backward compatibility, we
55    don't need to use __declspec(dllimport) in any case.  */
56 #if defined _MSC_VER && BUILDING_DLL
57 # define DLL_EXPORTED __declspec(dllexport)
58 #else
59 # define DLL_EXPORTED
60 #endif
61
62 #define STATIC static
63
64 /* This needs to be consistent with libgnuintl.h.in.  */
65 #if defined __NetBSD__ || defined __CYGWIN__ || defined __MINGW32__
66 /* Don't break __attribute__((format(printf,M,N))).
67    This redefinition is only possible because the libc in NetBSD, Cygwin,
68    mingw does not have a function __printf__.  */
69 # define libintl_printf __printf__
70 #endif
71
72 /* Define auxiliary functions declared in "printf-args.h".  */
73 #include "printf-args.c"
74
75 /* Define auxiliary functions declared in "printf-parse.h".  */
76 #include "printf-parse.c"
77
78 /* Define functions declared in "vasnprintf.h".  */
79 #define vasnprintf libintl_vasnprintf
80 #include "vasnprintf.c"
81 #if 0 /* not needed */
82 #define asnprintf libintl_asnprintf
83 #include "asnprintf.c"
84 #endif
85
86 DLL_EXPORTED
87 int
88 libintl_vfprintf (FILE *stream, const char *format, va_list args)
89 {
90   if (strchr (format, '$') == NULL)
91     return vfprintf (stream, format, args);
92   else
93     {
94       size_t length;
95       char *result = libintl_vasnprintf (NULL, &length, format, args);
96       int retval = -1;
97       if (result != NULL)
98         {
99           if (fwrite (result, 1, length, stream) == length)
100             retval = length;
101           free (result);
102         }
103       return retval;
104     }
105 }
106
107 DLL_EXPORTED
108 int
109 libintl_fprintf (FILE *stream, const char *format, ...)
110 {
111   va_list args;
112   int retval;
113
114   va_start (args, format);
115   retval = libintl_vfprintf (stream, format, args);
116   va_end (args);
117   return retval;
118 }
119
120 DLL_EXPORTED
121 int
122 libintl_vprintf (const char *format, va_list args)
123 {
124   return libintl_vfprintf (stdout, format, args);
125 }
126
127 DLL_EXPORTED
128 int
129 libintl_printf (const char *format, ...)
130 {
131   va_list args;
132   int retval;
133
134   va_start (args, format);
135   retval = libintl_vprintf (format, args);
136   va_end (args);
137   return retval;
138 }
139
140 DLL_EXPORTED
141 int
142 libintl_vsprintf (char *resultbuf, const char *format, va_list args)
143 {
144   if (strchr (format, '$') == NULL)
145     return vsprintf (resultbuf, format, args);
146   else
147     {
148       size_t length = (size_t) ~0 / (4 * sizeof (char));
149       char *result = libintl_vasnprintf (resultbuf, &length, format, args);
150       if (result != resultbuf)
151         {
152           free (result);
153           return -1;
154         }
155       else
156         return length;
157     }
158 }
159
160 DLL_EXPORTED
161 int
162 libintl_sprintf (char *resultbuf, const char *format, ...)
163 {
164   va_list args;
165   int retval;
166
167   va_start (args, format);
168   retval = libintl_vsprintf (resultbuf, format, args);
169   va_end (args);
170   return retval;
171 }
172
173 #if HAVE_SNPRINTF
174
175 # if HAVE_DECL__SNPRINTF
176    /* Windows.  */
177 #  define system_vsnprintf _vsnprintf
178 # else
179    /* Unix.  */
180 #  define system_vsnprintf vsnprintf
181 # endif
182
183 DLL_EXPORTED
184 int
185 libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
186 {
187   if (strchr (format, '$') == NULL)
188     return system_vsnprintf (resultbuf, length, format, args);
189   else
190     {
191       size_t maxlength = length;
192       char *result = libintl_vasnprintf (resultbuf, &length, format, args);
193       if (result != resultbuf)
194         {
195           if (maxlength > 0)
196             {
197               if (length < maxlength)
198                 abort ();
199               memcpy (resultbuf, result, maxlength - 1);
200               resultbuf[maxlength - 1] = '\0';
201             }
202           free (result);
203           return -1;
204         }
205       else
206         return length;
207     }
208 }
209
210 DLL_EXPORTED
211 int
212 libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
213 {
214   va_list args;
215   int retval;
216
217   va_start (args, format);
218   retval = libintl_vsnprintf (resultbuf, length, format, args);
219   va_end (args);
220   return retval;
221 }
222
223 #endif
224
225 #if HAVE_ASPRINTF
226
227 DLL_EXPORTED
228 int
229 libintl_vasprintf (char **resultp, const char *format, va_list args)
230 {
231   size_t length;
232   char *result = libintl_vasnprintf (NULL, &length, format, args);
233   if (result == NULL)
234     return -1;
235   *resultp = result;
236   return length;
237 }
238
239 DLL_EXPORTED
240 int
241 libintl_asprintf (char **resultp, const char *format, ...)
242 {
243   va_list args;
244   int retval;
245
246   va_start (args, format);
247   retval = libintl_vasprintf (resultp, format, args);
248   va_end (args);
249   return retval;
250 }
251
252 #endif
253
254 #if HAVE_FWPRINTF
255
256 #include <wchar.h>
257
258 #define WIDE_CHAR_VERSION 1
259
260 /* Define auxiliary functions declared in "wprintf-parse.h".  */
261 #include "printf-parse.c"
262
263 /* Define functions declared in "vasnprintf.h".  */
264 #define vasnwprintf libintl_vasnwprintf
265 #include "vasnprintf.c"
266 #if 0 /* not needed */
267 #define asnwprintf libintl_asnwprintf
268 #include "asnprintf.c"
269 #endif
270
271 # if HAVE_DECL__SNWPRINTF
272    /* Windows.  */
273 #  define system_vswprintf _vsnwprintf
274 # else
275    /* Unix.  */
276 #  define system_vswprintf vswprintf
277 # endif
278
279 DLL_EXPORTED
280 int
281 libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
282 {
283   if (wcschr (format, '$') == NULL)
284     return vfwprintf (stream, format, args);
285   else
286     {
287       size_t length;
288       wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
289       int retval = -1;
290       if (result != NULL)
291         {
292           size_t i;
293           for (i = 0; i < length; i++)
294             if (fputwc (result[i], stream) == WEOF)
295               break;
296           if (i == length)
297             retval = length;
298           free (result);
299         }
300       return retval;
301     }
302 }
303
304 DLL_EXPORTED
305 int
306 libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
307 {
308   va_list args;
309   int retval;
310
311   va_start (args, format);
312   retval = libintl_vfwprintf (stream, format, args);
313   va_end (args);
314   return retval;
315 }
316
317 DLL_EXPORTED
318 int
319 libintl_vwprintf (const wchar_t *format, va_list args)
320 {
321   return libintl_vfwprintf (stdout, format, args);
322 }
323
324 DLL_EXPORTED
325 int
326 libintl_wprintf (const wchar_t *format, ...)
327 {
328   va_list args;
329   int retval;
330
331   va_start (args, format);
332   retval = libintl_vwprintf (format, args);
333   va_end (args);
334   return retval;
335 }
336
337 DLL_EXPORTED
338 int
339 libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
340 {
341   if (wcschr (format, '$') == NULL)
342     return system_vswprintf (resultbuf, length, format, args);
343   else
344     {
345       size_t maxlength = length;
346       wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
347       if (result != resultbuf)
348         {
349           if (maxlength > 0)
350             {
351               if (length < maxlength)
352                 abort ();
353               memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t));
354               resultbuf[maxlength - 1] = 0;
355             }
356           free (result);
357           return -1;
358         }
359       else
360         return length;
361     }
362 }
363
364 DLL_EXPORTED
365 int
366 libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
367 {
368   va_list args;
369   int retval;
370
371   va_start (args, format);
372   retval = libintl_vswprintf (resultbuf, length, format, args);
373   va_end (args);
374   return retval;
375 }
376
377 #endif
378
379 #endif