Tests for module 'unicase/u8-is-uppercase'.
[gnulib.git] / lib / quotearg.c
index b6237b0..339bf34 100644 (file)
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
-#if !HAVE_MBRTOWC
-/* Disable multibyte processing entirely.  Since MB_CUR_MAX is 1, the
-   other macros are defined only for documentation and to satisfy C
-   syntax.  */
-# undef MB_CUR_MAX
-# define MB_CUR_MAX 1
-# undef mbstate_t
-# define mbstate_t int
-# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
-# define iswprint(wc) isprint ((unsigned char) (wc))
-# undef HAVE_MBSINIT
-#endif
-
-#if !defined mbsinit && !HAVE_MBSINIT
-# define mbsinit(ps) 1
-#endif
-
 #ifndef SIZE_MAX
 # define SIZE_MAX ((size_t) -1)
 #endif
 #ifndef SIZE_MAX
 # define SIZE_MAX ((size_t) -1)
 #endif
@@ -163,6 +146,17 @@ set_quoting_flags (struct quoting_options *o, int i)
   return r;
 }
 
   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 *
 /* 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 +169,8 @@ gettext_quote (char const *msgid, enum quoting_style s)
 }
 
 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
 }
 
 /* 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
    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 +178,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,
    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,
 
 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 const *quote_these_too)
 {
   size_t i;
   size_t len = 0;
 {
   size_t i;
   size_t len = 0;
@@ -306,8 +300,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
              if (elide_outer_quotes)
                goto force_outer_quoting_style;
              STORE ('\\');
              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)
              c = '0';
            }
          else if (flags & QA_ELIDE_NULL_BYTES)
@@ -323,7 +320,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
              break;
 
            case c_quoting_style:
              break;
 
            case c_quoting_style:
-             if (i + 2 < argsize && arg[i + 1] == '?')
+             if ((flags & QA_SPLIT_TRIGRAPHS)
+                 && i + 2 < argsize && arg[i + 1] == '?')
                switch (arg[i + 2])
                  {
                  case '!': case '\'':
                switch (arg[i + 2])
                  {
                  case '!': case '\'':
@@ -336,7 +334,8 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
                    c = arg[i + 2];
                    i += 2;
                    STORE ('?');
                    c = arg[i + 2];
                    i += 2;
                    STORE ('?');
-                   STORE ('\\');
+                   STORE ('"');
+                   STORE ('"');
                    STORE ('?');
                    break;
 
                    STORE ('?');
                    break;
 
@@ -357,7 +356,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
        case '\r': esc = 'r'; goto c_and_shell_escape;
        case '\t': esc = 't'; goto c_and_shell_escape;
        case '\v': esc = 'v'; goto c_escape;
        case '\r': esc = 'r'; goto c_and_shell_escape;
        case '\t': esc = 't'; goto c_and_shell_escape;
        case '\v': esc = 'v'; goto c_escape;
-       case '\\': esc = c; goto c_and_shell_escape;
+       case '\\': esc = c;
+         /* No need to escape the escape if we are trying to elide
+            outer quotes and nothing else is problematic.  */
+         if (backslash_escapes && elide_outer_quotes && quote_string_len)
+           goto store_c;
 
        c_and_shell_escape:
          if (quoting_style == shell_always_quoting_style
 
        c_and_shell_escape:
          if (quoting_style == shell_always_quoting_style
@@ -529,8 +532,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:
        goto store_c;
 
     store_escape:
@@ -542,7 +546,7 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
       STORE (c);
     }
 
       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;
 
       && elide_outer_quotes)
     goto force_outer_quoting_style;
 
@@ -555,9 +559,11 @@ quotearg_buffer_restyled (char *buffer, size_t buffersize,
   return len;
 
  force_outer_quoting_style:
   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,
   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
 }
 
 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
@@ -577,7 +583,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,
   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;
 }
   errno = e;
   return r;
 }
@@ -605,9 +611,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,
   /* 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);
   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;
   errno = e;
   if (size)
     *size = bufsize - 1;
@@ -695,7 +702,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,
     /* 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)
       {
 
     if (size <= qsize)
       {
@@ -704,7 +712,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,
          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;
       }
 
     errno = e;
@@ -736,17 +744,6 @@ quotearg_mem (char const *arg, size_t argsize)
   return quotearg_n_mem (0, arg, 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)
 {
 char *
 quotearg_n_style (int n, enum quoting_style s, char const *arg)
 {