~ubuntu-branches/ubuntu/precise/gzip/precise

« back to all changes in this revision

Viewing changes to lib/quotearg.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-10-19 11:42:42 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20111019114242-d8wiiu8kbvdtgmgj
Tags: 1.4-1ubuntu1
* Merge with Debian testing.  Remaining Ubuntu changes:
  - debian/{control,rules}: Remove the Win32 build and mingw64
    build-dependency, since mingw is in universe, and will remain so for
    the forseeable future.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* quotearg.c - quote arguments for output
 
2
 
 
3
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
 
4
   2009, 2010 Free Software 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 3 of the License, or
 
9
   (at your option) 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, see <http://www.gnu.org/licenses/>.  */
 
18
 
 
19
/* Written by Paul Eggert <eggert@twinsun.com> */
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#include "quotearg.h"
 
24
 
 
25
#include "xalloc.h"
 
26
 
 
27
#include <ctype.h>
 
28
#include <errno.h>
 
29
#include <limits.h>
 
30
#include <stdbool.h>
 
31
#include <stdlib.h>
 
32
#include <string.h>
 
33
#include <wchar.h>
 
34
#include <wctype.h>
 
35
 
 
36
#include "gettext.h"
 
37
#define _(msgid) gettext (msgid)
 
38
#define N_(msgid) msgid
 
39
 
 
40
#ifndef SIZE_MAX
 
41
# define SIZE_MAX ((size_t) -1)
 
42
#endif
 
43
 
 
44
#define INT_BITS (sizeof (int) * CHAR_BIT)
 
45
 
 
46
struct quoting_options
 
47
{
 
48
  /* Basic quoting style.  */
 
49
  enum quoting_style style;
 
50
 
 
51
  /* Additional flags.  Bitwise combination of enum quoting_flags.  */
 
52
  int flags;
 
53
 
 
54
  /* Quote the characters indicated by this bit vector even if the
 
55
     quoting style would not normally require them to be quoted.  */
 
56
  unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
 
57
 
 
58
  /* The left quote for custom_quoting_style.  */
 
59
  char const *left_quote;
 
60
 
 
61
  /* The right quote for custom_quoting_style.  */
 
62
  char const *right_quote;
 
63
};
 
64
 
 
65
/* Names of quoting styles.  */
 
66
char const *const quoting_style_args[] =
 
67
{
 
68
  "literal",
 
69
  "shell",
 
70
  "shell-always",
 
71
  "c",
 
72
  "c-maybe",
 
73
  "escape",
 
74
  "locale",
 
75
  "clocale",
 
76
  0
 
77
};
 
78
 
 
79
/* Correspondences to quoting style names.  */
 
80
enum quoting_style const quoting_style_vals[] =
 
81
{
 
82
  literal_quoting_style,
 
83
  shell_quoting_style,
 
84
  shell_always_quoting_style,
 
85
  c_quoting_style,
 
86
  c_maybe_quoting_style,
 
87
  escape_quoting_style,
 
88
  locale_quoting_style,
 
89
  clocale_quoting_style
 
90
};
 
91
 
 
92
/* The default quoting options.  */
 
93
static struct quoting_options default_quoting_options;
 
94
 
 
95
/* Allocate a new set of quoting options, with contents initially identical
 
96
   to O if O is not null, or to the default if O is null.
 
97
   It is the caller's responsibility to free the result.  */
 
98
struct quoting_options *
 
99
clone_quoting_options (struct quoting_options *o)
 
100
{
 
101
  int e = errno;
 
102
  struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
 
103
                                       sizeof *o);
 
104
  errno = e;
 
105
  return p;
 
106
}
 
107
 
 
108
/* Get the value of O's quoting style.  If O is null, use the default.  */
 
109
enum quoting_style
 
110
get_quoting_style (struct quoting_options *o)
 
111
{
 
112
  return (o ? o : &default_quoting_options)->style;
 
113
}
 
114
 
 
115
/* In O (or in the default if O is null),
 
116
   set the value of the quoting style to S.  */
 
117
void
 
118
set_quoting_style (struct quoting_options *o, enum quoting_style s)
 
119
{
 
120
  (o ? o : &default_quoting_options)->style = s;
 
121
}
 
122
 
 
123
/* In O (or in the default if O is null),
 
124
   set the value of the quoting options for character C to I.
 
125
   Return the old value.  Currently, the only values defined for I are
 
126
   0 (the default) and 1 (which means to quote the character even if
 
127
   it would not otherwise be quoted).  */
 
128
int
 
129
set_char_quoting (struct quoting_options *o, char c, int i)
 
130
{
 
131
  unsigned char uc = c;
 
132
  unsigned int *p =
 
133
    (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
 
134
  int shift = uc % INT_BITS;
 
135
  int r = (*p >> shift) & 1;
 
136
  *p ^= ((i & 1) ^ r) << shift;
 
137
  return r;
 
138
}
 
139
 
 
140
/* In O (or in the default if O is null),
 
141
   set the value of the quoting options flag to I, which can be a
 
142
   bitwise combination of enum quoting_flags, or 0 for default
 
143
   behavior.  Return the old value.  */
 
144
int
 
145
set_quoting_flags (struct quoting_options *o, int i)
 
146
{
 
147
  int r;
 
148
  if (!o)
 
149
    o = &default_quoting_options;
 
150
  r = o->flags;
 
151
  o->flags = i;
 
152
  return r;
 
153
}
 
154
 
 
155
void
 
156
set_custom_quoting (struct quoting_options *o,
 
157
                    char const *left_quote, char const *right_quote)
 
158
{
 
159
  if (!o)
 
160
    o = &default_quoting_options;
 
161
  o->style = custom_quoting_style;
 
162
  if (!left_quote || !right_quote)
 
163
    abort ();
 
164
  o->left_quote = left_quote;
 
165
  o->right_quote = right_quote;
 
166
}
 
167
 
 
168
/* Return quoting options for STYLE, with no extra quoting.  */
 
169
static struct quoting_options
 
170
quoting_options_from_style (enum quoting_style style)
 
171
{
 
172
  struct quoting_options o;
 
173
  o.style = style;
 
174
  o.flags = 0;
 
175
  memset (o.quote_these_too, 0, sizeof o.quote_these_too);
 
176
  return o;
 
177
}
 
178
 
 
179
/* MSGID approximates a quotation mark.  Return its translation if it
 
180
   has one; otherwise, return either it or "\"", depending on S.  */
 
181
static char const *
 
182
gettext_quote (char const *msgid, enum quoting_style s)
 
183
{
 
184
  char const *translation = _(msgid);
 
185
  if (translation == msgid && s == clocale_quoting_style)
 
186
    translation = "\"";
 
187
  return translation;
 
188
}
 
189
 
 
190
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
 
191
   argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
 
192
   QUOTE_THESE_TOO to control quoting.
 
193
   Terminate the output with a null character, and return the written
 
194
   size of the output, not counting the terminating null.
 
195
   If BUFFERSIZE is too small to store the output string, return the
 
196
   value that would have been returned had BUFFERSIZE been large enough.
 
197
   If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
 
198
 
 
199
   This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
 
200
   ARGSIZE, O), except it breaks O into its component pieces and is
 
201
   not careful about errno.  */
 
202
 
 
203
static size_t
 
204
quotearg_buffer_restyled (char *buffer, size_t buffersize,
 
205
                          char const *arg, size_t argsize,
 
206
                          enum quoting_style quoting_style, int flags,
 
207
                          unsigned int const *quote_these_too,
 
208
                          char const *left_quote,
 
209
                          char const *right_quote)
 
210
{
 
211
  size_t i;
 
212
  size_t len = 0;
 
213
  char const *quote_string = 0;
 
214
  size_t quote_string_len = 0;
 
215
  bool backslash_escapes = false;
 
216
  bool unibyte_locale = MB_CUR_MAX == 1;
 
217
  bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
 
218
 
 
219
#define STORE(c) \
 
220
    do \
 
221
      { \
 
222
        if (len < buffersize) \
 
223
          buffer[len] = (c); \
 
224
        len++; \
 
225
      } \
 
226
    while (0)
 
227
 
 
228
  switch (quoting_style)
 
229
    {
 
230
    case c_maybe_quoting_style:
 
231
      quoting_style = c_quoting_style;
 
232
      elide_outer_quotes = true;
 
233
      /* Fall through.  */
 
234
    case c_quoting_style:
 
235
      if (!elide_outer_quotes)
 
236
        STORE ('"');
 
237
      backslash_escapes = true;
 
238
      quote_string = "\"";
 
239
      quote_string_len = 1;
 
240
      break;
 
241
 
 
242
    case escape_quoting_style:
 
243
      backslash_escapes = true;
 
244
      elide_outer_quotes = false;
 
245
      break;
 
246
 
 
247
    case locale_quoting_style:
 
248
    case clocale_quoting_style:
 
249
    case custom_quoting_style:
 
250
      {
 
251
        if (quoting_style != custom_quoting_style)
 
252
          {
 
253
            /* TRANSLATORS:
 
254
               Get translations for open and closing quotation marks.
 
255
 
 
256
               The message catalog should translate "`" to a left
 
257
               quotation mark suitable for the locale, and similarly for
 
258
               "'".  If the catalog has no translation,
 
259
               locale_quoting_style quotes `like this', and
 
260
               clocale_quoting_style quotes "like this".
 
261
 
 
262
               For example, an American English Unicode locale should
 
263
               translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and
 
264
               should translate "'" to U+201D (RIGHT DOUBLE QUOTATION
 
265
               MARK).  A British English Unicode locale should instead
 
266
               translate these to U+2018 (LEFT SINGLE QUOTATION MARK)
 
267
               and U+2019 (RIGHT SINGLE QUOTATION MARK), respectively.
 
268
 
 
269
               If you don't know what to put here, please see
 
270
               <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
 
271
               and use glyphs suitable for your language.  */
 
272
            left_quote = gettext_quote (N_("`"), quoting_style);
 
273
            right_quote = gettext_quote (N_("'"), quoting_style);
 
274
          }
 
275
        if (!elide_outer_quotes)
 
276
          for (quote_string = left_quote; *quote_string; quote_string++)
 
277
            STORE (*quote_string);
 
278
        backslash_escapes = true;
 
279
        quote_string = right_quote;
 
280
        quote_string_len = strlen (quote_string);
 
281
      }
 
282
      break;
 
283
 
 
284
    case shell_quoting_style:
 
285
      quoting_style = shell_always_quoting_style;
 
286
      elide_outer_quotes = true;
 
287
      /* Fall through.  */
 
288
    case shell_always_quoting_style:
 
289
      if (!elide_outer_quotes)
 
290
        STORE ('\'');
 
291
      quote_string = "'";
 
292
      quote_string_len = 1;
 
293
      break;
 
294
 
 
295
    case literal_quoting_style:
 
296
      elide_outer_quotes = false;
 
297
      break;
 
298
 
 
299
    default:
 
300
      abort ();
 
301
    }
 
302
 
 
303
  for (i = 0;  ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize);  i++)
 
304
    {
 
305
      unsigned char c;
 
306
      unsigned char esc;
 
307
      bool is_right_quote = false;
 
308
 
 
309
      if (backslash_escapes
 
310
          && quote_string_len
 
311
          && i + quote_string_len <= argsize
 
312
          && memcmp (arg + i, quote_string, quote_string_len) == 0)
 
313
        {
 
314
          if (elide_outer_quotes)
 
315
            goto force_outer_quoting_style;
 
316
          is_right_quote = true;
 
317
        }
 
318
 
 
319
      c = arg[i];
 
320
      switch (c)
 
321
        {
 
322
        case '\0':
 
323
          if (backslash_escapes)
 
324
            {
 
325
              if (elide_outer_quotes)
 
326
                goto force_outer_quoting_style;
 
327
              STORE ('\\');
 
328
              /* If quote_string were to begin with digits, we'd need to
 
329
                 test for the end of the arg as well.  However, it's
 
330
                 hard to imagine any locale that would use digits in
 
331
                 quotes, and set_custom_quoting is documented not to
 
332
                 accept them.  */
 
333
              if (i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
 
334
                {
 
335
                  STORE ('0');
 
336
                  STORE ('0');
 
337
                }
 
338
              c = '0';
 
339
              /* We don't have to worry that this last '0' will be
 
340
                 backslash-escaped because, again, quote_string should
 
341
                 not start with it and because quote_these_too is
 
342
                 documented as not accepting it.  */
 
343
            }
 
344
          else if (flags & QA_ELIDE_NULL_BYTES)
 
345
            continue;
 
346
          break;
 
347
 
 
348
        case '?':
 
349
          switch (quoting_style)
 
350
            {
 
351
            case shell_always_quoting_style:
 
352
              if (elide_outer_quotes)
 
353
                goto force_outer_quoting_style;
 
354
              break;
 
355
 
 
356
            case c_quoting_style:
 
357
              if ((flags & QA_SPLIT_TRIGRAPHS)
 
358
                  && i + 2 < argsize && arg[i + 1] == '?')
 
359
                switch (arg[i + 2])
 
360
                  {
 
361
                  case '!': case '\'':
 
362
                  case '(': case ')': case '-': case '/':
 
363
                  case '<': case '=': case '>':
 
364
                    /* Escape the second '?' in what would otherwise be
 
365
                       a trigraph.  */
 
366
                    if (elide_outer_quotes)
 
367
                      goto force_outer_quoting_style;
 
368
                    c = arg[i + 2];
 
369
                    i += 2;
 
370
                    STORE ('?');
 
371
                    STORE ('"');
 
372
                    STORE ('"');
 
373
                    STORE ('?');
 
374
                    break;
 
375
 
 
376
                  default:
 
377
                    break;
 
378
                  }
 
379
              break;
 
380
 
 
381
            default:
 
382
              break;
 
383
            }
 
384
          break;
 
385
 
 
386
        case '\a': esc = 'a'; goto c_escape;
 
387
        case '\b': esc = 'b'; goto c_escape;
 
388
        case '\f': esc = 'f'; goto c_escape;
 
389
        case '\n': esc = 'n'; goto c_and_shell_escape;
 
390
        case '\r': esc = 'r'; goto c_and_shell_escape;
 
391
        case '\t': esc = 't'; goto c_and_shell_escape;
 
392
        case '\v': esc = 'v'; goto c_escape;
 
393
        case '\\': esc = c;
 
394
          /* No need to escape the escape if we are trying to elide
 
395
             outer quotes and nothing else is problematic.  */
 
396
          if (backslash_escapes && elide_outer_quotes && quote_string_len)
 
397
            goto store_c;
 
398
 
 
399
        c_and_shell_escape:
 
400
          if (quoting_style == shell_always_quoting_style
 
401
              && elide_outer_quotes)
 
402
            goto force_outer_quoting_style;
 
403
          /* Fall through.  */
 
404
        c_escape:
 
405
          if (backslash_escapes)
 
406
            {
 
407
              c = esc;
 
408
              goto store_escape;
 
409
            }
 
410
          break;
 
411
 
 
412
        case '{': case '}': /* sometimes special if isolated */
 
413
          if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
 
414
            break;
 
415
          /* Fall through.  */
 
416
        case '#': case '~':
 
417
          if (i != 0)
 
418
            break;
 
419
          /* Fall through.  */
 
420
        case ' ':
 
421
        case '!': /* special in bash */
 
422
        case '"': case '$': case '&':
 
423
        case '(': case ')': case '*': case ';':
 
424
        case '<':
 
425
        case '=': /* sometimes special in 0th or (with "set -k") later args */
 
426
        case '>': case '[':
 
427
        case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
 
428
        case '`': case '|':
 
429
          /* A shell special character.  In theory, '$' and '`' could
 
430
             be the first bytes of multibyte characters, which means
 
431
             we should check them with mbrtowc, but in practice this
 
432
             doesn't happen so it's not worth worrying about.  */
 
433
          if (quoting_style == shell_always_quoting_style
 
434
              && elide_outer_quotes)
 
435
            goto force_outer_quoting_style;
 
436
          break;
 
437
 
 
438
        case '\'':
 
439
          if (quoting_style == shell_always_quoting_style)
 
440
            {
 
441
              if (elide_outer_quotes)
 
442
                goto force_outer_quoting_style;
 
443
              STORE ('\'');
 
444
              STORE ('\\');
 
445
              STORE ('\'');
 
446
            }
 
447
          break;
 
448
 
 
449
        case '%': case '+': case ',': case '-': case '.': case '/':
 
450
        case '0': case '1': case '2': case '3': case '4': case '5':
 
451
        case '6': case '7': case '8': case '9': case ':':
 
452
        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 
453
        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
 
454
        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 
455
        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 
456
        case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
 
457
        case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
 
458
        case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
 
459
        case 'o': case 'p': case 'q': case 'r': case 's': case 't':
 
460
        case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
 
461
          /* These characters don't cause problems, no matter what the
 
462
             quoting style is.  They cannot start multibyte sequences.
 
463
             A digit or a special letter would cause trouble if it
 
464
             appeared at the beginning of quote_string because we'd then
 
465
             escape by prepending a backslash.  However, it's hard to
 
466
             imagine any locale that would use digits or letters as
 
467
             quotes, and set_custom_quoting is documented not to accept
 
468
             them.  Also, a digit or a special letter would cause
 
469
             trouble if it appeared in quote_these_too, but that's also
 
470
             documented as not accepting them.  */
 
471
          break;
 
472
 
 
473
        default:
 
474
          /* If we have a multibyte sequence, copy it until we reach
 
475
             its end, find an error, or come back to the initial shift
 
476
             state.  For C-like styles, if the sequence has
 
477
             unprintable characters, escape the whole sequence, since
 
478
             we can't easily escape single characters within it.  */
 
479
          {
 
480
            /* Length of multibyte sequence found so far.  */
 
481
            size_t m;
 
482
 
 
483
            bool printable;
 
484
 
 
485
            if (unibyte_locale)
 
486
              {
 
487
                m = 1;
 
488
                printable = isprint (c) != 0;
 
489
              }
 
490
            else
 
491
              {
 
492
                mbstate_t mbstate;
 
493
                memset (&mbstate, 0, sizeof mbstate);
 
494
 
 
495
                m = 0;
 
496
                printable = true;
 
497
                if (argsize == SIZE_MAX)
 
498
                  argsize = strlen (arg);
 
499
 
 
500
                do
 
501
                  {
 
502
                    wchar_t w;
 
503
                    size_t bytes = mbrtowc (&w, &arg[i + m],
 
504
                                            argsize - (i + m), &mbstate);
 
505
                    if (bytes == 0)
 
506
                      break;
 
507
                    else if (bytes == (size_t) -1)
 
508
                      {
 
509
                        printable = false;
 
510
                        break;
 
511
                      }
 
512
                    else if (bytes == (size_t) -2)
 
513
                      {
 
514
                        printable = false;
 
515
                        while (i + m < argsize && arg[i + m])
 
516
                          m++;
 
517
                        break;
 
518
                      }
 
519
                    else
 
520
                      {
 
521
                        /* Work around a bug with older shells that "see" a '\'
 
522
                           that is really the 2nd byte of a multibyte character.
 
523
                           In practice the problem is limited to ASCII
 
524
                           chars >= '@' that are shell special chars.  */
 
525
                        if ('[' == 0x5b && elide_outer_quotes
 
526
                            && quoting_style == shell_always_quoting_style)
 
527
                          {
 
528
                            size_t j;
 
529
                            for (j = 1; j < bytes; j++)
 
530
                              switch (arg[i + m + j])
 
531
                                {
 
532
                                case '[': case '\\': case '^':
 
533
                                case '`': case '|':
 
534
                                  goto force_outer_quoting_style;
 
535
 
 
536
                                default:
 
537
                                  break;
 
538
                                }
 
539
                          }
 
540
 
 
541
                        if (! iswprint (w))
 
542
                          printable = false;
 
543
                        m += bytes;
 
544
                      }
 
545
                  }
 
546
                while (! mbsinit (&mbstate));
 
547
              }
 
548
 
 
549
            if (1 < m || (backslash_escapes && ! printable))
 
550
              {
 
551
                /* Output a multibyte sequence, or an escaped
 
552
                   unprintable unibyte character.  */
 
553
                size_t ilim = i + m;
 
554
 
 
555
                for (;;)
 
556
                  {
 
557
                    if (backslash_escapes && ! printable)
 
558
                      {
 
559
                        if (elide_outer_quotes)
 
560
                          goto force_outer_quoting_style;
 
561
                        STORE ('\\');
 
562
                        STORE ('0' + (c >> 6));
 
563
                        STORE ('0' + ((c >> 3) & 7));
 
564
                        c = '0' + (c & 7);
 
565
                      }
 
566
                    else if (is_right_quote)
 
567
                      {
 
568
                        STORE ('\\');
 
569
                        is_right_quote = false;
 
570
                      }
 
571
                    if (ilim <= i + 1)
 
572
                      break;
 
573
                    STORE (c);
 
574
                    c = arg[++i];
 
575
                  }
 
576
 
 
577
                goto store_c;
 
578
              }
 
579
          }
 
580
        }
 
581
 
 
582
      if (! ((backslash_escapes || elide_outer_quotes)
 
583
             && quote_these_too
 
584
             && quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
 
585
          && !is_right_quote)
 
586
        goto store_c;
 
587
 
 
588
    store_escape:
 
589
      if (elide_outer_quotes)
 
590
        goto force_outer_quoting_style;
 
591
      STORE ('\\');
 
592
 
 
593
    store_c:
 
594
      STORE (c);
 
595
    }
 
596
 
 
597
  if (len == 0 && quoting_style == shell_always_quoting_style
 
598
      && elide_outer_quotes)
 
599
    goto force_outer_quoting_style;
 
600
 
 
601
  if (quote_string && !elide_outer_quotes)
 
602
    for (; *quote_string; quote_string++)
 
603
      STORE (*quote_string);
 
604
 
 
605
  if (len < buffersize)
 
606
    buffer[len] = '\0';
 
607
  return len;
 
608
 
 
609
 force_outer_quoting_style:
 
610
  /* Don't reuse quote_these_too, since the addition of outer quotes
 
611
     sufficiently quotes the specified characters.  */
 
612
  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
 
613
                                   quoting_style,
 
614
                                   flags & ~QA_ELIDE_OUTER_QUOTES, NULL,
 
615
                                   left_quote, right_quote);
 
616
}
 
617
 
 
618
/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
 
619
   argument ARG (of size ARGSIZE), using O to control quoting.
 
620
   If O is null, use the default.
 
621
   Terminate the output with a null character, and return the written
 
622
   size of the output, not counting the terminating null.
 
623
   If BUFFERSIZE is too small to store the output string, return the
 
624
   value that would have been returned had BUFFERSIZE been large enough.
 
625
   If ARGSIZE is SIZE_MAX, use the string length of the argument for
 
626
   ARGSIZE.  */
 
627
size_t
 
628
quotearg_buffer (char *buffer, size_t buffersize,
 
629
                 char const *arg, size_t argsize,
 
630
                 struct quoting_options const *o)
 
631
{
 
632
  struct quoting_options const *p = o ? o : &default_quoting_options;
 
633
  int e = errno;
 
634
  size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
 
635
                                       p->style, p->flags, p->quote_these_too,
 
636
                                       p->left_quote, p->right_quote);
 
637
  errno = e;
 
638
  return r;
 
639
}
 
640
 
 
641
/* Equivalent to quotearg_alloc (ARG, ARGSIZE, NULL, O).  */
 
642
char *
 
643
quotearg_alloc (char const *arg, size_t argsize,
 
644
                struct quoting_options const *o)
 
645
{
 
646
  return quotearg_alloc_mem (arg, argsize, NULL, o);
 
647
}
 
648
 
 
649
/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
 
650
   allocated storage containing the quoted string, and store the
 
651
   resulting size into *SIZE, if non-NULL.  The result can contain
 
652
   embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
 
653
   NULL, and set_quoting_flags has not set the null byte elision
 
654
   flag.  */
 
655
char *
 
656
quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
 
657
                    struct quoting_options const *o)
 
658
{
 
659
  struct quoting_options const *p = o ? o : &default_quoting_options;
 
660
  int e = errno;
 
661
  /* Elide embedded null bytes if we can't return a size.  */
 
662
  int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
 
663
  size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
 
664
                                             flags, p->quote_these_too,
 
665
                                             p->left_quote,
 
666
                                             p->right_quote) + 1;
 
667
  char *buf = xcharalloc (bufsize);
 
668
  quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
 
669
                            p->quote_these_too,
 
670
                            p->left_quote, p->right_quote);
 
671
  errno = e;
 
672
  if (size)
 
673
    *size = bufsize - 1;
 
674
  return buf;
 
675
}
 
676
 
 
677
/* A storage slot with size and pointer to a value.  */
 
678
struct slotvec
 
679
{
 
680
  size_t size;
 
681
  char *val;
 
682
};
 
683
 
 
684
/* Preallocate a slot 0 buffer, so that the caller can always quote
 
685
   one small component of a "memory exhausted" message in slot 0.  */
 
686
static char slot0[256];
 
687
static unsigned int nslots = 1;
 
688
static struct slotvec slotvec0 = {sizeof slot0, slot0};
 
689
static struct slotvec *slotvec = &slotvec0;
 
690
 
 
691
void
 
692
quotearg_free (void)
 
693
{
 
694
  struct slotvec *sv = slotvec;
 
695
  unsigned int i;
 
696
  for (i = 1; i < nslots; i++)
 
697
    free (sv[i].val);
 
698
  if (sv[0].val != slot0)
 
699
    {
 
700
      free (sv[0].val);
 
701
      slotvec0.size = sizeof slot0;
 
702
      slotvec0.val = slot0;
 
703
    }
 
704
  if (sv != &slotvec0)
 
705
    {
 
706
      free (sv);
 
707
      slotvec = &slotvec0;
 
708
    }
 
709
  nslots = 1;
 
710
}
 
711
 
 
712
/* Use storage slot N to return a quoted version of argument ARG.
 
713
   ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
 
714
   null-terminated string.
 
715
   OPTIONS specifies the quoting options.
 
716
   The returned value points to static storage that can be
 
717
   reused by the next call to this function with the same value of N.
 
718
   N must be nonnegative.  N is deliberately declared with type "int"
 
719
   to allow for future extensions (using negative values).  */
 
720
static char *
 
721
quotearg_n_options (int n, char const *arg, size_t argsize,
 
722
                    struct quoting_options const *options)
 
723
{
 
724
  int e = errno;
 
725
 
 
726
  unsigned int n0 = n;
 
727
  struct slotvec *sv = slotvec;
 
728
 
 
729
  if (n < 0)
 
730
    abort ();
 
731
 
 
732
  if (nslots <= n0)
 
733
    {
 
734
      /* FIXME: technically, the type of n1 should be `unsigned int',
 
735
         but that evokes an unsuppressible warning from gcc-4.0.1 and
 
736
         older.  If gcc ever provides an option to suppress that warning,
 
737
         revert to the original type, so that the test in xalloc_oversized
 
738
         is once again performed only at compile time.  */
 
739
      size_t n1 = n0 + 1;
 
740
      bool preallocated = (sv == &slotvec0);
 
741
 
 
742
      if (xalloc_oversized (n1, sizeof *sv))
 
743
        xalloc_die ();
 
744
 
 
745
      slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv);
 
746
      if (preallocated)
 
747
        *sv = slotvec0;
 
748
      memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv);
 
749
      nslots = n1;
 
750
    }
 
751
 
 
752
  {
 
753
    size_t size = sv[n].size;
 
754
    char *val = sv[n].val;
 
755
    /* Elide embedded null bytes since we don't return a size.  */
 
756
    int flags = options->flags | QA_ELIDE_NULL_BYTES;
 
757
    size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
 
758
                                             options->style, flags,
 
759
                                             options->quote_these_too,
 
760
                                             options->left_quote,
 
761
                                             options->right_quote);
 
762
 
 
763
    if (size <= qsize)
 
764
      {
 
765
        sv[n].size = size = qsize + 1;
 
766
        if (val != slot0)
 
767
          free (val);
 
768
        sv[n].val = val = xcharalloc (size);
 
769
        quotearg_buffer_restyled (val, size, arg, argsize, options->style,
 
770
                                  flags, options->quote_these_too,
 
771
                                  options->left_quote,
 
772
                                  options->right_quote);
 
773
      }
 
774
 
 
775
    errno = e;
 
776
    return val;
 
777
  }
 
778
}
 
779
 
 
780
char *
 
781
quotearg_n (int n, char const *arg)
 
782
{
 
783
  return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options);
 
784
}
 
785
 
 
786
char *
 
787
quotearg_n_mem (int n, char const *arg, size_t argsize)
 
788
{
 
789
  return quotearg_n_options (n, arg, argsize, &default_quoting_options);
 
790
}
 
791
 
 
792
char *
 
793
quotearg (char const *arg)
 
794
{
 
795
  return quotearg_n (0, arg);
 
796
}
 
797
 
 
798
char *
 
799
quotearg_mem (char const *arg, size_t argsize)
 
800
{
 
801
  return quotearg_n_mem (0, arg, argsize);
 
802
}
 
803
 
 
804
char *
 
805
quotearg_n_style (int n, enum quoting_style s, char const *arg)
 
806
{
 
807
  struct quoting_options const o = quoting_options_from_style (s);
 
808
  return quotearg_n_options (n, arg, SIZE_MAX, &o);
 
809
}
 
810
 
 
811
char *
 
812
quotearg_n_style_mem (int n, enum quoting_style s,
 
813
                      char const *arg, size_t argsize)
 
814
{
 
815
  struct quoting_options const o = quoting_options_from_style (s);
 
816
  return quotearg_n_options (n, arg, argsize, &o);
 
817
}
 
818
 
 
819
char *
 
820
quotearg_style (enum quoting_style s, char const *arg)
 
821
{
 
822
  return quotearg_n_style (0, s, arg);
 
823
}
 
824
 
 
825
char *
 
826
quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
 
827
{
 
828
  return quotearg_n_style_mem (0, s, arg, argsize);
 
829
}
 
830
 
 
831
char *
 
832
quotearg_char_mem (char const *arg, size_t argsize, char ch)
 
833
{
 
834
  struct quoting_options options;
 
835
  options = default_quoting_options;
 
836
  set_char_quoting (&options, ch, 1);
 
837
  return quotearg_n_options (0, arg, argsize, &options);
 
838
}
 
839
 
 
840
char *
 
841
quotearg_char (char const *arg, char ch)
 
842
{
 
843
  return quotearg_char_mem (arg, SIZE_MAX, ch);
 
844
}
 
845
 
 
846
char *
 
847
quotearg_colon (char const *arg)
 
848
{
 
849
  return quotearg_char (arg, ':');
 
850
}
 
851
 
 
852
char *
 
853
quotearg_colon_mem (char const *arg, size_t argsize)
 
854
{
 
855
  return quotearg_char_mem (arg, argsize, ':');
 
856
}
 
857
 
 
858
char *
 
859
quotearg_n_custom (int n, char const *left_quote,
 
860
                   char const *right_quote, char const *arg)
 
861
{
 
862
  return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
 
863
                                SIZE_MAX);
 
864
}
 
865
 
 
866
char *
 
867
quotearg_n_custom_mem (int n, char const *left_quote,
 
868
                       char const *right_quote,
 
869
                       char const *arg, size_t argsize)
 
870
{
 
871
  struct quoting_options o = default_quoting_options;
 
872
  set_custom_quoting (&o, left_quote, right_quote);
 
873
  return quotearg_n_options (n, arg, argsize, &o);
 
874
}
 
875
 
 
876
char *
 
877
quotearg_custom (char const *left_quote, char const *right_quote,
 
878
                 char const *arg)
 
879
{
 
880
  return quotearg_n_custom (0, left_quote, right_quote, arg);
 
881
}
 
882
 
 
883
char *
 
884
quotearg_custom_mem (char const *left_quote, char const *right_quote,
 
885
                     char const *arg, size_t argsize)
 
886
{
 
887
  return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
 
888
                                argsize);
 
889
}