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