quotearg.c revision 1.2 1 1.1 christos /* quotearg.c - quote arguments for output
2 1.1 christos
3 1.1 christos Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software
4 1.1 christos 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 #ifdef HAVE_CONFIG_H
23 1.1 christos # include <config.h>
24 1.1 christos #endif
25 1.1 christos
26 1.1 christos #include "quotearg.h"
27 1.1 christos
28 1.1 christos #include "xalloc.h"
29 1.1 christos
30 1.1 christos #include <ctype.h>
31 1.1 christos #include <errno.h>
32 1.1 christos #include <limits.h>
33 1.1 christos #include <stdbool.h>
34 1.1 christos #include <stdlib.h>
35 1.1 christos #include <string.h>
36 1.1 christos
37 1.1 christos #include "gettext.h"
38 1.1 christos #define _(msgid) gettext (msgid)
39 1.1 christos #define N_(msgid) msgid
40 1.1 christos
41 1.1 christos #if HAVE_WCHAR_H
42 1.1 christos
43 1.1 christos /* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared. */
44 1.1 christos # include <stdio.h>
45 1.1 christos # include <time.h>
46 1.1 christos
47 1.1 christos # include <wchar.h>
48 1.1 christos #endif
49 1.1 christos
50 1.1 christos #if !HAVE_MBRTOWC
51 1.1 christos /* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the
52 1.1 christos other macros are defined only for documentation and to satisfy C
53 1.1 christos syntax. */
54 1.1 christos # undef MB_CUR_MAX
55 1.1 christos # define MB_CUR_MAX 1
56 1.1 christos # define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
57 1.1 christos # define iswprint(wc) isprint ((unsigned char) (wc))
58 1.1 christos # undef HAVE_MBSINIT
59 1.1 christos #endif
60 1.1 christos
61 1.1 christos #if !defined mbsinit && !HAVE_MBSINIT
62 1.1 christos # define mbsinit(ps) 1
63 1.1 christos #endif
64 1.1 christos
65 1.1 christos #ifndef iswprint
66 1.1 christos # if HAVE_WCTYPE_H
67 1.1 christos # include <wctype.h>
68 1.1 christos # endif
69 1.1 christos # if !defined iswprint && !HAVE_ISWPRINT
70 1.1 christos # define iswprint(wc) 1
71 1.1 christos # endif
72 1.1 christos #endif
73 1.1 christos
74 1.1 christos #ifndef SIZE_MAX
75 1.1 christos # define SIZE_MAX ((size_t) -1)
76 1.1 christos #endif
77 1.1 christos
78 1.1 christos #define INT_BITS (sizeof (int) * CHAR_BIT)
79 1.1 christos
80 1.1 christos struct quoting_options
81 1.1 christos {
82 1.1 christos /* Basic quoting style. */
83 1.1 christos enum quoting_style style;
84 1.1 christos
85 1.1 christos /* Quote the characters indicated by this bit vector even if the
86 1.1 christos quoting style would not normally require them to be quoted. */
87 1.1 christos unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
88 1.1 christos };
89 1.1 christos
90 1.1 christos /* Names of quoting styles. */
91 1.1 christos char const *const quoting_style_args[] =
92 1.1 christos {
93 1.1 christos "literal",
94 1.1 christos "shell",
95 1.1 christos "shell-always",
96 1.1 christos "c",
97 1.1 christos "escape",
98 1.1 christos "locale",
99 1.1 christos "clocale",
100 1.1 christos 0
101 1.1 christos };
102 1.1 christos
103 1.1 christos /* Correspondences to quoting style names. */
104 1.1 christos enum quoting_style const quoting_style_vals[] =
105 1.1 christos {
106 1.1 christos literal_quoting_style,
107 1.1 christos shell_quoting_style,
108 1.1 christos shell_always_quoting_style,
109 1.1 christos c_quoting_style,
110 1.1 christos escape_quoting_style,
111 1.1 christos locale_quoting_style,
112 1.1 christos clocale_quoting_style
113 1.1 christos };
114 1.1 christos
115 1.1 christos /* The default quoting options. */
116 1.1 christos static struct quoting_options default_quoting_options;
117 1.1 christos
118 1.1 christos /* Allocate a new set of quoting options, with contents initially identical
119 1.1 christos to O if O is not null, or to the default if O is null.
120 1.1 christos It is the caller's responsibility to free the result. */
121 1.1 christos struct quoting_options *
122 1.1 christos clone_quoting_options (struct quoting_options *o)
123 1.1 christos {
124 1.1 christos int e = errno;
125 1.1 christos struct quoting_options *p = xmalloc (sizeof *p);
126 1.1 christos *p = *(o ? o : &default_quoting_options);
127 1.1 christos errno = e;
128 1.1 christos return p;
129 1.1 christos }
130 1.1 christos
131 1.1 christos /* Get the value of O's quoting style. If O is null, use the default. */
132 1.1 christos enum quoting_style
133 1.1 christos get_quoting_style (struct quoting_options *o)
134 1.1 christos {
135 1.1 christos return (o ? o : &default_quoting_options)->style;
136 1.1 christos }
137 1.1 christos
138 1.1 christos /* In O (or in the default if O is null),
139 1.1 christos set the value of the quoting style to S. */
140 1.1 christos void
141 1.1 christos set_quoting_style (struct quoting_options *o, enum quoting_style s)
142 1.1 christos {
143 1.1 christos (o ? o : &default_quoting_options)->style = s;
144 1.1 christos }
145 1.1 christos
146 1.1 christos /* In O (or in the default if O is null),
147 1.1 christos set the value of the quoting options for character C to I.
148 1.1 christos Return the old value. Currently, the only values defined for I are
149 1.1 christos 0 (the default) and 1 (which means to quote the character even if
150 1.1 christos it would not otherwise be quoted). */
151 1.1 christos int
152 1.1 christos set_char_quoting (struct quoting_options *o, char c, int i)
153 1.1 christos {
154 1.1 christos unsigned char uc = c;
155 1.1 christos unsigned int *p =
156 1.1 christos (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
157 1.1 christos int shift = uc % INT_BITS;
158 1.1 christos int r = (*p >> shift) & 1;
159 1.1 christos *p ^= ((i & 1) ^ r) << shift;
160 1.1 christos return r;
161 1.1 christos }
162 1.1 christos
163 1.1 christos /* MSGID approximates a quotation mark. Return its translation if it
164 1.1 christos has one; otherwise, return either it or "\"", depending on S. */
165 1.1 christos static char const *
166 1.1 christos gettext_quote (char const *msgid, enum quoting_style s)
167 1.1 christos {
168 1.1 christos char const *translation = _(msgid);
169 1.1 christos if (translation == msgid && s == clocale_quoting_style)
170 1.1 christos translation = "\"";
171 1.1 christos return translation;
172 1.1 christos }
173 1.1 christos
174 1.1 christos /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
175 1.1 christos argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
176 1.1 christos non-quoting-style part of O to control quoting.
177 1.1 christos Terminate the output with a null character, and return the written
178 1.1 christos size of the output, not counting the terminating null.
179 1.1 christos If BUFFERSIZE is too small to store the output string, return the
180 1.1 christos value that would have been returned had BUFFERSIZE been large enough.
181 1.1 christos If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
182 1.1 christos
183 1.1 christos This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
184 1.1 christos ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
185 1.1 christos style specified by O, and O may not be null. */
186 1.1 christos
187 1.1 christos static size_t
188 1.1 christos quotearg_buffer_restyled (char *buffer, size_t buffersize,
189 1.1 christos char const *arg, size_t argsize,
190 1.1 christos enum quoting_style quoting_style,
191 1.1 christos struct quoting_options const *o)
192 1.1 christos {
193 1.1 christos size_t i;
194 1.1 christos size_t len = 0;
195 1.1 christos char const *quote_string = 0;
196 1.1 christos size_t quote_string_len = 0;
197 1.1 christos bool backslash_escapes = false;
198 1.1 christos bool unibyte_locale = MB_CUR_MAX == 1;
199 1.1 christos
200 1.1 christos #define STORE(c) \
201 1.1 christos do \
202 1.1 christos { \
203 1.1 christos if (len < buffersize) \
204 1.1 christos buffer[len] = (c); \
205 1.1 christos len++; \
206 1.1 christos } \
207 1.1 christos while (0)
208 1.1 christos
209 1.1 christos switch (quoting_style)
210 1.1 christos {
211 1.1 christos case c_quoting_style:
212 1.1 christos STORE ('"');
213 1.1 christos backslash_escapes = true;
214 1.1 christos quote_string = "\"";
215 1.1 christos quote_string_len = 1;
216 1.1 christos break;
217 1.1 christos
218 1.1 christos case escape_quoting_style:
219 1.1 christos backslash_escapes = true;
220 1.1 christos break;
221 1.1 christos
222 1.1 christos case locale_quoting_style:
223 1.1 christos case clocale_quoting_style:
224 1.1 christos {
225 1.1 christos /* TRANSLATORS:
226 1.1 christos Get translations for open and closing quotation marks.
227 1.1 christos
228 1.1 christos The message catalog should translate "`" to a left
229 1.1 christos quotation mark suitable for the locale, and similarly for
230 1.1 christos "'". If the catalog has no translation,
231 1.1 christos locale_quoting_style quotes `like this', and
232 1.1 christos clocale_quoting_style quotes "like this".
233 1.1 christos
234 1.1 christos For example, an American English Unicode locale should
235 1.1 christos translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
236 1.1 christos should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
237 1.1 christos MARK). A British English Unicode locale should instead
238 1.1 christos translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
239 1.1 christos U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
240 1.1 christos
241 1.1 christos If you don't know what to put here, please see
242 1.1 christos <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
243 1.1 christos and use glyphs suitable for your language. */
244 1.1 christos
245 1.1 christos char const *left = gettext_quote (N_("`"), quoting_style);
246 1.1 christos char const *right = gettext_quote (N_("'"), quoting_style);
247 1.1 christos for (quote_string = left; *quote_string; quote_string++)
248 1.1 christos STORE (*quote_string);
249 1.1 christos backslash_escapes = true;
250 1.1 christos quote_string = right;
251 1.1 christos quote_string_len = strlen (quote_string);
252 1.1 christos }
253 1.1 christos break;
254 1.1 christos
255 1.1 christos case shell_always_quoting_style:
256 1.1 christos STORE ('\'');
257 1.1 christos quote_string = "'";
258 1.1 christos quote_string_len = 1;
259 1.1 christos break;
260 1.1 christos
261 1.1 christos default:
262 1.1 christos break;
263 1.1 christos }
264 1.1 christos
265 1.1 christos for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
266 1.1 christos {
267 1.1 christos unsigned char c;
268 1.1 christos unsigned char esc;
269 1.1 christos
270 1.1 christos if (backslash_escapes
271 1.1 christos && quote_string_len
272 1.1 christos && i + quote_string_len <= argsize
273 1.1 christos && memcmp (arg + i, quote_string, quote_string_len) == 0)
274 1.1 christos STORE ('\\');
275 1.1 christos
276 1.1 christos c = arg[i];
277 1.1 christos switch (c)
278 1.1 christos {
279 1.1 christos case '\0':
280 1.1 christos if (backslash_escapes)
281 1.1 christos {
282 1.1 christos STORE ('\\');
283 1.1 christos STORE ('0');
284 1.1 christos STORE ('0');
285 1.1 christos c = '0';
286 1.1 christos }
287 1.1 christos break;
288 1.1 christos
289 1.1 christos case '?':
290 1.1 christos switch (quoting_style)
291 1.1 christos {
292 1.1 christos case shell_quoting_style:
293 1.1 christos goto use_shell_always_quoting_style;
294 1.1 christos
295 1.1 christos case c_quoting_style:
296 1.1 christos if (i + 2 < argsize && arg[i + 1] == '?')
297 1.1 christos switch (arg[i + 2])
298 1.1 christos {
299 1.1 christos case '!': case '\'':
300 1.1 christos case '(': case ')': case '-': case '/':
301 1.1 christos case '<': case '=': case '>':
302 1.1 christos /* Escape the second '?' in what would otherwise be
303 1.1 christos a trigraph. */
304 1.1 christos c = arg[i + 2];
305 1.1 christos i += 2;
306 1.1 christos STORE ('?');
307 1.1 christos STORE ('\\');
308 1.1 christos STORE ('?');
309 1.1 christos break;
310 1.1 christos }
311 1.1 christos break;
312 1.1 christos
313 1.1 christos default:
314 1.1 christos break;
315 1.1 christos }
316 1.1 christos break;
317 1.1 christos
318 1.1 christos case '\a': esc = 'a'; goto c_escape;
319 1.1 christos case '\b': esc = 'b'; goto c_escape;
320 1.1 christos case '\f': esc = 'f'; goto c_escape;
321 1.1 christos case '\n': esc = 'n'; goto c_and_shell_escape;
322 1.1 christos case '\r': esc = 'r'; goto c_and_shell_escape;
323 1.1 christos case '\t': esc = 't'; goto c_and_shell_escape;
324 1.1 christos case '\v': esc = 'v'; goto c_escape;
325 1.1 christos case '\\': esc = c; goto c_and_shell_escape;
326 1.1 christos
327 1.1 christos c_and_shell_escape:
328 1.1 christos if (quoting_style == shell_quoting_style)
329 1.1 christos goto use_shell_always_quoting_style;
330 1.1 christos c_escape:
331 1.1 christos if (backslash_escapes)
332 1.1 christos {
333 1.1 christos c = esc;
334 1.1 christos goto store_escape;
335 1.1 christos }
336 1.1 christos break;
337 1.1 christos
338 1.1 christos case '{': case '}': /* sometimes special if isolated */
339 1.1 christos if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
340 1.1 christos break;
341 1.1 christos /* Fall through. */
342 1.1 christos case '#': case '~':
343 1.1 christos if (i != 0)
344 1.1 christos break;
345 1.1 christos /* Fall through. */
346 1.1 christos case ' ':
347 1.1 christos case '!': /* special in bash */
348 1.1 christos case '"': case '$': case '&':
349 1.1 christos case '(': case ')': case '*': case ';':
350 1.1 christos case '<':
351 1.1 christos case '=': /* sometimes special in 0th or (with "set -k") later args */
352 1.1 christos 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 ':':
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 /* These characters don't cause problems, no matter what the
393 1.1 christos quoting style is. They cannot start multibyte sequences. */
394 1.1 christos break;
395 1.1 christos
396 1.1 christos default:
397 1.1 christos /* If we have a multibyte sequence, copy it until we reach
398 1.1 christos its end, find an error, or come back to the initial shift
399 1.1 christos state. For C-like styles, if the sequence has
400 1.1 christos unprintable characters, escape the whole sequence, since
401 1.1 christos we can't easily escape single characters within it. */
402 1.1 christos {
403 1.1 christos /* Length of multibyte sequence found so far. */
404 1.1 christos size_t m;
405 1.1 christos
406 1.1 christos bool printable;
407 1.1 christos
408 1.1 christos if (unibyte_locale)
409 1.1 christos {
410 1.1 christos m = 1;
411 1.1 christos printable = isprint (c) != 0;
412 1.1 christos }
413 1.1 christos else
414 1.1 christos {
415 1.1 christos mbstate_t mbstate;
416 1.1 christos memset (&mbstate, 0, sizeof mbstate);
417 1.1 christos
418 1.1 christos m = 0;
419 1.1 christos printable = true;
420 1.1 christos if (argsize == SIZE_MAX)
421 1.1 christos argsize = strlen (arg);
422 1.1 christos
423 1.1 christos do
424 1.1 christos {
425 1.1 christos wchar_t w;
426 1.1 christos size_t bytes = mbrtowc (&w, &arg[i + m],
427 1.1 christos argsize - (i + m), &mbstate);
428 1.1 christos if (bytes == 0)
429 1.1 christos break;
430 1.1 christos else if (bytes == (size_t) -1)
431 1.1 christos {
432 1.1 christos printable = false;
433 1.1 christos break;
434 1.1 christos }
435 1.1 christos else if (bytes == (size_t) -2)
436 1.1 christos {
437 1.1 christos printable = false;
438 1.1 christos while (i + m < argsize && arg[i + m])
439 1.1 christos m++;
440 1.1 christos break;
441 1.1 christos }
442 1.1 christos else
443 1.1 christos {
444 1.1 christos /* Work around a bug with older shells that "see" a '\'
445 1.1 christos that is really the 2nd byte of a multibyte character.
446 1.1 christos In practice the problem is limited to ASCII
447 1.1 christos chars >= '@' that are shell special chars. */
448 1.1 christos if ('[' == 0x5b && quoting_style == shell_quoting_style)
449 1.1 christos {
450 1.1 christos size_t j;
451 1.1 christos for (j = 1; j < bytes; j++)
452 1.1 christos switch (arg[i + m + j])
453 1.1 christos {
454 1.1 christos case '[': case '\\': case '^':
455 1.1 christos case '`': case '|':
456 1.1 christos goto use_shell_always_quoting_style;
457 1.1 christos }
458 1.1 christos }
459 1.1 christos
460 1.1 christos if (! iswprint (w))
461 1.1 christos printable = false;
462 1.1 christos m += bytes;
463 1.1 christos }
464 1.1 christos }
465 1.1 christos while (! mbsinit (&mbstate));
466 1.1 christos }
467 1.1 christos
468 1.1 christos if (1 < m || (backslash_escapes && ! printable))
469 1.1 christos {
470 1.1 christos /* Output a multibyte sequence, or an escaped
471 1.1 christos unprintable unibyte character. */
472 1.1 christos size_t ilim = i + m;
473 1.1 christos
474 1.1 christos for (;;)
475 1.1 christos {
476 1.1 christos if (backslash_escapes && ! printable)
477 1.1 christos {
478 1.1 christos STORE ('\\');
479 1.1 christos STORE ('0' + (c >> 6));
480 1.1 christos STORE ('0' + ((c >> 3) & 7));
481 1.1 christos c = '0' + (c & 7);
482 1.1 christos }
483 1.1 christos if (ilim <= i + 1)
484 1.1 christos break;
485 1.1 christos STORE (c);
486 1.1 christos c = arg[++i];
487 1.1 christos }
488 1.1 christos
489 1.1 christos goto store_c;
490 1.1 christos }
491 1.1 christos }
492 1.1 christos }
493 1.1 christos
494 1.1 christos if (! (backslash_escapes
495 1.1 christos && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
496 1.1 christos goto store_c;
497 1.1 christos
498 1.1 christos store_escape:
499 1.1 christos STORE ('\\');
500 1.1 christos
501 1.1 christos store_c:
502 1.1 christos STORE (c);
503 1.1 christos }
504 1.1 christos
505 1.1 christos if (i == 0 && quoting_style == shell_quoting_style)
506 1.1 christos goto use_shell_always_quoting_style;
507 1.1 christos
508 1.1 christos if (quote_string)
509 1.1 christos for (; *quote_string; quote_string++)
510 1.1 christos STORE (*quote_string);
511 1.1 christos
512 1.1 christos if (len < buffersize)
513 1.1 christos buffer[len] = '\0';
514 1.1 christos return len;
515 1.1 christos
516 1.1 christos use_shell_always_quoting_style:
517 1.1 christos return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
518 1.1 christos shell_always_quoting_style, o);
519 1.1 christos }
520 1.1 christos
521 1.1 christos /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
522 1.1 christos argument ARG (of size ARGSIZE), using O to control quoting.
523 1.1 christos If O is null, use the default.
524 1.1 christos Terminate the output with a null character, and return the written
525 1.1 christos size of the output, not counting the terminating null.
526 1.1 christos If BUFFERSIZE is too small to store the output string, return the
527 1.1 christos value that would have been returned had BUFFERSIZE been large enough.
528 1.1 christos If ARGSIZE is SIZE_MAX, use the string length of the argument for
529 1.1 christos ARGSIZE. */
530 1.1 christos size_t
531 1.1 christos quotearg_buffer (char *buffer, size_t buffersize,
532 1.1 christos char const *arg, size_t argsize,
533 1.1 christos struct quoting_options const *o)
534 1.1 christos {
535 1.1 christos struct quoting_options const *p = o ? o : &default_quoting_options;
536 1.1 christos int e = errno;
537 1.1 christos size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
538 1.1 christos p->style, p);
539 1.1 christos errno = e;
540 1.1 christos return r;
541 1.1 christos }
542 1.1 christos
543 1.1 christos /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
544 1.1 christos allocated storage containing the quoted string. */
545 1.1 christos char *
546 1.1 christos quotearg_alloc (char const *arg, size_t argsize,
547 1.1 christos struct quoting_options const *o)
548 1.1 christos {
549 1.1 christos int e = errno;
550 1.1 christos size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
551 1.1 christos char *buf = xmalloc (bufsize);
552 1.1 christos quotearg_buffer (buf, bufsize, arg, argsize, o);
553 1.1 christos errno = e;
554 1.1 christos return buf;
555 1.1 christos }
556 1.1 christos
557 1.1 christos /* Use storage slot N to return a quoted version of argument ARG.
558 1.1 christos ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
559 1.1 christos null-terminated string.
560 1.1 christos OPTIONS specifies the quoting options.
561 1.1 christos The returned value points to static storage that can be
562 1.1 christos reused by the next call to this function with the same value of N.
563 1.1 christos N must be nonnegative. N is deliberately declared with type "int"
564 1.1 christos to allow for future extensions (using negative values). */
565 1.1 christos static char *
566 1.1 christos quotearg_n_options (int n, char const *arg, size_t argsize,
567 1.1 christos struct quoting_options const *options)
568 1.1 christos {
569 1.1 christos int e = errno;
570 1.1 christos
571 1.1 christos /* Preallocate a slot 0 buffer, so that the caller can always quote
572 1.1 christos one small component of a "memory exhausted" message in slot 0. */
573 1.1 christos static char slot0[256];
574 1.1 christos static unsigned int nslots = 1;
575 1.1 christos unsigned int n0 = n;
576 1.1 christos struct slotvec
577 1.1 christos {
578 1.1 christos size_t size;
579 1.1 christos char *val;
580 1.1 christos };
581 1.1 christos static struct slotvec slotvec0 = {sizeof slot0, slot0};
582 1.1 christos static struct slotvec *slotvec = &slotvec0;
583 1.1 christos
584 1.1 christos if (n < 0)
585 1.1 christos abort ();
586 1.1 christos
587 1.1 christos if (nslots <= n0)
588 1.1 christos {
589 1.1 christos unsigned int n1 = n0 + 1;
590 1.1 christos
591 1.2 christos /* XXX: wrong int cast to avoid gcc warning */
592 1.2 christos if (xalloc_oversized ((int)n1, sizeof *slotvec))
593 1.1 christos xalloc_die ();
594 1.1 christos
595 1.1 christos if (slotvec == &slotvec0)
596 1.1 christos {
597 1.1 christos slotvec = xmalloc (sizeof *slotvec);
598 1.1 christos *slotvec = slotvec0;
599 1.1 christos }
600 1.1 christos slotvec = xrealloc (slotvec, n1 * sizeof *slotvec);
601 1.1 christos memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
602 1.1 christos nslots = n1;
603 1.1 christos }
604 1.1 christos
605 1.1 christos {
606 1.1 christos size_t size = slotvec[n].size;
607 1.1 christos char *val = slotvec[n].val;
608 1.1 christos size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
609 1.1 christos
610 1.1 christos if (size <= qsize)
611 1.1 christos {
612 1.1 christos slotvec[n].size = size = qsize + 1;
613 1.1 christos if (val != slot0)
614 1.1 christos free (val);
615 1.1 christos slotvec[n].val = val = xmalloc (size);
616 1.1 christos quotearg_buffer (val, size, arg, argsize, options);
617 1.1 christos }
618 1.1 christos
619 1.1 christos errno = e;
620 1.1 christos return val;
621 1.1 christos }
622 1.1 christos }
623 1.1 christos
624 1.1 christos char *
625 1.1 christos quotearg_n (int n, char const *arg)
626 1.1 christos {
627 1.1 christos return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
628 1.1 christos }
629 1.1 christos
630 1.1 christos char *
631 1.1 christos quotearg (char const *arg)
632 1.1 christos {
633 1.1 christos return quotearg_n (0, arg);
634 1.1 christos }
635 1.1 christos
636 1.1 christos /* Return quoting options for STYLE, with no extra quoting. */
637 1.1 christos static struct quoting_options
638 1.1 christos quoting_options_from_style (enum quoting_style style)
639 1.1 christos {
640 1.1 christos struct quoting_options o;
641 1.1 christos o.style = style;
642 1.1 christos memset (o.quote_these_too, 0, sizeof o.quote_these_too);
643 1.1 christos return o;
644 1.1 christos }
645 1.1 christos
646 1.1 christos char *
647 1.1 christos quotearg_n_style (int n, enum quoting_style s, char const *arg)
648 1.1 christos {
649 1.1 christos struct quoting_options const o = quoting_options_from_style (s);
650 1.1 christos return quotearg_n_options (n, arg, SIZE_MAX, &o);
651 1.1 christos }
652 1.1 christos
653 1.1 christos char *
654 1.1 christos quotearg_n_style_mem (int n, enum quoting_style s,
655 1.1 christos char const *arg, size_t argsize)
656 1.1 christos {
657 1.1 christos struct quoting_options const o = quoting_options_from_style (s);
658 1.1 christos return quotearg_n_options (n, arg, argsize, &o);
659 1.1 christos }
660 1.1 christos
661 1.1 christos char *
662 1.1 christos quotearg_style (enum quoting_style s, char const *arg)
663 1.1 christos {
664 1.1 christos return quotearg_n_style (0, s, arg);
665 1.1 christos }
666 1.1 christos
667 1.1 christos char *
668 1.1 christos quotearg_char (char const *arg, char ch)
669 1.1 christos {
670 1.1 christos struct quoting_options options;
671 1.1 christos options = default_quoting_options;
672 1.1 christos set_char_quoting (&options, ch, 1);
673 1.1 christos return quotearg_n_options (0, arg, SIZE_MAX, &options);
674 1.1 christos }
675 1.1 christos
676 1.1 christos char *
677 1.1 christos quotearg_colon (char const *arg)
678 1.1 christos {
679 1.1 christos return quotearg_char (arg, ':');
680 1.1 christos }
681