Reuben Thomas wrote:
> quote.h says it contains "prototypes for quote.c", but there is no longer
> such a file, so it should probably mention "quotearg.c" instead.

You are right that there is a problem here: On 2012-03-07 this patch [1]
from Akim did a good thing — it made the quote.h functions' effect more
customizable — and a not so good thing: it combined the implementations
of two modules. However, two separate .c files is more maintainable
than a .c files that combines both (due to the time a programmer needs
in order to understand the file, before being able to make a change).

The observation in [1] was that "quoting_options ... is hidden inside
quotearg.c". So, the fix is to let the 'quotearg' module export all that
the 'quote' module (and similar code in applications) needs.

[1] https://lists.gnu.org/archive/html/bug-gnulib/2012-03/msg00031.html

Here are three proposed patches. Paul and Akim, is this OK?


2020-10-31  Bruno Haible  <br...@clisp.org>

        quote: Don't mix with the implementation of module 'quotearg'.
        * lib/quote.c: New file, extracted from lib/quotearg.c.
        * lib/quotearg.c: Don't include quote.h.
        (quote_quoting_options, quote_n_mem, quote_mem, quote_n, quote): Remove.
        * modules/quote (Files): Add lib/quote.c.
        (Depends-on): Add stdint.
        (Makefile.am): Compile quote.c.
        * modules/quotearg (Files): Remove lib/quote.h.

2020-10-31  Bruno Haible  <br...@clisp.org>

        quotearg: Export quotearg_slot_n_mem.
        * lib/quotearg.h (quotearg_buffer, quotearg_alloc_mem): Write SIZE_MAX
        instead of -1.
        (quotearg_slot_n_mem): New declaration.
        * lib/quotearg.c (quotearg_slot_n_mem): Renamed from quotearg_n_options.
        Use default_quoting_options if the options argument is NULL.

2020-10-31  Bruno Haible  <br...@clisp.org>

        quotearg: Allow static init of 'struct quoting_options' variables.
        * lib/quotearg.h: Include <limits.h>.
        (struct quoting_options): Move to here from lib/quotearg.c. Use
        INT_WIDTH instead of INT_BITS.
        (QUOTING_OPTIONS_INIT): New macro.
        * lib/quotearg.c (INT_BITS): Remove macro. Use INT_WIDTH instead.
        (default_quoting_options, quote_quoting_options): Use
        QUOTING_OPTIONS_INIT.
        * modules/quotearg (Depends-on): Add limits-h.

>From 4d27e85e3db848a844e64a9bc0961ba293c9f09b Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 31 Oct 2020 19:13:23 +0100
Subject: [PATCH 1/3] quotearg: Allow static init of 'struct quoting_options'
 variables.

* lib/quotearg.h: Include <limits.h>.
(struct quoting_options): Move to here from lib/quotearg.c. Use
INT_WIDTH instead of INT_BITS.
(QUOTING_OPTIONS_INIT): New macro.
* lib/quotearg.c (INT_BITS): Remove macro. Use INT_WIDTH instead.
(default_quoting_options, quote_quoting_options): Use
QUOTING_OPTIONS_INIT.
* modules/quotearg (Depends-on): Add limits-h.
---
 ChangeLog        | 12 ++++++++++++
 lib/quotearg.c   | 37 ++++++-------------------------------
 lib/quotearg.h   | 32 +++++++++++++++++++++++++++++++-
 modules/quotearg |  1 +
 4 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8cc39d3..9cc1a43 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2020-10-31  Bruno Haible  <br...@clisp.org>
+
+	quotearg: Allow static init of 'struct quoting_options' variables.
+	* lib/quotearg.h: Include <limits.h>.
+	(struct quoting_options): Move to here from lib/quotearg.c. Use
+	INT_WIDTH instead of INT_BITS.
+	(QUOTING_OPTIONS_INIT): New macro.
+	* lib/quotearg.c (INT_BITS): Remove macro. Use INT_WIDTH instead.
+	(default_quoting_options, quote_quoting_options): Use
+	QUOTING_OPTIONS_INIT.
+	* modules/quotearg (Depends-on): Add limits-h.
+
 2020-10-30  Bernhard Voelker  <m...@bernhard-voelker.de>
 
 	verify tests: avoid -Wmissing-declarations warnings
diff --git a/lib/quotearg.c b/lib/quotearg.c
index b13574d..c742632 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -53,27 +53,6 @@
 # define SIZE_MAX ((size_t) -1)
 #endif
 
-#define INT_BITS (sizeof (int) * CHAR_BIT)
-
-struct quoting_options
-{
-  /* Basic quoting style.  */
-  enum quoting_style style;
-
-  /* Additional flags.  Bitwise combination of enum quoting_flags.  */
-  int flags;
-
-  /* Quote the characters indicated by this bit vector even if the
-     quoting style would not normally require them to be quoted.  */
-  unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
-
-  /* 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.  */
 char const *const quoting_style_args[] =
 {
@@ -106,7 +85,8 @@ enum quoting_style const quoting_style_vals[] =
 };
 
 /* The default quoting options.  */
-static struct quoting_options default_quoting_options;
+static struct quoting_options default_quoting_options =
+  QUOTING_OPTIONS_INIT (literal_quoting_style, 0);
 
 /* Allocate a new set of quoting options, with contents initially identical
    to O if O is not null, or to the default if O is null.
@@ -146,8 +126,8 @@ set_char_quoting (struct quoting_options *o, char c, int i)
 {
   unsigned char uc = c;
   unsigned int *p =
-    (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
-  int shift = uc % INT_BITS;
+    (o ? o : &default_quoting_options)->quote_these_too + uc / INT_WIDTH;
+  int shift = uc % INT_WIDTH;
   int r = (*p >> shift) & 1;
   *p ^= ((i & 1) ^ r) << shift;
   return r;
@@ -705,7 +685,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
       if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
               || elide_outer_quotes)
              && quote_these_too
-             && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
+             && quote_these_too[c / INT_WIDTH] >> (c % INT_WIDTH) & 1)
           && !is_right_quote)
         goto store_c;
 
@@ -1043,12 +1023,7 @@ quotearg_custom_mem (char const *left_quote, char const *right_quote,
 
 /* The quoting option used by the functions of quote.h.  */
 struct quoting_options quote_quoting_options =
-  {
-    locale_quoting_style,
-    0,
-    { 0 },
-    NULL, NULL
-  };
+  QUOTING_OPTIONS_INIT (locale_quoting_style, 0);
 
 char const *
 quote_n_mem (int n, char const *arg, size_t argsize)
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 3bf149b..55fa464 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -21,6 +21,7 @@
 #ifndef QUOTEARG_H_
 # define QUOTEARG_H_ 1
 
+# include <limits.h>
 # include <stddef.h>
 
 /* Basic quoting styles.  For each style, an example is given on the
@@ -267,7 +268,36 @@ enum quoting_flags
 extern char const *const quoting_style_args[];
 extern enum quoting_style const quoting_style_vals[];
 
-struct quoting_options;
+/* Quoting options.
+   The fields of this struct are considered private.  Instead of accessing
+   them directly, use the accessors
+     get_quoting_style, set_quoting_style,
+     set_quoting_flags,
+     set_char_quoting,
+     set_custom_quoting
+   declared below.  */
+struct quoting_options
+{
+  /* Basic quoting style.  */
+  enum quoting_style style;
+
+  /* Additional flags.  Bitwise combination of enum quoting_flags.  */
+  int flags;
+
+  /* Quote the characters indicated by this bit vector even if the
+     quoting style would not normally require them to be quoted.  */
+  unsigned int quote_these_too[(UCHAR_MAX / INT_WIDTH) + 1];
+
+  /* The left quote for custom_quoting_style.  */
+  char const *left_quote;
+
+  /* The right quote for custom_quoting_style.  */
+  char const *right_quote;
+};
+
+/* Initializer for a variable of type 'struct quoting_options'.  */
+#define QUOTING_OPTIONS_INIT(style, flags) \
+  { style, flags, { 0 }, NULL, NULL }
 
 /* The functions listed below set and use a hidden variable
    that contains the default quoting style options.  */
diff --git a/modules/quotearg b/modules/quotearg
index 6f5356d..28b5353 100644
--- a/modules/quotearg
+++ b/modules/quotearg
@@ -14,6 +14,7 @@ attribute
 c-strcaseeq
 extensions
 gettext-h
+limits-h
 mbrtowc
 mbsinit
 memcmp
-- 
2.7.4

>From d51f785bbc797651edc5b696f09a53317d4f7de7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 31 Oct 2020 20:00:41 +0100
Subject: [PATCH 2/3] quotearg: Export quotearg_slot_n_mem.

* lib/quotearg.h (quotearg_buffer, quotearg_alloc_mem): Write SIZE_MAX
instead of -1.
(quotearg_slot_n_mem): New declaration.
* lib/quotearg.c (quotearg_slot_n_mem): Renamed from quotearg_n_options.
Use default_quoting_options if the options argument is NULL.
---
 ChangeLog      |  9 +++++++++
 lib/quotearg.c | 33 ++++++++++++++-------------------
 lib/quotearg.h | 21 ++++++++++++++++-----
 3 files changed, 39 insertions(+), 24 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9cc1a43..e7ecf39 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2020-10-31  Bruno Haible  <br...@clisp.org>
 
+	quotearg: Export quotearg_slot_n_mem.
+	* lib/quotearg.h (quotearg_buffer, quotearg_alloc_mem): Write SIZE_MAX
+	instead of -1.
+	(quotearg_slot_n_mem): New declaration.
+	* lib/quotearg.c (quotearg_slot_n_mem): Renamed from quotearg_n_options.
+	Use default_quoting_options if the options argument is NULL.
+
+2020-10-31  Bruno Haible  <br...@clisp.org>
+
 	quotearg: Allow static init of 'struct quoting_options' variables.
 	* lib/quotearg.h: Include <limits.h>.
 	(struct quoting_options): Move to here from lib/quotearg.c. Use
diff --git a/lib/quotearg.c b/lib/quotearg.c
index c742632..2954b12 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -838,17 +838,9 @@ quotearg_free (void)
   nslots = 1;
 }
 
-/* Use storage slot N to return a quoted version of argument ARG.
-   ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
-   null-terminated string.
-   OPTIONS specifies the quoting options.
-   The returned value points to static storage that can be
-   reused by the next call to this function with the same value of N.
-   N must be nonnegative.  N is deliberately declared with type "int"
-   to allow for future extensions (using negative values).  */
-static char *
-quotearg_n_options (int n, char const *arg, size_t argsize,
-                    struct quoting_options const *options)
+char *
+quotearg_slot_n_mem (int n, char const *arg, size_t argsize,
+                     struct quoting_options const *options)
 {
   int e = errno;
 
@@ -872,6 +864,9 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
       nslots = n + 1;
     }
 
+  if (options == NULL)
+    options = &default_quoting_options;
+
   {
     size_t size = sv[n].size;
     char *val = sv[n].val;
@@ -903,13 +898,13 @@ quotearg_n_options (int n, char const *arg, size_t argsize,
 char *
 quotearg_n (int n, char const *arg)
 {
-  return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
+  return quotearg_slot_n_mem (n, arg, SIZE_MAX, &default_quoting_options);
 }
 
 char *
 quotearg_n_mem (int n, char const *arg, size_t argsize)
 {
-  return quotearg_n_options (n, arg, argsize, &default_quoting_options);
+  return quotearg_slot_n_mem (n, arg, argsize, &default_quoting_options);
 }
 
 char *
@@ -928,7 +923,7 @@ char *
 quotearg_n_style (int n, enum quoting_style s, char const *arg)
 {
   struct quoting_options const o = quoting_options_from_style (s);
-  return quotearg_n_options (n, arg, SIZE_MAX, &o);
+  return quotearg_slot_n_mem (n, arg, SIZE_MAX, &o);
 }
 
 char *
@@ -936,7 +931,7 @@ quotearg_n_style_mem (int n, enum quoting_style s,
                       char const *arg, size_t argsize)
 {
   struct quoting_options const o = quoting_options_from_style (s);
-  return quotearg_n_options (n, arg, argsize, &o);
+  return quotearg_slot_n_mem (n, arg, argsize, &o);
 }
 
 char *
@@ -957,7 +952,7 @@ quotearg_char_mem (char const *arg, size_t argsize, char ch)
   struct quoting_options options;
   options = default_quoting_options;
   set_char_quoting (&options, ch, 1);
-  return quotearg_n_options (0, arg, argsize, &options);
+  return quotearg_slot_n_mem (0, arg, argsize, &options);
 }
 
 char *
@@ -984,7 +979,7 @@ quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
   struct quoting_options options;
   options = quoting_options_from_style (s);
   set_char_quoting (&options, ':', 1);
-  return quotearg_n_options (n, arg, SIZE_MAX, &options);
+  return quotearg_slot_n_mem (n, arg, SIZE_MAX, &options);
 }
 
 char *
@@ -1002,7 +997,7 @@ quotearg_n_custom_mem (int n, char const *left_quote,
 {
   struct quoting_options o = default_quoting_options;
   set_custom_quoting (&o, left_quote, right_quote);
-  return quotearg_n_options (n, arg, argsize, &o);
+  return quotearg_slot_n_mem (n, arg, argsize, &o);
 }
 
 char *
@@ -1028,7 +1023,7 @@ struct quoting_options quote_quoting_options =
 char const *
 quote_n_mem (int n, char const *arg, size_t argsize)
 {
-  return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
+  return quotearg_slot_n_mem (n, arg, argsize, &quote_quoting_options);
 }
 
 char const *
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 55fa464..d601b80 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -349,10 +349,10 @@ void set_custom_quoting (struct quoting_options *o,
    size of the output, not counting the terminating null.
    If BUFFERSIZE is too small to store the output string, return the
    value that would have been returned had BUFFERSIZE been large enough.
-   If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
-   On output, BUFFER might contain embedded null bytes if ARGSIZE was
-   not -1, the style of O does not use backslash escapes, and the
-   flags of O do not request elision of null bytes.*/
+   If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
+   On output, BUFFER might contain embedded null bytes if ARGSIZE was not
+   SIZE_MAX, the style of O does not use backslash escapes, and the flags
+   of O do not request elision of null bytes.*/
 size_t quotearg_buffer (char *restrict buffer, size_t buffersize,
                         char const *arg, size_t argsize,
                         struct quoting_options const *o);
@@ -366,12 +366,23 @@ char *quotearg_alloc (char const *arg, size_t argsize,
 /* Like quotearg_alloc, except that the length of the result,
    excluding the terminating null byte, is stored into SIZE if it is
    non-NULL.  The result might contain embedded null bytes if ARGSIZE
-   was not -1, SIZE was not NULL, the style of O does not use
+   was not SIZE_MAX, SIZE was not NULL, the style of O does not use
    backslash escapes, and the flags of O do not request elision of
    null bytes.*/
 char *quotearg_alloc_mem (char const *arg, size_t argsize,
                           size_t *size, struct quoting_options const *o);
 
+/* Use storage slot N to return a quoted version of argument ARG.
+   ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
+   null-terminated string.
+   OPTIONS specifies the quoting options.  If null, use the default.
+   The returned value points to static storage that can be
+   reused by the next call to this function with the same value of N.
+   N must be nonnegative.  N is deliberately declared with type "int"
+   to allow for future extensions (using negative values).  */
+char *quotearg_slot_n_mem (int n, char const *arg, size_t argsize,
+                           struct quoting_options const *options);
+
 /* Use storage slot N to return a quoted version of the string ARG.
    Use the default quoting options.
    The returned value points to static storage that can be
-- 
2.7.4

>From 68300c2c7b1f788322c41f897c01b26327a21d41 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 31 Oct 2020 20:39:50 +0100
Subject: [PATCH 3/3] quote: Don't mix with the implementation of module
 'quotearg'.

* lib/quote.c: New file, extracted from lib/quotearg.c.
* lib/quotearg.c: Don't include quote.h.
(quote_quoting_options, quote_n_mem, quote_mem, quote_n, quote): Remove.
* modules/quote (Files): Add lib/quote.c.
(Depends-on): Add stdint.
(Makefile.am): Compile quote.c.
* modules/quotearg (Files): Remove lib/quote.h.
---
 ChangeLog        | 11 +++++++++++
 lib/quote.c      | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/quotearg.c   | 29 -----------------------------
 modules/quote    |  3 +++
 modules/quotearg |  1 -
 5 files changed, 68 insertions(+), 30 deletions(-)
 create mode 100644 lib/quote.c

diff --git a/ChangeLog b/ChangeLog
index e7ecf39..87dff6e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2020-10-31  Bruno Haible  <br...@clisp.org>
 
+	quote: Don't mix with the implementation of module 'quotearg'.
+	* lib/quote.c: New file, extracted from lib/quotearg.c.
+	* lib/quotearg.c: Don't include quote.h.
+	(quote_quoting_options, quote_n_mem, quote_mem, quote_n, quote): Remove.
+	* modules/quote (Files): Add lib/quote.c.
+	(Depends-on): Add stdint.
+	(Makefile.am): Compile quote.c.
+	* modules/quotearg (Files): Remove lib/quote.h.
+
+2020-10-31  Bruno Haible  <br...@clisp.org>
+
 	quotearg: Export quotearg_slot_n_mem.
 	* lib/quotearg.h (quotearg_buffer, quotearg_alloc_mem): Write SIZE_MAX
 	instead of -1.
diff --git a/lib/quote.c b/lib/quote.c
new file mode 100644
index 0000000..dfe4930
--- /dev/null
+++ b/lib/quote.c
@@ -0,0 +1,54 @@
+/* quote.c - quote arguments for output
+
+   Copyright (C) 1998-2020 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 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   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, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Paul Eggert <egg...@twinsun.com> */
+
+#include <config.h>
+
+#include "quote.h"
+
+#include <stdint.h>
+
+#include "quotearg.h"
+
+/* The quoting option used by the functions of quote.h.  */
+struct quoting_options quote_quoting_options =
+  QUOTING_OPTIONS_INIT (locale_quoting_style, 0);
+
+char const *
+quote_n_mem (int n, char const *arg, size_t argsize)
+{
+  return quotearg_slot_n_mem (n, arg, argsize, &quote_quoting_options);
+}
+
+char const *
+quote_mem (char const *arg, size_t argsize)
+{
+  return quote_n_mem (0, arg, argsize);
+}
+
+char const *
+quote_n (int n, char const *arg)
+{
+  return quote_n_mem (n, arg, SIZE_MAX);
+}
+
+char const *
+quote (char const *arg)
+{
+  return quote_n (0, arg);
+}
diff --git a/lib/quotearg.c b/lib/quotearg.c
index 2954b12..674b2b2 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -27,7 +27,6 @@
 #include <config.h>
 
 #include "quotearg.h"
-#include "quote.h"
 
 #include "attribute.h"
 #include "minmax.h"
@@ -1016,34 +1015,6 @@ quotearg_custom_mem (char const *left_quote, char const *right_quote,
 }
 
 
-/* The quoting option used by the functions of quote.h.  */
-struct quoting_options quote_quoting_options =
-  QUOTING_OPTIONS_INIT (locale_quoting_style, 0);
-
-char const *
-quote_n_mem (int n, char const *arg, size_t argsize)
-{
-  return quotearg_slot_n_mem (n, arg, argsize, &quote_quoting_options);
-}
-
-char const *
-quote_mem (char const *arg, size_t argsize)
-{
-  return quote_n_mem (0, arg, argsize);
-}
-
-char const *
-quote_n (int n, char const *arg)
-{
-  return quote_n_mem (n, arg, SIZE_MAX);
-}
-
-char const *
-quote (char const *arg)
-{
-  return quote_n (0, arg);
-}
-
 /*
  * Hey Emacs!
  * Local Variables:
diff --git a/modules/quote b/modules/quote
index 35c30ce..5599b18 100644
--- a/modules/quote
+++ b/modules/quote
@@ -3,15 +3,18 @@ Quote arguments for use in error messages.
 
 Files:
 lib/quote.h
+lib/quote.c
 m4/quote.m4
 
 Depends-on:
 quotearg
+stdint
 
 configure.ac:
 gl_QUOTE
 
 Makefile.am:
+lib_SOURCES += quote.c
 
 Include:
 "quote.h"
diff --git a/modules/quotearg b/modules/quotearg
index 28b5353..8db40f5 100644
--- a/modules/quotearg
+++ b/modules/quotearg
@@ -4,7 +4,6 @@ Quote arguments for use in error messages.
 Files:
 lib/quotearg.h
 lib/quotearg.c
-lib/quote.h
 m4/mbstate_t.m4
 m4/mbrtowc.m4
 m4/quotearg.m4
-- 
2.7.4

Reply via email to