VirtualBox

source: kBuild/vendor/sed/current/lib/quotearg.c@ 3611

Last change on this file since 3611 was 3611, checked in by bird, 7 months ago

vendor/sed/current: GNU sed 4.9 (sed-4.9.tar.xz sha256:6e226b732e1cd739464ad6862bd1a1aba42d7982922da7a53519631d24975181)

File size: 34.3 KB
Line 
1/* quotearg.c - quote arguments for output
2
3 Copyright (C) 1998-2002, 2004-2022 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 <[email protected]> */
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 <stdint.h>
42#include <stdlib.h>
43#include <string.h>
44#include <wchar.h>
45#include <wctype.h>
46
47#include "gettext.h"
48#define _(msgid) gettext (msgid)
49#define N_(msgid) msgid
50
51#ifndef SIZE_MAX
52# define SIZE_MAX ((size_t) -1)
53#endif
54
55#define INT_BITS (sizeof (int) * CHAR_BIT)
56
57struct quoting_options
58{
59 /* Basic quoting style. */
60 enum quoting_style style;
61
62 /* Additional flags. Bitwise combination of enum quoting_flags. */
63 int flags;
64
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];
68
69 /* The left quote for custom_quoting_style. */
70 char const *left_quote;
71
72 /* The right quote for custom_quoting_style. */
73 char const *right_quote;
74};
75
76/* Names of quoting styles. */
77char const *const quoting_style_args[] =
78{
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 0
90};
91
92/* Correspondences to quoting style names. */
93enum quoting_style const quoting_style_vals[] =
94{
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
105};
106
107/* The default quoting options. */
108static struct quoting_options default_quoting_options;
109
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. */
113struct quoting_options *
114clone_quoting_options (struct quoting_options *o)
115{
116 int e = errno;
117 struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
118 sizeof *o);
119 errno = e;
120 return p;
121}
122
123/* Get the value of O's quoting style. If O is null, use the default. */
124enum quoting_style
125get_quoting_style (struct quoting_options const *o)
126{
127 return (o ? o : &default_quoting_options)->style;
128}
129
130/* In O (or in the default if O is null),
131 set the value of the quoting style to S. */
132void
133set_quoting_style (struct quoting_options *o, enum quoting_style s)
134{
135 (o ? o : &default_quoting_options)->style = s;
136}
137
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). */
143int
144set_char_quoting (struct quoting_options *o, char c, int i)
145{
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;
153}
154
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. */
159int
160set_quoting_flags (struct quoting_options *o, int i)
161{
162 int r;
163 if (!o)
164 o = &default_quoting_options;
165 r = o->flags;
166 o->flags = i;
167 return r;
168}
169
170void
171set_custom_quoting (struct quoting_options *o,
172 char const *left_quote, char const *right_quote)
173{
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;
181}
182
183/* Return quoting options for STYLE, with no extra quoting. */
184static struct quoting_options /* NOT PURE!! */
185quoting_options_from_style (enum quoting_style style)
186{
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;
192}
193
194/* MSGID approximates a quotation mark. Return its translation if it
195 has one; otherwise, return either it or "\"", depending on S.
196
197 S is either clocale_quoting_style or locale_quoting_style. */
198static char const *
199gettext_quote (char const *msgid, enum quoting_style s)
200{
201 char const *translation = _(msgid);
202 char const *locale_code;
203
204 if (translation != msgid)
205 return translation;
206
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:
209
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
223
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";
230
231 return (s == clocale_quoting_style ? "\"" : "'");
232}
233
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.
242
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. */
246
247static size_t
248quotearg_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)
254{
255 size_t i;
256 size_t len = 0;
257 size_t orig_buffersize = 0;
258 char const *quote_string = 0;
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 pending_shell_escape_end = false;
264 bool encountered_single_quote = false;
265 bool all_c_and_shell_quote_compat = true;
266
267#define STORE(c) \
268 do \
269 { \
270 if (len < buffersize) \
271 buffer[len] = (c); \
272 len++; \
273 } \
274 while (0)
275
276#define START_ESC() \
277 do \
278 { \
279 if (elide_outer_quotes) \
280 goto force_outer_quoting_style; \
281 escaping = true; \
282 if (quoting_style == shell_always_quoting_style \
283 && ! pending_shell_escape_end) \
284 { \
285 STORE ('\''); \
286 STORE ('$'); \
287 STORE ('\''); \
288 pending_shell_escape_end = true; \
289 } \
290 STORE ('\\'); \
291 } \
292 while (0)
293
294#define END_ESC() \
295 do \
296 { \
297 if (pending_shell_escape_end && ! escaping) \
298 { \
299 STORE ('\''); \
300 STORE ('\''); \
301 pending_shell_escape_end = false; \
302 } \
303 } \
304 while (0)
305
306 process_input:
307
308 switch (quoting_style)
309 {
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;
321
322 case escape_quoting_style:
323 backslash_escapes = true;
324 elide_outer_quotes = false;
325 break;
326
327 case locale_quoting_style:
328 case clocale_quoting_style:
329 case custom_quoting_style:
330 {
331 if (quoting_style != custom_quoting_style)
332 {
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.
341
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.
350
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);
356 }
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);
363 }
364 break;
365
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;
383
384 case literal_quoting_style:
385 elide_outer_quotes = false;
386 break;
387
388 default:
389 abort ();
390 }
391
392 for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
393 {
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;
399
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)
410 {
411 if (elide_outer_quotes)
412 goto force_outer_quoting_style;
413 is_right_quote = true;
414 }
415
416 c = arg[i];
417 switch (c)
418 {
419 case '\0':
420 if (backslash_escapes)
421 {
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')
431 {
432 STORE ('0');
433 STORE ('0');
434 }
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. */
440 }
441 else if (flags & QA_ELIDE_NULL_BYTES)
442 continue;
443 break;
444
445 case '?':
446 switch (quoting_style)
447 {
448 case shell_always_quoting_style:
449 if (elide_outer_quotes)
450 goto force_outer_quoting_style;
451 break;
452
453 case c_quoting_style:
454 if ((flags & QA_SPLIT_TRIGRAPHS)
455 && i + 2 < argsize && arg[i + 1] == '?')
456 switch (arg[i + 2])
457 {
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;
472
473 default:
474 break;
475 }
476 break;
477
478 default:
479 break;
480 }
481 break;
482
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)
493 {
494 if (elide_outer_quotes)
495 goto force_outer_quoting_style;
496 goto store_c;
497 }
498
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;
503
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)
511 {
512 c = esc;
513 goto store_escape;
514 }
515 break;
516
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. SunOS 4.1.4 */
535 case '`': case '|':
536 /* A shell special character. In theory, '$' and '`' could
537 be the first bytes of multibyte characters, which means
538 we should check them with mbrtowc, but in practice this
539 doesn't happen so it's not worth worrying about. */
540 if (quoting_style == shell_always_quoting_style
541 && elide_outer_quotes)
542 goto force_outer_quoting_style;
543 break;
544
545 case '\'':
546 encountered_single_quote = true;
547 c_and_shell_quote_compat = true;
548 if (quoting_style == shell_always_quoting_style)
549 {
550 if (elide_outer_quotes)
551 goto force_outer_quoting_style;
552
553 if (buffersize && ! orig_buffersize)
554 {
555 /* Just scan string to see if supports a more concise
556 representation, rather than writing a longer string
557 but returning the length of the more concise form. */
558 orig_buffersize = buffersize;
559 buffersize = 0;
560 }
561
562 STORE ('\'');
563 STORE ('\\');
564 STORE ('\'');
565 pending_shell_escape_end = false;
566 }
567 break;
568
569 case '%': case '+': case ',': case '-': case '.': case '/':
570 case '0': case '1': case '2': case '3': case '4': case '5':
571 case '6': case '7': case '8': case '9': case ':':
572 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
573 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
574 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
575 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
576 case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
577 case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
578 case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
579 case 'o': case 'p': case 'q': case 'r': case 's': case 't':
580 case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
581 /* These characters don't cause problems, no matter what the
582 quoting style is. They cannot start multibyte sequences.
583 A digit or a special letter would cause trouble if it
584 appeared at the beginning of quote_string because we'd then
585 escape by prepending a backslash. However, it's hard to
586 imagine any locale that would use digits or letters as
587 quotes, and set_custom_quoting is documented not to accept
588 them. Also, a digit or a special letter would cause
589 trouble if it appeared in quote_these_too, but that's also
590 documented as not accepting them. */
591 c_and_shell_quote_compat = true;
592 break;
593
594 default:
595 /* If we have a multibyte sequence, copy it until we reach
596 its end, find an error, or come back to the initial shift
597 state. For C-like styles, if the sequence has
598 unprintable characters, escape the whole sequence, since
599 we can't easily escape single characters within it. */
600 {
601 /* Length of multibyte sequence found so far. */
602 size_t m;
603
604 bool printable;
605
606 if (unibyte_locale)
607 {
608 m = 1;
609 printable = isprint (c) != 0;
610 }
611 else
612 {
613 mbstate_t mbstate;
614 memset (&mbstate, 0, sizeof mbstate);
615
616 m = 0;
617 printable = true;
618 if (argsize == SIZE_MAX)
619 argsize = strlen (arg);
620
621 do
622 {
623 wchar_t w;
624 size_t bytes = mbrtowc (&w, &arg[i + m],
625 argsize - (i + m), &mbstate);
626 if (bytes == 0)
627 break;
628 else if (bytes == (size_t) -1)
629 {
630 printable = false;
631 break;
632 }
633 else if (bytes == (size_t) -2)
634 {
635 printable = false;
636 while (i + m < argsize && arg[i + m])
637 m++;
638 break;
639 }
640 else
641 {
642 /* Work around a bug with older shells that "see" a '\'
643 that is really the 2nd byte of a multibyte character.
644 In practice the problem is limited to ASCII
645 chars >= '@' that are shell special chars. */
646 if ('[' == 0x5b && elide_outer_quotes
647 && quoting_style == shell_always_quoting_style)
648 {
649 size_t j;
650 for (j = 1; j < bytes; j++)
651 switch (arg[i + m + j])
652 {
653 case '[': case '\\': case '^':
654 case '`': case '|':
655 goto force_outer_quoting_style;
656
657 default:
658 break;
659 }
660 }
661
662 if (! iswprint (w))
663 printable = false;
664 m += bytes;
665 }
666 }
667 while (! mbsinit (&mbstate));
668 }
669
670 c_and_shell_quote_compat = printable;
671
672 if (1 < m || (backslash_escapes && ! printable))
673 {
674 /* Output a multibyte sequence, or an escaped
675 unprintable unibyte character. */
676 size_t ilim = i + m;
677
678 for (;;)
679 {
680 if (backslash_escapes && ! printable)
681 {
682 START_ESC ();
683 STORE ('0' + (c >> 6));
684 STORE ('0' + ((c >> 3) & 7));
685 c = '0' + (c & 7);
686 }
687 else if (is_right_quote)
688 {
689 STORE ('\\');
690 is_right_quote = false;
691 }
692 if (ilim <= i + 1)
693 break;
694 END_ESC ();
695 STORE (c);
696 c = arg[++i];
697 }
698
699 goto store_c;
700 }
701 }
702 }
703
704 if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
705 || elide_outer_quotes)
706 && quote_these_too
707 && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
708 && !is_right_quote)
709 goto store_c;
710
711 store_escape:
712 START_ESC ();
713
714 store_c:
715 END_ESC ();
716 STORE (c);
717
718 if (! c_and_shell_quote_compat)
719 all_c_and_shell_quote_compat = false;
720 }
721
722 if (len == 0 && quoting_style == shell_always_quoting_style
723 && elide_outer_quotes)
724 goto force_outer_quoting_style;
725
726 /* Single shell quotes (') are commonly enough used as an apostrophe,
727 that we attempt to minimize the quoting in this case. Note itʼs
728 better to use the apostrophe modifier "\u02BC" if possible, as that
729 renders better and works with the word match regex \W+ etc. */
730 if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
731 && encountered_single_quote)
732 {
733 if (all_c_and_shell_quote_compat)
734 return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
735 c_quoting_style,
736 flags, quote_these_too,
737 left_quote, right_quote);
738 else if (! buffersize && orig_buffersize)
739 {
740 /* Disable read-only scan, and reprocess to write quoted string. */
741 buffersize = orig_buffersize;
742 len = 0;
743 goto process_input;
744 }
745 }
746
747 if (quote_string && !elide_outer_quotes)
748 for (; *quote_string; quote_string++)
749 STORE (*quote_string);
750
751 if (len < buffersize)
752 buffer[len] = '\0';
753 return len;
754
755 force_outer_quoting_style:
756 /* Don't reuse quote_these_too, since the addition of outer quotes
757 sufficiently quotes the specified characters. */
758 if (quoting_style == shell_always_quoting_style && backslash_escapes)
759 quoting_style = shell_escape_always_quoting_style;
760 return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
761 quoting_style,
762 flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
763 left_quote, right_quote);
764}
765
766/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
767 argument ARG (of size ARGSIZE), using O to control quoting.
768 If O is null, use the default.
769 Terminate the output with a null character, and return the written
770 size of the output, not counting the terminating null.
771 If BUFFERSIZE is too small to store the output string, return the
772 value that would have been returned had BUFFERSIZE been large enough.
773 If ARGSIZE is SIZE_MAX, use the string length of the argument for
774 ARGSIZE. */
775size_t
776quotearg_buffer (char *buffer, size_t buffersize,
777 char const *arg, size_t argsize,
778 struct quoting_options const *o)
779{
780 struct quoting_options const *p = o ? o : &default_quoting_options;
781 int e = errno;
782 size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
783 p->style, p->flags, p->quote_these_too,
784 p->left_quote, p->right_quote);
785 errno = e;
786 return r;
787}
788
789char *
790quotearg_alloc (char const *arg, size_t argsize,
791 struct quoting_options const *o)
792{
793 return quotearg_alloc_mem (arg, argsize, NULL, o);
794}
795
796/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
797 allocated storage containing the quoted string, and store the
798 resulting size into *SIZE, if non-NULL. The result can contain
799 embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
800 NULL, and set_quoting_flags has not set the null byte elision
801 flag. */
802char *
803quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
804 struct quoting_options const *o)
805{
806 struct quoting_options const *p = o ? o : &default_quoting_options;
807 int e = errno;
808 /* Elide embedded null bytes if we can't return a size. */
809 int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
810 size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
811 flags, p->quote_these_too,
812 p->left_quote,
813 p->right_quote) + 1;
814 char *buf = xcharalloc (bufsize);
815 quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
816 p->quote_these_too,
817 p->left_quote, p->right_quote);
818 errno = e;
819 if (size)
820 *size = bufsize - 1;
821 return buf;
822}
823
824/* A storage slot with size and pointer to a value. */
825struct slotvec
826{
827 size_t size;
828 char *val;
829};
830
831/* Preallocate a slot 0 buffer, so that the caller can always quote
832 one small component of a "memory exhausted" message in slot 0. */
833static char slot0[256];
834static int nslots = 1;
835static struct slotvec slotvec0 = {sizeof slot0, slot0};
836static struct slotvec *slotvec = &slotvec0;
837
838void
839quotearg_free (void)
840{
841 struct slotvec *sv = slotvec;
842 int i;
843 for (i = 1; i < nslots; i++)
844 free (sv[i].val);
845 if (sv[0].val != slot0)
846 {
847 free (sv[0].val);
848 slotvec0.size = sizeof slot0;
849 slotvec0.val = slot0;
850 }
851 if (sv != &slotvec0)
852 {
853 free (sv);
854 slotvec = &slotvec0;
855 }
856 nslots = 1;
857}
858
859/* Use storage slot N to return a quoted version of argument ARG.
860 ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
861 null-terminated string.
862 OPTIONS specifies the quoting options.
863 The returned value points to static storage that can be
864 reused by the next call to this function with the same value of N.
865 N must be nonnegative; it is typically small, and must be
866 less than MIN (INT_MAX, IDX_MAX). The type of N is signed
867 to allow for future extensions (using negative values). */
868static char *
869quotearg_n_options (int n, char const *arg, size_t argsize,
870 struct quoting_options const *options)
871{
872 int e = errno;
873
874 struct slotvec *sv = slotvec;
875
876 int nslots_max = MIN (INT_MAX, IDX_MAX);
877 if (! (0 <= n && n < nslots_max))
878 abort ();
879
880 if (nslots <= n)
881 {
882 bool preallocated = (sv == &slotvec0);
883 idx_t new_nslots = nslots;
884
885 slotvec = sv = xpalloc (preallocated ? NULL : sv, &new_nslots,
886 n - nslots + 1, nslots_max, sizeof *sv);
887 if (preallocated)
888 *sv = slotvec0;
889 memset (sv + nslots, 0, (new_nslots - nslots) * sizeof *sv);
890 nslots = new_nslots;
891 }
892
893 {
894 size_t size = sv[n].size;
895 char *val = sv[n].val;
896 /* Elide embedded null bytes since we don't return a size. */
897 int flags = options->flags | QA_ELIDE_NULL_BYTES;
898 size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
899 options->style, flags,
900 options->quote_these_too,
901 options->left_quote,
902 options->right_quote);
903
904 if (size <= qsize)
905 {
906 sv[n].size = size = qsize + 1;
907 if (val != slot0)
908 free (val);
909 sv[n].val = val = xcharalloc (size);
910 quotearg_buffer_restyled (val, size, arg, argsize, options->style,
911 flags, options->quote_these_too,
912 options->left_quote,
913 options->right_quote);
914 }
915
916 errno = e;
917 return val;
918 }
919}
920
921char *
922quotearg_n (int n, char const *arg)
923{
924 return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
925}
926
927char *
928quotearg_n_mem (int n, char const *arg, size_t argsize)
929{
930 return quotearg_n_options (n, arg, argsize, &default_quoting_options);
931}
932
933char *
934quotearg (char const *arg)
935{
936 return quotearg_n (0, arg);
937}
938
939char *
940quotearg_mem (char const *arg, size_t argsize)
941{
942 return quotearg_n_mem (0, arg, argsize);
943}
944
945char *
946quotearg_n_style (int n, enum quoting_style s, char const *arg)
947{
948 struct quoting_options const o = quoting_options_from_style (s);
949 return quotearg_n_options (n, arg, SIZE_MAX, &o);
950}
951
952char *
953quotearg_n_style_mem (int n, enum quoting_style s,
954 char const *arg, size_t argsize)
955{
956 struct quoting_options const o = quoting_options_from_style (s);
957 return quotearg_n_options (n, arg, argsize, &o);
958}
959
960char *
961quotearg_style (enum quoting_style s, char const *arg)
962{
963 return quotearg_n_style (0, s, arg);
964}
965
966char *
967quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
968{
969 return quotearg_n_style_mem (0, s, arg, argsize);
970}
971
972char *
973quotearg_char_mem (char const *arg, size_t argsize, char ch)
974{
975 struct quoting_options options;
976 options = default_quoting_options;
977 set_char_quoting (&options, ch, 1);
978 return quotearg_n_options (0, arg, argsize, &options);
979}
980
981char *
982quotearg_char (char const *arg, char ch)
983{
984 return quotearg_char_mem (arg, SIZE_MAX, ch);
985}
986
987char *
988quotearg_colon (char const *arg)
989{
990 return quotearg_char (arg, ':');
991}
992
993char *
994quotearg_colon_mem (char const *arg, size_t argsize)
995{
996 return quotearg_char_mem (arg, argsize, ':');
997}
998
999char *
1000quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
1001{
1002 struct quoting_options options;
1003 options = quoting_options_from_style (s);
1004 set_char_quoting (&options, ':', 1);
1005 return quotearg_n_options (n, arg, SIZE_MAX, &options);
1006}
1007
1008char *
1009quotearg_n_custom (int n, char const *left_quote,
1010 char const *right_quote, char const *arg)
1011{
1012 return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
1013 SIZE_MAX);
1014}
1015
1016char *
1017quotearg_n_custom_mem (int n, char const *left_quote,
1018 char const *right_quote,
1019 char const *arg, size_t argsize)
1020{
1021 struct quoting_options o = default_quoting_options;
1022 set_custom_quoting (&o, left_quote, right_quote);
1023 return quotearg_n_options (n, arg, argsize, &o);
1024}
1025
1026char *
1027quotearg_custom (char const *left_quote, char const *right_quote,
1028 char const *arg)
1029{
1030 return quotearg_n_custom (0, left_quote, right_quote, arg);
1031}
1032
1033char *
1034quotearg_custom_mem (char const *left_quote, char const *right_quote,
1035 char const *arg, size_t argsize)
1036{
1037 return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
1038 argsize);
1039}
1040
1041
1042/* The quoting option used by the functions of quote.h. */
1043struct quoting_options quote_quoting_options =
1044 {
1045 locale_quoting_style,
1046 0,
1047 { 0 },
1048 NULL, NULL
1049 };
1050
1051char const *
1052quote_n_mem (int n, char const *arg, size_t argsize)
1053{
1054 return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
1055}
1056
1057char const *
1058quote_mem (char const *arg, size_t argsize)
1059{
1060 return quote_n_mem (0, arg, argsize);
1061}
1062
1063char const *
1064quote_n (int n, char const *arg)
1065{
1066 return quote_n_mem (n, arg, SIZE_MAX);
1067}
1068
1069char const *
1070quote (char const *arg)
1071{
1072 return quote_n (0, arg);
1073}
1074
1075/*
1076 * Hey Emacs!
1077 * Local Variables:
1078 * coding: utf-8
1079 * End:
1080 */
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette