# include <wchar.h>
#endif
-#if HAVE_MBRTOWC && HAVE_WCHAR_H
+#if HAVE_MBRTOWC
size_t mbrtowc ();
-# if !HAVE_MBSTATE_T_OBJECT
+# ifdef mbstate_t
# define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
+# define mbsinit(ps) 1
# endif
#else
+/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
+ other macros are defined only for documentation and to satisfy C
+ syntax. */
+# undef MB_CUR_MAX
+# define MB_CUR_MAX 1
# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
# define mbsinit(ps) 1
# define iswprint(wc) ISPRINT ((unsigned char) (wc))
#define INT_BITS (sizeof (int) * CHAR_BIT)
#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
-/* Undefine to protect against the definition in wctype.h of solaris2.6. */
-# undef ISASCII
-# define ISASCII(c) 1
+# define IN_CTYPE_DOMAIN(c) 1
#else
-# define ISASCII(c) isascii (c)
+# define IN_CTYPE_DOMAIN(c) isascii(c)
#endif
+
/* Undefine to protect against the definition in wctype.h of solaris2.6. */
#undef ISPRINT
-#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
struct quoting_options
{
"c",
"escape",
"locale",
+ "clocale",
0
};
shell_always_quoting_style,
c_quoting_style,
escape_quoting_style,
- locale_quoting_style
+ locale_quoting_style,
+ clocale_quoting_style
};
/* The default quoting options. */
return r;
}
-/* Return the translation of MSGID if there is one, and
- DEFAULT_TRANSLATION otherwise. */
+/* MSGID approximates a quotation mark. Return its translation if it
+ has one; otherwise, return either it or "\"", depending on S. */
static char const *
-gettext_default (char const *msgid, char const *default_translation)
+gettext_quote (char const *msgid, enum quoting_style s)
{
char const *translation = _(msgid);
- return translation == msgid ? default_translation : translation;
+ if (translation == msgid && s == clocale_quoting_style)
+ translation = "\"";
+ return translation;
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
char const *quote_string = 0;
size_t quote_string_len = 0;
int backslash_escapes = 0;
+ int unibyte_locale = MB_CUR_MAX == 1;
#define STORE(c) \
do \
break;
case locale_quoting_style:
+ case clocale_quoting_style:
{
/* Get translations for open and closing quotation marks.
- The message catalog should translate "{LEFT QUOTATION
- MARK}" to a left quotation mark suitable for the locale,
- and similarly for "{RIGHT QUOTATION MARK}". If the catalog
- has no translation, the code below uses a neutral
- (vertical) quotation mark instead, as it is the most
- appropriate for the C locale.
+ The message catalog should translate "`" to a left
+ quotation mark suitable for the locale, and similarly for
+ "'". If the catalog has no translation,
+ locale_quoting_style quotes `like this', and
+ clocale_quoting_style quotes "like this".
For example, an American English Unicode locale should
- translate the string "{LEFT QUOTATION MARK}" to the
- character U+201C (LEFT DOUBLE QUOTATION MARK), and should
- translate the string "{RIGHT QUOTATION MARK}" to the
- character U+201D (RIGHT DOUBLE QUOTATION MARK). A British
- English Unicode locale should instead translate these to
- U+2018 (LEFT SINGLE QUOTATION MARK) and U+2019 (RIGHT
- SINGLE QUOTATION MARK), respectively. */
-
- static char const quotation_mark[] = "\"";
- char const *left = gettext_default (N_("{LEFT QUOTATION MARK}"),
- quotation_mark);
- char const *right = gettext_default (N_("{RIGHT QUOTATION MARK}"),
- quotation_mark);
+ translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
+ should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
+ MARK). A British English Unicode locale should instead
+ translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
+ U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. */
+
+ char const *left = gettext_quote (N_("`"), quoting_style);
+ char const *right = gettext_quote (N_("'"), quoting_style);
for (quote_string = left; *quote_string; quote_string++)
STORE (*quote_string);
backslash_escapes = 1;
we can't easily escape single characters within it. */
{
/* Length of multibyte sequence found so far. */
- size_t m = 0;
+ size_t m;
- int printable = 1;
- mbstate_t mbstate;
- memset (&mbstate, 0, sizeof mbstate);
+ int printable;
- if (argsize == (size_t) -1)
- argsize = strlen (arg);
-
- do
+ if (unibyte_locale)
{
- wchar_t w;
- size_t bytes = mbrtowc (&w, &arg[i + m],
- argsize - (i + m), &mbstate);
- if (bytes == 0)
- break;
- else if (bytes == (size_t) -1)
- {
- printable = 0;
- break;
- }
- else if (bytes == (size_t) -2)
- {
- printable = 0;
- while (i + m < argsize && arg[i + m])
- m++;
- break;
- }
- else
- {
- if (! iswprint (w))
- printable = 0;
- m += bytes;
- }
+ m = 1;
+ printable = ISPRINT (c);
}
- while (! mbsinit (&mbstate));
-
- if (m <= 1)
+ else
{
- /* Escape a unibyte character like a multibyte
- sequence if using backslash escapes, and if the
- character is not printable. */
- m = backslash_escapes && ! ISPRINT (c);
- printable = 0;
+ mbstate_t mbstate;
+ memset (&mbstate, 0, sizeof mbstate);
+
+ m = 0;
+ printable = 1;
+ if (argsize == (size_t) -1)
+ argsize = strlen (arg);
+
+ do
+ {
+ wchar_t w;
+ size_t bytes = mbrtowc (&w, &arg[i + m],
+ argsize - (i + m), &mbstate);
+ if (bytes == 0)
+ break;
+ else if (bytes == (size_t) -1)
+ {
+ printable = 0;
+ break;
+ }
+ else if (bytes == (size_t) -2)
+ {
+ printable = 0;
+ while (i + m < argsize && arg[i + m])
+ m++;
+ break;
+ }
+ else
+ {
+ if (! iswprint (w))
+ printable = 0;
+ m += bytes;
+ }
+ }
+ while (! mbsinit (&mbstate));
}
- if (m)
+ if (1 < m || (backslash_escapes && ! printable))
{
/* Output a multibyte sequence, or an escaped
unprintable unibyte character. */
- size_t imax = i + m - 1;
+ size_t ilim = i + m;
for (;;)
{
STORE ('0' + ((c >> 3) & 7));
c = '0' + (c & 7);
}
- if (i == imax)
+ if (ilim <= i + 1)
break;
STORE (c);
c = arg[++i];
quotearg_n_options (int n, char const *arg,
struct quoting_options const *options)
{
- static unsigned int nslots;
- static struct slotvec
+ /* Preallocate a slot 0 buffer, so that the caller can always quote
+ one small component of a "memory exhausted" message in slot 0. */
+ static char slot0[256];
+ static unsigned int nslots = 1;
+ struct slotvec
{
size_t size;
char *val;
- } *slotvec;
+ };
+ static struct slotvec slotvec0 = {sizeof slot0, slot0};
+ static struct slotvec *slotvec = &slotvec0;
if (nslots <= n)
{
size_t s = n1 * sizeof (struct slotvec);
if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
abort ();
+ if (slotvec == &slotvec0)
+ {
+ slotvec = (struct slotvec *) xmalloc (sizeof (struct slotvec));
+ *slotvec = slotvec0;
+ }
slotvec = (struct slotvec *) xrealloc (slotvec, s);
memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
nslots = n;
if (size <= qsize)
{
slotvec[n].size = size = qsize + 1;
- slotvec[n].val = val = xrealloc (val, size);
+ slotvec[n].val = val = xrealloc (val == slot0 ? 0 : val, size);
quotearg_buffer (val, size, arg, (size_t) -1, options);
}