~brian-thomason/+junk/hello

« back to all changes in this revision

Viewing changes to gnulib/lib/quotearg.c

  • Committer: Brian Thomason
  • Date: 2012-03-06 19:40:19 UTC
  • Revision ID: brian.thomason@canonical.com-20120306194019-f1lgtgb3r7sg21ee
Initial import

Show diffs side-by-side

added added

removed removed

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