diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-06-11 10:51:03 +0200 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-06-11 10:51:03 +0200 |
commit | 609e3c695319d84bc009520bba0dbebebed2f289 (patch) | |
tree | 05ab566b815e4340e18cdb27bbf49d72a5f07816 /lgl | |
parent | c86c105e35466f58203a41b2bd9cd94c9967602d (diff) | |
download | gnutls-609e3c695319d84bc009520bba0dbebebed2f289.tar.gz |
Update gnulib files.
Diffstat (limited to 'lgl')
-rw-r--r-- | lgl/Makefile.am | 1 | ||||
-rw-r--r-- | lgl/fseeko.c | 5 | ||||
-rw-r--r-- | lgl/m4/gettext.m4 | 40 | ||||
-rw-r--r-- | lgl/m4/gnulib-comp.m4 | 1 | ||||
-rw-r--r-- | lgl/m4/intlmacosx.m4 | 51 | ||||
-rw-r--r-- | lgl/m4/string_h.m4 | 1 | ||||
-rw-r--r-- | lgl/m4/vasnprintf.m4 | 18 | ||||
-rw-r--r-- | lgl/printf-args.c | 54 | ||||
-rw-r--r-- | lgl/printf-args.h | 24 | ||||
-rw-r--r-- | lgl/printf-parse.c | 65 | ||||
-rw-r--r-- | lgl/printf-parse.h | 113 | ||||
-rw-r--r-- | lgl/string_.h | 6 | ||||
-rw-r--r-- | lgl/vasnprintf.c | 1128 |
13 files changed, 1264 insertions, 243 deletions
diff --git a/lgl/Makefile.am b/lgl/Makefile.am index 73dbeebd8f..6c1620bda7 100644 --- a/lgl/Makefile.am +++ b/lgl/Makefile.am @@ -434,6 +434,7 @@ string.h: string_.h sed -e 's|@''ABSOLUTE_STRING_H''@|$(ABSOLUTE_STRING_H)|g' \ -e 's/@''HAVE_INCLUDE_NEXT''@/$(HAVE_INCLUDE_NEXT)/g' \ -e 's|@''GNULIB_MBSLEN''@|$(GNULIB_MBSLEN)|g' \ + -e 's|@''GNULIB_MBSNLEN''@|$(GNULIB_MBSNLEN)|g' \ -e 's|@''GNULIB_MBSCHR''@|$(GNULIB_MBSCHR)|g' \ -e 's|@''GNULIB_MBSRCHR''@|$(GNULIB_MBSRCHR)|g' \ -e 's|@''GNULIB_MBSSTR''@|$(GNULIB_MBSSTR)|g' \ diff --git a/lgl/fseeko.c b/lgl/fseeko.c index ee94376b8b..5397220816 100644 --- a/lgl/fseeko.c +++ b/lgl/fseeko.c @@ -83,6 +83,11 @@ rpl_fseeko (FILE *fp, off_t offset, int whence) if (fp->_ptr == fp->_base && (fp->_ptr == NULL || fp->_cnt == 0)) # endif +#elif defined __UCLIBC__ /* uClibc */ + if (((fp->__modeflags & __FLAG_WRITING) == 0 + || fp->__bufpos == fp->__bufstart) + && ((fp->__modeflags & (__FLAG_READONLY | __FLAG_READING)) == 0 + || fp->__bufpos == fp->__bufread)) #else #error "Please port gnulib fseeko.c to your platform! Look at the code in fpurge.c, then report this to bug-gnulib." #endif diff --git a/lgl/m4/gettext.m4 b/lgl/m4/gettext.m4 index 91c345e992..7f3e4e283c 100644 --- a/lgl/m4/gettext.m4 +++ b/lgl/m4/gettext.m4 @@ -1,4 +1,4 @@ -# gettext.m4 serial 59 (gettext-0.16.1) +# gettext.m4 serial 59a (gettext-0.16.1) dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -362,44 +362,6 @@ return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_a ]) -dnl Checks for special options needed on MacOS X. -dnl Defines INTL_MACOSX_LIBS. -AC_DEFUN([gt_INTL_MACOSX], -[ - dnl Check for API introduced in MacOS X 10.2. - AC_CACHE_CHECK([for CFPreferencesCopyAppValue], - gt_cv_func_CFPreferencesCopyAppValue, - [gt_save_LIBS="$LIBS" - LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" - AC_TRY_LINK([#include <CoreFoundation/CFPreferences.h>], - [CFPreferencesCopyAppValue(NULL, NULL)], - [gt_cv_func_CFPreferencesCopyAppValue=yes], - [gt_cv_func_CFPreferencesCopyAppValue=no]) - LIBS="$gt_save_LIBS"]) - if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then - AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, - [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) - fi - dnl Check for API introduced in MacOS X 10.3. - AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, - [gt_save_LIBS="$LIBS" - LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" - AC_TRY_LINK([#include <CoreFoundation/CFLocale.h>], [CFLocaleCopyCurrent();], - [gt_cv_func_CFLocaleCopyCurrent=yes], - [gt_cv_func_CFLocaleCopyCurrent=no]) - LIBS="$gt_save_LIBS"]) - if test $gt_cv_func_CFLocaleCopyCurrent = yes; then - AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, - [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) - fi - INTL_MACOSX_LIBS= - if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then - INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" - fi - AC_SUBST([INTL_MACOSX_LIBS]) -]) - - dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. m4_define([gt_NEEDS_INIT], [ diff --git a/lgl/m4/gnulib-comp.m4 b/lgl/m4/gnulib-comp.m4 index 11d94e9c76..59c3010c94 100644 --- a/lgl/m4/gnulib-comp.m4 +++ b/lgl/m4/gnulib-comp.m4 @@ -252,6 +252,7 @@ AC_DEFUN([lgl_FILE_LIST], [ m4/intdiv0.m4 m4/intl.m4 m4/intldir.m4 + m4/intlmacosx.m4 m4/intmax.m4 m4/intmax_t.m4 m4/inttypes-pri.m4 diff --git a/lgl/m4/intlmacosx.m4 b/lgl/m4/intlmacosx.m4 new file mode 100644 index 0000000000..6019bbfa24 --- /dev/null +++ b/lgl/m4/intlmacosx.m4 @@ -0,0 +1,51 @@ +# intlmacosx.m4 serial 1 (gettext-0.16.2) +dnl Copyright (C) 2004-2007 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + gt_cv_func_CFPreferencesCopyAppValue, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include <CoreFoundation/CFPreferences.h>], + [CFPreferencesCopyAppValue(NULL, NULL)], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include <CoreFoundation/CFLocale.h>], [CFLocaleCopyCurrent();], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/lgl/m4/string_h.m4 b/lgl/m4/string_h.m4 index f706d491be..ab5d786988 100644 --- a/lgl/m4/string_h.m4 +++ b/lgl/m4/string_h.m4 @@ -46,6 +46,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS], GNULIB_STRCASESTR=0; AC_SUBST([GNULIB_STRCASESTR]) GNULIB_STRTOK_R=0; AC_SUBST([GNULIB_STRTOK_R]) GNULIB_MBSLEN=0; AC_SUBST([GNULIB_MBSLEN]) + GNULIB_MBSNLEN=0; AC_SUBST([GNULIB_MBSNLEN]) GNULIB_MBSCHR=0; AC_SUBST([GNULIB_MBSCHR]) GNULIB_MBSRCHR=0; AC_SUBST([GNULIB_MBSRCHR]) GNULIB_MBSSTR=0; AC_SUBST([GNULIB_MBSSTR]) diff --git a/lgl/m4/vasnprintf.m4 b/lgl/m4/vasnprintf.m4 index 7d676c25f2..ef2de787f0 100644 --- a/lgl/m4/vasnprintf.m4 +++ b/lgl/m4/vasnprintf.m4 @@ -1,4 +1,4 @@ -# vasnprintf.m4 serial 18 +# vasnprintf.m4 serial 20 dnl Copyright (C) 2002-2004, 2006-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -57,6 +57,9 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF], AC_REQUIRE([gt_TYPE_WCHAR_T]) AC_REQUIRE([gt_TYPE_WINT_T]) AC_CHECK_FUNCS(snprintf wcslen) + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + AC_CHECK_DECLS([_snprintf], , , [#include <stdio.h>]) ]) # Extra prerequisites of lib/vasnprintf.c for supporting 'long double' @@ -175,6 +178,19 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO], esac ]) +# Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance. +AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS], +[ + AC_REQUIRE([gl_PREREQ_VASNPRINTF]) + gl_PREREQ_VASNPRINTF_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_DOUBLE + gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE + gl_PREREQ_VASNPRINTF_DIRECTIVE_A + gl_PREREQ_VASNPRINTF_DIRECTIVE_F + gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO +]) + # Prerequisites of lib/asnprintf.c. AC_DEFUN([gl_PREREQ_ASNPRINTF], [ diff --git a/lgl/printf-args.c b/lgl/printf-args.c index 9205d61720..9bf1ac6732 100644 --- a/lgl/printf-args.c +++ b/lgl/printf-args.c @@ -15,16 +15,25 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <config.h> +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + PRINTF_FETCHARGS Name of the function to be defined. + STATIC Set to 'static' to declare the function static. */ + +#ifndef PRINTF_FETCHARGS +# include <config.h> +#endif /* Specification. */ -#include "printf-args.h" +#ifndef PRINTF_FETCHARGS +# include "printf-args.h" +#endif #ifdef STATIC STATIC #endif int -printf_fetchargs (va_list args, arguments *a) +PRINTF_FETCHARGS (va_list args, arguments *a) { size_t i; argument *ap; @@ -131,6 +140,45 @@ printf_fetchargs (va_list args, arguments *a) ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); break; #endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + case TYPE_U8_STRING: + ap->a.a_u8_string = va_arg (args, const uint8_t *); + /* A null pointer is an invalid argument for "%U", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u8_string == NULL) + { + static const uint8_t u8_null_string[] = + { '(', 'N', 'U', 'L', 'L', 0 }; + ap->a.a_u8_string = u8_null_string; + } + break; + case TYPE_U16_STRING: + ap->a.a_u16_string = va_arg (args, const uint16_t *); + /* A null pointer is an invalid argument for "%lU", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u16_string == NULL) + { + static const uint16_t u16_null_string[] = + { '(', 'N', 'U', 'L', 'L', 0 }; + ap->a.a_u16_string = u16_null_string; + } + break; + case TYPE_U32_STRING: + ap->a.a_u32_string = va_arg (args, const uint32_t *); + /* A null pointer is an invalid argument for "%llU", but in practice + it occurs quite frequently in printf statements that produce + debug output. Use a fallback in this case. */ + if (ap->a.a_u32_string == NULL) + { + static const uint32_t u32_null_string[] = + { '(', 'N', 'U', 'L', 'L', 0 }; + ap->a.a_u32_string = u32_null_string; + } + break; +#endif default: /* Unknown type. */ return -1; diff --git a/lgl/printf-args.h b/lgl/printf-args.h index e270e04988..b663a63b17 100644 --- a/lgl/printf-args.h +++ b/lgl/printf-args.h @@ -18,6 +18,16 @@ #ifndef _PRINTF_ARGS_H #define _PRINTF_ARGS_H +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + PRINTF_FETCHARGS Name of the function to be declared. + STATIC Set to 'static' to declare the function static. */ + +/* Default parameters. */ +#ifndef PRINTF_FETCHARGS +# define PRINTF_FETCHARGS printf_fetchargs +#endif + /* Get size_t. */ #include <stddef.h> @@ -69,6 +79,12 @@ typedef enum #if HAVE_LONG_LONG_INT , TYPE_COUNT_LONGLONGINT_POINTER #endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ +, TYPE_U8_STRING +, TYPE_U16_STRING +, TYPE_U32_STRING +#endif } arg_type; /* Polymorphic argument */ @@ -108,6 +124,12 @@ typedef struct #if HAVE_LONG_LONG_INT long long int * a_count_longlongint_pointer; #endif +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + const uint8_t * a_u8_string; + const uint16_t * a_u16_string; + const uint32_t * a_u32_string; +#endif } a; } @@ -127,6 +149,6 @@ STATIC #else extern #endif -int printf_fetchargs (va_list args, arguments *a); +int PRINTF_FETCHARGS (va_list args, arguments *a); #endif /* _PRINTF_ARGS_H */ diff --git a/lgl/printf-parse.c b/lgl/printf-parse.c index b18bcdc930..1c3e6c0a11 100644 --- a/lgl/printf-parse.c +++ b/lgl/printf-parse.c @@ -15,15 +15,36 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <config.h> +/* This file can be parametrized with the following macros: + CHAR_T The element type of the format string. + CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters + in the format string are ASCII. + DIRECTIVE Structure denoting a format directive. + Depends on CHAR_T. + DIRECTIVES Structure denoting the set of format directives of a + format string. Depends on CHAR_T. + PRINTF_PARSE Function that parses a format string. + Depends on CHAR_T. + STATIC Set to 'static' to declare the function static. + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */ + +#ifndef PRINTF_PARSE +# include <config.h> +#endif /* Specification. */ -#if WIDE_CHAR_VERSION -# include "wprintf-parse.h" -#else +#ifndef PRINTF_PARSE # include "printf-parse.h" #endif +/* Default parameters. */ +#ifndef PRINTF_PARSE +# define PRINTF_PARSE printf_parse +# define CHAR_T char +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +#endif + /* Get size_t, NULL. */ #include <stddef.h> @@ -45,16 +66,9 @@ /* Checked size_t computations. */ #include "xsize.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 +#if CHAR_T_ONLY_ASCII +/* c_isascii(). */ +# include "c-ctype.h" #endif #ifdef STATIC @@ -119,7 +133,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) if (c == '%') { size_t arg_index = ARG_NONE; - 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; @@ -479,6 +493,17 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) else type = TYPE_COUNT_INT_POINTER; break; +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + case 'U': + if (flags >= 16) + type = TYPE_U32_STRING; + else if (flags >= 8) + type = TYPE_U16_STRING; + else + type = TYPE_U8_STRING; + break; +#endif case '%': type = TYPE_NONE; break; @@ -522,6 +547,13 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) d->dir = memory; } } +#if CHAR_T_ONLY_ASCII + else if (!c_isascii (c)) + { + /* Non-ASCII character. Not supported. */ + goto error; + } +#endif } d->dir[d->count].dir_start = cp; @@ -537,7 +569,8 @@ error: return -1; } +#undef PRINTF_PARSE #undef DIRECTIVES #undef DIRECTIVE +#undef CHAR_T_ONLY_ASCII #undef CHAR_T -#undef PRINTF_PARSE diff --git a/lgl/printf-parse.h b/lgl/printf-parse.h index 6d254e4d33..b0b458cc51 100644 --- a/lgl/printf-parse.h +++ b/lgl/printf-parse.h @@ -1,5 +1,5 @@ /* Parse printf format string. - Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc. + Copyright (C) 1999, 2002-2003, 2005, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -18,6 +18,10 @@ #ifndef _PRINTF_PARSE_H #define _PRINTF_PARSE_H +/* This file can be parametrized with the following macros: + ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. + STATIC Set to 'static' to declare the function static. */ + #include "printf-args.h" @@ -32,6 +36,9 @@ /* arg_index value indicating that no argument is consumed. */ #define ARG_NONE (~(size_t)0) +/* xxx_directive: A parsed directive. + xxx_directives: A parsed format string. */ + /* A parsed directive. */ typedef struct { @@ -59,16 +66,114 @@ typedef struct } char_directives; +#if ENABLE_UNISTDIO + +/* A parsed directive. */ +typedef struct +{ + const uint8_t* dir_start; + const uint8_t* dir_end; + int flags; + const uint8_t* width_start; + const uint8_t* width_end; + size_t width_arg_index; + const uint8_t* precision_start; + const uint8_t* precision_end; + size_t precision_arg_index; + uint8_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + size_t arg_index; +} +u8_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u8_directive *dir; + size_t max_width_length; + size_t max_precision_length; +} +u8_directives; + +/* A parsed directive. */ +typedef struct +{ + const uint16_t* dir_start; + const uint16_t* dir_end; + int flags; + const uint16_t* width_start; + const uint16_t* width_end; + size_t width_arg_index; + const uint16_t* precision_start; + const uint16_t* precision_end; + size_t precision_arg_index; + uint16_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + size_t arg_index; +} +u16_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u16_directive *dir; + size_t max_width_length; + size_t max_precision_length; +} +u16_directives; + +/* A parsed directive. */ +typedef struct +{ + const uint32_t* dir_start; + const uint32_t* dir_end; + int flags; + const uint32_t* width_start; + const uint32_t* width_end; + size_t width_arg_index; + const uint32_t* precision_start; + const uint32_t* precision_end; + size_t precision_arg_index; + uint32_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */ + size_t arg_index; +} +u32_directive; + +/* A parsed format string. */ +typedef struct +{ + size_t count; + u32_directive *dir; + size_t max_width_length; + size_t max_precision_length; +} +u32_directives; + +#endif + /* 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 +#if ENABLE_UNISTDIO +extern int + ulc_printf_parse (const char *format, char_directives *d, arguments *a); +extern int + u8_printf_parse (const uint8_t *format, u8_directives *d, arguments *a); +extern int + u16_printf_parse (const uint16_t *format, u16_directives *d, + arguments *a); +extern int + u32_printf_parse (const uint32_t *format, u32_directives *d, + arguments *a); #else +# ifdef STATIC +STATIC +# else extern -#endif +# endif int printf_parse (const char *format, char_directives *d, arguments *a); +#endif #endif /* _PRINTF_PARSE_H */ diff --git a/lgl/string_.h b/lgl/string_.h index 75f2925334..7533f4fae1 100644 --- a/lgl/string_.h +++ b/lgl/string_.h @@ -401,6 +401,12 @@ extern char *strtok_r (char *restrict s, char const *restrict delim, extern size_t mbslen (const char *string); #endif +#if @GNULIB_MBSNLEN@ +/* Return the number of multibyte characters in the character string starting + at STRING and ending at STRING + LEN. */ +extern size_t mbsnlen (const char *string, size_t len); +#endif + #if @GNULIB_MBSCHR@ /* Locate the first single-byte character C in the character string STRING, and return a pointer to it. Return NULL if C is not found in STRING. diff --git a/lgl/vasnprintf.c b/lgl/vasnprintf.c index 54ae10446b..d8ec00ece1 100644 --- a/lgl/vasnprintf.c +++ b/lgl/vasnprintf.c @@ -15,6 +15,35 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* This file can be parametrized with the following macros: + VASNPRINTF The name of the function being defined. + FCHAR_T The element type of the format string. + DCHAR_T The element type of the destination (result) string. + FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters + in the format string are ASCII. MUST be set if + FCHAR_T and DCHAR_T are not the same type. + DIRECTIVE Structure denoting a format directive. + Depends on FCHAR_T. + DIRECTIVES Structure denoting the set of format directives of a + format string. Depends on FCHAR_T. + PRINTF_PARSE Function that parses a format string. + Depends on FCHAR_T. + DCHAR_CPY memcpy like function for DCHAR_T[] arrays. + DCHAR_SET memset like function for DCHAR_T[] arrays. + DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays. + SNPRINTF The system's snprintf (or similar) function. + This may be either snprintf or swprintf. + TCHAR_T The element type of the argument and result string + of the said SNPRINTF function. This may be either + char or wchar_t. The code exploits that + sizeof (TCHAR_T) | sizeof (DCHAR_T) and + alignof (TCHAR_T) <= alignof (DCHAR_T). + DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type. + DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[]. + DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t. + DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t. + DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */ + /* 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. */ @@ -22,16 +51,20 @@ # define _GNU_SOURCE 1 #endif -#include <config.h> +#ifndef VASNPRINTF +# include <config.h> +#endif #ifndef IN_LIBINTL # include <alloca.h> #endif /* Specification. */ -#if WIDE_CHAR_VERSION -# include "vasnwprintf.h" -#else -# include "vasnprintf.h" +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +# else +# include "vasnprintf.h" +# endif #endif #include <locale.h> /* localeconv() */ @@ -44,10 +77,12 @@ #if HAVE_NL_LANGINFO # include <langinfo.h> #endif -#if WIDE_CHAR_VERSION -# include "wprintf-parse.h" -#else -# include "printf-parse.h" +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# include "wprintf-parse.h" +# else +# include "printf-parse.h" +# endif #endif /* Checked size_t computations. */ @@ -107,12 +142,32 @@ local_wcslen (const wchar_t *s) # endif #endif +/* Default parameters. */ +#ifndef VASNPRINTF +# if WIDE_CHAR_VERSION +# define VASNPRINTF vasnwprintf +# define FCHAR_T wchar_t +# define DCHAR_T wchar_t +# define TCHAR_T wchar_t +# define DCHAR_IS_TCHAR 1 +# define DIRECTIVE wchar_t_directive +# define DIRECTIVES wchar_t_directives +# define PRINTF_PARSE wprintf_parse +# define DCHAR_CPY wmemcpy +# else +# define VASNPRINTF vasnprintf +# define FCHAR_T char +# define DCHAR_T char +# define TCHAR_T char +# define DCHAR_IS_TCHAR 1 +# define DIRECTIVE char_directive +# define DIRECTIVES char_directives +# define PRINTF_PARSE printf_parse +# define DCHAR_CPY memcpy +# endif +#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 + /* TCHAR_T is wchar_t. */ # define USE_SNPRINTF 1 # if HAVE_DECL__SNWPRINTF /* On Windows, the function swprintf() has a different signature than @@ -123,11 +178,7 @@ local_wcslen (const wchar_t *s) # define SNPRINTF swprintf # endif #else -# define VASNPRINTF vasnprintf -# define CHAR_T char -# define DIRECTIVE char_directive -# define DIRECTIVES char_directives -# define PRINTF_PARSE printf_parse + /* TCHAR_T is char. */ # /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. But don't use it on BeOS, since BeOS snprintf produces no output if the size argument is >= 0x3000000. */ @@ -1137,8 +1188,9 @@ floorlog10l (long double x) #endif -CHAR_T * -VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args) +DCHAR_T * +VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, + const FCHAR_T *format, va_list args) { DIRECTIVES d; arguments a; @@ -1154,7 +1206,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (a.arg) \ free (a.arg); - if (printf_fetchargs (args, &a) < 0) + if (PRINTF_FETCHARGS (args, &a) < 0) { CLEANUP (); errno = EINVAL; @@ -1163,13 +1215,13 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { size_t buf_neededlength; - CHAR_T *buf; - CHAR_T *buf_malloced; - const CHAR_T *cp; + TCHAR_T *buf; + TCHAR_T *buf_malloced; + const FCHAR_T *cp; size_t i; DIRECTIVE *dp; /* Output string accumulator. */ - CHAR_T *result; + DCHAR_T *result; size_t allocated; size_t length; @@ -1178,18 +1230,18 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar buf_neededlength = xsum4 (7, d.max_width_length, d.max_precision_length, 6); #if HAVE_ALLOCA - if (buf_neededlength < 4000 / sizeof (CHAR_T)) + if (buf_neededlength < 4000 / sizeof (TCHAR_T)) { - buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T)); + buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T)); buf_malloced = NULL; } else #endif { - size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T)); + size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T)); if (size_overflow_p (buf_memsize)) goto out_of_memory_1; - buf = (CHAR_T *) malloc (buf_memsize); + buf = (TCHAR_T *) malloc (buf_memsize); if (buf == NULL) goto out_of_memory_1; buf_malloced = buf; @@ -1216,22 +1268,22 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if ((needed) > allocated) \ { \ size_t memory_size; \ - CHAR_T *memory; \ + DCHAR_T *memory; \ \ allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ if ((needed) > allocated) \ allocated = (needed); \ - memory_size = xtimes (allocated, sizeof (CHAR_T)); \ + memory_size = xtimes (allocated, sizeof (DCHAR_T)); \ if (size_overflow_p (memory_size)) \ goto out_of_memory; \ if (result == resultbuf || result == NULL) \ - memory = (CHAR_T *) malloc (memory_size); \ + memory = (DCHAR_T *) malloc (memory_size); \ else \ - memory = (CHAR_T *) realloc (result, memory_size); \ + memory = (DCHAR_T *) realloc (result, memory_size); \ if (memory == NULL) \ goto out_of_memory; \ if (result == resultbuf && length > 0) \ - memcpy (memory, result, length * sizeof (CHAR_T)); \ + DCHAR_CPY (memory, result, length); \ result = memory; \ } @@ -1243,8 +1295,20 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar size_t augmented_length = xsum (length, n); ENSURE_ALLOCATION (augmented_length); - memcpy (result + length, cp, n * sizeof (CHAR_T)); - length = augmented_length; + /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we + need that the format string contains only ASCII characters + if FCHAR_T and DCHAR_T are not the same type. */ + if (sizeof (FCHAR_T) == sizeof (DCHAR_T)) + { + DCHAR_CPY (result + length, (const DCHAR_T *) cp, n); + length = augmented_length; + } + else + { + do + result[length++] = (unsigned char) *cp++; + while (--n > 0); + } } if (i == d.count) break; @@ -1291,6 +1355,470 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar abort (); } } +#if ENABLE_UNISTDIO + /* The unistdio extensions. */ + else if (dp->conversion == 'U') + { + arg_type type = a.arg[dp->arg_index].type; + int flags = dp->flags; + int has_width; + size_t width; + int has_precision; + size_t precision; + + has_width = 0; + width = 0; + if (dp->width_start != dp->width_end) + { + if (dp->width_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->width_arg_index].a.a_int; + if (arg < 0) + { + /* "A negative field width is taken as a '-' flag + followed by a positive field width." */ + flags |= FLAG_LEFT; + width = (unsigned int) (-arg); + } + else + width = arg; + } + else + { + const FCHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } + + has_precision = 0; + precision = 0; + if (dp->precision_start != dp->precision_end) + { + if (dp->precision_arg_index != ARG_NONE) + { + int arg; + + if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) + abort (); + arg = a.arg[dp->precision_arg_index].a.a_int; + /* "A negative precision is taken as if the precision + were omitted." */ + if (arg >= 0) + { + precision = arg; + has_precision = 1; + } + } + else + { + const FCHAR_T *digitp = dp->precision_start + 1; + + precision = 0; + while (digitp != dp->precision_end) + precision = xsum (xtimes (precision, 10), *digitp++ - '0'); + has_precision = 1; + } + } + + switch (type) + { + case TYPE_U8_STRING: + { + const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string; + const uint8_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u8_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u8_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u8_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (has_width && width > characters + && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT8_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-8 to locale encoding. */ + if (u8_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + &converted, &converted_len) + < 0) +# else + /* Convert from UTF-8 to UTF-16/UTF-32. */ + converted = + U8_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); + if (converted == NULL) +# endif + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (has_width && width > characters + && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + case TYPE_U16_STRING: + { + const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string; + const uint16_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u16_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u16_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u16_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (has_width && width > characters + && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT16_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-16 to locale encoding. */ + if (u16_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + &converted, &converted_len) + < 0) +# else + /* Convert from UTF-16 to UTF-8/UTF-32. */ + converted = + U16_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); + if (converted == NULL) +# endif + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (has_width && width > characters + && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + case TYPE_U32_STRING: + { + const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string; + const uint32_t *arg_end; + size_t characters; + + if (has_precision) + { + /* Use only PRECISION characters, from the left. */ + arg_end = arg; + characters = 0; + for (; precision > 0; precision--) + { + int count = u32_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else if (has_width) + { + /* Use the entire string, and count the number of + characters. */ + arg_end = arg; + characters = 0; + for (;;) + { + int count = u32_strmblen (arg_end); + if (count == 0) + break; + if (count < 0) + { + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EILSEQ; + return NULL; + } + arg_end += count; + characters++; + } + } + else + { + /* Use the entire string. */ + arg_end = arg + u32_strlen (arg); + /* The number of characters doesn't matter. */ + characters = 0; + } + + if (has_width && width > characters + && !(dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + +# if DCHAR_IS_UINT32_T + { + size_t n = arg_end - arg; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_CPY (result + length, arg, n); + length += n; + } +# else + { /* Convert. */ + DCHAR_T *converted = result + length; + size_t converted_len = allocated - length; +# if DCHAR_IS_TCHAR + /* Convert from UTF-32 to locale encoding. */ + if (u32_conv_to_encoding (locale_charset (), + iconveh_question_mark, + arg, arg_end - arg, NULL, + &converted, &converted_len) + < 0) +# else + /* Convert from UTF-32 to UTF-8/UTF-16. */ + converted = + U32_TO_DCHAR (arg, arg_end - arg, + converted, &converted_len); + if (converted == NULL) +# endif + { + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; + } + if (converted != result + length) + { + ENSURE_ALLOCATION (xsum (length, converted_len)); + DCHAR_CPY (result + length, converted, converted_len); + free (converted); + } + length += converted_len; + } +# endif + + if (has_width && width > characters + && (dp->flags & FLAG_LEFT)) + { + size_t n = width - characters; + ENSURE_ALLOCATION (xsum (length, n)); + DCHAR_SET (result + length, ' ', n); + length += n; + } + } + break; + + default: + abort (); + } + } +#endif #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL else if (dp->conversion == 'a' || dp->conversion == 'A') { @@ -1301,10 +1829,10 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar int has_precision; size_t precision; size_t tmp_length; - CHAR_T tmpbuf[700]; - CHAR_T *tmp; - CHAR_T *pad_ptr; - CHAR_T *p; + DCHAR_T tmpbuf[700]; + DCHAR_T *tmp; + DCHAR_T *pad_ptr; + DCHAR_T *p; has_width = 0; width = 0; @@ -1329,7 +1857,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } else { - const CHAR_T *digitp = dp->width_start; + const FCHAR_T *digitp = dp->width_start; do width = xsum (xtimes (width, 10), *digitp++ - '0'); @@ -1359,7 +1887,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } else { - const CHAR_T *digitp = dp->precision_start + 1; + const FCHAR_T *digitp = dp->precision_start + 1; precision = 0; while (digitp != dp->precision_end) @@ -1391,16 +1919,16 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) tmp = tmpbuf; else { - size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); if (size_overflow_p (tmp_memsize)) /* Overflow, would lead to out of memory. */ goto out_of_memory; - tmp = (CHAR_T *) malloc (tmp_memsize); + tmp = (DCHAR_T *) malloc (tmp_memsize); if (tmp == NULL) /* Out of memory. */ goto out_of_memory; @@ -1535,11 +2063,24 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { '%', '+', 'd', '\0' }; SNPRINTF (p, 6 + 1, decimal_format, exponent); } -# else - sprintf (p, "%+d", exponent); -# endif while (*p != '\0') p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif } END_LONG_DOUBLE_ROUNDING (); @@ -1669,11 +2210,24 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { '%', '+', 'd', '\0' }; SNPRINTF (p, 6 + 1, decimal_format, exponent); } -# else - sprintf (p, "%+d", exponent); -# endif while (*p != '\0') p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif } } } @@ -1682,7 +2236,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (has_width && p - tmp < width) { size_t pad = width - (p - tmp); - CHAR_T *end = p + pad; + DCHAR_T *end = p + pad; if (flags & FLAG_LEFT) { @@ -1693,7 +2247,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar else if ((flags & FLAG_ZERO) && pad_ptr != NULL) { /* Pad with zeroes. */ - CHAR_T *q = end; + DCHAR_T *q = end; while (p > pad_ptr) *--q = *--p; @@ -1703,7 +2257,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar else { /* Pad with spaces on the left. */ - CHAR_T *q = end; + DCHAR_T *q = end; while (p > tmp) *--q = *--p; @@ -1731,7 +2285,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } /* Append the result. */ - memcpy (result + length, tmp, count * sizeof (CHAR_T)); + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); if (tmp != tmpbuf) free (tmp); length += count; @@ -1770,10 +2324,10 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar int has_precision; size_t precision; size_t tmp_length; - CHAR_T tmpbuf[700]; - CHAR_T *tmp; - CHAR_T *pad_ptr; - CHAR_T *p; + DCHAR_T tmpbuf[700]; + DCHAR_T *tmp; + DCHAR_T *pad_ptr; + DCHAR_T *p; has_width = 0; width = 0; @@ -1798,7 +2352,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } else { - const CHAR_T *digitp = dp->width_start; + const FCHAR_T *digitp = dp->width_start; do width = xsum (xtimes (width, 10), *digitp++ - '0'); @@ -1828,7 +2382,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } else { - const CHAR_T *digitp = dp->precision_start + 1; + const FCHAR_T *digitp = dp->precision_start + 1; precision = 0; while (digitp != dp->precision_end) @@ -1877,16 +2431,16 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) tmp = tmpbuf; else { - size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); if (size_overflow_p (tmp_memsize)) /* Overflow, would lead to out of memory. */ goto out_of_memory; - tmp = (CHAR_T *) malloc (tmp_memsize); + tmp = (DCHAR_T *) malloc (tmp_memsize); if (tmp == NULL) /* Out of memory. */ goto out_of_memory; @@ -2065,11 +2619,24 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { '%', '+', '.', '2', 'd', '\0' }; SNPRINTF (p, 6 + 1, decimal_format, exponent); } -# else - sprintf (p, "%+.2d", exponent); -# endif while (*p != '\0') p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+.2d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+.2d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif } else if (dp->conversion == 'g' || dp->conversion == 'G') { @@ -2209,11 +2776,24 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { '%', '+', '.', '2', 'd', '\0' }; SNPRINTF (p, 6 + 1, decimal_format, exponent); } -# else - sprintf (p, "%+.2d", exponent); -# endif while (*p != '\0') p++; +# else + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, "%+.2d", exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, "%+.2d", exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } +# endif } free (digits); @@ -2338,7 +2918,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (has_width && p - tmp < width) { size_t pad = width - (p - tmp); - CHAR_T *end = p + pad; + DCHAR_T *end = p + pad; if (flags & FLAG_LEFT) { @@ -2349,7 +2929,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar else if ((flags & FLAG_ZERO) && pad_ptr != NULL) { /* Pad with zeroes. */ - CHAR_T *q = end; + DCHAR_T *q = end; while (p > pad_ptr) *--q = *--p; @@ -2359,7 +2939,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar else { /* Pad with spaces on the left. */ - CHAR_T *q = end; + DCHAR_T *q = end; while (p > tmp) *--q = *--p; @@ -2387,7 +2967,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } /* Append the result. */ - memcpy (result + length, tmp, count * sizeof (CHAR_T)); + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); if (tmp != tmpbuf) free (tmp); length += count; @@ -2398,25 +2978,25 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; -#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO int has_width; size_t width; #endif -#if NEED_PRINTF_FLAG_ZERO +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO int pad_ourselves; #else # define pad_ourselves 0 #endif - CHAR_T *fbp; + TCHAR_T *fbp; unsigned int prefix_count; int prefixes[2]; #if !USE_SNPRINTF size_t tmp_length; - CHAR_T tmpbuf[700]; - CHAR_T *tmp; + TCHAR_T tmpbuf[700]; + TCHAR_T *tmp; #endif -#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO has_width = 0; width = 0; if (dp->width_start != dp->width_end) @@ -2440,7 +3020,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } else { - const CHAR_T *digitp = dp->width_start; + const FCHAR_T *digitp = dp->width_start; do width = xsum (xtimes (width, 10), *digitp++ - '0'); @@ -2470,7 +3050,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } else { - const CHAR_T *digitp = dp->precision_start + 1; + const FCHAR_T *digitp = dp->precision_start + 1; precision = 0; while (digitp != dp->precision_end) @@ -2650,22 +3230,32 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar abort (); } +# if ENABLE_UNISTDIO + /* Padding considers the number of characters, therefore the + number of elements after padding may be + > max (tmp_length, width) + but is certainly + <= tmp_length + width. */ + tmp_length = xsum (tmp_length, width); +# else + /* Padding considers the number of elements, says POSIX. */ if (tmp_length < width) tmp_length = width; +# endif tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ } - if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T)) + if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) tmp = tmpbuf; else { - size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T)); + size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T)); if (size_overflow_p (tmp_memsize)) /* Overflow, would lead to out of memory. */ goto out_of_memory; - tmp = (CHAR_T *) malloc (tmp_memsize); + tmp = (TCHAR_T *) malloc (tmp_memsize); if (tmp == NULL) /* Out of memory. */ goto out_of_memory; @@ -2673,11 +3263,20 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar #endif /* Decide whether to perform the padding ourselves. */ -#if NEED_PRINTF_FLAG_ZERO +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO switch (dp->conversion) { +# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO + /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need + to perform the padding after this conversion. Functions + with unistdio extensions perform the padding based on + character count rather than element count. */ + case 'c': case 's': +# endif +# if NEED_PRINTF_FLAG_ZERO case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': case 'a': case 'A': +# endif pad_ourselves = 1; break; default: @@ -2713,15 +3312,39 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (dp->width_start != dp->width_end) { size_t n = dp->width_end - dp->width_start; - memcpy (fbp, dp->width_start, n * sizeof (CHAR_T)); - fbp += n; + /* The width specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->width_start; + do + *fbp++ = (unsigned char) *mp++; + while (--n > 0); + } } } if (dp->precision_start != dp->precision_end) { size_t n = dp->precision_end - dp->precision_start; - memcpy (fbp, dp->precision_start, n * sizeof (CHAR_T)); - fbp += n; + /* The precision specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->precision_start; + do + *fbp++ = (unsigned char) *mp++; + while (--n > 0); + } } switch (type) @@ -2785,39 +3408,46 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } #if USE_SNPRINTF + /* The SNPRINTF result is appended after result[0..length]. + The latter is an array of DCHAR_T; SNPRINTF appends an + array of TCHAR_T to it. This is possible because + sizeof (TCHAR_T) divides sizeof (DCHAR_T) and + alignof (TCHAR_T) <= alignof (DCHAR_T). */ +# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T)) /* Prepare checking whether snprintf returns the count via %n. */ ENSURE_ALLOCATION (xsum (length, 1)); - result[length] = '\0'; + *(TCHAR_T *) (result + length) = '\0'; #endif for (;;) { - size_t maxlen; - int count; - int retcount; - - maxlen = allocated - length; - count = -1; - retcount = 0; + int count = -1; #if USE_SNPRINTF - /* SNPRINTF can fail if maxlen > INT_MAX. */ - if (maxlen > INT_MAX) + int retcount = 0; + size_t maxlen = allocated - length; + /* SNPRINTF can fail if its second argument is + > INT_MAX. */ + if (maxlen > INT_MAX / TCHARS_PER_DCHAR) goto overflow; + maxlen = maxlen * TCHARS_PER_DCHAR; # define SNPRINTF_BUF(arg) \ switch (prefix_count) \ { \ case 0: \ - retcount = SNPRINTF (result + length, maxlen, buf, \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ arg, &count); \ break; \ case 1: \ - retcount = SNPRINTF (result + length, maxlen, buf, \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ prefixes[0], arg, &count); \ break; \ case 2: \ - retcount = SNPRINTF (result + length, maxlen, buf, \ + retcount = SNPRINTF ((TCHAR_T *) (result + length), \ + maxlen, buf, \ prefixes[0], prefixes[1], arg, \ &count); \ break; \ @@ -2966,7 +3596,8 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { /* Verify that snprintf() has NUL-terminated its result. */ - if (count < maxlen && result[length + count] != '\0') + if (count < maxlen + && ((TCHAR_T *) (result + length)) [count] != '\0') abort (); /* Portability hack. */ if (retcount > count) @@ -3016,109 +3647,245 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar return NULL; } - /* Make room for the result. */ +#if USE_SNPRINTF + /* Handle overflow of the allocated buffer. */ if (count >= maxlen) { - /* Need at least count bytes. But allocate - proportionally, to avoid looping eternally if - snprintf() reports a too small count. */ + /* Need at least count * sizeof (TCHAR_T) bytes. But + allocate proportionally, to avoid looping eternally + if snprintf() reports a too small count. */ size_t n = - xmax (xsum (length, count), xtimes (allocated, 2)); + xmax (xsum (length, + (count + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR), + xtimes (allocated, 2)); ENSURE_ALLOCATION (n); -#if USE_SNPRINTF continue; -#else - maxlen = allocated - length; -#endif } +#endif - /* Perform padding. */ -#if NEED_PRINTF_FLAG_ZERO - if (pad_ourselves && has_width && count < width) +#if !DCHAR_IS_TCHAR +# if !USE_SNPRINTF + if (count >= tmp_length) + /* tmp_length was incorrectly calculated - fix the + code above! */ + abort (); +# endif + + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + if (dp->conversion == 'c' || dp->conversion == 's') { + /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING + TYPE_WIDE_STRING. + The result string is not certainly ASCII. */ + const TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t tmpdst_len; + /* This code assumes that TCHAR_T is 'char'. */ + typedef int TCHAR_T_verify + [2 * (sizeof (TCHAR_T) == 1) - 1]; # if USE_SNPRINTF - /* Make room for the result. */ - if (width >= maxlen) + tmpsrc = (TCHAR_T *) (result + length); +# else + tmpsrc = tmp; +# endif + tmpdst = NULL; + tmpdst_len = 0; + if (DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, count, + NULL, + &tmpdst, &tmpdst_len) + < 0) { - /* Need at least width bytes. But allocate - proportionally, to avoid looping eternally if - snprintf() reports a too small count. */ - size_t n = - xmax (xsum (length + 1, width), - xtimes (allocated, 2)); - - length += count; - ENSURE_ALLOCATION (n); - length -= count; - maxlen = allocated - length; /* > width */ + int saved_errno = errno; + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = saved_errno; + return NULL; } - /* Here width < maxlen. */ + ENSURE_ALLOCATION (xsum (length, tmpdst_len)); + DCHAR_CPY (result + length, tmpdst, tmpdst_len); + free (tmpdst); + count = tmpdst_len; + } + else + { + /* The result string is ASCII. + Simple 1:1 conversion. */ +# if USE_SNPRINTF + /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a + no-op conversion, in-place on the array starting + at (result + length). */ + if (sizeof (DCHAR_T) != sizeof (TCHAR_T)) # endif - { + { + const TCHAR_T *tmpsrc; + DCHAR_T *tmpdst; + size_t n; + # if USE_SNPRINTF - CHAR_T * const rp = result + length; + if (result == resultbuf) + { + tmpsrc = (TCHAR_T *) (result + length); + /* ENSURE_ALLOCATION will not move tmpsrc + (because it's part of resultbuf). */ + ENSURE_ALLOCATION (xsum (length, count)); + } + else + { + /* ENSURE_ALLOCATION will move the array + (because it uses realloc(). */ + ENSURE_ALLOCATION (xsum (length, count)); + tmpsrc = (TCHAR_T *) (result + length); + } # else - CHAR_T * const rp = tmp; + tmpsrc = tmp; + ENSURE_ALLOCATION (xsum (length, count)); # endif - CHAR_T *p = rp + count; - size_t pad = width - count; - CHAR_T *end = p + pad; - CHAR_T *pad_ptr = (*rp == '-' ? rp + 1 : rp); - /* No zero-padding of "inf" and "nan". */ - if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') - || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) - pad_ptr = NULL; - /* The generated string now extends from rp to p, - with the zero padding insertion point being at - pad_ptr. */ - - if (flags & FLAG_LEFT) - { - /* Pad with spaces on the right. */ - for (; pad > 0; pad--) - *p++ = ' '; - } - else if ((flags & FLAG_ZERO) && pad_ptr != NULL) - { - /* Pad with zeroes. */ - CHAR_T *q = end; + tmpdst = result + length; + /* Copy backwards, because of overlapping. */ + tmpsrc += count; + tmpdst += count; + for (n = count; n > 0; n--) + *--tmpdst = (unsigned char) *--tmpsrc; + } + } +#endif - while (p > pad_ptr) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = '0'; - } - else +#if DCHAR_IS_TCHAR && !USE_SNPRINTF + /* Make room for the result. */ + if (count > allocated - length) + { + /* Need at least count elements. But allocate + proportionally. */ + size_t n = + xmax (xsum (length, count), xtimes (allocated, 2)); + + ENSURE_ALLOCATION (n); + } +#endif + + /* Here count <= allocated - length. */ + + /* Perform padding. */ +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO + if (pad_ourselves && has_width) + { + size_t w; +# if ENABLE_UNISTDIO + /* Outside POSIX, it's preferrable to compare the width + against the number of _characters_ of the converted + value. */ + w = DCHAR_MBSNLEN (result + length, count); +# else + /* The width is compared against the number of _bytes_ + of the converted value, says POSIX. */ + w = count; +# endif + if (w < width) + { + size_t pad = width - w; +# if USE_SNPRINTF + /* Make room for the result. */ + if (xsum (count, pad) > allocated - length) + { + /* Need at least count + pad elements. But + allocate proportionally. */ + size_t n = + xmax (xsum3 (length, count, pad), + xtimes (allocated, 2)); + + length += count; + ENSURE_ALLOCATION (n); + length -= count; + } + /* Here count + pad <= allocated - length. */ +# endif { - /* Pad with spaces on the left. */ - CHAR_T *q = end; +# if !DCHAR_IS_TCHAR || USE_SNPRINTF + DCHAR_T * const rp = result + length; +# else + DCHAR_T * const rp = tmp; +# endif + DCHAR_T *p = rp + count; + DCHAR_T *end = p + pad; +# if NEED_PRINTF_FLAG_ZERO + DCHAR_T *pad_ptr; +# if !DCHAR_IS_TCHAR + if (dp->conversion == 'c' + || dp->conversion == 's') + /* No zero-padding for string directives. */ + pad_ptr = NULL; + else +# endif + { + pad_ptr = (*rp == '-' ? rp + 1 : rp); + /* No zero-padding of "inf" and "nan". */ + if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') + || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) + pad_ptr = NULL; + } +# endif + /* The generated string now extends from rp to p, + with the zero padding insertion point being at + pad_ptr. */ - while (p > rp) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = ' '; - } + count = count + pad; /* = end - rp */ - count = width; /* = count + pad = end - rp */ - } + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } +# if NEED_PRINTF_FLAG_ZERO + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + DCHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } +# endif + else + { + /* Pad with spaces on the left. */ + DCHAR_T *q = end; + + while (p > rp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + } + } } #endif -#if !USE_SNPRINTF +#if DCHAR_IS_TCHAR && !USE_SNPRINTF if (count >= tmp_length) /* tmp_length was incorrectly calculated - fix the code above! */ abort (); #endif - /* Here still count < maxlen. */ + /* Here still count <= allocated - length. */ -#if USE_SNPRINTF +#if !DCHAR_IS_TCHAR || USE_SNPRINTF /* The snprintf() result did fit. */ #else /* Append the sprintf() result. */ - memcpy (result + length, tmp, count * sizeof (CHAR_T)); + memcpy (result + length, tmp, count * sizeof (DCHAR_T)); +#endif +#if !USE_SNPRINTF if (tmp != tmpbuf) free (tmp); #endif @@ -3127,7 +3894,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (dp->conversion == 'F') { /* Convert the %f result to upper case for %F. */ - CHAR_T *rp = result + length; + DCHAR_T *rp = result + length; size_t rc; for (rc = count; rc > 0; rc--, rp++) if (*rp >= 'a' && *rp <= 'z') @@ -3149,9 +3916,9 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar if (result != resultbuf && length + 1 < allocated) { /* Shrink the allocated memory if possible. */ - CHAR_T *memory; + DCHAR_T *memory; - memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T)); + memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T)); if (memory != NULL) result = memory; } @@ -3187,10 +3954,13 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } } +#undef TCHARS_PER_DCHAR #undef SNPRINTF #undef USE_SNPRINTF #undef PRINTF_PARSE #undef DIRECTIVES #undef DIRECTIVE -#undef CHAR_T +#undef TCHAR_T +#undef DCHAR_T +#undef FCHAR_T #undef VASNPRINTF |