(root)/
bison-3.8.2/
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  char *
     791  quotearg_alloc (char const *arg, size_t argsize,
     792                  struct quoting_options const *o)
     793  {
     794    return quotearg_alloc_mem (arg, argsize, NULL, o);
     795  }
     796  
     797  /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
     798     allocated storage containing the quoted string, and store the
     799     resulting size into *SIZE, if non-NULL.  The result can contain
     800     embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
     801     NULL, and set_quoting_flags has not set the null byte elision
     802     flag.  */
     803  char *
     804  quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
     805                      struct quoting_options const *o)
     806  {
     807    struct quoting_options const *p = o ? o : &default_quoting_options;
     808    int e = errno;
     809    /* Elide embedded null bytes if we can't return a size.  */
     810    int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
     811    size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
     812                                               flags, p->quote_these_too,
     813                                               p->left_quote,
     814                                               p->right_quote) + 1;
     815    char *buf = xcharalloc (bufsize);
     816    quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
     817                              p->quote_these_too,
     818                              p->left_quote, p->right_quote);
     819    errno = e;
     820    if (size)
     821      *size = bufsize - 1;
     822    return buf;
     823  }
     824  
     825  /* A storage slot with size and pointer to a value.  */
     826  struct slotvec
     827  {
     828    size_t size;
     829    char *val;
     830  };
     831  
     832  /* Preallocate a slot 0 buffer, so that the caller can always quote
     833     one small component of a "memory exhausted" message in slot 0.  */
     834  static char slot0[256];
     835  static int nslots = 1;
     836  static struct slotvec slotvec0 = {sizeof slot0, slot0};
     837  static struct slotvec *slotvec = &slotvec0;
     838  
     839  void
     840  quotearg_free (void)
     841  {
     842    struct slotvec *sv = slotvec;
     843    int i;
     844    for (i = 1; i < nslots; i++)
     845      free (sv[i].val);
     846    if (sv[0].val != slot0)
     847      {
     848        free (sv[0].val);
     849        slotvec0.size = sizeof slot0;
     850        slotvec0.val = slot0;
     851      }
     852    if (sv != &slotvec0)
     853      {
     854        free (sv);
     855        slotvec = &slotvec0;
     856      }
     857    nslots = 1;
     858  }
     859  
     860  /* Use storage slot N to return a quoted version of argument ARG.
     861     ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
     862     null-terminated string.
     863     OPTIONS specifies the quoting options.
     864     The returned value points to static storage that can be
     865     reused by the next call to this function with the same value of N.
     866     N must be nonnegative; it is typically small, and must be
     867     less than MIN (INT_MAX, IDX_MAX).  The type of N is signed
     868     to allow for future extensions (using negative values).  */
     869  static char *
     870  quotearg_n_options (int n, char const *arg, size_t argsize,
     871                      struct quoting_options const *options)
     872  {
     873    int e = errno;
     874  
     875    struct slotvec *sv = slotvec;
     876  
     877    int nslots_max = MIN (INT_MAX, IDX_MAX);
     878    if (! (0 <= n && n < nslots_max))
     879      abort ();
     880  
     881    if (nslots <= n)
     882      {
     883        bool preallocated = (sv == &slotvec0);
     884        idx_t new_nslots = nslots;
     885  
     886        slotvec = sv = xpalloc (preallocated ? NULL : sv, &new_nslots,
     887                                n - nslots + 1, nslots_max, sizeof *sv);
     888        if (preallocated)
     889          *sv = slotvec0;
     890        memset (sv + nslots, 0, (new_nslots - nslots) * sizeof *sv);
     891        nslots = new_nslots;
     892      }
     893  
     894    {
     895      size_t size = sv[n].size;
     896      char *val = sv[n].val;
     897      /* Elide embedded null bytes since we don't return a size.  */
     898      int flags = options->flags | QA_ELIDE_NULL_BYTES;
     899      size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
     900                                               options->style, flags,
     901                                               options->quote_these_too,
     902                                               options->left_quote,
     903                                               options->right_quote);
     904  
     905      if (size <= qsize)
     906        {
     907          sv[n].size = size = qsize + 1;
     908          if (val != slot0)
     909            free (val);
     910          sv[n].val = val = xcharalloc (size);
     911          quotearg_buffer_restyled (val, size, arg, argsize, options->style,
     912                                    flags, options->quote_these_too,
     913                                    options->left_quote,
     914                                    options->right_quote);
     915        }
     916  
     917      errno = e;
     918      return val;
     919    }
     920  }
     921  
     922  char *
     923  quotearg_n (int n, char const *arg)
     924  {
     925    return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
     926  }
     927  
     928  char *
     929  quotearg_n_mem (int n, char const *arg, size_t argsize)
     930  {
     931    return quotearg_n_options (n, arg, argsize, &default_quoting_options);
     932  }
     933  
     934  char *
     935  quotearg (char const *arg)
     936  {
     937    return quotearg_n (0, arg);
     938  }
     939  
     940  char *
     941  quotearg_mem (char const *arg, size_t argsize)
     942  {
     943    return quotearg_n_mem (0, arg, argsize);
     944  }
     945  
     946  char *
     947  quotearg_n_style (int n, enum quoting_style s, char const *arg)
     948  {
     949    struct quoting_options const o = quoting_options_from_style (s);
     950    return quotearg_n_options (n, arg, SIZE_MAX, &o);
     951  }
     952  
     953  char *
     954  quotearg_n_style_mem (int n, enum quoting_style s,
     955                        char const *arg, size_t argsize)
     956  {
     957    struct quoting_options const o = quoting_options_from_style (s);
     958    return quotearg_n_options (n, arg, argsize, &o);
     959  }
     960  
     961  char *
     962  quotearg_style (enum quoting_style s, char const *arg)
     963  {
     964    return quotearg_n_style (0, s, arg);
     965  }
     966  
     967  char *
     968  quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
     969  {
     970    return quotearg_n_style_mem (0, s, arg, argsize);
     971  }
     972  
     973  char *
     974  quotearg_char_mem (char const *arg, size_t argsize, char ch)
     975  {
     976    struct quoting_options options;
     977    options = default_quoting_options;
     978    set_char_quoting (&options, ch, 1);
     979    return quotearg_n_options (0, arg, argsize, &options);
     980  }
     981  
     982  char *
     983  quotearg_char (char const *arg, char ch)
     984  {
     985    return quotearg_char_mem (arg, SIZE_MAX, ch);
     986  }
     987  
     988  char *
     989  quotearg_colon (char const *arg)
     990  {
     991    return quotearg_char (arg, ':');
     992  }
     993  
     994  char *
     995  quotearg_colon_mem (char const *arg, size_t argsize)
     996  {
     997    return quotearg_char_mem (arg, argsize, ':');
     998  }
     999  
    1000  char *
    1001  quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
    1002  {
    1003    struct quoting_options options;
    1004    options = quoting_options_from_style (s);
    1005    set_char_quoting (&options, ':', 1);
    1006    return quotearg_n_options (n, arg, SIZE_MAX, &options);
    1007  }
    1008  
    1009  char *
    1010  quotearg_n_custom (int n, char const *left_quote,
    1011                     char const *right_quote, char const *arg)
    1012  {
    1013    return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
    1014                                  SIZE_MAX);
    1015  }
    1016  
    1017  char *
    1018  quotearg_n_custom_mem (int n, char const *left_quote,
    1019                         char const *right_quote,
    1020                         char const *arg, size_t argsize)
    1021  {
    1022    struct quoting_options o = default_quoting_options;
    1023    set_custom_quoting (&o, left_quote, right_quote);
    1024    return quotearg_n_options (n, arg, argsize, &o);
    1025  }
    1026  
    1027  char *
    1028  quotearg_custom (char const *left_quote, char const *right_quote,
    1029                   char const *arg)
    1030  {
    1031    return quotearg_n_custom (0, left_quote, right_quote, arg);
    1032  }
    1033  
    1034  char *
    1035  quotearg_custom_mem (char const *left_quote, char const *right_quote,
    1036                       char const *arg, size_t argsize)
    1037  {
    1038    return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
    1039                                  argsize);
    1040  }
    1041  
    1042  
    1043  /* The quoting option used by the functions of quote.h.  */
    1044  struct quoting_options quote_quoting_options =
    1045    {
    1046      locale_quoting_style,
    1047      0,
    1048      { 0 },
    1049      NULL, NULL
    1050    };
    1051  
    1052  char const *
    1053  quote_n_mem (int n, char const *arg, size_t argsize)
    1054  {
    1055    return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
    1056  }
    1057  
    1058  char const *
    1059  quote_mem (char const *arg, size_t argsize)
    1060  {
    1061    return quote_n_mem (0, arg, argsize);
    1062  }
    1063  
    1064  char const *
    1065  quote_n (int n, char const *arg)
    1066  {
    1067    return quote_n_mem (n, arg, SIZE_MAX);
    1068  }
    1069  
    1070  char const *
    1071  quote (char const *arg)
    1072  {
    1073    return quote_n (0, arg);
    1074  }
    1075  
    1076  /*
    1077   * Hey Emacs!
    1078   * Local Variables:
    1079   * coding: utf-8
    1080   * End:
    1081   */