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