Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / lib / sh / shquote.c
index a1e9146..31cce1c 100644 (file)
 #include "syntax.h"
 #include <xmalloc.h>
 
+/* Default set of characters that should be backslash-quoted in strings */
+static const char bstab[256] =
+  {
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 1, 1, 0, 0, 0, 0, 0,    /* TAB, NL */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+
+    1, 1, 1, 0, 1, 0, 1, 1,    /* SPACE, !, DQUOTE, DOL, AMP, SQUOTE */
+    1, 1, 1, 0, 1, 0, 0, 0,    /* LPAR, RPAR, STAR, COMMA */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 1, 1, 0, 1, 1,    /* SEMI, LESSTHAN, GREATERTHAN, QUEST */
+
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 1, 1, 1, 1, 0,    /* LBRACK, BS, RBRACK, CARAT */
+
+    1, 0, 0, 0, 0, 0, 0, 0,    /* BACKQ */
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 1, 1, 1, 0, 0,    /* LBRACE, BAR, RBRACE */
+
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+  };
+
 /* **************************************************************** */
 /*                                                                 */
 /*      Functions for quoting strings to be re-read as input       */
@@ -50,6 +94,15 @@ sh_single_quote (string)
 
   result = (char *)xmalloc (3 + (4 * strlen (string)));
   r = result;
+
+  if (string[0] == '\'' && string[1] == 0)
+    {
+      *r++ = '\\';
+      *r++ = '\'';
+      *r++ = 0;
+      return result;
+    }
+
   *r++ = '\'';
 
   for (s = string; s && (c = *s); s++)
@@ -163,53 +216,33 @@ sh_un_double_quote (string)
    way to protect the CTLESC and CTLNUL characters.  As I write this,
    the current callers will never cause the string to be expanded without
    going through the shell parser, which will protect the internal
-   quoting characters. */
+   quoting characters.  TABLE, if set, points to a map of the ascii code
+   set with char needing to be backslash-quoted if table[char]==1.  FLAGS,
+   if 1, causes tildes to be quoted as well. */
+   
 char *
-sh_backslash_quote (string)
+sh_backslash_quote (string, table, flags)
      char *string;
+     char *table;
+     int flags;
 {
   int c;
-  char *result, *r, *s;
+  char *result, *r, *s, *backslash_table;
 
   result = (char *)xmalloc (2 * strlen (string) + 1);
 
+  backslash_table = table ? table : (char *)bstab;
   for (r = result, s = string; s && (c = *s); s++)
     {
-      switch (c)
-       {
-       case ' ': case '\t': case '\n':         /* IFS white space */
-       case '\'': case '"': case '\\':         /* quoting chars */
-       case '|': case '&': case ';':           /* shell metacharacters */
-       case '(': case ')': case '<': case '>':
-       case '!': case '{': case '}':           /* reserved words */
-       case '*': case '[': case '?': case ']': /* globbing chars */
-       case '^':
-       case '$': case '`':                     /* expansion chars */
-       case ',':                               /* brace expansion */
-         *r++ = '\\';
-         *r++ = c;
-         break;
-#if 0
-       case '~':                               /* tilde expansion */
-         if (s == string || s[-1] == '=' || s[-1] == ':')
-           *r++ = '\\';
-         *r++ = c;
-         break;
-
-       case CTLESC: case CTLNUL:               /* internal quoting characters */
-         *r++ = CTLESC;                        /* could be '\\'? */
-         *r++ = c;
-         break;
-#endif
-
-       case '#':                               /* comment char */
-         if (s == string)
-           *r++ = '\\';
-         /* FALLTHROUGH */
-       default:
-         *r++ = c;
-         break;
-       }
+      if (backslash_table[c] == 1)
+       *r++ = '\\';
+      else if (c == '#' && s == string)                        /* comment char */
+       *r++ = '\\';
+      else if ((flags&1) && c == '~' && (s == string || s[-1] == ':' || s[-1] == '='))
+        /* Tildes are special at the start of a word or after a `:' or `='
+          (technically unquoted, but it doesn't make a difference in practice) */
+       *r++ = '\\';
+      *r++ = c;
     }
 
   *r = '\0';