*** empty log message ***
[coreutils.git] / lib / quotearg.c
blob06f5fea843f5bd46fd68656a648ee60a67488269
1 /* quotearg.c - quote arguments for output
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Paul Eggert <eggert@twinsun.com> */
20 /* FIXME: Multibyte characters are not supported yet. */
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
26 #include <sys/types.h>
27 #include <quotearg.h>
28 #include <xalloc.h>
30 #include <ctype.h>
31 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
32 # define ISASCII(c) 1
33 #else
34 # define ISASCII(c) isascii (c)
35 #endif
36 #ifdef isgraph
37 # define ISGRAPH(c) (ISASCII (c) && isgraph (c))
38 #else
39 # define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
40 #endif
42 #if ENABLE_NLS
43 # include <libintl.h>
44 # define _(text) gettext (text)
45 #else
46 # define _(text) text
47 #endif
49 #if HAVE_LIMITS_H
50 # include <limits.h>
51 #endif
52 #ifndef CHAR_BIT
53 # define CHAR_BIT 8
54 #endif
55 #ifndef UCHAR_MAX
56 # define UCHAR_MAX ((unsigned char) -1)
57 #endif
59 #if HAVE_STDLIB_H
60 # include <stdlib.h>
61 #endif
63 #if HAVE_STRING_H
64 # include <string.h>
65 #endif
67 #define INT_BITS (sizeof (int) * CHAR_BIT)
69 struct quoting_options
71 /* Basic quoting style. */
72 enum quoting_style style;
74 /* Quote the chararacters indicated by this bit vector even if the
75 quoting style would not normally require them to be quoted. */
76 int quote_these_too[((UCHAR_MAX + 1) / INT_BITS
77 + ((UCHAR_MAX + 1) % INT_BITS != 0))];
80 /* Names of quoting styles. */
81 char const *const quoting_style_args[] =
83 "literal",
84 "shell",
85 "shell-always",
86 "c",
87 "escape",
88 "locale",
92 /* Correspondances to quoting style names. */
93 enum quoting_style const quoting_style_vals[] =
95 literal_quoting_style,
96 shell_quoting_style,
97 shell_always_quoting_style,
98 c_quoting_style,
99 escape_quoting_style,
100 locale_quoting_style
103 /* The default quoting options. */
104 static struct quoting_options default_quoting_options;
106 /* Allocate a new set of quoting options, with contents initially identical
107 to O if O is not null, or to the default if O is null.
108 It is the caller's responsibility to free the result. */
109 struct quoting_options *
110 clone_quoting_options (struct quoting_options *o)
112 struct quoting_options *p
113 = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
114 *p = *(o ? o : &default_quoting_options);
115 return p;
118 /* Get the value of O's quoting style. If O is null, use the default. */
119 enum quoting_style
120 get_quoting_style (struct quoting_options *o)
122 return (o ? o : &default_quoting_options)->style;
125 /* In O (or in the default if O is null),
126 set the value of the quoting style to S. */
127 void
128 set_quoting_style (struct quoting_options *o, enum quoting_style s)
130 (o ? o : &default_quoting_options)->style = s;
133 /* In O (or in the default if O is null),
134 set the value of the quoting options for character C to I.
135 Return the old value. Currently, the only values defined for I are
136 0 (the default) and 1 (which means to quote the character even if
137 it would not otherwise be quoted). */
139 set_char_quoting (struct quoting_options *o, char c, int i)
141 unsigned char uc = c;
142 int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
143 int shift = uc % INT_BITS;
144 int r = (*p >> shift) & 1;
145 *p ^= ((i & 1) ^ r) << shift;
146 return r;
149 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
150 argument ARG (of size ARGSIZE), using O to control quoting.
151 If O is null, use the default.
152 Terminate the output with a null character, and return the written
153 size of the output, not counting the terminating null.
154 If BUFFERSIZE is too small to store the output string, return the
155 value that would have been returned had BUFFERSIZE been large enough.
156 If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
157 size_t
158 quotearg_buffer (char *buffer, size_t buffersize,
159 char const *arg, size_t argsize,
160 struct quoting_options const *o)
162 unsigned char c;
163 size_t i;
164 size_t len = 0;
165 char const *quote_string;
166 size_t quote_string_len;
167 struct quoting_options const *p = o ? o : &default_quoting_options;
168 enum quoting_style quoting_style = p->style;
169 #define STORE(c) \
170 do \
172 if (len < buffersize) \
173 buffer[len] = (c); \
174 len++; \
176 while (0)
178 switch (quoting_style)
180 case shell_quoting_style:
181 if (! (argsize == (size_t) -1 ? arg[0] == '\0' : argsize == 0))
183 switch (arg[0])
185 case '#': case '~':
186 break;
188 default:
189 for (i = 0; ; i++)
191 if (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize)
192 goto done;
194 c = arg[i];
196 switch (c)
198 case '\t': case '\n': case ' ':
199 case '!': /* special in csh */
200 case '"': case '$': case '&': case '\'':
201 case '(': case ')': case '*': case ';':
202 case '<': case '>': case '?': case '[': case '\\':
203 case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
204 case '`': case '|':
205 goto needs_quoting;
208 if (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
209 goto needs_quoting;
211 STORE (c);
213 needs_quoting:;
215 len = 0;
216 break;
219 /* Fall through. */
221 case shell_always_quoting_style:
222 STORE ('\'');
223 quote_string = "'";
224 quote_string_len = 1;
225 break;
227 case c_quoting_style:
228 STORE ('"');
229 quote_string = "\"";
230 quote_string_len = 1;
231 break;
233 case locale_quoting_style:
234 for (quote_string = _("`"); *quote_string; quote_string++)
235 STORE (*quote_string);
236 quote_string = _("'");
237 quote_string_len = strlen (quote_string);
238 break;
240 default:
241 quote_string = 0;
242 quote_string_len = 0;
243 break;
246 for (i = 0; ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize); i++)
248 c = arg[i];
250 switch (quoting_style)
252 case literal_quoting_style:
253 break;
255 case shell_quoting_style:
256 case shell_always_quoting_style:
257 if (c == '\'')
259 STORE ('\'');
260 STORE ('\\');
261 STORE ('\'');
263 break;
265 case c_quoting_style:
266 case escape_quoting_style:
267 case locale_quoting_style:
268 switch (c)
270 case '?': /* Do not generate trigraphs. */
271 case '\\': goto store_escape;
272 /* Not all C compilers know what \a means. */
273 case 7 : c = 'a'; goto store_escape;
274 case '\b': c = 'b'; goto store_escape;
275 case '\f': c = 'f'; goto store_escape;
276 case '\n': c = 'n'; goto store_escape;
277 case '\r': c = 'r'; goto store_escape;
278 case '\t': c = 't'; goto store_escape;
279 case '\v': c = 'v'; goto store_escape;
281 case ' ': break;
283 default:
284 if (quote_string_len
285 && strncmp (arg + i, quote_string, quote_string_len) == 0)
286 goto store_escape;
287 if (!ISGRAPH (c))
289 STORE ('\\');
290 STORE ('0' + (c >> 6));
291 STORE ('0' + ((c >> 3) & 7));
292 c = '0' + (c & 7);
293 goto store_c;
295 break;
298 if (! (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
299 goto store_c;
301 store_escape:
302 STORE ('\\');
305 store_c:
306 STORE (c);
309 if (quote_string)
310 for (; *quote_string; quote_string++)
311 STORE (*quote_string);
313 done:
314 if (len < buffersize)
315 buffer[len] = '\0';
316 return len;
319 /* Use storage slot N to return a quoted version of the string ARG.
320 OPTIONS specifies the quoting options.
321 The returned value points to static storage that can be
322 reused by the next call to this function with the same value of N.
323 N must be nonnegative. N is deliberately declared with type `int'
324 to allow for future extensions (using negative values). */
325 static char *
326 quotearg_n_options (int n, char const *arg,
327 struct quoting_options const *options)
329 static unsigned int nslots;
330 static struct slotvec
332 size_t size;
333 char *val;
334 } *slotvec;
336 if (nslots <= n)
338 int n1 = n + 1;
339 size_t s = n1 * sizeof (struct slotvec);
340 if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
341 abort ();
342 slotvec = (struct slotvec *) xrealloc (slotvec, s);
343 memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
344 nslots = n;
348 size_t size = slotvec[n].size;
349 char *val = slotvec[n].val;
350 size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
352 if (size <= qsize)
354 slotvec[n].size = size = qsize + 1;
355 slotvec[n].val = val = xrealloc (val, size);
356 quotearg_buffer (val, size, arg, (size_t) -1, options);
359 return val;
363 char *
364 quotearg_n (unsigned int n, char const *arg)
366 return quotearg_n_options (n, arg, &default_quoting_options);
369 char *
370 quotearg (char const *arg)
372 return quotearg_n (0, arg);
375 char *
376 quotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
378 struct quoting_options o;
379 o.style = s;
380 memset (o.quote_these_too, 0, sizeof o.quote_these_too);
381 return quotearg_n_options (n, arg, &o);
384 char *
385 quotearg_style (enum quoting_style s, char const *arg)
387 return quotearg_n_style (0, s, arg);
390 char *
391 quotearg_char (char const *arg, char ch)
393 struct quoting_options options;
394 options = default_quoting_options;
395 set_char_quoting (&options, ch, 1);
396 return quotearg_n_options (0, arg, &options);
399 char *
400 quotearg_colon (char const *arg)
402 return quotearg_char (arg, ':');