gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

quotearg.c
Go to the documentation of this file.
1 /* quotearg.c - quote arguments for output
2 
3  Copyright (C) 1998-2002, 2004-2021 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 <https://www.gnu.org/licenses/>. */
17 
18 /* Written by Paul Eggert <eggert@twinsun.com> */
19 
20 /* Without this pragma, gcc 4.7.0 20111124 mistakenly suggests that
21  the quoting_options_from_style function might be candidate for
22  attribute 'pure' */
23 #if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
24 # pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
25 #endif
26 
27 #include <config.h>
28 
29 #include "quotearg.h"
30 #include "quote.h"
31 
32 #include "attribute.h"
33 #include "minmax.h"
34 #include "xalloc.h"
35 #include "c-strcaseeq.h"
36 #include "localcharset.h"
37 
38 #include <ctype.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdbool.h>
42 #include <stdint.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <wchar.h>
46 #include <wctype.h>
47 
48 #include "gettext.h"
49 #define _(msgid) gettext (msgid)
50 #define N_(msgid) msgid
51 
52 #ifndef SIZE_MAX
53 # define SIZE_MAX ((size_t) -1)
54 #endif
55 
56 #define INT_BITS (sizeof (int) * CHAR_BIT)
57 
59 {
60  /* Basic quoting style. */
61  enum quoting_style style;
62 
63  /* Additional flags. Bitwise combination of enum quoting_flags. */
64  int flags;
65 
66  /* Quote the characters indicated by this bit vector even if the
67  quoting style would not normally require them to be quoted. */
68  unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1];
69 
70  /* The left quote for custom_quoting_style. */
71  char const *left_quote;
72 
73  /* The right quote for custom_quoting_style. */
74  char const *right_quote;
75 };
76 
77 /* Names of quoting styles. */
78 char const *const quoting_style_args[] =
79 {
80  "literal",
81  "shell",
82  "shell-always",
83  "shell-escape",
84  "shell-escape-always",
85  "c",
86  "c-maybe",
87  "escape",
88  "locale",
89  "clocale",
90  0
91 };
92 
93 /* Correspondences to quoting style names. */
94 enum quoting_style const quoting_style_vals[] =
95 {
106 };
107 
108 /* The default quoting options. */
110 
111 /* Allocate a new set of quoting options, with contents initially identical
112  to O if O is not null, or to the default if O is null.
113  It is the caller's responsibility to free the result. */
114 struct quoting_options *
116 {
117  int e = errno;
118  struct quoting_options *p = xmemdup (o ? o : &default_quoting_options,
119  sizeof *o);
120  errno = e;
121  return p;
122 }
123 
124 /* Get the value of O's quoting style. If O is null, use the default. */
125 enum quoting_style
126 get_quoting_style (struct quoting_options const *o)
127 {
128  return (o ? o : &default_quoting_options)->style;
129 }
130 
131 /* In O (or in the default if O is null),
132  set the value of the quoting style to S. */
133 void
135 {
136  (o ? o : &default_quoting_options)->style = s;
137 }
138 
139 /* In O (or in the default if O is null),
140  set the value of the quoting options for character C to I.
141  Return the old value. Currently, the only values defined for I are
142  0 (the default) and 1 (which means to quote the character even if
143  it would not otherwise be quoted). */
144 int
145 set_char_quoting (struct quoting_options *o, char c, int i)
146 {
147  unsigned char uc = c;
148  unsigned int *p =
150  int shift = uc % INT_BITS;
151  int r = (*p >> shift) & 1;
152  *p ^= ((i & 1) ^ r) << shift;
153  return r;
154 }
155 
156 /* In O (or in the default if O is null),
157  set the value of the quoting options flag to I, which can be a
158  bitwise combination of enum quoting_flags, or 0 for default
159  behavior. Return the old value. */
160 int
162 {
163  int r;
164  if (!o)
166  r = o->flags;
167  o->flags = i;
168  return r;
169 }
170 
171 void
173  char const *left_quote, char const *right_quote)
174 {
175  if (!o)
178  if (!left_quote || !right_quote)
179  abort ();
180  o->left_quote = left_quote;
182 }
183 
184 /* Return quoting options for STYLE, with no extra quoting. */
185 static struct quoting_options /* NOT PURE!! */
187 {
188  struct quoting_options o = { literal_quoting_style, 0, { 0 }, NULL, NULL };
190  abort ();
191  o.style = style;
192  return o;
193 }
194 
195 /* MSGID approximates a quotation mark. Return its translation if it
196  has one; otherwise, return either it or "\"", depending on S.
197 
198  S is either clocale_quoting_style or locale_quoting_style. */
199 static char const *
200 gettext_quote (char const *msgid, enum quoting_style s)
201 {
202  char const *translation = _(msgid);
203  char const *locale_code;
204 
205  if (translation != msgid)
206  return translation;
207 
208  /* For UTF-8 and GB-18030, use single quotes U+2018 and U+2019.
209  Here is a list of other locales that include U+2018 and U+2019:
210 
211  ISO-8859-7 0xA1 KOI8-T 0x91
212  CP869 0x8B CP874 0x91
213  CP932 0x81 0x65 CP936 0xA1 0xAE
214  CP949 0xA1 0xAE CP950 0xA1 0xA5
215  CP1250 0x91 CP1251 0x91
216  CP1252 0x91 CP1253 0x91
217  CP1254 0x91 CP1255 0x91
218  CP1256 0x91 CP1257 0x91
219  EUC-JP 0xA1 0xC6 EUC-KR 0xA1 0xAE
220  EUC-TW 0xA1 0xE4 BIG5 0xA1 0xA5
221  BIG5-HKSCS 0xA1 0xA5 EUC-CN 0xA1 0xAE
222  GBK 0xA1 0xAE Georgian-PS 0x91
223  PT154 0x91
224 
225  None of these is still in wide use; using iconv is overkill. */
226  locale_code = locale_charset ();
227  if (STRCASEEQ (locale_code, "UTF-8", 'U','T','F','-','8',0,0,0,0))
228  return msgid[0] == '`' ? "\xe2\x80\x98": "\xe2\x80\x99";
229  if (STRCASEEQ (locale_code, "GB18030", 'G','B','1','8','0','3','0',0,0))
230  return msgid[0] == '`' ? "\xa1\ae": "\xa1\xaf";
231 
232  return (s == clocale_quoting_style ? "\"" : "'");
233 }
234 
235 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
236  argument ARG (of size ARGSIZE), using QUOTING_STYLE, FLAGS, and
237  QUOTE_THESE_TOO to control quoting.
238  Terminate the output with a null character, and return the written
239  size of the output, not counting the terminating null.
240  If BUFFERSIZE is too small to store the output string, return the
241  value that would have been returned had BUFFERSIZE been large enough.
242  If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE.
243 
244  This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG,
245  ARGSIZE, O), except it breaks O into its component pieces and is
246  not careful about errno. */
247 
248 static size_t
249 quotearg_buffer_restyled (char *buffer, size_t buffersize,
250  char const *arg, size_t argsize,
252  unsigned int const *quote_these_too,
253  char const *left_quote,
254  char const *right_quote)
255 {
256  size_t i;
257  size_t len = 0;
258  size_t orig_buffersize = 0;
259  char const *quote_string = 0;
260  size_t quote_string_len = 0;
261  bool backslash_escapes = false;
262  bool unibyte_locale = MB_CUR_MAX == 1;
263  bool elide_outer_quotes = (flags & QA_ELIDE_OUTER_QUOTES) != 0;
264  bool pending_shell_escape_end = false;
265  bool encountered_single_quote = false;
266  bool all_c_and_shell_quote_compat = true;
267 
268 #define STORE(c) \
269  do \
270  { \
271  if (len < buffersize) \
272  buffer[len] = (c); \
273  len++; \
274  } \
275  while (0)
276 
277 #define START_ESC() \
278  do \
279  { \
280  if (elide_outer_quotes) \
281  goto force_outer_quoting_style; \
282  escaping = true; \
283  if (quoting_style == shell_always_quoting_style \
284  && ! pending_shell_escape_end) \
285  { \
286  STORE ('\''); \
287  STORE ('$'); \
288  STORE ('\''); \
289  pending_shell_escape_end = true; \
290  } \
291  STORE ('\\'); \
292  } \
293  while (0)
294 
295 #define END_ESC() \
296  do \
297  { \
298  if (pending_shell_escape_end && ! escaping) \
299  { \
300  STORE ('\''); \
301  STORE ('\''); \
302  pending_shell_escape_end = false; \
303  } \
304  } \
305  while (0)
306 
307  process_input:
308 
309  switch (quoting_style)
310  {
313  elide_outer_quotes = true;
314  FALLTHROUGH;
315  case c_quoting_style:
316  if (!elide_outer_quotes)
317  STORE ('"');
318  backslash_escapes = true;
319  quote_string = "\"";
320  quote_string_len = 1;
321  break;
322 
324  backslash_escapes = true;
325  elide_outer_quotes = false;
326  break;
327 
331  {
333  {
334  /* TRANSLATORS:
335  Get translations for open and closing quotation marks.
336  The message catalog should translate "`" to a left
337  quotation mark suitable for the locale, and similarly for
338  "'". For example, a French Unicode local should translate
339  these to U+00AB (LEFT-POINTING DOUBLE ANGLE
340  QUOTATION MARK), and U+00BB (RIGHT-POINTING DOUBLE ANGLE
341  QUOTATION MARK), respectively.
342 
343  If the catalog has no translation, we will try to
344  use Unicode U+2018 (LEFT SINGLE QUOTATION MARK) and
345  Unicode U+2019 (RIGHT SINGLE QUOTATION MARK). If the
346  current locale is not Unicode, locale_quoting_style
347  will quote 'like this', and clocale_quoting_style will
348  quote "like this". You should always include translations
349  for "`" and "'" even if U+2018 and U+2019 are appropriate
350  for your locale.
351 
352  If you don't know what to put here, please see
353  <https://en.wikipedia.org/wiki/Quotation_marks_in_other_languages>
354  and use glyphs suitable for your language. */
357  }
358  if (!elide_outer_quotes)
359  for (quote_string = left_quote; *quote_string; quote_string++)
360  STORE (*quote_string);
361  backslash_escapes = true;
362  quote_string = right_quote;
363  quote_string_len = strlen (quote_string);
364  }
365  break;
366 
368  backslash_escapes = true;
369  FALLTHROUGH;
370  case shell_quoting_style:
371  elide_outer_quotes = true;
372  FALLTHROUGH;
374  if (!elide_outer_quotes)
375  backslash_escapes = true;
376  FALLTHROUGH;
379  if (!elide_outer_quotes)
380  STORE ('\'');
381  quote_string = "'";
382  quote_string_len = 1;
383  break;
384 
386  elide_outer_quotes = false;
387  break;
388 
389  default:
390  abort ();
391  }
392 
393  for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++)
394  {
395  unsigned char c;
396  unsigned char esc;
397  bool is_right_quote = false;
398  bool escaping = false;
399  bool c_and_shell_quote_compat = false;
400 
401  if (backslash_escapes
403  && quote_string_len
404  && (i + quote_string_len
405  <= (argsize == SIZE_MAX && 1 < quote_string_len
406  /* Use strlen only if we must: when argsize is SIZE_MAX,
407  and when the quote string is more than 1 byte long.
408  If we do call strlen, save the result. */
409  ? (argsize = strlen (arg)) : argsize))
410  && memcmp (arg + i, quote_string, quote_string_len) == 0)
411  {
412  if (elide_outer_quotes)
413  goto force_outer_quoting_style;
414  is_right_quote = true;
415  }
416 
417  c = arg[i];
418  switch (c)
419  {
420  case '\0':
421  if (backslash_escapes)
422  {
423  START_ESC ();
424  /* If quote_string were to begin with digits, we'd need to
425  test for the end of the arg as well. However, it's
426  hard to imagine any locale that would use digits in
427  quotes, and set_custom_quoting is documented not to
428  accept them. Use only a single \0 with shell-escape
429  as currently digits are not printed within $'...' */
431  && i + 1 < argsize && '0' <= arg[i + 1] && arg[i + 1] <= '9')
432  {
433  STORE ('0');
434  STORE ('0');
435  }
436  c = '0';
437  /* We don't have to worry that this last '0' will be
438  backslash-escaped because, again, quote_string should
439  not start with it and because quote_these_too is
440  documented as not accepting it. */
441  }
442  else if (flags & QA_ELIDE_NULL_BYTES)
443  continue;
444  break;
445 
446  case '?':
447  switch (quoting_style)
448  {
450  if (elide_outer_quotes)
451  goto force_outer_quoting_style;
452  break;
453 
454  case c_quoting_style:
455  if ((flags & QA_SPLIT_TRIGRAPHS)
456  && i + 2 < argsize && arg[i + 1] == '?')
457  switch (arg[i + 2])
458  {
459  case '!': case '\'':
460  case '(': case ')': case '-': case '/':
461  case '<': case '=': case '>':
462  /* Escape the second '?' in what would otherwise be
463  a trigraph. */
464  if (elide_outer_quotes)
465  goto force_outer_quoting_style;
466  c = arg[i + 2];
467  i += 2;
468  STORE ('?');
469  STORE ('"');
470  STORE ('"');
471  STORE ('?');
472  break;
473 
474  default:
475  break;
476  }
477  break;
478 
479  default:
480  break;
481  }
482  break;
483 
484  case '\a': esc = 'a'; goto c_escape;
485  case '\b': esc = 'b'; goto c_escape;
486  case '\f': esc = 'f'; goto c_escape;
487  case '\n': esc = 'n'; goto c_and_shell_escape;
488  case '\r': esc = 'r'; goto c_and_shell_escape;
489  case '\t': esc = 't'; goto c_and_shell_escape;
490  case '\v': esc = 'v'; goto c_escape;
491  case '\\': esc = c;
492  /* Never need to escape '\' in shell case. */
494  {
495  if (elide_outer_quotes)
496  goto force_outer_quoting_style;
497  goto store_c;
498  }
499 
500  /* No need to escape the escape if we are trying to elide
501  outer quotes and nothing else is problematic. */
502  if (backslash_escapes && elide_outer_quotes && quote_string_len)
503  goto store_c;
504 
505  c_and_shell_escape:
507  && elide_outer_quotes)
508  goto force_outer_quoting_style;
509  /* fall through */
510  c_escape:
511  if (backslash_escapes)
512  {
513  c = esc;
514  goto store_escape;
515  }
516  break;
517 
518  case '{': case '}': /* sometimes special if isolated */
519  if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1))
520  break;
521  FALLTHROUGH;
522  case '#': case '~':
523  if (i != 0)
524  break;
525  FALLTHROUGH;
526  case ' ':
527  c_and_shell_quote_compat = true;
528  FALLTHROUGH;
529  case '!': /* special in bash */
530  case '"': case '$': case '&':
531  case '(': case ')': case '*': case ';':
532  case '<':
533  case '=': /* sometimes special in 0th or (with "set -k") later args */
534  case '>': case '[':
535  case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
536  case '`': case '|':
537  /* A shell special character. In theory, '$' and '`' could
538  be the first bytes of multibyte characters, which means
539  we should check them with mbrtowc, but in practice this
540  doesn't happen so it's not worth worrying about. */
542  && elide_outer_quotes)
543  goto force_outer_quoting_style;
544  break;
545 
546  case '\'':
547  encountered_single_quote = true;
548  c_and_shell_quote_compat = true;
550  {
551  if (elide_outer_quotes)
552  goto force_outer_quoting_style;
553 
554  if (buffersize && ! orig_buffersize)
555  {
556  /* Just scan string to see if supports a more concise
557  representation, rather than writing a longer string
558  but returning the length of the more concise form. */
559  orig_buffersize = buffersize;
560  buffersize = 0;
561  }
562 
563  STORE ('\'');
564  STORE ('\\');
565  STORE ('\'');
566  pending_shell_escape_end = false;
567  }
568  break;
569 
570  case '%': case '+': case ',': case '-': case '.': case '/':
571  case '0': case '1': case '2': case '3': case '4': case '5':
572  case '6': case '7': case '8': case '9': case ':':
573  case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
574  case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
575  case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
576  case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
577  case 'Y': case 'Z': case ']': case '_': case 'a': case 'b':
578  case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
579  case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
580  case 'o': case 'p': case 'q': case 'r': case 's': case 't':
581  case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
582  /* These characters don't cause problems, no matter what the
583  quoting style is. They cannot start multibyte sequences.
584  A digit or a special letter would cause trouble if it
585  appeared at the beginning of quote_string because we'd then
586  escape by prepending a backslash. However, it's hard to
587  imagine any locale that would use digits or letters as
588  quotes, and set_custom_quoting is documented not to accept
589  them. Also, a digit or a special letter would cause
590  trouble if it appeared in quote_these_too, but that's also
591  documented as not accepting them. */
592  c_and_shell_quote_compat = true;
593  break;
594 
595  default:
596  /* If we have a multibyte sequence, copy it until we reach
597  its end, find an error, or come back to the initial shift
598  state. For C-like styles, if the sequence has
599  unprintable characters, escape the whole sequence, since
600  we can't easily escape single characters within it. */
601  {
602  /* Length of multibyte sequence found so far. */
603  size_t m;
604 
605  bool printable;
606 
607  if (unibyte_locale)
608  {
609  m = 1;
610  printable = isprint (c) != 0;
611  }
612  else
613  {
614  mbstate_t mbstate;
615  memset (&mbstate, 0, sizeof mbstate);
616 
617  m = 0;
618  printable = true;
619  if (argsize == SIZE_MAX)
620  argsize = strlen (arg);
621 
622  do
623  {
624  wchar_t w;
625  size_t bytes = mbrtowc (&w, &arg[i + m],
626  argsize - (i + m), &mbstate);
627  if (bytes == 0)
628  break;
629  else if (bytes == (size_t) -1)
630  {
631  printable = false;
632  break;
633  }
634  else if (bytes == (size_t) -2)
635  {
636  printable = false;
637  while (i + m < argsize && arg[i + m])
638  m++;
639  break;
640  }
641  else
642  {
643  /* Work around a bug with older shells that "see" a '\'
644  that is really the 2nd byte of a multibyte character.
645  In practice the problem is limited to ASCII
646  chars >= '@' that are shell special chars. */
647  if ('[' == 0x5b && elide_outer_quotes
649  {
650  size_t j;
651  for (j = 1; j < bytes; j++)
652  switch (arg[i + m + j])
653  {
654  case '[': case '\\': case '^':
655  case '`': case '|':
656  goto force_outer_quoting_style;
657 
658  default:
659  break;
660  }
661  }
662 
663  if (! iswprint (w))
664  printable = false;
665  m += bytes;
666  }
667  }
668  while (! mbsinit (&mbstate));
669  }
670 
671  c_and_shell_quote_compat = printable;
672 
673  if (1 < m || (backslash_escapes && ! printable))
674  {
675  /* Output a multibyte sequence, or an escaped
676  unprintable unibyte character. */
677  size_t ilim = i + m;
678 
679  for (;;)
680  {
681  if (backslash_escapes && ! printable)
682  {
683  START_ESC ();
684  STORE ('0' + (c >> 6));
685  STORE ('0' + ((c >> 3) & 7));
686  c = '0' + (c & 7);
687  }
688  else if (is_right_quote)
689  {
690  STORE ('\\');
691  is_right_quote = false;
692  }
693  if (ilim <= i + 1)
694  break;
695  END_ESC ();
696  STORE (c);
697  c = arg[++i];
698  }
699 
700  goto store_c;
701  }
702  }
703  }
704 
705  if (! (((backslash_escapes && quoting_style != shell_always_quoting_style)
706  || elide_outer_quotes)
707  && quote_these_too
708  && quote_these_too[c / INT_BITS] >> (c % INT_BITS) & 1)
709  && !is_right_quote)
710  goto store_c;
711 
712  store_escape:
713  START_ESC ();
714 
715  store_c:
716  END_ESC ();
717  STORE (c);
718 
719  if (! c_and_shell_quote_compat)
720  all_c_and_shell_quote_compat = false;
721  }
722 
723  if (len == 0 && quoting_style == shell_always_quoting_style
724  && elide_outer_quotes)
725  goto force_outer_quoting_style;
726 
727  /* Single shell quotes (') are commonly enough used as an apostrophe,
728  that we attempt to minimize the quoting in this case. Note itʼs
729  better to use the apostrophe modifier "\u02BC" if possible, as that
730  renders better and works with the word match regex \W+ etc. */
731  if (quoting_style == shell_always_quoting_style && ! elide_outer_quotes
732  && encountered_single_quote)
733  {
734  if (all_c_and_shell_quote_compat)
735  return quotearg_buffer_restyled (buffer, orig_buffersize, arg, argsize,
739  else if (! buffersize && orig_buffersize)
740  {
741  /* Disable read-only scan, and reprocess to write quoted string. */
742  buffersize = orig_buffersize;
743  len = 0;
744  goto process_input;
745  }
746  }
747 
748  if (quote_string && !elide_outer_quotes)
749  for (; *quote_string; quote_string++)
750  STORE (*quote_string);
751 
752  if (len < buffersize)
753  buffer[len] = '\0';
754  return len;
755 
756  force_outer_quoting_style:
757  /* Don't reuse quote_these_too, since the addition of outer quotes
758  sufficiently quotes the specified characters. */
759  if (quoting_style == shell_always_quoting_style && backslash_escapes)
761  return quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
765 }
766 
767 /* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
768  argument ARG (of size ARGSIZE), using O to control quoting.
769  If O is null, use the default.
770  Terminate the output with a null character, and return the written
771  size of the output, not counting the terminating null.
772  If BUFFERSIZE is too small to store the output string, return the
773  value that would have been returned had BUFFERSIZE been large enough.
774  If ARGSIZE is SIZE_MAX, use the string length of the argument for
775  ARGSIZE. */
776 size_t
777 quotearg_buffer (char *buffer, size_t buffersize,
778  char const *arg, size_t argsize,
779  struct quoting_options const *o)
780 {
781  struct quoting_options const *p = o ? o : &default_quoting_options;
782  int e = errno;
783  size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize,
784  p->style, p->flags, p->quote_these_too,
785  p->left_quote, p->right_quote);
786  errno = e;
787  return r;
788 }
789 
790 /* Equivalent to quotearg_alloc (ARG, ARGSIZE, NULL, O). */
791 char *
792 quotearg_alloc (char const *arg, size_t argsize,
793  struct quoting_options const *o)
794 {
795  return quotearg_alloc_mem (arg, argsize, NULL, o);
796 }
797 
798 /* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly
799  allocated storage containing the quoted string, and store the
800  resulting size into *SIZE, if non-NULL. The result can contain
801  embedded null bytes only if ARGSIZE is not SIZE_MAX, SIZE is not
802  NULL, and set_quoting_flags has not set the null byte elision
803  flag. */
804 char *
805 quotearg_alloc_mem (char const *arg, size_t argsize, size_t *size,
806  struct quoting_options const *o)
807 {
808  struct quoting_options const *p = o ? o : &default_quoting_options;
809  int e = errno;
810  /* Elide embedded null bytes if we can't return a size. */
811  int flags = p->flags | (size ? 0 : QA_ELIDE_NULL_BYTES);
812  size_t bufsize = quotearg_buffer_restyled (0, 0, arg, argsize, p->style,
813  flags, p->quote_these_too,
814  p->left_quote,
815  p->right_quote) + 1;
816  char *buf = xcharalloc (bufsize);
817  quotearg_buffer_restyled (buf, bufsize, arg, argsize, p->style, flags,
818  p->quote_these_too,
819  p->left_quote, p->right_quote);
820  errno = e;
821  if (size)
822  *size = bufsize - 1;
823  return buf;
824 }
825 
826 /* A storage slot with size and pointer to a value. */
827 struct slotvec
828 {
829  size_t size;
830  char *val;
831 };
832 
833 /* Preallocate a slot 0 buffer, so that the caller can always quote
834  one small component of a "memory exhausted" message in slot 0. */
835 static char slot0[256];
836 static int nslots = 1;
837 static struct slotvec slotvec0 = {sizeof slot0, slot0};
838 static struct slotvec *slotvec = &slotvec0;
839 
840 void
842 {
843  struct slotvec *sv = slotvec;
844  int i;
845  for (i = 1; i < nslots; i++)
846  free (sv[i].val);
847  if (sv[0].val != slot0)
848  {
849  free (sv[0].val);
850  slotvec0.size = sizeof slot0;
851  slotvec0.val = slot0;
852  }
853  if (sv != &slotvec0)
854  {
855  free (sv);
856  slotvec = &slotvec0;
857  }
858  nslots = 1;
859 }
860 
861 /* Use storage slot N to return a quoted version of argument ARG.
862  ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a
863  null-terminated string.
864  OPTIONS specifies the quoting options.
865  The returned value points to static storage that can be
866  reused by the next call to this function with the same value of N.
867  N must be nonnegative. N is deliberately declared with type "int"
868  to allow for future extensions (using negative values). */
869 static char *
870 quotearg_n_options (int n, char const *arg, size_t argsize,
871  struct quoting_options const *options)
872 {
873  int e = errno;
874 
875  struct slotvec *sv = slotvec;
876 
877  if (n < 0)
878  abort ();
879 
880  if (nslots <= n)
881  {
882  bool preallocated = (sv == &slotvec0);
883  int nmax = MIN (INT_MAX, MIN (PTRDIFF_MAX, SIZE_MAX) / sizeof *sv) - 1;
884 
885  if (nmax < n)
886  xalloc_die ();
887 
888  slotvec = sv = xrealloc (preallocated ? NULL : sv, (n + 1) * sizeof *sv);
889  if (preallocated)
890  *sv = slotvec0;
891  memset (sv + nslots, 0, (n + 1 - nslots) * sizeof *sv);
892  nslots = n + 1;
893  }
894 
895  {
896  size_t size = sv[n].size;
897  char *val = sv[n].val;
898  /* Elide embedded null bytes since we don't return a size. */
899  int flags = options->flags | QA_ELIDE_NULL_BYTES;
900  size_t qsize = quotearg_buffer_restyled (val, size, arg, argsize,
901  options->style, flags,
902  options->quote_these_too,
903  options->left_quote,
904  options->right_quote);
905 
906  if (size <= qsize)
907  {
908  sv[n].size = size = qsize + 1;
909  if (val != slot0)
910  free (val);
911  sv[n].val = val = xcharalloc (size);
912  quotearg_buffer_restyled (val, size, arg, argsize, options->style,
913  flags, options->quote_these_too,
914  options->left_quote,
915  options->right_quote);
916  }
917 
918  errno = e;
919  return val;
920  }
921 }
922 
923 char *
924 quotearg_n (int n, char const *arg)
925 {
927 }
928 
929 char *
930 quotearg_n_mem (int n, char const *arg, size_t argsize)
931 {
932  return quotearg_n_options (n, arg, argsize, &default_quoting_options);
933 }
934 
935 char *
936 quotearg (char const *arg)
937 {
938  return quotearg_n (0, arg);
939 }
940 
941 char *
942 quotearg_mem (char const *arg, size_t argsize)
943 {
944  return quotearg_n_mem (0, arg, argsize);
945 }
946 
947 char *
948 quotearg_n_style (int n, enum quoting_style s, char const *arg)
949 {
950  struct quoting_options const o = quoting_options_from_style (s);
951  return quotearg_n_options (n, arg, SIZE_MAX, &o);
952 }
953 
954 char *
956  char const *arg, size_t argsize)
957 {
958  struct quoting_options const o = quoting_options_from_style (s);
959  return quotearg_n_options (n, arg, argsize, &o);
960 }
961 
962 char *
963 quotearg_style (enum quoting_style s, char const *arg)
964 {
965  return quotearg_n_style (0, s, arg);
966 }
967 
968 char *
969 quotearg_style_mem (enum quoting_style s, char const *arg, size_t argsize)
970 {
971  return quotearg_n_style_mem (0, s, arg, argsize);
972 }
973 
974 char *
975 quotearg_char_mem (char const *arg, size_t argsize, char ch)
976 {
977  struct quoting_options options;
978  options = default_quoting_options;
979  set_char_quoting (&options, ch, 1);
980  return quotearg_n_options (0, arg, argsize, &options);
981 }
982 
983 char *
984 quotearg_char (char const *arg, char ch)
985 {
986  return quotearg_char_mem (arg, SIZE_MAX, ch);
987 }
988 
989 char *
990 quotearg_colon (char const *arg)
991 {
992  return quotearg_char (arg, ':');
993 }
994 
995 char *
996 quotearg_colon_mem (char const *arg, size_t argsize)
997 {
998  return quotearg_char_mem (arg, argsize, ':');
999 }
1000 
1001 char *
1002 quotearg_n_style_colon (int n, enum quoting_style s, char const *arg)
1003 {
1004  struct quoting_options options;
1005  options = quoting_options_from_style (s);
1006  set_char_quoting (&options, ':', 1);
1007  return quotearg_n_options (n, arg, SIZE_MAX, &options);
1008 }
1009 
1010 char *
1011 quotearg_n_custom (int n, char const *left_quote,
1012  char const *right_quote, char const *arg)
1013 {
1014  return quotearg_n_custom_mem (n, left_quote, right_quote, arg,
1015  SIZE_MAX);
1016 }
1017 
1018 char *
1019 quotearg_n_custom_mem (int n, char const *left_quote,
1020  char const *right_quote,
1021  char const *arg, size_t argsize)
1022 {
1025  return quotearg_n_options (n, arg, argsize, &o);
1026 }
1027 
1028 char *
1029 quotearg_custom (char const *left_quote, char const *right_quote,
1030  char const *arg)
1031 {
1032  return quotearg_n_custom (0, left_quote, right_quote, arg);
1033 }
1034 
1035 char *
1036 quotearg_custom_mem (char const *left_quote, char const *right_quote,
1037  char const *arg, size_t argsize)
1038 {
1039  return quotearg_n_custom_mem (0, left_quote, right_quote, arg,
1040  argsize);
1041 }
1042 
1043 
1044 /* The quoting option used by the functions of quote.h. */
1046  {
1048  0,
1049  { 0 },
1050  NULL, NULL
1051  };
1052 
1053 char const *
1054 quote_n_mem (int n, char const *arg, size_t argsize)
1055 {
1056  return quotearg_n_options (n, arg, argsize, &quote_quoting_options);
1057 }
1058 
1059 char const *
1060 quote_mem (char const *arg, size_t argsize)
1061 {
1062  return quote_n_mem (0, arg, argsize);
1063 }
1064 
1065 char const *
1066 quote_n (int n, char const *arg)
1067 {
1068  return quote_n_mem (n, arg, SIZE_MAX);
1069 }
1070 
1071 char const *
1072 quote (char const *arg)
1073 {
1074  return quote_n (0, arg);
1075 }
1076 
1077 /*
1078  * Hey Emacs!
1079  * Local Variables:
1080  * coding: utf-8
1081  * End:
1082  */
#define STRCASEEQ(s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
Definition: c-strcaseeq.h:178
#define FALLTHROUGH
Definition: attribute.h:142
#define MIN(a, b)
Definition: minmax.h:57
#define NULL
Definition: stddef.in.h:72
#define PTRDIFF_MAX
Definition: stdint.in.h:544
#define mbstate_t
Definition: wchar.in.h:143
const char * locale_charset(void)
Definition: localcharset.c:831
unsigned char c
size_t m
Definition: mbrtowc-impl.h:43
const char * p
Definition: mbrtowc-impl.h:42
char buf[4]
Definition: mbrtowc-impl.h:39
int mbsinit(const mbstate_t *ps)
Definition: mbsinit.c:55
char * quotearg(char const *arg)
Definition: quotearg.c:936
int set_char_quoting(struct quoting_options *o, char c, int i)
Definition: quotearg.c:145
char * quotearg_colon(char const *arg)
Definition: quotearg.c:990
#define START_ESC()
char * quotearg_colon_mem(char const *arg, size_t argsize)
Definition: quotearg.c:996
static char const * gettext_quote(char const *msgid, enum quoting_style s)
Definition: quotearg.c:200
char * quotearg_n_mem(int n, char const *arg, size_t argsize)
Definition: quotearg.c:930
char * quotearg_n_style_mem(int n, enum quoting_style s, char const *arg, size_t argsize)
Definition: quotearg.c:955
char const * quote(char const *arg)
Definition: quotearg.c:1072
char * quotearg_n_custom_mem(int n, char const *left_quote, char const *right_quote, char const *arg, size_t argsize)
Definition: quotearg.c:1019
char * quotearg_n_custom(int n, char const *left_quote, char const *right_quote, char const *arg)
Definition: quotearg.c:1011
#define SIZE_MAX
Definition: quotearg.c:53
char const * quote_mem(char const *arg, size_t argsize)
Definition: quotearg.c:1060
char * quotearg_mem(char const *arg, size_t argsize)
Definition: quotearg.c:942
static char slot0[256]
Definition: quotearg.c:835
#define STORE(c)
void set_quoting_style(struct quoting_options *o, enum quoting_style s)
Definition: quotearg.c:134
char const * quote_n_mem(int n, char const *arg, size_t argsize)
Definition: quotearg.c:1054
static size_t quotearg_buffer_restyled(char *buffer, size_t buffersize, char const *arg, size_t argsize, enum quoting_style quoting_style, int flags, unsigned int const *quote_these_too, char const *left_quote, char const *right_quote)
Definition: quotearg.c:249
char * quotearg_alloc_mem(char const *arg, size_t argsize, size_t *size, struct quoting_options const *o)
Definition: quotearg.c:805
char const * quote_n(int n, char const *arg)
Definition: quotearg.c:1066
char * quotearg_custom(char const *left_quote, char const *right_quote, char const *arg)
Definition: quotearg.c:1029
#define _(msgid)
Definition: quotearg.c:49
int set_quoting_flags(struct quoting_options *o, int i)
Definition: quotearg.c:161
char * quotearg_n_style_colon(int n, enum quoting_style s, char const *arg)
Definition: quotearg.c:1002
struct quoting_options * clone_quoting_options(struct quoting_options *o)
Definition: quotearg.c:115
void set_custom_quoting(struct quoting_options *o, char const *left_quote, char const *right_quote)
Definition: quotearg.c:172
struct quoting_options quote_quoting_options
Definition: quotearg.c:1045
char * quotearg_style(enum quoting_style s, char const *arg)
Definition: quotearg.c:963
#define INT_BITS
Definition: quotearg.c:56
enum quoting_style const quoting_style_vals[]
Definition: quotearg.c:94
static struct quoting_options default_quoting_options
Definition: quotearg.c:109
char * quotearg_char(char const *arg, char ch)
Definition: quotearg.c:984
void quotearg_free(void)
Definition: quotearg.c:841
#define N_(msgid)
Definition: quotearg.c:50
static struct slotvec slotvec0
Definition: quotearg.c:837
char const *const quoting_style_args[]
Definition: quotearg.c:78
char * quotearg_custom_mem(char const *left_quote, char const *right_quote, char const *arg, size_t argsize)
Definition: quotearg.c:1036
static int nslots
Definition: quotearg.c:836
char * quotearg_alloc(char const *arg, size_t argsize, struct quoting_options const *o)
Definition: quotearg.c:792
size_t quotearg_buffer(char *buffer, size_t buffersize, char const *arg, size_t argsize, struct quoting_options const *o)
Definition: quotearg.c:777
enum quoting_style get_quoting_style(struct quoting_options const *o)
Definition: quotearg.c:126
static struct slotvec * slotvec
Definition: quotearg.c:838
#define END_ESC()
char * quotearg_n_style(int n, enum quoting_style s, char const *arg)
Definition: quotearg.c:948
static struct quoting_options quoting_options_from_style(enum quoting_style style)
Definition: quotearg.c:186
static char * quotearg_n_options(int n, char const *arg, size_t argsize, struct quoting_options const *options)
Definition: quotearg.c:870
char * quotearg_style_mem(enum quoting_style s, char const *arg, size_t argsize)
Definition: quotearg.c:969
char * quotearg_n(int n, char const *arg)
Definition: quotearg.c:924
char * quotearg_char_mem(char const *arg, size_t argsize, char ch)
Definition: quotearg.c:975
quoting_style
Definition: quotearg.h:33
@ clocale_quoting_style
Definition: quotearg.h:195
@ shell_quoting_style
Definition: quotearg.h:59
@ shell_always_quoting_style
Definition: quotearg.h:74
@ shell_escape_always_quoting_style
Definition: quotearg.h:105
@ shell_escape_quoting_style
Definition: quotearg.h:89
@ custom_quoting_style
Definition: quotearg.h:238
@ literal_quoting_style
Definition: quotearg.h:45
@ c_maybe_quoting_style
Definition: quotearg.h:131
@ locale_quoting_style
Definition: quotearg.h:170
@ escape_quoting_style
Definition: quotearg.h:144
@ c_quoting_style
Definition: quotearg.h:119
@ QA_ELIDE_OUTER_QUOTES
Definition: quotearg.h:252
@ QA_SPLIT_TRIGRAPHS
Definition: quotearg.h:258
@ QA_ELIDE_NULL_BYTES
Definition: quotearg.h:247
char const * right_quote
Definition: quotearg.c:74
enum quoting_style style
Definition: quotearg.c:61
unsigned int quote_these_too[(UCHAR_MAX/(sizeof(int) *CHAR_BIT))+1]
Definition: quotearg.c:68
char const * left_quote
Definition: quotearg.c:71
size_t size
Definition: quotearg.c:829
char * val
Definition: quotearg.c:830
_GL_INLINE int iswprint(int wc)
Definition: wctype.in.h:385
void xalloc_die(void)
Definition: xalloc-die.c:32
void * xrealloc(void *p, size_t n)
Definition: xmalloc.c:63
void * xmemdup(void const *p, size_t s)
Definition: xmalloc.c:122