This is for gzip, which does not use setlocale, but does need to quote file names. * lib/quotearg.c (USE_C_LOCALE): Default to 0. If set, include c-ctype.h instead of ctype.h, gettext.h, uchar.h, wchar.h; and define _ to be an identity macro. (wch, mbstate): New types. (mbs_clear, mbrtowch, wchisprint, chisprint): New functions. (gettext_quote, quotearg_buffer_restyled): Use them. --- ChangeLog | 10 ++++++ lib/quotearg.c | 91 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 87 insertions(+), 14 deletions(-)
diff --git a/ChangeLog b/ChangeLog index cd74c15b09..ec8648260e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2026-05-25 Paul Eggert <[email protected]> + quotearg: support USE_C_LOCALE variant + This is for gzip, which does not use setlocale, + but does need to quote file names. + * lib/quotearg.c (USE_C_LOCALE): Default to 0. If set, include + c-ctype.h instead of ctype.h, gettext.h, uchar.h, wchar.h; and + define _ to be an identity macro. + (wch, mbstate): New types. + (mbs_clear, mbrtowch, wchisprint, chisprint): New functions. + (gettext_quote, quotearg_buffer_restyled): Use them. + quotearg: lessen dependencies * lib/quotearg.c: Do not include c-strcaseeq.h, as its macros are no longer used here. diff --git a/lib/quotearg.c b/lib/quotearg.c index c3706016ec..21014d4782 100644 --- a/lib/quotearg.c +++ b/lib/quotearg.c @@ -33,17 +33,80 @@ #include "minmax.h" #include "xalloc.h" -#include <ctype.h> #include <errno.h> #include <limits.h> #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <uchar.h> -#include <wchar.h> -#include "gettext.h" -#define _(msgid) dgettext (GNULIB_TEXT_DOMAIN, msgid) +/* If USE_C_LOCALE is set to 1, this file defines a function that uses the + "C" locale, regardless of the current locale. Applications + defining this macro might avoid the need for Gnulib's c32isprint, + gettext-h, mbrtoc32, mbsinit, mbszero, wchar-h, and uchar-h modules, + but they also need the c-ctype module. */ +#ifndef USE_C_LOCALE +# define USE_C_LOCALE 0 +#endif + +#if USE_C_LOCALE +# include <c-ctype.h> +typedef unsigned char wch; +typedef struct incomplete_mbstate *mbstate; +# ifndef GNULIB_MBRTOC32_REGULAR +# define GNULIB_MBRTOC32_REGULAR 1 +# endif +#else +# include <ctype.h> +# include <wchar.h> +# include <uchar.h> +typedef char32_t wch; +typedef mbstate_t mbstate; +#endif + +static void +mbs_clear (MAYBE_UNUSED mbstate *ps) +{ +#if !USE_C_LOCALE + mbszero (ps); +#endif +} + +static size_t +mbrtowch (wch *pwc, char const *s, size_t n, MAYBE_UNUSED mbstate *ps) +{ +#if USE_C_LOCALE + return n && (*pwc = *s); +#else + return mbrtoc32 (pwc, s, n, ps); +#endif +} + +static bool +wchisprint (wch w) +{ +#if USE_C_LOCALE + return c_isprint (w); +#else + return c32isprint (w); +#endif +} + +static bool +chisprint (unsigned char c) +{ +#if USE_C_LOCALE + return c_isprint (c); +#else + return isprint (c) != 0; +#endif +} + +#if USE_C_LOCALE +# define _(msgid) msgid +#else +# include "gettext.h" +# define _(msgid) dgettext (GNULIB_TEXT_DOMAIN, msgid) +#endif #define N_(msgid) msgid #ifndef SIZE_MAX @@ -225,9 +288,9 @@ gettext_quote (char const *msgid, enum quoting_style s) and means we need not use a function like locale_charset that has other dependencies. */ static char const quote[][4] = { "\xe2\x80\x98", "\xe2\x80\x99" }; - char32_t w; - mbstate_t mbs; mbszero (&mbs); - if (mbrtoc32 (&w, quote[0], 3, &mbs) == 3 && w == 0x2018) + wch w; + mbstate mbs; mbs_clear (&mbs); + if (mbrtowch (&w, quote[0], 3, &mbs) == 3 && w == 0x2018) return quote[msgid[0] == '\'']; return (s == clocale_quoting_style ? "\"" : "'"); @@ -254,7 +317,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize, char const *left_quote, char const *right_quote) { - bool unibyte_locale = MB_CUR_MAX == 1; + bool unibyte_locale = USE_C_LOCALE || MB_CUR_MAX == 1; size_t len = 0; size_t orig_buffersize = 0; @@ -601,11 +664,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize, if (unibyte_locale) { m = 1; - printable = isprint (c) != 0; + printable = chisprint (c); } else { - mbstate_t mbs; mbszero (&mbs); + mbstate mbs; mbs_clear (&mbs); m = 0; printable = true; @@ -614,8 +677,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize, for (;;) { - char32_t w; - size_t bytes = mbrtoc32 (&w, &arg[i + m], + wch w; + size_t bytes = mbrtowch (&w, &arg[i + m], argsize - (i + m), &mbs); if (bytes == 0) break; @@ -653,7 +716,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize, } } - if (! c32isprint (w)) + if (! wchisprint (w)) printable = false; m += bytes; } -- 2.54.0
