Blame lib/quotearg.c

Packit Service a2489d
/* quotearg.c - quote arguments for output
Packit Service a2489d
Packit Service a2489d
   Copyright (C) 1998-2002, 2004-2018 Free Software Foundation, Inc.
Packit Service a2489d
Packit Service a2489d
   This program is free software: you can redistribute it and/or modify
Packit Service a2489d
   it under the terms of the GNU General Public License as published by
Packit Service a2489d
   the Free Software Foundation; either version 3 of the License, or
Packit Service a2489d
   (at your option) any later version.
Packit Service a2489d
Packit Service a2489d
   This program is distributed in the hope that it will be useful,
Packit Service a2489d
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a2489d
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a2489d
   GNU General Public License for more details.
Packit Service a2489d
Packit Service a2489d
   You should have received a copy of the GNU General Public License
Packit Service a2489d
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit Service a2489d
Packit Service a2489d
/* Written by Paul Eggert <eggert@twinsun.com> */
Packit Service a2489d
Packit Service a2489d
/* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that
Packit Service a2489d
   the quoting_options_from_style function might be candidate for
Packit Service a2489d
   attribute 'pure'  */
Packit Service a2489d
#if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
Packit Service a2489d
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
Packit Service a2489d
#endif
Packit Service a2489d
Packit Service a2489d
#include <config.h>
Packit Service a2489d
Packit Service a2489d
#include "quotearg.h"
Packit Service a2489d
#include "quote.h"
Packit Service a2489d
Packit Service a2489d
#include "minmax.h"
Packit Service a2489d
#include "xalloc.h"
Packit Service a2489d
#include "c-strcaseeq.h"
Packit Service a2489d
#include "localcharset.h"
Packit Service a2489d
Packit Service a2489d
#include <ctype.h>
Packit Service a2489d
#include <errno.h>
Packit Service a2489d
#include <limits.h>
Packit Service a2489d
#include <stdbool.h>
Packit Service a2489d
#include <stdint.h>
Packit Service a2489d
#include <stdlib.h>
Packit Service a2489d
#include <string.h>
Packit Service a2489d
#include <wchar.h>
Packit Service a2489d
#include <wctype.h>
Packit Service a2489d
Packit Service a2489d
#include "gettext.h"
Packit Service a2489d
#define _(msgid) gettext (msgid)
Packit Service a2489d
#define N_(msgid) msgid
Packit Service a2489d
Packit Service a2489d
#ifndef SIZE_MAX
Packit Service a2489d
# define SIZE_MAX ((size_t) -1)
Packit Service a2489d
#endif
Packit Service a2489d
Packit Service a2489d
#define INT_BITS (sizeof (int) * CHAR_BIT)
Packit Service a2489d
Packit Service a2489d
#ifndef FALLTHROUGH
Packit Service a2489d
# if __GNUC__ < 7
Packit Service a2489d
#  define FALLTHROUGH ((void) 0)
Packit Service a2489d
# else
Packit Service a2489d
#  define FALLTHROUGH __attribute__ ((__fallthrough__))
Packit Service a2489d
# endif
Packit Service a2489d
#endif
Packit Service a2489d
Packit Service a2489d
struct quoting_options
Packit Service a2489d
{
Packit Service a2489d
  /* Basic quoting style.  */
Packit Service a2489d
  enum quoting_style style;
Packit Service a2489d
Packit Service a2489d
  /* Additional flags.  Bitwise combination of enum quoting_flags.  */
Packit Service a2489d
  int flags;
Packit Service a2489d
Packit Service a2489d
  /* Quote the characters indicated by this bit vector even if the
Packit Service a2489d
     quoting style would not normally require them to be quoted.  */
Packit Service a2489d
  unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
Packit Service a2489d
Packit Service a2489d
  /* The left quote for custom_quoting_style.  */
Packit Service a2489d
  char const *left_quote;
Packit Service a2489d
Packit Service a2489d
  /* The right quote for custom_quoting_style.  */
Packit Service a2489d
  char const *right_quote;
Packit Service a2489d
};
Packit Service a2489d
Packit Service a2489d
/* Names of quoting styles.  */
Packit Service a2489d
char const *const quoting_style_args[] =
Packit Service a2489d
{
Packit Service a2489d
  "literal",
Packit Service a2489d
  "shell",
Packit Service a2489d
  "shell-always",
Packit Service a2489d
  "shell-escape",
Packit Service a2489d
  "shell-escape-always",
Packit Service a2489d
  "c",
Packit Service a2489d
  "c-maybe",
Packit Service a2489d
  "escape",
Packit Service a2489d
  "locale",
Packit Service a2489d
  "clocale",
Packit Service a2489d
  0
Packit Service a2489d
};
Packit Service a2489d
Packit Service a2489d
/* Correspondences to quoting style names.  */
Packit Service a2489d
enum quoting_style const quoting_style_vals[] =
Packit Service a2489d
{
Packit Service a2489d
  literal_quoting_style,
Packit Service a2489d
  shell_quoting_style,
Packit Service a2489d
  shell_always_quoting_style,
Packit Service a2489d
  shell_escape_quoting_style,
Packit Service a2489d
  shell_escape_always_quoting_style,
Packit Service a2489d
  c_quoting_style,
Packit Service a2489d
  c_maybe_quoting_style,
Packit Service a2489d
  escape_quoting_style,
Packit Service a2489d
  locale_quoting_style,
Packit Service a2489d
  clocale_quoting_style
Packit Service a2489d
};
Packit Service a2489d
Packit Service a2489d
/* The default quoting options.  */
Packit Service a2489d
static struct quoting_options default_quoting_options;
Packit Service a2489d
Packit Service a2489d
/* Allocate a new set of quoting options, with contents initially identical
Packit Service a2489d
   to O if O is not null, or to the default if O is null.
Packit Service a2489d
   It is the caller's responsibility to free the result.  */
Packit Service a2489d
struct quoting_options *
Packit Service a2489d
clone_quoting_options (struct quoting_options *o)
Packit Service a2489d
{
Packit Service a2489d
  int e = errno;
Packit Service a2489d
  struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
Packit Service a2489d
                                       sizeof *o);
Packit Service a2489d
  errno = e;
Packit Service a2489d
  return p;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Get the value of O's quoting style.  If O is null, use the default.  */
Packit Service a2489d
enum quoting_style
Packit Service a2489d
get_quoting_style (struct quoting_options const *o)
Packit Service a2489d
{
Packit Service a2489d
  return (o ? o : &default_quoting_options)->style;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* In O (or in the default if O is null),
Packit Service a2489d
   set the value of the quoting style to S.  */
Packit Service a2489d
void
Packit Service a2489d
set_quoting_style (struct quoting_options *o, enum quoting_style s)
Packit Service a2489d
{
Packit Service a2489d
  (o ? o : &default_quoting_options)->style = s;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* In O (or in the default if O is null),
Packit Service a2489d
   set the value of the quoting options for character C to I.
Packit Service a2489d
   Return the old value.  Currently, the only values defined for I are
Packit Service a2489d
   0 (the default) and 1 (which means to quote the character even if
Packit Service a2489d
   it would not otherwise be quoted).  */
Packit Service a2489d
int
Packit Service a2489d
set_char_quoting (struct quoting_options *o, char c, int i)
Packit Service a2489d
{
Packit Service a2489d
  unsigned char uc = c;
Packit Service a2489d
  unsigned int *p =
Packit Service a2489d
    (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
Packit Service a2489d
  int shift = uc % INT_BITS;
Packit Service a2489d
  int r = (*p >> shift) & 1;
Packit Service a2489d
  *p ^= ((i & 1) ^ r) << shift;
Packit Service a2489d
  return r;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* In O (or in the default if O is null),
Packit Service a2489d
   set the value of the quoting options flag to I, which can be a
Packit Service a2489d
   bitwise combination of enum quoting_flags, or 0 for default
Packit Service a2489d
   behavior.  Return the old value.  */
Packit Service a2489d
int
Packit Service a2489d
set_quoting_flags (struct quoting_options *o, int i)
Packit Service a2489d
{
Packit Service a2489d
  int r;
Packit Service a2489d
  if (!o)
Packit Service a2489d
    o = &default_quoting_options;
Packit Service a2489d
  r = o->flags;
Packit Service a2489d
  o->flags = i;
Packit Service a2489d
  return r;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
void
Packit Service a2489d
set_custom_quoting (struct quoting_options *o,
Packit Service a2489d
                    char const *left_quote, char const *right_quote)
Packit Service a2489d
{
Packit Service a2489d
  if (!o)
Packit Service a2489d
    o = &default_quoting_options;
Packit Service a2489d
  o->style = custom_quoting_style;
Packit Service a2489d
  if (!left_quote || !right_quote)
Packit Service a2489d
    abort ();
Packit Service a2489d
  o->left_quote = left_quote;
Packit Service a2489d
  o->right_quote = right_quote;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Return quoting options for STYLE, with no extra quoting.  */
Packit Service a2489d
static struct quoting_options /* NOT PURE!! */
Packit Service a2489d
quoting_options_from_style (enum quoting_style style)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options o = { literal_quoting_style, 0, { 0 }, NULL, NULL };
Packit Service a2489d
  if (style == custom_quoting_style)
Packit Service a2489d
    abort ();
Packit Service a2489d
  o.style = style;
Packit Service a2489d
  return o;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* MSGID approximates a quotation mark.  Return its translation if it
Packit Service a2489d
   has one; otherwise, return either it or "\"", depending on S.
Packit Service a2489d
Packit Service a2489d
   S is either clocale_quoting_style or locale_quoting_style.  */
Packit Service a2489d
static char const *
Packit Service a2489d
gettext_quote (char const *msgid, enum quoting_style s)
Packit Service a2489d
{
Packit Service a2489d
  char const *translation = _(msgid);
Packit Service a2489d
  char const *locale_code;
Packit Service a2489d
Packit Service a2489d
  if (translation != msgid)
Packit Service a2489d
    return translation;
Packit Service a2489d
Packit Service a2489d
  /* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019.
Packit Service a2489d
     Here is a list of other locales that include U+2018 and U+2019:
Packit Service a2489d
Packit Service a2489d
        ISO-8859-7   0xA1                 KOI8-T       0x91
Packit Service a2489d
        CP869        0x8B                 CP874        0x91
Packit Service a2489d
        CP932        0x81 0x65            CP936        0xA1 0xAE
Packit Service a2489d
        CP949        0xA1 0xAE            CP950        0xA1 0xA5
Packit Service a2489d
        CP1250       0x91                 CP1251       0x91
Packit Service a2489d
        CP1252       0x91                 CP1253       0x91
Packit Service a2489d
        CP1254       0x91                 CP1255       0x91
Packit Service a2489d
        CP1256       0x91                 CP1257       0x91
Packit Service a2489d
        EUC-JP       0xA1 0xC6            EUC-KR       0xA1 0xAE
Packit Service a2489d
        EUC-TW       0xA1 0xE4            BIG5         0xA1 0xA5
Packit Service a2489d
        BIG5-HKSCS   0xA1 0xA5            EUC-CN       0xA1 0xAE
Packit Service a2489d
        GBK          0xA1 0xAE            Georgian-PS  0x91
Packit Service a2489d
        PT154        0x91
Packit Service a2489d
Packit Service a2489d
     None of these is still in wide use; using iconv is overkill.  */
Packit Service a2489d
  locale_code = locale_charset ();
Packit Service a2489d
  if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0))
Packit Service a2489d
    return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99";
Packit Service a2489d
  if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0))
Packit Service a2489d
    return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf";
Packit Service a2489d
Packit Service a2489d
  return (s == clocale_quoting_style ? "\"" : "'");
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
Packit Service a2489d
   argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
Packit Service a2489d
   QUOTE_THESE_TOO to control quoting.
Packit Service a2489d
   Terminate the output with a null character, and return the written
Packit Service a2489d
   size of the output, not counting the terminating null.
Packit Service a2489d
   If BUFFERSIZE is too small to store the output string, return the
Packit Service a2489d
   value that would have been returned had BUFFERSIZE been large enough.
Packit Service a2489d
   If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
Packit Service a2489d
Packit Service a2489d
   This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
Packit Service a2489d
   ARGSIZE, O), except it breaks O into its component pieces and is
Packit Service a2489d
   not careful about errno.  */
Packit Service a2489d
Packit Service a2489d
static size_t
Packit Service a2489d
quotearg_buffer_restyled (char *buffer, size_t buffersize,
Packit Service a2489d
                          char const *arg, size_t argsize,
Packit Service a2489d
                          enum quoting_style quoting_style, int flags,
Packit Service a2489d
                          unsigned int const *quote_these_too,
Packit Service a2489d
                          char const *left_quote,
Packit Service a2489d
                          char const *right_quote)
Packit Service a2489d
{
Packit Service a2489d
  size_t i;
Packit Service a2489d
  size_t len = 0;
Packit Service a2489d
  size_t orig_buffersize = 0;
Packit Service a2489d
  char const *quote_string = 0;
Packit Service a2489d
  size_t quote_string_len = 0;
Packit Service a2489d
  bool backslash_escapes = false;
Packit Service a2489d
  bool unibyte_locale = MB_CUR_MAX == 1;
Packit Service a2489d
  bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
Packit Service a2489d
  bool pending_shell_escape_end = false;
Packit Service a2489d
  bool encountered_single_quote = false;
Packit Service a2489d
  bool all_c_and_shell_quote_compat = true;
Packit Service a2489d
Packit Service a2489d
#define STORE(c) \
Packit Service a2489d
    do \
Packit Service a2489d
      { \
Packit Service a2489d
        if (len < buffersize) \
Packit Service a2489d
          buffer[len] = (c); \
Packit Service a2489d
        len++; \
Packit Service a2489d
      } \
Packit Service a2489d
    while (0)
Packit Service a2489d
Packit Service a2489d
#define START_ESC() \
Packit Service a2489d
    do \
Packit Service a2489d
      { \
Packit Service a2489d
        if (elide_outer_quotes) \
Packit Service a2489d
          goto force_outer_quoting_style; \
Packit Service a2489d
        escaping = true; \
Packit Service a2489d
        if (quoting_style == shell_always_quoting_style \
Packit Service a2489d
            && ! pending_shell_escape_end) \
Packit Service a2489d
          { \
Packit Service a2489d
            STORE ('\''); \
Packit Service a2489d
            STORE ('$'); \
Packit Service a2489d
            STORE ('\''); \
Packit Service a2489d
            pending_shell_escape_end = true; \
Packit Service a2489d
          } \
Packit Service a2489d
        STORE ('\\'); \
Packit Service a2489d
      } \
Packit Service a2489d
    while (0)
Packit Service a2489d
Packit Service a2489d
#define END_ESC() \
Packit Service a2489d
    do \
Packit Service a2489d
      { \
Packit Service a2489d
        if (pending_shell_escape_end && ! escaping) \
Packit Service a2489d
          { \
Packit Service a2489d
            STORE ('\''); \
Packit Service a2489d
            STORE ('\''); \
Packit Service a2489d
            pending_shell_escape_end = false; \
Packit Service a2489d
          } \
Packit Service a2489d
      } \
Packit Service a2489d
    while (0)
Packit Service a2489d
Packit Service a2489d
 process_input:
Packit Service a2489d
Packit Service a2489d
  switch (quoting_style)
Packit Service a2489d
    {
Packit Service a2489d
    case c_maybe_quoting_style:
Packit Service a2489d
      quoting_style = c_quoting_style;
Packit Service a2489d
      elide_outer_quotes = true;
Packit Service a2489d
      FALLTHROUGH;
Packit Service a2489d
    case c_quoting_style:
Packit Service a2489d
      if (!elide_outer_quotes)
Packit Service a2489d
        STORE ('"');
Packit Service a2489d
      backslash_escapes = true;
Packit Service a2489d
      quote_string = "\"";
Packit Service a2489d
      quote_string_len = 1;
Packit Service a2489d
      break;
Packit Service a2489d
Packit Service a2489d
    case escape_quoting_style:
Packit Service a2489d
      backslash_escapes = true;
Packit Service a2489d
      elide_outer_quotes = false;
Packit Service a2489d
      break;
Packit Service a2489d
Packit Service a2489d
    case locale_quoting_style:
Packit Service a2489d
    case clocale_quoting_style:
Packit Service a2489d
    case custom_quoting_style:
Packit Service a2489d
      {
Packit Service a2489d
        if (quoting_style != custom_quoting_style)
Packit Service a2489d
          {
Packit Service a2489d
            /* TRANSLATORS:
Packit Service a2489d
               Get translations for open and closing quotation marks.
Packit Service a2489d
               The message catalog should translate "`" to a left
Packit Service a2489d
               quotation mark suitable for the locale, and similarly for
Packit Service a2489d
               "'".  For example, a French Unicode local should translate
Packit Service a2489d
               these to U+00AB (LEFT-POINTING DOUBLE ANGLE
Packit Service a2489d
               QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE
Packit Service a2489d
               QUOTATION MARK), respectively.
Packit Service a2489d
Packit Service a2489d
               If the catalog has no translation, we will try to
Packit Service a2489d
               use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and
Packit Service a2489d
               Unicode U+2019 (RIGHT SINGLE QUOTATION MARK).  If the
Packit Service a2489d
               current locale is not Unicode, locale_quoting_style
Packit Service a2489d
               will quote 'like this', and clocale_quoting_style will
Packit Service a2489d
               quote "like this".  You should always include translations
Packit Service a2489d
               for "`" and "'" even if U+2018 and U+2019 are appropriate
Packit Service a2489d
               for your locale.
Packit Service a2489d
Packit Service a2489d
               If you don't know what to put here, please see
Packit Service a2489d
               <https://en.wikipedia.org/wiki/Quotation_marks_in_other_languages>
Packit Service a2489d
               and use glyphs suitable for your language.  */
Packit Service a2489d
            left_quote = gettext_quote (N_("`"), quoting_style);
Packit Service a2489d
            right_quote = gettext_quote (N_("'"), quoting_style);
Packit Service a2489d
          }
Packit Service a2489d
        if (!elide_outer_quotes)
Packit Service a2489d
          for (quote_string = left_quote; *quote_string; quote_string++)
Packit Service a2489d
            STORE (*quote_string);
Packit Service a2489d
        backslash_escapes = true;
Packit Service a2489d
        quote_string = right_quote;
Packit Service a2489d
        quote_string_len = strlen (quote_string);
Packit Service a2489d
      }
Packit Service a2489d
      break;
Packit Service a2489d
Packit Service a2489d
    case shell_escape_quoting_style:
Packit Service a2489d
      backslash_escapes = true;
Packit Service a2489d
      FALLTHROUGH;
Packit Service a2489d
    case shell_quoting_style:
Packit Service a2489d
      elide_outer_quotes = true;
Packit Service a2489d
      FALLTHROUGH;
Packit Service a2489d
    case shell_escape_always_quoting_style:
Packit Service a2489d
      if (!elide_outer_quotes)
Packit Service a2489d
        backslash_escapes = true;
Packit Service a2489d
      FALLTHROUGH;
Packit Service a2489d
    case shell_always_quoting_style:
Packit Service a2489d
      quoting_style = shell_always_quoting_style;
Packit Service a2489d
      if (!elide_outer_quotes)
Packit Service a2489d
        STORE ('\'');
Packit Service a2489d
      quote_string = "'";
Packit Service a2489d
      quote_string_len = 1;
Packit Service a2489d
      break;
Packit Service a2489d
Packit Service a2489d
    case literal_quoting_style:
Packit Service a2489d
      elide_outer_quotes = false;
Packit Service a2489d
      break;
Packit Service a2489d
Packit Service a2489d
    default:
Packit Service a2489d
      abort ();
Packit Service a2489d
    }
Packit Service a2489d
Packit Service a2489d
  for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
Packit Service a2489d
    {
Packit Service a2489d
      unsigned char c;
Packit Service a2489d
      unsigned char esc;
Packit Service a2489d
      bool is_right_quote = false;
Packit Service a2489d
      bool escaping = false;
Packit Service a2489d
      bool c_and_shell_quote_compat = false;
Packit Service a2489d
Packit Service a2489d
      if (backslash_escapes
Packit Service a2489d
          && quoting_style != shell_always_quoting_style
Packit Service a2489d
          && quote_string_len
Packit Service a2489d
          && (i + quote_string_len
Packit Service a2489d
              <= (argsize == SIZE_MAX && 1 < quote_string_len
Packit Service a2489d
                  /* Use strlen only if we must: when argsize is SIZE_MAX,
Packit Service a2489d
                     and when the quote string is more than 1 byte long.
Packit Service a2489d
                     If we do call strlen, save the result.  */
Packit Service a2489d
                  ? (argsize = strlen (arg)) : argsize))
Packit Service a2489d
          && memcmp (arg + i, quote_string, quote_string_len) == 0)
Packit Service a2489d
        {
Packit Service a2489d
          if (elide_outer_quotes)
Packit Service a2489d
            goto force_outer_quoting_style;
Packit Service a2489d
          is_right_quote = true;
Packit Service a2489d
        }
Packit Service a2489d
Packit Service a2489d
      c = arg[i];
Packit Service a2489d
      switch (c)
Packit Service a2489d
        {
Packit Service a2489d
        case '\0':
Packit Service a2489d
          if (backslash_escapes)
Packit Service a2489d
            {
Packit Service a2489d
              START_ESC ();
Packit Service a2489d
              /* If quote_string were to begin with digits, we'd need to
Packit Service a2489d
                 test for the end of the arg as well.  However, it's
Packit Service a2489d
                 hard to imagine any locale that would use digits in
Packit Service a2489d
                 quotes, and set_custom_quoting is documented not to
Packit Service a2489d
                 accept them.  Use only a single \0 with shell-escape
Packit Service a2489d
                 as currently digits are not printed within $'...'  */
Packit Service a2489d
              if (quoting_style != shell_always_quoting_style
Packit Service a2489d
                  && i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
Packit Service a2489d
                {
Packit Service a2489d
                  STORE ('0');
Packit Service a2489d
                  STORE ('0');
Packit Service a2489d
                }
Packit Service a2489d
              c = '0';
Packit Service a2489d
              /* We don't have to worry that this last '0' will be
Packit Service a2489d
                 backslash-escaped because, again, quote_string should
Packit Service a2489d
                 not start with it and because quote_these_too is
Packit Service a2489d
                 documented as not accepting it.  */
Packit Service a2489d
            }
Packit Service a2489d
          else if (flags & QA_ELIDE_NULL_BYTES)
Packit Service a2489d
            continue;
Packit Service a2489d
          break;
Packit Service a2489d
Packit Service a2489d
        case '?':
Packit Service a2489d
          switch (quoting_style)
Packit Service a2489d
            {
Packit Service a2489d
            case shell_always_quoting_style:
Packit Service a2489d
              if (elide_outer_quotes)
Packit Service a2489d
                goto force_outer_quoting_style;
Packit Service a2489d
              break;
Packit Service a2489d
Packit Service a2489d
            case c_quoting_style:
Packit Service a2489d
              if ((flags & QA_SPLIT_TRIGRAPHS)
Packit Service a2489d
                  && i + 2 < argsize && arg[i + 1] == '?')
Packit Service a2489d
                switch (arg[i + 2])
Packit Service a2489d
                  {
Packit Service a2489d
                  case '!': case '\'':
Packit Service a2489d
                  case '(': case ')': case '-': case '/':
Packit Service a2489d
                  case '<': case '=': case '>':
Packit Service a2489d
                    /* Escape the second '?' in what would otherwise be
Packit Service a2489d
                       a trigraph.  */
Packit Service a2489d
                    if (elide_outer_quotes)
Packit Service a2489d
                      goto force_outer_quoting_style;
Packit Service a2489d
                    c = arg[i + 2];
Packit Service a2489d
                    i += 2;
Packit Service a2489d
                    STORE ('?');
Packit Service a2489d
                    STORE ('"');
Packit Service a2489d
                    STORE ('"');
Packit Service a2489d
                    STORE ('?');
Packit Service a2489d
                    break;
Packit Service a2489d
Packit Service a2489d
                  default:
Packit Service a2489d
                    break;
Packit Service a2489d
                  }
Packit Service a2489d
              break;
Packit Service a2489d
Packit Service a2489d
            default:
Packit Service a2489d
              break;
Packit Service a2489d
            }
Packit Service a2489d
          break;
Packit Service a2489d
Packit Service a2489d
        case '\a': esc = 'a'; goto c_escape;
Packit Service a2489d
        case '\b': esc = 'b'; goto c_escape;
Packit Service a2489d
        case '\f': esc = 'f'; goto c_escape;
Packit Service a2489d
        case '\n': esc = 'n'; goto c_and_shell_escape;
Packit Service a2489d
        case '\r': esc = 'r'; goto c_and_shell_escape;
Packit Service a2489d
        case '\t': esc = 't'; goto c_and_shell_escape;
Packit Service a2489d
        case '\v': esc = 'v'; goto c_escape;
Packit Service a2489d
        case '\\': esc = c;
Packit Service a2489d
          /* Never need to escape '\' in shell case.  */
Packit Service a2489d
          if (quoting_style == shell_always_quoting_style)
Packit Service a2489d
            {
Packit Service a2489d
              if (elide_outer_quotes)
Packit Service a2489d
                goto force_outer_quoting_style;
Packit Service a2489d
              goto store_c;
Packit Service a2489d
            }
Packit Service a2489d
Packit Service a2489d
          /* No need to escape the escape if we are trying to elide
Packit Service a2489d
             outer quotes and nothing else is problematic.  */
Packit Service a2489d
          if (backslash_escapes && elide_outer_quotes && quote_string_len)
Packit Service a2489d
            goto store_c;
Packit Service a2489d
Packit Service a2489d
        c_and_shell_escape:
Packit Service a2489d
          if (quoting_style == shell_always_quoting_style
Packit Service a2489d
              && elide_outer_quotes)
Packit Service a2489d
            goto force_outer_quoting_style;
Packit Service a2489d
          /* fall through */
Packit Service a2489d
        c_escape:
Packit Service a2489d
          if (backslash_escapes)
Packit Service a2489d
            {
Packit Service a2489d
              c = esc;
Packit Service a2489d
              goto store_escape;
Packit Service a2489d
            }
Packit Service a2489d
          break;
Packit Service a2489d
Packit Service a2489d
        case '{': case '}': /* sometimes special if isolated */
Packit Service a2489d
          if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
Packit Service a2489d
            break;
Packit Service a2489d
          FALLTHROUGH;
Packit Service a2489d
        case '#': case '~':
Packit Service a2489d
          if (i != 0)
Packit Service a2489d
            break;
Packit Service a2489d
          FALLTHROUGH;
Packit Service a2489d
        case ' ':
Packit Service a2489d
          c_and_shell_quote_compat = true;
Packit Service a2489d
          FALLTHROUGH;
Packit Service a2489d
        case '!': /* special in bash */
Packit Service a2489d
        case '"': case '$': case '&':
Packit Service a2489d
        case '(': case ')': case '*': case ';':
Packit Service a2489d
        case '<':
Packit Service a2489d
        case '=': /* sometimes special in 0th or (with "set -k") later args */
Packit Service a2489d
        case '>': case '[':
Packit Service a2489d
        case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
Packit Service a2489d
        case '`': case '|':
Packit Service a2489d
          /* A shell special character.  In theory, '$' and '`' could
Packit Service a2489d
             be the first bytes of multibyte characters, which means
Packit Service a2489d
             we should check them with mbrtowc, but in practice this
Packit Service a2489d
             doesn't happen so it's not worth worrying about.  */
Packit Service a2489d
          if (quoting_style == shell_always_quoting_style
Packit Service a2489d
              && elide_outer_quotes)
Packit Service a2489d
            goto force_outer_quoting_style;
Packit Service a2489d
          break;
Packit Service a2489d
Packit Service a2489d
        case '\'':
Packit Service a2489d
          encountered_single_quote = true;
Packit Service a2489d
          c_and_shell_quote_compat = true;
Packit Service a2489d
          if (quoting_style == shell_always_quoting_style)
Packit Service a2489d
            {
Packit Service a2489d
              if (elide_outer_quotes)
Packit Service a2489d
                goto force_outer_quoting_style;
Packit Service a2489d
Packit Service a2489d
              if (buffersize && ! orig_buffersize)
Packit Service a2489d
                {
Packit Service a2489d
                  /* Just scan string to see if supports a more concise
Packit Service a2489d
                     representation, rather than writing a longer string
Packit Service a2489d
                     but returning the length of the more concise form.  */
Packit Service a2489d
                  orig_buffersize = buffersize;
Packit Service a2489d
                  buffersize = 0;
Packit Service a2489d
                }
Packit Service a2489d
Packit Service a2489d
              STORE ('\'');
Packit Service a2489d
              STORE ('\\');
Packit Service a2489d
              STORE ('\'');
Packit Service a2489d
              pending_shell_escape_end = false;
Packit Service a2489d
            }
Packit Service a2489d
          break;
Packit Service a2489d
Packit Service a2489d
        case '%': case '+': case ',': case '-': case '.': case '/':
Packit Service a2489d
        case '0': case '1': case '2': case '3': case '4': case '5':
Packit Service a2489d
        case '6': case '7': case '8': case '9': case ':':
Packit Service a2489d
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
Packit Service a2489d
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
Packit Service a2489d
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
Packit Service a2489d
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
Packit Service a2489d
        case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
Packit Service a2489d
        case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
Packit Service a2489d
        case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
Packit Service a2489d
        case 'o': case 'p': case 'q': case 'r': case 's': case 't':
Packit Service a2489d
        case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
Packit Service a2489d
          /* These characters don't cause problems, no matter what the
Packit Service a2489d
             quoting style is.  They cannot start multibyte sequences.
Packit Service a2489d
             A digit or a special letter would cause trouble if it
Packit Service a2489d
             appeared at the beginning of quote_string because we'd then
Packit Service a2489d
             escape by prepending a backslash.  However, it's hard to
Packit Service a2489d
             imagine any locale that would use digits or letters as
Packit Service a2489d
             quotes, and set_custom_quoting is documented not to accept
Packit Service a2489d
             them.  Also, a digit or a special letter would cause
Packit Service a2489d
             trouble if it appeared in quote_these_too, but that's also
Packit Service a2489d
             documented as not accepting them.  */
Packit Service a2489d
          c_and_shell_quote_compat = true;
Packit Service a2489d
          break;
Packit Service a2489d
Packit Service a2489d
        default:
Packit Service a2489d
          /* If we have a multibyte sequence, copy it until we reach
Packit Service a2489d
             its end, find an error, or come back to the initial shift
Packit Service a2489d
             state.  For C-like styles, if the sequence has
Packit Service a2489d
             unprintable characters, escape the whole sequence, since
Packit Service a2489d
             we can't easily escape single characters within it.  */
Packit Service a2489d
          {
Packit Service a2489d
            /* Length of multibyte sequence found so far.  */
Packit Service a2489d
            size_t m;
Packit Service a2489d
Packit Service a2489d
            bool printable;
Packit Service a2489d
Packit Service a2489d
            if (unibyte_locale)
Packit Service a2489d
              {
Packit Service a2489d
                m = 1;
Packit Service a2489d
                printable = isprint (c) != 0;
Packit Service a2489d
              }
Packit Service a2489d
            else
Packit Service a2489d
              {
Packit Service a2489d
                mbstate_t mbstate;
Packit Service a2489d
                memset (&mbstate, 0, sizeof mbstate);
Packit Service a2489d
Packit Service a2489d
                m = 0;
Packit Service a2489d
                printable = true;
Packit Service a2489d
                if (argsize == SIZE_MAX)
Packit Service a2489d
                  argsize = strlen (arg);
Packit Service a2489d
Packit Service a2489d
                do
Packit Service a2489d
                  {
Packit Service a2489d
                    wchar_t w;
Packit Service a2489d
                    size_t bytes = mbrtowc (&w, &arg[i + m],
Packit Service a2489d
                                            argsize - (i + m), &mbstate);
Packit Service a2489d
                    if (bytes == 0)
Packit Service a2489d
                      break;
Packit Service a2489d
                    else if (bytes == (size_t) -1)
Packit Service a2489d
                      {
Packit Service a2489d
                        printable = false;
Packit Service a2489d
                        break;
Packit Service a2489d
                      }
Packit Service a2489d
                    else if (bytes == (size_t) -2)
Packit Service a2489d
                      {
Packit Service a2489d
                        printable = false;
Packit Service a2489d
                        while (i + m < argsize && arg[i + m])
Packit Service a2489d
                          m++;
Packit Service a2489d
                        break;
Packit Service a2489d
                      }
Packit Service a2489d
                    else
Packit Service a2489d
                      {
Packit Service a2489d
                        /* Work around a bug with older shells that "see" a '\'
Packit Service a2489d
                           that is really the 2nd byte of a multibyte character.
Packit Service a2489d
                           In practice the problem is limited to ASCII
Packit Service a2489d
                           chars >= '@' that are shell special chars.  */
Packit Service a2489d
                        if ('[' == 0x5b && elide_outer_quotes
Packit Service a2489d
                            && quoting_style == shell_always_quoting_style)
Packit Service a2489d
                          {
Packit Service a2489d
                            size_t j;
Packit Service a2489d
                            for (j = 1; j < bytes; j++)
Packit Service a2489d
                              switch (arg[i + m + j])
Packit Service a2489d
                                {
Packit Service a2489d
                                case '[': case '\\': case '^':
Packit Service a2489d
                                case '`': case '|':
Packit Service a2489d
                                  goto force_outer_quoting_style;
Packit Service a2489d
Packit Service a2489d
                                default:
Packit Service a2489d
                                  break;
Packit Service a2489d
                                }
Packit Service a2489d
                          }
Packit Service a2489d
Packit Service a2489d
                        if (! iswprint (w))
Packit Service a2489d
                          printable = false;
Packit Service a2489d
                        m += bytes;
Packit Service a2489d
                      }
Packit Service a2489d
                  }
Packit Service a2489d
                while (! mbsinit (&mbstate));
Packit Service a2489d
              }
Packit Service a2489d
Packit Service a2489d
            c_and_shell_quote_compat = printable;
Packit Service a2489d
Packit Service a2489d
            if (1 < m || (backslash_escapes && ! printable))
Packit Service a2489d
              {
Packit Service a2489d
                /* Output a multibyte sequence, or an escaped
Packit Service a2489d
                   unprintable unibyte character.  */
Packit Service a2489d
                size_t ilim = i + m;
Packit Service a2489d
Packit Service a2489d
                for (;;)
Packit Service a2489d
                  {
Packit Service a2489d
                    if (backslash_escapes && ! printable)
Packit Service a2489d
                      {
Packit Service a2489d
                        START_ESC ();
Packit Service a2489d
                        STORE ('0' + (c >> 6));
Packit Service a2489d
                        STORE ('0' + ((c >> 3) & 7));
Packit Service a2489d
                        c = '0' + (c & 7);
Packit Service a2489d
                      }
Packit Service a2489d
                    else if (is_right_quote)
Packit Service a2489d
                      {
Packit Service a2489d
                        STORE ('\\');
Packit Service a2489d
                        is_right_quote = false;
Packit Service a2489d
                      }
Packit Service a2489d
                    if (ilim <= i + 1)
Packit Service a2489d
                      break;
Packit Service a2489d
                    END_ESC ();
Packit Service a2489d
                    STORE (c);
Packit Service a2489d
                    c = arg[++i];
Packit Service a2489d
                  }
Packit Service a2489d
Packit Service a2489d
                goto store_c;
Packit Service a2489d
              }
Packit Service a2489d
          }
Packit Service a2489d
        }
Packit Service a2489d
Packit Service a2489d
      if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
Packit Service a2489d
              || elide_outer_quotes)
Packit Service a2489d
             && quote_these_too
Packit Service a2489d
             && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
Packit Service a2489d
          && !is_right_quote)
Packit Service a2489d
        goto store_c;
Packit Service a2489d
Packit Service a2489d
    store_escape:
Packit Service a2489d
      START_ESC ();
Packit Service a2489d
Packit Service a2489d
    store_c:
Packit Service a2489d
      END_ESC ();
Packit Service a2489d
      STORE (c);
Packit Service a2489d
Packit Service a2489d
      if (! c_and_shell_quote_compat)
Packit Service a2489d
        all_c_and_shell_quote_compat = false;
Packit Service a2489d
    }
Packit Service a2489d
Packit Service a2489d
  if (len == 0 && quoting_style == shell_always_quoting_style
Packit Service a2489d
      && elide_outer_quotes)
Packit Service a2489d
    goto force_outer_quoting_style;
Packit Service a2489d
Packit Service a2489d
  /* Single shell quotes (') are commonly enough used as an apostrophe,
Packit Service a2489d
     that we attempt to minimize the quoting in this case.  Note itʼs
Packit Service a2489d
     better to use the apostrophe modifier "\u02BC" if possible, as that
Packit Service a2489d
     renders better and works with the word match regex \W+ etc.  */
Packit Service a2489d
  if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
Packit Service a2489d
      && encountered_single_quote)
Packit Service a2489d
    {
Packit Service a2489d
      if (all_c_and_shell_quote_compat)
Packit Service a2489d
        return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
Packit Service a2489d
                                         c_quoting_style,
Packit Service a2489d
                                         flags, quote_these_too,
Packit Service a2489d
                                         left_quote, right_quote);
Packit Service a2489d
      else if (! buffersize && orig_buffersize)
Packit Service a2489d
        {
Packit Service a2489d
          /* Disable read-only scan, and reprocess to write quoted string.  */
Packit Service a2489d
          buffersize = orig_buffersize;
Packit Service a2489d
          len = 0;
Packit Service a2489d
          goto process_input;
Packit Service a2489d
        }
Packit Service a2489d
    }
Packit Service a2489d
Packit Service a2489d
  if (quote_string && !elide_outer_quotes)
Packit Service a2489d
    for (; *quote_string; quote_string++)
Packit Service a2489d
      STORE (*quote_string);
Packit Service a2489d
Packit Service a2489d
  if (len < buffersize)
Packit Service a2489d
    buffer[len] = '\0';
Packit Service a2489d
  return len;
Packit Service a2489d
Packit Service a2489d
 force_outer_quoting_style:
Packit Service a2489d
  /* Don't reuse quote_these_too, since the addition of outer quotes
Packit Service a2489d
     sufficiently quotes the specified characters.  */
Packit Service a2489d
  if (quoting_style == shell_always_quoting_style && backslash_escapes)
Packit Service a2489d
    quoting_style = shell_escape_always_quoting_style;
Packit Service a2489d
  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
Packit Service a2489d
                                   quoting_style,
Packit Service a2489d
                                   flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
Packit Service a2489d
                                   left_quote, right_quote);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
Packit Service a2489d
   argument ARG (of size ARGSIZE), using O to control quoting.
Packit Service a2489d
   If O is null, use the default.
Packit Service a2489d
   Terminate the output with a null character, and return the written
Packit Service a2489d
   size of the output, not counting the terminating null.
Packit Service a2489d
   If BUFFERSIZE is too small to store the output string, return the
Packit Service a2489d
   value that would have been returned had BUFFERSIZE been large enough.
Packit Service a2489d
   If ARGSIZE is SIZE_MAX, use the string length of the argument for
Packit Service a2489d
   ARGSIZE.  */
Packit Service a2489d
size_t
Packit Service a2489d
quotearg_buffer (char *buffer, size_t buffersize,
Packit Service a2489d
                 char const *arg, size_t argsize,
Packit Service a2489d
                 struct quoting_options const *o)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options const *p = o ? o : &default_quoting_options;
Packit Service a2489d
  int e = errno;
Packit Service a2489d
  size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
Packit Service a2489d
                                       p->style, p->flags, p->quote_these_too,
Packit Service a2489d
                                       p->left_quote, p->right_quote);
Packit Service a2489d
  errno = e;
Packit Service a2489d
  return r;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Equivalent to quotearg_alloc (ARG, ARGSIZE, NULL, O).  */
Packit Service a2489d
char *
Packit Service a2489d
quotearg_alloc (char const *arg, size_t argsize,
Packit Service a2489d
                struct quoting_options const *o)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_alloc_mem (arg, argsize, NULL, o);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
Packit Service a2489d
   allocated storage containing the quoted string, and store the
Packit Service a2489d
   resulting size into *SIZE, if non-NULL.  The result can contain
Packit Service a2489d
   embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
Packit Service a2489d
   NULL, and set_quoting_flags has not set the null byte elision
Packit Service a2489d
   flag.  */
Packit Service a2489d
char *
Packit Service a2489d
quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
Packit Service a2489d
                    struct quoting_options const *o)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options const *p = o ? o : &default_quoting_options;
Packit Service a2489d
  int e = errno;
Packit Service a2489d
  /* Elide embedded null bytes if we can't return a size.  */
Packit Service a2489d
  int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
Packit Service a2489d
  size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
Packit Service a2489d
                                             flags, p->quote_these_too,
Packit Service a2489d
                                             p->left_quote,
Packit Service a2489d
                                             p->right_quote) + 1;
Packit Service a2489d
  char *buf = xcharalloc (bufsize);
Packit Service a2489d
  quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
Packit Service a2489d
                            p->quote_these_too,
Packit Service a2489d
                            p->left_quote, p->right_quote);
Packit Service a2489d
  errno = e;
Packit Service a2489d
  if (size)
Packit Service a2489d
    *size = bufsize - 1;
Packit Service a2489d
  return buf;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* A storage slot with size and pointer to a value.  */
Packit Service a2489d
struct slotvec
Packit Service a2489d
{
Packit Service a2489d
  size_t size;
Packit Service a2489d
  char *val;
Packit Service a2489d
};
Packit Service a2489d
Packit Service a2489d
/* Preallocate a slot 0 buffer, so that the caller can always quote
Packit Service a2489d
   one small component of a "memory exhausted" message in slot 0.  */
Packit Service a2489d
static char slot0[256];
Packit Service a2489d
static int nslots = 1;
Packit Service a2489d
static struct slotvec slotvec0 = {sizeof slot0, slot0};
Packit Service a2489d
static struct slotvec *slotvec = &slotvec0;
Packit Service a2489d
Packit Service a2489d
void
Packit Service a2489d
quotearg_free (void)
Packit Service a2489d
{
Packit Service a2489d
  struct slotvec *sv = slotvec;
Packit Service a2489d
  int i;
Packit Service a2489d
  for (i = 1; i < nslots; i++)
Packit Service a2489d
    free (sv[i].val);
Packit Service a2489d
  if (sv[0].val != slot0)
Packit Service a2489d
    {
Packit Service a2489d
      free (sv[0].val);
Packit Service a2489d
      slotvec0.size = sizeof slot0;
Packit Service a2489d
      slotvec0.val = slot0;
Packit Service a2489d
    }
Packit Service a2489d
  if (sv != &slotvec0)
Packit Service a2489d
    {
Packit Service a2489d
      free (sv);
Packit Service a2489d
      slotvec = &slotvec0;
Packit Service a2489d
    }
Packit Service a2489d
  nslots = 1;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/* Use storage slot N to return a quoted version of argument ARG.
Packit Service a2489d
   ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
Packit Service a2489d
   null-terminated string.
Packit Service a2489d
   OPTIONS specifies the quoting options.
Packit Service a2489d
   The returned value points to static storage that can be
Packit Service a2489d
   reused by the next call to this function with the same value of N.
Packit Service a2489d
   N must be nonnegative.  N is deliberately declared with type "int"
Packit Service a2489d
   to allow for future extensions (using negative values).  */
Packit Service a2489d
static char *
Packit Service a2489d
quotearg_n_options (int n, char const *arg, size_t argsize,
Packit Service a2489d
                    struct quoting_options const *options)
Packit Service a2489d
{
Packit Service a2489d
  int e = errno;
Packit Service a2489d
Packit Service a2489d
  struct slotvec *sv = slotvec;
Packit Service a2489d
Packit Service a2489d
  if (n < 0)
Packit Service a2489d
    abort ();
Packit Service a2489d
Packit Service a2489d
  if (nslots <= n)
Packit Service a2489d
    {
Packit Service a2489d
      bool preallocated = (sv == &slotvec0);
Packit Service a2489d
      int nmax = MIN (INT_MAX, MIN (PTRDIFF_MAX, SIZE_MAX) / sizeof *sv) - 1;
Packit Service a2489d
Packit Service a2489d
      if (nmax < n)
Packit Service a2489d
        xalloc_die ();
Packit Service a2489d
Packit Service a2489d
      slotvec = sv = xrealloc (preallocated ? NULL : sv, (n + 1) * sizeof *sv);
Packit Service a2489d
      if (preallocated)
Packit Service a2489d
        *sv = slotvec0;
Packit Service a2489d
      memset (sv + nslots, 0, (n + 1 - nslots) * sizeof *sv);
Packit Service a2489d
      nslots = n + 1;
Packit Service a2489d
    }
Packit Service a2489d
Packit Service a2489d
  {
Packit Service a2489d
    size_t size = sv[n].size;
Packit Service a2489d
    char *val = sv[n].val;
Packit Service a2489d
    /* Elide embedded null bytes since we don't return a size.  */
Packit Service a2489d
    int flags = options->flags | QA_ELIDE_NULL_BYTES;
Packit Service a2489d
    size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
Packit Service a2489d
                                             options->style, flags,
Packit Service a2489d
                                             options->quote_these_too,
Packit Service a2489d
                                             options->left_quote,
Packit Service a2489d
                                             options->right_quote);
Packit Service a2489d
Packit Service a2489d
    if (size <= qsize)
Packit Service a2489d
      {
Packit Service a2489d
        sv[n].size = size = qsize + 1;
Packit Service a2489d
        if (val != slot0)
Packit Service a2489d
          free (val);
Packit Service a2489d
        sv[n].val = val = xcharalloc (size);
Packit Service a2489d
        quotearg_buffer_restyled (val, size, arg, argsize, options->style,
Packit Service a2489d
                                  flags, options->quote_these_too,
Packit Service a2489d
                                  options->left_quote,
Packit Service a2489d
                                  options->right_quote);
Packit Service a2489d
      }
Packit Service a2489d
Packit Service a2489d
    errno = e;
Packit Service a2489d
    return val;
Packit Service a2489d
  }
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n (int n, char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n_mem (int n, char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_options (n, arg, argsize, &default_quoting_options);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg (char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n (0, arg);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_mem (char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_mem (0, arg, argsize);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n_style (int n, enum quoting_style s, char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options const o = quoting_options_from_style (s);
Packit Service a2489d
  return quotearg_n_options (n, arg, SIZE_MAX, &o);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n_style_mem (int n, enum quoting_style s,
Packit Service a2489d
                      char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options const o = quoting_options_from_style (s);
Packit Service a2489d
  return quotearg_n_options (n, arg, argsize, &o);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_style (enum quoting_style s, char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_style (0, s, arg);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_style_mem (0, s, arg, argsize);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_char_mem (char const *arg, size_t argsize, char ch)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options options;
Packit Service a2489d
  options = default_quoting_options;
Packit Service a2489d
  set_char_quoting (&options, ch, 1);
Packit Service a2489d
  return quotearg_n_options (0, arg, argsize, &options);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_char (char const *arg, char ch)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_char_mem (arg, SIZE_MAX, ch);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_colon (char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_char (arg, ':');
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_colon_mem (char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_char_mem (arg, argsize, ':');
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options options;
Packit Service a2489d
  options = quoting_options_from_style (s);
Packit Service a2489d
  set_char_quoting (&options, ':', 1);
Packit Service a2489d
  return quotearg_n_options (n, arg, SIZE_MAX, &options);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n_custom (int n, char const *left_quote,
Packit Service a2489d
                   char const *right_quote, char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
Packit Service a2489d
                                SIZE_MAX);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_n_custom_mem (int n, char const *left_quote,
Packit Service a2489d
                       char const *right_quote,
Packit Service a2489d
                       char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  struct quoting_options o = default_quoting_options;
Packit Service a2489d
  set_custom_quoting (&o, left_quote, right_quote);
Packit Service a2489d
  return quotearg_n_options (n, arg, argsize, &o);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_custom (char const *left_quote, char const *right_quote,
Packit Service a2489d
                 char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_custom (0, left_quote, right_quote, arg);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char *
Packit Service a2489d
quotearg_custom_mem (char const *left_quote, char const *right_quote,
Packit Service a2489d
                     char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
Packit Service a2489d
                                argsize);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
Packit Service a2489d
/* The quoting option used by the functions of quote.h.  */
Packit Service a2489d
struct quoting_options quote_quoting_options =
Packit Service a2489d
  {
Packit Service a2489d
    locale_quoting_style,
Packit Service a2489d
    0,
Packit Service a2489d
    { 0 },
Packit Service a2489d
    NULL, NULL
Packit Service a2489d
  };
Packit Service a2489d
Packit Service a2489d
char const *
Packit Service a2489d
quote_n_mem (int n, char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char const *
Packit Service a2489d
quote_mem (char const *arg, size_t argsize)
Packit Service a2489d
{
Packit Service a2489d
  return quote_n_mem (0, arg, argsize);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char const *
Packit Service a2489d
quote_n (int n, char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quote_n_mem (n, arg, SIZE_MAX);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
char const *
Packit Service a2489d
quote (char const *arg)
Packit Service a2489d
{
Packit Service a2489d
  return quote_n (0, arg);
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
/*
Packit Service a2489d
 * Hey Emacs!
Packit Service a2489d
 * Local Variables:
Packit Service a2489d
 * coding: utf-8
Packit Service a2489d
 * End:
Packit Service a2489d
 */