about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--Src/utils.c34
-rw-r--r--Test/A03quoting.ztst14
3 files changed, 43 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index b474eb635..fa6fbff49 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,8 @@
 2007-01-27  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
-	* 23136: Src/utils.c, Test/A03quoting.ztst: 23097 added Bnulls
-	for backslashes in $'...' strings but then didn't handle them.
+	* 23136, 23138: Src/utils.c, Test/A03quoting.ztst: 23097 added
+	Bnulls for backslashes in $'...' strings but then didn't handle
+	them.
 
 2007-01-26  Wayne Davison  <wayned@users.sourceforge.net>
 
diff --git a/Src/utils.c b/Src/utils.c
index c0ccc6715..ce7b4caac 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -4915,27 +4915,45 @@ getkeystring(char *s, int *len, int how, int *misc)
 	    *t++ = *++s ^ 32;
 	else {
 	    if (itok(*s)) {
+		/*
+		 * We need to be quite careful here.  We haven't
+		 * necessarily got an input stream with all tokens
+		 * removed, so the majority of tokens need passing
+		 * through untouched and without Meta handling.
+		 * However, me may need to handle tokenized
+		 * backslashes.
+		 */
 		if (meta || control) {
 		    /*
 		     * Presumably we should be using meta or control
 		     * on the character representing the token.
+		     *
+		     * Special case: $'\M-\\' where the token is a Bnull.
+		     * This time we dump the Bnull since we're
+		     * replacing the whole thing.  The lexer
+		     * doesn't know about the meta or control modifiers.
 		     */
-		    *t++ = ztokens[*s - Pound];
+		    if ((how & GETKEY_DOLLAR_QUOTE) && *s == Bnull)
+			*t++ = *++s;
+		    else
+			*t++ = ztokens[*s - Pound];
 		} else if (how & GETKEY_DOLLAR_QUOTE) {
+		    /*
+		     * We don't want to metafy this, it's a real
+		     * token.
+		     */
+		    *tdest++ = *s;
 		    if (*s == Bnull) {
 			/*
 			 * Bnull is a backslash which quotes a couple
 			 * of special characters that always appear
 			 * literally next.  See strquote handling
-			 * in gettokstr() in lex.c.
+			 * in gettokstr() in lex.c.  We need
+			 * to retain the Bnull (as above) so that quote
+			 * handling in completion can tell where the
+			 * backslash was.
 			 */
 			*tdest++ = *++s;
-		    } else {
-			/*
-			 * We don't want to metafy this, it's a real
-			 * token.
-			 */
-			*tdest++ = *s;
 		    }
 		    continue;
 		} else
diff --git a/Test/A03quoting.ztst b/Test/A03quoting.ztst
index 3187382a8..54005ebe3 100644
--- a/Test/A03quoting.ztst
+++ b/Test/A03quoting.ztst
@@ -17,6 +17,20 @@
 0:$'-style quotes with backslashed backslashes
 >'a \' is 'a backslash' is 'a \'
 
+  chars=$(print -r $'BS\\MBS\M-\\')
+  for (( i = 1; i <= $#chars; i++ )); do
+    char=$chars[$i]
+    print $(( [#16] #char ))
+  done
+0:$'-style quote with metafied backslash
+>16#42
+>16#53
+>16#5C
+>16#4D
+>16#42
+>16#53
+>16#DC
+
   print -r ''''
   setopt rcquotes
 # We need to set rcquotes here for the next example since it is