(root)/
tar-1.35/
gnu/
quotearg.c
       1  /* quotearg.c - quote arguments for output
       2  
       3     Copyright (C) 1998-2002, 2004-2023 Free Software Foundation, Inc.
       4  
       5     This program is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU General Public License as published by
       7     the Free Software Foundation, either version 3 of the License, or
       8     (at your option) any later version.
       9  
      10     This program is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU General Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Written by Paul Eggert <eggert@twinsun.com> */
      19  
      20  /* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that
      21     the quoting_options_from_style function might be candidate for
      22     attribute 'pure'  */
      23  #if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
      24  # pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
      25  #endif
      26  
      27  #include <config.h>
      28  
      29  #include "quotearg.h"
      30  #include "quote.h"
      31  
      32  #include "attribute.h"
      33  #include "minmax.h"
      34  #include "xalloc.h"
      35  #include "c-strcaseeq.h"
      36  #include "localcharset.h"
      37  
      38  #include <ctype.h>
      39  #include <errno.h>
      40  #include <limits.h>
      41  #include <stdint.h>
      42  #include <stdlib.h>
      43  #include <string.h>
      44  #include <wchar.h>
      45  #include <wctype.h>
      46  
      47  #include "gettext.h"
      48  #define _(msgid) gettext (msgid)
      49  #define N_(msgid) msgid
      50  
      51  #ifndef SIZE_MAX
      52  # define SIZE_MAX ((size_t) -1)
      53  #endif
      54  
      55  #define INT_BITS (sizeof (int) * CHAR_BIT)
      56  
      57  struct quoting_options
      58  {
      59    /* Basic quoting style.  */
      60    enum quoting_style style;
      61  
      62    /* Additional flags.  Bitwise combination of enum quoting_flags.  */
      63    int flags;
      64  
      65    /* Quote the characters indicated by this bit vector even if the
      66       quoting style would not normally require them to be quoted.  */
      67    unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
      68  
      69    /* The left quote for custom_quoting_style.  */
      70    char const *left_quote;
      71  
      72    /* The right quote for custom_quoting_style.  */
      73    char const *right_quote;
      74  };
      75  
      76  /* Names of quoting styles.  */
      77  char const *const quoting_style_args[] =
      78  {
      79    "literal",
      80    "shell",
      81    "shell-always",
      82    "shell-escape",
      83    "shell-escape-always",
      84    "c",
      85    "c-maybe",
      86    "escape",
      87    "locale",
      88    "clocale",
      89    0
      90  };
      91  
      92  /* Correspondences to quoting style names.  */
      93  enum quoting_style const quoting_style_vals[] =
      94  {
      95    literal_quoting_style,
      96    shell_quoting_style,
      97    shell_always_quoting_style,
      98    shell_escape_quoting_style,
      99    shell_escape_always_quoting_style,
     100    c_quoting_style,
     101    c_maybe_quoting_style,
     102    escape_quoting_style,
     103    locale_quoting_style,
     104    clocale_quoting_style
     105  };
     106  
     107  /* The default quoting options.  */
     108  static struct quoting_options default_quoting_options;
     109  
     110  /* Allocate a new set of quoting options, with contents initially identical
     111     to O if O is not null, or to the default if O is null.
     112     It is the caller's responsibility to free the result.  */
     113  struct quoting_options *
     114  clone_quoting_options (struct quoting_options *o)
     115  {
     116    int e = errno;
     117    struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
     118                                         sizeof *o);
     119    errno = e;
     120    return p;
     121  }
     122  
     123  /* Get the value of O's quoting style.  If O is null, use the default.  */
     124  enum quoting_style
     125  get_quoting_style (struct quoting_options const *o)
     126  {
     127    return (o ? o : &default_quoting_options)->style;
     128  }
     129  
     130  /* In O (or in the default if O is null),
     131     set the value of the quoting style to S.  */
     132  void
     133  set_quoting_style (struct quoting_options *o, enum quoting_style s)
     134  {
     135    (o ? o : &default_quoting_options)->style = s;
     136  }
     137  
     138  /* In O (or in the default if O is null),
     139     set the value of the quoting options for character C to I.
     140     Return the old value.  Currently, the only values defined for I are
     141     0 (the default) and 1 (which means to quote the character even if
     142     it would not otherwise be quoted).  */
     143  int
     144  set_char_quoting (struct quoting_options *o, char c, int i)
     145  {
     146    unsigned char uc = c;
     147    unsigned int *p =
     148      (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
     149    int shift = uc % INT_BITS;
     150    int r = (*p >> shift) & 1;
     151    *p ^= ((i & 1) ^ r) << shift;
     152    return r;
     153  }
     154  
     155  /* In O (or in the default if O is null),
     156     set the value of the quoting options flag to I, which can be a
     157     bitwise combination of enum quoting_flags, or 0 for default
     158     behavior.  Return the old value.  */
     159  int
     160  set_quoting_flags (struct quoting_options *o, int i)
     161  {
     162    int r;
     163    if (!o)
     164      o = &default_quoting_options;
     165    r = o->flags;
     166    o->flags = i;
     167    return r;
     168  }
     169  
     170  void
     171  set_custom_quoting (struct quoting_options *o,
     172                      char const *left_quote, char const *right_quote)
     173  {
     174    if (!o)
     175      o = &default_quoting_options;
     176    o->style = custom_quoting_style;
     177    if (!left_quote || !right_quote)
     178      abort ();
     179    o->left_quote = left_quote;
     180    o->right_quote = right_quote;
     181  }
     182  
     183  /* Return quoting options for STYLE, with no extra quoting.  */
     184  static struct quoting_options /* NOT PURE!! */
     185  quoting_options_from_style (enum quoting_style style)
     186  {
     187    struct quoting_options o = { literal_quoting_style, 0, { 0 }, NULL, NULL };
     188    if (style == custom_quoting_style)
     189      abort ();
     190    o.style = style;
     191    return o;
     192  }
     193  
     194  /* MSGID approximates a quotation mark.  Return its translation if it
     195     has one; otherwise, return either it or "\"", depending on S.
     196  
     197     S is either clocale_quoting_style or locale_quoting_style.  */
     198  static char const *
     199  gettext_quote (char const *msgid, enum quoting_style s)
     200  {
     201    char const *translation = _(msgid);
     202    char const *locale_code;
     203  
     204    if (translation != msgid)
     205      return translation;
     206  
     207    /* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019.
     208       Here is a list of other locales that include U+2018 and U+2019:
     209  
     210          ISO-8859-7   0xA1                 KOI8-T       0x91
     211          CP869        0x8B                 CP874        0x91
     212          CP932        0x81 0x65            CP936        0xA1 0xAE
     213          CP949        0xA1 0xAE            CP950        0xA1 0xA5
     214          CP1250       0x91                 CP1251       0x91
     215          CP1252       0x91                 CP1253       0x91
     216          CP1254       0x91                 CP1255       0x91
     217          CP1256       0x91                 CP1257       0x91
     218          EUC-JP       0xA1 0xC6            EUC-KR       0xA1 0xAE
     219          EUC-TW       0xA1 0xE4            BIG5         0xA1 0xA5
     220          BIG5-HKSCS   0xA1 0xA5            EUC-CN       0xA1 0xAE
     221          GBK          0xA1 0xAE            Georgian-PS  0x91
     222          PT154        0x91
     223  
     224       None of these is still in wide use; using iconv is overkill.  */
     225    locale_code = locale_charset ();
     226    if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0))
     227      return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99";
     228    if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0))
     229      return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf";
     230  
     231    return (s == clocale_quoting_style ? "\"" : "'");
     232  }
     233  
     234  /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
     235     argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
     236     QUOTE_THESE_TOO to control quoting.
     237     Terminate the output with a null character, and return the written
     238     size of the output, not counting the terminating null.
     239     If BUFFERSIZE is too small to store the output string, return the
     240     value that would have been returned had BUFFERSIZE been large enough.
     241     If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
     242  
     243     This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
     244     ARGSIZE, O), except it breaks O into its component pieces and is
     245     not careful about errno.  */
     246  
     247  static size_t
     248  quotearg_buffer_restyled (char *buffer, size_t buffersize,
     249                            char const *arg, size_t argsize,
     250                            enum quoting_style quoting_style, int flags,
     251                            unsigned int const *quote_these_too,
     252                            char const *left_quote,
     253                            char const *right_quote)
     254  {
     255    size_t i;
     256    size_t len = 0;
     257    size_t orig_buffersize = 0;
     258    char const *quote_string = 0;
     259    size_t quote_string_len = 0;
     260    bool backslash_escapes = false;
     261    bool unibyte_locale = MB_CUR_MAX == 1;
     262    bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
     263    bool pending_shell_escape_end = false;
     264    bool encountered_single_quote = false;
     265    bool all_c_and_shell_quote_compat = true;
     266  
     267  #define STORE(c) \
     268      do \
     269        { \
     270          if (len < buffersize) \
     271            buffer[len] = (c); \
     272          len++; \
     273        } \
     274      while (0)
     275  
     276  #define START_ESC() \
     277      do \
     278        { \
     279          if (elide_outer_quotes) \
     280            goto force_outer_quoting_style; \
     281          escaping = true; \
     282          if (quoting_style == shell_always_quoting_style \
     283              && ! pending_shell_escape_end) \
     284            { \
     285              STORE ('\''); \
     286              STORE ('$'); \
     287              STORE ('\''); \
     288              pending_shell_escape_end = true; \
     289            } \
     290          STORE ('\\'); \
     291        } \
     292      while (0)
     293  
     294  #define END_ESC() \
     295      do \
     296        { \
     297          if (pending_shell_escape_end && ! escaping) \
     298            { \
     299              STORE ('\''); \
     300              STORE ('\''); \
     301              pending_shell_escape_end = false; \
     302            } \
     303        } \
     304      while (0)
     305  
     306   process_input:
     307  
     308    switch (quoting_style)
     309      {
     310      case c_maybe_quoting_style:
     311        quoting_style = c_quoting_style;
     312        elide_outer_quotes = true;
     313        FALLTHROUGH;
     314      case c_quoting_style:
     315        if (!elide_outer_quotes)
     316          STORE ('"');
     317        backslash_escapes = true;
     318        quote_string = "\"";
     319        quote_string_len = 1;
     320        break;
     321  
     322      case escape_quoting_style:
     323        backslash_escapes = true;
     324        elide_outer_quotes = false;
     325        break;
     326  
     327      case locale_quoting_style:
     328      case clocale_quoting_style:
     329      case custom_quoting_style:
     330        {
     331          if (quoting_style != custom_quoting_style)
     332            {
     333              /* TRANSLATORS:
     334                 Get translations for open and closing quotation marks.
     335                 The message catalog should translate "`" to a left
     336                 quotation mark suitable for the locale, and similarly for
     337                 "'".  For example, a French Unicode local should translate
     338                 these to U+00AB (LEFT-POINTING DOUBLE ANGLE
     339                 QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE
     340                 QUOTATION MARK), respectively.
     341  
     342                 If the catalog has no translation, we will try to
     343                 use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and
     344                 Unicode U+2019 (RIGHT SINGLE QUOTATION MARK).  If the
     345                 current locale is not Unicode, locale_quoting_style
     346                 will quote 'like this', and clocale_quoting_style will
     347                 quote "like this".  You should always include translations
     348                 for "`" and "'" even if U+2018 and U+2019 are appropriate
     349                 for your locale.
     350  
     351                 If you don't know what to put here, please see
     352                 <https://en.wikipedia.org/wiki/Quotation_marks_in_other_languages>
     353                 and use glyphs suitable for your language.  */
     354              left_quote = gettext_quote (N_("`"), quoting_style);
     355              right_quote = gettext_quote (N_("'"), quoting_style);
     356            }
     357          if (!elide_outer_quotes)
     358            for (quote_string = left_quote; *quote_string; quote_string++)
     359              STORE (*quote_string);
     360          backslash_escapes = true;
     361          quote_string = right_quote;
     362          quote_string_len = strlen (quote_string);
     363        }
     364        break;
     365  
     366      case shell_escape_quoting_style:
     367        backslash_escapes = true;
     368        FALLTHROUGH;
     369      case shell_quoting_style:
     370        elide_outer_quotes = true;
     371        FALLTHROUGH;
     372      case shell_escape_always_quoting_style:
     373        if (!elide_outer_quotes)
     374          backslash_escapes = true;
     375        FALLTHROUGH;
     376      case shell_always_quoting_style:
     377        quoting_style = shell_always_quoting_style;
     378        if (!elide_outer_quotes)
     379          STORE ('\'');
     380        quote_string = "'";
     381        quote_string_len = 1;
     382        break;
     383  
     384      case literal_quoting_style:
     385        elide_outer_quotes = false;
     386        break;
     387  
     388      default:
     389        abort ();
     390      }
     391  
     392    for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
     393      {
     394        unsigned char c;
     395        unsigned char esc;
     396        bool is_right_quote = false;
     397        bool escaping = false;
     398        bool c_and_shell_quote_compat = false;
     399  
     400        if (backslash_escapes
     401            && quoting_style != shell_always_quoting_style
     402            && quote_string_len
     403            && (i + quote_string_len
     404                <= (argsize == SIZE_MAX && 1 < quote_string_len
     405                    /* Use strlen only if we must: when argsize is SIZE_MAX,
     406                       and when the quote string is more than 1 byte long.
     407                       If we do call strlen, save the result.  */
     408                    ? (argsize = strlen (arg)) : argsize))
     409            && memcmp (arg + i, quote_string, quote_string_len) == 0)
     410          {
     411            if (elide_outer_quotes)
     412              goto force_outer_quoting_style;
     413            is_right_quote = true;
     414          }
     415  
     416        c = arg[i];
     417        switch (c)
     418          {
     419          case '\0':
     420            if (backslash_escapes)
     421              {
     422                START_ESC ();
     423                /* If quote_string were to begin with digits, we'd need to
     424                   test for the end of the arg as well.  However, it's
     425                   hard to imagine any locale that would use digits in
     426                   quotes, and set_custom_quoting is documented not to
     427                   accept them.  Use only a single \0 with shell-escape
     428                   as currently digits are not printed within $'...'  */
     429                if (quoting_style != shell_always_quoting_style
     430                    && i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
     431                  {
     432                    STORE ('0');
     433                    STORE ('0');
     434                  }
     435                c = '0';
     436                /* We don't have to worry that this last '0' will be
     437                   backslash-escaped because, again, quote_string should
     438                   not start with it and because quote_these_too is
     439                   documented as not accepting it.  */
     440              }
     441            else if (flags & QA_ELIDE_NULL_BYTES)
     442              continue;
     443            break;
     444  
     445          case '?':
     446            switch (quoting_style)
     447              {
     448              case shell_always_quoting_style:
     449                if (elide_outer_quotes)
     450                  goto force_outer_quoting_style;
     451                break;
     452  
     453              case c_quoting_style:
     454                if ((flags & QA_SPLIT_TRIGRAPHS)
     455                    && i + 2 < argsize && arg[i + 1] == '?')
     456                  switch (arg[i + 2])
     457                    {
     458                    case '!': case '\'':
     459                    case '(': case ')': case '-': case '/':
     460                    case '<': case '=': case '>':
     461                      /* Escape the second '?' in what would otherwise be
     462                         a trigraph.  */
     463                      if (elide_outer_quotes)
     464                        goto force_outer_quoting_style;
     465                      c = arg[i + 2];
     466                      i += 2;
     467                      STORE ('?');
     468                      STORE ('"');
     469                      STORE ('"');
     470                      STORE ('?');
     471                      break;
     472  
     473                    default:
     474                      break;
     475                    }
     476                break;
     477  
     478              default:
     479                break;
     480              }
     481            break;
     482  
     483          case '\a': esc = 'a'; goto c_escape;
     484          case '\b': esc = 'b'; goto c_escape;
     485          case '\f': esc = 'f'; goto c_escape;
     486          case '\n': esc = 'n'; goto c_and_shell_escape;
     487          case '\r': esc = 'r'; goto c_and_shell_escape;
     488          case '\t': esc = 't'; goto c_and_shell_escape;
     489          case '\v': esc = 'v'; goto c_escape;
     490          case '\\': esc = c;
     491            /* Never need to escape '\' in shell case.  */
     492            if (quoting_style == shell_always_quoting_style)
     493              {
     494                if (elide_outer_quotes)
     495                  goto force_outer_quoting_style;
     496                goto store_c;
     497              }
     498  
     499            /* No need to escape the escape if we are trying to elide
     500               outer quotes and nothing else is problematic.  */
     501            if (backslash_escapes && elide_outer_quotes && quote_string_len)
     502              goto store_c;
     503  
     504          c_and_shell_escape:
     505            if (quoting_style == shell_always_quoting_style
     506                && elide_outer_quotes)
     507              goto force_outer_quoting_style;
     508            /* fall through */
     509          c_escape:
     510            if (backslash_escapes)
     511              {
     512                c = esc;
     513                goto store_escape;
     514              }
     515            break;
     516  
     517          case '{': case '}': /* sometimes special if isolated */
     518            if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
     519              break;
     520            FALLTHROUGH;
     521          case '#': case '~':
     522            if (i != 0)
     523              break;
     524            FALLTHROUGH;
     525          case ' ':
     526            c_and_shell_quote_compat = true;
     527            FALLTHROUGH;
     528          case '!': /* special in bash */
     529          case '"': case '$': case '&':
     530          case '(': case ')': case '*': case ';':
     531          case '<':
     532          case '=': /* sometimes special in 0th or (with "set -k") later args */
     533          case '>': case '[':
     534          case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
     535          case '`': case '|':
     536            /* A shell special character.  In theory, '$' and '`' could
     537               be the first bytes of multibyte characters, which means
     538               we should check them with mbrtowc, but in practice this
     539               doesn't happen so it's not worth worrying about.  */
     540            if (quoting_style == shell_always_quoting_style
     541                && elide_outer_quotes)
     542              goto force_outer_quoting_style;
     543            break;
     544  
     545          case '\'':
     546            encountered_single_quote = true;
     547            c_and_shell_quote_compat = true;
     548            if (quoting_style == shell_always_quoting_style)
     549              {
     550                if (elide_outer_quotes)
     551                  goto force_outer_quoting_style;
     552  
     553                if (buffersize && ! orig_buffersize)
     554                  {
     555                    /* Just scan string to see if supports a more concise
     556                       representation, rather than writing a longer string
     557                       but returning the length of the more concise form.  */
     558                    orig_buffersize = buffersize;
     559                    buffersize = 0;
     560                  }
     561  
     562                STORE ('\'');
     563                STORE ('\\');
     564                STORE ('\'');
     565                pending_shell_escape_end = false;
     566              }
     567            break;
     568  
     569          case '%': case '+': case ',': case '-': case '.': case '/':
     570          case '0': case '1': case '2': case '3': case '4': case '5':
     571          case '6': case '7': case '8': case '9': case ':':
     572          case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
     573          case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
     574          case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
     575          case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
     576          case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
     577          case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
     578          case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
     579          case 'o': case 'p': case 'q': case 'r': case 's': case 't':
     580          case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
     581            /* These characters don't cause problems, no matter what the
     582               quoting style is.  They cannot start multibyte sequences.
     583               A digit or a special letter would cause trouble if it
     584               appeared at the beginning of quote_string because we'd then
     585               escape by prepending a backslash.  However, it's hard to
     586               imagine any locale that would use digits or letters as
     587               quotes, and set_custom_quoting is documented not to accept
     588               them.  Also, a digit or a special letter would cause
     589               trouble if it appeared in quote_these_too, but that's also
     590               documented as not accepting them.  */
     591            c_and_shell_quote_compat = true;
     592            break;
     593  
     594          default:
     595            /* If we have a multibyte sequence, copy it until we reach
     596               its end, find an error, or come back to the initial shift
     597               state.  For C-like styles, if the sequence has
     598               unprintable characters, escape the whole sequence, since
     599               we can't easily escape single characters within it.  */
     600            {
     601              /* Length of multibyte sequence found so far.  */
     602              size_t m;
     603  
     604              bool printable;
     605  
     606              if (unibyte_locale)
     607                {
     608                  m = 1;
     609                  printable = isprint (c) != 0;
     610                }
     611              else
     612                {
     613                  mbstate_t mbstate;
     614                  memset (&mbstate, 0, sizeof mbstate);
     615  
     616                  m = 0;
     617                  printable = true;
     618                  if (argsize == SIZE_MAX)
     619                    argsize = strlen (arg);
     620  
     621                  do
     622                    {
     623                      wchar_t w;
     624                      size_t bytes = mbrtowc (&w, &arg[i + m],
     625                                              argsize - (i + m), &mbstate);
     626                      if (bytes == 0)
     627                        break;
     628                      else if (bytes == (size_t) -1)
     629                        {
     630                          printable = false;
     631                          break;
     632                        }
     633                      else if (bytes == (size_t) -2)
     634                        {
     635                          printable = false;
     636                          while (i + m < argsize && arg[i + m])
     637                            m++;
     638                          break;
     639                        }
     640                      else
     641                        {
     642                          /* Work around a bug with older shells that "see" a '\'
     643                             that is really the 2nd byte of a multibyte character.
     644                             In practice the problem is limited to ASCII
     645                             chars >= '@' that are shell special chars.  */
     646                          if ('[' == 0x5b && elide_outer_quotes
     647                              && quoting_style == shell_always_quoting_style)
     648                            {
     649                              size_t j;
     650                              for (j = 1; j < bytes; j++)
     651                                switch (arg[i + m + j])
     652                                  {
     653                                  case '[': case '\\': case '^':
     654                                  case '`': case '|':
     655                                    goto force_outer_quoting_style;
     656  
     657                                  default:
     658                                    break;
     659                                  }
     660                            }
     661  
     662                          if (! iswprint (w))
     663                            printable = false;
     664                          m += bytes;
     665                        }
     666                    }
     667                  while (! mbsinit (&mbstate));
     668                }
     669  
     670              c_and_shell_quote_compat = printable;
     671  
     672              if (1 < m || (backslash_escapes && ! printable))
     673                {
     674                  /* Output a multibyte sequence, or an escaped
     675                     unprintable unibyte character.  */
     676                  size_t ilim = i + m;
     677  
     678                  for (;;)
     679                    {
     680                      if (backslash_escapes && ! printable)
     681                        {
     682                          START_ESC ();
     683                          STORE ('0' + (c >> 6));
     684                          STORE ('0' + ((c >> 3) & 7));
     685                          c = '0' + (c & 7);
     686                        }
     687                      else if (is_right_quote)
     688                        {
     689                          STORE ('\\');
     690                          is_right_quote = false;
     691                        }
     692                      if (ilim <= i + 1)
     693                        break;
     694                      END_ESC ();
     695                      STORE (c);
     696                      c = arg[++i];
     697                    }
     698  
     699                  goto store_c;
     700                }
     701            }
     702          }
     703  
     704        if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
     705                || elide_outer_quotes)
     706               && quote_these_too
     707               && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
     708            && !is_right_quote)
     709          goto store_c;
     710  
     711      store_escape:
     712        START_ESC ();
     713  
     714      store_c:
     715        END_ESC ();
     716        STORE (c);
     717  
     718        if (! c_and_shell_quote_compat)
     719          all_c_and_shell_quote_compat = false;
     720      }
     721  
     722    if (len == 0 && quoting_style == shell_always_quoting_style
     723        && elide_outer_quotes)
     724      goto force_outer_quoting_style;
     725  
     726    /* Single shell quotes (') are commonly enough used as an apostrophe,
     727       that we attempt to minimize the quoting in this case.  Note itʼs
     728       better to use the apostrophe modifier "\u02BC" if possible, as that
     729       renders better and works with the word match regex \W+ etc.  */
     730    if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
     731        && encountered_single_quote)
     732      {
     733        if (all_c_and_shell_quote_compat)
     734          return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
     735                                           c_quoting_style,
     736                                           flags, quote_these_too,
     737                                           left_quote, right_quote);
     738        else if (! buffersize && orig_buffersize)
     739          {
     740            /* Disable read-only scan, and reprocess to write quoted string.  */
     741            buffersize = orig_buffersize;
     742            len = 0;
     743            goto process_input;
     744          }
     745      }
     746  
     747    if (quote_string && !elide_outer_quotes)
     748      for (; *quote_string; quote_string++)
     749        STORE (*quote_string);
     750  
     751    if (len < buffersize)
     752      buffer[len] = '\0';
     753    return len;
     754  
     755   force_outer_quoting_style:
     756    /* Don't reuse quote_these_too, since the addition of outer quotes
     757       sufficiently quotes the specified characters.  */
     758    if (quoting_style == shell_always_quoting_style && backslash_escapes)
     759      quoting_style = shell_escape_always_quoting_style;
     760    return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
     761                                     quoting_style,
     762                                     flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
     763                                     left_quote, right_quote);
     764  }
     765  
     766  /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
     767     argument ARG (of size ARGSIZE), using O to control quoting.
     768     If O is null, use the default.
     769     Terminate the output with a null character, and return the written
     770     size of the output, not counting the terminating null.
     771     If BUFFERSIZE is too small to store the output string, return the
     772     value that would have been returned had BUFFERSIZE been large enough.
     773     If ARGSIZE is SIZE_MAX, use the string length of the argument for
     774     ARGSIZE.  */
     775  size_t
     776  quotearg_buffer (char *buffer, size_t buffersize,
     777                   char const *arg, size_t argsize,
     778                   struct quoting_options const *o)
     779  {
     780    struct quoting_options const *p = o ? o : &default_quoting_options;
     781    int e = errno;
     782    size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
     783                                         p->style, p->flags, p->quote_these_too,
     784                                         p->left_quote, p->right_quote);
     785    errno = e;
     786    return r;
     787  }
     788  
     789  char *
     790  quotearg_alloc (char const *arg, size_t argsize,
     791                  struct quoting_options const *o)
     792  {
     793    return quotearg_alloc_mem (arg, argsize, NULL, o);
     794  }
     795  
     796  /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
     797     allocated storage containing the quoted string, and store the
     798     resulting size into *SIZE, if non-NULL.  The result can contain
     799     embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
     800     NULL, and set_quoting_flags has not set the null byte elision
     801     flag.  */
     802  char *
     803  quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
     804                      struct quoting_options const *o)
     805  {
     806    struct quoting_options const *p = o ? o : &default_quoting_options;
     807    int e = errno;
     808    /* Elide embedded null bytes if we can't return a size.  */
     809    int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
     810    size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
     811                                               flags, p->quote_these_too,
     812                                               p->left_quote,
     813                                               p->right_quote) + 1;
     814    char *buf = xcharalloc (bufsize);
     815    quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
     816                              p->quote_these_too,
     817                              p->left_quote, p->right_quote);
     818    errno = e;
     819    if (size)
     820      *size = bufsize - 1;
     821    return buf;
     822  }
     823  
     824  /* A storage slot with size and pointer to a value.  */
     825  struct slotvec
     826  {
     827    size_t size;
     828    char *val;
     829  };
     830  
     831  /* Preallocate a slot 0 buffer, so that the caller can always quote
     832     one small component of a "memory exhausted" message in slot 0.  */
     833  static char slot0[256];
     834  static int nslots = 1;
     835  static struct slotvec slotvec0 = {sizeof slot0, slot0};
     836  static struct slotvec *slotvec = &slotvec0;
     837  
     838  void
     839  quotearg_free (void)
     840  {
     841    struct slotvec *sv = slotvec;
     842    int i;
     843    for (i = 1; i < nslots; i++)
     844      free (sv[i].val);
     845    if (sv[0].val != slot0)
     846      {
     847        free (sv[0].val);
     848        slotvec0.size = sizeof slot0;
     849        slotvec0.val = slot0;
     850      }
     851    if (sv != &slotvec0)
     852      {
     853        free (sv);
     854        slotvec = &slotvec0;
     855      }
     856    nslots = 1;
     857  }
     858  
     859  /* Use storage slot N to return a quoted version of argument ARG.
     860     ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
     861     null-terminated string.
     862     OPTIONS specifies the quoting options.
     863     The returned value points to static storage that can be
     864     reused by the next call to this function with the same value of N.
     865     N must be nonnegative; it is typically small, and must be
     866     less than MIN (INT_MAX, IDX_MAX).  The type of N is signed
     867     to allow for future extensions (using negative values).  */
     868  static char *
     869  quotearg_n_options (int n, char const *arg, size_t argsize,
     870                      struct quoting_options const *options)
     871  {
     872    int e = errno;
     873  
     874    struct slotvec *sv = slotvec;
     875  
     876    int nslots_max = MIN (INT_MAX, IDX_MAX);
     877    if (! (0 <= n && n < nslots_max))
     878      abort ();
     879  
     880    if (nslots <= n)
     881      {
     882        bool preallocated = (sv == &slotvec0);
     883        idx_t new_nslots = nslots;
     884  
     885        slotvec = sv = xpalloc (preallocated ? NULL : sv, &new_nslots,
     886                                n - nslots + 1, nslots_max, sizeof *sv);
     887        if (preallocated)
     888          *sv = slotvec0;
     889        memset (sv + nslots, 0, (new_nslots - nslots) * sizeof *sv);
     890        nslots = new_nslots;
     891      }
     892  
     893    {
     894      size_t size = sv[n].size;
     895      char *val = sv[n].val;
     896      /* Elide embedded null bytes since we don't return a size.  */
     897      int flags = options->flags | QA_ELIDE_NULL_BYTES;
     898      size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
     899                                               options->style, flags,
     900                                               options->quote_these_too,
     901                                               options->left_quote,
     902                                               options->right_quote);
     903  
     904      if (size <= qsize)
     905        {
     906          sv[n].size = size = qsize + 1;
     907          if (val != slot0)
     908            free (val);
     909          sv[n].val = val = xcharalloc (size);
     910          quotearg_buffer_restyled (val, size, arg, argsize, options->style,
     911                                    flags, options->quote_these_too,
     912                                    options->left_quote,
     913                                    options->right_quote);
     914        }
     915  
     916      errno = e;
     917      return val;
     918    }
     919  }
     920  
     921  char *
     922  quotearg_n (int n, char const *arg)
     923  {
     924    return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
     925  }
     926  
     927  char *
     928  quotearg_n_mem (int n, char const *arg, size_t argsize)
     929  {
     930    return quotearg_n_options (n, arg, argsize, &default_quoting_options);
     931  }
     932  
     933  char *
     934  quotearg (char const *arg)
     935  {
     936    return quotearg_n (0, arg);
     937  }
     938  
     939  char *
     940  quotearg_mem (char const *arg, size_t argsize)
     941  {
     942    return quotearg_n_mem (0, arg, argsize);
     943  }
     944  
     945  char *
     946  quotearg_n_style (int n, enum quoting_style s, char const *arg)
     947  {
     948    struct quoting_options const o = quoting_options_from_style (s);
     949    return quotearg_n_options (n, arg, SIZE_MAX, &o);
     950  }
     951  
     952  char *
     953  quotearg_n_style_mem (int n, enum quoting_style s,
     954                        char const *arg, size_t argsize)
     955  {
     956    struct quoting_options const o = quoting_options_from_style (s);
     957    return quotearg_n_options (n, arg, argsize, &o);
     958  }
     959  
     960  char *
     961  quotearg_style (enum quoting_style s, char const *arg)
     962  {
     963    return quotearg_n_style (0, s, arg);
     964  }
     965  
     966  char *
     967  quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
     968  {
     969    return quotearg_n_style_mem (0, s, arg, argsize);
     970  }
     971  
     972  char *
     973  quotearg_char_mem (char const *arg, size_t argsize, char ch)
     974  {
     975    struct quoting_options options;
     976    options = default_quoting_options;
     977    set_char_quoting (&options, ch, 1);
     978    return quotearg_n_options (0, arg, argsize, &options);
     979  }
     980  
     981  char *
     982  quotearg_char (char const *arg, char ch)
     983  {
     984    return quotearg_char_mem (arg, SIZE_MAX, ch);
     985  }
     986  
     987  char *
     988  quotearg_colon (char const *arg)
     989  {
     990    return quotearg_char (arg, ':');
     991  }
     992  
     993  char *
     994  quotearg_colon_mem (char const *arg, size_t argsize)
     995  {
     996    return quotearg_char_mem (arg, argsize, ':');
     997  }
     998  
     999  char *
    1000  quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
    1001  {
    1002    struct quoting_options options;
    1003    options = quoting_options_from_style (s);
    1004    set_char_quoting (&options, ':', 1);
    1005    return quotearg_n_options (n, arg, SIZE_MAX, &options);
    1006  }
    1007  
    1008  char *
    1009  quotearg_n_custom (int n, char const *left_quote,
    1010                     char const *right_quote, char const *arg)
    1011  {
    1012    return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
    1013                                  SIZE_MAX);
    1014  }
    1015  
    1016  char *
    1017  quotearg_n_custom_mem (int n, char const *left_quote,
    1018                         char const *right_quote,
    1019                         char const *arg, size_t argsize)
    1020  {
    1021    struct quoting_options o = default_quoting_options;
    1022    set_custom_quoting (&o, left_quote, right_quote);
    1023    return quotearg_n_options (n, arg, argsize, &o);
    1024  }
    1025  
    1026  char *
    1027  quotearg_custom (char const *left_quote, char const *right_quote,
    1028                   char const *arg)
    1029  {
    1030    return quotearg_n_custom (0, left_quote, right_quote, arg);
    1031  }
    1032  
    1033  char *
    1034  quotearg_custom_mem (char const *left_quote, char const *right_quote,
    1035                       char const *arg, size_t argsize)
    1036  {
    1037    return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
    1038                                  argsize);
    1039  }
    1040  
    1041  
    1042  /* The quoting option used by the functions of quote.h.  */
    1043  struct quoting_options quote_quoting_options =
    1044    {
    1045      locale_quoting_style,
    1046      0,
    1047      { 0 },
    1048      NULL, NULL
    1049    };
    1050  
    1051  char const *
    1052  quote_n_mem (int n, char const *arg, size_t argsize)
    1053  {
    1054    return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
    1055  }
    1056  
    1057  char const *
    1058  quote_mem (char const *arg, size_t argsize)
    1059  {
    1060    return quote_n_mem (0, arg, argsize);
    1061  }
    1062  
    1063  char const *
    1064  quote_n (int n, char const *arg)
    1065  {
    1066    return quote_n_mem (n, arg, SIZE_MAX);
    1067  }
    1068  
    1069  char const *
    1070  quote (char const *arg)
    1071  {
    1072    return quote_n (0, arg);
    1073  }
    1074  
    1075  /*
    1076   * Hey Emacs!
    1077   * Local Variables:
    1078   * coding: utf-8
    1079   * End:
    1080   */