]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/gnu-sort/lib/quotearg.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / gnu-sort / lib / quotearg.c
1 /* quotearg.c - quote arguments for output
2
3    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
4    Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 /* Written by Paul Eggert <eggert@twinsun.com> */
21
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 #include "quotearg.h"
27
28 #include "xalloc.h"
29
30 #include <ctype.h>
31 #include <errno.h>
32 #include <limits.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include "gettext.h"
38 #define _(msgid) gettext (msgid)
39 #define N_(msgid) msgid
40
41 #if HAVE_WCHAR_H
42
43 /* BSD/OS 4.1 wchar.h requires FILE and struct tm to be declared.  */
44 # include <stdio.h>
45 # include <time.h>
46
47 # include <wchar.h>
48 #endif
49
50 #if !HAVE_MBRTOWC
51 /* Disable multibyte processing entirely.  Since MB_CUR_MAX is 1, the
52    other macros are defined only for documentation and to satisfy C
53    syntax.  */
54 # undef MB_CUR_MAX
55 # define MB_CUR_MAX 1
56 # define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0)
57 # define iswprint(wc) isprint ((unsigned char) (wc))
58 # undef HAVE_MBSINIT
59 #endif
60
61 #if !defined mbsinit && !HAVE_MBSINIT
62 # define mbsinit(ps) 1
63 #endif
64
65 #ifndef iswprint
66 # if HAVE_WCTYPE_H
67 #  include <wctype.h>
68 # endif
69 # if !defined iswprint && !HAVE_ISWPRINT
70 #  define iswprint(wc) 1
71 # endif
72 #endif
73
74 #ifndef SIZE_MAX
75 # define SIZE_MAX ((size_t) -1)
76 #endif
77
78 #define INT_BITS (sizeof (int) * CHAR_BIT)
79
80 struct quoting_options
81 {
82   /* Basic quoting style.  */
83   enum quoting_style style;
84
85   /* Quote the characters indicated by this bit vector even if the
86      quoting style would not normally require them to be quoted.  */
87   int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
88 };
89
90 /* Names of quoting styles.  */
91 char const *const quoting_style_args[] =
92 {
93   "literal",
94   "shell",
95   "shell-always",
96   "c",
97   "escape",
98   "locale",
99   "clocale",
100   0
101 };
102
103 /* Correspondences to quoting style names.  */
104 enum quoting_style const quoting_style_vals[] =
105 {
106   literal_quoting_style,
107   shell_quoting_style,
108   shell_always_quoting_style,
109   c_quoting_style,
110   escape_quoting_style,
111   locale_quoting_style,
112   clocale_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   int e = errno;
125   struct quoting_options *p = xmalloc (sizeof *p);
126   *p = *(o ? o : &default_quoting_options);
127   errno = e;
128   return p;
129 }
130
131 /* Get the value of O's quoting style.  If O is null, use the default.  */
132 enum quoting_style
133 get_quoting_style (struct quoting_options *o)
134 {
135   return (o ? o : &default_quoting_options)->style;
136 }
137
138 /* In O (or in the default if O is null),
139    set the value of the quoting style to S.  */
140 void
141 set_quoting_style (struct quoting_options *o, enum quoting_style s)
142 {
143   (o ? o : &default_quoting_options)->style = s;
144 }
145
146 /* In O (or in the default if O is null),
147    set the value of the quoting options for character C to I.
148    Return the old value.  Currently, the only values defined for I are
149    0 (the default) and 1 (which means to quote the character even if
150    it would not otherwise be quoted).  */
151 int
152 set_char_quoting (struct quoting_options *o, char c, int i)
153 {
154   unsigned char uc = c;
155   int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
156   int shift = uc % INT_BITS;
157   int r = (*p >> shift) & 1;
158   *p ^= ((i & 1) ^ r) << shift;
159   return r;
160 }
161
162 /* MSGID approximates a quotation mark.  Return its translation if it
163    has one; otherwise, return either it or "\"", depending on S.  */
164 static char const *
165 gettext_quote (char const *msgid, enum quoting_style s)
166 {
167   char const *translation = _(msgid);
168   if (translation == msgid && s == clocale_quoting_style)
169     translation = "\"";
170   return translation;
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 SIZE_MAX, 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   bool backslash_escapes = false;
197   bool unibyte_locale = MB_CUR_MAX == 1;
198
199 #define STORE(c) \
200     do \
201       { \
202         if (len < buffersize) \
203           buffer[len] = (c); \
204         len++; \
205       } \
206     while (0)
207
208   switch (quoting_style)
209     {
210     case c_quoting_style:
211       STORE ('"');
212       backslash_escapes = true;
213       quote_string = "\"";
214       quote_string_len = 1;
215       break;
216
217     case escape_quoting_style:
218       backslash_escapes = true;
219       break;
220
221     case locale_quoting_style:
222     case clocale_quoting_style:
223       {
224         /* Get translations for open and closing quotation marks.
225
226            The message catalog should translate "`" to a left
227            quotation mark suitable for the locale, and similarly for
228            "'".  If the catalog has no translation,
229            locale_quoting_style quotes `like this', and
230            clocale_quoting_style quotes "like this".
231
232            For example, an American English Unicode locale should
233            translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
234            should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
235            MARK).  A British English Unicode locale should instead
236            translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and
237            U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.  */
238
239         char const *left = gettext_quote (N_("`"), quoting_style);
240         char const *right = gettext_quote (N_("'"), quoting_style);
241         for (quote_string = left; *quote_string; quote_string++)
242           STORE (*quote_string);
243         backslash_escapes = true;
244         quote_string = right;
245         quote_string_len = strlen (quote_string);
246       }
247       break;
248
249     case shell_always_quoting_style:
250       STORE ('\'');
251       quote_string = "'";
252       quote_string_len = 1;
253       break;
254
255     default:
256       break;
257     }
258
259   for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
260     {
261       unsigned char c;
262       unsigned char esc;
263
264       if (backslash_escapes
265           && quote_string_len
266           && i + quote_string_len <= argsize
267           && memcmp (arg + i, quote_string, quote_string_len) == 0)
268         STORE ('\\');
269
270       c = arg[i];
271       switch (c)
272         {
273         case '\0':
274           if (backslash_escapes)
275             {
276               STORE ('\\');
277               STORE ('0');
278               STORE ('0');
279               c = '0';
280             }
281           break;
282
283         case '?':
284           switch (quoting_style)
285             {
286             case shell_quoting_style:
287               goto use_shell_always_quoting_style;
288
289             case c_quoting_style:
290               if (i + 2 < argsize && arg[i + 1] == '?')
291                 switch (arg[i + 2])
292                   {
293                   case '!': case '\'':
294                   case '(': case ')': case '-': case '/':
295                   case '<': case '=': case '>':
296                     /* Escape the second '?' in what would otherwise be
297                        a trigraph.  */
298                     c = arg[i + 2];
299                     i += 2;
300                     STORE ('?');
301                     STORE ('\\');
302                     STORE ('?');
303                     break;
304                   }
305               break;
306
307             default:
308               break;
309             }
310           break;
311
312         case '\a': esc = 'a'; goto c_escape;
313         case '\b': esc = 'b'; goto c_escape;
314         case '\f': esc = 'f'; goto c_escape;
315         case '\n': esc = 'n'; goto c_and_shell_escape;
316         case '\r': esc = 'r'; goto c_and_shell_escape;
317         case '\t': esc = 't'; goto c_and_shell_escape;
318         case '\v': esc = 'v'; goto c_escape;
319         case '\\': esc = c; goto c_and_shell_escape;
320
321         c_and_shell_escape:
322           if (quoting_style == shell_quoting_style)
323             goto use_shell_always_quoting_style;
324         c_escape:
325           if (backslash_escapes)
326             {
327               c = esc;
328               goto store_escape;
329             }
330           break;
331
332         case '{': case '}': /* sometimes special if isolated */
333           if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
334             break;
335           /* Fall through.  */
336         case '#': case '~':
337           if (i != 0)
338             break;
339           /* Fall through.  */
340         case ' ':
341         case '!': /* special in bash */
342         case '"': case '$': case '&':
343         case '(': case ')': case '*': case ';':
344         case '<':
345         case '=': /* sometimes special in 0th or (with "set -k") later args */
346         case '>': case '[':
347         case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
348         case '`': case '|':
349           /* A shell special character.  In theory, '$' and '`' could
350              be the first bytes of multibyte characters, which means
351              we should check them with mbrtowc, but in practice this
352              doesn't happen so it's not worth worrying about.  */
353           if (quoting_style == shell_quoting_style)
354             goto use_shell_always_quoting_style;
355           break;
356
357         case '\'':
358           switch (quoting_style)
359             {
360             case shell_quoting_style:
361               goto use_shell_always_quoting_style;
362
363             case shell_always_quoting_style:
364               STORE ('\'');
365               STORE ('\\');
366               STORE ('\'');
367               break;
368
369             default:
370               break;
371             }
372           break;
373
374         case '%': case '+': case ',': case '-': case '.': case '/':
375         case '0': case '1': case '2': case '3': case '4': case '5':
376         case '6': case '7': case '8': case '9': case ':':
377         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
378         case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
379         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
380         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
381         case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
382         case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
383         case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
384         case 'o': case 'p': case 'q': case 'r': case 's': case 't':
385         case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
386           /* These characters don't cause problems, no matter what the
387              quoting style is.  They cannot start multibyte sequences.  */
388           break;
389
390         default:
391           /* If we have a multibyte sequence, copy it until we reach
392              its end, find an error, or come back to the initial shift
393              state.  For C-like styles, if the sequence has
394              unprintable characters, escape the whole sequence, since
395              we can't easily escape single characters within it.  */
396           {
397             /* Length of multibyte sequence found so far.  */
398             size_t m;
399
400             bool printable;
401
402             if (unibyte_locale)
403               {
404                 m = 1;
405                 printable = isprint (c) != 0;
406               }
407             else
408               {
409                 mbstate_t mbstate;
410                 memset (&mbstate, 0, sizeof mbstate);
411
412                 m = 0;
413                 printable = true;
414                 if (argsize == SIZE_MAX)
415                   argsize = strlen (arg);
416
417                 do
418                   {
419                     wchar_t w;
420                     size_t bytes = mbrtowc (&w, &arg[i + m],
421                                             argsize - (i + m), &mbstate);
422                     if (bytes == 0)
423                       break;
424                     else if (bytes == (size_t) -1)
425                       {
426                         printable = false;
427                         break;
428                       }
429                     else if (bytes == (size_t) -2)
430                       {
431                         printable = false;
432                         while (i + m < argsize && arg[i + m])
433                           m++;
434                         break;
435                       }
436                     else
437                       {
438                         /* Work around a bug with older shells that "see" a '\'
439                            that is really the 2nd byte of a multibyte character.
440                            In practice the problem is limited to ASCII
441                            chars >= '@' that are shell special chars.  */
442                         if ('[' == 0x5b && quoting_style == shell_quoting_style)
443                           {
444                             size_t j;
445                             for (j = 1; j < bytes; j++)
446                               switch (arg[i + m + j])
447                                 {
448                                 case '[': case '\\': case '^':
449                                 case '`': case '|':
450                                   goto use_shell_always_quoting_style;
451                                 }
452                           }
453
454                         if (! iswprint (w))
455                           printable = false;
456                         m += bytes;
457                       }
458                   }
459                 while (! mbsinit (&mbstate));
460               }
461
462             if (1 < m || (backslash_escapes && ! printable))
463               {
464                 /* Output a multibyte sequence, or an escaped
465                    unprintable unibyte character.  */
466                 size_t ilim = i + m;
467
468                 for (;;)
469                   {
470                     if (backslash_escapes && ! printable)
471                       {
472                         STORE ('\\');
473                         STORE ('0' + (c >> 6));
474                         STORE ('0' + ((c >> 3) & 7));
475                         c = '0' + (c & 7);
476                       }
477                     if (ilim <= i + 1)
478                       break;
479                     STORE (c);
480                     c = arg[++i];
481                   }
482
483                 goto store_c;
484               }
485           }
486         }
487
488       if (! (backslash_escapes
489              && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
490         goto store_c;
491
492     store_escape:
493       STORE ('\\');
494
495     store_c:
496       STORE (c);
497     }
498
499   if (i == 0 && quoting_style == shell_quoting_style)
500     goto use_shell_always_quoting_style;
501
502   if (quote_string)
503     for (; *quote_string; quote_string++)
504       STORE (*quote_string);
505
506   if (len < buffersize)
507     buffer[len] = '\0';
508   return len;
509
510  use_shell_always_quoting_style:
511   return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
512                                    shell_always_quoting_style, o);
513 }
514
515 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
516    argument ARG (of size ARGSIZE), using O to control quoting.
517    If O is null, use the default.
518    Terminate the output with a null character, and return the written
519    size of the output, not counting the terminating null.
520    If BUFFERSIZE is too small to store the output string, return the
521    value that would have been returned had BUFFERSIZE been large enough.
522    If ARGSIZE is SIZE_MAX, use the string length of the argument for
523    ARGSIZE.  */
524 size_t
525 quotearg_buffer (char *buffer, size_t buffersize,
526                  char const *arg, size_t argsize,
527                  struct quoting_options const *o)
528 {
529   struct quoting_options const *p = o ? o : &default_quoting_options;
530   int e = errno;
531   size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
532                                        p->style, p);
533   errno = e;
534   return r;
535 }
536
537 /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
538    allocated storage containing the quoted string.  */
539 char *
540 quotearg_alloc (char const *arg, size_t argsize,
541                 struct quoting_options const *o)
542 {
543   int e = errno;
544   size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1;
545   char *buf = xmalloc (bufsize);
546   quotearg_buffer (buf, bufsize, arg, argsize, o);
547   errno = e;
548   return buf;
549 }
550
551 /* Use storage slot N to return a quoted version of argument ARG.
552    ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
553    null-terminated string.
554    OPTIONS specifies the quoting options.
555    The returned value points to static storage that can be
556    reused by the next call to this function with the same value of N.
557    N must be nonnegative.  N is deliberately declared with type "int"
558    to allow for future extensions (using negative values).  */
559 static char *
560 quotearg_n_options (int n, char const *arg, size_t argsize,
561                     struct quoting_options const *options)
562 {
563   int e = errno;
564
565   /* Preallocate a slot 0 buffer, so that the caller can always quote
566      one small component of a "memory exhausted" message in slot 0.  */
567   static char slot0[256];
568   static unsigned int nslots = 1;
569   unsigned int n0 = n;
570   struct slotvec
571     {
572       size_t size;
573       char *val;
574     };
575   static struct slotvec slotvec0 = {sizeof slot0, slot0};
576   static struct slotvec *slotvec = &slotvec0;
577
578   if (n < 0)
579     abort ();
580
581   if (nslots <= n0)
582     {
583       unsigned int n1 = n0 + 1;
584
585       if (xalloc_oversized (n1, sizeof *slotvec))
586         xalloc_die ();
587
588       if (slotvec == &slotvec0)
589         {
590           slotvec = xmalloc (sizeof *slotvec);
591           *slotvec = slotvec0;
592         }
593       slotvec = xrealloc (slotvec, n1 * sizeof *slotvec);
594       memset (slotvec + nslots, 0, (n1 - nslots) * sizeof *slotvec);
595       nslots = n1;
596     }
597
598   {
599     size_t size = slotvec[n].size;
600     char *val = slotvec[n].val;
601     size_t qsize = quotearg_buffer (val, size, arg, argsize, options);
602
603     if (size <= qsize)
604       {
605         slotvec[n].size = size = qsize + 1;
606         if (val != slot0)
607           free (val);
608         slotvec[n].val = val = xmalloc (size);
609         quotearg_buffer (val, size, arg, argsize, options);
610       }
611
612     errno = e;
613     return val;
614   }
615 }
616
617 char *
618 quotearg_n (int n, char const *arg)
619 {
620   return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
621 }
622
623 char *
624 quotearg (char const *arg)
625 {
626   return quotearg_n (0, arg);
627 }
628
629 /* Return quoting options for STYLE, with no extra quoting.  */
630 static struct quoting_options
631 quoting_options_from_style (enum quoting_style style)
632 {
633   struct quoting_options o;
634   o.style = style;
635   memset (o.quote_these_too, 0, sizeof o.quote_these_too);
636   return o;
637 }
638
639 char *
640 quotearg_n_style (int n, enum quoting_style s, char const *arg)
641 {
642   struct quoting_options const o = quoting_options_from_style (s);
643   return quotearg_n_options (n, arg, SIZE_MAX, &o);
644 }
645
646 char *
647 quotearg_n_style_mem (int n, enum quoting_style s,
648                       char const *arg, size_t argsize)
649 {
650   struct quoting_options const o = quoting_options_from_style (s);
651   return quotearg_n_options (n, arg, argsize, &o);
652 }
653
654 char *
655 quotearg_style (enum quoting_style s, char const *arg)
656 {
657   return quotearg_n_style (0, s, arg);
658 }
659
660 char *
661 quotearg_char (char const *arg, char ch)
662 {
663   struct quoting_options options;
664   options = default_quoting_options;
665   set_char_quoting (&options, ch, 1);
666   return quotearg_n_options (0, arg, SIZE_MAX, &options);
667 }
668
669 char *
670 quotearg_colon (char const *arg)
671 {
672   return quotearg_char (arg, ':');
673 }