Include <libintl.h> if ENABLE_NLS.
[gnulib.git] / lib / quotearg.c
1 /* quotearg.c - quote arguments for output
2    Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3
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.
8
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.
13
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.  */
17
18 /* Written by Paul Eggert <eggert@twinsun.com> */
19
20 /* FIXME: Multibyte characters are not supported yet.  */
21
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 #include <sys/types.h>
27 #include <quotearg.h>
28 #include <xalloc.h>
29
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
41
42 #if ENABLE_NLS
43 # include <libintl.h>
44 # define _(text) gettext (text)
45 #else
46 # define _(text) text
47 #endif
48
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
58
59 #if HAVE_STDLIB_H
60 # include <stdlib.h>
61 #endif
62
63 #if HAVE_STRING_H
64 # include <string.h>
65 #endif
66
67 #define INT_BITS (sizeof (int) * CHAR_BIT)
68
69 struct quoting_options
70 {
71   /* Basic quoting style.  */
72   enum quoting_style style;
73
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))];
78 };
79
80 /* Names of quoting styles.  */
81 char const *const quoting_style_args[] =
82 {
83   "literal",
84   "shell",
85   "shell-always",
86   "c",
87   "escape",
88   "locale",
89   0
90 };
91
92 /* Correspondances to quoting style names.  */
93 enum quoting_style const quoting_style_vals[] =
94 {
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
101 };
102
103 /* The default quoting options.  */
104 static struct quoting_options default_quoting_options;
105
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)
111 {
112   struct quoting_options *p
113     = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
114   *p = *(o ? o : &default_quoting_options);
115   return p;
116 }
117
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)
121 {
122   return (o ? o : &default_quoting_options)->style;
123 }
124
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)
129 {
130   (o ? o : &default_quoting_options)->style = s;
131 }
132
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).  */
138 int
139 set_char_quoting (struct quoting_options *o, char c, int i)
140 {
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;
147 }
148
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)
161 {
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 \
171       { \
172         if (len < buffersize) \
173           buffer[len] = (c); \
174           len++; \
175       } \
176     while (0)
177
178   switch (quoting_style)
179     {
180     case shell_quoting_style:
181       if (! (argsize == (size_t) -1 ? arg[0] == '\0' : argsize == 0))
182         {
183           switch (arg[0])
184             {
185             case '#': case '~':
186               break;
187
188             default:
189               for (i = 0; ; i++)
190                 {
191                   if (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize)
192                     goto done;
193
194                   c = arg[i];
195
196                   switch (c)
197                     {
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;
206                     }
207
208                   if (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
209                     goto needs_quoting;
210
211                   STORE (c);
212                 }
213             needs_quoting:;
214
215               len = 0;
216               break;
217             }
218         }
219       /* Fall through.  */
220
221     case shell_always_quoting_style:
222       STORE ('\'');
223       quote_string = "'";
224       quote_string_len = 1;
225       break;
226
227     case c_quoting_style:
228       STORE ('"');
229       quote_string = "\"";
230       quote_string_len = 1;
231       break;
232
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;
239
240     default:
241       quote_string = 0;
242       quote_string_len = 0;
243       break;
244     }
245
246   for (i = 0;  ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize);  i++)
247     {
248       c = arg[i];
249
250       switch (quoting_style)
251         {
252         case literal_quoting_style:
253           break;
254
255         case shell_quoting_style:
256         case shell_always_quoting_style:
257           if (c == '\'')
258             {
259               STORE ('\'');
260               STORE ('\\');
261               STORE ('\'');
262             }
263           break;
264
265         case c_quoting_style:
266         case escape_quoting_style:
267         case locale_quoting_style:
268           switch (c)
269             {
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;
280
281             case ' ': break;
282
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))
288                 {
289                   STORE ('\\');
290                   STORE ('0' + (c >> 6));
291                   STORE ('0' + ((c >> 3) & 7));
292                   c = '0' + (c & 7);
293                   goto store_c;
294                 }
295               break;
296             }
297
298           if (! (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
299             goto store_c;
300
301         store_escape:
302           STORE ('\\');
303         }
304
305     store_c:
306       STORE (c);
307     }
308
309   if (quote_string)
310     for (; *quote_string; quote_string++)
311       STORE (*quote_string);
312
313  done:
314   if (len < buffersize)
315     buffer[len] = '\0';
316   return len;
317 }
318
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)
328 {
329   static unsigned int nslots;
330   static struct slotvec
331     {
332       size_t size;
333       char *val;
334     } *slotvec;
335
336   if (nslots <= n)
337     {
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;
345     }
346
347   {
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);
351
352     if (size <= qsize)
353       {
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);
357       }
358
359     return val;
360   }
361 }
362
363 char *
364 quotearg_n (unsigned int n, char const *arg)
365 {
366   return quotearg_n_options (n, arg, &default_quoting_options);
367 }
368
369 char *
370 quotearg (char const *arg)
371 {
372   return quotearg_n (0, arg);
373 }
374
375 char *
376 quotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
377 {
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);
382 }
383
384 char *
385 quotearg_style (enum quoting_style s, char const *arg)
386 {
387   return quotearg_n_style (0, s, arg);
388 }
389
390 char *
391 quotearg_char (char const *arg, char ch)
392 {
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);
397 }
398
399 char *
400 quotearg_colon (char const *arg)
401 {
402   return quotearg_char (arg, ':');
403 }