xref: /openbsd/gnu/usr.bin/texinfo/intl/printf.c (revision a1acfa9b)
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
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 /* 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 
78 DLL_EXPORTED
79 int
libintl_vfprintf(FILE * stream,const char * format,va_list args)80 libintl_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 
99 DLL_EXPORTED
100 int
libintl_fprintf(FILE * stream,const char * format,...)101 libintl_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 
112 DLL_EXPORTED
113 int
libintl_vprintf(const char * format,va_list args)114 libintl_vprintf (const char *format, va_list args)
115 {
116   return libintl_vfprintf (stdout, format, args);
117 }
118 
119 DLL_EXPORTED
120 int
libintl_printf(const char * format,...)121 libintl_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 
132 DLL_EXPORTED
133 int
libintl_vsprintf(char * resultbuf,const char * format,va_list args)134 libintl_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 
152 DLL_EXPORTED
153 int
libintl_sprintf(char * resultbuf,const char * format,...)154 libintl_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 
175 DLL_EXPORTED
176 int
libintl_vsnprintf(char * resultbuf,size_t length,const char * format,va_list args)177 libintl_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 
202 DLL_EXPORTED
203 int
libintl_snprintf(char * resultbuf,size_t length,const char * format,...)204 libintl_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 
219 DLL_EXPORTED
220 int
libintl_vasprintf(char ** resultp,const char * format,va_list args)221 libintl_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 
231 DLL_EXPORTED
232 int
libintl_asprintf(char ** resultp,const char * format,...)233 libintl_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 
271 DLL_EXPORTED
272 int
libintl_vfwprintf(FILE * stream,const wchar_t * format,va_list args)273 libintl_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 
296 DLL_EXPORTED
297 int
libintl_fwprintf(FILE * stream,const wchar_t * format,...)298 libintl_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 
309 DLL_EXPORTED
310 int
libintl_vwprintf(const wchar_t * format,va_list args)311 libintl_vwprintf (const wchar_t *format, va_list args)
312 {
313   return libintl_vfwprintf (stdout, format, args);
314 }
315 
316 DLL_EXPORTED
317 int
libintl_wprintf(const wchar_t * format,...)318 libintl_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 
329 DLL_EXPORTED
330 int
libintl_vswprintf(wchar_t * resultbuf,size_t length,const wchar_t * format,va_list args)331 libintl_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 
356 DLL_EXPORTED
357 int
libintl_swprintf(wchar_t * resultbuf,size_t length,const wchar_t * format,...)358 libintl_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