xref: /netbsd-src/external/gpl2/grep/dist/lib/quotearg.c (revision a8fa202a6440953be7b92a8960a811bff58203f4)
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