]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Add an implementation of printf(), fprintf() etc. that supports formatting
authorBruno Haible <bruno@clisp.org>
Thu, 19 Jun 2003 12:45:06 +0000 (12:45 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:10:42 +0000 (12:10 +0200)
with positions, for those systems that lack it (NetBSD, Woe32).

33 files changed:
ChangeLog
PACKAGING
gettext-runtime/ChangeLog
gettext-runtime/Makefile.am
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/Makefile.in
gettext-runtime/intl/Makefile.msvc
gettext-runtime/intl/Makefile.vms
gettext-runtime/intl/libgnuintl.h.in
gettext-runtime/intl/printf-args.c [new file with mode: 0644]
gettext-runtime/intl/printf-args.h [new file with mode: 0644]
gettext-runtime/intl/printf-parse.c [new file with mode: 0644]
gettext-runtime/intl/printf-parse.h [new file with mode: 0644]
gettext-runtime/intl/printf.c [new file with mode: 0644]
gettext-runtime/intl/vasnprintf.c [new file with mode: 0644]
gettext-runtime/intl/vasnprintf.h [new file with mode: 0644]
gettext-runtime/intl/vasnwprintf.h [new file with mode: 0644]
gettext-runtime/intl/wprintf-parse.h [new file with mode: 0644]
gettext-runtime/libasprintf/ChangeLog
gettext-runtime/libasprintf/configure.ac
gettext-runtime/libasprintf/printf-parse.c
gettext-runtime/libasprintf/vasnprintf.c
gettext-runtime/m4/ChangeLog
gettext-runtime/m4/Makefile.am
gettext-runtime/m4/gettext.m4
gettext-runtime/m4/longlong.m4
gettext-runtime/m4/printf-posix.m4 [new file with mode: 0644]
gettext-tools/doc/ChangeLog
gettext-tools/doc/gettext.texi
gettext-tools/m4/ChangeLog
gettext-tools/m4/Makefile.am
gettext-tools/misc/ChangeLog
gettext-tools/misc/gettextize.in

index 5e7f1450f969358449315be891338f46d1d6cf72..a2f1566b9e5b2bfe9dba917815ef362c3419de32 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+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.
index b92d00724b267436279775395e9657cb3e062fe1..9a53831f2f1ac7f8eb2ebd31acabc0c1fd68d7be 100644 (file)
--- a/PACKAGING
+++ b/PACKAGING
@@ -111,6 +111,7 @@ following file list.
       $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
@@ -119,12 +120,18 @@ following file list.
       $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
index 58c8c96e9bd80e6aca506a8d2f2ff16bd3b445f7..2f9a688a4018c902cb14097862c330e9b89f5662 100644 (file)
@@ -1,3 +1,11 @@
+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.
index 347d6394b9d2fbb1eb1b6e51f6a9328bd5ec51bc..99ed8ae967af3a31327d98d9978c359617405497 100644 (file)
@@ -69,12 +69,16 @@ config.h_vms: config.h.in ../version.sh
             -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/' \
@@ -94,6 +98,9 @@ config.h_vms: config.h.in ../version.sh
             -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/' \
@@ -104,6 +111,15 @@ config.h_vms: config.h.in ../version.sh
 # 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
 
 
@@ -120,9 +136,12 @@ config.h.msvc: config.h.in ../version.sh
            -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/' \
@@ -132,6 +151,9 @@ config.h.msvc: config.h.in ../version.sh
            -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/' \
@@ -142,9 +164,22 @@ config.h.msvc: config.h.in ../version.sh
            -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
index 9aeb58f81495d8d2173b824979bc3bcef5620da0..f2645f87c9ead62a4b68f38a2b00ce4b5104a348 100644 (file)
@@ -1,3 +1,32 @@
+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.
index 882396481f620524c7fb5f73c56e7a4453b59866..a4d299298c725deae589dd8a3250d7898ababb35 100644 (file)
@@ -73,6 +73,9 @@ HEADERS = \
   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 = \
@@ -96,6 +99,7 @@ SOURCES = \
   relocatable.c \
   localename.c \
   log.c \
+  printf.c \
   osdep.c \
   os2compat.c \
   intl-compat.c
@@ -120,6 +124,7 @@ OBJECTS = \
   relocatable.$lo \
   localename.$lo \
   log.$lo \
+  printf.$lo \
   osdep.$lo \
   intl-compat.$lo
 DISTFILES.common = Makefile.in \
@@ -127,7 +132,8 @@ config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES)
 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
 
@@ -209,6 +215,8 @@ localename.lo: $(srcdir)/localename.c
        $(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
@@ -224,7 +232,11 @@ ref-del.sed: $(srcdir)/ref-del.sin
 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
@@ -412,6 +424,7 @@ dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.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
 
index 552a3f6c998a0ee6674ba08409ad987c31e4214d..7fbb2f75cf0cdd5df4c53ad90ebd32e455c2a242 100644 (file)
@@ -99,7 +99,7 @@ INSTALL_DATA = copy
 
 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
 
@@ -107,7 +107,7 @@ all : intl.lib libintl.h
 
 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
@@ -172,6 +172,9 @@ localename.obj : $(srcdir)\localename.c libgnuintl.h
 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
 
index 4db38fbe645e1d0e1783ba2031b9b5bc04021312..97ab0112994a78b4b3e9f509b8e58b7ff7d6d104 100644 (file)
@@ -51,8 +51,7 @@ all : intl.olb,libintl.h
        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
index b6c526c83bf19394afcc6f3c55e520aeefdf2062..ce06b18be9e390fde93d943cfe68b8a16cb128e3 100644 (file)
@@ -289,6 +289,97 @@ extern char *bind_textdomain_codeset _INTL_PARAMS ((const char *__domainname,
 #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.
diff --git a/gettext-runtime/intl/printf-args.c b/gettext-runtime/intl/printf-args.c
new file mode 100644 (file)
index 0000000..f391974
--- /dev/null
@@ -0,0 +1,119 @@
+/* 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;
+}
diff --git a/gettext-runtime/intl/printf-args.h b/gettext-runtime/intl/printf-args.h
new file mode 100644 (file)
index 0000000..35114a8
--- /dev/null
@@ -0,0 +1,134 @@
+/* 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 */
diff --git a/gettext-runtime/intl/printf-parse.c b/gettext-runtime/intl/printf-parse.c
new file mode 100644 (file)
index 0000000..ff61c17
--- /dev/null
@@ -0,0 +1,498 @@
+/* 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
diff --git a/gettext-runtime/intl/printf-parse.h b/gettext-runtime/intl/printf-parse.h
new file mode 100644 (file)
index 0000000..97e432a
--- /dev/null
@@ -0,0 +1,72 @@
+/* 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 */
diff --git a/gettext-runtime/intl/printf.c b/gettext-runtime/intl/printf.c
new file mode 100644 (file)
index 0000000..c96ad2f
--- /dev/null
@@ -0,0 +1,308 @@
+/* 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
diff --git a/gettext-runtime/intl/vasnprintf.c b/gettext-runtime/intl/vasnprintf.c
new file mode 100644 (file)
index 0000000..b8bd3ce
--- /dev/null
@@ -0,0 +1,807 @@
+/* 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
diff --git a/gettext-runtime/intl/vasnprintf.h b/gettext-runtime/intl/vasnprintf.h
new file mode 100644 (file)
index 0000000..65f1bc1
--- /dev/null
@@ -0,0 +1,61 @@
+/* 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 */
diff --git a/gettext-runtime/intl/vasnwprintf.h b/gettext-runtime/intl/vasnwprintf.h
new file mode 100644 (file)
index 0000000..d3cef4c
--- /dev/null
@@ -0,0 +1,46 @@
+/* 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 */
diff --git a/gettext-runtime/intl/wprintf-parse.h b/gettext-runtime/intl/wprintf-parse.h
new file mode 100644 (file)
index 0000000..83ebbf0
--- /dev/null
@@ -0,0 +1,72 @@
+/* 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 */
index 338776e386da0df25116cf7680b4ae32535dc4a5..a3f00c80b2c4b18b364f1a2f478c64a4d7bf6475 100644 (file)
@@ -1,3 +1,12 @@
+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.
index b3f427678327ae27851d5786a975342354b76a55..9d1ed6cac832991300b25e6df09b359e2afd59be 100644 (file)
@@ -48,7 +48,7 @@ dnl Checks for typedefs, structures, and compiler characteristics.
 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
index bdfe88fe8f8942f57fe26295a34bd2bc5e35e9c2..ff61c174ced6c239c4750a915d20824085a9c061 100644 (file)
 #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 */
@@ -52,7 +68,7 @@ printf_parse (const char *format, char_directives *d, arguments *a)
 
   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;
@@ -89,11 +105,11 @@ printf_parse (const char *format, char_directives *d, arguments *a)
 
   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;
@@ -109,7 +125,7 @@ printf_parse (const char *format, char_directives *d, arguments *a)
          /* Test for positional argument.  */
          if (*cp >= '0' && *cp <= '9')
            {
-             const char *np;
+             const CHAR_T *np;
 
              for (np = cp; *np >= '0' && *np <= '9'; np++)
                ;
@@ -176,7 +192,7 @@ printf_parse (const char *format, char_directives *d, arguments *a)
              /* Test for positional argument.  */
              if (*cp >= '0' && *cp <= '9')
                {
-                 const char *np;
+                 const CHAR_T *np;
 
                  for (np = cp; *np >= '0' && *np <= '9'; np++)
                    ;
@@ -225,7 +241,7 @@ printf_parse (const char *format, char_directives *d, arguments *a)
                  /* Test for positional argument.  */
                  if (*cp >= '0' && *cp <= '9')
                    {
-                     const char *np;
+                     const CHAR_T *np;
 
                      for (np = cp; *np >= '0' && *np <= '9'; np++)
                        ;
@@ -451,10 +467,10 @@ printf_parse (const char *format, char_directives *d, arguments *a)
          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;
@@ -475,3 +491,8 @@ error:
     free (d->dir);
   return -1;
 }
+
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef PRINTF_PARSE
index 7aac42bcd5749424d1915907d890bc9d006da38e..b8bd3ce85d88f7db4f0cb14e10c95d794e575015 100644 (file)
 #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;
@@ -73,13 +99,14 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
     }
 
   {
-    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;
 
@@ -99,30 +126,30 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
        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++)
@@ -132,7 +159,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
            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)
@@ -180,13 +207,13 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
            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.  */
@@ -208,7 +235,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                        }
                      else
                        {
-                         const char *digitp = dp->width_start;
+                         const CHAR_T *digitp = dp->width_start;
 
                          do
                            width = width * 10 + (*digitp++ - '0');
@@ -230,7 +257,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                        }
                      else
                        {
-                         const char *digitp = dp->precision_start + 1;
+                         const CHAR_T *digitp = dp->precision_start + 1;
 
                          precision = 0;
                          do
@@ -357,7 +384,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                      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
@@ -368,9 +395,14 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                    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);
@@ -395,11 +427,11 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                  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.  */
@@ -432,13 +464,13 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                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;
                  }
 
@@ -469,7 +501,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                    break;
                  }
                *p = dp->conversion;
-#if HAVE_SNPRINTF
+#if USE_SNPRINTF
                p[1] = '%';
                p[2] = 'n';
                p[3] = '\0';
@@ -492,7 +524,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                    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);
@@ -509,20 +541,20 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                    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;                                              \
@@ -664,7 +696,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                        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
@@ -705,7 +737,7 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                        return NULL;
                      }
 
-#if !HAVE_SNPRINTF
+#if !USE_SNPRINTF
                    if (count >= tmp_length)
                      /* tmp_length was incorrectly calculated - fix the
                         code above!  */
@@ -724,16 +756,16 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
                          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
@@ -752,9 +784,9 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
     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;
       }
@@ -765,3 +797,11 @@ vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
     return result;
   }
 }
+
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T
+#undef VASNPRINTF
index e553ded18635d6dfe2f928098baa6175491d5724..3ef0b9c5ab90168cd74902ad851581c9a20c9551 100644 (file)
@@ -1,3 +1,15 @@
+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
index 2cb866bae8ac65e86e2fbfcf0b714e2e777cb190..130539180858c3307dba95debb81e738f1b736a4 100644 (file)
@@ -19,6 +19,7 @@ longdouble.m4 \
 longlong.m4 \
 nls.m4 \
 po.m4 \
+printf-posix.m4 \
 progtest.m4 \
 signed.m4 \
 stdint_h.m4 \
index 16070b40a99c5d99dffdf3e43672e75901355334..1bf54ff0dc0815dd5cddbcc02509310d73ad22e9 100644 (file)
@@ -1,4 +1,4 @@
-# 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
@@ -354,9 +354,18 @@ AC_DEFUN([AM_INTL_SUBDIR],
   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
@@ -365,12 +374,37 @@ AC_DEFUN([AM_INTL_SUBDIR],
   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
index b4f472db8aa3c4e90ceacbde51044fbc2d987307..d7d7350b3f53bc18f92ee82cb501a8819e0c28d0 100644 (file)
@@ -1,27 +1,25 @@
-# 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
 ])
diff --git a/gettext-runtime/m4/printf-posix.m4 b/gettext-runtime/m4/printf-posix.m4
new file mode 100644 (file)
index 0000000..d96c32c
--- /dev/null
@@ -0,0 +1,43 @@
+# 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
+])
index 52519def7cca9f016d978a0a298cc19fc55c78f4..2bba4138e2f2fbcce18566e0f6ccaea07bb8468f 100644 (file)
@@ -1,3 +1,11 @@
+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
index 5d1d197ba247cfc1485feb2b8d34d4f0e8a04ed1..07a1099a9db90dd73a31219bed72ce8207a135f5 100644 (file)
@@ -1709,6 +1709,14 @@ having translated C strings should contain the line:
 #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.
 
@@ -6426,10 +6434,12 @@ AC_CONFIG_AUX_DIR([@var{subdir}])
 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},
@@ -7210,6 +7220,26 @@ See also the fprintf(3) manual page,
 @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
 
@@ -7450,7 +7480,7 @@ Use
 @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})
 
@@ -7711,7 +7741,7 @@ use
 @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.
index a8f6de07c50e16f3d0c29d1bf3bbea3b5fbc6937..4d145a2fef2105804d34ba3ee72d170beb261a4b 100644 (file)
@@ -1,3 +1,8 @@
+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.
index b315fd0b47868f6e04f697f1301ae34ca1a298db..bfac6f135626d0e656b34e660b186807afae3dfd 100644 (file)
@@ -12,17 +12,24 @@ aclocal_DATA = \
   ../../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'
index 149a9c4a2724b89323085c51385f5c5b31b9e912..18004368764d8d5888b08fcb885a547ecbf42758 100644 (file)
@@ -1,3 +1,8 @@
+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.
index 7bb0f453b2ce543eb456e8dbe095cb0c216707d1..52a0f1dd05f78343184309aa3cafaaa3157ded5e 100644 (file)
@@ -638,12 +638,15 @@ if test -f "$srcdir/po/stamp-cat-id"; then
 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.)