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