quotearg.c revision 1.1 1 1.1 christos /* $NetBSD: quotearg.c,v 1.1 2016/01/10 21:36:18 christos Exp $ */
2 1.1 christos
3 1.1 christos /* quotearg.c - quote arguments for output
4 1.1 christos Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 2, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software Foundation,
18 1.1 christos Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 1.1 christos
20 1.1 christos /* Written by Paul Eggert <eggert (at) twinsun.com> */
21 1.1 christos
22 1.1 christos #if HAVE_CONFIG_H
23 1.1 christos # include <config.h>
24 1.1 christos #endif
25 1.1 christos
26 1.1 christos #if HAVE_STDDEF_H
27 1.1 christos # include <stddef.h> /* For the definition of size_t on windows w/MSVC. */
28 1.1 christos #endif
29 1.1 christos #include <sys/types.h>
30 1.1 christos #include <quotearg.h>
31 1.1 christos #include <xalloc.h>
32 1.1 christos
33 1.1 christos #include <ctype.h>
34 1.1 christos
35 1.1 christos #if ENABLE_NLS
36 1.1 christos # include <libintl.h>
37 1.1 christos # define _(text) gettext (text)
38 1.1 christos #else
39 1.1 christos # define _(text) text
40 1.1 christos #endif
41 1.1 christos #define N_(text) text
42 1.1 christos
43 1.1 christos #if HAVE_LIMITS_H
44 1.1 christos # include <limits.h>
45 1.1 christos #endif
46 1.1 christos #ifndef CHAR_BIT
47 1.1 christos # define CHAR_BIT 8
48 1.1 christos #endif
49 1.1 christos #ifndef UCHAR_MAX
50 1.1 christos # define UCHAR_MAX ((unsigned char) -1)
51 1.1 christos #endif
52 1.1 christos
53 1.1 christos #if HAVE_C_BACKSLASH_A
54 1.1 christos # define ALERT_CHAR '\a'
55 1.1 christos #else
56 1.1 christos # define ALERT_CHAR '\7'
57 1.1 christos #endif
58 1.1 christos
59 1.1 christos #if HAVE_STDLIB_H
60 1.1 christos # include <stdlib.h>
61 1.1 christos #endif
62 1.1 christos
63 1.1 christos #if HAVE_STRING_H
64 1.1 christos # include <string.h>
65 1.1 christos #endif
66 1.1 christos
67 1.1 christos #if HAVE_WCHAR_H
68 1.1 christos # include <wchar.h>
69 1.1 christos #endif
70 1.1 christos
71 1.1 christos #if !HAVE_MBRTOWC
72 1.1 christos /* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
73 1.1 christos other macros are defined only for documentation and to satisfy C
74 1.1 christos syntax. */
75 1.1 christos # undef MB_CUR_MAX
76 1.1 christos # define MB_CUR_MAX 1
77 1.1 christos # define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
78 1.1 christos # define mbsinit(ps) 1
79 1.1 christos # define iswprint(wc) ISPRINT ((unsigned char) (wc))
80 1.1 christos #endif
81 1.1 christos
82 1.1 christos #ifndef iswprint
83 1.1 christos # if HAVE_WCTYPE_H
84 1.1 christos # include <wctype.h>
85 1.1 christos # endif
86 1.1 christos # if !defined iswprint && !HAVE_ISWPRINT
87 1.1 christos # define iswprint(wc) 1
88 1.1 christos # endif
89 1.1 christos #endif
90 1.1 christos
91 1.1 christos #define INT_BITS (sizeof (int) * CHAR_BIT)
92 1.1 christos
93 1.1 christos #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
94 1.1 christos # define IN_CTYPE_DOMAIN(c) 1
95 1.1 christos #else
96 1.1 christos # define IN_CTYPE_DOMAIN(c) isascii(c)
97 1.1 christos #endif
98 1.1 christos
99 1.1 christos /* Undefine to protect against the definition in wctype.h of solaris2.6. */
100 1.1 christos #undef ISPRINT
101 1.1 christos #define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
102 1.1 christos
103 1.1 christos struct quoting_options
104 1.1 christos {
105 1.1 christos /* Basic quoting style. */
106 1.1 christos enum quoting_style style;
107 1.1 christos
108 1.1 christos /* Quote the characters indicated by this bit vector even if the
109 1.1 christos quoting style would not normally require them to be quoted. */
110 1.1 christos int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
111 1.1 christos };
112 1.1 christos
113 1.1 christos /* Names of quoting styles. */
114 1.1 christos char const *const quoting_style_args[] =
115 1.1 christos {
116 1.1 christos "literal",
117 1.1 christos "shell",
118 1.1 christos "shell-always",
119 1.1 christos "c",
120 1.1 christos "escape",
121 1.1 christos "locale",
122 1.1 christos "clocale",
123 1.1 christos 0
124 1.1 christos };
125 1.1 christos
126 1.1 christos /* Correspondences to quoting style names. */
127 1.1 christos enum quoting_style const quoting_style_vals[] =
128 1.1 christos {
129 1.1 christos literal_quoting_style,
130 1.1 christos shell_quoting_style,
131 1.1 christos shell_always_quoting_style,
132 1.1 christos c_quoting_style,
133 1.1 christos escape_quoting_style,
134 1.1 christos locale_quoting_style,
135 1.1 christos clocale_quoting_style
136 1.1 christos };
137 1.1 christos
138 1.1 christos /* The default quoting options. */
139 1.1 christos static struct quoting_options default_quoting_options;
140 1.1 christos
141 1.1 christos /* Allocate a new set of quoting options, with contents initially identical
142 1.1 christos to O if O is not null, or to the default if O is null.
143 1.1 christos It is the caller's responsibility to free the result. */
144 1.1 christos struct quoting_options *
145 1.1 christos clone_quoting_options (struct quoting_options *o)
146 1.1 christos {
147 1.1 christos struct quoting_options *p
148 1.1 christos = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
149 1.1 christos *p = *(o ? o : &default_quoting_options);
150 1.1 christos return p;
151 1.1 christos }
152 1.1 christos
153 1.1 christos /* Get the value of O's quoting style. If O is null, use the default. */
154 1.1 christos enum quoting_style
155 1.1 christos get_quoting_style (struct quoting_options *o)
156 1.1 christos {
157 1.1 christos return (o ? o : &default_quoting_options)->style;
158 1.1 christos }
159 1.1 christos
160 1.1 christos /* In O (or in the default if O is null),
161 1.1 christos set the value of the quoting style to S. */
162 1.1 christos void
163 1.1 christos set_quoting_style (struct quoting_options *o, enum quoting_style s)
164 1.1 christos {
165 1.1 christos (o ? o : &default_quoting_options)->style = s;
166 1.1 christos }
167 1.1 christos
168 1.1 christos /* In O (or in the default if O is null),
169 1.1 christos set the value of the quoting options for character C to I.
170 1.1 christos Return the old value. Currently, the only values defined for I are
171 1.1 christos 0 (the default) and 1 (which means to quote the character even if
172 1.1 christos it would not otherwise be quoted). */
173 1.1 christos int
174 1.1 christos set_char_quoting (struct quoting_options *o, char c, int i)
175 1.1 christos {
176 1.1 christos unsigned char uc = c;
177 1.1 christos int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
178 1.1 christos int shift = uc % INT_BITS;
179 1.1 christos int r = (*p >> shift) & 1;
180 1.1 christos *p ^= ((i & 1) ^ r) << shift;
181 1.1 christos return r;
182 1.1 christos }
183 1.1 christos
184 1.1 christos /* MSGID approximates a quotation mark. Return its translation if it
185 1.1 christos has one; otherwise, return either it or "\"", depending on S. */
186 1.1 christos static char const *
187 1.1 christos gettext_quote (char const *msgid, enum quoting_style s)
188 1.1 christos {
189 1.1 christos char const *translation = _(msgid);
190 1.1 christos if (translation == msgid && s == clocale_quoting_style)
191 1.1 christos translation = "\"";
192 1.1 christos return translation;
193 1.1 christos }
194 1.1 christos
195 1.1 christos /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
196 1.1 christos argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
197 1.1 christos non-quoting-style part of O to control quoting.
198 1.1 christos Terminate the output with a null character, and return the written
199 1.1 christos size of the output, not counting the terminating null.
200 1.1 christos If BUFFERSIZE is too small to store the output string, return the
201 1.1 christos value that would have been returned had BUFFERSIZE been large enough.
202 1.1 christos If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
203 1.1 christos
204 1.1 christos This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
205 1.1 christos ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
206 1.1 christos style specified by O, and O may not be null. */
207 1.1 christos
208 1.1 christos static size_t
209 1.1 christos quotearg_buffer_restyled (char *buffer, size_t buffersize,
210 1.1 christos char const *arg, size_t argsize,
211 1.1 christos enum quoting_style quoting_style,
212 1.1 christos struct quoting_options const *o)
213 1.1 christos {
214 1.1 christos size_t i;
215 1.1 christos size_t len = 0;
216 1.1 christos char const *quote_string = 0;
217 1.1 christos size_t quote_string_len = 0;
218 1.1 christos int backslash_escapes = 0;
219 1.1 christos int unibyte_locale = MB_CUR_MAX == 1;
220 1.1 christos
221 1.1 christos #define STORE(c) \
222 1.1 christos do \
223 1.1 christos { \
224 1.1 christos if (len < buffersize) \
225 1.1 christos buffer[len] = (c); \
226 1.1 christos len++; \
227 1.1 christos } \
228 1.1 christos while (0)
229 1.1 christos
230 1.1 christos switch (quoting_style)
231 1.1 christos {
232 1.1 christos case c_quoting_style:
233 1.1 christos STORE ('"');
234 1.1 christos backslash_escapes = 1;
235 1.1 christos quote_string = "\"";
236 1.1 christos quote_string_len = 1;
237 1.1 christos break;
238 1.1 christos
239 1.1 christos case escape_quoting_style:
240 1.1 christos backslash_escapes = 1;
241 1.1 christos break;
242 1.1 christos
243 1.1 christos case locale_quoting_style:
244 1.1 christos case clocale_quoting_style:
245 1.1 christos {
246 1.1 christos /* Get translations for open and closing quotation marks.
247 1.1 christos
248 1.1 christos The message catalog should translate "`" to a left
249 1.1 christos quotation mark suitable for the locale, and similarly for
250 1.1 christos "'". If the catalog has no translation,
251 1.1 christos locale_quoting_style quotes `like this', and
252 1.1 christos clocale_quoting_style quotes "like this".
253 1.1 christos
254 1.1 christos For example, an American English Unicode locale should
255 1.1 christos translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
256 1.1 christos should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
257 1.1 christos MARK). A British English Unicode locale should instead
258 1.1 christos translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
259 1.1 christos U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. */
260 1.1 christos
261 1.1 christos char const *left = gettext_quote (N_("`"), quoting_style);
262 1.1 christos char const *right = gettext_quote (N_("'"), quoting_style);
263 1.1 christos for (quote_string = left; *quote_string; quote_string++)
264 1.1 christos STORE (*quote_string);
265 1.1 christos backslash_escapes = 1;
266 1.1 christos quote_string = right;
267 1.1 christos quote_string_len = strlen (quote_string);
268 1.1 christos }
269 1.1 christos break;
270 1.1 christos
271 1.1 christos case shell_always_quoting_style:
272 1.1 christos STORE ('\'');
273 1.1 christos quote_string = "'";
274 1.1 christos quote_string_len = 1;
275 1.1 christos break;
276 1.1 christos
277 1.1 christos default:
278 1.1 christos break;
279 1.1 christos }
280 1.1 christos
281 1.1 christos for (i = 0; ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize); i++)
282 1.1 christos {
283 1.1 christos unsigned char c;
284 1.1 christos unsigned char esc;
285 1.1 christos
286 1.1 christos if (backslash_escapes
287 1.1 christos && quote_string_len
288 1.1 christos && i + quote_string_len <= argsize
289 1.1 christos && memcmp (arg + i, quote_string, quote_string_len) == 0)
290 1.1 christos STORE ('\\');
291 1.1 christos
292 1.1 christos c = arg[i];
293 1.1 christos switch (c)
294 1.1 christos {
295 1.1 christos case '?':
296 1.1 christos switch (quoting_style)
297 1.1 christos {
298 1.1 christos case shell_quoting_style:
299 1.1 christos goto use_shell_always_quoting_style;
300 1.1 christos
301 1.1 christos case c_quoting_style:
302 1.1 christos if (i + 2 < argsize && arg[i + 1] == '?')
303 1.1 christos switch (arg[i + 2])
304 1.1 christos {
305 1.1 christos case '!': case '\'':
306 1.1 christos case '(': case ')': case '-': case '/':
307 1.1 christos case '<': case '=': case '>':
308 1.1 christos /* Escape the second '?' in what would otherwise be
309 1.1 christos a trigraph. */
310 1.1 christos i += 2;
311 1.1 christos c = arg[i + 2];
312 1.1 christos STORE ('?');
313 1.1 christos STORE ('\\');
314 1.1 christos STORE ('?');
315 1.1 christos break;
316 1.1 christos }
317 1.1 christos break;
318 1.1 christos
319 1.1 christos default:
320 1.1 christos break;
321 1.1 christos }
322 1.1 christos break;
323 1.1 christos
324 1.1 christos case ALERT_CHAR: esc = 'a'; goto c_escape;
325 1.1 christos case '\b': esc = 'b'; goto c_escape;
326 1.1 christos case '\f': esc = 'f'; goto c_escape;
327 1.1 christos case '\n': esc = 'n'; goto c_and_shell_escape;
328 1.1 christos case '\r': esc = 'r'; goto c_and_shell_escape;
329 1.1 christos case '\t': esc = 't'; goto c_and_shell_escape;
330 1.1 christos case '\v': esc = 'v'; goto c_escape;
331 1.1 christos case '\\': esc = c; goto c_and_shell_escape;
332 1.1 christos
333 1.1 christos c_and_shell_escape:
334 1.1 christos if (quoting_style == shell_quoting_style)
335 1.1 christos goto use_shell_always_quoting_style;
336 1.1 christos c_escape:
337 1.1 christos if (backslash_escapes)
338 1.1 christos {
339 1.1 christos c = esc;
340 1.1 christos goto store_escape;
341 1.1 christos }
342 1.1 christos break;
343 1.1 christos
344 1.1 christos case '#': case '~':
345 1.1 christos if (i != 0)
346 1.1 christos break;
347 1.1 christos /* Fall through. */
348 1.1 christos case ' ':
349 1.1 christos case '!': /* special in bash */
350 1.1 christos case '"': case '$': case '&':
351 1.1 christos case '(': case ')': case '*': case ';':
352 1.1 christos case '<': case '>': case '[':
353 1.1 christos case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
354 1.1 christos case '`': case '|':
355 1.1 christos /* A shell special character. In theory, '$' and '`' could
356 1.1 christos be the first bytes of multibyte characters, which means
357 1.1 christos we should check them with mbrtowc, but in practice this
358 1.1 christos doesn't happen so it's not worth worrying about. */
359 1.1 christos if (quoting_style == shell_quoting_style)
360 1.1 christos goto use_shell_always_quoting_style;
361 1.1 christos break;
362 1.1 christos
363 1.1 christos case '\'':
364 1.1 christos switch (quoting_style)
365 1.1 christos {
366 1.1 christos case shell_quoting_style:
367 1.1 christos goto use_shell_always_quoting_style;
368 1.1 christos
369 1.1 christos case shell_always_quoting_style:
370 1.1 christos STORE ('\'');
371 1.1 christos STORE ('\\');
372 1.1 christos STORE ('\'');
373 1.1 christos break;
374 1.1 christos
375 1.1 christos default:
376 1.1 christos break;
377 1.1 christos }
378 1.1 christos break;
379 1.1 christos
380 1.1 christos case '%': case '+': case ',': case '-': case '.': case '/':
381 1.1 christos case '0': case '1': case '2': case '3': case '4': case '5':
382 1.1 christos case '6': case '7': case '8': case '9': case ':': case '=':
383 1.1 christos case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
384 1.1 christos case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
385 1.1 christos case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
386 1.1 christos case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
387 1.1 christos case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
388 1.1 christos case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
389 1.1 christos case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
390 1.1 christos case 'o': case 'p': case 'q': case 'r': case 's': case 't':
391 1.1 christos case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
392 1.1 christos case '{': case '}':
393 1.1 christos /* These characters don't cause problems, no matter what the
394 1.1 christos quoting style is. They cannot start multibyte sequences. */
395 1.1 christos break;
396 1.1 christos
397 1.1 christos default:
398 1.1 christos /* If we have a multibyte sequence, copy it until we reach
399 1.1 christos its end, find an error, or come back to the initial shift
400 1.1 christos state. For C-like styles, if the sequence has
401 1.1 christos unprintable characters, escape the whole sequence, since
402 1.1 christos we can't easily escape single characters within it. */
403 1.1 christos {
404 1.1 christos /* Length of multibyte sequence found so far. */
405 1.1 christos size_t m;
406 1.1 christos
407 1.1 christos int printable;
408 1.1 christos
409 1.1 christos if (unibyte_locale)
410 1.1 christos {
411 1.1 christos m = 1;
412 1.1 christos printable = ISPRINT (c);
413 1.1 christos }
414 1.1 christos else
415 1.1 christos {
416 1.1 christos mbstate_t mbstate;
417 1.1 christos memset (&mbstate, 0, sizeof mbstate);
418 1.1 christos
419 1.1 christos m = 0;
420 1.1 christos printable = 1;
421 1.1 christos if (argsize == (size_t) -1)
422 1.1 christos argsize = strlen (arg);
423 1.1 christos
424 1.1 christos do
425 1.1 christos {
426 1.1 christos wchar_t w;
427 1.1 christos size_t bytes = mbrtowc (&w, &arg[i + m],
428 1.1 christos argsize - (i + m), &mbstate);
429 1.1 christos if (bytes == 0)
430 1.1 christos break;
431 1.1 christos else if (bytes == (size_t) -1)
432 1.1 christos {
433 1.1 christos printable = 0;
434 1.1 christos break;
435 1.1 christos }
436 1.1 christos else if (bytes == (size_t) -2)
437 1.1 christos {
438 1.1 christos printable = 0;
439 1.1 christos while (i + m < argsize && arg[i + m])
440 1.1 christos m++;
441 1.1 christos break;
442 1.1 christos }
443 1.1 christos else
444 1.1 christos {
445 1.1 christos if (! iswprint (w))
446 1.1 christos printable = 0;
447 1.1 christos m += bytes;
448 1.1 christos }
449 1.1 christos }
450 1.1 christos while (! mbsinit (&mbstate));
451 1.1 christos }
452 1.1 christos
453 1.1 christos if (1 < m || (backslash_escapes && ! printable))
454 1.1 christos {
455 1.1 christos /* Output a multibyte sequence, or an escaped
456 1.1 christos unprintable unibyte character. */
457 1.1 christos size_t ilim = i + m;
458 1.1 christos
459 1.1 christos for (;;)
460 1.1 christos {
461 1.1 christos if (backslash_escapes && ! printable)
462 1.1 christos {
463 1.1 christos STORE ('\\');
464 1.1 christos STORE ('0' + (c >> 6));
465 1.1 christos STORE ('0' + ((c >> 3) & 7));
466 1.1 christos c = '0' + (c & 7);
467 1.1 christos }
468 1.1 christos if (ilim <= i + 1)
469 1.1 christos break;
470 1.1 christos STORE (c);
471 1.1 christos c = arg[++i];
472 1.1 christos }
473 1.1 christos
474 1.1 christos goto store_c;
475 1.1 christos }
476 1.1 christos }
477 1.1 christos }
478 1.1 christos
479 1.1 christos if (! (backslash_escapes
480 1.1 christos && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
481 1.1 christos goto store_c;
482 1.1 christos
483 1.1 christos store_escape:
484 1.1 christos STORE ('\\');
485 1.1 christos
486 1.1 christos store_c:
487 1.1 christos STORE (c);
488 1.1 christos }
489 1.1 christos
490 1.1 christos if (quote_string)
491 1.1 christos for (; *quote_string; quote_string++)
492 1.1 christos STORE (*quote_string);
493 1.1 christos
494 1.1 christos if (len < buffersize)
495 1.1 christos buffer[len] = '\0';
496 1.1 christos return len;
497 1.1 christos
498 1.1 christos use_shell_always_quoting_style:
499 1.1 christos return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
500 1.1 christos shell_always_quoting_style, o);
501 1.1 christos }
502 1.1 christos
503 1.1 christos /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
504 1.1 christos argument ARG (of size ARGSIZE), using O to control quoting.
505 1.1 christos If O is null, use the default.
506 1.1 christos Terminate the output with a null character, and return the written
507 1.1 christos size of the output, not counting the terminating null.
508 1.1 christos If BUFFERSIZE is too small to store the output string, return the
509 1.1 christos value that would have been returned had BUFFERSIZE been large enough.
510 1.1 christos If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
511 1.1 christos size_t
512 1.1 christos quotearg_buffer (char *buffer, size_t buffersize,
513 1.1 christos char const *arg, size_t argsize,
514 1.1 christos struct quoting_options const *o)
515 1.1 christos {
516 1.1 christos struct quoting_options const *p = o ? o : &default_quoting_options;
517 1.1 christos return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
518 1.1 christos p->style, p);
519 1.1 christos }
520 1.1 christos
521 1.1 christos /* Use storage slot N to return a quoted version of the string ARG.
522 1.1 christos OPTIONS specifies the quoting options.
523 1.1 christos The returned value points to static storage that can be
524 1.1 christos reused by the next call to this function with the same value of N.
525 1.1 christos N must be nonnegative. N is deliberately declared with type "int"
526 1.1 christos to allow for future extensions (using negative values). */
527 1.1 christos static char *
528 1.1 christos quotearg_n_options (int n, char const *arg,
529 1.1 christos struct quoting_options const *options)
530 1.1 christos {
531 1.1 christos /* Preallocate a slot 0 buffer, so that the caller can always quote
532 1.1 christos one small component of a "memory exhausted" message in slot 0. */
533 1.1 christos static char slot0[256];
534 1.1 christos static unsigned int nslots = 1;
535 1.1 christos struct slotvec
536 1.1 christos {
537 1.1 christos size_t size;
538 1.1 christos char *val;
539 1.1 christos };
540 1.1 christos static struct slotvec slotvec0 = {sizeof slot0, slot0};
541 1.1 christos static struct slotvec *slotvec = &slotvec0;
542 1.1 christos
543 1.1 christos if (nslots <= n)
544 1.1 christos {
545 1.1 christos int n1 = n + 1;
546 1.1 christos size_t s = n1 * sizeof (struct slotvec);
547 1.1 christos if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
548 1.1 christos abort ();
549 1.1 christos if (slotvec == &slotvec0)
550 1.1 christos {
551 1.1 christos slotvec = (struct slotvec *) xmalloc (sizeof (struct slotvec));
552 1.1 christos *slotvec = slotvec0;
553 1.1 christos }
554 1.1 christos slotvec = (struct slotvec *) xrealloc (slotvec, s);
555 1.1 christos memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
556 1.1 christos nslots = n;
557 1.1 christos }
558 1.1 christos
559 1.1 christos {
560 1.1 christos size_t size = slotvec[n].size;
561 1.1 christos char *val = slotvec[n].val;
562 1.1 christos size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
563 1.1 christos
564 1.1 christos if (size <= qsize)
565 1.1 christos {
566 1.1 christos slotvec[n].size = size = qsize + 1;
567 1.1 christos slotvec[n].val = val = xrealloc (val == slot0 ? 0 : val, size);
568 1.1 christos quotearg_buffer (val, size, arg, (size_t) -1, options);
569 1.1 christos }
570 1.1 christos
571 1.1 christos return val;
572 1.1 christos }
573 1.1 christos }
574 1.1 christos
575 1.1 christos char *
576 1.1 christos quotearg_n (unsigned int n, char const *arg)
577 1.1 christos {
578 1.1 christos return quotearg_n_options (n, arg, &default_quoting_options);
579 1.1 christos }
580 1.1 christos
581 1.1 christos char *
582 1.1 christos quotearg (char const *arg)
583 1.1 christos {
584 1.1 christos return quotearg_n (0, arg);
585 1.1 christos }
586 1.1 christos
587 1.1 christos char *
588 1.1 christos quotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
589 1.1 christos {
590 1.1 christos struct quoting_options o;
591 1.1 christos o.style = s;
592 1.1 christos memset (o.quote_these_too, 0, sizeof o.quote_these_too);
593 1.1 christos return quotearg_n_options (n, arg, &o);
594 1.1 christos }
595 1.1 christos
596 1.1 christos char *
597 1.1 christos quotearg_style (enum quoting_style s, char const *arg)
598 1.1 christos {
599 1.1 christos return quotearg_n_style (0, s, arg);
600 1.1 christos }
601 1.1 christos
602 1.1 christos char *
603 1.1 christos quotearg_char (char const *arg, char ch)
604 1.1 christos {
605 1.1 christos struct quoting_options options;
606 1.1 christos options = default_quoting_options;
607 1.1 christos set_char_quoting (&options, ch, 1);
608 1.1 christos return quotearg_n_options (0, arg, &options);
609 1.1 christos }
610 1.1 christos
611 1.1 christos char *
612 1.1 christos quotearg_colon (char const *arg)
613 1.1 christos {
614 1.1 christos return quotearg_char (arg, ':');
615 1.1 christos }
616