1 /* quotearg.c - quote arguments for output
2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Paul Eggert <eggert@twinsun.com> */
24 #include <sys/types.h>
32 # define _(text) gettext (text)
44 # define UCHAR_MAX ((unsigned char) -1)
47 #if HAVE_C_BACKSLASH_A
48 # define ALERT_CHAR '\a'
50 # define ALERT_CHAR '\7'
65 #if HAVE_MBRTOWC && HAVE_WCHAR_H
66 # if !HAVE_MBSTATE_T_OBJECT
67 # define mbrtowc(pwc, s, n, ps) (mbrtowc) (pwc, s, n, 0)
70 # define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
71 # define mbsinit(ps) 1
72 # define iswprint(wc) ISPRINT ((unsigned char) (wc))
79 # if !defined iswprint && !HAVE_ISWPRINT
80 # define iswprint(wc) 1
84 #define INT_BITS (sizeof (int) * CHAR_BIT)
86 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
87 /* Undefine to protect against the definition in wctype.h of solaris2.6. */
91 # define ISASCII(c) isascii (c)
93 /* Undefine to protect against the definition in wctype.h of solaris2.6. */
95 #define ISPRINT(c) (ISASCII (c) && isprint (c))
97 struct quoting_options
99 /* Basic quoting style. */
100 enum quoting_style style;
102 /* Quote the characters indicated by this bit vector even if the
103 quoting style would not normally require them to be quoted. */
104 int quote_these_too[((UCHAR_MAX + 1) / INT_BITS
105 + ((UCHAR_MAX + 1) % INT_BITS != 0))];
108 /* Names of quoting styles. */
109 char const *const quoting_style_args[] =
120 /* Correspondences to quoting style names. */
121 enum quoting_style const quoting_style_vals[] =
123 literal_quoting_style,
125 shell_always_quoting_style,
127 escape_quoting_style,
131 /* The default quoting options. */
132 static struct quoting_options default_quoting_options;
134 /* Allocate a new set of quoting options, with contents initially identical
135 to O if O is not null, or to the default if O is null.
136 It is the caller's responsibility to free the result. */
137 struct quoting_options *
138 clone_quoting_options (struct quoting_options *o)
140 struct quoting_options *p
141 = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
142 *p = *(o ? o : &default_quoting_options);
146 /* Get the value of O's quoting style. If O is null, use the default. */
148 get_quoting_style (struct quoting_options *o)
150 return (o ? o : &default_quoting_options)->style;
153 /* In O (or in the default if O is null),
154 set the value of the quoting style to S. */
156 set_quoting_style (struct quoting_options *o, enum quoting_style s)
158 (o ? o : &default_quoting_options)->style = s;
161 /* In O (or in the default if O is null),
162 set the value of the quoting options for character C to I.
163 Return the old value. Currently, the only values defined for I are
164 0 (the default) and 1 (which means to quote the character even if
165 it would not otherwise be quoted). */
167 set_char_quoting (struct quoting_options *o, char c, int i)
169 unsigned char uc = c;
170 int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
171 int shift = uc % INT_BITS;
172 int r = (*p >> shift) & 1;
173 *p ^= ((i & 1) ^ r) << shift;
177 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
178 argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
179 non-quoting-style part of O to control quoting.
180 Terminate the output with a null character, and return the written
181 size of the output, not counting the terminating null.
182 If BUFFERSIZE is too small to store the output string, return the
183 value that would have been returned had BUFFERSIZE been large enough.
184 If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
186 This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
187 ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
188 style specified by O, and O may not be null. */
191 quotearg_buffer_restyled (char *buffer, size_t buffersize,
192 char const *arg, size_t argsize,
193 enum quoting_style quoting_style,
194 struct quoting_options const *o)
198 char const *quote_string = 0;
199 size_t quote_string_len = 0;
200 int backslash_escapes = 0;
205 if (len < buffersize) \
211 switch (quoting_style)
213 case c_quoting_style:
215 backslash_escapes = 1;
217 quote_string_len = 1;
220 case escape_quoting_style:
221 backslash_escapes = 1;
224 case locale_quoting_style:
225 for (quote_string = _("`"); *quote_string; quote_string++)
226 STORE (*quote_string);
227 backslash_escapes = 1;
228 quote_string = _("'");
229 quote_string_len = strlen (quote_string);
232 case shell_always_quoting_style:
235 quote_string_len = 1;
242 for (i = 0; ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize); i++)
247 if (backslash_escapes
249 && i + quote_string_len <= argsize
250 && memcmp (arg + i, quote_string, quote_string_len) == 0)
257 switch (quoting_style)
259 case shell_quoting_style:
260 goto use_shell_always_quoting_style;
262 case c_quoting_style:
263 if (i + 2 < argsize && arg[i + 1] == '?')
267 case '(': case ')': case '-': case '/':
268 case '<': case '=': case '>':
269 /* Escape the second '?' in what would otherwise be
285 case ALERT_CHAR: esc = 'a'; goto c_escape;
286 case '\b': esc = 'b'; goto c_escape;
287 case '\f': esc = 'f'; goto c_escape;
288 case '\n': esc = 'n'; goto c_and_shell_escape;
289 case '\r': esc = 'r'; goto c_and_shell_escape;
290 case '\t': esc = 't'; goto c_and_shell_escape;
291 case '\v': esc = 'v'; goto c_escape;
292 case '\\': esc = c; goto c_and_shell_escape;
295 if (quoting_style == shell_quoting_style)
296 goto use_shell_always_quoting_style;
298 if (backslash_escapes)
310 case '!': /* special in bash */
311 case '"': case '$': case '&':
312 case '(': case ')': case '*': case ';':
313 case '<': case '>': case '[':
314 case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
316 /* A shell special character. In theory, '$' and '`' could
317 be the first bytes of multibyte characters, which means
318 we should check them with mbrtowc, but in practice this
319 doesn't happen so it's not worth worrying about. */
320 if (quoting_style == shell_quoting_style)
321 goto use_shell_always_quoting_style;
325 switch (quoting_style)
327 case shell_quoting_style:
328 goto use_shell_always_quoting_style;
330 case shell_always_quoting_style:
341 case '%': case '+': case ',': case '-': case '.': case '/':
342 case '0': case '1': case '2': case '3': case '4': case '5':
343 case '6': case '7': case '8': case '9': case ':': case '=':
344 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
345 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
346 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
347 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
348 case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
349 case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
350 case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
351 case 'o': case 'p': case 'q': case 'r': case 's': case 't':
352 case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
354 /* These characters don't cause problems, no matter what the
355 quoting style is. They cannot start multibyte sequences. */
359 /* If we have a multibyte sequence, copy it until we reach
360 its end, find an error, or come back to the initial shift
361 state. For C-like styles, if the sequence has
362 unprintable characters, escape the whole sequence, since
363 we can't easily escape single characters within it. */
365 /* Length of multibyte sequence found so far. */
370 memset (&mbstate, 0, sizeof mbstate);
372 if (argsize == (size_t) -1)
373 argsize = strlen (arg);
378 size_t bytes = mbrtowc (&w, &arg[i + m],
379 argsize - (i + m), &mbstate);
382 else if (bytes == (size_t) -1)
387 else if (bytes == (size_t) -2)
390 while (i + m < argsize && arg[i + m])
401 while (! mbsinit (&mbstate));
405 /* Escape a unibyte character like a multibyte
406 sequence if using backslash escapes, and if the
407 character is not printable. */
408 m = backslash_escapes && ! ISPRINT (c);
414 /* Output a multibyte sequence, or an escaped
415 unprintable unibyte character. */
416 size_t imax = i + m - 1;
420 if (backslash_escapes && ! printable)
423 STORE ('0' + (c >> 6));
424 STORE ('0' + ((c >> 3) & 7));
438 if (! (backslash_escapes
439 && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
450 for (; *quote_string; quote_string++)
451 STORE (*quote_string);
453 if (len < buffersize)
457 use_shell_always_quoting_style:
458 return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
459 shell_always_quoting_style, o);
462 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
463 argument ARG (of size ARGSIZE), using O to control quoting.
464 If O is null, use the default.
465 Terminate the output with a null character, and return the written
466 size of the output, not counting the terminating null.
467 If BUFFERSIZE is too small to store the output string, return the
468 value that would have been returned had BUFFERSIZE been large enough.
469 If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
471 quotearg_buffer (char *buffer, size_t buffersize,
472 char const *arg, size_t argsize,
473 struct quoting_options const *o)
475 struct quoting_options const *p = o ? o : &default_quoting_options;
476 return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
480 /* Use storage slot N to return a quoted version of the string ARG.
481 OPTIONS specifies the quoting options.
482 The returned value points to static storage that can be
483 reused by the next call to this function with the same value of N.
484 N must be nonnegative. N is deliberately declared with type `int'
485 to allow for future extensions (using negative values). */
487 quotearg_n_options (int n, char const *arg,
488 struct quoting_options const *options)
490 static unsigned int nslots;
491 static struct slotvec
500 size_t s = n1 * sizeof (struct slotvec);
501 if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
503 slotvec = (struct slotvec *) xrealloc (slotvec, s);
504 memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
509 size_t size = slotvec[n].size;
510 char *val = slotvec[n].val;
511 size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
515 slotvec[n].size = size = qsize + 1;
516 slotvec[n].val = val = xrealloc (val, size);
517 quotearg_buffer (val, size, arg, (size_t) -1, options);
525 quotearg_n (unsigned int n, char const *arg)
527 return quotearg_n_options (n, arg, &default_quoting_options);
531 quotearg (char const *arg)
533 return quotearg_n (0, arg);
537 quotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
539 struct quoting_options o;
541 memset (o.quote_these_too, 0, sizeof o.quote_these_too);
542 return quotearg_n_options (n, arg, &o);
546 quotearg_style (enum quoting_style s, char const *arg)
548 return quotearg_n_style (0, s, arg);
552 quotearg_char (char const *arg, char ch)
554 struct quoting_options options;
555 options = default_quoting_options;
556 set_char_quoting (&options, ch, 1);
557 return quotearg_n_options (0, arg, &options);
561 quotearg_colon (char const *arg)
563 return quotearg_char (arg, ':');