1131554Stjr/* quotearg.c - quote arguments for output
2131554Stjr   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3131554Stjr
4131554Stjr   This program is free software; you can redistribute it and/or modify
5131554Stjr   it under the terms of the GNU General Public License as published by
6131554Stjr   the Free Software Foundation; either version 2, or (at your option)
7131554Stjr   any later version.
8131554Stjr
9131554Stjr   This program is distributed in the hope that it will be useful,
10131554Stjr   but WITHOUT ANY WARRANTY; without even the implied warranty of
11131554Stjr   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12131554Stjr   GNU General Public License for more details.
13131554Stjr
14131554Stjr   You should have received a copy of the GNU General Public License
15131554Stjr   along with this program; if not, write to the Free Software Foundation,
16131554Stjr   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17131554Stjr
18131554Stjr/* Written by Paul Eggert <eggert@twinsun.com> */
19131554Stjr
20131554Stjr#if HAVE_CONFIG_H
21131554Stjr# include <config.h>
22131554Stjr#endif
23131554Stjr
24131554Stjr#if HAVE_STDDEF_H
25131554Stjr# include <stddef.h>  /* For the definition of size_t on windows w/MSVC.  */
26131554Stjr#endif
27131554Stjr#include <sys/types.h>
28131554Stjr#include <quotearg.h>
29131554Stjr#include <xalloc.h>
30131554Stjr
31131554Stjr#include <ctype.h>
32131554Stjr
33131554Stjr#if ENABLE_NLS
34131554Stjr# include <libintl.h>
35131554Stjr# define _(text) gettext (text)
36131554Stjr#else
37131554Stjr# define _(text) text
38131554Stjr#endif
39131554Stjr#define N_(text) text
40131554Stjr
41131554Stjr#if HAVE_LIMITS_H
42131554Stjr# include <limits.h>
43131554Stjr#endif
44131554Stjr#ifndef CHAR_BIT
45131554Stjr# define CHAR_BIT 8
46131554Stjr#endif
47131554Stjr#ifndef UCHAR_MAX
48131554Stjr# define UCHAR_MAX ((unsigned char) -1)
49131554Stjr#endif
50131554Stjr
51131554Stjr#if HAVE_C_BACKSLASH_A
52131554Stjr# define ALERT_CHAR '\a'
53131554Stjr#else
54131554Stjr# define ALERT_CHAR '\7'
55131554Stjr#endif
56131554Stjr
57131554Stjr#if HAVE_STDLIB_H
58131554Stjr# include <stdlib.h>
59131554Stjr#endif
60131554Stjr
61131554Stjr#if HAVE_STRING_H
62131554Stjr# include <string.h>
63131554Stjr#endif
64131554Stjr
65131554Stjr#if HAVE_WCHAR_H
66131554Stjr# include <wchar.h>
67131554Stjr#endif
68131554Stjr
69131554Stjr#if !HAVE_MBRTOWC
70131554Stjr/* Disable multibyte processing entirely.  Since MB_CUR_MAX is 1, the
71131554Stjr   other macros are defined only for documentation and to satisfy C
72131554Stjr   syntax.  */
73131554Stjr# undef MB_CUR_MAX
74131554Stjr# define MB_CUR_MAX 1
75131554Stjr# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
76131554Stjr# define mbsinit(ps) 1
77131554Stjr# define iswprint(wc) ISPRINT ((unsigned char) (wc))
78131554Stjr#endif
79131554Stjr
80131554Stjr#ifndef iswprint
81131554Stjr# if HAVE_WCTYPE_H
82131554Stjr#  include <wctype.h>
83131554Stjr# endif
84131554Stjr# if !defined iswprint && !HAVE_ISWPRINT
85131554Stjr#  define iswprint(wc) 1
86131554Stjr# endif
87131554Stjr#endif
88131554Stjr
89131554Stjr#define INT_BITS (sizeof (int) * CHAR_BIT)
90131554Stjr
91131554Stjr#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
92131554Stjr# define IN_CTYPE_DOMAIN(c) 1
93131554Stjr#else
94131554Stjr# define IN_CTYPE_DOMAIN(c) isascii(c)
95131554Stjr#endif
96131554Stjr
97131554Stjr/* Undefine to protect against the definition in wctype.h of solaris2.6.   */
98131554Stjr#undef ISPRINT
99131554Stjr#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c))
100131554Stjr
101131554Stjrstruct quoting_options
102131554Stjr{
103131554Stjr  /* Basic quoting style.  */
104131554Stjr  enum quoting_style style;
105131554Stjr
106131554Stjr  /* Quote the characters indicated by this bit vector even if the
107131554Stjr     quoting style would not normally require them to be quoted.  */
108131554Stjr  int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
109131554Stjr};
110131554Stjr
111131554Stjr/* Names of quoting styles.  */
112131554Stjrchar const *const quoting_style_args[] =
113131554Stjr{
114131554Stjr  "literal",
115131554Stjr  "shell",
116131554Stjr  "shell-always",
117131554Stjr  "c",
118131554Stjr  "escape",
119131554Stjr  "locale",
120131554Stjr  "clocale",
121131554Stjr  0
122131554Stjr};
123131554Stjr
124131554Stjr/* Correspondences to quoting style names.  */
125131554Stjrenum quoting_style const quoting_style_vals[] =
126131554Stjr{
127131554Stjr  literal_quoting_style,
128131554Stjr  shell_quoting_style,
129131554Stjr  shell_always_quoting_style,
130131554Stjr  c_quoting_style,
131131554Stjr  escape_quoting_style,
132131554Stjr  locale_quoting_style,
133131554Stjr  clocale_quoting_style
134131554Stjr};
135131554Stjr
136131554Stjr/* The default quoting options.  */
137131554Stjrstatic struct quoting_options default_quoting_options;
138131554Stjr
139131554Stjr/* Allocate a new set of quoting options, with contents initially identical
140131554Stjr   to O if O is not null, or to the default if O is null.
141131554Stjr   It is the caller's responsibility to free the result.  */
142131554Stjrstruct quoting_options *
143131554Stjrclone_quoting_options (struct quoting_options *o)
144131554Stjr{
145131554Stjr  struct quoting_options *p
146131554Stjr    = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
147131554Stjr  *p = *(o ? o : &default_quoting_options);
148131554Stjr  return p;
149131554Stjr}
150131554Stjr
151131554Stjr/* Get the value of O's quoting style.  If O is null, use the default.  */
152131554Stjrenum quoting_style
153131554Stjrget_quoting_style (struct quoting_options *o)
154131554Stjr{
155131554Stjr  return (o ? o : &default_quoting_options)->style;
156131554Stjr}
157131554Stjr
158131554Stjr/* In O (or in the default if O is null),
159131554Stjr   set the value of the quoting style to S.  */
160131554Stjrvoid
161131554Stjrset_quoting_style (struct quoting_options *o, enum quoting_style s)
162131554Stjr{
163131554Stjr  (o ? o : &default_quoting_options)->style = s;
164131554Stjr}
165131554Stjr
166131554Stjr/* In O (or in the default if O is null),
167131554Stjr   set the value of the quoting options for character C to I.
168131554Stjr   Return the old value.  Currently, the only values defined for I are
169131554Stjr   0 (the default) and 1 (which means to quote the character even if
170131554Stjr   it would not otherwise be quoted).  */
171131554Stjrint
172131554Stjrset_char_quoting (struct quoting_options *o, char c, int i)
173131554Stjr{
174131554Stjr  unsigned char uc = c;
175131554Stjr  int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
176131554Stjr  int shift = uc % INT_BITS;
177131554Stjr  int r = (*p >> shift) & 1;
178131554Stjr  *p ^= ((i & 1) ^ r) << shift;
179131554Stjr  return r;
180131554Stjr}
181131554Stjr
182131554Stjr/* MSGID approximates a quotation mark.  Return its translation if it
183131554Stjr   has one; otherwise, return either it or "\"", depending on S.  */
184131554Stjrstatic char const *
185131554Stjrgettext_quote (char const *msgid, enum quoting_style s)
186131554Stjr{
187131554Stjr  char const *translation = _(msgid);
188131554Stjr  if (translation == msgid && s == clocale_quoting_style)
189131554Stjr    translation = "\"";
190131554Stjr  return translation;
191131554Stjr}
192131554Stjr
193131554Stjr/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
194131554Stjr   argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
195131554Stjr   non-quoting-style part of O to control quoting.
196131554Stjr   Terminate the output with a null character, and return the written
197131554Stjr   size of the output, not counting the terminating null.
198131554Stjr   If BUFFERSIZE is too small to store the output string, return the
199131554Stjr   value that would have been returned had BUFFERSIZE been large enough.
200131554Stjr   If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
201131554Stjr
202131554Stjr   This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
203131554Stjr   ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
204131554Stjr   style specified by O, and O may not be null.  */
205131554Stjr
206131554Stjrstatic size_t
207131554Stjrquotearg_buffer_restyled (char *buffer, size_t buffersize,
208131554Stjr			  char const *arg, size_t argsize,
209131554Stjr			  enum quoting_style quoting_style,
210131554Stjr			  struct quoting_options const *o)
211131554Stjr{
212131554Stjr  size_t i;
213131554Stjr  size_t len = 0;
214131554Stjr  char const *quote_string = 0;
215131554Stjr  size_t quote_string_len = 0;
216131554Stjr  int backslash_escapes = 0;
217131554Stjr  int unibyte_locale = MB_CUR_MAX == 1;
218131554Stjr
219131554Stjr#define STORE(c) \
220131554Stjr    do \
221131554Stjr      { \
222131554Stjr	if (len < buffersize) \
223131554Stjr	  buffer[len] = (c); \
224131554Stjr	len++; \
225131554Stjr      } \
226131554Stjr    while (0)
227131554Stjr
228131554Stjr  switch (quoting_style)
229131554Stjr    {
230131554Stjr    case c_quoting_style:
231131554Stjr      STORE ('"');
232131554Stjr      backslash_escapes = 1;
233131554Stjr      quote_string = "\"";
234131554Stjr      quote_string_len = 1;
235131554Stjr      break;
236131554Stjr
237131554Stjr    case escape_quoting_style:
238131554Stjr      backslash_escapes = 1;
239131554Stjr      break;
240131554Stjr
241131554Stjr    case locale_quoting_style:
242131554Stjr    case clocale_quoting_style:
243131554Stjr      {
244131554Stjr	/* Get translations for open and closing quotation marks.
245131554Stjr
246131554Stjr	   The message catalog should translate "`" to a left
247131554Stjr	   quotation mark suitable for the locale, and similarly for
248131554Stjr	   "'".  If the catalog has no translation,
249131554Stjr	   locale_quoting_style quotes `like this', and
250131554Stjr	   clocale_quoting_style quotes "like this".
251131554Stjr
252131554Stjr	   For example, an American English Unicode locale should
253131554Stjr	   translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
254131554Stjr	   should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
255131554Stjr	   MARK).  A British English Unicode locale should instead
256131554Stjr	   translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
257131554Stjr	   U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.  */
258131554Stjr
259131554Stjr	char const *left = gettext_quote (N_("`"), quoting_style);
260131554Stjr	char const *right = gettext_quote (N_("'"), quoting_style);
261131554Stjr	for (quote_string = left; *quote_string; quote_string++)
262131554Stjr	  STORE (*quote_string);
263131554Stjr	backslash_escapes = 1;
264131554Stjr	quote_string = right;
265131554Stjr	quote_string_len = strlen (quote_string);
266131554Stjr      }
267131554Stjr      break;
268131554Stjr
269131554Stjr    case shell_always_quoting_style:
270131554Stjr      STORE ('\'');
271131554Stjr      quote_string = "'";
272131554Stjr      quote_string_len = 1;
273131554Stjr      break;
274131554Stjr
275131554Stjr    default:
276131554Stjr      break;
277131554Stjr    }
278131554Stjr
279131554Stjr  for (i = 0;  ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize);  i++)
280131554Stjr    {
281131554Stjr      unsigned char c;
282131554Stjr      unsigned char esc;
283131554Stjr
284131554Stjr      if (backslash_escapes
285131554Stjr	  && quote_string_len
286131554Stjr	  && i + quote_string_len <= argsize
287131554Stjr	  && memcmp (arg + i, quote_string, quote_string_len) == 0)
288131554Stjr	STORE ('\\');
289131554Stjr
290131554Stjr      c = arg[i];
291131554Stjr      switch (c)
292131554Stjr	{
293131554Stjr	case '?':
294131554Stjr	  switch (quoting_style)
295131554Stjr	    {
296131554Stjr	    case shell_quoting_style:
297131554Stjr	      goto use_shell_always_quoting_style;
298131554Stjr
299131554Stjr	    case c_quoting_style:
300131554Stjr	      if (i + 2 < argsize && arg[i + 1] == '?')
301131554Stjr		switch (arg[i + 2])
302131554Stjr		  {
303131554Stjr		  case '!': case '\'':
304131554Stjr		  case '(': case ')': case '-': case '/':
305131554Stjr		  case '<': case '=': case '>':
306131554Stjr		    /* Escape the second '?' in what would otherwise be
307131554Stjr		       a trigraph.  */
308131554Stjr		    i += 2;
309131554Stjr		    c = arg[i + 2];
310131554Stjr		    STORE ('?');
311131554Stjr		    STORE ('\\');
312131554Stjr		    STORE ('?');
313131554Stjr		    break;
314131554Stjr		  }
315131554Stjr	      break;
316131554Stjr
317131554Stjr	    default:
318131554Stjr	      break;
319131554Stjr	    }
320131554Stjr	  break;
321131554Stjr
322131554Stjr	case ALERT_CHAR: esc = 'a'; goto c_escape;
323131554Stjr	case '\b': esc = 'b'; goto c_escape;
324131554Stjr	case '\f': esc = 'f'; goto c_escape;
325131554Stjr	case '\n': esc = 'n'; goto c_and_shell_escape;
326131554Stjr	case '\r': esc = 'r'; goto c_and_shell_escape;
327131554Stjr	case '\t': esc = 't'; goto c_and_shell_escape;
328131554Stjr	case '\v': esc = 'v'; goto c_escape;
329131554Stjr	case '\\': esc = c; goto c_and_shell_escape;
330131554Stjr
331131554Stjr	c_and_shell_escape:
332131554Stjr	  if (quoting_style == shell_quoting_style)
333131554Stjr	    goto use_shell_always_quoting_style;
334131554Stjr	c_escape:
335131554Stjr	  if (backslash_escapes)
336131554Stjr	    {
337131554Stjr	      c = esc;
338131554Stjr	      goto store_escape;
339131554Stjr	    }
340131554Stjr	  break;
341131554Stjr
342131554Stjr	case '#': case '~':
343131554Stjr	  if (i != 0)
344131554Stjr	    break;
345131554Stjr	  /* Fall through.  */
346131554Stjr	case ' ':
347131554Stjr	case '!': /* special in bash */
348131554Stjr	case '"': case '$': case '&':
349131554Stjr	case '(': case ')': case '*': case ';':
350131554Stjr	case '<': case '>': case '[':
351131554Stjr	case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
352131554Stjr	case '`': case '|':
353131554Stjr	  /* A shell special character.  In theory, '$' and '`' could
354131554Stjr	     be the first bytes of multibyte characters, which means
355131554Stjr	     we should check them with mbrtowc, but in practice this
356131554Stjr	     doesn't happen so it's not worth worrying about.  */
357131554Stjr	  if (quoting_style == shell_quoting_style)
358131554Stjr	    goto use_shell_always_quoting_style;
359131554Stjr	  break;
360131554Stjr
361131554Stjr	case '\'':
362131554Stjr	  switch (quoting_style)
363131554Stjr	    {
364131554Stjr	    case shell_quoting_style:
365131554Stjr	      goto use_shell_always_quoting_style;
366131554Stjr
367131554Stjr	    case shell_always_quoting_style:
368131554Stjr	      STORE ('\'');
369131554Stjr	      STORE ('\\');
370131554Stjr	      STORE ('\'');
371131554Stjr	      break;
372131554Stjr
373131554Stjr	    default:
374131554Stjr	      break;
375131554Stjr	    }
376131554Stjr	  break;
377131554Stjr
378131554Stjr	case '%': case '+': case ',': case '-': case '.': case '/':
379131554Stjr	case '0': case '1': case '2': case '3': case '4': case '5':
380131554Stjr	case '6': case '7': case '8': case '9': case ':': case '=':
381131554Stjr	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
382131554Stjr	case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
383131554Stjr	case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
384131554Stjr	case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
385131554Stjr	case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
386131554Stjr	case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
387131554Stjr	case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
388131554Stjr	case 'o': case 'p': case 'q': case 'r': case 's': case 't':
389131554Stjr	case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
390131554Stjr	case '{': case '}':
391131554Stjr	  /* These characters don't cause problems, no matter what the
392131554Stjr	     quoting style is.  They cannot start multibyte sequences.  */
393131554Stjr	  break;
394131554Stjr
395131554Stjr	default:
396131554Stjr	  /* If we have a multibyte sequence, copy it until we reach
397131554Stjr	     its end, find an error, or come back to the initial shift
398131554Stjr	     state.  For C-like styles, if the sequence has
399131554Stjr	     unprintable characters, escape the whole sequence, since
400131554Stjr	     we can't easily escape single characters within it.  */
401131554Stjr	  {
402131554Stjr	    /* Length of multibyte sequence found so far.  */
403131554Stjr	    size_t m;
404131554Stjr
405131554Stjr	    int printable;
406131554Stjr
407131554Stjr	    if (unibyte_locale)
408131554Stjr	      {
409131554Stjr		m = 1;
410131554Stjr		printable = ISPRINT (c);
411131554Stjr	      }
412131554Stjr	    else
413131554Stjr	      {
414131554Stjr		mbstate_t mbstate;
415131554Stjr		memset (&mbstate, 0, sizeof mbstate);
416131554Stjr
417131554Stjr		m = 0;
418131554Stjr		printable = 1;
419131554Stjr		if (argsize == (size_t) -1)
420131554Stjr		  argsize = strlen (arg);
421131554Stjr
422131554Stjr		do
423131554Stjr		  {
424131554Stjr		    wchar_t w;
425131554Stjr		    size_t bytes = mbrtowc (&w, &arg[i + m],
426131554Stjr					    argsize - (i + m), &mbstate);
427131554Stjr		    if (bytes == 0)
428131554Stjr		      break;
429131554Stjr		    else if (bytes == (size_t) -1)
430131554Stjr		      {
431131554Stjr			printable = 0;
432131554Stjr			break;
433131554Stjr		      }
434131554Stjr		    else if (bytes == (size_t) -2)
435131554Stjr		      {
436131554Stjr			printable = 0;
437131554Stjr			while (i + m < argsize && arg[i + m])
438131554Stjr			  m++;
439131554Stjr			break;
440131554Stjr		      }
441131554Stjr		    else
442131554Stjr		      {
443131554Stjr			if (! iswprint (w))
444131554Stjr			  printable = 0;
445131554Stjr			m += bytes;
446131554Stjr		      }
447131554Stjr		  }
448131554Stjr		while (! mbsinit (&mbstate));
449131554Stjr	      }
450131554Stjr
451131554Stjr	    if (1 < m || (backslash_escapes && ! printable))
452131554Stjr	      {
453131554Stjr		/* Output a multibyte sequence, or an escaped
454131554Stjr		   unprintable unibyte character.  */
455131554Stjr		size_t ilim = i + m;
456131554Stjr
457131554Stjr		for (;;)
458131554Stjr		  {
459131554Stjr		    if (backslash_escapes && ! printable)
460131554Stjr		      {
461131554Stjr			STORE ('\\');
462131554Stjr			STORE ('0' + (c >> 6));
463131554Stjr			STORE ('0' + ((c >> 3) & 7));
464131554Stjr			c = '0' + (c & 7);
465131554Stjr		      }
466131554Stjr		    if (ilim <= i + 1)
467131554Stjr		      break;
468131554Stjr		    STORE (c);
469131554Stjr		    c = arg[++i];
470131554Stjr		  }
471131554Stjr
472131554Stjr		goto store_c;
473131554Stjr	      }
474131554Stjr	  }
475131554Stjr	}
476131554Stjr
477131554Stjr      if (! (backslash_escapes
478131554Stjr	     && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
479131554Stjr	goto store_c;
480131554Stjr
481131554Stjr    store_escape:
482131554Stjr      STORE ('\\');
483131554Stjr
484131554Stjr    store_c:
485131554Stjr      STORE (c);
486131554Stjr    }
487131554Stjr
488131554Stjr  if (quote_string)
489131554Stjr    for (; *quote_string; quote_string++)
490131554Stjr      STORE (*quote_string);
491131554Stjr
492131554Stjr  if (len < buffersize)
493131554Stjr    buffer[len] = '\0';
494131554Stjr  return len;
495131554Stjr
496131554Stjr use_shell_always_quoting_style:
497131554Stjr  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
498131554Stjr				   shell_always_quoting_style, o);
499131554Stjr}
500131554Stjr
501131554Stjr/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
502131554Stjr   argument ARG (of size ARGSIZE), using O to control quoting.
503131554Stjr   If O is null, use the default.
504131554Stjr   Terminate the output with a null character, and return the written
505131554Stjr   size of the output, not counting the terminating null.
506131554Stjr   If BUFFERSIZE is too small to store the output string, return the
507131554Stjr   value that would have been returned had BUFFERSIZE been large enough.
508131554Stjr   If ARGSIZE is -1, use the string length of the argument for ARGSIZE.  */
509131554Stjrsize_t
510131554Stjrquotearg_buffer (char *buffer, size_t buffersize,
511131554Stjr		 char const *arg, size_t argsize,
512131554Stjr		 struct quoting_options const *o)
513131554Stjr{
514131554Stjr  struct quoting_options const *p = o ? o : &default_quoting_options;
515131554Stjr  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
516131554Stjr				   p->style, p);
517131554Stjr}
518131554Stjr
519131554Stjr/* Use storage slot N to return a quoted version of the string ARG.
520131554Stjr   OPTIONS specifies the quoting options.
521131554Stjr   The returned value points to static storage that can be
522131554Stjr   reused by the next call to this function with the same value of N.
523131554Stjr   N must be nonnegative.  N is deliberately declared with type "int"
524131554Stjr   to allow for future extensions (using negative values).  */
525131554Stjrstatic char *
526131554Stjrquotearg_n_options (int n, char const *arg,
527131554Stjr		    struct quoting_options const *options)
528131554Stjr{
529131554Stjr  /* Preallocate a slot 0 buffer, so that the caller can always quote
530131554Stjr     one small component of a "memory exhausted" message in slot 0.  */
531131554Stjr  static char slot0[256];
532131554Stjr  static unsigned int nslots = 1;
533131554Stjr  struct slotvec
534131554Stjr    {
535131554Stjr      size_t size;
536131554Stjr      char *val;
537131554Stjr    };
538131554Stjr  static struct slotvec slotvec0 = {sizeof slot0, slot0};
539131554Stjr  static struct slotvec *slotvec = &slotvec0;
540131554Stjr
541131554Stjr  if (nslots <= n)
542131554Stjr    {
543131554Stjr      int n1 = n + 1;
544131554Stjr      size_t s = n1 * sizeof (struct slotvec);
545131554Stjr      if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
546131554Stjr	abort ();
547131554Stjr      if (slotvec == &slotvec0)
548131554Stjr	{
549131554Stjr	  slotvec = (struct slotvec *) xmalloc (sizeof (struct slotvec));
550131554Stjr	  *slotvec = slotvec0;
551131554Stjr	}
552131554Stjr      slotvec = (struct slotvec *) xrealloc (slotvec, s);
553131554Stjr      memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
554131554Stjr      nslots = n;
555131554Stjr    }
556131554Stjr
557131554Stjr  {
558131554Stjr    size_t size = slotvec[n].size;
559131554Stjr    char *val = slotvec[n].val;
560131554Stjr    size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
561131554Stjr
562131554Stjr    if (size <= qsize)
563131554Stjr      {
564131554Stjr	slotvec[n].size = size = qsize + 1;
565131554Stjr	slotvec[n].val = val = xrealloc (val == slot0 ? 0 : val, size);
566131554Stjr	quotearg_buffer (val, size, arg, (size_t) -1, options);
567131554Stjr      }
568131554Stjr
569131554Stjr    return val;
570131554Stjr  }
571131554Stjr}
572131554Stjr
573131554Stjrchar *
574131554Stjrquotearg_n (unsigned int n, char const *arg)
575131554Stjr{
576131554Stjr  return quotearg_n_options (n, arg, &default_quoting_options);
577131554Stjr}
578131554Stjr
579131554Stjrchar *
580131554Stjrquotearg (char const *arg)
581131554Stjr{
582131554Stjr  return quotearg_n (0, arg);
583131554Stjr}
584131554Stjr
585131554Stjrchar *
586131554Stjrquotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
587131554Stjr{
588131554Stjr  struct quoting_options o;
589131554Stjr  o.style = s;
590131554Stjr  memset (o.quote_these_too, 0, sizeof o.quote_these_too);
591131554Stjr  return quotearg_n_options (n, arg, &o);
592131554Stjr}
593131554Stjr
594131554Stjrchar *
595131554Stjrquotearg_style (enum quoting_style s, char const *arg)
596131554Stjr{
597131554Stjr  return quotearg_n_style (0, s, arg);
598131554Stjr}
599131554Stjr
600131554Stjrchar *
601131554Stjrquotearg_char (char const *arg, char ch)
602131554Stjr{
603131554Stjr  struct quoting_options options;
604131554Stjr  options = default_quoting_options;
605131554Stjr  set_char_quoting (&options, ch, 1);
606131554Stjr  return quotearg_n_options (0, arg, &options);
607131554Stjr}
608131554Stjr
609131554Stjrchar *
610131554Stjrquotearg_colon (char const *arg)
611131554Stjr{
612131554Stjr  return quotearg_char (arg, ':');
613131554Stjr}
614