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