bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: quotearg: implement custom_quoting_style


From: Joel E. Denny
Subject: Re: quotearg: implement custom_quoting_style
Date: Sun, 23 Aug 2009 18:37:43 -0400 (EDT)
User-agent: Alpine 1.00 (DEB 882 2007-12-20)

On Sun, 23 Aug 2009, Bruno Haible wrote:

> > Ok to push the previous 4 patches followed by the one below?
> 
> If you can do that, it would be preferable to merge the 3rd and 5th
> patch together before pushing, because the intermediate states of your
> work are hardly important for the future.

Ok.

> You can't do that any more
> once it's pushed. You know how to do that? If not, here's the recipe:

>   4. "git rebase -i HEAD~3" and in the editor change
>          pick 3
>          pick 4
>          pick 5
>      into
>          pick 3
>          squash 5
>          pick 4
>      (where the numbers 3, 4, 5 are more complicated than that).

Thanks.  I had never used "git rebase -i" before.  At the squash step, it 
let me merge the git log entries but not the ChangeLog entries.  Is there 
a way to do that?

For now, I stuck with what I know:

  git branch tmp
  git reset --hard HEAD^^
  git reset --soft HEAD^
  git cherry-pick -n tmp
  # Merge ChangeLog entries.
  git commit -a
  git cherry-pick tmp^

I pushed the result, shown below.

>From 3293597efd0255a347b8a71890f08f605ef267b4 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 9c9e827..4698367 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-23  Bruno Haible  <address@hidden>
 
        Tests for module 'dup3'.
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 f6fe750d033c40b403688dc3eee9dbff468aa8f3 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 4698367..57f5f32 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 12247f770487cd389e515a51d6bfeb250f26e519 Mon Sep 17 00:00:00 2001
From: Joel E. Denny <address@hidden>
Date: Sun, 23 Aug 2009 18:24:53 -0400
Subject: [PATCH] quotearg: implement custom_quoting_style

* lib/quotearg.c: (struct quoting_options): Add left_quote and
right_quote fields.
(set_custom_quoting): New public function.
(quotearg_buffer_restyled): Add left_quote and right_quote
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): For escape_quoting_style and
clocale_quoting_style, comment that QA_SPLIT_TRIGRAPHS is
ignored even though they're otherwise like c_quoting_style.
Add custom_quoting_style member and document with comparison to
clocale_quoting_style.
* tests/test-quotearg.c (custom_quotes): New array.
(custom_results): New array.
(main): Extend to test custom quoting.
---
 ChangeLog             |   23 ++++++++
 lib/quotearg.c        |  141 ++++++++++++++++++++++++++++++++++++++-----------
 lib/quotearg.h        |   87 +++++++++++++++++++++++++++++-
 tests/test-quotearg.c |   98 ++++++++++++++++++++++++++++++++++
 4 files changed, 314 insertions(+), 35 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 57f5f32..c71b417 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2009-08-23  Joel E. Denny  <address@hidden>
+
+       quotearg: implement custom_quoting_style
+       * lib/quotearg.c: (struct quoting_options): Add left_quote and
+       right_quote fields.
+       (set_custom_quoting): New public function.
+       (quotearg_buffer_restyled): Add left_quote and right_quote
+       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): For escape_quoting_style and
+       clocale_quoting_style, comment that QA_SPLIT_TRIGRAPHS is
+       ignored even though they're otherwise like c_quoting_style.
+       Add custom_quoting_style member and document with comparison to
+       clocale_quoting_style.
+       * 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
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 3f9e628..314c627 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_quote;
+
+  /* The right quote for custom_quoting_style.  */
+  char const *right_quote;
 };
 
 /* 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 *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)
@@ -185,7 +204,9 @@ 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_quote,
+                         char const *right_quote)
 {
   size_t i;
   size_t len = 0;
@@ -225,34 +246,37 @@ 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.
-
-          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;
@@ -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_quote, right_quote);
 }
 
 /* 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_quote, p->right_quote);
   errno = e;
   return r;
 }
@@ -618,10 +655,13 @@ 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_quote,
+                                            p->right_quote) + 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_quote, p->right_quote);
   errno = e;
   if (size)
     *size = bufsize - 1;
@@ -710,7 +750,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_quote,
+                                            options->right_quote);
 
     if (size <= qsize)
       {
@@ -719,7 +761,9 @@ 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_quote,
+                                 options->right_quote);
       }
 
     errno = e;
@@ -804,3 +848,36 @@ quotearg_colon_mem (char const *arg, size_t argsize)
 {
   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);
+}
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 7700107..e9f6f56 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -100,7 +100,8 @@ enum quoting_style
     c_maybe_quoting_style,
 
     /* Like c_quoting_style except always omit the surrounding
-       double-quote characters (ls --quoting-style=escape).
+       double-quote characters and ignore QA_SPLIT_TRIGRAPHS
+       (ls --quoting-style=escape).
 
        quotearg_buffer:
        "simple", "\\0 \\t\\n'\"\\033??/\\\\", "a:b"
@@ -136,7 +137,8 @@ enum quoting_style
     locale_quoting_style,
 
     /* Like c_quoting_style except use quotation marks appropriate for
-       the locale (ls --quoting-style=clocale).
+       the locale and ignore QA_SPLIT_TRIGRAPHS
+       (ls --quoting-style=clocale).
 
        LC_MESSAGES=C
        quotearg_buffer:
@@ -157,7 +159,50 @@ 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 clocale_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_quote = right_quote = "'"
+       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_quote = "(" and right_quote = ")"
+       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_quote = ":" and right_quote = " "
+       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_quote = "\"'" and right_quote = "'\""
+       Notice that this is treated as a single level of quotes or two
+       levels where the outer quote need not be escaped within the inner
+       quotes.  For two levels where the outer quote must be escaped
+       within the inner quotes, you must use separate quotearg
+       invocations.
+       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 +264,19 @@ 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 LEFT_QUOTE, and set the right quote to
+   RIGHT_QUOTE.  Each of LEFT_QUOTE and RIGHT_QUOTE must be
+   null-terminated and can be the empty string.  Because backslashes are
+   used for escaping, it does not make sense for RIGHT_QUOTE to contain
+   a backslash.  RIGHT_QUOTE 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 *left_quote,
+                        char const *right_quote);
+
 /* 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 +357,29 @@ 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 LEFT_QUOTE and right quote as RIGHT_QUOTE.  See
+   set_custom_quoting for a description of acceptable LEFT_QUOTE and
+   RIGHT_QUOTE values.  */
+char *quotearg_n_custom (int n, char const *left_quote,
+                        char const *right_quote, char const *arg);
+
+/* Like quotearg_n_custom (N, LEFT_QUOTE, RIGHT_QUOTE, ARG) except it
+   can quote null bytes.  */
+char *quotearg_n_custom_mem (int n, char const *left_quote,
+                            char const *right_quote,
+                            char const *arg, size_t argsize);
+
+/* Equivalent to quotearg_n_custom (0, LEFT_QUOTE, RIGHT_QUOTE, ARG).  */
+char *quotearg_custom (char const *left_quote, char const *right_quote,
+                      char const *arg);
+
+/* Equivalent to quotearg_n_custom_mem (0, LEFT_QUOTE, RIGHT_QUOTE, ARG,
+                                       ARGSIZE).  */
+char *quotearg_custom_mem (char const *left_quote,
+                          char const *right_quote,
+                          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..65779ad 100644
--- a/tests/test-quotearg.c
+++ b/tests/test-quotearg.c
@@ -199,6 +199,95 @@ static struct result_groups locale_results[] = {
 
 #endif /* ENABLE_NLS */
 
+static char const *custom_quotes[][2] = {
+  { "", ""  },
+  { "'", "'"  },
+  { "(", ")"  },
+  { ":", " "  },
+  { " ", ":"  },
+  { "# ", "\n" },
+  { "\"'", "'\"" }
+};
+
+static struct result_groups custom_results[] = {
+  /* left_quote = right_quote = "" */
+  { { "", "\\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_quote = right_quote = "'" */
+  { { "''", "'\\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_quote = "(" and right_quote = ")" */
+  { { "()", "(\\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_quote = ":" and right_quote = " " */
+  { { ": ", ":\\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_quote = " " and right_quote = ":" */
+  { { " :", " \\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_quote = "# " and right_quote = "\n" */
+  { { "# \n", "# \\0001\\0\n", 10, "# simple\n",
+      "#  \\t\\n'\"\\033?""?/\\\\\n", "# a:b\n", "# a\\\\b\n",
+      "# " LQ_ENC RQ_ENC "\n" },
+    { "# \n", "# \\0001\\0\n", 10, "# simple\n",
+      "#  \\t\\n'\"\\033?""?/\\\\\n", "# a:b\n", "# a\\\\b\n",
+      "# " LQ_ENC RQ_ENC "\n" },
+    { "# \n", "# \\0001\\0\n", 10, "# simple\n",
+      "#  \\t\\n'\"\\033?""?/\\\\\n", "# a\\:b\n", "# a\\\\b\n",
+      "# " LQ_ENC RQ_ENC "\n" } },
+
+  /* left_quote = "\"'" and right_quote = "'\"" */
+  { { "\"''\"", "\"'\\0001\\0'\"", 11, "\"'simple'\"",
+      "\"' \\t\\n\\'\"\\033?""?/\\\\'\"", "\"'a:b'\"", "\"'a\\\\b'\"",
+      "\"'" LQ_ENC RQ_ENC "'\"" },
+    { "\"''\"", "\"'\\0001\\0'\"", 11, "\"'simple'\"",
+      "\"' \\t\\n\\'\"\\033?""?/\\\\'\"", "\"'a:b'\"", "\"'a\\\\b'\"",
+      "\"'" LQ_ENC RQ_ENC "'\"" },
+    { "\"''\"", "\"'\\0001\\0'\"", 11, "\"'simple'\"",
+      "\"' \\t\\n\\'\"\\033?""?/\\\\'\"", "\"'a\\:b'\"", "\"'a\\\\b'\"",
+      "\"'" LQ_ENC RQ_ENC "'\"" } }
+};
+
 static void
 compare (char const *a, size_t la, char const *b, size_t lb)
 {
@@ -324,6 +413,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 98bf7f3d50bbdf7f043938f754c50c7e467933bf 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 c71b417..6fc1016 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+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-23  Joel E. Denny  <address@hidden>
 
        quotearg: implement custom_quoting_style
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 314c627..8380e9d 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 e9f6f56..63c47f1 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -255,7 +255,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),
@@ -345,7 +347,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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]