/hunspell-1.3.2/intl/printf.c
C | 427 lines | 339 code | 49 blank | 39 comment | 46 complexity | 3beb97c21416071fa2a8fdb740273870 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1
- /* Formatted output to strings, using POSIX/XSI format strings with positions.
- Copyright (C) 2003, 2006-2007 Free Software Foundation, Inc.
- Written by Bruno Haible <bruno@clisp.org>, 2003.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- USA. */
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #ifdef __GNUC__
- # define alloca __builtin_alloca
- # define HAVE_ALLOCA 1
- #else
- # ifdef _MSC_VER
- # include <malloc.h>
- # define alloca _alloca
- # else
- # if defined HAVE_ALLOCA_H || defined _LIBC
- # include <alloca.h>
- # else
- # ifdef _AIX
- #pragma alloca
- # else
- # ifndef alloca
- char *alloca ();
- # endif
- # endif
- # endif
- # endif
- #endif
- #include <stdio.h>
- #if !HAVE_POSIX_PRINTF
- #include <errno.h>
- #include <limits.h>
- #include <stdlib.h>
- #include <string.h>
- /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
- #ifndef EOVERFLOW
- # define EOVERFLOW E2BIG
- #endif
- /* When building a DLL, we must export some functions. Note that because
- the functions are only defined for binary backward compatibility, we
- don't need to use __declspec(dllimport) in any case. */
- #if defined _MSC_VER && BUILDING_DLL
- # define DLL_EXPORTED __declspec(dllexport)
- #else
- # define DLL_EXPORTED
- #endif
- #define STATIC static
- /* This needs to be consistent with libgnuintl.h.in. */
- #if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__
- /* Don't break __attribute__((format(printf,M,N))).
- This redefinition is only possible because the libc in NetBSD, Cygwin,
- mingw does not have a function __printf__. */
- # define libintl_printf __printf__
- #endif
- /* Define auxiliary functions declared in "printf-args.h". */
- #include "printf-args.c"
- /* Define auxiliary functions declared in "printf-parse.h". */
- #include "printf-parse.c"
- /* Define functions declared in "vasnprintf.h". */
- #define vasnprintf libintl_vasnprintf
- #include "vasnprintf.c"
- #if 0 /* not needed */
- #define asnprintf libintl_asnprintf
- #include "asnprintf.c"
- #endif
- DLL_EXPORTED
- int
- libintl_vfprintf (FILE *stream, const char *format, va_list args)
- {
- if (strchr (format, '$') == NULL)
- return vfprintf (stream, format, args);
- else
- {
- size_t length;
- char *result = libintl_vasnprintf (NULL, &length, format, args);
- int retval = -1;
- if (result != NULL)
- {
- size_t written = fwrite (result, 1, length, stream);
- free (result);
- if (written == length)
- {
- if (length > INT_MAX)
- errno = EOVERFLOW;
- else
- retval = length;
- }
- }
- return retval;
- }
- }
- DLL_EXPORTED
- int
- libintl_fprintf (FILE *stream, const char *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vfprintf (stream, format, args);
- va_end (args);
- return retval;
- }
- DLL_EXPORTED
- int
- libintl_vprintf (const char *format, va_list args)
- {
- return libintl_vfprintf (stdout, format, args);
- }
- DLL_EXPORTED
- int
- libintl_printf (const char *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vprintf (format, args);
- va_end (args);
- return retval;
- }
- DLL_EXPORTED
- int
- libintl_vsprintf (char *resultbuf, const char *format, va_list args)
- {
- if (strchr (format, '$') == NULL)
- return vsprintf (resultbuf, format, args);
- else
- {
- size_t length = (size_t) ~0 / (4 * sizeof (char));
- char *result = libintl_vasnprintf (resultbuf, &length, format, args);
- if (result != resultbuf)
- {
- free (result);
- return -1;
- }
- if (length > INT_MAX)
- {
- errno = EOVERFLOW;
- return -1;
- }
- else
- return length;
- }
- }
- DLL_EXPORTED
- int
- libintl_sprintf (char *resultbuf, const char *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vsprintf (resultbuf, format, args);
- va_end (args);
- return retval;
- }
- #if HAVE_SNPRINTF
- # if HAVE_DECL__SNPRINTF
- /* Windows. */
- # define system_vsnprintf _vsnprintf
- # else
- /* Unix. */
- # define system_vsnprintf vsnprintf
- # endif
- DLL_EXPORTED
- int
- libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
- {
- if (strchr (format, '$') == NULL)
- return system_vsnprintf (resultbuf, length, format, args);
- else
- {
- size_t maxlength = length;
- char *result = libintl_vasnprintf (resultbuf, &length, format, args);
- if (result != resultbuf)
- {
- if (maxlength > 0)
- {
- size_t pruned_length =
- (length < maxlength ? length : maxlength - 1);
- memcpy (resultbuf, result, pruned_length);
- resultbuf[pruned_length] = '\0';
- }
- free (result);
- }
- if (length > INT_MAX)
- {
- errno = EOVERFLOW;
- return -1;
- }
- else
- return length;
- }
- }
- DLL_EXPORTED
- int
- libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vsnprintf (resultbuf, length, format, args);
- va_end (args);
- return retval;
- }
- #endif
- #if HAVE_ASPRINTF
- DLL_EXPORTED
- int
- libintl_vasprintf (char **resultp, const char *format, va_list args)
- {
- size_t length;
- char *result = libintl_vasnprintf (NULL, &length, format, args);
- if (result == NULL)
- return -1;
- if (length > INT_MAX)
- {
- free (result);
- errno = EOVERFLOW;
- return -1;
- }
- *resultp = result;
- return length;
- }
- DLL_EXPORTED
- int
- libintl_asprintf (char **resultp, const char *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vasprintf (resultp, format, args);
- va_end (args);
- return retval;
- }
- #endif
- #if HAVE_FWPRINTF
- #include <wchar.h>
- #define WIDE_CHAR_VERSION 1
- #include "wprintf-parse.h"
- /* Define auxiliary functions declared in "wprintf-parse.h". */
- #define CHAR_T wchar_t
- #define DIRECTIVE wchar_t_directive
- #define DIRECTIVES wchar_t_directives
- #define PRINTF_PARSE wprintf_parse
- #include "printf-parse.c"
- /* Define functions declared in "vasnprintf.h". */
- #define vasnwprintf libintl_vasnwprintf
- #include "vasnprintf.c"
- #if 0 /* not needed */
- #define asnwprintf libintl_asnwprintf
- #include "asnprintf.c"
- #endif
- # if HAVE_DECL__SNWPRINTF
- /* Windows. */
- # define system_vswprintf _vsnwprintf
- # else
- /* Unix. */
- # define system_vswprintf vswprintf
- # endif
- DLL_EXPORTED
- int
- libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
- {
- if (wcschr (format, '$') == NULL)
- return vfwprintf (stream, format, args);
- else
- {
- size_t length;
- wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
- int retval = -1;
- if (result != NULL)
- {
- size_t i;
- for (i = 0; i < length; i++)
- if (fputwc (result[i], stream) == WEOF)
- break;
- free (result);
- if (i == length)
- {
- if (length > INT_MAX)
- errno = EOVERFLOW;
- else
- retval = length;
- }
- }
- return retval;
- }
- }
- DLL_EXPORTED
- int
- libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vfwprintf (stream, format, args);
- va_end (args);
- return retval;
- }
- DLL_EXPORTED
- int
- libintl_vwprintf (const wchar_t *format, va_list args)
- {
- return libintl_vfwprintf (stdout, format, args);
- }
- DLL_EXPORTED
- int
- libintl_wprintf (const wchar_t *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vwprintf (format, args);
- va_end (args);
- return retval;
- }
- DLL_EXPORTED
- int
- libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
- {
- if (wcschr (format, '$') == NULL)
- return system_vswprintf (resultbuf, length, format, args);
- else
- {
- size_t maxlength = length;
- wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
- if (result != resultbuf)
- {
- if (maxlength > 0)
- {
- size_t pruned_length =
- (length < maxlength ? length : maxlength - 1);
- memcpy (resultbuf, result, pruned_length * sizeof (wchar_t));
- resultbuf[pruned_length] = 0;
- }
- free (result);
- /* Unlike vsnprintf, which has to return the number of character that
- would have been produced if the resultbuf had been sufficiently
- large, the vswprintf function has to return a negative value if
- the resultbuf was not sufficiently large. */
- if (length >= maxlength)
- return -1;
- }
- if (length > INT_MAX)
- {
- errno = EOVERFLOW;
- return -1;
- }
- else
- return length;
- }
- }
- DLL_EXPORTED
- int
- libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
- {
- va_list args;
- int retval;
- va_start (args, format);
- retval = libintl_vswprintf (resultbuf, length, format, args);
- va_end (args);
- return retval;
- }
- #endif
- #endif