[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
quotearg: implement custom_quoting_style
From: |
Joel E. Denny |
Subject: |
quotearg: implement custom_quoting_style |
Date: |
Sat, 22 Aug 2009 22:01:10 -0400 (EDT) |
User-agent: |
Alpine 1.00 (DEB 882 2007-12-20) |
The following patch series implements custom quotation marks in quotearg.
My main motivation is to be able to handle single-quoted strings. For
example, you can invoke this:
quotearg_custom ("'", "'", "joel's\tstring");
to produce this:
"'joel\\'s\\tstring'"
However, I figured it was probably better to generalize. For example, you
can also invoke this:
quotearg_custom ("(", ")", "(joel's)\tstring");
to produce this:
"((joel's\\)\\tstring)"
As a somewhat separate issue, the last patch in this series documents a
limitation of the quote_these_too array that I discovered while working on
the other patches: quote_these_too should not contain a digit or a letter
that's special after a backslash. It looks straightforward to overcome
this limitation, but I'm not sure anyone would benefit, so I didn't
bother. I just documented it.
>From f81fc0cf92afa6a6b3f7a87bc898b344fb73c6a8 Mon Sep 17 00:00:00 2001
From: Joel E. Denny <address@hidden>
Date: Sat, 22 Aug 2009 17:55:15 -0400
Subject: [PATCH] quotearg-tests: test escaping of embedded locale quotes
* tests/test-quotearg.c (struct result_strings): Add member for
new input.
(LQ_ENC, RQ_ENC, RQ_ESC): New macros.
(inputs): Add new input.
(results_g): Add expected results.
(flag_results): Likewise.
(locale_results): Likewise.
(compare_strings): Check those.
---
ChangeLog | 12 +++++
tests/test-quotearg.c | 115 ++++++++++++++++++++++++++++++-------------------
2 files changed, 83 insertions(+), 44 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 4e33717..361914b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-08-22 Joel E. Denny <address@hidden>
+
+ quotearg-tests: test escaping of embedded locale quotes
+ * tests/test-quotearg.c (struct result_strings): Add member for
+ new input.
+ (LQ_ENC, RQ_ENC, RQ_ESC): New macros.
+ (inputs): Add new input.
+ (results_g): Add expected results.
+ (flag_results): Likewise.
+ (locale_results): Likewise.
+ (compare_strings): Check those.
+
2009-08-22 Bruno Haible <address@hidden>
* modules/binary-io (License): Relicense under LGPL.
diff --git a/tests/test-quotearg.c b/tests/test-quotearg.c
index 73bb1f9..ef91c80 100644
--- a/tests/test-quotearg.c
+++ b/tests/test-quotearg.c
@@ -52,6 +52,7 @@ struct result_strings {
char const *str4; /* Translation of " \t\n'\"\033?""?/\\". */
char const *str5; /* Translation of "a:b". */
char const *str6; /* Translation of "a\\b". */
+ char const *str7; /* Translation of LQ RQ. */
};
struct result_groups {
@@ -60,118 +61,140 @@ struct result_groups {
struct result_strings group3; /* Via quotearg_colon{,_mem}. */
};
+/* These quotes are borrowed from a pt_PT.utf8 translation. */
+# define LQ "\302\253"
+# define RQ "\302\273"
+# define LQ_ENC "\\302\\253"
+# define RQ_ENC "\\302\\273"
+# define RQ_ESC "\\\302\273"
+
static struct result_strings inputs = {
- "", "\0001\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b"
+ "", "\0001\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
+ LQ RQ
};
static struct result_groups results_g[] = {
/* literal_quoting_style */
- { { "", "\0""1\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b" },
- { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b" },
- { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b" } },
+ { { "", "\0""1\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
+ LQ RQ },
+ { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
+ LQ RQ },
+ { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b",
+ LQ RQ } },
/* shell_quoting_style */
{ { "''", "\0""1\0", 3, "simple", "' \t\n'\\''\"\033?""?/\\'", "a:b",
- "'a\\b'" },
+ "'a\\b'", LQ RQ },
{ "''", "1", 1, "simple", "' \t\n'\\''\"\033?""?/\\'", "a:b",
- "'a\\b'" },
+ "'a\\b'", LQ RQ },
{ "''", "1", 1, "simple", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
- "'a\\b'" } },
+ "'a\\b'", LQ RQ } },
/* shell_always_quoting_style */
{ { "''", "'\0""1\0'", 5, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
- "'a\\b'" },
+ "'a\\b'", "'" LQ RQ "'" },
{ "''", "'1'", 3, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
- "'a\\b'" },
+ "'a\\b'", "'" LQ RQ "'" },
{ "''", "'1'", 3, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'",
- "'a\\b'" } },
+ "'a\\b'", "'" LQ RQ "'" } },
/* c_quoting_style */
{ { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"" },
+ "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" },
{ "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"" },
+ "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" },
{ "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"" } },
+ "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" } },
/* c_maybe_quoting_style */
{ { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
- "a:b", "a\\b" },
+ "a:b", "a\\b", "\"" LQ_ENC RQ_ENC "\"" },
{ "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
- "a:b", "a\\b" },
+ "a:b", "a\\b", "\"" LQ_ENC RQ_ENC "\"" },
{ "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
- "\"a:b\"", "a\\b" } },
+ "\"a:b\"", "a\\b", "\"" LQ_ENC RQ_ENC "\"" } },
/* escape_quoting_style */
{ { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a:b",
- "a\\\\b" },
+ "a\\\\b", LQ_ENC RQ_ENC },
{ "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a:b",
- "a\\\\b" },
+ "a\\\\b", LQ_ENC RQ_ENC },
{ "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a\\:b",
- "a\\\\b" } },
+ "a\\\\b", LQ_ENC RQ_ENC } },
/* locale_quoting_style */
{ { "`'", "`\\0001\\0'", 9, "`simple'", "` \\t\\n\\'\"\\033?""?/\\\\'",
- "`a:b'", "`a\\\\b'" },
+ "`a:b'", "`a\\\\b'", "`" LQ_ENC RQ_ENC "'" },
{ "`'", "`\\0001\\0'", 9, "`simple'", "` \\t\\n\\'\"\\033?""?/\\\\'",
- "`a:b'", "`a\\\\b'" },
+ "`a:b'", "`a\\\\b'", "`" LQ_ENC RQ_ENC "'" },
{ "`'", "`\\0001\\0'", 9, "`simple'", "` \\t\\n\\'\"\\033?""?/\\\\'",
- "`a\\:b'", "`a\\\\b'" } },
+ "`a\\:b'", "`a\\\\b'", "`" LQ_ENC RQ_ENC "'" } },
/* clocale_quoting_style */
{ { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"" },
+ "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" },
{ "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"" },
+ "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" },
{ "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"" } }
+ "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" } }
};
static struct result_groups flag_results[] = {
/* literal_quoting_style and QA_ELIDE_NULL_BYTES */
- { { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b" },
- { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b" },
- { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b" } },
+ { { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", LQ RQ },
+ { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", LQ RQ },
+ { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b", "a\\b", LQ RQ } },
/* c_quoting_style and QA_ELIDE_OUTER_QUOTES */
{ { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
- "a:b", "a\\b" },
+ "a:b", "a\\b", "\"" LQ_ENC RQ_ENC "\"" },
{ "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
- "a:b", "a\\b" },
+ "a:b", "a\\b", "\"" LQ_ENC RQ_ENC "\"" },
{ "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?""?/\\\\\"",
- "\"a:b\"", "a\\b" } },
+ "\"a:b\"", "a\\b", "\"" LQ_ENC RQ_ENC "\"" } },
/* c_quoting_style and QA_SPLIT_TRIGRAPHS */
{ { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"", "\"a\\\\b\"" },
+ "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" },
{ "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"", "\"a\\\\b\"" },
+ "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" },
{ "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
- "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"" } }
+ "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a\\:b\"", "\"a\\\\b\"",
+ "\"" LQ_ENC RQ_ENC "\"" } }
};
#if ENABLE_NLS
-/* These quotes are borrowed from a pt_PT.utf8 translation. */
-# define LQ "\302\253"
-# define RQ "\302\273"
-
static struct result_groups locale_results[] = {
/* locale_quoting_style */
{ { LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
- LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ },
+ LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ,
+ LQ LQ RQ_ESC RQ },
{ LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
- LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ },
+ LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ,
+ LQ LQ RQ_ESC RQ },
{ LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
- LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a\\:b" RQ, LQ "a\\\\b" RQ } },
+ LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a\\:b" RQ, LQ "a\\\\b" RQ,
+ LQ LQ RQ_ESC RQ } },
/* clocale_quoting_style */
{ { LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
- LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ },
+ LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ,
+ LQ LQ RQ_ESC RQ },
{ LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
- LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ },
+ LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ, LQ "a\\\\b" RQ,
+ LQ LQ RQ_ESC RQ },
{ LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
- LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a\\:b" RQ, LQ "a\\\\b" RQ } }
+ LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a\\:b" RQ, LQ "a\\\\b" RQ,
+ LQ LQ RQ_ESC RQ } }
};
#endif /* ENABLE_NLS */
@@ -214,6 +237,10 @@ compare_strings (char *(func) (char const *, size_t *),
len = strlen (inputs.str6);
p = func (inputs.str6, &len);
compare (results->str6, strlen (results->str6), p, len);
+
+ len = strlen (inputs.str7);
+ p = func (inputs.str7, &len);
+ compare (results->str7, strlen (results->str7), p, len);
}
static char *
--
1.5.4.3
>From 47bd1531d990bddf3ba09419ccc6309b9fe3ed4e Mon Sep 17 00:00:00 2001
From: Joel E. Denny <address@hidden>
Date: Sat, 22 Aug 2009 20:26:46 -0400
Subject: [PATCH] quotearg: fix right quote escaping when it's in quote_these_too
* lib/quotearg.c (quotearg_buffer_restyled): Upon seeing a right
quote, be sure to prepend only one backslash.
* tests/test-quotearg.c (use_quote_double_quotes): New function.
(main): Test it.
---
ChangeLog | 8 ++++++++
lib/quotearg.c | 11 +++++++++--
tests/test-quotearg.c | 13 +++++++++++++
3 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 361914b..5f1ec94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2009-08-22 Joel E. Denny <address@hidden>
+ quotearg: fix right quote escaping when it's in quote_these_too
+ * lib/quotearg.c (quotearg_buffer_restyled): Upon seeing a right
+ quote, be sure to prepend only one backslash.
+ * tests/test-quotearg.c (use_quote_double_quotes): New function.
+ (main): Test it.
+
+2009-08-22 Joel E. Denny <address@hidden>
+
quotearg-tests: test escaping of embedded locale quotes
* tests/test-quotearg.c (struct result_strings): Add member for
new input.
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 339bf34..3f9e628 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -280,6 +280,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
{
unsigned char c;
unsigned char esc;
+ bool is_right_quote = false;
if (backslash_escapes
&& quote_string_len
@@ -288,7 +289,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
{
if (elide_outer_quotes)
goto force_outer_quoting_style;
- STORE ('\\');
+ is_right_quote = true;
}
c = arg[i];
@@ -521,6 +522,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
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);
@@ -534,7 +540,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
if (! ((backslash_escapes || elide_outer_quotes)
&& quote_these_too
- && quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
+ && quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
+ && !is_right_quote)
goto store_c;
store_escape:
diff --git a/tests/test-quotearg.c b/tests/test-quotearg.c
index ef91c80..2e2c56b 100644
--- a/tests/test-quotearg.c
+++ b/tests/test-quotearg.c
@@ -264,6 +264,15 @@ use_quotearg (const char *str, size_t *len)
}
static char *
+use_quote_double_quotes (const char *str, size_t *len)
+{
+ char *p = *len == SIZE_MAX ? quotearg_char (str, '"')
+ : quotearg_char_mem (str, *len, '"');
+ *len = strlen (p);
+ return p;
+}
+
+static char *
use_quotearg_colon (const char *str, size_t *len)
{
char *p = (*len == SIZE_MAX ? quotearg_colon (str)
@@ -287,6 +296,8 @@ main (int argc, char *argv[])
set_quoting_style (NULL, i);
compare_strings (use_quotearg_buffer, &results_g[i].group1);
compare_strings (use_quotearg, &results_g[i].group2);
+ if (i == c_quoting_style)
+ compare_strings (use_quote_double_quotes, &results_g[i].group2);
compare_strings (use_quotearg_colon, &results_g[i].group3);
}
@@ -301,12 +312,14 @@ main (int argc, char *argv[])
== QA_ELIDE_NULL_BYTES);
compare_strings (use_quotearg_buffer, &flag_results[1].group1);
compare_strings (use_quotearg, &flag_results[1].group2);
+ compare_strings (use_quote_double_quotes, &flag_results[1].group2);
compare_strings (use_quotearg_colon, &flag_results[1].group3);
ASSERT (set_quoting_flags (NULL, QA_SPLIT_TRIGRAPHS)
== QA_ELIDE_OUTER_QUOTES);
compare_strings (use_quotearg_buffer, &flag_results[2].group1);
compare_strings (use_quotearg, &flag_results[2].group2);
+ compare_strings (use_quote_double_quotes, &flag_results[2].group2);
compare_strings (use_quotearg_colon, &flag_results[2].group3);
ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);
--
1.5.4.3
>From 814f12a49687047a2e9a5b03f8373a3986ca2c3b Mon Sep 17 00:00:00 2001
From: Joel E. Denny <address@hidden>
Date: Sat, 22 Aug 2009 04:21:49 -0400
Subject: [PATCH] quotearg: implement custom_quoting_style
* lib/quotearg.c: (struct quoting_options): Add left and right
fields to store quotes.
(set_custom_quoting): New public function.
(quotearg_buffer_restyled): Add left and right arguments,
handle them very much like locale quoting, and update all uses.
(quotearg_n_custom): New public function.
(quotearg_n_custom_mem): New public function.
(quotearg_custom): New public function.
(quotearg_custom_mem): New public function.
* lib/quotearg.h: Prototype and document new public functions.
(enum quoting_style): Add custom_quoting_style member and
document.
* tests/test-quotearg.c (custom_quotes): New array.
(custom_results): New array.
(main): Extend to test custom quoting.
---
ChangeLog | 19 ++++++++++
lib/quotearg.c | 89 +++++++++++++++++++++++++++++++++++++++++++-----
lib/quotearg.h | 61 +++++++++++++++++++++++++++++++++-
tests/test-quotearg.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 244 insertions(+), 11 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5f1ec94..255e17e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
2009-08-22 Joel E. Denny <address@hidden>
+ quotearg: implement custom_quoting_style
+ * lib/quotearg.c: (struct quoting_options): Add left and right
+ fields to store quotes.
+ (set_custom_quoting): New public function.
+ (quotearg_buffer_restyled): Add left and right arguments,
+ handle them very much like locale quoting, and update all uses.
+ (quotearg_n_custom): New public function.
+ (quotearg_n_custom_mem): New public function.
+ (quotearg_custom): New public function.
+ (quotearg_custom_mem): New public function.
+ * lib/quotearg.h: Prototype and document new public functions.
+ (enum quoting_style): Add custom_quoting_style member and
+ document.
+ * tests/test-quotearg.c (custom_quotes): New array.
+ (custom_results): New array.
+ (main): Extend to test custom quoting.
+
+2009-08-22 Joel E. Denny <address@hidden>
+
quotearg: fix right quote escaping when it's in quote_these_too
* lib/quotearg.c (quotearg_buffer_restyled): Upon seeing a right
quote, be sure to prepend only one backslash.
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 3f9e628..9e5f038 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -54,6 +54,12 @@ struct quoting_options
/* 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;
+
+ /* The right quote for custom_quoting_style. */
+ char const *right;
};
/* Names of quoting styles. */
@@ -146,6 +152,19 @@ set_quoting_flags (struct quoting_options *o, int i)
return r;
}
+void
+set_custom_quoting (struct quoting_options *o,
+ char const *l, char const *r)
+{
+ if (!o)
+ o = &default_quoting_options;
+ o->style = custom_quoting_style;
+ if (!l || !r)
+ abort ();
+ o->left = l;
+ o->right = r;
+}
+
/* Return quoting options for STYLE, with no extra quoting. */
static struct quoting_options
quoting_options_from_style (enum quoting_style style)
@@ -185,7 +204,8 @@ static size_t
quotearg_buffer_restyled (char *buffer, size_t buffersize,
char const *arg, size_t argsize,
enum quoting_style quoting_style, int flags,
- unsigned int const *quote_these_too)
+ unsigned int const *quote_these_too,
+ char const *left, char const *right)
{
size_t i;
size_t len = 0;
@@ -225,6 +245,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
case locale_quoting_style:
case clocale_quoting_style:
+ case custom_quoting_style:
{
/* TRANSLATORS:
Get translations for open and closing quotation marks.
@@ -246,8 +267,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
<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)
+ {
+ left = gettext_quote (N_("`"), quoting_style);
+ right = gettext_quote (N_("'"), quoting_style);
+ }
if (!elide_outer_quotes)
for (quote_string = left; *quote_string; quote_string++)
STORE (*quote_string);
@@ -301,6 +325,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
if (elide_outer_quotes)
goto force_outer_quoting_style;
STORE ('\\');
+ /* 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');
@@ -426,7 +455,13 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
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. */
break;
default:
@@ -570,7 +605,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
sufficiently quotes the specified characters. */
return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
quoting_style,
- flags & ~QA_ELIDE_OUTER_QUOTES, NULL);
+ flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
+ left, right);
}
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
@@ -590,7 +626,8 @@ 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->flags, p->quote_these_too);
+ p->style, p->flags, p->quote_these_too,
+ p->left, p->right);
errno = e;
return r;
}
@@ -618,10 +655,11 @@ quotearg_alloc_mem (char const *arg, size_t argsize,
size_t *size,
/* 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;
+ flags, p->quote_these_too,
+ p->left, p->right) + 1;
char *buf = xcharalloc (bufsize);
quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
- p->quote_these_too);
+ p->quote_these_too, p->left, p->right);
errno = e;
if (size)
*size = bufsize - 1;
@@ -710,7 +748,9 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
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);
+ options->quote_these_too,
+ options->left,
+ options->right);
if (size <= qsize)
{
@@ -719,7 +759,8 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
free (val);
sv[n].val = val = xcharalloc (size);
quotearg_buffer_restyled (val, size, arg, argsize, options->style,
- flags, options->quote_these_too);
+ flags, options->quote_these_too,
+ options->left, options->right);
}
errno = e;
@@ -804,3 +845,31 @@ quotearg_colon_mem (char const *arg, size_t argsize)
{
return quotearg_char_mem (arg, argsize, ':');
}
+
+char *
+quotearg_n_custom (int n, char const *l, char const *r, char const *arg)
+{
+ return quotearg_n_custom_mem (n, l, r, arg, SIZE_MAX);
+}
+
+char *
+quotearg_n_custom_mem (int n, char const *l, char const *r,
+ char const *arg, size_t argsize)
+{
+ struct quoting_options o = default_quoting_options;
+ set_custom_quoting (&o, l, r);
+ return quotearg_n_options (n, arg, argsize, &o);
+}
+
+char *
+quotearg_custom (char const *l, char const *r, char const *arg)
+{
+ return quotearg_n_custom (0, l, r, arg);
+}
+
+char *
+quotearg_custom_mem (char const *l, char const *r, char const *arg,
+ size_t argsize)
+{
+ return quotearg_n_custom_mem (0, l, r, arg, argsize);
+}
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 7700107..6704b32 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -157,7 +157,37 @@ enum quoting_style
"\302\253simple\302\273",
"\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273"
*/
- clocale_quoting_style
+ clocale_quoting_style,
+
+ /* Like c_quoting_style except use the custom quotation marks set by
+ set_custom_quoting. If custom quotation marks are not set, the
+ behavior is undefined.
+
+ left = right = "'"
+ quotearg_buffer:
+ "'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a:b'"
+ quotearg:
+ "'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a:b'"
+ quotearg_colon:
+ "'simple'", "'\\0 \\t\\n\\'\"\\033??/\\\\'", "'a\\:b'"
+
+ left = "(" and right = ")"
+ quotearg_buffer:
+ "(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a:b)"
+ quotearg:
+ "(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a:b)"
+ quotearg_colon:
+ "(simple)", "(\\0 \\t\\n'\"\\033??/\\\\)", "(a\\:b)"
+
+ left = ":" and right = " "
+ quotearg_buffer:
+ ":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a:b "
+ quotearg:
+ ":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a:b "
+ quotearg_colon:
+ ":simple ", ":\\0\\ \\t\\n'\"\\033??/\\\\ ", ":a\\:b "
+ */
+ custom_quoting_style
};
/* Flags for use in set_quoting_flags. */
@@ -219,6 +249,17 @@ int set_char_quoting (struct quoting_options *o, char c,
int i);
behavior. Return the old value. */
int set_quoting_flags (struct quoting_options *o, int i);
+/* In O (or in the default if O is null),
+ set the value of the quoting style to custom_quoting_style,
+ set the left quote to L, and set the right quote to R.
+ Each of L and R must be null-terminated and can be the empty
+ string. Because backslashes are used for escaping, it does not make
+ sense for R to contain a backslash. R must not begin with a digit or
+ a letter that has special meaning after a backslash (for example,
+ "\t" for tab). */
+void set_custom_quoting (struct quoting_options *o,
+ char const *l, char const *r);
+
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
argument ARG (of size ARGSIZE), using O to control quoting.
If O is null, use the default.
@@ -299,6 +340,24 @@ char *quotearg_colon (char const *arg);
/* Like quotearg_colon (ARG), except it can quote null bytes. */
char *quotearg_colon_mem (char const *arg, size_t argsize);
+/* Like quotearg_n_style (N, S, ARG) but with S as custom_quoting_style
+ with left quote as L and right quote as R. See set_custom_quoting
+ for a description of acceptable L and R values. */
+char *quotearg_n_custom (int n, char const *l, char const *r,
+ char const *arg);
+
+/* Like quotearg_n_custom (N, L, R, ARG) except it can quote null
+ bytes. */
+char *quotearg_n_custom_mem (int n, char const *l, char const *r,
+ char const *arg, size_t argsize);
+
+/* Equivalent to quotearg_n_custom (0, L, R, ARG). */
+char *quotearg_custom (char const *l, char const *r, char const *arg);
+
+/* Equivalent to quotearg_n_custom_mem (0, L, R, ARG, ARGSIZE). */
+char *quotearg_custom_mem (char const *l, char const *r,
+ char const *arg, size_t argsize);
+
/* Free any dynamically allocated memory. */
void quotearg_free (void);
diff --git a/tests/test-quotearg.c b/tests/test-quotearg.c
index 2e2c56b..5a680d9 100644
--- a/tests/test-quotearg.c
+++ b/tests/test-quotearg.c
@@ -199,6 +199,83 @@ static struct result_groups locale_results[] = {
#endif /* ENABLE_NLS */
+static char const *custom_quotes[][2] = {
+ { "", "" },
+ { "'", "'" },
+ { "(", ")" },
+ { ":", " " },
+ { " ", ":" },
+ { "# ", "\n\n" }
+};
+
+static struct result_groups custom_results[] = {
+ /* left = right = "" */
+ { { "", "\\0001\\0", 7, "simple",
+ " \\t\\n'\"\\033?""?/\\\\", "a:b", "a\\\\b",
+ LQ_ENC RQ_ENC },
+ { "", "\\0001\\0", 7, "simple",
+ " \\t\\n'\"\\033?""?/\\\\", "a:b", "a\\\\b",
+ LQ_ENC RQ_ENC },
+ { "", "\\0001\\0", 7, "simple",
+ " \\t\\n'\"\\033?""?/\\\\", "a\\:b", "a\\\\b",
+ LQ_ENC RQ_ENC } },
+
+ /* left = right = "'" */
+ { { "''", "'\\0001\\0'", 9, "'simple'",
+ "' \\t\\n\\'\"\\033?""?/\\\\'", "'a:b'", "'a\\\\b'",
+ "'" LQ_ENC RQ_ENC "'" },
+ { "''", "'\\0001\\0'", 9, "'simple'",
+ "' \\t\\n\\'\"\\033?""?/\\\\'", "'a:b'", "'a\\\\b'",
+ "'" LQ_ENC RQ_ENC "'" },
+ { "''", "'\\0001\\0'", 9, "'simple'",
+ "' \\t\\n\\'\"\\033?""?/\\\\'", "'a\\:b'", "'a\\\\b'",
+ "'" LQ_ENC RQ_ENC "'" } },
+
+ /* left = "(" and right = ")" */
+ { { "()", "(\\0001\\0)", 9, "(simple)",
+ "( \\t\\n'\"\\033?""?/\\\\)", "(a:b)", "(a\\\\b)",
+ "(" LQ_ENC RQ_ENC ")" },
+ { "()", "(\\0001\\0)", 9, "(simple)",
+ "( \\t\\n'\"\\033?""?/\\\\)", "(a:b)", "(a\\\\b)",
+ "(" LQ_ENC RQ_ENC ")" },
+ { "()", "(\\0001\\0)", 9, "(simple)",
+ "( \\t\\n'\"\\033?""?/\\\\)", "(a\\:b)", "(a\\\\b)",
+ "(" LQ_ENC RQ_ENC ")" } },
+
+ /* left = ":" and right = " " */
+ { { ": ", ":\\0001\\0 ", 9, ":simple ",
+ ":\\ \\t\\n'\"\\033?""?/\\\\ ", ":a:b ", ":a\\\\b ",
+ ":" LQ_ENC RQ_ENC " " },
+ { ": ", ":\\0001\\0 ", 9, ":simple ",
+ ":\\ \\t\\n'\"\\033?""?/\\\\ ", ":a:b ", ":a\\\\b ",
+ ":" LQ_ENC RQ_ENC " " },
+ { ": ", ":\\0001\\0 ", 9, ":simple ",
+ ":\\ \\t\\n'\"\\033?""?/\\\\ ", ":a\\:b ", ":a\\\\b ",
+ ":" LQ_ENC RQ_ENC " " } },
+
+ /* left = " " and right = ":" */
+ { { " :", " \\0001\\0:", 9, " simple:",
+ " \\t\\n'\"\\033?""?/\\\\:", " a\\:b:", " a\\\\b:",
+ " " LQ_ENC RQ_ENC ":" },
+ { " :", " \\0001\\0:", 9, " simple:",
+ " \\t\\n'\"\\033?""?/\\\\:", " a\\:b:", " a\\\\b:",
+ " " LQ_ENC RQ_ENC ":" },
+ { " :", " \\0001\\0:", 9, " simple:",
+ " \\t\\n'\"\\033?""?/\\\\:", " a\\:b:", " a\\\\b:",
+ " " LQ_ENC RQ_ENC ":" } },
+
+ /* left = "# " and right = "\n\n" */
+ { { "# \n\n", "# \\0001\\0\n\n", 11, "# simple\n\n",
+ "# \\t\\n'\"\\033?""?/\\\\\n\n", "# a:b\n\n", "# a\\\\b\n\n",
+ "# " LQ_ENC RQ_ENC "\n\n" },
+ { "# \n\n", "# \\0001\\0\n\n", 11, "# simple\n\n",
+ "# \\t\\n'\"\\033?""?/\\\\\n\n", "# a:b\n\n", "# a\\\\b\n\n",
+ "# " LQ_ENC RQ_ENC "\n\n" },
+ { "# \n\n", "# \\0001\\0\n\n", 11, "# simple\n\n",
+ "# \\t\\n'\"\\033?""?/\\\\\n\n", "# a\\:b\n\n", "# a\\\\b\n\n",
+ "# " LQ_ENC RQ_ENC "\n\n" } }
+};
+
static void
compare (char const *a, size_t la, char const *b, size_t lb)
{
@@ -324,6 +401,15 @@ main (int argc, char *argv[])
ASSERT (set_quoting_flags (NULL, 0) == QA_SPLIT_TRIGRAPHS);
+ for (i = 0; i < sizeof custom_quotes / sizeof *custom_quotes; ++i)
+ {
+ set_custom_quoting (NULL,
+ custom_quotes[i][0], custom_quotes[i][1]);
+ compare_strings (use_quotearg_buffer, &custom_results[i].group1);
+ compare_strings (use_quotearg, &custom_results[i].group2);
+ compare_strings (use_quotearg_colon, &custom_results[i].group3);
+ }
+
#if ENABLE_NLS
/* Clean up environment. */
unsetenv ("LANGUAGE");
--
1.5.4.3
>From f4414fcbb869bda06d8c66d95451228cb016e034 Mon Sep 17 00:00:00 2001
From: Joel E. Denny <address@hidden>
Date: Sat, 22 Aug 2009 20:55:17 -0400
Subject: [PATCH] quotearg: document limitations of quote_these_too
* lib/quotearg.c (quotearg_buffer_restyled): Add comments where
those limitations are created.
* lib/quotearg.h (set_char_quoting): Document that digits and
letters that are special after backslash are not permitted.
(quotearg_char): Cross-reference set_char_quoting documentation.
---
ChangeLog | 9 +++++++++
lib/quotearg.c | 8 +++++++-
lib/quotearg.h | 7 +++++--
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 255e17e..42b96f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2009-08-22 Joel E. Denny <address@hidden>
+ quotearg: document limitations of quote_these_too
+ * lib/quotearg.c (quotearg_buffer_restyled): Add comments where
+ those limitations are created.
+ * lib/quotearg.h (set_char_quoting): Document that digits and
+ letters that are special after backslash are not permitted.
+ (quotearg_char): Cross-reference set_char_quoting documentation.
+
+2009-08-22 Joel E. Denny <address@hidden>
+
quotearg: implement custom_quoting_style
* lib/quotearg.c: (struct quoting_options): Add left and right
fields to store quotes.
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 9e5f038..0c11a62 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -336,6 +336,10 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
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;
@@ -461,7 +465,9 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
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. */
+ 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:
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 6704b32..0701d73 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -240,7 +240,9 @@ void set_quoting_style (struct quoting_options *o, enum
quoting_style s);
set the value of the quoting options for character C to I.
Return the old value. Currently, the only values defined for I are
0 (the default) and 1 (which means to quote the character even if
- it would not otherwise be quoted). */
+ it would not otherwise be quoted). C must never be a digit or a
+ letter that has special meaning after a backslash (for example, "\t"
+ for tab). */
int set_char_quoting (struct quoting_options *o, char c, int i);
/* In O (or in the default if O is null),
@@ -328,7 +330,8 @@ char *quotearg_style (enum quoting_style s, char const
*arg);
char *quotearg_style_mem (enum quoting_style s,
char const *arg, size_t argsize);
-/* Like quotearg (ARG), except also quote any instances of CH. */
+/* Like quotearg (ARG), except also quote any instances of CH.
+ See set_char_quoting for a description of acceptable CH values. */
char *quotearg_char (char const *arg, char ch);
/* Like quotearg_char (ARG, CH), except it can quote null bytes. */
--
1.5.4.3
- quotearg: implement custom_quoting_style,
Joel E. Denny <=
- Re: quotearg: implement custom_quoting_style, Bruno Haible, 2009/08/23
- Re: quotearg: implement custom_quoting_style, Joel E. Denny, 2009/08/23
- Re: quotearg: implement custom_quoting_style, Joel E. Denny, 2009/08/23
- Re: quotearg: implement custom_quoting_style, Bruno Haible, 2009/08/23
- Re: quotearg: implement custom_quoting_style, Joel E. Denny, 2009/08/23
- Re: quotearg: implement custom_quoting_style, Bruno Haible, 2009/08/23
- Re: quotearg: implement custom_quoting_style, Joel E. Denny, 2009/08/23