openat: don’t close (-1)
[gnulib.git] / lib / quotearg.c
blob00977f5714f8a461f9ad294698141f22d00846c3
1 /* quotearg.c - quote arguments for output
3 Copyright (C) 1998-2002, 2004-2024 Free Software Foundation, Inc.
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.
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.
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/>. */
18 /* Written by Paul Eggert <eggert@twinsun.com> */
20 #include <config.h>
22 /* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that
23 the quoting_options_from_style function might be candidate for
24 attribute 'pure' */
25 #if _GL_GNUC_PREREQ (4, 6)
26 # pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
27 #endif
29 #include "quotearg.h"
30 #include "quote.h"
32 #include "attribute.h"
33 #include "minmax.h"
34 #include "xalloc.h"
35 #include "c-strcaseeq.h"
36 #include "localcharset.h"
38 #include <ctype.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdint.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <uchar.h>
45 #include <wchar.h>
47 #include "gettext.h"
48 #define _(msgid) gettext (msgid)
49 #define N_(msgid) msgid
51 #ifndef SIZE_MAX
52 # define SIZE_MAX ((size_t) -1)
53 #endif
55 #define INT_BITS (sizeof (int) * CHAR_BIT)
57 struct quoting_options
59 /* Basic quoting style. */
60 enum quoting_style style;
62 /* Additional flags. Bitwise combination of enum quoting_flags. */
63 int flags;
65 /* Quote the characters indicated by this bit vector even if the
66 quoting style would not normally require them to be quoted. */
67 unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
69 /* The left quote for custom_quoting_style. */
70 char const *left_quote;
72 /* The right quote for custom_quoting_style. */
73 char const *right_quote;
76 /* Names of quoting styles. */
77 char const *const quoting_style_args[] =
79 "literal",
80 "shell",
81 "shell-always",
82 "shell-escape",
83 "shell-escape-always",
84 "c",
85 "c-maybe",
86 "escape",
87 "locale",
88 "clocale",
89 NULL
92 /* Correspondences to quoting style names. */
93 enum quoting_style const quoting_style_vals[] =
95 literal_quoting_style,
96 shell_quoting_style,
97 shell_always_quoting_style,
98 shell_escape_quoting_style,
99 shell_escape_always_quoting_style,
100 c_quoting_style,
101 c_maybe_quoting_style,
102 escape_quoting_style,
103 locale_quoting_style,
104 clocale_quoting_style
107 /* The default quoting options. */
108 static struct quoting_options default_quoting_options;
110 /* Allocate a new set of quoting options, with contents initially identical
111 to O if O is not null, or to the default if O is null.
112 It is the caller's responsibility to free the result. */
113 struct quoting_options *
114 clone_quoting_options (struct quoting_options *o)
116 int e = errno;
117 struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
118 sizeof *o);
119 errno = e;
120 return p;
123 /* Get the value of O's quoting style. If O is null, use the default. */
124 enum quoting_style
125 get_quoting_style (struct quoting_options const *o)
127 return (o ? o : &default_quoting_options)->style;
130 /* In O (or in the default if O is null),
131 set the value of the quoting style to S. */
132 void
133 set_quoting_style (struct quoting_options *o, enum quoting_style s)
135 (o ? o : &default_quoting_options)->style = s;
138 /* In O (or in the default if O is null),
139 set the value of the quoting options for character C to I.
140 Return the old value. Currently, the only values defined for I are
141 0 (the default) and 1 (which means to quote the character even if
142 it would not otherwise be quoted). */
144 set_char_quoting (struct quoting_options *o, char c, int i)
146 unsigned char uc = c;
147 unsigned int *p =
148 (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
149 int shift = uc % INT_BITS;
150 int r = (*p >> shift) & 1;
151 *p ^= ((i & 1) ^ r) << shift;
152 return r;
155 /* In O (or in the default if O is null),
156 set the value of the quoting options flag to I, which can be a
157 bitwise combination of enum quoting_flags, or 0 for default
158 behavior. Return the old value. */
160 set_quoting_flags (struct quoting_options *o, int i)
162 int r;
163 if (!o)
164 o = &default_quoting_options;
165 r = o->flags;
166 o->flags = i;
167 return r;
170 void
171 set_custom_quoting (struct quoting_options *o,
172 char const *left_quote, char const *right_quote)
174 if (!o)
175 o = &default_quoting_options;
176 o->style = custom_quoting_style;
177 if (!left_quote || !right_quote)
178 abort ();
179 o->left_quote = left_quote;
180 o->right_quote = right_quote;
183 /* Return quoting options for STYLE, with no extra quoting. */
184 static struct quoting_options /* NOT PURE!! */
185 quoting_options_from_style (enum quoting_style style)
187 struct quoting_options o = { literal_quoting_style, 0, { 0 }, NULL, NULL };
188 if (style == custom_quoting_style)
189 abort ();
190 o.style = style;
191 return o;
194 /* MSGID approximates a quotation mark. Return its translation if it
195 has one; otherwise, return either it or "\"", depending on S.
197 S is either clocale_quoting_style or locale_quoting_style. */
198 static char const *
199 gettext_quote (char const *msgid, enum quoting_style s)
201 char const *translation = _(msgid);
202 char const *locale_code;
204 if (translation != msgid)
205 return translation;
207 /* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019.
208 Here is a list of other locales that include U+2018 and U+2019:
210 ISO-8859-7 0xA1 KOI8-T 0x91
211 CP869 0x8B CP874 0x91
212 CP932 0x81 0x65 CP936 0xA1 0xAE
213 CP949 0xA1 0xAE CP950 0xA1 0xA5
214 CP1250 0x91 CP1251 0x91
215 CP1252 0x91 CP1253 0x91
216 CP1254 0x91 CP1255 0x91
217 CP1256 0x91 CP1257 0x91
218 EUC-JP 0xA1 0xC6 EUC-KR 0xA1 0xAE
219 EUC-TW 0xA1 0xE4 BIG5 0xA1 0xA5
220 BIG5-HKSCS 0xA1 0xA5 EUC-CN 0xA1 0xAE
221 GBK 0xA1 0xAE Georgian-PS 0x91
222 PT154 0x91
224 None of these is still in wide use; using iconv is overkill. */
225 locale_code = locale_charset ();
226 if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0))
227 return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99";
228 if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0))
229 return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf";
231 return (s == clocale_quoting_style ? "\"" : "'");
234 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
235 argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
236 QUOTE_THESE_TOO to control quoting.
237 Terminate the output with a null character, and return the written
238 size of the output, not counting the terminating null.
239 If BUFFERSIZE is too small to store the output string, return the
240 value that would have been returned had BUFFERSIZE been large enough.
241 If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
243 This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
244 ARGSIZE, O), except it breaks O into its component pieces and is
245 not careful about errno. */
247 static size_t
248 quotearg_buffer_restyled (char *buffer, size_t buffersize,
249 char const *arg, size_t argsize,
250 enum quoting_style quoting_style, int flags,
251 unsigned int const *quote_these_too,
252 char const *left_quote,
253 char const *right_quote)
255 size_t i;
256 size_t len = 0;
257 size_t orig_buffersize = 0;
258 char const *quote_string = NULL;
259 size_t quote_string_len = 0;
260 bool backslash_escapes = false;
261 bool unibyte_locale = MB_CUR_MAX == 1;
262 bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
263 bool encountered_single_quote = false;
264 bool all_c_and_shell_quote_compat = true;
266 #define STORE(c) \
267 do \
269 if (len < buffersize) \
270 buffer[len] = (c); \
271 len++; \
273 while (0)
275 #define START_ESC() \
276 do \
278 if (elide_outer_quotes) \
279 goto force_outer_quoting_style; \
280 escaping = true; \
281 if (quoting_style == shell_always_quoting_style \
282 && ! pending_shell_escape_end) \
284 STORE ('\''); \
285 STORE ('$'); \
286 STORE ('\''); \
287 pending_shell_escape_end = true; \
289 STORE ('\\'); \
291 while (0)
293 #define END_ESC() \
294 do \
296 if (pending_shell_escape_end && ! escaping) \
298 STORE ('\''); \
299 STORE ('\''); \
300 pending_shell_escape_end = false; \
303 while (0)
305 process_input: ;
306 bool pending_shell_escape_end = false;
308 switch (quoting_style)
310 case c_maybe_quoting_style:
311 quoting_style = c_quoting_style;
312 elide_outer_quotes = true;
313 FALLTHROUGH;
314 case c_quoting_style:
315 if (!elide_outer_quotes)
316 STORE ('"');
317 backslash_escapes = true;
318 quote_string = "\"";
319 quote_string_len = 1;
320 break;
322 case escape_quoting_style:
323 backslash_escapes = true;
324 elide_outer_quotes = false;
325 break;
327 case locale_quoting_style:
328 case clocale_quoting_style:
329 case custom_quoting_style:
331 if (quoting_style != custom_quoting_style)
333 /* TRANSLATORS:
334 Get translations for open and closing quotation marks.
335 The message catalog should translate "`" to a left
336 quotation mark suitable for the locale, and similarly for
337 "'". For example, a French Unicode local should translate
338 these to U+00AB (LEFT-POINTING DOUBLE ANGLE
339 QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE
340 QUOTATION MARK), respectively.
342 If the catalog has no translation, we will try to
343 use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and
344 Unicode U+2019 (RIGHT SINGLE QUOTATION MARK). If the
345 current locale is not Unicode, locale_quoting_style
346 will quote 'like this', and clocale_quoting_style will
347 quote "like this". You should always include translations
348 for "`" and "'" even if U+2018 and U+2019 are appropriate
349 for your locale.
351 If you don't know what to put here, please see
352 <https://en.wikipedia.org/wiki/Quotation_marks_in_other_languages>
353 and use glyphs suitable for your language. */
354 left_quote = gettext_quote (N_("`"), quoting_style);
355 right_quote = gettext_quote (N_("'"), quoting_style);
357 if (!elide_outer_quotes)
358 for (quote_string = left_quote; *quote_string; quote_string++)
359 STORE (*quote_string);
360 backslash_escapes = true;
361 quote_string = right_quote;
362 quote_string_len = strlen (quote_string);
364 break;
366 case shell_escape_quoting_style:
367 backslash_escapes = true;
368 FALLTHROUGH;
369 case shell_quoting_style:
370 elide_outer_quotes = true;
371 FALLTHROUGH;
372 case shell_escape_always_quoting_style:
373 if (!elide_outer_quotes)
374 backslash_escapes = true;
375 FALLTHROUGH;
376 case shell_always_quoting_style:
377 quoting_style = shell_always_quoting_style;
378 if (!elide_outer_quotes)
379 STORE ('\'');
380 quote_string = "'";
381 quote_string_len = 1;
382 break;
384 case literal_quoting_style:
385 elide_outer_quotes = false;
386 break;
388 default:
389 abort ();
392 for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
394 unsigned char c;
395 unsigned char esc;
396 bool is_right_quote = false;
397 bool escaping = false;
398 bool c_and_shell_quote_compat = false;
400 if (backslash_escapes
401 && quoting_style != shell_always_quoting_style
402 && quote_string_len
403 && (i + quote_string_len
404 <= (argsize == SIZE_MAX && 1 < quote_string_len
405 /* Use strlen only if we must: when argsize is SIZE_MAX,
406 and when the quote string is more than 1 byte long.
407 If we do call strlen, save the result. */
408 ? (argsize = strlen (arg)) : argsize))
409 && memcmp (arg + i, quote_string, quote_string_len) == 0)
411 if (elide_outer_quotes)
412 goto force_outer_quoting_style;
413 is_right_quote = true;
416 c = arg[i];
417 switch (c)
419 case '\0':
420 if (backslash_escapes)
422 START_ESC ();
423 /* If quote_string were to begin with digits, we'd need to
424 test for the end of the arg as well. However, it's
425 hard to imagine any locale that would use digits in
426 quotes, and set_custom_quoting is documented not to
427 accept them. Use only a single \0 with shell-escape
428 as currently digits are not printed within $'...' */
429 if (quoting_style != shell_always_quoting_style
430 && i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
432 STORE ('0');
433 STORE ('0');
435 c = '0';
436 /* We don't have to worry that this last '0' will be
437 backslash-escaped because, again, quote_string should
438 not start with it and because quote_these_too is
439 documented as not accepting it. */
441 else if (flags & QA_ELIDE_NULL_BYTES)
442 continue;
443 break;
445 case '?':
446 switch (quoting_style)
448 case shell_always_quoting_style:
449 if (elide_outer_quotes)
450 goto force_outer_quoting_style;
451 break;
453 case c_quoting_style:
454 if ((flags & QA_SPLIT_TRIGRAPHS)
455 && i + 2 < argsize && arg[i + 1] == '?')
456 switch (arg[i + 2])
458 case '!': case '\'':
459 case '(': case ')': case '-': case '/':
460 case '<': case '=': case '>':
461 /* Escape the second '?' in what would otherwise be
462 a trigraph. */
463 if (elide_outer_quotes)
464 goto force_outer_quoting_style;
465 c = arg[i + 2];
466 i += 2;
467 STORE ('?');
468 STORE ('"');
469 STORE ('"');
470 STORE ('?');
471 break;
473 default:
474 break;
476 break;
478 default:
479 break;
481 break;
483 case '\a': esc = 'a'; goto c_escape;
484 case '\b': esc = 'b'; goto c_escape;
485 case '\f': esc = 'f'; goto c_escape;
486 case '\n': esc = 'n'; goto c_and_shell_escape;
487 case '\r': esc = 'r'; goto c_and_shell_escape;
488 case '\t': esc = 't'; goto c_and_shell_escape;
489 case '\v': esc = 'v'; goto c_escape;
490 case '\\': esc = c;
491 /* Never need to escape '\' in shell case. */
492 if (quoting_style == shell_always_quoting_style)
494 if (elide_outer_quotes)
495 goto force_outer_quoting_style;
496 goto store_c;
499 /* No need to escape the escape if we are trying to elide
500 outer quotes and nothing else is problematic. */
501 if (backslash_escapes && elide_outer_quotes && quote_string_len)
502 goto store_c;
504 c_and_shell_escape:
505 if (quoting_style == shell_always_quoting_style
506 && elide_outer_quotes)
507 goto force_outer_quoting_style;
508 /* fall through */
509 c_escape:
510 if (backslash_escapes)
512 c = esc;
513 goto store_escape;
515 break;
517 case '{': case '}': /* sometimes special if isolated */
518 if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
519 break;
520 FALLTHROUGH;
521 case '#': case '~':
522 if (i != 0)
523 break;
524 FALLTHROUGH;
525 case ' ':
526 c_and_shell_quote_compat = true;
527 FALLTHROUGH;
528 case '!': /* special in bash */
529 case '"': case '$': case '&':
530 case '(': case ')': case '*': case ';':
531 case '<':
532 case '=': /* sometimes special in 0th or (with "set -k") later args */
533 case '>': case '[':
534 case '^': /* special in old /bin/sh, e.g., Solaris 10 */
535 case '`': case '|':
536 /* A shell special character. */
537 if (quoting_style == shell_always_quoting_style
538 && elide_outer_quotes)
539 goto force_outer_quoting_style;
540 break;
542 case '\'':
543 encountered_single_quote = true;
544 c_and_shell_quote_compat = true;
545 if (quoting_style == shell_always_quoting_style)
547 if (elide_outer_quotes)
548 goto force_outer_quoting_style;
550 if (buffersize && ! orig_buffersize)
552 /* Just scan string to see if supports a more concise
553 representation, rather than writing a longer string
554 but returning the length of the more concise form. */
555 orig_buffersize = buffersize;
556 buffersize = 0;
559 STORE ('\'');
560 STORE ('\\');
561 STORE ('\'');
562 pending_shell_escape_end = false;
564 break;
566 case '%': case '+': case ',': case '-': case '.': case '/':
567 case '0': case '1': case '2': case '3': case '4': case '5':
568 case '6': case '7': case '8': case '9': case ':':
569 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
570 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
571 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
572 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
573 case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
574 case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
575 case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
576 case 'o': case 'p': case 'q': case 'r': case 's': case 't':
577 case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
578 /* These characters don't cause problems, no matter what the
579 quoting style is. They cannot start multibyte sequences.
580 A digit or a special letter would cause trouble if it
581 appeared at the beginning of quote_string because we'd then
582 escape by prepending a backslash. However, it's hard to
583 imagine any locale that would use digits or letters as
584 quotes, and set_custom_quoting is documented not to accept
585 them. Also, a digit or a special letter would cause
586 trouble if it appeared in quote_these_too, but that's also
587 documented as not accepting them. */
588 c_and_shell_quote_compat = true;
589 break;
591 default:
592 /* If we have a multibyte sequence, copy it until we reach
593 its end, find an error, or come back to the initial shift
594 state. For C-like styles, if the sequence has
595 unprintable characters, escape the whole sequence, since
596 we can't easily escape single characters within it. */
598 /* Length of multibyte sequence found so far. */
599 size_t m;
601 bool printable;
603 if (unibyte_locale)
605 m = 1;
606 printable = isprint (c) != 0;
608 else
610 mbstate_t mbstate;
611 mbszero (&mbstate);
613 m = 0;
614 printable = true;
615 if (argsize == SIZE_MAX)
616 argsize = strlen (arg);
618 for (;;)
620 char32_t w;
621 size_t bytes = mbrtoc32 (&w, &arg[i + m],
622 argsize - (i + m), &mbstate);
623 if (bytes == 0)
624 break;
625 else if (bytes == (size_t) -1)
627 printable = false;
628 break;
630 else if (bytes == (size_t) -2)
632 printable = false;
633 while (i + m < argsize && arg[i + m])
634 m++;
635 break;
637 else
639 #if !GNULIB_MBRTOC32_REGULAR
640 if (bytes == (size_t) -3)
641 bytes = 0;
642 #endif
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)
650 size_t j;
651 for (j = 1; j < bytes; j++)
652 switch (arg[i + m + j])
654 case '[': case '\\': case '^':
655 case '`': case '|':
656 goto force_outer_quoting_style;
658 default:
659 break;
663 if (! c32isprint (w))
664 printable = false;
665 m += bytes;
667 #if !GNULIB_MBRTOC32_REGULAR
668 if (mbsinit (&mbstate))
669 #endif
670 break;
674 c_and_shell_quote_compat = printable;
676 if (1 < m || (backslash_escapes && ! printable))
678 /* Output a multibyte sequence, or an escaped
679 unprintable unibyte character. */
680 size_t ilim = i + m;
682 for (;;)
684 if (backslash_escapes && ! printable)
686 START_ESC ();
687 STORE ('0' + (c >> 6));
688 STORE ('0' + ((c >> 3) & 7));
689 c = '0' + (c & 7);
691 else if (is_right_quote)
693 STORE ('\\');
694 is_right_quote = false;
696 if (ilim <= i + 1)
697 break;
698 END_ESC ();
699 STORE (c);
700 c = arg[++i];
703 goto store_c;
708 if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
709 || elide_outer_quotes)
710 && quote_these_too
711 && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
712 && !is_right_quote)
713 goto store_c;
715 store_escape:
716 START_ESC ();
718 store_c:
719 END_ESC ();
720 STORE (c);
722 if (! c_and_shell_quote_compat)
723 all_c_and_shell_quote_compat = false;
726 if (len == 0 && quoting_style == shell_always_quoting_style
727 && elide_outer_quotes)
728 goto force_outer_quoting_style;
730 /* Single shell quotes (') are commonly enough used as an apostrophe,
731 that we attempt to minimize the quoting in this case. Note itĘĽs
732 better to use the apostrophe modifier "\u02BC" if possible, as that
733 renders better and works with the word match regex \W+ etc. */
734 if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
735 && encountered_single_quote)
737 if (all_c_and_shell_quote_compat)
738 return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
739 c_quoting_style,
740 flags, quote_these_too,
741 left_quote, right_quote);
742 else if (! buffersize && orig_buffersize)
744 /* Disable read-only scan, and reprocess to write quoted string. */
745 buffersize = orig_buffersize;
746 len = 0;
747 goto process_input;
751 if (quote_string && !elide_outer_quotes)
752 for (; *quote_string; quote_string++)
753 STORE (*quote_string);
755 if (len < buffersize)
756 buffer[len] = '\0';
757 return len;
759 force_outer_quoting_style:
760 /* Don't reuse quote_these_too, since the addition of outer quotes
761 sufficiently quotes the specified characters. */
762 if (quoting_style == shell_always_quoting_style && backslash_escapes)
763 quoting_style = shell_escape_always_quoting_style;
764 return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
765 quoting_style,
766 flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
767 left_quote, right_quote);
770 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
771 argument ARG (of size ARGSIZE), using O to control quoting.
772 If O is null, use the default.
773 Terminate the output with a null character, and return the written
774 size of the output, not counting the terminating null.
775 If BUFFERSIZE is too small to store the output string, return the
776 value that would have been returned had BUFFERSIZE been large enough.
777 If ARGSIZE is SIZE_MAX, use the string length of the argument for
778 ARGSIZE. */
779 size_t
780 quotearg_buffer (char *buffer, size_t buffersize,
781 char const *arg, size_t argsize,
782 struct quoting_options const *o)
784 struct quoting_options const *p = o ? o : &default_quoting_options;
785 int e = errno;
786 size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
787 p->style, p->flags, p->quote_these_too,
788 p->left_quote, p->right_quote);
789 errno = e;
790 return r;
793 char *
794 quotearg_alloc (char const *arg, size_t argsize,
795 struct quoting_options const *o)
797 return quotearg_alloc_mem (arg, argsize, NULL, o);
800 /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
801 allocated storage containing the quoted string, and store the
802 resulting size into *SIZE, if non-NULL. The result can contain
803 embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
804 NULL, and set_quoting_flags has not set the null byte elision
805 flag. */
806 char *
807 quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
808 struct quoting_options const *o)
810 struct quoting_options const *p = o ? o : &default_quoting_options;
811 int e = errno;
812 /* Elide embedded null bytes if we can't return a size. */
813 int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
814 size_t bufsize = quotearg_buffer_restyled (NULL, 0, arg, argsize, p->style,
815 flags, p->quote_these_too,
816 p->left_quote,
817 p->right_quote) + 1;
818 char *buf = xcharalloc (bufsize);
819 quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
820 p->quote_these_too,
821 p->left_quote, p->right_quote);
822 errno = e;
823 if (size)
824 *size = bufsize - 1;
825 return buf;
828 /* A storage slot with size and pointer to a value. */
829 struct slotvec
831 size_t size;
832 char *val;
835 /* Preallocate a slot 0 buffer, so that the caller can always quote
836 one small component of a "memory exhausted" message in slot 0. */
837 static char slot0[256];
838 static int nslots = 1;
839 static struct slotvec slotvec0 = {sizeof slot0, slot0};
840 static struct slotvec *slotvec = &slotvec0;
842 void
843 quotearg_free (void)
845 struct slotvec *sv = slotvec;
846 int i;
847 for (i = 1; i < nslots; i++)
848 free (sv[i].val);
849 if (sv[0].val != slot0)
851 free (sv[0].val);
852 slotvec0.size = sizeof slot0;
853 slotvec0.val = slot0;
855 if (sv != &slotvec0)
857 free (sv);
858 slotvec = &slotvec0;
860 nslots = 1;
863 /* Use storage slot N to return a quoted version of argument ARG.
864 ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
865 null-terminated string.
866 OPTIONS specifies the quoting options.
867 The returned value points to static storage that can be
868 reused by the next call to this function with the same value of N.
869 N must be nonnegative; it is typically small, and must be
870 less than MIN (INT_MAX, IDX_MAX). The type of N is signed
871 to allow for future extensions (using negative values). */
872 static char *
873 quotearg_n_options (int n, char const *arg, size_t argsize,
874 struct quoting_options const *options)
876 int e = errno;
878 struct slotvec *sv = slotvec;
880 int nslots_max = MIN (INT_MAX, IDX_MAX);
881 if (! (0 <= n && n < nslots_max))
882 abort ();
884 if (nslots <= n)
886 bool preallocated = (sv == &slotvec0);
887 idx_t new_nslots = nslots;
889 slotvec = sv = xpalloc (preallocated ? NULL : sv, &new_nslots,
890 n - nslots + 1, nslots_max, sizeof *sv);
891 if (preallocated)
892 *sv = slotvec0;
893 memset (sv + nslots, 0, (new_nslots - nslots) * sizeof *sv);
894 nslots = new_nslots;
898 size_t size = sv[n].size;
899 char *val = sv[n].val;
900 /* Elide embedded null bytes since we don't return a size. */
901 int flags = options->flags | QA_ELIDE_NULL_BYTES;
902 size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
903 options->style, flags,
904 options->quote_these_too,
905 options->left_quote,
906 options->right_quote);
908 if (size <= qsize)
910 sv[n].size = size = qsize + 1;
911 if (val != slot0)
912 free (val);
913 sv[n].val = val = xcharalloc (size);
914 quotearg_buffer_restyled (val, size, arg, argsize, options->style,
915 flags, options->quote_these_too,
916 options->left_quote,
917 options->right_quote);
920 errno = e;
921 return val;
925 char *
926 quotearg_n (int n, char const *arg)
928 return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
931 char *
932 quotearg_n_mem (int n, char const *arg, size_t argsize)
934 return quotearg_n_options (n, arg, argsize, &default_quoting_options);
937 char *
938 quotearg (char const *arg)
940 return quotearg_n (0, arg);
943 char *
944 quotearg_mem (char const *arg, size_t argsize)
946 return quotearg_n_mem (0, arg, argsize);
949 char *
950 quotearg_n_style (int n, enum quoting_style s, char const *arg)
952 struct quoting_options const o = quoting_options_from_style (s);
953 return quotearg_n_options (n, arg, SIZE_MAX, &o);
956 char *
957 quotearg_n_style_mem (int n, enum quoting_style s,
958 char const *arg, size_t argsize)
960 struct quoting_options const o = quoting_options_from_style (s);
961 return quotearg_n_options (n, arg, argsize, &o);
964 char *
965 quotearg_style (enum quoting_style s, char const *arg)
967 return quotearg_n_style (0, s, arg);
970 char *
971 quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
973 return quotearg_n_style_mem (0, s, arg, argsize);
976 char *
977 quotearg_char_mem (char const *arg, size_t argsize, char ch)
979 struct quoting_options options;
980 options = default_quoting_options;
981 set_char_quoting (&options, ch, 1);
982 return quotearg_n_options (0, arg, argsize, &options);
985 char *
986 quotearg_char (char const *arg, char ch)
988 return quotearg_char_mem (arg, SIZE_MAX, ch);
991 char *
992 quotearg_colon (char const *arg)
994 return quotearg_char (arg, ':');
997 char *
998 quotearg_colon_mem (char const *arg, size_t argsize)
1000 return quotearg_char_mem (arg, argsize, ':');
1003 char *
1004 quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
1006 struct quoting_options options;
1007 options = quoting_options_from_style (s);
1008 set_char_quoting (&options, ':', 1);
1009 return quotearg_n_options (n, arg, SIZE_MAX, &options);
1012 char *
1013 quotearg_n_custom (int n, char const *left_quote,
1014 char const *right_quote, char const *arg)
1016 return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
1017 SIZE_MAX);
1020 char *
1021 quotearg_n_custom_mem (int n, char const *left_quote,
1022 char const *right_quote,
1023 char const *arg, size_t argsize)
1025 struct quoting_options o = default_quoting_options;
1026 set_custom_quoting (&o, left_quote, right_quote);
1027 return quotearg_n_options (n, arg, argsize, &o);
1030 char *
1031 quotearg_custom (char const *left_quote, char const *right_quote,
1032 char const *arg)
1034 return quotearg_n_custom (0, left_quote, right_quote, arg);
1037 char *
1038 quotearg_custom_mem (char const *left_quote, char const *right_quote,
1039 char const *arg, size_t argsize)
1041 return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
1042 argsize);
1046 /* The quoting option used by the functions of quote.h. */
1047 struct quoting_options quote_quoting_options =
1049 locale_quoting_style,
1051 { 0 },
1052 NULL, NULL
1055 char const *
1056 quote_n_mem (int n, char const *arg, size_t argsize)
1058 return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
1061 char const *
1062 quote_mem (char const *arg, size_t argsize)
1064 return quote_n_mem (0, arg, argsize);
1067 char const *
1068 quote_n (int n, char const *arg)
1070 return quote_n_mem (n, arg, SIZE_MAX);
1073 char const *
1074 quote (char const *arg)
1076 return quote_n (0, arg);
1080 * Hey Emacs!
1081 * Local Variables:
1082 * coding: utf-8
1083 * End: