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>
 
 #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       */
 /* **************************************************************** */
 /*                                                                 */
 /*      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;
 
   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++)
   *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
    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 *
 char *
-sh_backslash_quote (string)
+sh_backslash_quote (string, table, flags)
      char *string;
      char *string;
+     char *table;
+     int flags;
 {
   int c;
 {
   int c;
-  char *result, *r, *s;
+  char *result, *r, *s, *backslash_table;
 
   result = (char *)xmalloc (2 * strlen (string) + 1);
 
 
   result = (char *)xmalloc (2 * strlen (string) + 1);
 
+  backslash_table = table ? table : (char *)bstab;
   for (r = result, s = string; s && (c = *s); s++)
     {
   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';
     }
 
   *r = '\0';