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