with positions, for those systems that lack it (NetBSD, Woe32).
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * PACKAGING: Add intmax.m4, longdouble.m4, longlong.m4,
+ printf-posix.m4, signed.m4, wchar_t.m4, wint_t.m4.
+
2003-06-18 Bruno Haible <bruno@clisp.org>
* config/install-sh: Update from automake-1.7.5.
$prefix/share/aclocal/glibc21.m4
$prefix/share/aclocal/iconv.m4
$prefix/share/aclocal/intdiv0.m4
+ $prefix/share/aclocal/intmax.m4
$prefix/share/aclocal/inttypes.m4
$prefix/share/aclocal/inttypes_h.m4
$prefix/share/aclocal/inttypes-pri.m4
$prefix/share/aclocal/lib-ld.m4
$prefix/share/aclocal/lib-link.m4
$prefix/share/aclocal/lib-prefix.m4
+ $prefix/share/aclocal/longdouble.m4
+ $prefix/share/aclocal/longlong.m4
$prefix/share/aclocal/nls.m4
$prefix/share/aclocal/po.m4
+ $prefix/share/aclocal/printf-posix.m4
$prefix/share/aclocal/progtest.m4
+ $prefix/share/aclocal/signed.m4
$prefix/share/aclocal/stdint_h.m4
$prefix/share/aclocal/uintmax_t.m4
$prefix/share/aclocal/ulonglong.m4
+ $prefix/share/aclocal/wchar_t.m4
+ $prefix/share/aclocal/wint_t.m4
$prefix/share/emacs/site-lisp/po-compat.el
$prefix/share/emacs/site-lisp/po-compat.elc
$prefix/share/emacs/site-lisp/po-mode.el
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * Makefile.am (config.h_vms, config.h.msvc): Update.
+ (intl/libgnuintl.h_vms, intl/libgnuintl.h.msvc-static): New rule.
+ (all-local): Depend on them.
+ (intl/libgnuintl.h.msvc-shared): Also perform some AC_SUBST
+ substitutions.
+
2003-06-19 Bruno Haible <bruno@clisp.org>
* configure.ac: New option --disable-libasprintf.
-e 's/#undef HAVE_LC_MESSAGES$$/#define HAVE_LC_MESSAGES 1/' \
-e 's/#undef HAVE_LIMITS_H$$/#define HAVE_LIMITS_H 1/' \
-e 's/#undef HAVE_LOCALE_H$$/#define HAVE_LOCALE_H 1/' \
+ -e 's/#undef HAVE_LONG_DOUBLE$$/#define HAVE_LONG_DOUBLE 1/' \
+ -e 's/#undef HAVE_LONG_LONG$$/#define HAVE_LONG_LONG 1/' \
-e 's/#undef HAVE_MALLOC_H$$/#define HAVE_MALLOC_H 1/' \
-e 's/#undef HAVE_MEMMOVE$$/#define HAVE_MEMMOVE 1/' \
-e 's/#undef HAVE_MEMORY_H$$/#define HAVE_MEMORY_H 1/' \
-e 's/#undef HAVE_MMAP$$/#define HAVE_MMAP 1/' \
-e 's/#undef HAVE_MUNMAP$$/#define HAVE_MUNMAP 1/' \
-e 's/#undef HAVE_NL_TYPES_H$$/#define HAVE_NL_TYPES_H 1/' \
+ -e 's/#undef HAVE_POSIX_PRINTF$$/#define HAVE_POSIX_PRINTF 1/' \
+ -e 's/#undef HAVE_PTRDIFF_T$$/#define HAVE_PTRDIFF_T 1/' \
-e 's/#undef HAVE_PUTENV$$/#define HAVE_PUTENV 1/' \
-e 's/#undef HAVE_SETENV$$/#define HAVE_SETENV 1/' \
-e 's/#undef HAVE_SETLOCALE$$/#define HAVE_SETLOCALE 1/' \
-e 's/#undef HAVE_UNSETENV$$/#define HAVE_UNSETENV 1/' \
-e 's/#undef HAVE_UNSIGNED_LONG_LONG$$/#define HAVE_UNSIGNED_LONG_LONG 1/' \
-e 's/#undef HAVE_VPRINTF$$/#define HAVE_VPRINTF 1/' \
+ -e 's/#undef HAVE_WCHAR_T$$/#define HAVE_WCHAR_T 1/' \
+ -e 's/#undef HAVE_WINT_T$$/#define HAVE_WINT_T 1/' \
+ -e 's/#undef HAVE_WPRINTF$$/#define HAVE_WPRINTF 1/' \
-e 's/#undef ICONV_CONST$$/#define ICONV_CONST/' \
-e 's/#undef STDC_HEADERS$$/#define STDC_HEADERS 1/' \
-e 's/#undef realpath$$/#define realpath rpl_realpath/' \
# vms_jackets.h is a header that comes with Compaq's "porting library".
# KEEP_CRTL_SETLOCALE tells it to not override the native locale support.
+intl/libgnuintl.h_vms: intl/libgnuintl.h.in
+ sed -e 's,@''HAVE_POSIX_PRINTF''@,1,g ' \
+ -e 's,@''HAVE_ASPRINTF''@,0,g' \
+ -e 's,@''HAVE_SNPRINTF''@,0,g' \
+ -e 's,@''HAVE_WPRINTF''@,1,g' \
+ < $(srcdir)/intl/libgnuintl.h.in > $@
+
+all-local: intl/libgnuintl.h_vms
+
EXTRA_DIST += Makefile.vms config.h_vms
-e 's/#undef HAVE_ICONV$$/#define HAVE_ICONV 1/' \
-e 's/#undef HAVE_LIMITS_H$$/#define HAVE_LIMITS_H 1/' \
-e 's/#undef HAVE_LOCALE_H$$/#define HAVE_LOCALE_H 1/' \
+ -e 's/#undef HAVE_LONG_DOUBLE$$/#define HAVE_LONG_DOUBLE 1/' \
-e 's/#undef HAVE_MEMMOVE$$/#define HAVE_MEMMOVE 1/' \
+ -e 's/#undef HAVE_PTRDIFF_T$$/#define HAVE_PTRDIFF_T 1/' \
-e 's/#undef HAVE_PUTENV$$/#define HAVE_PUTENV 1/' \
-e 's/#undef HAVE_SETLOCALE$$/#define HAVE_SETLOCALE 1/' \
+ -e 's/#undef HAVE_SNPRINTF$$/#define HAVE_SNPRINTF 1/' \
-e 's/#undef HAVE_STDDEF_H$$/#define HAVE_STDDEF_H 1/' \
-e 's/#undef HAVE_STDLIB_H$$/#define HAVE_STDLIB_H 1/' \
-e 's/#undef HAVE_STRDUP$$/#define HAVE_STRDUP 1/' \
-e 's/#undef HAVE_SYS_STAT_H$$/#define HAVE_SYS_STAT_H 1/' \
-e 's/#undef HAVE_SYS_TYPES_H$$/#define HAVE_SYS_TYPES_H 1/' \
-e 's/#undef HAVE_VPRINTF$$/#define HAVE_VPRINTF 1/' \
+ -e 's/#undef HAVE_WCHAR_T$$/#define HAVE_WCHAR_T 1/' \
+ -e 's/#undef HAVE_WINT_T$$/#define HAVE_WINT_T 1/' \
+ -e 's/#undef HAVE_WPRINTF$$/#define HAVE_WPRINTF 1/' \
-e 's/#undef ICONV_CONST$$/#define ICONV_CONST const/' \
-e 's/#undef STACK_DIRECTION$$/#define STACK_DIRECTION -1/' \
-e 's/#undef STDC_HEADERS$$/#define STDC_HEADERS 1/' \
-e '/#undef INSTALLPREFIX$$/d' \
< $(srcdir)/config.h.in > $@
-intl/libgnuintl.h.msvc-shared: intl/libgnuintl.h.in windows/dllexport.h
- sed -e 's/extern \([^"]\)/extern LIBINTL_DLL_EXPORTED \1/' -e '/#define _LIBINTL_H/r windows/dllexport.h' < $(srcdir)/intl/libgnuintl.h.in > $@
+intl/libgnuintl.h.msvc-static: intl/libgnuintl.h.in
+ sed -e 's,@''HAVE_POSIX_PRINTF''@,0,g ' \
+ -e 's,@''HAVE_ASPRINTF''@,0,g' \
+ -e 's,@''HAVE_SNPRINTF''@,0,g' \
+ -e 's,@''HAVE_WPRINTF''@,1,g' \
+ < $(srcdir)/intl/libgnuintl.h.in > $@
-all-local: intl/libgnuintl.h.msvc-shared
+intl/libgnuintl.h.msvc-shared: intl/libgnuintl.h.in windows/dllexport.h
+ sed -e 's,@''HAVE_POSIX_PRINTF''@,0,g ' \
+ -e 's,@''HAVE_ASPRINTF''@,0,g' \
+ -e 's,@''HAVE_SNPRINTF''@,0,g' \
+ -e 's,@''HAVE_WPRINTF''@,1,g' \
+ -e 's/extern \([^"]\)/extern LIBINTL_DLL_EXPORTED \1/' \
+ -e '/#define _LIBINTL_H/r windows/dllexport.h' \
+ < $(srcdir)/intl/libgnuintl.h.in > $@
+
+all-local: intl/libgnuintl.h.msvc-static intl/libgnuintl.h.msvc-shared
EXTRA_DIST += README.woe32 Makefile.msvc config.h.msvc windows/dllexport.h windows/intl.rc
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * printf-args.h: New file, from ../libasprintf.
+ * printf-args.c: New file, from ../libasprintf.
+ * printf-parse.h: New file, from ../libasprintf.
+ * printf-parse.c: New file, from ../libasprintf.
+ * vasnprintf.h: New file, from ../libasprintf.
+ * vasnprintf.c: New file, from ../libasprintf.
+ * wprintf-parse.h: New file.
+ * vasnwprintf.h: New file.
+ * printf.c: New file.
+ * libgnuintl.h.in (fprintf, vfprintf, printf, vprintf, sprintf,
+ vsprintf, snprintf, vsnprintf, asprintf, vasprintf, fwprintf,
+ vfwprintf, wprintf, vwprintf, swprintf, vswprintf): New fallback
+ macros.
+ * Makefile.in (HEADERS): Add printf-args.h, printf-args.c,
+ printf-parse.h, wprintf-parse.h, printf-parse.c, vasnprintf.h,
+ vasnwprintf.h, vasnprintf.c.
+ (SOURCES): Add printf.c.
+ (OBJECTS): Add printf.$lo.
+ (DISTFILES.gettext): Add libgnuintl.h_vms, libgnuintl.h.msvc-static.
+ (printf.lo): New rule.
+ (libgnuintl.h): Also perform some AC_SUBST substitutions.
+ (printf.$lo): New dependencies.
+ * Makefile.msvc (OBJECTS): Add printf.obj.
+ (libgnuintl.h): Use libgnuintl.h.msvc-static.
+ (printf.obj): New rule.
+ * Makefile.vms (libgnuintl.h): Use libgnuintl.h_vms.
+
2003-06-12 Bruno Haible <bruno@clisp.org>
* libgnuintl.h (_INTL_REDIRECT_ASM): Don't define when using Mingw.
eval-plural.h \
localcharset.h \
relocatable.h \
+ printf-args.h printf-args.c \
+ printf-parse.h wprintf-parse.h printf-parse.c \
+ vasnprintf.h vasnwprintf.h vasnprintf.c \
os2compat.h \
libgnuintl.h.in
SOURCES = \
relocatable.c \
localename.c \
log.c \
+ printf.c \
osdep.c \
os2compat.c \
intl-compat.c
relocatable.$lo \
localename.$lo \
log.$lo \
+ printf.$lo \
osdep.$lo \
intl-compat.$lo
DISTFILES.common = Makefile.in \
DISTFILES.generated = plural.c
DISTFILES.normal = VERSION
DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc \
-Makefile.vms libgnuintl.h.msvc-shared README.woe32 Makefile.msvc
+libgnuintl.h_vms Makefile.vms \
+libgnuintl.h.msvc-static libgnuintl.h.msvc-shared README.woe32 Makefile.msvc
DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \
COPYING.LIB-2 gettext.h libgettext.h plural-eval.c libgnuintl.h
$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/localename.c
log.lo: $(srcdir)/log.c
$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/log.c
+printf.lo: $(srcdir)/printf.c
+ $(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/printf.c
osdep.lo: $(srcdir)/osdep.c
$(LIBTOOL) --mode=compile $(COMPILE) $(srcdir)/osdep.c
intl-compat.lo: $(srcdir)/intl-compat.c
INCLUDES = -I. -I$(srcdir) -I..
libgnuintl.h: $(srcdir)/libgnuintl.h.in
- cp $(srcdir)/libgnuintl.h.in libgnuintl.h
+ sed -e 's,@''HAVE_POSIX_PRINTF''@,@HAVE_POSIX_PRINTF@,g ' \
+ -e 's,@''HAVE_ASPRINTF''@,@HAVE_ASPRINTF@,g' \
+ -e 's,@''HAVE_SNPRINTF''@,@HAVE_SNPRINTF@,g' \
+ -e 's,@''HAVE_WPRINTF''@,@HAVE_WPRINTF@,g' \
+ < $(srcdir)/libgnuintl.h.in > libgnuintl.h
libintl.h: libgnuintl.h
cp libgnuintl.h libintl.h
dcigettext.$lo: $(srcdir)/eval-plural.h
localcharset.$lo: $(srcdir)/localcharset.h
localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h
+printf.$lo: $(srcdir)/printf-args.h $(srcdir)/printf-args.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/printf-parse.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/vasnprintf.c
tags: TAGS
SHELL = /bin/sh
-OBJECTS = bindtextdom.obj dcgettext.obj dgettext.obj gettext.obj finddomain.obj loadmsgcat.obj localealias.obj textdomain.obj l10nflist.obj explodename.obj dcigettext.obj dcngettext.obj dngettext.obj ngettext.obj plural.obj plural-exp.obj localcharset.obj relocatable.obj localename.obj log.obj osdep.obj intl-compat.obj
+OBJECTS = bindtextdom.obj dcgettext.obj dgettext.obj gettext.obj finddomain.obj loadmsgcat.obj localealias.obj textdomain.obj l10nflist.obj explodename.obj dcigettext.obj dcngettext.obj dngettext.obj ngettext.obj plural.obj plural-exp.obj localcharset.obj relocatable.obj localename.obj log.obj printf.obj osdep.obj intl-compat.obj
RESOURCES = intl.res
libgnuintl.h :
!if !$(DLL)
- $(LN) $(srcdir)\libgnuintl.h.in libgnuintl.h
+ $(LN) $(srcdir)\libgnuintl.h.msvc-static libgnuintl.h
!else
$(LN) $(srcdir)\libgnuintl.h.msvc-shared libgnuintl.h
!endif
log.obj : $(srcdir)\log.c libgnuintl.h
$(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c $(srcdir)\log.c
+printf.obj : $(srcdir)\printf.c libgnuintl.h $(srcdir)\printf-args.h $(srcdir)\printf-args.c $(srcdir)\printf-parse.h $(srcdir)\wprintf-parse.h $(srcdir)\printf-parse.c $(srcdir)\vasnprintf.h $(srcdir)\vasnwprintf.h $(srcdir)\vasnprintf.c
+ $(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c $(srcdir)\printf.c
+
osdep.obj : $(srcdir)\osdep.c libgnuintl.h
$(CC) $(INCLUDES) $(CFLAGS) $(PICFLAGS) -c $(srcdir)\osdep.c
write sys$output "Nothing else to be done for 'all'."
libgnuintl.h :
- if f$search("$(srcdir)libgnuintl.h_in") .nes. "" then $(LN) $(srcdir)libgnuintl.h_in libgnuintl.h
- if f$search("$(srcdir)libgnuintl.h_in") .eqs. "" then $(LN) $(srcdir)libgnuintl.h.in libgnuintl.h
+ $(LN) $(srcdir)libgnuintl.h_vms libgnuintl.h
bindtextdom.obj : $(srcdir)bindtextdom.c,libgnuintl.h,$(srcdir)gettextP.h,$(srcdir)gmo.h,$(srcdir)loadinfo.h
$(CC) $(INCLUDES) $(CFLAGS) /define=($(DEFS)) $(srcdir)bindtextdom.c
#endif
+/* Support for format strings with positions in *printf(), following the
+ POSIX/XSI specification.
+ Note: These replacements for the *printf() functions are visible only
+ in source files that #include <libintl.h> or #include "gettext.h".
+ Packages that use *printf() in source files that don't refer to _()
+ or gettext() but for which the format string could be the return value
+ of _() or gettext() need to add this #include. Oh well. */
+
+#if !@HAVE_POSIX_PRINTF@
+
+#include <stdio.h>
+#include <stddef.h>
+
+/* Get va_list. */
+#if __STDC__ || defined __cplusplus
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+#undef fprintf
+#define fprintf libintl_fprintf
+extern int fprintf _INTL_PARAMS ((FILE *, const char *, ...));
+#undef vfprintf
+#define vfprintf libintl_vfprintf
+extern int vfprintf _INTL_PARAMS ((FILE *, const char *, va_list));
+
+#undef printf
+#define printf libintl_printf
+extern int printf _INTL_PARAMS ((const char *, ...));
+#undef vprintf
+#define vprintf libintl_vprintf
+extern int vprintf _INTL_PARAMS ((const char *, va_list));
+
+#undef sprintf
+#define sprintf libintl_sprintf
+extern int sprintf _INTL_PARAMS ((char *, const char *, ...));
+#undef vsprintf
+#define vsprintf libintl_vsprintf
+extern int vsprintf _INTL_PARAMS ((char *, const char *, va_list));
+
+#if @HAVE_SNPRINTF@
+
+#undef snprintf
+#define snprintf libintl_snprintf
+extern int snprintf _INTL_PARAMS ((char *, size_t, const char *, ...));
+#undef vsnprintf
+#define vsnprintf libintl_vsnprintf
+extern int vsnprintf _INTL_PARAMS ((char *, size_t, const char *, va_list));
+
+#endif
+
+#if @HAVE_ASPRINTF@
+
+#undef asprintf
+#define asprintf libintl_asprintf
+extern int asprintf _INTL_PARAMS ((char **, const char *, ...));
+#undef vasprintf
+#define vasprintf libintl_vasprintf
+extern int vasprintf _INTL_PARAMS ((char **, const char *, va_list));
+
+#endif
+
+#if @HAVE_WPRINTF@
+
+#undef fwprintf
+#define fwprintf libintl_fwprintf
+extern int fwprintf _INTL_PARAMS ((FILE *, const wchar_t *, ...));
+#undef vfwprintf
+#define vfwprintf libintl_vfwprintf
+extern int vfwprintf _INTL_PARAMS ((FILE *, const wchar_t *, va_list));
+
+#undef wprintf
+#define wprintf libintl_wprintf
+extern int wprintf _INTL_PARAMS ((const wchar_t *, ...));
+#undef vwprintf
+#define vwprintf libintl_vwprintf
+extern int vwprintf _INTL_PARAMS ((const wchar_t *, va_list));
+
+#undef swprintf
+#define swprintf libintl_swprintf
+extern int swprintf _INTL_PARAMS ((wchar_t *, size_t, const wchar_t *, ...));
+#undef vswprintf
+#define vswprintf libintl_vswprintf
+extern int vswprintf _INTL_PARAMS ((wchar_t *, size_t, const wchar_t *, va_list));
+
+#endif
+
+#endif
+
+
/* Support for relocatable packages. */
/* Sets the original and the current installation prefix of the package.
--- /dev/null
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "printf-args.h"
+
+#ifdef STATIC
+STATIC
+#endif
+int
+printf_fetchargs (va_list args, arguments *a)
+{
+ unsigned int i;
+ argument *ap;
+
+ for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
+ switch (ap->type)
+ {
+ case TYPE_SCHAR:
+ ap->a.a_schar = va_arg (args, /*signed char*/ int);
+ break;
+ case TYPE_UCHAR:
+ ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
+ break;
+ case TYPE_SHORT:
+ ap->a.a_short = va_arg (args, /*short*/ int);
+ break;
+ case TYPE_USHORT:
+ ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
+ break;
+ case TYPE_INT:
+ ap->a.a_int = va_arg (args, int);
+ break;
+ case TYPE_UINT:
+ ap->a.a_uint = va_arg (args, unsigned int);
+ break;
+ case TYPE_LONGINT:
+ ap->a.a_longint = va_arg (args, long int);
+ break;
+ case TYPE_ULONGINT:
+ ap->a.a_ulongint = va_arg (args, unsigned long int);
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ ap->a.a_longlongint = va_arg (args, long long int);
+ break;
+ case TYPE_ULONGLONGINT:
+ ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
+ break;
+#endif
+ case TYPE_DOUBLE:
+ ap->a.a_double = va_arg (args, double);
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ ap->a.a_longdouble = va_arg (args, long double);
+ break;
+#endif
+ case TYPE_CHAR:
+ ap->a.a_char = va_arg (args, int);
+ break;
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ ap->a.a_wide_char = va_arg (args, wint_t);
+ break;
+#endif
+ case TYPE_STRING:
+ ap->a.a_string = va_arg (args, const char *);
+ break;
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ ap->a.a_wide_string = va_arg (args, const wchar_t *);
+ break;
+#endif
+ case TYPE_POINTER:
+ ap->a.a_pointer = va_arg (args, void *);
+ break;
+ case TYPE_COUNT_SCHAR_POINTER:
+ ap->a.a_count_schar_pointer = va_arg (args, signed char *);
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ ap->a.a_count_short_pointer = va_arg (args, short *);
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ ap->a.a_count_int_pointer = va_arg (args, int *);
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ ap->a.a_count_longint_pointer = va_arg (args, long int *);
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
+ break;
+#endif
+ default:
+ /* Unknown type. */
+ return -1;
+ }
+ return 0;
+}
--- /dev/null
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _PRINTF_ARGS_H
+#define _PRINTF_ARGS_H
+
+/* Get wchar_t. */
+#ifdef HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t. */
+#ifdef HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list. */
+#include <stdarg.h>
+
+
+/* Argument types */
+typedef enum
+{
+ TYPE_NONE,
+ TYPE_SCHAR,
+ TYPE_UCHAR,
+ TYPE_SHORT,
+ TYPE_USHORT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_LONGINT,
+ TYPE_ULONGINT,
+#ifdef HAVE_LONG_LONG
+ TYPE_LONGLONGINT,
+ TYPE_ULONGLONGINT,
+#endif
+ TYPE_DOUBLE,
+#ifdef HAVE_LONG_DOUBLE
+ TYPE_LONGDOUBLE,
+#endif
+ TYPE_CHAR,
+#ifdef HAVE_WINT_T
+ TYPE_WIDE_CHAR,
+#endif
+ TYPE_STRING,
+#ifdef HAVE_WCHAR_T
+ TYPE_WIDE_STRING,
+#endif
+ TYPE_POINTER,
+ TYPE_COUNT_SCHAR_POINTER,
+ TYPE_COUNT_SHORT_POINTER,
+ TYPE_COUNT_INT_POINTER,
+ TYPE_COUNT_LONGINT_POINTER
+#ifdef HAVE_LONG_LONG
+, TYPE_COUNT_LONGLONGINT_POINTER
+#endif
+} arg_type;
+
+/* Polymorphic argument */
+typedef struct
+{
+ arg_type type;
+ union
+ {
+ signed char a_schar;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long int a_longint;
+ unsigned long int a_ulongint;
+#ifdef HAVE_LONG_LONG
+ long long int a_longlongint;
+ unsigned long long int a_ulonglongint;
+#endif
+ float a_float;
+ double a_double;
+#ifdef HAVE_LONG_DOUBLE
+ long double a_longdouble;
+#endif
+ int a_char;
+#ifdef HAVE_WINT_T
+ wint_t a_wide_char;
+#endif
+ const char* a_string;
+#ifdef HAVE_WCHAR_T
+ const wchar_t* a_wide_string;
+#endif
+ void* a_pointer;
+ signed char * a_count_schar_pointer;
+ short * a_count_short_pointer;
+ int * a_count_int_pointer;
+ long int * a_count_longint_pointer;
+#ifdef HAVE_LONG_LONG
+ long long int * a_count_longlongint_pointer;
+#endif
+ }
+ a;
+}
+argument;
+
+typedef struct
+{
+ unsigned int count;
+ argument *arg;
+}
+arguments;
+
+
+/* Fetch the arguments, putting them into a. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_fetchargs (va_list args, arguments *a);
+
+#endif /* _PRINTF_ARGS_H */
--- /dev/null
+/* Formatted output to strings.
+ Copyright (C) 1999-2000, 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* Get size_t, NULL. */
+#include <stddef.h>
+
+/* Get intmax_t. */
+#if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+#endif
+
+/* malloc(), realloc(), free(). */
+#include <stdlib.h>
+
+#if WIDE_CHAR_VERSION
+# define PRINTF_PARSE wprintf_parse
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+#else
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
+{
+ const CHAR_T *cp = format; /* pointer into format */
+ int arg_posn = 0; /* number of regular arguments consumed */
+ unsigned int d_allocated; /* allocated elements of d->dir */
+ unsigned int a_allocated; /* allocated elements of a->arg */
+ unsigned int max_width_length = 0;
+ unsigned int max_precision_length = 0;
+
+ d->count = 0;
+ d_allocated = 1;
+ d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
+ if (d->dir == NULL)
+ /* Out of memory. */
+ return -1;
+
+ a->count = 0;
+ a_allocated = 0;
+ a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+ { \
+ unsigned int n = (_index_); \
+ if (n >= a_allocated) \
+ { \
+ argument *memory; \
+ a_allocated = 2 * a_allocated; \
+ if (a_allocated <= n) \
+ a_allocated = n + 1; \
+ memory = (a->arg \
+ ? realloc (a->arg, a_allocated * sizeof (argument)) \
+ : malloc (a_allocated * sizeof (argument))); \
+ if (memory == NULL) \
+ /* Out of memory. */ \
+ goto error; \
+ a->arg = memory; \
+ } \
+ while (a->count <= n) \
+ a->arg[a->count++].type = TYPE_NONE; \
+ if (a->arg[n].type == TYPE_NONE) \
+ a->arg[n].type = (_type_); \
+ else if (a->arg[n].type != (_type_)) \
+ /* Ambiguous type for positional argument. */ \
+ goto error; \
+ }
+
+ while (*cp != '\0')
+ {
+ CHAR_T c = *cp++;
+ if (c == '%')
+ {
+ int arg_index = -1;
+ DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
+
+ /* Initialize the next directive. */
+ dp->dir_start = cp - 1;
+ dp->flags = 0;
+ dp->width_start = NULL;
+ dp->width_end = NULL;
+ dp->width_arg_index = -1;
+ dp->precision_start = NULL;
+ dp->precision_end = NULL;
+ dp->precision_arg_index = -1;
+ dp->arg_index = -1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ unsigned int n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = 10 * n + (*np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+
+ /* Read the flags. */
+ for (;;)
+ {
+ if (*cp == '\'')
+ {
+ dp->flags |= FLAG_GROUP;
+ cp++;
+ }
+ else if (*cp == '-')
+ {
+ dp->flags |= FLAG_LEFT;
+ cp++;
+ }
+ else if (*cp == '+')
+ {
+ dp->flags |= FLAG_SHOWSIGN;
+ cp++;
+ }
+ else if (*cp == ' ')
+ {
+ dp->flags |= FLAG_SPACE;
+ cp++;
+ }
+ else if (*cp == '#')
+ {
+ dp->flags |= FLAG_ALT;
+ cp++;
+ }
+ else if (*cp == '0')
+ {
+ dp->flags |= FLAG_ZERO;
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Parse the field width. */
+ if (*cp == '*')
+ {
+ dp->width_start = cp;
+ cp++;
+ dp->width_end = cp;
+ if (max_width_length < 1)
+ max_width_length = 1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ unsigned int n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = 10 * n + (*np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ dp->width_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->width_arg_index < 0)
+ dp->width_arg_index = arg_posn++;
+ REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+ }
+ else if (*cp >= '0' && *cp <= '9')
+ {
+ unsigned int width_length;
+
+ dp->width_start = cp;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->width_end = cp;
+ width_length = dp->width_end - dp->width_start;
+ if (max_width_length < width_length)
+ max_width_length = width_length;
+ }
+
+ /* Parse the precision. */
+ if (*cp == '.')
+ {
+ cp++;
+ if (*cp == '*')
+ {
+ dp->precision_start = cp - 1;
+ cp++;
+ dp->precision_end = cp;
+ if (max_precision_length < 2)
+ max_precision_length = 2;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ unsigned int n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = 10 * n + (*np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ dp->precision_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->precision_arg_index < 0)
+ dp->precision_arg_index = arg_posn++;
+ REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+ }
+ else
+ {
+ unsigned int precision_length;
+
+ dp->precision_start = cp - 1;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->precision_end = cp;
+ precision_length = dp->precision_end - dp->precision_start;
+ if (max_precision_length < precision_length)
+ max_precision_length = precision_length;
+ }
+ }
+
+ {
+ arg_type type;
+
+ /* Parse argument type/size specifiers. */
+ {
+ int flags = 0;
+
+ for (;;)
+ {
+ if (*cp == 'h')
+ {
+ flags |= (1 << (flags & 1));
+ cp++;
+ }
+ else if (*cp == 'L')
+ {
+ flags |= 4;
+ cp++;
+ }
+ else if (*cp == 'l')
+ {
+ flags += 8;
+ cp++;
+ }
+#ifdef HAVE_INTMAX_T
+ else if (*cp == 'j')
+ {
+ if (sizeof (intmax_t) > sizeof (long))
+ {
+ /* intmax_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (intmax_t) > sizeof (int))
+ {
+ /* intmax_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+#endif
+ else if (*cp == 'z' || *cp == 'Z')
+ {
+ /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+ because the warning facility in gcc-2.95.2 understands
+ only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
+ if (sizeof (size_t) > sizeof (long))
+ {
+ /* size_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (size_t) > sizeof (int))
+ {
+ /* size_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 't')
+ {
+ if (sizeof (ptrdiff_t) > sizeof (long))
+ {
+ /* ptrdiff_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (ptrdiff_t) > sizeof (int))
+ {
+ /* ptrdiff_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Read the conversion character. */
+ c = *cp++;
+ switch (c)
+ {
+ case 'd': case 'i':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGLONGINT;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_LONGINT;
+ else if (flags & 2)
+ type = TYPE_SCHAR;
+ else if (flags & 1)
+ type = TYPE_SHORT;
+ else
+ type = TYPE_INT;
+ break;
+ case 'o': case 'u': case 'x': case 'X':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_ULONGLONGINT;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_ULONGINT;
+ else if (flags & 2)
+ type = TYPE_UCHAR;
+ else if (flags & 1)
+ type = TYPE_USHORT;
+ else
+ type = TYPE_UINT;
+ break;
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+#ifdef HAVE_LONG_DOUBLE
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGDOUBLE;
+ else
+#endif
+ type = TYPE_DOUBLE;
+ break;
+ case 'c':
+ if (flags >= 8)
+#ifdef HAVE_WINT_T
+ type = TYPE_WIDE_CHAR;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_CHAR;
+ break;
+#ifdef HAVE_WINT_T
+ case 'C':
+ type = TYPE_WIDE_CHAR;
+ c = 'c';
+ break;
+#endif
+ case 's':
+ if (flags >= 8)
+#ifdef HAVE_WCHAR_T
+ type = TYPE_WIDE_STRING;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_STRING;
+ break;
+#ifdef HAVE_WCHAR_T
+ case 'S':
+ type = TYPE_WIDE_STRING;
+ c = 's';
+ break;
+#endif
+ case 'p':
+ type = TYPE_POINTER;
+ break;
+ case 'n':
+#ifdef HAVE_LONG_LONG
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_COUNT_LONGLONGINT_POINTER;
+ else
+#endif
+ if (flags >= 8)
+ type = TYPE_COUNT_LONGINT_POINTER;
+ else if (flags & 2)
+ type = TYPE_COUNT_SCHAR_POINTER;
+ else if (flags & 1)
+ type = TYPE_COUNT_SHORT_POINTER;
+ else
+ type = TYPE_COUNT_INT_POINTER;
+ break;
+ case '%':
+ type = TYPE_NONE;
+ break;
+ default:
+ /* Unknown conversion character. */
+ goto error;
+ }
+ }
+
+ if (type != TYPE_NONE)
+ {
+ dp->arg_index = arg_index;
+ if (dp->arg_index < 0)
+ dp->arg_index = arg_posn++;
+ REGISTER_ARG (dp->arg_index, type);
+ }
+ dp->conversion = c;
+ dp->dir_end = cp;
+ }
+
+ d->count++;
+ if (d->count >= d_allocated)
+ {
+ DIRECTIVE *memory;
+
+ d_allocated = 2 * d_allocated;
+ memory = realloc (d->dir, d_allocated * sizeof (DIRECTIVE));
+ if (memory == NULL)
+ /* Out of memory. */
+ goto error;
+ d->dir = memory;
+ }
+ }
+ }
+ d->dir[d->count].dir_start = cp;
+
+ d->max_width_length = max_width_length;
+ d->max_precision_length = max_precision_length;
+ return 0;
+
+error:
+ if (a->arg)
+ free (a->arg);
+ if (d->dir)
+ free (d->dir);
+ return -1;
+}
+
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef PRINTF_PARSE
--- /dev/null
+/* Parse printf format string.
+ Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _PRINTF_PARSE_H
+#define _PRINTF_PARSE_H
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* A parsed directive. */
+typedef struct
+{
+ const char* dir_start;
+ const char* dir_end;
+ int flags;
+ const char* width_start;
+ const char* width_end;
+ int width_arg_index;
+ const char* precision_start;
+ const char* precision_end;
+ int precision_arg_index;
+ char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ int arg_index;
+}
+char_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ unsigned int count;
+ char_directive *dir;
+ unsigned int max_width_length;
+ unsigned int max_precision_length;
+}
+char_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_parse (const char *format, char_directives *d, arguments *a);
+
+#endif /* _PRINTF_PARSE_H */
--- /dev/null
+/* Formatted output to strings, using POSIX/XSI format strings with positions.
+ Copyright (C) 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if !HAVE_POSIX_PRINTF
+
+#include <stdlib.h>
+#include <string.h>
+
+#define STATIC static
+
+/* 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
+
+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)
+ {
+ if (fwrite (result, 1, length, stream) == length)
+ retval = length;
+ free (result);
+ }
+ return retval;
+ }
+}
+
+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;
+}
+
+int
+libintl_vprintf (const char *format, va_list args)
+{
+ return libintl_vfprintf (stdout, format, args);
+}
+
+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;
+}
+
+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;
+ }
+ else
+ return length;
+ }
+}
+
+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
+
+int
+libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
+{
+ if (strchr (format, '$') == NULL)
+ return vsnprintf (resultbuf, length, format, args);
+ else
+ {
+ size_t maxlength = length;
+ char *result = libintl_vasnprintf (resultbuf, &length, format, args);
+ if (result != resultbuf)
+ {
+ if (maxlength > 0)
+ {
+ if (length < maxlength)
+ abort ();
+ memcpy (resultbuf, result, maxlength - 1);
+ resultbuf[maxlength - 1] = '\0';
+ }
+ free (result);
+ return -1;
+ }
+ else
+ return length;
+ }
+}
+
+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
+
+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;
+ *resultp = result;
+ return length;
+}
+
+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_WPRINTF
+
+#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
+
+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;
+ if (i == length)
+ retval = length;
+ free (result);
+ }
+ return retval;
+ }
+}
+
+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;
+}
+
+int
+libintl_vwprintf (const wchar_t *format, va_list args)
+{
+ return libintl_vfwprintf (stdout, format, args);
+}
+
+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;
+}
+
+int
+libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
+{
+ if (wcschr (format, '$') == NULL)
+ return 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)
+ {
+ if (length < maxlength)
+ abort ();
+ memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t));
+ resultbuf[maxlength - 1] = 0;
+ }
+ free (result);
+ return -1;
+ }
+ else
+ return length;
+ }
+}
+
+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
--- /dev/null
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <alloca.h>
+
+/* Specification. */
+#if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+#else
+# include "vasnprintf.h"
+#endif
+
+#include <stdio.h> /* snprintf(), sprintf() */
+#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
+#include <string.h> /* memcpy(), strlen() */
+#include <errno.h> /* errno */
+#include <limits.h> /* CHAR_BIT */
+#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
+
+/* For those losing systems which don't have 'alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+#if WIDE_CHAR_VERSION
+# define VASNPRINTF vasnwprintf
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+# define PRINTF_PARSE wprintf_parse
+# define USE_SNPRINTF 1
+# define SNPRINTF swprintf
+#else
+# define VASNPRINTF vasnprintf
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+# define PRINTF_PARSE printf_parse
+# define USE_SNPRINTF HAVE_SNPRINTF
+# define SNPRINTF snprintf
+#endif
+
+CHAR_T *
+VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
+{
+ DIRECTIVES d;
+ arguments a;
+
+ if (PRINTF_PARSE (format, &d, &a) < 0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+#define CLEANUP() \
+ free (d.dir); \
+ if (a.arg) \
+ free (a.arg);
+
+ if (printf_fetchargs (args, &a) < 0)
+ {
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+ {
+ CHAR_T *buf =
+ (CHAR_T *) alloca ((7 + d.max_width_length + d.max_precision_length + 6)
+ * sizeof (CHAR_T));
+ const CHAR_T *cp;
+ unsigned int i;
+ DIRECTIVE *dp;
+ /* Output string accumulator. */
+ CHAR_T *result;
+ size_t allocated;
+ size_t length;
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+#define ENSURE_ALLOCATION(needed) \
+ if ((needed) > allocated) \
+ { \
+ CHAR_T *memory; \
+ \
+ allocated = (allocated > 0 ? 2 * allocated : 12); \
+ if ((needed) > allocated) \
+ allocated = (needed); \
+ if (result == resultbuf || result == NULL) \
+ memory = (CHAR_T *) malloc (allocated * sizeof (CHAR_T)); \
+ else \
+ memory = (CHAR_T *) realloc (result, allocated * sizeof (CHAR_T)); \
+ \
+ if (memory == NULL) \
+ { \
+ if (!(result == resultbuf || result == NULL)) \
+ free (result); \
+ freea (buf); \
+ CLEANUP (); \
+ errno = ENOMEM; \
+ return NULL; \
+ } \
+ if (result == resultbuf && length > 0) \
+ memcpy (memory, result, length * sizeof (CHAR_T)); \
+ result = memory; \
+ }
+
+ for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+ {
+ if (cp != dp->dir_start)
+ {
+ size_t n = dp->dir_start - cp;
+
+ ENSURE_ALLOCATION (length + n);
+ memcpy (result + length, cp, n * sizeof (CHAR_T));
+ length += n;
+ }
+ if (i == d.count)
+ break;
+
+ /* Execute a single directive. */
+ if (dp->conversion == '%')
+ {
+ if (!(dp->arg_index < 0))
+ abort ();
+ ENSURE_ALLOCATION (length + 1);
+ result[length] = '%';
+ length += 1;
+ }
+ else
+ {
+ if (!(dp->arg_index >= 0))
+ abort ();
+
+ if (dp->conversion == 'n')
+ {
+ switch (a.arg[dp->arg_index].type)
+ {
+ case TYPE_COUNT_SCHAR_POINTER:
+ *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
+ break;
+#endif
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ CHAR_T *p;
+ unsigned int prefix_count;
+ int prefixes[2];
+#if !USE_SNPRINTF
+ unsigned int tmp_length;
+ CHAR_T tmpbuf[700];
+ CHAR_T *tmp;
+
+ /* Allocate a temporary buffer of sufficient size for calling
+ sprintf. */
+ {
+ unsigned int width;
+ unsigned int precision;
+
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index >= 0)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ width = (arg < 0 ? -arg : arg);
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->width_start;
+
+ do
+ width = width * 10 + (*digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ }
+
+ precision = 6;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index >= 0)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ precision = (arg < 0 ? 0 : arg);
+ }
+ else
+ {
+ const CHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ do
+ precision = precision * 10 + (*digitp++ - '0');
+ while (digitp != dp->precision_end);
+ }
+ }
+
+ switch (dp->conversion)
+ {
+
+ case 'd': case 'i': case 'u':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ break;
+
+ case 'o':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1 /* turn floor into ceil */
+ + 1; /* account for leading sign */
+ break;
+
+ case 'x': case 'X':
+# ifdef HAVE_LONG_LONG
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading sign or alternate form */
+ break;
+
+ case 'f': case 'F':
+# ifdef HAVE_LONG_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + precision
+ + 10; /* sign, decimal point etc. */
+ else
+# endif
+ tmp_length =
+ (unsigned int) (DBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + precision
+ + 10; /* sign, decimal point etc. */
+ break;
+
+ case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+ tmp_length =
+ precision
+ + 12; /* sign, decimal point, exponent etc. */
+ break;
+
+ case 'c':
+# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
+ if (type == TYPE_WIDE_CHAR)
+ tmp_length = MB_CUR_MAX;
+ else
+# endif
+ tmp_length = 1;
+ break;
+
+ case 's':
+# ifdef HAVE_WCHAR_T
+ if (type == TYPE_WIDE_STRING)
+# if WIDE_CHAR_VERSION
+ tmp_length =
+ wcslen (a.arg[dp->arg_index].a.a_wide_string);
+# else
+ tmp_length =
+ wcslen (a.arg[dp->arg_index].a.a_wide_string)
+ * MB_CUR_MAX;
+# endif
+ else
+# endif
+ tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
+ break;
+
+ case 'p':
+ tmp_length =
+ (unsigned int) (sizeof (void *) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading 0x */
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length++; /* account for trailing NUL */
+ }
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ tmp = (CHAR_T *) malloc (tmp_length * sizeof (CHAR_T));
+ if (tmp == NULL)
+ {
+ /* Out of memory. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ freea (buf);
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
+ }
+ }
+#endif
+
+ /* Construct the format string for calling snprintf or
+ sprintf. */
+ p = buf;
+ *p++ = '%';
+ if (dp->flags & FLAG_GROUP)
+ *p++ = '\'';
+ if (dp->flags & FLAG_LEFT)
+ *p++ = '-';
+ if (dp->flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ if (dp->flags & FLAG_SPACE)
+ *p++ = ' ';
+ if (dp->flags & FLAG_ALT)
+ *p++ = '#';
+ if (dp->flags & FLAG_ZERO)
+ *p++ = '0';
+ if (dp->width_start != dp->width_end)
+ {
+ size_t n = dp->width_end - dp->width_start;
+ memcpy (p, dp->width_start, n * sizeof (CHAR_T));
+ p += n;
+ }
+ if (dp->precision_start != dp->precision_end)
+ {
+ size_t n = dp->precision_end - dp->precision_start;
+ memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
+ p += n;
+ }
+
+ switch (type)
+ {
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ case TYPE_ULONGLONGINT:
+ *p++ = 'l';
+ /*FALLTHROUGH*/
+#endif
+ case TYPE_LONGINT:
+ case TYPE_ULONGINT:
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+#endif
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+#endif
+ *p++ = 'l';
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ *p++ = 'L';
+ break;
+#endif
+ default:
+ break;
+ }
+ *p = dp->conversion;
+#if USE_SNPRINTF
+ p[1] = '%';
+ p[2] = 'n';
+ p[3] = '\0';
+#else
+ p[1] = '\0';
+#endif
+
+ /* Construct the arguments for calling snprintf or sprintf. */
+ prefix_count = 0;
+ if (dp->width_arg_index >= 0)
+ {
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
+ }
+ if (dp->precision_arg_index >= 0)
+ {
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
+ }
+
+#if USE_SNPRINTF
+ /* Prepare checking whether snprintf returns the count
+ via %n. */
+ ENSURE_ALLOCATION (length + 1);
+ result[length] = '\0';
+#endif
+
+ for (;;)
+ {
+ size_t maxlen;
+ int count;
+ int retcount;
+
+ maxlen = allocated - length;
+ count = -1;
+ retcount = 0;
+
+#if USE_SNPRINTF
+#define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ arg, &count); \
+ break; \
+ case 1: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ prefixes[0], arg, &count); \
+ break; \
+ case 2: \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
+ prefixes[0], prefixes[1], arg, \
+ &count); \
+ break; \
+ default: \
+ abort (); \
+ }
+#else
+#define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ count = sprintf (tmp, buf, arg); \
+ break; \
+ case 1: \
+ count = sprintf (tmp, buf, prefixes[0], arg); \
+ break; \
+ case 2: \
+ count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+ arg); \
+ break; \
+ default: \
+ abort (); \
+ }
+#endif
+
+ switch (type)
+ {
+ case TYPE_SCHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_schar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UCHAR:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_SHORT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_short;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_USHORT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_INT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_int;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UINT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGINT:
+ {
+ long int arg = a.arg[dp->arg_index].a.a_longint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGINT:
+ {
+ unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_LONG_LONG
+ case TYPE_LONGLONGINT:
+ {
+ long long int arg = a.arg[dp->arg_index].a.a_longlongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGLONGINT:
+ {
+ unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_DOUBLE:
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_LONG_DOUBLE
+ case TYPE_LONGDOUBLE:
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_CHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ {
+ wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_STRING:
+ {
+ const char *arg = a.arg[dp->arg_index].a.a_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#ifdef HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ {
+ const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ {
+ void *arg = a.arg[dp->arg_index].a.a_pointer;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ default:
+ abort ();
+ }
+
+#if USE_SNPRINTF
+ /* Portability: Not all implementations of snprintf()
+ are ISO C 99 compliant. Determine the number of
+ bytes that snprintf() has produced or would have
+ produced. */
+ if (count >= 0)
+ {
+ /* Verify that snprintf() has NUL-terminated its
+ result. */
+ if (count < maxlen && result[length + count] != '\0')
+ abort ();
+ /* Portability hack. */
+ if (retcount > count)
+ count = retcount;
+ }
+ else
+ {
+ /* snprintf() doesn't understand the '%n'
+ directive. */
+ if (p[1] != '\0')
+ {
+ /* Don't use the '%n' directive; instead, look
+ at the snprintf() return value. */
+ p[1] = '\0';
+ continue;
+ }
+ count = retcount;
+ }
+#endif
+
+ /* Attempt to handle failure. */
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ freea (buf);
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+#if !USE_SNPRINTF
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+#endif
+
+ /* Make room for the result. */
+ if (count >= maxlen)
+ {
+ /* Need at least count bytes. But allocate
+ proportionally, to avoid looping eternally if
+ snprintf() reports a too small count. */
+ size_t n = length + count;
+
+ if (n < 2 * allocated)
+ n = 2 * allocated;
+
+ ENSURE_ALLOCATION (n);
+#if USE_SNPRINTF
+ continue;
+#endif
+ }
+
+#if USE_SNPRINTF
+ /* The snprintf() result did fit. */
+#else
+ /* Append the sprintf() result. */
+ memcpy (result + length, tmp, count * sizeof (CHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+#endif
+
+ length += count;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Add the final NUL. */
+ ENSURE_ALLOCATION (length + 1);
+ result[length] = '\0';
+
+ if (result != resultbuf && length + 1 < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ CHAR_T *memory;
+
+ memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ freea (buf);
+ CLEANUP ();
+ *lengthp = length;
+ return result;
+ }
+}
+
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef VASNPRINTF
--- /dev/null
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL. */
+extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNPRINTF_H */
--- /dev/null
+/* vswprintf with automatic memory allocation.
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _VASNWPRINTF_H
+#define _VASNWPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get wchar_t, size_t. */
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL. */
+extern wchar_t * asnwprintf (wchar_t *resultbuf, size_t *lengthp, const wchar_t *format, ...);
+extern wchar_t * vasnwprintf (wchar_t *resultbuf, size_t *lengthp, const wchar_t *format, va_list args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNWPRINTF_H */
--- /dev/null
+/* Parse printf format string.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _WPRINTF_PARSE_H
+#define _WPRINTF_PARSE_H
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* A parsed directive. */
+typedef struct
+{
+ const wchar_t* dir_start;
+ const wchar_t* dir_end;
+ int flags;
+ const wchar_t* width_start;
+ const wchar_t* width_end;
+ int width_arg_index;
+ const wchar_t* precision_start;
+ const wchar_t* precision_end;
+ int precision_arg_index;
+ wchar_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ int arg_index;
+}
+wchar_t_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ unsigned int count;
+ wchar_t_directive *dir;
+ unsigned int max_width_length;
+ unsigned int max_precision_length;
+}
+wchar_t_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int wprintf_parse (const wchar_t *format, wchar_t_directives *d, arguments *a);
+
+#endif /* _WPRINTF_PARSE_H */
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * configure.ac (jm_AC_TYPE_LONG_LONG): Replaces gt_TYPE_LONGLONG.
+ * printf-args.c: Generalize to it can be compiled for wide strings.
+ (PRINTF_PARSE, CHAR_T, DIRECTIVE, DIRECTIVES): New macros.
+ * vasnprintf.c: Generalize to it can be compiled for wide strings.
+ (VASNPRINTF, CHAR_T, DIRECTIVE, DIRECTIVES, PRINTF_PARSE, USE_SNPRINTF,
+ SNPRINTF): New macros.
+
2003-05-30 Bruno Haible <bruno@clisp.org>
* autosprintf.texi: Tweak @dircategory and @direntry.
AC_C_CONST
bh_C_SIGNED
AC_TYPE_SIZE_T
-gt_TYPE_LONGLONG
+jm_AC_TYPE_LONG_LONG
gt_TYPE_LONGDOUBLE
gt_TYPE_WCHAR_T
gt_TYPE_WINT_T
#endif
/* Specification. */
-#include "printf-parse.h"
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
/* Get size_t, NULL. */
#include <stddef.h>
/* malloc(), realloc(), free(). */
#include <stdlib.h>
+#if WIDE_CHAR_VERSION
+# define PRINTF_PARSE wprintf_parse
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+#else
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
#ifdef STATIC
STATIC
#endif
int
-printf_parse (const char *format, char_directives *d, arguments *a)
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
{
- const char *cp = format; /* pointer into format */
+ const CHAR_T *cp = format; /* pointer into format */
int arg_posn = 0; /* number of regular arguments consumed */
unsigned int d_allocated; /* allocated elements of d->dir */
unsigned int a_allocated; /* allocated elements of a->arg */
d->count = 0;
d_allocated = 1;
- d->dir = malloc (d_allocated * sizeof (char_directive));
+ d->dir = malloc (d_allocated * sizeof (DIRECTIVE));
if (d->dir == NULL)
/* Out of memory. */
return -1;
while (*cp != '\0')
{
- char c = *cp++;
+ CHAR_T c = *cp++;
if (c == '%')
{
int arg_index = -1;
- char_directive *dp = &d->dir[d->count];/* pointer to next directive */
+ DIRECTIVE *dp = &d->dir[d->count];/* pointer to next directive */
/* Initialize the next directive. */
dp->dir_start = cp - 1;
/* Test for positional argument. */
if (*cp >= '0' && *cp <= '9')
{
- const char *np;
+ const CHAR_T *np;
for (np = cp; *np >= '0' && *np <= '9'; np++)
;
/* Test for positional argument. */
if (*cp >= '0' && *cp <= '9')
{
- const char *np;
+ const CHAR_T *np;
for (np = cp; *np >= '0' && *np <= '9'; np++)
;
/* Test for positional argument. */
if (*cp >= '0' && *cp <= '9')
{
- const char *np;
+ const CHAR_T *np;
for (np = cp; *np >= '0' && *np <= '9'; np++)
;
d->count++;
if (d->count >= d_allocated)
{
- char_directive *memory;
+ DIRECTIVE *memory;
d_allocated = 2 * d_allocated;
- memory = realloc (d->dir, d_allocated * sizeof (char_directive));
+ memory = realloc (d->dir, d_allocated * sizeof (DIRECTIVE));
if (memory == NULL)
/* Out of memory. */
goto error;
free (d->dir);
return -1;
}
+
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef PRINTF_PARSE
#include <alloca.h>
/* Specification. */
-#include "vasnprintf.h"
+#if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+#else
+# include "vasnprintf.h"
+#endif
#include <stdio.h> /* snprintf(), sprintf() */
#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
#include <errno.h> /* errno */
#include <limits.h> /* CHAR_BIT */
#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
-#include "printf-parse.h"
+#if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+#else
+# include "printf-parse.h"
+#endif
/* For those losing systems which don't have 'alloca' we have to add
- some additional code emulating it. */
-#ifdef HAVE_ALLOCA
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
# define freea(p) /* nothing */
#else
-# define alloca(n) malloc (n)
-# define freea(p) free (p)
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
#endif
-char *
-vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+#if WIDE_CHAR_VERSION
+# define VASNPRINTF vasnwprintf
+# define CHAR_T wchar_t
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+# define PRINTF_PARSE wprintf_parse
+# define USE_SNPRINTF 1
+# define SNPRINTF swprintf
+#else
+# define VASNPRINTF vasnprintf
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+# define PRINTF_PARSE printf_parse
+# define USE_SNPRINTF HAVE_SNPRINTF
+# define SNPRINTF snprintf
+#endif
+
+CHAR_T *
+VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
{
- char_directives d;
+ DIRECTIVES d;
arguments a;
- if (printf_parse (format, &d, &a) < 0)
+ if (PRINTF_PARSE (format, &d, &a) < 0)
{
errno = EINVAL;
return NULL;
}
{
- char *buf =
- (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
- const char *cp;
+ CHAR_T *buf =
+ (CHAR_T *) alloca ((7 + d.max_width_length + d.max_precision_length + 6)
+ * sizeof (CHAR_T));
+ const CHAR_T *cp;
unsigned int i;
- char_directive *dp;
+ DIRECTIVE *dp;
/* Output string accumulator. */
- char *result;
+ CHAR_T *result;
size_t allocated;
size_t length;
If length > 0, then result != NULL. */
#define ENSURE_ALLOCATION(needed) \
- if ((needed) > allocated) \
- { \
- char *memory; \
- \
- allocated = (allocated > 0 ? 2 * allocated : 12); \
- if ((needed) > allocated) \
- allocated = (needed); \
- if (result == resultbuf || result == NULL) \
- memory = (char *) malloc (allocated); \
- else \
- memory = (char *) realloc (result, allocated); \
- \
- if (memory == NULL) \
- { \
- if (!(result == resultbuf || result == NULL)) \
- free (result); \
- freea (buf); \
- CLEANUP (); \
- errno = ENOMEM; \
- return NULL; \
- } \
- if (result == resultbuf && length > 0) \
- memcpy (memory, result, length); \
- result = memory; \
+ if ((needed) > allocated) \
+ { \
+ CHAR_T *memory; \
+ \
+ allocated = (allocated > 0 ? 2 * allocated : 12); \
+ if ((needed) > allocated) \
+ allocated = (needed); \
+ if (result == resultbuf || result == NULL) \
+ memory = (CHAR_T *) malloc (allocated * sizeof (CHAR_T)); \
+ else \
+ memory = (CHAR_T *) realloc (result, allocated * sizeof (CHAR_T)); \
+ \
+ if (memory == NULL) \
+ { \
+ if (!(result == resultbuf || result == NULL)) \
+ free (result); \
+ freea (buf); \
+ CLEANUP (); \
+ errno = ENOMEM; \
+ return NULL; \
+ } \
+ if (result == resultbuf && length > 0) \
+ memcpy (memory, result, length * sizeof (CHAR_T)); \
+ result = memory; \
}
for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
size_t n = dp->dir_start - cp;
ENSURE_ALLOCATION (length + n);
- memcpy (result + length, cp, n);
+ memcpy (result + length, cp, n * sizeof (CHAR_T));
length += n;
}
if (i == d.count)
else
{
arg_type type = a.arg[dp->arg_index].type;
- char *p;
+ CHAR_T *p;
unsigned int prefix_count;
int prefixes[2];
-#if !HAVE_SNPRINTF
+#if !USE_SNPRINTF
unsigned int tmp_length;
- char tmpbuf[700];
- char *tmp;
+ CHAR_T tmpbuf[700];
+ CHAR_T *tmp;
/* Allocate a temporary buffer of sufficient size for calling
sprintf. */
}
else
{
- const char *digitp = dp->width_start;
+ const CHAR_T *digitp = dp->width_start;
do
width = width * 10 + (*digitp++ - '0');
}
else
{
- const char *digitp = dp->precision_start + 1;
+ const CHAR_T *digitp = dp->precision_start + 1;
precision = 0;
do
break;
case 'c':
-# ifdef HAVE_WINT_T
+# if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
if (type == TYPE_WIDE_CHAR)
tmp_length = MB_CUR_MAX;
else
case 's':
# ifdef HAVE_WCHAR_T
if (type == TYPE_WIDE_STRING)
+# if WIDE_CHAR_VERSION
+ tmp_length =
+ wcslen (a.arg[dp->arg_index].a.a_wide_string);
+# else
tmp_length =
wcslen (a.arg[dp->arg_index].a.a_wide_string)
* MB_CUR_MAX;
+# endif
else
# endif
tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
tmp_length++; /* account for trailing NUL */
}
- if (tmp_length <= sizeof (tmpbuf))
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
tmp = tmpbuf;
else
{
- tmp = (char *) malloc (tmp_length);
+ tmp = (CHAR_T *) malloc (tmp_length * sizeof (CHAR_T));
if (tmp == NULL)
{
/* Out of memory. */
if (dp->width_start != dp->width_end)
{
size_t n = dp->width_end - dp->width_start;
- memcpy (p, dp->width_start, n);
+ memcpy (p, dp->width_start, n * sizeof (CHAR_T));
p += n;
}
if (dp->precision_start != dp->precision_end)
{
size_t n = dp->precision_end - dp->precision_start;
- memcpy (p, dp->precision_start, n);
+ memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
p += n;
}
break;
}
*p = dp->conversion;
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
p[1] = '%';
p[2] = 'n';
p[3] = '\0';
prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
}
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
/* Prepare checking whether snprintf returns the count
via %n. */
ENSURE_ALLOCATION (length + 1);
count = -1;
retcount = 0;
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
#define SNPRINTF_BUF(arg) \
switch (prefix_count) \
{ \
case 0: \
- retcount = snprintf (result + length, maxlen, buf, \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
arg, &count); \
break; \
case 1: \
- retcount = snprintf (result + length, maxlen, buf, \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
prefixes[0], arg, &count); \
break; \
case 2: \
- retcount = snprintf (result + length, maxlen, buf, \
+ retcount = SNPRINTF (result + length, maxlen, buf, \
prefixes[0], prefixes[1], arg, \
&count); \
break; \
abort ();
}
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
/* Portability: Not all implementations of snprintf()
are ISO C 99 compliant. Determine the number of
bytes that snprintf() has produced or would have
return NULL;
}
-#if !HAVE_SNPRINTF
+#if !USE_SNPRINTF
if (count >= tmp_length)
/* tmp_length was incorrectly calculated - fix the
code above! */
n = 2 * allocated;
ENSURE_ALLOCATION (n);
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
continue;
#endif
}
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
/* The snprintf() result did fit. */
#else
/* Append the sprintf() result. */
- memcpy (result + length, tmp, count);
+ memcpy (result + length, tmp, count * sizeof (CHAR_T));
if (tmp != tmpbuf)
free (tmp);
#endif
if (result != resultbuf && length + 1 < allocated)
{
/* Shrink the allocated memory if possible. */
- char *memory;
+ CHAR_T *memory;
- memory = (char *) realloc (result, length + 1);
+ memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
if (memory != NULL)
result = memory;
}
return result;
}
}
+
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef VASNPRINTF
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * printf-posix.m4: New file.
+ * Makefile.am (EXTRA_DIST): Add printf-posix.m4.
+ * gettext.m4 (AM_INTL_SUBDIR): Require bh_C_SIGNED,
+ jm_AC_TYPE_LONG_LONG, gt_TYPE_LONGDOUBLE, gt_TYPE_WCHAR_T,
+ gt_TYPE_WINT_T, jm_AC_HEADER_INTTYPES_H, jm_AC_HEADER_STDINT_H,
+ gt_TYPE_INTMAX_T, gt_PRINTF_POSIX. Check for ptrdiff_t, asprintf,
+ snprintf, wprintf.
+ * longlong.m4: Update from gnulib.
+ (jm_AC_TYPE_LONG_LONG): Replaces gt_TYPE_LONGLONG.
+
2003-01-11 Bruno Haible <bruno@clisp.org>
* ulonglong.m4 (jm_AC_TYPE_UNSIGNED_LONG_LONG): Also test the ULL
longlong.m4 \
nls.m4 \
po.m4 \
+printf-posix.m4 \
progtest.m4 \
signed.m4 \
stdint_h.m4 \
-# gettext.m4 serial 20 (gettext-0.12)
+# gettext.m4 serial 21 (gettext-0.12.2)
dnl Copyright (C) 1995-2003 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
AC_REQUIRE([AC_ISC_POSIX])dnl
AC_REQUIRE([AC_HEADER_STDC])dnl
AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([bh_C_SIGNED])dnl
AC_REQUIRE([AC_C_INLINE])dnl
AC_REQUIRE([AC_TYPE_OFF_T])dnl
AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([jm_AC_TYPE_LONG_LONG])dnl
+ AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl
+ AC_REQUIRE([gt_TYPE_WCHAR_T])dnl
+ AC_REQUIRE([gt_TYPE_WINT_T])dnl
+ AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([jm_AC_HEADER_STDINT_H])
+ AC_REQUIRE([gt_TYPE_INTMAX_T])
+ AC_REQUIRE([gt_PRINTF_POSIX])
AC_REQUIRE([AC_FUNC_ALLOCA])dnl
AC_REQUIRE([AC_FUNC_MMAP])dnl
AC_REQUIRE([jm_GLIBC21])dnl
AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl
AC_REQUIRE([gt_INTTYPES_PRI])dnl
+ AC_CHECK_TYPES([ptrdiff_t])
AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
stdlib.h string.h unistd.h sys/param.h])
- AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \
-geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \
-strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next \
-__fsetlocking])
+ AC_CHECK_FUNCS([asprintf feof_unlocked fgets_unlocked getc_unlocked getcwd \
+getegid geteuid getgid getuid mempcpy munmap putenv setenv setlocale snprintf \
+stpcpy strcasecmp strdup strtoul tsearch wprintf __argz_count \
+__argz_stringify __argz_next __fsetlocking])
+
+ case $gt_cv_func_printf_posix in
+ *yes) HAVE_POSIX_PRINTF=1 ;;
+ *) HAVE_POSIX_PRINTF=0 ;;
+ esac
+ AC_SUBST([HAVE_POSIX_PRINTF])
+ if test "$ac_cv_func_asprintf" = yes; then
+ HAVE_ASPRINTF=1
+ else
+ HAVE_ASPRINTF=0
+ fi
+ AC_SUBST([HAVE_ASPRINTF])
+ if test "$ac_cv_func_snprintf" = yes; then
+ HAVE_SNPRINTF=1
+ else
+ HAVE_SNPRINTF=0
+ fi
+ AC_SUBST([HAVE_SNPRINTF])
+ if test "$ac_cv_func_wprintf" = yes; then
+ HAVE_WPRINTF=1
+ else
+ HAVE_WPRINTF=0
+ fi
+ AC_SUBST([HAVE_WPRINTF])
AM_ICONV
AM_LANGINFO_CODESET
-# longlong.m4 serial 1 (gettext-0.12)
-dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
+# longlong.m4 serial 4
+dnl Copyright (C) 1999-2003 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program.
-dnl From Bruno Haible.
-dnl Test whether the compiler supports the 'long long' type.
-dnl Prerequisite: AC_PROG_CC
+dnl From Paul Eggert.
-AC_DEFUN([gt_TYPE_LONGLONG],
+# Define HAVE_LONG_LONG if 'long long' works.
+
+AC_DEFUN([jm_AC_TYPE_LONG_LONG],
[
- AC_CACHE_CHECK([for long long], gt_cv_c_long_long,
- [if test "$GCC" = yes; then
- gt_cv_c_long_long=yes
- else
- AC_TRY_COMPILE([long long foo = 0LL;
- int array [2*(sizeof(long long) >= sizeof(long)) - 1];
- ], ,
- gt_cv_c_long_long=yes, gt_cv_c_long_long=no)
- fi])
- if test $gt_cv_c_long_long = yes; then
- AC_DEFINE(HAVE_LONG_LONG, 1, [Define if you have the 'long long' type.])
+ AC_CACHE_CHECK([for long long], ac_cv_type_long_long,
+ [AC_TRY_LINK([long long ll = 1LL; int i = 63;],
+ [long long llmax = (long long) -1;
+ return ll << i | ll >> i | llmax / ll | llmax % ll;],
+ ac_cv_type_long_long=yes,
+ ac_cv_type_long_long=no)])
+ if test $ac_cv_type_long_long = yes; then
+ AC_DEFINE(HAVE_LONG_LONG, 1,
+ [Define if you have the 'long long' type.])
fi
])
--- /dev/null
+# printf-posix.m4 serial 1 (gettext-0.12.2)
+dnl Copyright (C) 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+dnl Test whether the printf() function supports POSIX/XSI format strings with
+dnl positions.
+
+AC_DEFUN([gt_PRINTF_POSIX],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings],
+ gt_cv_func_printf_posix,
+ [
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+static char buf[100];
+int main ()
+{
+ sprintf (buf, "%2$d %1$d", 33, 55);
+ return (strcmp (buf, "55 33") == 0);
+}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no,
+ [
+ AC_EGREP_CPP(notposix, [
+#if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__
+ notposix
+#endif
+ ], gt_cv_func_printf_posix="guessing no",
+ gt_cv_func_printf_posix="guessing yes")
+ ])
+ ])
+ case $gt_cv_func_printf_posix in
+ *yes)
+ AC_DEFINE(HAVE_POSIX_PRINTF, 1,
+ [Define if your printf() function supports format strings with positions.])
+ ;;
+ esac
+])
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * gettext.texi (Sources): Recommend to use <libintl.h> also for printf.
+ (aclocal): Mention also intmax.m4, longdouble.m4, longlong.m4,
+ printf-posix.m4, signed.m4, wchar_t.m4, wint_t.m4.
+ (c-format): Mention the printf(), fprintf() replacements.
+ (C, clisp C): Remove portability note for formatting with positions.
+
2003-06-15 Bruno Haible <bruno@clisp.org>
* gettext.texi (C): Mention that formatting with positions doesn't work
#include <libintl.h>
@end example
+Similarly, each C module containing @code{printf()}/@code{fprintf()}/...
+calls with a format string that could be a translated C string (even if
+the C string comes from a different C module) should contain the line:
+
+@example
+#include <libintl.h>
+@end example
+
The remaining changes to your C sources are discussed in the further
sections of this chapter.
If you do not have an @file{aclocal.m4} file in your distribution,
the simplest is to concatenate the files @file{codeset.m4},
@file{gettext.m4}, @file{glibc21.m4}, @file{iconv.m4}, @file{intdiv0.m4},
-@file{inttypes.m4}, @file{inttypes_h.m4}, @file{inttypes-pri.m4},
-@file{isc-posix.m4}, @file{lcmessage.m4}, @file{lib-ld.m4},
-@file{lib-link.m4}, @file{lib-prefix.m4}, @file{progtest.m4},
-@file{stdint_h.m4}, @file{uintmax_t.m4}, @file{ulonglong.m4}
+@file{intmax.m4}, @file{inttypes.m4}, @file{inttypes_h.m4},
+@file{inttypes-pri.m4}, @file{isc-posix.m4}, @file{lcmessage.m4},
+@file{lib-ld.m4}, @file{lib-link.m4}, @file{lib-prefix.m4},
+@file{longdouble.m4}, @file{longlong.m4}, @file{printf-posix.m4},
+@file{progtest.m4}, @file{signed.m4}, @file{stdint_h.m4}, @file{uintmax_t.m4},
+@file{ulonglong.m4}, @file{wchar_t.m4}, @file{wint_t.m4}
from GNU @code{gettext}'s
@file{m4/} directory into a single file. If you have suppressed the
@file{intl/} directory, only @file{gettext.m4}, @file{iconv.m4},
@uref{http://www.linuxvalley.it/encyclopedia/ldp/manpage/man3/printf.3.php},
@uref{http://informatik.fh-wuerzburg.de/student/i510/man/printf.html}.
+Although format strings with positions that reorder arguments, such as
+
+@example
+"Only %2$d bytes free on '%1$s'."
+@end example
+
+@noindent
+which is semantically equivalent to
+
+@example
+"'%s' has only %d bytes free."
+@end example
+
+@noindent
+are a POSIX/XSI feature and not specified by ISO C 99, translators can rely
+on this reordering ability: On the few platforms where @code{printf()},
+@code{fprintf()} etc. don't support this feature natively, @file{libintl.a}
+or @file{libintl.so} provides replacement functions, and GNU @code{<libintl.h>}
+activates these replacement functions automatically.
+
@node python-format, lisp-format, c-format, Translators for other Languages
@subsection Python Format Strings
@code{xgettext -k_}
@item Formatting with positions
-@code{fprintf "%2$d %1$d"} (POSIX/XSI but not C 99 - in practice, not NetBSD and not Windows)
+@code{fprintf "%2$d %1$d"}
@*In C++: @code{autosprintf "%2$d %1$d"}
(@pxref{Top, , Introduction, autosprintf, GNU autosprintf})
@code{clisp-xgettext}
@item Formatting with positions
-@code{fprintf "%2$d %1$d"} (POSIX/XSI but not C 99)
+@code{fprintf "%2$d %1$d"}
@item Portability
On platforms without gettext, no translation.
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * Makefile.am (aclocal_DATA): Add intmax.m4, longdouble.m4,
+ longlong.m4, printf-posix.m4, signed.m4, wchar_t.m4, wint_t.m4.
+
2003-06-19 Bruno Haible <bruno@clisp.org>
* locale-fr.m4: New file.
../../gettext-runtime/m4/glibc21.m4 \
../../gettext-runtime/m4/iconv.m4 \
../../gettext-runtime/m4/intdiv0.m4 \
+ ../../gettext-runtime/m4/intmax.m4 \
../../gettext-runtime/m4/inttypes.m4 \
../../gettext-runtime/m4/inttypes_h.m4 \
../../gettext-runtime/m4/inttypes-pri.m4 \
../../gettext-runtime/m4/isc-posix.m4 \
../../gettext-runtime/m4/lcmessage.m4 \
+ ../../gettext-runtime/m4/longdouble.m4 \
+ ../../gettext-runtime/m4/longlong.m4 \
../../gettext-runtime/m4/nls.m4 \
../../gettext-runtime/m4/po.m4 \
+ ../../gettext-runtime/m4/printf-posix.m4 \
../../gettext-runtime/m4/progtest.m4 \
+ ../../gettext-runtime/m4/signed.m4 \
../../gettext-runtime/m4/stdint_h.m4 \
../../gettext-runtime/m4/uintmax_t.m4 \
- ../../gettext-runtime/m4/ulonglong.m4
+ ../../gettext-runtime/m4/ulonglong.m4 \
+ ../../gettext-runtime/m4/wchar_t.m4 \
+ ../../gettext-runtime/m4/wint_t.m4
# Generate this list with
# find . -type f -name '*.m4' -printf '%f\n' | sort | tr '\012' @ | sed 's/@$/%/;s/@/ \\@/g' | tr @% '\012\012'
+2003-06-19 Bruno Haible <bruno@clisp.org>
+
+ * gettextize.in (m4filelist): Add intmax.m4, longdouble.m4,
+ longlong.m4, printf-posix.m4, signed.m4, wchar_t.m4, wint_t.m4.
+
2003-05-22 Bruno Haible <bruno@clisp.org>
* gettext-0.12.1 released.
fi
$do_changelog && func_poChangeLog_finish
-m4filelist=' codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 inttypes.m4
- inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4 lib-link.m4
- lib-prefix.m4 nls.m4 po.m4 progtest.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4'
-# We cannot omit codeset.m4, glibc21.m4, intdiv0.m4, inttypes.m4,
-# inttypes_h.m4, inttypes-pri.m4, isc-posix.m4, lcmessage.m4, nls.m4, po.m4,
-# stdint_h.m4, uintmax_t.m4, ulonglong.m4
+m4filelist=' codeset.m4 gettext.m4 glibc21.m4 iconv.m4 intdiv0.m4 intmax.m4
+ inttypes.m4 inttypes_h.m4 inttypes-pri.m4 isc-posix.m4 lcmessage.m4 lib-ld.m4
+ lib-link.m4 lib-prefix.m4 longdouble.m4 longlong.m4 nls.m4 po.m4
+ printf-posix.m4 progtest.m4 signed.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4
+ wchar_t.m4 wint_t.m4'
+# We cannot omit codeset.m4, glibc21.m4, intdiv0.m4, intmax.m4, inttypes.m4,
+# inttypes_h.m4, inttypes-pri.m4, isc-posix.m4, lcmessage.m4, longdouble.m4,
+# longlong.m4, nls.m4, po.m4, printf-posix.m4, signed.m4, stdint_h.m4,
+# uintmax_t.m4, ulonglong.m4, wchar_t.m4, wint_t.m4
# if test -z "$intldir", otherwise "aclocal -I m4" might give an error.
# (aclocal doesn't know which macros are really needed, it looks which macros
# are potentially needed.)