bug-gnulib
[Top][All Lists]
Advanced

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

quotearg improvements [was: filenames in error messages]


From: Eric Blake
Subject: quotearg improvements [was: filenames in error messages]
Date: Tue, 12 Feb 2008 20:31:46 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071031 Thunderbird/2.0.0.9 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 2/7/2008 5:22 PM:
|
| 2008-02-07  Eric Blake  <address@hidden>
|
|       Quotearg part 3: add flag to control outer quote elision.
|       * lib/quotearg.h (c_maybe_quoting_style): New style.
|       (enum quoting_flags): Better documentation of flags.
|       * lib/quotearg.c (quoting_style_args, quoting_style_vals): Add
|       c-maybe style.
|       (quotearg_buffer_restyled): Handle new flag to elide outer
|       quotes.
|
|       Quotearg part 2: add flag that can control NUL elision.
|       * lib/quotearg.h (set_quoting_flags): New prototype.
|       * lib/quotearg.c (struct quoting_options): Add flag field.
|       (set_quoting_flags): New function.
|       (quotearg_buffer_restyled): Add flags parameter.
|       (quotearg_alloc_mem): Set the flag if length cannot be returned.
|       (quotearg_n_options): Set the flag, since length cannot be
|       returned.
|       (quoting_options_from_style): Default flags correctly.
|
|       Quotearg part 1: more wrappers, restore quotearg_char state.
|       * lib/quotearg.h (quotearg_alloc_mem, quotearg_n_mem)
|       (quotearg_mem, quotearg_style_mem, quotearg_char_mem)
|       (quotearg_colon_mem): New wrappers.
|       * lib/quotearg.c (quotearg_alloc, quotearg_char): Rewrite...
|       (quotearg_alloc_mem, quotearg_char_mem): ...in terms of these new
|       functions.
|       (quotearg_n_mem, quotearg_mem, quotearg_style_mem)
|       (quotearg_colon_mem): New functions.
|

I'm committing these three patches as is, plus a fourth.  This patch adds
a test, to help avoid regressions (I was surprised that coreutils didn't
appear to test variations on ls --quoting-style, other than a couple of
uses of an explicit --quoting-style=literal).  It also fixes some corner
cases I noticed during the patch.  I decided that when the default style
is my new "c-maybe", that quotearg_colon("a:b") should result in "\"a:b\""
("a:b") rather than "\"a\\:b\"" ("a\:b") (ie. keep the displayed output as
a valid C string literal, since \: is not a valid C escape).  In a similar
vein, for trigraphs, the "c" quoting style now outputs "\"?\"\"?/\""
("?""?/") rather than "\"?\\?/\"" ("?\?/"), since \? is not a valid C
escape; this assumes that C string concatenation is acceptable in that
style (note that the "locale" and "clocale" styles do not look for trigraphs).

The upshot of this patch is that you should be able to do:

#include "quotearg.h"
...
set_quoting_style (NULL, c_maybe_quoting_style);
quotearg_colon (string);

and get reasonable output for file names in error messages, when matching
the recommendations of this thread for the GNU Coding Standards to include
"" quoting only around otherwise-ambiguous or difficult strings.

I had fun designing the testsuite - by providing a stub gettext when the
library is compiled with NLS support, I managed to get the testsuite to
test translated quote characters as if in a non-C locale, but without
using setlocale.  I also had to relearn the fact that isprint('\377')
returns different results for the C locale on different systems, so I
settled for \033 (ESC) as a hopefully better choice of a non-printable
character in the testsuite.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHsmSi84KuGfSFAYARAn8bAKCXbSqwY1muwvAPRF8+BYHAdyqxIwCfV/d9
6LVLHH/6w1DVMrigZ88ysKQ=
=zJNi
-----END PGP SIGNATURE-----
>From 05230b809c6fec84e0505ef1240f37b9d5b40356 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Tue, 12 Feb 2008 11:42:29 -0700
Subject: [PATCH] Quotearg part 4: add tests, fix c-maybe colon quoting.

* lib/quotearg.h: Improve documentation.
* lib/quotearg.c (quotearg_buffer_restyled): Don't add extra
escapes when adding outer quotes.  When quoting trigraphs, use
valid C notation.  When quoting NUL, omit extra characters if next
character is not digit.  Alter prototype.
(quotearg_buffer, quotearg_alloc_mem, quotearg_n_options): Adjust
callers.
* modules/quotearg-tests: New module.
* tests/test-quotearg.c: New test.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog              |   13 +++
 lib/quotearg.c         |   65 +++++++-----
 lib/quotearg.h         |  113 ++++++++++++++++++--
 modules/quotearg-tests |   12 ++
 tests/test-quotearg.c  |  272 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 438 insertions(+), 37 deletions(-)
 create mode 100644 modules/quotearg-tests
 create mode 100644 tests/test-quotearg.c

diff --git a/ChangeLog b/ChangeLog
index 2da0617..ebf9e91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-02-12  Eric Blake  <address@hidden>
+
+       Quotearg part 4: add tests, fix c-maybe colon quoting.
+       * lib/quotearg.h: Improve documentation.
+       * lib/quotearg.c (quotearg_buffer_restyled): Don't add extra
+       escapes when adding outer quotes.  When quoting trigraphs, use
+       valid C notation.  When quoting NUL, omit extra characters if next
+       character is not digit.  Alter prototype.
+       (quotearg_buffer, quotearg_alloc_mem, quotearg_n_options): Adjust
+       callers.
+       * modules/quotearg-tests: New module.
+       * tests/test-quotearg.c: New test.
+
 2008-02-07  Eric Blake  <address@hidden>
 
        Quotearg part 3: add flag to control outer quote elision.
diff --git a/lib/quotearg.c b/lib/quotearg.c
index b6237b0..c2de86f 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -163,6 +163,17 @@ set_quoting_flags (struct quoting_options *o, int 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 *
@@ -175,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, 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
@@ -184,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 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 *quote_these_too)
 {
   size_t i;
   size_t len = 0;
@@ -306,8 +317,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
              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)
@@ -336,7 +350,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
                    c = arg[i + 2];
                    i += 2;
                    STORE ('?');
-                   STORE ('\\');
+                   STORE ('"');
+                   STORE ('"');
                    STORE ('?');
                    break;
 
@@ -529,8 +544,9 @@ 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:
@@ -542,7 +558,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
       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;
 
@@ -555,9 +571,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
   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);
 }
 
 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
@@ -577,7 +595,7 @@ 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);
+                                      p->style, p->flags, p->quote_these_too);
   errno = e;
   return r;
 }
@@ -605,9 +623,10 @@ 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) + 1;
+                                            flags, p->quote_these_too) + 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);
   errno = e;
   if (size)
     *size = bufsize - 1;
@@ -695,7 +714,8 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
     /* 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);
 
     if (size <= qsize)
       {
@@ -704,7 +724,7 @@ 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);
+                                 flags, options->quote_these_too);
       }
 
     errno = e;
@@ -736,17 +756,6 @@ quotearg_mem (char const *arg, size_t argsize)
   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)
 {
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 5d3ca47..9f81771 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -23,46 +23,141 @@
 
 # include <stddef.h>
 
-/* Basic quoting styles.  */
+/* Basic quoting styles.  For each style, an example is given on the
+   input strings "simple", "\0 \t\n'\"\033?""?/\\", and "a:b", using
+   quotearg_buffer, quotearg_mem, and quotearg_colon_mem with that
+   style and the default flags and quoted characters.  Note that the
+   examples are shown here as valid C strings rather than what
+   displays on a terminal (with "??/" as a trigraph for "\\").  */
 enum quoting_style
   {
     /* Output names as-is (ls --quoting-style=literal).  Can result in
        embedded null bytes if QA_ELIDE_NULL_BYTES is not in
-       effect.  */
+       effect.
+
+       quotearg_buffer:
+       "simple", "\0 \t\n'\"\033??/\\", "a:b"
+       quotearg:
+       "simple", " \t\n'\"\033??/\\", "a:b"
+       quotearg_colon:
+       "simple", " \t\n'\"\033??/\\", "a:b"
+    */
     literal_quoting_style,
 
     /* Quote names for the shell if they contain shell metacharacters
        or would cause ambiguous output (ls --quoting-style=shell).
        Can result in embedded null bytes if QA_ELIDE_NULL_BYTES is not
-       in effect.  */
+       in effect.
+
+       quotearg_buffer:
+       "simple", "'\0 \t\n'\\''\"\033??/\\'", "a:b"
+       quotearg:
+       "simple", "' \t\n'\\''\"\033??/\\'", "a:b"
+       quotearg_colon:
+       "simple", "' \t\n'\\''\"\033??/\\'", "'a:b'"
+    */
     shell_quoting_style,
 
     /* Quote names for the shell, even if they would normally not
        require quoting (ls --quoting-style=shell-always).  Can result
        in embedded null bytes if QA_ELIDE_NULL_BYTES is not in effect.
        Behaves like shell_quoting_style if QA_ELIDE_OUTER_QUOTES is in
-       effect.  */
+       effect.
+
+       quotearg_buffer:
+       "'simple'", "'\0 \t\n'\\''\"\033??/\\'", "'a:b'"
+       quotearg:
+       "'simple'", "' \t\n'\\''\"\033??/\\'", "'a:b'"
+       quotearg_colon:
+       "'simple'", "' \t\n'\\''\"\033??/\\'", "'a:b'"
+    */
     shell_always_quoting_style,
 
     /* Quote names as for a C language string (ls --quoting-style=c).
        Behaves like c_maybe_quoting_style if QA_ELIDE_OUTER_QUOTES is
-       in effect.  */
+       in effect.
+
+       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\""
+    */
     c_quoting_style,
 
     /* Like c_quoting_style except omit the surrounding double-quote
-       characters if no quoted characters are encountered.  */
+       characters if no quoted characters are encountered.
+
+       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\""
+    */
     c_maybe_quoting_style,
 
     /* Like c_quoting_style except always omit the surrounding
-       double-quote characters (ls --quoting-style=escape).  */
+       double-quote characters and don't worry about trigraphs (ls
+       --quoting-style=escape).
+
+       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"
+    */
     escape_quoting_style,
 
     /* Like clocale_quoting_style, but quote `like this' instead of
-       "like this" in the default C locale (ls --quoting-style=locale).  */
+       "like this" in the default C locale (ls --quoting-style=locale).
+
+       LC_MESSAGES=C
+       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'"
+
+       LC_MESSAGES=pt_PT.utf8
+       quotearg_buffer:
+       "\302\253simple\302\273",
+       "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
+       quotearg:
+       "\302\253simple\302\273",
+       "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
+       quotearg_colon:
+       "\302\253simple\302\273",
+       "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273"
+    */
     locale_quoting_style,
 
     /* Like c_quoting_style except use quotation marks appropriate for
-       the locale (ls --quoting-style=clocale).  */
+       the locale and don't worry about trigraphs (ls
+       --quoting-style=clocale).
+
+       LC_MESSAGES=C
+       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\""
+
+       LC_MESSAGES=pt_PT.utf8
+       quotearg_buffer:
+       "\302\253simple\302\273",
+       "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
+       quotearg:
+       "\302\253simple\302\273",
+       "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a:b\302\273"
+       quotearg_colon:
+       "\302\253simple\302\273",
+       "\302\253\\0 \\t\\n'\"\\033??/\\\\\302\253", "\302\253a\\:b\302\273"
+    */
     clocale_quoting_style
   };
 
diff --git a/modules/quotearg-tests b/modules/quotearg-tests
new file mode 100644
index 0000000..724d540
--- /dev/null
+++ b/modules/quotearg-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-quotearg.c
+
+Depends-on:
+progname
+stdint
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-quotearg
+check_PROGRAMS += test-quotearg
diff --git a/tests/test-quotearg.c b/tests/test-quotearg.c
new file mode 100644
index 0000000..86ffd7c
--- /dev/null
+++ b/tests/test-quotearg.c
@@ -0,0 +1,272 @@
+/* Test of quotearg family of functions.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   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 3, 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
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.  */
+
+/* Written by Eric Blake <address@hidden>, 2008.  */
+
+#include <config.h>
+
+#include "quotearg.h"
+
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if ENABLE_NLS
+# include <libintl.h>
+
+/* These quotes are borrowed from a pt_PT.utf8 translation.  */
+# define LQ "\302\253"
+# define RQ "\302\273"
+#endif
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+       {                                                                    \
+         fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+         abort ();                                                          \
+       }                                                                    \
+    }                                                                       \
+  while (0)
+
+struct result_strings {
+  char const *str1; /* Translation of "".  */
+  char const *str2; /* Translation of "\0""1\0".  */
+  size_t len2; /* Length of str2.  */
+  char const *str3; /* Translation of "simple".  */
+  char const *str4; /* Translation of " \t\n'\"\033?""?/\\".  */
+  char const *str5; /* Translation of "a:b".  */
+};
+
+struct result_groups {
+  struct result_strings group1; /* Via quotearg_buffer.  */
+  struct result_strings group2; /* Via quotearg{,_mem}.  */
+  struct result_strings group3; /* Via quotearg_colon{,_mem}.  */
+};
+
+static struct result_strings inputs = {
+  "", "\0001\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b"
+};
+
+static struct result_groups results[] = {
+  /* literal_quoting_style */
+  { { "", "\0""1\0", 3, "simple", " \t\n'\"\033?""?/\\", "a:b" },
+    { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b" },
+    { "", "1", 1, "simple", " \t\n'\"\033?""?/\\", "a:b" } },
+
+  /* shell_quoting_style */
+  { { "''", "\0""1\0", 3, "simple", "' \t\n'\\''\"\033?""?/\\'", "a:b" },
+    { "''", "1", 1, "simple", "' \t\n'\\''\"\033?""?/\\'", "a:b" },
+    { "''", "1", 1, "simple", "' \t\n'\\''\"\033?""?/\\'", "'a:b'" } },
+
+  /* shell_always_quoting_style */
+  { { "''", "'\0""1\0'", 5, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'" },
+    { "''", "'1'", 3, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'" },
+    { "''", "'1'", 3, "'simple'", "' \t\n'\\''\"\033?""?/\\'", "'a:b'" } },
+
+  /* c_quoting_style */
+  { { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
+      "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"" },
+    { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
+      "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a:b\"" },
+    { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
+      "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"", "\"a\\:b\"" } },
+
+  /* c_maybe_quoting_style */
+  { { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"",
+      "a:b" },
+    { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"",
+      "a:b" },
+    { "", "\"\\0001\\0\"", 9, "simple", "\" \\t\\n'\\\"\\033?\"\"?/\\\\\"",
+      "\"a:b\"" } },
+
+  /* escape_quoting_style */
+  { { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a:b" },
+    { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a:b" },
+    { "", "\\0001\\0", 7, "simple", " \\t\\n'\"\\033?""?/\\\\", "a\\:b" } },
+
+  /* locale_quoting_style */
+  { { "`'", "`\\0001\\0'", 9, "`simple'", "` \\t\\n\\'\"\\033?""?/\\\\'",
+      "`a:b'" },
+    { "`'", "`\\0001\\0'", 9, "`simple'", "` \\t\\n\\'\"\\033?""?/\\\\'",
+      "`a:b'" },
+    { "`'", "`\\0001\\0'", 9, "`simple'", "` \\t\\n\\'\"\\033?""?/\\\\'",
+      "`a\\:b'" } },
+
+  /* clocale_quoting_style */
+  { { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
+      "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"" },
+    { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
+      "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a:b\"" },
+    { "\"\"", "\"\\0001\\0\"", 9, "\"simple\"",
+      "\" \\t\\n'\\\"\\033?""?/\\\\\"", "\"a\\:b\"" } }
+};
+
+#if ENABLE_NLS
+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 RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
+      LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ },
+    { LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
+      LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a\\:b" RQ } },
+
+  /* clocale_quoting_style */
+  { { LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
+      LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ },
+    { LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
+      LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a:b" RQ },
+    { LQ RQ, LQ "\\0001\\0" RQ, 11, LQ "simple" RQ,
+      LQ " \\t\\n'\"\\033?""?/\\\\" RQ, LQ "a\\:b" RQ } }
+};
+#endif /* ENABLE_NLS */
+
+static void
+compare (char const *a, size_t la, char const *b, size_t lb)
+{
+  ASSERT (la == lb);
+  ASSERT (memcmp (a, b, la) == 0);
+  ASSERT (b[lb] == '\0');
+}
+
+static void
+compare_strings (char *(func) (char const *, size_t *),
+                struct result_strings *results)
+{
+  size_t len;
+  char *p;
+
+  len = 0;
+  p = func (inputs.str1, &len);
+  compare (results->str1, strlen (results->str1), p, len);
+
+  len = inputs.len2;
+  p = func (inputs.str2, &len);
+  compare (results->str2, results->len2, p, len);
+
+  len = SIZE_MAX;
+  p = func (inputs.str3, &len);
+  compare (results->str3, strlen (results->str3), p, len);
+
+  len = strlen (inputs.str4);
+  p = func (inputs.str4, &len);
+  compare (results->str4, strlen (results->str4), p, len);
+
+  len = SIZE_MAX;
+  p = func (inputs.str5, &len);
+  compare (results->str5, strlen (results->str5), p, len);
+}
+
+static char *
+use_quotearg_buffer (const char *str, size_t *len)
+{
+  static char buf[100];
+  size_t size;
+  memset (buf, 0xa5, 100);
+  size = quotearg_buffer (buf, 100, str, *len, NULL);
+  *len = size;
+  ASSERT ((unsigned char) buf[size + 1] == 0xa5);
+  return buf;
+}
+
+static char *
+use_quotearg (const char *str, size_t *len)
+{
+  char *p = *len == SIZE_MAX ? quotearg (str) : quotearg_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)
+            : quotearg_colon_mem (str, *len));
+  *len = strlen (p);
+  return p;
+}
+
+#if ENABLE_NLS
+/* True if the locale should be faked.  */
+static bool fake_locale;
+
+/* A replacement gettext that allows testing of locale quotes without
+   requiring a locale.  */
+char *
+gettext (char const *str)
+{
+  if (fake_locale)
+    {
+      static char lq[] = LQ;
+      static char rq[] = RQ;
+      if (strcmp (str, "`") == 0)
+       return lq;
+      if (strcmp (str, "'") == 0)
+       return rq;
+    }
+  return (char *) str;
+}
+
+char *
+dgettext (char const *d, char const *str)
+{
+  return gettext (str);
+}
+#endif /* ENABLE_NLS */
+
+int
+main (int argc, char **argv)
+{
+  int i;
+
+  /* This program is hard-wired to the C locale since it does not call
+     setlocale.  */
+  ASSERT (!isprint ('\033'));
+  for (i = literal_quoting_style; i <= clocale_quoting_style; i++)
+    {
+      set_quoting_style (NULL, i);
+      compare_strings (use_quotearg_buffer, &results[i].group1);
+      compare_strings (use_quotearg, &results[i].group2);
+      compare_strings (use_quotearg_colon, &results[i].group3);
+    }
+
+#if ENABLE_NLS
+  /* Rather than change locales, and require a .gmo file with
+     translations for "`" and "'" that match our expectations, we
+     merely override the gettext function to satisfy the link
+     dependencies of quotearg.c.  */
+  fake_locale = true;
+
+  set_quoting_style (NULL, locale_quoting_style);
+  compare_strings (use_quotearg_buffer, &locale_results[0].group1);
+  compare_strings (use_quotearg, &locale_results[0].group2);
+  compare_strings (use_quotearg_colon, &locale_results[0].group3);
+
+  set_quoting_style (NULL, clocale_quoting_style);
+  compare_strings (use_quotearg_buffer, &locale_results[1].group1);
+  compare_strings (use_quotearg, &locale_results[1].group2);
+  compare_strings (use_quotearg_colon, &locale_results[1].group3);
+#endif /* ENABLE_NLS */
+
+  quotearg_free ();
+  return 0;
+}
-- 
1.5.4


reply via email to

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