1/* Formatted output to strings, using POSIX/XSI format strings with positions.
2   Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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
39char *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/* Define auxiliary functions declared in "printf-args.h".  */
65#include "printf-args.c"
66
67/* Define auxiliary functions declared in "printf-parse.h".  */
68#include "printf-parse.c"
69
70/* Define functions declared in "vasnprintf.h".  */
71#define vasnprintf libintl_vasnprintf
72#include "vasnprintf.c"
73#if 0 /* not needed */
74#define asnprintf libintl_asnprintf
75#include "asnprintf.c"
76#endif
77
78DLL_EXPORTED
79int
80libintl_vfprintf (FILE *stream, const char *format, va_list args)
81{
82  if (strchr (format, '$') == NULL)
83    return vfprintf (stream, format, args);
84  else
85    {
86      size_t length;
87      char *result = libintl_vasnprintf (NULL, &length, format, args);
88      int retval = -1;
89      if (result != NULL)
90	{
91	  if (fwrite (result, 1, length, stream) == length)
92	    retval = length;
93	  free (result);
94	}
95      return retval;
96    }
97}
98
99DLL_EXPORTED
100int
101libintl_fprintf (FILE *stream, const char *format, ...)
102{
103  va_list args;
104  int retval;
105
106  va_start (args, format);
107  retval = libintl_vfprintf (stream, format, args);
108  va_end (args);
109  return retval;
110}
111
112DLL_EXPORTED
113int
114libintl_vprintf (const char *format, va_list args)
115{
116  return libintl_vfprintf (stdout, format, args);
117}
118
119DLL_EXPORTED
120int
121libintl_printf (const char *format, ...)
122{
123  va_list args;
124  int retval;
125
126  va_start (args, format);
127  retval = libintl_vprintf (format, args);
128  va_end (args);
129  return retval;
130}
131
132DLL_EXPORTED
133int
134libintl_vsprintf (char *resultbuf, const char *format, va_list args)
135{
136  if (strchr (format, '$') == NULL)
137    return vsprintf (resultbuf, format, args);
138  else
139    {
140      size_t length = (size_t) ~0 / (4 * sizeof (char));
141      char *result = libintl_vasnprintf (resultbuf, &length, format, args);
142      if (result != resultbuf)
143	{
144	  free (result);
145	  return -1;
146	}
147      else
148	return length;
149    }
150}
151
152DLL_EXPORTED
153int
154libintl_sprintf (char *resultbuf, const char *format, ...)
155{
156  va_list args;
157  int retval;
158
159  va_start (args, format);
160  retval = libintl_vsprintf (resultbuf, format, args);
161  va_end (args);
162  return retval;
163}
164
165#if HAVE_SNPRINTF
166
167# if HAVE_DECL__SNPRINTF
168   /* Windows.  */
169#  define system_vsnprintf _vsnprintf
170# else
171   /* Unix.  */
172#  define system_vsnprintf vsnprintf
173# endif
174
175DLL_EXPORTED
176int
177libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
178{
179  if (strchr (format, '$') == NULL)
180    return system_vsnprintf (resultbuf, length, format, args);
181  else
182    {
183      size_t maxlength = length;
184      char *result = libintl_vasnprintf (resultbuf, &length, format, args);
185      if (result != resultbuf)
186	{
187	  if (maxlength > 0)
188	    {
189	      if (length < maxlength)
190		abort ();
191	      memcpy (resultbuf, result, maxlength - 1);
192	      resultbuf[maxlength - 1] = '\0';
193	    }
194	  free (result);
195	  return -1;
196	}
197      else
198	return length;
199    }
200}
201
202DLL_EXPORTED
203int
204libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
205{
206  va_list args;
207  int retval;
208
209  va_start (args, format);
210  retval = libintl_vsnprintf (resultbuf, length, format, args);
211  va_end (args);
212  return retval;
213}
214
215#endif
216
217#if HAVE_ASPRINTF
218
219DLL_EXPORTED
220int
221libintl_vasprintf (char **resultp, const char *format, va_list args)
222{
223  size_t length;
224  char *result = libintl_vasnprintf (NULL, &length, format, args);
225  if (result == NULL)
226    return -1;
227  *resultp = result;
228  return length;
229}
230
231DLL_EXPORTED
232int
233libintl_asprintf (char **resultp, const char *format, ...)
234{
235  va_list args;
236  int retval;
237
238  va_start (args, format);
239  retval = libintl_vasprintf (resultp, format, args);
240  va_end (args);
241  return retval;
242}
243
244#endif
245
246#if HAVE_FWPRINTF
247
248#include <wchar.h>
249
250#define WIDE_CHAR_VERSION 1
251
252/* Define auxiliary functions declared in "wprintf-parse.h".  */
253#include "printf-parse.c"
254
255/* Define functions declared in "vasnprintf.h".  */
256#define vasnwprintf libintl_vasnwprintf
257#include "vasnprintf.c"
258#if 0 /* not needed */
259#define asnwprintf libintl_asnwprintf
260#include "asnprintf.c"
261#endif
262
263# if HAVE_DECL__SNWPRINTF
264   /* Windows.  */
265#  define system_vswprintf _vsnwprintf
266# else
267   /* Unix.  */
268#  define system_vswprintf vswprintf
269# endif
270
271DLL_EXPORTED
272int
273libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
274{
275  if (wcschr (format, '$') == NULL)
276    return vfwprintf (stream, format, args);
277  else
278    {
279      size_t length;
280      wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
281      int retval = -1;
282      if (result != NULL)
283	{
284	  size_t i;
285	  for (i = 0; i < length; i++)
286	    if (fputwc (result[i], stream) == WEOF)
287	      break;
288	  if (i == length)
289	    retval = length;
290	  free (result);
291	}
292      return retval;
293    }
294}
295
296DLL_EXPORTED
297int
298libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
299{
300  va_list args;
301  int retval;
302
303  va_start (args, format);
304  retval = libintl_vfwprintf (stream, format, args);
305  va_end (args);
306  return retval;
307}
308
309DLL_EXPORTED
310int
311libintl_vwprintf (const wchar_t *format, va_list args)
312{
313  return libintl_vfwprintf (stdout, format, args);
314}
315
316DLL_EXPORTED
317int
318libintl_wprintf (const wchar_t *format, ...)
319{
320  va_list args;
321  int retval;
322
323  va_start (args, format);
324  retval = libintl_vwprintf (format, args);
325  va_end (args);
326  return retval;
327}
328
329DLL_EXPORTED
330int
331libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
332{
333  if (wcschr (format, '$') == NULL)
334    return system_vswprintf (resultbuf, length, format, args);
335  else
336    {
337      size_t maxlength = length;
338      wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
339      if (result != resultbuf)
340	{
341	  if (maxlength > 0)
342	    {
343	      if (length < maxlength)
344		abort ();
345	      memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t));
346	      resultbuf[maxlength - 1] = 0;
347	    }
348	  free (result);
349	  return -1;
350	}
351      else
352	return length;
353    }
354}
355
356DLL_EXPORTED
357int
358libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
359{
360  va_list args;
361  int retval;
362
363  va_start (args, format);
364  retval = libintl_vswprintf (resultbuf, length, format, args);
365  va_end (args);
366  return retval;
367}
368
369#endif
370
371#endif
372