(ISASCII): Add #undef and move definition to follow
[gnulib.git] / lib / quotearg.c
1 /* quotearg.c - quote arguments for output
2    Copyright (C) 1998, 1999, 2000 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 #if HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <sys/types.h>
25 #include <quotearg.h>
26 #include <xalloc.h>
27
28 #include <ctype.h>
29
30 #if ENABLE_NLS
31 # include <libintl.h>
32 # define _(text) gettext (text)
33 #else
34 # define _(text) text
35 #endif
36
37 #if HAVE_LIMITS_H
38 # include <limits.h>
39 #endif
40 #ifndef CHAR_BIT
41 # define CHAR_BIT 8
42 #endif
43 #ifndef UCHAR_MAX
44 # define UCHAR_MAX ((unsigned char) -1)
45 #endif
46
47 #if HAVE_STDLIB_H
48 # include <stdlib.h>
49 #endif
50
51 #if HAVE_STRING_H
52 # include <string.h>
53 #endif
54
55 #if HAVE_WCTYPE_H
56 # include <wctype.h>
57 #endif
58
59 #if HAVE_MBRTOWC && HAVE_WCHAR_H
60 # include <wchar.h>
61 #else
62 # define iswprint(wc) 1
63 # define mbrtowc(pwc, s, n, ps) 1
64 # define mbsinit(ps) 1
65 # define mbstate_t int
66 #endif
67
68 #define INT_BITS (sizeof (int) * CHAR_BIT)
69
70 #if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
71 /* Undefine to protect against the definition in wctype.h of solaris2.6.   */
72 # undef ISASCII
73 # define ISASCII(c) 1
74 #else
75 # define ISASCII(c) isascii (c)
76 #endif
77 /* Undefine to protect against the definition in wctype.h of solaris2.6.   */
78 #undef ISASCII
79 #define ISPRINT(c) (ISASCII (c) && isprint (c))
80
81 struct quoting_options
82 {
83   /* Basic quoting style.  */
84   enum quoting_style style;
85
86   /* Quote the characters indicated by this bit vector even if the
87      quoting style would not normally require them to be quoted.  */
88   int quote_these_too[((UCHAR_MAX + 1) / INT_BITS
89                        + ((UCHAR_MAX + 1) % INT_BITS != 0))];
90 };
91
92 /* Names of quoting styles.  */
93 char const *const quoting_style_args[] =
94 {
95   "literal",
96   "shell",
97   "shell-always",
98   "c",
99   "escape",
100   "locale",
101   0
102 };
103
104 /* Correspondences to quoting style names.  */
105 enum quoting_style const quoting_style_vals[] =
106 {
107   literal_quoting_style,
108   shell_quoting_style,
109   shell_always_quoting_style,
110   c_quoting_style,
111   escape_quoting_style,
112   locale_quoting_style
113 };
114
115 /* The default quoting options.  */
116 static struct quoting_options default_quoting_options;
117
118 /* Allocate a new set of quoting options, with contents initially identical
119    to O if O is not null, or to the default if O is null.
120    It is the caller's responsibility to free the result.  */
121 struct quoting_options *
122 clone_quoting_options (struct quoting_options *o)
123 {
124   struct quoting_options *p
125     = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
126   *p = *(o ? o : &default_quoting_options);
127   return p;
128 }
129
130 /* Get the value of O's quoting style.  If O is null, use the default.  */
131 enum quoting_style
132 get_quoting_style (struct quoting_options *o)
133 {
134   return (o ? o : &default_quoting_options)->style;
135 }
136
137 /* In O (or in the default if O is null),
138    set the value of the quoting style to S.  */
139 void
140 set_quoting_style (struct quoting_options *o, enum quoting_style s)
141 {
142   (o ? o : &default_quoting_options)->style = s;
143 }
144
145 /* In O (or in the default if O is null),
146    set the value of the quoting options for character C to I.
147    Return the old value.  Currently, the only values defined for I are
148    0 (the default) and 1 (which means to quote the character even if
149    it would not otherwise be quoted).  */
150 int
151 set_char_quoting (struct quoting_options *o, char c, int i)
152 {
153   unsigned char uc = c;
154   int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
155   int shift = uc % INT_BITS;
156   int r = (*p >> shift) & 1;
157   *p ^= ((i & 1) ^ r) << shift;
158   return r;
159 }
160
161 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
162    argument ARG (of size ARGSIZE), using QUOTING_STYLE and the
163    non-quoting-style part of O to control quoting.
164    Terminate the output with a null character, and return the written
165    size of the output, not counting the terminating null.
166    If BUFFERSIZE is too small to store the output string, return the
167    value that would have been returned had BUFFERSIZE been large enough.
168    If ARGSIZE is -1, use the string length of the argument for ARGSIZE.
169
170    This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
171    ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting
172    style specified by O, and O may not be null.  */
173
174 static size_t
175 quotearg_buffer_restyled (char *buffer, size_t buffersize,
176                           char const *arg, size_t argsize,
177                           enum quoting_style quoting_style,
178                           struct quoting_options const *o)
179 {
180   size_t i;
181   size_t len = 0;
182   char const *quote_string = 0;
183   size_t quote_string_len = 0;
184   int backslash_escapes = 0;
185
186 #define STORE(c) \
187     do \
188       { \
189         if (len < buffersize) \
190           buffer[len] = (c); \
191         len++; \
192       } \
193     while (0)
194
195   switch (quoting_style)
196     {
197     case c_quoting_style:
198       STORE ('"');
199       backslash_escapes = 1;
200       quote_string = "\"";
201       quote_string_len = 1;
202       break;
203
204     case escape_quoting_style:
205       backslash_escapes = 1;
206       break;
207
208     case locale_quoting_style:
209       for (quote_string = _("`"); *quote_string; quote_string++)
210         STORE (*quote_string);
211       backslash_escapes = 1;
212       quote_string = _("'");
213       quote_string_len = strlen (quote_string);
214       break;
215
216     case shell_always_quoting_style:
217       STORE ('\'');
218       quote_string = "'";
219       quote_string_len = 1;
220       break;
221
222     default:
223       break;
224     }
225
226   for (i = 0;  ! (argsize == (size_t) -1 ? arg[i] == '\0' : i == argsize);  i++)
227     {
228       unsigned char c;
229       unsigned char esc;
230
231       if (backslash_escapes
232           && quote_string_len
233           && i + quote_string_len <= argsize
234           && memcmp (arg + i, quote_string, quote_string_len) == 0)
235         STORE ('\\');
236
237       c = arg[i];
238       switch (c)
239         {
240         case '?':
241           switch (quoting_style)
242             {
243             case shell_quoting_style:
244               goto use_shell_always_quoting_style;
245
246             case c_quoting_style:
247               if (i + 2 < argsize && arg[i + 1] == '?')
248                 switch (arg[i + 2])
249                   {
250                   case '!': case '\'':
251                   case '(': case ')': case '-': case '/':
252                   case '<': case '=': case '>':
253                     /* Escape the second '?' in what would otherwise be
254                        a trigraph.  */
255                     i += 2;
256                     c = arg[i + 2];
257                     STORE ('?');
258                     STORE ('\\');
259                     STORE ('?');
260                     break;
261                   }
262               break;
263
264             default:
265               break;
266             }
267           break;
268
269 #if HAVE_C_BACKSLASH_A
270         case '\a': esc = 'a'; goto c_escape;
271 #endif
272         case '\b': esc = 'b'; goto c_escape;
273         case '\f': esc = 'f'; goto c_escape;
274         case '\n': esc = 'n'; goto c_and_shell_escape;
275         case '\r': esc = 'r'; goto c_and_shell_escape;
276         case '\t': esc = 't'; goto c_and_shell_escape;
277         case '\v': esc = 'v'; goto c_escape;
278         case '\\': esc = c; goto c_and_shell_escape;
279
280         c_and_shell_escape:
281           if (quoting_style == shell_quoting_style)
282             goto use_shell_always_quoting_style;
283         c_escape:
284           if (backslash_escapes)
285             {
286               c = esc;
287               goto store_escape;
288             }
289           break;
290
291         case '#': case '~':
292           if (i != 0)
293             break;
294           /* Fall through.  */
295         case ' ':
296         case '!': /* special in bash */
297         case '"': case '$': case '&':
298         case '(': case ')': case '*': case ';':
299         case '<': case '>': case '[':
300         case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
301         case '`': case '|':
302           /* A shell special character.  In theory, '$' and '`' could
303              be the first bytes of multibyte characters, which means
304              we should check them with mbrtowc, but in practice this
305              doesn't happen so it's not worth worrying about.  */
306           if (quoting_style == shell_quoting_style)
307             goto use_shell_always_quoting_style;
308           break;
309
310         case '\'':
311           switch (quoting_style)
312             {
313             case shell_quoting_style:
314               goto use_shell_always_quoting_style;
315
316             case shell_always_quoting_style:
317               STORE ('\'');
318               STORE ('\\');
319               STORE ('\'');
320               break;
321
322             default:
323               break;
324             }
325           break;
326
327         case '%': case '+': case ',': case '-': case '.': case '/':
328         case '0': case '1': case '2': case '3': case '4': case '5':
329         case '6': case '7': case '8': case '9': case ':': case '=':
330         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
331         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
332         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
333         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
334         case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
335         case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
336         case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
337         case 'o': case 'p': case 'q': case 'r': case 's': case 't':
338         case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
339         case '{': case '}':
340           /* These characters don't cause problems, no matter what the
341              quoting style is.  They cannot start multibyte sequences.  */
342           break;
343
344         default:
345           /* If we have a multibyte sequence, copy it until we reach
346              its end, find an error, or come back to the initial shift
347              state.  For C-like styles, if the sequence has
348              unprintable characters, escape the whole sequence, since
349              we can't easily escape single characters within it.  */
350           {
351             /* Length of multibyte sequence found so far.  */
352             size_t m = 0;
353
354             int printable = 1;
355             mbstate_t mbstate;
356             memset (&mbstate, 0, sizeof mbstate);
357
358             if (argsize == (size_t) -1)
359               argsize = strlen (arg);
360
361             do
362               {
363                 wchar_t w;
364                 size_t bytes = mbrtowc (&w, &arg[i + m],
365                                         argsize - (i + m), &mbstate);
366                 if (bytes == 0)
367                   break;
368                 else if (bytes == (size_t) -1)
369                   {
370                     printable = 0;
371                     break;
372                   }
373                 else if (bytes == (size_t) -2)
374                   {
375                     printable = 0;
376                     while (i + m < argsize && arg[i + m])
377                       m++;
378                     break;
379                   }
380                 else
381                   {
382                     if (! iswprint (w))
383                       printable = 0;
384                     m += bytes;
385                   }
386               }
387             while (! mbsinit (&mbstate));
388
389             if (m <= 1)
390               {
391                 /* Escape a unibyte character like a multibyte
392                    sequence if using backslash escapes, and if the
393                    character is not printable.  */
394                 m = backslash_escapes && ! ISPRINT (c);
395                 printable = 0;
396               }
397
398             if (m)
399               {
400                 /* Output a multibyte sequence, or an escaped
401                    unprintable unibyte character.  */
402                 size_t imax = i + m - 1;
403
404                 for (;;)
405                   {
406                     if (backslash_escapes && ! printable)
407                       {
408                         STORE ('\\');
409                         STORE ('0' + (c >> 6));
410                         STORE ('0' + ((c >> 3) & 7));
411                         c = '0' + (c & 7);
412                       }
413                     if (i == imax)
414                       break;
415                     STORE (c);
416                     c = arg[++i];
417                   }
418
419                 goto store_c;
420               }
421           }
422         }
423
424       if (! (backslash_escapes
425              && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
426         goto store_c;
427
428     store_escape:
429       STORE ('\\');
430
431     store_c:
432       STORE (c);
433     }
434
435   if (quote_string)
436     for (; *quote_string; quote_string++)
437       STORE (*quote_string);
438
439   if (len < buffersize)
440     buffer[len] = '\0';
441   return len;
442
443  use_shell_always_quoting_style:
444   return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
445                                    shell_always_quoting_style, o);
446 }
447
448 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
449    argument ARG (of size ARGSIZE), using O to control quoting.
450    If O is null, use the default.
451    Terminate the output with a null character, and return the written
452    size of the output, not counting the terminating null.
453    If BUFFERSIZE is too small to store the output string, return the
454    value that would have been returned had BUFFERSIZE been large enough.
455    If ARGSIZE is -1, use the string length of the argument for ARGSIZE.  */
456 size_t
457 quotearg_buffer (char *buffer, size_t buffersize,
458                  char const *arg, size_t argsize,
459                  struct quoting_options const *o)
460 {
461   struct quoting_options const *p = o ? o : &default_quoting_options;
462   return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
463                                    p->style, p);
464 }
465
466 /* Use storage slot N to return a quoted version of the string ARG.
467    OPTIONS specifies the quoting options.
468    The returned value points to static storage that can be
469    reused by the next call to this function with the same value of N.
470    N must be nonnegative.  N is deliberately declared with type `int'
471    to allow for future extensions (using negative values).  */
472 static char *
473 quotearg_n_options (int n, char const *arg,
474                     struct quoting_options const *options)
475 {
476   static unsigned int nslots;
477   static struct slotvec
478     {
479       size_t size;
480       char *val;
481     } *slotvec;
482
483   if (nslots <= n)
484     {
485       int n1 = n + 1;
486       size_t s = n1 * sizeof (struct slotvec);
487       if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
488         abort ();
489       slotvec = (struct slotvec *) xrealloc (slotvec, s);
490       memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
491       nslots = n;
492     }
493
494   {
495     size_t size = slotvec[n].size;
496     char *val = slotvec[n].val;
497     size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
498
499     if (size <= qsize)
500       {
501         slotvec[n].size = size = qsize + 1;
502         slotvec[n].val = val = xrealloc (val, size);
503         quotearg_buffer (val, size, arg, (size_t) -1, options);
504       }
505
506     return val;
507   }
508 }
509
510 char *
511 quotearg_n (unsigned int n, char const *arg)
512 {
513   return quotearg_n_options (n, arg, &default_quoting_options);
514 }
515
516 char *
517 quotearg (char const *arg)
518 {
519   return quotearg_n (0, arg);
520 }
521
522 char *
523 quotearg_n_style (unsigned int n, enum quoting_style s, char const *arg)
524 {
525   struct quoting_options o;
526   o.style = s;
527   memset (o.quote_these_too, 0, sizeof o.quote_these_too);
528   return quotearg_n_options (n, arg, &o);
529 }
530
531 char *
532 quotearg_style (enum quoting_style s, char const *arg)
533 {
534   return quotearg_n_style (0, s, arg);
535 }
536
537 char *
538 quotearg_char (char const *arg, char ch)
539 {
540   struct quoting_options options;
541   options = default_quoting_options;
542   set_char_quoting (&options, ch, 1);
543   return quotearg_n_options (0, arg, &options);
544 }
545
546 char *
547 quotearg_colon (char const *arg)
548 {
549   return quotearg_char (arg, ':');
550 }