Rev 41539 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/* Formatted output to strings, using POSIX/XSI format strings with positions.Copyright (C) 2003, 2006 Free Software Foundation, Inc.Written by Bruno Haible <bruno@clisp.org>, 2003.This program is free software; you can redistribute it and/or modify itunder the terms of the GNU Library General Public License as publishedby 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULibrary General Public License for more details.You should have received a copy of the GNU Library General PublicLicense along with this program; if not, write to the Free SoftwareFoundation, 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 allocachar *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 becausethe functions are only defined for binary backward compatibility, wedon'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 __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"#endifDLL_EXPORTEDintlibintl_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;elseretval = length;}}return retval;}}DLL_EXPORTEDintlibintl_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_EXPORTEDintlibintl_vprintf (const char *format, va_list args){return libintl_vfprintf (stdout, format, args);}DLL_EXPORTEDintlibintl_printf (const char *format, ...){va_list args;int retval;va_start (args, format);retval = libintl_vprintf (format, args);va_end (args);return retval;}DLL_EXPORTEDintlibintl_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;}elsereturn length;}}DLL_EXPORTEDintlibintl_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# endifDLL_EXPORTEDintlibintl_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;}elsereturn length;}}DLL_EXPORTEDintlibintl_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_ASPRINTFDLL_EXPORTEDintlibintl_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_EXPORTEDintlibintl_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/* Define auxiliary functions declared in "wprintf-parse.h". */#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# endifDLL_EXPORTEDintlibintl_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;elseretval = length;}}return retval;}}DLL_EXPORTEDintlibintl_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_EXPORTEDintlibintl_vwprintf (const wchar_t *format, va_list args){return libintl_vfwprintf (stdout, format, args);}DLL_EXPORTEDintlibintl_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_EXPORTEDintlibintl_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 thatwould have been produced if the resultbuf had been sufficientlylarge, the vswprintf function has to return a negative value ifthe resultbuf was not sufficiently large. */if (length >= maxlength)return -1;}if (length > INT_MAX){errno = EOVERFLOW;return -1;}elsereturn length;}}DLL_EXPORTEDintlibintl_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