From 0aee5e1bb490617b1d84d5ad8e20571d26fc9986 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 27 Jul 2000 17:48:47 +0000 Subject: 12414: vared quotes separators when editing arrays --- Src/Zle/zle_main.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- Src/exec.c | 2 +- Src/utils.c | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 81 insertions(+), 13 deletions(-) (limited to 'Src') diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index d6f0b6c8e..e25f11f1e 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -823,7 +823,46 @@ bin_vared(char *name, char **args, char *ops, int func) zwarnnam(name, "no such variable: %s", args[0], 0); return 1; } else if (v) { - s = getstrvalue(v); + if (v->isarr) { + /* Array: check for separators and quote them. */ + char **arr = getarrvalue(v), **aptr, **tmparr, **tptr; + tptr = tmparr = (char **)zhalloc(sizeof(char *)*(arrlen(arr)+1)); + for (aptr = arr; *aptr; aptr++) { + int sepcount = 0; + /* See if this word contains a separator character */ + for (t = *aptr; *t; t++) { + if (*t == Meta) { + if (isep(t[1] ^ 32)) + sepcount++; + t++; + } else if (isep(*t)) + sepcount++; + } + if (sepcount) { + /* Yes, so allocate enough space to quote it. */ + char *newstr, *nptr; + newstr = zhalloc(strlen(*aptr)+sepcount+1); + /* Go through string quoting separators */ + for (t = *aptr, nptr = newstr; *t; ) { + if (*t == Meta) { + if (isep(t[1] ^ 32)) + *nptr++ = '\\'; + *nptr++ = *t++; + } else if (isep(*t)) + *nptr++ = '\\'; + *nptr++ = *t++; + } + *nptr = '\0'; + /* Stick this into the array of words to join up */ + *tptr++ = newstr; + } else + *tptr++ = *aptr; /* No, keep original array element */ + } + *tptr = NULL; + s = sepjoin(tmparr, NULL, 0); + } else { + s = ztrdup(getstrvalue(v)); + } pm = v->pm; } else if (*s) { zwarnnam(name, "invalid parameter name: %s", args[0], 0); @@ -842,7 +881,7 @@ bin_vared(char *name, char **args, char *ops, int func) haso = 1; } /* edit the parameter value */ - zpushnode(bufstack, ztrdup(s)); + zpushnode(bufstack, s); varedarg = *args; ifl = isfirstln; @@ -881,7 +920,11 @@ bin_vared(char *name, char **args, char *ops, int func) if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) { char **a; - a = spacesplit(t, 1, 0); + /* + * Use spacesplit with fourth argument 1: identify quoted separators, + * unquote but don't split. + */ + a = spacesplit(t, 1, 0, 1); if (PM_TYPE(pm->flags) == PM_ARRAY) setaparam(args[0], a); else diff --git a/Src/exec.c b/Src/exec.c index 027c11ca2..a3e28d45d 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2744,7 +2744,7 @@ readoutput(int in, int qt) } addlinknode(ret, buf); } else { - char **words = spacesplit(buf, 0, 1); + char **words = spacesplit(buf, 0, 1, 0); while (*words) { if (isset(GLOBSUBST)) diff --git a/Src/utils.c b/Src/utils.c index 33fed62dd..48218326b 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1831,7 +1831,7 @@ skipwsep(char **s) /**/ mod_export char ** -spacesplit(char *s, int allownull, int heap) +spacesplit(char *s, int allownull, int heap, int quote) { char *t, **ret, **ptr; int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1); @@ -1839,6 +1839,14 @@ spacesplit(char *s, int allownull, int heap) ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zcalloc(l)); + if (quote) { + /* + * we will be stripping quoted separators by hacking string, + * so make sure it's hackable. + */ + s = dupstring(s); + } + t = s; skipwsep(&s); if (*s && isep(*s == Meta ? s[1] ^ 32 : *s)) @@ -1853,7 +1861,7 @@ spacesplit(char *s, int allownull, int heap) skipwsep(&s); } t = s; - findsep(&s, NULL); + findsep(&s, NULL, quote); if (s > t || allownull) { *ptr = (heap ? (char *) hcalloc((s - t) + 1) : (char *) zcalloc((s - t) + 1)); @@ -1871,13 +1879,30 @@ spacesplit(char *s, int allownull, int heap) /**/ static int -findsep(char **s, char *sep) +findsep(char **s, char *sep, int quote) { + /* + * *s is the string we are looking along, which will be updated + * to the point we have got to. + * + * sep is a possibly multicharacter separator to look for. If NULL, + * use normal separator characters. + * + * quote is a flag that '\' should not be treated as a separator. + * in this case we need to be able to strip the backslash directly + * in the string, so the calling function must have sent us something + * modifiable. currently this only works for sep == NULL. + */ int i; char *t, *tt; if (!sep) { for (t = *s; *t; t++) { + if (quote && *t == '\\' && + isep(t[1] == Meta ? (t[2] ^ 32) : t[1])) { + chuck(t); + continue; + } if (*t == Meta) { if (isep(t[1] ^ 32)) break; @@ -1928,7 +1953,7 @@ findword(char **s, char *sep) if (sep) { sl = strlen(sep); r = *s; - while (! findsep(s, sep)) { + while (! findsep(s, sep, 0)) { r = *s += sl; } return r; @@ -1942,7 +1967,7 @@ findword(char **s, char *sep) break; } *s = t; - findsep(s, sep); + findsep(s, sep, 0); return t; } @@ -1955,7 +1980,7 @@ wordcount(char *s, char *sep, int mul) if (sep) { r = 1; sl = strlen(sep); - for (; (c = findsep(&s, sep)) >= 0; s += sl) + for (; (c = findsep(&s, sep, 0)) >= 0; s += sl) if ((c && *(s + sl)) || mul) r++; } else { @@ -1975,7 +2000,7 @@ wordcount(char *s, char *sep, int mul) if (mul <= 0) skipwsep(&s); } - findsep(&s, NULL); + findsep(&s, NULL, 0); t = s; if (mul <= 0) skipwsep(&s); @@ -2023,7 +2048,7 @@ sepsplit(char *s, char *sep, int allownull, int heap) char *t, *tt, **r, **p; if (!sep) - return spacesplit(s, allownull, heap); + return spacesplit(s, allownull, heap, 0); sl = strlen(sep); n = wordcount(s, sep, 1); @@ -2032,7 +2057,7 @@ sepsplit(char *s, char *sep, int allownull, int heap) for (t = s; n--;) { tt = t; - findsep(&t, sep); + findsep(&t, sep, 0); *p = (heap ? (char *) hcalloc(t - tt + 1) : (char *) zcalloc(t - tt + 1)); strncpy(*p, tt, t - tt); -- cgit 1.4.1