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