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