Hi, Just noticed that gnulib's vasnprintf function does not support the same flags as the underlying system. In particular, glibc's 'I' flag (that causes localized digits to appear in the output instead of ASCII digits - a feature used in Farsi and Indic languages) ought to be supported by vasnprintf.
This fixes it. 2010-11-07 Bruno Haible <br...@clisp.org> vasnprintf: Support I flag on glibc systems. * lib/printf-parse.h (FLAG_LOCALIZED): New macro. * lib/printf-parse.c (PRINTF_PARSE): Handle the 'I' flag. * lib/vasnprintf.c (VASNPRINTF): Pass the 'I' flag on to the system's snprintf function. * tests/test-vasnprintf-posix.c (test_function): Test the 'I' flag on glibc systems. * tests/test-vasnprintf-posix3.c: New file. * modules/vasnprintf-posix-tests (Files): Add it. (TESTS, check_PROGRAMS): Add test-vasnprintf-posix3. --- lib/printf-parse.c.orig Sun Nov 7 18:50:15 2010 +++ lib/printf-parse.c Sun Nov 7 17:39:27 2010 @@ -206,6 +206,13 @@ dp->flags |= FLAG_ZERO; cp++; } +#if __GLIBC__ >= 2 + else if (*cp == 'I') + { + dp->flags |= FLAG_LOCALIZED; + cp++; + } +#endif else break; } --- lib/printf-parse.h.orig Sun Nov 7 18:50:15 2010 +++ lib/printf-parse.h Sun Nov 7 18:48:45 2010 @@ -33,6 +33,9 @@ #define FLAG_SPACE 8 /* space flag */ #define FLAG_ALT 16 /* # flag */ #define FLAG_ZERO 32 +#if __GLIBC__ >= 2 +# define FLAG_LOCALIZED 64 /* I flag, uses localized digits */ +#endif /* arg_index value indicating that no argument is consumed. */ #define ARG_NONE (~(size_t)0) --- lib/vasnprintf.c.orig Sun Nov 7 18:50:15 2010 +++ lib/vasnprintf.c Sun Nov 7 17:45:20 2010 @@ -4754,6 +4754,10 @@ *fbp++ = ' '; if (flags & FLAG_ALT) *fbp++ = '#'; +#if __GLIBC__ >= 2 + if (flags & FLAG_LOCALIZED) + *fbp++ = 'I'; +#endif if (!pad_ourselves) { if (flags & FLAG_ZERO) --- modules/vasnprintf-posix-tests.orig Sun Nov 7 18:50:15 2010 +++ modules/vasnprintf-posix-tests Sun Nov 7 18:13:12 2010 @@ -2,6 +2,7 @@ tests/test-vasnprintf-posix.c tests/test-vasnprintf-posix2.sh tests/test-vasnprintf-posix2.c +tests/test-vasnprintf-posix3.c tests/minus-zero.h tests/nan.h tests/macros.h @@ -17,6 +18,6 @@ gt_LOCALE_FR_UTF8 Makefile.am: -TESTS += test-vasnprintf-posix test-vasnprintf-posix2.sh +TESTS += test-vasnprintf-posix test-vasnprintf-posix2.sh test-vasnprintf-posix3 TESTS_ENVIRONMENT += LOCALE_FR='@LOCALE_FR@' LOCALE_FR_UTF8='@LOCALE_FR_UTF8@' -check_PROGRAMS += test-vasnprintf-posix test-vasnprintf-posix2 +check_PROGRAMS += test-vasnprintf-posix test-vasnprintf-posix2 test-vasnprintf-posix3 --- tests/test-vasnprintf-posix.c.orig Sun Nov 7 18:50:15 2010 +++ tests/test-vasnprintf-posix.c Sun Nov 7 18:47:52 2010 @@ -3658,6 +3658,19 @@ free (result); } #endif + +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) + /* Test that the 'I' flag is supported. */ + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%Id %d", 1234567, 99); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1234567 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } +#endif } static char * ======================= tests/test-vasnprintf-posix3.c ======================= /* Test of POSIX compatible vasnprintf() and asnprintf() functions. Copyright (C) 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* Written by Bruno Haible <br...@clisp.org>, 2010. */ #include <config.h> #include "vasnprintf.h" #include <locale.h> #include <stdlib.h> #include <string.h> #include "macros.h" static void test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* glibc >= 2.2 supports the 'I' flag, and in glibc >= 2.2.3 the fa_IR locale defines the 'outdigits' to be U+06F0..U+06F9. So we test for glibc >= 2.3. */ #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) /* Test that the 'I' flag is supported. */ { size_t length; char *result = my_asnprintf (NULL, &length, "%Id %d", 1234567, 99); static const char expected[] = /* "۱۲۳۴۵۶۷ 99" */ "\xDB\xB1\xDB\xB2\xDB\xB3\xDB\xB4\xDB\xB5\xDB\xB6\xDB\xB7 99"; ASSERT (result != NULL); ASSERT (strcmp (result, expected) == 0); ASSERT (length == strlen (result)); free (result); } #endif } static char * my_asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) { va_list args; char *ret; va_start (args, format); ret = vasnprintf (resultbuf, lengthp, format, args); va_end (args); return ret; } static void test_vasnprintf () { test_function (my_asnprintf); } static void test_asnprintf () { test_function (asnprintf); } int main (int argc, char *argv[]) { #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) /* Select a locale with Arabic 'outdigits'. */ if (setlocale (LC_ALL, "fa_IR.UTF-8") == NULL) { fprintf (stderr, "Skipping test: no Iranian locale is installed\n"); return 77; } test_vasnprintf (); test_asnprintf (); return 0; #else fprintf (stderr, "Skipping test: not a glibc >= 2.3 system\n"); return 77; #endif }