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