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