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