Back to index

courier  0.68.2
printf.c
Go to the documentation of this file.
00001 /* Formatted output to strings, using POSIX/XSI format strings with positions.
00002    Copyright (C) 2003, 2006-2007, 2009 Free Software Foundation, Inc.
00003    Written by Bruno Haible <bruno@clisp.org>, 2003.
00004 
00005    This program is free software; you can redistribute it and/or modify it
00006    under the terms of the GNU Library General Public License as published
00007    by the Free Software Foundation; either version 2, or (at your option)
00008    any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this program; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00018    USA.  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023 
00024 #ifdef __GNUC__
00025 # define alloca __builtin_alloca
00026 # define HAVE_ALLOCA 1
00027 #else
00028 # ifdef _MSC_VER
00029 #  include <malloc.h>
00030 #  define alloca _alloca
00031 # else
00032 #  if defined HAVE_ALLOCA_H || defined _LIBC
00033 #   include <alloca.h>
00034 #  else
00035 #   ifdef _AIX
00036  #pragma alloca
00037 #   else
00038 #    ifndef alloca
00039 char *alloca ();
00040 #    endif
00041 #   endif
00042 #  endif
00043 # endif
00044 #endif
00045 
00046 #include <stdio.h>
00047 
00048 #if !HAVE_POSIX_PRINTF
00049 
00050 #include <errno.h>
00051 #include <limits.h>
00052 #include <stdlib.h>
00053 #include <string.h>
00054 
00055 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
00056 #ifndef EOVERFLOW
00057 # define EOVERFLOW E2BIG
00058 #endif
00059 
00060 /* When building a DLL, we must export some functions.  Note that because
00061    the functions are only defined for binary backward compatibility, we
00062    don't need to use __declspec(dllimport) in any case.  */
00063 #if HAVE_VISIBILITY && BUILDING_DLL
00064 # define DLL_EXPORTED __attribute__((__visibility__("default")))
00065 #elif defined _MSC_VER && BUILDING_DLL
00066 # define DLL_EXPORTED __declspec(dllexport)
00067 #else
00068 # define DLL_EXPORTED
00069 #endif
00070 
00071 #define STATIC static
00072 
00073 /* This needs to be consistent with libgnuintl.h.in.  */
00074 #if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__
00075 /* Don't break __attribute__((format(printf,M,N))).
00076    This redefinition is only possible because the libc in NetBSD, Cygwin,
00077    mingw does not have a function __printf__.  */
00078 # define libintl_printf __printf__
00079 #endif
00080 
00081 /* Define auxiliary functions declared in "printf-args.h".  */
00082 #include "printf-args.c"
00083 
00084 /* Define auxiliary functions declared in "printf-parse.h".  */
00085 #include "printf-parse.c"
00086 
00087 /* Define functions declared in "vasnprintf.h".  */
00088 #define vasnprintf libintl_vasnprintf
00089 #include "vasnprintf.c"
00090 #if 0 /* not needed */
00091 #define asnprintf libintl_asnprintf
00092 #include "asnprintf.c"
00093 #endif
00094 
00095 DLL_EXPORTED
00096 int
00097 libintl_vfprintf (FILE *stream, const char *format, va_list args)
00098 {
00099   if (strchr (format, '$') == NULL)
00100     return vfprintf (stream, format, args);
00101   else
00102     {
00103       size_t length;
00104       char *result = libintl_vasnprintf (NULL, &length, format, args);
00105       int retval = -1;
00106       if (result != NULL)
00107         {
00108           size_t written = fwrite (result, 1, length, stream);
00109           free (result);
00110           if (written == length)
00111             {
00112               if (length > INT_MAX)
00113                 errno = EOVERFLOW;
00114               else
00115                 retval = length;
00116             }
00117         }
00118       return retval;
00119     }
00120 }
00121 
00122 DLL_EXPORTED
00123 int
00124 libintl_fprintf (FILE *stream, const char *format, ...)
00125 {
00126   va_list args;
00127   int retval;
00128 
00129   va_start (args, format);
00130   retval = libintl_vfprintf (stream, format, args);
00131   va_end (args);
00132   return retval;
00133 }
00134 
00135 DLL_EXPORTED
00136 int
00137 libintl_vprintf (const char *format, va_list args)
00138 {
00139   return libintl_vfprintf (stdout, format, args);
00140 }
00141 
00142 DLL_EXPORTED
00143 int
00144 libintl_printf (const char *format, ...)
00145 {
00146   va_list args;
00147   int retval;
00148 
00149   va_start (args, format);
00150   retval = libintl_vprintf (format, args);
00151   va_end (args);
00152   return retval;
00153 }
00154 
00155 DLL_EXPORTED
00156 int
00157 libintl_vsprintf (char *resultbuf, const char *format, va_list args)
00158 {
00159   if (strchr (format, '$') == NULL)
00160     return vsprintf (resultbuf, format, args);
00161   else
00162     {
00163       size_t length = (size_t) ~0 / (4 * sizeof (char));
00164       char *result = libintl_vasnprintf (resultbuf, &length, format, args);
00165       if (result != resultbuf)
00166         {
00167           free (result);
00168           return -1;
00169         }
00170       if (length > INT_MAX)
00171         {
00172           errno = EOVERFLOW;
00173           return -1;
00174         }
00175       else
00176         return length;
00177     }
00178 }
00179 
00180 DLL_EXPORTED
00181 int
00182 libintl_sprintf (char *resultbuf, const char *format, ...)
00183 {
00184   va_list args;
00185   int retval;
00186 
00187   va_start (args, format);
00188   retval = libintl_vsprintf (resultbuf, format, args);
00189   va_end (args);
00190   return retval;
00191 }
00192 
00193 #if HAVE_SNPRINTF
00194 
00195 # if HAVE_DECL__SNPRINTF
00196    /* Windows.  */
00197 #  define system_vsnprintf _vsnprintf
00198 # else
00199    /* Unix.  */
00200 #  define system_vsnprintf vsnprintf
00201 # endif
00202 
00203 DLL_EXPORTED
00204 int
00205 libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
00206 {
00207   if (strchr (format, '$') == NULL)
00208     return system_vsnprintf (resultbuf, length, format, args);
00209   else
00210     {
00211       size_t maxlength = length;
00212       char *result = libintl_vasnprintf (resultbuf, &length, format, args);
00213       if (result != resultbuf)
00214         {
00215           if (maxlength > 0)
00216             {
00217               size_t pruned_length =
00218                 (length < maxlength ? length : maxlength - 1);
00219               memcpy (resultbuf, result, pruned_length);
00220               resultbuf[pruned_length] = '\0';
00221             }
00222           free (result);
00223         }
00224       if (length > INT_MAX)
00225         {
00226           errno = EOVERFLOW;
00227           return -1;
00228         }
00229       else
00230         return length;
00231     }
00232 }
00233 
00234 DLL_EXPORTED
00235 int
00236 libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
00237 {
00238   va_list args;
00239   int retval;
00240 
00241   va_start (args, format);
00242   retval = libintl_vsnprintf (resultbuf, length, format, args);
00243   va_end (args);
00244   return retval;
00245 }
00246 
00247 #endif
00248 
00249 #if HAVE_ASPRINTF
00250 
00251 DLL_EXPORTED
00252 int
00253 libintl_vasprintf (char **resultp, const char *format, va_list args)
00254 {
00255   size_t length;
00256   char *result = libintl_vasnprintf (NULL, &length, format, args);
00257   if (result == NULL)
00258     return -1;
00259   if (length > INT_MAX)
00260     {
00261       free (result);
00262       errno = EOVERFLOW;
00263       return -1;
00264     }
00265   *resultp = result;
00266   return length;
00267 }
00268 
00269 DLL_EXPORTED
00270 int
00271 libintl_asprintf (char **resultp, const char *format, ...)
00272 {
00273   va_list args;
00274   int retval;
00275 
00276   va_start (args, format);
00277   retval = libintl_vasprintf (resultp, format, args);
00278   va_end (args);
00279   return retval;
00280 }
00281 
00282 #endif
00283 
00284 #if HAVE_FWPRINTF
00285 
00286 #include <wchar.h>
00287 
00288 #define WIDE_CHAR_VERSION 1
00289 
00290 #include "wprintf-parse.h"
00291 /* Define auxiliary functions declared in "wprintf-parse.h".  */
00292 #define CHAR_T wchar_t
00293 #define DIRECTIVE wchar_t_directive
00294 #define DIRECTIVES wchar_t_directives
00295 #define PRINTF_PARSE wprintf_parse
00296 #include "printf-parse.c"
00297 
00298 /* Define functions declared in "vasnprintf.h".  */
00299 #define vasnwprintf libintl_vasnwprintf
00300 #include "vasnprintf.c"
00301 #if 0 /* not needed */
00302 #define asnwprintf libintl_asnwprintf
00303 #include "asnprintf.c"
00304 #endif
00305 
00306 # if HAVE_DECL__SNWPRINTF
00307    /* Windows.  */
00308 #  define system_vswprintf _vsnwprintf
00309 # else
00310    /* Unix.  */
00311 #  define system_vswprintf vswprintf
00312 # endif
00313 
00314 DLL_EXPORTED
00315 int
00316 libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
00317 {
00318   if (wcschr (format, '$') == NULL)
00319     return vfwprintf (stream, format, args);
00320   else
00321     {
00322       size_t length;
00323       wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
00324       int retval = -1;
00325       if (result != NULL)
00326         {
00327           size_t i;
00328           for (i = 0; i < length; i++)
00329             if (fputwc (result[i], stream) == WEOF)
00330               break;
00331           free (result);
00332           if (i == length)
00333             {
00334               if (length > INT_MAX)
00335                 errno = EOVERFLOW;
00336               else
00337                 retval = length;
00338             }
00339         }
00340       return retval;
00341     }
00342 }
00343 
00344 DLL_EXPORTED
00345 int
00346 libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
00347 {
00348   va_list args;
00349   int retval;
00350 
00351   va_start (args, format);
00352   retval = libintl_vfwprintf (stream, format, args);
00353   va_end (args);
00354   return retval;
00355 }
00356 
00357 DLL_EXPORTED
00358 int
00359 libintl_vwprintf (const wchar_t *format, va_list args)
00360 {
00361   return libintl_vfwprintf (stdout, format, args);
00362 }
00363 
00364 DLL_EXPORTED
00365 int
00366 libintl_wprintf (const wchar_t *format, ...)
00367 {
00368   va_list args;
00369   int retval;
00370 
00371   va_start (args, format);
00372   retval = libintl_vwprintf (format, args);
00373   va_end (args);
00374   return retval;
00375 }
00376 
00377 DLL_EXPORTED
00378 int
00379 libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
00380 {
00381   if (wcschr (format, '$') == NULL)
00382     return system_vswprintf (resultbuf, length, format, args);
00383   else
00384     {
00385       size_t maxlength = length;
00386       wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
00387       if (result != resultbuf)
00388         {
00389           if (maxlength > 0)
00390             {
00391               size_t pruned_length =
00392                 (length < maxlength ? length : maxlength - 1);
00393               memcpy (resultbuf, result, pruned_length * sizeof (wchar_t));
00394               resultbuf[pruned_length] = 0;
00395             }
00396           free (result);
00397           /* Unlike vsnprintf, which has to return the number of character that
00398              would have been produced if the resultbuf had been sufficiently
00399              large, the vswprintf function has to return a negative value if
00400              the resultbuf was not sufficiently large.  */
00401           if (length >= maxlength)
00402             return -1;
00403         }
00404       if (length > INT_MAX)
00405         {
00406           errno = EOVERFLOW;
00407           return -1;
00408         }
00409       else
00410         return length;
00411     }
00412 }
00413 
00414 DLL_EXPORTED
00415 int
00416 libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
00417 {
00418   va_list args;
00419   int retval;
00420 
00421   va_start (args, format);
00422   retval = libintl_vswprintf (resultbuf, length, format, args);
00423   va_end (args);
00424   return retval;
00425 }
00426 
00427 #endif
00428 
00429 #endif