#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-#if !HAVE_MBRTOWC
-/* 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
-# undef mbstate_t
-# define mbstate_t int
-# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
-# define iswprint(wc) isprint ((unsigned char) (wc))
-# undef HAVE_MBSINIT
-#endif
-
-#if !defined mbsinit && !HAVE_MBSINIT
-# define mbsinit(ps) 1
-#endif
-
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* Quote the characters indicated by this bit vector even if the
quoting style would not normally require them to be quoted. */
unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
+
+ /* The left quote for custom_quoting_style. */
+ char const *left_quote;
+
+ /* The right quote for custom_quoting_style. */
+ char const *right_quote;
};
/* Names of quoting styles. */
return r;
}
+void
+set_custom_quoting (struct quoting_options *o,
+ char const *left_quote, char const *right_quote)
+{
+ if (!o)
+ o = &default_quoting_options;
+ o->style = custom_quoting_style;
+ if (!left_quote || !right_quote)
+ abort ();
+ o->left_quote = left_quote;
+ o->right_quote = right_quote;
+}
+
+/* Return quoting options for STYLE, with no extra quoting. */
+static struct quoting_options
+quoting_options_from_style (enum quoting_style style)
+{
+ struct quoting_options o;
+ o.style = style;
+ o.flags = 0;
+ memset (o.quote_these_too, 0, sizeof o.quote_these_too);
+ return o;
+}
+
/* MSGID approximates a quotation mark. Return its translation if it
has one; otherwise, return either it or "\"", depending on S. */
static char const *
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
- argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and the
- remaining part of O to control quoting.
+ argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
+ QUOTE_THESE_TOO to control quoting.
Terminate the output with a null character, and return the written
size of the output, not counting the terminating null.
If BUFFERSIZE is too small to store the output string, return the
If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
- ARGSIZE, O), except it uses QUOTING_STYLE and FLAGS instead of the
- quoting style specified by O, and O may not be null. */
+ ARGSIZE, O), except it breaks O into its component pieces and is
+ not careful about errno. */
static size_t
quotearg_buffer_restyled (char *buffer, size_t buffersize,
char const *arg, size_t argsize,
enum quoting_style quoting_style, int flags,
- struct quoting_options const *o)
+ unsigned int const *quote_these_too,
+ char const *left_quote,
+ char const *right_quote)
{
size_t i;
size_t len = 0;
case locale_quoting_style:
case clocale_quoting_style:
+ case custom_quoting_style:
{
- /* TRANSLATORS:
- Get translations for open and closing quotation marks.
-
- 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 "`" 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.
-
- If you don't know what to put here, please see
- <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
- and use glyphs suitable for your language. */
-
- char const *left = gettext_quote (N_("`"), quoting_style);
- char const *right = gettext_quote (N_("'"), quoting_style);
+ if (quoting_style != custom_quoting_style)
+ {
+ /* TRANSLATORS:
+ Get translations for open and closing quotation marks.
+
+ 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 "`" 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.
+
+ If you don't know what to put here, please see
+ <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
+ and use glyphs suitable for your language. */
+ left_quote = gettext_quote (N_("`"), quoting_style);
+ right_quote = gettext_quote (N_("'"), quoting_style);
+ }
if (!elide_outer_quotes)
- for (quote_string = left; *quote_string; quote_string++)
+ for (quote_string = left_quote; *quote_string; quote_string++)
STORE (*quote_string);
backslash_escapes = true;
- quote_string = right;
+ quote_string = right_quote;
quote_string_len = strlen (quote_string);
}
break;
{
unsigned char c;
unsigned char esc;
+ bool is_right_quote = false;
if (backslash_escapes
&& quote_string_len
{
if (elide_outer_quotes)
goto force_outer_quoting_style;
- STORE ('\\');
+ is_right_quote = true;
}
c = arg[i];
if (elide_outer_quotes)
goto force_outer_quoting_style;
STORE ('\\');
- STORE ('0');
- STORE ('0');
+ /* If quote_string were to begin with digits, we'd need to
+ test for the end of the arg as well. However, it's
+ hard to imagine any locale that would use digits in
+ quotes, and set_custom_quoting is documented not to
+ accept them. */
+ if (i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
+ {
+ STORE ('0');
+ STORE ('0');
+ }
c = '0';
+ /* We don't have to worry that this last '0' will be
+ backslash-escaped because, again, quote_string should
+ not start with it and because quote_these_too is
+ documented as not accepting it. */
}
else if (flags & QA_ELIDE_NULL_BYTES)
continue;
break;
case c_quoting_style:
- if (i + 2 < argsize && arg[i + 1] == '?')
+ if ((flags & QA_SPLIT_TRIGRAPHS)
+ && i + 2 < argsize && arg[i + 1] == '?')
switch (arg[i + 2])
{
case '!': case '\'':
c = arg[i + 2];
i += 2;
STORE ('?');
- STORE ('\\');
+ STORE ('"');
+ STORE ('"');
STORE ('?');
break;
case '\r': esc = 'r'; goto c_and_shell_escape;
case '\t': esc = 't'; goto c_and_shell_escape;
case '\v': esc = 'v'; goto c_escape;
- case '\\': esc = c; goto c_and_shell_escape;
+ case '\\': esc = c;
+ /* No need to escape the escape if we are trying to elide
+ outer quotes and nothing else is problematic. */
+ if (backslash_escapes && elide_outer_quotes && quote_string_len)
+ goto store_c;
c_and_shell_escape:
if (quoting_style == shell_always_quoting_style
case 'o': case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
/* These characters don't cause problems, no matter what the
- quoting style is. They cannot start multibyte sequences. */
+ quoting style is. They cannot start multibyte sequences.
+ A digit or a special letter would cause trouble if it
+ appeared at the beginning of quote_string because we'd then
+ escape by prepending a backslash. However, it's hard to
+ imagine any locale that would use digits or letters as
+ quotes, and set_custom_quoting is documented not to accept
+ them. Also, a digit or a special letter would cause
+ trouble if it appeared in quote_these_too, but that's also
+ documented as not accepting them. */
break;
default:
STORE ('0' + ((c >> 3) & 7));
c = '0' + (c & 7);
}
+ else if (is_right_quote)
+ {
+ STORE ('\\');
+ is_right_quote = false;
+ }
if (ilim <= i + 1)
break;
STORE (c);
}
}
- if (! (backslash_escapes
- && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
+ if (! ((backslash_escapes || elide_outer_quotes)
+ && quote_these_too
+ && quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
+ && !is_right_quote)
goto store_c;
store_escape:
STORE (c);
}
- if (i == 0 && quoting_style == shell_always_quoting_style
+ if (len == 0 && quoting_style == shell_always_quoting_style
&& elide_outer_quotes)
goto force_outer_quoting_style;
return len;
force_outer_quoting_style:
+ /* Don't reuse quote_these_too, since the addition of outer quotes
+ sufficiently quotes the specified characters. */
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
quoting_style,
- flags & ~QA_ELIDE_OUTER_QUOTES, o);
+ flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
+ left_quote, right_quote);
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
struct quoting_options const *p = o ? o : &default_quoting_options;
int e = errno;
size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
- p->style, p->flags, p);
+ p->style, p->flags, p->quote_these_too,
+ p->left_quote, p->right_quote);
errno = e;
return r;
}
/* Elide embedded null bytes if we can't return a size. */
int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
- flags, p) + 1;
+ flags, p->quote_these_too,
+ p->left_quote,
+ p->right_quote) + 1;
char *buf = xcharalloc (bufsize);
- quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags, p);
+ quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
+ p->quote_these_too,
+ p->left_quote, p->right_quote);
errno = e;
if (size)
*size = bufsize - 1;
/* Elide embedded null bytes since we don't return a size. */
int flags = options->flags | QA_ELIDE_NULL_BYTES;
size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
- options->style, flags, options);
+ options->style, flags,
+ options->quote_these_too,
+ options->left_quote,
+ options->right_quote);
if (size <= qsize)
{
free (val);
sv[n].val = val = xcharalloc (size);
quotearg_buffer_restyled (val, size, arg, argsize, options->style,
- flags, options);
+ flags, options->quote_these_too,
+ options->left_quote,
+ options->right_quote);
}
errno = e;
return quotearg_n_mem (0, arg, argsize);
}
-/* Return quoting options for STYLE, with no extra quoting. */
-static struct quoting_options
-quoting_options_from_style (enum quoting_style style)
-{
- struct quoting_options o;
- o.style = style;
- o.flags = 0;
- memset (o.quote_these_too, 0, sizeof o.quote_these_too);
- return o;
-}
-
char *
quotearg_n_style (int n, enum quoting_style s, char const *arg)
{
{
return quotearg_char_mem (arg, argsize, ':');
}
+
+char *
+quotearg_n_custom (int n, char const *left_quote,
+ char const *right_quote, char const *arg)
+{
+ return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
+ SIZE_MAX);
+}
+
+char *
+quotearg_n_custom_mem (int n, char const *left_quote,
+ char const *right_quote,
+ char const *arg, size_t argsize)
+{
+ struct quoting_options o = default_quoting_options;
+ set_custom_quoting (&o, left_quote, right_quote);
+ return quotearg_n_options (n, arg, argsize, &o);
+}
+
+char *
+quotearg_custom (char const *left_quote, char const *right_quote,
+ char const *arg)
+{
+ return quotearg_n_custom (0, left_quote, right_quote, arg);
+}
+
+char *
+quotearg_custom_mem (char const *left_quote, char const *right_quote,
+ char const *arg, size_t argsize)
+{
+ return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
+ argsize);
+}