From 80acfd135cb41dc63b2e037fe8c18bcf46ce929c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 10 Sep 2006 18:10:48 +0000 Subject: 22684: improve getkeystring() interface and make printf do octal escapes --- Src/Zle/zle_hist.c | 2 +- Src/Zle/zle_keymap.c | 11 +++++----- Src/Zle/zle_misc.c | 2 +- Src/builtin.c | 17 +++++++++----- Src/math.c | 2 +- Src/params.c | 4 ++-- Src/subst.c | 8 +++---- Src/utils.c | 62 +++++++++++++++++++++------------------------------- Src/zsh.h | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 108 insertions(+), 56 deletions(-) (limited to 'Src') 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 */ /**********************************/ -- cgit 1.4.1