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