From 0402072d963b42c868444ffb39b9543d78b44269 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 23 Feb 1998 10:16:53 +0000 Subject: [PATCH] . --- lib/quotearg.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/quotearg.h | 97 ++++++++++++++ 2 files changed, 443 insertions(+) create mode 100644 lib/quotearg.c create mode 100644 lib/quotearg.h diff --git a/lib/quotearg.c b/lib/quotearg.c new file mode 100644 index 0000000000..5829c6df14 --- /dev/null +++ b/lib/quotearg.c @@ -0,0 +1,346 @@ +/* quotearg.c - quote arguments for output + Copyright (C) 1998 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include +#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) +# define ISASCII(c) 1 +#else +# define ISASCII(c) isascii (c) +#endif +#ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +#else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +#endif + +#if HAVE_LIMITS_H +# include +#endif +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif +#ifndef UCHAR_MAX +# define UCHAR_MAX ((unsigned char) -1) +#endif + +#if HAVE_STDLIB_H +# include +#endif + +#if HAVE_STRING_H +# include +#endif + +#define INT_BITS (sizeof (int) * CHAR_BIT) + +struct quoting_options +{ + /* Basic quoting style. */ + enum quoting_style style; + + /* Quote the chararacters indicated by this bit vector even if the + quoting style would not normally require them to be quoted. */ + int quote_these_too[((UCHAR_MAX + 1) / INT_BITS + + ((UCHAR_MAX + 1) % INT_BITS != 0))]; +}; + +/* Names of quoting styles. */ +char const *const quoting_style_args[] = +{ + "literal", "shell", "shell-always", "c", "escape", 0 +}; + +/* Allocate a new set of quoting options, with contents initially identical + to O if O is not null, or to a default value if O is null. + It is the caller's responsibility to free the result. */ +struct quoting_options * +clone_quoting_options (struct quoting_options *o) +{ + struct quoting_options *p + = (struct quoting_options *) xmalloc (sizeof (struct quoting_options)); + if (o) + *p = *o; + else + memset (p, 0, sizeof *p); + return p; +} + +/* Get the value of O's quoting style. */ +enum quoting_style +get_quoting_style (struct quoting_options *o) +{ + return o->style; +} + +/* In O, set the value of the quoting style to S. */ +void +set_quoting_style (struct quoting_options *o, enum quoting_style s) +{ + o->style = s; +} + +/* In O, set the value of the quoting options for character C to I. + Return the old value. Currently, the only values defined for I are + 0 (the default) and 1 (which means to quote the character even if + it would not otherwise be quoted). */ +int +set_char_quoting (struct quoting_options *o, char c, int i) +{ + unsigned char uc = c; + int *p = o->quote_these_too + uc / INT_BITS; + int shift = uc % INT_BITS; + int r = (*p >> shift) & 1; + *p ^= ((i & 1) ^ r) << shift; + return r; +} + +/* Place into buffer BUF (of size BUFSIZE) a quoted version of + argument ARG (of size ARGSIZE), using O to control quoting. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFSIZE is too small to store the output string, return the + value that would have been returned had BUFSIZE been large enough. + If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */ +size_t +quotearg_buffer (char *buf, size_t bufsize, + char const *arg, size_t argsize, + struct quoting_options const *o) +{ + unsigned char c; + size_t i; + size_t len; + int quote_mark; + enum quoting_style quoting_style = o->style; +#define STORE(c) do { if (len < bufsize) buf[len] = (c); len++; } while (0) + + switch (quoting_style) + { + case shell_quoting_style: + if (! (argsize == -1 ? arg[0] == '\0' : argsize == 0)) + { + switch (arg[0]) + { + case '#': case '~': + break; + + default: + len = 0; + for (i = 0; ; i++) + { + if (argsize == -1 ? arg[i] == '\0' : i == argsize) + goto done; + + c = arg[i]; + + switch (c) + { + case '\t': case '\n': case ' ': + case '!': /* special in csh */ + case '"': case '$': case '&': case '\'': + case '(': case ')': case '*': case ';': + case '<': case '>': case '?': case '[': case '\\': + case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */ + case '`': case '|': + goto needs_quoting; + } + + if (o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))) + goto needs_quoting; + + STORE (c); + } + + needs_quoting:; + break; + } + } + /* Fall through. */ + + case shell_always_quoting_style: + quote_mark = '\''; + break; + + case c_quoting_style: + quote_mark = '"'; + break; + + default: + quote_mark = 0; + break; + } + + len = 0; + + if (quote_mark) + STORE (quote_mark); + + for (i = 0; ! (argsize == -1 ? arg[i] == '\0' : i == argsize); i++) + { + c = arg[i]; + + switch (quoting_style) + { + case literal_quoting_style: + break; + + case shell_quoting_style: + case shell_always_quoting_style: + if (c == '\'') + { + STORE ('\''); + STORE ('\\'); + STORE ('\''); + } + break; + + case c_quoting_style: + case escape_quoting_style: + switch (c) + { + case '?': /* Do not generate trigraphs. */ + case '\\': goto store_escape; + /* Not all C compilers know what \a means. */ + case 7 : c = 'a'; goto store_escape; + case '\b': c = 'b'; goto store_escape; + case '\f': c = 'f'; goto store_escape; + case '\n': c = 'n'; goto store_escape; + case '\r': c = 'r'; goto store_escape; + case '\t': c = 't'; goto store_escape; + case '\v': c = 'v'; goto store_escape; + + case ' ': + if (quoting_style == escape_quoting_style) + goto store_escape; + break; + + case '"': + if (quoting_style == c_quoting_style) + goto store_escape; + break; + + default: + if (!ISGRAPH (c)) + { + STORE ('\\'); + STORE ('0' + (c >> 6)); + STORE ('0' + ((c >> 3) & 3)); + c = '0' + (c & 3); + goto store_c; + } + break; + } + + if (! (o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))) + goto store_c; + + store_escape: + STORE ('\\'); + } + + store_c: + STORE (c); + } + + if (quote_mark) + STORE (quote_mark); + + done: + if (len < bufsize) + buf[len] = '\0'; + return len; +} + +/* Use storage slot N to return a quoted version of the string ARG. + OPTIONS specifies the quoting options. + The returned value points to static storage that can be + reused by the next call to this function with the same value of N. + N must be nonnegative. */ +static char * +quotearg_n_options (int n, char const *arg, struct quoting_options *options) +{ + static unsigned nslots; + static struct slotvec + { + size_t size; + char *val; + } *slotvec; + + if (nslots <= n) + { + int n1 = n + 1; + size_t s = n1 * sizeof (struct slotvec); + if (! (0 < n1 && n1 == s / sizeof (struct slotvec))) + abort (); + slotvec = (struct slotvec *) xrealloc (slotvec, s); + memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec)); + nslots = n; + } + + { + size_t size = slotvec[n].size; + char *val = slotvec[n].val; + size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options); + + if (size <= qsize) + { + slotvec[n].size = size = qsize + 1; + slotvec[n].val = val = xrealloc (val, size); + quotearg_buffer (val, size, arg, (size_t) -1, options); + } + + return val; + } +} + +struct quoting_options quotearg_quoting_options; + +char * +quotearg_n (int n, char const *arg) +{ + return quotearg_n_options (n, arg, "earg_quoting_options); +} + +char * +quotearg (char const *arg) +{ + return quotearg_n (0, arg); +} + +char * +quotearg_char (char const *arg, char ch) +{ + struct quoting_options options; + options = quotearg_quoting_options; + set_char_quoting (&options, ch, 1); + return quotearg_n_options (0, arg, &options); +} + +char * +quotearg_colon (char const *arg) +{ + return quotearg_char (arg, ':'); +} diff --git a/lib/quotearg.h b/lib/quotearg.h new file mode 100644 index 0000000000..01cd899d2d --- /dev/null +++ b/lib/quotearg.h @@ -0,0 +1,97 @@ +/* quotearg.h - quote arguments for output + Copyright (C) 1998 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Paul Eggert */ + +/* Basic quoting styles. */ +enum quoting_style + { + literal_quoting_style, /* --quoting-style=literal */ + shell_quoting_style, /* --quoting-style=shell */ + shell_always_quoting_style, /* --quoting-style=shell-always */ + c_quoting_style, /* --quoting-style=c */ + escape_quoting_style /* --quoting-style=escape */ + }; + +/* For now, --quoting-style=literal is the default, but + this is planned to change to --quoting-style=shell in the future. */ +#ifndef DEFAULT_QUOTING_STYLE +# define DEFAULT_QUOTING_STYLE literal_quoting_style +#endif + +/* Names of quoting styles. */ +extern char const *const quoting_style_args[]; + +struct quoting_options; + +#ifndef PARAMS +# if defined PROTOTYPES || (defined __STDC__ && __STDC__) +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +#endif + +/* Allocate a new set of quoting options, with contents initially identical + to O if O is not null, or to a default value if O is null. + It is the caller's responsibility to free the result. */ +struct quoting_options *clone_quoting_options + PARAMS ((struct quoting_options *o)); + +/* Get the value of O's quoting style. */ +enum quoting_style get_quoting_style PARAMS ((struct quoting_options *o)); + +/* In O, set the value of the quoting style to S. */ +void set_quoting_style PARAMS ((struct quoting_options *o, + enum quoting_style s)); + +/* In O, set the value of the quoting options for character C to I. + Return the old value. Currently, the only values defined for I are + 0 (the default) and 1 (which means to quote the character even if + it would not otherwise be quoted). */ +int set_char_quoting PARAMS ((struct quoting_options *o, char c, int i)); + +/* Place into buffer BUF (of size BUFSIZE) a quoted version of + argument ARG (of size ARGSIZE), using O to control quoting. + Terminate the output with a null character, and return the written + size of the output, not counting the terminating null. + If BUFSIZE is too small to store the output string, return the + value that would have been returned had BUFSIZE been large enough. + If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */ +size_t quotearg_buffer PARAMS ((char *buf, size_t bufsize, + char const *arg, size_t argsize, + struct quoting_options const *o)); + +/* The quoting options used by the convenience functions listed below. */ + +extern struct quoting_options quotearg_quoting_options; + +/* Use storage slot N to return a quoted version of the string ARG. + The variable quotearg_quoting_options specifies the quoting options. + The returned value points to static storage that can be + reused by the next call to this function with the same value of N. + N must be nonnegative. */ +char *quotearg_n PARAMS ((int n, char const *arg)); + +/* Equivalent to quotearg_n (ARG, 0). */ +char *quotearg PARAMS ((char const *arg)); + +/* Like quotearg (ARG), except also quote any instances of CH. */ +char *quotearg_char PARAMS ((char const *arg, char ch)); + +/* Equivalent to quotearg_char (ARG, ':'). */ +char *quotearg_colon PARAMS ((char const *arg)); -- 2.30.2