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