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