198038Sache/* quotearg.c - quote arguments for output
298038Sache
3133543Stjr   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
4133543Stjr   Foundation, Inc.
5133543Stjr
698038Sache   This program is free software; you can redistribute it and/or modify
798038Sache   it under the terms of the GNU General Public License as published by
898038Sache   the Free Software Foundation; either version 2, or (at your option)
998038Sache   any later version.
1098038Sache
1198038Sache   This program is distributed in the hope that it will be useful,
1298038Sache   but WITHOUT ANY WARRANTY; without even the implied warranty of
1398038Sache   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1498038Sache   GNU General Public License for more details.
1598038Sache
1698038Sache   You should have received a copy of the GNU General Public License
1798038Sache   along with this program; if not, write to the Free Software Foundation,
1898038Sache   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
1998038Sache
2098038Sache/* Written by Paul Eggert <eggert@twinsun.com> */
2198038Sache
2298038Sache#if HAVE_CONFIG_H
2398038Sache# include <config.h>
2498038Sache#endif
2598038Sache
26131447Stjr#include "quotearg.h"
2798038Sache
28131447Stjr#include "xalloc.h"
29131447Stjr
3098038Sache#include <ctype.h>
31131447Stjr#include <errno.h>
32131447Stjr#include <limits.h>
33133543Stjr#include <stdbool.h>
34131447Stjr#include <stdlib.h>
35131447Stjr#include <string.h>
3698038Sache
37131447Stjr#include "gettext.h"
38131447Stjr#define _(msgid) gettext (msgid)
39131447Stjr#define N_(msgid) msgid
4098038Sache
4198038Sache#if HAVE_WCHAR_H
4298038Sache
4398038Sache/* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared.  */
4498038Sache# include <stdio.h>
4598038Sache# include <time.h>
4698038Sache
4798038Sache# include <wchar.h>
4898038Sache#endif
4998038Sache
5098038Sache#if !HAVE_MBRTOWC
5198038Sache/* Disable multibyte processing entirely.  Since MB_CUR_MAX is 1, the
5298038Sache   other macros are defined only for documentation and to satisfy C
5398038Sache   syntax.  */
5498038Sache# undef MB_CUR_MAX
5598038Sache# define MB_CUR_MAX 1
5698038Sache# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
57131447Stjr# define iswprint(wc) isprint ((unsigned char) (wc))
58131447Stjr# undef HAVE_MBSINIT
59131447Stjr#endif
60131447Stjr
61131447Stjr#if !defined mbsinit && !HAVE_MBSINIT
6298038Sache# define mbsinit(ps) 1
6398038Sache#endif
6498038Sache
6598038Sache#ifndef iswprint
6698038Sache# if HAVE_WCTYPE_H
6798038Sache#  include <wctype.h>
6898038Sache# endif
6998038Sache# if !defined iswprint && !HAVE_ISWPRINT
7098038Sache#  define iswprint(wc) 1
7198038Sache# endif
7298038Sache#endif
7398038Sache
74131447Stjr#ifndef SIZE_MAX
75131447Stjr# define SIZE_MAX ((size_t) -1)
7698038Sache#endif
7798038Sache
78131447Stjr#define INT_BITS (sizeof (int) * CHAR_BIT)
7998038Sache
8098038Sachestruct quoting_options
8198038Sache{
8298038Sache  /* Basic quoting style.  */
8398038Sache  enum quoting_style style;
8498038Sache
8598038Sache  /* Quote the characters indicated by this bit vector even if the
8698038Sache     quoting style would not normally require them to be quoted.  */
8798038Sache  int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
8898038Sache};
8998038Sache
9098038Sache/* Names of quoting styles.  */
9198038Sachechar const *const quoting_style_args[] =
9298038Sache{
9398038Sache  "literal",
9498038Sache  "shell",
9598038Sache  "shell-always",
9698038Sache  "c",
9798038Sache  "escape",
9898038Sache  "locale",
9998038Sache  "clocale",
10098038Sache  0
10198038Sache};
10298038Sache
10398038Sache/* Correspondences to quoting style names.  */
10498038Sacheenum quoting_style const quoting_style_vals[] =
10598038Sache{
10698038Sache  literal_quoting_style,
10798038Sache  shell_quoting_style,
10898038Sache  shell_always_quoting_style,
10998038Sache  c_quoting_style,
11098038Sache  escape_quoting_style,
11198038Sache  locale_quoting_style,
11298038Sache  clocale_quoting_style
11398038Sache};
11498038Sache
11598038Sache/* The default quoting options.  */
11698038Sachestatic struct quoting_options default_quoting_options;
11798038Sache
11898038Sache/* Allocate a new set of quoting options, with contents initially identical
11998038Sache   to O if O is not null, or to the default if O is null.
12098038Sache   It is the caller's responsibility to free the result.  */
12198038Sachestruct quoting_options *
12298038Sacheclone_quoting_options (struct quoting_options *o)
12398038Sache{
124131447Stjr  int e = errno;
125131447Stjr  struct quoting_options *p = xmalloc (sizeof *p);
12698038Sache  *p = *(o ? o : &default_quoting_options);
127131447Stjr  errno = e;
12898038Sache  return p;
12998038Sache}
13098038Sache
13198038Sache/* Get the value of O's quoting style.  If O is null, use the default.  */
13298038Sacheenum quoting_style
13398038Sacheget_quoting_style (struct quoting_options *o)
13498038Sache{
13598038Sache  return (o ? o : &default_quoting_options)->style;
13698038Sache}
13798038Sache
13898038Sache/* In O (or in the default if O is null),
13998038Sache   set the value of the quoting style to S.  */
14098038Sachevoid
14198038Sacheset_quoting_style (struct quoting_options *o, enum quoting_style s)
14298038Sache{
14398038Sache  (o ? o : &default_quoting_options)->style = s;
14498038Sache}
14598038Sache
14698038Sache/* In O (or in the default if O is null),
14798038Sache   set the value of the quoting options for character C to I.
14898038Sache   Return the old value.  Currently, the only values defined for I are
14998038Sache   0 (the default) and 1 (which means to quote the character even if
15098038Sache   it would not otherwise be quoted).  */
15198038Sacheint
15298038Sacheset_char_quoting (struct quoting_options *o, char c, int i)
15398038Sache{
15498038Sache  unsigned char uc = c;
15598038Sache  int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
15698038Sache  int shift = uc % INT_BITS;
15798038Sache  int r = (*p >> shift) & 1;
15898038Sache  *p ^= ((i & 1) ^ r) << shift;
15998038Sache  return r;
16098038Sache}
16198038Sache
16298038Sache/* MSGID approximates a quotation mark.  Return its translation if it
16398038Sache   has one; otherwise, return either it or "\"", depending on S.  */
16498038Sachestatic char const *
16598038Sachegettext_quote (char const *msgid, enum quoting_style s)
16698038Sache{
16798038Sache  char const *translation = _(msgid);
16898038Sache  if (translation == msgid && s == clocale_quoting_style)
16998038Sache    translation = "\"";
17098038Sache  return translation;
17198038Sache}
17298038Sache
17398038Sache/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
17498038Sache   argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
17598038Sache   non-quoting-style part of O to control quoting.
17698038Sache   Terminate the output with a null character, and return the written
17798038Sache   size of the output, not counting the terminating null.
17898038Sache   If BUFFERSIZE is too small to store the output string, return the
17998038Sache   value that would have been returned had BUFFERSIZE been large enough.
180133543Stjr   If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
18198038Sache
18298038Sache   This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
18398038Sache   ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
18498038Sache   style specified by O, and O may not be null.  */
18598038Sache
18698038Sachestatic size_t
18798038Sachequotearg_buffer_restyled (char *buffer, size_t buffersize,
18898038Sache			  char const *arg, size_t argsize,
18998038Sache			  enum quoting_style quoting_style,
19098038Sache			  struct quoting_options const *o)
19198038Sache{
19298038Sache  size_t i;
19398038Sache  size_t len = 0;
19498038Sache  char const *quote_string = 0;
19598038Sache  size_t quote_string_len = 0;
196133543Stjr  bool backslash_escapes = false;
197133543Stjr  bool unibyte_locale = MB_CUR_MAX == 1;
19898038Sache
19998038Sache#define STORE(c) \
20098038Sache    do \
20198038Sache      { \
20298038Sache	if (len < buffersize) \
20398038Sache	  buffer[len] = (c); \
20498038Sache	len++; \
20598038Sache      } \
20698038Sache    while (0)
20798038Sache
20898038Sache  switch (quoting_style)
20998038Sache    {
21098038Sache    case c_quoting_style:
21198038Sache      STORE ('"');
212133543Stjr      backslash_escapes = true;
21398038Sache      quote_string = "\"";
21498038Sache      quote_string_len = 1;
21598038Sache      break;
21698038Sache
21798038Sache    case escape_quoting_style:
218133543Stjr      backslash_escapes = true;
21998038Sache      break;
22098038Sache
22198038Sache    case locale_quoting_style:
22298038Sache    case clocale_quoting_style:
22398038Sache      {
22498038Sache	/* Get translations for open and closing quotation marks.
22598038Sache
22698038Sache	   The message catalog should translate "`" to a left
22798038Sache	   quotation mark suitable for the locale, and similarly for
22898038Sache	   "'".  If the catalog has no translation,
22998038Sache	   locale_quoting_style quotes `like this', and
23098038Sache	   clocale_quoting_style quotes "like this".
23198038Sache
23298038Sache	   For example, an American English Unicode locale should
23398038Sache	   translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
23498038Sache	   should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
23598038Sache	   MARK).  A British English Unicode locale should instead
23698038Sache	   translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
23798038Sache	   U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.  */
23898038Sache
23998038Sache	char const *left = gettext_quote (N_("`"), quoting_style);
24098038Sache	char const *right = gettext_quote (N_("'"), quoting_style);
24198038Sache	for (quote_string = left; *quote_string; quote_string++)
24298038Sache	  STORE (*quote_string);
243133543Stjr	backslash_escapes = true;
24498038Sache	quote_string = right;
24598038Sache	quote_string_len = strlen (quote_string);
24698038Sache      }
24798038Sache      break;
24898038Sache
24998038Sache    case shell_always_quoting_style:
25098038Sache      STORE ('\'');
25198038Sache      quote_string = "'";
25298038Sache      quote_string_len = 1;
25398038Sache      break;
25498038Sache
25598038Sache    default:
25698038Sache      break;
25798038Sache    }
25898038Sache
259131447Stjr  for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
26098038Sache    {
26198038Sache      unsigned char c;
26298038Sache      unsigned char esc;
26398038Sache
26498038Sache      if (backslash_escapes
26598038Sache	  && quote_string_len
26698038Sache	  && i + quote_string_len <= argsize
26798038Sache	  && memcmp (arg + i, quote_string, quote_string_len) == 0)
26898038Sache	STORE ('\\');
26998038Sache
27098038Sache      c = arg[i];
27198038Sache      switch (c)
27298038Sache	{
27398038Sache	case '\0':
27498038Sache	  if (backslash_escapes)
27598038Sache	    {
27698038Sache	      STORE ('\\');
27798038Sache	      STORE ('0');
27898038Sache	      STORE ('0');
27998038Sache	      c = '0';
28098038Sache	    }
28198038Sache	  break;
28298038Sache
28398038Sache	case '?':
28498038Sache	  switch (quoting_style)
28598038Sache	    {
28698038Sache	    case shell_quoting_style:
28798038Sache	      goto use_shell_always_quoting_style;
28898038Sache
28998038Sache	    case c_quoting_style:
29098038Sache	      if (i + 2 < argsize && arg[i + 1] == '?')
29198038Sache		switch (arg[i + 2])
29298038Sache		  {
29398038Sache		  case '!': case '\'':
29498038Sache		  case '(': case ')': case '-': case '/':
29598038Sache		  case '<': case '=': case '>':
29698038Sache		    /* Escape the second '?' in what would otherwise be
29798038Sache		       a trigraph.  */
298131447Stjr		    c = arg[i + 2];
29998038Sache		    i += 2;
30098038Sache		    STORE ('?');
30198038Sache		    STORE ('\\');
30298038Sache		    STORE ('?');
30398038Sache		    break;
30498038Sache		  }
30598038Sache	      break;
30698038Sache
30798038Sache	    default:
30898038Sache	      break;
30998038Sache	    }
31098038Sache	  break;
31198038Sache
312131447Stjr	case '\a': esc = 'a'; goto c_escape;
31398038Sache	case '\b': esc = 'b'; goto c_escape;
31498038Sache	case '\f': esc = 'f'; goto c_escape;
31598038Sache	case '\n': esc = 'n'; goto c_and_shell_escape;
31698038Sache	case '\r': esc = 'r'; goto c_and_shell_escape;
31798038Sache	case '\t': esc = 't'; goto c_and_shell_escape;
31898038Sache	case '\v': esc = 'v'; goto c_escape;
31998038Sache	case '\\': esc = c; goto c_and_shell_escape;
32098038Sache
32198038Sache	c_and_shell_escape:
32298038Sache	  if (quoting_style == shell_quoting_style)
32398038Sache	    goto use_shell_always_quoting_style;
32498038Sache	c_escape:
32598038Sache	  if (backslash_escapes)
32698038Sache	    {
32798038Sache	      c = esc;
32898038Sache	      goto store_escape;
32998038Sache	    }
33098038Sache	  break;
33198038Sache
332133543Stjr	case '{': case '}': /* sometimes special if isolated */
333133543Stjr	  if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
334133543Stjr	    break;
335133543Stjr	  /* Fall through.  */
33698038Sache	case '#': case '~':
33798038Sache	  if (i != 0)
33898038Sache	    break;
33998038Sache	  /* Fall through.  */
34098038Sache	case ' ':
34198038Sache	case '!': /* special in bash */
34298038Sache	case '"': case '$': case '&':
34398038Sache	case '(': case ')': case '*': case ';':
344133543Stjr	case '<':
345133543Stjr	case '=': /* sometimes special in 0th or (with "set -k") later args */
346133543Stjr	case '>': case '[':
34798038Sache	case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
34898038Sache	case '`': case '|':
34998038Sache	  /* A shell special character.  In theory, '$' and '`' could
35098038Sache	     be the first bytes of multibyte characters, which means
35198038Sache	     we should check them with mbrtowc, but in practice this
35298038Sache	     doesn't happen so it's not worth worrying about.  */
35398038Sache	  if (quoting_style == shell_quoting_style)
35498038Sache	    goto use_shell_always_quoting_style;
35598038Sache	  break;
35698038Sache
35798038Sache	case '\'':
35898038Sache	  switch (quoting_style)
35998038Sache	    {
36098038Sache	    case shell_quoting_style:
36198038Sache	      goto use_shell_always_quoting_style;
36298038Sache
36398038Sache	    case shell_always_quoting_style:
36498038Sache	      STORE ('\'');
36598038Sache	      STORE ('\\');
36698038Sache	      STORE ('\'');
36798038Sache	      break;
36898038Sache
36998038Sache	    default:
37098038Sache	      break;
37198038Sache	    }
37298038Sache	  break;
37398038Sache
37498038Sache	case '%': case '+': case ',': case '-': case '.': case '/':
37598038Sache	case '0': case '1': case '2': case '3': case '4': case '5':
376133543Stjr	case '6': case '7': case '8': case '9': case ':':
37798038Sache	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
37898038Sache	case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
37998038Sache	case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
38098038Sache	case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
38198038Sache	case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
38298038Sache	case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
38398038Sache	case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
38498038Sache	case 'o': case 'p': case 'q': case 'r': case 's': case 't':
38598038Sache	case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
38698038Sache	  /* These characters don't cause problems, no matter what the
38798038Sache	     quoting style is.  They cannot start multibyte sequences.  */
38898038Sache	  break;
38998038Sache
39098038Sache	default:
39198038Sache	  /* If we have a multibyte sequence, copy it until we reach
39298038Sache	     its end, find an error, or come back to the initial shift
39398038Sache	     state.  For C-like styles, if the sequence has
39498038Sache	     unprintable characters, escape the whole sequence, since
39598038Sache	     we can't easily escape single characters within it.  */
39698038Sache	  {
39798038Sache	    /* Length of multibyte sequence found so far.  */
39898038Sache	    size_t m;
39998038Sache
400133543Stjr	    bool printable;
40198038Sache
40298038Sache	    if (unibyte_locale)
40398038Sache	      {
40498038Sache		m = 1;
405133543Stjr		printable = isprint (c) != 0;
40698038Sache	      }
40798038Sache	    else
40898038Sache	      {
40998038Sache		mbstate_t mbstate;
41098038Sache		memset (&mbstate, 0, sizeof mbstate);
41198038Sache
41298038Sache		m = 0;
413133543Stjr		printable = true;
414131447Stjr		if (argsize == SIZE_MAX)
41598038Sache		  argsize = strlen (arg);
41698038Sache
41798038Sache		do
41898038Sache		  {
41998038Sache		    wchar_t w;
42098038Sache		    size_t bytes = mbrtowc (&w, &arg[i + m],
42198038Sache					    argsize - (i + m), &mbstate);
42298038Sache		    if (bytes == 0)
42398038Sache		      break;
42498038Sache		    else if (bytes == (size_t) -1)
42598038Sache		      {
426133543Stjr			printable = false;
42798038Sache			break;
42898038Sache		      }
42998038Sache		    else if (bytes == (size_t) -2)
43098038Sache		      {
431133543Stjr			printable = false;
43298038Sache			while (i + m < argsize && arg[i + m])
43398038Sache			  m++;
43498038Sache			break;
43598038Sache		      }
43698038Sache		    else
43798038Sache		      {
438133543Stjr			/* Work around a bug with older shells that "see" a '\'
439133543Stjr			   that is really the 2nd byte of a multibyte character.
440133543Stjr			   In practice the problem is limited to ASCII
441133543Stjr			   chars >= '@' that are shell special chars.  */
442133543Stjr			if ('[' == 0x5b && quoting_style == shell_quoting_style)
443133543Stjr			  {
444133543Stjr			    size_t j;
445133543Stjr			    for (j = 1; j < bytes; j++)
446133543Stjr			      switch (arg[i + m + j])
447133543Stjr				{
448133543Stjr				case '[': case '\\': case '^':
449133543Stjr				case '`': case '|':
450133543Stjr				  goto use_shell_always_quoting_style;
451133543Stjr				}
452133543Stjr			  }
453133543Stjr
45498038Sache			if (! iswprint (w))
455133543Stjr			  printable = false;
45698038Sache			m += bytes;
45798038Sache		      }
45898038Sache		  }
45998038Sache		while (! mbsinit (&mbstate));
46098038Sache	      }
46198038Sache
46298038Sache	    if (1 < m || (backslash_escapes && ! printable))
46398038Sache	      {
46498038Sache		/* Output a multibyte sequence, or an escaped
46598038Sache		   unprintable unibyte character.  */
46698038Sache		size_t ilim = i + m;
46798038Sache
46898038Sache		for (;;)
46998038Sache		  {
47098038Sache		    if (backslash_escapes && ! printable)
47198038Sache		      {
47298038Sache			STORE ('\\');
47398038Sache			STORE ('0' + (c >> 6));
47498038Sache			STORE ('0' + ((c >> 3) & 7));
47598038Sache			c = '0' + (c & 7);
47698038Sache		      }
47798038Sache		    if (ilim <= i + 1)
47898038Sache		      break;
47998038Sache		    STORE (c);
48098038Sache		    c = arg[++i];
48198038Sache		  }
48298038Sache
48398038Sache		goto store_c;
48498038Sache	      }
48598038Sache	  }
48698038Sache	}
48798038Sache
48898038Sache      if (! (backslash_escapes
48998038Sache	     && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
49098038Sache	goto store_c;
49198038Sache
49298038Sache    store_escape:
49398038Sache      STORE ('\\');
49498038Sache
49598038Sache    store_c:
49698038Sache      STORE (c);
49798038Sache    }
49898038Sache
499133543Stjr  if (i == 0 && quoting_style == shell_quoting_style)
500133543Stjr    goto use_shell_always_quoting_style;
501133543Stjr
50298038Sache  if (quote_string)
50398038Sache    for (; *quote_string; quote_string++)
50498038Sache      STORE (*quote_string);
50598038Sache
50698038Sache  if (len < buffersize)
50798038Sache    buffer[len] = '\0';
50898038Sache  return len;
50998038Sache
51098038Sache use_shell_always_quoting_style:
51198038Sache  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
51298038Sache				   shell_always_quoting_style, o);
51398038Sache}
51498038Sache
51598038Sache/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
51698038Sache   argument ARG (of size ARGSIZE), using O to control quoting.
51798038Sache   If O is null, use the default.
51898038Sache   Terminate the output with a null character, and return the written
51998038Sache   size of the output, not counting the terminating null.
52098038Sache   If BUFFERSIZE is too small to store the output string, return the
52198038Sache   value that would have been returned had BUFFERSIZE been large enough.
522133543Stjr   If ARGSIZE is SIZE_MAX, use the string length of the argument for
523133543Stjr   ARGSIZE.  */
52498038Sachesize_t
52598038Sachequotearg_buffer (char *buffer, size_t buffersize,
52698038Sache		 char const *arg, size_t argsize,
52798038Sache		 struct quoting_options const *o)
52898038Sache{
52998038Sache  struct quoting_options const *p = o ? o : &default_quoting_options;
530131447Stjr  int e = errno;
531131447Stjr  size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
532131447Stjr				       p->style, p);
533131447Stjr  errno = e;
534131447Stjr  return r;
53598038Sache}
53698038Sache
537133543Stjr/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
538133543Stjr   allocated storage containing the quoted string.  */
539133543Stjrchar *
540133543Stjrquotearg_alloc (char const *arg, size_t argsize,
541133543Stjr		struct quoting_options const *o)
542133543Stjr{
543133543Stjr  int e = errno;
544133543Stjr  size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
545133543Stjr  char *buf = xmalloc (bufsize);
546133543Stjr  quotearg_buffer (buf, bufsize, arg, argsize, o);
547133543Stjr  errno = e;
548133543Stjr  return buf;
549133543Stjr}
550133543Stjr
55198038Sache/* Use storage slot N to return a quoted version of argument ARG.
552133543Stjr   ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
553133543Stjr   null-terminated string.
55498038Sache   OPTIONS specifies the quoting options.
55598038Sache   The returned value points to static storage that can be
55698038Sache   reused by the next call to this function with the same value of N.
55798038Sache   N must be nonnegative.  N is deliberately declared with type "int"
55898038Sache   to allow for future extensions (using negative values).  */
55998038Sachestatic char *
56098038Sachequotearg_n_options (int n, char const *arg, size_t argsize,
56198038Sache		    struct quoting_options const *options)
56298038Sache{
563131447Stjr  int e = errno;
564131447Stjr
56598038Sache  /* Preallocate a slot 0 buffer, so that the caller can always quote
56698038Sache     one small component of a "memory exhausted" message in slot 0.  */
56798038Sache  static char slot0[256];
56898038Sache  static unsigned int nslots = 1;
56998038Sache  unsigned int n0 = n;
57098038Sache  struct slotvec
57198038Sache    {
57298038Sache      size_t size;
57398038Sache      char *val;
57498038Sache    };
57598038Sache  static struct slotvec slotvec0 = {sizeof slot0, slot0};
57698038Sache  static struct slotvec *slotvec = &slotvec0;
57798038Sache
57898038Sache  if (n < 0)
57998038Sache    abort ();
58098038Sache
58198038Sache  if (nslots <= n0)
58298038Sache    {
58398038Sache      unsigned int n1 = n0 + 1;
58498038Sache
585131447Stjr      if (xalloc_oversized (n1, sizeof *slotvec))
58698038Sache	xalloc_die ();
58798038Sache
58898038Sache      if (slotvec == &slotvec0)
58998038Sache	{
590131447Stjr	  slotvec = xmalloc (sizeof *slotvec);
59198038Sache	  *slotvec = slotvec0;
59298038Sache	}
593131447Stjr      slotvec = xrealloc (slotvec, n1 * sizeof *slotvec);
59498038Sache      memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
59598038Sache      nslots = n1;
59698038Sache    }
59798038Sache
59898038Sache  {
59998038Sache    size_t size = slotvec[n].size;
60098038Sache    char *val = slotvec[n].val;
60198038Sache    size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
60298038Sache
60398038Sache    if (size <= qsize)
60498038Sache      {
60598038Sache	slotvec[n].size = size = qsize + 1;
606131447Stjr	if (val != slot0)
607131447Stjr	  free (val);
608131447Stjr	slotvec[n].val = val = xmalloc (size);
60998038Sache	quotearg_buffer (val, size, arg, argsize, options);
61098038Sache      }
61198038Sache
612131447Stjr    errno = e;
61398038Sache    return val;
61498038Sache  }
61598038Sache}
61698038Sache
61798038Sachechar *
61898038Sachequotearg_n (int n, char const *arg)
61998038Sache{
620131447Stjr  return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
62198038Sache}
62298038Sache
62398038Sachechar *
62498038Sachequotearg (char const *arg)
62598038Sache{
62698038Sache  return quotearg_n (0, arg);
62798038Sache}
62898038Sache
62998038Sache/* Return quoting options for STYLE, with no extra quoting.  */
63098038Sachestatic struct quoting_options
63198038Sachequoting_options_from_style (enum quoting_style style)
63298038Sache{
63398038Sache  struct quoting_options o;
63498038Sache  o.style = style;
63598038Sache  memset (o.quote_these_too, 0, sizeof o.quote_these_too);
63698038Sache  return o;
63798038Sache}
63898038Sache
63998038Sachechar *
64098038Sachequotearg_n_style (int n, enum quoting_style s, char const *arg)
64198038Sache{
64298038Sache  struct quoting_options const o = quoting_options_from_style (s);
643131447Stjr  return quotearg_n_options (n, arg, SIZE_MAX, &o);
64498038Sache}
64598038Sache
64698038Sachechar *
64798038Sachequotearg_n_style_mem (int n, enum quoting_style s,
64898038Sache		      char const *arg, size_t argsize)
64998038Sache{
65098038Sache  struct quoting_options const o = quoting_options_from_style (s);
65198038Sache  return quotearg_n_options (n, arg, argsize, &o);
65298038Sache}
65398038Sache
65498038Sachechar *
65598038Sachequotearg_style (enum quoting_style s, char const *arg)
65698038Sache{
65798038Sache  return quotearg_n_style (0, s, arg);
65898038Sache}
65998038Sache
66098038Sachechar *
66198038Sachequotearg_char (char const *arg, char ch)
66298038Sache{
66398038Sache  struct quoting_options options;
66498038Sache  options = default_quoting_options;
66598038Sache  set_char_quoting (&options, ch, 1);
666131447Stjr  return quotearg_n_options (0, arg, SIZE_MAX, &options);
66798038Sache}
66898038Sache
66998038Sachechar *
67098038Sachequotearg_colon (char const *arg)
67198038Sache{
67298038Sache  return quotearg_char (arg, ':');
67398038Sache}
674