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