Line data Source code
1 : /* quotearg.c - quote arguments for output
2 :
3 : Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007,
4 : 2008 Free Software Foundation, Inc.
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : /* Written by Paul Eggert <eggert@twinsun.com> */
20 :
21 : #include <config.h>
22 :
23 : #include "quotearg.h"
24 :
25 : #include "xalloc.h"
26 :
27 : #include <ctype.h>
28 : #include <errno.h>
29 : #include <limits.h>
30 : #include <stdbool.h>
31 : #include <stdlib.h>
32 : #include <string.h>
33 : #include <wchar.h>
34 : #include <wctype.h>
35 :
36 : #include "gettext.h"
37 : #define _(msgid) gettext (msgid)
38 : #define N_(msgid) msgid
39 :
40 : #if !HAVE_MBRTOWC
41 : /* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
42 : other macros are defined only for documentation and to satisfy C
43 : syntax. */
44 : # undef MB_CUR_MAX
45 : # define MB_CUR_MAX 1
46 : # undef mbstate_t
47 : # define mbstate_t int
48 : # define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
49 : # define iswprint(wc) isprint ((unsigned char) (wc))
50 : # undef HAVE_MBSINIT
51 : #endif
52 :
53 : #if !defined mbsinit && !HAVE_MBSINIT
54 : # define mbsinit(ps) 1
55 : #endif
56 :
57 : #ifndef SIZE_MAX
58 : # define SIZE_MAX ((size_t) -1)
59 : #endif
60 :
61 : #define INT_BITS (sizeof (int) * CHAR_BIT)
62 :
63 : struct quoting_options
64 : {
65 : /* Basic quoting style. */
66 : enum quoting_style style;
67 :
68 : /* Additional flags. Bitwise combination of enum quoting_flags. */
69 : int flags;
70 :
71 : /* Quote the characters indicated by this bit vector even if the
72 : quoting style would not normally require them to be quoted. */
73 : unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
74 : };
75 :
76 : /* Names of quoting styles. */
77 : char const *const quoting_style_args[] =
78 : {
79 : "literal",
80 : "shell",
81 : "shell-always",
82 : "c",
83 : "c-maybe",
84 : "escape",
85 : "locale",
86 : "clocale",
87 : 0
88 : };
89 :
90 : /* Correspondences to quoting style names. */
91 : enum quoting_style const quoting_style_vals[] =
92 : {
93 : literal_quoting_style,
94 : shell_quoting_style,
95 : shell_always_quoting_style,
96 : c_quoting_style,
97 : c_maybe_quoting_style,
98 : escape_quoting_style,
99 : locale_quoting_style,
100 : clocale_quoting_style
101 : };
102 :
103 : /* The default quoting options. */
104 : static struct quoting_options default_quoting_options;
105 :
106 : /* Allocate a new set of quoting options, with contents initially identical
107 : to O if O is not null, or to the default if O is null.
108 : It is the caller's responsibility to free the result. */
109 : struct quoting_options *
110 0 : clone_quoting_options (struct quoting_options *o)
111 : {
112 0 : int e = errno;
113 0 : struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
114 : sizeof *o);
115 0 : errno = e;
116 0 : return p;
117 : }
118 :
119 : /* Get the value of O's quoting style. If O is null, use the default. */
120 : enum quoting_style
121 0 : get_quoting_style (struct quoting_options *o)
122 : {
123 0 : return (o ? o : &default_quoting_options)->style;
124 : }
125 :
126 : /* In O (or in the default if O is null),
127 : set the value of the quoting style to S. */
128 : void
129 18 : set_quoting_style (struct quoting_options *o, enum quoting_style s)
130 : {
131 18 : (o ? o : &default_quoting_options)->style = s;
132 18 : }
133 :
134 : /* In O (or in the default if O is null),
135 : set the value of the quoting options for character C to I.
136 : Return the old value. Currently, the only values defined for I are
137 : 0 (the default) and 1 (which means to quote the character even if
138 : it would not otherwise be quoted). */
139 : int
140 188 : set_char_quoting (struct quoting_options *o, char c, int i)
141 : {
142 188 : unsigned char uc = c;
143 188 : unsigned int *p =
144 188 : (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
145 188 : int shift = uc % INT_BITS;
146 188 : int r = (*p >> shift) & 1;
147 188 : *p ^= ((i & 1) ^ r) << shift;
148 188 : return r;
149 : }
150 :
151 : /* In O (or in the default if O is null),
152 : set the value of the quoting options flag to I, which can be a
153 : bitwise combination of enum quoting_flags, or 0 for default
154 : behavior. Return the old value. */
155 : int
156 0 : set_quoting_flags (struct quoting_options *o, int i)
157 : {
158 : int r;
159 0 : if (!o)
160 0 : o = &default_quoting_options;
161 0 : r = o->flags;
162 0 : o->flags = i;
163 0 : return r;
164 : }
165 :
166 : /* Return quoting options for STYLE, with no extra quoting. */
167 : static struct quoting_options
168 408534 : quoting_options_from_style (enum quoting_style style)
169 : {
170 : struct quoting_options o;
171 408534 : o.style = style;
172 408534 : o.flags = 0;
173 408534 : memset (o.quote_these_too, 0, sizeof o.quote_these_too);
174 408534 : return o;
175 : }
176 :
177 : /* MSGID approximates a quotation mark. Return its translation if it
178 : has one; otherwise, return either it or "\"", depending on S. */
179 : static char const *
180 817366 : gettext_quote (char const *msgid, enum quoting_style s)
181 : {
182 817366 : char const *translation = _(msgid);
183 817366 : if (translation == msgid && s == clocale_quoting_style)
184 0 : translation = "\"";
185 817366 : return translation;
186 : }
187 :
188 : /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
189 : argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
190 : QUOTE_THESE_TOO to control quoting.
191 : Terminate the output with a null character, and return the written
192 : size of the output, not counting the terminating null.
193 : If BUFFERSIZE is too small to store the output string, return the
194 : value that would have been returned had BUFFERSIZE been large enough.
195 : If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
196 :
197 : This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
198 : ARGSIZE, O), except it breaks O into its component pieces and is
199 : not careful about errno. */
200 :
201 : static size_t
202 408885 : quotearg_buffer_restyled (char *buffer, size_t buffersize,
203 : char const *arg, size_t argsize,
204 : enum quoting_style quoting_style, int flags,
205 : unsigned int const *quote_these_too)
206 : {
207 : size_t i;
208 408885 : size_t len = 0;
209 408885 : char const *quote_string = 0;
210 408885 : size_t quote_string_len = 0;
211 408885 : bool backslash_escapes = false;
212 408885 : bool unibyte_locale = MB_CUR_MAX == 1;
213 408885 : bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
214 :
215 : #define STORE(c) \
216 : do \
217 : { \
218 : if (len < buffersize) \
219 : buffer[len] = (c); \
220 : len++; \
221 : } \
222 : while (0)
223 :
224 408885 : switch (quoting_style)
225 : {
226 0 : case c_maybe_quoting_style:
227 0 : quoting_style = c_quoting_style;
228 0 : elide_outer_quotes = true;
229 : /* Fall through. */
230 0 : case c_quoting_style:
231 0 : if (!elide_outer_quotes)
232 0 : STORE ('"');
233 0 : backslash_escapes = true;
234 0 : quote_string = "\"";
235 0 : quote_string_len = 1;
236 0 : break;
237 :
238 18 : case escape_quoting_style:
239 18 : backslash_escapes = true;
240 18 : elide_outer_quotes = false;
241 18 : break;
242 :
243 408683 : case locale_quoting_style:
244 : case clocale_quoting_style:
245 : {
246 : /* TRANSLATORS:
247 : Get translations for open and closing quotation marks.
248 :
249 : The message catalog should translate "`" to a left
250 : quotation mark suitable for the locale, and similarly for
251 : "'". If the catalog has no translation,
252 : locale_quoting_style quotes `like this', and
253 : clocale_quoting_style quotes "like this".
254 :
255 : For example, an American English Unicode locale should
256 : translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
257 : should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
258 : MARK). A British English Unicode locale should instead
259 : translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
260 : U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
261 :
262 : If you don't know what to put here, please see
263 : <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
264 : and use glyphs suitable for your language. */
265 :
266 408683 : char const *left = gettext_quote (N_("`"), quoting_style);
267 408683 : char const *right = gettext_quote (N_("'"), quoting_style);
268 408683 : if (!elide_outer_quotes)
269 817366 : for (quote_string = left; *quote_string; quote_string++)
270 408683 : STORE (*quote_string);
271 408683 : backslash_escapes = true;
272 408683 : quote_string = right;
273 408683 : quote_string_len = strlen (quote_string);
274 : }
275 408683 : break;
276 :
277 4 : case shell_quoting_style:
278 4 : quoting_style = shell_always_quoting_style;
279 4 : elide_outer_quotes = true;
280 : /* Fall through. */
281 4 : case shell_always_quoting_style:
282 4 : if (!elide_outer_quotes)
283 0 : STORE ('\'');
284 4 : quote_string = "'";
285 4 : quote_string_len = 1;
286 4 : break;
287 :
288 180 : case literal_quoting_style:
289 180 : elide_outer_quotes = false;
290 180 : break;
291 :
292 0 : default:
293 0 : abort ();
294 : }
295 :
296 16417439 : for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
297 : {
298 : unsigned char c;
299 : unsigned char esc;
300 :
301 16008554 : if (backslash_escapes
302 16007786 : && quote_string_len
303 16007741 : && i + quote_string_len <= argsize
304 16007741 : && memcmp (arg + i, quote_string, quote_string_len) == 0)
305 : {
306 295 : if (elide_outer_quotes)
307 0 : goto force_outer_quoting_style;
308 295 : STORE ('\\');
309 : }
310 :
311 16008554 : c = arg[i];
312 16008554 : switch (c)
313 : {
314 0 : case '\0':
315 0 : if (backslash_escapes)
316 : {
317 0 : if (elide_outer_quotes)
318 0 : goto force_outer_quoting_style;
319 0 : STORE ('\\');
320 0 : if (i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
321 : {
322 0 : STORE ('0');
323 0 : STORE ('0');
324 : }
325 0 : c = '0';
326 : }
327 0 : else if (flags & QA_ELIDE_NULL_BYTES)
328 0 : continue;
329 0 : break;
330 :
331 67 : case '?':
332 67 : switch (quoting_style)
333 : {
334 0 : case shell_always_quoting_style:
335 0 : if (elide_outer_quotes)
336 0 : goto force_outer_quoting_style;
337 0 : break;
338 :
339 0 : case c_quoting_style:
340 0 : if ((flags & QA_SPLIT_TRIGRAPHS)
341 0 : && i + 2 < argsize && arg[i + 1] == '?')
342 0 : switch (arg[i + 2])
343 : {
344 0 : case '!': case '\'':
345 : case '(': case ')': case '-': case '/':
346 : case '<': case '=': case '>':
347 : /* Escape the second '?' in what would otherwise be
348 : a trigraph. */
349 0 : if (elide_outer_quotes)
350 0 : goto force_outer_quoting_style;
351 0 : c = arg[i + 2];
352 0 : i += 2;
353 0 : STORE ('?');
354 0 : STORE ('"');
355 0 : STORE ('"');
356 0 : STORE ('?');
357 0 : break;
358 :
359 0 : default:
360 0 : break;
361 : }
362 0 : break;
363 :
364 67 : default:
365 67 : break;
366 : }
367 67 : break;
368 :
369 11 : case '\a': esc = 'a'; goto c_escape;
370 59 : case '\b': esc = 'b'; goto c_escape;
371 59 : case '\f': esc = 'f'; goto c_escape;
372 12 : case '\n': esc = 'n'; goto c_and_shell_escape;
373 70 : case '\r': esc = 'r'; goto c_and_shell_escape;
374 121 : case '\t': esc = 't'; goto c_and_shell_escape;
375 76 : case '\v': esc = 'v'; goto c_escape;
376 104 : case '\\': esc = c;
377 : /* No need to escape the escape if we are trying to elide
378 : outer quotes and nothing else is problematic. */
379 104 : if (backslash_escapes && elide_outer_quotes && quote_string_len)
380 0 : goto store_c;
381 :
382 104 : c_and_shell_escape:
383 307 : if (quoting_style == shell_always_quoting_style
384 0 : && elide_outer_quotes)
385 0 : goto force_outer_quoting_style;
386 : /* Fall through. */
387 307 : c_escape:
388 512 : if (backslash_escapes)
389 : {
390 495 : c = esc;
391 495 : goto store_escape;
392 : }
393 17 : break;
394 :
395 59 : case '{': case '}': /* sometimes special if isolated */
396 59 : if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
397 22 : break;
398 : /* Fall through. */
399 : case '#': case '~':
400 145 : if (i != 0)
401 75 : break;
402 : /* Fall through. */
403 : case ' ':
404 : case '!': /* special in bash */
405 : case '"': case '$': case '&':
406 : case '(': case ')': case '*': case ';':
407 : case '<':
408 : case '=': /* sometimes special in 0th or (with "set -k") later args */
409 : case '>': case '[':
410 : case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
411 : case '`': case '|':
412 : /* A shell special character. In theory, '$' and '`' could
413 : be the first bytes of multibyte characters, which means
414 : we should check them with mbrtowc, but in practice this
415 : doesn't happen so it's not worth worrying about. */
416 790 : if (quoting_style == shell_always_quoting_style
417 0 : && elide_outer_quotes)
418 0 : goto force_outer_quoting_style;
419 790 : break;
420 :
421 297 : case '\'':
422 297 : if (quoting_style == shell_always_quoting_style)
423 : {
424 0 : if (elide_outer_quotes)
425 0 : goto force_outer_quoting_style;
426 0 : STORE ('\'');
427 0 : STORE ('\\');
428 0 : STORE ('\'');
429 : }
430 297 : break;
431 :
432 16006243 : case '%': case '+': case ',': case '-': case '.': case '/':
433 : case '0': case '1': case '2': case '3': case '4': case '5':
434 : case '6': case '7': case '8': case '9': case ':':
435 : case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
436 : case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
437 : case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
438 : case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
439 : case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
440 : case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
441 : case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
442 : case 'o': case 'p': case 'q': case 'r': case 's': case 't':
443 : case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
444 : /* These characters don't cause problems, no matter what the
445 : quoting style is. They cannot start multibyte sequences. */
446 16006243 : break;
447 :
448 548 : default:
449 : /* If we have a multibyte sequence, copy it until we reach
450 : its end, find an error, or come back to the initial shift
451 : state. For C-like styles, if the sequence has
452 : unprintable characters, escape the whole sequence, since
453 : we can't easily escape single characters within it. */
454 : {
455 : /* Length of multibyte sequence found so far. */
456 : size_t m;
457 :
458 : bool printable;
459 :
460 548 : if (unibyte_locale)
461 : {
462 548 : m = 1;
463 548 : printable = isprint (c) != 0;
464 : }
465 : else
466 : {
467 : mbstate_t mbstate;
468 0 : memset (&mbstate, 0, sizeof mbstate);
469 :
470 0 : m = 0;
471 0 : printable = true;
472 0 : if (argsize == SIZE_MAX)
473 0 : argsize = strlen (arg);
474 :
475 : do
476 : {
477 : wchar_t w;
478 0 : size_t bytes = mbrtowc (&w, &arg[i + m],
479 0 : argsize - (i + m), &mbstate);
480 0 : if (bytes == 0)
481 0 : break;
482 0 : else if (bytes == (size_t) -1)
483 : {
484 0 : printable = false;
485 0 : break;
486 : }
487 0 : else if (bytes == (size_t) -2)
488 : {
489 0 : printable = false;
490 0 : while (i + m < argsize && arg[i + m])
491 0 : m++;
492 0 : break;
493 : }
494 : else
495 : {
496 : /* Work around a bug with older shells that "see" a '\'
497 : that is really the 2nd byte of a multibyte character.
498 : In practice the problem is limited to ASCII
499 : chars >= '@' that are shell special chars. */
500 0 : if ('[' == 0x5b && elide_outer_quotes
501 0 : && quoting_style == shell_always_quoting_style)
502 : {
503 : size_t j;
504 0 : for (j = 1; j < bytes; j++)
505 0 : switch (arg[i + m + j])
506 : {
507 0 : case '[': case '\\': case '^':
508 : case '`': case '|':
509 0 : goto force_outer_quoting_style;
510 :
511 0 : default:
512 0 : break;
513 : }
514 : }
515 :
516 0 : if (! iswprint (w))
517 0 : printable = false;
518 0 : m += bytes;
519 : }
520 : }
521 0 : while (! mbsinit (&mbstate));
522 : }
523 :
524 548 : if (1 < m || (backslash_escapes && ! printable))
525 : {
526 : /* Output a multibyte sequence, or an escaped
527 : unprintable unibyte character. */
528 352 : size_t ilim = i + m;
529 :
530 : for (;;)
531 : {
532 352 : if (backslash_escapes && ! printable)
533 : {
534 352 : if (elide_outer_quotes)
535 0 : goto force_outer_quoting_style;
536 352 : STORE ('\\');
537 352 : STORE ('0' + (c >> 6));
538 352 : STORE ('0' + ((c >> 3) & 7));
539 352 : c = '0' + (c & 7);
540 : }
541 352 : if (ilim <= i + 1)
542 352 : break;
543 0 : STORE (c);
544 0 : c = arg[++i];
545 : }
546 :
547 352 : goto store_c;
548 : }
549 : }
550 : }
551 :
552 32014654 : if (! ((backslash_escapes || elide_outer_quotes)
553 16006947 : && quote_these_too
554 16006947 : && quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
555 : goto store_c;
556 :
557 1 : store_escape:
558 496 : if (elide_outer_quotes)
559 0 : goto force_outer_quoting_style;
560 496 : STORE ('\\');
561 :
562 32016260 : store_c:
563 16008554 : STORE (c);
564 : }
565 :
566 408885 : if (len == 0 && quoting_style == shell_always_quoting_style
567 0 : && elide_outer_quotes)
568 0 : goto force_outer_quoting_style;
569 :
570 408885 : if (quote_string && !elide_outer_quotes)
571 817366 : for (; *quote_string; quote_string++)
572 408683 : STORE (*quote_string);
573 :
574 408885 : if (len < buffersize)
575 408732 : buffer[len] = '\0';
576 408885 : return len;
577 :
578 0 : force_outer_quoting_style:
579 : /* Don't reuse quote_these_too, since the addition of outer quotes
580 : sufficiently quotes the specified characters. */
581 0 : return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
582 : quoting_style,
583 : flags & ~QA_ELIDE_OUTER_QUOTES, NULL);
584 : }
585 :
586 : /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
587 : argument ARG (of size ARGSIZE), using O to control quoting.
588 : If O is null, use the default.
589 : Terminate the output with a null character, and return the written
590 : size of the output, not counting the terminating null.
591 : If BUFFERSIZE is too small to store the output string, return the
592 : value that would have been returned had BUFFERSIZE been large enough.
593 : If ARGSIZE is SIZE_MAX, use the string length of the argument for
594 : ARGSIZE. */
595 : size_t
596 0 : quotearg_buffer (char *buffer, size_t buffersize,
597 : char const *arg, size_t argsize,
598 : struct quoting_options const *o)
599 : {
600 0 : struct quoting_options const *p = o ? o : &default_quoting_options;
601 0 : int e = errno;
602 0 : size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
603 0 : p->style, p->flags, p->quote_these_too);
604 0 : errno = e;
605 0 : return r;
606 : }
607 :
608 : /* Equivalent to quotearg_alloc (ARG, ARGSIZE, NULL, O). */
609 : char *
610 0 : quotearg_alloc (char const *arg, size_t argsize,
611 : struct quoting_options const *o)
612 : {
613 0 : return quotearg_alloc_mem (arg, argsize, NULL, o);
614 : }
615 :
616 : /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
617 : allocated storage containing the quoted string, and store the
618 : resulting size into *SIZE, if non-NULL. The result can contain
619 : embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
620 : NULL, and set_quoting_flags has not set the null byte elision
621 : flag. */
622 : char *
623 0 : quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
624 : struct quoting_options const *o)
625 : {
626 0 : struct quoting_options const *p = o ? o : &default_quoting_options;
627 0 : int e = errno;
628 : /* Elide embedded null bytes if we can't return a size. */
629 0 : int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
630 0 : size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
631 0 : flags, p->quote_these_too) + 1;
632 0 : char *buf = xcharalloc (bufsize);
633 0 : quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
634 0 : p->quote_these_too);
635 0 : errno = e;
636 0 : if (size)
637 0 : *size = bufsize - 1;
638 0 : return buf;
639 : }
640 :
641 : /* A storage slot with size and pointer to a value. */
642 : struct slotvec
643 : {
644 : size_t size;
645 : char *val;
646 : };
647 :
648 : /* Preallocate a slot 0 buffer, so that the caller can always quote
649 : one small component of a "memory exhausted" message in slot 0. */
650 : static char slot0[256];
651 : static unsigned int nslots = 1;
652 : static struct slotvec slotvec0 = {sizeof slot0, slot0};
653 : static struct slotvec *slotvec = &slotvec0;
654 :
655 : void
656 0 : quotearg_free (void)
657 : {
658 0 : struct slotvec *sv = slotvec;
659 : unsigned int i;
660 0 : for (i = 1; i < nslots; i++)
661 0 : free (sv[i].val);
662 0 : if (sv[0].val != slot0)
663 : {
664 0 : free (sv[0].val);
665 0 : slotvec0.size = sizeof slot0;
666 0 : slotvec0.val = slot0;
667 : }
668 0 : if (sv != &slotvec0)
669 : {
670 0 : free (sv);
671 0 : slotvec = &slotvec0;
672 : }
673 0 : nslots = 1;
674 0 : }
675 :
676 : /* Use storage slot N to return a quoted version of argument ARG.
677 : ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
678 : null-terminated string.
679 : OPTIONS specifies the quoting options.
680 : The returned value points to static storage that can be
681 : reused by the next call to this function with the same value of N.
682 : N must be nonnegative. N is deliberately declared with type "int"
683 : to allow for future extensions (using negative values). */
684 : static char *
685 408732 : quotearg_n_options (int n, char const *arg, size_t argsize,
686 : struct quoting_options const *options)
687 : {
688 408732 : int e = errno;
689 :
690 408732 : unsigned int n0 = n;
691 408732 : struct slotvec *sv = slotvec;
692 :
693 408732 : if (n < 0)
694 0 : abort ();
695 :
696 408732 : if (nslots <= n0)
697 : {
698 : /* FIXME: technically, the type of n1 should be `unsigned int',
699 : but that evokes an unsuppressible warning from gcc-4.0.1 and
700 : older. If gcc ever provides an option to suppress that warning,
701 : revert to the original type, so that the test in xalloc_oversized
702 : is once again performed only at compile time. */
703 153 : size_t n1 = n0 + 1;
704 153 : bool preallocated = (sv == &slotvec0);
705 :
706 153 : if (xalloc_oversized (n1, sizeof *sv))
707 0 : xalloc_die ();
708 :
709 153 : slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv);
710 153 : if (preallocated)
711 153 : *sv = slotvec0;
712 153 : memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv);
713 153 : nslots = n1;
714 : }
715 :
716 : {
717 408732 : size_t size = sv[n].size;
718 408732 : char *val = sv[n].val;
719 : /* Elide embedded null bytes since we don't return a size. */
720 408732 : int flags = options->flags | QA_ELIDE_NULL_BYTES;
721 408732 : size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
722 : options->style, flags,
723 408732 : options->quote_these_too);
724 :
725 408732 : if (size <= qsize)
726 : {
727 153 : sv[n].size = size = qsize + 1;
728 153 : if (val != slot0)
729 153 : free (val);
730 153 : sv[n].val = val = xcharalloc (size);
731 153 : quotearg_buffer_restyled (val, size, arg, argsize, options->style,
732 153 : flags, options->quote_these_too);
733 : }
734 :
735 408732 : errno = e;
736 408732 : return val;
737 : }
738 : }
739 :
740 : char *
741 10 : quotearg_n (int n, char const *arg)
742 : {
743 10 : return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
744 : }
745 :
746 : char *
747 0 : quotearg_n_mem (int n, char const *arg, size_t argsize)
748 : {
749 0 : return quotearg_n_options (n, arg, argsize, &default_quoting_options);
750 : }
751 :
752 : char *
753 10 : quotearg (char const *arg)
754 : {
755 10 : return quotearg_n (0, arg);
756 : }
757 :
758 : char *
759 0 : quotearg_mem (char const *arg, size_t argsize)
760 : {
761 0 : return quotearg_n_mem (0, arg, argsize);
762 : }
763 :
764 : char *
765 408526 : quotearg_n_style (int n, enum quoting_style s, char const *arg)
766 : {
767 408526 : struct quoting_options const o = quoting_options_from_style (s);
768 408526 : return quotearg_n_options (n, arg, SIZE_MAX, &o);
769 : }
770 :
771 : char *
772 8 : quotearg_n_style_mem (int n, enum quoting_style s,
773 : char const *arg, size_t argsize)
774 : {
775 8 : struct quoting_options const o = quoting_options_from_style (s);
776 8 : return quotearg_n_options (n, arg, argsize, &o);
777 : }
778 :
779 : char *
780 0 : quotearg_style (enum quoting_style s, char const *arg)
781 : {
782 0 : return quotearg_n_style (0, s, arg);
783 : }
784 :
785 : char *
786 0 : quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
787 : {
788 0 : return quotearg_n_style_mem (0, s, arg, argsize);
789 : }
790 :
791 : char *
792 188 : quotearg_char_mem (char const *arg, size_t argsize, char ch)
793 : {
794 : struct quoting_options options;
795 188 : options = default_quoting_options;
796 188 : set_char_quoting (&options, ch, 1);
797 188 : return quotearg_n_options (0, arg, argsize, &options);
798 : }
799 :
800 : char *
801 188 : quotearg_char (char const *arg, char ch)
802 : {
803 188 : return quotearg_char_mem (arg, SIZE_MAX, ch);
804 : }
805 :
806 : char *
807 188 : quotearg_colon (char const *arg)
808 : {
809 188 : return quotearg_char (arg, ':');
810 : }
811 :
812 : char *
813 0 : quotearg_colon_mem (char const *arg, size_t argsize)
814 : {
815 0 : return quotearg_char_mem (arg, argsize, ':');
816 : }
|