X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fquotearg.c;h=75fbc72f3d5174559161bdd35b9237d777dc9830;hb=c70a54e290ea07f2ac94169b15aa1919dcb28028;hp=6f3ee9e86cf260c60821ba435b6c38b18c758711;hpb=96159f3a857b1eb302118ab0add8f725981dbca0;p=gnulib.git
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 6f3ee9e86..75fbc72f3 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -1,12 +1,12 @@
/* quotearg.c - quote arguments for output
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 Free
- Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,8 +14,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program. If not, see . */
/* Written by Paul Eggert */
@@ -31,20 +30,13 @@
#include
#include
#include
+#include
+#include
#include "gettext.h"
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
-#if HAVE_WCHAR_H
-
-/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared. */
-# include
-# include
-
-# include
-#endif
-
#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
@@ -62,15 +54,6 @@
# define mbsinit(ps) 1
#endif
-#ifndef iswprint
-# if HAVE_WCTYPE_H
-# include
-# endif
-# if !defined iswprint && !HAVE_ISWPRINT
-# define iswprint(wc) 1
-# endif
-#endif
-
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
@@ -82,6 +65,9 @@ struct quoting_options
/* Basic quoting style. */
enum quoting_style style;
+ /* Additional flags. Bitwise combination of enum quoting_flags. */
+ int flags;
+
/* 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];
@@ -94,6 +80,7 @@ char const *const quoting_style_args[] =
"shell",
"shell-always",
"c",
+ "c-maybe",
"escape",
"locale",
"clocale",
@@ -107,6 +94,7 @@ enum quoting_style const quoting_style_vals[] =
shell_quoting_style,
shell_always_quoting_style,
c_quoting_style,
+ c_maybe_quoting_style,
escape_quoting_style,
locale_quoting_style,
clocale_quoting_style
@@ -160,6 +148,32 @@ set_char_quoting (struct quoting_options *o, char c, int i)
return r;
}
+/* In O (or in the default if O is null),
+ set the value of the quoting options flag to I, which can be a
+ bitwise combination of enum quoting_flags, or 0 for default
+ behavior. Return the old value. */
+int
+set_quoting_flags (struct quoting_options *o, int i)
+{
+ int r;
+ if (!o)
+ o = &default_quoting_options;
+ r = o->flags;
+ o->flags = i;
+ return r;
+}
+
+/* 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 *
@@ -172,8 +186,8 @@ gettext_quote (char const *msgid, enum quoting_style s)
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
- argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
- non-quoting-style 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
@@ -181,14 +195,14 @@ gettext_quote (char const *msgid, enum quoting_style s)
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 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,
- struct quoting_options const *o)
+ enum quoting_style quoting_style, int flags,
+ unsigned int const *quote_these_too)
{
size_t i;
size_t len = 0;
@@ -196,6 +210,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
size_t quote_string_len = 0;
bool backslash_escapes = false;
bool unibyte_locale = MB_CUR_MAX == 1;
+ bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
#define STORE(c) \
do \
@@ -208,8 +223,13 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
switch (quoting_style)
{
+ case c_maybe_quoting_style:
+ quoting_style = c_quoting_style;
+ elide_outer_quotes = true;
+ /* Fall through. */
case c_quoting_style:
- STORE ('"');
+ if (!elide_outer_quotes)
+ STORE ('"');
backslash_escapes = true;
quote_string = "\"";
quote_string_len = 1;
@@ -217,6 +237,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
case escape_quoting_style:
backslash_escapes = true;
+ elide_outer_quotes = false;
break;
case locale_quoting_style:
@@ -244,22 +265,32 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
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);
+ if (!elide_outer_quotes)
+ for (quote_string = left; *quote_string; quote_string++)
+ STORE (*quote_string);
backslash_escapes = true;
quote_string = right;
quote_string_len = strlen (quote_string);
}
break;
+ case shell_quoting_style:
+ quoting_style = shell_always_quoting_style;
+ elide_outer_quotes = true;
+ /* Fall through. */
case shell_always_quoting_style:
- STORE ('\'');
+ if (!elide_outer_quotes)
+ STORE ('\'');
quote_string = "'";
quote_string_len = 1;
break;
- default:
+ case literal_quoting_style:
+ elide_outer_quotes = false;
break;
+
+ default:
+ abort ();
}
for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
@@ -271,7 +302,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
&& quote_string_len
&& i + quote_string_len <= argsize
&& memcmp (arg + i, quote_string, quote_string_len) == 0)
- STORE ('\\');
+ {
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
+ STORE ('\\');
+ }
c = arg[i];
switch (c)
@@ -279,21 +314,31 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
case '\0':
if (backslash_escapes)
{
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
STORE ('\\');
- STORE ('0');
- STORE ('0');
+ if (i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
+ {
+ STORE ('0');
+ STORE ('0');
+ }
c = '0';
}
+ else if (flags & QA_ELIDE_NULL_BYTES)
+ continue;
break;
case '?':
switch (quoting_style)
{
- case shell_quoting_style:
- goto use_shell_always_quoting_style;
+ case shell_always_quoting_style:
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
+ 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 '\'':
@@ -301,10 +346,13 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
case '<': case '=': case '>':
/* Escape the second '?' in what would otherwise be
a trigraph. */
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
c = arg[i + 2];
i += 2;
STORE ('?');
- STORE ('\\');
+ STORE ('"');
+ STORE ('"');
STORE ('?');
break;
@@ -325,11 +373,17 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
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_quoting_style)
- goto use_shell_always_quoting_style;
+ if (quoting_style == shell_always_quoting_style
+ && elide_outer_quotes)
+ goto force_outer_quoting_style;
+ /* Fall through. */
c_escape:
if (backslash_escapes)
{
@@ -359,24 +413,19 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
be the first bytes of multibyte characters, which means
we should check them with mbrtowc, but in practice this
doesn't happen so it's not worth worrying about. */
- if (quoting_style == shell_quoting_style)
- goto use_shell_always_quoting_style;
+ if (quoting_style == shell_always_quoting_style
+ && elide_outer_quotes)
+ goto force_outer_quoting_style;
break;
case '\'':
- switch (quoting_style)
+ if (quoting_style == shell_always_quoting_style)
{
- case shell_quoting_style:
- goto use_shell_always_quoting_style;
-
- case shell_always_quoting_style:
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
STORE ('\'');
STORE ('\\');
STORE ('\'');
- break;
-
- default:
- break;
}
break;
@@ -448,7 +497,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
that is really the 2nd byte of a multibyte character.
In practice the problem is limited to ASCII
chars >= '@' that are shell special chars. */
- if ('[' == 0x5b && quoting_style == shell_quoting_style)
+ if ('[' == 0x5b && elide_outer_quotes
+ && quoting_style == shell_always_quoting_style)
{
size_t j;
for (j = 1; j < bytes; j++)
@@ -456,7 +506,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
{
case '[': case '\\': case '^':
case '`': case '|':
- goto use_shell_always_quoting_style;
+ goto force_outer_quoting_style;
default:
break;
@@ -481,6 +531,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
{
if (backslash_escapes && ! printable)
{
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
STORE ('\\');
STORE ('0' + (c >> 6));
STORE ('0' + ((c >> 3) & 7));
@@ -497,21 +549,25 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
}
}
- 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))))
goto store_c;
store_escape:
+ if (elide_outer_quotes)
+ goto force_outer_quoting_style;
STORE ('\\');
store_c:
STORE (c);
}
- if (i == 0 && quoting_style == shell_quoting_style)
- goto use_shell_always_quoting_style;
+ if (len == 0 && quoting_style == shell_always_quoting_style
+ && elide_outer_quotes)
+ goto force_outer_quoting_style;
- if (quote_string)
+ if (quote_string && !elide_outer_quotes)
for (; *quote_string; quote_string++)
STORE (*quote_string);
@@ -519,9 +575,12 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
buffer[len] = '\0';
return len;
- use_shell_always_quoting_style:
+ 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,
- shell_always_quoting_style, o);
+ quoting_style,
+ flags & ~QA_ELIDE_OUTER_QUOTES, NULL);
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
@@ -541,22 +600,41 @@ quotearg_buffer (char *buffer, size_t buffersize,
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);
+ p->style, p->flags, p->quote_these_too);
errno = e;
return r;
}
-/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
- allocated storage containing the quoted string. */
+/* Equivalent to quotearg_alloc (ARG, ARGSIZE, NULL, O). */
char *
quotearg_alloc (char const *arg, size_t argsize,
struct quoting_options const *o)
{
+ return quotearg_alloc_mem (arg, argsize, NULL, o);
+}
+
+/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
+ allocated storage containing the quoted string, and store the
+ resulting size into *SIZE, if non-NULL. The result can contain
+ embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
+ NULL, and set_quoting_flags has not set the null byte elision
+ flag. */
+char *
+quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
+ struct quoting_options const *o)
+{
+ struct quoting_options const *p = o ? o : &default_quoting_options;
int e = errno;
- size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
+ /* 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->quote_these_too) + 1;
char *buf = xcharalloc (bufsize);
- quotearg_buffer (buf, bufsize, arg, argsize, o);
+ quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
+ p->quote_these_too);
errno = e;
+ if (size)
+ *size = bufsize - 1;
return buf;
}
@@ -638,7 +716,11 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
{
size_t size = sv[n].size;
char *val = sv[n].val;
- size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
+ /* 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->quote_these_too);
if (size <= qsize)
{
@@ -646,7 +728,8 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
if (val != slot0)
free (val);
sv[n].val = val = xcharalloc (size);
- quotearg_buffer (val, size, arg, argsize, options);
+ quotearg_buffer_restyled (val, size, arg, argsize, options->style,
+ flags, options->quote_these_too);
}
errno = e;
@@ -661,19 +744,21 @@ quotearg_n (int n, char const *arg)
}
char *
+quotearg_n_mem (int n, char const *arg, size_t argsize)
+{
+ return quotearg_n_options (n, arg, argsize, &default_quoting_options);
+}
+
+char *
quotearg (char const *arg)
{
return quotearg_n (0, arg);
}
-/* Return quoting options for STYLE, with no extra quoting. */
-static struct quoting_options
-quoting_options_from_style (enum quoting_style style)
+char *
+quotearg_mem (char const *arg, size_t argsize)
{
- struct quoting_options o;
- o.style = style;
- memset (o.quote_these_too, 0, sizeof o.quote_these_too);
- return o;
+ return quotearg_n_mem (0, arg, argsize);
}
char *
@@ -698,12 +783,24 @@ quotearg_style (enum quoting_style s, char const *arg)
}
char *
-quotearg_char (char const *arg, char ch)
+quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
+{
+ return quotearg_n_style_mem (0, s, arg, argsize);
+}
+
+char *
+quotearg_char_mem (char const *arg, size_t argsize, char ch)
{
struct quoting_options options;
options = default_quoting_options;
set_char_quoting (&options, ch, 1);
- return quotearg_n_options (0, arg, SIZE_MAX, &options);
+ return quotearg_n_options (0, arg, argsize, &options);
+}
+
+char *
+quotearg_char (char const *arg, char ch)
+{
+ return quotearg_char_mem (arg, SIZE_MAX, ch);
}
char *
@@ -711,3 +808,9 @@ quotearg_colon (char const *arg)
{
return quotearg_char (arg, ':');
}
+
+char *
+quotearg_colon_mem (char const *arg, size_t argsize)
+{
+ return quotearg_char_mem (arg, argsize, ':');
+}