From dda38ff89ea6c5c28da197cebfbe2d5b510eafb5 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 17 Nov 2003 14:56:31 +0000 Subject: [PATCH] Merge support for wide characters, from GNU gettext. --- lib/printf-parse.c | 43 ++++++++--- lib/vasnprintf.c | 184 ++++++++++++++++++++++++++++++--------------- 2 files changed, 154 insertions(+), 73 deletions(-) diff --git a/lib/printf-parse.c b/lib/printf-parse.c index 51b08bbb0a..ad42e42c5c 100644 --- a/lib/printf-parse.c +++ b/lib/printf-parse.c @@ -20,7 +20,11 @@ #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 @@ -36,13 +40,25 @@ /* malloc(), realloc(), free(). */ #include +#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 */ @@ -51,7 +67,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; @@ -88,11 +104,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; @@ -108,7 +124,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++) ; @@ -175,7 +191,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++) ; @@ -224,7 +240,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++) ; @@ -450,10 +466,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; @@ -474,3 +490,8 @@ error: free (d->dir); return -1; } + +#undef DIRECTIVES +#undef DIRECTIVE +#undef CHAR_T +#undef PRINTF_PARSE diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 246c75bdfa..15ba9a1308 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -25,10 +25,16 @@ #ifdef HAVE_CONFIG_H # include #endif -#include +#ifndef IN_LIBINTL +# include +#endif /* Specification. */ -#include "vasnprintf.h" +#if WIDE_CHAR_VERSION +# include "vasnwprintf.h" +#else +# include "vasnprintf.h" +#endif #include /* snprintf(), sprintf() */ #include /* abort(), malloc(), realloc(), free() */ @@ -36,7 +42,11 @@ #include /* errno */ #include /* CHAR_BIT */ #include /* 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. */ @@ -52,7 +62,11 @@ # define local_wcslen wcslen # else /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid - a dependency towards this library, here is a local substitute. */ + a dependency towards this library, here is a local substitute. + Define this substitute only once, even if this file is included + twice in the same compilation unit. */ +# ifndef local_wcslen_defined +# define local_wcslen_defined 1 static size_t local_wcslen (const wchar_t *s) { @@ -62,16 +76,48 @@ local_wcslen (const wchar_t *s) ; return ptr - s; } +# endif +# 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 +# define USE_SNPRINTF 1 +# if HAVE_DECL__SNWPRINTF + /* On Windows, the function swprintf() has a different signature than + on Unix; we use the _snwprintf() function instead. */ +# define SNPRINTF _snwprintf +# else + /* Unix. */ +# 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 +# define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) +# if HAVE_DECL__SNPRINTF + /* Windows. */ +# define SNPRINTF _snprintf +# else + /* Unix. */ +# define SNPRINTF snprintf # endif #endif -char * -vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) +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; @@ -90,13 +136,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; @@ -116,30 +163,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++) @@ -149,7 +196,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) @@ -197,13 +244,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. */ @@ -225,7 +272,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'); @@ -247,7 +294,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 @@ -374,7 +421,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 @@ -385,9 +432,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 = + local_wcslen (a.arg[dp->arg_index].a.a_wide_string); +# else tmp_length = local_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); @@ -412,11 +464,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. */ @@ -449,13 +501,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; } @@ -486,7 +538,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'; @@ -509,7 +561,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); @@ -526,20 +578,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; \ @@ -681,7 +733,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 @@ -738,7 +790,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! */ @@ -757,16 +809,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 @@ -785,9 +837,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; } @@ -798,3 +850,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 -- 2.30.2