diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | Src/Zle/compcore.c | 55 | ||||
-rw-r--r-- | Src/lex.c | 22 | ||||
-rw-r--r-- | Src/utils.c | 24 | ||||
-rw-r--r-- | Src/zsh.h | 4 |
5 files changed, 77 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog index d8c091eab..3e5c5d4d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2007-01-08 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * 23097: Src/lex.c, Src/utils.c, Src/zsh.h, Src/Zle/compcore.c: + splitting of $'...' strings in completion. + 2007-01-05 Peter Stephenson <p.w.stephenson@ntlworld.com> * 23091: Doc/Zsh/compctl.yo, Doc/Zsh/contrib.yo: fixes diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index a21b83569..2259db01a 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1432,10 +1432,8 @@ set_comp_sep(void) * set, which isn't necessarily correct if the quotes were typed by * the user). * osq: c.f. odq, taking account of Snull's and embeded "'"'s. - * issq: flag that current quoting is single quotes; I assume that - * civilization would end if we used a consistent way of - * flagging the different types of quotes, or something. - * lsq: when quoting is single quotes (issq), counts the offset + * qttype: type of quotes using standard QT_* definitions. + * lsq: when quoting is single quotes (QT_SINGLE), counts the offset * adjustment needed in the word being examined in the lexer loop. * sqq: the value of lsq for the current completion word. * qa: not, unfortunately, a question and answer session with the @@ -1443,7 +1441,7 @@ set_comp_sep(void) * when stripping single quotes: 1 for RCQUOTES, 3 otherwise * (because we leave a "'" in the final string). */ - int dq = 0, odq, sq = 0, osq, issq = 0, sqq = 0, lsq = 0, qa = 0; + int dq = 0, odq, sq = 0, osq, qttype, sqq = 0, lsq = 0, qa = 0; /* dolq: like sq and dq but for dollars quoting. */ int dolq = 0; /* remember some global variable values (except lp is local) */ @@ -1479,26 +1477,25 @@ set_comp_sep(void) addedx = 1; noerrs = 1; lexsave(); - tmp = (char *) zhalloc(tl = 3 + strlen(s)); + /* + * tl is the length of the temporary string including + * the space at the start and the x at the cursor position, + * but not the NULL byte. + */ + tl = strlen(s) + 2; + tmp = (char *) zhalloc(tl + 1); tmp[0] = ' '; memcpy(tmp + 1, s, noffs); tmp[(scs = zlemetacs = 1 + noffs)] = 'x'; strcpy(tmp + 2 + noffs, s + noffs); - switch (*compqstack) { - case QT_NONE: -#ifdef DEBUG - dputs("BUG: head of compqstack is NULL"); -#endif - break; - + switch ((qttype = *compqstack)) { case QT_BACKSLASH: remq = 1; tmp = rembslash(tmp); break; case QT_SINGLE: - issq = 1; if (isset(RCQUOTES)) qa = 1; else @@ -1531,22 +1528,32 @@ set_comp_sep(void) break; case QT_DOLLARS: - sl = strlen(tmp); j = zlemetacs; - tmp = getkeystring(tmp, &tl, + tmp = getkeystring(tmp, &sl, GETKEY_DOLLAR_QUOTE|GETKEY_UPDATE_OFFSET, &zlemetacs); - /* The number of characters we removed because of $' quoting */ - dolq = sl - tl; + /* The number of bytes we removed because of $' quoting */ + dolq = tl - sl; /* Offset into the word is modified, too... */ css += zlemetacs - j; break; + + case QT_NONE: + default: /* to silence compiler warnings */ +#ifdef DEBUG + dputs("BUG: head of compqstack is NULL"); +#endif + break; + } odq = dq; osq = sq; inpush(dupstrspace(tmp), 0, NULL); zlemetaline = tmp; - zlemetall = tl - 1; + /* + * Length of temporary string, calculated above. + */ + zlemetall = tl; strinbeg(0); noaliases = 1; do { @@ -1582,7 +1589,7 @@ set_comp_sep(void) dq--; } } - if (issq) { + if (qttype == QT_SINGLE) { for (p = tokstr, lsq = 0; *p; p++) { if (sq && *p == Snull) sq -= qa; @@ -1606,6 +1613,8 @@ set_comp_sep(void) swe = we - 1 - dq - sq - dolq; sqq = lsq; soffs = zlemetacs - swb - css; + DPUTS2(p[soffs] != 'x', "expecting 'x' at offset %d of \"%s\"", + soffs, p); chuck(p + soffs); ns = dupstring(p); } @@ -1736,7 +1745,7 @@ set_comp_sep(void) */ sav = s[(i = swb - 1 - sqq + dq)]; s[i] = '\0'; - qp = (issq ? dupstring(s) : rembslash(s)); + qp = (qttype == QT_SINGLE) ? dupstring(s) : rembslash(s); s[i] = sav; if (swe < swb) swe = swb; @@ -1747,11 +1756,11 @@ set_comp_sep(void) if ((int)strlen(ns) > swe - swb + 1) ns[swe - swb + 1] = '\0'; } - qs = (issq ? dupstring(s + swe) : rembslash(s + swe)); + qs = (qttype == QT_SINGLE) ? dupstring(s + swe) : rembslash(s + swe); sl = strlen(ns); if (soffs > sl) soffs = sl; - if (issq) { + if (qttype == QT_SINGLE) { remsquote(qp); remsquote(qs); } diff --git a/Src/lex.c b/Src/lex.c index a568e25c4..7a0bf2b1c 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -96,18 +96,18 @@ mod_export int addedx; mod_export int wb, we; /* 1 if aliases should not be expanded */ - + /**/ mod_export int noaliases; /* we are parsing a line sent to use by the editor */ - + /**/ mod_export int zleparse; - + /**/ mod_export int wordbeg; - + /**/ mod_export int parbegin; @@ -115,7 +115,7 @@ mod_export int parbegin; mod_export int parend; /* don't recognize comments */ - + /**/ mod_export int nocomments; @@ -1181,10 +1181,20 @@ gettokstr(int c, int sub) STOPHIST while ((c = hgetc()) != '\'' && !lexstop) { if (strquote && c == '\\') { - add(c); c = hgetc(); if (lexstop) break; + /* + * Mostly we don't need to do anything special + * with escape backslashes or closing quotes + * inside $'...'; however in completion we + * need to be able to strip multiple backslashes + * neatly. + */ + if (c == '\\' || c == '\'') + add(Bnull); + else + add('\\'); } else if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') { if (bptr[-1] == '\\') bptr--, len--; diff --git a/Src/utils.c b/Src/utils.c index d4bf6c2eb..6faf196a9 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -3925,7 +3925,6 @@ mb_niceformat(const char *s, FILE *stream, char **outstrp, int heap) ptr = unmetafy(ums, ¨en); memset(&mbs, 0, sizeof mbs); - mb_metacharinit(); while (umlen > 0) { size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs); @@ -4577,10 +4576,27 @@ ucs4toutf8(char *dest, unsigned int wval) /* * Decode a key string, turning it into the literal characters. * The value returned is a newly allocated string from the heap. - * The length is (usually) returned in *len. + * + * The length is returned in *len. This is usually the length of + * the final unmetafied string. The exception is the case of + * a complete GETKEY_DOLLAR_QUOTE conversion where *len is the + * length of the input string which has been used (up to and including + * the terminating single quote); as the final string is metafied and + * NULL-terminated its length is not required. If both GETKEY_DOLLAR_QUOTE + * and GETKEY_UPDATE_OFFSET are present in "how", the string is not + * expected to be terminated (this is used in completion to parse + * a partial $'...'-quoted string) and the length passed back is + * that of the converted string. Note in both cases that this is a length + * in bytes (i.e. the same as given by a raw pointer difference), not + * characters, which may occupy multiple bytes. + * * 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. + * Note, for example that: + * - GETKEY_SINGLE_CHAR must not be combined with GETKEY_DOLLAR_QUOTE. + * - GETKEY_UPDATE_OFFSET is only allowed if GETKEY_DOLLAR_QUOTE is + * also present. * * The return value is unmetafied unless GETKEY_DOLLAR_QUOTE is * in use. @@ -4946,9 +4962,9 @@ getkeystring(char *s, int *len, int how, int *misc) if (how & GETKEY_DOLLAR_QUOTE) *tdest = '\0'; if (how & GETKEY_SINGLE_CHAR) - *misc = 0; + *misc = 0; else - *len = t - buf; + *len = ((how & GETKEY_DOLLAR_QUOTE) ? tdest : t) - buf; return buf; } diff --git a/Src/zsh.h b/Src/zsh.h index 752587c57..2f627a37f 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1914,8 +1914,12 @@ struct heap { #define STRINGIFY(x) STRINGIFY_LITERAL(x) #define ERRMSG(x) (__FILE__ ":" STRINGIFY(__LINE__) ": " x) # define DPUTS(X,Y) if (!(X)) {;} else dputs(ERRMSG(Y)) +# define DPUTS1(X,Y,Z1) if (!(X)) {;} else dputs(ERRMSG(Y), Z1) +# define DPUTS2(X,Y,Z1,Z2) if (!(X)) {;} else dputs(ERRMSG(Y), Z1, Z2) #else # define DPUTS(X,Y) +# define DPUTS1(X,Y,Z1) +# define DPUTS2(X,Y,Z1,Z2) #endif /**************************/ |