about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Src/Zle/zle_hist.c2
-rw-r--r--Src/Zle/zle_keymap.c11
-rw-r--r--Src/Zle/zle_misc.c2
-rw-r--r--Src/builtin.c17
-rw-r--r--Src/math.c2
-rw-r--r--Src/params.c4
-rw-r--r--Src/subst.c8
-rw-r--r--Src/utils.c62
-rw-r--r--Src/zsh.h56
10 files changed, 114 insertions, 56 deletions
diff --git a/ChangeLog b/ChangeLog
index 22d4b1d34..a3a870af4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2006-09-10  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
+	* 22684: Src/builtin.c, Src/math.c, Src/params.c, Src/subst.c,
+	Src/utils.c, Src/zsh.h, Src/Zle/zle_hist.c, Src/Zle/zle_hist.c,
+	Src/Zle/zle_misc.c: rewrite getkeystring() to have something
+	approaching an API; printf strings expand octal escapes even
+	without a leading zero.
+
 	* 22676, adapted as in 22678: README, Doc/Zsh/mod_sched.yo,
 	Src/init.c, Src/subst.c, Src/utils.c, Src/zsh.h,
 	Src/Builtins/sched.c, Src/Zle/zle_main.c, Src/Zle/zle_thingy.c:
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index da8f9244e..bb740d75c 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -902,7 +902,7 @@ doisearch(char **args, int dir)
 	int len;
 	char *arg;
 	savekeys = kungetct;
-	arg = getkeystring(*args, &len, 2, NULL);
+	arg = getkeystring(*args, &len, GETKEYS_BINDKEY, NULL);
 	ungetbytes(arg, len);
     }
 
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 5b6b7f05b..454e26f16 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -879,7 +879,7 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, Options ops,
 	struct remprefstate rps;
 	rps.km = km;
 	while ((useq = *argv++)) {
-	    bseq = getkeystring(useq, &len, 2, NULL);
+	    bseq = getkeystring(useq, &len, GETKEYS_BINDKEY, NULL);
 	    rps.prefix = metafy(bseq, len, META_USEHEAP);
 	    rps.prefixlen = strlen(rps.prefix);
 	    scankeymap(km, 0, scanremoveprefix, &rps);
@@ -895,14 +895,14 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, Options ops,
 	    fn = refthingy(t_undefinedkey);
 	    str = NULL;
 	} else if(func == 's') {
-	    str = getkeystring(*++argv, &len, 2, NULL);
+	    str = getkeystring(*++argv, &len, GETKEYS_BINDKEY, NULL);
 	    fn = NULL;
 	    str = metafy(str, len, META_HREALLOC);
 	} else {
 	    fn = rthingy(*++argv);
 	    str = NULL;
 	}
-	bseq = getkeystring(useq, &len, 2, NULL);
+	bseq = getkeystring(useq, &len, GETKEYS_BINDKEY, NULL);
 	seq = metafy(bseq, len, META_USEHEAP);
 	if(OPT_ISSET(ops,'R')) {
 	    int first, last;
@@ -960,7 +960,7 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, Options ops,
 	int len;
 	char *seq;
 
-	seq = getkeystring(argv[0], &len, 2, NULL);
+	seq = getkeystring(argv[0], &len, GETKEYS_BINDKEY, NULL);
 	seq = metafy(seq, len, META_HREALLOC);
 	bs.flags |= BS_ALL;
 	bs.firstseq = bs.lastseq = seq;
@@ -975,7 +975,8 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, Options ops,
 		zwarnnam(name, "option -p requires a prefix string");
 		return 1;
 	    }
-	    bs.prefix = getkeystring(argv[0], &bs.prefixlen, 2, NULL);
+	    bs.prefix = getkeystring(argv[0], &bs.prefixlen, GETKEYS_BINDKEY,
+				     NULL);
 	    bs.prefix = metafy(bs.prefix, bs.prefixlen, META_HREALLOC);
 	    bs.prefixlen = strlen(bs.prefix);
 	} else {
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 314e1333d..30fa0cc5b 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -1162,7 +1162,7 @@ makesuffixstr(char *f, char *s, int n)
 	    s++;
 	} else
 	    inv = 0;
-	s = getkeystring(s, &i, 5, &z);
+	s = getkeystring(s, &i, GETKEYS_SUFFIX, &z);
 	s = metafy(s, i, META_USEHEAP);
 	ws = stringaszleline(s, 0, &i, NULL, NULL);
 
diff --git a/Src/builtin.c b/Src/builtin.c
index 3bd3b63cb..979075392 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -3488,7 +3488,8 @@ bin_print(char *name, char **args, Options ops, int func)
     else if (OPT_HASARG(ops,'f'))
 	fmt = OPT_ARG(ops,'f');
     if (fmt)
-	fmt = getkeystring(fmt, &flen, OPT_ISSET(ops,'b') ? 2 : 0, &fmttrunc);
+	fmt = getkeystring(fmt, &flen, OPT_ISSET(ops,'b') ? GETKEYS_BINDKEY :
+			   GETKEYS_PRINTF, &fmttrunc);
 
     first = args;
     
@@ -3525,9 +3526,14 @@ bin_print(char *name, char **args, Options ops, int func)
 	     (OPT_ISSET(ops,'R') || OPT_ISSET(ops,'r') || OPT_ISSET(ops,'E'))))
 	    unmetafy(args[n], &len[n]);
 	else {
-	    args[n] = getkeystring(args[n], &len[n], OPT_ISSET(ops,'b') ? 2 :
-				   (func != BIN_ECHO && !OPT_ISSET(ops,'e')),
-				   &nnl);
+	    int escape_how;
+	    if (OPT_ISSET(ops,'b'))
+		escape_how = GETKEYS_BINDKEY;
+	    else if (func != BIN_ECHO && !OPT_ISSET(ops,'e'))
+		escape_how = GETKEYS_PRINT;
+	    else
+		escape_how = GETKEYS_ECHO;
+	    args[n] = getkeystring(args[n], &len[n], escape_how, &nnl);
 	    if (nnl) {
 		/* If there was a \c escape, make this the last arg. */
 		argc = n + 1;
@@ -3933,7 +3939,8 @@ bin_print(char *name, char **args, Options ops, int func)
 		    int l;
 		    if (*c == 'b') {
 			b = getkeystring(metafy(curarg, curlen, META_USEHEAP), &l,
-					 OPT_ISSET(ops,'b') ? 2 : 0, &nnl);
+					 OPT_ISSET(ops,'b') ? GETKEYS_BINDKEY :
+					 GETKEYS_PRINTF, &nnl);
 		    } else {
 			b = curarg;
 			l = curlen;
diff --git a/Src/math.c b/Src/math.c
index 243096be5..809999f9c 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -464,7 +464,7 @@ zzlex(void)
 			zerr("character missing after ##");
 			return EOI;
 		    }
-		    ptr = getkeystring(ptr, NULL, 6, &v);
+		    ptr = getkeystring(ptr, NULL, GETKEYS_MATH, &v);
 		    yyval.u.l = v;
 		    return NUM;
 		}
diff --git a/Src/params.c b/Src/params.c
index e3040fb7f..2a4a7a745 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1038,8 +1038,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
 		    goto flagerr;
 		sav = *t;
 		*t = '\0';
-		sep = escapes ? getkeystring(s + 1, &waste, 3, NULL) :
-				dupstring(s + 1);
+		sep = escapes ? getkeystring(s + 1, &waste, GETKEYS_SEP, NULL)
+		    : dupstring(s + 1);
 		*t = sav;
 		s = t;
 		break;
diff --git a/Src/subst.c b/Src/subst.c
index 67afd0f03..1e8907d5c 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -150,7 +150,7 @@ stringsubst(LinkList list, LinkNode node, int ssub, int asssub)
 		setdata(node, (void *) str3);
 		continue;
 	    } else if (c == Snull) {
-		str = getkeystring(str, NULL, 4, NULL);
+		str = getkeystring(str, NULL, GETKEYS_DOLLARS_QUOTE, NULL);
 		continue;
 	    } else {
 		node = paramsubst(list, node, &str, qt, ssub);
@@ -272,7 +272,7 @@ quotesubst(char *str)
 
     while (*s) {
 	if (*s == String && s[1] == Snull) {
-	    s = getkeystring(s, NULL, 4, NULL);
+	    s = getkeystring(s, NULL, GETKEYS_DOLLARS_QUOTE, NULL);
 	} else {
 	    s++;
 	}
@@ -942,7 +942,7 @@ substevalchar(char *ptr)
 
 	/* inefficient: should separate out \U handling from getkeystring */
 	sprintf(buf, "\\U%.8x", (unsigned int)ires);
-	return getkeystring(buf, &dummy, 2, NULL);
+	return getkeystring(buf, &dummy, GETKEYS_BINDKEY, NULL);
     } else {
 	ptr = zhalloc(2);
 	sprintf(ptr, "%c", (int)ires);
@@ -1232,7 +1232,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
 #define UNTOK_AND_ESCAPE(X) {\
 		untokenize(X = dupstring(s + 1));\
 		if (escapes) {\
-		    X = getkeystring(X, &klen, 3, NULL);\
+		    X = getkeystring(X, &klen, GETKEYS_SEP, NULL);\
 		    X = metafy(X, klen, META_HREALLOC);\
 		}\
 	    }
diff --git a/Src/utils.c b/Src/utils.c
index 3a5246bd1..a72ddfcc5 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2804,7 +2804,7 @@ zbeep(void)
     queue_signals();
     if ((vb = getsparam("ZBEEP"))) {
 	int len;
-	vb = getkeystring(vb, &len, 2, NULL);
+	vb = getkeystring(vb, &len, GETKEYS_BINDKEY, NULL);
 	write(SHTTY, vb, len);
     } else if (isset(BEEP))
 	write(SHTTY, "\07", 1);
@@ -4540,26 +4540,14 @@ ucs4toutf8(char *dest, unsigned int wval)
 /*
  * Decode a key string, turning it into the literal characters.
  * The length is (usually) returned in *len.
- * fromwhere determines how the processing works:
- *   0:  Don't handle keystring, just print-like escapes.
- *       If a \c escape is seen, *misc is set to 1.
- *   1:  Handle Emacs-like \C-X arguments etc., but not ^X.
- *       If a \c escape is seen, *misc is set to 1.
- *   2:  Handle ^X as well as emacs-like keys; don't handle \c
- *       (the misc arg is not used).
- *   3:  As 1, but don't handle \c (the misc arg is not used).
- *   4:  Do $'...' quoting.  Overwrites the existing string instead of
- *       zhalloc'ing. If \uNNNN ever generates multi-byte chars longer
- *       than 6 bytes, will need to adjust this to re-allocate memory.
- *   5:  As 2, but \- is special. If \- is seen, *misc is set to 1.
- *   6:  As 2, but parses only one character: returns a pointer to the
- *       next character and puts the parsed character into *misc (the
- *       len arg is not used).
+ * how is a set of bits from the GETKEY_ values defined in zsh.h;
+ * not all combinations of bits are useful.  Callers will typically
+ * use one of the GETKEYS_ values which define sets of bits.
  */
 
 /**/
 mod_export char *
-getkeystring(char *s, int *len, int fromwhere, int *misc)
+getkeystring(char *s, int *len, int how, int *misc)
 {
     char *buf, tmp[1];
     char *t, *u = NULL;
@@ -4579,9 +4567,9 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 # endif
 #endif
 
-    if (fromwhere == 6)
+    if (how & GETKEY_SINGLE_CHAR)
 	t = buf = tmp;
-    else if (fromwhere != 4)
+    else if (!(how & GETKEY_DOLLAR_QUOTE))
 	t = buf = zhalloc(strlen(s) + 1);
     else {
 	t = buf = s;
@@ -4616,7 +4604,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		*t++ = '\r';
 		break;
 	    case 'E':
-		if (!fromwhere) {
+		if (!(how & GETKEY_EMACS)) {
 		    *t++ = '\\', s--;
 		    continue;
 		}
@@ -4625,7 +4613,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		*t++ = '\033';
 		break;
 	    case 'M':
-		if (fromwhere) {
+		if (how & GETKEY_EMACS) {
 		    if (s[1] == '-')
 			s++;
 		    meta = 1 + control;	/* preserve the order of ^ and meta */
@@ -4633,7 +4621,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		    *t++ = '\\', s--;
 		continue;
 	    case 'C':
-		if (fromwhere) {
+		if (how & GETKEY_EMACS) {
 		    if (s[1] == '-')
 			s++;
 		    control = 1;
@@ -4644,13 +4632,13 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		*t++ = '\\', s--;
 		break;
 	    case '-':
-		if (fromwhere == 5) {
+		if (how & GETKEY_BACKSLASH_MINUS) {
 		    *misc  = 1;
 		    break;
 		}
 		goto def;
 	    case 'c':
-		if (fromwhere < 2) {
+		if (how & GETKEY_BACKSLASH_C) {
 		    *misc = 1;
 		    *t = '\0';
 		    *len = t - buf;
@@ -4671,7 +4659,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		        break;
 		    }
 		}
-    	    	if (fromwhere == 6) {
+    	    	if (how & GETKEY_SINGLE_CHAR) {
 		    *misc = wval;
 		    return s+1;
 		}
@@ -4679,7 +4667,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		count = wctomb(t, (wchar_t)wval);
 		if (count == -1) {
 		    zerr("character not in range");
-		    if (fromwhere == 4) {
+		    if (how & GETKEY_DOLLAR_QUOTE) {
 			for (u = t; (*u++ = *++s););
 			return t;
 		    }
@@ -4708,7 +4696,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
     	    	    cd = iconv_open(nl_langinfo(CODESET), "UCS-4BE");
 		    if (cd == (iconv_t)-1) {
 			zerr("cannot do charset conversion");
-			if (fromwhere == 4) {
+			if (how & GETKEY_DOLLAR_QUOTE) {
 			    for (u = t; (*u++ = *++s););
 			    return t;
 			}
@@ -4742,7 +4730,7 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 	    default:
 	    def:
 		if ((idigit(*s) && *s < '8') || *s == 'x') {
-		    if (!fromwhere) {
+		    if (!(how & GETKEY_OCTAL_ESC)) {
 			if (*s == '0')
 			    s++;
 			else if (*s != 'x') {
@@ -4763,21 +4751,21 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 		    }
 		    s--;
 		} else {
-		    if (!fromwhere && *s != '\\')
+		    if (!(how & GETKEY_EMACS) && *s != '\\')
 			*t++ = '\\';
 		    *t++ = *s;
 		}
 		break;
 	    }
-	} else if (fromwhere == 4 && *s == Snull) {
+	} else if ((how & GETKEY_DOLLAR_QUOTE) && *s == Snull) {
 	    for (u = t; (*u++ = *s++););
 	    return t + 1;
-	} else if (*s == '^' && !control &&
-		   (fromwhere == 2 || fromwhere == 5 || fromwhere == 6)) {
+	} else if (*s == '^' && !control && (how & GETKEY_CTRL)) {
 	    control = 1;
 	    continue;
 #ifdef MULTIBYTE_SUPPORT
-	} else if (fromwhere == 6 && isset(MULTIBYTE) && STOUC(*s) > 127) {
+	} else if ((how & GETKEY_SINGLE_CHAR) &&
+		   isset(MULTIBYTE) && STOUC(*s) > 127) {
 	    wint_t wc;
 	    int len;
 	    len = mb_metacharlenconv(s, &wc);
@@ -4806,19 +4794,19 @@ getkeystring(char *s, int *len, int fromwhere, int *misc)
 	    t[-1] |= 0x80;
 	    meta = 0;
 	}
-	if (fromwhere == 4 && imeta(t[-1])) {
+	if ((how & GETKEY_DOLLAR_QUOTE) && imeta(t[-1])) {
 	    *t = t[-1] ^ 32;
 	    t[-1] = Meta;
 	    t++;
 	}
-	if (fromwhere == 6 && t != tmp) {
+	if ((how & GETKEY_SINGLE_CHAR) && t != tmp) {
 	    *misc = STOUC(tmp[0]);
 	    return s + 1;
 	}
     }
-    DPUTS(fromwhere == 4, "BUG: unterminated $' substitution");
+    DPUTS(how & GETKEY_DOLLAR_QUOTE, "BUG: unterminated $' substitution");
     *t = '\0';
-    if (fromwhere == 6)
+    if (how & GETKEY_SINGLE_CHAR)
       *misc = 0;
     else
       *len = t - buf;
diff --git a/Src/zsh.h b/Src/zsh.h
index 19d8a368f..3cb006cbf 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1900,6 +1900,62 @@ enum {
     CASMOD_CAPS
 };
 
+/*******************************************/
+/* Flags to third argument of getkeystring */
+/*******************************************/
+
+/*
+ * By default handles some subset of \-escapes.  The following bits
+ * turn on extra features.
+ */
+enum {
+    /*
+     * Handle octal where the first digit is non-zero e.g. \3, \33, \333
+     * \0333 etc. is always handled.
+     */
+    GETKEY_OCTAL_ESC = (1 << 0),
+    /*
+     * Handle Emacs-like key sequences \C-x etc.
+     * Also treat \E like \e and use backslashes to escape the
+     * next character if not special, i.e. do all the things we
+     * don't do with the echo builtin.
+     */
+    GETKEY_EMACS = (1 << 1),
+    /* Handle ^X etc. */
+    GETKEY_CTRL = (1 << 2),
+    /* Handle \c (uses misc arg to getkeystring()) */
+    GETKEY_BACKSLASH_C = (1 << 3),
+    /* Do $'...' quoting (len arg to getkeystring() not used) */
+    GETKEY_DOLLAR_QUOTE = (1 << 4),
+    /* Handle \- (uses misc arg to getkeystring()) */
+    GETKEY_BACKSLASH_MINUS = (1 << 5),
+    /* Parse only one character (len arg to getkeystring() not used) */
+    GETKEY_SINGLE_CHAR = (1 << 6)
+};
+
+/*
+ * Standard combinations used within the shell.
+ * Note GETKEYS_... instead of GETKEY_...: this is important in some cases.
+ */
+/* echo builtin */
+#define GETKEYS_ECHO	(GETKEY_BACKSLASH_C)
+/* printf format string */
+#define GETKEYS_PRINTF	(GETKEY_OCTAL_ESC|GETKEY_BACKSLASH_C)
+/* Full print without -e */
+#define GETKEYS_PRINT	(GETKEY_OCTAL_ESC|GETKEY_BACKSLASH_C|GETKEY_EMACS)
+/* bindkey */
+#define GETKEYS_BINDKEY	(GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL)
+/* $'...' */
+#define GETKEYS_DOLLARS_QUOTE (GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_DOLLAR_QUOTE)
+/* Single character for math processing */
+#define GETKEYS_MATH	\
+	(GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL|GETKEY_SINGLE_CHAR)
+/* Used to process separators etc. with print-style escapes */
+#define GETKEYS_SEP	(GETKEY_OCTAL_ESC|GETKEY_EMACS)
+/* Used for suffix removal */
+#define GETKEYS_SUFFIX		\
+	(GETKEY_OCTAL_ESC|GETKEY_EMACS|GETKEY_CTRL|GETKEY_BACKSLASH_MINUS)
+
 /**********************************/
 /* Flags to third argument of zle */
 /**********************************/